yaml 2.0.0-9 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.md +1 -1
  2. package/browser/dist/compose/compose-collection.js +1 -1
  3. package/browser/dist/compose/compose-doc.js +4 -3
  4. package/browser/dist/compose/compose-node.js +13 -4
  5. package/browser/dist/compose/compose-scalar.js +18 -13
  6. package/browser/dist/compose/composer.js +8 -10
  7. package/browser/dist/compose/resolve-block-map.js +15 -8
  8. package/browser/dist/compose/resolve-block-scalar.js +12 -3
  9. package/browser/dist/compose/resolve-block-seq.js +5 -0
  10. package/browser/dist/compose/resolve-flow-collection.js +13 -5
  11. package/browser/dist/compose/resolve-flow-scalar.js +1 -1
  12. package/browser/dist/compose/resolve-props.js +9 -1
  13. package/browser/dist/compose/util-empty-scalar-position.js +1 -1
  14. package/browser/dist/compose/util-flow-indent-check.js +15 -0
  15. package/browser/dist/doc/Document.js +53 -20
  16. package/browser/dist/doc/anchors.js +2 -2
  17. package/browser/dist/doc/createNode.js +8 -7
  18. package/browser/dist/doc/directives.js +7 -4
  19. package/browser/dist/index.js +1 -2
  20. package/browser/dist/nodes/Collection.js +2 -1
  21. package/browser/dist/nodes/Pair.js +2 -2
  22. package/browser/dist/nodes/Scalar.js +1 -1
  23. package/browser/dist/nodes/YAMLMap.js +7 -7
  24. package/browser/dist/nodes/YAMLSeq.js +2 -10
  25. package/browser/dist/nodes/addPairToJSMap.js +1 -1
  26. package/browser/dist/nodes/toJS.js +3 -1
  27. package/browser/dist/parse/cst-scalar.js +1 -2
  28. package/browser/dist/parse/cst-visit.js +2 -2
  29. package/browser/dist/parse/lexer.js +20 -8
  30. package/browser/dist/parse/parser.js +142 -68
  31. package/browser/dist/public-api.js +5 -7
  32. package/browser/dist/schema/Schema.js +14 -4
  33. package/browser/dist/schema/common/null.js +3 -1
  34. package/browser/dist/schema/core/float.js +4 -1
  35. package/browser/dist/schema/tags.js +9 -9
  36. package/browser/dist/schema/yaml-1.1/float.js +4 -1
  37. package/browser/dist/schema/yaml-1.1/omap.js +1 -1
  38. package/browser/dist/schema/yaml-1.1/pairs.js +1 -1
  39. package/browser/dist/schema/yaml-1.1/set.js +4 -0
  40. package/browser/dist/stringify/stringify.js +49 -22
  41. package/browser/dist/stringify/stringifyCollection.js +114 -85
  42. package/browser/dist/stringify/stringifyComment.js +18 -12
  43. package/browser/dist/stringify/stringifyDocument.js +36 -15
  44. package/browser/dist/stringify/stringifyPair.js +34 -20
  45. package/browser/dist/stringify/stringifyString.js +8 -11
  46. package/browser/dist/visit.js +149 -62
  47. package/dist/compose/compose-collection.js +1 -1
  48. package/dist/compose/compose-doc.js +4 -3
  49. package/dist/compose/compose-node.d.ts +1 -0
  50. package/dist/compose/compose-node.js +13 -4
  51. package/dist/compose/compose-scalar.js +17 -12
  52. package/dist/compose/composer.d.ts +1 -1
  53. package/dist/compose/composer.js +10 -12
  54. package/dist/compose/resolve-block-map.js +15 -8
  55. package/dist/compose/resolve-block-scalar.js +12 -3
  56. package/dist/compose/resolve-block-seq.js +5 -0
  57. package/dist/compose/resolve-flow-collection.js +13 -5
  58. package/dist/compose/resolve-flow-scalar.js +1 -1
  59. package/dist/compose/resolve-props.d.ts +2 -1
  60. package/dist/compose/resolve-props.js +9 -1
  61. package/dist/compose/util-empty-scalar-position.js +1 -1
  62. package/dist/compose/util-flow-indent-check.d.ts +3 -0
  63. package/dist/compose/util-flow-indent-check.js +17 -0
  64. package/dist/doc/Document.d.ts +17 -14
  65. package/dist/doc/Document.js +58 -25
  66. package/dist/doc/anchors.d.ts +3 -3
  67. package/dist/doc/anchors.js +2 -2
  68. package/dist/doc/createNode.d.ts +1 -1
  69. package/dist/doc/createNode.js +8 -7
  70. package/dist/doc/directives.d.ts +4 -2
  71. package/dist/doc/directives.js +7 -4
  72. package/dist/index.d.ts +4 -2
  73. package/dist/index.js +1 -2
  74. package/dist/nodes/Collection.d.ts +2 -2
  75. package/dist/nodes/Collection.js +2 -1
  76. package/dist/nodes/Node.d.ts +14 -10
  77. package/dist/nodes/Pair.d.ts +1 -1
  78. package/dist/nodes/Pair.js +2 -2
  79. package/dist/nodes/Scalar.js +1 -1
  80. package/dist/nodes/YAMLMap.d.ts +9 -4
  81. package/dist/nodes/YAMLMap.js +7 -7
  82. package/dist/nodes/YAMLSeq.d.ts +4 -1
  83. package/dist/nodes/YAMLSeq.js +2 -10
  84. package/dist/nodes/addPairToJSMap.js +1 -1
  85. package/dist/nodes/toJS.js +3 -1
  86. package/dist/options.d.ts +44 -13
  87. package/dist/parse/cst-scalar.js +1 -2
  88. package/dist/parse/cst-visit.js +2 -2
  89. package/dist/parse/lexer.js +20 -8
  90. package/dist/parse/parser.js +142 -68
  91. package/dist/public-api.js +5 -7
  92. package/dist/schema/Schema.d.ts +5 -4
  93. package/dist/schema/Schema.js +13 -3
  94. package/dist/schema/common/null.js +3 -1
  95. package/dist/schema/core/float.js +4 -1
  96. package/dist/schema/json-schema.d.ts +69 -0
  97. package/dist/schema/tags.d.ts +1 -2
  98. package/dist/schema/tags.js +9 -9
  99. package/dist/schema/yaml-1.1/float.js +4 -1
  100. package/dist/schema/yaml-1.1/omap.d.ts +7 -3
  101. package/dist/schema/yaml-1.1/omap.js +1 -1
  102. package/dist/schema/yaml-1.1/pairs.js +1 -1
  103. package/dist/schema/yaml-1.1/set.d.ts +6 -2
  104. package/dist/schema/yaml-1.1/set.js +4 -0
  105. package/dist/stringify/stringify.d.ts +5 -3
  106. package/dist/stringify/stringify.js +49 -22
  107. package/dist/stringify/stringifyCollection.d.ts +2 -6
  108. package/dist/stringify/stringifyCollection.js +113 -84
  109. package/dist/stringify/stringifyComment.d.ts +10 -2
  110. package/dist/stringify/stringifyComment.js +19 -12
  111. package/dist/stringify/stringifyDocument.js +35 -14
  112. package/dist/stringify/stringifyPair.js +33 -19
  113. package/dist/stringify/stringifyString.js +8 -11
  114. package/dist/test-events.js +14 -14
  115. package/dist/visit.d.ts +49 -10
  116. package/dist/visit.js +148 -60
  117. package/package.json +11 -10
  118. package/browser/dist/options.js +0 -18
  119. package/dist/node_modules/tslib/tslib.es6.js +0 -76
  120. package/dist/options.js +0 -20
@@ -7,7 +7,7 @@ function includesToken(list, type) {
7
7
  return true;
8
8
  return false;
9
9
  }
10
- function includesNonEmpty(list) {
10
+ function findNonEmptyIndex(list) {
11
11
  for (let i = 0; i < list.length; ++i) {
12
12
  switch (list[i].type) {
13
13
  case 'space':
@@ -15,13 +15,13 @@ function includesNonEmpty(list) {
15
15
  case 'newline':
16
16
  break;
17
17
  default:
18
- return true;
18
+ return i;
19
19
  }
20
20
  }
21
- return false;
21
+ return -1;
22
22
  }
23
23
  function isFlowToken(token) {
24
- switch (token === null || token === void 0 ? void 0 : token.type) {
24
+ switch (token?.type) {
25
25
  case 'alias':
26
26
  case 'scalar':
27
27
  case 'single-quoted-scalar':
@@ -38,7 +38,7 @@ function getPrevProps(parent) {
38
38
  return parent.start;
39
39
  case 'block-map': {
40
40
  const it = parent.items[parent.items.length - 1];
41
- return it.sep || it.start;
41
+ return it.sep ?? it.start;
42
42
  }
43
43
  case 'block-seq':
44
44
  return parent.items[parent.items.length - 1].start;
@@ -49,7 +49,6 @@ function getPrevProps(parent) {
49
49
  }
50
50
  /** Note: May modify input array */
51
51
  function getFirstKeyStartProps(prev) {
52
- var _a;
53
52
  if (prev.length === 0)
54
53
  return [];
55
54
  let i = prev.length;
@@ -63,7 +62,7 @@ function getFirstKeyStartProps(prev) {
63
62
  break loop;
64
63
  }
65
64
  }
66
- while (((_a = prev[++i]) === null || _a === void 0 ? void 0 : _a.type) === 'space') {
65
+ while (prev[++i]?.type === 'space') {
67
66
  /* loop */
68
67
  }
69
68
  return prev.splice(i, prev.length);
@@ -203,6 +202,7 @@ class Parser {
203
202
  this.indent += source.length;
204
203
  break;
205
204
  case 'doc-mode':
205
+ case 'flow-error-end':
206
206
  return;
207
207
  default:
208
208
  this.atNewLine = false;
@@ -264,7 +264,7 @@ class Parser {
264
264
  return this.stack[this.stack.length - n];
265
265
  }
266
266
  *pop(error) {
267
- const token = error || this.stack.pop();
267
+ const token = error ?? this.stack.pop();
268
268
  /* istanbul ignore if should not happen */
269
269
  if (!token) {
270
270
  const message = 'Tried to pop an empty stack';
@@ -275,9 +275,14 @@ class Parser {
275
275
  }
276
276
  else {
277
277
  const top = this.peek(1);
278
- // For these, parent indent is needed instead of own
279
- if (token.type === 'block-scalar' || token.type === 'flow-collection')
280
- token.indent = 'indent' in top ? top.indent : -1;
278
+ if (token.type === 'block-scalar') {
279
+ // Block scalars use their parent rather than header indent
280
+ token.indent = 'indent' in top ? top.indent : 0;
281
+ }
282
+ else if (token.type === 'flow-collection' && top.type === 'document') {
283
+ // Ignore all indent for top-level flow collections
284
+ token.indent = 0;
285
+ }
281
286
  if (token.type === 'flow-collection')
282
287
  fixFlowSeqItems(token);
283
288
  switch (top.type) {
@@ -336,7 +341,7 @@ class Parser {
336
341
  !last.sep &&
337
342
  !last.value &&
338
343
  last.start.length > 0 &&
339
- !includesNonEmpty(last.start) &&
344
+ findNonEmptyIndex(last.start) === -1 &&
340
345
  (token.indent === 0 ||
341
346
  last.start.every(st => st.type !== 'comment' || st.indent < token.indent))) {
342
347
  if (top.type === 'document')
@@ -384,7 +389,7 @@ class Parser {
384
389
  return yield* this.lineEnd(doc);
385
390
  switch (this.type) {
386
391
  case 'doc-start': {
387
- if (includesNonEmpty(doc.start)) {
392
+ if (findNonEmptyIndex(doc.start) !== -1) {
388
393
  yield* this.pop();
389
394
  yield* this.step();
390
395
  }
@@ -464,7 +469,6 @@ class Parser {
464
469
  }
465
470
  }
466
471
  *blockMap(map) {
467
- var _a;
468
472
  const it = map.items[map.items.length - 1];
469
473
  // it.sep is true-ish if pair already has key or : separator
470
474
  switch (this.type) {
@@ -473,26 +477,30 @@ class Parser {
473
477
  if (it.value) {
474
478
  const end = 'end' in it.value ? it.value.end : undefined;
475
479
  const last = Array.isArray(end) ? end[end.length - 1] : undefined;
476
- if ((last === null || last === void 0 ? void 0 : last.type) === 'comment')
477
- end === null || end === void 0 ? void 0 : end.push(this.sourceToken);
480
+ if (last?.type === 'comment')
481
+ end?.push(this.sourceToken);
478
482
  else
479
483
  map.items.push({ start: [this.sourceToken] });
480
484
  }
481
- else if (it.sep)
485
+ else if (it.sep) {
482
486
  it.sep.push(this.sourceToken);
483
- else
487
+ }
488
+ else {
484
489
  it.start.push(this.sourceToken);
490
+ }
485
491
  return;
486
492
  case 'space':
487
493
  case 'comment':
488
- if (it.value)
494
+ if (it.value) {
489
495
  map.items.push({ start: [this.sourceToken] });
490
- else if (it.sep)
496
+ }
497
+ else if (it.sep) {
491
498
  it.sep.push(this.sourceToken);
499
+ }
492
500
  else {
493
501
  if (this.atIndentedComment(it.start, map.indent)) {
494
502
  const prev = map.items[map.items.length - 2];
495
- const end = (_a = prev === null || prev === void 0 ? void 0 : prev.value) === null || _a === void 0 ? void 0 : _a.end;
503
+ const end = prev?.value?.end;
496
504
  if (Array.isArray(end)) {
497
505
  Array.prototype.push.apply(end, it.start);
498
506
  end.push(this.sourceToken);
@@ -505,66 +513,132 @@ class Parser {
505
513
  return;
506
514
  }
507
515
  if (this.indent >= map.indent) {
508
- const atNextItem = !this.onKeyLine &&
509
- this.indent === map.indent &&
510
- (it.sep || includesNonEmpty(it.start));
516
+ const atNextItem = !this.onKeyLine && this.indent === map.indent && it.sep;
517
+ // For empty nodes, assign newline-separated not indented empty tokens to following node
518
+ let start = [];
519
+ if (atNextItem && it.sep && !it.value) {
520
+ const nl = [];
521
+ for (let i = 0; i < it.sep.length; ++i) {
522
+ const st = it.sep[i];
523
+ switch (st.type) {
524
+ case 'newline':
525
+ nl.push(i);
526
+ break;
527
+ case 'space':
528
+ break;
529
+ case 'comment':
530
+ if (st.indent > map.indent)
531
+ nl.length = 0;
532
+ break;
533
+ default:
534
+ nl.length = 0;
535
+ }
536
+ }
537
+ if (nl.length >= 2)
538
+ start = it.sep.splice(nl[1]);
539
+ }
511
540
  switch (this.type) {
512
541
  case 'anchor':
513
542
  case 'tag':
514
543
  if (atNextItem || it.value) {
515
- map.items.push({ start: [this.sourceToken] });
544
+ start.push(this.sourceToken);
545
+ map.items.push({ start });
516
546
  this.onKeyLine = true;
517
547
  }
518
- else if (it.sep)
548
+ else if (it.sep) {
519
549
  it.sep.push(this.sourceToken);
520
- else
550
+ }
551
+ else {
521
552
  it.start.push(this.sourceToken);
553
+ }
522
554
  return;
523
555
  case 'explicit-key-ind':
524
- if (!it.sep && !includesToken(it.start, 'explicit-key-ind'))
556
+ if (!it.sep && !includesToken(it.start, 'explicit-key-ind')) {
525
557
  it.start.push(this.sourceToken);
526
- else if (atNextItem || it.value)
527
- map.items.push({ start: [this.sourceToken] });
528
- else
558
+ }
559
+ else if (atNextItem || it.value) {
560
+ start.push(this.sourceToken);
561
+ map.items.push({ start });
562
+ }
563
+ else {
529
564
  this.stack.push({
530
565
  type: 'block-map',
531
566
  offset: this.offset,
532
567
  indent: this.indent,
533
568
  items: [{ start: [this.sourceToken] }]
534
569
  });
570
+ }
535
571
  this.onKeyLine = true;
536
572
  return;
537
573
  case 'map-value-ind':
538
- if (!it.sep)
539
- Object.assign(it, { key: null, sep: [this.sourceToken] });
540
- else if (it.value ||
541
- (atNextItem && !includesToken(it.start, 'explicit-key-ind')))
542
- map.items.push({ start: [], key: null, sep: [this.sourceToken] });
543
- else if (includesToken(it.sep, 'map-value-ind'))
544
- this.stack.push({
545
- type: 'block-map',
546
- offset: this.offset,
547
- indent: this.indent,
548
- items: [{ start: [], key: null, sep: [this.sourceToken] }]
549
- });
550
- else if (includesToken(it.start, 'explicit-key-ind') &&
551
- isFlowToken(it.key) &&
552
- !includesToken(it.sep, 'newline')) {
553
- const start = getFirstKeyStartProps(it.start);
554
- const key = it.key;
555
- const sep = it.sep;
556
- sep.push(this.sourceToken);
557
- // @ts-ignore type guard is wrong here
558
- delete it.key, delete it.sep;
559
- this.stack.push({
560
- type: 'block-map',
561
- offset: this.offset,
562
- indent: this.indent,
563
- items: [{ start, key, sep }]
564
- });
574
+ if (includesToken(it.start, 'explicit-key-ind')) {
575
+ if (!it.sep) {
576
+ if (includesToken(it.start, 'newline')) {
577
+ Object.assign(it, { key: null, sep: [this.sourceToken] });
578
+ }
579
+ else {
580
+ const start = getFirstKeyStartProps(it.start);
581
+ this.stack.push({
582
+ type: 'block-map',
583
+ offset: this.offset,
584
+ indent: this.indent,
585
+ items: [{ start, key: null, sep: [this.sourceToken] }]
586
+ });
587
+ }
588
+ }
589
+ else if (it.value) {
590
+ map.items.push({ start: [], key: null, sep: [this.sourceToken] });
591
+ }
592
+ else if (includesToken(it.sep, 'map-value-ind')) {
593
+ this.stack.push({
594
+ type: 'block-map',
595
+ offset: this.offset,
596
+ indent: this.indent,
597
+ items: [{ start, key: null, sep: [this.sourceToken] }]
598
+ });
599
+ }
600
+ else if (isFlowToken(it.key) &&
601
+ !includesToken(it.sep, 'newline')) {
602
+ const start = getFirstKeyStartProps(it.start);
603
+ const key = it.key;
604
+ const sep = it.sep;
605
+ sep.push(this.sourceToken);
606
+ // @ts-expect-error type guard is wrong here
607
+ delete it.key, delete it.sep;
608
+ this.stack.push({
609
+ type: 'block-map',
610
+ offset: this.offset,
611
+ indent: this.indent,
612
+ items: [{ start, key, sep }]
613
+ });
614
+ }
615
+ else if (start.length > 0) {
616
+ // Not actually at next item
617
+ it.sep = it.sep.concat(start, this.sourceToken);
618
+ }
619
+ else {
620
+ it.sep.push(this.sourceToken);
621
+ }
622
+ }
623
+ else {
624
+ if (!it.sep) {
625
+ Object.assign(it, { key: null, sep: [this.sourceToken] });
626
+ }
627
+ else if (it.value || atNextItem) {
628
+ map.items.push({ start, key: null, sep: [this.sourceToken] });
629
+ }
630
+ else if (includesToken(it.sep, 'map-value-ind')) {
631
+ this.stack.push({
632
+ type: 'block-map',
633
+ offset: this.offset,
634
+ indent: this.indent,
635
+ items: [{ start: [], key: null, sep: [this.sourceToken] }]
636
+ });
637
+ }
638
+ else {
639
+ it.sep.push(this.sourceToken);
640
+ }
565
641
  }
566
- else
567
- it.sep.push(this.sourceToken);
568
642
  this.onKeyLine = true;
569
643
  return;
570
644
  case 'alias':
@@ -573,7 +647,7 @@ class Parser {
573
647
  case 'double-quoted-scalar': {
574
648
  const fs = this.flowScalar(this.type);
575
649
  if (atNextItem || it.value) {
576
- map.items.push({ start: [], key: fs, sep: [] });
650
+ map.items.push({ start, key: fs, sep: [] });
577
651
  this.onKeyLine = true;
578
652
  }
579
653
  else if (it.sep) {
@@ -590,8 +664,9 @@ class Parser {
590
664
  if (bv) {
591
665
  if (atNextItem &&
592
666
  bv.type !== 'block-seq' &&
593
- includesToken(it.start, 'explicit-key-ind'))
594
- map.items.push({ start: [] });
667
+ includesToken(it.start, 'explicit-key-ind')) {
668
+ map.items.push({ start });
669
+ }
595
670
  this.stack.push(bv);
596
671
  return;
597
672
  }
@@ -602,15 +677,14 @@ class Parser {
602
677
  yield* this.step();
603
678
  }
604
679
  *blockSequence(seq) {
605
- var _a;
606
680
  const it = seq.items[seq.items.length - 1];
607
681
  switch (this.type) {
608
682
  case 'newline':
609
683
  if (it.value) {
610
684
  const end = 'end' in it.value ? it.value.end : undefined;
611
685
  const last = Array.isArray(end) ? end[end.length - 1] : undefined;
612
- if ((last === null || last === void 0 ? void 0 : last.type) === 'comment')
613
- end === null || end === void 0 ? void 0 : end.push(this.sourceToken);
686
+ if (last?.type === 'comment')
687
+ end?.push(this.sourceToken);
614
688
  else
615
689
  seq.items.push({ start: [this.sourceToken] });
616
690
  }
@@ -624,7 +698,7 @@ class Parser {
624
698
  else {
625
699
  if (this.atIndentedComment(it.start, seq.indent)) {
626
700
  const prev = seq.items[seq.items.length - 2];
627
- const end = (_a = prev === null || prev === void 0 ? void 0 : prev.value) === null || _a === void 0 ? void 0 : _a.end;
701
+ const end = prev?.value?.end;
628
702
  if (Array.isArray(end)) {
629
703
  Array.prototype.push.apply(end, it.start);
630
704
  end.push(this.sourceToken);
@@ -728,7 +802,7 @@ class Parser {
728
802
  else {
729
803
  const parent = this.peek(2);
730
804
  if (parent.type === 'block-map' &&
731
- (this.type === 'map-value-ind' ||
805
+ ((this.type === 'map-value-ind' && parent.indent === fc.indent) ||
732
806
  (this.type === 'newline' &&
733
807
  !parent.items[parent.items.length - 1].sep))) {
734
808
  yield* this.pop();
@@ -6,10 +6,8 @@ import { LineCounter } from './parse/line-counter.js';
6
6
  import { Parser } from './parse/parser.js';
7
7
 
8
8
  function parseOptions(options) {
9
- const prettyErrors = !options || options.prettyErrors !== false;
10
- const lineCounter = (options && options.lineCounter) ||
11
- (prettyErrors && new LineCounter()) ||
12
- null;
9
+ const prettyErrors = options.prettyErrors !== false;
10
+ const lineCounter = options.lineCounter || (prettyErrors && new LineCounter()) || null;
13
11
  return { lineCounter, prettyErrors };
14
12
  }
15
13
  /**
@@ -23,7 +21,7 @@ function parseOptions(options) {
23
21
  */
24
22
  function parseAllDocuments(source, options = {}) {
25
23
  const { lineCounter, prettyErrors } = parseOptions(options);
26
- const parser = new Parser(lineCounter === null || lineCounter === void 0 ? void 0 : lineCounter.addNewLine);
24
+ const parser = new Parser(lineCounter?.addNewLine);
27
25
  const composer = new Composer(options);
28
26
  const docs = Array.from(composer.compose(parser.parse(source)));
29
27
  if (prettyErrors && lineCounter)
@@ -38,7 +36,7 @@ function parseAllDocuments(source, options = {}) {
38
36
  /** Parse an input string into a single YAML.Document */
39
37
  function parseDocument(source, options = {}) {
40
38
  const { lineCounter, prettyErrors } = parseOptions(options);
41
- const parser = new Parser(lineCounter === null || lineCounter === void 0 ? void 0 : lineCounter.addNewLine);
39
+ const parser = new Parser(lineCounter?.addNewLine);
42
40
  const composer = new Composer(options);
43
41
  // `doc` is always set by compose.end(true) at the very latest
44
42
  let doc = null;
@@ -91,7 +89,7 @@ function stringify(value, replacer, options) {
91
89
  options = indent < 1 ? undefined : indent > 8 ? { indent: 8 } : { indent };
92
90
  }
93
91
  if (value === undefined) {
94
- const { keepUndefined } = options || replacer || {};
92
+ const { keepUndefined } = options ?? replacer ?? {};
95
93
  if (!keepUndefined)
96
94
  return undefined;
97
95
  }
@@ -2,21 +2,31 @@ import { MAP, SCALAR, SEQ } from '../nodes/Node.js';
2
2
  import { map } from './common/map.js';
3
3
  import { seq } from './common/seq.js';
4
4
  import { string } from './common/string.js';
5
- import { coreKnownTags, getTags } from './tags.js';
5
+ import { getTags, coreKnownTags } from './tags.js';
6
6
 
7
7
  const sortMapEntriesByKey = (a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
8
8
  class Schema {
9
- constructor({ customTags, merge, resolveKnownTags, schema, sortMapEntries }) {
9
+ constructor({ compat, customTags, merge, resolveKnownTags, schema, sortMapEntries, toStringDefaults }) {
10
+ this.compat = Array.isArray(compat)
11
+ ? getTags(compat, 'compat')
12
+ : compat
13
+ ? getTags(null, compat)
14
+ : null;
10
15
  this.merge = !!merge;
11
- this.name = schema || 'core';
16
+ this.name = (typeof schema === 'string' && schema) || 'core';
12
17
  this.knownTags = resolveKnownTags ? coreKnownTags : {};
13
18
  this.tags = getTags(customTags, this.name);
19
+ this.toStringOptions = toStringDefaults ?? null;
14
20
  Object.defineProperty(this, MAP, { value: map });
15
21
  Object.defineProperty(this, SCALAR, { value: string });
16
22
  Object.defineProperty(this, SEQ, { value: seq });
17
23
  // Used by createMap()
18
24
  this.sortMapEntries =
19
- sortMapEntries === true ? sortMapEntriesByKey : sortMapEntries || null;
25
+ typeof sortMapEntries === 'function'
26
+ ? sortMapEntries
27
+ : sortMapEntries === true
28
+ ? sortMapEntriesByKey
29
+ : null;
20
30
  }
21
31
  clone() {
22
32
  const copy = Object.create(Schema.prototype, Object.getOwnPropertyDescriptors(this));
@@ -7,7 +7,9 @@ const nullTag = {
7
7
  tag: 'tag:yaml.org,2002:null',
8
8
  test: /^(?:~|[Nn]ull|NULL)?$/,
9
9
  resolve: () => new Scalar(null),
10
- stringify: ({ source }, ctx) => source && nullTag.test.test(source) ? source : ctx.options.nullStr
10
+ stringify: ({ source }, ctx) => typeof source === 'string' && nullTag.test.test(source)
11
+ ? source
12
+ : ctx.options.nullStr
11
13
  };
12
14
 
13
15
  export { nullTag };
@@ -20,7 +20,10 @@ const floatExp = {
20
20
  format: 'EXP',
21
21
  test: /^[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+$/,
22
22
  resolve: str => parseFloat(str),
23
- stringify: ({ value }) => Number(value).toExponential()
23
+ stringify(node) {
24
+ const num = Number(node.value);
25
+ return isFinite(num) ? num.toExponential() : stringifyNumber(node);
26
+ }
24
27
  };
25
28
  const float = {
26
29
  identify: value => typeof value === 'number',
@@ -14,13 +14,13 @@ import { schema as schema$2 } from './yaml-1.1/schema.js';
14
14
  import { set } from './yaml-1.1/set.js';
15
15
  import { floatTime, intTime, timestamp } from './yaml-1.1/timestamp.js';
16
16
 
17
- const schemas = {
18
- core: schema,
19
- failsafe: [map, seq, string],
20
- json: schema$1,
21
- yaml11: schema$2,
22
- 'yaml-1.1': schema$2
23
- };
17
+ const schemas = new Map([
18
+ ['core', schema],
19
+ ['failsafe', [map, seq, string]],
20
+ ['json', schema$1],
21
+ ['yaml11', schema$2],
22
+ ['yaml-1.1', schema$2]
23
+ ]);
24
24
  const tagsByName = {
25
25
  binary,
26
26
  bool: boolTag,
@@ -48,12 +48,12 @@ const coreKnownTags = {
48
48
  'tag:yaml.org,2002:timestamp': timestamp
49
49
  };
50
50
  function getTags(customTags, schemaName) {
51
- let tags = schemas[schemaName];
51
+ let tags = schemas.get(schemaName);
52
52
  if (!tags) {
53
53
  if (Array.isArray(customTags))
54
54
  tags = [];
55
55
  else {
56
- const keys = Object.keys(schemas)
56
+ const keys = Array.from(schemas.keys())
57
57
  .filter(key => key !== 'yaml11')
58
58
  .map(key => JSON.stringify(key))
59
59
  .join(', ');
@@ -20,7 +20,10 @@ const floatExp = {
20
20
  format: 'EXP',
21
21
  test: /^[-+]?(?:[0-9][0-9_]*)?(?:\.[0-9_]*)?[eE][-+]?[0-9]+$/,
22
22
  resolve: (str) => parseFloat(str.replace(/_/g, '')),
23
- stringify: ({ value }) => Number(value).toExponential()
23
+ stringify(node) {
24
+ const num = Number(node.value);
25
+ return isFinite(num) ? num.toExponential() : stringifyNumber(node);
26
+ }
24
27
  };
25
28
  const float = {
26
29
  identify: value => typeof value === 'number',
@@ -22,7 +22,7 @@ class YAMLOMap extends YAMLSeq {
22
22
  if (!ctx)
23
23
  return super.toJSON(_);
24
24
  const map = new Map();
25
- if (ctx && ctx.onCreate)
25
+ if (ctx?.onCreate)
26
26
  ctx.onCreate(map);
27
27
  for (const pair of this.items) {
28
28
  let key, value;
@@ -18,7 +18,7 @@ function resolvePairs(seq, onError) {
18
18
  ? `${item.commentBefore}\n${pair.key.commentBefore}`
19
19
  : item.commentBefore;
20
20
  if (item.comment) {
21
- const cn = pair.value || pair.key;
21
+ const cn = pair.value ?? pair.key;
22
22
  cn.comment = cn.comment
23
23
  ? `${item.comment}\n${cn.comment}`
24
24
  : item.comment;
@@ -22,6 +22,10 @@ class YAMLSet extends YAMLMap {
22
22
  if (!prev)
23
23
  this.items.push(pair);
24
24
  }
25
+ /**
26
+ * If `keepPair` is `true`, returns the Pair matching `key`.
27
+ * Otherwise, returns the value of that Pair's key.
28
+ */
25
29
  get(key, keepPair) {
26
30
  const pair = findPair(this.items, key);
27
31
  return !keepPair && isPair(pair)