explico 0.3.0 → 0.5.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 +344 -1
- package/README.md +117 -3
- package/dist/compiler/astro.d.ts +38 -0
- package/dist/compiler/astro.js +258 -0
- package/dist/compiler/cli.d.ts +13 -0
- package/dist/compiler/cli.js +32 -12
- package/dist/compiler/collections.d.ts +3 -2
- package/dist/compiler/collections.js +28 -1
- package/dist/compiler/course-config.d.ts +86 -4
- package/dist/compiler/course-config.js +39 -0
- package/dist/compiler/exports/standalone-html.d.ts +34 -0
- package/dist/compiler/exports/standalone-html.js +803 -0
- package/dist/compiler/lesson-derivation.d.ts +1 -1
- package/dist/compiler/lesson-derivation.js +2 -2
- package/dist/compiler/manifest.d.ts +112 -7
- package/dist/compiler/manifest.js +205 -40
- package/dist/compiler/resolution-report.d.ts +4 -0
- package/dist/reference/base-abbreviations.d.mts +30 -0
- package/dist/reference/base-abbreviations.mjs +60 -0
- package/dist/reference/base-operators.d.mts +15 -0
- package/dist/reference/base-operators.mjs +40 -0
- package/dist/reference/base-roman-labels.d.mts +35 -0
- package/dist/reference/base-roman-labels.mjs +43 -0
- package/dist/reference/consistency.d.ts +8 -2
- package/dist/reference/consistency.js +50 -3
- package/dist/reference/diagrams-validate.d.ts +21 -0
- package/dist/reference/diagrams-validate.js +13 -0
- package/dist/reference/equations-validate.d.ts +8 -3
- package/dist/reference/equations-validate.js +1 -1
- package/dist/reference/equations.d.mts +66 -35
- package/dist/reference/equations.mjs +142 -40
- package/dist/reference/gate-abbreviations.d.ts +17 -0
- package/dist/reference/gate-abbreviations.js +64 -0
- package/dist/reference/gate-math.d.ts +28 -5
- package/dist/reference/gate-math.js +5 -2
- package/dist/reference/gate-prose-notation.d.ts +60 -0
- package/dist/reference/gate-prose-notation.js +125 -0
- package/dist/reference/keyed-float-validate.d.ts +14 -8
- package/dist/reference/keyed-float-validate.js +1 -1
- package/dist/reference/keyed-jsx-floats.d.mts +24 -21
- package/dist/reference/keyed-jsx-floats.mjs +90 -41
- package/dist/reference/knowledge-checks-validate.d.ts +35 -0
- package/dist/reference/knowledge-checks-validate.js +78 -0
- package/dist/reference/knowledge-checks.d.mts +25 -0
- package/dist/reference/knowledge-checks.mjs +45 -0
- package/dist/reference/lab-math-scope.d.ts +9 -1
- package/dist/reference/lab-math-scope.js +32 -4
- package/dist/reference/math-glyphs.d.mts +30 -0
- package/dist/reference/math-glyphs.mjs +367 -0
- package/dist/reference/mdx-attributes.d.mts +13 -0
- package/dist/reference/mdx-attributes.mjs +38 -0
- package/dist/reference/mixed-content.d.ts +17 -0
- package/dist/reference/mixed-content.js +29 -0
- package/dist/reference/page-notation.d.ts +52 -0
- package/dist/reference/page-notation.js +171 -0
- package/dist/reference/raw-floats-validate.d.ts +18 -0
- package/dist/reference/raw-floats-validate.js +53 -0
- package/dist/reference/raw-floats.d.mts +18 -0
- package/dist/reference/raw-floats.mjs +129 -0
- package/dist/reference/rehype-heading-anchors.d.mts +1 -1
- package/dist/reference/rehype-heading-anchors.mjs +107 -1
- package/dist/reference/rehype-table-header-labels.d.mts +26 -0
- package/dist/reference/rehype-table-header-labels.mjs +152 -0
- package/dist/reference/remark-abbreviations.d.mts +7 -0
- package/dist/reference/remark-abbreviations.mjs +174 -0
- package/dist/reference/remark-memo.d.mts +16 -0
- package/dist/reference/remark-memo.mjs +339 -0
- package/dist/reference/remark-notation.d.mts +102 -5
- package/dist/reference/remark-notation.mjs +506 -50
- package/dist/reference/remark-short-note.d.mts +4 -0
- package/dist/reference/remark-short-note.mjs +237 -0
- package/dist/reference/types.d.ts +16 -1
- package/dist/reference/units-vocab.js +4 -0
- package/docs/VERSIONING.md +33 -4
- package/docs/authoring/README.md +12 -0
- package/docs/authoring/agents.md +17 -2
- package/docs/authoring/components.md +135 -0
- package/docs/authoring/migrating.md +154 -7
- package/docs/authoring/notation.md +568 -8
- package/docs/authoring/structure.md +251 -0
- package/docs/authoring/visualizations.md +36 -3
- package/package.json +5 -2
- package/src/compiler/astro.ts +332 -0
- package/src/compiler/cli.ts +33 -10
- package/src/compiler/collections.ts +45 -4
- package/src/compiler/course-config.ts +131 -3
- package/src/compiler/exports/standalone-html.ts +963 -0
- package/src/compiler/lesson-derivation.ts +2 -2
- package/src/compiler/manifest.ts +367 -49
- package/src/components/HoverPanel.astro +45 -4
- package/src/components/abbreviation/AbbreviationGlossary.astro +70 -0
- package/src/components/abbreviation/AbbreviationLayer.astro +127 -0
- package/src/components/assessments/AssessmentRunner.tsx +52 -17
- package/src/components/assessments/AssessmentSet.astro +98 -14
- package/src/components/assessments/RenderedContent.tsx +55 -0
- package/src/components/assessments/assessment-randomization.ts +16 -0
- package/src/components/diagram/Diagram.astro +444 -83
- package/src/components/disclosure/hover-preview.ts +202 -0
- package/src/components/disclosure/persisted-disclosure.ts +66 -0
- package/src/components/examples/CompactExamples.astro +2 -0
- package/src/components/figure/Figure.astro +279 -10
- package/src/components/memo/Memo.astro +453 -0
- package/src/components/memo/ShortNote.astro +223 -0
- package/src/components/notation/NotationFormula.astro +18 -1
- package/src/components/notation/NotationLayer.astro +116 -8
- package/src/components/notation/render-notation-math.ts +39 -2
- package/src/components/notation/safe-math-to-react.ts +50 -0
- package/src/components/reference/FloatRefLayer.astro +233 -15
- package/src/components/starlight/CollapsibleSections.astro +461 -0
- package/src/components/starlight/DiagramEnhancer.astro +385 -0
- package/src/components/starlight/HeadingAnchorEnhancer.astro +5 -17
- package/src/components/starlight/KeyedFloatEnhancer.astro +81 -3
- package/src/components/starlight/LayoutHeader.astro +50 -0
- package/src/components/starlight/LayoutSidebar.astro +62 -1
- package/src/components/starlight/LayoutSocialIcons.astro +41 -2
- package/src/components/starlight/LessonExportActions.astro +436 -0
- package/src/components/starlight/LessonFooter.astro +38 -2
- package/src/components/starlight/section-parts.ts +31 -0
- package/src/components/table/Table.astro +296 -9
- package/src/components/table/TableOverflowExpander.astro +489 -0
- package/src/content-config.ts +20 -0
- package/src/reference/base-abbreviations.mjs +60 -0
- package/src/reference/base-operators.mjs +40 -0
- package/src/reference/base-roman-labels.mjs +43 -0
- package/src/reference/consistency.ts +73 -2
- package/src/reference/diagrams-validate.ts +40 -0
- package/src/reference/equations-validate.ts +6 -4
- package/src/reference/equations.mjs +142 -40
- package/src/reference/gate-abbreviations.ts +128 -0
- package/src/reference/gate-math.ts +27 -7
- package/src/reference/gate-prose-notation.ts +224 -0
- package/src/reference/keyed-float-validate.ts +12 -9
- package/src/reference/keyed-jsx-floats.mjs +90 -41
- package/src/reference/knowledge-checks-validate.ts +130 -0
- package/src/reference/knowledge-checks.mjs +45 -0
- package/src/reference/lab-math-scope.ts +45 -3
- package/src/reference/math-glyphs.mjs +367 -0
- package/src/reference/mdx-attributes.mjs +38 -0
- package/src/reference/mixed-content.ts +69 -0
- package/src/reference/page-notation.ts +252 -0
- package/src/reference/raw-floats-validate.ts +103 -0
- package/src/reference/raw-floats.mjs +129 -0
- package/src/reference/rehype-heading-anchors.mjs +107 -1
- package/src/reference/rehype-table-header-labels.mjs +152 -0
- package/src/reference/remark-abbreviations.mjs +174 -0
- package/src/reference/remark-memo.mjs +339 -0
- package/src/reference/remark-notation.mjs +506 -50
- package/src/reference/remark-short-note.mjs +237 -0
- package/src/reference/types.ts +16 -0
- package/src/reference/units-vocab.ts +4 -0
- package/src/styles/global.css +1125 -50
|
@@ -84,6 +84,6 @@ type SidebarGroup = {
|
|
|
84
84
|
* merged track order (ties broken by slug), then the static Reference group.
|
|
85
85
|
* Replaces seven `autogenerate` blocks that read an authored `sidebar.order`.
|
|
86
86
|
*/
|
|
87
|
-
declare function buildSidebar(tracks: readonly TrackLike[], lessonSlugs: readonly string[],
|
|
87
|
+
declare function buildSidebar(tracks: readonly TrackLike[], lessonSlugs: readonly string[], parts: readonly SidebarSection[]): SidebarGroup[];
|
|
88
88
|
|
|
89
89
|
export { type SidebarGroup, type SidebarSection, buildSidebar, citedSourceIds, deriveRequires, deriveSources, isLessonSlug, lessonIdFromSlug, mergeTrackOrder, parseCheckList };
|
|
@@ -59,12 +59,12 @@ function mergeTrackOrder(tracks) {
|
|
|
59
59
|
}
|
|
60
60
|
return ordered;
|
|
61
61
|
}
|
|
62
|
-
function buildSidebar(tracks, lessonSlugs,
|
|
62
|
+
function buildSidebar(tracks, lessonSlugs, parts) {
|
|
63
63
|
const rank = new Map(
|
|
64
64
|
mergeTrackOrder(tracks).map((lessonId, index) => [lessonId, index])
|
|
65
65
|
);
|
|
66
66
|
const positionOf = (slug) => rank.get(lessonIdFromSlug(slug)) ?? Number.POSITIVE_INFINITY;
|
|
67
|
-
const groups =
|
|
67
|
+
const groups = parts.map(({ dir, label }) => ({
|
|
68
68
|
label,
|
|
69
69
|
items: lessonSlugs.filter((slug) => slug.startsWith(`${dir}/`)).sort(
|
|
70
70
|
(left, right) => positionOf(left) - positionOf(right) || left.localeCompare(right)
|
|
@@ -3,10 +3,14 @@ import { ConsistencyDiagnostic } from '../reference/consistency.js';
|
|
|
3
3
|
import { EquationLabelRecord, EquationDiagnostic } from '../reference/equations-validate.js';
|
|
4
4
|
import { TableLabelRecord, TableDiagnostic } from '../reference/tables-validate.js';
|
|
5
5
|
import { FigureLabelRecord, FigureDiagnostic } from '../reference/figures-validate.js';
|
|
6
|
+
import { DiagramLabelRecord, DiagramDiagnostic } from '../reference/diagrams-validate.js';
|
|
7
|
+
import { KnowledgeCheckLabelRecord, KnowledgeCheckDiagnostic } from '../reference/knowledge-checks-validate.js';
|
|
8
|
+
import { RawFloatDiagnostic } from '../reference/raw-floats-validate.js';
|
|
6
9
|
import { MathGateDiagnostic } from '../reference/gate-math.js';
|
|
10
|
+
import { ContentSegment } from '../reference/mixed-content.js';
|
|
7
11
|
import { GlyphScopeEntry } from '../reference/gloss.js';
|
|
8
12
|
import { NotationDefinitionRecord, NotationPageBundle, NotationBacklink, NotationDiagnostic, EditorialStatus, NotationGlossEntry } from '../reference/types.js';
|
|
9
|
-
import { CourseConfig } from './course-config.js';
|
|
13
|
+
import { NormalizedLessonExports, CourseConfig } from './course-config.js';
|
|
10
14
|
import { KnowledgeVersionDiagnostic } from './knowledge-version.js';
|
|
11
15
|
import { SidebarGroup } from './lesson-derivation.js';
|
|
12
16
|
import './collections.js';
|
|
@@ -51,14 +55,43 @@ import '../reference/keyed-float-validate.js';
|
|
|
51
55
|
* `lessons[].equations`, and `diagnostics.equations`.
|
|
52
56
|
* v4 (F-tables-figures): `tables`/`figures` (same shape as `equations`, for
|
|
53
57
|
* `<Table>`/`<Figure>`), `lessons[].tables`/`lessons[].figures`, and
|
|
54
|
-
* `diagnostics.tables`/`diagnostics.figures`.
|
|
58
|
+
* `diagnostics.tables`/`diagnostics.figures`/`diagnostics.diagrams`.
|
|
55
59
|
* v5 (about): `about` (engine identity from `explico`'s `package.json`, the
|
|
56
60
|
* course's reader-facing `about` block, and the knowledge version resolved
|
|
57
61
|
* against `content/CHANGELOG.md`) and `diagnostics.knowledge`.
|
|
58
62
|
* v6 (chapter numbering): `lessons[].chapter` — the lesson's 1-based course
|
|
59
63
|
* ordinal, the chapter in every equation/table/figure number (`(2.1)`).
|
|
64
|
+
* v7 (part numbering): `lessons[].part` (the sidebar group's 1-based ordinal,
|
|
65
|
+
* now the number before the dot), `lessons[].chapter` redefined as the
|
|
66
|
+
* lesson's ordinal *within its part*, and `lessons[].numbering` — the
|
|
67
|
+
* per-kind offsets that make `n` run continuously across a part.
|
|
68
|
+
* v8 (assessment math): `assessmentContent` — every assessment item's
|
|
69
|
+
* `prompt` / `explanation`, pre-split into text/math segments and resolved
|
|
70
|
+
* against the scope of the lesson that embeds it, so `AssessmentSet.astro`
|
|
71
|
+
* can render them through the same KaTeX pipeline as lesson body math instead
|
|
72
|
+
* of showing raw text.
|
|
73
|
+
* v9 (diagram identity): `diagrams` (the independent `<Diagram>` number and
|
|
74
|
+
* cross-page lookup), `lessons[].diagrams`, `lessons[].numbering.diagrams`,
|
|
75
|
+
* and `diagnostics.diagrams`.
|
|
76
|
+
* v10 (knowledge-check identity): `checks` (part-wide numbering and cross-page
|
|
77
|
+
* lookup), `lessons[].knowledgeChecks`, `lessons[].numbering.checks`, and
|
|
78
|
+
* `diagnostics.checks`.
|
|
79
|
+
* v11 (lesson exports): normalized standalone HTML and print build/UI settings.
|
|
80
|
+
* v12 (abbreviation hover cards): `manifest.abbreviations` — the
|
|
81
|
+
* `abbreviations` content collection (N14), flattened to plain
|
|
82
|
+
* `{key, abbr, expansion, aliases, domain?}` records sorted by key, the way
|
|
83
|
+
* `manifest.notation.raw` already carries notation frontmatter for
|
|
84
|
+
* `remarkNotation`. `remarkAbbreviations` reads it to wrap the first
|
|
85
|
+
* occurrence of a known abbreviation in a lesson's prose with a hover/click
|
|
86
|
+
* card.
|
|
87
|
+
* v13 (raw-float diagnostics, additive): `diagnostics.rawFloats` — a raw
|
|
88
|
+
* Markdown table, a raw HTML `<table>`, or an Explico `<Diagram>` that is
|
|
89
|
+
* unkeyed or nested outside `<Table>`/`<Figure>` never reaches keyed-float
|
|
90
|
+
* validation and can never get a stable number or `[[…]]` reference; this
|
|
91
|
+
* flags it (warning-only — the manifest shape a client already reads is
|
|
92
|
+
* unchanged).
|
|
60
93
|
*/
|
|
61
|
-
declare const MANIFEST_SCHEMA_VERSION =
|
|
94
|
+
declare const MANIFEST_SCHEMA_VERSION = 13;
|
|
62
95
|
declare const MANIFEST_PATH: string;
|
|
63
96
|
interface ManifestCitation {
|
|
64
97
|
readonly id: string;
|
|
@@ -108,11 +141,31 @@ interface ManifestLesson {
|
|
|
108
141
|
/** Docs-loader slug, e.g. `bonds/price-yield-relationship`. */
|
|
109
142
|
readonly slug: string;
|
|
110
143
|
/**
|
|
111
|
-
* The
|
|
112
|
-
*
|
|
113
|
-
*
|
|
144
|
+
* The 1-based ordinal of the **part** this lesson sits in — its sidebar
|
|
145
|
+
* group's position in `courseConfig.parts`. It is the number before the dot
|
|
146
|
+
* in every equation, table, figure, diagram, and knowledge-check number on
|
|
147
|
+
* the page: `(2.1)` is the first equation of part 2. See
|
|
148
|
+
* `docs/authoring/structure.md`.
|
|
149
|
+
*/
|
|
150
|
+
readonly part: number;
|
|
151
|
+
/**
|
|
152
|
+
* The lesson's 1-based ordinal **within its part** (merged track order, then
|
|
153
|
+
* any unranked lessons by slug) — its chapter number. This orders the
|
|
154
|
+
* sidebar and the reading path; it does not appear in a float's number.
|
|
114
155
|
*/
|
|
115
156
|
readonly chapter: number;
|
|
157
|
+
/**
|
|
158
|
+
* How many floats of each kind the earlier lessons of this part already
|
|
159
|
+
* used. The lesson's own floats continue from here, so a part's sequence
|
|
160
|
+
* runs unbroken across its chapters instead of restarting on every page.
|
|
161
|
+
*/
|
|
162
|
+
readonly numbering: {
|
|
163
|
+
readonly equations: number;
|
|
164
|
+
readonly tables: number;
|
|
165
|
+
readonly figures: number;
|
|
166
|
+
readonly diagrams: number;
|
|
167
|
+
readonly checks: number;
|
|
168
|
+
};
|
|
116
169
|
readonly file: string;
|
|
117
170
|
readonly title: string;
|
|
118
171
|
readonly description: string;
|
|
@@ -122,6 +175,11 @@ interface ManifestLesson {
|
|
|
122
175
|
readonly requires: readonly string[];
|
|
123
176
|
readonly assumptions: readonly string[];
|
|
124
177
|
readonly assessments: readonly string[];
|
|
178
|
+
/** Numbered knowledge checks from `assessments`, in `.checks.yml` order. */
|
|
179
|
+
readonly knowledgeChecks: readonly {
|
|
180
|
+
readonly key: string;
|
|
181
|
+
readonly number: string;
|
|
182
|
+
}[];
|
|
125
183
|
readonly sources: readonly string[];
|
|
126
184
|
readonly citations: readonly ManifestCitation[];
|
|
127
185
|
/** Competency prerequisite edges this lesson introduces. */
|
|
@@ -141,6 +199,11 @@ interface ManifestLesson {
|
|
|
141
199
|
readonly key: string;
|
|
142
200
|
readonly number: string;
|
|
143
201
|
}[];
|
|
202
|
+
/** Keyed `<Diagram>` elements in appearance order. */
|
|
203
|
+
readonly diagrams: readonly {
|
|
204
|
+
readonly key: string;
|
|
205
|
+
readonly number: string;
|
|
206
|
+
}[];
|
|
144
207
|
readonly notation: {
|
|
145
208
|
readonly bindings: readonly {
|
|
146
209
|
readonly key: string;
|
|
@@ -181,8 +244,18 @@ interface ManifestAbout {
|
|
|
181
244
|
readonly disclaimer: string;
|
|
182
245
|
readonly changelogHref?: string;
|
|
183
246
|
}
|
|
247
|
+
/** One assessment item's pre-rendered `prompt` / `explanation` (v8). */
|
|
248
|
+
interface ManifestAssessmentItemContent {
|
|
249
|
+
readonly lessonId: string;
|
|
250
|
+
readonly assessmentId: string;
|
|
251
|
+
readonly itemId: string;
|
|
252
|
+
readonly promptSegments: readonly ContentSegment[];
|
|
253
|
+
readonly explanationSegments: readonly ContentSegment[];
|
|
254
|
+
}
|
|
184
255
|
interface Manifest {
|
|
185
256
|
readonly schemaVersion: number;
|
|
257
|
+
/** Normalized build/UI settings for opt-in per-lesson exports. */
|
|
258
|
+
readonly lessonExports: NormalizedLessonExports;
|
|
186
259
|
/** Reader-facing identity + versions (the `[?]` About panel). */
|
|
187
260
|
readonly about: ManifestAbout;
|
|
188
261
|
readonly notation: {
|
|
@@ -196,6 +269,8 @@ interface Manifest {
|
|
|
196
269
|
readonly competencies: readonly Record<string, unknown>[];
|
|
197
270
|
readonly sources: readonly Record<string, unknown>[];
|
|
198
271
|
readonly tracks: readonly Record<string, unknown>[];
|
|
272
|
+
/** Abbreviations table (N14), for `remarkAbbreviations`. Ordered by key. */
|
|
273
|
+
readonly abbreviations: readonly Record<string, unknown>[];
|
|
199
274
|
readonly sidebar: readonly SidebarGroup[];
|
|
200
275
|
readonly lessons: readonly ManifestLesson[];
|
|
201
276
|
/** Full competency prerequisite graph. */
|
|
@@ -216,6 +291,26 @@ interface Manifest {
|
|
|
216
291
|
readonly labels: readonly FigureLabelRecord[];
|
|
217
292
|
readonly numbersBySlug: Record<string, Record<string, string>>;
|
|
218
293
|
};
|
|
294
|
+
/** Keyed-float identity for `<Diagram>` — independent of figure numbering. */
|
|
295
|
+
readonly diagrams: {
|
|
296
|
+
readonly labels: readonly DiagramLabelRecord[];
|
|
297
|
+
readonly numbersBySlug: Record<string, Record<string, string>>;
|
|
298
|
+
};
|
|
299
|
+
/** Knowledge-check identity, derived from each lesson's `.checks.yml`. */
|
|
300
|
+
readonly checks: {
|
|
301
|
+
readonly labels: readonly KnowledgeCheckLabelRecord[];
|
|
302
|
+
readonly numbersBySlug: Record<string, Record<string, string>>;
|
|
303
|
+
};
|
|
304
|
+
/**
|
|
305
|
+
* Every assessment item's `prompt` / `explanation`, pre-split into
|
|
306
|
+
* text/math segments (v8). `AssessmentSet.astro` filters this by
|
|
307
|
+
* `lessonId` + `assessmentId` and renders each `math` segment's `latex`
|
|
308
|
+
* through `renderNotationMath` before handing the result to
|
|
309
|
+
* `AssessmentRunner`. An assessment embedded in more than one lesson (via
|
|
310
|
+
* more than one `checks.yml`) appears once per lesson here, since each
|
|
311
|
+
* lesson's scope can resolve its glyphs differently.
|
|
312
|
+
*/
|
|
313
|
+
readonly assessmentContent: readonly ManifestAssessmentItemContent[];
|
|
219
314
|
readonly diagnostics: {
|
|
220
315
|
readonly curriculum: readonly CurriculumIssue[];
|
|
221
316
|
readonly notation: readonly NotationDiagnostic[];
|
|
@@ -231,6 +326,16 @@ interface Manifest {
|
|
|
231
326
|
readonly tables: readonly TableDiagnostic[];
|
|
232
327
|
/** `<Figure>` identity checks (F-tables-figures) — same codes, `fig-` prefixed. */
|
|
233
328
|
readonly figures: readonly FigureDiagnostic[];
|
|
329
|
+
/** `<Diagram>` identity checks — same codes, `dia-` prefixed. */
|
|
330
|
+
readonly diagrams: readonly DiagramDiagnostic[];
|
|
331
|
+
/** Knowledge-check identity and `[[check-…]]` reference checks. */
|
|
332
|
+
readonly checks: readonly KnowledgeCheckDiagnostic[];
|
|
333
|
+
/**
|
|
334
|
+
* A raw Markdown table, a raw HTML `<table>`, or an Explico `<Diagram>`
|
|
335
|
+
* that is unkeyed or nested outside `<Table>`/`<Figure>` — invisible to
|
|
336
|
+
* keyed-float validation above. Warnings only.
|
|
337
|
+
*/
|
|
338
|
+
readonly rawFloats: readonly RawFloatDiagnostic[];
|
|
234
339
|
};
|
|
235
340
|
readonly hashes: {
|
|
236
341
|
/** `sha256` of every content source file, keyed by repo-relative path. */
|
|
@@ -259,4 +364,4 @@ declare function readManifestSync(): Manifest;
|
|
|
259
364
|
*/
|
|
260
365
|
declare function loadManifest(courseConfig?: CourseConfig): Promise<Manifest>;
|
|
261
366
|
|
|
262
|
-
export { MANIFEST_PATH, MANIFEST_SCHEMA_VERSION, type Manifest, type ManifestAbout, type ManifestCitation, type ManifestLesson, type ManifestLessonNotation, type ManifestNotationResolution, type PrereqEdge, compileManifest, loadManifest, readManifestSync, serializeManifest, writeManifest };
|
|
367
|
+
export { MANIFEST_PATH, MANIFEST_SCHEMA_VERSION, type Manifest, type ManifestAbout, type ManifestAssessmentItemContent, type ManifestCitation, type ManifestLesson, type ManifestLessonNotation, type ManifestNotationResolution, type PrereqEdge, compileManifest, loadManifest, readManifestSync, serializeManifest, writeManifest };
|
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
runConsistencyChecks
|
|
17
17
|
} from "../reference/consistency.js";
|
|
18
18
|
import { validateNotationAlignment } from "../reference/curriculum-alignment.js";
|
|
19
|
+
import { countDisplayEquations } from "../reference/equations.mjs";
|
|
20
|
+
import { countKeyedJsxFloats } from "../reference/keyed-jsx-floats.mjs";
|
|
19
21
|
import {
|
|
20
22
|
validateEquations
|
|
21
23
|
} from "../reference/equations-validate.js";
|
|
@@ -26,16 +28,39 @@ import {
|
|
|
26
28
|
validateFigures
|
|
27
29
|
} from "../reference/figures-validate.js";
|
|
28
30
|
import {
|
|
29
|
-
|
|
31
|
+
validateDiagrams
|
|
32
|
+
} from "../reference/diagrams-validate.js";
|
|
33
|
+
import {
|
|
34
|
+
validateKnowledgeChecks
|
|
35
|
+
} from "../reference/knowledge-checks-validate.js";
|
|
36
|
+
import {
|
|
37
|
+
validateRawFloats
|
|
38
|
+
} from "../reference/raw-floats-validate.js";
|
|
39
|
+
import {
|
|
40
|
+
gateContentMath,
|
|
41
|
+
pageScope
|
|
30
42
|
} from "../reference/gate-math.js";
|
|
43
|
+
import {
|
|
44
|
+
gateProseNotation,
|
|
45
|
+
gateProseNotationInAssessments
|
|
46
|
+
} from "../reference/gate-prose-notation.js";
|
|
47
|
+
import { gateAbbreviations } from "../reference/gate-abbreviations.js";
|
|
48
|
+
import {
|
|
49
|
+
splitMixedContent
|
|
50
|
+
} from "../reference/mixed-content.js";
|
|
31
51
|
import { loadLintIgnore } from "../reference/lint-ignore.js";
|
|
32
52
|
import { buildNotationRegistry } from "../reference/registry.js";
|
|
33
53
|
import { formulaGlyphScope } from "../reference/gloss.js";
|
|
34
54
|
import { resolveReferenceId } from "../reference/references.js";
|
|
55
|
+
import {
|
|
56
|
+
coursePartsOf,
|
|
57
|
+
normalizeLessonExports
|
|
58
|
+
} from "./course-config.js";
|
|
35
59
|
import {
|
|
36
60
|
resolveKnowledgeVersion
|
|
37
61
|
} from "./knowledge-version.js";
|
|
38
62
|
import {
|
|
63
|
+
loadAbbreviationRegistryInput,
|
|
39
64
|
loadCurriculumCatalog,
|
|
40
65
|
loadNotationDefinitions,
|
|
41
66
|
loadNotationRegistryInput,
|
|
@@ -48,7 +73,7 @@ import {
|
|
|
48
73
|
isLessonSlug,
|
|
49
74
|
lessonIdFromSlug
|
|
50
75
|
} from "./lesson-derivation.js";
|
|
51
|
-
const MANIFEST_SCHEMA_VERSION =
|
|
76
|
+
const MANIFEST_SCHEMA_VERSION = 13;
|
|
52
77
|
const REPOSITORY_ROOT = process.cwd();
|
|
53
78
|
const CONTENT_ROOT = join(REPOSITORY_ROOT, "content");
|
|
54
79
|
const MANIFEST_PATH = join(REPOSITORY_ROOT, "build", "manifest.json");
|
|
@@ -181,9 +206,10 @@ async function compileManifest(courseConfig) {
|
|
|
181
206
|
"course.config.ts is missing a complete `about` block (required since explico 0.3.0): `about: { version, authors: [{ name }], disclaimer, materialName?, summary?, changelogHref? }`. See docs/authoring/migrating.md (\xA7 0.2.x \u2192 0.3.0) in the installed package."
|
|
182
207
|
);
|
|
183
208
|
}
|
|
184
|
-
const [catalog, notationInput] = await Promise.all([
|
|
209
|
+
const [catalog, notationInput, abbreviationsInput] = await Promise.all([
|
|
185
210
|
loadCurriculumCatalog(),
|
|
186
|
-
loadNotationRegistryInput()
|
|
211
|
+
loadNotationRegistryInput(),
|
|
212
|
+
loadAbbreviationRegistryInput()
|
|
187
213
|
]);
|
|
188
214
|
const registry = buildNotationRegistry(notationInput);
|
|
189
215
|
const cardsByKey = new Map(
|
|
@@ -199,16 +225,53 @@ async function compileManifest(courseConfig) {
|
|
|
199
225
|
const bundlesByLesson = new Map(
|
|
200
226
|
registry.bundles.map((bundle) => [bundle.lessonId, bundle])
|
|
201
227
|
);
|
|
228
|
+
const assessmentsInput = catalog.assessments;
|
|
202
229
|
const curriculumIssues = validateCurriculum(catalog);
|
|
203
230
|
const alignmentIssues = validateNotationAlignment(registry, catalog);
|
|
204
|
-
const mathIssues =
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
231
|
+
const mathIssues = [
|
|
232
|
+
...gateContentMath({
|
|
233
|
+
notationInput,
|
|
234
|
+
assessments: assessmentsInput,
|
|
235
|
+
lessonAssessments: catalog.lessons.map((lesson) => ({
|
|
236
|
+
lessonId: lesson.id,
|
|
237
|
+
assessmentIds: lesson.assessments
|
|
238
|
+
}))
|
|
239
|
+
}),
|
|
240
|
+
...gateProseNotation(notationInput.lessons),
|
|
241
|
+
...gateProseNotationInAssessments(assessmentsInput),
|
|
242
|
+
...gateAbbreviations({
|
|
243
|
+
notationInput,
|
|
244
|
+
abbreviations: abbreviationsInput,
|
|
245
|
+
courseAbbreviations: courseConfig.abbreviations
|
|
246
|
+
})
|
|
247
|
+
];
|
|
248
|
+
const notationLessonById = new Map(
|
|
249
|
+
notationInput.lessons.map((lesson) => [lesson.lessonId, lesson])
|
|
250
|
+
);
|
|
251
|
+
const assessmentInputById = new Map(
|
|
252
|
+
assessmentsInput.map((assessment) => [assessment.id, assessment])
|
|
253
|
+
);
|
|
254
|
+
const assessmentContent = [];
|
|
255
|
+
for (const lesson of catalog.lessons) {
|
|
256
|
+
if (lesson.assessments.length === 0) continue;
|
|
257
|
+
const lessonInput = notationLessonById.get(lesson.id);
|
|
258
|
+
if (!lessonInput) continue;
|
|
259
|
+
const scope = pageScope(lessonInput, cardsByKey);
|
|
260
|
+
for (const assessmentId of lesson.assessments) {
|
|
261
|
+
const assessment = assessmentInputById.get(assessmentId);
|
|
262
|
+
if (!assessment?.items) continue;
|
|
263
|
+
for (const item of assessment.items) {
|
|
264
|
+
if (!item.id) continue;
|
|
265
|
+
assessmentContent.push({
|
|
266
|
+
lessonId: lesson.id,
|
|
267
|
+
assessmentId,
|
|
268
|
+
itemId: item.id,
|
|
269
|
+
promptSegments: splitMixedContent(item.prompt ?? "", scope),
|
|
270
|
+
explanationSegments: splitMixedContent(item.explanation ?? "", scope)
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
212
275
|
const prerequisitesById = new Map(
|
|
213
276
|
catalog.competencies.map((competency) => [
|
|
214
277
|
competency.id,
|
|
@@ -231,44 +294,114 @@ async function compileManifest(courseConfig) {
|
|
|
231
294
|
const sidebar = buildSidebar(
|
|
232
295
|
catalog.tracks.map((track) => ({ id: track.id, lessons: track.lessons })),
|
|
233
296
|
lessonSlugs,
|
|
234
|
-
courseConfig
|
|
297
|
+
coursePartsOf(courseConfig)
|
|
298
|
+
);
|
|
299
|
+
const bodyByLessonId = new Map(
|
|
300
|
+
notationInput.lessons.map((lesson) => [lesson.lessonId, lesson.body])
|
|
235
301
|
);
|
|
236
|
-
const
|
|
237
|
-
let
|
|
302
|
+
const placementByLessonId = /* @__PURE__ */ new Map();
|
|
303
|
+
let partCursor = 0;
|
|
238
304
|
for (const group of sidebar) {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
305
|
+
const lessonIds = group.items.filter((item) => typeof item === "string").map(lessonIdFromSlug);
|
|
306
|
+
if (lessonIds.length === 0) continue;
|
|
307
|
+
partCursor += 1;
|
|
308
|
+
const used = {
|
|
309
|
+
equations: 0,
|
|
310
|
+
tables: 0,
|
|
311
|
+
figures: 0,
|
|
312
|
+
diagrams: 0,
|
|
313
|
+
checks: 0
|
|
314
|
+
};
|
|
315
|
+
let chapterCursor = 0;
|
|
316
|
+
for (const lessonId of lessonIds) {
|
|
317
|
+
const body = bodyByLessonId.get(lessonId) ?? "";
|
|
318
|
+
placementByLessonId.set(lessonId, {
|
|
319
|
+
part: partCursor,
|
|
320
|
+
chapter: ++chapterCursor,
|
|
321
|
+
numbering: { ...used }
|
|
322
|
+
});
|
|
323
|
+
used.equations += countDisplayEquations(body);
|
|
324
|
+
used.tables += countKeyedJsxFloats(body, { tagName: "Table" });
|
|
325
|
+
used.figures += countKeyedJsxFloats(body, { tagName: "Figure" });
|
|
326
|
+
used.diagrams += countKeyedJsxFloats(body, { tagName: "Diagram" });
|
|
327
|
+
used.checks += lessonMetaById.get(lessonId)?.assessments.length ?? 0;
|
|
242
328
|
}
|
|
243
329
|
}
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
330
|
+
const floatInputs = (kind) => notationInput.lessons.map((lesson) => {
|
|
331
|
+
const placement = placementByLessonId.get(lesson.lessonId);
|
|
332
|
+
return {
|
|
333
|
+
lessonId: lesson.lessonId,
|
|
334
|
+
slug: lesson.lessonId.replace(/\./g, "/"),
|
|
335
|
+
file: lesson.source.file,
|
|
336
|
+
body: lesson.body,
|
|
337
|
+
...placement ? {
|
|
338
|
+
numbering: {
|
|
339
|
+
prefix: placement.part,
|
|
340
|
+
offset: placement.numbering[kind]
|
|
341
|
+
}
|
|
342
|
+
} : {}
|
|
343
|
+
};
|
|
344
|
+
});
|
|
345
|
+
const equationValidation = validateEquations(floatInputs("equations"));
|
|
252
346
|
const equationsBySlug = new Map(
|
|
253
347
|
Object.entries(equationValidation.numbersBySlug).map(([slug, table]) => [
|
|
254
348
|
slug,
|
|
255
349
|
Object.entries(table).map(([key, number]) => ({ key, number }))
|
|
256
350
|
])
|
|
257
351
|
);
|
|
258
|
-
const tableValidation = validateTables(
|
|
352
|
+
const tableValidation = validateTables(floatInputs("tables"));
|
|
259
353
|
const tablesBySlug = new Map(
|
|
260
354
|
Object.entries(tableValidation.numbersBySlug).map(([slug, table]) => [
|
|
261
355
|
slug,
|
|
262
356
|
Object.entries(table).map(([key, number]) => ({ key, number }))
|
|
263
357
|
])
|
|
264
358
|
);
|
|
265
|
-
const figureValidation = validateFigures(
|
|
359
|
+
const figureValidation = validateFigures(floatInputs("figures"));
|
|
266
360
|
const figuresBySlug = new Map(
|
|
267
361
|
Object.entries(figureValidation.numbersBySlug).map(([slug, table]) => [
|
|
268
362
|
slug,
|
|
269
363
|
Object.entries(table).map(([key, number]) => ({ key, number }))
|
|
270
364
|
])
|
|
271
365
|
);
|
|
366
|
+
const diagramValidation = validateDiagrams(floatInputs("diagrams"));
|
|
367
|
+
const diagramsBySlug = new Map(
|
|
368
|
+
Object.entries(diagramValidation.numbersBySlug).map(([slug, table]) => [
|
|
369
|
+
slug,
|
|
370
|
+
Object.entries(table).map(([key, number]) => ({ key, number }))
|
|
371
|
+
])
|
|
372
|
+
);
|
|
373
|
+
const checkValidation = validateKnowledgeChecks(
|
|
374
|
+
notationInput.lessons.map((lesson) => {
|
|
375
|
+
const placement = placementByLessonId.get(lesson.lessonId);
|
|
376
|
+
return {
|
|
377
|
+
lessonId: lesson.lessonId,
|
|
378
|
+
slug: lesson.lessonId.replace(/\./g, "/"),
|
|
379
|
+
file: lesson.source.file,
|
|
380
|
+
body: lesson.body,
|
|
381
|
+
assessmentIds: lessonMetaById.get(lesson.lessonId)?.assessments ?? [],
|
|
382
|
+
...placement ? {
|
|
383
|
+
numbering: {
|
|
384
|
+
prefix: placement.part,
|
|
385
|
+
offset: placement.numbering.checks
|
|
386
|
+
}
|
|
387
|
+
} : {}
|
|
388
|
+
};
|
|
389
|
+
})
|
|
390
|
+
);
|
|
391
|
+
const checksBySlug = new Map(
|
|
392
|
+
Object.entries(checkValidation.numbersBySlug).map(([slug, table]) => [
|
|
393
|
+
slug,
|
|
394
|
+
Object.entries(table).map(([key, number]) => ({ key, number }))
|
|
395
|
+
])
|
|
396
|
+
);
|
|
397
|
+
const rawFloatDiagnostics = validateRawFloats(
|
|
398
|
+
notationInput.lessons.map((lesson) => ({
|
|
399
|
+
lessonId: lesson.lessonId,
|
|
400
|
+
slug: lesson.lessonId.replace(/\./g, "/"),
|
|
401
|
+
file: lesson.source.file,
|
|
402
|
+
body: lesson.body
|
|
403
|
+
}))
|
|
404
|
+
);
|
|
272
405
|
const lessons = [];
|
|
273
406
|
for (const notationLesson of notationInput.lessons) {
|
|
274
407
|
const id = notationLesson.lessonId;
|
|
@@ -282,10 +415,18 @@ async function compileManifest(courseConfig) {
|
|
|
282
415
|
lessons.push({
|
|
283
416
|
id,
|
|
284
417
|
slug: id.replace(/\./g, "/"),
|
|
285
|
-
// 0 = the lesson is not placed in any configured
|
|
418
|
+
// 0 = the lesson is not placed in any configured part; a curriculum
|
|
286
419
|
// diagnostic covers that separately, and both numbering paths then fall
|
|
287
420
|
// back to the legacy `##`-section scheme.
|
|
288
|
-
|
|
421
|
+
part: placementByLessonId.get(id)?.part ?? 0,
|
|
422
|
+
chapter: placementByLessonId.get(id)?.chapter ?? 0,
|
|
423
|
+
numbering: placementByLessonId.get(id)?.numbering ?? {
|
|
424
|
+
equations: 0,
|
|
425
|
+
tables: 0,
|
|
426
|
+
figures: 0,
|
|
427
|
+
diagrams: 0,
|
|
428
|
+
checks: 0
|
|
429
|
+
},
|
|
289
430
|
file: notationLesson.source.file,
|
|
290
431
|
title: frontmatter.title,
|
|
291
432
|
description: frontmatter.description,
|
|
@@ -294,11 +435,13 @@ async function compileManifest(courseConfig) {
|
|
|
294
435
|
requires: [...meta.requires],
|
|
295
436
|
assumptions: [...meta.assumptions],
|
|
296
437
|
assessments: [...meta.assessments],
|
|
438
|
+
knowledgeChecks: checksBySlug.get(id.replace(/\./g, "/")) ?? [],
|
|
297
439
|
sources: deriveSources(notationLesson.body),
|
|
298
440
|
citations: lessonCitations(notationLesson.body),
|
|
299
441
|
equations: equationsBySlug.get(id.replace(/\./g, "/")) ?? [],
|
|
300
442
|
tables: tablesBySlug.get(id.replace(/\./g, "/")) ?? [],
|
|
301
443
|
figures: figuresBySlug.get(id.replace(/\./g, "/")) ?? [],
|
|
444
|
+
diagrams: diagramsBySlug.get(id.replace(/\./g, "/")) ?? [],
|
|
302
445
|
prereqEdges: sortEdges(
|
|
303
446
|
teaches.flatMap(
|
|
304
447
|
(to) => (prerequisitesById.get(to) ?? []).filter((from) => !teaches.includes(from)).map((from) => ({ from, to }))
|
|
@@ -324,7 +467,8 @@ async function compileManifest(courseConfig) {
|
|
|
324
467
|
catalog,
|
|
325
468
|
lintIgnore: loadLintIgnore(),
|
|
326
469
|
conventions: courseConfig.conventions,
|
|
327
|
-
...courseConfig.operators === void 0 ? {} : { operators: courseConfig.operators }
|
|
470
|
+
...courseConfig.operators === void 0 ? {} : { operators: courseConfig.operators },
|
|
471
|
+
...courseConfig.romanLabels === void 0 ? {} : { romanLabels: courseConfig.romanLabels }
|
|
328
472
|
});
|
|
329
473
|
const rawNotation = [...loadNotationDefinitions()].sort(
|
|
330
474
|
(a, b) => String(a.key).localeCompare(String(b.key))
|
|
@@ -332,6 +476,13 @@ async function compileManifest(courseConfig) {
|
|
|
332
476
|
const competencies = catalog.competencies.map((entry) => ({ ...entry })).sort(byId);
|
|
333
477
|
const sources = [...loadSourceRecords()].sort(byId);
|
|
334
478
|
const tracks = catalog.tracks.map((entry) => ({ ...entry })).sort(byId);
|
|
479
|
+
const abbreviations = abbreviationsInput.map((entry) => ({
|
|
480
|
+
key: entry.key,
|
|
481
|
+
abbr: entry.abbr,
|
|
482
|
+
expansion: entry.expansion,
|
|
483
|
+
aliases: entry.aliases,
|
|
484
|
+
...entry.domain === void 0 ? {} : { domain: entry.domain }
|
|
485
|
+
})).sort((a, b) => a.key.localeCompare(b.key));
|
|
335
486
|
const hashes = contentHashes();
|
|
336
487
|
const knowledgeChangelogPath = join(CONTENT_ROOT, "CHANGELOG.md");
|
|
337
488
|
const knowledge = resolveKnowledgeVersion({
|
|
@@ -365,6 +516,7 @@ async function compileManifest(courseConfig) {
|
|
|
365
516
|
};
|
|
366
517
|
return {
|
|
367
518
|
schemaVersion: MANIFEST_SCHEMA_VERSION,
|
|
519
|
+
lessonExports: normalizeLessonExports(courseConfig),
|
|
368
520
|
about,
|
|
369
521
|
notation: {
|
|
370
522
|
definitions: registry.definitions,
|
|
@@ -376,6 +528,7 @@ async function compileManifest(courseConfig) {
|
|
|
376
528
|
competencies,
|
|
377
529
|
sources,
|
|
378
530
|
tracks,
|
|
531
|
+
abbreviations,
|
|
379
532
|
sidebar,
|
|
380
533
|
lessons,
|
|
381
534
|
prereqEdges,
|
|
@@ -391,6 +544,15 @@ async function compileManifest(courseConfig) {
|
|
|
391
544
|
labels: figureValidation.labels,
|
|
392
545
|
numbersBySlug: figureValidation.numbersBySlug
|
|
393
546
|
},
|
|
547
|
+
diagrams: {
|
|
548
|
+
labels: diagramValidation.labels,
|
|
549
|
+
numbersBySlug: diagramValidation.numbersBySlug
|
|
550
|
+
},
|
|
551
|
+
checks: {
|
|
552
|
+
labels: checkValidation.labels,
|
|
553
|
+
numbersBySlug: checkValidation.numbersBySlug
|
|
554
|
+
},
|
|
555
|
+
assessmentContent,
|
|
394
556
|
diagnostics: {
|
|
395
557
|
curriculum: curriculumIssues,
|
|
396
558
|
notation: registry.diagnostics,
|
|
@@ -400,7 +562,10 @@ async function compileManifest(courseConfig) {
|
|
|
400
562
|
equations: equationValidation.diagnostics,
|
|
401
563
|
tables: tableValidation.diagnostics,
|
|
402
564
|
figures: figureValidation.diagnostics,
|
|
403
|
-
|
|
565
|
+
diagrams: diagramValidation.diagnostics,
|
|
566
|
+
checks: checkValidation.diagnostics,
|
|
567
|
+
knowledge: knowledge.diagnostics,
|
|
568
|
+
rawFloats: rawFloatDiagnostics
|
|
404
569
|
},
|
|
405
570
|
hashes
|
|
406
571
|
};
|
|
@@ -437,15 +602,15 @@ function readManifestSync() {
|
|
|
437
602
|
return JSON.parse(readFileSync(MANIFEST_PATH, "utf8"));
|
|
438
603
|
}
|
|
439
604
|
async function loadManifest(courseConfig) {
|
|
440
|
-
if (
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
);
|
|
605
|
+
if (courseConfig) {
|
|
606
|
+
const manifest = await compileManifest(courseConfig);
|
|
607
|
+
writeManifest(manifest);
|
|
608
|
+
return manifest;
|
|
445
609
|
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
610
|
+
if (existsSync(MANIFEST_PATH)) return readManifestSync();
|
|
611
|
+
throw new Error(
|
|
612
|
+
`${relative(REPOSITORY_ROOT, MANIFEST_PATH)} not found. Run \`pnpm validate:content\` first.`
|
|
613
|
+
);
|
|
449
614
|
}
|
|
450
615
|
export {
|
|
451
616
|
MANIFEST_PATH,
|
|
@@ -9,7 +9,11 @@ import '../reference/equations-validate.js';
|
|
|
9
9
|
import '../reference/tables-validate.js';
|
|
10
10
|
import '../reference/keyed-float-validate.js';
|
|
11
11
|
import '../reference/figures-validate.js';
|
|
12
|
+
import '../reference/diagrams-validate.js';
|
|
13
|
+
import '../reference/knowledge-checks-validate.js';
|
|
14
|
+
import '../reference/raw-floats-validate.js';
|
|
12
15
|
import '../reference/gate-math.js';
|
|
16
|
+
import '../reference/mixed-content.js';
|
|
13
17
|
import '../reference/gloss.js';
|
|
14
18
|
import './knowledge-version.js';
|
|
15
19
|
import './lesson-derivation.js';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The abbreviations a course treats as common, given its `course.config.ts`
|
|
3
|
+
* `abbreviations` block: the shipped baseline, plus `allow`, minus `deny`.
|
|
4
|
+
*
|
|
5
|
+
* @param {{ allow?: readonly string[], deny?: readonly string[] } | undefined} abbreviations
|
|
6
|
+
* @returns {Set<string>}
|
|
7
|
+
*/
|
|
8
|
+
export function effectiveAbbreviationAllowlist(abbreviations: {
|
|
9
|
+
allow?: readonly string[];
|
|
10
|
+
deny?: readonly string[];
|
|
11
|
+
} | undefined): Set<string>;
|
|
12
|
+
/** True when `token` needs no abbreviations-table entry for this course. */
|
|
13
|
+
export function isBaseAbbreviation(token: any, abbreviations: any): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* The base abbreviation baseline: acronyms and dotted abbreviations every
|
|
16
|
+
* reader is assumed to know, so a lesson never has to introduce them with an
|
|
17
|
+
* abbreviations-table entry. The `\operatorname{…}` / `\mathrm{…}` twins are
|
|
18
|
+
* `base-operators.mjs` (rule N8) / `base-roman-labels.mjs` (rule N10); this is
|
|
19
|
+
* the plain-prose equivalent for rule N14.
|
|
20
|
+
*
|
|
21
|
+
* Kept intentionally small, same rationale as `BASE_ROMAN_LABELS`: a
|
|
22
|
+
* course-specific acronym (`OLS`, `SSR`, `MSE`) is exactly the thing a reader
|
|
23
|
+
* benefits from having spelled out, so it belongs in the course's own
|
|
24
|
+
* `content/abbreviations/*.md` table, not here. This baseline only holds
|
|
25
|
+
* abbreviations so common in ordinary English/academic writing that spelling
|
|
26
|
+
* them out on every course would be noise, not help. A course adds a real
|
|
27
|
+
* one via `abbreviations.allow` in `course.config.ts`, the same shape as
|
|
28
|
+
* `operators.allow` / `romanLabels.allow`.
|
|
29
|
+
*/
|
|
30
|
+
export const BASE_ABBREVIATIONS: Readonly<Set<string>>;
|