explico 0.8.0 → 0.11.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 +1239 -1
- package/README.md +60 -15
- package/dist/compiler/astro.d.ts +6 -1
- package/dist/compiler/cli.d.ts +46 -2
- package/dist/compiler/cli.js +70 -4
- package/dist/compiler/collections.d.ts +35 -2
- package/dist/compiler/collections.js +68 -5
- package/dist/compiler/course-config.d.ts +3 -194
- package/dist/compiler/course-config.js +78 -5
- package/dist/compiler/exports/standalone-html.d.ts +6 -1
- package/dist/compiler/knowledge-version.js +1 -1
- package/dist/compiler/lesson-derivation.d.ts +27 -10
- package/dist/compiler/lesson-derivation.js +23 -8
- package/dist/compiler/logging.d.ts +4 -1
- package/dist/compiler/logging.js +4 -1
- package/dist/compiler/manifest.d.ts +204 -31
- package/dist/compiler/manifest.js +270 -55
- package/dist/compiler/resolution-report.d.ts +6 -1
- package/dist/course-config-Dsnri9Tk.d.ts +464 -0
- package/dist/reference/base-accents.d.mts +26 -0
- package/dist/reference/base-accents.mjs +31 -0
- package/dist/reference/base-roman-labels.d.mts +2 -2
- package/dist/reference/base-roman-labels.mjs +2 -2
- package/dist/reference/consistency.d.ts +14 -2
- package/dist/reference/consistency.js +108 -4
- package/dist/reference/delimiter-size.d.ts +3 -2
- package/dist/reference/diagrams-validate.d.ts +7 -2
- package/dist/reference/diagrams-validate.js +9 -1
- package/dist/reference/equations-validate.d.ts +8 -5
- package/dist/reference/equations-validate.js +1 -0
- package/dist/reference/equations.d.mts +60 -31
- package/dist/reference/equations.mjs +83 -43
- package/dist/reference/examples-validate.d.ts +31 -0
- package/dist/reference/examples-validate.js +48 -0
- package/dist/reference/figures-validate.d.ts +1 -1
- package/dist/reference/figures-validate.js +4 -1
- package/dist/reference/folds-validate.d.ts +33 -0
- package/dist/reference/folds-validate.js +32 -0
- package/dist/reference/gate-abbreviations.d.ts +3 -1
- package/dist/reference/gate-abbreviations.js +1 -0
- package/dist/reference/gate-course-rules.d.ts +32 -0
- package/dist/reference/gate-course-rules.js +85 -0
- package/dist/reference/gate-heading-length.d.ts +5 -2
- package/dist/reference/gate-heading-length.js +45 -21
- package/dist/reference/gate-heading-structure.d.ts +41 -0
- package/dist/reference/gate-heading-structure.js +113 -0
- package/dist/reference/gate-math-punctuation.d.ts +71 -0
- package/dist/reference/gate-math-punctuation.js +251 -0
- package/dist/reference/gate-math.d.ts +22 -6
- package/dist/reference/gate-math.js +42 -8
- package/dist/reference/gate-part-pages.d.ts +50 -0
- package/dist/reference/gate-part-pages.js +118 -0
- package/dist/reference/gate-prose-notation.d.ts +21 -11
- package/dist/reference/gate-prose-notation.js +25 -7
- package/dist/reference/katex-delimiters.mjs +20 -7
- package/dist/reference/keyed-float-validate.d.ts +27 -10
- package/dist/reference/keyed-float-validate.js +15 -1
- package/dist/reference/keyed-jsx-floats.d.mts +11 -5
- package/dist/reference/keyed-jsx-floats.mjs +73 -20
- package/dist/reference/knowledge-checks-validate.d.ts +1 -1
- package/dist/reference/knowledge-checks.d.mts +3 -1
- package/dist/reference/knowledge-checks.mjs +9 -4
- package/dist/reference/lab-math-scope.d.ts +1 -0
- package/dist/reference/lab-math-slot.d.ts +34 -0
- package/dist/reference/lab-math-slot.js +6 -0
- package/dist/reference/math-glyphs.d.mts +80 -4
- package/dist/reference/math-glyphs.mjs +572 -37
- package/dist/reference/page-notation.d.ts +6 -1
- package/dist/reference/raw-floats-validate.js +1 -1
- package/dist/reference/raw-floats.mjs +1 -1
- package/dist/reference/rehype-heading-anchors.d.mts +14 -0
- package/dist/reference/rehype-heading-anchors.mjs +116 -17
- package/dist/reference/rehype-table-header-labels.d.mts +6 -1
- package/dist/reference/rehype-table-header-labels.mjs +21 -3
- package/dist/reference/remark-asides.d.mts +3 -0
- package/dist/reference/remark-asides.mjs +180 -0
- package/dist/reference/remark-memo.d.mts +3 -1
- package/dist/reference/remark-memo.mjs +42 -11
- package/dist/reference/remark-notation.d.mts +60 -10
- package/dist/reference/remark-notation.mjs +387 -36
- package/dist/reference/render-lab-math.d.ts +4 -26
- package/dist/reference/render-lab-math.js +4 -4
- package/dist/reference/sections-validate.d.ts +27 -0
- package/dist/reference/sections-validate.js +41 -0
- package/dist/reference/sections.d.mts +97 -0
- package/dist/reference/sections.mjs +306 -0
- package/dist/reference/tables-validate.d.ts +1 -1
- package/dist/reference/types.d.ts +17 -1
- package/dist/reference/unit-words.d.ts +37 -0
- package/dist/reference/unit-words.js +170 -0
- package/dist/rules/catalog.d.ts +176 -0
- package/dist/rules/catalog.js +983 -0
- package/dist/rules/course-rules.d.ts +115 -0
- package/dist/rules/course-rules.js +292 -0
- package/dist/rules/course-rules.schema.json +138 -0
- package/dist/rules/in-effect.d.ts +53 -0
- package/dist/rules/in-effect.js +142 -0
- package/dist/rules/rules.schema.json +1072 -0
- package/dist/rules/settings.d.ts +3 -0
- package/dist/rules/settings.js +290 -0
- package/dist/rules/waivers.d.ts +53 -0
- package/dist/rules/waivers.js +132 -0
- package/dist/session/PreferenceStore.d.ts +5 -0
- package/dist/session/PreferenceStore.js +9 -0
- package/docs/VERSIONING.md +2 -2
- package/docs/authoring/README.md +232 -40
- package/docs/authoring/agents.md +55 -9
- package/docs/authoring/components.md +178 -22
- package/docs/authoring/migrating.md +1096 -2
- package/docs/authoring/notation.md +576 -322
- package/docs/authoring/prose.md +551 -0
- package/docs/authoring/retired.md +35 -0
- package/docs/authoring/structure-rules.md +422 -40
- package/docs/authoring/structure.md +445 -62
- package/docs/authoring/versioning.md +20 -28
- package/docs/authoring/visualizations.md +142 -20
- package/package.json +2 -2
- package/src/compiler/cli.ts +116 -6
- package/src/compiler/collections.ts +111 -7
- package/src/compiler/course-config.ts +273 -34
- package/src/compiler/knowledge-version.ts +1 -1
- package/src/compiler/lesson-derivation.ts +54 -15
- package/src/compiler/logging.ts +8 -2
- package/src/compiler/manifest.ts +573 -104
- package/src/components/BlockHeading.astro +113 -0
- package/src/components/CourseContents.astro +221 -0
- package/src/components/CurriculumMap.astro +5 -6
- package/src/components/FloatIndex.astro +200 -0
- package/src/components/HoverPanel.astro +431 -79
- package/src/components/PartBridge.astro +27 -0
- package/src/components/PartOverview.astro +401 -0
- package/src/components/PartScope.astro +27 -0
- package/src/components/abbreviation/AbbreviationLayer.astro +49 -51
- package/src/components/assessments/AssessmentRunner.tsx +8 -5
- package/src/components/assessments/AssessmentSet.astro +23 -26
- package/src/components/block-heading.ts +146 -0
- package/src/components/card-arrow.ts +243 -0
- package/src/components/card-drag.ts +631 -0
- package/src/components/card-jump.ts +45 -0
- package/src/components/card-manager.ts +1589 -0
- package/src/components/card-memory.ts +177 -0
- package/src/components/card-placement.ts +504 -0
- package/src/components/card-side.ts +336 -0
- package/src/components/card-travel.ts +197 -0
- package/src/components/citation/CitationLayer.astro +77 -76
- package/src/components/diagram/Diagram.astro +161 -316
- package/src/components/disclosure/course-disclosure.ts +24 -0
- package/src/components/disclosure/hover-preview.ts +122 -42
- package/src/components/disclosure/persisted-disclosure.ts +3 -3
- package/src/components/disclosure/print-as-shown.ts +252 -0
- package/src/components/examples/CompactExample.astro +3 -1
- package/src/components/examples/CompactExamples.astro +101 -94
- package/src/components/figure/Figure.astro +174 -274
- package/src/components/figure/FloatCaption.astro +87 -0
- package/src/components/figure/figure-state.ts +58 -0
- package/src/components/figure/figure-tools.ts +87 -0
- package/src/components/float-name.ts +101 -0
- package/src/components/fold/Fold.astro +125 -0
- package/src/components/fold/fold-id.ts +40 -0
- package/src/components/memo/Memo.astro +162 -231
- package/src/components/memo/ShortNote.astro +6 -6
- package/src/components/notation/NotationFormula.astro +5 -1
- package/src/components/notation/NotationGlossary.astro +3 -4
- package/src/components/notation/NotationLayer.astro +169 -162
- package/src/components/notation/NotationMath.astro +10 -1
- package/src/components/reference/FloatRefLayer.astro +485 -423
- package/src/components/starlight/AboutPanel.astro +5 -4
- package/src/components/starlight/CollapsibleSections.astro +207 -93
- package/src/components/starlight/DiagramEnhancer.astro +15 -138
- package/src/components/starlight/HeadingAnchorEnhancer.astro +193 -1
- package/src/components/starlight/KeyedFloatEnhancer.astro +100 -9
- package/src/components/starlight/LayoutHeader.astro +298 -19
- package/src/components/starlight/LayoutPageSidebar.astro +99 -12
- package/src/components/starlight/LayoutPageTitle.astro +120 -0
- package/src/components/starlight/LayoutSidebar.astro +229 -11
- package/src/components/starlight/LessonExportActions.astro +53 -72
- package/src/components/starlight/LessonFooter.astro +26 -4
- package/src/components/starlight/section-parts.ts +15 -2
- package/src/components/starlight/section-summary.ts +181 -0
- package/src/components/table/Table.astro +95 -76
- package/src/components/table/TableOverflowExpander.astro +65 -28
- package/src/content-config.ts +40 -4
- package/src/reference/base-accents.mjs +31 -0
- package/src/reference/base-roman-labels.mjs +2 -2
- package/src/reference/consistency.ts +176 -5
- package/src/reference/delimiter-size.ts +3 -2
- package/src/reference/diagrams-validate.ts +17 -1
- package/src/reference/equations-validate.ts +10 -5
- package/src/reference/equations.mjs +83 -43
- package/src/reference/examples-validate.ts +97 -0
- package/src/reference/figures-validate.ts +6 -1
- package/src/reference/folds-validate.ts +65 -0
- package/src/reference/gate-abbreviations.ts +1 -0
- package/src/reference/gate-course-rules.ts +134 -0
- package/src/reference/gate-heading-length.ts +66 -35
- package/src/reference/gate-heading-structure.ts +193 -0
- package/src/reference/gate-math-punctuation.ts +381 -0
- package/src/reference/gate-math.ts +69 -10
- package/src/reference/gate-part-pages.ts +217 -0
- package/src/reference/gate-prose-notation.ts +59 -12
- package/src/reference/katex-delimiters.mjs +20 -7
- package/src/reference/keyed-float-validate.ts +45 -11
- package/src/reference/keyed-jsx-floats.mjs +73 -20
- package/src/reference/knowledge-checks-validate.ts +1 -1
- package/src/reference/knowledge-checks.mjs +9 -4
- package/src/reference/lab-math-slot.ts +36 -0
- package/src/reference/math-glyphs.mjs +572 -37
- package/src/reference/raw-floats-validate.ts +1 -1
- package/src/reference/raw-floats.mjs +1 -1
- package/src/reference/rehype-heading-anchors.mjs +116 -17
- package/src/reference/rehype-table-header-labels.mjs +21 -3
- package/src/reference/remark-asides.mjs +180 -0
- package/src/reference/remark-memo.mjs +42 -11
- package/src/reference/remark-notation.mjs +387 -36
- package/src/reference/render-lab-math.ts +16 -31
- package/src/reference/sections-validate.ts +81 -0
- package/src/reference/sections.mjs +306 -0
- package/src/reference/tables-validate.ts +2 -1
- package/src/reference/types.ts +17 -0
- package/src/reference/unit-words.ts +233 -0
- package/src/rules/catalog.ts +1298 -0
- package/src/rules/course-rules.ts +456 -0
- package/src/rules/in-effect.ts +235 -0
- package/src/rules/settings.ts +448 -0
- package/src/rules/waivers.ts +249 -0
- package/src/session/PreferenceStore.ts +15 -0
- package/src/styles/global.css +1471 -163
- package/src/styles/surfaces.css +182 -0
- package/src/components/hover-panel.ts +0 -339
- package/src/components/popup-stack.ts +0 -345
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
import { RuleId } from './rules/catalog.js';
|
|
2
|
+
import { CourseRule, CourseRuleDefinitions } from './rules/course-rules.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A course's per-rule settings — `rules` in `CourseConfig` — resolved against
|
|
6
|
+
* the catalog.
|
|
7
|
+
*
|
|
8
|
+
* The block is flat by rule ID and holds only deviations from the defaults:
|
|
9
|
+
*
|
|
10
|
+
* ```json
|
|
11
|
+
* "rules": {
|
|
12
|
+
* "P5": { "enabled": false },
|
|
13
|
+
* "S1": { "maxLength": 72 },
|
|
14
|
+
* "N14": { "allow": ["GDP"] }
|
|
15
|
+
* }
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* It also resolves the course's *own* rules — `courseRules`, a separate block
|
|
19
|
+
* with a separate module (`src/rules/course-rules.ts`) — so that one call hands
|
|
20
|
+
* the compiler every rule decision the course made, engine or not.
|
|
21
|
+
*
|
|
22
|
+
* `resolveRules` validates it (an unknown ID, an unknown key, a value outside
|
|
23
|
+
* its spec, or `enabled: false` on a locked rule is an error — the settings
|
|
24
|
+
* file is wrong, and a wrong bump would ship), applies every default from the
|
|
25
|
+
* catalog, folds in the deprecated top-level `operators` / `romanLabels` /
|
|
26
|
+
* `abbreviations` blocks, and hands the gates one object to ask. It never
|
|
27
|
+
* decides *what* a rule means — that is the catalog's job.
|
|
28
|
+
*
|
|
29
|
+
* `rulesJsonSchema` renders the same catalog as the JSON Schema fragment the
|
|
30
|
+
* course's settings form uses (`dist/rules/rules.schema.json`, built by
|
|
31
|
+
* `scripts/gen-rules-schema.mjs`), with properties ordered by element and an
|
|
32
|
+
* `x-element` hint per rule so the form can group them.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/** One rule's block in the settings file. Every key is optional. */
|
|
36
|
+
interface RuleSettingsInput {
|
|
37
|
+
readonly enabled?: boolean;
|
|
38
|
+
readonly [key: string]: unknown;
|
|
39
|
+
}
|
|
40
|
+
/** `CourseConfig.rules` — flat by rule ID. */
|
|
41
|
+
type CourseRulesConfig = Readonly<Record<string, RuleSettingsInput>>;
|
|
42
|
+
/** A non-fatal finding about the settings file itself. */
|
|
43
|
+
interface ConfigDiagnostic {
|
|
44
|
+
readonly code: 'config-deprecated-key' | 'config-retired-rule';
|
|
45
|
+
readonly severity: 'warning';
|
|
46
|
+
readonly message: string;
|
|
47
|
+
}
|
|
48
|
+
interface ResolvedRules {
|
|
49
|
+
/** False only for a rule the course turned off. An invariant is always on. */
|
|
50
|
+
isEnabled(id: string): boolean;
|
|
51
|
+
/** The course's own rules (`courseRules`), validated, in file order. */
|
|
52
|
+
readonly course: readonly CourseRule[];
|
|
53
|
+
/** The rule's settings with every default applied. `{}` for a rule without any. */
|
|
54
|
+
settings(id: string): Readonly<Record<string, unknown>>;
|
|
55
|
+
number(id: string, key: string): number;
|
|
56
|
+
strings(id: string, key: string): readonly string[];
|
|
57
|
+
/** Rules the course turned off — catalog order, then its own `X` rules. */
|
|
58
|
+
readonly disabled: readonly RuleId[];
|
|
59
|
+
readonly diagnostics: readonly ConfigDiagnostic[];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Validate `config.rules` (plus the deprecated top-level blocks) against the
|
|
63
|
+
* catalog and apply defaults. Throws on anything that would make a gate run
|
|
64
|
+
* with a value the author did not mean.
|
|
65
|
+
*/
|
|
66
|
+
declare function resolveRules(config: CourseConfig): ResolvedRules;
|
|
67
|
+
/** Rule S2's word ranges in the shape `gatePartPages` takes. */
|
|
68
|
+
declare function partPageLimits(rules: ResolvedRules): NormalizedPartPages;
|
|
69
|
+
type JsonSchema = Record<string, unknown>;
|
|
70
|
+
/**
|
|
71
|
+
* The `rules` property for a course's `course.settings.schema.json`:
|
|
72
|
+
* self-contained (no `$ref`), properties ordered by primary element, then
|
|
73
|
+
* catalog order. A retired rule is not in the catalog at all, so it cannot be a
|
|
74
|
+
* form field; a block for one is a warning at resolve time.
|
|
75
|
+
*/
|
|
76
|
+
declare function rulesJsonSchema(): JsonSchema;
|
|
77
|
+
/** Every rule and invariant ID, for tooling that wants the closed list. */
|
|
78
|
+
declare function catalogIds(): readonly string[];
|
|
79
|
+
/** What the manifest publishes about the course's rule settings. */
|
|
80
|
+
interface ManifestRules {
|
|
81
|
+
/** Rules the course turned off — catalog order, then its own `X` rules. */
|
|
82
|
+
readonly disabled: readonly RuleId[];
|
|
83
|
+
/** Every rule's settings with defaults applied, by ID. `{}` for a rule without any. */
|
|
84
|
+
readonly settings: Readonly<Record<string, Readonly<Record<string, unknown>>>>;
|
|
85
|
+
/**
|
|
86
|
+
* The course's own rules, as written in `courseRules` and validated. Carried
|
|
87
|
+
* in the manifest so the rules-in-effect page and `content rules` list them
|
|
88
|
+
* beside the engine's without re-reading the settings file.
|
|
89
|
+
*/
|
|
90
|
+
readonly course: readonly CourseRule[];
|
|
91
|
+
}
|
|
92
|
+
declare function rulesSnapshot(rules: ResolvedRules): ManifestRules;
|
|
93
|
+
/** The diagnostic codes owned by every rule the course turned off. */
|
|
94
|
+
declare function disabledCodes(rules: ResolvedRules): ReadonlySet<string>;
|
|
95
|
+
/**
|
|
96
|
+
* Drop every diagnostic a disabled rule owns. This is how a switch takes
|
|
97
|
+
* effect for a validator that hosts several owners (`consistency.ts`,
|
|
98
|
+
* `raw-floats-validate.ts`, the resolver behind `gate-math.ts`): the
|
|
99
|
+
* validator stays ignorant of the catalog and the manifest filters by code.
|
|
100
|
+
* A whole-rule gate (N9, N14, S1, S2) is additionally skipped at its call
|
|
101
|
+
* site so its work is not done at all. Curriculum issues carry `kind`, not
|
|
102
|
+
* `code`.
|
|
103
|
+
*/
|
|
104
|
+
declare function dropDisabled<T extends {
|
|
105
|
+
readonly code?: string;
|
|
106
|
+
readonly kind?: string;
|
|
107
|
+
}>(diagnostics: readonly T[], disabled: ReadonlySet<string>): T[];
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The shape `content/course.config.ts` must satisfy (Phase F).
|
|
111
|
+
*
|
|
112
|
+
* The engine never imports the course's config file; the wiring layer
|
|
113
|
+
* (`astro.config.mjs`, `scripts/*`, `src/content.config.ts`) imports the plain
|
|
114
|
+
* data value and passes it here, typed against `CourseConfig`. A second course
|
|
115
|
+
* supplies its own value of this shape.
|
|
116
|
+
*/
|
|
117
|
+
/**
|
|
118
|
+
* One **part** — a sidebar group, holding the chapters (lessons) whose slugs
|
|
119
|
+
* start with `dir`. A part's 1-based position in `CourseConfig.parts` is the
|
|
120
|
+
* first number in every section, equation, table, and figure number inside
|
|
121
|
+
* it. See `docs/authoring/structure.md` for the full level taxonomy.
|
|
122
|
+
*/
|
|
123
|
+
interface CoursePart {
|
|
124
|
+
/** Lesson-slug prefix, e.g. `bonds` for `bonds/yield-to-maturity`. */
|
|
125
|
+
readonly dir: string;
|
|
126
|
+
/** Sidebar group heading. */
|
|
127
|
+
readonly label: string;
|
|
128
|
+
/**
|
|
129
|
+
* The sidebar row that opens this part's **overview page**, when
|
|
130
|
+
* `content/docs/<dir>/index.mdx` exists. Defaults to `Overview`; the page's
|
|
131
|
+
* own title stays the part's name, which would only repeat the group
|
|
132
|
+
* heading one row below it.
|
|
133
|
+
*/
|
|
134
|
+
readonly overviewLabel?: string;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* @deprecated Renamed to {@link CoursePart}. "Section" now only ever means an
|
|
138
|
+
* `##` heading inside a lesson. Removed in the next MINOR release.
|
|
139
|
+
*/
|
|
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
|
+
/**
|
|
148
|
+
* A course's edits to the shipped named-operator baseline (`BASE_OPERATORS`),
|
|
149
|
+
* consumed by the `operator-explained` consistency check (rule N8). An operator
|
|
150
|
+
* a lesson uses is fine when it is on the baseline plus `allow` minus `deny`;
|
|
151
|
+
* otherwise it needs a notation entry the reader can hover.
|
|
152
|
+
*
|
|
153
|
+
* Names are the KaTeX command without its backslash (`erf`, not `\erf`) for a
|
|
154
|
+
* built-in, and the verbatim body for an `\operatorname{…}` operator (`Var`).
|
|
155
|
+
*/
|
|
156
|
+
interface CourseOperators {
|
|
157
|
+
/** Operators this course also treats as universal (`Var`, `Cov`, `sgn`, …). */
|
|
158
|
+
readonly allow?: readonly string[];
|
|
159
|
+
/** Baseline operators this course wants explained anyway. */
|
|
160
|
+
readonly deny?: readonly string[];
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* A course's edits to the shipped roman-label baseline (`BASE_ROMAN_LABELS`),
|
|
164
|
+
* consumed by the `roman-label-explained` consistency check (rule N10). A
|
|
165
|
+
* `\mathrm{…}` multi-letter label a lesson uses is fine when it is on the
|
|
166
|
+
* baseline plus `allow` minus `deny`; otherwise it needs a notation entry the
|
|
167
|
+
* reader can hover. Same shape as {@link CourseOperators}, one level down:
|
|
168
|
+
* this governs `\mathrm{KE}`-style labels, not `\operatorname{Var}`-style
|
|
169
|
+
* operators.
|
|
170
|
+
*/
|
|
171
|
+
interface CourseRomanLabels {
|
|
172
|
+
/** Labels this course also treats as universal qualifiers (`eff`, `net`, …). */
|
|
173
|
+
readonly allow?: readonly string[];
|
|
174
|
+
/** Baseline labels this course wants explained anyway. */
|
|
175
|
+
readonly deny?: readonly string[];
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* A course's edits to the shipped accent baseline (`BASE_ACCENTS`, empty),
|
|
179
|
+
* consumed by the `accent-explained` consistency check (rule N22). A
|
|
180
|
+
* decoration a lesson uses (`\hat`, `\bar`, `'`, `*`, …) is fine when it is on
|
|
181
|
+
* the baseline plus `allow` minus `deny`, explained by an operator entry
|
|
182
|
+
* (`latex: \hat{}`), or part of a whole-form entry (`latex: \hat{\beta}`).
|
|
183
|
+
* Same shape as {@link CourseOperators}; set under `rules.N22` only.
|
|
184
|
+
*/
|
|
185
|
+
interface CourseAccents {
|
|
186
|
+
/** Decorations this course treats as universal (`\dot`, `\vec`, …). */
|
|
187
|
+
readonly allow?: readonly string[];
|
|
188
|
+
/** Baseline decorations this course wants explained anyway. */
|
|
189
|
+
readonly deny?: readonly string[];
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* A course's edits to the shipped abbreviation baseline (`BASE_ABBREVIATIONS`),
|
|
193
|
+
* consumed by the `abbreviation-explained` gate (rule N14). An abbreviation-
|
|
194
|
+
* shaped token — an all-caps acronym or a dotted form like `w.r.t.` — a
|
|
195
|
+
* lesson uses in prose is fine when it is on the baseline plus `allow` minus
|
|
196
|
+
* `deny`; otherwise it needs an entry in the `abbreviations` content
|
|
197
|
+
* collection, or — if it also names a math quantity — a notation entry the
|
|
198
|
+
* reader can hover. Same shape as {@link CourseOperators} / {@link
|
|
199
|
+
* CourseRomanLabels}.
|
|
200
|
+
*/
|
|
201
|
+
interface CourseAbbreviations {
|
|
202
|
+
/** Abbreviations this course also treats as universal (`GDP`, `CPU`, …). */
|
|
203
|
+
readonly allow?: readonly string[];
|
|
204
|
+
/** Baseline abbreviations this course wants explained anyway. */
|
|
205
|
+
readonly deny?: readonly string[];
|
|
206
|
+
}
|
|
207
|
+
/** One person or team credited for the study material. */
|
|
208
|
+
interface CourseAuthor {
|
|
209
|
+
readonly name: string;
|
|
210
|
+
/**
|
|
211
|
+
* Email, URL, or handle. Rendered in the About panel as a link when it looks
|
|
212
|
+
* like a `mailto:` or `https:` target, plain text otherwise.
|
|
213
|
+
*/
|
|
214
|
+
readonly contact?: string;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* The reader-facing "about this material" block, surfaced by the `[?]` panel in
|
|
218
|
+
* the header (`components/starlight/AboutPanel.astro`) on every page.
|
|
219
|
+
*
|
|
220
|
+
* `version` is the course's **knowledge version** — semver over the
|
|
221
|
+
* learning-facing content, independent of the `explico` engine's own version.
|
|
222
|
+
* It must equal the newest entry in `content/CHANGELOG.md`; a mismatch is a
|
|
223
|
+
* Tier-3 `knowledge-version-mismatch` warning (rule C3, `docs/authoring/versioning.md`).
|
|
224
|
+
*/
|
|
225
|
+
interface CourseAbout {
|
|
226
|
+
/** Display name of the material. Defaults to {@link CourseConfig.title}. */
|
|
227
|
+
readonly materialName?: string;
|
|
228
|
+
/** One or two sentences on what the material covers. Defaults to {@link CourseConfig.description}. */
|
|
229
|
+
readonly summary?: string;
|
|
230
|
+
/** Knowledge version — semver; equals the latest `content/CHANGELOG.md` heading. */
|
|
231
|
+
readonly version: string;
|
|
232
|
+
/** Who authored / maintains the material. At least one entry. */
|
|
233
|
+
readonly authors: readonly CourseAuthor[];
|
|
234
|
+
/** Shown verbatim in the About panel — scope, warranty, AI-assistance note. */
|
|
235
|
+
readonly disclaimer: string;
|
|
236
|
+
/** Link to the published content changelog (repo blob, docs page, …). */
|
|
237
|
+
readonly changelogHref?: string;
|
|
238
|
+
}
|
|
239
|
+
/** A heading-like block's collapse default: may it fold, and does it start open? */
|
|
240
|
+
interface CourseHeadingDisclosure {
|
|
241
|
+
/** Wrap it in a collapsible section. */
|
|
242
|
+
readonly collapsible?: boolean;
|
|
243
|
+
/** Its state for a reader with nothing saved yet; ignored when not collapsible. */
|
|
244
|
+
readonly defaultOpen?: boolean;
|
|
245
|
+
}
|
|
246
|
+
/** A block that always folds; only its first-visit state is a course choice. */
|
|
247
|
+
interface CourseOpenDefault {
|
|
248
|
+
readonly defaultOpen?: boolean;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Every collapse default a course sets — the `disclosure` block of the course
|
|
252
|
+
* settings, in its own shape (docs/plans/titles-and-containers.md Part 4).
|
|
253
|
+
* Each kind names its default here:
|
|
254
|
+
*
|
|
255
|
+
* - **Full collapse**, the section wrapper (`CollapsibleSections.astro`):
|
|
256
|
+
* `sections` (`##`), `subsections` (`###`–`######`), `knowledgeChecks`, the
|
|
257
|
+
* generated `references` section, `memos` (a memo is a `######`-rank
|
|
258
|
+
* section of its own), `folds` (a `<Fold>`, the same without a memo's
|
|
259
|
+
* marker, letter or frame) and `workedExamples` (a set is a `##`-rank
|
|
260
|
+
* section of its own, Part 6). The notation panel (`notation`) folds the
|
|
261
|
+
* same way.
|
|
262
|
+
* - **A float's own fold**, which keeps its picture and caption line:
|
|
263
|
+
* `figures` sets whether a lab's tools start open
|
|
264
|
+
* (docs/plans/figures-and-short-captions.md, decision 5); a table is
|
|
265
|
+
* minimized by hand, and starts truncated when it has more than
|
|
266
|
+
* `tables.truncateAfter` rows. A figure or a diagram never folds by
|
|
267
|
+
* itself (decision 7).
|
|
268
|
+
*
|
|
269
|
+
* A heading's own marker (`[collapsible]`, `[collapsed]`, `[no-collapsible]`)
|
|
270
|
+
* and a component's `defaultOpen` prop override the kind's default at one
|
|
271
|
+
* place. Every collapsible remembers the reader's choice per page.
|
|
272
|
+
* {@link normalizeDisclosure} fills in the engine defaults — the values each
|
|
273
|
+
* kind had before they became settings.
|
|
274
|
+
*/
|
|
275
|
+
interface CourseDisclosure {
|
|
276
|
+
readonly sections?: CourseHeadingDisclosure;
|
|
277
|
+
readonly subsections?: CourseHeadingDisclosure;
|
|
278
|
+
readonly knowledgeChecks?: CourseHeadingDisclosure;
|
|
279
|
+
readonly notation?: CourseOpenDefault;
|
|
280
|
+
readonly references?: CourseOpenDefault;
|
|
281
|
+
readonly memos?: CourseOpenDefault;
|
|
282
|
+
/** Whether a `<Fold>` starts open. */
|
|
283
|
+
readonly folds?: CourseOpenDefault;
|
|
284
|
+
/** Whether a lab's tools start open. */
|
|
285
|
+
readonly figures?: CourseOpenDefault;
|
|
286
|
+
readonly workedExamples?: CourseOpenDefault;
|
|
287
|
+
readonly tables?: {
|
|
288
|
+
/** A table with more rows than this starts truncated. Default `6`. */
|
|
289
|
+
readonly truncateAfter?: number;
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
/** {@link CourseDisclosure} with every default applied. */
|
|
293
|
+
interface NormalizedDisclosure {
|
|
294
|
+
readonly sections: Required<CourseHeadingDisclosure>;
|
|
295
|
+
readonly subsections: Required<CourseHeadingDisclosure>;
|
|
296
|
+
readonly knowledgeChecks: Required<CourseHeadingDisclosure>;
|
|
297
|
+
readonly notation: Required<CourseOpenDefault>;
|
|
298
|
+
readonly references: Required<CourseOpenDefault>;
|
|
299
|
+
readonly memos: Required<CourseOpenDefault>;
|
|
300
|
+
readonly folds: Required<CourseOpenDefault>;
|
|
301
|
+
readonly figures: Required<CourseOpenDefault>;
|
|
302
|
+
readonly workedExamples: Required<CourseOpenDefault>;
|
|
303
|
+
readonly tables: {
|
|
304
|
+
readonly truncateAfter: number;
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* The engine's defaults. Headings do not fold unless the course says so;
|
|
309
|
+
* the notation panel, References, memos, folds and worked examples start
|
|
310
|
+
* closed; a knowledge check folds and starts open; a lab's tools start open;
|
|
311
|
+
* a table over 6 rows starts truncated.
|
|
312
|
+
*/
|
|
313
|
+
declare const DISCLOSURE_DEFAULTS: NormalizedDisclosure;
|
|
314
|
+
/** Validate `CourseConfig.disclosure` and apply its defaults. Throws on a bad value. */
|
|
315
|
+
declare function normalizeDisclosure(config: CourseConfig): NormalizedDisclosure;
|
|
316
|
+
/**
|
|
317
|
+
* How the course numbers its outline and its floats (`numbering` in the
|
|
318
|
+
* course settings; docs/authoring/structure.md § Numbering). Every field is
|
|
319
|
+
* optional; {@link normalizeNumbering} fills in the defaults.
|
|
320
|
+
*/
|
|
321
|
+
interface CourseNumbering {
|
|
322
|
+
readonly sections?: {
|
|
323
|
+
/**
|
|
324
|
+
* Show section numbers: on wide screens, in print, and on a collapsed
|
|
325
|
+
* section's bar. Default `true`. Off, `[[sec-…]]` prints the title.
|
|
326
|
+
*/
|
|
327
|
+
readonly show?: boolean;
|
|
328
|
+
/** The deepest heading level numbered, `2` (`##`) to `6`. Default `4`. */
|
|
329
|
+
readonly depth?: number;
|
|
330
|
+
};
|
|
331
|
+
/**
|
|
332
|
+
* The scope a float's counter runs over. `chapter` (default) restarts every
|
|
333
|
+
* kind in each chapter and prints `‹part›.‹chapter›.‹n›`; `part` runs on
|
|
334
|
+
* across the part's chapters and prints `‹part›.‹n›`. A plain `string`
|
|
335
|
+
* because the settings arrive as JSON; {@link normalizeNumbering} rejects
|
|
336
|
+
* any other value.
|
|
337
|
+
*/
|
|
338
|
+
readonly floats?: string;
|
|
339
|
+
/**
|
|
340
|
+
* Resolve a number-form fragment a reader types (`#sec-1.1.2`,
|
|
341
|
+
* `#fig-2.2.1`) to the named anchor. Default `true`. The site itself only
|
|
342
|
+
* ever links and copies the named anchor.
|
|
343
|
+
*/
|
|
344
|
+
readonly aliases?: boolean;
|
|
345
|
+
}
|
|
346
|
+
/** {@link CourseNumbering} with every default applied. */
|
|
347
|
+
interface NormalizedNumbering {
|
|
348
|
+
readonly sections: {
|
|
349
|
+
readonly show: boolean;
|
|
350
|
+
readonly depth: number;
|
|
351
|
+
};
|
|
352
|
+
readonly floats: 'chapter' | 'part';
|
|
353
|
+
readonly aliases: boolean;
|
|
354
|
+
}
|
|
355
|
+
/** Validate `CourseConfig.numbering` and apply its defaults. Throws on a bad value. */
|
|
356
|
+
declare function normalizeNumbering(config: CourseConfig): NormalizedNumbering;
|
|
357
|
+
/**
|
|
358
|
+
* How a knowledge check's and a worked-example set's heading names its kind
|
|
359
|
+
* (`blockLabels` in the course settings; docs/plans/titles-and-containers.md
|
|
360
|
+
* Q11). The engine draws the kind before the author's title: `icon-word`
|
|
361
|
+
* (the default) shows the kind's icon and its word, "Knowledge check" or
|
|
362
|
+
* "Example"; `icon` shows the icon alone and keeps the word for a screen
|
|
363
|
+
* reader.
|
|
364
|
+
*/
|
|
365
|
+
type BlockLabels = 'icon' | 'icon-word';
|
|
366
|
+
/** The engine default for {@link CourseConfig.blockLabels}. */
|
|
367
|
+
declare const BLOCK_LABELS_DEFAULT: BlockLabels;
|
|
368
|
+
/** Validate `CourseConfig.blockLabels` and apply its default. Throws on a bad value. */
|
|
369
|
+
declare function normalizeBlockLabels(config: CourseConfig): BlockLabels;
|
|
370
|
+
/**
|
|
371
|
+
* Rule S2's word ranges (`rules.S2.bridgeMinWords` … in the course settings),
|
|
372
|
+
* in the shape `gate-part-pages.ts` takes. Built by `partPageLimits` in
|
|
373
|
+
* `src/rules/settings.ts`.
|
|
374
|
+
*/
|
|
375
|
+
interface NormalizedPartPages {
|
|
376
|
+
readonly bridge: {
|
|
377
|
+
readonly minWords: number;
|
|
378
|
+
readonly maxWords: number;
|
|
379
|
+
};
|
|
380
|
+
readonly scope: {
|
|
381
|
+
readonly minWords: number;
|
|
382
|
+
readonly maxWords: number;
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
/** Optional, build-time lesson artifacts exposed to readers. */
|
|
386
|
+
interface LessonExportsConfig {
|
|
387
|
+
/** Emit one self-contained, offline-capable HTML file per lesson. */
|
|
388
|
+
readonly standaloneHtml?: boolean;
|
|
389
|
+
/** Offer the browser's native print dialog with explico's lesson print layout. */
|
|
390
|
+
readonly print?: boolean;
|
|
391
|
+
/**
|
|
392
|
+
* Published course root used for links that intentionally leave the exported
|
|
393
|
+
* lesson. Required at export time when such a link is present.
|
|
394
|
+
*/
|
|
395
|
+
readonly canonicalBaseUrl?: string;
|
|
396
|
+
}
|
|
397
|
+
/** The stable, non-optional export settings carried by the manifest. */
|
|
398
|
+
interface NormalizedLessonExports {
|
|
399
|
+
readonly standaloneHtml: boolean;
|
|
400
|
+
readonly print: boolean;
|
|
401
|
+
readonly canonicalBaseUrl?: string;
|
|
402
|
+
}
|
|
403
|
+
interface CourseConfig {
|
|
404
|
+
readonly title: string;
|
|
405
|
+
readonly description: string;
|
|
406
|
+
/**
|
|
407
|
+
* The course's parts (sidebar groups), in order. Exactly one of `parts` or
|
|
408
|
+
* the deprecated `sections` must be given.
|
|
409
|
+
*/
|
|
410
|
+
readonly parts?: readonly CoursePart[];
|
|
411
|
+
/**
|
|
412
|
+
* @deprecated Renamed to {@link CourseConfig.parts}. Still honoured, so a
|
|
413
|
+
* course on the old name keeps building; removed in the next MINOR release.
|
|
414
|
+
*/
|
|
415
|
+
readonly sections?: readonly CoursePart[];
|
|
416
|
+
/** Namespaces used by competency / notation `domain` fields. */
|
|
417
|
+
readonly domains: readonly string[];
|
|
418
|
+
readonly conventions: CourseConventions;
|
|
419
|
+
/** Reader-facing identity + knowledge version (the `[?]` About panel). */
|
|
420
|
+
readonly about: CourseAbout;
|
|
421
|
+
/**
|
|
422
|
+
* Per-rule switches and settings, flat by rule ID — only what differs from
|
|
423
|
+
* the defaults (`{ "P5": { "enabled": false }, "S1": { "maxLength": 72 } }`).
|
|
424
|
+
* Resolved and validated by `resolveRules` (`src/rules/settings.ts`); the
|
|
425
|
+
* closed list of IDs and settings is `src/rules/catalog.ts`.
|
|
426
|
+
*/
|
|
427
|
+
readonly rules?: CourseRulesConfig;
|
|
428
|
+
/**
|
|
429
|
+
* The course's *own* rules, on top of the engine's — `X1`…`X99`, each with
|
|
430
|
+
* its own text, elements, severity and optional `forbid` patterns. A list,
|
|
431
|
+
* not a map, so the settings form can add and remove one. Resolved and
|
|
432
|
+
* validated by `resolveCourseRules` (`src/rules/course-rules.ts`).
|
|
433
|
+
*/
|
|
434
|
+
readonly courseRules?: CourseRuleDefinitions;
|
|
435
|
+
/** @deprecated Moved to `rules.N8` (same shape). Honoured for now; removed in a later MINOR. */
|
|
436
|
+
readonly operators?: CourseOperators;
|
|
437
|
+
/** @deprecated Moved to `rules.N10` (same shape). Honoured for now; removed in a later MINOR. */
|
|
438
|
+
readonly romanLabels?: CourseRomanLabels;
|
|
439
|
+
/** @deprecated Moved to `rules.N14` (same shape). Honoured for now; removed in a later MINOR. */
|
|
440
|
+
readonly abbreviations?: CourseAbbreviations;
|
|
441
|
+
/** Per-lesson export actions and downloadable artifacts. Disabled when omitted. */
|
|
442
|
+
readonly lessonExports?: LessonExportsConfig;
|
|
443
|
+
/** Every collapse default: headings, checks, memos, floats, tables. */
|
|
444
|
+
readonly disclosure?: CourseDisclosure;
|
|
445
|
+
/** Outline and float numbering. The defaults apply when omitted. */
|
|
446
|
+
readonly numbering?: CourseNumbering;
|
|
447
|
+
/**
|
|
448
|
+
* How a check's and an example set's heading names its kind: `icon-word`
|
|
449
|
+
* (default) or `icon` ({@link BlockLabels}). A plain `string` because the
|
|
450
|
+
* settings arrive as JSON; {@link normalizeBlockLabels} rejects any other
|
|
451
|
+
* value.
|
|
452
|
+
*/
|
|
453
|
+
readonly blockLabels?: string;
|
|
454
|
+
}
|
|
455
|
+
/** Validate and canonicalize the build-facing lesson-export configuration. */
|
|
456
|
+
declare function normalizeLessonExports(config: CourseConfig): NormalizedLessonExports;
|
|
457
|
+
/**
|
|
458
|
+
* The course's parts, from whichever field the config uses. Throws rather than
|
|
459
|
+
* silently producing a course with no sidebar groups — a config with neither
|
|
460
|
+
* field would otherwise number every float by the `##`-section fallback.
|
|
461
|
+
*/
|
|
462
|
+
declare function coursePartsOf(config: CourseConfig): readonly CoursePart[];
|
|
463
|
+
|
|
464
|
+
export { type CourseSection as A, type BlockLabels as B, type CourseConfig as C, DISCLOSURE_DEFAULTS as D, coursePartsOf as E, normalizeBlockLabels as F, normalizeDisclosure as G, normalizeLessonExports as H, normalizeNumbering as I, type LessonExportsConfig as L, type ManifestRules as M, type NormalizedPartPages as N, type ResolvedRules as R, type CourseAbbreviations as a, type NormalizedLessonExports as b, type NormalizedDisclosure as c, type NormalizedNumbering as d, type ConfigDiagnostic as e, type CourseConventions as f, type CourseOperators as g, type CourseRomanLabels as h, type CourseAccents 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, type CourseAbout as t, type CourseAuthor as u, type CourseDisclosure as v, type CourseHeadingDisclosure as w, type CourseNumbering as x, type CourseOpenDefault as y, type CoursePart as z };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The decorations a course treats as universal, given its `rules.N22` block:
|
|
3
|
+
* the shipped baseline, plus `allow`, minus `deny`.
|
|
4
|
+
*
|
|
5
|
+
* @param {{ allow?: readonly string[], deny?: readonly string[] } | undefined} accents
|
|
6
|
+
* @returns {Set<string>}
|
|
7
|
+
*/
|
|
8
|
+
export function effectiveAccentAllowlist(accents: {
|
|
9
|
+
allow?: readonly string[];
|
|
10
|
+
deny?: readonly string[];
|
|
11
|
+
} | undefined): Set<string>;
|
|
12
|
+
/**
|
|
13
|
+
* The base accent baseline: decorations every reader is assumed to know, so a
|
|
14
|
+
* lesson never has to explain them (rule N22). The named-operator counterpart
|
|
15
|
+
* is `base-operators.mjs` (rule N8).
|
|
16
|
+
*
|
|
17
|
+
* It ships **empty**, because no decoration has one meaning across fields:
|
|
18
|
+
* `\hat` can mean an estimator, a unit vector or a Fourier transform; `\bar`
|
|
19
|
+
* a mean, a conjugate or a closure; `'` a derivative or "another one". A
|
|
20
|
+
* course that uses one consistently says so with `rules.N22.allow` (a physics
|
|
21
|
+
* course might allow `\dot` and `\vec`); anything else is explained by an
|
|
22
|
+
* operator entry (`latex: \hat{}`) or a whole-form entry (`latex:
|
|
23
|
+
* \hat{\beta}`). Names are the canonical ones in `DECORATION_NAMES`
|
|
24
|
+
* (`math-glyphs.mjs`): `\hat`, `\overline`, `'`, `*`, `\dagger`, ….
|
|
25
|
+
*/
|
|
26
|
+
export const BASE_ACCENTS: Readonly<Set<any>>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The base accent baseline: decorations every reader is assumed to know, so a
|
|
3
|
+
* lesson never has to explain them (rule N22). The named-operator counterpart
|
|
4
|
+
* is `base-operators.mjs` (rule N8).
|
|
5
|
+
*
|
|
6
|
+
* It ships **empty**, because no decoration has one meaning across fields:
|
|
7
|
+
* `\hat` can mean an estimator, a unit vector or a Fourier transform; `\bar`
|
|
8
|
+
* a mean, a conjugate or a closure; `'` a derivative or "another one". A
|
|
9
|
+
* course that uses one consistently says so with `rules.N22.allow` (a physics
|
|
10
|
+
* course might allow `\dot` and `\vec`); anything else is explained by an
|
|
11
|
+
* operator entry (`latex: \hat{}`) or a whole-form entry (`latex:
|
|
12
|
+
* \hat{\beta}`). Names are the canonical ones in `DECORATION_NAMES`
|
|
13
|
+
* (`math-glyphs.mjs`): `\hat`, `\overline`, `'`, `*`, `\dagger`, ….
|
|
14
|
+
*/
|
|
15
|
+
export const BASE_ACCENTS = Object.freeze(new Set());
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The decorations a course treats as universal, given its `rules.N22` block:
|
|
19
|
+
* the shipped baseline, plus `allow`, minus `deny`.
|
|
20
|
+
*
|
|
21
|
+
* @param {{ allow?: readonly string[], deny?: readonly string[] } | undefined} accents
|
|
22
|
+
* @returns {Set<string>}
|
|
23
|
+
*/
|
|
24
|
+
export function effectiveAccentAllowlist(accents) {
|
|
25
|
+
const allow = accents?.allow ?? [];
|
|
26
|
+
const deny = new Set(accents?.deny ?? []);
|
|
27
|
+
const effective = new Set(BASE_ACCENTS);
|
|
28
|
+
for (const name of allow) effective.add(name);
|
|
29
|
+
for (const name of deny) effective.delete(name);
|
|
30
|
+
return effective;
|
|
31
|
+
}
|
|
@@ -18,8 +18,8 @@ export function isBaseRomanLabel(name: any, romanLabels: any): boolean;
|
|
|
18
18
|
* (rule N8); this is its `\mathrm{…}` twin (rule N10).
|
|
19
19
|
*
|
|
20
20
|
* Rationale: the completeness gate has no opinion about `\mathrm{…}` bodies —
|
|
21
|
-
* they are a typographic label to KaTeX, not a bindable symbol,
|
|
22
|
-
*
|
|
21
|
+
* they are a typographic label to KaTeX, not a bindable symbol, so the
|
|
22
|
+
* format half of rule N10 says nothing about whether the label is explained.
|
|
23
23
|
* The `roman-label-explained` consistency check fills that gap: a label a
|
|
24
24
|
* lesson uses is either on this list (or the course's additions to it) or it
|
|
25
25
|
* carries a notation entry the reader can hover.
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* (rule N8); this is its `\mathrm{…}` twin (rule N10).
|
|
6
6
|
*
|
|
7
7
|
* Rationale: the completeness gate has no opinion about `\mathrm{…}` bodies —
|
|
8
|
-
* they are a typographic label to KaTeX, not a bindable symbol,
|
|
9
|
-
*
|
|
8
|
+
* they are a typographic label to KaTeX, not a bindable symbol, so the
|
|
9
|
+
* format half of rule N10 says nothing about whether the label is explained.
|
|
10
10
|
* The `roman-label-explained` consistency check fills that gap: a label a
|
|
11
11
|
* lesson uses is either on this list (or the course's additions to it) or it
|
|
12
12
|
* carries a notation entry the reader can hover.
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { CourseConventions, CourseOperators, CourseRomanLabels } from '../
|
|
1
|
+
import { f as CourseConventions, g as CourseOperators, h as CourseRomanLabels, i as CourseAccents } from '../course-config-Dsnri9Tk.js';
|
|
2
2
|
import { CurriculumCatalog } from '../curriculum/validation.js';
|
|
3
3
|
import { NotationSpec } from '../compiler/collections.js';
|
|
4
4
|
import { LintIgnore } from './lint-ignore.js';
|
|
5
5
|
import { NotationRegistry, NotationRegistryInput } from './types.js';
|
|
6
|
+
import '../rules/catalog.js';
|
|
7
|
+
import '../rules/course-rules.js';
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* Corpus consistency checks (Step D6) — the Tier 1–2 checks from the cleanup
|
|
@@ -30,12 +32,20 @@ import { NotationRegistry, NotationRegistryInput } from './types.js';
|
|
|
30
32
|
* uses is on the shipped/course roman-label
|
|
31
33
|
* allowlist or carries a notation entry
|
|
32
34
|
* (rule N10)
|
|
35
|
+
* (j) accent-explained a decoration a lesson composes (`\hat`,
|
|
36
|
+
* `'`, `^*`, …) is on the course accent
|
|
37
|
+
* allowlist, explained by an operator entry,
|
|
38
|
+
* or part of a whole-form entry (rule N22)
|
|
39
|
+
* (k) operator-suspended / a `notation.suspend` item, with or without
|
|
40
|
+
* operator-suspension-reason its reason, and a whole-form entry that
|
|
41
|
+
* / operator-shadowed shadows an operator the page does not
|
|
42
|
+
* suspend (rule N22)
|
|
33
43
|
*
|
|
34
44
|
* Check (d) — the committed per-lesson resolution report — lives in
|
|
35
45
|
* `src/content/resolution-report.ts`.
|
|
36
46
|
*/
|
|
37
47
|
|
|
38
|
-
type ConsistencyCode = 'glyph-unique-in-corpus' | 'notation-units' | 'units-vocab' | 'convention-single-definition' | 'weak-local' | 'notation-source-locator' | 'gloss-wants-promoting' | 'card-wants-demoting' | 'gloss-name-shape' | 'operator-explained' | 'roman-label-explained';
|
|
48
|
+
type ConsistencyCode = 'glyph-unique-in-corpus' | 'notation-units' | 'units-vocab' | 'convention-single-definition' | 'weak-local' | 'notation-source-locator' | 'gloss-wants-promoting' | 'card-wants-demoting' | 'gloss-name-shape' | 'operator-explained' | 'roman-label-explained' | 'accent-explained' | 'operator-suspended' | 'operator-suspension-reason' | 'operator-shadowed';
|
|
39
49
|
interface ConsistencyDiagnostic {
|
|
40
50
|
readonly code: ConsistencyCode;
|
|
41
51
|
/** Tier 3 — repairable violations are warnings; optional advice is info. */
|
|
@@ -60,6 +70,8 @@ interface ConsistencyInput {
|
|
|
60
70
|
readonly operators?: CourseOperators;
|
|
61
71
|
/** This course's edits to the roman-label baseline (rule N10). */
|
|
62
72
|
readonly romanLabels?: CourseRomanLabels;
|
|
73
|
+
/** This course's edits to the (empty) accent baseline (rule N22). */
|
|
74
|
+
readonly accents?: CourseAccents;
|
|
63
75
|
}
|
|
64
76
|
/**
|
|
65
77
|
* Run every consistency check. The result is sorted deterministically (code,
|