explico 0.13.0 → 0.14.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 +894 -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 +43 -0
- package/dist/compiler/cli-main.js +392 -0
- package/dist/compiler/cli.d.ts +424 -9
- package/dist/compiler/cli.js +1289 -8
- package/dist/compiler/collections.d.ts +88 -1
- package/dist/compiler/collections.js +170 -25
- 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 +359 -58
- package/dist/compiler/page-versions.d.ts +160 -0
- package/dist/compiler/page-versions.js +198 -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 +76 -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 +1 -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 +221 -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 +30 -7
- package/dist/rules/rules.schema.json +259 -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 +29 -9
- package/docs/authoring/agents.md +63 -16
- package/docs/authoring/components.md +15 -0
- package/docs/authoring/deck.md +588 -0
- package/docs/authoring/migrating.md +1087 -14
- package/docs/authoring/notation.md +49 -6
- package/docs/authoring/structure.md +80 -1
- package/docs/authoring/versioning.md +54 -2
- package/docs/authoring/visualizations.md +7 -2
- package/docs/course-agent/AGENTS.md +37 -0
- package/docs/course-agent/agents/rules-reviewer.md +33 -0
- package/docs/course-agent/skills/draft-lesson/SKILL.md +37 -0
- package/docs/course-agent/skills/migrate-course/SKILL.md +31 -0
- package/docs/course-agent/skills/release-content/SKILL.md +24 -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 +469 -0
- package/src/compiler/cli.ts +1905 -16
- package/src/compiler/collections.ts +284 -25
- 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 +558 -63
- package/src/compiler/page-versions.ts +359 -0
- package/src/compiler/resolution-report.ts +38 -7
- package/src/compiler/validate-content.ts +212 -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 +29 -0
- 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 +126 -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-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 +257 -4
- package/src/rules/course-rules.ts +21 -1
- package/src/rules/in-effect.ts +54 -8
- 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
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { DeckFile } from './collections.js';
|
|
2
|
+
import { g as NormalizedDeck } from '../course-config-BLtIdkei.js';
|
|
3
|
+
import { DeckRuleSettings, ChapterFloats } from '../reference/decks-validate.js';
|
|
4
|
+
import { ScopeEntry, MathGateDiagnostic } from '../reference/gate-math.js';
|
|
5
|
+
import '../curriculum/validation.js';
|
|
6
|
+
import '../reference/types.js';
|
|
7
|
+
import '../reference/gate-retired-keys.js';
|
|
8
|
+
import '../rules/catalog.js';
|
|
9
|
+
import '../rules/course-rules.js';
|
|
10
|
+
import '../reference/deck-source.js';
|
|
11
|
+
|
|
12
|
+
/** One frame of a deck, in the order the deck shows it. */
|
|
13
|
+
interface ManifestDeckFrame {
|
|
14
|
+
/** 1-based: the generated title frame is 1. */
|
|
15
|
+
readonly number: number;
|
|
16
|
+
/**
|
|
17
|
+
* What the frame shows, as 12 hex digits of a SHA-256 (v35), as rule C5's
|
|
18
|
+
* hash names a page's content. A reader's record of the frames they saw
|
|
19
|
+
* keeps it, so a frame that changed since is told from one they never saw
|
|
20
|
+
* (`session/deck-memory.ts`). An authored frame hashes its source,
|
|
21
|
+
* notes included, and the chapter's number for each float it recalls; the
|
|
22
|
+
* title frame its title, course and authors, not its version, which every
|
|
23
|
+
* release moves; the outcomes frame its outcomes; the references frame the
|
|
24
|
+
* sources it cites. Another frame's change leaves it as it is.
|
|
25
|
+
*/
|
|
26
|
+
readonly id: string;
|
|
27
|
+
/**
|
|
28
|
+
* `title` and `outcomes` and `references` are generated; `section` is a
|
|
29
|
+
* `##` divider; `frame` is a `###` frame.
|
|
30
|
+
*/
|
|
31
|
+
readonly kind: 'title' | 'section' | 'frame' | 'outcomes' | 'references';
|
|
32
|
+
/** What the reader sees as its title. */
|
|
33
|
+
readonly title: string;
|
|
34
|
+
/** The heading's anchor (a section or a frame). */
|
|
35
|
+
readonly slug?: string;
|
|
36
|
+
/** A frame's section, by its anchor. */
|
|
37
|
+
readonly section?: string;
|
|
38
|
+
/** How many steps the frame shows in: one more than its `<Pause />` marks. */
|
|
39
|
+
readonly steps: number;
|
|
40
|
+
/** `### Title [morph]`: the frame morphs from the frame before it. */
|
|
41
|
+
readonly morph?: true;
|
|
42
|
+
/** The chapter floats the frame recalls, as written (`eq-range`, `fig-…`). */
|
|
43
|
+
readonly recalls?: readonly string[];
|
|
44
|
+
/** The frame carries speaker notes. */
|
|
45
|
+
readonly notes?: true;
|
|
46
|
+
/** The notation keys the frame shows for the first time in the deck — its legend line's first-use list. */
|
|
47
|
+
readonly symbols?: readonly string[];
|
|
48
|
+
/**
|
|
49
|
+
* On a part's deck, the chapter the frame's section covers (v36), by its
|
|
50
|
+
* lesson slug: on the section's divider and on each of its frames.
|
|
51
|
+
*/
|
|
52
|
+
readonly chapter?: string;
|
|
53
|
+
}
|
|
54
|
+
/** One deck, a lesson's or a part's, as the builder makes it (`ManifestDeck` adds its notation). */
|
|
55
|
+
interface BuiltDeck {
|
|
56
|
+
/** The lesson the deck is the slide edition of; a part's deck belongs to none (v36). */
|
|
57
|
+
readonly lessonId?: string;
|
|
58
|
+
/**
|
|
59
|
+
* The deck page's id: `<lessonId>.slides`, the lesson's own id when it has
|
|
60
|
+
* no chapter, or a part's `<part>.slides`.
|
|
61
|
+
*/
|
|
62
|
+
readonly pageId: string;
|
|
63
|
+
/** Its route: `<lesson>/slides`, the lesson's own for a slides-first lesson, or a part's `<part>/slides`. */
|
|
64
|
+
readonly slug: string;
|
|
65
|
+
readonly file: string;
|
|
66
|
+
readonly title: string;
|
|
67
|
+
readonly description: string;
|
|
68
|
+
/** The lesson's chapter slug, when the deck stands beside one. */
|
|
69
|
+
readonly chapter?: string;
|
|
70
|
+
/** A part's deck (`<part>/index.deck.mdx`, v36): the part's directory, `motion`. */
|
|
71
|
+
readonly part?: string;
|
|
72
|
+
/**
|
|
73
|
+
* Each chapter a part's deck covers, in deck order (v36): its lesson slug,
|
|
74
|
+
* and the number of the frame its section opens on, the divider — the
|
|
75
|
+
* chapter's address in the deck, `#slide-N`. Empty on a lesson's deck.
|
|
76
|
+
*/
|
|
77
|
+
readonly covers: readonly {
|
|
78
|
+
readonly chapter: string;
|
|
79
|
+
readonly frame: number;
|
|
80
|
+
}[];
|
|
81
|
+
/**
|
|
82
|
+
* A part's deck (v36): the chapter whose float each recall shows, by its
|
|
83
|
+
* ref (`eq-range` → `projectiles/projectile-range`), which its number
|
|
84
|
+
* links to. A lesson's deck recalls from its {@link chapter}.
|
|
85
|
+
*/
|
|
86
|
+
readonly recalledFrom?: Readonly<Record<string, string>>;
|
|
87
|
+
readonly frames: readonly ManifestDeckFrame[];
|
|
88
|
+
/** The deck's own labelled equations, numbered (1), (2)… in the deck (rule D8). */
|
|
89
|
+
readonly equations: readonly {
|
|
90
|
+
readonly key: string;
|
|
91
|
+
readonly number: string;
|
|
92
|
+
}[];
|
|
93
|
+
}
|
|
94
|
+
/** What the builder needs about each deck's lesson. */
|
|
95
|
+
interface DeckLessonFacts {
|
|
96
|
+
readonly title: string;
|
|
97
|
+
/** Competencies the lesson teaches; the outcomes frame lists their outcomes. */
|
|
98
|
+
readonly teaches: readonly string[];
|
|
99
|
+
/** Those outcomes, in order: what the outcomes frame shows. */
|
|
100
|
+
readonly outcomes?: readonly string[];
|
|
101
|
+
/** The chapter's numbered floats, by kind, key → number. Absent: no chapter. */
|
|
102
|
+
readonly chapterFloats?: ChapterFloats;
|
|
103
|
+
}
|
|
104
|
+
/** One chapter of a part, as a part's deck draws on it. */
|
|
105
|
+
interface DeckChapterFacts {
|
|
106
|
+
/** Its name in the part's directory, what `[chapter: <name>]` writes: `constant-acceleration`. */
|
|
107
|
+
readonly name: string;
|
|
108
|
+
/** Its lesson slug: `motion/constant-acceleration`. */
|
|
109
|
+
readonly slug: string;
|
|
110
|
+
/** Competencies it teaches; the outcomes frame lists those of every chapter covered. */
|
|
111
|
+
readonly teaches: readonly string[];
|
|
112
|
+
/** Their outcomes, in order. */
|
|
113
|
+
readonly outcomes: readonly string[];
|
|
114
|
+
/** What it numbers, which a section of the deck may recall. */
|
|
115
|
+
readonly floats: ChapterFloats;
|
|
116
|
+
}
|
|
117
|
+
/** What the builder needs about each part that has a deck. */
|
|
118
|
+
interface DeckPartFacts {
|
|
119
|
+
/** The part's label: the title of its deck when the deck sets none. */
|
|
120
|
+
readonly label: string;
|
|
121
|
+
/** The part's chapters, in reading order. */
|
|
122
|
+
readonly chapters: readonly DeckChapterFacts[];
|
|
123
|
+
/** The part's lessons that are only slides, by name: a section cannot cover one. */
|
|
124
|
+
readonly slidesFirst: readonly string[];
|
|
125
|
+
}
|
|
126
|
+
interface BuildDecksInput {
|
|
127
|
+
readonly decks: readonly DeckFile[];
|
|
128
|
+
readonly settings: NormalizedDeck;
|
|
129
|
+
readonly rules: DeckRuleSettings;
|
|
130
|
+
/** The lesson behind each lesson's deck, by lesson id. */
|
|
131
|
+
readonly lessons: ReadonlyMap<string, DeckLessonFacts>;
|
|
132
|
+
/** Each part the course configures that has a deck, by its directory. */
|
|
133
|
+
readonly parts?: ReadonlyMap<string, DeckPartFacts>;
|
|
134
|
+
/** What every title frame shows under the deck's title: the course's name and its authors. */
|
|
135
|
+
readonly course?: {
|
|
136
|
+
readonly name?: string;
|
|
137
|
+
readonly authors: readonly string[];
|
|
138
|
+
};
|
|
139
|
+
/** The glyph table of each deck's page, by page id (`pageScope`). */
|
|
140
|
+
readonly scopeOf: (pageId: string) => readonly ScopeEntry[];
|
|
141
|
+
/** Decorations a deck's page suspends (rule N22), by page id. */
|
|
142
|
+
readonly suspendedOf?: (pageId: string) => readonly string[];
|
|
143
|
+
/** A `[[key]]` term's label in a heading, as the deck's page reads it. */
|
|
144
|
+
readonly labelFor?: (pageId: string, key: string) => string | undefined;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* A frame's id: 12 hex digits of a SHA-256 over its kind and what it shows,
|
|
148
|
+
* one string each (`ManifestDeckFrame.id`).
|
|
149
|
+
*/
|
|
150
|
+
declare function deckFrameId(kind: ManifestDeckFrame['kind'], shows: readonly string[]): string;
|
|
151
|
+
declare function buildDecks(input: BuildDecksInput): {
|
|
152
|
+
decks: BuiltDeck[];
|
|
153
|
+
diagnostics: MathGateDiagnostic[];
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Each labelled display equation of a chapter body, by key: its LaTeX (what
|
|
157
|
+
* rule D8 compares a deck's equation with).
|
|
158
|
+
*/
|
|
159
|
+
declare function chapterEquationLatex(body: string): Map<string, string>;
|
|
160
|
+
|
|
161
|
+
export { type BuildDecksInput, type BuiltDeck, type DeckChapterFacts, type DeckLessonFacts, type DeckPartFacts, type ManifestDeckFrame, buildDecks, chapterEquationLatex, deckFrameId };
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { readDeckSource } from "../reference/deck-source.js";
|
|
3
|
+
import {
|
|
4
|
+
chapterNumberOf,
|
|
5
|
+
resolvePartRecalls,
|
|
6
|
+
validateDecks
|
|
7
|
+
} from "../reference/decks-validate.js";
|
|
8
|
+
import { mathSpans } from "../reference/gate-math.js";
|
|
9
|
+
import { resolveMathGlyphs } from "../reference/math-glyphs.mjs";
|
|
10
|
+
import { citedSourceIds } from "./lesson-derivation.js";
|
|
11
|
+
const NOTES_BLOCK = /<Notes\s*>[\s\S]*?<\/Notes\s*>/g;
|
|
12
|
+
const TERM = /\[\[\s*([a-z0-9]+(?:[.-][a-z0-9]+)*)\s*\]\]/g;
|
|
13
|
+
const EXPLAIN = /\\explain\s*\{([^{}]+)\}/g;
|
|
14
|
+
const EQ_LABEL = /\\label\{eq:([^{}]+)\}/g;
|
|
15
|
+
function frameKeys(frame, scope, suspended, recalled = /* @__PURE__ */ new Map()) {
|
|
16
|
+
const text = frame.body.replace(NOTES_BLOCK, (block) => block.replace(/[^\n]/g, " "));
|
|
17
|
+
const keys = [];
|
|
18
|
+
const add = (key) => {
|
|
19
|
+
if (!keys.includes(key)) keys.push(key);
|
|
20
|
+
};
|
|
21
|
+
const known = new Set(scope.map((entry) => entry.key));
|
|
22
|
+
for (const match of text.matchAll(TERM)) {
|
|
23
|
+
if (known.has(match[1] ?? "")) add(match[1] ?? "");
|
|
24
|
+
}
|
|
25
|
+
const latexes = [
|
|
26
|
+
...mathSpans(text).map((span) => span.latex),
|
|
27
|
+
...frame.recalls.flatMap((recall) => {
|
|
28
|
+
const latex = recall.ref?.startsWith("eq-") ? recalled.get(recall.ref.slice(3)) : void 0;
|
|
29
|
+
return latex === void 0 ? [] : [latex];
|
|
30
|
+
})
|
|
31
|
+
];
|
|
32
|
+
for (const latex of latexes) {
|
|
33
|
+
for (const match of latex.matchAll(EXPLAIN)) add((match[1] ?? "").trim());
|
|
34
|
+
try {
|
|
35
|
+
const result = resolveMathGlyphs(latex.replace(EQ_LABEL, ""), [...scope], { suspended: [...suspended] });
|
|
36
|
+
for (const binding of result.bindings ?? []) add(binding.key);
|
|
37
|
+
} catch {
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return keys;
|
|
41
|
+
}
|
|
42
|
+
function ownEquationKeys(source) {
|
|
43
|
+
const keys = [];
|
|
44
|
+
for (const frame of source.frames) {
|
|
45
|
+
for (const math of frame.displayMath) {
|
|
46
|
+
for (const match of math.latex.matchAll(EQ_LABEL)) {
|
|
47
|
+
const key = (match[1] ?? "").trim();
|
|
48
|
+
if (key && !keys.includes(key)) keys.push(key);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return keys;
|
|
53
|
+
}
|
|
54
|
+
function deckFrameId(kind, shows) {
|
|
55
|
+
return createHash("sha256").update(JSON.stringify([kind, ...shows])).digest("hex").slice(0, 12);
|
|
56
|
+
}
|
|
57
|
+
function frameSource(body, frame) {
|
|
58
|
+
return body.slice(frame.index, frame.end).replace(/\r\n?/gu, "\n").replace(/[ \t]+$/gmu, "").trimEnd();
|
|
59
|
+
}
|
|
60
|
+
function lessonOwner(deck, lesson) {
|
|
61
|
+
const floats = lesson?.chapterFloats;
|
|
62
|
+
return {
|
|
63
|
+
recalled: (ref) => {
|
|
64
|
+
const number = chapterNumberOf(ref, floats);
|
|
65
|
+
const latex = ref.startsWith("eq-") ? floats?.equations.get(ref.slice(3))?.latex : void 0;
|
|
66
|
+
return { ...number === void 0 ? {} : { number }, ...latex === void 0 ? {} : { latex } };
|
|
67
|
+
},
|
|
68
|
+
frameChapter: () => void 0,
|
|
69
|
+
teaches: lesson?.teaches ?? [],
|
|
70
|
+
outcomes: lesson?.outcomes ?? [],
|
|
71
|
+
fallbackTitle: lesson?.title ?? deck.lessonId,
|
|
72
|
+
identity: {
|
|
73
|
+
lessonId: deck.lessonId,
|
|
74
|
+
...deck.chapterPath === void 0 ? {} : { chapter: deck.lessonSlug },
|
|
75
|
+
covers: []
|
|
76
|
+
},
|
|
77
|
+
validation: {
|
|
78
|
+
hasChapter: deck.chapterPath !== void 0,
|
|
79
|
+
inPart: deck.inPart,
|
|
80
|
+
...floats === void 0 ? {} : { chapter: floats }
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function partOwner(deck, part, source) {
|
|
85
|
+
const facts = {
|
|
86
|
+
dir: deck.partDir,
|
|
87
|
+
chapters: (part?.chapters ?? []).map((chapter) => ({ name: chapter.name, slug: chapter.slug, floats: chapter.floats })),
|
|
88
|
+
slidesFirst: part?.slidesFirst ?? []
|
|
89
|
+
};
|
|
90
|
+
const recalls = resolvePartRecalls(source, facts);
|
|
91
|
+
const covered = new Set(recalls.covered.map((chapter) => chapter.name));
|
|
92
|
+
const inOrder = (part?.chapters ?? []).filter((chapter) => covered.has(chapter.name));
|
|
93
|
+
const teaches = [...new Set(inOrder.flatMap((chapter) => chapter.teaches))];
|
|
94
|
+
return {
|
|
95
|
+
recalled: (ref) => {
|
|
96
|
+
const floats = recalls.chapterOf.get(ref)?.floats;
|
|
97
|
+
const number = chapterNumberOf(ref, floats);
|
|
98
|
+
const latex = ref.startsWith("eq-") ? floats?.equations.get(ref.slice(3))?.latex : void 0;
|
|
99
|
+
return { ...number === void 0 ? {} : { number }, ...latex === void 0 ? {} : { latex } };
|
|
100
|
+
},
|
|
101
|
+
frameChapter: (position) => recalls.frameChapters[position]?.slug,
|
|
102
|
+
teaches,
|
|
103
|
+
outcomes: [...new Set(inOrder.flatMap((chapter) => chapter.outcomes))],
|
|
104
|
+
fallbackTitle: part?.label ?? deck.partDir,
|
|
105
|
+
identity: {
|
|
106
|
+
part: deck.partDir,
|
|
107
|
+
covers: recalls.covered.map((chapter) => ({ chapter: chapter.slug, frame: chapter.position + 2 })),
|
|
108
|
+
recalledFrom: Object.fromEntries(
|
|
109
|
+
[...recalls.chapterOf].sort(([left], [right]) => left.localeCompare(right)).map(([ref, chapter]) => [ref, chapter.slug])
|
|
110
|
+
)
|
|
111
|
+
},
|
|
112
|
+
validation: { hasChapter: false, inPart: part !== void 0, part: facts }
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function buildDecks(input) {
|
|
116
|
+
const decks = [];
|
|
117
|
+
const validation = [];
|
|
118
|
+
for (const deck of input.decks) {
|
|
119
|
+
const source = readDeckSource(deck.body, {
|
|
120
|
+
labelFor: (key) => input.labelFor?.(deck.pageId, key)
|
|
121
|
+
});
|
|
122
|
+
const owner = deck.scope === "part" ? partOwner(deck, input.parts?.get(deck.partDir), source) : lessonOwner(deck, input.lessons.get(deck.lessonId));
|
|
123
|
+
const scope = input.scopeOf(deck.pageId);
|
|
124
|
+
const suspended = input.suspendedOf?.(deck.pageId) ?? [];
|
|
125
|
+
const seen = /* @__PURE__ */ new Set();
|
|
126
|
+
const recalled = new Map(
|
|
127
|
+
source.frames.flatMap(
|
|
128
|
+
(frame) => frame.recalls.flatMap((recall) => {
|
|
129
|
+
if (!recall.ref?.startsWith("eq-")) return [];
|
|
130
|
+
const latex = owner.recalled(recall.ref).latex;
|
|
131
|
+
return latex === void 0 ? [] : [[recall.ref.slice(3), latex]];
|
|
132
|
+
})
|
|
133
|
+
)
|
|
134
|
+
);
|
|
135
|
+
const newSymbols = source.frames.map((frame) => {
|
|
136
|
+
const fresh = frameKeys(frame, scope, suspended, recalled).filter((key) => !seen.has(key));
|
|
137
|
+
for (const key of fresh) seen.add(key);
|
|
138
|
+
return fresh;
|
|
139
|
+
});
|
|
140
|
+
validation.push({
|
|
141
|
+
file: deck.file,
|
|
142
|
+
pageId: deck.pageId,
|
|
143
|
+
body: deck.body,
|
|
144
|
+
bodyLine: deck.bodyLine,
|
|
145
|
+
data: deck.data,
|
|
146
|
+
source,
|
|
147
|
+
...owner.validation,
|
|
148
|
+
newSymbols
|
|
149
|
+
});
|
|
150
|
+
const title = typeof deck.data.title === "string" && deck.data.title.trim() !== "" ? deck.data.title : owner.fallbackTitle;
|
|
151
|
+
const frames = [
|
|
152
|
+
{
|
|
153
|
+
number: 1,
|
|
154
|
+
id: deckFrameId("title", [title, input.course?.name ?? "", ...input.course?.authors ?? []]),
|
|
155
|
+
kind: "title",
|
|
156
|
+
title,
|
|
157
|
+
steps: 1
|
|
158
|
+
}
|
|
159
|
+
];
|
|
160
|
+
source.frames.forEach((frame, index) => {
|
|
161
|
+
const symbols = newSymbols[index] ?? [];
|
|
162
|
+
const recalls = frame.recalls.flatMap((recall) => recall.ref === void 0 ? [] : [recall.ref]);
|
|
163
|
+
const chapter = owner.frameChapter(index);
|
|
164
|
+
frames.push({
|
|
165
|
+
number: frames.length + 1,
|
|
166
|
+
id: deckFrameId(frame.kind, [
|
|
167
|
+
frameSource(deck.body, frame),
|
|
168
|
+
...recalls.map((ref) => `${ref} ${owner.recalled(ref).number ?? "?"}`)
|
|
169
|
+
]),
|
|
170
|
+
kind: frame.kind,
|
|
171
|
+
title: frame.title,
|
|
172
|
+
slug: frame.slug,
|
|
173
|
+
...frame.section === void 0 ? {} : { section: frame.section },
|
|
174
|
+
steps: frame.pauses.length + 1,
|
|
175
|
+
...frame.morph ? { morph: true } : {},
|
|
176
|
+
...recalls.length === 0 ? {} : { recalls },
|
|
177
|
+
...frame.notes.length === 0 ? {} : { notes: true },
|
|
178
|
+
...symbols.length === 0 ? {} : { symbols },
|
|
179
|
+
...chapter === void 0 ? {} : { chapter }
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
if (input.settings.outcomesFrame && owner.teaches.length > 0) {
|
|
183
|
+
frames.push({
|
|
184
|
+
number: frames.length + 1,
|
|
185
|
+
id: deckFrameId("outcomes", owner.outcomes),
|
|
186
|
+
kind: "outcomes",
|
|
187
|
+
title: "What you can now do",
|
|
188
|
+
steps: 1
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
const cited = [...citedSourceIds(deck.body)].sort();
|
|
192
|
+
if (cited.length > 0) {
|
|
193
|
+
frames.push({
|
|
194
|
+
number: frames.length + 1,
|
|
195
|
+
id: deckFrameId("references", cited),
|
|
196
|
+
kind: "references",
|
|
197
|
+
title: "References",
|
|
198
|
+
steps: 1
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
decks.push({
|
|
202
|
+
...owner.identity.lessonId === void 0 ? {} : { lessonId: owner.identity.lessonId },
|
|
203
|
+
pageId: deck.pageId,
|
|
204
|
+
slug: deck.route,
|
|
205
|
+
file: deck.file,
|
|
206
|
+
title,
|
|
207
|
+
description: typeof deck.data.description === "string" ? deck.data.description : "",
|
|
208
|
+
...owner.identity.chapter === void 0 ? {} : { chapter: owner.identity.chapter },
|
|
209
|
+
...owner.identity.part === void 0 ? {} : { part: owner.identity.part },
|
|
210
|
+
covers: owner.identity.covers,
|
|
211
|
+
...owner.identity.recalledFrom === void 0 ? {} : { recalledFrom: owner.identity.recalledFrom },
|
|
212
|
+
frames,
|
|
213
|
+
equations: ownEquationKeys(source).map((key, index) => ({ key, number: String(index + 1) }))
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
decks: decks.sort((left, right) => left.slug.localeCompare(right.slug)),
|
|
218
|
+
diagnostics: validateDecks(validation, input.rules)
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function chapterEquationLatex(body) {
|
|
222
|
+
const latex = /* @__PURE__ */ new Map();
|
|
223
|
+
for (const span of mathSpans(body)) {
|
|
224
|
+
for (const match of span.latex.matchAll(EQ_LABEL)) {
|
|
225
|
+
const key = (match[1] ?? "").trim();
|
|
226
|
+
if (key && !latex.has(key)) latex.set(key, span.latex);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return latex;
|
|
230
|
+
}
|
|
231
|
+
export {
|
|
232
|
+
buildDecks,
|
|
233
|
+
chapterEquationLatex,
|
|
234
|
+
deckFrameId
|
|
235
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Manifest } from '../manifest.js';
|
|
2
2
|
import '../../curriculum/validation.js';
|
|
3
3
|
import '../../reference/consistency.js';
|
|
4
|
-
import '../../course-config-
|
|
4
|
+
import '../../course-config-BLtIdkei.js';
|
|
5
5
|
import '../../rules/catalog.js';
|
|
6
6
|
import '../../rules/course-rules.js';
|
|
7
7
|
import '../collections.js';
|
|
@@ -23,6 +23,10 @@ import '../../reference/mixed-content.js';
|
|
|
23
23
|
import '../../reference/gloss.js';
|
|
24
24
|
import '../../rules/waivers.js';
|
|
25
25
|
import '../knowledge-version.js';
|
|
26
|
+
import '../page-versions.js';
|
|
27
|
+
import '../decks.js';
|
|
28
|
+
import '../../reference/decks-validate.js';
|
|
29
|
+
import '../../reference/deck-source.js';
|
|
26
30
|
import '../lesson-derivation.js';
|
|
27
31
|
|
|
28
32
|
/**
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ExportLogger } from './export-chapters.js';
|
|
2
|
+
import { Manifest } from '../manifest.js';
|
|
3
|
+
import './static-tree.js';
|
|
4
|
+
import './html-tree.js';
|
|
5
|
+
import 'parse5';
|
|
6
|
+
import './latex/capture.js';
|
|
7
|
+
import 'node:http';
|
|
8
|
+
import '../../curriculum/validation.js';
|
|
9
|
+
import '../../reference/consistency.js';
|
|
10
|
+
import '../../course-config-BLtIdkei.js';
|
|
11
|
+
import '../../rules/catalog.js';
|
|
12
|
+
import '../../rules/course-rules.js';
|
|
13
|
+
import '../collections.js';
|
|
14
|
+
import '../../reference/types.js';
|
|
15
|
+
import '../../reference/gate-retired-keys.js';
|
|
16
|
+
import '../../reference/lint-ignore.js';
|
|
17
|
+
import '../../reference/equations-validate.js';
|
|
18
|
+
import '../../reference/tables-validate.js';
|
|
19
|
+
import '../../reference/keyed-float-validate.js';
|
|
20
|
+
import '../../reference/figures-validate.js';
|
|
21
|
+
import '../../reference/diagrams-validate.js';
|
|
22
|
+
import '../../reference/examples-validate.js';
|
|
23
|
+
import '../../reference/folds-validate.js';
|
|
24
|
+
import '../../reference/knowledge-checks-validate.js';
|
|
25
|
+
import '../../reference/raw-floats-validate.js';
|
|
26
|
+
import '../../reference/lab-katex-validate.js';
|
|
27
|
+
import '../../reference/gate-math.js';
|
|
28
|
+
import '../../reference/mixed-content.js';
|
|
29
|
+
import '../../reference/gloss.js';
|
|
30
|
+
import '../../rules/waivers.js';
|
|
31
|
+
import '../knowledge-version.js';
|
|
32
|
+
import '../page-versions.js';
|
|
33
|
+
import '../decks.js';
|
|
34
|
+
import '../../reference/decks-validate.js';
|
|
35
|
+
import '../../reference/deck-source.js';
|
|
36
|
+
import '../lesson-derivation.js';
|
|
37
|
+
|
|
38
|
+
interface FrameFitFinding {
|
|
39
|
+
readonly code: 'frame-overflow';
|
|
40
|
+
readonly severity: 'error';
|
|
41
|
+
/** The deck file. */
|
|
42
|
+
readonly file: string;
|
|
43
|
+
readonly frame: number;
|
|
44
|
+
readonly title: string;
|
|
45
|
+
/** How far past the canvas the content runs, in canvas pixels. */
|
|
46
|
+
readonly overflow: number;
|
|
47
|
+
readonly message: string;
|
|
48
|
+
}
|
|
49
|
+
declare function checkFrameFit(outputRoot: string, manifest: Pick<Manifest, 'decks'>, options: {
|
|
50
|
+
readonly logger: ExportLogger;
|
|
51
|
+
readonly projectRoot?: string;
|
|
52
|
+
readonly timeoutMs?: number;
|
|
53
|
+
}): Promise<FrameFitFinding[]>;
|
|
54
|
+
|
|
55
|
+
export { type FrameFitFinding, checkFrameFit };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { parse } from "parse5";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { inferBasePrefix } from "./html-tree.js";
|
|
5
|
+
import { courseChromium, serve } from "./latex/capture.js";
|
|
6
|
+
import { strictMode } from "./export-chapters.js";
|
|
7
|
+
function measureFrames() {
|
|
8
|
+
const found = [];
|
|
9
|
+
for (const frame of document.querySelectorAll(".deck .deck-frame")) {
|
|
10
|
+
const body = frame.querySelector(".deck-frame__body");
|
|
11
|
+
const canvas = frame.querySelector(".deck-canvas");
|
|
12
|
+
const over = Math.max(
|
|
13
|
+
body ? body.scrollHeight - body.clientHeight : 0,
|
|
14
|
+
body ? body.scrollWidth - body.clientWidth : 0,
|
|
15
|
+
canvas ? canvas.scrollHeight - canvas.clientHeight : 0
|
|
16
|
+
);
|
|
17
|
+
if (over > 1) {
|
|
18
|
+
found.push({
|
|
19
|
+
frame: Number(frame.dataset.frame),
|
|
20
|
+
title: frame.querySelector(".deck-frame__title, .deck-title__title")?.textContent?.trim() ?? "",
|
|
21
|
+
overflow: Math.round(over)
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return found;
|
|
26
|
+
}
|
|
27
|
+
async function checkFrameFit(outputRoot, manifest, options) {
|
|
28
|
+
const decks = manifest.decks ?? [];
|
|
29
|
+
if (decks.length === 0) return [];
|
|
30
|
+
const chromium = await courseChromium(options.projectRoot ?? process.cwd());
|
|
31
|
+
if (!chromium) {
|
|
32
|
+
const message = "frame-overflow (rule D2): no Chromium from Playwright in this course, so no frame was measured. Install it (`pnpm exec playwright install chromium`) to check that every frame fits its canvas.";
|
|
33
|
+
if (strictMode()) throw new Error(message);
|
|
34
|
+
options.logger.warn(message);
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
const firstPage = await readFile(join(outputRoot, decks[0].slug, "index.html"), "utf8");
|
|
38
|
+
const base = inferBasePrefix(parse(firstPage));
|
|
39
|
+
const { origin, server } = await serve(outputRoot, base);
|
|
40
|
+
const findings = [];
|
|
41
|
+
let browser;
|
|
42
|
+
try {
|
|
43
|
+
browser = await chromium.launch();
|
|
44
|
+
for (const deck of decks) {
|
|
45
|
+
const context = await browser.newContext({
|
|
46
|
+
viewport: { width: 1280, height: 900 },
|
|
47
|
+
colorScheme: "light",
|
|
48
|
+
reducedMotion: "reduce",
|
|
49
|
+
locale: "en-US"
|
|
50
|
+
});
|
|
51
|
+
try {
|
|
52
|
+
const page = await context.newPage();
|
|
53
|
+
await page.goto(`${origin}${base}${deck.slug}/`, { waitUntil: "load" });
|
|
54
|
+
await page.evaluate(async (timeout) => {
|
|
55
|
+
const start = performance.now();
|
|
56
|
+
while (!(document.querySelector(".deck[data-deck-ready]") && document.fonts.status === "loaded")) {
|
|
57
|
+
if (performance.now() - start > timeout) break;
|
|
58
|
+
await new Promise((done) => setTimeout(done, 50));
|
|
59
|
+
}
|
|
60
|
+
for (const frame of document.querySelectorAll(".deck .deck-frame")) {
|
|
61
|
+
frame.scrollIntoView({ block: "center" });
|
|
62
|
+
await new Promise((done) => requestAnimationFrame(() => setTimeout(done, 30)));
|
|
63
|
+
}
|
|
64
|
+
await new Promise((done) => setTimeout(done, 400));
|
|
65
|
+
window.explicoDeckOverflow?.();
|
|
66
|
+
}, options.timeoutMs ?? 3e4);
|
|
67
|
+
for (const { frame, title, overflow } of await page.evaluate(measureFrames)) {
|
|
68
|
+
findings.push({
|
|
69
|
+
code: "frame-overflow",
|
|
70
|
+
severity: "error",
|
|
71
|
+
file: deck.file,
|
|
72
|
+
frame,
|
|
73
|
+
title,
|
|
74
|
+
overflow,
|
|
75
|
+
message: `${deck.file}: slide ${frame}${title ? ` \u201C${title}\u201D` : ""} does not fit its canvas \u2014 its content runs ${overflow}px past it (rule D2). Split the frame in two, move its argument into <Notes>, or recall less.`
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
} finally {
|
|
79
|
+
await context.close();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} finally {
|
|
83
|
+
await browser?.close();
|
|
84
|
+
await new Promise((done) => server.close(() => done()));
|
|
85
|
+
}
|
|
86
|
+
return findings;
|
|
87
|
+
}
|
|
88
|
+
export {
|
|
89
|
+
checkFrameFit
|
|
90
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ManifestLesson, Manifest } from '../manifest.js';
|
|
2
|
-
import { StaticPage, Block } from './static-tree.js';
|
|
1
|
+
import { ManifestLesson, ManifestDeck, Manifest } from '../manifest.js';
|
|
2
|
+
import { StaticPage, StaticDeck, Block } from './static-tree.js';
|
|
3
3
|
import { CaptureResults } from './latex/capture.js';
|
|
4
4
|
import '../../curriculum/validation.js';
|
|
5
5
|
import '../../reference/consistency.js';
|
|
6
|
-
import '../../course-config-
|
|
6
|
+
import '../../course-config-BLtIdkei.js';
|
|
7
7
|
import '../../rules/catalog.js';
|
|
8
8
|
import '../../rules/course-rules.js';
|
|
9
9
|
import '../collections.js';
|
|
@@ -25,9 +25,14 @@ import '../../reference/mixed-content.js';
|
|
|
25
25
|
import '../../reference/gloss.js';
|
|
26
26
|
import '../../rules/waivers.js';
|
|
27
27
|
import '../knowledge-version.js';
|
|
28
|
+
import '../page-versions.js';
|
|
29
|
+
import '../decks.js';
|
|
30
|
+
import '../../reference/decks-validate.js';
|
|
31
|
+
import '../../reference/deck-source.js';
|
|
28
32
|
import '../lesson-derivation.js';
|
|
29
33
|
import './html-tree.js';
|
|
30
34
|
import 'parse5';
|
|
35
|
+
import 'node:http';
|
|
31
36
|
|
|
32
37
|
/**
|
|
33
38
|
* What the print exporters (LaTeX, Markdown) share: every chapter's static
|
|
@@ -42,8 +47,13 @@ interface ExportLogger {
|
|
|
42
47
|
declare const consoleLogger: ExportLogger;
|
|
43
48
|
/** In CI or with `EXPLICO_LATEX_STRICT=1`, a missing engine or browser fails the build. */
|
|
44
49
|
declare function strictMode(): boolean;
|
|
45
|
-
/**
|
|
46
|
-
|
|
50
|
+
/**
|
|
51
|
+
* A document's date as seconds since 1970, for its timestamps: the date of
|
|
52
|
+
* the release its content last changed in (`since`, rule C5), so a document
|
|
53
|
+
* keeps its date across the releases that did not touch it; the newest
|
|
54
|
+
* release's date for a change not yet released, and with no `since`.
|
|
55
|
+
*/
|
|
56
|
+
declare function epochOf(manifest: Pick<Manifest, 'about'>, since?: string | null): number;
|
|
47
57
|
type FigureBlock = Extract<Block, {
|
|
48
58
|
kind: 'figure';
|
|
49
59
|
}>;
|
|
@@ -71,13 +81,34 @@ interface PreparedChapter {
|
|
|
71
81
|
/** The chapter's reading tree, its labs' live caption clauses filled in. */
|
|
72
82
|
readonly page: StaticPage;
|
|
73
83
|
}
|
|
84
|
+
/** A lesson's deck, read from its page (docs/authoring/deck.md). */
|
|
85
|
+
interface PreparedDeck {
|
|
86
|
+
readonly deck: ManifestDeck;
|
|
87
|
+
/** Its frames, each lab's live caption clause filled in. */
|
|
88
|
+
readonly page: StaticDeck;
|
|
89
|
+
/**
|
|
90
|
+
* Where each of its figures and diagrams was drawn, by anchor: the deck's
|
|
91
|
+
* own route, or its chapter's for one it recalls (the chapter's capture is
|
|
92
|
+
* reused).
|
|
93
|
+
*/
|
|
94
|
+
readonly figureRoutes: ReadonlyMap<string, string>;
|
|
95
|
+
}
|
|
74
96
|
interface PreparedChapters {
|
|
75
97
|
/** The site's base path, `/` or `/course/`. */
|
|
76
98
|
readonly base: string;
|
|
77
99
|
readonly chapters: readonly PreparedChapter[];
|
|
100
|
+
/** Each lesson's deck. */
|
|
101
|
+
readonly decks: readonly PreparedDeck[];
|
|
78
102
|
/** What the capture pass drew, by route and anchor. */
|
|
79
103
|
readonly captures: CaptureResults;
|
|
80
104
|
}
|
|
105
|
+
/** Read one built deck page into its frames. */
|
|
106
|
+
declare function readBuiltDeck(outputRoot: string, route: string): Promise<{
|
|
107
|
+
html: string;
|
|
108
|
+
page: StaticDeck;
|
|
109
|
+
}>;
|
|
110
|
+
/** Every block a deck's frames show, notes aside. */
|
|
111
|
+
declare function deckBlocks(page: StaticDeck): Block[];
|
|
81
112
|
/** Read one built page into its reading tree. */
|
|
82
113
|
declare function readBuiltPage(outputRoot: string, slug: string): Promise<{
|
|
83
114
|
html: string;
|
|
@@ -95,4 +126,4 @@ declare function prepareChapters(outputRoot: string, manifest: Manifest, options
|
|
|
95
126
|
readonly projectRoot?: string;
|
|
96
127
|
}): Promise<PreparedChapters>;
|
|
97
128
|
|
|
98
|
-
export { type ExportLogger, type PreparedChapter, type PreparedChapters, consoleLogger, diagramsOf, epochOf, figuresOf, imageExtension, imageFile, imagesOf, needsCapture, prepareChapters, readBuiltPage, strictMode, withLiveClauses };
|
|
129
|
+
export { type ExportLogger, type PreparedChapter, type PreparedChapters, type PreparedDeck, consoleLogger, deckBlocks, diagramsOf, epochOf, figuresOf, imageExtension, imageFile, imagesOf, needsCapture, prepareChapters, readBuiltDeck, readBuiltPage, strictMode, withLiveClauses };
|