diffwiki-core 0.14.0 → 0.15.0-rc.202608040926.6b3b436
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/dist/bm25.cjs +6 -0
- package/dist/bm25.js +1 -1
- package/dist/chunk-6MW6KSS4.js +278 -0
- package/dist/{chunk-FTUF6IXS.js → chunk-TK2373AM.js} +6 -0
- package/dist/{chunk-7V2DIQNL.js → chunk-TXM4OGBA.js} +12 -3
- package/dist/{events-AVD3G5AX.js → events-K3MKWACA.js} +1 -1
- package/dist/frontmatter-ghMCpLNf.d.cts +585 -0
- package/dist/frontmatter-ghMCpLNf.d.ts +585 -0
- package/dist/index.cjs +325 -211
- package/dist/index.d.cts +69 -359
- package/dist/index.d.ts +69 -359
- package/dist/index.js +222 -205
- package/dist/plugin.cjs +134 -2
- package/dist/plugin.d.cts +54 -177
- package/dist/plugin.d.ts +54 -177
- package/dist/plugin.js +9 -3
- package/package.json +1 -1
- package/dist/chunk-EEETAETA.js +0 -145
package/dist/bm25.cjs
CHANGED
|
@@ -76,6 +76,12 @@ function rankDocs(term, docs) {
|
|
|
76
76
|
if (total > 0) scored.push({ ...d, score: total });
|
|
77
77
|
}
|
|
78
78
|
scored.sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
|
|
79
|
+
const max = scored[0]?.score ?? 0;
|
|
80
|
+
if (max > 0) {
|
|
81
|
+
for (const d of scored) {
|
|
82
|
+
if (typeof d.score === "number") d.score = Number((d.score / max).toFixed(4));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
79
85
|
return scored;
|
|
80
86
|
}
|
|
81
87
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/bm25.js
CHANGED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
// src/frontmatter.ts
|
|
2
|
+
import matter from "gray-matter";
|
|
3
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
4
|
+
var YAML_ENGINE = {
|
|
5
|
+
parse: (input) => {
|
|
6
|
+
const data = parseYaml(input);
|
|
7
|
+
return data && typeof data === "object" ? data : {};
|
|
8
|
+
},
|
|
9
|
+
stringify: (data) => stringifyYaml(data)
|
|
10
|
+
};
|
|
11
|
+
var MATTER_OPTS = { engines: { yaml: YAML_ENGINE } };
|
|
12
|
+
function coerceAudience(value) {
|
|
13
|
+
return value === "private" || value === "system" ? value : "public";
|
|
14
|
+
}
|
|
15
|
+
function coerceStatus(value) {
|
|
16
|
+
return value === "draft" || value === "deprecated" ? value : "published";
|
|
17
|
+
}
|
|
18
|
+
function parseFallback(raw) {
|
|
19
|
+
const fenceRe = /^---[ \t]*\n([\s\S]*?)\n---[ \t]*\n/;
|
|
20
|
+
const fenceMatch = fenceRe.exec(raw);
|
|
21
|
+
let title = "";
|
|
22
|
+
let audience = "public";
|
|
23
|
+
let status = "published";
|
|
24
|
+
let body;
|
|
25
|
+
const clean = (s) => s.trim().replace(/^["']|["']$/g, "");
|
|
26
|
+
if (fenceMatch) {
|
|
27
|
+
const inner = fenceMatch[1];
|
|
28
|
+
const titleMatch = /^title:\s*(.+)$/m.exec(inner);
|
|
29
|
+
if (titleMatch) {
|
|
30
|
+
title = clean(titleMatch[1]);
|
|
31
|
+
}
|
|
32
|
+
const audienceMatch = /^audience:\s*(.+)$/m.exec(inner);
|
|
33
|
+
if (audienceMatch) {
|
|
34
|
+
audience = coerceAudience(clean(audienceMatch[1]));
|
|
35
|
+
}
|
|
36
|
+
const statusMatch = /^status:\s*(.+)$/m.exec(inner);
|
|
37
|
+
if (statusMatch) {
|
|
38
|
+
status = coerceStatus(clean(statusMatch[1]));
|
|
39
|
+
}
|
|
40
|
+
body = raw.slice(fenceMatch[0].length);
|
|
41
|
+
} else {
|
|
42
|
+
body = raw;
|
|
43
|
+
}
|
|
44
|
+
return { title, tags: [], audience, status, body: body.replace(/^\n+/, "") };
|
|
45
|
+
}
|
|
46
|
+
var FRONTMATTER_BLOCK_RE = /^\uFEFF?[ \t]*---\r?\n[\s\S]*?\r?\n---[ \t]*(?:\r?\n|$)/;
|
|
47
|
+
function stripFrontmatter(raw) {
|
|
48
|
+
return raw.replace(FRONTMATTER_BLOCK_RE, "");
|
|
49
|
+
}
|
|
50
|
+
function parseFrontmatter(raw) {
|
|
51
|
+
try {
|
|
52
|
+
const { data, content } = matter(raw, MATTER_OPTS);
|
|
53
|
+
return { data: data ?? {}, body: content };
|
|
54
|
+
} catch {
|
|
55
|
+
return { data: {}, body: raw };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function parseArticle(raw) {
|
|
59
|
+
try {
|
|
60
|
+
const { data, content } = matter(raw, MATTER_OPTS);
|
|
61
|
+
const title = typeof data.title === "string" ? data.title : "";
|
|
62
|
+
const tags = Array.isArray(data.tags) ? data.tags.map((t) => String(t)) : [];
|
|
63
|
+
const created = typeof data.created === "string" ? data.created : void 0;
|
|
64
|
+
const audience = coerceAudience(data.audience);
|
|
65
|
+
const status = coerceStatus(data.status);
|
|
66
|
+
return { title, tags, created, audience, status, body: content.replace(/^\n+/, "") };
|
|
67
|
+
} catch {
|
|
68
|
+
return parseFallback(raw);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function serializeArticle(article) {
|
|
72
|
+
const front = { title: article.title, tags: article.tags };
|
|
73
|
+
if (article.audience === "private" || article.audience === "system") front.audience = article.audience;
|
|
74
|
+
if (article.status === "draft" || article.status === "deprecated") front.status = article.status;
|
|
75
|
+
return matter.stringify(article.body, front, MATTER_OPTS);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// src/plugins/sdk.ts
|
|
79
|
+
import { execFile } from "child_process";
|
|
80
|
+
import { promisify } from "util";
|
|
81
|
+
import { existsSync, readFileSync } from "fs";
|
|
82
|
+
import { dirname, join } from "path";
|
|
83
|
+
import { fileURLToPath } from "url";
|
|
84
|
+
var execFileAsync = promisify(execFile);
|
|
85
|
+
async function runProcess(file, args, opts) {
|
|
86
|
+
const { stdout, stderr } = await execFileAsync(file, args, {
|
|
87
|
+
env: opts?.env,
|
|
88
|
+
timeout: opts?.timeout,
|
|
89
|
+
// Large: qmd emits multi-MB JSON search payloads that overflow the default 1 MB.
|
|
90
|
+
maxBuffer: 50 * 1024 * 1024
|
|
91
|
+
});
|
|
92
|
+
return { stdout, stderr };
|
|
93
|
+
}
|
|
94
|
+
async function runProcessJson(file, args, opts) {
|
|
95
|
+
const { stdout } = await runProcess(file, args, opts);
|
|
96
|
+
try {
|
|
97
|
+
return JSON.parse(stdout);
|
|
98
|
+
} catch {
|
|
99
|
+
throw new Error(`${file} ${args.join(" ")} did not return valid JSON: ${stdout.slice(0, 200)}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async function commandExists(name) {
|
|
103
|
+
try {
|
|
104
|
+
await execFileAsync(name, ["--version"]);
|
|
105
|
+
return true;
|
|
106
|
+
} catch {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function resolveNpmBin(pkg, command, fromUrl) {
|
|
111
|
+
try {
|
|
112
|
+
let dir = dirname(fileURLToPath(fromUrl));
|
|
113
|
+
for (; ; ) {
|
|
114
|
+
const pkgJson = join(dir, "node_modules", pkg, "package.json");
|
|
115
|
+
if (existsSync(pkgJson)) {
|
|
116
|
+
const raw = JSON.parse(readFileSync(pkgJson, "utf8"));
|
|
117
|
+
const rel = typeof raw.bin === "string" ? raw.bin : raw.bin?.[command];
|
|
118
|
+
if (!rel) return null;
|
|
119
|
+
const binPath = join(dirname(pkgJson), rel);
|
|
120
|
+
return existsSync(binPath) ? binPath : null;
|
|
121
|
+
}
|
|
122
|
+
const parent = dirname(dir);
|
|
123
|
+
if (parent === dir) return null;
|
|
124
|
+
dir = parent;
|
|
125
|
+
}
|
|
126
|
+
} catch {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
async function resolveDependency(dep, fromUrl) {
|
|
131
|
+
if (dep.npm) {
|
|
132
|
+
const local = resolveNpmBin(dep.npm, dep.command, fromUrl);
|
|
133
|
+
if (local) return { dependency: dep, command: [local], source: "npm" };
|
|
134
|
+
}
|
|
135
|
+
if (await commandExists(dep.command)) {
|
|
136
|
+
return { dependency: dep, command: [dep.command], source: "path" };
|
|
137
|
+
}
|
|
138
|
+
return { dependency: dep, command: null, source: "missing" };
|
|
139
|
+
}
|
|
140
|
+
async function ensureTool(spec, opts) {
|
|
141
|
+
const exists = opts?.exists ?? commandExists;
|
|
142
|
+
const run = opts?.run ?? ((file, args) => runProcess(file, args));
|
|
143
|
+
const log = opts?.log;
|
|
144
|
+
if (await exists(spec.command)) {
|
|
145
|
+
return { command: spec.command, present: true, installed: false, message: `${spec.command} present` };
|
|
146
|
+
}
|
|
147
|
+
if (!opts?.install) {
|
|
148
|
+
return {
|
|
149
|
+
command: spec.command,
|
|
150
|
+
present: false,
|
|
151
|
+
installed: false,
|
|
152
|
+
message: `${spec.command} not found \u2014 ${spec.manual}`
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
const attempts = [];
|
|
156
|
+
if (spec.mise && await exists("mise"))
|
|
157
|
+
attempts.push({ method: "mise", bin: "mise", args: ["use", "-g", spec.mise] });
|
|
158
|
+
if (spec.brew && await exists("brew")) attempts.push({ method: "brew", bin: "brew", args: ["install", spec.brew] });
|
|
159
|
+
for (const a of attempts) {
|
|
160
|
+
try {
|
|
161
|
+
log?.("info", `installing ${spec.command} via ${a.method}\u2026`);
|
|
162
|
+
await run(a.bin, a.args);
|
|
163
|
+
if (await exists(spec.command)) {
|
|
164
|
+
return {
|
|
165
|
+
command: spec.command,
|
|
166
|
+
present: true,
|
|
167
|
+
installed: true,
|
|
168
|
+
method: a.method,
|
|
169
|
+
message: `installed ${spec.command} via ${a.method}`
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
command: spec.command,
|
|
174
|
+
present: false,
|
|
175
|
+
installed: true,
|
|
176
|
+
method: a.method,
|
|
177
|
+
message: `installed ${spec.command} via ${a.method}, but it isn't on PATH yet \u2014 restart your shell (or activate ${a.method}) and retry`
|
|
178
|
+
};
|
|
179
|
+
} catch (err) {
|
|
180
|
+
log?.("warn", `${a.method} could not install ${spec.command}: ${err.message}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const aptHint = spec.apt ? ` (Debian/Ubuntu: sudo apt-get install -y ${spec.apt})` : "";
|
|
184
|
+
return {
|
|
185
|
+
command: spec.command,
|
|
186
|
+
present: false,
|
|
187
|
+
installed: false,
|
|
188
|
+
message: `could not auto-install ${spec.command} \u2014 ${spec.manual}${aptHint}`
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function definePlugin(def) {
|
|
192
|
+
const { name, kind, version, capabilities, dependencies, handlers } = def;
|
|
193
|
+
const describeResult = {
|
|
194
|
+
name,
|
|
195
|
+
kind,
|
|
196
|
+
version,
|
|
197
|
+
capabilities: {
|
|
198
|
+
searchTypes: capabilities.searchTypes,
|
|
199
|
+
collectionFilter: capabilities.collectionFilter,
|
|
200
|
+
events: capabilities.events
|
|
201
|
+
},
|
|
202
|
+
dependencies: (dependencies ?? []).map((d) => ({ command: d.command, npm: d.npm, hint: d.hint }))
|
|
203
|
+
};
|
|
204
|
+
async function dispatch(op, params, log) {
|
|
205
|
+
switch (op) {
|
|
206
|
+
case "describe":
|
|
207
|
+
return describeResult;
|
|
208
|
+
case "search":
|
|
209
|
+
return handlers.search(params, log);
|
|
210
|
+
case "index":
|
|
211
|
+
if (handlers.index) return handlers.index(params, log);
|
|
212
|
+
return { indexed: 0 };
|
|
213
|
+
case "setup":
|
|
214
|
+
if (handlers.setup) return handlers.setup(params, log);
|
|
215
|
+
return { ready: true };
|
|
216
|
+
case "event":
|
|
217
|
+
if (handlers.onEvent) return handlers.onEvent(params, log);
|
|
218
|
+
return { accepted: true };
|
|
219
|
+
case "health":
|
|
220
|
+
if (handlers.health) return handlers.health(params, log);
|
|
221
|
+
return { ready: true, diagnostics: [] };
|
|
222
|
+
default:
|
|
223
|
+
throw new Error(`unknown op: ${op}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function run() {
|
|
227
|
+
const log = (level, message) => {
|
|
228
|
+
process.stderr.write(JSON.stringify({ log: { level, message } }) + "\n");
|
|
229
|
+
};
|
|
230
|
+
let buffer = "";
|
|
231
|
+
process.stdin.setEncoding("utf8");
|
|
232
|
+
process.stdin.on("data", (chunk) => {
|
|
233
|
+
buffer += chunk;
|
|
234
|
+
});
|
|
235
|
+
process.stdin.on("end", () => {
|
|
236
|
+
const line = buffer.trim();
|
|
237
|
+
if (!line) {
|
|
238
|
+
process.stderr.write(`${name}: no input received on stdin
|
|
239
|
+
`);
|
|
240
|
+
process.exit(1);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
let req;
|
|
244
|
+
try {
|
|
245
|
+
req = JSON.parse(line);
|
|
246
|
+
} catch {
|
|
247
|
+
process.stderr.write(`${name}: malformed JSON on stdin: ${line.slice(0, 200)}
|
|
248
|
+
`);
|
|
249
|
+
process.exit(1);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
dispatch(req.op, req.params ?? {}, log).then((result) => {
|
|
253
|
+
const response = { ok: true, result };
|
|
254
|
+
process.stdout.write(JSON.stringify(response) + "\n");
|
|
255
|
+
process.exit(0);
|
|
256
|
+
}).catch((err) => {
|
|
257
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
258
|
+
const response = { ok: false, error: { message } };
|
|
259
|
+
process.stdout.write(JSON.stringify(response) + "\n");
|
|
260
|
+
process.exit(1);
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
return { definition: def, run };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export {
|
|
268
|
+
stripFrontmatter,
|
|
269
|
+
parseFrontmatter,
|
|
270
|
+
parseArticle,
|
|
271
|
+
serializeArticle,
|
|
272
|
+
runProcess,
|
|
273
|
+
runProcessJson,
|
|
274
|
+
commandExists,
|
|
275
|
+
resolveDependency,
|
|
276
|
+
ensureTool,
|
|
277
|
+
definePlugin
|
|
278
|
+
};
|
|
@@ -51,6 +51,12 @@ function rankDocs(term, docs) {
|
|
|
51
51
|
if (total > 0) scored.push({ ...d, score: total });
|
|
52
52
|
}
|
|
53
53
|
scored.sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
|
|
54
|
+
const max = scored[0]?.score ?? 0;
|
|
55
|
+
if (max > 0) {
|
|
56
|
+
for (const d of scored) {
|
|
57
|
+
if (typeof d.score === "number") d.score = Number((d.score / max).toFixed(4));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
54
60
|
return scored;
|
|
55
61
|
}
|
|
56
62
|
|
|
@@ -17,6 +17,9 @@ function configPath() {
|
|
|
17
17
|
function collectionsDir() {
|
|
18
18
|
return path.join(resolveHome(), "collections");
|
|
19
19
|
}
|
|
20
|
+
function templatesDir() {
|
|
21
|
+
return path.join(resolveHome(), "templates");
|
|
22
|
+
}
|
|
20
23
|
function collectionDir(name) {
|
|
21
24
|
return path.join(collectionsDir(), name);
|
|
22
25
|
}
|
|
@@ -116,7 +119,7 @@ ${problems.map((p) => ` - ${p}`).join("\n")}`);
|
|
|
116
119
|
// src/collections.ts
|
|
117
120
|
async function fireHook(event, collection) {
|
|
118
121
|
try {
|
|
119
|
-
const { emitPluginEvent: emitPluginEvent2 } = await import("./events-
|
|
122
|
+
const { emitPluginEvent: emitPluginEvent2 } = await import("./events-K3MKWACA.js");
|
|
120
123
|
await emitPluginEvent2(event, collection);
|
|
121
124
|
} catch {
|
|
122
125
|
}
|
|
@@ -351,7 +354,11 @@ function mapHits(result, collections) {
|
|
|
351
354
|
tags: Array.isArray(h.tags) ? h.tags.filter((t) => typeof t === "string") : [],
|
|
352
355
|
snippet: typeof h.snippet === "string" ? h.snippet : void 0,
|
|
353
356
|
score: typeof h.score === "number" ? h.score : void 0,
|
|
354
|
-
docid: typeof h.docid === "string" ? h.docid : void 0
|
|
357
|
+
docid: typeof h.docid === "string" ? h.docid : void 0,
|
|
358
|
+
rawChunk: typeof h.rawChunk === "string" ? h.rawChunk : void 0,
|
|
359
|
+
cleanedChunk: typeof h.cleanedChunk === "string" ? h.cleanedChunk : void 0,
|
|
360
|
+
line: typeof h.line === "number" ? h.line : void 0,
|
|
361
|
+
snippetFromBody: h.snippetFromBody === true ? true : void 0
|
|
355
362
|
});
|
|
356
363
|
}
|
|
357
364
|
return out;
|
|
@@ -381,7 +388,8 @@ async function loadSearchProvider(name) {
|
|
|
381
388
|
collections: toWireCollections(collections),
|
|
382
389
|
collection: opts?.collection,
|
|
383
390
|
type: opts?.type,
|
|
384
|
-
limit: opts?.limit
|
|
391
|
+
limit: opts?.limit,
|
|
392
|
+
expansions: opts?.expansions
|
|
385
393
|
},
|
|
386
394
|
{ timeoutMs: SEARCH_TIMEOUT_MS, name: record.name }
|
|
387
395
|
);
|
|
@@ -479,6 +487,7 @@ export {
|
|
|
479
487
|
registryPath,
|
|
480
488
|
configPath,
|
|
481
489
|
collectionsDir,
|
|
490
|
+
templatesDir,
|
|
482
491
|
collectionDir,
|
|
483
492
|
pluginsDir,
|
|
484
493
|
pluginsRegistryPath,
|