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
@@ -18,14 +18,17 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
18
18
  ? new YAMLMap.YAMLMap(ctx.schema)
19
19
  : new YAMLSeq.YAMLSeq(ctx.schema);
20
20
  coll.flow = true;
21
- let offset = fc.offset;
21
+ const atRoot = ctx.atRoot;
22
+ if (atRoot)
23
+ ctx.atRoot = false;
24
+ let offset = fc.offset + fc.start.source.length;
22
25
  for (let i = 0; i < fc.items.length; ++i) {
23
26
  const collItem = fc.items[i];
24
27
  const { start, key, sep, value } = collItem;
25
28
  const props = resolveProps.resolveProps(start, {
26
29
  flow: fcName,
27
30
  indicator: 'explicit-key-ind',
28
- next: key || (sep === null || sep === void 0 ? void 0 : sep[0]),
31
+ next: key ?? sep?.[0],
29
32
  offset,
30
33
  onError,
31
34
  startOnNewline: false
@@ -42,6 +45,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
42
45
  else
43
46
  coll.comment = props.comment;
44
47
  }
48
+ offset = props.end;
45
49
  continue;
46
50
  }
47
51
  if (!isMap && ctx.options.strict && utilContainsNewline.containsNewline(key))
@@ -72,7 +76,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
72
76
  if (prevItemComment) {
73
77
  let prev = coll.items[coll.items.length - 1];
74
78
  if (Node.isPair(prev))
75
- prev = prev.value || prev.key;
79
+ prev = prev.value ?? prev.key;
76
80
  if (prev.comment)
77
81
  prev.comment += '\n' + prevItemComment;
78
82
  else
@@ -102,7 +106,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
102
106
  if (isBlock(key))
103
107
  onError(keyNode.range, 'BLOCK_IN_FLOW', blockMsg);
104
108
  // value properties
105
- const valueProps = resolveProps.resolveProps(sep || [], {
109
+ const valueProps = resolveProps.resolveProps(sep ?? [], {
106
110
  flow: fcName,
107
111
  indicator: 'map-value-ind',
108
112
  next: value,
@@ -171,7 +175,11 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
171
175
  if (ce && ce.source === expectedEnd)
172
176
  cePos = ce.offset + ce.source.length;
173
177
  else {
174
- onError(offset + 1, 'MISSING_CHAR', `Expected ${fcName} to end with ${expectedEnd}`);
178
+ const name = fcName[0].toUpperCase() + fcName.substring(1);
179
+ const msg = atRoot
180
+ ? `${name} must end with a ${expectedEnd}`
181
+ : `${name} in block collection must be sufficiently indented and end with a ${expectedEnd}`;
182
+ onError(offset, atRoot ? 'MISSING_CHAR' : 'BAD_INDENT', msg);
175
183
  if (ce && ce.source.length !== 1)
176
184
  ee.unshift(ce);
177
185
  }
@@ -113,7 +113,7 @@ function foldLines(source) {
113
113
  const last = /[ \t]*(.*)/sy;
114
114
  last.lastIndex = pos;
115
115
  match = last.exec(source);
116
- return res + sep + ((match && match[1]) || '');
116
+ return res + sep + (match?.[1] ?? '');
117
117
  }
118
118
  function doubleQuotedValue(source, onError) {
119
119
  let res = '';
@@ -1,7 +1,7 @@
1
1
  import type { SourceToken, Token } from '../parse/cst.js';
2
2
  import type { ComposeErrorHandler } from './composer.js';
3
3
  export interface ResolvePropsArg {
4
- flow?: string;
4
+ flow?: 'flow map' | 'flow sequence';
5
5
  indicator: 'doc-start' | 'explicit-key-ind' | 'map-value-ind' | 'seq-item-ind';
6
6
  next: Token | null | undefined;
7
7
  offset: number;
@@ -14,6 +14,7 @@ export declare function resolveProps(tokens: SourceToken[], { flow, indicator, n
14
14
  spaceBefore: boolean;
15
15
  comment: string;
16
16
  hasNewline: boolean;
17
+ hasNewlineAfterProp: boolean;
17
18
  anchor: SourceToken | null;
18
19
  tag: SourceToken | null;
19
20
  end: number;
@@ -7,6 +7,7 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
7
7
  let comment = '';
8
8
  let commentSep = '';
9
9
  let hasNewline = false;
10
+ let hasNewlineAfterProp = false;
10
11
  let reqSpace = false;
11
12
  let anchor = null;
12
13
  let tag = null;
@@ -56,11 +57,15 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
56
57
  commentSep += token.source;
57
58
  atNewline = true;
58
59
  hasNewline = true;
60
+ if (anchor || tag)
61
+ hasNewlineAfterProp = true;
59
62
  hasSpace = true;
60
63
  break;
61
64
  case 'anchor':
62
65
  if (anchor)
63
66
  onError(token, 'MULTIPLE_ANCHORS', 'A node can have at most one anchor');
67
+ if (token.source.endsWith(':'))
68
+ onError(token.offset + token.source.length - 1, 'BAD_ALIAS', 'Anchor ending in : is ambiguous', true);
64
69
  anchor = token;
65
70
  if (start === null)
66
71
  start = token.offset;
@@ -83,6 +88,8 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
83
88
  // Could here handle preceding comments differently
84
89
  if (anchor || tag)
85
90
  onError(token, 'BAD_PROP_ORDER', `Anchors and tags must be after the ${token.source} indicator`);
91
+ if (found)
92
+ onError(token, 'UNEXPECTED_TOKEN', `Unexpected ${token.source} in ${flow ?? 'collection'}`);
86
93
  found = token;
87
94
  atNewline = false;
88
95
  hasSpace = false;
@@ -118,10 +125,11 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
118
125
  spaceBefore,
119
126
  comment,
120
127
  hasNewline,
128
+ hasNewlineAfterProp,
121
129
  anchor,
122
130
  tag,
123
131
  end,
124
- start: start !== null && start !== void 0 ? start : end
132
+ start: start ?? end
125
133
  };
126
134
  }
127
135
 
@@ -16,7 +16,7 @@ function emptyScalarPosition(offset, before, pos) {
16
16
  // Technically, an empty scalar is immediately after the last non-empty
17
17
  // node, but it's more useful to place it after any whitespace.
18
18
  st = before[++i];
19
- while ((st === null || st === void 0 ? void 0 : st.type) === 'space') {
19
+ while (st?.type === 'space') {
20
20
  offset += st.source.length;
21
21
  st = before[++i];
22
22
  }
@@ -0,0 +1,3 @@
1
+ import { Token } from '../parse/cst';
2
+ import { ComposeErrorHandler } from './composer';
3
+ export declare function flowIndentCheck(indent: number, fc: Token | null | undefined, onError: ComposeErrorHandler): void;
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ var utilContainsNewline = require('./util-contains-newline.js');
4
+
5
+ function flowIndentCheck(indent, fc, onError) {
6
+ if (fc?.type === 'flow-collection') {
7
+ const end = fc.end[0];
8
+ if (end.indent === indent &&
9
+ (end.source === ']' || end.source === '}') &&
10
+ utilContainsNewline.containsNewline(fc)) {
11
+ const msg = 'Flow end indicator should be more indented than parent';
12
+ onError(end, 'BAD_INDENT', msg, true);
13
+ }
14
+ }
15
+ }
16
+
17
+ exports.flowIndentCheck = flowIndentCheck;
@@ -1,20 +1,21 @@
1
1
  import type { YAMLError, YAMLWarning } from '../errors.js';
2
2
  import { Alias } from '../nodes/Alias.js';
3
- import { Node, NODE_TYPE, ParsedNode, Range } from '../nodes/Node.js';
3
+ import { Node, NodeType, NODE_TYPE, ParsedNode, Range } from '../nodes/Node.js';
4
4
  import { Pair } from '../nodes/Pair.js';
5
5
  import type { Scalar } from '../nodes/Scalar.js';
6
6
  import type { YAMLMap } from '../nodes/YAMLMap.js';
7
7
  import type { YAMLSeq } from '../nodes/YAMLSeq.js';
8
- import { CreateNodeOptions, DocumentOptions, ParseOptions, SchemaOptions, ToJSOptions, ToStringOptions } from '../options.js';
8
+ import type { CreateNodeOptions, DocumentOptions, ParseOptions, SchemaOptions, ToJSOptions, ToStringOptions } from '../options.js';
9
9
  import { Schema } from '../schema/Schema.js';
10
10
  import { Directives } from './directives.js';
11
11
  export declare type Replacer = any[] | ((key: any, value: any) => unknown);
12
12
  export declare namespace Document {
13
13
  interface Parsed<T extends ParsedNode = ParsedNode> extends Document<T> {
14
+ directives: Directives;
14
15
  range: Range;
15
16
  }
16
17
  }
17
- export declare class Document<T = unknown> {
18
+ export declare class Document<T extends Node = Node> {
18
19
  readonly [NODE_TYPE]: symbol;
19
20
  /** A comment before this Document */
20
21
  commentBefore: string | null;
@@ -22,10 +23,10 @@ export declare class Document<T = unknown> {
22
23
  comment: string | null;
23
24
  /** The document contents. */
24
25
  contents: T | null;
25
- directives: Directives;
26
+ directives?: Directives;
26
27
  /** Errors encountered during parsing. */
27
28
  errors: YAMLError[];
28
- options: Required<Omit<ParseOptions & DocumentOptions, 'lineCounter' | 'directives' | 'version'>>;
29
+ options: Required<Omit<ParseOptions & DocumentOptions, '_directives' | 'lineCounter' | 'version'>>;
29
30
  /**
30
31
  * The `[start, value-end, node-end]` character offsets for the part of the
31
32
  * source parsed into this document (undefined if not parsed). The `value-end`
@@ -67,8 +68,8 @@ export declare class Document<T = unknown> {
67
68
  * Convert any value into a `Node` using the current schema, recursively
68
69
  * turning objects into collections.
69
70
  */
70
- createNode(value: unknown, options?: CreateNodeOptions): Node;
71
- createNode(value: unknown, replacer: Replacer | CreateNodeOptions | null, options?: CreateNodeOptions): Node;
71
+ createNode<T = unknown>(value: T, options?: CreateNodeOptions): NodeType<T>;
72
+ createNode<T = unknown>(value: T, replacer: Replacer | CreateNodeOptions | null, options?: CreateNodeOptions): NodeType<T>;
72
73
  /**
73
74
  * Convert a key and a value into a `Pair` using the current schema,
74
75
  * recursively wrapping all values as `Scalar` or `Collection` nodes.
@@ -78,12 +79,12 @@ export declare class Document<T = unknown> {
78
79
  * Removes a value from the document.
79
80
  * @returns `true` if the item was found and removed.
80
81
  */
81
- delete(key: any): boolean;
82
+ delete(key: unknown): boolean;
82
83
  /**
83
84
  * Removes a value from the document.
84
85
  * @returns `true` if the item was found and removed.
85
86
  */
86
- deleteIn(path: Iterable<unknown>): boolean;
87
+ deleteIn(path: Iterable<unknown> | null): boolean;
87
88
  /**
88
89
  * Returns item at `key`, or `undefined` if not found. By default unwraps
89
90
  * scalar values from their surrounding node; to disable set `keepScalar` to
@@ -95,7 +96,7 @@ export declare class Document<T = unknown> {
95
96
  * scalar values from their surrounding node; to disable set `keepScalar` to
96
97
  * `true` (collections are always returned intact).
97
98
  */
98
- getIn(path: Iterable<unknown>, keepScalar?: boolean): unknown;
99
+ getIn(path: Iterable<unknown> | null, keepScalar?: boolean): unknown;
99
100
  /**
100
101
  * Checks if the document includes a value with the key `key`.
101
102
  */
@@ -103,7 +104,7 @@ export declare class Document<T = unknown> {
103
104
  /**
104
105
  * Checks if the document includes a value at `path`.
105
106
  */
106
- hasIn(path: Iterable<unknown>): boolean;
107
+ hasIn(path: Iterable<unknown> | null): boolean;
107
108
  /**
108
109
  * Sets a value in this document. For `!!set`, `value` needs to be a
109
110
  * boolean to add/remove the item from the set.
@@ -113,13 +114,15 @@ export declare class Document<T = unknown> {
113
114
  * Sets a value in this document. For `!!set`, `value` needs to be a
114
115
  * boolean to add/remove the item from the set.
115
116
  */
116
- setIn(path: Iterable<unknown>, value: unknown): void;
117
+ setIn(path: Iterable<unknown> | null, value: unknown): void;
117
118
  /**
118
119
  * Change the YAML version and schema used by the document.
120
+ * A `null` version disables support for directives, explicit tags, anchors, and aliases.
121
+ * It also requires the `schema` option to be given as a `Schema` instance value.
119
122
  *
120
- * Overrides all previously set schema options
123
+ * Overrides all previously set schema options.
121
124
  */
122
- setSchema(version: '1.1' | '1.2', options?: SchemaOptions): void;
125
+ setSchema(version: '1.1' | '1.2' | 'next' | null, options?: SchemaOptions): void;
123
126
  /** A plain JavaScript representation of the document `contents`. */
124
127
  toJS(opt?: ToJSOptions & {
125
128
  [ignored: string]: unknown;
@@ -5,7 +5,6 @@ var Collection = require('../nodes/Collection.js');
5
5
  var Node = require('../nodes/Node.js');
6
6
  var Pair = require('../nodes/Pair.js');
7
7
  var toJS = require('../nodes/toJS.js');
8
- var options = require('../options.js');
9
8
  var Schema = require('../schema/Schema.js');
10
9
  var stringify = require('../stringify/stringify.js');
11
10
  var stringifyDocument = require('../stringify/stringifyDocument.js');
@@ -15,7 +14,7 @@ var createNode = require('./createNode.js');
15
14
  var directives = require('./directives.js');
16
15
 
17
16
  class Document {
18
- constructor(value, replacer, options$1) {
17
+ constructor(value, replacer, options) {
19
18
  /** A comment before this Document */
20
19
  this.commentBefore = null;
21
20
  /** A comment immediately after this Document */
@@ -29,25 +28,33 @@ class Document {
29
28
  if (typeof replacer === 'function' || Array.isArray(replacer)) {
30
29
  _replacer = replacer;
31
30
  }
32
- else if (options$1 === undefined && replacer) {
33
- options$1 = replacer;
31
+ else if (options === undefined && replacer) {
32
+ options = replacer;
34
33
  replacer = undefined;
35
34
  }
36
- const opt = Object.assign({}, options.defaultOptions, options$1);
35
+ const opt = Object.assign({
36
+ intAsBigInt: false,
37
+ keepSourceTokens: false,
38
+ logLevel: 'warn',
39
+ prettyErrors: true,
40
+ strict: true,
41
+ uniqueKeys: true,
42
+ version: '1.2'
43
+ }, options);
37
44
  this.options = opt;
38
45
  let { version } = opt;
39
- if (options$1 === null || options$1 === void 0 ? void 0 : options$1.directives) {
40
- this.directives = options$1.directives.atDocument();
46
+ if (options?._directives) {
47
+ this.directives = options._directives.atDocument();
41
48
  if (this.directives.yaml.explicit)
42
49
  version = this.directives.yaml.version;
43
50
  }
44
51
  else
45
52
  this.directives = new directives.Directives({ version });
46
- this.setSchema(version, options$1);
53
+ this.setSchema(version, options);
47
54
  if (value === undefined)
48
55
  this.contents = null;
49
56
  else {
50
- this.contents = this.createNode(value, _replacer, options$1);
57
+ this.contents = this.createNode(value, _replacer, options);
51
58
  }
52
59
  }
53
60
  /**
@@ -64,7 +71,8 @@ class Document {
64
71
  copy.errors = this.errors.slice();
65
72
  copy.warnings = this.warnings.slice();
66
73
  copy.options = Object.assign({}, this.options);
67
- copy.directives = this.directives.clone();
74
+ if (this.directives)
75
+ copy.directives = this.directives.clone();
68
76
  copy.schema = this.schema.clone();
69
77
  copy.contents = Node.isNode(this.contents)
70
78
  ? this.contents.clone(copy.schema)
@@ -96,6 +104,7 @@ class Document {
96
104
  if (!node.anchor) {
97
105
  const prev = anchors.anchorNames(this);
98
106
  node.anchor =
107
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
99
108
  !name || prev.has(name) ? anchors.findNewAnchor(name || 'a', prev) : name;
100
109
  }
101
110
  return new Alias.Alias(node.anchor);
@@ -117,11 +126,13 @@ class Document {
117
126
  options = replacer;
118
127
  replacer = undefined;
119
128
  }
120
- const { aliasDuplicateObjects, anchorPrefix, flow, keepUndefined, onTagObj, tag } = options || {};
121
- const { onAnchor, setAnchors, sourceObjects } = anchors.createNodeAnchors(this, anchorPrefix || 'a');
129
+ const { aliasDuplicateObjects, anchorPrefix, flow, keepUndefined, onTagObj, tag } = options ?? {};
130
+ const { onAnchor, setAnchors, sourceObjects } = anchors.createNodeAnchors(this,
131
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
132
+ anchorPrefix || 'a');
122
133
  const ctx = {
123
- aliasDuplicateObjects: aliasDuplicateObjects !== null && aliasDuplicateObjects !== void 0 ? aliasDuplicateObjects : true,
124
- keepUndefined: keepUndefined !== null && keepUndefined !== void 0 ? keepUndefined : false,
134
+ aliasDuplicateObjects: aliasDuplicateObjects ?? true,
135
+ keepUndefined: keepUndefined ?? false,
125
136
  onAnchor,
126
137
  onTagObj,
127
138
  replacer: _replacer,
@@ -231,26 +242,48 @@ class Document {
231
242
  }
232
243
  /**
233
244
  * Change the YAML version and schema used by the document.
245
+ * A `null` version disables support for directives, explicit tags, anchors, and aliases.
246
+ * It also requires the `schema` option to be given as a `Schema` instance value.
234
247
  *
235
- * Overrides all previously set schema options
248
+ * Overrides all previously set schema options.
236
249
  */
237
- setSchema(version, options) {
238
- let _options;
239
- switch (String(version)) {
250
+ setSchema(version, options = {}) {
251
+ if (typeof version === 'number')
252
+ version = String(version);
253
+ let opt;
254
+ switch (version) {
240
255
  case '1.1':
241
- this.directives.yaml.version = '1.1';
242
- _options = Object.assign({ merge: true, resolveKnownTags: false, schema: 'yaml-1.1' }, options);
256
+ if (this.directives)
257
+ this.directives.yaml.version = '1.1';
258
+ else
259
+ this.directives = new directives.Directives({ version: '1.1' });
260
+ opt = { merge: true, resolveKnownTags: false, schema: 'yaml-1.1' };
243
261
  break;
244
262
  case '1.2':
245
- this.directives.yaml.version = '1.2';
246
- _options = Object.assign({ merge: false, resolveKnownTags: true, schema: 'core' }, options);
263
+ case 'next':
264
+ if (this.directives)
265
+ this.directives.yaml.version = version;
266
+ else
267
+ this.directives = new directives.Directives({ version });
268
+ opt = { merge: false, resolveKnownTags: true, schema: 'core' };
269
+ break;
270
+ case null:
271
+ if (this.directives)
272
+ delete this.directives;
273
+ opt = null;
247
274
  break;
248
275
  default: {
249
276
  const sv = JSON.stringify(version);
250
- throw new Error(`Expected '1.1' or '1.2' as version, but found: ${sv}`);
277
+ throw new Error(`Expected '1.1', '1.2' or null as first argument, but found: ${sv}`);
251
278
  }
252
279
  }
253
- this.schema = new Schema.Schema(_options);
280
+ // Not using `instanceof Schema` to allow for duck typing
281
+ if (options.schema instanceof Object)
282
+ this.schema = options.schema;
283
+ else if (opt)
284
+ this.schema = new Schema.Schema(Object.assign(opt, options));
285
+ else
286
+ throw new Error(`With a null YAML version, the { schema: Schema } option is required`);
254
287
  }
255
288
  // json & jsonArg are only used from toJSON()
256
289
  toJS({ json, jsonArg, mapAsMap, maxAliasCount, onAnchor, reviver } = {}) {
@@ -263,7 +296,7 @@ class Document {
263
296
  maxAliasCount: typeof maxAliasCount === 'number' ? maxAliasCount : 100,
264
297
  stringify: stringify.stringify
265
298
  };
266
- const res = toJS.toJS(this.contents, jsonArg || '', ctx);
299
+ const res = toJS.toJS(this.contents, jsonArg ?? '', ctx);
267
300
  if (typeof onAnchor === 'function')
268
301
  for (const { count, res } of ctx.anchors.values())
269
302
  onAnchor(res, count);
@@ -10,15 +10,15 @@ export declare function anchorNames(root: Document | Node): Set<string>;
10
10
  /** Find a new anchor name with the given `prefix` and a one-indexed suffix. */
11
11
  export declare function findNewAnchor(prefix: string, exclude: Set<string>): string;
12
12
  export declare function createNodeAnchors(doc: Document, prefix: string): {
13
- onAnchor(source: unknown): string;
13
+ onAnchor: (source: unknown) => string;
14
14
  /**
15
15
  * With circular references, the source node is only resolved after all
16
16
  * of its child nodes are. This is why anchors are set only after all of
17
17
  * the nodes have been created.
18
18
  */
19
- setAnchors(): void;
19
+ setAnchors: () => void;
20
20
  sourceObjects: Map<unknown, {
21
21
  anchor: string | null;
22
- node: Node | null;
22
+ node: Node<unknown> | null;
23
23
  }>;
24
24
  };
@@ -39,7 +39,7 @@ function createNodeAnchors(doc, prefix) {
39
39
  const sourceObjects = new Map();
40
40
  let prevAnchors = null;
41
41
  return {
42
- onAnchor(source) {
42
+ onAnchor: (source) => {
43
43
  aliasObjects.push(source);
44
44
  if (!prevAnchors)
45
45
  prevAnchors = anchorNames(doc);
@@ -52,7 +52,7 @@ function createNodeAnchors(doc, prefix) {
52
52
  * of its child nodes are. This is why anchors are set only after all of
53
53
  * the nodes have been created.
54
54
  */
55
- setAnchors() {
55
+ setAnchors: () => {
56
56
  for (const source of aliasObjects) {
57
57
  const ref = sourceObjects.get(source);
58
58
  if (typeof ref === 'object' &&
@@ -5,7 +5,7 @@ import type { Replacer } from './Document.js';
5
5
  export interface CreateNodeContext {
6
6
  aliasDuplicateObjects: boolean;
7
7
  keepUndefined: boolean;
8
- onAnchor(source: unknown): string;
8
+ onAnchor: (source: unknown) => string;
9
9
  onTagObj?: (tagObj: ScalarTag | CollectionTag) => void;
10
10
  sourceObjects: Map<unknown, {
11
11
  anchor: string | null;
@@ -8,21 +8,20 @@ const defaultTagPrefix = 'tag:yaml.org,2002:';
8
8
  function findTagObject(value, tagName, tags) {
9
9
  if (tagName) {
10
10
  const match = tags.filter(t => t.tag === tagName);
11
- const tagObj = match.find(t => !t.format) || match[0];
11
+ const tagObj = match.find(t => !t.format) ?? match[0];
12
12
  if (!tagObj)
13
13
  throw new Error(`Tag ${tagName} not found`);
14
14
  return tagObj;
15
15
  }
16
- return tags.find(t => t.identify && t.identify(value) && !t.format);
16
+ return tags.find(t => t.identify?.(value) && !t.format);
17
17
  }
18
18
  function createNode(value, tagName, ctx) {
19
- var _a, _b;
20
19
  if (Node.isDocument(value))
21
20
  value = value.contents;
22
21
  if (Node.isNode(value))
23
22
  return value;
24
23
  if (Node.isPair(value)) {
25
- const map = (_b = (_a = ctx.schema[Node.MAP]).createNode) === null || _b === void 0 ? void 0 : _b.call(_a, ctx.schema, null, ctx);
24
+ const map = ctx.schema[Node.MAP].createNode?.(ctx.schema, null, ctx);
26
25
  map.items.push(value);
27
26
  return map;
28
27
  }
@@ -50,12 +49,14 @@ function createNode(value, tagName, ctx) {
50
49
  sourceObjects.set(value, ref);
51
50
  }
52
51
  }
53
- if (tagName && tagName.startsWith('!!'))
52
+ if (tagName?.startsWith('!!'))
54
53
  tagName = defaultTagPrefix + tagName.slice(2);
55
54
  let tagObj = findTagObject(value, tagName, schema.tags);
56
55
  if (!tagObj) {
57
- if (value && typeof value.toJSON === 'function')
56
+ if (value && typeof value.toJSON === 'function') {
57
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
58
58
  value = value.toJSON();
59
+ }
59
60
  if (!value || typeof value !== 'object') {
60
61
  const node = new Scalar.Scalar(value);
61
62
  if (ref)
@@ -73,7 +74,7 @@ function createNode(value, tagName, ctx) {
73
74
  onTagObj(tagObj);
74
75
  delete ctx.onTagObj;
75
76
  }
76
- const node = (tagObj === null || tagObj === void 0 ? void 0 : tagObj.createNode)
77
+ const node = tagObj?.createNode
77
78
  ? tagObj.createNode(ctx.schema, value, ctx)
78
79
  : new Scalar.Scalar(value);
79
80
  if (tagName)
@@ -3,7 +3,7 @@ export declare class Directives {
3
3
  static defaultYaml: Directives['yaml'];
4
4
  static defaultTags: Directives['tags'];
5
5
  yaml: {
6
- version: '1.1' | '1.2';
6
+ version: '1.1' | '1.2' | 'next';
7
7
  explicit?: boolean;
8
8
  };
9
9
  tags: Record<string, string>;
@@ -11,7 +11,9 @@ export declare class Directives {
11
11
  * The directives-end/doc-start marker `---`. If `null`, a marker may still be
12
12
  * included in the document's stringified representation.
13
13
  */
14
- marker: true | null;
14
+ docStart: true | null;
15
+ /** The doc-end marker `...`. */
16
+ docEnd: boolean;
15
17
  /**
16
18
  * Used when parsing YAML 1.1, where:
17
19
  * > If the document specifies no directives, it is parsed using the same
@@ -18,13 +18,15 @@ class Directives {
18
18
  * The directives-end/doc-start marker `---`. If `null`, a marker may still be
19
19
  * included in the document's stringified representation.
20
20
  */
21
- this.marker = null;
21
+ this.docStart = null;
22
+ /** The doc-end marker `...`. */
23
+ this.docEnd = false;
22
24
  this.yaml = Object.assign({}, Directives.defaultYaml, yaml);
23
25
  this.tags = Object.assign({}, Directives.defaultTags, tags);
24
26
  }
25
27
  clone() {
26
28
  const copy = new Directives(this.yaml, this.tags);
27
- copy.marker = this.marker;
29
+ copy.docStart = this.docStart;
28
30
  return copy;
29
31
  }
30
32
  /**
@@ -73,7 +75,7 @@ class Directives {
73
75
  }
74
76
  case '%YAML': {
75
77
  this.yaml.explicit = true;
76
- if (parts.length < 1) {
78
+ if (parts.length !== 1) {
77
79
  onError(0, '%YAML directive should contain exactly one part');
78
80
  return false;
79
81
  }
@@ -83,7 +85,8 @@ class Directives {
83
85
  return true;
84
86
  }
85
87
  else {
86
- onError(6, `Unsupported YAML version ${version}`, true);
88
+ const isValid = /^\d+\.\d+$/.test(version);
89
+ onError(6, `Unsupported YAML version ${version}`, isValid);
87
90
  return false;
88
91
  }
89
92
  }
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ export { Pair } from './nodes/Pair.js';
8
8
  export { Scalar } from './nodes/Scalar.js';
9
9
  export { YAMLMap } from './nodes/YAMLMap.js';
10
10
  export { YAMLSeq } from './nodes/YAMLSeq.js';
11
- export { CreateNodeOptions, defaultOptions, DocumentOptions, ParseOptions, SchemaOptions, ToJSOptions, ToStringOptions } from './options.js';
11
+ export type { CreateNodeOptions, DocumentOptions, ParseOptions, SchemaOptions, ToJSOptions, ToStringOptions } from './options.js';
12
12
  export * as CST from './parse/cst.js';
13
13
  export { Lexer } from './parse/lexer.js';
14
14
  export { LineCounter } from './parse/line-counter.js';
@@ -16,4 +16,6 @@ export { Parser } from './parse/parser.js';
16
16
  export { EmptyStream, parse, parseAllDocuments, parseDocument, stringify } from './public-api.js';
17
17
  export type { TagId, Tags } from './schema/tags';
18
18
  export type { CollectionTag, ScalarTag } from './schema/types';
19
- export { visit, visitor, visitorFn } from './visit.js';
19
+ export type { YAMLOMap } from './schema/yaml-1.1/omap';
20
+ export type { YAMLSet } from './schema/yaml-1.1/set';
21
+ export { asyncVisitor, asyncVisitorFn, visit, visitAsync, visitor, visitorFn } from './visit.js';
package/dist/index.js CHANGED
@@ -10,7 +10,6 @@ var Pair = require('./nodes/Pair.js');
10
10
  var Scalar = require('./nodes/Scalar.js');
11
11
  var YAMLMap = require('./nodes/YAMLMap.js');
12
12
  var YAMLSeq = require('./nodes/YAMLSeq.js');
13
- var options = require('./options.js');
14
13
  var cst = require('./parse/cst.js');
15
14
  var lexer = require('./parse/lexer.js');
16
15
  var lineCounter = require('./parse/line-counter.js');
@@ -39,7 +38,6 @@ exports.Pair = Pair.Pair;
39
38
  exports.Scalar = Scalar.Scalar;
40
39
  exports.YAMLMap = YAMLMap.YAMLMap;
41
40
  exports.YAMLSeq = YAMLSeq.YAMLSeq;
42
- exports.defaultOptions = options.defaultOptions;
43
41
  exports.CST = cst;
44
42
  exports.Lexer = lexer.Lexer;
45
43
  exports.LineCounter = lineCounter.LineCounter;
@@ -49,3 +47,4 @@ exports.parseAllDocuments = publicApi.parseAllDocuments;
49
47
  exports.parseDocument = publicApi.parseDocument;
50
48
  exports.stringify = publicApi.stringify;
51
49
  exports.visit = visit.visit;
50
+ exports.visitAsync = visit.visitAsync;
@@ -1,7 +1,7 @@
1
1
  import type { Schema } from '../schema/Schema.js';
2
2
  import { NodeBase, NODE_TYPE } from './Node.js';
3
- export declare function collectionFromPath(schema: Schema, path: unknown[], value: unknown): import("./Node.js").Node;
4
- export declare const isEmptyPath: (path: Iterable<unknown> | null | undefined) => boolean;
3
+ export declare function collectionFromPath(schema: Schema, path: unknown[], value: unknown): import("./Node.js").Node<unknown>;
4
+ export declare const isEmptyPath: (path: Iterable<unknown> | null | undefined) => path is null | undefined;
5
5
  export declare abstract class Collection extends NodeBase {
6
6
  static maxFlowStringSingleLineLength: number;
7
7
  schema: Schema | undefined;
@@ -26,7 +26,8 @@ function collectionFromPath(schema, path, value) {
26
26
  sourceObjects: new Map()
27
27
  });
28
28
  }
29
- // null, undefined, or an empty non-string iterable (e.g. [])
29
+ // Type guard is intentionally a little wrong so as to be more useful,
30
+ // as it does not cover untypable empty non-string iterables (e.g. []).
30
31
  const isEmptyPath = (path) => path == null ||
31
32
  (typeof path === 'object' && !!path[Symbol.iterator]().next().done);
32
33
  class Collection extends Node.NodeBase {