explico 0.4.0 → 0.6.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 +382 -1
- package/README.md +103 -8
- package/dist/compiler/astro.d.ts +9 -1
- package/dist/compiler/astro.js +182 -3
- package/dist/compiler/cli.d.ts +13 -0
- package/dist/compiler/cli.js +28 -4
- package/dist/compiler/collections.d.ts +3 -2
- package/dist/compiler/collections.js +28 -1
- package/dist/compiler/course-config.d.ts +88 -1
- package/dist/compiler/course-config.js +35 -1
- package/dist/compiler/exports/standalone-html.d.ts +34 -0
- package/dist/compiler/exports/standalone-html.js +803 -0
- package/dist/compiler/manifest.d.ts +98 -6
- package/dist/compiler/manifest.js +154 -17
- package/dist/compiler/resolution-report.d.ts +4 -0
- package/dist/reference/base-abbreviations.d.mts +30 -0
- package/dist/reference/base-abbreviations.mjs +60 -0
- package/dist/reference/base-operators.d.mts +15 -0
- package/dist/reference/base-operators.mjs +40 -0
- package/dist/reference/base-roman-labels.d.mts +35 -0
- package/dist/reference/base-roman-labels.mjs +43 -0
- package/dist/reference/consistency.d.ts +8 -2
- package/dist/reference/consistency.js +50 -3
- package/dist/reference/diagrams-validate.d.ts +21 -0
- package/dist/reference/diagrams-validate.js +13 -0
- package/dist/reference/equations.d.mts +10 -15
- package/dist/reference/equations.mjs +67 -14
- package/dist/reference/gate-abbreviations.d.ts +17 -0
- package/dist/reference/gate-abbreviations.js +64 -0
- package/dist/reference/gate-heading-length.d.ts +12 -0
- package/dist/reference/gate-heading-length.js +79 -0
- package/dist/reference/gate-math.d.ts +32 -5
- package/dist/reference/gate-math.js +6 -2
- package/dist/reference/gate-prose-notation.d.ts +60 -0
- package/dist/reference/gate-prose-notation.js +125 -0
- package/dist/reference/keyed-float-validate.d.ts +5 -5
- package/dist/reference/keyed-jsx-floats.d.mts +7 -12
- package/dist/reference/keyed-jsx-floats.mjs +50 -25
- package/dist/reference/knowledge-checks-validate.d.ts +35 -0
- package/dist/reference/knowledge-checks-validate.js +78 -0
- package/dist/reference/knowledge-checks.d.mts +25 -0
- package/dist/reference/knowledge-checks.mjs +45 -0
- package/dist/reference/lab-math-scope.d.ts +9 -1
- package/dist/reference/lab-math-scope.js +32 -4
- package/dist/reference/math-glyphs.d.mts +42 -0
- package/dist/reference/math-glyphs.mjs +548 -40
- package/dist/reference/mdx-attributes.d.mts +13 -0
- package/dist/reference/mdx-attributes.mjs +38 -0
- package/dist/reference/mixed-content.d.ts +17 -0
- package/dist/reference/mixed-content.js +29 -0
- package/dist/reference/page-notation.d.ts +52 -0
- package/dist/reference/page-notation.js +171 -0
- package/dist/reference/raw-floats-validate.d.ts +18 -0
- package/dist/reference/raw-floats-validate.js +53 -0
- package/dist/reference/raw-floats.d.mts +18 -0
- package/dist/reference/raw-floats.mjs +129 -0
- package/dist/reference/rehype-heading-anchors.d.mts +1 -1
- package/dist/reference/rehype-heading-anchors.mjs +107 -1
- package/dist/reference/rehype-table-header-labels.d.mts +26 -0
- package/dist/reference/rehype-table-header-labels.mjs +152 -0
- package/dist/reference/remark-abbreviations.d.mts +7 -0
- package/dist/reference/remark-abbreviations.mjs +174 -0
- package/dist/reference/remark-citation.d.mts +5 -1
- package/dist/reference/remark-citation.mjs +0 -0
- package/dist/reference/remark-memo.d.mts +16 -0
- package/dist/reference/remark-memo.mjs +339 -0
- package/dist/reference/remark-notation.d.mts +57 -9
- package/dist/reference/remark-notation.mjs +354 -42
- package/dist/reference/remark-short-note.d.mts +4 -0
- package/dist/reference/remark-short-note.mjs +237 -0
- package/dist/reference/types.d.ts +16 -1
- package/dist/reference/units-vocab.js +4 -0
- package/docs/VERSIONING.md +53 -4
- package/docs/authoring/README.md +10 -0
- package/docs/authoring/agents.md +17 -2
- package/docs/authoring/components.md +138 -0
- package/docs/authoring/migrating.md +275 -7
- package/docs/authoring/notation.md +615 -1
- package/docs/authoring/structure-rules.md +69 -0
- package/docs/authoring/structure.md +120 -8
- package/docs/authoring/visualizations.md +36 -3
- package/package.json +5 -2
- package/src/compiler/astro.ts +208 -3
- package/src/compiler/cli.ts +29 -2
- package/src/compiler/collections.ts +45 -4
- package/src/compiler/course-config.ts +132 -0
- package/src/compiler/exports/standalone-html.ts +963 -0
- package/src/compiler/manifest.ts +281 -22
- package/src/components/HoverPanel.astro +45 -4
- package/src/components/abbreviation/AbbreviationGlossary.astro +70 -0
- package/src/components/abbreviation/AbbreviationLayer.astro +127 -0
- package/src/components/assessments/AssessmentRunner.tsx +52 -17
- package/src/components/assessments/AssessmentSet.astro +98 -14
- package/src/components/assessments/RenderedContent.tsx +55 -0
- package/src/components/assessments/assessment-randomization.ts +16 -0
- package/src/components/diagram/Diagram.astro +409 -103
- package/src/components/disclosure/hover-preview.ts +202 -0
- package/src/components/disclosure/persisted-disclosure.ts +66 -0
- package/src/components/examples/CompactExamples.astro +2 -0
- package/src/components/figure/Figure.astro +279 -10
- package/src/components/memo/Memo.astro +453 -0
- package/src/components/memo/ShortNote.astro +223 -0
- package/src/components/notation/NotationFormula.astro +18 -1
- package/src/components/notation/NotationLayer.astro +260 -83
- package/src/components/notation/render-notation-math.ts +39 -2
- package/src/components/notation/safe-math-to-react.ts +50 -0
- package/src/components/reference/FloatRefLayer.astro +233 -15
- package/src/components/starlight/CollapsibleSections.astro +461 -0
- package/src/components/starlight/DiagramEnhancer.astro +385 -0
- package/src/components/starlight/HeadingAnchorEnhancer.astro +5 -17
- package/src/components/starlight/KeyedFloatEnhancer.astro +81 -3
- package/src/components/starlight/LayoutHeader.astro +50 -0
- package/src/components/starlight/LayoutSocialIcons.astro +41 -2
- package/src/components/starlight/LessonExportActions.astro +436 -0
- package/src/components/starlight/LessonFooter.astro +30 -3
- package/src/components/starlight/section-parts.ts +31 -0
- package/src/components/table/Table.astro +293 -7
- package/src/components/table/TableOverflowExpander.astro +489 -0
- package/src/content-config.ts +36 -1
- package/src/reference/base-abbreviations.mjs +60 -0
- package/src/reference/base-operators.mjs +40 -0
- package/src/reference/base-roman-labels.mjs +43 -0
- package/src/reference/consistency.ts +73 -2
- package/src/reference/diagrams-validate.ts +40 -0
- package/src/reference/equations.mjs +67 -14
- package/src/reference/gate-abbreviations.ts +128 -0
- package/src/reference/gate-heading-length.ts +131 -0
- package/src/reference/gate-math.ts +32 -7
- package/src/reference/gate-prose-notation.ts +224 -0
- package/src/reference/keyed-float-validate.ts +5 -5
- package/src/reference/keyed-jsx-floats.mjs +50 -25
- package/src/reference/knowledge-checks-validate.ts +130 -0
- package/src/reference/knowledge-checks.mjs +45 -0
- package/src/reference/lab-math-scope.ts +45 -3
- package/src/reference/math-glyphs.mjs +548 -40
- package/src/reference/mdx-attributes.mjs +38 -0
- package/src/reference/mixed-content.ts +69 -0
- package/src/reference/page-notation.ts +252 -0
- package/src/reference/raw-floats-validate.ts +103 -0
- package/src/reference/raw-floats.mjs +129 -0
- package/src/reference/rehype-heading-anchors.mjs +107 -1
- package/src/reference/rehype-table-header-labels.mjs +152 -0
- package/src/reference/remark-abbreviations.mjs +174 -0
- package/src/reference/remark-citation.mjs +0 -0
- package/src/reference/remark-memo.mjs +339 -0
- package/src/reference/remark-notation.mjs +354 -42
- package/src/reference/remark-short-note.mjs +237 -0
- package/src/reference/types.ts +16 -0
- package/src/reference/units-vocab.ts +4 -0
- package/src/styles/global.css +996 -50
|
@@ -24,6 +24,7 @@ import type {
|
|
|
24
24
|
TrackDefinition,
|
|
25
25
|
} from '../curriculum/validation';
|
|
26
26
|
import type {
|
|
27
|
+
AbbreviationDefinitionInput,
|
|
27
28
|
EditorialStatus,
|
|
28
29
|
LocalNotationDefinitionInput,
|
|
29
30
|
NotationAlignment,
|
|
@@ -37,6 +38,8 @@ import type {
|
|
|
37
38
|
import { isSubstantiveMeaning } from '../reference/prose';
|
|
38
39
|
import { parseEquationRef } from '../reference/equations.mjs';
|
|
39
40
|
import { parseKeyedFloatRef } from '../reference/keyed-jsx-floats.mjs';
|
|
41
|
+
import { parseKnowledgeCheckRef } from '../reference/knowledge-checks.mjs';
|
|
42
|
+
import { parseMemoRef } from '../reference/remark-memo.mjs';
|
|
40
43
|
import { resolveLabel } from '../reference/label';
|
|
41
44
|
import { resolveGlosses } from '../reference/gloss';
|
|
42
45
|
import {
|
|
@@ -231,13 +234,17 @@ export function extractNotationReferences(
|
|
|
231
234
|
for (const match of searchable.matchAll(pattern)) {
|
|
232
235
|
const key = (match[1] ?? '').trim();
|
|
233
236
|
// `[[eq-key]]` / `[[slug#eq-key]]` are equation references (D7), and
|
|
234
|
-
// `[[tab-key]]`/`[[fig-key]]` (and their cross-page forms)
|
|
235
|
-
//
|
|
236
|
-
//
|
|
237
|
+
// `[[tab-key]]`/`[[fig-key]]`/`[[dia-key]]` (and their cross-page forms)
|
|
238
|
+
// are keyed-float references, `[[check-key]]` targets a lesson's
|
|
239
|
+
// assessment list, and `[[memo-key]]` is a page-local memo reference —
|
|
240
|
+
// all resolved by the remark pass and the manifest, not notation keys.
|
|
237
241
|
if (
|
|
238
242
|
parseEquationRef(key) ||
|
|
239
243
|
parseKeyedFloatRef(key, { prefix: 'tab' }) ||
|
|
240
|
-
parseKeyedFloatRef(key, { prefix: 'fig' })
|
|
244
|
+
parseKeyedFloatRef(key, { prefix: 'fig' }) ||
|
|
245
|
+
parseKeyedFloatRef(key, { prefix: 'dia' }) ||
|
|
246
|
+
parseKnowledgeCheckRef(key) ||
|
|
247
|
+
parseMemoRef(key)
|
|
241
248
|
) {
|
|
242
249
|
continue;
|
|
243
250
|
}
|
|
@@ -438,6 +445,40 @@ function sharedNotationEntries(): SharedNotationDefinitionInput[] {
|
|
|
438
445
|
});
|
|
439
446
|
}
|
|
440
447
|
|
|
448
|
+
/**
|
|
449
|
+
* Abbreviations table (rule N14) — a lighter tier than a notation card, read
|
|
450
|
+
* straight off disk the same way `sharedNotationEntries` reads `notation/`.
|
|
451
|
+
* The directory is optional: a course that never uses this feature need not
|
|
452
|
+
* create an empty `content/abbreviations/`.
|
|
453
|
+
*/
|
|
454
|
+
function abbreviationEntries(): AbbreviationDefinitionInput[] {
|
|
455
|
+
const directory = join(CONTENT_ROOT, 'abbreviations');
|
|
456
|
+
if (!existsSync(directory)) return [];
|
|
457
|
+
return filesBelow(directory, ['.md']).map((path) => {
|
|
458
|
+
const { file, data } = parseDocument(path);
|
|
459
|
+
const key = string(data.key, `${file} key`);
|
|
460
|
+
const filenameKey = basename(path, '.md');
|
|
461
|
+
if (key !== filenameKey) {
|
|
462
|
+
throw new Error(`${file} declares key ${key}; expected ${filenameKey}`);
|
|
463
|
+
}
|
|
464
|
+
const domain = optionalString(data.domain, `${file} domain`);
|
|
465
|
+
return {
|
|
466
|
+
key,
|
|
467
|
+
abbr: string(data.abbr, `${file} abbr`),
|
|
468
|
+
expansion: meaningText(data.expansion, `${file} expansion`),
|
|
469
|
+
aliases: strings(data.aliases, `${file} aliases`),
|
|
470
|
+
source: { file },
|
|
471
|
+
...(domain === undefined ? {} : { domain }),
|
|
472
|
+
};
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
export async function loadAbbreviationRegistryInput(): Promise<
|
|
477
|
+
readonly AbbreviationDefinitionInput[]
|
|
478
|
+
> {
|
|
479
|
+
return abbreviationEntries();
|
|
480
|
+
}
|
|
481
|
+
|
|
441
482
|
function notationLessonEntries(): NotationLessonInput[] {
|
|
442
483
|
const lessons: NotationLessonInput[] = [];
|
|
443
484
|
for (const path of filesBelow(join(CONTENT_ROOT, 'docs'), ['.md', '.mdx'])) {
|
|
@@ -49,6 +49,39 @@ export interface CourseOperators {
|
|
|
49
49
|
readonly deny?: readonly string[];
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
/**
|
|
53
|
+
* A course's edits to the shipped roman-label baseline (`BASE_ROMAN_LABELS`),
|
|
54
|
+
* consumed by the `roman-label-explained` consistency check (rule N10). A
|
|
55
|
+
* `\mathrm{…}` multi-letter label a lesson uses is fine when it is on the
|
|
56
|
+
* baseline plus `allow` minus `deny`; otherwise it needs a notation entry the
|
|
57
|
+
* reader can hover. Same shape as {@link CourseOperators}, one level down:
|
|
58
|
+
* this governs `\mathrm{KE}`-style labels, not `\operatorname{Var}`-style
|
|
59
|
+
* operators.
|
|
60
|
+
*/
|
|
61
|
+
export interface CourseRomanLabels {
|
|
62
|
+
/** Labels this course also treats as universal qualifiers (`eff`, `net`, …). */
|
|
63
|
+
readonly allow?: readonly string[];
|
|
64
|
+
/** Baseline labels this course wants explained anyway. */
|
|
65
|
+
readonly deny?: readonly string[];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* A course's edits to the shipped abbreviation baseline (`BASE_ABBREVIATIONS`),
|
|
70
|
+
* consumed by the `abbreviation-explained` gate (rule N14). An abbreviation-
|
|
71
|
+
* shaped token — an all-caps acronym or a dotted form like `w.r.t.` — a
|
|
72
|
+
* lesson uses in prose is fine when it is on the baseline plus `allow` minus
|
|
73
|
+
* `deny`; otherwise it needs an entry in the `abbreviations` content
|
|
74
|
+
* collection, or — if it also names a math quantity — a notation entry the
|
|
75
|
+
* reader can hover. Same shape as {@link CourseOperators} / {@link
|
|
76
|
+
* CourseRomanLabels}.
|
|
77
|
+
*/
|
|
78
|
+
export interface CourseAbbreviations {
|
|
79
|
+
/** Abbreviations this course also treats as universal (`GDP`, `CPU`, …). */
|
|
80
|
+
readonly allow?: readonly string[];
|
|
81
|
+
/** Baseline abbreviations this course wants explained anyway. */
|
|
82
|
+
readonly deny?: readonly string[];
|
|
83
|
+
}
|
|
84
|
+
|
|
52
85
|
/** One person or team credited for the study material. */
|
|
53
86
|
export interface CourseAuthor {
|
|
54
87
|
readonly name: string;
|
|
@@ -83,6 +116,63 @@ export interface CourseAbout {
|
|
|
83
116
|
readonly changelogHref?: string;
|
|
84
117
|
}
|
|
85
118
|
|
|
119
|
+
/**
|
|
120
|
+
* A course's chosen initial open/closed state for the engine's own built-in
|
|
121
|
+
* collapsible sections — the "Page notation" panel (`NotationLayer.astro`)
|
|
122
|
+
* and the generated "References" section (`remark-citation.mjs`). Each is
|
|
123
|
+
* independent of `defaultCollapsible.sections`/`.subsections` (an author's
|
|
124
|
+
* own `##` headings): both of these are engine-authored, not written by a
|
|
125
|
+
* lesson, so they need their own default rather than inheriting the site's
|
|
126
|
+
* general heading default.
|
|
127
|
+
*
|
|
128
|
+
* `true` starts open, `false` (or omitted) starts closed — the engine's own
|
|
129
|
+
* default is closed either way, matching a long panel a reader usually
|
|
130
|
+
* doesn't need open on arrival.
|
|
131
|
+
*/
|
|
132
|
+
export interface CourseDisclosureDefaults {
|
|
133
|
+
/** Initial state of the "Page notation" panel. Default: closed. */
|
|
134
|
+
readonly notation?: boolean;
|
|
135
|
+
/** Initial state of the generated "References" section. Default: closed. */
|
|
136
|
+
readonly references?: boolean;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** The stable, non-optional form `NormalizedLessonExports` mirrors. */
|
|
140
|
+
export interface NormalizedDisclosureDefaults {
|
|
141
|
+
readonly notation: boolean;
|
|
142
|
+
readonly references: boolean;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Validate and canonicalize `CourseConfig.disclosureDefaults`. Absent (or
|
|
146
|
+
* an absent sub-field) resolves to closed, the engine's own default. */
|
|
147
|
+
export function normalizeDisclosureDefaults(
|
|
148
|
+
config: CourseConfig,
|
|
149
|
+
): NormalizedDisclosureDefaults {
|
|
150
|
+
return {
|
|
151
|
+
notation: config.disclosureDefaults?.notation === true,
|
|
152
|
+
references: config.disclosureDefaults?.references === true,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Optional, build-time lesson artifacts exposed to readers. */
|
|
157
|
+
export interface LessonExportsConfig {
|
|
158
|
+
/** Emit one self-contained, offline-capable HTML file per lesson. */
|
|
159
|
+
readonly standaloneHtml?: boolean;
|
|
160
|
+
/** Offer the browser's native print dialog with explico's lesson print layout. */
|
|
161
|
+
readonly print?: boolean;
|
|
162
|
+
/**
|
|
163
|
+
* Published course root used for links that intentionally leave the exported
|
|
164
|
+
* lesson. Required at export time when such a link is present.
|
|
165
|
+
*/
|
|
166
|
+
readonly canonicalBaseUrl?: string;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** The stable, non-optional export settings carried by the manifest. */
|
|
170
|
+
export interface NormalizedLessonExports {
|
|
171
|
+
readonly standaloneHtml: boolean;
|
|
172
|
+
readonly print: boolean;
|
|
173
|
+
readonly canonicalBaseUrl?: string;
|
|
174
|
+
}
|
|
175
|
+
|
|
86
176
|
export interface CourseConfig {
|
|
87
177
|
readonly title: string;
|
|
88
178
|
readonly description: string;
|
|
@@ -103,6 +193,48 @@ export interface CourseConfig {
|
|
|
103
193
|
readonly about: CourseAbout;
|
|
104
194
|
/** Edits to the shipped named-operator baseline (rule N8). Optional. */
|
|
105
195
|
readonly operators?: CourseOperators;
|
|
196
|
+
/** Edits to the shipped roman-label baseline (rule N10). Optional. */
|
|
197
|
+
readonly romanLabels?: CourseRomanLabels;
|
|
198
|
+
/** Edits to the shipped abbreviation baseline (rule N14). Optional. */
|
|
199
|
+
readonly abbreviations?: CourseAbbreviations;
|
|
200
|
+
/** Per-lesson export actions and downloadable artifacts. Disabled when omitted. */
|
|
201
|
+
readonly lessonExports?: LessonExportsConfig;
|
|
202
|
+
/** Initial open/closed state for the engine's own built-in collapsible
|
|
203
|
+
* sections ("Page notation", "References"). Closed when omitted. */
|
|
204
|
+
readonly disclosureDefaults?: CourseDisclosureDefaults;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** Validate and canonicalize the build-facing lesson-export configuration. */
|
|
208
|
+
export function normalizeLessonExports(
|
|
209
|
+
config: CourseConfig,
|
|
210
|
+
): NormalizedLessonExports {
|
|
211
|
+
const standaloneHtml = config.lessonExports?.standaloneHtml === true;
|
|
212
|
+
const print = config.lessonExports?.print === true;
|
|
213
|
+
const rawBase = config.lessonExports?.canonicalBaseUrl;
|
|
214
|
+
if (rawBase === undefined) return { standaloneHtml, print };
|
|
215
|
+
|
|
216
|
+
let parsed: URL;
|
|
217
|
+
try {
|
|
218
|
+
parsed = new URL(rawBase);
|
|
219
|
+
} catch {
|
|
220
|
+
throw new Error(
|
|
221
|
+
`CourseConfig lessonExports.canonicalBaseUrl must be an absolute ` +
|
|
222
|
+
`http(s) URL; received ${JSON.stringify(rawBase)}.`,
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
|
|
226
|
+
throw new Error(
|
|
227
|
+
`CourseConfig lessonExports.canonicalBaseUrl must use http(s); ` +
|
|
228
|
+
`received ${JSON.stringify(rawBase)}.`,
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
if (parsed.search || parsed.hash) {
|
|
232
|
+
throw new Error(
|
|
233
|
+
'CourseConfig lessonExports.canonicalBaseUrl cannot contain a query or fragment.',
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
if (!parsed.pathname.endsWith('/')) parsed.pathname += '/';
|
|
237
|
+
return { standaloneHtml, print, canonicalBaseUrl: parsed.toString() };
|
|
106
238
|
}
|
|
107
239
|
|
|
108
240
|
/**
|