diff --git a/quartz/plugins/emitters/static.ts b/quartz/plugins/emitters/static.ts index 0b45290..8b34049 100644 --- a/quartz/plugins/emitters/static.ts +++ b/quartz/plugins/emitters/static.ts @@ -7,6 +7,7 @@ import { dirname } from "path" export const Static: QuartzEmitterPlugin = () => ({ name: "Static", async *emit({ argv, cfg }) { + // Copy Quartz's own internal static assets (quartz/static/) → output/static/ const staticPath = joinSegments(QUARTZ, "static") const fps = await glob("**", staticPath, cfg.configuration.ignorePatterns) const outputStaticPath = joinSegments(argv.output, "static") @@ -18,6 +19,21 @@ export const Static: QuartzEmitterPlugin = () => ({ await fs.promises.copyFile(src, dest) yield dest } + + // Copy user-facing static assets (static/) → output/ preserving paths. + // This mirrors Hugo's convention: static/ox-hugo/foo.png is served at /ox-hugo/foo.png, + // which matches the src="/ox-hugo/..." paths that ox-hugo writes into exported markdown. + const userStaticPath = "static" + if (fs.existsSync(userStaticPath)) { + const userFps = await glob("**", userStaticPath, cfg.configuration.ignorePatterns, false) + for (const fp of userFps) { + const src = joinSegments(userStaticPath, fp) as FilePath + const dest = joinSegments(argv.output, fp) as FilePath + await fs.promises.mkdir(dirname(dest), { recursive: true }) + await fs.promises.copyFile(src, dest) + yield dest + } + } }, async *partialEmit() {}, })