explico 0.11.1 → 0.13.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 +1292 -1
- package/README.md +91 -13
- package/dist/compiler/astro.d.ts +11 -4
- package/dist/compiler/astro.js +48 -15
- package/dist/compiler/cli.d.ts +27 -12
- package/dist/compiler/cli.js +96 -25
- package/dist/compiler/collections.d.ts +33 -2
- package/dist/compiler/collections.js +91 -19
- package/dist/compiler/content-schema.d.ts +31 -0
- package/dist/compiler/content-schema.js +82 -0
- package/dist/compiler/content-schemas.d.ts +422 -0
- package/dist/compiler/content-schemas.js +229 -0
- package/dist/compiler/course-config.d.ts +1 -1
- package/dist/compiler/course-config.js +30 -2
- package/dist/compiler/exports/combined-html.d.ts +97 -0
- package/dist/compiler/exports/combined-html.js +492 -0
- package/dist/compiler/exports/download-index.d.ts +9 -0
- package/dist/compiler/exports/download-index.js +33 -0
- package/dist/compiler/exports/export-chapters.d.ts +98 -0
- package/dist/compiler/exports/export-chapters.js +164 -0
- package/dist/compiler/exports/export-pages.d.ts +48 -0
- package/dist/compiler/exports/export-pages.js +22 -0
- package/dist/compiler/exports/html-tree.d.ts +22 -0
- package/dist/compiler/exports/html-tree.js +47 -0
- package/dist/compiler/exports/latex/capture.d.ts +106 -0
- package/dist/compiler/exports/latex/capture.js +435 -0
- package/dist/compiler/exports/latex/compile.d.ts +73 -0
- package/dist/compiler/exports/latex/compile.js +115 -0
- package/dist/compiler/exports/latex/document.d.ts +102 -0
- package/dist/compiler/exports/latex/document.js +349 -0
- package/dist/compiler/exports/latex/explico.cls +415 -0
- package/dist/compiler/exports/latex/numbering.d.ts +18 -0
- package/dist/compiler/exports/latex/numbering.js +57 -0
- package/dist/compiler/exports/latex/serialize.d.ts +112 -0
- package/dist/compiler/exports/latex/serialize.js +606 -0
- package/dist/compiler/exports/latex-export.d.ts +44 -0
- package/dist/compiler/exports/latex-export.js +169 -0
- package/dist/compiler/exports/markdown/serialize.d.ts +51 -0
- package/dist/compiler/exports/markdown/serialize.js +527 -0
- package/dist/compiler/exports/markdown-export.d.ts +39 -0
- package/dist/compiler/exports/markdown-export.js +240 -0
- package/dist/compiler/exports/standalone-html.d.ts +15 -5
- package/dist/compiler/exports/standalone-html.js +23 -51
- package/dist/compiler/exports/static-tree.d.ts +253 -0
- package/dist/compiler/exports/static-tree.js +625 -0
- package/dist/compiler/exports/zip.d.ts +16 -0
- package/dist/compiler/exports/zip.js +72 -0
- package/dist/compiler/lesson-derivation.d.ts +8 -2
- package/dist/compiler/lesson-derivation.js +6 -7
- package/dist/compiler/manifest.d.ts +115 -8
- package/dist/compiler/manifest.js +221 -39
- package/dist/compiler/render-diagnostics.d.ts +65 -0
- package/dist/compiler/render-diagnostics.js +56 -0
- package/dist/compiler/resolution-report.d.ts +3 -1
- package/dist/{course-config-Dsnri9Tk.d.ts → course-config-rRtME5UV.d.ts} +56 -13
- package/dist/curriculum/validation.d.ts +9 -3
- package/dist/curriculum/validation.js +35 -17
- package/dist/reference/base-abbreviations.d.mts +2 -2
- package/dist/reference/base-abbreviations.mjs +2 -2
- package/dist/reference/base-operators.d.mts +8 -2
- package/dist/reference/base-operators.mjs +8 -10
- package/dist/reference/base-roman-labels.d.mts +4 -3
- package/dist/reference/base-roman-labels.mjs +4 -3
- package/dist/reference/citation-format.d.mts +35 -0
- package/dist/reference/citation-format.mjs +74 -0
- package/dist/reference/consistency.d.ts +5 -9
- package/dist/reference/consistency.js +34 -38
- package/dist/reference/curriculum-alignment.js +3 -24
- package/dist/reference/derived-entries.d.ts +45 -0
- package/dist/reference/derived-entries.js +50 -0
- package/dist/reference/derived-notation.d.mts +125 -0
- package/dist/reference/derived-notation.mjs +121 -0
- package/dist/reference/diagram-fit.d.ts +45 -0
- package/dist/reference/diagram-fit.js +54 -0
- package/dist/reference/diagram-layout.d.ts +59 -10
- package/dist/reference/diagram-layout.js +85 -24
- package/dist/reference/diagrams-validate.d.ts +1 -1
- package/dist/reference/equations-validate.d.ts +1 -1
- package/dist/reference/equations-validate.js +26 -1
- package/dist/reference/equations.d.mts +27 -0
- package/dist/reference/equations.mjs +120 -22
- package/dist/reference/examples-validate.d.ts +1 -1
- package/dist/reference/figure-fit.d.ts +70 -0
- package/dist/reference/figure-fit.js +60 -0
- package/dist/reference/figure-pictures.d.ts +27 -0
- package/dist/reference/figure-pictures.js +49 -0
- package/dist/reference/figure-symbols.d.ts +32 -0
- package/dist/reference/figure-symbols.js +55 -0
- package/dist/reference/figures-validate.d.ts +1 -1
- package/dist/reference/gate-abbreviations.d.ts +1 -1
- package/dist/reference/gate-abbreviations.js +1 -1
- package/dist/reference/gate-course-rules.d.ts +4 -3
- package/dist/reference/gate-course-rules.js +9 -4
- package/dist/reference/gate-heading-length.d.ts +2 -0
- package/dist/reference/gate-heading-length.js +7 -5
- package/dist/reference/gate-heading-structure.js +26 -0
- package/dist/reference/gate-indices.d.ts +35 -0
- package/dist/reference/gate-indices.js +299 -0
- package/dist/reference/gate-math.d.ts +32 -2
- package/dist/reference/gate-math.js +68 -12
- package/dist/reference/gate-mdx-expression.d.ts +17 -0
- package/dist/reference/gate-mdx-expression.js +29 -0
- package/dist/reference/gate-non-chapter-pages.d.ts +39 -0
- package/dist/reference/gate-non-chapter-pages.js +156 -0
- package/dist/reference/gate-part-pages.d.ts +4 -2
- package/dist/reference/gate-part-pages.js +2 -1
- package/dist/reference/gate-prop-text.d.ts +28 -0
- package/dist/reference/gate-prop-text.js +106 -0
- package/dist/reference/gate-prose-notation.d.ts +3 -1
- package/dist/reference/gate-prose-notation.js +4 -2
- package/dist/reference/gate-retired-keys.d.ts +35 -0
- package/dist/reference/gate-retired-keys.js +58 -0
- package/dist/reference/gloss.d.ts +2 -0
- package/dist/reference/katex-measure.d.ts +17 -0
- package/dist/reference/katex-measure.js +223 -0
- package/dist/reference/keyed-float-validate.js +12 -0
- package/dist/reference/keyed-jsx-floats.d.mts +2 -2
- package/dist/reference/keyed-jsx-floats.mjs +11 -14
- package/dist/reference/lab-katex-validate.d.ts +43 -0
- package/dist/reference/lab-katex-validate.js +96 -0
- package/dist/reference/lab-math-scope.d.ts +1 -0
- package/dist/reference/lab-math-scope.js +13 -2
- package/dist/reference/lint-ignore.js +1 -1
- package/dist/reference/math-glyphs.d.mts +94 -2
- package/dist/reference/math-glyphs.mjs +851 -46
- package/dist/reference/mixed-content.d.ts +8 -3
- package/dist/reference/mixed-content.js +4 -2
- package/dist/reference/page-notation.d.ts +39 -7
- package/dist/reference/page-notation.js +62 -10
- package/dist/reference/raw-floats.mjs +37 -13
- package/dist/reference/references.d.ts +11 -1
- package/dist/reference/references.js +6 -0
- package/dist/reference/registry.js +115 -11
- package/dist/reference/rehype-fail-katex-errors.d.mts +9 -0
- package/dist/reference/rehype-fail-katex-errors.mjs +19 -0
- package/dist/reference/rehype-heading-anchors.mjs +11 -1
- package/dist/reference/remark-citation.mjs +0 -0
- package/dist/reference/remark-notation.mjs +275 -23
- package/dist/reference/render-lab-math.d.ts +13 -2
- package/dist/reference/render-lab-math.js +18 -6
- package/dist/reference/sections-validate.d.ts +28 -3
- package/dist/reference/sections-validate.js +31 -4
- package/dist/reference/sections.d.mts +24 -6
- package/dist/reference/sections.mjs +92 -17
- package/dist/reference/tables-validate.d.ts +1 -1
- package/dist/reference/tables-validate.js +24 -1
- package/dist/reference/text-measure.d.ts +10 -0
- package/dist/reference/text-measure.js +41 -0
- package/dist/reference/text-widths.d.ts +10 -0
- package/dist/reference/text-widths.js +1238 -0
- package/dist/reference/types.d.ts +64 -8
- package/dist/rules/catalog.js +223 -32
- package/dist/rules/in-effect.d.ts +1 -1
- package/dist/rules/rules.schema.json +100 -27
- package/dist/rules/settings.d.ts +1 -1
- package/dist/rules/settings.js +7 -0
- package/dist/session/PreferenceStore.d.ts +18 -1
- package/dist/session/PreferenceStore.js +29 -1
- package/docs/authoring/README.md +33 -21
- package/docs/authoring/agents.md +38 -7
- package/docs/authoring/components.md +115 -10
- package/docs/authoring/migrating.md +878 -0
- package/docs/authoring/notation.md +285 -30
- package/docs/authoring/retired.md +1 -0
- package/docs/authoring/structure-rules.md +84 -45
- package/docs/authoring/structure.md +67 -2
- package/docs/authoring/visualizations.md +167 -25
- package/package.json +12 -7
- package/src/compiler/astro.ts +72 -21
- package/src/compiler/cli.ts +143 -35
- package/src/compiler/collections.ts +158 -27
- package/src/compiler/content-schema.ts +108 -0
- package/src/compiler/content-schemas.ts +391 -0
- package/src/compiler/course-config.ts +86 -15
- package/src/compiler/exports/combined-html.ts +669 -0
- package/src/compiler/exports/download-index.ts +36 -0
- package/src/compiler/exports/export-chapters.ts +233 -0
- package/src/compiler/exports/export-pages.ts +44 -0
- package/src/compiler/exports/html-tree.ts +62 -0
- package/src/compiler/exports/latex/capture.ts +651 -0
- package/src/compiler/exports/latex/compile.ts +168 -0
- package/src/compiler/exports/latex/document.ts +479 -0
- package/src/compiler/exports/latex/explico.cls +415 -0
- package/src/compiler/exports/latex/numbering.ts +74 -0
- package/src/compiler/exports/latex/serialize.ts +787 -0
- package/src/compiler/exports/latex/texlive-packages.txt +76 -0
- package/src/compiler/exports/latex-export.ts +255 -0
- package/src/compiler/exports/markdown/serialize.ts +632 -0
- package/src/compiler/exports/markdown-export.ts +329 -0
- package/src/compiler/exports/standalone-html.ts +39 -70
- package/src/compiler/exports/static-tree.ts +944 -0
- package/src/compiler/exports/zip.ts +88 -0
- package/src/compiler/lesson-derivation.ts +13 -8
- package/src/compiler/manifest.ts +387 -40
- package/src/compiler/render-diagnostics.ts +111 -0
- package/src/components/CourseContents.astro +6 -0
- package/src/components/HoverPanel.astro +204 -6
- package/src/components/PartOverview.astro +18 -9
- package/src/components/abbreviation/AbbreviationGlossary.astro +6 -2
- package/src/components/abbreviation/AbbreviationLayer.astro +21 -12
- package/src/components/assessments/AssessmentRunner.tsx +7 -1
- package/src/components/assessments/AssessmentSet.astro +14 -1
- package/src/components/block-heading.ts +38 -0
- package/src/components/card-arrow.ts +18 -4
- package/src/components/card-carry.ts +406 -0
- package/src/components/card-drag.ts +1 -30
- package/src/components/card-fetch.ts +87 -0
- package/src/components/card-manager.ts +1222 -38
- package/src/components/card-memory.ts +5 -1
- package/src/components/card-placement.ts +211 -13
- package/src/components/card-side.ts +281 -31
- package/src/components/citation/CitationLayer.astro +45 -40
- package/src/components/diagram/Diagram.astro +123 -44
- package/src/components/disclosure/print-as-shown.ts +42 -6
- package/src/components/figure/Figure.astro +17 -1
- package/src/components/figure/FloatCaption.astro +4 -17
- package/src/components/figure/figure-state.ts +26 -17
- package/src/components/float-toolbar.ts +274 -0
- package/src/components/memo/Memo.astro +21 -10
- package/src/components/memo/ShortNote.astro +4 -0
- package/src/components/notation/NotationGlossary.astro +22 -17
- package/src/components/notation/NotationLayer.astro +300 -79
- package/src/components/notation/NotationMath.astro +8 -1
- package/src/components/notation/render-notation-math.ts +51 -5
- package/src/components/readable-text.ts +25 -0
- package/src/components/reference/FloatRefLayer.astro +162 -89
- package/src/components/starlight/HeadingAnchorEnhancer.astro +13 -8
- package/src/components/starlight/KeyedFloatEnhancer.astro +28 -9
- package/src/components/starlight/LayoutPageSidebar.astro +17 -3
- package/src/components/starlight/LayoutSocialIcons.astro +79 -29
- package/src/components/starlight/LessonExportActions.astro +384 -310
- package/src/components/starlight/LessonFooter.astro +66 -8
- package/src/components/starlight/PrintController.astro +28 -0
- package/src/components/starlight/TextSizeControl.astro +137 -0
- package/src/components/starlight/print-controller.ts +380 -0
- package/src/components/starlight/section-summary.ts +13 -5
- package/src/components/table/Table.astro +14 -22
- package/src/components/table/table-truncation.ts +15 -0
- package/src/content-config.ts +20 -312
- package/src/curriculum/validation.ts +72 -24
- package/src/reference/base-abbreviations.mjs +2 -2
- package/src/reference/base-operators.mjs +8 -10
- package/src/reference/base-roman-labels.mjs +4 -3
- package/src/reference/citation-format.mjs +74 -0
- package/src/reference/consistency.ts +47 -61
- package/src/reference/curriculum-alignment.ts +4 -41
- package/src/reference/derived-entries.ts +68 -0
- package/src/reference/derived-notation.mjs +121 -0
- package/src/reference/diagram-fit.ts +104 -0
- package/src/reference/diagram-layout.ts +182 -51
- package/src/reference/diagrams-validate.ts +2 -1
- package/src/reference/equations-validate.ts +41 -2
- package/src/reference/equations.mjs +120 -22
- package/src/reference/examples-validate.ts +1 -0
- package/src/reference/figure-fit.ts +139 -0
- package/src/reference/figure-pictures.ts +96 -0
- package/src/reference/figure-symbols.ts +117 -0
- package/src/reference/figures-validate.ts +2 -1
- package/src/reference/gate-abbreviations.ts +1 -1
- package/src/reference/gate-course-rules.ts +22 -7
- package/src/reference/gate-heading-length.ts +25 -7
- package/src/reference/gate-heading-structure.ts +40 -1
- package/src/reference/gate-indices.ts +470 -0
- package/src/reference/gate-math.ts +102 -13
- package/src/reference/gate-mdx-expression.ts +45 -0
- package/src/reference/gate-non-chapter-pages.ts +241 -0
- package/src/reference/gate-part-pages.ts +1 -1
- package/src/reference/gate-prop-text.ts +145 -0
- package/src/reference/gate-prose-notation.ts +19 -5
- package/src/reference/gate-retired-keys.ts +101 -0
- package/src/reference/gloss.ts +2 -0
- package/src/reference/katex-measure.ts +384 -0
- package/src/reference/keyed-float-validate.ts +22 -0
- package/src/reference/keyed-jsx-floats.mjs +11 -14
- package/src/reference/lab-katex-validate.ts +156 -0
- package/src/reference/lab-math-scope.ts +15 -1
- package/src/reference/lint-ignore.ts +4 -1
- package/src/reference/math-glyphs.mjs +851 -46
- package/src/reference/mixed-content.ts +11 -2
- package/src/reference/page-notation.ts +114 -14
- package/src/reference/raw-floats.mjs +37 -13
- package/src/reference/references.ts +14 -0
- package/src/reference/registry.ts +170 -9
- package/src/reference/rehype-fail-katex-errors.mjs +19 -0
- package/src/reference/rehype-heading-anchors.mjs +11 -1
- package/src/reference/remark-citation.mjs +0 -0
- package/src/reference/remark-notation.mjs +275 -23
- package/src/reference/render-lab-math.ts +40 -5
- package/src/reference/sections-validate.ts +67 -3
- package/src/reference/sections.mjs +92 -17
- package/src/reference/tables-validate.ts +40 -2
- package/src/reference/text-measure.ts +63 -0
- package/src/reference/text-widths.ts +133 -0
- package/src/reference/types.ts +75 -8
- package/src/rules/catalog.ts +241 -31
- package/src/rules/settings.ts +10 -0
- package/src/session/PreferenceStore.ts +53 -0
- package/src/styles/global.css +322 -83
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
import { parse, parseFragment } from "parse5";
|
|
2
|
+
import {
|
|
3
|
+
attribute,
|
|
4
|
+
childrenOf,
|
|
5
|
+
elements,
|
|
6
|
+
hasClass,
|
|
7
|
+
inferBasePrefix,
|
|
8
|
+
isElement
|
|
9
|
+
} from "./html-tree.js";
|
|
10
|
+
const SKIPPED_TAGS = /* @__PURE__ */ new Set([
|
|
11
|
+
"button",
|
|
12
|
+
"input",
|
|
13
|
+
"nav",
|
|
14
|
+
"noscript",
|
|
15
|
+
"script",
|
|
16
|
+
"select",
|
|
17
|
+
"style",
|
|
18
|
+
"svg",
|
|
19
|
+
"template",
|
|
20
|
+
"textarea",
|
|
21
|
+
"astro-island"
|
|
22
|
+
]);
|
|
23
|
+
const SKIPPED_CLASSES = [
|
|
24
|
+
"sr-only",
|
|
25
|
+
"sl-anchor-link",
|
|
26
|
+
"keyed-equation__controls",
|
|
27
|
+
"float-tools",
|
|
28
|
+
"float-caption__anchor",
|
|
29
|
+
"keyed-figure__tools-stub",
|
|
30
|
+
"short-note__collapse",
|
|
31
|
+
"notation-enhancement-help",
|
|
32
|
+
"pagination-links",
|
|
33
|
+
"explico-site-footer",
|
|
34
|
+
"lesson-breadcrumb",
|
|
35
|
+
// A part page's stats line and chapter list are navigation the site builds;
|
|
36
|
+
// a print export's own contents replace them. Its objectives stay.
|
|
37
|
+
"part-meta",
|
|
38
|
+
"part-chapters"
|
|
39
|
+
];
|
|
40
|
+
const REF_CLASSES = [
|
|
41
|
+
["equation-ref", "equation"],
|
|
42
|
+
["figure-ref", "figure"],
|
|
43
|
+
["table-ref", "table"],
|
|
44
|
+
["diagram-ref", "diagram"],
|
|
45
|
+
["section-ref", "section"],
|
|
46
|
+
["example-ref", "example"],
|
|
47
|
+
["knowledge-check-ref", "check"],
|
|
48
|
+
["memo-ref", "memo"]
|
|
49
|
+
];
|
|
50
|
+
function skipped(node) {
|
|
51
|
+
if (SKIPPED_TAGS.has(node.tagName)) return true;
|
|
52
|
+
if (attribute(node, "aria-hidden") === "true") return true;
|
|
53
|
+
if (attribute(node, "data-print-omit") !== void 0) return true;
|
|
54
|
+
return SKIPPED_CLASSES.some((name) => hasClass(node, name));
|
|
55
|
+
}
|
|
56
|
+
function readableText(node) {
|
|
57
|
+
if (!isElement(node)) {
|
|
58
|
+
return node.nodeName === "#text" ? node.value : "";
|
|
59
|
+
}
|
|
60
|
+
if (skipped(node)) return "";
|
|
61
|
+
return childrenOf(node).map(readableText).join("");
|
|
62
|
+
}
|
|
63
|
+
function collapse(text) {
|
|
64
|
+
return text.replace(/[ \t\r\n\f]+/gu, " ");
|
|
65
|
+
}
|
|
66
|
+
function texOf(katex) {
|
|
67
|
+
const annotation = elements(
|
|
68
|
+
katex,
|
|
69
|
+
(node) => node.tagName === "annotation" && attribute(node, "encoding") === "application/x-tex"
|
|
70
|
+
)[0];
|
|
71
|
+
if (!annotation) return void 0;
|
|
72
|
+
return childrenOf(annotation).map((child) => "value" in child ? String(child.value) : "").join("").trim();
|
|
73
|
+
}
|
|
74
|
+
function firstByClass(root, name) {
|
|
75
|
+
return elements(root, (node) => hasClass(node, name))[0];
|
|
76
|
+
}
|
|
77
|
+
function cleanRoute(pathname, base) {
|
|
78
|
+
let path = pathname;
|
|
79
|
+
if (path.startsWith(base)) path = path.slice(base.length);
|
|
80
|
+
return path.replace(/\/index\.html$/u, "").replace(/\.html$/u, "").replace(/^\/+|\/+$/gu, "");
|
|
81
|
+
}
|
|
82
|
+
function courseTarget(href, context) {
|
|
83
|
+
const trimmed = href.trim();
|
|
84
|
+
if (trimmed.startsWith("#")) {
|
|
85
|
+
return { route: context.route, anchor: decodeURIComponent(trimmed.slice(1)) };
|
|
86
|
+
}
|
|
87
|
+
if (/^[a-z][a-z0-9+.-]*:/iu.test(trimmed) || trimmed.startsWith("//")) return void 0;
|
|
88
|
+
const page = new URL(
|
|
89
|
+
`${context.base}${context.route ? `${context.route}/` : ""}`,
|
|
90
|
+
"https://explico.invalid"
|
|
91
|
+
);
|
|
92
|
+
const url = new URL(trimmed, page);
|
|
93
|
+
return {
|
|
94
|
+
route: cleanRoute(url.pathname, context.base),
|
|
95
|
+
anchor: decodeURIComponent(url.hash.slice(1))
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function trimInlines(inlines) {
|
|
99
|
+
const result = [...inlines];
|
|
100
|
+
while (result[0]?.kind === "text" && !result[0].value.trim()) result.shift();
|
|
101
|
+
while (result.at(-1)?.kind === "text" && !result.at(-1).value.trim()) {
|
|
102
|
+
result.pop();
|
|
103
|
+
}
|
|
104
|
+
const first = result[0];
|
|
105
|
+
if (first?.kind === "text") result[0] = { kind: "text", value: first.value.replace(/^ +/u, "") };
|
|
106
|
+
const last = result.at(-1);
|
|
107
|
+
if (last?.kind === "text") {
|
|
108
|
+
result[result.length - 1] = { kind: "text", value: last.value.replace(/ +$/u, "") };
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
function readLink(node, context) {
|
|
113
|
+
const href = attribute(node, "href") ?? "";
|
|
114
|
+
const children = readInlines(node, context);
|
|
115
|
+
if (hasClass(node, "citation-ref")) {
|
|
116
|
+
const number = attribute(node, "data-citation-number") ?? readableText(node).replace(/\D/gu, "");
|
|
117
|
+
return [
|
|
118
|
+
{
|
|
119
|
+
kind: "cite",
|
|
120
|
+
number,
|
|
121
|
+
anchor: href.replace(/^#/u, ""),
|
|
122
|
+
sourceId: attribute(node, "data-citation-id"),
|
|
123
|
+
locator: attribute(node, "data-citation-locator") || void 0
|
|
124
|
+
}
|
|
125
|
+
];
|
|
126
|
+
}
|
|
127
|
+
if (hasClass(node, "memo-marker")) {
|
|
128
|
+
return [
|
|
129
|
+
{
|
|
130
|
+
kind: "memoMark",
|
|
131
|
+
anchor: href.replace(/^#/u, ""),
|
|
132
|
+
label: attribute(node, "data-memo-number") ?? readableText(node).trim()
|
|
133
|
+
}
|
|
134
|
+
];
|
|
135
|
+
}
|
|
136
|
+
if (hasClass(node, "short-note-marker")) {
|
|
137
|
+
return [{ kind: "noteMark", anchor: href.replace(/^#/u, ""), children }];
|
|
138
|
+
}
|
|
139
|
+
if (hasClass(node, "notation-term")) {
|
|
140
|
+
return [{ kind: "term", key: attribute(node, "data-notation-key") ?? "", children }];
|
|
141
|
+
}
|
|
142
|
+
if (!href) return children;
|
|
143
|
+
const target = courseTarget(href, context);
|
|
144
|
+
if (!target) return [{ kind: "link", href, children }];
|
|
145
|
+
const refKind = REF_CLASSES.find(([name]) => hasClass(node, name))?.[1] ?? (target.route === context.route ? "anchor" : "page");
|
|
146
|
+
return [{ kind: "ref", refKind, target, children }];
|
|
147
|
+
}
|
|
148
|
+
function readInline(node, context) {
|
|
149
|
+
if (!isElement(node)) {
|
|
150
|
+
if (node.nodeName !== "#text") return [];
|
|
151
|
+
const value = collapse(node.value);
|
|
152
|
+
return value ? [{ kind: "text", value }] : [];
|
|
153
|
+
}
|
|
154
|
+
if (hasClass(node, "katex")) {
|
|
155
|
+
const tex = texOf(node);
|
|
156
|
+
return tex ? [{ kind: "math", tex }] : [];
|
|
157
|
+
}
|
|
158
|
+
if (skipped(node)) return [];
|
|
159
|
+
switch (node.tagName) {
|
|
160
|
+
case "em":
|
|
161
|
+
case "i":
|
|
162
|
+
return [{ kind: "emphasis", children: readInlines(node, context) }];
|
|
163
|
+
case "strong":
|
|
164
|
+
case "b":
|
|
165
|
+
return [{ kind: "strong", children: readInlines(node, context) }];
|
|
166
|
+
case "sup":
|
|
167
|
+
if (hasClass(node, "memo-marker-wrap")) return readInlines(node, context);
|
|
168
|
+
return [{ kind: "superscript", children: readInlines(node, context) }];
|
|
169
|
+
case "sub":
|
|
170
|
+
return [{ kind: "subscript", children: readInlines(node, context) }];
|
|
171
|
+
case "code":
|
|
172
|
+
case "kbd":
|
|
173
|
+
return [{ kind: "code", value: readableText(node) }];
|
|
174
|
+
case "br":
|
|
175
|
+
return [{ kind: "break" }];
|
|
176
|
+
case "a":
|
|
177
|
+
return readLink(node, context);
|
|
178
|
+
default:
|
|
179
|
+
return readInlines(node, context);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function readInlines(node, context) {
|
|
183
|
+
const result = [];
|
|
184
|
+
for (const child of childrenOf(node)) {
|
|
185
|
+
for (const inline of readInline(child, context)) {
|
|
186
|
+
const previous = result.at(-1);
|
|
187
|
+
if (inline.kind === "text" && previous?.kind === "text") {
|
|
188
|
+
result[result.length - 1] = {
|
|
189
|
+
kind: "text",
|
|
190
|
+
value: collapse(previous.value + inline.value)
|
|
191
|
+
};
|
|
192
|
+
} else {
|
|
193
|
+
result.push(inline);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return result;
|
|
198
|
+
}
|
|
199
|
+
function inlineContent(node, context) {
|
|
200
|
+
return node ? trimInlines(readInlines(node, context)) : [];
|
|
201
|
+
}
|
|
202
|
+
function numberAttribute(node, name) {
|
|
203
|
+
return Number.parseFloat(attribute(node, name) ?? "0") || 0;
|
|
204
|
+
}
|
|
205
|
+
function readDiagramGeometry(figure) {
|
|
206
|
+
const svg = elements(figure, (node) => node.tagName === "svg" && !!attribute(node, "viewBox")).find((node) => elements(node, (child) => hasClass(child, "diagram-node")).length > 0);
|
|
207
|
+
if (!svg) return void 0;
|
|
208
|
+
const [, , width, height] = (attribute(svg, "viewBox") ?? "0 0 0 0").trim().split(/[\s,]+/u).map(Number);
|
|
209
|
+
const nodes = elements(svg, (node) => hasClass(node, "diagram-node")).flatMap((group) => {
|
|
210
|
+
const rect = elements(group, (node) => node.tagName === "rect")[0];
|
|
211
|
+
if (!rect) return [];
|
|
212
|
+
const text = firstByClass(group, "diagram-node-text");
|
|
213
|
+
const formula = firstByClass(group, "diagram-node-formula");
|
|
214
|
+
const katex = formula ? elements(formula, (node) => hasClass(node, "katex"))[0] : void 0;
|
|
215
|
+
const label = text ? collapse(readableText(text)).trim() : "";
|
|
216
|
+
const tex = katex ? texOf(katex) : void 0;
|
|
217
|
+
return [
|
|
218
|
+
{
|
|
219
|
+
x: numberAttribute(rect, "x"),
|
|
220
|
+
y: numberAttribute(rect, "y"),
|
|
221
|
+
width: numberAttribute(rect, "width"),
|
|
222
|
+
height: numberAttribute(rect, "height"),
|
|
223
|
+
radius: numberAttribute(rect, "rx"),
|
|
224
|
+
...label ? { text: label } : {},
|
|
225
|
+
...tex ? { tex } : {}
|
|
226
|
+
}
|
|
227
|
+
];
|
|
228
|
+
});
|
|
229
|
+
const edges = elements(svg, (node) => node.tagName === "path" && hasClass(node, "diagram-edge")).map(
|
|
230
|
+
(path) => [...(attribute(path, "d") ?? "").matchAll(/[ML]\s*(-?[\d.]+)[\s,]+(-?[\d.]+)/gu)].map(
|
|
231
|
+
(match) => [Number(match[1]), Number(match[2])]
|
|
232
|
+
)
|
|
233
|
+
).filter((points) => points.length >= 2);
|
|
234
|
+
return { width: width ?? 0, height: height ?? 0, nodes, edges };
|
|
235
|
+
}
|
|
236
|
+
function readCaption(figcaption, context) {
|
|
237
|
+
if (!figcaption) return [];
|
|
238
|
+
const text = firstByClass(figcaption, "float-caption__text");
|
|
239
|
+
return inlineContent(text, context);
|
|
240
|
+
}
|
|
241
|
+
function floatBase(node, prefix, context) {
|
|
242
|
+
const figcaption = elements(node, (child) => child.tagName === "figcaption")[0];
|
|
243
|
+
const key = attribute(node, `data-${prefix}-key`);
|
|
244
|
+
const short = attribute(node, `data-${prefix}-short`);
|
|
245
|
+
return {
|
|
246
|
+
anchor: attribute(node, "id") ?? "",
|
|
247
|
+
number: attribute(node, `data-${prefix}-number`) ?? "",
|
|
248
|
+
...key ? { key } : {},
|
|
249
|
+
...short ? { short } : {},
|
|
250
|
+
caption: readCaption(figcaption, context)
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function readFigurePicture(body) {
|
|
254
|
+
if (!body) return { kind: "capture" };
|
|
255
|
+
const diagram = elements(body, (node) => node.tagName === "figure" && hasClass(node, "diagram"))[0];
|
|
256
|
+
if (diagram) {
|
|
257
|
+
const geometry = readDiagramGeometry(diagram);
|
|
258
|
+
if (geometry) return { kind: "diagram", geometry };
|
|
259
|
+
}
|
|
260
|
+
const meaningful = childrenOf(body).filter(
|
|
261
|
+
(child) => isElement(child) && !["script", "style"].includes(child.tagName) || child.nodeName === "#text" && child.value.trim()
|
|
262
|
+
);
|
|
263
|
+
const only = meaningful.length === 1 && isElement(meaningful[0]) ? meaningful[0] : void 0;
|
|
264
|
+
const image = only?.tagName === "img" ? only : only?.tagName === "picture" ? elements(only, (node) => node.tagName === "img")[0] : void 0;
|
|
265
|
+
if (image && attribute(image, "src")) {
|
|
266
|
+
return { kind: "image", src: attribute(image, "src"), alt: attribute(image, "alt") ?? "" };
|
|
267
|
+
}
|
|
268
|
+
return { kind: "capture" };
|
|
269
|
+
}
|
|
270
|
+
function readTableCells(row, context) {
|
|
271
|
+
return childrenOf(row).filter((cell) => isElement(cell) && ["td", "th"].includes(cell.tagName)).map((cell) => {
|
|
272
|
+
const style = attribute(cell, "style") ?? "";
|
|
273
|
+
const align = attribute(cell, "align") ?? /text-align:\s*(left|center|right)/u.exec(style)?.[1];
|
|
274
|
+
return {
|
|
275
|
+
header: cell.tagName === "th",
|
|
276
|
+
colspan: Number.parseInt(attribute(cell, "colspan") ?? "1", 10) || 1,
|
|
277
|
+
rowspan: Number.parseInt(attribute(cell, "rowspan") ?? "1", 10) || 1,
|
|
278
|
+
...align === "left" || align === "center" || align === "right" ? { align } : {},
|
|
279
|
+
children: inlineContent(cell, context)
|
|
280
|
+
};
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
function readTable(table, context) {
|
|
284
|
+
const rows = (section) => elements(table, (node) => node.tagName === section).flatMap(
|
|
285
|
+
(group) => childrenOf(group).filter(
|
|
286
|
+
(row) => isElement(row) && row.tagName === "tr" && !hasClass(row, "keyed-table__more-row")
|
|
287
|
+
)
|
|
288
|
+
).map((row) => readTableCells(row, context));
|
|
289
|
+
const head = rows("thead");
|
|
290
|
+
const body = rows("tbody");
|
|
291
|
+
if (head.length === 0 && body.length === 0) {
|
|
292
|
+
return {
|
|
293
|
+
head: [],
|
|
294
|
+
body: childrenOf(table).filter((row) => isElement(row) && row.tagName === "tr").map((row) => readTableCells(row, context))
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
return { head, body };
|
|
298
|
+
}
|
|
299
|
+
function headingOf(wrapper) {
|
|
300
|
+
return childrenOf(wrapper).find(
|
|
301
|
+
(child) => isElement(child) && /^h[1-6]$/u.test(child.tagName)
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
function blockTitle(heading, context) {
|
|
305
|
+
if (!heading) return [];
|
|
306
|
+
return inlineContent(firstByClass(heading, "block-heading__title") ?? heading, context);
|
|
307
|
+
}
|
|
308
|
+
function readExamples(node, context) {
|
|
309
|
+
const heading = elements(node, (child) => hasClass(child, "block-heading"))[0];
|
|
310
|
+
const items = elements(node, (child) => hasClass(child, "compact-example")).map((section) => {
|
|
311
|
+
const title = elements(section, (child) => hasClass(child, "compact-example__heading"))[0];
|
|
312
|
+
return {
|
|
313
|
+
title: title ? inlineContent(title, context) : [{ kind: "text", value: attribute(section, "data-example-label") ?? "" }],
|
|
314
|
+
children: readBlocks(section, context, (child) => child !== title)
|
|
315
|
+
};
|
|
316
|
+
});
|
|
317
|
+
return {
|
|
318
|
+
kind: "examples",
|
|
319
|
+
anchor: attribute(heading ?? node, "id") ?? "",
|
|
320
|
+
number: (heading && attribute(heading, "data-ex-number")) ?? "",
|
|
321
|
+
title: blockTitle(heading, context),
|
|
322
|
+
items
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
function readNotationEntry(entry, context) {
|
|
326
|
+
const key = attribute(entry, "data-notation-entry") ?? "";
|
|
327
|
+
const symbol = elements(entry, (node) => hasClass(node, "notation-symbol"))[0];
|
|
328
|
+
const symbolKatex = symbol ? elements(symbol, (node) => hasClass(node, "katex"))[0] : void 0;
|
|
329
|
+
const label = elements(entry, (node) => node.tagName === "a" && !!attribute(node, "data-notation-link"))[0];
|
|
330
|
+
const summary = elements(entry, (node) => attribute(node, "data-notation-summary") !== void 0)[0];
|
|
331
|
+
const units = elements(entry, (node) => attribute(node, "data-notation-units") !== void 0)[0];
|
|
332
|
+
const formula = elements(entry, (node) => attribute(node, "data-notation-formula") !== void 0)[0];
|
|
333
|
+
const formulaKatex = formula ? elements(formula, (node) => hasClass(node, "katex"))[0] : void 0;
|
|
334
|
+
const unitsInlines = units ? trimInlines(
|
|
335
|
+
readInlines(units, context).filter(
|
|
336
|
+
(inline) => !(inline.kind === "strong")
|
|
337
|
+
)
|
|
338
|
+
) : void 0;
|
|
339
|
+
const symbolTex = symbolKatex ? texOf(symbolKatex) : void 0;
|
|
340
|
+
const formulaTex = formulaKatex ? texOf(formulaKatex) : void 0;
|
|
341
|
+
return {
|
|
342
|
+
key,
|
|
343
|
+
anchor: attribute(entry, "id") ?? `notation-${key}`,
|
|
344
|
+
...symbolTex ? { symbolTex } : {},
|
|
345
|
+
label: inlineContent(label, context),
|
|
346
|
+
summary: inlineContent(summary, context),
|
|
347
|
+
...unitsInlines && unitsInlines.length > 0 ? { units: unitsInlines } : {},
|
|
348
|
+
...formulaTex ? { formulaTex } : {}
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
function readBlocks(node, context, keep = () => true) {
|
|
352
|
+
const blocks = [];
|
|
353
|
+
let pending = [];
|
|
354
|
+
const flush = () => {
|
|
355
|
+
const content = trimInlines(pending);
|
|
356
|
+
if (content.length > 0) blocks.push({ kind: "paragraph", children: content });
|
|
357
|
+
pending = [];
|
|
358
|
+
};
|
|
359
|
+
for (const child of childrenOf(node)) {
|
|
360
|
+
if (!keep(child)) continue;
|
|
361
|
+
const block = isElement(child) ? readBlock(child, context) : void 0;
|
|
362
|
+
if (block === void 0) {
|
|
363
|
+
pending.push(...readInline(child, context));
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
flush();
|
|
367
|
+
blocks.push(...block);
|
|
368
|
+
}
|
|
369
|
+
flush();
|
|
370
|
+
return blocks;
|
|
371
|
+
}
|
|
372
|
+
function readBlock(node, context) {
|
|
373
|
+
if (hasClass(node, "katex-display")) {
|
|
374
|
+
const katex = elements(node, (child) => hasClass(child, "katex"))[0];
|
|
375
|
+
const tex = katex ? texOf(katex) : void 0;
|
|
376
|
+
return tex ? [{ kind: "displayMath", tex }] : [];
|
|
377
|
+
}
|
|
378
|
+
if (skipped(node)) return [];
|
|
379
|
+
if (hasClass(node, "notation-layer")) return [];
|
|
380
|
+
if (hasClass(node, "keyed-equation")) {
|
|
381
|
+
const katex = elements(node, (child) => hasClass(child, "katex"))[0];
|
|
382
|
+
const key = attribute(node, "data-eq-key");
|
|
383
|
+
return [
|
|
384
|
+
{
|
|
385
|
+
kind: "equation",
|
|
386
|
+
anchor: attribute(node, "id") ?? "",
|
|
387
|
+
number: attribute(node, "data-eq-number") ?? "",
|
|
388
|
+
...key ? { key } : {},
|
|
389
|
+
tex: (katex && texOf(katex)) ?? ""
|
|
390
|
+
}
|
|
391
|
+
];
|
|
392
|
+
}
|
|
393
|
+
if (node.tagName === "figure" && hasClass(node, "keyed-figure")) {
|
|
394
|
+
const body = firstByClass(node, "keyed-figure__body");
|
|
395
|
+
const island = body ? elements(body, (child) => child.tagName === "astro-island")[0] : void 0;
|
|
396
|
+
const figcaption = elements(node, (child) => child.tagName === "figcaption")[0];
|
|
397
|
+
const live = figcaption ? firstByClass(figcaption, "float-caption__state") : void 0;
|
|
398
|
+
const alt = island ? void 0 : body && attribute(body, "aria-label");
|
|
399
|
+
return [
|
|
400
|
+
{
|
|
401
|
+
kind: "figure",
|
|
402
|
+
...floatBase(node, "fig", context),
|
|
403
|
+
live: inlineContent(live, context),
|
|
404
|
+
picture: readFigurePicture(body),
|
|
405
|
+
...alt ? { alt } : {}
|
|
406
|
+
}
|
|
407
|
+
];
|
|
408
|
+
}
|
|
409
|
+
if (node.tagName === "figure" && hasClass(node, "keyed-table")) {
|
|
410
|
+
const table = elements(node, (child) => child.tagName === "table")[0];
|
|
411
|
+
return [
|
|
412
|
+
{
|
|
413
|
+
kind: "table",
|
|
414
|
+
...floatBase(node, "tab", context),
|
|
415
|
+
...table ? readTable(table, context) : { head: [], body: [] }
|
|
416
|
+
}
|
|
417
|
+
];
|
|
418
|
+
}
|
|
419
|
+
if (node.tagName === "figure" && hasClass(node, "diagram")) {
|
|
420
|
+
const geometry = readDiagramGeometry(node);
|
|
421
|
+
return [
|
|
422
|
+
{
|
|
423
|
+
kind: "diagram",
|
|
424
|
+
...floatBase(node, "dia", context),
|
|
425
|
+
geometry: geometry ?? { width: 0, height: 0, nodes: [], edges: [] }
|
|
426
|
+
}
|
|
427
|
+
];
|
|
428
|
+
}
|
|
429
|
+
if (hasClass(node, "memo-block")) {
|
|
430
|
+
const heading = elements(node, (child) => hasClass(child, "memo-block__heading"))[0];
|
|
431
|
+
const body = firstByClass(node, "memo-block__body");
|
|
432
|
+
const short = attribute(node, "data-memo-short");
|
|
433
|
+
return [
|
|
434
|
+
{
|
|
435
|
+
kind: "memo",
|
|
436
|
+
anchor: (heading && attribute(heading, "id")) ?? `memo-${attribute(node, "data-memo-key") ?? ""}`,
|
|
437
|
+
label: attribute(node, "data-memo-number") ?? "",
|
|
438
|
+
...short ? { short } : {},
|
|
439
|
+
title: inlineContent(heading, context),
|
|
440
|
+
children: body ? readBlocks(body, context) : []
|
|
441
|
+
}
|
|
442
|
+
];
|
|
443
|
+
}
|
|
444
|
+
if (node.tagName === "aside" && hasClass(node, "short-note")) {
|
|
445
|
+
const body = firstByClass(node, "short-note__body");
|
|
446
|
+
return [
|
|
447
|
+
{
|
|
448
|
+
kind: "note",
|
|
449
|
+
anchor: attribute(node, "id") ?? "",
|
|
450
|
+
title: attribute(node, "aria-label") ?? "",
|
|
451
|
+
children: body ? readBlocks(body, context) : []
|
|
452
|
+
}
|
|
453
|
+
];
|
|
454
|
+
}
|
|
455
|
+
if (node.tagName === "aside" && hasClass(node, "starlight-aside")) {
|
|
456
|
+
const variant = /starlight-aside--([a-z]+)/u.exec(attribute(node, "class") ?? "")?.[1] ?? "note";
|
|
457
|
+
const title = firstByClass(node, "starlight-aside__title");
|
|
458
|
+
const content = firstByClass(node, "starlight-aside__content");
|
|
459
|
+
return [
|
|
460
|
+
{
|
|
461
|
+
kind: "aside",
|
|
462
|
+
variant,
|
|
463
|
+
title: inlineContent(title, context),
|
|
464
|
+
children: content ? readBlocks(content, context) : []
|
|
465
|
+
}
|
|
466
|
+
];
|
|
467
|
+
}
|
|
468
|
+
if (hasClass(node, "fold")) {
|
|
469
|
+
const label = firstByClass(node, "fold__label");
|
|
470
|
+
const body = firstByClass(node, "fold__body");
|
|
471
|
+
const namesFloats = attribute(node, "data-names-floats") !== void 0;
|
|
472
|
+
return [
|
|
473
|
+
{
|
|
474
|
+
kind: "fold",
|
|
475
|
+
...label && !namesFloats ? { title: inlineContent(label, context) } : {},
|
|
476
|
+
children: body ? readBlocks(body, context) : []
|
|
477
|
+
}
|
|
478
|
+
];
|
|
479
|
+
}
|
|
480
|
+
if (node.tagName === "compact-examples" || hasClass(node, "compact-examples")) {
|
|
481
|
+
return [readExamples(node, context)];
|
|
482
|
+
}
|
|
483
|
+
if (hasClass(node, "sl-heading-wrapper")) {
|
|
484
|
+
const heading = headingOf(node);
|
|
485
|
+
if (!heading) return readBlocks(node, context);
|
|
486
|
+
if (attribute(heading, "data-block-kind") === "check") {
|
|
487
|
+
const anchor = attribute(heading, "id") ?? "";
|
|
488
|
+
return [
|
|
489
|
+
{
|
|
490
|
+
kind: "check",
|
|
491
|
+
anchor,
|
|
492
|
+
number: attribute(heading, "data-check-number") ?? "",
|
|
493
|
+
assessmentId: anchor.replace(/^check-/u, ""),
|
|
494
|
+
title: blockTitle(heading, context)
|
|
495
|
+
}
|
|
496
|
+
];
|
|
497
|
+
}
|
|
498
|
+
return readBlock(heading, context) ?? [];
|
|
499
|
+
}
|
|
500
|
+
if (/^h[1-6]$/u.test(node.tagName)) {
|
|
501
|
+
if (hasClass(node, "citations-heading")) return [];
|
|
502
|
+
const anchor = attribute(node, "id");
|
|
503
|
+
const number = attribute(node, "data-sec-number");
|
|
504
|
+
return [
|
|
505
|
+
{
|
|
506
|
+
kind: "heading",
|
|
507
|
+
level: Number(node.tagName.slice(1)),
|
|
508
|
+
...anchor ? { anchor } : {},
|
|
509
|
+
...number ? { number } : {},
|
|
510
|
+
children: inlineContent(node, context)
|
|
511
|
+
}
|
|
512
|
+
];
|
|
513
|
+
}
|
|
514
|
+
if (node.tagName === "ol" && hasClass(node, "citations-list")) {
|
|
515
|
+
return [
|
|
516
|
+
{
|
|
517
|
+
kind: "references",
|
|
518
|
+
items: childrenOf(node).filter((item) => isElement(item) && item.tagName === "li").map((item) => {
|
|
519
|
+
const anchor = attribute(item, "id") ?? "";
|
|
520
|
+
return {
|
|
521
|
+
number: anchor.replace(/^cite-/u, ""),
|
|
522
|
+
anchor,
|
|
523
|
+
children: trimInlines(
|
|
524
|
+
readInlines(item, context).filter(
|
|
525
|
+
(inline) => !(inline.kind === "ref" && inline.target.anchor.startsWith("cite-ref-"))
|
|
526
|
+
)
|
|
527
|
+
)
|
|
528
|
+
};
|
|
529
|
+
})
|
|
530
|
+
}
|
|
531
|
+
];
|
|
532
|
+
}
|
|
533
|
+
switch (node.tagName) {
|
|
534
|
+
case "p": {
|
|
535
|
+
const children = inlineContent(node, context);
|
|
536
|
+
return children.length > 0 ? [{ kind: "paragraph", children }] : [];
|
|
537
|
+
}
|
|
538
|
+
case "ul":
|
|
539
|
+
case "ol": {
|
|
540
|
+
const start = Number.parseInt(attribute(node, "start") ?? "", 10);
|
|
541
|
+
return [
|
|
542
|
+
{
|
|
543
|
+
kind: "list",
|
|
544
|
+
ordered: node.tagName === "ol",
|
|
545
|
+
...Number.isFinite(start) ? { start } : {},
|
|
546
|
+
items: childrenOf(node).filter((item) => isElement(item) && item.tagName === "li").map((item) => readBlocks(item, context))
|
|
547
|
+
}
|
|
548
|
+
];
|
|
549
|
+
}
|
|
550
|
+
case "blockquote":
|
|
551
|
+
return [{ kind: "quote", children: readBlocks(node, context) }];
|
|
552
|
+
case "pre":
|
|
553
|
+
return [{ kind: "code", value: readableText(node).replace(/\n$/u, "") }];
|
|
554
|
+
case "hr":
|
|
555
|
+
return [{ kind: "rule" }];
|
|
556
|
+
case "img": {
|
|
557
|
+
const src = attribute(node, "src");
|
|
558
|
+
return src ? [{ kind: "image", src, alt: attribute(node, "alt") ?? "" }] : [];
|
|
559
|
+
}
|
|
560
|
+
case "table":
|
|
561
|
+
return [
|
|
562
|
+
{
|
|
563
|
+
kind: "table",
|
|
564
|
+
anchor: attribute(node, "id") ?? "",
|
|
565
|
+
number: "",
|
|
566
|
+
caption: [],
|
|
567
|
+
...readTable(node, context)
|
|
568
|
+
}
|
|
569
|
+
];
|
|
570
|
+
case "details":
|
|
571
|
+
return readBlocks(node, context, (child) => !(isElement(child) && child.tagName === "summary"));
|
|
572
|
+
case "div":
|
|
573
|
+
case "section":
|
|
574
|
+
case "article":
|
|
575
|
+
case "header":
|
|
576
|
+
case "footer":
|
|
577
|
+
case "main":
|
|
578
|
+
case "figure":
|
|
579
|
+
case "aside":
|
|
580
|
+
case "dl":
|
|
581
|
+
case "dd":
|
|
582
|
+
case "dt":
|
|
583
|
+
case "li":
|
|
584
|
+
case "compact-example":
|
|
585
|
+
return readBlocks(node, context);
|
|
586
|
+
default:
|
|
587
|
+
return void 0;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
function readInlineFragment(html, route, base = "/") {
|
|
591
|
+
return inlineContent(parseFragment(html), { route, base });
|
|
592
|
+
}
|
|
593
|
+
function readStaticPage(html, slug, route) {
|
|
594
|
+
const document = parse(html);
|
|
595
|
+
const base = inferBasePrefix(document);
|
|
596
|
+
const context = { route, base };
|
|
597
|
+
const main = elements(document, (node) => node.tagName === "main")[0];
|
|
598
|
+
if (!main) throw new Error(`Built page ${slug} has no <main> element.`);
|
|
599
|
+
const title = elements(main, (node) => node.tagName === "h1")[0];
|
|
600
|
+
const content = elements(main, (node) => hasClass(node, "sl-markdown-content"))[0];
|
|
601
|
+
if (!content) throw new Error(`Built page ${slug} has no .sl-markdown-content element.`);
|
|
602
|
+
const layer = elements(
|
|
603
|
+
main,
|
|
604
|
+
(node) => hasClass(node, "notation-layer") && attribute(node, "data-notation-layer-id") === "page-notation"
|
|
605
|
+
)[0];
|
|
606
|
+
const entries = layer ? elements(layer, (node) => hasClass(node, "notation-entry") && attribute(node, "data-notation-entry") !== void 0) : [];
|
|
607
|
+
const remarks = layer ? elements(layer, (node) => node.tagName === "ul" && hasClass(node, "notation-suspended")).flatMap(
|
|
608
|
+
(list) => childrenOf(list).filter((item) => isElement(item) && item.tagName === "li").map((item) => inlineContent(item, context))
|
|
609
|
+
) : [];
|
|
610
|
+
return {
|
|
611
|
+
slug,
|
|
612
|
+
route,
|
|
613
|
+
title: title ? collapse(readableText(title)).trim() : slug,
|
|
614
|
+
blocks: readBlocks(content, context),
|
|
615
|
+
notation: entries.map((entry) => readNotationEntry(entry, context)),
|
|
616
|
+
notationRemarks: remarks
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
export {
|
|
620
|
+
courseTarget,
|
|
621
|
+
readDiagramGeometry,
|
|
622
|
+
readInlineFragment,
|
|
623
|
+
readStaticPage,
|
|
624
|
+
readableText
|
|
625
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Buffer } from 'node:buffer';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A minimal, deterministic ZIP writer for export downloads: entries sorted by
|
|
5
|
+
* path, one fixed timestamp (1980-01-01, the format's epoch), UTF-8 names,
|
|
6
|
+
* deflate where it helps. The same files always give the same bytes, so a
|
|
7
|
+
* rebuild does not churn the published download.
|
|
8
|
+
*/
|
|
9
|
+
interface ZipEntry {
|
|
10
|
+
/** Path inside the archive, `/`-separated, no leading slash. */
|
|
11
|
+
readonly path: string;
|
|
12
|
+
readonly content: string | Uint8Array;
|
|
13
|
+
}
|
|
14
|
+
declare function zip(entries: readonly ZipEntry[]): Buffer;
|
|
15
|
+
|
|
16
|
+
export { type ZipEntry, zip };
|