explico 0.1.1 → 0.3.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 +102 -0
- package/README.md +46 -5
- package/dist/compiler/cli.d.ts +17 -0
- package/dist/compiler/cli.js +41 -3
- package/dist/compiler/collections.js +31 -1
- package/dist/compiler/course-config.d.ts +52 -1
- package/dist/compiler/knowledge-version.d.ts +58 -0
- package/dist/compiler/knowledge-version.js +80 -0
- package/dist/compiler/manifest.d.ts +87 -3
- package/dist/compiler/manifest.js +133 -20
- package/dist/compiler/resolution-report.d.ts +5 -0
- package/dist/reference/base-operators.d.mts +38 -0
- package/dist/reference/base-operators.mjs +103 -0
- package/dist/reference/consistency.d.ts +7 -2
- package/dist/reference/consistency.js +142 -2
- package/dist/reference/diagram-layout.d.ts +63 -0
- package/dist/reference/diagram-layout.js +122 -0
- package/dist/reference/equations-validate.d.ts +5 -0
- package/dist/reference/equations-validate.js +1 -1
- package/dist/reference/equations.d.mts +76 -18
- package/dist/reference/equations.mjs +118 -41
- package/dist/reference/figures-validate.d.ts +21 -0
- package/dist/reference/figures-validate.js +13 -0
- package/dist/reference/gate-math.d.ts +5 -4
- package/dist/reference/gate-math.js +73 -2
- package/dist/reference/gloss.d.ts +87 -0
- package/dist/reference/gloss.js +59 -0
- package/dist/reference/keyed-float-validate.d.ts +67 -0
- package/dist/reference/keyed-float-validate.js +110 -0
- package/dist/reference/keyed-jsx-floats.d.mts +56 -0
- package/dist/reference/keyed-jsx-floats.mjs +167 -0
- package/dist/reference/math-glyphs.d.mts +18 -0
- package/dist/reference/math-glyphs.mjs +92 -0
- package/dist/reference/registry.js +25 -0
- package/dist/reference/rehype-heading-anchors.d.mts +1 -0
- package/dist/reference/rehype-heading-anchors.mjs +144 -0
- package/dist/reference/remark-notation.d.mts +12 -0
- package/dist/reference/remark-notation.mjs +228 -32
- package/dist/reference/tables-validate.d.ts +21 -0
- package/dist/reference/tables-validate.js +13 -0
- package/dist/reference/types.d.ts +25 -2
- package/dist/reference/units-vocab.js +19 -1
- package/docs/VERSIONING.md +66 -0
- package/docs/authoring/README.md +96 -0
- package/docs/authoring/agents.md +63 -0
- package/docs/authoring/migrating.md +107 -0
- package/docs/authoring/notation.md +296 -0
- package/docs/authoring/versioning.md +116 -0
- package/docs/authoring/visualizations.md +195 -0
- package/package.json +20 -5
- package/src/compiler/cli.ts +49 -0
- package/src/compiler/collections.ts +52 -3
- package/src/compiler/course-config.ts +54 -0
- package/src/compiler/knowledge-version.ts +157 -0
- package/src/compiler/manifest.ts +270 -17
- package/src/components/CurriculumMap.astro +27 -0
- package/src/components/HoverPanel.astro +42 -0
- package/src/components/citation/CitationLayer.astro +1 -0
- package/src/components/diagram/Diagram.astro +317 -0
- package/src/components/examples/CompactExamples.astro +1 -1
- package/src/components/figure/Figure.astro +104 -0
- package/src/components/hover-panel.ts +71 -5
- package/src/components/notation/NotationFormula.astro +154 -0
- package/src/components/notation/NotationGlossary.astro +60 -0
- package/src/components/notation/NotationLayer.astro +248 -103
- package/src/components/notation/render-notation-math.ts +66 -0
- package/src/components/popup-stack.ts +345 -0
- package/src/components/reference/FloatRefLayer.astro +671 -0
- package/src/components/starlight/AboutPanel.astro +255 -0
- package/src/components/starlight/HeadingAnchorEnhancer.astro +131 -0
- package/src/components/starlight/KeyedFloatEnhancer.astro +137 -0
- package/src/components/starlight/LayoutSocialIcons.astro +12 -0
- package/src/components/starlight/LessonFooter.astro +8 -2
- package/src/components/table/Table.astro +104 -0
- package/src/content-config.ts +38 -0
- package/src/reference/base-operators.mjs +103 -0
- package/src/reference/consistency.ts +236 -2
- package/src/reference/diagram-layout.ts +246 -0
- package/src/reference/equations-validate.ts +6 -1
- package/src/reference/equations.mjs +118 -41
- package/src/reference/figures-validate.ts +40 -0
- package/src/reference/gate-math.ts +104 -7
- package/src/reference/gloss.ts +153 -0
- package/src/reference/keyed-float-validate.ts +207 -0
- package/src/reference/keyed-jsx-floats.mjs +167 -0
- package/src/reference/math-glyphs.mjs +92 -0
- package/src/reference/registry.ts +43 -0
- package/src/reference/rehype-heading-anchors.mjs +144 -0
- package/src/reference/remark-notation.mjs +228 -32
- package/src/reference/tables-validate.ts +40 -0
- package/src/reference/types.ts +26 -1
- package/src/reference/units-vocab.ts +18 -0
- package/src/styles/global.css +193 -3
- package/src/components/starlight/EquationEnhancer.astro +0 -72
package/src/styles/global.css
CHANGED
|
@@ -668,7 +668,7 @@
|
|
|
668
668
|
`.keyed-equation` with an `id="eq-<key>"`, a `data-eq-number`, and a
|
|
669
669
|
focusable number link. Prose refers to it with `[[eq:key]]` →
|
|
670
670
|
`a.equation-ref`. The deep-link highlight is a pure-CSS `:target` animation
|
|
671
|
-
with a reduced-motion fallback; `
|
|
671
|
+
with a reduced-motion fallback; `KeyedFloatEnhancer.astro` only re-triggers it
|
|
672
672
|
on a repeated activation and moves focus. */
|
|
673
673
|
.sl-markdown-content .keyed-equation {
|
|
674
674
|
position: relative;
|
|
@@ -690,13 +690,76 @@
|
|
|
690
690
|
font-size: var(--sl-text-sm);
|
|
691
691
|
color: var(--sl-color-text-accent);
|
|
692
692
|
text-decoration: none;
|
|
693
|
+
/* Present but quiet by default (F4): partially visible so a reader
|
|
694
|
+
scanning the page can always find the number without hunting, but it
|
|
695
|
+
still doesn't compete with the equation itself. Hover, focus, and a
|
|
696
|
+
deep-link (`:target`) push it to full opacity, same as before. */
|
|
697
|
+
opacity: 0.45;
|
|
698
|
+
transition: opacity 120ms ease-out;
|
|
693
699
|
}
|
|
694
700
|
|
|
695
|
-
|
|
701
|
+
@media (hover: none) {
|
|
702
|
+
/* No hover to reveal it on touch, so keep the number legible there. */
|
|
703
|
+
.sl-markdown-content a.keyed-equation__number {
|
|
704
|
+
opacity: 1;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
.sl-markdown-content .keyed-equation:hover a.keyed-equation__number,
|
|
709
|
+
.sl-markdown-content .keyed-equation:focus-within a.keyed-equation__number,
|
|
710
|
+
.sl-markdown-content .keyed-equation:target a.keyed-equation__number,
|
|
696
711
|
.sl-markdown-content a.keyed-equation__number:focus-visible {
|
|
712
|
+
opacity: 1;
|
|
697
713
|
text-decoration: underline;
|
|
698
714
|
}
|
|
699
715
|
|
|
716
|
+
@media (prefers-reduced-motion: reduce) {
|
|
717
|
+
.sl-markdown-content a.keyed-equation__number {
|
|
718
|
+
transition: none;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
@media (forced-colors: active) {
|
|
723
|
+
.sl-markdown-content a.keyed-equation__number {
|
|
724
|
+
opacity: 1;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/* Once a reader has actually arrived at (or clicked through to) an equation —
|
|
729
|
+
a deep-link on load, an in-page `[[eq:key]]` navigation, or pinning its
|
|
730
|
+
preview card (`FloatRefLayer.astro`) — its number stays fully visible
|
|
731
|
+
for the rest of the page's life, not just while `:target` or `:hover`
|
|
732
|
+
holds. `KeyedFloatEnhancer.astro` and `FloatRefLayer.astro` add this class
|
|
733
|
+
in JS; it is never present in the static markup. One extra class over the
|
|
734
|
+
base selector's specificity, so this always wins regardless of rule order. */
|
|
735
|
+
.sl-markdown-content a.keyed-equation__number.eq-number-revealed {
|
|
736
|
+
opacity: 1;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/* A referencing `[[eq:key]]` link elsewhere in the prose was hovered/focused
|
|
740
|
+
and the equation it points to is already fully on screen: highlight it in
|
|
741
|
+
place instead of opening a preview card (`FloatRefLayer.astro` decides
|
|
742
|
+
which). Mirrors the reduced-motion `:target` treatment below — steady, no
|
|
743
|
+
keyframe — since this fires on every hover, not just a rare deep-link. */
|
|
744
|
+
.sl-markdown-content .keyed-equation.eq-ref-highlight {
|
|
745
|
+
background: var(--sl-color-accent-low);
|
|
746
|
+
outline: 2px solid var(--sl-color-accent);
|
|
747
|
+
outline-offset: 0.2rem;
|
|
748
|
+
transition:
|
|
749
|
+
background 120ms ease-out,
|
|
750
|
+
outline-color 120ms ease-out;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
.sl-markdown-content .keyed-equation.eq-ref-highlight a.keyed-equation__number {
|
|
754
|
+
opacity: 1;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
@media (forced-colors: active) {
|
|
758
|
+
.sl-markdown-content .keyed-equation.eq-ref-highlight {
|
|
759
|
+
outline-color: Highlight;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
700
763
|
.sl-markdown-content a.equation-ref {
|
|
701
764
|
font-variant-numeric: tabular-nums;
|
|
702
765
|
font-weight: 600;
|
|
@@ -725,7 +788,7 @@
|
|
|
725
788
|
}
|
|
726
789
|
|
|
727
790
|
.sl-markdown-content .keyed-equation:target {
|
|
728
|
-
animation: eq-flash
|
|
791
|
+
animation: eq-flash 5s ease-out both;
|
|
729
792
|
}
|
|
730
793
|
|
|
731
794
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -756,8 +819,135 @@
|
|
|
756
819
|
transform: none;
|
|
757
820
|
text-align: end;
|
|
758
821
|
color: inherit;
|
|
822
|
+
opacity: 1;
|
|
759
823
|
}
|
|
760
824
|
.sl-markdown-content .keyed-equation {
|
|
761
825
|
padding-inline-end: 0;
|
|
762
826
|
}
|
|
763
827
|
}
|
|
828
|
+
|
|
829
|
+
/* `<Table>`/`<Figure>` keyed floats (F-tables-figures) — the same deep-link
|
|
830
|
+
and hover-highlight treatment as equations above, via `KeyedFloatEnhancer`
|
|
831
|
+
and `FloatRefLayer.astro`. Unlike an equation's number (quiet until
|
|
832
|
+
hovered, F4), a table/figure number lives in its always-visible caption,
|
|
833
|
+
so there is no opacity dance to mirror here — only the `:target` flash
|
|
834
|
+
(reusing the `eq-flash` keyframe above) and the ref-highlight. */
|
|
835
|
+
.sl-markdown-content a.table-ref,
|
|
836
|
+
.sl-markdown-content a.figure-ref {
|
|
837
|
+
font-variant-numeric: tabular-nums;
|
|
838
|
+
font-weight: 600;
|
|
839
|
+
text-decoration: underline;
|
|
840
|
+
text-underline-offset: 0.15em;
|
|
841
|
+
padding-inline: 0.1em;
|
|
842
|
+
border-radius: 0.2em;
|
|
843
|
+
color: var(--sl-color-text-accent);
|
|
844
|
+
white-space: nowrap;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
.sl-markdown-content a.table-ref:hover,
|
|
848
|
+
.sl-markdown-content a.table-ref:focus-visible,
|
|
849
|
+
.sl-markdown-content a.figure-ref:hover,
|
|
850
|
+
.sl-markdown-content a.figure-ref:focus-visible {
|
|
851
|
+
background: var(--sl-color-accent-low);
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
.sl-markdown-content .keyed-table:target,
|
|
855
|
+
.sl-markdown-content .keyed-figure:target {
|
|
856
|
+
animation: eq-flash 5s ease-out both;
|
|
857
|
+
border-radius: 0.3rem;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
@media (prefers-reduced-motion: reduce) {
|
|
861
|
+
.sl-markdown-content .keyed-table:target,
|
|
862
|
+
.sl-markdown-content .keyed-figure:target {
|
|
863
|
+
animation: none;
|
|
864
|
+
background: var(--sl-color-accent-low);
|
|
865
|
+
outline: 2px solid var(--sl-color-accent);
|
|
866
|
+
outline-offset: 0.2rem;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
/* A referencing `[[tab-key]]`/`[[fig-key]]` link elsewhere in the prose was
|
|
871
|
+
hovered/focused and the float it points to is already fully on screen:
|
|
872
|
+
highlight it in place instead of opening a preview card
|
|
873
|
+
(`FloatRefLayer.astro` decides which) — mirrors `.eq-ref-highlight`. */
|
|
874
|
+
.sl-markdown-content .keyed-table.tab-ref-highlight,
|
|
875
|
+
.sl-markdown-content .keyed-figure.fig-ref-highlight {
|
|
876
|
+
background: var(--sl-color-accent-low);
|
|
877
|
+
outline: 2px solid var(--sl-color-accent);
|
|
878
|
+
outline-offset: 0.2rem;
|
|
879
|
+
border-radius: 0.3rem;
|
|
880
|
+
transition:
|
|
881
|
+
background 120ms ease-out,
|
|
882
|
+
outline-color 120ms ease-out;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
@media (forced-colors: active) {
|
|
886
|
+
.sl-markdown-content .keyed-table:target,
|
|
887
|
+
.sl-markdown-content .keyed-figure:target,
|
|
888
|
+
.sl-markdown-content .keyed-table.tab-ref-highlight,
|
|
889
|
+
.sl-markdown-content .keyed-figure.fig-ref-highlight {
|
|
890
|
+
animation: none;
|
|
891
|
+
outline: 2px solid Highlight;
|
|
892
|
+
outline-offset: 0.2rem;
|
|
893
|
+
}
|
|
894
|
+
.sl-markdown-content a.table-ref:hover,
|
|
895
|
+
.sl-markdown-content a.table-ref:focus-visible,
|
|
896
|
+
.sl-markdown-content a.figure-ref:hover,
|
|
897
|
+
.sl-markdown-content a.figure-ref:focus-visible {
|
|
898
|
+
outline: 2px solid Highlight;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
/* Deep-linkable content headings (F3). The wrapper + anchor-link markup and its
|
|
903
|
+
hover/focus reveal come from Starlight's bundled `anchor-links.css`; these
|
|
904
|
+
rules add the sticky-header scroll offset and the `:target` flash, mirroring
|
|
905
|
+
the keyed-equation deep-link treatment. `HeadingAnchorEnhancer.astro` adds
|
|
906
|
+
the JS-only niceties (smooth scroll, repeat-activation re-trigger, and a
|
|
907
|
+
brief highlight of the section body). */
|
|
908
|
+
.sl-markdown-content :is(h1, h2, h3, h4, h5, h6),
|
|
909
|
+
.sl-markdown-content .sl-heading-wrapper {
|
|
910
|
+
scroll-margin-block-start: 5rem;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
@keyframes heading-flash {
|
|
914
|
+
from {
|
|
915
|
+
background: var(--sl-color-accent-low);
|
|
916
|
+
box-shadow: 0 0 0 0.3rem var(--sl-color-accent-low);
|
|
917
|
+
}
|
|
918
|
+
to {
|
|
919
|
+
background: transparent;
|
|
920
|
+
box-shadow: 0 0 0 0.3rem transparent;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
.sl-markdown-content :is(h1, h2, h3, h4, h5, h6):target,
|
|
925
|
+
.sl-markdown-content .sl-heading-wrapper:has(> :target),
|
|
926
|
+
.sl-markdown-content .deep-link-section-flash {
|
|
927
|
+
border-radius: 0.3rem;
|
|
928
|
+
/* `HeadingAnchorEnhancer.astro`'s `FLASH_MS` cleanup timeout must stay
|
|
929
|
+
comfortably longer than this so it never clips the fade-out. */
|
|
930
|
+
animation: heading-flash 5s ease-out both;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
@media (prefers-reduced-motion: reduce) {
|
|
934
|
+
.sl-markdown-content :is(h1, h2, h3, h4, h5, h6):target,
|
|
935
|
+
.sl-markdown-content .sl-heading-wrapper:has(> :target) {
|
|
936
|
+
animation: none;
|
|
937
|
+
background: var(--sl-color-accent-low);
|
|
938
|
+
outline: 2px solid var(--sl-color-accent);
|
|
939
|
+
outline-offset: 0.2rem;
|
|
940
|
+
}
|
|
941
|
+
.sl-markdown-content .deep-link-section-flash {
|
|
942
|
+
animation: none;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
@media (forced-colors: active) {
|
|
947
|
+
.sl-markdown-content :is(h1, h2, h3, h4, h5, h6):target,
|
|
948
|
+
.sl-markdown-content .sl-heading-wrapper:has(> :target) {
|
|
949
|
+
animation: none;
|
|
950
|
+
outline: 2px solid Highlight;
|
|
951
|
+
outline-offset: 0.2rem;
|
|
952
|
+
}
|
|
953
|
+
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
/**
|
|
3
|
-
* Progressive enhancement for keyed equations (Step D7).
|
|
4
|
-
*
|
|
5
|
-
* The no-JS baseline is complete: `remark-notation` emits a real `id="eq-<key>"`
|
|
6
|
-
* container, a focusable number `<a>`, and `[[eq:key]]` renders a plain anchor;
|
|
7
|
-
* `global.css` does the `:target` deep-link highlight (with a
|
|
8
|
-
* `prefers-reduced-motion` fallback) and the sticky-header scroll offset via
|
|
9
|
-
* `scroll-margin`.
|
|
10
|
-
*
|
|
11
|
-
* This script only adds what CSS and anchors cannot:
|
|
12
|
-
* - re-triggering the highlight when the same `#eq-…` is activated again;
|
|
13
|
-
* - a smooth, header-aware scroll on an in-page jump;
|
|
14
|
-
* - moving keyboard focus onto the equation so screen-reader users land on it.
|
|
15
|
-
*
|
|
16
|
-
* Everything here is gated on `prefers-reduced-motion` and degrades to the
|
|
17
|
-
* native anchor behaviour if it throws.
|
|
18
|
-
*/
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
<script>
|
|
22
|
-
(() => {
|
|
23
|
-
const root = document.querySelector('.sl-markdown-content');
|
|
24
|
-
if (!root) return;
|
|
25
|
-
|
|
26
|
-
const reduce = window.matchMedia('(prefers-reduced-motion: reduce)');
|
|
27
|
-
|
|
28
|
-
const activate = (target: HTMLElement | null, doScroll: boolean) => {
|
|
29
|
-
if (!target) return;
|
|
30
|
-
if (!reduce.matches) {
|
|
31
|
-
// Restart the CSS `:target` animation even when the hash is unchanged.
|
|
32
|
-
target.style.animation = 'none';
|
|
33
|
-
void target.offsetWidth;
|
|
34
|
-
target.style.removeProperty('animation');
|
|
35
|
-
}
|
|
36
|
-
if (doScroll) {
|
|
37
|
-
target.scrollIntoView({
|
|
38
|
-
behavior: reduce.matches ? 'auto' : 'smooth',
|
|
39
|
-
block: 'start',
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
target.setAttribute('tabindex', '-1');
|
|
43
|
-
try {
|
|
44
|
-
target.focus({ preventScroll: true });
|
|
45
|
-
} catch {
|
|
46
|
-
target.focus();
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
root.addEventListener('click', (event) => {
|
|
51
|
-
const origin = event.target instanceof Element ? event.target : null;
|
|
52
|
-
const link = origin?.closest('a.equation-ref, a.keyed-equation__number');
|
|
53
|
-
if (!link) return;
|
|
54
|
-
const href = link.getAttribute('href') || '';
|
|
55
|
-
if (!href.startsWith('#eq-')) return; // cross-page: let the browser navigate
|
|
56
|
-
const target = document.getElementById(href.slice(1));
|
|
57
|
-
if (!target) return;
|
|
58
|
-
event.preventDefault();
|
|
59
|
-
if (location.hash !== href) history.pushState(null, '', href);
|
|
60
|
-
activate(target, true);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
window.addEventListener('hashchange', () => {
|
|
64
|
-
if (!location.hash.startsWith('#eq-')) return;
|
|
65
|
-
activate(document.getElementById(location.hash.slice(1)), false);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
if (location.hash.startsWith('#eq-')) {
|
|
69
|
-
activate(document.getElementById(location.hash.slice(1)), true);
|
|
70
|
-
}
|
|
71
|
-
})();
|
|
72
|
-
</script>
|