explico 0.8.0 → 0.11.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.
- package/CHANGELOG.md +1239 -1
- package/README.md +60 -15
- package/dist/compiler/astro.d.ts +6 -1
- package/dist/compiler/cli.d.ts +46 -2
- package/dist/compiler/cli.js +70 -4
- package/dist/compiler/collections.d.ts +35 -2
- package/dist/compiler/collections.js +68 -5
- package/dist/compiler/course-config.d.ts +3 -194
- package/dist/compiler/course-config.js +78 -5
- package/dist/compiler/exports/standalone-html.d.ts +6 -1
- package/dist/compiler/knowledge-version.js +1 -1
- package/dist/compiler/lesson-derivation.d.ts +27 -10
- package/dist/compiler/lesson-derivation.js +23 -8
- package/dist/compiler/logging.d.ts +4 -1
- package/dist/compiler/logging.js +4 -1
- package/dist/compiler/manifest.d.ts +204 -31
- package/dist/compiler/manifest.js +270 -55
- package/dist/compiler/resolution-report.d.ts +6 -1
- package/dist/course-config-Dsnri9Tk.d.ts +464 -0
- package/dist/reference/base-accents.d.mts +26 -0
- package/dist/reference/base-accents.mjs +31 -0
- package/dist/reference/base-roman-labels.d.mts +2 -2
- package/dist/reference/base-roman-labels.mjs +2 -2
- package/dist/reference/consistency.d.ts +14 -2
- package/dist/reference/consistency.js +108 -4
- package/dist/reference/delimiter-size.d.ts +3 -2
- package/dist/reference/diagrams-validate.d.ts +7 -2
- package/dist/reference/diagrams-validate.js +9 -1
- package/dist/reference/equations-validate.d.ts +8 -5
- package/dist/reference/equations-validate.js +1 -0
- package/dist/reference/equations.d.mts +60 -31
- package/dist/reference/equations.mjs +83 -43
- package/dist/reference/examples-validate.d.ts +31 -0
- package/dist/reference/examples-validate.js +48 -0
- package/dist/reference/figures-validate.d.ts +1 -1
- package/dist/reference/figures-validate.js +4 -1
- package/dist/reference/folds-validate.d.ts +33 -0
- package/dist/reference/folds-validate.js +32 -0
- package/dist/reference/gate-abbreviations.d.ts +3 -1
- package/dist/reference/gate-abbreviations.js +1 -0
- package/dist/reference/gate-course-rules.d.ts +32 -0
- package/dist/reference/gate-course-rules.js +85 -0
- package/dist/reference/gate-heading-length.d.ts +5 -2
- package/dist/reference/gate-heading-length.js +45 -21
- package/dist/reference/gate-heading-structure.d.ts +41 -0
- package/dist/reference/gate-heading-structure.js +113 -0
- package/dist/reference/gate-math-punctuation.d.ts +71 -0
- package/dist/reference/gate-math-punctuation.js +251 -0
- package/dist/reference/gate-math.d.ts +22 -6
- package/dist/reference/gate-math.js +42 -8
- package/dist/reference/gate-part-pages.d.ts +50 -0
- package/dist/reference/gate-part-pages.js +118 -0
- package/dist/reference/gate-prose-notation.d.ts +21 -11
- package/dist/reference/gate-prose-notation.js +25 -7
- package/dist/reference/katex-delimiters.mjs +20 -7
- package/dist/reference/keyed-float-validate.d.ts +27 -10
- package/dist/reference/keyed-float-validate.js +15 -1
- package/dist/reference/keyed-jsx-floats.d.mts +11 -5
- package/dist/reference/keyed-jsx-floats.mjs +73 -20
- package/dist/reference/knowledge-checks-validate.d.ts +1 -1
- package/dist/reference/knowledge-checks.d.mts +3 -1
- package/dist/reference/knowledge-checks.mjs +9 -4
- package/dist/reference/lab-math-scope.d.ts +1 -0
- package/dist/reference/lab-math-slot.d.ts +34 -0
- package/dist/reference/lab-math-slot.js +6 -0
- package/dist/reference/math-glyphs.d.mts +80 -4
- package/dist/reference/math-glyphs.mjs +572 -37
- package/dist/reference/page-notation.d.ts +6 -1
- package/dist/reference/raw-floats-validate.js +1 -1
- package/dist/reference/raw-floats.mjs +1 -1
- package/dist/reference/rehype-heading-anchors.d.mts +14 -0
- package/dist/reference/rehype-heading-anchors.mjs +116 -17
- package/dist/reference/rehype-table-header-labels.d.mts +6 -1
- package/dist/reference/rehype-table-header-labels.mjs +21 -3
- package/dist/reference/remark-asides.d.mts +3 -0
- package/dist/reference/remark-asides.mjs +180 -0
- package/dist/reference/remark-memo.d.mts +3 -1
- package/dist/reference/remark-memo.mjs +42 -11
- package/dist/reference/remark-notation.d.mts +60 -10
- package/dist/reference/remark-notation.mjs +387 -36
- package/dist/reference/render-lab-math.d.ts +4 -26
- package/dist/reference/render-lab-math.js +4 -4
- package/dist/reference/sections-validate.d.ts +27 -0
- package/dist/reference/sections-validate.js +41 -0
- package/dist/reference/sections.d.mts +97 -0
- package/dist/reference/sections.mjs +306 -0
- package/dist/reference/tables-validate.d.ts +1 -1
- package/dist/reference/types.d.ts +17 -1
- package/dist/reference/unit-words.d.ts +37 -0
- package/dist/reference/unit-words.js +170 -0
- package/dist/rules/catalog.d.ts +176 -0
- package/dist/rules/catalog.js +983 -0
- package/dist/rules/course-rules.d.ts +115 -0
- package/dist/rules/course-rules.js +292 -0
- package/dist/rules/course-rules.schema.json +138 -0
- package/dist/rules/in-effect.d.ts +53 -0
- package/dist/rules/in-effect.js +142 -0
- package/dist/rules/rules.schema.json +1072 -0
- package/dist/rules/settings.d.ts +3 -0
- package/dist/rules/settings.js +290 -0
- package/dist/rules/waivers.d.ts +53 -0
- package/dist/rules/waivers.js +132 -0
- package/dist/session/PreferenceStore.d.ts +5 -0
- package/dist/session/PreferenceStore.js +9 -0
- package/docs/VERSIONING.md +2 -2
- package/docs/authoring/README.md +232 -40
- package/docs/authoring/agents.md +55 -9
- package/docs/authoring/components.md +178 -22
- package/docs/authoring/migrating.md +1096 -2
- package/docs/authoring/notation.md +576 -322
- package/docs/authoring/prose.md +551 -0
- package/docs/authoring/retired.md +35 -0
- package/docs/authoring/structure-rules.md +422 -40
- package/docs/authoring/structure.md +445 -62
- package/docs/authoring/versioning.md +20 -28
- package/docs/authoring/visualizations.md +142 -20
- package/package.json +2 -2
- package/src/compiler/cli.ts +116 -6
- package/src/compiler/collections.ts +111 -7
- package/src/compiler/course-config.ts +273 -34
- package/src/compiler/knowledge-version.ts +1 -1
- package/src/compiler/lesson-derivation.ts +54 -15
- package/src/compiler/logging.ts +8 -2
- package/src/compiler/manifest.ts +573 -104
- package/src/components/BlockHeading.astro +113 -0
- package/src/components/CourseContents.astro +221 -0
- package/src/components/CurriculumMap.astro +5 -6
- package/src/components/FloatIndex.astro +200 -0
- package/src/components/HoverPanel.astro +431 -79
- package/src/components/PartBridge.astro +27 -0
- package/src/components/PartOverview.astro +401 -0
- package/src/components/PartScope.astro +27 -0
- package/src/components/abbreviation/AbbreviationLayer.astro +49 -51
- package/src/components/assessments/AssessmentRunner.tsx +8 -5
- package/src/components/assessments/AssessmentSet.astro +23 -26
- package/src/components/block-heading.ts +146 -0
- package/src/components/card-arrow.ts +243 -0
- package/src/components/card-drag.ts +631 -0
- package/src/components/card-jump.ts +45 -0
- package/src/components/card-manager.ts +1589 -0
- package/src/components/card-memory.ts +177 -0
- package/src/components/card-placement.ts +504 -0
- package/src/components/card-side.ts +336 -0
- package/src/components/card-travel.ts +197 -0
- package/src/components/citation/CitationLayer.astro +77 -76
- package/src/components/diagram/Diagram.astro +161 -316
- package/src/components/disclosure/course-disclosure.ts +24 -0
- package/src/components/disclosure/hover-preview.ts +122 -42
- package/src/components/disclosure/persisted-disclosure.ts +3 -3
- package/src/components/disclosure/print-as-shown.ts +252 -0
- package/src/components/examples/CompactExample.astro +3 -1
- package/src/components/examples/CompactExamples.astro +101 -94
- package/src/components/figure/Figure.astro +174 -274
- package/src/components/figure/FloatCaption.astro +87 -0
- package/src/components/figure/figure-state.ts +58 -0
- package/src/components/figure/figure-tools.ts +87 -0
- package/src/components/float-name.ts +101 -0
- package/src/components/fold/Fold.astro +125 -0
- package/src/components/fold/fold-id.ts +40 -0
- package/src/components/memo/Memo.astro +162 -231
- package/src/components/memo/ShortNote.astro +6 -6
- package/src/components/notation/NotationFormula.astro +5 -1
- package/src/components/notation/NotationGlossary.astro +3 -4
- package/src/components/notation/NotationLayer.astro +169 -162
- package/src/components/notation/NotationMath.astro +10 -1
- package/src/components/reference/FloatRefLayer.astro +485 -423
- package/src/components/starlight/AboutPanel.astro +5 -4
- package/src/components/starlight/CollapsibleSections.astro +207 -93
- package/src/components/starlight/DiagramEnhancer.astro +15 -138
- package/src/components/starlight/HeadingAnchorEnhancer.astro +193 -1
- package/src/components/starlight/KeyedFloatEnhancer.astro +100 -9
- package/src/components/starlight/LayoutHeader.astro +298 -19
- package/src/components/starlight/LayoutPageSidebar.astro +99 -12
- package/src/components/starlight/LayoutPageTitle.astro +120 -0
- package/src/components/starlight/LayoutSidebar.astro +229 -11
- package/src/components/starlight/LessonExportActions.astro +53 -72
- package/src/components/starlight/LessonFooter.astro +26 -4
- package/src/components/starlight/section-parts.ts +15 -2
- package/src/components/starlight/section-summary.ts +181 -0
- package/src/components/table/Table.astro +95 -76
- package/src/components/table/TableOverflowExpander.astro +65 -28
- package/src/content-config.ts +40 -4
- package/src/reference/base-accents.mjs +31 -0
- package/src/reference/base-roman-labels.mjs +2 -2
- package/src/reference/consistency.ts +176 -5
- package/src/reference/delimiter-size.ts +3 -2
- package/src/reference/diagrams-validate.ts +17 -1
- package/src/reference/equations-validate.ts +10 -5
- package/src/reference/equations.mjs +83 -43
- package/src/reference/examples-validate.ts +97 -0
- package/src/reference/figures-validate.ts +6 -1
- package/src/reference/folds-validate.ts +65 -0
- package/src/reference/gate-abbreviations.ts +1 -0
- package/src/reference/gate-course-rules.ts +134 -0
- package/src/reference/gate-heading-length.ts +66 -35
- package/src/reference/gate-heading-structure.ts +193 -0
- package/src/reference/gate-math-punctuation.ts +381 -0
- package/src/reference/gate-math.ts +69 -10
- package/src/reference/gate-part-pages.ts +217 -0
- package/src/reference/gate-prose-notation.ts +59 -12
- package/src/reference/katex-delimiters.mjs +20 -7
- package/src/reference/keyed-float-validate.ts +45 -11
- package/src/reference/keyed-jsx-floats.mjs +73 -20
- package/src/reference/knowledge-checks-validate.ts +1 -1
- package/src/reference/knowledge-checks.mjs +9 -4
- package/src/reference/lab-math-slot.ts +36 -0
- package/src/reference/math-glyphs.mjs +572 -37
- package/src/reference/raw-floats-validate.ts +1 -1
- package/src/reference/raw-floats.mjs +1 -1
- package/src/reference/rehype-heading-anchors.mjs +116 -17
- package/src/reference/rehype-table-header-labels.mjs +21 -3
- package/src/reference/remark-asides.mjs +180 -0
- package/src/reference/remark-memo.mjs +42 -11
- package/src/reference/remark-notation.mjs +387 -36
- package/src/reference/render-lab-math.ts +16 -31
- package/src/reference/sections-validate.ts +81 -0
- package/src/reference/sections.mjs +306 -0
- package/src/reference/tables-validate.ts +2 -1
- package/src/reference/types.ts +17 -0
- package/src/reference/unit-words.ts +233 -0
- package/src/rules/catalog.ts +1298 -0
- package/src/rules/course-rules.ts +456 -0
- package/src/rules/in-effect.ts +235 -0
- package/src/rules/settings.ts +448 -0
- package/src/rules/waivers.ts +249 -0
- package/src/session/PreferenceStore.ts +15 -0
- package/src/styles/global.css +1471 -163
- package/src/styles/surfaces.css +182 -0
- package/src/components/hover-panel.ts +0 -339
- package/src/components/popup-stack.ts +0 -345
|
@@ -33,6 +33,1100 @@ required config block throws with the section of this file to read.
|
|
|
33
33
|
|
|
34
34
|
---
|
|
35
35
|
|
|
36
|
+
## 0.10.0 → 0.11.0
|
|
37
|
+
|
|
38
|
+
**Course changes are required.** Figures and diagrams no longer compact.
|
|
39
|
+
`disclosure.diagrams`, `<Diagram defaultOpen>` and `<Diagram rememberState>`
|
|
40
|
+
are removed, and each one fails the build until you delete it (steps 2–3).
|
|
41
|
+
The rest is additive or affects only readers: `<Fold>`, a lab's `tools`
|
|
42
|
+
slot and live caption end, the short caption shown in the caption line (rule
|
|
43
|
+
S9, a guide), the "Figures and tables" page, unnumbered `[card=meta]`
|
|
44
|
+
sections, and explanation cards that pin, dock, drag and are remembered.
|
|
45
|
+
Nothing in `astro.config.mjs` changes. The manifest schema moves from v23 to
|
|
46
|
+
v24.
|
|
47
|
+
|
|
48
|
+
**Coming from 0.8.0, the last version on npm before this one.** 0.9.0 and
|
|
49
|
+
0.10.0 were tagged but never published to npm, so a course that installs
|
|
50
|
+
from npm goes from 0.8.0 straight to 0.11.0. Install 0.11.0 once (step 1).
|
|
51
|
+
Then apply the course changes of "0.8.0 → 0.9.0" and "0.9.0 → 0.10.0" below,
|
|
52
|
+
oldest first, and skip their "Update the dependency" steps. Finish with this
|
|
53
|
+
section. Three steps of the 0.10.0 section read differently at 0.11.0. Apply
|
|
54
|
+
them in this form:
|
|
55
|
+
|
|
56
|
+
- Its step 3 puts `diagrams: { defaultOpen: true }` in `disclosure`, and its
|
|
57
|
+
step 4 adds `diagrams` to the settings schema. Leave `diagrams` out: it now
|
|
58
|
+
fails the build (step 2 below). `disclosure.figures` now sets whether a
|
|
59
|
+
lab's tools start open, not whether a figure starts compacted.
|
|
60
|
+
- Its step 14 describes the compaction markup of a figure and a diagram
|
|
61
|
+
(`.float-caption__toggle`, "a compacted float keeps the caption line").
|
|
62
|
+
That markup is gone (step 9 below).
|
|
63
|
+
- Its step 5 lists the diagnostic groups for `compile-manifest.ts`. Add
|
|
64
|
+
`folds` to them as well (step 4 below).
|
|
65
|
+
|
|
66
|
+
Work in this order: steps 1–5 fix the wiring, so that `pnpm validate:content`
|
|
67
|
+
runs; steps 6–8 are content, and steps 7–8 are conditional; steps 9–11 apply
|
|
68
|
+
only to a course whose own CSS, tests, code or stored keys reach into the
|
|
69
|
+
engine; step 12 is optional; step 13 records the content changes; step 15 is
|
|
70
|
+
the check.
|
|
71
|
+
|
|
72
|
+
### 1. Update the dependency
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pnpm add -D explico@0.11.0
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 2. Delete `disclosure.diagrams` (the build fails until you do)
|
|
79
|
+
|
|
80
|
+
A diagram no longer folds by itself, so it has no default. `normalizeDisclosure`
|
|
81
|
+
throws on the key and names the edit to make, which stops both
|
|
82
|
+
`pnpm validate:content` and `astro build`. Delete `diagrams` from the
|
|
83
|
+
`disclosure` block of `content/course.settings.json`, or from
|
|
84
|
+
`CourseConfig.disclosure` in `content/course.config.ts`, wherever the course
|
|
85
|
+
keeps it.
|
|
86
|
+
|
|
87
|
+
`disclosure.figures` stays, but it now means something else: whether a
|
|
88
|
+
**lab's tools** start open (the `tools` slot, step 12). A figure's picture
|
|
89
|
+
and caption always show. A course that set `figures: { defaultOpen: false }`
|
|
90
|
+
to start its figures compacted now starts every lab's tools folded instead.
|
|
91
|
+
Delete the setting unless that is what you want. To let a reader fold a
|
|
92
|
+
figure away, put it in a `<Fold>` (step 12) or a collapsible section.
|
|
93
|
+
|
|
94
|
+
New and optional: `disclosure.folds: { defaultOpen }`, whether a `<Fold>`
|
|
95
|
+
starts open. The default is closed.
|
|
96
|
+
|
|
97
|
+
**Only if the course describes its settings in a JSON Schema** (the
|
|
98
|
+
playground's `course.settings.schema.json`, where `disclosure` has
|
|
99
|
+
`additionalProperties: false`), remove `diagrams`, add `folds` and
|
|
100
|
+
re-describe `figures`:
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
"folds": {
|
|
104
|
+
"title": "Folds",
|
|
105
|
+
"description": "A `<Fold>` folds like a memo, with no marker, letter or frame: a stretch of content — most often a figure or diagram — a reader can fold away. Default: closed.",
|
|
106
|
+
"$ref": "#/definitions/initialState"
|
|
107
|
+
},
|
|
108
|
+
"figures": {
|
|
109
|
+
"title": "A lab's tools",
|
|
110
|
+
"description": "Whether a lab's tools (the sliders, fields and live equation after a `<Figure>`'s caption) start open. The figure's picture and caption always show. Default: open.",
|
|
111
|
+
"$ref": "#/definitions/initialState"
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The `rules` and `courseRules` properties `$ref` the schemas in
|
|
116
|
+
`node_modules/explico/dist/rules/`, so rule S9 (step 6) needs no edit there.
|
|
117
|
+
|
|
118
|
+
### 3. Delete `defaultOpen` / `rememberState` from every `<Diagram>`
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
rg -n -U '<Diagram\b[^>]*\b(defaultOpen|rememberState)\b' content src
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Both props are removed. In a lesson, each one fails `pnpm validate:content`
|
|
125
|
+
(`dia-removed-prop`). A `<Diagram>` rendered by a wrapper component throws
|
|
126
|
+
when its page builds, and the manifest scan cannot see inside the wrapper.
|
|
127
|
+
Check every wrapper `.astro` file, including one that passes its own props
|
|
128
|
+
through to `<Diagram>`. To let a reader fold a diagram away, put it in a
|
|
129
|
+
`<Fold>` (step 12) or a collapsible section.
|
|
130
|
+
|
|
131
|
+
`<Figure defaultOpen>` and `<Figure rememberState>` stay. They now set that
|
|
132
|
+
figure's lab tools (step 12), and they do nothing on a figure without a
|
|
133
|
+
`tools` slot.
|
|
134
|
+
|
|
135
|
+
### 4. `scripts/compile-manifest.ts`: add the `folds` group
|
|
136
|
+
|
|
137
|
+
The manifest has a new diagnostics group, `diagnostics.folds`
|
|
138
|
+
(`fold-unnamed`, step 12). Add it to both the warnings loop and the errors
|
|
139
|
+
loop, next to `examples`:
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
const { /* … */ examples, folds, knowledge, rawFloats, config, waivers } =
|
|
143
|
+
manifest.diagnostics;
|
|
144
|
+
|
|
145
|
+
// In BOTH loops over [['equations', equations], …]:
|
|
146
|
+
['examples', examples],
|
|
147
|
+
['folds', folds],
|
|
148
|
+
['rawFloats', rawFloats],
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Without it, a `<Fold>` with nothing to name its bar does not fail
|
|
152
|
+
`validate:content`, though the page build still fails on it. `content check`,
|
|
153
|
+
`content diagnostics` and `content status` read the group already.
|
|
154
|
+
|
|
155
|
+
### 5. The manifest schema is now v24
|
|
156
|
+
|
|
157
|
+
It was v23 in 0.10.0. `pnpm validate:content` rewrites `build/manifest.json`,
|
|
158
|
+
so this step matters only for code that reads the manifest or pins its
|
|
159
|
+
version:
|
|
160
|
+
|
|
161
|
+
- **v24**: `disclosure` loses `diagrams` and gains `folds`, and
|
|
162
|
+
`diagnostics.folds` is new. When the course has a top-level
|
|
163
|
+
`content/docs/figures-and-tables.mdx`, the Reference group in `sidebar` also
|
|
164
|
+
lists "Figures and tables". The item has the same shape as the others.
|
|
165
|
+
|
|
166
|
+
### 6. Captions: rule S9, and the short caption that now shows
|
|
167
|
+
|
|
168
|
+
A float's `short` caption now opens its caption line as a bold title:
|
|
169
|
+
"**Sampled flight data.** Position, velocity, …". It also names the float in
|
|
170
|
+
a folded section's "Hidden here" line, in a copied link, and on the "Figures
|
|
171
|
+
and tables" page. Nothing fails, but two kinds of float now read badly:
|
|
172
|
+
|
|
173
|
+
1. **A long `caption` that restates the `short` one reads twice**, for
|
|
174
|
+
example "**Sampled flight data.** Sampled flight data: position, …". Rule
|
|
175
|
+
S9 (`structure-rules.md#s9`) says the long caption continues from the
|
|
176
|
+
short caption's name. It says what the float shows — its subject, its
|
|
177
|
+
marks and symbols, the case shown — and at most the one thing to notice.
|
|
178
|
+
2. **A figure, table or diagram without `short`** has no title, and the
|
|
179
|
+
"Figures and tables" page lists it by its long caption, greyed out. Rule
|
|
180
|
+
S9 and `components.md` now ask for a `short` on every one. Find them:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
rg -n -U --pcre2 '<(Figure|Table|Diagram)\b(?![^>]*\bshort=)[^>]*>' content/docs
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Rule S9 also moves text out of figures. A figure holds no running text. The
|
|
187
|
+
argument drawn from a figure is lesson text after it, and a lab's
|
|
188
|
+
instructions are the first line of its tools (step 12). Rule S9 is a guide:
|
|
189
|
+
review-only, on `build/rules-in-effect.md` and `pnpm content rules`. Switch it
|
|
190
|
+
off with `rules.S9.enabled: false` if it does not fit the course.
|
|
191
|
+
|
|
192
|
+
### 7. Only if a lesson has a `[card=meta]` section: section numbers change
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
rg -n '^#{2,6} .*\[card=meta\]' content/docs
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
A `[card=meta]` section is now unnumbered, like References, and so is every
|
|
199
|
+
heading inside it. The sections after it no longer count it: in a chapter
|
|
200
|
+
that opens with one, § 1.2.2 becomes § 1.2.1. Float, check and example
|
|
201
|
+
numbers do not change.
|
|
202
|
+
|
|
203
|
+
- `[[sec-…]]` references print from the manifest and need no edit. A
|
|
204
|
+
reference to the meta section itself now prints its title in quotes
|
|
205
|
+
("What this chapter uses"), since the section has no number.
|
|
206
|
+
- Prose, captions and tests that type a section number, and number-form
|
|
207
|
+
fragments (`#sec-1.2.2`) past the meta section, now point at a different
|
|
208
|
+
section. Cite the section by key, or update the number.
|
|
209
|
+
- If the section should keep its number, drop the `=meta` (a plain `[card]`
|
|
210
|
+
accent card is numbered) or make it an aside (`:::note[Title]`).
|
|
211
|
+
|
|
212
|
+
Record the renumbering in `content/CHANGELOG.md` (step 13), because readers
|
|
213
|
+
see new numbers.
|
|
214
|
+
|
|
215
|
+
### 8. Only if the course has its own `Fold` component or a `figures-and-tables` page
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
rg -n '<Fold\b|import Fold\b' content src
|
|
219
|
+
ls content/docs/figures-and-tables.* 2>/dev/null
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
- **`<Fold>` is now an engine name.** A hit that imports
|
|
223
|
+
`explico/components/fold/Fold.astro` is the engine's own component; any
|
|
224
|
+
other `Fold` is the course's. The manifest reads every `<Fold>` in a
|
|
225
|
+
lesson as the engine's, whatever it is imported from. The equations and
|
|
226
|
+
floats inside it are numbered in the lesson's sequence, and a `<Fold>` with
|
|
227
|
+
no `label` and no numbered float inside fails `fold-unnamed`. To keep the
|
|
228
|
+
old behaviour, import the course's own component under another name
|
|
229
|
+
(`import CourseFold from …`, `<CourseFold>`).
|
|
230
|
+
- **A top-level `content/docs/figures-and-tables.mdx`** (or `.md`) now adds
|
|
231
|
+
"Figures and tables" to the sidebar's Reference group. If the course
|
|
232
|
+
already has a page at that path for something else, rename it, or make it
|
|
233
|
+
the float index (step 12).
|
|
234
|
+
|
|
235
|
+
### 9. Only if your course CSS, browser tests or scripts reach into engine markup
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
rg -n 'float-caption__toggle|keyed-figure__details|diagram__details|float-compact|--float-toggle-|diagram-toolbar|diagram-(expand|shrink)-(button|icon)|data-diagram-(details|body|toolbar)|block-badge__icon|table-overflow-expand-btn|keyed-table__caption--paginated|data-panel-pin|citation-panel-pin|notation-popup-close|[0-9] questions|Link copied|Hidden here' src content tests
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
- **Figure and diagram.** Neither one compacts. `.float-caption__toggle`,
|
|
242
|
+
`.keyed-figure__details`, `.diagram__details`, `.float-compact`,
|
|
243
|
+
`.float-compact__summary` and the `--float-toggle-size`,
|
|
244
|
+
`--float-toggle-gutter` and `--float-toggle-room` tokens are gone. A
|
|
245
|
+
figure's picture is `.keyed-figure > .keyed-figure__body`. The caption line
|
|
246
|
+
can open with `b.float-caption__title` (the short caption) and end with a
|
|
247
|
+
`.float-tools` row of boxed `.float-tool` buttons. A `<Figure>`'s caption
|
|
248
|
+
line ends with `span.float-caption__state[data-figure-state]`, outside
|
|
249
|
+
`.float-caption__text`. Print shows a figure's picture and caption, never
|
|
250
|
+
a lab's tools, and never a "compacted" note.
|
|
251
|
+
- **A diagram's widen button** is now
|
|
252
|
+
`figcaption .float-tools > [data-diagram-expand]`, and shows only while the
|
|
253
|
+
graph is wider than the column. `.diagram-toolbar`, `.diagram-expand-button`,
|
|
254
|
+
`.diagram-expand-icon` and `.diagram-shrink-icon` are gone.
|
|
255
|
+
- **Table.** The widen button ↔ and the fold button sit together in the
|
|
256
|
+
caption line's `.float-tools`. The fold toggle reads ⌃ / ⌄ (it read ▴ / ▾),
|
|
257
|
+
keeps `.keyed-table__pagination-toggle`, and is no longer a
|
|
258
|
+
`.table-overflow-expand-btn`. `.keyed-table__caption--paginated` is gone.
|
|
259
|
+
The "… N more rows …" label is centred on the part of the table on screen.
|
|
260
|
+
- **Knowledge check and example set.** The icon is `.block-heading__icon`,
|
|
261
|
+
before `.block-heading__title` (it was `.block-badge__icon`, inside the
|
|
262
|
+
badge). The badge (`.block-badge`: the word and `.block-heading__number`)
|
|
263
|
+
sits in the card's top-right corner. A check's score is empty until the
|
|
264
|
+
first answer, then reads "2 of 3 correct" under the questions. The
|
|
265
|
+
"3 questions" line is gone.
|
|
266
|
+
- **Explanation cards** (notation, `[[key]]` terms, citations,
|
|
267
|
+
abbreviations, and equation, table, figure, diagram and section
|
|
268
|
+
references) are all clones of `HoverPanel.astro`'s `<template>`, run by one
|
|
269
|
+
card manager. The header row holds the grip `[data-card-grip]` ("Move
|
|
270
|
+
card"), Side `[data-card-side]`, Pin `[data-card-pin]` (`aria-pressed`) and
|
|
271
|
+
× `[data-card-close]`. A note line `[data-card-note]` sits under it. A
|
|
272
|
+
dragged card has `data-card-mode="moved"`. `[data-panel-pin]`,
|
|
273
|
+
`.citation-panel-pin` and `.notation-popup-close` are gone.
|
|
274
|
+
`.notation-popup[data-popup-key="…"]` still finds a notation card. For
|
|
275
|
+
behaviour tests:
|
|
276
|
+
- A click or tap on a trigger pins its card and never navigates. The
|
|
277
|
+
card's "Go to …" link navigates, and ends in ↑ / ↓ (same page), → (another
|
|
278
|
+
page) or ↗ (a citation's source); every one used to end in ↗. A reference
|
|
279
|
+
whose target is already fully on screen still highlights it and
|
|
280
|
+
navigates.
|
|
281
|
+
- A click inside a card never closes it. A hovered card no longer closes a
|
|
282
|
+
pinned one, and several cards can be open at once. Escape closes the
|
|
283
|
+
newest card first. A `[[key]]` term shows no browser tooltip.
|
|
284
|
+
- A page restores the cards a reader kept on it, from local storage. A
|
|
285
|
+
fresh browser context starts empty, but a test that pins a card and then
|
|
286
|
+
reloads or goes back sees the card again.
|
|
287
|
+
- **Copy link and "Hidden here".** The confirmation names what was copied:
|
|
288
|
+
"Link copied · Figure 2.1.1 · Projectile trajectory explorer", or a
|
|
289
|
+
section's, check's or example set's title. Where the browser has
|
|
290
|
+
`ClipboardItem`, a `text/html` link goes on the clipboard next to the URL. A
|
|
291
|
+
folded section's line names its floats first: "Hidden here: **Figure
|
|
292
|
+
2.1.1** Projectile trajectory explorer, 2 paragraphs". A heading's chain
|
|
293
|
+
icon has the title "Copy link" where a click copies.
|
|
294
|
+
- **Layout.** The header is 3rem tall at every width (`--sl-nav-height`), with
|
|
295
|
+
a 2rem search box. Check course header content sized for 3.5rem or 4rem.
|
|
296
|
+
Headings are smaller: `global.css` sets `--sl-text-h1`…`--sl-text-h5`, and
|
|
297
|
+
course CSS that sets them wins. The navigation and "On this page" rail
|
|
298
|
+
cover a card that reaches them. Accent and meta cards have less padding, a
|
|
299
|
+
lesson's first block adds no top margin, and Previous / Next stay side by
|
|
300
|
+
side down to a 26rem column. The notation panel's help text is inside the
|
|
301
|
+
panel. Re-record screenshots.
|
|
302
|
+
- **A figure's preview card** shows a still copy of its picture, a lab's
|
|
303
|
+
plot included (controls disabled, ids prefixed). A lab no longer needs
|
|
304
|
+
`previewable={false}`.
|
|
305
|
+
|
|
306
|
+
### 10. Only if course code imports engine internals
|
|
307
|
+
|
|
308
|
+
- `components/hover-panel.ts` (`createHoverPanel`, `claimActiveSurface`,
|
|
309
|
+
`releaseActiveSurface`), `components/popup-stack.ts` and
|
|
310
|
+
`components/disclosure/float-compaction.ts` are gone. A layer of the
|
|
311
|
+
course's own registers a `CardSource` with `registerCardSource`. An overlay
|
|
312
|
+
that must clear the hovered cards calls `closeTransientCards()`. Both come
|
|
313
|
+
from `explico/components/card-manager.ts`.
|
|
314
|
+
- `countHiddenContent` in `components/starlight/section-summary.ts` is gone.
|
|
315
|
+
Use `collectHiddenContent`, then `hiddenContentParts`.
|
|
316
|
+
- `PreferenceStore` gains an optional `remove(key)`. A course's own store
|
|
317
|
+
still fits the interface. Implement `remove` so that closing a page's last
|
|
318
|
+
card forgets the page.
|
|
319
|
+
|
|
320
|
+
### 11. Reader-side state
|
|
321
|
+
|
|
322
|
+
A figure's and a diagram's remembered compaction (`figure:<id>`,
|
|
323
|
+
`diagram:<id>`) is no longer read, so a returning reader sees every figure
|
|
324
|
+
and diagram open. The new keys are `figure-tools:<figure id>` (a lab's
|
|
325
|
+
tools), `section:fold-…` (a `<Fold>`), `explico:cards:<page path>` (the cards
|
|
326
|
+
kept on a page) and `explico:layout:keep-article-left`. You need to add them
|
|
327
|
+
only if the course clears preference keys by name.
|
|
328
|
+
|
|
329
|
+
### 12. Optional: features to adopt
|
|
330
|
+
|
|
331
|
+
- **`<Fold>`** (`explico/components/fold/Fold.astro`) lets a reader fold away
|
|
332
|
+
a stretch of the lesson where it stands, most often one figure, diagram or
|
|
333
|
+
table. It has no heading, number, marker or frame:
|
|
334
|
+
|
|
335
|
+
```mdx
|
|
336
|
+
import Fold from 'explico/components/fold/Fold.astro';
|
|
337
|
+
|
|
338
|
+
<Fold>
|
|
339
|
+
<Diagram id="launch-angle-dependency" short="Inputs to the launch-angle search" caption="…" />
|
|
340
|
+
</Fold>
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
The bar is the `label`, or else the numbers and short captions of the
|
|
344
|
+
numbered floats inside. A fold with neither fails `fold-unnamed`. A float
|
|
345
|
+
the bar names drops its own bold caption title inside the fold. The fold's
|
|
346
|
+
first state comes from `defaultOpen`, or else `disclosure.folds` (closed);
|
|
347
|
+
`rememberState={false}` keeps the default on every visit. The equations
|
|
348
|
+
and floats inside keep their numbers.
|
|
349
|
+
- **A lab's tools.** In a `<Figure>`, the default slot is the picture. Give the
|
|
350
|
+
controls island `slot="tools"`, or wrap the controls in
|
|
351
|
+
`<Fragment slot="tools">`. The tools render after the caption line in a
|
|
352
|
+
tray with a fold button. They start as `defaultOpen` says, or else as
|
|
353
|
+
`disclosure.figures` says, and they never print. The picture and the tools
|
|
354
|
+
are separate islands, so they share their values through the course's own
|
|
355
|
+
store (the playground's `content/labs/useStoredState.ts`). `global.css`
|
|
356
|
+
styles `.lab-tools`, `.lab-instruction` (the tools' first line, saying
|
|
357
|
+
what to do) and a `.lab-shell` in the tray. A figure without the slot
|
|
358
|
+
renders as before.
|
|
359
|
+
|
|
360
|
+
```mdx
|
|
361
|
+
<Figure id="launch-angle-explorer" short="Range vs. launch angle explorer" caption="…">
|
|
362
|
+
<LaunchAnglePlot client:visible />
|
|
363
|
+
<LaunchAngleTools slot="tools" client:visible />
|
|
364
|
+
</Figure>
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
- **The caption's live end.** `setFigureState(element, runs)` from
|
|
368
|
+
`explico/components/figure/figure-state` writes the case the plot shows
|
|
369
|
+
at the end of the caption line. `element` is any element of the lab's
|
|
370
|
+
inside the figure. `runs` holds strings, `{ text, italic: true }` and
|
|
371
|
+
`{ sub }` items, never HTML:
|
|
372
|
+
`setFigureState(host, ['Shown for ', { text: 'v', italic: true }, { sub: '0' }, ' = 20 m/s'])`.
|
|
373
|
+
The clause prints with the caption.
|
|
374
|
+
- **Drop `previewable={false}`** from labs. The preview card now copies the
|
|
375
|
+
plot as drawn, and falls back to the caption and number when the plot is
|
|
376
|
+
not drawn yet.
|
|
377
|
+
- **The "Figures and tables" page** is LaTeX's `\listoffigures` and
|
|
378
|
+
`\listoftables` in one. Create `content/docs/figures-and-tables.mdx`:
|
|
379
|
+
|
|
380
|
+
```mdx
|
|
381
|
+
---
|
|
382
|
+
title: Figures and tables
|
|
383
|
+
description: Every numbered figure, table and diagram of the course, by part and chapter.
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
import FloatIndex from 'explico/components/FloatIndex.astro';
|
|
387
|
+
|
|
388
|
+
<FloatIndex />
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
It lists every numbered figure, table and diagram that has an `id`. A
|
|
392
|
+
diagram drawn by a wrapper component is listed when the lesson imports the
|
|
393
|
+
wrapper as `Diagram` and passes it `id`, `short` and `caption`
|
|
394
|
+
(`<Diagram id="…" short="…" caption="…" />`). That is also how the diagram
|
|
395
|
+
gets a number and a `[[dia-…]]` key.
|
|
396
|
+
- **Cards beside the article, dragged cards and remembered cards** need no
|
|
397
|
+
wiring.
|
|
398
|
+
|
|
399
|
+
### 13. Record the content changes (rules C1–C3)
|
|
400
|
+
|
|
401
|
+
Steps 2, 6, 7 and 12 edit `content/`. A settings edit is a content change
|
|
402
|
+
too. Add bullets under `## [Unreleased]` in `content/CHANGELOG.md` (rule C1):
|
|
403
|
+
the dropped `disclosure.diagrams`, new and rewritten captions, renumbered
|
|
404
|
+
sections, and new folds or pages. Bump `about.version` per rule C2 when you
|
|
405
|
+
release, and keep it equal to the newest heading (rule C3).
|
|
406
|
+
|
|
407
|
+
### 14. Fixes that need no action
|
|
408
|
+
|
|
409
|
+
A section, memo or fold that the browser opens itself, for find-in-page or
|
|
410
|
+
a linked fragment, now opens properly and stays open. A reference into a
|
|
411
|
+
closed memo or folded section opens its preview card and marks the fold's
|
|
412
|
+
bar. A figure's preview card shows an SVG sized only by its `viewBox`. A
|
|
413
|
+
touch screen no longer draws a badge icon over its word. A worked example's
|
|
414
|
+
closing display equation loses its stray bottom margin.
|
|
415
|
+
|
|
416
|
+
### 15. Verify
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
pnpm validate:content # run twice: the first run regenerates build/resolution/*
|
|
420
|
+
pnpm content rules # rule S9 is on the list now
|
|
421
|
+
pnpm content warnings
|
|
422
|
+
pnpm content check --changed
|
|
423
|
+
astro check
|
|
424
|
+
astro build
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Then run the course's browser tests, if it has any, and update the selectors
|
|
428
|
+
and texts from step 9. A course with its own gate script that runs these
|
|
429
|
+
stages (explico's is `scripts/agent/verify`) runs that instead.
|
|
430
|
+
|
|
431
|
+
## 0.9.0 → 0.10.0
|
|
432
|
+
|
|
433
|
+
**Course changes are required.** This release carries four lines of work: the
|
|
434
|
+
rule catalog (per-rule settings and switches, waivers, the rules-in-effect
|
|
435
|
+
page, a course's own rules), the rule restructuring (six rules folded into
|
|
436
|
+
four), accents and styled letters as symbols of their own, and titles and
|
|
437
|
+
containers (outline numbering, one caption pair per float, one collapse
|
|
438
|
+
model, heading discipline, kind badges). Several props are removed with no
|
|
439
|
+
alias period, and several rules now fail the build where they did not.
|
|
440
|
+
|
|
441
|
+
Work in this order: steps 1–6 fix the wiring, so that `pnpm validate:content`
|
|
442
|
+
runs and reports; steps 7–13 clear what it reports; steps 14–16 are
|
|
443
|
+
conditional or optional; step 17 is the check. Where a diagnostic code leads
|
|
444
|
+
to a step, the step names it. The manifest schema moves from v16 to v23 in
|
|
445
|
+
seven bumps (step 6).
|
|
446
|
+
|
|
447
|
+
### 1. Update the dependency
|
|
448
|
+
|
|
449
|
+
```bash
|
|
450
|
+
pnpm add -D explico@0.10.0
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
0.10.0 was never published to npm. Coming from npm's 0.8.0, install 0.11.0
|
|
454
|
+
instead, and read the "Coming from 0.8.0" note of "0.10.0 → 0.11.0" first.
|
|
455
|
+
|
|
456
|
+
### 2. `astro.config.mjs`
|
|
457
|
+
|
|
458
|
+
Make these edits; the result below shows all of them together.
|
|
459
|
+
|
|
460
|
+
1. **Add `remarkAsides` last in `markdown.remarkPlugins`.** Starlight turns
|
|
461
|
+
`:::note` / `:::tip` / `:::caution` / `:::danger` into asides only under its
|
|
462
|
+
own `src/content/docs/`, so in a course's `content/docs/` they rendered as a
|
|
463
|
+
bare `<div>`. `remarkAsides` hands each one to Starlight's `<Aside>`. No
|
|
464
|
+
check fails without it; the asides just stay unstyled. Do **not** add
|
|
465
|
+
`content/docs/` to Starlight's `markdown.processedDirs` instead: every
|
|
466
|
+
heading would get two anchors.
|
|
467
|
+
2. **Drop the `disclosureDefaults` mapping.** `CourseConfig.disclosureDefaults`
|
|
468
|
+
is gone (step 3). If the file builds a `resolvedCourseConfig = { ...courseConfig,
|
|
469
|
+
disclosureDefaults: { notation, references } }`, delete it and pass
|
|
470
|
+
`courseConfig` itself to both `loadManifest` and `explicoContentRefresh`.
|
|
471
|
+
3. **Read the heading and References defaults from `courseConfig.disclosure`.**
|
|
472
|
+
`rehypeHeadingAnchors` takes `{ defaultCollapsible: courseConfig.disclosure }`
|
|
473
|
+
(it reads `sections` and `subsections`), and `remarkCitation` takes
|
|
474
|
+
`defaultOpen: courseConfig.disclosure?.references?.defaultOpen === true`.
|
|
475
|
+
A local `defaultCollapsible` object moves into the `disclosure` block of
|
|
476
|
+
step 3.
|
|
477
|
+
4. **Wire `LayoutPageTitle.astro` as Starlight's `PageTitle` override.** It puts
|
|
478
|
+
the part's name, linked, above every chapter title. Optional, but it is the
|
|
479
|
+
one route to a part page (step 15) that does not depend on the sidebar.
|
|
480
|
+
5. **Check that `PageSidebar` is `LayoutPageSidebar.astro`.** "On this page"
|
|
481
|
+
lists knowledge checks and worked-example sets only through it.
|
|
482
|
+
6. **Only for a course deployed under a subpath** (an Astro `base`, such as a
|
|
483
|
+
GitHub Pages project site): pass `base` to `createRemarkNotationOptions` and
|
|
484
|
+
to `remarkAbbreviations`. Without it, the links these plugins write (a
|
|
485
|
+
symbol's glossary card, a cross-lesson reference, an abbreviation) are
|
|
486
|
+
root-relative and 404.
|
|
487
|
+
|
|
488
|
+
```js
|
|
489
|
+
import remarkAsides from 'explico/reference/remark-asides.mjs';
|
|
490
|
+
import rehypeHeadingAnchors from 'explico/reference/rehype-heading-anchors.mjs';
|
|
491
|
+
import { courseConfig } from './content/course.config.ts';
|
|
492
|
+
|
|
493
|
+
const disclosure = courseConfig.disclosure ?? {};
|
|
494
|
+
const manifest = await loadManifest(courseConfig);
|
|
495
|
+
|
|
496
|
+
// … integrations:
|
|
497
|
+
explicoContentRefresh(courseConfig, manifest),
|
|
498
|
+
starlight({
|
|
499
|
+
// …
|
|
500
|
+
components: {
|
|
501
|
+
Footer: 'explico/components/starlight/LessonFooter.astro',
|
|
502
|
+
PageSidebar: 'explico/components/starlight/LayoutPageSidebar.astro',
|
|
503
|
+
PageTitle: 'explico/components/starlight/LayoutPageTitle.astro',
|
|
504
|
+
// … Header, Sidebar, SocialIcons as before
|
|
505
|
+
},
|
|
506
|
+
}),
|
|
507
|
+
|
|
508
|
+
// … markdown.remarkPlugins:
|
|
509
|
+
[remarkNotation, createRemarkNotationOptions(manifest, { strict: true, base })],
|
|
510
|
+
[remarkCitation, {
|
|
511
|
+
sources: manifest.sources,
|
|
512
|
+
defaultOpen: disclosure.references?.defaultOpen === true,
|
|
513
|
+
}],
|
|
514
|
+
[remarkAbbreviations, { abbreviations: manifest.abbreviations, base }],
|
|
515
|
+
remarkAsides, // last
|
|
516
|
+
|
|
517
|
+
// … markdown.rehypePlugins:
|
|
518
|
+
[rehypeHeadingAnchors, { defaultCollapsible: disclosure }],
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
**Only if your course overrides `Footer` with its own component** instead of
|
|
522
|
+
`LessonFooter.astro`: read the notation panel's first state from
|
|
523
|
+
`manifest.disclosure.notation.defaultOpen` (it was
|
|
524
|
+
`manifest.disclosureDefaults.notation`), pass `KeyedFloatEnhancer` its new
|
|
525
|
+
`aliases` prop (`manifest.numbering.aliases`, step 11) and `NotationLayer` its
|
|
526
|
+
new `suspended` prop (the page's `notation.suspend`, step 10), as
|
|
527
|
+
`LessonFooter.astro` does.
|
|
528
|
+
|
|
529
|
+
### 3. `CourseConfig` (`content/course.config.ts`)
|
|
530
|
+
|
|
531
|
+
1. **`disclosureDefaults` → `disclosure`.** Every collapse default is now one
|
|
532
|
+
block, in the shape of the course settings' `disclosure` block. Move the
|
|
533
|
+
old `disclosureDefaults.notation` / `.references` booleans and the
|
|
534
|
+
`sections` / `subsections` objects from `astro.config.mjs` into it. Every
|
|
535
|
+
key is optional; the values below are the defaults, which match what each
|
|
536
|
+
kind had hardcoded before:
|
|
537
|
+
|
|
538
|
+
```ts
|
|
539
|
+
disclosure: {
|
|
540
|
+
sections: { collapsible: false, defaultOpen: true }, // ## headings
|
|
541
|
+
subsections: { collapsible: false, defaultOpen: true }, // ### and deeper
|
|
542
|
+
notation: { defaultOpen: false }, // was disclosureDefaults.notation
|
|
543
|
+
references: { defaultOpen: false }, // was disclosureDefaults.references
|
|
544
|
+
knowledgeChecks: { collapsible: true, defaultOpen: true }, // new
|
|
545
|
+
memos: { defaultOpen: false }, // new
|
|
546
|
+
figures: { defaultOpen: true }, // new
|
|
547
|
+
diagrams: { defaultOpen: true }, // new
|
|
548
|
+
workedExamples: { defaultOpen: false }, // new
|
|
549
|
+
tables: { truncateAfter: 6 }, // new: rows shown, half from each end
|
|
550
|
+
},
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
If the course keeps its settings in a JSON file and spreads it into
|
|
554
|
+
`CourseConfig`, stop splitting `disclosure` off: pass the block through as
|
|
555
|
+
it is. A course that calls `normalizeDisclosureDefaults` switches to
|
|
556
|
+
`normalizeDisclosure` (with `DISCLOSURE_DEFAULTS`); both are exported from
|
|
557
|
+
`explico/compiler/course-config`.
|
|
558
|
+
2. **Move the deprecated top-level blocks into `rules`.** `operators`,
|
|
559
|
+
`romanLabels` and `abbreviations` still work with a `config-deprecated-key`
|
|
560
|
+
warning; move each `{ allow, deny }` block unchanged to `rules.N8`,
|
|
561
|
+
`rules.N10` and `rules.N14` (rule N8, rule N10, rule N14). Setting both
|
|
562
|
+
the old key and its replacement is an error. The old keys go away in a later
|
|
563
|
+
MINOR.
|
|
564
|
+
3. **Only if you took `partPages` from `main` before this release:** it is
|
|
565
|
+
`rules.S2` now (`bridgeMinWords`, `bridgeMaxWords`, `scopeMinWords`,
|
|
566
|
+
`scopeMaxWords`), with no alias.
|
|
567
|
+
4. **Optional new fields**, each with the default that applies when it is left
|
|
568
|
+
out:
|
|
569
|
+
- `numbering`: `{ sections: { show: true, depth: 4 }, floats: "chapter",
|
|
570
|
+
aliases: true }` (step 11).
|
|
571
|
+
- `blockLabels`: `"icon-word"`, or `"icon"` for a knowledge check's and an
|
|
572
|
+
example set's badge without its word (the word stays for a screen
|
|
573
|
+
reader).
|
|
574
|
+
- `rules`: per-rule switches and settings (step 12).
|
|
575
|
+
- `courseRules`: the course's own `X` rules (step 15).
|
|
576
|
+
- `CoursePart.overviewLabel`: renames a part's `Overview` sidebar row.
|
|
577
|
+
|
|
578
|
+
### 4. Course settings schema (only if your course publishes one)
|
|
579
|
+
|
|
580
|
+
A course that describes its settings in a JSON Schema (the playground's
|
|
581
|
+
`course.settings.schema.json`) points two properties at the schemas
|
|
582
|
+
`pnpm build` now ships, so the rule blocks never need a copy:
|
|
583
|
+
|
|
584
|
+
```json
|
|
585
|
+
"rules": { "$ref": "../node_modules/explico/dist/rules/rules.schema.json" },
|
|
586
|
+
"courseRules": { "$ref": "../node_modules/explico/dist/rules/course-rules.schema.json" }
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
Add `numbering`, `blockLabels`, and the new `disclosure` keys
|
|
590
|
+
(`knowledgeChecks`, `memos`, `figures`, `diagrams`, `workedExamples`,
|
|
591
|
+
`tables.truncateAfter`) with the defaults in step 3; the playground's
|
|
592
|
+
[`course.settings.schema.json`](https://github.com/danieltuzes/explico/blob/v0.10.0/playground/content/course.settings.schema.json)
|
|
593
|
+
has each with a title and a description. If you use explico's settings form
|
|
594
|
+
editor (`tools/vscode-settings-editor/` in the explico repository), reinstall
|
|
595
|
+
it from a v0.10.0 checkout (`node tools/vscode-settings-editor/install.mjs`):
|
|
596
|
+
an older build shows `rules` and `courseRules` as text fields reading
|
|
597
|
+
`[object Object]`.
|
|
598
|
+
|
|
599
|
+
### 5. Course scripts
|
|
600
|
+
|
|
601
|
+
1. **`scripts/compile-manifest.ts`** — three new diagnostics groups, and the
|
|
602
|
+
rules-in-effect page. Without `examples` in the group lists, an `ex-…`
|
|
603
|
+
error does not fail `validate:content` (the page build still fails on it).
|
|
604
|
+
|
|
605
|
+
```ts
|
|
606
|
+
import { createRunLog, diagnosticLine } from 'explico/compiler/logging';
|
|
607
|
+
import { writeRulesInEffect } from 'explico/rules/in-effect';
|
|
608
|
+
|
|
609
|
+
const { /* … */ checks, examples, knowledge, rawFloats, config, waivers } =
|
|
610
|
+
manifest.diagnostics;
|
|
611
|
+
|
|
612
|
+
// Add ['examples', examples] to BOTH the warnings loop and the errors loop
|
|
613
|
+
// over [['equations', equations], …, ['checks', checks], …].
|
|
614
|
+
|
|
615
|
+
// The course settings themselves: a deprecated block, a retired rule.
|
|
616
|
+
for (const warning of config) {
|
|
617
|
+
console.warn(log.warning('config', `[${warning.code}] ${warning.message}`));
|
|
618
|
+
}
|
|
619
|
+
// Per-place waivers: a stale one warns; a malformed or invalid one fails.
|
|
620
|
+
for (const warning of waivers.filter((d) => d.severity === 'warning')) {
|
|
621
|
+
console.warn(log.warning('waivers', diagnosticLine(warning)));
|
|
622
|
+
}
|
|
623
|
+
// … and next to the other failures:
|
|
624
|
+
for (const issue of waivers.filter((d) => d.severity === 'error')) {
|
|
625
|
+
fail('waivers', diagnosticLine(issue));
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Optional: format math findings with the owning rule's ID,
|
|
629
|
+
// `[N9 prose-notation] file:line: …`.
|
|
630
|
+
const formatMathIssue = (issue: (typeof math)[number]) => diagnosticLine(issue);
|
|
631
|
+
|
|
632
|
+
// The page an agent reads before drafting (step 12).
|
|
633
|
+
writeRulesInEffect(manifest);
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
2. **`scripts/content.ts`** — add the `rules` verb: `contentRules(manifest,
|
|
637
|
+
parseRulesFilter({ element, enforcement }))` from `explico/compiler/cli`,
|
|
638
|
+
taking `--element <e>[,<e>]`, `--enforcement script|partial|guide|locked`
|
|
639
|
+
and `--json`. `content status` can print the new `keyedExamples` count.
|
|
640
|
+
3. **`.gitignore`** — `build/rules-in-effect.md` is regenerated on every run.
|
|
641
|
+
Ignore it unless `build/` is ignored already.
|
|
642
|
+
4. **Tools that read `content … --json`.** Each diagnostic now carries its
|
|
643
|
+
owner as `rule`. A math finding's `code` is `math:<code>` for every finding
|
|
644
|
+
(`math:prose-notation`, `math:unresolved-glyph`, …), where it used to be
|
|
645
|
+
`math:prose` or `math:structure` for code-less ones.
|
|
646
|
+
`MathGateDiagnostic.code` is required in the type.
|
|
647
|
+
5. **Code that imports engine internals.** `RuleEntry.retired` is gone
|
|
648
|
+
(`retiredRules()` / `retiredRule(id)` in `explico/rules/catalog`);
|
|
649
|
+
`proseOnly` takes `{ keepMath }`; `gateProseNotation` /
|
|
650
|
+
`gateProseNotationInAssessments` take `{ allowSpelledUnits }`;
|
|
651
|
+
`resolveMathGlyphs` takes `{ suspended }` as a third argument, and an
|
|
652
|
+
`unresolved` item may carry `suspended` or `font`. A lab island imports
|
|
653
|
+
`slotPlaceholder` / `RenderedLabMath` from `explico/reference/lab-math-slot`
|
|
654
|
+
(`render-lab-math` still re-exports both, but pulls the server-only KaTeX
|
|
655
|
+
chain into the browser graph and makes Vite warn about `node:fs`).
|
|
656
|
+
|
|
657
|
+
### 6. The manifest schema is now v23
|
|
658
|
+
|
|
659
|
+
It was v16 in 0.9.0. `pnpm validate:content` rewrites `build/manifest.json`,
|
|
660
|
+
so this step is only for code that reads the manifest itself:
|
|
661
|
+
|
|
662
|
+
- **v17** (additive): `parts` — every part with its chapters in reading order
|
|
663
|
+
and its overview page; `sidebar[].items` is one mixed list of lesson slugs
|
|
664
|
+
and `{ label, link, attrs? }` entries (`SidebarItem`), and `SidebarGroup` is
|
|
665
|
+
one interface instead of a union; `lessons[].studyMinutes`,
|
|
666
|
+
`parts[].studyMinutes`.
|
|
667
|
+
- **v18** (additive): `rules` (`disabled`, each rule's effective settings);
|
|
668
|
+
`diagnostics.config`; `diagnostics.waivers`; every math-gate finding carries
|
|
669
|
+
a `code`.
|
|
670
|
+
- **v19** (additive): `rules.course`, the course's own rules;
|
|
671
|
+
`MathGateDiagnostic.context` gains `'course'`.
|
|
672
|
+
- **v20**: `numbering`; `lessons[].headings` (`slug`, `text`, `level`,
|
|
673
|
+
`number?`); `lessons[].numbering.prefix`. Under the default chapter scope,
|
|
674
|
+
the per-kind counts in `lessons[].numbering`, which used to carry a part's
|
|
675
|
+
running total, are all 0.
|
|
676
|
+
- **v21**: `lessons[].equations` / `.tables` / `.figures` / `.diagrams` and the
|
|
677
|
+
kinds' `labels` carry `short` and, for a JSX float, `caption`
|
|
678
|
+
(`ManifestLessonFloat`).
|
|
679
|
+
- **v22**: `disclosure` (every default applied) replaces
|
|
680
|
+
`disclosureDefaults`.
|
|
681
|
+
- **v23**: `examples`, `lessons[].examples`, `lessons[].numbering.examples`,
|
|
682
|
+
`diagnostics.examples`; `lessons[].knowledgeChecks[].title`;
|
|
683
|
+
`lessons[].titledBlocks`; `blockLabels`.
|
|
684
|
+
|
|
685
|
+
### 7. Rename the removed float props (the build fails until you do)
|
|
686
|
+
|
|
687
|
+
Every float is named by one caption pair: a long `caption` and an optional
|
|
688
|
+
`short` caption, LaTeX's `\caption[short]{long}`. The other name props are
|
|
689
|
+
removed outright, and each fails with the edit to make. Find them:
|
|
690
|
+
|
|
691
|
+
```bash
|
|
692
|
+
rg -n -U '<(Figure|Diagram|Memo|CompactExamples)\b[^>]*\b(title|label|description|summary)=' content src
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
1. `<Figure title="X" caption="Y">` → `<Figure short="X" caption="Y">`, or
|
|
696
|
+
drop `title` when X only repeats the caption (`fig-removed-prop`).
|
|
697
|
+
2. `<Diagram label="X">` → `<Diagram caption="X">`, plus `short` for a long
|
|
698
|
+
caption; `<Diagram title>` fails too (`dia-removed-prop`). Check wrapper
|
|
699
|
+
`.astro` components as well: the manifest scan cannot see inside them, but
|
|
700
|
+
the component throws when it renders.
|
|
701
|
+
3. `<Memo title="X" description="Y">` → `<Memo short="X" caption="…">`.
|
|
702
|
+
`caption` is required and is now the memo's bar, so write it as bar text;
|
|
703
|
+
`short` is optional (the marker's tooltip). `remarkMemo` fails the old props.
|
|
704
|
+
4. `<CompactExamples summary="X">` → `<CompactExamples id="…" short="X">`.
|
|
705
|
+
Both are required now (`ex-missing-prop`; `summary` is `ex-removed-prop`):
|
|
706
|
+
`id` is lowercase kebab-case and anchors the set as `#ex-‹id›`; `short` names
|
|
707
|
+
the set's topic ("Speeding up and braking"), since the engine draws the
|
|
708
|
+
"Example" badge and the number before it. `short` no longer defaults to
|
|
709
|
+
"Worked examples", and `hint` has no default.
|
|
710
|
+
|
|
711
|
+
Rule S1 now measures the `short` caption (of a `Figure`, `Diagram`, `Table`,
|
|
712
|
+
`Memo` and `CompactExamples`), a display equation's `\caption{…}` and a
|
|
713
|
+
`ShortNote`'s `title`, and never a long `caption`; a heading's `[collapsed]`
|
|
714
|
+
/ `[card]` markers no longer count toward it. A `Figure title` that passed rule
|
|
715
|
+
S1 passes the same way as `short`.
|
|
716
|
+
|
|
717
|
+
### 8. Assessment titles and labs
|
|
718
|
+
|
|
719
|
+
1. **Assessment titles name the topic alone.** A knowledge check's heading is
|
|
720
|
+
now the engine's badge ("Knowledge check"), its number, then the assessment
|
|
721
|
+
file's `title`, so a title that repeats the kind reads twice ("Knowledge
|
|
722
|
+
check 1.1.1 Velocity check"). In each `content/assessments/*.json`, drop
|
|
723
|
+
"check" / "Knowledge check" from `title`.
|
|
724
|
+
2. **A lab carries no title or caption of its own**; the `<Figure>` around it
|
|
725
|
+
names the whole. In a lab inside a `<Figure>`, delete its own heading and
|
|
726
|
+
the `aria-labelledby` that names it, and turn an inner
|
|
727
|
+
`<figure><figcaption>` into a plain element, moving the sentence into the
|
|
728
|
+
`<Figure caption>`. The engine's `.lab-chart-figure` styles are gone; draw
|
|
729
|
+
the chart in a plain `.lab-chart`.
|
|
730
|
+
3. **Rule V3 is narrowed.** It keeps the hydrated island, the `labMathScope` /
|
|
731
|
+
`renderLabMath` / `\slot{}` seam and labelled controls, and no longer asks
|
|
732
|
+
for an accessible name or description (`ariaLabel` / `ariaDescription` /
|
|
733
|
+
`ariaHidden`) or a `<details>` text alternative: the `<Figure>` caption is
|
|
734
|
+
the name. Nothing in a build changes; keep or drop what you wrote for the
|
|
735
|
+
old rule V3.
|
|
736
|
+
|
|
737
|
+
### 9. Headings: rule S6 and rule S7 (errors)
|
|
738
|
+
|
|
739
|
+
Both read a lesson's outline, the same top-level headings the section numbers
|
|
740
|
+
count. A heading inside a component and a memo's bar are not in it; a
|
|
741
|
+
`<AssessmentSet />` and a `<CompactExamples>` are, as `##` headings.
|
|
742
|
+
|
|
743
|
+
- **Rule S6** (`heading-skip`): headings descend one level at a time. A lesson
|
|
744
|
+
body starts at `##` (the frontmatter `title` is the page's one `#`, so a `#`
|
|
745
|
+
in the body fails), and `##` → `####` fails; going back up is free. A `###`
|
|
746
|
+
→ example set → `####` is a skip too. Fix it by making the heading one level
|
|
747
|
+
deeper than the one before it.
|
|
748
|
+
- **Rule S7** (`heading-adjacent`): a heading is followed by body content,
|
|
749
|
+
never directly by another heading, and a check or an example set counts as a
|
|
750
|
+
heading. Write a sentence between the two, or delete a heading that only
|
|
751
|
+
announces the block under it (`## Check yourself` above `<AssessmentSet />`,
|
|
752
|
+
`## Try it` above `<CompactExamples>`).
|
|
753
|
+
|
|
754
|
+
Otherwise waive one place with `{/* explico-allow S6: reason */}` on the line
|
|
755
|
+
above the heading, or switch a rule off with `rules.S6.enabled: false` /
|
|
756
|
+
`rules.S7.enabled: false`. For parallel items deep in the outline,
|
|
757
|
+
`docs/authoring/structure.md` § Structure from the bottom up recommends run-in
|
|
758
|
+
labels or a description list instead of deeper headings.
|
|
759
|
+
|
|
760
|
+
### 10. Math and prose: what now fails or warns
|
|
761
|
+
|
|
762
|
+
Run `pnpm validate:content` and work through these by code.
|
|
763
|
+
|
|
764
|
+
1. **Rule N9, `spelled-unit` (error).** A unit written as a word after a
|
|
765
|
+
number, around `per`, or with `square` / `cubic` / `squared` / `cubed`
|
|
766
|
+
fails, in lesson bodies and assessment `prompt` / `explanation`: "a time
|
|
767
|
+
of 4 seconds" → `$4\ \text{s}$`, "30 degrees above the horizontal" →
|
|
768
|
+
`$30^{\circ}$`, "$x = 3$ meters" → `$x = 3\ \text{m}$`. The message gives
|
|
769
|
+
the math. A unit named on its own ("measured in meters") passes, and rule
|
|
770
|
+
N9's old carve-out for a spelled-out unit in flowing prose is gone. Rewrite
|
|
771
|
+
it, waive a defining sentence with `{/* explico-allow N9: reason */}`, or
|
|
772
|
+
list unit words the course keeps in `rules.N9.allow`.
|
|
773
|
+
2. **Rule N12, `math-trailing-punctuation` (error).** A `.`, `,`, `;` or `:` is
|
|
774
|
+
never the last visible thing in a `$…$` / `$$…$$` span, or in a row before
|
|
775
|
+
`\\`; move it out after the closing `$`. A trailing decimal point (`5.`) and
|
|
776
|
+
a typed `...` fail too; the decimal-point exception is gone. Dotted notation
|
|
777
|
+
abbreviations (`a.e.`, `i.i.d.`, …) pass; edit that list with
|
|
778
|
+
`rules.N12.allow` / `rules.N12.deny`, waive a place, or switch rule N12 off.
|
|
779
|
+
3. **Rule N4, `unresolved-glyph` (error): a font-styled letter is its own
|
|
780
|
+
symbol.** `\mathbf{x}`, `\boldsymbol{\beta}`, `\bm{x}`, `\mathcal{N}`,
|
|
781
|
+
`\mathscr{L}`, `\mathfrak{g}`, `\mathbb{E}`, `\mathsf{x}` and `\mathtt{x}`
|
|
782
|
+
no longer borrow the plain letter's card, and `\mathbf{e}` /
|
|
783
|
+
`\boldsymbol{\pi}` no longer pass as Euler's number or π. Give each its own
|
|
784
|
+
entry (`latex: \mathbf{x}`) or an `\explain{key}{\mathbf{x}}` wrap — in
|
|
785
|
+
lessons, notation formulas, assessments and labs alike. `\mathit` /
|
|
786
|
+
`\mathnormal` still share the plain letter's card, and `\mathbb{N,Z,R,C}`
|
|
787
|
+
stay reserved.
|
|
788
|
+
4. **Rule N22, `accent-explained` (warning): an accent or mark is an
|
|
789
|
+
operator.** A decoration (`\hat`, `\bar`, `\tilde`, `\dot`, `\vec`,
|
|
790
|
+
`\overline`, a superscript `'`, `^*`, `^\dagger`, …) needs one of: an entry
|
|
791
|
+
on `rules.N22.allow` (empty by default), an operator notation entry
|
|
792
|
+
(`latex: \hat{}`, `{}'`, `{}^{*}`), or a whole-form entry
|
|
793
|
+
(`latex: \hat{\beta}`). A page where a mark is not an operator declares it
|
|
794
|
+
in its frontmatter (`notation.suspend: [{ operator: "'", reason: … }]`);
|
|
795
|
+
every decorated form of it on that page then needs its own entry or a
|
|
796
|
+
whole-form `\explain`, or the build fails with
|
|
797
|
+
`suspended-operator-unresolved`. Two consequences for existing notation:
|
|
798
|
+
- A marked entry no longer lends its card to the bare letter: with only
|
|
799
|
+
`latex: b'` (or `\theta^{*}`), a bare `b` elsewhere on the page now needs
|
|
800
|
+
its own entry, or rule N4's gate fails with `unresolved-glyph`.
|
|
801
|
+
- A whole-form match now wraps the decoration too
|
|
802
|
+
(`\explain{k}{\hat{\beta}}`, not `\hat{\explain{k}{\beta}}`), and the wrap
|
|
803
|
+
for `\boldsymbol`, `\bm`, `\bold`, `\Bbb`, `\frak`, `\mathsf`, `\mathtt`
|
|
804
|
+
and `\mathnormal` lands around the command. Only snapshot tests of
|
|
805
|
+
rendered HTML notice.
|
|
806
|
+
5. **Rule N8 and rule N10 now read labelled display equations**
|
|
807
|
+
(`operator-explained`, `roman-label-explained`, both warnings). A
|
|
808
|
+
`\label{eq:…}` used to hide the whole equation from both scans, so new
|
|
809
|
+
findings may appear. Explain the operator or label, or list it under
|
|
810
|
+
`rules.N8.allow` / `rules.N10.allow`.
|
|
811
|
+
6. **Rule N5: hand-typed numbers are now wrong numbers.** Every float number
|
|
812
|
+
changed (step 11). Prose that types "Equation 2.4" instead of citing
|
|
813
|
+
`[[eq-…]]` now names the wrong equation; cite it by key.
|
|
814
|
+
7. `x^\prime` no longer fails as an unresolved `\prime`.
|
|
815
|
+
|
|
816
|
+
### 11. Numbering: every number a reader sees changed
|
|
817
|
+
|
|
818
|
+
1. **Float numbers are chapter-scoped.** A display equation, table, figure,
|
|
819
|
+
diagram, knowledge check and example set is numbered
|
|
820
|
+
`‹part›.‹chapter›.‹n›`, and each kind restarts in every chapter:
|
|
821
|
+
`Figure 2.1` is now `Figure 2.2.1`. `[[…]]` references need no edit, since
|
|
822
|
+
they print from the manifest. `numbering.floats: "part"` keeps the old
|
|
823
|
+
`‹part›.‹n›` scheme.
|
|
824
|
+
2. **The positional anchor of an unkeyed float changed** with its number
|
|
825
|
+
(`#eq-2-4` → `#eq-2-2-4`). Update links that point at one, or give the
|
|
826
|
+
float a key (`\label{eq:…}`, an `id`) so its anchor names its content.
|
|
827
|
+
3. **Top-level headings are numbered** `1.1.2`, down to `####` by default
|
|
828
|
+
(`numbering.sections.depth`, `2`–`6`), on a wide screen, in print, and on a
|
|
829
|
+
folded section's bar. `numbering.sections.show: false` hides them, and a
|
|
830
|
+
knowledge check's and example set's numbers with them. The number is
|
|
831
|
+
generated content: the heading's text and anchor do not change.
|
|
832
|
+
4. **A heading with inline math gets its anchor from its source**
|
|
833
|
+
(`## The range $R$` → `#the-range-r`), no longer from KaTeX's output.
|
|
834
|
+
Update links to such headings: `rg -n '^#{2,6} .*\$' content/docs`.
|
|
835
|
+
5. **`sec-` and `ex-` are reserved reference prefixes.** `[[sec-…]]` cites a
|
|
836
|
+
section and `[[ex-…]]` an example set. Rename a notation key that starts
|
|
837
|
+
with either and is cited as `[[sec-…]]` or `[[ex-…]]`.
|
|
838
|
+
6. **Number aliases** (`numbering.aliases`, on by default): a fragment a reader
|
|
839
|
+
types in number form (`#sec-1.1.2`, `#fig-2.2.1`, `#ex-1.1.1`) lands on the
|
|
840
|
+
element that shows that number. The site itself links and copies only
|
|
841
|
+
named anchors.
|
|
842
|
+
7. Update prose, captions and tests that quote a number, and record the
|
|
843
|
+
renumbering in `content/CHANGELOG.md` (rule C1): readers see new numbers.
|
|
844
|
+
|
|
845
|
+
### 12. Rules: retired IDs, settings, switches, waivers
|
|
846
|
+
|
|
847
|
+
1. **Retired rules.** Rule N1 (the normal distribution is `\mathcal{N}`), rule
|
|
848
|
+
N6 (probability is `\mathbb{P}`) and rule N7 (the differential is
|
|
849
|
+
`\mathrm{d}`) are now lines of **rule N2**, whose table is the setting
|
|
850
|
+
`rules.N2.reserved`: by default the four number systems, `\mathbb{P}`,
|
|
851
|
+
`\mathcal{N}(\mu, \sigma^2)` and `\mathrm{d}`, one
|
|
852
|
+
`"<latex> — <meaning>"` string each. Replace the list to state the course's
|
|
853
|
+
own conventions: drop the probability lines in a course without
|
|
854
|
+
probability, or write `\mathcal{N}(\mu, \sigma)` for one that parameterises
|
|
855
|
+
the normal by standard deviation. Rule N3 (write a multi-letter label as
|
|
856
|
+
`\mathrm{…}`) is folded into **rule N10**, now `partial`. Rule N16
|
|
857
|
+
(alternate delimiter shapes to show nesting) is folded into **rule N17**,
|
|
858
|
+
and **reversed**: a delimiter's shape carries its meaning, and the engine
|
|
859
|
+
sizes a nest. Content that alternated shapes still builds, but the rule no
|
|
860
|
+
longer asks for it, and a `[` inside a grouping nest reads as an interval
|
|
861
|
+
first. Rule C4 (a release moves `[Unreleased]` and bumps `about.version`
|
|
862
|
+
together) is folded into **rule C3**, now `partial`. A `rules.N1` /
|
|
863
|
+
`rules.N3` / `rules.N6` / `rules.N7` / `rules.N16` / `rules.C4` block warns
|
|
864
|
+
`config-retired-rule`, naming the successor: delete it (only rule N2 takes
|
|
865
|
+
settings). A waiver naming a retired ID is `waiver-invalid`; name the
|
|
866
|
+
successor. `docs/authoring/retired.md` lists every retired rule.
|
|
867
|
+
2. **Per-rule settings and switches: `rules`.** One block per rule ID, holding
|
|
868
|
+
only what differs from the defaults: rule S1's `maxLength` (65), rule
|
|
869
|
+
S2's `bridgeMinWords` / `bridgeMaxWords` / `scopeMinWords` /
|
|
870
|
+
`scopeMaxWords` (30 / 150), rule V5's `seeds` (10), rule V6's
|
|
871
|
+
`minLabels` (3), the `allow` / `deny` lists of rule N8, rule N10, rule
|
|
872
|
+
N12, rule N14 and rule N22, rule N9's `allow`, and rule N2's `reserved`.
|
|
873
|
+
With `rules.<ID>.enabled: false` a rule stops running and its diagnostics
|
|
874
|
+
are withheld. Switchable: N5, N8, N9, N10, N14, N17, N19, N20, N21, S1–S7, C3,
|
|
875
|
+
and every guide rule. The build fails on an unknown rule or key, a value
|
|
876
|
+
outside its spec, `enabled: false` on a locked rule (rule N4, rule N13,
|
|
877
|
+
rule N15), and `rules.X1` (course rules live in `courseRules`).
|
|
878
|
+
3. **Per-place waivers.** `{/* explico-allow <ID>[, <ID>]: <reason> */}` on
|
|
879
|
+
its own line waives the named rules for the next block. A malformed waiver,
|
|
880
|
+
or one naming a locked rule, an invariant or an unknown ID, is an error
|
|
881
|
+
(`waiver-malformed`, `waiver-invalid`); one that silenced nothing warns
|
|
882
|
+
(`waiver-unused`). Record the reason: it is what a reviewer reads.
|
|
883
|
+
4. **Read the rules in effect, not the rule set.** `pnpm validate:content`
|
|
884
|
+
writes `build/rules-in-effect.md`, and `pnpm content rules [--element …]
|
|
885
|
+
[--enforcement …]` prints it filtered: the rules this course has on, by
|
|
886
|
+
element, with codes and settings. An agent drafting for the course reads
|
|
887
|
+
that page; `docs/authoring/agents.md` now says so.
|
|
888
|
+
5. **Rules that only gained a name.** Rule S3 (`raw-table-markdown`,
|
|
889
|
+
`raw-table-html`), rule S4 (`diagram-unkeyed`, `diagram-nested`), rule S5
|
|
890
|
+
(`convention-single-definition`), rule N19 (`notation-units`,
|
|
891
|
+
`units-vocab`), rule N20 (`notation-source-locator`) and rule N21
|
|
892
|
+
(`gloss-name-shape`) name checks that already ran. Nothing new fires; the
|
|
893
|
+
console line now carries the rule, `[S3 raw-table-markdown] …`.
|
|
894
|
+
6. **New guide rules** — review-only, so nothing fails; switch one off with
|
|
895
|
+
`rules.<ID>.enabled: false` if it does not fit the course:
|
|
896
|
+
- rule N18: a multi-step derivation is one `aligned` chain, `&` before each
|
|
897
|
+
relation, a justification after `\qquad` as `\text{…}`.
|
|
898
|
+
- rule V6: every quantitative axis shows at least three labelled values.
|
|
899
|
+
- rule P2 (one canonical term per concept), rule P3 (one meaning per term),
|
|
900
|
+
rule P4 (the established term, defined where first needed), rule P5
|
|
901
|
+
(literal main text; analogies in an aside), rule P6 (industry jargon only
|
|
902
|
+
in an "Industry jargon" aside), rule P7 (one claim per sentence, links
|
|
903
|
+
stated), rule P8 (relation words match the math), rule P9 (a display
|
|
904
|
+
equation's lead-in says what it gives and where it comes from).
|
|
905
|
+
- rule S8: prefer `<Memo>` over a Starlight aside when the content needs an
|
|
906
|
+
anchor, a caption or collapsing.
|
|
907
|
+
7. **Rule S2 applies only to a part page** (step 15). A course without
|
|
908
|
+
`content/docs/<dir>/index.mdx` is unaffected. With one, each needs a
|
|
909
|
+
`<PartScope>` paragraph and, for every part after the first, a
|
|
910
|
+
`<PartBridge>` paragraph before it, each within the `rules.S2` word range
|
|
911
|
+
(`part-page-paragraph`).
|
|
912
|
+
|
|
913
|
+
### 13. Record the content changes (rules C1–C3)
|
|
914
|
+
|
|
915
|
+
The steps above edit `content/`. Add bullets under `## [Unreleased]` in
|
|
916
|
+
`content/CHANGELOG.md` (rule C1): renumbered floats and sections, retitled
|
|
917
|
+
checks and example sets, renamed sections whose anchors changed. Bump
|
|
918
|
+
`about.version` per rule C2 when you release (`pnpm release:content` in the
|
|
919
|
+
playground's shape), keeping it equal to the newest heading (rule C3).
|
|
920
|
+
|
|
921
|
+
### 14. Only if your course CSS, browser tests or scripts reach into engine markup
|
|
922
|
+
|
|
923
|
+
```bash
|
|
924
|
+
rg -n 'keyed-figure__(titlebar|summary|title-anchor)|diagram__(titlebar|summary|title-anchor)|lab-chart-figure|memo-block__summary|memo-preview__description|data-memo-(self|anchor)-link|compact-examples__(summary|title)|details\.compact-examples|assessment-heading-number' src content tests
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
- **Figure and diagram.** The number moved into a caption line below the body:
|
|
928
|
+
`figcaption.float-caption` with `.float-caption__toggle`,
|
|
929
|
+
`.float-caption__number`, `.float-caption__anchor` and
|
|
930
|
+
`.float-caption__text`. `.keyed-figure__titlebar`, `.keyed-figure__summary`,
|
|
931
|
+
`.keyed-figure__title-anchor`, `.diagram__titlebar`, `.diagram__summary` and
|
|
932
|
+
`.diagram__title-anchor` are gone; `.diagram__number` is a link. A compacted
|
|
933
|
+
float keeps the caption line and hides only its body. The `<details>` keeps a
|
|
934
|
+
native `<summary>` shown only under `(scripting: none)`.
|
|
935
|
+
- **Table.** The caption line is the same `.float-caption` (caption size, a
|
|
936
|
+
chain icon after the number, no " — ").
|
|
937
|
+
- **Memo.** `.memo-block` is the frame; the `<details>`,
|
|
938
|
+
`.memo-block__summary`, `[data-memo-self-link]`, `[data-memo-anchor-link]`
|
|
939
|
+
and `.memo-preview__description` are gone. Its bar is an `<h6 role="none">`
|
|
940
|
+
with the `#memo-…` anchor, folded by `CollapsibleSections`. The marker is a
|
|
941
|
+
superscript italic letter (`a`, `b`, …), not `[1]`; `data-memo-number`
|
|
942
|
+
carries the letter.
|
|
943
|
+
- **Knowledge check.** The heading is `BlockHeading.astro`'s
|
|
944
|
+
`<h2 id="check-‹id›" class="block-heading">` (badge, number, title in
|
|
945
|
+
`.block-heading__title`), carrying `data-check-number`; its wrapper carries
|
|
946
|
+
`data-card="accent"`. `.assessment-heading-number` is gone, and
|
|
947
|
+
`.assessment-shell` draws no box.
|
|
948
|
+
- **Example set.** `details.compact-examples`, `.compact-examples__summary`
|
|
949
|
+
and `.compact-examples__title` are gone; `<compact-examples
|
|
950
|
+
class="compact-examples">` is the card, `#ex-‹id›` its heading.
|
|
951
|
+
- **Container tiers.** Every container is restyled from the tokens in
|
|
952
|
+
`explico/styles/surfaces.css` (`--ex-surface-*`, `--ex-edge-*`,
|
|
953
|
+
`--ex-depth-*`, `--ex-radius-*`; `.ex-tier-meta`, `.ex-tier-accent`,
|
|
954
|
+
`.ex-tier-aside`), which `global.css` imports — `customCss` needs no second
|
|
955
|
+
entry. A `<Figure>` and a `.lab-shell` lose their card; checks, example sets
|
|
956
|
+
and `[card]` sections are accent cards; the notation panel, part-page rail,
|
|
957
|
+
glossary entries, curriculum-map cards, About popover and a Starlight
|
|
958
|
+
`<Card>` are meta; a memo, an open `<ShortNote>` and Starlight asides are
|
|
959
|
+
asides. No container has a top rule. Override the tokens rather than the
|
|
960
|
+
old per-container rules.
|
|
961
|
+
- **Screenshots and layout assertions.** Printed and displayed numbers
|
|
962
|
+
(step 11); a folded section's "Hidden here: …" line and, on a narrow screen,
|
|
963
|
+
its in-line chevron and "(tap to expand)"; the chain icon's "Link copied ·
|
|
964
|
+
§ 1.1.2" confirmation; 0.25em more block padding on each display equation
|
|
965
|
+
(about 8px); the sidebar's leading part caret, filled hover rows, reading
|
|
966
|
+
progress, and `Overview` rows; print as shown (a closed disclosure prints
|
|
967
|
+
its title and a link, where print used to expand everything).
|
|
968
|
+
- **Reader state.** A memo's open state moved from `memo:‹id›` to
|
|
969
|
+
`section:memo-‹id›`, so a returning reader's choice resets once. An example
|
|
970
|
+
set remembers its state under `section:ex-‹id›` (new). A course that clears
|
|
971
|
+
preference keys by name adds both.
|
|
972
|
+
|
|
973
|
+
### 15. Optional: features to adopt
|
|
974
|
+
|
|
975
|
+
- **Captions.** `\caption{…}` inside a display equation's `$$…$$` (next to its
|
|
976
|
+
`\label`) gives it a short caption: the `[[eq-…]]` preview card's heading
|
|
977
|
+
and the copy tooltip ("Copy LaTeX — Range formula"). `short` on a
|
|
978
|
+
`<Table>`, `<Figure>` or `<Diagram>` heads its preview card.
|
|
979
|
+
- **References.** `[[sec-slug]]` prints `§ 1.1.2` with a preview card;
|
|
980
|
+
`[[ex-id]]` prints `Example 1.1.1`; `[[check-…]]` now previews the check.
|
|
981
|
+
`content context <lesson> --json` lists a lesson's `sections` and
|
|
982
|
+
`examples`, so a drafter need not derive a slug.
|
|
983
|
+
- **Cards and asides.** `[card]` / `[card=meta]` after a heading
|
|
984
|
+
(`### Explore the range [collapsed] [card]`) cards its whole section.
|
|
985
|
+
`:::note` / `:::tip` / `:::caution` / `:::danger` render as asides (step 2);
|
|
986
|
+
`{icon="heart"}` names another Starlight icon and `icon=""` drops it, on a
|
|
987
|
+
directive or an `<Aside>`.
|
|
988
|
+
- **Part pages.** `content/docs/<dir>/index.mdx` is a part's own page: render
|
|
989
|
+
it with `<PartOverview>` and state its argument with `<PartScope>` /
|
|
990
|
+
`<PartBridge>` (rule S2). `<CourseContents>` lists every part and chapter for
|
|
991
|
+
a landing page. `studyMinutes: 40` (or `[30, 40]`) in a lesson's frontmatter
|
|
992
|
+
feeds the per-part totals.
|
|
993
|
+
- **Disclosure per instance.** `defaultOpen` is new on `<Memo>` and
|
|
994
|
+
`<CompactExamples>`, and `rememberState` on `<CompactExamples>`.
|
|
995
|
+
- **Course rules.** `courseRules` in the settings is a list of the course's
|
|
996
|
+
own rules, `X1`…`X99` (the `X` area is never used by the engine), each
|
|
997
|
+
`{ id, title, summary?, elements?, enabled?, severity?, forbid?, unchecked?,
|
|
998
|
+
doc? }`. With `forbid` patterns a rule is enforced at its `severity`
|
|
999
|
+
(`error` or `warning`), and each finding's code is the rule's ID; without
|
|
1000
|
+
one it is a guide. A bad definition fails the build with the setting's path.
|
|
1001
|
+
See `docs/authoring/README.md` § Rules of your own.
|
|
1002
|
+
- **Accessibility** is the engine's job (`docs/authoring/README.md`
|
|
1003
|
+
§ Accessibility): nothing asks an author for an accessible name or a text
|
|
1004
|
+
alternative.
|
|
1005
|
+
|
|
1006
|
+
### 16. Fixes that need no action
|
|
1007
|
+
|
|
1008
|
+
Grey boxes get a background in the dark theme; an equation's copy button keeps
|
|
1009
|
+
its "Copy LaTeX" tooltip; a collapsed section's chevron is on screen on a
|
|
1010
|
+
phone; the copy-link icon shows on touch screens; labs hydrate under
|
|
1011
|
+
`astro dev` again; a printed `\sqrt` keeps its radical sign; `<Diagram>`
|
|
1012
|
+
formulas render in Safari and iOS, on screen and in print; display equations
|
|
1013
|
+
are no longer clipped at the bottom; pointing at the letter under an accent
|
|
1014
|
+
shows the letter's card.
|
|
1015
|
+
|
|
1016
|
+
### 17. Verify
|
|
1017
|
+
|
|
1018
|
+
```bash
|
|
1019
|
+
pnpm validate:content # run twice: the first run regenerates build/resolution/*
|
|
1020
|
+
pnpm content rules # the rules this course now has on; read before drafting
|
|
1021
|
+
pnpm content warnings # new warnings: rule N22, rule N8 / rule N10 in labelled equations
|
|
1022
|
+
pnpm content check --changed
|
|
1023
|
+
astro check
|
|
1024
|
+
astro build
|
|
1025
|
+
```
|
|
1026
|
+
|
|
1027
|
+
Then run the course's browser tests, if it has any, and re-record the numbers
|
|
1028
|
+
and selectors of step 11 and step 14. A course with a gate script of its own
|
|
1029
|
+
that runs these stages (explico's is `scripts/agent/verify`) runs that
|
|
1030
|
+
instead of the list above.
|
|
1031
|
+
|
|
1032
|
+
## 0.8.0 → 0.9.0
|
|
1033
|
+
|
|
1034
|
+
**No course changes are required** beyond the dependency bump, unless your
|
|
1035
|
+
course's own CSS reaches into the layout chrome (step 2). Everything in this
|
|
1036
|
+
release is engine-side UI: the panel collapse controls, reader-set panel
|
|
1037
|
+
widths, and the compact-chapter tooltip. No authoring rule, manifest field,
|
|
1038
|
+
CLI command, `CourseConfig` field, or Astro wiring moved, and the manifest
|
|
1039
|
+
schema version is unchanged.
|
|
1040
|
+
|
|
1041
|
+
### 1. Update the dependency
|
|
1042
|
+
|
|
1043
|
+
```bash
|
|
1044
|
+
pnpm add -D explico@0.9.0
|
|
1045
|
+
```
|
|
1046
|
+
|
|
1047
|
+
0.9.0 was never published to npm. Coming from npm's 0.8.0, install 0.11.0
|
|
1048
|
+
instead, and read the "Coming from 0.8.0" note of "0.10.0 → 0.11.0" first.
|
|
1049
|
+
|
|
1050
|
+
Or set `"explico": "0.9.0"` in `package.json` and run `pnpm install`. Nothing
|
|
1051
|
+
in `astro.config.mjs`, `content/course.config.ts`, `content/`, or your course
|
|
1052
|
+
scripts needs to change for this release.
|
|
1053
|
+
|
|
1054
|
+
### 2. Only if your course CSS targets the collapse control
|
|
1055
|
+
|
|
1056
|
+
Two names in the layout chrome changed. Check your own stylesheets and
|
|
1057
|
+
components:
|
|
1058
|
+
|
|
1059
|
+
```bash
|
|
1060
|
+
rg -n 'layout-edge-icon|--layout-edge-toggle-size' src content
|
|
1061
|
+
```
|
|
1062
|
+
|
|
1063
|
+
- `--layout-edge-toggle-size` no longer exists. It was one square; the control
|
|
1064
|
+
is now a rectangle, so set `--layout-edge-toggle-width` and
|
|
1065
|
+
`--layout-edge-toggle-height` instead.
|
|
1066
|
+
- `svg.layout-edge-icon` / `.layout-edge-icon-hide` / `.layout-edge-icon-restore`
|
|
1067
|
+
are now `span.layout-edge-glyph` / `.layout-edge-glyph-hide` /
|
|
1068
|
+
`.layout-edge-glyph-restore`.
|
|
1069
|
+
|
|
1070
|
+
No hit means nothing to do.
|
|
1071
|
+
|
|
1072
|
+
### 3. Optional: retune the docked control
|
|
1073
|
+
|
|
1074
|
+
The control docks into the corner the header and the panel's separator line
|
|
1075
|
+
make. One gap sets both of those edges, and the radius applies to the one
|
|
1076
|
+
corner free of them (bottom-left on the navigation panel, bottom-right on the
|
|
1077
|
+
contents panel, mirrored in RTL). Override any of these in your course CSS:
|
|
1078
|
+
|
|
1079
|
+
```css
|
|
1080
|
+
:root {
|
|
1081
|
+
--layout-edge-toggle-gap: 2px; /* under the header, and in from the line */
|
|
1082
|
+
--layout-edge-toggle-width: 1.875rem;
|
|
1083
|
+
--layout-edge-toggle-height: 1.125rem;
|
|
1084
|
+
--layout-edge-toggle-radius: 0.4375rem;
|
|
1085
|
+
--layout-peek-delay: 40ms; /* rest this long on a rail before it peeks */
|
|
1086
|
+
}
|
|
1087
|
+
```
|
|
1088
|
+
|
|
1089
|
+
`--layout-peek-delay` is read by the script, not only by the stylesheet, so it
|
|
1090
|
+
accepts any CSS `<time>` (`40ms`, `0.04s`) and falls back to 40ms if it cannot
|
|
1091
|
+
be parsed. Set it to `0ms` for the previous behaviour, where crossing a
|
|
1092
|
+
collapsed rail opened it immediately.
|
|
1093
|
+
|
|
1094
|
+
Widening or heightening the control also widens the strip each panel keeps
|
|
1095
|
+
clear at its top (`--layout-edge-toggle-reserve`), so the first chapter row
|
|
1096
|
+
stays out from under it; you do not set that one yourself.
|
|
1097
|
+
|
|
1098
|
+
### 4. Reader-side state
|
|
1099
|
+
|
|
1100
|
+
Layout preferences moved from `credit-playground:layout:*` to
|
|
1101
|
+
`explico:layout:*`, and two new keys join them
|
|
1102
|
+
(`explico:layout:navigation-width`, `explico:layout:contents-width`). The old
|
|
1103
|
+
keys are read once as a fallback, so a returning reader keeps the layout they
|
|
1104
|
+
left and there is nothing to migrate. Only if your course clears preference
|
|
1105
|
+
keys by name — few do — add the new names to that list.
|
|
1106
|
+
|
|
1107
|
+
### 5. Only if your course has browser tests over the layout chrome
|
|
1108
|
+
|
|
1109
|
+
A test that asserts the collapse control's size, shape, or position, or that
|
|
1110
|
+
clicks it by an `svg` selector, needs updating: it is a rectangle roughly
|
|
1111
|
+
30 × 18 px docked 2 px under the header and 2 px in from the separator line,
|
|
1112
|
+
both panels' controls share one block start, and its glyphs are text. While a
|
|
1113
|
+
collapsed panel peeks open on hover, its control also *grows* towards the
|
|
1114
|
+
separator — its outer edge stays put — so a test that hovers a rail sees a
|
|
1115
|
+
much wider control than the resting one. A peek also no longer opens the
|
|
1116
|
+
instant a rail is hovered: a test that hovers one and asserts immediately must
|
|
1117
|
+
poll, or set `--layout-peek-delay: 0ms` for the duration of that test. Panels also now carry
|
|
1118
|
+
`.layout-edge-resizer` handles, and a resized panel stamps
|
|
1119
|
+
`data-navigation-resized` / `data-contents-resized` on `<html>`.
|
|
1120
|
+
|
|
1121
|
+
### 6. Verify
|
|
1122
|
+
|
|
1123
|
+
```bash
|
|
1124
|
+
pnpm validate:content # run twice: the first run regenerates build/resolution/*
|
|
1125
|
+
pnpm content check --changed
|
|
1126
|
+
astro check
|
|
1127
|
+
astro build
|
|
1128
|
+
```
|
|
1129
|
+
|
|
36
1130
|
## 0.7.0 → 0.8.0
|
|
37
1131
|
|
|
38
1132
|
### 1. Rule N17 is inverted: delimiters are sized by the engine (`\left`/`\right` everywhere)
|
|
@@ -379,8 +1473,8 @@ needs to change to keep building. To clear the warnings, run
|
|
|
379
1473
|
`pnpm content diagnostics warning`, and enlarge each named outer pair to the
|
|
380
1474
|
next manual size without changing its delimiter shape. Rule N15's build-enforced
|
|
381
1475
|
behavior is unchanged — its documentation now also accepts an N17 manual pair as
|
|
382
|
-
"sized". See [`notation.md#
|
|
383
|
-
[`
|
|
1476
|
+
"sized". See [`notation.md#n17`](notation.md#n17) — and, for rule N16, which
|
|
1477
|
+
was later folded into N17, [`retired.md`](retired.md).
|
|
384
1478
|
|
|
385
1479
|
### 7. Rule P1: "or" never introduces a second name for the same thing
|
|
386
1480
|
|