@hraness/wordcell 0.22.3 → 0.22.5
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/README.md +20 -17
- package/dist/authoring.js +2 -2
- package/dist/{authority-06eqhqam.js → authority-3ga47syb.js} +2 -2
- package/dist/benchmark.js +3 -3
- package/dist/cli.js +16 -16
- package/dist/evaluation-builder.js +10 -10
- package/dist/evaluation-kb.js +10 -10
- package/dist/graph-authority.js +4 -4
- package/dist/graph-percolation.js +6 -6
- package/dist/graph.js +3 -1
- package/dist/{index-1k595z6v.js → index-1r5rnkfr.js} +2 -2
- package/dist/{index-3agn8scn.js → index-23m6bbjt.js} +47 -11
- package/dist/{index-q7tbg07z.js → index-42tb8qqp.js} +7 -7
- package/dist/{index-yx6p1vzc.js → index-8bgnhjgq.js} +17 -16
- package/dist/{index-233z9wmn.js → index-8v6k9h4r.js} +13 -5
- package/dist/{index-vnybgywh.js → index-aer0jdrq.js} +1 -1
- package/dist/{index-xv80vzfp.js → index-f75zmmdr.js} +4 -4
- package/dist/{index-ecqpgr5y.js → index-f7fnww7a.js} +1 -1
- package/dist/{index-djrcc1yf.js → index-gtwqye5a.js} +4 -4
- package/dist/{index-bqtqeak3.js → index-h2qn3y3f.js} +4 -4
- package/dist/{index-rr9kzq4n.js → index-n57tewfr.js} +2 -2
- package/dist/{index-76dbn6pe.js → index-n9kwenpt.js} +1 -1
- package/dist/{index-n386evxj.js → index-p96kb6t2.js} +1 -1
- package/dist/{index-tf4wzjew.js → index-pz2b2x0y.js} +1 -1
- package/dist/{index-jk1sgx36.js → index-qdb8f8va.js} +1 -1
- package/dist/{index-a3j61wz9.js → index-xzvcw9ga.js} +201 -131
- package/dist/{index-qbssx940.js → index-zy7an84p.js} +223 -8
- package/dist/index.js +21 -15
- package/dist/percolate.js +2 -2
- package/dist/portfolio.js +10 -10
- package/dist/publish-reader/reader.js +48 -12
- package/dist/publish-search.js +1 -1
- package/dist/publish.js +4 -4
- package/dist/sdk.js +9 -9
- package/dist/search.js +2 -2
- package/dist/semantic.js +4 -4
- package/dist/{support-vm8fw4yc.js → support-jf9v10j7.js} +15 -15
- package/dist/workflows/decision-context.js +10 -10
- package/dist/workflows/index.js +10 -10
- package/package.json +5 -4
- package/skills/wordcell/SKILL.md +1 -1
- package/skills/wordcell/references/plan-structure.md +1 -1
- package/skills/wordcell/references/url-platforms.md +1 -1
- package/src/cli-program.ts +4 -2
- package/src/graph.ts +79 -9
- package/src/mention-index.ts +194 -0
- package/src/publish-index.ts +3 -2
- package/src/publish-markdown.ts +55 -0
- package/src/publish-model.ts +2 -2
- package/src/publish-reader/reader.ts +3 -1
- package/src/publish-search.ts +44 -13
- package/src/publish.ts +4 -1
- package/src/vault.ts +26 -2
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
GRAPH_LIMITS,
|
|
4
4
|
GraphAuthorityError,
|
|
5
5
|
validateGraphQueryRequest
|
|
6
|
-
} from "./index-
|
|
6
|
+
} from "./index-pz2b2x0y.js";
|
|
7
7
|
import {
|
|
8
8
|
scanVault
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-8v6k9h4r.js";
|
|
10
10
|
import {
|
|
11
11
|
analyzeAuthoredRepositoryScopes
|
|
12
12
|
} from "./index-06c9ctr6.js";
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
documentIdState,
|
|
20
20
|
isCanonicalNoteId,
|
|
21
21
|
parseNote
|
|
22
|
-
} from "./index-
|
|
22
|
+
} from "./index-zy7an84p.js";
|
|
23
23
|
import {
|
|
24
24
|
__require
|
|
25
25
|
} from "./index-z1w83f81.js";
|
|
@@ -231,7 +231,7 @@ import { lstat, open } from "fs/promises";
|
|
|
231
231
|
var graphCacheFileSystem = { lstat, open };
|
|
232
232
|
|
|
233
233
|
// src/graph-authority.ts
|
|
234
|
-
var openOhGraphAdapter = async (...args) => await (await import("./authority-
|
|
234
|
+
var openOhGraphAdapter = async (...args) => await (await import("./authority-3ga47syb.js")).openOhGraphAdapter(...args);
|
|
235
235
|
var MAX_CACHE_BYTES = 67108864;
|
|
236
236
|
var ignoredCache = `# Disposable Wordcell graph state. Rebuild from Markdown.
|
|
237
237
|
*
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
percolateVault
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-qdb8f8va.js";
|
|
5
5
|
import {
|
|
6
6
|
createGraphSnapshot,
|
|
7
7
|
openGraphAuthority
|
|
8
|
-
} from "./index-
|
|
8
|
+
} from "./index-f75zmmdr.js";
|
|
9
9
|
import {
|
|
10
10
|
GraphAuthorityError,
|
|
11
11
|
validateGraphPercolationOptions
|
|
12
|
-
} from "./index-
|
|
12
|
+
} from "./index-pz2b2x0y.js";
|
|
13
13
|
import {
|
|
14
14
|
analyzeVault,
|
|
15
15
|
lookupNote,
|
|
16
16
|
parseNote
|
|
17
|
-
} from "./index-
|
|
17
|
+
} from "./index-zy7an84p.js";
|
|
18
18
|
|
|
19
19
|
// src/graph-percolation.ts
|
|
20
20
|
async function percolateWithGraph(snapshot, options) {
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
MAX_SEARCH_RESULTS,
|
|
6
6
|
openKnowledgeBase,
|
|
7
7
|
validateKnowledgeBaseSearchHistory
|
|
8
|
-
} from "./index-
|
|
8
|
+
} from "./index-42tb8qqp.js";
|
|
9
9
|
import {
|
|
10
10
|
expandSearchRequest,
|
|
11
11
|
parseSearchRules
|
|
@@ -15,10 +15,10 @@ import {
|
|
|
15
15
|
} from "./index-1gwbassd.js";
|
|
16
16
|
import {
|
|
17
17
|
validateSearchQuery
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-aer0jdrq.js";
|
|
19
19
|
import {
|
|
20
20
|
scanVault
|
|
21
|
-
} from "./index-
|
|
21
|
+
} from "./index-8v6k9h4r.js";
|
|
22
22
|
import {
|
|
23
23
|
validateQueryOptions
|
|
24
24
|
} from "./index-48pz4jpc.js";
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
parseVaultKey,
|
|
33
33
|
portfolioDocumentIdentity,
|
|
34
34
|
portfolioVaultIdentity
|
|
35
|
-
} from "./index-
|
|
35
|
+
} from "./index-zy7an84p.js";
|
|
36
36
|
|
|
37
37
|
// src/portfolio.ts
|
|
38
38
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import {
|
|
3
3
|
fuseRankedCandidates,
|
|
4
4
|
validateSearchQuery
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-aer0jdrq.js";
|
|
6
6
|
import {
|
|
7
7
|
MAX_NOTE_UTF8_BYTES,
|
|
8
8
|
MAX_SCANNED_NOTES,
|
|
9
9
|
MAX_VAULT_UTF8_BYTES,
|
|
10
10
|
VaultScanBudgetError,
|
|
11
11
|
scanVault
|
|
12
|
-
} from "./index-
|
|
12
|
+
} from "./index-8v6k9h4r.js";
|
|
13
13
|
|
|
14
14
|
// src/semantic.ts
|
|
15
15
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
scanVault
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-8v6k9h4r.js";
|
|
5
5
|
import {
|
|
6
6
|
navigateLinks
|
|
7
7
|
} from "./index-d13v9ckt.js";
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
import {
|
|
32
32
|
publishNormalize,
|
|
33
33
|
publishShardName
|
|
34
|
-
} from "./index-
|
|
34
|
+
} from "./index-23m6bbjt.js";
|
|
35
35
|
import {
|
|
36
36
|
parseLocalAttachmentReferences,
|
|
37
37
|
validateMarkdownAttachments
|
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
import {
|
|
40
40
|
lookupNote,
|
|
41
41
|
normalizeVaultPath
|
|
42
|
-
} from "./index-
|
|
42
|
+
} from "./index-zy7an84p.js";
|
|
43
43
|
|
|
44
44
|
// src/publish.ts
|
|
45
45
|
import { createHash } from "crypto";
|
|
@@ -49,133 +49,6 @@ import { canonicalJson as canonicalJson2, canonicalSha256 } from "@hraness/oh";
|
|
|
49
49
|
|
|
50
50
|
// src/publish-index.ts
|
|
51
51
|
import { canonicalJson } from "@hraness/oh";
|
|
52
|
-
var TERM_PATTERN = /[\p{L}\p{N}][\p{L}\p{N}._/-]*/gu;
|
|
53
|
-
function bounded(value, maximumBytes) {
|
|
54
|
-
if (Buffer.byteLength(value, "utf8") <= maximumBytes)
|
|
55
|
-
return { text: value, truncated: false };
|
|
56
|
-
const bytes = Buffer.from(value, "utf8");
|
|
57
|
-
let end = maximumBytes;
|
|
58
|
-
while (end > 0 && ((bytes[end] ?? 0) & 192) === 128)
|
|
59
|
-
end -= 1;
|
|
60
|
-
return { text: bytes.subarray(0, end).toString("utf8"), truncated: true };
|
|
61
|
-
}
|
|
62
|
-
function previewText(note) {
|
|
63
|
-
const basis = note.summary !== "" ? note.summary : note.searchableText;
|
|
64
|
-
const collapsed = basis.replace(/\s+/gu, " ").trim();
|
|
65
|
-
return bounded(collapsed, WORDCELL_SITE_LIMITS_V1.docPreviewBytes).text;
|
|
66
|
-
}
|
|
67
|
-
function indexableTerms(text) {
|
|
68
|
-
const terms = new Set;
|
|
69
|
-
for (const match of text.matchAll(TERM_PATTERN))
|
|
70
|
-
terms.add(match[0]);
|
|
71
|
-
return [...terms];
|
|
72
|
-
}
|
|
73
|
-
function buildSiteIndex(notes, slugById, options = {}) {
|
|
74
|
-
const indexContent = options.indexContent !== false;
|
|
75
|
-
const fields = [];
|
|
76
|
-
const inlineTexts = [];
|
|
77
|
-
let textTruncated = false;
|
|
78
|
-
let inlineTotal = 0;
|
|
79
|
-
for (const note of notes) {
|
|
80
|
-
const title = bounded(publishNormalize(note.title), WORDCELL_SITE_LIMITS_V1.fieldTextBytes);
|
|
81
|
-
const aliases = bounded(note.aliases.map(publishNormalize).join(`
|
|
82
|
-
`), WORDCELL_SITE_LIMITS_V1.fieldTextBytes);
|
|
83
|
-
const path = bounded(`${publishNormalize(note.path)}
|
|
84
|
-
${publishNormalize(note.id)}`, WORDCELL_SITE_LIMITS_V1.fieldTextBytes);
|
|
85
|
-
const tags = bounded(note.tags.map(publishNormalize).join(`
|
|
86
|
-
`), WORDCELL_SITE_LIMITS_V1.fieldTextBytes);
|
|
87
|
-
const metadata = bounded(publishNormalize(canonicalJson(note.metadata)), WORDCELL_SITE_LIMITS_V1.fieldTextBytes);
|
|
88
|
-
textTruncated ||= title.truncated || aliases.truncated || path.truncated || tags.truncated || metadata.truncated;
|
|
89
|
-
fields.push({ t: title.text, a: aliases.text, p: path.text, g: tags.text, m: metadata.text });
|
|
90
|
-
if (indexContent) {
|
|
91
|
-
const inline = bounded(publishNormalize(note.searchableText), WORDCELL_SITE_LIMITS_V1.inlineTextBytes);
|
|
92
|
-
textTruncated ||= inline.truncated;
|
|
93
|
-
inlineTexts.push(inline.text);
|
|
94
|
-
inlineTotal += Buffer.byteLength(inline.text, "utf8");
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
const mode = !indexContent ? "none" : inlineTotal <= WORDCELL_SITE_LIMITS_V1.inlineTotalBytes ? "inline" : "shards";
|
|
98
|
-
const allTerms = new Set;
|
|
99
|
-
const contentPostings = new Map;
|
|
100
|
-
const docs = [];
|
|
101
|
-
for (const [index, note] of notes.entries()) {
|
|
102
|
-
const slug = slugById.get(note.id);
|
|
103
|
-
if (slug === undefined)
|
|
104
|
-
throw new Error(`Missing published slug for ${note.id}.`);
|
|
105
|
-
const field = fields[index];
|
|
106
|
-
if (field === undefined)
|
|
107
|
-
throw new Error(`Missing indexed fields for ${note.id}.`);
|
|
108
|
-
const inline = mode === "inline" ? inlineTexts[index] : undefined;
|
|
109
|
-
const fieldTerms = indexableTerms(`${field.t}
|
|
110
|
-
${field.a}
|
|
111
|
-
${field.p}
|
|
112
|
-
${field.g}
|
|
113
|
-
${field.m}`);
|
|
114
|
-
for (const term of fieldTerms)
|
|
115
|
-
allTerms.add(term);
|
|
116
|
-
if (mode !== "none") {
|
|
117
|
-
const content = inlineTexts[index] ?? "";
|
|
118
|
-
for (const term of indexableTerms(content)) {
|
|
119
|
-
allTerms.add(term);
|
|
120
|
-
if (mode === "shards") {
|
|
121
|
-
const list = contentPostings.get(term) ?? [];
|
|
122
|
-
list.push(index);
|
|
123
|
-
contentPostings.set(term, list);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
docs.push({
|
|
128
|
-
i: index,
|
|
129
|
-
s: slug,
|
|
130
|
-
t: note.title,
|
|
131
|
-
p: previewText(note),
|
|
132
|
-
f: field,
|
|
133
|
-
...inline === undefined ? {} : { x: inline }
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
let termsTruncated = false;
|
|
137
|
-
let sortedTerms = [...allTerms].toSorted((left, right) => left.localeCompare(right));
|
|
138
|
-
if (sortedTerms.length > WORDCELL_SITE_LIMITS_V1.indexTerms) {
|
|
139
|
-
sortedTerms = sortedTerms.slice(0, WORDCELL_SITE_LIMITS_V1.indexTerms);
|
|
140
|
-
termsTruncated = true;
|
|
141
|
-
}
|
|
142
|
-
const admitted = new Set(sortedTerms);
|
|
143
|
-
const postings = new Map;
|
|
144
|
-
if (mode === "shards") {
|
|
145
|
-
const grouped = new Map;
|
|
146
|
-
for (const [term, docIds] of [...contentPostings.entries()].toSorted(([a], [b]) => a.localeCompare(b))) {
|
|
147
|
-
if (!admitted.has(term))
|
|
148
|
-
continue;
|
|
149
|
-
const shard = publishShardName(term);
|
|
150
|
-
const bucket = grouped.get(shard) ?? Object.create(null);
|
|
151
|
-
bucket[term] = docIds;
|
|
152
|
-
grouped.set(shard, bucket);
|
|
153
|
-
}
|
|
154
|
-
for (const [shard, bucket] of [...grouped.entries()].toSorted(([a], [b]) => a.localeCompare(b))) {
|
|
155
|
-
postings.set(shard, {
|
|
156
|
-
format: WORDCELL_SITE_POSTINGS_FORMAT_V1,
|
|
157
|
-
shard,
|
|
158
|
-
postings: Object.freeze(bucket)
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
return {
|
|
163
|
-
docs: {
|
|
164
|
-
format: WORDCELL_SITE_DOCS_FORMAT_V1,
|
|
165
|
-
content: mode,
|
|
166
|
-
docs
|
|
167
|
-
},
|
|
168
|
-
terms: {
|
|
169
|
-
format: WORDCELL_SITE_TERMS_FORMAT_V1,
|
|
170
|
-
terms: sortedTerms
|
|
171
|
-
},
|
|
172
|
-
postings,
|
|
173
|
-
termsCount: sortedTerms.length,
|
|
174
|
-
termsTruncated,
|
|
175
|
-
textTruncated,
|
|
176
|
-
mode
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
52
|
|
|
180
53
|
// src/publish-markdown.ts
|
|
181
54
|
var VOID_SLUG = /[^\p{L}\p{N}._~-]+/gu;
|
|
@@ -257,6 +130,8 @@ function renderFootnoteReference(raw, label, footnotes) {
|
|
|
257
130
|
const id = `wordcell:footnote-ref:${number}:${note.references.length + 1}`;
|
|
258
131
|
note.references.push(id);
|
|
259
132
|
footnotes.references += 1;
|
|
133
|
+
if (footnotes.plain)
|
|
134
|
+
return "";
|
|
260
135
|
return `<sup><a id="${id}" href="#wordcell:footnote:${number}" role="doc-noteref" aria-label="Footnote ${number}">${number}</a></sup>`;
|
|
261
136
|
}
|
|
262
137
|
function renderInline(text, ctx, footnotes) {
|
|
@@ -904,6 +779,72 @@ function renderMarkdownToHtml(content, ctx) {
|
|
|
904
779
|
${notes}
|
|
905
780
|
</ol></section>`;
|
|
906
781
|
}
|
|
782
|
+
function projectMarkdownText(content, description) {
|
|
783
|
+
const footnotes = { byLabel: new Map, numbered: [], definitions: 0, references: 0, disabled: false, plain: true };
|
|
784
|
+
const blocks = parseMarkdownBlocks(content, footnotes, true);
|
|
785
|
+
const context = {
|
|
786
|
+
source: "",
|
|
787
|
+
resolveNote: () => {
|
|
788
|
+
return;
|
|
789
|
+
},
|
|
790
|
+
resolveAsset: () => {
|
|
791
|
+
return;
|
|
792
|
+
},
|
|
793
|
+
noteHref: () => ""
|
|
794
|
+
};
|
|
795
|
+
const inline = (text2, state) => stripMarkup(renderInline(text2, context, state));
|
|
796
|
+
const parts = (items, state) => items.map((block) => {
|
|
797
|
+
switch (block.type) {
|
|
798
|
+
case "paragraph":
|
|
799
|
+
case "heading":
|
|
800
|
+
return inline(block.text, state);
|
|
801
|
+
case "literal":
|
|
802
|
+
case "code":
|
|
803
|
+
return block.text;
|
|
804
|
+
case "break":
|
|
805
|
+
return "";
|
|
806
|
+
case "quote":
|
|
807
|
+
return parts(block.blocks, state).join(`
|
|
808
|
+
|
|
809
|
+
`);
|
|
810
|
+
case "table":
|
|
811
|
+
return [block.header, ...block.rows].map((row) => row.map((cell) => inline(cell, state)).join(" ")).join(`
|
|
812
|
+
`);
|
|
813
|
+
case "list":
|
|
814
|
+
return block.parts.map((part) => part.type === "item" || part.type === "continuation" ? inline(part.text, state) : "").filter(Boolean).join(`
|
|
815
|
+
`);
|
|
816
|
+
case "footnote":
|
|
817
|
+
return state.disabled || block.note.invalid ? block.note.authored : "";
|
|
818
|
+
}
|
|
819
|
+
});
|
|
820
|
+
const rendered = parts(blocks, footnotes);
|
|
821
|
+
if (!footnotes.disabled)
|
|
822
|
+
for (const note of footnotes.byLabel.values()) {
|
|
823
|
+
if (note !== null && !note.invalid)
|
|
824
|
+
footnoteNumber(note, footnotes);
|
|
825
|
+
}
|
|
826
|
+
const text = [...rendered, ...footnotes.numbered.map((note) => inline(note.body.replaceAll(`
|
|
827
|
+
`, " ")))].filter(Boolean).join(`
|
|
828
|
+
|
|
829
|
+
`);
|
|
830
|
+
let preview = rendered.find((value, index) => blocks[index]?.type === "paragraph" && value.trim() !== "") ?? text;
|
|
831
|
+
if (description !== undefined && description.trim() !== "") {
|
|
832
|
+
const state = {
|
|
833
|
+
byLabel: new Map([...footnotes.byLabel].map(([label, note]) => [label, note === null ? null : { body: note.body, authored: note.authored, invalid: note.invalid, references: [] }])),
|
|
834
|
+
numbered: [],
|
|
835
|
+
definitions: footnotes.definitions,
|
|
836
|
+
references: 0,
|
|
837
|
+
disabled: footnotes.disabled,
|
|
838
|
+
plain: true
|
|
839
|
+
};
|
|
840
|
+
const authored = parts(parseMarkdownBlocks(description, state, false), state).filter(Boolean).join(`
|
|
841
|
+
|
|
842
|
+
`);
|
|
843
|
+
if (authored.trim() !== "")
|
|
844
|
+
preview = authored;
|
|
845
|
+
}
|
|
846
|
+
return { text, preview };
|
|
847
|
+
}
|
|
907
848
|
function stripMarkup(html) {
|
|
908
849
|
let stripped = "";
|
|
909
850
|
let inTag = false;
|
|
@@ -918,6 +859,135 @@ function stripMarkup(html) {
|
|
|
918
859
|
return stripped.replaceAll("<", "<").replaceAll(">", ">").replaceAll(""", '"').replaceAll("'", "'").replaceAll("&", "&");
|
|
919
860
|
}
|
|
920
861
|
|
|
862
|
+
// src/publish-index.ts
|
|
863
|
+
var TERM_PATTERN = /[\p{L}\p{N}][\p{L}\p{N}._/-]*/gu;
|
|
864
|
+
function bounded(value, maximumBytes) {
|
|
865
|
+
if (Buffer.byteLength(value, "utf8") <= maximumBytes)
|
|
866
|
+
return { text: value, truncated: false };
|
|
867
|
+
const bytes = Buffer.from(value, "utf8");
|
|
868
|
+
let end = maximumBytes;
|
|
869
|
+
while (end > 0 && ((bytes[end] ?? 0) & 192) === 128)
|
|
870
|
+
end -= 1;
|
|
871
|
+
return { text: bytes.subarray(0, end).toString("utf8"), truncated: true };
|
|
872
|
+
}
|
|
873
|
+
function previewText(note) {
|
|
874
|
+
const display = projectMarkdownText(note.content, note.properties["description"]);
|
|
875
|
+
const collapsed = display.preview.replace(/\s+/gu, " ").trim();
|
|
876
|
+
return bounded(collapsed, WORDCELL_SITE_LIMITS_V1.docPreviewBytes).text;
|
|
877
|
+
}
|
|
878
|
+
function indexableTerms(text) {
|
|
879
|
+
const terms = new Set;
|
|
880
|
+
for (const match of text.matchAll(TERM_PATTERN))
|
|
881
|
+
terms.add(match[0]);
|
|
882
|
+
return [...terms];
|
|
883
|
+
}
|
|
884
|
+
function buildSiteIndex(notes, slugById, options = {}) {
|
|
885
|
+
const indexContent = options.indexContent !== false;
|
|
886
|
+
const fields = [];
|
|
887
|
+
const inlineTexts = [];
|
|
888
|
+
let textTruncated = false;
|
|
889
|
+
let inlineTotal = 0;
|
|
890
|
+
for (const note of notes) {
|
|
891
|
+
const title = bounded(publishNormalize(note.title), WORDCELL_SITE_LIMITS_V1.fieldTextBytes);
|
|
892
|
+
const aliases = bounded(note.aliases.map(publishNormalize).join(`
|
|
893
|
+
`), WORDCELL_SITE_LIMITS_V1.fieldTextBytes);
|
|
894
|
+
const path = bounded(`${publishNormalize(note.path)}
|
|
895
|
+
${publishNormalize(note.id)}`, WORDCELL_SITE_LIMITS_V1.fieldTextBytes);
|
|
896
|
+
const tags = bounded(note.tags.map(publishNormalize).join(`
|
|
897
|
+
`), WORDCELL_SITE_LIMITS_V1.fieldTextBytes);
|
|
898
|
+
const metadata = bounded(publishNormalize(canonicalJson(note.metadata)), WORDCELL_SITE_LIMITS_V1.fieldTextBytes);
|
|
899
|
+
textTruncated ||= title.truncated || aliases.truncated || path.truncated || tags.truncated || metadata.truncated;
|
|
900
|
+
fields.push({ t: title.text, a: aliases.text, p: path.text, g: tags.text, m: metadata.text });
|
|
901
|
+
if (indexContent) {
|
|
902
|
+
const inline = bounded(publishNormalize(note.searchableText), WORDCELL_SITE_LIMITS_V1.inlineTextBytes);
|
|
903
|
+
textTruncated ||= inline.truncated;
|
|
904
|
+
inlineTexts.push(inline.text);
|
|
905
|
+
inlineTotal += Buffer.byteLength(inline.text, "utf8");
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
const mode = !indexContent ? "none" : inlineTotal <= WORDCELL_SITE_LIMITS_V1.inlineTotalBytes ? "inline" : "shards";
|
|
909
|
+
const allTerms = new Set;
|
|
910
|
+
const contentPostings = new Map;
|
|
911
|
+
const docs = [];
|
|
912
|
+
for (const [index, note] of notes.entries()) {
|
|
913
|
+
const slug = slugById.get(note.id);
|
|
914
|
+
if (slug === undefined)
|
|
915
|
+
throw new Error(`Missing published slug for ${note.id}.`);
|
|
916
|
+
const field = fields[index];
|
|
917
|
+
if (field === undefined)
|
|
918
|
+
throw new Error(`Missing indexed fields for ${note.id}.`);
|
|
919
|
+
const inline = mode === "inline" ? inlineTexts[index] : undefined;
|
|
920
|
+
const fieldTerms = indexableTerms(`${field.t}
|
|
921
|
+
${field.a}
|
|
922
|
+
${field.p}
|
|
923
|
+
${field.g}
|
|
924
|
+
${field.m}`);
|
|
925
|
+
for (const term of fieldTerms)
|
|
926
|
+
allTerms.add(term);
|
|
927
|
+
if (mode !== "none") {
|
|
928
|
+
const content = inlineTexts[index] ?? "";
|
|
929
|
+
for (const term of indexableTerms(content)) {
|
|
930
|
+
allTerms.add(term);
|
|
931
|
+
if (mode === "shards") {
|
|
932
|
+
const list = contentPostings.get(term) ?? [];
|
|
933
|
+
list.push(index);
|
|
934
|
+
contentPostings.set(term, list);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
docs.push({
|
|
939
|
+
i: index,
|
|
940
|
+
s: slug,
|
|
941
|
+
t: note.title,
|
|
942
|
+
p: previewText(note),
|
|
943
|
+
f: field,
|
|
944
|
+
...inline === undefined ? {} : { x: inline }
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
let termsTruncated = false;
|
|
948
|
+
let sortedTerms = [...allTerms].toSorted((left, right) => left.localeCompare(right));
|
|
949
|
+
if (sortedTerms.length > WORDCELL_SITE_LIMITS_V1.indexTerms) {
|
|
950
|
+
sortedTerms = sortedTerms.slice(0, WORDCELL_SITE_LIMITS_V1.indexTerms);
|
|
951
|
+
termsTruncated = true;
|
|
952
|
+
}
|
|
953
|
+
const admitted = new Set(sortedTerms);
|
|
954
|
+
const postings = new Map;
|
|
955
|
+
if (mode === "shards") {
|
|
956
|
+
const grouped = new Map;
|
|
957
|
+
for (const [term, docIds] of [...contentPostings.entries()].toSorted(([a], [b]) => a.localeCompare(b))) {
|
|
958
|
+
if (!admitted.has(term))
|
|
959
|
+
continue;
|
|
960
|
+
const shard = publishShardName(term);
|
|
961
|
+
const bucket = grouped.get(shard) ?? Object.create(null);
|
|
962
|
+
bucket[term] = docIds;
|
|
963
|
+
grouped.set(shard, bucket);
|
|
964
|
+
}
|
|
965
|
+
for (const [shard, bucket] of [...grouped.entries()].toSorted(([a], [b]) => a.localeCompare(b))) {
|
|
966
|
+
postings.set(shard, {
|
|
967
|
+
format: WORDCELL_SITE_POSTINGS_FORMAT_V1,
|
|
968
|
+
shard,
|
|
969
|
+
postings: Object.freeze(bucket)
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
return {
|
|
974
|
+
docs: {
|
|
975
|
+
format: WORDCELL_SITE_DOCS_FORMAT_V1,
|
|
976
|
+
content: mode,
|
|
977
|
+
docs
|
|
978
|
+
},
|
|
979
|
+
terms: {
|
|
980
|
+
format: WORDCELL_SITE_TERMS_FORMAT_V1,
|
|
981
|
+
terms: sortedTerms
|
|
982
|
+
},
|
|
983
|
+
postings,
|
|
984
|
+
termsCount: sortedTerms.length,
|
|
985
|
+
termsTruncated,
|
|
986
|
+
textTruncated,
|
|
987
|
+
mode
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
|
|
921
991
|
// src/publish-nav.ts
|
|
922
992
|
var SITE_NAV_GROUP_LIMIT = 96;
|
|
923
993
|
var SITE_NAV_NODE_BUDGET = 768;
|
|
@@ -1709,7 +1779,7 @@ async function projectVault(snapshot, options, io) {
|
|
|
1709
1779
|
let anyTextTruncated = false;
|
|
1710
1780
|
for (const note of selection.notes) {
|
|
1711
1781
|
const slug = slugFor(note.id);
|
|
1712
|
-
const text = boundedNormalized(note.
|
|
1782
|
+
const text = boundedNormalized(projectMarkdownText(note.content).text, WORDCELL_SITE_LIMITS_V1.noteTextBytes);
|
|
1713
1783
|
anyTextTruncated ||= text.truncated;
|
|
1714
1784
|
const payload = {
|
|
1715
1785
|
format: WORDCELL_SITE_NOTE_FORMAT_V1,
|