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
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# Structure rules
|
|
2
2
|
|
|
3
|
-
`S` rules govern the shape of a lesson's headings
|
|
4
|
-
keyed floats
|
|
3
|
+
`S` rules govern the shape of a lesson's headings, the short captions on its
|
|
4
|
+
keyed floats, the paragraphs that open a part page, and how a table, a
|
|
5
|
+
diagram, or a convention is declared so the rest of the course can reach it —
|
|
6
|
+
the parts of a page a reader scans, links to, or cites. This
|
|
5
7
|
is not [structure.md](structure.md), which is the taxonomy these rules (and
|
|
6
8
|
the rest of the engine) speak in, not a rule set itself.
|
|
7
9
|
|
|
@@ -12,58 +14,438 @@ and "Review-only" mean here, and how to amend a rule.
|
|
|
12
14
|
|
|
13
15
|
## S1
|
|
14
16
|
|
|
15
|
-
**No heading,
|
|
16
|
-
characters.**
|
|
17
|
+
**No heading, no short caption (`short`, an equation's `\caption{}`) and no
|
|
18
|
+
short-note title runs past 65 characters.**
|
|
17
19
|
|
|
18
20
|
This caps every Markdown heading (`##` through `######`), a lesson's own
|
|
19
|
-
`frontmatter.title` (rendered as the page's `<h1>`),
|
|
20
|
-
`
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
`frontmatter.title` (rendered as the page's `<h1>`), the `short` caption of a
|
|
22
|
+
`Figure`, `Diagram`, `Table`, `Memo` or `CompactExamples`, a display
|
|
23
|
+
equation's `\caption{…}`, and a `ShortNote`'s `title` (its inline link
|
|
24
|
+
text). A short caption is the name a float goes by away from itself — the
|
|
25
|
+
heading of its `[[…]]` preview card, an equation's "Copy LaTeX — ‹caption›"
|
|
26
|
+
tooltip — the `[short]` half of LaTeX's `\caption[short]{long}`. The long
|
|
27
|
+
`caption` is never measured: it is the full sentence shown with the float's
|
|
28
|
+
number (see [components.md § The caption pair](components.md#the-caption-pair)).
|
|
29
|
+
A heading is measured as the reader sees it: its markers (`[collapsed]`,
|
|
30
|
+
`[card]`, …) never render, so they never count.
|
|
24
31
|
|
|
25
|
-
A heading or
|
|
26
|
-
the rest of the sentence into the paragraph right after a heading, or
|
|
27
|
-
float's
|
|
32
|
+
A heading or short caption that runs long is usually doing a caption's job.
|
|
33
|
+
Move the rest of the sentence into the paragraph right after a heading, or
|
|
34
|
+
into the float's long `caption`.
|
|
28
35
|
|
|
29
36
|
```mdx
|
|
30
|
-
<!-- Over the limit: the
|
|
37
|
+
<!-- Over the limit: the short caption carries the whole explanation. -->
|
|
31
38
|
<Figure
|
|
32
39
|
id="ar1-forecast-fan"
|
|
33
|
-
|
|
40
|
+
short="Multi-step AR(1) forecast: the conditional mean decays while the band widens"
|
|
41
|
+
caption="…"
|
|
34
42
|
>
|
|
35
43
|
|
|
36
|
-
<!-- At the limit: a short
|
|
44
|
+
<!-- At the limit: a short noun phrase, the rest in the long caption. -->
|
|
37
45
|
<Figure
|
|
38
46
|
id="ar1-forecast-fan"
|
|
39
|
-
|
|
47
|
+
short="Multi-step AR(1) forecast"
|
|
40
48
|
caption="The conditional mean (teal) decays geometrically to the unconditional mean while the Gaussian 95% band (shaded) widens toward the stationary dispersion Γ₀; the coral line is one seeded future path."
|
|
41
49
|
>
|
|
42
50
|
```
|
|
43
51
|
|
|
44
|
-
_Rationale._ A
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
_How to apply._ Write the heading or `title` as a short noun phrase (a topic,
|
|
55
|
-
not a claim about it); put the claim in the prose or the `caption`. If a
|
|
56
|
-
`Figure` needs no distinct title beyond its caption's own first clause,
|
|
57
|
-
extract that clause into `title` explicitly rather than omitting the prop and
|
|
58
|
-
relying on the fallback — an omitted `title` on a long caption is exactly the
|
|
59
|
-
failure this rule exists to catch.
|
|
52
|
+
_Rationale._ A short name lands where space is tight: the sidebar, the table
|
|
53
|
+
of contents, an anchor link, the heading of a preview card, a tooltip. A
|
|
54
|
+
heading authored as a full sentence instead of a label puts a paragraph in
|
|
55
|
+
every one of them. Sixty-five characters is roughly one sidebar line at
|
|
56
|
+
normal zoom before Starlight starts wrapping or truncating it.
|
|
57
|
+
|
|
58
|
+
_How to apply._ Write the heading or short caption as a short noun phrase (a
|
|
59
|
+
topic, not a claim about it); put the claim in the prose or the long
|
|
60
|
+
`caption`. A float needs no `short` at all when its long caption is already
|
|
61
|
+
short — leave it out rather than repeat the caption.
|
|
60
62
|
|
|
61
63
|
_Enforcement._ Build-enforced (`gate-heading-length.ts`, `pnpm
|
|
62
|
-
validate:content`) for every Markdown heading in a lesson body
|
|
63
|
-
`Figure`/`Diagram`/`Memo`/`
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
validate:content`) for every Markdown heading in a lesson body, every literal
|
|
65
|
+
`short` prop on a `Figure`/`Diagram`/`Table`/`Memo`/`CompactExamples`, every
|
|
66
|
+
display equation's `\caption{…}`, and every `ShortNote` `title`. Review-only
|
|
67
|
+
for a lesson's `frontmatter.title` — the gate scans lesson body text and
|
|
68
|
+
cannot see frontmatter, so a long page title (`<h1>`) is caught by a
|
|
69
|
+
reviewer, not the build — and for a `short` set in a wrapper component the
|
|
70
|
+
gate never sees (`DerivationDiagram.astro` passing `short` to `<Diagram>`).
|
|
71
|
+
|
|
72
|
+
_Exceptions._ None — a heading or short caption that must exceed the limit
|
|
73
|
+
should not be one; find the shorter label first.
|
|
74
|
+
|
|
75
|
+
## S2
|
|
76
|
+
|
|
77
|
+
**A part's overview page carries two authored paragraphs: a `<PartBridge>`
|
|
78
|
+
on how the earlier parts lead into this one, then a `<PartScope>` on what
|
|
79
|
+
this part covers.**
|
|
80
|
+
|
|
81
|
+
This applies to every `content/docs/<dir>/index.mdx` a course authors (see
|
|
82
|
+
[structure.md § Part pages](structure.md#part-pages)). Each slot holds exactly
|
|
83
|
+
one paragraph, whose length falls inside the course's word range. The bridge
|
|
84
|
+
comes before the scope. The first part has no earlier part to link from, so
|
|
85
|
+
its bridge is optional; every other part must have one.
|
|
86
|
+
|
|
87
|
+
```mdx
|
|
88
|
+
import PartBridge from 'explico/components/PartBridge.astro';
|
|
89
|
+
import PartOverview from 'explico/components/PartOverview.astro';
|
|
90
|
+
import PartScope from 'explico/components/PartScope.astro';
|
|
91
|
+
|
|
92
|
+
<PartBridge>
|
|
93
|
+
|
|
94
|
+
Part 1 gave two results for a point that moves under a constant acceleration:
|
|
95
|
+
its velocity and its position at any later time. … So this part needs no new
|
|
96
|
+
law of motion.
|
|
97
|
+
|
|
98
|
+
</PartBridge>
|
|
99
|
+
|
|
100
|
+
<PartScope>
|
|
101
|
+
|
|
102
|
+
This part answers two questions about a projectile launched over level
|
|
103
|
+
ground. The first chapter derives the range … The second chapter finds the
|
|
104
|
+
launch angle that gives the largest range.
|
|
105
|
+
|
|
106
|
+
</PartScope>
|
|
107
|
+
|
|
108
|
+
<PartOverview />
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Keep a blank line inside each tag, so MDX parses the paragraph as Markdown and
|
|
112
|
+
its math and `[[key]]` references render.
|
|
113
|
+
|
|
114
|
+
The word range is a course setting, `rules.S2` in `course.settings.json`
|
|
115
|
+
(`CourseConfig.rules`). Each end defaults to 30–150 words; list only what
|
|
116
|
+
differs:
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
"rules": {
|
|
120
|
+
"S2": { "bridgeMaxWords": 120, "scopeMaxWords": 120 }
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The four keys are `bridgeMinWords`, `bridgeMaxWords`, `scopeMinWords`,
|
|
125
|
+
`scopeMaxWords`.
|
|
126
|
+
|
|
127
|
+
A math span and a `[[key]]` reference count as one word each; a link counts
|
|
128
|
+
by its text; a citation and markup count nothing.
|
|
129
|
+
|
|
130
|
+
_Rationale._ `<PartOverview>` lists a part's chapters and the parts it builds
|
|
131
|
+
on, but a list does not say _why_ the part follows the one before it. A reader
|
|
132
|
+
who lands on a part page from a search result or a link needs to know which
|
|
133
|
+
earlier results this part reuses before the chapter list means anything.
|
|
134
|
+
Without a required slot, an intro drifts into one of two failures: it restates
|
|
135
|
+
the chapter list, or it describes this part as if nothing came before it. A
|
|
136
|
+
separate scope paragraph stops the bridge from turning into a summary of the
|
|
137
|
+
part itself. A length range keeps both paragraphs substantive but short enough
|
|
138
|
+
to read before the chapter list.
|
|
139
|
+
|
|
140
|
+
_How to apply._ In the bridge, name the earlier part and the results from it
|
|
141
|
+
that this part uses, and state what those results now make possible. In the
|
|
142
|
+
scope, state the question this part answers and how its chapters answer it,
|
|
143
|
+
in reading order. Keep prose that fits neither paragraph outside both slots.
|
|
144
|
+
|
|
145
|
+
_Enforcement._ Build-enforced (`gate-part-pages.ts`, `pnpm validate:content`)
|
|
146
|
+
for the presence, count, order, paragraph count, and word range of both
|
|
147
|
+
slots. Review-only for what each paragraph says — the gate cannot tell a
|
|
148
|
+
bridge that links the parts from one that does not.
|
|
149
|
+
|
|
150
|
+
_Exceptions._ None for a part that has an overview page. A part without an
|
|
151
|
+
`index.mdx` is out of scope: overview pages stay opt-in.
|
|
152
|
+
|
|
153
|
+
## S3
|
|
154
|
+
|
|
155
|
+
**A table is a `<Table id="…">`, never a raw Markdown or HTML table.**
|
|
156
|
+
|
|
157
|
+
A pipe table or a `<table>` element written straight into a lesson renders,
|
|
158
|
+
but it has no number, no anchor, and `[[tab-…]]` cannot reach it. Wrapping it
|
|
159
|
+
gives it all three:
|
|
160
|
+
|
|
161
|
+
```mdx
|
|
162
|
+
<Table id="kinematics-summary" caption="Position and velocity under constant acceleration.">
|
|
163
|
+
|
|
164
|
+
| Quantity | Formula |
|
|
165
|
+
| --- | --- |
|
|
166
|
+
| $x(t)$ | $x_0 + v_0 t + \tfrac{1}{2} a t^2$ |
|
|
167
|
+
|
|
168
|
+
</Table>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
_Rationale._ Every other float on a page — equation, figure, diagram, knowledge
|
|
172
|
+
check — is numbered and citable; a table that is not breaks the reader's
|
|
173
|
+
expectation that "Table 2.3" exists and the author's ability to say "see
|
|
174
|
+
[[tab-kinematics-summary]]". The keyed-float validator never sees a raw table,
|
|
175
|
+
so its header labels, its overflow handling, and its place in the page's float
|
|
176
|
+
count are all skipped too.
|
|
177
|
+
|
|
178
|
+
_How to apply._ Wrap the table in `<Table id="…" caption="…">` with a blank
|
|
179
|
+
line inside each tag. The `id` is kebab-case and unique on the page; the
|
|
180
|
+
`caption` is the full sentence shown above the table.
|
|
181
|
+
|
|
182
|
+
_Enforcement._ Build-enforced (`raw-floats-validate.ts`, `pnpm
|
|
183
|
+
validate:content`) — a warning per lesson (`raw-table-markdown`,
|
|
184
|
+
`raw-table-html`); `remarkNotation` repeats it at render time for content
|
|
185
|
+
added since the manifest was compiled. It does not fail the build.
|
|
186
|
+
|
|
187
|
+
_Exceptions._ A table inside a component that already gives it identity is
|
|
188
|
+
out of scope: the scan only counts tables at the top level of the lesson
|
|
189
|
+
body.
|
|
190
|
+
|
|
191
|
+
## S4
|
|
192
|
+
|
|
193
|
+
**A `<Diagram>` carries an `id` and sits where diagram numbering can see it.**
|
|
194
|
+
|
|
195
|
+
Diagram numbering scans the top level of a lesson and the bodies of
|
|
196
|
+
`<Memo>`, `<ShortNote>`, `<Table>`, and `<Figure>`. A `<Diagram>` with no `id`,
|
|
197
|
+
or one nested anywhere else (inside `<CompactExample>`, say), is drawn but
|
|
198
|
+
never numbered, and `[[dia-…]]` cannot reach it.
|
|
199
|
+
|
|
200
|
+
```mdx
|
|
201
|
+
<!-- Numbered, citable. -->
|
|
202
|
+
<Diagram id="velocity-dependencies" caption="What the velocity depends on" … />
|
|
203
|
+
|
|
204
|
+
<!-- Drawn, but invisible to numbering. -->
|
|
205
|
+
<CompactExample>
|
|
206
|
+
<Diagram caption="…" … />
|
|
207
|
+
</CompactExample>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
_Rationale._ The same reason as S3: a float the reader can see but the author
|
|
211
|
+
cannot cite is a hole in the reference system. Nesting is the subtler case —
|
|
212
|
+
the diagram *looks* fine on the page, and only the missing number gives it
|
|
213
|
+
away.
|
|
214
|
+
|
|
215
|
+
_How to apply._ Give the diagram an `id`. Move it to the top level, or into a
|
|
216
|
+
`<Memo>`/`<ShortNote>`, or wrap it in `<Figure id="…">` so the figure carries
|
|
217
|
+
the identity.
|
|
218
|
+
|
|
219
|
+
_Enforcement._ Build-enforced (`raw-floats-validate.ts`, `pnpm
|
|
220
|
+
validate:content`) — a warning per lesson (`diagram-unkeyed`,
|
|
221
|
+
`diagram-nested`); repeated by `remarkNotation` at render time. It does not
|
|
222
|
+
fail the build.
|
|
223
|
+
|
|
224
|
+
_Exceptions._ A purely decorative diagram that nothing will ever cite may stay
|
|
225
|
+
unkeyed; say so in a comment next to it.
|
|
226
|
+
|
|
227
|
+
## S5
|
|
228
|
+
|
|
229
|
+
**A sign or perspective convention is declared once and cited everywhere
|
|
230
|
+
else.**
|
|
231
|
+
|
|
232
|
+
A course names one notation entry as its sign convention
|
|
233
|
+
(`conventions.signConventionKey`) and one competency as its cash-flow /
|
|
234
|
+
perspective convention (`conventions.cashFlowPerspectiveCompetency`). A lesson
|
|
235
|
+
whose prose states such a convention — "outflows are negative", "angles are
|
|
236
|
+
measured counter-clockwise from the horizontal" — resolves it to that single
|
|
237
|
+
declaration rather than restating it.
|
|
238
|
+
|
|
239
|
+
```mdx
|
|
240
|
+
<!-- Restated: a second, drifting definition. -->
|
|
241
|
+
In this chapter, an outflow is a negative cash flow.
|
|
242
|
+
|
|
243
|
+
<!-- Resolved to the declaration. -->
|
|
244
|
+
Cash flows follow the [[cash-flow.sign]] convention: an outflow is negative.
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
_Rationale._ A convention restated in several lessons drifts — one says
|
|
248
|
+
"negative", another "shown in parentheses" — and a reader who learned it in
|
|
249
|
+
one place cannot tell whether the other place means the same thing. One
|
|
250
|
+
declaration, cited, keeps the meaning in one file.
|
|
251
|
+
|
|
252
|
+
_How to apply._ Cite the convention's notation entry with `[[key]]` in the
|
|
253
|
+
sentence that invokes it, or list the convention's competency in the lesson's
|
|
254
|
+
`teaches` / `requires`. Either anchors the prose to the declaration.
|
|
255
|
+
|
|
256
|
+
_Enforcement._ Build-enforced (`consistency.ts`
|
|
257
|
+
`checkConventionSingleDefinition`, `pnpm validate:content`) — a warning
|
|
258
|
+
(`convention-single-definition`) for a lesson whose prose matches the
|
|
259
|
+
convention pattern and is anchored by neither the term nor the competency.
|
|
260
|
+
|
|
261
|
+
_Exceptions._ The lesson that *is* the declaration — the one that teaches the
|
|
262
|
+
convention's competency — is anchored by definition.
|
|
263
|
+
|
|
264
|
+
## S6
|
|
265
|
+
|
|
266
|
+
**Headings descend one level at a time: a lesson body starts at `##` and
|
|
267
|
+
never skips a level on the way down.**
|
|
268
|
+
|
|
269
|
+
The page title (`frontmatter.title`) is the lesson's `<h1>`, so the body's
|
|
270
|
+
first heading is a `##`, and a `#` in the body is a second title. From there
|
|
271
|
+
each heading is at most one level deeper than the one before it: `##` → `###`
|
|
272
|
+
→ `####`, never `##` → `####`. Going back up is free — a `####` may be
|
|
273
|
+
followed by a `##`. A knowledge check's heading (`<AssessmentSet />`) and a
|
|
274
|
+
worked-example set's (`<CompactExamples>`) are a `##` here, since that is what
|
|
275
|
+
each renders.
|
|
276
|
+
|
|
277
|
+
```mdx
|
|
278
|
+
<!-- A skip: the #### has no ### above it. -->
|
|
279
|
+
## Two ways to name the same point
|
|
280
|
+
The same point has a Cartesian and a polar name.
|
|
281
|
+
#### From Cartesian to polar
|
|
282
|
+
|
|
283
|
+
<!-- One level at a time. -->
|
|
284
|
+
## Two ways to name the same point
|
|
285
|
+
The same point has a Cartesian and a polar name.
|
|
286
|
+
### From Cartesian to polar
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
_Rationale._ A heading's level is its place in the outline, not its type
|
|
290
|
+
size. A skipped level leaves a subsection with no section above it: the
|
|
291
|
+
numbering has to invent a `0` for it (`1.1.1.0.1`), "On this page" indents it
|
|
292
|
+
under nothing, and a screen reader's heading list — the way many readers move
|
|
293
|
+
through a page — reports a level that does not exist.
|
|
294
|
+
|
|
295
|
+
_How to apply._ Pick the level from what the heading belongs under, never
|
|
296
|
+
from how large it should look. When the material near the bottom of the
|
|
297
|
+
outline needs more structure, do not open deeper headings to get it: see
|
|
298
|
+
[structure.md § Structure from the bottom up](structure.md#structure-from-the-bottom-up).
|
|
299
|
+
|
|
300
|
+
_Enforcement._ Build-enforced (`gate-heading-structure.ts`, `pnpm
|
|
301
|
+
validate:content`, `heading-skip`) over a lesson's outline — the top-level
|
|
302
|
+
headings the section numbers count. A heading inside a component's children
|
|
303
|
+
(a `<Memo>`, a `<CompactExample>`) belongs to that component and is not part
|
|
304
|
+
of the outline, and a memo's own bar is not a heading of the lesson.
|
|
305
|
+
|
|
306
|
+
_Exceptions._ None in the rule; waive one place with
|
|
307
|
+
`{/* explico-allow S6: reason */}` above the heading.
|
|
308
|
+
|
|
309
|
+
## S7
|
|
310
|
+
|
|
311
|
+
**A heading is followed by body content, never directly by another heading.**
|
|
312
|
+
|
|
313
|
+
Between a heading and the next one — whatever their levels — comes body
|
|
314
|
+
content: at least a sentence on what the section is about, or a figure, a
|
|
315
|
+
table, an equation. A comment renders nothing and does not count.
|
|
316
|
+
`<AssessmentSet />` and `<CompactExamples>` count as headings here, because
|
|
317
|
+
each draws an `<h2>` of its own (the kind's badge, its number and its topic):
|
|
318
|
+
no heading goes directly above either.
|
|
319
|
+
|
|
320
|
+
```mdx
|
|
321
|
+
<!-- Two titles in a row: "Try it", then the set's own heading. -->
|
|
322
|
+
## Try it
|
|
323
|
+
|
|
324
|
+
<CompactExamples id="coordinate-conversions" short="Calculation examples between coordinate systems">
|
|
325
|
+
|
|
326
|
+
<!-- A section heading with no body under it. -->
|
|
327
|
+
## Two ways to name the same point
|
|
328
|
+
### From Cartesian to polar
|
|
329
|
+
|
|
330
|
+
<!-- The section says what it is about before it subdivides. -->
|
|
331
|
+
## Two ways to name the same point
|
|
332
|
+
The same point has a Cartesian and a polar name; each converts to the other.
|
|
333
|
+
### From Cartesian to polar
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
_Rationale._ A heading introduces the text below it. Two in a row give the
|
|
337
|
+
reader two labels and nothing to read; the first says nothing of its own,
|
|
338
|
+
and a collapsed section with only a heading inside it folds away nothing.
|
|
339
|
+
The engine already names a knowledge check and a worked-example set, so a
|
|
340
|
+
heading written above either repeats a title the reader sees next.
|
|
341
|
+
|
|
342
|
+
_How to apply._ Write a sentence under a heading that has subsections, on
|
|
343
|
+
what the section covers. Drop a heading that only announces the block below
|
|
344
|
+
it ("Try it" above worked examples, "Check yourself" above a knowledge
|
|
345
|
+
check): the block's own title does that.
|
|
346
|
+
|
|
347
|
+
_Enforcement._ Build-enforced (`gate-heading-structure.ts`, `pnpm
|
|
348
|
+
validate:content`, `heading-adjacent`) over a lesson's outline, reported at
|
|
349
|
+
the first heading of the pair. A memo, a figure and every other component
|
|
350
|
+
count as body content.
|
|
351
|
+
|
|
352
|
+
_Exceptions._ None in the rule; waive one place with
|
|
353
|
+
`{/* explico-allow S7: reason */}` above the first heading.
|
|
354
|
+
|
|
355
|
+
## S8
|
|
356
|
+
|
|
357
|
+
**Use a `<Memo>`, not a Starlight aside, for content that deserves an anchor,
|
|
358
|
+
a caption, or collapsing.**
|
|
359
|
+
|
|
360
|
+
A Starlight aside — `:::note`, `:::tip`, `:::caution`, `:::danger`, or
|
|
361
|
+
`<Aside>` — is a short callout read in passing. It renders in the aside tier
|
|
362
|
+
(a left rule and a tint, Starlight's icon per type kept), but it has no
|
|
363
|
+
number, no link, and it never folds. A `<Memo>` is the same aside tier with
|
|
364
|
+
all three: a letter and a chain icon a reader can link to, a caption shown on
|
|
365
|
+
its bar and in its `[[memo-…]]` preview, and a collapsed state that
|
|
366
|
+
remembers the reader's choice.
|
|
367
|
+
|
|
368
|
+
```mdx
|
|
369
|
+
<!-- A passing remark: an aside is right. -->
|
|
370
|
+
:::note
|
|
371
|
+
Air resistance is ignored throughout this part.
|
|
372
|
+
:::
|
|
373
|
+
|
|
374
|
+
<!-- A derivation a reader may skip, and a later lesson may cite: a memo. -->
|
|
375
|
+
<Memo id="range-check" short="Checking the range formula" caption="…">
|
|
376
|
+
…
|
|
377
|
+
</Memo>
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
The icon is Starlight's default for the type (note → `information`, tip →
|
|
381
|
+
`rocket`, caution → `warning`, danger → `error`). Name any Starlight
|
|
382
|
+
built-in icon to replace it (`:::note{icon="heart"}`, `<Aside icon="heart">`),
|
|
383
|
+
or leave the value empty to drop it (`:::note{icon=""}`, `<Aside icon="">`).
|
|
384
|
+
`note` and `tip` take the course accent; `caution` and `danger` keep a
|
|
385
|
+
warning and a danger hue.
|
|
386
|
+
|
|
387
|
+
_Rationale._ An aside that grows into a derivation, or that another lesson
|
|
388
|
+
wants to point at, has outgrown its container: nothing can link to it, and a
|
|
389
|
+
reader who has already understood it cannot fold it away. Choosing the memo
|
|
390
|
+
up front keeps the reference system whole.
|
|
391
|
+
|
|
392
|
+
_How to apply._ Ask whether anyone would cite, skip, or return to the block.
|
|
393
|
+
If so, make it a `<Memo id="…">`; if it is one or two sentences read once,
|
|
394
|
+
keep the aside.
|
|
395
|
+
|
|
396
|
+
_Enforcement._ Review-only — no check can tell a passing remark from a
|
|
397
|
+
derivation that deserves a number.
|
|
398
|
+
|
|
399
|
+
_Exceptions._ None.
|
|
400
|
+
|
|
401
|
+
## S9
|
|
402
|
+
|
|
403
|
+
**A float’s short caption names it, and its long caption goes on from that
|
|
404
|
+
name instead of restating it; a figure holds no running text, and a lab’s
|
|
405
|
+
instructions go in its tools.**
|
|
406
|
+
|
|
407
|
+
A figure's, a table's or a diagram's `short` caption is its name wherever the
|
|
408
|
+
page names it: the bold title that opens its caption line, a folded
|
|
409
|
+
section's "Hidden here", a `<Fold>`'s bar, a copied link and the "Figures and
|
|
410
|
+
tables" page ([components.md § The caption pair](components.md#the-caption-pair)).
|
|
411
|
+
Printed as the title, it is read right before the long caption, so the long
|
|
412
|
+
caption continues from it, as a journal's figure legend does ("Fig. 1 |
|
|
413
|
+
Title. Description"), instead of saying the same thing twice. Each part of a
|
|
414
|
+
figure's text has one job:
|
|
415
|
+
|
|
416
|
+
- the short caption names the float;
|
|
417
|
+
- the long caption says what it shows — its subject, its marks and symbols,
|
|
418
|
+
the case shown with its parameters — and may state the one thing to
|
|
419
|
+
notice;
|
|
420
|
+
- the argument drawn from the figure is lesson text, after the figure;
|
|
421
|
+
- what to do with a lab's controls is the first line of its tools, never the
|
|
422
|
+
caption.
|
|
423
|
+
|
|
424
|
+
```mdx
|
|
425
|
+
<!-- Restated: the title says "sampled flight data", then the caption does. -->
|
|
426
|
+
<Table id="projectile-telemetry" short="Sampled flight data"
|
|
427
|
+
caption="Flight data sampled at eleven times: position, velocity, …">
|
|
428
|
+
|
|
429
|
+
<!-- Goes on from the title. -->
|
|
430
|
+
<Table id="projectile-telemetry" short="Sampled flight data"
|
|
431
|
+
caption="Position, velocity, acceleration and specific mechanical energy through one flight, from launch to landing.">
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
_Rationale._ With the short caption printed as the caption line's title, a
|
|
435
|
+
long caption that opens with the same words reads as a stutter. A caption
|
|
436
|
+
that carries the argument hides it where a reader of the text does not look,
|
|
437
|
+
and one that tells the reader to move a slider prints that instruction on a
|
|
438
|
+
page with no slider on it.
|
|
439
|
+
|
|
440
|
+
_How to apply._ Write the `short` first: the name a reader would use for the
|
|
441
|
+
float ("Sampled flight data"). Then read the caption line as it prints, the
|
|
442
|
+
title and the long caption together, and cut what the title already says.
|
|
443
|
+
Move a sentence that argues into the paragraph after the float, and a
|
|
444
|
+
sentence that says what to do with a lab's controls into its tools.
|
|
445
|
+
|
|
446
|
+
_Enforcement._ Review-only — no check can tell a caption that restates its
|
|
447
|
+
title from one that builds on it.
|
|
448
|
+
|
|
449
|
+
_Exceptions._ A float that needs no name of its own may go without a
|
|
450
|
+
`short`; the "Figures and tables" page then lists it by its long caption,
|
|
451
|
+
muted.
|