UNPKG

matrix-react-sdk

Version:
231 lines (223 loc) 31.6 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.containsEmote = containsEmote; exports.htmlSerializeFromMdIfNeeded = htmlSerializeFromMdIfNeeded; exports.htmlSerializeIfNeeded = htmlSerializeIfNeeded; exports.mdSerialize = mdSerialize; exports.startsWith = startsWith; exports.stripEmoteCommand = stripEmoteCommand; exports.stripPrefix = stripPrefix; exports.textSerialize = textSerialize; exports.unescapeMessage = unescapeMessage; var _htmlEntities = require("html-entities"); var _escapeHtml = _interopRequireDefault(require("escape-html")); var _Markdown = _interopRequireDefault(require("../Markdown")); var _Permalinks = require("../utils/permalinks/Permalinks"); var _SettingsStore = _interopRequireDefault(require("../settings/SettingsStore")); var _SdkConfig = _interopRequireDefault(require("../SdkConfig")); var _parts = require("./parts"); /* Copyright 2024 New Vector Ltd. Copyright 2019, 2020 The Matrix.org Foundation C.I.C. Copyright 2019 New Vector Ltd SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ function mdSerialize(model) { return model.parts.reduce((html, part) => { switch (part.type) { case _parts.Type.Newline: return html + "\n"; case _parts.Type.Plain: case _parts.Type.Emoji: case _parts.Type.Command: case _parts.Type.PillCandidate: case _parts.Type.AtRoomPill: return html + part.text; case _parts.Type.RoomPill: { const url = (0, _Permalinks.makeGenericPermalink)(part.resourceId, true); // Escape square brackets and backslashes // Here we use the resourceId for compatibility with non-rich text clients // See https://github.com/vector-im/element-web/issues/16660 const title = part.resourceId.replace(/[[\\\]]/g, c => "\\" + c); return html + `[${title}](${url})`; } case _parts.Type.UserPill: { const url = (0, _Permalinks.makeGenericPermalink)(part.resourceId, true); // Escape square brackets and backslashes; convert newlines to HTML const title = part.text.replace(/[[\\\]]/g, c => "\\" + c).replace(/\n/g, "<br>"); return html + `[${title}](${url})`; } } }, ""); } function htmlSerializeIfNeeded(model, { forceHTML = false, useMarkdown = true } = {}) { if (!useMarkdown) { return (0, _escapeHtml.default)(textSerialize(model)).replace(/\n/g, "<br/>"); } const md = mdSerialize(model); return htmlSerializeFromMdIfNeeded(md, { forceHTML }); } function htmlSerializeFromMdIfNeeded(md, { forceHTML = false } = {}) { // copy of raw input to remove unwanted math later const orig = md; if (_SettingsStore.default.getValue("feature_latex_maths")) { const patternNames = ["tex", "latex"]; const patternTypes = ["display", "inline"]; const patternDefaults = { tex: { // detect math with tex delimiters, inline: $...$, display $$...$$ // preferably use negative lookbehinds, not supported in all major browsers: // const displayPattern = "^(?<!\\\\)\\$\\$(?![ \\t])(([^$]|\\\\\\$)+?)\\$\\$$"; // const inlinePattern = "(?:^|\\s)(?<!\\\\)\\$(?!\\s)(([^$]|\\\\\\$)+?)(?<!\\\\|\\s)\\$"; // conditions for display math detection $$...$$: // - pattern starts and ends on a new line // - left delimiter ($$) is not escaped by backslash display: "(^)\\$\\$(([^$]|\\\\\\$)+?)\\$\\$$", // conditions for inline math detection $...$: // - pattern starts at beginning of line, follows whitespace character or punctuation // - pattern is on a single line // - left and right delimiters ($) are not escaped by backslashes // - left delimiter is not followed by whitespace character // - right delimiter is not prefixed with whitespace character inline: "(^|\\s|[.,!?:;])(?!\\\\)\\$(?!\\s)(([^$\\n]|\\\\\\$)*([^\\\\\\s\\$]|\\\\\\$)(?:\\\\\\$)?)\\$" }, latex: { // detect math with latex delimiters, inline: \(...\), display \[...\] // conditions for display math detection \[...\]: // - pattern starts and ends on a new line // - pattern is not empty display: "(^)\\\\\\[(?!\\\\\\])(.*?)\\\\\\]$", // conditions for inline math detection \(...\): // - pattern starts at beginning of line or is not prefixed with backslash // - pattern is not empty inline: "(^|[^\\\\])\\\\\\((?!\\\\\\))(.*?)\\\\\\)" } }; patternNames.forEach(function (patternName) { patternTypes.forEach(function (patternType) { // get the regex replace pattern from config or use the default const pattern = _SdkConfig.default.get("latex_maths_delims")?.[patternType]?.["pattern"]?.[patternName] || patternDefaults[patternName][patternType]; md = md.replace(RegExp(pattern, "gms"), function (m, p1, p2) { const p2e = (0, _htmlEntities.encode)(p2); switch (patternType) { case "display": return `${p1}<div data-mx-maths="${p2e}">\n\n</div>\n\n`; case "inline": return `${p1}<span data-mx-maths="${p2e}"></span>`; } }); }); }); // make sure div tags always start on a new line, otherwise it will confuse the markdown parser md = md.replace(/(.)<div/g, function (m, p1) { return `${p1}\n<div`; }); } const parser = new _Markdown.default(md); if (!parser.isPlainText() || forceHTML) { // feed Markdown output to HTML parser const phtml = new DOMParser().parseFromString(parser.toHTML(), "text/html"); if (_SettingsStore.default.getValue("feature_latex_maths")) { // original Markdown without LaTeX replacements const parserOrig = new _Markdown.default(orig); const phtmlOrig = new DOMParser().parseFromString(parserOrig.toHTML(), "text/html"); // since maths delimiters are handled before Markdown, // code blocks could contain mangled content. // replace code blocks with original content [...phtmlOrig.getElementsByTagName("code")].forEach((e, i) => { phtml.getElementsByTagName("code").item(i).textContent = e.textContent; }); // add fallback output for latex math, which should not be interpreted as markdown [...phtml.querySelectorAll("div, span")].forEach((e, i) => { const tex = e.getAttribute("data-mx-maths"); if (tex) { e.innerHTML = `<code>${tex}</code>`; } }); } return phtml.body.innerHTML; } // ensure removal of escape backslashes in non-Markdown messages if (md.indexOf("\\") > -1) { return parser.toPlaintext(); } } function textSerialize(model) { return model.parts.reduce((text, part) => { switch (part.type) { case _parts.Type.Newline: return text + "\n"; case _parts.Type.Plain: case _parts.Type.Emoji: case _parts.Type.Command: case _parts.Type.PillCandidate: case _parts.Type.AtRoomPill: return text + part.text; case _parts.Type.RoomPill: // Here we use the resourceId for compatibility with non-rich text clients // See https://github.com/vector-im/element-web/issues/16660 return text + `${part.resourceId}`; case _parts.Type.UserPill: return text + `${part.text}`; } }, ""); } function containsEmote(model) { const hasCommand = startsWith(model, "/me ", false); const hasArgument = model.parts[0]?.text?.length > 4 || model.parts.length > 1; return hasCommand && hasArgument; } function startsWith(model, prefix, caseSensitive = true) { const firstPart = model.parts[0]; // part type will be "plain" while editing, // and "command" while composing a message. let text = firstPart?.text || ""; if (!caseSensitive) { prefix = prefix.toLowerCase(); text = text.toLowerCase(); } return firstPart && (firstPart.type === _parts.Type.Plain || firstPart.type === _parts.Type.Command) && text.startsWith(prefix); } function stripEmoteCommand(model) { // trim "/me " return stripPrefix(model, "/me "); } function stripPrefix(model, prefix) { model = model.clone(); model.removeText({ index: 0, offset: 0 }, prefix.length); return model; } function unescapeMessage(model) { const { parts } = model; if (parts.length) { const firstPart = parts[0]; // only unescape \/ to / at start of editor if (firstPart.type === _parts.Type.Plain && firstPart.text.startsWith("\\/")) { model = model.clone(); model.removeText({ index: 0, offset: 0 }, 1); } } return model; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfaHRtbEVudGl0aWVzIiwicmVxdWlyZSIsIl9lc2NhcGVIdG1sIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9NYXJrZG93biIsIl9QZXJtYWxpbmtzIiwiX1NldHRpbmdzU3RvcmUiLCJfU2RrQ29uZmlnIiwiX3BhcnRzIiwibWRTZXJpYWxpemUiLCJtb2RlbCIsInBhcnRzIiwicmVkdWNlIiwiaHRtbCIsInBhcnQiLCJ0eXBlIiwiVHlwZSIsIk5ld2xpbmUiLCJQbGFpbiIsIkVtb2ppIiwiQ29tbWFuZCIsIlBpbGxDYW5kaWRhdGUiLCJBdFJvb21QaWxsIiwidGV4dCIsIlJvb21QaWxsIiwidXJsIiwibWFrZUdlbmVyaWNQZXJtYWxpbmsiLCJyZXNvdXJjZUlkIiwidGl0bGUiLCJyZXBsYWNlIiwiYyIsIlVzZXJQaWxsIiwiaHRtbFNlcmlhbGl6ZUlmTmVlZGVkIiwiZm9yY2VIVE1MIiwidXNlTWFya2Rvd24iLCJlc2NhcGVIdG1sIiwidGV4dFNlcmlhbGl6ZSIsIm1kIiwiaHRtbFNlcmlhbGl6ZUZyb21NZElmTmVlZGVkIiwib3JpZyIsIlNldHRpbmdzU3RvcmUiLCJnZXRWYWx1ZSIsInBhdHRlcm5OYW1lcyIsInBhdHRlcm5UeXBlcyIsInBhdHRlcm5EZWZhdWx0cyIsInRleCIsImRpc3BsYXkiLCJpbmxpbmUiLCJsYXRleCIsImZvckVhY2giLCJwYXR0ZXJuTmFtZSIsInBhdHRlcm5UeXBlIiwicGF0dGVybiIsIlNka0NvbmZpZyIsImdldCIsIlJlZ0V4cCIsIm0iLCJwMSIsInAyIiwicDJlIiwiZW5jb2RlIiwicGFyc2VyIiwiTWFya2Rvd24iLCJpc1BsYWluVGV4dCIsInBodG1sIiwiRE9NUGFyc2VyIiwicGFyc2VGcm9tU3RyaW5nIiwidG9IVE1MIiwicGFyc2VyT3JpZyIsInBodG1sT3JpZyIsImdldEVsZW1lbnRzQnlUYWdOYW1lIiwiZSIsImkiLCJpdGVtIiwidGV4dENvbnRlbnQiLCJxdWVyeVNlbGVjdG9yQWxsIiwiZ2V0QXR0cmlidXRlIiwiaW5uZXJIVE1MIiwiYm9keSIsImluZGV4T2YiLCJ0b1BsYWludGV4dCIsImNvbnRhaW5zRW1vdGUiLCJoYXNDb21tYW5kIiwic3RhcnRzV2l0aCIsImhhc0FyZ3VtZW50IiwibGVuZ3RoIiwicHJlZml4IiwiY2FzZVNlbnNpdGl2ZSIsImZpcnN0UGFydCIsInRvTG93ZXJDYXNlIiwic3RyaXBFbW90ZUNvbW1hbmQiLCJzdHJpcFByZWZpeCIsImNsb25lIiwicmVtb3ZlVGV4dCIsImluZGV4Iiwib2Zmc2V0IiwidW5lc2NhcGVNZXNzYWdlIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2VkaXRvci9zZXJpYWxpemUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMTksIDIwMjAgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cbkNvcHlyaWdodCAyMDE5IE5ldyBWZWN0b3IgTHRkXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCB7IGVuY29kZSB9IGZyb20gXCJodG1sLWVudGl0aWVzXCI7XG5pbXBvcnQgZXNjYXBlSHRtbCBmcm9tIFwiZXNjYXBlLWh0bWxcIjtcblxuaW1wb3J0IE1hcmtkb3duIGZyb20gXCIuLi9NYXJrZG93blwiO1xuaW1wb3J0IHsgbWFrZUdlbmVyaWNQZXJtYWxpbmsgfSBmcm9tIFwiLi4vdXRpbHMvcGVybWFsaW5rcy9QZXJtYWxpbmtzXCI7XG5pbXBvcnQgRWRpdG9yTW9kZWwgZnJvbSBcIi4vbW9kZWxcIjtcbmltcG9ydCBTZXR0aW5nc1N0b3JlIGZyb20gXCIuLi9zZXR0aW5ncy9TZXR0aW5nc1N0b3JlXCI7XG5pbXBvcnQgU2RrQ29uZmlnIGZyb20gXCIuLi9TZGtDb25maWdcIjtcbmltcG9ydCB7IFR5cGUgfSBmcm9tIFwiLi9wYXJ0c1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gbWRTZXJpYWxpemUobW9kZWw6IEVkaXRvck1vZGVsKTogc3RyaW5nIHtcbiAgICByZXR1cm4gbW9kZWwucGFydHMucmVkdWNlKChodG1sLCBwYXJ0KSA9PiB7XG4gICAgICAgIHN3aXRjaCAocGFydC50eXBlKSB7XG4gICAgICAgICAgICBjYXNlIFR5cGUuTmV3bGluZTpcbiAgICAgICAgICAgICAgICByZXR1cm4gaHRtbCArIFwiXFxuXCI7XG4gICAgICAgICAgICBjYXNlIFR5cGUuUGxhaW46XG4gICAgICAgICAgICBjYXNlIFR5cGUuRW1vamk6XG4gICAgICAgICAgICBjYXNlIFR5cGUuQ29tbWFuZDpcbiAgICAgICAgICAgIGNhc2UgVHlwZS5QaWxsQ2FuZGlkYXRlOlxuICAgICAgICAgICAgY2FzZSBUeXBlLkF0Um9vbVBpbGw6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGh0bWwgKyBwYXJ0LnRleHQ7XG4gICAgICAgICAgICBjYXNlIFR5cGUuUm9vbVBpbGw6IHtcbiAgICAgICAgICAgICAgICBjb25zdCB1cmwgPSBtYWtlR2VuZXJpY1Blcm1hbGluayhwYXJ0LnJlc291cmNlSWQsIHRydWUpO1xuICAgICAgICAgICAgICAgIC8vIEVzY2FwZSBzcXVhcmUgYnJhY2tldHMgYW5kIGJhY2tzbGFzaGVzXG4gICAgICAgICAgICAgICAgLy8gSGVyZSB3ZSB1c2UgdGhlIHJlc291cmNlSWQgZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBub24tcmljaCB0ZXh0IGNsaWVudHNcbiAgICAgICAgICAgICAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL3ZlY3Rvci1pbS9lbGVtZW50LXdlYi9pc3N1ZXMvMTY2NjBcbiAgICAgICAgICAgICAgICBjb25zdCB0aXRsZSA9IHBhcnQucmVzb3VyY2VJZC5yZXBsYWNlKC9bW1xcXFxcXF1dL2csIChjKSA9PiBcIlxcXFxcIiArIGMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBodG1sICsgYFske3RpdGxlfV0oJHt1cmx9KWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXNlIFR5cGUuVXNlclBpbGw6IHtcbiAgICAgICAgICAgICAgICBjb25zdCB1cmwgPSBtYWtlR2VuZXJpY1Blcm1hbGluayhwYXJ0LnJlc291cmNlSWQsIHRydWUpO1xuICAgICAgICAgICAgICAgIC8vIEVzY2FwZSBzcXVhcmUgYnJhY2tldHMgYW5kIGJhY2tzbGFzaGVzOyBjb252ZXJ0IG5ld2xpbmVzIHRvIEhUTUxcbiAgICAgICAgICAgICAgICBjb25zdCB0aXRsZSA9IHBhcnQudGV4dC5yZXBsYWNlKC9bW1xcXFxcXF1dL2csIChjKSA9PiBcIlxcXFxcIiArIGMpLnJlcGxhY2UoL1xcbi9nLCBcIjxicj5cIik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGh0bWwgKyBgWyR7dGl0bGV9XSgke3VybH0pYDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sIFwiXCIpO1xufVxuXG5pbnRlcmZhY2UgSVNlcmlhbGl6ZU9wdHMge1xuICAgIGZvcmNlSFRNTD86IGJvb2xlYW47XG4gICAgdXNlTWFya2Rvd24/OiBib29sZWFuO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaHRtbFNlcmlhbGl6ZUlmTmVlZGVkKFxuICAgIG1vZGVsOiBFZGl0b3JNb2RlbCxcbiAgICB7IGZvcmNlSFRNTCA9IGZhbHNlLCB1c2VNYXJrZG93biA9IHRydWUgfTogSVNlcmlhbGl6ZU9wdHMgPSB7fSxcbik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCF1c2VNYXJrZG93bikge1xuICAgICAgICByZXR1cm4gZXNjYXBlSHRtbCh0ZXh0U2VyaWFsaXplKG1vZGVsKSkucmVwbGFjZSgvXFxuL2csIFwiPGJyLz5cIik7XG4gICAgfVxuXG4gICAgY29uc3QgbWQgPSBtZFNlcmlhbGl6ZShtb2RlbCk7XG4gICAgcmV0dXJuIGh0bWxTZXJpYWxpemVGcm9tTWRJZk5lZWRlZChtZCwgeyBmb3JjZUhUTUwgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBodG1sU2VyaWFsaXplRnJvbU1kSWZOZWVkZWQobWQ6IHN0cmluZywgeyBmb3JjZUhUTUwgPSBmYWxzZSB9ID0ge30pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIC8vIGNvcHkgb2YgcmF3IGlucHV0IHRvIHJlbW92ZSB1bndhbnRlZCBtYXRoIGxhdGVyXG4gICAgY29uc3Qgb3JpZyA9IG1kO1xuXG4gICAgaWYgKFNldHRpbmdzU3RvcmUuZ2V0VmFsdWUoXCJmZWF0dXJlX2xhdGV4X21hdGhzXCIpKSB7XG4gICAgICAgIGNvbnN0IHBhdHRlcm5OYW1lcyA9IFtcInRleFwiLCBcImxhdGV4XCJdIGFzIGNvbnN0O1xuICAgICAgICBjb25zdCBwYXR0ZXJuVHlwZXMgPSBbXCJkaXNwbGF5XCIsIFwiaW5saW5lXCJdIGFzIGNvbnN0O1xuICAgICAgICBjb25zdCBwYXR0ZXJuRGVmYXVsdHMgPSB7XG4gICAgICAgICAgICB0ZXg6IHtcbiAgICAgICAgICAgICAgICAvLyBkZXRlY3QgbWF0aCB3aXRoIHRleCBkZWxpbWl0ZXJzLCBpbmxpbmU6ICQuLi4kLCBkaXNwbGF5ICQkLi4uJCRcbiAgICAgICAgICAgICAgICAvLyBwcmVmZXJhYmx5IHVzZSBuZWdhdGl2ZSBsb29rYmVoaW5kcywgbm90IHN1cHBvcnRlZCBpbiBhbGwgbWFqb3IgYnJvd3NlcnM6XG4gICAgICAgICAgICAgICAgLy8gY29uc3QgZGlzcGxheVBhdHRlcm4gPSBcIl4oPzwhXFxcXFxcXFwpXFxcXCRcXFxcJCg/IVsgXFxcXHRdKSgoW14kXXxcXFxcXFxcXFxcXFwkKSs/KVxcXFwkXFxcXCQkXCI7XG4gICAgICAgICAgICAgICAgLy8gY29uc3QgaW5saW5lUGF0dGVybiA9IFwiKD86XnxcXFxccykoPzwhXFxcXFxcXFwpXFxcXCQoPyFcXFxccykoKFteJF18XFxcXFxcXFxcXFxcJCkrPykoPzwhXFxcXFxcXFx8XFxcXHMpXFxcXCRcIjtcblxuICAgICAgICAgICAgICAgIC8vIGNvbmRpdGlvbnMgZm9yIGRpc3BsYXkgbWF0aCBkZXRlY3Rpb24gJCQuLi4kJDpcbiAgICAgICAgICAgICAgICAvLyAtIHBhdHRlcm4gc3RhcnRzIGFuZCBlbmRzIG9uIGEgbmV3IGxpbmVcbiAgICAgICAgICAgICAgICAvLyAtIGxlZnQgZGVsaW1pdGVyICgkJCkgaXMgbm90IGVzY2FwZWQgYnkgYmFja3NsYXNoXG4gICAgICAgICAgICAgICAgZGlzcGxheTogXCIoXilcXFxcJFxcXFwkKChbXiRdfFxcXFxcXFxcXFxcXCQpKz8pXFxcXCRcXFxcJCRcIixcblxuICAgICAgICAgICAgICAgIC8vIGNvbmRpdGlvbnMgZm9yIGlubGluZSBtYXRoIGRldGVjdGlvbiAkLi4uJDpcbiAgICAgICAgICAgICAgICAvLyAtIHBhdHRlcm4gc3RhcnRzIGF0IGJlZ2lubmluZyBvZiBsaW5lLCBmb2xsb3dzIHdoaXRlc3BhY2UgY2hhcmFjdGVyIG9yIHB1bmN0dWF0aW9uXG4gICAgICAgICAgICAgICAgLy8gLSBwYXR0ZXJuIGlzIG9uIGEgc2luZ2xlIGxpbmVcbiAgICAgICAgICAgICAgICAvLyAtIGxlZnQgYW5kIHJpZ2h0IGRlbGltaXRlcnMgKCQpIGFyZSBub3QgZXNjYXBlZCBieSBiYWNrc2xhc2hlc1xuICAgICAgICAgICAgICAgIC8vIC0gbGVmdCBkZWxpbWl0ZXIgaXMgbm90IGZvbGxvd2VkIGJ5IHdoaXRlc3BhY2UgY2hhcmFjdGVyXG4gICAgICAgICAgICAgICAgLy8gLSByaWdodCBkZWxpbWl0ZXIgaXMgbm90IHByZWZpeGVkIHdpdGggd2hpdGVzcGFjZSBjaGFyYWN0ZXJcbiAgICAgICAgICAgICAgICBpbmxpbmU6IFwiKF58XFxcXHN8Wy4sIT86O10pKD8hXFxcXFxcXFwpXFxcXCQoPyFcXFxccykoKFteJFxcXFxuXXxcXFxcXFxcXFxcXFwkKSooW15cXFxcXFxcXFxcXFxzXFxcXCRdfFxcXFxcXFxcXFxcXCQpKD86XFxcXFxcXFxcXFxcJCk/KVxcXFwkXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGF0ZXg6IHtcbiAgICAgICAgICAgICAgICAvLyBkZXRlY3QgbWF0aCB3aXRoIGxhdGV4IGRlbGltaXRlcnMsIGlubGluZTogXFwoLi4uXFwpLCBkaXNwbGF5IFxcWy4uLlxcXVxuXG4gICAgICAgICAgICAgICAgLy8gY29uZGl0aW9ucyBmb3IgZGlzcGxheSBtYXRoIGRldGVjdGlvbiBcXFsuLi5cXF06XG4gICAgICAgICAgICAgICAgLy8gLSBwYXR0ZXJuIHN0YXJ0cyBhbmQgZW5kcyBvbiBhIG5ldyBsaW5lXG4gICAgICAgICAgICAgICAgLy8gLSBwYXR0ZXJuIGlzIG5vdCBlbXB0eVxuICAgICAgICAgICAgICAgIGRpc3BsYXk6IFwiKF4pXFxcXFxcXFxcXFxcWyg/IVxcXFxcXFxcXFxcXF0pKC4qPylcXFxcXFxcXFxcXFxdJFwiLFxuXG4gICAgICAgICAgICAgICAgLy8gY29uZGl0aW9ucyBmb3IgaW5saW5lIG1hdGggZGV0ZWN0aW9uIFxcKC4uLlxcKTpcbiAgICAgICAgICAgICAgICAvLyAtIHBhdHRlcm4gc3RhcnRzIGF0IGJlZ2lubmluZyBvZiBsaW5lIG9yIGlzIG5vdCBwcmVmaXhlZCB3aXRoIGJhY2tzbGFzaFxuICAgICAgICAgICAgICAgIC8vIC0gcGF0dGVybiBpcyBub3QgZW1wdHlcbiAgICAgICAgICAgICAgICBpbmxpbmU6IFwiKF58W15cXFxcXFxcXF0pXFxcXFxcXFxcXFxcKCg/IVxcXFxcXFxcXFxcXCkpKC4qPylcXFxcXFxcXFxcXFwpXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9O1xuXG4gICAgICAgIHBhdHRlcm5OYW1lcy5mb3JFYWNoKGZ1bmN0aW9uIChwYXR0ZXJuTmFtZSkge1xuICAgICAgICAgICAgcGF0dGVyblR5cGVzLmZvckVhY2goZnVuY3Rpb24gKHBhdHRlcm5UeXBlKSB7XG4gICAgICAgICAgICAgICAgLy8gZ2V0IHRoZSByZWdleCByZXBsYWNlIHBhdHRlcm4gZnJvbSBjb25maWcgb3IgdXNlIHRoZSBkZWZhdWx0XG4gICAgICAgICAgICAgICAgY29uc3QgcGF0dGVybiA9XG4gICAgICAgICAgICAgICAgICAgIFNka0NvbmZpZy5nZXQoXCJsYXRleF9tYXRoc19kZWxpbXNcIik/LltwYXR0ZXJuVHlwZV0/LltcInBhdHRlcm5cIl0/LltwYXR0ZXJuTmFtZV0gfHxcbiAgICAgICAgICAgICAgICAgICAgcGF0dGVybkRlZmF1bHRzW3BhdHRlcm5OYW1lXVtwYXR0ZXJuVHlwZV07XG5cbiAgICAgICAgICAgICAgICBtZCA9IG1kLnJlcGxhY2UoUmVnRXhwKHBhdHRlcm4sIFwiZ21zXCIpLCBmdW5jdGlvbiAobSwgcDEsIHAyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHAyZSA9IGVuY29kZShwMik7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAocGF0dGVyblR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJkaXNwbGF5XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGAke3AxfTxkaXYgZGF0YS1teC1tYXRocz1cIiR7cDJlfVwiPlxcblxcbjwvZGl2PlxcblxcbmA7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiaW5saW5lXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGAke3AxfTxzcGFuIGRhdGEtbXgtbWF0aHM9XCIke3AyZX1cIj48L3NwYW4+YDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIG1ha2Ugc3VyZSBkaXYgdGFncyBhbHdheXMgc3RhcnQgb24gYSBuZXcgbGluZSwgb3RoZXJ3aXNlIGl0IHdpbGwgY29uZnVzZSB0aGUgbWFya2Rvd24gcGFyc2VyXG4gICAgICAgIG1kID0gbWQucmVwbGFjZSgvKC4pPGRpdi9nLCBmdW5jdGlvbiAobSwgcDEpIHtcbiAgICAgICAgICAgIHJldHVybiBgJHtwMX1cXG48ZGl2YDtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgcGFyc2VyID0gbmV3IE1hcmtkb3duKG1kKTtcbiAgICBpZiAoIXBhcnNlci5pc1BsYWluVGV4dCgpIHx8IGZvcmNlSFRNTCkge1xuICAgICAgICAvLyBmZWVkIE1hcmtkb3duIG91dHB1dCB0byBIVE1MIHBhcnNlclxuICAgICAgICBjb25zdCBwaHRtbCA9IG5ldyBET01QYXJzZXIoKS5wYXJzZUZyb21TdHJpbmcocGFyc2VyLnRvSFRNTCgpLCBcInRleHQvaHRtbFwiKTtcblxuICAgICAgICBpZiAoU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZShcImZlYXR1cmVfbGF0ZXhfbWF0aHNcIikpIHtcbiAgICAgICAgICAgIC8vIG9yaWdpbmFsIE1hcmtkb3duIHdpdGhvdXQgTGFUZVggcmVwbGFjZW1lbnRzXG4gICAgICAgICAgICBjb25zdCBwYXJzZXJPcmlnID0gbmV3IE1hcmtkb3duKG9yaWcpO1xuICAgICAgICAgICAgY29uc3QgcGh0bWxPcmlnID0gbmV3IERPTVBhcnNlcigpLnBhcnNlRnJvbVN0cmluZyhwYXJzZXJPcmlnLnRvSFRNTCgpLCBcInRleHQvaHRtbFwiKTtcblxuICAgICAgICAgICAgLy8gc2luY2UgbWF0aHMgZGVsaW1pdGVycyBhcmUgaGFuZGxlZCBiZWZvcmUgTWFya2Rvd24sXG4gICAgICAgICAgICAvLyBjb2RlIGJsb2NrcyBjb3VsZCBjb250YWluIG1hbmdsZWQgY29udGVudC5cbiAgICAgICAgICAgIC8vIHJlcGxhY2UgY29kZSBibG9ja3Mgd2l0aCBvcmlnaW5hbCBjb250ZW50XG4gICAgICAgICAgICBbLi4ucGh0bWxPcmlnLmdldEVsZW1lbnRzQnlUYWdOYW1lKFwiY29kZVwiKV0uZm9yRWFjaCgoZSwgaSkgPT4ge1xuICAgICAgICAgICAgICAgIHBodG1sLmdldEVsZW1lbnRzQnlUYWdOYW1lKFwiY29kZVwiKS5pdGVtKGkpIS50ZXh0Q29udGVudCA9IGUudGV4dENvbnRlbnQ7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gYWRkIGZhbGxiYWNrIG91dHB1dCBmb3IgbGF0ZXggbWF0aCwgd2hpY2ggc2hvdWxkIG5vdCBiZSBpbnRlcnByZXRlZCBhcyBtYXJrZG93blxuICAgICAgICAgICAgWy4uLnBodG1sLnF1ZXJ5U2VsZWN0b3JBbGwoXCJkaXYsIHNwYW5cIildLmZvckVhY2goKGUsIGkpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCB0ZXggPSBlLmdldEF0dHJpYnV0ZShcImRhdGEtbXgtbWF0aHNcIik7XG4gICAgICAgICAgICAgICAgaWYgKHRleCkge1xuICAgICAgICAgICAgICAgICAgICBlLmlubmVySFRNTCA9IGA8Y29kZT4ke3RleH08L2NvZGU+YDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGh0bWwuYm9keS5pbm5lckhUTUw7XG4gICAgfVxuICAgIC8vIGVuc3VyZSByZW1vdmFsIG9mIGVzY2FwZSBiYWNrc2xhc2hlcyBpbiBub24tTWFya2Rvd24gbWVzc2FnZXNcbiAgICBpZiAobWQuaW5kZXhPZihcIlxcXFxcIikgPiAtMSkge1xuICAgICAgICByZXR1cm4gcGFyc2VyLnRvUGxhaW50ZXh0KCk7XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdGV4dFNlcmlhbGl6ZShtb2RlbDogRWRpdG9yTW9kZWwpOiBzdHJpbmcge1xuICAgIHJldHVybiBtb2RlbC5wYXJ0cy5yZWR1Y2UoKHRleHQsIHBhcnQpID0+IHtcbiAgICAgICAgc3dpdGNoIChwYXJ0LnR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgVHlwZS5OZXdsaW5lOlxuICAgICAgICAgICAgICAgIHJldHVybiB0ZXh0ICsgXCJcXG5cIjtcbiAgICAgICAgICAgIGNhc2UgVHlwZS5QbGFpbjpcbiAgICAgICAgICAgIGNhc2UgVHlwZS5FbW9qaTpcbiAgICAgICAgICAgIGNhc2UgVHlwZS5Db21tYW5kOlxuICAgICAgICAgICAgY2FzZSBUeXBlLlBpbGxDYW5kaWRhdGU6XG4gICAgICAgICAgICBjYXNlIFR5cGUuQXRSb29tUGlsbDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGV4dCArIHBhcnQudGV4dDtcbiAgICAgICAgICAgIGNhc2UgVHlwZS5Sb29tUGlsbDpcbiAgICAgICAgICAgICAgICAvLyBIZXJlIHdlIHVzZSB0aGUgcmVzb3VyY2VJZCBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG5vbi1yaWNoIHRleHQgY2xpZW50c1xuICAgICAgICAgICAgICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vdmVjdG9yLWltL2VsZW1lbnQtd2ViL2lzc3Vlcy8xNjY2MFxuICAgICAgICAgICAgICAgIHJldHVybiB0ZXh0ICsgYCR7cGFydC5yZXNvdXJjZUlkfWA7XG4gICAgICAgICAgICBjYXNlIFR5cGUuVXNlclBpbGw6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRleHQgKyBgJHtwYXJ0LnRleHR9YDtcbiAgICAgICAgfVxuICAgIH0sIFwiXCIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29udGFpbnNFbW90ZShtb2RlbDogRWRpdG9yTW9kZWwpOiBib29sZWFuIHtcbiAgICBjb25zdCBoYXNDb21tYW5kID0gc3RhcnRzV2l0aChtb2RlbCwgXCIvbWUgXCIsIGZhbHNlKTtcbiAgICBjb25zdCBoYXNBcmd1bWVudCA9IG1vZGVsLnBhcnRzWzBdPy50ZXh0Py5sZW5ndGggPiA0IHx8IG1vZGVsLnBhcnRzLmxlbmd0aCA+IDE7XG4gICAgcmV0dXJuIGhhc0NvbW1hbmQgJiYgaGFzQXJndW1lbnQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFydHNXaXRoKG1vZGVsOiBFZGl0b3JNb2RlbCwgcHJlZml4OiBzdHJpbmcsIGNhc2VTZW5zaXRpdmUgPSB0cnVlKTogYm9vbGVhbiB7XG4gICAgY29uc3QgZmlyc3RQYXJ0ID0gbW9kZWwucGFydHNbMF07XG4gICAgLy8gcGFydCB0eXBlIHdpbGwgYmUgXCJwbGFpblwiIHdoaWxlIGVkaXRpbmcsXG4gICAgLy8gYW5kIFwiY29tbWFuZFwiIHdoaWxlIGNvbXBvc2luZyBhIG1lc3NhZ2UuXG4gICAgbGV0IHRleHQgPSBmaXJzdFBhcnQ/LnRleHQgfHwgXCJcIjtcbiAgICBpZiAoIWNhc2VTZW5zaXRpdmUpIHtcbiAgICAgICAgcHJlZml4ID0gcHJlZml4LnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIHRleHQgPSB0ZXh0LnRvTG93ZXJDYXNlKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZpcnN0UGFydCAmJiAoZmlyc3RQYXJ0LnR5cGUgPT09IFR5cGUuUGxhaW4gfHwgZmlyc3RQYXJ0LnR5cGUgPT09IFR5cGUuQ29tbWFuZCkgJiYgdGV4dC5zdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdHJpcEVtb3RlQ29tbWFuZChtb2RlbDogRWRpdG9yTW9kZWwpOiBFZGl0b3JNb2RlbCB7XG4gICAgLy8gdHJpbSBcIi9tZSBcIlxuICAgIHJldHVybiBzdHJpcFByZWZpeChtb2RlbCwgXCIvbWUgXCIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc3RyaXBQcmVmaXgobW9kZWw6IEVkaXRvck1vZGVsLCBwcmVmaXg6IHN0cmluZyk6IEVkaXRvck1vZGVsIHtcbiAgICBtb2RlbCA9IG1vZGVsLmNsb25lKCk7XG4gICAgbW9kZWwucmVtb3ZlVGV4dCh7IGluZGV4OiAwLCBvZmZzZXQ6IDAgfSwgcHJlZml4Lmxlbmd0aCk7XG4gICAgcmV0dXJuIG1vZGVsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdW5lc2NhcGVNZXNzYWdlKG1vZGVsOiBFZGl0b3JNb2RlbCk6IEVkaXRvck1vZGVsIHtcbiAgICBjb25zdCB7IHBhcnRzIH0gPSBtb2RlbDtcbiAgICBpZiAocGFydHMubGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IGZpcnN0UGFydCA9IHBhcnRzWzBdO1xuICAgICAgICAvLyBvbmx5IHVuZXNjYXBlIFxcLyB0byAvIGF0IHN0YXJ0IG9mIGVkaXRvclxuICAgICAgICBpZiAoZmlyc3RQYXJ0LnR5cGUgPT09IFR5cGUuUGxhaW4gJiYgZmlyc3RQYXJ0LnRleHQuc3RhcnRzV2l0aChcIlxcXFwvXCIpKSB7XG4gICAgICAgICAgICBtb2RlbCA9IG1vZGVsLmNsb25lKCk7XG4gICAgICAgICAgICBtb2RlbC5yZW1vdmVUZXh0KHsgaW5kZXg6IDAsIG9mZnNldDogMCB9LCAxKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbW9kZWw7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7OztBQVNBLElBQUFBLGFBQUEsR0FBQUMsT0FBQTtBQUNBLElBQUFDLFdBQUEsR0FBQUMsc0JBQUEsQ0FBQUYsT0FBQTtBQUVBLElBQUFHLFNBQUEsR0FBQUQsc0JBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFJLFdBQUEsR0FBQUosT0FBQTtBQUVBLElBQUFLLGNBQUEsR0FBQUgsc0JBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFNLFVBQUEsR0FBQUosc0JBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFPLE1BQUEsR0FBQVAsT0FBQTtBQWpCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQVlPLFNBQVNRLFdBQVdBLENBQUNDLEtBQWtCLEVBQVU7RUFDcEQsT0FBT0EsS0FBSyxDQUFDQyxLQUFLLENBQUNDLE1BQU0sQ0FBQyxDQUFDQyxJQUFJLEVBQUVDLElBQUksS0FBSztJQUN0QyxRQUFRQSxJQUFJLENBQUNDLElBQUk7TUFDYixLQUFLQyxXQUFJLENBQUNDLE9BQU87UUFDYixPQUFPSixJQUFJLEdBQUcsSUFBSTtNQUN0QixLQUFLRyxXQUFJLENBQUNFLEtBQUs7TUFDZixLQUFLRixXQUFJLENBQUNHLEtBQUs7TUFDZixLQUFLSCxXQUFJLENBQUNJLE9BQU87TUFDakIsS0FBS0osV0FBSSxDQUFDSyxhQUFhO01BQ3ZCLEtBQUtMLFdBQUksQ0FBQ00sVUFBVTtRQUNoQixPQUFPVCxJQUFJLEdBQUdDLElBQUksQ0FBQ1MsSUFBSTtNQUMzQixLQUFLUCxXQUFJLENBQUNRLFFBQVE7UUFB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