yaml 2.0.0-8 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.md +1 -1
  2. package/browser/dist/compose/compose-doc.js +3 -2
  3. package/browser/dist/compose/compose-node.js +14 -3
  4. package/browser/dist/compose/compose-scalar.js +16 -10
  5. package/browser/dist/compose/composer.js +6 -7
  6. package/browser/dist/compose/resolve-block-map.js +24 -9
  7. package/browser/dist/compose/resolve-block-scalar.js +12 -3
  8. package/browser/dist/compose/resolve-block-seq.js +5 -0
  9. package/browser/dist/compose/resolve-flow-collection.js +18 -6
  10. package/browser/dist/compose/resolve-flow-scalar.js +2 -1
  11. package/browser/dist/compose/resolve-props.js +8 -0
  12. package/browser/dist/compose/util-flow-indent-check.js +15 -0
  13. package/browser/dist/doc/Document.js +49 -16
  14. package/browser/dist/doc/anchors.js +2 -2
  15. package/browser/dist/doc/createNode.js +7 -4
  16. package/browser/dist/doc/directives.js +7 -4
  17. package/browser/dist/index.js +1 -2
  18. package/browser/dist/node_modules/tslib/tslib.es6.js +164 -0
  19. package/browser/dist/nodes/Collection.js +8 -4
  20. package/browser/dist/nodes/Pair.js +2 -2
  21. package/browser/dist/nodes/Scalar.js +1 -1
  22. package/browser/dist/nodes/YAMLMap.js +6 -5
  23. package/browser/dist/nodes/YAMLSeq.js +2 -2
  24. package/browser/dist/nodes/addPairToJSMap.js +3 -2
  25. package/browser/dist/nodes/toJS.js +3 -1
  26. package/browser/dist/parse/cst-scalar.js +2 -6
  27. package/browser/dist/parse/cst-visit.js +2 -2
  28. package/browser/dist/parse/lexer.js +27 -11
  29. package/browser/dist/parse/parser.js +135 -57
  30. package/browser/dist/public-api.js +4 -5
  31. package/browser/dist/schema/Schema.js +14 -4
  32. package/browser/dist/schema/common/null.js +3 -1
  33. package/browser/dist/schema/core/float.js +4 -1
  34. package/browser/dist/schema/tags.js +17 -13
  35. package/browser/dist/schema/yaml-1.1/float.js +4 -1
  36. package/browser/dist/schema/yaml-1.1/omap.js +1 -1
  37. package/browser/dist/schema/yaml-1.1/pairs.js +2 -1
  38. package/browser/dist/stringify/stringify.js +53 -23
  39. package/browser/dist/stringify/stringifyCollection.js +115 -85
  40. package/browser/dist/stringify/stringifyComment.js +18 -12
  41. package/browser/dist/stringify/stringifyDocument.js +37 -15
  42. package/browser/dist/stringify/stringifyPair.js +35 -21
  43. package/browser/dist/stringify/stringifyString.js +41 -43
  44. package/browser/dist/util.js +3 -0
  45. package/browser/dist/visit.js +150 -62
  46. package/dist/compose/compose-doc.js +3 -2
  47. package/dist/compose/compose-node.d.ts +1 -0
  48. package/dist/compose/compose-node.js +14 -3
  49. package/dist/compose/compose-scalar.js +15 -9
  50. package/dist/compose/composer.d.ts +1 -1
  51. package/dist/compose/composer.js +8 -9
  52. package/dist/compose/resolve-block-map.js +24 -9
  53. package/dist/compose/resolve-block-scalar.js +12 -3
  54. package/dist/compose/resolve-block-seq.js +5 -0
  55. package/dist/compose/resolve-flow-collection.js +18 -6
  56. package/dist/compose/resolve-flow-scalar.js +2 -1
  57. package/dist/compose/resolve-props.d.ts +2 -1
  58. package/dist/compose/resolve-props.js +8 -0
  59. package/dist/compose/util-flow-indent-check.d.ts +3 -0
  60. package/dist/compose/util-flow-indent-check.js +17 -0
  61. package/dist/doc/Document.d.ts +7 -4
  62. package/dist/doc/Document.js +56 -23
  63. package/dist/doc/anchors.d.ts +2 -2
  64. package/dist/doc/anchors.js +2 -2
  65. package/dist/doc/createNode.d.ts +1 -1
  66. package/dist/doc/createNode.js +7 -4
  67. package/dist/doc/directives.d.ts +4 -2
  68. package/dist/doc/directives.js +7 -4
  69. package/dist/index.d.ts +4 -4
  70. package/dist/index.js +1 -2
  71. package/dist/node_modules/tslib/tslib.es6.js +76 -0
  72. package/dist/nodes/Alias.d.ts +7 -3
  73. package/dist/nodes/Collection.d.ts +4 -4
  74. package/dist/nodes/Collection.js +8 -4
  75. package/dist/nodes/Node.d.ts +3 -0
  76. package/dist/nodes/Pair.d.ts +3 -0
  77. package/dist/nodes/Pair.js +2 -2
  78. package/dist/nodes/Scalar.d.ts +2 -0
  79. package/dist/nodes/Scalar.js +1 -1
  80. package/dist/nodes/YAMLMap.d.ts +5 -1
  81. package/dist/nodes/YAMLMap.js +6 -5
  82. package/dist/nodes/YAMLSeq.d.ts +2 -0
  83. package/dist/nodes/YAMLSeq.js +2 -2
  84. package/dist/nodes/addPairToJSMap.js +2 -1
  85. package/dist/nodes/toJS.js +3 -1
  86. package/dist/options.d.ts +60 -15
  87. package/dist/parse/cst-scalar.d.ts +6 -0
  88. package/dist/parse/cst-scalar.js +2 -6
  89. package/dist/parse/cst-visit.js +2 -2
  90. package/dist/parse/lexer.js +27 -11
  91. package/dist/parse/parser.js +135 -57
  92. package/dist/public-api.js +4 -5
  93. package/dist/schema/Schema.d.ts +5 -4
  94. package/dist/schema/Schema.js +13 -3
  95. package/dist/schema/common/null.js +3 -1
  96. package/dist/schema/core/float.js +4 -1
  97. package/dist/schema/tags.d.ts +1 -2
  98. package/dist/schema/tags.js +17 -13
  99. package/dist/schema/yaml-1.1/float.js +4 -1
  100. package/dist/schema/yaml-1.1/omap.js +1 -1
  101. package/dist/schema/yaml-1.1/pairs.js +2 -1
  102. package/dist/stringify/stringify.d.ts +5 -3
  103. package/dist/stringify/stringify.js +53 -23
  104. package/dist/stringify/stringifyCollection.d.ts +2 -6
  105. package/dist/stringify/stringifyCollection.js +114 -84
  106. package/dist/stringify/stringifyComment.d.ts +10 -2
  107. package/dist/stringify/stringifyComment.js +19 -12
  108. package/dist/stringify/stringifyDocument.js +36 -14
  109. package/dist/stringify/stringifyPair.js +34 -20
  110. package/dist/stringify/stringifyString.js +41 -43
  111. package/dist/test-events.d.ts +1 -1
  112. package/dist/test-events.js +13 -12
  113. package/dist/util.d.ts +3 -0
  114. package/dist/util.js +6 -0
  115. package/dist/visit.d.ts +49 -10
  116. package/dist/visit.js +149 -60
  117. package/package.json +10 -8
  118. package/util.d.ts +3 -0
  119. package/browser/dist/options.js +0 -17
  120. package/dist/options.js +0 -19
package/README.md CHANGED
@@ -19,7 +19,7 @@ For more information, see the project's documentation site: [**eemeli.org/yaml**
19
19
  To install:
20
20
 
21
21
  ```sh
22
- npm install --save-exact yaml@next
22
+ npm install yaml
23
23
  ```
24
24
 
25
25
  **Note:** These docs are for `yaml@2`. For v1, see the [v1.10.0 tag](https://github.com/eemeli/yaml/tree/v1.10.0) for the source and [eemeli.org/yaml/v1](https://eemeli.org/yaml/v1/) for the documentation.
@@ -7,19 +7,20 @@ function composeDoc(options, directives, { offset, start, value, end }, onError)
7
7
  const opts = Object.assign({ directives }, options);
8
8
  const doc = new Document(undefined, opts);
9
9
  const ctx = {
10
+ atRoot: true,
10
11
  directives: doc.directives,
11
12
  options: doc.options,
12
13
  schema: doc.schema
13
14
  };
14
15
  const props = resolveProps(start, {
15
16
  indicator: 'doc-start',
16
- next: value || (end === null || end === void 0 ? void 0 : end[0]),
17
+ next: value !== null && value !== void 0 ? value : end === null || end === void 0 ? void 0 : end[0],
17
18
  offset,
18
19
  onError,
19
20
  startOnNewline: true
20
21
  });
21
22
  if (props.found) {
22
- doc.directives.marker = true;
23
+ doc.directives.docStart = true;
23
24
  if (value &&
24
25
  (value.type === 'block-map' || value.type === 'block-seq') &&
25
26
  !props.hasNewline)
@@ -8,6 +8,7 @@ const CN = { composeNode, composeEmptyNode };
8
8
  function composeNode(ctx, token, props, onError) {
9
9
  const { spaceBefore, comment, anchor, tag } = props;
10
10
  let node;
11
+ let isSrcToken = true;
11
12
  switch (token.type) {
12
13
  case 'alias':
13
14
  node = composeAlias(ctx, token, onError);
@@ -29,9 +30,14 @@ function composeNode(ctx, token, props, onError) {
29
30
  if (anchor)
30
31
  node.anchor = anchor.source.substring(1);
31
32
  break;
32
- default:
33
- console.log(token);
34
- throw new Error(`Unsupporten token type: ${token.type}`);
33
+ default: {
34
+ const message = token.type === 'error'
35
+ ? token.message
36
+ : `Unsupported token (type: ${token.type})`;
37
+ onError(token, 'UNEXPECTED_TOKEN', message);
38
+ node = composeEmptyNode(ctx, token.offset, undefined, null, props, onError);
39
+ isSrcToken = false;
40
+ }
35
41
  }
36
42
  if (anchor && node.anchor === '')
37
43
  onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
@@ -43,6 +49,9 @@ function composeNode(ctx, token, props, onError) {
43
49
  else
44
50
  node.commentBefore = comment;
45
51
  }
52
+ // @ts-expect-error Type checking misses meaning of isSrcToken
53
+ if (ctx.options.keepSourceTokens && isSrcToken)
54
+ node.srcToken = token;
46
55
  return node;
47
56
  }
48
57
  function composeEmptyNode(ctx, offset, before, pos, { spaceBefore, comment, anchor, tag }, onError) {
@@ -68,6 +77,8 @@ function composeAlias({ options }, { offset, source, end }, onError) {
68
77
  const alias = new Alias(source.substring(1));
69
78
  if (alias.source === '')
70
79
  onError(offset, 'BAD_ALIAS', 'Alias cannot be an empty string');
80
+ if (alias.source.endsWith(':'))
81
+ onError(offset + source.length - 1, 'BAD_ALIAS', 'Alias ending in : is ambiguous', true);
71
82
  const valueEnd = offset + source.length;
72
83
  const re = resolveEnd(end, valueEnd, options.strict, onError);
73
84
  alias.range = [offset, valueEnd, re.offset];
@@ -1,4 +1,4 @@
1
- import { isScalar, SCALAR } from '../nodes/Node.js';
1
+ import { SCALAR, isScalar } from '../nodes/Node.js';
2
2
  import { Scalar } from '../nodes/Scalar.js';
3
3
  import { resolveBlockScalar } from './resolve-block-scalar.js';
4
4
  import { resolveFlowScalar } from './resolve-flow-scalar.js';
@@ -12,15 +12,17 @@ function composeScalar(ctx, token, tagToken, onError) {
12
12
  : null;
13
13
  const tag = tagToken && tagName
14
14
  ? findScalarTagByName(ctx.schema, value, tagName, tagToken, onError)
15
- : findScalarTagByTest(ctx.schema, value, token.type === 'scalar');
15
+ : token.type === 'scalar'
16
+ ? findScalarTagByTest(ctx, value, token, onError)
17
+ : ctx.schema[SCALAR];
16
18
  let scalar;
17
19
  try {
18
- const res = tag.resolve(value, msg => onError(tagToken || token, 'TAG_RESOLVE_FAILED', msg), ctx.options);
20
+ const res = tag.resolve(value, msg => onError(tagToken !== null && tagToken !== void 0 ? tagToken : token, 'TAG_RESOLVE_FAILED', msg), ctx.options);
19
21
  scalar = isScalar(res) ? res : new Scalar(res);
20
22
  }
21
23
  catch (error) {
22
24
  const msg = error instanceof Error ? error.message : String(error);
23
- onError(tagToken || token, 'TAG_RESOLVE_FAILED', msg);
25
+ onError(tagToken !== null && tagToken !== void 0 ? tagToken : token, 'TAG_RESOLVE_FAILED', msg);
24
26
  scalar = new Scalar(value);
25
27
  }
26
28
  scalar.range = range;
@@ -61,15 +63,19 @@ function findScalarTagByName(schema, value, tagName, tagToken, onError) {
61
63
  onError(tagToken, 'TAG_RESOLVE_FAILED', `Unresolved tag: ${tagName}`, tagName !== 'tag:yaml.org,2002:str');
62
64
  return schema[SCALAR];
63
65
  }
64
- function findScalarTagByTest(schema, value, apply) {
66
+ function findScalarTagByTest({ directives, schema }, value, token, onError) {
65
67
  var _a;
66
- if (apply) {
67
- for (const tag of schema.tags) {
68
- if (tag.default && ((_a = tag.test) === null || _a === void 0 ? void 0 : _a.test(value)))
69
- return tag;
68
+ const tag = schema.tags.find(tag => { var _a; return tag.default && ((_a = tag.test) === null || _a === void 0 ? void 0 : _a.test(value)); }) || schema[SCALAR];
69
+ if (schema.compat) {
70
+ const compat = (_a = schema.compat.find(tag => { var _a; return tag.default && ((_a = tag.test) === null || _a === void 0 ? void 0 : _a.test(value)); })) !== null && _a !== void 0 ? _a : schema[SCALAR];
71
+ if (tag.tag !== compat.tag) {
72
+ const ts = directives.tagString(tag.tag);
73
+ const cs = directives.tagString(compat.tag);
74
+ const msg = `Value may be parsed as either ${ts} or ${cs}`;
75
+ onError(token, 'TAG_RESOLVE_FAILED', msg, true);
70
76
  }
71
77
  }
72
- return schema[SCALAR];
78
+ return tag;
73
79
  }
74
80
 
75
81
  export { composeScalar };
@@ -2,7 +2,6 @@ import { Directives } from '../doc/directives.js';
2
2
  import { Document } from '../doc/Document.js';
3
3
  import { YAMLWarning, YAMLParseError } from '../errors.js';
4
4
  import { isCollection, isPair } from '../nodes/Node.js';
5
- import { defaultOptions } from '../options.js';
6
5
  import { composeDoc } from './compose-doc.js';
7
6
  import { resolveEnd } from './resolve-end.js';
8
7
 
@@ -68,9 +67,8 @@ class Composer {
68
67
  else
69
68
  this.errors.push(new YAMLParseError(pos, code, message));
70
69
  };
71
- this.directives = new Directives({
72
- version: options.version || defaultOptions.version
73
- });
70
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
71
+ this.directives = new Directives({ version: options.version || '1.2' });
74
72
  this.options = options;
75
73
  }
76
74
  decorate(doc, afterDoc) {
@@ -81,7 +79,7 @@ class Composer {
81
79
  if (afterDoc) {
82
80
  doc.comment = doc.comment ? `${doc.comment}\n${comment}` : comment;
83
81
  }
84
- else if (afterEmptyLine || doc.directives.marker || !dc) {
82
+ else if (afterEmptyLine || doc.directives.docStart || !dc) {
85
83
  doc.commentBefore = comment;
86
84
  }
87
85
  else if (isCollection(dc) && !dc.flow && dc.items.length > 0) {
@@ -146,8 +144,8 @@ class Composer {
146
144
  break;
147
145
  case 'document': {
148
146
  const doc = composeDoc(this.options, this.directives, token, this.onError);
149
- if (this.atDirectives && !doc.directives.marker)
150
- this.onError(token, 'MISSING_CHAR', 'Missing directives-end indicator line');
147
+ if (this.atDirectives && !doc.directives.docStart)
148
+ this.onError(token, 'MISSING_CHAR', 'Missing directives-end/doc-start indicator line');
151
149
  this.decorate(doc, false);
152
150
  if (this.doc)
153
151
  yield this.doc;
@@ -179,6 +177,7 @@ class Composer {
179
177
  this.errors.push(new YAMLParseError(getErrorPos(token), 'UNEXPECTED_TOKEN', msg));
180
178
  break;
181
179
  }
180
+ this.doc.directives.docEnd = true;
182
181
  const end = resolveEnd(token.end, token.offset + token.source.length, this.doc.options.strict, this.onError);
183
182
  this.decorate(this.doc, true);
184
183
  if (end.comment) {
@@ -2,18 +2,22 @@ import { Pair } from '../nodes/Pair.js';
2
2
  import { YAMLMap } from '../nodes/YAMLMap.js';
3
3
  import { resolveProps } from './resolve-props.js';
4
4
  import { containsNewline } from './util-contains-newline.js';
5
+ import { flowIndentCheck } from './util-flow-indent-check.js';
5
6
  import { mapIncludes } from './util-map-includes.js';
6
7
 
7
8
  const startColMsg = 'All mapping items must start at the same column';
8
9
  function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError) {
9
10
  var _a;
10
11
  const map = new YAMLMap(ctx.schema);
12
+ if (ctx.atRoot)
13
+ ctx.atRoot = false;
11
14
  let offset = bm.offset;
12
- for (const { start, key, sep, value } of bm.items) {
15
+ for (const collItem of bm.items) {
16
+ const { start, key, sep, value } = collItem;
13
17
  // key properties
14
18
  const keyProps = resolveProps(start, {
15
19
  indicator: 'explicit-key-ind',
16
- next: key || (sep === null || sep === void 0 ? void 0 : sep[0]),
20
+ next: key !== null && key !== void 0 ? key : sep === null || sep === void 0 ? void 0 : sep[0],
17
21
  offset,
18
22
  onError,
19
23
  startOnNewline: true
@@ -36,21 +40,24 @@ function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError) {
36
40
  }
37
41
  continue;
38
42
  }
43
+ if (keyProps.hasNewlineAfterProp || containsNewline(key)) {
44
+ onError(key !== null && key !== void 0 ? key : start[start.length - 1], 'MULTILINE_IMPLICIT_KEY', 'Implicit keys need to be on a single line');
45
+ }
39
46
  }
40
- else if (((_a = keyProps.found) === null || _a === void 0 ? void 0 : _a.indent) !== bm.indent)
47
+ else if (((_a = keyProps.found) === null || _a === void 0 ? void 0 : _a.indent) !== bm.indent) {
41
48
  onError(offset, 'BAD_INDENT', startColMsg);
42
- if (implicitKey && containsNewline(key))
43
- onError(key, // checked by containsNewline()
44
- 'MULTILINE_IMPLICIT_KEY', 'Implicit keys need to be on a single line');
49
+ }
45
50
  // key value
46
51
  const keyStart = keyProps.end;
47
52
  const keyNode = key
48
53
  ? composeNode(ctx, key, keyProps, onError)
49
54
  : composeEmptyNode(ctx, keyStart, start, null, keyProps, onError);
55
+ if (ctx.schema.compat)
56
+ flowIndentCheck(bm.indent, key, onError);
50
57
  if (mapIncludes(ctx, map.items, keyNode))
51
58
  onError(keyStart, 'DUPLICATE_KEY', 'Map keys must be unique');
52
59
  // value properties
53
- const valueProps = resolveProps(sep || [], {
60
+ const valueProps = resolveProps(sep !== null && sep !== void 0 ? sep : [], {
54
61
  indicator: 'map-value-ind',
55
62
  next: value,
56
63
  offset: keyNode.range[2],
@@ -70,8 +77,13 @@ function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError) {
70
77
  const valueNode = value
71
78
  ? composeNode(ctx, value, valueProps, onError)
72
79
  : composeEmptyNode(ctx, offset, sep, null, valueProps, onError);
80
+ if (ctx.schema.compat)
81
+ flowIndentCheck(bm.indent, value, onError);
73
82
  offset = valueNode.range[2];
74
- map.items.push(new Pair(keyNode, valueNode));
83
+ const pair = new Pair(keyNode, valueNode);
84
+ if (ctx.options.keepSourceTokens)
85
+ pair.srcToken = collItem;
86
+ map.items.push(pair);
75
87
  }
76
88
  else {
77
89
  // key with no value
@@ -83,7 +95,10 @@ function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError) {
83
95
  else
84
96
  keyNode.comment = valueProps.comment;
85
97
  }
86
- map.items.push(new Pair(keyNode));
98
+ const pair = new Pair(keyNode);
99
+ if (ctx.options.keepSourceTokens)
100
+ pair.srcToken = collItem;
101
+ map.items.push(pair);
87
102
  }
88
103
  }
89
104
  map.range = [bm.offset, offset, offset];
@@ -17,8 +17,10 @@ function resolveBlockScalar(scalar, strict, onError) {
17
17
  break;
18
18
  }
19
19
  // shortcut for empty contents
20
- if (!scalar.source || chompStart === 0) {
21
- const value = header.chomp === '+' ? lines.map(line => line[0]).join('\n') : '';
20
+ if (chompStart === 0) {
21
+ const value = header.chomp === '+' && lines.length > 0
22
+ ? '\n'.repeat(Math.max(1, lines.length - 1))
23
+ : '';
22
24
  let end = start + header.length;
23
25
  if (scalar.source)
24
26
  end += scalar.source.length;
@@ -46,6 +48,11 @@ function resolveBlockScalar(scalar, strict, onError) {
46
48
  }
47
49
  offset += indent.length + content.length + 1;
48
50
  }
51
+ // include trailing more-indented empty lines in content
52
+ for (let i = lines.length - 1; i >= chompStart; --i) {
53
+ if (lines[i][0].length > trimIndent)
54
+ chompStart = i + 1;
55
+ }
49
56
  let value = '';
50
57
  let sep = '';
51
58
  let prevMoreIndented = false;
@@ -175,7 +182,9 @@ function splitLines(source) {
175
182
  const split = source.split(/\n( *)/);
176
183
  const first = split[0];
177
184
  const m = first.match(/^( *)/);
178
- const line0 = m && m[1] ? [m[1], first.slice(m[1].length)] : ['', first];
185
+ const line0 = (m === null || m === void 0 ? void 0 : m[1])
186
+ ? [m[1], first.slice(m[1].length)]
187
+ : ['', first];
179
188
  const lines = [line0];
180
189
  for (let i = 1; i < split.length; i += 2)
181
190
  lines.push([split[i], split[i + 1]]);
@@ -1,8 +1,11 @@
1
1
  import { YAMLSeq } from '../nodes/YAMLSeq.js';
2
2
  import { resolveProps } from './resolve-props.js';
3
+ import { flowIndentCheck } from './util-flow-indent-check.js';
3
4
 
4
5
  function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError) {
5
6
  const seq = new YAMLSeq(ctx.schema);
7
+ if (ctx.atRoot)
8
+ ctx.atRoot = false;
6
9
  let offset = bs.offset;
7
10
  for (const { start, value } of bs.items) {
8
11
  const props = resolveProps(start, {
@@ -30,6 +33,8 @@ function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError) {
30
33
  const node = value
31
34
  ? composeNode(ctx, value, props, onError)
32
35
  : composeEmptyNode(ctx, offset, start, null, props, onError);
36
+ if (ctx.schema.compat)
37
+ flowIndentCheck(bs.indent, value, onError);
33
38
  offset = node.range[2];
34
39
  seq.items.push(node);
35
40
  }
@@ -10,19 +10,24 @@ import { mapIncludes } from './util-map-includes.js';
10
10
  const blockMsg = 'Block collections are not allowed within flow collections';
11
11
  const isBlock = (token) => token && (token.type === 'block-map' || token.type === 'block-seq');
12
12
  function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onError) {
13
+ var _a;
13
14
  const isMap = fc.start.source === '{';
14
15
  const fcName = isMap ? 'flow map' : 'flow sequence';
15
16
  const coll = isMap
16
17
  ? new YAMLMap(ctx.schema)
17
18
  : new YAMLSeq(ctx.schema);
18
19
  coll.flow = true;
19
- let offset = fc.offset;
20
+ const atRoot = ctx.atRoot;
21
+ if (atRoot)
22
+ ctx.atRoot = false;
23
+ let offset = fc.offset + fc.start.source.length;
20
24
  for (let i = 0; i < fc.items.length; ++i) {
21
- const { start, key, sep, value } = fc.items[i];
25
+ const collItem = fc.items[i];
26
+ const { start, key, sep, value } = collItem;
22
27
  const props = resolveProps(start, {
23
28
  flow: fcName,
24
29
  indicator: 'explicit-key-ind',
25
- next: key || (sep === null || sep === void 0 ? void 0 : sep[0]),
30
+ next: key !== null && key !== void 0 ? key : sep === null || sep === void 0 ? void 0 : sep[0],
26
31
  offset,
27
32
  onError,
28
33
  startOnNewline: false
@@ -39,6 +44,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
39
44
  else
40
45
  coll.comment = props.comment;
41
46
  }
47
+ offset = props.end;
42
48
  continue;
43
49
  }
44
50
  if (!isMap && ctx.options.strict && containsNewline(key))
@@ -69,7 +75,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
69
75
  if (prevItemComment) {
70
76
  let prev = coll.items[coll.items.length - 1];
71
77
  if (isPair(prev))
72
- prev = prev.value || prev.key;
78
+ prev = (_a = prev.value) !== null && _a !== void 0 ? _a : prev.key;
73
79
  if (prev.comment)
74
80
  prev.comment += '\n' + prevItemComment;
75
81
  else
@@ -99,7 +105,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
99
105
  if (isBlock(key))
100
106
  onError(keyNode.range, 'BLOCK_IN_FLOW', blockMsg);
101
107
  // value properties
102
- const valueProps = resolveProps(sep || [], {
108
+ const valueProps = resolveProps(sep !== null && sep !== void 0 ? sep : [], {
103
109
  flow: fcName,
104
110
  indicator: 'map-value-ind',
105
111
  next: value,
@@ -145,6 +151,8 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
145
151
  keyNode.comment = valueProps.comment;
146
152
  }
147
153
  const pair = new Pair(keyNode, valueNode);
154
+ if (ctx.options.keepSourceTokens)
155
+ pair.srcToken = collItem;
148
156
  if (isMap) {
149
157
  const map = coll;
150
158
  if (mapIncludes(ctx, map.items, keyNode))
@@ -166,7 +174,11 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
166
174
  if (ce && ce.source === expectedEnd)
167
175
  cePos = ce.offset + ce.source.length;
168
176
  else {
169
- onError(offset + 1, 'MISSING_CHAR', `Expected ${fcName} to end with ${expectedEnd}`);
177
+ const name = fcName[0].toUpperCase() + fcName.substring(1);
178
+ const msg = atRoot
179
+ ? `${name} must end with a ${expectedEnd}`
180
+ : `${name} in block collection must be sufficiently indented and end with a ${expectedEnd}`;
181
+ onError(offset, atRoot ? 'MISSING_CHAR' : 'BAD_INDENT', msg);
170
182
  if (ce && ce.source.length !== 1)
171
183
  ee.unshift(ce);
172
184
  }
@@ -72,6 +72,7 @@ function singleQuotedValue(source, onError) {
72
72
  return foldLines(source.slice(1, -1)).replace(/''/g, "'");
73
73
  }
74
74
  function foldLines(source) {
75
+ var _a;
75
76
  /**
76
77
  * The negative lookbehind here and in the `re` RegExp is to
77
78
  * prevent causing a polynomial search time in certain cases.
@@ -111,7 +112,7 @@ function foldLines(source) {
111
112
  const last = /[ \t]*(.*)/sy;
112
113
  last.lastIndex = pos;
113
114
  match = last.exec(source);
114
- return res + sep + ((match && match[1]) || '');
115
+ return res + sep + ((_a = match === null || match === void 0 ? void 0 : match[1]) !== null && _a !== void 0 ? _a : '');
115
116
  }
116
117
  function doubleQuotedValue(source, onError) {
117
118
  let res = '';
@@ -5,6 +5,7 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
5
5
  let comment = '';
6
6
  let commentSep = '';
7
7
  let hasNewline = false;
8
+ let hasNewlineAfterProp = false;
8
9
  let reqSpace = false;
9
10
  let anchor = null;
10
11
  let tag = null;
@@ -54,11 +55,15 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
54
55
  commentSep += token.source;
55
56
  atNewline = true;
56
57
  hasNewline = true;
58
+ if (anchor || tag)
59
+ hasNewlineAfterProp = true;
57
60
  hasSpace = true;
58
61
  break;
59
62
  case 'anchor':
60
63
  if (anchor)
61
64
  onError(token, 'MULTIPLE_ANCHORS', 'A node can have at most one anchor');
65
+ if (token.source.endsWith(':'))
66
+ onError(token.offset + token.source.length - 1, 'BAD_ALIAS', 'Anchor ending in : is ambiguous', true);
62
67
  anchor = token;
63
68
  if (start === null)
64
69
  start = token.offset;
@@ -81,6 +86,8 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
81
86
  // Could here handle preceding comments differently
82
87
  if (anchor || tag)
83
88
  onError(token, 'BAD_PROP_ORDER', `Anchors and tags must be after the ${token.source} indicator`);
89
+ if (found)
90
+ onError(token, 'UNEXPECTED_TOKEN', `Unexpected ${token.source} in ${flow !== null && flow !== void 0 ? flow : 'collection'}`);
84
91
  found = token;
85
92
  atNewline = false;
86
93
  hasSpace = false;
@@ -116,6 +123,7 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
116
123
  spaceBefore,
117
124
  comment,
118
125
  hasNewline,
126
+ hasNewlineAfterProp,
119
127
  anchor,
120
128
  tag,
121
129
  end,
@@ -0,0 +1,15 @@
1
+ import { containsNewline } from './util-contains-newline.js';
2
+
3
+ function flowIndentCheck(indent, fc, onError) {
4
+ if ((fc === null || fc === void 0 ? void 0 : fc.type) === 'flow-collection') {
5
+ const end = fc.end[0];
6
+ if (end.indent === indent &&
7
+ (end.source === ']' || end.source === '}') &&
8
+ containsNewline(fc)) {
9
+ const msg = 'Flow end indicator should be more indented than parent';
10
+ onError(end, 'BAD_INDENT', msg, true);
11
+ }
12
+ }
13
+ }
14
+
15
+ export { flowIndentCheck };
@@ -3,7 +3,6 @@ import { isEmptyPath, collectionFromPath } from '../nodes/Collection.js';
3
3
  import { NODE_TYPE, DOC, isNode, isCollection, isScalar } from '../nodes/Node.js';
4
4
  import { Pair } from '../nodes/Pair.js';
5
5
  import { toJS } from '../nodes/toJS.js';
6
- import { defaultOptions } from '../options.js';
7
6
  import { Schema } from '../schema/Schema.js';
8
7
  import { stringify } from '../stringify/stringify.js';
9
8
  import { stringifyDocument } from '../stringify/stringifyDocument.js';
@@ -31,7 +30,15 @@ class Document {
31
30
  options = replacer;
32
31
  replacer = undefined;
33
32
  }
34
- const opt = Object.assign({}, defaultOptions, options);
33
+ const opt = Object.assign({
34
+ intAsBigInt: false,
35
+ keepSourceTokens: false,
36
+ logLevel: 'warn',
37
+ prettyErrors: true,
38
+ strict: true,
39
+ uniqueKeys: true,
40
+ version: '1.2'
41
+ }, options);
35
42
  this.options = opt;
36
43
  let { version } = opt;
37
44
  if (options === null || options === void 0 ? void 0 : options.directives) {
@@ -62,7 +69,8 @@ class Document {
62
69
  copy.errors = this.errors.slice();
63
70
  copy.warnings = this.warnings.slice();
64
71
  copy.options = Object.assign({}, this.options);
65
- copy.directives = this.directives.clone();
72
+ if (this.directives)
73
+ copy.directives = this.directives.clone();
66
74
  copy.schema = this.schema.clone();
67
75
  copy.contents = isNode(this.contents)
68
76
  ? this.contents.clone(copy.schema)
@@ -94,6 +102,7 @@ class Document {
94
102
  if (!node.anchor) {
95
103
  const prev = anchorNames(this);
96
104
  node.anchor =
105
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
97
106
  !name || prev.has(name) ? findNewAnchor(name || 'a', prev) : name;
98
107
  }
99
108
  return new Alias(node.anchor);
@@ -115,8 +124,10 @@ class Document {
115
124
  options = replacer;
116
125
  replacer = undefined;
117
126
  }
118
- const { aliasDuplicateObjects, anchorPrefix, flow, keepUndefined, onTagObj, tag } = options || {};
119
- const { onAnchor, setAnchors, sourceObjects } = createNodeAnchors(this, anchorPrefix || 'a');
127
+ const { aliasDuplicateObjects, anchorPrefix, flow, keepUndefined, onTagObj, tag } = options !== null && options !== void 0 ? options : {};
128
+ const { onAnchor, setAnchors, sourceObjects } = createNodeAnchors(this,
129
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
130
+ anchorPrefix || 'a');
120
131
  const ctx = {
121
132
  aliasDuplicateObjects: aliasDuplicateObjects !== null && aliasDuplicateObjects !== void 0 ? aliasDuplicateObjects : true,
122
133
  keepUndefined: keepUndefined !== null && keepUndefined !== void 0 ? keepUndefined : false,
@@ -229,26 +240,48 @@ class Document {
229
240
  }
230
241
  /**
231
242
  * Change the YAML version and schema used by the document.
243
+ * A `null` version disables support for directives, explicit tags, anchors, and aliases.
244
+ * It also requires the `schema` option to be given as a `Schema` instance value.
232
245
  *
233
- * Overrides all previously set schema options
246
+ * Overrides all previously set schema options.
234
247
  */
235
- setSchema(version, options) {
236
- let _options;
237
- switch (String(version)) {
248
+ setSchema(version, options = {}) {
249
+ if (typeof version === 'number')
250
+ version = String(version);
251
+ let opt;
252
+ switch (version) {
238
253
  case '1.1':
239
- this.directives.yaml.version = '1.1';
240
- _options = Object.assign({ merge: true, resolveKnownTags: false, schema: 'yaml-1.1' }, options);
254
+ if (this.directives)
255
+ this.directives.yaml.version = '1.1';
256
+ else
257
+ this.directives = new Directives({ version: '1.1' });
258
+ opt = { merge: true, resolveKnownTags: false, schema: 'yaml-1.1' };
241
259
  break;
242
260
  case '1.2':
243
- this.directives.yaml.version = '1.2';
244
- _options = Object.assign({ merge: false, resolveKnownTags: true, schema: 'core' }, options);
261
+ case 'next':
262
+ if (this.directives)
263
+ this.directives.yaml.version = version;
264
+ else
265
+ this.directives = new Directives({ version });
266
+ opt = { merge: false, resolveKnownTags: true, schema: 'core' };
267
+ break;
268
+ case null:
269
+ if (this.directives)
270
+ delete this.directives;
271
+ opt = null;
245
272
  break;
246
273
  default: {
247
274
  const sv = JSON.stringify(version);
248
- throw new Error(`Expected '1.1' or '1.2' as version, but found: ${sv}`);
275
+ throw new Error(`Expected '1.1', '1.2' or null as first argument, but found: ${sv}`);
249
276
  }
250
277
  }
251
- this.schema = new Schema(_options);
278
+ // Not using `instanceof Schema` to allow for duck typing
279
+ if (options.schema instanceof Object)
280
+ this.schema = options.schema;
281
+ else if (opt)
282
+ this.schema = new Schema(Object.assign(opt, options));
283
+ else
284
+ throw new Error(`With a null YAML version, the { schema: Schema } option is required`);
252
285
  }
253
286
  // json & jsonArg are only used from toJSON()
254
287
  toJS({ json, jsonArg, mapAsMap, maxAliasCount, onAnchor, reviver } = {}) {
@@ -261,7 +294,7 @@ class Document {
261
294
  maxAliasCount: typeof maxAliasCount === 'number' ? maxAliasCount : 100,
262
295
  stringify
263
296
  };
264
- const res = toJS(this.contents, jsonArg || '', ctx);
297
+ const res = toJS(this.contents, jsonArg !== null && jsonArg !== void 0 ? jsonArg : '', ctx);
265
298
  if (typeof onAnchor === 'function')
266
299
  for (const { count, res } of ctx.anchors.values())
267
300
  onAnchor(res, count);
@@ -37,7 +37,7 @@ function createNodeAnchors(doc, prefix) {
37
37
  const sourceObjects = new Map();
38
38
  let prevAnchors = null;
39
39
  return {
40
- onAnchor(source) {
40
+ onAnchor: (source) => {
41
41
  aliasObjects.push(source);
42
42
  if (!prevAnchors)
43
43
  prevAnchors = anchorNames(doc);
@@ -50,7 +50,7 @@ function createNodeAnchors(doc, prefix) {
50
50
  * of its child nodes are. This is why anchors are set only after all of
51
51
  * the nodes have been created.
52
52
  */
53
- setAnchors() {
53
+ setAnchors: () => {
54
54
  for (const source of aliasObjects) {
55
55
  const ref = sourceObjects.get(source);
56
56
  if (typeof ref === 'object' &&
@@ -4,14 +4,15 @@ import { Scalar } from '../nodes/Scalar.js';
4
4
 
5
5
  const defaultTagPrefix = 'tag:yaml.org,2002:';
6
6
  function findTagObject(value, tagName, tags) {
7
+ var _a;
7
8
  if (tagName) {
8
9
  const match = tags.filter(t => t.tag === tagName);
9
- const tagObj = match.find(t => !t.format) || match[0];
10
+ const tagObj = (_a = match.find(t => !t.format)) !== null && _a !== void 0 ? _a : match[0];
10
11
  if (!tagObj)
11
12
  throw new Error(`Tag ${tagName} not found`);
12
13
  return tagObj;
13
14
  }
14
- return tags.find(t => t.identify && t.identify(value) && !t.format);
15
+ return tags.find(t => { var _a; return ((_a = t.identify) === null || _a === void 0 ? void 0 : _a.call(t, value)) && !t.format; });
15
16
  }
16
17
  function createNode(value, tagName, ctx) {
17
18
  var _a, _b;
@@ -48,12 +49,14 @@ function createNode(value, tagName, ctx) {
48
49
  sourceObjects.set(value, ref);
49
50
  }
50
51
  }
51
- if (tagName && tagName.startsWith('!!'))
52
+ if (tagName === null || tagName === void 0 ? void 0 : tagName.startsWith('!!'))
52
53
  tagName = defaultTagPrefix + tagName.slice(2);
53
54
  let tagObj = findTagObject(value, tagName, schema.tags);
54
55
  if (!tagObj) {
55
- if (value && typeof value.toJSON === 'function')
56
+ if (value && typeof value.toJSON === 'function') {
57
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
56
58
  value = value.toJSON();
59
+ }
57
60
  if (!value || typeof value !== 'object') {
58
61
  const node = new Scalar(value);
59
62
  if (ref)