diff --git a/website/astro.config.mjs b/website/astro.config.mjs index 84a89b33..3a18ce54 100644 --- a/website/astro.config.mjs +++ b/website/astro.config.mjs @@ -15,25 +15,34 @@ const site = `https://strudel.cc/`; // root url without a path const base = '/'; // base path of the strudel site const baseNoTrailing = base.endsWith('/') ? base.slice(0, -1) : base; -// this rehype plugin converts relative anchor links to absolute ones -// it wokrs by prepending the absolute page path to anchor links -// example: #gain -> /learn/effects/#gain +// this rehype plugin fixes relative links +// it works by prepending the base + page path to anchor links +// and by prepending the base path to all other relative links // this is necessary when using a base href like -// in this setup, relative anchor links will always link to base, instead of the current page -function absoluteAnchors() { +// examples with base as "mybase": +// #gain -> /mybase/learn/effects/#gain +// /some/page -> /mybase/some/page +function relativeURLFix() { return (tree, file) => { const chunks = file.history[0].split('/src/pages/'); // file.history[0] is the file path const path = chunks[chunks.length - 1].slice(0, -4); // only path inside src/pages, without .mdx return rehypeUrls((url) => { - if (url.href.startsWith('/')) { - const hrefWithTrailingSlash = url.href.endsWith('/') ? url.href : url.href + '/'; - return baseNoTrailing + hrefWithTrailingSlash; + // NOTE: the base argument to the URL constructor is ignored if the input is already + // absolute and used if not, which facilitates the comparison below + // true if url is relative + if (new URL(site).origin === new URL(url.href, site).origin) { + let newHref = baseNoTrailing; + if (url.href.startsWith('#')) { + // special case: a relative anchor link to the current page + newHref += `/${path}/${url.href}`; + } else { + // any other relative link + // NOTE: this does strip off serialized queries and fragments + newHref += (url.pathname.endsWith('/') ? url.pathname : url.pathname + '/'); + } + // console.log(url.href + ' -> ', newHref); + return newHref; } - if (url.href.startsWith('#')) { - const absoluteUrl = `${baseNoTrailing}/${path}/${url.href}`; - return absoluteUrl; - } - // console.log(url.href + ' -> ', absoluteUrl); return; })(tree); }; @@ -44,7 +53,7 @@ const options = { remarkToc, // E.g. `remark-frontmatter` ], - rehypePlugins: [rehypeSlug, [rehypeAutolinkHeadings, { behavior: 'append' }], absoluteAnchors], + rehypePlugins: [rehypeSlug, [rehypeAutolinkHeadings, { behavior: 'append' }], relativeURLFix], }; // https://astro.build/config diff --git a/website/src/components/HeadCommon.astro b/website/src/components/HeadCommon.astro index 724c4b07..ab18500f 100644 --- a/website/src/components/HeadCommon.astro +++ b/website/src/components/HeadCommon.astro @@ -3,8 +3,7 @@ import { pwaInfo } from 'virtual:pwa-info'; import '../styles/index.css'; const { BASE_URL } = import.meta.env; -const base = BASE_URL; -const baseNoTrailing = base.endsWith('/') ? base.slice(0, -1) : base; +const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL; --- @@ -22,7 +21,7 @@ const baseNoTrailing = base.endsWith('/') ? base.slice(0, -1) : base; - + diff --git a/website/src/components/Header/Header.astro b/website/src/components/Header/Header.astro index b429fdb1..6447d9d6 100644 --- a/website/src/components/Header/Header.astro +++ b/website/src/components/Header/Header.astro @@ -18,8 +18,7 @@ const langCode = 'en'; // getLanguageFromURL(currentPage); const sidebar = SIDEBAR[langCode]; const { BASE_URL } = import.meta.env; -const base = BASE_URL; -const baseNoTrailing = base.endsWith('/') ? base.slice(0, -1) : base; +const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL; ---