explico 0.7.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 +1409 -1
- package/README.md +60 -15
- package/dist/compiler/astro.d.ts +6 -1
- package/dist/compiler/cli.d.ts +54 -3
- package/dist/compiler/cli.js +80 -6
- package/dist/compiler/collections.d.ts +35 -2
- package/dist/compiler/collections.js +84 -8
- 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 +14 -1
- package/dist/compiler/logging.js +6 -2
- 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 +21 -11
- package/dist/reference/delimiter-size.js +15 -39
- 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 +69 -34
- package/dist/reference/equations.mjs +90 -44
- 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 +3 -2
- 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 +47 -23
- 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 +44 -6
- package/dist/reference/gate-math.js +63 -10
- 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 +32 -11
- package/dist/reference/gate-prose-notation.js +30 -8
- package/dist/reference/katex-delimiters.d.mts +15 -0
- package/dist/reference/katex-delimiters.mjs +138 -0
- package/dist/reference/katex-options.mjs +4 -0
- 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 +588 -39
- 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 +5 -5
- 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 +24 -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 +1324 -2
- package/docs/authoring/notation.md +616 -344
- 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/docs/katex-bracket-scaling.md +191 -0
- package/package.json +3 -2
- package/src/compiler/cli.ts +139 -6
- package/src/compiler/collections.ts +144 -10
- 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 +21 -4
- 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 +24 -14
- package/src/components/notation/NotationLayer.astro +169 -162
- package/src/components/notation/NotationMath.astro +10 -1
- package/src/components/notation/render-notation-math.ts +111 -10
- package/src/components/reference/FloatRefLayer.astro +485 -423
- package/src/components/starlight/AboutPanel.astro +22 -6
- 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 +40 -61
- package/src/reference/diagrams-validate.ts +17 -1
- package/src/reference/equations-validate.ts +10 -5
- package/src/reference/equations.mjs +90 -44
- 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 +3 -2
- package/src/reference/gate-course-rules.ts +134 -0
- package/src/reference/gate-heading-length.ts +68 -37
- package/src/reference/gate-heading-structure.ts +193 -0
- package/src/reference/gate-math-punctuation.ts +381 -0
- package/src/reference/gate-math.ts +119 -12
- package/src/reference/gate-part-pages.ts +217 -0
- package/src/reference/gate-prose-notation.ts +74 -13
- package/src/reference/katex-delimiters.mjs +138 -0
- package/src/reference/katex-options.mjs +4 -0
- 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 +588 -39
- 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 +17 -32
- 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 +24 -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
|
@@ -75,63 +75,315 @@ naming collision both stayed invisible.
|
|
|
75
75
|
|
|
76
76
|
```
|
|
77
77
|
Course Explico Playground
|
|
78
|
-
├── Part 1 Motion in the plane
|
|
79
|
-
│ ├── Ch 1 Position and Coordinate Systems
|
|
80
|
-
│ │ ├── § Locating a point in the plane
|
|
81
|
-
│ │ ├── § Two ways to name the same point
|
|
82
|
-
│ │ │ ├──
|
|
83
|
-
│ │ │ └──
|
|
84
|
-
│ │ ├── § Velocity and acceleration as derivatives ##
|
|
85
|
-
│ │
|
|
86
|
-
│ │
|
|
87
|
-
│ │
|
|
88
|
-
│ └──
|
|
89
|
-
└──
|
|
90
|
-
|
|
91
|
-
|
|
78
|
+
├── Part 1 Motion in the plane content/docs/motion/
|
|
79
|
+
│ ├── Ch 1 Position and Coordinate Systems position-and-coordinates.mdx
|
|
80
|
+
│ │ ├── § 1.1.1 Locating a point in the plane ##
|
|
81
|
+
│ │ ├── § 1.1.2 Two ways to name the same point ##
|
|
82
|
+
│ │ │ ├── § 1.1.2.1 From Cartesian to polar ###
|
|
83
|
+
│ │ │ └── § 1.1.2.2 From polar to Cartesian ###
|
|
84
|
+
│ │ ├── § 1.1.3 Velocity and acceleration as derivatives ##
|
|
85
|
+
│ │ ├── § 1.1.4 The special case: constant acceleration ##
|
|
86
|
+
│ │ │ ├── § 1.1.4.1 Integrating once: velocity ###
|
|
87
|
+
│ │ │ └── § 1.1.4.2 Integrating twice: position ###
|
|
88
|
+
│ │ └── § 1.1.5 Try it ##
|
|
89
|
+
│ └── Ch 2 Velocity Under Constant Acceleration constant-acceleration.mdx
|
|
90
|
+
└── Part 2 Projectile motion content/docs/projectiles/
|
|
91
|
+
├── Ch 1 Projectile Range projectile-range.mdx
|
|
92
|
+
└── Ch 2 Optimal Launch Angle optimal-launch-angle.mdx
|
|
92
93
|
```
|
|
93
94
|
|
|
94
|
-
Which numbers every float like this — the part
|
|
95
|
-
|
|
95
|
+
Which numbers every float like this — the part and the chapter supply the
|
|
96
|
+
prefix, and each chapter counts from 1:
|
|
96
97
|
|
|
97
98
|
```
|
|
98
99
|
Part 1 Motion in the plane
|
|
99
|
-
Ch 1 Position and Coordinate Systems (1.1
|
|
100
|
-
Ch 2 Velocity Under Constant Accel. (1.
|
|
100
|
+
Ch 1 Position and Coordinate Systems (1.1.1) (1.1.2) … (1.1.7)
|
|
101
|
+
Ch 2 Velocity Under Constant Accel. (1.2.1)
|
|
101
102
|
Part 2 Projectile motion
|
|
102
|
-
Ch 1 Projectile Range (2.1) (2.2)
|
|
103
|
-
Ch 2 Optimal Launch Angle (2.
|
|
103
|
+
Ch 1 Projectile Range (2.1.1) (2.1.2) (2.1.3)
|
|
104
|
+
Ch 2 Optimal Launch Angle (2.2.1) (2.2.2) (2.2.3) (2.2.4)
|
|
104
105
|
```
|
|
105
106
|
|
|
107
|
+
## Part pages
|
|
108
|
+
|
|
109
|
+
A part is a directory, so `/<part>/` is a URL a reader will eventually type,
|
|
110
|
+
follow, or be handed by a search engine. Without a page it is a 404, and the
|
|
111
|
+
part exists only as a sidebar heading that cannot be linked to.
|
|
112
|
+
|
|
113
|
+
Give a part a page by authoring **`content/docs/<dir>/index.mdx`**:
|
|
114
|
+
|
|
115
|
+
```mdx
|
|
116
|
+
---
|
|
117
|
+
title: Motion in the plane
|
|
118
|
+
description: Locate a moving point, then predict where it goes next.
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
import PartBridge from 'explico/components/PartBridge.astro';
|
|
122
|
+
import PartOverview from 'explico/components/PartOverview.astro';
|
|
123
|
+
import PartScope from 'explico/components/PartScope.astro';
|
|
124
|
+
|
|
125
|
+
<PartBridge>
|
|
126
|
+
|
|
127
|
+
How the earlier parts lead into this one — omitted on the first part.
|
|
128
|
+
|
|
129
|
+
</PartBridge>
|
|
130
|
+
|
|
131
|
+
<PartScope>
|
|
132
|
+
|
|
133
|
+
What this part covers, in the course's own voice.
|
|
134
|
+
|
|
135
|
+
</PartScope>
|
|
136
|
+
|
|
137
|
+
<PartOverview
|
|
138
|
+
chain={[
|
|
139
|
+
'A point in the plane gets a name: Cartesian, or polar',
|
|
140
|
+
'Velocity and acceleration are that name differentiated',
|
|
141
|
+
]}
|
|
142
|
+
/>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**The two paragraphs are required** ([S2](structure-rules.md#s2)): every part
|
|
146
|
+
page after the first opens with a `<PartBridge>` paragraph that links the
|
|
147
|
+
earlier parts to this one, and every part page carries a `<PartScope>`
|
|
148
|
+
paragraph on its own content. `pnpm validate:content` fails when one is
|
|
149
|
+
missing, holds more than one paragraph, or falls outside the course's
|
|
150
|
+
`rules.S2` word range (30–150 words unless the course sets its own).
|
|
151
|
+
|
|
152
|
+
**An overview page is not a chapter.** `isLessonSlug` has always excluded
|
|
153
|
+
`<dir>/index`, so the page teaches no competency, carries no knowledge check,
|
|
154
|
+
takes no float numbers, and never appears in `manifest.lessons` or a track. A
|
|
155
|
+
course adds one part at a time; a part without one behaves exactly as before.
|
|
156
|
+
|
|
157
|
+
`<PartOverview>` reads the manifest for everything it lists — chapters in
|
|
158
|
+
reading order with their descriptions, the competencies the part teaches, the
|
|
159
|
+
parts it builds on and leads to — so the page cannot fall out of date with the
|
|
160
|
+
content. Only the two paragraphs and the optional `chain` (the part's argument,
|
|
161
|
+
one step per line, which no manifest field knows) are authored. `rail={false}` drops the
|
|
162
|
+
side rail and keeps the reading list.
|
|
163
|
+
|
|
164
|
+
### Study time
|
|
165
|
+
|
|
166
|
+
A chapter may state how long it takes, and only the chapter can know:
|
|
167
|
+
|
|
168
|
+
```yaml
|
|
169
|
+
studyMinutes: 40 # or a range
|
|
170
|
+
studyMinutes: [30, 40]
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`<PartOverview>` prints it beside each chapter and totals the part;
|
|
174
|
+
`<CourseContents>` totals the course in hours. **A total appears only when
|
|
175
|
+
every chapter in that part states one**, so a half-annotated course shows the
|
|
176
|
+
chapters it knows about and no misleading sum. Nothing derives the field and
|
|
177
|
+
nothing requires it — it is the reader-facing half of the old
|
|
178
|
+
`estimatedMinutes`, which was dropped when there was nowhere to add it up.
|
|
179
|
+
|
|
180
|
+
### Reaching the page
|
|
181
|
+
|
|
182
|
+
Three routes lead to it, and a course gets all three at once:
|
|
183
|
+
|
|
184
|
+
| Route | Where it comes from | Works without JavaScript |
|
|
185
|
+
| --- | --- | --- |
|
|
186
|
+
| The `Overview` row leading the part's sidebar group | the compiled `sidebar` | yes |
|
|
187
|
+
| The `»` control in the sidebar group's header | `LayoutSidebar.astro`'s script | no |
|
|
188
|
+
| The part's name above every chapter title | `LayoutPageTitle.astro` | yes |
|
|
189
|
+
|
|
190
|
+
The part label in the sidebar keeps collapsing the group when clicked — the
|
|
191
|
+
control sits beside the caret rather than taking either gesture. The breadcrumb
|
|
192
|
+
needs one line of wiring in the course's `astro.config.mjs`:
|
|
193
|
+
|
|
194
|
+
```js
|
|
195
|
+
components: {
|
|
196
|
+
PageTitle: 'explico/components/starlight/LayoutPageTitle.astro',
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Name the sidebar row with `overviewLabel` on the part when `Overview` is wrong
|
|
201
|
+
for a course: `{ dir: 'bonds', label: 'Bonds', overviewLabel: 'All bonds' }`.
|
|
202
|
+
|
|
203
|
+
## The course's own contents
|
|
204
|
+
|
|
205
|
+
A landing page that links only the first chapter hides the rest of the course.
|
|
206
|
+
`<CourseContents>` lists every part with its chapters, in reading order, each
|
|
207
|
+
part heading linking its overview page:
|
|
208
|
+
|
|
209
|
+
```mdx
|
|
210
|
+
import CourseContents from 'explico/components/CourseContents.astro';
|
|
211
|
+
|
|
212
|
+
<CourseContents />
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
It reads the same manifest the sidebar does, so a renamed chapter or a new part
|
|
216
|
+
cannot leave a stale copy behind on the front page. `descriptions={false}`
|
|
217
|
+
drops the one-line summaries; `headingLevel={3}` fits it under an existing
|
|
218
|
+
`##`.
|
|
219
|
+
|
|
220
|
+
## Where the reader is
|
|
221
|
+
|
|
222
|
+
Two marks, both derived, neither authored:
|
|
223
|
+
|
|
224
|
+
- **The navigation rail** colours the segment beside every chapter already
|
|
225
|
+
passed, so the boundary between accent and hairline is the reader's position
|
|
226
|
+
in the course. A part whose chapters are all behind them is marked whole.
|
|
227
|
+
Reading order is the sidebar's own order, which is the merged track order.
|
|
228
|
+
- **The contents rail** does the same down one page, following Starlight's
|
|
229
|
+
scroll-spy as the reader travels.
|
|
230
|
+
|
|
231
|
+
Both are progressive enhancements: without JavaScript the rails are simply
|
|
232
|
+
uncoloured.
|
|
233
|
+
|
|
234
|
+
The part header carries the third mark, and that one is pure CSS, so it is
|
|
235
|
+
right in the first painted frame: a standing tint while the open page belongs
|
|
236
|
+
to that part. Together the three never read as the same thing — a solid accent
|
|
237
|
+
row is the chapter you are on, a tint is the part holding it, a neutral fill
|
|
238
|
+
comes and goes with the pointer.
|
|
239
|
+
|
|
106
240
|
## Numbering
|
|
107
241
|
|
|
108
|
-
|
|
109
|
-
numbered
|
|
242
|
+
Every number follows the book's outline: part, then chapter, then the thing
|
|
243
|
+
numbered. A course sets the details in `course.settings.json` → `numbering`;
|
|
244
|
+
every key is optional, and these are the defaults:
|
|
110
245
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
246
|
+
```json
|
|
247
|
+
"numbering": {
|
|
248
|
+
"sections": { "show": true, "depth": 4 },
|
|
249
|
+
"floats": "chapter",
|
|
250
|
+
"aliases": true
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
A number is for a reader to see and say. It is never the anchor: a heading's
|
|
255
|
+
anchor is its slug (`#two-ways-to-name-the-same-point`) and a float's is its
|
|
256
|
+
`id` (`#tab-kinematics-summary`), so a link survives a section inserted above
|
|
257
|
+
its target.
|
|
258
|
+
|
|
259
|
+
### Section numbers
|
|
260
|
+
|
|
261
|
+
A lesson's top-level `##` to `######` headings are numbered
|
|
262
|
+
**`‹part›.‹chapter›.‹section›[.‹subsection›…]`**:
|
|
263
|
+
|
|
264
|
+
- **`part`** is the part's 1-based position in `courseConfig.parts`, and
|
|
265
|
+
**`chapter`** the lesson's position in its part, in sidebar order.
|
|
266
|
+
- `##` counts within the chapter, `###` within its `##`, and so on; a deeper
|
|
267
|
+
counter restarts under every shallower heading. Headings descend one level
|
|
268
|
+
at a time (rule S6), so no level is skipped; where one is anyway (S6 off or
|
|
269
|
+
waived), it counts as 0 (`##` then `####` is `1.1.1.0.1`), as in LaTeX.
|
|
270
|
+
- A heading deeper than `numbering.sections.depth` (default `4`, `####`) is
|
|
271
|
+
unnumbered. A heading inside a component — a `<Memo>`, a `<CompactExample>` —
|
|
272
|
+
belongs to that component, not to the outline, so it is neither numbered nor
|
|
273
|
+
counted. The generated "References" section and a knowledge check's own
|
|
274
|
+
heading are not numbered either.
|
|
275
|
+
|
|
276
|
+
Where a section number shows:
|
|
277
|
+
|
|
278
|
+
| | Wide screen | Narrow screen (under 50em) | Print |
|
|
279
|
+
| --- | :-: | :-: | :-: |
|
|
280
|
+
| An open section's heading | ✓ | — | ✓ |
|
|
281
|
+
| A collapsed section's bar | ✓ | ✓ | ✓ |
|
|
282
|
+
| The chain icon's "Link copied · § 1.1.2" | ✓ | ✓ | — |
|
|
283
|
+
|
|
284
|
+
`numbering.sections.show: false` shows no section numbers anywhere.
|
|
285
|
+
|
|
286
|
+
**The chain icon copies the link.** Clicking (or tapping) a heading's chain
|
|
287
|
+
icon puts the page's URL with the heading's named anchor on the clipboard,
|
|
288
|
+
sets the address bar to it, highlights the section, and says "Link copied ·
|
|
289
|
+
§ 1.1.2" beside the icon. On a narrow screen, where an open heading shows no
|
|
290
|
+
number, that confirmation is where the number surfaces, and the icon is always
|
|
291
|
+
visible there. If the browser refuses the clipboard, the click still navigates
|
|
292
|
+
and highlights. Tapping a heading's title only folds or unfolds a collapsible
|
|
293
|
+
section; it never changes the URL.
|
|
294
|
+
|
|
295
|
+
**Citing a section.** `[[sec-‹anchor›]]` on the same page, or
|
|
296
|
+
`[[lesson/slug#sec-‹anchor›]]` from another lesson, prints `§ 1.1.2` as a link
|
|
297
|
+
to the section, with a hover card showing its title and first paragraph. The
|
|
298
|
+
anchor is the heading's slug: its text in lowercase, spaces as hyphens,
|
|
299
|
+
punctuation dropped, so `## Two ways to name the same point` is
|
|
300
|
+
`[[sec-two-ways-to-name-the-same-point]]`, and a title that repeats takes
|
|
301
|
+
`-1`, `-2`. A reference to a heading without a number (deeper than `depth`, or
|
|
302
|
+
with `show: false`) prints the heading's title in quotes instead: a reader
|
|
303
|
+
could not find the number. A reference that names no top-level heading fails
|
|
304
|
+
`pnpm validate:content` (`sec-ref-resolves`) and the build.
|
|
305
|
+
|
|
306
|
+
### Structure from the bottom up
|
|
307
|
+
|
|
308
|
+
A heading's level says where it sits in the outline: rule S6 lets it go one
|
|
309
|
+
level deeper than the heading before it, and rule S7 puts body content
|
|
310
|
+
between two headings. Neither is a way to get structure where the outline
|
|
311
|
+
has run out. When a section near the bottom of the outline holds two parallel
|
|
312
|
+
enumerations — the assumptions of a model and its conclusions, the steps of
|
|
313
|
+
two methods — do not open `#####` headings for them, and do not climb back
|
|
314
|
+
to `##` for the look of it. Structure them from the bottom up, the way LaTeX
|
|
315
|
+
does with `\paragraph` and its `description` environment:
|
|
316
|
+
|
|
317
|
+
- a **run-in label** — a bold phrase that opens its paragraph (`**Level
|
|
318
|
+
ground.** The launch and landing heights are equal …`), for a few items
|
|
319
|
+
that each take a paragraph;
|
|
320
|
+
- a **description list** — one line per item, the label in bold and its
|
|
321
|
+
explanation after it — for many short items;
|
|
322
|
+
- a `<Table>`, when the items share the same attributes.
|
|
323
|
+
|
|
324
|
+
A run-in label is not in the outline, "On this page" or the numbering, and it
|
|
325
|
+
needs none of that: it names a paragraph for the reader who is already
|
|
326
|
+
reading the section, not a place to jump to. Promote it to a heading only
|
|
327
|
+
when it deserves a link, a number or folding of its own.
|
|
328
|
+
|
|
329
|
+
### Float numbers
|
|
330
|
+
|
|
331
|
+
A display equation, `<Table>`, `<Figure>`, `<Diagram>`, knowledge check or
|
|
332
|
+
worked-example set (`<CompactExamples>`) is numbered **`‹part›.‹chapter›.‹n›`**:
|
|
333
|
+
|
|
334
|
+
- **`n`** counts that kind of numbered item in the chapter, in document order.
|
|
335
|
+
Each kind counts on its own, so a `<Table>` never advances the `<Figure>`,
|
|
336
|
+
`<Diagram>`, knowledge-check or example sequence.
|
|
116
337
|
- **Sections and subsections do not participate.** Neither `##` nor `###`
|
|
117
338
|
resets `n` or appears in the number.
|
|
118
339
|
- **Keyed or not, everything counts.** An equation with no `\label{eq:…}` still
|
|
119
|
-
takes a number and a positional anchor (`#eq-2-4`); it just cannot be
|
|
340
|
+
takes a number and a positional anchor (`#eq-2-1-4`); it just cannot be
|
|
120
341
|
referenced by name.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
`
|
|
126
|
-
|
|
127
|
-
the
|
|
342
|
+
- **The number sits with the caption.** A figure or diagram prints it in the
|
|
343
|
+
caption line below its picture, a table in the caption line above, and a
|
|
344
|
+
display equation beside it. What names each
|
|
345
|
+
float — its long `caption` and optional `short` caption, an equation's
|
|
346
|
+
`\caption{…}` — is [components.md § The caption pair](components.md#the-caption-pair).
|
|
347
|
+
- **A check's and an example set's number shows like a section's.** Both are
|
|
348
|
+
sections of the page with a heading of their own, so their number follows
|
|
349
|
+
[§ Section numbers](#section-numbers) — wide screen, print, folded bar, and
|
|
350
|
+
not at all with `numbering.sections.show` off — while a float's stays in its
|
|
351
|
+
caption at every width, because prose names a float by its number.
|
|
352
|
+
|
|
353
|
+
In the playground: part 1 runs `1.1.1` … `1.1.7` through chapter 1, and
|
|
354
|
+
chapter 2 starts again at `1.2.1`; part 2 opens at `2.1.1`.
|
|
355
|
+
|
|
356
|
+
`numbering.floats: "part"` keeps the older scheme, **`‹part›.‹n›`**, with `n`
|
|
357
|
+
running on from one chapter of the part into the next — the first equation of
|
|
358
|
+
a chapter that follows one with seven is `1.8`.
|
|
359
|
+
|
|
360
|
+
`manifest.lessons[]` carries what the render path needs to reproduce all of
|
|
361
|
+
this: `part`, `chapter`, `numbering.prefix` and the per-kind count each chapter
|
|
362
|
+
starts from (`numbering.{equations,tables,figures,diagrams,checks,examples}`,
|
|
363
|
+
all 0 under the chapter scope), and `headings`, every top-level heading with
|
|
364
|
+
its anchor and number.
|
|
365
|
+
|
|
366
|
+
### Number aliases
|
|
367
|
+
|
|
368
|
+
A number is not an anchor, but a reader may still type one. With
|
|
369
|
+
`numbering.aliases` on (the default), a fragment in number form — `#sec-1.1.2`,
|
|
370
|
+
`#fig-2.2.1`, `#eq-1.1.4`, `#tab-…`, `#dia-…`, `#check-…`, `#ex-…` — lands on the
|
|
371
|
+
section or float that shows that number on the page, and the address bar
|
|
372
|
+
switches to its named anchor. This works inbound only: nothing the site links
|
|
373
|
+
or copies is in number form. An alias is only as stable as the content: once a
|
|
374
|
+
section is inserted above it, `§ 1.1.2` names a different section, so a number
|
|
375
|
+
quoted outside the course belongs next to the knowledge version the About
|
|
376
|
+
`[?]` panel shows.
|
|
128
377
|
|
|
129
378
|
### The invariant, and why it is build-enforced
|
|
130
379
|
|
|
131
380
|
The number a page prints beside an equation and the number a cross-page
|
|
132
381
|
`[[slug#eq-key]]` prints for it are computed by two code paths from the same
|
|
133
382
|
content. `remarkNotation` cross-checks them for every keyed float and fails the
|
|
134
|
-
build on any disagreement, naming the key and both numbers.
|
|
383
|
+
build on any disagreement, naming the key and both numbers. Sections get the
|
|
384
|
+
same guard: a page takes its headings' anchors and numbers from the manifest,
|
|
385
|
+
and the build fails if the page's top-level headings are not the ones the
|
|
386
|
+
manifest numbered.
|
|
135
387
|
|
|
136
388
|
This exists because the disagreement is otherwise silent and shipped: a course
|
|
137
389
|
config that passed the manifest number tables without the placement map
|
|
@@ -156,8 +408,8 @@ could still silently fall back to `##`-section numbering with no error at all.
|
|
|
156
408
|
`strict: true` closes that: it fails the build when a catalogued lesson
|
|
157
409
|
contains any equation, `<Table>`, or `<Figure>` — keyed or not — but has no
|
|
158
410
|
`numbering` placement or no cross-page number table entry for its slug.
|
|
159
|
-
`<Diagram>`
|
|
160
|
-
number by design when it has none. `strict` defaults to `false`, so existing
|
|
411
|
+
`<Diagram>` and `<CompactExamples>` are exempt, since both components already
|
|
412
|
+
render one without a number by design when it has none. `strict` defaults to `false`, so existing
|
|
161
413
|
non-strict wiring keeps building unchanged; turn it on once a course's
|
|
162
414
|
manifest covers every catalogued lesson.
|
|
163
415
|
|
|
@@ -182,14 +434,135 @@ inside `<Memo>`/`<ShortNote>`), or wrap it in `<Figure>`.
|
|
|
182
434
|
|
|
183
435
|
### Knowledge checks
|
|
184
436
|
|
|
185
|
-
An assessment title is authored once, in `content/assessments/<id>.json
|
|
186
|
-
that id in the lesson's
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
437
|
+
An assessment title is authored once, in `content/assessments/<id>.json`, and
|
|
438
|
+
names the topic alone ("Position and coordinates"). Put that id in the lesson's
|
|
439
|
+
colocated `.checks.yml`, then render `<AssessmentSet />`; do not add a
|
|
440
|
+
separate “Check yourself” heading. The component draws the check's `<h2>` —
|
|
441
|
+
the check-mark icon and the title, with "Knowledge check" and the number as a
|
|
442
|
+
label in the card's corner
|
|
443
|
+
([components.md § Knowledge checks and worked
|
|
444
|
+
examples](components.md#knowledge-checks-and-worked-examples)) — as a
|
|
445
|
+
permalinked section at `#check-<id>`, collapsible and open unless the course's
|
|
446
|
+
`disclosure.knowledgeChecks` says otherwise ([§ Collapsing](#collapsing-two-mechanisms)),
|
|
447
|
+
and "On this page" lists it. Cite it on the same page with `[[check-<id>]]`, or
|
|
448
|
+
from another lesson with `[[lesson/slug#check-<id>]]`. Single-choice options are
|
|
449
|
+
shuffled when the browser views the check; option ids, correctness, and
|
|
450
|
+
authored content remain unchanged.
|
|
451
|
+
|
|
452
|
+
### Worked examples
|
|
453
|
+
|
|
454
|
+
A `<CompactExamples id="…" short="…">` is a numbered set of worked examples,
|
|
455
|
+
`Example ‹part›.‹chapter›.‹n›`, one `<CompactExample label="…">` tab each. Both
|
|
456
|
+
props are required: the `id` anchors it at `#ex-<id>` and is what
|
|
457
|
+
`[[ex-<id>]]` (or `[[lesson/slug#ex-<id>]]`) cites; `short` is its topic. The
|
|
458
|
+
component draws the set's `<h2>` — the "Example" badge, the number, the topic
|
|
459
|
+
— so no heading goes above it. The set folds like a section, closed on a first
|
|
460
|
+
visit unless `disclosure.workedExamples` says otherwise, and "On this page"
|
|
461
|
+
lists it.
|
|
462
|
+
|
|
463
|
+
## Containers: plain, meta, accent, aside
|
|
464
|
+
|
|
465
|
+
Every box the engine draws belongs to one of four tiers, and the tier says
|
|
466
|
+
what the content *is* — the reader learns one visual language, not one per
|
|
467
|
+
component:
|
|
468
|
+
|
|
469
|
+
| Tier | Looks like | Means | Used by |
|
|
470
|
+
| --- | --- | --- | --- |
|
|
471
|
+
| **plain** | no card | material a book would print in its main flow | sections, figures, tables, equations, diagrams, References |
|
|
472
|
+
| **meta** | grey surface, thin border | logistics, or generated for the reader | the notation panel, a part page's rail, the About panel, the glossary and curriculum-map cards, a Starlight `<Card>` |
|
|
473
|
+
| **accent** | accent tint, thin border, shadow | enrichment the author marked | knowledge checks, worked examples, a `[card]` section |
|
|
474
|
+
| **aside** | a left rule (a memo is also tinted) | an annotation beside the flow | `<Memo>`, an opened `<ShortNote>`, a Starlight aside |
|
|
475
|
+
|
|
476
|
+
A tier is fixed per kind; a course has no setting to change it. No container
|
|
477
|
+
has a top rule, and the shadow never grows with heading depth: hierarchy is in
|
|
478
|
+
type size and numbers. An interactive figure has no card of its own either —
|
|
479
|
+
its lab is plain figure material.
|
|
480
|
+
|
|
481
|
+
**Heading markers.** A heading takes up to two markers at the end of its
|
|
482
|
+
line, one of each kind, in either order. They never render, never reach the
|
|
483
|
+
anchor (`### Explore the range [card]` is `#explore-the-range`), and rule S1
|
|
484
|
+
does not count them.
|
|
485
|
+
|
|
486
|
+
| Marker | Effect |
|
|
487
|
+
| --- | --- |
|
|
488
|
+
| `[collapsible]` | collapsible, starts open, whatever the `disclosure` default |
|
|
489
|
+
| `[collapsed]` | collapsible, starts closed |
|
|
490
|
+
| `[no-collapsible]` | never collapsible |
|
|
491
|
+
| `[card]` | the section — heading and body, down to the next heading of the same or a higher rank — becomes one **accent** card |
|
|
492
|
+
| `[card=meta]` | the same, in the **meta** tier, and unnumbered: logistics — what a chapter builds on, how to read it — is outside the outline, like References, and so is every heading inside it |
|
|
493
|
+
|
|
494
|
+
```mdx
|
|
495
|
+
### Explore the range [collapsed] [card]
|
|
496
|
+
|
|
497
|
+
Move the sliders; the section folds and unfolds as one card.
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
Use `[card]` to set a stretch of the lesson apart as something to try or
|
|
501
|
+
explore — a lab with the prose that frames it, say. It is not for emphasis:
|
|
502
|
+
a section that matters more is a better heading, not a box.
|
|
503
|
+
|
|
504
|
+
**Starlight asides and cards.** `:::note`, `:::tip`, `:::caution` and
|
|
505
|
+
`:::danger` (and `<Aside type="…">`) render in the aside tier with
|
|
506
|
+
Starlight's own icon per type; `note` and `tip` take the course accent,
|
|
507
|
+
`caution` and `danger` keep a warning and a danger hue. Name any Starlight
|
|
508
|
+
built-in icon to replace it (`:::note{icon="heart"}`), or leave it empty to
|
|
509
|
+
drop it (`:::note{icon=""}`, `<Aside icon="">`). The `:::` form needs
|
|
510
|
+
`remarkAsides` (`explico/reference/remark-asides.mjs`) last in the course's
|
|
511
|
+
`remarkPlugins`: Starlight renders directives only under its own
|
|
512
|
+
`src/content/docs/`, and this pass hands them to Starlight's `<Aside>`. In a
|
|
513
|
+
`.md` lesson (no JSX) an aside has no icon. A `<Card>` / `<CardGrid>` renders
|
|
514
|
+
in the meta tier. Rule S8 says when a `<Memo>` is the better choice than an
|
|
515
|
+
aside.
|
|
516
|
+
|
|
517
|
+
## Collapsing: two mechanisms
|
|
518
|
+
|
|
519
|
+
A block folds in one of two ways, and every default lives in one place, the
|
|
520
|
+
`disclosure` block of `course.settings.json`
|
|
521
|
+
(`CourseConfig.disclosure`, published as `manifest.disclosure`):
|
|
522
|
+
|
|
523
|
+
- **A section folds away whole.** Its heading stays as a bar with a chevron;
|
|
524
|
+
its body hides behind a "Hidden here: 2 paragraphs, 1 equation" line and
|
|
525
|
+
peeks on hover. `##` … `######` sections, a knowledge check, a set of worked
|
|
526
|
+
examples, the generated References, a `<Memo>` (a `######`-rank section
|
|
527
|
+
of its own) and a `<Fold>` (the same, with no marker, letter or frame, and
|
|
528
|
+
a bar that names the floats it holds — [components.md](components.md#folding-content-away-fold))
|
|
529
|
+
fold this way; the notation panel folds the same way.
|
|
530
|
+
- **A float folds what follows its caption line, never the line.** A table
|
|
531
|
+
folds to its caption line and header row, and starts truncated when it is
|
|
532
|
+
long. A table's fold button is at the top right of its caption line, next
|
|
533
|
+
to a widen button ↔ when the table is wider than the column; the column at
|
|
534
|
+
its right edge widens it too. A figure or a diagram does not fold: it is
|
|
535
|
+
its picture and then its caption line — number, link, caption
|
|
536
|
+
([components.md § The caption pair](components.md#the-caption-pair)) — in
|
|
537
|
+
every state, as LaTeX lays a figure out; a diagram's line ends with a widen
|
|
538
|
+
button ↔ while the graph is wider than the column. What a figure can fold
|
|
539
|
+
is what follows its caption line: a lab's tools, with the fold button ⌃ /
|
|
540
|
+
⌄ at the line's end and a "Hidden here: 2 sliders, 1 equation" line while
|
|
541
|
+
folded. To fold a float away
|
|
542
|
+
entirely, wrap it in a `<Fold>` or put it in a collapsible section.
|
|
543
|
+
|
|
544
|
+
| Block | Mechanism | Setting | Engine default | One place overrides with |
|
|
545
|
+
| --- | --- | --- | --- | --- |
|
|
546
|
+
| `##` section | section | `disclosure.sections` | not collapsible | a heading marker |
|
|
547
|
+
| `###`–`######` section | section | `disclosure.subsections` | not collapsible | a heading marker |
|
|
548
|
+
| Knowledge check | section | `disclosure.knowledgeChecks` | collapsible, open | — |
|
|
549
|
+
| References | section | `disclosure.references` | closed | — |
|
|
550
|
+
| Notation panel | section | `disclosure.notation` | closed | — |
|
|
551
|
+
| `<Memo>` | section, `######` rank | `disclosure.memos` | closed | `defaultOpen` |
|
|
552
|
+
| `<Fold>` | section, `######` rank | `disclosure.folds` | closed | `defaultOpen` |
|
|
553
|
+
| A lab's tools (`<Figure>`'s `tools` slot) | a float's fold, after its caption line | `disclosure.figures` | open | `defaultOpen` |
|
|
554
|
+
| `<CompactExamples>` | section, `##` rank | `disclosure.workedExamples` | closed | `defaultOpen` |
|
|
555
|
+
| `<Table>` | minimize + truncation | `disclosure.tables.truncateAfter` | truncated above 6 rows | — |
|
|
556
|
+
|
|
557
|
+
`sections`, `subsections` and `knowledgeChecks` take `{ collapsible,
|
|
558
|
+
defaultOpen }`; the others take `{ defaultOpen }`; `tables` takes
|
|
559
|
+
`{ truncateAfter }` — a table with more rows shows that many, half from each
|
|
560
|
+
end, and a "… N more rows …" line. There is no `disclosure.diagrams`: a
|
|
561
|
+
diagram does not fold. Every collapsible remembers the reader's own choice,
|
|
562
|
+
per page, over the default (`rememberState={false}` on a memo, a fold, a
|
|
563
|
+
figure's tools or an example set opts that one out). A short note's in-place
|
|
564
|
+
reveal and a question's show/hide button are inline affordances, not
|
|
565
|
+
containers, and are not settings.
|
|
193
566
|
|
|
194
567
|
## Detailed memos and inline short notes
|
|
195
568
|
|
|
@@ -197,8 +570,11 @@ Headings define the page's conceptual hierarchy: they belong in the outline and
|
|
|
197
570
|
should help every reader navigate the main argument. A `<Memo>` instead holds
|
|
198
571
|
optional depth — a long derivation, proof, robustness check, edge case, or
|
|
199
572
|
alternative method — without pretending that material is another section of
|
|
200
|
-
the lecture. It
|
|
201
|
-
|
|
573
|
+
the lecture. It sits in the aside tier (a left rule and the accent tint), is
|
|
574
|
+
independently lettered, and folds like a `######` section — the same chevron,
|
|
575
|
+
peek and "Hidden here" line — starting closed unless the course's
|
|
576
|
+
`disclosure.memos` says otherwise. Its bar is not a heading of the lesson: it
|
|
577
|
+
is not in the outline, "On this page" or the heading rules.
|
|
202
578
|
|
|
203
579
|
Register `remarkShortNote` and then `remarkMemo` after `remarkMath` in
|
|
204
580
|
`astro.config.mjs`. Import `explico/components/memo/Memo.astro`, cite a memo with
|
|
@@ -209,7 +585,7 @@ The full calculation is available in [[memo-supporting-check]].
|
|
|
209
585
|
|
|
210
586
|
Several paragraphs may intervene before the detailed material.
|
|
211
587
|
|
|
212
|
-
<Memo id="supporting-check"
|
|
588
|
+
<Memo id="supporting-check" short="Supporting check" caption="The detailed calculation behind the claim">
|
|
213
589
|
|
|
214
590
|
The body can contain ordinary Markdown, display equations, `<Table>`, and
|
|
215
591
|
`<Figure>` components.
|
|
@@ -217,19 +593,26 @@ The body can contain ordinary Markdown, display equations, `<Table>`, and
|
|
|
217
593
|
</Memo>
|
|
218
594
|
```
|
|
219
595
|
|
|
220
|
-
`[[memo-supporting-check]]` renders as
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
596
|
+
`[[memo-supporting-check]]` renders as a superscript letter, *ᵃ* — the footnote
|
|
597
|
+
convention, so it never reads as a citation's `[1]`; memos are lettered `a`,
|
|
598
|
+
`b`, … per page. Clicking it opens and scrolls to the block and updates the
|
|
599
|
+
URL to `#memo-supporting-check`; clicking it again folds the memo. The memo's
|
|
600
|
+
bar shows the same letter, and the chain icon beside it copies the memo's
|
|
601
|
+
link, as a heading's does. A memo is named like every float
|
|
602
|
+
([components.md § The caption pair](components.md#the-caption-pair)): `id` and
|
|
603
|
+
`caption` are required literal strings — the caption is the memo's bar and
|
|
604
|
+
heads its marker's preview — and an optional `short` caption is the marker's
|
|
605
|
+
tooltip. The block starts as `disclosure.memos` says (closed by default;
|
|
606
|
+
`defaultOpen` overrides it at one memo) and remembers later open/closed
|
|
607
|
+
choices unless `rememberState={false}` is set. Memo lettering is
|
|
608
|
+
independent of equation, table, figure, and diagram numbering. Those numbered
|
|
609
|
+
items remain in their normal page/part streams inside a memo.
|
|
610
|
+
|
|
611
|
+
For print and PDF export, the memo prints as the reader left it on screen. An
|
|
612
|
+
open memo prints at its reading-order position. It does not move to the bottom
|
|
613
|
+
of the page: browser support for CSS footnote floats is not reliable enough to
|
|
614
|
+
make that layout portable. A closed memo prints its caption and a "(content
|
|
615
|
+
collapsed — full text: …)" note that links its permalink.
|
|
233
616
|
|
|
234
617
|
Use `<ShortNote>` for the smaller, genuinely inline interaction. Import
|
|
235
618
|
`explico/components/memo/ShortNote.astro` and put it exactly where its collapsed
|
|
@@ -63,7 +63,7 @@ reader, a course that forks this one) needs the same "did this break me?" signal
|
|
|
63
63
|
from the knowledge version that a library gets from a package version.
|
|
64
64
|
|
|
65
65
|
_How to apply._ Decide the bump when you move `## [Unreleased]` to a dated
|
|
66
|
-
heading ([
|
|
66
|
+
heading ([C3](#c3)); set `about.version` to match.
|
|
67
67
|
|
|
68
68
|
_Enforcement._ Review-only.
|
|
69
69
|
|
|
@@ -74,36 +74,18 @@ _Exceptions._ None. If a change does not fit a tier, it is PATCH.
|
|
|
74
74
|
## C3
|
|
75
75
|
|
|
76
76
|
**`about.version` equals the newest `## [x.y.z]` heading in
|
|
77
|
-
`content/CHANGELOG.md
|
|
77
|
+
`content/CHANGELOG.md`, and a release moves `## [Unreleased]` and bumps
|
|
78
|
+
`about.version` in one commit.**
|
|
78
79
|
|
|
79
80
|
_Rationale._ Two sources of the same fact must not drift. The manifest — and so
|
|
80
81
|
the `[?]` panel — reads `about.version`; a reader chasing "what changed" reads
|
|
81
|
-
the changelog. If they disagree, one is lying.
|
|
82
|
+
the changelog. If they disagree, one is lying. A release is the atomic moment
|
|
83
|
+
they agree again; splitting it across commits leaves a window where the build
|
|
84
|
+
warns and the panel is wrong.
|
|
82
85
|
|
|
83
|
-
_How to apply._
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
_Enforcement._ Build-enforced (Tier-3). `pnpm validate:content` emits
|
|
88
|
-
`knowledge-version-mismatch` when they differ, `knowledge-changelog-missing`
|
|
89
|
-
when there is no released heading, and `knowledge-version-invalid` when
|
|
90
|
-
`about.version` is not `x.y.z`. All are warnings — they never fail the build, but
|
|
91
|
-
CI may choose to.
|
|
92
|
-
|
|
93
|
-
_Exceptions._ None.
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
## C4
|
|
98
|
-
|
|
99
|
-
**On a release, move `## [Unreleased]` to `## [x.y.z] - YYYY-MM-DD` and bump
|
|
100
|
-
`about.version` in the same commit.**
|
|
101
|
-
|
|
102
|
-
_Rationale._ A release is the atomic moment the two records agree again
|
|
103
|
-
([C3](#c3)). Splitting it across commits leaves a window where the build warns
|
|
104
|
-
and the panel is wrong.
|
|
105
|
-
|
|
106
|
-
_How to apply._
|
|
86
|
+
_How to apply._ Between releases, `about.version` stays at the last released
|
|
87
|
+
value while `## [Unreleased]` accumulates bullets ([C1](#c1)). On a release, in
|
|
88
|
+
one commit:
|
|
107
89
|
|
|
108
90
|
1. Choose `x.y.z` from the accumulated `## [Unreleased]` bullets and [C2](#c2).
|
|
109
91
|
2. Rename the heading to `## [x.y.z] - <today>`; add a fresh empty
|
|
@@ -111,6 +93,16 @@ _How to apply._
|
|
|
111
93
|
3. Set `about.version` in `content/course.config.ts` to `x.y.z`.
|
|
112
94
|
4. `pnpm validate:content` — no `knowledge-*` warning.
|
|
113
95
|
|
|
114
|
-
|
|
96
|
+
`pnpm release:content` does steps 2 and 3 for you.
|
|
97
|
+
|
|
98
|
+
_Enforcement._ Build-enforced (Tier-3, `knowledge-version.ts`
|
|
99
|
+
`resolveKnowledgeVersion`). `pnpm validate:content` emits
|
|
100
|
+
`knowledge-version-mismatch` when they differ, `knowledge-changelog-missing`
|
|
101
|
+
when there is no released heading — which is also what a half-finished release
|
|
102
|
+
looks like — and `knowledge-version-invalid` when `about.version` is not
|
|
103
|
+
`x.y.z`. All are warnings; they never fail the build, but CI may choose to.
|
|
104
|
+
Partial: the build only ever sees the end state, so it cannot tell that the two
|
|
105
|
+
edits landed in one commit — it warns until the second half lands.
|
|
115
106
|
|
|
116
107
|
_Exceptions._ None.
|
|
108
|
+
|