matrix-react-sdk
Version:
SDK for matrix.org using React
319 lines (264 loc) • 35.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.generateCompletionDomId = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _classnames = _interopRequireDefault(require("classnames"));
var _lodash = require("lodash");
var _Autocompleter = _interopRequireWildcard(require("../../../autocomplete/Autocompleter"));
var _SettingsStore = _interopRequireDefault(require("../../../settings/SettingsStore"));
var _replaceableComponent = require("../../../utils/replaceableComponent");
var _dec, _class, _temp;
const COMPOSER_SELECTED = 0;
const MAX_PROVIDER_MATCHES = 20;
const generateCompletionDomId = number => `mx_Autocomplete_Completion_${number}`;
exports.generateCompletionDomId = generateCompletionDomId;
let Autocomplete = (_dec = (0, _replaceableComponent.replaceableComponent)("views.rooms.Autocomplete"), _dec(_class = (_temp = class Autocomplete extends _react.default.PureComponent
/*:: <IProps, IState>*/
{
constructor(props) {
super(props);
(0, _defineProperty2.default)(this, "autocompleter", void 0);
(0, _defineProperty2.default)(this, "queryRequested", void 0);
(0, _defineProperty2.default)(this, "debounceCompletionsRequest", void 0);
(0, _defineProperty2.default)(this, "containerRef", /*#__PURE__*/(0, _react.createRef)());
(0, _defineProperty2.default)(this, "hide", () => {
this.setState({
hide: true,
selectionOffset: 0,
completions: [],
completionList: []
});
});
(0, _defineProperty2.default)(this, "onCompletionClicked", (selectionOffset
/*: number*/
) =>
/*: boolean*/
{
if (this.countCompletions() === 0 || selectionOffset === COMPOSER_SELECTED) {
return false;
}
this.props.onConfirm(this.state.completionList[selectionOffset - 1]);
this.hide();
return true;
});
this.autocompleter = new _Autocompleter.default(props.room);
this.state = {
// list of completionResults, each containing completions
completions: [],
// array of completions, so we can look up current selection by offset quickly
completionList: [],
// how far down the completion list we are (THIS IS 1-INDEXED!)
selectionOffset: COMPOSER_SELECTED,
// whether we should show completions if they're available
shouldShowCompletions: true,
hide: false,
forceComplete: false
};
}
componentDidMount() {
this.applyNewProps();
}
applyNewProps(oldQuery
/*: string*/
, oldRoom
/*: Room*/
) {
if (oldRoom && this.props.room.roomId !== oldRoom.roomId) {
this.autocompleter.destroy();
this.autocompleter = new _Autocompleter.default(this.props.room);
} // Query hasn't changed so don't try to complete it
if (oldQuery === this.props.query) {
return;
}
this.complete(this.props.query, this.props.selection);
}
componentWillUnmount() {
this.autocompleter.destroy();
}
complete(query
/*: string*/
, selection
/*: ISelectionRange*/
) {
this.queryRequested = query;
if (this.debounceCompletionsRequest) {
clearTimeout(this.debounceCompletionsRequest);
}
if (query === "") {
this.setState({
// Clear displayed completions
completions: [],
completionList: [],
// Reset selected completion
selectionOffset: COMPOSER_SELECTED,
// Hide the autocomplete box
hide: true
});
return Promise.resolve(null);
}
let autocompleteDelay = _SettingsStore.default.getValue("autocompleteDelay"); // Don't debounce if we are already showing completions
if (this.state.completions.length > 0 || this.state.forceComplete) {
autocompleteDelay = 0;
}
return new Promise(resolve => {
this.debounceCompletionsRequest = setTimeout(() => {
resolve(this.processQuery(query, selection));
}, autocompleteDelay);
});
}
processQuery(query
/*: string*/
, selection
/*: ISelectionRange*/
) {
return this.autocompleter.getCompletions(query, selection, this.state.forceComplete, MAX_PROVIDER_MATCHES).then(completions => {
// Only ever process the completions for the most recent query being processed
if (query !== this.queryRequested) {
return;
}
this.processCompletions(completions);
});
}
processCompletions(completions
/*: IProviderCompletions[]*/
) {
const completionList = (0, _lodash.flatMap)(completions, provider => provider.completions); // Reset selection when completion list becomes empty.
let selectionOffset = COMPOSER_SELECTED;
if (completionList.length > 0) {
/* If the currently selected completion is still in the completion list,
try to find it and jump to it. If not, select composer.
*/
const currentSelection = this.state.selectionOffset === 0 ? null : this.state.completionList[this.state.selectionOffset - 1].completion;
selectionOffset = completionList.findIndex(completion => completion.completion === currentSelection);
if (selectionOffset === -1) {
selectionOffset = COMPOSER_SELECTED;
} else {
selectionOffset++; // selectionOffset is 1-indexed!
}
}
let hide = this.state.hide; // If `completion.command.command` is truthy, then a provider has matched with the query
const anyMatches = completions.some(completion => !!completion.command.command);
hide = !anyMatches;
this.setState({
completions,
completionList,
selectionOffset,
hide,
// Force complete is turned off each time since we can't edit the query in that case
forceComplete: false
});
}
hasSelection()
/*: boolean*/
{
return this.countCompletions() > 0 && this.state.selectionOffset !== 0;
}
countCompletions()
/*: number*/
{
return this.state.completionList.length;
} // called from MessageComposerInput
moveSelection(delta
/*: number*/
) {
const completionCount = this.countCompletions();
if (completionCount === 0) return; // there are no items to move the selection through
// Note: selectionOffset 0 represents the unsubstituted text, while 1 means first pill selected
const index = (this.state.selectionOffset + delta + completionCount + 1) % (completionCount + 1);
this.setSelection(index);
}
onEscape(e
/*: KeyboardEvent*/
)
/*: boolean*/
{
const completionCount = this.countCompletions();
if (completionCount === 0) {
// autocomplete is already empty, so don't preventDefault
return;
}
e.preventDefault(); // selectionOffset = 0, so we don't end up completing when autocomplete is hidden
this.hide();
}
forceComplete() {
return new Promise(resolve => {
this.setState({
forceComplete: true,
hide: false
}, () => {
this.complete(this.props.query, this.props.selection).then(() => {
resolve(this.countCompletions());
});
});
});
}
setSelection(selectionOffset
/*: number*/
) {
this.setState({
selectionOffset,
hide: false
});
if (this.props.onSelectionChange) {
this.props.onSelectionChange(this.state.completionList[selectionOffset - 1], selectionOffset - 1);
}
}
componentDidUpdate(prevProps
/*: IProps*/
) {
this.applyNewProps(prevProps.query, prevProps.room); // this is the selected completion, so scroll it into view if needed
const selectedCompletion = this.refs[`completion${this.state.selectionOffset}`];
if (selectedCompletion) {
selectedCompletion.scrollIntoView({
behavior: "auto",
block: "nearest"
});
} else if (this.containerRef.current) {
this.containerRef.current.scrollTo({
top: 0
});
}
}
render() {
let position = 1;
const renderedCompletions = this.state.completions.map((completionResult, i) => {
const completions = completionResult.completions.map((completion, j) => {
const selected = position === this.state.selectionOffset;
const className = (0, _classnames.default)('mx_Autocomplete_Completion', {
selected
});
const componentPosition = position;
position++;
const onClick = () => {
this.onCompletionClicked(componentPosition);
};
return /*#__PURE__*/_react.default.cloneElement(completion.component, {
"key": j,
"ref": `completion${componentPosition}`,
"id": generateCompletionDomId(componentPosition - 1),
// 0 index the completion IDs
className,
onClick,
"aria-selected": selected
});
});
return completions.length > 0 ? /*#__PURE__*/_react.default.createElement("div", {
key: i,
className: "mx_Autocomplete_ProviderSection"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_Autocomplete_provider_name"
}, completionResult.provider.getName()), completionResult.provider.renderCompletions(completions)) : null;
}).filter(completion => !!completion);
return !this.state.hide && renderedCompletions.length > 0 ? /*#__PURE__*/_react.default.createElement("div", {
className: "mx_Autocomplete",
ref: this.containerRef
}, renderedCompletions) : null;
}
}, _temp)) || _class);
exports.default = Autocomplete;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3ZpZXdzL3Jvb21zL0F1dG9jb21wbGV0ZS50c3giXSwibmFtZXMiOlsiQ09NUE9TRVJfU0VMRUNURUQiLCJNQVhfUFJPVklERVJfTUFUQ0hFUyIsImdlbmVyYXRlQ29tcGxldGlvbkRvbUlkIiwibnVtYmVyIiwiQXV0b2NvbXBsZXRlIiwiUmVhY3QiLCJQdXJlQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJwcm9wcyIsInNldFN0YXRlIiwiaGlkZSIsInNlbGVjdGlvbk9mZnNldCIsImNvbXBsZXRpb25zIiwiY29tcGxldGlvbkxpc3QiLCJjb3VudENvbXBsZXRpb25zIiwib25Db25maXJtIiwic3RhdGUiLCJhdXRvY29tcGxldGVyIiwiQXV0b2NvbXBsZXRlciIsInJvb20iLCJzaG91bGRTaG93Q29tcGxldGlvbnMiLCJmb3JjZUNvbXBsZXRlIiwiY29tcG9uZW50RGlkTW91bnQiLCJhcHBseU5ld1Byb3BzIiwib2xkUXVlcnkiLCJvbGRSb29tIiwicm9vbUlkIiwiZGVzdHJveSIsInF1ZXJ5IiwiY29tcGxldGUiLCJzZWxlY3Rpb24iLCJjb21wb25lbnRXaWxsVW5tb3VudCIsInF1ZXJ5UmVxdWVzdGVkIiwiZGVib3VuY2VDb21wbGV0aW9uc1JlcXVlc3QiLCJjbGVhclRpbWVvdXQiLCJQcm9taXNlIiwicmVzb2x2ZSIsImF1dG9jb21wbGV0ZURlbGF5IiwiU2V0dGluZ3NTdG9yZSIsImdldFZhbHVlIiwibGVuZ3RoIiwic2V0VGltZW91dCIsInByb2Nlc3NRdWVyeSIsImdldENvbXBsZXRpb25zIiwidGhlbiIsInByb2Nlc3NDb21wbGV0aW9ucyIsInByb3ZpZGVyIiwiY3VycmVudFNlbGVjdGlvbiIsImNvbXBsZXRpb24iLCJmaW5kSW5kZXgiLCJhbnlNYXRjaGVzIiwic29tZSIsImNvbW1hbmQiLCJoYXNTZWxlY3Rpb24iLCJtb3ZlU2VsZWN0aW9uIiwiZGVsdGEiLCJjb21wbGV0aW9uQ291bnQiLCJpbmRleCIsInNldFNlbGVjdGlvbiIsIm9uRXNjYXBlIiwiZSIsInByZXZlbnREZWZhdWx0Iiwib25TZWxlY3Rpb25DaGFuZ2UiLCJjb21wb25lbnREaWRVcGRhdGUiLCJwcmV2UHJvcHMiLCJzZWxlY3RlZENvbXBsZXRpb24iLCJyZWZzIiwic2Nyb2xsSW50b1ZpZXciLCJiZWhhdmlvciIsImJsb2NrIiwiY29udGFpbmVyUmVmIiwiY3VycmVudCIsInNjcm9sbFRvIiwidG9wIiwicmVuZGVyIiwicG9zaXRpb24iLCJyZW5kZXJlZENvbXBsZXRpb25zIiwibWFwIiwiY29tcGxldGlvblJlc3VsdCIsImkiLCJqIiwic2VsZWN0ZWQiLCJjbGFzc05hbWUiLCJjb21wb25lbnRQb3NpdGlvbiIsIm9uQ2xpY2siLCJvbkNvbXBsZXRpb25DbGlja2VkIiwiY2xvbmVFbGVtZW50IiwiY29tcG9uZW50IiwiZ2V0TmFtZSIsInJlbmRlckNvbXBsZXRpb25zIiwiZmlsdGVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7O0FBaUJBOztBQUNBOztBQUNBOztBQUNBOztBQUdBOztBQUVBOzs7O0FBRUEsTUFBTUEsaUJBQWlCLEdBQUcsQ0FBMUI7QUFDQSxNQUFNQyxvQkFBb0IsR0FBRyxFQUE3Qjs7QUFFTyxNQUFNQyx1QkFBdUIsR0FBSUMsTUFBRCxJQUFhLDhCQUE2QkEsTUFBTyxFQUFqRjs7O0lBd0JjQyxZLFdBRHBCLGdEQUFxQiwwQkFBckIsQyx5QkFBRCxNQUNxQkEsWUFEckIsU0FDMENDLGVBQU1DO0FBRGhEO0FBQzhFO0FBTTFFQyxFQUFBQSxXQUFXLENBQUNDLEtBQUQsRUFBUTtBQUNmLFVBQU1BLEtBQU47QUFEZTtBQUFBO0FBQUE7QUFBQSxxRUFGSSx1QkFFSjtBQUFBLGdEQTJKWixNQUFNO0FBQ1QsV0FBS0MsUUFBTCxDQUFjO0FBQ1ZDLFFBQUFBLElBQUksRUFBRSxJQURJO0FBRVZDLFFBQUFBLGVBQWUsRUFBRSxDQUZQO0FBR1ZDLFFBQUFBLFdBQVcsRUFBRSxFQUhIO0FBSVZDLFFBQUFBLGNBQWMs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QUFOLENBQW1CdEMsVUFBVSxDQUFDdUMsU0FBOUIsRUFBeUM7QUFDNUMsaUJBQU9QLENBRHFDO0FBRTVDLGlCQUFRLGFBQVlHLGlCQUFrQixFQUZNO0FBRzVDLGdCQUFNakYsdUJBQXVCLENBQUNpRixpQkFBaUIsR0FBRyxDQUFyQixDQUhlO0FBR1U7QUFDdERELFVBQUFBLFNBSjRDO0FBSzVDRSxVQUFBQSxPQUw0QztBQU01QywyQkFBaUJIO0FBTjJCLFNBQXpDLENBQVA7QUFRSCxPQWxCbUIsQ0FBcEI7QUFxQkEsYUFBT3JFLFdBQVcsQ0FBQzRCLE1BQVosR0FBcUIsQ0FBckIsZ0JBQ0g7QUFBSyxRQUFBLEdBQUcsRUFBRXVDLENBQVY7QUFBYSxRQUFBLFNBQVMsRUFBQztBQUF2QixzQkFDSTtBQUFLLFFBQUEsU0FBUyxFQUFDO0FBQWYsU0FBaURELGdCQUFnQixDQUFDaEMsUUFBakIsQ0FBMEIwQyxPQUExQixFQUFqRCxDQURKLEVBRU1WLGdCQUFnQixDQUFDaEMsUUFBakIsQ0FBMEIyQyxpQkFBMUIsQ0FBNEM3RSxXQUE1QyxDQUZOLENBREcsR0FLSCxJQUxKO0FBTUgsS0E1QjJCLEVBNEJ6QjhFLE1BNUJ5QixDQTRCakIxQyxVQUFELElBQWdCLENBQUMsQ0FBQ0EsVUE1QkEsQ0FBNUI7QUE4QkEsV0FBTyxDQUFDLEtBQUtoQyxLQUFMLENBQVdOLElBQVosSUFBb0JrRSxtQkFBbUIsQ0FBQ3BDLE1BQXBCLEdBQTZCLENBQWpELGdCQUNIO0FBQUssTUFBQSxTQUFTLEVBQUMsaUJBQWY7QUFBaUMsTUFBQSxHQUFHLEVBQUUsS0FBSzhCO0FBQTNDLE9BQ01NLG1CQUROLENBREcsR0FJSCxJQUpKO0FBS0g7O0FBN1B5RSxDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDE2IEF2aXJhbCBEYXNndXB0YVxuQ29weXJpZ2h0IDIwMTcgTmV3IFZlY3RvciBMdGRcblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4qL1xuXG5pbXBvcnQgUmVhY3QsIHtjcmVhdGVSZWYsIEtleWJvYXJkRXZlbnR9IGZyb20gJ3JlYWN0JztcbmltcG9ydCBjbGFzc05hbWVzIGZyb20gJ2NsYXNzbmFtZXMnO1xuaW1wb3J0IHtmbGF0TWFwfSBmcm9tIFwibG9kYXNoXCI7XG5pbXBvcnQge0lDb21wbGV0aW9uLCBJU2VsZWN0aW9uUmFuZ2UsIElQcm92aWRlckNvbXBsZXRpb25zfSBmcm9tICcuLi8uLi8uLi9hdXRvY29tcGxldGUvQXV0b2NvbXBsZXRlcic7XG5pbXBvcnQge1Jvb219IGZyb20gJ21hdHJpeC1qcy1zZGsvc3JjL21vZGVscy9yb29tJztcblxuaW1wb3J0IFNldHRpbmdzU3RvcmUgZnJvbSBcIi4uLy4uLy4uL3NldHRpbmdzL1NldHRpbmdzU3RvcmVcIjtcbmltcG9ydCBBdXRvY29tcGxldGVyIGZyb20gJy4uLy4uLy4uL2F1dG9jb21wbGV0ZS9BdXRvY29tcGxldGVyJztcbmltcG9ydCB7cmVwbGFjZWFibGVDb21wb25lbnR9IGZyb20gXCIuLi8uLi8uLi91dGlscy9yZXBsYWNlYWJsZUNvbXBvbmVudFwiO1xuXG5jb25zdCBDT01QT1NFUl9TRUxFQ1RFRCA9IDA7XG5jb25zdCBNQVhfUFJPVklERVJfTUFUQ0hFUyA9IDIwO1xuXG5leHBvcnQgY29uc3QgZ2VuZXJhdGVDb21wbGV0aW9uRG9tSWQgPSAobnVtYmVyKSA9PiBgbXhfQXV0b2NvbXBsZXRlX0NvbXBsZXRpb25fJHtudW1iZXJ9YDtcblxuaW50ZXJmYWNlIElQcm9wcyB7XG4gICAgLy8gdGhlIHF1ZXJ5IHN0cmluZyBmb3Igd2hpY2ggdG8gc2hvdyBhdXRvY29tcGxldGUgc3VnZ2VzdGlvbnNcbiAgICBxdWVyeTogc3RyaW5nO1xuICAgIC8vIG1ldGhvZCBpbnZva2VkIHdpdGggcmFuZ2UgYW5kIHRleHQgY29udGVudCB3aGVuIGNvbXBsZXRpb24gaXMgY29uZmlybWVkXG4gICAgb25Db25maXJtOiAoSUNvbXBsZXRpb24pID0+IHZvaWQ7XG4gICAgLy8gbWV0aG9kIGludm9rZWQgd2hlbiBzZWxlY3RlZCAoaWYgYW55KSBjb21wbGV0aW9uIGNoYW5nZXNcbiAgICBvblNlbGVjdGlvbkNoYW5nZT86IChJQ29tcGxldGlvbiwgbnVtYmVyKSA9PiB2b2lkO1xuICAgIHNlbGVjdGlvbjogSVNlbGVjdGlvblJhbmdlO1xuICAgIC8vIFRoZSByb29tIGluIHdoaWNoIHdlJ3JlIGF1dG9jb21wbGV0aW5nXG4gICAgcm9vbTogUm9vbTtcbn1cblxuaW50ZXJmYWNlIElTdGF0ZSB7XG4gICAgY29tcGxldGlvbnM6IElQcm92aWRlckNvbXBsZXRpb25zW107XG4gICAgY29tcGxldGlvbkxpc3Q6IElDb21wbGV0aW9uW107XG4gICAgc2VsZWN0aW9uT2Zmc2V0OiBudW1iZXI7XG4gICAgc2hvdWxkU2hvd0NvbXBsZXRpb25zOiBib29sZWFuO1xuICAgIGhpZGU6IGJvb2xlYW47XG4gICAgZm9yY2VDb21wbGV0ZTogYm9vbGVhbjtcbn1cblxuQHJlcGxhY2VhYmxlQ29tcG9uZW50KFwidmlld3Mucm9vbXMuQXV0b2NvbXBsZXRlXCIpXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBdXRvY29tcGxldGUgZXh0ZW5kcyBSZWFjdC5QdXJlQ29tcG9uZW50PElQcm9wcywgSVN0YXRlPiB7XG4gICAgYXV0b2NvbXBsZXRlcjogQXV0b2NvbXBsZXRlcjtcbiAgICBxdWVyeVJlcXVlc3RlZDogc3RyaW5nO1xuICAgIGRlYm91bmNlQ29tcGxldGlvbnNSZXF1ZXN0OiBOb2RlSlMuVGltZW91dDtcbiAgICBwcml2YXRlIGNvbnRhaW5lclJlZiA9IGNyZWF0ZVJlZjxIVE1MRGl2RWxlbWVudD4oKTtcblxuICAgIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgICAgIHN1cGVyKHByb3BzKTtcblxuICAgICAgICB0aGlzLmF1dG9jb21wbGV0ZXIgPSBuZXcgQXV0b2NvbXBsZXRlcihwcm9wcy5yb29tKTtcblxuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgLy8gbGlzdCBvZiBjb21wbGV0aW9uUmVzdWx0cywgZWFjaCBjb250YWluaW5nIGNvbXBsZXRpb25zXG4gICAgICAgICAgICBjb21wbGV0aW9uczogW10sXG5cbiAgICAgICAgICAgIC8vIGFycmF5IG9mIGNvbXBsZXRpb25zLCBzbyB3ZSBjYW4gbG9vayB1cCBjdXJyZW50IHNlbGVjdGlvbiBieSBvZmZzZXQgcXVpY2tseVxuICAgICAgICAgICAgY29tcGxldGlvbkxpc3Q6IFtdLFxuXG4gICAgICAgICAgICAvLyBob3cgZmFyIGRvd24gdGhlIGNvbXBsZXRpb24gbGlzdCB3ZSBhcmUgKFRISVMgSVMgMS1JTkRFWEVEISlcbiAgICAgICAgICAgIHNlbGVjdGlvbk9mZnNldDogQ09NUE9TRVJfU0VMRUNURUQsXG5cbiAgICAgICAgICAgIC8vIHdoZXRoZXIgd2Ugc2hvdWxkIHNob3cgY29tcGxldGlvbnMgaWYgdGhleSdyZSBhdmFpbGFibGVcbiAgICAgICAgICAgIHNob3VsZFNob3dDb21wbGV0aW9uczogdHJ1ZSxcblxuICAgICAgICAgICAgaGlkZTogZmFsc2UsXG5cbiAgICAgICAgICAgIGZvcmNlQ29tcGxldGU6IGZhbHNlLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGNvbXBvbmVudERpZE1vdW50KCkge1xuICAgICAgICB0aGlzLmFwcGx5TmV3UHJvcHMoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFwcGx5TmV3UHJvcHMob2xkUXVlcnk/OiBzdHJpbmcsIG9sZFJvb20/OiBSb29tKSB7XG4gICAgICAgIGlmIChvbGRSb29tICYmIHRoaXMucHJvcHMucm9vbS5yb29tSWQgIT09IG9sZFJvb20ucm9vbUlkKSB7XG4gICAgICAgICAgICB0aGlzLmF1dG9jb21wbGV0ZXIuZGVzdHJveSgpO1xuICAgICAgICAgICAgdGhpcy5hdXRvY29tcGxldGVyID0gbmV3IEF1dG9jb21wbGV0ZXIodGhpcy5wcm9wcy5yb29tKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFF1ZXJ5IGhhc24ndCBjaGFuZ2VkIHNvIGRvbid0IHRyeSB0byBjb21wbGV0ZSBpdFxuICAgICAgICBpZiAob2xkUXVlcnkgPT09IHRoaXMucHJvcHMucXVlcnkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY29tcGxldGUodGhpcy5wcm9wcy5xdWVyeSwgdGhpcy5wcm9wcy5zZWxlY3Rpb24pO1xuICAgIH1cblxuICAgIGNvbXBvbmVudFdpbGxVbm1vdW50KCkge1xuICAgICAgICB0aGlzLmF1dG9jb21wbGV0ZXIuZGVzdHJveSgpO1xuICAgIH1cblxuICAgIGNvbXBsZXRlKHF1ZXJ5OiBzdHJpbmcsIHNlbGVjdGlvbjogSVNlbGVjdGlvblJhbmdlKSB7XG4gICAgICAgIHRoaXMucXVlcnlSZXF1ZXN0ZWQgPSBxdWVyeTtcbiAgICAgICAgaWYgKHRoaXMuZGVib3VuY2VDb21wbGV0aW9uc1JlcXVlc3QpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLmRlYm91bmNlQ29tcGxldGlvbnNSZXF1ZXN0KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocXVlcnkgPT09IFwiXCIpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgIC8vIENsZWFyIGRpc3BsYXllZCBjb21wbGV0aW9uc1xuICAgICAgICAgICAgICAgIGNvbXBsZXRpb25zOiBbXSxcbiAgICAgICAgICAgICAgICBjb21wbGV0aW9uTGlzdDogW10sXG4gICAgICAgICAgICAgICAgLy8gUmVzZXQgc2VsZWN0ZWQgY29tcGxldGlvblxuICAgICAgICAgICAgICAgIHNlbGVjdGlvbk9mZnNldDogQ09NUE9TRVJfU0VMRUNURUQsXG4gICAgICAgICAgICAgICAgLy8gSGlkZSB0aGUgYXV0b2NvbXBsZXRlIGJveFxuICAgICAgICAgICAgICAgIGhpZGU6IHRydWUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGF1dG9jb21wbGV0ZURlbGF5ID0gU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZShcImF1dG9jb21wbGV0ZURlbGF5XCIpO1xuXG4gICAgICAgIC8vIERvbid0IGRlYm91bmNlIGlmIHdlIGFyZSBhbHJlYWR5IHNob3dpbmcgY29tcGxldGlvbnNcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUuY29tcGxldGlvbnMubGVuZ3RoID4gMCB8fCB0aGlzLnN0YXRlLmZvcmNlQ29tcGxldGUpIHtcbiAgICAgICAgICAgIGF1dG9jb21wbGV0ZURlbGF5ID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgdGhpcy5kZWJvdW5jZUNvbXBsZXRpb25zUmVxdWVzdCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlc29sdmUodGhpcy5wcm9jZXNzUXVlcnkocXVlcnksIHNlbGVjdGlvbikpO1xuICAgICAgICAgICAgfSwgYXV0b2NvbXBsZXRlRGVsYXkpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcm9jZXNzUXVlcnkocXVlcnk6IHN0cmluZywgc2VsZWN0aW9uOiBJU2VsZWN0aW9uUmFuZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0b2NvbXBsZXRlci5nZXRDb21wbGV0aW9ucyhcbiAgICAgICAgICAgIHF1ZXJ5LCBzZWxlY3Rpb24sIHRoaXMuc3RhdGUuZm9yY2VDb21wbGV0ZSwgTUFYX1BST1ZJREVSX01BVENIRVMsXG4gICAgICAgICkudGhlbigoY29tcGxldGlvbnMpID0+IHtcbiAgICAgICAgICAgIC8vIE9ubHkgZXZlciBwcm9jZXNzIHRoZSBjb21wbGV0aW9ucyBmb3IgdGhlIG1vc3QgcmVjZW50IHF1ZXJ5IGJlaW5nIHByb2Nlc3NlZFxuICAgICAgICAgICAgaWYgKHF1ZXJ5ICE9PSB0aGlzLnF1ZXJ5UmVxdWVzdGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5wcm9jZXNzQ29tcGxldGlvbnMoY29tcGxldGlvbnMpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcm9jZXNzQ29tcGxldGlvbnMoY29tcGxldGlvbnM6IElQcm92aWRlckNvbXBsZXRpb25zW10pIHtcbiAgICAgICAgY29uc3QgY29tcGxldGlvbkxpc3QgPSBmbGF0TWFwKGNvbXBsZXRpb25zLCAocHJvdmlkZXIpID0+IHByb3ZpZGVyLmNvbXBsZXRpb25zKTtcblxuICAgICAgICAvLyBSZXNldCBzZWxlY3Rpb24gd2hlbiBjb21wbGV0aW9uIGxpc3QgYmVjb21lcyBlbXB0eS5cbiAgICAgICAgbGV0IHNlbGVjdGlvbk9mZnNldCA9IENPTVBPU0VSX1NFTEVDVEVEO1xuICAgICAgICBpZiAoY29tcGxldGlvbkxpc3QubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgLyogSWYgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBjb21wbGV0aW9uIGlzIHN0aWxsIGluIHRoZSBjb21wbGV0aW9uIGxpc3QsXG4gICAgICAgICAgICAgdHJ5IHRvIGZpbmQgaXQgYW5kIGp1bXAgdG8gaXQuIElmIG5vdCwgc2VsZWN0IGNvbXBvc2VyLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBjb25zdCBjdXJyZW50U2VsZWN0aW9uID0gdGhpcy5zdGF0ZS5zZWxlY3Rpb25PZmZzZXQgPT09IDAgPyBudWxsIDpcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLmNvbXBsZXRpb25MaXN0W3RoaXMuc3RhdGUuc2VsZWN0aW9uT2Zmc2V0IC0gMV0uY29tcGxldGlvbjtcbiAgICAgICAgICAgIHNlbGVjdGlvbk9mZnNldCA9IGNvbXBsZXRpb25MaXN0LmZpbmRJbmRleChcbiAgICAgICAgICAgICAgICAoY29tcGxldGlvbikgPT4gY29tcGxldGlvbi5jb21wbGV0aW9uID09PSBjdXJyZW50U2VsZWN0aW9uKTtcbiAgICAgICAgICAgIGlmIChzZWxlY3Rpb25PZmZzZXQgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uT2Zmc2V0ID0gQ09NUE9TRVJfU0VMRUNURUQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGVjdGlvbk9mZnNldCsrOyAvLyBzZWxlY3Rpb25PZmZzZXQgaXMgMS1pbmRleGVkIVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGhpZGUgPSB0aGlzLnN0YXRlLmhpZGU7XG4gICAgICAgIC8vIElmIGBjb21wbGV0aW9uLmNvbW1hbmQuY29tbWFuZGAgaXMgdHJ1dGh5LCB0aGVuIGEgcHJvdmlkZXIgaGFzIG1hdGNoZWQgd2l0aCB0aGUgcXVlcnlcbiAgICAgICAgY29uc3QgYW55TWF0Y2hlcyA9IGNvbXBsZXRpb25zLnNvbWUoKGNvbXBsZXRpb24pID0+ICEhY29tcGxldGlvbi5jb21tYW5kLmNvbW1hbmQpO1xuICAgICAgICBoaWRlID0gIWFueU1hdGNoZXM7XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBjb21wbGV0aW9ucyxcbiAgICAgICAgICAgIGNvbXBsZXRpb25MaXN0LFxuICAgICAgICAgICAgc2VsZWN0aW9uT2Zmc2V0LFxuICAgICAgICAgICAgaGlkZSxcbiAgICAgICAgICAgIC8vIEZvcmNlIGNvbXBsZXRlIGlzIHR1cm5lZCBvZmYgZWFjaCB0aW1lIHNpbmNlIHdlIGNhbid0IGVkaXQgdGhlIHF1ZXJ5IGluIHRoYXQgY2FzZVxuICAgICAgICAgICAgZm9yY2VDb21wbGV0ZTogZmFsc2UsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGhhc1NlbGVjdGlvbigpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY291bnRDb21wbGV0aW9ucygpID4gMCAmJiB0aGlzLnN0YXRlLnNlbGVjdGlvbk9mZnNldCAhPT0gMDtcbiAgICB9XG5cbiAgICBjb3VudENvbXBsZXRpb25zKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlLmNvbXBsZXRpb25MaXN0Lmxlbmd0aDtcbiAgICB9XG5cbiAgICAvLyBjYWxsZWQgZnJvbSBNZXNzYWdlQ29tcG9zZXJJbnB1dFxuICAgIG1vdmVTZWxlY3Rpb24oZGVsdGE6IG51bWJlcikge1xuICAgICAgICBjb25zdCBjb21wbGV0aW9uQ291bnQgPSB0aGlzLmNvdW50Q29tcGxldGlvbnMoKTtcbiAgICAgICAgaWYgKGNvbXBsZXRpb25Db3VudCA9PT0gMCkgcmV0dXJuOyAvLyB0aGVyZSBhcmUgbm8gaXRlbXMgdG8gbW92ZSB0aGUgc2VsZWN0aW9uIHRocm91Z2hcblxuICAgICAgICAvLyBOb3RlOiBzZWxlY3Rpb25PZmZzZXQgMCByZXByZXNlbnRzIHRoZSB1bnN1YnN0aXR1dGVkIHRleHQsIHdoaWxlIDEgbWVhbnMgZmlyc3QgcGlsbCBzZWxlY3RlZFxuICAgICAgICBjb25zdCBpbmRleCA9ICh0aGlzLnN0YXRlLnNlbGVjdGlvbk9mZnNldCArIGRlbHRhICsgY29tcGxldGlvbkNvdW50ICsgMSkgJSAoY29tcGxldGlvbkNvdW50ICsgMSk7XG4gICAgICAgIHRoaXMuc2V0U2VsZWN0aW9uKGluZGV4KTtcbiAgICB9XG5cbiAgICBvbkVzY2FwZShlOiBLZXlib2FyZEV2ZW50KTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IGNvbXBsZXRpb25Db3VudCA9IHRoaXMuY291bnRDb21wbGV0aW9ucygpO1xuICAgICAgICBpZiAoY29tcGxldGlvbkNvdW50ID09PSAwKSB7XG4gICAgICAgICAgICAvLyBhdXRvY29tcGxldGUgaXMgYWxyZWFkeSBlbXB0eSwgc28gZG9uJ3QgcHJldmVudERlZmF1bHRcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAvLyBzZWxlY3Rpb25PZmZzZXQgPSAwLCBzbyB3ZSBkb24ndCBlbmQgdXAgY29tcGxldGluZyB3aGVuIGF1dG9jb21wbGV0ZSBpcyBoaWRkZW5cbiAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgfVxuXG4gICAgaGlkZSA9ICgpID0+IHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBoaWRlOiB0cnVlLFxuICAgICAgICAgICAgc2VsZWN0aW9uT2Zmc2V0OiAwLFxuICAgICAgICAgICAgY29tcGxldGlvbnM6IFtdLFxuICAgICAgICAgICAgY29tcGxldGlvbkxpc3Q6IFtdLFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgZm9yY2VDb21wbGV0ZSgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICBmb3JjZUNvbXBsZXRlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGhpZGU6IGZhbHNlLFxuICAgICAgICAgICAgfSwgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuY29tcGxldGUodGhpcy5wcm9wcy5xdWVyeSwgdGhpcy5wcm9wcy5zZWxlY3Rpb24pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMuY291bnRDb21wbGV0aW9ucygpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBvbkNvbXBsZXRpb25DbGlja2VkID0gKHNlbGVjdGlvbk9mZnNldDogbnVtYmVyKTogYm9vbGVhbiA9PiB7XG4gICAgICAgIGlmICh0aGlzLmNvdW50Q29tcGxldGlvbnMoKSA9PT0gMCB8fCBzZWxlY3Rpb25PZmZzZXQgPT09IENPTVBPU0VSX1NFTEVDVEVEKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnByb3BzLm9uQ29uZmlybSh0aGlzLnN0YXRlLmNvbXBsZXRpb25MaXN0W3NlbGVjdGlvbk9mZnNldCAtIDFdKTtcbiAgICAgICAgdGhpcy5oaWRlKCk7XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcblxuICAgIHNldFNlbGVjdGlvbihzZWxlY3Rpb25PZmZzZXQ6IG51bWJlcikge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtzZWxlY3Rpb25PZmZzZXQsIGhpZGU6IGZhbHNlfSk7XG4gICAgICAgIGlmICh0aGlzLnByb3BzLm9uU2VsZWN0aW9uQ2hhbmdlKSB7XG4gICAgICAgICAgICB0aGlzLnByb3BzLm9uU2VsZWN0aW9uQ2hhbmdlKHRoaXMuc3RhdGUuY29tcGxldGlvbkxpc3Rbc2VsZWN0aW9uT2Zmc2V0IC0gMV0sIHNlbGVjdGlvbk9mZnNldCAtIDEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29tcG9uZW50RGlkVXBkYXRlKHByZXZQcm9wczogSVByb3BzKSB7XG4gICAgICAgIHRoaXMuYXBwbHlOZXdQcm9wcyhwcmV2UHJvcHMucXVlcnksIHByZXZQcm9wcy5yb29tKTtcbiAgICAgICAgLy8gdGhpcyBpcyB0aGUgc2VsZWN0ZWQgY29tcGxldGlvbiwgc28gc2Nyb2xsIGl0IGludG8gdmlldyBpZiBuZWVkZWRcbiAgICAgICAgY29uc3Qgc2VsZWN0ZWRDb21wbGV0aW9uID0gdGhpcy5yZWZzW2Bjb21wbGV0aW9uJHt0aGlzLnN0YXRlLnNlbGVjdGlvbk9mZnNldH1gXSBhcyBIVE1MRWxlbWVudDtcblxuICAgICAgICBpZiAoc2VsZWN0ZWRDb21wbGV0aW9uKSB7XG4gICAgICAgICAgICBzZWxlY3RlZENvbXBsZXRpb24uc2Nyb2xsSW50b1ZpZXcoe1xuICAgICAgICAgICAgICAgIGJlaGF2aW9yOiBcImF1dG9cIixcbiAgICAgICAgICAgICAgICBibG9jazogXCJuZWFyZXN0XCIsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmNvbnRhaW5lclJlZi5jdXJyZW50KSB7XG4gICAgICAgICAgICB0aGlzLmNvbnRhaW5lclJlZi5jdXJyZW50LnNjcm9sbFRvKHsgdG9wOiAwIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmVuZGVyKCkge1xuICAgICAgICBsZXQgcG9zaXRpb24gPSAxO1xuICAgICAgICBjb25zdCByZW5kZXJlZENvbXBsZXRpb25zID0gdGhpcy5zdGF0ZS5jb21wbGV0aW9ucy5tYXAoKGNvbXBsZXRpb25SZXN1bHQsIGkpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbXBsZXRpb25zID0gY29tcGxldGlvblJlc3VsdC5jb21wbGV0aW9ucy5tYXAoKGNvbXBsZXRpb24sIGopID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzZWxlY3RlZCA9IHBvc2l0aW9uID09PSB0aGlzLnN0YXRlLnNlbGVjdGlvbk9mZnNldDtcbiAgICAgICAgICAgICAgICBjb25zdCBjbGFzc05hbWUgPSBjbGFzc05hbWVzKCdteF9BdXRvY29tcGxldGVfQ29tcGxldGlvbicsIHtzZWxlY3RlZH0pO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbXBvbmVudFBvc2l0aW9uID0gcG9zaXRpb247XG4gICAgICAgICAgICAgICAgcG9zaXRpb24rKztcblxuICAgICAgICAgICAgICAgIGNvbnN0IG9uQ2xpY2sgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25Db21wbGV0aW9uQ2xpY2tlZChjb21wb25lbnRQb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBSZWFjdC5jbG9uZUVsZW1lbnQoY29tcGxldGlvbi5jb21wb25lbnQsIHtcbiAgICAgICAgICAgICAgICAgICAgXCJrZXlcIjogaixcbiAgICAgICAgICAgICAgICAgICAgXCJyZWZcIjogYGNvbXBsZXRpb24ke2NvbXBvbmVudFBvc2l0aW9ufWAsXG4gICAgICAgICAgICAgICAgICAgIFwiaWRcIjogZ2VuZXJhdGVDb21wbGV0aW9uRG9tSWQoY29tcG9uZW50UG9zaXRpb24gLSAxKSwgLy8gMCBpbmRleCB0aGUgY29tcGxldGlvbiBJRHNcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICAgICAgICBvbkNsaWNrLFxuICAgICAgICAgICAgICAgICAgICBcImFyaWEtc2VsZWN0ZWRcIjogc2VsZWN0ZWQsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcblxuXG4gICAgICAgICAgICByZXR1cm4gY29tcGxldGlvbnMubGVuZ3RoID4gMCA/IChcbiAgICAgICAgICAgICAgICA8ZGl2IGtleT17aX0gY2xhc3NOYW1lPVwibXhfQXV0b2NvbXBsZXRlX1Byb3ZpZGVyU2VjdGlvblwiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X0F1dG9jb21wbGV0ZV9wcm92aWRlcl9uYW1lXCI+eyBjb21wbGV0aW9uUmVzdWx0LnByb3ZpZGVyLmdldE5hbWUoKSB9PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIHsgY29tcGxldGlvblJlc3VsdC5wcm92aWRlci5yZW5kZXJDb21wbGV0aW9ucyhjb21wbGV0aW9ucykgfVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgKSA6IG51bGw7XG4gICAgICAgIH0pLmZpbHRlcigoY29tcGxldGlvbikgPT4gISFjb21wbGV0aW9uKTtcblxuICAgICAgICByZXR1cm4gIXRoaXMuc3RhdGUuaGlkZSAmJiByZW5kZXJlZENvbXBsZXRpb25zLmxlbmd0aCA+IDAgPyAoXG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X0F1dG9jb21wbGV0ZVwiIHJlZj17dGhpcy5jb250YWluZXJSZWZ9PlxuICAgICAgICAgICAgICAgIHsgcmVuZGVyZWRDb21wbGV0aW9ucyB9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgKSA6IG51bGw7XG4gICAgfVxufVxuIl19