explico 0.2.0 → 0.4.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 +173 -0
- package/README.md +67 -7
- package/dist/compiler/astro.d.ts +30 -0
- package/dist/compiler/astro.js +79 -0
- package/dist/compiler/cli.d.ts +16 -0
- package/dist/compiler/cli.js +43 -9
- package/dist/compiler/collections.js +4 -1
- package/dist/compiler/course-config.d.ts +80 -4
- package/dist/compiler/course-config.js +12 -0
- package/dist/compiler/knowledge-version.d.ts +58 -0
- package/dist/compiler/knowledge-version.js +80 -0
- package/dist/compiler/lesson-derivation.d.ts +1 -1
- package/dist/compiler/lesson-derivation.js +2 -2
- package/dist/compiler/manifest.d.ts +98 -2
- package/dist/compiler/manifest.js +153 -24
- package/dist/compiler/resolution-report.d.ts +4 -0
- package/dist/reference/base-operators.d.mts +38 -0
- package/dist/reference/base-operators.mjs +103 -0
- package/dist/reference/consistency.d.ts +7 -2
- package/dist/reference/consistency.js +51 -2
- package/dist/reference/diagram-layout.d.ts +63 -0
- package/dist/reference/diagram-layout.js +122 -0
- package/dist/reference/equations-validate.d.ts +10 -0
- package/dist/reference/equations-validate.js +1 -1
- package/dist/reference/equations.d.mts +80 -13
- package/dist/reference/equations.mjs +109 -19
- package/dist/reference/figures-validate.d.ts +21 -0
- package/dist/reference/figures-validate.js +13 -0
- package/dist/reference/keyed-float-validate.d.ts +73 -0
- package/dist/reference/keyed-float-validate.js +110 -0
- package/dist/reference/keyed-jsx-floats.d.mts +64 -0
- package/dist/reference/keyed-jsx-floats.mjs +191 -0
- package/dist/reference/math-glyphs.d.mts +18 -0
- package/dist/reference/math-glyphs.mjs +92 -0
- package/dist/reference/remark-notation.d.mts +61 -0
- package/dist/reference/remark-notation.mjs +344 -10
- package/dist/reference/tables-validate.d.ts +21 -0
- package/dist/reference/tables-validate.js +13 -0
- package/dist/reference/units-vocab.js +19 -1
- package/docs/VERSIONING.md +66 -0
- package/docs/authoring/README.md +100 -0
- package/docs/authoring/agents.md +63 -0
- package/docs/authoring/migrating.md +169 -0
- package/docs/authoring/notation.md +297 -0
- package/docs/authoring/structure.md +139 -0
- package/docs/authoring/versioning.md +116 -0
- package/docs/authoring/visualizations.md +195 -0
- package/package.json +20 -5
- package/src/compiler/astro.ts +127 -0
- package/src/compiler/cli.ts +52 -7
- package/src/compiler/collections.ts +12 -3
- package/src/compiler/course-config.ts +93 -3
- package/src/compiler/knowledge-version.ts +157 -0
- package/src/compiler/lesson-derivation.ts +2 -2
- package/src/compiler/manifest.ts +320 -26
- package/src/components/CurriculumMap.astro +27 -0
- package/src/components/diagram/Diagram.astro +317 -0
- package/src/components/examples/CompactExamples.astro +1 -1
- package/src/components/figure/Figure.astro +104 -0
- package/src/components/notation/NotationLayer.astro +11 -0
- package/src/components/notation/render-notation-math.ts +13 -2
- package/src/components/reference/FloatRefLayer.astro +671 -0
- package/src/components/starlight/AboutPanel.astro +255 -0
- package/src/components/starlight/HeadingAnchorEnhancer.astro +3 -3
- package/src/components/starlight/KeyedFloatEnhancer.astro +137 -0
- package/src/components/starlight/LayoutSidebar.astro +62 -1
- package/src/components/starlight/LayoutSocialIcons.astro +12 -0
- package/src/components/starlight/LessonFooter.astro +15 -2
- package/src/components/table/Table.astro +105 -0
- package/src/reference/base-operators.mjs +103 -0
- package/src/reference/consistency.ts +83 -2
- package/src/reference/diagram-layout.ts +246 -0
- package/src/reference/equations-validate.ts +8 -1
- package/src/reference/equations.mjs +109 -19
- package/src/reference/figures-validate.ts +40 -0
- package/src/reference/keyed-float-validate.ts +210 -0
- package/src/reference/keyed-jsx-floats.mjs +191 -0
- package/src/reference/math-glyphs.mjs +92 -0
- package/src/reference/remark-notation.mjs +344 -10
- package/src/reference/tables-validate.ts +40 -0
- package/src/reference/units-vocab.ts +18 -0
- package/src/styles/global.css +244 -7
- package/src/components/starlight/EquationEnhancer.astro +0 -87
|
@@ -6,26 +6,102 @@
|
|
|
6
6
|
* data value and passes it here, typed against `CourseConfig`. A second course
|
|
7
7
|
* supplies its own value of this shape.
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* One **part** — a sidebar group, holding the chapters (lessons) whose slugs
|
|
11
|
+
* start with `dir`. A part's 1-based position in `CourseConfig.parts` is the
|
|
12
|
+
* number before the dot in every equation, table, and figure number inside it.
|
|
13
|
+
* See `docs/authoring/structure.md` for the full level taxonomy.
|
|
14
|
+
*/
|
|
15
|
+
interface CoursePart {
|
|
10
16
|
/** Lesson-slug prefix, e.g. `bonds` for `bonds/yield-to-maturity`. */
|
|
11
17
|
readonly dir: string;
|
|
12
18
|
/** Sidebar group heading. */
|
|
13
19
|
readonly label: string;
|
|
14
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* @deprecated Renamed to {@link CoursePart}. "Section" now only ever means an
|
|
23
|
+
* `##` heading inside a lesson. Removed in the next MINOR release.
|
|
24
|
+
*/
|
|
25
|
+
type CourseSection = CoursePart;
|
|
15
26
|
interface CourseConventions {
|
|
16
27
|
/** Notation key a lesson's stated sign convention must resolve to. */
|
|
17
28
|
readonly signConventionKey: string;
|
|
18
29
|
/** Competency id that also counts as declaring the cash-flow perspective. */
|
|
19
30
|
readonly cashFlowPerspectiveCompetency: string;
|
|
20
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* A course's edits to the shipped named-operator baseline (`BASE_OPERATORS`),
|
|
34
|
+
* consumed by the `operator-explained` consistency check (rule N8). An operator
|
|
35
|
+
* a lesson uses is fine when it is on the baseline plus `allow` minus `deny`;
|
|
36
|
+
* otherwise it needs a notation entry the reader can hover.
|
|
37
|
+
*
|
|
38
|
+
* Names are the KaTeX command without its backslash (`erf`, not `\erf`) for a
|
|
39
|
+
* built-in, and the verbatim body for an `\operatorname{…}` operator (`Var`).
|
|
40
|
+
*/
|
|
41
|
+
interface CourseOperators {
|
|
42
|
+
/** Operators this course also treats as universal (`Var`, `Cov`, `sgn`, …). */
|
|
43
|
+
readonly allow?: readonly string[];
|
|
44
|
+
/** Baseline operators this course wants explained anyway. */
|
|
45
|
+
readonly deny?: readonly string[];
|
|
46
|
+
}
|
|
47
|
+
/** One person or team credited for the study material. */
|
|
48
|
+
interface CourseAuthor {
|
|
49
|
+
readonly name: string;
|
|
50
|
+
/**
|
|
51
|
+
* Email, URL, or handle. Rendered in the About panel as a link when it looks
|
|
52
|
+
* like a `mailto:` or `https:` target, plain text otherwise.
|
|
53
|
+
*/
|
|
54
|
+
readonly contact?: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The reader-facing "about this material" block, surfaced by the `[?]` panel in
|
|
58
|
+
* the header (`components/starlight/AboutPanel.astro`) on every page.
|
|
59
|
+
*
|
|
60
|
+
* `version` is the course's **knowledge version** — semver over the
|
|
61
|
+
* learning-facing content, independent of the `explico` engine's own version.
|
|
62
|
+
* It must equal the newest entry in `content/CHANGELOG.md`; a mismatch is a
|
|
63
|
+
* Tier-3 `knowledge-version-mismatch` warning (rule C3, `docs/authoring/versioning.md`).
|
|
64
|
+
*/
|
|
65
|
+
interface CourseAbout {
|
|
66
|
+
/** Display name of the material. Defaults to {@link CourseConfig.title}. */
|
|
67
|
+
readonly materialName?: string;
|
|
68
|
+
/** One or two sentences on what the material covers. Defaults to {@link CourseConfig.description}. */
|
|
69
|
+
readonly summary?: string;
|
|
70
|
+
/** Knowledge version — semver; equals the latest `content/CHANGELOG.md` heading. */
|
|
71
|
+
readonly version: string;
|
|
72
|
+
/** Who authored / maintains the material. At least one entry. */
|
|
73
|
+
readonly authors: readonly CourseAuthor[];
|
|
74
|
+
/** Shown verbatim in the About panel — scope, warranty, AI-assistance note. */
|
|
75
|
+
readonly disclaimer: string;
|
|
76
|
+
/** Link to the published content changelog (repo blob, docs page, …). */
|
|
77
|
+
readonly changelogHref?: string;
|
|
78
|
+
}
|
|
21
79
|
interface CourseConfig {
|
|
22
80
|
readonly title: string;
|
|
23
81
|
readonly description: string;
|
|
24
|
-
/**
|
|
25
|
-
|
|
82
|
+
/**
|
|
83
|
+
* The course's parts (sidebar groups), in order. Exactly one of `parts` or
|
|
84
|
+
* the deprecated `sections` must be given.
|
|
85
|
+
*/
|
|
86
|
+
readonly parts?: readonly CoursePart[];
|
|
87
|
+
/**
|
|
88
|
+
* @deprecated Renamed to {@link CourseConfig.parts}. Still honoured, so a
|
|
89
|
+
* course on the old name keeps building; removed in the next MINOR release.
|
|
90
|
+
*/
|
|
91
|
+
readonly sections?: readonly CoursePart[];
|
|
26
92
|
/** Namespaces used by competency / notation `domain` fields. */
|
|
27
93
|
readonly domains: readonly string[];
|
|
28
94
|
readonly conventions: CourseConventions;
|
|
95
|
+
/** Reader-facing identity + knowledge version (the `[?]` About panel). */
|
|
96
|
+
readonly about: CourseAbout;
|
|
97
|
+
/** Edits to the shipped named-operator baseline (rule N8). Optional. */
|
|
98
|
+
readonly operators?: CourseOperators;
|
|
29
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* The course's parts, from whichever field the config uses. Throws rather than
|
|
102
|
+
* silently producing a course with no sidebar groups — a config with neither
|
|
103
|
+
* field would otherwise number every float by the `##`-section fallback.
|
|
104
|
+
*/
|
|
105
|
+
declare function coursePartsOf(config: CourseConfig): readonly CoursePart[];
|
|
30
106
|
|
|
31
|
-
export type
|
|
107
|
+
export { type CourseAbout, type CourseAuthor, type CourseConfig, type CourseConventions, type CourseOperators, type CoursePart, type CourseSection, coursePartsOf };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
function coursePartsOf(config) {
|
|
2
|
+
const parts = config.parts ?? config.sections;
|
|
3
|
+
if (!parts || parts.length === 0) {
|
|
4
|
+
throw new Error(
|
|
5
|
+
"CourseConfig needs at least one entry in `parts` (a sidebar group: { dir, label }). The old name `sections` is still accepted."
|
|
6
|
+
);
|
|
7
|
+
}
|
|
8
|
+
return parts;
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
coursePartsOf
|
|
12
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The course's **knowledge version** — semver over the learning-facing content,
|
|
3
|
+
* independent of the `explico` engine's own package version.
|
|
4
|
+
*
|
|
5
|
+
* The declared value lives in `content/course.config.ts` (`about.version`); the
|
|
6
|
+
* history and the human-readable notes live in `content/CHANGELOG.md`
|
|
7
|
+
* (Keep a Changelog shape). This module parses that file and checks the two
|
|
8
|
+
* agree — rule C3 in `docs/authoring/versioning.md`. Every finding is a Tier-3
|
|
9
|
+
* warning: `pnpm validate:content` prints it, `manifest.diagnostics.knowledge`
|
|
10
|
+
* records it, and the build still passes. The resolved entry is what the `[?]`
|
|
11
|
+
* About panel publishes to readers (`manifest.about.knowledge`).
|
|
12
|
+
*
|
|
13
|
+
* Pure: `parseKnowledgeChangelog` takes text, `resolveKnowledgeVersion` takes
|
|
14
|
+
* text + the declared version. The caller (`compileManifest`) does the file IO.
|
|
15
|
+
*/
|
|
16
|
+
/** A released entry from `content/CHANGELOG.md`, newest first in file order. */
|
|
17
|
+
interface KnowledgeChangelogEntry {
|
|
18
|
+
readonly version: string;
|
|
19
|
+
/** The `- YYYY-MM-DD` part of the heading, if present. */
|
|
20
|
+
readonly date?: string;
|
|
21
|
+
/** Bullet lines under the heading, marker stripped, in file order. */
|
|
22
|
+
readonly notes: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
type KnowledgeVersionCode = 'knowledge-changelog-missing' | 'knowledge-version-invalid' | 'knowledge-version-mismatch';
|
|
25
|
+
interface KnowledgeVersionDiagnostic {
|
|
26
|
+
readonly code: KnowledgeVersionCode;
|
|
27
|
+
/** Tier 3 — a knowledge-version drift never fails the build. */
|
|
28
|
+
readonly severity: 'warning';
|
|
29
|
+
readonly message: string;
|
|
30
|
+
readonly file?: string;
|
|
31
|
+
}
|
|
32
|
+
interface KnowledgeVersion {
|
|
33
|
+
/** The declared `about.version`, echoed for consumers. */
|
|
34
|
+
readonly version: string;
|
|
35
|
+
/** The newest released `## [x.y.z]` entry, when the changelog has one. */
|
|
36
|
+
readonly latest?: KnowledgeChangelogEntry;
|
|
37
|
+
readonly diagnostics: readonly KnowledgeVersionDiagnostic[];
|
|
38
|
+
}
|
|
39
|
+
declare function isKnowledgeSemver(value: string): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Every released entry in a `content/CHANGELOG.md` body, in file order (newest
|
|
42
|
+
* first, by Keep a Changelog convention). `## [Unreleased]` is skipped.
|
|
43
|
+
*/
|
|
44
|
+
declare function parseKnowledgeChangelog(text: string): KnowledgeChangelogEntry[];
|
|
45
|
+
/**
|
|
46
|
+
* Check the declared knowledge version against `content/CHANGELOG.md`.
|
|
47
|
+
*
|
|
48
|
+
* @param options.changelogText the file body, or `undefined` when it is absent
|
|
49
|
+
* @param options.declaredVersion `courseConfig.about.version`
|
|
50
|
+
* @param options.file repo-relative path, for diagnostic messages
|
|
51
|
+
*/
|
|
52
|
+
declare function resolveKnowledgeVersion(options: {
|
|
53
|
+
readonly changelogText: string | undefined;
|
|
54
|
+
readonly declaredVersion: string;
|
|
55
|
+
readonly file?: string;
|
|
56
|
+
}): KnowledgeVersion;
|
|
57
|
+
|
|
58
|
+
export { type KnowledgeChangelogEntry, type KnowledgeVersion, type KnowledgeVersionCode, type KnowledgeVersionDiagnostic, isKnowledgeSemver, parseKnowledgeChangelog, resolveKnowledgeVersion };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const SEMVER_RE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
2
|
+
const HEADING_RE = /^##\s+\[([^\]]+)\]\s*(?:[-–—]\s*(\S.*?))?\s*$/;
|
|
3
|
+
const BULLET_RE = /^[-*]\s+(.*\S)\s*$/;
|
|
4
|
+
function isKnowledgeSemver(value) {
|
|
5
|
+
return SEMVER_RE.test(value.trim());
|
|
6
|
+
}
|
|
7
|
+
function parseKnowledgeChangelog(text) {
|
|
8
|
+
const lines = text.split(/\r?\n/);
|
|
9
|
+
const entries = [];
|
|
10
|
+
let current = null;
|
|
11
|
+
for (const line of lines) {
|
|
12
|
+
const heading = HEADING_RE.exec(line);
|
|
13
|
+
if (heading) {
|
|
14
|
+
const token = (heading[1] ?? "").trim();
|
|
15
|
+
if (/^unreleased$/i.test(token)) {
|
|
16
|
+
current = null;
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
current = { version: token, notes: [] };
|
|
20
|
+
const date = (heading[2] ?? "").trim();
|
|
21
|
+
if (date) current.date = date;
|
|
22
|
+
entries.push(current);
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (/^#{1,3}\s/.test(line) && !line.startsWith("## [")) {
|
|
26
|
+
current = null;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (!current) continue;
|
|
30
|
+
const bullet = BULLET_RE.exec(line);
|
|
31
|
+
if (bullet) current.notes.push(bullet[1] ?? "");
|
|
32
|
+
}
|
|
33
|
+
return entries.map((entry) => ({
|
|
34
|
+
version: entry.version,
|
|
35
|
+
...entry.date === void 0 ? {} : { date: entry.date },
|
|
36
|
+
notes: [...entry.notes]
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
function resolveKnowledgeVersion(options) {
|
|
40
|
+
const { changelogText, declaredVersion } = options;
|
|
41
|
+
const file = options.file ?? "content/CHANGELOG.md";
|
|
42
|
+
const diagnostics = [];
|
|
43
|
+
const warn = (code, message) => {
|
|
44
|
+
diagnostics.push({ code, severity: "warning", message, file });
|
|
45
|
+
};
|
|
46
|
+
if (!isKnowledgeSemver(declaredVersion)) {
|
|
47
|
+
warn(
|
|
48
|
+
"knowledge-version-invalid",
|
|
49
|
+
`about.version ${JSON.stringify(declaredVersion)} in content/course.config.ts is not a semver \`x.y.z\` string.`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
if (changelogText === void 0) {
|
|
53
|
+
warn(
|
|
54
|
+
"knowledge-changelog-missing",
|
|
55
|
+
`No ${file}. Add a Keep a Changelog file whose newest \`## [x.y.z]\` heading is ${JSON.stringify(declaredVersion)} (rule C1).`
|
|
56
|
+
);
|
|
57
|
+
return { version: declaredVersion, diagnostics };
|
|
58
|
+
}
|
|
59
|
+
const entries = parseKnowledgeChangelog(changelogText);
|
|
60
|
+
const latest = entries[0];
|
|
61
|
+
if (!latest) {
|
|
62
|
+
warn(
|
|
63
|
+
"knowledge-changelog-missing",
|
|
64
|
+
`${file} has no released \`## [x.y.z]\` entry \u2014 only \`## [Unreleased]\`. Cut a release: move it to \`## [${declaredVersion}] - <date>\` (rule C4).`
|
|
65
|
+
);
|
|
66
|
+
return { version: declaredVersion, diagnostics };
|
|
67
|
+
}
|
|
68
|
+
if (isKnowledgeSemver(declaredVersion) && latest.version !== declaredVersion) {
|
|
69
|
+
warn(
|
|
70
|
+
"knowledge-version-mismatch",
|
|
71
|
+
`about.version is ${JSON.stringify(declaredVersion)} but the newest ${file} entry is ${JSON.stringify(latest.version)}. Bump one to match the other (rule C3).`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
return { version: declaredVersion, latest, diagnostics };
|
|
75
|
+
}
|
|
76
|
+
export {
|
|
77
|
+
isKnowledgeSemver,
|
|
78
|
+
parseKnowledgeChangelog,
|
|
79
|
+
resolveKnowledgeVersion
|
|
80
|
+
};
|
|
@@ -84,6 +84,6 @@ type SidebarGroup = {
|
|
|
84
84
|
* merged track order (ties broken by slug), then the static Reference group.
|
|
85
85
|
* Replaces seven `autogenerate` blocks that read an authored `sidebar.order`.
|
|
86
86
|
*/
|
|
87
|
-
declare function buildSidebar(tracks: readonly TrackLike[], lessonSlugs: readonly string[],
|
|
87
|
+
declare function buildSidebar(tracks: readonly TrackLike[], lessonSlugs: readonly string[], parts: readonly SidebarSection[]): SidebarGroup[];
|
|
88
88
|
|
|
89
89
|
export { type SidebarGroup, type SidebarSection, buildSidebar, citedSourceIds, deriveRequires, deriveSources, isLessonSlug, lessonIdFromSlug, mergeTrackOrder, parseCheckList };
|
|
@@ -59,12 +59,12 @@ function mergeTrackOrder(tracks) {
|
|
|
59
59
|
}
|
|
60
60
|
return ordered;
|
|
61
61
|
}
|
|
62
|
-
function buildSidebar(tracks, lessonSlugs,
|
|
62
|
+
function buildSidebar(tracks, lessonSlugs, parts) {
|
|
63
63
|
const rank = new Map(
|
|
64
64
|
mergeTrackOrder(tracks).map((lessonId, index) => [lessonId, index])
|
|
65
65
|
);
|
|
66
66
|
const positionOf = (slug) => rank.get(lessonIdFromSlug(slug)) ?? Number.POSITIVE_INFINITY;
|
|
67
|
-
const groups =
|
|
67
|
+
const groups = parts.map(({ dir, label }) => ({
|
|
68
68
|
label,
|
|
69
69
|
items: lessonSlugs.filter((slug) => slug.startsWith(`${dir}/`)).sort(
|
|
70
70
|
(left, right) => positionOf(left) - positionOf(right) || left.localeCompare(right)
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { CurriculumIssue } from '../curriculum/validation.js';
|
|
2
2
|
import { ConsistencyDiagnostic } from '../reference/consistency.js';
|
|
3
3
|
import { EquationLabelRecord, EquationDiagnostic } from '../reference/equations-validate.js';
|
|
4
|
+
import { TableLabelRecord, TableDiagnostic } from '../reference/tables-validate.js';
|
|
5
|
+
import { FigureLabelRecord, FigureDiagnostic } from '../reference/figures-validate.js';
|
|
4
6
|
import { MathGateDiagnostic } from '../reference/gate-math.js';
|
|
5
7
|
import { GlyphScopeEntry } from '../reference/gloss.js';
|
|
6
8
|
import { NotationDefinitionRecord, NotationPageBundle, NotationBacklink, NotationDiagnostic, EditorialStatus, NotationGlossEntry } from '../reference/types.js';
|
|
7
9
|
import { CourseConfig } from './course-config.js';
|
|
10
|
+
import { KnowledgeVersionDiagnostic } from './knowledge-version.js';
|
|
8
11
|
import { SidebarGroup } from './lesson-derivation.js';
|
|
9
12
|
import './collections.js';
|
|
10
13
|
import '../reference/lint-ignore.js';
|
|
14
|
+
import '../reference/keyed-float-validate.js';
|
|
11
15
|
|
|
12
16
|
/**
|
|
13
17
|
* The one compiler manifest (Phase D5).
|
|
@@ -45,8 +49,20 @@ import '../reference/lint-ignore.js';
|
|
|
45
49
|
* `diagnostics.consistency` (Tier-3 corpus checks).
|
|
46
50
|
* v3 (D7): `equations` (labelled display equations + cross-page number table),
|
|
47
51
|
* `lessons[].equations`, and `diagnostics.equations`.
|
|
52
|
+
* v4 (F-tables-figures): `tables`/`figures` (same shape as `equations`, for
|
|
53
|
+
* `<Table>`/`<Figure>`), `lessons[].tables`/`lessons[].figures`, and
|
|
54
|
+
* `diagnostics.tables`/`diagnostics.figures`.
|
|
55
|
+
* v5 (about): `about` (engine identity from `explico`'s `package.json`, the
|
|
56
|
+
* course's reader-facing `about` block, and the knowledge version resolved
|
|
57
|
+
* against `content/CHANGELOG.md`) and `diagnostics.knowledge`.
|
|
58
|
+
* v6 (chapter numbering): `lessons[].chapter` — the lesson's 1-based course
|
|
59
|
+
* ordinal, the chapter in every equation/table/figure number (`(2.1)`).
|
|
60
|
+
* v7 (part numbering): `lessons[].part` (the sidebar group's 1-based ordinal,
|
|
61
|
+
* now the number before the dot), `lessons[].chapter` redefined as the
|
|
62
|
+
* lesson's ordinal *within its part*, and `lessons[].numbering` — the
|
|
63
|
+
* per-kind offsets that make `n` run continuously across a part.
|
|
48
64
|
*/
|
|
49
|
-
declare const MANIFEST_SCHEMA_VERSION =
|
|
65
|
+
declare const MANIFEST_SCHEMA_VERSION = 7;
|
|
50
66
|
declare const MANIFEST_PATH: string;
|
|
51
67
|
interface ManifestCitation {
|
|
52
68
|
readonly id: string;
|
|
@@ -95,6 +111,29 @@ interface ManifestLesson {
|
|
|
95
111
|
readonly id: string;
|
|
96
112
|
/** Docs-loader slug, e.g. `bonds/price-yield-relationship`. */
|
|
97
113
|
readonly slug: string;
|
|
114
|
+
/**
|
|
115
|
+
* The 1-based ordinal of the **part** this lesson sits in — its sidebar
|
|
116
|
+
* group's position in `courseConfig.parts`. It is the number before the dot
|
|
117
|
+
* in every equation, table, and figure number on the page: `(2.1)` is the
|
|
118
|
+
* first equation of part 2. See `docs/authoring/structure.md`.
|
|
119
|
+
*/
|
|
120
|
+
readonly part: number;
|
|
121
|
+
/**
|
|
122
|
+
* The lesson's 1-based ordinal **within its part** (merged track order, then
|
|
123
|
+
* any unranked lessons by slug) — its chapter number. This orders the
|
|
124
|
+
* sidebar and the reading path; it does not appear in a float's number.
|
|
125
|
+
*/
|
|
126
|
+
readonly chapter: number;
|
|
127
|
+
/**
|
|
128
|
+
* How many floats of each kind the earlier lessons of this part already
|
|
129
|
+
* used. The lesson's own floats continue from here, so a part's sequence
|
|
130
|
+
* runs unbroken across its chapters instead of restarting on every page.
|
|
131
|
+
*/
|
|
132
|
+
readonly numbering: {
|
|
133
|
+
readonly equations: number;
|
|
134
|
+
readonly tables: number;
|
|
135
|
+
readonly figures: number;
|
|
136
|
+
};
|
|
98
137
|
readonly file: string;
|
|
99
138
|
readonly title: string;
|
|
100
139
|
readonly description: string;
|
|
@@ -113,6 +152,16 @@ interface ManifestLesson {
|
|
|
113
152
|
readonly key: string;
|
|
114
153
|
readonly number: string;
|
|
115
154
|
}[];
|
|
155
|
+
/** Keyed `<Table>` elements in appearance order. */
|
|
156
|
+
readonly tables: readonly {
|
|
157
|
+
readonly key: string;
|
|
158
|
+
readonly number: string;
|
|
159
|
+
}[];
|
|
160
|
+
/** Keyed `<Figure>` elements in appearance order. */
|
|
161
|
+
readonly figures: readonly {
|
|
162
|
+
readonly key: string;
|
|
163
|
+
readonly number: string;
|
|
164
|
+
}[];
|
|
116
165
|
readonly notation: {
|
|
117
166
|
readonly bindings: readonly {
|
|
118
167
|
readonly key: string;
|
|
@@ -124,8 +173,39 @@ interface ManifestLesson {
|
|
|
124
173
|
readonly resolution: readonly ManifestNotationResolution[];
|
|
125
174
|
};
|
|
126
175
|
}
|
|
176
|
+
/** The reader-facing "about this material" bundle — the `[?]` panel's data. */
|
|
177
|
+
interface ManifestAbout {
|
|
178
|
+
/** `explico`'s own identity, from its `package.json` (the version's golden source). */
|
|
179
|
+
readonly engine: {
|
|
180
|
+
readonly name: string;
|
|
181
|
+
readonly version: string;
|
|
182
|
+
readonly homepage?: string;
|
|
183
|
+
};
|
|
184
|
+
readonly material: {
|
|
185
|
+
readonly name: string;
|
|
186
|
+
readonly summary: string;
|
|
187
|
+
};
|
|
188
|
+
/** The course's knowledge version — semver over the content, engine-independent. */
|
|
189
|
+
readonly knowledge: {
|
|
190
|
+
readonly version: string;
|
|
191
|
+
/** Date of the newest `content/CHANGELOG.md` entry, if it has one. */
|
|
192
|
+
readonly date?: string;
|
|
193
|
+
/** Bullet notes from that entry. */
|
|
194
|
+
readonly notes: readonly string[];
|
|
195
|
+
/** Content fingerprint at compile time — ties the shown version to a build. */
|
|
196
|
+
readonly contentTree: string;
|
|
197
|
+
};
|
|
198
|
+
readonly authors: readonly {
|
|
199
|
+
readonly name: string;
|
|
200
|
+
readonly contact?: string;
|
|
201
|
+
}[];
|
|
202
|
+
readonly disclaimer: string;
|
|
203
|
+
readonly changelogHref?: string;
|
|
204
|
+
}
|
|
127
205
|
interface Manifest {
|
|
128
206
|
readonly schemaVersion: number;
|
|
207
|
+
/** Reader-facing identity + versions (the `[?]` About panel). */
|
|
208
|
+
readonly about: ManifestAbout;
|
|
129
209
|
readonly notation: {
|
|
130
210
|
readonly definitions: readonly NotationDefinitionRecord[];
|
|
131
211
|
readonly bundles: readonly NotationPageBundle[];
|
|
@@ -147,6 +227,16 @@ interface Manifest {
|
|
|
147
227
|
/** `slug -> { eqKey: number }` — passed to `remarkNotation` for `[[slug#eq:key]]`. */
|
|
148
228
|
readonly numbersBySlug: Record<string, Record<string, string>>;
|
|
149
229
|
};
|
|
230
|
+
/** Keyed-float identity for `<Table>` — same shape as `equations`. */
|
|
231
|
+
readonly tables: {
|
|
232
|
+
readonly labels: readonly TableLabelRecord[];
|
|
233
|
+
readonly numbersBySlug: Record<string, Record<string, string>>;
|
|
234
|
+
};
|
|
235
|
+
/** Keyed-float identity for `<Figure>` — same shape as `equations`. */
|
|
236
|
+
readonly figures: {
|
|
237
|
+
readonly labels: readonly FigureLabelRecord[];
|
|
238
|
+
readonly numbersBySlug: Record<string, Record<string, string>>;
|
|
239
|
+
};
|
|
150
240
|
readonly diagnostics: {
|
|
151
241
|
readonly curriculum: readonly CurriculumIssue[];
|
|
152
242
|
readonly notation: readonly NotationDiagnostic[];
|
|
@@ -154,8 +244,14 @@ interface Manifest {
|
|
|
154
244
|
readonly math: readonly MathGateDiagnostic[];
|
|
155
245
|
/** Tier-3 corpus consistency checks (D6). Warnings only. */
|
|
156
246
|
readonly consistency: readonly ConsistencyDiagnostic[];
|
|
247
|
+
/** Knowledge-version checks (C3): `about.version` vs `content/CHANGELOG.md`. Warnings only. */
|
|
248
|
+
readonly knowledge: readonly KnowledgeVersionDiagnostic[];
|
|
157
249
|
/** Equation-identity checks (D7): `eq-duplicate-key`, `eq-ref-resolves` (error); `eq-key-unused` (warning). */
|
|
158
250
|
readonly equations: readonly EquationDiagnostic[];
|
|
251
|
+
/** `<Table>` identity checks (F-tables-figures) — same codes, `tab-` prefixed. */
|
|
252
|
+
readonly tables: readonly TableDiagnostic[];
|
|
253
|
+
/** `<Figure>` identity checks (F-tables-figures) — same codes, `fig-` prefixed. */
|
|
254
|
+
readonly figures: readonly FigureDiagnostic[];
|
|
159
255
|
};
|
|
160
256
|
readonly hashes: {
|
|
161
257
|
/** `sha256` of every content source file, keyed by repo-relative path. */
|
|
@@ -184,4 +280,4 @@ declare function readManifestSync(): Manifest;
|
|
|
184
280
|
*/
|
|
185
281
|
declare function loadManifest(courseConfig?: CourseConfig): Promise<Manifest>;
|
|
186
282
|
|
|
187
|
-
export { MANIFEST_PATH, MANIFEST_SCHEMA_VERSION, type Manifest, type ManifestCitation, type ManifestLesson, type ManifestLessonNotation, type ManifestNotationResolution, type PrereqEdge, compileManifest, loadManifest, readManifestSync, serializeManifest, writeManifest };
|
|
283
|
+
export { MANIFEST_PATH, MANIFEST_SCHEMA_VERSION, type Manifest, type ManifestAbout, type ManifestCitation, type ManifestLesson, type ManifestLessonNotation, type ManifestNotationResolution, type PrereqEdge, compileManifest, loadManifest, readManifestSync, serializeManifest, writeManifest };
|