yaml 3.0.0-0 → 3.0.0-1

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.
@@ -1,104 +1,5 @@
1
- //#region src/doc/applyReviver.ts
2
- /**
3
- * Applies the JSON.parse reviver algorithm as defined in the ECMA-262 spec,
4
- * in section 24.5.1.1 "Runtime Semantics: InternalizeJSONProperty" of the
5
- * 2021 edition: https://tc39.es/ecma262/#sec-json.parse
6
- *
7
- * Includes extensions for handling Map and Set objects.
8
- */
9
- function applyReviver(reviver, obj, key, val) {
10
- if (val && typeof val === "object") if (Array.isArray(val)) for (let i = 0, len = val.length; i < len; ++i) {
11
- const v0 = val[i];
12
- const v1 = applyReviver(reviver, val, String(i), v0);
13
- if (v1 === void 0) delete val[i];
14
- else if (v1 !== v0) val[i] = v1;
15
- }
16
- else if (val instanceof Map) for (const k of Array.from(val.keys())) {
17
- const v0 = val.get(k);
18
- const v1 = applyReviver(reviver, val, k, v0);
19
- if (v1 === void 0) val.delete(k);
20
- else if (v1 !== v0) val.set(k, v1);
21
- }
22
- else if (val instanceof Set) for (const v0 of Array.from(val)) {
23
- const v1 = applyReviver(reviver, val, v0, v0);
24
- if (v1 === void 0) val.delete(v0);
25
- else if (v1 !== v0) {
26
- val.delete(v0);
27
- val.add(v1);
28
- }
29
- }
30
- else for (const [k, v0] of Object.entries(val)) {
31
- const v1 = applyReviver(reviver, val, k, v0);
32
- if (v1 === void 0) delete val[k];
33
- else if (v1 !== v0) val[k] = v1;
34
- }
35
- return reviver.call(obj, key, val);
36
- }
37
-
38
- //#endregion
39
- //#region src/nodes/toJS.ts
40
- /**
41
- * Recursively convert any node or its contents to native JavaScript
42
- *
43
- * @param value - The input value
44
- * @param arg - If `value` defines a `toJSON()` method, use this
45
- * as its first argument
46
- * @param ctx - Conversion context, originally set in Document#toJS(). If
47
- * `{ keep: true }` is not set, output should be suitable for JSON
48
- * stringification.
49
- */
50
- function toJS(value, arg, ctx) {
51
- if (Array.isArray(value)) return value.map((v, i) => toJS(v, String(i), ctx));
52
- if (value && typeof value.toJSON === "function") {
53
- const node = value;
54
- if (!ctx || !(node instanceof NodeBase) || !node.anchor) return value.toJSON(arg, ctx);
55
- const data = {
56
- aliasCount: 0,
57
- count: 1,
58
- res: void 0
59
- };
60
- ctx.anchors.set(node, data);
61
- ctx.onCreate = (res) => {
62
- data.res = res;
63
- delete ctx.onCreate;
64
- };
65
- const res = node.toJSON(arg, ctx);
66
- if (ctx.onCreate) ctx.onCreate(res);
67
- return res;
68
- }
69
- if (typeof value === "bigint" && !ctx?.keep) return Number(value);
70
- return value;
71
- }
72
-
73
- //#endregion
74
- //#region src/nodes/Node.ts
75
- var NodeBase = class {
76
- /** Create a copy of this node. */
77
- clone(_schema) {
78
- const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
79
- if (this.range) copy.range = this.range.slice();
80
- return copy;
81
- }
82
- /** A plain JavaScript representation of this node. */
83
- toJS(doc, { mapAsMap, maxAliasCount, onAnchor, reviver } = {}) {
84
- if (!doc?.schema) throw new TypeError("A document argument is required");
85
- const ctx = {
86
- anchors: /* @__PURE__ */ new Map(),
87
- doc,
88
- keep: true,
89
- mapAsMap: mapAsMap === true,
90
- mapKeyWarned: false,
91
- maxAliasCount: typeof maxAliasCount === "number" ? maxAliasCount : 100
92
- };
93
- const res = toJS(this, "", ctx);
94
- if (typeof onAnchor === "function") for (const { count, res } of ctx.anchors.values()) onAnchor(res, count);
95
- return typeof reviver === "function" ? applyReviver(reviver, { "": res }, "", res) : res;
96
- }
97
- };
98
-
99
- //#endregion
100
1
  //#region src/nodes/Scalar.ts
101
- var Scalar = class extends NodeBase {
2
+ var Scalar = class {
102
3
  static BLOCK_FOLDED = "BLOCK_FOLDED";
103
4
  static BLOCK_LITERAL = "BLOCK_LITERAL";
104
5
  static PLAIN = "PLAIN";
@@ -106,17 +7,27 @@ var Scalar = class extends NodeBase {
106
7
  static QUOTE_SINGLE = "QUOTE_SINGLE";
107
8
  value;
108
9
  constructor(value) {
109
- super();
110
10
  this.value = value;
111
11
  }
112
- toJSON(arg, ctx) {
113
- return ctx?.keep ? this.value : toJS(this.value, arg, ctx);
12
+ /** Create a copy of this node. */
13
+ clone() {
14
+ const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
15
+ if (this.range) copy.range = [...this.range];
16
+ return copy;
17
+ }
18
+ /** A plain JavaScript representation of this node. */
19
+ toJS(_doc, ctx) {
20
+ if (ctx && this.anchor) ctx.anchors.set(this, {
21
+ aliasCount: 0,
22
+ count: 1,
23
+ res: this.value
24
+ });
25
+ return this.value;
114
26
  }
115
27
  toString() {
116
28
  return String(this.value);
117
29
  }
118
30
  };
119
-
120
31
  //#endregion
121
32
  //#region src/stringify/foldFlowLines.ts
122
33
  const FOLD_FLOW = "flow";
@@ -143,12 +54,12 @@ function foldFlowLines(text, indent, mode = "flow", { indentAtStart, lineWidth =
143
54
  let i = -1;
144
55
  let escStart = -1;
145
56
  let escEnd = -1;
146
- if (mode === FOLD_BLOCK) {
57
+ if (mode === "block") {
147
58
  i = consumeMoreIndentedLines(text, i, indent.length);
148
59
  if (i !== -1) end = i + endStep;
149
60
  }
150
61
  for (let ch; ch = text[i += 1];) {
151
- if (mode === FOLD_QUOTED && ch === "\\") {
62
+ if (mode === "quoted" && ch === "\\") {
152
63
  escStart = i;
153
64
  switch (text[i + 1]) {
154
65
  case "x":
@@ -165,7 +76,7 @@ function foldFlowLines(text, indent, mode = "flow", { indentAtStart, lineWidth =
165
76
  escEnd = i;
166
77
  }
167
78
  if (ch === "\n") {
168
- if (mode === FOLD_BLOCK) i = consumeMoreIndentedLines(text, i, indent.length);
79
+ if (mode === "block") i = consumeMoreIndentedLines(text, i, indent.length);
169
80
  end = i + indent.length + endStep;
170
81
  split = void 0;
171
82
  } else {
@@ -177,7 +88,7 @@ function foldFlowLines(text, indent, mode = "flow", { indentAtStart, lineWidth =
177
88
  folds.push(split);
178
89
  end = split + endStep;
179
90
  split = void 0;
180
- } else if (mode === FOLD_QUOTED) {
91
+ } else if (mode === "quoted") {
181
92
  while (prev === " " || prev === " ") {
182
93
  prev = ch;
183
94
  ch = text[i += 1];
@@ -202,7 +113,7 @@ function foldFlowLines(text, indent, mode = "flow", { indentAtStart, lineWidth =
202
113
  const end = folds[i + 1] || text.length;
203
114
  if (fold === 0) res = `\n${indent}${text.slice(0, end)}`;
204
115
  else {
205
- if (mode === FOLD_QUOTED && escapedFolds[fold]) res += `${text[fold]}\\`;
116
+ if (mode === "quoted" && escapedFolds[fold]) res += `${text[fold]}\\`;
206
117
  res += `\n${indent}${text.slice(fold + 1, end)}`;
207
118
  }
208
119
  }
@@ -227,7 +138,6 @@ function consumeMoreIndentedLines(text, i, indent) {
227
138
  }
228
139
  return end;
229
140
  }
230
-
231
141
  //#endregion
232
142
  //#region src/stringify/stringifyString.ts
233
143
  const getFoldOptions = (ctx, isBlock) => ({
@@ -447,7 +357,6 @@ function stringifyString(item, ctx, onComment, onChompKeep) {
447
357
  }
448
358
  return res;
449
359
  }
450
-
451
360
  //#endregion
452
361
  //#region src/doc/anchors.ts
453
362
  /**
@@ -476,7 +385,6 @@ function findNewAnchor(prefix, exclude) {
476
385
  if (!exclude.has(name)) return name;
477
386
  }
478
387
  }
479
-
480
388
  //#endregion
481
389
  //#region src/doc/NodeCreator.ts
482
390
  const defaultTagPrefix = "tag:yaml.org,2002:";
@@ -484,7 +392,6 @@ var NodeCreator = class {
484
392
  keepUndefined;
485
393
  replacer;
486
394
  schema;
487
- #aliasDuplicateObjects;
488
395
  #anchorPrefix;
489
396
  #aliasObjects = [];
490
397
  #doc;
@@ -497,24 +404,19 @@ var NodeCreator = class {
497
404
  this.replacer = replacer;
498
405
  this.#flow = options.flow ?? false;
499
406
  this.#onTagObj = options.onTagObj;
500
- this.#aliasDuplicateObjects = options.aliasDuplicateObjects ?? true;
501
407
  this.#anchorPrefix = options.anchorPrefix || "a";
502
408
  if (docOrSchema instanceof Document) {
503
- this.#doc = docOrSchema;
409
+ if (options.aliasDuplicateObjects ?? true) this.#doc = docOrSchema;
504
410
  this.schema = docOrSchema.schema;
505
411
  } else this.schema = docOrSchema;
506
412
  }
507
413
  create(value, tagName) {
508
414
  if (value instanceof Document) value = value.value;
509
- if (value instanceof NodeBase) return value;
510
- if (value instanceof Pair) {
511
- const map = this.schema.map.nodeClass.from(this, null);
512
- map.items.push(value);
513
- return map;
514
- }
415
+ if (isNode(value)) return value;
416
+ if (value instanceof Pair) return this.schema.map.createNode(this, null).set(value);
515
417
  if (value instanceof String || value instanceof Number || value instanceof Boolean || typeof BigInt !== "undefined" && value instanceof BigInt) value = value.valueOf();
516
418
  let ref = void 0;
517
- if (this.#aliasDuplicateObjects && value && typeof value === "object") {
419
+ if (this.#doc && value && typeof value === "object") {
518
420
  ref = this.#sourceObjects.get(value);
519
421
  if (ref) {
520
422
  if (!ref.anchor) {
@@ -552,11 +454,11 @@ var NodeCreator = class {
552
454
  this.#onTagObj(tagObj);
553
455
  this.#onTagObj = void 0;
554
456
  }
555
- const node = tagObj?.createNode?.(this, value) ?? tagObj?.nodeClass?.from?.(this, value) ?? new Scalar(value);
457
+ const node = tagObj?.createNode?.(this, value) ?? new Scalar(value);
556
458
  if (tagName) node.tag = tagName;
557
459
  else if (!tagObj.default) node.tag = tagObj.tag;
558
460
  if (ref) ref.node = node;
559
- if (this.#flow && node instanceof Collection) node.flow = true;
461
+ if (this.#flow && isCollection(node)) node.flow = true;
560
462
  return node;
561
463
  }
562
464
  createPair(key, value) {
@@ -570,109 +472,11 @@ var NodeCreator = class {
570
472
  setAnchors() {
571
473
  for (const source of this.#aliasObjects) {
572
474
  const ref = this.#sourceObjects.get(source);
573
- if (typeof ref === "object" && ref.anchor && (ref.node instanceof Scalar || ref.node instanceof Collection)) ref.node.anchor = ref.anchor;
574
- else throw Object.assign(new Error("Failed to resolve repeated object (this should not happen)"), { source });
475
+ if (typeof ref === "object" && ref.anchor && (ref.node instanceof Scalar || isCollection(ref.node))) ref.node.anchor = ref.anchor;
476
+ else throw Object.assign(/* @__PURE__ */ new Error("Failed to resolve repeated object (this should not happen)"), { source });
575
477
  }
576
478
  }
577
479
  };
578
-
579
- //#endregion
580
- //#region src/nodes/Collection.ts
581
- function collectionFromPath(schema, path, value) {
582
- let v = value;
583
- for (let i = path.length - 1; i >= 0; --i) {
584
- const k = path[i];
585
- if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
586
- const a = [];
587
- a[k] = v;
588
- v = a;
589
- } else v = new Map([[k, v]]);
590
- }
591
- return new NodeCreator(schema, { aliasDuplicateObjects: false }).create(v);
592
- }
593
- var Collection = class Collection extends NodeBase {
594
- schema;
595
- constructor(schema) {
596
- super();
597
- Object.defineProperty(this, "schema", {
598
- value: schema,
599
- configurable: true,
600
- enumerable: false,
601
- writable: true
602
- });
603
- }
604
- /**
605
- * Create a copy of this collection.
606
- *
607
- * @param schema - If defined, overwrites the original's schema
608
- */
609
- clone(schema) {
610
- const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
611
- if (schema) copy.schema = schema;
612
- copy.items = copy.items.map((it) => it.clone(schema));
613
- if (this.range) copy.range = this.range.slice();
614
- return copy;
615
- }
616
- /**
617
- * Adds a value to the collection.
618
- *
619
- * For `!!map` and `!!omap` the value must be a Pair instance.
620
- */
621
- addIn(path, value) {
622
- if (!path.length) this.add(value);
623
- else {
624
- const [key, ...rest] = path;
625
- const node = this.get(key);
626
- if (node instanceof Collection) node.addIn(rest, value);
627
- else if (node === void 0 && this.schema) this.set(key, collectionFromPath(this.schema, rest, value));
628
- else throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
629
- }
630
- }
631
- /**
632
- * Removes a value from the collection.
633
- *
634
- * @returns `true` if the item was found and removed.
635
- */
636
- deleteIn(path) {
637
- const [key, ...rest] = path;
638
- if (rest.length === 0) return this.delete(key);
639
- const node = this.get(key);
640
- if (node instanceof Collection) return node.deleteIn(rest);
641
- else throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
642
- }
643
- /**
644
- * Returns item at `key`, or `undefined` if not found.
645
- */
646
- getIn(path) {
647
- const [key, ...rest] = path;
648
- const node = this.get(key);
649
- if (rest.length === 0) return node;
650
- else return node instanceof Collection ? node.getIn(rest) : void 0;
651
- }
652
- /**
653
- * Checks if the collection includes a value with the key `key`.
654
- */
655
- hasIn(path) {
656
- const [key, ...rest] = path;
657
- if (rest.length === 0) return this.has(key);
658
- const node = this.get(key);
659
- return node instanceof Collection ? node.hasIn(rest) : false;
660
- }
661
- /**
662
- * Sets a value in this collection.
663
- */
664
- setIn(path, value) {
665
- const [key, ...rest] = path;
666
- if (rest.length === 0) this.set(key, value);
667
- else {
668
- const node = this.get(key);
669
- if (node instanceof Collection) node.setIn(rest, value);
670
- else if (node === void 0 && this.schema) this.set(key, collectionFromPath(this.schema, rest, value));
671
- else throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
672
- }
673
- }
674
- };
675
-
676
480
  //#endregion
677
481
  //#region src/stringify/stringifyComment.ts
678
482
  /**
@@ -688,9 +492,49 @@ function indentComment(comment, indent) {
688
492
  return indent ? comment.replace(/^(?! *$)/gm, indent) : comment;
689
493
  }
690
494
  const lineComment = (str, indent, comment) => str.endsWith("\n") ? indentComment(comment, indent) : comment.includes("\n") ? "\n" + indentComment(comment, indent) : (str.endsWith(" ") ? "" : " ") + comment;
691
-
495
+ //#endregion
496
+ //#region src/log.ts
497
+ function debug(logLevel, ...messages) {
498
+ if (logLevel === "debug") console.log(...messages);
499
+ }
500
+ function warn(logLevel, warning) {
501
+ if (logLevel === "debug" || logLevel === "warn") if (typeof process !== "undefined" && typeof process.emitWarning === "function") process.emitWarning(warning);
502
+ else console.warn(warning);
503
+ }
504
+ //#endregion
505
+ //#region src/schema/yaml-1.1/merge.ts
506
+ const MERGE_KEY = "<<";
507
+ const merge = {
508
+ identify: (value) => value === MERGE_KEY || typeof value === "symbol" && value.description === MERGE_KEY,
509
+ default: "key",
510
+ tag: "tag:yaml.org,2002:merge",
511
+ test: /^<<$/,
512
+ resolve: () => Object.assign(new Scalar(Symbol(MERGE_KEY)), { addToJSMap: addMergeToJSMap }),
513
+ stringify: () => MERGE_KEY
514
+ };
515
+ const isMergeKey = (doc, key) => (merge.identify(key) || key instanceof Scalar && (!key.type || key.type === Scalar.PLAIN) && merge.identify(key.value)) && Boolean(doc.schema.tags.some((tag) => tag.tag === merge.tag && tag.default));
516
+ function addMergeToJSMap(doc, ctx, map, value) {
517
+ value = ctx && value instanceof Alias ? value.resolve(doc, ctx) : value;
518
+ if (Array.isArray(value) && !(value instanceof YAMLMap)) for (const it of value) mergeValue(doc, ctx, map, it);
519
+ else mergeValue(doc, ctx, map, value);
520
+ }
521
+ function mergeValue(doc, ctx, map, value) {
522
+ const srcMap = (value instanceof Alias ? value.resolve(doc, ctx) : value).toJS(doc, ctx, Map);
523
+ if (!(srcMap instanceof Map)) throw new Error("Merge sources must be maps or map aliases");
524
+ for (const [key, value] of srcMap) if (map instanceof Map) {
525
+ if (!map.has(key)) map.set(key, value);
526
+ } else if (map instanceof Set) map.add(key);
527
+ else if (!Object.prototype.hasOwnProperty.call(map, key)) Object.defineProperty(map, key, {
528
+ value,
529
+ writable: true,
530
+ enumerable: true,
531
+ configurable: true
532
+ });
533
+ return map;
534
+ }
692
535
  //#endregion
693
536
  //#region src/stringify/stringify.ts
537
+ const sortMapEntriesByKey = (a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
694
538
  function createStringifyContext(doc, options) {
695
539
  const opt = Object.assign({
696
540
  blockQuote: true,
@@ -708,6 +552,8 @@ function createStringifyContext(doc, options) {
708
552
  nullStr: "null",
709
553
  simpleKeys: false,
710
554
  singleQuote: null,
555
+ sortMapEntries: false,
556
+ trailingComma: false,
711
557
  trueStr: "true",
712
558
  verifyAliasOrder: true
713
559
  }, doc.schema.toStringOptions, options);
@@ -721,6 +567,7 @@ function createStringifyContext(doc, options) {
721
567
  break;
722
568
  default: inFlow = null;
723
569
  }
570
+ const sortMapEntries = typeof opt.sortMapEntries === "function" ? opt.sortMapEntries : opt.sortMapEntries === true ? sortMapEntriesByKey : null;
724
571
  return {
725
572
  anchors: /* @__PURE__ */ new Set(),
726
573
  doc,
@@ -728,7 +575,8 @@ function createStringifyContext(doc, options) {
728
575
  indent: "",
729
576
  indentStep: typeof opt.indent === "number" ? " ".repeat(opt.indent) : " ",
730
577
  inFlow,
731
- options: opt
578
+ options: opt,
579
+ sortMapEntries
732
580
  };
733
581
  }
734
582
  function getTagObject(tags, item) {
@@ -759,7 +607,7 @@ function getTagObject(tags, item) {
759
607
  function stringifyProps(node, tagObj, { anchors, doc }) {
760
608
  if (!doc.directives) return "";
761
609
  const props = [];
762
- const anchor = (node instanceof Scalar || node instanceof Collection) && node.anchor;
610
+ const anchor = node.anchor;
763
611
  if (anchor && anchorIsValid(anchor)) {
764
612
  anchors.add(anchor);
765
613
  props.push(`&${anchor}`);
@@ -768,19 +616,17 @@ function stringifyProps(node, tagObj, { anchors, doc }) {
768
616
  if (tag) props.push(doc.directives.tagString(tag));
769
617
  return props.join(" ");
770
618
  }
771
- function stringify(item, ctx, onComment, onChompKeep) {
772
- if (item instanceof Pair) return item.toString(ctx, onComment, onChompKeep);
773
- if (item instanceof Alias) {
774
- if (ctx.doc.directives) return item.toString(ctx);
775
- if (ctx.resolvedAliases?.has(item)) throw new TypeError(`Cannot stringify circular structure without alias nodes`);
776
- else {
777
- if (ctx.resolvedAliases) ctx.resolvedAliases.add(item);
778
- else ctx.resolvedAliases = new Set([item]);
779
- item = item.resolve(ctx.doc);
780
- }
619
+ function stringify(node, ctx, onComment, onChompKeep) {
620
+ if (node instanceof Pair) return node.toString(ctx, onComment, onChompKeep);
621
+ if (node instanceof Alias) {
622
+ if (ctx.doc.directives) return node.toString(ctx);
623
+ if (ctx.resolvedAliases?.has(node)) throw new TypeError("Cannot stringify circular structure without alias nodes");
624
+ if (ctx.resolvedAliases) ctx.resolvedAliases.add(node);
625
+ else ctx.resolvedAliases = new Set([node]);
626
+ node = node.resolve(ctx.doc) ?? null;
781
627
  }
782
628
  let tagObj = void 0;
783
- const node = item instanceof NodeBase ? item : ctx.doc.createNode(item, { onTagObj: (o) => tagObj = o });
629
+ node ??= ctx.doc.createNode(null, { onTagObj: (o) => tagObj = o });
784
630
  tagObj ??= getTagObject(ctx.doc.schema.tags, node);
785
631
  const props = stringifyProps(node, tagObj, ctx);
786
632
  if (props.length > 0) ctx.indentAtStart = (ctx.indentAtStart ?? 0) + props.length + 1;
@@ -788,107 +634,533 @@ function stringify(item, ctx, onComment, onChompKeep) {
788
634
  if (!props) return str;
789
635
  return node instanceof Scalar || str[0] === "{" || str[0] === "[" ? `${props} ${str}` : `${props}\n${ctx.indent}${str}`;
790
636
  }
791
-
792
637
  //#endregion
793
- //#region src/stringify/stringifyCollection.ts
794
- function stringifyCollection(collection, ctx, options) {
795
- return (ctx.inFlow ?? collection.flow ? stringifyFlowCollection : stringifyBlockCollection)(collection, ctx, options);
638
+ //#region src/nodes/addPairToJSMap.ts
639
+ function addPairToJSMap(doc, ctx, map, { key, value }) {
640
+ if ("addToJSMap" in key) key.addToJSMap?.(doc, ctx, map, value);
641
+ else if (isMergeKey(doc, key)) addMergeToJSMap(doc, ctx, map, value);
642
+ else {
643
+ const jsKey = key.toJS(doc, ctx);
644
+ if (map instanceof Map) map.set(jsKey, value ? value.toJS(doc, ctx) : value);
645
+ else if (map instanceof Set) map.add(jsKey);
646
+ else {
647
+ const stringKey = stringifyKey(doc, ctx, key, jsKey);
648
+ const jsValue = value ? value.toJS(doc, ctx) : value;
649
+ if (stringKey in map) Object.defineProperty(map, stringKey, {
650
+ value: jsValue,
651
+ writable: true,
652
+ enumerable: true,
653
+ configurable: true
654
+ });
655
+ else map[stringKey] = jsValue;
656
+ }
657
+ }
658
+ return map;
796
659
  }
797
- function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
798
- const { indent, options: { commentString } } = ctx;
799
- const itemCtx = Object.assign({}, ctx, {
800
- indent: itemIndent,
801
- type: null
802
- });
803
- let chompKeep = false;
804
- const lines = [];
805
- for (let i = 0; i < items.length; ++i) {
806
- const item = items[i];
807
- let comment = null;
808
- if (item instanceof NodeBase) {
809
- if (!chompKeep && item.spaceBefore) lines.push("");
810
- addCommentBefore(ctx, lines, item.commentBefore, chompKeep);
811
- if (item.comment) comment = item.comment;
812
- } else if (item instanceof Pair) {
813
- const ik = item.key instanceof NodeBase ? item.key : null;
814
- if (ik) {
815
- if (!chompKeep && ik.spaceBefore) lines.push("");
816
- addCommentBefore(ctx, lines, ik.commentBefore, chompKeep);
660
+ function stringifyKey(doc, ctx, key, jsKey) {
661
+ if (jsKey === null) return "";
662
+ if (typeof jsKey !== "object") return String(jsKey);
663
+ const strCtx = createStringifyContext(doc, {});
664
+ strCtx.anchors = /* @__PURE__ */ new Set();
665
+ for (const node of ctx.anchors.keys()) strCtx.anchors.add(node.anchor);
666
+ strCtx.inFlow = true;
667
+ strCtx.inStringifyKey = true;
668
+ const strKey = key.toString(strCtx);
669
+ if (!ctx.mapKeyWarned) {
670
+ let jsonStr = JSON.stringify(strKey);
671
+ if (jsonStr.length > 40) jsonStr = jsonStr.substring(0, 36) + "...\"";
672
+ const msg = `Keys with collection values will be stringified due to JS Object restrictions: ${jsonStr}. Set mapAsMap: true to use a Map instead.`;
673
+ warn(doc.options.logLevel, msg);
674
+ ctx.mapKeyWarned = true;
675
+ }
676
+ return strKey;
677
+ }
678
+ //#endregion
679
+ //#region src/nodes/toJS.ts
680
+ /** A context used in `node.toJS()` implementations */
681
+ var ToJSContext = class {
682
+ anchors = /* @__PURE__ */ new Map();
683
+ /** Cached anchor and alias nodes in the order they occur in the document */
684
+ aliasResolveCache;
685
+ mapAsMap;
686
+ mapKeyWarned = false;
687
+ maxAliasCount;
688
+ constructor(opt) {
689
+ this.mapAsMap = opt?.mapAsMap === true;
690
+ this.maxAliasCount = opt?.maxAliasCount ?? 100;
691
+ }
692
+ setAnchor(node, res) {
693
+ this.anchors.set(node, {
694
+ aliasCount: 0,
695
+ count: 1,
696
+ res
697
+ });
698
+ }
699
+ };
700
+ //#endregion
701
+ //#region src/nodes/util-clone-map-or-set.ts
702
+ function cloneMapOrSet(coll, schema) {
703
+ schema ??= coll.schema;
704
+ const copy = new coll.constructor(schema);
705
+ for (const [key, value] of coll.values) copy.values.set(key, value.clone(schema));
706
+ if (coll.range) copy.range = [...coll.range];
707
+ const propDesc = Object.getOwnPropertyDescriptors(coll);
708
+ for (const [name, prop] of Object.entries(propDesc)) if (!(name in copy)) Object.defineProperty(copy, name, prop);
709
+ return copy;
710
+ }
711
+ //#endregion
712
+ //#region src/nodes/YAMLMap.ts
713
+ var YAMLMap = class {
714
+ static tagName = "tag:yaml.org,2002:map";
715
+ values = /* @__PURE__ */ new Map();
716
+ /**
717
+ * A generic collection factory method that can be used
718
+ * by other node classes that inherit from YAMLMap
719
+ */
720
+ static create(nc, obj) {
721
+ const { replacer } = nc;
722
+ const map = new this(nc.schema);
723
+ if (obj && typeof obj === "object") {
724
+ const iter = obj instanceof Map ? obj : Object.entries(obj);
725
+ for (let [key, value] of iter) {
726
+ if (replacer) {
727
+ if (typeof replacer === "function") value = replacer.call(obj, key, value);
728
+ else if (Array.isArray(replacer) && !replacer.includes(key)) continue;
729
+ }
730
+ if (value !== void 0 || nc.keepUndefined) {
731
+ const mk = nc.schema.mapKey(key);
732
+ const pair = nc.createPair(key, value);
733
+ map.values.set(mk, pair);
734
+ }
817
735
  }
818
736
  }
819
- chompKeep = false;
820
- let str = stringify(item, itemCtx, () => comment = null, () => chompKeep = true);
821
- if (comment) str += lineComment(str, itemIndent, commentString(comment));
822
- if (chompKeep && comment) chompKeep = false;
823
- lines.push(blockItemPrefix + str);
737
+ return map;
824
738
  }
825
- let str;
826
- if (lines.length === 0) str = flowChars.start + flowChars.end;
827
- else {
828
- str = lines[0];
829
- for (let i = 1; i < lines.length; ++i) {
830
- const line = lines[i];
831
- str += line ? `\n${indent}${line}` : "\n";
739
+ constructor(schema, elements) {
740
+ Object.defineProperty(this, "schema", {
741
+ value: schema,
742
+ configurable: true,
743
+ enumerable: false,
744
+ writable: true
745
+ });
746
+ this.values = new Map(elements?.map((pair) => [this.schema.mapKey(pair), pair]));
747
+ }
748
+ get size() {
749
+ return this.values.size;
750
+ }
751
+ /**
752
+ * Create a copy of this map.
753
+ *
754
+ * @param schema - If defined, overwrites the original's schema
755
+ */
756
+ clone(schema) {
757
+ return cloneMapOrSet(this, schema);
758
+ }
759
+ /**
760
+ * Remove a value from the mapping.
761
+ * @returns `true` if the item was found and removed.
762
+ */
763
+ delete(key) {
764
+ let mk = this.schema.mapKey(key);
765
+ if (this.values.delete(mk)) return true;
766
+ mk = key instanceof Pair ? key.key : isNode(key) ? key : null;
767
+ if (mk) {
768
+ for (const [k, p] of this.values) if (p.key === mk) return this.values.delete(k);
832
769
  }
770
+ return false;
833
771
  }
834
- if (comment) {
835
- str += "\n" + indentComment(commentString(comment), indent);
836
- if (onComment) onComment();
837
- } else if (chompKeep && onChompKeep) onChompKeep();
838
- return str;
839
- }
840
- function stringifyFlowCollection({ items }, ctx, { flowChars, itemIndent }) {
841
- const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString } } = ctx;
842
- itemIndent += indentStep;
843
- const itemCtx = Object.assign({}, ctx, {
844
- indent: itemIndent,
845
- inFlow: true,
846
- type: null
847
- });
848
- let reqNewline = false;
849
- let linesAtValue = 0;
850
- const lines = [];
851
- for (let i = 0; i < items.length; ++i) {
852
- const item = items[i];
853
- let comment = null;
854
- if (item instanceof NodeBase) {
855
- if (item.spaceBefore) lines.push("");
856
- addCommentBefore(ctx, lines, item.commentBefore, false);
857
- if (item.comment) comment = item.comment;
858
- } else if (item instanceof Pair) {
859
- const ik = item.key instanceof NodeBase ? item.key : null;
860
- if (ik) {
861
- if (ik.spaceBefore) lines.push("");
862
- addCommentBefore(ctx, lines, ik.commentBefore, false);
863
- if (ik.comment) reqNewline = true;
772
+ /** Return value at `key`, or `undefined` if not found. */
773
+ get(key) {
774
+ return this.getPair(key)?.value;
775
+ }
776
+ /** Return pair at `key`, or `undefined` if not found. */
777
+ getPair(key) {
778
+ let mk = this.schema.mapKey(key);
779
+ const pair = this.values.get(mk);
780
+ if (pair) return pair;
781
+ mk = key instanceof Pair ? key.key : isNode(key) ? key : null;
782
+ if (mk) {
783
+ for (const p of this.values.values()) if (p.key === mk) return p;
784
+ }
785
+ }
786
+ /** Check if the mapping includes a value with the key `key`. */
787
+ has(key) {
788
+ let mk = this.schema.mapKey(key);
789
+ if (this.values.has(mk)) return true;
790
+ mk = key instanceof Pair ? key.key : isNode(key) ? key : null;
791
+ if (mk) {
792
+ for (const p of this.values.values()) if (p.key === mk) return true;
793
+ }
794
+ return false;
795
+ }
796
+ /**
797
+ * Return the internal Map key matching `key`, or `undefined` if not found.
798
+ *
799
+ * @param allowMissing - If `true`, a key is always returned,
800
+ * even if the key is not in the map.
801
+ */
802
+ keyOf(key, allowMissing = false) {
803
+ let mk = this.schema.mapKey(key);
804
+ if (allowMissing || this.values.has(mk)) return mk;
805
+ mk = key instanceof Pair ? key.key : isNode(key) ? key : null;
806
+ if (mk) {
807
+ for (const [k, v] of this.values) if (v.key === mk) return k;
808
+ }
809
+ }
810
+ pairs() {
811
+ return this.values.values();
812
+ }
813
+ set(keyOrPair, value, options) {
814
+ const mk = this.schema.mapKey(keyOrPair);
815
+ let pair;
816
+ if (keyOrPair instanceof Pair) pair = keyOrPair;
817
+ else if (isNode(keyOrPair) && (value == null || isNode(value))) pair = new Pair(keyOrPair, value ?? null);
818
+ else pair = new NodeCreator(this.schema, options).createPair(keyOrPair, value);
819
+ if (pair.value instanceof Scalar) {
820
+ const prev = this.values.get(mk);
821
+ if (prev) {
822
+ if (!prev.value) {
823
+ prev.value = pair.value;
824
+ return this;
825
+ }
826
+ if (prev.value instanceof Scalar) {
827
+ Object.assign(prev.value, pair.value);
828
+ return this;
829
+ }
830
+ }
831
+ }
832
+ this.values.set(mk, pair);
833
+ return this;
834
+ }
835
+ toJS(doc, ctx, Type) {
836
+ ctx ??= new ToJSContext();
837
+ const map = Type ? new Type() : ctx?.mapAsMap ? /* @__PURE__ */ new Map() : {};
838
+ if (this.anchor) ctx.setAnchor(this, map);
839
+ for (const pair of this.values.values()) addPairToJSMap(doc, ctx, map, pair);
840
+ return map;
841
+ }
842
+ toString(ctx, onComment, onChompKeep) {
843
+ if (!ctx) return JSON.stringify(this);
844
+ let pairs = this.values.values();
845
+ if (ctx.sortMapEntries) pairs = Array.from(pairs).sort(ctx.sortMapEntries);
846
+ return ctx.inFlow ?? this.flow ? this.#stringifyFlowMap(ctx, pairs) : this.#stringifyBlockMap(ctx, pairs, onComment, onChompKeep);
847
+ }
848
+ #stringifyBlockMap(ctx, pairs, onComment, onChompKeep) {
849
+ const { indent, options: { commentString } } = ctx;
850
+ let chompKeep = false;
851
+ const lines = [];
852
+ for (const pair of pairs) {
853
+ let comment = null;
854
+ if (!chompKeep && pair.key.spaceBefore) lines.push("");
855
+ let cb = pair.key.commentBefore;
856
+ if (cb && chompKeep) cb = cb.replace(/^\n+/, "");
857
+ if (cb) {
858
+ const ic = indentComment(commentString(cb), indent).trimStart();
859
+ lines.push(ic);
860
+ }
861
+ chompKeep = false;
862
+ let str = stringifyPair(pair, ctx, () => comment = null, () => chompKeep = true);
863
+ if (comment) str += lineComment(str, indent, commentString(comment));
864
+ if (chompKeep && comment) chompKeep = false;
865
+ lines.push(str);
866
+ }
867
+ let str;
868
+ if (lines.length === 0) str = "{}";
869
+ else {
870
+ str = lines[0];
871
+ for (let i = 1; i < lines.length; ++i) {
872
+ const line = lines[i];
873
+ str += line ? `\n${indent}${line}` : "\n";
874
+ }
875
+ }
876
+ if (this.comment) {
877
+ str += "\n" + indentComment(commentString(this.comment), indent);
878
+ onComment?.();
879
+ } else if (chompKeep) onChompKeep?.();
880
+ return str;
881
+ }
882
+ #stringifyFlowMap(ctx, pairs) {
883
+ const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString, lineWidth, trailingComma } } = ctx;
884
+ const itemIndent = indent + indentStep;
885
+ const itemCtx = {
886
+ ...ctx,
887
+ indent: itemIndent,
888
+ inFlow: true
889
+ };
890
+ let reqNewline = false;
891
+ let linesAtValue = 0;
892
+ const lines = [];
893
+ let itemsLeft = this.values.size;
894
+ for (const pair of pairs) {
895
+ itemsLeft -= 1;
896
+ let comment = null;
897
+ const ik = pair.key;
898
+ if (ik.spaceBefore) {
899
+ lines.push("");
900
+ reqNewline = true;
864
901
  }
865
- const iv = item.value instanceof NodeBase ? item.value : null;
902
+ if (ik.commentBefore) {
903
+ const ic = indentComment(commentString(ik.commentBefore), indent);
904
+ lines.push(ic.trimStart());
905
+ reqNewline = true;
906
+ }
907
+ if (ik.comment) reqNewline = true;
908
+ const iv = pair.value;
866
909
  if (iv) {
867
910
  if (iv.comment) comment = iv.comment;
868
911
  if (iv.commentBefore) reqNewline = true;
869
- } else if (item.value == null && ik?.comment) comment = ik.comment;
870
- }
871
- if (comment) reqNewline = true;
872
- let str = stringify(item, itemCtx, () => comment = null);
873
- if (i < items.length - 1) str += ",";
874
- if (comment) str += lineComment(str, itemIndent, commentString(comment));
875
- if (!reqNewline && (lines.length > linesAtValue || str.includes("\n"))) reqNewline = true;
876
- lines.push(str);
877
- linesAtValue = lines.length;
878
- }
879
- const { start, end } = flowChars;
880
- if (lines.length === 0) return start + end;
881
- else {
912
+ } else if (ik?.comment) comment = ik.comment;
913
+ if (comment) reqNewline = true;
914
+ let str = stringifyPair(pair, itemCtx, () => comment = null);
915
+ reqNewline ||= lines.length > linesAtValue || str.includes("\n");
916
+ if (itemsLeft > 0) str += ",";
917
+ else if (trailingComma) {
918
+ if (!reqNewline && lineWidth > 0) reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) + (str.length + 2) > lineWidth;
919
+ if (reqNewline) str += ",";
920
+ }
921
+ if (comment) str += lineComment(str, itemIndent, commentString(comment));
922
+ lines.push(str);
923
+ linesAtValue = lines.length;
924
+ }
925
+ if (lines.length === 0) return "{}";
882
926
  if (!reqNewline) {
883
927
  const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
884
928
  reqNewline = ctx.options.lineWidth > 0 && len > ctx.options.lineWidth;
885
929
  }
886
930
  if (reqNewline) {
887
- let str = start;
931
+ let str = "{";
888
932
  for (const line of lines) str += line ? `\n${indentStep}${indent}${line}` : "\n";
889
- return `${str}\n${indent}${end}`;
890
- } else return `${start}${fcPadding}${lines.join(" ")}${fcPadding}${end}`;
933
+ return `${str}\n${indent}}`;
934
+ }
935
+ return `{${fcPadding}${lines.join(" ")}${fcPadding}}`;
936
+ }
937
+ };
938
+ //#endregion
939
+ //#region src/nodes/YAMLSeq.ts
940
+ const isScalarValue = (value) => !value || typeof value !== "function" && typeof value !== "object";
941
+ var YAMLSeq = class extends Array {
942
+ static get tagName() {
943
+ return "tag:yaml.org,2002:seq";
891
944
  }
945
+ /**
946
+ * A generic collection factory method that can be extended
947
+ * to other node classes that inherit from YAMLSeq
948
+ */
949
+ static create(nc, obj) {
950
+ const seq = new this(nc.schema);
951
+ if (obj && Symbol.iterator in Object(obj)) {
952
+ let i = 0;
953
+ for (let it of obj) {
954
+ if (typeof nc.replacer === "function") {
955
+ const key = obj instanceof Set ? it : String(i++);
956
+ it = nc.replacer.call(obj, key, it);
957
+ }
958
+ seq.push(nc.create(it));
959
+ }
960
+ }
961
+ return seq;
962
+ }
963
+ constructor(schema, elements = []) {
964
+ super(...nodeValues(schema, elements));
965
+ Object.defineProperty(this, "schema", {
966
+ value: schema,
967
+ configurable: true,
968
+ enumerable: false,
969
+ writable: true
970
+ });
971
+ }
972
+ get size() {
973
+ return this.length;
974
+ }
975
+ /**
976
+ * Create a copy of this collection.
977
+ *
978
+ * @param schema - If defined, overwrites the original's schema
979
+ */
980
+ clone(schema) {
981
+ const copy = this.constructor.from(this, (it) => it.clone(schema));
982
+ if (this.range) copy.range = [...this.range];
983
+ const propDesc = Object.getOwnPropertyDescriptors(this);
984
+ for (const [name, prop] of Object.entries(propDesc)) if (!(name in copy)) Object.defineProperty(copy, name, prop);
985
+ if (schema) copy.schema = schema;
986
+ return copy;
987
+ }
988
+ /**
989
+ * Change all elements within a range of indices in this sequence to a static value.
990
+ *
991
+ * Non-node values are converted to Node values.
992
+ */
993
+ fill(value, start, end) {
994
+ return super.fill(nodeValue(this.schema, value), start, end);
995
+ }
996
+ /** @private */
997
+ _push(item) {
998
+ super.push(item);
999
+ }
1000
+ /**
1001
+ * Append new elements to this sequence, and return its new length.
1002
+ *
1003
+ * Non-node values are converted to Node values.
1004
+ */
1005
+ push(...values) {
1006
+ return super.push(...nodeValues(this.schema, values));
1007
+ }
1008
+ /**
1009
+ * Set a value in this sequence.
1010
+ *
1011
+ * Non-node values are converted to Node values.
1012
+ */
1013
+ set(idx, value, options) {
1014
+ if (!Number.isInteger(idx)) throw new TypeError(`Expected an integer, not ${JSON.stringify(idx)}.`);
1015
+ const prev = this.at(idx);
1016
+ if (prev instanceof Scalar && isScalarValue(value)) prev.value = value;
1017
+ else {
1018
+ if (idx < 0) {
1019
+ if (idx < -this.length) throw new RangeError(`Invalid index ${idx}`);
1020
+ idx += this.length;
1021
+ }
1022
+ this[idx] = nodeValue(this.schema, value, options);
1023
+ }
1024
+ }
1025
+ /**
1026
+ * Changes the contents of this sequence by removing or replacing existing elements
1027
+ * and/or adding new elements in place.
1028
+ *
1029
+ * Non-node values are converted to Node values.
1030
+ */
1031
+ splice(start, deleteCount, ...values) {
1032
+ const nv = nodeValues(this.schema, values);
1033
+ return arguments.length < 2 ? super.splice(start) : super.splice(start, Number(deleteCount), ...nv);
1034
+ }
1035
+ /**
1036
+ * Prepend new elements to this sequence, and return its new length.
1037
+ *
1038
+ * Non-node values are converted to Node values.
1039
+ */
1040
+ unshift(...values) {
1041
+ return super.unshift(...nodeValues(this.schema, values));
1042
+ }
1043
+ /** A plain JavaScript representation of this node. */
1044
+ toJS(doc, ctx) {
1045
+ ctx ??= new ToJSContext();
1046
+ if (this.anchor) {
1047
+ const res = [];
1048
+ if (this.anchor) ctx.setAnchor(this, res);
1049
+ for (const item of this) res.push(item.toJS(doc, ctx));
1050
+ return res;
1051
+ }
1052
+ return Array.from(this, (item) => item.toJS(doc, ctx));
1053
+ }
1054
+ toString(ctx, onComment, onChompKeep) {
1055
+ if (!ctx) return JSON.stringify(this);
1056
+ return ctx.inFlow ?? this.flow ? this.#stringifyFlowSeq(ctx) : this.#stringifyBlockSeq(ctx, onComment, onChompKeep);
1057
+ }
1058
+ #stringifyBlockSeq(ctx, onComment, onChompKeep) {
1059
+ const { indent, options: { commentString } } = ctx;
1060
+ const itemIndent = indent + " ";
1061
+ const itemCtx = {
1062
+ ...ctx,
1063
+ indent: itemIndent
1064
+ };
1065
+ let chompKeep = false;
1066
+ const lines = [];
1067
+ for (let i = 0; i < this.length; ++i) {
1068
+ const item = this[i];
1069
+ let comment = null;
1070
+ if (item instanceof Pair) {
1071
+ if (!chompKeep && item.key.spaceBefore) lines.push("");
1072
+ addCommentBefore(ctx, lines, item.key.commentBefore, chompKeep);
1073
+ } else if (item) {
1074
+ if (!chompKeep && item.spaceBefore) lines.push("");
1075
+ addCommentBefore(ctx, lines, item.commentBefore, chompKeep);
1076
+ if (item.comment) comment = item.comment;
1077
+ }
1078
+ chompKeep = false;
1079
+ let str = stringify(item, itemCtx, () => comment = null, () => chompKeep = true);
1080
+ if (comment) str += lineComment(str, itemIndent, commentString(comment));
1081
+ if (chompKeep && comment) chompKeep = false;
1082
+ lines.push(`- ${str}`);
1083
+ }
1084
+ let str;
1085
+ if (lines.length === 0) str = "[]";
1086
+ else {
1087
+ str = lines[0];
1088
+ for (let i = 1; i < lines.length; ++i) {
1089
+ const line = lines[i];
1090
+ str += line ? `\n${indent}${line}` : "\n";
1091
+ }
1092
+ }
1093
+ if (this.comment) {
1094
+ str += "\n" + indentComment(commentString(this.comment), indent);
1095
+ onComment?.();
1096
+ } else if (chompKeep) onChompKeep?.();
1097
+ return str;
1098
+ }
1099
+ #stringifyFlowSeq(ctx) {
1100
+ const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString } } = ctx;
1101
+ const itemIndent = indent + " " + indentStep;
1102
+ const itemCtx = {
1103
+ ...ctx,
1104
+ indent: itemIndent,
1105
+ inFlow: true
1106
+ };
1107
+ let reqNewline = false;
1108
+ let linesAtValue = 0;
1109
+ const lines = [];
1110
+ for (let i = 0; i < this.length; ++i) {
1111
+ const item = this[i];
1112
+ let comment = null;
1113
+ if (item instanceof Pair) {
1114
+ const ik = item.key;
1115
+ if (ik.spaceBefore) lines.push("");
1116
+ addCommentBefore(ctx, lines, ik.commentBefore, false);
1117
+ if (ik.comment) reqNewline = true;
1118
+ const iv = item.value;
1119
+ if (iv) {
1120
+ if (iv.comment) comment = iv.comment;
1121
+ if (iv.commentBefore) reqNewline = true;
1122
+ } else if (ik?.comment) comment = ik.comment;
1123
+ } else if (item) {
1124
+ if (item.spaceBefore) lines.push("");
1125
+ addCommentBefore(ctx, lines, item.commentBefore, false);
1126
+ if (item.comment) comment = item.comment;
1127
+ }
1128
+ if (comment) reqNewline = true;
1129
+ let str = stringify(item, itemCtx, () => comment = null);
1130
+ reqNewline ||= lines.length > linesAtValue || str.includes("\n");
1131
+ if (i < this.length - 1) str += ",";
1132
+ else if (ctx.options.trailingComma) {
1133
+ if (ctx.options.lineWidth > 0) reqNewline ||= lines.reduce((sum, line) => sum + line.length + 2, 2) + (str.length + 2) > ctx.options.lineWidth;
1134
+ if (reqNewline) str += ",";
1135
+ }
1136
+ if (comment) str += lineComment(str, itemIndent, commentString(comment));
1137
+ lines.push(str);
1138
+ linesAtValue = lines.length;
1139
+ }
1140
+ if (lines.length === 0) return "[]";
1141
+ if (!reqNewline) {
1142
+ const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
1143
+ reqNewline = ctx.options.lineWidth > 0 && len > ctx.options.lineWidth;
1144
+ }
1145
+ if (reqNewline) {
1146
+ let str = "[";
1147
+ for (const line of lines) str += line ? `\n${indentStep}${indent}${line}` : "\n";
1148
+ return `${str}\n${indent}]`;
1149
+ }
1150
+ return `[${fcPadding}${lines.join(" ")}${fcPadding}]`;
1151
+ }
1152
+ };
1153
+ function nodeValue(schema, value, options) {
1154
+ if (isNode(value) || value instanceof Pair) return value;
1155
+ return new NodeCreator(schema, options).create(value);
1156
+ }
1157
+ function nodeValues(schema, values) {
1158
+ let nc;
1159
+ return values.map((value) => {
1160
+ if (isNode(value) || value instanceof Pair) return value;
1161
+ nc ??= new NodeCreator(schema);
1162
+ return nc.create(value);
1163
+ });
892
1164
  }
893
1165
  function addCommentBefore({ indent, options: { commentString } }, lines, comment, chompKeep) {
894
1166
  if (comment && chompKeep) comment = comment.replace(/^\n+/, "");
@@ -897,133 +1169,199 @@ function addCommentBefore({ indent, options: { commentString } }, lines, comment
897
1169
  lines.push(ic.trimStart());
898
1170
  }
899
1171
  }
900
-
901
1172
  //#endregion
902
- //#region src/nodes/YAMLSeq.ts
903
- const isScalarValue = (value) => !value || typeof value !== "function" && typeof value !== "object";
904
- var YAMLSeq = class extends Collection {
905
- static get tagName() {
906
- return "tag:yaml.org,2002:seq";
1173
+ //#region src/nodes/YAMLSet.ts
1174
+ var YAMLSet = class {
1175
+ static tagName = "tag:yaml.org,2002:set";
1176
+ /** A fully qualified tag */
1177
+ tag = "tag:yaml.org,2002:set";
1178
+ values = /* @__PURE__ */ new Map();
1179
+ constructor(schema) {
1180
+ Object.defineProperty(this, "schema", {
1181
+ value: schema,
1182
+ configurable: true,
1183
+ enumerable: false,
1184
+ writable: true
1185
+ });
1186
+ }
1187
+ get size() {
1188
+ return this.values.size;
907
1189
  }
908
- items = [];
909
1190
  add(value, options) {
910
- if (value instanceof NodeBase) this.items.push(value);
911
- else if (!this.schema) throw new Error("Schema is required");
912
- else {
913
- const nc = new NodeCreator(this.schema, {
914
- ...options,
915
- aliasDuplicateObjects: false
916
- });
917
- this.items.push(nc.create(value));
918
- nc.setAnchors();
919
- }
1191
+ if (this.has(value)) return this;
1192
+ const mk = this.schema.mapKey(value);
1193
+ const node = isNode(value) ? value : new NodeCreator(this.schema, options).create(value);
1194
+ this.values.set(mk, node);
1195
+ return this;
920
1196
  }
921
1197
  /**
922
- * Removes a value from the collection.
1198
+ * Create a copy of this set.
923
1199
  *
924
- * Throws if `idx` is not a non-negative integer.
925
- *
926
- * @returns `true` if the item was found and removed.
1200
+ * @param schema - If defined, overwrites the original's schema
927
1201
  */
928
- delete(idx) {
929
- if (!Number.isInteger(idx)) throw new TypeError(`Expected an integer, not ${idx}.`);
930
- if (idx < 0) throw new RangeError(`Invalid negative index ${idx}`);
931
- return this.items.splice(idx, 1).length > 0;
1202
+ clone(schema) {
1203
+ return cloneMapOrSet(this, schema);
932
1204
  }
933
1205
  /**
934
- * Returns item at `key`, or `undefined` if not found.
935
- *
936
- * Throws if `idx` is not a non-negative integer.
1206
+ * Remove `value` from the set.
1207
+ * @returns `true` if the item was found and removed.
937
1208
  */
938
- get(idx) {
939
- if (!Number.isInteger(idx)) throw new TypeError(`Expected an integer, not ${JSON.stringify(idx)}.`);
940
- if (idx < 0) throw new RangeError(`Invalid negative index ${idx}`);
941
- return this.items[idx];
1209
+ delete(value) {
1210
+ const mk = this.schema.mapKey(value);
1211
+ if (this.values.delete(mk)) return true;
1212
+ if (isNode(value)) {
1213
+ for (const [k, v] of this.values) if (v === value) return this.values.delete(k);
1214
+ }
1215
+ return false;
1216
+ }
1217
+ /** Return the node matching `value`, if the set includes it. */
1218
+ get(value) {
1219
+ const mk = this.schema.mapKey(value);
1220
+ const node = this.values.get(mk);
1221
+ if (node) return node;
1222
+ if (isNode(value)) {
1223
+ for (const v of this.values.values()) if (v === value) return v;
1224
+ }
942
1225
  }
943
- /**
944
- * Checks if the collection includes a value with the key `key`.
945
- *
946
- * Throws if `idx` is not a non-negative integer.
947
- */
948
- has(idx) {
949
- if (!Number.isInteger(idx)) throw new TypeError(`Expected an integer, not ${JSON.stringify(idx)}.`);
950
- if (idx < 0) throw new RangeError(`Invalid negative index ${idx}`);
951
- return idx < this.items.length;
1226
+ /** Check if the set includes `value`. */
1227
+ has(value) {
1228
+ const mk = this.schema.mapKey(value);
1229
+ if (this.values.has(mk)) return true;
1230
+ if (isNode(value)) {
1231
+ for (const v of this.values.values()) if (v === value) return true;
1232
+ }
1233
+ return false;
952
1234
  }
953
1235
  /**
954
- * Sets a value in this collection. For `!!set`, `value` needs to be a
955
- * boolean to add/remove the item from the set.
1236
+ * Return the internal Map key matching `value`, or `undefined` if not found.
956
1237
  *
957
- * Throws if `idx` is not a non-negative integer.
1238
+ * @param allowMissing - If `true`, a key is always returned,
1239
+ * even if the value is not in the set.
958
1240
  */
959
- set(idx, value, options) {
960
- if (!Number.isInteger(idx)) throw new TypeError(`Expected an integer, not ${JSON.stringify(idx)}.`);
961
- if (idx < 0) throw new RangeError(`Invalid negative index ${idx}`);
962
- const prev = this.items[idx];
963
- if (prev instanceof Scalar && isScalarValue(value)) prev.value = value;
964
- else if (value instanceof NodeBase) this.items[idx] = value;
965
- else if (!this.schema) throw new Error("Schema is required");
966
- else {
967
- const nc = new NodeCreator(this.schema, {
968
- ...options,
969
- aliasDuplicateObjects: false
970
- });
971
- this.items[idx] = nc.create(value);
972
- nc.setAnchors();
973
- }
974
- }
975
- toJSON(_, ctx) {
976
- const seq = [];
977
- if (ctx?.onCreate) ctx.onCreate(seq);
978
- let i = 0;
979
- for (const item of this.items) seq.push(toJS(item, String(i++), ctx));
980
- return seq;
1241
+ keyOf(value, allowMissing = false) {
1242
+ const mk = this.schema.mapKey(value);
1243
+ if (allowMissing || this.values.has(mk)) return mk;
1244
+ if (isNode(value)) {
1245
+ for (const [k, v] of this.values) if (v === value) return k;
1246
+ }
1247
+ }
1248
+ /** A plain JavaScript representation of this set. */
1249
+ toJS(doc, ctx) {
1250
+ ctx ??= new ToJSContext();
1251
+ const set = /* @__PURE__ */ new Set();
1252
+ if (this.anchor) ctx.setAnchor(this, set);
1253
+ for (const item of this.values.values()) set.add(item.toJS(doc, ctx));
1254
+ return set;
981
1255
  }
982
1256
  toString(ctx, onComment, onChompKeep) {
983
1257
  if (!ctx) return JSON.stringify(this);
984
- return stringifyCollection(this, ctx, {
985
- blockItemPrefix: "- ",
986
- flowChars: {
987
- start: "[",
988
- end: "]"
989
- },
990
- itemIndent: (ctx.indent || "") + " ",
991
- onChompKeep,
992
- onComment
993
- });
994
- }
995
- static from(nc, obj) {
996
- const seq = new this(nc.schema);
997
- if (obj && Symbol.iterator in Object(obj)) {
998
- let i = 0;
999
- for (let it of obj) {
1000
- if (typeof nc.replacer === "function") {
1001
- const key = obj instanceof Set ? it : String(i++);
1002
- it = nc.replacer.call(obj, key, it);
1003
- }
1004
- seq.items.push(nc.create(it));
1258
+ let items = this.values.values();
1259
+ if (ctx.sortMapEntries) items = Array.from(items, (item) => new Pair(item)).sort(ctx.sortMapEntries).map((pair) => pair.key);
1260
+ if (ctx.inFlow ?? this.flow) return this.#stringifyFlowSet(ctx, items);
1261
+ else return this.#stringifyBlockSet(ctx, items, onComment, onChompKeep);
1262
+ }
1263
+ #stringifyBlockSet(ctx, items, onComment, onChompKeep) {
1264
+ const { indent, indentStep, options: { commentString } } = ctx;
1265
+ const itemCtx = {
1266
+ ...ctx,
1267
+ implicitKey: false,
1268
+ indent: indent + indentStep
1269
+ };
1270
+ let chompKeep = false;
1271
+ let res = null;
1272
+ for (const item of items) {
1273
+ if (!chompKeep && item.spaceBefore) if (typeof res === "string") res += "\n";
1274
+ else res = "";
1275
+ let cb = item.commentBefore;
1276
+ if (cb && chompKeep) cb = cb.replace(/^\n+/, "");
1277
+ if (cb) {
1278
+ const ic = indentComment(commentString(cb), indent).trimStart();
1279
+ if (typeof res === "string") res += `\n${indent}${ic}`;
1280
+ else res = ic;
1281
+ }
1282
+ chompKeep = false;
1283
+ let comment = item.comment;
1284
+ let str = stringify(item, itemCtx, () => comment = null, () => chompKeep = true);
1285
+ str = str ? `? ${str}` : "?";
1286
+ if (comment) {
1287
+ str += lineComment(str, itemCtx.indent, commentString(comment));
1288
+ chompKeep = false;
1289
+ }
1290
+ if (typeof res === "string") res += `\n${indent}${str}`;
1291
+ else res = str;
1292
+ }
1293
+ if (this.comment) {
1294
+ const cs = commentString(this.comment);
1295
+ if (typeof res === "string") res += "\n" + indentComment(cs, indent);
1296
+ else res = "{}" + lineComment("", indent, cs);
1297
+ onComment?.();
1298
+ } else if (chompKeep) onChompKeep?.();
1299
+ return res ?? "{}";
1300
+ }
1301
+ #stringifyFlowSet(ctx, items) {
1302
+ const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString, lineWidth, trailingComma } } = ctx;
1303
+ const itemCtx = {
1304
+ ...ctx,
1305
+ indent: indent + indentStep + indentStep,
1306
+ inFlow: true
1307
+ };
1308
+ let reqNewline = false;
1309
+ const lines = [];
1310
+ let itemsLeft = this.values.size;
1311
+ let singleLineWidth = 2 * fcPadding.length;
1312
+ for (const item of items) {
1313
+ itemsLeft -= 1;
1314
+ if (item.spaceBefore) {
1315
+ lines.push("");
1316
+ reqNewline = true;
1317
+ }
1318
+ if (item.commentBefore) {
1319
+ const ic = indentComment(commentString(item.commentBefore), indent);
1320
+ lines.push(ic.trimStart());
1321
+ reqNewline = true;
1322
+ }
1323
+ let comment = item.comment;
1324
+ if (comment) reqNewline = true;
1325
+ itemCtx.implicitKey = !isCollection(item);
1326
+ let str = stringify(item, itemCtx, () => comment = null) || "?";
1327
+ if (isCollection(item)) str = `? ${str}`;
1328
+ reqNewline ||= str.includes("\n");
1329
+ if (!reqNewline && lineWidth > 0) {
1330
+ singleLineWidth += str.length + 2;
1331
+ if (singleLineWidth > lineWidth) reqNewline = true;
1005
1332
  }
1333
+ if (itemsLeft > 0 || trailingComma && reqNewline) str += ",";
1334
+ if (comment) str += lineComment(str, indent + indentStep, commentString(comment));
1335
+ lines.push(str);
1006
1336
  }
1007
- return seq;
1337
+ if (lines.length === 0) return "{}";
1338
+ if (!reqNewline) return `{${fcPadding}${lines.join(" ")}${fcPadding}}`;
1339
+ let str = "{";
1340
+ for (const line of lines) str += line ? `\n${indentStep}${indent}${line}` : "\n";
1341
+ return `${str}\n${indent}}`;
1008
1342
  }
1009
1343
  };
1010
-
1344
+ //#endregion
1345
+ //#region src/nodes/identity.ts
1346
+ /** Type predicate for collections */
1347
+ const isCollection = (node) => node instanceof YAMLMap || node instanceof YAMLSeq || node instanceof YAMLSet;
1348
+ /** Type predicate for `Node` values */
1349
+ const isNode = (node) => node instanceof Scalar || node instanceof Alias || node instanceof YAMLMap || node instanceof YAMLSeq || node instanceof YAMLSet;
1011
1350
  //#endregion
1012
1351
  //#region src/stringify/stringifyPair.ts
1013
1352
  function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
1014
- const { doc, indent, indentStep, noValues, options: { commentString, indentSeq, simpleKeys } } = ctx;
1015
- let keyComment = key instanceof NodeBase && key.comment || null;
1353
+ const { indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
1016
1354
  if (simpleKeys) {
1017
- if (keyComment) throw new Error("With simple keys, key nodes cannot have comments");
1018
- if (key instanceof Collection || !(key instanceof NodeBase) && typeof key === "object") throw new Error("With simple keys, collection cannot be used as a key value");
1355
+ if (key.comment) throw new Error("With simple keys, key nodes cannot have comments");
1356
+ if (isCollection(key)) throw new Error("With simple keys, collection cannot be used as a key value");
1019
1357
  }
1020
- let explicitKey = !simpleKeys && (!key || !(key instanceof Scalar) || key.type === Scalar.BLOCK_FOLDED || key.type === Scalar.BLOCK_LITERAL);
1358
+ let explicitKey = !simpleKeys && (!(key instanceof Scalar) || key.type === Scalar.BLOCK_FOLDED || key.type === Scalar.BLOCK_LITERAL);
1021
1359
  ctx = {
1022
1360
  ...ctx,
1023
- implicitKey: !explicitKey && (simpleKeys || !noValues),
1024
- indent: indent + indentStep,
1025
- noValues: false
1361
+ implicitKey: !explicitKey,
1362
+ indent: indent + indentStep
1026
1363
  };
1364
+ let keyComment = key.comment;
1027
1365
  let keyCommentDone = false;
1028
1366
  let chompKeep = false;
1029
1367
  let str = stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true);
@@ -1032,11 +1370,11 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
1032
1370
  explicitKey = true;
1033
1371
  }
1034
1372
  if (ctx.inFlow) {
1035
- if (noValues || value == null) {
1373
+ if (value == null) {
1036
1374
  if (keyCommentDone && onComment) onComment();
1037
- return str === "" ? "?" : explicitKey ? `? ${str}` : noValues ? str : `${str}:`;
1375
+ return str === "" ? "?" : explicitKey ? `? ${str}` : `${str}:`;
1038
1376
  }
1039
- } else if (noValues && !simpleKeys || value == null && explicitKey) {
1377
+ } else if (value == null && explicitKey) {
1040
1378
  str = `? ${str}`;
1041
1379
  if (keyComment && !keyCommentDone) str += lineComment(str, ctx.indent, commentString(keyComment));
1042
1380
  else if (chompKeep && onChompKeep) onChompKeep();
@@ -1051,7 +1389,7 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
1051
1389
  if (keyComment) str += lineComment(str, ctx.indent, commentString(keyComment));
1052
1390
  }
1053
1391
  let vsb, vcb, valueComment;
1054
- if (value instanceof NodeBase) {
1392
+ if (value) {
1055
1393
  vsb = !!value.spaceBefore;
1056
1394
  vcb = value.commentBefore;
1057
1395
  valueComment = value.comment;
@@ -1059,7 +1397,6 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
1059
1397
  vsb = false;
1060
1398
  vcb = null;
1061
1399
  valueComment = null;
1062
- if (value && typeof value === "object") value = doc.createNode(value);
1063
1400
  }
1064
1401
  ctx.implicitKey = false;
1065
1402
  if (!explicitKey && !keyComment && value instanceof Scalar) ctx.indentAtStart = str.length + 1;
@@ -1077,11 +1414,11 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
1077
1414
  if (valueStr === "" && !ctx.inFlow) {
1078
1415
  if (ws === "\n" && valueComment) ws = "\n\n";
1079
1416
  } else ws += `\n${ctx.indent}`;
1080
- } else if (!explicitKey && value instanceof Collection) {
1417
+ } else if (!explicitKey && isCollection(value)) {
1081
1418
  const vs0 = valueStr[0];
1082
1419
  const nl0 = valueStr.indexOf("\n");
1083
1420
  const hasNewline = nl0 !== -1;
1084
- const flow = ctx.inFlow ?? value.flow ?? value.items.length === 0;
1421
+ const flow = ctx.inFlow ?? value.flow ?? value.size === 0;
1085
1422
  if (hasNewline || !flow) {
1086
1423
  let hasPropsLine = false;
1087
1424
  if (hasNewline && (vs0 === "&" || vs0 === "!")) {
@@ -1099,94 +1436,6 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
1099
1436
  else if (chompKeep && onChompKeep) onChompKeep();
1100
1437
  return str;
1101
1438
  }
1102
-
1103
- //#endregion
1104
- //#region src/log.ts
1105
- function debug(logLevel, ...messages) {
1106
- if (logLevel === "debug") console.log(...messages);
1107
- }
1108
- function warn(logLevel, warning) {
1109
- if (logLevel === "debug" || logLevel === "warn") if (typeof process !== "undefined" && typeof process.emitWarning === "function") process.emitWarning(warning);
1110
- else console.warn(warning);
1111
- }
1112
-
1113
- //#endregion
1114
- //#region src/schema/yaml-1.1/merge.ts
1115
- const MERGE_KEY = "<<";
1116
- const merge = {
1117
- identify: (value) => value === MERGE_KEY || typeof value === "symbol" && value.description === MERGE_KEY,
1118
- default: "key",
1119
- tag: "tag:yaml.org,2002:merge",
1120
- test: /^<<$/,
1121
- resolve: () => Object.assign(new Scalar(Symbol(MERGE_KEY)), { addToJSMap: addMergeToJSMap }),
1122
- stringify: () => MERGE_KEY
1123
- };
1124
- const isMergeKey = (ctx, key) => (merge.identify(key) || key instanceof Scalar && (!key.type || key.type === Scalar.PLAIN) && merge.identify(key.value)) && Boolean(ctx?.doc.schema.tags.some((tag) => tag.tag === merge.tag && tag.default));
1125
- function addMergeToJSMap(ctx, map, value) {
1126
- value = ctx && value instanceof Alias ? value.resolve(ctx.doc) : value;
1127
- if (value instanceof YAMLSeq) for (const it of value.items) mergeValue(ctx, map, it);
1128
- else if (Array.isArray(value)) for (const it of value) mergeValue(ctx, map, it);
1129
- else mergeValue(ctx, map, value);
1130
- }
1131
- function mergeValue(ctx, map, value) {
1132
- const srcMap = (ctx && value instanceof Alias ? value.resolve(ctx.doc) : value).toJSON(null, ctx, Map);
1133
- if (!(srcMap instanceof Map)) throw new Error("Merge sources must be maps or map aliases");
1134
- for (const [key, value] of srcMap) if (map instanceof Map) {
1135
- if (!map.has(key)) map.set(key, value);
1136
- } else if (map instanceof Set) map.add(key);
1137
- else if (!Object.prototype.hasOwnProperty.call(map, key)) Object.defineProperty(map, key, {
1138
- value,
1139
- writable: true,
1140
- enumerable: true,
1141
- configurable: true
1142
- });
1143
- return map;
1144
- }
1145
-
1146
- //#endregion
1147
- //#region src/nodes/addPairToJSMap.ts
1148
- function addPairToJSMap(ctx, map, { key, value }) {
1149
- if (key instanceof NodeBase && key.addToJSMap) key.addToJSMap(ctx, map, value);
1150
- else if (isMergeKey(ctx, key)) addMergeToJSMap(ctx, map, value);
1151
- else {
1152
- const jsKey = toJS(key, "", ctx);
1153
- if (map instanceof Map) map.set(jsKey, toJS(value, jsKey, ctx));
1154
- else if (map instanceof Set) map.add(jsKey);
1155
- else {
1156
- const stringKey = stringifyKey(key, jsKey, ctx);
1157
- const jsValue = toJS(value, stringKey, ctx);
1158
- if (stringKey in map) Object.defineProperty(map, stringKey, {
1159
- value: jsValue,
1160
- writable: true,
1161
- enumerable: true,
1162
- configurable: true
1163
- });
1164
- else map[stringKey] = jsValue;
1165
- }
1166
- }
1167
- return map;
1168
- }
1169
- function stringifyKey(key, jsKey, ctx) {
1170
- if (jsKey === null) return "";
1171
- if (typeof jsKey !== "object") return String(jsKey);
1172
- if (key instanceof NodeBase && ctx?.doc) {
1173
- const strCtx = createStringifyContext(ctx.doc, {});
1174
- strCtx.anchors = /* @__PURE__ */ new Set();
1175
- for (const node of ctx.anchors.keys()) strCtx.anchors.add(node.anchor);
1176
- strCtx.inFlow = true;
1177
- strCtx.inStringifyKey = true;
1178
- const strKey = key.toString(strCtx);
1179
- if (!ctx.mapKeyWarned) {
1180
- let jsonStr = JSON.stringify(strKey);
1181
- if (jsonStr.length > 40) jsonStr = jsonStr.substring(0, 36) + "...\"";
1182
- warn(ctx.doc.options.logLevel, `Keys with collection values will be stringified due to JS Object restrictions: ${jsonStr}. Set mapAsMap: true to use object keys.`);
1183
- ctx.mapKeyWarned = true;
1184
- }
1185
- return strKey;
1186
- }
1187
- return JSON.stringify(jsKey);
1188
- }
1189
-
1190
1439
  //#endregion
1191
1440
  //#region src/nodes/Pair.ts
1192
1441
  var Pair = class Pair {
@@ -1199,30 +1448,35 @@ var Pair = class Pair {
1199
1448
  clone(schema) {
1200
1449
  return new Pair(this.key.clone(schema), this.value?.clone(schema) ?? null);
1201
1450
  }
1202
- toJSON(_, ctx) {
1203
- return addPairToJSMap(ctx, ctx?.mapAsMap ? /* @__PURE__ */ new Map() : {}, this);
1451
+ toJS(doc, ctx) {
1452
+ return addPairToJSMap(doc, ctx, ctx.mapAsMap ? /* @__PURE__ */ new Map() : {}, this);
1204
1453
  }
1205
1454
  toString(ctx, onComment, onChompKeep) {
1206
1455
  return ctx?.doc ? stringifyPair(this, ctx, onComment, onChompKeep) : JSON.stringify(this);
1207
1456
  }
1208
1457
  };
1209
-
1210
1458
  //#endregion
1211
1459
  //#region src/nodes/Alias.ts
1212
- var Alias = class Alias extends NodeBase {
1460
+ var Alias = class Alias {
1213
1461
  source;
1214
1462
  constructor(source) {
1215
- super();
1216
1463
  this.source = source;
1217
1464
  Object.defineProperty(this, "tag", { set() {
1218
1465
  throw new Error("Alias nodes cannot have tags");
1219
1466
  } });
1220
1467
  }
1468
+ /** Create a copy of this node. */
1469
+ clone() {
1470
+ const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
1471
+ if (this.range) copy.range = [...this.range];
1472
+ return copy;
1473
+ }
1221
1474
  /**
1222
1475
  * Resolve the value of this alias within `doc`, finding the last
1223
1476
  * instance of the `source` anchor before this node.
1224
1477
  */
1225
1478
  resolve(doc, ctx) {
1479
+ if (ctx?.maxAliasCount === 0) throw new ReferenceError("Alias resolution is disabled");
1226
1480
  let nodes;
1227
1481
  if (ctx?.aliasResolveCache) nodes = ctx.aliasResolveCache;
1228
1482
  else {
@@ -1239,9 +1493,11 @@ var Alias = class Alias extends NodeBase {
1239
1493
  }
1240
1494
  return found;
1241
1495
  }
1242
- toJSON(_arg, ctx) {
1243
- if (!ctx) return { source: this.source };
1244
- const { anchors, doc, maxAliasCount } = ctx;
1496
+ /** A plain JavaScript representation of the resolved value of this alias. */
1497
+ toJS(doc, ctx) {
1498
+ if (!doc?.schema) throw new TypeError("A document argument is required");
1499
+ ctx ??= new ToJSContext();
1500
+ const { anchors, maxAliasCount } = ctx;
1245
1501
  const source = this.resolve(doc, ctx);
1246
1502
  if (!source) {
1247
1503
  const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
@@ -1249,14 +1505,14 @@ var Alias = class Alias extends NodeBase {
1249
1505
  }
1250
1506
  let data = anchors.get(source);
1251
1507
  if (!data) {
1252
- toJS(source, null, ctx);
1508
+ source.toJS(doc, ctx);
1253
1509
  data = anchors.get(source);
1254
1510
  }
1255
1511
  /* istanbul ignore if */
1256
1512
  if (data?.res === void 0) throw new ReferenceError("This should not happen: Alias anchor was not resolved?");
1257
1513
  if (maxAliasCount >= 0) {
1258
1514
  data.count += 1;
1259
- if (data.aliasCount === 0) data.aliasCount = getAliasCount(doc, source, anchors);
1515
+ data.aliasCount ||= getAliasCount(doc, ctx, source, anchors);
1260
1516
  if (data.count * data.aliasCount > maxAliasCount) throw new ReferenceError("Excessive alias count indicates a resource exhaustion attack");
1261
1517
  }
1262
1518
  return data.res;
@@ -1274,122 +1530,25 @@ var Alias = class Alias extends NodeBase {
1274
1530
  return src;
1275
1531
  }
1276
1532
  };
1277
- function getAliasCount(doc, node, anchors) {
1533
+ function getAliasCount(doc, ctx, node, anchors) {
1278
1534
  if (node instanceof Alias) {
1279
- const source = node.resolve(doc);
1535
+ const source = node.resolve(doc, ctx);
1280
1536
  const anchor = anchors && source && anchors.get(source);
1281
1537
  return anchor ? anchor.count * anchor.aliasCount : 0;
1282
- } else if (node instanceof NodeBase && "items" in node) {
1283
- const coll = node;
1538
+ } else if (node instanceof Pair) {
1539
+ const kc = getAliasCount(doc, ctx, node.key, anchors);
1540
+ const vc = getAliasCount(doc, ctx, node.value, anchors);
1541
+ return Math.max(kc, vc);
1542
+ } else if (Array.isArray(node)) {
1284
1543
  let count = 0;
1285
- for (const item of coll.items) {
1286
- const c = getAliasCount(doc, item, anchors);
1544
+ for (const item of node) {
1545
+ const c = getAliasCount(doc, ctx, item, anchors);
1287
1546
  if (c > count) count = c;
1288
1547
  }
1289
1548
  return count;
1290
- } else if (node instanceof Pair) {
1291
- const kc = getAliasCount(doc, node.key, anchors);
1292
- const vc = getAliasCount(doc, node.value, anchors);
1293
- return Math.max(kc, vc);
1294
1549
  }
1295
1550
  return 1;
1296
1551
  }
1297
-
1298
- //#endregion
1299
- //#region src/nodes/YAMLMap.ts
1300
- function findPair(items, key) {
1301
- const k = key instanceof Scalar ? key.value : key;
1302
- for (const it of items) {
1303
- if (it.key === key || it.key === k) return it;
1304
- if (it.key instanceof Scalar && it.key.value === k) return it;
1305
- }
1306
- }
1307
- var YAMLMap = class extends Collection {
1308
- static get tagName() {
1309
- return "tag:yaml.org,2002:map";
1310
- }
1311
- items = [];
1312
- /**
1313
- * A generic collection parsing method that can be extended
1314
- * to other node classes that inherit from YAMLMap
1315
- */
1316
- static from(nc, obj) {
1317
- const { replacer } = nc;
1318
- const map = new this(nc.schema);
1319
- const add = (key, value) => {
1320
- if (typeof replacer === "function") value = replacer.call(obj, key, value);
1321
- else if (Array.isArray(replacer) && !replacer.includes(key)) return;
1322
- if (value !== void 0 || nc.keepUndefined) map.items.push(nc.createPair(key, value));
1323
- };
1324
- if (obj instanceof Map) for (const [key, value] of obj) add(key, value);
1325
- else if (obj && typeof obj === "object") for (const key of Object.keys(obj)) add(key, obj[key]);
1326
- if (typeof nc.schema.sortMapEntries === "function") map.items.sort(nc.schema.sortMapEntries);
1327
- return map;
1328
- }
1329
- /**
1330
- * Adds a key-value pair to the map.
1331
- *
1332
- * Using a key that is already in the collection overwrites the previous value.
1333
- */
1334
- add(pair) {
1335
- if (!(pair instanceof Pair)) throw new TypeError("Expected a Pair");
1336
- const prev = findPair(this.items, pair.key);
1337
- const sortEntries = this.schema?.sortMapEntries;
1338
- if (prev) if (prev.value instanceof Scalar && pair.value instanceof Scalar) prev.value.value = pair.value.value;
1339
- else prev.value = pair.value;
1340
- else if (sortEntries) {
1341
- const i = this.items.findIndex((item) => sortEntries(pair, item) < 0);
1342
- if (i === -1) this.items.push(pair);
1343
- else this.items.splice(i, 0, pair);
1344
- } else this.items.push(pair);
1345
- }
1346
- delete(key) {
1347
- const it = findPair(this.items, key);
1348
- if (!it) return false;
1349
- return this.items.splice(this.items.indexOf(it), 1).length > 0;
1350
- }
1351
- get(key) {
1352
- return findPair(this.items, key)?.value ?? void 0;
1353
- }
1354
- has(key) {
1355
- return !!findPair(this.items, key);
1356
- }
1357
- set(key, value, options) {
1358
- let pair;
1359
- if (key instanceof NodeBase && (value instanceof NodeBase || value === null)) pair = new Pair(key, value);
1360
- else if (!this.schema) throw new Error("Schema is required");
1361
- else {
1362
- const nc = new NodeCreator(this.schema, {
1363
- ...options,
1364
- aliasDuplicateObjects: false
1365
- });
1366
- pair = nc.createPair(key, value);
1367
- nc.setAnchors();
1368
- }
1369
- this.add(pair);
1370
- }
1371
- toJSON(_, ctx, Type) {
1372
- const map = Type ? new Type() : ctx?.mapAsMap ? /* @__PURE__ */ new Map() : {};
1373
- if (ctx?.onCreate) ctx.onCreate(map);
1374
- for (const item of this.items) addPairToJSMap(ctx, map, item);
1375
- return map;
1376
- }
1377
- toString(ctx, onComment, onChompKeep) {
1378
- if (!ctx) return JSON.stringify(this);
1379
- for (const item of this.items) if (!(item instanceof Pair)) throw new Error(`Map items must all be pairs; found ${JSON.stringify(item)} instead`);
1380
- return stringifyCollection(this, ctx, {
1381
- blockItemPrefix: "",
1382
- flowChars: {
1383
- start: "{",
1384
- end: "}"
1385
- },
1386
- itemIndent: ctx.indent || "",
1387
- onChompKeep,
1388
- onComment
1389
- });
1390
- }
1391
- };
1392
-
1393
1552
  //#endregion
1394
1553
  //#region src/schema/common/map.ts
1395
1554
  const map = {
@@ -1397,12 +1556,14 @@ const map = {
1397
1556
  default: true,
1398
1557
  nodeClass: YAMLMap,
1399
1558
  tag: "tag:yaml.org,2002:map",
1559
+ createNode(nc, obj) {
1560
+ return YAMLMap.create(nc, obj);
1561
+ },
1400
1562
  resolve(map, onError) {
1401
1563
  if (!(map instanceof YAMLMap)) onError("Expected a mapping for this tag");
1402
1564
  return map;
1403
1565
  }
1404
1566
  };
1405
-
1406
1567
  //#endregion
1407
1568
  //#region src/schema/common/seq.ts
1408
1569
  const seq = {
@@ -1410,12 +1571,14 @@ const seq = {
1410
1571
  default: true,
1411
1572
  nodeClass: YAMLSeq,
1412
1573
  tag: "tag:yaml.org,2002:seq",
1574
+ createNode(nc, obj) {
1575
+ return YAMLSeq.create(nc, obj);
1576
+ },
1413
1577
  resolve(seq, onError) {
1414
1578
  if (!(seq instanceof YAMLSeq)) onError("Expected a sequence for this tag");
1415
1579
  return seq;
1416
1580
  }
1417
1581
  };
1418
-
1419
1582
  //#endregion
1420
1583
  //#region src/schema/common/string.ts
1421
1584
  const string = {
@@ -1428,7 +1591,6 @@ const string = {
1428
1591
  return stringifyString(item, ctx, onComment, onChompKeep);
1429
1592
  }
1430
1593
  };
1431
-
1432
1594
  //#endregion
1433
1595
  //#region src/schema/common/null.ts
1434
1596
  const nullTag = {
@@ -1440,7 +1602,6 @@ const nullTag = {
1440
1602
  resolve: () => new Scalar(null),
1441
1603
  stringify: ({ source }, ctx) => typeof source === "string" && nullTag.test.test(source) ? source : ctx.options.nullStr
1442
1604
  };
1443
-
1444
1605
  //#endregion
1445
1606
  //#region src/schema/core/bool.ts
1446
1607
  const boolTag = {
@@ -1456,7 +1617,6 @@ const boolTag = {
1456
1617
  return value ? ctx.options.trueStr : ctx.options.falseStr;
1457
1618
  }
1458
1619
  };
1459
-
1460
1620
  //#endregion
1461
1621
  //#region src/stringify/stringifyNumber.ts
1462
1622
  function stringifyNumber({ format, minFractionDigits, tag, value }) {
@@ -1464,7 +1624,7 @@ function stringifyNumber({ format, minFractionDigits, tag, value }) {
1464
1624
  const num = typeof value === "number" ? value : Number(value);
1465
1625
  if (!isFinite(num)) return isNaN(num) ? ".nan" : num < 0 ? "-.inf" : ".inf";
1466
1626
  let n = Object.is(value, -0) ? "-0" : JSON.stringify(value);
1467
- if (!format && minFractionDigits && (!tag || tag === "tag:yaml.org,2002:float") && /^\d/.test(n)) {
1627
+ if (!format && minFractionDigits && (!tag || tag === "tag:yaml.org,2002:float") && /^-?\d/.test(n) && !n.includes("e")) {
1468
1628
  let i = n.indexOf(".");
1469
1629
  if (i < 0) {
1470
1630
  i = n.length;
@@ -1475,7 +1635,6 @@ function stringifyNumber({ format, minFractionDigits, tag, value }) {
1475
1635
  }
1476
1636
  return n;
1477
1637
  }
1478
-
1479
1638
  //#endregion
1480
1639
  //#region src/schema/core/float.ts
1481
1640
  const floatNaN$1 = {
@@ -1511,7 +1670,6 @@ const float$1 = {
1511
1670
  },
1512
1671
  stringify: stringifyNumber
1513
1672
  };
1514
-
1515
1673
  //#endregion
1516
1674
  //#region src/schema/core/int.ts
1517
1675
  const intIdentify$2 = (value) => typeof value === "bigint" || Number.isInteger(value);
@@ -1547,7 +1705,6 @@ const intHex$1 = {
1547
1705
  resolve: (str, _onError, opt) => intResolve$1(str, 2, 16, opt),
1548
1706
  stringify: (node) => intStringify$1(node, 16, "0x")
1549
1707
  };
1550
-
1551
1708
  //#endregion
1552
1709
  //#region src/schema/core/schema.ts
1553
1710
  const schema$2 = [
@@ -1563,7 +1720,6 @@ const schema$2 = [
1563
1720
  floatExp$1,
1564
1721
  float$1
1565
1722
  ];
1566
-
1567
1723
  //#endregion
1568
1724
  //#region src/schema/json/schema.ts
1569
1725
  function intIdentify$1(value) {
@@ -1627,7 +1783,6 @@ const schema$1 = [
1627
1783
  ...jsonScalars,
1628
1784
  jsonError
1629
1785
  ];
1630
-
1631
1786
  //#endregion
1632
1787
  //#region src/schema/yaml-1.1/binary.ts
1633
1788
  const binary = {
@@ -1673,23 +1828,22 @@ const binary = {
1673
1828
  }, ctx, onComment, onChompKeep);
1674
1829
  }
1675
1830
  };
1676
-
1677
1831
  //#endregion
1678
1832
  //#region src/schema/yaml-1.1/pairs.ts
1679
1833
  function resolvePairs(seq, onError) {
1680
- if (seq instanceof YAMLSeq) for (let i = 0; i < seq.items.length; ++i) {
1681
- const item = seq.items[i];
1834
+ if (seq instanceof YAMLSeq) for (let i = 0; i < seq.length; ++i) {
1835
+ const item = seq[i];
1682
1836
  if (item instanceof Pair) continue;
1683
- else if (item instanceof YAMLMap) {
1684
- if (item.items.length > 1) onError("Each pair must have its own sequence indicator");
1685
- const pair = item.items[0] || new Pair(new Scalar(null));
1837
+ if (item instanceof YAMLMap) {
1838
+ if (item.size > 1) onError("Each pair must have its own sequence indicator");
1839
+ const pair = item.values.values().next().value ?? new Pair(new Scalar(null));
1686
1840
  if (item.commentBefore) pair.key.commentBefore = pair.key.commentBefore ? `${item.commentBefore}\n${pair.key.commentBefore}` : item.commentBefore;
1687
1841
  if (item.comment) {
1688
1842
  const cn = pair.value ?? pair.key;
1689
1843
  cn.comment = cn.comment ? `${item.comment}\n${cn.comment}` : item.comment;
1690
1844
  }
1691
- seq.items[i] = pair;
1692
- } else seq.items[i] = new Pair(item, null);
1845
+ seq[i] = pair;
1846
+ } else seq[i] = new Pair(item, null);
1693
1847
  }
1694
1848
  else onError("Expected a sequence for this tag");
1695
1849
  return seq;
@@ -1712,7 +1866,7 @@ function createPairs(nc, iterable) {
1712
1866
  value = it[key];
1713
1867
  } else throw new TypeError(`Expected tuple with one key, not ${keys.length} keys`);
1714
1868
  } else key = it;
1715
- pairs.items.push(nc.createPair(key, value));
1869
+ pairs.push(nc.createPair(key, value));
1716
1870
  }
1717
1871
  return pairs;
1718
1872
  }
@@ -1723,44 +1877,62 @@ const pairs = {
1723
1877
  resolve: resolvePairs,
1724
1878
  createNode: createPairs
1725
1879
  };
1726
-
1727
1880
  //#endregion
1728
1881
  //#region src/schema/yaml-1.1/omap.ts
1729
- var YAMLOMap = class YAMLOMap extends YAMLSeq {
1730
- static tag = "tag:yaml.org,2002:omap";
1731
- constructor(schema) {
1732
- super(schema);
1733
- this.tag = YAMLOMap.tag;
1734
- }
1735
- add = YAMLMap.prototype.add.bind(this);
1736
- delete = YAMLMap.prototype.delete.bind(this);
1737
- get = YAMLMap.prototype.get.bind(this);
1738
- has = YAMLMap.prototype.has.bind(this);
1739
- set = YAMLMap.prototype.set.bind(this);
1882
+ var YAMLOMap = class extends YAMLSeq {
1883
+ constructor(schema, elements) {
1884
+ super(schema, elements);
1885
+ this.tag = omap.tag;
1886
+ }
1887
+ /**
1888
+ * Append new pairs to the omap, and return its new length.
1889
+ */
1890
+ push(...pairs) {
1891
+ for (const pair of pairs) if (pair instanceof Pair) super.push(pair);
1892
+ else throw new Error("Omap only supports Pair values");
1893
+ return this.length;
1894
+ }
1895
+ /**
1896
+ * Set a pair in this omap.
1897
+ *
1898
+ * Throws if `idx` is not an integer.
1899
+ */
1900
+ set(idx, pair) {
1901
+ if (!Number.isInteger(idx)) throw new TypeError(`Expected an integer, not ${JSON.stringify(idx)}.`);
1902
+ if (idx < 0) {
1903
+ if (idx < -this.length) throw new RangeError(`Invalid index ${idx}`);
1904
+ idx += this.length;
1905
+ }
1906
+ this[idx] = pair;
1907
+ }
1740
1908
  /**
1741
- * If `ctx` is given, the return type is actually `Map<unknown, unknown>`,
1909
+ * The returned value actually has type `Map<unknown, unknown>`,
1742
1910
  * but TypeScript won't allow widening the signature of a child method.
1743
1911
  */
1744
- toJSON(_, ctx) {
1745
- if (!ctx) return super.toJSON(_);
1912
+ toJS(doc, ctx) {
1913
+ if (!ctx) return super.toJS(doc);
1746
1914
  const map = /* @__PURE__ */ new Map();
1747
- if (ctx?.onCreate) ctx.onCreate(map);
1748
- for (const pair of this.items) {
1749
- let key, value;
1750
- if (pair instanceof Pair) {
1751
- key = toJS(pair.key, "", ctx);
1752
- value = toJS(pair.value, key, ctx);
1753
- } else key = toJS(pair, "", ctx);
1915
+ if (this.anchor) ctx.anchors.set(this, {
1916
+ aliasCount: 0,
1917
+ count: 1,
1918
+ res: map
1919
+ });
1920
+ for (const pair of this) {
1921
+ const key = pair.key.toJS(doc, ctx);
1922
+ const value = pair.value ? pair.value.toJS(doc, ctx) : null;
1754
1923
  if (map.has(key)) throw new Error("Ordered maps must not include duplicate keys");
1755
1924
  map.set(key, value);
1756
1925
  }
1757
1926
  return map;
1758
1927
  }
1759
- static from(nc, iterable) {
1760
- const pairs = createPairs(nc, iterable);
1761
- const omap = new this(nc.schema);
1762
- omap.items = pairs.items;
1763
- return omap;
1928
+ toString(ctx, onComment, onChompKeep) {
1929
+ const keys = /* @__PURE__ */ new Set();
1930
+ for (const pair of this) {
1931
+ const key = this.schema.mapKey(pair);
1932
+ if (keys.has(key)) throw new Error("Ordered maps must not include duplicate keys");
1933
+ keys.add(key);
1934
+ }
1935
+ return super.toString(ctx, onComment, onChompKeep);
1764
1936
  }
1765
1937
  };
1766
1938
  const omap = {
@@ -1769,15 +1941,18 @@ const omap = {
1769
1941
  nodeClass: YAMLOMap,
1770
1942
  default: false,
1771
1943
  tag: "tag:yaml.org,2002:omap",
1944
+ createNode(nc, iterable) {
1945
+ const pairs = createPairs(nc, iterable);
1946
+ return new YAMLOMap(nc.schema, pairs);
1947
+ },
1772
1948
  resolve(seq, onError) {
1773
1949
  const pairs = resolvePairs(seq, onError);
1774
1950
  const seenKeys = [];
1775
- for (const { key } of pairs.items) if (key instanceof Scalar) if (seenKeys.includes(key.value)) onError(`Ordered maps must not include duplicate keys: ${key.value}`);
1951
+ for (const { key } of pairs) if (key instanceof Scalar) if (seenKeys.includes(key.value)) onError(`Ordered maps must not include duplicate keys: ${key.value}`);
1776
1952
  else seenKeys.push(key.value);
1777
- return Object.assign(new YAMLOMap(), pairs);
1953
+ return Object.assign(new YAMLOMap(seq.schema), pairs);
1778
1954
  }
1779
1955
  };
1780
-
1781
1956
  //#endregion
1782
1957
  //#region src/schema/yaml-1.1/bool.ts
1783
1958
  function boolStringify({ value, source }, ctx) {
@@ -1800,7 +1975,6 @@ const falseTag = {
1800
1975
  resolve: () => new Scalar(false),
1801
1976
  stringify: boolStringify
1802
1977
  };
1803
-
1804
1978
  //#endregion
1805
1979
  //#region src/schema/yaml-1.1/float.ts
1806
1980
  const floatNaN = {
@@ -1839,7 +2013,6 @@ const float = {
1839
2013
  },
1840
2014
  stringify: stringifyNumber
1841
2015
  };
1842
-
1843
2016
  //#endregion
1844
2017
  //#region src/schema/yaml-1.1/int.ts
1845
2018
  const intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
@@ -1908,96 +2081,28 @@ const intHex = {
1908
2081
  resolve: (str, _onError, opt) => intResolve(str, 2, 16, opt),
1909
2082
  stringify: (node) => intStringify(node, 16, "0x")
1910
2083
  };
1911
-
1912
2084
  //#endregion
1913
2085
  //#region src/schema/yaml-1.1/set.ts
1914
- var YAMLSet = class YAMLSet extends YAMLMap {
1915
- static tag = "tag:yaml.org,2002:set";
1916
- constructor(schema) {
1917
- super(schema);
1918
- this.tag = YAMLSet.tag;
1919
- }
1920
- /**
1921
- * Add a value to the set.
1922
- *
1923
- * If `value` is a Pair, its `.value` must be null and `options` is ignored.
1924
- *
1925
- * If the set already includes a matching value, no value is added.
1926
- */
1927
- add(value, options) {
1928
- if (!(value instanceof Pair)) this.set(value, true, options);
1929
- else if (value.value !== null) throw new TypeError("set pair values must be null");
1930
- else if (!findPair(this.items, value.key)) this.items.push(value);
1931
- }
1932
- /**
1933
- * Returns the value matching `key`.
1934
- */
1935
- get(key) {
1936
- return findPair(this.items, key)?.key;
1937
- }
1938
- /**
1939
- * `value` needs to be true/false to add/remove the item from the set.
1940
- */
1941
- set(key, value, options) {
1942
- if (typeof value !== "boolean") throw new Error(`Expected a boolean value, not ${typeof value}`);
1943
- const prev = findPair(this.items, key);
1944
- if (prev && !value) this.items.splice(this.items.indexOf(prev), 1);
1945
- else if (!prev && value) {
1946
- let node;
1947
- if (key instanceof NodeBase) node = key;
1948
- else if (!this.schema) throw new Error("Schema is required");
1949
- else {
1950
- const nc = new NodeCreator(this.schema, {
1951
- ...options,
1952
- aliasDuplicateObjects: false
1953
- });
1954
- node = nc.create(key);
1955
- nc.setAnchors();
1956
- }
1957
- this.items.push(new Pair(node));
1958
- }
1959
- }
1960
- toJSON(_, ctx) {
1961
- return super.toJSON(_, ctx, Set);
1962
- }
1963
- toString(ctx, onComment, onChompKeep) {
1964
- if (!ctx) return JSON.stringify(this);
1965
- return super.toString({
1966
- ...ctx,
1967
- noValues: true
1968
- }, onComment, onChompKeep);
1969
- }
1970
- static from(nc, iterable) {
1971
- const set = new this(nc.schema);
1972
- if (iterable && Symbol.iterator in Object(iterable)) for (let value of iterable) {
1973
- if (typeof nc.replacer === "function") value = nc.replacer.call(iterable, value, value);
1974
- set.items.push(nc.createPair(value, null));
1975
- }
1976
- return set;
1977
- }
1978
- };
1979
- const hasAllNullValues = (map) => map.items.every(({ value }) => value == null || value instanceof Scalar && value.value == null && !value.commentBefore && !value.comment && !value.tag);
1980
2086
  const set = {
1981
2087
  collection: "map",
1982
2088
  identify: (value) => value instanceof Set,
1983
2089
  nodeClass: YAMLSet,
1984
2090
  default: false,
1985
2091
  tag: "tag:yaml.org,2002:set",
1986
- resolve(map, onError) {
1987
- if (!(map instanceof YAMLMap)) {
1988
- onError("Expected a mapping for this tag");
1989
- return map;
1990
- } else if (!hasAllNullValues(map)) {
1991
- onError("Set items must all have null values");
1992
- return map;
1993
- } else {
1994
- const set = Object.assign(new YAMLSet(), map);
1995
- for (const pair of map.items) pair.value &&= null;
1996
- return set;
2092
+ createNode(nc, iterable) {
2093
+ const set = new YAMLSet(nc.schema);
2094
+ if (iterable && Symbol.iterator in Object(iterable)) for (let value of iterable) {
2095
+ if (typeof nc.replacer === "function") value = nc.replacer.call(iterable, value, value);
2096
+ const mk = nc.schema.mapKey(value);
2097
+ set.values.set(mk, nc.create(value));
1997
2098
  }
2099
+ return set;
2100
+ },
2101
+ resolve(set, onError) {
2102
+ if (!(set instanceof YAMLSet)) onError("Expected a set for this tag");
2103
+ return set;
1998
2104
  }
1999
2105
  };
2000
-
2001
2106
  //#endregion
2002
2107
  //#region src/schema/yaml-1.1/timestamp.ts
2003
2108
  /** Internal types handle bigint as number, because TS can't figure it out. */
@@ -2075,7 +2180,6 @@ const timestamp = {
2075
2180
  },
2076
2181
  stringify: ({ value }) => value?.toISOString().replace(/(T00:00:00)?\.000Z$/, "") ?? ""
2077
2182
  };
2078
-
2079
2183
  //#endregion
2080
2184
  //#region src/schema/yaml-1.1/schema.ts
2081
2185
  const schema = [
@@ -2101,7 +2205,6 @@ const schema = [
2101
2205
  floatTime,
2102
2206
  timestamp
2103
2207
  ];
2104
-
2105
2208
  //#endregion
2106
2209
  //#region src/schema/tags.ts
2107
2210
  const schemas = new Map([
@@ -2145,7 +2248,7 @@ const coreKnownTags = {
2145
2248
  };
2146
2249
  function getTags(customTags, schemaName, addMergeTag) {
2147
2250
  const schemaTags = schemas.get(schemaName);
2148
- if (schemaTags && !customTags) return addMergeTag && !schemaTags.includes(merge) ? schemaTags.concat(merge) : schemaTags.slice();
2251
+ if (schemaTags && !customTags) return addMergeTag && !schemaTags.includes(merge) ? [...schemaTags, merge] : schemaTags.slice();
2149
2252
  let tags = schemaTags;
2150
2253
  if (!tags) if (Array.isArray(customTags)) tags = [];
2151
2254
  else {
@@ -2154,7 +2257,7 @@ function getTags(customTags, schemaName, addMergeTag) {
2154
2257
  }
2155
2258
  if (Array.isArray(customTags)) for (const tag of customTags) tags = tags.concat(tag);
2156
2259
  else if (typeof customTags === "function") tags = customTags(tags.slice());
2157
- if (addMergeTag) tags = tags.concat(merge);
2260
+ if (addMergeTag) tags = [...tags, merge];
2158
2261
  return tags.reduce((tags, tag) => {
2159
2262
  const tagObj = typeof tag === "string" ? tagsByName[tag] : tag;
2160
2263
  if (!tagObj) {
@@ -2166,19 +2269,18 @@ function getTags(customTags, schemaName, addMergeTag) {
2166
2269
  return tags;
2167
2270
  }, []);
2168
2271
  }
2169
-
2170
2272
  //#endregion
2171
2273
  //#region src/schema/Schema.ts
2172
- const sortMapEntriesByKey = (a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
2173
2274
  var Schema = class Schema {
2174
2275
  compat;
2175
2276
  knownTags;
2277
+ mapKey;
2176
2278
  name;
2177
- sortMapEntries;
2178
2279
  tags;
2179
2280
  toStringOptions;
2180
- constructor({ compat, customTags, merge, resolveKnownTags, schema, sortMapEntries, toStringDefaults }) {
2281
+ constructor({ compat, customTags, mapKey, merge, resolveKnownTags, schema, toStringDefaults }) {
2181
2282
  this.compat = Array.isArray(compat) ? getTags(compat, "compat") : compat ? getTags(null, compat) : null;
2283
+ this.mapKey = mapKey ?? defaultMapKey;
2182
2284
  this.name = typeof schema === "string" && schema || "core";
2183
2285
  this.knownTags = resolveKnownTags ? coreKnownTags : {};
2184
2286
  this.tags = getTags(customTags, this.name, merge);
@@ -2186,7 +2288,6 @@ var Schema = class Schema {
2186
2288
  Object.defineProperty(this, "map", { value: map });
2187
2289
  Object.defineProperty(this, "scalar", { value: string });
2188
2290
  Object.defineProperty(this, "seq", { value: seq });
2189
- this.sortMapEntries = typeof sortMapEntries === "function" ? sortMapEntries : sortMapEntries === true ? sortMapEntriesByKey : null;
2190
2291
  }
2191
2292
  clone() {
2192
2293
  const copy = Object.create(Schema.prototype, Object.getOwnPropertyDescriptors(this));
@@ -2194,7 +2295,11 @@ var Schema = class Schema {
2194
2295
  return copy;
2195
2296
  }
2196
2297
  };
2197
-
2298
+ function defaultMapKey(value) {
2299
+ if (value instanceof Pair) value = value.key;
2300
+ if (value instanceof Scalar) value = value.value;
2301
+ return value ?? null;
2302
+ }
2198
2303
  //#endregion
2199
2304
  //#region src/stringify/stringifyDocument.ts
2200
2305
  function stringifyDocument(doc, options) {
@@ -2246,7 +2351,36 @@ function stringifyDocument(doc, options) {
2246
2351
  }
2247
2352
  return lines.join("\n") + "\n";
2248
2353
  }
2249
-
2354
+ //#endregion
2355
+ //#region src/doc/applyReviver.ts
2356
+ function applyReviver(reviver, obj, key, val) {
2357
+ if (val && typeof val === "object") if (Array.isArray(val)) for (let i = 0, len = val.length; i < len; ++i) {
2358
+ const v0 = val[i];
2359
+ const v1 = applyReviver(reviver, val, String(i), v0);
2360
+ if (v1 === void 0) delete val[i];
2361
+ else if (v1 !== v0) val[i] = v1;
2362
+ }
2363
+ else if (val instanceof Map) for (const k of Array.from(val.keys())) {
2364
+ const v0 = val.get(k);
2365
+ const v1 = applyReviver(reviver, val, k, v0);
2366
+ if (v1 === void 0) val.delete(k);
2367
+ else if (v1 !== v0) val.set(k, v1);
2368
+ }
2369
+ else if (val instanceof Set) for (const v0 of Array.from(val)) {
2370
+ const v1 = applyReviver(reviver, val, v0, v0);
2371
+ if (v1 === void 0) val.delete(v0);
2372
+ else if (v1 !== v0) {
2373
+ val.delete(v0);
2374
+ val.add(v1);
2375
+ }
2376
+ }
2377
+ else for (const [k, v0] of Object.entries(val)) {
2378
+ const v1 = applyReviver(reviver, val, k, v0);
2379
+ if (v1 === void 0) delete val[k];
2380
+ else if (v1 !== v0) val[k] = v1;
2381
+ }
2382
+ return reviver.call(obj, key, val);
2383
+ }
2250
2384
  //#endregion
2251
2385
  //#region src/doc/Document.ts
2252
2386
  var Document = class Document {
@@ -2276,7 +2410,6 @@ var Document = class Document {
2276
2410
  prettyErrors: true,
2277
2411
  strict: true,
2278
2412
  stringKeys: false,
2279
- uniqueKeys: true,
2280
2413
  version: "1.2"
2281
2414
  }, options);
2282
2415
  this.options = opt;
@@ -2306,14 +2439,6 @@ var Document = class Document {
2306
2439
  if (this.range) copy.range = this.range.slice();
2307
2440
  return copy;
2308
2441
  }
2309
- /** Adds a value to the document. */
2310
- add(value) {
2311
- assertCollection(this.value).add(value);
2312
- }
2313
- /** Adds a value to the document. */
2314
- addIn(path, value) {
2315
- assertCollection(this.value).addIn(path, value);
2316
- }
2317
2442
  /**
2318
2443
  * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
2319
2444
  *
@@ -2338,7 +2463,7 @@ var Document = class Document {
2338
2463
  } else if (Array.isArray(replacer)) {
2339
2464
  const keyToStr = (v) => typeof v === "number" || v instanceof String || v instanceof Number;
2340
2465
  const asStr = replacer.filter(keyToStr).map(String);
2341
- if (asStr.length > 0) replacer = replacer.concat(asStr);
2466
+ if (asStr.length > 0) replacer = [...replacer, ...asStr];
2342
2467
  nc = new NodeCreator(this, options, replacer);
2343
2468
  } else {
2344
2469
  options ??= replacer ?? void 0;
@@ -2359,63 +2484,34 @@ var Document = class Document {
2359
2484
  return pair;
2360
2485
  }
2361
2486
  /**
2362
- * Removes a value from the document.
2363
- * @returns `true` if the item was found and removed.
2364
- */
2365
- delete(key) {
2366
- return assertCollection(this.value).delete(key);
2367
- }
2368
- /**
2369
- * Removes a value from the document.
2370
- * @returns `true` if the item was found and removed.
2371
- */
2372
- deleteIn(path) {
2373
- if (!path.length) {
2374
- this.value = new Scalar(null);
2375
- return true;
2376
- }
2377
- return assertCollection(this.value).deleteIn(path);
2378
- }
2379
- /**
2380
2487
  * Returns item at `key`, or `undefined` if not found.
2381
2488
  */
2382
2489
  get(key) {
2383
- return this.value instanceof Collection ? this.value.get(key) : void 0;
2384
- }
2385
- /**
2386
- * Returns item at `path`, or `undefined` if not found.
2387
- */
2388
- getIn(path) {
2389
- if (!path.length) return this.value;
2390
- return this.value instanceof Collection ? this.value.getIn(path) : void 0;
2391
- }
2392
- /**
2393
- * Checks if the document includes a value with the key `key`.
2394
- */
2395
- has(key) {
2396
- return this.value instanceof Collection ? this.value.has(key) : false;
2490
+ if (this.value instanceof YAMLMap || this.value instanceof YAMLSet) return this.value.get(key);
2491
+ if (this.value instanceof YAMLSeq) {
2492
+ if (Number.isInteger(key)) return this.value.at(key);
2493
+ throw new TypeError(`Expected an integer, not ${JSON.stringify(key)}.`);
2494
+ }
2397
2495
  }
2398
2496
  /**
2399
- * Checks if the document includes a value at `path`.
2497
+ * Returns pair at `key`, or `undefined` if not found.
2400
2498
  */
2401
- hasIn(path) {
2402
- if (!path.length) return true;
2403
- return this.value instanceof Collection ? this.value.hasIn(path) : false;
2499
+ getPair(key) {
2500
+ if (this.value instanceof YAMLMap) return this.value.getPair(key);
2501
+ if (this.value instanceof YAMLSeq) {
2502
+ if (!Number.isInteger(key)) throw new TypeError(`Expected an integer, not ${JSON.stringify(key)}.`);
2503
+ const pair = this.value.at(key);
2504
+ if (pair instanceof Pair) return pair;
2505
+ throw new TypeError(`Value at ${key} is not a Pair`);
2506
+ }
2404
2507
  }
2405
2508
  /**
2406
- * Sets a value in this document. For `!!set`, `value` needs to be a
2407
- * boolean to add/remove the item from the set.
2509
+ * Sets a value in this document's top-level collection. For `!!set`, `value` is ignored.
2408
2510
  */
2409
2511
  set(key, value) {
2410
- assertCollection(this.value).set(key, value);
2411
- }
2412
- /**
2413
- * Sets a value in this document. For `!!set`, `value` needs to be a
2414
- * boolean to add/remove the item from the set.
2415
- */
2416
- setIn(path, value) {
2417
- if (!path.length) this.value = value;
2418
- else assertCollection(this.value).setIn(path, value);
2512
+ if (this.value instanceof YAMLSet) this.value.add(key);
2513
+ else if (this.value instanceof YAMLMap || this.value instanceof YAMLSeq) this.value.set(key, value);
2514
+ else throw new Error("Expected a YAML collection as document value");
2419
2515
  }
2420
2516
  /**
2421
2517
  * Change the YAML version and schema used by the document.
@@ -2458,32 +2554,17 @@ var Document = class Document {
2458
2554
  else if (opt) this.schema = new Schema(Object.assign(opt, options));
2459
2555
  else throw new Error(`With a null YAML version, the { schema: Schema } option is required`);
2460
2556
  }
2461
- toJS({ json, jsonArg, mapAsMap, maxAliasCount, onAnchor, reviver } = {}) {
2462
- const ctx = {
2463
- anchors: /* @__PURE__ */ new Map(),
2464
- doc: this,
2465
- keep: !json,
2466
- mapAsMap: mapAsMap === true,
2467
- mapKeyWarned: false,
2468
- maxAliasCount: typeof maxAliasCount === "number" ? maxAliasCount : 100
2469
- };
2470
- const res = toJS(this.value, jsonArg ?? "", ctx);
2557
+ /** A plain JavaScript representation of the document `value`. */
2558
+ toJS(opt = {}) {
2559
+ const { onAnchor, reviver } = opt;
2560
+ const ctx = new ToJSContext(opt);
2561
+ const res = this.value.toJS(this, ctx);
2471
2562
  if (typeof onAnchor === "function") for (const { count, res } of ctx.anchors.values()) onAnchor(res, count);
2472
2563
  return typeof reviver === "function" ? applyReviver(reviver, { "": res }, "", res) : res;
2473
2564
  }
2474
- /**
2475
- * A JSON representation of the document `value`.
2476
- *
2477
- * @param jsonArg Used by `JSON.stringify` to indicate the array index or
2478
- * property name.
2479
- */
2480
- toJSON(jsonArg, onAnchor) {
2481
- return this.toJS({
2482
- json: true,
2483
- jsonArg,
2484
- mapAsMap: false,
2485
- onAnchor
2486
- });
2565
+ /** A JSON representation of the document `value`. */
2566
+ toJSON() {
2567
+ return this.toJS({ mapAsMap: false });
2487
2568
  }
2488
2569
  /** A YAML representation of the document. */
2489
2570
  toString(options = {}) {
@@ -2495,11 +2576,6 @@ var Document = class Document {
2495
2576
  return stringifyDocument(this, options);
2496
2577
  }
2497
2578
  };
2498
- function assertCollection(value) {
2499
- if (value instanceof Collection) return value;
2500
- throw new Error("Expected a YAML collection as document value");
2501
- }
2502
-
2503
2579
  //#endregion
2504
2580
  //#region src/visit.ts
2505
2581
  const BREAK = Symbol("break visit");
@@ -2538,32 +2614,43 @@ const REMOVE = Symbol("remove node");
2538
2614
  const visit = function visit(node, visitor) {
2539
2615
  const visitor_ = initVisitor(visitor);
2540
2616
  if (node instanceof Document) {
2541
- if (visit_(null, node.value, visitor_, Object.freeze([node])) === REMOVE) node.value = new Scalar(null);
2542
- } else visit_(null, node, visitor_, Object.freeze([]));
2617
+ if (visit_(null, node.value, visitor_, [node]) === REMOVE) node.value = new Scalar(null);
2618
+ } else visit_(null, node, visitor_, []);
2543
2619
  };
2544
2620
  visit.BREAK = BREAK;
2545
2621
  visit.SKIP = SKIP;
2546
2622
  visit.REMOVE = REMOVE;
2547
2623
  function visit_(key, node, visitor, path) {
2548
2624
  const ctrl = callVisitor(key, node, visitor, path);
2549
- if (ctrl instanceof NodeBase || ctrl instanceof Pair) {
2625
+ if (isNode(ctrl) || ctrl instanceof Pair) {
2550
2626
  replaceNode(key, path, ctrl);
2551
2627
  return visit_(key, ctrl, visitor, path);
2552
2628
  }
2553
2629
  if (typeof ctrl !== "symbol") {
2554
- if (node instanceof YAMLMap || node instanceof YAMLSeq) {
2555
- path = Object.freeze(path.concat(node));
2556
- for (let i = 0; i < node.items.length; ++i) {
2557
- const ci = visit_(i, node.items[i], visitor, path);
2630
+ if (node instanceof YAMLSeq) {
2631
+ path = [...path, node];
2632
+ for (let i = 0; i < node.length; ++i) {
2633
+ const ci = visit_(i, node[i], visitor, path);
2558
2634
  if (typeof ci === "number") i = ci - 1;
2559
2635
  else if (ci === BREAK) return BREAK;
2560
2636
  else if (ci === REMOVE) {
2561
- node.items.splice(i, 1);
2637
+ node.splice(i, 1);
2562
2638
  i -= 1;
2563
2639
  }
2564
2640
  }
2641
+ } else if (node instanceof YAMLMap || node instanceof YAMLSet) {
2642
+ path = [...path, node];
2643
+ const entries = Array.from(node.values);
2644
+ const delKeys = [];
2645
+ for (let i = 0; i < entries.length; ++i) {
2646
+ const ci = visit_(i, entries[i][1], visitor, path);
2647
+ if (typeof ci === "number") i = ci - 1;
2648
+ else if (ci === BREAK) return BREAK;
2649
+ else if (ci === REMOVE) delKeys.push(entries[i][0]);
2650
+ }
2651
+ for (const dk of delKeys) node.values.delete(dk);
2565
2652
  } else if (node instanceof Pair) {
2566
- path = Object.freeze(path.concat(node));
2653
+ path = [...path, node];
2567
2654
  const ck = visit_("key", node.key, visitor, path);
2568
2655
  if (ck === BREAK) return BREAK;
2569
2656
  else if (ck === REMOVE) node.key = new Scalar(null);
@@ -2609,32 +2696,43 @@ function visit_(key, node, visitor, path) {
2609
2696
  const visitAsync = async function visitAsync(node, visitor) {
2610
2697
  const visitor_ = initVisitor(visitor);
2611
2698
  if (node instanceof Document) {
2612
- if (await visitAsync_(null, node.value, visitor_, Object.freeze([node])) === REMOVE) node.value = new Scalar(null);
2613
- } else await visitAsync_(null, node, visitor_, Object.freeze([]));
2699
+ if (await visitAsync_(null, node.value, visitor_, [node]) === REMOVE) node.value = new Scalar(null);
2700
+ } else await visitAsync_(null, node, visitor_, []);
2614
2701
  };
2615
2702
  visitAsync.BREAK = BREAK;
2616
2703
  visitAsync.SKIP = SKIP;
2617
2704
  visitAsync.REMOVE = REMOVE;
2618
2705
  async function visitAsync_(key, node, visitor, path) {
2619
2706
  const ctrl = await callVisitor(key, node, visitor, path);
2620
- if (ctrl instanceof NodeBase || ctrl instanceof Pair) {
2707
+ if (isNode(ctrl) || ctrl instanceof Pair) {
2621
2708
  replaceNode(key, path, ctrl);
2622
2709
  return visitAsync_(key, ctrl, visitor, path);
2623
2710
  }
2624
2711
  if (typeof ctrl !== "symbol") {
2625
- if (node instanceof YAMLMap || node instanceof YAMLSeq) {
2626
- path = Object.freeze(path.concat(node));
2627
- for (let i = 0; i < node.items.length; ++i) {
2628
- const ci = await visitAsync_(i, node.items[i], visitor, path);
2712
+ if (node instanceof YAMLSeq) {
2713
+ path = [...path, node];
2714
+ for (let i = 0; i < node.length; ++i) {
2715
+ const ci = await visitAsync_(i, node[i], visitor, path);
2629
2716
  if (typeof ci === "number") i = ci - 1;
2630
2717
  else if (ci === BREAK) return BREAK;
2631
2718
  else if (ci === REMOVE) {
2632
- node.items.splice(i, 1);
2719
+ node.splice(i, 1);
2633
2720
  i -= 1;
2634
2721
  }
2635
2722
  }
2723
+ } else if (node instanceof YAMLMap || node instanceof YAMLSet) {
2724
+ path = [...path, node];
2725
+ const entries = Array.from(node.values);
2726
+ const delKeys = [];
2727
+ for (let i = 0; i < entries.length; ++i) {
2728
+ const ci = await visitAsync_(i, entries[i][1], visitor, path);
2729
+ if (typeof ci === "number") i = ci - 1;
2730
+ else if (ci === BREAK) return BREAK;
2731
+ else if (ci === REMOVE) delKeys.push(entries[i][0]);
2732
+ }
2733
+ for (const dk of delKeys) node.values.delete(dk);
2636
2734
  } else if (node instanceof Pair) {
2637
- path = Object.freeze(path.concat(node));
2735
+ path = [...path, node];
2638
2736
  const ck = await visitAsync_("key", node.key, visitor, path);
2639
2737
  if (ck === BREAK) return BREAK;
2640
2738
  else if (ck === REMOVE) node.key = new Scalar(null);
@@ -2663,7 +2761,7 @@ function initVisitor(visitor) {
2663
2761
  }
2664
2762
  function callVisitor(key, node, visitor, path) {
2665
2763
  if (typeof visitor === "function") return visitor(key, node, path);
2666
- if (node instanceof YAMLMap) return visitor.Map?.(key, node, path);
2764
+ if (node instanceof YAMLMap || node instanceof YAMLSet) return visitor.Map?.(key, node, path);
2667
2765
  if (node instanceof YAMLSeq) return visitor.Seq?.(key, node, path);
2668
2766
  if (node instanceof Pair) return visitor.Pair?.(key, node, path);
2669
2767
  if (node instanceof Scalar) return visitor.Scalar?.(key, node, path);
@@ -2671,17 +2769,27 @@ function callVisitor(key, node, visitor, path) {
2671
2769
  }
2672
2770
  function replaceNode(key, path, node) {
2673
2771
  const parent = path[path.length - 1];
2674
- if (parent instanceof YAMLMap || parent instanceof YAMLSeq) parent.items[key] = node;
2675
- else if (parent instanceof Pair) if (node instanceof NodeBase) if (key === "key") parent.key = node;
2772
+ if (parent instanceof YAMLSeq) parent[key] = node;
2773
+ else if (parent instanceof YAMLMap) if (node instanceof Pair) {
2774
+ const entries = Array.from(parent.values);
2775
+ entries[key] = [parent.keyOf(node, true), node];
2776
+ parent.values = new Map(entries);
2777
+ } else throw new Error("Cannot replace map pair with non-pair value");
2778
+ else if (parent instanceof YAMLSet) if (isNode(node)) {
2779
+ const entries = Array.from(parent.values);
2780
+ entries[key] = [parent.keyOf(node, true), node];
2781
+ parent.values = new Map(entries);
2782
+ } else throw new Error("Cannot replace set value with non-node value");
2783
+ else if (parent instanceof Pair) if (isNode(node)) if (key === "key") parent.key = node;
2676
2784
  else parent.value = node;
2677
2785
  else throw new Error(`Cannot replace pair ${key} with non-node value`);
2678
- else if (parent instanceof Document) parent.value = node;
2786
+ else if (parent instanceof Document) if (node instanceof Scalar || isCollection(node)) parent.value = node;
2787
+ else throw new Error("Cannot replace Document value with non-node value");
2679
2788
  else {
2680
2789
  const pt = parent instanceof Alias ? "alias" : "scalar";
2681
2790
  throw new Error(`Cannot replace node with ${pt} parent`);
2682
2791
  }
2683
2792
  }
2684
-
2685
2793
  //#endregion
2686
2794
  //#region src/doc/directives.ts
2687
2795
  const escapeChars = {
@@ -2840,7 +2948,7 @@ var Directives = class Directives {
2840
2948
  if (doc && tagEntries.length > 0) {
2841
2949
  const tags = {};
2842
2950
  visit(doc.value, (_key, node) => {
2843
- if (node instanceof NodeBase && node.tag) tags[node.tag] = true;
2951
+ if (node?.tag) tags[node.tag] = true;
2844
2952
  });
2845
2953
  tagNames = Object.keys(tags);
2846
2954
  } else tagNames = [];
@@ -2851,6 +2959,5 @@ var Directives = class Directives {
2851
2959
  return lines.join("\n");
2852
2960
  }
2853
2961
  };
2854
-
2855
2962
  //#endregion
2856
- export { toJS as S, Collection as _, Schema as a, Scalar as b, seq as c, findPair as d, Alias as f, YAMLSeq as g, warn as h, Document as i, map as l, debug as m, visit as n, stringifyNumber as o, Pair as p, visitAsync as r, string as s, Directives as t, YAMLMap as u, stringifyString as v, NodeBase as x, foldFlowLines as y };
2963
+ export { Scalar as S, ToJSContext as _, Schema as a, stringifyString as b, seq as c, Pair as d, isCollection as f, YAMLMap as g, YAMLSeq as h, Document as i, map as l, YAMLSet as m, visit as n, stringifyNumber as o, isNode as p, visitAsync as r, string as s, Directives as t, Alias as u, debug as v, foldFlowLines as x, warn as y };