angular-text-input-autocomplete
Version:
A angular 6+ directive for adding autocomplete functionality to text input elements, built around composability
460 lines (449 loc) • 48 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('rxjs'), require('textarea-caret'), require('rxjs/operators'), require('to-px'), require('@angular/common')) :
typeof define === 'function' && define.amd ? define('angular-text-input-autocomplete', ['exports', '@angular/core', 'rxjs', 'textarea-caret', 'rxjs/operators', 'to-px', '@angular/common'], factory) :
(factory((global['angular-text-input-autocomplete'] = {}),global.ng.core,global.rxjs,global.getCaretCoordinates,global.rxjs.operators,null,global.ng.common));
}(this, (function (exports,core,rxjs,getCaretCoordinates,operators,toPX,common) { 'use strict';
getCaretCoordinates = getCaretCoordinates && getCaretCoordinates.hasOwnProperty('default') ? getCaretCoordinates['default'] : getCaretCoordinates;
toPX = toPX && toPX.hasOwnProperty('default') ? toPX['default'] : toPX;
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var TextInputAutocompleteMenuComponent = (function () {
function TextInputAutocompleteMenuComponent() {
this.selectChoice = new rxjs.Subject();
this.choiceLoading = false;
this.trackById = function (index, choice) {
return typeof choice.id !== 'undefined' ? choice.id : choice;
};
}
Object.defineProperty(TextInputAutocompleteMenuComponent.prototype, "choices", {
get: /**
* @return {?}
*/ function () {
return this._choices;
},
set: /**
* @param {?} choices
* @return {?}
*/ function (choices) {
this._choices = choices;
if (choices.indexOf(this.activeChoice) === -1 && choices.length > 0) {
this.activeChoice = choices[0];
}
},
enumerable: true,
configurable: true
});
/**
* @param {?} event
* @return {?}
*/
TextInputAutocompleteMenuComponent.prototype.onArrowDown = /**
* @param {?} event
* @return {?}
*/
function (event) {
event.preventDefault();
var /** @type {?} */ index = this.choices.indexOf(this.activeChoice);
if (this.choices[index + 1]) {
this.scrollToChoice(index + 1);
}
};
/**
* @param {?} event
* @return {?}
*/
TextInputAutocompleteMenuComponent.prototype.onArrowUp = /**
* @param {?} event
* @return {?}
*/
function (event) {
event.preventDefault();
var /** @type {?} */ index = this.choices.indexOf(this.activeChoice);
if (this.choices[index - 1]) {
this.scrollToChoice(index - 1);
}
};
/**
* @param {?} event
* @return {?}
*/
TextInputAutocompleteMenuComponent.prototype.onEnter = /**
* @param {?} event
* @return {?}
*/
function (event) {
if (this.choices.indexOf(this.activeChoice) > -1) {
event.preventDefault();
this.selectChoice.next(this.activeChoice);
}
};
/**
* @param {?} index
* @return {?}
*/
TextInputAutocompleteMenuComponent.prototype.scrollToChoice = /**
* @param {?} index
* @return {?}
*/
function (index) {
this.activeChoice = this._choices[index];
if (this.dropdownMenuElement) {
var /** @type {?} */ ulPosition = this.dropdownMenuElement.nativeElement.getBoundingClientRect();
var /** @type {?} */ li = this.dropdownMenuElement.nativeElement.children[index];
var /** @type {?} */ liPosition = li.getBoundingClientRect();
if (liPosition.top < ulPosition.top ||
liPosition.bottom > ulPosition.bottom) {
li.scrollIntoView({
behavior: 'smooth',
block: 'nearest'
});
}
}
};
TextInputAutocompleteMenuComponent.decorators = [
{ type: core.Component, args: [{
selector: 'mwl-text-input-autocomplete-menu',
template: "\n <ul \n *ngIf=\"choices?.length > 0\"\n #dropdownMenu\n class=\"dropdown-menu\"\n [style.top.px]=\"position?.top\"\n [style.left.px]=\"position?.left\">\n <li\n *ngFor=\"let choice of choices; trackBy:trackById\"\n [class.active]=\"activeChoice === choice\">\n <a\n href=\"javascript:;\"\n (click)=\"selectChoice.next(choice)\">\n {{ choice }}\n </a>\n </li>\n </ul>\n ",
styles: [
"\n .dropdown-menu {\n display: block;\n max-height: 200px;\n overflow-y: auto;\n }\n "
]
},] },
];
TextInputAutocompleteMenuComponent.propDecorators = {
dropdownMenuElement: [{ type: core.ViewChild, args: ['dropdownMenu',] }],
onArrowDown: [{ type: core.HostListener, args: ['document:keydown.ArrowDown', ['$event'],] }],
onArrowUp: [{ type: core.HostListener, args: ['document:keydown.ArrowUp', ['$event'],] }],
onEnter: [{ type: core.HostListener, args: ['document:keydown.Enter', ['$event'],] }]
};
return TextInputAutocompleteMenuComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var TextInputAutocompleteDirective = (function () {
function TextInputAutocompleteDirective(componentFactoryResolver, viewContainerRef, injector, elm) {
this.componentFactoryResolver = componentFactoryResolver;
this.viewContainerRef = viewContainerRef;
this.injector = injector;
this.elm = elm;
/**
* The character that will trigger the menu to appear
*/
this.triggerCharacter = '@';
/**
* The regular expression that will match the search text after the trigger character
*/
this.searchRegexp = /^\w*$/;
/**
* Whether to close the menu when the host textarea loses focus
*/
this.closeMenuOnBlur = false;
/**
* The menu component to show with available options.
* You can extend the built in `TextInputAutocompleteMenuComponent` component to use a custom template
*/
this.menuComponent = TextInputAutocompleteMenuComponent;
/**
* Called when the options menu is shown
*/
this.menuShown = new core.EventEmitter();
/**
* Called when the options menu is hidden
*/
this.menuHidden = new core.EventEmitter();
/**
* Called when a choice is selected
*/
this.choiceSelected = new core.EventEmitter();
/**
* A function that formats the selected choice once selected.
*/
this.getChoiceLabel = function (choice) { return choice; };
this.menuHidden$ = new rxjs.Subject();
this.usingShortcut = false;
}
/**
* @param {?} key
* @return {?}
*/
TextInputAutocompleteDirective.prototype.onKeypress = /**
* @param {?} key
* @return {?}
*/
function (key) {
if (key === this.triggerCharacter) {
this.usingShortcut = false;
this.showMenu();
}
};
/**
* @param {?} event
* @return {?}
*/
TextInputAutocompleteDirective.prototype.onKeyDown = /**
* @param {?} event
* @return {?}
*/
function (event) {
if (this.keyboardShortcut && this.keyboardShortcut(event)) {
this.usingShortcut = true;
this.showMenu();
this.onChange('');
}
};
/**
* @param {?} value
* @return {?}
*/
TextInputAutocompleteDirective.prototype.onChange = /**
* @param {?} value
* @return {?}
*/
function (value) {
var _this = this;
if (this.menu) {
if (value[this.menu.triggerCharacterPosition] !== this.triggerCharacter &&
!this.usingShortcut) {
this.hideMenu();
}
else {
var /** @type {?} */ cursor = this.elm.nativeElement.selectionStart;
if (cursor < this.menu.triggerCharacterPosition) {
this.hideMenu();
}
else {
if (this.usingShortcut && !this.menu) {
value = this.triggerCharacter;
}
var /** @type {?} */ offset = this.usingShortcut ? 0 : 1;
var /** @type {?} */ searchText = value.slice(this.menu.triggerCharacterPosition + offset, cursor);
if (!searchText.match(this.searchRegexp)) {
this.hideMenu();
}
else {
this.menu.component.instance.searchText = searchText;
this.menu.component.instance.choices = [];
this.menu.component.instance.choiceLoadError = undefined;
this.menu.component.instance.choiceLoading = true;
this.menu.component.changeDetectorRef.detectChanges();
Promise.resolve(this.findChoices(searchText))
.then(function (choices) {
if (_this.menu) {
_this.menu.component.instance.choices = choices;
_this.menu.component.instance.choiceLoading = false;
_this.menu.component.changeDetectorRef.detectChanges();
}
})
.catch(function (err) {
if (_this.menu) {
_this.menu.component.instance.choiceLoading = false;
_this.menu.component.instance.choiceLoadError = err;
_this.menu.component.changeDetectorRef.detectChanges();
}
});
}
}
}
}
};
/**
* @return {?}
*/
TextInputAutocompleteDirective.prototype.onBlur = /**
* @return {?}
*/
function () {
if (this.menu) {
this.menu.lastCaretPosition = this.elm.nativeElement.selectionStart;
if (this.closeMenuOnBlur === true) {
this.hideMenu();
}
}
};
/**
* @return {?}
*/
TextInputAutocompleteDirective.prototype.showMenu = /**
* @return {?}
*/
function () {
var _this = this;
if (!this.menu) {
var /** @type {?} */ menuFactory = this.componentFactoryResolver.resolveComponentFactory(this.menuComponent);
this.menu = {
component: this.viewContainerRef.createComponent(menuFactory, 0, this.injector),
triggerCharacterPosition: this.elm.nativeElement.selectionStart
};
var /** @type {?} */ lineHeight = this.getLineHeight(this.elm.nativeElement);
var _a = getCaretCoordinates(this.elm.nativeElement, this.elm.nativeElement.selectionStart), top_1 = _a.top, left = _a.left;
this.menu.component.instance.position = {
top: top_1 + lineHeight,
left: left
};
this.menu.component.changeDetectorRef.detectChanges();
this.menu.component.instance.selectChoice
.pipe(operators.takeUntil(this.menuHidden$))
.subscribe(function (choice) {
var /** @type {?} */ label = _this.getChoiceLabel(choice);
var /** @type {?} */ textarea = _this.elm.nativeElement;
var /** @type {?} */ value = textarea.value;
var /** @type {?} */ startIndex = ((_this.menu)).triggerCharacterPosition;
var /** @type {?} */ start = value.slice(0, startIndex);
var /** @type {?} */ caretPosition = ((_this.menu)).lastCaretPosition || textarea.selectionStart;
var /** @type {?} */ end = value.slice(caretPosition);
textarea.value = start + label + end;
// force ng model / form control to update
textarea.dispatchEvent(new Event('input'));
_this.hideMenu();
var /** @type {?} */ setCursorAt = (start + label).length;
textarea.setSelectionRange(setCursorAt, setCursorAt);
textarea.focus();
_this.choiceSelected.emit({
choice: choice,
insertedAt: {
start: startIndex,
end: startIndex + label.length
}
});
});
this.menuShown.emit();
}
};
/**
* @param {?} elm
* @return {?}
*/
TextInputAutocompleteDirective.prototype.getLineHeight = /**
* @param {?} elm
* @return {?}
*/
function (elm) {
var /** @type {?} */ lineHeightStr = getComputedStyle(elm).lineHeight || '';
var /** @type {?} */ fontSizeStr = getComputedStyle(elm).fontSize || '';
var /** @type {?} */ fontSize = +toPX(fontSizeStr);
var /** @type {?} */ normal = 1.2;
var /** @type {?} */ lineHeightNum = parseFloat(lineHeightStr);
if (lineHeightStr === lineHeightNum + '') {
return fontSize * lineHeightNum;
}
if (lineHeightStr.toLowerCase() === 'normal') {
return fontSize * normal;
}
return toPX(lineHeightStr);
};
/**
* @return {?}
*/
TextInputAutocompleteDirective.prototype.hideMenu = /**
* @return {?}
*/
function () {
if (this.menu) {
this.menu.component.destroy();
this.menuHidden$.next();
this.menuHidden.emit();
this.menu = undefined;
}
};
/**
* @return {?}
*/
TextInputAutocompleteDirective.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this.hideMenu();
};
TextInputAutocompleteDirective.decorators = [
{ type: core.Directive, args: [{
selector: 'textarea[mwlTextInputAutocomplete],input[type="text"][mwlTextInputAutocomplete]'
},] },
];
/** @nocollapse */
TextInputAutocompleteDirective.ctorParameters = function () {
return [
{ type: core.ComponentFactoryResolver },
{ type: core.ViewContainerRef },
{ type: core.Injector },
{ type: core.ElementRef }
];
};
TextInputAutocompleteDirective.propDecorators = {
triggerCharacter: [{ type: core.Input }],
keyboardShortcut: [{ type: core.Input }],
searchRegexp: [{ type: core.Input }],
closeMenuOnBlur: [{ type: core.Input }],
menuComponent: [{ type: core.Input }],
menuShown: [{ type: core.Output }],
menuHidden: [{ type: core.Output }],
choiceSelected: [{ type: core.Output }],
findChoices: [{ type: core.Input }],
getChoiceLabel: [{ type: core.Input }],
onKeypress: [{ type: core.HostListener, args: ['keypress', ['$event.key'],] }],
onKeyDown: [{ type: core.HostListener, args: ['keydown', ['$event'],] }],
onChange: [{ type: core.HostListener, args: ['input', ['$event.target.value'],] }],
onBlur: [{ type: core.HostListener, args: ['blur',] }]
};
return TextInputAutocompleteDirective;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var TextInputAutocompleteContainerComponent = (function () {
function TextInputAutocompleteContainerComponent() {
}
TextInputAutocompleteContainerComponent.decorators = [
{ type: core.Component, args: [{
selector: 'mwl-text-input-autocomplete-container',
styles: [
"\n :host {\n position: relative;\n display: block;\n }\n "
],
template: '<ng-content></ng-content>'
},] },
];
return TextInputAutocompleteContainerComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var TextInputAutocompleteModule = (function () {
function TextInputAutocompleteModule() {
}
TextInputAutocompleteModule.decorators = [
{ type: core.NgModule, args: [{
declarations: [
TextInputAutocompleteDirective,
TextInputAutocompleteContainerComponent,
TextInputAutocompleteMenuComponent
],
imports: [common.CommonModule],
exports: [
TextInputAutocompleteDirective,
TextInputAutocompleteContainerComponent,
TextInputAutocompleteMenuComponent
],
entryComponents: [TextInputAutocompleteMenuComponent]
},] },
];
return TextInputAutocompleteModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
exports.TextInputAutocompleteMenuComponent = TextInputAutocompleteMenuComponent;
exports.TextInputAutocompleteModule = TextInputAutocompleteModule;
exports.ɵb = TextInputAutocompleteContainerComponent;
exports.ɵa = TextInputAutocompleteDirective;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci10ZXh0LWlucHV0LWF1dG9jb21wbGV0ZS51bWQuanMubWFwIiwic291cmNlcyI6WyJuZzovL2FuZ3VsYXItdGV4dC1pbnB1dC1hdXRvY29tcGxldGUvdGV4dC1pbnB1dC1hdXRvY29tcGxldGUtbWVudS5jb21wb25lbnQudHMiLCJuZzovL2FuZ3VsYXItdGV4dC1pbnB1dC1hdXRvY29tcGxldGUvdGV4dC1pbnB1dC1hdXRvY29tcGxldGUuZGlyZWN0aXZlLnRzIiwibmc6Ly9hbmd1bGFyLXRleHQtaW5wdXQtYXV0b2NvbXBsZXRlL3RleHQtaW5wdXQtYXV0b2NvbXBsZXRlLWNvbnRhaW5lci5jb21wb25lbnQudHMiLCJuZzovL2FuZ3VsYXItdGV4dC1pbnB1dC1hdXRvY29tcGxldGUvdGV4dC1pbnB1dC1hdXRvY29tcGxldGUubW9kdWxlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRWxlbWVudFJlZiwgSG9zdExpc3RlbmVyLCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbXdsLXRleHQtaW5wdXQtYXV0b2NvbXBsZXRlLW1lbnUnLFxuICB0ZW1wbGF0ZTogYFxuICAgIDx1bCBcbiAgICAgICpuZ0lmPVwiY2hvaWNlcz8ubGVuZ3RoID4gMFwiXG4gICAgICAjZHJvcGRvd25NZW51XG4gICAgICBjbGFzcz1cImRyb3Bkb3duLW1lbnVcIlxuICAgICAgW3N0eWxlLnRvcC5weF09XCJwb3NpdGlvbj8udG9wXCJcbiAgICAgIFtzdHlsZS5sZWZ0LnB4XT1cInBvc2l0aW9uPy5sZWZ0XCI+XG4gICAgICA8bGlcbiAgICAgICAgKm5nRm9yPVwibGV0IGNob2ljZSBvZiBjaG9pY2VzOyB0cmFja0J5OnRyYWNrQnlJZFwiXG4gICAgICAgIFtjbGFzcy5hY3RpdmVdPVwiYWN0aXZlQ2hvaWNlID09PSBjaG9pY2VcIj5cbiAgICAgICAgPGFcbiAgICAgICAgICBocmVmPVwiamF2YXNjcmlwdDo7XCJcbiAgICAgICAgICAoY2xpY2spPVwic2VsZWN0Q2hvaWNlLm5leHQoY2hvaWNlKVwiPlxuICAgICAgICAgIHt7IGNob2ljZSB9fVxuICAgICAgICA8L2E+XG4gICAgICA8L2xpPlxuICAgIDwvdWw+XG4gIGAsXG4gIHN0eWxlczogW1xuICAgIGBcbiAgICAgIC5kcm9wZG93bi1tZW51IHtcbiAgICAgICAgZGlzcGxheTogYmxvY2s7XG4gICAgICAgIG1heC1oZWlnaHQ6IDIwMHB4O1xuICAgICAgICBvdmVyZmxvdy15OiBhdXRvO1xuICAgICAgfVxuICAgIGBcbiAgXVxufSlcbmV4cG9ydCBjbGFzcyBUZXh0SW5wdXRBdXRvY29tcGxldGVNZW51Q29tcG9uZW50IHtcbiAgQFZpZXdDaGlsZCgnZHJvcGRvd25NZW51JykgZHJvcGRvd25NZW51RWxlbWVudDogRWxlbWVudFJlZjxIVE1MVUxpc3RFbGVtZW50PjtcbiAgcG9zaXRpb246IHsgdG9wOiBudW1iZXI7IGxlZnQ6IG51bWJlciB9O1xuICBzZWxlY3RDaG9pY2UgPSBuZXcgU3ViamVjdCgpO1xuICBhY3RpdmVDaG9pY2U6IGFueTtcbiAgc2VhcmNoVGV4dDogc3RyaW5nO1xuICBjaG9pY2VMb2FkRXJyb3I6IGFueTtcbiAgY2hvaWNlTG9hZGluZyA9IGZhbHNlO1xuICBwcml2YXRlIF9jaG9pY2VzOiBhbnlbXTtcbiAgdHJhY2tCeUlkID0gKGluZGV4OiBudW1iZXIsIGNob2ljZTogYW55KSA9PlxuICAgIHR5cGVvZiBjaG9pY2UuaWQgIT09ICd1bmRlZmluZWQnID8gY2hvaWNlLmlkIDogY2hvaWNlO1xuXG4gIHNldCBjaG9pY2VzKGNob2ljZXM6IGFueVtdKSB7XG4gICAgdGhpcy5fY2hvaWNlcyA9IGNob2ljZXM7XG4gICAgaWYgKGNob2ljZXMuaW5kZXhPZih0aGlzLmFjdGl2ZUNob2ljZSkgPT09IC0xICYmIGNob2ljZXMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5hY3RpdmVDaG9pY2UgPSBjaG9pY2VzWzBdO1xuICAgIH1cbiAgfVxuXG4gIGdldCBjaG9pY2VzKCkge1xuICAgIHJldHVybiB0aGlzLl9jaG9pY2VzO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6a2V5ZG93bi5BcnJvd0Rvd24nLCBbJyRldmVudCddKVxuICBvbkFycm93RG93bihldmVudDogS2V5Ym9hcmRFdmVudCkge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgY29uc3QgaW5kZXggPSB0aGlzLmNob2ljZXMuaW5kZXhPZih0aGlzLmFjdGl2ZUNob2ljZSk7XG4gICAgaWYgKHRoaXMuY2hvaWNlc1tpbmRleCArIDFdKSB7XG4gICAgICB0aGlzLnNjcm9sbFRvQ2hvaWNlKGluZGV4ICsgMSk7XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6a2V5ZG93bi5BcnJvd1VwJywgWyckZXZlbnQnXSlcbiAgb25BcnJvd1VwKGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBjb25zdCBpbmRleCA9IHRoaXMuY2hvaWNlcy5pbmRleE9mKHRoaXMuYWN0aXZlQ2hvaWNlKTtcbiAgICBpZiAodGhpcy5jaG9pY2VzW2luZGV4IC0gMV0pIHtcbiAgICAgIHRoaXMuc2Nyb2xsVG9DaG9pY2UoaW5kZXggLSAxKTtcbiAgICB9XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDprZXlkb3duLkVudGVyJywgWyckZXZlbnQnXSlcbiAgb25FbnRlcihldmVudDogS2V5Ym9hcmRFdmVudCkge1xuICAgIGlmICh0aGlzLmNob2ljZXMuaW5kZXhPZih0aGlzLmFjdGl2ZUNob2ljZSkgPiAtMSkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHRoaXMuc2VsZWN0Q2hvaWNlLm5leHQodGhpcy5hY3RpdmVDaG9pY2UpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc2Nyb2xsVG9DaG9pY2UoaW5kZXg6IG51bWJlcikge1xuICAgIHRoaXMuYWN0aXZlQ2hvaWNlID0gdGhpcy5fY2hvaWNlc1tpbmRleF07XG5cbiAgICBpZiAodGhpcy5kcm9wZG93bk1lbnVFbGVtZW50KSB7XG4gICAgICBjb25zdCB1bFBvc2l0aW9uID0gdGhpcy5kcm9wZG93bk1lbnVFbGVtZW50Lm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICBjb25zdCBsaSA9IHRoaXMuZHJvcGRvd25NZW51RWxlbWVudC5uYXRpdmVFbGVtZW50LmNoaWxkcmVuW2luZGV4XTtcbiAgICAgIGNvbnN0IGxpUG9zaXRpb24gPSBsaS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgICAgaWYgKFxuICAgICAgICBsaVBvc2l0aW9uLnRvcCA8IHVsUG9zaXRpb24udG9wIHx8XG4gICAgICAgIGxpUG9zaXRpb24uYm90dG9tID4gdWxQb3NpdGlvbi5ib3R0b21cbiAgICAgICkge1xuICAgICAgICBsaS5zY3JvbGxJbnRvVmlldyh7XG4gICAgICAgICAgYmVoYXZpb3I6ICdzbW9vdGgnLFxuICAgICAgICAgIGJsb2NrOiAnbmVhcmVzdCdcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iLCJpbXBvcnQge1xuICBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gIENvbXBvbmVudFJlZixcbiAgRGlyZWN0aXZlLFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIEhvc3RMaXN0ZW5lcixcbiAgSW5qZWN0b3IsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE91dHB1dCxcbiAgVmlld0NvbnRhaW5lclJlZlxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCBnZXRDYXJldENvb3JkaW5hdGVzIGZyb20gJ3RleHRhcmVhLWNhcmV0JztcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IFRleHRJbnB1dEF1dG9jb21wbGV0ZU1lbnVDb21wb25lbnQgfSBmcm9tICcuL3RleHQtaW5wdXQtYXV0b2NvbXBsZXRlLW1lbnUuY29tcG9uZW50JztcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcbi8vIEB0cy1pZ25vcmVcbmltcG9ydCB0b1BYIGZyb20gJ3RvLXB4JztcblxuZXhwb3J0IGludGVyZmFjZSBDaG9pY2VTZWxlY3RlZEV2ZW50IHtcbiAgY2hvaWNlOiBhbnk7XG4gIGluc2VydGVkQXQ6IHtcbiAgICBzdGFydDogbnVtYmVyO1xuICAgIGVuZDogbnVtYmVyO1xuICB9O1xufVxuXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6XG4gICAgJ3RleHRhcmVhW213bFRleHRJbnB1dEF1dG9jb21wbGV0ZV0saW5wdXRbdHlwZT1cInRleHRcIl1bbXdsVGV4dElucHV0QXV0b2NvbXBsZXRlXSdcbn0pXG5leHBvcnQgY2xhc3MgVGV4dElucHV0QXV0b2NvbXBsZXRlRGlyZWN0aXZlIGltcGxlbWVudHMgT25EZXN0cm95IHtcbiAgLyoqXG4gICAqIFRoZSBjaGFyYWN0ZXIgdGhhdCB3aWxsIHRyaWdnZXIgdGhlIG1lbnUgdG8gYXBwZWFyXG4gICAqL1xuICBASW5wdXQoKSB0cmlnZ2VyQ2hhcmFjdGVyID0gJ0AnO1xuXG4gIC8qKlxuICAgKiBBbiBvcHRpb25hbCBrZXlib2FyZCBzaG9ydGN1dCB0aGF0IHdpbGwgdHJpZ2dlciB0aGUgbWVudSB0byBhcHBlYXJcbiAgICovXG4gIEBJbnB1dCgpIGtleWJvYXJkU2hvcnRjdXQ6IChldmVudDogS2V5Ym9hcmRFdmVudCkgPT4gYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIHJlZ3VsYXIgZXhwcmVzc2lvbiB0aGF0IHdpbGwgbWF0Y2ggdGhlIHNlYXJjaCB0ZXh0IGFmdGVyIHRoZSB0cmlnZ2VyIGNoYXJhY3RlclxuICAgKi9cbiAgQElucHV0KCkgc2VhcmNoUmVnZXhwID0gL15cXHcqJC87XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gY2xvc2UgdGhlIG1lbnUgd2hlbiB0aGUgaG9zdCB0ZXh0YXJlYSBsb3NlcyBmb2N1c1xuICAgKi9cbiAgQElucHV0KCkgY2xvc2VNZW51T25CbHVyID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIFRoZSBtZW51IGNvbXBvbmVudCB0byBzaG93IHdpdGggYXZhaWxhYmxlIG9wdGlvbnMuXG4gICAqIFlvdSBjYW4gZXh0ZW5kIHRoZSBidWlsdCBpbiBgVGV4dElucHV0QXV0b2NvbXBsZXRlTWVudUNvbXBvbmVudGAgY29tcG9uZW50IHRvIHVzZSBhIGN1c3RvbSB0ZW1wbGF0ZVxuICAgKi9cbiAgQElucHV0KCkgbWVudUNvbXBvbmVudCA9IFRleHRJbnB1dEF1dG9jb21wbGV0ZU1lbnVDb21wb25lbnQ7XG5cbiAgLyoqXG4gICAqIENhbGxlZCB3aGVuIHRoZSBvcHRpb25zIG1lbnUgaXMgc2hvd25cbiAgICovXG4gIEBPdXRwdXQoKSBtZW51U2hvd24gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgLyoqXG4gICAqIENhbGxlZCB3aGVuIHRoZSBvcHRpb25zIG1lbnUgaXMgaGlkZGVuXG4gICAqL1xuICBAT3V0cHV0KCkgbWVudUhpZGRlbiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAvKipcbiAgICogQ2FsbGVkIHdoZW4gYSBjaG9pY2UgaXMgc2VsZWN0ZWRcbiAgICovXG4gIEBPdXRwdXQoKSBjaG9pY2VTZWxlY3RlZCA9IG5ldyBFdmVudEVtaXR0ZXI8Q2hvaWNlU2VsZWN0ZWRFdmVudD4oKTtcblxuICAvKipcbiAgICogQSBmdW5jdGlvbiB0aGF0IGFjY2VwdHMgYSBzZWFyY2ggc3RyaW5nIGFuZCByZXR1cm5zIGFuIGFycmF5IG9mIGNob2ljZXMuIENhbiBhbHNvIHJldHVybiBhIHByb21pc2UuXG4gICAqL1xuICBASW5wdXQoKSBmaW5kQ2hvaWNlczogKHNlYXJjaFRleHQ6IHN0cmluZykgPT4gYW55W10gfCBQcm9taXNlPGFueVtdPjtcblxuICAvKipcbiAgICogQSBmdW5jdGlvbiB0aGF0IGZvcm1hdHMgdGhlIHNlbGVjdGVkIGNob2ljZSBvbmNlIHNlbGVjdGVkLlxuICAgKi9cbiAgQElucHV0KCkgZ2V0Q2hvaWNlTGFiZWw6IChjaG9pY2U6IGFueSkgPT4gc3RyaW5nID0gY2hvaWNlID0+IGNob2ljZTtcblxuICAvKiB0c2xpbnQ6ZGlzYWJsZSBtZW1iZXItb3JkZXJpbmcgKi9cbiAgcHJpdmF0ZSBtZW51OlxuICAgIHwge1xuICAgICAgICBjb21wb25lbnQ6IENvbXBvbmVudFJlZjxUZXh0SW5wdXRBdXRvY29tcGxldGVNZW51Q29tcG9uZW50PjtcbiAgICAgICAgdHJpZ2dlckNoYXJhY3RlclBvc2l0aW9uOiBudW1iZXI7XG4gICAgICAgIGxhc3RDYXJldFBvc2l0aW9uPzogbnVtYmVyO1xuICAgICAgfVxuICAgIHwgdW5kZWZpbmVkO1xuXG4gIHByaXZhdGUgbWVudUhpZGRlbiQgPSBuZXcgU3ViamVjdCgpO1xuXG4gIHByaXZhdGUgdXNpbmdTaG9ydGN1dCA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgY29tcG9uZW50RmFjdG9yeVJlc29sdmVyOiBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gICAgcHJpdmF0ZSB2aWV3Q29udGFpbmVyUmVmOiBWaWV3Q29udGFpbmVyUmVmLFxuICAgIHByaXZhdGUgaW5qZWN0b3I6IEluamVjdG9yLFxuICAgIHByaXZhdGUgZWxtOiBFbGVtZW50UmVmXG4gICkge31cblxuICBASG9zdExpc3RlbmVyKCdrZXlwcmVzcycsIFsnJGV2ZW50LmtleSddKVxuICBvbktleXByZXNzKGtleTogc3RyaW5nKSB7XG4gICAgaWYgKGtleSA9PT0gdGhpcy50cmlnZ2VyQ2hhcmFjdGVyKSB7XG4gICAgICB0aGlzLnVzaW5nU2hvcnRjdXQgPSBmYWxzZTtcbiAgICAgIHRoaXMuc2hvd01lbnUoKTtcbiAgICB9XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdrZXlkb3duJywgWyckZXZlbnQnXSlcbiAgb25LZXlEb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XG4gICAgaWYgKHRoaXMua2V5Ym9hcmRTaG9ydGN1dCAmJiB0aGlzLmtleWJvYXJkU2hvcnRjdXQoZXZlbnQpKSB7XG4gICAgICB0aGlzLnVzaW5nU2hvcnRjdXQgPSB0cnVlO1xuICAgICAgdGhpcy5zaG93TWVudSgpO1xuICAgICAgdGhpcy5vbkNoYW5nZSgnJyk7XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignaW5wdXQnLCBbJyRldmVudC50YXJnZXQudmFsdWUnXSlcbiAgb25DaGFuZ2UodmFsdWU6IHN0cmluZykge1xuICAgIGlmICh0aGlzLm1lbnUpIHtcbiAgICAgIGlmIChcbiAgICAgICAgdmFsdWVbdGhpcy5tZW51LnRyaWdnZXJDaGFyYWN0ZXJQb3NpdGlvbl0gIT09IHRoaXMudHJpZ2dlckNoYXJhY3RlciAmJlxuICAgICAgICAhdGhpcy51c2luZ1Nob3J0Y3V0XG4gICAgICApIHtcbiAgICAgICAgdGhpcy5oaWRlTWVudSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgY3Vyc29yID0gdGhpcy5lbG0ubmF0aXZlRWxlbWVudC5zZWxlY3Rpb25TdGFydDtcbiAgICAgICAgaWYgKGN1cnNvciA8IHRoaXMubWVudS50cmlnZ2VyQ2hhcmFjdGVyUG9zaXRpb24pIHtcbiAgICAgICAgICB0aGlzLmhpZGVNZW51KCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKHRoaXMudXNpbmdTaG9ydGN1dCAmJiAhdGhpcy5tZW51KSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHRoaXMudHJpZ2dlckNoYXJhY3RlcjtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gdGhpcy51c2luZ1Nob3J0Y3V0ID8gMCA6IDE7XG4gICAgICAgICAgY29uc3Qgc2VhcmNoVGV4dCA9IHZhbHVlLnNsaWNlKFxuICAgICAgICAgICAgdGhpcy5tZW51LnRyaWdnZXJDaGFyYWN0ZXJQb3NpdGlvbiArIG9mZnNldCxcbiAgICAgICAgICAgIGN1cnNvclxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBpZiAoIXNlYXJjaFRleHQubWF0Y2godGhpcy5zZWFyY2hSZWdleHApKSB7XG4gICAgICAgICAgICB0aGlzLmhpZGVNZW51KCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMubWVudS5jb21wb25lbnQuaW5zdGFuY2Uuc2VhcmNoVGV4dCA9IHNlYXJjaFRleHQ7XG4gICAgICAgICAgICB0aGlzLm1lbnUuY29tcG9uZW50Lmluc3RhbmNlLmNob2ljZXMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMubWVudS5jb21wb25lbnQuaW5zdGFuY2UuY2hvaWNlTG9hZEVycm9yID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5tZW51LmNvbXBvbmVudC5pbnN0YW5jZS5jaG9pY2VMb2FkaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMubWVudS5jb21wb25lbnQuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgICAgICAgUHJvbWlzZS5yZXNvbHZlKHRoaXMuZmluZENob2ljZXMoc2VhcmNoVGV4dCkpXG4gICAgICAgICAgICAgIC50aGVuKGNob2ljZXMgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLm1lbnUpIHtcbiAgICAgICAgICAgICAgICAgIHRoaXMubWVudS5jb21wb25lbnQuaW5zdGFuY2UuY2hvaWNlcyA9IGNob2ljZXM7XG4gICAgICAgICAgICAgICAgICB0aGlzLm1lbnUuY29tcG9uZW50Lmluc3RhbmNlLmNob2ljZUxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgIHRoaXMubWVudS5jb21wb25lbnQuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubWVudSkge1xuICAgICAgICAgICAgICAgICAgdGhpcy5tZW51LmNvbXBvbmVudC5pbnN0YW5jZS5jaG9pY2VMb2FkaW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICB0aGlzLm1lbnUuY29tcG9uZW50Lmluc3RhbmNlLmNob2ljZUxvYWRFcnJvciA9IGVycjtcbiAgICAgICAgICAgICAgICAgIHRoaXMubWVudS5jb21wb25lbnQuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignYmx1cicpXG4gIG9uQmx1cigpIHtcbiAgICBpZiAodGhpcy5tZW51KSB7XG4gICAgICB0aGlzLm1lbnUubGFzdENhcmV0UG9zaXRpb24gPSB0aGlzLmVsbS5uYXRpdmVFbGVtZW50LnNlbGVjdGlvblN0YXJ0O1xuXG4gICAgICBpZiAodGhpcy5jbG9zZU1lbnVPbkJsdXIgPT09IHRydWUpIHtcbiAgICAgICAgdGhpcy5oaWRlTWVudSgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc2hvd01lbnUoKSB7XG4gICAgaWYgKCF0aGlzLm1lbnUpIHtcbiAgICAgIGNvbnN0IG1lbnVGYWN0b3J5ID0gdGhpcy5jb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIucmVzb2x2ZUNvbXBvbmVudEZhY3Rvcnk8XG4gICAgICAgIFRleHRJbnB1dEF1dG9jb21wbGV0ZU1lbnVDb21wb25lbnRcbiAgICAgID4odGhpcy5tZW51Q29tcG9uZW50KTtcbiAgICAgIHRoaXMubWVudSA9IHtcbiAgICAgICAgY29tcG9uZW50OiB0aGlzLnZpZXdDb250YWluZXJSZWYuY3JlYXRlQ29tcG9uZW50KFxuICAgICAgICAgIG1lbnVGYWN0b3J5LFxuICAgICAgICAgIDAsXG4gICAgICAgICAgdGhpcy5pbmplY3RvclxuICAgICAgICApLFxuICAgICAgICB0cmlnZ2VyQ2hhcmFjdGVyUG9zaXRpb246IHRoaXMuZWxtLm5hdGl2ZUVsZW1lbnQuc2VsZWN0aW9uU3RhcnRcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGxpbmVIZWlnaHQgPSB0aGlzLmdldExpbmVIZWlnaHQodGhpcy5lbG0ubmF0aXZlRWxlbWVudCk7XG4gICAgICBjb25zdCB7IHRvcCwgbGVmdCB9ID0gZ2V0Q2FyZXRDb29yZGluYXRlcyhcbiAgICAgICAgdGhpcy5lbG0ubmF0aXZlRWxlbWVudCxcbiAgICAgICAgdGhpcy5lbG0ubmF0aXZlRWxlbWVudC5zZWxlY3Rpb25TdGFydFxuICAgICAgKTtcbiAgICAgIHRoaXMubWVudS5jb21wb25lbnQuaW5zdGFuY2UucG9zaXRpb24gPSB7XG4gICAgICAgIHRvcDogdG9wICsgbGluZUhlaWdodCxcbiAgICAgICAgbGVmdFxuICAgICAgfTtcbiAgICAgIHRoaXMubWVudS5jb21wb25lbnQuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgdGhpcy5tZW51LmNvbXBvbmVudC5pbnN0YW5jZS5zZWxlY3RDaG9pY2VcbiAgICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMubWVudUhpZGRlbiQpKVxuICAgICAgICAuc3Vic2NyaWJlKGNob2ljZSA9PiB7XG4gICAgICAgICAgY29uc3QgbGFiZWwgPSB0aGlzLmdldENob2ljZUxhYmVsKGNob2ljZSk7XG4gICAgICAgICAgY29uc3QgdGV4dGFyZWE6IEhUTUxUZXh0QXJlYUVsZW1lbnQgPSB0aGlzLmVsbS5uYXRpdmVFbGVtZW50O1xuICAgICAgICAgIGNvbnN0IHZhbHVlOiBzdHJpbmcgPSB0ZXh0YXJlYS52YWx1ZTtcbiAgICAgICAgICBjb25zdCBzdGFydEluZGV4ID0gdGhpcy5tZW51IS50cmlnZ2VyQ2hhcmFjdGVyUG9zaXRpb247XG4gICAgICAgICAgY29uc3Qgc3RhcnQgPSB2YWx1ZS5zbGljZSgwLCBzdGFydEluZGV4KTtcbiAgICAgICAgICBjb25zdCBjYXJldFBvc2l0aW9uID1cbiAgICAgICAgICAgIHRoaXMubWVudSEubGFzdENhcmV0UG9zaXRpb24gfHwgdGV4dGFyZWEuc2VsZWN0aW9uU3RhcnQ7XG4gICAgICAgICAgY29uc3QgZW5kID0gdmFsdWUuc2xpY2UoY2FyZXRQb3NpdGlvbik7XG4gICAgICAgICAgdGV4dGFyZWEudmFsdWUgPSBzdGFydCArIGxhYmVsICsgZW5kO1xuICAgICAgICAgIC8vIGZvcmNlIG5nIG1vZGVsIC8gZm9ybSBjb250cm9sIHRvIHVwZGF0ZVxuICAgICAgICAgIHRleHRhcmVhLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCdpbnB1dCcpKTtcbiAgICAgICAgICB0aGlzLmhpZGVNZW51KCk7XG4gICAgICAgICAgY29uc3Qgc2V0Q3Vyc29yQXQgPSAoc3RhcnQgKyBsYWJlbCkubGVuZ3RoO1xuICAgICAgICAgIHRleHRhcmVhLnNldFNlbGVjdGlvblJhbmdlKHNldEN1cnNvckF0LCBzZXRDdXJzb3JBdCk7XG4gICAgICAgICAgdGV4dGFyZWEuZm9jdXMoKTtcbiAgICAgICAgICB0aGlzLmNob2ljZVNlbGVjdGVkLmVtaXQoe1xuICAgICAgICAgICAgY2hvaWNlLFxuICAgICAgICAgICAgaW5zZXJ0ZWRBdDoge1xuICAgICAgICAgICAgICBzdGFydDogc3RhcnRJbmRleCxcbiAgICAgICAgICAgICAgZW5kOiBzdGFydEluZGV4ICsgbGFiZWwubGVuZ3RoXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgdGhpcy5tZW51U2hvd24uZW1pdCgpO1xuICAgIH1cbiAgfVxuXG4gIGdldExpbmVIZWlnaHQoZWxtOiBIVE1MRWxlbWVudCk6IG51bWJlciB7XG4gICAgY29uc3QgbGluZUhlaWdodFN0ciA9IGdldENvbXB1dGVkU3R5bGUoZWxtKS5saW5lSGVpZ2h0IHx8ICcnO1xuICAgIGNvbnN0IGZvbnRTaXplU3RyID0gZ2V0Q29tcHV0ZWRTdHlsZShlbG0pLmZvbnRTaXplIHx8ICcnO1xuICAgIGNvbnN0IGZvbnRTaXplID0gK3RvUFgoZm9udFNpemVTdHIpO1xuICAgIGNvbnN0IG5vcm1hbCA9IDEuMjtcbiAgICBjb25zdCBsaW5lSGVpZ2h0TnVtID0gcGFyc2VGbG9hdChsaW5lSGVpZ2h0U3RyKTtcblxuICAgIGlmIChsaW5lSGVpZ2h0U3RyID09PSBsaW5lSGVpZ2h0TnVtICsgJycpIHtcbiAgICAgIHJldHVybiBmb250U2l6ZSAqIGxpbmVIZWlnaHROdW07XG4gICAgfVxuXG4gICAgaWYgKGxpbmVIZWlnaHRTdHIudG9Mb3dlckNhc2UoKSA9PT0gJ25vcm1hbCcpIHtcbiAgICAgIHJldHVybiBmb250U2l6ZSAqIG5vcm1hbDtcbiAgICB9XG5cbiAgICByZXR1cm4gdG9QWChsaW5lSGVpZ2h0U3RyKTtcbiAgfVxuXG4gIHByaXZhdGUgaGlkZU1lbnUoKSB7XG4gICAgaWYgKHRoaXMubWVudSkge1xuICAgICAgdGhpcy5tZW51LmNvbXBvbmVudC5kZXN0cm95KCk7XG4gICAgICB0aGlzLm1lbnVIaWRkZW4kLm5leHQoKTtcbiAgICAgIHRoaXMubWVudUhpZGRlbi5lbWl0KCk7XG4gICAgICB0aGlzLm1lbnUgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5oaWRlTWVudSgpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbXdsLXRleHQtaW5wdXQtYXV0b2NvbXBsZXRlLWNvbnRhaW5lcicsXG4gIHN0eWxlczogW1xuICAgIGBcbiAgICAgIDpob3N0IHtcbiAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgICAgICBkaXNwbGF5OiBibG9jaztcbiAgICAgIH1cbiAgICBgXG4gIF0sXG4gIHRlbXBsYXRlOiAnPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50Pidcbn0pXG5leHBvcnQgY2xhc3MgVGV4dElucHV0QXV0b2NvbXBsZXRlQ29udGFpbmVyQ29tcG9uZW50IHt9XG4iLCJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IFRleHRJbnB1dEF1dG9jb21wbGV0ZURpcmVjdGl2ZSB9IGZyb20gJy4vdGV4dC1pbnB1dC1hdXRvY29tcGxldGUuZGlyZWN0aXZlJztcbmltcG9ydCB7IFRleHRJbnB1dEF1dG9jb21wbGV0ZUNvbnRhaW5lckNvbXBvbmVudCB9IGZyb20gJy4vdGV4dC1pbnB1dC1hdXRvY29tcGxldGUtY29udGFpbmVyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBUZXh0SW5wdXRBdXRvY29tcGxldGVNZW51Q29tcG9uZW50IH0gZnJvbSAnLi90ZXh0LWlucHV0LWF1dG9jb21wbGV0ZS1tZW51LmNvbXBvbmVudCc7XG5cbkBOZ01vZHVsZSh7XG4gIGRlY2xhcmF0aW9uczogW1xuICAgIFRleHRJbnB1dEF1dG9jb21wbGV0ZURpcmVjdGl2ZSxcbiAgICBUZXh0SW5wdXRBdXRvY29tcGxldGVDb250YWluZXJDb21wb25lbnQsXG4gICAgVGV4dElucHV0QXV0b2NvbXBsZXRlTWVudUNvbXBvbmVudFxuICBdLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcbiAgZXhwb3J0czogW1xuICAgIFRleHRJbnB1dEF1dG9jb21wbGV0ZURpcmVjdGl2ZSxcbiAgICBUZXh0SW5wdXRBdXRvY29tcGxldGVDb250YWluZXJDb21wb25lbnQsXG4gICAgVGV4dElucHV0QXV0b2NvbXBsZXRlTWVudUNvbXBvbmVudFxuICBdLFxuICBlbnRyeUNvbXBvbmVudHM6IFtUZXh0SW5wdXRBdXRvY29tcGxldGVNZW51Q29tcG9uZW50XVxufSlcbmV4cG9ydCBjbGFzcyBUZXh0SW5wdXRBdXRvY29tcGxldGVNb2R1bGUge31cbiJdLCJuYW1lcyI6WyJTdWJqZWN0IiwiQ29tcG9uZW50IiwiVmlld0NoaWxkIiwiSG9zdExpc3RlbmVyIiwiRXZlbnRFbWl0dGVyIiwidGFrZVVudGlsIiwiRGlyZWN0aXZlIiwiQ29tcG9uZW50RmFjdG9yeVJlc29sdmVyIiwiVmlld0NvbnRhaW5lclJlZiIsIkluamVjdG9yIiwiRWxlbWVudFJlZiIsIklucHV0IiwiT3V0cHV0IiwiTmdNb2R1bGUiLCJDb21tb25Nb2R1bGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFBQTs7Z0NBb0NpQixJQUFJQSxZQUFPLEVBQUU7aUNBSVosS0FBSzs2QkFFVCxVQUFDLEtBQWEsRUFBRSxNQUFXO2dCQUNyQyxPQUFBLE9BQU8sTUFBTSxDQUFDLEVBQUUsS0FBSyxXQUFXLEdBQUcsTUFBTSxDQUFDLEVBQUUsR0FBRyxNQUFNO2FBQUE7O1FBRXZELHNCQUFJLHVEQUFPOzs7Z0JBT1g7Z0JBQ0UsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO2FBQ3RCOzs7O2dCQVRELFVBQVksT0FBYztnQkFDeEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUM7Z0JBQ3hCLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7b0JBQ25FLElBQUksQ0FBQyxZQUFZLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUNoQzthQUNGOzs7V0FBQTs7Ozs7UUFPRCx3REFBVzs7OztZQURYLFVBQ1ksS0FBb0I7Z0JBQzlCLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztnQkFDdkIscUJBQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztnQkFDdEQsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsRUFBRTtvQkFDM0IsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUM7aUJBQ2hDO2FBQ0Y7Ozs7O1FBR0Qs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