explico 0.8.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/CHANGELOG.md +1257 -1
  2. package/README.md +60 -15
  3. package/dist/compiler/astro.d.ts +6 -1
  4. package/dist/compiler/cli.d.ts +46 -2
  5. package/dist/compiler/cli.js +70 -4
  6. package/dist/compiler/collections.d.ts +35 -2
  7. package/dist/compiler/collections.js +68 -5
  8. package/dist/compiler/course-config.d.ts +3 -194
  9. package/dist/compiler/course-config.js +78 -5
  10. package/dist/compiler/exports/standalone-html.d.ts +6 -1
  11. package/dist/compiler/knowledge-version.js +1 -1
  12. package/dist/compiler/lesson-derivation.d.ts +27 -10
  13. package/dist/compiler/lesson-derivation.js +23 -8
  14. package/dist/compiler/logging.d.ts +4 -1
  15. package/dist/compiler/logging.js +4 -1
  16. package/dist/compiler/manifest.d.ts +204 -31
  17. package/dist/compiler/manifest.js +270 -55
  18. package/dist/compiler/resolution-report.d.ts +6 -1
  19. package/dist/course-config-Dsnri9Tk.d.ts +464 -0
  20. package/dist/reference/base-accents.d.mts +26 -0
  21. package/dist/reference/base-accents.mjs +31 -0
  22. package/dist/reference/base-roman-labels.d.mts +2 -2
  23. package/dist/reference/base-roman-labels.mjs +2 -2
  24. package/dist/reference/consistency.d.ts +14 -2
  25. package/dist/reference/consistency.js +108 -4
  26. package/dist/reference/delimiter-size.d.ts +3 -2
  27. package/dist/reference/diagrams-validate.d.ts +7 -2
  28. package/dist/reference/diagrams-validate.js +9 -1
  29. package/dist/reference/equations-validate.d.ts +8 -5
  30. package/dist/reference/equations-validate.js +1 -0
  31. package/dist/reference/equations.d.mts +60 -31
  32. package/dist/reference/equations.mjs +83 -43
  33. package/dist/reference/examples-validate.d.ts +31 -0
  34. package/dist/reference/examples-validate.js +48 -0
  35. package/dist/reference/figures-validate.d.ts +1 -1
  36. package/dist/reference/figures-validate.js +4 -1
  37. package/dist/reference/folds-validate.d.ts +33 -0
  38. package/dist/reference/folds-validate.js +32 -0
  39. package/dist/reference/gate-abbreviations.d.ts +3 -1
  40. package/dist/reference/gate-abbreviations.js +1 -0
  41. package/dist/reference/gate-course-rules.d.ts +32 -0
  42. package/dist/reference/gate-course-rules.js +85 -0
  43. package/dist/reference/gate-heading-length.d.ts +5 -2
  44. package/dist/reference/gate-heading-length.js +45 -21
  45. package/dist/reference/gate-heading-structure.d.ts +41 -0
  46. package/dist/reference/gate-heading-structure.js +113 -0
  47. package/dist/reference/gate-math-punctuation.d.ts +71 -0
  48. package/dist/reference/gate-math-punctuation.js +251 -0
  49. package/dist/reference/gate-math.d.ts +22 -6
  50. package/dist/reference/gate-math.js +42 -8
  51. package/dist/reference/gate-part-pages.d.ts +50 -0
  52. package/dist/reference/gate-part-pages.js +118 -0
  53. package/dist/reference/gate-prose-notation.d.ts +21 -11
  54. package/dist/reference/gate-prose-notation.js +25 -7
  55. package/dist/reference/katex-delimiters.mjs +20 -7
  56. package/dist/reference/keyed-float-validate.d.ts +27 -10
  57. package/dist/reference/keyed-float-validate.js +15 -1
  58. package/dist/reference/keyed-jsx-floats.d.mts +11 -5
  59. package/dist/reference/keyed-jsx-floats.mjs +73 -20
  60. package/dist/reference/knowledge-checks-validate.d.ts +1 -1
  61. package/dist/reference/knowledge-checks.d.mts +3 -1
  62. package/dist/reference/knowledge-checks.mjs +9 -4
  63. package/dist/reference/lab-math-scope.d.ts +1 -0
  64. package/dist/reference/lab-math-slot.d.ts +34 -0
  65. package/dist/reference/lab-math-slot.js +6 -0
  66. package/dist/reference/math-glyphs.d.mts +80 -4
  67. package/dist/reference/math-glyphs.mjs +572 -37
  68. package/dist/reference/page-notation.d.ts +6 -1
  69. package/dist/reference/raw-floats-validate.js +1 -1
  70. package/dist/reference/raw-floats.mjs +1 -1
  71. package/dist/reference/rehype-heading-anchors.d.mts +14 -0
  72. package/dist/reference/rehype-heading-anchors.mjs +116 -17
  73. package/dist/reference/rehype-table-header-labels.d.mts +6 -1
  74. package/dist/reference/rehype-table-header-labels.mjs +21 -3
  75. package/dist/reference/remark-asides.d.mts +3 -0
  76. package/dist/reference/remark-asides.mjs +180 -0
  77. package/dist/reference/remark-memo.d.mts +3 -1
  78. package/dist/reference/remark-memo.mjs +42 -11
  79. package/dist/reference/remark-notation.d.mts +60 -10
  80. package/dist/reference/remark-notation.mjs +387 -36
  81. package/dist/reference/render-lab-math.d.ts +4 -26
  82. package/dist/reference/render-lab-math.js +4 -4
  83. package/dist/reference/sections-validate.d.ts +27 -0
  84. package/dist/reference/sections-validate.js +41 -0
  85. package/dist/reference/sections.d.mts +97 -0
  86. package/dist/reference/sections.mjs +306 -0
  87. package/dist/reference/tables-validate.d.ts +1 -1
  88. package/dist/reference/types.d.ts +17 -1
  89. package/dist/reference/unit-words.d.ts +37 -0
  90. package/dist/reference/unit-words.js +170 -0
  91. package/dist/rules/catalog.d.ts +176 -0
  92. package/dist/rules/catalog.js +983 -0
  93. package/dist/rules/course-rules.d.ts +115 -0
  94. package/dist/rules/course-rules.js +292 -0
  95. package/dist/rules/course-rules.schema.json +138 -0
  96. package/dist/rules/in-effect.d.ts +53 -0
  97. package/dist/rules/in-effect.js +142 -0
  98. package/dist/rules/rules.schema.json +1072 -0
  99. package/dist/rules/settings.d.ts +3 -0
  100. package/dist/rules/settings.js +290 -0
  101. package/dist/rules/waivers.d.ts +53 -0
  102. package/dist/rules/waivers.js +132 -0
  103. package/dist/session/PreferenceStore.d.ts +5 -0
  104. package/dist/session/PreferenceStore.js +9 -0
  105. package/docs/VERSIONING.md +5 -3
  106. package/docs/authoring/README.md +232 -40
  107. package/docs/authoring/agents.md +55 -9
  108. package/docs/authoring/components.md +178 -22
  109. package/docs/authoring/migrating.md +1152 -2
  110. package/docs/authoring/notation.md +576 -322
  111. package/docs/authoring/prose.md +551 -0
  112. package/docs/authoring/retired.md +35 -0
  113. package/docs/authoring/structure-rules.md +422 -40
  114. package/docs/authoring/structure.md +445 -62
  115. package/docs/authoring/versioning.md +20 -28
  116. package/docs/authoring/visualizations.md +142 -20
  117. package/package.json +2 -2
  118. package/src/compiler/cli.ts +116 -6
  119. package/src/compiler/collections.ts +111 -7
  120. package/src/compiler/course-config.ts +273 -34
  121. package/src/compiler/knowledge-version.ts +1 -1
  122. package/src/compiler/lesson-derivation.ts +54 -15
  123. package/src/compiler/logging.ts +8 -2
  124. package/src/compiler/manifest.ts +573 -104
  125. package/src/components/BlockHeading.astro +113 -0
  126. package/src/components/CourseContents.astro +221 -0
  127. package/src/components/CurriculumMap.astro +5 -6
  128. package/src/components/FloatIndex.astro +200 -0
  129. package/src/components/HoverPanel.astro +431 -79
  130. package/src/components/PartBridge.astro +27 -0
  131. package/src/components/PartOverview.astro +401 -0
  132. package/src/components/PartScope.astro +27 -0
  133. package/src/components/abbreviation/AbbreviationLayer.astro +49 -51
  134. package/src/components/assessments/AssessmentRunner.tsx +8 -5
  135. package/src/components/assessments/AssessmentSet.astro +23 -26
  136. package/src/components/block-heading.ts +146 -0
  137. package/src/components/card-arrow.ts +243 -0
  138. package/src/components/card-drag.ts +631 -0
  139. package/src/components/card-jump.ts +45 -0
  140. package/src/components/card-manager.ts +1589 -0
  141. package/src/components/card-memory.ts +177 -0
  142. package/src/components/card-placement.ts +504 -0
  143. package/src/components/card-side.ts +336 -0
  144. package/src/components/card-travel.ts +197 -0
  145. package/src/components/citation/CitationLayer.astro +77 -76
  146. package/src/components/diagram/Diagram.astro +161 -316
  147. package/src/components/disclosure/course-disclosure.ts +24 -0
  148. package/src/components/disclosure/hover-preview.ts +122 -42
  149. package/src/components/disclosure/persisted-disclosure.ts +3 -3
  150. package/src/components/disclosure/print-as-shown.ts +252 -0
  151. package/src/components/examples/CompactExample.astro +3 -1
  152. package/src/components/examples/CompactExamples.astro +101 -94
  153. package/src/components/figure/Figure.astro +174 -274
  154. package/src/components/figure/FloatCaption.astro +87 -0
  155. package/src/components/figure/figure-state.ts +58 -0
  156. package/src/components/figure/figure-tools.ts +87 -0
  157. package/src/components/float-name.ts +101 -0
  158. package/src/components/fold/Fold.astro +125 -0
  159. package/src/components/fold/fold-id.ts +40 -0
  160. package/src/components/memo/Memo.astro +162 -231
  161. package/src/components/memo/ShortNote.astro +6 -6
  162. package/src/components/notation/NotationFormula.astro +5 -1
  163. package/src/components/notation/NotationGlossary.astro +3 -4
  164. package/src/components/notation/NotationLayer.astro +169 -162
  165. package/src/components/notation/NotationMath.astro +10 -1
  166. package/src/components/reference/FloatRefLayer.astro +485 -423
  167. package/src/components/starlight/AboutPanel.astro +5 -4
  168. package/src/components/starlight/CollapsibleSections.astro +207 -93
  169. package/src/components/starlight/DiagramEnhancer.astro +15 -138
  170. package/src/components/starlight/HeadingAnchorEnhancer.astro +193 -1
  171. package/src/components/starlight/KeyedFloatEnhancer.astro +100 -9
  172. package/src/components/starlight/LayoutHeader.astro +298 -19
  173. package/src/components/starlight/LayoutPageSidebar.astro +99 -12
  174. package/src/components/starlight/LayoutPageTitle.astro +120 -0
  175. package/src/components/starlight/LayoutSidebar.astro +229 -11
  176. package/src/components/starlight/LessonExportActions.astro +53 -72
  177. package/src/components/starlight/LessonFooter.astro +26 -4
  178. package/src/components/starlight/section-parts.ts +15 -2
  179. package/src/components/starlight/section-summary.ts +181 -0
  180. package/src/components/table/Table.astro +95 -76
  181. package/src/components/table/TableOverflowExpander.astro +65 -28
  182. package/src/content-config.ts +40 -4
  183. package/src/reference/base-accents.mjs +31 -0
  184. package/src/reference/base-roman-labels.mjs +2 -2
  185. package/src/reference/consistency.ts +176 -5
  186. package/src/reference/delimiter-size.ts +3 -2
  187. package/src/reference/diagrams-validate.ts +17 -1
  188. package/src/reference/equations-validate.ts +10 -5
  189. package/src/reference/equations.mjs +83 -43
  190. package/src/reference/examples-validate.ts +97 -0
  191. package/src/reference/figures-validate.ts +6 -1
  192. package/src/reference/folds-validate.ts +65 -0
  193. package/src/reference/gate-abbreviations.ts +1 -0
  194. package/src/reference/gate-course-rules.ts +134 -0
  195. package/src/reference/gate-heading-length.ts +66 -35
  196. package/src/reference/gate-heading-structure.ts +193 -0
  197. package/src/reference/gate-math-punctuation.ts +381 -0
  198. package/src/reference/gate-math.ts +69 -10
  199. package/src/reference/gate-part-pages.ts +217 -0
  200. package/src/reference/gate-prose-notation.ts +59 -12
  201. package/src/reference/katex-delimiters.mjs +20 -7
  202. package/src/reference/keyed-float-validate.ts +45 -11
  203. package/src/reference/keyed-jsx-floats.mjs +73 -20
  204. package/src/reference/knowledge-checks-validate.ts +1 -1
  205. package/src/reference/knowledge-checks.mjs +9 -4
  206. package/src/reference/lab-math-slot.ts +36 -0
  207. package/src/reference/math-glyphs.mjs +572 -37
  208. package/src/reference/raw-floats-validate.ts +1 -1
  209. package/src/reference/raw-floats.mjs +1 -1
  210. package/src/reference/rehype-heading-anchors.mjs +116 -17
  211. package/src/reference/rehype-table-header-labels.mjs +21 -3
  212. package/src/reference/remark-asides.mjs +180 -0
  213. package/src/reference/remark-memo.mjs +42 -11
  214. package/src/reference/remark-notation.mjs +387 -36
  215. package/src/reference/render-lab-math.ts +16 -31
  216. package/src/reference/sections-validate.ts +81 -0
  217. package/src/reference/sections.mjs +306 -0
  218. package/src/reference/tables-validate.ts +2 -1
  219. package/src/reference/types.ts +17 -0
  220. package/src/reference/unit-words.ts +233 -0
  221. package/src/rules/catalog.ts +1298 -0
  222. package/src/rules/course-rules.ts +456 -0
  223. package/src/rules/in-effect.ts +235 -0
  224. package/src/rules/settings.ts +448 -0
  225. package/src/rules/waivers.ts +249 -0
  226. package/src/session/PreferenceStore.ts +15 -0
  227. package/src/styles/global.css +1467 -163
  228. package/src/styles/surfaces.css +182 -0
  229. package/src/components/hover-panel.ts +0 -339
  230. package/src/components/popup-stack.ts +0 -345
@@ -1,194 +1,3 @@
1
- /**
2
- * The shape `content/course.config.ts` must satisfy (Phase F).
3
- *
4
- * The engine never imports the course's config file; the wiring layer
5
- * (`astro.config.mjs`, `scripts/*`, `src/content.config.ts`) imports the plain
6
- * data value and passes it here, typed against `CourseConfig`. A second course
7
- * supplies its own value of this shape.
8
- */
9
- /**
10
- * One **part** — a sidebar group, holding the chapters (lessons) whose slugs
11
- * start with `dir`. A part's 1-based position in `CourseConfig.parts` is the
12
- * number before the dot in every equation, table, and figure number inside it.
13
- * See `docs/authoring/structure.md` for the full level taxonomy.
14
- */
15
- interface CoursePart {
16
- /** Lesson-slug prefix, e.g. `bonds` for `bonds/yield-to-maturity`. */
17
- readonly dir: string;
18
- /** Sidebar group heading. */
19
- readonly label: string;
20
- }
21
- /**
22
- * @deprecated Renamed to {@link CoursePart}. "Section" now only ever means an
23
- * `##` heading inside a lesson. Removed in the next MINOR release.
24
- */
25
- type CourseSection = CoursePart;
26
- interface CourseConventions {
27
- /** Notation key a lesson's stated sign convention must resolve to. */
28
- readonly signConventionKey: string;
29
- /** Competency id that also counts as declaring the cash-flow perspective. */
30
- readonly cashFlowPerspectiveCompetency: string;
31
- }
32
- /**
33
- * A course's edits to the shipped named-operator baseline (`BASE_OPERATORS`),
34
- * consumed by the `operator-explained` consistency check (rule N8). An operator
35
- * a lesson uses is fine when it is on the baseline plus `allow` minus `deny`;
36
- * otherwise it needs a notation entry the reader can hover.
37
- *
38
- * Names are the KaTeX command without its backslash (`erf`, not `\erf`) for a
39
- * built-in, and the verbatim body for an `\operatorname{…}` operator (`Var`).
40
- */
41
- interface CourseOperators {
42
- /** Operators this course also treats as universal (`Var`, `Cov`, `sgn`, …). */
43
- readonly allow?: readonly string[];
44
- /** Baseline operators this course wants explained anyway. */
45
- readonly deny?: readonly string[];
46
- }
47
- /**
48
- * A course's edits to the shipped roman-label baseline (`BASE_ROMAN_LABELS`),
49
- * consumed by the `roman-label-explained` consistency check (rule N10). A
50
- * `\mathrm{…}` multi-letter label a lesson uses is fine when it is on the
51
- * baseline plus `allow` minus `deny`; otherwise it needs a notation entry the
52
- * reader can hover. Same shape as {@link CourseOperators}, one level down:
53
- * this governs `\mathrm{KE}`-style labels, not `\operatorname{Var}`-style
54
- * operators.
55
- */
56
- interface CourseRomanLabels {
57
- /** Labels this course also treats as universal qualifiers (`eff`, `net`, …). */
58
- readonly allow?: readonly string[];
59
- /** Baseline labels this course wants explained anyway. */
60
- readonly deny?: readonly string[];
61
- }
62
- /**
63
- * A course's edits to the shipped abbreviation baseline (`BASE_ABBREVIATIONS`),
64
- * consumed by the `abbreviation-explained` gate (rule N14). An abbreviation-
65
- * shaped token — an all-caps acronym or a dotted form like `w.r.t.` — a
66
- * lesson uses in prose is fine when it is on the baseline plus `allow` minus
67
- * `deny`; otherwise it needs an entry in the `abbreviations` content
68
- * collection, or — if it also names a math quantity — a notation entry the
69
- * reader can hover. Same shape as {@link CourseOperators} / {@link
70
- * CourseRomanLabels}.
71
- */
72
- interface CourseAbbreviations {
73
- /** Abbreviations this course also treats as universal (`GDP`, `CPU`, …). */
74
- readonly allow?: readonly string[];
75
- /** Baseline abbreviations this course wants explained anyway. */
76
- readonly deny?: readonly string[];
77
- }
78
- /** One person or team credited for the study material. */
79
- interface CourseAuthor {
80
- readonly name: string;
81
- /**
82
- * Email, URL, or handle. Rendered in the About panel as a link when it looks
83
- * like a `mailto:` or `https:` target, plain text otherwise.
84
- */
85
- readonly contact?: string;
86
- }
87
- /**
88
- * The reader-facing "about this material" block, surfaced by the `[?]` panel in
89
- * the header (`components/starlight/AboutPanel.astro`) on every page.
90
- *
91
- * `version` is the course's **knowledge version** — semver over the
92
- * learning-facing content, independent of the `explico` engine's own version.
93
- * It must equal the newest entry in `content/CHANGELOG.md`; a mismatch is a
94
- * Tier-3 `knowledge-version-mismatch` warning (rule C3, `docs/authoring/versioning.md`).
95
- */
96
- interface CourseAbout {
97
- /** Display name of the material. Defaults to {@link CourseConfig.title}. */
98
- readonly materialName?: string;
99
- /** One or two sentences on what the material covers. Defaults to {@link CourseConfig.description}. */
100
- readonly summary?: string;
101
- /** Knowledge version — semver; equals the latest `content/CHANGELOG.md` heading. */
102
- readonly version: string;
103
- /** Who authored / maintains the material. At least one entry. */
104
- readonly authors: readonly CourseAuthor[];
105
- /** Shown verbatim in the About panel — scope, warranty, AI-assistance note. */
106
- readonly disclaimer: string;
107
- /** Link to the published content changelog (repo blob, docs page, …). */
108
- readonly changelogHref?: string;
109
- }
110
- /**
111
- * A course's chosen initial open/closed state for the engine's own built-in
112
- * collapsible sections — the "Page notation" panel (`NotationLayer.astro`)
113
- * and the generated "References" section (`remark-citation.mjs`). Each is
114
- * independent of `defaultCollapsible.sections`/`.subsections` (an author's
115
- * own `##` headings): both of these are engine-authored, not written by a
116
- * lesson, so they need their own default rather than inheriting the site's
117
- * general heading default.
118
- *
119
- * `true` starts open, `false` (or omitted) starts closed — the engine's own
120
- * default is closed either way, matching a long panel a reader usually
121
- * doesn't need open on arrival.
122
- */
123
- interface CourseDisclosureDefaults {
124
- /** Initial state of the "Page notation" panel. Default: closed. */
125
- readonly notation?: boolean;
126
- /** Initial state of the generated "References" section. Default: closed. */
127
- readonly references?: boolean;
128
- }
129
- /** The stable, non-optional form `NormalizedLessonExports` mirrors. */
130
- interface NormalizedDisclosureDefaults {
131
- readonly notation: boolean;
132
- readonly references: boolean;
133
- }
134
- /** Validate and canonicalize `CourseConfig.disclosureDefaults`. Absent (or
135
- * an absent sub-field) resolves to closed, the engine's own default. */
136
- declare function normalizeDisclosureDefaults(config: CourseConfig): NormalizedDisclosureDefaults;
137
- /** Optional, build-time lesson artifacts exposed to readers. */
138
- interface LessonExportsConfig {
139
- /** Emit one self-contained, offline-capable HTML file per lesson. */
140
- readonly standaloneHtml?: boolean;
141
- /** Offer the browser's native print dialog with explico's lesson print layout. */
142
- readonly print?: boolean;
143
- /**
144
- * Published course root used for links that intentionally leave the exported
145
- * lesson. Required at export time when such a link is present.
146
- */
147
- readonly canonicalBaseUrl?: string;
148
- }
149
- /** The stable, non-optional export settings carried by the manifest. */
150
- interface NormalizedLessonExports {
151
- readonly standaloneHtml: boolean;
152
- readonly print: boolean;
153
- readonly canonicalBaseUrl?: string;
154
- }
155
- interface CourseConfig {
156
- readonly title: string;
157
- readonly description: string;
158
- /**
159
- * The course's parts (sidebar groups), in order. Exactly one of `parts` or
160
- * the deprecated `sections` must be given.
161
- */
162
- readonly parts?: readonly CoursePart[];
163
- /**
164
- * @deprecated Renamed to {@link CourseConfig.parts}. Still honoured, so a
165
- * course on the old name keeps building; removed in the next MINOR release.
166
- */
167
- readonly sections?: readonly CoursePart[];
168
- /** Namespaces used by competency / notation `domain` fields. */
169
- readonly domains: readonly string[];
170
- readonly conventions: CourseConventions;
171
- /** Reader-facing identity + knowledge version (the `[?]` About panel). */
172
- readonly about: CourseAbout;
173
- /** Edits to the shipped named-operator baseline (rule N8). Optional. */
174
- readonly operators?: CourseOperators;
175
- /** Edits to the shipped roman-label baseline (rule N10). Optional. */
176
- readonly romanLabels?: CourseRomanLabels;
177
- /** Edits to the shipped abbreviation baseline (rule N14). Optional. */
178
- readonly abbreviations?: CourseAbbreviations;
179
- /** Per-lesson export actions and downloadable artifacts. Disabled when omitted. */
180
- readonly lessonExports?: LessonExportsConfig;
181
- /** Initial open/closed state for the engine's own built-in collapsible
182
- * sections ("Page notation", "References"). Closed when omitted. */
183
- readonly disclosureDefaults?: CourseDisclosureDefaults;
184
- }
185
- /** Validate and canonicalize the build-facing lesson-export configuration. */
186
- declare function normalizeLessonExports(config: CourseConfig): NormalizedLessonExports;
187
- /**
188
- * The course's parts, from whichever field the config uses. Throws rather than
189
- * silently producing a course with no sidebar groups — a config with neither
190
- * field would otherwise number every float by the `##`-section fallback.
191
- */
192
- declare function coursePartsOf(config: CourseConfig): readonly CoursePart[];
193
-
194
- export { type CourseAbbreviations, type CourseAbout, type CourseAuthor, type CourseConfig, type CourseConventions, type CourseDisclosureDefaults, type CourseOperators, type CoursePart, type CourseRomanLabels, type CourseSection, type LessonExportsConfig, type NormalizedDisclosureDefaults, type NormalizedLessonExports, coursePartsOf, normalizeDisclosureDefaults, normalizeLessonExports };
1
+ export { s as BLOCK_LABELS_DEFAULT, B as BlockLabels, a as CourseAbbreviations, t as CourseAbout, i as CourseAccents, u as CourseAuthor, C as CourseConfig, f as CourseConventions, v as CourseDisclosure, w as CourseHeadingDisclosure, x as CourseNumbering, y as CourseOpenDefault, g as CourseOperators, z as CoursePart, h as CourseRomanLabels, A as CourseSection, D as DISCLOSURE_DEFAULTS, L as LessonExportsConfig, c as NormalizedDisclosure, b as NormalizedLessonExports, d as NormalizedNumbering, N as NormalizedPartPages, E as coursePartsOf, F as normalizeBlockLabels, G as normalizeDisclosure, H as normalizeLessonExports, I as normalizeNumbering } from '../course-config-Dsnri9Tk.js';
2
+ import '../rules/course-rules.js';
3
+ import '../rules/catalog.js';
@@ -1,9 +1,78 @@
1
- function normalizeDisclosureDefaults(config) {
1
+ const DISCLOSURE_DEFAULTS = {
2
+ sections: { collapsible: false, defaultOpen: true },
3
+ subsections: { collapsible: false, defaultOpen: true },
4
+ knowledgeChecks: { collapsible: true, defaultOpen: true },
5
+ notation: { defaultOpen: false },
6
+ references: { defaultOpen: false },
7
+ memos: { defaultOpen: false },
8
+ folds: { defaultOpen: false },
9
+ figures: { defaultOpen: true },
10
+ workedExamples: { defaultOpen: false },
11
+ tables: { truncateAfter: 6 }
12
+ };
13
+ function normalizeDisclosure(config) {
14
+ const disclosure = config.disclosure ?? {};
15
+ if ("diagrams" in disclosure) {
16
+ throw new Error(
17
+ "CourseConfig disclosure.diagrams is gone: a diagram no longer folds by itself. Delete the key; to let a reader fold a diagram away, wrap it in a <Fold> or put it in a collapsible section."
18
+ );
19
+ }
20
+ const heading = (key) => ({
21
+ collapsible: disclosure[key]?.collapsible ?? DISCLOSURE_DEFAULTS[key].collapsible,
22
+ defaultOpen: disclosure[key]?.defaultOpen ?? DISCLOSURE_DEFAULTS[key].defaultOpen
23
+ });
24
+ const open = (key) => ({
25
+ defaultOpen: disclosure[key]?.defaultOpen ?? DISCLOSURE_DEFAULTS[key].defaultOpen
26
+ });
27
+ const truncateAfter = disclosure.tables?.truncateAfter ?? DISCLOSURE_DEFAULTS.tables.truncateAfter;
28
+ if (!Number.isInteger(truncateAfter) || truncateAfter < 2) {
29
+ throw new Error(
30
+ `CourseConfig disclosure.tables.truncateAfter must be a whole number of rows, at least 2; received ${JSON.stringify(truncateAfter)}.`
31
+ );
32
+ }
33
+ return {
34
+ sections: heading("sections"),
35
+ subsections: heading("subsections"),
36
+ knowledgeChecks: heading("knowledgeChecks"),
37
+ notation: open("notation"),
38
+ references: open("references"),
39
+ memos: open("memos"),
40
+ folds: open("folds"),
41
+ figures: open("figures"),
42
+ workedExamples: open("workedExamples"),
43
+ tables: { truncateAfter }
44
+ };
45
+ }
46
+ function normalizeNumbering(config) {
47
+ const numbering = config.numbering ?? {};
48
+ const depth = numbering.sections?.depth ?? 4;
49
+ if (!Number.isInteger(depth) || depth < 2 || depth > 6) {
50
+ throw new Error(
51
+ `CourseConfig numbering.sections.depth must be a heading level from 2 (##) to 6 (######); received ${JSON.stringify(depth)}.`
52
+ );
53
+ }
54
+ const floats = numbering.floats ?? "chapter";
55
+ if (floats !== "chapter" && floats !== "part") {
56
+ throw new Error(
57
+ `CourseConfig numbering.floats must be "chapter" or "part"; received ${JSON.stringify(floats)}.`
58
+ );
59
+ }
2
60
  return {
3
- notation: config.disclosureDefaults?.notation === true,
4
- references: config.disclosureDefaults?.references === true
61
+ sections: { show: numbering.sections?.show !== false, depth },
62
+ floats,
63
+ aliases: numbering.aliases !== false
5
64
  };
6
65
  }
66
+ const BLOCK_LABELS_DEFAULT = "icon-word";
67
+ function normalizeBlockLabels(config) {
68
+ const labels = config.blockLabels ?? BLOCK_LABELS_DEFAULT;
69
+ if (labels !== "icon" && labels !== "icon-word") {
70
+ throw new Error(
71
+ `CourseConfig blockLabels must be "icon" or "icon-word"; received ${JSON.stringify(labels)}.`
72
+ );
73
+ }
74
+ return labels;
75
+ }
7
76
  function normalizeLessonExports(config) {
8
77
  const standaloneHtml = config.lessonExports?.standaloneHtml === true;
9
78
  const print = config.lessonExports?.print === true;
@@ -40,7 +109,11 @@ function coursePartsOf(config) {
40
109
  return parts;
41
110
  }
42
111
  export {
112
+ BLOCK_LABELS_DEFAULT,
113
+ DISCLOSURE_DEFAULTS,
43
114
  coursePartsOf,
44
- normalizeDisclosureDefaults,
45
- normalizeLessonExports
115
+ normalizeBlockLabels,
116
+ normalizeDisclosure,
117
+ normalizeLessonExports,
118
+ normalizeNumbering
46
119
  };
@@ -1,7 +1,9 @@
1
1
  import { Manifest } from '../manifest.js';
2
2
  import '../../curriculum/validation.js';
3
3
  import '../../reference/consistency.js';
4
- import '../course-config.js';
4
+ import '../../course-config-Dsnri9Tk.js';
5
+ import '../../rules/catalog.js';
6
+ import '../../rules/course-rules.js';
5
7
  import '../collections.js';
6
8
  import '../../reference/types.js';
7
9
  import '../../reference/lint-ignore.js';
@@ -10,11 +12,14 @@ import '../../reference/tables-validate.js';
10
12
  import '../../reference/keyed-float-validate.js';
11
13
  import '../../reference/figures-validate.js';
12
14
  import '../../reference/diagrams-validate.js';
15
+ import '../../reference/examples-validate.js';
16
+ import '../../reference/folds-validate.js';
13
17
  import '../../reference/knowledge-checks-validate.js';
14
18
  import '../../reference/raw-floats-validate.js';
15
19
  import '../../reference/gate-math.js';
16
20
  import '../../reference/mixed-content.js';
17
21
  import '../../reference/gloss.js';
22
+ import '../../rules/waivers.js';
18
23
  import '../knowledge-version.js';
19
24
  import '../lesson-derivation.js';
20
25
 
@@ -61,7 +61,7 @@ function resolveKnowledgeVersion(options) {
61
61
  if (!latest) {
62
62
  warn(
63
63
  "knowledge-changelog-missing",
64
- `${file} has no released \`## [x.y.z]\` entry \u2014 only \`## [Unreleased]\`. Cut a release: move it to \`## [${declaredVersion}] - <date>\` (rule C4).`
64
+ `${file} has no released \`## [x.y.z]\` entry \u2014 only \`## [Unreleased]\`. Cut a release: move it to \`## [${declaredVersion}] - <date>\` (rule C3).`
65
65
  );
66
66
  return { version: declaredVersion, diagnostics };
67
67
  }
@@ -68,22 +68,39 @@ declare function mergeTrackOrder(tracks: readonly TrackLike[]): string[];
68
68
  interface SidebarSection {
69
69
  readonly dir: string;
70
70
  readonly label: string;
71
+ readonly overviewLabel?: string;
72
+ /**
73
+ * Href of this part's overview page (`/<dir>/`), set only when the part has
74
+ * one. It becomes the group's first item, so the page a part directory
75
+ * resolves to is reachable from the navigation that names the part.
76
+ */
77
+ readonly overviewLink?: string;
71
78
  }
72
- type SidebarGroup = {
73
- readonly label: string;
74
- readonly items: readonly string[];
75
- } | {
79
+ /**
80
+ * One sidebar entry: a lesson slug, or an explicit link. `attrs` is Starlight's
81
+ * own passthrough onto the rendered `<a>` — the engine uses it to mark a part's
82
+ * overview row so CSS can give it its own icon.
83
+ */
84
+ type SidebarItem = string | {
76
85
  readonly label: string;
77
- readonly items: readonly {
78
- readonly label: string;
79
- readonly link: string;
80
- }[];
86
+ readonly link: string;
87
+ readonly attrs?: Readonly<Record<string, string>>;
81
88
  };
89
+ interface SidebarGroup {
90
+ readonly label: string;
91
+ readonly items: readonly SidebarItem[];
92
+ }
93
+ /** Marks the overview row so `global.css` can give it its own icon. */
94
+ declare const PART_OVERVIEW_CLASS = "explico-part-overview";
82
95
  /**
83
96
  * The Starlight `sidebar` config: one group per section, lessons ordered by the
84
97
  * merged track order (ties broken by slug), then the static Reference group.
85
98
  * Replaces seven `autogenerate` blocks that read an authored `sidebar.order`.
99
+ * `floatIndex`: the course has a top-level "Figures and tables" page
100
+ * (`figures-and-tables.mdx`, `FloatIndex.astro`), listed in Reference.
86
101
  */
87
- declare function buildSidebar(tracks: readonly TrackLike[], lessonSlugs: readonly string[], parts: readonly SidebarSection[]): SidebarGroup[];
102
+ declare function buildSidebar(tracks: readonly TrackLike[], lessonSlugs: readonly string[], parts: readonly SidebarSection[], { floatIndex }?: {
103
+ readonly floatIndex?: boolean;
104
+ }): SidebarGroup[];
88
105
 
89
- export { type SidebarGroup, type SidebarSection, buildSidebar, citedSourceIds, deriveRequires, deriveSources, isLessonSlug, lessonIdFromSlug, mergeTrackOrder, parseCheckList };
106
+ export { PART_OVERVIEW_CLASS, type SidebarGroup, type SidebarItem, type SidebarSection, buildSidebar, citedSourceIds, deriveRequires, deriveSources, isLessonSlug, lessonIdFromSlug, mergeTrackOrder, parseCheckList };
@@ -59,27 +59,42 @@ function mergeTrackOrder(tracks) {
59
59
  }
60
60
  return ordered;
61
61
  }
62
- function buildSidebar(tracks, lessonSlugs, parts) {
62
+ const PART_OVERVIEW_CLASS = "explico-part-overview";
63
+ function buildSidebar(tracks, lessonSlugs, parts, { floatIndex = false } = {}) {
63
64
  const rank = new Map(
64
65
  mergeTrackOrder(tracks).map((lessonId, index) => [lessonId, index])
65
66
  );
66
67
  const positionOf = (slug) => rank.get(lessonIdFromSlug(slug)) ?? Number.POSITIVE_INFINITY;
67
- const groups = parts.map(({ dir, label }) => ({
68
- label,
69
- items: lessonSlugs.filter((slug) => slug.startsWith(`${dir}/`)).sort(
70
- (left, right) => positionOf(left) - positionOf(right) || left.localeCompare(right)
71
- )
72
- }));
68
+ const groups = parts.map(
69
+ ({ dir, label, overviewLabel, overviewLink }) => {
70
+ const chapters = lessonSlugs.filter((slug) => slug.startsWith(`${dir}/`)).sort(
71
+ (left, right) => positionOf(left) - positionOf(right) || left.localeCompare(right)
72
+ );
73
+ return {
74
+ label,
75
+ items: overviewLink ? [
76
+ {
77
+ label: overviewLabel ?? "Overview",
78
+ link: overviewLink,
79
+ attrs: { class: PART_OVERVIEW_CLASS }
80
+ },
81
+ ...chapters
82
+ ] : chapters
83
+ };
84
+ }
85
+ );
73
86
  groups.push({
74
87
  label: "Reference",
75
88
  items: [
76
89
  { label: "Curriculum map", link: "/curriculum-map/" },
77
- { label: "Notation glossary", link: "/glossary/" }
90
+ { label: "Notation glossary", link: "/glossary/" },
91
+ ...floatIndex ? [{ label: "Figures and tables", link: "/figures-and-tables/" }] : []
78
92
  ]
79
93
  });
80
94
  return groups;
81
95
  }
82
96
  export {
97
+ PART_OVERVIEW_CLASS,
83
98
  buildSidebar,
84
99
  citedSourceIds,
85
100
  deriveRequires,
@@ -98,7 +98,10 @@ interface RunLog {
98
98
  * `[code] file:line:column: message`, matching what the console has always
99
99
  * printed, with ` (eq:<key> -> <href>)` appended when the finding belongs to a
100
100
  * keyed equation — so a size-only finding inside a long `aligned` block names
101
- * the result it is about, not just its coordinates.
101
+ * the result it is about, not just its coordinates. A code owned by a lettered
102
+ * rule is prefixed with that rule's ID (`[N9 prose-notation]`), so the line
103
+ * names the rule page to read; an invariant's code stands alone, and a course
104
+ * rule's code *is* its ID (`[X1]`), so it is not repeated.
102
105
  */
103
106
  declare function diagnosticLine(diagnostic: AnyDiagnostic): string;
104
107
  interface RunLogOptions {
@@ -7,6 +7,7 @@ import {
7
7
  writeFileSync
8
8
  } from "node:fs";
9
9
  import { join, relative } from "node:path";
10
+ import { ruleIdOf } from "../rules/catalog.js";
10
11
  const REPOSITORY_ROOT = process.cwd();
11
12
  const LOGS_DIR = join(REPOSITORY_ROOT, "build", "logs");
12
13
  const LEVELS = ["ERROR", "WARNING", "INFO"];
@@ -37,7 +38,9 @@ function formatRecord(level, source, message, date) {
37
38
  function diagnosticLine(diagnostic) {
38
39
  const code = diagnostic.code ?? diagnostic.kind;
39
40
  const at = [diagnostic.file, diagnostic.line, diagnostic.column].filter((part) => part !== void 0).join(":");
40
- const prefix = code === void 0 ? "" : `[${code}] `;
41
+ const owner = code === void 0 ? void 0 : ruleIdOf(code);
42
+ const rule = owner === void 0 || owner === code ? "" : `${owner} `;
43
+ const prefix = code === void 0 ? "" : `[${rule}${code}] `;
41
44
  const equation = diagnostic.equation === void 0 ? "" : ` (eq:${diagnostic.equation.key} -> ${diagnostic.equation.href})`;
42
45
  return at === "" ? `${prefix}${diagnostic.message}${equation}` : `${prefix}${at}: ${diagnostic.message}${equation}`;
43
46
  }