explico 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/CHANGELOG.md +382 -1
  2. package/README.md +103 -8
  3. package/dist/compiler/astro.d.ts +9 -1
  4. package/dist/compiler/astro.js +182 -3
  5. package/dist/compiler/cli.d.ts +13 -0
  6. package/dist/compiler/cli.js +28 -4
  7. package/dist/compiler/collections.d.ts +3 -2
  8. package/dist/compiler/collections.js +28 -1
  9. package/dist/compiler/course-config.d.ts +88 -1
  10. package/dist/compiler/course-config.js +35 -1
  11. package/dist/compiler/exports/standalone-html.d.ts +34 -0
  12. package/dist/compiler/exports/standalone-html.js +803 -0
  13. package/dist/compiler/manifest.d.ts +98 -6
  14. package/dist/compiler/manifest.js +154 -17
  15. package/dist/compiler/resolution-report.d.ts +4 -0
  16. package/dist/reference/base-abbreviations.d.mts +30 -0
  17. package/dist/reference/base-abbreviations.mjs +60 -0
  18. package/dist/reference/base-operators.d.mts +15 -0
  19. package/dist/reference/base-operators.mjs +40 -0
  20. package/dist/reference/base-roman-labels.d.mts +35 -0
  21. package/dist/reference/base-roman-labels.mjs +43 -0
  22. package/dist/reference/consistency.d.ts +8 -2
  23. package/dist/reference/consistency.js +50 -3
  24. package/dist/reference/diagrams-validate.d.ts +21 -0
  25. package/dist/reference/diagrams-validate.js +13 -0
  26. package/dist/reference/equations.d.mts +10 -15
  27. package/dist/reference/equations.mjs +67 -14
  28. package/dist/reference/gate-abbreviations.d.ts +17 -0
  29. package/dist/reference/gate-abbreviations.js +64 -0
  30. package/dist/reference/gate-heading-length.d.ts +12 -0
  31. package/dist/reference/gate-heading-length.js +79 -0
  32. package/dist/reference/gate-math.d.ts +32 -5
  33. package/dist/reference/gate-math.js +6 -2
  34. package/dist/reference/gate-prose-notation.d.ts +60 -0
  35. package/dist/reference/gate-prose-notation.js +125 -0
  36. package/dist/reference/keyed-float-validate.d.ts +5 -5
  37. package/dist/reference/keyed-jsx-floats.d.mts +7 -12
  38. package/dist/reference/keyed-jsx-floats.mjs +50 -25
  39. package/dist/reference/knowledge-checks-validate.d.ts +35 -0
  40. package/dist/reference/knowledge-checks-validate.js +78 -0
  41. package/dist/reference/knowledge-checks.d.mts +25 -0
  42. package/dist/reference/knowledge-checks.mjs +45 -0
  43. package/dist/reference/lab-math-scope.d.ts +9 -1
  44. package/dist/reference/lab-math-scope.js +32 -4
  45. package/dist/reference/math-glyphs.d.mts +42 -0
  46. package/dist/reference/math-glyphs.mjs +548 -40
  47. package/dist/reference/mdx-attributes.d.mts +13 -0
  48. package/dist/reference/mdx-attributes.mjs +38 -0
  49. package/dist/reference/mixed-content.d.ts +17 -0
  50. package/dist/reference/mixed-content.js +29 -0
  51. package/dist/reference/page-notation.d.ts +52 -0
  52. package/dist/reference/page-notation.js +171 -0
  53. package/dist/reference/raw-floats-validate.d.ts +18 -0
  54. package/dist/reference/raw-floats-validate.js +53 -0
  55. package/dist/reference/raw-floats.d.mts +18 -0
  56. package/dist/reference/raw-floats.mjs +129 -0
  57. package/dist/reference/rehype-heading-anchors.d.mts +1 -1
  58. package/dist/reference/rehype-heading-anchors.mjs +107 -1
  59. package/dist/reference/rehype-table-header-labels.d.mts +26 -0
  60. package/dist/reference/rehype-table-header-labels.mjs +152 -0
  61. package/dist/reference/remark-abbreviations.d.mts +7 -0
  62. package/dist/reference/remark-abbreviations.mjs +174 -0
  63. package/dist/reference/remark-citation.d.mts +5 -1
  64. package/dist/reference/remark-citation.mjs +0 -0
  65. package/dist/reference/remark-memo.d.mts +16 -0
  66. package/dist/reference/remark-memo.mjs +339 -0
  67. package/dist/reference/remark-notation.d.mts +57 -9
  68. package/dist/reference/remark-notation.mjs +354 -42
  69. package/dist/reference/remark-short-note.d.mts +4 -0
  70. package/dist/reference/remark-short-note.mjs +237 -0
  71. package/dist/reference/types.d.ts +16 -1
  72. package/dist/reference/units-vocab.js +4 -0
  73. package/docs/VERSIONING.md +53 -4
  74. package/docs/authoring/README.md +10 -0
  75. package/docs/authoring/agents.md +17 -2
  76. package/docs/authoring/components.md +138 -0
  77. package/docs/authoring/migrating.md +275 -7
  78. package/docs/authoring/notation.md +615 -1
  79. package/docs/authoring/structure-rules.md +69 -0
  80. package/docs/authoring/structure.md +120 -8
  81. package/docs/authoring/visualizations.md +36 -3
  82. package/package.json +5 -2
  83. package/src/compiler/astro.ts +208 -3
  84. package/src/compiler/cli.ts +29 -2
  85. package/src/compiler/collections.ts +45 -4
  86. package/src/compiler/course-config.ts +132 -0
  87. package/src/compiler/exports/standalone-html.ts +963 -0
  88. package/src/compiler/manifest.ts +281 -22
  89. package/src/components/HoverPanel.astro +45 -4
  90. package/src/components/abbreviation/AbbreviationGlossary.astro +70 -0
  91. package/src/components/abbreviation/AbbreviationLayer.astro +127 -0
  92. package/src/components/assessments/AssessmentRunner.tsx +52 -17
  93. package/src/components/assessments/AssessmentSet.astro +98 -14
  94. package/src/components/assessments/RenderedContent.tsx +55 -0
  95. package/src/components/assessments/assessment-randomization.ts +16 -0
  96. package/src/components/diagram/Diagram.astro +409 -103
  97. package/src/components/disclosure/hover-preview.ts +202 -0
  98. package/src/components/disclosure/persisted-disclosure.ts +66 -0
  99. package/src/components/examples/CompactExamples.astro +2 -0
  100. package/src/components/figure/Figure.astro +279 -10
  101. package/src/components/memo/Memo.astro +453 -0
  102. package/src/components/memo/ShortNote.astro +223 -0
  103. package/src/components/notation/NotationFormula.astro +18 -1
  104. package/src/components/notation/NotationLayer.astro +260 -83
  105. package/src/components/notation/render-notation-math.ts +39 -2
  106. package/src/components/notation/safe-math-to-react.ts +50 -0
  107. package/src/components/reference/FloatRefLayer.astro +233 -15
  108. package/src/components/starlight/CollapsibleSections.astro +461 -0
  109. package/src/components/starlight/DiagramEnhancer.astro +385 -0
  110. package/src/components/starlight/HeadingAnchorEnhancer.astro +5 -17
  111. package/src/components/starlight/KeyedFloatEnhancer.astro +81 -3
  112. package/src/components/starlight/LayoutHeader.astro +50 -0
  113. package/src/components/starlight/LayoutSocialIcons.astro +41 -2
  114. package/src/components/starlight/LessonExportActions.astro +436 -0
  115. package/src/components/starlight/LessonFooter.astro +30 -3
  116. package/src/components/starlight/section-parts.ts +31 -0
  117. package/src/components/table/Table.astro +293 -7
  118. package/src/components/table/TableOverflowExpander.astro +489 -0
  119. package/src/content-config.ts +36 -1
  120. package/src/reference/base-abbreviations.mjs +60 -0
  121. package/src/reference/base-operators.mjs +40 -0
  122. package/src/reference/base-roman-labels.mjs +43 -0
  123. package/src/reference/consistency.ts +73 -2
  124. package/src/reference/diagrams-validate.ts +40 -0
  125. package/src/reference/equations.mjs +67 -14
  126. package/src/reference/gate-abbreviations.ts +128 -0
  127. package/src/reference/gate-heading-length.ts +131 -0
  128. package/src/reference/gate-math.ts +32 -7
  129. package/src/reference/gate-prose-notation.ts +224 -0
  130. package/src/reference/keyed-float-validate.ts +5 -5
  131. package/src/reference/keyed-jsx-floats.mjs +50 -25
  132. package/src/reference/knowledge-checks-validate.ts +130 -0
  133. package/src/reference/knowledge-checks.mjs +45 -0
  134. package/src/reference/lab-math-scope.ts +45 -3
  135. package/src/reference/math-glyphs.mjs +548 -40
  136. package/src/reference/mdx-attributes.mjs +38 -0
  137. package/src/reference/mixed-content.ts +69 -0
  138. package/src/reference/page-notation.ts +252 -0
  139. package/src/reference/raw-floats-validate.ts +103 -0
  140. package/src/reference/raw-floats.mjs +129 -0
  141. package/src/reference/rehype-heading-anchors.mjs +107 -1
  142. package/src/reference/rehype-table-header-labels.mjs +152 -0
  143. package/src/reference/remark-abbreviations.mjs +174 -0
  144. package/src/reference/remark-citation.mjs +0 -0
  145. package/src/reference/remark-memo.mjs +339 -0
  146. package/src/reference/remark-notation.mjs +354 -42
  147. package/src/reference/remark-short-note.mjs +237 -0
  148. package/src/reference/types.ts +16 -0
  149. package/src/reference/units-vocab.ts +4 -0
  150. package/src/styles/global.css +996 -50
@@ -1,15 +1,29 @@
1
1
  # Upgrading the explico engine
2
2
 
3
- What a course repo has to change when it bumps its `explico` dependency across a
4
- version that carries **Breaking** notes. Each section is the concrete work; the
5
- matching `CHANGELOG.md` entry (shipped in the installed package) is the full
6
- list of what moved and why.
3
+ This is the agent-readable migration artifact shipped with `explico`. It lives
4
+ at `node_modules/explico/docs/authoring/migrating.md` in an installed course, so
5
+ the instructions always accompany the engine version they describe.
6
+
7
+ There is one newest-first section for **every** published version, not only for a
8
+ version whose changelog contains **Breaking** notes. A section contains the
9
+ concrete work for consumer-owned content, configuration, source wiring, scripts,
10
+ dependencies, and generated artifacts. When a release needs none of those, its
11
+ section says **No course changes required** explicitly. The matching
12
+ `CHANGELOG.md` entry (also shipped in the package) remains the full list of what
13
+ moved and why; it is context, not a replacement for these steps.
7
14
 
8
15
  The pattern every time:
9
16
 
10
- 1. `pnpm add -D explico@<version>`
11
- 2. Do the per-version steps below.
12
- 3. `pnpm validate:content` (run it **twice** — the first run regenerates
17
+ 1. Record the currently installed version before changing it:
18
+ `node -p "require('explico/package.json').version"`.
19
+ 2. `pnpm add -D explico@<version>`.
20
+ 3. Read this file from the newly installed package and apply **every** section
21
+ after the old version through the target version, oldest first. Do not skip a
22
+ section merely because its changelog entry is not labelled **Breaking**.
23
+ 4. Make every required course-side change named by those sections, including
24
+ changes under `content/`, Astro/source configuration, and course scripts; do
25
+ not stop after changing the dependency declaration.
26
+ 5. `pnpm validate:content` (run it **twice** — the first run regenerates
13
27
  `build/resolution/*` and reports it stale; the second is clean), then
14
28
  `pnpm content check --changed`, then `astro check`, then `astro build`.
15
29
  Each stage names what it doesn't like; fix and re-run.
@@ -19,6 +33,260 @@ required config block throws with the section of this file to read.
19
33
 
20
34
  ---
21
35
 
36
+ ## 0.5.0 → 0.6.0
37
+
38
+ ### 1. Rule S1: no heading or float title runs past 65 characters
39
+
40
+ Every Markdown heading (`##` through `######`), a lesson's own
41
+ `frontmatter.title`, and the `title`/`label` prop on `Figure`, `Diagram`,
42
+ `Memo`, and `ShortNote` is now capped at 65 characters; `Table` is exempt (it
43
+ has only a `caption`). No wiring is required — the check runs as part of
44
+ `pnpm validate:content` / `astro build` the same as N9/N13/N15. Audit for
45
+ existing violations and shorten them, moving the rest of the sentence into
46
+ the paragraph after a heading or into a float's `caption`. See
47
+ [`docs/authoring/structure-rules.md#s1`](structure-rules.md#s1).
48
+
49
+ ### 2. Removed markup: `.notation-pin`, `[data-notation-control]`, `.notation-layer-heading`
50
+
51
+ The "Page notation" panel's "Pin explanation" button (`.notation-pin`,
52
+ `[data-notation-control]`) and its separate `<h2>` (`.notation-layer-heading`)
53
+ are both gone from the rendered DOM. Pinning a card now works the same way an
54
+ inline prose symbol always has — click its glyph — and the panel's
55
+ `<summary>` is its only heading. Update any course-owned CSS or end-to-end
56
+ test that targets these selectors; no other action is required.
57
+
58
+ ### 3. Removed prop: `<Diagram description>`
59
+
60
+ `Diagram`'s `description` prop and its collapsed "Diagram description"
61
+ fallback block (`.diagram-fallback`) no longer exist. `astro check` fails on
62
+ an excess prop, so remove every `description="…"` passed to `<Diagram>`; fold
63
+ that text into the diagram's `label` (caption) instead.
64
+
65
+ ### 4. Optional: collapsible "Page notation" panel and References section
66
+
67
+ `NotationLayer` gains `defaultOpen`/`rememberState` props (mirroring
68
+ `Figure`'s own), and `remark-citation.mjs`'s generated References heading now
69
+ accepts a `defaultOpen` plugin option — both ride the same persisted,
70
+ deep-linkable disclosure machinery `Figure`/`CollapsibleSections` already use,
71
+ in place of the previous always-native-default `<details>`. No action is
72
+ required to keep building: both default to closed, matching prior behavior,
73
+ and the References option only takes effect on a course whose
74
+ `astro.config.mjs` already wires `rehypeHeadingAnchors` into its rehype
75
+ pipeline. To opt into a different default, set `CourseConfig.disclosureDefaults`:
76
+
77
+ ```ts
78
+ disclosureDefaults: {
79
+ notation: true, // "Page notation" panel starts open for a reader with nothing saved yet
80
+ references: true, // generated References section starts open
81
+ },
82
+ ```
83
+
84
+ ### 5. Manifest schema is now v14 (additive: v13 → v14)
85
+
86
+ `CourseConfig.disclosureDefaults` is new and additive — nothing existing
87
+ changed shape — but a client asserting on `MANIFEST_SCHEMA_VERSION` by exact
88
+ equality needs the bump.
89
+
90
+ ### 6. Re-run `pnpm validate:content` — the notation auto-annotator's silent-failure bugs are fixed
91
+
92
+ Several shapes that previously either dropped a symbol's tooltip silently (no
93
+ build error) or produced malformed output are now fixed at the resolver
94
+ (`resolveMathGlyphs`), not just documented as traps to avoid: a bare
95
+ `\mathrm{…}`-only symbol (`\mathrm{SSR}`, `\mathrm{SST}`) can now auto-resolve
96
+ at every later bare occurrence, a bare symbol immediately next to an
97
+ `\explain{…}{…}` call no longer has its span corrupted, and a partial
98
+ `\explain{key}{…}` wrap no longer produces unparseable doubled output. No
99
+ course-side wiring changes, but re-running `pnpm validate:content` may surface
100
+ two new classes of error that previously passed silently:
101
+
102
+ - **"Unresolved notation"** for a symbol that was relying on one of the fixed
103
+ bugs to appear resolved when it was not (rare — the bugs mostly hid symbols
104
+ entirely rather than falsely resolving them) or for the uncovered remainder
105
+ of a partial `\explain{key}{…}` wrap. Fix by explaining the symbol, or by
106
+ wrapping the key's *entire* declared `latex`, not just its base glyph.
107
+ - **"Page glyphs … have structurally identical LaTeX"** for two different
108
+ notation keys whose declared `latex` is the same `\operatorname{…}` or
109
+ `\mathrm{…}` form (e.g. two keys both `\operatorname{Var}`) — this check
110
+ previously silently skipped every such glyph and could not catch this. Give
111
+ the colliding keys distinct canonical forms, or reach for
112
+ `\explain{key}{…}` at every occurrence of whichever one keeps the shared
113
+ form.
114
+
115
+ ## 0.4.x → 0.5.0
116
+
117
+ ### 1. Rule N9: wrap every plain-text quantity, unit, and operator in `$…$`
118
+
119
+ Every physical quantity, unit abbreviation, or math operator ever typed as
120
+ plain text — in lesson prose, a table cell, or (new in 0.5.0) an assessment
121
+ item's `prompt` / `explanation` string — must now be inside `$…$`. `45 m/s`,
122
+ `t (s)`, `vx`, `\|v\|`, `KE/m` are all the same mistake. This is build-enforced
123
+ with **no `lint-ignore.yml` escape hatch**: `pnpm validate:content` / `astro
124
+ build` fails on every existing violation. Fix per
125
+ [`docs/authoring/notation.md#n9`](notation.md#n9) — wrap the symbol in `$…$`
126
+ and fold its unit into the *same* span as `\text{}` (`$t\ \text{(s)}$`, not two
127
+ adjacent spans).
128
+
129
+ Also wire the accessible-table-header plugin this rule ships with — the build
130
+ works without it, but a table header that is now 100% KaTeX (a bare `$t$`
131
+ column, since its unit moved inside `$…$` too) renders with no
132
+ screen-reader-visible name until this is wired:
133
+
134
+ ```diff
135
+ + import rehypeTableHeaderLabels from 'explico/reference/rehype-table-header-labels.mjs';
136
+ …
137
+ rehypePlugins: [
138
+ [rehypeKatex, createNotationKatexOptions()],
139
+ rehypeFailKatexErrors,
140
+ + rehypeTableHeaderLabels,
141
+ ]
142
+ ```
143
+
144
+ It reads the `\explain{key}{…}` key(s) a header's LaTeX names and backfills an
145
+ `sr-only` label from that key's notation metadata — the one prerequisite is
146
+ that the header's symbol resolves to a key at all, so a `\mathrm{…}` compound
147
+ (`\mathrm{KE}/m`) needs each side explicitly `\explain{}`-wrapped.
148
+
149
+ ### 2. Rule N13: a nonlinear function always takes a parenthesized argument
150
+
151
+ `\sin x`, `\log t`, `\exp\theta` — every trig/inverse-trig/hyperbolic function
152
+ plus `exp`/`log`/`ln`/`lg` — is now a hard error unless its argument is
153
+ parenthesized: `\sin(x)` or `\sin\left(x\right)` is required. Same enforcement
154
+ shape as N9: build-enforced, no `lint-ignore.yml` escape. It fires on lesson
155
+ body math, `notation.formula`, assessment `prompt`/`explanation`, `Diagram`
156
+ formulas, and interactive lab math alike, since all of them resolve through
157
+ the same glyph walker. Fix every occurrence; see
158
+ [`docs/authoring/notation.md#n13`](notation.md#n13).
159
+
160
+ ### 3. Rule N15: size every level of a nested visible delimiter
161
+
162
+ Once a `(`, `[`, `\{`, or `|` sits inside another one of those four — same
163
+ type or mixed, e.g. `(a + [b])` — **every level of that nest** must switch to
164
+ `\left`/`\right` sizing: `\sin(2(90°-\theta))` is now a hard error,
165
+ `\sin\left(2\left(90°-\theta\right)\right)` is required. Same enforcement
166
+ shape as N9/N13: build-enforced, no escape hatch. A single, non-nested bare
167
+ delimiter (`(x)`) is untouched. Fix every nest; see
168
+ [`docs/authoring/notation.md#n15`](notation.md#n15).
169
+
170
+ ### 4. Rule N14: catalogue every abbreviation used in lesson prose
171
+
172
+ Every acronym (`OLS`, `MSE`) or dotted abbreviation (`w.r.t.`, `i.i.d.`) used in
173
+ plain prose must now be on the shipped baseline
174
+ (`base-abbreviations.mjs`), listed in `course.config.ts`'s new
175
+ `abbreviations.allow` / `abbreviations.deny`, given an entry in the new
176
+ `content/abbreviations/*.md` collection, or already explained as a math
177
+ quantity via N8/N10. This is build-enforced, same error-severity and
178
+ no-`lint-ignore.yml`-escape-hatch shape as N9.
179
+
180
+ ```ts
181
+ export const courseConfig = {
182
+ // …existing fields…
183
+ abbreviations: {
184
+ allow: ['GDP'], // treat as universal, skip the check
185
+ deny: ['ETA'], // demote a baseline entry back to "must be explained"
186
+ },
187
+ } satisfies CourseConfig;
188
+ ```
189
+
190
+ ```markdown
191
+ ---
192
+ key: ols
193
+ abbr: OLS
194
+ expansion: Ordinary least squares
195
+ aliases: []
196
+ ---
197
+ ```
198
+
199
+ Run `pnpm validate:content` (twice) and `pnpm content check --changed`. Fix
200
+ every `abbreviation-explained` diagnostic by adding a
201
+ `content/abbreviations/<key>.md` entry or an `allow` entry in
202
+ `course.config.ts`.
203
+
204
+ The catalog check above runs regardless of Astro wiring, but the inline
205
+ hover/click card on a lesson page's first occurrence of a catalogued
206
+ abbreviation needs its remark plugin wired in too:
207
+
208
+ ```diff
209
+ + import remarkAbbreviations from 'explico/reference/remark-abbreviations.mjs';
210
+ …
211
+ remarkPlugins: [
212
+ …
213
+ [remarkCitation, { sources: manifest.sources }],
214
+ + [remarkAbbreviations, { abbreviations: manifest.abbreviations }],
215
+ ]
216
+ ```
217
+
218
+ ### 5. Optional: rule N10 warns on an unexplained `\mathrm{…}` label
219
+
220
+ A `\mathrm{…}` multi-letter label (`\mathrm{KE}`, `\mathrm{PV}`) not on the
221
+ shipped roman-label baseline (`base-roman-labels.mjs`) or `course.config.ts`'s
222
+ new `romanLabels.allow` now needs a notation entry the reader can hover — the
223
+ `\mathrm{…}` counterpart to N8. Unlike N9/N13/N14/N15, this is a **Tier-3
224
+ warning** (`roman-label-explained`), not a build failure: it never blocks
225
+ `astro build`, and an existing violation can be silenced with a reviewed
226
+ `lint-ignore.yml` line (`roman-label-explained:KE — <reason>`) while content is
227
+ cleaned up. `pnpm validate:content` surfaces it. See
228
+ [`docs/authoring/notation.md#n10`](notation.md#n10).
229
+
230
+ ### 6. Only if you render `AssessmentRunner` directly (bypassing `AssessmentSet.astro`)
231
+
232
+ `AssessmentRunner`'s `Item` props changed shape: `prompt` / `explanation`
233
+ (`string`) are now `promptContent` / `explanationContent`
234
+ (`MixedContentNode[]`), rendered with the new `RenderedContent` component,
235
+ because `AssessmentSet.astro` now pre-renders assessment math through the same
236
+ KaTeX pipeline as lesson body math instead of handing `AssessmentRunner` a raw
237
+ string. A course that only uses `<AssessmentSet>` needs no change here — this
238
+ only applies to a course that imports and renders `AssessmentRunner` itself.
239
+
240
+ ### 7. Manifest schema is v13 (additive: v7 → v8 → v9 → v10 → v11 → v12 → v13)
241
+
242
+ Every step is additive — nothing existing changed shape — but a client
243
+ asserting on `MANIFEST_SCHEMA_VERSION` by exact equality needs the final
244
+ number:
245
+
246
+ - **v8** — `assessmentContent`: every assessment item's `prompt` /
247
+ `explanation`, pre-split and resolved for `AssessmentSet.astro` (see item 6
248
+ above).
249
+ - **v9** — `diagrams`, `lessons[].diagrams`, `lessons[].numbering.diagrams`,
250
+ `diagnostics.diagrams`: `<Diagram>` becomes a first-class keyed float with
251
+ its own number stream and `[[dia-<id>]]` references.
252
+ - **v10** — `checks`, `lessons[].knowledgeChecks`, `lessons[].numbering.checks`,
253
+ `diagnostics.checks`: numbered, referenceable knowledge checks.
254
+ - **v11** — `lessons[].lessonExports`-derived fields: standalone HTML / print
255
+ export settings (item 8 below).
256
+ - **v12** — `manifest.abbreviations` (rule N14, item 4 above).
257
+ - **v13** — `manifest.diagnostics.rawFloats`: a raw Markdown/HTML table, an
258
+ unkeyed `<Diagram>`, or a `<Diagram>` nested outside
259
+ `<Memo>`/`<ShortNote>`/`<Table>`/`<Figure>` — none of these reach
260
+ keyed-float validation, so this diagnostic flags them separately.
261
+
262
+ ### 8. Optional: enable standalone HTML / print lesson exports
263
+
264
+ No action required to keep building. To opt in, add to
265
+ `content/course.config.ts`:
266
+
267
+ ```ts
268
+ lessonExports: {
269
+ standaloneHtml: true,
270
+ print: true,
271
+ },
272
+ canonicalBaseUrl: 'https://your-course.example.com',
273
+ ```
274
+
275
+ ### 9. Optional: turn on strict numbering cross-checks
276
+
277
+ `remarkNotation`'s new `strict: true` option — recommended via
278
+ `createRemarkNotationOptions(manifest, { strict: true })` — fails the build on
279
+ any catalogued lesson that has an equation, `<Table>`, or `<Figure>` (keyed or
280
+ not) with no placement, instead of silently falling back to legacy `##`-section
281
+ numbering. Off by default; turn it on once existing content is clean.
282
+
283
+ ### Verification
284
+
285
+ `pnpm validate:content` (run it twice), then `pnpm content check --changed`,
286
+ then `astro check`, then `astro build`.
287
+
288
+ ---
289
+
22
290
  ## 0.3.x → 0.4.0
23
291
 
24
292
  ### 1. Rename `sections` to `parts` in `content/course.config.ts`