diff --git a/src/marketing/blogPlugin.test.ts b/src/marketing/blogPlugin.test.ts new file mode 100644 index 00000000..daafac97 --- /dev/null +++ b/src/marketing/blogPlugin.test.ts @@ -0,0 +1,22 @@ +import { describe, expect, it } from 'vitest' +import { makeBlogAssetUrlsMountSafe } from './blogPlugin' + +describe('makeBlogAssetUrlsMountSafe', () => { + it('keeps blog media under the current mount path', () => { + const html = [ + '', + '', + 'Watch the video', + 'Read the docs', + ].join('') + + expect(makeBlogAssetUrlsMountSafe(html)).toBe( + [ + '', + '', + 'Watch the video', + 'Read the docs', + ].join(''), + ) + }) +}) diff --git a/src/marketing/blogPlugin.ts b/src/marketing/blogPlugin.ts index b6598e39..fae55990 100644 --- a/src/marketing/blogPlugin.ts +++ b/src/marketing/blogPlugin.ts @@ -44,6 +44,12 @@ function inlineSvgImages(html: string): string { }) } +// Blog pages are mounted at /developers/blog in production and /blog in +// previews. Relative media URLs preserve the active mount path in both places. +export function makeBlogAssetUrlsMountSafe(html: string): string { + return html.replace(/(\b(?:src|href)=["'])\/blog\//g, '$1./') +} + const CATEGORY_SLUGS = ['network-upgrades', 'events', 'technical', 'case-studies'] // ALL-CAPS markdown files (AGENTS.md, DIAGRAMS.md, …) are documentation for @@ -148,7 +154,7 @@ async function renderPost(filename: string): Promise { ) } - const html = inlineSvgImages(String(await processor.process(content))) + const html = makeBlogAssetUrlsMountSafe(inlineSvgImages(String(await processor.process(content)))) return { slug,