ember-legacy-class-transform
Version:
The default blueprint for ember-cli addons.
273 lines (254 loc) • 35.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.syntax = exports.TokenizerEventHandlers = undefined;
exports.preprocess = preprocess;
var _builders = require("../builders");
var _builders2 = _interopRequireDefault(_builders);
var _utils = require("../utils");
var _handlebarsNodeVisitors = require("./handlebars-node-visitors");
var _syntaxError = require("../errors/syntax-error");
var _syntaxError2 = _interopRequireDefault(_syntaxError);
var _traverse = require("../traversal/traverse");
var _traverse2 = _interopRequireDefault(_traverse);
var _print = require("../generation/print");
var _print2 = _interopRequireDefault(_print);
var _walker = require("../traversal/walker");
var _walker2 = _interopRequireDefault(_walker);
var _handlebars = require("handlebars");
var handlebars = _interopRequireWildcard(_handlebars);
var _util = require("@glimmer/util");
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const voidMap = Object.create(null);
let voidTagNames = "area base br col command embed hr img input keygen link meta param source track wbr";
voidTagNames.split(" ").forEach(tagName => {
voidMap[tagName] = true;
});
class TokenizerEventHandlers extends _handlebarsNodeVisitors.HandlebarsNodeVisitors {
constructor() {
super(...arguments);
this.tagOpenLine = 0;
this.tagOpenColumn = 0;
}
reset() {
this.currentNode = null;
}
// Comment
beginComment() {
this.currentNode = _builders2.default.comment("");
this.currentNode.loc = {
source: null,
start: _builders2.default.pos(this.tagOpenLine, this.tagOpenColumn),
end: null
};
}
appendToCommentData(char) {
this.currentComment.value += char;
}
finishComment() {
this.currentComment.loc.end = _builders2.default.pos(this.tokenizer.line, this.tokenizer.column);
(0, _utils.appendChild)(this.currentElement(), this.currentComment);
}
// Data
beginData() {
this.currentNode = _builders2.default.text();
this.currentNode.loc = {
source: null,
start: _builders2.default.pos(this.tokenizer.line, this.tokenizer.column),
end: null
};
}
appendToData(char) {
this.currentData.chars += char;
}
finishData() {
this.currentData.loc.end = _builders2.default.pos(this.tokenizer.line, this.tokenizer.column);
(0, _utils.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: _builders.SYNTHETIC
};
}
beginEndTag() {
this.currentNode = {
type: 'EndTag',
name: "",
attributes: [],
modifiers: [],
comments: [],
selfClosing: false,
loc: _builders.SYNTHETIC
};
}
finishTag() {
let { line, column } = this.tokenizer;
let tag = this.currentTag;
tag.loc = _builders2.default.loc(this.tagOpenLine, this.tagOpenColumn, line, column);
if (tag.type === 'StartTag') {
this.finishStartTag();
if (voidMap[tag.name] || tag.selfClosing) {
this.finishEndTag(true);
}
} else if (tag.type === 'EndTag') {
this.finishEndTag(false);
}
}
finishStartTag() {
let { name, attributes, modifiers, comments } = this.currentStartTag;
let loc = _builders2.default.loc(this.tagOpenLine, this.tagOpenColumn);
let element = _builders2.default.element(name, attributes, modifiers, [], comments, loc);
this.elementStack.push(element);
}
finishEndTag(isVoid) {
let tag = this.currentTag;
let element = this.elementStack.pop();
let parent = this.currentElement();
validateEndTag(tag, element, isVoid);
element.loc.end.line = this.tokenizer.line;
element.loc.end.column = this.tokenizer.column;
(0, _utils.parseElementBlockParams)(element);
(0, _utils.appendChild)(parent, element);
}
markTagAsSelfClosing() {
this.currentTag.selfClosing = true;
}
// Tags - name
appendToTagName(char) {
this.currentTag.name += char;
}
// Tags - attributes
beginAttribute() {
let tag = this.currentTag;
if (tag.type === 'EndTag') {
throw new _syntaxError2.default(`Invalid end tag: closing tag must not have attributes, ` + `in \`${tag.name}\` (on line ${this.tokenizer.line}).`, tag.loc);
}
this.currentAttribute = {
name: "",
parts: [],
isQuoted: false,
isDynamic: false,
start: _builders2.default.pos(this.tokenizer.line, this.tokenizer.column),
valueStartLine: 0,
valueStartColumn: 0
};
}
appendToAttributeName(char) {
this.currentAttr.name += char;
}
beginAttributeValue(isQuoted) {
this.currentAttr.isQuoted = isQuoted;
this.currentAttr.valueStartLine = this.tokenizer.line;
this.currentAttr.valueStartColumn = this.tokenizer.column;
}
appendToAttributeValue(char) {
let parts = this.currentAttr.parts;
let lastPart = parts[parts.length - 1];
if (lastPart && lastPart.type === 'TextNode') {
lastPart.chars += char;
// update end location for each added char
lastPart.loc.end.line = this.tokenizer.line;
lastPart.loc.end.column = this.tokenizer.column;
} else {
// initially assume the text node is a single char
let loc = _builders2.default.loc(this.tokenizer.line, this.tokenizer.column, this.tokenizer.line, this.tokenizer.column);
// correct for `\n` as first char
if (char === '\n') {
loc.start.line -= 1;
loc.start.column = lastPart ? lastPart.loc.end.column : this.currentAttr.valueStartColumn;
}
let text = _builders2.default.text(char, loc);
parts.push(text);
}
}
finishAttributeValue() {
let { name, parts, isQuoted, isDynamic, valueStartLine, valueStartColumn } = this.currentAttr;
let value = assembleAttributeValue(parts, isQuoted, isDynamic, this.tokenizer.line);
value.loc = _builders2.default.loc(valueStartLine, valueStartColumn, this.tokenizer.line, this.tokenizer.column);
let loc = _builders2.default.loc(this.currentAttr.start.line, this.currentAttr.start.column, this.tokenizer.line, this.tokenizer.column);
let attribute = _builders2.default.attr(name, value, loc);
this.currentStartTag.attributes.push(attribute);
}
reportSyntaxError(message) {
throw new _syntaxError2.default(`Syntax error at line ${this.tokenizer.line} col ${this.tokenizer.column}: ${message}`, _builders2.default.loc(this.tokenizer.line, this.tokenizer.column));
}
}
exports.TokenizerEventHandlers = TokenizerEventHandlers;
;
function assembleAttributeValue(parts, isQuoted, isDynamic, line) {
if (isDynamic) {
if (isQuoted) {
return assembleConcatenatedValue(parts);
} else {
if (parts.length === 1 || parts.length === 2 && parts[1].type === 'TextNode' && parts[1].chars === '/') {
return parts[0];
} else {
throw new _syntaxError2.default(`An unquoted attribute value must be a string or a mustache, ` + `preceeded by whitespace or a '=' character, and ` + `followed by whitespace, a '>' character, or '/>' (on line ${line})`, _builders2.default.loc(line, 0));
}
}
} else {
return parts.length > 0 ? parts[0] : _builders2.default.text("");
}
}
function assembleConcatenatedValue(parts) {
for (let i = 0; i < parts.length; i++) {
let part = parts[i];
if (part.type !== 'MustacheStatement' && part.type !== 'TextNode') {
throw new _syntaxError2.default("Unsupported node in quoted attribute value: " + part['type'], part.loc);
}
}
return _builders2.default.concat(parts);
}
function 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.
// <input> or <br />, so we need to check for that here. Otherwise, we would
// throw an error for those cases.
error = "Invalid end tag " + formatEndTagInfo(tag) + " (void elements cannot have end tags).";
} else if (element.tag === undefined) {
error = "Closing tag " + formatEndTagInfo(tag) + " without an open tag.";
} else if (element.tag !== tag.name) {
error = "Closing tag " + formatEndTagInfo(tag) + " did not match last open tag `" + element.tag + "` (on line " + element.loc.start.line + ").";
}
if (error) {
throw new _syntaxError2.default(error, element.loc);
}
}
function formatEndTagInfo(tag) {
return "`" + tag.name + "` (on line " + tag.loc.end.line + ")";
}
const syntax = exports.syntax = {
parse: preprocess,
builders: _builders2.default,
print: _print2.default,
traverse: _traverse2.default,
Walker: _walker2.default
};
function preprocess(html, options) {
let ast = typeof html === 'object' ? html : handlebars.parse(html);
let program = new TokenizerEventHandlers(html, options).acceptNode(ast);
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 = (0, _util.assign)({}, options, { syntax }, { plugins: undefined });
let pluginResult = transform(env);
(0, _traverse2.default)(program, pluginResult.visitors);
}
}
return program;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9wYXJzZXIvdG9rZW5pemVyLWV2ZW50LWhhbmRsZXJzLmpzIl0sIm5hbWVzIjpbInByZXByb2Nlc3MiLCJoYW5kbGViYXJzIiwidm9pZE1hcCIsIk9iamVjdCIsImNyZWF0ZSIsInZvaWRUYWdOYW1lcyIsInNwbGl0IiwiZm9yRWFjaCIsInRhZ05hbWUiLCJUb2tlbml6ZXJFdmVudEhhbmRsZXJzIiwiY29uc3RydWN0b3IiLCJhcmd1bWVudHMiLCJ0YWdPcGVuTGluZSIsInRhZ09wZW5Db2x1bW4iLCJyZXNldCIsImN1cnJlbnROb2RlIiwiYmVnaW5Db21tZW50IiwiY29tbWVudCIsImxvYyIsInNvdXJjZSIsInN0YXJ0IiwicG9zIiwiZW5kIiwiYXBwZW5kVG9Db21tZW50RGF0YSIsImNoYXIiLCJjdXJyZW50Q29tbWVudCIsInZhbHVlIiwiZmluaXNoQ29tbWVudCIsInRva2VuaXplciIsImxpbmUiLCJjb2x1bW4iLCJjdXJyZW50RWxlbWVudCIsImJlZ2luRGF0YSIsInRleHQiLCJhcHBlbmRUb0RhdGEiLCJjdXJyZW50RGF0YSIsImNoYXJzIiwiZmluaXNoRGF0YSIsInRhZ09wZW4iLCJiZWdpblN0YXJ0VGFnIiwidHlwZSIsIm5hbWUiLCJhdHRyaWJ1dGVzIiwibW9kaWZpZXJzIiwiY29tbWVudHMiLCJzZWxmQ2xvc2luZyIsImJlZ2luRW5kVGFnIiwiZmluaXNoVGFnIiwidGFnIiwiY3VycmVudFRhZyIsImZpbmlzaFN0YXJ0VGFnIiwiZmluaXNoRW5kVGFnIiwiY3VycmVudFN0YXJ0VGFnIiwiZWxlbWVudCIsImVsZW1lbnRTdGFjayIsInB1c2giLCJpc1ZvaWQiLCJwb3AiLCJwYXJlbnQiLCJ2YWxpZGF0ZUVuZFRhZyIsIm1hcmtUYWdBc1NlbGZDbG9zaW5nIiwiYXBwZW5kVG9UYWdOYW1lIiwiYmVnaW5BdHRyaWJ1dGUiLCJjdXJyZW50QXR0cmlidXRlIiwicGFydHMiLCJpc1F1b3RlZCIsImlzRHluYW1pYyIsInZhbHVlU3RhcnRMaW5lIiwidmFsdWVTdGFydENvbHVtbiIsImFwcGVuZFRvQXR0cmlidXRlTmFtZSIsImN1cnJlbnRBdHRyIiwiYmVnaW5BdHRyaWJ1dGVWYWx1ZSIsImFwcGVuZFRvQXR0cmlidXRlVmFsdWUiLCJsYXN0UGFydCIsImxlbmd0aCIsImZpbmlzaEF0dHJpYnV0ZVZhbHVlIiwiYXNzZW1ibGVBdHRyaWJ1dGVWYWx1ZSIsImF0dHJpYnV0ZSIsImF0dHIiLCJyZXBvcnRTeW50YXhFcnJvciIsIm1lc3NhZ2UiLCJhc3NlbWJsZUNvbmNhdGVuYXRlZFZhbHVlIiwiaSIsInBhcnQiLCJjb25jYXQiLCJlcnJvciIsImZvcm1hdEVuZFRhZ0luZm8iLCJ1bmRlZmluZWQiLCJzeW50YXgiLCJwYXJzZSIsImJ1aWxkZXJzIiwicHJpbnQiLCJ0cmF2ZXJzZSIsIldhbGtlciIsImh0bWwiLCJvcHRpb25zIiwiYXN0IiwicHJvZ3JhbSIsImFjY2VwdE5vZGUiLCJwbHVnaW5zIiwibCIsInRyYW5zZm9ybSIsImVudiIsInBsdWdpblJlc3VsdCIsInZpc2l0b3JzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7UUFrT2dCQSxVLEdBQUFBLFU7O0FBbE9oQjs7OztBQUNBOztBQUNBOztBQUNBOzs7O0FBRUE7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7O0lBQVlDLFU7O0FBQ1o7Ozs7OztBQUNBLE1BQU1DLFVBQVVDLE9BQU9DLE1BQVAsQ0FBYyxJQUFkLENBQWhCO0FBQ0EsSUFBSUMsZUFBZSxxRkFBbkI7QUFDQUEsYUFBYUMsS0FBYixDQUFtQixHQUFuQixFQUF3QkMsT0FBeEIsQ0FBZ0NDLFdBQVc7QUFDdkNOLFlBQVFNLE9BQVIsSUFBbUIsSUFBbkI7QUFDSCxDQUZEO0FBR08sTUFBTUMsc0JBQU4sd0RBQTREO0FBQy9EQyxrQkFBYztBQUNWLGNBQU0sR0FBR0MsU0FBVDtBQUNBLGFBQUtDLFdBQUwsR0FBbUIsQ0FBbkI7QUFDQSxhQUFLQyxhQUFMLEdBQXFCLENBQXJCO0FBQ0g7QUFDREMsWUFBUTtBQUNKLGFBQUtDLFdBQUwsR0FBbUIs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LE9BQVIsQ0FBZ0JILEdBQWhCLENBQW9CdEIsTUFBeEMsRUFBZ0RRLElBQUlrQixDQUFwRCxFQUF1RGxCLEdBQXZELEVBQTREO0FBQ3hELGdCQUFJbUIsWUFBWU4sUUFBUUksT0FBUixDQUFnQkgsR0FBaEIsQ0FBb0JkLENBQXBCLENBQWhCO0FBQ0EsZ0JBQUlvQixNQUFNLGtCQUFPLEVBQVAsRUFBV1AsT0FBWCxFQUFvQixFQUFFUCxNQUFGLEVBQXBCLEVBQWdDLEVBQUVXLFNBQVNaLFNBQVgsRUFBaEMsQ0FBVjtBQUNBLGdCQUFJZ0IsZUFBZUYsVUFBVUMsR0FBVixDQUFuQjtBQUNBLG9DQUFTTCxPQUFULEVBQWtCTSxhQUFhQyxRQUEvQjtBQUNIO0FBQ0o7QUFDRCxXQUFPUCxPQUFQO0FBQ0giLCJmaWxlIjoibGliL3BhcnNlci90b2tlbml6ZXItZXZlbnQtaGFuZGxlcnMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgYiwgeyBTWU5USEVUSUMgfSBmcm9tIFwiLi4vYnVpbGRlcnNcIjtcbmltcG9ydCB7IGFwcGVuZENoaWxkLCBwYXJzZUVsZW1lbnRCbG9ja1BhcmFtcyB9IGZyb20gXCIuLi91dGlsc1wiO1xuaW1wb3J0IHsgSGFuZGxlYmFyc05vZGVWaXNpdG9ycyB9IGZyb20gJy4vaGFuZGxlYmFycy1ub2RlLXZpc2l0b3JzJztcbmltcG9ydCBTeW50YXhFcnJvciBmcm9tICcuLi9lcnJvcnMvc3ludGF4LWVycm9yJztcbmltcG9ydCBidWlsZGVycyBmcm9tIFwiLi4vYnVpbGRlcnNcIjtcbmltcG9ydCB0cmF2ZXJzZSBmcm9tIFwiLi4vdHJhdmVyc2FsL3RyYXZlcnNlXCI7XG5pbXBvcnQgcHJpbnQgZnJvbSBcIi4uL2dlbmVyYXRpb24vcHJpbnRcIjtcbmltcG9ydCBXYWxrZXIgZnJvbSBcIi4uL3RyYXZlcnNhbC93YWxrZXJcIjtcbmltcG9ydCAqIGFzIGhhbmRsZWJhcnMgZnJvbSBcImhhbmRsZWJhcnNcIjtcbmltcG9ydCB7IGFzc2lnbiB9IGZyb20gJ0BnbGltbWVyL3V0aWwnO1xuY29uc3Qgdm9pZE1hcCA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG5sZXQgdm9pZFRhZ05hbWVzID0gXCJhcmVhIGJhc2UgYnIgY29sIGNvbW1hbmQgZW1iZWQgaHIgaW1nIGlucHV0IGtleWdlbiBsaW5rIG1ldGEgcGFyYW0gc291cmNlIHRyYWNrIHdiclwiO1xudm9pZFRhZ05hbWVzLnNwbGl0KFwiIFwiKS5mb3JFYWNoKHRhZ05hbWUgPT4ge1xuICAgIHZvaWRNYXBbdGFnTmFtZV0gPSB0cnVlO1xufSk7XG5leHBvcnQgY2xhc3MgVG9rZW5pemVyRXZlbnRIYW5kbGVycyBleHRlbmRzIEhhbmRsZWJhcnNOb2RlVmlzaXRvcnMge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICB0aGlzLnRhZ09wZW5MaW5lID0gMDtcbiAgICAgICAgdGhpcy50YWdPcGVuQ29sdW1uID0gMDtcbiAgICB9XG4gICAgcmVzZXQoKSB7XG4gICAgICAgIHRoaXMuY3VycmVudE5vZGUgPSBudWxsO1xuICAgIH1cbiAgICAvLyBDb21tZW50XG4gICAgYmVnaW5Db21tZW50KCkge1xuICAgICAgICB0aGlzLmN1cnJlbnROb2RlID0gYi5jb21tZW50KFwiXCIpO1xuICAgICAgICB0aGlzLmN1cnJlbnROb2RlLmxvYyA9IHtcbiAgICAgICAgICAgIHNvdXJjZTogbnVsbCxcbiAgICAgICAgICAgIHN0YXJ0OiBiLnBvcyh0aGlzLnRhZ09wZW5MaW5lLCB0aGlzLnRhZ09wZW5Db2x1bW4pLFxuICAgICAgICAgICAgZW5kOiBudWxsXG4gICAgICAgIH07XG4gICAgfVxuICAgIGFwcGVuZFRvQ29tbWVudERhdGEoY2hhcikge1xuICAgICAgICB0aGlzLmN1cnJlbnRDb21tZW50LnZhbHVlICs9IGNoYXI7XG4gICAgfVxuICAgIGZpbmlzaENvbW1lbnQoKSB7XG4gICAgICAgIHRoaXMuY3VycmVudENvbW1lbnQubG9jLmVuZCA9IGIucG9zKHRoaXMudG9rZW5pemVyLmxpbmUsIHRoaXMudG9rZW5pemVyLmNvbHVtbik7XG4gICAgICAgIGFwcGVuZENoaWxkKHRoaXMuY3VycmVudEVsZW1lbnQoKSwgdGhpcy5jdXJyZW50Q29tbWVudCk7XG4gICAgfVxuICAgIC8vIERhdGFcbiAgICBiZWdpbkRhdGEoKSB7XG4gICAgICAgIHRoaXMuY3VycmVudE5vZGUgPSBiLnRleHQoKTtcbiAgICAgICAgdGhpcy5jdXJyZW50Tm9kZS5sb2MgPSB7XG4gICAgICAgICAgICBzb3VyY2U6IG51bGwsXG4gICAgICAgICAgICBzdGFydDogYi5wb3ModGhpcy50b2tlbml6ZXIubGluZSwgdGhpcy50b2tlbml6ZXIuY29sdW1uKSxcbiAgICAgICAgICAgIGVuZDogbnVsbFxuICAgICAgICB9O1xuICAgIH1cbiAgICBhcHBlbmRUb0RhdGEoY2hhcikge1xuICAgICAgICB0aGlzLmN1cnJlbnREYXRhLmNoYXJzICs9IGNoYXI7XG4gICAgfVxuICAgIGZpbmlzaERhdGEoKSB7XG4gICAgICAgIHRoaXMuY3VycmVudERhdGEubG9jLmVuZCA9IGIucG9zKHRoaXMudG9rZW5pemVyLmxpbmUsIHRoaXMudG9rZW5pemVyLmNvbHVtbik7XG4gICAgICAgIGFwcGVuZENoaWxkKHRoaXMuY3VycmVudEVsZW1lbnQoKSwgdGhpcy5jdXJyZW50RGF0YSk7XG4gICAgfVxuICAgIC8vIFRhZ3MgLSBiYXNpY1xuICAgIHRhZ09wZW4oKSB7XG4gICAgICAgIHRoaXMudGFnT3BlbkxpbmUgPSB0aGlzLnRva2VuaXplci5saW5lO1xuICAgICAgICB0aGlzLnRhZ09wZW5Db2x1bW4gPSB0aGlzLnRva2VuaXplci5jb2x1bW47XG4gICAgfVxuICAgIGJlZ2luU3RhcnRUYWcoKSB7XG4gICAgICAgIHRoaXMuY3VycmVudE5vZGUgPSB7XG4gICAgICAgICAgICB0eXBlOiAnU3RhcnRUYWcnLFxuICAgICAgICAgICAgbmFtZTogXCJcIixcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IFtdLFxuICAgICAgICAgICAgbW9kaWZpZXJzOiBbXSxcbiAgICAgICAgICAgIGNvbW1lbnRzOiBbXSxcbiAgICAgICAgICAgIHNlbGZDbG9zaW5nOiBmYWxzZSxcbiAgICAgICAgICAgIGxvYzogU1lOVEhFVElDXG4gICAgICAgIH07XG4gICAgfVxuICAgIGJlZ2luRW5kVGFnKCkge1xuICAgICAgICB0aGlzLmN1cnJlbnROb2RlID0ge1xuICAgICAgICAgICAgdHlwZTogJ0VuZFRhZycsXG4gICAgICAgICAgICBuYW1lOiBcIlwiLFxuICAgICAgICAgICAgYXR0cmlidXRlczogW10sXG4gICAgICAgICAgICBtb2RpZmllcnM6IFtdLFxuICAgICAgICAgICAgY29tbWVudHM6IFtdLFxuICAgICAgICAgICAgc2VsZkNsb3Npbmc6IGZhbHNlLFxuICAgICAgICAgICAgbG9jOiBTWU5USEVUSUNcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZmluaXNoVGFnKCkge1xuICAgICAgICBsZXQgeyBsaW5lLCBjb2x1bW4gfSA9IHRoaXMudG9rZW5pemVyO1xuICAgICAgICBsZXQgdGFnID0gdGhpcy5jdXJyZW50VGFnO1xuICAgICAgICB0YWcubG9jID0gYi5sb2ModGhpcy50YWdPcGVuTGluZSwgdGhpcy50YWdPcGVuQ29sdW1uLCBsaW5lLCBjb2x1bW4pO1xuICAgICAgICBpZiAodGFnLnR5cGUgPT09ICdTdGFydFRhZycpIHtcbiAgICAgICAgICAgIHRoaXMuZmluaXNoU3RhcnRUYWcoKTtcbiAgICAgICAgICAgIGlmICh2b2lkTWFwW3RhZy5uYW1lXSB8fCB0YWcuc2VsZkNsb3NpbmcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpbmlzaEVuZFRhZyh0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0YWcudHlwZSA9PT0gJ0VuZFRhZycpIHtcbiAgICAgICAgICAgIHRoaXMuZmluaXNoRW5kVGFnKGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmaW5pc2hTdGFydFRhZygpIHtcbiAgICAgICAgbGV0IHsgbmFtZSwgYXR0cmlidXRlcywgbW9kaWZpZXJzLCBjb21tZW50cyB9ID0gdGhpcy5jdXJyZW50U3RhcnRUYWc7XG4gICAgICAgIGxldCBsb2MgPSBiLmxvYyh0aGlzLnRhZ09wZW5MaW5lLCB0aGlzLnRhZ09wZW5Db2x1bW4pO1xuICAgICAgICBsZXQgZWxlbWVudCA9IGIuZWxlbWVudChuYW1lLCBhdHRyaWJ1dGVzLCBtb2RpZmllcnMsIFtdLCBjb21tZW50cywgbG9jKTtcbiAgICAgICAgdGhpcy5lbGVtZW50U3RhY2sucHVzaChlbGVtZW50KTtcbiAgICB9XG4gICAgZmluaXNoRW5kVGFnKGlzVm9pZCkge1xuICAgICAgICBsZXQgdGFnID0gdGhpcy5jdXJyZW50VGFnO1xuICAgICAgICBsZXQgZWxlbWVudCA9IHRoaXMuZWxlbWVudFN0YWNrLnBvcCgpO1xuICAgICAgICBsZXQgcGFyZW50ID0gdGhpcy5jdXJyZW50RWxlbWVudCgpO1xuICAgICAgICB2YWxpZGF0ZUVuZFRhZyh0YWcsIGVsZW1lbnQsIGlzVm9pZCk7XG4gICAgICAgIGVsZW1lbnQubG9jLmVuZC5saW5lID0gdGhpcy50b2tlbml6ZXIubGluZTtcbiAgICAgICAgZWxlbWVudC5sb2MuZW5kLmNvbHVtbiA9IHRoaXMudG9rZW5pemVyLmNvbHVtbjtcbiAgICAgICAgcGFyc2VFbGVtZW50QmxvY2tQYXJhbXMoZWxlbWVudCk7XG4gICAgICAgIGFwcGVuZENoaWxkKHBhcmVudCwgZWxlbWVudCk7XG4gICAgfVxuICAgIG1hcmtUYWdBc1NlbGZDbG9zaW5nKCkge1xuICAgICAgICB0aGlzLmN1cnJlbnRUYWcuc2VsZkNsb3NpbmcgPSB0cnVlO1xuICAgIH1cbiAgICAvLyBUYWdzIC0gbmFtZVxuICAgIGFwcGVuZFRvVGFnTmFtZShjaGFyKSB7XG4gICAgICAgIHRoaXMuY3VycmVudFRhZy5uYW1lICs9IGNoYXI7XG4gICAgfVxuICAgIC8vIFRhZ3MgLSBhdHRyaWJ1dGVzXG4gICAgYmVnaW5BdHRyaWJ1dGUoKSB7XG4gICAgICAgIGxldCB0YWcgPSB0aGlzLmN1cnJlbnRUYWc7XG4gICAgICAgIGlmICh0YWcudHlwZSA9PT0gJ0VuZFRhZycpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihgSW52YWxpZCBlbmQgdGFnOiBjbG9zaW5nIHRhZyBtdXN0IG5vdCBoYXZlIGF0dHJpYnV0ZXMsIGAgKyBgaW4gXFxgJHt0YWcubmFtZX1cXGAgKG9uIGxpbmUgJHt0aGlzLnRva2VuaXplci5saW5lfSkuYCwgdGFnLmxvYyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jdXJyZW50QXR0cmlidXRlID0ge1xuICAgICAgICAgICAgbmFtZTogXCJcIixcbiAgICAgICAgICAgIHBhcnRzOiBbXSxcbiAgICAgICAgICAgIGlzUXVvdGVkOiBmYWxzZSxcbiAgICAgICAgICAgIGlzRHluYW1pYzogZmFsc2UsXG4gICAgICAgICAgICBzdGFydDogYi5wb3ModGhpcy50b2tlbml6ZXIubGluZSwgdGhpcy50b2tlbml6ZXIuY29sdW1uKSxcbiAgICAgICAgICAgIHZhbHVlU3RhcnRMaW5lOiAwLFxuICAgICAgICAgICAgdmFsdWVTdGFydENvbHVtbjogMFxuICAgICAgICB9O1xuICAgIH1cbiAgICBhcHBlbmRUb0F0dHJpYnV0ZU5hbWUoY2hhcikge1xuICAgICAgICB0aGlzLmN1cnJlbnRBdHRyLm5hbWUgKz0gY2hhcjtcbiAgICB9XG4gICAgYmVnaW5BdHRyaWJ1dGVWYWx1ZShpc1F1b3RlZCkge1xuICAgICAgICB0aGlzLmN1cnJlbnRBdHRyLmlzUXVvdGVkID0gaXNRdW90ZWQ7XG4gICAgICAgIHRoaXMuY3VycmVudEF0dHIudmFsdWVTdGFydExpbmUgPSB0aGlzLnRva2VuaXplci5saW5lO1xuICAgICAgICB0aGlzLmN1cnJlbnRBdHRyLnZhbHVlU3RhcnRDb2x1bW4gPSB0aGlzLnRva2VuaXplci5jb2x1bW47XG4gICAgfVxuICAgIGFwcGVuZFRvQXR0cmlidXRlVmFsdWUoY2hhcikge1xuICAgICAgICBsZXQgcGFydHMgPSB0aGlzLmN1cnJlbnRBdHRyLnBhcnRzO1xuICAgICAgICBsZXQgbGFzdFBhcnQgPSBwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXTtcbiAgICAgICAgaWYgKGxhc3RQYXJ0ICYmIGxhc3RQYXJ0LnR5cGUgPT09ICdUZXh0Tm9kZScpIHtcbiAgICAgICAgICAgIGxhc3RQYXJ0LmNoYXJzICs9IGNoYXI7XG4gICAgICAgICAgICAvLyB1cGRhdGUgZW5kIGxvY2F0aW9uIGZvciBlYWNoIGFkZGVkIGNoYXJcbiAgICAgICAgICAgIGxhc3RQYXJ0LmxvYy5lbmQubGluZSA9IHRoaXMudG9rZW5pemVyLmxpbmU7XG4gICAgICAgICAgICBsYXN0UGFydC5sb2MuZW5kLmNvbHVtbiA9IHRoaXMudG9rZW5pemVyLmNvbHVtbjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGluaXRpYWxseSBhc3N1bWUgdGhlIHRleHQgbm9kZSBpcyBhIHNpbmdsZSBjaGFyXG4gICAgICAgICAgICBsZXQgbG9jID0gYi5sb2ModGhpcy50b2tlbml6ZXIubGluZSwgdGhpcy50b2tlbml6ZXIuY29sdW1uLCB0aGlzLnRva2VuaXplci5saW5lLCB0aGlzLnRva2VuaXplci5jb2x1bW4pO1xuICAgICAgICAgICAgLy8gY29ycmVjdCBmb3IgYFxcbmAgYXMgZmlyc3QgY2hhclxuICAgICAgICAgICAgaWYgKGNoYXIgPT09ICdcXG4nKSB7XG4gICAgICAgICAgICAgICAgbG9jLnN0YXJ0LmxpbmUgLT0gMTtcbiAgICAgICAgICAgICAgICBsb2Muc3RhcnQuY29sdW1uID0gbGFzdFBhcnQgPyBsYXN0UGFydC5sb2MuZW5kLmNvbHVtbiA6IHRoaXMuY3VycmVudEF0dHIudmFsdWVTdGFydENvbHVtbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCB0ZXh0ID0gYi50ZXh0KGNoYXIsIGxvYyk7XG4gICAgICAgICAgICBwYXJ0cy5wdXNoKHRleHQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZpbmlzaEF0dHJpYnV0ZVZhbHVlKCkge1xuICAgICAgICBsZXQgeyBuYW1lLCBwYXJ0cywgaXNRdW90ZWQsIGlzRHluYW1pYywgdmFsdWVTdGFydExpbmUsIHZhbHVlU3RhcnRDb2x1bW4gfSA9IHRoaXMuY3VycmVudEF0dHI7XG4gICAgICAgIGxldCB2YWx1ZSA9IGFzc2VtYmxlQXR0cmlidXRlVmFsdWUocGFydHMsIGlzUXVvdGVkLCBpc0R5bmFtaWMsIHRoaXMudG9rZW5pemVyLmxpbmUpO1xuICAgICAgICB2YWx1ZS5sb2MgPSBiLmxvYyh2YWx1ZVN0YXJ0TGluZSwgdmFsdWVTdGFydENvbHVtbiwgdGhpcy50b2tlbml6ZXIubGluZSwgdGhpcy50b2tlbml6ZXIuY29sdW1uKTtcbiAgICAgICAgbGV0IGxvYyA9IGIubG9jKHRoaXMuY3VycmVudEF0dHIuc3RhcnQubGluZSwgdGhpcy5jdXJyZW50QXR0ci5zdGFydC5jb2x1bW4sIHRoaXMudG9rZW5pemVyLmxpbmUsIHRoaXMudG9rZW5pemVyLmNvbHVtbik7XG4gICAgICAgIGxldCBhdHRyaWJ1dGUgPSBiLmF0dHIobmFtZSwgdmFsdWUsIGxvYyk7XG4gICAgICAgIHRoaXMuY3VycmVudFN0YXJ0VGFnLmF0dHJpYnV0ZXMucHVzaChhdHRyaWJ1dGUpO1xuICAgIH1cbiAgICByZXBvcnRTeW50YXhFcnJvcihtZXNzYWdlKSB7XG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihgU3ludGF4IGVycm9yIGF0IGxpbmUgJHt0aGlzLnRva2VuaXplci5saW5lfSBjb2wgJHt0aGlzLnRva2VuaXplci5jb2x1bW59OiAke21lc3NhZ2V9YCwgYi5sb2ModGhpcy50b2tlbml6ZXIubGluZSwgdGhpcy50b2tlbml6ZXIuY29sdW1uKSk7XG4gICAgfVxufVxuO1xuZnVuY3Rpb24gYXNzZW1ibGVBdHRyaWJ1dGVWYWx1ZShwYXJ0cywgaXNRdW90ZWQsIGlzRHluYW1pYywgbGluZSkge1xuICAgIGlmIChpc0R5bmFtaWMpIHtcbiAgICAgICAgaWYgKGlzUXVvdGVkKSB7XG4gICAgICAgICAgICByZXR1cm4gYXNzZW1ibGVDb25jYXRlbmF0ZWRWYWx1ZShwYXJ0cyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAocGFydHMubGVuZ3RoID09PSAxIHx8IHBhcnRzLmxlbmd0aCA9PT0gMiAmJiBwYXJ0c1sxXS50eXBlID09PSAnVGV4dE5vZGUnICYmIHBhcnRzWzFdLmNoYXJzID09PSAnLycpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFydHNbMF07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihgQW4gdW5xdW90ZWQgYXR0cmlidXRlIHZhbHVlIG11c3QgYmUgYSBzdHJpbmcgb3IgYSBtdXN0YWNoZSwgYCArIGBwcmVjZWVkZWQgYnkgd2hpdGVzcGFjZSBvciBhICc9JyBjaGFyYWN0ZXIsIGFuZCBgICsgYGZvbGxvd2VkIGJ5IHdoaXRlc3BhY2UsIGEgJz4nIGNoYXJhY3Rlciwgb3IgJy8+JyAob24gbGluZSAke2xpbmV9KWAsIGIubG9jKGxpbmUsIDApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBwYXJ0cy5sZW5ndGggPiAwID8gcGFydHNbMF0gOiBiLnRleHQoXCJcIik7XG4gICAgfVxufVxuZnVuY3Rpb24gYXNzZW1ibGVDb25jYXRlbmF0ZWRWYWx1ZShwYXJ0cykge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbGV0IHBhcnQgPSBwYXJ0c1tpXTtcbiAgICAgICAgaWYgKHBhcnQudHlwZSAhPT0gJ011c3RhY2hlU3RhdGVtZW50JyAmJiBwYXJ0LnR5cGUgIT09ICdUZXh0Tm9kZScpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlVuc3VwcG9ydGVkIG5vZGUgaW4gcXVvdGVkIGF0dHJpYnV0ZSB2YWx1ZTogXCIgKyBwYXJ0Wyd0eXBlJ10sIHBhcnQubG9jKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYi5jb25jYXQocGFydHMpO1xufVxuZnVuY3Rpb24gdmFsaWRhdGVFbmRUYWcodGFnLCBlbGVtZW50LCBzZWxmQ2xvc2luZykge1xuICAgIGxldCBlcnJvcjtcbiAgICBpZiAodm9pZE1hcFt0YWcubmFtZV0gJiYgIXNlbGZDbG9zaW5nKSB7XG4gICAgICAgIC8vIEVuZ1RhZyBpcyBhbHNvIGNhbGxlZCBieSBTdGFydFRhZyBmb3Igdm9pZCBhbmQgc2VsZi1jbG9zaW5nIHRhZ3MgKGkuZS5cbiAgICAgICAgLy8gPGlucHV0PiBvciA8YnIgLz4sIHNvIHdlIG5lZWQgdG8gY2hlY2sgZm9yIHRoYXQgaGVyZS4gT3RoZXJ3aXNlLCB3ZSB3b3VsZFxuICAgICAgICAvLyB0aHJvdyBhbiBlcnJvciBmb3IgdGhvc2UgY2FzZXMuXG4gICAgICAgIGVycm9yID0gXCJJbnZhbGlkIGVuZCB0YWcgXCIgKyBmb3JtYXRFbmRUYWdJbmZvKHRhZykgKyBcIiAodm9pZCBlbGVtZW50cyBjYW5ub3QgaGF2ZSBlbmQgdGFncykuXCI7XG4gICAgfSBlbHNlIGlmIChlbGVtZW50LnRhZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGVycm9yID0gXCJDbG9zaW5nIHRhZyBcIiArIGZvcm1hdEVuZFRhZ0luZm8odGFnKSArIFwiIHdpdGhvdXQgYW4gb3BlbiB0YWcuXCI7XG4gICAgfSBlbHNlIGlmIChlbGVtZW50LnRhZyAhPT0gdGFnLm5hbWUpIHtcbiAgICAgICAgZXJyb3IgPSBcIkNsb3NpbmcgdGFnIFwiICsgZm9ybWF0RW5kVGFnSW5mbyh0YWcpICsgXCIgZGlkIG5vdCBtYXRjaCBsYXN0IG9wZW4gdGFnIGBcIiArIGVsZW1lbnQudGFnICsgXCJgIChvbiBsaW5lIFwiICsgZWxlbWVudC5sb2Muc3RhcnQubGluZSArIFwiKS5cIjtcbiAgICB9XG4gICAgaWYgKGVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihlcnJvciwgZWxlbWVudC5sb2MpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGZvcm1hdEVuZFRhZ0luZm8odGFnKSB7XG4gICAgcmV0dXJuIFwiYFwiICsgdGFnLm5hbWUgKyBcImAgKG9uIGxpbmUgXCIgKyB0YWcubG9jLmVuZC5saW5lICsgXCIpXCI7XG59XG5leHBvcnQgY29uc3Qgc3ludGF4ID0ge1xuICAgIHBhcnNlOiBwcmVwcm9jZXNzLFxuICAgIGJ1aWxkZXJzLFxuICAgIHByaW50LFxuICAgIHRyYXZlcnNlLFxuICAgIFdhbGtlclxufTtcbmV4cG9ydCBmdW5jdGlvbiBwcmVwcm9jZXNzKGh0bWwsIG9wdGlvbnMpIHtcbiAgICBsZXQgYXN0ID0gdHlwZW9mIGh0bWwgPT09ICdvYmplY3QnID8gaHRtbCA6IGhhbmRsZWJhcnMucGFyc2UoaHRtbCk7XG4gICAgbGV0IHByb2dyYW0gPSBuZXcgVG9rZW5pemVyRXZlbnRIYW5kbGVycyhodG1sLCBvcHRpb25zKS5hY2NlcHROb2RlKGFzdCk7XG4gICAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5wbHVnaW5zICYmIG9wdGlvbnMucGx1Z2lucy5hc3QpIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IDAsIGwgPSBvcHRpb25zLnBsdWdpbnMuYXN0Lmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgbGV0IHRyYW5zZm9ybSA9IG9wdGlvbnMucGx1Z2lucy5hc3RbaV07XG4gICAgICAgICAgICBsZXQgZW52ID0gYXNzaWduKHt9LCBvcHRpb25zLCB7IHN5bnRheCB9LCB7IHBsdWdpbnM6IHVuZGVmaW5lZCB9KTtcbiAgICAgICAgICAgIGxldCBwbHVnaW5SZXN1bHQgPSB0cmFuc2Zvcm0oZW52KTtcbiAgICAgICAgICAgIHRyYXZlcnNlKHByb2dyYW0sIHBsdWdpblJlc3VsdC52aXNpdG9ycyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHByb2dyYW07XG59Il19