/ cloudformation-templates / node_modules / aws-cdk / node_modules / yaml / dist / Document-9b4560a1.js
Document-9b4560a1.js
1 'use strict'; 2 3 var PlainValue = require('./PlainValue-ec8e588e.js'); 4 var resolveSeq = require('./resolveSeq-d03cb037.js'); 5 var Schema = require('./Schema-88e323a7.js'); 6 7 const defaultOptions = { 8 anchorPrefix: 'a', 9 customTags: null, 10 indent: 2, 11 indentSeq: true, 12 keepCstNodes: false, 13 keepNodeTypes: true, 14 keepBlobsInJSON: true, 15 mapAsMap: false, 16 maxAliasCount: 100, 17 prettyErrors: false, 18 // TODO Set true in v2 19 simpleKeys: false, 20 version: '1.2' 21 }; 22 const scalarOptions = { 23 get binary() { 24 return resolveSeq.binaryOptions; 25 }, 26 27 set binary(opt) { 28 Object.assign(resolveSeq.binaryOptions, opt); 29 }, 30 31 get bool() { 32 return resolveSeq.boolOptions; 33 }, 34 35 set bool(opt) { 36 Object.assign(resolveSeq.boolOptions, opt); 37 }, 38 39 get int() { 40 return resolveSeq.intOptions; 41 }, 42 43 set int(opt) { 44 Object.assign(resolveSeq.intOptions, opt); 45 }, 46 47 get null() { 48 return resolveSeq.nullOptions; 49 }, 50 51 set null(opt) { 52 Object.assign(resolveSeq.nullOptions, opt); 53 }, 54 55 get str() { 56 return resolveSeq.strOptions; 57 }, 58 59 set str(opt) { 60 Object.assign(resolveSeq.strOptions, opt); 61 } 62 63 }; 64 const documentOptions = { 65 '1.0': { 66 schema: 'yaml-1.1', 67 merge: true, 68 tagPrefixes: [{ 69 handle: '!', 70 prefix: PlainValue.defaultTagPrefix 71 }, { 72 handle: '!!', 73 prefix: 'tag:private.yaml.org,2002:' 74 }] 75 }, 76 1.1: { 77 schema: 'yaml-1.1', 78 merge: true, 79 tagPrefixes: [{ 80 handle: '!', 81 prefix: '!' 82 }, { 83 handle: '!!', 84 prefix: PlainValue.defaultTagPrefix 85 }] 86 }, 87 1.2: { 88 schema: 'core', 89 merge: false, 90 tagPrefixes: [{ 91 handle: '!', 92 prefix: '!' 93 }, { 94 handle: '!!', 95 prefix: PlainValue.defaultTagPrefix 96 }] 97 } 98 }; 99 100 function stringifyTag(doc, tag) { 101 if ((doc.version || doc.options.version) === '1.0') { 102 const priv = tag.match(/^tag:private\.yaml\.org,2002:([^:/]+)$/); 103 if (priv) return '!' + priv[1]; 104 const vocab = tag.match(/^tag:([a-zA-Z0-9-]+)\.yaml\.org,2002:(.*)/); 105 return vocab ? `!${vocab[1]}/${vocab[2]}` : `!${tag.replace(/^tag:/, '')}`; 106 } 107 108 let p = doc.tagPrefixes.find(p => tag.indexOf(p.prefix) === 0); 109 110 if (!p) { 111 const dtp = doc.getDefaults().tagPrefixes; 112 p = dtp && dtp.find(p => tag.indexOf(p.prefix) === 0); 113 } 114 115 if (!p) return tag[0] === '!' ? tag : `!<${tag}>`; 116 const suffix = tag.substr(p.prefix.length).replace(/[!,[\]{}]/g, ch => ({ 117 '!': '%21', 118 ',': '%2C', 119 '[': '%5B', 120 ']': '%5D', 121 '{': '%7B', 122 '}': '%7D' 123 })[ch]); 124 return p.handle + suffix; 125 } 126 127 function getTagObject(tags, item) { 128 if (item instanceof resolveSeq.Alias) return resolveSeq.Alias; 129 130 if (item.tag) { 131 const match = tags.filter(t => t.tag === item.tag); 132 if (match.length > 0) return match.find(t => t.format === item.format) || match[0]; 133 } 134 135 let tagObj, obj; 136 137 if (item instanceof resolveSeq.Scalar) { 138 obj = item.value; // TODO: deprecate/remove class check 139 140 const match = tags.filter(t => t.identify && t.identify(obj) || t.class && obj instanceof t.class); 141 tagObj = match.find(t => t.format === item.format) || match.find(t => !t.format); 142 } else { 143 obj = item; 144 tagObj = tags.find(t => t.nodeClass && obj instanceof t.nodeClass); 145 } 146 147 if (!tagObj) { 148 const name = obj && obj.constructor ? obj.constructor.name : typeof obj; 149 throw new Error(`Tag not resolved for ${name} value`); 150 } 151 152 return tagObj; 153 } // needs to be called before value stringifier to allow for circular anchor refs 154 155 156 function stringifyProps(node, tagObj, { 157 anchors, 158 doc 159 }) { 160 const props = []; 161 const anchor = doc.anchors.getName(node); 162 163 if (anchor) { 164 anchors[anchor] = node; 165 props.push(`&${anchor}`); 166 } 167 168 if (node.tag) { 169 props.push(stringifyTag(doc, node.tag)); 170 } else if (!tagObj.default) { 171 props.push(stringifyTag(doc, tagObj.tag)); 172 } 173 174 return props.join(' '); 175 } 176 177 function stringify(item, ctx, onComment, onChompKeep) { 178 const { 179 anchors, 180 schema 181 } = ctx.doc; 182 let tagObj; 183 184 if (!(item instanceof resolveSeq.Node)) { 185 const createCtx = { 186 aliasNodes: [], 187 onTagObj: o => tagObj = o, 188 prevObjects: new Map() 189 }; 190 item = schema.createNode(item, true, null, createCtx); 191 192 for (const alias of createCtx.aliasNodes) { 193 alias.source = alias.source.node; 194 let name = anchors.getName(alias.source); 195 196 if (!name) { 197 name = anchors.newName(); 198 anchors.map[name] = alias.source; 199 } 200 } 201 } 202 203 if (item instanceof resolveSeq.Pair) return item.toString(ctx, onComment, onChompKeep); 204 if (!tagObj) tagObj = getTagObject(schema.tags, item); 205 const props = stringifyProps(item, tagObj, ctx); 206 if (props.length > 0) ctx.indentAtStart = (ctx.indentAtStart || 0) + props.length + 1; 207 const str = typeof tagObj.stringify === 'function' ? tagObj.stringify(item, ctx, onComment, onChompKeep) : item instanceof resolveSeq.Scalar ? resolveSeq.stringifyString(item, ctx, onComment, onChompKeep) : item.toString(ctx, onComment, onChompKeep); 208 if (!props) return str; 209 return item instanceof resolveSeq.Scalar || str[0] === '{' || str[0] === '[' ? `${props} ${str}` : `${props}\n${ctx.indent}${str}`; 210 } 211 212 class Anchors { 213 static validAnchorNode(node) { 214 return node instanceof resolveSeq.Scalar || node instanceof resolveSeq.YAMLSeq || node instanceof resolveSeq.YAMLMap; 215 } 216 217 constructor(prefix) { 218 PlainValue._defineProperty(this, "map", Object.create(null)); 219 220 this.prefix = prefix; 221 } 222 223 createAlias(node, name) { 224 this.setAnchor(node, name); 225 return new resolveSeq.Alias(node); 226 } 227 228 createMergePair(...sources) { 229 const merge = new resolveSeq.Merge(); 230 merge.value.items = sources.map(s => { 231 if (s instanceof resolveSeq.Alias) { 232 if (s.source instanceof resolveSeq.YAMLMap) return s; 233 } else if (s instanceof resolveSeq.YAMLMap) { 234 return this.createAlias(s); 235 } 236 237 throw new Error('Merge sources must be Map nodes or their Aliases'); 238 }); 239 return merge; 240 } 241 242 getName(node) { 243 const { 244 map 245 } = this; 246 return Object.keys(map).find(a => map[a] === node); 247 } 248 249 getNames() { 250 return Object.keys(this.map); 251 } 252 253 getNode(name) { 254 return this.map[name]; 255 } 256 257 newName(prefix) { 258 if (!prefix) prefix = this.prefix; 259 const names = Object.keys(this.map); 260 261 for (let i = 1; true; ++i) { 262 const name = `${prefix}${i}`; 263 if (!names.includes(name)) return name; 264 } 265 } // During parsing, map & aliases contain CST nodes 266 267 268 resolveNodes() { 269 const { 270 map, 271 _cstAliases 272 } = this; 273 Object.keys(map).forEach(a => { 274 map[a] = map[a].resolved; 275 }); 276 277 _cstAliases.forEach(a => { 278 a.source = a.source.resolved; 279 }); 280 281 delete this._cstAliases; 282 } 283 284 setAnchor(node, name) { 285 if (node != null && !Anchors.validAnchorNode(node)) { 286 throw new Error('Anchors may only be set for Scalar, Seq and Map nodes'); 287 } 288 289 if (name && /[\x00-\x19\s,[\]{}]/.test(name)) { 290 throw new Error('Anchor names must not contain whitespace or control characters'); 291 } 292 293 const { 294 map 295 } = this; 296 const prev = node && Object.keys(map).find(a => map[a] === node); 297 298 if (prev) { 299 if (!name) { 300 return prev; 301 } else if (prev !== name) { 302 delete map[prev]; 303 map[name] = node; 304 } 305 } else { 306 if (!name) { 307 if (!node) return null; 308 name = this.newName(); 309 } 310 311 map[name] = node; 312 } 313 314 return name; 315 } 316 317 } 318 319 const visit = (node, tags) => { 320 if (node && typeof node === 'object') { 321 const { 322 tag 323 } = node; 324 325 if (node instanceof resolveSeq.Collection) { 326 if (tag) tags[tag] = true; 327 node.items.forEach(n => visit(n, tags)); 328 } else if (node instanceof resolveSeq.Pair) { 329 visit(node.key, tags); 330 visit(node.value, tags); 331 } else if (node instanceof resolveSeq.Scalar) { 332 if (tag) tags[tag] = true; 333 } 334 } 335 336 return tags; 337 }; 338 339 const listTagNames = node => Object.keys(visit(node, {})); 340 341 function parseContents(doc, contents) { 342 const comments = { 343 before: [], 344 after: [] 345 }; 346 let body = undefined; 347 let spaceBefore = false; 348 349 for (const node of contents) { 350 if (node.valueRange) { 351 if (body !== undefined) { 352 const msg = 'Document contains trailing content not separated by a ... or --- line'; 353 doc.errors.push(new PlainValue.YAMLSyntaxError(node, msg)); 354 break; 355 } 356 357 const res = resolveSeq.resolveNode(doc, node); 358 359 if (spaceBefore) { 360 res.spaceBefore = true; 361 spaceBefore = false; 362 } 363 364 body = res; 365 } else if (node.comment !== null) { 366 const cc = body === undefined ? comments.before : comments.after; 367 cc.push(node.comment); 368 } else if (node.type === PlainValue.Type.BLANK_LINE) { 369 spaceBefore = true; 370 371 if (body === undefined && comments.before.length > 0 && !doc.commentBefore) { 372 // space-separated comments at start are parsed as document comments 373 doc.commentBefore = comments.before.join('\n'); 374 comments.before = []; 375 } 376 } 377 } 378 379 doc.contents = body || null; 380 381 if (!body) { 382 doc.comment = comments.before.concat(comments.after).join('\n') || null; 383 } else { 384 const cb = comments.before.join('\n'); 385 386 if (cb) { 387 const cbNode = body instanceof resolveSeq.Collection && body.items[0] ? body.items[0] : body; 388 cbNode.commentBefore = cbNode.commentBefore ? `${cb}\n${cbNode.commentBefore}` : cb; 389 } 390 391 doc.comment = comments.after.join('\n') || null; 392 } 393 } 394 395 function resolveTagDirective({ 396 tagPrefixes 397 }, directive) { 398 const [handle, prefix] = directive.parameters; 399 400 if (!handle || !prefix) { 401 const msg = 'Insufficient parameters given for %TAG directive'; 402 throw new PlainValue.YAMLSemanticError(directive, msg); 403 } 404 405 if (tagPrefixes.some(p => p.handle === handle)) { 406 const msg = 'The %TAG directive must only be given at most once per handle in the same document.'; 407 throw new PlainValue.YAMLSemanticError(directive, msg); 408 } 409 410 return { 411 handle, 412 prefix 413 }; 414 } 415 416 function resolveYamlDirective(doc, directive) { 417 let [version] = directive.parameters; 418 if (directive.name === 'YAML:1.0') version = '1.0'; 419 420 if (!version) { 421 const msg = 'Insufficient parameters given for %YAML directive'; 422 throw new PlainValue.YAMLSemanticError(directive, msg); 423 } 424 425 if (!documentOptions[version]) { 426 const v0 = doc.version || doc.options.version; 427 const msg = `Document will be parsed as YAML ${v0} rather than YAML ${version}`; 428 doc.warnings.push(new PlainValue.YAMLWarning(directive, msg)); 429 } 430 431 return version; 432 } 433 434 function parseDirectives(doc, directives, prevDoc) { 435 const directiveComments = []; 436 let hasDirectives = false; 437 438 for (const directive of directives) { 439 const { 440 comment, 441 name 442 } = directive; 443 444 switch (name) { 445 case 'TAG': 446 try { 447 doc.tagPrefixes.push(resolveTagDirective(doc, directive)); 448 } catch (error) { 449 doc.errors.push(error); 450 } 451 452 hasDirectives = true; 453 break; 454 455 case 'YAML': 456 case 'YAML:1.0': 457 if (doc.version) { 458 const msg = 'The %YAML directive must only be given at most once per document.'; 459 doc.errors.push(new PlainValue.YAMLSemanticError(directive, msg)); 460 } 461 462 try { 463 doc.version = resolveYamlDirective(doc, directive); 464 } catch (error) { 465 doc.errors.push(error); 466 } 467 468 hasDirectives = true; 469 break; 470 471 default: 472 if (name) { 473 const msg = `YAML only supports %TAG and %YAML directives, and not %${name}`; 474 doc.warnings.push(new PlainValue.YAMLWarning(directive, msg)); 475 } 476 477 } 478 479 if (comment) directiveComments.push(comment); 480 } 481 482 if (prevDoc && !hasDirectives && '1.1' === (doc.version || prevDoc.version || doc.options.version)) { 483 const copyTagPrefix = ({ 484 handle, 485 prefix 486 }) => ({ 487 handle, 488 prefix 489 }); 490 491 doc.tagPrefixes = prevDoc.tagPrefixes.map(copyTagPrefix); 492 doc.version = prevDoc.version; 493 } 494 495 doc.commentBefore = directiveComments.join('\n') || null; 496 } 497 498 function assertCollection(contents) { 499 if (contents instanceof resolveSeq.Collection) return true; 500 throw new Error('Expected a YAML collection as document contents'); 501 } 502 503 class Document { 504 constructor(options) { 505 this.anchors = new Anchors(options.anchorPrefix); 506 this.commentBefore = null; 507 this.comment = null; 508 this.contents = null; 509 this.directivesEndMarker = null; 510 this.errors = []; 511 this.options = options; 512 this.schema = null; 513 this.tagPrefixes = []; 514 this.version = null; 515 this.warnings = []; 516 } 517 518 add(value) { 519 assertCollection(this.contents); 520 return this.contents.add(value); 521 } 522 523 addIn(path, value) { 524 assertCollection(this.contents); 525 this.contents.addIn(path, value); 526 } 527 528 delete(key) { 529 assertCollection(this.contents); 530 return this.contents.delete(key); 531 } 532 533 deleteIn(path) { 534 if (resolveSeq.isEmptyPath(path)) { 535 if (this.contents == null) return false; 536 this.contents = null; 537 return true; 538 } 539 540 assertCollection(this.contents); 541 return this.contents.deleteIn(path); 542 } 543 544 getDefaults() { 545 return Document.defaults[this.version] || Document.defaults[this.options.version] || {}; 546 } 547 548 get(key, keepScalar) { 549 return this.contents instanceof resolveSeq.Collection ? this.contents.get(key, keepScalar) : undefined; 550 } 551 552 getIn(path, keepScalar) { 553 if (resolveSeq.isEmptyPath(path)) return !keepScalar && this.contents instanceof resolveSeq.Scalar ? this.contents.value : this.contents; 554 return this.contents instanceof resolveSeq.Collection ? this.contents.getIn(path, keepScalar) : undefined; 555 } 556 557 has(key) { 558 return this.contents instanceof resolveSeq.Collection ? this.contents.has(key) : false; 559 } 560 561 hasIn(path) { 562 if (resolveSeq.isEmptyPath(path)) return this.contents !== undefined; 563 return this.contents instanceof resolveSeq.Collection ? this.contents.hasIn(path) : false; 564 } 565 566 set(key, value) { 567 assertCollection(this.contents); 568 this.contents.set(key, value); 569 } 570 571 setIn(path, value) { 572 if (resolveSeq.isEmptyPath(path)) this.contents = value;else { 573 assertCollection(this.contents); 574 this.contents.setIn(path, value); 575 } 576 } 577 578 setSchema(id, customTags) { 579 if (!id && !customTags && this.schema) return; 580 if (typeof id === 'number') id = id.toFixed(1); 581 582 if (id === '1.0' || id === '1.1' || id === '1.2') { 583 if (this.version) this.version = id;else this.options.version = id; 584 delete this.options.schema; 585 } else if (id && typeof id === 'string') { 586 this.options.schema = id; 587 } 588 589 if (Array.isArray(customTags)) this.options.customTags = customTags; 590 const opt = Object.assign({}, this.getDefaults(), this.options); 591 this.schema = new Schema.Schema(opt); 592 } 593 594 parse(node, prevDoc) { 595 if (this.options.keepCstNodes) this.cstNode = node; 596 if (this.options.keepNodeTypes) this.type = 'DOCUMENT'; 597 const { 598 directives = [], 599 contents = [], 600 directivesEndMarker, 601 error, 602 valueRange 603 } = node; 604 605 if (error) { 606 if (!error.source) error.source = this; 607 this.errors.push(error); 608 } 609 610 parseDirectives(this, directives, prevDoc); 611 if (directivesEndMarker) this.directivesEndMarker = true; 612 this.range = valueRange ? [valueRange.start, valueRange.end] : null; 613 this.setSchema(); 614 this.anchors._cstAliases = []; 615 parseContents(this, contents); 616 this.anchors.resolveNodes(); 617 618 if (this.options.prettyErrors) { 619 for (const error of this.errors) if (error instanceof PlainValue.YAMLError) error.makePretty(); 620 621 for (const warn of this.warnings) if (warn instanceof PlainValue.YAMLError) warn.makePretty(); 622 } 623 624 return this; 625 } 626 627 listNonDefaultTags() { 628 return listTagNames(this.contents).filter(t => t.indexOf(Schema.Schema.defaultPrefix) !== 0); 629 } 630 631 setTagPrefix(handle, prefix) { 632 if (handle[0] !== '!' || handle[handle.length - 1] !== '!') throw new Error('Handle must start and end with !'); 633 634 if (prefix) { 635 const prev = this.tagPrefixes.find(p => p.handle === handle); 636 if (prev) prev.prefix = prefix;else this.tagPrefixes.push({ 637 handle, 638 prefix 639 }); 640 } else { 641 this.tagPrefixes = this.tagPrefixes.filter(p => p.handle !== handle); 642 } 643 } 644 645 toJSON(arg, onAnchor) { 646 const { 647 keepBlobsInJSON, 648 mapAsMap, 649 maxAliasCount 650 } = this.options; 651 const keep = keepBlobsInJSON && (typeof arg !== 'string' || !(this.contents instanceof resolveSeq.Scalar)); 652 const ctx = { 653 doc: this, 654 indentStep: ' ', 655 keep, 656 mapAsMap: keep && !!mapAsMap, 657 maxAliasCount, 658 stringify // Requiring directly in Pair would create circular dependencies 659 660 }; 661 const anchorNames = Object.keys(this.anchors.map); 662 if (anchorNames.length > 0) ctx.anchors = new Map(anchorNames.map(name => [this.anchors.map[name], { 663 alias: [], 664 aliasCount: 0, 665 count: 1 666 }])); 667 const res = resolveSeq.toJSON(this.contents, arg, ctx); 668 if (typeof onAnchor === 'function' && ctx.anchors) for (const { 669 count, 670 res 671 } of ctx.anchors.values()) onAnchor(res, count); 672 return res; 673 } 674 675 toString() { 676 if (this.errors.length > 0) throw new Error('Document with errors cannot be stringified'); 677 const indentSize = this.options.indent; 678 679 if (!Number.isInteger(indentSize) || indentSize <= 0) { 680 const s = JSON.stringify(indentSize); 681 throw new Error(`"indent" option must be a positive integer, not ${s}`); 682 } 683 684 this.setSchema(); 685 const lines = []; 686 let hasDirectives = false; 687 688 if (this.version) { 689 let vd = '%YAML 1.2'; 690 691 if (this.schema.name === 'yaml-1.1') { 692 if (this.version === '1.0') vd = '%YAML:1.0';else if (this.version === '1.1') vd = '%YAML 1.1'; 693 } 694 695 lines.push(vd); 696 hasDirectives = true; 697 } 698 699 const tagNames = this.listNonDefaultTags(); 700 this.tagPrefixes.forEach(({ 701 handle, 702 prefix 703 }) => { 704 if (tagNames.some(t => t.indexOf(prefix) === 0)) { 705 lines.push(`%TAG ${handle} ${prefix}`); 706 hasDirectives = true; 707 } 708 }); 709 if (hasDirectives || this.directivesEndMarker) lines.push('---'); 710 711 if (this.commentBefore) { 712 if (hasDirectives || !this.directivesEndMarker) lines.unshift(''); 713 lines.unshift(this.commentBefore.replace(/^/gm, '#')); 714 } 715 716 const ctx = { 717 anchors: Object.create(null), 718 doc: this, 719 indent: '', 720 indentStep: ' '.repeat(indentSize), 721 stringify // Requiring directly in nodes would create circular dependencies 722 723 }; 724 let chompKeep = false; 725 let contentComment = null; 726 727 if (this.contents) { 728 if (this.contents instanceof resolveSeq.Node) { 729 if (this.contents.spaceBefore && (hasDirectives || this.directivesEndMarker)) lines.push(''); 730 if (this.contents.commentBefore) lines.push(this.contents.commentBefore.replace(/^/gm, '#')); // top-level block scalars need to be indented if followed by a comment 731 732 ctx.forceBlockIndent = !!this.comment; 733 contentComment = this.contents.comment; 734 } 735 736 const onChompKeep = contentComment ? null : () => chompKeep = true; 737 const body = stringify(this.contents, ctx, () => contentComment = null, onChompKeep); 738 lines.push(resolveSeq.addComment(body, '', contentComment)); 739 } else if (this.contents !== undefined) { 740 lines.push(stringify(this.contents, ctx)); 741 } 742 743 if (this.comment) { 744 if ((!chompKeep || contentComment) && lines[lines.length - 1] !== '') lines.push(''); 745 lines.push(this.comment.replace(/^/gm, '#')); 746 } 747 748 return lines.join('\n') + '\n'; 749 } 750 751 } 752 753 PlainValue._defineProperty(Document, "defaults", documentOptions); 754 755 exports.Document = Document; 756 exports.defaultOptions = defaultOptions; 757 exports.scalarOptions = scalarOptions;