yamlover 0.3.7 → 0.3.10
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/client/assets/{decoded-BOcSNNro.js → decoded-M-9MjrR3.js} +1 -1
- package/dist/client/assets/{djvu-BlBoGQOr.js → djvu-M6ksPMNz.js} +1 -1
- package/dist/client/assets/{docx-DHMG3jBZ.js → docx-D4h81KWC.js} +1 -1
- package/dist/client/assets/{heic-DyzDZBbr.js → heic-BoSpW_tk.js} +1 -1
- package/dist/client/assets/{imagemap-dBuJBDcO.js → imagemap-CIJFPvXv.js} +1 -1
- package/dist/client/assets/{index-DAOxKLZS.css → index-DHqicFJy.css} +1 -1
- package/dist/client/assets/index-DZ1FuhId.js +620 -0
- package/dist/client/assets/{map-DZ0HIGla.js → map-MATRMboW.js} +1 -1
- package/dist/client/assets/{paged-WKVquIPj.js → paged-BQLUFBor.js} +1 -1
- package/dist/client/assets/{panzoom--sfux6SK.js → panzoom-Do4jskMZ.js} +1 -1
- package/dist/client/assets/{pdf-BVBH0bXQ.js → pdf-BShpl2D5.js} +1 -1
- package/dist/client/assets/{psd-CsYV_1P8.js → psd-DIxfuhrV.js} +1 -1
- package/dist/client/assets/{spreadsheet-m5FCnukV.js → spreadsheet-DL0NoDcm.js} +1 -1
- package/dist/client/assets/{tiff-BX8kKhqw.js → tiff-C7zPNKoD.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server.js +199 -20
- package/package.json +1 -1
- package/dist/client/assets/index-c8LVvQSJ.js +0 -617
package/dist/server.js
CHANGED
|
@@ -62441,13 +62441,13 @@ function resolve(doc, chains, fromChain, ptr, visited, anchorKeys) {
|
|
|
62441
62441
|
let steps = ptr.steps;
|
|
62442
62442
|
let chain;
|
|
62443
62443
|
const linkAuthority = ptr.base.scope === "link" ? ptr.base.authority : "";
|
|
62444
|
-
|
|
62444
|
+
const isWorld = ptr.base.scope === "link" && ptr.base.world === true;
|
|
62445
62445
|
const external = () => ({ kind: "external", authority: linkAuthority, steps: ptr.steps });
|
|
62446
62446
|
switch (ptr.base.scope) {
|
|
62447
62447
|
case "link": {
|
|
62448
|
-
isLink = true;
|
|
62449
62448
|
chain = chains.get(root) ?? [root];
|
|
62450
|
-
|
|
62449
|
+
const selfImport = ptr.base.authority === "yamlover" && !root.entries?.some((e3) => e3.key === "yamlover");
|
|
62450
|
+
steps = selfImport ? ptr.steps : [{ sel: "key", name: ptr.base.authority }, ...ptr.steps];
|
|
62451
62451
|
break;
|
|
62452
62452
|
}
|
|
62453
62453
|
case "document": {
|
|
@@ -62470,7 +62470,7 @@ function resolve(doc, chains, fromChain, ptr, visited, anchorKeys) {
|
|
|
62470
62470
|
}
|
|
62471
62471
|
for (const st of steps) {
|
|
62472
62472
|
if (st.sel === "parent") {
|
|
62473
|
-
if (chain.length <= 1) return
|
|
62473
|
+
if (chain.length <= 1) return isWorld ? external() : { kind: "unresolved", reason: '".." above the document root' };
|
|
62474
62474
|
chain = chain.slice(0, -1);
|
|
62475
62475
|
continue;
|
|
62476
62476
|
}
|
|
@@ -62485,8 +62485,8 @@ function resolve(doc, chains, fromChain, ptr, visited, anchorKeys) {
|
|
|
62485
62485
|
continue;
|
|
62486
62486
|
}
|
|
62487
62487
|
}
|
|
62488
|
-
if (!node.entries) return
|
|
62489
|
-
return
|
|
62488
|
+
if (!node.entries) return isWorld ? external() : { kind: "unresolved", reason: "step into a node with no fields" };
|
|
62489
|
+
return isWorld ? external() : { kind: "unresolved", reason: `no ${st.sel === "key" ? `key "${st.name}"` : `index [${st.n}]`}` };
|
|
62490
62490
|
}
|
|
62491
62491
|
if (isPointer(entry.value)) {
|
|
62492
62492
|
if (visited.has(entry.value)) return { kind: "unresolved", reason: "pointer cycle" };
|
|
@@ -62631,6 +62631,71 @@ var Store = class {
|
|
|
62631
62631
|
throw e3;
|
|
62632
62632
|
}
|
|
62633
62633
|
}
|
|
62634
|
+
/** Patch the index for a SINGLE changed subtree instead of rebuilding the whole DB. `doc` is the
|
|
62635
|
+
* FULL, freshly-resolved document (the cached tree with the changed file's subtree spliced back
|
|
62636
|
+
* in and schemas re-applied) — correctness comes from resolving against the whole tree in
|
|
62637
|
+
* memory; speed comes from writing only the rows under `prefix` (the store path P of the changed
|
|
62638
|
+
* subtree). Every node/edge/dangling/file row whose owner lies under P is replaced; rows outside
|
|
62639
|
+
* P are left untouched (their resolution did not change). `files` is the re-walked manifest for
|
|
62640
|
+
* the subtree (POSIX paths under `relPrefix`).
|
|
62641
|
+
*
|
|
62642
|
+
* Returns false WITHOUT writing when the patch is not provably equal to a full rebuild: if any
|
|
62643
|
+
* external `ref`/`back` edge pointing INTO the subtree changed (a referenced node added/removed/
|
|
62644
|
+
* re-resolved), the caller must fall back to a full reindex. The boundary `contain` edge into P
|
|
62645
|
+
* (from P's parent, outside the subtree) is stable and intentionally left in place. */
|
|
62646
|
+
patchSubtree(doc, prefix, files, relPrefix) {
|
|
62647
|
+
const colon = prefix + ":";
|
|
62648
|
+
const brack = prefix + "[";
|
|
62649
|
+
const underP = (p2) => p2 === prefix || p2.startsWith(colon) || p2.startsWith(brack);
|
|
62650
|
+
const edges = resolveDocument(doc);
|
|
62651
|
+
const edgeKey = (from, to2, label, kind, pos) => JSON.stringify([from, to2, label, kind, pos]);
|
|
62652
|
+
const extInNew = edges.filter((r2) => r2.target.kind === "node" && underP(r2.target.path) && !underP(r2.holder)).map((r2) => edgeKey(r2.holder, r2.target.path, r2.label, r2.edge, r2.pos)).sort();
|
|
62653
|
+
const extInOld = this.db.prepare("SELECT from_path, to_path, label, kind, pos FROM edge WHERE kind IN ('ref','back')").all().filter((r2) => underP(r2.to_path) && !underP(r2.from_path)).map((r2) => edgeKey(r2.from_path, r2.to_path, r2.label ?? null, r2.kind, r2.pos ?? null)).sort();
|
|
62654
|
+
if (extInOld.length !== extInNew.length || extInOld.some((k, i2) => k !== extInNew[i2])) return false;
|
|
62655
|
+
const insNode = this.db.prepare(
|
|
62656
|
+
`INSERT INTO node (path, type, format, value, content_hash, size, is_array, meta)
|
|
62657
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
|
62658
|
+
);
|
|
62659
|
+
const insEdge = this.db.prepare(
|
|
62660
|
+
`INSERT INTO edge (from_path, to_path, label, kind, pos) VALUES (?, ?, ?, ?, ?)`
|
|
62661
|
+
);
|
|
62662
|
+
const insDangling = this.db.prepare("INSERT INTO dangling (from_path, raw, reason) VALUES (?, ?, ?)");
|
|
62663
|
+
const insFile = this.db.prepare("INSERT OR REPLACE INTO file (path, hash, size, mtime_ms) VALUES (?, ?, ?, ?)");
|
|
62664
|
+
this.db.exec("BEGIN");
|
|
62665
|
+
try {
|
|
62666
|
+
const delUnder = (col, table) => {
|
|
62667
|
+
this.db.prepare(`DELETE FROM ${table} WHERE ${col} = ? OR substr(${col},1,?) = ? OR substr(${col},1,?) = ?`).run(prefix, colon.length, colon, brack.length, brack);
|
|
62668
|
+
};
|
|
62669
|
+
delUnder("path", "node");
|
|
62670
|
+
delUnder("from_path", "edge");
|
|
62671
|
+
delUnder("from_path", "dangling");
|
|
62672
|
+
if (relPrefix) this.db.prepare("DELETE FROM file WHERE substr(path,1,?) = ?").run(relPrefix.length, relPrefix);
|
|
62673
|
+
walkNodes(doc.root, ":", (p2, node, parent, label, pos) => {
|
|
62674
|
+
if (!underP(p2)) return;
|
|
62675
|
+
const meta = node.meta ? JSON.stringify(node.meta) : null;
|
|
62676
|
+
const owned = node.entries?.filter((e3) => e3.edge !== "back") ?? [];
|
|
62677
|
+
const isArray = node.array || node.kind === "mapping" && owned.length > 0 && owned.every((e3) => e3.key === null);
|
|
62678
|
+
const value = node.kind === "scalar" ? JSON.stringify(node.value) : null;
|
|
62679
|
+
const format = node.kind === "blob" ? node.format : formatFromMeta(node);
|
|
62680
|
+
const hash = node.kind === "blob" ? node.contentHash : null;
|
|
62681
|
+
const size = node.kind === "blob" ? node.size : null;
|
|
62682
|
+
insNode.run(p2, node.kind, format, value, hash, size, isArray ? 1 : 0, meta);
|
|
62683
|
+
if (parent !== null && underP(parent)) insEdge.run(parent, p2, label, "contain", pos);
|
|
62684
|
+
});
|
|
62685
|
+
for (const r2 of edges) {
|
|
62686
|
+
if (!underP(r2.holder)) continue;
|
|
62687
|
+
if (r2.target.kind === "node") insEdge.run(r2.holder, r2.target.path, r2.label, r2.edge, r2.pos);
|
|
62688
|
+
else if (r2.target.kind === "unresolved") insDangling.run(r2.from, r2.raw, r2.target.reason);
|
|
62689
|
+
}
|
|
62690
|
+
for (const f2 of files) insFile.run(f2.path, f2.hash, f2.size, f2.mtimeMs);
|
|
62691
|
+
this.db.exec("COMMIT");
|
|
62692
|
+
this._stale = false;
|
|
62693
|
+
return true;
|
|
62694
|
+
} catch (e3) {
|
|
62695
|
+
this.db.exec("ROLLBACK");
|
|
62696
|
+
throw e3;
|
|
62697
|
+
}
|
|
62698
|
+
}
|
|
62634
62699
|
/** Incrementally add ONE annotation document at `annStorePath`, with a forward `target` ref edge
|
|
62635
62700
|
* to `targetStorePath` and (when given) a keyless `back` edge to `tagStorePath` — the applied
|
|
62636
62701
|
* tag's `~-` membership. This avoids a full re-walk/rebuild (which re-reads and re-hashes every
|
|
@@ -64312,15 +64377,16 @@ function* walkTreeGen(absDir, opts = {}) {
|
|
|
64312
64377
|
root.meta = { ...root.meta, documentRoot: true };
|
|
64313
64378
|
const defsRoot = findDefsRoot(absDir);
|
|
64314
64379
|
const defsDir = path.join(defsRoot, "$defs");
|
|
64380
|
+
const selfRoot = path.resolve(absDir) === defsRoot;
|
|
64315
64381
|
const arrayRoot = root.array || (root.entries?.length ? root.entries.every((e3) => e3.key === null) : false);
|
|
64316
64382
|
let builtinDefs;
|
|
64317
64383
|
if (!arrayRoot && root.entries && !root.entries.some((e3) => e3.key === "yamlover")) {
|
|
64318
|
-
if (fs.existsSync(defsDir)) {
|
|
64384
|
+
if (fs.existsSync(defsDir) && !selfRoot) {
|
|
64319
64385
|
const shared = [{ key: "$defs", edge: "contain", value: yield* dirNode(defsDir, ctx) }];
|
|
64320
64386
|
const tagsDir = path.join(defsRoot, "tags");
|
|
64321
64387
|
if (fs.existsSync(tagsDir)) shared.push({ key: "tags", edge: "contain", value: yield* dirNode(tagsDir, ctx) });
|
|
64322
64388
|
root.entries.push({ key: "yamlover", edge: "contain", value: { kind: "mapping", entries: shared, array: false } });
|
|
64323
|
-
} else {
|
|
64389
|
+
} else if (!fs.existsSync(defsDir)) {
|
|
64324
64390
|
const built = builtinYamloverGraft();
|
|
64325
64391
|
root.entries.push({ key: "yamlover", edge: "contain", value: built.node });
|
|
64326
64392
|
builtinDefs = built.defs;
|
|
@@ -64338,7 +64404,7 @@ function reindex(store, absDir, opts = {}) {
|
|
|
64338
64404
|
store.indexDocument(doc, files);
|
|
64339
64405
|
return diffManifest(prev, files);
|
|
64340
64406
|
}
|
|
64341
|
-
async function
|
|
64407
|
+
async function reindexAsyncDoc(store, absDir, opts = {}) {
|
|
64342
64408
|
const prev = store.stale ? /* @__PURE__ */ new Map() : store.manifest();
|
|
64343
64409
|
const onProgress = opts.onProgress;
|
|
64344
64410
|
const total = onProgress ? await countChildren(path.resolve(absDir), opts) : void 0;
|
|
@@ -64350,7 +64416,49 @@ async function reindexAsync(store, absDir, opts = {}) {
|
|
|
64350
64416
|
onProgress?.({ done: total ?? files.length, total, message: "writing index\u2026" });
|
|
64351
64417
|
await yieldLoop();
|
|
64352
64418
|
store.indexDocument(doc, files);
|
|
64353
|
-
return diffManifest(prev, files);
|
|
64419
|
+
return { diff: diffManifest(prev, files), doc, files };
|
|
64420
|
+
}
|
|
64421
|
+
async function reindexPathAsync(store, absDir, cachedDoc, changedRel, opts = {}) {
|
|
64422
|
+
const root = path.resolve(absDir);
|
|
64423
|
+
const parts = changedRel.split("/");
|
|
64424
|
+
const yi = parts.indexOf(YAMLOVER_DIR);
|
|
64425
|
+
const dirSegs = yi >= 0 ? parts.slice(0, yi) : parts.slice(0, -1);
|
|
64426
|
+
if (dirSegs.length === 0) return null;
|
|
64427
|
+
if (dirSegs[0] === "$defs" || dirSegs[0] === "tags") return null;
|
|
64428
|
+
let entries = cachedDoc.root.entries;
|
|
64429
|
+
let target = null;
|
|
64430
|
+
for (let d = 0; d < dirSegs.length; d++) {
|
|
64431
|
+
if (!entries) return null;
|
|
64432
|
+
const i2 = entries.findIndex((e3) => e3.key === dirSegs[d] && !isPointer(e3.value));
|
|
64433
|
+
if (i2 < 0) return null;
|
|
64434
|
+
if (d === dirSegs.length - 1) target = { arr: entries, i: i2 };
|
|
64435
|
+
else entries = entries[i2].value.entries;
|
|
64436
|
+
}
|
|
64437
|
+
if (!target) return null;
|
|
64438
|
+
const absSpliceDir = path.join(root, ...dirSegs);
|
|
64439
|
+
if (!fs.existsSync(absSpliceDir) || !fs.statSync(absSpliceDir).isDirectory()) return null;
|
|
64440
|
+
const prev = store.stale ? /* @__PURE__ */ new Map() : store.manifest();
|
|
64441
|
+
const ctx = { root, opts: { ...opts, cache: opts.cache ?? manifestCache(prev) }, files: /* @__PURE__ */ new Map(), count: 0 };
|
|
64442
|
+
const gen = dirNode(absSpliceDir, ctx);
|
|
64443
|
+
let r2 = gen.next();
|
|
64444
|
+
while (!r2.done) r2 = gen.next();
|
|
64445
|
+
target.arr[target.i].value = r2.value;
|
|
64446
|
+
applySchemas(cachedDoc.root, findDefsRoot(absDir), graftDefs(cachedDoc.root));
|
|
64447
|
+
const relPrefix = dirSegs.join("/") + "/";
|
|
64448
|
+
const P = ":" + dirSegs.join(":");
|
|
64449
|
+
const prevSub = new Map([...prev].filter(([k]) => k.startsWith(relPrefix)));
|
|
64450
|
+
const files = [...ctx.files.values()];
|
|
64451
|
+
const diff2 = diffManifest(prevSub, files);
|
|
64452
|
+
if (!store.patchSubtree(cachedDoc, P, files, relPrefix)) return null;
|
|
64453
|
+
return { diff: diff2, doc: cachedDoc };
|
|
64454
|
+
}
|
|
64455
|
+
function graftDefs(root) {
|
|
64456
|
+
const yam = root.entries?.find((e3) => e3.key === "yamlover" && !isPointer(e3.value))?.value;
|
|
64457
|
+
const defs = yam?.entries?.find((e3) => e3.key === "$defs" && !isPointer(e3.value))?.value;
|
|
64458
|
+
if (!defs?.entries) return void 0;
|
|
64459
|
+
const m = /* @__PURE__ */ new Map();
|
|
64460
|
+
for (const e3 of defs.entries) if (e3.key && !isPointer(e3.value)) m.set(e3.key, e3.value);
|
|
64461
|
+
return m.size ? m : void 0;
|
|
64354
64462
|
}
|
|
64355
64463
|
function manifestCache(prev) {
|
|
64356
64464
|
return (rel, size, mtimeMs) => {
|
|
@@ -64629,6 +64737,7 @@ function applySchemas(root, defsRoot, builtinDefs) {
|
|
|
64629
64737
|
const addl = field(s2, "additionalProperties");
|
|
64630
64738
|
for (const e3 of inst.entries ?? []) {
|
|
64631
64739
|
if (e3.key == null || isPointer(e3.value)) continue;
|
|
64740
|
+
if (e3.value.meta?.schema && isPointer(e3.value.meta.schema)) continue;
|
|
64632
64741
|
const declared = props && !isPointer(props) ? field(props, e3.key) : null;
|
|
64633
64742
|
const sub = declared ?? addl;
|
|
64634
64743
|
if (sub) apply(e3.value, sub, depth + 1);
|
|
@@ -65380,6 +65489,10 @@ function evalQuery(s2, text, from = ":") {
|
|
|
65380
65489
|
binds = [docRootOf(s2, from)];
|
|
65381
65490
|
break;
|
|
65382
65491
|
case "link": {
|
|
65492
|
+
if (q.base.authority === "yamlover" && childByKey(s2, ":", "yamlover") === null) {
|
|
65493
|
+
binds = [":"];
|
|
65494
|
+
break;
|
|
65495
|
+
}
|
|
65383
65496
|
const hit = childByKey(s2, ":", q.base.authority);
|
|
65384
65497
|
binds = hit === null ? [] : [hit];
|
|
65385
65498
|
break;
|
|
@@ -65994,6 +66107,7 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
65994
66107
|
fs9.mkdirSync(path9.dirname(dbPath), { recursive: true });
|
|
65995
66108
|
const store0 = new Store(dbPath);
|
|
65996
66109
|
const store = () => store0;
|
|
66110
|
+
let cachedDoc = null;
|
|
65997
66111
|
const log = opts.log ?? (() => {
|
|
65998
66112
|
});
|
|
65999
66113
|
let closed = false;
|
|
@@ -66099,14 +66213,32 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66099
66213
|
}
|
|
66100
66214
|
})();
|
|
66101
66215
|
};
|
|
66102
|
-
const doReindex = () =>
|
|
66216
|
+
const doReindex = async () => {
|
|
66217
|
+
const { diff: diff2, doc } = await reindexAsyncDoc(store0, dataRoot, { ignore: ignore2 });
|
|
66218
|
+
cachedDoc = doc;
|
|
66219
|
+
return diff2;
|
|
66220
|
+
};
|
|
66221
|
+
const doReindexFile = async (absFile) => {
|
|
66222
|
+
if (cachedDoc) {
|
|
66223
|
+
const rel = path9.relative(dataRoot, absFile).split(path9.sep).join("/");
|
|
66224
|
+
try {
|
|
66225
|
+
const res = await reindexPathAsync(store0, dataRoot, cachedDoc, rel, { ignore: ignore2 });
|
|
66226
|
+
if (res) {
|
|
66227
|
+
cachedDoc = res.doc;
|
|
66228
|
+
return res.diff;
|
|
66229
|
+
}
|
|
66230
|
+
} catch {
|
|
66231
|
+
}
|
|
66232
|
+
}
|
|
66233
|
+
return doReindex();
|
|
66234
|
+
};
|
|
66103
66235
|
const runIndexTask = (label) => enqueue(async () => {
|
|
66104
66236
|
const h = tasks.start(label);
|
|
66105
66237
|
const t0 = Date.now();
|
|
66106
66238
|
let lastLog = 0;
|
|
66107
66239
|
log(`${label}\u2026`);
|
|
66108
66240
|
try {
|
|
66109
|
-
const diff2 = await
|
|
66241
|
+
const { diff: diff2, doc } = await reindexAsyncDoc(store0, dataRoot, {
|
|
66110
66242
|
ignore: ignore2,
|
|
66111
66243
|
onProgress: (p2) => {
|
|
66112
66244
|
h.progress(p2.done, p2.total, p2.message);
|
|
@@ -66117,6 +66249,7 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66117
66249
|
}
|
|
66118
66250
|
}
|
|
66119
66251
|
});
|
|
66252
|
+
cachedDoc = doc;
|
|
66120
66253
|
h.done();
|
|
66121
66254
|
log(
|
|
66122
66255
|
`${label} done in ${((Date.now() - t0) / 1e3).toFixed(1)}s (+${diff2.added.length} ~${diff2.changed.length} \u2212${diff2.removed.length} \u2192${diff2.moved.length})`
|
|
@@ -66139,6 +66272,7 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66139
66272
|
if (r2.editedFiles.length > 0) {
|
|
66140
66273
|
const follow = reindex(store0, dataRoot, { ignore: ignore2 });
|
|
66141
66274
|
diff2.changed = [.../* @__PURE__ */ new Set([...diff2.changed, ...follow.changed])];
|
|
66275
|
+
cachedDoc = null;
|
|
66142
66276
|
}
|
|
66143
66277
|
}
|
|
66144
66278
|
h.done();
|
|
@@ -66202,8 +66336,8 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66202
66336
|
if (!a2?.tag || s2.node(tagStore)?.format !== TAG_FORMAT) {
|
|
66203
66337
|
throw new Error("annotation needs a `tag` that is an x-yamlover-tag node");
|
|
66204
66338
|
}
|
|
66205
|
-
embedAnnotation(dataRoot, s2, a2);
|
|
66206
|
-
broadcast(await
|
|
66339
|
+
const bodyFile = embedAnnotation(dataRoot, s2, a2);
|
|
66340
|
+
broadcast(await doReindexFile(bodyFile));
|
|
66207
66341
|
scheduleHasher();
|
|
66208
66342
|
return { ok: true };
|
|
66209
66343
|
})
|
|
@@ -66228,8 +66362,8 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66228
66362
|
const tag = url.searchParams.get("tag") || "";
|
|
66229
66363
|
enqueue(async () => {
|
|
66230
66364
|
if (!tag) throw new Error("delete needs a `tag`");
|
|
66231
|
-
unembedAnnotation(dataRoot, s2, target, tag);
|
|
66232
|
-
broadcast(await
|
|
66365
|
+
const bodyFile = unembedAnnotation(dataRoot, s2, target, tag);
|
|
66366
|
+
broadcast(await doReindexFile(bodyFile));
|
|
66233
66367
|
}).then(() => sendJson(res, 200, { ok: true })).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
|
|
66234
66368
|
return;
|
|
66235
66369
|
}
|
|
@@ -66255,6 +66389,22 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66255
66389
|
).then((body) => sendJson(res, 201, body)).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
|
|
66256
66390
|
return;
|
|
66257
66391
|
}
|
|
66392
|
+
if (req.method === "POST" && url.pathname === "/api/board") {
|
|
66393
|
+
readBody(req).then(
|
|
66394
|
+
(data) => enqueue(async () => {
|
|
66395
|
+
const b = data;
|
|
66396
|
+
const cols = Array.isArray(b?.columns) ? b.columns.map((lane) => Array.isArray(lane) ? lane.map((p3) => String(p3)) : []) : [];
|
|
66397
|
+
const { bodyFile } = hostFor(dataRoot, s2, strToSegs(b?.path || ":"));
|
|
66398
|
+
fs9.mkdirSync(path9.dirname(bodyFile), { recursive: true });
|
|
66399
|
+
const src = fs9.existsSync(bodyFile) ? fs9.readFileSync(bodyFile, "utf8") : "";
|
|
66400
|
+
fs9.writeFileSync(bodyFile, writeBoardColumns(src, cols));
|
|
66401
|
+
broadcast(await doReindex());
|
|
66402
|
+
scheduleHasher();
|
|
66403
|
+
return { ok: true };
|
|
66404
|
+
})
|
|
66405
|
+
).then((body) => sendJson(res, 201, body)).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
|
|
66406
|
+
return;
|
|
66407
|
+
}
|
|
66258
66408
|
if (req.method === "POST" && url.pathname === "/api/paste") {
|
|
66259
66409
|
readBody(req).then(
|
|
66260
66410
|
(data) => enqueue(async () => {
|
|
@@ -66350,7 +66500,7 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66350
66500
|
const viewDepth = depth ?? 1;
|
|
66351
66501
|
const kind = displayKind(s2, p2, row);
|
|
66352
66502
|
if (url.pathname === "/api/json") {
|
|
66353
|
-
const wantBytes =
|
|
66503
|
+
const wantBytes = row.type === "blob" && url.searchParams.get("binary") === "1";
|
|
66354
66504
|
sendJson(res, 200, {
|
|
66355
66505
|
path: segsToStr(segs),
|
|
66356
66506
|
type: tocType(s2, p2, row),
|
|
@@ -66389,7 +66539,19 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66389
66539
|
function tocType(s2, p2, row) {
|
|
66390
66540
|
return typeName(s2, p2, row);
|
|
66391
66541
|
}
|
|
66542
|
+
var JSON_EXT = { ".json": "json", ".json5": "json5", ".json5p": "json5p" };
|
|
66392
66543
|
function concreteOf(dataRoot, segs, row) {
|
|
66544
|
+
const last = segs[segs.length - 1];
|
|
66545
|
+
if (typeof last === "string") {
|
|
66546
|
+
const json = JSON_EXT[path9.extname(last).toLowerCase()];
|
|
66547
|
+
if (json) {
|
|
66548
|
+
const abs2 = path9.resolve(dataRoot, ...segs.map(String));
|
|
66549
|
+
try {
|
|
66550
|
+
if (fs9.statSync(abs2).isFile()) return json;
|
|
66551
|
+
} catch {
|
|
66552
|
+
}
|
|
66553
|
+
}
|
|
66554
|
+
}
|
|
66393
66555
|
if (row.type !== "mapping") return null;
|
|
66394
66556
|
if (segs.some((g) => typeof g === "number")) return null;
|
|
66395
66557
|
const abs = path9.resolve(dataRoot, ...segs.map(String));
|
|
@@ -66645,6 +66807,21 @@ function pointerRaw(clientPath) {
|
|
|
66645
66807
|
}
|
|
66646
66808
|
return "::" + out;
|
|
66647
66809
|
}
|
|
66810
|
+
function writeBoardColumns(src, cols) {
|
|
66811
|
+
const laneLine = (lane) => `- [${lane.map((p2) => pointerToken(pointerRaw(p2))).join(", ")}]`;
|
|
66812
|
+
const block = cols.length === 0 ? ["columns: []"] : ["columns:", ...cols.map(laneLine)];
|
|
66813
|
+
let lines = src.replace(/\n+$/, "").split("\n");
|
|
66814
|
+
if (src.trim() === "") lines = ["!!<*yamlover:$defs:board>"];
|
|
66815
|
+
const start = lines.findIndex((l2) => /^columns:/.test(l2));
|
|
66816
|
+
if (start >= 0) {
|
|
66817
|
+
let end = start + 1;
|
|
66818
|
+
while (end < lines.length && (lines[end] === "" || /^[ \t-]/.test(lines[end]))) end++;
|
|
66819
|
+
lines.splice(start, end - start, ...block);
|
|
66820
|
+
} else {
|
|
66821
|
+
lines.push(...block);
|
|
66822
|
+
}
|
|
66823
|
+
return lines.join("\n") + "\n";
|
|
66824
|
+
}
|
|
66648
66825
|
function sidecarTarget(dataRoot, mode, subdir, bodyFile) {
|
|
66649
66826
|
const dirOverlay = bodyFile.endsWith(path9.join(".yamlover", "body.yamlover"));
|
|
66650
66827
|
if (mode === "per-directory" && dirOverlay) {
|
|
@@ -66704,6 +66881,7 @@ function embedAnnotation(dataRoot, s2, a2) {
|
|
|
66704
66881
|
fs9.mkdirSync(path9.dirname(bodyFile), { recursive: true });
|
|
66705
66882
|
const src = fs9.existsSync(bodyFile) ? fs9.readFileSync(bodyFile, "utf8") : "";
|
|
66706
66883
|
fs9.writeFileSync(bodyFile, appendAnnotation(src, within, (indent) => annotationItemLines(a2, indent)));
|
|
66884
|
+
return bodyFile;
|
|
66707
66885
|
}
|
|
66708
66886
|
function embedFragment(dataRoot, s2, mode, f2) {
|
|
66709
66887
|
const segs = strToSegs(f2.target || ":");
|
|
@@ -66760,10 +66938,11 @@ async function ensureThumbnail(dataRoot, s2, mode, segs, row, w, h) {
|
|
|
66760
66938
|
}
|
|
66761
66939
|
function unembedAnnotation(dataRoot, s2, target, tag) {
|
|
66762
66940
|
const { bodyFile, within } = hostFor(dataRoot, s2, strToSegs(target || ":"));
|
|
66763
|
-
if (!fs9.existsSync(bodyFile)) return;
|
|
66764
|
-
const
|
|
66941
|
+
if (!fs9.existsSync(bodyFile)) return bodyFile;
|
|
66942
|
+
const needlePath = ":" + pointerRaw(tag).replace(/^:+/, "");
|
|
66765
66943
|
const src = fs9.readFileSync(bodyFile, "utf8");
|
|
66766
|
-
fs9.writeFileSync(bodyFile, removeAnnotation(src, within, (itemText) => itemText.includes(
|
|
66944
|
+
fs9.writeFileSync(bodyFile, removeAnnotation(src, within, (itemText) => itemText.replace(/\s+/g, "").includes(needlePath)));
|
|
66945
|
+
return bodyFile;
|
|
66767
66946
|
}
|
|
66768
66947
|
function writeTag(dataRoot, location, name) {
|
|
66769
66948
|
if (/[/\\\r\n:]/.test(name)) throw new Error("a tag name cannot contain '/', '\\', ':' or line breaks");
|