@mvarble/mesearch-cms 0.1.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.
Files changed (90) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +53 -0
  3. package/dist/cms.d.ts +22 -0
  4. package/dist/cms.js +270 -0
  5. package/dist/cms.js.map +1 -0
  6. package/dist/core/bibtex.d.ts +6 -0
  7. package/dist/core/bibtex.js +129 -0
  8. package/dist/core/bibtex.js.map +1 -0
  9. package/dist/core/build.d.ts +29 -0
  10. package/dist/core/build.js +41 -0
  11. package/dist/core/build.js.map +1 -0
  12. package/dist/core/facts.d.ts +4 -0
  13. package/dist/core/facts.js +39 -0
  14. package/dist/core/facts.js.map +1 -0
  15. package/dist/core/frontmatter.d.ts +26 -0
  16. package/dist/core/frontmatter.js +134 -0
  17. package/dist/core/frontmatter.js.map +1 -0
  18. package/dist/core/paths.d.ts +4 -0
  19. package/dist/core/paths.js +17 -0
  20. package/dist/core/paths.js.map +1 -0
  21. package/dist/core/resolver.d.ts +33 -0
  22. package/dist/core/resolver.js +45 -0
  23. package/dist/core/resolver.js.map +1 -0
  24. package/dist/core/scopes.d.ts +9 -0
  25. package/dist/core/scopes.js +29 -0
  26. package/dist/core/scopes.js.map +1 -0
  27. package/dist/core/source.d.ts +15 -0
  28. package/dist/core/source.js +68 -0
  29. package/dist/core/source.js.map +1 -0
  30. package/dist/core/statements.d.ts +18 -0
  31. package/dist/core/statements.js +65 -0
  32. package/dist/core/statements.js.map +1 -0
  33. package/dist/core/store.d.ts +67 -0
  34. package/dist/core/store.js +115 -0
  35. package/dist/core/store.js.map +1 -0
  36. package/dist/core/walk.d.ts +19 -0
  37. package/dist/core/walk.js +122 -0
  38. package/dist/core/walk.js.map +1 -0
  39. package/dist/index.d.ts +13 -0
  40. package/dist/index.js +14 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/model/build.d.ts +13 -0
  43. package/dist/model/build.js +67 -0
  44. package/dist/model/build.js.map +1 -0
  45. package/dist/model/index.d.ts +2 -0
  46. package/dist/model/index.js +3 -0
  47. package/dist/model/index.js.map +1 -0
  48. package/dist/model/outline.d.ts +11 -0
  49. package/dist/model/outline.js +51 -0
  50. package/dist/model/outline.js.map +1 -0
  51. package/dist/presets/blog/index.d.ts +9 -0
  52. package/dist/presets/blog/index.js +346 -0
  53. package/dist/presets/blog/index.js.map +1 -0
  54. package/dist/presets/blog/runtime.d.ts +60 -0
  55. package/dist/presets/blog/runtime.js +55 -0
  56. package/dist/presets/blog/runtime.js.map +1 -0
  57. package/dist/presets/blog/types.d.ts +48 -0
  58. package/dist/presets/blog/types.js +2 -0
  59. package/dist/presets/blog/types.js.map +1 -0
  60. package/dist/presets/mesearch/dates.d.ts +6 -0
  61. package/dist/presets/mesearch/dates.js +100 -0
  62. package/dist/presets/mesearch/dates.js.map +1 -0
  63. package/dist/presets/mesearch/index.d.ts +13 -0
  64. package/dist/presets/mesearch/index.js +407 -0
  65. package/dist/presets/mesearch/index.js.map +1 -0
  66. package/dist/presets/mesearch/runtime.d.ts +56 -0
  67. package/dist/presets/mesearch/runtime.js +57 -0
  68. package/dist/presets/mesearch/runtime.js.map +1 -0
  69. package/dist/presets/mesearch/types.d.ts +46 -0
  70. package/dist/presets/mesearch/types.js +8 -0
  71. package/dist/presets/mesearch/types.js.map +1 -0
  72. package/dist/resolvers/citation.d.ts +38 -0
  73. package/dist/resolvers/citation.js +60 -0
  74. package/dist/resolvers/citation.js.map +1 -0
  75. package/dist/resolvers/equation.d.ts +12 -0
  76. package/dist/resolvers/equation.js +52 -0
  77. package/dist/resolvers/equation.js.map +1 -0
  78. package/dist/resolvers/index.d.ts +4 -0
  79. package/dist/resolvers/index.js +5 -0
  80. package/dist/resolvers/index.js.map +1 -0
  81. package/dist/resolvers/page.d.ts +18 -0
  82. package/dist/resolvers/page.js +61 -0
  83. package/dist/resolvers/page.js.map +1 -0
  84. package/dist/resolvers/statement.d.ts +13 -0
  85. package/dist/resolvers/statement.js +45 -0
  86. package/dist/resolvers/statement.js.map +1 -0
  87. package/dist/runtime.d.ts +1 -0
  88. package/dist/runtime.js +20 -0
  89. package/dist/runtime.js.map +1 -0
  90. package/package.json +80 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facts.js","sourceRoot":"","sources":["../../src/core/facts.ts"],"names":[],"mappings":"AAEA,gFAAgF;AAChF,8EAA8E;AAC9E,+EAA+E;AAC/E,yEAAyE;AACzE,MAAM,UAAU,aAAa,CAAC,KAAY,EAAE,EAAU;IAClD,OAAO,IAAI,CAAC,SAAS,CAAC;QAClB,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,IAAI;QACtC,MAAM,EAAE,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,IAAI,EAAE,KAAK;aACN,MAAM,CAAC,EAAE,CAAC;aACV,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;aACnE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,QAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;YAC3E,KAAK;YACL,KAAK;YACL,IAAI;SACP,CAAC;QACF,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,IAAI;KACtC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAY;IACjC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,KAAK,MAAM,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;QAAE,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,aAAa,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;IACxF,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,4EAA4E;AAC5E,2BAA2B;AAC3B,MAAM,UAAU,SAAS,CAAC,MAA2B,EAAE,KAA0B;IAC7E,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,KAAK;QAAE,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,KAAK;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChF,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,EAAE;QAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrE,OAAO,OAAO,CAAC;AACnB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { KatexMacros } from '@mvarble/mesearch-markdown/katex';
2
+ export declare function parseFrontmatter(source: string): Record<string, unknown>;
3
+ export declare const stripFrontmatter: (source: string) => string;
4
+ export declare class Frontmatter {
5
+ readonly problems: string[];
6
+ readonly filename: string;
7
+ private readonly data;
8
+ private readonly kind;
9
+ private readonly root;
10
+ constructor(root: string, filename: string, data: unknown, kind: string);
11
+ reject(field: string, expected: string): void;
12
+ has(field: string): boolean;
13
+ raw(field: string): unknown;
14
+ requiredString(field: string): string;
15
+ optionalString(field: string): string | undefined;
16
+ requiredDate(field: string): Date;
17
+ optionalDate(field: string): Date | undefined;
18
+ optionalDate(field: string, fallback: Date): Date;
19
+ optionalBoolean(field: string, fallback: boolean): boolean;
20
+ optionalStrings(field: string): string[] | undefined;
21
+ optionalArray(field: string): unknown[] | undefined;
22
+ katexMacros(): KatexMacros;
23
+ slug(): string;
24
+ optionalPath(field: string): string | undefined;
25
+ valid(): boolean;
26
+ }
@@ -0,0 +1,134 @@
1
+ import path from 'node:path';
2
+ import yaml from 'js-yaml';
3
+ import { slugFromFilename, toId } from "./paths.js";
4
+ const FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/;
5
+ // The YAML at the top of a document, or an empty mapping when there is none.
6
+ // Dates come back as `Date`s, which is what the readers below expect.
7
+ export function parseFrontmatter(source) {
8
+ const match = FRONTMATTER.exec(source);
9
+ if (!match)
10
+ return {};
11
+ const data = yaml.load(match[1]);
12
+ if (data == null || typeof data != 'object' || Array.isArray(data))
13
+ return {};
14
+ return data;
15
+ }
16
+ // Everything after the frontmatter block.
17
+ export const stripFrontmatter = (source) => source.replace(FRONTMATTER, '');
18
+ const isDate = (value) => value instanceof Date && !Number.isNaN(value.valueOf());
19
+ // Documents of every kind describe themselves with overlapping frontmatter
20
+ // fields. A reader collects every problem it finds instead of stopping at the
21
+ // first, so one save reports everything wrong with a document, each message
22
+ // naming the file and the field.
23
+ export class Frontmatter {
24
+ problems = [];
25
+ filename;
26
+ data;
27
+ kind;
28
+ root;
29
+ // `filename` is relative to `root`, the way every document is identified.
30
+ constructor(root, filename, data, kind) {
31
+ this.root = root;
32
+ this.filename = filename;
33
+ this.data = data && typeof data == 'object' ? data : {};
34
+ this.kind = kind;
35
+ }
36
+ reject(field, expected) {
37
+ this.problems.push(`${this.filename}: ${this.kind} field \`${field}\` must be ${expected}.`);
38
+ }
39
+ has(field) {
40
+ return field in this.data && this.data[field] !== undefined;
41
+ }
42
+ raw(field) {
43
+ return this.data[field];
44
+ }
45
+ requiredString(field) {
46
+ const value = this.data[field];
47
+ if (typeof value != 'string' || !value) {
48
+ this.reject(field, 'a non-empty string');
49
+ return '';
50
+ }
51
+ return value;
52
+ }
53
+ optionalString(field) {
54
+ if (!this.has(field))
55
+ return undefined;
56
+ return this.requiredString(field) || undefined;
57
+ }
58
+ requiredDate(field) {
59
+ const value = this.data[field];
60
+ if (!isDate(value)) {
61
+ this.reject(field, 'a date');
62
+ return new Date(0);
63
+ }
64
+ return value;
65
+ }
66
+ optionalDate(field, fallback) {
67
+ if (!this.has(field))
68
+ return fallback;
69
+ return this.requiredDate(field);
70
+ }
71
+ optionalBoolean(field, fallback) {
72
+ if (!this.has(field))
73
+ return fallback;
74
+ const value = this.data[field];
75
+ if (typeof value != 'boolean') {
76
+ this.reject(field, 'a boolean');
77
+ return fallback;
78
+ }
79
+ return value;
80
+ }
81
+ optionalStrings(field) {
82
+ if (!this.has(field))
83
+ return undefined;
84
+ const value = this.data[field];
85
+ // A lone string is a list of one: `depends_on: foo` reads as it is meant.
86
+ if (typeof value == 'string' && value)
87
+ return [value];
88
+ if (!Array.isArray(value) || value.some((item) => typeof item != 'string')) {
89
+ this.reject(field, 'a list of strings');
90
+ return undefined;
91
+ }
92
+ return value;
93
+ }
94
+ optionalArray(field) {
95
+ if (!this.has(field))
96
+ return undefined;
97
+ const value = this.data[field];
98
+ if (!Array.isArray(value)) {
99
+ this.reject(field, 'an array');
100
+ return undefined;
101
+ }
102
+ return value;
103
+ }
104
+ katexMacros() {
105
+ const value = this.data.katex_macros ?? this.data.katexMacros;
106
+ if (!value || typeof value != 'object')
107
+ return {};
108
+ return value;
109
+ }
110
+ // Defaults to the filename, or to the directory name for an `index` file,
111
+ // which is what most documents rely on.
112
+ slug() {
113
+ const value = this.data.slug;
114
+ if (typeof value == 'string' && value)
115
+ return value;
116
+ return slugFromFilename(this.filename);
117
+ }
118
+ // A path written relative to the document, as a document id.
119
+ optionalPath(field) {
120
+ if (!this.has(field))
121
+ return undefined;
122
+ const value = this.data[field];
123
+ if (typeof value != 'string') {
124
+ this.reject(field, 'a string path');
125
+ return undefined;
126
+ }
127
+ const absolute = path.resolve(this.root, path.dirname(this.filename), value);
128
+ return toId(this.root, absolute);
129
+ }
130
+ valid() {
131
+ return this.problems.length == 0;
132
+ }
133
+ }
134
+ //# sourceMappingURL=frontmatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/core/frontmatter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare const toId: (root: string, absolute: string) => string;
2
+ export declare const toAbsolute: (root: string, id: string) => string;
3
+ export declare const resolveId: (from: string, relative: string) => string;
4
+ export declare function slugFromFilename(filename: string): string;
@@ -0,0 +1,17 @@
1
+ import path from 'node:path';
2
+ // Every document is identified by its path relative to the project root,
3
+ // written with forward slashes whatever the platform. Absolute paths are what
4
+ // Vite and mdsvex hand around, so the two meet here.
5
+ export const toId = (root, absolute) => path.relative(root, absolute).split(path.sep).join('/');
6
+ export const toAbsolute = (root, id) => path.resolve(root, ...id.split('/'));
7
+ // The document a relative import or link names, as an id.
8
+ export const resolveId = (from, relative) => path.posix.normalize(path.posix.join(path.posix.dirname(from), relative));
9
+ export function slugFromFilename(filename) {
10
+ const basename = path.posix.basename(filename);
11
+ const extname = path.posix.extname(basename);
12
+ const name = extname ? basename.slice(0, -extname.length) : basename;
13
+ if (name != 'index')
14
+ return name;
15
+ return path.posix.dirname(filename).split('/').at(-1);
16
+ }
17
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,yEAAyE;AACzE,8EAA8E;AAC9E,qDAAqD;AACrD,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,QAAgB,EAAE,EAAE,CACnD,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE5D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAU,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAE7F,0DAA0D;AAC1D,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAY,EAAE,QAAgB,EAAE,EAAE,CACxD,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;AAE9E,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACrE,IAAI,IAAI,IAAI,OAAO;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { DocRecord, Store } from './store.ts';
2
+ import type { SourceFile } from './source.ts';
3
+ export interface LinkNode {
4
+ type: 'link';
5
+ url: string;
6
+ title?: string | null;
7
+ children: Array<{
8
+ type: string;
9
+ value?: string;
10
+ }>;
11
+ data?: {
12
+ hProperties?: Record<string, unknown>;
13
+ } & Record<string, unknown>;
14
+ }
15
+ export interface MathNode {
16
+ type: 'math';
17
+ value: string;
18
+ data?: Record<string, unknown>;
19
+ }
20
+ export interface Resolver<T = unknown> {
21
+ name: string;
22
+ matchLink?(url: string, store: Store, doc: DocRecord): string | undefined;
23
+ matchMath?(tex: string): string[];
24
+ resolve(store: Store, doc: DocRecord, written: string): T | undefined;
25
+ unresolved?(store: Store, doc: DocRecord, written: string): string | undefined;
26
+ rewriteLink?(node: LinkNode, target: T): void;
27
+ rewriteMath?(node: MathNode, written: string, target: T): void;
28
+ }
29
+ export declare function resolveReferences(store: Store, doc: DocRecord, file: SourceFile, resolvers: readonly Resolver[]): void;
30
+ export declare function matchLink(resolvers: readonly Resolver[], url: string, store: Store, doc: DocRecord): {
31
+ resolver: Resolver;
32
+ written: string;
33
+ } | undefined;
@@ -0,0 +1,45 @@
1
+ // Records every reference a document makes, reporting the ones that resolve to
2
+ // nothing. Runs once every document has registered what it contributes, so the
3
+ // result does not depend on the order documents were visited in.
4
+ export function resolveReferences(store, doc, file, resolvers) {
5
+ const record = (resolver, written, report) => {
6
+ if (store.ref(doc.id, resolver.name, written))
7
+ return;
8
+ const target = resolver.resolve(store, doc, written);
9
+ if (target !== undefined) {
10
+ store.addRef(doc.id, { resolver: resolver.name, written, target });
11
+ return;
12
+ }
13
+ const message = report ? resolver.unresolved?.(store, doc, written) : undefined;
14
+ if (message)
15
+ store.error(doc.id, message);
16
+ };
17
+ const nodes = file.mdast.children.toReversed();
18
+ while (nodes.length > 0) {
19
+ const node = nodes.pop();
20
+ if ('children' in node && Array.isArray(node.children) && node.children.length) {
21
+ nodes.push(...node.children.toReversed());
22
+ }
23
+ if (node.type == 'math') {
24
+ for (const resolver of resolvers) {
25
+ for (const written of resolver.matchMath?.(node.value) ?? []) {
26
+ record(resolver, written, false);
27
+ }
28
+ }
29
+ }
30
+ if (node.type == 'link') {
31
+ const match = matchLink(resolvers, node.url, store, doc);
32
+ if (match)
33
+ record(match.resolver, match.written, true);
34
+ }
35
+ }
36
+ }
37
+ export function matchLink(resolvers, url, store, doc) {
38
+ for (const resolver of resolvers) {
39
+ const written = resolver.matchLink?.(url, store, doc);
40
+ if (written !== undefined)
41
+ return { resolver, written };
42
+ }
43
+ return undefined;
44
+ }
45
+ //# sourceMappingURL=resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/core/resolver.ts"],"names":[],"mappings":"AAqCA,+EAA+E;AAC/E,+EAA+E;AAC/E,iEAAiE;AACjE,MAAM,UAAU,iBAAiB,CAC7B,KAAY,EACZ,GAAc,EACd,IAAgB,EAChB,SAA8B;IAE9B,MAAM,MAAM,GAAG,CAAC,QAAkB,EAAE,OAAe,EAAE,MAAe,EAAE,EAAE;QACpE,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;YAAE,OAAO;QACtD,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;QACrD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACvB,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YACnE,OAAO;QACX,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAChF,IAAI,OAAO;YAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC,CAAC;IAEF,MAAM,KAAK,GAAkB,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;IAC9D,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;QAC1B,IAAI,UAAU,IAAI,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC7E,KAAK,CAAC,IAAI,CAAC,GAAI,IAAI,CAAC,QAA0B,CAAC,UAAU,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,IAAI,MAAM,EAAE,CAAC;YACtB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBAC/B,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;oBAC3D,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;gBACrC,CAAC;YACL,CAAC;QACL,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,IAAI,MAAM,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;YACzD,IAAI,KAAK;gBAAE,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC3D,CAAC;IACL,CAAC;AACL,CAAC;AAED,MAAM,UAAU,SAAS,CACrB,SAA8B,EAC9B,GAAW,EACX,KAAY,EACZ,GAAc;IAEd,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACtD,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAC5D,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { Store } from './store.ts';
2
+ export interface ParsedReference {
3
+ scopeSlug?: string;
4
+ slug: string;
5
+ }
6
+ export declare function parseReference(ref: string): ParsedReference;
7
+ export declare function resolveReferenceScope(store: Store, sourceScope: string, parsed: ParsedReference): string | undefined;
8
+ export declare const describeScope: (store: Store, scope: string) => string;
9
+ export declare function unresolvedReference(store: Store, source: string, scope: string, kind: string, ref: string): string;
@@ -0,0 +1,29 @@
1
+ // `slug` stays inside the current scope; `some-post/slug` reaches into another.
2
+ // Slugs never contain a slash, so the split is unambiguous.
3
+ export function parseReference(ref) {
4
+ const separator = ref.lastIndexOf('/');
5
+ if (separator < 0)
6
+ return { slug: ref };
7
+ return {
8
+ scopeSlug: ref.slice(0, separator),
9
+ slug: ref.slice(separator + 1),
10
+ };
11
+ }
12
+ // The scope a reference should be looked up in, or undefined when an explicit
13
+ // scope slug names nothing on the site.
14
+ export function resolveReferenceScope(store, sourceScope, parsed) {
15
+ if (typeof parsed.scopeSlug != 'string')
16
+ return sourceScope;
17
+ return store.scopes.get(parsed.scopeSlug);
18
+ }
19
+ // Names a scope the way an author would write it, for error messages.
20
+ export const describeScope = (store, scope) => store.scopeNames.get(scope) ?? `'${scope}'`;
21
+ // The error for a reference that resolved to nothing, with a hint as to why.
22
+ export function unresolvedReference(store, source, scope, kind, ref) {
23
+ const { scopeSlug, slug } = parseReference(ref);
24
+ const hint = typeof scopeSlug == 'string'
25
+ ? `No post or sequence has the slug '${scopeSlug}'.`
26
+ : `Write '<post-or-sequence-slug>/${slug}' to reach a ${kind} outside it.`;
27
+ return `${source}: '${ref}' does not name a ${kind} in ${describeScope(store, scope)}. ${hint}`;
28
+ }
29
+ //# sourceMappingURL=scopes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scopes.js","sourceRoot":"","sources":["../../src/core/scopes.ts"],"names":[],"mappings":"AAaA,gFAAgF;AAChF,4DAA4D;AAC5D,MAAM,UAAU,cAAc,CAAC,GAAW;IACtC,MAAM,SAAS,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,SAAS,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;IACxC,OAAO;QACH,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC;QAClC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;KACjC,CAAC;AACN,CAAC;AAED,8EAA8E;AAC9E,wCAAwC;AACxC,MAAM,UAAU,qBAAqB,CACjC,KAAY,EACZ,WAAmB,EACnB,MAAuB;IAEvB,IAAI,OAAO,MAAM,CAAC,SAAS,IAAI,QAAQ;QAAE,OAAO,WAAW,CAAC;IAC5D,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAC9C,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAY,EAAE,KAAa,EAAE,EAAE,CACzD,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,GAAG,CAAC;AAEhD,6EAA6E;AAC7E,MAAM,UAAU,mBAAmB,CAC/B,KAAY,EACZ,MAAc,EACd,KAAa,EACb,IAAY,EACZ,GAAW;IAEX,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,IAAI,GACN,OAAO,SAAS,IAAI,QAAQ;QACxB,CAAC,CAAC,qCAAqC,SAAS,IAAI;QACpD,CAAC,CAAC,kCAAkC,IAAI,gBAAgB,IAAI,cAAc,CAAC;IACnF,OAAO,GAAG,MAAM,MAAM,GAAG,qBAAqB,IAAI,OAAO,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;AACpG,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { Root } from 'mdast';
2
+ export declare class SourceFile {
3
+ readonly id: string;
4
+ readonly abs: string;
5
+ readonly raw: string;
6
+ private parsedFrontmatter?;
7
+ private frontmatterError?;
8
+ private tree?;
9
+ constructor(root: string, id: string, raw?: string);
10
+ get isMarkdown(): boolean;
11
+ get frontmatter(): Record<string, unknown>;
12
+ get frontmatterProblem(): string | undefined;
13
+ get mdast(): Root;
14
+ }
15
+ export declare function scan(root: string, dir: string, include: (id: string) => boolean): string[];
@@ -0,0 +1,68 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { unified } from 'unified';
4
+ import remarkParse from 'remark-parse';
5
+ import remarkFrontmatter from 'remark-frontmatter';
6
+ import remarkMath from 'remark-math';
7
+ import { parseFrontmatter } from "./frontmatter.js";
8
+ import { toAbsolute, toId } from "./paths.js";
9
+ const remark = unified().use(remarkParse).use(remarkFrontmatter).use(remarkMath);
10
+ // A file the content layer read, parsed at most once however many passes look
11
+ // at it.
12
+ export class SourceFile {
13
+ id;
14
+ abs;
15
+ raw;
16
+ parsedFrontmatter;
17
+ frontmatterError;
18
+ tree;
19
+ constructor(root, id, raw) {
20
+ this.id = id;
21
+ this.abs = toAbsolute(root, id);
22
+ this.raw = raw ?? fs.readFileSync(this.abs, 'utf8');
23
+ }
24
+ get isMarkdown() {
25
+ return this.id.endsWith('.svx') || this.id.endsWith('.md');
26
+ }
27
+ // Malformed YAML is reported once, by whoever first asks, and then reads as
28
+ // an empty mapping so that the rest of the site still builds.
29
+ get frontmatter() {
30
+ if (this.parsedFrontmatter)
31
+ return this.parsedFrontmatter;
32
+ try {
33
+ this.parsedFrontmatter = this.isMarkdown ? parseFrontmatter(this.raw) : {};
34
+ }
35
+ catch (error) {
36
+ this.frontmatterError = error;
37
+ this.parsedFrontmatter = {};
38
+ }
39
+ return this.parsedFrontmatter;
40
+ }
41
+ get frontmatterProblem() {
42
+ void this.frontmatter;
43
+ if (!this.frontmatterError)
44
+ return undefined;
45
+ const message = this.frontmatterError instanceof Error
46
+ ? this.frontmatterError.message
47
+ : String(this.frontmatterError);
48
+ return `${this.id}: the frontmatter does not parse.\n${message}`;
49
+ }
50
+ get mdast() {
51
+ return (this.tree ??= remark.parse(this.raw));
52
+ }
53
+ }
54
+ // What a site's content is made of: every file under `dir` that `include`
55
+ // accepts, by id, in a stable order. Sorting keeps processing order --- and so
56
+ // every label and every last-writer-wins registration --- reproducible.
57
+ export function scan(root, dir, include) {
58
+ const base = path.resolve(root, dir);
59
+ if (!fs.existsSync(base))
60
+ return [];
61
+ return fs.readdirSync(base, { recursive: true, withFileTypes: true })
62
+ .filter((entry) => entry.isFile())
63
+ .map((entry) => toId(root, path.join(entry.parentPath, entry.name)))
64
+ .filter((id) => !id.split('/').some((part) => part == 'node_modules' || part.startsWith('.')))
65
+ .filter(include)
66
+ .sort();
67
+ }
68
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/core/source.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { SourceFile } from './source.ts';
2
+ import type { Store } from './store.ts';
3
+ import type { WalkTarget } from './walk.ts';
4
+ export interface StatementInjection {
5
+ kind: string;
6
+ label: string;
7
+ slug: string;
8
+ pathname: string;
9
+ filename: string;
10
+ title?: string;
11
+ id?: string;
12
+ }
13
+ export interface StatementOptions {
14
+ next(): string;
15
+ walk(file: SourceFile, target: WalkTarget): void;
16
+ id?(slug: string): string;
17
+ }
18
+ export declare function registerStatement(store: Store, id: string, at: WalkTarget, options: StatementOptions): void;
@@ -0,0 +1,65 @@
1
+ import { docRecord } from "./build.js";
2
+ import { Frontmatter } from "./frontmatter.js";
3
+ // A document with `type: statement` --- a theorem, a lemma, a definition ---
4
+ // rendered inside the page that imports it. It takes the next number, and
5
+ // anything it contains keeps counting from there: a statement nested inside
6
+ // another does not restart, it belongs to the same run as the page.
7
+ export function registerStatement(store, id, at, options) {
8
+ let file;
9
+ try {
10
+ file = store.file(id);
11
+ }
12
+ catch {
13
+ store.error(at.doc, `${at.doc}: imports \`${id}\`, which does not exist.`);
14
+ return;
15
+ }
16
+ const fm = new Frontmatter(store.root, id, file.frontmatter, 'Statement');
17
+ if (fm.raw('type') != 'statement')
18
+ return;
19
+ const kind = fm.raw('kind');
20
+ if (typeof kind != 'string' || !kind) {
21
+ store.error(id, `${id}: a statement needs a \`kind\`, such as \`theorem\`.`);
22
+ return;
23
+ }
24
+ const title = fm.raw('title');
25
+ const slug = fm.slug();
26
+ const label = options.next();
27
+ // Rendering a statement twice takes two numbers, and only the last label
28
+ // sticks. It is usually an accident: an element such as `<Uniform />` is
29
+ // matched case-insensitively against an imported `uniform` document. The
30
+ // numbering is kept as it is, since published labels depend on it.
31
+ if (store.docs.has(id)) {
32
+ store.error(id, `${id}: rendered more than once on \`${at.page}\`; each rendering takes a number ` +
33
+ 'and the last label wins. (An element whose name matches the import ' +
34
+ 'case-insensitively counts as a rendering.)');
35
+ }
36
+ // A statement's macros fold under the page it is shown on, not under a
37
+ // statement that happens to contain it.
38
+ store.addDoc(docRecord(id, 'statement', {
39
+ scope: at.scope,
40
+ host: at.host,
41
+ macroParent: at.host,
42
+ macros: fm.katexMacros(),
43
+ }));
44
+ store.addAnchor({
45
+ kind: 'statement',
46
+ scope: at.scope,
47
+ slug,
48
+ label,
49
+ source: id,
50
+ page: at.page,
51
+ data: { kind },
52
+ });
53
+ const injection = {
54
+ kind,
55
+ label,
56
+ slug,
57
+ pathname: at.page,
58
+ filename: id,
59
+ ...(typeof title == 'string' && title ? { title } : {}),
60
+ ...(options.id ? { id: options.id(slug) } : {}),
61
+ };
62
+ store.inject(id, { ...injection });
63
+ options.walk(file, { doc: id, scope: at.scope, page: at.page, host: at.host });
64
+ }
65
+ //# sourceMappingURL=statements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statements.js","sourceRoot":"","sources":["../../src/core/statements.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ import type { KatexMacros } from '@mvarble/mesearch-markdown/katex';
2
+ import type { Heading } from '../model/outline.ts';
3
+ import { SourceFile } from './source.ts';
4
+ export interface DocRecord {
5
+ id: string;
6
+ doctype: string;
7
+ scope: string;
8
+ host?: string;
9
+ macroParent?: string;
10
+ macros: KatexMacros;
11
+ headings: Heading[];
12
+ }
13
+ export interface PageRecord {
14
+ pathname: string;
15
+ doc: string;
16
+ formats: Record<string, string>;
17
+ }
18
+ export interface Anchor {
19
+ kind: string;
20
+ scope: string;
21
+ slug: string;
22
+ label: string;
23
+ source: string;
24
+ page: string;
25
+ data?: Record<string, unknown>;
26
+ }
27
+ export interface ResolvedRef {
28
+ resolver: string;
29
+ written: string;
30
+ target: unknown;
31
+ }
32
+ export interface Diagnostic {
33
+ file: string;
34
+ message: string;
35
+ }
36
+ export declare class Store {
37
+ readonly root: string;
38
+ readonly siteMacros: KatexMacros;
39
+ readonly docs: Map<string, DocRecord>;
40
+ readonly pages: Map<string, PageRecord>;
41
+ readonly anchors: Map<string, Anchor>;
42
+ readonly diagnostics: Diagnostic[];
43
+ readonly scopes: Map<string, string>;
44
+ readonly scopeNames: Map<string, string>;
45
+ private readonly collections;
46
+ private readonly pageByDoc;
47
+ private readonly refs;
48
+ private readonly files;
49
+ private readonly injections;
50
+ constructor(root: string, siteMacros?: KatexMacros);
51
+ file(id: string): SourceFile;
52
+ hasFile(id: string): boolean;
53
+ addDoc(doc: DocRecord): DocRecord;
54
+ addPage(page: PageRecord): PageRecord;
55
+ pathnameOf(id: string): string | undefined;
56
+ ownPathname(id: string): string | undefined;
57
+ addAnchor(anchor: Anchor): void;
58
+ anchor(kind: string, scope: string, slug: string): Anchor | undefined;
59
+ addRef(doc: string, ref: ResolvedRef): void;
60
+ ref(doc: string, resolver: string, written: string): ResolvedRef | undefined;
61
+ refsOf(doc: string): ResolvedRef[];
62
+ collection<T>(name: string): Map<string, T>;
63
+ inject(doc: string, value: Record<string, unknown>): void;
64
+ injection(doc: string): Record<string, unknown> | undefined;
65
+ foldedMacros(id: string): KatexMacros;
66
+ error(file: string, message: string): void;
67
+ }