diff --git a/packages/docusaurus/src/server/htmlTags.ts b/packages/docusaurus/src/server/htmlTags.ts index e61f946804..d6587a91ac 100644 --- a/packages/docusaurus/src/server/htmlTags.ts +++ b/packages/docusaurus/src/server/htmlTags.ts @@ -36,16 +36,24 @@ function assertIsHtmlTagObject(val: unknown): asserts val is HtmlTagObject { } } +function absoluteToRelativeTagAttribute(name: string, value: string): string { + if ((name === 'src' || name === 'href') && value.startsWith('/')) { + return `.${value}`; // TODO would only work for homepage + } + return value; +} + function htmlTagObjectToString(tag: unknown): string { assertIsHtmlTagObject(tag); const isVoidTag = (voidHtmlTags as string[]).includes(tag.tagName); const tagAttributes = tag.attributes ?? {}; const attributes = Object.keys(tagAttributes) .map((attr) => { - const value = tagAttributes[attr]!; + let value = tagAttributes[attr]!; if (typeof value === 'boolean') { return value ? attr : undefined; } + value = absoluteToRelativeTagAttribute(attr, value); return `${attr}="${escapeHTML(value)}"`; }) .filter((str): str is string => Boolean(str)); diff --git a/packages/docusaurus/src/ssg.ts b/packages/docusaurus/src/ssg.ts index a1e6d4e9ce..76dfbdade4 100644 --- a/packages/docusaurus/src/ssg.ts +++ b/packages/docusaurus/src/ssg.ts @@ -182,6 +182,7 @@ async function generateStaticFile({ }); // This renders the full page HTML, including head tags... const fullPageHtml = renderSSRTemplate({ + pathname, params, result, }); diff --git a/packages/docusaurus/src/templates/templates.ts b/packages/docusaurus/src/templates/templates.ts index 24c5fb1005..2765baa47e 100644 --- a/packages/docusaurus/src/templates/templates.ts +++ b/packages/docusaurus/src/templates/templates.ts @@ -63,9 +63,11 @@ function getScriptsAndStylesheets({ } export function renderSSRTemplate({ + pathname, params, result, }: { + pathname: string; params: SSGParams; result: AppRenderResult; }): string { @@ -96,9 +98,18 @@ export function renderSSRTemplate({ ]; const metaAttributes = metaStrings.filter(Boolean); + const numberOfSlashes = pathname.match(/\//g)?.length ?? 0; + + const local = true; + + const localBaseUrl = + numberOfSlashes === 1 ? `./` : '../'.repeat(numberOfSlashes - 1); + + // console.log({pathname, numberOfSlashes, baseUrl, finalBaseUrl, headTags}); + const data: SSRTemplateData = { appHtml, - baseUrl, + baseUrl: local ? localBaseUrl : baseUrl, htmlAttributes, bodyAttributes, headTags, diff --git a/packages/docusaurus/src/webpack/base.ts b/packages/docusaurus/src/webpack/base.ts index f7fcb238de..98c98f4570 100644 --- a/packages/docusaurus/src/webpack/base.ts +++ b/packages/docusaurus/src/webpack/base.ts @@ -112,7 +112,7 @@ export async function createBaseConfig({ chunkFilename: isProd ? 'assets/js/[name].[contenthash:8].js' : '[name].js', - publicPath: baseUrl, + publicPath: isServer ? baseUrl : 'auto', hashFunction: 'xxhash64', }, // Don't throw warning when asset created is over 250kb