Skip to content

Commit 507dba6

Browse files
raifdmuellerclaude
andcommitted
fix(docs): re-root relative image paths in rendered docs
Rendered AsciiDoc emits relative image paths (e.g. image::docs/workflow-diagram.svg → <img src="docs/workflow-diagram.svg">). Doc pages are served under clean URLs like /spec-driven-development/, so the browser resolves that against the route → /spec-driven-development/docs/... → 404; the workflow diagram silently went missing on the Spec-Driven Development pages (EN + DE). Prefix relative <img> sources with the site base after loading, matching the asset's real location (/Semantic-Anchors/docs/...). Absolute, protocol, data and hash URLs are left untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 457c183 commit 507dba6

2 files changed

Lines changed: 30 additions & 0 deletions

File tree

website/src/components/doc-page.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@ export async function loadDocContent(docPath) {
7878
link.setAttribute('rel', 'noopener noreferrer')
7979
})
8080

81+
// Re-root relative image paths. Rendered AsciiDoc emits paths like
82+
// "docs/workflow-diagram.svg" relative to the document, but doc pages are
83+
// served under clean URLs (e.g. /spec-driven-development/), so the browser
84+
// resolves the relative path against the route and 404s. Prefix the site
85+
// base so it points at the asset's real location. Absolute, protocol and
86+
// data URLs are left untouched.
87+
contentEl.querySelectorAll('img[src]').forEach((img) => {
88+
const src = img.getAttribute('src')
89+
if (!src || /^(https?:|data:|\/|#)/.test(src)) return
90+
img.setAttribute('src', `${import.meta.env.BASE_URL}${src}`)
91+
})
92+
8193
// Attach click-to-load handlers for any YouTube placeholders in the doc.
8294
// Keeps us DSGVO-compliant: YouTube is only contacted after user consent.
8395
hydrateYouTubeFacades(contentEl)

website/src/components/doc-page.test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,22 @@ describe('doc-page', () => {
4242
'Failed to Load Documentation'
4343
)
4444
})
45+
46+
it('re-roots relative image paths to the site base, leaving absolute ones', async () => {
47+
global.fetch.mockResolvedValue({
48+
ok: true,
49+
text: async () =>
50+
'<h1>Spec</h1><img src="docs/workflow-diagram.svg" alt="d"><img src="https://x.test/a.png" alt="ext">',
51+
})
52+
53+
await loadDocContent('docs/spec-driven-workflow.adoc')
54+
55+
const base = import.meta.env.BASE_URL
56+
const rel = document.querySelector('#doc-content img[alt="d"]')
57+
const ext = document.querySelector('#doc-content img[alt="ext"]')
58+
// relative AsciiDoc image path must be re-rooted (clean-URL routes break it otherwise)
59+
expect(rel.getAttribute('src')).toBe(`${base}docs/workflow-diagram.svg`)
60+
// absolute/external sources are left untouched
61+
expect(ext.getAttribute('src')).toBe('https://x.test/a.png')
62+
})
4563
})

0 commit comments

Comments
 (0)