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
|
@@ -138,12 +138,6 @@ interface CoursePart {
|
|
|
138
138
|
* `##` heading inside a lesson. Removed in the next MINOR release.
|
|
139
139
|
*/
|
|
140
140
|
type CourseSection = CoursePart;
|
|
141
|
-
interface CourseConventions {
|
|
142
|
-
/** Notation key a lesson's stated sign convention must resolve to. */
|
|
143
|
-
readonly signConventionKey: string;
|
|
144
|
-
/** Competency id that also counts as declaring the cash-flow perspective. */
|
|
145
|
-
readonly cashFlowPerspectiveCompetency: string;
|
|
146
|
-
}
|
|
147
141
|
/**
|
|
148
142
|
* A course's edits to the shipped named-operator baseline (`BASE_OPERATORS`),
|
|
149
143
|
* consumed by the `operator-explained` consistency check (rule N8). An operator
|
|
@@ -367,6 +361,27 @@ type BlockLabels = 'icon' | 'icon-word';
|
|
|
367
361
|
declare const BLOCK_LABELS_DEFAULT: BlockLabels;
|
|
368
362
|
/** Validate `CourseConfig.blockLabels` and apply its default. Throws on a bad value. */
|
|
369
363
|
declare function normalizeBlockLabels(config: CourseConfig): BlockLabels;
|
|
364
|
+
/**
|
|
365
|
+
* How a course's explanation cards start for a reader who has not chosen
|
|
366
|
+
* yet (`cards` in the course settings). Every field is optional;
|
|
367
|
+
* {@link normalizeCards} fills in the defaults.
|
|
368
|
+
*/
|
|
369
|
+
interface CourseCards {
|
|
370
|
+
/**
|
|
371
|
+
* Whether "Carry cards" starts on (rule K1, `card-carry.ts`): a kept card
|
|
372
|
+
* stays on screen as the page scrolls and comes along to every page of the
|
|
373
|
+
* course. A reader's own choice always wins. Default `false`.
|
|
374
|
+
*/
|
|
375
|
+
readonly carry?: boolean;
|
|
376
|
+
}
|
|
377
|
+
/** {@link CourseCards} with every default applied. */
|
|
378
|
+
interface NormalizedCards {
|
|
379
|
+
readonly carry: boolean;
|
|
380
|
+
}
|
|
381
|
+
/** The engine's defaults: a reader turns carrying on (D8). */
|
|
382
|
+
declare const CARDS_DEFAULTS: NormalizedCards;
|
|
383
|
+
/** Validate `CourseConfig.cards` and apply its defaults. Throws on a bad value. */
|
|
384
|
+
declare function normalizeCards(config: CourseConfig): NormalizedCards;
|
|
370
385
|
/**
|
|
371
386
|
* Rule S2's word ranges (`rules.S2.bridgeMinWords` … in the course settings),
|
|
372
387
|
* in the shape `gate-part-pages.ts` takes. Built by `partPageLimits` in
|
|
@@ -382,15 +397,33 @@ interface NormalizedPartPages {
|
|
|
382
397
|
readonly maxWords: number;
|
|
383
398
|
};
|
|
384
399
|
}
|
|
385
|
-
/**
|
|
400
|
+
/**
|
|
401
|
+
* Optional, build-time downloads and print actions: each chapter, each part and
|
|
402
|
+
* the course download; every page prints.
|
|
403
|
+
*/
|
|
386
404
|
interface LessonExportsConfig {
|
|
387
|
-
/** Emit one self-contained, offline-capable HTML file per
|
|
405
|
+
/** Emit one self-contained, offline-capable HTML file per page. */
|
|
388
406
|
readonly standaloneHtml?: boolean;
|
|
389
|
-
/** Offer the browser's native print dialog with explico's
|
|
407
|
+
/** Offer the browser's native print dialog with explico's print layout. */
|
|
390
408
|
readonly print?: boolean;
|
|
409
|
+
/**
|
|
410
|
+
* Emit each chapter's LaTeX source — a zipped folder with explico's class,
|
|
411
|
+
* the chapter and its figures — and the PDF compiled from that folder.
|
|
412
|
+
*/
|
|
413
|
+
readonly latex?: boolean;
|
|
414
|
+
/**
|
|
415
|
+
* Paper size of the LaTeX documents: `letter` (default, LaTeX's own) or
|
|
416
|
+
* `a4`. A plain `string` because the settings arrive as JSON.
|
|
417
|
+
*/
|
|
418
|
+
readonly latexPaper?: string;
|
|
419
|
+
/**
|
|
420
|
+
* Emit each chapter, each part and the course as Markdown — GitHub's
|
|
421
|
+
* flavour with `$…$` math, its figures as PNG — zipped with its assets.
|
|
422
|
+
*/
|
|
423
|
+
readonly markdown?: boolean;
|
|
391
424
|
/**
|
|
392
425
|
* Published course root used for links that intentionally leave the exported
|
|
393
|
-
*
|
|
426
|
+
* page. Required at export time when such a link is present.
|
|
394
427
|
*/
|
|
395
428
|
readonly canonicalBaseUrl?: string;
|
|
396
429
|
}
|
|
@@ -398,6 +431,9 @@ interface LessonExportsConfig {
|
|
|
398
431
|
interface NormalizedLessonExports {
|
|
399
432
|
readonly standaloneHtml: boolean;
|
|
400
433
|
readonly print: boolean;
|
|
434
|
+
readonly latex: boolean;
|
|
435
|
+
readonly latexPaper: 'letter' | 'a4';
|
|
436
|
+
readonly markdown: boolean;
|
|
401
437
|
readonly canonicalBaseUrl?: string;
|
|
402
438
|
}
|
|
403
439
|
interface CourseConfig {
|
|
@@ -415,7 +451,12 @@ interface CourseConfig {
|
|
|
415
451
|
readonly sections?: readonly CoursePart[];
|
|
416
452
|
/** Namespaces used by competency / notation `domain` fields. */
|
|
417
453
|
readonly domains: readonly string[];
|
|
418
|
-
|
|
454
|
+
/**
|
|
455
|
+
* @deprecated No longer read: rule S5, the only reader, was retired. A
|
|
456
|
+
* course that still sets it gets a `config-deprecated-key` warning; delete
|
|
457
|
+
* the block. Removed from the type in the next MINOR release.
|
|
458
|
+
*/
|
|
459
|
+
readonly conventions?: unknown;
|
|
419
460
|
/** Reader-facing identity + knowledge version (the `[?]` About panel). */
|
|
420
461
|
readonly about: CourseAbout;
|
|
421
462
|
/**
|
|
@@ -438,12 +479,14 @@ interface CourseConfig {
|
|
|
438
479
|
readonly romanLabels?: CourseRomanLabels;
|
|
439
480
|
/** @deprecated Moved to `rules.N14` (same shape). Honoured for now; removed in a later MINOR. */
|
|
440
481
|
readonly abbreviations?: CourseAbbreviations;
|
|
441
|
-
/** Per-
|
|
482
|
+
/** Per-page export actions and downloadable artifacts. Disabled when omitted. */
|
|
442
483
|
readonly lessonExports?: LessonExportsConfig;
|
|
443
484
|
/** Every collapse default: headings, checks, memos, floats, tables. */
|
|
444
485
|
readonly disclosure?: CourseDisclosure;
|
|
445
486
|
/** Outline and float numbering. The defaults apply when omitted. */
|
|
446
487
|
readonly numbering?: CourseNumbering;
|
|
488
|
+
/** How explanation cards start for a reader: "Carry cards" on or off. */
|
|
489
|
+
readonly cards?: CourseCards;
|
|
447
490
|
/**
|
|
448
491
|
* How a check's and an example set's heading names its kind: `icon-word`
|
|
449
492
|
* (default) or `icon` ({@link BlockLabels}). A plain `string` because the
|
|
@@ -461,4 +504,4 @@ declare function normalizeLessonExports(config: CourseConfig): NormalizedLessonE
|
|
|
461
504
|
*/
|
|
462
505
|
declare function coursePartsOf(config: CourseConfig): readonly CoursePart[];
|
|
463
506
|
|
|
464
|
-
export { type
|
|
507
|
+
export { type CourseOpenDefault as A, type BlockLabels as B, type CourseConfig as C, type CoursePart as D, type CourseSection as E, DISCLOSURE_DEFAULTS as F, coursePartsOf as G, normalizeBlockLabels as H, normalizeCards as I, normalizeDisclosure as J, normalizeLessonExports as K, type LessonExportsConfig as L, type ManifestRules as M, type NormalizedLessonExports as N, normalizeNumbering as O, type ResolvedRules as R, type NormalizedDisclosure as a, type NormalizedNumbering as b, type NormalizedCards as c, type ConfigDiagnostic as d, type CourseOperators as e, type CourseRomanLabels as f, type CourseAccents as g, type CourseAbbreviations as h, type NormalizedPartPages as i, type CourseRulesConfig as j, type RuleSettingsInput as k, catalogIds as l, disabledCodes as m, dropDisabled as n, rulesJsonSchema as o, partPageLimits as p, rulesSnapshot as q, resolveRules as r, BLOCK_LABELS_DEFAULT as s, CARDS_DEFAULTS as t, type CourseAbout as u, type CourseAuthor as v, type CourseCards as w, type CourseDisclosure as x, type CourseHeadingDisclosure as y, type CourseNumbering as z };
|
|
@@ -10,7 +10,6 @@ interface CompetencyDefinition {
|
|
|
10
10
|
}
|
|
11
11
|
interface LessonDefinition {
|
|
12
12
|
readonly id: string;
|
|
13
|
-
readonly status: 'draft' | 'in-review' | 'reviewed';
|
|
14
13
|
readonly requires: readonly string[];
|
|
15
14
|
readonly teaches: readonly string[];
|
|
16
15
|
readonly assessments: readonly string[];
|
|
@@ -23,6 +22,8 @@ interface AssessmentItemBase {
|
|
|
23
22
|
readonly id: string;
|
|
24
23
|
readonly competencyId: string;
|
|
25
24
|
readonly evidenceKind: 'direct' | 'transfer';
|
|
25
|
+
readonly prompt?: string;
|
|
26
|
+
readonly explanation?: string;
|
|
26
27
|
}
|
|
27
28
|
interface NumericAssessmentItem extends AssessmentItemBase {
|
|
28
29
|
readonly type: 'numeric';
|
|
@@ -45,7 +46,6 @@ interface AssessmentDefinition {
|
|
|
45
46
|
}
|
|
46
47
|
interface SourceDefinition {
|
|
47
48
|
readonly id: string;
|
|
48
|
-
readonly editorialStatus: 'draft' | 'in-review' | 'reviewed';
|
|
49
49
|
}
|
|
50
50
|
interface TrackDefinition {
|
|
51
51
|
readonly id: string;
|
|
@@ -59,8 +59,14 @@ interface CurriculumCatalog {
|
|
|
59
59
|
readonly tracks: readonly TrackDefinition[];
|
|
60
60
|
}
|
|
61
61
|
interface CurriculumIssue {
|
|
62
|
-
readonly kind: 'invalid-id' | 'duplicate-id' | 'unknown-reference' | 'duplicate-reference' | 'self-prerequisite' | 'cycle' | 'lesson-order' | 'track-order' | 'assessment-coverage' | 'invalid-assessment' | '
|
|
62
|
+
readonly kind: 'invalid-id' | 'duplicate-id' | 'unknown-reference' | 'duplicate-reference' | 'self-prerequisite' | 'cycle' | 'lesson-order' | 'track-order' | 'assessment-coverage' | 'invalid-assessment' | 'missing-assumptions' | 'teaches-support' | 'retired-key' | 'content-schema' | 'part-empty' | 'lesson-outside-parts' | 'unsupported-key' | 'ignored-key' | 'markup-in-prop' | 'citation-in-link';
|
|
63
63
|
readonly message: string;
|
|
64
|
+
/**
|
|
65
|
+
* The content file the issue is about, when it is about one file rather
|
|
66
|
+
* than the graph (`retired-key`, `content-schema`), and the 1-based line in it.
|
|
67
|
+
*/
|
|
68
|
+
readonly file?: string;
|
|
69
|
+
readonly line?: number;
|
|
64
70
|
/**
|
|
65
71
|
* `error` (default) blocks the build; `warning` is reported but non-blocking.
|
|
66
72
|
* New checks enter as warnings and are promoted once they run clean on real
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { citationsInLinks, citedIds, withoutLinkCitations } from "../reference/citation-format.mjs";
|
|
2
|
+
const CHECK_TEXT_REFERENCE = /\[\[[^\]\n]*\]\]|\[@[^\]\n]*\]/;
|
|
1
3
|
const VALID_ID = /^[a-z0-9]+(?:[.-][a-z0-9]+)*$/;
|
|
2
4
|
function buildIndex(kind, entries, issues) {
|
|
3
5
|
const index = /* @__PURE__ */ new Map();
|
|
@@ -23,13 +25,7 @@ function buildIndex(kind, entries, issues) {
|
|
|
23
25
|
function citedSourceIds(body) {
|
|
24
26
|
if (!body) return /* @__PURE__ */ new Set();
|
|
25
27
|
const withoutCode = body.replace(/```[\s\S]*?```/g, "").replace(/`[^`\n]*`/g, "");
|
|
26
|
-
|
|
27
|
-
for (const match of withoutCode.matchAll(
|
|
28
|
-
/\[@([a-z0-9][a-z0-9.-]*)(?:;[^\]]*)?\]/g
|
|
29
|
-
)) {
|
|
30
|
-
ids.add((match[1] ?? "").trim());
|
|
31
|
-
}
|
|
32
|
-
return ids;
|
|
28
|
+
return citedIds(withoutLinkCitations(withoutCode));
|
|
33
29
|
}
|
|
34
30
|
function findDuplicates(values) {
|
|
35
31
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -173,18 +169,22 @@ function validateCurriculum(catalog) {
|
|
|
173
169
|
}
|
|
174
170
|
}
|
|
175
171
|
const cited = citedSourceIds(lesson.body);
|
|
172
|
+
if (lesson.body !== void 0) {
|
|
173
|
+
const blank = (code) => code.replace(/[^\n]/g, " ");
|
|
174
|
+
const prose = lesson.body.replace(/```[\s\S]*?```/g, blank).replace(/`[^`\n]*`/g, blank);
|
|
175
|
+
for (const { text } of citationsInLinks(prose)) {
|
|
176
|
+
issues.push({
|
|
177
|
+
kind: "citation-in-link",
|
|
178
|
+
message: `${lesson.id} puts the citation ${text} inside a link's text, where it prints as typed: a link cannot hold the citation's own link. Cite after the link: [the words](https://\u2026) ${text}.`
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
176
182
|
for (const sourceId of lesson.sources) {
|
|
177
|
-
|
|
178
|
-
if (!source) {
|
|
183
|
+
if (!sources.has(sourceId)) {
|
|
179
184
|
issues.push({
|
|
180
185
|
kind: "unknown-reference",
|
|
181
186
|
message: `${lesson.id} references unknown source ${sourceId}`
|
|
182
187
|
});
|
|
183
|
-
} else if (lesson.status === "reviewed" && source.editorialStatus !== "reviewed") {
|
|
184
|
-
issues.push({
|
|
185
|
-
kind: "review-state",
|
|
186
|
-
message: `${lesson.id} is reviewed but source ${sourceId} is ${source.editorialStatus}`
|
|
187
|
-
});
|
|
188
188
|
}
|
|
189
189
|
if (lesson.body !== void 0 && !cited.has(sourceId)) {
|
|
190
190
|
issues.push({
|
|
@@ -203,7 +203,7 @@ function validateCurriculum(catalog) {
|
|
|
203
203
|
}
|
|
204
204
|
if (lesson.teaches.length > 0 && lesson.assumptions.length === 0) {
|
|
205
205
|
issues.push({
|
|
206
|
-
kind: "
|
|
206
|
+
kind: "missing-assumptions",
|
|
207
207
|
message: `${lesson.id} teaches quantitative content but declares no assumptions`
|
|
208
208
|
});
|
|
209
209
|
}
|
|
@@ -232,10 +232,28 @@ function validateCurriculum(catalog) {
|
|
|
232
232
|
message: `${assessment.id}/${item.id} has unknown correct option ${item.correctOptionId}`
|
|
233
233
|
});
|
|
234
234
|
}
|
|
235
|
-
} else if (!Number.isFinite(item.answer.value)
|
|
235
|
+
} else if (!Number.isFinite(item.answer.value)) {
|
|
236
|
+
issues.push({
|
|
237
|
+
kind: "invalid-assessment",
|
|
238
|
+
message: `${assessment.id}/${item.id} answer.value must be a number`
|
|
239
|
+
});
|
|
240
|
+
} else if (!Number.isFinite(item.answer.tolerance) || item.answer.tolerance <= 0) {
|
|
241
|
+
issues.push({
|
|
242
|
+
kind: "invalid-assessment",
|
|
243
|
+
message: `${assessment.id}/${item.id} answer.tolerance must be a number greater than 0, not ${String(item.answer.tolerance)}: an answer within it of answer.value is correct. For an exact whole-number answer, use a tolerance below one half, such as 0.4.`
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
const texts = [
|
|
247
|
+
["prompt", item.prompt],
|
|
248
|
+
["explanation", item.explanation],
|
|
249
|
+
...item.type === "single-choice" ? item.options.map((option) => [`option ${option.id}`, option.label]) : []
|
|
250
|
+
];
|
|
251
|
+
for (const [field, text] of texts) {
|
|
252
|
+
const found = text === void 0 ? null : CHECK_TEXT_REFERENCE.exec(text);
|
|
253
|
+
if (!found) continue;
|
|
236
254
|
issues.push({
|
|
237
255
|
kind: "invalid-assessment",
|
|
238
|
-
message: `${assessment.id}/${item.id}
|
|
256
|
+
message: `${assessment.id}/${item.id} ${field} contains ${found[0]}, which a knowledge check shows exactly as written: its text renders math, not references or citations. Name the equation, section or source in words, or cite it in the lesson text the check follows.`
|
|
239
257
|
});
|
|
240
258
|
}
|
|
241
259
|
const evidence = evidenceByCompetency.get(item.competencyId) ?? {
|
|
@@ -24,7 +24,7 @@ export function isBaseAbbreviation(token: any, abbreviations: any): boolean;
|
|
|
24
24
|
* `content/abbreviations/*.md` table, not here. This baseline only holds
|
|
25
25
|
* abbreviations so common in ordinary English/academic writing that spelling
|
|
26
26
|
* them out on every course would be noise, not help. A course adds a real
|
|
27
|
-
* one via `
|
|
28
|
-
* `
|
|
27
|
+
* one via `rules.N14.allow` in its course config, the same shape as
|
|
28
|
+
* `rules.N8.allow` / `rules.N10.allow`.
|
|
29
29
|
*/
|
|
30
30
|
export const BASE_ABBREVIATIONS: Readonly<Set<string>>;
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
* `content/abbreviations/*.md` table, not here. This baseline only holds
|
|
12
12
|
* abbreviations so common in ordinary English/academic writing that spelling
|
|
13
13
|
* them out on every course would be noise, not help. A course adds a real
|
|
14
|
-
* one via `
|
|
15
|
-
* `
|
|
14
|
+
* one via `rules.N14.allow` in its course config, the same shape as
|
|
15
|
+
* `rules.N8.allow` / `rules.N10.allow`.
|
|
16
16
|
*/
|
|
17
17
|
export const BASE_ABBREVIATIONS = Object.freeze(
|
|
18
18
|
new Set([
|
|
@@ -26,10 +26,16 @@ export function isBaseOperator(name: any, operators: any): boolean;
|
|
|
26
26
|
* baseline — trig, the exponential and logarithms, limits, extrema, and the
|
|
27
27
|
* big operators — kept greppable and small like the base library.
|
|
28
28
|
*
|
|
29
|
+
* Only the plain limit, `\lim`, is baseline. `\limsup` / `\liminf` and the
|
|
30
|
+
* category-theory `\injlim` / `\projlim` / `\varlimsup` / `\varliminf` /
|
|
31
|
+
* `\varinjlim` / `\varprojlim` read fine to someone who already knows them,
|
|
32
|
+
* but none is "everyone knows this" the way `\lim` or `\max` is — a course
|
|
33
|
+
* that uses one owes it a notation entry, like any other domain operator.
|
|
34
|
+
*
|
|
29
35
|
* A domain operator (`Var`, `Cov`, `Corr`, `sgn`, `erf`, `Tr`, `argmax`, …) is
|
|
30
36
|
* written `\operatorname{…}` and is NOT here: it earns a card, a
|
|
31
|
-
* `notation.local` entry, or an explicit line in
|
|
32
|
-
* (`
|
|
37
|
+
* `notation.local` entry, or an explicit line in the course config
|
|
38
|
+
* (`rules.N8.allow`).
|
|
33
39
|
*
|
|
34
40
|
* Entries are the KaTeX command without its backslash (`exp`, not `\exp`) for
|
|
35
41
|
* `op` nodes, and the verbatim body for `\operatorname{…}` nodes (`Var`).
|
|
@@ -13,10 +13,16 @@
|
|
|
13
13
|
* baseline — trig, the exponential and logarithms, limits, extrema, and the
|
|
14
14
|
* big operators — kept greppable and small like the base library.
|
|
15
15
|
*
|
|
16
|
+
* Only the plain limit, `\lim`, is baseline. `\limsup` / `\liminf` and the
|
|
17
|
+
* category-theory `\injlim` / `\projlim` / `\varlimsup` / `\varliminf` /
|
|
18
|
+
* `\varinjlim` / `\varprojlim` read fine to someone who already knows them,
|
|
19
|
+
* but none is "everyone knows this" the way `\lim` or `\max` is — a course
|
|
20
|
+
* that uses one owes it a notation entry, like any other domain operator.
|
|
21
|
+
*
|
|
16
22
|
* A domain operator (`Var`, `Cov`, `Corr`, `sgn`, `erf`, `Tr`, `argmax`, …) is
|
|
17
23
|
* written `\operatorname{…}` and is NOT here: it earns a card, a
|
|
18
|
-
* `notation.local` entry, or an explicit line in
|
|
19
|
-
* (`
|
|
24
|
+
* `notation.local` entry, or an explicit line in the course config
|
|
25
|
+
* (`rules.N8.allow`).
|
|
20
26
|
*
|
|
21
27
|
* Entries are the KaTeX command without its backslash (`exp`, not `\exp`) for
|
|
22
28
|
* `op` nodes, and the verbatim body for `\operatorname{…}` nodes (`Var`).
|
|
@@ -47,14 +53,6 @@ export const BASE_OPERATORS = Object.freeze(
|
|
|
47
53
|
'coth',
|
|
48
54
|
// limits
|
|
49
55
|
'lim',
|
|
50
|
-
'limsup',
|
|
51
|
-
'liminf',
|
|
52
|
-
'injlim',
|
|
53
|
-
'projlim',
|
|
54
|
-
'varlimsup',
|
|
55
|
-
'varliminf',
|
|
56
|
-
'varinjlim',
|
|
57
|
-
'varprojlim',
|
|
58
56
|
// extrema
|
|
59
57
|
'max',
|
|
60
58
|
'min',
|
|
@@ -28,8 +28,9 @@ export function isBaseRomanLabel(name: any, romanLabels: any): boolean;
|
|
|
28
28
|
* always a course-specific named quantity (`KE`, `PV`, `Var`-as-a-label) that
|
|
29
29
|
* genuinely benefits from a hover card, so the shipped baseline holds only
|
|
30
30
|
* the qualifiers that function like an operator's extremum subscript
|
|
31
|
-
* (`x_{\mathrm{opt}}`) rather than naming a quantity of their own.
|
|
32
|
-
*
|
|
33
|
-
*
|
|
31
|
+
* (`x_{\mathrm{opt}}`) rather than naming a quantity of their own. That
|
|
32
|
+
* clears rule N10 only: the indexed symbol still needs a card (rule N23).
|
|
33
|
+
* A course adds a real one via `rules.N10.allow` in its course config, the
|
|
34
|
+
* same shape as `rules.N8.allow`.
|
|
34
35
|
*/
|
|
35
36
|
export const BASE_ROMAN_LABELS: Readonly<Set<string>>;
|
|
@@ -15,9 +15,10 @@
|
|
|
15
15
|
* always a course-specific named quantity (`KE`, `PV`, `Var`-as-a-label) that
|
|
16
16
|
* genuinely benefits from a hover card, so the shipped baseline holds only
|
|
17
17
|
* the qualifiers that function like an operator's extremum subscript
|
|
18
|
-
* (`x_{\mathrm{opt}}`) rather than naming a quantity of their own.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* (`x_{\mathrm{opt}}`) rather than naming a quantity of their own. That
|
|
19
|
+
* clears rule N10 only: the indexed symbol still needs a card (rule N23).
|
|
20
|
+
* A course adds a real one via `rules.N10.allow` in its course config, the
|
|
21
|
+
* same shape as `rules.N8.allow`.
|
|
21
22
|
*/
|
|
22
23
|
export const BASE_ROMAN_LABELS = Object.freeze(new Set(['opt']));
|
|
23
24
|
|
|
@@ -44,6 +44,35 @@ export function referenceLabelFromText(referenceText: string, locator: string |
|
|
|
44
44
|
* @returns {string}
|
|
45
45
|
*/
|
|
46
46
|
export function formatSourceLabel(record: Record<string, unknown>): string;
|
|
47
|
+
/**
|
|
48
|
+
* The citations one bracket holds, in order, as `{ id, locator }`. A
|
|
49
|
+
* `;`-separated part that is only `@id` starts another citation (Pandoc's
|
|
50
|
+
* `[@a; @b]`); any other part belongs to the locator of the citation before
|
|
51
|
+
* it, so a locator may itself contain `;` (`[@a; §1.2; eq. 3]`).
|
|
52
|
+
*
|
|
53
|
+
* @param {string} firstId
|
|
54
|
+
* @param {string | undefined} rest
|
|
55
|
+
* @returns {{ id: string, locator: string }[]}
|
|
56
|
+
*/
|
|
57
|
+
export function bracketCitations(firstId: string, rest: string | undefined): {
|
|
58
|
+
id: string;
|
|
59
|
+
locator: string;
|
|
60
|
+
}[];
|
|
61
|
+
/** Every source id a text cites, `[@a; @b]` included. */
|
|
62
|
+
export function citedIds(text: any): Set<any>;
|
|
63
|
+
/**
|
|
64
|
+
* Each citation written inside a link's text, as `{ index, text }`: the
|
|
65
|
+
* offset of its `[@` in `text`, and the citation as written.
|
|
66
|
+
*/
|
|
67
|
+
export function citationsInLinks(text: any): {
|
|
68
|
+
index: number;
|
|
69
|
+
text: string;
|
|
70
|
+
}[];
|
|
71
|
+
/**
|
|
72
|
+
* `text` with every citation inside a link's text blanked, offsets kept: what
|
|
73
|
+
* the page cites, for a scan that counts a lesson's sources.
|
|
74
|
+
*/
|
|
75
|
+
export function withoutLinkCitations(text: any): string;
|
|
47
76
|
/**
|
|
48
77
|
* Pure helpers for turning a source record plus a per-citation locator into
|
|
49
78
|
* the strings shown in the inline panel and the end-of-page reference list.
|
|
@@ -53,3 +82,9 @@ export function formatSourceLabel(record: Record<string, unknown>): string;
|
|
|
53
82
|
* file system, or Astro APIs.
|
|
54
83
|
*/
|
|
55
84
|
export const SOURCE_ID_PATTERN: RegExp;
|
|
85
|
+
/**
|
|
86
|
+
* One `[@…]` bracket: `[@id]`, `[@id; locator]`, or several citations as
|
|
87
|
+
* Pandoc writes them, `[@a; @b; p. 7]`. Group 1 is the first id, group 2 the
|
|
88
|
+
* rest after the first `;`, read by {@link bracketCitations}.
|
|
89
|
+
*/
|
|
90
|
+
export const CITATION_BRACKET: RegExp;
|
|
@@ -131,3 +131,77 @@ export function formatSourceLabel(record) {
|
|
|
131
131
|
.filter(Boolean)
|
|
132
132
|
.join(', ');
|
|
133
133
|
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* One `[@…]` bracket: `[@id]`, `[@id; locator]`, or several citations as
|
|
137
|
+
* Pandoc writes them, `[@a; @b; p. 7]`. Group 1 is the first id, group 2 the
|
|
138
|
+
* rest after the first `;`, read by {@link bracketCitations}.
|
|
139
|
+
*/
|
|
140
|
+
export const CITATION_BRACKET = /\[@([a-z0-9][a-z0-9.-]*)(?:;[ \t\r\n]*([^\]]*))?\]/g;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* The citations one bracket holds, in order, as `{ id, locator }`. A
|
|
144
|
+
* `;`-separated part that is only `@id` starts another citation (Pandoc's
|
|
145
|
+
* `[@a; @b]`); any other part belongs to the locator of the citation before
|
|
146
|
+
* it, so a locator may itself contain `;` (`[@a; §1.2; eq. 3]`).
|
|
147
|
+
*
|
|
148
|
+
* @param {string} firstId
|
|
149
|
+
* @param {string | undefined} rest
|
|
150
|
+
* @returns {{ id: string, locator: string }[]}
|
|
151
|
+
*/
|
|
152
|
+
export function bracketCitations(firstId, rest) {
|
|
153
|
+
const citations = [{ id: String(firstId).trim(), parts: [] }];
|
|
154
|
+
for (const part of String(rest ?? '').split(';')) {
|
|
155
|
+
const next = /^\s*@([a-z0-9][a-z0-9.-]*)\s*$/.exec(part);
|
|
156
|
+
if (next) citations.push({ id: next[1], parts: [] });
|
|
157
|
+
else if (part.trim()) citations[citations.length - 1].parts.push(part);
|
|
158
|
+
}
|
|
159
|
+
return citations.map(({ id, parts }) => ({
|
|
160
|
+
id,
|
|
161
|
+
locator: parts.join(';').replace(/\s+/g, ' ').trim(),
|
|
162
|
+
}));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** Every source id a text cites, `[@a; @b]` included. */
|
|
166
|
+
export function citedIds(text) {
|
|
167
|
+
const ids = new Set();
|
|
168
|
+
for (const match of String(text).matchAll(CITATION_BRACKET)) {
|
|
169
|
+
for (const { id } of bracketCitations(match[1] ?? '', match[2])) ids.add(id);
|
|
170
|
+
}
|
|
171
|
+
return ids;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* A Markdown link whose text holds a citation, `[as measured in [@id]](url)`:
|
|
176
|
+
* remark-citation leaves link text alone (a link cannot hold the marker's
|
|
177
|
+
* link), so the citation would print as typed. Group 1 is the link text.
|
|
178
|
+
*/
|
|
179
|
+
const LINK_WITH_CITATION = /\[((?:[^[\]\n]|\[[^[\]\n]*\])*?\[@[^\]\n]*\](?:[^[\]\n]|\[[^[\]\n]*\])*)\]\(/g;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Each citation written inside a link's text, as `{ index, text }`: the
|
|
183
|
+
* offset of its `[@` in `text`, and the citation as written.
|
|
184
|
+
*/
|
|
185
|
+
export function citationsInLinks(text) {
|
|
186
|
+
const found = [];
|
|
187
|
+
for (const link of String(text).matchAll(LINK_WITH_CITATION)) {
|
|
188
|
+
const start = (link.index ?? 0) + 1;
|
|
189
|
+
for (const citation of (link[1] ?? '').matchAll(/\[@[^\]\n]*\]/g)) {
|
|
190
|
+
found.push({ index: start + (citation.index ?? 0), text: citation[0] });
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return found;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* `text` with every citation inside a link's text blanked, offsets kept: what
|
|
198
|
+
* the page cites, for a scan that counts a lesson's sources.
|
|
199
|
+
*/
|
|
200
|
+
export function withoutLinkCitations(text) {
|
|
201
|
+
let out = String(text);
|
|
202
|
+
for (const { index, text: citation } of citationsInLinks(out)) {
|
|
203
|
+
out = out.slice(0, index) + citation.replace(/[^\n]/g, ' ') + out.slice(index + citation.length);
|
|
204
|
+
}
|
|
205
|
+
return out;
|
|
206
|
+
}
|
|
207
|
+
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CurriculumCatalog } from '../curriculum/validation.js';
|
|
1
|
+
import { e as CourseOperators, f as CourseRomanLabels, g as CourseAccents } from '../course-config-rRtME5UV.js';
|
|
3
2
|
import { NotationSpec } from '../compiler/collections.js';
|
|
4
3
|
import { LintIgnore } from './lint-ignore.js';
|
|
5
4
|
import { NotationRegistry, NotationRegistryInput } from './types.js';
|
|
6
5
|
import '../rules/catalog.js';
|
|
7
6
|
import '../rules/course-rules.js';
|
|
7
|
+
import '../curriculum/validation.js';
|
|
8
|
+
import './gate-retired-keys.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Corpus consistency checks (Step D6) — the Tier 1–2 checks from the cleanup
|
|
@@ -20,9 +21,7 @@ import '../rules/course-rules.js';
|
|
|
20
21
|
* (a) glyph-unique-in-corpus one rendered glyph → one meaning corpus-wide
|
|
21
22
|
* (b) notation-units / units-vocab every entry has units or `dimensionless`,
|
|
22
23
|
* unit strings drawn from a controlled vocab
|
|
23
|
-
* (
|
|
24
|
-
* lesson uses resolves to one declaration
|
|
25
|
-
* (f) weak-local a `notation.local` symbol used only in its
|
|
24
|
+
* (f) weak-local a `notation.local` symbol used only in its
|
|
26
25
|
* own defining equation and prose
|
|
27
26
|
* (g) notation-source-locator every notation `sources` entry has a locator
|
|
28
27
|
* (h) operator-explained a named operator a lesson uses is on the
|
|
@@ -45,7 +44,7 @@ import '../rules/course-rules.js';
|
|
|
45
44
|
* `src/content/resolution-report.ts`.
|
|
46
45
|
*/
|
|
47
46
|
|
|
48
|
-
type ConsistencyCode = 'glyph-unique-in-corpus' | 'notation-units' | 'units-vocab' | '
|
|
47
|
+
type ConsistencyCode = 'glyph-unique-in-corpus' | 'notation-units' | 'units-vocab' | 'weak-local' | 'notation-source-locator' | 'gloss-wants-promoting' | 'card-wants-demoting' | 'gloss-name-shape' | 'operator-explained' | 'roman-label-explained' | 'accent-explained' | 'accent-swallowed' | 'operator-suspended' | 'operator-suspension-reason' | 'operator-shadowed';
|
|
49
48
|
interface ConsistencyDiagnostic {
|
|
50
49
|
readonly code: ConsistencyCode;
|
|
51
50
|
/** Tier 3 — repairable violations are warnings; optional advice is info. */
|
|
@@ -62,10 +61,7 @@ interface ConsistencyInput {
|
|
|
62
61
|
readonly registry: NotationRegistry;
|
|
63
62
|
readonly notationInput: NotationRegistryInput;
|
|
64
63
|
readonly specs: readonly NotationSpec[];
|
|
65
|
-
readonly catalog: CurriculumCatalog;
|
|
66
64
|
readonly lintIgnore: LintIgnore;
|
|
67
|
-
/** Convention keys this course anchors on (from `content/course.config.ts`). */
|
|
68
|
-
readonly conventions: CourseConventions;
|
|
69
65
|
/** This course's edits to the named-operator baseline (rule N8). */
|
|
70
66
|
readonly operators?: CourseOperators;
|
|
71
67
|
/** This course's edits to the roman-label baseline (rule N10). */
|