import { assertPresent, assign } from '@glimmer/util'; import { parse, parseWithoutProcessing } from '@handlebars/parser'; import { EntityParser } from 'simple-html-tokenizer'; import print from '../generation/print'; import { voidMap } from '../generation/printer'; import { Source } from '../source/source'; import { SourceSpan } from '../source/span'; import { generateSyntaxError } from '../syntax-error'; import traverse from '../traversal/traverse'; import Walker from '../traversal/walker'; import { appendChild, parseElementBlockParams } from '../utils'; import b from '../v1/parser-builders'; import publicBuilder from '../v1/public-builders'; import { HandlebarsNodeVisitors } from './handlebars-node-visitors'; export class TokenizerEventHandlers extends HandlebarsNodeVisitors { constructor() { super(...arguments); this.tagOpenLine = 0; this.tagOpenColumn = 0; } reset() { this.currentNode = null; } // Comment beginComment() { this.currentNode = b.comment('', this.source.offsetFor(this.tagOpenLine, this.tagOpenColumn)); } appendToCommentData(char) { this.currentComment.value += char; } finishComment() { appendChild(this.currentElement(), this.finish(this.currentComment)); } // Data beginData() { this.currentNode = b.text({ chars: '', loc: this.offset().collapsed() }); } appendToData(char) { this.currentData.chars += char; } finishData() { this.currentData.loc = this.currentData.loc.withEnd(this.offset()); appendChild(this.currentElement(), this.currentData); } // Tags - basic tagOpen() { this.tagOpenLine = this.tokenizer.line; this.tagOpenColumn = this.tokenizer.column; } beginStartTag() { this.currentNode = { type: 'StartTag', name: '', attributes: [], modifiers: [], comments: [], selfClosing: false, loc: this.source.offsetFor(this.tagOpenLine, this.tagOpenColumn) }; } beginEndTag() { this.currentNode = { type: 'EndTag', name: '', attributes: [], modifiers: [], comments: [], selfClosing: false, loc: this.source.offsetFor(this.tagOpenLine, this.tagOpenColumn) }; } finishTag() { let tag = this.finish(this.currentTag); if (tag.type === 'StartTag') { this.finishStartTag(); if (tag.name === ':') { throw generateSyntaxError('Invalid named block named detected, you may have created a named block without a name, or you may have began your name with a number. Named blocks must have names that are at least one character long, and begin with a lower case letter', this.source.spanFor({ start: this.currentTag.loc.toJSON(), end: this.offset().toJSON() })); } if (voidMap[tag.name] || tag.selfClosing) { this.finishEndTag(true); } } else if (tag.type === 'EndTag') { this.finishEndTag(false); } } finishStartTag() { let { name, attributes: attrs, modifiers, comments, selfClosing, loc } = this.finish(this.currentStartTag); let element = b.element({ tag: name, selfClosing, attrs, modifiers, comments, children: [], blockParams: [], loc }); this.elementStack.push(element); } finishEndTag(isVoid) { let tag = this.finish(this.currentTag); let element = this.elementStack.pop(); let parent = this.currentElement(); this.validateEndTag(tag, element, isVoid); element.loc = element.loc.withEnd(this.offset()); parseElementBlockParams(element); appendChild(parent, element); } markTagAsSelfClosing() { this.currentTag.selfClosing = true; } // Tags - name appendToTagName(char) { this.currentTag.name += char; } // Tags - attributes beginAttribute() { let offset = this.offset(); this.currentAttribute = { name: '', parts: [], currentPart: null, isQuoted: false, isDynamic: false, start: offset, valueSpan: offset.collapsed() }; } appendToAttributeName(char) { this.currentAttr.name += char; } beginAttributeValue(isQuoted) { this.currentAttr.isQuoted = isQuoted; this.startTextPart(); this.currentAttr.valueSpan = this.offset().collapsed(); } appendToAttributeValue(char) { let parts = this.currentAttr.parts; let lastPart = parts[parts.length - 1]; let current = this.currentAttr.currentPart; if (current) { current.chars += char; // update end location for each added char current.loc = current.loc.withEnd(this.offset()); } else { // initially assume the text node is a single char let loc = this.offset(); // the tokenizer line/column have already been advanced, correct location info if (char === '\n') { loc = lastPart ? lastPart.loc.getEnd() : this.currentAttr.valueSpan.getStart(); } else { loc = loc.move(-1); } this.currentAttr.currentPart = b.text({ chars: char, loc: loc.collapsed() }); } } finishAttributeValue() { this.finalizeTextPart(); let tag = this.currentTag; let tokenizerPos = this.offset(); if (tag.type === 'EndTag') { throw generateSyntaxError(`Invalid end tag: closing tag must not have attributes`, this.source.spanFor({ start: tag.loc.toJSON(), end: tokenizerPos.toJSON() })); } let { name, parts, start, isQuoted, isDynamic, valueSpan } = this.currentAttr; let value = this.assembleAttributeValue(parts, isQuoted, isDynamic, start.until(tokenizerPos)); value.loc = valueSpan.withEnd(tokenizerPos); let attribute = b.attr({ name, value, loc: start.until(tokenizerPos) }); this.currentStartTag.attributes.push(attribute); } reportSyntaxError(message) { throw generateSyntaxError(message, this.offset().collapsed()); } assembleConcatenatedValue(parts) { for (let i = 0; i < parts.length; i++) { let part = parts[i]; if (part.type !== 'MustacheStatement' && part.type !== 'TextNode') { throw generateSyntaxError('Unsupported node in quoted attribute value: ' + part['type'], part.loc); } } assertPresent(parts, `the concatenation parts of an element should not be empty`); let first = parts[0]; let last = parts[parts.length - 1]; return b.concat(parts, this.source.spanFor(first.loc).extend(this.source.spanFor(last.loc))); } validateEndTag(tag, element, selfClosing) { let error; if (voidMap[tag.name] && !selfClosing) { // EngTag is also called by StartTag for void and self-closing tags (i.e. // or
, so we need to check for that here. Otherwise, we would // throw an error for those cases. error = `<${tag.name}> elements do not need end tags. You should remove it`; } else if (element.tag === undefined) { error = `Closing tag without an open tag`; } else if (element.tag !== tag.name) { error = `Closing tag did not match last open tag <${element.tag}> (on line ${element.loc.startPosition.line})`; } if (error) { throw generateSyntaxError(error, tag.loc); } } assembleAttributeValue(parts, isQuoted, isDynamic, span) { if (isDynamic) { if (isQuoted) { return this.assembleConcatenatedValue(parts); } else { if (parts.length === 1 || parts.length === 2 && parts[1].type === 'TextNode' && parts[1].chars === '/') { return parts[0]; } else { throw generateSyntaxError(`An unquoted attribute value must be a string or a mustache, ` + `preceded by whitespace or a '=' character, and ` + `followed by whitespace, a '>' character, or '/>'`, span); } } } else { return parts.length > 0 ? parts[0] : b.text({ chars: '', loc: span }); } } } const syntax = { parse: preprocess, builders: publicBuilder, print, traverse, Walker }; class CodemodEntityParser extends EntityParser { // match upstream types, but never match an entity constructor() { super({}); } parse() { return undefined; } } export function preprocess(input, options = {}) { var _a, _b, _c; let mode = options.mode || 'precompile'; let source; let ast; if (typeof input === 'string') { source = new Source(input, (_a = options.meta) === null || _a === void 0 ? void 0 : _a.moduleName); if (mode === 'codemod') { ast = parseWithoutProcessing(input, options.parseOptions); } else { ast = parse(input, options.parseOptions); } } else if (input instanceof Source) { source = input; if (mode === 'codemod') { ast = parseWithoutProcessing(input.source, options.parseOptions); } else { ast = parse(input.source, options.parseOptions); } } else { source = new Source('', (_b = options.meta) === null || _b === void 0 ? void 0 : _b.moduleName); ast = input; } let entityParser = undefined; if (mode === 'codemod') { entityParser = new CodemodEntityParser(); } let offsets = SourceSpan.forCharPositions(source, 0, source.source.length); ast.loc = { source: '(program)', start: offsets.startPosition, end: offsets.endPosition }; let program = new TokenizerEventHandlers(source, entityParser, mode).acceptTemplate(ast); if (options.strictMode) { program.blockParams = (_c = options.locals) !== null && _c !== void 0 ? _c : []; } if (options && options.plugins && options.plugins.ast) { for (let i = 0, l = options.plugins.ast.length; i < l; i++) { let transform = options.plugins.ast[i]; let env = assign({}, options, { syntax }, { plugins: undefined }); let pluginResult = transform(env); traverse(program, pluginResult.visitor); } } return program; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3N5bnRheC9saWIvcGFyc2VyL3Rva2VuaXplci1ldmVudC1oYW5kbGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxTQUFTLGFBQVQsRUFBd0IsTUFBeEIsUUFBc0MsZUFBdEM7QUFDQSxTQUFTLEtBQVQsRUFBZ0Isc0JBQWhCLFFBQThDLG9CQUE5QztBQUNBLFNBQVMsWUFBVCxRQUE2Qix1QkFBN0I7QUFFQSxPQUFPLEtBQVAsTUFBa0IscUJBQWxCO0FBQ0EsU0FBUyxPQUFULFFBQXdCLHVCQUF4QjtBQUVBLFNBQVMsTUFBVCxRQUF1QixrQkFBdkI7QUFDQSxTQUF1QixVQUF2QixRQUF5QyxnQkFBekM7QUFDQSxTQUFTLG1CQUFULFFBQW9DLGlCQUFwQztBQUNBLE9BQU8sUUFBUCxNQUFxQix1QkFBckI7QUFFQSxPQUFPLE1BQVAsTUFBbUIscUJBQW5CO0FBQ0EsU0FBUyxXQUFULEVBQXNCLHVCQUF0QixRQUFxRCxVQUFyRDtBQUdBLE9BQU8sQ0FBUCxNQUFjLHVCQUFkO0FBQ0EsT0FBTyxhQUFQLE1BQTBCLHVCQUExQjtBQUNBLFNBQVMsc0JBQVQsUUFBdUMsNEJBQXZDO0FBRUEsT0FBTSxNQUFPLHNCQUFQLFNBQXNDLHNCQUF0QyxDQUE0RDtBQUFsRSxFQUFBLFdBQUEsR0FBQTs7QUFDVSxTQUFBLFdBQUEsR0FBYyxDQUFkO0FBQ0EsU0FBQSxhQUFBLEdBQWdCLENBQWhCO0FBZ1NUOztBQTlSQyxFQUFBLEtBQUssR0FBQTtBQUNILFNBQUssV0FBTCxHQUFtQixJQUFuQjtBQUNELEdBTitELENBUWhFOzs7QUFFQSxFQUFBLFlBQVksR0FBQTtBQUNWLFNBQUssV0FBTCxHQUFtQixDQUFDLENBQUMsT0FBRixDQUFVLEVBQVYsRUFBYyxLQUFLLE1BQUwsQ0FBWSxTQUFaLENBQXNCLEtBQUssV0FBM0IsRUFBd0MsS0FBSyxhQUE3QyxDQUFkLENBQW5CO0FBQ0Q7O0FBRUQsRUFBQSxt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LEVBQUssT0FBTCxFQUFjO0FBQUUsUUFBQTtBQUFGLE9BQWQsRUFBMEI7QUFBRSxRQUFBLE9BQU8sRUFBRTtBQUFYLE9BQTFCLENBQXRDO0FBRUEsVUFBSSxZQUFZLEdBQUcsU0FBUyxDQUFDLEdBQUQsQ0FBNUI7QUFFQSxNQUFBLFFBQVEsQ0FBQyxPQUFELEVBQVUsWUFBWSxDQUFDLE9BQXZCLENBQVI7QUFDRDtBQUNGOztBQUVELFNBQU8sT0FBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgT3B0aW9uIH0gZnJvbSAnQGdsaW1tZXIvaW50ZXJmYWNlcyc7XG5pbXBvcnQgeyBhc3NlcnRQcmVzZW50LCBhc3NpZ24gfSBmcm9tICdAZ2xpbW1lci91dGlsJztcbmltcG9ydCB7IHBhcnNlLCBwYXJzZVdpdGhvdXRQcm9jZXNzaW5nIH0gZnJvbSAnQGhhbmRsZWJhcnMvcGFyc2VyJztcbmltcG9ydCB7IEVudGl0eVBhcnNlciB9IGZyb20gJ3NpbXBsZS1odG1sLXRva2VuaXplcic7XG5cbmltcG9ydCBwcmludCBmcm9tICcuLi9nZW5lcmF0aW9uL3ByaW50JztcbmltcG9ydCB7IHZvaWRNYXAgfSBmcm9tICcuLi9nZW5lcmF0aW9uL3ByaW50ZXInO1xuaW1wb3J0IHsgVGFnIH0gZnJvbSAnLi4vcGFyc2VyJztcbmltcG9ydCB7IFNvdXJjZSB9IGZyb20gJy4uL3NvdXJjZS9zb3VyY2UnO1xuaW1wb3J0IHsgU291cmNlT2Zmc2V0LCBTb3VyY2VTcGFuIH0gZnJvbSAnLi4vc291cmNlL3NwYW4nO1xuaW1wb3J0IHsgZ2VuZXJhdGVTeW50YXhFcnJvciB9IGZyb20gJy4uL3N5bnRheC1lcnJvcic7XG5pbXBvcnQgdHJhdmVyc2UgZnJvbSAnLi4vdHJhdmVyc2FsL3RyYXZlcnNlJztcbmltcG9ydCB7IE5vZGVWaXNpdG9yIH0gZnJvbSAnLi4vdHJhdmVyc2FsL3Zpc2l0b3InO1xuaW1wb3J0IFdhbGtlciBmcm9tICcuLi90cmF2ZXJzYWwvd2Fsa2VyJztcbmltcG9ydCB7IGFwcGVuZENoaWxkLCBwYXJzZUVsZW1lbnRCbG9ja1BhcmFtcyB9IGZyb20gJy4uL3V0aWxzJztcbmltcG9ydCAqIGFzIEFTVHYxIGZyb20gJy4uL3YxL2FwaSc7XG5pbXBvcnQgKiBhcyBIQlMgZnJvbSAnLi4vdjEvaGFuZGxlYmFycy1hc3QnO1xuaW1wb3J0IGIgZnJvbSAnLi4vdjEvcGFyc2VyLWJ1aWxkZXJzJztcbmltcG9ydCBwdWJsaWNCdWlsZGVyIGZyb20gJy4uL3YxL3B1YmxpYy1idWlsZGVycyc7XG5pbXBvcnQgeyBIYW5kbGViYXJzTm9kZVZpc2l0b3JzIH0gZnJvbSAnLi9oYW5kbGViYXJzLW5vZGUtdmlzaXRvcnMnO1xuXG5leHBvcnQgY2xhc3MgVG9rZW5pemVyRXZlbnRIYW5kbGVycyBleHRlbmRzIEhhbmRsZWJhcnNOb2RlVmlzaXRvcnMge1xuICBwcml2YXRlIHRhZ09wZW5MaW5lID0gMDtcbiAgcHJpdmF0ZSB0YWdPcGVuQ29sdW1uID0gMDtcblxuICByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnROb2RlID0gbnVsbDtcbiAgfVxuXG4gIC8vIENvbW1lbnRcblxuICBiZWdpbkNvbW1lbnQoKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50Tm9kZSA9IGIuY29tbWVudCgnJywgdGhpcy5zb3VyY2Uub2Zmc2V0Rm9yKHRoaXMudGFnT3BlbkxpbmUsIHRoaXMudGFnT3BlbkNvbHVtbikpO1xuICB9XG5cbiAgYXBwZW5kVG9Db21tZW50RGF0YShjaGFyOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnRDb21tZW50LnZhbHVlICs9IGNoYXI7XG4gIH1cblxuICBmaW5pc2hDb21tZW50KCk6IHZvaWQge1xuICAgIGFwcGVuZENoaWxkKHRoaXMuY3VycmVudEVsZW1lbnQoKSwgdGhpcy5maW5pc2godGhpcy5jdXJyZW50Q29tbWVudCkpO1xuICB9XG5cbiAgLy8gRGF0YVxuXG4gIGJlZ2luRGF0YSgpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnROb2RlID0gYi50ZXh0KHtcbiAgICAgIGNoYXJzOiAnJyxcbiAgICAgIGxvYzogdGhpcy5vZmZzZXQoKS5jb2xsYXBzZWQoKSxcbiAgICB9KTtcbiAgfVxuXG4gIGFwcGVuZFRvRGF0YShjaGFyOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnREYXRhLmNoYXJzICs9IGNoYXI7XG4gIH1cblxuICBmaW5pc2hEYXRhKCk6IHZvaWQge1xuICAgIHRoaXMuY3VycmVudERhdGEubG9jID0gdGhpcy5jdXJyZW50RGF0YS5sb2Mud2l0aEVuZCh0aGlzLm9mZnNldCgpKTtcblxuICAgIGFwcGVuZENoaWxkKHRoaXMuY3VycmVudEVsZW1lbnQoKSwgdGhpcy5jdXJyZW50RGF0YSk7XG4gIH1cblxuICAvLyBUYWdzIC0gYmFzaWNcblxuICB0YWdPcGVuKCk6IHZvaWQge1xuICAgIHRoaXMudGFnT3BlbkxpbmUgPSB0aGlzLnRva2VuaXplci5saW5lO1xuICAgIHRoaXMudGFnT3BlbkNvbHVtbiA9IHRoaXMudG9rZW5pemVyLmNvbHVtbjtcbiAgfVxuXG4gIGJlZ2luU3RhcnRUYWcoKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50Tm9kZSA9IHtcbiAgICAgIHR5cGU6ICdTdGFydFRhZycsXG4gICAgICBuYW1lOiAnJyxcbiAgICAgIGF0dHJpYnV0ZXM6IFtdLFxuICAgICAgbW9kaWZpZXJzOiBbXSxcbiAgICAgIGNvbW1lbnRzOiBbXSxcbiAgICAgIHNlbGZDbG9zaW5nOiBmYWxzZSxcbiAgICAgIGxvYzogdGhpcy5zb3VyY2Uub2Zmc2V0Rm9yKHRoaXMudGFnT3BlbkxpbmUsIHRoaXMudGFnT3BlbkNvbHVtbiksXG4gICAgfTtcbiAgfVxuXG4gIGJlZ2luRW5kVGFnKCk6IHZvaWQge1xuICAgIHRoaXMuY3VycmVudE5vZGUgPSB7XG4gICAgICB0eXBlOiAnRW5kVGFnJyxcbiAgICAgIG5hbWU6ICcnLFxuICAgICAgYXR0cmlidXRlczogW10sXG4gICAgICBtb2RpZmllcnM6IFtdLFxuICAgICAgY29tbWVudHM6IFtdLFxuICAgICAgc2VsZkNsb3Npbmc6IGZhbHNlLFxuICAgICAgbG9jOiB0aGlzLnNvdXJjZS5vZmZzZXRGb3IodGhpcy50YWdPcGVuTGluZSwgdGhpcy50YWdPcGVuQ29sdW1uKSxcbiAgICB9O1xuICB9XG5cbiAgZmluaXNoVGFnKCk6IHZvaWQge1xuICAgIGxldCB0YWcgPSB0aGlzLmZpbmlzaCh0aGlzLmN1cnJlbnRUYWcpO1xuXG4gICAgaWYgKHRhZy50eXBlID09PSAnU3RhcnRUYWcnKSB7XG4gICAgICB0aGlzLmZpbmlzaFN0YXJ0VGFnKCk7XG5cbiAgICAgIGlmICh0YWcubmFtZSA9PT0gJzonKSB7XG4gICAgICAgIHRocm93IGdlbmVyYXRlU3ludGF4RXJyb3IoXG4gICAgICAgICAgJ0ludmFsaWQgbmFtZWQgYmxvY2sgbmFtZWQgZGV0ZWN0ZWQsIHlvdSBtYXkgaGF2ZSBjcmVhdGVkIGEgbmFtZWQgYmxvY2sgd2l0aG91dCBhIG5hbWUsIG9yIHlvdSBtYXkgaGF2ZSBiZWdhbiB5b3VyIG5hbWUgd2l0aCBhIG51bWJlci4gTmFtZWQgYmxvY2tzIG11c3QgaGF2ZSBuYW1lcyB0aGF0IGFyZSBhdCBsZWFzdCBvbmUgY2hhcmFjdGVyIGxvbmcsIGFuZCBiZWdpbiB3aXRoIGEgbG93ZXIgY2FzZSBsZXR0ZXInLFxuICAgICAgICAgIHRoaXMuc291cmNlLnNwYW5Gb3Ioe1xuICAgICAgICAgICAgc3RhcnQ6IHRoaXMuY3VycmVudFRhZy5sb2MudG9KU09OKCksXG4gICAgICAgICAgICBlbmQ6IHRoaXMub2Zmc2V0KCkudG9KU09OKCksXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHZvaWRNYXBbdGFnLm5hbWVdIHx8IHRhZy5zZWxmQ2xvc2luZykge1xuICAgICAgICB0aGlzLmZpbmlzaEVuZFRhZyh0cnVlKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRhZy50eXBlID09PSAnRW5kVGFnJykge1xuICAgICAgdGhpcy5maW5pc2hFbmRUYWcoZmFsc2UpO1xuICAgIH1cbiAgfVxuXG4gIGZpbmlzaFN0YXJ0VGFnKCk6IHZvaWQge1xuICAgIGxldCB7IG5hbWUsIGF0dHJpYnV0ZXM6IGF0dHJzLCBtb2RpZmllcnMsIGNvbW1lbnRzLCBzZWxmQ2xvc2luZywgbG9jIH0gPSB0aGlzLmZpbmlzaChcbiAgICAgIHRoaXMuY3VycmVudFN0YXJ0VGFnXG4gICAgKTtcblxuICAgIGxldCBlbGVtZW50ID0gYi5lbGVtZW50KHtcbiAgICAgIHRhZzogbmFtZSxcbiAgICAgIHNlbGZDbG9zaW5nLFxuICAgICAgYXR0cnMsXG4gICAgICBtb2RpZmllcnMsXG4gICAgICBjb21tZW50cyxcbiAgICAgIGNoaWxkcmVuOiBbXSxcbiAgICAgIGJsb2NrUGFyYW1zOiBbXSxcbiAgICAgIGxvYyxcbiAgICB9KTtcbiAgICB0aGlzLmVsZW1lbnRTdGFjay5wdXNoKGVsZW1lbnQpO1xuICB9XG5cbiAgZmluaXNoRW5kVGFnKGlzVm9pZDogYm9vbGVhbik6IHZvaWQge1xuICAgIGxldCB0YWcgPSB0aGlzLmZpbmlzaCh0aGlzLmN1cnJlbnRUYWcpO1xuXG4gICAgbGV0IGVsZW1lbnQgPSB0aGlzLmVsZW1lbnRTdGFjay5wb3AoKSBhcyBBU1R2MS5FbGVtZW50Tm9kZTtcbiAgICBsZXQgcGFyZW50ID0gdGhpcy5jdXJyZW50RWxlbWVudCgpO1xuXG4gICAgdGhpcy52YWxpZGF0ZUVuZFRhZyh0YWcsIGVsZW1lbnQsIGlzVm9pZCk7XG5cbiAgICBlbGVtZW50LmxvYyA9IGVsZW1lbnQubG9jLndpdGhFbmQodGhpcy5vZmZzZXQoKSk7XG4gICAgcGFyc2VFbGVtZW50QmxvY2tQYXJhbXMoZWxlbWVudCk7XG4gICAgYXBwZW5kQ2hpbGQocGFyZW50LCBlbGVtZW50KTtcbiAgfVxuXG4gIG1hcmtUYWdBc1NlbGZDbG9zaW5nKCk6IHZvaWQge1xuICAgIHRoaXMuY3VycmVudFRhZy5zZWxmQ2xvc2luZyA9IHRydWU7XG4gIH1cblxuICAvLyBUYWdzIC0gbmFtZVxuXG4gIGFwcGVuZFRvVGFnTmFtZShjaGFyOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnRUYWcubmFtZSArPSBjaGFyO1xuICB9XG5cbiAgLy8gVGFncyAtIGF0dHJpYnV0ZXNcblxuICBiZWdpbkF0dHJpYnV0ZSgpOiB2b2lkIHtcbiAgICBsZXQgb2Zmc2V0ID0gdGhpcy5vZmZzZXQoKTtcblxuICAgIHRoaXMuY3VycmVudEF0dHJpYnV0ZSA9IHtcbiAgICAgIG5hbWU6ICcnLFxuICAgICAgcGFydHM6IFtdLFxuICAgICAgY3VycmVudFBhcnQ6IG51bGwsXG4gICAgICBpc1F1b3RlZDogZmFsc2UsXG4gICAgICBpc0R5bmFtaWM6IGZhbHNlLFxuICAgICAgc3RhcnQ6IG9mZnNldCxcbiAgICAgIHZhbHVlU3Bhbjogb2Zmc2V0LmNvbGxhcHNlZCgpLFxuICAgIH07XG4gIH1cblxuICBhcHBlbmRUb0F0dHJpYnV0ZU5hbWUoY2hhcjogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50QXR0ci5uYW1lICs9IGNoYXI7XG4gIH1cblxuICBiZWdpbkF0dHJpYnV0ZVZhbHVlKGlzUXVvdGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50QXR0ci5pc1F1b3RlZCA9IGlzUXVvdGVkO1xuICAgIHRoaXMuc3RhcnRUZXh0UGFydCgpO1xuICAgIHRoaXMuY3VycmVudEF0dHIudmFsdWVTcGFuID0gdGhpcy5vZmZzZXQoKS5jb2xsYXBzZWQoKTtcbiAgfVxuXG4gIGFwcGVuZFRvQXR0cmlidXRlVmFsdWUoY2hhcjogc3RyaW5nKTogdm9pZCB7XG4gICAgbGV0IHBhcnRzID0gdGhpcy5jdXJyZW50QXR0ci5wYXJ0cztcbiAgICBsZXQgbGFzdFBhcnQgPSBwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXTtcblxuICAgIGxldCBjdXJyZW50ID0gdGhpcy5jdXJyZW50QXR0ci5jdXJyZW50UGFydDtcblxuICAgIGlmIChjdXJyZW50KSB7XG4gICAgICBjdXJyZW50LmNoYXJzICs9IGNoYXI7XG5cbiAgICAgIC8vIHVwZGF0ZSBlbmQgbG9jYXRpb24gZm9yIGVhY2ggYWRkZWQgY2hhclxuICAgICAgY3VycmVudC5sb2MgPSBjdXJyZW50LmxvYy53aXRoRW5kKHRoaXMub2Zmc2V0KCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBpbml0aWFsbHkgYXNzdW1lIHRoZSB0ZXh0IG5vZGUgaXMgYSBzaW5nbGUgY2hhclxuICAgICAgbGV0IGxvYzogU291cmNlT2Zmc2V0ID0gdGhpcy5vZmZzZXQoKTtcblxuICAgICAgLy8gdGhlIHRva2VuaXplciBsaW5lL2NvbHVtbiBoYXZlIGFscmVhZHkgYmVlbiBhZHZhbmNlZCwgY29ycmVjdCBsb2NhdGlvbiBpbmZvXG4gICAgICBpZiAoY2hhciA9PT0gJ1xcbicpIHtcbiAgICAgICAgbG9jID0gbGFzdFBhcnQgPyBsYXN0UGFydC5sb2MuZ2V0RW5kKCkgOiB0aGlzLmN1cnJlbnRBdHRyLnZhbHVlU3Bhbi5nZXRTdGFydCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9jID0gbG9jLm1vdmUoLTEpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmN1cnJlbnRBdHRyLmN1cnJlbnRQYXJ0ID0gYi50ZXh0KHsgY2hhcnM6IGNoYXIsIGxvYzogbG9jLmNvbGxhcHNlZCgpIH0pO1xuICAgIH1cbiAgfVxuXG4gIGZpbmlzaEF0dHJpYnV0ZVZhbHVlKCk6IHZvaWQge1xuICAgIHRoaXMuZmluYWxpemVUZXh0UGFydCgpO1xuXG4gICAgbGV0IHRhZyA9IHRoaXMuY3VycmVudFRhZztcbiAgICBsZXQgdG9rZW5pemVyUG9zID0gdGhpcy5vZmZzZXQoKTtcblxuICAgIGlmICh0YWcudHlwZSA9PT0gJ0VuZFRhZycpIHtcbiAgICAgIHRocm93IGdlbmVyYXRlU3ludGF4RXJyb3IoXG4gICAgICAgIGBJbnZhbGlkIGVuZCB0YWc6IGNsb3NpbmcgdGFnIG11c3Qgbm90IGhhdmUgYXR0cmlidXRlc2AsXG4gICAgICAgIHRoaXMuc291cmNlLnNwYW5Gb3IoeyBzdGFydDogdGFnLmxvYy50b0pTT04oKSwgZW5kOiB0b2tlbml6ZXJQb3MudG9KU09OKCkgfSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgbGV0IHsgbmFtZSwgcGFydHMsIHN0YXJ0LCBpc1F1b3RlZCwgaXNEeW5hbWljLCB2YWx1ZVNwYW4gfSA9IHRoaXMuY3VycmVudEF0dHI7XG4gICAgbGV0IHZhbHVlID0gdGhpcy5hc3NlbWJsZUF0dHJpYnV0ZVZhbHVlKHBhcnRzLCBpc1F1b3RlZCwgaXNEeW5hbWljLCBzdGFydC51bnRpbCh0b2tlbml6ZXJQb3MpKTtcbiAgICB2YWx1ZS5sb2MgPSB2YWx1ZVNwYW4ud2l0aEVuZCh0b2tlbml6ZXJQb3MpO1xuXG4gICAgbGV0IGF0dHJpYnV0ZSA9IGIuYXR0cih7IG5hbWUsIHZhbHVlLCBsb2M6IHN0YXJ0LnVudGlsKHRva2VuaXplclBvcykgfSk7XG5cbiAgICB0aGlzLmN1cnJlbnRTdGFydFRhZy5hdHRyaWJ1dGVzLnB1c2goYXR0cmlidXRlKTtcbiAgfVxuXG4gIHJlcG9ydFN5bnRheEVycm9yKG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQge1xuICAgIHRocm93IGdlbmVyYXRlU3ludGF4RXJyb3IobWVzc2FnZSwgdGhpcy5vZmZzZXQoKS5jb2xsYXBzZWQoKSk7XG4gIH1cblxuICBhc3NlbWJsZUNvbmNhdGVuYXRlZFZhbHVlKFxuICAgIHBhcnRzOiAoQVNUdjEuTXVzdGFjaGVTdGF0ZW1lbnQgfCBBU1R2MS5UZXh0Tm9kZSlbXVxuICApOiBBU1R2MS5Db25jYXRTdGF0ZW1lbnQge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwYXJ0OiBBU1R2MS5CYXNlTm9kZSA9IHBhcnRzW2ldO1xuXG4gICAgICBpZiAocGFydC50eXBlICE9PSAnTXVzdGFjaGVTdGF0ZW1lbnQnICYmIHBhcnQudHlwZSAhPT0gJ1RleHROb2RlJykge1xuICAgICAgICB0aHJvdyBnZW5lcmF0ZVN5bnRheEVycm9yKFxuICAgICAgICAgICdVbnN1cHBvcnRlZCBub2RlIGluIHF1b3RlZCBhdHRyaWJ1dGUgdmFsdWU6ICcgKyBwYXJ0Wyd0eXBlJ10sXG4gICAgICAgICAgcGFydC5sb2NcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBhc3NlcnRQcmVzZW50KHBhcnRzLCBgdGhlIGNvbmNhdGVuYXRpb24gcGFydHMgb2YgYW4gZWxlbWVudCBzaG91bGQgbm90IGJlIGVtcHR5YCk7XG5cbiAgICBsZXQgZmlyc3QgPSBwYXJ0c1swXTtcbiAgICBsZXQgbGFzdCA9IHBhcnRzW3BhcnRzLmxlbmd0aCAtIDFdO1xuXG4gICAgcmV0dXJuIGIuY29uY2F0KHBhcnRzLCB0aGlzLnNvdXJjZS5zcGFuRm9yKGZpcnN0LmxvYykuZXh0ZW5kKHRoaXMuc291cmNlLnNwYW5Gb3IobGFzdC5sb2MpKSk7XG4gIH1cblxuICB2YWxpZGF0ZUVuZFRhZyhcbiAgICB0YWc6IFRhZzwnU3RhcnRUYWcnIHwgJ0VuZFRhZyc+LFxuICAgIGVsZW1lbnQ6IEFTVHYxLkVsZW1lbnROb2RlLFxuICAgIHNlbGZDbG9zaW5nOiBib29sZWFuXG4gICk6IHZvaWQge1xuICAgIGxldCBlcnJvcjtcblxuICAgIGlmICh2b2lkTWFwW3RhZy5uYW1lXSAmJiAhc2VsZkNsb3NpbmcpIHtcbiAgICAgIC8vIEVuZ1RhZyBpcyBhbHNvIGNhbGxlZCBieSBTdGFydFRhZyBmb3Igdm9pZCBhbmQgc2VsZi1jbG9zaW5nIHRhZ3MgKGkuZS5cbiAgICAgIC8vIDxpbnB1dD4gb3IgPGJyIC8+LCBzbyB3ZSBuZWVkIHRvIGNoZWNrIGZvciB0aGF0IGhlcmUuIE90aGVyd2lzZSwgd2Ugd291bGRcbiAgICAgIC8vIHRocm93IGFuIGVycm9yIGZvciB0aG9zZSBjYXNlcy5cbiAgICAgIGVycm9yID0gYDwke3RhZy5uYW1lfT4gZWxlbWVudHMgZG8gbm90IG5lZWQgZW5kIHRhZ3MuIFlvdSBzaG91bGQgcmVtb3ZlIGl0YDtcbiAgICB9IGVsc2UgaWYgKGVsZW1lbnQudGFnID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGVycm9yID0gYENsb3NpbmcgdGFnIDwvJHt0YWcubmFtZX0+IHdpdGhvdXQgYW4gb3BlbiB0YWdgO1xuICAgIH0gZWxzZSBpZiAoZWxlbWVudC50YWcgIT09IHRhZy5uYW1lKSB7XG4gICAgICBlcnJvciA9IGBDbG9zaW5nIHRhZyA8LyR7dGFnLm5hbWV9PiBkaWQgbm90IG1hdGNoIGxhc3Qgb3BlbiB0YWcgPCR7ZWxlbWVudC50YWd9PiAob24gbGluZSAke2VsZW1lbnQubG9jLnN0YXJ0UG9zaXRpb24ubGluZX0pYDtcbiAgICB9XG5cbiAgICBpZiAoZXJyb3IpIHtcbiAgICAgIHRocm93IGdlbmVyYXRlU3ludGF4RXJyb3IoZXJyb3IsIHRhZy5sb2MpO1xuICAgIH1cbiAgfVxuXG4gIGFzc2VtYmxlQXR0cmlidXRlVmFsdWUoXG4gICAgcGFydHM6IChBU1R2MS5NdXN0YWNoZVN0YXRlbWVudCB8IEFTVHYxLlRleHROb2RlKVtdLFxuICAgIGlzUXVvdGVkOiBib29sZWFuLFxuICAgIGlzRHluYW1pYzogYm9vbGVhbixcbiAgICBzcGFuOiBTb3VyY2VTcGFuXG4gICk6IEFTVHYxLkNvbmNhdFN0YXRlbWVudCB8IEFTVHYxLk11c3RhY2hlU3RhdGVtZW50IHwgQVNUdjEuVGV4dE5vZGUge1xuICAgIGlmIChpc0R5bmFtaWMpIHtcbiAgICAgIGlmIChpc1F1b3RlZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hc3NlbWJsZUNvbmNhdGVuYXRlZFZhbHVlKHBhcnRzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBwYXJ0cy5sZW5ndGggPT09IDEgfHxcbiAgICAgICAgICAocGFydHMubGVuZ3RoID09PSAyICYmXG4gICAgICAgICAgICBwYXJ0c1sxXS50eXBlID09PSAnVGV4dE5vZGUnICYmXG4gICAgICAgICAgICAocGFydHNbMV0gYXMgQVNUdjEuVGV4dE5vZGUpLmNoYXJzID09PSAnLycpXG4gICAgICAgICkge1xuICAgICAgICAgIHJldHVybiBwYXJ0c1swXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBnZW5lcmF0ZVN5bnRheEVycm9yKFxuICAgICAgICAgICAgYEFuIHVucXVvdGVkIGF0dHJpYnV0ZSB2YWx1ZSBtdXN0IGJlIGEgc3RyaW5nIG9yIGEgbXVzdGFjaGUsIGAgK1xuICAgICAgICAgICAgICBgcHJlY2VkZWQgYnkgd2hpdGVzcGFjZSBvciBhICc9JyBjaGFyYWN0ZXIsIGFuZCBgICtcbiAgICAgICAgICAgICAgYGZvbGxvd2VkIGJ5IHdoaXRlc3BhY2UsIGEgJz4nIGNoYXJhY3Rlciwgb3IgJy8+J2AsXG4gICAgICAgICAgICBzcGFuXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcGFydHMubGVuZ3RoID4gMCA/IHBhcnRzWzBdIDogYi50ZXh0KHsgY2hhcnM6ICcnLCBsb2M6IHNwYW4gfSk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICBBU1RQbHVnaW5zIGNhbiBtYWtlIGNoYW5nZXMgdG8gdGhlIEdsaW1tZXIgdGVtcGxhdGUgQVNUIGJlZm9yZVxuICBjb21waWxhdGlvbiBiZWdpbnMuXG4qL1xuZXhwb3J0IGludGVyZmFjZSBBU1RQbHVnaW5CdWlsZGVyPFRFbnYgZXh0ZW5kcyBBU1RQbHVnaW5FbnZpcm9ubWVudCA9IEFTVFBsdWdpbkVudmlyb25tZW50PiB7XG4gIChlbnY6IFRFbnYpOiBBU1RQbHVnaW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQVNUUGx1Z2luIHtcbiAgbmFtZTogc3RyaW5nO1xuICB2aXNpdG9yOiBOb2RlVmlzaXRvcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBU1RQbHVnaW5FbnZpcm9ubWVudCB7XG4gIG1ldGE/OiBvYmplY3Q7XG4gIHN5bnRheDogU3ludGF4O1xufVxuXG5pbnRlcmZhY2UgSGFuZGxlYmFyc1BhcnNlT3B0aW9ucyB7XG4gIHNyY05hbWU/OiBzdHJpbmc7XG4gIGlnbm9yZVN0YW5kYWxvbmU/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRlbXBsYXRlSWRGbiB7XG4gIChzcmM6IHN0cmluZyk6IE9wdGlvbjxzdHJpbmc+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFByZWNvbXBpbGVPcHRpb25zIGV4dGVuZHMgUHJlcHJvY2Vzc09wdGlvbnMge1xuICBpZD86IFRlbXBsYXRlSWRGbjtcbiAgY3VzdG9taXplQ29tcG9uZW50TmFtZT8oaW5wdXQ6IHN0cmluZyk6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcmVwcm9jZXNzT3B0aW9ucyB7XG4gIHN0cmljdE1vZGU/OiBib29sZWFuO1xuICBsb2NhbHM/OiBzdHJpbmdbXTtcbiAgbWV0YT86IHtcbiAgICBtb2R1bGVOYW1lPzogc3RyaW5nO1xuICB9O1xuICBwbHVnaW5zPzoge1xuICAgIGFzdD86IEFTVFBsdWdpbkJ1aWxkZXJbXTtcbiAgfTtcbiAgcGFyc2VPcHRpb25zPzogSGFuZGxlYmFyc1BhcnNlT3B0aW9ucztcbiAgY3VzdG9taXplQ29tcG9uZW50TmFtZT8oaW5wdXQ6IHN0cmluZyk6IHN0cmluZztcblxuICAvKipcbiAgICBVc2VmdWwgZm9yIHNwZWNpZnlpbmcgYSBncm91cCBvZiBvcHRpb25zIHRvZ2V0aGVyLlxuXG4gICAgV2hlbiBgJ2NvZGVtb2QnYCB3ZSBkaXNhYmxlIGFsbCB3aGl0ZXNwYWNlIGNvbnRyb2wgaW4gaGFuZGxlYmFyc1xuICAgICh0byBwcmVzZXJ2ZSBhcyBtdWNoIGFzIHBvc3NpYmxlKSBhbmQgd2UgYWxzbyBhdm9pZCBhbnlcbiAgICBlc2NhcGluZy91bmVzY2FwaW5nIG9mIEhUTUwgZW50aXR5IGNvZGVzLlxuICAgKi9cbiAgbW9kZT86ICdjb2RlbW9kJyB8ICdwcmVjb21waWxlJztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTeW50YXgge1xuICBwYXJzZTogdHlwZW9mIHByZXByb2Nlc3M7XG4gIGJ1aWxkZXJzOiB0eXBlb2YgcHVibGljQnVpbGRlcjtcbiAgcHJpbnQ6IHR5cGVvZiBwcmludDtcbiAgdHJhdmVyc2U6IHR5cGVvZiB0cmF2ZXJzZTtcbiAgV2Fsa2VyOiB0eXBlb2YgV2Fsa2VyO1xufVxuXG5jb25zdCBzeW50YXg6IFN5bnRheCA9IHtcbiAgcGFyc2U6IHByZXByb2Nlc3MsXG4gIGJ1aWxkZXJzOiBwdWJsaWNCdWlsZGVyLFxuICBwcmludCxcbiAgdHJhdmVyc2UsXG4gIFdhbGtlcixcbn07XG5cbmNsYXNzIENvZGVtb2RFbnRpdHlQYXJzZXIgZXh0ZW5kcyBFbnRpdHlQYXJzZXIge1xuICAvLyBtYXRjaCB1cHN0cmVhbSB0eXBlcywgYnV0IG5ldmVyIG1hdGNoIGFuIGVudGl0eVxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcih7fSk7XG4gIH1cblxuICBwYXJzZSgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHByZXByb2Nlc3MoXG4gIGlucHV0OiBzdHJpbmcgfCBTb3VyY2UgfCBIQlMuUHJvZ3JhbSxcbiAgb3B0aW9uczogUHJlcHJvY2Vzc09wdGlvbnMgPSB7fVxuKTogQVNUdjEuVGVtcGxhdGUge1xuICBsZXQgbW9kZSA9IG9wdGlvbnMubW9kZSB8fCAncHJlY29tcGlsZSc7XG5cbiAgbGV0IHNvdXJjZTogU291cmNlO1xuICBsZXQgYXN0OiBIQlMuUHJvZ3JhbTtcbiAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICBzb3VyY2UgPSBuZXcgU291cmNlKGlucHV0LCBvcHRpb25zLm1ldGE/Lm1vZHVsZU5hbWUpO1xuXG4gICAgaWYgKG1vZGUgPT09ICdjb2RlbW9kJykge1xuICAgICAgYXN0ID0gcGFyc2VXaXRob3V0UHJvY2Vzc2luZyhpbnB1dCwgb3B0aW9ucy5wYXJzZU9wdGlvbnMpIGFzIEhCUy5Qcm9ncmFtO1xuICAgIH0gZWxzZSB7XG4gICAgICBhc3QgPSBwYXJzZShpbnB1dCwgb3B0aW9ucy5wYXJzZU9wdGlvbnMpIGFzIEhCUy5Qcm9ncmFtO1xuICAgIH1cbiAgfSBlbHNlIGlmIChpbnB1dCBpbnN0YW5jZW9mIFNvdXJjZSkge1xuICAgIHNvdXJjZSA9IGlucHV0O1xuXG4gICAgaWYgKG1vZGUgPT09ICdjb2RlbW9kJykge1xuICAgICAgYXN0ID0gcGFyc2VXaXRob3V0UHJvY2Vzc2luZyhpbnB1dC5zb3VyY2UsIG9wdGlvbnMucGFyc2VPcHRpb25zKSBhcyBIQlMuUHJvZ3JhbTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXN0ID0gcGFyc2UoaW5wdXQuc291cmNlLCBvcHRpb25zLnBhcnNlT3B0aW9ucykgYXMgSEJTLlByb2dyYW07XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHNvdXJjZSA9IG5ldyBTb3VyY2UoJycsIG9wdGlvbnMubWV0YT8ubW9kdWxlTmFtZSk7XG4gICAgYXN0ID0gaW5wdXQ7XG4gIH1cblxuICBsZXQgZW50aXR5UGFyc2VyID0gdW5kZWZpbmVkO1xuICBpZiAobW9kZSA9PT0gJ2NvZGVtb2QnKSB7XG4gICAgZW50aXR5UGFyc2VyID0gbmV3IENvZGVtb2RFbnRpdHlQYXJzZXIoKTtcbiAgfVxuXG4gIGxldCBvZmZzZXRzID0gU291cmNlU3Bhbi5mb3JDaGFyUG9zaXRpb25zKHNvdXJjZSwgMCwgc291cmNlLnNvdXJjZS5sZW5ndGgpO1xuICBhc3QubG9jID0ge1xuICAgIHNvdXJjZTogJyhwcm9ncmFtKScsXG4gICAgc3RhcnQ6IG9mZnNldHMuc3RhcnRQb3NpdGlvbixcbiAgICBlbmQ6IG9mZnNldHMuZW5kUG9zaXRpb24sXG4gIH07XG5cbiAgbGV0IHByb2dyYW0gPSBuZXcgVG9rZW5pemVyRXZlbnRIYW5kbGVycyhzb3VyY2UsIGVudGl0eVBhcnNlciwgbW9kZSkuYWNjZXB0VGVtcGxhdGUoYXN0KTtcblxuICBpZiAob3B0aW9ucy5zdHJpY3RNb2RlKSB7XG4gICAgcHJvZ3JhbS5ibG9ja1BhcmFtcyA9IG9wdGlvbnMubG9jYWxzID8/IFtdO1xuICB9XG5cbiAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5wbHVnaW5zICYmIG9wdGlvbnMucGx1Z2lucy5hc3QpIHtcbiAgICBmb3IgKGxldCBpID0gMCwgbCA9IG9wdGlvbnMucGx1Z2lucy5hc3QubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICBsZXQgdHJhbnNmb3JtID0gb3B0aW9ucy5wbHVnaW5zLmFzdFtpXTtcbiAgICAgIGxldCBlbnY6IEFTVFBsdWdpbkVudmlyb25tZW50ID0gYXNzaWduKHt9LCBvcHRpb25zLCB7IHN5bnRheCB9LCB7IHBsdWdpbnM6IHVuZGVmaW5lZCB9KTtcblxuICAgICAgbGV0IHBsdWdpblJlc3VsdCA9IHRyYW5zZm9ybShlbnYpO1xuXG4gICAgICB0cmF2ZXJzZShwcm9ncmFtLCBwbHVnaW5SZXN1bHQudmlzaXRvcik7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHByb2dyYW07XG59XG4iXSwic291cmNlUm9vdCI6IiJ9