explico 0.12.0 → 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 +1122 -1
- package/README.md +91 -13
- package/dist/compiler/astro.d.ts +4 -3
- package/dist/compiler/astro.js +45 -15
- package/dist/compiler/cli.d.ts +26 -12
- package/dist/compiler/cli.js +96 -25
- package/dist/compiler/collections.d.ts +9 -1
- package/dist/compiler/collections.js +55 -16
- 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 +14 -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 +87 -6
- package/dist/compiler/manifest.js +174 -31
- package/dist/compiler/render-diagnostics.d.ts +65 -0
- package/dist/compiler/render-diagnostics.js +56 -0
- package/dist/compiler/resolution-report.d.ts +2 -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 +2 -2
- package/dist/reference/base-operators.mjs +2 -2
- 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/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-part-pages.d.ts +1 -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-math-scope.d.ts +1 -0
- package/dist/reference/lab-math-scope.js +13 -2
- 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 +34 -4
- package/dist/reference/page-notation.js +54 -2
- package/dist/reference/references.d.ts +11 -1
- package/dist/reference/references.js +6 -0
- package/dist/reference/registry.js +104 -10
- 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 +84 -20
- package/dist/reference/render-lab-math.d.ts +2 -0
- package/dist/reference/render-lab-math.js +17 -5
- 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 +191 -30
- package/dist/rules/in-effect.d.ts +1 -1
- package/dist/rules/rules.schema.json +79 -24
- 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 +32 -21
- package/docs/authoring/agents.md +38 -7
- package/docs/authoring/components.md +111 -6
- package/docs/authoring/migrating.md +663 -0
- package/docs/authoring/notation.md +281 -29
- package/docs/authoring/retired.md +1 -0
- package/docs/authoring/structure-rules.md +10 -41
- package/docs/authoring/structure.md +53 -2
- package/docs/authoring/visualizations.md +144 -18
- package/package.json +12 -7
- package/src/compiler/astro.ts +57 -17
- package/src/compiler/cli.ts +143 -35
- package/src/compiler/collections.ts +92 -19
- 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 +299 -28
- package/src/compiler/render-diagnostics.ts +111 -0
- package/src/components/HoverPanel.astro +204 -6
- package/src/components/PartOverview.astro +12 -9
- 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/figure/Figure.astro +11 -0
- package/src/components/figure/FloatCaption.astro +4 -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 +47 -9
- 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 +13 -21
- 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 +2 -2
- 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/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-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-math-scope.ts +15 -1
- package/src/reference/math-glyphs.mjs +851 -46
- package/src/reference/mixed-content.ts +11 -2
- package/src/reference/page-notation.ts +100 -3
- package/src/reference/references.ts +14 -0
- package/src/reference/registry.ts +154 -8
- 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 +84 -20
- package/src/reference/render-lab-math.ts +29 -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 +205 -29
- package/src/rules/settings.ts +10 -0
- package/src/session/PreferenceStore.ts +53 -0
- package/src/styles/global.css +291 -75
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* quick look at the source without leaving the reader's place.
|
|
7
7
|
*
|
|
8
8
|
* It reads everything it shows from the page's own static markup — the
|
|
9
|
-
* marker's `data-*` and the
|
|
10
|
-
* page serializes a second copy of the source database. Opening, pinning,
|
|
9
|
+
* marker's `data-*` and the reference-list item it links to (`#cite-n`) —
|
|
10
|
+
* so no page serializes a second copy of the source database. Opening, pinning,
|
|
11
11
|
* Escape and placement come from the card manager (`../card-manager.ts`); a
|
|
12
12
|
* card per source, several at once.
|
|
13
13
|
*/
|
|
@@ -21,12 +21,11 @@ import HoverPanel from '../HoverPanel.astro';
|
|
|
21
21
|
</p>
|
|
22
22
|
<div class="citation-panel-body">
|
|
23
23
|
<p class="citation-panel-locator" data-panel-locator hidden></p>
|
|
24
|
-
<p class="citation-panel-status" data-panel-status hidden></p>
|
|
25
24
|
<p class="citation-panel-links">
|
|
26
|
-
<a class="citation-panel-link" data-panel-link hidden
|
|
25
|
+
<a class="citation-panel-link hover-panel-action" data-panel-link hidden
|
|
27
26
|
>Go to the source<span aria-hidden="true" data-jump-arrow> ↗</span></a
|
|
28
27
|
>
|
|
29
|
-
<a class="citation-panel-jump" data-panel-jump
|
|
28
|
+
<a class="citation-panel-jump hover-panel-action" data-panel-jump
|
|
30
29
|
>Go to the reference list<span aria-hidden="true" data-jump-arrow> ↓</span></a
|
|
31
30
|
>
|
|
32
31
|
</p>
|
|
@@ -35,6 +34,7 @@ import HoverPanel from '../HoverPanel.astro';
|
|
|
35
34
|
|
|
36
35
|
<script>
|
|
37
36
|
import { cloneCardShell, registerCardSource } from '../card-manager';
|
|
37
|
+
import { fetchDoc, hrefFrom } from '../card-fetch';
|
|
38
38
|
import { wireJumpArrow } from '../card-jump';
|
|
39
39
|
import { referenceLabelFromText } from '../../reference/citation-format.mjs';
|
|
40
40
|
|
|
@@ -49,10 +49,11 @@ import HoverPanel from '../HoverPanel.astro';
|
|
|
49
49
|
|
|
50
50
|
function setup() {
|
|
51
51
|
const template = document.getElementById('citation-panel');
|
|
52
|
+
// Every page registers, with markers or none: a citation's card carried
|
|
53
|
+
// in from another page is built here (rule K5).
|
|
52
54
|
if (
|
|
53
55
|
!(template instanceof HTMLTemplateElement) ||
|
|
54
|
-
template.dataset.cardSourceReady === 'true'
|
|
55
|
-
!document.querySelector('a.citation-ref[data-citation-id]')
|
|
56
|
+
template.dataset.cardSourceReady === 'true'
|
|
56
57
|
) {
|
|
57
58
|
return;
|
|
58
59
|
}
|
|
@@ -66,27 +67,34 @@ import HoverPanel from '../HoverPanel.astro';
|
|
|
66
67
|
return candidate && !candidate.closest('[data-card-foreign]') ? candidate : null;
|
|
67
68
|
};
|
|
68
69
|
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
// The reference-list item a marker links to (`#cite-n`). Followed, not
|
|
71
|
+
// built from the number: a downloaded part or course holds one list per
|
|
72
|
+
// chapter, each numbered from 1, with the chapter in its items' ids.
|
|
73
|
+
const itemIdOf = (marker: HTMLElement) => {
|
|
74
|
+
const href = marker.getAttribute('href') ?? '';
|
|
75
|
+
return href.startsWith('#') && href.length > 1 ? decodeURIComponent(href.slice(1)) : null;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Fill a card from the marker plus its reference-list item — never from
|
|
79
|
+
// a serialized source table. On another page (K5), both come from the
|
|
80
|
+
// page the card was opened on, and its links go there.
|
|
81
|
+
const render = (itemId: string, marker: HTMLElement, from?: Document, page?: string) => {
|
|
82
|
+
const item = (from ?? document).getElementById(itemId);
|
|
83
|
+
const number = marker.dataset.citationNumber ?? '';
|
|
73
84
|
const el = cloneCardShell(template);
|
|
74
85
|
if (!item || !el) return null;
|
|
75
86
|
const field = (name: string) => el.querySelector<HTMLElement>(`[data-panel-${name}]`);
|
|
76
87
|
const markerEl = field('marker');
|
|
77
88
|
const label = field('label');
|
|
78
89
|
const locator = field('locator');
|
|
79
|
-
const status = field('status');
|
|
80
90
|
const link = el.querySelector<HTMLAnchorElement>('[data-panel-link]');
|
|
81
91
|
const jump = el.querySelector<HTMLAnchorElement>('[data-panel-jump]');
|
|
82
|
-
if (!markerEl || !label || !locator || !
|
|
92
|
+
if (!markerEl || !label || !locator || !link || !jump) return null;
|
|
83
93
|
|
|
84
94
|
// The reference list is a tight list, so the `<li>` has no `<p>`
|
|
85
|
-
// wrapper: clone it and drop the trailing link
|
|
86
|
-
const line =
|
|
87
|
-
for (const extra of line.querySelectorAll(
|
|
88
|
-
'.citation-url, .citation-status, .citation-backref',
|
|
89
|
-
)) {
|
|
95
|
+
// wrapper: clone it and drop the trailing link chrome.
|
|
96
|
+
const line = document.importNode(item, true);
|
|
97
|
+
for (const extra of line.querySelectorAll('.citation-url, .citation-backref')) {
|
|
90
98
|
extra.remove();
|
|
91
99
|
}
|
|
92
100
|
const referenceText = line.textContent ?? '';
|
|
@@ -97,11 +105,6 @@ import HoverPanel from '../HoverPanel.astro';
|
|
|
97
105
|
setText(locator, loc);
|
|
98
106
|
el.setAttribute('aria-label', `Source citation ${number}`);
|
|
99
107
|
|
|
100
|
-
const sourceStatus = item
|
|
101
|
-
.querySelector('.citation-status')
|
|
102
|
-
?.textContent?.trim();
|
|
103
|
-
setText(status, sourceStatus ? `Source record: ${sourceStatus}` : '');
|
|
104
|
-
|
|
105
108
|
const sourceUrl = item.querySelector<HTMLAnchorElement>('a.citation-url');
|
|
106
109
|
if (sourceUrl) {
|
|
107
110
|
link.href = sourceUrl.href;
|
|
@@ -109,19 +112,34 @@ import HoverPanel from '../HoverPanel.astro';
|
|
|
109
112
|
link.hidden = false;
|
|
110
113
|
}
|
|
111
114
|
|
|
112
|
-
|
|
115
|
+
const jumpTo = marker.getAttribute('href') ?? '#references';
|
|
116
|
+
jump.href = page ? hrefFrom(jumpTo, page) : jumpTo;
|
|
113
117
|
wireJumpArrow(jump);
|
|
114
118
|
return el;
|
|
115
119
|
};
|
|
116
120
|
|
|
121
|
+
/** A reference-list item names its source only on its own page. */
|
|
122
|
+
const idOf = (item: string) => item.split('@')[0] ?? item;
|
|
123
|
+
|
|
117
124
|
registerCardSource({
|
|
118
125
|
layer: 'citation',
|
|
119
126
|
triggerFrom: markerFrom,
|
|
120
127
|
itemFor: (marker) => {
|
|
121
|
-
const
|
|
122
|
-
return
|
|
128
|
+
const id = itemIdOf(marker);
|
|
129
|
+
return id && marker.dataset.citationNumber && document.getElementById(id) ? id : null;
|
|
123
130
|
},
|
|
124
|
-
render,
|
|
131
|
+
render: (id, marker) => render(id, marker),
|
|
132
|
+
// K5: on another page, `[3]` is that page's third source.
|
|
133
|
+
awayItem: (id, page) => `${idOf(id)}@${page}`,
|
|
134
|
+
build: (id, page) =>
|
|
135
|
+
fetchDoc(page).then((doc) => {
|
|
136
|
+
const marker = [
|
|
137
|
+
...doc.querySelectorAll<HTMLElement>('a.citation-ref[data-citation-number]'),
|
|
138
|
+
].find((candidate) => itemIdOf(candidate) === idOf(id));
|
|
139
|
+
const el = marker ? render(idOf(id), marker, doc, page) : null;
|
|
140
|
+
el?.setAttribute('data-card-foreign', '');
|
|
141
|
+
return el;
|
|
142
|
+
}),
|
|
125
143
|
});
|
|
126
144
|
}
|
|
127
145
|
|
|
@@ -155,21 +173,8 @@ import HoverPanel from '../HoverPanel.astro';
|
|
|
155
173
|
color: var(--sl-color-gray-2);
|
|
156
174
|
}
|
|
157
175
|
|
|
158
|
-
.citation-panel-status {
|
|
159
|
-
color: var(--sl-color-gray-3);
|
|
160
|
-
font-size: var(--sl-text-xs);
|
|
161
|
-
text-transform: lowercase;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
176
|
.citation-panel-body .citation-panel-links {
|
|
165
177
|
margin: 0;
|
|
166
178
|
}
|
|
167
|
-
|
|
168
|
-
.citation-panel-link,
|
|
169
|
-
.citation-panel-jump {
|
|
170
|
-
display: inline-block;
|
|
171
|
-
margin-inline-end: 0.9rem;
|
|
172
|
-
font-size: var(--sl-text-xs);
|
|
173
|
-
}
|
|
174
179
|
}
|
|
175
180
|
</style>
|
|
@@ -17,9 +17,20 @@
|
|
|
17
17
|
* client script**: `NotationLayer`'s trigger scan already queries the whole
|
|
18
18
|
* document, not just its own subtree.
|
|
19
19
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* Each box is sized from what it holds (`nodeBoxSize` in
|
|
21
|
+
* `reference/diagram-layout.ts`): the label measured in DejaVu Sans, the
|
|
22
|
+
* widest common system font, and wrapped to a line count that sets the
|
|
23
|
+
* height, and the formula measured from KaTeX's own layout tree
|
|
24
|
+
* (`reference/katex-measure.ts`). A node's `width` or `height` overrides
|
|
25
|
+
* either; with only a `width`, the label wraps inside it and the height
|
|
26
|
+
* follows. A diagram wider than the lesson column first wraps its labels
|
|
27
|
+
* narrower until it fits (`fitDiagramLayout`).
|
|
28
|
+
*
|
|
29
|
+
* One that still does not fit (rule V8, `rules.V8.columnWidth`, or the
|
|
30
|
+
* diagram's own `warnAboveWidth`) is marked `data-diagram-too-wide`; the
|
|
31
|
+
* build reports it as a `dia-too-wide` warning with the lesson file and this
|
|
32
|
+
* id (`reference/diagram-fit.ts`), and `astro dev` prints the same warning as
|
|
33
|
+
* it renders.
|
|
23
34
|
*
|
|
24
35
|
* Named like every float (docs/plans/titles-and-containers.md Part 3): the
|
|
25
36
|
* long `caption` sits below the graph with its number, in the same caption
|
|
@@ -31,7 +42,10 @@
|
|
|
31
42
|
* reader fold a diagram away, wrap it in a `<Fold>` or put it in a
|
|
32
43
|
* collapsible section.
|
|
33
44
|
*/
|
|
34
|
-
import {
|
|
45
|
+
import { fitDiagramLayout, FORMULA_FONT_PX } from '../../reference/diagram-layout';
|
|
46
|
+
import { measureFormula } from '../../reference/katex-measure';
|
|
47
|
+
import { diagramTooWideMessage, diagramWidthLimit } from '../../reference/diagram-fit';
|
|
48
|
+
import { loadManifest } from '../../compiler/manifest';
|
|
35
49
|
import { renderNotationFormula } from '../notation/render-notation-math';
|
|
36
50
|
import type { SafeMathNode as SafeMathNodeType } from '../notation/render-notation-math';
|
|
37
51
|
import SafeMathNode from '../notation/SafeMathNode.astro';
|
|
@@ -40,8 +54,11 @@ import { DIAGRAM_NO_LONGER_FOLDS } from '../../reference/diagrams-validate';
|
|
|
40
54
|
import type { GlyphScopeEntry } from '../../reference/gloss';
|
|
41
55
|
import {
|
|
42
56
|
notationKeysInMathNodes,
|
|
57
|
+
registerPageDerivedNotation,
|
|
43
58
|
registerPageNotationDependencies,
|
|
44
59
|
} from '../../reference/page-notation';
|
|
60
|
+
import { indexFindings } from '../../reference/gate-indices';
|
|
61
|
+
import type { DerivedUse } from '../../reference/types';
|
|
45
62
|
|
|
46
63
|
export interface DiagramNode {
|
|
47
64
|
readonly id: string;
|
|
@@ -49,8 +66,9 @@ export interface DiagramNode {
|
|
|
49
66
|
readonly text?: string;
|
|
50
67
|
/** Raw LaTeX, resolved against `scope` before rendering. */
|
|
51
68
|
readonly formula?: string;
|
|
52
|
-
/**
|
|
69
|
+
/** The box's width in px; the label wraps inside it and the height follows. */
|
|
53
70
|
readonly width?: number;
|
|
71
|
+
/** The box's height in px. */
|
|
54
72
|
readonly height?: number;
|
|
55
73
|
}
|
|
56
74
|
|
|
@@ -76,8 +94,9 @@ export interface Props {
|
|
|
76
94
|
/** Computed by `remark-notation.mjs` for a top-level lesson diagram. */
|
|
77
95
|
anchorId?: string;
|
|
78
96
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
97
|
+
* The widest this diagram may lay out, in px, before the build warns
|
|
98
|
+
* (`dia-too-wide`, rule V8). Default: the course's `rules.V8.columnWidth`,
|
|
99
|
+
* the lesson column. Set `false` only when horizontal overflow is deliberate.
|
|
81
100
|
*/
|
|
82
101
|
warnAboveWidth?: number | false;
|
|
83
102
|
}
|
|
@@ -92,7 +111,7 @@ const {
|
|
|
92
111
|
direction = 'TB',
|
|
93
112
|
number,
|
|
94
113
|
anchorId,
|
|
95
|
-
warnAboveWidth
|
|
114
|
+
warnAboveWidth,
|
|
96
115
|
} = Astro.props;
|
|
97
116
|
|
|
98
117
|
const idPattern = /^[A-Za-z][A-Za-z0-9_-]*$/;
|
|
@@ -128,6 +147,7 @@ if ((number && !anchorId) || (!number && anchorId)) {
|
|
|
128
147
|
);
|
|
129
148
|
}
|
|
130
149
|
if (
|
|
150
|
+
warnAboveWidth !== undefined &&
|
|
131
151
|
warnAboveWidth !== false &&
|
|
132
152
|
(!Number.isFinite(warnAboveWidth) || warnAboveWidth <= 0)
|
|
133
153
|
) {
|
|
@@ -136,26 +156,47 @@ if (
|
|
|
136
156
|
|
|
137
157
|
interface RenderedNode extends DiagramNode {
|
|
138
158
|
readonly mathNodes?: readonly SafeMathNodeType[];
|
|
159
|
+
/** The LaTeX `mathNodes` were rendered from, glyphs bound. */
|
|
160
|
+
readonly boundFormula?: string;
|
|
139
161
|
}
|
|
140
162
|
|
|
163
|
+
// The course's rule settings; a page rendered without a manifest (a
|
|
164
|
+
// component test) checks against the defaults.
|
|
165
|
+
const rules = await loadManifest().then(
|
|
166
|
+
(manifest) => manifest.rules,
|
|
167
|
+
() => undefined,
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
// Rule N23: a diagram's formula is page math, so its indexed symbols take
|
|
171
|
+
// derived cards like the lesson's, and are held to the rule.
|
|
172
|
+
const derivedUses: DerivedUse[] = [];
|
|
141
173
|
const rendered: RenderedNode[] = nodes.map((node) => {
|
|
142
174
|
if (!node.text && !node.formula) {
|
|
143
175
|
throw new Error(`Diagram "${id}" node "${node.id}" has neither text nor formula.`);
|
|
144
176
|
}
|
|
145
177
|
if (!node.formula) return { ...node };
|
|
146
178
|
|
|
147
|
-
const {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
179
|
+
const {
|
|
180
|
+
nodes: mathNodes,
|
|
181
|
+
latex,
|
|
182
|
+
unresolved,
|
|
183
|
+
degraded,
|
|
184
|
+
reason,
|
|
185
|
+
derived,
|
|
186
|
+
indices,
|
|
187
|
+
} = renderNotationFormula(node.formula, scope, { derive: true });
|
|
151
188
|
if (degraded) {
|
|
189
|
+
// The resolver says what went wrong; an empty `scope` is the usual cause
|
|
190
|
+
// when the diagram is written straight into MDX, where nothing passes it.
|
|
191
|
+
const emptyScope =
|
|
192
|
+
scope.length === 0
|
|
193
|
+
? ' The diagram has no `scope`, so no symbol can resolve: pass the page\'s ' +
|
|
194
|
+
'notation scope (`labMathScope`), as a wrapper component does.'
|
|
195
|
+
: '';
|
|
152
196
|
throw new Error(
|
|
153
197
|
`Diagram "${id}" node "${node.id}" formula "${node.formula}" could not be ` +
|
|
154
|
-
`bound to the notation scope: the LaTeX did not parse
|
|
155
|
-
`
|
|
156
|
-
`\\explain{key}{latex}, or brace a subscripted base (write {v_0}^{2}, not ` +
|
|
157
|
-
`v_0^{2}), so every glyph resolves — a diagram formula is never allowed to ` +
|
|
158
|
-
`render as silent, unexplained math.`,
|
|
198
|
+
`bound to the notation scope: ${(reason ?? 'the LaTeX did not parse').replace(/\.$/, '')}.${emptyScope} ` +
|
|
199
|
+
`A diagram formula is never allowed to render as silent, unexplained math.`,
|
|
159
200
|
);
|
|
160
201
|
}
|
|
161
202
|
if (unresolved.length > 0) {
|
|
@@ -166,33 +207,55 @@ const rendered: RenderedNode[] = nodes.map((node) => {
|
|
|
166
207
|
`or pass it in the diagram's scope.`,
|
|
167
208
|
);
|
|
168
209
|
}
|
|
169
|
-
|
|
210
|
+
const findings = rules?.disabled.includes('N23') ? [] : indexFindings(indices);
|
|
211
|
+
if (findings.length > 0) {
|
|
212
|
+
throw new Error(
|
|
213
|
+
`Diagram "${id}" node "${node.id}" formula "${node.formula}" has an index no card ` +
|
|
214
|
+
`explains (rule N23): ${findings.join('; ')}.`,
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
derivedUses.push(...derived);
|
|
218
|
+
return { ...node, mathNodes, boundFormula: latex };
|
|
170
219
|
});
|
|
171
220
|
|
|
221
|
+
const derivedKeys = new Set(derivedUses.map((use) => use.key));
|
|
222
|
+
registerPageDerivedNotation(Astro.locals, derivedUses, `Diagram "${id}"`);
|
|
172
223
|
for (const node of rendered) {
|
|
173
224
|
if (!node.mathNodes) continue;
|
|
174
225
|
registerPageNotationDependencies(
|
|
175
226
|
Astro.locals,
|
|
176
|
-
|
|
227
|
+
// A derived card is no definition: it ships through its own registry.
|
|
228
|
+
notationKeysInMathNodes(node.mathNodes).filter((key) => !derivedKeys.has(key)),
|
|
177
229
|
`Diagram "${id}" node "${node.id}" formula "${node.formula}"`,
|
|
178
230
|
);
|
|
179
231
|
}
|
|
180
232
|
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
233
|
+
for (const node of rendered) {
|
|
234
|
+
for (const side of ['width', 'height'] as const) {
|
|
235
|
+
const value = node[side];
|
|
236
|
+
if (value !== undefined && !(Number.isFinite(value) && value > 0)) {
|
|
237
|
+
throw new Error(`Diagram "${id}" node "${node.id}" needs a positive \`${side}\`.`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Rule V8's settings, from the course's rules above.
|
|
243
|
+
const widthLimit = diagramWidthLimit(warnAboveWidth, rules);
|
|
244
|
+
|
|
245
|
+
const { layout } = fitDiagramLayout(
|
|
246
|
+
rendered.map((node) => ({
|
|
247
|
+
id: node.id,
|
|
248
|
+
content: {
|
|
249
|
+
...(node.text ? { text: node.text } : {}),
|
|
250
|
+
...(node.boundFormula
|
|
251
|
+
? { formula: measureFormula(node.boundFormula, FORMULA_FONT_PX) }
|
|
252
|
+
: {}),
|
|
253
|
+
},
|
|
254
|
+
...(node.width !== undefined ? { width: node.width } : {}),
|
|
255
|
+
...(node.height !== undefined ? { height: node.height } : {}),
|
|
256
|
+
})),
|
|
194
257
|
edges.map((edge) => ({ from: edge.from, to: edge.to })),
|
|
195
|
-
{ direction },
|
|
258
|
+
{ direction, ...(widthLimit !== undefined ? { fitWidth: widthLimit } : {}) },
|
|
196
259
|
);
|
|
197
260
|
|
|
198
261
|
const nodeById = new Map(rendered.map((node) => [node.id, node]));
|
|
@@ -203,13 +266,13 @@ const renderedAnchorId = anchorId ?? legacyAnchorId;
|
|
|
203
266
|
const viewportId = `${legacyAnchorId}-viewport`;
|
|
204
267
|
const captionTextId = `${legacyAnchorId}-caption`;
|
|
205
268
|
|
|
206
|
-
|
|
269
|
+
const tooWide = widthLimit !== undefined && layout.width > widthLimit;
|
|
270
|
+
if (tooWide && import.meta.env.DEV) {
|
|
271
|
+
const entry = (Astro.locals as { starlightRoute?: { entry?: { filePath?: string; id?: string } } })
|
|
272
|
+
.starlightRoute?.entry;
|
|
207
273
|
console.warn(
|
|
208
|
-
`[
|
|
209
|
-
|
|
210
|
-
`by readers, but consider recreating the graph with direction="TB", shorter ` +
|
|
211
|
-
`labels, or explicit node sizes. Set warnAboveWidth={false} only when the ` +
|
|
212
|
-
`horizontal overflow is intentional.`,
|
|
274
|
+
`[dia-too-wide] ${entry?.filePath ?? entry?.id ?? Astro.url.pathname}: ` +
|
|
275
|
+
diagramTooWideMessage(id, layout.width, widthLimit),
|
|
213
276
|
);
|
|
214
277
|
}
|
|
215
278
|
|
|
@@ -227,6 +290,7 @@ function pathFrom(points: readonly { x: number; y: number }[]): string {
|
|
|
227
290
|
data-dia-key={number ? id : undefined}
|
|
228
291
|
data-dia-short={short}
|
|
229
292
|
data-diagram-width={layout.width}
|
|
293
|
+
data-diagram-too-wide={tooWide ? widthLimit : undefined}
|
|
230
294
|
data-diagram-expandable
|
|
231
295
|
>
|
|
232
296
|
<div class="diagram__body">
|
|
@@ -426,23 +490,38 @@ function pathFrom(points: readonly { x: number; y: number }[]): string {
|
|
|
426
490
|
stroke-width: 1;
|
|
427
491
|
}
|
|
428
492
|
|
|
493
|
+
/* `NODE_FONT_PX` and the insets in `reference/diagram-layout.ts` size each
|
|
494
|
+
box from these values; change them together. The size is in px, not
|
|
495
|
+
rem: the boxes are measured at build time for 13.6px text, so text that
|
|
496
|
+
followed a reader's larger default font size (20px, Chrome's "Large")
|
|
497
|
+
outgrew its box and was cut off. Scaling the whole drawing instead is no
|
|
498
|
+
way out — WebKit on iOS scales the SVG but not the HTML in a
|
|
499
|
+
`foreignObject`. Browser zoom still enlarges it with everything else. */
|
|
429
500
|
.diagram-node-content {
|
|
430
501
|
display: flex;
|
|
431
502
|
height: 100%;
|
|
432
503
|
flex-direction: column;
|
|
433
504
|
align-items: center;
|
|
434
505
|
justify-content: center;
|
|
435
|
-
gap:
|
|
436
|
-
padding:
|
|
506
|
+
gap: 2.4px;
|
|
507
|
+
padding: 3.2px 8px;
|
|
437
508
|
color: var(--sl-color-text);
|
|
438
509
|
font-family: var(--sl-font);
|
|
439
|
-
font-size:
|
|
510
|
+
font-size: 13.6px;
|
|
440
511
|
line-height: 1.25;
|
|
441
512
|
text-align: center;
|
|
442
513
|
}
|
|
443
514
|
|
|
444
|
-
|
|
445
|
-
|
|
515
|
+
/* The box was sized for its label wrapped evenly; a narrower font
|
|
516
|
+
balances it the same way rather than leaving one word alone. */
|
|
517
|
+
.diagram-node-text {
|
|
518
|
+
text-wrap: balance;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/* The box is as wide as the formula on one line (`nodeBoxSize`); KaTeX's
|
|
522
|
+
inline math would otherwise break after a `+` or `=` and outgrow it. */
|
|
523
|
+
.diagram-node-formula {
|
|
524
|
+
white-space: nowrap;
|
|
446
525
|
}
|
|
447
526
|
|
|
448
527
|
.diagram-edge {
|
|
@@ -263,6 +263,17 @@ const name = `Figure ${number}`;
|
|
|
263
263
|
.keyed-figure__tools-stub {
|
|
264
264
|
display: none !important;
|
|
265
265
|
}
|
|
266
|
+
|
|
267
|
+
/* A lab the reader never scrolled to has not drawn yet. The Print button
|
|
268
|
+
and Ctrl+P load it first; the browser's own File → Print cannot wait,
|
|
269
|
+
so the empty box says how to print the figure. */
|
|
270
|
+
.keyed-figure__body:has(astro-island[ssr])::after {
|
|
271
|
+
content: 'Interactive figure not loaded: print with the page’s Print button or Ctrl+P to include it.';
|
|
272
|
+
display: block;
|
|
273
|
+
font-size: 0.85em;
|
|
274
|
+
font-style: italic;
|
|
275
|
+
padding: 0.5rem 0;
|
|
276
|
+
}
|
|
266
277
|
}
|
|
267
278
|
</style>
|
|
268
279
|
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* (docs/plans/figures-and-short-captions.md, decisions 1 and 4). One
|
|
5
5
|
* anatomy, below the picture, the LaTeX figure convention:
|
|
6
6
|
*
|
|
7
|
-
* Figure 2.2.1
|
|
7
|
+
* Figure 2.2.1 **‹short›.** ‹caption› ‹live end› [buttons]
|
|
8
8
|
*
|
|
9
|
-
* The number links to the float
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* The number links to the float; hovering or focusing it shows its toolbar,
|
|
10
|
+
* whose Copy link copies that link (`float-toolbar.ts`). The caption is the
|
|
11
|
+
* float's one long caption. A float
|
|
12
12
|
* with a short caption opens the caption with it as a bold title,
|
|
13
13
|
* `b.float-caption__title` (decision 9.1), outside `.float-caption__text`, so
|
|
14
14
|
* a reader of the long caption (a preview card, a fold's bar) still reads
|
|
@@ -65,19 +65,6 @@ const tools = Astro.slots.has('default') ? (await Astro.slots.render('default'))
|
|
|
65
65
|
</a>
|
|
66
66
|
)
|
|
67
67
|
}
|
|
68
|
-
<a
|
|
69
|
-
class="float-caption__anchor"
|
|
70
|
-
href={`#${anchorId}`}
|
|
71
|
-
aria-label={`Copy the link to ${name}`}
|
|
72
|
-
title="Copy link"
|
|
73
|
-
data-copy-link={name}
|
|
74
|
-
>
|
|
75
|
-
<svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="currentColor"
|
|
76
|
-
><path
|
|
77
|
-
d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 1 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 0 0-1.42-1.42m8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 1 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0l3.88-3.89a4.49 4.49 0 0 0 0-6.33M8.83 15.17a1 1 0 0 0 .71.29 1 1 0 0 0 .71-.29l4.92-4.92a1 1 0 1 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42"
|
|
78
|
-
></path></svg
|
|
79
|
-
>
|
|
80
|
-
</a>
|
|
81
68
|
{short && <b class="float-caption__title">{captionTitle(short)}</b>}{short && ' '}<span
|
|
82
69
|
class:list={['float-caption__text', `${prefix}__caption-text`]}
|
|
83
70
|
id={textId}
|