UNPKG

matrix-react-sdk

Version:
322 lines (309 loc) 45.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.formatRange = formatRange; exports.formatRangeAsCode = formatRangeAsCode; exports.formatRangeAsLink = formatRangeAsLink; exports.formatRangeAsQuote = formatRangeAsQuote; exports.rangeEndsAtEndOfLine = rangeEndsAtEndOfLine; exports.rangeStartsAtBeginningOfLine = rangeStartsAtBeginningOfLine; exports.replaceRangeAndAutoAdjustCaret = replaceRangeAndAutoAdjustCaret; exports.replaceRangeAndExpandSelection = replaceRangeAndExpandSelection; exports.replaceRangeAndMoveCaret = replaceRangeAndMoveCaret; exports.selectRangeOfWordAtCaret = selectRangeOfWordAtCaret; exports.toggleInlineFormat = toggleInlineFormat; var _parts = require("./parts"); var _MessageComposerFormatBar = require("../components/views/rooms/MessageComposerFormatBar"); var _deserialize = require("./deserialize"); /* Copyright 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. */ /** * Some common queries and transformations on the editor model */ /** * Formats a given range with a given action * @param {Range} range the range that should be formatted * @param {Formatting} action the action that should be performed on the range */ function formatRange(range, action) { // If the selection was empty we select the current word instead if (range.wasInitializedEmpty()) { selectRangeOfWordAtCaret(range); } else { // Remove whitespace or new lines in our selection range.trim(); } // Edge case when just selecting whitespace or new line. // There should be no reason to format whitespace, so we can just return. if (range.length === 0) { return; } switch (action) { case _MessageComposerFormatBar.Formatting.Bold: toggleInlineFormat(range, "**"); break; case _MessageComposerFormatBar.Formatting.Italics: toggleInlineFormat(range, "*"); break; case _MessageComposerFormatBar.Formatting.Strikethrough: toggleInlineFormat(range, "<del>", "</del>"); break; case _MessageComposerFormatBar.Formatting.Code: formatRangeAsCode(range); break; case _MessageComposerFormatBar.Formatting.Quote: formatRangeAsQuote(range); break; case _MessageComposerFormatBar.Formatting.InsertLink: formatRangeAsLink(range); break; } } function replaceRangeAndExpandSelection(range, newParts) { const { model } = range; model.transform(() => { const oldLen = range.length; const addedLen = range.replace(newParts); const firstOffset = range.start.asOffset(model); const lastOffset = firstOffset.add(oldLen + addedLen); return model.startRange(firstOffset.asPosition(model), lastOffset.asPosition(model)); }); } function replaceRangeAndMoveCaret(range, newParts, offset = 0, atNodeEnd = false) { const { model } = range; model.transform(() => { const oldLen = range.length; const addedLen = range.replace(newParts); const firstOffset = range.start.asOffset(model); const lastOffset = firstOffset.add(oldLen + addedLen + offset, atNodeEnd); return lastOffset.asPosition(model); }); } /** * Replaces a range with formatting or removes existing formatting and * positions the cursor with respect to the prefix and suffix length. * @param {Range} range the previous value * @param {Part[]} newParts the new value * @param {boolean} rangeHasFormatting the new value * @param {number} prefixLength the length of the formatting prefix * @param {number} suffixLength the length of the formatting suffix, defaults to prefix length */ function replaceRangeAndAutoAdjustCaret(range, newParts, rangeHasFormatting = false, prefixLength, suffixLength = prefixLength) { const { model } = range; const lastStartingPosition = range.getLastStartingPosition(); const relativeOffset = lastStartingPosition.offset - range.start.offset; const distanceFromEnd = range.length - relativeOffset; // Handle edge case where the caret is located within the suffix or prefix if (rangeHasFormatting) { if (relativeOffset < prefixLength) { // Was the caret at the left format string? replaceRangeAndMoveCaret(range, newParts, -(range.length - 2 * suffixLength)); return; } if (distanceFromEnd < suffixLength) { // Was the caret at the right format string? replaceRangeAndMoveCaret(range, newParts, 0, true); return; } } // Calculate new position with respect to the previous position model.transform(() => { const offsetDirection = Math.sign(range.replace(newParts)); // Compensates for shrinkage or expansion const atEnd = distanceFromEnd === suffixLength; return lastStartingPosition.asOffset(model).add(offsetDirection * prefixLength, atEnd).asPosition(model); }); } const isFormattable = (_index, offset, part) => { return part.text[offset] !== " " && part.type === _parts.Type.Plain; }; function selectRangeOfWordAtCaret(range) { // Select right side of word range.expandForwardsWhile(isFormattable); // Select left side of word range.expandBackwardsWhile(isFormattable); // Trim possibly selected new lines range.trim(); } function rangeStartsAtBeginningOfLine(range) { const { model } = range; const startsWithPartial = range.start.offset !== 0; const isFirstPart = range.start.index === 0; const previousIsNewline = !isFirstPart && model.parts[range.start.index - 1].type === _parts.Type.Newline; return !startsWithPartial && (isFirstPart || previousIsNewline); } function rangeEndsAtEndOfLine(range) { const { model } = range; const lastPart = model.parts[range.end.index]; const endsWithPartial = range.end.offset !== lastPart.text.length; const isLastPart = range.end.index === model.parts.length - 1; const nextIsNewline = !isLastPart && model.parts[range.end.index + 1].type === _parts.Type.Newline; return !endsWithPartial && (isLastPart || nextIsNewline); } function formatRangeAsQuote(range) { const { model, parts } = range; const { partCreator } = model; for (let i = 0; i < parts.length; ++i) { const part = parts[i]; if (part.type === _parts.Type.Newline) { parts.splice(i + 1, 0, partCreator.plain("> ")); } } parts.unshift(partCreator.plain("> ")); if (!rangeStartsAtBeginningOfLine(range)) { parts.unshift(partCreator.newline()); } if (!rangeEndsAtEndOfLine(range)) { parts.push(partCreator.newline()); } parts.push(partCreator.newline()); replaceRangeAndExpandSelection(range, parts); } function formatRangeAsCode(range) { const { model, parts } = range; const { partCreator } = model; const hasBlockFormatting = range.length > 0 && range.text.startsWith("```") && range.text.endsWith("```") && range.text.includes("\n"); const needsBlockFormatting = parts.some(p => p.type === _parts.Type.Newline); if (hasBlockFormatting) { parts.shift(); parts.pop(); if (parts[0]?.text === "\n" && parts[parts.length - 1]?.text === "\n") { parts.shift(); parts.pop(); } } else if (needsBlockFormatting) { parts.unshift(partCreator.plain("```"), partCreator.newline()); if (!rangeStartsAtBeginningOfLine(range)) { parts.unshift(partCreator.newline()); } parts.push(partCreator.newline(), partCreator.plain("```")); if (!rangeEndsAtEndOfLine(range)) { parts.push(partCreator.newline()); } } else { const fenceLen = (0, _deserialize.longestBacktickSequence)(range.text); const hasInlineFormatting = range.text.startsWith("`") && range.text.endsWith("`"); //if it's already formatted untoggle based on fenceLen which returns the max. num of backtick within a text else increase the fence backticks with a factor of 1. toggleInlineFormat(range, "`".repeat(hasInlineFormatting ? fenceLen : fenceLen + 1)); return; } replaceRangeAndExpandSelection(range, parts); } function formatRangeAsLink(range, text) { const { model } = range; const { partCreator } = model; const linkRegex = /\[(.*?)]\(.*?\)/g; const isFormattedAsLink = linkRegex.test(range.text); if (isFormattedAsLink) { const linkDescription = range.text.replace(linkRegex, "$1"); const newParts = [partCreator.plain(linkDescription)]; replaceRangeAndMoveCaret(range, newParts, 0); } else { // We set offset to -1 here so that the caret lands between the brackets replaceRangeAndMoveCaret(range, [partCreator.plain("[" + range.text + "]" + "(" + (text ?? "") + ")")], -1); } } // parts helper methods const isBlank = part => !part.text || !/\S/.test(part.text); const isNL = part => part.type === _parts.Type.Newline; function toggleInlineFormat(range, prefix, suffix = prefix) { const { model, parts } = range; const { partCreator } = model; // compute paragraph [start, end] indexes const paragraphIndexes = []; let startIndex = 0; // start at i=2 because we look at i and up to two parts behind to detect paragraph breaks at their end for (let i = 2; i < parts.length; i++) { // paragraph breaks can be denoted in a multitude of ways, // - 2 newline parts in sequence // - newline part, plain(<empty or just spaces>), newline part // bump startIndex onto the first non-blank after the paragraph ending if (isBlank(parts[i - 2]) && isNL(parts[i - 1]) && !isNL(parts[i]) && !isBlank(parts[i])) { startIndex = i; } // if at a paragraph break, store the indexes of the paragraph if (isNL(parts[i - 1]) && isNL(parts[i])) { paragraphIndexes.push([startIndex, i - 1]); startIndex = i + 1; } else if (isNL(parts[i - 2]) && isBlank(parts[i - 1]) && isNL(parts[i])) { paragraphIndexes.push([startIndex, i - 2]); startIndex = i + 1; } } const lastNonEmptyPart = parts.map(isBlank).lastIndexOf(false); // If we have not yet included the final paragraph then add it now if (startIndex <= lastNonEmptyPart) { paragraphIndexes.push([startIndex, lastNonEmptyPart + 1]); } // keep track of how many things we have inserted as an offset:=0 let offset = 0; paragraphIndexes.forEach(([startIdx, endIdx]) => { // for each paragraph apply the same rule const base = startIdx + offset; const index = endIdx + offset; const isFormatted = index - base > 0 && parts[base].text.startsWith(prefix) && parts[index - 1].text.endsWith(suffix); if (isFormatted) { // remove prefix and suffix formatting string const partWithoutPrefix = parts[base].serialize(); partWithoutPrefix.text = partWithoutPrefix.text.slice(prefix.length); let deserializedPart = partCreator.deserializePart(partWithoutPrefix); if (deserializedPart) { parts[base] = deserializedPart; } const partWithoutSuffix = parts[index - 1].serialize(); const suffixPartText = partWithoutSuffix.text; partWithoutSuffix.text = suffixPartText.substring(0, suffixPartText.length - suffix.length); deserializedPart = partCreator.deserializePart(partWithoutSuffix); if (deserializedPart) { parts[index - 1] = deserializedPart; } } else { parts.splice(index, 0, partCreator.plain(suffix)); // splice in the later one first to not change offset parts.splice(base, 0, partCreator.plain(prefix)); offset += 2; // offset index to account for the two items we just spliced in } }); // If the user didn't select something initially, we want to just restore // the caret position instead of making a new selection. if (range.wasInitializedEmpty() && prefix === suffix) { // Check if we need to add a offset for a toggle or untoggle const hasFormatting = range.text.startsWith(prefix) && range.text.endsWith(suffix); replaceRangeAndAutoAdjustCaret(range, parts, hasFormatting, prefix.length); } else { replaceRangeAndExpandSelection(range, parts); } } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcGFydHMiLCJyZXF1aXJlIiwiX01lc3NhZ2VDb21wb3NlckZvcm1hdEJhciIsIl9kZXNlcmlhbGl6ZSIsImZvcm1hdFJhbmdlIiwicmFuZ2UiLCJhY3Rpb24iLCJ3YXNJbml0aWFsaXplZEVtcHR5Iiwic2VsZWN0UmFuZ2VPZldvcmRBdENhcmV0IiwidHJpbSIsImxlbmd0aCIsIkZvcm1hdHRpbmciLCJCb2xkIiwidG9nZ2xlSW5saW5lRm9ybWF0IiwiSXRhbGljcyIsIlN0cmlrZXRocm91Z2giLCJDb2RlIiwiZm9ybWF0UmFuZ2VBc0NvZGUiLCJRdW90ZSIsImZvcm1hdFJhbmdlQXNRdW90ZSIsIkluc2VydExpbmsiLCJmb3JtYXRSYW5nZUFzTGluayIsInJlcGxhY2VSYW5nZUFuZEV4cGFuZFNlbGVjdGlvbiIsIm5ld1BhcnRzIiwibW9kZWwiLCJ0cmFuc2Zvcm0iLCJvbGRMZW4iLCJhZGRlZExlbiIsInJlcGxhY2UiLCJmaXJzdE9mZnNldCIsInN0YXJ0IiwiYXNPZmZzZXQiLCJsYXN0T2Zmc2V0IiwiYWRkIiwic3RhcnRSYW5nZSIsImFzUG9zaXRpb24iLCJyZXBsYWNlUmFuZ2VBbmRNb3ZlQ2FyZXQiLCJvZmZzZXQiLCJhdE5vZGVFbmQiLCJyZXBsYWNlUmFuZ2VBbmRBdXRvQWRqdXN0Q2FyZXQiLCJyYW5nZUhhc0Zvcm1hdHRpbmciLCJwcmVmaXhMZW5ndGgiLCJzdWZmaXhMZW5ndGgiLCJsYXN0U3RhcnRpbmdQb3NpdGlvbiIsImdldExhc3RTdGFydGluZ1Bvc2l0aW9uIiwicmVsYXRpdmVPZmZzZXQiLCJkaXN0YW5jZUZyb21FbmQiLCJvZmZzZXREaXJlY3Rpb24iLCJNYXRoIiwic2lnbiIsImF0RW5kIiwiaXNGb3JtYXR0YWJsZSIsIl9pbmRleCIsInBhcnQiLCJ0ZXh0IiwidHlwZSIsIlR5cGUiLCJQbGFpbiIsImV4cGFuZEZvcndhcmRzV2hpbGUiLCJleHBhbmRCYWNrd2FyZHNXaGlsZSIsInJhbmdlU3RhcnRzQXRCZWdpbm5pbmdPZkxpbmUiLCJzdGFydHNXaXRoUGFydGlhbCIsImlzRmlyc3RQYXJ0IiwiaW5kZXgiLCJwcmV2aW91c0lzTmV3bGluZSIsInBhcnRzIiwiTmV3bGluZSIsInJhbmdlRW5kc0F0RW5kT2ZMaW5lIiwibGFzdFBhcnQiLCJlbmQiLCJlbmRzV2l0aFBhcnRpYWwiLCJpc0xhc3RQYXJ0IiwibmV4dElzTmV3bGluZSIsInBhcnRDcmVhdG9yIiwiaSIsInNwbGljZSIsInBsYWluIiwidW5zaGlmdCIsIm5ld2xpbmUiLCJwdXNoIiwiaGFzQmxvY2tGb3JtYXR0aW5nIiwic3RhcnRzV2l0aCIsImVuZHNXaXRoIiwiaW5jbHVkZXMiLCJuZWVkc0Jsb2NrRm9ybWF0dGluZyIsInNvbWUiLCJwIiwic2hpZnQiLCJwb3AiLCJmZW5jZUxlbiIsImxvbmdlc3RCYWNrdGlja1NlcXVlbmNlIiwiaGFzSW5saW5lRm9ybWF0dGluZyIsInJlcGVhdCIsImxpbmtSZWdleCIsImlzRm9ybWF0dGVkQXNMaW5rIiwidGVzdCIsImxpbmtEZXNjcmlwdGlvbiIsImlzQmxhbmsiLCJpc05MIiwicHJlZml4Iiwic3VmZml4IiwicGFyYWdyYXBoSW5kZXhlcyIsInN0YXJ0SW5kZXgiLCJsYXN0Tm9uRW1wdHlQYXJ0IiwibWFwIiwibGFzdEluZGV4T2YiLCJmb3JFYWNoIiwic3RhcnRJZHgiLCJlbmRJZHgiLCJiYXNlIiwiaXNGb3JtYXR0ZWQiLCJwYXJ0V2l0aG91dFByZWZpeCIsInNlcmlhbGl6ZSIsInNsaWNlIiwiZGVzZXJpYWxpemVkUGFydCIsImRlc2VyaWFsaXplUGFydCIsInBhcnRXaXRob3V0U3VmZml4Iiwic3VmZml4UGFydFRleHQiLCJzdWJzdHJpbmciLCJoYXNGb3JtYXR0aW5nIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2VkaXRvci9vcGVyYXRpb25zLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDE5IFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCBSYW5nZSBmcm9tIFwiLi9yYW5nZVwiO1xuaW1wb3J0IHsgUGFydCwgVHlwZSB9IGZyb20gXCIuL3BhcnRzXCI7XG5pbXBvcnQgeyBGb3JtYXR0aW5nIH0gZnJvbSBcIi4uL2NvbXBvbmVudHMvdmlld3Mvcm9vbXMvTWVzc2FnZUNvbXBvc2VyRm9ybWF0QmFyXCI7XG5pbXBvcnQgeyBsb25nZXN0QmFja3RpY2tTZXF1ZW5jZSB9IGZyb20gXCIuL2Rlc2VyaWFsaXplXCI7XG5cbi8qKlxuICogU29tZSBjb21tb24gcXVlcmllcyBhbmQgdHJhbnNmb3JtYXRpb25zIG9uIHRoZSBlZGl0b3IgbW9kZWxcbiAqL1xuXG4vKipcbiAqIEZvcm1hdHMgYSBnaXZlbiByYW5nZSB3aXRoIGEgZ2l2ZW4gYWN0aW9uXG4gKiBAcGFyYW0ge1JhbmdlfSByYW5nZSB0aGUgcmFuZ2UgdGhhdCBzaG91bGQgYmUgZm9ybWF0dGVkXG4gKiBAcGFyYW0ge0Zvcm1hdHRpbmd9IGFjdGlvbiB0aGUgYWN0aW9uIHRoYXQgc2hvdWxkIGJlIHBlcmZvcm1lZCBvbiB0aGUgcmFuZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdFJhbmdlKHJhbmdlOiBSYW5nZSwgYWN0aW9uOiBGb3JtYXR0aW5nKTogdm9pZCB7XG4gICAgLy8gSWYgdGhlIHNlbGVjdGlvbiB3YXMgZW1wdHkgd2Ugc2VsZWN0IHRoZSBjdXJyZW50IHdvcmQgaW5zdGVhZFxuICAgIGlmIChyYW5nZS53YXNJbml0aWFsaXplZEVtcHR5KCkpIHtcbiAgICAgICAgc2VsZWN0UmFuZ2VPZldvcmRBdENhcmV0KHJhbmdlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBSZW1vdmUgd2hpdGVzcGFjZSBvciBuZXcgbGluZXMgaW4gb3VyIHNlbGVjdGlvblxuICAgICAgICByYW5nZS50cmltKCk7XG4gICAgfVxuXG4gICAgLy8gRWRnZSBjYXNlIHdoZW4ganVzdCBzZWxlY3Rpbmcgd2hpdGVzcGFjZSBvciBuZXcgbGluZS5cbiAgICAvLyBUaGVyZSBzaG91bGQgYmUgbm8gcmVhc29uIHRvIGZvcm1hdCB3aGl0ZXNwYWNlLCBzbyB3ZSBjYW4ganVzdCByZXR1cm4uXG4gICAgaWYgKHJhbmdlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgc3dpdGNoIChhY3Rpb24pIHtcbiAgICAgICAgY2FzZSBGb3JtYXR0aW5nLkJvbGQ6XG4gICAgICAgICAgICB0b2dnbGVJbmxpbmVGb3JtYXQocmFuZ2UsIFwiKipcIik7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBGb3JtYXR0aW5nLkl0YWxpY3M6XG4gICAgICAgICAgICB0b2dnbGVJbmxpbmVGb3JtYXQocmFuZ2UsIFwiKlwiKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEZvcm1hdHRpbmcuU3RyaWtldGhyb3VnaDpcbiAgICAgICAgICAgIHRvZ2dsZUlubGluZUZvcm1hdChyYW5nZSwgXCI8ZGVsPlwiLCBcIjwvZGVsPlwiKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEZvcm1hdHRpbmcuQ29kZTpcbiAgICAgICAgICAgIGZvcm1hdFJhbmdlQXNDb2RlKHJhbmdlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEZvcm1hdHRpbmcuUXVvdGU6XG4gICAgICAgICAgICBmb3JtYXRSYW5nZUFzUXVvdGUocmFuZ2UpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgRm9ybWF0dGluZy5JbnNlcnRMaW5rOlxuICAgICAgICAgICAgZm9ybWF0UmFuZ2VBc0xpbmsocmFuZ2UpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVwbGFjZVJhbmdlQW5kRXhwYW5kU2VsZWN0aW9uKHJhbmdlOiBSYW5nZSwgbmV3UGFydHM6IFBhcnRbXSk6IHZvaWQge1xuICAgIGNvbnN0IHsgbW9kZWwgfSA9IHJhbmdlO1xuICAgIG1vZGVsLnRyYW5zZm9ybSgoKSA9PiB7XG4gICAgICAgIGNvbnN0IG9sZExlbiA9IHJhbmdlLmxlbmd0aDtcbiAgICAgICAgY29uc3QgYWRkZWRMZW4gPSByYW5nZS5yZXBsYWNlKG5ld1BhcnRzKTtcbiAgICAgICAgY29uc3QgZmlyc3RPZmZzZXQgPSByYW5nZS5zdGFydC5hc09mZnNldChtb2RlbCk7XG4gICAgICAgIGNvbnN0IGxhc3RPZmZzZXQgPSBmaXJzdE9mZnNldC5hZGQob2xkTGVuICsgYWRkZWRMZW4pO1xuICAgICAgICByZXR1cm4gbW9kZWwuc3RhcnRSYW5nZShmaXJzdE9mZnNldC5hc1Bvc2l0aW9uKG1vZGVsKSwgbGFzdE9mZnNldC5hc1Bvc2l0aW9uKG1vZGVsKSk7XG4gICAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZXBsYWNlUmFuZ2VBbmRNb3ZlQ2FyZXQocmFuZ2U6IFJhbmdlLCBuZXdQYXJ0czogUGFydFtdLCBvZmZzZXQgPSAwLCBhdE5vZGVFbmQgPSBmYWxzZSk6IHZvaWQge1xuICAgIGNvbnN0IHsgbW9kZWwgfSA9IHJhbmdlO1xuICAgIG1vZGVsLnRyYW5zZm9ybSgoKSA9PiB7XG4gICAgICAgIGNvbnN0IG9sZExlbiA9IHJhbmdlLmxlbmd0aDtcbiAgICAgICAgY29uc3QgYWRkZWRMZW4gPSByYW5nZS5yZXBsYWNlKG5ld1BhcnRzKTtcbiAgICAgICAgY29uc3QgZmlyc3RPZmZzZXQgPSByYW5nZS5zdGFydC5hc09mZnNldChtb2RlbCk7XG4gICAgICAgIGNvbnN0IGxhc3RPZmZzZXQgPSBmaXJzdE9mZnNldC5hZGQob2xkTGVuICsgYWRkZWRMZW4gKyBvZmZzZXQsIGF0Tm9kZUVuZCk7XG4gICAgICAgIHJldHVybiBsYXN0T2Zmc2V0LmFzUG9zaXRpb24obW9kZWwpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIFJlcGxhY2VzIGEgcmFuZ2Ugd2l0aCBmb3JtYXR0aW5nIG9yIHJlbW92ZXMgZXhpc3RpbmcgZm9ybWF0dGluZyBhbmRcbiAqIHBvc2l0aW9ucyB0aGUgY3Vyc29yIHdpdGggcmVzcGVjdCB0byB0aGUgcHJlZml4IGFuZCBzdWZmaXggbGVuZ3RoLlxuICogQHBhcmFtIHtSYW5nZX0gcmFuZ2UgdGhlIHByZXZpb3VzIHZhbHVlXG4gKiBAcGFyYW0ge1BhcnRbXX0gbmV3UGFydHMgdGhlIG5ldyB2YWx1ZVxuICogQHBhcmFtIHtib29sZWFufSByYW5nZUhhc0Zvcm1hdHRpbmcgdGhlIG5ldyB2YWx1ZVxuICogQHBhcmFtIHtudW1iZXJ9IHByZWZpeExlbmd0aCB0aGUgbGVuZ3RoIG9mIHRoZSBmb3JtYXR0aW5nIHByZWZpeFxuICogQHBhcmFtIHtudW1iZXJ9IHN1ZmZpeExlbmd0aCB0aGUgbGVuZ3RoIG9mIHRoZSBmb3JtYXR0aW5nIHN1ZmZpeCwgZGVmYXVsdHMgdG8gcHJlZml4IGxlbmd0aFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVwbGFjZVJhbmdlQW5kQXV0b0FkanVzdENhcmV0KFxuICAgIHJhbmdlOiBSYW5nZSxcbiAgICBuZXdQYXJ0czogUGFydFtdLFxuICAgIHJhbmdlSGFzRm9ybWF0dGluZyA9IGZhbHNlLFxuICAgIHByZWZpeExlbmd0aDogbnVtYmVyLFxuICAgIHN1ZmZpeExlbmd0aCA9IHByZWZpeExlbmd0aCxcbik6IHZvaWQge1xuICAgIGNvbnN0IHsgbW9kZWwgfSA9IHJhbmdlO1xuICAgIGNvbnN0IGxhc3RTdGFydGluZ1Bvc2l0aW9uID0gcmFuZ2UuZ2V0TGFzdFN0YXJ0aW5nUG9zaXRpb24oKTtcbiAgICBjb25zdCByZWxhdGl2ZU9mZnNldCA9IGxhc3RTdGFydGluZ1Bvc2l0aW9uLm9mZnNldCAtIHJhbmdlLnN0YXJ0Lm9mZnNldDtcbiAgICBjb25zdCBkaXN0YW5jZUZyb21FbmQgPSByYW5nZS5sZW5ndGggLSByZWxhdGl2ZU9mZnNldDtcbiAgICAvLyBIYW5kbGUgZWRnZSBjYXNlIHdoZXJlIHRoZSBjYXJldCBpcyBsb2NhdGVkIHdpdGhpbiB0aGUgc3VmZml4IG9yIHByZWZpeFxuICAgIGlmIChyYW5nZUhhc0Zvcm1hdHRpbmcpIHtcbiAgICAgICAgaWYgKHJlbGF0aXZlT2Zmc2V0IDwgcHJlZml4TGVuZ3RoKSB7XG4gICAgICAgICAgICAvLyBXYXMgdGhlIGNhcmV0IGF0IHRoZSBsZWZ0IGZvcm1hdCBzdHJpbmc/XG4gICAgICAgICAgICByZXBsYWNlUmFuZ2VBbmRNb3ZlQ2FyZXQocmFuZ2UsIG5ld1BhcnRzLCAtKHJhbmdlLmxlbmd0aCAtIDIgKiBzdWZmaXhMZW5ndGgpKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGlzdGFuY2VGcm9tRW5kIDwgc3VmZml4TGVuZ3RoKSB7XG4gICAgICAgICAgICAvLyBXYXMgdGhlIGNhcmV0IGF0IHRoZSByaWdodCBmb3JtYXQgc3RyaW5nP1xuICAgICAgICAgICAgcmVwbGFjZVJhbmdlQW5kTW92ZUNhcmV0KHJhbmdlLCBuZXdQYXJ0cywgMCwgdHJ1ZSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gQ2FsY3VsYXRlIG5ldyBwb3NpdGlvbiB3aXRoIHJlc3BlY3QgdG8gdGhlIHByZXZpb3VzIHBvc2l0aW9uXG4gICAgbW9kZWwudHJhbnNmb3JtKCgpID0+IHtcbiAgICAgICAgY29uc3Qgb2Zmc2V0RGlyZWN0aW9uID0gTWF0aC5zaWduKHJhbmdlLnJlcGxhY2UobmV3UGFydHMpKTsgLy8gQ29tcGVuc2F0ZXMgZm9yIHNocmlua2FnZSBvciBleHBhbnNpb25cbiAgICAgICAgY29uc3QgYXRFbmQgPSBkaXN0YW5jZUZyb21FbmQgPT09IHN1ZmZpeExlbmd0aDtcbiAgICAgICAgcmV0dXJuIGxhc3RTdGFydGluZ1Bvc2l0aW9uXG4gICAgICAgICAgICAuYXNPZmZzZXQobW9kZWwpXG4gICAgICAgICAgICAuYWRkKG9mZnNldERpcmVjdGlvbiAqIHByZWZpeExlbmd0aCwgYXRFbmQpXG4gICAgICAgICAgICAuYXNQb3NpdGlvbihtb2RlbCk7XG4gICAgfSk7XG59XG5cbmNvbnN0IGlzRm9ybWF0dGFibGUgPSAoX2luZGV4OiBudW1iZXIsIG9mZnNldDogbnVtYmVyLCBwYXJ0OiBQYXJ0KTogYm9vbGVhbiA9PiB7XG4gICAgcmV0dXJuIHBhcnQudGV4dFtvZmZzZXRdICE9PSBcIiBcIiAmJiBwYXJ0LnR5cGUgPT09IFR5cGUuUGxhaW47XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gc2VsZWN0UmFuZ2VPZldvcmRBdENhcmV0KHJhbmdlOiBSYW5nZSk6IHZvaWQge1xuICAgIC8vIFNlbGVjdCByaWdodCBzaWRlIG9mIHdvcmRcbiAgICByYW5nZS5leHBhbmRGb3J3YXJkc1doaWxlKGlzRm9ybWF0dGFibGUpO1xuICAgIC8vIFNlbGVjdCBsZWZ0IHNpZGUgb2Ygd29yZFxuICAgIHJhbmdlLmV4cGFuZEJhY2t3YXJkc1doaWxlKGlzRm9ybWF0dGFibGUpO1xuICAgIC8vIFRyaW0gcG9zc2libHkgc2VsZWN0ZWQgbmV3IGxpbmVzXG4gICAgcmFuZ2UudHJpbSgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmFuZ2VTdGFydHNBdEJlZ2lubmluZ09mTGluZShyYW5nZTogUmFuZ2UpOiBib29sZWFuIHtcbiAgICBjb25zdCB7IG1vZGVsIH0gPSByYW5nZTtcbiAgICBjb25zdCBzdGFydHNXaXRoUGFydGlhbCA9IHJhbmdlLnN0YXJ0Lm9mZnNldCAhPT0gMDtcbiAgICBjb25zdCBpc0ZpcnN0UGFydCA9IHJhbmdlLnN0YXJ0LmluZGV4ID09PSAwO1xuICAgIGNvbnN0IHByZXZpb3VzSXNOZXdsaW5lID0gIWlzRmlyc3RQYXJ0ICYmIG1vZGVsLnBhcnRzW3JhbmdlLnN0YXJ0LmluZGV4IC0gMV0udHlwZSA9PT0gVHlwZS5OZXdsaW5lO1xuICAgIHJldHVybiAhc3RhcnRzV2l0aFBhcnRpYWwgJiYgKGlzRmlyc3RQYXJ0IHx8IHByZXZpb3VzSXNOZXdsaW5lKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJhbmdlRW5kc0F0RW5kT2ZMaW5lKHJhbmdlOiBSYW5nZSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHsgbW9kZWwgfSA9IHJhbmdlO1xuICAgIGNvbnN0IGxhc3RQYXJ0ID0gbW9kZWwucGFydHNbcmFuZ2UuZW5kLmluZGV4XTtcbiAgICBjb25zdCBlbmRzV2l0aFBhcnRpYWwgPSByYW5nZS5lbmQub2Zmc2V0ICE9PSBsYXN0UGFydC50ZXh0Lmxlbmd0aDtcbiAgICBjb25zdCBpc0xhc3RQYXJ0ID0gcmFuZ2UuZW5kLmluZGV4ID09PSBtb2RlbC5wYXJ0cy5sZW5ndGggLSAxO1xuICAgIGNvbnN0IG5leHRJc05ld2xpbmUgPSAhaXNMYXN0UGFydCAmJiBtb2RlbC5wYXJ0c1tyYW5nZS5lbmQuaW5kZXggKyAxXS50eXBlID09PSBUeXBlLk5ld2xpbmU7XG4gICAgcmV0dXJuICFlbmRzV2l0aFBhcnRpYWwgJiYgKGlzTGFzdFBhcnQgfHwgbmV4dElzTmV3bGluZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXRSYW5nZUFzUXVvdGUocmFuZ2U6IFJhbmdlKTogdm9pZCB7XG4gICAgY29uc3QgeyBtb2RlbCwgcGFydHMgfSA9IHJhbmdlO1xuICAgIGNvbnN0IHsgcGFydENyZWF0b3IgfSA9IG1vZGVsO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgY29uc3QgcGFydCA9IHBhcnRzW2ldO1xuICAgICAgICBpZiAocGFydC50eXBlID09PSBUeXBlLk5ld2xpbmUpIHtcbiAgICAgICAgICAgIHBhcnRzLnNwbGljZShpICsgMSwgMCwgcGFydENyZWF0b3IucGxhaW4oXCI+IFwiKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcGFydHMudW5zaGlmdChwYXJ0Q3JlYXRvci5wbGFpbihcIj4gXCIpKTtcbiAgICBpZiAoIXJhbmdlU3RhcnRzQXRCZWdpbm5pbmdPZkxpbmUocmFuZ2UpKSB7XG4gICAgICAgIHBhcnRzLnVuc2hpZnQocGFydENyZWF0b3IubmV3bGluZSgpKTtcbiAgICB9XG4gICAgaWYgKCFyYW5nZUVuZHNBdEVuZE9mTGluZShyYW5nZSkpIHtcbiAgICAgICAgcGFydHMucHVzaChwYXJ0Q3JlYXRvci5uZXdsaW5lKCkpO1xuICAgIH1cbiAgICBwYXJ0cy5wdXNoKHBhcnRDcmVhdG9yLm5ld2xpbmUoKSk7XG4gICAgcmVwbGFjZVJhbmdlQW5kRXhwYW5kU2VsZWN0aW9uKHJhbmdlLCBwYXJ0cyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXRSYW5nZUFzQ29kZShyYW5nZTogUmFuZ2UpOiB2b2lkIHtcbiAgICBjb25zdCB7IG1vZGVsLCBwYXJ0cyB9ID0gcmFuZ2U7XG4gICAgY29uc3QgeyBwYXJ0Q3JlYXRvciB9ID0gbW9kZWw7XG5cbiAgICBjb25zdCBoYXNCbG9ja0Zvcm1hdHRpbmcgPVxuICAgICAgICByYW5nZS5sZW5ndGggPiAwICYmIHJhbmdlLnRleHQuc3RhcnRzV2l0aChcImBgYFwiKSAmJiByYW5nZS50ZXh0LmVuZHNXaXRoKFwiYGBgXCIpICYmIHJhbmdlLnRleHQuaW5jbHVkZXMoXCJcXG5cIik7XG5cbiAgICBjb25zdCBuZWVkc0Jsb2NrRm9ybWF0dGluZyA9IHBhcnRzLnNvbWUoKHApID0+IHAudHlwZSA9PT0gVHlwZS5OZXdsaW5lKTtcblxuICAgIGlmIChoYXNCbG9ja0Zvcm1hdHRpbmcpIHtcbiAgICAgICAgcGFydHMuc2hpZnQoKTtcbiAgICAgICAgcGFydHMucG9wKCk7XG4gICAgICAgIGlmIChwYXJ0c1swXT8udGV4dCA9PT0gXCJcXG5cIiAmJiBwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXT8udGV4dCA9PT0gXCJcXG5cIikge1xuICAgICAgICAgICAgcGFydHMuc2hpZnQoKTtcbiAgICAgICAgICAgIHBhcnRzLnBvcCgpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmIChuZWVkc0Jsb2NrRm9ybWF0dGluZykge1xuICAgICAgICBwYXJ0cy51bnNoaWZ0KHBhcnRDcmVhdG9yLnBsYWluKFwiYGBgXCIpLCBwYXJ0Q3JlYXRvci5uZXdsaW5lKCkpO1xuICAgICAgICBpZiAoIXJhbmdlU3RhcnRzQXRCZWdpbm5pbmdPZkxpbmUocmFuZ2UpKSB7XG4gICAgICAgICAgICBwYXJ0cy51bnNoaWZ0KHBhcnRDcmVhdG9yLm5ld2xpbmUoKSk7XG4gICAgICAgIH1cbiAgICAgICAgcGFydHMucHVzaChwYXJ0Q3JlYXRvci5uZXdsaW5lKCksIHBhcnRDcmVhdG9yLnBsYWluKFwiYGBgXCIpKTtcbiAgICAgICAgaWYgKCFyYW5nZUVuZHNBdEVuZE9mTGluZShyYW5nZSkpIHtcbiAgICAgICAgICAgIHBhcnRzLnB1c2gocGFydENyZWF0b3IubmV3bGluZSgpKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IGZlbmNlTGVuID0gbG9uZ2VzdEJhY2t0aWNrU2VxdWVuY2UocmFuZ2UudGV4dCk7XG4gICAgICAgIGNvbnN0IGhhc0lubGluZUZvcm1hdHRpbmcgPSByYW5nZS50ZXh0LnN0YXJ0c1dpdGgoXCJgXCIpICYmIHJhbmdlLnRleHQuZW5kc1dpdGgoXCJgXCIpO1xuICAgICAgICAvL2lmIGl0J3MgYWxyZWFkeSBmb3JtYXR0ZWQgdW50b2dnbGUgYmFzZWQgb24gZmVuY2VMZW4gd2hpY2ggcmV0dXJucyB0aGUgbWF4LiBudW0gb2YgYmFja3RpY2sgd2l0aGluIGEgdGV4dCBlbHNlIGluY3JlYXNlIHRoZSBmZW5jZSBiYWNrdGlja3Mgd2l0aCBhIGZhY3RvciBvZiAxLlxuICAgICAgICB0b2dnbGVJbmxpbmVGb3JtYXQocmFuZ2UsIFwiYFwiLnJlcGVhdChoYXNJbmxpbmVGb3JtYXR0aW5nID8gZmVuY2VMZW4gOiBmZW5jZUxlbiArIDEpKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHJlcGxhY2VSYW5nZUFuZEV4cGFuZFNlbGVjdGlvbihyYW5nZSwgcGFydHMpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0UmFuZ2VBc0xpbmsocmFuZ2U6IFJhbmdlLCB0ZXh0Pzogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgeyBtb2RlbCB9ID0gcmFuZ2U7XG4gICAgY29uc3QgeyBwYXJ0Q3JlYXRvciB9ID0gbW9kZWw7XG4gICAgY29uc3QgbGlua1JlZ2V4ID0gL1xcWyguKj8pXVxcKC4qP1xcKS9nO1xuICAgIGNvbnN0IGlzRm9ybWF0dGVkQXNMaW5rID0gbGlua1JlZ2V4LnRlc3QocmFuZ2UudGV4dCk7XG4gICAgaWYgKGlzRm9ybWF0dGVkQXNMaW5rKSB7XG4gICAgICAgIGNvbnN0IGxpbmtEZXNjcmlwdGlvbiA9IHJhbmdlLnRleHQucmVwbGFjZShsaW5rUmVnZXgsIFwiJDFcIik7XG4gICAgICAgIGNvbnN0IG5ld1BhcnRzID0gW3BhcnRDcmVhdG9yLnBsYWluKGxpbmtEZXNjcmlwdGlvbildO1xuICAgICAgICByZXBsYWNlUmFuZ2VBbmRNb3ZlQ2FyZXQocmFuZ2UsIG5ld1BhcnRzLCAwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBXZSBzZXQgb2Zmc2V0IHRvIC0xIGhlcmUgc28gdGhhdCB0aGUgY2FyZXQgbGFuZHMgYmV0d2VlbiB0aGUgYnJhY2tldHNcbiAgICAgICAgcmVwbGFjZVJhbmdlQW5kTW92ZUNhcmV0KHJhbmdlLCBbcGFydENyZWF0b3IucGxhaW4oXCJbXCIgKyByYW5nZS50ZXh0ICsgXCJdXCIgKyBcIihcIiArICh0ZXh0ID8/IFwiXCIpICsgXCIpXCIpXSwgLTEpO1xuICAgIH1cbn1cblxuLy8gcGFydHMgaGVscGVyIG1ldGhvZHNcbmNvbnN0IGlzQmxhbmsgPSAocGFydDogUGFydCk6IGJvb2xlYW4gPT4gIXBhcnQudGV4dCB8fCAhL1xcUy8udGVzdChwYXJ0LnRleHQpO1xuY29uc3QgaXNOTCA9IChwYXJ0OiBQYXJ0KTogYm9vbGVhbiA9PiBwYXJ0LnR5cGUgPT09IFR5cGUuTmV3bGluZTtcblxuZXhwb3J0IGZ1bmN0aW9uIHRvZ2dsZUlubGluZUZvcm1hdChyYW5nZTogUmFuZ2UsIHByZWZpeDogc3RyaW5nLCBzdWZmaXggPSBwcmVmaXgpOiB2b2lkIHtcbiAgICBjb25zdCB7IG1vZGVsLCBwYXJ0cyB9ID0gcmFuZ2U7XG4gICAgY29uc3QgeyBwYXJ0Q3JlYXRvciB9ID0gbW9kZWw7XG5cbiAgICAvLyBjb21wdXRlIHBhcmFncmFwaCBbc3RhcnQsIGVuZF0gaW5kZXhlc1xuICAgIGNvbnN0IHBhcmFncmFwaEluZGV4ZXM6IFtudW1iZXIsIG51bWJlcl1bXSA9IFtdO1xuICAgIGxldCBzdGFydEluZGV4ID0gMDtcblxuICAgIC8vIHN0YXJ0IGF0IGk9MiBiZWNhdXNlIHdlIGxvb2sgYXQgaSBhbmQgdXAgdG8gdHdvIHBhcnRzIGJlaGluZCB0byBkZXRlY3QgcGFyYWdyYXBoIGJyZWFrcyBhdCB0aGVpciBlbmRcbiAgICBmb3IgKGxldCBpID0gMjsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIC8vIHBhcmFncmFwaCBicmVha3MgY2FuIGJlIGRlbm90ZWQgaW4gYSBtdWx0aXR1ZGUgb2Ygd2F5cyxcbiAgICAgICAgLy8gLSAyIG5ld2xpbmUgcGFydHMgaW4gc2VxdWVuY2VcbiAgICAgICAgLy8gLSBuZXdsaW5lIHBhcnQsIHBsYWluKDxlbXB0eSBvciBqdXN0IHNwYWNlcz4pLCBuZXdsaW5lIHBhcnRcblxuICAgICAgICAvLyBidW1wIHN0YXJ0SW5kZXggb250byB0aGUgZmlyc3Qgbm9uLWJsYW5rIGFmdGVyIHRoZSBwYXJhZ3JhcGggZW5kaW5nXG4gICAgICAgIGlmIChpc0JsYW5rKHBhcnRzW2kgLSAyXSkgJiYgaXNOTChwYXJ0c1tpIC0gMV0pICYmICFpc05MKHBhcnRzW2ldKSAmJiAhaXNCbGFuayhwYXJ0c1tpXSkpIHtcbiAgICAgICAgICAgIHN0YXJ0SW5kZXggPSBpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gaWYgYXQgYSBwYXJhZ3JhcGggYnJlYWssIHN0b3JlIHRoZSBpbmRleGVzIG9mIHRoZSBwYXJhZ3JhcGhcbiAgICAgICAgaWYgKGlzTkwocGFydHNbaSAtIDFdKSAmJiBpc05MKHBhcnRzW2ldKSkge1xuICAgICAgICAgICAgcGFyYWdyYXBoSW5kZXhlcy5wdXNoKFtzdGFydEluZGV4LCBpIC0gMV0pO1xuICAgICAgICAgICAgc3RhcnRJbmRleCA9IGkgKyAxO1xuICAgICAgICB9IGVsc2UgaWYgKGlzTkwocGFydHNbaSAtIDJdKSAmJiBpc0JsYW5rKHBhcnRzW2kgLSAxXSkgJiYgaXNOTChwYXJ0c1tpXSkpIHtcbiAgICAgICAgICAgIHBhcmFncmFwaEluZGV4ZXMucHVzaChbc3RhcnRJbmRleCwgaSAtIDJdKTtcbiAgICAgICAgICAgIHN0YXJ0SW5kZXggPSBpICsgMTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGxhc3ROb25FbXB0eVBhcnQgPSBwYXJ0cy5tYXAoaXNCbGFuaykubGFzdEluZGV4T2YoZmFsc2UpO1xuICAgIC8vIElmIHdlIGhhdmUgbm90IHlldCBpbmNsdWRlZCB0aGUgZmluYWwgcGFyYWdyYXBoIHRoZW4gYWRkIGl0IG5vd1xuICAgIGlmIChzdGFydEluZGV4IDw9IGxhc3ROb25FbXB0eVBhcnQpIHtcbiAgICAgICAgcGFyYWdyYXBoSW5kZXhlcy5wdXNoKFtzdGFydEluZGV4LCBsYXN0Tm9uRW1wdHlQYXJ0ICsgMV0pO1xuICAgIH1cblxuICAgIC8vIGtlZXAgdHJhY2sgb2YgaG93IG1hbnkgdGhpbmdzIHdlIGhhdmUgaW5zZXJ0ZWQgYXMgYW4gb2Zmc2V0Oj0wXG4gICAgbGV0IG9mZnNldCA9IDA7XG4gICAgcGFyYWdyYXBoSW5kZXhlcy5mb3JFYWNoKChbc3RhcnRJZHgsIGVuZElkeF0pID0+IHtcbiAgICAgICAgLy8gZm9yIGVhY2ggcGFyYWdyYXBoIGFwcGx5IHRoZSBzYW1lIHJ1bGVcbiAgICAgICAgY29uc3QgYmFzZSA9IHN0YXJ0SWR4ICsgb2Zmc2V0O1xuICAgICAgICBjb25zdCBpbmRleCA9IGVuZElkeCArIG9mZnNldDtcblxuICAgICAgICBjb25zdCBpc0Zvcm1hdHRlZCA9XG4gICAgICAgICAgICBpbmRleCAtIGJhc2UgPiAwICYmIHBhcnRzW2Jhc2VdLnRleHQuc3RhcnRzV2l0aChwcmVmaXgpICYmIHBhcnRzW2luZGV4IC0gMV0udGV4dC5lbmRzV2l0aChzdWZmaXgpO1xuXG4gICAgICAgIGlmIChpc0Zvcm1hdHRlZCkge1xuICAgICAgICAgICAgLy8gcmVtb3ZlIHByZWZpeCBhbmQgc3VmZml4IGZvcm1hdHRpbmcgc3RyaW5nXG4gICAgICAgICAgICBjb25zdCBwYXJ0V2l0aG91dFByZWZpeCA9IHBhcnRzW2Jhc2VdLnNlcmlhbGl6ZSgpO1xuICAgICAgICAgICAgcGFydFdpdGhvdXRQcmVmaXgudGV4dCA9IHBhcnRXaXRob3V0UHJlZml4LnRleHQuc2xpY2UocHJlZml4Lmxlbmd0aCk7XG4gICAgICAgICAgICBsZXQgZGVzZXJpYWxpemVkUGFydCA9IHBhcnRDcmVhdG9yLmRlc2VyaWFsaXplUGFydChwYXJ0V2l0aG91dFByZWZpeCk7XG4gICAgICAgICAgICBpZiAoZGVzZXJpYWxpemVkUGFydCkge1xuICAgICAgICAgICAgICAgIHBhcnRzW2Jhc2VdID0gZGVzZXJpYWxpemVkUGFydDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgcGFydFdpdGhvdXRTdWZmaXggPSBwYXJ0c1tpbmRleCAtIDFdLnNlcmlhbGl6ZSgpO1xuICAgICAgICAgICAgY29uc3Qgc3VmZml4UGFydFRleHQgPSBwYXJ0V2l0aG91dFN1ZmZpeC50ZXh0O1xuICAgICAgICAgICAgcGFydFdpdGhvdXRTdWZmaXgudGV4dCA9IHN1ZmZpeFBhcnRUZXh0LnN1YnN0cmluZygwLCBzdWZmaXhQYXJ0VGV4dC5sZW5ndGggLSBzdWZmaXgubGVuZ3RoKTtcbiAgICAgICAgICAgIGRlc2VyaWFsaXplZFBhcnQgPSBwYXJ0Q3JlYXRvci5kZXNlcmlhbGl6ZVBhcnQocGFydFdpdGhvdXRTdWZmaXgpO1xuICAgICAgICAgICAgaWYgKGRlc2VyaWFsaXplZFBhcnQpIHtcbiAgICAgICAgICAgICAgICBwYXJ0c1tpbmRleCAtIDFdID0gZGVzZXJpYWxpemVkUGFydDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBhcnRzLnNwbGljZShpbmRleCwgMCwgcGFydENyZWF0b3IucGxhaW4oc3VmZml4KSk7IC8vIHNwbGljZSBpbiB0aGUgbGF0ZXIgb25lIGZpcnN0IHRvIG5vdCBjaGFuZ2Ugb2Zmc2V0XG4gICAgICAgICAgICBwYXJ0cy5zcGxpY2UoYmFzZSwgMCwgcGFydENyZWF0b3IucGxhaW4ocHJlZml4KSk7XG4gICAgICAgICAgICBvZmZzZXQgKz0gMjsgLy8gb2Zmc2V0IGluZGV4IHRvIGFjY291bnQgZm9yIHRoZSB0d28gaXRlbXMgd2UganVzdCBzcGxpY2VkIGluXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIElmIHRoZSB1c2VyIGRpZG4ndCBzZWxlY3Qgc29tZXRoaW5nIGluaXRpYWxseSwgd2Ugd2FudCB0byBqdXN0IHJlc3RvcmVcbiAgICAvLyB0aGUgY2FyZXQgcG9zaXRpb24gaW5zdGVhZCBvZiBtYWtpbmcgYSBuZXcgc2VsZWN0aW9uLlxuICAgIGlmIChyYW5nZS53YXNJbml0aWFsaXplZEVtcHR5KCkgJiYgcHJlZml4ID09PSBzdWZmaXgpIHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgd2UgbmVlZCB0byBhZGQgYSBvZmZzZXQgZm9yIGEgdG9nZ2xlIG9yIHVudG9nZ2xlXG4gICAgICAgIGNvbnN0IGhhc0Zvcm1hdHRpbmcgPSByYW5nZS50ZXh0LnN0YXJ0c1dpdGgocHJlZml4KSAmJiByYW5nZS50ZXh0LmVuZHNXaXRoKHN1ZmZpeCk7XG4gICAgICAgIHJlcGxhY2VSYW5nZUFuZEF1dG9BZGp1c3RDYXJldChyYW5nZSwgcGFydHMsIGhhc0Zvcm1hdHRpbmcsIHByZWZpeC5sZW5ndGgpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJlcGxhY2VSYW5nZUFuZEV4cGFuZFNlbGVjdGlvbihyYW5nZSwgcGFydHMpO1xuICAgIH1cbn1cbiJdLCJt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