explico 0.11.1 → 0.13.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 +1292 -1
- package/README.md +91 -13
- package/dist/compiler/astro.d.ts +11 -4
- package/dist/compiler/astro.js +48 -15
- package/dist/compiler/cli.d.ts +27 -12
- package/dist/compiler/cli.js +96 -25
- package/dist/compiler/collections.d.ts +33 -2
- package/dist/compiler/collections.js +91 -19
- 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 +15 -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 +115 -8
- package/dist/compiler/manifest.js +221 -39
- package/dist/compiler/render-diagnostics.d.ts +65 -0
- package/dist/compiler/render-diagnostics.js +56 -0
- package/dist/compiler/resolution-report.d.ts +3 -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 +8 -2
- package/dist/reference/base-operators.mjs +8 -10
- 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/figure-symbols.d.ts +32 -0
- package/dist/reference/figure-symbols.js +55 -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-non-chapter-pages.d.ts +39 -0
- package/dist/reference/gate-non-chapter-pages.js +156 -0
- package/dist/reference/gate-part-pages.d.ts +4 -2
- package/dist/reference/gate-part-pages.js +2 -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-katex-validate.d.ts +43 -0
- package/dist/reference/lab-katex-validate.js +96 -0
- package/dist/reference/lab-math-scope.d.ts +1 -0
- package/dist/reference/lab-math-scope.js +13 -2
- package/dist/reference/lint-ignore.js +1 -1
- 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 +39 -7
- package/dist/reference/page-notation.js +62 -10
- package/dist/reference/raw-floats.mjs +37 -13
- package/dist/reference/references.d.ts +11 -1
- package/dist/reference/references.js +6 -0
- package/dist/reference/registry.js +115 -11
- 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 +275 -23
- package/dist/reference/render-lab-math.d.ts +13 -2
- package/dist/reference/render-lab-math.js +18 -6
- 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 +223 -32
- package/dist/rules/in-effect.d.ts +1 -1
- package/dist/rules/rules.schema.json +100 -27
- 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 +33 -21
- package/docs/authoring/agents.md +38 -7
- package/docs/authoring/components.md +115 -10
- package/docs/authoring/migrating.md +878 -0
- package/docs/authoring/notation.md +285 -30
- package/docs/authoring/retired.md +1 -0
- package/docs/authoring/structure-rules.md +84 -45
- package/docs/authoring/structure.md +67 -2
- package/docs/authoring/visualizations.md +167 -25
- package/package.json +12 -7
- package/src/compiler/astro.ts +72 -21
- package/src/compiler/cli.ts +143 -35
- package/src/compiler/collections.ts +158 -27
- 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 +387 -40
- package/src/compiler/render-diagnostics.ts +111 -0
- package/src/components/CourseContents.astro +6 -0
- package/src/components/HoverPanel.astro +204 -6
- package/src/components/PartOverview.astro +18 -9
- package/src/components/abbreviation/AbbreviationGlossary.astro +6 -2
- 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/disclosure/print-as-shown.ts +42 -6
- package/src/components/figure/Figure.astro +17 -1
- package/src/components/figure/FloatCaption.astro +4 -17
- package/src/components/figure/figure-state.ts +26 -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 +300 -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 +66 -8
- 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 +14 -22
- 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 +8 -10
- 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/figure-symbols.ts +117 -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-non-chapter-pages.ts +241 -0
- package/src/reference/gate-part-pages.ts +1 -1
- 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-katex-validate.ts +156 -0
- package/src/reference/lab-math-scope.ts +15 -1
- package/src/reference/lint-ignore.ts +4 -1
- package/src/reference/math-glyphs.mjs +851 -46
- package/src/reference/mixed-content.ts +11 -2
- package/src/reference/page-notation.ts +114 -14
- package/src/reference/raw-floats.mjs +37 -13
- package/src/reference/references.ts +14 -0
- package/src/reference/registry.ts +170 -9
- 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 +275 -23
- package/src/reference/render-lab-math.ts +40 -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 +241 -31
- package/src/rules/settings.ts +10 -0
- package/src/session/PreferenceStore.ts +53 -0
- package/src/styles/global.css +322 -83
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
29
|
import { rehypeHeadingIds } from '@astrojs/markdown-remark';
|
|
30
|
+
import katex from 'katex';
|
|
31
|
+
import { createNotationKatexOptions } from './katex-options.mjs';
|
|
30
32
|
import { headingCardTier, stripHeadingMarker } from './rehype-heading-anchors.mjs';
|
|
31
33
|
|
|
32
34
|
/** The deepest heading level numbered when a course sets nothing (`####`). */
|
|
@@ -113,19 +115,18 @@ const ATX_HEADING = /^[ \t]{0,3}(#{1,6})(?:[ \t]+([^\n]*?))?(?:[ \t]+#+)?[ \t]*$
|
|
|
113
115
|
const ENTITIES = { amp: '&', lt: '<', gt: '>', quot: '"', apos: "'", nbsp: ' ' };
|
|
114
116
|
|
|
115
117
|
/**
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
* source
|
|
119
|
-
* term keeps its key; a link keeps its text; an image, a citation and an MDX
|
|
118
|
+
* A heading source's text, with `math` and `term` deciding what a `$…$` span
|
|
119
|
+
* and a `[[key]]` contribute. Markup goes, the words stay; inline code keeps
|
|
120
|
+
* its source; a link keeps its text; an image, a citation and an MDX
|
|
120
121
|
* expression contribute nothing; the authoring marker is dropped.
|
|
121
122
|
*/
|
|
122
|
-
|
|
123
|
+
function headingText(source, { math, term }) {
|
|
123
124
|
const literals = [];
|
|
124
125
|
const keep = (value) => `\u0000${literals.push(value) - 1}\u0000`;
|
|
125
126
|
let text = stripHeadingMarker(source ?? '')
|
|
126
127
|
.replace(/(`+)([\s\S]*?[^`])\1(?!`)/g, (_, _ticks, code) => keep(code.trim()))
|
|
127
|
-
.replace(/\$([^$\n]+)\$/g, (_, latex) => keep(latex.trim()))
|
|
128
|
-
.replace(/\[\[\s*([^\][]+?)\s*\]\]/g, (_, key) => keep(key))
|
|
128
|
+
.replace(/\$([^$\n]+)\$/g, (_, latex) => keep(math(latex.trim())))
|
|
129
|
+
.replace(/\[\[\s*([^\][]+?)\s*\]\]/g, (_, key) => keep(term(key)))
|
|
129
130
|
.replace(/\[@[^\]]*\]/g, '')
|
|
130
131
|
.replace(/!\[[^\]]*\]\([^)]*\)/g, '')
|
|
131
132
|
.replace(/\[([^\]]*)\]\([^)]*\)/g, '$1')
|
|
@@ -138,17 +139,84 @@ export function headingPlainText(source) {
|
|
|
138
139
|
.replace(/(^|[^\w])_(?=\S)([\s\S]*?\S)_(?!\w)/g, '$1$2')
|
|
139
140
|
.replace(/~~(?=\S)([\s\S]*?\S)~~/g, '$1')
|
|
140
141
|
.replace(/\\([!-/:-@[-`{-~])/g, '$1')
|
|
141
|
-
.replace(/&(#x[0-9a-f]+|#[0-9]+|[a-z]+);/gi, (entity, name) =>
|
|
142
|
-
if (name[0] !== '#') return ENTITIES[name.toLowerCase()] ?? entity;
|
|
143
|
-
const code = name[1] === 'x' || name[1] === 'X'
|
|
144
|
-
? Number.parseInt(name.slice(2), 16)
|
|
145
|
-
: Number.parseInt(name.slice(1), 10);
|
|
146
|
-
return Number.isFinite(code) ? String.fromCodePoint(code) : entity;
|
|
147
|
-
});
|
|
142
|
+
.replace(/&(#x[0-9a-f]+|#[0-9]+|[a-z]+);/gi, (entity, name) => decodeEntity(entity, name));
|
|
148
143
|
text = text.replace(/\u0000(\d+)\u0000/g, (_, index) => literals[Number(index)]);
|
|
149
144
|
return text.replace(/\s+/g, ' ').trim();
|
|
150
145
|
}
|
|
151
146
|
|
|
147
|
+
function decodeEntity(entity, name) {
|
|
148
|
+
if (name[0] !== '#') return ENTITIES[name.toLowerCase()] ?? entity;
|
|
149
|
+
const code = name[1] === 'x' || name[1] === 'X'
|
|
150
|
+
? Number.parseInt(name.slice(2), 16)
|
|
151
|
+
: Number.parseInt(name.slice(1), 10);
|
|
152
|
+
return Number.isFinite(code) ? String.fromCodePoint(code) : entity;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* The text a heading's source slugs as, near enough to the way Astro would:
|
|
157
|
+
* math as it reads, a notation term its key. A heading's anchor is made from
|
|
158
|
+
* it, so a plain heading keeps the id it always had; math reads as it renders
|
|
159
|
+
* (`mathSlugText`), so `## The range $\explain{motion.range}{R}$` is
|
|
160
|
+
* `#the-range-r` and not `#the-range-explainmotionranger`.
|
|
161
|
+
*/
|
|
162
|
+
export function headingPlainText(source) {
|
|
163
|
+
return headingText(source, { math: mathSlugText, term: (key) => key });
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** A Greek letter as LaTeX names it, for a slug that stays in ASCII. */
|
|
167
|
+
const GREEK_NAMES = {
|
|
168
|
+
α: 'alpha', β: 'beta', γ: 'gamma', δ: 'delta', ε: 'epsilon', ϵ: 'epsilon', ζ: 'zeta', η: 'eta',
|
|
169
|
+
θ: 'theta', ϑ: 'theta', ι: 'iota', κ: 'kappa', λ: 'lambda', μ: 'mu', ν: 'nu', ξ: 'xi', ο: 'omicron',
|
|
170
|
+
π: 'pi', ϖ: 'pi', ρ: 'rho', ϱ: 'rho', σ: 'sigma', ς: 'sigma', τ: 'tau', υ: 'upsilon', φ: 'phi',
|
|
171
|
+
ϕ: 'phi', χ: 'chi', ψ: 'psi', ω: 'omega', Γ: 'Gamma', Δ: 'Delta', Θ: 'Theta', Λ: 'Lambda',
|
|
172
|
+
Ξ: 'Xi', Π: 'Pi', Σ: 'Sigma', Υ: 'Upsilon', Φ: 'Phi', Ψ: 'Psi', Ω: 'Omega',
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* The text a heading's math slugs as: what it reads, each Greek letter spelled
|
|
177
|
+
* as LaTeX names it. `$e^{\lambda\cos(u)}$` reads `eλcos(u)` and slugs as
|
|
178
|
+
* `elambdacosu`, the anchor its source always gave it; what changes is the
|
|
179
|
+
* markup that never shows (`\explain{motion.range}{R}` is `R`).
|
|
180
|
+
*/
|
|
181
|
+
function mathSlugText(latex) {
|
|
182
|
+
return mathPlainText(latex).replace(/[\u0370-\u03FF]/g, (char) => GREEK_NAMES[char] ?? char);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* The text a reader sees for a math span: KaTeX's MathML without the LaTeX
|
|
187
|
+
* annotation, so `$\explain{motion.range}{R}$` reads `R` and `$v_0$` reads
|
|
188
|
+
* `v0`. Falls back to the source when KaTeX cannot render it.
|
|
189
|
+
*/
|
|
190
|
+
export function mathPlainText(latex) {
|
|
191
|
+
let markup;
|
|
192
|
+
try {
|
|
193
|
+
markup = katex.renderToString(latex, createNotationKatexOptions());
|
|
194
|
+
} catch {
|
|
195
|
+
return latex;
|
|
196
|
+
}
|
|
197
|
+
const mathml = /<math[\s\S]*?<\/math>/.exec(markup)?.[0] ?? '';
|
|
198
|
+
return mathml
|
|
199
|
+
.replace(/<annotation[\s\S]*?<\/annotation>/g, '')
|
|
200
|
+
.replace(/<[^>]+>/g, '')
|
|
201
|
+
.replace(/&(#x[0-9a-f]+|#[0-9]+|[a-z]+);/gi, (entity, name) => decodeEntity(entity, name))
|
|
202
|
+
.replace(/[\u200b\u2061-\u2064]/g, '')
|
|
203
|
+
.replace(/\s+/g, ' ')
|
|
204
|
+
.trim();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* The text a reader sees for a heading: math as it reads (`mathPlainText`)
|
|
209
|
+
* and a `[[key]]` term as its label, from `labelFor` (the page's notation),
|
|
210
|
+
* else as its key. "On this page", an unnumbered section's quoted title and a
|
|
211
|
+
* copied link name use it; the anchor is `headingPlainText`'s.
|
|
212
|
+
*/
|
|
213
|
+
export function headingDisplayText(source, { labelFor } = {}) {
|
|
214
|
+
return headingText(source, {
|
|
215
|
+
math: mathPlainText,
|
|
216
|
+
term: (key) => labelFor?.(key) ?? key,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
152
220
|
/**
|
|
153
221
|
* Anchors for a page's headings, in order, from Astro's own `rehypeHeadingIds`
|
|
154
222
|
* run over their plain text: the same slugger with the same duplicate
|
|
@@ -171,18 +239,24 @@ export function slugHeadings(texts) {
|
|
|
171
239
|
/**
|
|
172
240
|
* Every top-level heading of a lesson body in document order, as the
|
|
173
241
|
* manifest records it: `{ level, text, slug, number? }`. `prefix` is the
|
|
174
|
-
* chapter's `‹part›.‹chapter›`; without one nothing is numbered.
|
|
242
|
+
* chapter's `‹part›.‹chapter›`; without one nothing is numbered. `text` is
|
|
243
|
+
* what a reader sees (`headingDisplayText`, with `labelFor` naming a
|
|
244
|
+
* `[[key]]` term); the `slug` is made from `headingPlainText`.
|
|
245
|
+
* `math: true` marks a heading with inline math, whose text Astro's own
|
|
246
|
+
* heading list garbles (`LayoutPageSidebar.astro` relabels it).
|
|
175
247
|
*/
|
|
176
248
|
export function scanSectionHeadings(markdown, options = {}) {
|
|
177
249
|
const found = [];
|
|
178
250
|
for (const match of outlineSource(markdown).matchAll(ATX_HEADING)) {
|
|
179
251
|
found.push({
|
|
180
252
|
level: match[1].length,
|
|
181
|
-
|
|
253
|
+
slugText: headingPlainText(match[2] ?? ''),
|
|
254
|
+
text: headingDisplayText(match[2] ?? '', options),
|
|
255
|
+
math: /\$[^$\n]+\$/.test(stripHeadingMarker(match[2] ?? '')),
|
|
182
256
|
meta: headingCardTier(match[2] ?? '') === 'meta',
|
|
183
257
|
});
|
|
184
258
|
}
|
|
185
|
-
const slugs = slugHeadings(found.map((heading) => heading.
|
|
259
|
+
const slugs = slugHeadings(found.map((heading) => heading.slugText));
|
|
186
260
|
const numbers = sectionNumbers(
|
|
187
261
|
found.map((heading) => heading.level),
|
|
188
262
|
{ ...options, unnumbered: found.map((heading) => heading.meta) },
|
|
@@ -192,6 +266,7 @@ export function scanSectionHeadings(markdown, options = {}) {
|
|
|
192
266
|
text: heading.text,
|
|
193
267
|
slug: slugs[index],
|
|
194
268
|
...(numbers[index] === undefined ? {} : { number: numbers[index] }),
|
|
269
|
+
...(heading.math ? { math: true } : {}),
|
|
195
270
|
}));
|
|
196
271
|
}
|
|
197
272
|
|
|
@@ -12,7 +12,9 @@ export type TableDiagnosticCode =
|
|
|
12
12
|
| 'tab-duplicate-key'
|
|
13
13
|
| 'tab-ref-resolves'
|
|
14
14
|
| 'tab-key-unused'
|
|
15
|
-
| 'tab-removed-prop'
|
|
15
|
+
| 'tab-removed-prop'
|
|
16
|
+
| 'tab-unread-prop'
|
|
17
|
+
| 'tab-several-tables';
|
|
16
18
|
|
|
17
19
|
export interface TableDiagnostic {
|
|
18
20
|
readonly code: TableDiagnosticCode;
|
|
@@ -33,9 +35,45 @@ export interface TableValidation extends KeyedFloatValidation {
|
|
|
33
35
|
export function validateTables(
|
|
34
36
|
lessons: readonly TableLessonInput[],
|
|
35
37
|
): TableValidation {
|
|
36
|
-
|
|
38
|
+
const validation = validateKeyedFloats(lessons, {
|
|
37
39
|
tagName: 'Table',
|
|
38
40
|
prefix: 'tab',
|
|
39
41
|
noun: 'table',
|
|
40
42
|
}) as TableValidation;
|
|
43
|
+
const several = lessons.flatMap(severalTables);
|
|
44
|
+
return several.length === 0
|
|
45
|
+
? validation
|
|
46
|
+
: { ...validation, diagnostics: [...validation.diagnostics, ...several] };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** A pipe table's delimiter row, `| --- | :-: |`: one per pipe table. */
|
|
50
|
+
const DELIMITER_ROW = /^[ \t]*\|?(?:[ \t]*:?-+:?[ \t]*\|)+(?:[ \t]*:?-+:?[ \t]*)?$/gm;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* A `<Table>` holds one table: it has one number and one caption, and a
|
|
54
|
+
* reference to it names one table. The page showed a second under the same
|
|
55
|
+
* number, and every export kept only the first (`static-tree.ts`), silently.
|
|
56
|
+
*/
|
|
57
|
+
function severalTables(lesson: TableLessonInput): TableDiagnostic[] {
|
|
58
|
+
const blank = (match: string) => match.replace(/[^\n]/g, ' ');
|
|
59
|
+
const body = lesson.body.replace(/```[\s\S]*?```/g, blank).replace(/\{\/\*[\s\S]*?\*\/\}/g, blank);
|
|
60
|
+
const found: TableDiagnostic[] = [];
|
|
61
|
+
for (const table of body.matchAll(/<Table\b((?:[^>"']|"[^"]*"|'[^']*')*?)(?<!\/)>([\s\S]*?)<\/Table>/g)) {
|
|
62
|
+
const inner = table[2] ?? '';
|
|
63
|
+
const count = (inner.match(DELIMITER_ROW)?.length ?? 0) + (inner.match(/<table\b/g)?.length ?? 0);
|
|
64
|
+
if (count < 2) continue;
|
|
65
|
+
const key = /\bid\s*=\s*["']([^"']*)["']/.exec(table[1] ?? '')?.[1];
|
|
66
|
+
found.push({
|
|
67
|
+
code: 'tab-several-tables',
|
|
68
|
+
severity: 'error',
|
|
69
|
+
message:
|
|
70
|
+
`${lesson.lessonId} has a <Table${key ? ` id="${key}"` : ''}> holding ${count} tables: a <Table> ` +
|
|
71
|
+
'holds one, with one number and one caption, and every export keeps only the first. Give ' +
|
|
72
|
+
'each table its own <Table id>, or join them into one.',
|
|
73
|
+
file: lesson.file,
|
|
74
|
+
lessonId: lesson.lessonId,
|
|
75
|
+
...(key ? { key } : {}),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return found;
|
|
41
79
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The width of a diagram label, measured at build time.
|
|
3
|
+
*
|
|
4
|
+
* The site draws text in the reader's system font, so no width computed at
|
|
5
|
+
* build time is exact. DejaVu Sans is the widest of the common system
|
|
6
|
+
* sans-serifs (Segoe UI, San Francisco, Roboto, Helvetica, Arial, Noto Sans,
|
|
7
|
+
* Ubuntu, Cantarell), so a label measured with its advance widths
|
|
8
|
+
* (`text-widths.ts`, generated from the font) fits in every one of them.
|
|
9
|
+
* Kerning only ever narrows that, and is ignored: measured in Chromium, the
|
|
10
|
+
* table gives DejaVu Sans's own width or up to 3% more, and no label of the
|
|
11
|
+
* playground or of data-science-I is wider in Liberation Sans (Arial's
|
|
12
|
+
* metrics), Noto Sans or Lato than in DejaVu Sans.
|
|
13
|
+
*/
|
|
14
|
+
import { UNITS_PER_EM, WIDTH_BLOCKS } from './text-widths';
|
|
15
|
+
|
|
16
|
+
const WIDTHS = new Map<number, number>();
|
|
17
|
+
for (const [first, widths] of WIDTH_BLOCKS) {
|
|
18
|
+
widths.forEach((width, offset) => {
|
|
19
|
+
if (width >= 0) WIDTHS.set(first + offset, width / UNITS_PER_EM);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** A character outside the table (a CJK ideograph, an emoji) is about 1em. */
|
|
24
|
+
const FALLBACK_EM = 1;
|
|
25
|
+
const COMBINING_MARK = /\p{M}/u;
|
|
26
|
+
|
|
27
|
+
/** One character's advance, in em. */
|
|
28
|
+
function advanceEm(char: string): number {
|
|
29
|
+
if (COMBINING_MARK.test(char)) return 0;
|
|
30
|
+
return WIDTHS.get(char.codePointAt(0) ?? 0) ?? FALLBACK_EM;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** The advance of `text` at `fontPx`, in px, rounded up to a whole pixel. */
|
|
34
|
+
export function textWidth(text: string, fontPx: number): number {
|
|
35
|
+
let em = 0;
|
|
36
|
+
for (const char of text) em += advanceEm(char);
|
|
37
|
+
return Math.ceil(em * fontPx - 1e-6);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Break `text` into lines no wider than `maxWidth` px, greedily at spaces,
|
|
42
|
+
* the way a browser wraps it. A word wider than `maxWidth` keeps a line of its
|
|
43
|
+
* own (the caller widens the box to it); a space never ends or starts a line.
|
|
44
|
+
*/
|
|
45
|
+
export function wrapText(text: string, maxWidth: number, fontPx: number): string[] {
|
|
46
|
+
const words = text.trim().split(/[ \t\r\n]+/u).filter(Boolean);
|
|
47
|
+
const space = textWidth(' ', fontPx);
|
|
48
|
+
const lines: string[] = [];
|
|
49
|
+
let line = '';
|
|
50
|
+
let lineWidth = 0;
|
|
51
|
+
for (const word of words) {
|
|
52
|
+
const wordWidth = textWidth(word, fontPx);
|
|
53
|
+
if (line && lineWidth + space + wordWidth > maxWidth) {
|
|
54
|
+
lines.push(line);
|
|
55
|
+
line = '';
|
|
56
|
+
lineWidth = 0;
|
|
57
|
+
}
|
|
58
|
+
line = line ? `${line} ${word}` : word;
|
|
59
|
+
lineWidth = lineWidth ? lineWidth + space + wordWidth : wordWidth;
|
|
60
|
+
}
|
|
61
|
+
if (line) lines.push(line);
|
|
62
|
+
return lines;
|
|
63
|
+
}
|
|
@@ -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
|
+
}
|