yamlover 0.3.13 → 0.3.21

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.
Files changed (34) hide show
  1. package/README.md +11 -2
  2. package/dist/agent-docs/AGENTS.md +4 -2
  3. package/dist/builtin-taxonomy/$defs/board +7 -7
  4. package/dist/builtin-taxonomy/$defs/chapter +17 -11
  5. package/dist/builtin-taxonomy/$defs/chunk +5 -3
  6. package/dist/builtin-taxonomy/$defs/task +15 -16
  7. package/dist/builtin-taxonomy/$defs/workflow +1 -1
  8. package/dist/client/assets/decoded-CY5-anyl.js +1 -0
  9. package/dist/client/assets/djvu-CbL4_9ak.js +1 -0
  10. package/dist/client/assets/{docx-B_9I-KwO.js → docx-CCEuxO9n.js} +1 -1
  11. package/dist/client/assets/{heic-Ce7tu8UK.js → heic-BvS6Unla.js} +2 -2
  12. package/dist/client/assets/imagemap-DBji1qL1.js +1 -0
  13. package/dist/client/assets/index-1sCxQdj3.css +1 -0
  14. package/dist/client/assets/index-DqdQvRi4.js +632 -0
  15. package/dist/client/assets/map-BfHrzAqt.js +1 -0
  16. package/dist/client/assets/openable-DIyqYrzm.js +4 -0
  17. package/dist/client/assets/{paged-CBui7Gsu.js → paged-COP9CRTO.js} +1 -1
  18. package/dist/client/assets/{pdf-DEAMWCiJ.js → pdf-C-kvASQl.js} +9 -9
  19. package/dist/client/assets/psd-KxbPOIwA.js +11 -0
  20. package/dist/client/assets/{spreadsheet-DM8lRCkI.js → spreadsheet-DkG5umsc.js} +1 -1
  21. package/dist/client/assets/tiff-sq_Q9sNj.js +1 -0
  22. package/dist/client/index.html +2 -2
  23. package/dist/server.js +1014 -274
  24. package/package.json +1 -1
  25. package/dist/client/assets/decoded-7CsibQKd.js +0 -1
  26. package/dist/client/assets/djvu-BXFlPnkK.js +0 -1
  27. package/dist/client/assets/imagemap-DlsYOgu-.js +0 -1
  28. package/dist/client/assets/index-D7TqaRqy.js +0 -620
  29. package/dist/client/assets/index-DEBdytA6.css +0 -1
  30. package/dist/client/assets/map-CKyCg437.js +0 -1
  31. package/dist/client/assets/panzoom-BDtxTlLr.js +0 -4
  32. package/dist/client/assets/psd-BUfV7J7j.js +0 -11
  33. package/dist/client/assets/tiff-DvGVB25t.js +0 -1
  34. /package/dist/client/assets/{panzoom-CIGW-MKW.css → openable-CIGW-MKW.css} +0 -0
package/dist/server.js CHANGED
@@ -62535,7 +62535,7 @@ function pathOf(chain) {
62535
62535
 
62536
62536
  // ../engine/ts/src/store.ts
62537
62537
  import { DatabaseSync } from "node:sqlite";
62538
- var SCHEMA_VERSION = 4;
62538
+ var SCHEMA_VERSION = 5;
62539
62539
  var SCHEMA = `
62540
62540
  CREATE TABLE IF NOT EXISTS node (
62541
62541
  path TEXT PRIMARY KEY,
@@ -62568,6 +62568,18 @@ CREATE TABLE IF NOT EXISTS dangling (
62568
62568
  reason TEXT NOT NULL -- why it did not resolve
62569
62569
  );
62570
62570
  `;
62571
+ function encodeScalarValue(v) {
62572
+ if (typeof v === "number" && !Number.isFinite(v)) return JSON.stringify({ "@nonfinite": String(v) });
62573
+ return JSON.stringify(v);
62574
+ }
62575
+ function decodeScalarValue(s2) {
62576
+ const v = JSON.parse(s2);
62577
+ if (v && typeof v === "object" && !Array.isArray(v) && "@nonfinite" in v) {
62578
+ const n2 = v["@nonfinite"];
62579
+ return n2 === "Infinity" ? Infinity : n2 === "-Infinity" ? -Infinity : NaN;
62580
+ }
62581
+ return v;
62582
+ }
62571
62583
  var Store = class {
62572
62584
  db;
62573
62585
  /** True while the DB holds no usable index (a new file, or a schema-version mismatch dropped
@@ -62612,7 +62624,7 @@ var Store = class {
62612
62624
  const meta = node.meta ? JSON.stringify(node.meta) : null;
62613
62625
  const owned = node.entries?.filter((e3) => e3.edge !== "back") ?? [];
62614
62626
  const isArray = node.array || node.kind === "mapping" && owned.length > 0 && owned.every((e3) => e3.key === null);
62615
- const value = node.kind === "scalar" ? JSON.stringify(node.value) : null;
62627
+ const value = node.kind === "scalar" ? encodeScalarValue(node.value) : null;
62616
62628
  const format = node.kind === "blob" ? node.format : formatFromMeta(node);
62617
62629
  const hash = node.kind === "blob" ? node.contentHash : null;
62618
62630
  const size = node.kind === "blob" ? node.size : null;
@@ -62679,7 +62691,7 @@ var Store = class {
62679
62691
  const meta = node.meta ? JSON.stringify(node.meta) : null;
62680
62692
  const owned = node.entries?.filter((e3) => e3.edge !== "back") ?? [];
62681
62693
  const isArray = node.array || node.kind === "mapping" && owned.length > 0 && owned.every((e3) => e3.key === null);
62682
- const value = node.kind === "scalar" ? JSON.stringify(node.value) : null;
62694
+ const value = node.kind === "scalar" ? encodeScalarValue(node.value) : null;
62683
62695
  const format = node.kind === "blob" ? node.format : formatFromMeta(node);
62684
62696
  const hash = node.kind === "blob" ? node.contentHash : null;
62685
62697
  const size = node.kind === "blob" ? node.size : null;
@@ -62720,7 +62732,7 @@ var Store = class {
62720
62732
  walkNodes(doc.root, annStorePath, (p2, node, parent, label, pos) => {
62721
62733
  const meta = node.meta ? JSON.stringify(node.meta) : null;
62722
62734
  const isArray = node.array || node.kind === "mapping" && (node.entries?.every((e3) => e3.key === null) ?? false);
62723
- const value = node.kind === "scalar" ? JSON.stringify(node.value) : null;
62735
+ const value = node.kind === "scalar" ? encodeScalarValue(node.value) : null;
62724
62736
  const format = p2 === annStorePath ? "x-yamlover-annotation" : node.kind === "blob" ? node.format : formatFromMeta(node);
62725
62737
  const hash = node.kind === "blob" ? node.contentHash : null;
62726
62738
  const size = node.kind === "blob" ? node.size : null;
@@ -62919,7 +62931,7 @@ function rowToNode(r2) {
62919
62931
  path: r2.path,
62920
62932
  type: r2.type,
62921
62933
  format: r2.format ?? null,
62922
- value: r2.value != null ? JSON.parse(r2.value) : null,
62934
+ value: r2.value != null ? decodeScalarValue(r2.value) : null,
62923
62935
  content_hash: r2.content_hash ?? null,
62924
62936
  size: r2.size ?? null,
62925
62937
  is_array: !!r2.is_array,
@@ -62941,7 +62953,7 @@ import fs2 from "node:fs";
62941
62953
  import path2 from "node:path";
62942
62954
  import { setImmediate as yieldLoop } from "node:timers/promises";
62943
62955
 
62944
- // ../engine/ts/node_modules/xxhash-wasm/esm/xxhash-wasm.js
62956
+ // ../../node_modules/xxhash-wasm/esm/xxhash-wasm.js
62945
62957
  var t = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 48, 8, 96, 3, 127, 127, 127, 1, 127, 96, 3, 127, 127, 127, 0, 96, 2, 127, 127, 0, 96, 1, 127, 1, 127, 96, 3, 127, 127, 126, 1, 126, 96, 3, 126, 127, 127, 1, 126, 96, 2, 127, 126, 0, 96, 1, 127, 1, 126, 3, 11, 10, 0, 0, 2, 1, 3, 4, 5, 6, 1, 7, 5, 3, 1, 0, 1, 7, 85, 9, 3, 109, 101, 109, 2, 0, 5, 120, 120, 104, 51, 50, 0, 0, 6, 105, 110, 105, 116, 51, 50, 0, 2, 8, 117, 112, 100, 97, 116, 101, 51, 50, 0, 3, 8, 100, 105, 103, 101, 115, 116, 51, 50, 0, 4, 5, 120, 120, 104, 54, 52, 0, 5, 6, 105, 110, 105, 116, 54, 52, 0, 7, 8, 117, 112, 100, 97, 116, 101, 54, 52, 0, 8, 8, 100, 105, 103, 101, 115, 116, 54, 52, 0, 9, 10, 251, 22, 10, 242, 1, 1, 4, 127, 32, 0, 32, 1, 106, 33, 3, 32, 1, 65, 16, 79, 4, 127, 32, 3, 65, 16, 107, 33, 6, 32, 2, 65, 168, 136, 141, 161, 2, 106, 33, 3, 32, 2, 65, 137, 235, 208, 208, 7, 107, 33, 4, 32, 2, 65, 207, 140, 162, 142, 6, 106, 33, 5, 3, 64, 32, 3, 32, 0, 40, 2, 0, 65, 247, 148, 175, 175, 120, 108, 106, 65, 13, 119, 65, 177, 243, 221, 241, 121, 108, 33, 3, 32, 4, 32, 0, 65, 4, 106, 34, 0, 40, 2, 0, 65, 247, 148, 175, 175, 120, 108, 106, 65, 13, 119, 65, 177, 243, 221, 241, 121, 108, 33, 4, 32, 2, 32, 0, 65, 4, 106, 34, 0, 40, 2, 0, 65, 247, 148, 175, 175, 120, 108, 106, 65, 13, 119, 65, 177, 243, 221, 241, 121, 108, 33, 2, 32, 5, 32, 0, 65, 4, 106, 34, 0, 40, 2, 0, 65, 247, 148, 175, 175, 120, 108, 106, 65, 13, 119, 65, 177, 243, 221, 241, 121, 108, 33, 5, 32, 6, 32, 0, 65, 4, 106, 34, 0, 79, 13, 0, 11, 32, 2, 65, 12, 119, 32, 5, 65, 18, 119, 106, 32, 4, 65, 7, 119, 106, 32, 3, 65, 1, 119, 106, 5, 32, 2, 65, 177, 207, 217, 178, 1, 106, 11, 32, 1, 106, 32, 0, 32, 1, 65, 15, 113, 16, 1, 11, 146, 1, 0, 32, 1, 32, 2, 106, 33, 2, 3, 64, 32, 1, 65, 4, 106, 32, 2, 75, 69, 4, 64, 32, 0, 32, 1, 40, 2, 0, 65, 189, 220, 202, 149, 124, 108, 106, 65, 17, 119, 65, 175, 214, 211, 190, 2, 108, 33, 0, 32, 1, 65, 4, 106, 33, 1, 12, 1, 11, 11, 3, 64, 32, 1, 32, 2, 79, 69, 4, 64, 32, 0, 32, 1, 45, 0, 0, 65, 177, 207, 217, 178, 1, 108, 106, 65, 11, 119, 65, 177, 243, 221, 241, 121, 108, 33, 0, 32, 1, 65, 1, 106, 33, 1, 12, 1, 11, 11, 32, 0, 32, 0, 65, 15, 118, 115, 65, 247, 148, 175, 175, 120, 108, 34, 0, 65, 13, 118, 32, 0, 115, 65, 189, 220, 202, 149, 124, 108, 34, 0, 65, 16, 118, 32, 0, 115, 11, 63, 0, 32, 0, 65, 8, 106, 32, 1, 65, 168, 136, 141, 161, 2, 106, 54, 2, 0, 32, 0, 65, 12, 106, 32, 1, 65, 137, 235, 208, 208, 7, 107, 54, 2, 0, 32, 0, 65, 16, 106, 32, 1, 54, 2, 0, 32, 0, 65, 20, 106, 32, 1, 65, 207, 140, 162, 142, 6, 106, 54, 2, 0, 11, 195, 4, 1, 6, 127, 32, 1, 32, 2, 106, 33, 6, 32, 0, 65, 24, 106, 33, 4, 32, 0, 65, 40, 106, 40, 2, 0, 33, 3, 32, 0, 32, 0, 40, 2, 0, 32, 2, 106, 54, 2, 0, 32, 0, 65, 4, 106, 34, 5, 32, 5, 40, 2, 0, 32, 2, 65, 16, 79, 32, 0, 40, 2, 0, 65, 16, 79, 114, 114, 54, 2, 0, 32, 2, 32, 3, 106, 65, 16, 73, 4, 64, 32, 3, 32, 4, 106, 32, 1, 32, 2, 252, 10, 0, 0, 32, 0, 65, 40, 106, 32, 2, 32, 3, 106, 54, 2, 0, 15, 11, 32, 3, 4, 64, 32, 3, 32, 4, 106, 32, 1, 65, 16, 32, 3, 107, 34, 2, 252, 10, 0, 0, 32, 0, 65, 8, 106, 34, 3, 32, 3, 40, 2, 0, 32, 4, 40, 2, 0, 65, 247, 148, 175, 175, 120, 108, 106, 65, 13, 119, 65, 177, 243, 221, 241, 121, 108, 54, 2, 0, 32, 0, 65, 12, 106, 34, 3, 32, 3, 40, 2, 0, 32, 4, 65, 4, 106, 40, 2, 0, 65, 247, 148, 175, 175, 120, 108, 106, 65, 13, 119, 65, 177, 243, 221, 241, 121, 108, 54, 2, 0, 32, 0, 65, 16, 106, 34, 3, 32, 3, 40, 2, 0, 32, 4, 65, 8, 106, 40, 2, 0, 65, 247, 148, 175, 175, 120, 108, 106, 65, 13, 119, 65, 177, 243, 221, 241, 121, 108, 54, 2, 0, 32, 0, 65, 20, 106, 34, 3, 32, 3, 40, 2, 0, 32, 4, 65, 12, 106, 40, 2, 0, 65, 247, 148, 175, 175, 120, 108, 106, 65, 13, 119, 65, 177, 243, 221, 241, 121, 108, 54, 2, 0, 32, 0, 65, 40, 106, 65, 0, 54, 2, 0, 32, 1, 32, 2, 106, 33, 1, 11, 32, 1, 32, 6, 65, 16, 107, 77, 4, 64, 32, 6, 65, 16, 107, 33, 8, 32, 0, 65, 8, 106, 40, 2, 0, 33, 2, 32, 0, 65, 12, 106, 40, 2, 0, 33, 3, 32, 0, 65, 16, 106, 40, 2, 0, 33, 5, 32, 0, 65, 20, 106, 40, 2, 0, 33, 7, 3, 64, 32, 2, 32, 1, 40, 2, 0, 65, 247, 148, 175, 175, 120, 108, 106, 65, 13, 119, 65, 177, 243, 221, 241, 121, 108, 33, 2, 32, 3, 32, 1, 65, 4, 106, 34, 1, 40, 2, 0, 65, 247, 148, 175, 175, 120, 108, 106, 65, 13, 119, 65, 177, 243, 221, 241, 121, 108, 33, 3, 32, 5, 32, 1, 65, 4, 106, 34, 1, 40, 2, 0, 65, 247, 148, 175, 175, 120, 108, 106, 65, 13, 119, 65, 177, 243, 221, 241, 121, 108, 33, 5, 32, 7, 32, 1, 65, 4, 106, 34, 1, 40, 2, 0, 65, 247, 148, 175, 175, 120, 108, 106, 65, 13, 119, 65, 177, 243, 221, 241, 121, 108, 33, 7, 32, 8, 32, 1, 65, 4, 106, 34, 1, 79, 13, 0, 11, 32, 0, 65, 8, 106, 32, 2, 54, 2, 0, 32, 0, 65, 12, 106, 32, 3, 54, 2, 0, 32, 0, 65, 16, 106, 32, 5, 54, 2, 0, 32, 0, 65, 20, 106, 32, 7, 54, 2, 0, 11, 32, 1, 32, 6, 73, 4, 64, 32, 4, 32, 1, 32, 6, 32, 1, 107, 34, 1, 252, 10, 0, 0, 32, 0, 65, 40, 106, 32, 1, 54, 2, 0, 11, 11, 97, 1, 1, 127, 32, 0, 65, 16, 106, 40, 2, 0, 33, 1, 32, 0, 65, 4, 106, 40, 2, 0, 4, 127, 32, 1, 65, 12, 119, 32, 0, 65, 20, 106, 40, 2, 0, 65, 18, 119, 106, 32, 0, 65, 12, 106, 40, 2, 0, 65, 7, 119, 106, 32, 0, 65, 8, 106, 40, 2, 0, 65, 1, 119, 106, 5, 32, 1, 65, 177, 207, 217, 178, 1, 106, 11, 32, 0, 40, 2, 0, 106, 32, 0, 65, 24, 106, 32, 0, 65, 40, 106, 40, 2, 0, 16, 1, 11, 255, 3, 2, 3, 126, 1, 127, 32, 0, 32, 1, 106, 33, 6, 32, 1, 65, 32, 79, 4, 126, 32, 6, 65, 32, 107, 33, 6, 32, 2, 66, 214, 235, 130, 238, 234, 253, 137, 245, 224, 0, 124, 33, 3, 32, 2, 66, 177, 169, 172, 193, 173, 184, 212, 166, 61, 125, 33, 4, 32, 2, 66, 249, 234, 208, 208, 231, 201, 161, 228, 225, 0, 124, 33, 5, 3, 64, 32, 3, 32, 0, 41, 3, 0, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 124, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 33, 3, 32, 4, 32, 0, 65, 8, 106, 34, 0, 41, 3, 0, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 124, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 33, 4, 32, 2, 32, 0, 65, 8, 106, 34, 0, 41, 3, 0, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 124, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 33, 2, 32, 5, 32, 0, 65, 8, 106, 34, 0, 41, 3, 0, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 124, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 33, 5, 32, 6, 32, 0, 65, 8, 106, 34, 0, 79, 13, 0, 11, 32, 2, 66, 12, 137, 32, 5, 66, 18, 137, 124, 32, 4, 66, 7, 137, 124, 32, 3, 66, 1, 137, 124, 32, 3, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 133, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 66, 157, 163, 181, 234, 131, 177, 141, 138, 250, 0, 125, 32, 4, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 133, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 66, 157, 163, 181, 234, 131, 177, 141, 138, 250, 0, 125, 32, 2, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 133, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 66, 157, 163, 181, 234, 131, 177, 141, 138, 250, 0, 125, 32, 5, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 133, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 66, 157, 163, 181, 234, 131, 177, 141, 138, 250, 0, 125, 5, 32, 2, 66, 197, 207, 217, 178, 241, 229, 186, 234, 39, 124, 11, 32, 1, 173, 124, 32, 0, 32, 1, 65, 31, 113, 16, 6, 11, 134, 2, 0, 32, 1, 32, 2, 106, 33, 2, 3, 64, 32, 2, 32, 1, 65, 8, 106, 79, 4, 64, 32, 1, 41, 3, 0, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 32, 0, 133, 66, 27, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 66, 157, 163, 181, 234, 131, 177, 141, 138, 250, 0, 125, 33, 0, 32, 1, 65, 8, 106, 33, 1, 12, 1, 11, 11, 32, 1, 65, 4, 106, 32, 2, 77, 4, 64, 32, 0, 32, 1, 53, 2, 0, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 133, 66, 23, 137, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 66, 249, 243, 221, 241, 153, 246, 153, 171, 22, 124, 33, 0, 32, 1, 65, 4, 106, 33, 1, 11, 3, 64, 32, 1, 32, 2, 73, 4, 64, 32, 0, 32, 1, 49, 0, 0, 66, 197, 207, 217, 178, 241, 229, 186, 234, 39, 126, 133, 66, 11, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 33, 0, 32, 1, 65, 1, 106, 33, 1, 12, 1, 11, 11, 32, 0, 32, 0, 66, 33, 136, 133, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 34, 0, 32, 0, 66, 29, 136, 133, 66, 249, 243, 221, 241, 153, 246, 153, 171, 22, 126, 34, 0, 32, 0, 66, 32, 136, 133, 11, 77, 0, 32, 0, 65, 8, 106, 32, 1, 66, 214, 235, 130, 238, 234, 253, 137, 245, 224, 0, 124, 55, 3, 0, 32, 0, 65, 16, 106, 32, 1, 66, 177, 169, 172, 193, 173, 184, 212, 166, 61, 125, 55, 3, 0, 32, 0, 65, 24, 106, 32, 1, 55, 3, 0, 32, 0, 65, 32, 106, 32, 1, 66, 249, 234, 208, 208, 231, 201, 161, 228, 225, 0, 124, 55, 3, 0, 11, 244, 4, 2, 3, 127, 4, 126, 32, 1, 32, 2, 106, 33, 5, 32, 0, 65, 40, 106, 33, 4, 32, 0, 65, 200, 0, 106, 40, 2, 0, 33, 3, 32, 0, 32, 0, 41, 3, 0, 32, 2, 173, 124, 55, 3, 0, 32, 2, 32, 3, 106, 65, 32, 73, 4, 64, 32, 3, 32, 4, 106, 32, 1, 32, 2, 252, 10, 0, 0, 32, 0, 65, 200, 0, 106, 32, 2, 32, 3, 106, 54, 2, 0, 15, 11, 32, 3, 4, 64, 32, 3, 32, 4, 106, 32, 1, 65, 32, 32, 3, 107, 34, 2, 252, 10, 0, 0, 32, 0, 65, 8, 106, 34, 3, 32, 3, 41, 3, 0, 32, 4, 41, 3, 0, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 124, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 55, 3, 0, 32, 0, 65, 16, 106, 34, 3, 32, 3, 41, 3, 0, 32, 4, 65, 8, 106, 41, 3, 0, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 124, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 55, 3, 0, 32, 0, 65, 24, 106, 34, 3, 32, 3, 41, 3, 0, 32, 4, 65, 16, 106, 41, 3, 0, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 124, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 55, 3, 0, 32, 0, 65, 32, 106, 34, 3, 32, 3, 41, 3, 0, 32, 4, 65, 24, 106, 41, 3, 0, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 124, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 55, 3, 0, 32, 0, 65, 200, 0, 106, 65, 0, 54, 2, 0, 32, 1, 32, 2, 106, 33, 1, 11, 32, 1, 65, 32, 106, 32, 5, 77, 4, 64, 32, 5, 65, 32, 107, 33, 2, 32, 0, 65, 8, 106, 41, 3, 0, 33, 6, 32, 0, 65, 16, 106, 41, 3, 0, 33, 7, 32, 0, 65, 24, 106, 41, 3, 0, 33, 8, 32, 0, 65, 32, 106, 41, 3, 0, 33, 9, 3, 64, 32, 6, 32, 1, 41, 3, 0, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 124, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 33, 6, 32, 7, 32, 1, 65, 8, 106, 34, 1, 41, 3, 0, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 124, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 33, 7, 32, 8, 32, 1, 65, 8, 106, 34, 1, 41, 3, 0, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 124, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 33, 8, 32, 9, 32, 1, 65, 8, 106, 34, 1, 41, 3, 0, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 124, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 33, 9, 32, 2, 32, 1, 65, 8, 106, 34, 1, 79, 13, 0, 11, 32, 0, 65, 8, 106, 32, 6, 55, 3, 0, 32, 0, 65, 16, 106, 32, 7, 55, 3, 0, 32, 0, 65, 24, 106, 32, 8, 55, 3, 0, 32, 0, 65, 32, 106, 32, 9, 55, 3, 0, 11, 32, 1, 32, 5, 73, 4, 64, 32, 4, 32, 1, 32, 5, 32, 1, 107, 34, 1, 252, 10, 0, 0, 32, 0, 65, 200, 0, 106, 32, 1, 54, 2, 0, 11, 11, 188, 2, 1, 5, 126, 32, 0, 65, 24, 106, 41, 3, 0, 33, 1, 32, 0, 41, 3, 0, 34, 2, 66, 32, 90, 4, 126, 32, 0, 65, 8, 106, 41, 3, 0, 34, 3, 66, 1, 137, 32, 0, 65, 16, 106, 41, 3, 0, 34, 4, 66, 7, 137, 124, 32, 1, 66, 12, 137, 32, 0, 65, 32, 106, 41, 3, 0, 34, 5, 66, 18, 137, 124, 124, 32, 3, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 133, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 66, 157, 163, 181, 234, 131, 177, 141, 138, 250, 0, 125, 32, 4, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 133, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 66, 157, 163, 181, 234, 131, 177, 141, 138, 250, 0, 125, 32, 1, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 133, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 66, 157, 163, 181, 234, 131, 177, 141, 138, 250, 0, 125, 32, 5, 66, 207, 214, 211, 190, 210, 199, 171, 217, 66, 126, 66, 31, 137, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 133, 66, 135, 149, 175, 175, 152, 182, 222, 155, 158, 127, 126, 66, 157, 163, 181, 234, 131, 177, 141, 138, 250, 0, 125, 5, 32, 1, 66, 197, 207, 217, 178, 241, 229, 186, 234, 39, 124, 11, 32, 2, 124, 32, 0, 65, 40, 106, 32, 2, 66, 31, 131, 167, 16, 6, 11]);
62946
62958
  async function e() {
62947
62959
  return function(t3) {
@@ -62981,7 +62993,11 @@ async function e() {
62981
62993
 
62982
62994
  // ../parser/ts/src/pointer.ts
62983
62995
  var LINK_RE = /^(?:[A-Za-z][A-Za-z0-9+.-]*:)?\/\//;
62984
- function parsePointer(raw) {
62996
+ function parsePointer(raw, yaml = false) {
62997
+ if (yaml) {
62998
+ const p2 = parsePointer(raw);
62999
+ return p2.base.scope === "current" ? { ...p2, base: { scope: "document" } } : p2;
63000
+ }
62985
63001
  if (looksColon(raw)) return parseColon(raw);
62986
63002
  const lm = LINK_RE.exec(raw);
62987
63003
  if (lm) {
@@ -63268,13 +63284,13 @@ function unescape(s2) {
63268
63284
  }
63269
63285
  return out;
63270
63286
  }
63271
- function makeAnchor(body, fail) {
63287
+ function makeAnchor(body, fail, yaml = false) {
63272
63288
  let ordinal = false;
63273
63289
  if (body.endsWith("[]") && !body.endsWith("\\[]")) {
63274
63290
  ordinal = true;
63275
63291
  body = body.slice(0, -2);
63276
63292
  }
63277
- const path11 = parsePointer(body);
63293
+ const path11 = parsePointer(body, yaml);
63278
63294
  if (!ordinal) {
63279
63295
  const last = path11.steps[path11.steps.length - 1];
63280
63296
  if (last === void 0) fail('an anchor path needs a key segment (or a trailing "[]" for ordinal membership)');
@@ -63287,8 +63303,117 @@ function escapeSegment(name) {
63287
63303
  return name.replace(/[\\/:[\]*&#~?!()<>=|]/g, (c3) => "\\" + c3);
63288
63304
  }
63289
63305
 
63306
+ // ../parser/ts/src/comments.ts
63307
+ function attachComments(doc, raws, src, uri) {
63308
+ if (raws.length === 0) return;
63309
+ raws.sort((a2, b) => a2.start - b.start);
63310
+ const entries = [];
63311
+ const parentOf2 = /* @__PURE__ */ new Map();
63312
+ const collect = (n2) => {
63313
+ for (const e3 of n2.entries ?? []) {
63314
+ if (e3.meta?.span) {
63315
+ entries.push(e3);
63316
+ parentOf2.set(e3, n2);
63317
+ }
63318
+ if (!isPointer(e3.value)) collect(e3.value);
63319
+ }
63320
+ };
63321
+ collect(doc.root);
63322
+ const firstStart = entries.length ? Math.min(...entries.map((e3) => e3.meta.span.start)) : src.length;
63323
+ const lineOf = lineIndexer(src);
63324
+ const blankBetween = (a2, b) => b > a2 && /\r?\n[ \t]*\r?\n/.test(src.slice(a2, b));
63325
+ const make = (r2, placement) => ({
63326
+ text: r2.text,
63327
+ span: { uri, start: r2.start, end: r2.end },
63328
+ placement,
63329
+ style: r2.style,
63330
+ ...precededByBlank(src, r2.start) ? { blankBefore: true } : {}
63331
+ });
63332
+ const push = (host, c3) => {
63333
+ host.comments = [...host.comments ?? [], c3];
63334
+ };
63335
+ const used = /* @__PURE__ */ new Set();
63336
+ const pre = raws.filter((r2) => r2.ownLine && r2.start < firstStart);
63337
+ if (pre.length > 0) {
63338
+ let m = 0;
63339
+ while (m + 1 < pre.length && !blankBetween(pre[m].end, pre[m + 1].start)) m++;
63340
+ const after = m + 1 < pre.length ? pre[m + 1].start : firstStart;
63341
+ if (blankBetween(pre[m].end, after)) {
63342
+ doc.head = pre.slice(0, m + 1).map((r2) => make(r2, "leading"));
63343
+ for (let i2 = 0; i2 <= m; i2++) used.add(pre[i2]);
63344
+ }
63345
+ }
63346
+ for (const r2 of raws) {
63347
+ if (used.has(r2)) continue;
63348
+ if (!r2.ownLine) {
63349
+ const rl = lineOf(r2.start);
63350
+ let best;
63351
+ for (const e3 of entries) {
63352
+ const s2 = e3.meta.span;
63353
+ if (s2.end > r2.start || lineOf(s2.end) !== rl) continue;
63354
+ const b = best ? best.meta.span : void 0;
63355
+ if (!b || s2.end > b.end || s2.end === b.end && s2.start > b.start) best = e3;
63356
+ }
63357
+ if (best) {
63358
+ push(best.meta, make(r2, "trailing"));
63359
+ used.add(r2);
63360
+ continue;
63361
+ }
63362
+ const next = nextEntryAfter(entries, r2.start);
63363
+ if (next && lineOf(next.meta.span.start) === rl) {
63364
+ push(next.meta, make(r2, "leading"));
63365
+ used.add(r2);
63366
+ continue;
63367
+ }
63368
+ const host = next ? parentOf2.get(next) : doc.root;
63369
+ host.meta = host.meta ?? {};
63370
+ push(host.meta, make(r2, "trailing"));
63371
+ used.add(r2);
63372
+ continue;
63373
+ }
63374
+ const target = nextEntryAfter(entries, r2.start);
63375
+ if (target) {
63376
+ push(target.meta, make(r2, "leading"));
63377
+ used.add(r2);
63378
+ continue;
63379
+ }
63380
+ doc.root.meta = doc.root.meta ?? {};
63381
+ push(doc.root.meta, make(r2, r2.ownLine ? "leading" : "trailing"));
63382
+ used.add(r2);
63383
+ }
63384
+ }
63385
+ function nextEntryAfter(entries, off) {
63386
+ let best;
63387
+ for (const e3 of entries) {
63388
+ const st = e3.meta.span.start;
63389
+ if (st > off && (!best || st < best.meta.span.start)) best = e3;
63390
+ }
63391
+ return best;
63392
+ }
63393
+ function lineIndexer(src) {
63394
+ const starts = [0];
63395
+ for (let i2 = 0; i2 < src.length; i2++) if (src[i2] === "\n") starts.push(i2 + 1);
63396
+ return (off) => {
63397
+ let lo = 0;
63398
+ let hi = starts.length - 1;
63399
+ while (lo < hi) {
63400
+ const mid = lo + hi + 1 >> 1;
63401
+ if (starts[mid] <= off) lo = mid;
63402
+ else hi = mid - 1;
63403
+ }
63404
+ return lo;
63405
+ };
63406
+ }
63407
+ function precededByBlank(src, off) {
63408
+ const ls = src.lastIndexOf("\n", off - 1);
63409
+ if (ls < 0) return false;
63410
+ const ps = src.lastIndexOf("\n", ls - 1);
63411
+ return /^[ \t\r]*$/.test(src.slice(ps + 1, ls));
63412
+ }
63413
+
63290
63414
  // ../parser/ts/src/yamlover.ts
63291
- function parseYamlover(src, uri = "<yamlover>") {
63415
+ function parseYamlover(src, uri = "<yamlover>", opts = {}) {
63416
+ const yaml = opts.yaml === true;
63292
63417
  const raw = [];
63293
63418
  const lineStarts = [];
63294
63419
  const sep2 = /\r\n|\r|\n/g;
@@ -63300,7 +63425,8 @@ function parseYamlover(src, uri = "<yamlover>") {
63300
63425
  }
63301
63426
  raw.push(src.slice(at));
63302
63427
  lineStarts.push(at);
63303
- const p2 = new Block(lex(raw), raw, uri, lineStarts);
63428
+ const lexed = lex(raw, lineStarts, uri);
63429
+ const p2 = new Block(lexed.lines, raw, uri, lineStarts, yaml);
63304
63430
  for (let k = 0; k < p2.lines.length; k++) {
63305
63431
  const l2 = p2.lines[k];
63306
63432
  if (l2.indent === 0 && (l2.text === "---" || l2.text.startsWith("--- ") || l2.text === "...")) {
@@ -63321,21 +63447,46 @@ function parseYamlover(src, uri = "<yamlover>") {
63321
63447
  }
63322
63448
  if (p2.i < p2.lines.length) p2.fail("unexpected content");
63323
63449
  if (rootSchema !== void 0) root.meta = { ...root.meta, schema: rootSchema };
63324
- return { root, source: { concrete: "yamlover", uri } };
63450
+ root.meta = { ...root.meta, span: { uri, start: 0, end: src.length } };
63451
+ const doc = { root, source: { concrete: yaml ? "yaml" : "yamlover", uri } };
63452
+ const comments = lexed.comments.filter((c3) => !p2.blockLines.has(c3.n)).map(({ n: _n, ...r2 }) => r2);
63453
+ attachComments(doc, comments, src, uri);
63454
+ return doc;
63325
63455
  }
63326
- function lex(raw) {
63456
+ function lex(raw, lineStarts, uri) {
63327
63457
  const out = [];
63458
+ const comments = [];
63459
+ let prevBlank = false;
63328
63460
  for (let n2 = 0; n2 < raw.length; n2++) {
63329
63461
  const line = raw[n2];
63330
63462
  let indent = 0;
63331
63463
  while (indent < line.length && line[indent] === " ") indent++;
63332
- const content = stripComment(line.slice(indent)).replace(/\s+$/, "");
63333
- if (content === "") continue;
63334
- out.push({ indent, text: content, n: n2 });
63464
+ const body = line.slice(indent);
63465
+ const at = commentStart(body);
63466
+ const content = (at >= 0 ? body.slice(0, at) : body).replace(/\s+$/, "");
63467
+ if (at >= 0) {
63468
+ const base = lineStarts[n2] ?? 0;
63469
+ comments.push({
63470
+ start: base + indent + at,
63471
+ end: base + line.replace(/\s+$/, "").length,
63472
+ // through the last non-blank char
63473
+ text: body.slice(at + 1).replace(/\s+$/, ""),
63474
+ // body after `#`, trailing ws trimmed
63475
+ ownLine: content === "",
63476
+ style: "line",
63477
+ n: n2
63478
+ });
63479
+ }
63480
+ if (content === "") {
63481
+ prevBlank = at < 0;
63482
+ continue;
63483
+ }
63484
+ out.push({ indent, text: content, n: n2, ...prevBlank ? { blankBefore: true } : {} });
63485
+ prevBlank = false;
63335
63486
  }
63336
- return out;
63487
+ return { lines: out, comments };
63337
63488
  }
63338
- function stripComment(s2) {
63489
+ function commentStart(s2) {
63339
63490
  let inS = false;
63340
63491
  let inD = false;
63341
63492
  for (let i2 = 0; i2 < s2.length; i2++) {
@@ -63347,10 +63498,10 @@ function stripComment(s2) {
63347
63498
  if (c3 === "'" && !inD) inS = !inS;
63348
63499
  else if (c3 === '"' && !inS) inD = !inD;
63349
63500
  else if (c3 === "#" && !inS && !inD && (i2 === 0 || s2[i2 - 1] === " " || s2[i2 - 1] === " ")) {
63350
- return s2.slice(0, i2);
63501
+ return i2;
63351
63502
  }
63352
63503
  }
63353
- return s2;
63504
+ return -1;
63354
63505
  }
63355
63506
  var Block = class {
63356
63507
  lines;
@@ -63360,12 +63511,17 @@ var Block = class {
63360
63511
  // source path/id, surfaced in parse-error messages
63361
63512
  lineStarts;
63362
63513
  // absolute offset of each raw line's first character
63514
+ blockLines = /* @__PURE__ */ new Set();
63515
+ // raw lines consumed by a block scalar (their `#` is content)
63516
+ yaml;
63517
+ // YAML concrete: bare `&`/`*` resolve at the document root
63363
63518
  i = 0;
63364
- constructor(lines, raw, uri = "<yamlover>", lineStarts = []) {
63519
+ constructor(lines, raw, uri = "<yamlover>", lineStarts = [], yaml = false) {
63365
63520
  this.lines = lines;
63366
63521
  this.raw = raw;
63367
63522
  this.uri = uri;
63368
63523
  this.lineStarts = lineStarts;
63524
+ this.yaml = yaml;
63369
63525
  }
63370
63526
  /** Absolute span of `len` chars starting at column `col` of raw line `lineN`. Valid
63371
63527
  * because every Line.text is a prefix-aligned slice of its raw line (lex strips only
@@ -63415,7 +63571,7 @@ var Block = class {
63415
63571
  body = text.slice(1, j);
63416
63572
  tokenLen = j;
63417
63573
  }
63418
- const anchor = makeAnchor(body, (m) => this.fail(m));
63574
+ const anchor = makeAnchor(body, (m) => this.fail(m), this.yaml);
63419
63575
  anchor.path.span = this.spanAt(lineN, col, tokenLen);
63420
63576
  const a2 = adv(text, tokenLen, col);
63421
63577
  return { anchor, rest: a2.rest, col: a2.col };
@@ -63459,14 +63615,19 @@ var Block = class {
63459
63615
  return this.container(l2.indent);
63460
63616
  }
63461
63617
  this.i++;
63462
- let v = this.valueInline(
63463
- l2.text,
63464
- l2.indent,
63465
- /*allowBlock*/
63466
- true,
63467
- l2.n,
63468
- l2.indent
63469
- );
63618
+ let v;
63619
+ if (/^[|>][+-]?\d*$/.test(l2.text)) {
63620
+ v = this.blockScalar(l2.text, l2.indent, l2.n);
63621
+ } else {
63622
+ v = this.valueInline(
63623
+ l2.text,
63624
+ l2.indent,
63625
+ /*allowBlock*/
63626
+ true,
63627
+ l2.n,
63628
+ l2.indent
63629
+ );
63630
+ }
63470
63631
  const nxt = this.peek();
63471
63632
  if (nxt && nxt.indent === l2.indent && nxt.indent >= minIndent && !isPointer(v) && v.kind === "scalar") {
63472
63633
  v = this.mergeCont(v, this.container(l2.indent));
@@ -63486,9 +63647,13 @@ var Block = class {
63486
63647
  const entries = [];
63487
63648
  const anchors = [];
63488
63649
  let self2;
63650
+ let selfAt;
63489
63651
  for (; ; ) {
63490
63652
  const l2 = this.peek();
63491
63653
  if (!l2 || l2.indent !== indent) break;
63654
+ const startLineN = l2.n;
63655
+ const startCol = l2.indent;
63656
+ const startBlank = l2.blankBefore === true;
63492
63657
  let value;
63493
63658
  let entry;
63494
63659
  if (l2.text.startsWith("&")) {
@@ -63512,6 +63677,7 @@ var Block = class {
63512
63677
  if (isPointer(v) || v.kind !== "scalar") this.fail("only a scalar value may share a line with an own-line anchor");
63513
63678
  if (self2 !== void 0) this.fail("a node may carry at most one scalar value line");
63514
63679
  self2 = v;
63680
+ selfAt = entries.length;
63515
63681
  }
63516
63682
  continue;
63517
63683
  }
@@ -63547,17 +63713,24 @@ var Block = class {
63547
63713
  const kv = splitKV(l2.text);
63548
63714
  if (!kv) {
63549
63715
  this.i++;
63550
- const v = this.valueInline(
63551
- l2.text,
63552
- indent,
63553
- /*allowBlock*/
63554
- false,
63555
- l2.n,
63556
- l2.indent
63557
- );
63558
- if (isPointer(v) || v.kind !== "scalar") this.fail("unexpected content (expected an entry, an anchor, or a scalar value line)");
63716
+ let v;
63717
+ if (/^[|>][+-]?\d*$/.test(l2.text)) {
63718
+ v = this.blockScalar(l2.text, indent, l2.n);
63719
+ } else {
63720
+ const iv = this.valueInline(
63721
+ l2.text,
63722
+ indent,
63723
+ /*allowBlock*/
63724
+ false,
63725
+ l2.n,
63726
+ l2.indent
63727
+ );
63728
+ if (isPointer(iv) || iv.kind !== "scalar") this.fail("unexpected content (expected an entry, an anchor, or a scalar value line)");
63729
+ v = iv;
63730
+ }
63559
63731
  if (self2 !== void 0) this.fail("a node may carry at most one scalar value line");
63560
63732
  self2 = v;
63733
+ selfAt = entries.length;
63561
63734
  continue;
63562
63735
  }
63563
63736
  this.i++;
@@ -63570,11 +63743,16 @@ var Block = class {
63570
63743
  value = this.valueAfter(kv.rest, indent, l2.n, l2.indent + kv.restCol);
63571
63744
  entry = { key: unquoteKey(key), edge: back ? "back" : isPointer(value) ? "ref" : "contain", value };
63572
63745
  }
63746
+ const endLine = this.lines[this.i - 1];
63747
+ const start = (this.lineStarts[startLineN] ?? 0) + startCol;
63748
+ const end = endLine ? (this.lineStarts[endLine.n] ?? 0) + endLine.indent + endLine.text.length : start;
63749
+ entry.meta = { ...entry.meta, span: { uri: this.uri, start, end }, ...startBlank ? { blankBefore: true } : {} };
63573
63750
  entries.push(entry);
63574
63751
  }
63575
63752
  const owned = entries.filter((e3) => e3.edge !== "back");
63576
63753
  const array = owned.length > 0 && owned.every((e3) => e3.key === null);
63577
63754
  const node = self2 !== void 0 ? { ...self2, entries, array } : entries.length === 0 ? nul() : { kind: "mapping", entries, array };
63755
+ if (self2 !== void 0 && selfAt !== void 0 && selfAt > 0) node.meta = { ...node.meta, selfAt };
63578
63756
  this.attachAnchors(node, anchors);
63579
63757
  return node;
63580
63758
  }
@@ -63662,6 +63840,7 @@ var Block = class {
63662
63840
  if (ind >= r2.length) {
63663
63841
  lines.push("");
63664
63842
  lastN = n2;
63843
+ this.blockLines.add(n2);
63665
63844
  continue;
63666
63845
  }
63667
63846
  if (ind <= parentIndent) break;
@@ -63669,6 +63848,7 @@ var Block = class {
63669
63848
  if (blockIndent < 0) blockIndent = ind;
63670
63849
  lines.push(r2.slice(blockIndent));
63671
63850
  lastN = n2;
63851
+ this.blockLines.add(n2);
63672
63852
  }
63673
63853
  while (this.peek() && this.peek().n <= lastN) this.i++;
63674
63854
  let last = -1;
@@ -63685,10 +63865,10 @@ var Block = class {
63685
63865
  ({ rest: text, col } = adv(text, 0, col));
63686
63866
  const c3 = text[0];
63687
63867
  if (c3 === "{" || c3 === "[") {
63688
- return new Flow(text, this.uri, (this.lineStarts[lineN] ?? 0) + col).parse();
63868
+ return new Flow(text, this.uri, (this.lineStarts[lineN] ?? 0) + col, this.yaml).parse();
63689
63869
  }
63690
63870
  if (c3 === "*") {
63691
- const p2 = parsePointer(unquoteIfQuoted(text.slice(1)));
63871
+ const p2 = parsePointer(unquoteIfQuoted(text.slice(1)), this.yaml);
63692
63872
  p2.span = this.spanAt(lineN, col, text.length);
63693
63873
  return p2;
63694
63874
  }
@@ -63715,10 +63895,12 @@ var Flow = class {
63715
63895
  uri;
63716
63896
  base;
63717
63897
  // absolute offset of s[0] in the source (span tracking)
63718
- constructor(s2, uri = "<flow>", base = 0) {
63898
+ yaml;
63899
+ constructor(s2, uri = "<flow>", base = 0, yaml = false) {
63719
63900
  this.s = s2;
63720
63901
  this.uri = uri;
63721
63902
  this.base = base;
63903
+ this.yaml = yaml;
63722
63904
  }
63723
63905
  fail(msg) {
63724
63906
  throw new SyntaxError(`yamlover (flow): ${msg} at offset ${this.i}`);
@@ -63761,7 +63943,7 @@ var Flow = class {
63761
63943
  }
63762
63944
  txt = this.s.slice(st, this.i).trim();
63763
63945
  }
63764
- const p2 = parsePointer(txt);
63946
+ const p2 = parsePointer(txt, this.yaml);
63765
63947
  p2.span = { uri: this.uri, start: this.base + start, end: this.base + this.i };
63766
63948
  return p2;
63767
63949
  }
@@ -63779,7 +63961,7 @@ var Flow = class {
63779
63961
  }
63780
63962
  body = this.s.slice(st, this.i);
63781
63963
  }
63782
- const anchor = makeAnchor(body, (m) => this.fail(m));
63964
+ const anchor = makeAnchor(body, (m) => this.fail(m), this.yaml);
63783
63965
  anchor.path.span = { uri: this.uri, start: this.base + start, end: this.base + this.i };
63784
63966
  this.ws();
63785
63967
  const v = this.value();
@@ -64011,6 +64193,8 @@ function plainScalar(text) {
64011
64193
  if (t3 === "" || t3 === "~" || t3 === "null" || t3 === "Null" || t3 === "NULL") return { kind: "scalar", value: null, raw: text };
64012
64194
  if (t3 === "true" || t3 === "True" || t3 === "TRUE") return { kind: "scalar", value: true, raw: text };
64013
64195
  if (t3 === "false" || t3 === "False" || t3 === "FALSE") return { kind: "scalar", value: false, raw: text };
64196
+ if (/^[-+]?\.(?:inf|Inf|INF)$/.test(t3)) return { kind: "scalar", value: t3[0] === "-" ? -Infinity : Infinity, raw: text };
64197
+ if (/^\.(?:nan|NaN|NAN)$/.test(t3)) return { kind: "scalar", value: NaN, raw: text };
64014
64198
  if (/^[-+]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/.test(t3)) return { kind: "scalar", value: Number(t3), raw: text };
64015
64199
  if (/^[-+]?0x[0-9a-fA-F]+$/.test(t3)) return { kind: "scalar", value: Number(t3), raw: text };
64016
64200
  return { kind: "scalar", value: t3, raw: text };
@@ -64040,12 +64224,17 @@ function parseJson5p(src, uri = "<json5p>") {
64040
64224
  p2.ws();
64041
64225
  if (p2.i < src.length) p2.fail("trailing characters");
64042
64226
  if (isPointer(root)) return p2.fail("a top-level pointer is not allowed");
64043
- return { root, source: { concrete: "json5p", uri } };
64227
+ root.meta = { ...root.meta, span: { uri, start: 0, end: src.length } };
64228
+ const doc = { root, source: { concrete: "json5p", uri } };
64229
+ attachComments(doc, p2.comments, src, uri);
64230
+ return doc;
64044
64231
  }
64045
64232
  var Parser = class {
64046
64233
  src;
64047
64234
  uri;
64048
64235
  i = 0;
64236
+ comments = [];
64237
+ // captured in ws(); placed onto the tree after the parse
64049
64238
  constructor(src, uri) {
64050
64239
  this.src = src;
64051
64240
  this.uri = uri;
@@ -64068,20 +64257,29 @@ var Parser = class {
64068
64257
  continue;
64069
64258
  }
64070
64259
  if (c3 === "/" && this.src[this.i + 1] === "/") {
64260
+ const start = this.i;
64071
64261
  this.i += 2;
64072
64262
  while (this.i < this.src.length && this.src[this.i] !== "\n" && this.src[this.i] !== "\r") this.i++;
64263
+ this.comments.push({ start, end: this.i, text: this.src.slice(start + 2, this.i).replace(/\s+$/, ""), ownLine: this.atLineStart(start), style: "line" });
64073
64264
  continue;
64074
64265
  }
64075
64266
  if (c3 === "/" && this.src[this.i + 1] === "*") {
64267
+ const start = this.i;
64076
64268
  this.i += 2;
64077
64269
  while (this.i < this.src.length && !(this.src[this.i] === "*" && this.src[this.i + 1] === "/")) this.i++;
64078
64270
  if (this.i >= this.src.length) this.fail("unterminated block comment");
64079
64271
  this.i += 2;
64272
+ this.comments.push({ start, end: this.i, text: this.src.slice(start + 2, this.i - 2).trim(), ownLine: this.atLineStart(start), style: "block" });
64080
64273
  continue;
64081
64274
  }
64082
64275
  return;
64083
64276
  }
64084
64277
  }
64278
+ /** True when only whitespace precedes `off` on its line (so a comment there is own-line). */
64279
+ atLineStart(off) {
64280
+ const ls = this.src.lastIndexOf("\n", off - 1);
64281
+ return /^[ \t\r]*$/.test(this.src.slice(ls + 1, off));
64282
+ }
64085
64283
  value() {
64086
64284
  const c3 = this.peek();
64087
64285
  if (c3 === void 0) this.fail("unexpected end of input");
@@ -64103,13 +64301,14 @@ var Parser = class {
64103
64301
  break;
64104
64302
  }
64105
64303
  if (c3 === void 0) this.fail("unterminated object");
64304
+ const entryStart = this.i;
64106
64305
  let back = false;
64107
64306
  if (this.peek() === "~") {
64108
64307
  back = true;
64109
64308
  this.i++;
64110
64309
  }
64111
64310
  if (back && this.peek() === "*") {
64112
- entries.push({ key: null, edge: "back", value: this.pointer() });
64311
+ entries.push(withSpan({ key: null, edge: "back", value: this.pointer() }, this.uri, entryStart, this.i));
64113
64312
  } else {
64114
64313
  const key = this.key();
64115
64314
  this.ws();
@@ -64117,7 +64316,7 @@ var Parser = class {
64117
64316
  this.i++;
64118
64317
  this.ws();
64119
64318
  const v = this.value();
64120
- entries.push(makeEntry(key, back, v));
64319
+ entries.push(withSpan(makeEntry(key, back, v), this.uri, entryStart, this.i));
64121
64320
  }
64122
64321
  this.ws();
64123
64322
  const n2 = this.peek();
@@ -64144,12 +64343,13 @@ var Parser = class {
64144
64343
  break;
64145
64344
  }
64146
64345
  if (c3 === void 0) this.fail("unterminated array");
64346
+ const entryStart = this.i;
64147
64347
  if (c3 === "~") {
64148
64348
  this.i++;
64149
64349
  if (this.peek() !== "*") this.fail('expected a pointer after "~" (keyless back member)');
64150
- entries.push({ key: null, edge: "back", value: this.pointer() });
64350
+ entries.push(withSpan({ key: null, edge: "back", value: this.pointer() }, this.uri, entryStart, this.i));
64151
64351
  } else {
64152
- entries.push(makeEntry(null, false, this.value()));
64352
+ entries.push(withSpan(makeEntry(null, false, this.value()), this.uri, entryStart, this.i));
64153
64353
  }
64154
64354
  this.ws();
64155
64355
  const n2 = this.peek();
@@ -64286,6 +64486,10 @@ function makeEntry(key, back, v) {
64286
64486
  const edge = back ? "back" : isPointer(v) ? "ref" : "contain";
64287
64487
  return { key, edge, value: v };
64288
64488
  }
64489
+ function withSpan(e3, uri, start, end) {
64490
+ e3.meta = { ...e3.meta, span: { uri, start, end } };
64491
+ return e3;
64492
+ }
64289
64493
  function scalar(value, raw) {
64290
64494
  return { kind: "scalar", value, raw };
64291
64495
  }
@@ -64734,14 +64938,15 @@ function textScalar(abs, format, ctx) {
64734
64938
  return { kind: "scalar", value: text, raw: text, meta: { schema: inlineFormat(format) } };
64735
64939
  }
64736
64940
  function parsedScalar(abs, ext, ctx) {
64737
- return parsedDoc(abs, ext === ".json" || ext === ".json5" || ext === ".json5p" ? "json5p" : "yamlover", ctx);
64941
+ const lang = ext === ".json" || ext === ".json5" || ext === ".json5p" ? "json5p" : ext === ".yaml" || ext === ".yml" ? "yaml" : "yamlover";
64942
+ return parsedDoc(abs, lang, ctx);
64738
64943
  }
64739
64944
  function parsedDoc(abs, lang, ctx) {
64740
64945
  const text = readTracked(ctx, abs).toString("utf8");
64741
64946
  try {
64742
- const doc = lang === "json5p" ? parseJson5p(text, abs) : parseYamlover(text, abs);
64947
+ const doc = lang === "json5p" ? parseJson5p(text, abs) : parseYamlover(text, abs, { yaml: lang === "yaml" });
64743
64948
  const root = doc.root;
64744
- root.meta = { ...root.meta, documentRoot: true };
64949
+ root.meta = { ...root.meta, documentRoot: true, ...doc.head?.length ? { head: doc.head } : {} };
64745
64950
  return root;
64746
64951
  } catch {
64747
64952
  return { kind: "scalar", value: text, raw: text };
@@ -64782,20 +64987,40 @@ function applySchemas(root, defsRoot, builtinDefs) {
64782
64987
  const s2 = inst.meta?.schema;
64783
64988
  return !!s2 && !isPointer(s2) && s2.kind === "mapping" && !!field(s2, "format");
64784
64989
  };
64990
+ const resolveSchema = (v) => {
64991
+ if (isPointer(v)) {
64992
+ const last = v.steps[v.steps.length - 1];
64993
+ const nm = last?.sel === "key" ? last.name : null;
64994
+ return { name: nm, node: nm ? loadDef(nm) : null };
64995
+ }
64996
+ return { name: null, node: v };
64997
+ };
64998
+ const isContainerSchema = (n2) => !!field(n2, "properties") || !!field(n2, "items") || !!field(n2, "allOf") || ["object", "variant", "mixed", "array"].includes(str(n2, "type") ?? "");
64999
+ const elemIsContainer = (el) => el.kind === "mapping";
65000
+ const applyItems = (inst, items, depth) => {
65001
+ const { node: itemsNode } = resolveSchema(items);
65002
+ const anyOf = itemsNode ? field(itemsNode, "anyOf") : null;
65003
+ const elems = (inst.entries ?? []).filter((e3) => e3.key == null && !isPointer(e3.value));
65004
+ if (anyOf && !isPointer(anyOf) && anyOf.entries) {
65005
+ const branches = anyOf.entries.map((e3) => e3.value).map((b) => ({ ptr: b, ...resolveSchema(b) }));
65006
+ for (const e3 of elems) {
65007
+ const want = elemIsContainer(e3.value);
65008
+ const pick = branches.find((b) => b.node && isContainerSchema(b.node) === want) ?? branches[0];
65009
+ if (pick) apply(e3.value, pick.ptr, depth + 1);
65010
+ }
65011
+ } else {
65012
+ for (const e3 of elems) apply(e3.value, items, depth + 1);
65013
+ }
65014
+ };
64785
65015
  const apply = (inst, schema, depth) => {
64786
65016
  if (depth > 64 || isPointer(inst)) return;
64787
- let name = null;
64788
- let s2;
64789
- if (isPointer(schema)) {
64790
- const last = schema.steps[schema.steps.length - 1];
64791
- name = last?.sel === "key" ? last.name : null;
64792
- s2 = name ? loadDef(name) : null;
64793
- } else s2 = schema;
65017
+ const { name, node: s2 } = resolveSchema(schema);
64794
65018
  if (!s2 || isPointer(s2)) return;
64795
- const fmt = str(s2, "format") ?? (name && str(s2, "type") === "object" ? `x-yamlover-${name}` : null);
64796
- if (fmt && !hasFormat(inst)) inst.meta = { ...inst.meta, schema: inlineFormat(fmt) };
64797
65019
  const stype = str(s2, "type");
64798
- if (stype === "object" || stype === "variant" || stype === "mixed") {
65020
+ const named = name && (stype === "object" || stype === "variant" || stype === "mixed" || !!field(s2, "allOf"));
65021
+ const fmt = str(s2, "format") ?? (named ? `x-yamlover-${name}` : null);
65022
+ if (fmt && !hasFormat(inst)) inst.meta = { ...inst.meta, schema: inlineFormat(fmt) };
65023
+ if (stype === "object" || stype === "variant" || stype === "mixed" || stype === "array" || field(s2, "items")) {
64799
65024
  const props = field(s2, "properties");
64800
65025
  const addl = field(s2, "additionalProperties");
64801
65026
  for (const e3 of inst.entries ?? []) {
@@ -64805,11 +65030,12 @@ function applySchemas(root, defsRoot, builtinDefs) {
64805
65030
  const sub = declared ?? addl;
64806
65031
  if (sub) apply(e3.value, sub, depth + 1);
64807
65032
  }
64808
- } else if (stype === "array") {
64809
65033
  const items = field(s2, "items");
64810
- if (items) {
64811
- for (const e3 of inst.entries ?? []) if (!isPointer(e3.value)) apply(e3.value, items, depth + 1);
64812
- }
65034
+ if (items) applyItems(inst, items, depth);
65035
+ }
65036
+ const allOf = field(s2, "allOf");
65037
+ if (allOf && !isPointer(allOf) && allOf.entries) {
65038
+ for (const b of allOf.entries) apply(inst, b.value, depth + 1);
64813
65039
  }
64814
65040
  };
64815
65041
  const walk = (node) => {
@@ -64826,12 +65052,13 @@ function applyBody(dir, node, ctx) {
64826
65052
  if (!fs2.existsSync(file)) return node;
64827
65053
  const bodyDoc = parseYamlover(readTracked(ctx, file).toString("utf8"), file);
64828
65054
  const body = bodyDoc.root;
64829
- if (body.kind !== "mapping" && body.kind !== "scalar" || !body.entries) return node;
64830
- const meta = { ...node.meta, ...body.meta, documentRoot: true };
64831
- if (body.kind === "mapping" && (body.array || body.entries.length > 0 && body.entries.every((e3) => e3.key === null))) {
65055
+ if (body.kind !== "mapping" && body.kind !== "scalar") return node;
65056
+ const bodyEntries = body.entries ?? [];
65057
+ const meta = { ...node.meta, ...body.meta, documentRoot: true, ...bodyDoc.head?.length ? { head: bodyDoc.head } : {} };
65058
+ if (body.kind === "mapping" && (body.array || bodyEntries.length > 0 && bodyEntries.every((e3) => e3.key === null))) {
64832
65059
  const byKey = new Map(node.entries.map((e3) => [e3.key, e3]));
64833
65060
  const ordered = [];
64834
- for (const e3 of body.entries) {
65061
+ for (const e3 of bodyEntries) {
64835
65062
  const targetKey = isPointer(e3.value) ? pointerLeafKey(e3.value) : null;
64836
65063
  const hit = targetKey != null ? byKey.get(targetKey) : null;
64837
65064
  if (hit) {
@@ -64842,16 +65069,23 @@ function applyBody(dir, node, ctx) {
64842
65069
  for (const e3 of node.entries) if (e3.key != null && byKey.has(e3.key)) ordered.push(e3);
64843
65070
  return { kind: "mapping", entries: ordered, array: true, meta };
64844
65071
  }
64845
- const merged = new Map(node.entries.map((e3) => [e3.key, e3]));
64846
- const order = node.entries.map((e3) => e3.key);
64847
- for (const e3 of body.entries) {
64848
- const existing = merged.get(e3.key);
65072
+ const keyed = new Map(node.entries.filter((e3) => e3.key != null).map((e3) => [e3.key, e3]));
65073
+ const entries = [...node.entries];
65074
+ for (const e3 of bodyEntries) {
65075
+ if (e3.key == null) {
65076
+ entries.push(e3);
65077
+ continue;
65078
+ }
65079
+ const existing = keyed.get(e3.key);
64849
65080
  if (!existing) {
64850
- order.push(e3.key);
64851
- merged.set(e3.key, e3);
64852
- } else merged.set(e3.key, augmentEntry(existing, e3));
65081
+ keyed.set(e3.key, e3);
65082
+ entries.push(e3);
65083
+ } else {
65084
+ const aug = augmentEntry(existing, e3);
65085
+ keyed.set(e3.key, aug);
65086
+ entries[entries.indexOf(existing)] = aug;
65087
+ }
64853
65088
  }
64854
- const entries = order.map((k) => merged.get(k));
64855
65089
  if (body.kind === "scalar") return { kind: "scalar", value: body.value, raw: body.raw, entries, array: false, meta };
64856
65090
  return { kind: "mapping", entries, array: false, meta };
64857
65091
  }
@@ -64940,9 +65174,9 @@ var EXT_FORMAT = {
64940
65174
  var TEXT_FORMATS = /* @__PURE__ */ new Set(["text/markdown", "text/asciidoc", "text/x-plantuml", "text/csv", "text/tab-separated-values"]);
64941
65175
  var DOC_FORMATS = {
64942
65176
  "yamlover": "yamlover",
64943
- "yaml": "yamlover",
65177
+ "yaml": "yaml",
64944
65178
  "yamlover/meta": "yamlover",
64945
- "yaml/meta": "yamlover",
65179
+ "yaml/meta": "yaml",
64946
65180
  "json": "json5p",
64947
65181
  "json5": "json5p",
64948
65182
  "json5p": "json5p",
@@ -64954,6 +65188,11 @@ var DOC_FORMATS = {
64954
65188
  // ../engine/ts/src/rewrite.ts
64955
65189
  import * as path3 from "node:path";
64956
65190
 
65191
+ // ../parser/ts/src/serialize-common.ts
65192
+ function anchorBody(a2) {
65193
+ return renderPointer(a2.path) + (a2.ordinal ? "[]" : "");
65194
+ }
65195
+
64957
65196
  // ../parser/ts/src/serialize-yamlover.ts
64958
65197
  function pointerToken(raw) {
64959
65198
  if (raw !== raw.trim()) return `*'${raw.replace(/'/g, "''")}'`;
@@ -65317,8 +65556,7 @@ var DEFAULT_SETTINGS = {
65317
65556
  exports: [],
65318
65557
  annotations: ":annotations",
65319
65558
  tags: ":tags",
65320
- sidecars: "per-directory",
65321
- annotationTag: void 0
65559
+ sidecars: "per-directory"
65322
65560
  };
65323
65561
  var DEFAULT_SETTINGS_SOURCE = `# .yamlover/settings.yamlover \u2014 project settings for this root (created with defaults).
65324
65562
  # Settings are DEFAULTS, never constraints: they only say where the server CREATES things when you
@@ -65354,8 +65592,7 @@ function loadSettings(absRoot) {
65354
65592
  exports: exportsSetting(valueAt(root, "exports")),
65355
65593
  annotations: locationSetting(valueAt(root, "annotations"), DEFAULT_SETTINGS.annotations),
65356
65594
  tags: locationSetting(valueAt(root, "tags"), DEFAULT_SETTINGS.tags),
65357
- sidecars: sidecarLocation(valueAt(root, "sidecars"), DEFAULT_SETTINGS.sidecars),
65358
- annotationTag: locationSetting(valueAt(root, "annotation-tag"), void 0)
65595
+ sidecars: sidecarLocation(valueAt(root, "sidecars"), DEFAULT_SETTINGS.sidecars)
65359
65596
  };
65360
65597
  }
65361
65598
  function uriSetting(v) {
@@ -65376,17 +65613,6 @@ function exportsSetting(v) {
65376
65613
  }
65377
65614
  return out;
65378
65615
  }
65379
- function writeSettingKey(absRoot, key, valueText) {
65380
- const file = path6.join(absRoot, ".yamlover", "settings.yamlover");
65381
- const src = fs5.existsSync(file) ? fs5.readFileSync(file, "utf8") : "";
65382
- const line = `${key}: ${valueText}`;
65383
- const re = new RegExp("^" + key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + ":.*$", "m");
65384
- let out = re.test(src) ? src.replace(re, line) : (src === "" || src.endsWith("\n") ? src : src + "\n") + line;
65385
- if (!out.endsWith("\n")) out += "\n";
65386
- fs5.mkdirSync(path6.dirname(file), { recursive: true });
65387
- fs5.writeFileSync(file, out);
65388
- return file;
65389
- }
65390
65616
  function sidecarLocation(v, dflt) {
65391
65617
  const s2 = v !== void 0 && !isPointer(v) && v.kind === "scalar" && typeof v.value === "string" ? v.value.trim() : "";
65392
65618
  if (s2 === "per-directory" || s2 === "document") return "per-directory";
@@ -65856,14 +66082,15 @@ function blockEnd(lines, from, hi, indent) {
65856
66082
  return trimBack(lines, last, hi);
65857
66083
  }
65858
66084
  function reachBody(lines, within) {
65859
- let lo = 0;
65860
- let hi = lines.length;
65861
- let indent = firstContentIndent(lines);
66085
+ let start = { lo: 0, hi: lines.length, indent: firstContentIndent(lines) };
65862
66086
  if (lines.length === 1 && lines[0] === "") {
65863
66087
  lines.length = 0;
65864
- hi = 0;
65865
- indent = 0;
66088
+ start = { lo: 0, hi: 0, indent: 0 };
65866
66089
  }
66090
+ return reachBodyAt(lines, start, within);
66091
+ }
66092
+ function reachBodyAt(lines, start, within) {
66093
+ let { lo, hi, indent } = start;
65867
66094
  for (const key of within) {
65868
66095
  const L2 = findKeyLine(lines, lo, hi, indent, key);
65869
66096
  if (L2 < 0) {
@@ -65914,7 +66141,10 @@ function seqItemLines(lines, region, key) {
65914
66141
  }
65915
66142
  function appendAnnotation(text, within, render) {
65916
66143
  const lines = text.replace(/\n$/, "").split("\n");
65917
- const region = reachBody(lines, within);
66144
+ appendAnnotationAt(lines, reachBody(lines, within), render);
66145
+ return lines.join("\n") + "\n";
66146
+ }
66147
+ function appendAnnotationAt(lines, region, render) {
65918
66148
  const seq = seqItemLines(lines, region, ANNOTATIONS_KEY);
65919
66149
  if (!seq) {
65920
66150
  const at = trimBack(lines, region.lo - 1, region.hi);
@@ -65922,11 +66152,13 @@ function appendAnnotation(text, within, render) {
65922
66152
  } else {
65923
66153
  lines.splice(seq.end, 0, ...render(region.indent));
65924
66154
  }
65925
- return lines.join("\n") + "\n";
65926
66155
  }
65927
66156
  function upsertMapEntry(text, within, mapKey, entryKey, render) {
65928
66157
  const lines = text.replace(/\n$/, "").split("\n");
65929
- const region = reachBody(lines, within);
66158
+ upsertMapEntryAt(lines, reachBody(lines, within), mapKey, entryKey, render);
66159
+ return lines.join("\n") + "\n";
66160
+ }
66161
+ function upsertMapEntryAt(lines, region, mapKey, entryKey, render) {
65930
66162
  let mapLine = findKeyLine(lines, region.lo, region.hi, region.indent, mapKey);
65931
66163
  if (mapLine < 0) {
65932
66164
  const at = trimBack(lines, region.lo - 1, region.hi);
@@ -65943,7 +66175,6 @@ function upsertMapEntry(text, within, mapKey, entryKey, render) {
65943
66175
  const at = trimBack(lines, mapLine, mapBody.hi);
65944
66176
  lines.splice(at, 0, ...render(mapIndent));
65945
66177
  }
65946
- return lines.join("\n") + "\n";
65947
66178
  }
65948
66179
  function upsertFragment(text, within, slug, render) {
65949
66180
  return upsertMapEntry(text, within, FRAGMENTS_KEY, slug, render);
@@ -65951,20 +66182,85 @@ function upsertFragment(text, within, slug, render) {
65951
66182
  function upsertThumbnail(text, within, resKey, render) {
65952
66183
  return upsertMapEntry(text, within, THUMBNAILS_KEY, resKey, render);
65953
66184
  }
65954
- function removeAnnotation(text, within, predicate) {
66185
+ function annotationsRemain(text, within) {
65955
66186
  const lines = text.replace(/\n$/, "").split("\n");
65956
- const region = reachBody(lines, within);
66187
+ return annotationsRemainAt(lines, reachBody(lines, within));
66188
+ }
66189
+ function annotationsRemainAt(lines, region) {
65957
66190
  const seq = seqItemLines(lines, region, ANNOTATIONS_KEY);
65958
- if (!seq) return text;
65959
- for (let k = 0; k < seq.items.length; k++) {
66191
+ return !!seq && seq.items.length > 0;
66192
+ }
66193
+ function removeMapEntry(text, within, mapKey, entryKey) {
66194
+ const lines = text.replace(/\n$/, "").split("\n");
66195
+ return removeMapEntryAt(lines, reachBody(lines, within), mapKey, entryKey) ? lines.join("\n") + "\n" : text;
66196
+ }
66197
+ function removeMapEntryAt(lines, region, mapKey, entryKey) {
66198
+ const mapLine = findKeyLine(lines, region.lo, region.hi, region.indent, mapKey);
66199
+ if (mapLine < 0) return false;
66200
+ const mapIndent = region.indent + 2;
66201
+ const mapHi = blockEnd(lines, mapLine + 1, lines.length, region.indent + 1);
66202
+ const entry = findKeyLine(lines, mapLine + 1, mapHi, mapIndent, entryKey);
66203
+ if (entry < 0) return false;
66204
+ const end = blockEnd(lines, entry + 1, mapHi, mapIndent + 1);
66205
+ lines.splice(entry, end - entry);
66206
+ const newHi = blockEnd(lines, mapLine + 1, lines.length, region.indent + 1);
66207
+ let hasChild = false;
66208
+ for (let i2 = mapLine + 1; i2 < newHi; i2++) {
66209
+ if (isContentLine(lines[i2]) && indentOf(lines[i2]) === mapIndent) {
66210
+ hasChild = true;
66211
+ break;
66212
+ }
66213
+ }
66214
+ if (!hasChild) lines.splice(mapLine, blockEnd(lines, mapLine + 1, lines.length, region.indent + 1) - mapLine);
66215
+ return true;
66216
+ }
66217
+ function removeAnnotation(text, within, predicate) {
66218
+ const lines = text.replace(/\n$/, "").split("\n");
66219
+ return removeAnnotationAt(lines, () => reachBody(lines, within), predicate) ? lines.join("\n") + "\n" : text;
66220
+ }
66221
+ function removeAnnotationAt(lines, region, predicate) {
66222
+ let removed = false;
66223
+ for (; ; ) {
66224
+ const seq = seqItemLines(lines, region(), ANNOTATIONS_KEY);
66225
+ if (!seq) break;
66226
+ const k = seq.items.findIndex((i3) => predicate(lines[i3].trim().replace(/^-\s*/, "")));
66227
+ if (k < 0) break;
65960
66228
  const i2 = seq.items[k];
65961
- const itemText = lines[i2].trim().replace(/^-\s*/, "");
65962
- if (!predicate(itemText)) continue;
65963
66229
  const next = k + 1 < seq.items.length ? seq.items[k + 1] : seq.end;
65964
66230
  lines.splice(i2, next - i2);
65965
- return lines.join("\n") + "\n";
66231
+ removed = true;
65966
66232
  }
65967
- return text;
66233
+ return removed;
66234
+ }
66235
+
66236
+ // src/concrete.ts
66237
+ var JSON_FAMILY = /* @__PURE__ */ new Set(["json", "json5", "json5p"]);
66238
+ var YAML_FAMILY = /* @__PURE__ */ new Set(["yaml", "yamlover"]);
66239
+ function isDirConcrete(c3) {
66240
+ return c3 === "dir" || c3 === "dir/yamlover";
66241
+ }
66242
+ function baseLanguage(c3) {
66243
+ if (!c3) return null;
66244
+ const bare = c3.startsWith("file/") ? c3.slice("file/".length) : c3;
66245
+ return JSON_FAMILY.has(bare) || YAML_FAMILY.has(bare) ? bare : null;
66246
+ }
66247
+ function interiorOf(c3) {
66248
+ return baseLanguage(c3) ?? "yaml";
66249
+ }
66250
+ var EXT_FILE_CONCRETE = {
66251
+ ".yamlover": "file/yamlover",
66252
+ ".yaml": "file/yaml",
66253
+ ".yml": "file/yaml",
66254
+ ".json": "file/json",
66255
+ ".json5": "file/json5",
66256
+ ".json5p": "file/json5p"
66257
+ };
66258
+ function dataFileConcrete(filePath) {
66259
+ const slash = Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\"));
66260
+ const base = filePath.slice(slash + 1);
66261
+ const dot = base.lastIndexOf(".");
66262
+ const ext = dot > 0 ? base.slice(dot).toLowerCase() : "";
66263
+ return EXT_FILE_CONCRETE[ext] ?? null;
65968
66264
  }
65969
66265
 
65970
66266
  // src/server/extract/types.ts
@@ -66226,6 +66522,9 @@ var TaskRegistry = class {
66226
66522
  var LINK_KEY = "$yamloverLink";
66227
66523
  var BINARY_KEY = "$yamloverBinary";
66228
66524
  var MIXED_KEY = "$yamloverMixed";
66525
+ var REF_KEY = "$yamloverRef";
66526
+ var NUM_KEY = "$yamloverNum";
66527
+ var wireScalar = (v) => typeof v === "number" && !Number.isFinite(v) ? { [NUM_KEY]: String(v) } : v;
66229
66528
  function createHandlers(dataRoot, opts = {}) {
66230
66529
  const rootName = path10.basename(path10.resolve(dataRoot)) || "/";
66231
66530
  const dbPath = path10.join(dataRoot, ".yamlover", "index.db");
@@ -66529,11 +66828,11 @@ function createHandlers(dataRoot, opts = {}) {
66529
66828
  readBody(req).then(
66530
66829
  (data) => enqueue(async () => {
66531
66830
  const b = data;
66532
- const cols = Array.isArray(b?.columns) ? b.columns.map((lane) => Array.isArray(lane) ? lane.map((p3) => String(p3)) : []) : [];
66831
+ const lanes = Array.isArray(b?.lanes) ? b.lanes.map((lane) => Array.isArray(lane) ? lane.map((p3) => String(p3)) : []) : [];
66533
66832
  const { bodyFile } = hostFor(dataRoot, s2, strToSegs(b?.path || ":"));
66534
66833
  fs10.mkdirSync(path10.dirname(bodyFile), { recursive: true });
66535
66834
  const src = fs10.existsSync(bodyFile) ? fs10.readFileSync(bodyFile, "utf8") : "";
66536
- fs10.writeFileSync(bodyFile, writeBoardColumns(src, cols));
66835
+ fs10.writeFileSync(bodyFile, writeBoardLanes(src, lanes));
66537
66836
  broadcast(await doReindex());
66538
66837
  scheduleHasher();
66539
66838
  return { ok: true };
@@ -66552,6 +66851,69 @@ function createHandlers(dataRoot, opts = {}) {
66552
66851
  ).then((result) => sendJson(res, 201, result)).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
66553
66852
  return;
66554
66853
  }
66854
+ if (req.method === "POST" && url.pathname === "/api/edit") {
66855
+ readBody(req).then(
66856
+ (data) => enqueue(async () => {
66857
+ const d = data;
66858
+ const edits = Array.isArray(d.edits) ? d.edits : [d];
66859
+ const touched = applyEdits2(dataRoot, s2, edits);
66860
+ for (const f2 of touched) broadcast(await doReindexFile(f2));
66861
+ scheduleHasher();
66862
+ return { ok: true };
66863
+ })
66864
+ ).then((body) => sendJson(res, 200, body)).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
66865
+ return;
66866
+ }
66867
+ if (req.method === "POST" && url.pathname === "/api/create") {
66868
+ readBody(req).then(
66869
+ (data) => enqueue(async () => {
66870
+ const b = data;
66871
+ const reg = CREATABLE[String(b.schema ?? "")];
66872
+ if (!reg) throw new Error(`unknown schema: ${b.schema}`);
66873
+ const concrete = String(b.concrete ?? "");
66874
+ const parentSegs = strToSegs(b.parent ?? ":");
66875
+ const row2 = s2.node(storePath(parentSegs));
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) }));
66915
+ return;
66916
+ }
66555
66917
  if (req.method === "POST" && url.pathname === "/api/mv") {
66556
66918
  readBody(req).then(
66557
66919
  (data) => enqueue(async () => {
@@ -66571,28 +66933,25 @@ function createHandlers(dataRoot, opts = {}) {
66571
66933
  return;
66572
66934
  }
66573
66935
  if (req.method === "POST" && url.pathname === "/api/agent-docs") {
66574
- readBody(req).then(
66575
- (data) => enqueue(async () => {
66576
- const overwrite = !!data?.overwrite;
66577
- const files = [];
66578
- let wrote = false;
66579
- for (const doc of loadAgentDocs()) {
66580
- const exists = fs10.existsSync(path10.resolve(dataRoot, doc.name));
66581
- if (exists && !overwrite) {
66582
- files.push({ name: doc.name, status: "exists" });
66583
- continue;
66584
- }
66585
- writeInside(dataRoot, dataRoot, doc.name, Buffer.from(doc.content, "utf8"));
66586
- files.push({ name: doc.name, status: exists ? "overwritten" : "created" });
66936
+ enqueue(async () => {
66937
+ const files = [];
66938
+ let wrote = false;
66939
+ for (const doc of loadAgentDocs()) {
66940
+ const target = path10.resolve(dataRoot, doc.name);
66941
+ const existing = fs10.existsSync(target) ? fs10.readFileSync(target, "utf8") : null;
66942
+ const { text, status } = mergeAgentDoc(existing, doc.content);
66943
+ if (status !== "exists") {
66944
+ writeInside(dataRoot, dataRoot, doc.name, Buffer.from(text, "utf8"));
66587
66945
  wrote = true;
66588
66946
  }
66589
- if (wrote) {
66590
- broadcast(await doReindex());
66591
- scheduleHasher();
66592
- }
66593
- return { files };
66594
- })
66595
- ).then((body) => sendJson(res, 201, body)).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
66947
+ files.push({ name: doc.name, status });
66948
+ }
66949
+ if (wrote) {
66950
+ broadcast(await doReindex());
66951
+ scheduleHasher();
66952
+ }
66953
+ return { files };
66954
+ }).then((body) => sendJson(res, 201, body)).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
66596
66955
  return;
66597
66956
  }
66598
66957
  if (req.method !== "POST" && url.pathname === "/api/config") {
@@ -66614,21 +66973,6 @@ function createHandlers(dataRoot, opts = {}) {
66614
66973
  ).then((body) => sendJson(res, 200, body)).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
66615
66974
  return;
66616
66975
  }
66617
- if (req.method === "POST" && url.pathname === "/api/last-tag") {
66618
- readBody(req).then(
66619
- (data) => enqueue(async () => {
66620
- const tag = String(data?.tag ?? "").trim();
66621
- if (!tag) throw new Error("last-tag needs a `tag` path");
66622
- const segs2 = strToSegs(tag);
66623
- if (segs2.length === 0 || segs2.some((g) => typeof g === "number")) throw new Error(`not a tag node path: ${tag}`);
66624
- writeSettingKey(dataRoot, "annotation-tag", "*:: " + segs2.map((s3) => colonSegment(String(s3))).join(": "));
66625
- settings = loadSettings(dataRoot);
66626
- announce({ changed: [relFileOf(":.yamlover:settings.yamlover")] });
66627
- return { ok: true, annotationTag: settings.annotationTag };
66628
- })
66629
- ).then((body) => sendJson(res, 200, body)).catch((e3) => sendJson(res, 400, { error: String(e3.message || e3) }));
66630
- return;
66631
- }
66632
66976
  const segs = strToSegs(url.searchParams.get("path") || ":");
66633
66977
  const p2 = storePath(segs);
66634
66978
  const depth = parseDepth(url.searchParams.get("depth"));
@@ -66692,23 +67036,33 @@ function createHandlers(dataRoot, opts = {}) {
66692
67036
  }
66693
67037
  const row = s2.node(p2);
66694
67038
  if (!row) return notFound(res, url);
66695
- const viewDepth = depth ?? 1;
66696
67039
  const kind = displayKind(s2, p2, row);
67040
+ const viewDepth = depth === void 0 ? defaultDepth(s2, dataRoot, segs, row, kind) : depth;
66697
67041
  if (url.pathname === "/api/json") {
66698
67042
  const wantBytes = row.type === "blob" && url.searchParams.get("binary") === "1";
67043
+ let value;
67044
+ if (!wantBytes) value = projectValue(dataRoot, s2, segs, viewDepth, true);
67045
+ else if (kind !== "omni") value = binaryContent(dataRoot, segs, row);
67046
+ else {
67047
+ const projected = projectValue(dataRoot, s2, segs, viewDepth, true);
67048
+ const marker = projected[MIXED_KEY];
67049
+ if (marker) marker.value = binaryContent(dataRoot, segs, row);
67050
+ value = projected;
67051
+ }
66699
67052
  sendJson(res, 200, {
66700
67053
  path: segsToStr(segs),
66701
67054
  type: tocType(s2, p2, row),
66702
67055
  format: row.format ?? null,
66703
67056
  ...facetsOf(s2, p2, row),
66704
67057
  // valueType / hasKeyed / hasOrdinal — the renderer dispatch facets (TYPES.md §9)
66705
- concrete: concreteOf(dataRoot, segs, row),
66706
- // dir | yamlover | null (stat-derived; engine tracks no per-node concrete yet)
67058
+ concrete: concreteOf(s2, dataRoot, segs, row),
67059
+ // the full per-node concrete taxonomy (stat + document language)
66707
67060
  documentPath: documentPath(s2, segs),
66708
67061
  // nearest enclosing document root (for `/…` links)
66709
67062
  title: titleOf(s2, p2),
66710
- description: null,
66711
- value: wantBytes ? binaryContent(dataRoot, segs, row) : projectValue(dataRoot, s2, segs, viewDepth, true),
67063
+ description: descriptionOf(s2, p2),
67064
+ value,
67065
+ comments: cachedDoc && !wantBytes ? collectComments(cachedDoc, segs, viewDepth) : {},
66712
67066
  relations: buildRelations(dataRoot, s2, segs)
66713
67067
  });
66714
67068
  } else if (url.pathname === "/api/schema") {
@@ -66734,34 +67088,37 @@ function createHandlers(dataRoot, opts = {}) {
66734
67088
  function tocType(s2, p2, row) {
66735
67089
  return typeName(s2, p2, row);
66736
67090
  }
66737
- var JSON_EXT = { ".json": "json", ".json5": "json5", ".json5p": "json5p" };
66738
- function concreteOf(dataRoot, segs, row) {
66739
- const last = segs[segs.length - 1];
66740
- if (typeof last === "string") {
66741
- const json = JSON_EXT[path10.extname(last).toLowerCase()];
66742
- if (json) {
66743
- const abs2 = path10.resolve(dataRoot, ...segs.map(String));
66744
- try {
66745
- if (fs10.statSync(abs2).isFile()) return json;
66746
- } catch {
66747
- }
67091
+ function concreteOf(s2, dataRoot, segs, row) {
67092
+ if (segs.every((g) => typeof g === "string")) {
67093
+ const abs = path10.resolve(dataRoot, ...segs.map(String));
67094
+ let st;
67095
+ try {
67096
+ st = fs10.statSync(abs);
67097
+ } catch {
66748
67098
  }
67099
+ if (st?.isDirectory()) return fs10.existsSync(path10.join(abs, ".yamlover")) ? "dir/yamlover" : "dir";
67100
+ if (st?.isFile()) return dataFileConcrete(abs) ?? (row.type === "blob" ? "file/binary" : "file/yaml");
66749
67101
  }
66750
- if (row.type !== "mapping") return null;
66751
- if (segs.some((g) => typeof g === "number")) return null;
66752
- const abs = path10.resolve(dataRoot, ...segs.map(String));
66753
- let st;
67102
+ const docAbs = path10.resolve(dataRoot, ...documentRootSegs(s2, segs).map(String));
66754
67103
  try {
66755
- st = fs10.statSync(abs);
67104
+ if (fs10.statSync(docAbs).isFile()) return interiorOf(dataFileConcrete(docAbs) ?? "file/yaml");
66756
67105
  } catch {
66757
- return null;
66758
67106
  }
66759
- if (!st.isDirectory()) return null;
66760
- return fs10.existsSync(path10.join(abs, ".yamlover")) ? "yamlover" : "dir";
67107
+ return "yamlover";
66761
67108
  }
66762
67109
  var relKey = (label, other) => `${label ?? ""}\0${other}`;
66763
67110
  var isHidden = (s2, to2) => !!s2.node(to2)?.meta?.hidden;
67111
+ var inHiddenSubtree = (s2, p2) => {
67112
+ for (let segs = storePathToSegs(p2); segs.length; segs = segs.slice(0, -1))
67113
+ if (isHidden(s2, storePath(segs))) return true;
67114
+ return false;
67115
+ };
66764
67116
  var visibleHasChildren = (s2, p2) => s2.children(p2).some((c3) => !isHidden(s2, c3.to));
67117
+ var hasSubchapterChild = (s2, p2) => s2.children(p2).some((c3) => {
67118
+ if (isHidden(s2, c3.to)) return false;
67119
+ const f2 = s2.node(c3.to)?.format;
67120
+ return f2 === "x-yamlover-chapter" || f2 === "x-yamlover-task";
67121
+ });
66765
67122
  function downstreamEntries(s2, p2) {
66766
67123
  const isSet = !!s2.node(p2)?.meta?.set;
66767
67124
  let own = s2.entries(p2).filter((e3) => e3.kind !== "back" && !(e3.kind === "contain" && isHidden(s2, e3.to)));
@@ -66795,12 +67152,20 @@ function projectValue(dataRoot, s2, segs, depth, top) {
66795
67152
  if (k === "binary" && !top) return linkMarker(dataRoot, s2, segs);
66796
67153
  if (k === "binary") return { size: row.size, format: row.format };
66797
67154
  const kids = downstreamEntries(s2, p2);
66798
- const project = (c3) => c3.kind === "contain" ? projectValue(dataRoot, s2, [...segs, c3.label ?? c3.pos ?? 0], depth - 1, false) : linkMarker(dataRoot, s2, storePathToSegs(c3.to));
67155
+ const currentDoc = documentRootSegs(s2, segs);
67156
+ const project = (c3) => {
67157
+ if (c3.kind === "contain") return projectValue(dataRoot, s2, [...segs, c3.label ?? c3.pos ?? 0], depth - 1, false);
67158
+ const targetSegs = storePathToSegs(c3.to);
67159
+ return depth === Infinity ? refMarker(refPointerText(s2, targetSegs, currentDoc), segsToStr(targetSegs)) : linkMarker(dataRoot, s2, targetSegs);
67160
+ };
66799
67161
  if (k === "array") return kids.map(project);
66800
67162
  if (k === "omni" || k === "mix") {
66801
67163
  const entries = kids.map((c3) => ({ key: c3.label, value: project(c3) }));
66802
67164
  const marker = { kind: k, entries };
66803
- if (k === "omni") marker.value = row.value;
67165
+ if (k === "omni") {
67166
+ marker.value = row.type === "blob" ? binaryValueMarker(segs, row) : wireScalar(row.value);
67167
+ if (typeof row.meta?.selfAt === "number") marker.selfAt = row.meta.selfAt;
67168
+ }
66804
67169
  return { [MIXED_KEY]: marker };
66805
67170
  }
66806
67171
  if (k === "object") {
@@ -66808,7 +67173,73 @@ function projectValue(dataRoot, s2, segs, depth, top) {
66808
67173
  for (const c3 of kids) out[c3.label ?? String(c3.pos)] = project(c3);
66809
67174
  return out;
66810
67175
  }
66811
- return row.value;
67176
+ return wireScalar(row.value);
67177
+ }
67178
+ function irNodeAt(doc, segs) {
67179
+ let node = doc.root;
67180
+ for (const seg of segs) {
67181
+ const entries = node.entries ?? [];
67182
+ let val;
67183
+ if (typeof seg === "number") {
67184
+ const e3 = entries[seg];
67185
+ if (!e3 || e3.key !== null || e3.edge !== "contain") return void 0;
67186
+ val = e3.value;
67187
+ } else {
67188
+ val = entries.find((en) => en.key === seg && en.edge === "contain")?.value;
67189
+ }
67190
+ if (!val || isPointer(val)) return void 0;
67191
+ node = val;
67192
+ }
67193
+ return node;
67194
+ }
67195
+ function tagOf(n2) {
67196
+ return n2.meta?.set ? "!!set" : void 0;
67197
+ }
67198
+ function nodeDeco(bucket, node) {
67199
+ const anchors = (node.meta?.anchors ?? []).map(anchorBody);
67200
+ if (anchors.length > 0) bucket.anchors = anchors;
67201
+ const tag = tagOf(node);
67202
+ if (tag) bucket.tag = tag;
67203
+ const vt = (node.meta?.comments ?? []).filter((c3) => c3.placement === "trailing").map((c3) => c3.text);
67204
+ if (vt.length > 0) bucket.valueTrailing = vt;
67205
+ }
67206
+ function collectComments(doc, segs, depth) {
67207
+ const out = {};
67208
+ const root = irNodeAt(doc, segs);
67209
+ if (!root) return out;
67210
+ {
67211
+ const self2 = {};
67212
+ nodeDeco(self2, root);
67213
+ if (self2.anchors || self2.tag || self2.valueTrailing) out[""] = self2;
67214
+ }
67215
+ const head = (root.meta?.head ?? []).map((c3) => c3.text);
67216
+ if (head.length > 0) out.$head = head;
67217
+ const tail = (root.meta?.comments ?? []).filter((c3) => c3.placement === "leading").map((c3) => c3.text);
67218
+ if (tail.length > 0) out.$tail = tail;
67219
+ const placed = (cs, p2) => (cs ?? []).filter((c3) => c3.placement === p2).map((c3) => c3.text);
67220
+ const walk = (node, rel, d, top) => {
67221
+ if (!top && d <= 0) return;
67222
+ let i2 = 0;
67223
+ for (const e3 of node.entries ?? []) {
67224
+ if (e3.edge === "back") continue;
67225
+ if (e3.edge === "contain" && !isPointer(e3.value) && e3.value.meta?.hidden) continue;
67226
+ const cont = e3.key != null ? `/${e3.key}` : `[${i2}]`;
67227
+ i2++;
67228
+ const bucket = {};
67229
+ const lead = placed(e3.meta?.comments, "leading");
67230
+ const trail = placed(e3.meta?.comments, "trailing");
67231
+ if (lead.length > 0) bucket.leading = lead;
67232
+ if (trail.length > 0) bucket.trailing = trail;
67233
+ const leadComment = e3.meta?.comments?.find((c3) => c3.placement === "leading");
67234
+ if (e3.meta?.blankBefore || leadComment?.blankBefore) bucket.blankBefore = true;
67235
+ if (isPointer(e3.value)) bucket.pointer = renderPointer(e3.value);
67236
+ else nodeDeco(bucket, e3.value);
67237
+ if (Object.keys(bucket).length > 0) out[rel + cont] = bucket;
67238
+ if (e3.edge === "contain" && !isPointer(e3.value)) walk(e3.value, rel + cont, d - 1, false);
67239
+ }
67240
+ };
67241
+ walk(root, "", depth, true);
67242
+ return out;
66812
67243
  }
66813
67244
  function projectSchema(dataRoot, s2, segs, depth, top) {
66814
67245
  const p2 = storePath(segs);
@@ -66843,20 +67274,23 @@ function linkMarker(dataRoot, s2, segs) {
66843
67274
  const k = displayKind(s2, p2, row);
66844
67275
  const info = { kind: k, type: tocType(s2, p2, row), ...facetsOf(s2, p2, row), path: segsToStr(segs) };
66845
67276
  if (row.format) info.format = row.format;
66846
- const concrete = concreteOf(dataRoot, segs, row);
66847
- if (concrete) info.concrete = concrete;
67277
+ info.concrete = concreteOf(s2, dataRoot, segs, row);
66848
67278
  const title = titleOf(s2, p2);
66849
67279
  if (title) info.title = title;
66850
67280
  if (k === "binary") info.size = row.size;
66851
- else if (k === "scalar") info.value = row.value;
67281
+ else if (k === "scalar") info.value = wireScalar(row.value);
66852
67282
  else if (k === "omni" || k === "mix") {
66853
67283
  info.count = ownedEntries(s2, p2).length;
66854
- if (k === "omni") info.value = row.value;
67284
+ if (k === "omni") info.value = wireScalar(row.value);
66855
67285
  } else info.count = s2.children(p2).filter((c3) => !isHidden(s2, c3.to)).length;
66856
67286
  if (row.format === TAG_FORMAT) {
66857
67287
  const c3 = s2.node(p2 + ":color")?.value;
66858
67288
  if (typeof c3 === "string") info.color = c3;
66859
67289
  }
67290
+ if (row.format === FRAGMENT_FORMAT) {
67291
+ const imgEdge = s2.relationships(p2).out.find((o2) => o2.kind === "ref" && o2.label === "image");
67292
+ if (imgEdge) info.preview = segsToStr(storePathToSegs(imgEdge.to));
67293
+ }
66860
67294
  return { [LINK_KEY]: info };
66861
67295
  }
66862
67296
  var segsEqual = (a2, b) => a2.length === b.length && a2.every((x2, i2) => x2 === b[i2]);
@@ -66864,6 +67298,14 @@ function scopedPath(s2, src, currentDoc) {
66864
67298
  if (segsEqual(documentRootSegs(s2, src), currentDoc)) return segsToStr(src.slice(currentDoc.length));
66865
67299
  return "::" + segsToStr(src).slice(1);
66866
67300
  }
67301
+ function refPointerText(s2, src, currentDoc) {
67302
+ const seg = (x2) => typeof x2 === "number" ? `[${x2}]` : `: ${x2}`;
67303
+ if (segsEqual(documentRootSegs(s2, src), currentDoc)) {
67304
+ const tail = src.slice(currentDoc.length);
67305
+ return "*" + (tail.length > 0 ? tail.map(seg).join("") : ":");
67306
+ }
67307
+ return "*:" + src.map(seg).join("");
67308
+ }
66867
67309
  function buildRelations(dataRoot, s2, segs) {
66868
67310
  const p2 = storePath(segs);
66869
67311
  const out = {};
@@ -66872,7 +67314,7 @@ function buildRelations(dataRoot, s2, segs) {
66872
67314
  for (let i2 = 2; k in out; i2++) k = `${label} (${i2})`;
66873
67315
  out[k] = marker;
66874
67316
  };
66875
- if (segs.length > 0) put("..", linkMarker(dataRoot, s2, segs.slice(0, -1)));
67317
+ if (segs.length > 0) put("..", refMarker("..", segsToStr(segs.slice(0, -1))));
66876
67318
  const currentDoc = documentRootSegs(s2, segs);
66877
67319
  const { out: outEdges, in: inEdges } = s2.relationships(p2);
66878
67320
  const upstream = /* @__PURE__ */ new Map();
@@ -66883,7 +67325,8 @@ function buildRelations(dataRoot, s2, segs) {
66883
67325
  for (const e3 of outEdges) if (e3.kind === "back") addUp(e3.to, e3.label);
66884
67326
  for (const src of upstream.values()) {
66885
67327
  const segs2 = storePathToSegs(src);
66886
- put(scopedPath(s2, segs2, currentDoc), linkMarker(dataRoot, s2, segs2));
67328
+ const key = scopedPath(s2, segs2, currentDoc);
67329
+ put(key, s2.node(src)?.format === TAG_FORMAT ? linkMarker(dataRoot, s2, segs2) : refMarker(key, segsToStr(segs2)));
66887
67330
  }
66888
67331
  return out;
66889
67332
  }
@@ -66901,12 +67344,14 @@ function buildTree(dataRoot, s2, segs, label, depth) {
66901
67344
  type: tocType(s2, p2, row),
66902
67345
  format: row.format ?? null,
66903
67346
  ...facetsOf(s2, p2, row),
66904
- concrete: concreteOf(dataRoot, segs, row),
66905
- hasChildren: visibleHasChildren(s2, p2),
67347
+ concrete: concreteOf(s2, dataRoot, segs, row),
67348
+ // a CHAPTER's TOC entry expands to its SUBCHAPTERS only; count those, so a chunks-only chapter
67349
+ // is a leaf. Any other node reports the generic "has a visible child".
67350
+ hasChildren: row.format === "x-yamlover-chapter" || row.format === "x-yamlover-task" ? hasSubchapterChild(s2, p2) : visibleHasChildren(s2, p2),
66906
67351
  children: []
66907
67352
  };
66908
67353
  if (node.hasChildren && depth > 0) {
66909
- for (const c3 of s2.children(p2)) {
67354
+ for (const c3 of chapterOrderedChildren(s2, p2, row.format ?? null)) {
66910
67355
  if (isHidden(s2, c3.to)) continue;
66911
67356
  const seg = c3.label ?? c3.pos ?? 0;
66912
67357
  node.children.push(buildTree(dataRoot, s2, [...segs, seg], labelFor(s2, c3.to, seg), depth - 1));
@@ -66914,12 +67359,22 @@ function buildTree(dataRoot, s2, segs, label, depth) {
66914
67359
  }
66915
67360
  return node;
66916
67361
  }
67362
+ function chapterOrderedChildren(s2, p2, format) {
67363
+ const kids = s2.children(p2);
67364
+ if (format !== "x-yamlover-chapter" && format !== "x-yamlover-task") return kids;
67365
+ const bodyPos = /* @__PURE__ */ new Map();
67366
+ for (const e3 of s2.entries(p2)) if (e3.kind === "ref" && !bodyPos.has(e3.to)) bodyPos.set(e3.to, e3.pos ?? 0);
67367
+ if (bodyPos.size === 0) return kids;
67368
+ const key = (c3) => bodyPos.get(c3.to) ?? c3.pos ?? 0;
67369
+ 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);
67370
+ }
66917
67371
  function labelFor(s2, p2, keyOrIdx) {
66918
67372
  const t3 = titleOf(s2, p2);
66919
67373
  if (t3) return t3;
66920
67374
  return typeof keyOrIdx === "number" ? `[${keyOrIdx}]` : keyOrIdx;
66921
67375
  }
66922
67376
  var TAG_FORMAT = "x-yamlover-tag";
67377
+ var FRAGMENT_FORMAT = "x-yamlover-fragment";
66923
67378
  var ANN_KEY = "yamlover-annotations";
66924
67379
  var FRAG_KEY = "yamlover-fragments";
66925
67380
  var CROP_SUBDIR = "fragments";
@@ -66974,11 +67429,18 @@ function readFragments(s2, hostStore) {
66974
67429
  function annotationsFor(dataRoot, s2, segs) {
66975
67430
  const p2 = storePath(segs);
66976
67431
  const out = [];
66977
- for (const a2 of readAnnotations(s2, p2)) out.push({ ...a2 });
66978
- for (const f2 of readFragments(s2, p2)) {
66979
- for (const a2 of readAnnotations(s2, f2.node)) {
66980
- out.push({ ...a2, selector: f2.selector, fragmentSlug: f2.slug, ...f2.imageUrl ? { imageUrl: f2.imageUrl } : {} });
67432
+ const gather = (hostStore, nodeClient) => {
67433
+ for (const a2 of readAnnotations(s2, hostStore)) out.push({ ...a2, node: nodeClient });
67434
+ for (const f2 of readFragments(s2, hostStore)) {
67435
+ for (const a2 of readAnnotations(s2, f2.node)) {
67436
+ out.push({ ...a2, node: nodeClient, selector: f2.selector, fragmentSlug: f2.slug, ...f2.imageUrl ? { imageUrl: f2.imageUrl } : {} });
67437
+ }
66981
67438
  }
67439
+ };
67440
+ gather(p2, segsToStr(segs));
67441
+ for (const c3 of s2.children(p2)) {
67442
+ if (isHidden(s2, c3.to)) continue;
67443
+ gather(c3.to, segsToStr(storePathToSegs(c3.to)));
66982
67444
  }
66983
67445
  return out;
66984
67446
  }
@@ -66989,7 +67451,7 @@ function taggedMaterials(dataRoot, s2, tagStorePath) {
66989
67451
  for (const e3 of ins) {
66990
67452
  const arrOwner = e3.from.replace(/\[\d+\]$/, "").match(/^(.*):yamlover-annotations$/);
66991
67453
  const owner = arrOwner ? arrOwner[1] || ":" : e3.from;
66992
- if (owner === tagStorePath || seen.has(owner) || !s2.node(owner)) continue;
67454
+ if (owner === tagStorePath || seen.has(owner) || !s2.node(owner) || inHiddenSubtree(s2, owner)) continue;
66993
67455
  seen.add(owner);
66994
67456
  out.push(linkMarker(dataRoot, s2, storePathToSegs(owner)));
66995
67457
  }
@@ -67002,12 +67464,12 @@ function pointerRaw(clientPath) {
67002
67464
  }
67003
67465
  return "::" + out;
67004
67466
  }
67005
- function writeBoardColumns(src, cols) {
67467
+ function writeBoardLanes(src, lanes) {
67006
67468
  const laneLine = (lane) => `- [${lane.map((p2) => pointerToken(pointerRaw(p2))).join(", ")}]`;
67007
- const block = cols.length === 0 ? ["columns: []"] : ["columns:", ...cols.map(laneLine)];
67469
+ const block = lanes.length === 0 ? ["lanes: []"] : ["lanes:", ...lanes.map(laneLine)];
67008
67470
  let lines = src.replace(/\n+$/, "").split("\n");
67009
67471
  if (src.trim() === "") lines = ["!!<*yamlover:$defs:board>"];
67010
- const start = lines.findIndex((l2) => /^columns:/.test(l2));
67472
+ const start = lines.findIndex((l2) => /^lanes:/.test(l2));
67011
67473
  if (start >= 0) {
67012
67474
  let end = start + 1;
67013
67475
  while (end < lines.length && (lines[end] === "" || /^[ \t-]/.test(lines[end]))) end++;
@@ -67072,7 +67534,22 @@ function fragmentBlockLines(slug, selector, imagePtr, indent) {
67072
67534
  return lines;
67073
67535
  }
67074
67536
  function embedAnnotation(dataRoot, s2, a2) {
67075
- const { bodyFile, within } = hostFor(dataRoot, s2, strToSegs(a2.target || ":"));
67537
+ const segs = strToSegs(a2.target || ":");
67538
+ if (isChunkTarget(s2, segs)) {
67539
+ const { docSegs, bodyFile: bodyFile2 } = chapterSource(dataRoot, s2, segs);
67540
+ const { indices, keys } = splitChunkWithin(segs.slice(docSegs.length));
67541
+ const lines = fs10.readFileSync(bodyFile2, "utf8").replace(/\n$/, "").split("\n");
67542
+ const region = reachBodyAt(lines, chunkFieldRegion(
67543
+ lines,
67544
+ indices,
67545
+ /*ensureOmni*/
67546
+ true
67547
+ ), keys);
67548
+ appendAnnotationAt(lines, region, (indent) => annotationItemLines(a2, indent));
67549
+ fs10.writeFileSync(bodyFile2, lines.join("\n") + "\n");
67550
+ return bodyFile2;
67551
+ }
67552
+ const { bodyFile, within } = hostFor(dataRoot, s2, segs);
67076
67553
  fs10.mkdirSync(path10.dirname(bodyFile), { recursive: true });
67077
67554
  const src = fs10.existsSync(bodyFile) ? fs10.readFileSync(bodyFile, "utf8") : "";
67078
67555
  fs10.writeFileSync(bodyFile, appendAnnotation(src, within, (indent) => annotationItemLines(a2, indent)));
@@ -67080,8 +67557,24 @@ function embedAnnotation(dataRoot, s2, a2) {
67080
67557
  }
67081
67558
  function embedFragment(dataRoot, s2, mode, f2) {
67082
67559
  const segs = strToSegs(f2.target || ":");
67083
- const { bodyFile, within } = hostFor(dataRoot, s2, segs);
67084
67560
  const slug = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
67561
+ if (isChunkTarget(s2, segs)) {
67562
+ const { docSegs, bodyFile: bodyFile2 } = chapterSource(dataRoot, s2, segs);
67563
+ const { indices, keys } = splitChunkWithin(segs.slice(docSegs.length));
67564
+ if (keys.length) throw new Error("a fragment target must be the chunk itself");
67565
+ const lines = fs10.readFileSync(bodyFile2, "utf8").replace(/\n$/, "").split("\n");
67566
+ assertProseChunk(lines, indices);
67567
+ const region = chunkFieldRegion(
67568
+ lines,
67569
+ indices,
67570
+ /*ensureOmni*/
67571
+ true
67572
+ );
67573
+ upsertMapEntryAt(lines, region, FRAG_KEY, slug, (indent) => fragmentBlockLines(slug, f2.selector, null, indent));
67574
+ fs10.writeFileSync(bodyFile2, lines.join("\n") + "\n");
67575
+ return { slug, fragmentPath: segsToStr([...segs, FRAG_KEY, slug]) };
67576
+ }
67577
+ const { bodyFile, within } = hostFor(dataRoot, s2, segs);
67085
67578
  let imagePtr = null;
67086
67579
  if (f2.imageBase64) {
67087
67580
  const bytes = Buffer.from(String(f2.imageBase64).replace(/^data:[^,]*,/, ""), "base64");
@@ -67132,11 +67625,34 @@ async function ensureThumbnail(dataRoot, s2, mode, segs, row, w, h) {
67132
67625
  return abs;
67133
67626
  }
67134
67627
  function unembedAnnotation(dataRoot, s2, target, tag) {
67135
- const { bodyFile, within } = hostFor(dataRoot, s2, strToSegs(target || ":"));
67628
+ const segs = strToSegs(target || ":");
67629
+ const needle = (":" + pointerRaw(tag).replace(/^:+/, "")).replace(/\s+/g, "");
67630
+ if (isChunkTarget(s2, segs)) {
67631
+ const { docSegs, bodyFile: bodyFile2 } = chapterSource(dataRoot, s2, segs);
67632
+ if (!fs10.existsSync(bodyFile2)) return bodyFile2;
67633
+ const { indices, keys } = splitChunkWithin(segs.slice(docSegs.length));
67634
+ const lines = fs10.readFileSync(bodyFile2, "utf8").replace(/\n$/, "").split("\n");
67635
+ const fragRegion = () => reachBodyAt(lines, chunkFieldRegion(
67636
+ lines,
67637
+ indices,
67638
+ /*ensureOmni*/
67639
+ false
67640
+ ), keys);
67641
+ removeAnnotationAt(lines, fragRegion, (t3) => t3.replace(/\s+/g, "").includes(needle));
67642
+ if (keys.length >= 2 && keys[keys.length - 2] === FRAG_KEY && !annotationsRemainAt(lines, fragRegion())) {
67643
+ removeMapEntryAt(lines, reachBodyAt(lines, chunkFieldRegion(lines, indices, false), keys.slice(0, -2)), FRAG_KEY, keys[keys.length - 1]);
67644
+ collapseChunkOmni(lines, indices);
67645
+ }
67646
+ fs10.writeFileSync(bodyFile2, lines.join("\n") + "\n");
67647
+ return bodyFile2;
67648
+ }
67649
+ const { bodyFile, within } = hostFor(dataRoot, s2, segs);
67136
67650
  if (!fs10.existsSync(bodyFile)) return bodyFile;
67137
- const needlePath = ":" + pointerRaw(tag).replace(/^:+/, "");
67138
- const src = fs10.readFileSync(bodyFile, "utf8");
67139
- fs10.writeFileSync(bodyFile, removeAnnotation(src, within, (itemText) => itemText.replace(/\s+/g, "").includes(needlePath)));
67651
+ let src = removeAnnotation(fs10.readFileSync(bodyFile, "utf8"), within, (itemText) => itemText.replace(/\s+/g, "").includes(needle));
67652
+ if (within.length >= 2 && within[within.length - 2] === FRAG_KEY && !annotationsRemain(src, within)) {
67653
+ src = removeMapEntry(src, within.slice(0, -2), FRAG_KEY, within[within.length - 1]);
67654
+ }
67655
+ fs10.writeFileSync(bodyFile, src);
67140
67656
  return bodyFile;
67141
67657
  }
67142
67658
  function writeTag(dataRoot, location, name) {
@@ -67214,14 +67730,14 @@ function pasteIntoChapter(dataRoot, s2, segs, name, bytes) {
67214
67730
  const pointer = dirBacked ? `*/${final}` : `*/${segsToStr(fileSegs)}`;
67215
67731
  const within = segs.slice(docSegs.length);
67216
67732
  const src = fs10.readFileSync(bodyFile, "utf8");
67217
- fs10.writeFileSync(bodyFile, appendToList(src, within, "chunks", (indent) => [`${" ".repeat(indent)}- ${pointer}`]));
67733
+ fs10.writeFileSync(bodyFile, appendBody(src, within, (indent) => [`${" ".repeat(indent)}- ${pointer}`]));
67218
67734
  return { path: segsToStr(fileSegs), chapter: segsToStr(segs), pointer };
67219
67735
  }
67220
67736
  function pasteTextIntoChapter(dataRoot, s2, segs, text) {
67221
67737
  const { docSegs, bodyFile } = chapterSource(dataRoot, s2, segs);
67222
67738
  const within = segs.slice(docSegs.length);
67223
67739
  const src = fs10.readFileSync(bodyFile, "utf8");
67224
- fs10.writeFileSync(bodyFile, appendToList(src, within, "chunks", (indent) => textChunkLines(text, indent)));
67740
+ fs10.writeFileSync(bodyFile, appendBody(src, within, (indent) => textChunkLines(text, indent)));
67225
67741
  return { path: segsToStr(segs), chapter: segsToStr(segs) };
67226
67742
  }
67227
67743
  function pasteTextAsChapterFile(dataRoot, segs, text) {
@@ -67230,7 +67746,7 @@ function pasteTextAsChapterFile(dataRoot, segs, text) {
67230
67746
  const dir = path10.resolve(dataRoot, ...dirSegs.map(String));
67231
67747
  const title = titleFromText(text);
67232
67748
  const final = uniqueName(dir, chapterFileName(title));
67233
- const src = ["!!<*::yamlover:$defs:chapter>", `title: ${JSON.stringify(title)}`, "chunks:", ...textChunkLines(text, 0), ""].join("\n");
67749
+ const src = ["!!<*::yamlover:$defs:chapter>", `title: ${JSON.stringify(title)}`, ...textChunkLines(text, 0), ""].join("\n");
67234
67750
  writeInside(dataRoot, dir, final, Buffer.from(src, "utf8"));
67235
67751
  return { path: segsToStr([...dirSegs, final]), dir: segsToStr(dirSegs), open: dirSegs.length !== segs.length };
67236
67752
  }
@@ -67267,10 +67783,16 @@ function richItemLines(item, indent, pointerFor) {
67267
67783
  function richChildLines(node, indent, pointerFor) {
67268
67784
  const pad = " ".repeat(indent);
67269
67785
  const lines = [`${pad}- title: ${JSON.stringify(node.title)}`];
67270
- if (node.chunks.length) lines.push(`${pad} chunks:`, ...node.chunks.flatMap((c3) => richItemLines(c3, indent + 2, pointerFor)));
67271
- if (node.children.length) lines.push(`${pad} children:`, ...node.children.flatMap((k) => richChildLines(k, indent + 2, pointerFor)));
67786
+ for (const c3 of node.chunks) lines.push(...richItemLines(c3, indent + 2, pointerFor));
67787
+ for (const k of node.children) lines.push(...richChildLines(k, indent + 2, pointerFor));
67272
67788
  return lines;
67273
67789
  }
67790
+ function richBodyLines(rich, indent, pointerFor) {
67791
+ return [
67792
+ ...rich.chunks.flatMap((c3) => richItemLines(c3, indent, pointerFor)),
67793
+ ...rich.children.flatMap((k) => richChildLines(k, indent, pointerFor))
67794
+ ];
67795
+ }
67274
67796
  function pasteRichIntoChapter(dataRoot, s2, segs, rich) {
67275
67797
  const { docSegs, bodyFile, dirBacked } = chapterSource(dataRoot, s2, segs);
67276
67798
  const writeDirSegs = dirBacked ? docSegs : docSegs.slice(0, -1);
@@ -67284,8 +67806,7 @@ function pasteRichIntoChapter(dataRoot, s2, segs, rich) {
67284
67806
  };
67285
67807
  const within = segs.slice(docSegs.length);
67286
67808
  let src = fs10.readFileSync(bodyFile, "utf8");
67287
- if (rich.chunks.length) src = appendToList(src, within, "chunks", (ind) => rich.chunks.flatMap((c3) => richItemLines(c3, ind, pointerFor)));
67288
- if (rich.children.length) src = appendToList(src, within, "children", (ind) => rich.children.flatMap((k) => richChildLines(k, ind, pointerFor)));
67809
+ if (rich.chunks.length || rich.children.length) src = appendBody(src, within, (ind) => richBodyLines(rich, ind, pointerFor));
67289
67810
  fs10.writeFileSync(bodyFile, src);
67290
67811
  return { path: segsToStr(segs), chapter: segsToStr(segs), files };
67291
67812
  }
@@ -67318,9 +67839,7 @@ function pasteRichAsChapter(dataRoot, segs, rich) {
67318
67839
  return { path: segsToStr([...dirSegs, name]), dir: segsToStr(dirSegs), open: dirSegs.length !== segs.length };
67319
67840
  }
67320
67841
  function renderChapterSource(title, rich, pointerFor) {
67321
- const lines = ["!!<*::yamlover:$defs:chapter>", `title: ${JSON.stringify(title)}`];
67322
- if (rich.chunks.length) lines.push("chunks:", ...rich.chunks.flatMap((c3) => richItemLines(c3, 0, pointerFor)));
67323
- if (rich.children.length) lines.push("children:", ...rich.children.flatMap((k) => richChildLines(k, 0, pointerFor)));
67842
+ const lines = ["!!<*::yamlover:$defs:chapter>", `title: ${JSON.stringify(title)}`, ...richBodyLines(rich, 0, pointerFor)];
67324
67843
  return lines.join("\n") + "\n";
67325
67844
  }
67326
67845
  function richHasFiles(rich) {
@@ -67331,6 +67850,47 @@ function titleFromText(text) {
67331
67850
  const t3 = first.replace(/^#{1,6}\s+/, "").trim();
67332
67851
  return (t3.length > 80 ? t3.slice(0, 79).trimEnd() + "\u2026" : t3) || "Pasted text";
67333
67852
  }
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
+ function lastBodyChildPath(s2, parentSegs) {
67862
+ const positional = s2.entries(storePath(parentSegs)).filter((e3) => e3.kind === "contain" && e3.label == null);
67863
+ const last = positional[positional.length - 1];
67864
+ return last ? segsToStr(storePathToSegs(last.to)) : segsToStr([...parentSegs, 0]);
67865
+ }
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
+ function objectBaseName(title) {
67880
+ const base = title.replace(/[^\p{L}\p{N} ._-]+/gu, " ").replace(/\s+/g, " ").trim().slice(0, 60).trim().replace(/^\.+/, "");
67881
+ return base || "new";
67882
+ }
67883
+ function writeObject(dataRoot, dir, base, concrete, src) {
67884
+ if (concrete === "dir/yamlover") {
67885
+ const final2 = uniqueName(dir, base);
67886
+ fs10.mkdirSync(path10.join(dir, final2, ".yamlover"), { recursive: true });
67887
+ writeInside(dataRoot, path10.join(dir, final2, ".yamlover"), "body.yamlover", Buffer.from(src, "utf8"));
67888
+ return final2;
67889
+ }
67890
+ const final = uniqueName(dir, base + ".yamlover");
67891
+ writeInside(dataRoot, dir, final, Buffer.from(src, "utf8"));
67892
+ return final;
67893
+ }
67334
67894
  function chapterFileName(title) {
67335
67895
  const base = title.replace(/[^\p{L}\p{N} ._-]+/gu, " ").replace(/\s+/g, " ").trim().slice(0, 60).trim().replace(/^\.+/, "");
67336
67896
  return `${base || "pasted"}.yamlover`;
@@ -67365,6 +67925,24 @@ function loadAgentDocs() {
67365
67925
  if (names3.length === 0) throw new Error(`no agent-docs resources at ${AGENT_DOCS_DIR}`);
67366
67926
  return names3.map((name) => ({ name, content: fs10.readFileSync(path10.join(AGENT_DOCS_DIR, name), "utf8") }));
67367
67927
  }
67928
+ var DOC_BEGIN = "<!-- BEGIN yamlover agent guide (auto-managed by `npx yamlover` \u2014 regenerated on reinstall) -->";
67929
+ var DOC_END = "<!-- END yamlover agent guide -->";
67930
+ function mergeAgentDoc(existing, content) {
67931
+ const block = `${DOC_BEGIN}
67932
+ ${content.trimEnd()}
67933
+ ${DOC_END}
67934
+ `;
67935
+ if (existing === null) return { text: block, status: "created" };
67936
+ const b = existing.indexOf(DOC_BEGIN);
67937
+ if (b === -1) {
67938
+ const sep2 = existing.endsWith("\n\n") ? "" : existing.endsWith("\n") ? "\n" : "\n\n";
67939
+ return { text: existing + sep2 + block, status: "appended" };
67940
+ }
67941
+ const e3 = existing.indexOf(DOC_END, b);
67942
+ const end = e3 === -1 ? existing.length : e3 + DOC_END.length;
67943
+ const text = existing.slice(0, b) + block.trimEnd() + existing.slice(end);
67944
+ return { text, status: text === existing ? "exists" : "updated" };
67945
+ }
67368
67946
  var indentOf2 = (line) => {
67369
67947
  let i2 = 0;
67370
67948
  while (line[i2] === " ") i2++;
@@ -67382,76 +67960,218 @@ function textChunkLines(text, indent) {
67382
67960
  const head = text.endsWith("\n") ? "|" : "|-";
67383
67961
  return [`${pad}- ${head}`, ...body.split("\n").map((l2) => l2.trim().length ? `${pad} ${l2}` : "")];
67384
67962
  }
67385
- function appendToList(text, chapterPath, key, renderItems) {
67386
- const lines = text.split("\n");
67387
- let lo = 0;
67388
- let hi = lines.length;
67389
- let indent = firstContentIndent2(lines);
67390
- for (let i2 = 0; i2 < chapterPath.length; i2 += 2) {
67391
- const idx = Number(chapterPath[i2 + 1]);
67392
- const kids = findKeyLine2(lines, lo, hi, indent, "children");
67393
- if (kids < 0) throw new Error(`no 'children:' at indent ${indent}`);
67394
- const items = seqItems(lines, kids + 1, hi, indent);
67395
- if (!(idx >= 0 && idx < items.length)) throw new Error(`children[${idx}] out of range (${items.length})`);
67396
- hi = idx + 1 < items.length ? items[idx + 1] : seqEnd(lines, kids + 1, hi, indent);
67397
- lo = items[idx] + 1;
67398
- indent += 2;
67399
- }
67400
- const keyLine = findKeyLine2(lines, lo, hi, indent, key);
67401
- if (keyLine < 0) {
67402
- const end = trimBack2(lines, lo - 1, hi);
67403
- lines.splice(end, 0, `${" ".repeat(indent)}${key}:`, ...renderItems(indent));
67404
- } else {
67405
- const end = seqEnd(lines, keyLine + 1, hi, indent);
67406
- lines.splice(end, 0, ...renderItems(indent));
67963
+ function chapterEntries(lines, r2) {
67964
+ const starts = [];
67965
+ if (r2.marker >= 0) {
67966
+ const inline = lines[r2.marker].replace(/^\s*-\s*/, "");
67967
+ if (inline.trim()) starts.push({ key: /^-/.test(inline) ? null : inline.match(/^([^:\s]+):/)?.[1] ?? null, start: r2.marker, inline: true });
67407
67968
  }
67408
- return lines.join("\n");
67409
- }
67410
- function firstContentIndent2(lines) {
67411
- for (const l2 of lines) if (isContentLine2(l2)) return indentOf2(l2);
67412
- return 0;
67413
- }
67414
- function findKeyLine2(lines, lo, hi, indent, key) {
67415
- for (let i2 = lo; i2 < hi; i2++) {
67969
+ for (let i2 = r2.lo; i2 < r2.hi; i2++) {
67416
67970
  if (!isContentLine2(lines[i2])) continue;
67417
67971
  const ind = indentOf2(lines[i2]);
67418
- if (ind < indent) return -1;
67419
- if (ind !== indent) continue;
67972
+ if (ind < r2.indent) break;
67973
+ if (ind !== r2.indent) continue;
67420
67974
  const t3 = lines[i2].trim();
67421
- if (t3 === `${key}:` || t3.startsWith(`${key}:`)) return i2;
67975
+ if (t3.startsWith("!!<")) continue;
67976
+ starts.push({ key: t3 === "-" || t3.startsWith("- ") ? null : t3.match(/^([^:\s]+):/)?.[1] ?? null, start: i2, inline: false });
67977
+ }
67978
+ return starts.map((s2, k) => ({
67979
+ absIndex: k,
67980
+ key: s2.key,
67981
+ start: s2.start,
67982
+ end: k + 1 < starts.length ? starts[k + 1].start : trimBack2(lines, s2.start, r2.hi),
67983
+ inline: s2.inline
67984
+ }));
67985
+ }
67986
+ function bodyItems(lines, r2) {
67987
+ return chapterEntries(lines, r2).filter((e3) => e3.key === null);
67988
+ }
67989
+ function reachChapter(lines, chapterPath) {
67990
+ let r2 = { lo: 0, hi: lines.length, indent: firstContentIndent2(lines), marker: -1 };
67991
+ for (const seg of chapterPath) {
67992
+ const idx = Number(seg);
67993
+ const item = chapterEntries(lines, r2)[idx];
67994
+ if (!item || item.key !== null) throw new Error(`no subchapter at [${idx}]`);
67995
+ r2 = { lo: item.start + 1, hi: item.end, indent: r2.indent + 2, marker: item.start };
67996
+ }
67997
+ return r2;
67998
+ }
67999
+ function bodyAppendPoint(lines, r2) {
68000
+ const entries = chapterEntries(lines, r2);
68001
+ const items = entries.filter((e3) => e3.key === null);
68002
+ if (items.length) return items[items.length - 1].end;
68003
+ if (entries.length) return entries[entries.length - 1].end;
68004
+ return r2.marker >= 0 ? r2.marker + 1 : trimBack2(lines, r2.lo - 1, r2.hi);
68005
+ }
68006
+ function appendBody(text, chapterPath, renderItems) {
68007
+ const lines = text.split("\n");
68008
+ const r2 = reachChapter(lines, chapterPath);
68009
+ lines.splice(bodyAppendPoint(lines, r2), 0, ...renderItems(r2.indent));
68010
+ return lines.join("\n");
68011
+ }
68012
+ function bodyItemHead(lines, r2, rank) {
68013
+ const items = bodyItems(lines, r2);
68014
+ if (!(rank >= 0 && rank < items.length)) throw new Error(`body[${rank}] out of range (${items.length})`);
68015
+ return lines[items[rank].start].trim().replace(/^-\s*/, "");
68016
+ }
68017
+ function setScalarKey(lines, r2, key, value) {
68018
+ const entry = chapterEntries(lines, r2).find((e3) => e3.key === key);
68019
+ if (entry?.inline) {
68020
+ const pad3 = " ".repeat(indentOf2(lines[entry.start]));
68021
+ lines[entry.start] = `${pad3}- ${key}: ${JSON.stringify(value)}`;
68022
+ return;
67422
68023
  }
67423
- return -1;
68024
+ const pad = " ".repeat(r2.indent);
68025
+ if (!value) {
68026
+ if (entry) lines.splice(entry.start, 1);
68027
+ return;
68028
+ }
68029
+ const rendered = `${pad}${key}: ${JSON.stringify(value)}`;
68030
+ if (entry) lines.splice(entry.start, 1, rendered);
68031
+ else lines.splice(r2.marker >= 0 ? r2.marker + 1 : trimBack2(lines, r2.lo - 1, r2.hi), 0, rendered);
67424
68032
  }
67425
- function seqItems(lines, from, hi, indent) {
67426
- const out = [];
67427
- for (let i2 = from; i2 < hi; i2++) {
68033
+ function replaceBodyItem(lines, r2, rank, text) {
68034
+ const items = bodyItems(lines, r2);
68035
+ if (!(rank >= 0 && rank < items.length)) throw new Error(`body[${rank}] out of range (${items.length})`);
68036
+ const { start, end } = items[rank];
68037
+ const head = lines[start].trim().replace(/^-\s*/, "");
68038
+ const tag = head.match(/^(!!<[^>]*>)/)?.[1];
68039
+ const rendered = tag ? taggedChunkLines(text, r2.indent, tag) : textChunkLines(text, r2.indent);
68040
+ lines.splice(start, end - start, ...rendered);
68041
+ }
68042
+ function insertBodyItem(lines, r2, rank, text) {
68043
+ const items = bodyItems(lines, r2);
68044
+ const at = rank < items.length ? items[rank].start : bodyAppendPoint(lines, r2);
68045
+ lines.splice(at, 0, ...textChunkLines(text, r2.indent));
68046
+ }
68047
+ function removeBodyItem(lines, r2, rank) {
68048
+ const items = bodyItems(lines, r2);
68049
+ if (!(rank >= 0 && rank < items.length)) throw new Error(`body[${rank}] out of range (${items.length})`);
68050
+ const { start, end } = items[rank];
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");
68066
+ }
68067
+ function reachChapterItem(lines, indices) {
68068
+ const parent = reachChapter(lines, indices.slice(0, -1));
68069
+ const idx = indices[indices.length - 1];
68070
+ const item = chapterEntries(lines, parent)[idx];
68071
+ if (!item || item.key !== null) throw new Error(`no chapter body item at [${idx}]`);
68072
+ return { parent, item, itemIndent: parent.indent };
68073
+ }
68074
+ function itemHasFields(lines, item, fieldIndent) {
68075
+ for (let i2 = item.start + 1; i2 < item.end; i2++) {
67428
68076
  if (!isContentLine2(lines[i2])) continue;
67429
68077
  const ind = indentOf2(lines[i2]);
67430
- if (ind < indent) break;
67431
- if (ind !== indent) continue;
67432
- const t3 = lines[i2].trim();
67433
- if (t3 === "-" || t3.startsWith("- ")) out.push(i2);
67434
- else break;
68078
+ if (ind < fieldIndent) break;
68079
+ if (ind === fieldIndent && /^[^\s-][^:]*:(\s|$)/.test(lines[i2].trim())) return true;
67435
68080
  }
67436
- return out;
68081
+ return false;
67437
68082
  }
67438
- function seqEnd(lines, from, hi, indent) {
67439
- let last = from;
67440
- for (let i2 = from; i2 < hi; i2++) {
67441
- if (!isContentLine2(lines[i2])) continue;
67442
- const ind = indentOf2(lines[i2]);
67443
- if (ind < indent) return trimBack2(lines, last, i2);
67444
- if (ind === indent) {
67445
- const t3 = lines[i2].trim();
67446
- if (t3 === "-" || t3.startsWith("- ")) {
67447
- last = i2;
67448
- continue;
67449
- }
67450
- return trimBack2(lines, last, i2);
67451
- }
67452
- last = i2;
68083
+ function convertChunkToOmni(lines, item, itemIndent) {
68084
+ const head = lines[item.start].slice(itemIndent).replace(/^-\s*/, "");
68085
+ const tagMatch = head.match(/^(!!<[^>]*>)\s*/);
68086
+ const tag = tagMatch ? tagMatch[1] + " " : "";
68087
+ const rest = tagMatch ? head.slice(tagMatch[0].length) : head;
68088
+ if (/^[|>][+-]?\d*$/.test(rest.trim())) {
68089
+ for (let i2 = item.start + 1; i2 < item.end; i2++) if (lines[i2].trim().length) lines[i2] = " " + lines[i2];
68090
+ return;
67453
68091
  }
67454
- return trimBack2(lines, last, hi);
68092
+ const value = rest.startsWith('"') ? String(JSON.parse(rest)) : rest;
68093
+ const pad = " ".repeat(itemIndent);
68094
+ const chomp = value.endsWith("\n") ? "|" : "|-";
68095
+ const clean = value.endsWith("\n") ? value.slice(0, -1) : value;
68096
+ lines.splice(item.start, item.end - item.start, `${pad}- ${tag}${chomp}`, ...clean.split("\n").map((l2) => l2.trim() ? `${pad} ${l2}` : ""));
68097
+ }
68098
+ function chunkFieldRegion(lines, indices, ensureOmni) {
68099
+ const { item, itemIndent } = reachChapterItem(lines, indices);
68100
+ const fieldIndent = itemIndent + 2;
68101
+ if (ensureOmni && !itemHasFields(lines, item, fieldIndent)) convertChunkToOmni(lines, item, itemIndent);
68102
+ const { item: cur } = reachChapterItem(lines, indices);
68103
+ return { lo: cur.start + 1, hi: cur.end, indent: fieldIndent };
68104
+ }
68105
+ function collapseChunkOmni(lines, indices) {
68106
+ const { item, itemIndent } = reachChapterItem(lines, indices);
68107
+ if (itemHasFields(lines, item, itemIndent + 2)) return;
68108
+ for (let i2 = item.start + 1; i2 < item.end; i2++) {
68109
+ if (lines[i2].trim().length && indentOf2(lines[i2]) >= itemIndent + 2) lines[i2] = lines[i2].slice(2);
68110
+ }
68111
+ }
68112
+ function assertProseChunk(lines, indices) {
68113
+ const { item } = reachChapterItem(lines, indices);
68114
+ const head = lines[item.start].slice(indentOf2(lines[item.start])).replace(/^-\s*/, "");
68115
+ if (head.startsWith("*")) throw new Error("cannot tag a file/pointer chunk's text");
68116
+ const tag = head.match(/^!!<([^>]*)>/)?.[1];
68117
+ if (tag && !/text\/(markdown|marklower|x-latex)/.test(tag)) throw new Error("cannot tag a non-text chunk's text");
68118
+ }
68119
+ function isChunkTarget(s2, segs) {
68120
+ const within = segs.slice(documentRootSegs(s2, segs).length);
68121
+ return within.length > 0 && typeof within[0] === "number";
68122
+ }
68123
+ function splitChunkWithin(within) {
68124
+ let i2 = 0;
68125
+ while (i2 < within.length && typeof within[i2] === "number") i2++;
68126
+ return { indices: within.slice(0, i2).map(Number), keys: within.slice(i2).map(String) };
68127
+ }
68128
+ function editChapterSource(src, within, op, text, index) {
68129
+ const lines = src.split("\n");
68130
+ if (op === "set") {
68131
+ const key = within[within.length - 1];
68132
+ if (key !== "title" && key !== "description") throw new Error("`set` needs a title/description target");
68133
+ setScalarKey(lines, reachChapter(lines, within.slice(0, -1)), key, text);
68134
+ return lines.join("\n");
68135
+ }
68136
+ if (op === "insert") {
68137
+ insertBodyItem(lines, reachChapter(lines, within), index ?? Number.MAX_SAFE_INTEGER, text);
68138
+ return lines.join("\n");
68139
+ }
68140
+ const rank = within[within.length - 1];
68141
+ if (typeof rank !== "number") throw new Error(`\`${op}\` needs a body-element target (path ends \`[rank]\`)`);
68142
+ const region = reachChapter(lines, within.slice(0, -1));
68143
+ if (op === "replace") {
68144
+ assertProseBodyItem(lines, region, rank);
68145
+ replaceBodyItem(lines, region, rank, text);
68146
+ } else if (op === "remove") {
68147
+ removeBodyItem(lines, region, rank);
68148
+ } else {
68149
+ throw new Error(`unknown edit op: ${op}`);
68150
+ }
68151
+ return lines.join("\n");
68152
+ }
68153
+ function applyEdits2(dataRoot, s2, edits) {
68154
+ const byFile = /* @__PURE__ */ new Map();
68155
+ for (const e3 of edits) {
68156
+ const editSegs = strToSegs(e3.path ?? "");
68157
+ const { docSegs, bodyFile } = chapterSource(dataRoot, s2, editSegs);
68158
+ const within = editSegs.slice(docSegs.length);
68159
+ const list = byFile.get(bodyFile) ?? [];
68160
+ list.push({ within, op: String(e3.op ?? ""), text: String(e3.text ?? ""), index: typeof e3.index === "number" ? e3.index : void 0 });
68161
+ byFile.set(bodyFile, list);
68162
+ }
68163
+ const touched = [];
68164
+ for (const [bodyFile, ops] of byFile) {
68165
+ let src = fs10.readFileSync(bodyFile, "utf8");
68166
+ for (const o2 of ops) src = editChapterSource(src, o2.within, o2.op, o2.text, o2.index);
68167
+ fs10.writeFileSync(bodyFile, src);
68168
+ touched.push(bodyFile);
68169
+ }
68170
+ return touched;
68171
+ }
68172
+ function firstContentIndent2(lines) {
68173
+ for (const l2 of lines) if (isContentLine2(l2)) return indentOf2(l2);
68174
+ return 0;
67455
68175
  }
67456
68176
  function trimBack2(lines, lastItemLine, end) {
67457
68177
  let e3 = end;
@@ -67483,9 +68203,15 @@ function documentPath(s2, segs) {
67483
68203
  return segsToStr(documentRootSegs(s2, segs));
67484
68204
  }
67485
68205
  function titleOf(s2, p2) {
67486
- const titlePath = (p2 === ":" ? "" : p2) + ":title";
67487
- const t3 = s2.node(titlePath);
67488
- if (t3 && t3.type === "scalar" && !s2.hasChildren(titlePath) && t3.value != null) return String(t3.value);
68206
+ return scalarKeyOf(s2, p2, "title");
68207
+ }
68208
+ function descriptionOf(s2, p2) {
68209
+ return scalarKeyOf(s2, p2, "description");
68210
+ }
68211
+ function scalarKeyOf(s2, p2, key) {
68212
+ const kp = (p2 === ":" ? "" : p2) + ":" + key;
68213
+ const t3 = s2.node(kp);
68214
+ if (t3 && t3.type === "scalar" && !s2.hasChildren(kp) && t3.value != null) return String(t3.value);
67489
68215
  return null;
67490
68216
  }
67491
68217
  var PATH_TOKEN = /\[\d+\]|[^:\[\]]+/g;
@@ -67533,9 +68259,22 @@ function formatFromExt(file) {
67533
68259
  return EXT_CT[path10.extname(file).toLowerCase()] ?? null;
67534
68260
  }
67535
68261
  function parseDepth(raw) {
67536
- if (raw == null || raw === "") return null;
68262
+ if (raw == null || raw === "") return void 0;
68263
+ if (raw === ".inf" || raw === "inf") return Infinity;
67537
68264
  const n2 = Number(raw);
67538
- return Number.isInteger(n2) && n2 >= 0 ? n2 : null;
68265
+ return Number.isInteger(n2) && n2 >= 0 ? n2 : void 0;
68266
+ }
68267
+ function defaultDepth(s2, dataRoot, segs, row, kind) {
68268
+ if (kind === "binary") return 1;
68269
+ return isDirConcrete(concreteOf(s2, dataRoot, segs, row)) ? 1 : Infinity;
68270
+ }
68271
+ function refMarker(text, path11) {
68272
+ return { [REF_KEY]: { text, path: path11 } };
68273
+ }
68274
+ function binaryValueMarker(segs, row) {
68275
+ const info = { kind: "binary", type: "blob", path: segsToStr(segs), size: row.size };
68276
+ if (row.format) info.format = row.format;
68277
+ return { [LINK_KEY]: info };
67539
68278
  }
67540
68279
  function clampThumbDim(raw, def) {
67541
68280
  const n2 = raw == null ? NaN : Math.round(Number(raw));
@@ -67550,7 +68289,8 @@ function notFound(res, url) {
67550
68289
  sendJson(res, 404, { error: `no such node/endpoint: ${url.pathname}?${url.searchParams}` });
67551
68290
  }
67552
68291
  export {
67553
- createHandlers
68292
+ createHandlers,
68293
+ mergeAgentDoc
67554
68294
  };
67555
68295
  /*! Bundled license information:
67556
68296