@wxxb789/anc 0.0.1

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.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +295 -0
  3. package/astro.config.mjs +255 -0
  4. package/bin/anc.mjs +798 -0
  5. package/package.json +93 -0
  6. package/public/_headers +45 -0
  7. package/public/favicon.ico +0 -0
  8. package/public/favicon.svg +9 -0
  9. package/public/fonts/Temml.woff2 +0 -0
  10. package/scripts/build-snapshot.js +69 -0
  11. package/scripts/build-wasm.js +67 -0
  12. package/scripts/build-workspace.js +50 -0
  13. package/scripts/copy-snapshot.js +48 -0
  14. package/scripts/copy-wasm.js +57 -0
  15. package/scripts/emit-redirects.js +64 -0
  16. package/scripts/generate-corpus.js +421 -0
  17. package/scripts/init-repository.js +249 -0
  18. package/scripts/load-config.js +975 -0
  19. package/scripts/markdown-to-artifact.js +1286 -0
  20. package/scripts/preview-site.js +364 -0
  21. package/scripts/publish-set-review.js +157 -0
  22. package/scripts/resolve-links.js +640 -0
  23. package/scripts/run-pagefind.js +125 -0
  24. package/scripts/scan-residue.js +1016 -0
  25. package/scripts/scan-secrets.js +268 -0
  26. package/scripts/seed-gitignore.js +410 -0
  27. package/scripts/snapshot-rows.js +205 -0
  28. package/scripts/validate-content.js +95 -0
  29. package/scripts/vendor-provenance.js +307 -0
  30. package/scripts/verify-output-inventory.js +307 -0
  31. package/scripts/write-report.js +351 -0
  32. package/scripts/write-snapshot.js +136 -0
  33. package/src/components/CollectionExplorer.astro +149 -0
  34. package/src/components/FacetIndex.astro +45 -0
  35. package/src/components/LinkedNotes.astro +94 -0
  36. package/src/components/NoteGraph.astro +434 -0
  37. package/src/components/NoteList.astro +54 -0
  38. package/src/components/SiteMetadata.astro +143 -0
  39. package/src/components/TableOfContents.astro +69 -0
  40. package/src/components/TagBrowser.astro +70 -0
  41. package/src/layouts/Layout.astro +305 -0
  42. package/src/lib/artifact-source.js +72 -0
  43. package/src/lib/build-bindings.js +11 -0
  44. package/src/lib/collection-navigation.js +145 -0
  45. package/src/lib/content.js +92 -0
  46. package/src/lib/diagram-mode.js +18 -0
  47. package/src/lib/graph-layout.js +219 -0
  48. package/src/lib/graph-selection.js +84 -0
  49. package/src/lib/graph.js +42 -0
  50. package/src/lib/link-resolution.js +389 -0
  51. package/src/lib/markdown.js +1469 -0
  52. package/src/lib/math-mode.js +31 -0
  53. package/src/lib/math-output.js +131 -0
  54. package/src/lib/math.js +165 -0
  55. package/src/lib/mermaid-environment.js +475 -0
  56. package/src/lib/mermaid-render.js +769 -0
  57. package/src/lib/preview-model.js +96 -0
  58. package/src/lib/relations.js +242 -0
  59. package/src/lib/rendered-marker.js +55 -0
  60. package/src/lib/route-path.js +192 -0
  61. package/src/lib/routes.js +342 -0
  62. package/src/lib/schema.js +578 -0
  63. package/src/lib/site.js +578 -0
  64. package/src/lib/snapshot-contract.js +216 -0
  65. package/src/lib/snapshot-operations.js +147 -0
  66. package/src/lib/snapshot-queries.js +216 -0
  67. package/src/lib/snapshot-reader.js +210 -0
  68. package/src/lib/snapshot.js +233 -0
  69. package/src/lib/sqlite-warning.js +22 -0
  70. package/src/lib/sqlite.js +14 -0
  71. package/src/lib/tag-browser-model.js +18 -0
  72. package/src/lib/translations.js +533 -0
  73. package/src/lib/wasm-asset.js +47 -0
  74. package/src/lib/worker-protocol.js +93 -0
  75. package/src/pages/404.astro +35 -0
  76. package/src/pages/about.astro +100 -0
  77. package/src/pages/collections/[slug].astro +36 -0
  78. package/src/pages/collections/index.astro +33 -0
  79. package/src/pages/graph.astro +64 -0
  80. package/src/pages/index.astro +33 -0
  81. package/src/pages/notes/[slug].astro +509 -0
  82. package/src/pages/privacy.astro +121 -0
  83. package/src/pages/private.astro +59 -0
  84. package/src/pages/recent.astro +33 -0
  85. package/src/pages/robots.txt.js +15 -0
  86. package/src/pages/rss.xml.js +21 -0
  87. package/src/pages/sitemap.xml.js +20 -0
  88. package/src/pages/tags/[tag].astro +56 -0
  89. package/src/pages/tags/index.astro +37 -0
  90. package/src/scripts/code-copy.js +45 -0
  91. package/src/scripts/diagram-disabled.js +16 -0
  92. package/src/scripts/diagram.js +322 -0
  93. package/src/scripts/graph-client.js +222 -0
  94. package/src/scripts/graph-draw.js +166 -0
  95. package/src/scripts/link-preview.js +334 -0
  96. package/src/scripts/math-disabled.js +18 -0
  97. package/src/scripts/math.js +133 -0
  98. package/src/scripts/preferences.js +123 -0
  99. package/src/scripts/search-dialog.js +651 -0
  100. package/src/scripts/snapshot-client.js +157 -0
  101. package/src/scripts/snapshot-worker.js +341 -0
  102. package/src/scripts/tag-browser.js +153 -0
  103. package/src/scripts/theme-init.js +35 -0
  104. package/src/scripts/toc-active.js +38 -0
  105. package/src/styles/code.css +152 -0
  106. package/src/styles/diagram.css +149 -0
  107. package/src/styles/global.css +1739 -0
  108. package/src/styles/graph.css +317 -0
  109. package/src/styles/math.css +376 -0
  110. package/src/styles/tokens.css +171 -0
  111. package/tsconfig.json +25 -0
@@ -0,0 +1,38 @@
1
+ /** Mark the section currently crossing the reading offset in the static TOC. */
2
+ export {};
3
+ const links = [...document.querySelectorAll('.toc a[href^="#"]')];
4
+ const targets = links.flatMap((link) => {
5
+ const id = decodeURIComponent(link.hash.slice(1));
6
+ const heading = document.getElementById(id);
7
+ return heading instanceof HTMLElement ? [{ heading, link }] : [];
8
+ });
9
+ if (targets.length > 0) {
10
+ let frame;
11
+ const update = () => {
12
+ frame = undefined;
13
+ const scrollPadding = Number.parseFloat(getComputedStyle(document.documentElement).scrollPaddingTop) || 0;
14
+ const offset = Math.min(scrollPadding + 1, window.innerHeight / 3);
15
+ let active = targets[0];
16
+ for (const target of targets) {
17
+ if (target.heading.getBoundingClientRect().top > offset)
18
+ break;
19
+ active = target;
20
+ }
21
+ for (const target of targets) {
22
+ if (target === active)
23
+ target.link.setAttribute('aria-current', 'location');
24
+ else
25
+ target.link.removeAttribute('aria-current');
26
+ }
27
+ };
28
+ const schedule = () => {
29
+ if (frame === undefined)
30
+ frame = window.requestAnimationFrame(update);
31
+ };
32
+ update();
33
+ // This static site has no client navigation: one module instance and these
34
+ // listeners share the document lifetime, so there is no teardown boundary.
35
+ // Smooth hash navigation emits scroll events throughout its movement.
36
+ window.addEventListener('scroll', schedule, { passive: true });
37
+ window.addEventListener('resize', schedule, { passive: true });
38
+ }
@@ -0,0 +1,152 @@
1
+ /*
2
+ * Syntax highlighting, loaded only by pages that contain a code fence.
3
+ *
4
+ * Split out of `global.css` rather than merged into it because owner decision 7
5
+ * makes every heavy asset load per page and per invocation, and `token-*` is the
6
+ * first asset that qualifies: it is the largest single block of rendered-Markdown
7
+ * CSS and it is dead weight on the many notes with no code in them.
8
+ * `RenderedNote.hasCode` is the gate, and `src/pages/notes/[slug].astro` emits
9
+ * the `<link>` only when it is true. TK-15 adds the math and Mermaid sheets
10
+ * behind `hasMath` and `hasMermaid` through the same mechanism.
11
+ *
12
+ * Only the `token-*` map moved. `.code-block` stays in `global.css`: a Mermaid
13
+ * fence also renders as `figure.code-block` while setting `hasMermaid` rather
14
+ * than `hasCode`, so gating the figure's own rules on `hasCode` would ship an
15
+ * unstyled block on a diagram-only page. Nothing emits a `token-*` span except
16
+ * the highlighter, which never runs for Mermaid or math, so this file's gate is
17
+ * exact.
18
+ *
19
+ * Every colour is a token declared in `tokens.css`, which the global stylesheet
20
+ * has already loaded by the time this one applies. `tests/design-tokens.test.ts`
21
+ * measures both syntax hues on all three backgrounds in both themes.
22
+ */
23
+
24
+ /*
25
+ * Prism's token vocabulary is open-ended and this maps it onto four roles, not
26
+ * onto Prism's own names: keywords and operators, literals (numbers, booleans,
27
+ * constants), strings, and comments. Anything unmapped inherits the body colour,
28
+ * which is a readable default rather than an invisible one — the failure mode
29
+ * of a highlighting theme should be "less colour", never "no text".
30
+ *
31
+ * Colour is never the only signal: comments are italic, keywords are bold. A
32
+ * reader with any colour vision deficiency, or reading a printed page, still
33
+ * sees the structure.
34
+ *
35
+ * Eight of these names are here because TK-11's fixture corpus produced them
36
+ * and the published one-note corpus never had: Python, JavaScript, and
37
+ * PowerShell fences emit `builtin`, `class-name`, `control-flow`, `module`,
38
+ * `arrow`, `function-variable`, `doc-comment`, and `triple-quoted-string`. Each
39
+ * is folded into the role it already belongs to rather than given a fifth
40
+ * colour. Seven of them nest inside an already-mapped token, so only
41
+ * `token-builtin` changed what a reader sees; the rest close the coverage gate
42
+ * on a class that could ship alone the day a grammar emits it that way.
43
+ */
44
+ .token-comment,
45
+ .token-doc-comment,
46
+ .token-prolog,
47
+ .token-doctype,
48
+ .token-cdata {
49
+ color: var(--color-muted);
50
+ font-style: italic;
51
+ }
52
+
53
+ .token-keyword,
54
+ .token-control-flow,
55
+ /* bash grammar spells a for/select loop this way; it is control flow. */
56
+ .token-for-or-select,
57
+ .token-module,
58
+ .token-operator,
59
+ .token-arrow,
60
+ .token-atrule,
61
+ .token-important,
62
+ .token-selector,
63
+ .token-tag {
64
+ color: var(--color-syntax-keyword);
65
+ font-weight: 600;
66
+ }
67
+
68
+ /*
69
+ * Container tokens, which wrap other tokens rather than marking a leaf: batch's
70
+ * `command` spans a whole command line with `keyword` nested inside it, and
71
+ * `namespace` wraps a qualified name. Colouring one paints everything it
72
+ * contains — a whole command line came out entirely purple — so
73
+ * they inherit and let the nested token carry the meaning. `inherit` is
74
+ * declared rather than omitted so the intent is visible and the rule exists.
75
+ */
76
+ .token-command,
77
+ .token-namespace {
78
+ color: inherit;
79
+ }
80
+
81
+ .token-string,
82
+ .token-triple-quoted-string,
83
+ .token-char,
84
+ .token-attr-value,
85
+ .token-regex {
86
+ color: var(--color-accent);
87
+ }
88
+
89
+ .token-number,
90
+ .token-boolean,
91
+ .token-constant,
92
+ .token-symbol,
93
+ .token-property,
94
+ .token-attr-name,
95
+ .token-variable,
96
+ .token-parameter,
97
+ .token-function,
98
+ .token-function-variable,
99
+ /* `method` and `property-access` are what Prism calls a function and a field
100
+ reached through a receiver, in the grammars that distinguish them —
101
+ JavaScript among them. Both were missing while every fence in this
102
+ repository's own corpus was `cmd`, which produces neither, so the gate that
103
+ requires every shipped class to be styled had nothing to catch. Replacing
104
+ that corpus with one carrying a JavaScript fence is what surfaced them.
105
+ Grouped with `function` because they are the same things with a dot in
106
+ front. */
107
+ .token-method,
108
+ .token-property-access,
109
+ .token-builtin,
110
+ .token-class-name {
111
+ color: var(--color-syntax-literal);
112
+ }
113
+
114
+ /* Structure, not meaning: punctuation stays body-coloured so it recedes. */
115
+ .token-punctuation,
116
+ .token-entity {
117
+ color: var(--color-text);
118
+ }
119
+
120
+ /* Inserted by `code-copy.ts`, so no scripting means no dead control. */
121
+ .code-copy {
122
+ display: block;
123
+ margin: 0 0 var(--space-2) auto;
124
+ padding: var(--space-1) var(--space-2);
125
+ border: 1px solid var(--color-line-strong);
126
+ border-radius: var(--radius-sm);
127
+ background: var(--color-surface);
128
+ color: var(--color-text);
129
+ font: inherit;
130
+ font-size: var(--text-sm);
131
+ cursor: pointer;
132
+ }
133
+
134
+ .code-copy:disabled {
135
+ cursor: wait;
136
+ opacity: 0.75;
137
+ }
138
+
139
+ /*
140
+ * Deliberately unstyled classes are recorded once, in `global.css`'s
141
+ * "deliberately unstyled" block, which is the list `tests/built-output.test.ts`
142
+ * reads and asserts against. Restating it here would be a second copy that gate
143
+ * does not check, and therefore a copy free to drift.
144
+ *
145
+ * One thing does belong here, because it is a property of the split rather than
146
+ * of either file: **no rule in `global.css` may style `.token` or any
147
+ * `token-*`.** The built `<head>` currently orders this sheet *before* the
148
+ * layout's, so an equal-specificity rule there would win over every rule above
149
+ * and repaint the whole token stream in one colour. Nothing styles them there
150
+ * today, so the order is not load-bearing — but it is the one way this split
151
+ * could fail silently, and it is why the classes stay together in one file.
152
+ */
@@ -0,0 +1,149 @@
1
+ /*
2
+ * Diagrams.
3
+ *
4
+ * Loaded only on pages whose body contains one, via the conditional `<link>` in
5
+ * `src/pages/notes/[slug].astro` gated on `RenderedNote.hasMermaid` — owner
6
+ * decision 7. A page with no diagram pays nothing, asserted in both directions
7
+ * by `tests/math-and-diagrams.test.ts`.
8
+ *
9
+ * This is the *whole* diagram stylesheet, in both modes, and it is small on
10
+ * purpose. `src/lib/mermaid-render.ts` flattens Mermaid's own injected
11
+ * stylesheet onto the elements as SVG presentation attributes at build time, so
12
+ * nothing here reproduces Mermaid's theming. The alternative — hoisting that
13
+ * stylesheet into 23 per-diagram-type files — was rejected on a measurement:
14
+ * 86% of its rules (1,279 of 1,495) match no element in any rendered diagram,
15
+ * because Mermaid emits the union of every shape it could draw.
16
+ *
17
+ * Colour is likewise absent here. Each diagram carries its own
18
+ * `light-dark(light, dark)` values, paired at build time from two renders, so
19
+ * one SVG follows the system preference and the site's own theme toggle with no
20
+ * second file and no script.
21
+ */
22
+
23
+ .diagram {
24
+ margin-block: var(--space-6);
25
+ /* `figure` has a user-agent margin-inline of 40px, which would indent the
26
+ diagram relative to the prose around it. */
27
+ margin-inline: 0;
28
+ }
29
+
30
+ /*
31
+ * The diagram itself.
32
+ *
33
+ * The SVG carries a `width` attribute holding its intrinsic size and no
34
+ * `height`, so `max-width: 100%` lets it shrink to fit a 320 px viewport while
35
+ * the `viewBox` preserves its aspect ratio. Without `height: auto` a browser
36
+ * would keep the attribute width's implied height and distort it.
37
+ */
38
+ .diagram svg {
39
+ max-width: 100%;
40
+ height: auto;
41
+ }
42
+
43
+ /*
44
+ * The diagram is laid out at 16 px and must render at 16 px.
45
+ *
46
+ * Mermaid computes every box from its own measurement of the label text at its
47
+ * configured `fontSize`, which is 16. This site's body text is `--text-base`,
48
+ * 1.0625rem — **17 px** — and the labels inherit it, so each one rendered 6%
49
+ * wider than the box built for it and every multi-word label was visibly
50
+ * clipped: "Private vault" showed as "Private vaul". Measured in Chromium, not
51
+ * inferred; the two-thousandths-of-an-em font-metric differences between Arial
52
+ * and the site's stack are within 2.7% and were *not* the cause.
53
+ *
54
+ * Pinning the size here rather than raising Mermaid's is the smaller fix: the
55
+ * diagram's geometry is baked into the SVG at build time, so the number the
56
+ * renderer measured with is the only number that can be correct. `px` rather
57
+ * than `rem` for the same reason — a reader who scales the root font size
58
+ * scales the whole SVG, which keeps the label inside its box, whereas scaling
59
+ * only the text would reintroduce exactly this clipping.
60
+ *
61
+ * **Restricted to `foreignObject` content.** An SVG `<text>` is deliberately
62
+ * excluded: those carry their own `font-size` presentation attribute — 12 px on
63
+ * a radar axis label, 38 px on a treemap label, 32 px on the info banner — which
64
+ * the flattening pass wrote from Mermaid's own stylesheet, and a class rule
65
+ * beats a presentation attribute. An earlier version of this rule included
66
+ * `text` and silently resized 139 elements across seven diagram types. Caught by
67
+ * comparing computed styles against the unflattened SVG in a real browser.
68
+ */
69
+ .diagram foreignObject div,
70
+ .diagram foreignObject span {
71
+ font-size: 16px;
72
+ }
73
+
74
+ .diagram-canvas {
75
+ /* A wide diagram scrolls rather than widening the page. Centred, because a
76
+ diagram narrower than the measure otherwise sits oddly against the text.
77
+ `tabindex="0"` is on the element itself: a scrollable region must be
78
+ reachable by keyboard, and the browser then scrolls it with the arrows. */
79
+ overflow-x: auto;
80
+ text-align: center;
81
+ }
82
+
83
+ .diagram-canvas:focus-visible {
84
+ outline: 2px solid var(--color-focus);
85
+ outline-offset: 2px;
86
+ }
87
+
88
+ /*
89
+ * Client mode only: the diagram's source, shown until the runtime replaces it.
90
+ *
91
+ * This is also what a reader without JavaScript is left with, which is why it
92
+ * is styled as a legible code block rather than hidden. Requirements §5.2 and
93
+ * §5.3 ask for the static baseline to be the product; client mode is a
94
+ * deliberate carve-out from that, and showing the source is the honest form of
95
+ * the carve-out — a hidden element would present the same page as complete
96
+ * while silently missing a figure.
97
+ */
98
+ .diagram-source {
99
+ margin: 0;
100
+ padding: var(--space-4);
101
+ overflow-x: auto;
102
+ background: var(--color-surface-alt);
103
+ border: 1px solid var(--color-line);
104
+ border-radius: var(--radius-md);
105
+ font-family: var(--font-mono);
106
+ font-size: var(--text-sm);
107
+ line-height: var(--leading-body);
108
+ color: var(--color-text);
109
+ }
110
+
111
+ .diagram figcaption {
112
+ margin-top: var(--space-2);
113
+ color: var(--color-muted);
114
+ font-size: var(--text-sm);
115
+ text-align: center;
116
+ }
117
+
118
+ /*
119
+ * Classes the flattening pass writes.
120
+ *
121
+ * The six non-presentational declarations that survive flattening, from
122
+ * `LAYOUT_CLASSES` in `src/lib/mermaid-render.ts`. Every other declaration in
123
+ * Mermaid's stylesheet is an SVG presentation attribute and is written onto the
124
+ * element itself, which is why this list is six rules rather than a stylesheet.
125
+ */
126
+ .diagram-center { text-align: center; }
127
+ .diagram-left { text-align: left; }
128
+ .diagram-start { text-align: start; }
129
+ .diagram-nowrap { white-space: nowrap; }
130
+ .diagram-line { line-height: 1.5; }
131
+ .diagram-blend { mix-blend-mode: multiply; }
132
+ .diagram-table { display: table; }
133
+
134
+ /*
135
+ * A diagram's HTML labels live in a `foreignObject`, outside the article's own
136
+ * cascade for margins: the browser applies the default `p` margin there and
137
+ * pushes the label off its own centre.
138
+ */
139
+ .diagram foreignObject p {
140
+ margin: 0;
141
+ }
142
+
143
+ @media print {
144
+ /* A scroll container prints as its visible window, cutting the diagram off at
145
+ the page edge. Letting it size itself prints the whole figure. */
146
+ .diagram-canvas {
147
+ overflow-x: visible;
148
+ }
149
+ }