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
|
@@ -40,10 +40,16 @@ import {
|
|
|
40
40
|
import {
|
|
41
41
|
validateRawFloats
|
|
42
42
|
} from "../reference/raw-floats-validate.js";
|
|
43
|
+
import {
|
|
44
|
+
validateLabKatexImports
|
|
45
|
+
} from "../reference/lab-katex-validate.js";
|
|
43
46
|
import {
|
|
44
47
|
gateContentMath,
|
|
45
|
-
pageScope
|
|
48
|
+
pageScope,
|
|
49
|
+
scopeEntry
|
|
46
50
|
} from "../reference/gate-math.js";
|
|
51
|
+
import { gateIndices } from "../reference/gate-indices.js";
|
|
52
|
+
import { derivedNotationEntries } from "../reference/derived-entries.js";
|
|
47
53
|
import {
|
|
48
54
|
gateProseNotation,
|
|
49
55
|
gateProseNotationInAssessments
|
|
@@ -57,12 +63,18 @@ import { gateCourseRules } from "../reference/gate-course-rules.js";
|
|
|
57
63
|
import { gateHeadingLength } from "../reference/gate-heading-length.js";
|
|
58
64
|
import { gateHeadingStructure } from "../reference/gate-heading-structure.js";
|
|
59
65
|
import { gatePartPages } from "../reference/gate-part-pages.js";
|
|
66
|
+
import { gateNonChapterPages } from "../reference/gate-non-chapter-pages.js";
|
|
67
|
+
import { findRetiredKeys, findUnsupportedKeys } from "../reference/gate-retired-keys.js";
|
|
68
|
+
import { findMarkupInProps } from "../reference/gate-prop-text.js";
|
|
69
|
+
import { gateMdxExpressions } from "../reference/gate-mdx-expression.js";
|
|
70
|
+
import { CITATION_BRACKET, bracketCitations, withoutLinkCitations } from "../reference/citation-format.mjs";
|
|
71
|
+
import { validateContentSchemas } from "./content-schema.js";
|
|
60
72
|
import {
|
|
61
73
|
scanSectionHeadings,
|
|
62
74
|
scanTitledBlocks
|
|
63
75
|
} from "../reference/sections.mjs";
|
|
64
76
|
import { knowledgeCheckAnchorId } from "../reference/knowledge-checks.mjs";
|
|
65
|
-
import { validateSectionRefs } from "../reference/sections-validate.js";
|
|
77
|
+
import { validateHeadingAnchors, validateSectionRefs } from "../reference/sections-validate.js";
|
|
66
78
|
import {
|
|
67
79
|
splitMixedContent
|
|
68
80
|
} from "../reference/mixed-content.js";
|
|
@@ -73,6 +85,7 @@ import { resolveReferenceId } from "../reference/references.js";
|
|
|
73
85
|
import {
|
|
74
86
|
coursePartsOf,
|
|
75
87
|
normalizeBlockLabels,
|
|
88
|
+
normalizeCards,
|
|
76
89
|
normalizeLessonExports,
|
|
77
90
|
normalizeDisclosure,
|
|
78
91
|
normalizeNumbering
|
|
@@ -93,9 +106,11 @@ import {
|
|
|
93
106
|
} from "./knowledge-version.js";
|
|
94
107
|
import {
|
|
95
108
|
loadAbbreviationRegistryInput,
|
|
109
|
+
loadContentRecords,
|
|
96
110
|
loadCurriculumCatalog,
|
|
97
111
|
loadNotationDefinitions,
|
|
98
112
|
loadNotationRegistryInput,
|
|
113
|
+
loadNonChapterPages,
|
|
99
114
|
loadNotationSpecs,
|
|
100
115
|
loadPartOverviews,
|
|
101
116
|
loadSourceRecords
|
|
@@ -106,7 +121,7 @@ import {
|
|
|
106
121
|
isLessonSlug,
|
|
107
122
|
lessonIdFromSlug
|
|
108
123
|
} from "./lesson-derivation.js";
|
|
109
|
-
const MANIFEST_SCHEMA_VERSION =
|
|
124
|
+
const MANIFEST_SCHEMA_VERSION = 31;
|
|
110
125
|
const REPOSITORY_ROOT = process.cwd();
|
|
111
126
|
const CONTENT_ROOT = join(REPOSITORY_ROOT, "content");
|
|
112
127
|
const MANIFEST_PATH = join(REPOSITORY_ROOT, "build", "manifest.json");
|
|
@@ -119,18 +134,19 @@ function readEnginePackage() {
|
|
|
119
134
|
}
|
|
120
135
|
return enginePackage;
|
|
121
136
|
}
|
|
122
|
-
const CITE_PATTERN = /\[@([a-z0-9][a-z0-9.-]*)(?:;[ \t\r\n]*([^\]]*))?\]/g;
|
|
123
137
|
function lessonCitations(body) {
|
|
124
138
|
const withoutCode = body.replace(/```[\s\S]*?```/g, "").replace(/`[^`\n]*`/g, "");
|
|
125
139
|
const seen = /* @__PURE__ */ new Set();
|
|
126
140
|
const citations = [];
|
|
127
|
-
for (const match of withoutCode.matchAll(
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
141
|
+
for (const match of withoutLinkCitations(withoutCode).matchAll(CITATION_BRACKET)) {
|
|
142
|
+
for (const citation of bracketCitations(match[1] ?? "", match[2])) {
|
|
143
|
+
const id = citation.id;
|
|
144
|
+
const locator = citation.locator || void 0;
|
|
145
|
+
const dedupeKey = `${id} ${locator ?? ""}`;
|
|
146
|
+
if (seen.has(dedupeKey)) continue;
|
|
147
|
+
seen.add(dedupeKey);
|
|
148
|
+
citations.push(locator === void 0 ? { id } : { id, locator });
|
|
149
|
+
}
|
|
134
150
|
}
|
|
135
151
|
return citations;
|
|
136
152
|
}
|
|
@@ -170,17 +186,21 @@ function lessonNotationResolution(lesson, definitionsById, availableDefinitionId
|
|
|
170
186
|
key: reference.key,
|
|
171
187
|
scope: definition ? definition.kind === "shared" ? "shared" : "local" : "unresolved",
|
|
172
188
|
definitionId: definitionId ?? null,
|
|
173
|
-
|
|
189
|
+
// A page's own references are prose or math; a definition's formula
|
|
190
|
+
// reference is reported as the definition reference it always was.
|
|
191
|
+
kind: reference.kind === "formula" ? "definition" : reference.kind,
|
|
174
192
|
line: reference.source.line ?? null,
|
|
175
193
|
column: reference.source.column ?? null
|
|
176
194
|
};
|
|
177
195
|
});
|
|
178
196
|
}
|
|
179
|
-
function lessonNotationBundle(bundle, definitionsById, resolution, cardsByKey) {
|
|
197
|
+
function lessonNotationBundle(bundle, definitionsById, resolution, cardsByKey, derivedUses = []) {
|
|
180
198
|
const definitions = [];
|
|
199
|
+
const records = [];
|
|
181
200
|
for (const definitionId of bundle?.definitionIds ?? []) {
|
|
182
201
|
const definition = definitionsById.get(definitionId);
|
|
183
202
|
if (!definition) continue;
|
|
203
|
+
records.push(definition);
|
|
184
204
|
definitions.push({
|
|
185
205
|
id: definition.id,
|
|
186
206
|
key: definition.key,
|
|
@@ -188,7 +208,6 @@ function lessonNotationBundle(bundle, definitionsById, resolution, cardsByKey) {
|
|
|
188
208
|
notation: definition.notation,
|
|
189
209
|
label: definition.label,
|
|
190
210
|
summary: definition.summary,
|
|
191
|
-
editorialStatus: definition.status,
|
|
192
211
|
seeAlso: [...definition.seeAlso],
|
|
193
212
|
glosses: [...definition.glosses],
|
|
194
213
|
formulaScope: formulaGlyphScope({
|
|
@@ -199,13 +218,19 @@ function lessonNotationBundle(bundle, definitionsById, resolution, cardsByKey) {
|
|
|
199
218
|
...definition.formula === void 0 ? {} : { formula: definition.formula }
|
|
200
219
|
}),
|
|
201
220
|
...definition.units === void 0 ? {} : { units: definition.units },
|
|
202
|
-
...definition.formula === void 0 ? {} : { formula: definition.formula }
|
|
221
|
+
...definition.formula === void 0 ? {} : { formula: definition.formula },
|
|
222
|
+
...definition.range === void 0 ? {} : { range: definition.range }
|
|
203
223
|
});
|
|
204
224
|
}
|
|
205
225
|
return {
|
|
206
226
|
bindings: [...bundle?.bindings ?? []].map((binding) => ({ ...binding })),
|
|
207
227
|
definitionIds: [...bundle?.definitionIds ?? []],
|
|
208
228
|
definitions,
|
|
229
|
+
derived: derivedNotationEntries(
|
|
230
|
+
derivedUses,
|
|
231
|
+
new Map(records.map((record) => [record.key, record])),
|
|
232
|
+
cardsByKey
|
|
233
|
+
),
|
|
209
234
|
resolution: [...resolution]
|
|
210
235
|
};
|
|
211
236
|
}
|
|
@@ -260,11 +285,19 @@ async function compileManifest(courseConfig) {
|
|
|
260
285
|
loadNotationRegistryInput(),
|
|
261
286
|
loadAbbreviationRegistryInput()
|
|
262
287
|
]);
|
|
263
|
-
const
|
|
288
|
+
const nonChapterPages = loadNonChapterPages();
|
|
289
|
+
const withPages = {
|
|
290
|
+
...notationInput,
|
|
291
|
+
lessons: [
|
|
292
|
+
...notationInput.lessons,
|
|
293
|
+
...nonChapterPages.map((page) => page.notation)
|
|
294
|
+
]
|
|
295
|
+
};
|
|
296
|
+
const registry = buildNotationRegistry(withPages);
|
|
264
297
|
const cardsByKey = new Map(
|
|
265
298
|
notationInput.sharedDefinitions.map((definition) => [
|
|
266
299
|
definition.key,
|
|
267
|
-
|
|
300
|
+
scopeEntry(definition)
|
|
268
301
|
])
|
|
269
302
|
);
|
|
270
303
|
const definitionsById = new Map(
|
|
@@ -275,23 +308,55 @@ async function compileManifest(courseConfig) {
|
|
|
275
308
|
registry.bundles.map((bundle) => [bundle.lessonId, bundle])
|
|
276
309
|
);
|
|
277
310
|
const assessmentsInput = catalog.assessments;
|
|
278
|
-
const
|
|
311
|
+
const contentRecords = loadContentRecords();
|
|
312
|
+
const curriculumIssues = [
|
|
313
|
+
...validateCurriculum(catalog),
|
|
314
|
+
...validateContentSchemas(contentRecords),
|
|
315
|
+
...findRetiredKeys(contentRecords),
|
|
316
|
+
...findUnsupportedKeys(contentRecords),
|
|
317
|
+
...findMarkupInProps(contentRecords)
|
|
318
|
+
];
|
|
279
319
|
const alignmentIssues = validateNotationAlignment(registry, catalog);
|
|
280
320
|
const mathEndAbbreviations = {
|
|
281
321
|
allow: rules.strings("N12", "allow"),
|
|
282
322
|
deny: rules.strings("N12", "deny")
|
|
283
323
|
};
|
|
324
|
+
const sharedLabels = new Map(
|
|
325
|
+
notationInput.sharedDefinitions.map((definition) => [definition.key, definition.label])
|
|
326
|
+
);
|
|
327
|
+
const localLabelsByLesson = new Map(
|
|
328
|
+
notationInput.lessons.map((lesson) => [
|
|
329
|
+
lesson.lessonId,
|
|
330
|
+
new Map(lesson.localDefinitions.map((definition) => [definition.key, definition.label]))
|
|
331
|
+
])
|
|
332
|
+
);
|
|
333
|
+
const termLabel = (lessonId, key) => localLabelsByLesson.get(lessonId)?.get(key) ?? sharedLabels.get(key);
|
|
334
|
+
const indexGate = gateIndices(
|
|
335
|
+
withPages.lessons,
|
|
336
|
+
new Map(
|
|
337
|
+
notationInput.sharedDefinitions.map((definition) => [definition.key, definition])
|
|
338
|
+
),
|
|
339
|
+
{
|
|
340
|
+
assessments: assessmentsInput,
|
|
341
|
+
lessonAssessments: catalog.lessons.map((lesson) => ({
|
|
342
|
+
lessonId: lesson.id,
|
|
343
|
+
assessmentIds: lesson.assessments
|
|
344
|
+
}))
|
|
345
|
+
}
|
|
346
|
+
);
|
|
284
347
|
const mathIssues = [
|
|
348
|
+
...indexGate.diagnostics,
|
|
285
349
|
...gateContentMath({
|
|
286
|
-
notationInput,
|
|
350
|
+
notationInput: withPages,
|
|
287
351
|
assessments: assessmentsInput,
|
|
288
352
|
lessonAssessments: catalog.lessons.map((lesson) => ({
|
|
289
353
|
lessonId: lesson.id,
|
|
290
354
|
assessmentIds: lesson.assessments
|
|
291
355
|
}))
|
|
292
356
|
}),
|
|
357
|
+
...gateMdxExpressions(withPages.lessons),
|
|
293
358
|
...rules.isEnabled("N9") ? [
|
|
294
|
-
...gateProseNotation(
|
|
359
|
+
...gateProseNotation(withPages.lessons, {
|
|
295
360
|
allowSpelledUnits: rules.strings("N9", "allow")
|
|
296
361
|
}),
|
|
297
362
|
...gateProseNotationInAssessments(assessmentsInput, {
|
|
@@ -299,16 +364,17 @@ async function compileManifest(courseConfig) {
|
|
|
299
364
|
})
|
|
300
365
|
] : [],
|
|
301
366
|
...rules.isEnabled("N12") ? [
|
|
302
|
-
...gateMathPunctuation(
|
|
367
|
+
...gateMathPunctuation(withPages.lessons, mathEndAbbreviations),
|
|
303
368
|
...gateMathPunctuationInAssessments(assessmentsInput, mathEndAbbreviations)
|
|
304
369
|
] : [],
|
|
305
370
|
...rules.isEnabled("N14") ? gateAbbreviations({
|
|
306
|
-
notationInput,
|
|
371
|
+
notationInput: withPages,
|
|
307
372
|
abbreviations: abbreviationsInput,
|
|
308
373
|
courseAbbreviations: rules.settings("N14")
|
|
309
374
|
}) : [],
|
|
310
375
|
...rules.isEnabled("S1") ? gateHeadingLength(notationInput.lessons, {
|
|
311
|
-
maxLength: rules.number("S1", "maxLength")
|
|
376
|
+
maxLength: rules.number("S1", "maxLength"),
|
|
377
|
+
labelFor: termLabel
|
|
312
378
|
}) : [],
|
|
313
379
|
...gateHeadingStructure(notationInput.lessons, {
|
|
314
380
|
levels: rules.isEnabled("S6"),
|
|
@@ -317,7 +383,9 @@ async function compileManifest(courseConfig) {
|
|
|
317
383
|
// The course's own rules (`courseRules`): one pass for every enabled `X`
|
|
318
384
|
// rule that carries a `forbid` pattern. A disabled one, and a guide rule
|
|
319
385
|
// with no pattern, do no work here.
|
|
320
|
-
...gateCourseRules(
|
|
386
|
+
...gateCourseRules(withPages.lessons, rules.course),
|
|
387
|
+
// S10 is locked: a float on a non-chapter page has no number to render.
|
|
388
|
+
...gateNonChapterPages(nonChapterPages)
|
|
321
389
|
];
|
|
322
390
|
const notationLessonById = new Map(
|
|
323
391
|
notationInput.lessons.map((lesson) => [lesson.lessonId, lesson])
|
|
@@ -326,22 +394,46 @@ async function compileManifest(courseConfig) {
|
|
|
326
394
|
assessmentsInput.map((assessment) => [assessment.id, assessment])
|
|
327
395
|
);
|
|
328
396
|
const assessmentContent = [];
|
|
397
|
+
const assessmentDerived = /* @__PURE__ */ new Map();
|
|
329
398
|
for (const lesson of catalog.lessons) {
|
|
330
399
|
if (lesson.assessments.length === 0) continue;
|
|
331
400
|
const lessonInput = notationLessonById.get(lesson.id);
|
|
332
401
|
if (!lessonInput) continue;
|
|
333
402
|
const scope = pageScope(lessonInput, cardsByKey);
|
|
403
|
+
const derived = /* @__PURE__ */ new Map();
|
|
404
|
+
assessmentDerived.set(lesson.id, derived);
|
|
405
|
+
const page = { derive: true, derived };
|
|
334
406
|
for (const assessmentId of lesson.assessments) {
|
|
335
407
|
const assessment = assessmentInputById.get(assessmentId);
|
|
336
408
|
if (!assessment?.items) continue;
|
|
337
409
|
for (const item of assessment.items) {
|
|
338
410
|
if (!item.id) continue;
|
|
411
|
+
const numeric = item.type === "numeric" && typeof item.answer?.value === "number" && typeof item.answer.tolerance === "number";
|
|
339
412
|
assessmentContent.push({
|
|
340
413
|
lessonId: lesson.id,
|
|
341
414
|
assessmentId,
|
|
342
415
|
itemId: item.id,
|
|
343
|
-
promptSegments: splitMixedContent(item.prompt ?? "", scope),
|
|
344
|
-
explanationSegments: splitMixedContent(item.explanation ?? "", scope)
|
|
416
|
+
promptSegments: splitMixedContent(item.prompt ?? "", scope, page),
|
|
417
|
+
explanationSegments: splitMixedContent(item.explanation ?? "", scope, page),
|
|
418
|
+
type: item.type === "numeric" ? "numeric" : "single-choice",
|
|
419
|
+
...item.options ? {
|
|
420
|
+
options: item.options.flatMap(
|
|
421
|
+
(option) => option.id ? [
|
|
422
|
+
{
|
|
423
|
+
id: option.id,
|
|
424
|
+
label: option.label ?? "",
|
|
425
|
+
labelSegments: splitMixedContent(option.label ?? "", scope, page)
|
|
426
|
+
}
|
|
427
|
+
] : []
|
|
428
|
+
)
|
|
429
|
+
} : {},
|
|
430
|
+
...item.correctOptionId ? { correctOptionId: item.correctOptionId } : {},
|
|
431
|
+
...numeric ? {
|
|
432
|
+
answer: {
|
|
433
|
+
value: item.answer.value,
|
|
434
|
+
tolerance: item.answer.tolerance
|
|
435
|
+
}
|
|
436
|
+
} : {}
|
|
345
437
|
});
|
|
346
438
|
}
|
|
347
439
|
}
|
|
@@ -365,9 +457,31 @@ async function compileManifest(courseConfig) {
|
|
|
365
457
|
);
|
|
366
458
|
const frontmatterById = lessonFrontmatterById();
|
|
367
459
|
const lessonSlugs = [...notationInput.lessons].map((lesson) => lesson.lessonId.replace(/\./g, "/")).sort();
|
|
368
|
-
const
|
|
369
|
-
const overviewPages = loadPartOverviews(
|
|
460
|
+
const listedParts = coursePartsOf(courseConfig);
|
|
461
|
+
const overviewPages = loadPartOverviews(listedParts);
|
|
370
462
|
const overviewByDir = new Map(overviewPages.map((page) => [page.dir, page]));
|
|
463
|
+
const hasChapter = (dir) => lessonSlugs.some((slug) => slug.startsWith(`${dir}/`));
|
|
464
|
+
const configuredParts = listedParts.filter(
|
|
465
|
+
(part) => hasChapter(part.dir) || overviewByDir.has(part.dir)
|
|
466
|
+
);
|
|
467
|
+
for (const part of listedParts) {
|
|
468
|
+
if (configuredParts.includes(part)) continue;
|
|
469
|
+
curriculumIssues.push({
|
|
470
|
+
kind: "part-empty",
|
|
471
|
+
severity: "warning",
|
|
472
|
+
message: `course.settings.json \`parts\` lists "${part.dir}" (${JSON.stringify(part.label)}), but content/docs/${part.dir}/ has no chapter and no overview page yet, so the part is left out of the sidebar and the numbering until it has one.`
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
const partDirs = new Set(listedParts.map((part) => part.dir));
|
|
476
|
+
for (const lesson of notationInput.lessons) {
|
|
477
|
+
const dir = lesson.lessonId.split(".")[0] ?? "";
|
|
478
|
+
if (partDirs.has(dir)) continue;
|
|
479
|
+
curriculumIssues.push({
|
|
480
|
+
kind: "lesson-outside-parts",
|
|
481
|
+
message: `${lesson.source.file} is in content/docs/${dir}/, which no part in course.settings.json \`parts\` lists, so it has no part, no chapter number and no place in the sidebar. Add { "dir": "${dir}", "label": "\u2026" } to \`parts\`, or move the lesson into a part's directory.`,
|
|
482
|
+
file: lesson.source.file
|
|
483
|
+
});
|
|
484
|
+
}
|
|
371
485
|
if (rules.isEnabled("S2")) {
|
|
372
486
|
mathIssues.push(
|
|
373
487
|
...gatePartPages(
|
|
@@ -381,7 +495,7 @@ async function compileManifest(courseConfig) {
|
|
|
381
495
|
}
|
|
382
496
|
const waiverDiagnostics = [];
|
|
383
497
|
const waiverRules = { courseRules: rules.course };
|
|
384
|
-
const waivers =
|
|
498
|
+
const waivers = withPages.lessons.flatMap((lesson) => {
|
|
385
499
|
const collected = collectWaivers(lesson, waiverRules);
|
|
386
500
|
waiverDiagnostics.push(...collected.diagnostics);
|
|
387
501
|
return collected.waivers;
|
|
@@ -408,10 +522,10 @@ async function compileManifest(courseConfig) {
|
|
|
408
522
|
const placementByLessonId = /* @__PURE__ */ new Map();
|
|
409
523
|
const chapterScoped = numberingSettings.floats === "chapter";
|
|
410
524
|
let partCursor = 0;
|
|
411
|
-
for (const group of sidebar) {
|
|
525
|
+
for (const group of sidebar.slice(0, configuredParts.length)) {
|
|
526
|
+
partCursor += 1;
|
|
412
527
|
const lessonIds = group.items.filter((item) => typeof item === "string").map(lessonIdFromSlug);
|
|
413
528
|
if (lessonIds.length === 0) continue;
|
|
414
|
-
partCursor += 1;
|
|
415
529
|
const used = {
|
|
416
530
|
equations: 0,
|
|
417
531
|
tables: 0,
|
|
@@ -452,7 +566,8 @@ async function compileManifest(courseConfig) {
|
|
|
452
566
|
lesson.lessonId,
|
|
453
567
|
scanSectionHeadings(lesson.body, {
|
|
454
568
|
...placement ? { prefix: `${placement.part}.${placement.chapter}` } : {},
|
|
455
|
-
depth: numberingSettings.sections.depth
|
|
569
|
+
depth: numberingSettings.sections.depth,
|
|
570
|
+
labelFor: (key) => termLabel(lesson.lessonId, key)
|
|
456
571
|
})
|
|
457
572
|
];
|
|
458
573
|
})
|
|
@@ -467,7 +582,8 @@ async function compileManifest(courseConfig) {
|
|
|
467
582
|
headingSlugs: (headingsByLessonId.get(lesson.lessonId) ?? []).map(
|
|
468
583
|
(heading) => heading.slug
|
|
469
584
|
)
|
|
470
|
-
}))
|
|
585
|
+
})),
|
|
586
|
+
nonChapterPages.map((page) => page.slug)
|
|
471
587
|
)
|
|
472
588
|
);
|
|
473
589
|
const manifestParts = configuredParts.map((part, index) => {
|
|
@@ -569,6 +685,45 @@ async function compileManifest(courseConfig) {
|
|
|
569
685
|
})
|
|
570
686
|
])
|
|
571
687
|
);
|
|
688
|
+
const engineAnchorsFor = (lessonId, body) => {
|
|
689
|
+
const slug = lessonId.replace(/\./g, "/");
|
|
690
|
+
const anchors = /* @__PURE__ */ new Map();
|
|
691
|
+
const keyed = (floats, prefix, owner) => {
|
|
692
|
+
for (const float of floats) anchors.set(`${prefix}-${float.key}`, owner(float.key));
|
|
693
|
+
};
|
|
694
|
+
keyed(equationsBySlug.get(slug) ?? [], "eq", (key) => `the equation labelled eq:${key}`);
|
|
695
|
+
keyed(tablesBySlug.get(slug) ?? [], "tab", (key) => `<Table id="${key}">`);
|
|
696
|
+
keyed(figuresBySlug.get(slug) ?? [], "fig", (key) => `<Figure id="${key}">`);
|
|
697
|
+
keyed(diagramsBySlug.get(slug) ?? [], "dia", (key) => `<Diagram id="${key}">`);
|
|
698
|
+
keyed(examplesBySlug.get(slug) ?? [], "ex", (key) => `<CompactExamples id="${key}">`);
|
|
699
|
+
for (const check of checksBySlug.get(slug) ?? []) {
|
|
700
|
+
anchors.set(knowledgeCheckAnchorId(check.key), `the knowledge check ${check.key}`);
|
|
701
|
+
}
|
|
702
|
+
for (const [name, prefix] of [
|
|
703
|
+
["Memo", "memo"],
|
|
704
|
+
["ShortNote", "short-note"]
|
|
705
|
+
]) {
|
|
706
|
+
const tag = new RegExp(`<${name}\\b[^>]*?\\bid=["']([^"']+)["']`, "g");
|
|
707
|
+
for (const match of body.matchAll(tag)) {
|
|
708
|
+
anchors.set(`${prefix}-${match[1]}`, `<${name} id="${match[1]}">`);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
if (deriveSources(body).length > 0) {
|
|
712
|
+
anchors.set("references", "the References section generated from the page\u2019s citations");
|
|
713
|
+
}
|
|
714
|
+
return anchors;
|
|
715
|
+
};
|
|
716
|
+
mathIssues.push(
|
|
717
|
+
...validateHeadingAnchors(
|
|
718
|
+
notationInput.lessons.map((lesson) => ({
|
|
719
|
+
file: lesson.source.file,
|
|
720
|
+
body: lesson.body,
|
|
721
|
+
...lesson.bodyLine === void 0 ? {} : { bodyLine: lesson.bodyLine },
|
|
722
|
+
headings: headingsByLessonId.get(lesson.lessonId) ?? [],
|
|
723
|
+
anchors: engineAnchorsFor(lesson.lessonId, lesson.body)
|
|
724
|
+
}))
|
|
725
|
+
)
|
|
726
|
+
);
|
|
572
727
|
const titledBlocksFor = (lessonId) => {
|
|
573
728
|
const slug = lessonId.replace(/\./g, "/");
|
|
574
729
|
const body = bodyByLessonId.get(lessonId) ?? "";
|
|
@@ -593,6 +748,14 @@ async function compileManifest(courseConfig) {
|
|
|
593
748
|
}
|
|
594
749
|
);
|
|
595
750
|
};
|
|
751
|
+
const labKatexDiagnostics = validateLabKatexImports(
|
|
752
|
+
notationInput.lessons.map((lesson) => ({
|
|
753
|
+
lessonId: lesson.lessonId,
|
|
754
|
+
file: lesson.source.file,
|
|
755
|
+
body: lesson.body
|
|
756
|
+
})),
|
|
757
|
+
REPOSITORY_ROOT
|
|
758
|
+
);
|
|
596
759
|
const rawFloatDiagnostics = validateRawFloats(
|
|
597
760
|
notationInput.lessons.map((lesson) => ({
|
|
598
761
|
lessonId: lesson.lessonId,
|
|
@@ -633,7 +796,6 @@ async function compileManifest(courseConfig) {
|
|
|
633
796
|
title: frontmatter.title,
|
|
634
797
|
description: frontmatter.description,
|
|
635
798
|
...frontmatter.studyMinutes === void 0 ? {} : { studyMinutes: frontmatter.studyMinutes },
|
|
636
|
-
status: meta.status,
|
|
637
799
|
teaches: [...teaches],
|
|
638
800
|
requires: [...meta.requires],
|
|
639
801
|
assumptions: [...meta.assumptions],
|
|
@@ -660,18 +822,36 @@ async function compileManifest(courseConfig) {
|
|
|
660
822
|
definitionsById,
|
|
661
823
|
availableDefinitionIds
|
|
662
824
|
),
|
|
663
|
-
cardsByKey
|
|
825
|
+
cardsByKey,
|
|
826
|
+
[
|
|
827
|
+
...indexGate.derivedByLesson.get(id) ?? [],
|
|
828
|
+
...assessmentDerived.get(id)?.values() ?? []
|
|
829
|
+
]
|
|
664
830
|
)
|
|
665
831
|
});
|
|
666
832
|
}
|
|
667
833
|
lessons.sort((a, b) => a.id.localeCompare(b.id));
|
|
834
|
+
const pages = nonChapterPages.map((page) => ({
|
|
835
|
+
id: page.id,
|
|
836
|
+
slug: page.slug,
|
|
837
|
+
file: page.file,
|
|
838
|
+
notation: lessonNotationBundle(
|
|
839
|
+
bundlesByLesson.get(page.id),
|
|
840
|
+
definitionsById,
|
|
841
|
+
lessonNotationResolution(
|
|
842
|
+
page.notation,
|
|
843
|
+
definitionsById,
|
|
844
|
+
availableDefinitionIds
|
|
845
|
+
),
|
|
846
|
+
cardsByKey,
|
|
847
|
+
indexGate.derivedByLesson.get(page.id)
|
|
848
|
+
)
|
|
849
|
+
})).sort((a, b) => a.id.localeCompare(b.id));
|
|
668
850
|
const consistencyIssues = runConsistencyChecks({
|
|
669
851
|
registry,
|
|
670
|
-
notationInput,
|
|
852
|
+
notationInput: withPages,
|
|
671
853
|
specs: loadNotationSpecs(),
|
|
672
|
-
catalog,
|
|
673
854
|
lintIgnore: loadLintIgnore(),
|
|
674
|
-
conventions: courseConfig.conventions,
|
|
675
855
|
operators: rules.settings("N8"),
|
|
676
856
|
romanLabels: rules.settings("N10"),
|
|
677
857
|
accents: rules.settings("N22")
|
|
@@ -726,6 +906,7 @@ async function compileManifest(courseConfig) {
|
|
|
726
906
|
disclosure: normalizeDisclosure(courseConfig),
|
|
727
907
|
numbering: numberingSettings,
|
|
728
908
|
blockLabels,
|
|
909
|
+
cards: normalizeCards(courseConfig),
|
|
729
910
|
about,
|
|
730
911
|
notation: {
|
|
731
912
|
definitions: registry.definitions,
|
|
@@ -741,6 +922,7 @@ async function compileManifest(courseConfig) {
|
|
|
741
922
|
sidebar,
|
|
742
923
|
parts: manifestParts,
|
|
743
924
|
lessons,
|
|
925
|
+
pages,
|
|
744
926
|
prereqEdges,
|
|
745
927
|
equations: {
|
|
746
928
|
labels: equationValidation.labels,
|
|
@@ -776,7 +958,7 @@ async function compileManifest(courseConfig) {
|
|
|
776
958
|
consistency: dropDisabled(consistencyIssues, off),
|
|
777
959
|
equations: dropDisabled(equationValidation.diagnostics, off),
|
|
778
960
|
tables: dropDisabled(tableValidation.diagnostics, off),
|
|
779
|
-
figures: dropDisabled(figureValidation.diagnostics, off),
|
|
961
|
+
figures: dropDisabled([...figureValidation.diagnostics, ...labKatexDiagnostics], off),
|
|
780
962
|
diagrams: dropDisabled(diagramValidation.diagnostics, off),
|
|
781
963
|
checks: dropDisabled(checkValidation.diagnostics, off),
|
|
782
964
|
examples: dropDisabled(exampleValidation.diagnostics, off),
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { DiagnosticSeverity } from '../reference/types.js';
|
|
2
|
+
import { Manifest } from './manifest.js';
|
|
3
|
+
import '../curriculum/validation.js';
|
|
4
|
+
import '../reference/consistency.js';
|
|
5
|
+
import '../course-config-rRtME5UV.js';
|
|
6
|
+
import '../rules/catalog.js';
|
|
7
|
+
import '../rules/course-rules.js';
|
|
8
|
+
import './collections.js';
|
|
9
|
+
import '../reference/gate-retired-keys.js';
|
|
10
|
+
import '../reference/lint-ignore.js';
|
|
11
|
+
import '../reference/equations-validate.js';
|
|
12
|
+
import '../reference/tables-validate.js';
|
|
13
|
+
import '../reference/keyed-float-validate.js';
|
|
14
|
+
import '../reference/figures-validate.js';
|
|
15
|
+
import '../reference/diagrams-validate.js';
|
|
16
|
+
import '../reference/examples-validate.js';
|
|
17
|
+
import '../reference/folds-validate.js';
|
|
18
|
+
import '../reference/knowledge-checks-validate.js';
|
|
19
|
+
import '../reference/raw-floats-validate.js';
|
|
20
|
+
import '../reference/lab-katex-validate.js';
|
|
21
|
+
import '../reference/gate-math.js';
|
|
22
|
+
import '../reference/mixed-content.js';
|
|
23
|
+
import '../reference/gloss.js';
|
|
24
|
+
import '../rules/waivers.js';
|
|
25
|
+
import './knowledge-version.js';
|
|
26
|
+
import './lesson-derivation.js';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Diagnostics only a rendered page can give, kept from one `astro build` for
|
|
30
|
+
* `content warnings`.
|
|
31
|
+
*
|
|
32
|
+
* Most checks read the content tree, so the manifest carries them and every
|
|
33
|
+
* `content` command recomputes them. A few need the page as Astro renders it:
|
|
34
|
+
* a diagram drawn by a wrapper component lays out to a width only its render
|
|
35
|
+
* knows (rule V8, `reference/diagram-fit.ts`). `compiler/astro.ts` reports
|
|
36
|
+
* those as the build finishes and writes them to
|
|
37
|
+
* `build/render-diagnostics.json`, replacing the previous build's; the
|
|
38
|
+
* `content` CLI lists them beside the manifest's under the `render:` source.
|
|
39
|
+
* They are as current as the last build: run `pnpm build` (or `astro build`)
|
|
40
|
+
* after changing a diagram to refresh them.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
declare const RENDER_DIAGNOSTICS_PATH: string;
|
|
44
|
+
interface RenderDiagnostic {
|
|
45
|
+
readonly code: string;
|
|
46
|
+
readonly severity: DiagnosticSeverity;
|
|
47
|
+
readonly message: string;
|
|
48
|
+
/** The lesson's source file, e.g. `content/docs/motion/range.mdx`; else the built page. */
|
|
49
|
+
readonly file: string;
|
|
50
|
+
readonly lessonId?: string;
|
|
51
|
+
/** The float the finding is about, e.g. a diagram's `id`. */
|
|
52
|
+
readonly key?: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The render diagnostics of one built page. A diagram that appears on more
|
|
56
|
+
* than one page (a lesson and its standalone export) is reported once per
|
|
57
|
+
* lesson by {@link writeRenderDiagnostics}.
|
|
58
|
+
*/
|
|
59
|
+
declare function pageRenderDiagnostics(manifest: Pick<Manifest, 'lessons'>, page: string, html: string): RenderDiagnostic[];
|
|
60
|
+
/** Replace the last build's render diagnostics with these, deduplicated and sorted. */
|
|
61
|
+
declare function writeRenderDiagnostics(diagnostics: readonly RenderDiagnostic[], path?: string): readonly RenderDiagnostic[];
|
|
62
|
+
/** What the last build reported; `[]` before the first build. */
|
|
63
|
+
declare function readRenderDiagnostics(path?: string): readonly RenderDiagnostic[];
|
|
64
|
+
|
|
65
|
+
export { RENDER_DIAGNOSTICS_PATH, type RenderDiagnostic, pageRenderDiagnostics, readRenderDiagnostics, writeRenderDiagnostics };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
diagramTooWideMessage,
|
|
5
|
+
oversizedDiagrams
|
|
6
|
+
} from "../reference/diagram-fit.js";
|
|
7
|
+
const RENDER_DIAGNOSTICS_PATH = join(
|
|
8
|
+
process.cwd(),
|
|
9
|
+
"build",
|
|
10
|
+
"render-diagnostics.json"
|
|
11
|
+
);
|
|
12
|
+
function slugOfPage(page) {
|
|
13
|
+
return page.split(/[\\/]/u).join("/").replace(/(^|\/)index\.html$/u, "").replace(/\.html$/u, "");
|
|
14
|
+
}
|
|
15
|
+
function pageRenderDiagnostics(manifest, page, html) {
|
|
16
|
+
const oversized = oversizedDiagrams(html);
|
|
17
|
+
if (oversized.length === 0) return [];
|
|
18
|
+
const slug = slugOfPage(page);
|
|
19
|
+
const lesson = manifest.lessons.find((candidate) => candidate.slug === slug);
|
|
20
|
+
return oversized.map((diagram) => ({
|
|
21
|
+
code: diagram.code,
|
|
22
|
+
severity: "warning",
|
|
23
|
+
message: diagramTooWideMessage(diagram.key, diagram.width, diagram.limit),
|
|
24
|
+
file: lesson?.file ?? page,
|
|
25
|
+
...lesson ? { lessonId: lesson.id } : {},
|
|
26
|
+
key: diagram.key
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
function writeRenderDiagnostics(diagnostics, path = RENDER_DIAGNOSTICS_PATH) {
|
|
30
|
+
const unique = /* @__PURE__ */ new Map();
|
|
31
|
+
for (const diagnostic of diagnostics) {
|
|
32
|
+
unique.set(`${diagnostic.file}\0${diagnostic.code}\0${diagnostic.key ?? diagnostic.message}`, diagnostic);
|
|
33
|
+
}
|
|
34
|
+
const sorted = [...unique.values()].sort(
|
|
35
|
+
(a, b) => a.file.localeCompare(b.file) || a.code.localeCompare(b.code) || (a.key ?? "").localeCompare(b.key ?? "")
|
|
36
|
+
);
|
|
37
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
38
|
+
writeFileSync(path, `${JSON.stringify({ diagnostics: sorted }, null, 2)}
|
|
39
|
+
`);
|
|
40
|
+
return sorted;
|
|
41
|
+
}
|
|
42
|
+
function readRenderDiagnostics(path = RENDER_DIAGNOSTICS_PATH) {
|
|
43
|
+
if (!existsSync(path)) return [];
|
|
44
|
+
try {
|
|
45
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
46
|
+
return Array.isArray(parsed.diagnostics) ? parsed.diagnostics : [];
|
|
47
|
+
} catch {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
RENDER_DIAGNOSTICS_PATH,
|
|
53
|
+
pageRenderDiagnostics,
|
|
54
|
+
readRenderDiagnostics,
|
|
55
|
+
writeRenderDiagnostics
|
|
56
|
+
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Manifest } from './manifest.js';
|
|
2
2
|
import '../curriculum/validation.js';
|
|
3
3
|
import '../reference/consistency.js';
|
|
4
|
-
import '../course-config-
|
|
4
|
+
import '../course-config-rRtME5UV.js';
|
|
5
5
|
import '../rules/catalog.js';
|
|
6
6
|
import '../rules/course-rules.js';
|
|
7
7
|
import './collections.js';
|
|
8
8
|
import '../reference/types.js';
|
|
9
|
+
import '../reference/gate-retired-keys.js';
|
|
9
10
|
import '../reference/lint-ignore.js';
|
|
10
11
|
import '../reference/equations-validate.js';
|
|
11
12
|
import '../reference/tables-validate.js';
|
|
@@ -16,6 +17,7 @@ import '../reference/examples-validate.js';
|
|
|
16
17
|
import '../reference/folds-validate.js';
|
|
17
18
|
import '../reference/knowledge-checks-validate.js';
|
|
18
19
|
import '../reference/raw-floats-validate.js';
|
|
20
|
+
import '../reference/lab-katex-validate.js';
|
|
19
21
|
import '../reference/gate-math.js';
|
|
20
22
|
import '../reference/mixed-content.js';
|
|
21
23
|
import '../reference/gloss.js';
|