yamlover 0.3.24 → 0.3.25

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/server.js CHANGED
@@ -62375,7 +62375,8 @@ function resolveDocument(doc) {
62375
62375
  node.entries?.forEach((e3, i2) => {
62376
62376
  const seg = e3.key != null ? ":" + e3.key : "[" + i2 + "]";
62377
62377
  if (isPointer(e3.value)) {
62378
- const target = resolve(doc, chains, chain, e3.value, /* @__PURE__ */ new Set([e3.value]), keys);
62378
+ const host = hasRelindex(e3.value) ? hostPositions(chain, i2) : void 0;
62379
+ const target = resolve(doc, chains, chain, e3.value, /* @__PURE__ */ new Set([e3.value]), keys, host);
62379
62380
  out.push({ from: prefix + seg, holder: base, label: e3.key, pos: i2, raw: e3.value.raw, edge: e3.edge, target, ptr: e3.value, docRoot: dr });
62380
62381
  } else {
62381
62382
  walk(e3.value, dr);
@@ -62401,6 +62402,21 @@ function resolveDocument(doc) {
62401
62402
  walk(doc.root, ":");
62402
62403
  return out;
62403
62404
  }
62405
+ function hasRelindex(p2) {
62406
+ return p2.steps.some((s2) => s2.sel === "relindex");
62407
+ }
62408
+ function hostPositions(chain, entryIdx) {
62409
+ const pos = [];
62410
+ for (let i2 = 1; i2 < chain.length; i2++) {
62411
+ const idx = chain[i2 - 1].entries?.findIndex((e3) => e3.value === chain[i2]) ?? -1;
62412
+ pos[i2] = idx >= 0 ? idx : void 0;
62413
+ }
62414
+ pos[chain.length] = entryIdx;
62415
+ return pos;
62416
+ }
62417
+ function relRaw(k) {
62418
+ return `[.${k === 0 ? "" : k > 0 ? "+" + k : k}]`;
62419
+ }
62404
62420
  function anchorKeyOf(a2) {
62405
62421
  return a2.ordinal ? null : lastKey(a2.path);
62406
62422
  }
@@ -62439,7 +62455,7 @@ function realizeAnchors(doc, chains) {
62439
62455
  }
62440
62456
  return { edges, keys };
62441
62457
  }
62442
- function resolve(doc, chains, fromChain, ptr, visited, anchorKeys) {
62458
+ function resolve(doc, chains, fromChain, ptr, visited, anchorKeys, host) {
62443
62459
  const root = doc.root;
62444
62460
  let steps = ptr.steps;
62445
62461
  let chain;
@@ -62481,7 +62497,16 @@ function resolve(doc, chains, fromChain, ptr, visited, anchorKeys) {
62481
62497
  }
62482
62498
  const node = chain[chain.length - 1];
62483
62499
  if (node === void 0) return { kind: "unresolved", reason: "empty resolution scope" };
62484
- const entry = st.sel === "key" ? node.entries?.find((e3) => e3.key === st.name) : node.entries?.[st.n];
62500
+ let idx;
62501
+ if (st.sel === "key") idx = node.entries?.findIndex((e3) => e3.key === st.name) ?? -1;
62502
+ else if (st.sel === "index") idx = st.n;
62503
+ else {
62504
+ const at = host?.[chain.length];
62505
+ if (at === void 0) return { kind: "unresolved", reason: `relative index ${relRaw(st.k)} has no host frame at this depth (URIs.md \xA7Relative indexes)` };
62506
+ idx = at + st.k;
62507
+ if (idx < 0) return { kind: "unresolved", reason: `relative index ${relRaw(st.k)} out of range (position ${at})` };
62508
+ }
62509
+ const entry = idx >= 0 ? node.entries?.[idx] : void 0;
62485
62510
  if (!entry) {
62486
62511
  if (st.sel === "key") {
62487
62512
  const via = anchorKeys?.get(node)?.get(st.name);
@@ -62491,13 +62516,14 @@ function resolve(doc, chains, fromChain, ptr, visited, anchorKeys) {
62491
62516
  }
62492
62517
  }
62493
62518
  if (!node.entries) return isWorld ? external() : { kind: "unresolved", reason: "step into a node with no fields" };
62494
- return isWorld ? external() : { kind: "unresolved", reason: `no ${st.sel === "key" ? `key "${st.name}"` : `index [${st.n}]`}` };
62519
+ return isWorld ? external() : { kind: "unresolved", reason: `no ${st.sel === "key" ? `key "${st.name}"` : st.sel === "index" ? `index [${st.n}]` : `entry at relative index ${relRaw(st.k)} (position ${idx})`}` };
62495
62520
  }
62496
62521
  if (isPointer(entry.value)) {
62497
62522
  if (visited.has(entry.value)) return { kind: "unresolved", reason: "pointer cycle" };
62498
62523
  const next = new Set(visited);
62499
62524
  next.add(entry.value);
62500
- const r2 = resolve(doc, chains, chain, entry.value, next, anchorKeys);
62525
+ const innerHost = hasRelindex(entry.value) ? hostPositions(chain, idx) : void 0;
62526
+ const r2 = resolve(doc, chains, chain, entry.value, next, anchorKeys, innerHost);
62501
62527
  if (r2.kind !== "node") return r2;
62502
62528
  chain = chains.get(r2.node) ?? [r2.node];
62503
62529
  } else {
@@ -63140,6 +63166,7 @@ function portionsToSteps(portions) {
63140
63166
  }
63141
63167
  function portionToSteps(p2) {
63142
63168
  if (p2 === "..") return [{ sel: "parent" }];
63169
+ if (p2.startsWith("..") && p2[2] === "[") return [{ sel: "parent" }, ...indexGroups(p2.slice(2), p2, "portion")];
63143
63170
  let name = "";
63144
63171
  let i2 = 0;
63145
63172
  if (p2[0] === "'" || p2[0] === '"') {
@@ -63177,15 +63204,40 @@ function portionToSteps(p2) {
63177
63204
  }
63178
63205
  const steps = [];
63179
63206
  if (name !== "") steps.push({ sel: "key", name });
63180
- while (i2 < p2.length) {
63181
- if (p2[i2] !== "[") throw new SyntaxError(`pointer: malformed portion "${p2}"`);
63207
+ if (i2 < p2.length) steps.push(...indexGroups(p2.slice(i2), p2, "portion"));
63208
+ return steps;
63209
+ }
63210
+ function indexGroups(s2, whole, noun) {
63211
+ const steps = [];
63212
+ let i2 = 0;
63213
+ while (i2 < s2.length) {
63214
+ if (s2[i2] !== "[") throw new SyntaxError(`pointer: malformed ${noun} "${whole}"`);
63182
63215
  let j = i2 + 1;
63216
+ if (s2[j] === ".") {
63217
+ j++;
63218
+ let k = 0;
63219
+ if (s2[j] === "+" || s2[j] === "-") {
63220
+ const sign = s2[j] === "-" ? -1 : 1;
63221
+ j++;
63222
+ let digits2 = "";
63223
+ while (j < s2.length && s2[j] >= "0" && s2[j] <= "9") {
63224
+ digits2 += s2[j];
63225
+ j++;
63226
+ }
63227
+ if (digits2 === "") throw new SyntaxError(`pointer: malformed index in "${whole}"`);
63228
+ k = sign * Number.parseInt(digits2, 10);
63229
+ }
63230
+ if (s2[j] !== "]") throw new SyntaxError(`pointer: malformed index in "${whole}"`);
63231
+ steps.push({ sel: "relindex", k });
63232
+ i2 = j + 1;
63233
+ continue;
63234
+ }
63183
63235
  let digits = "";
63184
- while (j < p2.length && p2[j] >= "0" && p2[j] <= "9") {
63185
- digits += p2[j];
63236
+ while (j < s2.length && s2[j] >= "0" && s2[j] <= "9") {
63237
+ digits += s2[j];
63186
63238
  j++;
63187
63239
  }
63188
- if (digits === "" || p2[j] !== "]") throw new SyntaxError(`pointer: malformed index in "${p2}"`);
63240
+ if (digits === "" || s2[j] !== "]") throw new SyntaxError(`pointer: malformed index in "${whole}"`);
63189
63241
  steps.push({ sel: "index", n: Number.parseInt(digits, 10) });
63190
63242
  i2 = j + 1;
63191
63243
  }
@@ -63201,10 +63253,17 @@ function renderPointer(p2, opts = {}) {
63201
63253
  const sep2 = spaced ? ": " : ":";
63202
63254
  const toks = [];
63203
63255
  for (const st of p2.steps) {
63204
- if (st.sel === "parent") toks.push("..");
63205
- else if (st.sel === "key") toks.push(colonSegment(st.name));
63206
- else if (toks.length > 0 && !toks[toks.length - 1].endsWith("..")) toks[toks.length - 1] += `[${st.n}]`;
63207
- else toks.push(`[${st.n}]`);
63256
+ if (st.sel === "parent") {
63257
+ toks.push("..");
63258
+ continue;
63259
+ }
63260
+ if (st.sel === "key") {
63261
+ toks.push(colonSegment(st.name));
63262
+ continue;
63263
+ }
63264
+ const t3 = st.sel === "index" ? `[${st.n}]` : `[.${st.k === 0 ? "" : (st.k > 0 ? "+" : "") + st.k}]`;
63265
+ if (toks.length > 0 && (st.sel === "relindex" || !toks[toks.length - 1].endsWith(".."))) toks[toks.length - 1] += t3;
63266
+ else toks.push(t3);
63208
63267
  }
63209
63268
  const body = toks.join(sep2);
63210
63269
  switch (p2.base.scope) {
@@ -63272,6 +63331,7 @@ function readUntilSlash(s2) {
63272
63331
  }
63273
63332
  function segToSteps(seg) {
63274
63333
  if (seg === "..") return [{ sel: "parent" }];
63334
+ if (seg.startsWith("..") && seg[2] === "[") return [{ sel: "parent" }, ...indexGroups(seg.slice(2), seg, "segment")];
63275
63335
  let i2 = 0;
63276
63336
  let name = "";
63277
63337
  for (; i2 < seg.length; i2++) {
@@ -63286,18 +63346,7 @@ function segToSteps(seg) {
63286
63346
  }
63287
63347
  const steps = [];
63288
63348
  if (name !== "") steps.push({ sel: "key", name: unescape(name) });
63289
- while (i2 < seg.length) {
63290
- if (seg[i2] !== "[") throw new SyntaxError(`pointer: malformed segment "${seg}"`);
63291
- let j = i2 + 1;
63292
- let digits = "";
63293
- while (j < seg.length && seg[j] >= "0" && seg[j] <= "9") {
63294
- digits += seg[j];
63295
- j++;
63296
- }
63297
- if (digits === "" || seg[j] !== "]") throw new SyntaxError(`pointer: malformed index in "${seg}"`);
63298
- steps.push({ sel: "index", n: Number.parseInt(digits, 10) });
63299
- i2 = j + 1;
63300
- }
63349
+ if (i2 < seg.length) steps.push(...indexGroups(seg.slice(i2), seg, "segment"));
63301
63350
  return steps;
63302
63351
  }
63303
63352
  function unescape(s2) {
@@ -63319,6 +63368,7 @@ function makeAnchor(body, fail, yaml = false) {
63319
63368
  body = body.slice(0, -2);
63320
63369
  }
63321
63370
  const path11 = parsePointer(body, yaml);
63371
+ if (path11.steps.some((s2) => s2.sel === "relindex")) fail('an anchor may not claim a position \u2014 "[.\xB1k]" is link-only');
63322
63372
  if (!ordinal) {
63323
63373
  const last = path11.steps[path11.steps.length - 1];
63324
63374
  if (last === void 0) fail('an anchor path needs a key segment (or a trailing "[]" for ordinal membership)');
@@ -65028,7 +65078,7 @@ function applySchemas(root, defsRoot, builtinDefs) {
65028
65078
  const applyItems = (inst, items, depth) => {
65029
65079
  const { node: itemsNode } = resolveSchema(items);
65030
65080
  const anyOf = itemsNode ? field(itemsNode, "anyOf") : null;
65031
- const elems = (inst.entries ?? []).filter((e3) => e3.key == null && !isPointer(e3.value));
65081
+ const elems = (inst.entries ?? []).filter((e3) => e3.key == null && !isPointer(e3.value) && !(e3.value.meta?.schema && isPointer(e3.value.meta.schema)));
65032
65082
  if (anyOf && !isPointer(anyOf) && anyOf.entries) {
65033
65083
  const branches = anyOf.entries.map((e3) => e3.value).map((b) => ({ ptr: b, ...resolveSchema(b) }));
65034
65084
  for (const e3 of elems) {
@@ -65471,7 +65521,8 @@ function nominalPath(doc, e3) {
65471
65521
  if (up === null) return null;
65472
65522
  p2 = up === ":" ? "" : up;
65473
65523
  } else if (st.sel === "key") p2 += ":" + st.name;
65474
- else p2 += "[" + st.n + "]";
65524
+ else if (st.sel === "index") p2 += "[" + st.n + "]";
65525
+ else return null;
65475
65526
  }
65476
65527
  return p2 === "" ? ":" : p2;
65477
65528
  }
@@ -65860,7 +65911,12 @@ function parsePortion(r2) {
65860
65911
  const test = parseValTest(r2);
65861
65912
  if (test !== null) return [test];
65862
65913
  const steps = parsePointer(r2).steps;
65863
- return steps.map((st) => st.sel === "key" ? { kind: "key", name: st.name } : st.sel === "index" ? { kind: "index", n: st.n } : { kind: "spine" });
65914
+ return steps.map((st) => {
65915
+ if (st.sel === "key") return { kind: "key", name: st.name };
65916
+ if (st.sel === "index") return { kind: "index", n: st.n };
65917
+ if (st.sel === "relindex") throw new SyntaxError('query: a relative index "[.\xB1k]" is a link step, not a query portion (URIs.md \xA7Relative indexes)');
65918
+ return { kind: "spine" };
65919
+ });
65864
65920
  }
65865
65921
  function parseValTest(r2) {
65866
65922
  const m = CMP.exec(r2);
@@ -67149,6 +67205,7 @@ function createHandlers(dataRoot, opts = {}) {
67149
67205
  return Object.assign(handler, {
67150
67206
  ready,
67151
67207
  close: () => {
67208
+ if (closed) return;
67152
67209
  closed = true;
67153
67210
  stopWatch?.();
67154
67211
  for (const r2 of sseClients) r2.end();
@@ -67235,6 +67292,7 @@ function projectValue(dataRoot, s2, segs, depth, top) {
67235
67292
  if (k === "omni" || k === "mix") {
67236
67293
  const entries = kids.map((c3) => ({ key: c3.label, value: project(c3) }));
67237
67294
  const marker = { kind: k, entries };
67295
+ if (row.format) marker.format = row.format;
67238
67296
  if (k === "omni") {
67239
67297
  marker.value = row.type === "blob" ? binaryValueMarker(segs, row) : wireScalar(row.value);
67240
67298
  if (typeof row.meta?.selfAt === "number") marker.selfAt = row.meta.selfAt;
@@ -67463,7 +67521,13 @@ function chapterOrderedChildren(s2, p2, format) {
67463
67521
  const bodyPos = /* @__PURE__ */ new Map();
67464
67522
  for (const e3 of s2.entries(p2)) if (e3.kind === "ref" && !bodyPos.has(e3.to)) bodyPos.set(e3.to, e3.pos ?? 0);
67465
67523
  if (bodyPos.size === 0) return kids;
67466
- const key = (c3) => bodyPos.get(c3.to) ?? c3.pos ?? 0;
67524
+ const maxPos = Math.max(...bodyPos.values(), ...kids.map((c3) => c3.pos ?? 0));
67525
+ const key = (c3) => {
67526
+ const bp = bodyPos.get(c3.to);
67527
+ if (bp != null) return bp;
67528
+ if (c3.label != null) return maxPos + 1 + (c3.pos ?? 0);
67529
+ return c3.pos ?? 0;
67530
+ };
67467
67531
  return kids.map((c3, i2) => ({ c: c3, i: i2 })).sort((a2, b) => key(a2.c) - key(b.c) || a2.i - b.i).map((x2) => x2.c);
67468
67532
  }
67469
67533
  function labelFor(s2, p2, keyOrIdx) {
@@ -68057,7 +68121,7 @@ function chapterEntries(lines, r2) {
68057
68121
  if (r2.marker >= 0) {
68058
68122
  const raw = lines[r2.marker].replace(/^\s*/, "");
68059
68123
  if (raw === "-" || raw.startsWith("- ")) {
68060
- const inline = raw.replace(/^-\s*/, "");
68124
+ const inline = raw.replace(/^-\s*/, "").replace(/^!!<[^>]*>\s*/, "");
68061
68125
  if (inline.trim()) starts.push({ key: /^-/.test(inline) ? null : inline.match(/^([^:\s]+):/)?.[1] ?? null, start: r2.marker, inline: true });
68062
68126
  }
68063
68127
  }
@@ -68297,6 +68361,76 @@ function setRootTag(lines, meta) {
68297
68361
  if (existing >= 0) lines[existing] = `!!<${meta}>`;
68298
68362
  else lines.splice(Math.max(at, 0), 0, `!!<${meta}>`);
68299
68363
  }
68364
+ function flowValueStart(raw, e3) {
68365
+ let i2 = indentOf2(raw);
68366
+ if (raw.startsWith("- ", i2)) i2 += 2;
68367
+ while (raw[i2] === " ") i2++;
68368
+ if (raw.startsWith("!!<", i2)) {
68369
+ const gt = raw.indexOf(">", i2);
68370
+ if (gt < 0) return -1;
68371
+ i2 = gt + 1;
68372
+ while (raw[i2] === " ") i2++;
68373
+ }
68374
+ if (e3.key !== null) {
68375
+ const c3 = raw.indexOf(":", i2);
68376
+ if (c3 < 0) return -1;
68377
+ i2 = c3 + 1;
68378
+ while (raw[i2] === " ") i2++;
68379
+ }
68380
+ return raw[i2] === "[" ? i2 : -1;
68381
+ }
68382
+ function scanFlowSeq(s2, open) {
68383
+ let depth = 0;
68384
+ let q = null;
68385
+ const cells = [];
68386
+ let cellStart = open + 1;
68387
+ for (let j = open; j < s2.length; j++) {
68388
+ const ch = s2[j];
68389
+ if (q) {
68390
+ if (ch === q) {
68391
+ if (q === "'" && s2[j + 1] === "'") j++;
68392
+ else q = null;
68393
+ }
68394
+ continue;
68395
+ }
68396
+ if (ch === "'" || ch === '"') q = ch;
68397
+ else if (ch === "[") depth++;
68398
+ else if (ch === "]") {
68399
+ depth--;
68400
+ if (depth === 0) {
68401
+ if (j > open + 1 || s2.slice(open + 1, j).trim().length) cells.push({ start: cellStart, end: j });
68402
+ return { close: j, cells };
68403
+ }
68404
+ } else if (ch === "," && depth === 1) {
68405
+ cells.push({ start: cellStart, end: j });
68406
+ cellStart = j + 1;
68407
+ }
68408
+ }
68409
+ return null;
68410
+ }
68411
+ function flowCellToken(s2) {
68412
+ const plain = s2.length > 0 && s2 === s2.trim() && !/[\s,[\]:#'"{}]/.test(s2) && !/^[*&\-|>!]/.test(s2);
68413
+ return plain ? s2 : `'${s2.replace(/'/g, "''")}'`;
68414
+ }
68415
+ function editFlowRowCell(lines, row, cellIdx, op, valueSrc) {
68416
+ const raw = lines[row.start];
68417
+ const open = flowValueStart(raw, row);
68418
+ if (open < 0) return false;
68419
+ const scan2 = scanFlowSeq(raw, open);
68420
+ if (!scan2) return false;
68421
+ if (op !== "emplace" && op !== "replace") throw new Error(`a flow-row cell supports emplace/replace only (got \`${op}\`)`);
68422
+ const payload = payloadFacets(valueSrc);
68423
+ if (payload.scalar === void 0) throw new Error("a flow-row cell takes a scalar value");
68424
+ const parsed = parseYamlover(payload.scalar, "cell").root;
68425
+ if (parsed.kind !== "scalar") throw new Error("a flow-row cell takes a scalar value");
68426
+ const text = String(parsed.value ?? "");
68427
+ if (text.includes("\n")) throw new Error("a flow-row cell cannot hold multi-line text \u2014 rewrite the row in block form (TABLE.md)");
68428
+ const cell = scan2.cells[cellIdx];
68429
+ if (!cell) throw new Error(`no cell [${cellIdx}] in the flow row (${scan2.cells.length} cells)`);
68430
+ const lead = cellIdx === 0 ? "" : " ";
68431
+ lines[row.start] = raw.slice(0, cell.start) + lead + flowCellToken(text) + raw.slice(cell.end);
68432
+ return true;
68433
+ }
68300
68434
  function editChapterSource(src, within, op, valueSrc, meta) {
68301
68435
  const lines = src.split("\n");
68302
68436
  if (within.length === 0) {
@@ -68310,6 +68444,14 @@ function editChapterSource(src, within, op, valueSrc, meta) {
68310
68444
  }
68311
68445
  throw new Error(`\`${op}\` at a document root needs a key or index target`);
68312
68446
  }
68447
+ const last = within[within.length - 1];
68448
+ if (within.length >= 2 && typeof last === "number") {
68449
+ const parentR = reachChapter(lines, within.slice(0, -2));
68450
+ const rowEntry = findEntry(lines, parentR, within[within.length - 2]);
68451
+ if (rowEntry && !isContainerEntry(lines, rowEntry, parentR.indent + 2) && editFlowRowCell(lines, rowEntry, last, op, valueSrc)) {
68452
+ return lines.join("\n");
68453
+ }
68454
+ }
68313
68455
  assignAt(lines, reachChapter(lines, within.slice(0, -1)), within[within.length - 1], op, valueSrc, meta);
68314
68456
  return lines.join("\n");
68315
68457
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yamlover",
3
- "version": "0.3.24",
3
+ "version": "0.3.25",
4
4
  "description": "Browse a yamlover tree in the web: npx yamlover <root> serves a React SPA over a directory.",
5
5
  "type": "module",
6
6
  "license": "MIT",