UNPKG

matrix-react-sdk

Version:
238 lines (197 loc) 21.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.needsCaretNodeBefore = needsCaretNodeBefore; exports.needsCaretNodeAfter = needsCaretNodeAfter; exports.isCaretNode = isCaretNode; exports.renderModel = renderModel; exports.CARET_NODE_CHAR = void 0; /* Copyright 2019 New Vector Ltd Copyright 2019 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 needsCaretNodeBefore(part /*: Part*/ , prevPart /*: Part*/ ) { const isFirst = !prevPart || prevPart.type === "newline"; return !part.canEdit && (isFirst || !prevPart.canEdit); } function needsCaretNodeAfter(part /*: Part*/ , isLastOfLine /*: boolean*/ ) { return !part.canEdit && isLastOfLine; } function insertAfter(node /*: HTMLElement*/ , nodeToInsert /*: HTMLElement*/ ) { 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 = "\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) exports.CARET_NODE_CHAR = CARET_NODE_CHAR; function createCaretNode() { const span = document.createElement("span"); span.className = "caretNode"; span.appendChild(document.createTextNode(CARET_NODE_CHAR)); return span; } function updateCaretNode(node /*: HTMLElement*/ ) { // ensure the caret node contains only a zero-width space if (node.textContent !== CARET_NODE_CHAR) { node.textContent = CARET_NODE_CHAR; } } function isCaretNode(node /*: HTMLElement*/ ) { return node && node.tagName === "SPAN" && node.className === "caretNode"; } function removeNextSiblings(node /*: ChildNode*/ ) { if (!node) { return; } node = node.nextSibling; while (node) { const removeNode = node; node = node.nextSibling; removeNode.remove(); } } function removeChildren(parent /*: HTMLElement*/ ) { const firstChild = parent.firstChild; if (firstChild) { removeNextSiblings(firstChild); firstChild.remove(); } } function reconcileLine(lineContainer /*: ChildNode*/ , parts /*: Part[]*/ ) { let currentNode; 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 /*: HTMLDivElement*/ , model /*: EditorModel*/ ) { const lines = model.parts.reduce((linesArr, part) => { if (part.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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9lZGl0b3IvcmVuZGVyLnRzIl0sIm5hbWVzIjpbIm5lZWRzQ2FyZXROb2RlQmVmb3JlIiwicGFydCIsInByZXZQYXJ0IiwiaXNGaXJzdCIsInR5cGUiLCJjYW5FZGl0IiwibmVlZHNDYXJldE5vZGVBZnRlciIsImlzTGFzdE9mTGluZSIsImluc2VydEFmdGVyIiwibm9kZSIsIm5vZGVUb0luc2VydCIsIm5leHQiLCJuZXh0U2libGluZyIsInBhcmVudEVsZW1lbnQiLCJpbnNlcnRCZWZvcmUiLCJhcHBlbmRDaGlsZCIsIkNBUkVUX05PREVfQ0hBUiIsImNyZWF0ZUNhcmV0Tm9kZSIsInNwYW4iLCJkb2N1bWVudCIsImNyZWF0ZUVsZW1lbnQiLCJjbGFzc05hbWUiLCJjcmVhdGVUZXh0Tm9kZSIsInVwZGF0ZUNhcmV0Tm9kZSIsInRleHRDb250ZW50IiwiaXNDYXJldE5vZGUiLCJ0YWdOYW1lIiwicmVtb3ZlTmV4dFNpYmxpbmdzIiwicmVtb3ZlTm9kZSIsInJlbW92ZSIsInJlbW92ZUNoaWxkcmVuIiwicGFyZW50IiwiZmlyc3RDaGlsZCIsInJlY29uY2lsZUxpbmUiLCJsaW5lQ29udGFpbmVyIiwicGFydHMiLCJjdXJyZW50Tm9kZSIsImxhc3RQYXJ0IiwibGVuZ3RoIiwiY2FuVXBkYXRlRE9NTm9kZSIsIm5leHROb2RlIiwicmVtb3ZlQ2hpbGQiLCJ1cGRhdGVET01Ob2RlIiwidG9ET01Ob2RlIiwiY2FyZXROb2RlIiwicmVjb25jaWxlRW1wdHlMaW5lIiwiZm91bmRCUiIsInBhcnROb2RlIiwicmVuZGVyTW9kZWwiLCJlZGl0b3IiLCJtb2RlbCIsImxpbmVzIiwicmVkdWNlIiwibGluZXNBcnIiLCJwdXNoIiwibGFzdExpbmUiLCJmb3JFYWNoIiwiaSIsImNoaWxkTm9kZXMiLCJjaGlsZHJlbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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bUJBLE1BQUlpQixLQUFLLENBQUNiLE1BQVYsRUFBa0I7QUFDZFgsSUFBQUEsa0JBQWtCLENBQUNzQixNQUFNLENBQUNVLFFBQVAsQ0FBZ0JSLEtBQUssQ0FBQ2IsTUFBTixHQUFlLENBQS9CLENBQUQsQ0FBbEI7QUFDSCxHQUZELE1BRU87QUFDSFIsSUFBQUEsY0FBYyxDQUFDbUIsTUFBRCxDQUFkO0FBQ0g7QUFDSiIsInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAxOSBOZXcgVmVjdG9yIEx0ZFxuQ29weXJpZ2h0IDIwMTkgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4qL1xuXG5pbXBvcnQge1BhcnR9IGZyb20gXCIuL3BhcnRzXCI7XG5pbXBvcnQgRWRpdG9yTW9kZWwgZnJvbSBcIi4vbW9kZWxcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIG5lZWRzQ2FyZXROb2RlQmVmb3JlKHBhcnQ6IFBhcnQsIHByZXZQYXJ0OiBQYXJ0KSB7XG4gICAgY29uc3QgaXNGaXJzdCA9ICFwcmV2UGFydCB8fCBwcmV2UGFydC50eXBlID09PSBcIm5ld2xpbmVcIjtcbiAgICByZXR1cm4gIXBhcnQuY2FuRWRpdCAmJiAoaXNGaXJzdCB8fCAhcHJldlBhcnQuY2FuRWRpdCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBuZWVkc0NhcmV0Tm9kZUFmdGVyKHBhcnQ6IFBhcnQsIGlzTGFzdE9mTGluZTogYm9vbGVhbikge1xuICAgIHJldHVybiAhcGFydC5jYW5FZGl0ICYmIGlzTGFzdE9mTGluZTtcbn1cblxuZnVuY3Rpb24gaW5zZXJ0QWZ0ZXIobm9kZTogSFRNTEVsZW1lbnQsIG5vZGVUb0luc2VydDogSFRNTEVsZW1lbnQpIHtcbiAgICBjb25zdCBuZXh0ID0gbm9kZS5uZXh0U2libGluZztcbiAgICBpZiAobmV4dCkge1xuICAgICAgICBub2RlLnBhcmVudEVsZW1lbnQuaW5zZXJ0QmVmb3JlKG5vZGVUb0luc2VydCwgbmV4dCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbm9kZS5wYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKG5vZGVUb0luc2VydCk7XG4gICAgfVxufVxuXG4vLyBVc2UgYSBCT00gbWFya2VyIGZvciBjYXJldCBub2Rlcy5cbi8vIE9uIGEgZmlyc3QgdGVzdCwgdGhleSBzZWVtIHRvIGJlIGZpbHRlcmVkIG91dCB3aGVuIGNvcHlpbmcgdGV4dCBvdXQgb2YgdGhlIGVkaXRvcixcbi8vIGJ1dCB0aGlzIGNvdWxkIGJlIHBsYXRmb3JtIGRlcGVuZGVudC5cbi8vIEFzIGEgcHJlY2F1dGlvbmFyeSBtZWFzdXJlLCBJIGNob3NlIHRoZSBjaGFyYWN0ZXIgdGhhdCBzbGF0ZSBhbHNvIHVzZXMuXG5leHBvcnQgY29uc3QgQ0FSRVRfTk9ERV9DSEFSID0gXCJcXHVmZWZmXCI7XG4vLyBhIGNhcmV0IG5vZGUgaXMgYSBub2RlIHRoYXQgYWxsb3dzIHRoZSBjYXJldCB0byBiZSBwbGFjZWRcbi8vIHdoZXJlIG90aGVyd2lzZSBpdCB3b3VsZG4ndCBiZSBwb3NzaWJsZVxuLy8gKGUuZy4gbmV4dCB0byBhIHBpbGwgc3BhbiB3aXRob3V0IGFkamFjZW50IHRleHQgbm9kZSlcbmZ1bmN0aW9uIGNyZWF0ZUNhcmV0Tm9kZSgpIHtcbiAgICBjb25zdCBzcGFuID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNwYW5cIik7XG4gICAgc3Bhbi5jbGFzc05hbWUgPSBcImNhcmV0Tm9kZVwiO1xuICAgIHNwYW4uYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoQ0FSRVRfTk9ERV9DSEFSKSk7XG4gICAgcmV0dXJuIHNwYW47XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZUNhcmV0Tm9kZShub2RlOiBIVE1MRWxlbWVudCkge1xuICAgIC8vIGVuc3VyZSB0aGUgY2FyZXQgbm9kZSBjb250YWlucyBvbmx5IGEgemVyby13aWR0aCBzcGFjZVxuICAgIGlmIChub2RlLnRleHRDb250ZW50ICE9PSBDQVJFVF9OT0RFX0NIQVIpIHtcbiAgICAgICAgbm9kZS50ZXh0Q29udGVudCA9IENBUkVUX05PREVfQ0hBUjtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0NhcmV0Tm9kZShub2RlOiBIVE1MRWxlbWVudCkge1xuICAgIHJldHVybiBub2RlICYmIG5vZGUudGFnTmFtZSA9PT0gXCJTUEFOXCIgJiYgbm9kZS5jbGFzc05hbWUgPT09IFwiY2FyZXROb2RlXCI7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZU5leHRTaWJsaW5ncyhub2RlOiBDaGlsZE5vZGUpIHtcbiAgICBpZiAoIW5vZGUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBub2RlID0gbm9kZS5uZXh0U2libGluZztcbiAgICB3aGlsZSAobm9kZSkge1xuICAgICAgICBjb25zdCByZW1vdmVOb2RlID0gbm9kZTtcbiAgICAgICAgbm9kZSA9IG5vZGUubmV4dFNpYmxpbmc7XG4gICAgICAgIHJlbW92ZU5vZGUucmVtb3ZlKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmVDaGlsZHJlbihwYXJlbnQ6IEhUTUxFbGVtZW50KSB7XG4gICAgY29uc3QgZmlyc3RDaGlsZCA9IHBhcmVudC5maXJzdENoaWxkO1xuICAgIGlmIChmaXJzdENoaWxkKSB7XG4gICAgICAgIHJlbW92ZU5leHRTaWJsaW5ncyhmaXJzdENoaWxkKTtcbiAgICAgICAgZmlyc3RDaGlsZC5yZW1vdmUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlY29uY2lsZUxpbmUobGluZUNvbnRhaW5lcjogQ2hpbGROb2RlLCBwYXJ0czogUGFydFtdKSB7XG4gICAgbGV0IGN1cnJlbnROb2RlO1xuICAgIGxldCBwcmV2UGFydDtcbiAgICBjb25zdCBsYXN0UGFydCA9IHBhcnRzW3BhcnRzLmxlbmd0aCAtIDFdO1xuXG4gICAgZm9yIChjb25zdCBwYXJ0IG9mIHBhcnRzKSB7XG4gICAgICAgIGNvbnN0IGlzRmlyc3QgPSAhcHJldlBhcnQ7XG4gICAgICAgIGN1cnJlbnROb2RlID0gaXNGaXJzdCA/IGxpbmVDb250YWluZXIuZmlyc3RDaGlsZCA6IGN1cnJlbnROb2RlLm5leHRTaWJsaW5nO1xuXG4gICAgICAgIGlmIChuZWVkc0NhcmV0Tm9kZUJlZm9yZShwYXJ0LCBwcmV2UGFydCkpIHtcbiAgICAgICAgICAgIGlmIChpc0NhcmV0Tm9kZShjdXJyZW50Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICB1cGRhdGVDYXJldE5vZGUoY3VycmVudE5vZGUpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnROb2RlID0gY3VycmVudE5vZGUubmV4dFNpYmxpbmc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGxpbmVDb250YWluZXIuaW5zZXJ0QmVmb3JlKGNyZWF0ZUNhcmV0Tm9kZSgpLCBjdXJyZW50Tm9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gcmVtb3ZlIG5vZGVzIHVudGlsIG1hdGNoaW5nIGN1cnJlbnQgcGFydFxuICAgICAgICB3aGlsZSAoY3VycmVudE5vZGUgJiYgIXBhcnQuY2FuVXBkYXRlRE9NTm9kZShjdXJyZW50Tm9kZSkpIHtcbiAgICAgICAgICAgIGNvbnN0IG5leHROb2RlID0gY3VycmVudE5vZGUubmV4dFNpYmxpbmc7XG4gICAgICAgICAgICBsaW5lQ29udGFpbmVyLnJlbW92ZUNoaWxkKGN1cnJlbnROb2RlKTtcbiAgICAgICAgICAgIGN1cnJlbnROb2RlID0gbmV4dE5vZGU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gdXBkYXRlIG9yIGluc2VydCBub2RlIGZvciBjdXJyZW50IHBhcnRcbiAgICAgICAgaWYgKGN1cnJlbnROb2RlICYmIHBhcnQpIHtcbiAgICAgICAgICAgIHBhcnQudXBkYXRlRE9NTm9kZShjdXJyZW50Tm9kZSk7XG4gICAgICAgIH0gZWxzZSBpZiAocGFydCkge1xuICAgICAgICAgICAgY3VycmVudE5vZGUgPSBwYXJ0LnRvRE9NTm9kZSgpO1xuICAgICAgICAgICAgLy8gaG9va3MgdXAgbmV4dFNpYmxpbmcgZm9yIG5leHQgaXRlcmF0aW9uXG4gICAgICAgICAgICBsaW5lQ29udGFpbmVyLmFwcGVuZENoaWxkKGN1cnJlbnROb2RlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChuZWVkc0NhcmV0Tm9kZUFmdGVyKHBhcnQsIHBhcnQgPT09IGxhc3RQYXJ0KSkge1xuICAgICAgICAgICAgaWYgKGlzQ2FyZXROb2RlKGN1cnJlbnROb2RlLm5leHRTaWJsaW5nKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnROb2RlID0gY3VycmVudE5vZGUubmV4dFNpYmxpbmc7XG4gICAgICAgICAgICAgICAgdXBkYXRlQ2FyZXROb2RlKGN1cnJlbnROb2RlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY2FyZXROb2RlID0gY3JlYXRlQ2FyZXROb2RlKCk7XG4gICAgICAgICAgICAgICAgaW5zZXJ0QWZ0ZXIoY3VycmVudE5vZGUsIGNhcmV0Tm9kZSk7XG4gICAgICAgICAgICAgICAgY3VycmVudE5vZGUgPSBjYXJldE5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBwcmV2UGFydCA9IHBhcnQ7XG4gICAgfVxuXG4gICAgcmVtb3ZlTmV4dFNpYmxpbmdzKGN1cnJlbnROb2RlKTtcbn1cblxuZnVuY3Rpb24gcmVjb25jaWxlRW1wdHlMaW5lKGxpbmVDb250YWluZXIpIHtcbiAgICAvLyBlbXB0eSBkaXYgbmVlZHMgdG8gaGF2ZSBhIEJSIGluIGl0IHRvIGdpdmUgaXQgaGVpZ2h0XG4gICAgbGV0IGZvdW5kQlIgPSBmYWxzZTtcbiAgICBsZXQgcGFydE5vZGUgPSBsaW5lQ29udGFpbmVyLmZpcnN0Q2hpbGQ7XG4gICAgd2hpbGUgKHBhcnROb2RlKSB7XG4gICAgICAgIGNvbnN0IG5leHROb2RlID0gcGFydE5vZGUubmV4dFNpYmxpbmc7XG4gICAgICAgIGlmICghZm91bmRCUiAmJiBwYXJ0Tm9kZS50YWdOYW1lID09PSBcIkJSXCIpIHtcbiAgICAgICAgICAgIGZvdW5kQlIgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGFydE5vZGUucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICAgICAgcGFydE5vZGUgPSBuZXh0Tm9kZTtcbiAgICB9XG4gICAgaWYgKCFmb3VuZEJSKSB7XG4gICAgICAgIGxpbmVDb250YWluZXIuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImJyXCIpKTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJNb2RlbChlZGl0b3I6IEhUTUxEaXZFbGVtZW50LCBtb2RlbDogRWRpdG9yTW9kZWwpIHtcbiAgICBjb25zdCBsaW5lcyA9IG1vZGVsLnBhcnRzLnJlZHVjZSgobGluZXNBcnIsIHBhcnQpID0+IHtcbiAgICAgICAgaWYgKHBhcnQudHlwZSA9PT0gXCJuZXdsaW5lXCIpIHtcbiAgICAgICAgICAgIGxpbmVzQXJyLnB1c2goW10pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgbGFzdExpbmUgPSBsaW5lc0FycltsaW5lc0Fyci5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgIGxhc3RMaW5lLnB1c2gocGFydCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxpbmVzQXJyO1xuICAgIH0sIFtbXV0pO1xuICAgIGxpbmVzLmZvckVhY2goKHBhcnRzLCBpKSA9PiB7XG4gICAgICAgIC8vIGZpbmQgZmlyc3QgKGFuZCByZW1vdmUgYW55dGhpbmcgZWxzZSkgZGl2IHdpdGhvdXQgY2xhc3NOYW1lXG4gICAgICAgIC8vIChhcyBicm93c2VycyBpbnNlcnQgdGhlc2UgaW4gY29udGVudGVkaXRhYmxlKSBsaW5lIGNvbnRhaW5lclxuICAgICAgICBsZXQgbGluZUNvbnRhaW5lciA9IGVkaXRvci5jaGlsZE5vZGVzW2ldO1xuICAgICAgICB3aGlsZSAobGluZUNvbnRhaW5lciAmJiAoKDxFbGVtZW50PmxpbmVDb250YWluZXIpLnRhZ05hbWUgIT09IFwiRElWXCIgfHwgISEoPEVsZW1lbnQ+bGluZUNvbnRhaW5lcikuY2xhc3NOYW1lKSkge1xuICAgICAgICAgICAgZWRpdG9yLnJlbW92ZUNoaWxkKGxpbmVDb250YWluZXIpO1xuICAgICAgICAgICAgbGluZUNvbnRhaW5lciA9IGVkaXRvci5jaGlsZE5vZGVzW2ldO1xuICAgICAgICB9XG4gICAgICAgIGlmICghbGluZUNvbnRhaW5lcikge1xuICAgICAgICAgICAgbGluZUNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgICAgICBlZGl0b3IuYXBwZW5kQ2hpbGQobGluZUNvbnRhaW5lcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZWNvbmNpbGVMaW5lKGxpbmVDb250YWluZXIsIHBhcnRzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlY29uY2lsZUVtcHR5TGluZShsaW5lQ29udGFpbmVyKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIGlmIChsaW5lcy5sZW5ndGgpIHtcbiAgICAgICAgcmVtb3ZlTmV4dFNpYmxpbmdzKGVkaXRvci5jaGlsZHJlbltsaW5lcy5sZW5ndGggLSAxXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmVtb3ZlQ2hpbGRyZW4oZWRpdG9yKTtcbiAgICB9XG59XG4iXX0=