diff --git a/plans/260503-1121-lesson-4-5-gcd-factor/phase-01-katex-integration.md b/plans/260503-1121-lesson-4-5-gcd-factor/phase-01-katex-integration.md new file mode 100644 index 0000000..1839a01 --- /dev/null +++ b/plans/260503-1121-lesson-4-5-gcd-factor/phase-01-katex-integration.md @@ -0,0 +1,76 @@ +--- +phase: 1 +title: "KaTeX integration" +status: pending +priority: P1 +effort: "2h" +dependencies: [] +--- + +# Phase 01: KaTeX integration + +## Overview +Add KaTeX to the project, wrap it in a single `` Svelte component, and verify rendering in a sandbox route. This is the only place KaTeX is touched directly — every lesson uses ``. + +## Requirements +- Functional: render inline + display math from a string prop; SSR-safe (KaTeX renders to static HTML, no client JS needed for display) +- Non-functional: no FOUC; CSS loaded once at app level; no per-component CSS imports +- A11y: KaTeX outputs MathML alongside HTML — keep it; `aria-label` fallback prop for screen readers when math expression is non-trivial + +## Architecture +- KaTeX has two APIs: `katex.render(string, element, options)` (mutates DOM) and `katex.renderToString(string, options)` (returns HTML string). +- Use `renderToString` — pure function, SSR-friendly, plugs into `{@html}`. No `$effect` needed. +- CSS imported once in `+layout.svelte` so it's in the global bundle. +- KaTeX fonts are auto-fetched via CSS `@font-face` from the package's `dist/fonts/` — Vite's static asset handling picks them up. + +## Related Code Files +- Create: `src/lib/components/tex.svelte` — `` component +- Create: `src/routes/__sandbox/katex/+page.svelte` — smoke test route (delete in Phase 05 or leave guarded by `dev` mode) +- Modify: `src/routes/+layout.svelte` — add `import 'katex/dist/katex.min.css'` +- Modify: `package.json` — add `katex` dep + `@types/katex` is unnecessary (we use JSDoc) + +## Implementation Steps +1. `npm install katex@^0.16.x` — pin minor; KaTeX is mature, breaking changes rare. +2. Create `src/lib/components/tex.svelte`: + ```svelte + + {#if ariaLabel} + {@html html} + {:else} + {@html html} + {/if} + ``` +3. Add `import 'katex/dist/katex.min.css';` at top of `