/ tutorials / laplace-dirichlet
Sign in
tutorials / laplace-dirichlet
laplace-dirichlet / src / ui / ChapterView.tsx
54 lines · 2.0 KBCodeBlameHistory
e5fc8c6An introduction and static figures, and the MATLAB written plainly againJeremy Magland 1// A chapter: prose with its labs and figures dropped in where the text calls
2// for them.
4// The prose is one markdown file per chapter, with a line
5//
6// <!--lab:convergence-->
e5fc8c6An introduction and static figures, and the MATLAB written plainly againJeremy Magland 9// wherever a lab or a static figure belongs. Splitting on those markers keeps
10// the writing in one readable file instead of scattered through JSX.
088be4cAn interactive tutorial on the Dirichlet problem, accuracy against costJeremy Magland 11import { useMemo } from 'react'
12import Markdown from './Markdown.tsx'
13import Lab from './Lab.tsx'
14import type { Chapter } from './types.ts'
e5fc8c6An introduction and static figures, and the MATLAB written plainly againJeremy Magland 15import { FIGURES } from '../figures/index.ts'
e5fc8c6An introduction and static figures, and the MATLAB written plainly againJeremy Magland 17const MARKER = /<!--\s*(lab|fig):([a-z0-9_-]+)\s*-->/gi
19export default function ChapterView({ chapter }: { chapter: Chapter }) {
20 const pieces = useMemo(() => {
e5fc8c6An introduction and static figures, and the MATLAB written plainly againJeremy Magland 21 const out: ({ md: string } | { labId: string } | { figId: string })[] = []
23 MARKER.lastIndex = 0
24 let m: RegExpExecArray | null
25 while ((m = MARKER.exec(chapter.text)) !== null) {
26 out.push({ md: chapter.text.slice(last, m.index) })
e5fc8c6An introduction and static figures, and the MATLAB written plainly againJeremy Magland 27 out.push(m[1] === 'fig' ? { figId: m[2] } : { labId: m[2] })
088be4cAn interactive tutorial on the Dirichlet problem, accuracy against costJeremy Magland 28 last = m.index + m[0].length
29 }
30 out.push({ md: chapter.text.slice(last) })
31 return out
32 }, [chapter.text])
34 return (
35 <article className="chapter">
36 <header className="chapter-head">
37 <div className="chapter-part">{chapter.part}</div>
38 <h2>{chapter.title}</h2>
39 <p className="chapter-blurb">{chapter.blurb}</p>
40 </header>
41 {pieces.map((p, i) => {
42 if ('md' in p) return p.md.trim() === '' ? null : <Markdown key={i} src={p.md} />
44 const Fig = FIGURES[p.figId]
45 if (!Fig) return <p key={i} className="lab-error">missing figure: {p.figId}</p>
46 return <Fig key={`${chapter.id}-fig-${p.figId}`} />
47 }
088be4cAn interactive tutorial on the Dirichlet problem, accuracy against costJeremy Magland 48 const lab = chapter.labs.find((l) => l.id === p.labId)
49 if (!lab) return <p key={i} className="lab-error">missing lab: {p.labId}</p>
50 return <Lab key={`${chapter.id}-${lab.id}`} spec={lab} />
51 })}
52 </article>
53 )
↑↓ move↵openescclose