yamlover 0.3.22 → 0.3.24
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 +34 -1
- package/bin/yamlover.js +30 -15
- package/dist/builtin-taxonomy/$defs/config +4 -0
- package/dist/client/assets/{decoded-CJRPjXa1.js → decoded-CoBf28Qo.js} +1 -1
- package/dist/client/assets/{djvu-DTScSRBE.js → djvu-CZ2rFOhT.js} +1 -1
- package/dist/client/assets/{docx-CZ_-bbiw.js → docx-D39uvoU4.js} +1 -1
- package/dist/client/assets/{heic-GGCTCDdl.js → heic-V9_YmnBI.js} +1 -1
- package/dist/client/assets/imagemap-b1Kpzcjf.js +1 -0
- package/dist/client/assets/index-DGta_4EZ.js +665 -0
- package/dist/client/assets/index-DyHnoDfk.css +1 -0
- package/dist/client/assets/{map-B1r-13cZ.js → map-CTJuSrDN.js} +1 -1
- package/dist/client/assets/{openable-Bh72damS.js → openable-BA6YbLif.js} +1 -1
- package/dist/client/assets/{paged-DMHOhYfR.js → paged-BYF4Obqh.js} +1 -1
- package/dist/client/assets/{pdf-DNh_WoxB.js → pdf-n0dUtCdE.js} +1 -1
- package/dist/client/assets/{psd-BODwPXZY.js → psd-Z9Xy8WJM.js} +1 -1
- package/dist/client/assets/{spreadsheet-jmhwwLqI.js → spreadsheet-Cx1xwMVZ.js} +1 -1
- package/dist/client/assets/{tiff-B7WRQzVg.js → tiff-BU7hwL9b.js} +1 -1
- package/dist/client/index.html +12 -2
- package/dist/server.js +534 -209
- package/package.json +1 -1
- package/dist/client/assets/imagemap-99Y1w9r3.js +0 -1
- package/dist/client/assets/index-1sCxQdj3.css +0 -1
- package/dist/client/assets/index-Dwsn6NQE.js +0 -632
package/dist/server.js
CHANGED
|
@@ -62331,6 +62331,7 @@ var require_ignore = __commonJS({
|
|
|
62331
62331
|
// src/server/engine-api.ts
|
|
62332
62332
|
import path10 from "node:path";
|
|
62333
62333
|
import fs10 from "node:fs";
|
|
62334
|
+
import os from "node:os";
|
|
62334
62335
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
62335
62336
|
|
|
62336
62337
|
// ../parser/ts/src/ir.ts
|
|
@@ -62535,7 +62536,7 @@ function pathOf(chain) {
|
|
|
62535
62536
|
|
|
62536
62537
|
// ../engine/ts/src/store.ts
|
|
62537
62538
|
import { DatabaseSync } from "node:sqlite";
|
|
62538
|
-
var SCHEMA_VERSION =
|
|
62539
|
+
var SCHEMA_VERSION = 6;
|
|
62539
62540
|
var SCHEMA = `
|
|
62540
62541
|
CREATE TABLE IF NOT EXISTS node (
|
|
62541
62542
|
path TEXT PRIMARY KEY,
|
|
@@ -62565,8 +62566,14 @@ CREATE TABLE IF NOT EXISTS file (
|
|
|
62565
62566
|
CREATE TABLE IF NOT EXISTS dangling (
|
|
62566
62567
|
from_path TEXT NOT NULL, -- the entry holding the pointer
|
|
62567
62568
|
raw TEXT NOT NULL, -- the pointer text as authored
|
|
62568
|
-
reason TEXT NOT NULL
|
|
62569
|
+
reason TEXT NOT NULL, -- why it did not resolve (externals: the authority)
|
|
62570
|
+
holder TEXT NOT NULL, -- the mapping that holds the entry
|
|
62571
|
+
label TEXT, -- the entry's key; null for keyless/positional
|
|
62572
|
+
pos INTEGER, -- the entry's index in the holder (source order)
|
|
62573
|
+
edge TEXT NOT NULL, -- ref | back (as authored)
|
|
62574
|
+
external INTEGER NOT NULL DEFAULT 0 -- 1 = an external-authority link, not an error
|
|
62569
62575
|
);
|
|
62576
|
+
CREATE INDEX IF NOT EXISTS dangling_holder ON dangling (holder);
|
|
62570
62577
|
`;
|
|
62571
62578
|
function encodeScalarValue(v) {
|
|
62572
62579
|
if (typeof v === "number" && !Number.isFinite(v)) return JSON.stringify({ "@nonfinite": String(v) });
|
|
@@ -62631,10 +62638,10 @@ var Store = class {
|
|
|
62631
62638
|
insNode.run(path11, node.kind, format, value, hash, size, isArray ? 1 : 0, meta);
|
|
62632
62639
|
if (parent !== null) insEdge.run(parent, path11, label, "contain", pos);
|
|
62633
62640
|
});
|
|
62634
|
-
const insDangling = this.db.prepare(
|
|
62641
|
+
const insDangling = this.db.prepare(INSERT_DANGLING);
|
|
62635
62642
|
for (const r2 of resolveDocument(doc)) {
|
|
62636
62643
|
if (r2.target.kind === "node") insEdge.run(r2.holder, r2.target.path, r2.label, r2.edge, r2.pos);
|
|
62637
|
-
else
|
|
62644
|
+
else insDanglingRef(insDangling, r2);
|
|
62638
62645
|
}
|
|
62639
62646
|
if (files) {
|
|
62640
62647
|
const insFile = this.db.prepare("INSERT OR REPLACE INTO file (path, hash, size, mtime_ms) VALUES (?, ?, ?, ?)");
|
|
@@ -62675,7 +62682,7 @@ var Store = class {
|
|
|
62675
62682
|
const insEdge = this.db.prepare(
|
|
62676
62683
|
`INSERT INTO edge (from_path, to_path, label, kind, pos) VALUES (?, ?, ?, ?, ?)`
|
|
62677
62684
|
);
|
|
62678
|
-
const insDangling = this.db.prepare(
|
|
62685
|
+
const insDangling = this.db.prepare(INSERT_DANGLING);
|
|
62679
62686
|
const insFile = this.db.prepare("INSERT OR REPLACE INTO file (path, hash, size, mtime_ms) VALUES (?, ?, ?, ?)");
|
|
62680
62687
|
this.db.exec("BEGIN");
|
|
62681
62688
|
try {
|
|
@@ -62684,7 +62691,7 @@ var Store = class {
|
|
|
62684
62691
|
};
|
|
62685
62692
|
delUnder("path", "node");
|
|
62686
62693
|
delUnder("from_path", "edge");
|
|
62687
|
-
delUnder("
|
|
62694
|
+
delUnder("holder", "dangling");
|
|
62688
62695
|
if (relPrefix) this.db.prepare("DELETE FROM file WHERE substr(path,1,?) = ?").run(relPrefix.length, relPrefix);
|
|
62689
62696
|
walkNodes(doc.root, ":", (p2, node, parent, label, pos) => {
|
|
62690
62697
|
if (!underP(p2)) return;
|
|
@@ -62701,7 +62708,7 @@ var Store = class {
|
|
|
62701
62708
|
for (const r2 of edges) {
|
|
62702
62709
|
if (!underP(r2.holder)) continue;
|
|
62703
62710
|
if (r2.target.kind === "node") insEdge.run(r2.holder, r2.target.path, r2.label, r2.edge, r2.pos);
|
|
62704
|
-
else
|
|
62711
|
+
else insDanglingRef(insDangling, r2);
|
|
62705
62712
|
}
|
|
62706
62713
|
for (const f2 of files) insFile.run(f2.path, f2.hash, f2.size, f2.mtimeMs);
|
|
62707
62714
|
this.db.exec("COMMIT");
|
|
@@ -62835,14 +62842,27 @@ var Store = class {
|
|
|
62835
62842
|
throw e3;
|
|
62836
62843
|
}
|
|
62837
62844
|
}
|
|
62838
|
-
/** The pointers that failed to resolve at index time (ENGINE.md: reported, never dropped).
|
|
62845
|
+
/** The pointers that failed to resolve at index time (ENGINE.md: reported, never dropped).
|
|
62846
|
+
* External-authority links are not errors, so they are excluded here. */
|
|
62839
62847
|
dangling() {
|
|
62840
|
-
return this.db.prepare("SELECT * FROM dangling").all().map((r2) => ({
|
|
62848
|
+
return this.db.prepare("SELECT * FROM dangling WHERE external = 0").all().map((r2) => ({
|
|
62841
62849
|
from: r2.from_path,
|
|
62842
62850
|
raw: r2.raw,
|
|
62843
62851
|
reason: r2.reason
|
|
62844
62852
|
}));
|
|
62845
62853
|
}
|
|
62854
|
+
/** A node's pointer ENTRIES with no local target — unresolved (dangling) plus external-
|
|
62855
|
+
* authority links — in source order. These are the entries {@link entries} cannot list (no
|
|
62856
|
+
* edge exists), returned so a projection can still show the authored pointer in place. */
|
|
62857
|
+
unrealizedRefs(holder) {
|
|
62858
|
+
return this.db.prepare("SELECT label, pos, raw, edge, external FROM dangling WHERE holder = ? ORDER BY pos").all(holder).map((r2) => ({
|
|
62859
|
+
label: r2.label ?? null,
|
|
62860
|
+
pos: r2.pos ?? null,
|
|
62861
|
+
raw: r2.raw,
|
|
62862
|
+
edge: r2.edge,
|
|
62863
|
+
external: r2.external === 1
|
|
62864
|
+
}));
|
|
62865
|
+
}
|
|
62846
62866
|
/** A node's attributes (null if no such path). */
|
|
62847
62867
|
node(path11) {
|
|
62848
62868
|
const row = this.db.prepare("SELECT * FROM node WHERE path = ?").get(path11);
|
|
@@ -62905,6 +62925,13 @@ var Store = class {
|
|
|
62905
62925
|
return { out, in: [...inc, ...derivedIn] };
|
|
62906
62926
|
}
|
|
62907
62927
|
};
|
|
62928
|
+
var INSERT_DANGLING = "INSERT INTO dangling (from_path, raw, reason, holder, label, pos, edge, external) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
|
62929
|
+
function insDanglingRef(stmt, r2) {
|
|
62930
|
+
if (r2.target.kind === "node") return;
|
|
62931
|
+
const ext = r2.target.kind === "external";
|
|
62932
|
+
const reason = r2.target.kind === "external" ? r2.target.authority : r2.target.reason;
|
|
62933
|
+
stmt.run(r2.from, r2.raw, reason, r2.anchor ? "" : r2.holder, r2.label, r2.pos, r2.edge, ext ? 1 : 0);
|
|
62934
|
+
}
|
|
62908
62935
|
function walkNodes(node, path11, visit2, parent = null, label = null, pos = null) {
|
|
62909
62936
|
visit2(path11, node, parent, label, pos);
|
|
62910
62937
|
if (!node.entries) return;
|
|
@@ -62915,6 +62942,7 @@ function walkNodes(node, path11, visit2, parent = null, label = null, pos = null
|
|
|
62915
62942
|
});
|
|
62916
62943
|
}
|
|
62917
62944
|
function formatFromMeta(node) {
|
|
62945
|
+
if (node.meta?.derivedFormat) return node.meta.derivedFormat;
|
|
62918
62946
|
const s2 = node.meta?.schema;
|
|
62919
62947
|
if (!s2) return null;
|
|
62920
62948
|
if (isPointer(s2)) {
|
|
@@ -64916,7 +64944,7 @@ function applyMeta(node, meta) {
|
|
|
64916
64944
|
if (!m) continue;
|
|
64917
64945
|
if (m.uniqueItems) e3.value = { ...e3.value, meta: { ...e3.value.meta, set: true } };
|
|
64918
64946
|
if (e3.value.kind === "blob") continue;
|
|
64919
|
-
if (m.format && !e3.value.meta?.schema) e3.value = { ...e3.value, meta: { ...e3.value.meta,
|
|
64947
|
+
if (m.format && !e3.value.meta?.schema) e3.value = { ...e3.value, meta: { ...e3.value.meta, derivedFormat: m.format } };
|
|
64920
64948
|
}
|
|
64921
64949
|
return node;
|
|
64922
64950
|
}
|
|
@@ -64935,7 +64963,7 @@ function blob(abs, format, ctx) {
|
|
|
64935
64963
|
}
|
|
64936
64964
|
function textScalar(abs, format, ctx) {
|
|
64937
64965
|
const text = readTracked(ctx, abs).toString("utf8");
|
|
64938
|
-
return { kind: "scalar", value: text, raw: text, meta: {
|
|
64966
|
+
return { kind: "scalar", value: text, raw: text, meta: { derivedFormat: format } };
|
|
64939
64967
|
}
|
|
64940
64968
|
function parsedScalar(abs, ext, ctx) {
|
|
64941
64969
|
const lang = ext === ".json" || ext === ".json5" || ext === ".json5p" ? "json5p" : ext === ".yaml" || ext === ".yml" ? "yaml" : "yamlover";
|
|
@@ -64983,7 +65011,7 @@ function applySchemas(root, defsRoot, builtinDefs) {
|
|
|
64983
65011
|
return v && !isPointer(v) && v.kind === "scalar" && v.value != null ? String(v.value) : null;
|
|
64984
65012
|
};
|
|
64985
65013
|
const hasFormat = (inst) => {
|
|
64986
|
-
if (inst.kind === "blob") return true;
|
|
65014
|
+
if (inst.kind === "blob" || inst.meta?.derivedFormat) return true;
|
|
64987
65015
|
const s2 = inst.meta?.schema;
|
|
64988
65016
|
return !!s2 && !isPointer(s2) && s2.kind === "mapping" && !!field(s2, "format");
|
|
64989
65017
|
};
|
|
@@ -65019,7 +65047,7 @@ function applySchemas(root, defsRoot, builtinDefs) {
|
|
|
65019
65047
|
const stype = str(s2, "type");
|
|
65020
65048
|
const named = name && (stype === "object" || stype === "variant" || stype === "mixed" || !!field(s2, "allOf"));
|
|
65021
65049
|
const fmt = str(s2, "format") ?? (named ? `x-yamlover-${name}` : null);
|
|
65022
|
-
if (fmt && !hasFormat(inst)) inst.meta = { ...inst.meta,
|
|
65050
|
+
if (fmt && !hasFormat(inst)) inst.meta = { ...inst.meta, derivedFormat: fmt };
|
|
65023
65051
|
if (stype === "object" || stype === "variant" || stype === "mixed" || stype === "array" || field(s2, "items")) {
|
|
65024
65052
|
const props = field(s2, "properties");
|
|
65025
65053
|
const addl = field(s2, "additionalProperties");
|
|
@@ -65044,9 +65072,6 @@ function applySchemas(root, defsRoot, builtinDefs) {
|
|
|
65044
65072
|
};
|
|
65045
65073
|
walk(root);
|
|
65046
65074
|
}
|
|
65047
|
-
function inlineFormat(format) {
|
|
65048
|
-
return { kind: "mapping", entries: [{ key: "format", edge: "contain", value: { kind: "scalar", value: format, raw: format } }], array: false };
|
|
65049
|
-
}
|
|
65050
65075
|
function applyBody(dir, node, ctx) {
|
|
65051
65076
|
const file = path2.join(dir, YAMLOVER_DIR, "body.yamlover");
|
|
65052
65077
|
if (!fs2.existsSync(file)) return node;
|
|
@@ -65189,11 +65214,21 @@ var DOC_FORMATS = {
|
|
|
65189
65214
|
import * as path3 from "node:path";
|
|
65190
65215
|
|
|
65191
65216
|
// ../parser/ts/src/serialize-common.ts
|
|
65217
|
+
var LossyError = class extends Error {
|
|
65218
|
+
};
|
|
65192
65219
|
function anchorBody(a2) {
|
|
65193
65220
|
return renderPointer(a2.path) + (a2.ordinal ? "[]" : "");
|
|
65194
65221
|
}
|
|
65195
65222
|
|
|
65196
65223
|
// ../parser/ts/src/serialize-yamlover.ts
|
|
65224
|
+
function schemaText(v) {
|
|
65225
|
+
const text = isPointer(v) ? `*${renderPointer(v)}` : schemaNodeText(v);
|
|
65226
|
+
if (/[>\n]/.test(text)) throw new LossyError(`a !!<\u2026> schema tag cannot contain ">" or a newline: ${text}`);
|
|
65227
|
+
return text;
|
|
65228
|
+
}
|
|
65229
|
+
function schemaTagToken(v) {
|
|
65230
|
+
return `!!<${schemaText(v)}>`;
|
|
65231
|
+
}
|
|
65197
65232
|
function pointerToken(raw) {
|
|
65198
65233
|
if (raw !== raw.trim()) return `*'${raw.replace(/'/g, "''")}'`;
|
|
65199
65234
|
return "*" + raw;
|
|
@@ -65222,6 +65257,73 @@ function hasUnquotedSpace(s2) {
|
|
|
65222
65257
|
}
|
|
65223
65258
|
return false;
|
|
65224
65259
|
}
|
|
65260
|
+
function dq(s2) {
|
|
65261
|
+
return JSON.stringify(s2);
|
|
65262
|
+
}
|
|
65263
|
+
function keyText(key) {
|
|
65264
|
+
const needsQuote = key === "" || key !== key.trim() || /[\u0000-\u001f\u007f]/.test(key) || key.includes(": ") || // splitKV would split at the inner colon
|
|
65265
|
+
key === "-" || key.startsWith("- ") || /^['"]/.test(key) || key.includes("\\");
|
|
65266
|
+
if (needsQuote) return dq(key);
|
|
65267
|
+
return key.replace(/[/[\]*&#~?!()<>=|]/g, (c3) => "\\" + c3);
|
|
65268
|
+
}
|
|
65269
|
+
function schemaNodeText(n2) {
|
|
65270
|
+
if (n2.kind === "mapping") {
|
|
65271
|
+
const ents = n2.entries;
|
|
65272
|
+
const keyed = ents.filter((e3) => e3.key !== null);
|
|
65273
|
+
if (keyed.length === ents.length && ents.length === 1 && ents[0].edge !== "back") {
|
|
65274
|
+
const e3 = ents[0];
|
|
65275
|
+
const v = isPointer(e3.value) ? flowPtr(e3.value) : flowText(e3.value);
|
|
65276
|
+
return `${keyText(e3.key)}: ${v}`;
|
|
65277
|
+
}
|
|
65278
|
+
if (keyed.length > 0) {
|
|
65279
|
+
throw new LossyError("an inline !!<\u2026> schema holds at most one top-level key");
|
|
65280
|
+
}
|
|
65281
|
+
}
|
|
65282
|
+
return flowText(n2);
|
|
65283
|
+
}
|
|
65284
|
+
function flowText(n2) {
|
|
65285
|
+
if (n2.kind === "blob") throw new LossyError("a blob has no flow form");
|
|
65286
|
+
if (n2.meta?.schema !== void 0 || n2.meta?.set === true) {
|
|
65287
|
+
throw new LossyError("tags inside an inline !!<\u2026> schema are not serializable");
|
|
65288
|
+
}
|
|
65289
|
+
const ents = n2.entries ?? [];
|
|
65290
|
+
if (n2.kind === "scalar") {
|
|
65291
|
+
if (ents.length > 0) throw new LossyError("a value-plus-fields node has no flow form");
|
|
65292
|
+
return flowTok(n2);
|
|
65293
|
+
}
|
|
65294
|
+
if (ents.length === 0) return n2.array ? "[]" : "{}";
|
|
65295
|
+
const keyed = ents.filter((e3) => e3.key !== null);
|
|
65296
|
+
if (keyed.length > 0 && keyed.length < ents.length) throw new LossyError("a mixed container has no flow form");
|
|
65297
|
+
if (ents.some((e3) => e3.edge === "back")) throw new LossyError("back-edges inside an inline !!<\u2026> schema are not serializable");
|
|
65298
|
+
const item = (e3) => {
|
|
65299
|
+
const v = isPointer(e3.value) ? flowPtr(e3.value) : flowText(e3.value);
|
|
65300
|
+
return e3.key === null ? v : `${flowKey(e3.key)}: ${v}`;
|
|
65301
|
+
};
|
|
65302
|
+
return keyed.length === 0 ? `[${ents.map(item).join(", ")}]` : `{${ents.map(item).join(", ")}}`;
|
|
65303
|
+
}
|
|
65304
|
+
function nonFinite(v) {
|
|
65305
|
+
return Number.isNaN(v) ? ".nan" : v === Infinity ? ".inf" : "-.inf";
|
|
65306
|
+
}
|
|
65307
|
+
function flowTok(s2) {
|
|
65308
|
+
const v = s2.value;
|
|
65309
|
+
if (v === null) return "null";
|
|
65310
|
+
if (typeof v === "boolean") return v ? "true" : "false";
|
|
65311
|
+
if (typeof v === "number") {
|
|
65312
|
+
if (!Number.isFinite(v)) return nonFinite(v);
|
|
65313
|
+
return String(v);
|
|
65314
|
+
}
|
|
65315
|
+
if (v !== "" && /^[^,:[\]{}'"#\s]+$/.test(v) && !"*&~!|>".includes(v[0]) && plainScalar(v).value === v) return v;
|
|
65316
|
+
if (/[\n\r\u0000-\u0008\u000b-\u001f\u007f]/.test(v)) throw new LossyError("a control character has no flow form inside a !!<\u2026> tag");
|
|
65317
|
+
return `'${v.replace(/'/g, "''")}'`;
|
|
65318
|
+
}
|
|
65319
|
+
function flowPtr(p2) {
|
|
65320
|
+
const compact2 = renderPointer(p2, { spaced: false });
|
|
65321
|
+
if (/['"\s]/.test(compact2)) throw new LossyError(`pointer "*${compact2}" does not fit a flow context`);
|
|
65322
|
+
return `*${compact2}`;
|
|
65323
|
+
}
|
|
65324
|
+
function flowKey(k) {
|
|
65325
|
+
return /^[\w.$/-]+$/.test(k) ? k : `'${k.replace(/'/g, "''")}'`;
|
|
65326
|
+
}
|
|
65225
65327
|
|
|
65226
65328
|
// ../engine/ts/src/rewrite.ts
|
|
65227
65329
|
function under(p2, x2) {
|
|
@@ -65556,7 +65658,9 @@ var DEFAULT_SETTINGS = {
|
|
|
65556
65658
|
exports: [],
|
|
65557
65659
|
annotations: ":annotations",
|
|
65558
65660
|
tags: ":tags",
|
|
65559
|
-
sidecars: "per-directory"
|
|
65661
|
+
sidecars: "per-directory",
|
|
65662
|
+
width: void 0,
|
|
65663
|
+
theme: void 0
|
|
65560
65664
|
};
|
|
65561
65665
|
var DEFAULT_SETTINGS_SOURCE = `# .yamlover/settings.yamlover \u2014 project settings for this root (created with defaults).
|
|
65562
65666
|
# Settings are DEFAULTS, never constraints: they only say where the server CREATES things when you
|
|
@@ -65569,6 +65673,7 @@ var DEFAULT_SETTINGS_SOURCE = `# .yamlover/settings.yamlover \u2014 project sett
|
|
|
65569
65673
|
annotations: *:: annotations # create new annotations in :annotations
|
|
65570
65674
|
tags: *:: tags # create new tags in :tags
|
|
65571
65675
|
sidecars: per-directory # where derived thumbnail/crop blobs go (enum, not a path)
|
|
65676
|
+
# width: 100 # reading width (ch) for prose views; browser settings override it
|
|
65572
65677
|
`;
|
|
65573
65678
|
function ensureSettingsFile(absRoot) {
|
|
65574
65679
|
const file = path6.join(absRoot, ".yamlover", "settings.yamlover");
|
|
@@ -65592,9 +65697,20 @@ function loadSettings(absRoot) {
|
|
|
65592
65697
|
exports: exportsSetting(valueAt(root, "exports")),
|
|
65593
65698
|
annotations: locationSetting(valueAt(root, "annotations"), DEFAULT_SETTINGS.annotations),
|
|
65594
65699
|
tags: locationSetting(valueAt(root, "tags"), DEFAULT_SETTINGS.tags),
|
|
65595
|
-
sidecars: sidecarLocation(valueAt(root, "sidecars"), DEFAULT_SETTINGS.sidecars)
|
|
65700
|
+
sidecars: sidecarLocation(valueAt(root, "sidecars"), DEFAULT_SETTINGS.sidecars),
|
|
65701
|
+
width: intSetting(valueAt(root, "width"), 20, 400),
|
|
65702
|
+
theme: enumSetting(valueAt(root, "theme"), ["dark", "light"])
|
|
65596
65703
|
};
|
|
65597
65704
|
}
|
|
65705
|
+
function intSetting(v, min, max) {
|
|
65706
|
+
if (v === void 0 || isPointer(v) || v.kind !== "scalar") return void 0;
|
|
65707
|
+
const n2 = typeof v.value === "number" ? v.value : NaN;
|
|
65708
|
+
return Number.isInteger(n2) && n2 >= min && n2 <= max ? n2 : void 0;
|
|
65709
|
+
}
|
|
65710
|
+
function enumSetting(v, values) {
|
|
65711
|
+
if (v === void 0 || isPointer(v) || v.kind !== "scalar") return void 0;
|
|
65712
|
+
return values.includes(v.value) ? v.value : void 0;
|
|
65713
|
+
}
|
|
65598
65714
|
function uriSetting(v) {
|
|
65599
65715
|
if (v === void 0) return void 0;
|
|
65600
65716
|
if (isPointer(v)) return v.base.scope === "link" ? v.base.authority : void 0;
|
|
@@ -66434,7 +66550,11 @@ function findGitRoot(start) {
|
|
|
66434
66550
|
|
|
66435
66551
|
// src/server/node-kind.ts
|
|
66436
66552
|
function ownedEntries(s2, p2) {
|
|
66437
|
-
|
|
66553
|
+
const own = s2.entries(p2).filter((e3) => e3.kind !== "back");
|
|
66554
|
+
const unrealized = s2.unrealizedRefs(p2).filter((u2) => u2.edge !== "back");
|
|
66555
|
+
if (unrealized.length === 0) return own;
|
|
66556
|
+
for (const u2 of unrealized) own.push({ to: "", label: u2.label, pos: u2.pos, kind: "ref", raw: u2.raw });
|
|
66557
|
+
return own.sort((a2, b) => (a2.pos ?? 0) - (b.pos ?? 0));
|
|
66438
66558
|
}
|
|
66439
66559
|
function displayKind(s2, p2, row) {
|
|
66440
66560
|
const ents = ownedEntries(s2, p2);
|
|
@@ -66529,6 +66649,7 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66529
66649
|
const rootName = path10.basename(path10.resolve(dataRoot)) || "/";
|
|
66530
66650
|
const dbPath = path10.join(dataRoot, ".yamlover", "index.db");
|
|
66531
66651
|
const settingsFile = path10.join(dataRoot, ".yamlover", "settings.yamlover");
|
|
66652
|
+
const settingsRel = path10.relative(dataRoot, settingsFile).split(path10.sep).join("/");
|
|
66532
66653
|
if (opts.ensureSettings) {
|
|
66533
66654
|
try {
|
|
66534
66655
|
ensureSettingsFile(dataRoot);
|
|
@@ -66555,6 +66676,7 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66555
66676
|
};
|
|
66556
66677
|
const broadcast = (diff2) => {
|
|
66557
66678
|
if (diff2.added.length + diff2.changed.length + diff2.removed.length + diff2.moved.length === 0) return;
|
|
66679
|
+
if (diff2.changed.includes(settingsRel) || diff2.added.includes(settingsRel)) settings = loadSettings(dataRoot);
|
|
66558
66680
|
const toClient = (rel) => segsToStr(rel.split("/"));
|
|
66559
66681
|
sseWrite({
|
|
66560
66682
|
type: "diff",
|
|
@@ -66856,62 +66978,26 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66856
66978
|
(data) => enqueue(async () => {
|
|
66857
66979
|
const d = data;
|
|
66858
66980
|
const edits = Array.isArray(d.edits) ? d.edits : [d];
|
|
66859
|
-
const touched = applyEdits2(dataRoot, s2, edits);
|
|
66860
|
-
|
|
66981
|
+
const { touched, created, appended } = applyEdits2(dataRoot, s2, edits);
|
|
66982
|
+
if (created.length) broadcast(await doReindex());
|
|
66983
|
+
else for (const f2 of touched) broadcast(await doReindexFile(f2));
|
|
66861
66984
|
scheduleHasher();
|
|
66985
|
+
if (created.length) return { ok: true, path: created[created.length - 1] };
|
|
66986
|
+
if (appended.length) return { ok: true, path: lastBodyChildPath(s2, appended[appended.length - 1]) };
|
|
66862
66987
|
return { ok: true };
|
|
66863
66988
|
})
|
|
66864
66989
|
).then((body) => sendJson(res, 200, body)).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
|
|
66865
66990
|
return;
|
|
66866
66991
|
}
|
|
66867
|
-
if (req.method === "POST" && url.pathname === "/api/
|
|
66868
|
-
readBody(req).then(
|
|
66869
|
-
|
|
66870
|
-
|
|
66871
|
-
|
|
66872
|
-
|
|
66873
|
-
|
|
66874
|
-
|
|
66875
|
-
|
|
66876
|
-
if (!row2) throw new Error(`no such node: ${b.parent}`);
|
|
66877
|
-
const title = String(b.title ?? "").trim() || defaultTitle(String(b.schema));
|
|
66878
|
-
const body = reg.body(title);
|
|
66879
|
-
const objSrc = objectFileSource(reg.tag, body);
|
|
66880
|
-
if (reg.childOf.includes(row2.format ?? "")) {
|
|
66881
|
-
const { docSegs, bodyFile, dirBacked } = chapterSource(dataRoot, s2, parentSegs);
|
|
66882
|
-
const within = parentSegs.slice(docSegs.length);
|
|
66883
|
-
if (concrete === "yamlover") {
|
|
66884
|
-
const src = fs10.readFileSync(bodyFile, "utf8");
|
|
66885
|
-
fs10.writeFileSync(bodyFile, appendBody(src, within, (indent) => inlineChildLines(body, indent)));
|
|
66886
|
-
broadcast(await doReindexFile(bodyFile));
|
|
66887
|
-
scheduleHasher();
|
|
66888
|
-
return { path: lastBodyChildPath(s2, parentSegs) };
|
|
66889
|
-
}
|
|
66890
|
-
if (concrete === "file/yamlover" || concrete === "dir/yamlover") {
|
|
66891
|
-
const writeDirSegs = dirBacked ? docSegs : docSegs.slice(0, -1);
|
|
66892
|
-
const writeDir = path10.resolve(dataRoot, ...writeDirSegs.map(String));
|
|
66893
|
-
const final = writeObject(dataRoot, writeDir, sanitizeName(title), concrete, objSrc);
|
|
66894
|
-
const targetSegs = [...writeDirSegs, final];
|
|
66895
|
-
const pointer = dirBacked ? `*/${final}` : `*/${segsToStr(targetSegs)}`;
|
|
66896
|
-
const src = fs10.readFileSync(bodyFile, "utf8");
|
|
66897
|
-
fs10.writeFileSync(bodyFile, appendBody(src, within, (indent) => [`${" ".repeat(indent)}- ${pointer}`]));
|
|
66898
|
-
broadcast(await doReindex());
|
|
66899
|
-
scheduleHasher();
|
|
66900
|
-
return { path: segsToStr(targetSegs) };
|
|
66901
|
-
}
|
|
66902
|
-
throw new Error(`invalid concrete for a child: ${concrete}`);
|
|
66903
|
-
}
|
|
66904
|
-
const abs = path10.resolve(dataRoot, ...parentSegs.map(String));
|
|
66905
|
-
if (parentSegs.every((g) => typeof g === "string") && fs10.existsSync(abs) && fs10.statSync(abs).isDirectory()) {
|
|
66906
|
-
if (concrete !== "file/yamlover" && concrete !== "dir/yamlover") throw new Error(`invalid concrete for a directory member: ${concrete}`);
|
|
66907
|
-
const final = writeObject(dataRoot, abs, objectBaseName(title), concrete, objSrc);
|
|
66908
|
-
broadcast(await doReindex());
|
|
66909
|
-
scheduleHasher();
|
|
66910
|
-
return { path: segsToStr([...parentSegs, final]) };
|
|
66911
|
-
}
|
|
66912
|
-
throw new Error("this schema can be created only inside a directory or a compatible parent");
|
|
66913
|
-
})
|
|
66914
|
-
).then((body) => sendJson(res, 201, body)).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
|
|
66992
|
+
if (req.method === "POST" && url.pathname === "/api/preview") {
|
|
66993
|
+
readBody(req).then((data) => sendJson(res, 200, previewPayload(String(data.source ?? "")))).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
|
|
66994
|
+
return;
|
|
66995
|
+
}
|
|
66996
|
+
if (req.method === "POST" && url.pathname === "/api/edit-text") {
|
|
66997
|
+
readBody(req).then((data) => {
|
|
66998
|
+
const d = data;
|
|
66999
|
+
sendJson(res, 200, { source: applyTextEdits(String(d.source ?? ""), Array.isArray(d.edits) ? d.edits : []) });
|
|
67000
|
+
}).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
|
|
66915
67001
|
return;
|
|
66916
67002
|
}
|
|
66917
67003
|
if (req.method === "POST" && url.pathname === "/api/mv") {
|
|
@@ -66959,20 +67045,6 @@ function createHandlers(dataRoot, opts = {}) {
|
|
|
66959
67045
|
sendJson(res, 200, { source, settings, path: ":.yamlover:settings.yamlover" });
|
|
66960
67046
|
return;
|
|
66961
67047
|
}
|
|
66962
|
-
if (req.method === "POST" && url.pathname === "/api/config") {
|
|
66963
|
-
readBody(req).then(
|
|
66964
|
-
(data) => enqueue(async () => {
|
|
66965
|
-
const source = String(data?.source ?? "");
|
|
66966
|
-
parseYamlover(source, settingsFile);
|
|
66967
|
-
fs10.mkdirSync(path10.dirname(settingsFile), { recursive: true });
|
|
66968
|
-
fs10.writeFileSync(settingsFile, source);
|
|
66969
|
-
settings = loadSettings(dataRoot);
|
|
66970
|
-
broadcast(await doReindexFile(settingsFile));
|
|
66971
|
-
return { ok: true, settings };
|
|
66972
|
-
})
|
|
66973
|
-
).then((body) => sendJson(res, 200, body)).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
|
|
66974
|
-
return;
|
|
66975
|
-
}
|
|
66976
67048
|
const segs = strToSegs(url.searchParams.get("path") || ":");
|
|
66977
67049
|
const p2 = storePath(segs);
|
|
66978
67050
|
const depth = parseDepth(url.searchParams.get("depth"));
|
|
@@ -67121,12 +67193,12 @@ var hasSubchapterChild = (s2, p2) => s2.children(p2).some((c3) => {
|
|
|
67121
67193
|
});
|
|
67122
67194
|
function downstreamEntries(s2, p2) {
|
|
67123
67195
|
const isSet = !!s2.node(p2)?.meta?.set;
|
|
67124
|
-
let own = s2
|
|
67125
|
-
const seen = new Set(own.map((e3) => relKey(e3.label, e3.to)));
|
|
67196
|
+
let own = ownedEntries(s2, p2).filter((e3) => !(e3.kind === "contain" && isHidden(s2, e3.to)));
|
|
67197
|
+
const seen = new Set(own.map((e3) => relKey(e3.label, e3.to || e3.raw || "")));
|
|
67126
67198
|
if (isSet) {
|
|
67127
67199
|
const kept = /* @__PURE__ */ new Set();
|
|
67128
67200
|
own = own.filter((e3) => {
|
|
67129
|
-
const k = relKey(e3.label, e3.to);
|
|
67201
|
+
const k = relKey(e3.label, e3.to || e3.raw || "");
|
|
67130
67202
|
if (kept.has(k)) return false;
|
|
67131
67203
|
kept.add(k);
|
|
67132
67204
|
return true;
|
|
@@ -67155,6 +67227,7 @@ function projectValue(dataRoot, s2, segs, depth, top) {
|
|
|
67155
67227
|
const currentDoc = documentRootSegs(s2, segs);
|
|
67156
67228
|
const project = (c3) => {
|
|
67157
67229
|
if (c3.kind === "contain") return projectValue(dataRoot, s2, [...segs, c3.label ?? c3.pos ?? 0], depth - 1, false);
|
|
67230
|
+
if (!c3.to) return refMarker(c3.raw ?? "", null);
|
|
67158
67231
|
const targetSegs = storePathToSegs(c3.to);
|
|
67159
67232
|
return depth === Infinity ? refMarker(refPointerText(s2, targetSegs, currentDoc), segsToStr(targetSegs)) : linkMarker(dataRoot, s2, targetSegs);
|
|
67160
67233
|
};
|
|
@@ -67192,8 +67265,25 @@ function irNodeAt(doc, segs) {
|
|
|
67192
67265
|
}
|
|
67193
67266
|
return node;
|
|
67194
67267
|
}
|
|
67268
|
+
function scalarRawToken(node) {
|
|
67269
|
+
if (isPointer(node) || node.kind !== "scalar") return void 0;
|
|
67270
|
+
const raw = node.raw;
|
|
67271
|
+
if (raw == null || raw.includes("\n")) return void 0;
|
|
67272
|
+
const v = node.value;
|
|
67273
|
+
if (typeof v === "string" && v.includes("\n")) return void 0;
|
|
67274
|
+
const plain = v === null ? "null" : String(v);
|
|
67275
|
+
return raw === plain ? void 0 : raw;
|
|
67276
|
+
}
|
|
67195
67277
|
function tagOf(n2) {
|
|
67196
|
-
|
|
67278
|
+
const parts = [];
|
|
67279
|
+
if (n2.meta?.schema !== void 0) {
|
|
67280
|
+
try {
|
|
67281
|
+
parts.push(schemaTagToken(n2.meta.schema));
|
|
67282
|
+
} catch {
|
|
67283
|
+
}
|
|
67284
|
+
}
|
|
67285
|
+
if (n2.meta?.set) parts.push("!!set");
|
|
67286
|
+
return parts.length ? parts.join(" ") : void 0;
|
|
67197
67287
|
}
|
|
67198
67288
|
function nodeDeco(bucket, node) {
|
|
67199
67289
|
const anchors = (node.meta?.anchors ?? []).map(anchorBody);
|
|
@@ -67210,7 +67300,9 @@ function collectComments(doc, segs, depth) {
|
|
|
67210
67300
|
{
|
|
67211
67301
|
const self2 = {};
|
|
67212
67302
|
nodeDeco(self2, root);
|
|
67213
|
-
|
|
67303
|
+
const raw = scalarRawToken(root);
|
|
67304
|
+
if (raw) self2.raw = raw;
|
|
67305
|
+
if (self2.anchors || self2.tag || self2.valueTrailing || self2.raw) out[""] = self2;
|
|
67214
67306
|
}
|
|
67215
67307
|
const head = (root.meta?.head ?? []).map((c3) => c3.text);
|
|
67216
67308
|
if (head.length > 0) out.$head = head;
|
|
@@ -67233,7 +67325,11 @@ function collectComments(doc, segs, depth) {
|
|
|
67233
67325
|
const leadComment = e3.meta?.comments?.find((c3) => c3.placement === "leading");
|
|
67234
67326
|
if (e3.meta?.blankBefore || leadComment?.blankBefore) bucket.blankBefore = true;
|
|
67235
67327
|
if (isPointer(e3.value)) bucket.pointer = renderPointer(e3.value);
|
|
67236
|
-
else
|
|
67328
|
+
else {
|
|
67329
|
+
nodeDeco(bucket, e3.value);
|
|
67330
|
+
const raw = scalarRawToken(e3.value);
|
|
67331
|
+
if (raw) bucket.raw = raw;
|
|
67332
|
+
}
|
|
67237
67333
|
if (Object.keys(bucket).length > 0) out[rel + cont] = bucket;
|
|
67238
67334
|
if (e3.edge === "contain" && !isPointer(e3.value)) walk(e3.value, rel + cont, d - 1, false);
|
|
67239
67335
|
}
|
|
@@ -67250,7 +67346,7 @@ function projectSchema(dataRoot, s2, segs, depth, top) {
|
|
|
67250
67346
|
const schema = { type: typeName(s2, p2, row) };
|
|
67251
67347
|
if (row.format) schema.format = row.format;
|
|
67252
67348
|
const kids = downstreamEntries(s2, p2);
|
|
67253
|
-
const sub = (c3) => c3.kind === "contain" ? projectSchema(dataRoot, s2, [...segs, c3.label ?? c3.pos ?? 0], depth - 1, false) : linkMarker(dataRoot, s2, storePathToSegs(c3.to));
|
|
67349
|
+
const sub = (c3) => c3.kind === "contain" ? projectSchema(dataRoot, s2, [...segs, c3.label ?? c3.pos ?? 0], depth - 1, false) : c3.to ? linkMarker(dataRoot, s2, storePathToSegs(c3.to)) : refMarker(c3.raw ?? "", null);
|
|
67254
67350
|
if (k === "object" || k === "mix" || k === "omni") {
|
|
67255
67351
|
const props = {};
|
|
67256
67352
|
for (const c3 of kids) props[c3.label ?? `[${c3.pos}]`] = sub(c3);
|
|
@@ -67282,7 +67378,9 @@ function linkMarker(dataRoot, s2, segs) {
|
|
|
67282
67378
|
else if (k === "omni" || k === "mix") {
|
|
67283
67379
|
info.count = ownedEntries(s2, p2).length;
|
|
67284
67380
|
if (k === "omni") info.value = wireScalar(row.value);
|
|
67285
|
-
} else
|
|
67381
|
+
} else {
|
|
67382
|
+
info.count = ownedEntries(s2, p2).filter((e3) => !(e3.kind === "contain" && isHidden(s2, e3.to))).length;
|
|
67383
|
+
}
|
|
67286
67384
|
if (row.format === TAG_FORMAT) {
|
|
67287
67385
|
const c3 = s2.node(p2 + ":color")?.value;
|
|
67288
67386
|
if (typeof c3 === "string") info.color = c3;
|
|
@@ -67694,13 +67792,13 @@ function handlePaste(dataRoot, s2, input) {
|
|
|
67694
67792
|
const bytes = Buffer.from(input.contentBase64 || "", "base64");
|
|
67695
67793
|
if (bytes.length === 0) throw new Error("empty paste (no file bytes)");
|
|
67696
67794
|
const name = sanitizeName(input.filename ?? "");
|
|
67697
|
-
if (row.format === "x-yamlover-chapter") return pasteIntoChapter(dataRoot, s2, segs, name, bytes);
|
|
67795
|
+
if (row.format === "x-yamlover-chapter" && !input.inline) return pasteIntoChapter(dataRoot, s2, segs, name, bytes);
|
|
67698
67796
|
const dirSegs = nearestDirSegs(dataRoot, segs);
|
|
67699
67797
|
if (!dirSegs) throw new Error("no enclosing directory to paste into");
|
|
67700
67798
|
const dir = path10.resolve(dataRoot, ...dirSegs.map(String));
|
|
67701
67799
|
const final = uniqueName(dir, name);
|
|
67702
67800
|
writeInside(dataRoot, dir, final, bytes);
|
|
67703
|
-
return { path: segsToStr([...dirSegs, final]), dir: segsToStr(dirSegs), open: dirSegs.length !== segs.length };
|
|
67801
|
+
return { path: segsToStr([...dirSegs, final]), dir: segsToStr(dirSegs), open: !input.inline && dirSegs.length !== segs.length };
|
|
67704
67802
|
}
|
|
67705
67803
|
function nearestDirSegs(dataRoot, segs) {
|
|
67706
67804
|
for (let i2 = segs.length; i2 >= 0; i2--) {
|
|
@@ -67710,16 +67808,24 @@ function nearestDirSegs(dataRoot, segs) {
|
|
|
67710
67808
|
}
|
|
67711
67809
|
return null;
|
|
67712
67810
|
}
|
|
67713
|
-
|
|
67811
|
+
var YAMLOVER_ONLY = /\.yamlover$/i;
|
|
67812
|
+
var BLOCK_YAML = /\.(ya?ml|yamlover)$/i;
|
|
67813
|
+
var JSON_FILE = /\.(json|json5|json5p)$/i;
|
|
67814
|
+
function resolveBacking(dataRoot, s2, segs) {
|
|
67714
67815
|
const docSegs = documentRootSegs(s2, segs);
|
|
67715
67816
|
const docFs = path10.resolve(dataRoot, ...docSegs.map(String));
|
|
67716
67817
|
const dirBacked = fs10.existsSync(docFs) && fs10.statSync(docFs).isDirectory();
|
|
67717
67818
|
const bodyFile = dirBacked ? path10.join(docFs, ".yamlover", "body.yamlover") : docFs;
|
|
67718
|
-
if (!bodyFile.endsWith(".yamlover") || !fs10.existsSync(bodyFile)) {
|
|
67719
|
-
throw new Error("unsupported chapter source (need a .yamlover body)");
|
|
67720
|
-
}
|
|
67721
67819
|
return { docSegs, bodyFile, dirBacked };
|
|
67722
67820
|
}
|
|
67821
|
+
function chapterSource(dataRoot, s2, segs, allow = YAMLOVER_ONLY) {
|
|
67822
|
+
const r2 = resolveBacking(dataRoot, s2, segs);
|
|
67823
|
+
const okExt = r2.dirBacked ? r2.bodyFile.endsWith(".yamlover") : allow.test(r2.bodyFile);
|
|
67824
|
+
if (!okExt || !fs10.existsSync(r2.bodyFile)) {
|
|
67825
|
+
throw new Error("unsupported edit source (need a .yamlover / .yaml / .yml body)");
|
|
67826
|
+
}
|
|
67827
|
+
return r2;
|
|
67828
|
+
}
|
|
67723
67829
|
function pasteIntoChapter(dataRoot, s2, segs, name, bytes) {
|
|
67724
67830
|
const { docSegs, bodyFile, dirBacked } = chapterSource(dataRoot, s2, segs);
|
|
67725
67831
|
const writeDirSegs = dirBacked ? docSegs : docSegs.slice(0, -1);
|
|
@@ -67850,32 +67956,11 @@ function titleFromText(text) {
|
|
|
67850
67956
|
const t3 = first.replace(/^#{1,6}\s+/, "").trim();
|
|
67851
67957
|
return (t3.length > 80 ? t3.slice(0, 79).trimEnd() + "\u2026" : t3) || "Pasted text";
|
|
67852
67958
|
}
|
|
67853
|
-
var CREATABLE = {
|
|
67854
|
-
"::yamlover:$defs:chapter": {
|
|
67855
|
-
tag: "*::yamlover:$defs:chapter",
|
|
67856
|
-
childOf: ["x-yamlover-chapter", "x-yamlover-task"],
|
|
67857
|
-
// a chapter with one empty prose chunk (a positional body item), so it is immediately editable
|
|
67858
|
-
body: (title) => [`title: ${JSON.stringify(title)}`, `- ""`]
|
|
67859
|
-
}
|
|
67860
|
-
};
|
|
67861
67959
|
function lastBodyChildPath(s2, parentSegs) {
|
|
67862
67960
|
const positional = s2.entries(storePath(parentSegs)).filter((e3) => e3.kind === "contain" && e3.label == null);
|
|
67863
67961
|
const last = positional[positional.length - 1];
|
|
67864
67962
|
return last ? segsToStr(storePathToSegs(last.to)) : segsToStr([...parentSegs, 0]);
|
|
67865
67963
|
}
|
|
67866
|
-
function defaultTitle(schema) {
|
|
67867
|
-
const segs = strToSegs(schema);
|
|
67868
|
-
return "New " + String(segs[segs.length - 1] ?? "object");
|
|
67869
|
-
}
|
|
67870
|
-
function objectFileSource(tag, body) {
|
|
67871
|
-
return `!!<${tag}>
|
|
67872
|
-
${body.join("\n")}
|
|
67873
|
-
`;
|
|
67874
|
-
}
|
|
67875
|
-
function inlineChildLines(body, indent) {
|
|
67876
|
-
const pad = " ".repeat(indent);
|
|
67877
|
-
return body.map((line, i2) => i2 === 0 ? `${pad}- ${line}` : `${pad} ${line}`);
|
|
67878
|
-
}
|
|
67879
67964
|
function objectBaseName(title) {
|
|
67880
67965
|
const base = title.replace(/[^\p{L}\p{N} ._-]+/gu, " ").replace(/\s+/g, " ").trim().slice(0, 60).trim().replace(/^\.+/, "");
|
|
67881
67966
|
return base || "new";
|
|
@@ -67952,19 +68037,29 @@ var isContentLine2 = (line) => {
|
|
|
67952
68037
|
const t3 = line.trim();
|
|
67953
68038
|
return t3.length > 0 && !t3.startsWith("#");
|
|
67954
68039
|
};
|
|
67955
|
-
function
|
|
67956
|
-
const pad = " ".repeat(indent);
|
|
68040
|
+
function escapeScalarSrc(text) {
|
|
67957
68041
|
const first = text.split("\n").find((l2) => l2.trim().length > 0);
|
|
67958
|
-
if (!first || /^\s/.test(first)) return
|
|
68042
|
+
if (!first || /^\s/.test(first)) return JSON.stringify(text);
|
|
67959
68043
|
const body = text.endsWith("\n") ? text.slice(0, -1) : text;
|
|
67960
68044
|
const head = text.endsWith("\n") ? "|" : "|-";
|
|
67961
|
-
return [
|
|
68045
|
+
return [head, ...body.split("\n").map((l2) => l2.trim().length ? " " + l2 : "")].join("\n");
|
|
68046
|
+
}
|
|
68047
|
+
function renderEntry(valueSrc, indent, marker, tag, deeper = false) {
|
|
68048
|
+
const pad = " ".repeat(indent + (deeper ? 2 : 0));
|
|
68049
|
+
const [first, ...rest] = valueSrc.split("\n");
|
|
68050
|
+
return [`${" ".repeat(indent)}${marker}${tag ? tag + " " : ""}${first}`, ...rest.map((l2) => l2.trim().length ? pad + l2 : "")];
|
|
68051
|
+
}
|
|
68052
|
+
function textChunkLines(text, indent) {
|
|
68053
|
+
return renderEntry(escapeScalarSrc(text), indent, "- ");
|
|
67962
68054
|
}
|
|
67963
68055
|
function chapterEntries(lines, r2) {
|
|
67964
68056
|
const starts = [];
|
|
67965
68057
|
if (r2.marker >= 0) {
|
|
67966
|
-
const
|
|
67967
|
-
if (
|
|
68058
|
+
const raw = lines[r2.marker].replace(/^\s*/, "");
|
|
68059
|
+
if (raw === "-" || raw.startsWith("- ")) {
|
|
68060
|
+
const inline = raw.replace(/^-\s*/, "");
|
|
68061
|
+
if (inline.trim()) starts.push({ key: /^-/.test(inline) ? null : inline.match(/^([^:\s]+):/)?.[1] ?? null, start: r2.marker, inline: true });
|
|
68062
|
+
}
|
|
67968
68063
|
}
|
|
67969
68064
|
for (let i2 = r2.lo; i2 < r2.hi; i2++) {
|
|
67970
68065
|
if (!isContentLine2(lines[i2])) continue;
|
|
@@ -67983,16 +68078,37 @@ function chapterEntries(lines, r2) {
|
|
|
67983
68078
|
inline: s2.inline
|
|
67984
68079
|
}));
|
|
67985
68080
|
}
|
|
67986
|
-
function
|
|
67987
|
-
|
|
68081
|
+
function findEntry(lines, r2, seg) {
|
|
68082
|
+
const entries = chapterEntries(lines, r2);
|
|
68083
|
+
return typeof seg === "number" ? entries[seg] : entries.find((e3) => e3.key === seg);
|
|
68084
|
+
}
|
|
68085
|
+
function entryHead(lines, e3) {
|
|
68086
|
+
let t3 = lines[e3.start].trim().replace(/^-\s*/, "").replace(/^!!<[^>]*>\s*/, "");
|
|
68087
|
+
if (e3.key) t3 = t3.slice(t3.indexOf(":") + 1).trim();
|
|
68088
|
+
return t3;
|
|
68089
|
+
}
|
|
68090
|
+
function isContainerEntry(lines, e3, childIndent) {
|
|
68091
|
+
const head = entryHead(lines, e3);
|
|
68092
|
+
if (/^[|>][+-]?\d*$/.test(head.trim())) return itemHasFields(lines, e3, childIndent);
|
|
68093
|
+
const bare = head.replace(/\s+#.*$/, "");
|
|
68094
|
+
if (/^[^\s"'*|>#-][^:]*:(\s|$)/.test(bare)) return true;
|
|
68095
|
+
for (let i2 = e3.start + 1; i2 < e3.end; i2++) {
|
|
68096
|
+
if (!isContentLine2(lines[i2])) continue;
|
|
68097
|
+
const ind = indentOf2(lines[i2]);
|
|
68098
|
+
if (ind < childIndent) break;
|
|
68099
|
+
if (ind === childIndent) return true;
|
|
68100
|
+
}
|
|
68101
|
+
return false;
|
|
67988
68102
|
}
|
|
67989
|
-
function reachChapter(lines,
|
|
68103
|
+
function reachChapter(lines, within) {
|
|
67990
68104
|
let r2 = { lo: 0, hi: lines.length, indent: firstContentIndent2(lines), marker: -1 };
|
|
67991
|
-
for (const seg of
|
|
67992
|
-
const
|
|
67993
|
-
|
|
67994
|
-
if (!
|
|
67995
|
-
|
|
68105
|
+
for (const seg of within) {
|
|
68106
|
+
const entry = findEntry(lines, r2, seg);
|
|
68107
|
+
if (!entry) throw new Error(`no entry at ${typeof seg === "number" ? `[${seg}]` : seg}`);
|
|
68108
|
+
if (!isContainerEntry(lines, entry, r2.indent + 2)) {
|
|
68109
|
+
throw new Error(`cannot descend into a scalar element at ${typeof seg === "number" ? `[${seg}]` : seg}`);
|
|
68110
|
+
}
|
|
68111
|
+
r2 = { lo: entry.start + 1, hi: entry.end, indent: r2.indent + 2, marker: entry.start };
|
|
67996
68112
|
}
|
|
67997
68113
|
return r2;
|
|
67998
68114
|
}
|
|
@@ -68009,60 +68125,106 @@ function appendBody(text, chapterPath, renderItems) {
|
|
|
68009
68125
|
lines.splice(bodyAppendPoint(lines, r2), 0, ...renderItems(r2.indent));
|
|
68010
68126
|
return lines.join("\n");
|
|
68011
68127
|
}
|
|
68012
|
-
|
|
68013
|
-
|
|
68014
|
-
|
|
68015
|
-
|
|
68128
|
+
var opensEntry = (t3) => t3 === "-" || t3.startsWith("- ") || /^[^\s"'*|>#-][^:]*:(\s|$)/.test(t3);
|
|
68129
|
+
var isBlockHeader = (head) => /^[|>][+-]?\d*$/.test(head.trim());
|
|
68130
|
+
function groupEntries(lines, at) {
|
|
68131
|
+
const starts = lines.map((l2, i2) => i2).filter((i2) => isContentLine2(lines[i2]) && indentOf2(lines[i2]) === at);
|
|
68132
|
+
const keyed = [];
|
|
68133
|
+
const ordinal = [];
|
|
68134
|
+
starts.forEach((s2, k) => {
|
|
68135
|
+
const group = lines.slice(s2, k + 1 < starts.length ? starts[k + 1] : lines.length).map((l2) => l2.slice(at));
|
|
68136
|
+
(lines[s2].trim() === "-" || lines[s2].trim().startsWith("- ") ? ordinal : keyed).push(group);
|
|
68137
|
+
});
|
|
68138
|
+
return { keyed, ordinal };
|
|
68139
|
+
}
|
|
68140
|
+
function payloadFacets(src) {
|
|
68141
|
+
const lines = src.split("\n");
|
|
68142
|
+
const first = lines.find(isContentLine2);
|
|
68143
|
+
if (first === void 0) return { keyed: [], ordinal: [] };
|
|
68144
|
+
if (!opensEntry(first.trim())) return { scalar: src, keyed: [], ordinal: [] };
|
|
68145
|
+
return { scalar: void 0, ...groupEntries(lines, 0) };
|
|
68146
|
+
}
|
|
68147
|
+
function entryFacets(lines, e3, indent) {
|
|
68148
|
+
const marked = lines[e3.start].trim().replace(/^-\s*/, "");
|
|
68149
|
+
const tag = marked.match(/^(!!<[^>]*>)/)?.[1];
|
|
68150
|
+
const head = entryHead(lines, e3);
|
|
68151
|
+
const childIndent = indent + 2;
|
|
68152
|
+
const value = (from, to2, at) => [head, ...lines.slice(from, to2).map((l2) => l2.trim().length ? " " + l2.slice(at) : "")].join("\n").replace(/\n+$/, "");
|
|
68153
|
+
if (!isContainerEntry(lines, e3, childIndent)) {
|
|
68154
|
+
return { tag, scalar: value(e3.start + 1, e3.end, childIndent), keyed: [], ordinal: [] };
|
|
68155
|
+
}
|
|
68156
|
+
const blockValue = isBlockHeader(head);
|
|
68157
|
+
let firstChild = e3.end;
|
|
68158
|
+
for (let i2 = e3.start + 1; i2 < e3.end; i2++) {
|
|
68159
|
+
if (isContentLine2(lines[i2]) && indentOf2(lines[i2]) === childIndent) {
|
|
68160
|
+
firstChild = i2;
|
|
68161
|
+
break;
|
|
68162
|
+
}
|
|
68163
|
+
}
|
|
68164
|
+
const scalar2 = blockValue ? value(e3.start + 1, firstChild, childIndent + 2) : void 0;
|
|
68165
|
+
const groups = groupEntries(lines.slice(firstChild, e3.end), childIndent);
|
|
68166
|
+
if (!blockValue && head) groups.keyed.unshift([head]);
|
|
68167
|
+
return { tag, scalar: scalar2, ...groups };
|
|
68016
68168
|
}
|
|
68017
|
-
function
|
|
68018
|
-
const
|
|
68019
|
-
|
|
68020
|
-
|
|
68021
|
-
|
|
68169
|
+
function renderNode(f2, indent, marker, tag) {
|
|
68170
|
+
const pad = " ".repeat(indent);
|
|
68171
|
+
const childPad = " ".repeat(indent + 2);
|
|
68172
|
+
const groups = [...f2.keyed, ...f2.ordinal];
|
|
68173
|
+
const child = (g) => g.map((l2) => l2.trim().length ? childPad + l2 : "");
|
|
68174
|
+
if (f2.scalar !== void 0) {
|
|
68175
|
+
return [...renderEntry(f2.scalar, indent, marker, tag, groups.length > 0), ...groups.flatMap(child)];
|
|
68176
|
+
}
|
|
68177
|
+
if (!groups.length) return [`${pad}${marker.trimEnd()}${tag ? " " + tag : ""}`];
|
|
68178
|
+
if (marker.startsWith("-") && !tag) {
|
|
68179
|
+
const [g0, ...rest] = groups;
|
|
68180
|
+
return [`${pad}${marker}${g0[0]}`, ...child(g0.slice(1)), ...rest.flatMap(child)];
|
|
68181
|
+
}
|
|
68182
|
+
return [`${pad}${marker.trimEnd()}${tag ? " " + tag : ""}`, ...groups.flatMap(child)];
|
|
68183
|
+
}
|
|
68184
|
+
function metaTag(meta, existing, preserve) {
|
|
68185
|
+
if (meta === null) return void 0;
|
|
68186
|
+
if (meta !== void 0) return `!!<${meta}>`;
|
|
68187
|
+
return preserve ? existing : void 0;
|
|
68188
|
+
}
|
|
68189
|
+
function assignAt(lines, r2, seg, op, valueSrc, meta) {
|
|
68190
|
+
const marker = (s2) => typeof s2 === "string" ? `${s2}: ` : "- ";
|
|
68191
|
+
if (op === "insert") {
|
|
68192
|
+
if (typeof seg === "string") throw new Error("`insert` needs a positional target (a path ending `[i]`, or the node itself)");
|
|
68193
|
+
const entry2 = seg === void 0 ? void 0 : findEntry(lines, r2, seg);
|
|
68194
|
+
const at = entry2 ? entry2.start : bodyAppendPoint(lines, r2);
|
|
68195
|
+
lines.splice(at, 0, ...renderNode(payloadFacets(valueSrc), r2.indent, "- ", metaTag(meta, void 0, false)));
|
|
68022
68196
|
return;
|
|
68023
68197
|
}
|
|
68024
|
-
|
|
68025
|
-
|
|
68026
|
-
|
|
68198
|
+
if (seg === void 0) throw new Error(`\`${op}\` needs a key or index target`);
|
|
68199
|
+
const entry = findEntry(lines, r2, seg);
|
|
68200
|
+
if (op === "remove") {
|
|
68201
|
+
if (!entry) throw new Error(`no entry at ${typeof seg === "number" ? `[${seg}]` : seg}`);
|
|
68202
|
+
lines.splice(entry.start, entry.end - entry.start);
|
|
68027
68203
|
return;
|
|
68028
68204
|
}
|
|
68029
|
-
|
|
68030
|
-
if (entry)
|
|
68031
|
-
|
|
68032
|
-
|
|
68033
|
-
|
|
68034
|
-
|
|
68035
|
-
|
|
68036
|
-
|
|
68037
|
-
const
|
|
68038
|
-
const
|
|
68039
|
-
const
|
|
68040
|
-
|
|
68041
|
-
|
|
68042
|
-
|
|
68043
|
-
|
|
68044
|
-
|
|
68045
|
-
|
|
68046
|
-
|
|
68047
|
-
|
|
68048
|
-
|
|
68049
|
-
|
|
68050
|
-
|
|
68051
|
-
lines.splice(start, end - start);
|
|
68052
|
-
}
|
|
68053
|
-
function taggedChunkLines(text, indent, tag) {
|
|
68054
|
-
const pad = " ".repeat(indent);
|
|
68055
|
-
const first = text.split("\n").find((l2) => l2.trim().length > 0);
|
|
68056
|
-
if (!first || /^\s/.test(first)) return [`${pad}- ${tag} ${JSON.stringify(text)}`];
|
|
68057
|
-
const body = text.endsWith("\n") ? text.slice(0, -1) : text;
|
|
68058
|
-
const head = text.endsWith("\n") ? "|" : "|-";
|
|
68059
|
-
return [`${pad}- ${tag} ${head}`, ...body.split("\n").map((l2) => l2.trim().length ? `${pad} ${l2}` : "")];
|
|
68060
|
-
}
|
|
68061
|
-
function assertProseBodyItem(lines, r2, rank) {
|
|
68062
|
-
const head = bodyItemHead(lines, r2, rank);
|
|
68063
|
-
if (head.startsWith("*")) throw new Error("cannot edit a file/pointer chunk as text");
|
|
68064
|
-
const tag = head.match(/^!!<([^>]*)>/)?.[1];
|
|
68065
|
-
if (tag && !/text\/(markdown|marklower|x-latex)/.test(tag)) throw new Error("cannot edit a non-text chunk as text");
|
|
68205
|
+
if (op !== "emplace" && op !== "replace") throw new Error(`unknown edit op: ${op}`);
|
|
68206
|
+
if (!entry) {
|
|
68207
|
+
if (op === "replace") throw new Error(`no entry at ${typeof seg === "number" ? `[${seg}]` : seg}`);
|
|
68208
|
+
const rendered = renderNode(payloadFacets(valueSrc), r2.indent, marker(seg), metaTag(meta, void 0, false));
|
|
68209
|
+
const at = typeof seg === "string" ? r2.marker >= 0 ? r2.marker + 1 : trimBack2(lines, r2.lo - 1, r2.hi) : bodyAppendPoint(lines, r2);
|
|
68210
|
+
lines.splice(at, 0, ...rendered);
|
|
68211
|
+
return;
|
|
68212
|
+
}
|
|
68213
|
+
const had = entryFacets(lines, entry, r2.indent);
|
|
68214
|
+
const payload = payloadFacets(valueSrc);
|
|
68215
|
+
const inlineKey = entry.inline ? entry.key : null;
|
|
68216
|
+
const next = op === "replace" ? payload : {
|
|
68217
|
+
scalar: payload.scalar ?? had.scalar,
|
|
68218
|
+
keyed: payload.keyed.length ? payload.keyed : had.keyed,
|
|
68219
|
+
ordinal: payload.ordinal.length ? payload.ordinal : had.ordinal
|
|
68220
|
+
};
|
|
68221
|
+
const tag = metaTag(meta, had.tag, op === "emplace");
|
|
68222
|
+
if (inlineKey) {
|
|
68223
|
+
const pad = " ".repeat(indentOf2(lines[entry.start]));
|
|
68224
|
+
lines[entry.start] = `${pad}- ${tag ? tag + " " : ""}${inlineKey}: ${next.scalar ?? '""'}`;
|
|
68225
|
+
return;
|
|
68226
|
+
}
|
|
68227
|
+
lines.splice(entry.start, entry.end - entry.start, ...renderNode(next, r2.indent, marker(seg), tag));
|
|
68066
68228
|
}
|
|
68067
68229
|
function reachChapterItem(lines, indices) {
|
|
68068
68230
|
const parent = reachChapter(lines, indices.slice(0, -1));
|
|
@@ -68125,49 +68287,210 @@ function splitChunkWithin(within) {
|
|
|
68125
68287
|
while (i2 < within.length && typeof within[i2] === "number") i2++;
|
|
68126
68288
|
return { indices: within.slice(0, i2).map(Number), keys: within.slice(i2).map(String) };
|
|
68127
68289
|
}
|
|
68128
|
-
function
|
|
68129
|
-
const
|
|
68130
|
-
|
|
68131
|
-
|
|
68132
|
-
if (
|
|
68133
|
-
|
|
68134
|
-
return lines.join("\n");
|
|
68290
|
+
function setRootTag(lines, meta) {
|
|
68291
|
+
const at = lines.findIndex(isContentLine2);
|
|
68292
|
+
const existing = at >= 0 && lines[at].trim().startsWith("!!<") ? at : -1;
|
|
68293
|
+
if (meta === null) {
|
|
68294
|
+
if (existing >= 0) lines.splice(existing, 1);
|
|
68295
|
+
return;
|
|
68135
68296
|
}
|
|
68136
|
-
if (
|
|
68137
|
-
|
|
68138
|
-
|
|
68139
|
-
|
|
68140
|
-
const
|
|
68141
|
-
if (
|
|
68142
|
-
|
|
68143
|
-
|
|
68144
|
-
|
|
68145
|
-
|
|
68146
|
-
|
|
68147
|
-
|
|
68148
|
-
|
|
68149
|
-
|
|
68297
|
+
if (existing >= 0) lines[existing] = `!!<${meta}>`;
|
|
68298
|
+
else lines.splice(Math.max(at, 0), 0, `!!<${meta}>`);
|
|
68299
|
+
}
|
|
68300
|
+
function editChapterSource(src, within, op, valueSrc, meta) {
|
|
68301
|
+
const lines = src.split("\n");
|
|
68302
|
+
if (within.length === 0) {
|
|
68303
|
+
if (op === "insert") {
|
|
68304
|
+
assignAt(lines, reachChapter(lines, []), void 0, op, valueSrc, meta);
|
|
68305
|
+
return lines.join("\n");
|
|
68306
|
+
}
|
|
68307
|
+
if (op === "emplace" && meta !== void 0 && !valueSrc) {
|
|
68308
|
+
setRootTag(lines, meta);
|
|
68309
|
+
return lines.join("\n");
|
|
68310
|
+
}
|
|
68311
|
+
throw new Error(`\`${op}\` at a document root needs a key or index target`);
|
|
68150
68312
|
}
|
|
68313
|
+
assignAt(lines, reachChapter(lines, within.slice(0, -1)), within[within.length - 1], op, valueSrc, meta);
|
|
68151
68314
|
return lines.join("\n");
|
|
68152
68315
|
}
|
|
68316
|
+
function jsonValueSpan(src, es, ee) {
|
|
68317
|
+
const last = src[ee - 1];
|
|
68318
|
+
if (last === '"' || last === "'") {
|
|
68319
|
+
for (let j2 = ee - 2; j2 >= es; j2--) {
|
|
68320
|
+
if (src[j2] !== last) continue;
|
|
68321
|
+
let bs = 0;
|
|
68322
|
+
for (let k = j2 - 1; k >= es && src[k] === "\\"; k--) bs++;
|
|
68323
|
+
if (bs % 2 === 0) return [j2, ee];
|
|
68324
|
+
}
|
|
68325
|
+
throw new Error("could not locate the string value in the source");
|
|
68326
|
+
}
|
|
68327
|
+
let j = ee;
|
|
68328
|
+
while (j > es && !/[\s,:{}[\]]/.test(src[j - 1])) j--;
|
|
68329
|
+
return [j, ee];
|
|
68330
|
+
}
|
|
68331
|
+
function yamloverScalarToJsonToken(valueSrc) {
|
|
68332
|
+
const root = parseYamlover(valueSrc, "<edit>").root;
|
|
68333
|
+
if (root.kind !== "scalar") throw new Error("only a scalar value is editable in a JSON file");
|
|
68334
|
+
const v = root.value;
|
|
68335
|
+
if (v === null) return "null";
|
|
68336
|
+
if (typeof v === "boolean") return v ? "true" : "false";
|
|
68337
|
+
if (typeof v === "number") return /^[-+]?(\d+\.?\d*|\.\d+)([eE][-+]?\d+)?$/.test(root.raw) ? root.raw : String(v);
|
|
68338
|
+
return JSON.stringify(v);
|
|
68339
|
+
}
|
|
68340
|
+
function editJsonScalar(src, within, token) {
|
|
68341
|
+
if (within.length === 0) throw new Error("cannot edit the JSON document root as a scalar value");
|
|
68342
|
+
let node = parseJson5p(src, "<edit>").root;
|
|
68343
|
+
for (let k = 0; k < within.length; k++) {
|
|
68344
|
+
const seg = within[k];
|
|
68345
|
+
const entries = node.entries ?? [];
|
|
68346
|
+
const entry = typeof seg === "number" ? entries.filter((e3) => e3.edge === "contain" && e3.key === null)[seg] : entries.find((e3) => e3.edge === "contain" && e3.key === seg);
|
|
68347
|
+
if (!entry) throw new Error(`no entry at ${typeof seg === "number" ? `[${seg}]` : seg}`);
|
|
68348
|
+
const value = entry.value;
|
|
68349
|
+
if (k === within.length - 1) {
|
|
68350
|
+
if (isPointer(value) || value.kind !== "scalar") throw new Error("only a scalar value is editable in a JSON file");
|
|
68351
|
+
const span = entry.meta?.span;
|
|
68352
|
+
if (!span) throw new Error("no source span for the target value");
|
|
68353
|
+
const [vs, ve] = jsonValueSpan(src, span.start, span.end);
|
|
68354
|
+
return src.slice(0, vs) + token + src.slice(ve);
|
|
68355
|
+
}
|
|
68356
|
+
if (isPointer(value) || value.kind !== "mapping") throw new Error(`cannot descend into a non-container at ${typeof seg === "number" ? `[${seg}]` : seg}`);
|
|
68357
|
+
node = value;
|
|
68358
|
+
}
|
|
68359
|
+
throw new Error("empty JSON edit path");
|
|
68360
|
+
}
|
|
68361
|
+
var isPointerValue = (src) => /^\*\S*$/.test(src.trim()) && !src.includes("\n");
|
|
68362
|
+
function isPlainDir(dataRoot, s2, segs) {
|
|
68363
|
+
if (!segs.every((g) => typeof g === "string")) return false;
|
|
68364
|
+
const abs = path10.resolve(dataRoot, ...segs.map(String));
|
|
68365
|
+
if (!fs10.existsSync(abs) || !fs10.statSync(abs).isDirectory()) return false;
|
|
68366
|
+
try {
|
|
68367
|
+
chapterSource(dataRoot, s2, segs);
|
|
68368
|
+
return false;
|
|
68369
|
+
} catch {
|
|
68370
|
+
return true;
|
|
68371
|
+
}
|
|
68372
|
+
}
|
|
68373
|
+
function bornAsDocument(dataRoot, e3, tag) {
|
|
68374
|
+
const writeDirSegs = e3.dirBacked ? e3.docSegs : e3.docSegs.slice(0, -1);
|
|
68375
|
+
const writeDir = path10.resolve(dataRoot, ...writeDirSegs.map(String));
|
|
68376
|
+
const src = [...tag ? [tag] : [], e3.valueSrc, ""].join("\n");
|
|
68377
|
+
const final = writeObject(dataRoot, writeDir, sanitizeName(e3.name || "object"), e3.concrete, src);
|
|
68378
|
+
const targetSegs = [...writeDirSegs, final];
|
|
68379
|
+
return { pointer: e3.dirBacked ? `*/${final}` : `*/${segsToStr(targetSegs)}`, path: segsToStr(targetSegs) };
|
|
68380
|
+
}
|
|
68153
68381
|
function applyEdits2(dataRoot, s2, edits) {
|
|
68154
68382
|
const byFile = /* @__PURE__ */ new Map();
|
|
68383
|
+
const jsonByFile = /* @__PURE__ */ new Map();
|
|
68384
|
+
const appended = [];
|
|
68385
|
+
const created = [];
|
|
68155
68386
|
for (const e3 of edits) {
|
|
68156
68387
|
const editSegs = strToSegs(e3.path ?? "");
|
|
68157
|
-
const
|
|
68158
|
-
|
|
68388
|
+
const op = String(e3.op ?? "");
|
|
68389
|
+
if (op === "insert" && (e3.concrete === "file/yamlover" || e3.concrete === "dir/yamlover") && isPlainDir(dataRoot, s2, editSegs)) {
|
|
68390
|
+
const dir = path10.resolve(dataRoot, ...editSegs.map(String));
|
|
68391
|
+
const src = [...metaTag(e3.meta, void 0, false) ? [metaTag(e3.meta, void 0, false)] : [], String(e3.yamlover ?? ""), ""].join("\n");
|
|
68392
|
+
if (e3.yamlover) parseYamlover(String(e3.yamlover), "<edit>");
|
|
68393
|
+
const final = writeObject(dataRoot, dir, objectBaseName(String(e3.name || "new")), String(e3.concrete), src);
|
|
68394
|
+
created.push(segsToStr([...editSegs, final]));
|
|
68395
|
+
continue;
|
|
68396
|
+
}
|
|
68397
|
+
const backing = resolveBacking(dataRoot, s2, editSegs);
|
|
68398
|
+
if (!backing.dirBacked && JSON_FILE.test(backing.bodyFile)) {
|
|
68399
|
+
if (op !== "emplace") throw new Error("only scalar value edits (emplace) are supported for JSON files");
|
|
68400
|
+
const jlist = jsonByFile.get(backing.bodyFile) ?? [];
|
|
68401
|
+
jlist.push({ within: editSegs.slice(backing.docSegs.length), valueSrc: String(e3.yamlover ?? "") });
|
|
68402
|
+
jsonByFile.set(backing.bodyFile, jlist);
|
|
68403
|
+
continue;
|
|
68404
|
+
}
|
|
68405
|
+
const { docSegs, bodyFile, dirBacked } = chapterSource(dataRoot, s2, editSegs, BLOCK_YAML);
|
|
68406
|
+
if (op === "insert" && !e3.concrete?.includes("/")) {
|
|
68407
|
+
const last = editSegs[editSegs.length - 1];
|
|
68408
|
+
if (typeof last !== "number") appended.push(editSegs);
|
|
68409
|
+
else if (!s2.node(storePath(editSegs))) appended.push(editSegs.slice(0, -1));
|
|
68410
|
+
}
|
|
68411
|
+
const concrete = e3.concrete ? String(e3.concrete) : void 0;
|
|
68412
|
+
if (concrete && concrete !== "yamlover" && op !== "insert" && !(op === "emplace" && !s2.node(storePath(editSegs)))) {
|
|
68413
|
+
throw new Error("`concrete` is only for content being created \u2014 converting an existing node is a move, not an edit");
|
|
68414
|
+
}
|
|
68159
68415
|
const list = byFile.get(bodyFile) ?? [];
|
|
68160
|
-
list.push({
|
|
68416
|
+
list.push({
|
|
68417
|
+
within: editSegs.slice(docSegs.length),
|
|
68418
|
+
op,
|
|
68419
|
+
valueSrc: String(e3.yamlover ?? ""),
|
|
68420
|
+
meta: e3.meta === void 0 ? void 0 : e3.meta === null ? null : String(e3.meta),
|
|
68421
|
+
concrete,
|
|
68422
|
+
name: e3.name ? String(e3.name) : void 0,
|
|
68423
|
+
docSegs,
|
|
68424
|
+
dirBacked
|
|
68425
|
+
});
|
|
68161
68426
|
byFile.set(bodyFile, list);
|
|
68162
68427
|
}
|
|
68163
68428
|
const touched = [];
|
|
68164
68429
|
for (const [bodyFile, ops] of byFile) {
|
|
68165
68430
|
let src = fs10.readFileSync(bodyFile, "utf8");
|
|
68166
|
-
for (const o2 of ops)
|
|
68431
|
+
for (const o2 of ops) {
|
|
68432
|
+
let { valueSrc, meta } = o2;
|
|
68433
|
+
const tag = metaTag(meta, void 0, false);
|
|
68434
|
+
if (valueSrc && !isPointerValue(valueSrc)) parseYamlover(valueSrc, "<edit>");
|
|
68435
|
+
if (o2.concrete === "file/yamlover" || o2.concrete === "dir/yamlover") {
|
|
68436
|
+
const born = bornAsDocument(dataRoot, o2, tag);
|
|
68437
|
+
created.push(born.path);
|
|
68438
|
+
valueSrc = born.pointer;
|
|
68439
|
+
meta = void 0;
|
|
68440
|
+
}
|
|
68441
|
+
src = editChapterSource(src, o2.within, o2.op, valueSrc, meta);
|
|
68442
|
+
}
|
|
68167
68443
|
fs10.writeFileSync(bodyFile, src);
|
|
68168
68444
|
touched.push(bodyFile);
|
|
68169
68445
|
}
|
|
68170
|
-
|
|
68446
|
+
for (const [file, jedits] of jsonByFile) {
|
|
68447
|
+
let src = fs10.readFileSync(file, "utf8");
|
|
68448
|
+
for (const j of jedits) {
|
|
68449
|
+
src = editJsonScalar(src, j.within, yamloverScalarToJsonToken(j.valueSrc));
|
|
68450
|
+
}
|
|
68451
|
+
fs10.writeFileSync(file, src);
|
|
68452
|
+
touched.push(file);
|
|
68453
|
+
}
|
|
68454
|
+
return { touched, created, appended };
|
|
68455
|
+
}
|
|
68456
|
+
var PREVIEW_ROOT = path10.join(os.tmpdir(), ".yamlover-preview-nonexistent");
|
|
68457
|
+
function previewPayload(source) {
|
|
68458
|
+
const doc = parseYamlover(source, "<preview>");
|
|
68459
|
+
doc.root.meta = { ...doc.root.meta, documentRoot: true, ...doc.head?.length ? { head: doc.head } : {} };
|
|
68460
|
+
const s2 = new Store(":memory:");
|
|
68461
|
+
try {
|
|
68462
|
+
s2.indexDocument(doc);
|
|
68463
|
+
const row = s2.node(":");
|
|
68464
|
+
return {
|
|
68465
|
+
path: ":",
|
|
68466
|
+
type: tocType(s2, ":", row),
|
|
68467
|
+
format: row.format ?? null,
|
|
68468
|
+
...facetsOf(s2, ":", row),
|
|
68469
|
+
concrete: "yamlover",
|
|
68470
|
+
// by construction — the document IS yamlover text
|
|
68471
|
+
documentPath: ":",
|
|
68472
|
+
title: titleOf(s2, ":"),
|
|
68473
|
+
description: descriptionOf(s2, ":"),
|
|
68474
|
+
value: projectValue(PREVIEW_ROOT, s2, [], Infinity, true),
|
|
68475
|
+
comments: collectComments(doc, [], Infinity),
|
|
68476
|
+
relations: {}
|
|
68477
|
+
// a standalone document has no project around it
|
|
68478
|
+
};
|
|
68479
|
+
} finally {
|
|
68480
|
+
s2.close();
|
|
68481
|
+
}
|
|
68482
|
+
}
|
|
68483
|
+
function applyTextEdits(src, edits) {
|
|
68484
|
+
let out = src;
|
|
68485
|
+
for (const e3 of edits) {
|
|
68486
|
+
if (e3.concrete || e3.name) throw new Error("`concrete`/`name` are only for file-backed edits");
|
|
68487
|
+
const valueSrc = String(e3.yamlover ?? "");
|
|
68488
|
+
const meta = e3.meta === void 0 ? void 0 : e3.meta === null ? null : String(e3.meta);
|
|
68489
|
+
if (valueSrc && !isPointerValue(valueSrc)) parseYamlover(valueSrc, "<edit>");
|
|
68490
|
+
out = editChapterSource(out, strToSegs(String(e3.path ?? "")), String(e3.op ?? ""), valueSrc, meta);
|
|
68491
|
+
}
|
|
68492
|
+
parseYamlover(out, "<edit-result>");
|
|
68493
|
+
return out;
|
|
68171
68494
|
}
|
|
68172
68495
|
function firstContentIndent2(lines) {
|
|
68173
68496
|
for (const l2 of lines) if (isContentLine2(l2)) return indentOf2(l2);
|
|
@@ -68211,7 +68534,7 @@ function descriptionOf(s2, p2) {
|
|
|
68211
68534
|
function scalarKeyOf(s2, p2, key) {
|
|
68212
68535
|
const kp = (p2 === ":" ? "" : p2) + ":" + key;
|
|
68213
68536
|
const t3 = s2.node(kp);
|
|
68214
|
-
if (t3 && t3.type === "scalar" &&
|
|
68537
|
+
if (t3 && t3.type === "scalar" && t3.value != null) return String(t3.value);
|
|
68215
68538
|
return null;
|
|
68216
68539
|
}
|
|
68217
68540
|
var PATH_TOKEN = /\[\d+\]|[^:\[\]]+/g;
|
|
@@ -68289,8 +68612,10 @@ function notFound(res, url) {
|
|
|
68289
68612
|
sendJson(res, 404, { error: `no such node/endpoint: ${url.pathname}?${url.searchParams}` });
|
|
68290
68613
|
}
|
|
68291
68614
|
export {
|
|
68615
|
+
applyTextEdits,
|
|
68292
68616
|
createHandlers,
|
|
68293
|
-
mergeAgentDoc
|
|
68617
|
+
mergeAgentDoc,
|
|
68618
|
+
previewPayload
|
|
68294
68619
|
};
|
|
68295
68620
|
/*! Bundled license information:
|
|
68296
68621
|
|