matrix-react-sdk
Version:
SDK for matrix.org using React
415 lines (337 loc) • 39.9 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.parsePlainTextMessage = parsePlainTextMessage;
exports.parseEvent = parseEvent;
var _dom = require("./dom");
var _HtmlUtils = require("../HtmlUtils");
var _Permalinks = require("../utils/permalinks/Permalinks");
var _SdkConfig = _interopRequireDefault(require("../SdkConfig"));
/*
Copyright 2019 New Vector Ltd
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
function parseAtRoomMentions(text
/*: string*/
, partCreator
/*: PartCreator*/
) {
const ATROOM = "@room";
const parts = [];
text.split(ATROOM).forEach((textPart, i, arr) => {
if (textPart.length) {
parts.push(partCreator.plain(textPart));
} // it's safe to never append @room after the last textPart
// as split will report an empty string at the end if
// `text` ended in @room.
const isLast = i === arr.length - 1;
if (!isLast) {
parts.push(partCreator.atRoomPill(ATROOM));
}
});
return parts;
}
function parseLink(a
/*: HTMLAnchorElement*/
, partCreator
/*: PartCreator*/
) {
const {
href
} = a;
const resourceId = (0, _Permalinks.getPrimaryPermalinkEntity)(href); // The room/user ID
const prefix = resourceId ? resourceId[0] : undefined; // First character of ID
switch (prefix) {
case "@":
return partCreator.userPill(a.textContent, resourceId);
case "#":
return partCreator.roomPill(resourceId);
default:
{
if (href === a.textContent) {
return partCreator.plain(a.textContent);
} else {
return partCreator.plain(`[${a.textContent.replace(/[[\\\]]/g, c => "\\" + c)}](${href})`);
}
}
}
}
function parseImage(img
/*: HTMLImageElement*/
, partCreator
/*: PartCreator*/
) {
const {
src
} = img;
return partCreator.plain(`![${img.alt.replace(/[[\\\]]/g, c => "\\" + c)}](${src})`);
}
function parseCodeBlock(n
/*: HTMLElement*/
, partCreator
/*: PartCreator*/
) {
const parts = [];
let language = "";
if (n.firstChild && n.firstChild.nodeName === "CODE") {
for (const className of n.firstChild.classList) {
if (className.startsWith("language-") && !className.startsWith("language-_")) {
language = className.substr("language-".length);
break;
}
}
}
const preLines = ("```" + language + "\n" + n.textContent + "```").split("\n");
preLines.forEach((l, i) => {
parts.push(partCreator.plain(l));
if (i < preLines.length - 1) {
parts.push(partCreator.newline());
}
});
return parts;
}
function parseHeader(el
/*: HTMLElement*/
, partCreator
/*: PartCreator*/
) {
const depth = parseInt(el.nodeName.substr(1), 10);
return partCreator.plain("#".repeat(depth) + " ");
}
function parseElement(n
/*: HTMLElement*/
, partCreator
/*: PartCreator*/
, lastNode
/*: HTMLElement | undefined*/
, state
/*: IState*/
) {
switch (n.nodeName) {
case "H1":
case "H2":
case "H3":
case "H4":
case "H5":
case "H6":
return parseHeader(n, partCreator);
case "A":
return parseLink(n, partCreator);
case "IMG":
return parseImage(n, partCreator);
case "BR":
return partCreator.newline();
case "EM":
return partCreator.plain(`_${n.textContent}_`);
case "STRONG":
return partCreator.plain(`**${n.textContent}**`);
case "PRE":
return parseCodeBlock(n, partCreator);
case "CODE":
return partCreator.plain(`\`${n.textContent}\``);
case "DEL":
return partCreator.plain(`<del>${n.textContent}</del>`);
case "LI":
{
const indent = " ".repeat(state.listDepth - 1);
if (n.parentElement.nodeName === "OL") {
// The markdown parser doesn't do nested indexed lists at all, but this supports it anyway.
const index = state.listIndex[state.listIndex.length - 1];
state.listIndex[state.listIndex.length - 1] += 1;
return partCreator.plain(`${indent}${index}. `);
} else {
return partCreator.plain(`${indent}- `);
}
}
case "P":
{
if (lastNode) {
return partCreator.newline();
}
break;
}
case "DIV":
case "SPAN":
{
// math nodes are translated back into delimited latex strings
if (n.hasAttribute("data-mx-maths")) {
const delimLeft = n.nodeName == "SPAN" ? ((_SdkConfig.default.get()['latex_maths_delims'] || {})['inline'] || {})['left'] || "\\(" : ((_SdkConfig.default.get()['latex_maths_delims'] || {})['display'] || {})['left'] || "\\[";
const delimRight = n.nodeName == "SPAN" ? ((_SdkConfig.default.get()['latex_maths_delims'] || {})['inline'] || {})['right'] || "\\)" : ((_SdkConfig.default.get()['latex_maths_delims'] || {})['display'] || {})['right'] || "\\]";
const tex = n.getAttribute("data-mx-maths");
return partCreator.plain(delimLeft + tex + delimRight);
} else if (!checkDescendInto(n)) {
return partCreator.plain(n.textContent);
}
break;
}
case "OL":
state.listIndex.push(n.start || 1);
/* falls through */
case "UL":
state.listDepth = (state.listDepth || 0) + 1;
/* falls through */
default:
// don't textify block nodes we'll descend into
if (!checkDescendInto(n)) {
return partCreator.plain(n.textContent);
}
}
}
function checkDescendInto(node) {
switch (node.nodeName) {
case "PRE":
// a code block is textified in parseCodeBlock
// as we don't want to preserve markup in it,
// so no need to descend into it
return false;
default:
return (0, _HtmlUtils.checkBlockNode)(node);
}
}
function checkIgnored(n) {
if (n.nodeType === Node.TEXT_NODE) {
// Element adds \n text nodes in a lot of places,
// which should be ignored
return n.nodeValue === "\n";
} else if (n.nodeType === Node.ELEMENT_NODE) {
return n.nodeName === "MX-REPLY";
}
return true;
}
const QUOTE_LINE_PREFIX = "> ";
function prefixQuoteLines(isFirstNode, parts, partCreator) {
// a newline (to append a > to) wouldn't be added to parts for the first line
// if there was no content before the BLOCKQUOTE, so handle that
if (isFirstNode) {
parts.splice(0, 0, partCreator.plain(QUOTE_LINE_PREFIX));
}
for (let i = 0; i < parts.length; i += 1) {
if (parts[i].type === "newline") {
parts.splice(i + 1, 0, partCreator.plain(QUOTE_LINE_PREFIX));
i += 1;
}
}
}
function parseHtmlMessage(html
/*: string*/
, partCreator
/*: PartCreator*/
, isQuotedMessage
/*: boolean*/
) {
// no nodes from parsing here should be inserted in the document,
// as scripts in event handlers, etc would be executed then.
// we're only taking text, so that is fine
const rootNode = new DOMParser().parseFromString(html, "text/html").body;
const parts = [];
let lastNode;
let inQuote = isQuotedMessage;
const state
/*: IState*/
= {
listIndex: []
};
function onNodeEnter(n) {
if (checkIgnored(n)) {
return false;
}
if (n.nodeName === "BLOCKQUOTE") {
inQuote = true;
}
const newParts = [];
if (lastNode && ((0, _HtmlUtils.checkBlockNode)(lastNode) || (0, _HtmlUtils.checkBlockNode)(n))) {
newParts.push(partCreator.newline());
}
if (n.nodeType === Node.TEXT_NODE) {
newParts.push(...parseAtRoomMentions(n.nodeValue, partCreator));
} else if (n.nodeType === Node.ELEMENT_NODE) {
const parseResult = parseElement(n, partCreator, lastNode, state);
if (parseResult) {
if (Array.isArray(parseResult)) {
newParts.push(...parseResult);
} else {
newParts.push(parseResult);
}
}
}
if (newParts.length && inQuote) {
const isFirstPart = parts.length === 0;
prefixQuoteLines(isFirstPart, newParts, partCreator);
}
parts.push(...newParts);
const descend = checkDescendInto(n); // when not descending (like for PRE), onNodeLeave won't be called to set lastNode
// so do that here.
lastNode = descend ? null : n;
return descend;
}
function onNodeLeave(n) {
if (checkIgnored(n)) {
return;
}
switch (n.nodeName) {
case "BLOCKQUOTE":
inQuote = false;
break;
case "OL":
state.listIndex.pop();
/* falls through */
case "UL":
state.listDepth -= 1;
break;
}
lastNode = n;
}
(0, _dom.walkDOMDepthFirst)(rootNode, onNodeEnter, onNodeLeave);
return parts;
}
function parsePlainTextMessage(body
/*: string*/
, partCreator
/*: PartCreator*/
, isQuotedMessage
/*: boolean*/
) {
const lines = body.split(/\r\n|\r|\n/g); // split on any new-line combination not just \n, collapses \r\n
return lines.reduce((parts, line, i) => {
if (isQuotedMessage) {
parts.push(partCreator.plain(QUOTE_LINE_PREFIX));
}
parts.push(...parseAtRoomMentions(line, partCreator));
const isLast = i === lines.length - 1;
if (!isLast) {
parts.push(partCreator.newline());
}
return parts;
}, []);
}
function parseEvent(event
/*: MatrixEvent*/
, partCreator
/*: PartCreator*/
, {
isQuotedMessage = false
} = {}) {
const content = event.getContent();
let parts;
if (content.format === "org.matrix.custom.html") {
parts = parseHtmlMessage(content.formatted_body || "", partCreator, isQuotedMessage);
} else {
parts = parsePlainTextMessage(content.body || "", partCreator, isQuotedMessage);
}
if (content.msgtype === "m.emote") {
parts.unshift(partCreator.plain("/me "));
}
return parts;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9lZGl0b3IvZGVzZXJpYWxpemUudHMiXSwibmFtZXMiOlsicGFyc2VBdFJvb21NZW50aW9ucyIsInRleHQiLCJwYXJ0Q3JlYXRvciIsIkFUUk9PTSIsInBhcnRzIiwic3BsaXQiLCJmb3JFYWNoIiwidGV4dFBhcnQiLCJpIiwiYXJyIiwibGVuZ3RoIiwicHVzaCIsInBsYWluIiwiaXNMYXN0IiwiYXRSb29tUGlsbCIsInBhcnNlTGluayIsImEiLCJocmVmIiwicmVzb3VyY2VJZCIsInByZWZpeCIsInVuZGVmaW5lZCIsInVzZXJQaWxsIiwidGV4dENvbnRlbnQiLCJyb29tUGlsbCIsInJlcGxhY2UiLCJjIiwicGFyc2VJbWFnZSIsImltZyIsInNyYyIsImFsdCIsInBhcnNlQ29kZUJsb2NrIiwibiIsImxhbmd1YWdlIiwiZmlyc3RDaGlsZCIsIm5vZGVOYW1lIiwiY2xhc3NOYW1lIiwiY2xhc3NMaXN0Iiwic3RhcnRzV2l0aCIsInN1YnN0ciIsInByZUxpbmVzIiwibCIsIm5ld2xpbmUiLCJwYXJzZUhlYWRlciIsImVsIiwiZGVwdGgiLCJwYXJzZUludCIsInJlcGVhdCIsInBhcnNlRWxlbWVudCIsImxhc3ROb2RlIiwic3RhdGUiLCJpbmRlbnQiLCJsaXN0RGVwdGgiLCJwYXJlbnRFbGVtZW50IiwiaW5kZXgiLCJsaXN0SW5kZXgiLCJoYXNBdHRyaWJ1dGUiLCJkZWxpbUxlZnQiLCJTZGtDb25maWciLCJnZXQiLCJkZWxpbVJpZ2h0IiwidGV4IiwiZ2V0QXR0cmlidXRlIiwiY2hlY2tEZXNjZW5kSW50byIsInN0YXJ0Iiwibm9kZSIsImNoZWNrSWdub3JlZCIsIm5vZGVUeXBlIiwiTm9kZSIsIlRFWFRfTk9ERSIsIm5vZGVWYWx1ZSIsIkVMRU1FTlRfTk9ERSIsIlFVT1RFX0xJTkVfUFJFRklYIiwicHJlZml4UXVvdGVMaW5lcyIsImlzRmlyc3ROb2RlIiwic3BsaWNlIiwidHlwZSIsInBhcnNlSHRtbE1lc3NhZ2UiLCJodG1sIiwiaXNRdW90ZWRNZXNzYWdlIiwicm9vdE5vZGUiLCJET01QYXJzZXIiLCJwYXJzZUZyb21TdHJpbmciLCJib2R5IiwiaW5RdW90ZSIsIm9uTm9kZUVudGVyIiwibmV3UGFydHMiLCJwYXJzZVJlc3VsdCIsIkFycmF5IiwiaXNBcnJheSIsImlzRmlyc3RQYXJ0IiwiZGVzY2VuZCIsIm9uTm9kZUxlYXZlIiwicG9wIiwicGFyc2VQbGFpblRleHRNZXNzYWdlIiwibGluZXMiLCJyZWR1Y2UiLCJsaW5lIiwicGFyc2VFdmVudCIsImV2ZW50IiwiY29udGVudCIsImdldENvbnRlbnQiLCJmb3JtYXQiLCJmb3JtYXR0ZWRfYm9keSIsIm1zZ3R5cGUiLCJ1bnNoaWZ0Il0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBbUJBOztBQUNBOztBQUNBOztBQUVBOztBQXZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVVBLFNBQVNBLG1CQUFULENBQTZCQztBQUE3QjtBQUFBLEVBQTJDQztBQUEzQztBQUFBLEVBQXFFO0FBQ2pFLFFBQU1DLE1BQU0sR0FBRyxPQUFmO0FBQ0EsUUFBTUMsS0FBSyxHQUFHLEVBQWQ7QUFDQUgsRUFBQUEsSUFBSSxDQUFDSSxLQUFMLENBQVdGLE1BQVgsRUFBbUJHLE9BQW5CLENBQTJCLENBQUNDLFFBQUQsRUFBV0MsQ0FBWCxFQUFjQyxHQUFkLEtBQXNCO0FBQzdDLFFBQUlGLFFBQVEsQ0FBQ0csTUFBYixFQUFxQjtBQUNqQk4sTUFBQUEsS0FBSyxDQUFDTyxJQUFOLENBQVdULFdBQVcsQ0FBQ1UsS0FBWixDQUFrQkwsUUFBbEIsQ0FBWDtBQUNILEtBSDRDLENBSTdDO0FBQ0E7QUFDQTs7O0FBQ0EsVUFBTU0sTUFBTSxHQUFHTCxDQUFDLEtBQUtDLEdBQUcsQ0FBQ0MsTUFBSixHQUFhLENBQWxDOztBQUNBLFFBQUksQ0FBQ0csTUFBTCxFQUFhO0FBQ1RULE1BQUFBLEtBQUssQ0FBQ08sSUFBTixDQUFX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QSxLQUFLLENBQUNPLElBQU4sQ0FBV1QsV0FBVyxDQUFDdUMsT0FBWixFQUFYO0FBQ0g7O0FBQ0QsV0FBT3JDLEtBQVA7QUFDSCxHQVZNLEVBVUosRUFWSSxDQUFQO0FBV0g7O0FBRU0sU0FBUzZGLFVBQVQsQ0FBb0JDO0FBQXBCO0FBQUEsRUFBd0NoRztBQUF4QztBQUFBLEVBQWtFO0FBQUM0RSxFQUFBQSxlQUFlLEdBQUc7QUFBbkIsSUFBNEIsRUFBOUYsRUFBa0c7QUFDckcsUUFBTXFCLE9BQU8sR0FBR0QsS0FBSyxDQUFDRSxVQUFOLEVBQWhCO0FBQ0EsTUFBSWhHLEtBQUo7O0FBQ0EsTUFBSStGLE9BQU8sQ0FBQ0UsTUFBUixLQUFtQix3QkFBdkIsRUFBaUQ7QUFDN0NqRyxJQUFBQSxLQUFLLEdBQUd3RSxnQkFBZ0IsQ0FBQ3VCLE9BQU8sQ0FBQ0csY0FBUixJQUEwQixFQUEzQixFQUErQnBHLFdBQS9CLEVBQTRDNEUsZUFBNUMsQ0FBeEI7QUFDSCxHQUZELE1BRU87QUFDSDFFLElBQUFBLEtBQUssR0FBR3lGLHFCQUFxQixDQUFDTSxPQUFPLENBQUNqQixJQUFSLElBQWdCLEVBQWpCLEVBQXFCaEYsV0FBckIsRUFBa0M0RSxlQUFsQyxDQUE3QjtBQUNIOztBQUNELE1BQUlxQixPQUFPLENBQUNJLE9BQVIsS0FBb0IsU0FBeEIsRUFBbUM7QUFDL0JuRyxJQUFBQSxLQUFLLENBQUNvRyxPQUFOLENBQWN0RyxXQUFXLENBQUNVLEtBQVosQ0FBa0IsTUFBbEIsQ0FBZDtBQUNIOztBQUNELFNBQU9SLEtBQVA7QUFDSCIsInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAxOSBOZXcgVmVjdG9yIEx0ZFxuQ29weXJpZ2h0IDIwMTksIDIwMjAgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4qL1xuXG5pbXBvcnQgeyBNYXRyaXhFdmVudCB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9tb2RlbHMvZXZlbnRcIjtcblxuaW1wb3J0IHsgd2Fsa0RPTURlcHRoRmlyc3QgfSBmcm9tIFwiLi9kb21cIjtcbmltcG9ydCB7IGNoZWNrQmxvY2tOb2RlIH0gZnJvbSBcIi4uL0h0bWxVdGlsc1wiO1xuaW1wb3J0IHsgZ2V0UHJpbWFyeVBlcm1hbGlua0VudGl0eSB9IGZyb20gXCIuLi91dGlscy9wZXJtYWxpbmtzL1Blcm1hbGlua3NcIjtcbmltcG9ydCB7IFBhcnRDcmVhdG9yIH0gZnJvbSBcIi4vcGFydHNcIjtcbmltcG9ydCBTZGtDb25maWcgZnJvbSBcIi4uL1Nka0NvbmZpZ1wiO1xuXG5mdW5jdGlvbiBwYXJzZUF0Um9vbU1lbnRpb25zKHRleHQ6IHN0cmluZywgcGFydENyZWF0b3I6IFBhcnRDcmVhdG9yKSB7XG4gICAgY29uc3QgQVRST09NID0gXCJAcm9vbVwiO1xuICAgIGNvbnN0IHBhcnRzID0gW107XG4gICAgdGV4dC5zcGxpdChBVFJPT00pLmZvckVhY2goKHRleHRQYXJ0LCBpLCBhcnIpID0+IHtcbiAgICAgICAgaWYgKHRleHRQYXJ0Lmxlbmd0aCkge1xuICAgICAgICAgICAgcGFydHMucHVzaChwYXJ0Q3JlYXRvci5wbGFpbih0ZXh0UGFydCkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGl0J3Mgc2FmZSB0byBuZXZlciBhcHBlbmQgQHJvb20gYWZ0ZXIgdGhlIGxhc3QgdGV4dFBhcnRcbiAgICAgICAgLy8gYXMgc3BsaXQgd2lsbCByZXBvcnQgYW4gZW1wdHkgc3RyaW5nIGF0IHRoZSBlbmQgaWZcbiAgICAgICAgLy8gYHRleHRgIGVuZGVkIGluIEByb29tLlxuICAgICAgICBjb25zdCBpc0xhc3QgPSBpID09PSBhcnIubGVuZ3RoIC0gMTtcbiAgICAgICAgaWYgKCFpc0xhc3QpIHtcbiAgICAgICAgICAgIHBhcnRzLnB1c2gocGFydENyZWF0b3IuYXRSb29tUGlsbChBVFJPT00pKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBwYXJ0cztcbn1cblxuZnVuY3Rpb24gcGFyc2VMaW5rKGE6IEhUTUxBbmNob3JFbGVtZW50LCBwYXJ0Q3JlYXRvcjogUGFydENyZWF0b3IpIHtcbiAgICBjb25zdCB7aHJlZn0gPSBhO1xuICAgIGNvbnN0IHJlc291cmNlSWQgPSBnZXRQcmltYXJ5UGVybWFsaW5rRW50aXR5KGhyZWYpOyAvLyBUaGUgcm9vbS91c2VyIElEXG4gICAgY29uc3QgcHJlZml4ID0gcmVzb3VyY2VJZCA/IHJlc291cmNlSWRbMF0gOiB1bmRlZmluZWQ7IC8vIEZpcnN0IGNoYXJhY3RlciBvZiBJRFxuICAgIHN3aXRjaCAocHJlZml4KSB7XG4gICAgICAgIGNhc2UgXCJAXCI6XG4gICAgICAgICAgICByZXR1cm4gcGFydENyZWF0b3IudXNlclBpbGwoYS50ZXh0Q29udGVudCwgcmVzb3VyY2VJZCk7XG4gICAgICAgIGNhc2UgXCIjXCI6XG4gICAgICAgICAgICByZXR1cm4gcGFydENyZWF0b3Iucm9vbVBpbGwocmVzb3VyY2VJZCk7XG4gICAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgICAgIGlmIChocmVmID09PSBhLnRleHRDb250ZW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcnRDcmVhdG9yLnBsYWluKGEudGV4dENvbnRlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFydENyZWF0b3IucGxhaW4oYFske2EudGV4dENvbnRlbnQucmVwbGFjZSgvW1tcXFxcXFxdXS9nLCBjID0+IFwiXFxcXFwiICsgYyl9XSgke2hyZWZ9KWApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZUltYWdlKGltZzogSFRNTEltYWdlRWxlbWVudCwgcGFydENyZWF0b3I6IFBhcnRDcmVhdG9yKSB7XG4gICAgY29uc3QgeyBzcmMgfSA9IGltZztcbiAgICByZXR1cm4gcGFydENyZWF0b3IucGxhaW4oYCFbJHtpbWcuYWx0LnJlcGxhY2UoL1tbXFxcXFxcXV0vZywgYyA9PiBcIlxcXFxcIiArIGMpfV0oJHtzcmN9KWApO1xufVxuXG5mdW5jdGlvbiBwYXJzZUNvZGVCbG9jayhuOiBIVE1MRWxlbWVudCwgcGFydENyZWF0b3I6IFBhcnRDcmVhdG9yKSB7XG4gICAgY29uc3QgcGFydHMgPSBbXTtcbiAgICBsZXQgbGFuZ3VhZ2UgPSBcIlwiO1xuICAgIGlmIChuLmZpcnN0Q2hpbGQgJiYgbi5maXJzdENoaWxkLm5vZGVOYW1lID09PSBcIkNPREVcIikge1xuICAgICAgICBmb3IgKGNvbnN0IGNsYXNzTmFtZSBvZiAoPEhUTUxFbGVtZW50Pm4uZmlyc3RDaGlsZCkuY2xhc3NMaXN0KSB7XG4gICAgICAgICAgICBpZiAoY2xhc3NOYW1lLnN0YXJ0c1dpdGgoXCJsYW5ndWFnZS1cIikgJiYgIWNsYXNzTmFtZS5zdGFydHNXaXRoKFwibGFuZ3VhZ2UtX1wiKSkge1xuICAgICAgICAgICAgICAgIGxhbmd1YWdlID0gY2xhc3NOYW1lLnN1YnN0cihcImxhbmd1YWdlLVwiLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgcHJlTGluZXMgPSAoXCJgYGBcIiArIGxhbmd1YWdlICsgXCJcXG5cIiArIG4udGV4dENvbnRlbnQgKyBcImBgYFwiKS5zcGxpdChcIlxcblwiKTtcbiAgICBwcmVMaW5lcy5mb3JFYWNoKChsLCBpKSA9PiB7XG4gICAgICAgIHBhcnRzLnB1c2gocGFydENyZWF0b3IucGxhaW4obCkpO1xuICAgICAgICBpZiAoaSA8IHByZUxpbmVzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIHBhcnRzLnB1c2gocGFydENyZWF0b3IubmV3bGluZSgpKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBwYXJ0cztcbn1cblxuZnVuY3Rpb24gcGFyc2VIZWFkZXIoZWw6IEhUTUxFbGVtZW50LCBwYXJ0Q3JlYXRvcjogUGFydENyZWF0b3IpIHtcbiAgICBjb25zdCBkZXB0aCA9IHBhcnNlSW50KGVsLm5vZGVOYW1lLnN1YnN0cigxKSwgMTApO1xuICAgIHJldHVybiBwYXJ0Q3JlYXRvci5wbGFpbihcIiNcIi5yZXBlYXQoZGVwdGgpICsgXCIgXCIpO1xufVxuXG5pbnRlcmZhY2UgSVN0YXRlIHtcbiAgICBsaXN0SW5kZXg6IG51bWJlcltdO1xuICAgIGxpc3REZXB0aD86IG51bWJlcjtcbn1cblxuZnVuY3Rpb24gcGFyc2VFbGVtZW50KG46IEhUTUxFbGVtZW50LCBwYXJ0Q3JlYXRvcjogUGFydENyZWF0b3IsIGxhc3ROb2RlOiBIVE1MRWxlbWVudCB8IHVuZGVmaW5lZCwgc3RhdGU6IElTdGF0ZSkge1xuICAgIHN3aXRjaCAobi5ub2RlTmFtZSkge1xuICAgICAgICBjYXNlIFwiSDFcIjpcbiAgICAgICAgY2FzZSBcIkgyXCI6XG4gICAgICAgIGNhc2UgXCJIM1wiOlxuICAgICAgICBjYXNlIFwiSDRcIjpcbiAgICAgICAgY2FzZSBcIkg1XCI6XG4gICAgICAgIGNhc2UgXCJINlwiOlxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlSGVhZGVyKG4sIHBhcnRDcmVhdG9yKTtcbiAgICAgICAgY2FzZSBcIkFcIjpcbiAgICAgICAgICAgIHJldHVybiBwYXJzZUxpbmsoPEhUTUxBbmNob3JFbGVtZW50Pm4sIHBhcnRDcmVhdG9yKTtcbiAgICAgICAgY2FzZSBcIklNR1wiOlxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlSW1hZ2UoPEhUTUxJbWFnZUVsZW1lbnQ+biwgcGFydENyZWF0b3IpO1xuICAgICAgICBjYXNlIFwiQlJcIjpcbiAgICAgICAgICAgIHJldHVybiBwYXJ0Q3JlYXRvci5uZXdsaW5lKCk7XG4gICAgICAgIGNhc2UgXCJFTVwiOlxuICAgICAgICAgICAgcmV0dXJuIHBhcnRDcmVhdG9yLnBsYWluKGBfJHtuLnRleHRDb250ZW50fV9gKTtcbiAgICAgICAgY2FzZSBcIlNUUk9OR1wiOlxuICAgICAgICAgICAgcmV0dXJuIHBhcnRDcmVhdG9yLnBsYWluKGAqKiR7bi50ZXh0Q29udGVudH0qKmApO1xuICAgICAgICBjYXNlIFwiUFJFXCI6XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VDb2RlQmxvY2sobiwgcGFydENyZWF0b3IpO1xuICAgICAgICBjYXNlIFwiQ09ERVwiOlxuICAgICAgICAgICAgcmV0dXJuIHBhcnRDcmVhdG9yLnBsYWluKGBcXGAke24udGV4dENvbnRlbnR9XFxgYCk7XG4gICAgICAgIGNhc2UgXCJERUxcIjpcbiAgICAgICAgICAgIHJldHVybiBwYXJ0Q3JlYXRvci5wbGFpbihgPGRlbD4ke24udGV4dENvbnRlbnR9PC9kZWw+YCk7XG4gICAgICAgIGNhc2UgXCJMSVwiOiB7XG4gICAgICAgICAgICBjb25zdCBpbmRlbnQgPSBcIiAgXCIucmVwZWF0KHN0YXRlLmxpc3REZXB0aCAtIDEpO1xuICAgICAgICAgICAgaWYgKG4ucGFyZW50RWxlbWVudC5ub2RlTmFtZSA9PT0gXCJPTFwiKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIG1hcmtkb3duIHBhcnNlciBkb2Vzbid0IGRvIG5lc3RlZCBpbmRleGVkIGxpc3RzIGF0IGFsbCwgYnV0IHRoaXMgc3VwcG9ydHMgaXQgYW55d2F5LlxuICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gc3RhdGUubGlzdEluZGV4W3N0YXRlLmxpc3RJbmRleC5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgICAgICBzdGF0ZS5saXN0SW5kZXhbc3RhdGUubGlzdEluZGV4Lmxlbmd0aCAtIDFdICs9IDE7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcnRDcmVhdG9yLnBsYWluKGAke2luZGVudH0ke2luZGV4fS4gYCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXJ0Q3JlYXRvci5wbGFpbihgJHtpbmRlbnR9LSBgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXNlIFwiUFwiOiB7XG4gICAgICAgICAgICBpZiAobGFzdE5vZGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFydENyZWF0b3IubmV3bGluZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSBcIkRJVlwiOlxuICAgICAgICBjYXNlIFwiU1BBTlwiOiB7XG4gICAgICAgICAgICAvLyBtYXRoIG5vZGVzIGFyZSB0cmFuc2xhdGVkIGJhY2sgaW50byBkZWxpbWl0ZWQgbGF0ZXggc3RyaW5nc1xuICAgICAgICAgICAgaWYgKG4uaGFzQXR0cmlidXRlKFwiZGF0YS1teC1tYXRoc1wiKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlbGltTGVmdCA9IChuLm5vZGVOYW1lID09IFwiU1BBTlwiKSA/XG4gICAgICAgICAgICAgICAgICAgICgoU2RrQ29uZmlnLmdldCgpWydsYXRleF9tYXRoc19kZWxpbXMnXSB8fCB7fSlbJ2lubGluZSddIHx8IHt9KVsnbGVmdCddIHx8IFwiXFxcXChcIiA6XG4gICAgICAgICAgICAgICAgICAgICgoU2RrQ29uZmlnLmdldCgpWydsYXRleF9tYXRoc19kZWxpbXMnXSB8fCB7fSlbJ2Rpc3BsYXknXSB8fCB7fSlbJ2xlZnQnXSB8fCBcIlxcXFxbXCI7XG4gICAgICAgICAgICAgICAgY29uc3QgZGVsaW1SaWdodCA9IChuLm5vZGVOYW1lID09IFwiU1BBTlwiKSA/XG4gICAgICAgICAgICAgICAgICAgICgoU2RrQ29uZmlnLmdldCgpWydsYXRleF9tYXRoc19kZWxpbXMnXSB8fCB7fSlbJ2lubGluZSddIHx8IHt9KVsncmlnaHQnXSB8fCBcIlxcXFwpXCIgOlxuICAgICAgICAgICAgICAgICAgICAoKFNka0NvbmZpZy5nZXQoKVsnbGF0ZXhfbWF0aHNfZGVsaW1zJ10gfHwge30pWydkaXNwbGF5J10gfHwge30pWydyaWdodCddIHx8IFwiXFxcXF1cIjtcbiAgICAgICAgICAgICAgICBjb25zdCB0ZXggPSBuLmdldEF0dHJpYnV0ZShcImRhdGEtbXgtbWF0aHNcIik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcnRDcmVhdG9yLnBsYWluKGRlbGltTGVmdCArIHRleCArIGRlbGltUmlnaHQpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICghY2hlY2tEZXNjZW5kSW50byhuKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXJ0Q3JlYXRvci5wbGFpbihuLnRleHRDb250ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgXCJPTFwiOlxuICAgICAgICAgICAgc3RhdGUubGlzdEluZGV4LnB1c2goKDxIVE1MT0xpc3RFbGVtZW50Pm4pLnN0YXJ0IHx8IDEpO1xuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICBjYXNlIFwiVUxcIjpcbiAgICAgICAgICAgIHN0YXRlLmxpc3REZXB0aCA9IChzdGF0ZS5saXN0RGVwdGggfHwgMCkgKyAxO1xuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgLy8gZG9uJ3QgdGV4dGlmeSBibG9jayBub2RlcyB3ZSdsbCBkZXNjZW5kIGludG9cbiAgICAgICAgICAgIGlmICghY2hlY2tEZXNjZW5kSW50byhuKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXJ0Q3JlYXRvci5wbGFpbihuLnRleHRDb250ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrRGVzY2VuZEludG8obm9kZSkge1xuICAgIHN3aXRjaCAobm9kZS5ub2RlTmFtZSkge1xuICAgICAgICBjYXNlIFwiUFJFXCI6XG4gICAgICAgICAgICAvLyBhIGNvZGUgYmxvY2sgaXMgdGV4dGlmaWVkIGluIHBhcnNlQ29kZUJsb2NrXG4gICAgICAgICAgICAvLyBhcyB3ZSBkb24ndCB3YW50IHRvIHByZXNlcnZlIG1hcmt1cCBpbiBpdCxcbiAgICAgICAgICAgIC8vIHNvIG5vIG5lZWQgdG8gZGVzY2VuZCBpbnRvIGl0XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gY2hlY2tCbG9ja05vZGUobm9kZSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjaGVja0lnbm9yZWQobikge1xuICAgIGlmIChuLm5vZGVUeXBlID09PSBOb2RlLlRFWFRfTk9ERSkge1xuICAgICAgICAvLyBFbGVtZW50IGFkZHMgXFxuIHRleHQgbm9kZXMgaW4gYSBsb3Qgb2YgcGxhY2VzLFxuICAgICAgICAvLyB3aGljaCBzaG91bGQgYmUgaWdub3JlZFxuICAgICAgICByZXR1cm4gbi5ub2RlVmFsdWUgPT09IFwiXFxuXCI7XG4gICAgfSBlbHNlIGlmIChuLm5vZGVUeXBlID09PSBOb2RlLkVMRU1FTlRfTk9ERSkge1xuICAgICAgICByZXR1cm4gbi5ub2RlTmFtZSA9PT0gXCJNWC1SRVBMWVwiO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuY29uc3QgUVVPVEVfTElORV9QUkVGSVggPSBcIj4gXCI7XG5mdW5jdGlvbiBwcmVmaXhRdW90ZUxpbmVzKGlzRmlyc3ROb2RlLCBwYXJ0cywgcGFydENyZWF0b3IpIHtcbiAgICAvLyBhIG5ld2xpbmUgKHRvIGFwcGVuZCBhID4gdG8pIHdvdWxkbid0IGJlIGFkZGVkIHRvIHBhcnRzIGZvciB0aGUgZmlyc3QgbGluZVxuICAgIC8vIGlmIHRoZXJlIHdhcyBubyBjb250ZW50IGJlZm9yZSB0aGUgQkxPQ0tRVU9URSwgc28gaGFuZGxlIHRoYXRcbiAgICBpZiAoaXNGaXJzdE5vZGUpIHtcbiAgICAgICAgcGFydHMuc3BsaWNlKDAsIDAsIHBhcnRDcmVhdG9yLnBsYWluKFFVT1RFX0xJTkVfUFJFRklYKSk7XG4gICAgfVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgaWYgKHBhcnRzW2ldLnR5cGUgPT09IFwibmV3bGluZVwiKSB7XG4gICAgICAgICAgICBwYXJ0cy5zcGxpY2UoaSArIDEsIDAsIHBhcnRDcmVhdG9yLnBsYWluKFFVT1RFX0xJTkVfUFJFRklYKSk7XG4gICAgICAgICAgICBpICs9IDE7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIHBhcnNlSHRtbE1lc3NhZ2UoaHRtbDogc3RyaW5nLCBwYXJ0Q3JlYXRvcjogUGFydENyZWF0b3IsIGlzUXVvdGVkTWVzc2FnZTogYm9vbGVhbikge1xuICAgIC8vIG5vIG5vZGVzIGZyb20gcGFyc2luZyBoZXJlIHNob3VsZCBiZSBpbnNlcnRlZCBpbiB0aGUgZG9jdW1lbnQsXG4gICAgLy8gYXMgc2NyaXB0cyBpbiBldmVudCBoYW5kbGVycywgZXRjIHdvdWxkIGJlIGV4ZWN1dGVkIHRoZW4uXG4gICAgLy8gd2UncmUgb25seSB0YWtpbmcgdGV4dCwgc28gdGhhdCBpcyBmaW5lXG4gICAgY29uc3Qgcm9vdE5vZGUgPSBuZXcgRE9NUGFyc2VyKCkucGFyc2VGcm9tU3RyaW5nKGh0bWwsIFwidGV4dC9odG1sXCIpLmJvZHk7XG4gICAgY29uc3QgcGFydHMgPSBbXTtcbiAgICBsZXQgbGFzdE5vZGU7XG4gICAgbGV0IGluUXVvdGUgPSBpc1F1b3RlZE1lc3NhZ2U7XG4gICAgY29uc3Qgc3RhdGU6IElTdGF0ZSA9IHtcbiAgICAgICAgbGlzdEluZGV4OiBbXSxcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gb25Ob2RlRW50ZXIobikge1xuICAgICAgICBpZiAoY2hlY2tJZ25vcmVkKG4pKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG4ubm9kZU5hbWUgPT09IFwiQkxPQ0tRVU9URVwiKSB7XG4gICAgICAgICAgICBpblF1b3RlID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG5ld1BhcnRzID0gW107XG4gICAgICAgIGlmIChsYXN0Tm9kZSAmJiAoY2hlY2tCbG9ja05vZGUobGFzdE5vZGUpIHx8IGNoZWNrQmxvY2tOb2RlKG4pKSkge1xuICAgICAgICAgICAgbmV3UGFydHMucHVzaChwYXJ0Q3JlYXRvci5uZXdsaW5lKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG4ubm9kZVR5cGUgPT09IE5vZGUuVEVYVF9OT0RFKSB7XG4gICAgICAgICAgICBuZXdQYXJ0cy5wdXNoKC4uLnBhcnNlQXRSb29tTWVudGlvbnMobi5ub2RlVmFsdWUsIHBhcnRDcmVhdG9yKSk7XG4gICAgICAgIH0gZWxzZSBpZiAobi5ub2RlVHlwZSA9PT0gTm9kZS5FTEVNRU5UX05PREUpIHtcbiAgICAgICAgICAgIGNvbnN0IHBhcnNlUmVzdWx0ID0gcGFyc2VFbGVtZW50KG4sIHBhcnRDcmVhdG9yLCBsYXN0Tm9kZSwgc3RhdGUpO1xuICAgICAgICAgICAgaWYgKHBhcnNlUmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocGFyc2VSZXN1bHQpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld1BhcnRzLnB1c2goLi4ucGFyc2VSZXN1bHQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld1BhcnRzLnB1c2gocGFyc2VSZXN1bHQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChuZXdQYXJ0cy5sZW5ndGggJiYgaW5RdW90ZSkge1xuICAgICAgICAgICAgY29uc3QgaXNGaXJzdFBhcnQgPSBwYXJ0cy5sZW5ndGggPT09IDA7XG4gICAgICAgICAgICBwcmVmaXhRdW90ZUxpbmVzKGlzRmlyc3RQYXJ0LCBuZXdQYXJ0cywgcGFydENyZWF0b3IpO1xuICAgICAgICB9XG5cbiAgICAgICAgcGFydHMucHVzaCguLi5uZXdQYXJ0cyk7XG5cbiAgICAgICAgY29uc3QgZGVzY2VuZCA9IGNoZWNrRGVzY2VuZEludG8obik7XG4gICAgICAgIC8vIHdoZW4gbm90IGRlc2NlbmRpbmcgKGxpa2UgZm9yIFBSRSksIG9uTm9kZUxlYXZlIHdvbid0IGJlIGNhbGxlZCB0byBzZXQgbGFzdE5vZGVcbiAgICAgICAgLy8gc28gZG8gdGhhdCBoZXJlLlxuICAgICAgICBsYXN0Tm9kZSA9IGRlc2NlbmQgPyBudWxsIDogbjtcbiAgICAgICAgcmV0dXJuIGRlc2NlbmQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25Ob2RlTGVhdmUobikge1xuICAgICAgICBpZiAoY2hlY2tJZ25vcmVkKG4pKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3dpdGNoIChuLm5vZGVOYW1lKSB7XG4gICAgICAgICAgICBjYXNlIFwiQkxPQ0tRVU9URVwiOlxuICAgICAgICAgICAgICAgIGluUXVvdGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJPTFwiOlxuICAgICAgICAgICAgICAgIHN0YXRlLmxpc3RJbmRleC5wb3AoKTtcbiAgICAgICAgICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICAgICAgICBjYXNlIFwiVUxcIjpcbiAgICAgICAgICAgICAgICBzdGF0ZS5saXN0RGVwdGggLT0gMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBsYXN0Tm9kZSA9IG47XG4gICAgfVxuXG4gICAgd2Fsa0RPTURlcHRoRmlyc3Qocm9vdE5vZGUsIG9uTm9kZUVudGVyLCBvbk5vZGVMZWF2ZSk7XG5cbiAgICByZXR1cm4gcGFydHM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVBsYWluVGV4dE1lc3NhZ2UoYm9keTogc3RyaW5nLCBwYXJ0Q3JlYXRvcjogUGFydENyZWF0b3IsIGlzUXVvdGVkTWVzc2FnZT86IGJvb2xlYW4pIHtcbiAgICBjb25zdCBsaW5lcyA9IGJvZHkuc3BsaXQoL1xcclxcbnxcXHJ8XFxuL2cpOyAvLyBzcGxpdCBvbiBhbnkgbmV3LWxpbmUgY29tYmluYXRpb24gbm90IGp1c3QgXFxuLCBjb2xsYXBzZXMgXFxyXFxuXG4gICAgcmV0dXJuIGxpbmVzLnJlZHVjZSgocGFydHMsIGxpbmUsIGkpID0+IHtcbiAgICAgICAgaWYgKGlzUXVvdGVkTWVzc2FnZSkge1xuICAgICAgICAgICAgcGFydHMucHVzaChwYXJ0Q3JlYXRvci5wbGFpbihRVU9URV9MSU5FX1BSRUZJWCkpO1xuICAgICAgICB9XG4gICAgICAgIHBhcnRzLnB1c2goLi4ucGFyc2VBdFJvb21NZW50aW9ucyhsaW5lLCBwYXJ0Q3JlYXRvcikpO1xuICAgICAgICBjb25zdCBpc0xhc3QgPSBpID09PSBsaW5lcy5sZW5ndGggLSAxO1xuICAgICAgICBpZiAoIWlzTGFzdCkge1xuICAgICAgICAgICAgcGFydHMucHVzaChwYXJ0Q3JlYXRvci5uZXdsaW5lKCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwYXJ0cztcbiAgICB9LCBbXSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUV2ZW50KGV2ZW50OiBNYXRyaXhFdmVudCwgcGFydENyZWF0b3I6IFBhcnRDcmVhdG9yLCB7aXNRdW90ZWRNZXNzYWdlID0gZmFsc2V9ID0ge30pIHtcbiAgICBjb25zdCBjb250ZW50ID0gZXZlbnQuZ2V0Q29udGVudCgpO1xuICAgIGxldCBwYXJ0cztcbiAgICBpZiAoY29udGVudC5mb3JtYXQgPT09IFwib3JnLm1hdHJpeC5jdXN0b20uaHRtbFwiKSB7XG4gICAgICAgIHBhcnRzID0gcGFyc2VIdG1sTWVzc2FnZShjb250ZW50LmZvcm1hdHRlZF9ib2R5IHx8IFwiXCIsIHBhcnRDcmVhdG9yLCBpc1F1b3RlZE1lc3NhZ2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHBhcnRzID0gcGFyc2VQbGFpblRleHRNZXNzYWdlKGNvbnRlbnQuYm9keSB8fCBcIlwiLCBwYXJ0Q3JlYXRvciwgaXNRdW90ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgaWYgKGNvbnRlbnQubXNndHlwZSA9PT0gXCJtLmVtb3RlXCIpIHtcbiAgICAgICAgcGFydHMudW5zaGlmdChwYXJ0Q3JlYXRvci5wbGFpbihcIi9tZSBcIikpO1xuICAgIH1cbiAgICByZXR1cm4gcGFydHM7XG59XG4iXX0=