From 1d4d832b6c22b4bb9d641507536fd49150b9bdfa Mon Sep 17 00:00:00 2001 From: msa46 Date: Sat, 15 Aug 2026 21:09:25 +0200 Subject: [PATCH] fix: verify programme routes across deployment bases --- astro.config.mjs | 7 ++++++- ...rogramme-sidebar-and-course-integration.md | 6 +++--- package-lock.json | 1 + package.json | 5 ++++- scripts/lib/internal-links.mjs | 1 + scripts/lib/rendered-output.mjs | 1 + src/components/ProgrammeSwitch.astro | 2 +- src/config/base-aware-markdown.mjs | 19 +++++++++++++++++++ tests/base-aware-markdown.test.mjs | 15 +++++++++++++++ tests/internal-links.test.mjs | 8 ++++++++ tests/rendered-output.test.mjs | 8 ++++++++ 11 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 src/config/base-aware-markdown.mjs create mode 100644 tests/base-aware-markdown.test.mjs diff --git a/astro.config.mjs b/astro.config.mjs index b0f76ec..b1764f2 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,7 +1,9 @@ import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; +import { unified } from '@astrojs/markdown-remark'; import { sidebar } from './src/config/sidebar.mjs'; import { legacyBachelorRedirects } from './src/config/legacy-bachelor-redirects.mjs'; +import { baseAwareLinks } from './src/config/base-aware-markdown.mjs'; const site = process.env.SITE || 'http://localhost:4321'; const base = process.env.BASE || '/'; @@ -13,7 +15,10 @@ const matomoConsentScript = `${normalizedBase}/matomo-consent.js`; export default defineConfig({ site, base, - redirects: legacyBachelorRedirects, + redirects: Object.fromEntries(Object.entries(legacyBachelorRedirects).map(([from, to]) => [from, `${normalizedBase}${to}`])), + markdown: { + processor: unified({ remarkPlugins: [[baseAwareLinks, { base }]] }), + }, integrations: [ starlight({ title: 'Incognito Wiki', diff --git a/docs/superpowers/plans/2026-08-15-programme-sidebar-and-course-integration.md b/docs/superpowers/plans/2026-08-15-programme-sidebar-and-course-integration.md index 38289e1..bc3e678 100644 --- a/docs/superpowers/plans/2026-08-15-programme-sidebar-and-course-integration.md +++ b/docs/superpowers/plans/2026-08-15-programme-sidebar-and-course-integration.md @@ -16,9 +16,9 @@ - Preserve every old `/bachelor/...` URL with an explicit permanent redirect to the exact new route. - Import only these substantive Computer Science pages from `d5d6730`: - `computer-science/year-1/period-1/introduction-to-computer-science.md` - - `computer-science/year-1/period-2/computer-architecture.md` - - `computer-science/year-1/period-4/algorithmic-design.md` - - `computer-science/year-1/period-4/databases.md` + - `computer-science/year-1/period-4/computer-architecture.md` + - `computer-science/year-1/period-5/algorithmic-design.md` + - `computer-science/year-1/period-5/databases.md` - `computer-science/year-1/period-5/statistics.md` - Do not import the malformed `computer-science/course-description.md`, any `Empty Page` placeholder, or the branch deletion of `previous-exams-and-documents.md`. - Store the body of each byte-identical shared course once, outside `src/content/docs`, and expose it through two programme wrappers: diff --git a/package-lock.json b/package-lock.json index 6bfceb7..5994df2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "incognito-wiki", "version": "0.1.0", "dependencies": { + "@astrojs/markdown-remark": "7.2.2", "@astrojs/starlight": "0.41.6", "astro": "7.1.6", "sharp": "0.35.3" diff --git a/package.json b/package.json index 16a5757..c930d0f 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,9 @@ "version": "0.1.0", "private": true, "type": "module", - "engines": { "node": ">=22.12.0" }, + "engines": { + "node": ">=22.12.0" + }, "scripts": { "dev": "astro dev", "build": "astro build", @@ -18,6 +20,7 @@ "verify": "npm run check && npm run audit:content && npm run build && npm run check:rendered && npm run check:links" }, "dependencies": { + "@astrojs/markdown-remark": "7.2.2", "@astrojs/starlight": "0.41.6", "astro": "7.1.6", "sharp": "0.35.3" diff --git a/scripts/lib/internal-links.mjs b/scripts/lib/internal-links.mjs index bf11a06..28dabac 100644 --- a/scripts/lib/internal-links.mjs +++ b/scripts/lib/internal-links.mjs @@ -90,6 +90,7 @@ export async function checkInternalLinks({ distRoot, base }) { const pageUrl = new URL(`${normalizedBase.replace(/\/$/, '')}${route}`, 'https://built.invalid'); const html = await readFile(sourcePath, 'utf8'); const { document } = parseHTML(html); + if (document.querySelector('meta[http-equiv="refresh"]')) continue; for (const element of document.querySelectorAll('[href]')) { const href = element.getAttribute('href')?.trim() ?? ''; diff --git a/scripts/lib/rendered-output.mjs b/scripts/lib/rendered-output.mjs index d75e908..ef181c4 100644 --- a/scripts/lib/rendered-output.mjs +++ b/scripts/lib/rendered-output.mjs @@ -26,6 +26,7 @@ export async function checkRenderedOutput({ distRoot }) { for (const file of htmlFiles) { const path = relative(absoluteDistRoot, file).split(sep).join('/'); const { document } = parseHTML(await readFile(file, 'utf8')); + if (document.querySelector('meta[http-equiv="refresh"]')) continue; const h1Count = document.querySelectorAll('h1').length; if (h1Count !== 1) headingIssues.push({ file: path, h1Count }); } diff --git a/src/components/ProgrammeSwitch.astro b/src/components/ProgrammeSwitch.astro index 6020ecc..9c081c6 100644 --- a/src/components/ProgrammeSwitch.astro +++ b/src/components/ProgrammeSwitch.astro @@ -3,7 +3,7 @@ import { programmeForPathname, programmeSwitchTargets } from '../config/programm const active = programmeForPathname(Astro.url.pathname.replace(import.meta.env.BASE_URL.replace(/\/$/, ''), '')); const targets = programmeSwitchTargets(Astro.url.pathname); -const withBase = (path: string) => `${import.meta.env.BASE_URL}${path.replace(/^\//, '')}`; +const withBase = (path: string) => `${import.meta.env.BASE_URL.replace(/\/$/, '')}/${path.replace(/^\//, '')}`; ---