UNPKG

@engie-group/fluid-design-system-angular

Version:

Fluid Design System Angular

334 lines (331 loc) 47.8 kB
import { CommonModule, DOCUMENT } from '@angular/common'; import { ChangeDetectionStrategy, Component, ContentChild, ContentChildren, forwardRef, Inject, Input, ViewChild, ViewEncapsulation, } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { race, Subject, takeUntil } from 'rxjs'; import { selectAnimations } from '../../shared/animations'; import { CustomLabelDirective } from '../custom-label/custom-label.directive'; import { FormFieldDirective } from '../form-field/form-field.directive'; import { FormItemComponent } from '../form-item/form-item.component'; import { ListGroupComponent } from '../list-group/list-group.component'; import { ListItemComponent } from '../list-item/list-item.component'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; export class SelectComponent extends FormItemComponent { static { this.ESCAPE_CODE = 'Escape'; } static { this.ENTER_CODE = 'Enter'; } static { this.UP_CODE = 'ArrowUp'; } static { this.DOWN_CODE = 'ArrowDown'; } /* Regex matching every alpha-numeric characters. \d : every digits \p{Letter} : every letters in the latin alphabet including letters with diacritics The "u" flag enables unicode mode required to use `\p{Letter}`. See : - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Unicode_Property_Escapes#general_categories - https://unicode.org/reports/tr18/#General_Category_Property */ static { this.ALPHA_NUMERIC_REGEX = /^[\d\p{Letter}]$/u; } constructor(element, cdr, document) { super(); this.element = element; this.cdr = cdr; this.document = document; /** * @ignore */ this._onChange = (_) => { }; /** * @ignore */ this._onTouched = () => { }; /** * Notifier used to stop items click event subscription. * @ignore */ this.unsubscribe = new Subject(); this.childOptionsChange = new Subject(); /** * @ignore */ this.isOpen = false; /** * @ignore */ this.selectedValue = ''; /** * @ignore */ this.selectedIndex = -1; this.iconName = 'keyboard_arrow_down'; } ngAfterViewInit() { setTimeout(() => { this.setInputsAndListenersOnOptions(); this.selectOptions?.changes .pipe(takeUntil(this.unsubscribe)) .subscribe(() => { setTimeout(() => { this.setInputsAndListenersOnOptions(); }); }); }); } ngOnDestroy() { this.unsubscribe.next(); this.unsubscribe.complete(); this.childOptionsChange.complete(); } setInputsAndListenersOnOptions() { this.childOptionsChange.next(); const unsubscribeCond$ = race(this.unsubscribe, this.childOptionsChange); this.selectOptions?.forEach((item) => { item.role = 'option'; if (this.selectedValue?.trim() !== '') { item.updateSelected(this.selectedValue === item.getValue()); } item.itemClick .pipe(takeUntil(unsubscribeCond$)) .subscribe(() => { const value = item.getValue(); this.writeValue(value); this._onChange(value); this.closeList(); setTimeout(() => { this.buttonEl?.nativeElement.focus(); }); }); }); // Get selected index on mount based on current value this.selectedIndex = this.selectOptions?.toArray().findIndex(opt => { return opt.getValue() === this.selectedValue; }); this.cdr.markForCheck(); } /** * @ignore */ getAdditionalClass() { const classes = ['nj-form-item--select', 'nj-form-item--custom-list']; if (this.isOpen) { classes.push('nj-form-item--open'); } if (this.customLabel?.templateRef) { classes.push('nj-form-item--custom-label'); } return classes.join(' '); } getSubscriptId() { return `${this.inputId}-subscript`; } getInstructionsId() { return `${this.inputId}-instructions`; } getDescriptionId() { return `${this.getSubscriptId()} ${this.getInstructionsId()}`; } /** * Get index of the selected value */ indexForValue(value) { return this.selectOptions ?.toArray() .findIndex((item) => item.getValue() === value); } openList() { this.isOpen = true; this.focusedIndex = this.selectedIndex; setTimeout(() => { if (this.selectedIndex === -1) { // Focus the `ul` element this.listEl?.rootEl.nativeElement.focus(); // The scrolling element is not the `ul` node but the `nj-list-group` this.listEl?.element.nativeElement.scrollTo({ top: 0 }); } }); } closeList() { this.isOpen = false; } toggleIsOpen() { if (this.isOpen) { this.closeList(); } else { this.openList(); } } /** * Index of the currently focused option. */ get focusedIndex() { return this.selectOptions ?.toArray() .findIndex((item) => this.document.activeElement === item.el.nativeElement); } set focusedIndex(value) { this.selectOptions?.forEach((el, i) => { el.ariaSelected = i === value; }); setTimeout(() => { if (value !== -1) { this.selectOptions?.get(value).el.nativeElement.focus(); } }); } handleListKeydown(e) { // Escape key closes the list and focuses the button if (e.code === SelectComponent.ESCAPE_CODE) { this.closeList(); setTimeout(() => { this.buttonEl?.nativeElement.focus(); }); } // Navigate between options and set `focusedIndex` if (e.code === SelectComponent.UP_CODE) { e.preventDefault(); // Dont loop back to the end of the list if (this.focusedIndex > 0) { this.focusedIndex -= 1; } } if (e.code === SelectComponent.DOWN_CODE) { e.preventDefault(); // Dont loop back to the beginning of the list if (this.focusedIndex < this.selectOptions?.length - 1) { this.focusedIndex += 1; } } // Select the current `focusedIndex` option if (e.code === SelectComponent.ENTER_CODE) { e.preventDefault(); if (this.focusedIndex !== -1) { const value = this.selectOptions?.get(this.focusedIndex).getValue(); this.writeValue(value); this._onChange(value); } this.closeList(); setTimeout(() => { this.buttonEl?.nativeElement.focus(); }); } // Jump to first option matching first letter if (SelectComponent.ALPHA_NUMERIC_REGEX.test(e.key)) { const goToIndex = this.selectOptions ?.toArray() .findIndex((item) => item.getValue()[0].toLowerCase() === e.key.toLowerCase()); if (goToIndex !== -1) { this.focusedIndex = goToIndex; } } } handleFocusout(e) { if (!this.element.nativeElement?.contains(e.relatedTarget)) { this.closeList(); if (this._onTouched) { this._onTouched(); } } } /** * Implemented as part of ControlValueAccessor. * @ignore */ registerOnChange(fn) { this._onChange = fn; } /** * Implemented as part of ControlValueAccessor. * @ignore */ registerOnTouched(fn) { this._onTouched = fn; } /** * Implemented as part of ControlValueAccessor. * @ignore */ setDisabledState(isDisabled) { if (!this.selectedValue) { return; } this.isDisabled = isDisabled; } /** * Implemented as part of ControlValueAccessor. * @ignore */ writeValue(value) { this.selectedValue = value; this.selectedIndex = this.indexForValue(value); this.selectOptions?.forEach((item) => { item.updateSelected(item.getValue() === value); }); this.cdr.markForCheck(); } get customLabelContext() { const value = this.selectedValue; const index = this.selectedIndex; return { $implicit: value, value, index }; } /** * Label (≠ value) of selected option * @ignore */ get selectedLabel() { return this.selectOptions?.get(this.selectedIndex)?.getLabel() ?? ''; } /** * Aria-label for the trigger button element. * @ignore */ get buttonLabel() { return `${this.fieldLabel} - ${this.customLabelEl?.nativeElement.innerText || this.selectedValue || this.buttonDefaultValueLabel}`; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SelectComponent, isStandalone: true, selector: "nj-select", inputs: { iconName: "iconName", fieldLabel: "fieldLabel", listNavigationLabel: "listNavigationLabel", buttonDefaultValueLabel: "buttonDefaultValueLabel" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SelectComponent), multi: true, }, ], queries: [{ propertyName: "customLabel", first: true, predicate: CustomLabelDirective, descendants: true }, { propertyName: "selectOptions", predicate: ListItemComponent, descendants: true }], viewQueries: [{ propertyName: "buttonEl", first: true, predicate: ["button"], descendants: true }, { propertyName: "customLabelEl", first: true, predicate: ["customLabelEl"], descendants: true }, { propertyName: "listEl", first: true, predicate: ListGroupComponent, descendants: true }], usesInheritance: true, ngImport: i0, template: "<nj-form-item\n [hasError]=\"hasError\"\n [hasSuccess]=\"hasSuccess\"\n [hasHint]=\"hasHint\"\n [isDisabled]=\"isDisabled\"\n [hasCustomIcon]=\"hasCustomIcon\"\n [isFloatingLabel]=\"isFloatingLabel\"\n [iconName]=\"iconName\"\n [size]=\"size\"\n [isSelect]=\"true\"\n [additionalClass]=\"getAdditionalClass()\"\n [inputId]=\"inputId\"\n (focusout)=\"handleFocusout($event)\"\n>\n <input\n type=\"text\"\n readonly\n [value]=\"selectedLabel\"\n [attr.id]=\"inputId\"\n [disabled]=\"isDisabled\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n njFormField\n />\n <ng-content njFormLabel select=\"[njFormLabel]\"></ng-content>\n <ng-content njFormSubscript select=\"[njFormSubscript]\"></ng-content>\n <ng-container njFormAdditionalContent>\n <div\n *ngIf=\"selectedValue && customLabel?.templateRef\"\n #customLabelEl\n class=\"nj-form-item__custom-label\"\n aria-hidden=\"true\"\n njFormField>\n <ng-container [ngTemplateOutlet]=\"customLabel.templateRef\"\n [ngTemplateOutletContext]=\"customLabelContext\"></ng-container>\n </div>\n <p [id]=\"getInstructionsId()\" hidden>{{ listNavigationLabel }}</p>\n <button\n #button\n type=\"button\"\n class=\"nj-form-item__custom-list-button\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"isOpen\"\n role=\"combobox\"\n [attr.aria-label]=\"buttonLabel\"\n [attr.tabindex]=\"isOpen ? -1 : null\"\n [attr.aria-describedby]=\"getDescriptionId()\"\n (click)=\"toggleIsOpen()\"\n ></button>\n <nj-list-group\n class=\"nj-form-item__list nj-form-item__list--no-animate\"\n [hidden]=\"!isOpen\"\n [@transformList]=\"isOpen ? 'open': 'void'\"\n [isDense]=\"true\"\n [hasBorder]=\"false\"\n [isClickable]=\"true\"\n [isCustomSelectList]=\"true\"\n tabindex=\"-1\"\n [ariaLabel]=\"fieldLabel\"\n (keydown)=\"handleListKeydown($event)\"\n >\n <ng-content select=\"[njSelectOptions]\"></ng-content>\n </nj-list-group>\n </ng-container>\n</nj-form-item>\n", styles: [":host{display:block;width:100%;height:100%}.nj-form-item__custom-list-button{outline:none}.nj-form-item--custom-label input{z-index:-1;transform:scale(0);opacity:0}.nj-form-item--custom-label div.nj-form-item__custom-label{position:absolute;inset:0}\n"], dependencies: [{ kind: "component", type: ListGroupComponent, selector: "nj-list-group", inputs: ["listId", "isClickable", "isCheckboxList", "hasBorder", "isDense", "isCustomSelectList", "ariaLabel", "isMultiSelect"] }, { kind: "component", type: FormItemComponent, selector: "nj-form-item", inputs: ["inputId", "size", "isFloatingLabel", "isDisabled", "isRequired", "hasSuccess", "hasError", "hasHint", "hasCustomIcon", "isIconClickable", "iconName", "additionalClass", "passwordButtonLabelShow", "passwordButtonLabelHide", "passwordNoticeIsVisible", "passwordNoticeIsHidden", "isSelect"], outputs: ["iconClick", "iconKeydown", "wrapperClick"] }, { kind: "directive", type: FormFieldDirective, selector: "input[njFormField], textarea[njFormField], select[njFormField], nj-select[njFormField], div[njFormField]", exportAs: ["njFormField"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], animations: [selectAnimations.transformList], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectComponent, decorators: [{ type: Component, args: [{ selector: 'nj-select', changeDetection: ChangeDetectionStrategy.OnPush, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SelectComponent), multi: true, }, ], animations: [selectAnimations.transformList], encapsulation: ViewEncapsulation.None, standalone: true, imports: [ListGroupComponent, FormItemComponent, FormFieldDirective, CommonModule], template: "<nj-form-item\n [hasError]=\"hasError\"\n [hasSuccess]=\"hasSuccess\"\n [hasHint]=\"hasHint\"\n [isDisabled]=\"isDisabled\"\n [hasCustomIcon]=\"hasCustomIcon\"\n [isFloatingLabel]=\"isFloatingLabel\"\n [iconName]=\"iconName\"\n [size]=\"size\"\n [isSelect]=\"true\"\n [additionalClass]=\"getAdditionalClass()\"\n [inputId]=\"inputId\"\n (focusout)=\"handleFocusout($event)\"\n>\n <input\n type=\"text\"\n readonly\n [value]=\"selectedLabel\"\n [attr.id]=\"inputId\"\n [disabled]=\"isDisabled\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n njFormField\n />\n <ng-content njFormLabel select=\"[njFormLabel]\"></ng-content>\n <ng-content njFormSubscript select=\"[njFormSubscript]\"></ng-content>\n <ng-container njFormAdditionalContent>\n <div\n *ngIf=\"selectedValue && customLabel?.templateRef\"\n #customLabelEl\n class=\"nj-form-item__custom-label\"\n aria-hidden=\"true\"\n njFormField>\n <ng-container [ngTemplateOutlet]=\"customLabel.templateRef\"\n [ngTemplateOutletContext]=\"customLabelContext\"></ng-container>\n </div>\n <p [id]=\"getInstructionsId()\" hidden>{{ listNavigationLabel }}</p>\n <button\n #button\n type=\"button\"\n class=\"nj-form-item__custom-list-button\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"isOpen\"\n role=\"combobox\"\n [attr.aria-label]=\"buttonLabel\"\n [attr.tabindex]=\"isOpen ? -1 : null\"\n [attr.aria-describedby]=\"getDescriptionId()\"\n (click)=\"toggleIsOpen()\"\n ></button>\n <nj-list-group\n class=\"nj-form-item__list nj-form-item__list--no-animate\"\n [hidden]=\"!isOpen\"\n [@transformList]=\"isOpen ? 'open': 'void'\"\n [isDense]=\"true\"\n [hasBorder]=\"false\"\n [isClickable]=\"true\"\n [isCustomSelectList]=\"true\"\n tabindex=\"-1\"\n [ariaLabel]=\"fieldLabel\"\n (keydown)=\"handleListKeydown($event)\"\n >\n <ng-content select=\"[njSelectOptions]\"></ng-content>\n </nj-list-group>\n </ng-container>\n</nj-form-item>\n", styles: [":host{display:block;width:100%;height:100%}.nj-form-item__custom-list-button{outline:none}.nj-form-item--custom-label input{z-index:-1;transform:scale(0);opacity:0}.nj-form-item--custom-label div.nj-form-item__custom-label{position:absolute;inset:0}\n"] }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT] }] }]; }, propDecorators: { iconName: [{ type: Input }], fieldLabel: [{ type: Input }], listNavigationLabel: [{ type: Input }], buttonDefaultValueLabel: [{ type: Input }], buttonEl: [{ type: ViewChild, args: ['button'] }], customLabelEl: [{ type: ViewChild, args: ['customLabelEl'] }], listEl: [{ type: ViewChild, args: [ListGroupComponent] }], customLabel: [{ type: ContentChild, args: [CustomLabelDirective] }], selectOptions: [{ type: ContentChildren, args: [ListItemComponent, { descendants: true }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3NlbGVjdC9zZWxlY3QuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvc2VsZWN0L3NlbGVjdC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsWUFBWSxFQUFFLFFBQVEsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3ZELE9BQU8sRUFFTCx1QkFBdUIsRUFFdkIsU0FBUyxFQUNULFlBQVksRUFDWixlQUFlLEVBRWYsVUFBVSxFQUNWLE1BQU0sRUFDTixLQUFLLEVBR0wsU0FBUyxFQUNULGlCQUFpQixHQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQXVCLGlCQUFpQixFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDdkUsT0FBTyxFQUFXLElBQUksRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQ3hELE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLHlCQUF5QixDQUFDO0FBQ3pELE9BQU8sRUFBQyxvQkFBb0IsRUFBQyxNQUFNLHdDQUF3QyxDQUFDO0FBQzVFLE9BQU8sRUFBQyxrQkFBa0IsRUFBQyxNQUFNLG9DQUFvQyxDQUFDO0FBQ3RFLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLGtDQUFrQyxDQUFDO0FBQ25FLE9BQU8sRUFBQyxrQkFBa0IsRUFBQyxNQUFNLG9DQUFvQyxDQUFDO0FBQ3RFLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLGtDQUFrQyxDQUFDOzs7QUFvQm5FLE1BQU0sT0FBTyxlQUNYLFNBQVEsaUJBQWlCO2FBRUQsZ0JBQVcsR0FBRyxRQUFRLEFBQVgsQ0FBWTthQUN2QixlQUFVLEdBQUcsT0FBTyxBQUFWLENBQVc7YUFDckIsWUFBTyxHQUFHLFNBQVMsQUFBWixDQUFhO2FBQ3BCLGNB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LFVBQVU7c0JBQWxCLEtBQUs7Z0JBTUcsbUJBQW1CO3NCQUEzQixLQUFLO2dCQU1HLHVCQUF1QjtzQkFBL0IsS0FBSztnQkFNZSxRQUFRO3NCQUE1QixTQUFTO3VCQUFDLFFBQVE7Z0JBRW1CLGFBQWE7c0JBQWxELFNBQVM7dUJBQUMsZUFBZTtnQkFNSyxNQUFNO3NCQUFwQyxTQUFTO3VCQUFDLGtCQUFrQjtnQkFlaUIsV0FBVztzQkFBeEQsWUFBWTt1QkFBQyxvQkFBb0I7Z0JBT2xDLGFBQWE7c0JBRFosZUFBZTt1QkFBQyxpQkFBaUIsRUFBRSxFQUFDLFdBQVcsRUFBRSxJQUFJLEVBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0NvbW1vbk1vZHVsZSwgRE9DVU1FTlR9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgQ29udGVudENoaWxkLFxuICBDb250ZW50Q2hpbGRyZW4sXG4gIEVsZW1lbnRSZWYsXG4gIGZvcndhcmRSZWYsXG4gIEluamVjdCxcbiAgSW5wdXQsXG4gIE9uRGVzdHJveSxcbiAgUXVlcnlMaXN0LFxuICBWaWV3Q2hpbGQsXG4gIFZpZXdFbmNhcHN1bGF0aW9uLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7Q29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQge2ZpbmFsaXplLCByYWNlLCBTdWJqZWN0LCB0YWtlVW50aWx9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtzZWxlY3RBbmltYXRpb25zfSBmcm9tICcuLi8uLi9zaGFyZWQvYW5pbWF0aW9ucyc7XG5pbXBvcnQge0N1c3RvbUxhYmVsRGlyZWN0aXZlfSBmcm9tICcuLi9jdXN0b20tbGFiZWwvY3VzdG9tLWxhYmVsLmRpcmVjdGl2ZSc7XG5pbXBvcnQge0Zvcm1GaWVsZERpcmVjdGl2ZX0gZnJvbSAnLi4vZm9ybS1maWVsZC9mb3JtLWZpZWxkLmRpcmVjdGl2ZSc7XG5pbXBvcnQge0Zvcm1JdGVtQ29tcG9uZW50fSBmcm9tICcuLi9mb3JtLWl0ZW0vZm9ybS1pdGVtLmNvbXBvbmVudCc7XG5pbXBvcnQge0xpc3RHcm91cENvbXBvbmVudH0gZnJvbSAnLi4vbGlzdC1ncm91cC9saXN0LWdyb3VwLmNvbXBvbmVudCc7XG5pbXBvcnQge0xpc3RJdGVtQ29tcG9uZW50fSBmcm9tICcuLi9saXN0LWl0ZW0vbGlzdC1pdGVtLmNvbXBvbmVudCc7XG5pbXBvcnQge1NlbGVjdEN1c3RvbUxhYmVsQ29udGV4dH0gZnJvbSAnLi9zZWxlY3QtY3VzdG9tLWxhYmVsLWNvbnRleHQubW9kZWwnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduai1zZWxlY3QnLFxuICB0ZW1wbGF0ZVVybDogJy4vc2VsZWN0LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vc2VsZWN0LmNvbXBvbmVudC5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IFNlbGVjdENvbXBvbmVudCksXG4gICAgICBtdWx0aTogdHJ1ZSxcbiAgICB9LFxuICBdLFxuICBhbmltYXRpb25zOiBbc2VsZWN0QW5pbWF0aW9ucy50cmFuc2Zvcm1MaXN0XSxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0xpc3RHcm91cENvbXBvbmVudCwgRm9ybUl0ZW1Db21wb25lbnQsIEZvcm1GaWVsZERpcmVjdGl2ZSwgQ29tbW9uTW9kdWxlXVxufSlcbmV4cG9ydCBjbGFzcyBTZWxlY3RDb21wb25lbnRcbiAgZXh0ZW5kcyBGb3JtSXRlbUNvbXBvbmVudFxuICBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBPbkRlc3Ryb3kge1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBFU0NBUEVfQ09ERSA9ICdFc2NhcGUnO1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBFTlRFUl9DT0RFID0gJ0VudGVyJztcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgVVBfQ09ERSA9ICdBcnJvd1VwJztcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgRE9XTl9DT0RFID0gJ0Fycm93RG93bic7XG4gIC8qXG4gICAgUmVnZXggbWF0Y2hpbmcgZXZlcnkgYWxwaGEtbnVtZXJpYyBjaGFyYWN0ZXJzLlxuXG4gICAgXFxkIDogZXZlcnkgZGlnaXRzXG4gICAgXFxwe0xldHRlcn0gOiBldmVyeSBsZXR0ZXJzIGluIHRoZSBsYXRpbiBhbHBoYWJldCBpbmNsdWRpbmcgbGV0dGVycyB3aXRoIGRpYWNyaXRpY3NcblxuICAgIFRoZSBcInVcIiBmbGFnIGVuYWJsZXMgdW5pY29kZSBtb2RlIHJlcXVpcmVkIHRvIHVzZSBgXFxwe0xldHRlcn1gLlxuXG4gICAgU2VlIDpcbiAgICAtIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvR3VpZGUvUmVndWxhcl9FeHByZXNzaW9ucy9Vbmljb2RlX1Byb3BlcnR5X0VzY2FwZXMjZ2VuZXJhbF9jYXRlZ29yaWVzXG4gICAgLSBodHRwczovL3VuaWNvZGUub3JnL3JlcG9ydHMvdHIxOC8jR2VuZXJhbF9DYXRlZ29yeV9Qcm9wZXJ0eVxuICAqL1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBBTFBIQV9OVU1FUklDX1JFR0VYID0gL15bXFxkXFxwe0xldHRlcn1dJC91O1xuXG4gIC8qKlxuICAgKiBAaWdub3JlXG4gICAqL1xuICBwcml2YXRlIF9vbkNoYW5nZSA9IChfOiBhbnkpOiB2b2lkID0+IHtcbiAgfTtcblxuICAvKipcbiAgICogQGlnbm9yZVxuICAgKi9cbiAgcHJpdmF0ZSBfb25Ub3VjaGVkID0gKCk6IHZvaWQgPT4ge1xuICB9O1xuXG4gIC8qKlxuICAgKiBOb3RpZmllciB1c2VkIHRvIHN0b3AgaXRlbXMgY2xpY2sgZXZlbnQgc3Vic2NyaXB0aW9uLlxuICAgKiBAaWdub3JlXG4gICAqL1xuICBwcml2YXRlIHVuc3Vic2NyaWJlID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICBwcml2YXRlIGNoaWxkT3B0aW9uc0NoYW5nZSA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgLyoqXG4gICAqIEBpZ25vcmVcbiAgICovXG4gIGlzT3BlbiA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBAaWdub3JlXG4gICAqL1xuICBzZWxlY3RlZFZhbHVlID0gJyc7XG5cbiAgLyoqXG4gICAqIEBpZ25vcmVcbiAgICovXG4gIHNlbGVjdGVkSW5kZXggPSAtMTtcblxuICBASW5wdXQoKSBpY29uTmFtZSA9ICdrZXlib2FyZF9hcnJvd19kb3duJztcblxuICAvKipcbiAgICogTGFiZWwgdXNlZCBmb3IgYWNjZXNzaWJpbGl0eSByZWxhdGVkIGF0dHJpYnV0ZXMgb24gYnV0dG9uIGFuZCBsaXN0LlxuICAgKiBTaG91bGQgYmUgdGhlIHNhbWUgdmFsdWUgKHRleHQgb25seSkgYXMgdGhlIGA8bGFiZWw+YCBlbGVtZW50XG4gICAqL1xuICBASW5wdXQoKSBmaWVsZExhYmVsOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEluc3RydWN0aW9ucyBvbiBob3cgdG8gbmF2aWdhdGUgdGhlIGxpc3QuIEl0IGlzIGFwcGVuZCBhZnRlciB0aGUgaW5wdXQgbGFiZWwuXG4gICAqIEBleGFtcGxlIFwiVXNlIHVwIGFuZCBkb3duIGFycm93cyBhbmQgRW50ZXIgdG8gc2VsZWN0IGEgdmFsdWVcIlxuICAgKi9cbiAgQElucHV0KCkgbGlzdE5hdmlnYXRpb25MYWJlbDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBCdXR0b24gZGVmYXVsdCBsYWJlbCB3aGVuIG5vIHZhbHVlIGlzIHNlbGVjdGVkLiBJdCBpcyBhcHBlbmQgYWZ0ZXIgdGhlIGlucHV0IGxhYmVsLlxuICAgKiBAZXhhbXBsZSBcIlNlbGVjdCBhIHZhbHVlXCJcbiAgICovXG4gIEBJbnB1dCgpIGJ1dHRvbkRlZmF1bHRWYWx1ZUxhYmVsOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRyaWdnZXIgYnV0dG9uIHRvIHRvZ2dsZSB0aGUgbGlzdFxuICAgKiBAaWdub3JlXG4gICAqL1xuICBAVmlld0NoaWxkKCdidXR0b24nKSBidXR0b25FbDogRWxlbWVudFJlZjxIVE1MQnV0dG9uRWxlbWVudD47XG5cbiAgQFZpZXdDaGlsZCgnY3VzdG9tTGFiZWxFbCcpIHByb3RlY3RlZCBjdXN0b21MYWJlbEVsOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PjtcblxuICAvKipcbiAgICogTGlzdCBjb250YWluaW5nIG9wdGlvbnNcbiAgICogQGlnbm9yZVxuICAgKi9cbiAgQFZpZXdDaGlsZChMaXN0R3JvdXBDb21wb25lbnQpIGxpc3RFbDogTGlzdEdyb3VwQ29tcG9uZW50O1xuXG4gIC8qKlxuICAgKiBMYWJlbCB0byBkaXNwbGF5IGluc3RlYWQgb2YgcmF3IHRleHQgdmFsdWVcbiAgICogQGlnbm9yZVxuICAgKiBAZXhhbXBsZVxuICAgKiA8bmctdGVtcGxhdGUgbmpDdXN0b21MYWJlbCBsZXQtdmFsdWUgbGV0LWluZGV4PVwiaW5kZXhcIj5cbiAgICogIFZhbHVlOiB7e3ZhbHVlfX0gLSBJbmRleDoge3tpbmRleH19XG4gICAqIDwvbmctdGVtcGxhdGU+XG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIDxzcGFuICpuakN1c3RvbUxhYmVsPVwibGV0IHZhbHVlO2xldCBpbmRleD1pbmRleFwiPlxuICAgKiAgVmFsdWU6IHt7dmFsdWV9fSAtIEluZGV4OiB7e2luZGV4fX1cbiAgICogPC9zcGFuPlxuICAgKi9cbiAgQENvbnRlbnRDaGlsZChDdXN0b21MYWJlbERpcmVjdGl2ZSkgcHJvdGVjdGVkIGN1c3RvbUxhYmVsPzogQ3VzdG9tTGFiZWxEaXJlY3RpdmU8U2VsZWN0Q3VzdG9tTGFiZWxDb250ZXh0PjtcblxuICAvKipcbiAgICogT3B0aW9uIGl0ZW1zXG4gICAqIEBpZ25vcmVcbiAgICovXG4gIEBDb250ZW50Q2hpbGRyZW4oTGlzdEl0ZW1Db21wb25lbnQsIHtkZXNjZW5kYW50czogdHJ1ZX0pXG4gIHNlbGVjdE9wdGlvbnM6IFF1ZXJ5TGlzdDxMaXN0SXRlbUNvbXBvbmVudD47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBlbGVtZW50OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PixcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNkcjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgQEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBkb2N1bWVudFxuICApIHtcbiAgICBzdXBlcigpO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5zZXRJbnB1dHNBbmRMaXN0ZW5lcnNPbk9wdGlvbnMoKTtcblxuICAgICAgdGhpcy5zZWxlY3RPcHRpb25zPy5jaGFuZ2VzXG4gICAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLnVuc3Vic2NyaWJlKSlcbiAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNldElucHV0c0FuZExpc3RlbmVyc09uT3B0aW9ucygpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMudW5zdWJzY3JpYmUubmV4dCgpO1xuICAgIHRoaXMudW5zdWJzY3JpYmUuY29tcGxldGUoKTtcbiAgICB0aGlzLmNoaWxkT3B0aW9uc0NoYW5nZS5jb21wbGV0ZSgpO1xuICB9XG5cbiAgc2V0SW5wdXRzQW5kTGlzdGVuZXJzT25PcHRpb25zKCkge1xuICAgIHRoaXMuY2hpbGRPcHRpb25zQ2hhbmdlLm5leHQoKTtcbiAgICBjb25zdCB1bnN1YnNjcmliZUNvbmQkID0gcmFjZSh0aGlzLnVuc3Vic2NyaWJlLCB0aGlzLmNoaWxkT3B0aW9uc0NoYW5nZSk7XG5cbiAgICB0aGlzLnNlbGVjdE9wdGlvbnM/LmZvckVhY2goKGl0ZW0pID0+IHtcbiAgICAgIGl0ZW0ucm9sZSA9ICdvcHRpb24nO1xuXG4gICAgICBpZiAodGhpcy5zZWxlY3RlZFZhbHVlPy50cmltKCkgIT09ICcnKSB7XG4gICAgICAgIGl0ZW0udXBkYXRlU2VsZWN0ZWQodGhpcy5zZWxlY3RlZFZhbHVlID09PSBpdGVtLmdldFZhbHVlKCkpO1xuICAgICAgfVxuXG5cbiAgICAgIGl0ZW0uaXRlbUNsaWNrXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgIHRha2VVbnRpbCh1bnN1YnNjcmliZUNvbmQkKSxcbiAgICAgICAgKVxuICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IGl0ZW0uZ2V0VmFsdWUoKTtcbiAgICAgICAgICB0aGlzLndyaXRlVmFsdWUodmFsdWUpO1xuICAgICAgICAgIHRoaXMuX29uQ2hhbmdlKHZhbHVlKTtcbiAgICAgICAgICB0aGlzLmNsb3NlTGlzdCgpO1xuXG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmJ1dHRvbkVsPy5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy8gR2V0IHNlbGVjdGVkIGluZGV4IG9uIG1vdW50IGJhc2VkIG9uIGN1cnJlbnQgdmFsdWVcbiAgICB0aGlzLnNlbGVjdGVkSW5kZXggPSB0aGlzLnNlbGVjdE9wdGlvbnM/LnRvQXJyYXkoKS5maW5kSW5kZXgob3B0ID0+IHtcbiAgICAgIHJldHVybiBvcHQuZ2V0VmFsdWUoKSA9PT0gdGhpcy5zZWxlY3RlZFZhbHVlO1xuICAgIH0pO1xuXG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICAvKipcbiAgICogQGlnbm9yZVxuICAgKi9cbiAgZ2V0QWRkaXRpb25hbENsYXNzKCk6IHN0cmluZyB7XG4gICAgY29uc3QgY2xhc3NlcyA9IFsnbmotZm9ybS1pdGVtLS1zZWxlY3QnLCAnbmotZm9ybS1pdGVtLS1jdXN0b20tbGlzdCddO1xuICAgIGlmICh0aGlzLmlzT3Blbikge1xuICAgICAgY2xhc3Nlcy5wdXNoKCduai1mb3JtLWl0ZW0tLW9wZW4nKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5jdXN0b21MYWJlbD8udGVtcGxhdGVSZWYpIHtcbiAgICAgIGNsYXNzZXMucHVzaCgnbmotZm9ybS1pdGVtLS1jdXN0b20tbGFiZWwnKTtcbiAgICB9XG4gICAgcmV0dXJuIGNsYXNzZXMuam9pbignICcpO1xuICB9XG5cbiAgZ2V0U3Vic2NyaXB0SWQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYCR7dGhpcy5pbnB1dElkfS1zdWJzY3JpcHRgO1xuICB9XG5cbiAgZ2V0SW5zdHJ1Y3Rpb25zSWQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYCR7dGhpcy5pbnB1dElkfS1pbnN0cnVjdGlvbnNgO1xuICB9XG5cbiAgZ2V0RGVzY3JpcHRpb25JZCgpOiBzdHJpbmcge1xuICAgIHJldHVybiBgJHt0aGlzLmdldFN1YnNjcmlwdElkKCl9ICR7dGhpcy5nZXRJbnN0cnVjdGlvbnNJZCgpfWA7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGluZGV4IG9mIHRoZSBzZWxlY3RlZCB2YWx1ZVxuICAgKi9cbiAgcHJpdmF0ZSBpbmRleEZvclZhbHVlKHZhbHVlOiBzdHJpbmcpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnNlbGVjdE9wdGlvbnNcbiAgICAgID8udG9BcnJheSgpXG4gICAgICAuZmluZEluZGV4KChpdGVtKSA9PiBpdGVtLmdldFZhbHVlKCkgPT09IHZhbHVlKTtcbiAgfVxuXG4gIHByaXZhdGUgb3Blbkxpc3QoKSB7XG4gICAgdGhpcy5pc09wZW4gPSB0cnVlO1xuICAgIHRoaXMuZm9jdXNlZEluZGV4ID0gdGhpcy5zZWxlY3RlZEluZGV4O1xuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBpZiAodGhpcy5zZWxlY3RlZEluZGV4ID09PSAtMSkge1xuICAgICAgICAvLyBGb2N1cyB0aGUgYHVsYCBlbGVtZW50XG4gICAgICAgIHRoaXMubGlzdEVsPy5yb290RWwubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICAgICAgICAvLyBUaGUgc2Nyb2xsaW5nIGVsZW1lbnQgaXMgbm90IHRoZSBgdWxgIG5vZGUgYnV0IHRoZSBgbmotbGlzdC1ncm91cGBcbiAgICAgICAgdGhpcy5saXN0RWw/LmVsZW1lbnQubmF0aXZlRWxlbWVudC5zY3JvbGxUbyh7dG9wOiAwfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGNsb3NlTGlzdCgpIHtcbiAgICB0aGlzLmlzT3BlbiA9IGZhbHNlO1xuICB9XG5cbiAgdG9nZ2xlSXNPcGVuKCkge1xuICAgIGlmICh0aGlzLmlzT3Blbikge1xuICAgICAgdGhpcy5jbG9zZUxpc3QoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vcGVuTGlzdCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmRleCBvZiB0aGUgY3VycmVudGx5IGZvY3VzZWQgb3B0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBnZXQgZm9jdXNlZEluZGV4KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0T3B0aW9uc1xuICAgICAgPy50b0FycmF5KClcbiAgICAgIC5maW5kSW5kZXgoXG4gICAgICAgIChpdGVtKSA9PiB0aGlzLmRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgPT09IGl0ZW0uZWwubmF0aXZlRWxlbWVudFxuICAgICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0IGZvY3VzZWRJbmRleCh2YWx1ZTogbnVtYmVyKSB7XG4gICAgdGhpcy5zZWxlY3RPcHRpb25zPy5mb3JFYWNoKChlbCwgaSkgPT4ge1xuICAgICAgZWwuYXJpYVNlbGVjdGVkID0gaSA9PT0gdmFsdWU7XG4gICAgfSk7XG5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGlmICh2YWx1ZSAhPT0gLTEpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RPcHRpb25zPy5nZXQodmFsdWUpLmVsLm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGhhbmRsZUxpc3RLZXlkb3duKGU6IEtleWJvYXJkRXZlbnQpIHtcbiAgICAvLyBFc2NhcGUga2V5IGNsb3NlcyB0aGUgbGlzdCBhbmQgZm9jdXNlcyB0aGUgYnV0dG9uXG4gICAgaWYgKGUuY29kZSA9PT0gU2VsZWN0Q29tcG9uZW50LkVTQ0FQRV9DT0RFKSB7XG4gICAgICB0aGlzLmNsb3NlTGlzdCgpO1xuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHRoaXMuYnV0dG9uRWw/Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIE5hdmlnYXRlIGJldHdlZW4gb3B0aW9ucyBhbmQgc2V0IGBmb2N1c2VkSW5kZXhgXG4gICAgaWYgKGUuY29kZSA9PT0gU2VsZWN0Q29tcG9uZW50LlVQX0NPREUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIC8vIERvbnQgbG9vcCBiYWNrIHRvIHRoZSBlbmQgb2YgdGhlIGxpc3RcbiAgICAgIGlmICh0aGlzLmZvY3VzZWRJbmRleCA+IDApIHtcbiAgICAgICAgdGhpcy5mb2N1c2VkSW5kZXggLT0gMTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZS5jb2RlID09PSBTZWxlY3RDb21wb25lbnQuRE9XTl9DT0RFKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAvLyBEb250IGxvb3AgYmFjayB0byB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaXN0XG4gICAgICBpZiAodGhpcy5mb2N1c2VkSW5kZXggPCB0aGlzLnNlbGVjdE9wdGlvbnM/Lmxlbmd0aCAtIDEpIHtcbiAgICAgICAgdGhpcy5mb2N1c2VkSW5kZXggKz0gMTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTZWxlY3QgdGhlIGN1cnJlbnQgYGZvY3VzZWRJbmRleGAgb3B0aW9uXG4gICAgaWYgKGUuY29kZSA9PT0gU2VsZWN0Q29tcG9uZW50LkVOVEVSX0NPREUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGlmICh0aGlzLmZvY3VzZWRJbmRleCAhPT0gLTEpIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLnNlbGVjdE9wdGlvbnM/LmdldCh0aGlzLmZvY3VzZWRJbmRleCkuZ2V0VmFsdWUoKTtcbiAgICAgICAgdGhpcy53cml0ZVZhbHVlKHZhbHVlKTtcbiAgICAgICAgdGhpcy5fb25DaGFuZ2UodmFsdWUpO1xuICAgICAgfVxuICAgICAgdGhpcy5jbG9zZUxpc3QoKTtcblxuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHRoaXMuYnV0dG9uRWw/Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIEp1bXAgdG8gZmlyc3Qgb3B0aW9uIG1hdGNoaW5nIGZpcnN0IGxldHRlclxuICAgIGlmIChTZWxlY3RDb21wb25lbnQuQUxQSEFfTlVNRVJJQ19SRUdFWC50ZXN0KGUua2V5KSkge1xuICAgICAgY29uc3QgZ29Ub0luZGV4ID0gdGhpcy5zZWxlY3RPcHRpb25zXG4gICAgICAgID8udG9BcnJheSgpXG4gICAgICAgIC5maW5kSW5kZXgoXG4gICAgICAgICAgKGl0ZW0pID0+IGl0ZW0uZ2V0VmFsdWUoKVswXS50b0xvd2VyQ2FzZSgpID09PSBlLmtleS50b0xvd2VyQ2FzZSgpXG4gICAgICAgICk7XG5cbiAgICAgIGlmIChnb1RvSW5kZXggIT09IC0xKSB7XG4gICAgICAgIHRoaXMuZm9jdXNlZEluZGV4ID0gZ29Ub0luZGV4O1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGhhbmRsZUZvY3Vzb3V0KGU6IEZvY3VzRXZlbnQpIHtcbiAgICBpZiAoIXRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50Py5jb250YWlucyhlLnJlbGF0ZWRUYXJnZXQgYXMgTm9kZSkpIHtcbiAgICAgIHRoaXMuY2xvc2VMaXN0KCk7XG5cbiAgICAgIGlmICh0aGlzLl9vblRvdWNoZWQpIHtcbiAgICAgICAgdGhpcy5fb25Ub3VjaGVkKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEltcGxlbWVudGVkIGFzIHBhcnQgb2YgQ29udHJvbFZhbHVlQWNjZXNzb3IuXG4gICAqIEBpZ25vcmVcbiAgICovXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46IGFueSk6IHZvaWQge1xuICAgIHRoaXMuX29uQ2hhbmdlID0gZm47XG4gIH1cblxuICAvKipcbiAgICogSW1wbGVtZW50ZWQgYXMgcGFydCBvZiBDb250cm9sVmFsdWVBY2Nlc3Nvci5cbiAgICogQGlnbm9yZVxuICAgKi9cbiAgcmVnaXN0ZXJPblRvdWNoZWQoZm46IGFueSk6IHZvaWQge1xuICAgIHRoaXMuX29uVG91Y2hlZCA9IGZuO1xuICB9XG5cbiAgLyoqXG4gICAqIEltcGxlbWVudGVkIGFzIHBhcnQgb2YgQ29udHJvbFZhbHVlQWNjZXNzb3IuXG4gICAqIEBpZ25vcmVcbiAgICovXG4gIHNldERpc2FibGVkU3RhdGUoaXNEaXNhYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmICghdGhpcy5zZWxlY3RlZFZhbHVlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuaXNEaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG4gIH1cblxuICAvKipcbiAgICogSW1wbGVtZW50ZWQgYXMgcGFydCBvZiBDb250cm9sVmFsdWVBY2Nlc3Nvci5cbiAgICogQGlnbm9yZVxuICAgKi9cbiAgd3JpdGVWYWx1ZSh2YWx1ZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5zZWxlY3RlZFZhbHVlID0gdmFsdWU7XG4gICAgdGhpcy5zZWxlY3RlZEluZGV4ID0gdGhpcy5pbmRleEZvclZhbHVlKHZhbHVlKTtcbiAgICB0aGlzLnNlbGVjdE9wdGlvbnM/LmZvckVhY2goKGl0ZW0pID0+IHtcbiAgICAgIGl0ZW0udXBkYXRlU2VsZWN0ZWQoaXRlbS5nZXRWYWx1ZSgpID09PSB2YWx1ZSk7XG4gICAgfSk7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IGN1c3RvbUxhYmVsQ29udGV4dCgpOiBTZWxlY3RDdXN0b21MYWJlbENvbnRleHQge1xuICAgIGNvbnN0IHZhbHVlID0gdGhpcy5zZWxlY3RlZFZhbHVlO1xuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5zZWxlY3RlZEluZGV4O1xuICAgIHJldHVybiB7JGltcGxpY2l0OiB2YWx1ZSwgdmFsdWUsIGluZGV4fTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMYWJlbCAo4omgIHZhbHVlKSBvZiBzZWxlY3RlZCBvcHRpb25cbiAgICogQGlnbm9yZVxuICAgKi9cbiAgZ2V0IHNlbGVjdGVkTGFiZWwoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3RPcHRpb25zPy5nZXQodGhpcy5zZWxlY3RlZEluZGV4KT8uZ2V0TGFiZWwoKSA/PyAnJztcbiAgfVxuXG4gIC8qKlxuICAgKiBBcmlhLWxhYmVsIGZvciB0aGUgdHJpZ2dlciBidXR0b24gZWxlbWVudC5cbiAgICogQGlnbm9yZVxuICAgKi9cbiAgZ2V0IGJ1dHRvbkxhYmVsKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke3RoaXMuZmllbGRMYWJlbH0gLSAke1xuICAgICAgdGhpcy5jdXN0b21MYWJlbEVsPy5uYXRpdmVFbGVtZW50LmlubmVyVGV4dCB8fCB0aGlzLnNlbGVjdGVkVmFsdWUgfHwgdGhpcy5idXR0b25EZWZhdWx0VmFsdWVMYWJlbFxuICAgIH1gO1xuICB9XG59XG4iLCI8bmotZm9ybS1pdGVtXG4gIFtoYXNFcnJvcl09XCJoYXNFcnJvclwiXG4gIFtoYXNTdWNjZXNzXT1cImhhc1N1Y2Nlc3NcIlxuICBbaGFzSGludF09XCJoYXNIaW50XCJcbiAgW2lzRGlzYWJsZWRdPVwiaXNEaXNhYmxlZFwiXG4gIFtoYXNDdXN0b21JY29uXT1cImhhc0N1c3RvbUljb25cIlxuICBbaXNGbG9hdGluZ0xhYmVsXT1cImlzRmxvYXRpbmdMYWJlbFwiXG4gIFtpY29uTmFtZV09XCJpY29uTmFtZVwiXG4gIFtzaXplXT1cInNpemVcIlxuICBbaXNTZWxlY3RdPVwidHJ1ZVwiXG4gIFthZGRpdGlvbmFsQ2xhc3NdPVwiZ2V0QWRkaXRpb25hbENsYXNzKClcIlxuICBbaW5wdXRJZF09XCJpbnB1dElkXCJcbiAgKGZvY3Vzb3V0KT1cImhhbmRsZUZvY3Vzb3V0KCRldmVudClcIlxuPlxuICA8aW5wdXRcbiAgICB0eXBlPVwidGV4dFwiXG4gICAgcmVhZG9ubHlcbiAgICBbdmFsdWVdPVwic2VsZWN0ZWRMYWJlbFwiXG4gICAgW2F0dHIuaWRdPVwiaW5wdXRJZFwiXG4gICAgW2Rpc2FibGVkXT1cImlzRGlzYWJsZWRcIlxuICAgIHRhYmluZGV4PVwiLTFcIlxuICAgIGFyaWEtaGlkZGVuPVwidHJ1ZVwiXG4gICAgbmpGb3JtRmllbGRcbiAgLz5cbiAgPG5nLWNvbnRlbnQgbmpGb3JtTGFiZWwgc2VsZWN0PVwiW25qRm9ybUxhYmVsXVwiPjwvbmctY29udGVudD5cbiAgPG5nLWNvbnRlbnQgbmpGb3JtU3Vic2NyaXB0IHNlbGVjdD1cIltuakZvcm1TdWJzY3JpcHRdXCI+PC9uZy1jb250ZW50PlxuICA8bmctY29udGFpbmVyIG5qRm9ybUFkZGl0aW9uYWxDb250ZW50PlxuICAgIDxkaXZcbiAgICAgICpuZ0lmPVwic2VsZWN0ZWRWYWx1ZSAmJiBjdXN0b21MYWJlbD8udGVtcGxhdGVSZWZcIlxuICAgICAgI2N1c3RvbUxhYmVsRWxcbiAgICAgIGNsYXNzPVwibmotZm9ybS1pdGVtX19jdXN0b20tbGFiZWxcIlxuICAgICAgYXJpYS1oaWRkZW49XCJ0cnVlXCJcbiAgICAgIG5qRm9ybUZpZWxkPlxuICAgICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJjdXN0b21MYWJlbC50ZW1wbGF0ZVJlZlwiXG4gICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJjdXN0b21MYWJlbENvbnRleHRcIj48L25nLWNvbnRhaW5lcj5cbiAgICA8L2Rpdj5cbiAgICA8cCBbaWRdPVwiZ2V0SW5zdHJ1Y3Rpb25zSWQoKVwiIGhpZGRlbj57eyBsaXN0TmF2aWdhdGlvbkxhYmVsIH19PC9wPlxuICAgIDxidXR0b25cbiAgICAgICNidXR0b25cbiAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgY2xhc3M9XCJuai1mb3JtLWl0ZW1fX2N1c3RvbS1saXN0LWJ1dHRvblwiXG4gICAgICBhcmlhLWhhc3BvcHVwPVwibGlzdGJveFwiXG4gICAgICBbYXR0ci5hcmlhLWV4cGFuZGVkXT1cImlzT3BlblwiXG4gICAgICByb2xlPVwiY29tYm9ib3hcIlxuICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJidXR0b25MYWJlbFwiXG4gICAgICBbYXR0ci50YWJpbmRleF09XCJpc09wZW4gPyAtMSA6IG51bGxcIlxuICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJnZXREZXNjcmlwdGlvbklkKClcIlxuICAgICAgKGNsaWNrKT1cInRvZ2dsZUlzT3BlbigpXCJcbiAgICA+PC9idXR0b24+XG4gICAgPG5qLWxpc3QtZ3JvdXBcbiAgICAgIGNsYXNzPVwibmotZm9ybS1pdGVtX19saXN0IG5qLWZvcm0taXRlbV9fbGlzdC0tbm8tYW5pbWF0ZVwiXG4gICAgICBbaGlkZGVuXT1cIiFpc09wZW5cIlxuICAgICAgW0B0cmFuc2Zvcm1MaXN0XT1cImlzT3BlbiA/ICdvcGVuJzogJ3ZvaWQnXCJcbiAgICAgIFtpc0RlbnNlXT1cInRydWVcIlxuICAgICAgW2hhc0JvcmRlcl09XCJmYWxzZVwiXG4gICAgICBbaXNDbGlja2FibGVdPVwidHJ1ZVwiXG4gICAgICBbaXNDdXN0b21TZWxlY3RMaXN0XT1cInRydWVcIlxuICAgICAgdGFiaW5kZXg9XCItMVwiXG4gICAgICBbYXJpYUxhYmVsXT1cImZpZWxkTGFiZWxcIlxuICAgICAgKGtleWRvd24pPVwiaGFuZGxlTGlzdEtleWRvd24oJGV2ZW50KVwiXG4gICAgPlxuICAgICAgPG5nLWNvbnRlbnQgc2VsZWN0PVwiW25qU2VsZWN0T3B0aW9uc11cIj48L25nLWNvbnRlbnQ+XG4gICAgPC9uai1saXN0LWdyb3VwPlxuICA8L25nLWNvbnRhaW5lcj5cbjwvbmotZm9ybS1pdGVtPlxuIl19