yaml 3.0.0-0 → 3.0.0-2

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";
@@ -135,20 +46,22 @@ function foldFlowLines(text, indent, mode = "flow", { indentAtStart, lineWidth =
135
46
  const folds = [];
136
47
  const escapedFolds = {};
137
48
  let end = lineWidth - indent.length;
138
- if (typeof indentAtStart === "number") if (indentAtStart > lineWidth - Math.max(2, minContentWidth)) folds.push(0);
139
- else end = lineWidth - indentAtStart;
49
+ if (typeof indentAtStart === "number") {
50
+ if (indentAtStart > lineWidth - Math.max(2, minContentWidth)) folds.push(0);
51
+ else end = lineWidth - indentAtStart;
52
+ }
140
53
  let split = void 0;
141
54
  let prev = void 0;
142
55
  let overflow = false;
143
56
  let i = -1;
144
57
  let escStart = -1;
145
58
  let escEnd = -1;
146
- if (mode === FOLD_BLOCK) {
59
+ if (mode === "block") {
147
60
  i = consumeMoreIndentedLines(text, i, indent.length);
148
61
  if (i !== -1) end = i + endStep;
149
62
  }
150
63
  for (let ch; ch = text[i += 1];) {
151
- if (mode === FOLD_QUOTED && ch === "\\") {
64
+ if (mode === "quoted" && ch === "\\") {
152
65
  escStart = i;
153
66
  switch (text[i + 1]) {
154
67
  case "x":
@@ -165,7 +78,7 @@ function foldFlowLines(text, indent, mode = "flow", { indentAtStart, lineWidth =
165
78
  escEnd = i;
166
79
  }
167
80
  if (ch === "\n") {
168
- if (mode === FOLD_BLOCK) i = consumeMoreIndentedLines(text, i, indent.length);
81
+ if (mode === "block") i = consumeMoreIndentedLines(text, i, indent.length);
169
82
  end = i + indent.length + endStep;
170
83
  split = void 0;
171
84
  } else {
@@ -173,23 +86,25 @@ function foldFlowLines(text, indent, mode = "flow", { indentAtStart, lineWidth =
173
86
  const next = text[i + 1];
174
87
  if (next && next !== " " && next !== "\n" && next !== " ") split = i;
175
88
  }
176
- if (i >= end) if (split) {
177
- folds.push(split);
178
- end = split + endStep;
179
- split = void 0;
180
- } else if (mode === FOLD_QUOTED) {
181
- while (prev === " " || prev === " ") {
182
- prev = ch;
183
- ch = text[i += 1];
184
- overflow = true;
185
- }
186
- const j = i > escEnd + 1 ? i - 2 : escStart - 1;
187
- if (escapedFolds[j]) return text;
188
- folds.push(j);
189
- escapedFolds[j] = true;
190
- end = j + endStep;
191
- split = void 0;
192
- } else overflow = true;
89
+ if (i >= end) {
90
+ if (split) {
91
+ folds.push(split);
92
+ end = split + endStep;
93
+ split = void 0;
94
+ } else if (mode === "quoted") {
95
+ while (prev === " " || prev === " ") {
96
+ prev = ch;
97
+ ch = text[i += 1];
98
+ overflow = true;
99
+ }
100
+ const j = i > escEnd + 1 ? i - 2 : escStart - 1;
101
+ if (escapedFolds[j]) return text;
102
+ folds.push(j);
103
+ escapedFolds[j] = true;
104
+ end = j + endStep;
105
+ split = void 0;
106
+ } else overflow = true;
107
+ }
193
108
  }
194
109
  prev = ch;
195
110
  }
@@ -202,7 +117,7 @@ function foldFlowLines(text, indent, mode = "flow", { indentAtStart, lineWidth =
202
117
  const end = folds[i + 1] || text.length;
203
118
  if (fold === 0) res = `\n${indent}${text.slice(0, end)}`;
204
119
  else {
205
- if (mode === FOLD_QUOTED && escapedFolds[fold]) res += `${text[fold]}\\`;
120
+ if (mode === "quoted" && escapedFolds[fold]) res += `${text[fold]}\\`;
206
121
  res += `\n${indent}${text.slice(fold + 1, end)}`;
207
122
  }
208
123
  }
@@ -227,7 +142,6 @@ function consumeMoreIndentedLines(text, i, indent) {
227
142
  }
228
143
  return end;
229
144
  }
230
-
231
145
  //#endregion
232
146
  //#region src/stringify/stringifyString.ts
233
147
  const getFoldOptions = (ctx, isBlock) => ({
@@ -341,7 +255,7 @@ function quotedString(value, ctx) {
341
255
  }
342
256
  let blockEndNewlines;
343
257
  try {
344
- blockEndNewlines = /* @__PURE__ */ new RegExp("(^|(?<!\n))\n+(?!\n|$)", "g");
258
+ blockEndNewlines = new RegExp("(^|(?<!\n))\n+(?!\n|$)", "g");
345
259
  } catch {
346
260
  blockEndNewlines = /\n+(?!\n|$)/g;
347
261
  }
@@ -415,7 +329,7 @@ function plainString(item, ctx, onComment, onChompKeep) {
415
329
  }
416
330
  const str = value.replace(/\n+/g, `$&\n${indent}`);
417
331
  if (actualString) {
418
- const test = (tag) => tag.default && tag.tag !== "tag:yaml.org,2002:str" && tag.test?.test(str);
332
+ const test = (tag) => tag.default && tag.tag !== "tag:yaml.org,2002:str" && tag.test?.(str);
419
333
  const { compat, tags } = ctx.doc.schema;
420
334
  if (tags.some(test) || compat?.some(test)) return quotedString(value, ctx);
421
335
  }
@@ -447,7 +361,6 @@ function stringifyString(item, ctx, onComment, onChompKeep) {
447
361
  }
448
362
  return res;
449
363
  }
450
-
451
364
  //#endregion
452
365
  //#region src/doc/anchors.ts
453
366
  /**
@@ -476,7 +389,6 @@ function findNewAnchor(prefix, exclude) {
476
389
  if (!exclude.has(name)) return name;
477
390
  }
478
391
  }
479
-
480
392
  //#endregion
481
393
  //#region src/doc/NodeCreator.ts
482
394
  const defaultTagPrefix = "tag:yaml.org,2002:";
@@ -484,7 +396,6 @@ var NodeCreator = class {
484
396
  keepUndefined;
485
397
  replacer;
486
398
  schema;
487
- #aliasDuplicateObjects;
488
399
  #anchorPrefix;
489
400
  #aliasObjects = [];
490
401
  #doc;
@@ -497,24 +408,19 @@ var NodeCreator = class {
497
408
  this.replacer = replacer;
498
409
  this.#flow = options.flow ?? false;
499
410
  this.#onTagObj = options.onTagObj;
500
- this.#aliasDuplicateObjects = options.aliasDuplicateObjects ?? true;
501
411
  this.#anchorPrefix = options.anchorPrefix || "a";
502
412
  if (docOrSchema instanceof Document) {
503
- this.#doc = docOrSchema;
413
+ if (options.aliasDuplicateObjects ?? true) this.#doc = docOrSchema;
504
414
  this.schema = docOrSchema.schema;
505
415
  } else this.schema = docOrSchema;
506
416
  }
507
417
  create(value, tagName) {
508
418
  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
- }
419
+ if (isNode(value)) return value;
420
+ if (value instanceof Pair) return this.schema.map.createNode(this, null).set(value);
515
421
  if (value instanceof String || value instanceof Number || value instanceof Boolean || typeof BigInt !== "undefined" && value instanceof BigInt) value = value.valueOf();
516
422
  let ref = void 0;
517
- if (this.#aliasDuplicateObjects && value && typeof value === "object") {
423
+ if (this.#doc && value && typeof value === "object") {
518
424
  ref = this.#sourceObjects.get(value);
519
425
  if (ref) {
520
426
  if (!ref.anchor) {
@@ -552,11 +458,11 @@ var NodeCreator = class {
552
458
  this.#onTagObj(tagObj);
553
459
  this.#onTagObj = void 0;
554
460
  }
555
- const node = tagObj?.createNode?.(this, value) ?? tagObj?.nodeClass?.from?.(this, value) ?? new Scalar(value);
461
+ const node = tagObj?.createNode?.(this, value) ?? new Scalar(value);
556
462
  if (tagName) node.tag = tagName;
557
463
  else if (!tagObj.default) node.tag = tagObj.tag;
558
464
  if (ref) ref.node = node;
559
- if (this.#flow && node instanceof Collection) node.flow = true;
465
+ if (this.#flow && isCollection(node)) node.flow = true;
560
466
  return node;
561
467
  }
562
468
  createPair(key, value) {
@@ -570,109 +476,11 @@ var NodeCreator = class {
570
476
  setAnchors() {
571
477
  for (const source of this.#aliasObjects) {
572
478
  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 });
575
- }
576
- }
577
- };
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}`);
479
+ if (typeof ref === "object" && ref.anchor && (ref.node instanceof Scalar || isCollection(ref.node))) ref.node.anchor = ref.anchor;
480
+ else throw Object.assign(/* @__PURE__ */ new Error("Failed to resolve repeated object (this should not happen)"), { source });
672
481
  }
673
482
  }
674
483
  };
675
-
676
484
  //#endregion
677
485
  //#region src/stringify/stringifyComment.ts
678
486
  /**
@@ -688,29 +496,104 @@ function indentComment(comment, indent) {
688
496
  return indent ? comment.replace(/^(?! *$)/gm, indent) : comment;
689
497
  }
690
498
  const lineComment = (str, indent, comment) => str.endsWith("\n") ? indentComment(comment, indent) : comment.includes("\n") ? "\n" + indentComment(comment, indent) : (str.endsWith(" ") ? "" : " ") + comment;
691
-
499
+ //#endregion
500
+ //#region src/log.ts
501
+ function debug(logLevel, ...messages) {
502
+ if (logLevel === "debug") console.log(...messages);
503
+ }
504
+ function warn(logLevel, warning) {
505
+ if (logLevel === "debug" || logLevel === "warn") {
506
+ if (typeof process !== "undefined" && typeof process.emitWarning === "function") process.emitWarning(warning);
507
+ else console.warn(warning);
508
+ }
509
+ }
510
+ //#endregion
511
+ //#region src/schema/yaml-1.1/merge.ts
512
+ const MERGE_KEY = "<<";
513
+ const merge = {
514
+ identify: (value) => value === MERGE_KEY || typeof value === "symbol" && value.description === MERGE_KEY,
515
+ default: "key",
516
+ tag: "tag:yaml.org,2002:merge",
517
+ test: (str) => str === MERGE_KEY,
518
+ resolve: () => Object.assign(new Scalar(Symbol(MERGE_KEY)), { addToJSMap: addMergeToJSMap }),
519
+ stringify: () => MERGE_KEY
520
+ };
521
+ 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));
522
+ function addMergeToJSMap(doc, ctx, map, value, isPlainObject) {
523
+ const source = getMergeSource(doc, ctx, value);
524
+ if (Array.isArray(source)) for (const it of source) mergeValue(doc, ctx, map, it, isPlainObject);
525
+ else mergeValue(doc, ctx, map, value, isPlainObject);
526
+ }
527
+ function mergeValue(doc, ctx, map, value, isPlainObject) {
528
+ const srcMap = getMergeSource(doc, ctx, value).toJS(doc, ctx, Map);
529
+ if (!(srcMap instanceof Map)) throw new Error("Merge sources must be maps or map aliases");
530
+ for (const [key, value] of srcMap) if (map instanceof Map) {
531
+ if (!map.has(key)) map.set(key, value);
532
+ } else if (map instanceof Set) map.add(key);
533
+ else if (!Object.prototype.hasOwnProperty.call(map, key)) {
534
+ if (!isPlainObject || key === "__proto__" || key === "constructor") Object.defineProperty(map, key, {
535
+ value,
536
+ writable: true,
537
+ enumerable: true,
538
+ configurable: true
539
+ });
540
+ else map[key] = value;
541
+ }
542
+ return map;
543
+ }
544
+ function getMergeSource(doc, ctx, value) {
545
+ if (!(value instanceof Alias)) return value;
546
+ const source = value.resolve(doc, ctx);
547
+ if (!source) {
548
+ const msg = `Unresolved alias (the anchor must be set before the alias): ${value.source}`;
549
+ throw new ReferenceError(msg);
550
+ }
551
+ ctx.resolveAlias(doc, source);
552
+ return source;
553
+ }
692
554
  //#endregion
693
555
  //#region src/stringify/stringify.ts
556
+ const defaultStringifyOptions = {
557
+ blockQuote: true,
558
+ commentString: stringifyComment,
559
+ defaultKeyType: null,
560
+ defaultStringType: "PLAIN",
561
+ directives: null,
562
+ doubleQuotedAsJSON: false,
563
+ doubleQuotedMinMultiLineLength: 40,
564
+ falseStr: "false",
565
+ flowCollectionPadding: true,
566
+ indentSeq: true,
567
+ lineWidth: 80,
568
+ minContentWidth: 20,
569
+ nullStr: "null",
570
+ simpleKeys: false,
571
+ singleQuote: null,
572
+ sortMapEntries: false,
573
+ trailingComma: false,
574
+ trueStr: "true",
575
+ verifyAliasOrder: true
576
+ };
577
+ const resolvedCache = /* @__PURE__ */ new WeakMap();
578
+ function getResolvedOptions(schema) {
579
+ const key = schema.toStringOptions ?? defaultStringifyOptions;
580
+ let resolved = resolvedCache.get(key);
581
+ if (!resolved) {
582
+ resolved = schema.toStringOptions ? {
583
+ ...defaultStringifyOptions,
584
+ ...schema.toStringOptions
585
+ } : defaultStringifyOptions;
586
+ resolvedCache.set(key, resolved);
587
+ }
588
+ return resolved;
589
+ }
590
+ const sortMapEntriesByKey = (a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
694
591
  function createStringifyContext(doc, options) {
695
- const opt = Object.assign({
696
- blockQuote: true,
697
- commentString: stringifyComment,
698
- defaultKeyType: null,
699
- defaultStringType: "PLAIN",
700
- directives: null,
701
- doubleQuotedAsJSON: false,
702
- doubleQuotedMinMultiLineLength: 40,
703
- falseStr: "false",
704
- flowCollectionPadding: true,
705
- indentSeq: true,
706
- lineWidth: 80,
707
- minContentWidth: 20,
708
- nullStr: "null",
709
- simpleKeys: false,
710
- singleQuote: null,
711
- trueStr: "true",
712
- verifyAliasOrder: true
713
- }, doc.schema.toStringOptions, options);
592
+ const resolved = getResolvedOptions(doc.schema);
593
+ const opt = options ? {
594
+ ...resolved,
595
+ ...options
596
+ } : resolved;
714
597
  let inFlow;
715
598
  switch (opt.collectionStyle) {
716
599
  case "block":
@@ -721,6 +604,7 @@ function createStringifyContext(doc, options) {
721
604
  break;
722
605
  default: inFlow = null;
723
606
  }
607
+ const sortMapEntries = typeof opt.sortMapEntries === "function" ? opt.sortMapEntries : opt.sortMapEntries === true ? sortMapEntriesByKey : null;
724
608
  return {
725
609
  anchors: /* @__PURE__ */ new Set(),
726
610
  doc,
@@ -728,7 +612,8 @@ function createStringifyContext(doc, options) {
728
612
  indent: "",
729
613
  indentStep: typeof opt.indent === "number" ? " ".repeat(opt.indent) : " ",
730
614
  inFlow,
731
- options: opt
615
+ options: opt,
616
+ sortMapEntries
732
617
  };
733
618
  }
734
619
  function getTagObject(tags, item) {
@@ -736,7 +621,7 @@ function getTagObject(tags, item) {
736
621
  const match = tags.filter((t) => t.tag === item.tag);
737
622
  if (match.length > 0) return match.find((t) => t.format === item.format) ?? match[0];
738
623
  }
739
- let tagObj = void 0;
624
+ let tagObj;
740
625
  let obj;
741
626
  if (item instanceof Scalar) {
742
627
  obj = item.value;
@@ -759,7 +644,7 @@ function getTagObject(tags, item) {
759
644
  function stringifyProps(node, tagObj, { anchors, doc }) {
760
645
  if (!doc.directives) return "";
761
646
  const props = [];
762
- const anchor = (node instanceof Scalar || node instanceof Collection) && node.anchor;
647
+ const anchor = node.anchor;
763
648
  if (anchor && anchorIsValid(anchor)) {
764
649
  anchors.add(anchor);
765
650
  props.push(`&${anchor}`);
@@ -768,19 +653,17 @@ function stringifyProps(node, tagObj, { anchors, doc }) {
768
653
  if (tag) props.push(doc.directives.tagString(tag));
769
654
  return props.join(" ");
770
655
  }
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
- }
656
+ function stringify(node, ctx, onComment, onChompKeep) {
657
+ if (node instanceof Pair) return node.toString(ctx, onComment, onChompKeep);
658
+ if (node instanceof Alias) {
659
+ if (ctx.doc.directives) return node.toString(ctx);
660
+ if (ctx.resolvedAliases?.has(node)) throw new TypeError("Cannot stringify circular structure without alias nodes");
661
+ if (ctx.resolvedAliases) ctx.resolvedAliases.add(node);
662
+ else ctx.resolvedAliases = /* @__PURE__ */ new Set([node]);
663
+ node = node.resolve(ctx.doc) ?? null;
781
664
  }
782
665
  let tagObj = void 0;
783
- const node = item instanceof NodeBase ? item : ctx.doc.createNode(item, { onTagObj: (o) => tagObj = o });
666
+ node ??= ctx.doc.createNode(null, { onTagObj: (o) => tagObj = o });
784
667
  tagObj ??= getTagObject(ctx.doc.schema.tags, node);
785
668
  const props = stringifyProps(node, tagObj, ctx);
786
669
  if (props.length > 0) ctx.indentAtStart = (ctx.indentAtStart ?? 0) + props.length + 1;
@@ -788,242 +671,720 @@ function stringify(item, ctx, onComment, onChompKeep) {
788
671
  if (!props) return str;
789
672
  return node instanceof Scalar || str[0] === "{" || str[0] === "[" ? `${props} ${str}` : `${props}\n${ctx.indent}${str}`;
790
673
  }
791
-
792
674
  //#endregion
793
- //#region src/stringify/stringifyCollection.ts
794
- function stringifyCollection(collection, ctx, options) {
795
- return (ctx.inFlow ?? collection.flow ? stringifyFlowCollection : stringifyBlockCollection)(collection, ctx, options);
675
+ //#region src/nodes/addPairToJSMap.ts
676
+ function addPairToJSMap(doc, ctx, map, { key, value }, isPlainObject) {
677
+ if ("addToJSMap" in key) key.addToJSMap?.(doc, ctx, map, value, isPlainObject);
678
+ else if (isMergeKey(doc, key)) addMergeToJSMap(doc, ctx, map, value, isPlainObject);
679
+ else {
680
+ const jsKey = key.toJS(doc, ctx);
681
+ if (map instanceof Map) map.set(jsKey, value ? value.toJS(doc, ctx) : value);
682
+ else if (map instanceof Set) map.add(jsKey);
683
+ else {
684
+ const stringKey = stringifyKey(doc, ctx, key, jsKey);
685
+ const jsValue = value ? value.toJS(doc, ctx) : value;
686
+ if (!isPlainObject && stringKey in map || stringKey === "__proto__" || stringKey === "constructor") Object.defineProperty(map, stringKey, {
687
+ value: jsValue,
688
+ writable: true,
689
+ enumerable: true,
690
+ configurable: true
691
+ });
692
+ else map[stringKey] = jsValue;
693
+ }
694
+ }
695
+ return map;
796
696
  }
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);
697
+ function stringifyKey(doc, ctx, key, jsKey) {
698
+ if (jsKey === null) return "";
699
+ if (typeof jsKey !== "object") return String(jsKey);
700
+ const strCtx = createStringifyContext(doc, void 0);
701
+ for (const node of ctx.anchors.keys()) strCtx.anchors.add(node.anchor);
702
+ strCtx.inFlow = true;
703
+ strCtx.inStringifyKey = true;
704
+ const strKey = key.toString(strCtx);
705
+ if (!ctx.mapKeyWarned) {
706
+ let jsonStr = JSON.stringify(strKey);
707
+ if (jsonStr.length > 40) jsonStr = jsonStr.substring(0, 36) + "...\"";
708
+ const msg = `Keys with collection values will be stringified due to JS Object restrictions: ${jsonStr}. Set mapAsMap: true to use a Map instead.`;
709
+ warn(doc.options.logLevel, msg);
710
+ ctx.mapKeyWarned = true;
711
+ }
712
+ return strKey;
713
+ }
714
+ //#endregion
715
+ //#region src/nodes/util-clone-map-or-set.ts
716
+ function cloneMapOrSet(coll, schema) {
717
+ schema ??= coll.schema;
718
+ const copy = new coll.constructor(schema);
719
+ for (const [key, value] of coll.values) copy.values.set(key, value.clone(schema));
720
+ if (coll.range) copy.range = [...coll.range];
721
+ const propDesc = Object.getOwnPropertyDescriptors(coll);
722
+ for (const [name, prop] of Object.entries(propDesc)) if (!(name in copy)) Object.defineProperty(copy, name, prop);
723
+ return copy;
724
+ }
725
+ //#endregion
726
+ //#region src/nodes/YAMLMap.ts
727
+ var YAMLMap = class {
728
+ static tagName = "tag:yaml.org,2002:map";
729
+ values = /* @__PURE__ */ new Map();
730
+ /**
731
+ * A generic collection factory method that can be used
732
+ * by other node classes that inherit from YAMLMap
733
+ */
734
+ static create(nc, obj) {
735
+ const { replacer } = nc;
736
+ const map = new this(nc.schema);
737
+ if (obj && typeof obj === "object") {
738
+ const iter = obj instanceof Map ? obj : Object.entries(obj);
739
+ for (let [key, value] of iter) {
740
+ if (replacer) {
741
+ if (typeof replacer === "function") value = replacer.call(obj, key, value);
742
+ else if (Array.isArray(replacer) && !replacer.includes(key)) continue;
743
+ }
744
+ if (value !== void 0 || nc.keepUndefined) {
745
+ const mk = nc.schema.mapKey(key);
746
+ const pair = nc.createPair(key, value);
747
+ map.values.set(mk, pair);
748
+ }
817
749
  }
818
750
  }
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);
751
+ return map;
824
752
  }
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";
753
+ constructor(schema, elements) {
754
+ Object.defineProperty(this, "schema", {
755
+ value: schema,
756
+ configurable: true,
757
+ enumerable: false,
758
+ writable: true
759
+ });
760
+ this.values = new Map(elements?.map((pair) => [this.schema.mapKey(pair), pair]));
761
+ }
762
+ get size() {
763
+ return this.values.size;
764
+ }
765
+ /**
766
+ * Create a copy of this map.
767
+ *
768
+ * @param schema - If defined, overwrites the original's schema
769
+ */
770
+ clone(schema) {
771
+ return cloneMapOrSet(this, schema);
772
+ }
773
+ /**
774
+ * Remove a value from the mapping.
775
+ * @returns `true` if the item was found and removed.
776
+ */
777
+ delete(key) {
778
+ let mk = this.schema.mapKey(key);
779
+ if (this.values.delete(mk)) return true;
780
+ mk = key instanceof Pair ? key.key : isNode(key) ? key : null;
781
+ if (mk) {
782
+ for (const [k, p] of this.values) if (p.key === mk) return this.values.delete(k);
832
783
  }
784
+ return false;
833
785
  }
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;
786
+ /** Return value at `key`, or `undefined` if not found. */
787
+ get(key) {
788
+ return this.getPair(key)?.value;
789
+ }
790
+ /** Return pair at `key`, or `undefined` if not found. */
791
+ getPair(key) {
792
+ let mk = this.schema.mapKey(key);
793
+ const pair = this.values.get(mk);
794
+ if (pair) return pair;
795
+ mk = key instanceof Pair ? key.key : isNode(key) ? key : null;
796
+ if (mk) {
797
+ for (const p of this.values.values()) if (p.key === mk) return p;
798
+ }
799
+ }
800
+ /** Check if the mapping includes a value with the key `key`. */
801
+ has(key) {
802
+ let mk = this.schema.mapKey(key);
803
+ if (this.values.has(mk)) return true;
804
+ mk = key instanceof Pair ? key.key : isNode(key) ? key : null;
805
+ if (mk) {
806
+ for (const p of this.values.values()) if (p.key === mk) return true;
807
+ }
808
+ return false;
809
+ }
810
+ /**
811
+ * Return the internal Map key matching `key`, or `undefined` if not found.
812
+ *
813
+ * @param allowMissing - If `true`, a key is always returned,
814
+ * even if the key is not in the map.
815
+ */
816
+ keyOf(key, allowMissing = false) {
817
+ let mk = this.schema.mapKey(key);
818
+ if (allowMissing || this.values.has(mk)) return mk;
819
+ mk = key instanceof Pair ? key.key : isNode(key) ? key : null;
820
+ if (mk) {
821
+ for (const [k, v] of this.values) if (v.key === mk) return k;
822
+ }
823
+ }
824
+ pairs() {
825
+ return this.values.values();
826
+ }
827
+ set(keyOrPair, value, options) {
828
+ const mk = this.schema.mapKey(keyOrPair);
829
+ let pair;
830
+ if (keyOrPair instanceof Pair) pair = keyOrPair;
831
+ else if (isNode(keyOrPair) && (value == null || isNode(value))) pair = new Pair(keyOrPair, value ?? null);
832
+ else pair = new NodeCreator(this.schema, options).createPair(keyOrPair, value);
833
+ if (pair.value instanceof Scalar) {
834
+ const prev = this.values.get(mk);
835
+ if (prev) {
836
+ if (!prev.value) {
837
+ prev.value = pair.value;
838
+ return this;
839
+ }
840
+ if (prev.value instanceof Scalar) {
841
+ Object.assign(prev.value, pair.value);
842
+ return this;
843
+ }
844
+ }
845
+ }
846
+ this.values.set(mk, pair);
847
+ return this;
848
+ }
849
+ toJS(doc, ctx, Type) {
850
+ ctx ??= new ToJSContext();
851
+ let map;
852
+ let isPlainObject = false;
853
+ if (Type) map = new Type();
854
+ else if (ctx.mapAsMap) map = /* @__PURE__ */ new Map();
855
+ else {
856
+ map = {};
857
+ isPlainObject = true;
858
+ }
859
+ if (this.anchor) ctx.setAnchor(this, map);
860
+ for (const pair of this.values.values()) addPairToJSMap(doc, ctx, map, pair, isPlainObject);
861
+ return map;
862
+ }
863
+ toString(ctx, onComment, onChompKeep) {
864
+ if (!ctx) return JSON.stringify(this);
865
+ let pairs = this.values.values();
866
+ if (ctx.sortMapEntries) pairs = Array.from(pairs).sort(ctx.sortMapEntries);
867
+ return ctx.inFlow ?? this.flow ? this.#stringifyFlowMap(ctx, pairs) : this.#stringifyBlockMap(ctx, pairs, onComment, onChompKeep);
868
+ }
869
+ #stringifyBlockMap(ctx, pairs, onComment, onChompKeep) {
870
+ const { indent, options: { commentString } } = ctx;
871
+ let chompKeep = false;
872
+ const lines = [];
873
+ for (const pair of pairs) {
874
+ let comment = null;
875
+ if (!chompKeep && pair.key.spaceBefore) lines.push("");
876
+ let cb = pair.key.commentBefore;
877
+ if (cb && chompKeep) cb = cb.replace(/^\n+/, "");
878
+ if (cb) {
879
+ const ic = indentComment(commentString(cb), indent).trimStart();
880
+ lines.push(ic);
881
+ }
882
+ chompKeep = false;
883
+ let str = stringifyPair(pair, ctx, () => comment = null, () => chompKeep = true);
884
+ if (comment) str += lineComment(str, indent, commentString(comment));
885
+ if (chompKeep && comment) chompKeep = false;
886
+ lines.push(str);
887
+ }
888
+ let str;
889
+ if (lines.length === 0) str = "{}";
890
+ else {
891
+ str = lines[0];
892
+ for (let i = 1; i < lines.length; ++i) {
893
+ const line = lines[i];
894
+ str += line ? `\n${indent}${line}` : "\n";
864
895
  }
865
- const iv = item.value instanceof NodeBase ? item.value : null;
896
+ }
897
+ if (this.comment) {
898
+ str += "\n" + indentComment(commentString(this.comment), indent);
899
+ onComment?.();
900
+ } else if (chompKeep) onChompKeep?.();
901
+ return str;
902
+ }
903
+ #stringifyFlowMap(ctx, pairs) {
904
+ const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString, lineWidth, trailingComma } } = ctx;
905
+ const itemIndent = indent + indentStep;
906
+ const itemCtx = {
907
+ ...ctx,
908
+ indent: itemIndent,
909
+ inFlow: true
910
+ };
911
+ let reqNewline = false;
912
+ let linesAtValue = 0;
913
+ const lines = [];
914
+ let itemsLeft = this.values.size;
915
+ for (const pair of pairs) {
916
+ itemsLeft -= 1;
917
+ let comment = null;
918
+ const ik = pair.key;
919
+ if (ik.spaceBefore) {
920
+ lines.push("");
921
+ reqNewline = true;
922
+ }
923
+ if (ik.commentBefore) {
924
+ const ic = indentComment(commentString(ik.commentBefore), indent);
925
+ lines.push(ic.trimStart());
926
+ reqNewline = true;
927
+ }
928
+ if (ik.comment) reqNewline = true;
929
+ const iv = pair.value;
866
930
  if (iv) {
867
931
  if (iv.comment) comment = iv.comment;
868
932
  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 {
933
+ } else if (ik?.comment) comment = ik.comment;
934
+ if (comment) reqNewline = true;
935
+ let str = stringifyPair(pair, itemCtx, () => comment = null);
936
+ reqNewline ||= lines.length > linesAtValue || str.includes("\n");
937
+ if (itemsLeft > 0) str += ",";
938
+ else if (trailingComma) {
939
+ if (!reqNewline && lineWidth > 0) reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) + (str.length + 2) > lineWidth;
940
+ if (reqNewline) str += ",";
941
+ }
942
+ if (comment) str += lineComment(str, itemIndent, commentString(comment));
943
+ lines.push(str);
944
+ linesAtValue = lines.length;
945
+ }
946
+ if (lines.length === 0) return "{}";
882
947
  if (!reqNewline) {
883
948
  const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
884
949
  reqNewline = ctx.options.lineWidth > 0 && len > ctx.options.lineWidth;
885
950
  }
886
951
  if (reqNewline) {
887
- let str = start;
952
+ let str = "{";
888
953
  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}`;
891
- }
892
- }
893
- function addCommentBefore({ indent, options: { commentString } }, lines, comment, chompKeep) {
894
- if (comment && chompKeep) comment = comment.replace(/^\n+/, "");
895
- if (comment) {
896
- const ic = indentComment(commentString(comment), indent);
897
- lines.push(ic.trimStart());
954
+ return `${str}\n${indent}}`;
955
+ }
956
+ return `{${fcPadding}${lines.join(" ")}${fcPadding}}`;
898
957
  }
899
- }
900
-
958
+ };
901
959
  //#endregion
902
960
  //#region src/nodes/YAMLSeq.ts
903
961
  const isScalarValue = (value) => !value || typeof value !== "function" && typeof value !== "object";
904
- var YAMLSeq = class extends Collection {
962
+ var YAMLSeq = class extends Array {
905
963
  static get tagName() {
906
964
  return "tag:yaml.org,2002:seq";
907
965
  }
908
- items = [];
909
- 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();
966
+ /**
967
+ * A generic collection factory method that can be extended
968
+ * to other node classes that inherit from YAMLSeq
969
+ */
970
+ static create(nc, obj) {
971
+ const seq = new this(nc.schema);
972
+ if (obj && Symbol.iterator in Object(obj)) {
973
+ let i = 0;
974
+ for (let it of obj) {
975
+ if (typeof nc.replacer === "function") {
976
+ const key = obj instanceof Set ? it : String(i++);
977
+ it = nc.replacer.call(obj, key, it);
978
+ }
979
+ seq.push(nc.create(it));
980
+ }
919
981
  }
982
+ return seq;
983
+ }
984
+ constructor(schema, elements = []) {
985
+ super(...nodeValues(schema, elements));
986
+ Object.defineProperty(this, "schema", {
987
+ value: schema,
988
+ configurable: true,
989
+ enumerable: false,
990
+ writable: true
991
+ });
992
+ }
993
+ get size() {
994
+ return this.length;
920
995
  }
921
996
  /**
922
- * Removes a value from the collection.
923
- *
924
- * Throws if `idx` is not a non-negative integer.
997
+ * Create a copy of this collection.
925
998
  *
926
- * @returns `true` if the item was found and removed.
999
+ * @param schema - If defined, overwrites the original's schema
927
1000
  */
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;
1001
+ clone(schema) {
1002
+ const copy = this.constructor.from(this, (it) => it.clone(schema));
1003
+ if (this.range) copy.range = [...this.range];
1004
+ const propDesc = Object.getOwnPropertyDescriptors(this);
1005
+ for (const [name, prop] of Object.entries(propDesc)) if (!(name in copy)) Object.defineProperty(copy, name, prop);
1006
+ if (schema) copy.schema = schema;
1007
+ return copy;
932
1008
  }
933
1009
  /**
934
- * Returns item at `key`, or `undefined` if not found.
1010
+ * Change all elements within a range of indices in this sequence to a static value.
935
1011
  *
936
- * Throws if `idx` is not a non-negative integer.
1012
+ * Non-node values are converted to Node values.
937
1013
  */
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];
1014
+ fill(value, start, end) {
1015
+ return super.fill(nodeValue(this.schema, value), start, end);
1016
+ }
1017
+ /** @private */
1018
+ _push(item) {
1019
+ super.push(item);
942
1020
  }
943
1021
  /**
944
- * Checks if the collection includes a value with the key `key`.
1022
+ * Append new elements to this sequence, and return its new length.
945
1023
  *
946
- * Throws if `idx` is not a non-negative integer.
1024
+ * Non-node values are converted to Node values.
947
1025
  */
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;
1026
+ push(...values) {
1027
+ return super.push(...nodeValues(this.schema, values));
952
1028
  }
953
1029
  /**
954
- * Sets a value in this collection. For `!!set`, `value` needs to be a
955
- * boolean to add/remove the item from the set.
1030
+ * Set a value in this sequence.
956
1031
  *
957
- * Throws if `idx` is not a non-negative integer.
1032
+ * Non-node values are converted to Node values.
958
1033
  */
959
1034
  set(idx, value, options) {
960
1035
  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];
1036
+ const prev = this.at(idx);
963
1037
  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
1038
  else {
967
- const nc = new NodeCreator(this.schema, {
968
- ...options,
969
- aliasDuplicateObjects: false
970
- });
971
- this.items[idx] = nc.create(value);
972
- nc.setAnchors();
1039
+ if (idx < 0) {
1040
+ if (idx < -this.length) throw new RangeError(`Invalid index ${idx}`);
1041
+ idx += this.length;
1042
+ }
1043
+ this[idx] = nodeValue(this.schema, value, options);
973
1044
  }
974
1045
  }
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;
1046
+ /**
1047
+ * Changes the contents of this sequence by removing or replacing existing elements
1048
+ * and/or adding new elements in place.
1049
+ *
1050
+ * Non-node values are converted to Node values.
1051
+ */
1052
+ splice(start, deleteCount, ...values) {
1053
+ const nv = nodeValues(this.schema, values);
1054
+ return arguments.length < 2 ? super.splice(start) : super.splice(start, Number(deleteCount), ...nv);
1055
+ }
1056
+ /**
1057
+ * Prepend new elements to this sequence, and return its new length.
1058
+ *
1059
+ * Non-node values are converted to Node values.
1060
+ */
1061
+ unshift(...values) {
1062
+ return super.unshift(...nodeValues(this.schema, values));
1063
+ }
1064
+ /** A plain JavaScript representation of this node. */
1065
+ toJS(doc, ctx) {
1066
+ ctx ??= new ToJSContext();
1067
+ if (this.anchor) {
1068
+ const res = [];
1069
+ if (this.anchor) ctx.setAnchor(this, res);
1070
+ for (const item of this) res.push(item.toJS(doc, ctx));
1071
+ return res;
1072
+ }
1073
+ return Array.from(this, (item) => item.toJS(doc, ctx));
981
1074
  }
982
1075
  toString(ctx, onComment, onChompKeep) {
983
1076
  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
1077
+ return ctx.inFlow ?? this.flow ? this.#stringifyFlowSeq(ctx) : this.#stringifyBlockSeq(ctx, onComment, onChompKeep);
1078
+ }
1079
+ #stringifyBlockSeq(ctx, onComment, onChompKeep) {
1080
+ const { indent, options: { commentString } } = ctx;
1081
+ const itemIndent = indent + " ";
1082
+ const itemCtx = {
1083
+ ...ctx,
1084
+ indent: itemIndent
1085
+ };
1086
+ let chompKeep = false;
1087
+ const lines = [];
1088
+ for (let i = 0; i < this.length; ++i) {
1089
+ const item = this[i];
1090
+ let comment = null;
1091
+ if (item instanceof Pair) {
1092
+ if (!chompKeep && item.key.spaceBefore) lines.push("");
1093
+ addCommentBefore(ctx, lines, item.key.commentBefore, chompKeep);
1094
+ } else if (item) {
1095
+ if (!chompKeep && item.spaceBefore) lines.push("");
1096
+ addCommentBefore(ctx, lines, item.commentBefore, chompKeep);
1097
+ if (item.comment) comment = item.comment;
1098
+ }
1099
+ chompKeep = false;
1100
+ let str = stringify(item, itemCtx, () => comment = null, () => chompKeep = true);
1101
+ if (comment) str += lineComment(str, itemIndent, commentString(comment));
1102
+ if (chompKeep && comment) chompKeep = false;
1103
+ lines.push(`- ${str}`);
1104
+ }
1105
+ let str;
1106
+ if (lines.length === 0) str = "[]";
1107
+ else {
1108
+ str = lines[0];
1109
+ for (let i = 1; i < lines.length; ++i) {
1110
+ const line = lines[i];
1111
+ str += line ? `\n${indent}${line}` : "\n";
1112
+ }
1113
+ }
1114
+ if (this.comment) {
1115
+ str += "\n" + indentComment(commentString(this.comment), indent);
1116
+ onComment?.();
1117
+ } else if (chompKeep) onChompKeep?.();
1118
+ return str;
1119
+ }
1120
+ #stringifyFlowSeq(ctx) {
1121
+ const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString } } = ctx;
1122
+ const itemIndent = indent + " " + indentStep;
1123
+ const itemCtx = {
1124
+ ...ctx,
1125
+ indent: itemIndent,
1126
+ inFlow: true
1127
+ };
1128
+ let reqNewline = false;
1129
+ let linesAtValue = 0;
1130
+ const lines = [];
1131
+ for (let i = 0; i < this.length; ++i) {
1132
+ const item = this[i];
1133
+ let comment = null;
1134
+ if (item instanceof Pair) {
1135
+ const ik = item.key;
1136
+ if (ik.spaceBefore) lines.push("");
1137
+ addCommentBefore(ctx, lines, ik.commentBefore, false);
1138
+ if (ik.comment) reqNewline = true;
1139
+ const iv = item.value;
1140
+ if (iv) {
1141
+ if (iv.comment) comment = iv.comment;
1142
+ if (iv.commentBefore) reqNewline = true;
1143
+ } else if (ik?.comment) comment = ik.comment;
1144
+ } else if (item) {
1145
+ if (item.spaceBefore) lines.push("");
1146
+ addCommentBefore(ctx, lines, item.commentBefore, false);
1147
+ if (item.comment) comment = item.comment;
1148
+ }
1149
+ if (comment) reqNewline = true;
1150
+ let str = stringify(item, itemCtx, () => comment = null);
1151
+ reqNewline ||= lines.length > linesAtValue || str.includes("\n");
1152
+ if (i < this.length - 1) str += ",";
1153
+ else if (ctx.options.trailingComma) {
1154
+ if (ctx.options.lineWidth > 0) reqNewline ||= lines.reduce((sum, line) => sum + line.length + 2, 2) + (str.length + 2) > ctx.options.lineWidth;
1155
+ if (reqNewline) str += ",";
1156
+ }
1157
+ if (comment) str += lineComment(str, itemIndent, commentString(comment));
1158
+ lines.push(str);
1159
+ linesAtValue = lines.length;
1160
+ }
1161
+ if (lines.length === 0) return "[]";
1162
+ if (!reqNewline) {
1163
+ const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
1164
+ reqNewline = ctx.options.lineWidth > 0 && len > ctx.options.lineWidth;
1165
+ }
1166
+ if (reqNewline) {
1167
+ let str = "[";
1168
+ for (const line of lines) str += line ? `\n${indentStep}${indent}${line}` : "\n";
1169
+ return `${str}\n${indent}]`;
1170
+ }
1171
+ return `[${fcPadding}${lines.join(" ")}${fcPadding}]`;
1172
+ }
1173
+ };
1174
+ function nodeValue(schema, value, options) {
1175
+ if (isNode(value) || value instanceof Pair) return value;
1176
+ return new NodeCreator(schema, options).create(value);
1177
+ }
1178
+ function nodeValues(schema, values) {
1179
+ let nc;
1180
+ return values.map((value) => {
1181
+ if (isNode(value) || value instanceof Pair) return value;
1182
+ nc ??= new NodeCreator(schema);
1183
+ return nc.create(value);
1184
+ });
1185
+ }
1186
+ function addCommentBefore({ indent, options: { commentString } }, lines, comment, chompKeep) {
1187
+ if (comment && chompKeep) comment = comment.replace(/^\n+/, "");
1188
+ if (comment) {
1189
+ const ic = indentComment(commentString(comment), indent);
1190
+ lines.push(ic.trimStart());
1191
+ }
1192
+ }
1193
+ //#endregion
1194
+ //#region src/nodes/YAMLSet.ts
1195
+ var YAMLSet = class {
1196
+ static tagName = "tag:yaml.org,2002:set";
1197
+ /** A fully qualified tag */
1198
+ tag = "tag:yaml.org,2002:set";
1199
+ values = /* @__PURE__ */ new Map();
1200
+ constructor(schema) {
1201
+ Object.defineProperty(this, "schema", {
1202
+ value: schema,
1203
+ configurable: true,
1204
+ enumerable: false,
1205
+ writable: true
993
1206
  });
994
1207
  }
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));
1208
+ get size() {
1209
+ return this.values.size;
1210
+ }
1211
+ add(value, options) {
1212
+ if (this.has(value)) return this;
1213
+ const mk = this.schema.mapKey(value);
1214
+ const node = isNode(value) ? value : new NodeCreator(this.schema, options).create(value);
1215
+ this.values.set(mk, node);
1216
+ return this;
1217
+ }
1218
+ /**
1219
+ * Create a copy of this set.
1220
+ *
1221
+ * @param schema - If defined, overwrites the original's schema
1222
+ */
1223
+ clone(schema) {
1224
+ return cloneMapOrSet(this, schema);
1225
+ }
1226
+ /**
1227
+ * Remove `value` from the set.
1228
+ * @returns `true` if the item was found and removed.
1229
+ */
1230
+ delete(value) {
1231
+ const mk = this.schema.mapKey(value);
1232
+ if (this.values.delete(mk)) return true;
1233
+ if (isNode(value)) {
1234
+ for (const [k, v] of this.values) if (v === value) return this.values.delete(k);
1235
+ }
1236
+ return false;
1237
+ }
1238
+ /** Return the node matching `value`, if the set includes it. */
1239
+ get(value) {
1240
+ const mk = this.schema.mapKey(value);
1241
+ const node = this.values.get(mk);
1242
+ if (node) return node;
1243
+ if (isNode(value)) {
1244
+ for (const v of this.values.values()) if (v === value) return v;
1245
+ }
1246
+ }
1247
+ /** Check if the set includes `value`. */
1248
+ has(value) {
1249
+ const mk = this.schema.mapKey(value);
1250
+ if (this.values.has(mk)) return true;
1251
+ if (isNode(value)) {
1252
+ for (const v of this.values.values()) if (v === value) return true;
1253
+ }
1254
+ return false;
1255
+ }
1256
+ /**
1257
+ * Return the internal Map key matching `value`, or `undefined` if not found.
1258
+ *
1259
+ * @param allowMissing - If `true`, a key is always returned,
1260
+ * even if the value is not in the set.
1261
+ */
1262
+ keyOf(value, allowMissing = false) {
1263
+ const mk = this.schema.mapKey(value);
1264
+ if (allowMissing || this.values.has(mk)) return mk;
1265
+ if (isNode(value)) {
1266
+ for (const [k, v] of this.values) if (v === value) return k;
1267
+ }
1268
+ }
1269
+ /** A plain JavaScript representation of this set. */
1270
+ toJS(doc, ctx) {
1271
+ ctx ??= new ToJSContext();
1272
+ const set = /* @__PURE__ */ new Set();
1273
+ if (this.anchor) ctx.setAnchor(this, set);
1274
+ for (const item of this.values.values()) set.add(item.toJS(doc, ctx));
1275
+ return set;
1276
+ }
1277
+ toString(ctx, onComment, onChompKeep) {
1278
+ if (!ctx) return JSON.stringify(this);
1279
+ let items = this.values.values();
1280
+ if (ctx.sortMapEntries) items = Array.from(items, (item) => new Pair(item)).sort(ctx.sortMapEntries).map((pair) => pair.key);
1281
+ if (ctx.inFlow ?? this.flow) return this.#stringifyFlowSet(ctx, items);
1282
+ else return this.#stringifyBlockSet(ctx, items, onComment, onChompKeep);
1283
+ }
1284
+ #stringifyBlockSet(ctx, items, onComment, onChompKeep) {
1285
+ const { indent, indentStep, options: { commentString } } = ctx;
1286
+ const itemCtx = {
1287
+ ...ctx,
1288
+ implicitKey: false,
1289
+ indent: indent + indentStep
1290
+ };
1291
+ let chompKeep = false;
1292
+ let res = null;
1293
+ for (const item of items) {
1294
+ if (!chompKeep && item.spaceBefore) {
1295
+ if (typeof res === "string") res += "\n";
1296
+ else res = "";
1005
1297
  }
1298
+ let cb = item.commentBefore;
1299
+ if (cb && chompKeep) cb = cb.replace(/^\n+/, "");
1300
+ if (cb) {
1301
+ const ic = indentComment(commentString(cb), indent).trimStart();
1302
+ if (typeof res === "string") res += `\n${indent}${ic}`;
1303
+ else res = ic;
1304
+ }
1305
+ chompKeep = false;
1306
+ let comment = item.comment;
1307
+ let str = stringify(item, itemCtx, () => comment = null, () => chompKeep = true);
1308
+ str = str ? `? ${str}` : "?";
1309
+ if (comment) {
1310
+ str += lineComment(str, itemCtx.indent, commentString(comment));
1311
+ chompKeep = false;
1312
+ }
1313
+ if (typeof res === "string") res += `\n${indent}${str}`;
1314
+ else res = str;
1315
+ }
1316
+ if (this.comment) {
1317
+ const cs = commentString(this.comment);
1318
+ if (typeof res === "string") res += "\n" + indentComment(cs, indent);
1319
+ else res = "{}" + lineComment("", indent, cs);
1320
+ onComment?.();
1321
+ } else if (chompKeep) onChompKeep?.();
1322
+ return res ?? "{}";
1323
+ }
1324
+ #stringifyFlowSet(ctx, items) {
1325
+ const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString, lineWidth, trailingComma } } = ctx;
1326
+ const itemCtx = {
1327
+ ...ctx,
1328
+ indent: indent + indentStep + indentStep,
1329
+ inFlow: true
1330
+ };
1331
+ let reqNewline = false;
1332
+ const lines = [];
1333
+ let itemsLeft = this.values.size;
1334
+ let singleLineWidth = 2 * fcPadding.length;
1335
+ for (const item of items) {
1336
+ itemsLeft -= 1;
1337
+ if (item.spaceBefore) {
1338
+ lines.push("");
1339
+ reqNewline = true;
1340
+ }
1341
+ if (item.commentBefore) {
1342
+ const ic = indentComment(commentString(item.commentBefore), indent);
1343
+ lines.push(ic.trimStart());
1344
+ reqNewline = true;
1345
+ }
1346
+ let comment = item.comment;
1347
+ if (comment) reqNewline = true;
1348
+ itemCtx.implicitKey = !isCollection(item);
1349
+ let str = stringify(item, itemCtx, () => comment = null) || "?";
1350
+ if (isCollection(item)) str = `? ${str}`;
1351
+ reqNewline ||= str.includes("\n");
1352
+ if (!reqNewline && lineWidth > 0) {
1353
+ singleLineWidth += str.length + 2;
1354
+ if (singleLineWidth > lineWidth) reqNewline = true;
1355
+ }
1356
+ if (itemsLeft > 0 || trailingComma && reqNewline) str += ",";
1357
+ if (comment) str += lineComment(str, indent + indentStep, commentString(comment));
1358
+ lines.push(str);
1006
1359
  }
1007
- return seq;
1360
+ if (lines.length === 0) return "{}";
1361
+ if (!reqNewline) return `{${fcPadding}${lines.join(" ")}${fcPadding}}`;
1362
+ let str = "{";
1363
+ for (const line of lines) str += line ? `\n${indentStep}${indent}${line}` : "\n";
1364
+ return `${str}\n${indent}}`;
1008
1365
  }
1009
1366
  };
1010
-
1367
+ //#endregion
1368
+ //#region src/nodes/identity.ts
1369
+ /** Type predicate for collections */
1370
+ const isCollection = (node) => node instanceof YAMLMap || node instanceof YAMLSeq || node instanceof YAMLSet;
1371
+ /** Type predicate for `Node` values */
1372
+ const isNode = (node) => node instanceof Scalar || node instanceof Alias || node instanceof YAMLMap || node instanceof YAMLSeq || node instanceof YAMLSet;
1011
1373
  //#endregion
1012
1374
  //#region src/stringify/stringifyPair.ts
1013
1375
  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;
1376
+ const { indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
1016
1377
  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");
1378
+ if (key.comment) throw new Error("With simple keys, key nodes cannot have comments");
1379
+ if (isCollection(key)) throw new Error("With simple keys, collection cannot be used as a key value");
1019
1380
  }
1020
- let explicitKey = !simpleKeys && (!key || !(key instanceof Scalar) || key.type === Scalar.BLOCK_FOLDED || key.type === Scalar.BLOCK_LITERAL);
1381
+ let explicitKey = !simpleKeys && (!(key instanceof Scalar) || key.type === Scalar.BLOCK_FOLDED || key.type === Scalar.BLOCK_LITERAL);
1021
1382
  ctx = {
1022
1383
  ...ctx,
1023
- implicitKey: !explicitKey && (simpleKeys || !noValues),
1024
- indent: indent + indentStep,
1025
- noValues: false
1384
+ implicitKey: !explicitKey,
1385
+ indent: indent + indentStep
1026
1386
  };
1387
+ let keyComment = key.comment;
1027
1388
  let keyCommentDone = false;
1028
1389
  let chompKeep = false;
1029
1390
  let str = stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true);
@@ -1032,11 +1393,11 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
1032
1393
  explicitKey = true;
1033
1394
  }
1034
1395
  if (ctx.inFlow) {
1035
- if (noValues || value == null) {
1396
+ if (value == null) {
1036
1397
  if (keyCommentDone && onComment) onComment();
1037
- return str === "" ? "?" : explicitKey ? `? ${str}` : noValues ? str : `${str}:`;
1398
+ return str === "" ? "?" : explicitKey ? `? ${str}` : `${str}:`;
1038
1399
  }
1039
- } else if (noValues && !simpleKeys || value == null && explicitKey) {
1400
+ } else if (value == null && explicitKey) {
1040
1401
  str = `? ${str}`;
1041
1402
  if (keyComment && !keyCommentDone) str += lineComment(str, ctx.indent, commentString(keyComment));
1042
1403
  else if (chompKeep && onChompKeep) onChompKeep();
@@ -1051,7 +1412,7 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
1051
1412
  if (keyComment) str += lineComment(str, ctx.indent, commentString(keyComment));
1052
1413
  }
1053
1414
  let vsb, vcb, valueComment;
1054
- if (value instanceof NodeBase) {
1415
+ if (value) {
1055
1416
  vsb = !!value.spaceBefore;
1056
1417
  vcb = value.commentBefore;
1057
1418
  valueComment = value.comment;
@@ -1059,7 +1420,6 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
1059
1420
  vsb = false;
1060
1421
  vcb = null;
1061
1422
  valueComment = null;
1062
- if (value && typeof value === "object") value = doc.createNode(value);
1063
1423
  }
1064
1424
  ctx.implicitKey = false;
1065
1425
  if (!explicitKey && !keyComment && value instanceof Scalar) ctx.indentAtStart = str.length + 1;
@@ -1077,11 +1437,11 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
1077
1437
  if (valueStr === "" && !ctx.inFlow) {
1078
1438
  if (ws === "\n" && valueComment) ws = "\n\n";
1079
1439
  } else ws += `\n${ctx.indent}`;
1080
- } else if (!explicitKey && value instanceof Collection) {
1440
+ } else if (!explicitKey && isCollection(value)) {
1081
1441
  const vs0 = valueStr[0];
1082
1442
  const nl0 = valueStr.indexOf("\n");
1083
1443
  const hasNewline = nl0 !== -1;
1084
- const flow = ctx.inFlow ?? value.flow ?? value.items.length === 0;
1444
+ const flow = ctx.inFlow ?? value.flow ?? value.size === 0;
1085
1445
  if (hasNewline || !flow) {
1086
1446
  let hasPropsLine = false;
1087
1447
  if (hasNewline && (vs0 === "&" || vs0 === "!")) {
@@ -1099,94 +1459,6 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
1099
1459
  else if (chompKeep && onChompKeep) onChompKeep();
1100
1460
  return str;
1101
1461
  }
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
1462
  //#endregion
1191
1463
  //#region src/nodes/Pair.ts
1192
1464
  var Pair = class Pair {
@@ -1197,32 +1469,97 @@ var Pair = class Pair {
1197
1469
  this.value = value;
1198
1470
  }
1199
1471
  clone(schema) {
1200
- return new Pair(this.key.clone(schema), this.value?.clone(schema) ?? null);
1472
+ const key = this.key.clone(schema);
1473
+ const value = this.value?.clone(schema) ?? null;
1474
+ return new Pair(key, value);
1201
1475
  }
1202
- toJSON(_, ctx) {
1203
- return addPairToJSMap(ctx, ctx?.mapAsMap ? /* @__PURE__ */ new Map() : {}, this);
1476
+ toJS(doc, ctx) {
1477
+ return addPairToJSMap(doc, ctx, ctx.mapAsMap ? /* @__PURE__ */ new Map() : {}, this, true);
1204
1478
  }
1205
1479
  toString(ctx, onComment, onChompKeep) {
1206
1480
  return ctx?.doc ? stringifyPair(this, ctx, onComment, onChompKeep) : JSON.stringify(this);
1207
1481
  }
1208
1482
  };
1209
-
1483
+ //#endregion
1484
+ //#region src/nodes/toJS.ts
1485
+ /** A context used in `node.toJS()` implementations */
1486
+ var ToJSContext = class {
1487
+ anchors = /* @__PURE__ */ new Map();
1488
+ /** Cached anchor and alias nodes in the order they occur in the document */
1489
+ aliasResolveCache;
1490
+ mapAsMap;
1491
+ mapKeyWarned = false;
1492
+ maxAliasCount;
1493
+ constructor(opt) {
1494
+ this.mapAsMap = opt?.mapAsMap === true;
1495
+ this.maxAliasCount = opt?.maxAliasCount ?? 100;
1496
+ }
1497
+ setAnchor(node, res) {
1498
+ const anchor = this.anchors.get(node);
1499
+ if (anchor) anchor.res = res;
1500
+ else this.anchors.set(node, {
1501
+ aliasCount: 0,
1502
+ count: 1,
1503
+ res
1504
+ });
1505
+ }
1506
+ resolveAlias(doc, source) {
1507
+ let data = this.anchors.get(source);
1508
+ if (!data) {
1509
+ source.toJS(doc, this);
1510
+ data = this.anchors.get(source);
1511
+ }
1512
+ /* istanbul ignore if */
1513
+ if (data?.res === void 0) throw new ReferenceError("This should not happen: Alias anchor was not resolved?");
1514
+ if (this.maxAliasCount >= 0) {
1515
+ data.count += 1;
1516
+ data.aliasCount ||= this.#getAliasCount(doc, source);
1517
+ if (data.count * data.aliasCount > this.maxAliasCount) throw new ReferenceError("Excessive alias count indicates a resource exhaustion attack");
1518
+ }
1519
+ return data.res;
1520
+ }
1521
+ #getAliasCount(doc, node) {
1522
+ if (node instanceof Alias) {
1523
+ const source = node.resolve(doc, this);
1524
+ const anchor = source && this.anchors.get(source);
1525
+ return anchor ? anchor.count * anchor.aliasCount : 0;
1526
+ } else if (node instanceof Pair) {
1527
+ const kc = this.#getAliasCount(doc, node.key);
1528
+ const vc = this.#getAliasCount(doc, node.value);
1529
+ return Math.max(kc, vc);
1530
+ } else if (Array.isArray(node)) {
1531
+ let count = 0;
1532
+ for (const item of node) {
1533
+ const c = this.#getAliasCount(doc, item);
1534
+ if (c > count) count = c;
1535
+ }
1536
+ return count;
1537
+ }
1538
+ return 1;
1539
+ }
1540
+ };
1210
1541
  //#endregion
1211
1542
  //#region src/nodes/Alias.ts
1212
- var Alias = class Alias extends NodeBase {
1543
+ var Alias = class Alias {
1213
1544
  source;
1214
1545
  constructor(source) {
1215
- super();
1216
1546
  this.source = source;
1217
1547
  Object.defineProperty(this, "tag", { set() {
1218
1548
  throw new Error("Alias nodes cannot have tags");
1219
1549
  } });
1220
1550
  }
1551
+ /** Create a copy of this node. */
1552
+ clone() {
1553
+ const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
1554
+ if (this.range) copy.range = [...this.range];
1555
+ return copy;
1556
+ }
1221
1557
  /**
1222
1558
  * Resolve the value of this alias within `doc`, finding the last
1223
1559
  * instance of the `source` anchor before this node.
1224
1560
  */
1225
1561
  resolve(doc, ctx) {
1562
+ if (ctx?.maxAliasCount === 0) throw new ReferenceError("Alias resolution is disabled");
1226
1563
  let nodes;
1227
1564
  if (ctx?.aliasResolveCache) nodes = ctx.aliasResolveCache;
1228
1565
  else {
@@ -1239,27 +1576,16 @@ var Alias = class Alias extends NodeBase {
1239
1576
  }
1240
1577
  return found;
1241
1578
  }
1242
- toJSON(_arg, ctx) {
1243
- if (!ctx) return { source: this.source };
1244
- const { anchors, doc, maxAliasCount } = ctx;
1579
+ /** A plain JavaScript representation of the resolved value of this alias. */
1580
+ toJS(doc, ctx) {
1581
+ if (!doc?.schema) throw new TypeError("A document argument is required");
1582
+ ctx ??= new ToJSContext();
1245
1583
  const source = this.resolve(doc, ctx);
1246
1584
  if (!source) {
1247
1585
  const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
1248
1586
  throw new ReferenceError(msg);
1249
1587
  }
1250
- let data = anchors.get(source);
1251
- if (!data) {
1252
- toJS(source, null, ctx);
1253
- data = anchors.get(source);
1254
- }
1255
- /* istanbul ignore if */
1256
- if (data?.res === void 0) throw new ReferenceError("This should not happen: Alias anchor was not resolved?");
1257
- if (maxAliasCount >= 0) {
1258
- data.count += 1;
1259
- if (data.aliasCount === 0) data.aliasCount = getAliasCount(doc, source, anchors);
1260
- if (data.count * data.aliasCount > maxAliasCount) throw new ReferenceError("Excessive alias count indicates a resource exhaustion attack");
1261
- }
1262
- return data.res;
1588
+ return ctx.resolveAlias(doc, source);
1263
1589
  }
1264
1590
  toString(ctx, _onComment, _onChompKeep) {
1265
1591
  const src = `*${this.source}`;
@@ -1274,122 +1600,6 @@ var Alias = class Alias extends NodeBase {
1274
1600
  return src;
1275
1601
  }
1276
1602
  };
1277
- function getAliasCount(doc, node, anchors) {
1278
- if (node instanceof Alias) {
1279
- const source = node.resolve(doc);
1280
- const anchor = anchors && source && anchors.get(source);
1281
- return anchor ? anchor.count * anchor.aliasCount : 0;
1282
- } else if (node instanceof NodeBase && "items" in node) {
1283
- const coll = node;
1284
- let count = 0;
1285
- for (const item of coll.items) {
1286
- const c = getAliasCount(doc, item, anchors);
1287
- if (c > count) count = c;
1288
- }
1289
- 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
- }
1295
- return 1;
1296
- }
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
1603
  //#endregion
1394
1604
  //#region src/schema/common/map.ts
1395
1605
  const map = {
@@ -1397,12 +1607,14 @@ const map = {
1397
1607
  default: true,
1398
1608
  nodeClass: YAMLMap,
1399
1609
  tag: "tag:yaml.org,2002:map",
1610
+ createNode(nc, obj) {
1611
+ return YAMLMap.create(nc, obj);
1612
+ },
1400
1613
  resolve(map, onError) {
1401
1614
  if (!(map instanceof YAMLMap)) onError("Expected a mapping for this tag");
1402
1615
  return map;
1403
1616
  }
1404
1617
  };
1405
-
1406
1618
  //#endregion
1407
1619
  //#region src/schema/common/seq.ts
1408
1620
  const seq = {
@@ -1410,12 +1622,14 @@ const seq = {
1410
1622
  default: true,
1411
1623
  nodeClass: YAMLSeq,
1412
1624
  tag: "tag:yaml.org,2002:seq",
1625
+ createNode(nc, obj) {
1626
+ return YAMLSeq.create(nc, obj);
1627
+ },
1413
1628
  resolve(seq, onError) {
1414
1629
  if (!(seq instanceof YAMLSeq)) onError("Expected a sequence for this tag");
1415
1630
  return seq;
1416
1631
  }
1417
1632
  };
1418
-
1419
1633
  //#endregion
1420
1634
  //#region src/schema/common/string.ts
1421
1635
  const string = {
@@ -1428,43 +1642,61 @@ const string = {
1428
1642
  return stringifyString(item, ctx, onComment, onChompKeep);
1429
1643
  }
1430
1644
  };
1431
-
1432
1645
  //#endregion
1433
1646
  //#region src/schema/common/null.ts
1647
+ const nullValues = /* @__PURE__ */ new Set([
1648
+ "",
1649
+ "~",
1650
+ "null",
1651
+ "Null",
1652
+ "NULL"
1653
+ ]);
1434
1654
  const nullTag = {
1435
1655
  identify: (value) => value == null,
1436
1656
  createNode: () => new Scalar(null),
1437
1657
  default: true,
1438
1658
  tag: "tag:yaml.org,2002:null",
1439
- test: /^(?:~|[Nn]ull|NULL)?$/,
1659
+ test: (value) => nullValues.has(value),
1440
1660
  resolve: () => new Scalar(null),
1441
- stringify: ({ source }, ctx) => typeof source === "string" && nullTag.test.test(source) ? source : ctx.options.nullStr
1661
+ stringify: ({ source }, ctx) => typeof source === "string" && nullTag.test(source) ? source : ctx.options.nullStr
1442
1662
  };
1443
-
1444
1663
  //#endregion
1445
1664
  //#region src/schema/core/bool.ts
1665
+ const boolValues = /* @__PURE__ */ new Set([
1666
+ "true",
1667
+ "True",
1668
+ "TRUE",
1669
+ "false",
1670
+ "False",
1671
+ "FALSE"
1672
+ ]);
1446
1673
  const boolTag = {
1447
1674
  identify: (value) => typeof value === "boolean",
1448
1675
  default: true,
1449
1676
  tag: "tag:yaml.org,2002:bool",
1450
- test: /^(?:[Tt]rue|TRUE|[Ff]alse|FALSE)$/,
1677
+ test: (value) => boolValues.has(value),
1451
1678
  resolve: (str) => new Scalar(str[0] === "t" || str[0] === "T"),
1452
1679
  stringify({ source, value }, ctx) {
1453
- if (source && boolTag.test.test(source)) {
1680
+ if (source && boolTag.test(source)) {
1454
1681
  if (value === (source[0] === "t" || source[0] === "T")) return source;
1455
1682
  }
1456
1683
  return value ? ctx.options.trueStr : ctx.options.falseStr;
1457
1684
  }
1458
1685
  };
1459
-
1460
1686
  //#endregion
1461
1687
  //#region src/stringify/stringifyNumber.ts
1462
- function stringifyNumber({ format, minFractionDigits, tag, value }) {
1688
+ function stringifyNumber({ format, minFractionDigits, source, tag, value }, version = "1.2") {
1463
1689
  if (typeof value === "bigint") return String(value);
1464
1690
  const num = typeof value === "number" ? value : Number(value);
1465
- if (!isFinite(num)) return isNaN(num) ? ".nan" : num < 0 ? "-.inf" : ".inf";
1691
+ if (!isFinite(num)) {
1692
+ if (typeof value === "number" && source) {
1693
+ const source_ = version === "1.1" ? source.replace(/_/g, "") : source;
1694
+ if (parseFloat(source_) === num) return source;
1695
+ }
1696
+ return isNaN(num) ? ".nan" : num < 0 ? "-.inf" : ".inf";
1697
+ }
1466
1698
  let n = Object.is(value, -0) ? "-0" : JSON.stringify(value);
1467
- if (!format && minFractionDigits && (!tag || tag === "tag:yaml.org,2002:float") && /^\d/.test(n)) {
1699
+ if (!format && minFractionDigits && (!tag || tag === "tag:yaml.org,2002:float") && /^-?\d/.test(n) && !n.includes("e")) {
1468
1700
  let i = n.indexOf(".");
1469
1701
  if (i < 0) {
1470
1702
  i = n.length;
@@ -1475,23 +1707,43 @@ function stringifyNumber({ format, minFractionDigits, tag, value }) {
1475
1707
  }
1476
1708
  return n;
1477
1709
  }
1478
-
1479
1710
  //#endregion
1480
1711
  //#region src/schema/core/float.ts
1712
+ const floatNaNValues = /* @__PURE__ */ new Set([
1713
+ ".nan",
1714
+ ".NaN",
1715
+ ".NAN",
1716
+ ".inf",
1717
+ ".Inf",
1718
+ ".INF",
1719
+ "+.inf",
1720
+ "+.Inf",
1721
+ "+.INF",
1722
+ "-.inf",
1723
+ "-.Inf",
1724
+ "-.INF"
1725
+ ]);
1726
+ /** First char must be a digit, sign, or dot to match any float pattern */
1727
+ function couldBeFloat(value) {
1728
+ const c = value.charCodeAt(0);
1729
+ return c >= 48 && c <= 57 || c === 43 || c === 45 || c === 46;
1730
+ }
1731
+ const floatExpRe = /^[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+$/;
1732
+ const floatRe = /^[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*)$/;
1481
1733
  const floatNaN$1 = {
1482
1734
  identify: (value) => typeof value === "number",
1483
1735
  default: true,
1484
1736
  tag: "tag:yaml.org,2002:float",
1485
- test: /^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,
1737
+ test: (value) => floatNaNValues.has(value),
1486
1738
  resolve: (str) => str.slice(-3).toLowerCase() === "nan" ? NaN : str[0] === "-" ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
1487
- stringify: stringifyNumber
1739
+ stringify: (node) => stringifyNumber(node)
1488
1740
  };
1489
1741
  const floatExp$1 = {
1490
1742
  identify: (value) => typeof value === "number",
1491
1743
  default: true,
1492
1744
  tag: "tag:yaml.org,2002:float",
1493
1745
  format: "EXP",
1494
- test: /^[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+$/,
1746
+ test: (value) => couldBeFloat(value) && floatExpRe.test(value),
1495
1747
  resolve: (str) => parseFloat(str),
1496
1748
  stringify(node) {
1497
1749
  const num = Number(node.value);
@@ -1502,16 +1754,15 @@ const float$1 = {
1502
1754
  identify: (value) => typeof value === "number",
1503
1755
  default: true,
1504
1756
  tag: "tag:yaml.org,2002:float",
1505
- test: /^[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*)$/,
1757
+ test: (value) => couldBeFloat(value) && floatRe.test(value),
1506
1758
  resolve(str) {
1507
1759
  const node = new Scalar(parseFloat(str));
1508
1760
  const dot = str.indexOf(".");
1509
1761
  if (dot !== -1 && str[str.length - 1] === "0") node.minFractionDigits = str.length - dot - 1;
1510
1762
  return node;
1511
1763
  },
1512
- stringify: stringifyNumber
1764
+ stringify: (node) => stringifyNumber(node)
1513
1765
  };
1514
-
1515
1766
  //#endregion
1516
1767
  //#region src/schema/core/int.ts
1517
1768
  const intIdentify$2 = (value) => typeof value === "bigint" || Number.isInteger(value);
@@ -1521,12 +1772,39 @@ function intStringify$1(node, radix, prefix) {
1521
1772
  if (intIdentify$2(value) && value >= 0) return prefix + value.toString(radix);
1522
1773
  return stringifyNumber(node);
1523
1774
  }
1775
+ function isOctInt(value) {
1776
+ if (value.length < 3 || value[0] !== "0" || value[1] !== "o") return false;
1777
+ for (let i = 2; i < value.length; i++) {
1778
+ const c = value.charCodeAt(i);
1779
+ if (c < 48 || c > 55) return false;
1780
+ }
1781
+ return true;
1782
+ }
1783
+ function isInt(value) {
1784
+ let i = 0;
1785
+ if (value.length === 0) return false;
1786
+ if (value.charCodeAt(0) === 43 || value.charCodeAt(0) === 45) i = 1;
1787
+ if (i === value.length) return false;
1788
+ for (; i < value.length; i++) {
1789
+ const c = value.charCodeAt(i);
1790
+ if (c < 48 || c > 57) return false;
1791
+ }
1792
+ return true;
1793
+ }
1794
+ function isHexInt(value) {
1795
+ if (value.length < 3 || value[0] !== "0" || value[1] !== "x") return false;
1796
+ for (let i = 2; i < value.length; i++) {
1797
+ const c = value.charCodeAt(i);
1798
+ if (!(c >= 48 && c <= 57) && !(c >= 65 && c <= 70) && !(c >= 97 && c <= 102)) return false;
1799
+ }
1800
+ return true;
1801
+ }
1524
1802
  const intOct$1 = {
1525
1803
  identify: (value) => intIdentify$2(value) && value >= 0,
1526
1804
  default: true,
1527
1805
  tag: "tag:yaml.org,2002:int",
1528
1806
  format: "OCT",
1529
- test: /^0o[0-7]+$/,
1807
+ test: isOctInt,
1530
1808
  resolve: (str, _onError, opt) => intResolve$1(str, 2, 8, opt),
1531
1809
  stringify: (node) => intStringify$1(node, 8, "0o")
1532
1810
  };
@@ -1534,20 +1812,19 @@ const int$1 = {
1534
1812
  identify: intIdentify$2,
1535
1813
  default: true,
1536
1814
  tag: "tag:yaml.org,2002:int",
1537
- test: /^[-+]?[0-9]+$/,
1815
+ test: isInt,
1538
1816
  resolve: (str, _onError, opt) => intResolve$1(str, 0, 10, opt),
1539
- stringify: stringifyNumber
1817
+ stringify: (node) => stringifyNumber(node)
1540
1818
  };
1541
1819
  const intHex$1 = {
1542
1820
  identify: (value) => intIdentify$2(value) && value >= 0,
1543
1821
  default: true,
1544
1822
  tag: "tag:yaml.org,2002:int",
1545
1823
  format: "HEX",
1546
- test: /^0x[0-9a-fA-F]+$/,
1824
+ test: isHexInt,
1547
1825
  resolve: (str, _onError, opt) => intResolve$1(str, 2, 16, opt),
1548
1826
  stringify: (node) => intStringify$1(node, 16, "0x")
1549
1827
  };
1550
-
1551
1828
  //#endregion
1552
1829
  //#region src/schema/core/schema.ts
1553
1830
  const schema$2 = [
@@ -1563,7 +1840,6 @@ const schema$2 = [
1563
1840
  floatExp$1,
1564
1841
  float$1
1565
1842
  ];
1566
-
1567
1843
  //#endregion
1568
1844
  //#region src/schema/json/schema.ts
1569
1845
  function intIdentify$1(value) {
@@ -1583,7 +1859,7 @@ const jsonScalars = [
1583
1859
  createNode: () => new Scalar(null),
1584
1860
  default: true,
1585
1861
  tag: "tag:yaml.org,2002:null",
1586
- test: /^null$/,
1862
+ test: (str) => str === "null",
1587
1863
  resolve: () => null,
1588
1864
  stringify: stringifyJSON
1589
1865
  },
@@ -1591,7 +1867,7 @@ const jsonScalars = [
1591
1867
  identify: (value) => typeof value === "boolean",
1592
1868
  default: true,
1593
1869
  tag: "tag:yaml.org,2002:bool",
1594
- test: /^true$|^false$/,
1870
+ test: (str) => str === "true" || str === "false",
1595
1871
  resolve: (str) => str === "true",
1596
1872
  stringify: stringifyJSON
1597
1873
  },
@@ -1599,7 +1875,7 @@ const jsonScalars = [
1599
1875
  identify: intIdentify$1,
1600
1876
  default: true,
1601
1877
  tag: "tag:yaml.org,2002:int",
1602
- test: /^-?(?:0|[1-9][0-9]*)$/,
1878
+ test: (str) => /^-?(?:0|[1-9][0-9]*)$/.test(str),
1603
1879
  resolve: (str, _onError, { intAsBigInt }) => intAsBigInt ? BigInt(str) : parseInt(str, 10),
1604
1880
  stringify: ({ value }) => intIdentify$1(value) ? value.toString() : JSON.stringify(value)
1605
1881
  },
@@ -1607,7 +1883,7 @@ const jsonScalars = [
1607
1883
  identify: (value) => typeof value === "number",
1608
1884
  default: true,
1609
1885
  tag: "tag:yaml.org,2002:float",
1610
- test: /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$/,
1886
+ test: (str) => /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$/.test(str),
1611
1887
  resolve: (str) => parseFloat(str),
1612
1888
  stringify: stringifyJSON
1613
1889
  }
@@ -1615,7 +1891,7 @@ const jsonScalars = [
1615
1891
  const jsonError = {
1616
1892
  default: true,
1617
1893
  tag: "",
1618
- test: /^/,
1894
+ test: () => true,
1619
1895
  resolve(str, onError) {
1620
1896
  onError(`Unresolved plain scalar ${JSON.stringify(str)}`);
1621
1897
  return str;
@@ -1627,13 +1903,20 @@ const schema$1 = [
1627
1903
  ...jsonScalars,
1628
1904
  jsonError
1629
1905
  ];
1630
-
1631
1906
  //#endregion
1632
1907
  //#region src/schema/yaml-1.1/binary.ts
1633
1908
  const binary = {
1634
1909
  identify: (value) => value instanceof Uint8Array,
1635
1910
  default: false,
1636
1911
  tag: "tag:yaml.org,2002:binary",
1912
+ /**
1913
+ * Returns a Buffer in Node.js and an Uint8Array elsewhere
1914
+ *
1915
+ * To use the resulting buffer as an image, you'll want to do something like:
1916
+ *
1917
+ * const blob = new Blob([buffer], { type: 'image/jpeg' })
1918
+ * document.querySelector('#photo').src = URL.createObjectURL(blob)
1919
+ */
1637
1920
  resolve(src, onError) {
1638
1921
  if (typeof Buffer === "function") return Buffer.from(src, "base64");
1639
1922
  else if (typeof Uint8Array.fromBase64 === "function") return Uint8Array.fromBase64(src);
@@ -1673,23 +1956,22 @@ const binary = {
1673
1956
  }, ctx, onComment, onChompKeep);
1674
1957
  }
1675
1958
  };
1676
-
1677
1959
  //#endregion
1678
1960
  //#region src/schema/yaml-1.1/pairs.ts
1679
1961
  function resolvePairs(seq, onError) {
1680
- if (seq instanceof YAMLSeq) for (let i = 0; i < seq.items.length; ++i) {
1681
- const item = seq.items[i];
1962
+ if (seq instanceof YAMLSeq) for (let i = 0; i < seq.length; ++i) {
1963
+ const item = seq[i];
1682
1964
  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));
1965
+ if (item instanceof YAMLMap) {
1966
+ if (item.size > 1) onError("Each pair must have its own sequence indicator");
1967
+ const pair = item.values.values().next().value ?? new Pair(new Scalar(null));
1686
1968
  if (item.commentBefore) pair.key.commentBefore = pair.key.commentBefore ? `${item.commentBefore}\n${pair.key.commentBefore}` : item.commentBefore;
1687
1969
  if (item.comment) {
1688
1970
  const cn = pair.value ?? pair.key;
1689
1971
  cn.comment = cn.comment ? `${item.comment}\n${cn.comment}` : item.comment;
1690
1972
  }
1691
- seq.items[i] = pair;
1692
- } else seq.items[i] = new Pair(item, null);
1973
+ seq[i] = pair;
1974
+ } else seq[i] = new Pair(item, null);
1693
1975
  }
1694
1976
  else onError("Expected a sequence for this tag");
1695
1977
  return seq;
@@ -1701,18 +1983,19 @@ function createPairs(nc, iterable) {
1701
1983
  if (iterable && Symbol.iterator in Object(iterable)) for (let it of iterable) {
1702
1984
  if (typeof nc.replacer === "function") it = nc.replacer.call(iterable, String(i++), it);
1703
1985
  let key, value;
1704
- if (Array.isArray(it)) if (it.length === 2) {
1705
- key = it[0];
1706
- value = it[1];
1707
- } else throw new TypeError(`Expected [key, value] tuple: ${it}`);
1708
- else if (it && it instanceof Object) {
1986
+ if (Array.isArray(it)) {
1987
+ if (it.length === 2) {
1988
+ key = it[0];
1989
+ value = it[1];
1990
+ } else throw new TypeError(`Expected [key, value] tuple: ${it}`);
1991
+ } else if (it && it instanceof Object) {
1709
1992
  const keys = Object.keys(it);
1710
1993
  if (keys.length === 1) {
1711
1994
  key = keys[0];
1712
1995
  value = it[key];
1713
1996
  } else throw new TypeError(`Expected tuple with one key, not ${keys.length} keys`);
1714
1997
  } else key = it;
1715
- pairs.items.push(nc.createPair(key, value));
1998
+ pairs.push(nc.createPair(key, value));
1716
1999
  }
1717
2000
  return pairs;
1718
2001
  }
@@ -1723,44 +2006,62 @@ const pairs = {
1723
2006
  resolve: resolvePairs,
1724
2007
  createNode: createPairs
1725
2008
  };
1726
-
1727
2009
  //#endregion
1728
2010
  //#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);
2011
+ var YAMLOMap = class extends YAMLSeq {
2012
+ constructor(schema, elements) {
2013
+ super(schema, elements);
2014
+ this.tag = omap.tag;
2015
+ }
2016
+ /**
2017
+ * Append new pairs to the omap, and return its new length.
2018
+ */
2019
+ push(...pairs) {
2020
+ for (const pair of pairs) if (pair instanceof Pair) super.push(pair);
2021
+ else throw new Error("Omap only supports Pair values");
2022
+ return this.length;
2023
+ }
2024
+ /**
2025
+ * Set a pair in this omap.
2026
+ *
2027
+ * Throws if `idx` is not an integer.
2028
+ */
2029
+ set(idx, pair) {
2030
+ if (!Number.isInteger(idx)) throw new TypeError(`Expected an integer, not ${JSON.stringify(idx)}.`);
2031
+ if (idx < 0) {
2032
+ if (idx < -this.length) throw new RangeError(`Invalid index ${idx}`);
2033
+ idx += this.length;
2034
+ }
2035
+ this[idx] = pair;
2036
+ }
1740
2037
  /**
1741
- * If `ctx` is given, the return type is actually `Map<unknown, unknown>`,
2038
+ * The returned value actually has type `Map<unknown, unknown>`,
1742
2039
  * but TypeScript won't allow widening the signature of a child method.
1743
2040
  */
1744
- toJSON(_, ctx) {
1745
- if (!ctx) return super.toJSON(_);
2041
+ toJS(doc, ctx) {
2042
+ if (!ctx) return super.toJS(doc);
1746
2043
  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);
2044
+ if (this.anchor) ctx.anchors.set(this, {
2045
+ aliasCount: 0,
2046
+ count: 1,
2047
+ res: map
2048
+ });
2049
+ for (const pair of this) {
2050
+ const key = pair.key.toJS(doc, ctx);
2051
+ const value = pair.value ? pair.value.toJS(doc, ctx) : null;
1754
2052
  if (map.has(key)) throw new Error("Ordered maps must not include duplicate keys");
1755
2053
  map.set(key, value);
1756
2054
  }
1757
2055
  return map;
1758
2056
  }
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;
2057
+ toString(ctx, onComment, onChompKeep) {
2058
+ const keys = /* @__PURE__ */ new Set();
2059
+ for (const pair of this) {
2060
+ const key = this.schema.mapKey(pair);
2061
+ if (keys.has(key)) throw new Error("Ordered maps must not include duplicate keys");
2062
+ keys.add(key);
2063
+ }
2064
+ return super.toString(ctx, onComment, onChompKeep);
1764
2065
  }
1765
2066
  };
1766
2067
  const omap = {
@@ -1769,26 +2070,31 @@ const omap = {
1769
2070
  nodeClass: YAMLOMap,
1770
2071
  default: false,
1771
2072
  tag: "tag:yaml.org,2002:omap",
2073
+ createNode(nc, iterable) {
2074
+ const pairs = createPairs(nc, iterable);
2075
+ return new YAMLOMap(nc.schema, pairs);
2076
+ },
1772
2077
  resolve(seq, onError) {
1773
2078
  const pairs = resolvePairs(seq, onError);
1774
2079
  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}`);
1776
- else seenKeys.push(key.value);
1777
- return Object.assign(new YAMLOMap(), pairs);
2080
+ for (const { key } of pairs) if (key instanceof Scalar) {
2081
+ if (seenKeys.includes(key.value)) onError(`Ordered maps must not include duplicate keys: ${key.value}`);
2082
+ else seenKeys.push(key.value);
2083
+ }
2084
+ return Object.assign(new YAMLOMap(seq.schema), pairs);
1778
2085
  }
1779
2086
  };
1780
-
1781
2087
  //#endregion
1782
2088
  //#region src/schema/yaml-1.1/bool.ts
1783
2089
  function boolStringify({ value, source }, ctx) {
1784
- if (source && (value ? trueTag : falseTag).test.test(source)) return source;
2090
+ if (source && (value ? trueTag : falseTag).test(source)) return source;
1785
2091
  return value ? ctx.options.trueStr : ctx.options.falseStr;
1786
2092
  }
1787
2093
  const trueTag = {
1788
2094
  identify: (value) => value === true,
1789
2095
  default: true,
1790
2096
  tag: "tag:yaml.org,2002:bool",
1791
- test: /^(?:Y|y|[Yy]es|YES|[Tt]rue|TRUE|[Oo]n|ON)$/,
2097
+ test: (str) => /^(?:Y|y|[Yy]es|YES|[Tt]rue|TRUE|[Oo]n|ON)$/.test(str),
1792
2098
  resolve: () => new Scalar(true),
1793
2099
  stringify: boolStringify
1794
2100
  };
@@ -1796,38 +2102,37 @@ const falseTag = {
1796
2102
  identify: (value) => value === false,
1797
2103
  default: true,
1798
2104
  tag: "tag:yaml.org,2002:bool",
1799
- test: /^(?:N|n|[Nn]o|NO|[Ff]alse|FALSE|[Oo]ff|OFF)$/,
2105
+ test: (str) => /^(?:N|n|[Nn]o|NO|[Ff]alse|FALSE|[Oo]ff|OFF)$/.test(str),
1800
2106
  resolve: () => new Scalar(false),
1801
2107
  stringify: boolStringify
1802
2108
  };
1803
-
1804
2109
  //#endregion
1805
2110
  //#region src/schema/yaml-1.1/float.ts
1806
2111
  const floatNaN = {
1807
2112
  identify: (value) => typeof value === "number",
1808
2113
  default: true,
1809
2114
  tag: "tag:yaml.org,2002:float",
1810
- test: /^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,
2115
+ test: (str) => /^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/.test(str),
1811
2116
  resolve: (str) => str.slice(-3).toLowerCase() === "nan" ? NaN : str[0] === "-" ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
1812
- stringify: stringifyNumber
2117
+ stringify: (node) => stringifyNumber(node, "1.1")
1813
2118
  };
1814
2119
  const floatExp = {
1815
2120
  identify: (value) => typeof value === "number",
1816
2121
  default: true,
1817
2122
  tag: "tag:yaml.org,2002:float",
1818
2123
  format: "EXP",
1819
- test: /^[-+]?(?:[0-9][0-9_]*)?(?:\.[0-9_]*)?[eE][-+]?[0-9]+$/,
2124
+ test: (str) => /^[-+]?(?:[0-9][0-9_]*)?(?:\.[0-9_]*)?[eE][-+]?[0-9]+$/.test(str),
1820
2125
  resolve: (str) => parseFloat(str.replace(/_/g, "")),
1821
2126
  stringify(node) {
1822
2127
  const num = Number(node.value);
1823
- return isFinite(num) ? num.toExponential() : stringifyNumber(node);
2128
+ return isFinite(num) ? num.toExponential() : stringifyNumber(node, "1.1");
1824
2129
  }
1825
2130
  };
1826
2131
  const float = {
1827
2132
  identify: (value) => typeof value === "number",
1828
2133
  default: true,
1829
2134
  tag: "tag:yaml.org,2002:float",
1830
- test: /^[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*$/,
2135
+ test: (str) => /^[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*$/.test(str),
1831
2136
  resolve(str) {
1832
2137
  const node = new Scalar(parseFloat(str.replace(/_/g, "")));
1833
2138
  const dot = str.indexOf(".");
@@ -1837,9 +2142,8 @@ const float = {
1837
2142
  }
1838
2143
  return node;
1839
2144
  },
1840
- stringify: stringifyNumber
2145
+ stringify: (node) => stringifyNumber(node, "1.1")
1841
2146
  };
1842
-
1843
2147
  //#endregion
1844
2148
  //#region src/schema/yaml-1.1/int.ts
1845
2149
  const intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
@@ -1855,9 +2159,7 @@ function intResolve(str, offset, radix, { intAsBigInt }) {
1855
2159
  case 8:
1856
2160
  str = `0o${str}`;
1857
2161
  break;
1858
- case 16:
1859
- str = `0x${str}`;
1860
- break;
2162
+ case 16: str = `0x${str}`;
1861
2163
  }
1862
2164
  const n = BigInt(str);
1863
2165
  return sign === "-" ? BigInt(-1) * n : n;
@@ -1878,7 +2180,7 @@ const intBin = {
1878
2180
  default: true,
1879
2181
  tag: "tag:yaml.org,2002:int",
1880
2182
  format: "BIN",
1881
- test: /^[-+]?0b[0-1_]+$/,
2183
+ test: (str) => /^[-+]?0b[0-1_]+$/.test(str),
1882
2184
  resolve: (str, _onError, opt) => intResolve(str, 2, 2, opt),
1883
2185
  stringify: (node) => intStringify(node, 2, "0b")
1884
2186
  };
@@ -1887,7 +2189,7 @@ const intOct = {
1887
2189
  default: true,
1888
2190
  tag: "tag:yaml.org,2002:int",
1889
2191
  format: "OCT",
1890
- test: /^[-+]?0[0-7_]+$/,
2192
+ test: (str) => /^[-+]?0[0-7_]+$/.test(str),
1891
2193
  resolve: (str, _onError, opt) => intResolve(str, 1, 8, opt),
1892
2194
  stringify: (node) => intStringify(node, 8, "0")
1893
2195
  };
@@ -1895,109 +2197,41 @@ const int = {
1895
2197
  identify: intIdentify,
1896
2198
  default: true,
1897
2199
  tag: "tag:yaml.org,2002:int",
1898
- test: /^[-+]?[0-9][0-9_]*$/,
2200
+ test: (str) => /^[-+]?[0-9][0-9_]*$/.test(str),
1899
2201
  resolve: (str, _onError, opt) => intResolve(str, 0, 10, opt),
1900
- stringify: stringifyNumber
2202
+ stringify: (node) => stringifyNumber(node, "1.1")
1901
2203
  };
1902
2204
  const intHex = {
1903
2205
  identify: intIdentify,
1904
2206
  default: true,
1905
2207
  tag: "tag:yaml.org,2002:int",
1906
2208
  format: "HEX",
1907
- test: /^[-+]?0x[0-9a-fA-F_]+$/,
2209
+ test: (str) => /^[-+]?0x[0-9a-fA-F_]+$/.test(str),
1908
2210
  resolve: (str, _onError, opt) => intResolve(str, 2, 16, opt),
1909
2211
  stringify: (node) => intStringify(node, 16, "0x")
1910
2212
  };
1911
-
1912
2213
  //#endregion
1913
2214
  //#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
2215
  const set = {
1981
2216
  collection: "map",
1982
2217
  identify: (value) => value instanceof Set,
1983
2218
  nodeClass: YAMLSet,
1984
2219
  default: false,
1985
2220
  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;
2221
+ createNode(nc, iterable) {
2222
+ const set = new YAMLSet(nc.schema);
2223
+ if (iterable && Symbol.iterator in Object(iterable)) for (let value of iterable) {
2224
+ if (typeof nc.replacer === "function") value = nc.replacer.call(iterable, value, value);
2225
+ const mk = nc.schema.mapKey(value);
2226
+ set.values.set(mk, nc.create(value));
1997
2227
  }
2228
+ return set;
2229
+ },
2230
+ resolve(set, onError) {
2231
+ if (!(set instanceof YAMLSet)) onError("Expected a set for this tag");
2232
+ return set;
1998
2233
  }
1999
2234
  };
2000
-
2001
2235
  //#endregion
2002
2236
  //#region src/schema/yaml-1.1/timestamp.ts
2003
2237
  /** Internal types handle bigint as number, because TS can't figure it out. */
@@ -2041,7 +2275,7 @@ const intTime = {
2041
2275
  default: true,
2042
2276
  tag: "tag:yaml.org,2002:int",
2043
2277
  format: "TIME",
2044
- test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+$/,
2278
+ test: (str) => /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+$/.test(str),
2045
2279
  resolve: (str, _onError, { intAsBigInt }) => parseSexagesimal(str, intAsBigInt),
2046
2280
  stringify: stringifySexagesimal
2047
2281
  };
@@ -2050,17 +2284,18 @@ const floatTime = {
2050
2284
  default: true,
2051
2285
  tag: "tag:yaml.org,2002:float",
2052
2286
  format: "TIME",
2053
- test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*$/,
2287
+ test: (str) => /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*$/.test(str),
2054
2288
  resolve: (str) => parseSexagesimal(str, false),
2055
2289
  stringify: stringifySexagesimal
2056
2290
  };
2291
+ const timestampRe = RegExp("^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})(?:(?:t|T|[ \\t]+)([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}(\\.[0-9]+)?)(?:[ \\t]*(Z|[-+][012]?[0-9](?::[0-9]{2})?))?)?$");
2057
2292
  const timestamp = {
2058
2293
  identify: (value) => value instanceof Date,
2059
2294
  default: true,
2060
2295
  tag: "tag:yaml.org,2002:timestamp",
2061
- test: RegExp("^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})(?:(?:t|T|[ \\t]+)([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}(\\.[0-9]+)?)(?:[ \\t]*(Z|[-+][012]?[0-9](?::[0-9]{2})?))?)?$"),
2296
+ test: (str) => timestampRe.test(str),
2062
2297
  resolve(str) {
2063
- const match = str.match(timestamp.test);
2298
+ const match = str.match(timestampRe);
2064
2299
  if (!match) throw new Error("!!timestamp expects a date, starting with yyyy-mm-dd");
2065
2300
  const [, year, month, day, hour, minute, second] = match.map(Number);
2066
2301
  const millisec = match[7] ? Number((match[7] + "00").substr(1, 3)) : 0;
@@ -2075,7 +2310,6 @@ const timestamp = {
2075
2310
  },
2076
2311
  stringify: ({ value }) => value?.toISOString().replace(/(T00:00:00)?\.000Z$/, "") ?? ""
2077
2312
  };
2078
-
2079
2313
  //#endregion
2080
2314
  //#region src/schema/yaml-1.1/schema.ts
2081
2315
  const schema = [
@@ -2101,10 +2335,9 @@ const schema = [
2101
2335
  floatTime,
2102
2336
  timestamp
2103
2337
  ];
2104
-
2105
2338
  //#endregion
2106
2339
  //#region src/schema/tags.ts
2107
- const schemas = new Map([
2340
+ const schemas = /* @__PURE__ */ new Map([
2108
2341
  ["core", schema$2],
2109
2342
  ["failsafe", [
2110
2343
  map,
@@ -2145,16 +2378,18 @@ const coreKnownTags = {
2145
2378
  };
2146
2379
  function getTags(customTags, schemaName, addMergeTag) {
2147
2380
  const schemaTags = schemas.get(schemaName);
2148
- if (schemaTags && !customTags) return addMergeTag && !schemaTags.includes(merge) ? schemaTags.concat(merge) : schemaTags.slice();
2381
+ if (schemaTags && !customTags) return addMergeTag && !schemaTags.includes(merge) ? [...schemaTags, merge] : schemaTags.slice();
2149
2382
  let tags = schemaTags;
2150
- if (!tags) if (Array.isArray(customTags)) tags = [];
2151
- else {
2152
- const keys = Array.from(schemas.keys()).filter((key) => key !== "yaml11").map((key) => JSON.stringify(key)).join(", ");
2153
- throw new Error(`Unknown schema "${schemaName}"; use one of ${keys} or define customTags array`);
2383
+ if (!tags) {
2384
+ if (Array.isArray(customTags)) tags = [];
2385
+ else {
2386
+ const keys = Array.from(schemas.keys()).filter((key) => key !== "yaml11").map((key) => JSON.stringify(key)).join(", ");
2387
+ throw new Error(`Unknown schema "${schemaName}"; use one of ${keys} or define customTags array`);
2388
+ }
2154
2389
  }
2155
2390
  if (Array.isArray(customTags)) for (const tag of customTags) tags = tags.concat(tag);
2156
2391
  else if (typeof customTags === "function") tags = customTags(tags.slice());
2157
- if (addMergeTag) tags = tags.concat(merge);
2392
+ if (addMergeTag) tags = [...tags, merge];
2158
2393
  return tags.reduce((tags, tag) => {
2159
2394
  const tagObj = typeof tag === "string" ? tagsByName[tag] : tag;
2160
2395
  if (!tagObj) {
@@ -2166,19 +2401,18 @@ function getTags(customTags, schemaName, addMergeTag) {
2166
2401
  return tags;
2167
2402
  }, []);
2168
2403
  }
2169
-
2170
2404
  //#endregion
2171
2405
  //#region src/schema/Schema.ts
2172
- const sortMapEntriesByKey = (a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
2173
2406
  var Schema = class Schema {
2174
2407
  compat;
2175
2408
  knownTags;
2409
+ mapKey;
2176
2410
  name;
2177
- sortMapEntries;
2178
2411
  tags;
2179
2412
  toStringOptions;
2180
- constructor({ compat, customTags, merge, resolveKnownTags, schema, sortMapEntries, toStringDefaults }) {
2413
+ constructor({ compat, customTags, mapKey, merge, resolveKnownTags, schema, toStringDefaults }) {
2181
2414
  this.compat = Array.isArray(compat) ? getTags(compat, "compat") : compat ? getTags(null, compat) : null;
2415
+ this.mapKey = mapKey ?? defaultMapKey;
2182
2416
  this.name = typeof schema === "string" && schema || "core";
2183
2417
  this.knownTags = resolveKnownTags ? coreKnownTags : {};
2184
2418
  this.tags = getTags(customTags, this.name, merge);
@@ -2186,7 +2420,6 @@ var Schema = class Schema {
2186
2420
  Object.defineProperty(this, "map", { value: map });
2187
2421
  Object.defineProperty(this, "scalar", { value: string });
2188
2422
  Object.defineProperty(this, "seq", { value: seq });
2189
- this.sortMapEntries = typeof sortMapEntries === "function" ? sortMapEntries : sortMapEntries === true ? sortMapEntriesByKey : null;
2190
2423
  }
2191
2424
  clone() {
2192
2425
  const copy = Object.create(Schema.prototype, Object.getOwnPropertyDescriptors(this));
@@ -2194,7 +2427,11 @@ var Schema = class Schema {
2194
2427
  return copy;
2195
2428
  }
2196
2429
  };
2197
-
2430
+ function defaultMapKey(value) {
2431
+ if (value instanceof Pair) value = value.key;
2432
+ if (value instanceof Scalar) value = value.value;
2433
+ return value ?? null;
2434
+ }
2198
2435
  //#endregion
2199
2436
  //#region src/stringify/stringifyDocument.ts
2200
2437
  function stringifyDocument(doc, options) {
@@ -2216,27 +2453,27 @@ function stringifyDocument(doc, options) {
2216
2453
  lines.unshift(indentComment(cs, ""));
2217
2454
  }
2218
2455
  let chompKeep = false;
2219
- let contentComment = null;
2220
2456
  if (doc.value.spaceBefore && hasDirectives) lines.push("");
2221
2457
  if (doc.value.commentBefore) {
2222
2458
  const cs = commentString(doc.value.commentBefore);
2223
2459
  lines.push(indentComment(cs, ""));
2224
2460
  }
2225
2461
  ctx.forceBlockIndent = !!doc.comment;
2226
- contentComment = doc.value.comment;
2462
+ let contentComment = doc.value.comment;
2227
2463
  const onChompKeep = contentComment ? void 0 : () => chompKeep = true;
2228
2464
  let body = stringify(doc.value, ctx, () => contentComment = null, onChompKeep);
2229
2465
  if (contentComment) body += lineComment(body, "", commentString(contentComment));
2230
2466
  if ((body[0] === "|" || body[0] === ">") && lines[lines.length - 1] === "---") lines[lines.length - 1] = `--- ${body}`;
2231
2467
  else lines.push(body);
2232
- if (doc.directives?.docEnd) if (doc.comment) {
2233
- const cs = commentString(doc.comment);
2234
- if (cs.includes("\n")) {
2235
- lines.push("...");
2236
- lines.push(indentComment(cs, ""));
2237
- } else lines.push(`... ${cs}`);
2238
- } else lines.push("...");
2239
- else {
2468
+ if (doc.directives?.docEnd) {
2469
+ if (doc.comment) {
2470
+ const cs = commentString(doc.comment);
2471
+ if (cs.includes("\n")) {
2472
+ lines.push("...");
2473
+ lines.push(indentComment(cs, ""));
2474
+ } else lines.push(`... ${cs}`);
2475
+ } else lines.push("...");
2476
+ } else {
2240
2477
  let dc = doc.comment;
2241
2478
  if (dc && chompKeep) dc = dc.replace(/^\n+/, "");
2242
2479
  if (dc) {
@@ -2246,7 +2483,38 @@ function stringifyDocument(doc, options) {
2246
2483
  }
2247
2484
  return lines.join("\n") + "\n";
2248
2485
  }
2249
-
2486
+ //#endregion
2487
+ //#region src/doc/applyReviver.ts
2488
+ function applyReviver(reviver, obj, key, val) {
2489
+ if (val && typeof val === "object") {
2490
+ if (Array.isArray(val)) for (let i = 0, len = val.length; i < len; ++i) {
2491
+ const v0 = val[i];
2492
+ const v1 = applyReviver(reviver, val, String(i), v0);
2493
+ if (v1 === void 0) delete val[i];
2494
+ else if (v1 !== v0) val[i] = v1;
2495
+ }
2496
+ else if (val instanceof Map) for (const k of Array.from(val.keys())) {
2497
+ const v0 = val.get(k);
2498
+ const v1 = applyReviver(reviver, val, k, v0);
2499
+ if (v1 === void 0) val.delete(k);
2500
+ else if (v1 !== v0) val.set(k, v1);
2501
+ }
2502
+ else if (val instanceof Set) for (const v0 of Array.from(val)) {
2503
+ const v1 = applyReviver(reviver, val, v0, v0);
2504
+ if (v1 === void 0) val.delete(v0);
2505
+ else if (v1 !== v0) {
2506
+ val.delete(v0);
2507
+ val.add(v1);
2508
+ }
2509
+ }
2510
+ else for (const [k, v0] of Object.entries(val)) {
2511
+ const v1 = applyReviver(reviver, val, k, v0);
2512
+ if (v1 === void 0) delete val[k];
2513
+ else if (v1 !== v0) val[k] = v1;
2514
+ }
2515
+ }
2516
+ return reviver.call(obj, key, val);
2517
+ }
2250
2518
  //#endregion
2251
2519
  //#region src/doc/Document.ts
2252
2520
  var Document = class Document {
@@ -2262,13 +2530,10 @@ var Document = class Document {
2262
2530
  options;
2263
2531
  /** Warnings encountered during parsing. */
2264
2532
  warnings = [];
2265
- constructor(value, replacer, options) {
2266
- let _replacer = null;
2267
- if (typeof replacer === "function" || Array.isArray(replacer)) _replacer = replacer;
2268
- else if (options === void 0 && replacer) {
2269
- options = replacer;
2270
- replacer = void 0;
2271
- }
2533
+ constructor(value, replacerOrOptions, options) {
2534
+ let replacer = null;
2535
+ if (typeof replacerOrOptions === "function" || Array.isArray(replacerOrOptions)) replacer = replacerOrOptions;
2536
+ else if (options === void 0 && replacerOrOptions) options = replacerOrOptions;
2272
2537
  const opt = Object.assign({
2273
2538
  intAsBigInt: false,
2274
2539
  keepSourceTokens: false,
@@ -2276,7 +2541,6 @@ var Document = class Document {
2276
2541
  prettyErrors: true,
2277
2542
  strict: true,
2278
2543
  stringKeys: false,
2279
- uniqueKeys: true,
2280
2544
  version: "1.2"
2281
2545
  }, options);
2282
2546
  this.options = opt;
@@ -2286,7 +2550,7 @@ var Document = class Document {
2286
2550
  if (this.directives.yaml.explicit) version = this.directives.yaml.version;
2287
2551
  } else this.directives = new Directives({ version });
2288
2552
  this.setSchema(version, options);
2289
- this.value = this.createNode(value, _replacer, options);
2553
+ this.value = this.createNode(value, replacer, options);
2290
2554
  }
2291
2555
  /**
2292
2556
  * Create a deep copy of this Document and its value.
@@ -2306,14 +2570,6 @@ var Document = class Document {
2306
2570
  if (this.range) copy.range = this.range.slice();
2307
2571
  return copy;
2308
2572
  }
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
2573
  /**
2318
2574
  * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
2319
2575
  *
@@ -2338,7 +2594,7 @@ var Document = class Document {
2338
2594
  } else if (Array.isArray(replacer)) {
2339
2595
  const keyToStr = (v) => typeof v === "number" || v instanceof String || v instanceof Number;
2340
2596
  const asStr = replacer.filter(keyToStr).map(String);
2341
- if (asStr.length > 0) replacer = replacer.concat(asStr);
2597
+ if (asStr.length > 0) replacer = [...replacer, ...asStr];
2342
2598
  nc = new NodeCreator(this, options, replacer);
2343
2599
  } else {
2344
2600
  options ??= replacer ?? void 0;
@@ -2359,63 +2615,34 @@ var Document = class Document {
2359
2615
  return pair;
2360
2616
  }
2361
2617
  /**
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
2618
  * Returns item at `key`, or `undefined` if not found.
2381
2619
  */
2382
2620
  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;
2621
+ if (this.value instanceof YAMLMap || this.value instanceof YAMLSet) return this.value.get(key);
2622
+ if (this.value instanceof YAMLSeq) {
2623
+ if (Number.isInteger(key)) return this.value.at(key);
2624
+ throw new TypeError(`Expected an integer, not ${JSON.stringify(key)}.`);
2625
+ }
2397
2626
  }
2398
2627
  /**
2399
- * Checks if the document includes a value at `path`.
2628
+ * Returns pair at `key`, or `undefined` if not found.
2400
2629
  */
2401
- hasIn(path) {
2402
- if (!path.length) return true;
2403
- return this.value instanceof Collection ? this.value.hasIn(path) : false;
2630
+ getPair(key) {
2631
+ if (this.value instanceof YAMLMap) return this.value.getPair(key);
2632
+ if (this.value instanceof YAMLSeq) {
2633
+ if (!Number.isInteger(key)) throw new TypeError(`Expected an integer, not ${JSON.stringify(key)}.`);
2634
+ const pair = this.value.at(key);
2635
+ if (pair instanceof Pair) return pair;
2636
+ throw new TypeError(`Value at ${key} is not a Pair`);
2637
+ }
2404
2638
  }
2405
2639
  /**
2406
- * Sets a value in this document. For `!!set`, `value` needs to be a
2407
- * boolean to add/remove the item from the set.
2640
+ * Sets a value in this document's top-level collection. For `!!set`, `value` is ignored.
2408
2641
  */
2409
2642
  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);
2643
+ if (this.value instanceof YAMLSet) this.value.add(key);
2644
+ else if (this.value instanceof YAMLMap || this.value instanceof YAMLSeq) this.value.set(key, value);
2645
+ else throw new Error("Expected a YAML collection as document value");
2419
2646
  }
2420
2647
  /**
2421
2648
  * Change the YAML version and schema used by the document.
@@ -2458,32 +2685,17 @@ var Document = class Document {
2458
2685
  else if (opt) this.schema = new Schema(Object.assign(opt, options));
2459
2686
  else throw new Error(`With a null YAML version, the { schema: Schema } option is required`);
2460
2687
  }
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);
2688
+ /** A plain JavaScript representation of the document `value`. */
2689
+ toJS(opt = {}) {
2690
+ const { onAnchor, reviver } = opt;
2691
+ const ctx = new ToJSContext(opt);
2692
+ const res = this.value.toJS(this, ctx);
2471
2693
  if (typeof onAnchor === "function") for (const { count, res } of ctx.anchors.values()) onAnchor(res, count);
2472
2694
  return typeof reviver === "function" ? applyReviver(reviver, { "": res }, "", res) : res;
2473
2695
  }
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
- });
2696
+ /** A JSON representation of the document `value`. */
2697
+ toJSON() {
2698
+ return this.toJS({ mapAsMap: false });
2487
2699
  }
2488
2700
  /** A YAML representation of the document. */
2489
2701
  toString(options = {}) {
@@ -2495,11 +2707,6 @@ var Document = class Document {
2495
2707
  return stringifyDocument(this, options);
2496
2708
  }
2497
2709
  };
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
2710
  //#endregion
2504
2711
  //#region src/visit.ts
2505
2712
  const BREAK = Symbol("break visit");
@@ -2538,32 +2745,43 @@ const REMOVE = Symbol("remove node");
2538
2745
  const visit = function visit(node, visitor) {
2539
2746
  const visitor_ = initVisitor(visitor);
2540
2747
  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([]));
2748
+ if (visit_(null, node.value, visitor_, [node]) === REMOVE) node.value = new Scalar(null);
2749
+ } else visit_(null, node, visitor_, []);
2543
2750
  };
2544
2751
  visit.BREAK = BREAK;
2545
2752
  visit.SKIP = SKIP;
2546
2753
  visit.REMOVE = REMOVE;
2547
2754
  function visit_(key, node, visitor, path) {
2548
2755
  const ctrl = callVisitor(key, node, visitor, path);
2549
- if (ctrl instanceof NodeBase || ctrl instanceof Pair) {
2756
+ if (isNode(ctrl) || ctrl instanceof Pair) {
2550
2757
  replaceNode(key, path, ctrl);
2551
2758
  return visit_(key, ctrl, visitor, path);
2552
2759
  }
2553
2760
  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);
2761
+ if (node instanceof YAMLSeq) {
2762
+ path = [...path, node];
2763
+ for (let i = 0; i < node.length; ++i) {
2764
+ const ci = visit_(i, node[i], visitor, path);
2558
2765
  if (typeof ci === "number") i = ci - 1;
2559
2766
  else if (ci === BREAK) return BREAK;
2560
2767
  else if (ci === REMOVE) {
2561
- node.items.splice(i, 1);
2768
+ node.splice(i, 1);
2562
2769
  i -= 1;
2563
2770
  }
2564
2771
  }
2772
+ } else if (node instanceof YAMLMap || node instanceof YAMLSet) {
2773
+ path = [...path, node];
2774
+ const entries = Array.from(node.values);
2775
+ const delKeys = [];
2776
+ for (let i = 0; i < entries.length; ++i) {
2777
+ const ci = visit_(i, entries[i][1], visitor, path);
2778
+ if (typeof ci === "number") i = ci - 1;
2779
+ else if (ci === BREAK) return BREAK;
2780
+ else if (ci === REMOVE) delKeys.push(entries[i][0]);
2781
+ }
2782
+ for (const dk of delKeys) node.values.delete(dk);
2565
2783
  } else if (node instanceof Pair) {
2566
- path = Object.freeze(path.concat(node));
2784
+ path = [...path, node];
2567
2785
  const ck = visit_("key", node.key, visitor, path);
2568
2786
  if (ck === BREAK) return BREAK;
2569
2787
  else if (ck === REMOVE) node.key = new Scalar(null);
@@ -2609,32 +2827,43 @@ function visit_(key, node, visitor, path) {
2609
2827
  const visitAsync = async function visitAsync(node, visitor) {
2610
2828
  const visitor_ = initVisitor(visitor);
2611
2829
  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([]));
2830
+ if (await visitAsync_(null, node.value, visitor_, [node]) === REMOVE) node.value = new Scalar(null);
2831
+ } else await visitAsync_(null, node, visitor_, []);
2614
2832
  };
2615
2833
  visitAsync.BREAK = BREAK;
2616
2834
  visitAsync.SKIP = SKIP;
2617
2835
  visitAsync.REMOVE = REMOVE;
2618
2836
  async function visitAsync_(key, node, visitor, path) {
2619
2837
  const ctrl = await callVisitor(key, node, visitor, path);
2620
- if (ctrl instanceof NodeBase || ctrl instanceof Pair) {
2838
+ if (isNode(ctrl) || ctrl instanceof Pair) {
2621
2839
  replaceNode(key, path, ctrl);
2622
2840
  return visitAsync_(key, ctrl, visitor, path);
2623
2841
  }
2624
2842
  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);
2843
+ if (node instanceof YAMLSeq) {
2844
+ path = [...path, node];
2845
+ for (let i = 0; i < node.length; ++i) {
2846
+ const ci = await visitAsync_(i, node[i], visitor, path);
2629
2847
  if (typeof ci === "number") i = ci - 1;
2630
2848
  else if (ci === BREAK) return BREAK;
2631
2849
  else if (ci === REMOVE) {
2632
- node.items.splice(i, 1);
2850
+ node.splice(i, 1);
2633
2851
  i -= 1;
2634
2852
  }
2635
2853
  }
2854
+ } else if (node instanceof YAMLMap || node instanceof YAMLSet) {
2855
+ path = [...path, node];
2856
+ const entries = Array.from(node.values);
2857
+ const delKeys = [];
2858
+ for (let i = 0; i < entries.length; ++i) {
2859
+ const ci = await visitAsync_(i, entries[i][1], visitor, path);
2860
+ if (typeof ci === "number") i = ci - 1;
2861
+ else if (ci === BREAK) return BREAK;
2862
+ else if (ci === REMOVE) delKeys.push(entries[i][0]);
2863
+ }
2864
+ for (const dk of delKeys) node.values.delete(dk);
2636
2865
  } else if (node instanceof Pair) {
2637
- path = Object.freeze(path.concat(node));
2866
+ path = [...path, node];
2638
2867
  const ck = await visitAsync_("key", node.key, visitor, path);
2639
2868
  if (ck === BREAK) return BREAK;
2640
2869
  else if (ck === REMOVE) node.key = new Scalar(null);
@@ -2663,7 +2892,7 @@ function initVisitor(visitor) {
2663
2892
  }
2664
2893
  function callVisitor(key, node, visitor, path) {
2665
2894
  if (typeof visitor === "function") return visitor(key, node, path);
2666
- if (node instanceof YAMLMap) return visitor.Map?.(key, node, path);
2895
+ if (node instanceof YAMLMap || node instanceof YAMLSet) return visitor.Map?.(key, node, path);
2667
2896
  if (node instanceof YAMLSeq) return visitor.Seq?.(key, node, path);
2668
2897
  if (node instanceof Pair) return visitor.Pair?.(key, node, path);
2669
2898
  if (node instanceof Scalar) return visitor.Scalar?.(key, node, path);
@@ -2671,17 +2900,32 @@ function callVisitor(key, node, visitor, path) {
2671
2900
  }
2672
2901
  function replaceNode(key, path, node) {
2673
2902
  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;
2676
- else parent.value = node;
2677
- else throw new Error(`Cannot replace pair ${key} with non-node value`);
2678
- else if (parent instanceof Document) parent.value = node;
2679
- else {
2903
+ if (parent instanceof YAMLSeq) parent[key] = node;
2904
+ else if (parent instanceof YAMLMap) {
2905
+ if (node instanceof Pair) {
2906
+ const entries = Array.from(parent.values);
2907
+ entries[key] = [parent.keyOf(node, true), node];
2908
+ parent.values = new Map(entries);
2909
+ } else throw new Error("Cannot replace map pair with non-pair value");
2910
+ } else if (parent instanceof YAMLSet) {
2911
+ if (isNode(node)) {
2912
+ const entries = Array.from(parent.values);
2913
+ entries[key] = [parent.keyOf(node, true), node];
2914
+ parent.values = new Map(entries);
2915
+ } else throw new Error("Cannot replace set value with non-node value");
2916
+ } else if (parent instanceof Pair) {
2917
+ if (isNode(node)) {
2918
+ if (key === "key") parent.key = node;
2919
+ else parent.value = node;
2920
+ } else throw new Error(`Cannot replace pair ${key} with non-node value`);
2921
+ } else if (parent instanceof Document) {
2922
+ if (node instanceof Scalar || isCollection(node)) parent.value = node;
2923
+ else throw new Error("Cannot replace Document value with non-node value");
2924
+ } else {
2680
2925
  const pt = parent instanceof Alias ? "alias" : "scalar";
2681
2926
  throw new Error(`Cannot replace node with ${pt} parent`);
2682
2927
  }
2683
2928
  }
2684
-
2685
2929
  //#endregion
2686
2930
  //#region src/doc/directives.ts
2687
2931
  const escapeChars = {
@@ -2741,7 +2985,6 @@ var Directives = class Directives {
2741
2985
  version: "1.2"
2742
2986
  };
2743
2987
  this.tags = Object.assign({}, Directives.defaultTags);
2744
- break;
2745
2988
  }
2746
2989
  return res;
2747
2990
  }
@@ -2840,7 +3083,7 @@ var Directives = class Directives {
2840
3083
  if (doc && tagEntries.length > 0) {
2841
3084
  const tags = {};
2842
3085
  visit(doc.value, (_key, node) => {
2843
- if (node instanceof NodeBase && node.tag) tags[node.tag] = true;
3086
+ if (node?.tag) tags[node.tag] = true;
2844
3087
  });
2845
3088
  tagNames = Object.keys(tags);
2846
3089
  } else tagNames = [];
@@ -2851,6 +3094,5 @@ var Directives = class Directives {
2851
3094
  return lines.join("\n");
2852
3095
  }
2853
3096
  };
2854
-
2855
3097
  //#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 };
3098
+ export { Scalar as S, YAMLMap as _, Schema as a, stringifyString as b, seq as c, ToJSContext as d, Pair as f, YAMLSeq as g, YAMLSet as h, Document as i, map as l, isNode as m, visit as n, stringifyNumber as o, isCollection as p, visitAsync as r, string as s, Directives as t, Alias as u, debug as v, foldFlowLines as x, warn as y };