yaml 2.0.0-4 → 2.0.0-5

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 (210) 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 +20 -17
  5. package/browser/dist/compose/compose-scalar.js +20 -23
  6. package/browser/dist/compose/composer.js +105 -76
  7. package/browser/dist/compose/resolve-block-map.js +38 -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 +6 -7
  11. package/browser/dist/compose/resolve-flow-collection.js +153 -199
  12. package/browser/dist/compose/resolve-flow-scalar.js +49 -25
  13. package/browser/dist/compose/resolve-props.js +47 -35
  14. package/browser/dist/compose/util-contains-newline.js +15 -12
  15. package/browser/dist/doc/Document.js +50 -99
  16. package/browser/dist/doc/anchors.js +72 -0
  17. package/browser/dist/doc/createNode.js +27 -17
  18. package/browser/dist/errors.js +16 -12
  19. package/browser/dist/index.js +3 -3
  20. package/browser/dist/nodes/Alias.js +51 -28
  21. package/browser/dist/nodes/Collection.js +5 -83
  22. package/browser/dist/nodes/Node.js +2 -1
  23. package/browser/dist/nodes/Pair.js +9 -232
  24. package/browser/dist/nodes/YAMLMap.js +8 -4
  25. package/browser/dist/nodes/YAMLSeq.js +7 -4
  26. package/browser/dist/nodes/addPairToJSMap.js +103 -0
  27. package/browser/dist/nodes/toJS.js +12 -10
  28. package/browser/dist/options.js +0 -2
  29. package/browser/dist/parse/cst-scalar.js +219 -0
  30. package/browser/dist/parse/cst-stringify.js +61 -0
  31. package/browser/dist/parse/cst-visit.js +97 -0
  32. package/{dist/parse/tokens.js → browser/dist/parse/cst.js} +12 -7
  33. package/browser/dist/parse/lexer.js +99 -105
  34. package/browser/dist/parse/parser.js +219 -144
  35. package/browser/dist/public-api.js +11 -14
  36. package/browser/dist/schema/Schema.js +23 -0
  37. package/browser/dist/{tags/failsafe → schema/common}/map.js +0 -0
  38. package/browser/dist/schema/common/null.js +13 -0
  39. package/browser/dist/{tags/failsafe → schema/common}/seq.js +1 -1
  40. package/browser/dist/{tags/failsafe → schema/common}/string.js +0 -0
  41. package/browser/dist/schema/core/bool.js +19 -0
  42. package/browser/dist/schema/core/float.js +40 -0
  43. package/browser/dist/schema/core/int.js +38 -0
  44. package/browser/dist/schema/core/schema.js +23 -0
  45. package/browser/dist/{tags/json.js → schema/json/schema.js} +5 -6
  46. package/browser/dist/schema/tags.js +79 -0
  47. package/browser/dist/{tags → schema}/yaml-1.1/binary.js +0 -0
  48. package/browser/dist/schema/yaml-1.1/bool.js +26 -0
  49. package/browser/dist/schema/yaml-1.1/float.js +43 -0
  50. package/browser/dist/schema/yaml-1.1/int.js +71 -0
  51. package/browser/dist/{tags → schema}/yaml-1.1/omap.js +0 -0
  52. package/browser/dist/{tags → schema}/yaml-1.1/pairs.js +9 -6
  53. package/browser/dist/schema/yaml-1.1/schema.js +37 -0
  54. package/browser/dist/{tags → schema}/yaml-1.1/set.js +0 -0
  55. package/browser/dist/{tags → schema}/yaml-1.1/timestamp.js +0 -0
  56. package/browser/dist/stringify/addComment.js +1 -7
  57. package/browser/dist/stringify/stringify.js +8 -6
  58. package/browser/dist/stringify/stringifyCollection.js +108 -0
  59. package/browser/dist/stringify/stringifyDocument.js +61 -0
  60. package/browser/dist/stringify/stringifyPair.js +113 -0
  61. package/browser/dist/stringify/stringifyString.js +53 -52
  62. package/browser/dist/visit.js +20 -1
  63. package/dist/compose/compose-collection.d.ts +4 -4
  64. package/dist/compose/compose-collection.js +12 -9
  65. package/dist/compose/compose-doc.d.ts +4 -3
  66. package/dist/compose/compose-doc.js +23 -6
  67. package/dist/compose/compose-node.d.ts +15 -7
  68. package/dist/compose/compose-node.js +20 -17
  69. package/dist/compose/compose-scalar.d.ts +4 -3
  70. package/dist/compose/compose-scalar.js +19 -22
  71. package/dist/compose/composer.d.ts +28 -23
  72. package/dist/compose/composer.js +106 -77
  73. package/dist/compose/resolve-block-map.d.ts +4 -4
  74. package/dist/compose/resolve-block-map.js +38 -29
  75. package/dist/compose/resolve-block-scalar.d.ts +5 -3
  76. package/dist/compose/resolve-block-scalar.js +14 -17
  77. package/dist/compose/resolve-block-seq.d.ts +4 -4
  78. package/dist/compose/resolve-block-seq.js +21 -17
  79. package/dist/compose/resolve-end.d.ts +3 -2
  80. package/dist/compose/resolve-end.js +6 -7
  81. package/dist/compose/resolve-flow-collection.d.ts +4 -5
  82. package/dist/compose/resolve-flow-collection.js +152 -198
  83. package/dist/compose/resolve-flow-scalar.d.ts +5 -3
  84. package/dist/compose/resolve-flow-scalar.js +49 -25
  85. package/dist/compose/resolve-props.d.ts +17 -10
  86. package/dist/compose/resolve-props.js +47 -35
  87. package/dist/compose/util-contains-newline.d.ts +1 -1
  88. package/dist/compose/util-contains-newline.js +15 -12
  89. package/dist/compose/util-empty-scalar-position.d.ts +1 -1
  90. package/dist/doc/Document.d.ts +27 -15
  91. package/dist/doc/Document.js +48 -97
  92. package/dist/doc/anchors.d.ts +24 -0
  93. package/dist/doc/anchors.js +77 -0
  94. package/dist/doc/createNode.d.ts +8 -10
  95. package/dist/doc/createNode.js +26 -16
  96. package/dist/errors.d.ts +11 -8
  97. package/dist/errors.js +16 -12
  98. package/dist/index.d.ts +5 -3
  99. package/dist/index.js +3 -3
  100. package/dist/nodes/Alias.d.ts +19 -9
  101. package/dist/nodes/Alias.js +51 -28
  102. package/dist/nodes/Collection.d.ts +3 -17
  103. package/dist/nodes/Collection.js +4 -82
  104. package/dist/nodes/Node.d.ts +6 -4
  105. package/dist/nodes/Node.js +2 -0
  106. package/dist/nodes/Pair.d.ts +6 -11
  107. package/dist/nodes/Pair.js +8 -231
  108. package/dist/nodes/Scalar.d.ts +6 -3
  109. package/dist/nodes/YAMLMap.d.ts +3 -3
  110. package/dist/nodes/YAMLMap.js +8 -4
  111. package/dist/nodes/YAMLSeq.d.ts +3 -3
  112. package/dist/nodes/YAMLSeq.js +7 -4
  113. package/dist/nodes/addPairToJSMap.d.ts +3 -0
  114. package/dist/nodes/addPairToJSMap.js +105 -0
  115. package/dist/nodes/toJS.d.ts +4 -5
  116. package/dist/nodes/toJS.js +12 -10
  117. package/dist/options.d.ts +20 -26
  118. package/dist/options.js +0 -2
  119. package/dist/parse/cst-scalar.d.ts +58 -0
  120. package/dist/parse/cst-scalar.js +223 -0
  121. package/dist/parse/cst-stringify.d.ts +8 -0
  122. package/dist/parse/cst-stringify.js +63 -0
  123. package/dist/parse/cst-visit.d.ts +39 -0
  124. package/dist/parse/cst-visit.js +99 -0
  125. package/dist/parse/{tokens.d.ts → cst.d.ts} +23 -7
  126. package/{browser/dist/parse/tokens.js → dist/parse/cst.js} +27 -1
  127. package/dist/parse/lexer.d.ts +4 -13
  128. package/dist/parse/lexer.js +100 -106
  129. package/dist/parse/parser.d.ts +30 -24
  130. package/dist/parse/parser.js +221 -146
  131. package/dist/public-api.d.ts +7 -7
  132. package/dist/public-api.js +11 -14
  133. package/dist/{doc → schema}/Schema.d.ts +5 -3
  134. package/dist/schema/Schema.js +25 -0
  135. package/dist/{tags/failsafe → schema/common}/map.d.ts +0 -0
  136. package/dist/{tags/failsafe → schema/common}/map.js +0 -0
  137. package/dist/schema/common/null.d.ts +4 -0
  138. package/dist/schema/common/null.js +15 -0
  139. package/dist/{tags/failsafe → schema/common}/seq.d.ts +0 -0
  140. package/dist/{tags/failsafe → schema/common}/seq.js +1 -1
  141. package/dist/{tags/failsafe → schema/common}/string.d.ts +0 -0
  142. package/dist/{tags/failsafe → schema/common}/string.js +0 -0
  143. package/dist/schema/core/bool.d.ts +4 -0
  144. package/dist/schema/core/bool.js +21 -0
  145. package/dist/schema/core/float.d.ts +4 -0
  146. package/dist/schema/core/float.js +44 -0
  147. package/dist/schema/core/int.d.ts +4 -0
  148. package/dist/schema/core/int.js +42 -0
  149. package/dist/schema/core/schema.d.ts +1 -0
  150. package/dist/schema/core/schema.js +25 -0
  151. package/dist/schema/json/schema.d.ts +2 -0
  152. package/dist/{tags/json.js → schema/json/schema.js} +5 -6
  153. package/dist/schema/tags.d.ts +41 -0
  154. package/dist/schema/tags.js +82 -0
  155. package/dist/{tags → schema}/types.d.ts +3 -7
  156. package/dist/{tags → schema}/yaml-1.1/binary.d.ts +0 -0
  157. package/dist/{tags → schema}/yaml-1.1/binary.js +0 -0
  158. package/dist/schema/yaml-1.1/bool.d.ts +7 -0
  159. package/dist/schema/yaml-1.1/bool.js +29 -0
  160. package/dist/schema/yaml-1.1/float.d.ts +4 -0
  161. package/dist/schema/yaml-1.1/float.js +47 -0
  162. package/dist/schema/yaml-1.1/int.d.ts +5 -0
  163. package/dist/schema/yaml-1.1/int.js +76 -0
  164. package/dist/{tags → schema}/yaml-1.1/omap.d.ts +0 -0
  165. package/dist/{tags → schema}/yaml-1.1/omap.js +0 -0
  166. package/dist/{tags → schema}/yaml-1.1/pairs.d.ts +3 -2
  167. package/dist/{tags → schema}/yaml-1.1/pairs.js +9 -6
  168. package/dist/schema/yaml-1.1/schema.d.ts +1 -0
  169. package/dist/schema/yaml-1.1/schema.js +39 -0
  170. package/dist/{tags → schema}/yaml-1.1/set.d.ts +1 -1
  171. package/dist/{tags → schema}/yaml-1.1/set.js +0 -0
  172. package/dist/{tags → schema}/yaml-1.1/timestamp.d.ts +0 -0
  173. package/dist/{tags → schema}/yaml-1.1/timestamp.js +0 -0
  174. package/dist/stringify/addComment.js +0 -7
  175. package/dist/stringify/stringify.d.ts +1 -2
  176. package/dist/stringify/stringify.js +8 -6
  177. package/dist/stringify/stringifyCollection.d.ts +21 -0
  178. package/dist/stringify/stringifyCollection.js +110 -0
  179. package/dist/stringify/stringifyDocument.d.ts +3 -0
  180. package/dist/stringify/stringifyDocument.js +63 -0
  181. package/dist/stringify/stringifyPair.d.ts +3 -0
  182. package/dist/stringify/stringifyPair.js +115 -0
  183. package/dist/stringify/stringifyString.js +53 -52
  184. package/dist/test-events.d.ts +1 -2
  185. package/dist/test-events.js +25 -12
  186. package/dist/util.d.ts +1 -1
  187. package/dist/visit.d.ts +10 -1
  188. package/dist/visit.js +20 -1
  189. package/package.json +4 -3
  190. package/browser/dist/doc/Anchors.js +0 -102
  191. package/browser/dist/doc/Schema.js +0 -27
  192. package/browser/dist/doc/getSchemaTags.js +0 -30
  193. package/browser/dist/tags/core.js +0 -109
  194. package/browser/dist/tags/failsafe/index.js +0 -7
  195. package/browser/dist/tags/index.js +0 -34
  196. package/browser/dist/tags/yaml-1.1/index.js +0 -152
  197. package/dist/doc/Anchors.d.ts +0 -36
  198. package/dist/doc/Anchors.js +0 -104
  199. package/dist/doc/Schema.js +0 -29
  200. package/dist/doc/getSchemaTags.d.ts +0 -3
  201. package/dist/doc/getSchemaTags.js +0 -32
  202. package/dist/tags/core.d.ts +0 -14
  203. package/dist/tags/core.js +0 -119
  204. package/dist/tags/failsafe/index.d.ts +0 -1
  205. package/dist/tags/failsafe/index.js +0 -9
  206. package/dist/tags/index.d.ts +0 -31
  207. package/dist/tags/index.js +0 -37
  208. package/dist/tags/json.d.ts +0 -2
  209. package/dist/tags/yaml-1.1/index.d.ts +0 -2
  210. package/dist/tags/yaml-1.1/index.js +0 -154
@@ -1,9 +1,10 @@
1
1
  import { Scalar } from '../nodes/Scalar.js';
2
2
 
3
3
  function resolveBlockScalar(scalar, strict, onError) {
4
+ const start = scalar.offset;
4
5
  const header = parseBlockScalarHeader(scalar, strict, onError);
5
6
  if (!header)
6
- return { value: '', type: null, comment: '', length: 0 };
7
+ return { value: '', type: null, comment: '', range: [start, start, start] };
7
8
  const type = header.mode === '>' ? Scalar.BLOCK_FOLDED : Scalar.BLOCK_LITERAL;
8
9
  const lines = scalar.source ? splitLines(scalar.source) : [];
9
10
  // determine the end of content & start of chomping
@@ -18,10 +19,10 @@ function resolveBlockScalar(scalar, strict, onError) {
18
19
  // shortcut for empty contents
19
20
  if (!scalar.source || chompStart === 0) {
20
21
  const value = header.chomp === '+' ? lines.map(line => line[0]).join('\n') : '';
21
- let length = header.length;
22
+ let end = start + header.length;
22
23
  if (scalar.source)
23
- length += scalar.source.length;
24
- return { value, type, comment: header.comment, length };
24
+ end += scalar.source.length;
25
+ return { value, type, comment: header.comment, range: [start, end, end] };
25
26
  }
26
27
  // find the indentation level to trim from start
27
28
  let trimIndent = scalar.indent + header.indent;
@@ -36,7 +37,7 @@ function resolveBlockScalar(scalar, strict, onError) {
36
37
  else {
37
38
  if (indent.length < trimIndent) {
38
39
  const message = 'Block scalars with more-indented leading empty lines must use an explicit indentation indicator';
39
- onError(offset + indent.length, message);
40
+ onError(offset + indent.length, 'MISSING_CHAR', message);
40
41
  }
41
42
  if (header.indent === 0)
42
43
  trimIndent = indent.length;
@@ -63,7 +64,7 @@ function resolveBlockScalar(scalar, strict, onError) {
63
64
  ? 'explicit indentation indicator'
64
65
  : 'first line';
65
66
  const message = `Block scalar lines must not be less indented than their ${src}`;
66
- onError(offset - content.length - (crlf ? 2 : 1), message);
67
+ onError(offset - content.length - (crlf ? 2 : 1), 'BAD_INDENT', message);
67
68
  indent = '';
68
69
  }
69
70
  if (type === Scalar.BLOCK_LITERAL) {
@@ -105,17 +106,13 @@ function resolveBlockScalar(scalar, strict, onError) {
105
106
  default:
106
107
  value += '\n';
107
108
  }
108
- return {
109
- value,
110
- type,
111
- comment: header.comment,
112
- length: header.length + scalar.source.length
113
- };
109
+ const end = start + header.length + scalar.source.length;
110
+ return { value, type, comment: header.comment, range: [start, end, end] };
114
111
  }
115
112
  function parseBlockScalarHeader({ offset, props }, strict, onError) {
116
113
  /* istanbul ignore if should not happen */
117
114
  if (props[0].type !== 'block-scalar-header') {
118
- onError(offset, 'Block scalar header not found');
115
+ onError(props[0], 'IMPOSSIBLE', 'Block scalar header not found');
119
116
  return null;
120
117
  }
121
118
  const { source } = props[0];
@@ -136,7 +133,7 @@ function parseBlockScalarHeader({ offset, props }, strict, onError) {
136
133
  }
137
134
  }
138
135
  if (error !== -1)
139
- onError(error, `Block scalar header includes extra characters: ${source}`);
136
+ onError(error, 'UNEXPECTED_TOKEN', `Block scalar header includes extra characters: ${source}`);
140
137
  let hasSpace = false;
141
138
  let comment = '';
142
139
  let length = source.length;
@@ -152,19 +149,19 @@ function parseBlockScalarHeader({ offset, props }, strict, onError) {
152
149
  case 'comment':
153
150
  if (strict && !hasSpace) {
154
151
  const message = 'Comments must be separated from other tokens by white space characters';
155
- onError(offset + length, message);
152
+ onError(token, 'COMMENT_SPACE', message);
156
153
  }
157
154
  length += token.source.length;
158
155
  comment = token.source.substring(1);
159
156
  break;
160
157
  case 'error':
161
- onError(offset + length, token.message);
158
+ onError(token, 'UNEXPECTED_TOKEN', token.message);
162
159
  length += token.source.length;
163
160
  break;
164
161
  /* istanbul ignore next should not happen */
165
162
  default: {
166
163
  const message = `Unexpected token in block scalar header: ${token.type}`;
167
- onError(offset + length, message);
164
+ onError(token, 'UNEXPECTED_TOKEN', message);
168
165
  const ts = token.source;
169
166
  if (ts && typeof ts === 'string')
170
167
  length += ts.length;
@@ -1,20 +1,24 @@
1
1
  import { YAMLSeq } from '../nodes/YAMLSeq.js';
2
2
  import { resolveProps } from './resolve-props.js';
3
3
 
4
- function resolveBlockSeq({ composeNode, composeEmptyNode }, doc, { items, offset }, anchor, onError) {
5
- const start = offset;
6
- const seq = new YAMLSeq(doc.schema);
7
- if (anchor)
8
- doc.anchors.setAnchor(seq, anchor);
9
- for (const { start, value } of items) {
10
- const props = resolveProps(doc, start, true, 'seq-item-ind', offset, onError);
11
- offset += props.length;
4
+ function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError) {
5
+ const seq = new YAMLSeq(ctx.schema);
6
+ let offset = bs.offset;
7
+ for (const { start, value } of bs.items) {
8
+ const props = resolveProps(start, {
9
+ ctx,
10
+ indicator: 'seq-item-ind',
11
+ offset,
12
+ onError,
13
+ startOnNewline: true
14
+ });
15
+ offset = props.end;
12
16
  if (!props.found) {
13
- if (props.anchor || props.tagName || value) {
14
- const msg = value && value.type === 'block-seq'
15
- ? 'All sequence items must start at the same column'
16
- : 'Sequence item without - indicator';
17
- onError(offset, msg);
17
+ if (props.anchor || props.tag || value) {
18
+ if (value && value.type === 'block-seq')
19
+ onError(offset, 'BAD_INDENT', 'All sequence items must start at the same column');
20
+ else
21
+ onError(offset, 'MISSING_CHAR', 'Sequence item without - indicator');
18
22
  }
19
23
  else {
20
24
  // TODO: assert being at last item?
@@ -24,12 +28,12 @@ function resolveBlockSeq({ composeNode, composeEmptyNode }, doc, { items, offset
24
28
  }
25
29
  }
26
30
  const node = value
27
- ? composeNode(doc, value, props, onError)
28
- : composeEmptyNode(doc, offset, start, null, props, onError);
29
- offset = node.range[1];
31
+ ? composeNode(ctx, value, props, onError)
32
+ : composeEmptyNode(ctx, offset, start, null, props, onError);
33
+ offset = node.range[2];
30
34
  seq.items.push(node);
31
35
  }
32
- seq.range = [start, offset];
36
+ seq.range = [bs.offset, offset, offset];
33
37
  return seq;
34
38
  }
35
39
 
@@ -2,32 +2,31 @@ function resolveEnd(end, offset, reqSpace, onError) {
2
2
  let comment = '';
3
3
  if (end) {
4
4
  let hasSpace = false;
5
- let hasComment = false;
6
5
  let sep = '';
7
- for (const { source, type } of end) {
6
+ for (const token of end) {
7
+ const { source, type } = token;
8
8
  switch (type) {
9
9
  case 'space':
10
10
  hasSpace = true;
11
11
  break;
12
12
  case 'comment': {
13
13
  if (reqSpace && !hasSpace)
14
- onError(offset, 'Comments must be separated from other tokens by white space characters');
14
+ onError(token, 'COMMENT_SPACE', 'Comments must be separated from other tokens by white space characters');
15
15
  const cb = source.substring(1);
16
- if (!hasComment)
16
+ if (!comment)
17
17
  comment = cb;
18
18
  else
19
19
  comment += sep + cb;
20
- hasComment = true;
21
20
  sep = '';
22
21
  break;
23
22
  }
24
23
  case 'newline':
25
- if (hasComment)
24
+ if (comment)
26
25
  sep += source;
27
26
  hasSpace = true;
28
27
  break;
29
28
  default:
30
- onError(offset, `Unexpected ${type} at node end`);
29
+ onError(token, 'UNEXPECTED_TOKEN', `Unexpected ${type} at node end`);
31
30
  }
32
31
  offset += source.length;
33
32
  }
@@ -1,229 +1,183 @@
1
- import { isNode, isPair } from '../nodes/Node.js';
1
+ import { isPair } from '../nodes/Node.js';
2
2
  import { Pair } from '../nodes/Pair.js';
3
3
  import { YAMLMap } from '../nodes/YAMLMap.js';
4
4
  import { YAMLSeq } from '../nodes/YAMLSeq.js';
5
5
  import { resolveEnd } from './resolve-end.js';
6
+ import { resolveProps } from './resolve-props.js';
6
7
  import { containsNewline } from './util-contains-newline.js';
7
8
 
8
- function resolveFlowCollection({ composeNode, composeEmptyNode }, doc, fc, _anchor, onError) {
9
+ const blockMsg = 'Block collections are not allowed within flow collections';
10
+ const isBlock = (token) => token && (token.type === 'block-map' || token.type === 'block-seq');
11
+ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onError) {
9
12
  const isMap = fc.start.source === '{';
10
- const coll = isMap ? new YAMLMap(doc.schema) : new YAMLSeq(doc.schema);
13
+ const fcName = isMap ? 'flow map' : 'flow sequence';
14
+ const coll = isMap
15
+ ? new YAMLMap(ctx.schema)
16
+ : new YAMLSeq(ctx.schema);
11
17
  coll.flow = true;
12
- if (_anchor)
13
- doc.anchors.setAnchor(coll, _anchor);
14
- let key = null;
15
- let value = null;
16
- let spaceBefore = false;
17
- let comment = '';
18
- let hasSpace = false;
19
- let hasComment = false;
20
- let newlines = '';
21
- let anchor = '';
22
- let tagName = '';
23
- let offset = fc.offset + 1;
24
- let atLineStart = false;
25
- let atExplicitKey = false;
26
- let atValueEnd = false;
27
- let nlAfterValueInSeq = false;
28
- let seqKeyToken = null;
29
- function getProps() {
30
- const props = { spaceBefore, comment, anchor, tagName };
31
- spaceBefore = false;
32
- comment = '';
33
- hasComment = false;
34
- newlines = '';
35
- anchor = '';
36
- tagName = '';
37
- return props;
38
- }
39
- function addItem(pos) {
40
- if (value) {
41
- if (hasComment)
42
- value.comment = comment;
43
- }
44
- else {
45
- value = composeEmptyNode(doc, offset, fc.items, pos, getProps(), onError);
18
+ let offset = fc.offset;
19
+ for (let i = 0; i < fc.items.length; ++i) {
20
+ const { start, key, sep, value } = fc.items[i];
21
+ const props = resolveProps(start, {
22
+ ctx,
23
+ flow: fcName,
24
+ indicator: 'explicit-key-ind',
25
+ offset,
26
+ onError,
27
+ startOnNewline: false
28
+ });
29
+ if (!props.found) {
30
+ if (!props.anchor && !props.tag && !sep && !value) {
31
+ if (i === 0 && props.comma)
32
+ onError(props.comma, 'UNEXPECTED_TOKEN', `Unexpected , in ${fcName}`);
33
+ else if (i < fc.items.length - 1)
34
+ onError(props.start, 'UNEXPECTED_TOKEN', `Unexpected empty item in ${fcName}`);
35
+ if (props.comment) {
36
+ if (coll.comment)
37
+ coll.comment += '\n' + props.comment;
38
+ else
39
+ coll.comment = props.comment;
40
+ }
41
+ continue;
42
+ }
43
+ if (!isMap && ctx.options.strict && containsNewline(key))
44
+ onError(key, // checked by containsNewline()
45
+ 'MULTILINE_IMPLICIT_KEY', 'Implicit keys of flow sequence pairs need to be on a single line');
46
46
  }
47
- if (isMap || atExplicitKey) {
48
- coll.items.push(key ? new Pair(key, value) : new Pair(value));
47
+ if (i === 0) {
48
+ if (props.comma)
49
+ onError(props.comma, 'UNEXPECTED_TOKEN', `Unexpected , in ${fcName}`);
49
50
  }
50
51
  else {
51
- const seq = coll;
52
- if (key) {
53
- const map = new YAMLMap(doc.schema);
54
- map.flow = true;
55
- map.items.push(new Pair(key, value));
56
- seq.items.push(map);
57
- }
58
- else
59
- seq.items.push(value);
60
- }
61
- }
62
- for (let i = 0; i < fc.items.length; ++i) {
63
- const token = fc.items[i];
64
- let isSourceToken = true;
65
- switch (token.type) {
66
- case 'space':
67
- hasSpace = true;
68
- break;
69
- case 'comment': {
70
- if (doc.options.strict && !hasSpace)
71
- onError(offset, 'Comments must be separated from other tokens by white space characters');
72
- const cb = token.source.substring(1);
73
- if (!hasComment)
74
- comment = cb;
75
- else
76
- comment += newlines + cb;
77
- atLineStart = false;
78
- hasComment = true;
79
- newlines = '';
80
- break;
81
- }
82
- case 'newline':
83
- if (atLineStart && !hasComment)
84
- spaceBefore = true;
85
- if (atValueEnd) {
86
- if (hasComment) {
87
- let node = coll.items[coll.items.length - 1];
88
- if (isPair(node))
89
- node = node.value || node.key;
90
- /* istanbul ignore else should not happen */
91
- if (isNode(node))
92
- node.comment = comment;
93
- else
94
- onError(offset, 'Error adding trailing comment to node');
95
- comment = '';
96
- hasComment = false;
52
+ if (!props.comma)
53
+ onError(props.start, 'MISSING_CHAR', `Missing , between ${fcName} items`);
54
+ if (props.comment) {
55
+ let prevItemComment = '';
56
+ loop: for (const st of start) {
57
+ switch (st.type) {
58
+ case 'comma':
59
+ case 'space':
60
+ break;
61
+ case 'comment':
62
+ prevItemComment = st.source.substring(1);
63
+ break loop;
64
+ default:
65
+ break loop;
97
66
  }
98
- atValueEnd = false;
99
67
  }
100
- else {
101
- newlines += token.source;
102
- if (!isMap && !key && value)
103
- nlAfterValueInSeq = true;
68
+ if (prevItemComment) {
69
+ let prev = coll.items[coll.items.length - 1];
70
+ if (isPair(prev))
71
+ prev = prev.value || prev.key;
72
+ if (prev.comment)
73
+ prev.comment += '\n' + prevItemComment;
74
+ else
75
+ prev.comment = prevItemComment;
76
+ props.comment = props.comment.substring(prevItemComment.length + 1);
104
77
  }
105
- atLineStart = true;
106
- hasSpace = true;
107
- break;
108
- case 'anchor':
109
- if (anchor)
110
- onError(offset, 'A node can have at most one anchor');
111
- anchor = token.source.substring(1);
112
- atLineStart = false;
113
- atValueEnd = false;
114
- hasSpace = false;
115
- break;
116
- case 'tag': {
117
- if (tagName)
118
- onError(offset, 'A node can have at most one tag');
119
- const tn = doc.directives.tagName(token.source, m => onError(offset, m));
120
- if (tn)
121
- tagName = tn;
122
- atLineStart = false;
123
- atValueEnd = false;
124
- hasSpace = false;
125
- break;
126
78
  }
127
- case 'explicit-key-ind':
128
- if (anchor || tagName)
129
- onError(offset, 'Anchors and tags must be after the ? indicator');
130
- atExplicitKey = true;
131
- atLineStart = false;
132
- atValueEnd = false;
133
- hasSpace = false;
134
- break;
135
- case 'map-value-ind': {
136
- if (key) {
137
- if (value) {
138
- onError(offset, 'Missing {} around pair used as mapping key');
139
- const map = new YAMLMap(doc.schema);
140
- map.flow = true;
141
- map.items.push(new Pair(key, value));
142
- map.range = [key.range[0], value.range[1]];
143
- key = map;
144
- value = null;
145
- } // else explicit key
146
- }
147
- else if (value) {
148
- if (doc.options.strict) {
149
- const slMsg = 'Implicit keys of flow sequence pairs need to be on a single line';
150
- if (nlAfterValueInSeq)
151
- onError(offset, slMsg);
152
- else if (seqKeyToken) {
153
- if (containsNewline(seqKeyToken))
154
- onError(offset, slMsg);
155
- const start = 'offset' in seqKeyToken && seqKeyToken.offset;
156
- if (typeof start === 'number' && start < offset - 1024)
157
- onError(offset, 'The : indicator must be at most 1024 chars after the start of an implicit flow sequence key');
158
- seqKeyToken = null;
79
+ }
80
+ if (!isMap && !sep && !props.found) {
81
+ // item is a value in a seq
82
+ // → key & sep are empty, start does not include ? or :
83
+ const valueNode = value
84
+ ? composeNode(ctx, value, props, onError)
85
+ : composeEmptyNode(ctx, props.end, sep, null, props, onError);
86
+ coll.items.push(valueNode);
87
+ offset = valueNode.range[2];
88
+ if (isBlock(value))
89
+ onError(valueNode.range, 'BLOCK_IN_FLOW', blockMsg);
90
+ }
91
+ else {
92
+ // item is a key+value pair
93
+ // key value
94
+ const keyStart = props.end;
95
+ const keyNode = key
96
+ ? composeNode(ctx, key, props, onError)
97
+ : composeEmptyNode(ctx, keyStart, start, null, props, onError);
98
+ if (isBlock(key))
99
+ onError(keyNode.range, 'BLOCK_IN_FLOW', blockMsg);
100
+ // value properties
101
+ const valueProps = resolveProps(sep || [], {
102
+ ctx,
103
+ flow: fcName,
104
+ indicator: 'map-value-ind',
105
+ offset: keyNode.range[2],
106
+ onError,
107
+ startOnNewline: false
108
+ });
109
+ if (valueProps.found) {
110
+ if (!isMap && !props.found && ctx.options.strict) {
111
+ if (sep)
112
+ for (const st of sep) {
113
+ if (st === valueProps.found)
114
+ break;
115
+ if (st.type === 'newline') {
116
+ onError(st, 'MULTILINE_IMPLICIT_KEY', 'Implicit keys of flow sequence pairs need to be on a single line');
117
+ break;
118
+ }
159
119
  }
160
- }
161
- key = value;
162
- value = null;
120
+ if (props.start < valueProps.found.offset - 1024)
121
+ onError(valueProps.found, 'KEY_OVER_1024_CHARS', 'The : indicator must be at most 1024 chars after the start of an implicit flow sequence key');
163
122
  }
164
- else {
165
- key = composeEmptyNode(doc, offset, fc.items, i, getProps(), onError);
166
- }
167
- if (hasComment) {
168
- key.comment = comment;
169
- comment = '';
170
- hasComment = false;
171
- }
172
- atExplicitKey = false;
173
- atValueEnd = false;
174
- hasSpace = false;
175
- break;
176
123
  }
177
- case 'comma':
178
- if (key || value || anchor || tagName || atExplicitKey)
179
- addItem(i);
124
+ else if (value) {
125
+ if ('source' in value && value.source && value.source[0] === ':')
126
+ onError(value, 'MISSING_CHAR', `Missing space after : in ${fcName}`);
127
+ else
128
+ onError(valueProps.start, 'MISSING_CHAR', `Missing , or : between ${fcName} items`);
129
+ }
130
+ // value value
131
+ const valueNode = value
132
+ ? composeNode(ctx, value, valueProps, onError)
133
+ : valueProps.found
134
+ ? composeEmptyNode(ctx, valueProps.end, sep, null, valueProps, onError)
135
+ : null;
136
+ if (valueNode) {
137
+ if (isBlock(value))
138
+ onError(valueNode.range, 'BLOCK_IN_FLOW', blockMsg);
139
+ }
140
+ else if (valueProps.comment) {
141
+ if (keyNode.comment)
142
+ keyNode.comment += '\n' + valueProps.comment;
180
143
  else
181
- onError(offset, `Unexpected , in flow ${isMap ? 'map' : 'sequence'}`);
182
- key = null;
183
- value = null;
184
- atExplicitKey = false;
185
- atValueEnd = true;
186
- hasSpace = false;
187
- nlAfterValueInSeq = false;
188
- seqKeyToken = null;
189
- break;
190
- case 'block-map':
191
- case 'block-seq':
192
- onError(offset, 'Block collections are not allowed within flow collections');
193
- // fallthrough
194
- default: {
195
- if (value)
196
- onError(offset, 'Missing , between flow collection items');
197
- if (!isMap && !key && !atExplicitKey)
198
- seqKeyToken = token;
199
- value = composeNode(doc, token, getProps(), onError);
200
- offset = value.range[1];
201
- atLineStart = false;
202
- isSourceToken = false;
203
- atValueEnd = false;
204
- hasSpace = false;
144
+ keyNode.comment = valueProps.comment;
145
+ }
146
+ const pair = new Pair(keyNode, valueNode);
147
+ if (isMap)
148
+ coll.items.push(pair);
149
+ else {
150
+ const map = new YAMLMap(ctx.schema);
151
+ map.flow = true;
152
+ map.items.push(pair);
153
+ coll.items.push(map);
205
154
  }
155
+ offset = valueNode ? valueNode.range[2] : valueProps.end;
206
156
  }
207
- if (isSourceToken)
208
- offset += token.source.length;
209
157
  }
210
- if (key || value || anchor || tagName || atExplicitKey)
211
- addItem(fc.items.length);
212
158
  const expectedEnd = isMap ? '}' : ']';
213
159
  const [ce, ...ee] = fc.end;
214
- if (!ce || ce.source !== expectedEnd) {
215
- const cs = isMap ? 'map' : 'sequence';
216
- onError(offset, `Expected flow ${cs} to end with ${expectedEnd}`);
160
+ let cePos = offset;
161
+ if (ce && ce.source === expectedEnd)
162
+ cePos += ce.source.length;
163
+ else {
164
+ onError(offset + 1, 'MISSING_CHAR', `Expected ${fcName} to end with ${expectedEnd}`);
165
+ if (ce && ce.source.length !== 1)
166
+ ee.unshift(ce);
217
167
  }
218
- if (ce)
219
- offset += ce.source.length;
220
168
  if (ee.length > 0) {
221
- const end = resolveEnd(ee, offset, doc.options.strict, onError);
222
- if (end.comment)
223
- coll.comment = comment;
224
- offset = end.offset;
169
+ const end = resolveEnd(ee, cePos, ctx.options.strict, onError);
170
+ if (end.comment) {
171
+ if (coll.comment)
172
+ coll.comment += '\n' + end.comment;
173
+ else
174
+ coll.comment = end.comment;
175
+ }
176
+ coll.range = [fc.offset, cePos, end.offset];
177
+ }
178
+ else {
179
+ coll.range = [fc.offset, cePos, cePos];
225
180
  }
226
- coll.range = [fc.offset, offset];
227
181
  return coll;
228
182
  }
229
183