explico 0.13.1 → 0.15.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 +990 -1
- package/README.md +200 -30
- package/dist/compiler/astro.d.ts +15 -2
- package/dist/compiler/astro.js +40 -11
- package/dist/compiler/cli-main.d.ts +100 -0
- package/dist/compiler/cli-main.js +433 -0
- package/dist/compiler/cli-reference.d.ts +50 -0
- package/dist/compiler/cli-reference.js +213 -0
- package/dist/compiler/cli-verbs.d.ts +45 -0
- package/dist/compiler/cli-verbs.js +224 -0
- package/dist/compiler/cli-verify.d.ts +51 -0
- package/dist/compiler/cli-verify.js +151 -0
- package/dist/compiler/cli.d.ts +408 -24
- package/dist/compiler/cli.js +1328 -8
- package/dist/compiler/collections.d.ts +88 -1
- package/dist/compiler/collections.js +170 -25
- package/dist/compiler/content-release.d.ts +49 -0
- package/dist/compiler/content-release.js +63 -0
- package/dist/compiler/content-schemas.d.ts +2 -2
- package/dist/compiler/course-config.d.ts +1 -1
- package/dist/compiler/course-config.js +105 -1
- package/dist/compiler/decks.d.ts +161 -0
- package/dist/compiler/decks.js +235 -0
- package/dist/compiler/exports/combined-html.d.ts +5 -1
- package/dist/compiler/exports/deck-fit.d.ts +55 -0
- package/dist/compiler/exports/deck-fit.js +90 -0
- package/dist/compiler/exports/export-chapters.d.ts +37 -6
- package/dist/compiler/exports/export-chapters.js +64 -5
- package/dist/compiler/exports/export-pages.d.ts +30 -3
- package/dist/compiler/exports/export-pages.js +24 -1
- package/dist/compiler/exports/latex/beamerthemeexplico.sty +124 -0
- package/dist/compiler/exports/latex/cache.d.ts +78 -0
- package/dist/compiler/exports/latex/cache.js +129 -0
- package/dist/compiler/exports/latex/capture.d.ts +10 -1
- package/dist/compiler/exports/latex/capture.js +3 -1
- package/dist/compiler/exports/latex/compile.d.ts +13 -2
- package/dist/compiler/exports/latex/compile.js +12 -1
- package/dist/compiler/exports/latex/deck.d.ts +92 -0
- package/dist/compiler/exports/latex/deck.js +349 -0
- package/dist/compiler/exports/latex/document.d.ts +51 -6
- package/dist/compiler/exports/latex/document.js +71 -12
- package/dist/compiler/exports/latex/explico-common.sty +198 -0
- package/dist/compiler/exports/latex/explico.cls +13 -183
- package/dist/compiler/exports/latex/serialize.d.ts +60 -4
- package/dist/compiler/exports/latex/serialize.js +4 -2
- package/dist/compiler/exports/latex-export.d.ts +24 -2
- package/dist/compiler/exports/latex-export.js +107 -26
- package/dist/compiler/exports/markdown/serialize.d.ts +24 -4
- package/dist/compiler/exports/markdown/serialize.js +85 -8
- package/dist/compiler/exports/markdown-export.d.ts +6 -1
- package/dist/compiler/exports/markdown-export.js +50 -11
- package/dist/compiler/exports/standalone-html.d.ts +10 -5
- package/dist/compiler/exports/standalone-html.js +3 -3
- package/dist/compiler/exports/static-tree.d.ts +38 -1
- package/dist/compiler/exports/static-tree.js +120 -4
- package/dist/compiler/knowledge-version.d.ts +26 -2
- package/dist/compiler/knowledge-version.js +27 -17
- package/dist/compiler/lesson-derivation.d.ts +143 -6
- package/dist/compiler/lesson-derivation.js +145 -13
- package/dist/compiler/manifest.d.ts +133 -4
- package/dist/compiler/manifest.js +364 -58
- package/dist/compiler/page-versions.d.ts +184 -0
- package/dist/compiler/page-versions.js +217 -0
- package/dist/compiler/render-diagnostics.d.ts +5 -1
- package/dist/compiler/resolution-report.d.ts +24 -6
- package/dist/compiler/resolution-report.js +22 -4
- package/dist/compiler/validate-content.d.ts +7 -0
- package/dist/compiler/validate-content.js +160 -0
- package/dist/{course-config-rRtME5UV.d.ts → course-config-BLtIdkei.d.ts} +164 -1
- package/dist/curriculum/competency-graph.d.ts +54 -0
- package/dist/curriculum/competency-graph.js +41 -0
- package/dist/reference/base-library.d.mts +8 -0
- package/dist/reference/base-library.mjs +19 -0
- package/dist/reference/consistency.d.ts +8 -4
- package/dist/reference/consistency.js +82 -26
- package/dist/reference/deck-remark.d.mts +123 -0
- package/dist/reference/deck-remark.mjs +600 -0
- package/dist/reference/deck-source.d.ts +107 -0
- package/dist/reference/deck-source.js +140 -0
- package/dist/reference/decks-validate.d.ts +133 -0
- package/dist/reference/decks-validate.js +359 -0
- package/dist/reference/derived-entries.d.ts +5 -1
- package/dist/reference/diagram-fit.d.ts +6 -2
- package/dist/reference/diagram-fit.js +5 -1
- package/dist/reference/figure-symbols.d.ts +23 -6
- package/dist/reference/figure-symbols.js +51 -15
- package/dist/reference/float-name.d.ts +43 -0
- package/dist/reference/float-name.js +58 -0
- package/dist/reference/folds-validate.d.ts +1 -1
- package/dist/reference/gate-abbreviations.d.ts +1 -1
- package/dist/reference/gate-indices.js +5 -4
- package/dist/reference/gate-math.d.ts +29 -2
- package/dist/reference/gate-math.js +99 -18
- package/dist/reference/gate-part-pages.d.ts +1 -1
- package/dist/reference/lab-katex-validate.d.ts +10 -6
- package/dist/reference/lab-katex-validate.js +17 -9
- package/dist/reference/lab-math-scope.js +29 -4
- package/dist/reference/math-glyphs.d.mts +25 -0
- package/dist/reference/math-glyphs.mjs +189 -25
- package/dist/reference/page-notation.d.ts +22 -3
- package/dist/reference/page-notation.js +32 -10
- package/dist/reference/references.d.ts +14 -1
- package/dist/reference/references.js +13 -0
- package/dist/reference/registry-scope.d.mts +33 -0
- package/dist/reference/registry-scope.mjs +34 -0
- package/dist/reference/registry.js +29 -10
- package/dist/reference/rehype-deck.d.mts +6 -0
- package/dist/reference/rehype-deck.mjs +286 -0
- package/dist/reference/rehype-heading-anchors.d.mts +20 -0
- package/dist/reference/rehype-heading-anchors.mjs +48 -6
- package/dist/reference/remark-notation.mjs +249 -40
- package/dist/reference/source-lines.d.mts +12 -0
- package/dist/reference/source-lines.mjs +65 -0
- package/dist/reference/types.d.ts +28 -0
- package/dist/rules/catalog.d.ts +21 -4
- package/dist/rules/catalog.js +237 -2
- package/dist/rules/course-rules.d.ts +5 -1
- package/dist/rules/course-rules.js +17 -3
- package/dist/rules/course-rules.schema.json +12 -0
- package/dist/rules/in-effect.d.ts +13 -3
- package/dist/rules/in-effect.js +34 -10
- package/dist/rules/rules.schema.json +280 -1
- package/dist/rules/settings.d.ts +1 -1
- package/dist/session/PreferenceStore.d.ts +6 -0
- package/dist/session/PreferenceStore.js +18 -1
- package/dist/session/deck-memory.d.ts +116 -0
- package/dist/session/deck-memory.js +143 -0
- package/dist/session/reading-memory.d.ts +96 -0
- package/dist/session/reading-memory.js +133 -0
- package/docs/VERSIONING.md +21 -18
- package/docs/authoring/README.md +31 -9
- package/docs/authoring/agents.md +72 -18
- package/docs/authoring/cli-reference.json +2172 -0
- package/docs/authoring/cli.md +887 -0
- package/docs/authoring/components.md +15 -0
- package/docs/authoring/deck.md +612 -0
- package/docs/authoring/migrating.md +1195 -16
- package/docs/authoring/notation.md +49 -6
- package/docs/authoring/structure.md +80 -1
- package/docs/authoring/versioning.md +56 -3
- package/docs/authoring/visualizations.md +7 -2
- package/docs/course-agent/AGENTS.md +40 -0
- package/docs/course-agent/agents/rules-reviewer.md +33 -0
- package/docs/course-agent/skills/draft-lesson/SKILL.md +38 -0
- package/docs/course-agent/skills/migrate-course/SKILL.md +32 -0
- package/docs/course-agent/skills/release-content/SKILL.md +26 -0
- package/docs/diagram-scaling.md +148 -0
- package/docs/privacy.md +59 -0
- package/package.json +8 -2
- package/src/compiler/astro.ts +60 -21
- package/src/compiler/cli-main.ts +557 -0
- package/src/compiler/cli-reference.ts +285 -0
- package/src/compiler/cli-verbs.ts +270 -0
- package/src/compiler/cli-verify.ts +241 -0
- package/src/compiler/cli.ts +2119 -170
- package/src/compiler/collections.ts +284 -25
- package/src/compiler/content-release.ts +91 -0
- package/src/compiler/course-config.ts +267 -0
- package/src/compiler/decks.ts +455 -0
- package/src/compiler/exports/deck-fit.ts +127 -0
- package/src/compiler/exports/export-chapters.ts +105 -6
- package/src/compiler/exports/export-pages.ts +46 -2
- package/src/compiler/exports/latex/beamerthemeexplico.sty +124 -0
- package/src/compiler/exports/latex/cache.ts +183 -0
- package/src/compiler/exports/latex/capture.ts +5 -2
- package/src/compiler/exports/latex/compile.ts +18 -0
- package/src/compiler/exports/latex/deck.ts +419 -0
- package/src/compiler/exports/latex/document.ts +117 -21
- package/src/compiler/exports/latex/explico-common.sty +198 -0
- package/src/compiler/exports/latex/explico.cls +13 -183
- package/src/compiler/exports/latex/serialize.ts +25 -21
- package/src/compiler/exports/latex/texlive-packages.txt +6 -2
- package/src/compiler/exports/latex-export.ts +187 -45
- package/src/compiler/exports/markdown/serialize.ts +118 -9
- package/src/compiler/exports/markdown-export.ts +56 -11
- package/src/compiler/exports/standalone-html.ts +8 -7
- package/src/compiler/exports/static-tree.ts +175 -3
- package/src/compiler/knowledge-version.ts +56 -21
- package/src/compiler/lesson-derivation.ts +282 -16
- package/src/compiler/manifest.ts +568 -63
- package/src/compiler/page-versions.ts +401 -0
- package/src/compiler/resolution-report.ts +38 -7
- package/src/compiler/validate-content.ts +215 -0
- package/src/components/CourseContents.astro +124 -6
- package/src/components/CurriculumMap.astro +49 -1
- package/src/components/FloatIndex.astro +1 -1
- package/src/components/PartOverview.astro +51 -5
- package/src/components/assessments/AssessmentSet.astro +41 -15
- package/src/components/block-heading.ts +15 -6
- package/src/components/card-carry.ts +7 -4
- package/src/components/card-manager.ts +14 -2
- package/src/components/card-memory.ts +13 -9
- package/src/components/deck/DeckEnhancer.astro +13 -0
- package/src/components/deck/deck-context.ts +104 -0
- package/src/components/deck/deck-controller.ts +1287 -0
- package/src/components/deck/deck-map.ts +91 -0
- package/src/components/deck-lane.ts +163 -0
- package/src/components/diagram/Diagram.astro +131 -86
- package/src/components/disclosure/persisted-disclosure.ts +9 -1
- package/src/components/figure/Figure.astro +7 -2
- package/src/components/figure/FloatCaption.astro +5 -3
- package/src/components/fold/Fold.astro +2 -2
- package/src/components/notation/NotationFormula.astro +81 -11
- package/src/components/notation/NotationGlossary.astro +132 -1
- package/src/components/notation/NotationLayer.astro +15 -7
- package/src/components/starlight/AboutPanel.astro +186 -3
- package/src/components/starlight/CollapsibleSections.astro +24 -3
- package/src/components/starlight/DiagramEnhancer.astro +5 -1
- package/src/components/starlight/HeadingAnchorEnhancer.astro +1 -1
- package/src/components/starlight/LayoutHeader.astro +17 -0
- package/src/components/starlight/LayoutPageTitle.astro +110 -0
- package/src/components/starlight/LayoutSidebar.astro +807 -21
- package/src/components/starlight/LayoutSocialIcons.astro +62 -6
- package/src/components/starlight/LessonExportActions.astro +27 -9
- package/src/components/starlight/LessonFooter.astro +59 -0
- package/src/components/starlight/ReadingMemoryNotice.astro +114 -0
- package/src/components/starlight/TextSizeControl.astro +24 -13
- package/src/components/starlight/page-marks.ts +139 -0
- package/src/components/starlight/section-summary.ts +1 -1
- package/src/components/starlight/sidebar-editions.ts +245 -0
- package/src/components/table/Table.astro +15 -7
- package/src/content-config.ts +87 -1
- package/src/curriculum/competency-graph.ts +95 -0
- package/src/reference/base-library.mjs +19 -0
- package/src/reference/consistency.ts +137 -39
- package/src/reference/deck-remark.mjs +600 -0
- package/src/reference/deck-source.ts +273 -0
- package/src/reference/decks-validate.ts +604 -0
- package/src/reference/diagram-fit.ts +18 -4
- package/src/reference/diagram-layout.ts +3 -1
- package/src/reference/figure-symbols.ts +108 -31
- package/src/reference/folds-validate.ts +1 -1
- package/src/reference/gate-indices.ts +5 -3
- package/src/reference/gate-math.ts +169 -25
- package/src/reference/lab-katex-validate.ts +30 -15
- package/src/reference/lab-math-scope.ts +34 -3
- package/src/reference/math-glyphs.mjs +189 -25
- package/src/reference/page-notation.ts +69 -15
- package/src/reference/references.ts +28 -0
- package/src/reference/registry-scope.mjs +34 -0
- package/src/reference/registry.ts +41 -11
- package/src/reference/rehype-deck.mjs +286 -0
- package/src/reference/rehype-heading-anchors.mjs +48 -6
- package/src/reference/remark-notation.mjs +249 -40
- package/src/reference/source-lines.mjs +65 -0
- package/src/reference/types.ts +28 -0
- package/src/rules/catalog.ts +274 -4
- package/src/rules/course-rules.ts +21 -1
- package/src/rules/in-effect.ts +58 -11
- package/src/session/PreferenceStore.ts +23 -0
- package/src/session/deck-memory.ts +263 -0
- package/src/session/reading-memory.ts +243 -0
- package/src/styles/deck.css +1150 -0
- package/src/styles/global.css +958 -27
- package/src/styles/zones.css +277 -0
- /package/src/{components → reference}/float-name.ts +0 -0
|
@@ -63,14 +63,23 @@ export async function titledBlocksOf(
|
|
|
63
63
|
* The text a reader sees for each outline heading with inline math, by its
|
|
64
64
|
* anchor (`manifest.lessons[].headings`, v30). Astro lists a heading by all
|
|
65
65
|
* the text in it, and KaTeX writes a formula three ways — MathML, its LaTeX
|
|
66
|
-
* annotation and its glyphs — so its own list reads `R\explain{k}{R}R`.
|
|
66
|
+
* annotation and its glyphs — so its own list reads `R\explain{k}{R}R`. A
|
|
67
|
+
* deck beside its chapter, or a part's, is no lesson: its page lists its
|
|
68
|
+
* frames by their titles as the reader sees them (`decks[].frames`).
|
|
67
69
|
*/
|
|
68
|
-
export async function mathHeadingTextsOf(
|
|
69
|
-
const
|
|
70
|
+
export async function mathHeadingTextsOf(pageId: string): Promise<ReadonlyMap<string, string>> {
|
|
71
|
+
const manifest = await manifestOnce();
|
|
72
|
+
const lesson = manifest.lessons.find((entry) => entry.id === pageId);
|
|
73
|
+
if (lesson) {
|
|
74
|
+
return new Map(
|
|
75
|
+
lesson.headings.filter((heading) => heading.math).map((heading) => [heading.slug, heading.text]),
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
const deck = (manifest.decks ?? []).find((entry) => entry.pageId === pageId);
|
|
70
79
|
return new Map(
|
|
71
|
-
(
|
|
72
|
-
.
|
|
73
|
-
|
|
80
|
+
(deck?.frames ?? []).flatMap((frame): [string, string][] =>
|
|
81
|
+
frame.slug === undefined ? [] : [[frame.slug, frame.title]],
|
|
82
|
+
),
|
|
74
83
|
);
|
|
75
84
|
}
|
|
76
85
|
|
|
@@ -63,6 +63,7 @@ import {
|
|
|
63
63
|
createBrowserPreferenceStore,
|
|
64
64
|
createSessionPreferenceStore,
|
|
65
65
|
} from '../session/PreferenceStore';
|
|
66
|
+
import { rememberReading } from '../session/reading-memory';
|
|
66
67
|
import { decodeCard, keyOf, type RememberedCard } from './card-memory';
|
|
67
68
|
import type { HoldEdge } from './card-placement';
|
|
68
69
|
|
|
@@ -305,21 +306,23 @@ const setKey = (base: string) => `explico:cards:carried:${base}`;
|
|
|
305
306
|
|
|
306
307
|
/**
|
|
307
308
|
* K5, D9: this tab's own set; a tab with none takes the course's last set,
|
|
308
|
-
* which is its own from then on.
|
|
309
|
+
* which is its own from then on. The course's last set is reading memory
|
|
310
|
+
* (`../session/reading-memory.ts`): it is read and kept only with the
|
|
311
|
+
* reader's yes, so without it a new tab starts with no cards.
|
|
309
312
|
*/
|
|
310
313
|
export function readCarried(base: string): CarriedSet {
|
|
311
314
|
const own = decodeCarried(tab.get(setKey(base)));
|
|
312
315
|
if (own) return own;
|
|
313
|
-
const last = decodeCarried(preferences.get(setKey(base))) ?? EMPTY_SET;
|
|
316
|
+
const last = (rememberReading(base) ? decodeCarried(preferences.get(setKey(base))) : null) ?? EMPTY_SET;
|
|
314
317
|
tab.set(setKey(base), encodeCarried(last));
|
|
315
318
|
return last;
|
|
316
319
|
}
|
|
317
320
|
|
|
318
|
-
/** K5: this tab's set, written as the course's last set too. Returns what was stored. */
|
|
321
|
+
/** K5: this tab's set, written as the course's last set too with the reader's yes. Returns what was stored. */
|
|
319
322
|
export function writeCarried(base: string, set: CarriedSet): string {
|
|
320
323
|
const text = encodeCarried(set);
|
|
321
324
|
tab.set(setKey(base), text);
|
|
322
|
-
preferences.set(setKey(base), text);
|
|
325
|
+
if (rememberReading(base)) preferences.set(setKey(base), text);
|
|
323
326
|
return text;
|
|
324
327
|
}
|
|
325
328
|
|
|
@@ -75,6 +75,10 @@ import {
|
|
|
75
75
|
type CarriedSet,
|
|
76
76
|
type OpenedAt,
|
|
77
77
|
} from './card-carry';
|
|
78
|
+
import {
|
|
79
|
+
READING_MEMORY_EVENT,
|
|
80
|
+
type ReadingMemoryChange,
|
|
81
|
+
} from '../session/reading-memory';
|
|
78
82
|
import { isThisPage, pageTitleOf } from './card-fetch';
|
|
79
83
|
import { wireJumpArrow } from './card-jump';
|
|
80
84
|
import { readableText } from './readable-text';
|
|
@@ -2051,7 +2055,7 @@ function rememberCards(): void {
|
|
|
2051
2055
|
width: card.width,
|
|
2052
2056
|
});
|
|
2053
2057
|
}
|
|
2054
|
-
writeRememberedCards({
|
|
2058
|
+
writeRememberedCards(base, {
|
|
2055
2059
|
cards: saved,
|
|
2056
2060
|
pointed: pointedKey !== null && keys.has(pointedKey) ? pointedKey : null,
|
|
2057
2061
|
});
|
|
@@ -2599,11 +2603,19 @@ function install(): void {
|
|
|
2599
2603
|
if (carry) {
|
|
2600
2604
|
restoreCarriedSet(readCarried(base));
|
|
2601
2605
|
} else {
|
|
2602
|
-
const page = readRememberedCards();
|
|
2606
|
+
const page = readRememberedCards(base);
|
|
2603
2607
|
remembered = [...page.cards];
|
|
2604
2608
|
rememberedPointed = page.pointed;
|
|
2605
2609
|
}
|
|
2606
2610
|
window.addEventListener('pagehide', leavePage);
|
|
2611
|
+
// A yes to reading memory keeps what is open now beyond the tab; a no has
|
|
2612
|
+
// already deleted the kept copies, and the tab's own go on.
|
|
2613
|
+
window.addEventListener(READING_MEMORY_EVENT, (event) => {
|
|
2614
|
+
const { answer } = (event as CustomEvent<ReadingMemoryChange>).detail;
|
|
2615
|
+
if (answer !== 'yes') return;
|
|
2616
|
+
lastStored = null;
|
|
2617
|
+
leavePage();
|
|
2618
|
+
});
|
|
2607
2619
|
document.addEventListener('visibilitychange', () => {
|
|
2608
2620
|
if (document.visibilityState === 'hidden') leavePage();
|
|
2609
2621
|
});
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
* Remembering a page's open explanation cards. A reader who leaves a lesson
|
|
3
3
|
* with cards pinned, docked or moved finds them where they were on coming
|
|
4
4
|
* back to it: through a link, Back or a reload, in another tab, or after the
|
|
5
|
-
* browser restarts. Closing the last card forgets the page.
|
|
5
|
+
* browser restarts. Closing the last card forgets the page. This is reading
|
|
6
|
+
* memory (`../session/reading-memory.ts`): kept in the browser only with the
|
|
7
|
+
* reader's yes; without it, in the tab's session, so Back, a reload and a
|
|
8
|
+
* link still bring the cards back until the tab is closed.
|
|
6
9
|
*
|
|
7
10
|
* The card manager (`./card-manager.ts`) saves the kept cards as the page is
|
|
8
11
|
* left (`pagehide`) and restores them as each layer registers. A card is
|
|
@@ -17,7 +20,7 @@
|
|
|
17
20
|
* `decodeCards` and `restorable` are pure, so `tests/unit/card-memory.test.ts`
|
|
18
21
|
* checks them in Node.
|
|
19
22
|
*/
|
|
20
|
-
import {
|
|
23
|
+
import { readingMemoryStore } from '../session/reading-memory';
|
|
21
24
|
import type { MovedSpot } from './card-drag';
|
|
22
25
|
import type { CardAnchor } from './card-placement';
|
|
23
26
|
|
|
@@ -159,21 +162,22 @@ export function restorable(
|
|
|
159
162
|
// ---------------------------------------------------------------------------
|
|
160
163
|
|
|
161
164
|
// The one seam for browser storage; this module never touches it itself.
|
|
162
|
-
//
|
|
163
|
-
// open on the same page share one entry, and the last
|
|
164
|
-
|
|
165
|
-
|
|
165
|
+
// With the reader's yes, local storage, so the cards outlive the tab and a
|
|
166
|
+
// browser restart (tabs open on the same page share one entry, and the last
|
|
167
|
+
// one left wins); without it, the tab's session storage.
|
|
166
168
|
/**
|
|
167
169
|
* One entry per page, kept only while the page has cards to bring back. The
|
|
168
170
|
* path includes a course's base, so courses on one origin never share one.
|
|
169
171
|
*/
|
|
170
172
|
const storageKey = () => `explico:cards:${window.location.pathname}`;
|
|
171
173
|
|
|
172
|
-
/** The cards this page had open when the reader last left it
|
|
173
|
-
export const readRememberedCards = (): RememberedPage =>
|
|
174
|
+
/** The cards this page had open when the reader last left it, in the course at `base`. */
|
|
175
|
+
export const readRememberedCards = (base: string): RememberedPage =>
|
|
176
|
+
decodeCards(readingMemoryStore(base).get(storageKey()));
|
|
174
177
|
|
|
175
178
|
/** Remember this page's cards; with none, the page is forgotten. */
|
|
176
|
-
export function writeRememberedCards(page: RememberedPage): void {
|
|
179
|
+
export function writeRememberedCards(base: string, page: RememberedPage): void {
|
|
180
|
+
const store = readingMemoryStore(base);
|
|
177
181
|
const key = storageKey();
|
|
178
182
|
if (page.cards.length > 0) store.set(key, encodeCards(page));
|
|
179
183
|
else if (store.remove) store.remove(key);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* A deck page's behaviour in the browser: the scaled frames, Present mode,
|
|
4
|
+
* the presenter window and the steps' effects (`deck-controller.ts`).
|
|
5
|
+
* `LessonFooter.astro` includes it on a deck's page only.
|
|
6
|
+
*/
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<script>
|
|
10
|
+
import { installDecks } from './deck-controller';
|
|
11
|
+
|
|
12
|
+
installDecks();
|
|
13
|
+
</script>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a component on a deck page (`<lesson>.deck.mdx`, `<part>/index.deck.mdx`,
|
|
3
|
+
* docs/authoring/deck.md) needs to know about it, read from the one manifest:
|
|
4
|
+
* a float on a deck carries no number of its own, and one the deck recalls
|
|
5
|
+
* from a chapter keeps the chapter's number, which links to the chapter. A
|
|
6
|
+
* course's own wrapper around `<Figure>`, `<Table>` or `<Diagram>` forwards
|
|
7
|
+
* `number` and `anchorId` as it always did, and nothing more.
|
|
8
|
+
*/
|
|
9
|
+
import { loadManifest, type Manifest } from '../../compiler/manifest';
|
|
10
|
+
import type { ManifestDeck } from '../../compiler/manifest';
|
|
11
|
+
import { routeIdFromLocals } from '../../reference/page-notation';
|
|
12
|
+
|
|
13
|
+
/** The manifest's deck the page renders, if the page is one. */
|
|
14
|
+
export function deckOfRoute(manifest: Pick<Manifest, 'decks'>, routeId: string | undefined): ManifestDeck | undefined {
|
|
15
|
+
if (routeId === undefined) return undefined;
|
|
16
|
+
return (manifest.decks ?? []).find((deck) => deck.slug === routeId);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** A part's deck, by the part's directory. */
|
|
20
|
+
export function partDeckOf(manifest: Pick<Manifest, 'decks'>, dir: string): ManifestDeck | undefined {
|
|
21
|
+
return (manifest.decks ?? []).find((deck) => deck.part === dir);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Where a chapter's page sends a reader for its slides ("Slides for this
|
|
26
|
+
* chapter", and the sidebar's icon): its own deck, or else the section of
|
|
27
|
+
* its part's deck that covers it, at the section's divider (`#slide-N`). A
|
|
28
|
+
* lesson's own deck wins. `path` is below the site's base: `motion/x/slides/`.
|
|
29
|
+
*/
|
|
30
|
+
export function chapterSlides(
|
|
31
|
+
manifest: Pick<Manifest, 'decks'>,
|
|
32
|
+
chapterSlug: string,
|
|
33
|
+
): { readonly deck: ManifestDeck; readonly path: string } | undefined {
|
|
34
|
+
const decks = manifest.decks ?? [];
|
|
35
|
+
const own = decks.find((deck) => deck.chapter === chapterSlug);
|
|
36
|
+
if (own) return { deck: own, path: `${own.slug}/` };
|
|
37
|
+
for (const deck of decks) {
|
|
38
|
+
const cover = deck.part === undefined ? undefined : deck.covers.find((entry) => entry.chapter === chapterSlug);
|
|
39
|
+
if (cover) return { deck, path: `${deck.slug}/#slide-${cover.frame}` };
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** A sidebar link as Starlight hands it to the footer's pagination. */
|
|
45
|
+
export interface PaginationLink {
|
|
46
|
+
readonly type: string;
|
|
47
|
+
readonly label?: string;
|
|
48
|
+
readonly href?: string;
|
|
49
|
+
readonly attrs?: Readonly<Record<string, unknown>>;
|
|
50
|
+
readonly isCurrent?: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Next and Previous on a deck's page: the decks before and after it in the
|
|
55
|
+
* sidebar's order — a lesson's deck, a slides-first lesson, a part's deck —
|
|
56
|
+
* each named "Slides: *title*". `links` is the sidebar flattened, `current`
|
|
57
|
+
* the deck's own place in it; `titleOf` gives a deck's title by its link.
|
|
58
|
+
*/
|
|
59
|
+
export function deckNeighbours<T extends PaginationLink>(
|
|
60
|
+
links: readonly T[],
|
|
61
|
+
current: number,
|
|
62
|
+
titleOf: (link: T) => string | undefined,
|
|
63
|
+
): { readonly prev?: T; readonly next?: T } {
|
|
64
|
+
const isDeck = (link: T | undefined) => link?.attrs?.['data-edition'] === 'slides';
|
|
65
|
+
const named = (link: T): T => {
|
|
66
|
+
const title = titleOf(link);
|
|
67
|
+
return title === undefined ? link : { ...link, label: `Slides: ${title}` };
|
|
68
|
+
};
|
|
69
|
+
const step = (direction: 1 | -1): T | undefined => {
|
|
70
|
+
for (let index = current + direction; index >= 0 && index < links.length; index += direction) {
|
|
71
|
+
if (isDeck(links[index])) return named(links[index]!);
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
};
|
|
75
|
+
const prev = step(-1);
|
|
76
|
+
const next = step(1);
|
|
77
|
+
return { ...(prev === undefined ? {} : { prev }), ...(next === undefined ? {} : { next }) };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface DeckFloat {
|
|
81
|
+
/** The float is on a deck page, where a float of the deck's own has no number. */
|
|
82
|
+
readonly onDeck: boolean;
|
|
83
|
+
/** Where a recalled float's number links: the float on its chapter's page. */
|
|
84
|
+
readonly numberHref?: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* A float on the page `locals` renders, anchored at `anchorId`. A recalled
|
|
89
|
+
* one links to its chapter: a lesson's deck's, or on a part's deck the
|
|
90
|
+
* chapter the recall named (`recalledFrom`).
|
|
91
|
+
*/
|
|
92
|
+
export async function deckFloat(locals: object, anchorId: string | undefined, base: string): Promise<DeckFloat> {
|
|
93
|
+
const deck = deckOfRoute(await loadManifest(), routeIdFromLocals(locals));
|
|
94
|
+
if (!deck) return { onDeck: false };
|
|
95
|
+
const chapter = anchorId === undefined ? undefined : (deck.recalledFrom?.[anchorId] ?? deck.chapter);
|
|
96
|
+
const recalled =
|
|
97
|
+
anchorId !== undefined &&
|
|
98
|
+
chapter !== undefined &&
|
|
99
|
+
deck.frames.some((frame) => frame.recalls?.includes(anchorId));
|
|
100
|
+
return {
|
|
101
|
+
onDeck: true,
|
|
102
|
+
...(recalled ? { numberHref: `${base.replace(/\/$/, '')}/${chapter}/#${anchorId}` } : {}),
|
|
103
|
+
};
|
|
104
|
+
}
|