explico 0.13.1 → 0.15.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 +990 -1
- package/README.md +200 -30
- package/dist/compiler/astro.d.ts +15 -2
- package/dist/compiler/astro.js +40 -11
- package/dist/compiler/cli-main.d.ts +100 -0
- package/dist/compiler/cli-main.js +433 -0
- package/dist/compiler/cli-reference.d.ts +50 -0
- package/dist/compiler/cli-reference.js +213 -0
- package/dist/compiler/cli-verbs.d.ts +45 -0
- package/dist/compiler/cli-verbs.js +224 -0
- package/dist/compiler/cli-verify.d.ts +51 -0
- package/dist/compiler/cli-verify.js +151 -0
- package/dist/compiler/cli.d.ts +408 -24
- package/dist/compiler/cli.js +1328 -8
- package/dist/compiler/collections.d.ts +88 -1
- package/dist/compiler/collections.js +170 -25
- package/dist/compiler/content-release.d.ts +49 -0
- package/dist/compiler/content-release.js +63 -0
- package/dist/compiler/content-schemas.d.ts +2 -2
- package/dist/compiler/course-config.d.ts +1 -1
- package/dist/compiler/course-config.js +105 -1
- package/dist/compiler/decks.d.ts +161 -0
- package/dist/compiler/decks.js +235 -0
- package/dist/compiler/exports/combined-html.d.ts +5 -1
- package/dist/compiler/exports/deck-fit.d.ts +55 -0
- package/dist/compiler/exports/deck-fit.js +90 -0
- package/dist/compiler/exports/export-chapters.d.ts +37 -6
- package/dist/compiler/exports/export-chapters.js +64 -5
- package/dist/compiler/exports/export-pages.d.ts +30 -3
- package/dist/compiler/exports/export-pages.js +24 -1
- package/dist/compiler/exports/latex/beamerthemeexplico.sty +124 -0
- package/dist/compiler/exports/latex/cache.d.ts +78 -0
- package/dist/compiler/exports/latex/cache.js +129 -0
- package/dist/compiler/exports/latex/capture.d.ts +10 -1
- package/dist/compiler/exports/latex/capture.js +3 -1
- package/dist/compiler/exports/latex/compile.d.ts +13 -2
- package/dist/compiler/exports/latex/compile.js +12 -1
- package/dist/compiler/exports/latex/deck.d.ts +92 -0
- package/dist/compiler/exports/latex/deck.js +349 -0
- package/dist/compiler/exports/latex/document.d.ts +51 -6
- package/dist/compiler/exports/latex/document.js +71 -12
- package/dist/compiler/exports/latex/explico-common.sty +198 -0
- package/dist/compiler/exports/latex/explico.cls +13 -183
- package/dist/compiler/exports/latex/serialize.d.ts +60 -4
- package/dist/compiler/exports/latex/serialize.js +4 -2
- package/dist/compiler/exports/latex-export.d.ts +24 -2
- package/dist/compiler/exports/latex-export.js +107 -26
- package/dist/compiler/exports/markdown/serialize.d.ts +24 -4
- package/dist/compiler/exports/markdown/serialize.js +85 -8
- package/dist/compiler/exports/markdown-export.d.ts +6 -1
- package/dist/compiler/exports/markdown-export.js +50 -11
- package/dist/compiler/exports/standalone-html.d.ts +10 -5
- package/dist/compiler/exports/standalone-html.js +3 -3
- package/dist/compiler/exports/static-tree.d.ts +38 -1
- package/dist/compiler/exports/static-tree.js +120 -4
- package/dist/compiler/knowledge-version.d.ts +26 -2
- package/dist/compiler/knowledge-version.js +27 -17
- package/dist/compiler/lesson-derivation.d.ts +143 -6
- package/dist/compiler/lesson-derivation.js +145 -13
- package/dist/compiler/manifest.d.ts +133 -4
- package/dist/compiler/manifest.js +364 -58
- package/dist/compiler/page-versions.d.ts +184 -0
- package/dist/compiler/page-versions.js +217 -0
- package/dist/compiler/render-diagnostics.d.ts +5 -1
- package/dist/compiler/resolution-report.d.ts +24 -6
- package/dist/compiler/resolution-report.js +22 -4
- package/dist/compiler/validate-content.d.ts +7 -0
- package/dist/compiler/validate-content.js +160 -0
- package/dist/{course-config-rRtME5UV.d.ts → course-config-BLtIdkei.d.ts} +164 -1
- package/dist/curriculum/competency-graph.d.ts +54 -0
- package/dist/curriculum/competency-graph.js +41 -0
- package/dist/reference/base-library.d.mts +8 -0
- package/dist/reference/base-library.mjs +19 -0
- package/dist/reference/consistency.d.ts +8 -4
- package/dist/reference/consistency.js +82 -26
- package/dist/reference/deck-remark.d.mts +123 -0
- package/dist/reference/deck-remark.mjs +600 -0
- package/dist/reference/deck-source.d.ts +107 -0
- package/dist/reference/deck-source.js +140 -0
- package/dist/reference/decks-validate.d.ts +133 -0
- package/dist/reference/decks-validate.js +359 -0
- package/dist/reference/derived-entries.d.ts +5 -1
- package/dist/reference/diagram-fit.d.ts +6 -2
- package/dist/reference/diagram-fit.js +5 -1
- package/dist/reference/figure-symbols.d.ts +23 -6
- package/dist/reference/figure-symbols.js +51 -15
- package/dist/reference/float-name.d.ts +43 -0
- package/dist/reference/float-name.js +58 -0
- package/dist/reference/folds-validate.d.ts +1 -1
- package/dist/reference/gate-abbreviations.d.ts +1 -1
- package/dist/reference/gate-indices.js +5 -4
- package/dist/reference/gate-math.d.ts +29 -2
- package/dist/reference/gate-math.js +99 -18
- package/dist/reference/gate-part-pages.d.ts +1 -1
- package/dist/reference/lab-katex-validate.d.ts +10 -6
- package/dist/reference/lab-katex-validate.js +17 -9
- package/dist/reference/lab-math-scope.js +29 -4
- package/dist/reference/math-glyphs.d.mts +25 -0
- package/dist/reference/math-glyphs.mjs +189 -25
- package/dist/reference/page-notation.d.ts +22 -3
- package/dist/reference/page-notation.js +32 -10
- package/dist/reference/references.d.ts +14 -1
- package/dist/reference/references.js +13 -0
- package/dist/reference/registry-scope.d.mts +33 -0
- package/dist/reference/registry-scope.mjs +34 -0
- package/dist/reference/registry.js +29 -10
- package/dist/reference/rehype-deck.d.mts +6 -0
- package/dist/reference/rehype-deck.mjs +286 -0
- package/dist/reference/rehype-heading-anchors.d.mts +20 -0
- package/dist/reference/rehype-heading-anchors.mjs +48 -6
- package/dist/reference/remark-notation.mjs +249 -40
- package/dist/reference/source-lines.d.mts +12 -0
- package/dist/reference/source-lines.mjs +65 -0
- package/dist/reference/types.d.ts +28 -0
- package/dist/rules/catalog.d.ts +21 -4
- package/dist/rules/catalog.js +237 -2
- package/dist/rules/course-rules.d.ts +5 -1
- package/dist/rules/course-rules.js +17 -3
- package/dist/rules/course-rules.schema.json +12 -0
- package/dist/rules/in-effect.d.ts +13 -3
- package/dist/rules/in-effect.js +34 -10
- package/dist/rules/rules.schema.json +280 -1
- package/dist/rules/settings.d.ts +1 -1
- package/dist/session/PreferenceStore.d.ts +6 -0
- package/dist/session/PreferenceStore.js +18 -1
- package/dist/session/deck-memory.d.ts +116 -0
- package/dist/session/deck-memory.js +143 -0
- package/dist/session/reading-memory.d.ts +96 -0
- package/dist/session/reading-memory.js +133 -0
- package/docs/VERSIONING.md +21 -18
- package/docs/authoring/README.md +31 -9
- package/docs/authoring/agents.md +72 -18
- package/docs/authoring/cli-reference.json +2172 -0
- package/docs/authoring/cli.md +887 -0
- package/docs/authoring/components.md +15 -0
- package/docs/authoring/deck.md +612 -0
- package/docs/authoring/migrating.md +1195 -16
- package/docs/authoring/notation.md +49 -6
- package/docs/authoring/structure.md +80 -1
- package/docs/authoring/versioning.md +56 -3
- package/docs/authoring/visualizations.md +7 -2
- package/docs/course-agent/AGENTS.md +40 -0
- package/docs/course-agent/agents/rules-reviewer.md +33 -0
- package/docs/course-agent/skills/draft-lesson/SKILL.md +38 -0
- package/docs/course-agent/skills/migrate-course/SKILL.md +32 -0
- package/docs/course-agent/skills/release-content/SKILL.md +26 -0
- package/docs/diagram-scaling.md +148 -0
- package/docs/privacy.md +59 -0
- package/package.json +8 -2
- package/src/compiler/astro.ts +60 -21
- package/src/compiler/cli-main.ts +557 -0
- package/src/compiler/cli-reference.ts +285 -0
- package/src/compiler/cli-verbs.ts +270 -0
- package/src/compiler/cli-verify.ts +241 -0
- package/src/compiler/cli.ts +2119 -170
- package/src/compiler/collections.ts +284 -25
- package/src/compiler/content-release.ts +91 -0
- package/src/compiler/course-config.ts +267 -0
- package/src/compiler/decks.ts +455 -0
- package/src/compiler/exports/deck-fit.ts +127 -0
- package/src/compiler/exports/export-chapters.ts +105 -6
- package/src/compiler/exports/export-pages.ts +46 -2
- package/src/compiler/exports/latex/beamerthemeexplico.sty +124 -0
- package/src/compiler/exports/latex/cache.ts +183 -0
- package/src/compiler/exports/latex/capture.ts +5 -2
- package/src/compiler/exports/latex/compile.ts +18 -0
- package/src/compiler/exports/latex/deck.ts +419 -0
- package/src/compiler/exports/latex/document.ts +117 -21
- package/src/compiler/exports/latex/explico-common.sty +198 -0
- package/src/compiler/exports/latex/explico.cls +13 -183
- package/src/compiler/exports/latex/serialize.ts +25 -21
- package/src/compiler/exports/latex/texlive-packages.txt +6 -2
- package/src/compiler/exports/latex-export.ts +187 -45
- package/src/compiler/exports/markdown/serialize.ts +118 -9
- package/src/compiler/exports/markdown-export.ts +56 -11
- package/src/compiler/exports/standalone-html.ts +8 -7
- package/src/compiler/exports/static-tree.ts +175 -3
- package/src/compiler/knowledge-version.ts +56 -21
- package/src/compiler/lesson-derivation.ts +282 -16
- package/src/compiler/manifest.ts +568 -63
- package/src/compiler/page-versions.ts +401 -0
- package/src/compiler/resolution-report.ts +38 -7
- package/src/compiler/validate-content.ts +215 -0
- package/src/components/CourseContents.astro +124 -6
- package/src/components/CurriculumMap.astro +49 -1
- package/src/components/FloatIndex.astro +1 -1
- package/src/components/PartOverview.astro +51 -5
- package/src/components/assessments/AssessmentSet.astro +41 -15
- package/src/components/block-heading.ts +15 -6
- package/src/components/card-carry.ts +7 -4
- package/src/components/card-manager.ts +14 -2
- package/src/components/card-memory.ts +13 -9
- package/src/components/deck/DeckEnhancer.astro +13 -0
- package/src/components/deck/deck-context.ts +104 -0
- package/src/components/deck/deck-controller.ts +1287 -0
- package/src/components/deck/deck-map.ts +91 -0
- package/src/components/deck-lane.ts +163 -0
- package/src/components/diagram/Diagram.astro +131 -86
- package/src/components/disclosure/persisted-disclosure.ts +9 -1
- package/src/components/figure/Figure.astro +7 -2
- package/src/components/figure/FloatCaption.astro +5 -3
- package/src/components/fold/Fold.astro +2 -2
- package/src/components/notation/NotationFormula.astro +81 -11
- package/src/components/notation/NotationGlossary.astro +132 -1
- package/src/components/notation/NotationLayer.astro +15 -7
- package/src/components/starlight/AboutPanel.astro +186 -3
- package/src/components/starlight/CollapsibleSections.astro +24 -3
- package/src/components/starlight/DiagramEnhancer.astro +5 -1
- package/src/components/starlight/HeadingAnchorEnhancer.astro +1 -1
- package/src/components/starlight/LayoutHeader.astro +17 -0
- package/src/components/starlight/LayoutPageTitle.astro +110 -0
- package/src/components/starlight/LayoutSidebar.astro +807 -21
- package/src/components/starlight/LayoutSocialIcons.astro +62 -6
- package/src/components/starlight/LessonExportActions.astro +27 -9
- package/src/components/starlight/LessonFooter.astro +59 -0
- package/src/components/starlight/ReadingMemoryNotice.astro +114 -0
- package/src/components/starlight/TextSizeControl.astro +24 -13
- package/src/components/starlight/page-marks.ts +139 -0
- package/src/components/starlight/section-summary.ts +1 -1
- package/src/components/starlight/sidebar-editions.ts +245 -0
- package/src/components/table/Table.astro +15 -7
- package/src/content-config.ts +87 -1
- package/src/curriculum/competency-graph.ts +95 -0
- package/src/reference/base-library.mjs +19 -0
- package/src/reference/consistency.ts +137 -39
- package/src/reference/deck-remark.mjs +600 -0
- package/src/reference/deck-source.ts +273 -0
- package/src/reference/decks-validate.ts +604 -0
- package/src/reference/diagram-fit.ts +18 -4
- package/src/reference/diagram-layout.ts +3 -1
- package/src/reference/figure-symbols.ts +108 -31
- package/src/reference/folds-validate.ts +1 -1
- package/src/reference/gate-indices.ts +5 -3
- package/src/reference/gate-math.ts +169 -25
- package/src/reference/lab-katex-validate.ts +30 -15
- package/src/reference/lab-math-scope.ts +34 -3
- package/src/reference/math-glyphs.mjs +189 -25
- package/src/reference/page-notation.ts +69 -15
- package/src/reference/references.ts +28 -0
- package/src/reference/registry-scope.mjs +34 -0
- package/src/reference/registry.ts +41 -11
- package/src/reference/rehype-deck.mjs +286 -0
- package/src/reference/rehype-heading-anchors.mjs +48 -6
- package/src/reference/remark-notation.mjs +249 -40
- package/src/reference/source-lines.mjs +65 -0
- package/src/reference/types.ts +28 -0
- package/src/rules/catalog.ts +274 -4
- package/src/rules/course-rules.ts +21 -1
- package/src/rules/in-effect.ts +58 -11
- package/src/session/PreferenceStore.ts +23 -0
- package/src/session/deck-memory.ts +263 -0
- package/src/session/reading-memory.ts +243 -0
- package/src/styles/deck.css +1150 -0
- package/src/styles/global.css +958 -27
- package/src/styles/zones.css +277 -0
- /package/src/{components → reference}/float-name.ts +0 -0
|
@@ -20,6 +20,73 @@ import { ContentRecord } from '../reference/gate-retired-keys.js';
|
|
|
20
20
|
* ignoring code fences and inline code, sorted by position.
|
|
21
21
|
*/
|
|
22
22
|
declare function extractNotationReferences(text: string, file: string, kind: NotationReferenceInput['kind'] | undefined): NotationReferenceInput[];
|
|
23
|
+
/** What every deck file is, whichever it belongs to ({@link DeckFile}). */
|
|
24
|
+
interface DeckFileBase {
|
|
25
|
+
/** Absolute path of the deck file. */
|
|
26
|
+
readonly path: string;
|
|
27
|
+
/** Repository-relative path, the `file` of its diagnostics. */
|
|
28
|
+
readonly file: string;
|
|
29
|
+
/** Docs slug of the deck file, extension included: `motion/range.deck.mdx`. */
|
|
30
|
+
readonly slug: string;
|
|
31
|
+
/** Where the deck is served: `motion/range/slides`, `motion/range` alone, or a part's `motion/slides`. */
|
|
32
|
+
readonly route: string;
|
|
33
|
+
/** The id of the deck's page: `motion.range.slides`, the lesson's id alone, or a part's `motion.slides`. */
|
|
34
|
+
readonly pageId: string;
|
|
35
|
+
/** The part directory the deck sits in: `motion`; empty for a deck outside one. */
|
|
36
|
+
readonly partDir: string;
|
|
37
|
+
/** True when the deck sits in a part's directory, as a lesson does. */
|
|
38
|
+
readonly inPart: boolean;
|
|
39
|
+
/** The deck file's frontmatter. */
|
|
40
|
+
readonly data: Record<string, unknown>;
|
|
41
|
+
readonly body: string;
|
|
42
|
+
/** 1-based file line {@link body} starts on. */
|
|
43
|
+
readonly bodyLine: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A lesson's deck (`<lesson>.deck.mdx`): its slide edition, beside the
|
|
47
|
+
* lesson's chapter or, for a lesson that is only slides, alone. See
|
|
48
|
+
* `docs/authoring/deck.md`.
|
|
49
|
+
*/
|
|
50
|
+
interface LessonDeckFile extends DeckFileBase {
|
|
51
|
+
readonly scope: 'lesson';
|
|
52
|
+
/** The lesson's slug: `motion/range`. */
|
|
53
|
+
readonly lessonSlug: string;
|
|
54
|
+
readonly lessonId: string;
|
|
55
|
+
/** The lesson's chapter file, when it has one. */
|
|
56
|
+
readonly chapterPath?: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A part's deck (`<part>/index.deck.mdx`, beside the part's page): the
|
|
60
|
+
* slides of the part, whose sections may name the chapters they cover. It
|
|
61
|
+
* belongs to no lesson.
|
|
62
|
+
*/
|
|
63
|
+
interface PartDeckFile extends DeckFileBase {
|
|
64
|
+
readonly scope: 'part';
|
|
65
|
+
}
|
|
66
|
+
/** A deck file: a lesson's slide edition, or a part's deck. */
|
|
67
|
+
type DeckFile = LessonDeckFile | PartDeckFile;
|
|
68
|
+
/**
|
|
69
|
+
* Every deck file, by slug: each lesson's, and each part's. A part's deck
|
|
70
|
+
* (`<part>/index.deck.mdx`) is never read as the deck of a lesson
|
|
71
|
+
* `<part>/index` whose chapter is the part's page.
|
|
72
|
+
*/
|
|
73
|
+
declare function loadDeckFiles(): DeckFile[];
|
|
74
|
+
/**
|
|
75
|
+
* A file that defines a lesson: every chapter, and every deck whose lesson has
|
|
76
|
+
* no chapter (a slides-first lesson). Its frontmatter is the lesson's —
|
|
77
|
+
* `teaches`, `assumptions`, `studyMinutes`, `notation` — and its body is what
|
|
78
|
+
* the lesson's numbering and curriculum passes read.
|
|
79
|
+
*/
|
|
80
|
+
interface LessonFile {
|
|
81
|
+
readonly path: string;
|
|
82
|
+
/** Docs slug of the file, extension included. */
|
|
83
|
+
readonly slug: string;
|
|
84
|
+
readonly lessonSlug: string;
|
|
85
|
+
readonly lessonId: string;
|
|
86
|
+
readonly edition: 'chapter' | 'deck';
|
|
87
|
+
}
|
|
88
|
+
/** Every lesson's defining file, sorted by lesson slug. */
|
|
89
|
+
declare function loadLessonFiles(): LessonFile[];
|
|
23
90
|
/**
|
|
24
91
|
* One part's **overview page** — `content/docs/<dir>/index.mdx`, the page the
|
|
25
92
|
* part's own directory URL resolves to. `isLessonSlug` already excludes any
|
|
@@ -55,6 +122,26 @@ declare function loadAbbreviationRegistryInput(): Promise<readonly AbbreviationD
|
|
|
55
122
|
* decoration (the page would contradict itself) each fail the load.
|
|
56
123
|
*/
|
|
57
124
|
declare function notationSuspensions(raw: unknown, localDefinitions: readonly LocalNotationDefinitionInput[], file: string): NotationSuspension[];
|
|
125
|
+
/**
|
|
126
|
+
* A deck beside its chapter, as a page of the notation registry: its own id
|
|
127
|
+
* (`<lessonId>.slides`), no entries of its own, and its chapter's scope — the
|
|
128
|
+
* chapter's `notation.local` entries are the lesson's, so a deck names them
|
|
129
|
+
* as the chapter does, and it suspends what the chapter suspends. A part's
|
|
130
|
+
* deck (`<part>.slides`) has its part's scope: every chapter of the part, in
|
|
131
|
+
* the order the tracks read them, a key one chapter defines locally binding
|
|
132
|
+
* to the first that does; it suspends what any of them suspends. A deck that
|
|
133
|
+
* is a lesson's only edition is not here: it is that lesson's page
|
|
134
|
+
* (`loadNotationRegistryInput`).
|
|
135
|
+
*/
|
|
136
|
+
interface DeckNotationPage {
|
|
137
|
+
readonly deck: DeckFile;
|
|
138
|
+
readonly data: Record<string, unknown>;
|
|
139
|
+
readonly notation: NotationLessonInput;
|
|
140
|
+
}
|
|
141
|
+
declare function loadDeckNotationPages(decks?: readonly DeckFile[], { order, }?: {
|
|
142
|
+
/** The lessons of a part in reading order (the tracks'); by slug without it. */
|
|
143
|
+
readonly order?: (lessonIds: readonly string[]) => readonly string[];
|
|
144
|
+
}): DeckNotationPage[];
|
|
58
145
|
/**
|
|
59
146
|
* A docs page that is **not a chapter** (rule S10): the landing page, a part's
|
|
60
147
|
* overview page, and any other page outside a part directory — every slug
|
|
@@ -132,4 +219,4 @@ declare function notationSourceLocatorGaps(): {
|
|
|
132
219
|
total: number;
|
|
133
220
|
};
|
|
134
221
|
|
|
135
|
-
export { type NonChapterPage, type NotationSpec, type PartOverviewPage, extractNotationReferences, loadAbbreviationRegistryInput, loadContentRecords, loadCurriculumCatalog, loadLessonChecks, loadNonChapterPages, loadNotationDefinitions, loadNotationRegistryInput, loadNotationSpecs, loadPartOverviews, loadSourceRecords, notationSourceLocatorGaps, notationSuspensions };
|
|
222
|
+
export { type DeckFile, type DeckNotationPage, type LessonDeckFile, type LessonFile, type NonChapterPage, type NotationSpec, type PartDeckFile, type PartOverviewPage, extractNotationReferences, loadAbbreviationRegistryInput, loadContentRecords, loadCurriculumCatalog, loadDeckFiles, loadDeckNotationPages, loadLessonChecks, loadLessonFiles, loadNonChapterPages, loadNotationDefinitions, loadNotationRegistryInput, loadNotationSpecs, loadPartOverviews, loadSourceRecords, notationSourceLocatorGaps, notationSuspensions };
|
|
@@ -16,11 +16,19 @@ import { resolveGlosses } from "../reference/gloss.js";
|
|
|
16
16
|
import { indexEntryFormula } from "../reference/derived-notation.mjs";
|
|
17
17
|
import { isIndexEntryLatex } from "./content-schemas.js";
|
|
18
18
|
import {
|
|
19
|
+
deckLessonSlug,
|
|
20
|
+
deckPageId,
|
|
21
|
+
deckRouteSlug,
|
|
19
22
|
deriveRequires,
|
|
20
23
|
deriveSources,
|
|
24
|
+
isDeckSlug,
|
|
21
25
|
isLessonSlug,
|
|
26
|
+
isPartDeckSlug,
|
|
22
27
|
lessonIdFromSlug,
|
|
23
|
-
parseCheckList
|
|
28
|
+
parseCheckList,
|
|
29
|
+
partDeckDir,
|
|
30
|
+
partDeckPageId,
|
|
31
|
+
partDeckRouteSlug
|
|
24
32
|
} from "./lesson-derivation.js";
|
|
25
33
|
const REPOSITORY_ROOT = process.cwd();
|
|
26
34
|
const CONTENT_ROOT = join(REPOSITORY_ROOT, "content");
|
|
@@ -186,9 +194,81 @@ function docSlug(path) {
|
|
|
186
194
|
return relative(join(CONTENT_ROOT, "docs"), path).replace(/\\/g, "/");
|
|
187
195
|
}
|
|
188
196
|
function lessonCheckIds(lessonPath) {
|
|
189
|
-
const checksPath = lessonPath.replace(
|
|
197
|
+
const checksPath = lessonPath.replace(/(?:\.deck)?\.mdx?$/, ".checks.yml");
|
|
190
198
|
return existsSync(checksPath) ? parseCheckList(readFileSync(checksPath, "utf8")) : [];
|
|
191
199
|
}
|
|
200
|
+
function docsFiles() {
|
|
201
|
+
const root = join(CONTENT_ROOT, "docs");
|
|
202
|
+
return existsSync(root) ? filesBelow(root, [".md", ".mdx"]) : [];
|
|
203
|
+
}
|
|
204
|
+
function chapterPathOf(lessonSlug) {
|
|
205
|
+
for (const extension of [".mdx", ".md"]) {
|
|
206
|
+
const path = join(CONTENT_ROOT, "docs", `${lessonSlug}${extension}`);
|
|
207
|
+
if (existsSync(path)) return path;
|
|
208
|
+
}
|
|
209
|
+
return void 0;
|
|
210
|
+
}
|
|
211
|
+
function loadDeckFiles() {
|
|
212
|
+
const decks = [];
|
|
213
|
+
for (const path of docsFiles()) {
|
|
214
|
+
const slug = docSlug(path);
|
|
215
|
+
if (!isDeckSlug(slug)) continue;
|
|
216
|
+
const { file, data, body, bodyLine } = parseDocument(path);
|
|
217
|
+
if (isPartDeckSlug(slug)) {
|
|
218
|
+
const partDir = partDeckDir(slug);
|
|
219
|
+
decks.push({
|
|
220
|
+
scope: "part",
|
|
221
|
+
path,
|
|
222
|
+
file,
|
|
223
|
+
slug,
|
|
224
|
+
route: partDeckRouteSlug(partDir),
|
|
225
|
+
pageId: partDeckPageId(partDir),
|
|
226
|
+
partDir,
|
|
227
|
+
inPart: true,
|
|
228
|
+
data,
|
|
229
|
+
body,
|
|
230
|
+
bodyLine
|
|
231
|
+
});
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
const lessonSlug = deckLessonSlug(slug);
|
|
235
|
+
const lessonId = lessonIdFromSlug(lessonSlug);
|
|
236
|
+
const chapterPath = chapterPathOf(lessonSlug);
|
|
237
|
+
const hasChapter = chapterPath !== void 0;
|
|
238
|
+
decks.push({
|
|
239
|
+
scope: "lesson",
|
|
240
|
+
path,
|
|
241
|
+
file,
|
|
242
|
+
slug,
|
|
243
|
+
lessonSlug,
|
|
244
|
+
lessonId,
|
|
245
|
+
...chapterPath === void 0 ? {} : { chapterPath },
|
|
246
|
+
route: deckRouteSlug(lessonSlug, hasChapter),
|
|
247
|
+
pageId: deckPageId(lessonId, hasChapter),
|
|
248
|
+
partDir: lessonSlug.includes("/") ? lessonSlug.slice(0, lessonSlug.indexOf("/")) : "",
|
|
249
|
+
inPart: lessonSlug.includes("/") && !lessonSlug.endsWith("/index"),
|
|
250
|
+
data,
|
|
251
|
+
body,
|
|
252
|
+
bodyLine
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
return decks;
|
|
256
|
+
}
|
|
257
|
+
function loadLessonFiles() {
|
|
258
|
+
const lessons = [];
|
|
259
|
+
for (const path of docsFiles()) {
|
|
260
|
+
const slug = docSlug(path);
|
|
261
|
+
if (isLessonSlug(slug)) {
|
|
262
|
+
const lessonSlug = slug.replace(/\.(md|mdx)$/, "");
|
|
263
|
+
lessons.push({ path, slug, lessonSlug, lessonId: lessonIdFromSlug(slug), edition: "chapter" });
|
|
264
|
+
} else if (isDeckSlug(slug) && slug.includes("/") && !isPartDeckSlug(slug)) {
|
|
265
|
+
const lessonSlug = deckLessonSlug(slug);
|
|
266
|
+
if (chapterPathOf(lessonSlug) !== void 0) continue;
|
|
267
|
+
lessons.push({ path, slug, lessonSlug, lessonId: lessonIdFromSlug(lessonSlug), edition: "deck" });
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return lessons.sort((left, right) => left.lessonSlug.localeCompare(right.lessonSlug));
|
|
271
|
+
}
|
|
192
272
|
function loadPartOverviews(parts) {
|
|
193
273
|
const pages = [];
|
|
194
274
|
for (const { dir } of parts) {
|
|
@@ -214,17 +294,19 @@ function loadPartOverviews(parts) {
|
|
|
214
294
|
}
|
|
215
295
|
function lessonEntries(prerequisitesById) {
|
|
216
296
|
const lessons = [];
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
297
|
+
const deckBodies = new Map(
|
|
298
|
+
loadDeckFiles().filter((deck) => deck.scope === "lesson" && deck.chapterPath !== void 0).map((deck) => [deck.lessonId, parseDocument(deck.path).body])
|
|
299
|
+
);
|
|
300
|
+
for (const { path, lessonId } of loadLessonFiles()) {
|
|
220
301
|
const { data, body } = parseDocument(path);
|
|
221
302
|
const teaches = data.teaches ?? [];
|
|
303
|
+
const deckBody = deckBodies.get(lessonId);
|
|
222
304
|
lessons.push({
|
|
223
|
-
id:
|
|
305
|
+
id: lessonId,
|
|
224
306
|
requires: deriveRequires(teaches, prerequisitesById),
|
|
225
307
|
teaches,
|
|
226
308
|
assessments: lessonCheckIds(path),
|
|
227
|
-
sources: deriveSources(body),
|
|
309
|
+
sources: deckBody === void 0 ? deriveSources(body) : [.../* @__PURE__ */ new Set([...deriveSources(body), ...deriveSources(deckBody)])].sort(),
|
|
228
310
|
assumptions: data.assumptions ?? [],
|
|
229
311
|
body
|
|
230
312
|
});
|
|
@@ -317,7 +399,7 @@ function localDefinition(raw, file, index) {
|
|
|
317
399
|
function sharedNotationEntries() {
|
|
318
400
|
const directory = join(CONTENT_ROOT, "notation");
|
|
319
401
|
return filesBelow(directory, [".md"]).map((path) => {
|
|
320
|
-
const { file, data, body } = parseDocument(path);
|
|
402
|
+
const { file, data, body, bodyLine } = parseDocument(path);
|
|
321
403
|
const key = string(data.key, `${file} key`);
|
|
322
404
|
const filenameKey = basename(path, ".md");
|
|
323
405
|
if (key !== filenameKey) {
|
|
@@ -339,6 +421,7 @@ function sharedNotationEntries() {
|
|
|
339
421
|
alignment: data.alignment === void 0 ? { kind: "general", rationale: "General notation." } : alignment(data.alignment, `${file} alignment`),
|
|
340
422
|
aiAssisted: data.aiAssisted === void 0 ? false : boolean(data.aiAssisted, `${file} aiAssisted`),
|
|
341
423
|
body,
|
|
424
|
+
bodyLine,
|
|
342
425
|
references: extractNotationReferences(body, file, void 0),
|
|
343
426
|
glosses: glossEntries(data.glosses, key, `${file} glosses`),
|
|
344
427
|
source: { file },
|
|
@@ -403,21 +486,26 @@ function notationSuspensions(raw, localDefinitions, file) {
|
|
|
403
486
|
return reason === void 0 ? { operator } : { operator, reason: reason.trim() };
|
|
404
487
|
});
|
|
405
488
|
}
|
|
489
|
+
function lessonNotationOf(file, data) {
|
|
490
|
+
const notation = record(data.notation ?? {}, `${file} notation`);
|
|
491
|
+
const local = Array.isArray(notation.local) ? notation.local : [];
|
|
492
|
+
const localDefinitions = local.map(
|
|
493
|
+
(entry, index) => localDefinition(entry, file, index)
|
|
494
|
+
);
|
|
495
|
+
return {
|
|
496
|
+
localDefinitions,
|
|
497
|
+
suspended: notationSuspensions(notation.suspend, localDefinitions, file)
|
|
498
|
+
};
|
|
499
|
+
}
|
|
406
500
|
function notationLessonEntries() {
|
|
407
501
|
const lessons = [];
|
|
408
|
-
for (const path of
|
|
409
|
-
const slug = docSlug(path);
|
|
410
|
-
if (!isLessonSlug(slug)) continue;
|
|
502
|
+
for (const { path, lessonId } of loadLessonFiles()) {
|
|
411
503
|
const { file, data, body, bodyLine } = parseDocument(path);
|
|
412
|
-
const
|
|
413
|
-
const local = Array.isArray(notation.local) ? notation.local : [];
|
|
414
|
-
const localDefinitions = local.map(
|
|
415
|
-
(entry, index) => localDefinition(entry, file, index)
|
|
416
|
-
);
|
|
504
|
+
const { localDefinitions, suspended } = lessonNotationOf(file, data);
|
|
417
505
|
lessons.push({
|
|
418
|
-
lessonId
|
|
506
|
+
lessonId,
|
|
419
507
|
localDefinitions,
|
|
420
|
-
suspended
|
|
508
|
+
suspended,
|
|
421
509
|
references: extractNotationReferences(body, file, void 0),
|
|
422
510
|
body,
|
|
423
511
|
bodyLine,
|
|
@@ -426,11 +514,68 @@ function notationLessonEntries() {
|
|
|
426
514
|
}
|
|
427
515
|
return lessons;
|
|
428
516
|
}
|
|
517
|
+
function loadDeckNotationPages(decks = loadDeckFiles(), {
|
|
518
|
+
order = (lessonIds) => lessonIds
|
|
519
|
+
} = {}) {
|
|
520
|
+
const pages = [];
|
|
521
|
+
const chapterFiles = loadLessonFiles().filter((lesson) => lesson.edition === "chapter");
|
|
522
|
+
for (const deck of decks) {
|
|
523
|
+
let chapters;
|
|
524
|
+
if (deck.scope === "part") {
|
|
525
|
+
const inPart = chapterFiles.filter((lesson) => lesson.lessonSlug.startsWith(`${deck.partDir}/`));
|
|
526
|
+
const pathById = new Map(inPart.map((lesson) => [lesson.lessonId, lesson.path]));
|
|
527
|
+
chapters = order(inPart.map((lesson) => lesson.lessonId)).flatMap((lessonId) => {
|
|
528
|
+
const path = pathById.get(lessonId);
|
|
529
|
+
return path === void 0 ? [] : [{ lessonId, path }];
|
|
530
|
+
});
|
|
531
|
+
} else if (deck.chapterPath !== void 0) {
|
|
532
|
+
chapters = [{ lessonId: deck.lessonId, path: deck.chapterPath }];
|
|
533
|
+
} else {
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
536
|
+
const inheritedLocalDefinitions = [];
|
|
537
|
+
const suspended = [];
|
|
538
|
+
const inheritedKeys = /* @__PURE__ */ new Set();
|
|
539
|
+
for (const { path } of chapters) {
|
|
540
|
+
const chapter = parseDocument(path);
|
|
541
|
+
const notation = lessonNotationOf(chapter.file, chapter.data);
|
|
542
|
+
for (const definition of notation.localDefinitions) {
|
|
543
|
+
if (!inheritedLocalDefinitions.some((known) => known.key === definition.key)) {
|
|
544
|
+
inheritedLocalDefinitions.push(definition);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
for (const suspension of notation.suspended) {
|
|
548
|
+
if (!suspended.some((known) => known.operator === suspension.operator)) suspended.push(suspension);
|
|
549
|
+
}
|
|
550
|
+
for (const reference of extractNotationReferences(chapter.body, chapter.file, void 0)) {
|
|
551
|
+
inheritedKeys.add(reference.key);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
const { file, data, body, bodyLine } = deck;
|
|
555
|
+
pages.push({
|
|
556
|
+
deck,
|
|
557
|
+
data,
|
|
558
|
+
notation: {
|
|
559
|
+
lessonId: deck.pageId,
|
|
560
|
+
localDefinitions: [],
|
|
561
|
+
suspended,
|
|
562
|
+
scopeLessonIds: chapters.map((chapter) => chapter.lessonId),
|
|
563
|
+
inheritedLocalDefinitions,
|
|
564
|
+
inheritedKeys: [...inheritedKeys].sort(),
|
|
565
|
+
references: extractNotationReferences(body, file, void 0),
|
|
566
|
+
body,
|
|
567
|
+
bodyLine,
|
|
568
|
+
source: { file }
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
return pages;
|
|
573
|
+
}
|
|
429
574
|
function loadNonChapterPages() {
|
|
430
575
|
const pages = [];
|
|
431
|
-
for (const path of
|
|
576
|
+
for (const path of docsFiles()) {
|
|
432
577
|
const slug = docSlug(path);
|
|
433
|
-
if (isLessonSlug(slug)) continue;
|
|
578
|
+
if (isLessonSlug(slug) || isDeckSlug(slug)) continue;
|
|
434
579
|
const { file, data, body, bodyLine } = parseDocument(path);
|
|
435
580
|
const id = lessonIdFromSlug(slug);
|
|
436
581
|
pages.push({
|
|
@@ -500,7 +645,7 @@ function loadSourceRecords() {
|
|
|
500
645
|
}
|
|
501
646
|
function loadLessonChecks(lessonId) {
|
|
502
647
|
const slug = lessonId.replace(/\./g, "/");
|
|
503
|
-
for (const extension of [".mdx", ".md"]) {
|
|
648
|
+
for (const extension of [".mdx", ".md", ".deck.mdx", ".deck.md"]) {
|
|
504
649
|
const lessonPath = join(CONTENT_ROOT, "docs", `${slug}${extension}`);
|
|
505
650
|
if (existsSync(lessonPath)) return lessonCheckIds(lessonPath);
|
|
506
651
|
}
|
|
@@ -534,11 +679,8 @@ function loadNotationSpecs() {
|
|
|
534
679
|
sources: specSources(data.sources)
|
|
535
680
|
});
|
|
536
681
|
}
|
|
537
|
-
for (const path of
|
|
538
|
-
const slug = docSlug(path);
|
|
539
|
-
if (!isLessonSlug(slug)) continue;
|
|
682
|
+
for (const { path, lessonId } of loadLessonFiles()) {
|
|
540
683
|
const { file, data } = parseDocument(path);
|
|
541
|
-
const lessonId = lessonIdFromSlug(slug);
|
|
542
684
|
const local = data.notation?.local;
|
|
543
685
|
if (!Array.isArray(local)) continue;
|
|
544
686
|
for (const raw of local) {
|
|
@@ -576,7 +718,10 @@ export {
|
|
|
576
718
|
loadAbbreviationRegistryInput,
|
|
577
719
|
loadContentRecords,
|
|
578
720
|
loadCurriculumCatalog,
|
|
721
|
+
loadDeckFiles,
|
|
722
|
+
loadDeckNotationPages,
|
|
579
723
|
loadLessonChecks,
|
|
724
|
+
loadLessonFiles,
|
|
580
725
|
loadNonChapterPages,
|
|
581
726
|
loadNotationDefinitions,
|
|
582
727
|
loadNotationRegistryInput,
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { EditPlan } from './cli.js';
|
|
2
|
+
import '../reference/types.js';
|
|
3
|
+
import '../reference/gate-math.js';
|
|
4
|
+
import './manifest.js';
|
|
5
|
+
import '../curriculum/validation.js';
|
|
6
|
+
import '../reference/consistency.js';
|
|
7
|
+
import '../course-config-BLtIdkei.js';
|
|
8
|
+
import '../rules/catalog.js';
|
|
9
|
+
import '../rules/course-rules.js';
|
|
10
|
+
import './collections.js';
|
|
11
|
+
import '../reference/gate-retired-keys.js';
|
|
12
|
+
import '../reference/lint-ignore.js';
|
|
13
|
+
import '../reference/equations-validate.js';
|
|
14
|
+
import '../reference/tables-validate.js';
|
|
15
|
+
import '../reference/keyed-float-validate.js';
|
|
16
|
+
import '../reference/figures-validate.js';
|
|
17
|
+
import '../reference/diagrams-validate.js';
|
|
18
|
+
import '../reference/examples-validate.js';
|
|
19
|
+
import '../reference/folds-validate.js';
|
|
20
|
+
import '../reference/knowledge-checks-validate.js';
|
|
21
|
+
import '../reference/raw-floats-validate.js';
|
|
22
|
+
import '../reference/lab-katex-validate.js';
|
|
23
|
+
import '../reference/mixed-content.js';
|
|
24
|
+
import '../reference/gloss.js';
|
|
25
|
+
import '../rules/waivers.js';
|
|
26
|
+
import './knowledge-version.js';
|
|
27
|
+
import './page-versions.js';
|
|
28
|
+
import './decks.js';
|
|
29
|
+
import '../reference/decks-validate.js';
|
|
30
|
+
import '../reference/deck-source.js';
|
|
31
|
+
import './lesson-derivation.js';
|
|
32
|
+
import './render-diagnostics.js';
|
|
33
|
+
import '../rules/in-effect.js';
|
|
34
|
+
|
|
35
|
+
type ReleaseBump = 'major' | 'minor' | 'patch';
|
|
36
|
+
interface ReleaseEdit {
|
|
37
|
+
readonly from: string;
|
|
38
|
+
readonly to: string;
|
|
39
|
+
readonly bump: ReleaseBump;
|
|
40
|
+
/** True when the bump was read from the section's headings, not asked for. */
|
|
41
|
+
readonly inferred: boolean;
|
|
42
|
+
readonly changelog: string;
|
|
43
|
+
readonly config: string;
|
|
44
|
+
}
|
|
45
|
+
/** The release of these two files' text on `date` (`YYYY-MM-DD`); `null` when `[Unreleased]` has no entry. */
|
|
46
|
+
declare function releaseEdit(changelog: string, config: string, date: string, requested?: ReleaseBump): ReleaseEdit | null;
|
|
47
|
+
declare function planContentRelease(requested?: string, date?: string): EditPlan;
|
|
48
|
+
|
|
49
|
+
export { type ReleaseBump, type ReleaseEdit, planContentRelease, releaseEdit };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { ContentCliError } from "./cli.js";
|
|
4
|
+
const CHANGELOG = "content/CHANGELOG.md";
|
|
5
|
+
const CONFIG = "content/course.config.ts";
|
|
6
|
+
function releaseEdit(changelog, config, date, requested) {
|
|
7
|
+
const unreleased = /^## \[Unreleased\]\r?$/m.exec(changelog);
|
|
8
|
+
if (!unreleased) throw new ContentCliError("no-changelog", `${CHANGELOG} has no "## [Unreleased]" heading.`);
|
|
9
|
+
const bodyStart = unreleased.index + unreleased[0].length;
|
|
10
|
+
const released = /^## \[\d+\.\d+\.\d+\](?: - .*?)?\r?$/m.exec(changelog.slice(bodyStart));
|
|
11
|
+
if (!released) throw new ContentCliError("no-changelog", `${CHANGELOG} has no released "## [x.y.z]" heading below "## [Unreleased]".`);
|
|
12
|
+
const bodyEnd = bodyStart + released.index;
|
|
13
|
+
const body = changelog.slice(bodyStart, bodyEnd);
|
|
14
|
+
if (!/^-\s+/m.test(body)) return null;
|
|
15
|
+
const version = /(about:\s*\{[\s\S]*?\bversion:\s*['"])(\d+)\.(\d+)\.(\d+)(['"])/.exec(config);
|
|
16
|
+
if (!version) throw new ContentCliError("unknown-version", `No about.version "x.y.z" in ${CONFIG}.`);
|
|
17
|
+
const [major, minor, patch] = version.slice(2, 5).map(Number);
|
|
18
|
+
const implied = /^### (Breaking|Removed)\s*$/m.test(body) ? "major" : /^### Added\s*$/m.test(body) ? "minor" : "patch";
|
|
19
|
+
const bump = requested ?? implied;
|
|
20
|
+
const to = bump === "major" ? `${major + 1}.0.0` : bump === "minor" ? `${major}.${minor + 1}.0` : `${major}.${minor}.${patch + 1}`;
|
|
21
|
+
return {
|
|
22
|
+
from: `${major}.${minor}.${patch}`,
|
|
23
|
+
to,
|
|
24
|
+
bump,
|
|
25
|
+
inferred: requested === void 0,
|
|
26
|
+
changelog: `${changelog.slice(0, bodyStart)}
|
|
27
|
+
|
|
28
|
+
## [${to}] - ${date}${body}${changelog.slice(bodyEnd)}`,
|
|
29
|
+
config: config.replace(version[0], `${version[1]}${to}${version[5]}`)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function localDate(now = /* @__PURE__ */ new Date()) {
|
|
33
|
+
return [now.getFullYear(), now.getMonth() + 1, now.getDate()].map((n, i) => String(n).padStart(i === 0 ? 4 : 2, "0")).join("-");
|
|
34
|
+
}
|
|
35
|
+
function planContentRelease(requested, date = localDate()) {
|
|
36
|
+
if (requested !== void 0 && requested !== "major" && requested !== "minor" && requested !== "patch") {
|
|
37
|
+
throw new ContentCliError("usage", `content release takes major, minor or patch; got ${requested}.`);
|
|
38
|
+
}
|
|
39
|
+
for (const file of [CHANGELOG, CONFIG]) {
|
|
40
|
+
if (!existsSync(join(process.cwd(), file))) throw new ContentCliError("no-changelog", `No ${file} in this course.`);
|
|
41
|
+
}
|
|
42
|
+
const changelog = readFileSync(join(process.cwd(), CHANGELOG), "utf8");
|
|
43
|
+
const config = readFileSync(join(process.cwd(), CONFIG), "utf8");
|
|
44
|
+
const edit = releaseEdit(changelog, config, date, requested);
|
|
45
|
+
if (edit === null) {
|
|
46
|
+
return { summary: ["## [Unreleased] has no entries: nothing to release"], edits: [], next: [] };
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
summary: [
|
|
50
|
+
`about.version ${edit.from} \u2192 ${edit.to} (${edit.bump}${edit.inferred ? ", from the section's headings" : ""})`,
|
|
51
|
+
`${CHANGELOG}: ## [Unreleased] \u2192 ## [${edit.to}] - ${date}, a fresh ## [Unreleased] above it`
|
|
52
|
+
],
|
|
53
|
+
edits: [
|
|
54
|
+
{ file: CHANGELOG, before: changelog, after: edit.changelog },
|
|
55
|
+
{ file: CONFIG, before: config, after: edit.config }
|
|
56
|
+
],
|
|
57
|
+
next: ["pnpm validate:content (records the release in content/versions.json)", "commit the changelog, the config and content/versions.json together"]
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export {
|
|
61
|
+
planContentRelease,
|
|
62
|
+
releaseEdit
|
|
63
|
+
};
|
|
@@ -178,9 +178,9 @@ declare const trackSchema: z.ZodObject<{
|
|
|
178
178
|
declare const sourceSchema: z.ZodObject<{
|
|
179
179
|
id: z.ZodString;
|
|
180
180
|
type: z.ZodEnum<{
|
|
181
|
+
paper: "paper";
|
|
181
182
|
primary: "primary";
|
|
182
183
|
"official-guidance": "official-guidance";
|
|
183
|
-
paper: "paper";
|
|
184
184
|
book: "book";
|
|
185
185
|
secondary: "secondary";
|
|
186
186
|
}>;
|
|
@@ -359,9 +359,9 @@ declare const CONTENT_SCHEMAS: {
|
|
|
359
359
|
readonly sources: z.ZodObject<{
|
|
360
360
|
id: z.ZodString;
|
|
361
361
|
type: z.ZodEnum<{
|
|
362
|
+
paper: "paper";
|
|
362
363
|
primary: "primary";
|
|
363
364
|
"official-guidance": "official-guidance";
|
|
364
|
-
paper: "paper";
|
|
365
365
|
book: "book";
|
|
366
366
|
secondary: "secondary";
|
|
367
367
|
}>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { A as APPEARANCE_DEFAULTS, x as AppearanceSlides, y as AppearanceZones, z as BLOCK_LABELS_DEFAULT, B as BlockLabels, D as CARDS_DEFAULTS, l as CourseAbbreviations, E as CourseAbout, k as CourseAccents, F as CourseAppearance, G as CourseAuthor, H as CourseCards, C as CourseConfig, I as CourseDeck, J as CourseDisclosure, K as CourseHeadingDisclosure, L as CourseNumbering, O as CourseOpenDefault, i as CourseOperators, P as CoursePart, j as CourseRomanLabels, Q as CourseSection, S as CourseSidebarEditions, T as CourseSidebarMarks, U as DECK_CANVAS, V as DECK_DEFAULTS, W as DISCLOSURE_DEFAULTS, X as DeckAspectRatio, Y as DeckLegend, Z as DeckNotes, _ as LessonExportsConfig, f as NormalizedAppearance, c as NormalizedCards, g as NormalizedDeck, a as NormalizedDisclosure, N as NormalizedLessonExports, b as NormalizedNumbering, m as NormalizedPartPages, e as NormalizedSidebarEditions, d as NormalizedSidebarMarks, R as ReadingMemorySetting, $ as SIDEBAR_EDITIONS_DEFAULTS, a0 as SIDEBAR_MARKS_DEFAULTS, a1 as SidebarEditionLead, a2 as SidebarEditionOther, a3 as coursePartsOf, a4 as normalizeAppearance, a5 as normalizeBlockLabels, a6 as normalizeCards, a7 as normalizeDeck, a8 as normalizeDisclosure, a9 as normalizeLessonExports, aa as normalizeNumbering, ab as normalizeReadingMemory, ac as normalizeSidebarEditions, ad as normalizeSidebarMarks } from '../course-config-BLtIdkei.js';
|
|
2
2
|
import '../rules/course-rules.js';
|
|
3
3
|
import '../rules/catalog.js';
|
|
@@ -83,6 +83,100 @@ function normalizeCards(config) {
|
|
|
83
83
|
}
|
|
84
84
|
return { carry };
|
|
85
85
|
}
|
|
86
|
+
const SIDEBAR_MARKS_DEFAULTS = { unopened: true, changed: true };
|
|
87
|
+
function normalizeSidebarMarks(config) {
|
|
88
|
+
const marks = config.sidebarMarks ?? {};
|
|
89
|
+
const read = (field) => {
|
|
90
|
+
const value = marks[field] ?? SIDEBAR_MARKS_DEFAULTS[field];
|
|
91
|
+
if (typeof value !== "boolean") {
|
|
92
|
+
throw new Error(
|
|
93
|
+
`CourseConfig sidebarMarks.${field} must be true or false; received ${JSON.stringify(value)}.`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
return value;
|
|
97
|
+
};
|
|
98
|
+
return { unopened: read("unopened"), changed: read("changed") };
|
|
99
|
+
}
|
|
100
|
+
const SIDEBAR_EDITIONS_DEFAULTS = { lead: "chapter", other: "listed" };
|
|
101
|
+
function normalizeSidebarEditions(config) {
|
|
102
|
+
const editions = config.sidebarEditions ?? {};
|
|
103
|
+
const choice = (field, allowed) => {
|
|
104
|
+
const value = editions[field] ?? SIDEBAR_EDITIONS_DEFAULTS[field];
|
|
105
|
+
if (typeof value !== "string" || !allowed.includes(value)) {
|
|
106
|
+
throw new Error(
|
|
107
|
+
`CourseConfig sidebarEditions.${field} must be one of ${allowed.map((item) => JSON.stringify(item)).join(", ")}; received ${JSON.stringify(value)}.`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
return value;
|
|
111
|
+
};
|
|
112
|
+
return {
|
|
113
|
+
lead: choice("lead", ["chapter", "slides"]),
|
|
114
|
+
other: choice("other", ["listed", "hidden"])
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const DECK_CANVAS = {
|
|
118
|
+
"16:9": { width: 800, height: 450 },
|
|
119
|
+
"16:10": { width: 720, height: 450 },
|
|
120
|
+
"4:3": { width: 600, height: 450 }
|
|
121
|
+
};
|
|
122
|
+
const DECK_DEFAULTS = {
|
|
123
|
+
aspectRatio: "16:9",
|
|
124
|
+
legend: "first-use",
|
|
125
|
+
notes: "reader",
|
|
126
|
+
outcomesFrame: true,
|
|
127
|
+
handoutPdf: true
|
|
128
|
+
};
|
|
129
|
+
function normalizeDeck(config) {
|
|
130
|
+
const deck = config.deck ?? {};
|
|
131
|
+
const choice = (field, allowed) => {
|
|
132
|
+
const value = deck[field] ?? DECK_DEFAULTS[field];
|
|
133
|
+
if (typeof value !== "string" || !allowed.includes(value)) {
|
|
134
|
+
throw new Error(
|
|
135
|
+
`CourseConfig deck.${field} must be one of ${allowed.map((item) => JSON.stringify(item)).join(", ")}; received ${JSON.stringify(value)}.`
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
return value;
|
|
139
|
+
};
|
|
140
|
+
const flag = (field) => {
|
|
141
|
+
const value = deck[field] ?? DECK_DEFAULTS[field];
|
|
142
|
+
if (typeof value !== "boolean") {
|
|
143
|
+
throw new Error(`CourseConfig deck.${field} must be true or false; received ${JSON.stringify(value)}.`);
|
|
144
|
+
}
|
|
145
|
+
return value;
|
|
146
|
+
};
|
|
147
|
+
const aspectRatio = choice("aspectRatio", ["16:9", "16:10", "4:3"]);
|
|
148
|
+
return {
|
|
149
|
+
aspectRatio,
|
|
150
|
+
legend: choice("legend", ["first-use", "every-frame", "off"]),
|
|
151
|
+
notes: choice("notes", ["reader", "presenter", "off"]),
|
|
152
|
+
outcomesFrame: flag("outcomesFrame"),
|
|
153
|
+
handoutPdf: flag("handoutPdf"),
|
|
154
|
+
canvas: DECK_CANVAS[aspectRatio]
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function normalizeReadingMemory(config) {
|
|
158
|
+
const value = config.readingMemory ?? "ask";
|
|
159
|
+
if (value !== "ask" && value !== "off") {
|
|
160
|
+
throw new Error(`CourseConfig readingMemory must be "ask" or "off"; received ${JSON.stringify(value)}.`);
|
|
161
|
+
}
|
|
162
|
+
return value;
|
|
163
|
+
}
|
|
164
|
+
const APPEARANCE_DEFAULTS = { zones: "tonal", slides: "lifted" };
|
|
165
|
+
const APPEARANCE_ZONES = ["tonal", "accent-header", "paper", "none"];
|
|
166
|
+
const APPEARANCE_SLIDES = ["lifted", "edge", "sorter"];
|
|
167
|
+
function normalizeAppearance(config) {
|
|
168
|
+
const appearance = config.appearance ?? {};
|
|
169
|
+
const choice = (field, allowed) => {
|
|
170
|
+
const value = appearance[field] ?? APPEARANCE_DEFAULTS[field];
|
|
171
|
+
if (!allowed.includes(value)) {
|
|
172
|
+
throw new Error(
|
|
173
|
+
`CourseConfig appearance.${field} must be one of ${allowed.map((v) => `"${v}"`).join(", ")}; received ${JSON.stringify(value)}.`
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
return value;
|
|
177
|
+
};
|
|
178
|
+
return { zones: choice("zones", APPEARANCE_ZONES), slides: choice("slides", APPEARANCE_SLIDES) };
|
|
179
|
+
}
|
|
86
180
|
function normalizeLessonExports(config) {
|
|
87
181
|
const standaloneHtml = config.lessonExports?.standaloneHtml === true;
|
|
88
182
|
const print = config.lessonExports?.print === true;
|
|
@@ -135,13 +229,23 @@ function coursePartsOf(config) {
|
|
|
135
229
|
return parts;
|
|
136
230
|
}
|
|
137
231
|
export {
|
|
232
|
+
APPEARANCE_DEFAULTS,
|
|
138
233
|
BLOCK_LABELS_DEFAULT,
|
|
139
234
|
CARDS_DEFAULTS,
|
|
235
|
+
DECK_CANVAS,
|
|
236
|
+
DECK_DEFAULTS,
|
|
140
237
|
DISCLOSURE_DEFAULTS,
|
|
238
|
+
SIDEBAR_EDITIONS_DEFAULTS,
|
|
239
|
+
SIDEBAR_MARKS_DEFAULTS,
|
|
141
240
|
coursePartsOf,
|
|
241
|
+
normalizeAppearance,
|
|
142
242
|
normalizeBlockLabels,
|
|
143
243
|
normalizeCards,
|
|
244
|
+
normalizeDeck,
|
|
144
245
|
normalizeDisclosure,
|
|
145
246
|
normalizeLessonExports,
|
|
146
|
-
normalizeNumbering
|
|
247
|
+
normalizeNumbering,
|
|
248
|
+
normalizeReadingMemory,
|
|
249
|
+
normalizeSidebarEditions,
|
|
250
|
+
normalizeSidebarMarks
|
|
147
251
|
};
|