Catch-all route at app/(app)/manual/[[...slug]]/page.tsx with generateStaticParams covering every TOC entry. Server-side MarkdownView uses react-markdown with remark-gfm, rehype-slug, and rehype-autolink-headings; mermaid code blocks are routed to a client-only MermaidBlock that dynamic-imports mermaid on mount. ManualSidebar (client) reads the typed TOC and highlights the active chapter via usePathname. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
28 lines
813 B
TypeScript
28 lines
813 B
TypeScript
import { MANUAL_TOC, type ManualEntry } from './manual.generated'
|
|
|
|
export type { ManualEntry } from './manual.generated'
|
|
|
|
export type ManualChapter = {
|
|
entry: ManualEntry
|
|
body: string
|
|
}
|
|
|
|
export function getManualToc(): readonly ManualEntry[] {
|
|
return MANUAL_TOC
|
|
}
|
|
|
|
function slugMatches(a: readonly string[], b: readonly string[]): boolean {
|
|
if (a.length !== b.length) return false
|
|
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false
|
|
return true
|
|
}
|
|
|
|
export function findManualEntry(slug: readonly string[]): ManualEntry | null {
|
|
return MANUAL_TOC.find((e) => slugMatches(e.slug, slug)) ?? null
|
|
}
|
|
|
|
export function getManualChapter(slug: readonly string[]): ManualChapter | null {
|
|
const entry = findManualEntry(slug)
|
|
if (!entry) return null
|
|
return { entry, body: entry.markdown }
|
|
}
|