matrix-react-sdk
Version:
SDK for matrix.org using React
170 lines (162 loc) • 28.1 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _lodash = require("lodash");
var _emoticon = _interopRequireDefault(require("emojibase-regex/emoticon"));
var _emojibaseBindings = require("@matrix-org/emojibase-bindings");
var _languageHandler = require("../languageHandler");
var _AutocompleteProvider = _interopRequireDefault(require("./AutocompleteProvider"));
var _QueryMatcher = _interopRequireDefault(require("./QueryMatcher"));
var _Components = require("./Components");
var _SettingsStore = _interopRequireDefault(require("../settings/SettingsStore"));
var recent = _interopRequireWildcard(require("../emojipicker/recent"));
var _arrays = require("../utils/arrays");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/*
Copyright 2024 New Vector Ltd.
Copyright 2022 Ryan Browne <code@commonlawfeature.com>
Copyright 2019 The Matrix.org Foundation C.I.C.
Copyright 2017, 2018 New Vector Ltd
Copyright 2017 Vector Creations Ltd
Copyright 2016 Aviral Dasgupta
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
const LIMIT = 20;
// Match for ascii-style ";-)" emoticons or ":wink:" shortcodes provided by emojibase
// anchored to only match from the start of parts otherwise it'll show emoji suggestions whilst typing matrix IDs
const EMOJI_REGEX = new RegExp("(" + _emoticon.default.source + "|(?:^|\\s):[+-\\w]*:?)$", "g");
const SORTED_EMOJI = _emojibaseBindings.EMOJI.sort((a, b) => {
if (a.group === b.group) {
return a.order - b.order;
}
return a.group - b.group;
}).map((emoji, index) => ({
emoji,
// Include the index so that we can preserve the original order
_orderBy: index
}));
function score(query, space) {
if (Array.isArray(space)) {
return Math.min(...space.map(s => score(query, s)));
}
const index = space.indexOf(query);
if (index === -1) {
return Infinity;
} else {
return index;
}
}
function colonsTrimmed(str) {
// Trim off leading and potentially trailing `:` to correctly match the emoji data as they exist in emojibase.
// Notes: The regex is pinned to the start and end of the string so that we can use the lazy-capturing `*?` matcher.
// It needs to be lazy so that the trailing `:` is not captured in the replacement group, if it exists.
return str.replace(/^:(.*?):?$/, "$1");
}
class EmojiProvider extends _AutocompleteProvider.default {
constructor(room, renderingType) {
super({
commandRegex: EMOJI_REGEX,
renderingType
});
(0, _defineProperty2.default)(this, "matcher", void 0);
(0, _defineProperty2.default)(this, "nameMatcher", void 0);
(0, _defineProperty2.default)(this, "recentlyUsed", void 0);
this.matcher = new _QueryMatcher.default(SORTED_EMOJI, {
keys: [],
funcs: [o => o.emoji.shortcodes.map(s => `:${s}:`)],
// For matching against ascii equivalents
shouldMatchWordsOnly: false
});
this.nameMatcher = new _QueryMatcher.default(SORTED_EMOJI, {
keys: ["emoji.label"],
// For removing punctuation
shouldMatchWordsOnly: true
});
this.recentlyUsed = Array.from(new Set((0, _arrays.filterBoolean)(recent.get().map(_emojibaseBindings.getEmojiFromUnicode))));
}
async getCompletions(query, selection, force, limit = -1) {
if (!_SettingsStore.default.getValue("MessageComposerInput.suggestEmoji")) {
return []; // don't give any suggestions if the user doesn't want them
}
let completions = [];
const {
command,
range
} = this.getCurrentCommand(query, selection);
if (command && command[0].length > 2) {
const matchedString = command[0];
completions = this.matcher.match(matchedString, limit);
// Do second match with shouldMatchWordsOnly in order to match against 'name'
completions = completions.concat(this.nameMatcher.match(matchedString));
const sorters = [];
// make sure that emoticons come first
sorters.push(c => score(matchedString, c.emoji.emoticon || ""));
// then sort by score (Infinity if matchedString not in shortcode)
sorters.push(c => score(matchedString, c.emoji.shortcodes[0]));
// then sort by max score of all shortcodes, trim off the `:`
const trimmedMatch = colonsTrimmed(matchedString);
sorters.push(c => Math.min(...c.emoji.shortcodes.map(s => score(trimmedMatch, s))));
// If the matchedString is not empty, sort by length of shortcode. Example:
// matchedString = ":bookmark"
// completions = [":bookmark:", ":bookmark_tabs:", ...]
if (matchedString.length > 1) {
sorters.push(c => c.emoji.shortcodes[0].length);
}
// Finally, sort by original ordering
sorters.push(c => c._orderBy);
completions = (0, _lodash.sortBy)((0, _lodash.uniq)(completions), sorters);
completions = completions.slice(0, LIMIT);
// Do a second sort to place emoji matching with frequently used one on top
const recentlyUsedAutocomplete = [];
this.recentlyUsed.forEach(emoji => {
if (emoji.shortcodes[0].indexOf(trimmedMatch) === 0) {
recentlyUsedAutocomplete.push({
emoji: emoji,
_orderBy: 0
});
}
});
//if there is an exact shortcode match in the frequently used emojis, it goes before everything
for (let i = 0; i < recentlyUsedAutocomplete.length; i++) {
if (recentlyUsedAutocomplete[i].emoji.shortcodes[0] === trimmedMatch) {
const exactMatchEmoji = recentlyUsedAutocomplete[i];
for (let j = i; j > 0; j--) {
recentlyUsedAutocomplete[j] = recentlyUsedAutocomplete[j - 1];
}
recentlyUsedAutocomplete[0] = exactMatchEmoji;
break;
}
}
completions = recentlyUsedAutocomplete.concat(completions);
completions = (0, _lodash.uniqBy)(completions, "emoji");
return completions.map(c => ({
completion: c.emoji.unicode,
component: /*#__PURE__*/_react.default.createElement(_Components.PillCompletion, {
title: `:${c.emoji.shortcodes[0]}:`,
"aria-label": c.emoji.unicode
}, /*#__PURE__*/_react.default.createElement("span", null, c.emoji.unicode)),
range: range
}));
}
return [];
}
getName() {
return "😃 " + (0, _languageHandler._t)("common|emoji");
}
renderCompletions(completions) {
return /*#__PURE__*/_react.default.createElement("div", {
className: "mx_Autocomplete_Completion_container_pill",
role: "presentation",
"aria-label": (0, _languageHandler._t)("composer|autocomplete|emoji_a11y")
}, completions);
}
}
exports.default = EmojiProvider;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9sb2Rhc2giLCJfZW1vdGljb24iLCJfZW1vamliYXNlQmluZGluZ3MiLCJfbGFuZ3VhZ2VIYW5kbGVyIiwiX0F1dG9jb21wbGV0ZVByb3ZpZGVyIiwiX1F1ZXJ5TWF0Y2hlciIsIl9Db21wb25lbnRzIiwiX1NldHRpbmdzU3RvcmUiLCJyZWNlbnQiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsIl9hcnJheXMiLCJfZ2V0UmVxdWlyZVdpbGRjYXJkQ2FjaGUiLCJlIiwiV2Vha01hcCIsInIiLCJ0IiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJoYXMiLCJnZXQiLCJuIiwiX19wcm90b19fIiwiYSIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwidSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImkiLCJzZXQiLCJMSU1JVCIsIkVNT0pJX1JFR0VYIiwiUmVnRXhwIiwiRU1PVElDT05fUkVHRVgiLCJzb3VyY2UiLCJTT1JURURfRU1PSkkiLCJFTU9KSSIsInNvcnQiLCJiIiwiZ3JvdXAiLCJvcmRlciIsIm1hcCIsImVtb2ppIiwiaW5kZXgiLCJfb3JkZXJCeSIsInNjb3JlIiwicXVlcnkiLCJzcGFjZSIsIkFycmF5IiwiaXNBcnJheSIsIk1hdGgiLCJtaW4iLCJzIiwiaW5kZXhPZiIsIkluZmluaXR5IiwiY29sb25zVHJpbW1lZCIsInN0ciIsInJlcGxhY2UiLCJFbW9qaVByb3ZpZGVyIiwiQXV0b2NvbXBsZXRlUHJvdmlkZXIiLCJjb25zdHJ1Y3RvciIsInJvb20iLCJyZW5kZXJpbmdUeXBlIiwiY29tbWFuZFJlZ2V4IiwiX2RlZmluZVByb3BlcnR5MiIsIm1hdGNoZXIiLCJRdWVyeU1hdGNoZXIiLCJrZXlzIiwiZnVuY3MiLCJvIiwic2hvcnRjb2RlcyIsInNob3VsZE1hdGNoV29yZHNPbmx5IiwibmFtZU1hdGNoZXIiLCJyZWNlbnRseVVzZWQiLCJmcm9tIiwiU2V0IiwiZmlsdGVyQm9vbGVhbiIsImdldEVtb2ppRnJvbVVuaWNvZGUiLCJnZXRDb21wbGV0aW9ucyIsInNlbGVjdGlvbiIsImZvcmNlIiwibGltaXQiLCJTZXR0aW5nc1N0b3JlIiwiZ2V0VmFsdWUiLCJjb21wbGV0aW9ucyIsImNvbW1hbmQiLCJyYW5nZSIsImdldEN1cnJlbnRDb21tYW5kIiwibGVuZ3RoIiwibWF0Y2hlZFN0cmluZyIsIm1hdGNoIiwiY29uY2F0Iiwic29ydGVycyIsInB1c2giLCJjIiwiZW1vdGljb24iLCJ0cmltbWVkTWF0Y2giLCJzb3J0QnkiLCJ1bmlxIiwic2xpY2UiLCJyZWNlbnRseVVzZWRBdXRvY29tcGxldGUiLCJmb3JFYWNoIiwiZXhhY3RNYXRjaEVtb2ppIiwiaiIsInVuaXFCeSIsImNvbXBsZXRpb24iLCJ1bmljb2RlIiwiY29tcG9uZW50IiwiY3JlYXRlRWxlbWVudCIsIlBpbGxDb21wbGV0aW9uIiwidGl0bGUiLCJnZXROYW1lIiwiX3QiLCJyZW5kZXJDb21wbGV0aW9ucyIsImNsYXNzTmFtZSIsInJvbGUiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2F1dG9jb21wbGV0ZS9FbW9qaVByb3ZpZGVyLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAyMiBSeWFuIEJyb3duZSA8Y29kZUBjb21tb25sYXdmZWF0dXJlLmNvbT5cbkNvcHlyaWdodCAyMDE5IFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5Db3B5cmlnaHQgMjAxNywgMjAxOCBOZXcgVmVjdG9yIEx0ZFxuQ29weXJpZ2h0IDIwMTcgVmVjdG9yIENyZWF0aW9ucyBMdGRcbkNvcHlyaWdodCAyMDE2IEF2aXJhbCBEYXNndXB0YVxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgUmVhY3QgZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyB1bmlxLCBzb3J0QnksIHVuaXFCeSwgTGlzdEl0ZXJhdGVlIH0gZnJvbSBcImxvZGFzaFwiO1xuaW1wb3J0IEVNT1RJQ09OX1JFR0VYIGZyb20gXCJlbW9qaWJhc2UtcmVnZXgvZW1vdGljb25cIjtcbmltcG9ydCB7IFJvb20gfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgeyBFTU9KSSwgRW1vamksIGdldEVtb2ppRnJvbVVuaWNvZGUgfSBmcm9tIFwiQG1hdHJpeC1vcmcvZW1vamliYXNlLWJpbmRpbmdzXCI7XG5cbmltcG9ydCB7IF90IH0gZnJvbSBcIi4uL2xhbmd1YWdlSGFuZGxlclwiO1xuaW1wb3J0IEF1dG9jb21wbGV0ZVByb3ZpZGVyIGZyb20gXCIuL0F1dG9jb21wbGV0ZVByb3ZpZGVyXCI7XG5pbXBvcnQgUXVlcnlNYXRjaGVyIGZyb20gXCIuL1F1ZXJ5TWF0Y2hlclwiO1xuaW1wb3J0IHsgUGlsbENvbXBsZXRpb24gfSBmcm9tIFwiLi9Db21wb25lbnRzXCI7XG5pbXBvcnQgeyBJQ29tcGxldGlvbiwgSVNlbGVjdGlvblJhbmdlIH0gZnJvbSBcIi4vQXV0b2NvbXBsZXRlclwiO1xuaW1wb3J0IFNldHRpbmdzU3RvcmUgZnJvbSBcIi4uL3NldHRpbmdzL1NldHRpbmdzU3RvcmVcIjtcbmltcG9ydCB7IFRpbWVsaW5lUmVuZGVyaW5nVHlwZSB9IGZyb20gXCIuLi9jb250ZXh0cy9Sb29tQ29udGV4dFwiO1xuaW1wb3J0ICogYXMgcmVjZW50IGZyb20gXCIuLi9lbW9qaXBpY2tlci9yZWNlbnRcIjtcbmltcG9ydCB7IGZpbHRlckJvb2xlYW4gfSBmcm9tIFwiLi4vdXRpbHMvYXJyYXlzXCI7XG5cbmNvbnN0IExJTUlUID0gMjA7XG5cbi8vIE1hdGNoIGZvciBhc2NpaS1zdHlsZSBcIjstKVwiIGVtb3RpY29ucyBvciBcIjp3aW5rOlwiIHNob3J0Y29kZXMgcHJvdmlkZWQgYnkgZW1vamliYXNlXG4vLyBhbmNob3JlZCB0byBvbmx5IG1hdGNoIGZyb20gdGhlIHN0YXJ0IG9mIHBhcnRzIG90aGVyd2lzZSBpdCdsbCBzaG93IGVtb2ppIHN1Z2dlc3Rpb25zIHdoaWxzdCB0eXBpbmcgbWF0cml4IElEc1xuY29uc3QgRU1PSklfUkVHRVggPSBuZXcgUmVnRXhwKFwiKFwiICsgRU1PVElDT05fUkVHRVguc291cmNlICsgXCJ8KD86XnxcXFxccyk6WystXFxcXHddKjo/KSRcIiwgXCJnXCIpO1xuXG5pbnRlcmZhY2UgSVNvcnRlZEVtb2ppIHtcbiAgICBlbW9qaTogRW1vamk7XG4gICAgX29yZGVyQnk6IG51bWJlcjtcbn1cblxuY29uc3QgU09SVEVEX0VNT0pJOiBJU29ydGVkRW1vamlbXSA9IEVNT0pJLnNvcnQoKGEsIGIpID0+IHtcbiAgICBpZiAoYS5ncm91cCA9PT0gYi5ncm91cCkge1xuICAgICAgICByZXR1cm4gYS5vcmRlciEgLSBiLm9yZGVyITtcbiAgICB9XG4gICAgcmV0dXJuIGEuZ3JvdXAhIC0gYi5ncm91cCE7XG59KS5tYXAoKGVtb2ppLCBpbmRleCkgPT4gKHtcbiAgICBlbW9qaSxcbiAgICAvLyBJbmNsdWRlIHRoZSBpbmRleCBzbyB0aGF0IHdlIGNhbiBwcmVzZXJ2ZSB0aGUgb3JpZ2luYWwgb3JkZXJcbiAgICBfb3JkZXJCeTogaW5kZXgsXG59KSk7XG5cbmZ1bmN0aW9uIHNjb3JlKHF1ZXJ5OiBzdHJpbmcsIHNwYWNlOiBzdHJpbmdbXSB8IHN0cmluZyk6IG51bWJlciB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoc3BhY2UpKSB7XG4gICAgICAgIHJldHVybiBNYXRoLm1pbiguLi5zcGFjZS5tYXAoKHMpID0+IHNjb3JlKHF1ZXJ5LCBzKSkpO1xuICAgIH1cblxuICAgIGNvbnN0IGluZGV4ID0gc3BhY2UuaW5kZXhPZihxdWVyeSk7XG4gICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgICByZXR1cm4gSW5maW5pdHk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gY29sb25zVHJpbW1lZChzdHI6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgLy8gVHJpbSBvZmYgbGVhZGluZyBhbmQgcG90ZW50aWFsbHkgdHJhaWxpbmcgYDpgIHRvIGNvcnJlY3RseSBtYXRjaCB0aGUgZW1vamkgZGF0YSBhcyB0aGV5IGV4aXN0IGluIGVtb2ppYmFzZS5cbiAgICAvLyBOb3RlczogVGhlIHJlZ2V4IGlzIHBpbm5lZCB0byB0aGUgc3RhcnQgYW5kIGVuZCBvZiB0aGUgc3RyaW5nIHNvIHRoYXQgd2UgY2FuIHVzZSB0aGUgbGF6eS1jYXB0dXJpbmcgYCo/YCBtYXRjaGVyLlxuICAgIC8vIEl0IG5lZWRzIHRvIGJlIGxhenkgc28gdGhhdCB0aGUgdHJhaWxpbmcgYDpgIGlzIG5vdCBjYXB0dXJlZCBpbiB0aGUgcmVwbGFjZW1lbnQgZ3JvdXAsIGlmIGl0IGV4aXN0cy5cbiAgICByZXR1cm4gc3RyLnJlcGxhY2UoL146KC4qPyk6PyQvLCBcIiQxXCIpO1xufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBFbW9qaVByb3ZpZGVyIGV4dGVuZHMgQXV0b2NvbXBsZXRlUHJvdmlkZXIge1xuICAgIHB1YmxpYyBtYXRjaGVyOiBRdWVyeU1hdGNoZXI8SVNvcnRlZEVtb2ppPjtcbiAgICBwdWJsaWMgbmFtZU1hdGNoZXI6IFF1ZXJ5TWF0Y2hlcjxJU29ydGVkRW1vamk+O1xuICAgIHByaXZhdGUgcmVhZG9ubHkgcmVjZW50bHlVc2VkOiBFbW9qaVtdO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHJvb206IFJvb20sIHJlbmRlcmluZ1R5cGU/OiBUaW1lbGluZVJlbmRlcmluZ1R5cGUpIHtcbiAgICAgICAgc3VwZXIoeyBjb21tYW5kUmVnZXg6IEVNT0pJX1JFR0VYLCByZW5kZXJpbmdUeXBlIH0pO1xuICAgICAgICB0aGlzLm1hdGNoZXIgPSBuZXcgUXVlcnlNYXRjaGVyPElTb3J0ZWRFbW9qaT4oU09SVEVEX0VNT0pJLCB7XG4gICAgICAgICAgICBrZXlzOiBbXSxcbiAgICAgICAgICAgIGZ1bmNzOiBbKG8pID0+IG8uZW1vamkuc2hvcnRjb2Rlcy5tYXAoKHMpID0+IGA6JHtzfTpgKV0sXG4gICAgICAgICAgICAvLyBGb3IgbWF0Y2hpbmcgYWdhaW5zdCBhc2NpaSBlcXVpdmFsZW50c1xuICAgICAgICAgICAgc2hvdWxkTWF0Y2hXb3Jkc09ubHk6IGZhbHNlLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5uYW1lTWF0Y2hlciA9IG5ldyBRdWVyeU1hdGNoZXIoU09SVEVEX0VNT0pJLCB7XG4gICAgICAgICAgICBrZXlzOiBbXCJlbW9qaS5sYWJlbFwiXSxcbiAgICAgICAgICAgIC8vIEZvciByZW1vdmluZyBwdW5jdHVhdGlvblxuICAgICAgICAgICAgc2hvdWxkTWF0Y2hXb3Jkc09ubHk6IHRydWUsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMucmVjZW50bHlVc2VkID0gQXJyYXkuZnJvbShuZXcgU2V0KGZpbHRlckJvb2xlYW4ocmVjZW50LmdldCgpLm1hcChnZXRFbW9qaUZyb21Vbmljb2RlKSkpKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0Q29tcGxldGlvbnMoXG4gICAgICAgIHF1ZXJ5OiBzdHJpbmcsXG4gICAgICAgIHNlbGVjdGlvbjogSVNlbGVjdGlvblJhbmdlLFxuICAgICAgICBmb3JjZT86IGJvb2xlYW4sXG4gICAgICAgIGxpbWl0ID0gLTEsXG4gICAgKTogUHJvbWlzZTxJQ29tcGxldGlvbltdPiB7XG4gICAgICAgIGlmICghU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZShcIk1lc3NhZ2VDb21wb3NlcklucHV0LnN1Z2dlc3RFbW9qaVwiKSkge1xuICAgICAgICAgICAgcmV0dXJuIFtdOyAvLyBkb24ndCBnaXZlIGFueSBzdWdnZXN0aW9ucyBpZiB0aGUgdXNlciBkb2Vzbid0IHdhbnQgdGhlbVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNvbXBsZXRpb25zOiBJU29ydGVkRW1vamlbXSA9IFtdO1xuICAgICAgICBjb25zdCB7IGNvbW1hbmQsIHJhbmdlIH0gPSB0aGlzLmdldEN1cnJlbnRDb21tYW5kKHF1ZXJ5LCBzZWxlY3Rpb24pO1xuXG4gICAgICAgIGlmIChjb21tYW5kICYmIGNvbW1hbmRbMF0ubGVuZ3RoID4gMikge1xuICAgICAgICAgICAgY29uc3QgbWF0Y2hlZFN0cmluZyA9IGNvbW1hbmRbMF07XG4gICAgICAgICAgICBjb21wbGV0aW9ucyA9IHRoaXMubWF0Y2hlci5tYXRjaChtYXRjaGVkU3RyaW5nLCBsaW1pdCk7XG5cbiAgICAgICAgICAgIC8vIERvIHNlY29uZCBtYXRjaCB3aXRoIHNob3VsZE1hdGNoV29yZHNPbmx5IGluIG9yZGVyIHRvIG1hdGNoIGFnYWluc3QgJ25hbWUnXG4gICAgICAgICAgICBjb21wbGV0aW9ucyA9IGNvbXBsZXRpb25zLmNvbmNhdCh0aGlzLm5hbWVNYXRjaGVyLm1hdGNoKG1hdGNoZWRTdHJpbmcpKTtcblxuICAgICAgICAgICAgY29uc3Qgc29ydGVyczogTGlzdEl0ZXJhdGVlPElTb3J0ZWRFbW9qaT5bXSA9IFtdO1xuICAgICAgICAgICAgLy8gbWFrZSBzdXJlIHRoYXQgZW1vdGljb25zIGNvbWUgZmlyc3RcbiAgICAgICAgICAgIHNvcnRlcnMucHVzaCgoYykgPT4gc2NvcmUobWF0Y2hlZFN0cmluZywgYy5lbW9qaS5lbW90aWNvbiB8fCBcIlwiKSk7XG5cbiAgICAgICAgICAgIC8vIHRoZW4gc29ydCBieSBzY29yZSAoSW5maW5pdHkgaWYgbWF0Y2hlZFN0cmluZyBub3QgaW4gc2hvcnRjb2RlKVxuICAgICAgICAgICAgc29ydGVycy5wdXNoKChjKSA9PiBzY29yZShtYXRjaGVkU3RyaW5nLCBjLmVtb2ppLnNob3J0Y29kZXNbMF0pKTtcbiAgICAgICAgICAgIC8vIHRoZW4gc29ydCBieSBtYXggc2NvcmUgb2YgYWxsIHNob3J0Y29kZXMsIHRyaW0gb2ZmIHRoZSBgOmBcbiAgICAgICAgICAgIGNvbnN0IHRyaW1tZWRNYXRjaCA9IGNvbG9uc1RyaW1tZWQobWF0Y2hlZFN0cmluZyk7XG4gICAgICAgICAgICBzb3J0ZXJzLnB1c2goKGMpID0+IE1hdGgubWluKC4uLmMuZW1vamkuc2hvcnRjb2Rlcy5tYXAoKHMpID0+IHNjb3JlKHRyaW1tZWRNYXRjaCwgcykpKSk7XG4gICAgICAgICAgICAvLyBJZiB0aGUgbWF0Y2hlZFN0cmluZyBpcyBub3QgZW1wdHksIHNvcnQgYnkgbGVuZ3RoIG9mIHNob3J0Y29kZS4gRXhhbXBsZTpcbiAgICAgICAgICAgIC8vICBtYXRjaGVkU3RyaW5nID0gXCI6Ym9va21hcmtcIlxuICAgICAgICAgICAgLy8gIGNvbXBsZXRpb25zID0gW1wiOmJvb2ttYXJrOlwiLCBcIjpib29rbWFya190YWJzOlwiLCAuLi5dXG4gICAgICAgICAgICBpZiAobWF0Y2hlZFN0cmluZy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgc29ydGVycy5wdXNoKChjKSA9PiBjLmVtb2ppLnNob3J0Y29kZXNbMF0ubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEZpbmFsbHksIHNvcnQgYnkgb3JpZ2luYWwgb3JkZXJpbmdcbiAgICAgICAgICAgIHNvcnRlcnMucHVzaCgoYykgPT4gYy5fb3JkZXJCeSk7XG4gICAgICAgICAgICBjb21wbGV0aW9ucyA9IHNvcnRCeTxJU29ydGVkRW1vamk+KHVuaXEoY29tcGxldGlvbnMpLCBzb3J0ZXJzKTtcblxuICAgICAgICAgICAgY29tcGxldGlvbnMgPSBjb21wbGV0aW9ucy5zbGljZSgwLCBMSU1JVCk7XG5cbiAgICAgICAgICAgIC8vIERvIGEgc2Vjb25kIHNvcnQgdG8gcGxhY2UgZW1vamkgbWF0Y2hpbmcgd2l0aCBmcmVxdWVudGx5IHVzZWQgb25lIG9uIHRvcFxuICAgICAgICAgICAgY29uc3QgcmVjZW50bHlVc2VkQXV0b2NvbXBsZXRlOiBJU29ydGVkRW1vamlbXSA9IFtdO1xuICAgICAgICAgICAgdGhpcy5yZWNlbnRseVVzZWQuZm9yRWFjaCgoZW1vamkpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZW1vamkuc2hvcnRjb2Rlc1swXS5pbmRleE9mKHRyaW1tZWRNYXRjaCkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjZW50bHlVc2VkQXV0b2NvbXBsZXRlLnB1c2goeyBlbW9qaTogZW1vamksIF9vcmRlckJ5OiAwIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvL2lmIHRoZXJlIGlzIGFuIGV4YWN0IHNob3J0Y29kZSBtYXRjaCBpbiB0aGUgZnJlcXVlbnRseSB1c2VkIGVtb2ppcywgaXQgZ29lcyBiZWZvcmUgZXZlcnl0aGluZ1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZWNlbnRseVVzZWRBdXRvY29tcGxldGUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAocmVjZW50bHlVc2VkQXV0b2NvbXBsZXRlW2ldLmVtb2ppLnNob3J0Y29kZXNbMF0gPT09IHRyaW1tZWRNYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBleGFjdE1hdGNoRW1vamkgPSByZWNlbnRseVVzZWRBdXRvY29tcGxldGVbaV07XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSBpOyBqID4gMDsgai0tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWNlbnRseVVzZWRBdXRvY29tcGxldGVbal0gPSByZWNlbnRseVVzZWRBdXRvY29tcGxldGVbaiAtIDFdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJlY2VudGx5VXNlZEF1dG9jb21wbGV0ZVswXSA9IGV4YWN0TWF0Y2hFbW9qaTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb21wbGV0aW9ucyA9IHJlY2VudGx5VXNlZEF1dG9jb21wbGV0ZS5jb25jYXQoY29tcGxldGlvbnMpO1xuICAgICAgICAgICAgY29tcGxldGlvbnMgPSB1bmlxQnkoY29tcGxldGlvbnMsIFwiZW1vamlcIik7XG5cbiAgICAgICAgICAgIHJldHVybiBjb21wbGV0aW9ucy5tYXAoKGMpID0+ICh7XG4gICAgICAgICAgICAgICAgY29tcGxldGlvbjogYy5lbW9qaS51bmljb2RlLFxuICAgICAgICAgICAgICAgIGNvbXBvbmVudDogKFxuICAgICAgICAgICAgICAgICAgICA8UGlsbENvbXBsZXRpb24gdGl0bGU9e2A6JHtjLmVtb2ppLnNob3J0Y29kZXNbMF19OmB9IGFyaWEtbGFiZWw9e2MuZW1vamkudW5pY29kZX0+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3Bhbj57Yy5lbW9qaS51bmljb2RlfTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPC9QaWxsQ29tcGxldGlvbj5cbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIHJhbmdlOiByYW5nZSEsXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXROYW1lKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBcIvCfmIMgXCIgKyBfdChcImNvbW1vbnxlbW9qaVwiKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVuZGVyQ29tcGxldGlvbnMoY29tcGxldGlvbnM6IFJlYWN0LlJlYWN0Tm9kZVtdKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9BdXRvY29tcGxldGVfQ29tcGxldGlvbl9jb250YWluZXJfcGlsbFwiXG4gICAgICAgICAgICAgICAgcm9sZT1cInByZXNlbnRhdGlvblwiXG4gICAgICAgICAgICAgICAgYXJpYS1sYWJlbD17X3QoXCJjb21wb3NlcnxhdXRvY29tcGxldGV8ZW1vamlfYTExeVwiKX1cbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICB7Y29tcGxldGlvbnN9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgKTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBWUEsSUFBQUEsTUFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsT0FBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsU0FBQSxHQUFBSCxzQkFBQSxDQUFBQyxPQUFBO0FBRUEsSUFBQUcsa0JBQUEsR0FBQUgsT0FBQTtBQUVBLElBQUFJLGdCQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxxQkFBQSxHQUFBTixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQU0sYUFBQSxHQUFBUCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQU8sV0FBQSxHQUFBUCxPQUFBO0FBRUEsSUFBQVEsY0FBQSxHQUFBVCxzQkFBQSxDQUFBQyxPQUFBO0FBRUEsSUFBQVMsTUFBQSxHQUFBQyx1QkFBQSxDQUFBVixPQUFBO0FBQ0EsSUFBQVcsT0FBQSxHQUFBWCxPQUFBO0FBQWdELFNBQUFZLHlCQUFBQyxDQUFBLDZCQUFBQyxPQUFBLG1CQUFBQyxDQUFBLE9BQUFELE9BQUEsSUFBQUUsQ0FBQSxPQUFBRixPQUFBLFlBQUFGLHdCQUFBLFlBQUFBLENBQUFDLENBQUEsV0FBQUEsQ0FBQSxHQUFBRyxDQUFBLEdBQUFELENBQUEsS0FBQUYsQ0FBQTtBQUFBLFNBQUFILHdCQUFBRyxDQUFBLEVBQUFFLENBQUEsU0FBQUEsQ0FBQSxJQUFBRixDQUFBLElBQUFBLENBQUEsQ0FBQUksVUFBQSxTQUFBSixDQUFBLGVBQUFBLENBQUEsdUJBQUFBLENBQUEseUJBQUFBLENBQUEsV0FBQUssT0FBQSxFQUFBTCxDQUFBLFFBQUFHLENBQUEsR0FBQUosd0JBQUEsQ0FBQUcsQ0FBQSxPQUFBQyxDQUFBLElBQUFBLENBQUEsQ0FB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