matrix-react-sdk
Version:
SDK for matrix.org using React
182 lines (178 loc) • 21.3 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getLineAndNodePosition = getLineAndNodePosition;
exports.setCaretPosition = setCaretPosition;
exports.setSelection = setSelection;
var _render = require("./render");
var _range = _interopRequireDefault(require("./range"));
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 setSelection(editor, model, selection) {
if (selection instanceof _range.default) {
setDocumentRangeSelection(editor, model, selection);
} else {
setCaretPosition(editor, model, selection);
}
}
function setDocumentRangeSelection(editor, model, range) {
const sel = document.getSelection();
sel.removeAllRanges();
const selectionRange = document.createRange();
const start = getNodeAndOffsetForPosition(editor, model, range.start);
selectionRange.setStart(start.node, start.offset);
const end = getNodeAndOffsetForPosition(editor, model, range.end);
selectionRange.setEnd(end.node, end.offset);
sel.addRange(selectionRange);
}
function setCaretPosition(editor, model, caretPosition) {
if (model.isEmpty) return; // selection can't possibly be wrong, so avoid a reflow
const range = document.createRange();
const {
node,
offset
} = getNodeAndOffsetForPosition(editor, model, caretPosition);
range.setStart(node, offset);
range.collapse(true);
const sel = document.getSelection();
if (sel.rangeCount === 1) {
const existingRange = sel.getRangeAt(0);
if (existingRange.startContainer === range.startContainer && existingRange.startOffset === range.startOffset && existingRange.collapsed === range.collapsed) {
// If the selection matches, it's important to leave it alone.
// Recreating the selection state in at least Chrome can cause
// strange side effects, like touch bar flickering on every key.
// See https://github.com/vector-im/element-web/issues/9299
return;
}
}
sel.removeAllRanges();
sel.addRange(range);
}
function getNodeAndOffsetForPosition(editor, model, position) {
const {
offset,
lineIndex,
nodeIndex
} = getLineAndNodePosition(model, position);
const lineNode = editor.childNodes[lineIndex];
let focusNode;
// empty line with just a <br>
if (nodeIndex === -1) {
focusNode = lineNode;
} else {
focusNode = lineNode.childNodes[nodeIndex];
// make sure we have a text node
if (focusNode.nodeType === Node.ELEMENT_NODE && focusNode.firstChild) {
focusNode = focusNode.firstChild;
}
}
return {
node: focusNode,
offset
};
}
function getLineAndNodePosition(model, caretPosition) {
const {
parts
} = model;
const partIndex = caretPosition.index;
let {
offset
} = caretPosition;
const lineResult = findNodeInLineForPart(parts, partIndex, offset);
const {
lineIndex
} = lineResult;
let {
nodeIndex
} = lineResult;
// we're at an empty line between a newline part
// and another newline part or end/start of parts.
// set offset to 0 so it gets set to the <br> inside the line container
if (nodeIndex === -1) {
offset = 0;
} else {
// move caret out of uneditable part (into caret node, or empty line br) if needed
({
nodeIndex,
offset
} = moveOutOfUnselectablePart(parts, partIndex, nodeIndex, offset));
}
return {
lineIndex,
nodeIndex,
offset
};
}
function findNodeInLineForPart(parts, partIndex, offset) {
let lineIndex = 0;
let nodeIndex = -1;
let prevPart;
// go through to parts up till (and including) the index
// to find newline parts
for (let i = 0; i <= partIndex; ++i) {
const part = parts[i];
if (part.type === _parts.Type.Newline) {
// don't jump over the linebreak if the offset is before it
if (i == partIndex && offset === 0) {
continue;
}
lineIndex += 1;
nodeIndex = -1;
prevPart = undefined;
} else {
nodeIndex += 1;
if ((0, _render.needsCaretNodeBefore)(part, prevPart)) {
nodeIndex += 1;
}
// only jump over caret node if we're not at our destination node already,
// as we'll assume in moveOutOfUnselectablePart that nodeIndex
// refers to the node corresponding to the part,
// and not an adjacent caret node
if (i < partIndex) {
const nextPart = parts[i + 1];
const isLastOfLine = !nextPart || nextPart.type === _parts.Type.Newline;
if ((0, _render.needsCaretNodeAfter)(part, isLastOfLine)) {
nodeIndex += 1;
}
}
prevPart = part;
}
}
return {
lineIndex,
nodeIndex
};
}
function moveOutOfUnselectablePart(parts, partIndex, nodeIndex, offset) {
// move caret before or after unselectable part
const part = parts[partIndex];
if (part && !part.acceptsCaret) {
if (offset === 0) {
nodeIndex -= 1;
const prevPart = parts[partIndex - 1];
// if the previous node is a caret node, it's empty
// so the offset can stay at 0
// only when it's not, we need to set the offset
// at the end of the node
if (!(0, _render.needsCaretNodeBefore)(part, prevPart)) {
offset = prevPart.text.length;
}
} else {
nodeIndex += 1;
offset = 0;
}
}
return {
nodeIndex,
offset
};
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVuZGVyIiwicmVxdWlyZSIsIl9yYW5nZSIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfcGFydHMiLCJzZXRTZWxlY3Rpb24iLCJlZGl0b3IiLCJtb2RlbCIsInNlbGVjdGlvbiIsIlJhbmdlIiwic2V0RG9jdW1lbnRSYW5nZVNlbGVjdGlvbiIsInNldENhcmV0UG9zaXRpb24iLCJyYW5nZSIsInNlbCIsImRvY3VtZW50IiwiZ2V0U2VsZWN0aW9uIiwicmVtb3ZlQWxsUmFuZ2VzIiwic2VsZWN0aW9uUmFuZ2UiLCJjcmVhdGVSYW5nZSIsInN0YXJ0IiwiZ2V0Tm9kZUFuZE9mZnNldEZvclBvc2l0aW9uIiwic2V0U3RhcnQiLCJub2RlIiwib2Zmc2V0IiwiZW5kIiwic2V0RW5kIiwiYWRkUmFuZ2UiLCJjYXJldFBvc2l0aW9uIiwiaXNFbXB0eSIsImNvbGxhcHNlIiwicmFuZ2VDb3VudCIsImV4aXN0aW5nUmFuZ2UiLCJnZXRSYW5nZUF0Iiwic3RhcnRDb250YWluZXIiLCJzdGFydE9mZnNldCIsImNvbGxhcHNlZCIsInBvc2l0aW9uIiwibGluZUluZGV4Iiwibm9kZUluZGV4IiwiZ2V0TGluZUFuZE5vZGVQb3NpdGlvbiIsImxpbmVOb2RlIiwiY2hpbGROb2RlcyIsImZvY3VzTm9kZSIsIm5vZGVUeXBlIiwiTm9kZSIsIkVMRU1FTlRfTk9ERSIsImZpcnN0Q2hpbGQiLCJwYXJ0cyIsInBhcnRJbmRleCIsImluZGV4IiwibGluZVJlc3VsdCIsImZpbmROb2RlSW5MaW5lRm9yUGFydCIsIm1vdmVPdXRPZlVuc2VsZWN0YWJsZVBhcnQiLCJwcmV2UGFydCIsImkiLCJwYXJ0IiwidHlwZSIsIlR5cGUiLCJOZXdsaW5lIiwidW5kZWZpbmVkIiwibmVlZHNDYXJldE5vZGVCZWZvcmUiLCJuZXh0UGFydCIsImlzTGFzdE9mTGluZSIsIm5lZWRzQ2FyZXROb2RlQWZ0ZXIiLCJhY2NlcHRzQ2FyZXQiLCJ0ZXh0IiwibGVuZ3RoIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2VkaXRvci9jYXJldC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMTktMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDE5IFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCB7IG5lZWRzQ2FyZXROb2RlQmVmb3JlLCBuZWVkc0NhcmV0Tm9kZUFmdGVyIH0gZnJvbSBcIi4vcmVuZGVyXCI7XG5pbXBvcnQgUmFuZ2UgZnJvbSBcIi4vcmFuZ2VcIjtcbmltcG9ydCBFZGl0b3JNb2RlbCBmcm9tIFwiLi9tb2RlbFwiO1xuaW1wb3J0IERvY3VtZW50UG9zaXRpb24sIHsgSVBvc2l0aW9uIH0gZnJvbSBcIi4vcG9zaXRpb25cIjtcbmltcG9ydCB7IFBhcnQsIFR5cGUgfSBmcm9tIFwiLi9wYXJ0c1wiO1xuXG5leHBvcnQgdHlwZSBDYXJldCA9IFJhbmdlIHwgRG9jdW1lbnRQb3NpdGlvbjtcblxuZXhwb3J0IGZ1bmN0aW9uIHNldFNlbGVjdGlvbihlZGl0b3I6IEhUTUxEaXZFbGVtZW50LCBtb2RlbDogRWRpdG9yTW9kZWwsIHNlbGVjdGlvbjogUmFuZ2UgfCBJUG9zaXRpb24pOiB2b2lkIHtcbiAgICBpZiAoc2VsZWN0aW9uIGluc3RhbmNlb2YgUmFuZ2UpIHtcbiAgICAgICAgc2V0RG9jdW1lbnRSYW5nZVNlbGVjdGlvbihlZGl0b3IsIG1vZGVsLCBzZWxlY3Rpb24pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHNldENhcmV0UG9zaXRpb24oZWRpdG9yLCBtb2RlbCwgc2VsZWN0aW9uKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNldERvY3VtZW50UmFuZ2VTZWxlY3Rpb24oZWRpdG9yOiBIVE1MRGl2RWxlbWVudCwgbW9kZWw6IEVkaXRvck1vZGVsLCByYW5nZTogUmFuZ2UpOiB2b2lkIHtcbiAgICBjb25zdCBzZWwgPSBkb2N1bWVudC5nZXRTZWxlY3Rpb24oKSE7XG4gICAgc2VsLnJlbW92ZUFsbFJhbmdlcygpO1xuICAgIGNvbnN0IHNlbGVjdGlvblJhbmdlID0gZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTtcbiAgICBjb25zdCBzdGFydCA9IGdldE5vZGVBbmRPZmZzZXRGb3JQb3NpdGlvbihlZGl0b3IsIG1vZGVsLCByYW5nZS5zdGFydCk7XG4gICAgc2VsZWN0aW9uUmFuZ2Uuc2V0U3RhcnQoc3RhcnQubm9kZSwgc3RhcnQub2Zmc2V0KTtcbiAgICBjb25zdCBlbmQgPSBnZXROb2RlQW5kT2Zmc2V0Rm9yUG9zaXRpb24oZWRpdG9yLCBtb2RlbCwgcmFuZ2UuZW5kKTtcbiAgICBzZWxlY3Rpb25SYW5nZS5zZXRFbmQoZW5kLm5vZGUsIGVuZC5vZmZzZXQpO1xuICAgIHNlbC5hZGRSYW5nZShzZWxlY3Rpb25SYW5nZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRDYXJldFBvc2l0aW9uKGVkaXRvcjogSFRNTERpdkVsZW1lbnQsIG1vZGVsOiBFZGl0b3JNb2RlbCwgY2FyZXRQb3NpdGlvbjogSVBvc2l0aW9uKTogdm9pZCB7XG4gICAgaWYgKG1vZGVsLmlzRW1wdHkpIHJldHVybjsgLy8gc2VsZWN0aW9uIGNhbid0IHBvc3NpYmx5IGJlIHdyb25nLCBzbyBhdm9pZCBhIHJlZmxvd1xuXG4gICAgY29uc3QgcmFuZ2UgPSBkb2N1bWVudC5jcmVhdGVSYW5nZSgpO1xuICAgIGNvbnN0IHsgbm9kZSwgb2Zmc2V0IH0gPSBnZXROb2RlQW5kT2Zmc2V0Rm9yUG9zaXRpb24oZWRpdG9yLCBtb2RlbCwgY2FyZXRQb3NpdGlvbik7XG4gICAgcmFuZ2Uuc2V0U3RhcnQobm9kZSwgb2Zmc2V0KTtcbiAgICByYW5nZS5jb2xsYXBzZSh0cnVlKTtcblxuICAgIGNvbnN0IHNlbCA9IGRvY3VtZW50LmdldFNlbGVjdGlvbigpITtcbiAgICBpZiAoc2VsLnJhbmdlQ291bnQgPT09IDEpIHtcbiAgICAgICAgY29uc3QgZXhpc3RpbmdSYW5nZSA9IHNlbC5nZXRSYW5nZUF0KDApO1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICBleGlzdGluZ1JhbmdlLnN0YXJ0Q29udGFpbmVyID09PSByYW5nZS5zdGFydENvbnRhaW5lciAmJlxuICAgICAgICAgICAgZXhpc3RpbmdSYW5nZS5zdGFydE9mZnNldCA9PT0gcmFuZ2Uuc3RhcnRPZmZzZXQgJiZcbiAgICAgICAgICAgIGV4aXN0aW5nUmFuZ2UuY29sbGFwc2VkID09PSByYW5nZS5jb2xsYXBzZWRcbiAgICAgICAgKSB7XG4gICAgICAgICAgICAvLyBJZiB0aGUgc2VsZWN0aW9uIG1hdGNoZXMsIGl0J3MgaW1wb3J0YW50IHRvIGxlYXZlIGl0IGFsb25lLlxuICAgICAgICAgICAgLy8gUmVjcmVhdGluZyB0aGUgc2VsZWN0aW9uIHN0YXRlIGluIGF0IGxlYXN0IENocm9tZSBjYW4gY2F1c2VcbiAgICAgICAgICAgIC8vIHN0cmFuZ2Ugc2lkZSBlZmZlY3RzLCBsaWtlIHRvdWNoIGJhciBmbGlja2VyaW5nIG9uIGV2ZXJ5IGtleS5cbiAgICAgICAgICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vdmVjdG9yLWltL2VsZW1lbnQtd2ViL2lzc3Vlcy85Mjk5XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG4gICAgc2VsLnJlbW92ZUFsbFJhbmdlcygpO1xuICAgIHNlbC5hZGRSYW5nZShyYW5nZSk7XG59XG5cbmZ1bmN0aW9uIGdldE5vZGVBbmRPZmZzZXRGb3JQb3NpdGlvbihcbiAgICBlZGl0b3I6IEhUTUxEaXZFbGVtZW50LFxuICAgIG1vZGVsOiBFZGl0b3JNb2RlbCxcbiAgICBwb3NpdGlvbjogSVBvc2l0aW9uLFxuKToge1xuICAgIG5vZGU6IE5vZGU7XG4gICAgb2Zmc2V0OiBudW1iZXI7XG59IHtcbiAgICBjb25zdCB7IG9mZnNldCwgbGluZUluZGV4LCBub2RlSW5kZXggfSA9IGdldExpbmVBbmROb2RlUG9zaXRpb24obW9kZWwsIHBvc2l0aW9uKTtcbiAgICBjb25zdCBsaW5lTm9kZSA9IGVkaXRvci5jaGlsZE5vZGVzW2xpbmVJbmRleF07XG5cbiAgICBsZXQgZm9jdXNOb2RlO1xuICAgIC8vIGVtcHR5IGxpbmUgd2l0aCBqdXN0IGEgPGJyPlxuICAgIGlmIChub2RlSW5kZXggPT09IC0xKSB7XG4gICAgICAgIGZvY3VzTm9kZSA9IGxpbmVOb2RlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGZvY3VzTm9kZSA9IGxpbmVOb2RlLmNoaWxkTm9kZXNbbm9kZUluZGV4XTtcbiAgICAgICAgLy8gbWFrZSBzdXJlIHdlIGhhdmUgYSB0ZXh0IG5vZGVcbiAgICAgICAgaWYgKGZvY3VzTm9kZS5ub2RlVHlwZSA9PT0gTm9kZS5FTEVNRU5UX05PREUgJiYgZm9jdXNOb2RlLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgICAgIGZvY3VzTm9kZSA9IGZvY3VzTm9kZS5maXJzdENoaWxkO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IG5vZGU6IGZvY3VzTm9kZSwgb2Zmc2V0IH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRMaW5lQW5kTm9kZVBvc2l0aW9uKFxuICAgIG1vZGVsOiBFZGl0b3JNb2RlbCxcbiAgICBjYXJldFBvc2l0aW9uOiBJUG9zaXRpb24sXG4pOiB7XG4gICAgb2Zmc2V0OiBudW1iZXI7XG4gICAgbGluZUluZGV4OiBudW1iZXI7XG4gICAgbm9kZUluZGV4OiBudW1iZXI7XG59IHtcbiAgICBjb25zdCB7IHBhcnRzIH0gPSBtb2RlbDtcbiAgICBjb25zdCBwYXJ0SW5kZXggPSBjYXJldFBvc2l0aW9uLmluZGV4O1xuICAgIGxldCB7IG9mZnNldCB9ID0gY2FyZXRQb3NpdGlvbjtcbiAgICBjb25zdCBsaW5lUmVzdWx0ID0gZmluZE5vZGVJbkxpbmVGb3JQYXJ0KHBhcnRzLCBwYXJ0SW5kZXgsIG9mZnNldCk7XG4gICAgY29uc3QgeyBsaW5lSW5kZXggfSA9IGxpbmVSZXN1bHQ7XG4gICAgbGV0IHsgbm9kZUluZGV4IH0gPSBsaW5lUmVzdWx0O1xuICAgIC8vIHdlJ3JlIGF0IGFuIGVtcHR5IGxpbmUgYmV0d2VlbiBhIG5ld2xpbmUgcGFydFxuICAgIC8vIGFuZCBhbm90aGVyIG5ld2xpbmUgcGFydCBvciBlbmQvc3RhcnQgb2YgcGFydHMuXG4gICAgLy8gc2V0IG9mZnNldCB0byAwIHNvIGl0IGdldHMgc2V0IHRvIHRoZSA8YnI+IGluc2lkZSB0aGUgbGluZSBjb250YWluZXJcbiAgICBpZiAobm9kZUluZGV4ID09PSAtMSkge1xuICAgICAgICBvZmZzZXQgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIG1vdmUgY2FyZXQgb3V0IG9mIHVuZWRpdGFibGUgcGFydCAoaW50byBjYXJldCBub2RlLCBvciBlbXB0eSBsaW5lIGJyKSBpZiBuZWVkZWRcbiAgICAgICAgKHsgbm9kZUluZGV4LCBvZmZzZXQgfSA9IG1vdmVPdXRPZlVuc2VsZWN0YWJsZVBhcnQocGFydHMsIHBhcnRJbmRleCwgbm9kZUluZGV4LCBvZmZzZXQpKTtcbiAgICB9XG4gICAgcmV0dXJuIHsgbGluZUluZGV4LCBub2RlSW5kZXgsIG9mZnNldCB9O1xufVxuXG5mdW5jdGlvbiBmaW5kTm9kZUluTGluZUZvclBhcnQoXG4gICAgcGFydHM6IFBhcnRbXSxcbiAgICBwYXJ0SW5kZXg6IG51bWJlcixcbiAgICBvZmZzZXQ6IG51bWJlcixcbik6IHsgbGluZUluZGV4OiBudW1iZXI7IG5vZGVJbmRleDogbnVtYmVyIH0ge1xuICAgIGxldCBsaW5lSW5kZXggPSAwO1xuICAgIGxldCBub2RlSW5kZXggPSAtMTtcblxuICAgIGxldCBwcmV2UGFydDogUGFydCB8IHVuZGVmaW5lZDtcbiAgICAvLyBnbyB0aHJvdWdoIHRvIHBhcnRzIHVwIHRpbGwgKGFuZCBpbmNsdWRpbmcpIHRoZSBpbmRleFxuICAgIC8vIHRvIGZpbmQgbmV3bGluZSBwYXJ0c1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IHBhcnRJbmRleDsgKytpKSB7XG4gICAgICAgIGNvbnN0IHBhcnQgPSBwYXJ0c1tpXTtcbiAgICAgICAgaWYgKHBhcnQudHlwZSA9PT0gVHlwZS5OZXdsaW5lKSB7XG4gICAgICAgICAgICAvLyBkb24ndCBqdW1wIG92ZXIgdGhlIGxpbmVicmVhayBpZiB0aGUgb2Zmc2V0IGlzIGJlZm9yZSBpdFxuICAgICAgICAgICAgaWYgKGkgPT0gcGFydEluZGV4ICYmIG9mZnNldCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGluZUluZGV4ICs9IDE7XG4gICAgICAgICAgICBub2RlSW5kZXggPSAtMTtcbiAgICAgICAgICAgIHByZXZQYXJ0ID0gdW5kZWZpbmVkO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbm9kZUluZGV4ICs9IDE7XG4gICAgICAgICAgICBpZiAobmVlZHNDYXJldE5vZGVCZWZvcmUocGFydCwgcHJldlBhcnQpKSB7XG4gICAgICAgICAgICAgICAgbm9kZUluZGV4ICs9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBvbmx5IGp1bXAgb3ZlciBjYXJldCBub2RlIGlmIHdlJ3JlIG5vdCBhdCBvdXIgZGVzdGluYXRpb24gbm9kZSBhbHJlYWR5LFxuICAgICAgICAgICAgLy8gYXMgd2UnbGwgYXNzdW1lIGluIG1vdmVPdXRPZlVuc2VsZWN0YWJsZVBhcnQgdGhhdCBub2RlSW5kZXhcbiAgICAgICAgICAgIC8vIHJlZmVycyB0byB0aGUgbm9kZSBjb3JyZXNwb25kaW5nIHRvIHRoZSBwYXJ0LFxuICAgICAgICAgICAgLy8gYW5kIG5vdCBhbiBhZGphY2VudCBjYXJldCBub2RlXG4gICAgICAgICAgICBpZiAoaSA8IHBhcnRJbmRleCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG5leHRQYXJ0ID0gcGFydHNbaSArIDFdO1xuICAgICAgICAgICAgICAgIGNvbnN0IGlzTGFzdE9mTGluZSA9ICFuZXh0UGFydCB8fCBuZXh0UGFydC50eXBlID09PSBUeXBlLk5ld2xpbmU7XG4gICAgICAgICAgICAgICAgaWYgKG5lZWRzQ2FyZXROb2RlQWZ0ZXIocGFydCwgaXNMYXN0T2ZMaW5lKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlSW5kZXggKz0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcmV2UGFydCA9IHBhcnQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyBsaW5lSW5kZXgsIG5vZGVJbmRleCB9O1xufVxuXG5mdW5jdGlvbiBtb3ZlT3V0T2ZVbnNlbGVjdGFibGVQYXJ0KFxuICAgIHBhcnRzOiBQYXJ0W10sXG4gICAgcGFydEluZGV4OiBudW1iZXIsXG4gICAgbm9kZUluZGV4OiBudW1iZXIsXG4gICAgb2Zmc2V0OiBudW1iZXIsXG4pOiB7IG9mZnNldDogbnVtYmVyOyBub2RlSW5kZXg6IG51bWJlciB9IHtcbiAgICAvLyBtb3ZlIGNhcmV0IGJlZm9yZSBvciBhZnRlciB1bnNlbGVjdGFibGUgcGFydFxuICAgIGNvbnN0IHBhcnQgPSBwYXJ0c1twYXJ0SW5kZXhdO1xuICAgIGlmIChwYXJ0ICYmICFwYXJ0LmFjY2VwdHNDYXJldCkge1xuICAgICAgICBpZiAob2Zmc2V0ID09PSAwKSB7XG4gICAgICAgICAgICBub2RlSW5kZXggLT0gMTtcbiAgICAgICAgICAgIGNvbnN0IHByZXZQYXJ0ID0gcGFydHNbcGFydEluZGV4IC0gMV07XG4gICAgICAgICAgICAvLyBpZiB0aGUgcHJldmlvdXMgbm9kZSBpcyBhIGNhcmV0IG5vZGUsIGl0J3MgZW1wdHlcbiAgICAgICAgICAgIC8vIHNvIHRoZSBvZmZzZXQgY2FuIHN0YXkgYXQgMFxuICAgICAgICAgICAgLy8gb25seSB3aGVuIGl0J3Mgbm90LCB3ZSBuZWVkIHRvIHNldCB0aGUgb2Zmc2V0XG4gICAgICAgICAgICAvLyBhdCB0aGUgZW5kIG9mIHRoZSBub2RlXG4gICAgICAgICAgICBpZiAoIW5lZWRzQ2FyZXROb2RlQmVmb3JlKHBhcnQsIHByZXZQYXJ0KSkge1xuICAgICAgICAgICAgICAgIG9mZnNldCA9IHByZXZQYXJ0LnRleHQubGVuZ3RoO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbm9kZUluZGV4ICs9IDE7XG4gICAgICAgICAgICBvZmZzZXQgPSAwO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IG5vZGVJbmRleCwgb2Zmc2V0IH07XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQVFBLElBQUFBLE9BQUEsR0FBQUMsT0FBQTtBQUNBLElBQUFDLE1BQUEsR0FBQUMsc0JBQUEsQ0FBQUYsT0FBQTtBQUdBLElBQUFHLE1BQUEsR0FBQUgsT0FBQTtBQVpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQVVPLFNBQVNJLFlBQVlBLENBQUNDLE1BQXNCLEVBQUVDLEtBQWtCLEVBQUVDLFNBQTRCLEVBQVE7RUFDekcsSUFBSUEsU0FBUyxZQUFZQyxjQUFLLEVBQUU7SUFDNUJDLHlCQUF5QixDQUFDSixNQUFNLEVBQUVDLEtBQUssRUFBRUMsU0FBUyxDQUFDO0VBQ3ZELENBQUMsTUFBTTtJQUNIRyxnQkFBZ0IsQ0FBQ0wsTUFBTSxFQUFFQyxLQUFLLEVBQUVDLFNBQVMsQ0FBQztFQUM5QztBQUNKO0FBRUEsU0FBU0UseUJBQXlCQSxDQUFDSixNQUFzQixFQUFFQyxLQUFrQixFQUFFSyxLQUFZLEVBQVE7RUFDL0YsTUFBTUMsR0FBRyxHQUFHQyxRQUFRLENBQUNDLFlBQVksQ0FBQyxDQUFFO0VBQ3BDRixHQUFHLENBQUNHLGVBQWUsQ0FBQyxDQUFDO0VBQ3JCLE1BQU1DLGNBQWMsR0FBR0gsUUFBUSxDQUFDSSxXQUFXLENBQUMsQ0FBQztFQUM3QyxNQUFNQyxLQUFLLEdBQUdDLDJCQUEyQixDQUFDZCxNQUFNLEVBQUVDLEtBQUssRUFBRUssS0FBSyxDQUFDTyxLQUFL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