explico 0.12.0 → 0.13.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.
- package/CHANGELOG.md +1137 -1
- package/README.md +91 -13
- package/dist/compiler/astro.d.ts +4 -3
- package/dist/compiler/astro.js +45 -15
- package/dist/compiler/cli.d.ts +26 -12
- package/dist/compiler/cli.js +96 -25
- package/dist/compiler/collections.d.ts +9 -1
- package/dist/compiler/collections.js +55 -16
- package/dist/compiler/content-schema.d.ts +31 -0
- package/dist/compiler/content-schema.js +82 -0
- package/dist/compiler/content-schemas.d.ts +422 -0
- package/dist/compiler/content-schemas.js +229 -0
- package/dist/compiler/course-config.d.ts +1 -1
- package/dist/compiler/course-config.js +30 -2
- package/dist/compiler/exports/combined-html.d.ts +97 -0
- package/dist/compiler/exports/combined-html.js +492 -0
- package/dist/compiler/exports/download-index.d.ts +9 -0
- package/dist/compiler/exports/download-index.js +33 -0
- package/dist/compiler/exports/export-chapters.d.ts +98 -0
- package/dist/compiler/exports/export-chapters.js +164 -0
- package/dist/compiler/exports/export-pages.d.ts +48 -0
- package/dist/compiler/exports/export-pages.js +22 -0
- package/dist/compiler/exports/html-tree.d.ts +22 -0
- package/dist/compiler/exports/html-tree.js +47 -0
- package/dist/compiler/exports/latex/capture.d.ts +106 -0
- package/dist/compiler/exports/latex/capture.js +435 -0
- package/dist/compiler/exports/latex/compile.d.ts +73 -0
- package/dist/compiler/exports/latex/compile.js +115 -0
- package/dist/compiler/exports/latex/document.d.ts +102 -0
- package/dist/compiler/exports/latex/document.js +349 -0
- package/dist/compiler/exports/latex/explico.cls +415 -0
- package/dist/compiler/exports/latex/numbering.d.ts +18 -0
- package/dist/compiler/exports/latex/numbering.js +57 -0
- package/dist/compiler/exports/latex/serialize.d.ts +112 -0
- package/dist/compiler/exports/latex/serialize.js +606 -0
- package/dist/compiler/exports/latex-export.d.ts +44 -0
- package/dist/compiler/exports/latex-export.js +169 -0
- package/dist/compiler/exports/markdown/serialize.d.ts +51 -0
- package/dist/compiler/exports/markdown/serialize.js +527 -0
- package/dist/compiler/exports/markdown-export.d.ts +39 -0
- package/dist/compiler/exports/markdown-export.js +240 -0
- package/dist/compiler/exports/standalone-html.d.ts +14 -5
- package/dist/compiler/exports/standalone-html.js +23 -51
- package/dist/compiler/exports/static-tree.d.ts +253 -0
- package/dist/compiler/exports/static-tree.js +625 -0
- package/dist/compiler/exports/zip.d.ts +16 -0
- package/dist/compiler/exports/zip.js +72 -0
- package/dist/compiler/lesson-derivation.d.ts +8 -2
- package/dist/compiler/lesson-derivation.js +6 -7
- package/dist/compiler/manifest.d.ts +87 -6
- package/dist/compiler/manifest.js +174 -31
- package/dist/compiler/render-diagnostics.d.ts +65 -0
- package/dist/compiler/render-diagnostics.js +56 -0
- package/dist/compiler/resolution-report.d.ts +2 -1
- package/dist/{course-config-Dsnri9Tk.d.ts → course-config-rRtME5UV.d.ts} +56 -13
- package/dist/curriculum/validation.d.ts +9 -3
- package/dist/curriculum/validation.js +35 -17
- package/dist/reference/base-abbreviations.d.mts +2 -2
- package/dist/reference/base-abbreviations.mjs +2 -2
- package/dist/reference/base-operators.d.mts +2 -2
- package/dist/reference/base-operators.mjs +2 -2
- package/dist/reference/base-roman-labels.d.mts +4 -3
- package/dist/reference/base-roman-labels.mjs +4 -3
- package/dist/reference/citation-format.d.mts +35 -0
- package/dist/reference/citation-format.mjs +74 -0
- package/dist/reference/consistency.d.ts +5 -9
- package/dist/reference/consistency.js +34 -38
- package/dist/reference/curriculum-alignment.js +3 -24
- package/dist/reference/derived-entries.d.ts +45 -0
- package/dist/reference/derived-entries.js +50 -0
- package/dist/reference/derived-notation.d.mts +125 -0
- package/dist/reference/derived-notation.mjs +121 -0
- package/dist/reference/diagram-fit.d.ts +45 -0
- package/dist/reference/diagram-fit.js +54 -0
- package/dist/reference/diagram-layout.d.ts +59 -10
- package/dist/reference/diagram-layout.js +85 -24
- package/dist/reference/diagrams-validate.d.ts +1 -1
- package/dist/reference/equations-validate.d.ts +1 -1
- package/dist/reference/equations-validate.js +26 -1
- package/dist/reference/equations.d.mts +27 -0
- package/dist/reference/equations.mjs +120 -22
- package/dist/reference/examples-validate.d.ts +1 -1
- package/dist/reference/figure-fit.d.ts +70 -0
- package/dist/reference/figure-fit.js +60 -0
- package/dist/reference/figure-pictures.d.ts +27 -0
- package/dist/reference/figure-pictures.js +49 -0
- package/dist/reference/figures-validate.d.ts +1 -1
- package/dist/reference/gate-abbreviations.d.ts +1 -1
- package/dist/reference/gate-abbreviations.js +1 -1
- package/dist/reference/gate-course-rules.d.ts +4 -3
- package/dist/reference/gate-course-rules.js +9 -4
- package/dist/reference/gate-heading-length.d.ts +2 -0
- package/dist/reference/gate-heading-length.js +7 -5
- package/dist/reference/gate-heading-structure.js +26 -0
- package/dist/reference/gate-indices.d.ts +35 -0
- package/dist/reference/gate-indices.js +299 -0
- package/dist/reference/gate-math.d.ts +32 -2
- package/dist/reference/gate-math.js +68 -12
- package/dist/reference/gate-mdx-expression.d.ts +17 -0
- package/dist/reference/gate-mdx-expression.js +29 -0
- package/dist/reference/gate-part-pages.d.ts +1 -1
- package/dist/reference/gate-prop-text.d.ts +28 -0
- package/dist/reference/gate-prop-text.js +106 -0
- package/dist/reference/gate-prose-notation.d.ts +3 -1
- package/dist/reference/gate-prose-notation.js +4 -2
- package/dist/reference/gate-retired-keys.d.ts +35 -0
- package/dist/reference/gate-retired-keys.js +58 -0
- package/dist/reference/gloss.d.ts +2 -0
- package/dist/reference/katex-measure.d.ts +17 -0
- package/dist/reference/katex-measure.js +223 -0
- package/dist/reference/keyed-float-validate.js +12 -0
- package/dist/reference/keyed-jsx-floats.d.mts +2 -2
- package/dist/reference/keyed-jsx-floats.mjs +11 -14
- package/dist/reference/lab-math-scope.d.ts +1 -0
- package/dist/reference/lab-math-scope.js +13 -2
- package/dist/reference/math-glyphs.d.mts +94 -2
- package/dist/reference/math-glyphs.mjs +851 -46
- package/dist/reference/mixed-content.d.ts +8 -3
- package/dist/reference/mixed-content.js +4 -2
- package/dist/reference/page-notation.d.ts +34 -4
- package/dist/reference/page-notation.js +54 -2
- package/dist/reference/references.d.ts +11 -1
- package/dist/reference/references.js +6 -0
- package/dist/reference/registry.js +104 -10
- package/dist/reference/rehype-fail-katex-errors.d.mts +9 -0
- package/dist/reference/rehype-fail-katex-errors.mjs +19 -0
- package/dist/reference/rehype-heading-anchors.mjs +11 -1
- package/dist/reference/remark-citation.mjs +0 -0
- package/dist/reference/remark-notation.mjs +84 -20
- package/dist/reference/render-lab-math.d.ts +2 -0
- package/dist/reference/render-lab-math.js +17 -5
- package/dist/reference/sections-validate.d.ts +28 -3
- package/dist/reference/sections-validate.js +31 -4
- package/dist/reference/sections.d.mts +24 -6
- package/dist/reference/sections.mjs +92 -17
- package/dist/reference/tables-validate.d.ts +1 -1
- package/dist/reference/tables-validate.js +24 -1
- package/dist/reference/text-measure.d.ts +10 -0
- package/dist/reference/text-measure.js +41 -0
- package/dist/reference/text-widths.d.ts +10 -0
- package/dist/reference/text-widths.js +1238 -0
- package/dist/reference/types.d.ts +64 -8
- package/dist/rules/catalog.js +191 -30
- package/dist/rules/in-effect.d.ts +1 -1
- package/dist/rules/rules.schema.json +79 -24
- package/dist/rules/settings.d.ts +1 -1
- package/dist/rules/settings.js +7 -0
- package/dist/session/PreferenceStore.d.ts +18 -1
- package/dist/session/PreferenceStore.js +29 -1
- package/docs/authoring/README.md +32 -21
- package/docs/authoring/agents.md +38 -7
- package/docs/authoring/components.md +111 -6
- package/docs/authoring/migrating.md +707 -0
- package/docs/authoring/notation.md +281 -29
- package/docs/authoring/retired.md +1 -0
- package/docs/authoring/structure-rules.md +10 -41
- package/docs/authoring/structure.md +53 -2
- package/docs/authoring/visualizations.md +144 -18
- package/package.json +12 -7
- package/src/compiler/astro.ts +57 -17
- package/src/compiler/cli.ts +143 -35
- package/src/compiler/collections.ts +92 -19
- package/src/compiler/content-schema.ts +108 -0
- package/src/compiler/content-schemas.ts +391 -0
- package/src/compiler/course-config.ts +86 -15
- package/src/compiler/exports/combined-html.ts +669 -0
- package/src/compiler/exports/download-index.ts +36 -0
- package/src/compiler/exports/export-chapters.ts +233 -0
- package/src/compiler/exports/export-pages.ts +44 -0
- package/src/compiler/exports/html-tree.ts +62 -0
- package/src/compiler/exports/latex/capture.ts +651 -0
- package/src/compiler/exports/latex/compile.ts +168 -0
- package/src/compiler/exports/latex/document.ts +479 -0
- package/src/compiler/exports/latex/explico.cls +415 -0
- package/src/compiler/exports/latex/numbering.ts +74 -0
- package/src/compiler/exports/latex/serialize.ts +787 -0
- package/src/compiler/exports/latex/texlive-packages.txt +76 -0
- package/src/compiler/exports/latex-export.ts +255 -0
- package/src/compiler/exports/markdown/serialize.ts +632 -0
- package/src/compiler/exports/markdown-export.ts +329 -0
- package/src/compiler/exports/standalone-html.ts +39 -70
- package/src/compiler/exports/static-tree.ts +944 -0
- package/src/compiler/exports/zip.ts +88 -0
- package/src/compiler/lesson-derivation.ts +13 -8
- package/src/compiler/manifest.ts +299 -28
- package/src/compiler/render-diagnostics.ts +111 -0
- package/src/components/HoverPanel.astro +204 -6
- package/src/components/PartOverview.astro +12 -9
- package/src/components/abbreviation/AbbreviationLayer.astro +21 -12
- package/src/components/assessments/AssessmentRunner.tsx +7 -1
- package/src/components/assessments/AssessmentSet.astro +14 -1
- package/src/components/block-heading.ts +38 -0
- package/src/components/card-arrow.ts +18 -4
- package/src/components/card-carry.ts +406 -0
- package/src/components/card-drag.ts +1 -30
- package/src/components/card-fetch.ts +87 -0
- package/src/components/card-manager.ts +1222 -38
- package/src/components/card-memory.ts +5 -1
- package/src/components/card-placement.ts +211 -13
- package/src/components/card-side.ts +281 -31
- package/src/components/citation/CitationLayer.astro +45 -40
- package/src/components/diagram/Diagram.astro +123 -44
- package/src/components/figure/Figure.astro +11 -0
- package/src/components/figure/FloatCaption.astro +4 -17
- package/src/components/float-toolbar.ts +274 -0
- package/src/components/memo/Memo.astro +21 -10
- package/src/components/memo/ShortNote.astro +4 -0
- package/src/components/notation/NotationGlossary.astro +22 -17
- package/src/components/notation/NotationLayer.astro +321 -79
- package/src/components/notation/NotationMath.astro +8 -1
- package/src/components/notation/render-notation-math.ts +51 -5
- package/src/components/readable-text.ts +25 -0
- package/src/components/reference/FloatRefLayer.astro +162 -89
- package/src/components/starlight/HeadingAnchorEnhancer.astro +13 -8
- package/src/components/starlight/KeyedFloatEnhancer.astro +28 -9
- package/src/components/starlight/LayoutPageSidebar.astro +17 -3
- package/src/components/starlight/LayoutSocialIcons.astro +79 -29
- package/src/components/starlight/LessonExportActions.astro +384 -310
- package/src/components/starlight/LessonFooter.astro +47 -9
- package/src/components/starlight/PrintController.astro +28 -0
- package/src/components/starlight/TextSizeControl.astro +137 -0
- package/src/components/starlight/print-controller.ts +380 -0
- package/src/components/starlight/section-summary.ts +13 -5
- package/src/components/table/Table.astro +13 -21
- package/src/components/table/table-truncation.ts +15 -0
- package/src/content-config.ts +20 -312
- package/src/curriculum/validation.ts +72 -24
- package/src/reference/base-abbreviations.mjs +2 -2
- package/src/reference/base-operators.mjs +2 -2
- package/src/reference/base-roman-labels.mjs +4 -3
- package/src/reference/citation-format.mjs +74 -0
- package/src/reference/consistency.ts +47 -61
- package/src/reference/curriculum-alignment.ts +4 -41
- package/src/reference/derived-entries.ts +68 -0
- package/src/reference/derived-notation.mjs +121 -0
- package/src/reference/diagram-fit.ts +104 -0
- package/src/reference/diagram-layout.ts +182 -51
- package/src/reference/diagrams-validate.ts +2 -1
- package/src/reference/equations-validate.ts +41 -2
- package/src/reference/equations.mjs +120 -22
- package/src/reference/examples-validate.ts +1 -0
- package/src/reference/figure-fit.ts +139 -0
- package/src/reference/figure-pictures.ts +96 -0
- package/src/reference/figures-validate.ts +2 -1
- package/src/reference/gate-abbreviations.ts +1 -1
- package/src/reference/gate-course-rules.ts +22 -7
- package/src/reference/gate-heading-length.ts +25 -7
- package/src/reference/gate-heading-structure.ts +40 -1
- package/src/reference/gate-indices.ts +470 -0
- package/src/reference/gate-math.ts +102 -13
- package/src/reference/gate-mdx-expression.ts +45 -0
- package/src/reference/gate-prop-text.ts +145 -0
- package/src/reference/gate-prose-notation.ts +19 -5
- package/src/reference/gate-retired-keys.ts +101 -0
- package/src/reference/gloss.ts +2 -0
- package/src/reference/katex-measure.ts +384 -0
- package/src/reference/keyed-float-validate.ts +22 -0
- package/src/reference/keyed-jsx-floats.mjs +11 -14
- package/src/reference/lab-math-scope.ts +15 -1
- package/src/reference/math-glyphs.mjs +851 -46
- package/src/reference/mixed-content.ts +11 -2
- package/src/reference/page-notation.ts +100 -3
- package/src/reference/references.ts +14 -0
- package/src/reference/registry.ts +154 -8
- package/src/reference/rehype-fail-katex-errors.mjs +19 -0
- package/src/reference/rehype-heading-anchors.mjs +11 -1
- package/src/reference/remark-citation.mjs +0 -0
- package/src/reference/remark-notation.mjs +84 -20
- package/src/reference/render-lab-math.ts +29 -5
- package/src/reference/sections-validate.ts +67 -3
- package/src/reference/sections.mjs +92 -17
- package/src/reference/tables-validate.ts +40 -2
- package/src/reference/text-measure.ts +63 -0
- package/src/reference/text-widths.ts +133 -0
- package/src/reference/types.ts +75 -8
- package/src/rules/catalog.ts +205 -29
- package/src/rules/settings.ts +10 -0
- package/src/session/PreferenceStore.ts +53 -0
- package/src/styles/global.css +291 -75
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Advance widths of DejaVu Sans (Version 2.37), in font units.
|
|
3
|
+
* Generated by `scripts/gen-text-widths.mjs` — do not edit by hand.
|
|
4
|
+
* `-1` marks a code point the font has no glyph for.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const UNITS_PER_EM = 2048;
|
|
8
|
+
|
|
9
|
+
/** `[first code point, widths of it and the code points after it]`. */
|
|
10
|
+
export const WIDTH_BLOCKS: readonly (readonly [number, readonly number[]])[] = [
|
|
11
|
+
// Basic Latin
|
|
12
|
+
[
|
|
13
|
+
0x0020,
|
|
14
|
+
[
|
|
15
|
+
651, 821, 942, 1716, 1303, 1946, 1597, 563, 799, 799, 1024, 1716, 651, 739, 651, 690,
|
|
16
|
+
1303, 1303, 1303, 1303, 1303, 1303, 1303, 1303, 1303, 1303, 690, 690, 1716, 1716, 1716, 1087,
|
|
17
|
+
2048, 1401, 1405, 1430, 1577, 1294, 1178, 1587, 1540, 604, 604, 1343, 1141, 1767, 1532, 1612,
|
|
18
|
+
1235, 1612, 1423, 1300, 1251, 1499, 1401, 2025, 1403, 1251, 1403, 799, 690, 799, 1716, 1024,
|
|
19
|
+
1024, 1255, 1300, 1126, 1300, 1260, 721, 1300, 1298, 569, 569, 1186, 569, 1995, 1298, 1253,
|
|
20
|
+
1300, 1300, 842, 1067, 803, 1298, 1212, 1675, 1212, 1212, 1075, 1303, 690, 1303, 1716,
|
|
21
|
+
],
|
|
22
|
+
],
|
|
23
|
+
// Latin-1 Supplement, Latin Extended-A
|
|
24
|
+
[
|
|
25
|
+
0x00a0,
|
|
26
|
+
[
|
|
27
|
+
651, 821, 1303, 1303, 1303, 1303, 690, 1024, 1024, 2048, 965, 1253, 1716, 739, 2048, 1024,
|
|
28
|
+
1024, 1716, 821, 821, 1024, 1303, 1303, 651, 1024, 821, 965, 1253, 1985, 1985, 1985, 1087,
|
|
29
|
+
1401, 1401, 1401, 1401, 1401, 1401, 1995, 1430, 1294, 1294, 1294, 1294, 604, 604, 604, 604,
|
|
30
|
+
1587, 1532, 1612, 1612, 1612, 1612, 1612, 1716, 1612, 1499, 1499, 1499, 1499, 1251, 1239, 1290,
|
|
31
|
+
1255, 1255, 1255, 1255, 1255, 1255, 2011, 1126, 1260, 1260, 1260, 1260, 569, 569, 569, 569,
|
|
32
|
+
1253, 1298, 1253, 1253, 1253, 1253, 1253, 1716, 1253, 1298, 1298, 1298, 1298, 1212, 1300, 1212,
|
|
33
|
+
1401, 1255, 1401, 1255, 1401, 1255, 1430, 1126, 1430, 1126, 1430, 1126, 1430, 1126, 1577, 1300,
|
|
34
|
+
1587, 1300, 1294, 1260, 1294, 1260, 1294, 1260, 1294, 1260, 1294, 1260, 1587, 1300, 1587, 1300,
|
|
35
|
+
1587, 1300, 1587, 1300, 1540, 1298, 1876, 1423, 604, 569, 604, 569, 604, 569, 604, 569,
|
|
36
|
+
604, 569, 1208, 1138, 604, 569, 1343, 1186, 1186, 1141, 569, 1141, 569, 1141, 768, 1141,
|
|
37
|
+
700, 1151, 582, 1532, 1298, 1532, 1298, 1532, 1298, 1666, 1532, 1298, 1612, 1253, 1612, 1253,
|
|
38
|
+
1612, 1253, 2191, 2095, 1423, 842, 1423, 842, 1423, 842, 1300, 1067, 1300, 1067, 1300, 1067,
|
|
39
|
+
1300, 1067, 1251, 803, 1251, 803, 1251, 803, 1499, 1298, 1499, 1298, 1499, 1298, 1499, 1298,
|
|
40
|
+
1499, 1298, 1499, 1298, 2025, 1675, 1251, 1212, 1251, 1403, 1075, 1403, 1075, 1403, 1075, 721,
|
|
41
|
+
],
|
|
42
|
+
],
|
|
43
|
+
// Greek
|
|
44
|
+
[
|
|
45
|
+
0x0370,
|
|
46
|
+
[
|
|
47
|
+
1340, 1163, 1765, 1326, 570, 570, 1532, 1331, -1, -1, 1024, 1125, 1126, 1125, 690, 604,
|
|
48
|
+
-1, -1, -1, -1, 1024, 1024, 1418, 651, 1528, 1784, 836, -1, 1664, -1, 1689, 1691,
|
|
49
|
+
693, 1401, 1405, 1141, 1401, 1294, 1403, 1540, 1612, 604, 1343, 1401, 1767, 1532, 1294, 1612,
|
|
50
|
+
1540, 1235, -1, 1294, 1251, 1251, 1612, 1403, 1612, 1565, 604, 1251, 1350, 1107, 1298, 693,
|
|
51
|
+
1185, 1350, 1307, 1212, 1253, 1107, 1114, 1298, 1253, 693, 1207, 1212, 1303, 1144, 1142, 1253,
|
|
52
|
+
1233, 1300, 1202, 1298, 1233, 1185, 1351, 1183, 1351, 1715, 693, 1185, 1253, 1185, 1715, 1343,
|
|
53
|
+
1258, 1268, 1431, 1725, 1431, 1351, 1715, 1359, 1612, 1253, 1328, 1202, 1178, 939, 1351, 1351,
|
|
54
|
+
1772, 1285, 1912, 1715, 1553, 1350, 1621, 1259, 1406, 1243, 1572, 1280, 1432, 1253, 1251, 1098,
|
|
55
|
+
1359, 1300, 1126, 569, 1612, 1260, 1260, 1239, 1300, 1430, 1767, 1333, 1300, 1440, 1430, 1440,
|
|
56
|
+
],
|
|
57
|
+
],
|
|
58
|
+
// General Punctuation
|
|
59
|
+
[
|
|
60
|
+
0x2000,
|
|
61
|
+
[
|
|
62
|
+
1024, 2048, 1024, 2048, 675, 512, 342, 1303, 651, 409, 204, 0, 0, 0, 0, 0,
|
|
63
|
+
739, 739, 1303, 1024, 2048, 2048, 1024, 1024, 651, 651, 651, 651, 1061, 1061, 1061, 1061,
|
|
64
|
+
1024, 1024, 1208, 1208, 685, 1367, 2048, 651, 0, 0, 0, 0, 0, 0, 0, 409,
|
|
65
|
+
2748, 3554, 465, 765, 1065, 465, 765, 1065, 694, 819, 819, 1716, 994, 1087, 1024, 1646,
|
|
66
|
+
1646, 512, 2048, 1024, 342, 799, 799, 1888, 1501, 1501, 1018, 1303, 1024, 1024, 1024, 690,
|
|
67
|
+
1646, 1024, 921, 2048, 1646, 1716, 1200, 1358, 1716, 1716, 651, 1633, 1716, 651, 651, 455,
|
|
68
|
+
0, 0, 0, 0, 0, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0,
|
|
69
|
+
],
|
|
70
|
+
],
|
|
71
|
+
// superscripts and subscripts
|
|
72
|
+
[
|
|
73
|
+
0x2070,
|
|
74
|
+
[
|
|
75
|
+
821, 366, -1, -1, 821, 821, 821, 821, 821, 821, 1081, 1081, 1081, 503, 503, 816,
|
|
76
|
+
821, 821, 821, 821, 821, 821, 821, 821, 821, 821, 1081, 1081, 1081, 503, 503, -1,
|
|
77
|
+
802, 854, 847, 909, 854, 828, 872, 340, 1276, 816, 877, 764, 604, -1, -1, -1,
|
|
78
|
+
],
|
|
79
|
+
],
|
|
80
|
+
// currency
|
|
81
|
+
[
|
|
82
|
+
0x20a0,
|
|
83
|
+
[
|
|
84
|
+
1796, 1303, 1303, 1303, 1303, 1995, 1303, 2606, 2199, 2025, 1606, 1303, 1303, 1303, 1303, 2606,
|
|
85
|
+
1303, 1303, 1303, 1303, 1585, 1303, -1, -1, 1303, 1303, 1303, -1, -1, 1303, -1, -1,
|
|
86
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
87
|
+
],
|
|
88
|
+
],
|
|
89
|
+
// letterlike symbols, number forms
|
|
90
|
+
[
|
|
91
|
+
0x2100,
|
|
92
|
+
[
|
|
93
|
+
2086, 2086, 1430, 2300, 1315, 2086, 2185, 1258, 1430, 1949, -1, 2024, 1545, 1740, 1298, 1298,
|
|
94
|
+
962, 1428, 1475, 846, 1675, 1640, 2130, 2048, 1428, 1436, 1612, 1634, 1667, 1622, 1836, 1401,
|
|
95
|
+
2088, 2200, 2048, 1401, 1525, 1183, 1565, 1565, 1262, 693, 1343, 1401, 1610, 1440, 1750, 1212,
|
|
96
|
+
1240, 1610, 1178, 2190, 946, 1526, 1380, 954, 1320, 778, 1896, 2445, 1438, 1490, 1340, 1738,
|
|
97
|
+
1660, 1587, 1141, 1141, 1251, 1677, 1450, 1260, 719, 719, -1, 1597, -1, -1, 1078, -1,
|
|
98
|
+
1985, 1985, 2806, 1985, 1985, 1985, 1985, 1985, 1985, 1985, 1985, 1985, 1985, 1985, 1985, 1163,
|
|
99
|
+
604, 1008, 1412, 1890, 1401, 1889, 2293, 2697, 1879, 1403, 1911, 2317, 1141, 1430, 1577, 1767,
|
|
100
|
+
569, 937, 1305, 1662, 1212, 1661, 2029, 2397, 1677, 1212, 1684, 2052, 569, 1126, 1300, 1995,
|
|
101
|
+
2550, 1577, 2550, 1440, 1125, 1430, -1, -1, -1, 1985, -1, -1, -1, -1, -1, -1,
|
|
102
|
+
],
|
|
103
|
+
],
|
|
104
|
+
// arrows, mathematical operators
|
|
105
|
+
[
|
|
106
|
+
0x2190,
|
|
107
|
+
[
|
|
108
|
+
1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
|
|
109
|
+
1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
|
|
110
|
+
1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
|
|
111
|
+
1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
|
|
112
|
+
1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
|
|
113
|
+
1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
|
|
114
|
+
1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
|
|
115
|
+
1401, 1303, 1059, 1294, 1294, 1784, 1370, 1370, 1784, 1784, 1470, 1784, 1784, 1470, 1303, 1550,
|
|
116
|
+
1550, 1380, 1716, 1716, 1716, 690, 1304, 1716, 1282, 1282, 1305, 1305, 1305, 1463, 1706, 1716,
|
|
117
|
+
1836, 1836, 1716, 1024, 1024, 1024, 1024, 1499, 1499, 1499, 1499, 1067, 1616, 2165, 1067, 1616,
|
|
118
|
+
2165, 1067, 1067, 1067, 1303, 1303, 533, 1303, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
|
|
119
|
+
768, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
|
|
120
|
+
1716, 1716, 1718, 1718, 2048, 2048, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
|
|
121
|
+
1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 2144, 2144, 950, 1716, 1716, 1716,
|
|
122
|
+
1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
|
|
123
|
+
1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1499, 1499, 1499, 1716,
|
|
124
|
+
1716, 1716, 1716, 1598, 1598, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716,
|
|
125
|
+
1716, 1716, 1784, 1784, 1784, 1784, 1066, 1066, 1784, 1784, 1784, 1784, 1784, 1784, 1784, 1784,
|
|
126
|
+
1716, 1716, 1716, 1716, 1716, 1716, 2048, 2048, 1716, 1716, 1066, 1499, 1499, 1499, 1716, 1716,
|
|
127
|
+
1680, 1680, 1680, 1680, 1282, 651, 1282, 1716, 2048, 2048, 2048, 2048, 2048, 1716, 1500, 1500,
|
|
128
|
+
1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 2913, 2913, 1716, 1716, 1716, 1716, 1716, 1716,
|
|
129
|
+
1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 1716, 2048, 2048,
|
|
130
|
+
2048, 2048, 2048, 1784, 1470, 1784, 1784, 1470, 1784, 1784, 2048, 1784, 1470, 1784, 1470, 1784,
|
|
131
|
+
],
|
|
132
|
+
],
|
|
133
|
+
];
|
package/src/reference/types.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export type EditorialStatus = 'draft' | 'in-review' | 'reviewed';
|
|
2
|
-
|
|
3
1
|
export interface SourceSpan {
|
|
4
2
|
readonly file: string;
|
|
5
3
|
readonly line?: number;
|
|
@@ -19,7 +17,13 @@ export type NotationAlignment =
|
|
|
19
17
|
readonly rationale: string;
|
|
20
18
|
};
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Where a reference was written: in prose, in math, in a definition's meaning
|
|
22
|
+
* or body, or in its `formula`. A formula's references bring their cards onto
|
|
23
|
+
* the page but are no dependency: two formulas may name each other
|
|
24
|
+
* (γ = 1 − α, α = 1 − γ).
|
|
25
|
+
*/
|
|
26
|
+
export type NotationReferenceKind = 'prose' | 'math' | 'definition' | 'formula';
|
|
23
27
|
|
|
24
28
|
/**
|
|
25
29
|
* A gloss resolved by the loader (D15). Declared on a card, keyed
|
|
@@ -50,10 +54,17 @@ export interface SharedNotationDefinitionInput {
|
|
|
50
54
|
readonly domain: string;
|
|
51
55
|
readonly formula?: string;
|
|
52
56
|
readonly units?: string;
|
|
57
|
+
/** Rule N23: an index entry's title for what it indexes, `{base} …`. */
|
|
58
|
+
readonly reads?: string;
|
|
59
|
+
/** Rule N23: the set a running index letter runs over. */
|
|
60
|
+
readonly range?: string;
|
|
61
|
+
/** Rule N23: as an index, a fixed label rather than a running position. */
|
|
62
|
+
readonly fixedIndex?: true;
|
|
63
|
+
/** Rule N23: an index entry's `formula` as written, `{base}` unbound. */
|
|
64
|
+
readonly formulaTemplate?: string;
|
|
53
65
|
readonly sources: readonly string[];
|
|
54
66
|
readonly seeAlso: readonly string[];
|
|
55
67
|
readonly alignment: NotationAlignment;
|
|
56
|
-
readonly status: EditorialStatus;
|
|
57
68
|
readonly aiAssisted: boolean;
|
|
58
69
|
readonly body: string;
|
|
59
70
|
/** References harvested from the Markdown body. */
|
|
@@ -70,6 +81,14 @@ export interface LocalNotationDefinitionInput {
|
|
|
70
81
|
readonly summary: string;
|
|
71
82
|
readonly formula?: string;
|
|
72
83
|
readonly units?: string;
|
|
84
|
+
/** Rule N23: an index entry's title for what it indexes, `{base} …`. */
|
|
85
|
+
readonly reads?: string;
|
|
86
|
+
/** Rule N23: the set a running index letter runs over. */
|
|
87
|
+
readonly range?: string;
|
|
88
|
+
/** Rule N23: as an index, a fixed label rather than a running position. */
|
|
89
|
+
readonly fixedIndex?: true;
|
|
90
|
+
/** Rule N23: an index entry's `formula` as written, `{base}` unbound. */
|
|
91
|
+
readonly formulaTemplate?: string;
|
|
73
92
|
readonly sources: readonly string[];
|
|
74
93
|
readonly seeAlso: readonly string[];
|
|
75
94
|
readonly alignment: NotationAlignment;
|
|
@@ -94,7 +113,6 @@ export interface NotationSuspension {
|
|
|
94
113
|
|
|
95
114
|
export interface NotationLessonInput {
|
|
96
115
|
readonly lessonId: string;
|
|
97
|
-
readonly status: EditorialStatus;
|
|
98
116
|
readonly localDefinitions: readonly LocalNotationDefinitionInput[];
|
|
99
117
|
/**
|
|
100
118
|
* Decorations this page suspends (`notation.suspend`, rule N22). Optional
|
|
@@ -144,11 +162,12 @@ export type NotationDiagnosticCode =
|
|
|
144
162
|
| 'undefined-reference'
|
|
145
163
|
| 'reference-cycle'
|
|
146
164
|
| 'unused-definition'
|
|
165
|
+
| 'local-shadows-shared'
|
|
166
|
+
| 'malformed-reference'
|
|
147
167
|
| 'alignment-unknown-competency'
|
|
148
168
|
| 'alignment-unknown-lesson'
|
|
149
169
|
| 'alignment-introduction'
|
|
150
170
|
| 'alignment-unavailable'
|
|
151
|
-
| 'alignment-review-state'
|
|
152
171
|
| 'gloss-collides-with-card';
|
|
153
172
|
|
|
154
173
|
export type DiagnosticSeverity = 'error' | 'warning' | 'info';
|
|
@@ -188,9 +207,16 @@ interface NotationDefinitionRecordBase {
|
|
|
188
207
|
readonly scope: NotationDefinitionScope;
|
|
189
208
|
readonly notation: string;
|
|
190
209
|
readonly label: string;
|
|
210
|
+
/** Rule N23: an index entry's title for what it indexes, `{base} …`. */
|
|
211
|
+
readonly reads?: string;
|
|
212
|
+
/** Rule N23: the set a running index letter runs over. */
|
|
213
|
+
readonly range?: string;
|
|
214
|
+
/** Rule N23: as an index, a fixed label rather than a running position. */
|
|
215
|
+
readonly fixedIndex?: true;
|
|
216
|
+
/** Rule N23: an index entry's `formula` as written, `{base}` unbound. */
|
|
217
|
+
readonly formulaTemplate?: string;
|
|
191
218
|
readonly seeAlso: readonly string[];
|
|
192
219
|
readonly alignment: NotationAlignment;
|
|
193
|
-
readonly status: EditorialStatus;
|
|
194
220
|
readonly source: SourceSpan;
|
|
195
221
|
readonly resolvedReferences: readonly ResolvedNotationReference[];
|
|
196
222
|
}
|
|
@@ -226,7 +252,6 @@ export interface NotationBinding {
|
|
|
226
252
|
|
|
227
253
|
export interface NotationPageBundle {
|
|
228
254
|
readonly lessonId: string;
|
|
229
|
-
readonly status: EditorialStatus;
|
|
230
255
|
readonly source: SourceSpan;
|
|
231
256
|
readonly bindings: readonly NotationBinding[];
|
|
232
257
|
readonly definitionIds: readonly string[];
|
|
@@ -245,3 +270,45 @@ export interface NotationRegistry {
|
|
|
245
270
|
readonly backlinks: readonly NotationBacklink[];
|
|
246
271
|
readonly diagnostics: readonly NotationDiagnostic[];
|
|
247
272
|
}
|
|
273
|
+
|
|
274
|
+
/** A derived card a math source uses (rule N23): `key` is `<base>.sub.<index>`. */
|
|
275
|
+
export interface DerivedUse {
|
|
276
|
+
readonly key: string;
|
|
277
|
+
readonly base: string;
|
|
278
|
+
readonly index: string;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* How one symbol with a subscript is explained (rule N23), as
|
|
283
|
+
* `resolveMathGlyphs` reports it in `indices`.
|
|
284
|
+
*/
|
|
285
|
+
export interface IndexedSymbol {
|
|
286
|
+
readonly token: string;
|
|
287
|
+
readonly start: number;
|
|
288
|
+
readonly end: number;
|
|
289
|
+
readonly base: string;
|
|
290
|
+
readonly index: string;
|
|
291
|
+
readonly how:
|
|
292
|
+
| 'whole-form'
|
|
293
|
+
| 'family'
|
|
294
|
+
| 'derived'
|
|
295
|
+
| 'inside-form'
|
|
296
|
+
| 'explicit'
|
|
297
|
+
| 'swallowed'
|
|
298
|
+
| 'inside-wrap'
|
|
299
|
+
| 'composed'
|
|
300
|
+
| 'unresolved';
|
|
301
|
+
readonly key: string | null;
|
|
302
|
+
readonly explained: boolean;
|
|
303
|
+
readonly baseExplained: boolean;
|
|
304
|
+
/** The parts no card explains: the base first, when it has none, then each slot. */
|
|
305
|
+
readonly unexplained: readonly string[];
|
|
306
|
+
/** Running index letters (`i`, `k`, `t`) in its slots, for the index-set check. */
|
|
307
|
+
readonly running: readonly {
|
|
308
|
+
readonly letter: string;
|
|
309
|
+
readonly start: number;
|
|
310
|
+
readonly end: number;
|
|
311
|
+
readonly key: string | null;
|
|
312
|
+
readonly cover: string | null;
|
|
313
|
+
}[];
|
|
314
|
+
}
|
package/src/rules/catalog.ts
CHANGED
|
@@ -168,6 +168,7 @@ const GATE_MATH: Emitter = { module: 'src/reference/gate-math.ts', fn: 'resolveI
|
|
|
168
168
|
const GLYPHS: Emitter = { module: 'src/reference/math-glyphs.mjs', fn: 'resolveMathGlyphs' };
|
|
169
169
|
const REGISTRY: Emitter = { module: 'src/reference/registry.ts', fn: 'buildNotationRegistry' };
|
|
170
170
|
const KEYED_FLOATS: Emitter = { module: 'src/reference/keyed-float-validate.ts', fn: 'validateKeyedFloats' };
|
|
171
|
+
const INDICES: Emitter = { module: 'src/reference/gate-indices.ts', fn: 'gateIndices' };
|
|
171
172
|
|
|
172
173
|
function consistency(fn: string): Emitter {
|
|
173
174
|
return { module: 'src/reference/consistency.ts', fn };
|
|
@@ -203,6 +204,15 @@ function keyedFloatChecks(): RuleCheck[] {
|
|
|
203
204
|
check(`${prefix}-duplicate-key`, 'error', false, emitter),
|
|
204
205
|
check(`${prefix}-ref-resolves`, 'error', false, emitter),
|
|
205
206
|
);
|
|
207
|
+
// A display block is one numbered equation: a second `\label` in it
|
|
208
|
+
// would name nothing.
|
|
209
|
+
if (prefix === 'eq') {
|
|
210
|
+
out.push(
|
|
211
|
+
check('eq-label-repeated', 'error', false, emitter),
|
|
212
|
+
// LaTeX's `\eqref{eq:key}` in prose, which MDX cannot parse.
|
|
213
|
+
check('eq-latex-ref', 'error', false, emitter),
|
|
214
|
+
);
|
|
215
|
+
}
|
|
206
216
|
if (prefix === 'tab' || prefix === 'fig' || prefix === 'dia' || prefix === 'ex') {
|
|
207
217
|
out.push(check(`${prefix}-key-unused`, 'info', false, emitter));
|
|
208
218
|
// A prop that is gone: a name prop the caption pair (`caption` +
|
|
@@ -212,6 +222,20 @@ function keyedFloatChecks(): RuleCheck[] {
|
|
|
212
222
|
// JSX float; a table never had one to remove.
|
|
213
223
|
out.push(check(`${prefix}-removed-prop`, 'error', false, emitter));
|
|
214
224
|
}
|
|
225
|
+
// A `short={…}` / `caption={…}` the manifest cannot read: a reference's
|
|
226
|
+
// card, a copied link and the float index name the float without it.
|
|
227
|
+
if (prefix !== 'eq' && prefix !== 'check') {
|
|
228
|
+
out.push(check(`${prefix}-unread-prop`, 'warning', false, emitter));
|
|
229
|
+
}
|
|
230
|
+
// A `<Table>` holding a second table, which every export would drop.
|
|
231
|
+
if (prefix === 'tab') {
|
|
232
|
+
out.push(
|
|
233
|
+
check('tab-several-tables', 'error', false, {
|
|
234
|
+
module: 'src/reference/tables-validate.ts',
|
|
235
|
+
fn: 'validateTables',
|
|
236
|
+
}),
|
|
237
|
+
);
|
|
238
|
+
}
|
|
215
239
|
}
|
|
216
240
|
// A worked-example set cannot do without its `id` (its anchor and
|
|
217
241
|
// `[[ex-…]]`) or its `short` title (its heading after the "Example" badge).
|
|
@@ -221,13 +245,18 @@ function keyedFloatChecks(): RuleCheck[] {
|
|
|
221
245
|
fn: 'validateExamples',
|
|
222
246
|
}),
|
|
223
247
|
);
|
|
224
|
-
// A section's key is its heading's anchor, which the slugger makes unique
|
|
225
|
-
//
|
|
248
|
+
// A section's key is its heading's anchor, which the slugger makes unique
|
|
249
|
+
// among headings; the reference can go wrong, and so can an anchor the
|
|
250
|
+
// engine already gives a float, a memo or the References section.
|
|
226
251
|
out.push(
|
|
227
252
|
check('sec-ref-resolves', 'error', true, {
|
|
228
253
|
module: 'src/reference/sections-validate.ts',
|
|
229
254
|
fn: 'validateSectionRefs',
|
|
230
255
|
}),
|
|
256
|
+
check('heading-anchor-collision', 'error', true, {
|
|
257
|
+
module: 'src/reference/sections-validate.ts',
|
|
258
|
+
fn: 'validateHeadingAnchors',
|
|
259
|
+
}),
|
|
231
260
|
);
|
|
232
261
|
// A `<Fold>` is named by its `label`, or by the numbered floats it holds;
|
|
233
262
|
// one with neither has an empty bar.
|
|
@@ -356,7 +385,7 @@ const RULES: readonly RuleEntry[] = [
|
|
|
356
385
|
elements: ['prose', 'assessment', 'table'],
|
|
357
386
|
doc: 'notation.md#n9',
|
|
358
387
|
summary:
|
|
359
|
-
'Never write `45 m/s`, `t (s)`, `vx` or `KE/m` as plain text, and never spell a stated quantity\'s unit out: "4 seconds", "2 meters per second squared", "30 degrees", "$x = 3$ meters" are `$4\\ \\text{s}$`, `$2\\ \\text{m/s}^2$`, `$30^{\\circ}$`, `$x = 3\\ \\text{m}$`. A unit inside math is `\\text{}`-wrapped, short form, in the same span as its number or symbol. A unit named on its own ("measured in meters") stays a word; a sentence that defines a unit is waived. JSX prop strings (`caption="…"`)
|
|
388
|
+
'Never write `45 m/s`, `t (s)`, `vx` or `KE/m` as plain text, and never spell a stated quantity\'s unit out: "4 seconds", "2 meters per second squared", "30 degrees", "$x = 3$ meters" are `$4\\ \\text{s}$`, `$2\\ \\text{m/s}^2$`, `$30^{\\circ}$`, `$x = 3\\ \\text{m}$`. A unit inside math is `\\text{}`-wrapped, short form, in the same span as its number or symbol. A unit named on its own ("measured in meters") stays a word; a sentence that defines a unit is waived. JSX prop strings (`caption="…"`) render no math, so N9 does not apply there; nor does it apply to an assessment choice label, which may still hold math (`$30^{\\circ}$`).',
|
|
360
389
|
checks: [
|
|
361
390
|
check(
|
|
362
391
|
'prose-notation',
|
|
@@ -530,7 +559,7 @@ const RULES: readonly RuleEntry[] = [
|
|
|
530
559
|
elements: ['notation'],
|
|
531
560
|
doc: 'notation.md#n19',
|
|
532
561
|
summary:
|
|
533
|
-
'Every notation entry has `units:` from `units-vocab.ts` (`m/s`, `s`, `kg`, …) or `dimensionless: true
|
|
562
|
+
'Every notation entry has `units:` from `units-vocab.ts` (`m/s`, `s`, `kg`, …) or `dimensionless: true`, except an index entry (`latex: "{}_0"`, N23), which takes neither. A token outside the vocabulary is a warning.',
|
|
534
563
|
checks: [
|
|
535
564
|
check('notation-units', 'warning', false, consistency('checkNotationUnits')),
|
|
536
565
|
check('units-vocab', 'warning', false, consistency('checkNotationUnits')),
|
|
@@ -557,7 +586,7 @@ const RULES: readonly RuleEntry[] = [
|
|
|
557
586
|
elements: ['notation'],
|
|
558
587
|
doc: 'notation.md#n21',
|
|
559
588
|
summary:
|
|
560
|
-
'A gloss `
|
|
589
|
+
'A gloss `name` names the symbol in a few words (“launch angle”); a clause, sentence punctuation, or a definition belongs in a full notation entry instead.',
|
|
561
590
|
checks: [check('gloss-name-shape', 'warning', false, consistency('checkGlossNameShape'))],
|
|
562
591
|
},
|
|
563
592
|
{
|
|
@@ -572,6 +601,7 @@ const RULES: readonly RuleEntry[] = [
|
|
|
572
601
|
'A decoration (`\\hat`, `\\bar`, `\\overline`, `\'`, `^*`, `^\\dagger`, …) is on the course’s `allow` list (shipped empty), explained by an operator entry (`latex: \\hat{}`), or the decorated form has its own entry (`latex: \\hat{\\beta}`), which wins for that form. A page may suspend a decoration in `notation.suspend`, with a `reason`; every decorated form of it there then needs its own entry.',
|
|
573
602
|
checks: [
|
|
574
603
|
check('accent-explained', 'warning', false, consistency('checkAccentExplained')),
|
|
604
|
+
check('accent-swallowed', 'warning', false, consistency('checkAccentExplained')),
|
|
575
605
|
check('suspended-operator-unresolved', 'error', true, GATE_MATH),
|
|
576
606
|
check('operator-suspension-reason', 'warning', false, consistency('checkOperatorSuspension')),
|
|
577
607
|
check('operator-suspended', 'info', false, consistency('checkOperatorSuspension')),
|
|
@@ -579,6 +609,25 @@ const RULES: readonly RuleEntry[] = [
|
|
|
579
609
|
],
|
|
580
610
|
settings: baselineEdits('Decorations'),
|
|
581
611
|
},
|
|
612
|
+
{
|
|
613
|
+
kind: 'rule',
|
|
614
|
+
id: 'N23',
|
|
615
|
+
short: 'An index is part of the symbol: whole form, family or index entry',
|
|
616
|
+
title:
|
|
617
|
+
'An index is part of the symbol: a subscript is explained by the indexed symbol’s entry, a family entry, or an index entry.',
|
|
618
|
+
elements: ['math', 'notation'],
|
|
619
|
+
doc: 'notation.md#n23',
|
|
620
|
+
summary:
|
|
621
|
+
'A subscript on a symbol is explained by the indexed symbol’s own entry (`latex: v_0`), a family entry whose index runs (`latex: x_k` explains `x_1`), or an index entry for the subscript (`latex: "{}_0"`, which composes a derived card); a card on the base alone does not explain it, and arithmetic on an index letter with its own card does (`X_{t-1}`). A running index — a lowercase letter not marked `fixedIndex` — states its set, as `range` on its card or after a `\\quad` on the first display line that uses it. Never wrap an indexed symbol in `\\explain` with a key whose `latex` has no index.',
|
|
622
|
+
checks: [
|
|
623
|
+
check('index-explained', 'error', true, INDICES),
|
|
624
|
+
check('index-swallowed', 'error', true, INDICES),
|
|
625
|
+
check('index-range', 'error', true, INDICES),
|
|
626
|
+
check('derived-key-taken', 'error', true, INDICES),
|
|
627
|
+
],
|
|
628
|
+
unchecked:
|
|
629
|
+
'whether a `\\quad` clause states the set correctly; whether a lowercase index is really running; lab math whose glyph table is a copy of the one `labMathScope` returned.',
|
|
630
|
+
},
|
|
582
631
|
|
|
583
632
|
// ---- V — visualizations -----------------------------------------------------
|
|
584
633
|
{
|
|
@@ -613,12 +662,16 @@ const RULES: readonly RuleEntry[] = [
|
|
|
613
662
|
elements: ['plot'],
|
|
614
663
|
doc: 'visualizations.md#v3',
|
|
615
664
|
summary:
|
|
616
|
-
'An interactive figure is an island under `content/labs/` inside a `<Figure>`, renders its equations through `renderLabMath` (`{ display: false }` for a legend, an axis title or a label; a `{ math }` run for the caption clause) and never KaTeX directly, and labels its controls; the figure’s caption is its name, so the lab writes no accessible name or text alternative of its own.',
|
|
665
|
+
'An interactive figure is an island under `content/labs/` inside a `<Figure>`, renders its equations through `renderLabMath` (`{ display: false }` for a legend, an axis title or a label; a `{ math }` run for the caption clause) and never KaTeX directly, and labels its controls; the figure’s caption is its name, so the lab writes no accessible name or text alternative of its own. Its default picture is drawn at build time too and handed to the island as children, so the built page has it.',
|
|
617
666
|
checks: [
|
|
618
667
|
check('lab-katex-direct', 'error', false, {
|
|
619
668
|
module: 'src/reference/lab-katex-validate.ts',
|
|
620
669
|
fn: 'validateLabKatexImports',
|
|
621
670
|
}),
|
|
671
|
+
check('lab-picture-undrawn', 'warning', false, {
|
|
672
|
+
module: 'src/reference/figure-pictures.ts',
|
|
673
|
+
fn: 'undrawnFigurePictures',
|
|
674
|
+
}),
|
|
622
675
|
],
|
|
623
676
|
unchecked:
|
|
624
677
|
'that a lab labels its controls and writes no name of its own, and math a lab draws without importing `katex` — the build’s rendered check (`figure-symbols.ts`) covers the page it renders.',
|
|
@@ -673,6 +726,57 @@ const RULES: readonly RuleEntry[] = [
|
|
|
673
726
|
},
|
|
674
727
|
],
|
|
675
728
|
},
|
|
729
|
+
{
|
|
730
|
+
kind: 'rule',
|
|
731
|
+
id: 'V7',
|
|
732
|
+
short: 'A figure’s picture fits on one screen',
|
|
733
|
+
title: 'A figure’s picture takes at most `maxPercent` of the screen height.',
|
|
734
|
+
elements: ['plot'],
|
|
735
|
+
doc: 'visualizations.md#v7',
|
|
736
|
+
summary:
|
|
737
|
+
'The default slot of a `<Figure>` — plot, key and tables — stays within `maxPercent` of the viewport height, so the reader sees the picture and its caption line together. A square or tall plot gets a fixed width instead of the full column.',
|
|
738
|
+
checks: [
|
|
739
|
+
check('figure-too-tall', 'warning', false, {
|
|
740
|
+
module: 'src/reference/figure-fit.ts',
|
|
741
|
+
fn: 'checkFigureFit',
|
|
742
|
+
}),
|
|
743
|
+
],
|
|
744
|
+
unchecked:
|
|
745
|
+
'any page or viewport the course’s Playwright suite does not open — the check runs in the browser, not in the build.',
|
|
746
|
+
settings: [
|
|
747
|
+
{
|
|
748
|
+
key: 'maxPercent',
|
|
749
|
+
title: 'Largest picture height (% of screen)',
|
|
750
|
+
description: 'How much of the viewport height a figure’s picture may take.',
|
|
751
|
+
schema: { type: 'integer', minimum: 10, default: 80 },
|
|
752
|
+
},
|
|
753
|
+
],
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
kind: 'rule',
|
|
757
|
+
id: 'V8',
|
|
758
|
+
short: 'A diagram fits the lesson column',
|
|
759
|
+
title: 'A diagram is no wider than the lesson column.',
|
|
760
|
+
elements: ['diagram'],
|
|
761
|
+
doc: 'visualizations.md#v8',
|
|
762
|
+
summary:
|
|
763
|
+
'A `<Diagram>` lays out no wider than `columnWidth`, the lesson column at a 1366px-wide window, so the reader sees the whole graph without scrolling it. Narrow it with `direction="TB"`, a shorter label or a node `width` (its label wraps inside it); `warnAboveWidth={false}` marks a diagram meant to scroll.',
|
|
764
|
+
checks: [
|
|
765
|
+
check('dia-too-wide', 'warning', false, {
|
|
766
|
+
module: 'src/reference/diagram-fit.ts',
|
|
767
|
+
fn: 'oversizedDiagrams',
|
|
768
|
+
}),
|
|
769
|
+
],
|
|
770
|
+
settings: [
|
|
771
|
+
{
|
|
772
|
+
key: 'columnWidth',
|
|
773
|
+
title: 'Column width (px)',
|
|
774
|
+
description:
|
|
775
|
+
'The widest a diagram may lay out: the lesson column at the window width the course is read at most (707px at 1366px).',
|
|
776
|
+
schema: { type: 'integer', minimum: 200, default: 707 },
|
|
777
|
+
},
|
|
778
|
+
],
|
|
779
|
+
},
|
|
676
780
|
|
|
677
781
|
// ---- C — versioning ---------------------------------------------------------
|
|
678
782
|
{
|
|
@@ -838,24 +942,6 @@ const RULES: readonly RuleEntry[] = [
|
|
|
838
942
|
}),
|
|
839
943
|
],
|
|
840
944
|
},
|
|
841
|
-
{
|
|
842
|
-
kind: 'rule',
|
|
843
|
-
id: 'S5',
|
|
844
|
-
short: 'A sign / perspective convention is declared once and cited elsewhere',
|
|
845
|
-
title: 'A sign or perspective convention is declared once and cited everywhere else.',
|
|
846
|
-
elements: ['prose'],
|
|
847
|
-
doc: 'structure-rules.md#s5',
|
|
848
|
-
summary:
|
|
849
|
-
'Prose that states a sign / cash-flow-perspective convention resolves it to the single declaration — the `conventions.signConventionKey` notation entry (`[[key]]`) or the `conventions.cashFlowPerspectiveCompetency` competency — rather than restating it.',
|
|
850
|
-
checks: [
|
|
851
|
-
check(
|
|
852
|
-
'convention-single-definition',
|
|
853
|
-
'warning',
|
|
854
|
-
false,
|
|
855
|
-
consistency('checkConventionSingleDefinition'),
|
|
856
|
-
),
|
|
857
|
-
],
|
|
858
|
-
},
|
|
859
945
|
{
|
|
860
946
|
kind: 'rule',
|
|
861
947
|
id: 'S6',
|
|
@@ -871,6 +957,12 @@ const RULES: readonly RuleEntry[] = [
|
|
|
871
957
|
module: 'src/reference/gate-heading-structure.ts',
|
|
872
958
|
fn: 'gateHeadingStructure',
|
|
873
959
|
}),
|
|
960
|
+
// A knowledge check or a worked-example set, which draws an `<h2>`,
|
|
961
|
+
// inside a memo or a short note.
|
|
962
|
+
check('heading-nested', 'error', true, {
|
|
963
|
+
module: 'src/reference/gate-heading-structure.ts',
|
|
964
|
+
fn: 'gateHeadingStructure',
|
|
965
|
+
}),
|
|
874
966
|
],
|
|
875
967
|
},
|
|
876
968
|
{
|
|
@@ -1111,6 +1203,13 @@ const RETIRED: readonly RetiredRule[] = [
|
|
|
1111
1203
|
into: 'C3',
|
|
1112
1204
|
why: 'The release procedure and the invariant it keeps are one rule, and `knowledge-changelog-missing` (owned by C3) was already the check that fired on a half-finished release.',
|
|
1113
1205
|
},
|
|
1206
|
+
{
|
|
1207
|
+
id: 'S5',
|
|
1208
|
+
title: 'A sign or perspective convention is declared once and cited everywhere else.',
|
|
1209
|
+
date: '2026-10-07',
|
|
1210
|
+
into: 'N4',
|
|
1211
|
+
why: 'Its check knew one finance course’s phrasing and one key per course, and never fired in any course; the `conventions` setting it read is gone. A convention is a definition, so it is now N4’s: defined once on its notation entry, whose `meaning` names the other choice and whose body says how to convert.',
|
|
1212
|
+
},
|
|
1114
1213
|
];
|
|
1115
1214
|
|
|
1116
1215
|
const INVARIANTS: readonly InvariantEntry[] = [
|
|
@@ -1121,7 +1220,7 @@ const INVARIANTS: readonly InvariantEntry[] = [
|
|
|
1121
1220
|
elements: ['notation', 'math'],
|
|
1122
1221
|
doc: 'components.md#reference-systems',
|
|
1123
1222
|
summary:
|
|
1124
|
-
'A `[[key]]` or `\\explain{key}{…}` names an existing entry; a key is kebab-case; a shared entry is defined once;
|
|
1223
|
+
'A `[[key]]` or `\\explain{key}{…}` names an existing entry; a key is kebab-case; a shared entry is defined once; references in meanings and bodies never form a cycle (formulas may name each other).',
|
|
1125
1224
|
checks: [
|
|
1126
1225
|
check('undefined-reference', 'error', false, REGISTRY),
|
|
1127
1226
|
check('invalid-key', 'error', false, REGISTRY, GLYPHS),
|
|
@@ -1137,6 +1236,10 @@ const INVARIANTS: readonly InvariantEntry[] = [
|
|
|
1137
1236
|
}),
|
|
1138
1237
|
check('malformed-explicit-binding', 'error', true, GLYPHS),
|
|
1139
1238
|
check('unused-definition', 'info', false, REGISTRY),
|
|
1239
|
+
// A page-local entry under a shared key: two meanings for one key.
|
|
1240
|
+
check('local-shadows-shared', 'warning', false, REGISTRY),
|
|
1241
|
+
// A `[[` that never closes, before the render fails on it.
|
|
1242
|
+
check('malformed-reference', 'error', false, REGISTRY),
|
|
1140
1243
|
],
|
|
1141
1244
|
},
|
|
1142
1245
|
{
|
|
@@ -1157,6 +1260,11 @@ const INVARIANTS: readonly InvariantEntry[] = [
|
|
|
1157
1260
|
check('ambiguous-base-fallback', 'error', true, GLYPHS),
|
|
1158
1261
|
check('ambiguous-canonical-notation', 'error', false, GLYPHS),
|
|
1159
1262
|
check('math-compile-error', 'error', true, GATE_MATH),
|
|
1263
|
+
// `$5 to $6`: money remark-math reads as one math span.
|
|
1264
|
+
check('currency-dollar', 'error', true, {
|
|
1265
|
+
module: 'src/reference/gate-math.ts',
|
|
1266
|
+
fn: 'gateContentMath',
|
|
1267
|
+
}),
|
|
1160
1268
|
],
|
|
1161
1269
|
},
|
|
1162
1270
|
{
|
|
@@ -1176,7 +1284,7 @@ const INVARIANTS: readonly InvariantEntry[] = [
|
|
|
1176
1284
|
elements: ['changelog'],
|
|
1177
1285
|
doc: 'README.md#amending',
|
|
1178
1286
|
summary:
|
|
1179
|
-
'A `rules.<ID>` block names a live rule; a deprecated top-level key (`operators`, `romanLabels`, `abbreviations`) still works but warns until it is moved under `rules
|
|
1287
|
+
'A `rules.<ID>` block names a live rule; a deprecated top-level key (`operators`, `romanLabels`, `abbreviations`) still works but warns until it is moved under `rules`; `conventions` is ignored and warns until it is deleted.',
|
|
1180
1288
|
checks: [
|
|
1181
1289
|
check('config-deprecated-key', 'warning', false, {
|
|
1182
1290
|
module: 'src/rules/settings.ts',
|
|
@@ -1223,8 +1331,10 @@ const INVARIANTS: readonly InvariantEntry[] = [
|
|
|
1223
1331
|
'track-order',
|
|
1224
1332
|
'assessment-coverage',
|
|
1225
1333
|
'invalid-assessment',
|
|
1226
|
-
'
|
|
1334
|
+
'missing-assumptions',
|
|
1227
1335
|
'teaches-support',
|
|
1336
|
+
// `[text [@id]](url)`: a citation the page prints as typed.
|
|
1337
|
+
'citation-in-link',
|
|
1228
1338
|
] as const
|
|
1229
1339
|
).map((code) =>
|
|
1230
1340
|
check(code, 'error', false, {
|
|
@@ -1238,7 +1348,6 @@ const INVARIANTS: readonly InvariantEntry[] = [
|
|
|
1238
1348
|
'alignment-unknown-lesson',
|
|
1239
1349
|
'alignment-introduction',
|
|
1240
1350
|
'alignment-unavailable',
|
|
1241
|
-
'alignment-review-state',
|
|
1242
1351
|
] as const
|
|
1243
1352
|
).map((code) =>
|
|
1244
1353
|
check(code, 'error', false, {
|
|
@@ -1246,7 +1355,74 @@ const INVARIANTS: readonly InvariantEntry[] = [
|
|
|
1246
1355
|
fn: 'validateNotationAlignment',
|
|
1247
1356
|
}),
|
|
1248
1357
|
),
|
|
1249
|
-
|
|
1358
|
+
// A course's parts and the lessons in them (`compileManifest`): a
|
|
1359
|
+
// lesson in a directory no part lists, and a part with nothing in it yet.
|
|
1360
|
+
check('lesson-outside-parts', 'error', false, {
|
|
1361
|
+
module: 'src/compiler/manifest.ts',
|
|
1362
|
+
fn: 'compileManifest',
|
|
1363
|
+
}),
|
|
1364
|
+
check('part-empty', 'warning', false, {
|
|
1365
|
+
module: 'src/compiler/manifest.ts',
|
|
1366
|
+
fn: 'compileManifest',
|
|
1367
|
+
}),
|
|
1368
|
+
] as unknown as [RuleCheck, ...RuleCheck[]],
|
|
1369
|
+
},
|
|
1370
|
+
{
|
|
1371
|
+
kind: 'invariant',
|
|
1372
|
+
id: 'content-schema',
|
|
1373
|
+
title: 'Every content file satisfies its collection’s schema.',
|
|
1374
|
+
elements: ['notation', 'assessment', 'source', 'changelog'],
|
|
1375
|
+
doc: 'structure.md#content-schemas',
|
|
1376
|
+
summary:
|
|
1377
|
+
'A page’s explico fields, a notation entry, an abbreviation, a competency, an assessment, a source and a track match the schema `astro build` loads them with (`compiler/content-schemas.ts`); `validate:content` reports the field and its line.',
|
|
1378
|
+
checks: [
|
|
1379
|
+
check('content-schema', 'error', false, {
|
|
1380
|
+
module: 'src/compiler/content-schema.ts',
|
|
1381
|
+
fn: 'validateContentSchemas',
|
|
1382
|
+
}),
|
|
1383
|
+
],
|
|
1384
|
+
},
|
|
1385
|
+
{
|
|
1386
|
+
kind: 'invariant',
|
|
1387
|
+
id: 'retired-keys',
|
|
1388
|
+
title: 'No content file sets a key the engine has retired or cannot honour.',
|
|
1389
|
+
elements: ['changelog'],
|
|
1390
|
+
doc: 'structure.md#retired-keys',
|
|
1391
|
+
summary:
|
|
1392
|
+
'A frontmatter or JSON key explico no longer reads (`editorialStatus`) fails the build at every file that still sets it; delete the line. A lesson’s `draft: true` fails it too (the sidebar would name a page the build drops), and its `sidebar.order` warns (chapters follow the tracks).',
|
|
1393
|
+
checks: [
|
|
1394
|
+
check('retired-key', 'error', false, {
|
|
1395
|
+
module: 'src/reference/gate-retired-keys.ts',
|
|
1396
|
+
fn: 'findRetiredKeys',
|
|
1397
|
+
}),
|
|
1398
|
+
check('unsupported-key', 'error', false, {
|
|
1399
|
+
module: 'src/reference/gate-retired-keys.ts',
|
|
1400
|
+
fn: 'findUnsupportedKeys',
|
|
1401
|
+
}),
|
|
1402
|
+
check('ignored-key', 'warning', false, {
|
|
1403
|
+
module: 'src/reference/gate-retired-keys.ts',
|
|
1404
|
+
fn: 'findUnsupportedKeys',
|
|
1405
|
+
}),
|
|
1406
|
+
],
|
|
1407
|
+
},
|
|
1408
|
+
{
|
|
1409
|
+
kind: 'invariant',
|
|
1410
|
+
id: 'prop-text',
|
|
1411
|
+
title: 'A component’s quoted prop holds plain text, and prose holds no `{…}` expression.',
|
|
1412
|
+
elements: ['math', 'plot', 'diagram', 'table'],
|
|
1413
|
+
doc: 'components.md#props-are-plain-text',
|
|
1414
|
+
summary:
|
|
1415
|
+
'A quoted prop (`caption="…"`, `short="…"`, `title="…"`, `label="…"`) reaches the page as plain text: no KaTeX, reference or citation runs in it. `$…$`, `[[…]]` or `[@…]` in one fails the build, since it would print as typed; write the symbol in Unicode or words, and reference or cite from the prose next to the component. MDX reads `{…}` in prose as JavaScript (`{a}` fails the build, "a is not defined"): write `\\{a\\}`, or `$\\{a\\}$` for a set.',
|
|
1416
|
+
checks: [
|
|
1417
|
+
check('markup-in-prop', 'error', false, {
|
|
1418
|
+
module: 'src/reference/gate-prop-text.ts',
|
|
1419
|
+
fn: 'findMarkupInProps',
|
|
1420
|
+
}),
|
|
1421
|
+
check('mdx-expression', 'error', false, {
|
|
1422
|
+
module: 'src/reference/gate-mdx-expression.ts',
|
|
1423
|
+
fn: 'gateMdxExpressions',
|
|
1424
|
+
}),
|
|
1425
|
+
],
|
|
1250
1426
|
},
|
|
1251
1427
|
];
|
|
1252
1428
|
|