yaml 1.9.2 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/README.md +4 -4
  2. package/browser/dist/PlainValue-ff5147c6.js +1277 -0
  3. package/browser/dist/Schema-2bf2c74e.js +679 -0
  4. package/browser/dist/index.js +869 -34
  5. package/browser/dist/legacy-exports.js +3 -0
  6. package/browser/dist/parse-cst.js +1904 -0
  7. package/browser/dist/resolveSeq-04825f30.js +2373 -0
  8. package/browser/dist/types.js +4 -0
  9. package/browser/dist/util.js +2 -0
  10. package/browser/dist/warnings-0e4b70d3.js +499 -0
  11. package/browser/index.js +1 -1
  12. package/browser/map.js +2 -4
  13. package/browser/pair.js +2 -4
  14. package/browser/parse-cst.js +1 -1
  15. package/browser/scalar.js +2 -4
  16. package/browser/schema.js +7 -10
  17. package/browser/seq.js +2 -4
  18. package/browser/types/binary.js +7 -5
  19. package/browser/types/omap.js +3 -4
  20. package/browser/types/pairs.js +3 -4
  21. package/browser/types/set.js +3 -4
  22. package/browser/types/timestamp.js +9 -5
  23. package/browser/types.js +1 -13
  24. package/browser/util.js +1 -18
  25. package/dist/Document-2cf6b08c.js +757 -0
  26. package/dist/PlainValue-ec8e588e.js +876 -0
  27. package/dist/Schema-42e9705c.js +522 -0
  28. package/dist/index.js +20 -84
  29. package/dist/legacy-exports.js +16 -0
  30. package/dist/parse-cst.js +1747 -0
  31. package/dist/resolveSeq-4a68b39b.js +2115 -0
  32. package/dist/test-events.js +11 -9
  33. package/dist/types.js +23 -0
  34. package/dist/util.js +19 -0
  35. package/dist/warnings-39684f17.js +416 -0
  36. package/index.d.ts +22 -8
  37. package/map.js +2 -2
  38. package/package.json +22 -39
  39. package/pair.js +2 -2
  40. package/parse-cst.js +1 -1
  41. package/scalar.js +2 -2
  42. package/schema.js +8 -6
  43. package/seq.js +2 -2
  44. package/types/binary.js +3 -2
  45. package/types/omap.js +3 -2
  46. package/types/pairs.js +3 -2
  47. package/types/set.js +3 -2
  48. package/types/timestamp.js +6 -6
  49. package/types.d.ts +113 -99
  50. package/types.js +16 -11
  51. package/types.mjs +15 -19
  52. package/util.js +14 -14
  53. package/util.mjs +13 -20
  54. package/browser/dist/Anchors.js +0 -130
  55. package/browser/dist/Document.js +0 -824
  56. package/browser/dist/addComment.js +0 -8
  57. package/browser/dist/constants.js +0 -26
  58. package/browser/dist/cst/Alias.js +0 -46
  59. package/browser/dist/cst/BlankLine.js +0 -52
  60. package/browser/dist/cst/BlockValue.js +0 -251
  61. package/browser/dist/cst/Collection.js +0 -278
  62. package/browser/dist/cst/CollectionItem.js +0 -140
  63. package/browser/dist/cst/Comment.js +0 -44
  64. package/browser/dist/cst/Directive.js +0 -76
  65. package/browser/dist/cst/Document.js +0 -286
  66. package/browser/dist/cst/FlowCollection.js +0 -220
  67. package/browser/dist/cst/Node.js +0 -386
  68. package/browser/dist/cst/ParseContext.js +0 -246
  69. package/browser/dist/cst/PlainValue.js +0 -170
  70. package/browser/dist/cst/QuoteDouble.js +0 -245
  71. package/browser/dist/cst/QuoteSingle.js +0 -120
  72. package/browser/dist/cst/Range.js +0 -64
  73. package/browser/dist/cst/parse.js +0 -48
  74. package/browser/dist/cst/source-utils.js +0 -168
  75. package/browser/dist/errors.js +0 -127
  76. package/browser/dist/foldFlowLines.js +0 -138
  77. package/browser/dist/listTagNames.js +0 -28
  78. package/browser/dist/schema/Alias.js +0 -135
  79. package/browser/dist/schema/Collection.js +0 -260
  80. package/browser/dist/schema/Map.js +0 -161
  81. package/browser/dist/schema/Merge.js +0 -118
  82. package/browser/dist/schema/Node.js +0 -4
  83. package/browser/dist/schema/Pair.js +0 -194
  84. package/browser/dist/schema/Scalar.js +0 -42
  85. package/browser/dist/schema/Seq.js +0 -116
  86. package/browser/dist/schema/index.js +0 -368
  87. package/browser/dist/schema/parseMap.js +0 -312
  88. package/browser/dist/schema/parseSeq.js +0 -168
  89. package/browser/dist/schema/parseUtils.js +0 -106
  90. package/browser/dist/stringify.js +0 -332
  91. package/browser/dist/tags/core.js +0 -141
  92. package/browser/dist/tags/failsafe/index.js +0 -4
  93. package/browser/dist/tags/failsafe/map.js +0 -53
  94. package/browser/dist/tags/failsafe/seq.js +0 -39
  95. package/browser/dist/tags/failsafe/string.js +0 -28
  96. package/browser/dist/tags/index.js +0 -36
  97. package/browser/dist/tags/json.js +0 -77
  98. package/browser/dist/tags/options.js +0 -26
  99. package/browser/dist/tags/yaml-1.1/binary.js +0 -87
  100. package/browser/dist/tags/yaml-1.1/index.js +0 -189
  101. package/browser/dist/tags/yaml-1.1/omap.js +0 -137
  102. package/browser/dist/tags/yaml-1.1/pairs.js +0 -78
  103. package/browser/dist/tags/yaml-1.1/set.js +0 -118
  104. package/browser/dist/tags/yaml-1.1/timestamp.js +0 -97
  105. package/browser/dist/test-events.js +0 -163
  106. package/browser/dist/toJSON.js +0 -19
  107. package/browser/dist/warnings.js +0 -39
  108. package/dist/Anchors.js +0 -120
  109. package/dist/Document.js +0 -714
  110. package/dist/addComment.js +0 -14
  111. package/dist/constants.js +0 -31
  112. package/dist/cst/Alias.js +0 -33
  113. package/dist/cst/BlankLine.js +0 -40
  114. package/dist/cst/BlockValue.js +0 -243
  115. package/dist/cst/Collection.js +0 -266
  116. package/dist/cst/CollectionItem.js +0 -135
  117. package/dist/cst/Comment.js +0 -33
  118. package/dist/cst/Directive.js +0 -59
  119. package/dist/cst/Document.js +0 -276
  120. package/dist/cst/FlowCollection.js +0 -213
  121. package/dist/cst/Node.js +0 -360
  122. package/dist/cst/ParseContext.js +0 -253
  123. package/dist/cst/PlainValue.js +0 -156
  124. package/dist/cst/QuoteDouble.js +0 -232
  125. package/dist/cst/QuoteSingle.js +0 -108
  126. package/dist/cst/Range.js +0 -60
  127. package/dist/cst/parse.js +0 -50
  128. package/dist/cst/source-utils.js +0 -175
  129. package/dist/errors.js +0 -97
  130. package/dist/foldFlowLines.js +0 -143
  131. package/dist/listTagNames.js +0 -33
  132. package/dist/schema/Alias.js +0 -105
  133. package/dist/schema/Collection.js +0 -184
  134. package/dist/schema/Map.js +0 -98
  135. package/dist/schema/Merge.js +0 -75
  136. package/dist/schema/Node.js +0 -7
  137. package/dist/schema/Pair.js +0 -174
  138. package/dist/schema/Scalar.js +0 -26
  139. package/dist/schema/Seq.js +0 -73
  140. package/dist/schema/index.js +0 -310
  141. package/dist/schema/parseMap.js +0 -334
  142. package/dist/schema/parseSeq.js +0 -175
  143. package/dist/schema/parseUtils.js +0 -101
  144. package/dist/stringify.js +0 -352
  145. package/dist/tags/core.js +0 -121
  146. package/dist/tags/failsafe/index.js +0 -12
  147. package/dist/tags/failsafe/map.js +0 -32
  148. package/dist/tags/failsafe/seq.js +0 -29
  149. package/dist/tags/failsafe/string.js +0 -37
  150. package/dist/tags/index.js +0 -53
  151. package/dist/tags/json.js +0 -64
  152. package/dist/tags/options.js +0 -36
  153. package/dist/tags/yaml-1.1/binary.js +0 -94
  154. package/dist/tags/yaml-1.1/index.js +0 -162
  155. package/dist/tags/yaml-1.1/omap.js +0 -100
  156. package/dist/tags/yaml-1.1/pairs.js +0 -75
  157. package/dist/tags/yaml-1.1/set.js +0 -82
  158. package/dist/tags/yaml-1.1/timestamp.js +0 -90
  159. package/dist/toJSON.js +0 -21
  160. package/dist/warnings.js +0 -48
@@ -0,0 +1,2115 @@
1
+ 'use strict';
2
+
3
+ var PlainValue = require('./PlainValue-ec8e588e.js');
4
+
5
+ function addCommentBefore(str, indent, comment) {
6
+ if (!comment) return str;
7
+ const cc = comment.replace(/[\s\S]^/gm, `$&${indent}#`);
8
+ return `#${cc}\n${indent}${str}`;
9
+ }
10
+ function addComment(str, indent, comment) {
11
+ return !comment ? str : comment.indexOf('\n') === -1 ? `${str} #${comment}` : `${str}\n` + comment.replace(/^/gm, `${indent || ''}#`);
12
+ }
13
+
14
+ class Node {}
15
+
16
+ function toJSON(value, arg, ctx) {
17
+ if (Array.isArray(value)) return value.map((v, i) => toJSON(v, String(i), ctx));
18
+
19
+ if (value && typeof value.toJSON === 'function') {
20
+ const anchor = ctx && ctx.anchors && ctx.anchors.get(value);
21
+ if (anchor) ctx.onCreate = res => {
22
+ anchor.res = res;
23
+ delete ctx.onCreate;
24
+ };
25
+ const res = value.toJSON(arg, ctx);
26
+ if (anchor && ctx.onCreate) ctx.onCreate(res);
27
+ return res;
28
+ }
29
+
30
+ if ((!ctx || !ctx.keep) && typeof value === 'bigint') return Number(value);
31
+ return value;
32
+ }
33
+
34
+ class Scalar extends Node {
35
+ constructor(value) {
36
+ super();
37
+ this.value = value;
38
+ }
39
+
40
+ toJSON(arg, ctx) {
41
+ return ctx && ctx.keep ? this.value : toJSON(this.value, arg, ctx);
42
+ }
43
+
44
+ toString() {
45
+ return String(this.value);
46
+ }
47
+
48
+ }
49
+
50
+ function collectionFromPath(schema, path, value) {
51
+ let v = value;
52
+
53
+ for (let i = path.length - 1; i >= 0; --i) {
54
+ const k = path[i];
55
+ const o = Number.isInteger(k) && k >= 0 ? [] : {};
56
+ o[k] = v;
57
+ v = o;
58
+ }
59
+
60
+ return schema.createNode(v, false);
61
+ } // null, undefined, or an empty non-string iterable (e.g. [])
62
+
63
+
64
+ const isEmptyPath = path => path == null || typeof path === 'object' && path[Symbol.iterator]().next().done;
65
+ class Collection extends Node {
66
+ constructor(schema) {
67
+ super();
68
+
69
+ PlainValue._defineProperty(this, "items", []);
70
+
71
+ this.schema = schema;
72
+ }
73
+
74
+ addIn(path, value) {
75
+ if (isEmptyPath(path)) this.add(value);else {
76
+ const [key, ...rest] = path;
77
+ const node = this.get(key, true);
78
+ if (node instanceof Collection) node.addIn(rest, value);else if (node === undefined && this.schema) this.set(key, collectionFromPath(this.schema, rest, value));else throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
79
+ }
80
+ }
81
+
82
+ deleteIn([key, ...rest]) {
83
+ if (rest.length === 0) return this.delete(key);
84
+ const node = this.get(key, true);
85
+ if (node instanceof Collection) return node.deleteIn(rest);else throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
86
+ }
87
+
88
+ getIn([key, ...rest], keepScalar) {
89
+ const node = this.get(key, true);
90
+ if (rest.length === 0) return !keepScalar && node instanceof Scalar ? node.value : node;else return node instanceof Collection ? node.getIn(rest, keepScalar) : undefined;
91
+ }
92
+
93
+ hasAllNullValues() {
94
+ return this.items.every(node => {
95
+ if (!node || node.type !== 'PAIR') return false;
96
+ const n = node.value;
97
+ return n == null || n instanceof Scalar && n.value == null && !n.commentBefore && !n.comment && !n.tag;
98
+ });
99
+ }
100
+
101
+ hasIn([key, ...rest]) {
102
+ if (rest.length === 0) return this.has(key);
103
+ const node = this.get(key, true);
104
+ return node instanceof Collection ? node.hasIn(rest) : false;
105
+ }
106
+
107
+ setIn([key, ...rest], value) {
108
+ if (rest.length === 0) {
109
+ this.set(key, value);
110
+ } else {
111
+ const node = this.get(key, true);
112
+ if (node instanceof Collection) node.setIn(rest, value);else if (node === undefined && this.schema) this.set(key, collectionFromPath(this.schema, rest, value));else throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
113
+ }
114
+ } // overridden in implementations
115
+
116
+ /* istanbul ignore next */
117
+
118
+
119
+ toJSON() {
120
+ return null;
121
+ }
122
+
123
+ toString(ctx, {
124
+ blockItem,
125
+ flowChars,
126
+ isMap,
127
+ itemIndent
128
+ }, onComment, onChompKeep) {
129
+ const {
130
+ indent,
131
+ indentStep,
132
+ stringify
133
+ } = ctx;
134
+ const inFlow = this.type === PlainValue.Type.FLOW_MAP || this.type === PlainValue.Type.FLOW_SEQ || ctx.inFlow;
135
+ if (inFlow) itemIndent += indentStep;
136
+ const allNullValues = isMap && this.hasAllNullValues();
137
+ ctx = Object.assign({}, ctx, {
138
+ allNullValues,
139
+ indent: itemIndent,
140
+ inFlow,
141
+ type: null
142
+ });
143
+ let chompKeep = false;
144
+ let hasItemWithNewLine = false;
145
+ const nodes = this.items.reduce((nodes, item, i) => {
146
+ let comment;
147
+
148
+ if (item) {
149
+ if (!chompKeep && item.spaceBefore) nodes.push({
150
+ type: 'comment',
151
+ str: ''
152
+ });
153
+ if (item.commentBefore) item.commentBefore.match(/^.*$/gm).forEach(line => {
154
+ nodes.push({
155
+ type: 'comment',
156
+ str: `#${line}`
157
+ });
158
+ });
159
+ if (item.comment) comment = item.comment;
160
+ if (inFlow && (!chompKeep && item.spaceBefore || item.commentBefore || item.comment || item.key && (item.key.commentBefore || item.key.comment) || item.value && (item.value.commentBefore || item.value.comment))) hasItemWithNewLine = true;
161
+ }
162
+
163
+ chompKeep = false;
164
+ let str = stringify(item, ctx, () => comment = null, () => chompKeep = true);
165
+ if (inFlow && !hasItemWithNewLine && str.includes('\n')) hasItemWithNewLine = true;
166
+ if (inFlow && i < this.items.length - 1) str += ',';
167
+ str = addComment(str, itemIndent, comment);
168
+ if (chompKeep && (comment || inFlow)) chompKeep = false;
169
+ nodes.push({
170
+ type: 'item',
171
+ str
172
+ });
173
+ return nodes;
174
+ }, []);
175
+ let str;
176
+
177
+ if (nodes.length === 0) {
178
+ str = flowChars.start + flowChars.end;
179
+ } else if (inFlow) {
180
+ const {
181
+ start,
182
+ end
183
+ } = flowChars;
184
+ const strings = nodes.map(n => n.str);
185
+
186
+ if (hasItemWithNewLine || strings.reduce((sum, str) => sum + str.length + 2, 2) > Collection.maxFlowStringSingleLineLength) {
187
+ str = start;
188
+
189
+ for (const s of strings) {
190
+ str += s ? `\n${indentStep}${indent}${s}` : '\n';
191
+ }
192
+
193
+ str += `\n${indent}${end}`;
194
+ } else {
195
+ str = `${start} ${strings.join(' ')} ${end}`;
196
+ }
197
+ } else {
198
+ const strings = nodes.map(blockItem);
199
+ str = strings.shift();
200
+
201
+ for (const s of strings) str += s ? `\n${indent}${s}` : '\n';
202
+ }
203
+
204
+ if (this.comment) {
205
+ str += '\n' + this.comment.replace(/^/gm, `${indent}#`);
206
+ if (onComment) onComment();
207
+ } else if (chompKeep && onChompKeep) onChompKeep();
208
+
209
+ return str;
210
+ }
211
+
212
+ }
213
+
214
+ PlainValue._defineProperty(Collection, "maxFlowStringSingleLineLength", 60);
215
+
216
+ function asItemIndex(key) {
217
+ let idx = key instanceof Scalar ? key.value : key;
218
+ if (idx && typeof idx === 'string') idx = Number(idx);
219
+ return Number.isInteger(idx) && idx >= 0 ? idx : null;
220
+ }
221
+
222
+ class YAMLSeq extends Collection {
223
+ add(value) {
224
+ this.items.push(value);
225
+ }
226
+
227
+ delete(key) {
228
+ const idx = asItemIndex(key);
229
+ if (typeof idx !== 'number') return false;
230
+ const del = this.items.splice(idx, 1);
231
+ return del.length > 0;
232
+ }
233
+
234
+ get(key, keepScalar) {
235
+ const idx = asItemIndex(key);
236
+ if (typeof idx !== 'number') return undefined;
237
+ const it = this.items[idx];
238
+ return !keepScalar && it instanceof Scalar ? it.value : it;
239
+ }
240
+
241
+ has(key) {
242
+ const idx = asItemIndex(key);
243
+ return typeof idx === 'number' && idx < this.items.length;
244
+ }
245
+
246
+ set(key, value) {
247
+ const idx = asItemIndex(key);
248
+ if (typeof idx !== 'number') throw new Error(`Expected a valid index, not ${key}.`);
249
+ this.items[idx] = value;
250
+ }
251
+
252
+ toJSON(_, ctx) {
253
+ const seq = [];
254
+ if (ctx && ctx.onCreate) ctx.onCreate(seq);
255
+ let i = 0;
256
+
257
+ for (const item of this.items) seq.push(toJSON(item, String(i++), ctx));
258
+
259
+ return seq;
260
+ }
261
+
262
+ toString(ctx, onComment, onChompKeep) {
263
+ if (!ctx) return JSON.stringify(this);
264
+ return super.toString(ctx, {
265
+ blockItem: n => n.type === 'comment' ? n.str : `- ${n.str}`,
266
+ flowChars: {
267
+ start: '[',
268
+ end: ']'
269
+ },
270
+ isMap: false,
271
+ itemIndent: (ctx.indent || '') + ' '
272
+ }, onComment, onChompKeep);
273
+ }
274
+
275
+ }
276
+
277
+ const stringifyKey = (key, jsKey, ctx) => {
278
+ if (jsKey === null) return '';
279
+ if (typeof jsKey !== 'object') return String(jsKey);
280
+ if (key instanceof Node && ctx && ctx.doc) return key.toString({
281
+ anchors: {},
282
+ doc: ctx.doc,
283
+ indent: '',
284
+ indentStep: ctx.indentStep,
285
+ inFlow: true,
286
+ inStringifyKey: true,
287
+ stringify: ctx.stringify
288
+ });
289
+ return JSON.stringify(jsKey);
290
+ };
291
+
292
+ class Pair extends Node {
293
+ constructor(key, value = null) {
294
+ super();
295
+ this.key = key;
296
+ this.value = value;
297
+ this.type = Pair.Type.PAIR;
298
+ }
299
+
300
+ get commentBefore() {
301
+ return this.key instanceof Node ? this.key.commentBefore : undefined;
302
+ }
303
+
304
+ set commentBefore(cb) {
305
+ if (this.key == null) this.key = new Scalar(null);
306
+ if (this.key instanceof Node) this.key.commentBefore = cb;else {
307
+ const msg = 'Pair.commentBefore is an alias for Pair.key.commentBefore. To set it, the key must be a Node.';
308
+ throw new Error(msg);
309
+ }
310
+ }
311
+
312
+ addToJSMap(ctx, map) {
313
+ const key = toJSON(this.key, '', ctx);
314
+
315
+ if (map instanceof Map) {
316
+ const value = toJSON(this.value, key, ctx);
317
+ map.set(key, value);
318
+ } else if (map instanceof Set) {
319
+ map.add(key);
320
+ } else {
321
+ const stringKey = stringifyKey(this.key, key, ctx);
322
+ map[stringKey] = toJSON(this.value, stringKey, ctx);
323
+ }
324
+
325
+ return map;
326
+ }
327
+
328
+ toJSON(_, ctx) {
329
+ const pair = ctx && ctx.mapAsMap ? new Map() : {};
330
+ return this.addToJSMap(ctx, pair);
331
+ }
332
+
333
+ toString(ctx, onComment, onChompKeep) {
334
+ if (!ctx || !ctx.doc) return JSON.stringify(this);
335
+ const {
336
+ indent: indentSize,
337
+ indentSeq,
338
+ simpleKeys
339
+ } = ctx.doc.options;
340
+ let {
341
+ key,
342
+ value
343
+ } = this;
344
+ let keyComment = key instanceof Node && key.comment;
345
+
346
+ if (simpleKeys) {
347
+ if (keyComment) {
348
+ throw new Error('With simple keys, key nodes cannot have comments');
349
+ }
350
+
351
+ if (key instanceof Collection) {
352
+ const msg = 'With simple keys, collection cannot be used as a key value';
353
+ throw new Error(msg);
354
+ }
355
+ }
356
+
357
+ const explicitKey = !simpleKeys && (!key || keyComment || key instanceof Collection || key.type === PlainValue.Type.BLOCK_FOLDED || key.type === PlainValue.Type.BLOCK_LITERAL);
358
+ const {
359
+ doc,
360
+ indent,
361
+ indentStep,
362
+ stringify
363
+ } = ctx;
364
+ ctx = Object.assign({}, ctx, {
365
+ implicitKey: !explicitKey,
366
+ indent: indent + indentStep
367
+ });
368
+ let chompKeep = false;
369
+ let str = stringify(key, ctx, () => keyComment = null, () => chompKeep = true);
370
+ str = addComment(str, ctx.indent, keyComment);
371
+
372
+ if (ctx.allNullValues && !simpleKeys) {
373
+ if (this.comment) {
374
+ str = addComment(str, ctx.indent, this.comment);
375
+ if (onComment) onComment();
376
+ } else if (chompKeep && !keyComment && onChompKeep) onChompKeep();
377
+
378
+ return ctx.inFlow ? str : `? ${str}`;
379
+ }
380
+
381
+ str = explicitKey ? `? ${str}\n${indent}:` : `${str}:`;
382
+
383
+ if (this.comment) {
384
+ // expected (but not strictly required) to be a single-line comment
385
+ str = addComment(str, ctx.indent, this.comment);
386
+ if (onComment) onComment();
387
+ }
388
+
389
+ let vcb = '';
390
+ let valueComment = null;
391
+
392
+ if (value instanceof Node) {
393
+ if (value.spaceBefore) vcb = '\n';
394
+
395
+ if (value.commentBefore) {
396
+ const cs = value.commentBefore.replace(/^/gm, `${ctx.indent}#`);
397
+ vcb += `\n${cs}`;
398
+ }
399
+
400
+ valueComment = value.comment;
401
+ } else if (value && typeof value === 'object') {
402
+ value = doc.schema.createNode(value, true);
403
+ }
404
+
405
+ ctx.implicitKey = false;
406
+ if (!explicitKey && !this.comment && value instanceof Scalar) ctx.indentAtStart = str.length + 1;
407
+ chompKeep = false;
408
+
409
+ if (!indentSeq && indentSize >= 2 && !ctx.inFlow && !explicitKey && value instanceof YAMLSeq && value.type !== PlainValue.Type.FLOW_SEQ && !value.tag && !doc.anchors.getName(value)) {
410
+ // If indentSeq === false, consider '- ' as part of indentation where possible
411
+ ctx.indent = ctx.indent.substr(2);
412
+ }
413
+
414
+ const valueStr = stringify(value, ctx, () => valueComment = null, () => chompKeep = true);
415
+ let ws = ' ';
416
+
417
+ if (vcb || this.comment) {
418
+ ws = `${vcb}\n${ctx.indent}`;
419
+ } else if (!explicitKey && value instanceof Collection) {
420
+ const flow = valueStr[0] === '[' || valueStr[0] === '{';
421
+ if (!flow || valueStr.includes('\n')) ws = `\n${ctx.indent}`;
422
+ }
423
+
424
+ if (chompKeep && !valueComment && onChompKeep) onChompKeep();
425
+ return addComment(str + ws + valueStr, ctx.indent, valueComment);
426
+ }
427
+
428
+ }
429
+
430
+ PlainValue._defineProperty(Pair, "Type", {
431
+ PAIR: 'PAIR',
432
+ MERGE_PAIR: 'MERGE_PAIR'
433
+ });
434
+
435
+ const getAliasCount = (node, anchors) => {
436
+ if (node instanceof Alias) {
437
+ const anchor = anchors.get(node.source);
438
+ return anchor.count * anchor.aliasCount;
439
+ } else if (node instanceof Collection) {
440
+ let count = 0;
441
+
442
+ for (const item of node.items) {
443
+ const c = getAliasCount(item, anchors);
444
+ if (c > count) count = c;
445
+ }
446
+
447
+ return count;
448
+ } else if (node instanceof Pair) {
449
+ const kc = getAliasCount(node.key, anchors);
450
+ const vc = getAliasCount(node.value, anchors);
451
+ return Math.max(kc, vc);
452
+ }
453
+
454
+ return 1;
455
+ };
456
+
457
+ class Alias extends Node {
458
+ static stringify({
459
+ range,
460
+ source
461
+ }, {
462
+ anchors,
463
+ doc,
464
+ implicitKey,
465
+ inStringifyKey
466
+ }) {
467
+ let anchor = Object.keys(anchors).find(a => anchors[a] === source);
468
+ if (!anchor && inStringifyKey) anchor = doc.anchors.getName(source) || doc.anchors.newName();
469
+ if (anchor) return `*${anchor}${implicitKey ? ' ' : ''}`;
470
+ const msg = doc.anchors.getName(source) ? 'Alias node must be after source node' : 'Source node not found for alias node';
471
+ throw new Error(`${msg} [${range}]`);
472
+ }
473
+
474
+ constructor(source) {
475
+ super();
476
+ this.source = source;
477
+ this.type = PlainValue.Type.ALIAS;
478
+ }
479
+
480
+ set tag(t) {
481
+ throw new Error('Alias nodes cannot have tags');
482
+ }
483
+
484
+ toJSON(arg, ctx) {
485
+ if (!ctx) return toJSON(this.source, arg, ctx);
486
+ const {
487
+ anchors,
488
+ maxAliasCount
489
+ } = ctx;
490
+ const anchor = anchors.get(this.source);
491
+ /* istanbul ignore if */
492
+
493
+ if (!anchor || anchor.res === undefined) {
494
+ const msg = 'This should not happen: Alias anchor was not resolved?';
495
+ if (this.cstNode) throw new PlainValue.YAMLReferenceError(this.cstNode, msg);else throw new ReferenceError(msg);
496
+ }
497
+
498
+ if (maxAliasCount >= 0) {
499
+ anchor.count += 1;
500
+ if (anchor.aliasCount === 0) anchor.aliasCount = getAliasCount(this.source, anchors);
501
+
502
+ if (anchor.count * anchor.aliasCount > maxAliasCount) {
503
+ const msg = 'Excessive alias count indicates a resource exhaustion attack';
504
+ if (this.cstNode) throw new PlainValue.YAMLReferenceError(this.cstNode, msg);else throw new ReferenceError(msg);
505
+ }
506
+ }
507
+
508
+ return anchor.res;
509
+ } // Only called when stringifying an alias mapping key while constructing
510
+ // Object output.
511
+
512
+
513
+ toString(ctx) {
514
+ return Alias.stringify(this, ctx);
515
+ }
516
+
517
+ }
518
+
519
+ PlainValue._defineProperty(Alias, "default", true);
520
+
521
+ function findPair(items, key) {
522
+ const k = key instanceof Scalar ? key.value : key;
523
+
524
+ for (const it of items) {
525
+ if (it instanceof Pair) {
526
+ if (it.key === key || it.key === k) return it;
527
+ if (it.key && it.key.value === k) return it;
528
+ }
529
+ }
530
+
531
+ return undefined;
532
+ }
533
+ class YAMLMap extends Collection {
534
+ add(pair, overwrite) {
535
+ if (!pair) pair = new Pair(pair);else if (!(pair instanceof Pair)) pair = new Pair(pair.key || pair, pair.value);
536
+ const prev = findPair(this.items, pair.key);
537
+ const sortEntries = this.schema && this.schema.sortMapEntries;
538
+
539
+ if (prev) {
540
+ if (overwrite) prev.value = pair.value;else throw new Error(`Key ${pair.key} already set`);
541
+ } else if (sortEntries) {
542
+ const i = this.items.findIndex(item => sortEntries(pair, item) < 0);
543
+ if (i === -1) this.items.push(pair);else this.items.splice(i, 0, pair);
544
+ } else {
545
+ this.items.push(pair);
546
+ }
547
+ }
548
+
549
+ delete(key) {
550
+ const it = findPair(this.items, key);
551
+ if (!it) return false;
552
+ const del = this.items.splice(this.items.indexOf(it), 1);
553
+ return del.length > 0;
554
+ }
555
+
556
+ get(key, keepScalar) {
557
+ const it = findPair(this.items, key);
558
+ const node = it && it.value;
559
+ return !keepScalar && node instanceof Scalar ? node.value : node;
560
+ }
561
+
562
+ has(key) {
563
+ return !!findPair(this.items, key);
564
+ }
565
+
566
+ set(key, value) {
567
+ this.add(new Pair(key, value), true);
568
+ }
569
+ /**
570
+ * @param {*} arg ignored
571
+ * @param {*} ctx Conversion context, originally set in Document#toJSON()
572
+ * @param {Class} Type If set, forces the returned collection type
573
+ * @returns {*} Instance of Type, Map, or Object
574
+ */
575
+
576
+
577
+ toJSON(_, ctx, Type) {
578
+ const map = Type ? new Type() : ctx && ctx.mapAsMap ? new Map() : {};
579
+ if (ctx && ctx.onCreate) ctx.onCreate(map);
580
+
581
+ for (const item of this.items) item.addToJSMap(ctx, map);
582
+
583
+ return map;
584
+ }
585
+
586
+ toString(ctx, onComment, onChompKeep) {
587
+ if (!ctx) return JSON.stringify(this);
588
+
589
+ for (const item of this.items) {
590
+ if (!(item instanceof Pair)) throw new Error(`Map items must all be pairs; found ${JSON.stringify(item)} instead`);
591
+ }
592
+
593
+ return super.toString(ctx, {
594
+ blockItem: n => n.str,
595
+ flowChars: {
596
+ start: '{',
597
+ end: '}'
598
+ },
599
+ isMap: true,
600
+ itemIndent: ctx.indent || ''
601
+ }, onComment, onChompKeep);
602
+ }
603
+
604
+ }
605
+
606
+ const MERGE_KEY = '<<';
607
+ class Merge extends Pair {
608
+ constructor(pair) {
609
+ if (pair instanceof Pair) {
610
+ let seq = pair.value;
611
+
612
+ if (!(seq instanceof YAMLSeq)) {
613
+ seq = new YAMLSeq();
614
+ seq.items.push(pair.value);
615
+ seq.range = pair.value.range;
616
+ }
617
+
618
+ super(pair.key, seq);
619
+ this.range = pair.range;
620
+ } else {
621
+ super(new Scalar(MERGE_KEY), new YAMLSeq());
622
+ }
623
+
624
+ this.type = Pair.Type.MERGE_PAIR;
625
+ } // If the value associated with a merge key is a single mapping node, each of
626
+ // its key/value pairs is inserted into the current mapping, unless the key
627
+ // already exists in it. If the value associated with the merge key is a
628
+ // sequence, then this sequence is expected to contain mapping nodes and each
629
+ // of these nodes is merged in turn according to its order in the sequence.
630
+ // Keys in mapping nodes earlier in the sequence override keys specified in
631
+ // later mapping nodes. -- http://yaml.org/type/merge.html
632
+
633
+
634
+ addToJSMap(ctx, map) {
635
+ for (const {
636
+ source
637
+ } of this.value.items) {
638
+ if (!(source instanceof YAMLMap)) throw new Error('Merge sources must be maps');
639
+ const srcMap = source.toJSON(null, ctx, Map);
640
+
641
+ for (const [key, value] of srcMap) {
642
+ if (map instanceof Map) {
643
+ if (!map.has(key)) map.set(key, value);
644
+ } else if (map instanceof Set) {
645
+ map.add(key);
646
+ } else {
647
+ if (!Object.prototype.hasOwnProperty.call(map, key)) map[key] = value;
648
+ }
649
+ }
650
+ }
651
+
652
+ return map;
653
+ }
654
+
655
+ toString(ctx, onComment) {
656
+ const seq = this.value;
657
+ if (seq.items.length > 1) return super.toString(ctx, onComment);
658
+ this.value = seq.items[0];
659
+ const str = super.toString(ctx, onComment);
660
+ this.value = seq;
661
+ return str;
662
+ }
663
+
664
+ }
665
+
666
+ const binaryOptions = {
667
+ defaultType: PlainValue.Type.BLOCK_LITERAL,
668
+ lineWidth: 76
669
+ };
670
+ const boolOptions = {
671
+ trueStr: 'true',
672
+ falseStr: 'false'
673
+ };
674
+ const intOptions = {
675
+ asBigInt: false
676
+ };
677
+ const nullOptions = {
678
+ nullStr: 'null'
679
+ };
680
+ const strOptions = {
681
+ defaultType: PlainValue.Type.PLAIN,
682
+ doubleQuoted: {
683
+ jsonEncoding: false,
684
+ minMultiLineLength: 40
685
+ },
686
+ fold: {
687
+ lineWidth: 80,
688
+ minContentWidth: 20
689
+ }
690
+ };
691
+
692
+ function resolveScalar(str, tags, scalarFallback) {
693
+ for (const {
694
+ format,
695
+ test,
696
+ resolve
697
+ } of tags) {
698
+ if (test) {
699
+ const match = str.match(test);
700
+
701
+ if (match) {
702
+ let res = resolve.apply(null, match);
703
+ if (!(res instanceof Scalar)) res = new Scalar(res);
704
+ if (format) res.format = format;
705
+ return res;
706
+ }
707
+ }
708
+ }
709
+
710
+ if (scalarFallback) str = scalarFallback(str);
711
+ return new Scalar(str);
712
+ }
713
+
714
+ const FOLD_FLOW = 'flow';
715
+ const FOLD_BLOCK = 'block';
716
+ const FOLD_QUOTED = 'quoted'; // presumes i+1 is at the start of a line
717
+ // returns index of last newline in more-indented block
718
+
719
+ const consumeMoreIndentedLines = (text, i) => {
720
+ let ch = text[i + 1];
721
+
722
+ while (ch === ' ' || ch === '\t') {
723
+ do {
724
+ ch = text[i += 1];
725
+ } while (ch && ch !== '\n');
726
+
727
+ ch = text[i + 1];
728
+ }
729
+
730
+ return i;
731
+ };
732
+ /**
733
+ * Tries to keep input at up to `lineWidth` characters, splitting only on spaces
734
+ * not followed by newlines or spaces unless `mode` is `'quoted'`. Lines are
735
+ * terminated with `\n` and started with `indent`.
736
+ *
737
+ * @param {string} text
738
+ * @param {string} indent
739
+ * @param {string} [mode='flow'] `'block'` prevents more-indented lines
740
+ * from being folded; `'quoted'` allows for `\` escapes, including escaped
741
+ * newlines
742
+ * @param {Object} options
743
+ * @param {number} [options.indentAtStart] Accounts for leading contents on
744
+ * the first line, defaulting to `indent.length`
745
+ * @param {number} [options.lineWidth=80]
746
+ * @param {number} [options.minContentWidth=20] Allow highly indented lines to
747
+ * stretch the line width
748
+ * @param {function} options.onFold Called once if the text is folded
749
+ * @param {function} options.onFold Called once if any line of text exceeds
750
+ * lineWidth characters
751
+ */
752
+
753
+
754
+ function foldFlowLines(text, indent, mode, {
755
+ indentAtStart,
756
+ lineWidth = 80,
757
+ minContentWidth = 20,
758
+ onFold,
759
+ onOverflow
760
+ }) {
761
+ if (!lineWidth || lineWidth < 0) return text;
762
+ const endStep = Math.max(1 + minContentWidth, 1 + lineWidth - indent.length);
763
+ if (text.length <= endStep) return text;
764
+ const folds = [];
765
+ const escapedFolds = {};
766
+ let end = lineWidth - (typeof indentAtStart === 'number' ? indentAtStart : indent.length);
767
+ let split = undefined;
768
+ let prev = undefined;
769
+ let overflow = false;
770
+ let i = -1;
771
+
772
+ if (mode === FOLD_BLOCK) {
773
+ i = consumeMoreIndentedLines(text, i);
774
+ if (i !== -1) end = i + endStep;
775
+ }
776
+
777
+ for (let ch; ch = text[i += 1];) {
778
+ if (mode === FOLD_QUOTED && ch === '\\') {
779
+ switch (text[i + 1]) {
780
+ case 'x':
781
+ i += 3;
782
+ break;
783
+
784
+ case 'u':
785
+ i += 5;
786
+ break;
787
+
788
+ case 'U':
789
+ i += 9;
790
+ break;
791
+
792
+ default:
793
+ i += 1;
794
+ }
795
+ }
796
+
797
+ if (ch === '\n') {
798
+ if (mode === FOLD_BLOCK) i = consumeMoreIndentedLines(text, i);
799
+ end = i + endStep;
800
+ split = undefined;
801
+ } else {
802
+ if (ch === ' ' && prev && prev !== ' ' && prev !== '\n' && prev !== '\t') {
803
+ // space surrounded by non-space can be replaced with newline + indent
804
+ const next = text[i + 1];
805
+ if (next && next !== ' ' && next !== '\n' && next !== '\t') split = i;
806
+ }
807
+
808
+ if (i >= end) {
809
+ if (split) {
810
+ folds.push(split);
811
+ end = split + endStep;
812
+ split = undefined;
813
+ } else if (mode === FOLD_QUOTED) {
814
+ // white-space collected at end may stretch past lineWidth
815
+ while (prev === ' ' || prev === '\t') {
816
+ prev = ch;
817
+ ch = text[i += 1];
818
+ overflow = true;
819
+ } // i - 2 accounts for not-dropped last char + newline-escaping \
820
+
821
+
822
+ folds.push(i - 2);
823
+ escapedFolds[i - 2] = true;
824
+ end = i - 2 + endStep;
825
+ split = undefined;
826
+ } else {
827
+ overflow = true;
828
+ }
829
+ }
830
+ }
831
+
832
+ prev = ch;
833
+ }
834
+
835
+ if (overflow && onOverflow) onOverflow();
836
+ if (folds.length === 0) return text;
837
+ if (onFold) onFold();
838
+ let res = text.slice(0, folds[0]);
839
+
840
+ for (let i = 0; i < folds.length; ++i) {
841
+ const fold = folds[i];
842
+ const end = folds[i + 1] || text.length;
843
+ if (mode === FOLD_QUOTED && escapedFolds[fold]) res += `${text[fold]}\\`;
844
+ res += `\n${indent}${text.slice(fold + 1, end)}`;
845
+ }
846
+
847
+ return res;
848
+ }
849
+
850
+ const getFoldOptions = ({
851
+ indentAtStart
852
+ }) => indentAtStart ? Object.assign({
853
+ indentAtStart
854
+ }, strOptions.fold) : strOptions.fold; // Also checks for lines starting with %, as parsing the output as YAML 1.1 will
855
+ // presume that's starting a new document.
856
+
857
+
858
+ const containsDocumentMarker = str => /^(%|---|\.\.\.)/m.test(str);
859
+
860
+ function lineLengthOverLimit(str, limit) {
861
+ const strLen = str.length;
862
+ if (strLen <= limit) return false;
863
+
864
+ for (let i = 0, start = 0; i < strLen; ++i) {
865
+ if (str[i] === '\n') {
866
+ if (i - start > limit) return true;
867
+ start = i + 1;
868
+ if (strLen - start <= limit) return false;
869
+ }
870
+ }
871
+
872
+ return true;
873
+ }
874
+
875
+ function doubleQuotedString(value, ctx) {
876
+ const {
877
+ implicitKey
878
+ } = ctx;
879
+ const {
880
+ jsonEncoding,
881
+ minMultiLineLength
882
+ } = strOptions.doubleQuoted;
883
+ const json = JSON.stringify(value);
884
+ if (jsonEncoding) return json;
885
+ const indent = ctx.indent || (containsDocumentMarker(value) ? ' ' : '');
886
+ let str = '';
887
+ let start = 0;
888
+
889
+ for (let i = 0, ch = json[i]; ch; ch = json[++i]) {
890
+ if (ch === ' ' && json[i + 1] === '\\' && json[i + 2] === 'n') {
891
+ // space before newline needs to be escaped to not be folded
892
+ str += json.slice(start, i) + '\\ ';
893
+ i += 1;
894
+ start = i;
895
+ ch = '\\';
896
+ }
897
+
898
+ if (ch === '\\') switch (json[i + 1]) {
899
+ case 'u':
900
+ {
901
+ str += json.slice(start, i);
902
+ const code = json.substr(i + 2, 4);
903
+
904
+ switch (code) {
905
+ case '0000':
906
+ str += '\\0';
907
+ break;
908
+
909
+ case '0007':
910
+ str += '\\a';
911
+ break;
912
+
913
+ case '000b':
914
+ str += '\\v';
915
+ break;
916
+
917
+ case '001b':
918
+ str += '\\e';
919
+ break;
920
+
921
+ case '0085':
922
+ str += '\\N';
923
+ break;
924
+
925
+ case '00a0':
926
+ str += '\\_';
927
+ break;
928
+
929
+ case '2028':
930
+ str += '\\L';
931
+ break;
932
+
933
+ case '2029':
934
+ str += '\\P';
935
+ break;
936
+
937
+ default:
938
+ if (code.substr(0, 2) === '00') str += '\\x' + code.substr(2);else str += json.substr(i, 6);
939
+ }
940
+
941
+ i += 5;
942
+ start = i + 1;
943
+ }
944
+ break;
945
+
946
+ case 'n':
947
+ if (implicitKey || json[i + 2] === '"' || json.length < minMultiLineLength) {
948
+ i += 1;
949
+ } else {
950
+ // folding will eat first newline
951
+ str += json.slice(start, i) + '\n\n';
952
+
953
+ while (json[i + 2] === '\\' && json[i + 3] === 'n' && json[i + 4] !== '"') {
954
+ str += '\n';
955
+ i += 2;
956
+ }
957
+
958
+ str += indent; // space after newline needs to be escaped to not be folded
959
+
960
+ if (json[i + 2] === ' ') str += '\\';
961
+ i += 1;
962
+ start = i + 1;
963
+ }
964
+
965
+ break;
966
+
967
+ default:
968
+ i += 1;
969
+ }
970
+ }
971
+
972
+ str = start ? str + json.slice(start) : json;
973
+ return implicitKey ? str : foldFlowLines(str, indent, FOLD_QUOTED, getFoldOptions(ctx));
974
+ }
975
+
976
+ function singleQuotedString(value, ctx) {
977
+ if (ctx.implicitKey) {
978
+ if (/\n/.test(value)) return doubleQuotedString(value, ctx);
979
+ } else {
980
+ // single quoted string can't have leading or trailing whitespace around newline
981
+ if (/[ \t]\n|\n[ \t]/.test(value)) return doubleQuotedString(value, ctx);
982
+ }
983
+
984
+ const indent = ctx.indent || (containsDocumentMarker(value) ? ' ' : '');
985
+ const res = "'" + value.replace(/'/g, "''").replace(/\n+/g, `$&\n${indent}`) + "'";
986
+ return ctx.implicitKey ? res : foldFlowLines(res, indent, FOLD_FLOW, getFoldOptions(ctx));
987
+ }
988
+
989
+ function blockString({
990
+ comment,
991
+ type,
992
+ value
993
+ }, ctx, onComment, onChompKeep) {
994
+ // 1. Block can't end in whitespace unless the last line is non-empty.
995
+ // 2. Strings consisting of only whitespace are best rendered explicitly.
996
+ if (/\n[\t ]+$/.test(value) || /^\s*$/.test(value)) {
997
+ return doubleQuotedString(value, ctx);
998
+ }
999
+
1000
+ const indent = ctx.indent || (ctx.forceBlockIndent || containsDocumentMarker(value) ? ' ' : '');
1001
+ const indentSize = indent ? '2' : '1'; // root is at -1
1002
+
1003
+ const literal = type === PlainValue.Type.BLOCK_FOLDED ? false : type === PlainValue.Type.BLOCK_LITERAL ? true : !lineLengthOverLimit(value, strOptions.fold.lineWidth - indent.length);
1004
+ let header = literal ? '|' : '>';
1005
+ if (!value) return header + '\n';
1006
+ let wsStart = '';
1007
+ let wsEnd = '';
1008
+ value = value.replace(/[\n\t ]*$/, ws => {
1009
+ const n = ws.indexOf('\n');
1010
+
1011
+ if (n === -1) {
1012
+ header += '-'; // strip
1013
+ } else if (value === ws || n !== ws.length - 1) {
1014
+ header += '+'; // keep
1015
+
1016
+ if (onChompKeep) onChompKeep();
1017
+ }
1018
+
1019
+ wsEnd = ws.replace(/\n$/, '');
1020
+ return '';
1021
+ }).replace(/^[\n ]*/, ws => {
1022
+ if (ws.indexOf(' ') !== -1) header += indentSize;
1023
+ const m = ws.match(/ +$/);
1024
+
1025
+ if (m) {
1026
+ wsStart = ws.slice(0, -m[0].length);
1027
+ return m[0];
1028
+ } else {
1029
+ wsStart = ws;
1030
+ return '';
1031
+ }
1032
+ });
1033
+ if (wsEnd) wsEnd = wsEnd.replace(/\n+(?!\n|$)/g, `$&${indent}`);
1034
+ if (wsStart) wsStart = wsStart.replace(/\n+/g, `$&${indent}`);
1035
+
1036
+ if (comment) {
1037
+ header += ' #' + comment.replace(/ ?[\r\n]+/g, ' ');
1038
+ if (onComment) onComment();
1039
+ }
1040
+
1041
+ if (!value) return `${header}${indentSize}\n${indent}${wsEnd}`;
1042
+
1043
+ if (literal) {
1044
+ value = value.replace(/\n+/g, `$&${indent}`);
1045
+ return `${header}\n${indent}${wsStart}${value}${wsEnd}`;
1046
+ }
1047
+
1048
+ value = value.replace(/\n+/g, '\n$&').replace(/(?:^|\n)([\t ].*)(?:([\n\t ]*)\n(?![\n\t ]))?/g, '$1$2') // more-indented lines aren't folded
1049
+ // ^ ind.line ^ empty ^ capture next empty lines only at end of indent
1050
+ .replace(/\n+/g, `$&${indent}`);
1051
+ const body = foldFlowLines(`${wsStart}${value}${wsEnd}`, indent, FOLD_BLOCK, strOptions.fold);
1052
+ return `${header}\n${indent}${body}`;
1053
+ }
1054
+
1055
+ function plainString(item, ctx, onComment, onChompKeep) {
1056
+ const {
1057
+ comment,
1058
+ type,
1059
+ value
1060
+ } = item;
1061
+ const {
1062
+ actualString,
1063
+ implicitKey,
1064
+ indent,
1065
+ inFlow
1066
+ } = ctx;
1067
+
1068
+ if (implicitKey && /[\n[\]{},]/.test(value) || inFlow && /[[\]{},]/.test(value)) {
1069
+ return doubleQuotedString(value, ctx);
1070
+ }
1071
+
1072
+ if (!value || /^[\n\t ,[\]{}#&*!|>'"%@`]|^[?-]$|^[?-][ \t]|[\n:][ \t]|[ \t]\n|[\n\t ]#|[\n\t :]$/.test(value)) {
1073
+ // not allowed:
1074
+ // - empty string, '-' or '?'
1075
+ // - start with an indicator character (except [?:-]) or /[?-] /
1076
+ // - '\n ', ': ' or ' \n' anywhere
1077
+ // - '#' not preceded by a non-space char
1078
+ // - end with ' ' or ':'
1079
+ return implicitKey || inFlow || value.indexOf('\n') === -1 ? value.indexOf('"') !== -1 && value.indexOf("'") === -1 ? singleQuotedString(value, ctx) : doubleQuotedString(value, ctx) : blockString(item, ctx, onComment, onChompKeep);
1080
+ }
1081
+
1082
+ if (!implicitKey && !inFlow && type !== PlainValue.Type.PLAIN && value.indexOf('\n') !== -1) {
1083
+ // Where allowed & type not set explicitly, prefer block style for multiline strings
1084
+ return blockString(item, ctx, onComment, onChompKeep);
1085
+ }
1086
+
1087
+ if (indent === '' && containsDocumentMarker(value)) {
1088
+ ctx.forceBlockIndent = true;
1089
+ return blockString(item, ctx, onComment, onChompKeep);
1090
+ }
1091
+
1092
+ const str = value.replace(/\n+/g, `$&\n${indent}`); // Verify that output will be parsed as a string, as e.g. plain numbers and
1093
+ // booleans get parsed with those types in v1.2 (e.g. '42', 'true' & '0.9e-3'),
1094
+ // and others in v1.1.
1095
+
1096
+ if (actualString) {
1097
+ const {
1098
+ tags
1099
+ } = ctx.doc.schema;
1100
+ const resolved = resolveScalar(str, tags, tags.scalarFallback).value;
1101
+ if (typeof resolved !== 'string') return doubleQuotedString(value, ctx);
1102
+ }
1103
+
1104
+ const body = implicitKey ? str : foldFlowLines(str, indent, FOLD_FLOW, getFoldOptions(ctx));
1105
+
1106
+ if (comment && !inFlow && (body.indexOf('\n') !== -1 || comment.indexOf('\n') !== -1)) {
1107
+ if (onComment) onComment();
1108
+ return addCommentBefore(body, indent, comment);
1109
+ }
1110
+
1111
+ return body;
1112
+ }
1113
+
1114
+ function stringifyString(item, ctx, onComment, onChompKeep) {
1115
+ const {
1116
+ defaultType
1117
+ } = strOptions;
1118
+ const {
1119
+ implicitKey,
1120
+ inFlow
1121
+ } = ctx;
1122
+ let {
1123
+ type,
1124
+ value
1125
+ } = item;
1126
+
1127
+ if (typeof value !== 'string') {
1128
+ value = String(value);
1129
+ item = Object.assign({}, item, {
1130
+ value
1131
+ });
1132
+ }
1133
+
1134
+ const _stringify = _type => {
1135
+ switch (_type) {
1136
+ case PlainValue.Type.BLOCK_FOLDED:
1137
+ case PlainValue.Type.BLOCK_LITERAL:
1138
+ return blockString(item, ctx, onComment, onChompKeep);
1139
+
1140
+ case PlainValue.Type.QUOTE_DOUBLE:
1141
+ return doubleQuotedString(value, ctx);
1142
+
1143
+ case PlainValue.Type.QUOTE_SINGLE:
1144
+ return singleQuotedString(value, ctx);
1145
+
1146
+ case PlainValue.Type.PLAIN:
1147
+ return plainString(item, ctx, onComment, onChompKeep);
1148
+
1149
+ default:
1150
+ return null;
1151
+ }
1152
+ };
1153
+
1154
+ if (type !== PlainValue.Type.QUOTE_DOUBLE && /[\x00-\x08\x0b-\x1f\x7f-\x9f]/.test(value)) {
1155
+ // force double quotes on control characters
1156
+ type = PlainValue.Type.QUOTE_DOUBLE;
1157
+ } else if ((implicitKey || inFlow) && (type === PlainValue.Type.BLOCK_FOLDED || type === PlainValue.Type.BLOCK_LITERAL)) {
1158
+ // should not happen; blocks are not valid inside flow containers
1159
+ type = PlainValue.Type.QUOTE_DOUBLE;
1160
+ }
1161
+
1162
+ let res = _stringify(type);
1163
+
1164
+ if (res === null) {
1165
+ res = _stringify(defaultType);
1166
+ if (res === null) throw new Error(`Unsupported default string type ${defaultType}`);
1167
+ }
1168
+
1169
+ return res;
1170
+ }
1171
+
1172
+ function stringifyNumber({
1173
+ format,
1174
+ minFractionDigits,
1175
+ tag,
1176
+ value
1177
+ }) {
1178
+ if (typeof value === 'bigint') return String(value);
1179
+ if (!isFinite(value)) return isNaN(value) ? '.nan' : value < 0 ? '-.inf' : '.inf';
1180
+ let n = JSON.stringify(value);
1181
+
1182
+ if (!format && minFractionDigits && (!tag || tag === 'tag:yaml.org,2002:float') && /^\d/.test(n)) {
1183
+ let i = n.indexOf('.');
1184
+
1185
+ if (i < 0) {
1186
+ i = n.length;
1187
+ n += '.';
1188
+ }
1189
+
1190
+ let d = minFractionDigits - (n.length - i - 1);
1191
+
1192
+ while (d-- > 0) n += '0';
1193
+ }
1194
+
1195
+ return n;
1196
+ }
1197
+
1198
+ function checkFlowCollectionEnd(errors, cst) {
1199
+ let char, name;
1200
+
1201
+ switch (cst.type) {
1202
+ case PlainValue.Type.FLOW_MAP:
1203
+ char = '}';
1204
+ name = 'flow map';
1205
+ break;
1206
+
1207
+ case PlainValue.Type.FLOW_SEQ:
1208
+ char = ']';
1209
+ name = 'flow sequence';
1210
+ break;
1211
+
1212
+ default:
1213
+ errors.push(new PlainValue.YAMLSemanticError(cst, 'Not a flow collection!?'));
1214
+ return;
1215
+ }
1216
+
1217
+ let lastItem;
1218
+
1219
+ for (let i = cst.items.length - 1; i >= 0; --i) {
1220
+ const item = cst.items[i];
1221
+
1222
+ if (!item || item.type !== PlainValue.Type.COMMENT) {
1223
+ lastItem = item;
1224
+ break;
1225
+ }
1226
+ }
1227
+
1228
+ if (lastItem && lastItem.char !== char) {
1229
+ const msg = `Expected ${name} to end with ${char}`;
1230
+ let err;
1231
+
1232
+ if (typeof lastItem.offset === 'number') {
1233
+ err = new PlainValue.YAMLSemanticError(cst, msg);
1234
+ err.offset = lastItem.offset + 1;
1235
+ } else {
1236
+ err = new PlainValue.YAMLSemanticError(lastItem, msg);
1237
+ if (lastItem.range && lastItem.range.end) err.offset = lastItem.range.end - lastItem.range.start;
1238
+ }
1239
+
1240
+ errors.push(err);
1241
+ }
1242
+ }
1243
+ function checkFlowCommentSpace(errors, comment) {
1244
+ const prev = comment.context.src[comment.range.start - 1];
1245
+
1246
+ if (prev !== '\n' && prev !== '\t' && prev !== ' ') {
1247
+ const msg = 'Comments must be separated from other tokens by white space characters';
1248
+ errors.push(new PlainValue.YAMLSemanticError(comment, msg));
1249
+ }
1250
+ }
1251
+ function getLongKeyError(source, key) {
1252
+ const sk = String(key);
1253
+ const k = sk.substr(0, 8) + '...' + sk.substr(-8);
1254
+ return new PlainValue.YAMLSemanticError(source, `The "${k}" key is too long`);
1255
+ }
1256
+ function resolveComments(collection, comments) {
1257
+ for (const {
1258
+ afterKey,
1259
+ before,
1260
+ comment
1261
+ } of comments) {
1262
+ let item = collection.items[before];
1263
+
1264
+ if (!item) {
1265
+ if (comment !== undefined) {
1266
+ if (collection.comment) collection.comment += '\n' + comment;else collection.comment = comment;
1267
+ }
1268
+ } else {
1269
+ if (afterKey && item.value) item = item.value;
1270
+
1271
+ if (comment === undefined) {
1272
+ if (afterKey || !item.commentBefore) item.spaceBefore = true;
1273
+ } else {
1274
+ if (item.commentBefore) item.commentBefore += '\n' + comment;else item.commentBefore = comment;
1275
+ }
1276
+ }
1277
+ }
1278
+ }
1279
+
1280
+ // on error, will return { str: string, errors: Error[] }
1281
+ function resolveString(doc, node) {
1282
+ const res = node.strValue;
1283
+ if (!res) return '';
1284
+ if (typeof res === 'string') return res;
1285
+ res.errors.forEach(error => {
1286
+ if (!error.source) error.source = node;
1287
+ doc.errors.push(error);
1288
+ });
1289
+ return res.str;
1290
+ }
1291
+
1292
+ function resolveTagHandle(doc, node) {
1293
+ const {
1294
+ handle,
1295
+ suffix
1296
+ } = node.tag;
1297
+ let prefix = doc.tagPrefixes.find(p => p.handle === handle);
1298
+
1299
+ if (!prefix) {
1300
+ const dtp = doc.getDefaults().tagPrefixes;
1301
+ if (dtp) prefix = dtp.find(p => p.handle === handle);
1302
+ if (!prefix) throw new PlainValue.YAMLSemanticError(node, `The ${handle} tag handle is non-default and was not declared.`);
1303
+ }
1304
+
1305
+ if (!suffix) throw new PlainValue.YAMLSemanticError(node, `The ${handle} tag has no suffix.`);
1306
+
1307
+ if (handle === '!' && (doc.version || doc.options.version) === '1.0') {
1308
+ if (suffix[0] === '^') {
1309
+ doc.warnings.push(new PlainValue.YAMLWarning(node, 'YAML 1.0 ^ tag expansion is not supported'));
1310
+ return suffix;
1311
+ }
1312
+
1313
+ if (/[:/]/.test(suffix)) {
1314
+ // word/foo -> tag:word.yaml.org,2002:foo
1315
+ const vocab = suffix.match(/^([a-z0-9-]+)\/(.*)/i);
1316
+ return vocab ? `tag:${vocab[1]}.yaml.org,2002:${vocab[2]}` : `tag:${suffix}`;
1317
+ }
1318
+ }
1319
+
1320
+ return prefix.prefix + decodeURIComponent(suffix);
1321
+ }
1322
+
1323
+ function resolveTagName(doc, node) {
1324
+ const {
1325
+ tag,
1326
+ type
1327
+ } = node;
1328
+ let nonSpecific = false;
1329
+
1330
+ if (tag) {
1331
+ const {
1332
+ handle,
1333
+ suffix,
1334
+ verbatim
1335
+ } = tag;
1336
+
1337
+ if (verbatim) {
1338
+ if (verbatim !== '!' && verbatim !== '!!') return verbatim;
1339
+ const msg = `Verbatim tags aren't resolved, so ${verbatim} is invalid.`;
1340
+ doc.errors.push(new PlainValue.YAMLSemanticError(node, msg));
1341
+ } else if (handle === '!' && !suffix) {
1342
+ nonSpecific = true;
1343
+ } else {
1344
+ try {
1345
+ return resolveTagHandle(doc, node);
1346
+ } catch (error) {
1347
+ doc.errors.push(error);
1348
+ }
1349
+ }
1350
+ }
1351
+
1352
+ switch (type) {
1353
+ case PlainValue.Type.BLOCK_FOLDED:
1354
+ case PlainValue.Type.BLOCK_LITERAL:
1355
+ case PlainValue.Type.QUOTE_DOUBLE:
1356
+ case PlainValue.Type.QUOTE_SINGLE:
1357
+ return PlainValue.defaultTags.STR;
1358
+
1359
+ case PlainValue.Type.FLOW_MAP:
1360
+ case PlainValue.Type.MAP:
1361
+ return PlainValue.defaultTags.MAP;
1362
+
1363
+ case PlainValue.Type.FLOW_SEQ:
1364
+ case PlainValue.Type.SEQ:
1365
+ return PlainValue.defaultTags.SEQ;
1366
+
1367
+ case PlainValue.Type.PLAIN:
1368
+ return nonSpecific ? PlainValue.defaultTags.STR : null;
1369
+
1370
+ default:
1371
+ return null;
1372
+ }
1373
+ }
1374
+
1375
+ function resolveByTagName(doc, node, tagName) {
1376
+ const {
1377
+ tags
1378
+ } = doc.schema;
1379
+ const matchWithTest = [];
1380
+
1381
+ for (const tag of tags) {
1382
+ if (tag.tag === tagName) {
1383
+ if (tag.test) matchWithTest.push(tag);else {
1384
+ const res = tag.resolve(doc, node);
1385
+ return res instanceof Collection ? res : new Scalar(res);
1386
+ }
1387
+ }
1388
+ }
1389
+
1390
+ const str = resolveString(doc, node);
1391
+ if (typeof str === 'string' && matchWithTest.length > 0) return resolveScalar(str, matchWithTest, tags.scalarFallback);
1392
+ return null;
1393
+ }
1394
+
1395
+ function getFallbackTagName({
1396
+ type
1397
+ }) {
1398
+ switch (type) {
1399
+ case PlainValue.Type.FLOW_MAP:
1400
+ case PlainValue.Type.MAP:
1401
+ return PlainValue.defaultTags.MAP;
1402
+
1403
+ case PlainValue.Type.FLOW_SEQ:
1404
+ case PlainValue.Type.SEQ:
1405
+ return PlainValue.defaultTags.SEQ;
1406
+
1407
+ default:
1408
+ return PlainValue.defaultTags.STR;
1409
+ }
1410
+ }
1411
+
1412
+ function resolveTag(doc, node, tagName) {
1413
+ try {
1414
+ const res = resolveByTagName(doc, node, tagName);
1415
+
1416
+ if (res) {
1417
+ if (tagName && node.tag) res.tag = tagName;
1418
+ return res;
1419
+ }
1420
+ } catch (error) {
1421
+ /* istanbul ignore if */
1422
+ if (!error.source) error.source = node;
1423
+ doc.errors.push(error);
1424
+ return null;
1425
+ }
1426
+
1427
+ try {
1428
+ const fallback = getFallbackTagName(node);
1429
+ if (!fallback) throw new Error(`The tag ${tagName} is unavailable`);
1430
+ const msg = `The tag ${tagName} is unavailable, falling back to ${fallback}`;
1431
+ doc.warnings.push(new PlainValue.YAMLWarning(node, msg));
1432
+ const res = resolveByTagName(doc, node, fallback);
1433
+ res.tag = tagName;
1434
+ return res;
1435
+ } catch (error) {
1436
+ const refError = new PlainValue.YAMLReferenceError(node, error.message);
1437
+ refError.stack = error.stack;
1438
+ doc.errors.push(refError);
1439
+ return null;
1440
+ }
1441
+ }
1442
+
1443
+ const isCollectionItem = node => {
1444
+ if (!node) return false;
1445
+ const {
1446
+ type
1447
+ } = node;
1448
+ return type === PlainValue.Type.MAP_KEY || type === PlainValue.Type.MAP_VALUE || type === PlainValue.Type.SEQ_ITEM;
1449
+ };
1450
+
1451
+ function resolveNodeProps(errors, node) {
1452
+ const comments = {
1453
+ before: [],
1454
+ after: []
1455
+ };
1456
+ let hasAnchor = false;
1457
+ let hasTag = false;
1458
+ const props = isCollectionItem(node.context.parent) ? node.context.parent.props.concat(node.props) : node.props;
1459
+
1460
+ for (const {
1461
+ start,
1462
+ end
1463
+ } of props) {
1464
+ switch (node.context.src[start]) {
1465
+ case PlainValue.Char.COMMENT:
1466
+ {
1467
+ if (!node.commentHasRequiredWhitespace(start)) {
1468
+ const msg = 'Comments must be separated from other tokens by white space characters';
1469
+ errors.push(new PlainValue.YAMLSemanticError(node, msg));
1470
+ }
1471
+
1472
+ const {
1473
+ header,
1474
+ valueRange
1475
+ } = node;
1476
+ const cc = valueRange && (start > valueRange.start || header && start > header.start) ? comments.after : comments.before;
1477
+ cc.push(node.context.src.slice(start + 1, end));
1478
+ break;
1479
+ }
1480
+ // Actual anchor & tag resolution is handled by schema, here we just complain
1481
+
1482
+ case PlainValue.Char.ANCHOR:
1483
+ if (hasAnchor) {
1484
+ const msg = 'A node can have at most one anchor';
1485
+ errors.push(new PlainValue.YAMLSemanticError(node, msg));
1486
+ }
1487
+
1488
+ hasAnchor = true;
1489
+ break;
1490
+
1491
+ case PlainValue.Char.TAG:
1492
+ if (hasTag) {
1493
+ const msg = 'A node can have at most one tag';
1494
+ errors.push(new PlainValue.YAMLSemanticError(node, msg));
1495
+ }
1496
+
1497
+ hasTag = true;
1498
+ break;
1499
+ }
1500
+ }
1501
+
1502
+ return {
1503
+ comments,
1504
+ hasAnchor,
1505
+ hasTag
1506
+ };
1507
+ }
1508
+
1509
+ function resolveNodeValue(doc, node) {
1510
+ const {
1511
+ anchors,
1512
+ errors,
1513
+ schema
1514
+ } = doc;
1515
+
1516
+ if (node.type === PlainValue.Type.ALIAS) {
1517
+ const name = node.rawValue;
1518
+ const src = anchors.getNode(name);
1519
+
1520
+ if (!src) {
1521
+ const msg = `Aliased anchor not found: ${name}`;
1522
+ errors.push(new PlainValue.YAMLReferenceError(node, msg));
1523
+ return null;
1524
+ } // Lazy resolution for circular references
1525
+
1526
+
1527
+ const res = new Alias(src);
1528
+
1529
+ anchors._cstAliases.push(res);
1530
+
1531
+ return res;
1532
+ }
1533
+
1534
+ const tagName = resolveTagName(doc, node);
1535
+ if (tagName) return resolveTag(doc, node, tagName);
1536
+
1537
+ if (node.type !== PlainValue.Type.PLAIN) {
1538
+ const msg = `Failed to resolve ${node.type} node here`;
1539
+ errors.push(new PlainValue.YAMLSyntaxError(node, msg));
1540
+ return null;
1541
+ }
1542
+
1543
+ try {
1544
+ const str = resolveString(doc, node);
1545
+ return resolveScalar(str, schema.tags, schema.tags.scalarFallback);
1546
+ } catch (error) {
1547
+ if (!error.source) error.source = node;
1548
+ errors.push(error);
1549
+ return null;
1550
+ }
1551
+ } // sets node.resolved on success
1552
+
1553
+
1554
+ function resolveNode(doc, node) {
1555
+ if (!node) return null;
1556
+ if (node.error) doc.errors.push(node.error);
1557
+ const {
1558
+ comments,
1559
+ hasAnchor,
1560
+ hasTag
1561
+ } = resolveNodeProps(doc.errors, node);
1562
+
1563
+ if (hasAnchor) {
1564
+ const {
1565
+ anchors
1566
+ } = doc;
1567
+ const name = node.anchor;
1568
+ const prev = anchors.getNode(name); // At this point, aliases for any preceding node with the same anchor
1569
+ // name have already been resolved, so it may safely be renamed.
1570
+
1571
+ if (prev) anchors.map[anchors.newName(name)] = prev; // During parsing, we need to store the CST node in anchors.map as
1572
+ // anchors need to be available during resolution to allow for
1573
+ // circular references.
1574
+
1575
+ anchors.map[name] = node;
1576
+ }
1577
+
1578
+ if (node.type === PlainValue.Type.ALIAS && (hasAnchor || hasTag)) {
1579
+ const msg = 'An alias node must not specify any properties';
1580
+ doc.errors.push(new PlainValue.YAMLSemanticError(node, msg));
1581
+ }
1582
+
1583
+ const res = resolveNodeValue(doc, node);
1584
+
1585
+ if (res) {
1586
+ res.range = [node.range.start, node.range.end];
1587
+ if (doc.options.keepCstNodes) res.cstNode = node;
1588
+ if (doc.options.keepNodeTypes) res.type = node.type;
1589
+ const cb = comments.before.join('\n');
1590
+
1591
+ if (cb) {
1592
+ res.commentBefore = res.commentBefore ? `${res.commentBefore}\n${cb}` : cb;
1593
+ }
1594
+
1595
+ const ca = comments.after.join('\n');
1596
+ if (ca) res.comment = res.comment ? `${res.comment}\n${ca}` : ca;
1597
+ }
1598
+
1599
+ return node.resolved = res;
1600
+ }
1601
+
1602
+ function resolveMap(doc, cst) {
1603
+ if (cst.type !== PlainValue.Type.MAP && cst.type !== PlainValue.Type.FLOW_MAP) {
1604
+ const msg = `A ${cst.type} node cannot be resolved as a mapping`;
1605
+ doc.errors.push(new PlainValue.YAMLSyntaxError(cst, msg));
1606
+ return null;
1607
+ }
1608
+
1609
+ const {
1610
+ comments,
1611
+ items
1612
+ } = cst.type === PlainValue.Type.FLOW_MAP ? resolveFlowMapItems(doc, cst) : resolveBlockMapItems(doc, cst);
1613
+ const map = new YAMLMap();
1614
+ map.items = items;
1615
+ resolveComments(map, comments);
1616
+ let hasCollectionKey = false;
1617
+
1618
+ for (let i = 0; i < items.length; ++i) {
1619
+ const {
1620
+ key: iKey
1621
+ } = items[i];
1622
+ if (iKey instanceof Collection) hasCollectionKey = true;
1623
+
1624
+ if (doc.schema.merge && iKey && iKey.value === MERGE_KEY) {
1625
+ items[i] = new Merge(items[i]);
1626
+ const sources = items[i].value.items;
1627
+ let error = null;
1628
+ sources.some(node => {
1629
+ if (node instanceof Alias) {
1630
+ // During parsing, alias sources are CST nodes; to account for
1631
+ // circular references their resolved values can't be used here.
1632
+ const {
1633
+ type
1634
+ } = node.source;
1635
+ if (type === PlainValue.Type.MAP || type === PlainValue.Type.FLOW_MAP) return false;
1636
+ return error = 'Merge nodes aliases can only point to maps';
1637
+ }
1638
+
1639
+ return error = 'Merge nodes can only have Alias nodes as values';
1640
+ });
1641
+ if (error) doc.errors.push(new PlainValue.YAMLSemanticError(cst, error));
1642
+ } else {
1643
+ for (let j = i + 1; j < items.length; ++j) {
1644
+ const {
1645
+ key: jKey
1646
+ } = items[j];
1647
+
1648
+ if (iKey === jKey || iKey && jKey && Object.prototype.hasOwnProperty.call(iKey, 'value') && iKey.value === jKey.value) {
1649
+ const msg = `Map keys must be unique; "${iKey}" is repeated`;
1650
+ doc.errors.push(new PlainValue.YAMLSemanticError(cst, msg));
1651
+ break;
1652
+ }
1653
+ }
1654
+ }
1655
+ }
1656
+
1657
+ if (hasCollectionKey && !doc.options.mapAsMap) {
1658
+ const warn = 'Keys with collection values will be stringified as YAML due to JS Object restrictions. Use mapAsMap: true to avoid this.';
1659
+ doc.warnings.push(new PlainValue.YAMLWarning(cst, warn));
1660
+ }
1661
+
1662
+ cst.resolved = map;
1663
+ return map;
1664
+ }
1665
+
1666
+ const valueHasPairComment = ({
1667
+ context: {
1668
+ lineStart,
1669
+ node,
1670
+ src
1671
+ },
1672
+ props
1673
+ }) => {
1674
+ if (props.length === 0) return false;
1675
+ const {
1676
+ start
1677
+ } = props[0];
1678
+ if (node && start > node.valueRange.start) return false;
1679
+ if (src[start] !== PlainValue.Char.COMMENT) return false;
1680
+
1681
+ for (let i = lineStart; i < start; ++i) if (src[i] === '\n') return false;
1682
+
1683
+ return true;
1684
+ };
1685
+
1686
+ function resolvePairComment(item, pair) {
1687
+ if (!valueHasPairComment(item)) return;
1688
+ const comment = item.getPropValue(0, PlainValue.Char.COMMENT, true);
1689
+ let found = false;
1690
+ const cb = pair.value.commentBefore;
1691
+
1692
+ if (cb && cb.startsWith(comment)) {
1693
+ pair.value.commentBefore = cb.substr(comment.length + 1);
1694
+ found = true;
1695
+ } else {
1696
+ const cc = pair.value.comment;
1697
+
1698
+ if (!item.node && cc && cc.startsWith(comment)) {
1699
+ pair.value.comment = cc.substr(comment.length + 1);
1700
+ found = true;
1701
+ }
1702
+ }
1703
+
1704
+ if (found) pair.comment = comment;
1705
+ }
1706
+
1707
+ function resolveBlockMapItems(doc, cst) {
1708
+ const comments = [];
1709
+ const items = [];
1710
+ let key = undefined;
1711
+ let keyStart = null;
1712
+
1713
+ for (let i = 0; i < cst.items.length; ++i) {
1714
+ const item = cst.items[i];
1715
+
1716
+ switch (item.type) {
1717
+ case PlainValue.Type.BLANK_LINE:
1718
+ comments.push({
1719
+ afterKey: !!key,
1720
+ before: items.length
1721
+ });
1722
+ break;
1723
+
1724
+ case PlainValue.Type.COMMENT:
1725
+ comments.push({
1726
+ afterKey: !!key,
1727
+ before: items.length,
1728
+ comment: item.comment
1729
+ });
1730
+ break;
1731
+
1732
+ case PlainValue.Type.MAP_KEY:
1733
+ if (key !== undefined) items.push(new Pair(key));
1734
+ if (item.error) doc.errors.push(item.error);
1735
+ key = resolveNode(doc, item.node);
1736
+ keyStart = null;
1737
+ break;
1738
+
1739
+ case PlainValue.Type.MAP_VALUE:
1740
+ {
1741
+ if (key === undefined) key = null;
1742
+ if (item.error) doc.errors.push(item.error);
1743
+
1744
+ if (!item.context.atLineStart && item.node && item.node.type === PlainValue.Type.MAP && !item.node.context.atLineStart) {
1745
+ const msg = 'Nested mappings are not allowed in compact mappings';
1746
+ doc.errors.push(new PlainValue.YAMLSemanticError(item.node, msg));
1747
+ }
1748
+
1749
+ let valueNode = item.node;
1750
+
1751
+ if (!valueNode && item.props.length > 0) {
1752
+ // Comments on an empty mapping value need to be preserved, so we
1753
+ // need to construct a minimal empty node here to use instead of the
1754
+ // missing `item.node`. -- eemeli/yaml#19
1755
+ valueNode = new PlainValue.PlainValue(PlainValue.Type.PLAIN, []);
1756
+ valueNode.context = {
1757
+ parent: item,
1758
+ src: item.context.src
1759
+ };
1760
+ const pos = item.range.start + 1;
1761
+ valueNode.range = {
1762
+ start: pos,
1763
+ end: pos
1764
+ };
1765
+ valueNode.valueRange = {
1766
+ start: pos,
1767
+ end: pos
1768
+ };
1769
+
1770
+ if (typeof item.range.origStart === 'number') {
1771
+ const origPos = item.range.origStart + 1;
1772
+ valueNode.range.origStart = valueNode.range.origEnd = origPos;
1773
+ valueNode.valueRange.origStart = valueNode.valueRange.origEnd = origPos;
1774
+ }
1775
+ }
1776
+
1777
+ const pair = new Pair(key, resolveNode(doc, valueNode));
1778
+ resolvePairComment(item, pair);
1779
+ items.push(pair);
1780
+
1781
+ if (key && typeof keyStart === 'number') {
1782
+ if (item.range.start > keyStart + 1024) doc.errors.push(getLongKeyError(cst, key));
1783
+ }
1784
+
1785
+ key = undefined;
1786
+ keyStart = null;
1787
+ }
1788
+ break;
1789
+
1790
+ default:
1791
+ if (key !== undefined) items.push(new Pair(key));
1792
+ key = resolveNode(doc, item);
1793
+ keyStart = item.range.start;
1794
+ if (item.error) doc.errors.push(item.error);
1795
+
1796
+ next: for (let j = i + 1;; ++j) {
1797
+ const nextItem = cst.items[j];
1798
+
1799
+ switch (nextItem && nextItem.type) {
1800
+ case PlainValue.Type.BLANK_LINE:
1801
+ case PlainValue.Type.COMMENT:
1802
+ continue next;
1803
+
1804
+ case PlainValue.Type.MAP_VALUE:
1805
+ break next;
1806
+
1807
+ default:
1808
+ {
1809
+ const msg = 'Implicit map keys need to be followed by map values';
1810
+ doc.errors.push(new PlainValue.YAMLSemanticError(item, msg));
1811
+ break next;
1812
+ }
1813
+ }
1814
+ }
1815
+
1816
+ if (item.valueRangeContainsNewline) {
1817
+ const msg = 'Implicit map keys need to be on a single line';
1818
+ doc.errors.push(new PlainValue.YAMLSemanticError(item, msg));
1819
+ }
1820
+
1821
+ }
1822
+ }
1823
+
1824
+ if (key !== undefined) items.push(new Pair(key));
1825
+ return {
1826
+ comments,
1827
+ items
1828
+ };
1829
+ }
1830
+
1831
+ function resolveFlowMapItems(doc, cst) {
1832
+ const comments = [];
1833
+ const items = [];
1834
+ let key = undefined;
1835
+ let explicitKey = false;
1836
+ let next = '{';
1837
+
1838
+ for (let i = 0; i < cst.items.length; ++i) {
1839
+ const item = cst.items[i];
1840
+
1841
+ if (typeof item.char === 'string') {
1842
+ const {
1843
+ char,
1844
+ offset
1845
+ } = item;
1846
+
1847
+ if (char === '?' && key === undefined && !explicitKey) {
1848
+ explicitKey = true;
1849
+ next = ':';
1850
+ continue;
1851
+ }
1852
+
1853
+ if (char === ':') {
1854
+ if (key === undefined) key = null;
1855
+
1856
+ if (next === ':') {
1857
+ next = ',';
1858
+ continue;
1859
+ }
1860
+ } else {
1861
+ if (explicitKey) {
1862
+ if (key === undefined && char !== ',') key = null;
1863
+ explicitKey = false;
1864
+ }
1865
+
1866
+ if (key !== undefined) {
1867
+ items.push(new Pair(key));
1868
+ key = undefined;
1869
+
1870
+ if (char === ',') {
1871
+ next = ':';
1872
+ continue;
1873
+ }
1874
+ }
1875
+ }
1876
+
1877
+ if (char === '}') {
1878
+ if (i === cst.items.length - 1) continue;
1879
+ } else if (char === next) {
1880
+ next = ':';
1881
+ continue;
1882
+ }
1883
+
1884
+ const msg = `Flow map contains an unexpected ${char}`;
1885
+ const err = new PlainValue.YAMLSyntaxError(cst, msg);
1886
+ err.offset = offset;
1887
+ doc.errors.push(err);
1888
+ } else if (item.type === PlainValue.Type.BLANK_LINE) {
1889
+ comments.push({
1890
+ afterKey: !!key,
1891
+ before: items.length
1892
+ });
1893
+ } else if (item.type === PlainValue.Type.COMMENT) {
1894
+ checkFlowCommentSpace(doc.errors, item);
1895
+ comments.push({
1896
+ afterKey: !!key,
1897
+ before: items.length,
1898
+ comment: item.comment
1899
+ });
1900
+ } else if (key === undefined) {
1901
+ if (next === ',') doc.errors.push(new PlainValue.YAMLSemanticError(item, 'Separator , missing in flow map'));
1902
+ key = resolveNode(doc, item);
1903
+ } else {
1904
+ if (next !== ',') doc.errors.push(new PlainValue.YAMLSemanticError(item, 'Indicator : missing in flow map entry'));
1905
+ items.push(new Pair(key, resolveNode(doc, item)));
1906
+ key = undefined;
1907
+ explicitKey = false;
1908
+ }
1909
+ }
1910
+
1911
+ checkFlowCollectionEnd(doc.errors, cst);
1912
+ if (key !== undefined) items.push(new Pair(key));
1913
+ return {
1914
+ comments,
1915
+ items
1916
+ };
1917
+ }
1918
+
1919
+ function resolveSeq(doc, cst) {
1920
+ if (cst.type !== PlainValue.Type.SEQ && cst.type !== PlainValue.Type.FLOW_SEQ) {
1921
+ const msg = `A ${cst.type} node cannot be resolved as a sequence`;
1922
+ doc.errors.push(new PlainValue.YAMLSyntaxError(cst, msg));
1923
+ return null;
1924
+ }
1925
+
1926
+ const {
1927
+ comments,
1928
+ items
1929
+ } = cst.type === PlainValue.Type.FLOW_SEQ ? resolveFlowSeqItems(doc, cst) : resolveBlockSeqItems(doc, cst);
1930
+ const seq = new YAMLSeq();
1931
+ seq.items = items;
1932
+ resolveComments(seq, comments);
1933
+
1934
+ if (!doc.options.mapAsMap && items.some(it => it instanceof Pair && it.key instanceof Collection)) {
1935
+ const warn = 'Keys with collection values will be stringified as YAML due to JS Object restrictions. Use mapAsMap: true to avoid this.';
1936
+ doc.warnings.push(new PlainValue.YAMLWarning(cst, warn));
1937
+ }
1938
+
1939
+ cst.resolved = seq;
1940
+ return seq;
1941
+ }
1942
+
1943
+ function resolveBlockSeqItems(doc, cst) {
1944
+ const comments = [];
1945
+ const items = [];
1946
+
1947
+ for (let i = 0; i < cst.items.length; ++i) {
1948
+ const item = cst.items[i];
1949
+
1950
+ switch (item.type) {
1951
+ case PlainValue.Type.BLANK_LINE:
1952
+ comments.push({
1953
+ before: items.length
1954
+ });
1955
+ break;
1956
+
1957
+ case PlainValue.Type.COMMENT:
1958
+ comments.push({
1959
+ comment: item.comment,
1960
+ before: items.length
1961
+ });
1962
+ break;
1963
+
1964
+ case PlainValue.Type.SEQ_ITEM:
1965
+ if (item.error) doc.errors.push(item.error);
1966
+ items.push(resolveNode(doc, item.node));
1967
+
1968
+ if (item.hasProps) {
1969
+ const msg = 'Sequence items cannot have tags or anchors before the - indicator';
1970
+ doc.errors.push(new PlainValue.YAMLSemanticError(item, msg));
1971
+ }
1972
+
1973
+ break;
1974
+
1975
+ default:
1976
+ if (item.error) doc.errors.push(item.error);
1977
+ doc.errors.push(new PlainValue.YAMLSyntaxError(item, `Unexpected ${item.type} node in sequence`));
1978
+ }
1979
+ }
1980
+
1981
+ return {
1982
+ comments,
1983
+ items
1984
+ };
1985
+ }
1986
+
1987
+ function resolveFlowSeqItems(doc, cst) {
1988
+ const comments = [];
1989
+ const items = [];
1990
+ let explicitKey = false;
1991
+ let key = undefined;
1992
+ let keyStart = null;
1993
+ let next = '[';
1994
+ let prevItem = null;
1995
+
1996
+ for (let i = 0; i < cst.items.length; ++i) {
1997
+ const item = cst.items[i];
1998
+
1999
+ if (typeof item.char === 'string') {
2000
+ const {
2001
+ char,
2002
+ offset
2003
+ } = item;
2004
+
2005
+ if (char !== ':' && (explicitKey || key !== undefined)) {
2006
+ if (explicitKey && key === undefined) key = next ? items.pop() : null;
2007
+ items.push(new Pair(key));
2008
+ explicitKey = false;
2009
+ key = undefined;
2010
+ keyStart = null;
2011
+ }
2012
+
2013
+ if (char === next) {
2014
+ next = null;
2015
+ } else if (!next && char === '?') {
2016
+ explicitKey = true;
2017
+ } else if (next !== '[' && char === ':' && key === undefined) {
2018
+ if (next === ',') {
2019
+ key = items.pop();
2020
+
2021
+ if (key instanceof Pair) {
2022
+ const msg = 'Chaining flow sequence pairs is invalid';
2023
+ const err = new PlainValue.YAMLSemanticError(cst, msg);
2024
+ err.offset = offset;
2025
+ doc.errors.push(err);
2026
+ }
2027
+
2028
+ if (!explicitKey && typeof keyStart === 'number') {
2029
+ const keyEnd = item.range ? item.range.start : item.offset;
2030
+ if (keyEnd > keyStart + 1024) doc.errors.push(getLongKeyError(cst, key));
2031
+ const {
2032
+ src
2033
+ } = prevItem.context;
2034
+
2035
+ for (let i = keyStart; i < keyEnd; ++i) if (src[i] === '\n') {
2036
+ const msg = 'Implicit keys of flow sequence pairs need to be on a single line';
2037
+ doc.errors.push(new PlainValue.YAMLSemanticError(prevItem, msg));
2038
+ break;
2039
+ }
2040
+ }
2041
+ } else {
2042
+ key = null;
2043
+ }
2044
+
2045
+ keyStart = null;
2046
+ explicitKey = false;
2047
+ next = null;
2048
+ } else if (next === '[' || char !== ']' || i < cst.items.length - 1) {
2049
+ const msg = `Flow sequence contains an unexpected ${char}`;
2050
+ const err = new PlainValue.YAMLSyntaxError(cst, msg);
2051
+ err.offset = offset;
2052
+ doc.errors.push(err);
2053
+ }
2054
+ } else if (item.type === PlainValue.Type.BLANK_LINE) {
2055
+ comments.push({
2056
+ before: items.length
2057
+ });
2058
+ } else if (item.type === PlainValue.Type.COMMENT) {
2059
+ checkFlowCommentSpace(doc.errors, item);
2060
+ comments.push({
2061
+ comment: item.comment,
2062
+ before: items.length
2063
+ });
2064
+ } else {
2065
+ if (next) {
2066
+ const msg = `Expected a ${next} in flow sequence`;
2067
+ doc.errors.push(new PlainValue.YAMLSemanticError(item, msg));
2068
+ }
2069
+
2070
+ const value = resolveNode(doc, item);
2071
+
2072
+ if (key === undefined) {
2073
+ items.push(value);
2074
+ prevItem = item;
2075
+ } else {
2076
+ items.push(new Pair(key, value));
2077
+ key = undefined;
2078
+ }
2079
+
2080
+ keyStart = item.range.start;
2081
+ next = ',';
2082
+ }
2083
+ }
2084
+
2085
+ checkFlowCollectionEnd(doc.errors, cst);
2086
+ if (key !== undefined) items.push(new Pair(key));
2087
+ return {
2088
+ comments,
2089
+ items
2090
+ };
2091
+ }
2092
+
2093
+ exports.Alias = Alias;
2094
+ exports.Collection = Collection;
2095
+ exports.Merge = Merge;
2096
+ exports.Node = Node;
2097
+ exports.Pair = Pair;
2098
+ exports.Scalar = Scalar;
2099
+ exports.YAMLMap = YAMLMap;
2100
+ exports.YAMLSeq = YAMLSeq;
2101
+ exports.addComment = addComment;
2102
+ exports.binaryOptions = binaryOptions;
2103
+ exports.boolOptions = boolOptions;
2104
+ exports.findPair = findPair;
2105
+ exports.intOptions = intOptions;
2106
+ exports.isEmptyPath = isEmptyPath;
2107
+ exports.nullOptions = nullOptions;
2108
+ exports.resolveMap = resolveMap;
2109
+ exports.resolveNode = resolveNode;
2110
+ exports.resolveSeq = resolveSeq;
2111
+ exports.resolveString = resolveString;
2112
+ exports.strOptions = strOptions;
2113
+ exports.stringifyNumber = stringifyNumber;
2114
+ exports.stringifyString = stringifyString;
2115
+ exports.toJSON = toJSON;