cdk8s-operator 0.1.407 → 0.1.409

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