yaml 2.0.0-4 → 2.0.0-8

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 (220) hide show
  1. package/README.md +5 -5
  2. package/browser/dist/compose/compose-collection.js +12 -9
  3. package/browser/dist/compose/compose-doc.js +23 -6
  4. package/browser/dist/compose/compose-node.js +27 -17
  5. package/browser/dist/compose/compose-scalar.js +21 -23
  6. package/browser/dist/compose/composer.js +108 -78
  7. package/browser/dist/compose/resolve-block-map.js +41 -29
  8. package/browser/dist/compose/resolve-block-scalar.js +14 -17
  9. package/browser/dist/compose/resolve-block-seq.js +21 -17
  10. package/browser/dist/compose/resolve-end.js +7 -8
  11. package/browser/dist/compose/resolve-flow-collection.js +158 -199
  12. package/browser/dist/compose/resolve-flow-scalar.js +62 -26
  13. package/browser/dist/compose/resolve-props.js +72 -37
  14. package/browser/dist/compose/util-contains-newline.js +15 -12
  15. package/browser/dist/compose/util-map-includes.js +17 -0
  16. package/browser/dist/doc/Document.js +74 -99
  17. package/browser/dist/doc/anchors.js +72 -0
  18. package/browser/dist/doc/createNode.js +35 -19
  19. package/browser/dist/doc/directives.js +5 -0
  20. package/browser/dist/errors.js +16 -12
  21. package/browser/dist/index.js +3 -3
  22. package/browser/dist/nodes/Alias.js +51 -28
  23. package/browser/dist/nodes/Collection.js +23 -92
  24. package/browser/dist/nodes/Node.js +9 -1
  25. package/browser/dist/nodes/Pair.js +16 -231
  26. package/browser/dist/nodes/YAMLMap.js +8 -4
  27. package/browser/dist/nodes/YAMLSeq.js +7 -4
  28. package/browser/dist/nodes/addPairToJSMap.js +103 -0
  29. package/browser/dist/nodes/toJS.js +12 -10
  30. package/browser/dist/options.js +1 -2
  31. package/browser/dist/parse/cst-scalar.js +219 -0
  32. package/browser/dist/parse/cst-stringify.js +61 -0
  33. package/browser/dist/parse/cst-visit.js +97 -0
  34. package/{dist/parse/tokens.js → browser/dist/parse/cst.js} +12 -7
  35. package/browser/dist/parse/lexer.js +149 -125
  36. package/browser/dist/parse/parser.js +272 -196
  37. package/browser/dist/public-api.js +11 -14
  38. package/browser/dist/schema/Schema.js +28 -0
  39. package/browser/dist/{tags/failsafe → schema/common}/map.js +0 -0
  40. package/browser/dist/schema/common/null.js +13 -0
  41. package/browser/dist/{tags/failsafe → schema/common}/seq.js +1 -1
  42. package/browser/dist/{tags/failsafe → schema/common}/string.js +0 -0
  43. package/browser/dist/schema/core/bool.js +19 -0
  44. package/browser/dist/schema/core/float.js +40 -0
  45. package/browser/dist/schema/core/int.js +38 -0
  46. package/browser/dist/schema/core/schema.js +23 -0
  47. package/browser/dist/{tags/json.js → schema/json/schema.js} +5 -6
  48. package/browser/dist/schema/tags.js +79 -0
  49. package/browser/dist/{tags → schema}/yaml-1.1/binary.js +0 -0
  50. package/browser/dist/schema/yaml-1.1/bool.js +26 -0
  51. package/browser/dist/schema/yaml-1.1/float.js +43 -0
  52. package/browser/dist/schema/yaml-1.1/int.js +71 -0
  53. package/browser/dist/{tags → schema}/yaml-1.1/omap.js +0 -0
  54. package/browser/dist/{tags → schema}/yaml-1.1/pairs.js +9 -6
  55. package/browser/dist/schema/yaml-1.1/schema.js +37 -0
  56. package/browser/dist/{tags → schema}/yaml-1.1/set.js +0 -0
  57. package/browser/dist/{tags → schema}/yaml-1.1/timestamp.js +0 -0
  58. package/browser/dist/stringify/stringify.js +8 -6
  59. package/browser/dist/stringify/stringifyCollection.js +122 -0
  60. package/browser/dist/stringify/stringifyComment.js +14 -0
  61. package/browser/dist/stringify/stringifyDocument.js +64 -0
  62. package/browser/dist/stringify/stringifyPair.js +111 -0
  63. package/browser/dist/stringify/stringifyString.js +53 -52
  64. package/browser/dist/visit.js +20 -1
  65. package/dist/compose/compose-collection.d.ts +4 -4
  66. package/dist/compose/compose-collection.js +12 -9
  67. package/dist/compose/compose-doc.d.ts +4 -3
  68. package/dist/compose/compose-doc.js +23 -6
  69. package/dist/compose/compose-node.d.ts +15 -7
  70. package/dist/compose/compose-node.js +27 -17
  71. package/dist/compose/compose-scalar.d.ts +4 -3
  72. package/dist/compose/compose-scalar.js +20 -22
  73. package/dist/compose/composer.d.ts +28 -23
  74. package/dist/compose/composer.js +109 -79
  75. package/dist/compose/resolve-block-map.d.ts +5 -4
  76. package/dist/compose/resolve-block-map.js +41 -29
  77. package/dist/compose/resolve-block-scalar.d.ts +5 -3
  78. package/dist/compose/resolve-block-scalar.js +14 -17
  79. package/dist/compose/resolve-block-seq.d.ts +4 -4
  80. package/dist/compose/resolve-block-seq.js +21 -17
  81. package/dist/compose/resolve-end.d.ts +3 -2
  82. package/dist/compose/resolve-end.js +7 -8
  83. package/dist/compose/resolve-flow-collection.d.ts +4 -5
  84. package/dist/compose/resolve-flow-collection.js +157 -198
  85. package/dist/compose/resolve-flow-scalar.d.ts +5 -3
  86. package/dist/compose/resolve-flow-scalar.js +62 -26
  87. package/dist/compose/resolve-props.d.ts +16 -10
  88. package/dist/compose/resolve-props.js +72 -37
  89. package/dist/compose/util-contains-newline.d.ts +1 -1
  90. package/dist/compose/util-contains-newline.js +15 -12
  91. package/dist/compose/util-empty-scalar-position.d.ts +1 -1
  92. package/dist/compose/util-map-includes.d.ts +4 -0
  93. package/dist/compose/util-map-includes.js +19 -0
  94. package/dist/doc/Document.d.ts +35 -15
  95. package/dist/doc/Document.js +72 -97
  96. package/dist/doc/anchors.d.ts +24 -0
  97. package/dist/doc/anchors.js +77 -0
  98. package/dist/doc/createNode.d.ts +10 -11
  99. package/dist/doc/createNode.js +34 -18
  100. package/dist/doc/directives.d.ts +1 -0
  101. package/dist/doc/directives.js +5 -0
  102. package/dist/errors.d.ts +11 -8
  103. package/dist/errors.js +16 -12
  104. package/dist/index.d.ts +5 -3
  105. package/dist/index.js +3 -3
  106. package/dist/nodes/Alias.d.ts +19 -9
  107. package/dist/nodes/Alias.js +51 -28
  108. package/dist/nodes/Collection.d.ts +9 -17
  109. package/dist/nodes/Collection.js +22 -91
  110. package/dist/nodes/Node.d.ts +10 -4
  111. package/dist/nodes/Node.js +9 -0
  112. package/dist/nodes/Pair.d.ts +10 -13
  113. package/dist/nodes/Pair.js +15 -230
  114. package/dist/nodes/Scalar.d.ts +6 -3
  115. package/dist/nodes/YAMLMap.d.ts +3 -3
  116. package/dist/nodes/YAMLMap.js +8 -4
  117. package/dist/nodes/YAMLSeq.d.ts +3 -3
  118. package/dist/nodes/YAMLSeq.js +7 -4
  119. package/dist/nodes/addPairToJSMap.d.ts +3 -0
  120. package/dist/nodes/addPairToJSMap.js +105 -0
  121. package/dist/nodes/toJS.d.ts +4 -5
  122. package/dist/nodes/toJS.js +12 -10
  123. package/dist/options.d.ts +41 -25
  124. package/dist/options.js +1 -2
  125. package/dist/parse/cst-scalar.d.ts +58 -0
  126. package/dist/parse/cst-scalar.js +223 -0
  127. package/dist/parse/cst-stringify.d.ts +8 -0
  128. package/dist/parse/cst-stringify.js +63 -0
  129. package/dist/parse/cst-visit.d.ts +39 -0
  130. package/dist/parse/cst-visit.js +99 -0
  131. package/dist/parse/{tokens.d.ts → cst.d.ts} +23 -7
  132. package/{browser/dist/parse/tokens.js → dist/parse/cst.js} +27 -1
  133. package/dist/parse/lexer.d.ts +7 -14
  134. package/dist/parse/lexer.js +150 -126
  135. package/dist/parse/parser.d.ts +31 -24
  136. package/dist/parse/parser.js +274 -198
  137. package/dist/public-api.d.ts +7 -7
  138. package/dist/public-api.js +11 -14
  139. package/dist/{doc → schema}/Schema.d.ts +6 -3
  140. package/dist/schema/Schema.js +30 -0
  141. package/dist/{tags/failsafe → schema/common}/map.d.ts +0 -0
  142. package/dist/{tags/failsafe → schema/common}/map.js +0 -0
  143. package/dist/schema/common/null.d.ts +4 -0
  144. package/dist/schema/common/null.js +15 -0
  145. package/dist/{tags/failsafe → schema/common}/seq.d.ts +0 -0
  146. package/dist/{tags/failsafe → schema/common}/seq.js +1 -1
  147. package/dist/{tags/failsafe → schema/common}/string.d.ts +0 -0
  148. package/dist/{tags/failsafe → schema/common}/string.js +0 -0
  149. package/dist/schema/core/bool.d.ts +4 -0
  150. package/dist/schema/core/bool.js +21 -0
  151. package/dist/schema/core/float.d.ts +4 -0
  152. package/dist/schema/core/float.js +44 -0
  153. package/dist/schema/core/int.d.ts +4 -0
  154. package/dist/schema/core/int.js +42 -0
  155. package/dist/schema/core/schema.d.ts +1 -0
  156. package/dist/schema/core/schema.js +25 -0
  157. package/dist/schema/json/schema.d.ts +2 -0
  158. package/dist/{tags/json.js → schema/json/schema.js} +5 -6
  159. package/dist/schema/tags.d.ts +41 -0
  160. package/dist/schema/tags.js +82 -0
  161. package/dist/{tags → schema}/types.d.ts +3 -7
  162. package/dist/{tags → schema}/yaml-1.1/binary.d.ts +0 -0
  163. package/dist/{tags → schema}/yaml-1.1/binary.js +0 -0
  164. package/dist/schema/yaml-1.1/bool.d.ts +7 -0
  165. package/dist/schema/yaml-1.1/bool.js +29 -0
  166. package/dist/schema/yaml-1.1/float.d.ts +4 -0
  167. package/dist/schema/yaml-1.1/float.js +47 -0
  168. package/dist/schema/yaml-1.1/int.d.ts +5 -0
  169. package/dist/schema/yaml-1.1/int.js +76 -0
  170. package/dist/{tags → schema}/yaml-1.1/omap.d.ts +0 -0
  171. package/dist/{tags → schema}/yaml-1.1/omap.js +0 -0
  172. package/dist/{tags → schema}/yaml-1.1/pairs.d.ts +3 -2
  173. package/dist/{tags → schema}/yaml-1.1/pairs.js +9 -6
  174. package/dist/schema/yaml-1.1/schema.d.ts +1 -0
  175. package/dist/schema/yaml-1.1/schema.js +39 -0
  176. package/dist/{tags → schema}/yaml-1.1/set.d.ts +1 -1
  177. package/dist/{tags → schema}/yaml-1.1/set.js +0 -0
  178. package/dist/{tags → schema}/yaml-1.1/timestamp.d.ts +0 -0
  179. package/dist/{tags → schema}/yaml-1.1/timestamp.js +0 -0
  180. package/dist/stringify/stringify.d.ts +1 -2
  181. package/dist/stringify/stringify.js +8 -6
  182. package/dist/stringify/stringifyCollection.d.ts +21 -0
  183. package/dist/stringify/stringifyCollection.js +124 -0
  184. package/dist/stringify/stringifyComment.d.ts +2 -0
  185. package/dist/stringify/stringifyComment.js +17 -0
  186. package/dist/stringify/stringifyDocument.d.ts +3 -0
  187. package/dist/stringify/stringifyDocument.js +66 -0
  188. package/dist/stringify/stringifyPair.d.ts +3 -0
  189. package/dist/stringify/stringifyPair.js +113 -0
  190. package/dist/stringify/stringifyString.js +53 -52
  191. package/dist/test-events.d.ts +1 -2
  192. package/dist/test-events.js +25 -12
  193. package/dist/util.d.ts +1 -1
  194. package/dist/visit.d.ts +10 -1
  195. package/dist/visit.js +20 -1
  196. package/package.json +9 -8
  197. package/browser/dist/doc/Anchors.js +0 -102
  198. package/browser/dist/doc/Schema.js +0 -27
  199. package/browser/dist/doc/getSchemaTags.js +0 -30
  200. package/browser/dist/stringify/addComment.js +0 -17
  201. package/browser/dist/tags/core.js +0 -109
  202. package/browser/dist/tags/failsafe/index.js +0 -7
  203. package/browser/dist/tags/index.js +0 -34
  204. package/browser/dist/tags/yaml-1.1/index.js +0 -152
  205. package/dist/doc/Anchors.d.ts +0 -36
  206. package/dist/doc/Anchors.js +0 -104
  207. package/dist/doc/Schema.js +0 -29
  208. package/dist/doc/getSchemaTags.d.ts +0 -3
  209. package/dist/doc/getSchemaTags.js +0 -32
  210. package/dist/stringify/addComment.d.ts +0 -2
  211. package/dist/stringify/addComment.js +0 -20
  212. package/dist/tags/core.d.ts +0 -14
  213. package/dist/tags/core.js +0 -119
  214. package/dist/tags/failsafe/index.d.ts +0 -1
  215. package/dist/tags/failsafe/index.js +0 -9
  216. package/dist/tags/index.d.ts +0 -31
  217. package/dist/tags/index.js +0 -37
  218. package/dist/tags/json.d.ts +0 -2
  219. package/dist/tags/yaml-1.1/index.d.ts +0 -2
  220. package/dist/tags/yaml-1.1/index.js +0 -154
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 yaml@next
22
+ npm install --save-exact yaml@next
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.
@@ -67,16 +67,16 @@ const YAML = require('yaml')
67
67
  - [`new Scalar(value)`](https://eemeli.org/yaml/#scalar-values)
68
68
  - [`new YAMLMap()`](https://eemeli.org/yaml/#collections)
69
69
  - [`new YAMLSeq()`](https://eemeli.org/yaml/#collections)
70
- - [`doc.anchors.createAlias(node, name?): Alias`](https://eemeli.org/yaml/#working-with-anchors)
70
+ - [`doc.createAlias(node, name?): Alias`](https://eemeli.org/yaml/#working-with-anchors)
71
71
  - [`doc.createNode(value, options?): Node`](https://eemeli.org/yaml/#creating-nodes)
72
72
  - [`doc.createPair(key, value): Pair`](https://eemeli.org/yaml/#creating-nodes)
73
73
  - [`visit(node, visitor)`](https://eemeli.org/yaml/#modifying-nodes)
74
74
 
75
75
  ### Parsing YAML
76
76
 
77
- - [`new Lexer(push)`](https://eemeli.org/yaml/#lexer)
78
- - [`new Parser(push, onNewLine?)`](https://eemeli.org/yaml/#parser)
79
- - [`new Composer(push, options?)`](https://eemeli.org/yaml/#composer)
77
+ - [`new Lexer().lex(src)`](https://eemeli.org/yaml/#lexer)
78
+ - [`new Parser(onNewLine?).parse(src)`](https://eemeli.org/yaml/#parser)
79
+ - [`new Composer(options?).compose(tokens)`](https://eemeli.org/yaml/#composer)
80
80
 
81
81
  ## YAML.parse
82
82
 
@@ -4,22 +4,25 @@ import { resolveBlockMap } from './resolve-block-map.js';
4
4
  import { resolveBlockSeq } from './resolve-block-seq.js';
5
5
  import { resolveFlowCollection } from './resolve-flow-collection.js';
6
6
 
7
- function composeCollection(CN, doc, token, anchor, tagName, onError) {
7
+ function composeCollection(CN, ctx, token, tagToken, onError) {
8
8
  let coll;
9
9
  switch (token.type) {
10
10
  case 'block-map': {
11
- coll = resolveBlockMap(CN, doc, token, anchor, onError);
11
+ coll = resolveBlockMap(CN, ctx, token, onError);
12
12
  break;
13
13
  }
14
14
  case 'block-seq': {
15
- coll = resolveBlockSeq(CN, doc, token, anchor, onError);
15
+ coll = resolveBlockSeq(CN, ctx, token, onError);
16
16
  break;
17
17
  }
18
18
  case 'flow-collection': {
19
- coll = resolveFlowCollection(CN, doc, token, anchor, onError);
19
+ coll = resolveFlowCollection(CN, ctx, token, onError);
20
20
  break;
21
21
  }
22
22
  }
23
+ if (!tagToken)
24
+ return coll;
25
+ const tagName = ctx.directives.tagName(tagToken.source, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg));
23
26
  if (!tagName)
24
27
  return coll;
25
28
  // Cast needed due to: https://github.com/Microsoft/TypeScript/issues/3841
@@ -29,20 +32,20 @@ function composeCollection(CN, doc, token, anchor, tagName, onError) {
29
32
  return coll;
30
33
  }
31
34
  const expType = isMap(coll) ? 'map' : 'seq';
32
- let tag = doc.schema.tags.find(t => t.collection === expType && t.tag === tagName);
35
+ let tag = ctx.schema.tags.find(t => t.collection === expType && t.tag === tagName);
33
36
  if (!tag) {
34
- const kt = doc.schema.knownTags[tagName];
37
+ const kt = ctx.schema.knownTags[tagName];
35
38
  if (kt && kt.collection === expType) {
36
- doc.schema.tags.push(Object.assign({}, kt, { default: false }));
39
+ ctx.schema.tags.push(Object.assign({}, kt, { default: false }));
37
40
  tag = kt;
38
41
  }
39
42
  else {
40
- onError(coll.range[0], `Unresolved tag: ${tagName}`, true);
43
+ onError(tagToken, 'TAG_RESOLVE_FAILED', `Unresolved tag: ${tagName}`, true);
41
44
  coll.tag = tagName;
42
45
  return coll;
43
46
  }
44
47
  }
45
- const res = tag.resolve(coll, msg => onError(coll.range[0], msg), doc.options);
48
+ const res = tag.resolve(coll, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg), ctx.options);
46
49
  const node = isNode(res)
47
50
  ? res
48
51
  : new Scalar(res);
@@ -6,16 +6,33 @@ import { resolveProps } from './resolve-props.js';
6
6
  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
- const props = resolveProps(doc, start, true, 'doc-start', offset, onError);
10
- if (props.found)
9
+ const ctx = {
10
+ directives: doc.directives,
11
+ options: doc.options,
12
+ schema: doc.schema
13
+ };
14
+ const props = resolveProps(start, {
15
+ indicator: 'doc-start',
16
+ next: value || (end === null || end === void 0 ? void 0 : end[0]),
17
+ offset,
18
+ onError,
19
+ startOnNewline: true
20
+ });
21
+ if (props.found) {
11
22
  doc.directives.marker = true;
23
+ if (value &&
24
+ (value.type === 'block-map' || value.type === 'block-seq') &&
25
+ !props.hasNewline)
26
+ onError(props.end, 'MISSING_CHAR', 'Block collection cannot start on same line with directives-end marker');
27
+ }
12
28
  doc.contents = value
13
- ? composeNode(doc, value, props, onError)
14
- : composeEmptyNode(doc, offset + props.length, start, null, props, onError);
15
- const re = resolveEnd(end, doc.contents.range[1], false, onError);
29
+ ? composeNode(ctx, value, props, onError)
30
+ : composeEmptyNode(ctx, props.end, start, null, props, onError);
31
+ const contentEnd = doc.contents.range[2];
32
+ const re = resolveEnd(end, contentEnd, false, onError);
16
33
  if (re.comment)
17
34
  doc.comment = re.comment;
18
- doc.range = [offset, re.offset];
35
+ doc.range = [offset, contentEnd, re.offset];
19
36
  return doc;
20
37
  }
21
38
 
@@ -5,30 +5,36 @@ import { resolveEnd } from './resolve-end.js';
5
5
  import { emptyScalarPosition } from './util-empty-scalar-position.js';
6
6
 
7
7
  const CN = { composeNode, composeEmptyNode };
8
- function composeNode(doc, token, props, onError) {
9
- const { spaceBefore, comment, anchor, tagName } = props;
8
+ function composeNode(ctx, token, props, onError) {
9
+ const { spaceBefore, comment, anchor, tag } = props;
10
10
  let node;
11
11
  switch (token.type) {
12
12
  case 'alias':
13
- node = composeAlias(doc, token, onError);
14
- if (anchor || tagName)
15
- onError(token.offset, 'An alias node must not specify any properties');
13
+ node = composeAlias(ctx, token, onError);
14
+ if (anchor || tag)
15
+ onError(token, 'ALIAS_PROPS', 'An alias node must not specify any properties');
16
16
  break;
17
17
  case 'scalar':
18
18
  case 'single-quoted-scalar':
19
19
  case 'double-quoted-scalar':
20
20
  case 'block-scalar':
21
- node = composeScalar(doc, token, anchor, tagName, onError);
21
+ node = composeScalar(ctx, token, tag, onError);
22
+ if (anchor)
23
+ node.anchor = anchor.source.substring(1);
22
24
  break;
23
25
  case 'block-map':
24
26
  case 'block-seq':
25
27
  case 'flow-collection':
26
- node = composeCollection(CN, doc, token, anchor, tagName, onError);
28
+ node = composeCollection(CN, ctx, token, tag, onError);
29
+ if (anchor)
30
+ node.anchor = anchor.source.substring(1);
27
31
  break;
28
32
  default:
29
33
  console.log(token);
30
34
  throw new Error(`Unsupporten token type: ${token.type}`);
31
35
  }
36
+ if (anchor && node.anchor === '')
37
+ onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
32
38
  if (spaceBefore)
33
39
  node.spaceBefore = true;
34
40
  if (comment) {
@@ -39,28 +45,32 @@ function composeNode(doc, token, props, onError) {
39
45
  }
40
46
  return node;
41
47
  }
42
- function composeEmptyNode(doc, offset, before, pos, { spaceBefore, comment, anchor, tagName }, onError) {
48
+ function composeEmptyNode(ctx, offset, before, pos, { spaceBefore, comment, anchor, tag }, onError) {
43
49
  const token = {
44
50
  type: 'scalar',
45
51
  offset: emptyScalarPosition(offset, before, pos),
46
52
  indent: -1,
47
53
  source: ''
48
54
  };
49
- const node = composeScalar(doc, token, anchor, tagName, onError);
55
+ const node = composeScalar(ctx, token, tag, onError);
56
+ if (anchor) {
57
+ node.anchor = anchor.source.substring(1);
58
+ if (node.anchor === '')
59
+ onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
60
+ }
50
61
  if (spaceBefore)
51
62
  node.spaceBefore = true;
52
63
  if (comment)
53
64
  node.comment = comment;
54
65
  return node;
55
66
  }
56
- function composeAlias(doc, { offset, source, end }, onError) {
57
- const name = source.substring(1);
58
- const src = doc.anchors.getNode(name);
59
- if (!src)
60
- onError(offset, `Aliased anchor not found: ${name}`);
61
- const alias = new Alias(src);
62
- const re = resolveEnd(end, offset + source.length, doc.options.strict, onError);
63
- alias.range = [offset, re.offset];
67
+ function composeAlias({ options }, { offset, source, end }, onError) {
68
+ const alias = new Alias(source.substring(1));
69
+ if (alias.source === '')
70
+ onError(offset, 'BAD_ALIAS', 'Alias cannot be an empty string');
71
+ const valueEnd = offset + source.length;
72
+ const re = resolveEnd(end, valueEnd, options.strict, onError);
73
+ alias.range = [offset, valueEnd, re.offset];
64
74
  if (re.comment)
65
75
  alias.comment = re.comment;
66
76
  return alias;
@@ -1,46 +1,44 @@
1
- import { isScalar } from '../nodes/Node.js';
1
+ import { isScalar, SCALAR } 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';
5
5
 
6
- function composeScalar(doc, token, anchor, tagName, onError) {
7
- const { offset } = token;
8
- const { value, type, comment, length } = token.type === 'block-scalar'
9
- ? resolveBlockScalar(token, doc.options.strict, onError)
10
- : resolveFlowScalar(token, doc.options.strict, onError);
11
- const tag = tagName
12
- ? findScalarTagByName(doc.schema, value, tagName, onError)
13
- : findScalarTagByTest(doc.schema, value, token.type === 'scalar');
6
+ function composeScalar(ctx, token, tagToken, onError) {
7
+ const { value, type, comment, range } = token.type === 'block-scalar'
8
+ ? resolveBlockScalar(token, ctx.options.strict, onError)
9
+ : resolveFlowScalar(token, ctx.options.strict, onError);
10
+ const tagName = tagToken
11
+ ? ctx.directives.tagName(tagToken.source, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg))
12
+ : null;
13
+ const tag = tagToken && tagName
14
+ ? findScalarTagByName(ctx.schema, value, tagName, tagToken, onError)
15
+ : findScalarTagByTest(ctx.schema, value, token.type === 'scalar');
14
16
  let scalar;
15
17
  try {
16
- const res = tag
17
- ? tag.resolve(value, msg => onError(offset, msg), doc.options)
18
- : value;
18
+ const res = tag.resolve(value, msg => onError(tagToken || token, 'TAG_RESOLVE_FAILED', msg), ctx.options);
19
19
  scalar = isScalar(res) ? res : new Scalar(res);
20
20
  }
21
21
  catch (error) {
22
- onError(offset, error.message);
22
+ const msg = error instanceof Error ? error.message : String(error);
23
+ onError(tagToken || token, 'TAG_RESOLVE_FAILED', msg);
23
24
  scalar = new Scalar(value);
24
25
  }
25
- scalar.range = [offset, offset + length];
26
+ scalar.range = range;
26
27
  scalar.source = value;
27
28
  if (type)
28
29
  scalar.type = type;
29
30
  if (tagName)
30
31
  scalar.tag = tagName;
31
- if (tag === null || tag === void 0 ? void 0 : tag.format)
32
+ if (tag.format)
32
33
  scalar.format = tag.format;
33
34
  if (comment)
34
35
  scalar.comment = comment;
35
- if (anchor)
36
- doc.anchors.setAnchor(scalar, anchor);
37
36
  return scalar;
38
37
  }
39
- const defaultScalarTag = (schema) => schema.tags.find(tag => !tag.collection && tag.tag === 'tag:yaml.org,2002:str');
40
- function findScalarTagByName(schema, value, tagName, onError) {
38
+ function findScalarTagByName(schema, value, tagName, tagToken, onError) {
41
39
  var _a;
42
40
  if (tagName === '!')
43
- return defaultScalarTag(schema); // non-specific tag
41
+ return schema[SCALAR]; // non-specific tag
44
42
  const matchWithTest = [];
45
43
  for (const tag of schema.tags) {
46
44
  if (!tag.collection && tag.tag === tagName) {
@@ -60,8 +58,8 @@ function findScalarTagByName(schema, value, tagName, onError) {
60
58
  schema.tags.push(Object.assign({}, kt, { default: false, test: undefined }));
61
59
  return kt;
62
60
  }
63
- onError(0, `Unresolved tag: ${tagName}`, tagName !== 'tag:yaml.org,2002:str');
64
- return defaultScalarTag(schema);
61
+ onError(tagToken, 'TAG_RESOLVE_FAILED', `Unresolved tag: ${tagName}`, tagName !== 'tag:yaml.org,2002:str');
62
+ return schema[SCALAR];
65
63
  }
66
64
  function findScalarTagByTest(schema, value, apply) {
67
65
  var _a;
@@ -71,7 +69,7 @@ function findScalarTagByTest(schema, value, apply) {
71
69
  return tag;
72
70
  }
73
71
  }
74
- return defaultScalarTag(schema);
72
+ return schema[SCALAR];
75
73
  }
76
74
 
77
75
  export { composeScalar };
@@ -1,12 +1,21 @@
1
1
  import { Directives } from '../doc/directives.js';
2
2
  import { Document } from '../doc/Document.js';
3
3
  import { YAMLWarning, YAMLParseError } from '../errors.js';
4
- import { isCollection } from '../nodes/Node.js';
4
+ import { isCollection, isPair } from '../nodes/Node.js';
5
5
  import { defaultOptions } from '../options.js';
6
6
  import { composeDoc } from './compose-doc.js';
7
7
  import { resolveEnd } from './resolve-end.js';
8
8
 
9
+ function getErrorPos(src) {
10
+ if (typeof src === 'number')
11
+ return [src, src + 1];
12
+ if (Array.isArray(src))
13
+ return src.length === 2 ? src : [src[0], src[1]];
14
+ const { offset, source } = src;
15
+ return [offset, offset + (typeof source === 'string' ? source.length : 1)];
16
+ }
9
17
  function parsePrelude(prelude) {
18
+ var _a;
10
19
  let comment = '';
11
20
  let atComment = false;
12
21
  let afterEmptyLine = false;
@@ -16,12 +25,12 @@ function parsePrelude(prelude) {
16
25
  case '#':
17
26
  comment +=
18
27
  (comment === '' ? '' : afterEmptyLine ? '\n\n' : '\n') +
19
- source.substring(1);
28
+ (source.substring(1) || ' ');
20
29
  atComment = true;
21
30
  afterEmptyLine = false;
22
31
  break;
23
32
  case '%':
24
- if (prelude[i + 1][0] !== '#')
33
+ if (((_a = prelude[i + 1]) === null || _a === void 0 ? void 0 : _a[0]) !== '#')
25
34
  i += 1;
26
35
  atComment = false;
27
36
  break;
@@ -38,88 +47,30 @@ function parsePrelude(prelude) {
38
47
  * Compose a stream of CST nodes into a stream of YAML Documents.
39
48
  *
40
49
  * ```ts
41
- * const options: Options = { ... }
42
- * const docs: Document.Parsed[] = []
43
- * const composer = new Composer(doc => docs.push(doc), options)
44
- * const parser = new Parser(composer.next)
45
- * parser.parse(source)
46
- * composer.end()
50
+ * import { Composer, Parser } from 'yaml'
51
+ *
52
+ * const src: string = ...
53
+ * const tokens = new Parser().parse(src)
54
+ * const docs = new Composer().compose(tokens)
47
55
  * ```
48
56
  */
49
57
  class Composer {
50
- constructor(onDocument, options = {}) {
58
+ constructor(options = {}) {
51
59
  this.doc = null;
52
60
  this.atDirectives = false;
53
61
  this.prelude = [];
54
62
  this.errors = [];
55
63
  this.warnings = [];
56
- this.onError = (offset, message, warning) => {
64
+ this.onError = (source, code, message, warning) => {
65
+ const pos = getErrorPos(source);
57
66
  if (warning)
58
- this.warnings.push(new YAMLWarning(offset, message));
67
+ this.warnings.push(new YAMLWarning(pos, code, message));
59
68
  else
60
- this.errors.push(new YAMLParseError(offset, message));
61
- };
62
- /**
63
- * Advance the composed by one CST token. Bound to the Composer
64
- * instance, so may be used directly as a callback function.
65
- */
66
- this.next = (token) => {
67
- switch (token.type) {
68
- case 'directive':
69
- this.directives.add(token.source, this.onError);
70
- this.prelude.push(token.source);
71
- this.atDirectives = true;
72
- break;
73
- case 'document': {
74
- const doc = composeDoc(this.options, this.directives, token, this.onError);
75
- this.decorate(doc, false);
76
- if (this.doc)
77
- this.onDocument(this.doc);
78
- this.doc = doc;
79
- this.atDirectives = false;
80
- break;
81
- }
82
- case 'byte-order-mark':
83
- case 'space':
84
- break;
85
- case 'comment':
86
- case 'newline':
87
- this.prelude.push(token.source);
88
- break;
89
- case 'error': {
90
- const msg = token.source
91
- ? `${token.message}: ${JSON.stringify(token.source)}`
92
- : token.message;
93
- const error = new YAMLParseError(-1, msg);
94
- if (this.atDirectives || !this.doc)
95
- this.errors.push(error);
96
- else
97
- this.doc.errors.push(error);
98
- break;
99
- }
100
- case 'doc-end': {
101
- if (!this.doc) {
102
- const msg = 'Unexpected doc-end without preceding document';
103
- this.errors.push(new YAMLParseError(token.offset, msg));
104
- break;
105
- }
106
- const end = resolveEnd(token.end, token.offset + token.source.length, this.doc.options.strict, this.onError);
107
- this.decorate(this.doc, true);
108
- if (end.comment) {
109
- const dc = this.doc.comment;
110
- this.doc.comment = dc ? `${dc}\n${end.comment}` : end.comment;
111
- }
112
- this.doc.range[1] = end.offset;
113
- break;
114
- }
115
- default:
116
- this.errors.push(new YAMLParseError(-1, `Unsupported token ${token.type}`));
117
- }
69
+ this.errors.push(new YAMLParseError(pos, code, message));
118
70
  };
119
71
  this.directives = new Directives({
120
- version: (options === null || options === void 0 ? void 0 : options.version) || defaultOptions.version
72
+ version: options.version || defaultOptions.version
121
73
  });
122
- this.onDocument = onDocument;
123
74
  this.options = options;
124
75
  }
125
76
  decorate(doc, afterDoc) {
@@ -134,7 +85,9 @@ class Composer {
134
85
  doc.commentBefore = comment;
135
86
  }
136
87
  else if (isCollection(dc) && !dc.flow && dc.items.length > 0) {
137
- const it = dc.items[0];
88
+ let it = dc.items[0];
89
+ if (isPair(it))
90
+ it = it.key;
138
91
  const cb = it.commentBefore;
139
92
  it.commentBefore = cb ? `${comment}\n${cb}` : comment;
140
93
  }
@@ -168,20 +121,97 @@ class Composer {
168
121
  warnings: this.warnings
169
122
  };
170
123
  }
171
- end(forceDoc = false, offset = -1) {
124
+ /**
125
+ * Compose tokens into documents.
126
+ *
127
+ * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document.
128
+ * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly.
129
+ */
130
+ *compose(tokens, forceDoc = false, endOffset = -1) {
131
+ for (const token of tokens)
132
+ yield* this.next(token);
133
+ yield* this.end(forceDoc, endOffset);
134
+ }
135
+ /** Advance the composer by one CST token. */
136
+ *next(token) {
137
+ switch (token.type) {
138
+ case 'directive':
139
+ this.directives.add(token.source, (offset, message, warning) => {
140
+ const pos = getErrorPos(token);
141
+ pos[0] += offset;
142
+ this.onError(pos, 'BAD_DIRECTIVE', message, warning);
143
+ });
144
+ this.prelude.push(token.source);
145
+ this.atDirectives = true;
146
+ break;
147
+ case 'document': {
148
+ 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');
151
+ this.decorate(doc, false);
152
+ if (this.doc)
153
+ yield this.doc;
154
+ this.doc = doc;
155
+ this.atDirectives = false;
156
+ break;
157
+ }
158
+ case 'byte-order-mark':
159
+ case 'space':
160
+ break;
161
+ case 'comment':
162
+ case 'newline':
163
+ this.prelude.push(token.source);
164
+ break;
165
+ case 'error': {
166
+ const msg = token.source
167
+ ? `${token.message}: ${JSON.stringify(token.source)}`
168
+ : token.message;
169
+ const error = new YAMLParseError(getErrorPos(token), 'UNEXPECTED_TOKEN', msg);
170
+ if (this.atDirectives || !this.doc)
171
+ this.errors.push(error);
172
+ else
173
+ this.doc.errors.push(error);
174
+ break;
175
+ }
176
+ case 'doc-end': {
177
+ if (!this.doc) {
178
+ const msg = 'Unexpected doc-end without preceding document';
179
+ this.errors.push(new YAMLParseError(getErrorPos(token), 'UNEXPECTED_TOKEN', msg));
180
+ break;
181
+ }
182
+ const end = resolveEnd(token.end, token.offset + token.source.length, this.doc.options.strict, this.onError);
183
+ this.decorate(this.doc, true);
184
+ if (end.comment) {
185
+ const dc = this.doc.comment;
186
+ this.doc.comment = dc ? `${dc}\n${end.comment}` : end.comment;
187
+ }
188
+ this.doc.range[2] = end.offset;
189
+ break;
190
+ }
191
+ default:
192
+ this.errors.push(new YAMLParseError(getErrorPos(token), 'UNEXPECTED_TOKEN', `Unsupported token ${token.type}`));
193
+ }
194
+ }
195
+ /**
196
+ * Call at end of input to yield any remaining document.
197
+ *
198
+ * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document.
199
+ * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly.
200
+ */
201
+ *end(forceDoc = false, endOffset = -1) {
172
202
  if (this.doc) {
173
203
  this.decorate(this.doc, true);
174
- this.onDocument(this.doc);
204
+ yield this.doc;
175
205
  this.doc = null;
176
206
  }
177
207
  else if (forceDoc) {
178
208
  const opts = Object.assign({ directives: this.directives }, this.options);
179
209
  const doc = new Document(undefined, opts);
180
210
  if (this.atDirectives)
181
- this.onError(offset, 'Missing directives-end indicator line');
182
- doc.range = [0, offset];
211
+ this.onError(endOffset, 'MISSING_CHAR', 'Missing directives-end indicator line');
212
+ doc.range = [0, endOffset, endOffset];
183
213
  this.decorate(doc, false);
184
- this.onDocument(doc);
214
+ yield doc;
185
215
  }
186
216
  }
187
217
  }