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