Fix static assets not found by resolving path relative to content directory

The static/ directory lookup was hardcoded as a relative path from the
Quartz working directory (QUARTZ_PATH). However, ox-hugo places static
files in output_dir/static, while Quartz runs with --directory pointing
to output_dir/content.

This fix resolves static/ relative to argv.directory's parent (the
output_dir), matching where ox-hugo actually places the files. Images
referenced as /ox-hugo/... in exported markdown now display correctly.
This commit is contained in:
Ignacio Ballesteros
2026-02-22 22:25:30 +01:00
parent 1fac31dc73
commit 798401539f

View File

@@ -6,19 +6,26 @@ index 0b45290..8b34049 100644
export const Static: QuartzEmitterPlugin = () => ({ export const Static: QuartzEmitterPlugin = () => ({
name: "Static", name: "Static",
async *emit({ argv, cfg }) { async *emit({ argv, cfg }) {
+ // Copy Quartz's own internal static assets (quartz/static/) output/static/ + // Copy Quartz's own internal static assets (quartz/static/) -> output/static/
const staticPath = joinSegments(QUARTZ, "static") const staticPath = joinSegments(QUARTZ, "static")
const fps = await glob("**", staticPath, cfg.configuration.ignorePatterns) const fps = await glob("**", staticPath, cfg.configuration.ignorePatterns)
const outputStaticPath = joinSegments(argv.output, "static") const outputStaticPath = joinSegments(argv.output, "static")
@@ -18,6 +19,21 @@ export const Static: QuartzEmitterPlugin = () => ({ @@ -18,6 +19,28 @@ export const Static: QuartzEmitterPlugin = () => ({
await fs.promises.copyFile(src, dest) await fs.promises.copyFile(src, dest)
yield dest yield dest
} }
+ +
+ // Copy user-facing static assets (static/) output/ preserving paths. + // 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, + // 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. + // which matches the src="/ox-hugo/..." paths that ox-hugo writes into exported markdown.
+ const userStaticPath = "static" + //
+ // We resolve static/ relative to argv.directory (the content directory) rather than
+ // the current working directory. This is because org-garden runs Quartz with:
+ // - working directory: QUARTZ_PATH (the Quartz installation)
+ // - --directory: output_dir/content (where markdown files are)
+ // But ox-hugo places static files in output_dir/static (sibling to content/).
+ // Using dirname(argv.directory) gives us output_dir, where static/ actually lives.
+ const userStaticPath = joinSegments(dirname(argv.directory), "static")
+ if (fs.existsSync(userStaticPath)) { + if (fs.existsSync(userStaticPath)) {
+ const userFps = await glob("**", userStaticPath, cfg.configuration.ignorePatterns, false) + const userFps = await glob("**", userStaticPath, cfg.configuration.ignorePatterns, false)
+ for (const fp of userFps) { + for (const fp of userFps) {