@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,125 @@
1
+ /**
2
+ * Builds the Pagefind search index over a built site.
3
+ *
4
+ * The JavaScript API rather than the `pagefind` CLI, so that this repository's
5
+ * own build and the packaged one run the same indexer through the same call.
6
+ * The CLI is reachable here — `pagefind` is a declared dependency and pnpm links
7
+ * its binary — but not reliably from a consumer's tree: the executable ships in
8
+ * seven per-platform optional dependencies, and locating it from a
9
+ * `node_modules/.bin` belonging to *the user's* project is an assumption this
10
+ * package should not make when a supported programmatic entry point exists.
11
+ *
12
+ * The exclusion is not a preference. `--exclude-selectors ".heading-anchor"`
13
+ * keeps the `#` character every heading anchor carries out of the index, and
14
+ * without it a search for any heading returns results whose excerpt begins with
15
+ * a stray `#`. It lives here as a constant rather than in a command line so that
16
+ * every path indexes alike: `package.json`'s `build`, `build-fixture.ts`, and
17
+ * the packaged binary all call this one function. They did not — `build` passed
18
+ * the flag and `build-fixture.ts` did not, so the fixture corpus the search
19
+ * gates measure was indexed differently from the corpus that ships, and
20
+ * `tests/search.test.ts` measures results rather than flags and so could not
21
+ * see it.
22
+ */
23
+ import { createIndex, close } from 'pagefind';
24
+ import { mkdirSync, writeFileSync } from 'node:fs';
25
+ import { dirname, join } from 'node:path';
26
+ import { fileURLToPath } from 'node:url';
27
+ import { BuildFailure } from "./write-report.js";
28
+ /**
29
+ * The selectors whose text must not enter the index.
30
+ *
31
+ * `.heading-anchor` is the `#` link every heading carries; indexing it puts a
32
+ * bare `#` into every heading's searchable text.
33
+ *
34
+ * **`code.language-math` is a cost, not a free win, and the cost is stated
35
+ * because it is a real one: a reader can no longer find a note by an expression
36
+ * in it.** Under client rendering the TeX source ships as the fallback a
37
+ * JS-disabled reader sees, and a Pagefind fragment stores extracted *text* with
38
+ * markup stripped — so `f:\mathbb{R} \to \mathbb{C}` arrives in the index with
39
+ * no element around it, where it reads as noise beside the prose and trips the
40
+ * residue scan's `absolute local path` rule with no code region left to exempt
41
+ * it. Measured: the fragment for such a note carries the raw TeX.
42
+ *
43
+ * The alternative is exempting the rule over every fragment, which
44
+ * `scripts/scan-residue.ts` measures as taking a genuinely leaked path with it.
45
+ * Excluding the source from the index is the narrower price, and it is paid by
46
+ * search rather than by the privacy boundary.
47
+ *
48
+ * `src/lib/math.ts` already declines to emit Temml's `<annotation>` copy of the
49
+ * source for the same reason, so this is the same decision applied to the mode
50
+ * where the source is what ships.
51
+ */
52
+ const EXCLUDE_SELECTORS = ['.heading-anchor', 'code.language-math'];
53
+ const DIST = fileURLToPath(new URL('../dist', import.meta.url));
54
+ /**
55
+ * Pagefind's own error strings are third-party, of opaque provenance, and are
56
+ * composed over the directory being indexed — so they go to the report rather
57
+ * than to a stream a workflow log inherits. The public half is which of the
58
+ * three calls failed, which is a literal of this file's own source.
59
+ */
60
+ function pagefindFailed(what, errors) {
61
+ return new BuildFailure('pagefind-failed', `pagefind ${what}`, `pagefind ${what}: ${errors.join('; ')}`);
62
+ }
63
+ /**
64
+ * Write the bundle the indexer authored, synchronously, and only report success
65
+ * when every byte of it is on disk.
66
+ *
67
+ * `writeFiles` is deliberately not used. Measured on CI: its promise resolves
68
+ * before the bundle directory is complete — `pagefind-entry.json` was the first
69
+ * member a gate caught, then a partial content-addressed member failed the
70
+ * secret scanner with `could not inflate one output member`, and two builds of
71
+ * one corpus hashed differently because a tree was read while members were
72
+ * still landing. `close()` terminates the indexer, so an in-flight write can be
73
+ * abandoned permanently, and the existing poll for the manifest alone covered
74
+ * one member of many. A poll over every member (measured while diagnosing this)
75
+ * also cannot be trusted, because members appear and disappear while the
76
+ * writer runs. `getFiles()` is the indexer's authored copy of the complete
77
+ * bundle, and writing it here makes completion structural: each member is
78
+ * closed before this function returns, so no gate can read a tree the indexer
79
+ * is still writing. Measured byte-for-byte equal to `writeFiles` output in a
80
+ * direct author-vs-writer comparison on this host over a 12-page corpus with
81
+ * nested members and CJK text, and in an author-after-write comparison over a
82
+ * 65-page corpus.
83
+ */
84
+ export function writePagefindBundle(bundleDirectory, authored) {
85
+ for (const file of authored) {
86
+ const target = join(bundleDirectory, file.path);
87
+ mkdirSync(dirname(target), { recursive: true });
88
+ writeFileSync(target, file.content);
89
+ }
90
+ }
91
+ export async function indexWithPagefind(siteDirectory) {
92
+ const { index, errors } = await createIndex({ excludeSelectors: EXCLUDE_SELECTORS });
93
+ if (errors.length > 0 || index === undefined) {
94
+ throw pagefindFailed('could not start', errors);
95
+ }
96
+ try {
97
+ const added = await index.addDirectory({ path: siteDirectory });
98
+ if (added.errors.length > 0)
99
+ throw pagefindFailed('failed to index', added.errors);
100
+ const authored = await index.getFiles();
101
+ if (authored.errors.length > 0)
102
+ throw pagefindFailed('could not read back', authored.errors);
103
+ writePagefindBundle(join(siteDirectory, 'pagefind'), authored.files);
104
+ return added.page_count;
105
+ }
106
+ finally {
107
+ // The indexer is a long-lived child process. Left running, the build never
108
+ // exits — which on CI is a job that hangs until its timeout rather than a
109
+ // build that failed.
110
+ await close();
111
+ }
112
+ }
113
+ async function main() {
114
+ try {
115
+ const pages = await indexWithPagefind(DIST);
116
+ console.log(`search index ok: ${pages} page${pages === 1 ? '' : 's'} indexed`);
117
+ return 0;
118
+ }
119
+ catch (error) {
120
+ console.error(error instanceof Error ? error.message : String(error));
121
+ return 1;
122
+ }
123
+ }
124
+ if (process.argv[1] === fileURLToPath(import.meta.url))
125
+ process.exit(await main());