feat: course website (Astro Starlight)

Pages (index, disclaimer, about), lockfile, root test:site script, fix for
Starlight 0.42 sidebar config and <details> rendering in generated MDX.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-10-29 18:35:29 +01:00
1 parent d41496655e
commit 699d038d1c
8 files changed
+5230 -3

No files matched your search

+4
View File
@@ -131,6 +131,10 @@ export function mdxSafeProse(prose) {
let s = p.s.replace(/<!--[\s\S]*?-->/g, "");
s = s.replace(/[{}]/g, (c) => `\\${c}`);
s = s.replace(/<(?!\/?(?:details|summary)\s*>)/g, "&lt;");
// Put each details/summary tag on its own line with blank lines around it, so the
// markdown inside <details> is parsed as markdown rather than as JSX text.
s = s.replace(/[ \t]*(<details>|<\/details>|<summary>[^\n]*?<\/summary>)[ \t]*/g, "\n\n$1\n\n");
s = s.replace(/\n{3,}/g, "\n\n");
return s;
})
.join("");
+1 -1
View File
@@ -79,7 +79,7 @@ test("sync_pairs_code_tabs", () => {
test("sync_strips_comments_and_escapes_mdx", () => {
const out = mdxSafeProse("a <!-- Task 17: re-verify --> b {x} and `{kept}` <details><summary>S</summary> 1 < 2");
assert.doesNotMatch(out, /<!--/);
assert.match(out, /a b \\\{x\\\} and `\{kept\}` <details><summary>S<\/summary> 1 &lt; 2/);
assert.match(out, /a b \\\{x\\\} and `\{kept\}`\n\n<details>\n\n<summary>S<\/summary>\n\n1 &lt; 2/);
const root = fixture({ "01-a": `# A\n\n<!-- hidden -->\n\n${FENCE}rust\nif a < b { <!-- keep --> }\n${FENCE}\n` });
const page = run(root)("01-a.mdx");
assert.doesNotMatch(page, /hidden/);