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 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
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  rankDocs,
3
3
  tokenize
4
- } from "./chunk-FTUF6IXS.js";
4
+ } from "./chunk-TK2373AM.js";
5
5
  export {
6
6
  rankDocs,
7
7
  tokenize
@@ -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-AVD3G5AX.js");
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,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  emitPluginEvent
3
- } from "./chunk-7V2DIQNL.js";
3
+ } from "./chunk-TXM4OGBA.js";
4
4
  export {
5
5
  emitPluginEvent
6
6
  };