matrix-react-sdk
Version:
SDK for matrix.org using React
171 lines (167 loc) • 21.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.CARET_NODE_CHAR = void 0;
exports.isCaretNode = isCaretNode;
exports.needsCaretNodeAfter = needsCaretNodeAfter;
exports.needsCaretNodeBefore = needsCaretNodeBefore;
exports.renderModel = renderModel;
var _parts = require("./parts");
/*
Copyright 2019-2024 New Vector Ltd.
Copyright 2019 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
function needsCaretNodeBefore(part, prevPart) {
const isFirst = !prevPart || prevPart.type === _parts.Type.Newline;
return !part.acceptsCaret && (isFirst || !prevPart.acceptsCaret);
}
function needsCaretNodeAfter(part, isLastOfLine) {
return !part.acceptsCaret && isLastOfLine;
}
function insertAfter(node, nodeToInsert) {
const next = node.nextSibling;
if (next) {
node.parentElement.insertBefore(nodeToInsert, next);
} else {
node.parentElement.appendChild(nodeToInsert);
}
}
// Use a BOM marker for caret nodes.
// On a first test, they seem to be filtered out when copying text out of the editor,
// but this could be platform dependent.
// As a precautionary measure, I chose the character that slate also uses.
const CARET_NODE_CHAR = exports.CARET_NODE_CHAR = "\ufeff";
// a caret node is a node that allows the caret to be placed
// where otherwise it wouldn't be possible
// (e.g. next to a pill span without adjacent text node)
function createCaretNode() {
const span = document.createElement("span");
span.className = "caretNode";
span.appendChild(document.createTextNode(CARET_NODE_CHAR));
return span;
}
function updateCaretNode(node) {
// ensure the caret node contains only a zero-width space
if (node.textContent !== CARET_NODE_CHAR) {
node.textContent = CARET_NODE_CHAR;
}
}
function isCaretNode(node) {
return !!node && node instanceof HTMLElement && node.tagName === "SPAN" && node.className === "caretNode";
}
function removeNextSiblings(node) {
if (!node) {
return;
}
node = node.nextSibling;
while (node) {
const removeNode = node;
node = node.nextSibling;
removeNode.remove();
}
}
function removeChildren(parent) {
const firstChild = parent.firstChild;
if (firstChild) {
removeNextSiblings(firstChild);
firstChild.remove();
}
}
function reconcileLine(lineContainer, parts) {
let currentNode = null;
let prevPart;
const lastPart = parts[parts.length - 1];
for (const part of parts) {
const isFirst = !prevPart;
currentNode = isFirst ? lineContainer.firstChild : currentNode.nextSibling;
if (needsCaretNodeBefore(part, prevPart)) {
if (isCaretNode(currentNode)) {
updateCaretNode(currentNode);
currentNode = currentNode.nextSibling;
} else {
lineContainer.insertBefore(createCaretNode(), currentNode);
}
}
// remove nodes until matching current part
while (currentNode && !part.canUpdateDOMNode(currentNode)) {
const nextNode = currentNode.nextSibling;
lineContainer.removeChild(currentNode);
currentNode = nextNode;
}
// update or insert node for current part
if (currentNode && part) {
part.updateDOMNode(currentNode);
} else if (part) {
currentNode = part.toDOMNode();
// hooks up nextSibling for next iteration
lineContainer.appendChild(currentNode);
}
if (needsCaretNodeAfter(part, part === lastPart)) {
if (isCaretNode(currentNode?.nextSibling)) {
currentNode = currentNode.nextSibling;
updateCaretNode(currentNode);
} else {
const caretNode = createCaretNode();
insertAfter(currentNode, caretNode);
currentNode = caretNode;
}
}
prevPart = part;
}
removeNextSiblings(currentNode);
}
function reconcileEmptyLine(lineContainer) {
// empty div needs to have a BR in it to give it height
let foundBR = false;
let partNode = lineContainer.firstChild;
while (partNode) {
const nextNode = partNode.nextSibling;
if (!foundBR && partNode.tagName === "BR") {
foundBR = true;
} else {
partNode.remove();
}
partNode = nextNode;
}
if (!foundBR) {
lineContainer.appendChild(document.createElement("br"));
}
}
function renderModel(editor, model) {
const lines = model.parts.reduce((linesArr, part) => {
if (part.type === _parts.Type.Newline) {
linesArr.push([]);
} else {
const lastLine = linesArr[linesArr.length - 1];
lastLine.push(part);
}
return linesArr;
}, [[]]);
lines.forEach((parts, i) => {
// find first (and remove anything else) div without className
// (as browsers insert these in contenteditable) line container
let lineContainer = editor.childNodes[i];
while (lineContainer && (lineContainer.tagName !== "DIV" || !!lineContainer.className)) {
editor.removeChild(lineContainer);
lineContainer = editor.childNodes[i];
}
if (!lineContainer) {
lineContainer = document.createElement("div");
editor.appendChild(lineContainer);
}
if (parts.length) {
reconcileLine(lineContainer, parts);
} else {
reconcileEmptyLine(lineContainer);
}
});
if (lines.length) {
removeNextSiblings(editor.children[lines.length - 1]);
} else {
removeChildren(editor);
}
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcGFydHMiLCJyZXF1aXJlIiwibmVlZHNDYXJldE5vZGVCZWZvcmUiLCJwYXJ0IiwicHJldlBhcnQiLCJpc0ZpcnN0IiwidHlwZSIsIlR5cGUiLCJOZXdsaW5lIiwiYWNjZXB0c0NhcmV0IiwibmVlZHNDYXJldE5vZGVBZnRlciIsImlzTGFzdE9mTGluZSIsImluc2VydEFmdGVyIiwibm9kZSIsIm5vZGVUb0luc2VydCIsIm5leHQiLCJuZXh0U2libGluZyIsInBhcmVudEVsZW1lbnQiLCJpbnNlcnRCZWZvcmUiLCJhcHBlbmRDaGlsZCIsIkNBUkVUX05PREVfQ0hBUiIsImV4cG9ydHMiLCJjcmVhdGVDYXJldE5vZGUiLCJzcGFuIiwiZG9jdW1lbnQiLCJjcmVhdGVFbGVtZW50IiwiY2xhc3NOYW1lIiwiY3JlYXRlVGV4dE5vZGUiLCJ1cGRhdGVDYXJldE5vZGUiLCJ0ZXh0Q29udGVudCIsImlzQ2FyZXROb2RlIiwiSFRNTEVsZW1lbnQiLCJ0YWdOYW1lIiwicmVtb3ZlTmV4dFNpYmxpbmdzIiwicmVtb3ZlTm9kZSIsInJlbW92ZSIsInJlbW92ZUNoaWxkcmVuIiwicGFyZW50IiwiZmlyc3RDaGlsZCIsInJlY29uY2lsZUxpbmUiLCJsaW5lQ29udGFpbmVyIiwicGFydHMiLCJjdXJyZW50Tm9kZSIsImxhc3RQYXJ0IiwibGVuZ3RoIiwiY2FuVXBkYXRlRE9NTm9kZSIsIm5leHROb2RlIiwicmVtb3ZlQ2hpbGQiLCJ1cGRhdGVET01Ob2RlIiwidG9ET01Ob2RlIiwiY2FyZXROb2RlIiwicmVjb25jaWxlRW1wdHlMaW5lIiwiZm91bmRCUiIsInBhcnROb2RlIiwicmVuZGVyTW9kZWwiLCJlZGl0b3IiLCJtb2RlbCIsImxpbmVzIiwicmVkdWNlIiwibGluZXNBcnIiLCJwdXNoIiwibGFzdExpbmUiLCJmb3JFYWNoIiwiaSIsImNoaWxkTm9kZXMiLCJjaGlsZHJlbiJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9lZGl0b3IvcmVuZGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAxOS0yMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMTkgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IHsgUGFydCwgVHlwZSB9IGZyb20gXCIuL3BhcnRzXCI7XG5pbXBvcnQgRWRpdG9yTW9kZWwgZnJvbSBcIi4vbW9kZWxcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIG5lZWRzQ2FyZXROb2RlQmVmb3JlKHBhcnQ6IFBhcnQsIHByZXZQYXJ0PzogUGFydCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGlzRmlyc3QgPSAhcHJldlBhcnQgfHwgcHJldlBhcnQudHlwZSA9PT0gVHlwZS5OZXdsaW5lO1xuICAgIHJldHVybiAhcGFydC5hY2NlcHRzQ2FyZXQgJiYgKGlzRmlyc3QgfHwgIXByZXZQYXJ0LmFjY2VwdHNDYXJldCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBuZWVkc0NhcmV0Tm9kZUFmdGVyKHBhcnQ6IFBhcnQsIGlzTGFzdE9mTGluZTogYm9vbGVhbik6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhcGFydC5hY2NlcHRzQ2FyZXQgJiYgaXNMYXN0T2ZMaW5lO1xufVxuXG5mdW5jdGlvbiBpbnNlcnRBZnRlcihub2RlOiBDaGlsZE5vZGUsIG5vZGVUb0luc2VydDogQ2hpbGROb2RlKTogdm9pZCB7XG4gICAgY29uc3QgbmV4dCA9IG5vZGUubmV4dFNpYmxpbmc7XG4gICAgaWYgKG5leHQpIHtcbiAgICAgICAgbm9kZS5wYXJlbnRFbGVtZW50IS5pbnNlcnRCZWZvcmUobm9kZVRvSW5zZXJ0LCBuZXh0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBub2RlLnBhcmVudEVsZW1lbnQhLmFwcGVuZENoaWxkKG5vZGVUb0luc2VydCk7XG4gICAgfVxufVxuXG4vLyBVc2UgYSBCT00gbWFya2VyIGZvciBjYXJldCBub2Rlcy5cbi8vIE9uIGEgZmlyc3QgdGVzdCwgdGhleSBzZWVtIHRvIGJlIGZpbHRlcmVkIG91dCB3aGVuIGNvcHlpbmcgdGV4dCBvdXQgb2YgdGhlIGVkaXRvcixcbi8vIGJ1dCB0aGlzIGNvdWxkIGJlIHBsYXRmb3JtIGRlcGVuZGVudC5cbi8vIEFzIGEgcHJlY2F1dGlvbmFyeSBtZWFzdXJlLCBJIGNob3NlIHRoZSBjaGFyYWN0ZXIgdGhhdCBzbGF0ZSBhbHNvIHVzZXMuXG5leHBvcnQgY29uc3QgQ0FSRVRfTk9ERV9DSEFSID0gXCJcXHVmZWZmXCI7XG4vLyBhIGNhcmV0IG5vZGUgaXMgYSBub2RlIHRoYXQgYWxsb3dzIHRoZSBjYXJldCB0byBiZSBwbGFjZWRcbi8vIHdoZXJlIG90aGVyd2lzZSBpdCB3b3VsZG4ndCBiZSBwb3NzaWJsZVxuLy8gKGUuZy4gbmV4dCB0byBhIHBpbGwgc3BhbiB3aXRob3V0IGFkamFjZW50IHRleHQgbm9kZSlcbmZ1bmN0aW9uIGNyZWF0ZUNhcmV0Tm9kZSgpOiBIVE1MRWxlbWVudCB7XG4gICAgY29uc3Qgc3BhbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIpO1xuICAgIHNwYW4uY2xhc3NOYW1lID0gXCJjYXJldE5vZGVcIjtcbiAgICBzcGFuLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKENBUkVUX05PREVfQ0hBUikpO1xuICAgIHJldHVybiBzcGFuO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVDYXJldE5vZGUobm9kZTogQ2hpbGROb2RlKTogdm9pZCB7XG4gICAgLy8gZW5zdXJlIHRoZSBjYXJldCBub2RlIGNvbnRhaW5zIG9ubHkgYSB6ZXJvLXdpZHRoIHNwYWNlXG4gICAgaWYgKG5vZGUudGV4dENvbnRlbnQgIT09IENBUkVUX05PREVfQ0hBUikge1xuICAgICAgICBub2RlLnRleHRDb250ZW50ID0gQ0FSRVRfTk9ERV9DSEFSO1xuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQ2FyZXROb2RlKG5vZGU/OiBOb2RlIHwgbnVsbCk6IG5vZGUgaXMgSFRNTEVsZW1lbnQge1xuICAgIHJldHVybiAhIW5vZGUgJiYgbm9kZSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50ICYmIG5vZGUudGFnTmFtZSA9PT0gXCJTUEFOXCIgJiYgbm9kZS5jbGFzc05hbWUgPT09IFwiY2FyZXROb2RlXCI7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZU5leHRTaWJsaW5ncyhub2RlOiBDaGlsZE5vZGUgfCBudWxsKTogdm9pZCB7XG4gICAgaWYgKCFub2RlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbm9kZSA9IG5vZGUubmV4dFNpYmxpbmc7XG4gICAgd2hpbGUgKG5vZGUpIHtcbiAgICAgICAgY29uc3QgcmVtb3ZlTm9kZSA9IG5vZGU7XG4gICAgICAgIG5vZGUgPSBub2RlLm5leHRTaWJsaW5nO1xuICAgICAgICByZW1vdmVOb2RlLnJlbW92ZSgpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcmVtb3ZlQ2hpbGRyZW4ocGFyZW50OiBIVE1MRWxlbWVudCk6IHZvaWQge1xuICAgIGNvbnN0IGZpcnN0Q2hpbGQgPSBwYXJlbnQuZmlyc3RDaGlsZDtcbiAgICBpZiAoZmlyc3RDaGlsZCkge1xuICAgICAgICByZW1vdmVOZXh0U2libGluZ3MoZmlyc3RDaGlsZCk7XG4gICAgICAgIGZpcnN0Q2hpbGQucmVtb3ZlKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZWNvbmNpbGVMaW5lKGxpbmVDb250YWluZXI6IENoaWxkTm9kZSwgcGFydHM6IFBhcnRbXSk6IHZvaWQge1xuICAgIGxldCBjdXJyZW50Tm9kZTogQ2hpbGROb2RlIHwgbnVsbCA9IG51bGw7XG4gICAgbGV0IHByZXZQYXJ0OiBQYXJ0IHwgdW5kZWZpbmVkO1xuICAgIGNvbnN0IGxhc3RQYXJ0ID0gcGFydHNbcGFydHMubGVuZ3RoIC0gMV07XG5cbiAgICBmb3IgKGNvbnN0IHBhcnQgb2YgcGFydHMpIHtcbiAgICAgICAgY29uc3QgaXNGaXJzdCA9ICFwcmV2UGFydDtcbiAgICAgICAgY3VycmVudE5vZGUgPSBpc0ZpcnN0ID8gbGluZUNvbnRhaW5lci5maXJzdENoaWxkIDogY3VycmVudE5vZGUhLm5leHRTaWJsaW5nO1xuXG4gICAgICAgIGlmIChuZWVkc0NhcmV0Tm9kZUJlZm9yZShwYXJ0LCBwcmV2UGFydCkpIHtcbiAgICAgICAgICAgIGlmIChpc0NhcmV0Tm9kZShjdXJyZW50Tm9kZSBhcyBFbGVtZW50KSkge1xuICAgICAgICAgICAgICAgIHVwZGF0ZUNhcmV0Tm9kZShjdXJyZW50Tm9kZSEpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnROb2RlID0gY3VycmVudE5vZGUhLm5leHRTaWJsaW5nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsaW5lQ29udGFpbmVyLmluc2VydEJlZm9yZShjcmVhdGVDYXJldE5vZGUoKSwgY3VycmVudE5vZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIHJlbW92ZSBub2RlcyB1bnRpbCBtYXRjaGluZyBjdXJyZW50IHBhcnRcbiAgICAgICAgd2hpbGUgKGN1cnJlbnROb2RlICYmICFwYXJ0LmNhblVwZGF0ZURPTU5vZGUoY3VycmVudE5vZGUpKSB7XG4gICAgICAgICAgICBjb25zdCBuZXh0Tm9kZSA9IGN1cnJlbnROb2RlLm5leHRTaWJsaW5nO1xuICAgICAgICAgICAgbGluZUNvbnRhaW5lci5yZW1vdmVDaGlsZChjdXJyZW50Tm9kZSk7XG4gICAgICAgICAgICBjdXJyZW50Tm9kZSA9IG5leHROb2RlO1xuICAgICAgICB9XG4gICAgICAgIC8vIHVwZGF0ZSBvciBpbnNlcnQgbm9kZSBmb3IgY3VycmVudCBwYXJ0XG4gICAgICAgIGlmIChjdXJyZW50Tm9kZSAmJiBwYXJ0KSB7XG4gICAgICAgICAgICBwYXJ0LnVwZGF0ZURPTU5vZGUoY3VycmVudE5vZGUpO1xuICAgICAgICB9IGVsc2UgaWYgKHBhcnQpIHtcbiAgICAgICAgICAgIGN1cnJlbnROb2RlID0gcGFydC50b0RPTU5vZGUoKSBhcyBDaGlsZE5vZGU7XG4gICAgICAgICAgICAvLyBob29rcyB1cCBuZXh0U2libGluZyBmb3IgbmV4dCBpdGVyYXRpb25cbiAgICAgICAgICAgIGxpbmVDb250YWluZXIuYXBwZW5kQ2hpbGQoY3VycmVudE5vZGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG5lZWRzQ2FyZXROb2RlQWZ0ZXIocGFydCwgcGFydCA9PT0gbGFzdFBhcnQpKSB7XG4gICAgICAgICAgICBpZiAoaXNDYXJldE5vZGUoY3VycmVudE5vZGU/Lm5leHRTaWJsaW5nIGFzIEVsZW1lbnQpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudE5vZGUgPSBjdXJyZW50Tm9kZSEubmV4dFNpYmxpbmc7XG4gICAgICAgICAgICAgICAgdXBkYXRlQ2FyZXROb2RlKGN1cnJlbnROb2RlIGFzIEhUTUxFbGVtZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY2FyZXROb2RlID0gY3JlYXRlQ2FyZXROb2RlKCk7XG4gICAgICAgICAgICAgICAgaW5zZXJ0QWZ0ZXIoY3VycmVudE5vZGUgYXMgSFRNTEVsZW1lbnQsIGNhcmV0Tm9kZSk7XG4gICAgICAgICAgICAgICAgY3VycmVudE5vZGUgPSBjYXJldE5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBwcmV2UGFydCA9IHBhcnQ7XG4gICAgfVxuXG4gICAgcmVtb3ZlTmV4dFNpYmxpbmdzKGN1cnJlbnROb2RlKTtcbn1cblxuZnVuY3Rpb24gcmVjb25jaWxlRW1wdHlMaW5lKGxpbmVDb250YWluZXI6IEhUTUxFbGVtZW50KTogdm9pZCB7XG4gICAgLy8gZW1wdHkgZGl2IG5lZWRzIHRvIGhhdmUgYSBCUiBpbiBpdCB0byBnaXZlIGl0IGhlaWdodFxuICAgIGxldCBmb3VuZEJSID0gZmFsc2U7XG4gICAgbGV0IHBhcnROb2RlID0gbGluZUNvbnRhaW5lci5maXJzdENoaWxkO1xuICAgIHdoaWxlIChwYXJ0Tm9kZSkge1xuICAgICAgICBjb25zdCBuZXh0Tm9kZSA9IHBhcnROb2RlLm5leHRTaWJsaW5nO1xuICAgICAgICBpZiAoIWZvdW5kQlIgJiYgKHBhcnROb2RlIGFzIEhUTUxFbGVtZW50KS50YWdOYW1lID09PSBcIkJSXCIpIHtcbiAgICAgICAgICAgIGZvdW5kQlIgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGFydE5vZGUucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICAgICAgcGFydE5vZGUgPSBuZXh0Tm9kZTtcbiAgICB9XG4gICAgaWYgKCFmb3VuZEJSKSB7XG4gICAgICAgIGxpbmVDb250YWluZXIuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImJyXCIpKTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJNb2RlbChlZGl0b3I6IEhUTUxEaXZFbGVtZW50LCBtb2RlbDogRWRpdG9yTW9kZWwpOiB2b2lkIHtcbiAgICBjb25zdCBsaW5lcyA9IG1vZGVsLnBhcnRzLnJlZHVjZTxQYXJ0W11bXT4oXG4gICAgICAgIChsaW5lc0FyciwgcGFydCkgPT4ge1xuICAgICAgICAgICAgaWYgKHBhcnQudHlwZSA9PT0gVHlwZS5OZXdsaW5lKSB7XG4gICAgICAgICAgICAgICAgbGluZXNBcnIucHVzaChbXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGxhc3RMaW5lID0gbGluZXNBcnJbbGluZXNBcnIubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgbGFzdExpbmUucHVzaChwYXJ0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBsaW5lc0FycjtcbiAgICAgICAgfSxcbiAgICAgICAgW1tdXSxcbiAgICApO1xuICAgIGxpbmVzLmZvckVhY2goKHBhcnRzLCBpKSA9PiB7XG4gICAgICAgIC8vIGZpbmQgZmlyc3QgKGFuZCByZW1vdmUgYW55dGhpbmcgZWxzZSkgZGl2IHdpdGhvdXQgY2xhc3NOYW1lXG4gICAgICAgIC8vIChhcyBicm93c2VycyBpbnNlcnQgdGhlc2UgaW4gY29udGVudGVkaXRhYmxlKSBsaW5lIGNvbnRhaW5lclxuICAgICAgICBsZXQgbGluZUNvbnRhaW5lciA9IGVkaXRvci5jaGlsZE5vZGVzW2ldO1xuICAgICAgICB3aGlsZSAobGluZUNvbnRhaW5lciAmJiAoKDxFbGVtZW50PmxpbmVDb250YWluZXIpLnRhZ05hbWUgIT09IFwiRElWXCIgfHwgISEoPEVsZW1lbnQ+bGluZUNvbnRhaW5lcikuY2xhc3NOYW1lKSkge1xuICAgICAgICAgICAgZWRpdG9yLnJlbW92ZUNoaWxkKGxpbmVDb250YWluZXIpO1xuICAgICAgICAgICAgbGluZUNvbnRhaW5lciA9IGVkaXRvci5jaGlsZE5vZGVzW2ldO1xuICAgICAgICB9XG4gICAgICAgIGlmICghbGluZUNvbnRhaW5lcikge1xuICAgICAgICAgICAgbGluZUNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgICAgICBlZGl0b3IuYXBwZW5kQ2hpbGQobGluZUNvbnRhaW5lcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZWNvbmNpbGVMaW5lKGxpbmVDb250YWluZXIsIHBhcnRzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlY29uY2lsZUVtcHR5TGluZShsaW5lQ29udGFpbmVyIGFzIEhUTUxFbGVtZW50KTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIGlmIChsaW5lcy5sZW5ndGgpIHtcbiAgICAgICAgcmVtb3ZlTmV4dFNpYmxpbmdzKGVkaXRvci5jaGlsZHJlbltsaW5lcy5sZW5ndGggLSAxXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmVtb3ZlQ2hpbGRyZW4oZWRpdG9y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