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
|
@@ -46,7 +46,9 @@ import {
|
|
|
46
46
|
import {
|
|
47
47
|
gateContentMath,
|
|
48
48
|
pageScope,
|
|
49
|
-
scopeEntry
|
|
49
|
+
scopeEntry,
|
|
50
|
+
scopeLocals,
|
|
51
|
+
suspendedOperators
|
|
50
52
|
} from "../reference/gate-math.js";
|
|
51
53
|
import { gateIndices } from "../reference/gate-indices.js";
|
|
52
54
|
import { derivedNotationEntries } from "../reference/derived-entries.js";
|
|
@@ -81,14 +83,19 @@ import {
|
|
|
81
83
|
import { loadLintIgnore } from "../reference/lint-ignore.js";
|
|
82
84
|
import { buildNotationRegistry } from "../reference/registry.js";
|
|
83
85
|
import { formulaGlyphScope } from "../reference/gloss.js";
|
|
84
|
-
import {
|
|
86
|
+
import { pageScopeLessonIds, resolvePageReferenceId } from "../reference/references.js";
|
|
85
87
|
import {
|
|
86
88
|
coursePartsOf,
|
|
87
89
|
normalizeBlockLabels,
|
|
88
90
|
normalizeCards,
|
|
91
|
+
normalizeSidebarMarks,
|
|
92
|
+
normalizeSidebarEditions,
|
|
93
|
+
normalizeReadingMemory,
|
|
94
|
+
normalizeAppearance,
|
|
89
95
|
normalizeLessonExports,
|
|
90
96
|
normalizeDisclosure,
|
|
91
|
-
normalizeNumbering
|
|
97
|
+
normalizeNumbering,
|
|
98
|
+
normalizeDeck
|
|
92
99
|
} from "./course-config.js";
|
|
93
100
|
import {
|
|
94
101
|
disabledCodes,
|
|
@@ -104,6 +111,14 @@ import {
|
|
|
104
111
|
import {
|
|
105
112
|
resolveKnowledgeVersion
|
|
106
113
|
} from "./knowledge-version.js";
|
|
114
|
+
import {
|
|
115
|
+
deckStaleDiagnostics,
|
|
116
|
+
nextPageVersions,
|
|
117
|
+
PAGE_VERSIONS_FILE,
|
|
118
|
+
pageSourceDigest,
|
|
119
|
+
readPageVersions,
|
|
120
|
+
sinceOf
|
|
121
|
+
} from "./page-versions.js";
|
|
107
122
|
import {
|
|
108
123
|
loadAbbreviationRegistryInput,
|
|
109
124
|
loadContentRecords,
|
|
@@ -113,15 +128,24 @@ import {
|
|
|
113
128
|
loadNonChapterPages,
|
|
114
129
|
loadNotationSpecs,
|
|
115
130
|
loadPartOverviews,
|
|
116
|
-
loadSourceRecords
|
|
131
|
+
loadSourceRecords,
|
|
132
|
+
loadDeckFiles,
|
|
133
|
+
loadDeckNotationPages,
|
|
134
|
+
loadLessonFiles
|
|
117
135
|
} from "./collections.js";
|
|
136
|
+
import { buildDecks, chapterEquationLatex } from "./decks.js";
|
|
137
|
+
import { readDeckSource } from "../reference/deck-source.js";
|
|
138
|
+
import { coveredSections } from "../reference/decks-validate.js";
|
|
118
139
|
import {
|
|
119
140
|
buildSidebar,
|
|
120
141
|
deriveSources,
|
|
121
142
|
isLessonSlug,
|
|
122
|
-
lessonIdFromSlug
|
|
143
|
+
lessonIdFromSlug,
|
|
144
|
+
mergeTrackOrder,
|
|
145
|
+
sidebarLessonSlug,
|
|
146
|
+
withPartDeckFrames
|
|
123
147
|
} from "./lesson-derivation.js";
|
|
124
|
-
const MANIFEST_SCHEMA_VERSION =
|
|
148
|
+
const MANIFEST_SCHEMA_VERSION = 37;
|
|
125
149
|
const REPOSITORY_ROOT = process.cwd();
|
|
126
150
|
const CONTENT_ROOT = join(REPOSITORY_ROOT, "content");
|
|
127
151
|
const MANIFEST_PATH = join(REPOSITORY_ROOT, "build", "manifest.json");
|
|
@@ -173,11 +197,11 @@ function contentHashes() {
|
|
|
173
197
|
return { content, contentTree: `sha256:${tree.digest("hex")}` };
|
|
174
198
|
}
|
|
175
199
|
function lessonNotationResolution(lesson, definitionsById, availableDefinitionIds) {
|
|
176
|
-
const
|
|
200
|
+
const scopes = pageScopeLessonIds(lesson);
|
|
177
201
|
return lesson.references.map((reference) => {
|
|
178
|
-
const definitionId =
|
|
202
|
+
const definitionId = resolvePageReferenceId(
|
|
179
203
|
reference.key,
|
|
180
|
-
|
|
204
|
+
scopes,
|
|
181
205
|
availableDefinitionIds
|
|
182
206
|
);
|
|
183
207
|
const definition = definitionId === void 0 ? void 0 : definitionsById.get(definitionId);
|
|
@@ -245,29 +269,16 @@ function studyMinutesRange(value) {
|
|
|
245
269
|
return void 0;
|
|
246
270
|
}
|
|
247
271
|
function lessonFrontmatterById() {
|
|
248
|
-
const base = join(CONTENT_ROOT, "docs");
|
|
249
272
|
const result = /* @__PURE__ */ new Map();
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
if (!isLessonSlug(slug)) continue;
|
|
260
|
-
const id = slug.replace(/\.(md|mdx)$/, "").replace(/\//g, ".");
|
|
261
|
-
const data = parseFrontmatter(readFileSync(path, "utf8")).frontmatter ?? {};
|
|
262
|
-
const studyMinutes = studyMinutesRange(data.studyMinutes);
|
|
263
|
-
result.set(id, {
|
|
264
|
-
title: typeof data.title === "string" ? data.title : id,
|
|
265
|
-
description: typeof data.description === "string" ? data.description : "",
|
|
266
|
-
...studyMinutes === void 0 ? {} : { studyMinutes }
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
walk(base);
|
|
273
|
+
for (const { path, lessonId: id } of loadLessonFiles()) {
|
|
274
|
+
const data = parseFrontmatter(readFileSync(path, "utf8")).frontmatter ?? {};
|
|
275
|
+
const studyMinutes = studyMinutesRange(data.studyMinutes);
|
|
276
|
+
result.set(id, {
|
|
277
|
+
title: typeof data.title === "string" ? data.title : id,
|
|
278
|
+
description: typeof data.description === "string" ? data.description : "",
|
|
279
|
+
...studyMinutes === void 0 ? {} : { studyMinutes }
|
|
280
|
+
});
|
|
281
|
+
}
|
|
271
282
|
return result;
|
|
272
283
|
}
|
|
273
284
|
async function compileManifest(courseConfig) {
|
|
@@ -280,17 +291,36 @@ async function compileManifest(courseConfig) {
|
|
|
280
291
|
const off = disabledCodes(rules);
|
|
281
292
|
const numberingSettings = normalizeNumbering(courseConfig);
|
|
282
293
|
const blockLabels = normalizeBlockLabels(courseConfig);
|
|
294
|
+
const deckSettings = normalizeDeck(courseConfig);
|
|
283
295
|
const [catalog, notationInput, abbreviationsInput] = await Promise.all([
|
|
284
296
|
loadCurriculumCatalog(),
|
|
285
297
|
loadNotationRegistryInput(),
|
|
286
298
|
loadAbbreviationRegistryInput()
|
|
287
299
|
]);
|
|
288
300
|
const nonChapterPages = loadNonChapterPages();
|
|
301
|
+
const deckFiles = loadDeckFiles();
|
|
302
|
+
const lessonDeckFiles = deckFiles.filter((deck) => deck.scope === "lesson");
|
|
303
|
+
const trackRank = new Map(
|
|
304
|
+
mergeTrackOrder(catalog.tracks.map((track) => ({ id: track.id, lessons: track.lessons }))).map(
|
|
305
|
+
(lessonId, index) => [lessonId, index]
|
|
306
|
+
)
|
|
307
|
+
);
|
|
308
|
+
const readingOrder = (lessonIds) => [...lessonIds].sort(
|
|
309
|
+
(left, right) => (trackRank.get(left) ?? Number.POSITIVE_INFINITY) - (trackRank.get(right) ?? Number.POSITIVE_INFINITY) || left.localeCompare(right)
|
|
310
|
+
);
|
|
311
|
+
const deckPages = loadDeckNotationPages(deckFiles, { order: readingOrder });
|
|
312
|
+
const deckLessonIds = new Set(
|
|
313
|
+
loadLessonFiles().filter((file) => file.edition === "deck").map((file) => file.lessonId)
|
|
314
|
+
);
|
|
315
|
+
const isChapter = (lessonId) => !deckLessonIds.has(lessonId);
|
|
316
|
+
const deckPageIds = new Set(deckPages.map((page) => page.notation.lessonId));
|
|
317
|
+
const chapterInputs = notationInput.lessons.filter((lesson) => isChapter(lesson.lessonId));
|
|
289
318
|
const withPages = {
|
|
290
319
|
...notationInput,
|
|
291
320
|
lessons: [
|
|
292
321
|
...notationInput.lessons,
|
|
293
|
-
...nonChapterPages.map((page) => page.notation)
|
|
322
|
+
...nonChapterPages.map((page) => page.notation),
|
|
323
|
+
...deckPages.map((page) => page.notation)
|
|
294
324
|
]
|
|
295
325
|
};
|
|
296
326
|
const registry = buildNotationRegistry(withPages);
|
|
@@ -325,9 +355,9 @@ async function compileManifest(courseConfig) {
|
|
|
325
355
|
notationInput.sharedDefinitions.map((definition) => [definition.key, definition.label])
|
|
326
356
|
);
|
|
327
357
|
const localLabelsByLesson = new Map(
|
|
328
|
-
|
|
358
|
+
withPages.lessons.map((lesson) => [
|
|
329
359
|
lesson.lessonId,
|
|
330
|
-
new Map(lesson.
|
|
360
|
+
new Map(scopeLocals(lesson).map((definition) => [definition.key, definition.label]))
|
|
331
361
|
])
|
|
332
362
|
);
|
|
333
363
|
const termLabel = (lessonId, key) => localLabelsByLesson.get(lessonId)?.get(key) ?? sharedLabels.get(key);
|
|
@@ -372,18 +402,26 @@ async function compileManifest(courseConfig) {
|
|
|
372
402
|
abbreviations: abbreviationsInput,
|
|
373
403
|
courseAbbreviations: rules.settings("N14")
|
|
374
404
|
}) : [],
|
|
375
|
-
...rules.isEnabled("S1") ? gateHeadingLength(
|
|
405
|
+
...rules.isEnabled("S1") ? gateHeadingLength(chapterInputs, {
|
|
376
406
|
maxLength: rules.number("S1", "maxLength"),
|
|
377
407
|
labelFor: termLabel
|
|
378
408
|
}) : [],
|
|
379
|
-
...gateHeadingStructure(
|
|
409
|
+
...gateHeadingStructure(chapterInputs, {
|
|
380
410
|
levels: rules.isEnabled("S6"),
|
|
381
411
|
adjacency: rules.isEnabled("S7")
|
|
382
412
|
}),
|
|
383
413
|
// The course's own rules (`courseRules`): one pass for every enabled `X`
|
|
384
414
|
// rule that carries a `forbid` pattern. A disabled one, and a guide rule
|
|
385
415
|
// with no pattern, do no work here.
|
|
386
|
-
|
|
416
|
+
// A course rule about one edition is checked on that edition's pages.
|
|
417
|
+
...gateCourseRules(
|
|
418
|
+
withPages.lessons.filter((lesson) => isChapter(lesson.lessonId) && !deckPageIds.has(lesson.lessonId)),
|
|
419
|
+
rules.course.filter((rule) => rule.editions !== "deck")
|
|
420
|
+
),
|
|
421
|
+
...gateCourseRules(
|
|
422
|
+
withPages.lessons.filter((lesson) => !isChapter(lesson.lessonId) || deckPageIds.has(lesson.lessonId)),
|
|
423
|
+
rules.course.filter((rule) => rule.editions !== "chapter")
|
|
424
|
+
),
|
|
387
425
|
// S10 is locked: a float on a non-chapter page has no number to render.
|
|
388
426
|
...gateNonChapterPages(nonChapterPages)
|
|
389
427
|
];
|
|
@@ -472,6 +510,11 @@ async function compileManifest(courseConfig) {
|
|
|
472
510
|
message: `course.settings.json \`parts\` lists "${part.dir}" (${JSON.stringify(part.label)}), but content/docs/${part.dir}/ has no chapter and no overview page yet, so the part is left out of the sidebar and the numbering until it has one.`
|
|
473
511
|
});
|
|
474
512
|
}
|
|
513
|
+
const configuredDirs = new Set(configuredParts.map((part) => part.dir));
|
|
514
|
+
const partDeckFiles = deckFiles.filter(
|
|
515
|
+
(deck) => deck.scope === "part" && configuredDirs.has(deck.partDir)
|
|
516
|
+
);
|
|
517
|
+
const partChapterNames = (dir) => lessonSlugs.filter((slug) => slug.startsWith(`${dir}/`) && isChapter(lessonIdFromSlug(slug))).map((slug) => slug.slice(dir.length + 1));
|
|
475
518
|
const partDirs = new Set(listedParts.map((part) => part.dir));
|
|
476
519
|
for (const lesson of notationInput.lessons) {
|
|
477
520
|
const dir = lesson.lessonId.split(".")[0] ?? "";
|
|
@@ -493,16 +536,6 @@ async function compileManifest(courseConfig) {
|
|
|
493
536
|
)
|
|
494
537
|
);
|
|
495
538
|
}
|
|
496
|
-
const waiverDiagnostics = [];
|
|
497
|
-
const waiverRules = { courseRules: rules.course };
|
|
498
|
-
const waivers = withPages.lessons.flatMap((lesson) => {
|
|
499
|
-
const collected = collectWaivers(lesson, waiverRules);
|
|
500
|
-
waiverDiagnostics.push(...collected.diagnostics);
|
|
501
|
-
return collected.waivers;
|
|
502
|
-
});
|
|
503
|
-
const waived = applyWaivers(mathIssues, waivers, waiverRules);
|
|
504
|
-
mathIssues.splice(0, mathIssues.length, ...waived.kept);
|
|
505
|
-
waiverDiagnostics.push(...waived.unused);
|
|
506
539
|
const sidebar = buildSidebar(
|
|
507
540
|
catalog.tracks.map((track) => ({ id: track.id, lessons: track.lessons })),
|
|
508
541
|
lessonSlugs,
|
|
@@ -513,7 +546,31 @@ async function compileManifest(courseConfig) {
|
|
|
513
546
|
{
|
|
514
547
|
floatIndex: [".mdx", ".md"].some(
|
|
515
548
|
(extension) => existsSync(join(CONTENT_ROOT, "docs", `figures-and-tables${extension}`))
|
|
516
|
-
)
|
|
549
|
+
),
|
|
550
|
+
// A deck beside its chapter is listed right under it.
|
|
551
|
+
decks: new Map(
|
|
552
|
+
lessonDeckFiles.filter((deck) => deck.chapterPath !== void 0 && deck.inPart).map((deck) => [deck.lessonSlug, deck.route])
|
|
553
|
+
),
|
|
554
|
+
// A deck with no chapter is the lesson: its row carries the deck's glyph.
|
|
555
|
+
slidesFirst: new Set(
|
|
556
|
+
lessonDeckFiles.filter((deck) => deck.chapterPath === void 0 && deck.inPart).map((deck) => deck.lessonSlug)
|
|
557
|
+
),
|
|
558
|
+
// A part's deck follows the part's Overview; a chapter it covers that
|
|
559
|
+
// has no deck of its own links into it, at its section's divider.
|
|
560
|
+
partDecks: new Map(
|
|
561
|
+
partDeckFiles.map((deck) => {
|
|
562
|
+
const { covered } = coveredSections(readDeckSource(deck.body), new Set(partChapterNames(deck.partDir)));
|
|
563
|
+
return [
|
|
564
|
+
deck.partDir,
|
|
565
|
+
{
|
|
566
|
+
route: deck.route,
|
|
567
|
+
covers: new Map(covered.map(({ name, position }) => [`${deck.partDir}/${name}`, position + 2]))
|
|
568
|
+
}
|
|
569
|
+
];
|
|
570
|
+
})
|
|
571
|
+
),
|
|
572
|
+
// Each edition's row names its lesson, which the sidebar's own row shows.
|
|
573
|
+
titleOf: (slug) => frontmatterById.get(lessonIdFromSlug(slug))?.title
|
|
517
574
|
}
|
|
518
575
|
);
|
|
519
576
|
const bodyByLessonId = new Map(
|
|
@@ -524,7 +581,10 @@ async function compileManifest(courseConfig) {
|
|
|
524
581
|
let partCursor = 0;
|
|
525
582
|
for (const group of sidebar.slice(0, configuredParts.length)) {
|
|
526
583
|
partCursor += 1;
|
|
527
|
-
const lessonIds = group.items.
|
|
584
|
+
const lessonIds = group.items.flatMap((item) => {
|
|
585
|
+
const slug = sidebarLessonSlug(item);
|
|
586
|
+
return slug === void 0 ? [] : [lessonIdFromSlug(slug)];
|
|
587
|
+
});
|
|
528
588
|
if (lessonIds.length === 0) continue;
|
|
529
589
|
const used = {
|
|
530
590
|
equations: 0,
|
|
@@ -536,7 +596,7 @@ async function compileManifest(courseConfig) {
|
|
|
536
596
|
};
|
|
537
597
|
let chapterCursor = 0;
|
|
538
598
|
for (const lessonId of lessonIds) {
|
|
539
|
-
const body = bodyByLessonId.get(lessonId) ?? "";
|
|
599
|
+
const body = isChapter(lessonId) ? bodyByLessonId.get(lessonId) ?? "" : "";
|
|
540
600
|
const chapter = ++chapterCursor;
|
|
541
601
|
placementByLessonId.set(lessonId, {
|
|
542
602
|
part: partCursor,
|
|
@@ -565,7 +625,8 @@ async function compileManifest(courseConfig) {
|
|
|
565
625
|
return [
|
|
566
626
|
lesson.lessonId,
|
|
567
627
|
scanSectionHeadings(lesson.body, {
|
|
568
|
-
|
|
628
|
+
// A deck's headings are sections and frames, numbered as frames.
|
|
629
|
+
...placement && isChapter(lesson.lessonId) ? { prefix: `${placement.part}.${placement.chapter}` } : {},
|
|
569
630
|
depth: numberingSettings.sections.depth,
|
|
570
631
|
labelFor: (key) => termLabel(lesson.lessonId, key)
|
|
571
632
|
})
|
|
@@ -615,7 +676,7 @@ async function compileManifest(courseConfig) {
|
|
|
615
676
|
} : {}
|
|
616
677
|
};
|
|
617
678
|
});
|
|
618
|
-
const floatInputs = (kind) =>
|
|
679
|
+
const floatInputs = (kind) => chapterInputs.map((lesson) => {
|
|
619
680
|
const placement = placementByLessonId.get(lesson.lessonId);
|
|
620
681
|
return {
|
|
621
682
|
lessonId: lesson.lessonId,
|
|
@@ -725,6 +786,7 @@ async function compileManifest(courseConfig) {
|
|
|
725
786
|
)
|
|
726
787
|
);
|
|
727
788
|
const titledBlocksFor = (lessonId) => {
|
|
789
|
+
if (!isChapter(lessonId)) return [];
|
|
728
790
|
const slug = lessonId.replace(/\./g, "/");
|
|
729
791
|
const body = bodyByLessonId.get(lessonId) ?? "";
|
|
730
792
|
const headings = headingsByLessonId.get(lessonId) ?? [];
|
|
@@ -749,7 +811,7 @@ async function compileManifest(courseConfig) {
|
|
|
749
811
|
);
|
|
750
812
|
};
|
|
751
813
|
const labKatexDiagnostics = validateLabKatexImports(
|
|
752
|
-
notationInput.lessons.map((lesson) => ({
|
|
814
|
+
[...notationInput.lessons, ...deckPages.map((page) => page.notation)].map((lesson) => ({
|
|
753
815
|
lessonId: lesson.lessonId,
|
|
754
816
|
file: lesson.source.file,
|
|
755
817
|
body: lesson.body
|
|
@@ -757,13 +819,112 @@ async function compileManifest(courseConfig) {
|
|
|
757
819
|
REPOSITORY_ROOT
|
|
758
820
|
);
|
|
759
821
|
const rawFloatDiagnostics = validateRawFloats(
|
|
760
|
-
notationInput.lessons.map((lesson) => ({
|
|
822
|
+
[...notationInput.lessons, ...deckPages.map((page) => page.notation)].map((lesson) => ({
|
|
761
823
|
lessonId: lesson.lessonId,
|
|
762
824
|
slug: lesson.lessonId.replace(/\./g, "/"),
|
|
763
825
|
file: lesson.source.file,
|
|
764
826
|
body: lesson.body
|
|
765
827
|
}))
|
|
766
828
|
);
|
|
829
|
+
const pageInputById = new Map(withPages.lessons.map((lesson) => [lesson.lessonId, lesson]));
|
|
830
|
+
const chapterBodyById = new Map(chapterInputs.map((lesson) => [lesson.lessonId, lesson.body]));
|
|
831
|
+
const floatNumbers = (floats) => new Map((floats ?? []).map((float) => [float.key, float.number]));
|
|
832
|
+
const outcomeById = new Map(
|
|
833
|
+
catalog.competencies.flatMap((competency) => {
|
|
834
|
+
const outcome = competency.outcome;
|
|
835
|
+
return typeof outcome === "string" ? [[competency.id, outcome]] : [];
|
|
836
|
+
})
|
|
837
|
+
);
|
|
838
|
+
const chapterFloatsOf = (lessonId) => {
|
|
839
|
+
const slug = lessonId.replace(/\./g, "/");
|
|
840
|
+
const chapterBody = chapterBodyById.get(lessonId);
|
|
841
|
+
const latex = chapterBody === void 0 ? /* @__PURE__ */ new Map() : chapterEquationLatex(chapterBody);
|
|
842
|
+
return {
|
|
843
|
+
equations: new Map(
|
|
844
|
+
(equationsBySlug.get(slug) ?? []).map((equation) => [
|
|
845
|
+
equation.key,
|
|
846
|
+
{ number: equation.number, ...latex.has(equation.key) ? { latex: latex.get(equation.key) } : {} }
|
|
847
|
+
])
|
|
848
|
+
),
|
|
849
|
+
figures: floatNumbers(figuresBySlug.get(slug)),
|
|
850
|
+
tables: floatNumbers(tablesBySlug.get(slug)),
|
|
851
|
+
diagrams: floatNumbers(diagramsBySlug.get(slug))
|
|
852
|
+
};
|
|
853
|
+
};
|
|
854
|
+
const outcomesOf = (lessonId) => (lessonMetaById.get(lessonId)?.teaches ?? []).flatMap((id) => {
|
|
855
|
+
const outcome = outcomeById.get(id);
|
|
856
|
+
return outcome ? [outcome] : [];
|
|
857
|
+
});
|
|
858
|
+
const deckParts = new Map(
|
|
859
|
+
partDeckFiles.map((deck) => {
|
|
860
|
+
const part = manifestParts.find((entry) => entry.dir === deck.partDir);
|
|
861
|
+
const lessonIds = part?.lessons ?? [];
|
|
862
|
+
const nameOf = (lessonId) => lessonId.replace(/\./g, "/").slice(deck.partDir.length + 1);
|
|
863
|
+
return [
|
|
864
|
+
deck.partDir,
|
|
865
|
+
{
|
|
866
|
+
label: part?.label ?? deck.partDir,
|
|
867
|
+
chapters: lessonIds.filter(isChapter).map((lessonId) => ({
|
|
868
|
+
name: nameOf(lessonId),
|
|
869
|
+
slug: lessonId.replace(/\./g, "/"),
|
|
870
|
+
teaches: lessonMetaById.get(lessonId)?.teaches ?? [],
|
|
871
|
+
outcomes: outcomesOf(lessonId),
|
|
872
|
+
floats: chapterFloatsOf(lessonId)
|
|
873
|
+
})),
|
|
874
|
+
slidesFirst: lessonIds.filter((lessonId) => !isChapter(lessonId)).map(nameOf)
|
|
875
|
+
}
|
|
876
|
+
];
|
|
877
|
+
})
|
|
878
|
+
);
|
|
879
|
+
const deckModel = buildDecks({
|
|
880
|
+
decks: deckFiles,
|
|
881
|
+
settings: deckSettings,
|
|
882
|
+
rules: {
|
|
883
|
+
maxWords: rules.number("D2", "maxWords"),
|
|
884
|
+
maxBullets: rules.number("D2", "maxBullets"),
|
|
885
|
+
maxTitleLength: rules.number("D5", "maxLength"),
|
|
886
|
+
maxSteps: rules.number("D6", "maxSteps"),
|
|
887
|
+
maxNewSymbols: rules.number("D9", "maxNewSymbols")
|
|
888
|
+
},
|
|
889
|
+
lessons: new Map(
|
|
890
|
+
lessonDeckFiles.map((deck) => [
|
|
891
|
+
deck.lessonId,
|
|
892
|
+
{
|
|
893
|
+
title: frontmatterById.get(deck.lessonId)?.title ?? deck.lessonId,
|
|
894
|
+
teaches: lessonMetaById.get(deck.lessonId)?.teaches ?? [],
|
|
895
|
+
outcomes: outcomesOf(deck.lessonId),
|
|
896
|
+
...deck.chapterPath === void 0 ? {} : { chapterFloats: chapterFloatsOf(deck.lessonId) }
|
|
897
|
+
}
|
|
898
|
+
])
|
|
899
|
+
),
|
|
900
|
+
parts: deckParts,
|
|
901
|
+
// As the title frame shows them (`titleFrameNode` in `deck-remark.mjs`).
|
|
902
|
+
course: {
|
|
903
|
+
name: courseConfig.about.materialName ?? courseConfig.title,
|
|
904
|
+
authors: courseConfig.about.authors.map((author) => author.name)
|
|
905
|
+
},
|
|
906
|
+
scopeOf: (pageId) => {
|
|
907
|
+
const page = pageInputById.get(pageId);
|
|
908
|
+
return page === void 0 ? [] : pageScope(page, cardsByKey);
|
|
909
|
+
},
|
|
910
|
+
suspendedOf: (pageId) => {
|
|
911
|
+
const page = pageInputById.get(pageId);
|
|
912
|
+
return page === void 0 ? [] : suspendedOperators(page);
|
|
913
|
+
},
|
|
914
|
+
labelFor: termLabel
|
|
915
|
+
});
|
|
916
|
+
mathIssues.push(...deckModel.diagnostics);
|
|
917
|
+
const sidebarWithFrames = withPartDeckFrames(sidebar, deckModel.decks);
|
|
918
|
+
const waiverDiagnostics = [];
|
|
919
|
+
const waiverRules = { courseRules: rules.course };
|
|
920
|
+
const waivers = withPages.lessons.flatMap((lesson) => {
|
|
921
|
+
const collected = collectWaivers(lesson, waiverRules);
|
|
922
|
+
waiverDiagnostics.push(...collected.diagnostics);
|
|
923
|
+
return collected.waivers;
|
|
924
|
+
});
|
|
925
|
+
const waived = applyWaivers(mathIssues, waivers, waiverRules);
|
|
926
|
+
mathIssues.splice(0, mathIssues.length, ...waived.kept);
|
|
927
|
+
waiverDiagnostics.push(...waived.unused);
|
|
767
928
|
const lessons = [];
|
|
768
929
|
for (const notationLesson of notationInput.lessons) {
|
|
769
930
|
const id = notationLesson.lessonId;
|
|
@@ -777,6 +938,10 @@ async function compileManifest(courseConfig) {
|
|
|
777
938
|
lessons.push({
|
|
778
939
|
id,
|
|
779
940
|
slug: id.replace(/\./g, "/"),
|
|
941
|
+
editions: [
|
|
942
|
+
...isChapter(id) ? ["chapter"] : [],
|
|
943
|
+
...lessonDeckFiles.some((deck) => deck.lessonId === id) ? ["deck"] : []
|
|
944
|
+
],
|
|
780
945
|
// 0 = the lesson is not placed in any configured part; a curriculum
|
|
781
946
|
// diagnostic covers that separately, and both numbering paths then fall
|
|
782
947
|
// back to the legacy `##`-section scheme.
|
|
@@ -876,6 +1041,107 @@ async function compileManifest(courseConfig) {
|
|
|
876
1041
|
declaredVersion: courseConfig.about.version,
|
|
877
1042
|
file: relative(REPOSITORY_ROOT, knowledgeChangelogPath).replace(/\\/g, "/")
|
|
878
1043
|
});
|
|
1044
|
+
const trackPageVersions = !rules.disabled.includes("C5");
|
|
1045
|
+
const previousVersions = trackPageVersions ? readPageVersions(join(CONTENT_ROOT, "versions.json"), PAGE_VERSIONS_FILE) : { record: void 0, diagnostics: [] };
|
|
1046
|
+
const digestOf = (file) => hashes.content[file] ?? "missing";
|
|
1047
|
+
const presentFiles = (files) => files.filter((file) => hashes.content[file] !== void 0);
|
|
1048
|
+
const sourceFileById = /* @__PURE__ */ new Map();
|
|
1049
|
+
for (const record of contentRecords) {
|
|
1050
|
+
const file = record.file.replace(/\\/g, "/");
|
|
1051
|
+
if (file.startsWith("content/sources/") && typeof record.data.id === "string") {
|
|
1052
|
+
sourceFileById.set(record.data.id, file);
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
const sharedEntryInputs = (definitionIds) => definitionIds.flatMap((definitionId) => {
|
|
1056
|
+
const definition = definitionsById.get(definitionId);
|
|
1057
|
+
return definition?.kind === "shared" ? [{ label: `notation ${definition.source.file}`, digest: digestOf(definition.source.file) }] : [];
|
|
1058
|
+
});
|
|
1059
|
+
const recalledFloatFacts = (recalledFrom) => Object.fromEntries(
|
|
1060
|
+
Object.entries(recalledFrom).map(([ref, chapter]) => {
|
|
1061
|
+
const [, prefix, key] = /^(eq|fig|tab|dia)-(.+)$/u.exec(ref) ?? [];
|
|
1062
|
+
const floats = prefix === "eq" ? equationsBySlug : prefix === "fig" ? figuresBySlug : prefix === "tab" ? tablesBySlug : diagramsBySlug;
|
|
1063
|
+
const float = floats.get(chapter)?.find((entry) => entry.key === key);
|
|
1064
|
+
const latex = prefix === "eq" ? chapterFloatsOf(chapter.replace(/\//g, ".")).equations.get(key ?? "")?.latex : void 0;
|
|
1065
|
+
return [ref, { chapter, ...float, ...latex === void 0 ? {} : { latex } }];
|
|
1066
|
+
})
|
|
1067
|
+
);
|
|
1068
|
+
const trackedPages = [
|
|
1069
|
+
...lessons.map((lesson) => ({
|
|
1070
|
+
slug: lesson.slug,
|
|
1071
|
+
source: pageSourceDigest(
|
|
1072
|
+
[
|
|
1073
|
+
{ label: `page ${lesson.file}`, digest: digestOf(lesson.file) },
|
|
1074
|
+
...presentFiles([lesson.file.replace(/\.mdx?$/u, ".checks.yml")]).map((file) => ({
|
|
1075
|
+
label: `checks ${file}`,
|
|
1076
|
+
digest: digestOf(file)
|
|
1077
|
+
})),
|
|
1078
|
+
...presentFiles(lesson.assessments.map((id) => `content/assessments/${id}.json`)).map((file) => ({
|
|
1079
|
+
label: `assessment ${file}`,
|
|
1080
|
+
digest: digestOf(file)
|
|
1081
|
+
})),
|
|
1082
|
+
...sharedEntryInputs(lesson.notation.definitionIds),
|
|
1083
|
+
...lesson.sources.map((id) => {
|
|
1084
|
+
const file = sourceFileById.get(id);
|
|
1085
|
+
return { label: `source ${id}`, digest: file === void 0 ? "missing" : digestOf(file) };
|
|
1086
|
+
})
|
|
1087
|
+
],
|
|
1088
|
+
{ part: lesson.part, chapter: lesson.chapter, numbering: lesson.numbering }
|
|
1089
|
+
)
|
|
1090
|
+
})),
|
|
1091
|
+
// A deck beside its chapter has a version of its own, by its route, and
|
|
1092
|
+
// so has a part's deck; a slides-first lesson's deck is the lesson, above.
|
|
1093
|
+
...deckModel.decks.flatMap((deck) => {
|
|
1094
|
+
if (deck.chapter === void 0 && deck.part === void 0) return [];
|
|
1095
|
+
const page = deckPages.find((entry) => entry.deck.route === deck.slug);
|
|
1096
|
+
return [
|
|
1097
|
+
{
|
|
1098
|
+
slug: deck.slug,
|
|
1099
|
+
source: pageSourceDigest(
|
|
1100
|
+
[
|
|
1101
|
+
{ label: `page ${deck.file}`, digest: digestOf(deck.file) },
|
|
1102
|
+
...sharedEntryInputs(bundlesByLesson.get(deck.pageId)?.definitionIds ?? []),
|
|
1103
|
+
...(page === void 0 ? [] : deriveSources(page.notation.body)).map((id) => {
|
|
1104
|
+
const file = sourceFileById.get(id);
|
|
1105
|
+
return { label: `source ${id}`, digest: file === void 0 ? "missing" : digestOf(file) };
|
|
1106
|
+
})
|
|
1107
|
+
],
|
|
1108
|
+
// A part's deck shows each float it recalls as its chapter
|
|
1109
|
+
// numbers and captions it: those count as the page's too.
|
|
1110
|
+
deck.recalledFrom === void 0 ? {} : { recalls: recalledFloatFacts(deck.recalledFrom) }
|
|
1111
|
+
)
|
|
1112
|
+
}
|
|
1113
|
+
];
|
|
1114
|
+
}),
|
|
1115
|
+
...manifestParts.flatMap((part) => {
|
|
1116
|
+
if (!part.overview) return [];
|
|
1117
|
+
const slug = `${part.dir}/index`;
|
|
1118
|
+
const page = pages.find((entry) => entry.slug === slug);
|
|
1119
|
+
return [
|
|
1120
|
+
{
|
|
1121
|
+
slug,
|
|
1122
|
+
source: pageSourceDigest([
|
|
1123
|
+
{ label: `page ${part.overview.file}`, digest: digestOf(part.overview.file) },
|
|
1124
|
+
...sharedEntryInputs(page?.notation.definitionIds ?? [])
|
|
1125
|
+
])
|
|
1126
|
+
}
|
|
1127
|
+
];
|
|
1128
|
+
})
|
|
1129
|
+
];
|
|
1130
|
+
const pageVersionsRecord = nextPageVersions({
|
|
1131
|
+
previous: previousVersions.record,
|
|
1132
|
+
version: knowledge.version,
|
|
1133
|
+
unreleased: knowledge.unreleased.length > 0,
|
|
1134
|
+
pages: trackedPages
|
|
1135
|
+
});
|
|
1136
|
+
const pageVersions = {
|
|
1137
|
+
enabled: trackPageVersions,
|
|
1138
|
+
file: PAGE_VERSIONS_FILE,
|
|
1139
|
+
record: pageVersionsRecord
|
|
1140
|
+
};
|
|
1141
|
+
const sinceOfPage = (slug) => {
|
|
1142
|
+
const entry = pageVersionsRecord.pages[slug];
|
|
1143
|
+
return trackPageVersions && entry !== void 0 ? sinceOf(entry) : knowledge.version;
|
|
1144
|
+
};
|
|
879
1145
|
const enginePkg = readEnginePackage();
|
|
880
1146
|
const about = {
|
|
881
1147
|
engine: {
|
|
@@ -891,6 +1157,11 @@ async function compileManifest(courseConfig) {
|
|
|
891
1157
|
version: knowledge.version,
|
|
892
1158
|
...knowledge.latest?.date === void 0 ? {} : { date: knowledge.latest.date },
|
|
893
1159
|
notes: knowledge.latest?.notes ?? [],
|
|
1160
|
+
releases: knowledge.entries.map((entry) => ({
|
|
1161
|
+
version: entry.version,
|
|
1162
|
+
...entry.date === void 0 ? {} : { date: entry.date }
|
|
1163
|
+
})),
|
|
1164
|
+
unreleased: knowledge.unreleased.length > 0,
|
|
894
1165
|
contentTree: hashes.contentTree
|
|
895
1166
|
},
|
|
896
1167
|
authors: courseConfig.about.authors.map((author) => ({
|
|
@@ -900,6 +1171,32 @@ async function compileManifest(courseConfig) {
|
|
|
900
1171
|
disclaimer: courseConfig.about.disclaimer,
|
|
901
1172
|
...courseConfig.about.changelogHref === void 0 ? {} : { changelogHref: courseConfig.about.changelogHref }
|
|
902
1173
|
};
|
|
1174
|
+
const lessonsWithSince = lessons.map((lesson) => ({ ...lesson, since: sinceOfPage(lesson.slug) }));
|
|
1175
|
+
const decksWithSince = deckModel.decks.map((deck) => {
|
|
1176
|
+
const page = pageInputById.get(deck.pageId);
|
|
1177
|
+
return {
|
|
1178
|
+
...deck,
|
|
1179
|
+
since: sinceOfPage(deck.slug),
|
|
1180
|
+
notation: lessonNotationBundle(
|
|
1181
|
+
bundlesByLesson.get(deck.pageId),
|
|
1182
|
+
definitionsById,
|
|
1183
|
+
page === void 0 ? [] : lessonNotationResolution(page, definitionsById, availableDefinitionIds),
|
|
1184
|
+
cardsByKey,
|
|
1185
|
+
// A deck shows its lessons' symbols: the derived cards (rule N23)
|
|
1186
|
+
// its chapters' bodies and checks use ship with it, as its bundle
|
|
1187
|
+
// holds the chapters' entries.
|
|
1188
|
+
[
|
|
1189
|
+
...indexGate.derivedByLesson.get(deck.pageId) ?? [],
|
|
1190
|
+
...(page?.scopeLessonIds ?? []).flatMap((lessonId) => [
|
|
1191
|
+
...indexGate.derivedByLesson.get(lessonId) ?? [],
|
|
1192
|
+
...assessmentDerived.get(lessonId)?.values() ?? []
|
|
1193
|
+
])
|
|
1194
|
+
].filter((use, index, all) => all.findIndex((other) => other.key === use.key) === index)
|
|
1195
|
+
)
|
|
1196
|
+
};
|
|
1197
|
+
});
|
|
1198
|
+
const chapterSince = new Map(lessonsWithSince.map((lesson) => [lesson.slug, lesson.since]));
|
|
1199
|
+
mathIssues.push(...deckStaleDiagnostics(decksWithSince, chapterSince));
|
|
903
1200
|
return {
|
|
904
1201
|
schemaVersion: MANIFEST_SCHEMA_VERSION,
|
|
905
1202
|
lessonExports: normalizeLessonExports(courseConfig),
|
|
@@ -907,6 +1204,12 @@ async function compileManifest(courseConfig) {
|
|
|
907
1204
|
numbering: numberingSettings,
|
|
908
1205
|
blockLabels,
|
|
909
1206
|
cards: normalizeCards(courseConfig),
|
|
1207
|
+
sidebarMarks: normalizeSidebarMarks(courseConfig),
|
|
1208
|
+
sidebarEditions: normalizeSidebarEditions(courseConfig),
|
|
1209
|
+
readingMemory: normalizeReadingMemory(courseConfig),
|
|
1210
|
+
appearance: normalizeAppearance(courseConfig),
|
|
1211
|
+
deck: deckSettings,
|
|
1212
|
+
decks: decksWithSince,
|
|
910
1213
|
about,
|
|
911
1214
|
notation: {
|
|
912
1215
|
definitions: registry.definitions,
|
|
@@ -919,9 +1222,12 @@ async function compileManifest(courseConfig) {
|
|
|
919
1222
|
sources,
|
|
920
1223
|
tracks,
|
|
921
1224
|
abbreviations,
|
|
922
|
-
sidebar,
|
|
923
|
-
parts: manifestParts
|
|
924
|
-
|
|
1225
|
+
sidebar: sidebarWithFrames,
|
|
1226
|
+
parts: manifestParts.map(
|
|
1227
|
+
({ overview, ...part }) => overview ? { ...part, overview: { ...overview, since: sinceOfPage(`${part.dir}/index`) } } : part
|
|
1228
|
+
),
|
|
1229
|
+
lessons: lessonsWithSince,
|
|
1230
|
+
pageVersions,
|
|
925
1231
|
pages,
|
|
926
1232
|
prereqEdges,
|
|
927
1233
|
equations: {
|
|
@@ -963,7 +1269,7 @@ async function compileManifest(courseConfig) {
|
|
|
963
1269
|
checks: dropDisabled(checkValidation.diagnostics, off),
|
|
964
1270
|
examples: dropDisabled(exampleValidation.diagnostics, off),
|
|
965
1271
|
folds: dropDisabled(foldValidation.diagnostics, off),
|
|
966
|
-
knowledge: dropDisabled(knowledge.diagnostics, off),
|
|
1272
|
+
knowledge: dropDisabled([...knowledge.diagnostics, ...previousVersions.diagnostics], off),
|
|
967
1273
|
rawFloats: dropDisabled(rawFloatDiagnostics, off),
|
|
968
1274
|
config: rules.diagnostics,
|
|
969
1275
|
waivers: waiverDiagnostics
|