explico 0.13.0 → 0.14.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 +894 -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 +43 -0
- package/dist/compiler/cli-main.js +392 -0
- package/dist/compiler/cli.d.ts +424 -9
- package/dist/compiler/cli.js +1289 -8
- package/dist/compiler/collections.d.ts +88 -1
- package/dist/compiler/collections.js +170 -25
- 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 +359 -58
- package/dist/compiler/page-versions.d.ts +160 -0
- package/dist/compiler/page-versions.js +198 -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 +76 -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 +1 -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 +221 -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 +30 -7
- package/dist/rules/rules.schema.json +259 -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 +29 -9
- package/docs/authoring/agents.md +63 -16
- package/docs/authoring/components.md +15 -0
- package/docs/authoring/deck.md +588 -0
- package/docs/authoring/migrating.md +1087 -14
- package/docs/authoring/notation.md +49 -6
- package/docs/authoring/structure.md +80 -1
- package/docs/authoring/versioning.md +54 -2
- package/docs/authoring/visualizations.md +7 -2
- package/docs/course-agent/AGENTS.md +37 -0
- package/docs/course-agent/agents/rules-reviewer.md +33 -0
- package/docs/course-agent/skills/draft-lesson/SKILL.md +37 -0
- package/docs/course-agent/skills/migrate-course/SKILL.md +31 -0
- package/docs/course-agent/skills/release-content/SKILL.md +24 -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 +469 -0
- package/src/compiler/cli.ts +1905 -16
- package/src/compiler/collections.ts +284 -25
- 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 +558 -63
- package/src/compiler/page-versions.ts +359 -0
- package/src/compiler/resolution-report.ts +38 -7
- package/src/compiler/validate-content.ts +212 -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 +29 -0
- 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 +126 -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-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 +257 -4
- package/src/rules/course-rules.ts +21 -1
- package/src/rules/in-effect.ts +54 -8
- 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
|
@@ -13,85 +13,24 @@
|
|
|
13
13
|
%% (‹part›.‹n›). LaTeX does the counting; explico checks every number against
|
|
14
14
|
%% the website when it builds the PDF.
|
|
15
15
|
\NeedsTeXFormat{LaTeX2e}
|
|
16
|
-
\ProvidesClass{explico}[2026/10/
|
|
16
|
+
\ProvidesClass{explico}[2026/10/10 explico course book class]
|
|
17
17
|
|
|
18
18
|
%% `scripts`: the document holds Greek, Cyrillic, CJK or emoji (the exporter
|
|
19
19
|
%% sets it when it does), so LuaLaTeX loads the fallback fonts below.
|
|
20
|
-
\
|
|
21
|
-
\DeclareOption{scripts}{\explico@scriptstrue}
|
|
20
|
+
\DeclareOption{scripts}{\PassOptionsToPackage{scripts}{explico-common}}
|
|
22
21
|
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{book}}
|
|
23
22
|
\ProcessOptions\relax
|
|
24
23
|
\LoadClass[11pt,oneside,openany]{book}
|
|
25
24
|
|
|
26
|
-
%%
|
|
27
|
-
|
|
28
|
-
\RequirePackage{
|
|
29
|
-
%% Rule N17's engine half, as on the website (src/reference/katex-delimiters.mjs):
|
|
30
|
-
%% a negative \delimitershortfall makes every \left...\right pair strictly taller
|
|
31
|
-
%% than its content, so a nest grows outward at each level. TeX's default (5pt)
|
|
32
|
-
%% lets nested pairs round to the same glyph.
|
|
33
|
-
\delimitershortfall=-1pt
|
|
34
|
-
%% Whether a text font sets Greek; if none does, a Greek letter in prose is
|
|
35
|
-
%% set as its math symbol (below, with the other Unicode characters).
|
|
36
|
-
\newif\ifexplico@greek
|
|
37
|
-
\ifPDFTeX
|
|
38
|
-
\RequirePackage[T1]{fontenc}
|
|
39
|
-
\RequirePackage{lmodern}
|
|
40
|
-
\RequirePackage{textcomp}
|
|
41
|
-
\RequirePackage{bm}
|
|
42
|
-
%% A character no pdfTeX font sets (accented Greek, Chinese, an emoji) stays
|
|
43
|
-
%% blank instead of stopping the compile, and the log says so in LuaLaTeX's
|
|
44
|
-
%% words, which the export turns into its warning about blank characters.
|
|
45
|
-
\def\UTFviii@undefined@err#1{%
|
|
46
|
-
\typeout{Missing character: There is no
|
|
47
|
-
\expandafter\UTFviii@splitcsname\string#1\relax\space in font pdftex!}}
|
|
48
|
-
\else
|
|
49
|
-
%% Latin Modern for text and math. unicode-math is also what lets a tagged
|
|
50
|
-
%% PDF carry MathML for every formula (luamml needs it); bm does not work
|
|
51
|
-
%% with it, so \bm becomes \boldsymbol.
|
|
52
|
-
\RequirePackage{unicode-math}
|
|
53
|
-
\providecommand{\bm}{\boldsymbol}
|
|
54
|
-
%% Latin Modern has no Greek, Cyrillic, Chinese, Japanese, Korean or emoji.
|
|
55
|
-
%% With `scripts`, prose in those scripts comes from fallback fonts: for each
|
|
56
|
-
%% script, the first of the fonts below this machine has (CMU Serif, from
|
|
57
|
-
%% TeX Live's cm-unicode, matches Latin Modern). A script none of them
|
|
58
|
-
%% covers stays blank, and the export warns about it.
|
|
59
|
-
\ifexplico@scripts
|
|
60
|
-
\def\explico@fallbacks{}
|
|
61
|
-
\def\explico@fallback#1#2{%
|
|
62
|
-
\let\explico@found\@empty
|
|
63
|
-
\@for\explico@candidate:=#1\do{%
|
|
64
|
-
\ifx\explico@found\@empty
|
|
65
|
-
\IfFontExistsTF{\explico@candidate}{%
|
|
66
|
-
\edef\explico@fallbacks{\explico@fallbacks"\explico@candidate:mode=harf;",}%
|
|
67
|
-
\let\explico@found\explico@candidate}{}%
|
|
68
|
-
\fi}%
|
|
69
|
-
\ifx\explico@found\@empty\else#2\fi}
|
|
70
|
-
\explico@fallback{CMU Serif,Noto Serif,DejaVu Serif,FreeSerif}{\explico@greektrue}
|
|
71
|
-
\explico@fallback{Noto Serif CJK SC,Noto Sans CJK SC,FandolSong,Source Han Serif SC}{}
|
|
72
|
-
\explico@fallback{Noto Color Emoji,Twemoji Mozilla,Symbola}{}
|
|
73
|
-
\ifx\explico@fallbacks\@empty\else
|
|
74
|
-
\directlua{luaotfload.add_fallback("explico", {\explico@fallbacks})}%
|
|
75
|
-
\setmainfont{Latin Modern Roman}[RawFeature={fallback=explico}]%
|
|
76
|
-
\fi
|
|
77
|
-
\fi
|
|
78
|
-
\fi
|
|
79
|
-
\RequirePackage{microtype}
|
|
25
|
+
%% What the deck theme shares: engine, fonts, colours, figures, TikZ, boxes,
|
|
26
|
+
%% Unicode, notation markers and cross-references (explico-common.sty).
|
|
27
|
+
\RequirePackage{explico-common}
|
|
80
28
|
|
|
81
|
-
%% --- Page
|
|
29
|
+
%% --- Page ---------------------------------------------------------------------
|
|
82
30
|
\RequirePackage[margin=1in]{geometry}
|
|
83
|
-
\RequirePackage{xcolor}
|
|
84
|
-
\definecolor{explicoaccent}{HTML}{12775C}
|
|
85
|
-
\definecolor{explicoframe}{HTML}{9DB8AD}
|
|
86
|
-
\definecolor{explicoback}{HTML}{F3F8F6}
|
|
87
|
-
\definecolor{explicoasidecaution}{HTML}{B5651D}
|
|
88
|
-
\definecolor{explicoasidecautionback}{HTML}{FBF3EA}
|
|
89
|
-
\definecolor{explicorule}{HTML}{8A9A93}
|
|
90
31
|
|
|
91
32
|
%% --- Floats, tables and captions -------------------------------------------
|
|
92
|
-
\RequirePackage{
|
|
93
|
-
\RequirePackage{array,booktabs,tabularx,longtable}
|
|
94
|
-
\RequirePackage[export]{adjustbox}
|
|
33
|
+
\RequirePackage{longtable}
|
|
95
34
|
\RequirePackage{caption}
|
|
96
35
|
\RequirePackage{newfloat}
|
|
97
36
|
\DeclareFloatingEnvironment[
|
|
@@ -155,105 +94,10 @@
|
|
|
155
94
|
\captionsetup{type=#1}%
|
|
156
95
|
}{\end{minipage}\par\medskip}
|
|
157
96
|
\fi
|
|
158
|
-
%% explico's short caption, run in bold before the long one.
|
|
159
|
-
\newcommand*{\ExplicoCaptionTitle}[1]{\textbf{#1}}
|
|
160
|
-
|
|
161
|
-
%% --- Diagrams ---------------------------------------------------------------
|
|
162
|
-
\RequirePackage{tikz}
|
|
163
|
-
\usetikzlibrary{arrows.meta}
|
|
164
|
-
\tikzset{
|
|
165
|
-
explico diagram node/.style={
|
|
166
|
-
draw=explicorule, fill=explicoback, rounded corners=3pt, line width=0.5pt,
|
|
167
|
-
align=center, inner sep=3pt, font=\small,
|
|
168
|
-
},
|
|
169
|
-
explico diagram edge/.style={
|
|
170
|
-
draw=explicorule, line width=0.6pt, -{Stealth[length=5pt,width=4pt]},
|
|
171
|
-
},
|
|
172
|
-
}
|
|
173
97
|
|
|
174
|
-
%% --- Boxes: memos, notes, asides, worked examples, checks ------------------
|
|
175
|
-
\RequirePackage[most]{tcolorbox}
|
|
176
|
-
\tcbset{
|
|
177
|
-
explico/.style={
|
|
178
|
-
enhanced, breakable, colback=explicoback, colframe=explicoframe,
|
|
179
|
-
boxrule=0.5pt, arc=2pt, left=6pt, right=6pt, top=4pt, bottom=4pt,
|
|
180
|
-
fonttitle=\bfseries\small, coltitle=black, colbacktitle=explicoback!60!white,
|
|
181
|
-
titlerule=0.4pt, before skip=10pt plus 2pt, after skip=10pt plus 2pt,
|
|
182
|
-
},
|
|
183
|
-
}
|
|
184
98
|
\RequirePackage{alphalph}
|
|
185
99
|
\RequirePackage{enumitem}
|
|
186
100
|
|
|
187
|
-
%% --- Unicode in text that the default fonts lack ---------------------------
|
|
188
|
-
\RequirePackage{newunicodechar}
|
|
189
|
-
\newunicodechar{°}{\ifmmode^\circ\else\textdegree\fi}
|
|
190
|
-
\newunicodechar{−}{\ensuremath{-}}
|
|
191
|
-
\newunicodechar{×}{\ensuremath{\times}}
|
|
192
|
-
\newunicodechar{±}{\ensuremath{\pm}}
|
|
193
|
-
\newunicodechar{≤}{\ensuremath{\le}}
|
|
194
|
-
\newunicodechar{≥}{\ensuremath{\ge}}
|
|
195
|
-
\newunicodechar{≈}{\ensuremath{\approx}}
|
|
196
|
-
\newunicodechar{≠}{\ensuremath{\neq}}
|
|
197
|
-
\newunicodechar{→}{\ensuremath{\rightarrow}}
|
|
198
|
-
\newunicodechar{←}{\ensuremath{\leftarrow}}
|
|
199
|
-
\newunicodechar{↑}{\ensuremath{\uparrow}}
|
|
200
|
-
\newunicodechar{↓}{\ensuremath{\downarrow}}
|
|
201
|
-
\newunicodechar{⟨}{\ensuremath{\langle}}
|
|
202
|
-
\newunicodechar{⟩}{\ensuremath{\rangle}}
|
|
203
|
-
\newunicodechar{⋮}{\ensuremath{\vdots}}
|
|
204
|
-
\newunicodechar{√}{\ensuremath{\surd}}
|
|
205
|
-
\newunicodechar{∞}{\ensuremath{\infty}}
|
|
206
|
-
\newunicodechar{′}{\ensuremath{'}}
|
|
207
|
-
\newunicodechar{𝒩}{\ensuremath{\mathcal{N}}}
|
|
208
|
-
\newunicodechar{①}{\textcircled{\scriptsize 1}}
|
|
209
|
-
\newunicodechar{②}{\textcircled{\scriptsize 2}}
|
|
210
|
-
\newunicodechar{③}{\textcircled{\scriptsize 3}}
|
|
211
|
-
\newunicodechar{④}{\textcircled{\scriptsize 4}}
|
|
212
|
-
\newunicodechar{⑤}{\textcircled{\scriptsize 5}}
|
|
213
|
-
\newunicodechar{₀}{\textsubscript{0}}
|
|
214
|
-
\newunicodechar{₁}{\textsubscript{1}}
|
|
215
|
-
\newunicodechar{₂}{\textsubscript{2}}
|
|
216
|
-
\newunicodechar{₃}{\textsubscript{3}}
|
|
217
|
-
\newunicodechar{¹}{\textsuperscript{1}}
|
|
218
|
-
\newunicodechar{²}{\textsuperscript{2}}
|
|
219
|
-
\newunicodechar{³}{\textsuperscript{3}}
|
|
220
|
-
%% A Greek letter on its own is a symbol (the polar coordinates ρ and φ in a
|
|
221
|
-
%% caption, which holds no math): it is set as its math symbol. Inside a Greek
|
|
222
|
-
%% word, which the exporter marks \ExplicoGreekWord{…}, it is a letter, set
|
|
223
|
-
%% from the text font's Greek where one is loaded (`scripts`).
|
|
224
|
-
\newif\ifexplico@word
|
|
225
|
-
\DeclareRobustCommand{\ExplicoGreekWord}[1]{{\explico@wordtrue#1}}
|
|
226
|
-
%% Protected, as \ensuremath is: the text of an equation is expanded for its
|
|
227
|
-
%% tagging (alt text, MathML), and an expandable body breaks it there.
|
|
228
|
-
\protected\def\explico@greekletter#1#2{%
|
|
229
|
-
\ifmmode#2\else
|
|
230
|
-
\ifexplico@word
|
|
231
|
-
\ifexplico@greek\char#1\relax\else\ensuremath{#2}\fi
|
|
232
|
-
\else\ensuremath{#2}\fi
|
|
233
|
-
\fi}
|
|
234
|
-
\newunicodechar{α}{\explico@greekletter{"03B1}{\alpha}}
|
|
235
|
-
\newunicodechar{β}{\explico@greekletter{"03B2}{\beta}}
|
|
236
|
-
\newunicodechar{γ}{\explico@greekletter{"03B3}{\gamma}}
|
|
237
|
-
\newunicodechar{δ}{\explico@greekletter{"03B4}{\delta}}
|
|
238
|
-
\newunicodechar{ε}{\explico@greekletter{"03B5}{\varepsilon}}
|
|
239
|
-
\newunicodechar{θ}{\explico@greekletter{"03B8}{\theta}}
|
|
240
|
-
\newunicodechar{λ}{\explico@greekletter{"03BB}{\lambda}}
|
|
241
|
-
\newunicodechar{μ}{\explico@greekletter{"03BC}{\mu}}
|
|
242
|
-
\newunicodechar{π}{\explico@greekletter{"03C0}{\pi}}
|
|
243
|
-
\newunicodechar{ρ}{\explico@greekletter{"03C1}{\rho}}
|
|
244
|
-
\newunicodechar{σ}{\explico@greekletter{"03C3}{\sigma}}
|
|
245
|
-
\newunicodechar{τ}{\explico@greekletter{"03C4}{\tau}}
|
|
246
|
-
\newunicodechar{φ}{\explico@greekletter{"03C6}{\varphi}}
|
|
247
|
-
\newunicodechar{ω}{\explico@greekletter{"03C9}{\omega}}
|
|
248
|
-
\newunicodechar{Γ}{\explico@greekletter{"0393}{\Gamma}}
|
|
249
|
-
\newunicodechar{Δ}{\explico@greekletter{"0394}{\Delta}}
|
|
250
|
-
\newunicodechar{Θ}{\explico@greekletter{"0398}{\Theta}}
|
|
251
|
-
\newunicodechar{Λ}{\explico@greekletter{"039B}{\Lambda}}
|
|
252
|
-
\newunicodechar{Π}{\explico@greekletter{"03A0}{\Pi}}
|
|
253
|
-
\newunicodechar{Σ}{\explico@greekletter{"03A3}{\Sigma}}
|
|
254
|
-
\newunicodechar{Φ}{\explico@greekletter{"03A6}{\Phi}}
|
|
255
|
-
\newunicodechar{Ω}{\explico@greekletter{"03A9}{\Omega}}
|
|
256
|
-
|
|
257
101
|
%% --- Links ------------------------------------------------------------------
|
|
258
102
|
\RequirePackage[colorlinks,linkcolor=explicoaccent,urlcolor=explicoaccent,citecolor=explicoaccent,bookmarksnumbered]{hyperref}
|
|
259
103
|
\pdfstringdefDisableCommands{\let\ExplicoGreekWord\@firstofone}
|
|
@@ -309,18 +153,20 @@
|
|
|
309
153
|
}
|
|
310
154
|
|
|
311
155
|
%% --- Chapter front line -----------------------------------------------------
|
|
312
|
-
%% Under a chapter's title: where it comes from
|
|
156
|
+
%% Under a chapter's title: where it comes from, the version its content is at
|
|
157
|
+
%% (#2, "unchanged since version 0.2.0") and where its live version is.
|
|
313
158
|
\newcommand{\ExplicoSource}[3]{%
|
|
314
159
|
\begingroup\small\color{black!65}%
|
|
315
160
|
\noindent From \emph{#1}%
|
|
316
|
-
\if\relax\detokenize{#2}\relax\else,
|
|
161
|
+
\if\relax\detokenize{#2}\relax\else, #2\fi.%
|
|
317
162
|
\if\relax\detokenize{#3}\relax\else\ Interactive version: \url{#3}\fi
|
|
318
163
|
\par\endgroup\medskip
|
|
319
164
|
}
|
|
320
165
|
|
|
321
166
|
%% --- Books: a part's or the course's PDF ------------------------------------
|
|
322
167
|
%% The title page. #1 title, #2 what it belongs to (empty for the course),
|
|
323
|
-
%% #3
|
|
168
|
+
%% #3 the version the content is at ("unchanged since version 0.2.0"),
|
|
169
|
+
%% #4 authors, #5 website.
|
|
324
170
|
\newcommand{\ExplicoTitlePage}[5]{%
|
|
325
171
|
%% The title page shares page number i with the contents: no anchor of its own.
|
|
326
172
|
\hypersetup{pageanchor=false}%
|
|
@@ -331,7 +177,7 @@
|
|
|
331
177
|
\if\relax\detokenize{#2}\relax\else\vspace{0.8em}{\Large #2\par}\fi
|
|
332
178
|
\if\relax\detokenize{#4}\relax\else\vspace{2.5em}{\large #4\par}\fi
|
|
333
179
|
\vfill
|
|
334
|
-
{Content
|
|
180
|
+
{Content #3\par}
|
|
335
181
|
\if\relax\detokenize{#5}\relax\else\vspace{0.4em}{\small\url{#5}\par}\fi
|
|
336
182
|
\end{titlepage}%
|
|
337
183
|
\hypersetup{pageanchor=true}%
|
|
@@ -345,22 +191,6 @@
|
|
|
345
191
|
%% A part opens on its own page, numbered as on the website.
|
|
346
192
|
\newcommand{\ExplicoPart}[2]{\setcounter{part}{\numexpr#1-1\relax}\part{#2}}
|
|
347
193
|
|
|
348
|
-
%% --- Notation ---------------------------------------------------------------
|
|
349
|
-
%% \explain{key}{tex} and \slot{key}{tex} are explico's markers in math: the
|
|
350
|
-
%% website opens a card for the key; on paper they print their content.
|
|
351
|
-
\providecommand{\explain}[2]{#2}
|
|
352
|
-
\providecommand{\slot}[2]{#2}
|
|
353
|
-
%% \ExplicoNotation{target}{tex}: a formula's symbol that links to its notation entry
|
|
354
|
-
%% (the serializer writes it only where the book has that entry).
|
|
355
|
-
\providecommand{\ExplicoNotation}[2]{\hyperlink{#1}{#2}}
|
|
356
|
-
%% A term in prose with a notation card on the website.
|
|
357
|
-
\newcommand{\ExplicoTerm}[2]{#2}
|
|
358
|
-
|
|
359
|
-
%% --- Cross-references ---------------------------------------------------------
|
|
360
|
-
%% #1 label, #2 text before the number, #3 text after it.
|
|
361
|
-
\newcommand{\ExplicoRef}[3]{\hyperref[#1]{#2\ref*{#1}#3}}
|
|
362
|
-
\newcommand{\ExplicoEqRef}[1]{\hyperref[#1]{(\ref*{#1})}}
|
|
363
|
-
|
|
364
194
|
%% --- Memos --------------------------------------------------------------------
|
|
365
195
|
\newenvironment{ExplicoMemo}[1]{%
|
|
366
196
|
\refstepcounter{explicomemo}%
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { captionTitle } from '../../../
|
|
1
|
+
import { captionTitle } from '../../../reference/float-name';
|
|
2
2
|
import type { ContentSegment } from '../../../reference/mixed-content';
|
|
3
3
|
import type {
|
|
4
4
|
Block,
|
|
@@ -30,8 +30,11 @@ export interface ChapterContext {
|
|
|
30
30
|
readonly pictures: ReadonlyMap<string, string>;
|
|
31
31
|
/** Answers of this chapter's checks, by assessment id, in authored order. */
|
|
32
32
|
readonly checkItems: ReadonlyMap<string, readonly CheckItem[]>;
|
|
33
|
-
/**
|
|
34
|
-
|
|
33
|
+
/**
|
|
34
|
+
* The front line under the title: the course, the version the chapter's
|
|
35
|
+
* content is at (`versionPhrase`, rule C5) and its live URL.
|
|
36
|
+
*/
|
|
37
|
+
readonly source?: { readonly course: string; readonly since?: string; readonly url?: string };
|
|
35
38
|
/**
|
|
36
39
|
* A chapter of a part's or the course's book: its citation keys gain the
|
|
37
40
|
* chapter (`projectiles/projectile-range/openstax`), since each chapter
|
|
@@ -95,7 +98,8 @@ export function escapeText(text: string): string {
|
|
|
95
98
|
.replace(GREEK_WORD, (word) => `\\ExplicoGreekWord{${word}}`);
|
|
96
99
|
}
|
|
97
100
|
|
|
98
|
-
|
|
101
|
+
/** A URL as `\url` and `\href` take it: no braces or backslashes, `%` and `#` escaped. */
|
|
102
|
+
export function escapeUrl(url: string): string {
|
|
99
103
|
return url.replace(/[\\{}]/gu, '').replace(/[%#]/gu, (char) => `\\${char}`);
|
|
100
104
|
}
|
|
101
105
|
|
|
@@ -237,19 +241,19 @@ export function linkExplains(tex: string, linkTo: (key: string) => string | unde
|
|
|
237
241
|
}
|
|
238
242
|
}
|
|
239
243
|
|
|
240
|
-
class ChapterWriter {
|
|
244
|
+
export class ChapterWriter {
|
|
241
245
|
private readonly route: string;
|
|
242
246
|
private readonly citationKeys: Map<string, string>;
|
|
243
247
|
/** Above zero inside a moving argument (a heading, a caption, a title) or a link: no link goes there. */
|
|
244
248
|
private unlinked = 0;
|
|
245
249
|
|
|
246
|
-
constructor(
|
|
250
|
+
constructor(protected readonly context: ChapterContext) {
|
|
247
251
|
this.route = context.page.route;
|
|
248
252
|
this.citationKeys = entryKeys(citationKeys(context.page.blocks));
|
|
249
253
|
}
|
|
250
254
|
|
|
251
255
|
/** A reference-list entry's citation key in this document, by its anchor. */
|
|
252
|
-
|
|
256
|
+
protected citeKey(anchor: string): string {
|
|
253
257
|
const key = this.citationKeys.get(anchor) ?? anchor;
|
|
254
258
|
return this.context.inBook ? `${this.route}/${key}` : key;
|
|
255
259
|
}
|
|
@@ -259,7 +263,7 @@ class ChapterWriter {
|
|
|
259
263
|
}
|
|
260
264
|
|
|
261
265
|
/** Renders `write` with links to notation off: a link cannot nest, or sit in a moving argument. */
|
|
262
|
-
|
|
266
|
+
protected unlinkedWhile<T>(write: () => T): T {
|
|
263
267
|
this.unlinked++;
|
|
264
268
|
try {
|
|
265
269
|
return write();
|
|
@@ -269,22 +273,22 @@ class ChapterWriter {
|
|
|
269
273
|
}
|
|
270
274
|
|
|
271
275
|
/** Inline content with no notation links inside it. */
|
|
272
|
-
|
|
276
|
+
protected plain(inlines: readonly Inline[]): string {
|
|
273
277
|
return this.unlinkedWhile(() => this.inlines(inlines));
|
|
274
278
|
}
|
|
275
279
|
|
|
276
280
|
/** A formula's TeX, with its notation markers linked to the appendix where the document has the entry. */
|
|
277
|
-
|
|
281
|
+
protected math(tex: string): string {
|
|
278
282
|
const targets = this.context.notationTargets;
|
|
279
283
|
if (this.unlinked > 0 || !targets || targets.size === 0) return tex;
|
|
280
284
|
return linkExplains(tex, (key) => (targets.has(key) ? labelOf('notation', key) : undefined));
|
|
281
285
|
}
|
|
282
286
|
|
|
283
|
-
|
|
287
|
+
protected inDocument(target: CourseTarget): boolean {
|
|
284
288
|
return this.context.documentRoutes.has(target.route);
|
|
285
289
|
}
|
|
286
290
|
|
|
287
|
-
|
|
291
|
+
protected canonicalUrl(target: CourseTarget): string | undefined {
|
|
288
292
|
const base = this.context.canonicalBaseUrl;
|
|
289
293
|
if (!base) return undefined;
|
|
290
294
|
const path = target.route ? `${target.route}/` : '';
|
|
@@ -292,7 +296,7 @@ class ChapterWriter {
|
|
|
292
296
|
}
|
|
293
297
|
|
|
294
298
|
/** A cross-reference: LaTeX's number inside the document, the website's outside it. */
|
|
295
|
-
|
|
299
|
+
protected reference(refKind: string, target: CourseTarget, children: readonly Inline[]): string {
|
|
296
300
|
const text = plainText(children);
|
|
297
301
|
if (this.inDocument(target) && target.anchor) {
|
|
298
302
|
const label = labelOf(target.route, target.anchor);
|
|
@@ -352,14 +356,14 @@ class ChapterWriter {
|
|
|
352
356
|
return inlines.map((inline) => this.inline(inline)).join('');
|
|
353
357
|
}
|
|
354
358
|
|
|
355
|
-
|
|
359
|
+
protected segments(segments: readonly ContentSegment[]): string {
|
|
356
360
|
return segments
|
|
357
361
|
.map((segment) => (segment.type === 'math' ? `$${this.math(segment.latex)}$` : escapeText(segment.value)))
|
|
358
362
|
.join('');
|
|
359
363
|
}
|
|
360
364
|
|
|
361
365
|
/** A float's caption: its short caption for the lists, bold before the long one. */
|
|
362
|
-
|
|
366
|
+
protected caption(block: { short?: string; caption: readonly Inline[]; anchor: string }, extra: readonly Inline[] = []): string {
|
|
363
367
|
const short = block.short?.trim();
|
|
364
368
|
const long = [this.plain(block.caption), this.plain(extra)].filter(Boolean).join(' ');
|
|
365
369
|
const title = short ? `\\ExplicoCaptionTitle{${escapeText(captionTitle(short))}} ` : '';
|
|
@@ -371,13 +375,13 @@ class ChapterWriter {
|
|
|
371
375
|
* A float. Inside a box (a memo, a worked example) a float cannot float, so
|
|
372
376
|
* it is set where it stands (`ExplicoHere`, explico.cls) and keeps its number.
|
|
373
377
|
*/
|
|
374
|
-
|
|
378
|
+
protected float(kind: string, inPlace: boolean, content: string, caption: string, captionFirst = false): string {
|
|
375
379
|
const parts = captionFirst ? [caption, content] : [content, caption];
|
|
376
380
|
if (inPlace) return [`\\begin{ExplicoHere}{${kind}}`, ...parts, '\\end{ExplicoHere}'].join('\n');
|
|
377
381
|
return [`\\begin{${kind}}[htbp]`, '\\centering', ...parts, `\\end{${kind}}`].join('\n');
|
|
378
382
|
}
|
|
379
383
|
|
|
380
|
-
|
|
384
|
+
protected picture(anchor: string, picture: FigurePicture, alt: string): string {
|
|
381
385
|
if (picture.kind === 'diagram') return diagramTikz(picture.geometry, this);
|
|
382
386
|
const file = this.context.pictures.get(anchor);
|
|
383
387
|
if (file) {
|
|
@@ -392,7 +396,7 @@ class ChapterWriter {
|
|
|
392
396
|
)}: see the interactive version on the course website.}}`;
|
|
393
397
|
}
|
|
394
398
|
|
|
395
|
-
|
|
399
|
+
protected table(block: Extract<Block, { kind: 'table' }>, inBox = false): string {
|
|
396
400
|
const rows = [...block.head, ...block.body];
|
|
397
401
|
const columns = Math.max(0, ...rows.map((row) => row.reduce((sum, cell) => sum + cell.colspan, 0)));
|
|
398
402
|
if (columns === 0) return '';
|
|
@@ -454,11 +458,11 @@ class ChapterWriter {
|
|
|
454
458
|
}
|
|
455
459
|
|
|
456
460
|
/** A choice's label, its math typeset like the prompt's. */
|
|
457
|
-
|
|
461
|
+
protected optionLabel(option: NonNullable<CheckItem['options']>[number]): string {
|
|
458
462
|
return option.labelSegments ? this.segments(option.labelSegments) : escapeText(option.label);
|
|
459
463
|
}
|
|
460
464
|
|
|
461
|
-
|
|
465
|
+
protected check(block: Extract<Block, { kind: 'check' }>): string {
|
|
462
466
|
const items = this.context.checkItems.get(block.assessmentId) ?? [];
|
|
463
467
|
const questions = items.map((item) => {
|
|
464
468
|
const options =
|
|
@@ -688,7 +692,7 @@ export function serializeChapter(context: ChapterContext): string {
|
|
|
688
692
|
? [`\\ExplicoInteractive{${escapeUrl(source.url)}}`]
|
|
689
693
|
: []
|
|
690
694
|
: [
|
|
691
|
-
`\\ExplicoSource{${escapeText(source.course)}}{${escapeText(source.
|
|
695
|
+
`\\ExplicoSource{${escapeText(source.course)}}{${escapeText(source.since ?? '')}}{${
|
|
692
696
|
source.url ? escapeUrl(source.url) : ''
|
|
693
697
|
}}`,
|
|
694
698
|
];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# TeX Live 2026 packages for explico's LaTeX export, for the package_file of
|
|
2
2
|
# zauguin/install-texlive; tlmgr adds each one's dependencies. This is what a
|
|
3
|
-
# chapter
|
|
4
|
-
# latex-bin brings. Package names change between TeX Live years: check the
|
|
3
|
+
# chapter and a deck read under LuaLaTeX and pdfLaTeX (latexmk -recorder),
|
|
4
|
+
# less what latex-bin brings. Package names change between TeX Live years: check the
|
|
5
5
|
# list again when moving texlive_version.
|
|
6
6
|
|
|
7
7
|
# Engines, formats, build tool
|
|
@@ -41,6 +41,10 @@ tcolorbox
|
|
|
41
41
|
unicode-math
|
|
42
42
|
xcolor
|
|
43
43
|
|
|
44
|
+
# beamerthemeexplico.sty: a deck's slides and handout
|
|
45
|
+
beamer
|
|
46
|
+
translator
|
|
47
|
+
|
|
44
48
|
# What those load
|
|
45
49
|
amscls
|
|
46
50
|
bigintcalc
|