"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _warnings = require("../warnings"); var _constants = require("../constants"); var _errors = require("../errors"); var _stringify = require("../stringify"); var _tags = require("../tags"); var _string = require("../tags/failsafe/string"); var _Alias = _interopRequireDefault(require("./Alias")); var _Collection = _interopRequireDefault(require("./Collection")); var _Node = _interopRequireDefault(require("./Node")); var _Pair = _interopRequireDefault(require("./Pair")); var _Scalar = _interopRequireDefault(require("./Scalar")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } const isMap = ({ type }) => type === _constants.Type.FLOW_MAP || type === _constants.Type.MAP; const isSeq = ({ type }) => type === _constants.Type.FLOW_SEQ || type === _constants.Type.SEQ; class Schema { constructor({ customTags, merge, schema, sortMapEntries, tags: deprecatedCustomTags }) { this.merge = !!merge; this.name = schema; this.sortMapEntries = sortMapEntries === true ? (a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0 : sortMapEntries || null; this.tags = _tags.schemas[schema.replace(/\W/g, '')]; // 'yaml-1.1' -> 'yaml11' if (!this.tags) { const keys = Object.keys(_tags.schemas).map(key => JSON.stringify(key)).join(', '); throw new Error(`Unknown schema "${schema}"; use one of ${keys}`); } if (!customTags && deprecatedCustomTags) { customTags = deprecatedCustomTags; (0, _warnings.warnOptionDeprecation)('tags', 'customTags'); } if (Array.isArray(customTags)) { for (const tag of customTags) this.tags = this.tags.concat(tag); } else if (typeof customTags === 'function') { this.tags = customTags(this.tags.slice()); } for (let i = 0; i < this.tags.length; ++i) { const tag = this.tags[i]; if (typeof tag === 'string') { const tagObj = _tags.tags[tag]; if (!tagObj) { const keys = Object.keys(_tags.tags).map(key => JSON.stringify(key)).join(', '); throw new Error(`Unknown custom tag "${tag}"; use one of ${keys}`); } this.tags[i] = tagObj; } } } createNode(value, wrapScalars, tag, ctx) { if (value instanceof _Node.default) return value; let tagObj; if (tag) { if (tag.startsWith('!!')) tag = Schema.defaultPrefix + tag.slice(2); const match = this.tags.filter(t => t.tag === tag); tagObj = match.find(t => !t.format) || match[0]; if (!tagObj) throw new Error(`Tag ${tag} not found`); } else { // TODO: deprecate/remove class check tagObj = this.tags.find(t => (t.identify && t.identify(value) || t.class && value instanceof t.class) && !t.format); if (!tagObj) { if (typeof value.toJSON === 'function') value = value.toJSON(); if (typeof value !== 'object') return wrapScalars ? new _Scalar.default(value) : value; tagObj = value instanceof Map ? _tags.tags.map : value[Symbol.iterator] ? _tags.tags.seq : _tags.tags.map; } } if (!ctx) ctx = { wrapScalars };else ctx.wrapScalars = wrapScalars; if (ctx.onTagObj) { ctx.onTagObj(tagObj); delete ctx.onTagObj; } const obj = {}; if (value && typeof value === 'object' && ctx.prevObjects) { const prev = ctx.prevObjects.get(value); if (prev) { const alias = new _Alias.default(prev); // leaves source dirty; must be cleaned by caller ctx.aliasNodes.push(alias); return alias; } obj.value = value; ctx.prevObjects.set(value, obj); } obj.node = tagObj.createNode ? tagObj.createNode(this, value, ctx) : wrapScalars ? new _Scalar.default(value) : value; if (tag && obj.node instanceof _Node.default) obj.node.tag = tag; return obj.node; } createPair(key, value, ctx) { const k = this.createNode(key, ctx.wrapScalars, null, ctx); const v = this.createNode(value, ctx.wrapScalars, null, ctx); return new _Pair.default(k, v); } // falls back to string on no match resolveScalar(str, tags) { if (!tags) tags = this.tags; for (let i = 0; i < tags.length; ++i) { const { format, test, resolve } = tags[i]; if (test) { const match = str.match(test); if (match) { let res = resolve.apply(null, match); if (!(res instanceof _Scalar.default)) res = new _Scalar.default(res); if (format) res.format = format; return res; } } } if (this.tags.scalarFallback) str = this.tags.scalarFallback(str); return new _Scalar.default(str); } // sets node.resolved on success resolveNode(doc, node, tagName) { const tags = this.tags.filter(({ tag }) => tag === tagName); const generic = tags.find(({ test }) => !test); if (node.error) doc.errors.push(node.error); try { if (generic) { let res = generic.resolve(doc, node); if (!(res instanceof _Collection.default)) res = new _Scalar.default(res); node.resolved = res; } else { const str = (0, _string.resolveString)(doc, node); if (typeof str === 'string' && tags.length > 0) { node.resolved = this.resolveScalar(str, tags); } } } catch (error) { /* istanbul ignore if */ if (!error.source) error.source = node; doc.errors.push(error); node.resolved = null; } if (!node.resolved) return null; if (tagName && node.tag) node.resolved.tag = tagName; return node.resolved; } resolveNodeWithFallback(doc, node, tagName) { const res = this.resolveNode(doc, node, tagName); if (Object.prototype.hasOwnProperty.call(node, 'resolved')) return res; const fallback = isMap(node) ? Schema.defaultTags.MAP : isSeq(node) ? Schema.defaultTags.SEQ : Schema.defaultTags.STR; /* istanbul ignore else */ if (fallback) { doc.warnings.push(new _errors.YAMLWarning(node, `The tag ${tagName} is unavailable, falling back to ${fallback}`)); const res = this.resolveNode(doc, node, fallback); res.tag = tagName; return res; } else { doc.errors.push(new _errors.YAMLReferenceError(node, `The tag ${tagName} is unavailable`)); return null; } } getTagObject(item) { if (item instanceof _Alias.default) return _Alias.default; if (item.tag) { const match = this.tags.filter(t => t.tag === item.tag); if (match.length > 0) return match.find(t => t.format === item.format) || match[0]; } let tagObj, obj; if (item instanceof _Scalar.default) { obj = item.value; // TODO: deprecate/remove class check const match = this.tags.filter(t => t.identify && t.identify(obj) || t.class && obj instanceof t.class); tagObj = match.find(t => t.format === item.format) || match.find(t => !t.format); } else { obj = item; tagObj = this.tags.find(t => t.nodeClass && obj instanceof t.nodeClass); } if (!tagObj) { const name = obj && obj.constructor ? obj.constructor.name : typeof obj; throw new Error(`Tag not resolved for ${name} value`); } return tagObj; } // needs to be called before stringifier to allow for circular anchor refs stringifyProps(node, tagObj, { anchors, doc }) { const props = []; const anchor = doc.anchors.getName(node); if (anchor) { anchors[anchor] = node; props.push(`&${anchor}`); } if (node.tag) { props.push(doc.stringifyTag(node.tag)); } else if (!tagObj.default) { props.push(doc.stringifyTag(tagObj.tag)); } return props.join(' '); } stringify(item, ctx, onComment, onChompKeep) { let tagObj; if (!(item instanceof _Node.default)) { const createCtx = { aliasNodes: [], onTagObj: o => tagObj = o, prevObjects: new Map() }; item = this.createNode(item, true, null, createCtx); const { anchors } = ctx.doc; for (const alias of createCtx.aliasNodes) { alias.source = alias.source.node; let name = anchors.getName(alias.source); if (!name) { name = anchors.newName(); anchors.map[name] = alias.source; } } } ctx.tags = this; if (item instanceof _Pair.default) return item.toString(ctx, onComment, onChompKeep); if (!tagObj) tagObj = this.getTagObject(item); const props = this.stringifyProps(item, tagObj, ctx); if (props.length > 0) ctx.indentAtStart = (ctx.indentAtStart || 0) + props.length + 1; const str = typeof tagObj.stringify === 'function' ? tagObj.stringify(item, ctx, onComment, onChompKeep) : item instanceof _Collection.default ? item.toString(ctx, onComment, onChompKeep) : (0, _stringify.stringifyString)(item, ctx, onComment, onChompKeep); return props ? item instanceof _Collection.default && str[0] !== '{' && str[0] !== '[' ? `${props}\n${ctx.indent}${str}` : `${props} ${str}` : str; } } exports.default = Schema; _defineProperty(Schema, "defaultPrefix", 'tag:yaml.org,2002:'); _defineProperty(Schema, "defaultTags", { MAP: 'tag:yaml.org,2002:map', SEQ: 'tag:yaml.org,2002:seq', STR: 'tag:yaml.org,2002:str' });