matrix-react-sdk
Version:
SDK for matrix.org using React
231 lines (223 loc) • 31.6 kB
JavaScript
;
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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