UNPKG

matrix-react-sdk

Version:
162 lines (154 loc) 25.4 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.pillifyLinks = pillifyLinks; exports.unmountPills = unmountPills; var _react = _interopRequireDefault(require("react")); var _reactDom = _interopRequireDefault(require("react-dom")); var _pushprocessor = require("matrix-js-sdk/src/pushprocessor"); var _matrix = require("matrix-js-sdk/src/matrix"); var _compoundWeb = require("@vector-im/compound-web"); var _SettingsStore = _interopRequireDefault(require("../settings/SettingsStore")); var _Pill = require("../components/views/elements/Pill"); var _Permalinks = require("./permalinks/Permalinks"); /* Copyright 2024 New Vector Ltd. Copyright 2019-2023 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. */ /** * A node here is an A element with a href attribute tag. * * It should be pillified if the permalink parser returns a result and one of the following conditions match: * - Text content equals href. This is the case when sending a plain permalink inside a message. * - The link does not have the "linkified" class. * Composer completions already create an A tag. * Linkify will not linkify things again. → There won't be a "linkified" class. */ const shouldBePillified = (node, href, parts) => { // permalink parser didn't return any parts if (!parts) return false; const textContent = node.textContent; // event permalink with custom label if (parts.eventId && href !== textContent) return false; return href === textContent || !node.classList.contains("linkified"); }; /** * Recurses depth-first through a DOM tree, converting matrix.to links * into pills based on the context of a given room. Returns a list of * the resulting React nodes so they can be unmounted rather than leaking. * * @param matrixClient the client of the logged-in user * @param {Element[]} nodes - a list of sibling DOM nodes to traverse to try * to turn into pills. * @param {MatrixEvent} mxEvent - the matrix event which the DOM nodes are * part of representing. * @param {Element[]} pills: an accumulator of the DOM nodes which contain * React components which have been mounted as part of this. * The initial caller should pass in an empty array to seed the accumulator. */ function pillifyLinks(matrixClient, nodes, mxEvent, pills) { const room = matrixClient.getRoom(mxEvent.getRoomId()) ?? undefined; const shouldShowPillAvatar = _SettingsStore.default.getValue("Pill.shouldShowPillAvatar"); let node = nodes[0]; while (node) { let pillified = false; if (node.tagName === "PRE" || node.tagName === "CODE" || pills.includes(node)) { // Skip code blocks and existing pills node = node.nextSibling; continue; } else if (node.tagName === "A" && node.getAttribute("href")) { const href = node.getAttribute("href"); const parts = (0, _Permalinks.parsePermalink)(href); if (shouldBePillified(node, href, parts)) { const pillContainer = document.createElement("span"); const pill = /*#__PURE__*/_react.default.createElement(_compoundWeb.TooltipProvider, null, /*#__PURE__*/_react.default.createElement(_Pill.Pill, { url: href, inMessage: true, room: room, shouldShowPillAvatar: shouldShowPillAvatar })); _reactDom.default.render(pill, pillContainer); node.parentNode?.replaceChild(pillContainer, node); pills.push(pillContainer); // Pills within pills aren't going to go well, so move on pillified = true; // update the current node with one that's now taken its place node = pillContainer; } } else if (node.nodeType === Node.TEXT_NODE && // as applying pills happens outside of react, make sure we're not doubly // applying @room pills here, as a rerender with the same content won't touch the DOM // to clear the pills from the last run of pillifyLinks !node.parentElement?.classList.contains("mx_AtRoomPill")) { let currentTextNode = node; const roomNotifTextNodes = []; // Take a textNode and break it up to make all the instances of @room their // own textNode, adding those nodes to roomNotifTextNodes while (currentTextNode !== null) { const roomNotifPos = (0, _Pill.pillRoomNotifPos)(currentTextNode.textContent); let nextTextNode = null; if (roomNotifPos > -1) { let roomTextNode = currentTextNode; if (roomNotifPos > 0) roomTextNode = roomTextNode.splitText(roomNotifPos); if (roomTextNode.textContent && roomTextNode.textContent.length > (0, _Pill.pillRoomNotifLen)()) { nextTextNode = roomTextNode.splitText((0, _Pill.pillRoomNotifLen)()); } roomNotifTextNodes.push(roomTextNode); } currentTextNode = nextTextNode; } if (roomNotifTextNodes.length > 0) { const pushProcessor = new _pushprocessor.PushProcessor(matrixClient); const atRoomRule = pushProcessor.getPushRuleById(mxEvent.getContent()["m.mentions"] !== undefined ? _matrix.RuleId.IsRoomMention : _matrix.RuleId.AtRoomNotification); if (atRoomRule && pushProcessor.ruleMatchesEvent(atRoomRule, mxEvent)) { // Now replace all those nodes with Pills for (const roomNotifTextNode of roomNotifTextNodes) { // Set the next node to be processed to the one after the node // we're adding now, since we've just inserted nodes into the structure // we're iterating over. // Note we've checked roomNotifTextNodes.length > 0 so we'll do this at least once node = roomNotifTextNode.nextSibling; const pillContainer = document.createElement("span"); const pill = /*#__PURE__*/_react.default.createElement(_compoundWeb.TooltipProvider, null, /*#__PURE__*/_react.default.createElement(_Pill.Pill, { type: _Pill.PillType.AtRoomMention, inMessage: true, room: room, shouldShowPillAvatar: shouldShowPillAvatar })); _reactDom.default.render(pill, pillContainer); roomNotifTextNode.parentNode?.replaceChild(pillContainer, roomNotifTextNode); pills.push(pillContainer); } // Nothing else to do for a text node (and we don't need to advance // the loop pointer because we did it above) continue; } } } if (node.childNodes && node.childNodes.length && !pillified) { pillifyLinks(matrixClient, node.childNodes, mxEvent, pills); } node = node.nextSibling; } } /** * Unmount all the pill containers from React created by pillifyLinks. * * It's critical to call this after pillifyLinks, otherwise * Pills will leak, leaking entire DOM trees via the event * emitter on BaseAvatar as per * https://github.com/vector-im/element-web/issues/12417 * * @param {Element[]} pills - array of pill containers whose React * components should be unmounted. */ function unmountPills(pills) { for (const pillContainer of pills) { _reactDom.default.unmountComponentAtNode(pillContainer); } } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9yZWFjdERvbSIsIl9wdXNocHJvY2Vzc29yIiwiX21hdHJpeCIsIl9jb21wb3VuZFdlYiIsIl9TZXR0aW5nc1N0b3JlIiwiX1BpbGwiLCJfUGVybWFsaW5rcyIsInNob3VsZEJlUGlsbGlmaWVkIiwibm9kZSIsImhyZWYiLCJwYXJ0cyIsInRleHRDb250ZW50IiwiZXZlbnRJZCIsImNsYXNzTGlzdCIsImNvbnRhaW5zIiwicGlsbGlmeUxpbmtzIiwibWF0cml4Q2xpZW50Iiwibm9kZXMiLCJteEV2ZW50IiwicGlsbHMiLCJyb29tIiwiZ2V0Um9vbSIsImdldFJvb21JZCIsInVuZGVmaW5lZCIsInNob3VsZFNob3dQaWxsQXZhdGFyIiwiU2V0dGluZ3NTdG9yZSIsImdldFZhbHVlIiwicGlsbGlmaWVkIiwidGFnTmFtZSIsImluY2x1ZGVzIiwibmV4dFNpYmxpbmciLCJnZXRBdHRyaWJ1dGUiLCJwYXJzZVBlcm1hbGluayIsInBpbGxDb250YWluZXIiLCJkb2N1bWVudCIsImNyZWF0ZUVsZW1lbnQiLCJwaWxsIiwiZGVmYXVsdCIsIlRvb2x0aXBQcm92aWRlciIsIlBpbGwiLCJ1cmwiLCJpbk1lc3NhZ2UiLCJSZWFjdERPTSIsInJlbmRlciIsInBhcmVudE5vZGUiLCJyZXBsYWNlQ2hpbGQiLCJwdXNoIiwibm9kZVR5cGUiLCJOb2RlIiwiVEVYVF9OT0RFIiwicGFyZW50RWxlbWVudCIsImN1cnJlbnRUZXh0Tm9kZSIsInJvb21Ob3RpZlRleHROb2RlcyIsInJvb21Ob3RpZlBvcyIsInBpbGxSb29tTm90aWZQb3MiLCJuZXh0VGV4dE5vZGUiLCJyb29tVGV4dE5vZGUiLCJzcGxpdFRleHQiLCJsZW5ndGgiLCJwaWxsUm9vbU5vdGlmTGVuIiwicHVzaFByb2Nlc3NvciIsIlB1c2hQcm9jZXNzb3IiLCJhdFJvb21SdWxlIiwiZ2V0UHVzaFJ1bGVCeUlkIiwiZ2V0Q29udGVudCIsIlJ1bGVJZCIsIklzUm9vbU1lbnRpb24iLCJBdFJvb21Ob3RpZmljYXRpb24iLCJydWxlTWF0Y2hlc0V2ZW50Iiwicm9vbU5vdGlmVGV4dE5vZGUiLCJ0eXBlIiwiUGlsbFR5cGUiLCJBdFJvb21NZW50aW9uIiwiY2hpbGROb2RlcyIsInVubW91bnRQaWxscyIsInVubW91bnRDb21wb25lbnRBdE5vZGUiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvcGlsbGlmeS50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMTktMjAyMyBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgUmVhY3QgZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgUmVhY3RET00gZnJvbSBcInJlYWN0LWRvbVwiO1xuaW1wb3J0IHsgUHVzaFByb2Nlc3NvciB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9wdXNocHJvY2Vzc29yXCI7XG5pbXBvcnQgeyBNYXRyaXhDbGllbnQsIE1hdHJpeEV2ZW50LCBSdWxlSWQgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgeyBUb29sdGlwUHJvdmlkZXIgfSBmcm9tIFwiQHZlY3Rvci1pbS9jb21wb3VuZC13ZWJcIjtcblxuaW1wb3J0IFNldHRpbmdzU3RvcmUgZnJvbSBcIi4uL3NldHRpbmdzL1NldHRpbmdzU3RvcmVcIjtcbmltcG9ydCB7IFBpbGwsIHBpbGxSb29tTm90aWZMZW4sIHBpbGxSb29tTm90aWZQb3MsIFBpbGxUeXBlIH0gZnJvbSBcIi4uL2NvbXBvbmVudHMvdmlld3MvZWxlbWVudHMvUGlsbFwiO1xuaW1wb3J0IHsgcGFyc2VQZXJtYWxpbmsgfSBmcm9tIFwiLi9wZXJtYWxpbmtzL1Blcm1hbGlua3NcIjtcbmltcG9ydCB7IFBlcm1hbGlua1BhcnRzIH0gZnJvbSBcIi4vcGVybWFsaW5rcy9QZXJtYWxpbmtDb25zdHJ1Y3RvclwiO1xuXG4vKipcbiAqIEEgbm9kZSBoZXJlIGlzIGFuIEEgZWxlbWVudCB3aXRoIGEgaHJlZiBhdHRyaWJ1dGUgdGFnLlxuICpcbiAqIEl0IHNob3VsZCBiZSBwaWxsaWZpZWQgaWYgdGhlIHBlcm1hbGluayBwYXJzZXIgcmV0dXJucyBhIHJlc3VsdCBhbmQgb25lIG9mIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBtYXRjaDpcbiAqIC0gVGV4dCBjb250ZW50IGVxdWFscyBocmVmLiBUaGlzIGlzIHRoZSBjYXNlIHdoZW4gc2VuZGluZyBhIHBsYWluIHBlcm1hbGluayBpbnNpZGUgYSBtZXNzYWdlLlxuICogLSBUaGUgbGluayBkb2VzIG5vdCBoYXZlIHRoZSBcImxpbmtpZmllZFwiIGNsYXNzLlxuICogICBDb21wb3NlciBjb21wbGV0aW9ucyBhbHJlYWR5IGNyZWF0ZSBhbiBBIHRhZy5cbiAqICAgTGlua2lmeSB3aWxsIG5vdCBsaW5raWZ5IHRoaW5ncyBhZ2Fpbi4g4oaSIFRoZXJlIHdvbid0IGJlIGEgXCJsaW5raWZpZWRcIiBjbGFzcy5cbiAqL1xuY29uc3Qgc2hvdWxkQmVQaWxsaWZpZWQgPSAobm9kZTogRWxlbWVudCwgaHJlZjogc3RyaW5nLCBwYXJ0czogUGVybWFsaW5rUGFydHMgfCBudWxsKTogYm9vbGVhbiA9PiB7XG4gICAgLy8gcGVybWFsaW5rIHBhcnNlciBkaWRuJ3QgcmV0dXJuIGFueSBwYXJ0c1xuICAgIGlmICghcGFydHMpIHJldHVybiBmYWxzZTtcblxuICAgIGNvbnN0IHRleHRDb250ZW50ID0gbm9kZS50ZXh0Q29udGVudDtcblxuICAgIC8vIGV2ZW50IHBlcm1hbGluayB3aXRoIGN1c3RvbSBsYWJlbFxuICAgIGlmIChwYXJ0cy5ldmVudElkICYmIGhyZWYgIT09IHRleHRDb250ZW50KSByZXR1cm4gZmFsc2U7XG5cbiAgICByZXR1cm4gaHJlZiA9PT0gdGV4dENvbnRlbnQgfHwgIW5vZGUuY2xhc3NMaXN0LmNvbnRhaW5zKFwibGlua2lmaWVkXCIpO1xufTtcblxuLyoqXG4gKiBSZWN1cnNlcyBkZXB0aC1maXJzdCB0aHJvdWdoIGEgRE9NIHRyZWUsIGNvbnZlcnRpbmcgbWF0cml4LnRvIGxpbmtzXG4gKiBpbnRvIHBpbGxzIGJhc2VkIG9uIHRoZSBjb250ZXh0IG9mIGEgZ2l2ZW4gcm9vbS4gIFJldHVybnMgYSBsaXN0IG9mXG4gKiB0aGUgcmVzdWx0aW5nIFJlYWN0IG5vZGVzIHNvIHRoZXkgY2FuIGJlIHVubW91bnRlZCByYXRoZXIgdGhhbiBsZWFraW5nLlxuICpcbiAqIEBwYXJhbSBtYXRyaXhDbGllbnQgdGhlIGNsaWVudCBvZiB0aGUgbG9nZ2VkLWluIHVzZXJcbiAqIEBwYXJhbSB7RWxlbWVudFtdfSBub2RlcyAtIGEgbGlzdCBvZiBzaWJsaW5nIERPTSBub2RlcyB0byB0cmF2ZXJzZSB0byB0cnlcbiAqICAgdG8gdHVybiBpbnRvIHBpbGxzLlxuICogQHBhcmFtIHtNYXRyaXhFdmVudH0gbXhFdmVudCAtIHRoZSBtYXRyaXggZXZlbnQgd2hpY2ggdGhlIERPTSBub2RlcyBhcmVcbiAqICAgcGFydCBvZiByZXByZXNlbnRpbmcuXG4gKiBAcGFyYW0ge0VsZW1lbnRbXX0gcGlsbHM6IGFuIGFjY3VtdWxhdG9yIG9mIHRoZSBET00gbm9kZXMgd2hpY2ggY29udGFpblxuICogICBSZWFjdCBjb21wb25lbnRzIHdoaWNoIGhhdmUgYmVlbiBtb3VudGVkIGFzIHBhcnQgb2YgdGhpcy5cbiAqICAgVGhlIGluaXRpYWwgY2FsbGVyIHNob3VsZCBwYXNzIGluIGFuIGVtcHR5IGFycmF5IHRvIHNlZWQgdGhlIGFjY3VtdWxhdG9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGlsbGlmeUxpbmtzKFxuICAgIG1hdHJpeENsaWVudDogTWF0cml4Q2xpZW50LFxuICAgIG5vZGVzOiBBcnJheUxpa2U8RWxlbWVudD4sXG4gICAgbXhFdmVudDogTWF0cml4RXZlbnQsXG4gICAgcGlsbHM6IEVsZW1lbnRbXSxcbik6IHZvaWQge1xuICAgIGNvbnN0IHJvb20gPSBtYXRyaXhDbGllbnQuZ2V0Um9vbShteEV2ZW50LmdldFJvb21JZCgpKSA/PyB1bmRlZmluZWQ7XG4gICAgY29uc3Qgc2hvdWxkU2hvd1BpbGxBdmF0YXIgPSBTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwiUGlsbC5zaG91bGRTaG93UGlsbEF2YXRhclwiKTtcbiAgICBsZXQgbm9kZSA9IG5vZGVzWzBdO1xuICAgIHdoaWxlIChub2RlKSB7XG4gICAgICAgIGxldCBwaWxsaWZpZWQgPSBmYWxzZTtcblxuICAgICAgICBpZiAobm9kZS50YWdOYW1lID09PSBcIlBSRVwiIHx8IG5vZGUudGFnTmFtZSA9PT0gXCJDT0RFXCIgfHwgcGlsbHMuaW5jbHVkZXMobm9kZSkpIHtcbiAgICAgICAgICAgIC8vIFNraXAgY29kZSBibG9ja3MgYW5kIGV4aXN0aW5nIHBpbGxzXG4gICAgICAgICAgICBub2RlID0gbm9kZS5uZXh0U2libGluZyBhcyBFbGVtZW50O1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH0gZWxzZSBpZiAobm9kZS50YWdOYW1lID09PSBcIkFcIiAmJiBub2RlLmdldEF0dHJpYnV0ZShcImhyZWZcIikpIHtcbiAgICAgICAgICAgIGNvbnN0IGhyZWYgPSBub2RlLmdldEF0dHJpYnV0ZShcImhyZWZcIikhO1xuICAgICAgICAgICAgY29uc3QgcGFydHMgPSBwYXJzZVBlcm1hbGluayhocmVmKTtcblxuICAgICAgICAgICAgaWYgKHNob3VsZEJlUGlsbGlmaWVkKG5vZGUsIGhyZWYsIHBhcnRzKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBpbGxDb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3BhblwiKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHBpbGwgPSAoXG4gICAgICAgICAgICAgICAgICAgIDxUb29sdGlwUHJvdmlkZXI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8UGlsbCB1cmw9e2hyZWZ9IGluTWVzc2FnZT17dHJ1ZX0gcm9vbT17cm9vbX0gc2hvdWxkU2hvd1BpbGxBdmF0YXI9e3Nob3VsZFNob3dQaWxsQXZhdGFyfSAvPlxuICAgICAgICAgICAgICAgICAgICA8L1Rvb2x0aXBQcm92aWRlcj5cbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgUmVhY3RET00ucmVuZGVyKHBpbGwsIHBpbGxDb250YWluZXIpO1xuICAgICAgICAgICAgICAgIG5vZGUucGFyZW50Tm9kZT8ucmVwbGFjZUNoaWxkKHBpbGxDb250YWluZXIsIG5vZGUpO1xuICAgICAgICAgICAgICAgIHBpbGxzLnB1c2gocGlsbENvbnRhaW5lcik7XG4gICAgICAgICAgICAgICAgLy8gUGlsbHMgd2l0aGluIHBpbGxzIGFyZW4ndCBnb2luZyB0byBnbyB3ZWxsLCBzbyBtb3ZlIG9uXG4gICAgICAgICAgICAgICAgcGlsbGlmaWVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgY3VycmVudCBub2RlIHdpdGggb25lIHRoYXQncyBub3cgdGFrZW4gaXRzIHBsYWNlXG4gICAgICAgICAgICAgICAgbm9kZSA9IHBpbGxDb250YWluZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICBub2RlLm5vZGVUeXBlID09PSBOb2RlLlRFWFRfTk9ERSAmJlxuICAgICAgICAgICAgLy8gYXMgYXBwbHlpbmcgcGlsbHMgaGFwcGVucyBvdXRzaWRlIG9mIHJlYWN0LCBtYWtlIHN1cmUgd2UncmUgbm90IGRvdWJseVxuICAgICAgICAgICAgLy8gYXBwbHlpbmcgQHJvb20gcGlsbHMgaGVyZSwgYXMgYSByZXJlbmRlciB3aXRoIHRoZSBzYW1lIGNvbnRlbnQgd29uJ3QgdG91Y2ggdGhlIERPTVxuICAgICAgICAgICAgLy8gdG8gY2xlYXIgdGhlIHBpbGxzIGZyb20gdGhlIGxhc3QgcnVuIG9mIHBpbGxpZnlMaW5rc1xuICAgICAgICAgICAgIW5vZGUucGFyZW50RWxlbWVudD8uY2xhc3NMaXN0LmNvbnRhaW5zKFwibXhfQXRSb29tUGlsbFwiKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIGxldCBjdXJyZW50VGV4dE5vZGUgPSBub2RlIGFzIE5vZGUgYXMgVGV4dCB8IG51bGw7XG4gICAgICAgICAgICBjb25zdCByb29tTm90aWZUZXh0Tm9kZXM6IFRleHRbXSA9IFtdO1xuXG4gICAgICAgICAgICAvLyBUYWtlIGEgdGV4dE5vZGUgYW5kIGJyZWFrIGl0IHVwIHRvIG1ha2UgYWxsIHRoZSBpbnN0YW5jZXMgb2YgQHJvb20gdGhlaXJcbiAgICAgICAgICAgIC8vIG93biB0ZXh0Tm9kZSwgYWRkaW5nIHRob3NlIG5vZGVzIHRvIHJvb21Ob3RpZlRleHROb2Rlc1xuICAgICAgICAgICAgd2hpbGUgKGN1cnJlbnRUZXh0Tm9kZSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJvb21Ob3RpZlBvcyA9IHBpbGxSb29tTm90aWZQb3MoY3VycmVudFRleHROb2RlLnRleHRDb250ZW50KTtcbiAgICAgICAgICAgICAgICBsZXQgbmV4dFRleHROb2RlOiBUZXh0IHwgbnVsbCA9IG51bGw7XG4gICAgICAgICAgICAgICAgaWYgKHJvb21Ob3RpZlBvcyA+IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCByb29tVGV4dE5vZGUgPSBjdXJyZW50VGV4dE5vZGU7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHJvb21Ob3RpZlBvcyA+IDApIHJvb21UZXh0Tm9kZSA9IHJvb21UZXh0Tm9kZS5zcGxpdFRleHQocm9vbU5vdGlmUG9zKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJvb21UZXh0Tm9kZS50ZXh0Q29udGVudCAmJiByb29tVGV4dE5vZGUudGV4dENvbnRlbnQubGVuZ3RoID4gcGlsbFJvb21Ob3RpZkxlbigpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXh0VGV4dE5vZGUgPSByb29tVGV4dE5vZGUuc3BsaXRUZXh0KHBpbGxSb29tTm90aWZMZW4oKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcm9vbU5vdGlmVGV4dE5vZGVzLnB1c2gocm9vbVRleHROb2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY3VycmVudFRleHROb2RlID0gbmV4dFRleHROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocm9vbU5vdGlmVGV4dE5vZGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwdXNoUHJvY2Vzc29yID0gbmV3IFB1c2hQcm9jZXNzb3IobWF0cml4Q2xpZW50KTtcbiAgICAgICAgICAgICAgICBjb25zdCBhdFJvb21SdWxlID0gcHVzaFByb2Nlc3Nvci5nZXRQdXNoUnVsZUJ5SWQoXG4gICAgICAgICAgICAgICAgICAgIG14RXZlbnQuZ2V0Q29udGVudCgpW1wibS5tZW50aW9uc1wiXSAhPT0gdW5kZWZpbmVkID8gUnVsZUlkLklzUm9vbU1lbnRpb24gOiBSdWxlSWQuQXRSb29tTm90aWZpY2F0aW9uLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgaWYgKGF0Um9vbVJ1bGUgJiYgcHVzaFByb2Nlc3Nvci5ydWxlTWF0Y2hlc0V2ZW50KGF0Um9vbVJ1bGUsIG14RXZlbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE5vdyByZXBsYWNlIGFsbCB0aG9zZSBub2RlcyB3aXRoIFBpbGxzXG4gICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgcm9vbU5vdGlmVGV4dE5vZGUgb2Ygcm9vbU5vdGlmVGV4dE5vZGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTZXQgdGhlIG5leHQgbm9kZSB0byBiZSBwcm9jZXNzZWQgdG8gdGhlIG9uZSBhZnRlciB0aGUgbm9kZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2UncmUgYWRkaW5nIG5vdywgc2luY2Ugd2UndmUganVzdCBpbnNlcnRlZCBub2RlcyBpbnRvIHRoZSBzdHJ1Y3R1cmVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdlJ3JlIGl0ZXJhdGluZyBvdmVyLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm90ZSB3ZSd2ZSBjaGVja2VkIHJvb21Ob3RpZlRleHROb2Rlcy5sZW5ndGggPiAwIHNvIHdlJ2xsIGRvIHRoaXMgYXQgbGVhc3Qgb25jZVxuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZSA9IHJvb21Ob3RpZlRleHROb2RlLm5leHRTaWJsaW5nIGFzIEVsZW1lbnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBpbGxDb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3BhblwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBpbGwgPSAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPFRvb2x0aXBQcm92aWRlcj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPFBpbGxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9e1BpbGxUeXBlLkF0Um9vbU1lbnRpb259XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbk1lc3NhZ2U9e3RydWV9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb29tPXtyb29tfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvdWxkU2hvd1BpbGxBdmF0YXI9e3Nob3VsZFNob3dQaWxsQXZhdGFyfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvVG9vbHRpcFByb3ZpZGVyPlxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgUmVhY3RET00ucmVuZGVyKHBpbGwsIHBpbGxDb250YWluZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vbU5vdGlmVGV4dE5vZGUucGFyZW50Tm9kZT8ucmVwbGFjZUNoaWxkKHBpbGxDb250YWluZXIsIHJvb21Ob3RpZlRleHROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBpbGxzLnB1c2gocGlsbENvbnRhaW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gTm90aGluZyBlbHNlIHRvIGRvIGZvciBhIHRleHQgbm9kZSAoYW5kIHdlIGRvbid0IG5lZWQgdG8gYWR2YW5jZVxuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgbG9vcCBwb2ludGVyIGJlY2F1c2Ugd2UgZGlkIGl0IGFib3ZlKVxuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobm9kZS5jaGlsZE5vZGVzICYmIG5vZGUuY2hpbGROb2Rlcy5sZW5ndGggJiYgIXBpbGxpZmllZCkge1xuICAgICAgICAgICAgcGlsbGlmeUxpbmtzKG1hdHJpeENsaWVudCwgbm9kZS5jaGlsZE5vZGVzIGFzIE5vZGVMaXN0T2Y8RWxlbWVudD4sIG14RXZlbnQsIHBpbGxzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5vZGUgPSBub2RlLm5leHRTaWJsaW5nIGFzIEVsZW1lbnQ7XG4gICAgfVxufVxuXG4vKipcbiAqIFVubW91bnQgYWxsIHRoZSBwaWxsIGNvbnRhaW5lcnMgZnJvbSBSZWFjdCBjcmVhdGVkIGJ5IHBpbGxpZnlMaW5rcy5cbiAqXG4gKiBJdCdzIGNyaXRpY2FsIHRvIGNhbGwgdGhpcyBhZnRlciBwaWxsaWZ5TGlua3MsIG90aGVyd2lzZVxuICogUGlsbHMgd2lsbCBsZWFrLCBsZWFraW5nIGVudGlyZSBET00gdHJlZXMgdmlhIHRoZSBldmVudFxuICogZW1pdHRlciBvbiBCYXNlQXZhdGFyIGFzIHBlclxuICogaHR0cHM6Ly9naXRodWIuY29tL3ZlY3Rvci1pbS9lbGVtZW50LXdlYi9pc3N1ZXMvMTI0MTdcbiAqXG4gKiBAcGFyYW0ge0VsZW1lbnRbXX0gcGlsbHMgLSBhcnJheSBvZiBwaWxsIGNvbnRhaW5lcnMgd2hvc2UgUmVhY3RcbiAqICAgY29tcG9uZW50cyBzaG91bGQgYmUgdW5tb3VudGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdW5tb3VudFBpbGxzKHBpbGxzOiBFbGVtZW50W10pOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IHBpbGxDb250YWluZXIgb2YgcGlsbHMpIHtcbiAgICAgICAgUmVhY3RET00udW5tb3VudENvbXBvbmVudEF0Tm9kZShwaWxsQ29udGFpbmVyKTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBUUEsSUFBQUEsTUFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsU0FBQSxHQUFBRixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUUsY0FBQSxHQUFBRixPQUFBO0FBQ0EsSUFBQUcsT0FBQSxHQUFBSCxPQUFBO0FBQ0EsSUFBQUksWUFBQSxHQUFBSixPQUFBO0FBRUEsSUFBQUssY0FBQSxHQUFBTixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQU0sS0FBQSxHQUFBTixPQUFBO0FBQ0EsSUFBQU8sV0FBQSxHQUFBUCxPQUFBO0FBaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQWFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU1RLGlCQUFpQixHQUFHQSxDQUFDQyxJQUFhLEVBQUVDLElBQVksRUFBRUMsS0FBNEIsS0FBYztFQUM5RjtFQUNBLElBQUksQ0FBQ0EsS0FBSyxFQUFFLE9BQU8sS0FBSztFQUV4QixNQUFNQyxXQUFXLEdBQUdILElB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