UNPKG

@visa/nova-angular

Version:

Visa Product Design System Nova Angular library

362 lines 53.3 kB
/** * © 2025 Visa * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * **/ import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { ContentChild, ContentChildren, Directive, ElementRef, EventEmitter, HostBinding, HostListener, Input, Output, QueryList, Renderer2 } from '@angular/core'; import { AppReadyService } from '../_utilities/services/app-stable-check.service'; import { UUIDService } from '../_utilities/services/uuid.service'; import { AccordionHeadingDirective } from '../accordion-heading/accordion-heading.directive'; import { ButtonDirective } from '../button/button.directive'; import { TabItemDisclosureDirective } from '../disclosure-tab-item/disclosure-tab-item.directive'; import { DropdownListDirective } from '../dropdown-list/dropdown-list.directive'; import { DropdownMenuDirective } from '../dropdown-menu/dropdown-menu.directive'; import { FloatingUIElementDirective } from '../floating-ui-element/floating-ui-element.directive'; import { FloatingUITriggerDirective } from '../floating-ui-trigger/floating-ui-trigger.directive'; import { FloatingUIPlacements, FloatingUIVisibility } from '../floating-ui/floating-ui.constants'; import { FloatingUIService } from '../floating-ui/floating-ui.service'; import { IconToggleComponent } from '../icon-toggle/icon-toggle.component'; import { IconToggleDirective } from '../icon-toggle/icon-toggle.directive'; import { ListboxDirective } from '../listbox/listbox.directive'; import { NovaLibService } from '../nova-lib.service'; import { TooltipDirective } from '../tooltip/tooltip.directive'; import * as i0 from "@angular/core"; import * as i1 from "../floating-ui/floating-ui.service"; import * as i2 from "../_utilities/services/uuid.service"; import * as i3 from "../nova-lib.service"; import * as i4 from "../_utilities/services/app-stable-check.service"; export class FloatingUIContainer { /** * Provides custom class&#40;es&#41; for custom styling. */ get class() { return this._class; } set class(value) { this._class = value; } get hostClasses() { return this.class; } /** @ignore */ get isShown() { return this._isShown; } set isShown(value) { this._isShown = coerceBooleanProperty(value); } /** * Placement of floating content relevant to triggering element. * @default FloatingUIPlacements.BOTTOM_START * @see 'FloatingUIPlacements'. */ get placement() { return this._placement; } set placement(value) { this._placement = value; } /** * Middleware for FloatingUIService. * @default [ offset(2), flip(), shift() ] for tooltip <br /> * @default [ offset(0), flip(), shift() ] for combobox <br /> * @see [Floating UI](https://floating-ui.com/docs/middleware) for options. */ get middleware() { return this._middleware; } set middleware(value) { this._middleware = value; } /** * Events array for FloatingUIService. <br /> * This array specifies whether to show or hide the floating element on a given UIEvent. <br /> * This should be an array of [UIEvent, FloatingUIVisibility]. * @default [ [new UIEvent('mouseenter'), FloatingUIVisibility.SHOW], <br /> [new UIEvent('mouseleave'), FloatingUIVisibility.HIDE], <br /> [new UIEvent('focus'), FloatingUIVisibility.SHOW], <br /> [new UIEvent('blur'), FloatingUIVisibility.HIDE] <br />] for tooltip * @default [ [new UIEvent('click')] ] for dropdown-menu and floating-ui-element * @default [] Ie. events are removed for combobox. */ get eventsArray() { return this._eventsArray; } set eventsArray(value) { this._eventsArray = value; } /** * Closes the menu on item is click/select when true. <br> * If <code>multiselect</code> is set to <code>true</code>, it will not take effect.<br> * @default true */ get closeOnClick() { return this._closeOnClick; } set closeOnClick(value) { this._closeOnClick = coerceBooleanProperty(value); } // this is an angular-specific override. Spacing between dropdown-menu and button/trigger // is handled within floating-ui.service get hostMarginBlockStart() { return '0'; } constructor(el, floatingUIService, uuidService, novaLibService, renderer, appReadyService) { this.el = el; this.floatingUIService = floatingUIService; this.uuidService = uuidService; this.novaLibService = novaLibService; this.renderer = renderer; this.appReadyService = appReadyService; this._isCombobox = false; this._tooltipDefaultEvents = [ [new UIEvent('mouseenter'), FloatingUIVisibility.SHOW], [new UIEvent('mouseleave'), FloatingUIVisibility.HIDE], [new UIEvent('focus'), FloatingUIVisibility.SHOW], [new UIEvent('blur'), FloatingUIVisibility.HIDE] ]; this._dropdownMenuDefaultEvents = [[new UIEvent('click')]]; this._class = ''; // override the standard class attr with a new one. this._isShown = false; this._placement = FloatingUIPlacements.BOTTOM_START; this._closeOnClick = true; /** * Emits whether or not the floating UI element is visible. */ this.floatingUIToggled = new EventEmitter(); this._tabPressed = false; } clickOut(event) { // listen for document click and close menu if click is outside of component if (this.appReadyService.isBrowserAndDomAvailable() && this.isShown && !this.el.nativeElement.contains(event.target)) { this.floatingUIService.hidefloatingUI(); } } tab(event) { if (event.key === 'Tab') { // used in focusout function this._tabPressed = true; } } focusout(event) { if (this._tabPressed) { // if focus out is a result of tabbing out of this component, hide the floating UI if (event.relatedTarget && !this.el.nativeElement.contains(event.relatedTarget)) { this.floatingUIService.hidefloatingUI(); } this._tabPressed = false; } } ngAfterContentInit() { let floatingElem = null; let _toggleIcon; let _toggleIconComponent; const toggleInChildContainer = this.containers.some((container) => container.toggleIcon === this.toggleIcon) || this.disclosureTabs.some((tab) => tab.button.toggleIcon === this.toggleIcon) || this.accordionHeadings.some((heading) => heading.hostButton?.toggleIcon === this.toggleIcon || heading._buttonHeading?.toggleIcon === this.toggleIcon); const toggleComponentInChildContainer = this.containers.some((container) => container.toggleIconComponent === this.toggleIconComponent) || this.disclosureTabs.some((tab) => tab.button.toggleIconComponent === this.toggleIconComponent) || this.accordionHeadings.some((heading) => heading.hostButton?.toggleIconComponent === this.toggleIconComponent || heading._buttonHeading?.toggleIconComponent === this.toggleIconComponent); if (this.toggleIcon && !toggleInChildContainer) { _toggleIcon = this.toggleIcon; _toggleIcon.icon.icon = this.isShown ? _toggleIcon.expandedIcon : _toggleIcon.collapsedIcon; } else if (this.toggleIconComponent && !toggleComponentInChildContainer) { _toggleIconComponent = this.toggleIconComponent; _toggleIconComponent._floatingUIToggle = true; _toggleIconComponent.rotated = this.isShown; } const tooltipInChildContainer = this.containers.some((container) => container.tooltip === this.tooltip); const menuInChildContainer = this.containers.some((container) => container.menu === this.menu); const dropdownInChildContainer = this.containers.some((container) => container.genericDropdown === this.genericDropdown); if (this.menu && !menuInChildContainer) { floatingElem = this.menu; this.renderer.setStyle(this.menu.el.nativeElement, 'position', 'absolute'); this.trigger._triggersDropdownMenu = true; floatingElem.id = this.menu.id ? this.menu.id : this.uuidService.getUUID('v-floating-'); this.menu._isShown = this.isShown; this.eventsArray = this.eventsArray ? this.eventsArray : this._dropdownMenuDefaultEvents; this.setUpListItems(); } else if (this.tooltip && !tooltipInChildContainer) { floatingElem = this.tooltip; this.trigger._triggersTooltip = true; this.eventsArray = this.eventsArray ? this.eventsArray : this._tooltipDefaultEvents; } else if (this.genericDropdown && !dropdownInChildContainer) { floatingElem = this.genericDropdown; this.renderer.setStyle(this.genericDropdown.el.nativeElement, 'position', 'absolute'); this.eventsArray = this.eventsArray ? this.eventsArray : this._dropdownMenuDefaultEvents; this.setUpListItems(); } if (this.trigger?.el && floatingElem?.el) { floatingElem.id = floatingElem.id ? floatingElem.id : this.uuidService.getUUID('v-floating-'); this.trigger._floatingElemID = floatingElem.id; if (this.tooltip?.arrow) { this.floatingUIService.customizeFloatingUI(this.placement, this.middleware, this.tooltip.display || 'block', this.tooltip.arrow); } else { if (!this.middleware && this._isCombobox) { this.middleware = this.floatingUIService.comboboxMiddleware; } this.floatingUIService.customizeFloatingUI(this.placement, this.middleware); } this.floatingUIService.setUpfloatingUI(this.trigger.el, floatingElem.el, this.eventsArray); } this.floatingUIService.isShownEmitter.subscribe((isShown) => { if (this.trigger) this.trigger._isShown = isShown; if (this.menu) this.menu._isShown = isShown; if (this.accordionHeadings.length === 0) { if (_toggleIcon) { _toggleIcon.icon.icon = isShown ? _toggleIcon.expandedIcon : _toggleIcon.collapsedIcon; } else if (_toggleIconComponent) { _toggleIconComponent.rotated = isShown; } } this.isShown = isShown; this.floatingUIToggled.emit(isShown); }); } setUpListItems() { const isMultiSelect = this.listbox?.multiselect ? true : false; if (this.closeOnClick && !isMultiSelect) { if (this.menu) { // this is for v-dropdown-menu let children; if (this.dropdownItems.length > 0) { // using dropdownItems children = this.dropdownItems.length > 0 ? this.dropdownItems : null; if (children) { children.forEach((item) => { if (!item.el.nativeElement.disabled) { this.renderer.listen(item.el.nativeElement, 'click', (event) => { this.floatingUIService.hidefloatingUI(); }); } }); } } else { // not using dropdownItems, gather all children, for buttons, disregard the triggering button children = this.buttons.length > 1 ? this.buttons : this.listbox?.listItems.length > 0 ? this.listbox.listItems : null; if (children) { children.forEach((child) => { // don't call for the trigger button if (child.el.nativeElement === this.trigger?.el.nativeElement) return; child.clicked.subscribe(() => { this.floatingUIService.hidefloatingUI(); }); }); } } } else if (this.listbox) { // this is for v-combobox this.listItemClose(); this.listbox.listItems.changes.subscribe(() => { this.listItemClose(); }); } } } listItemClose() { this.listbox.listItems.forEach((item) => { item.clicked.subscribe(() => { this.floatingUIService.hidefloatingUI(); }); }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FloatingUIContainer, deps: [{ token: i0.ElementRef }, { token: i1.FloatingUIService }, { token: i2.UUIDService }, { token: i3.NovaLibService }, { token: i0.Renderer2 }, { token: i4.AppReadyService }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: FloatingUIContainer, isStandalone: true, selector: "[v-floating-ui-container], [v-combobox]", inputs: { class: "class", isShown: "isShown", placement: "placement", middleware: "middleware", eventsArray: "eventsArray", closeOnClick: "closeOnClick" }, outputs: { floatingUIToggled: "floatingUIToggled" }, host: { listeners: { "document:click": "clickOut($event)", "document:keydown": "tab($event)", "focusout": "focusout($event)" }, properties: { "class": "this.hostClasses", "style.--v-dropdown-menu-surface-margin-block-start": "this.hostMarginBlockStart" } }, providers: [FloatingUIService], queries: [{ propertyName: "menu", first: true, predicate: DropdownMenuDirective, descendants: true }, { propertyName: "tooltip", first: true, predicate: TooltipDirective, descendants: true }, { propertyName: "genericDropdown", first: true, predicate: FloatingUIElementDirective, descendants: true }, { propertyName: "trigger", first: true, predicate: FloatingUITriggerDirective, descendants: true }, { propertyName: "toggleIcon", first: true, predicate: IconToggleDirective, descendants: true }, { propertyName: "toggleIconComponent", first: true, predicate: IconToggleComponent, descendants: true }, { propertyName: "listbox", first: true, predicate: ListboxDirective, descendants: true }, { propertyName: "containers", predicate: FloatingUIContainer, descendants: true }, { propertyName: "disclosureTabs", predicate: TabItemDisclosureDirective, descendants: true }, { propertyName: "buttons", predicate: ButtonDirective, descendants: true }, { propertyName: "dropdownItems", predicate: DropdownListDirective, descendants: true }, { propertyName: "accordionHeadings", predicate: AccordionHeadingDirective, descendants: true }], ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FloatingUIContainer, decorators: [{ type: Directive, args: [{ standalone: true, selector: '[v-floating-ui-container], [v-combobox]', providers: [FloatingUIService] }] }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.FloatingUIService }, { type: i2.UUIDService }, { type: i3.NovaLibService }, { type: i0.Renderer2 }, { type: i4.AppReadyService }], propDecorators: { containers: [{ type: ContentChildren, args: [FloatingUIContainer, { descendants: true }] }], disclosureTabs: [{ type: ContentChildren, args: [TabItemDisclosureDirective, { descendants: true }] }], menu: [{ type: ContentChild, args: [DropdownMenuDirective] }], tooltip: [{ type: ContentChild, args: [TooltipDirective] }], genericDropdown: [{ type: ContentChild, args: [FloatingUIElementDirective] }], trigger: [{ type: ContentChild, args: [FloatingUITriggerDirective] }], toggleIcon: [{ type: ContentChild, args: [IconToggleDirective] }], toggleIconComponent: [{ type: ContentChild, args: [IconToggleComponent] }], listbox: [{ type: ContentChild, args: [ListboxDirective] }], buttons: [{ type: ContentChildren, args: [ButtonDirective, { descendants: true }] }], dropdownItems: [{ type: ContentChildren, args: [DropdownListDirective, { descendants: true }] }], accordionHeadings: [{ type: ContentChildren, args: [AccordionHeadingDirective, { descendants: true }] }], class: [{ type: Input }], hostClasses: [{ type: HostBinding, args: ['class'] }], isShown: [{ type: Input }], placement: [{ type: Input }], middleware: [{ type: Input }], eventsArray: [{ type: Input }], closeOnClick: [{ type: Input }], floatingUIToggled: [{ type: Output }], hostMarginBlockStart: [{ type: HostBinding, args: ['style.--v-dropdown-menu-surface-margin-block-start'] }], clickOut: [{ type: HostListener, args: ['document:click', ['$event']] }], tab: [{ type: HostListener, args: ['document:keydown', ['$event']] }], focusout: [{ type: HostListener, args: ['focusout', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxvYXRpbmctdWktY29udGFpbmVyLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL2xpYnMvbm92YS1saWIvc3JjL2xpYi9mbG9hdGluZy11aS1jb250YWluZXIvZmxvYXRpbmctdWktY29udGFpbmVyLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0lBZUk7QUFDSixPQUFPLEVBQWdCLHFCQUFxQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDNUUsT0FBTyxFQUVMLFlBQVksRUFDWixlQUFlLEVBQ2YsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osV0FBVyxFQUNYLFlBQVksRUFDWixLQUFLLEVBQ0wsTUFBTSxFQUNOLFNBQVMsRUFDVCxTQUFTLEVBQ1YsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGlEQUFpRCxDQUFDO0FBQ2xGLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUNsRSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxrREFBa0QsQ0FBQztBQUM3RixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDN0QsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sc0RBQXNELENBQUM7QUFFbEcsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFDakYsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFDakYsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sc0RBQXNELENBQUM7QUFDbEcsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sc0RBQXNELENBQUM7QUFDbEcsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixvQkFBb0IsRUFFckIsTUFBTSxzQ0FBc0MsQ0FBQztBQUM5QyxPQUFPLEVBQUUsaUJBQWlCLEVB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QUFTO3NCQURaLEtBQUs7Z0JBZ0JGLFVBQVU7c0JBRGIsS0FBSztnQkFrQkYsV0FBVztzQkFEZCxLQUFLO2dCQWVGLFlBQVk7c0JBRGYsS0FBSztnQkFZSSxpQkFBaUI7c0JBQTFCLE1BQU07Z0JBS0gsb0JBQW9CO3NCQUR2QixXQUFXO3VCQUFDLG9EQUFvRDtnQkFlakUsUUFBUTtzQkFEUCxZQUFZO3VCQUFDLGdCQUFnQixFQUFFLENBQUMsUUFBUSxDQUFDO2dCQWMxQyxHQUFHO3NCQURGLFlBQVk7dUJBQUMsa0JBQWtCLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBUzVDLFFBQVE7c0JBRFAsWUFBWTt1QkFBQyxVQUFVLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqICAgICAgICAgICAgICDCqSAyMDI1IFZpc2FcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqKi9cbmltcG9ydCB7IEJvb2xlYW5JbnB1dCwgY29lcmNlQm9vbGVhblByb3BlcnR5IH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2NvZXJjaW9uJztcbmltcG9ydCB7XG4gIEFmdGVyQ29udGVudEluaXQsXG4gIENvbnRlbnRDaGlsZCxcbiAgQ29udGVudENoaWxkcmVuLFxuICBEaXJlY3RpdmUsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSG9zdEJpbmRpbmcsXG4gIEhvc3RMaXN0ZW5lcixcbiAgSW5wdXQsXG4gIE91dHB1dCxcbiAgUXVlcnlMaXN0LFxuICBSZW5kZXJlcjJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBNaWRkbGV3YXJlIH0gZnJvbSAnQGZsb2F0aW5nLXVpL2RvbSc7XG5pbXBvcnQgeyBBcHBSZWFkeVNlcnZpY2UgfSBmcm9tICcuLi9fdXRpbGl0aWVzL3NlcnZpY2VzL2FwcC1zdGFibGUtY2hlY2suc2VydmljZSc7XG5pbXBvcnQgeyBVVUlEU2VydmljZSB9IGZyb20gJy4uL191dGlsaXRpZXMvc2VydmljZXMvdXVpZC5zZXJ2aWNlJztcbmltcG9ydCB7IEFjY29yZGlvbkhlYWRpbmdEaXJlY3RpdmUgfSBmcm9tICcuLi9hY2NvcmRpb24taGVhZGluZy9hY2NvcmRpb24taGVhZGluZy5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgQnV0dG9uRGlyZWN0aXZlIH0gZnJvbSAnLi4vYnV0dG9uL2J1dHRvbi5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgVGFiSXRlbURpc2Nsb3N1cmVEaXJlY3RpdmUgfSBmcm9tICcuLi9kaXNjbG9zdXJlLXRhYi1pdGVtL2Rpc2Nsb3N1cmUtdGFiLWl0ZW0uZGlyZWN0aXZlJztcbmltcG9ydCB7IERyb3Bkb3duSXRlbURpcmVjdGl2ZSB9IGZyb20gJy4uL2Ryb3Bkb3duLWl0ZW0vZHJvcGRvd24taXRlbS5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgRHJvcGRvd25MaXN0RGlyZWN0aXZlIH0gZnJvbSAnLi4vZHJvcGRvd24tbGlzdC9kcm9wZG93bi1saXN0LmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBEcm9wZG93bk1lbnVEaXJlY3RpdmUgfSBmcm9tICcuLi9kcm9wZG93bi1tZW51L2Ryb3Bkb3duLW1lbnUuZGlyZWN0aXZlJztcbmltcG9ydCB7IEZsb2F0aW5nVUlFbGVtZW50RGlyZWN0aXZlIH0gZnJvbSAnLi4vZmxvYXRpbmctdWktZWxlbWVudC9mbG9hdGluZy11aS1lbGVtZW50LmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBGbG9hdGluZ1VJVHJpZ2dlckRpcmVjdGl2ZSB9IGZyb20gJy4uL2Zsb2F0aW5nLXVpLXRyaWdnZXIvZmxvYXRpbmctdWktdHJpZ2dlci5kaXJlY3RpdmUnO1xuaW1wb3J0IHtcbiAgRmxvYXRpbmdVSVBsYWNlbWVudHMsXG4gIEZsb2F0aW5nVUlWaXNpYmlsaXR5LFxuICBVSUV2ZW50VmlzaWJpbGl0eVBhaXJcbn0gZnJvbSAnLi4vZmxvYXRpbmctdWkvZmxvYXRpbmctdWkuY29uc3RhbnRzJztcbmltcG9ydCB7IEZsb2F0aW5nVUlTZXJ2aWNlIH0gZnJvbSAnLi4vZmxvYXRpbmctdWkvZmxvYXRpbmctdWkuc2VydmljZSc7XG5pbXBvcnQgeyBJY29uVG9nZ2xlQ29tcG9uZW50IH0gZnJvbSAnLi4vaWNvbi10b2dnbGUvaWNvbi10b2dnbGUuY29tcG9uZW50JztcbmltcG9ydCB7IEljb25Ub2dnbGVEaXJlY3RpdmUgfSBmcm9tICcuLi9pY29uLXRvZ2dsZS9pY29uLXRvZ2dsZS5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgTGlzdGJveEl0ZW1Db21wb25lbnQgfSBmcm9tICcuLi9saXN0Ym94LWl0ZW0vbGlzdGJveC1pdGVtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBMaXN0Ym94RGlyZWN0aXZlIH0gZnJvbSAnLi4vbGlzdGJveC9saXN0Ym94LmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBOb3ZhTGliU2VydmljZSB9IGZyb20gJy4uL25vdmEtbGliLnNlcnZpY2UnO1xuaW1wb3J0IHsgVG9vbHRpcERpcmVjdGl2ZSB9IGZyb20gJy4uL3Rvb2x0aXAvdG9vbHRpcC5kaXJlY3RpdmUnO1xuXG5ARGlyZWN0aXZlKHtcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgc2VsZWN0b3I6ICdbdi1mbG9hdGluZy11aS1jb250YWluZXJdLCBbdi1jb21ib2JveF0nLFxuICBwcm92aWRlcnM6IFtGbG9hdGluZ1VJU2VydmljZV1cbn0pXG5leHBvcnQgY2xhc3MgRmxvYXRpbmdVSUNvbnRhaW5lciBpbXBsZW1lbnRzIEFmdGVyQ29udGVudEluaXQge1xuICBAQ29udGVudENoaWxkcmVuKEZsb2F0aW5nVUlDb250YWluZXIsIHsgZGVzY2VuZGFudHM6IHRydWUgfSkgY29udGFpbmVyczogUXVlcnlMaXN0PEZsb2F0aW5nVUlDb250YWluZXI+O1xuICBAQ29udGVudENoaWxkcmVuKFRhYkl0ZW1EaXNjbG9zdXJlRGlyZWN0aXZlLCB7IGRlc2NlbmRhbnRzOiB0cnVlIH0pXG4gIGRpc2Nsb3N1cmVUYWJzOiBRdWVyeUxpc3Q8VGFiSXRlbURpc2Nsb3N1cmVEaXJlY3RpdmU+O1xuICBAQ29udGVudENoaWxkKERyb3Bkb3duTWVudURpcmVjdGl2ZSkgbWVudTogRHJvcGRvd25NZW51RGlyZWN0aXZlO1xuICBAQ29udGVudENoaWxkKFRvb2x0aXBEaXJlY3RpdmUpIHRvb2x0aXA6IFRvb2x0aXBEaXJlY3RpdmU7XG4gIEBDb250ZW50Q2hpbGQoRmxvYXRpbmdVSUVsZW1lbnREaXJlY3RpdmUpXG4gIGdlbmVyaWNEcm9wZG93bjogRmxvYXRpbmdVSUVsZW1lbnREaXJlY3RpdmU7XG4gIEBDb250ZW50Q2hpbGQoRmxvYXRpbmdVSVRyaWdnZXJEaXJlY3RpdmUpIHRyaWdnZXI6IEZsb2F0aW5nVUlUcmlnZ2VyRGlyZWN0aXZlO1xuICBAQ29udGVudENoaWxkKEljb25Ub2dnbGVEaXJlY3RpdmUpIHRvZ2dsZUljb246IEljb25Ub2dnbGVEaXJlY3RpdmU7XG4gIEBDb250ZW50Q2hpbGQoSWNvblRvZ2dsZUNvbXBvbmVudCkgdG9nZ2xlSWNvbkNvbXBvbmVudDogSWNvblRvZ2dsZUNvbXBvbmVudDtcbiAgQENvbnRlbnRDaGlsZChMaXN0Ym94RGlyZWN0aXZlKSBsaXN0Ym94OiBMaXN0Ym94RGlyZWN0aXZlO1xuICBAQ29udGVudENoaWxkcmVuKEJ1dHRvbkRpcmVjdGl2ZSwgeyBkZXNjZW5kYW50czogdHJ1ZSB9KSBidXR0b25zOiBRdWVyeUxpc3Q8QnV0dG9uRGlyZWN0aXZlPjtcbiAgQENvbnRlbnRDaGlsZHJlbihEcm9wZG93bkxpc3REaXJlY3RpdmUsIHsgZGVzY2VuZGFudHM6IHRydWUgfSkgZHJvcGRvd25JdGVtczogUXVlcnlMaXN0PERyb3Bkb3duSXRlbURpcmVjdGl2ZT47XG4gIEBDb250ZW50Q2hpbGRyZW4oQWNjb3JkaW9uSGVhZGluZ0RpcmVjdGl2ZSwgeyBkZXNjZW5kYW50czogdHJ1ZSB9KSBhY2NvcmRpb25IZWFkaW5nczogUXVlcnlMaXN0PEFjY29yZGlvbkhlYWRpbmdEaXJlY3RpdmU+O1xuXG4gIF9pc0NvbWJvYm94OiBib29sZWFuID0gZmFsc2U7XG4gIGRyb3Bkb3duTWVudVNob3duOiBib29sZWFuO1xuICBfdG9vbHRpcERlZmF1bHRFdmVudHM6IFVJRXZlbnRWaXNpYmlsaXR5UGFpciA9IFtcbiAgICBbbmV3IFVJRXZlbnQoJ21vdXNlZW50ZXInKSwgRmxvYXRpbmdVSVZpc2liaWxpdHkuU0hPV10sXG4gICAgW25ldyBVSUV2ZW50KCdtb3VzZWxlYXZlJyksIEZsb2F0aW5nVUlWaXNpYmlsaXR5LkhJREVdLFxuICAgIFtuZXcgVUlFdmVudCgnZm9jdXMnKSwgRmxvYXRpbmdVSVZpc2liaWxpdHkuU0hPV10sXG4gICAgW25ldyBVSUV2ZW50KCdibHVyJyksIEZsb2F0aW5nVUlWaXNpYmlsaXR5LkhJREVdXG4gIF07XG4gIF9kcm9wZG93bk1lbnVEZWZhdWx0RXZlbnRzOiBVSUV2ZW50VmlzaWJpbGl0eVBhaXIgPSBbW25ldyBVSUV2ZW50KCdjbGljaycpXV07XG5cbiAgLyoqXG4gICAqIFByb3ZpZGVzIGN1c3RvbSBjbGFzcyYjNDA7ZXMmIzQxOyBmb3IgY3VzdG9tIHN0eWxpbmcuXG4gICAqL1xuICBASW5wdXQoKVxuICBwdWJsaWMgZ2V0IGNsYXNzKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX2NsYXNzO1xuICB9XG4gIHB1YmxpYyBzZXQgY2xhc3ModmFsdWU6IHN0cmluZykge1xuICAgIHRoaXMuX2NsYXNzID0gdmFsdWU7XG4gIH1cbiAgX2NsYXNzOiBzdHJpbmcgPSAnJzsgLy8gb3ZlcnJpZGUgdGhlIHN0YW5kYXJkIGNsYXNzIGF0dHIgd2l0aCBhIG5ldyBvbmUuXG4gIEBIb3N0QmluZGluZygnY2xhc3MnKVxuICBnZXQgaG9zdENsYXNzZXMoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5jbGFzcztcbiAgfVxuXG4gIC8qKiBAaWdub3JlICovXG4gIEBJbnB1dCgpXG4gIGdldCBpc1Nob3duKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9pc1Nob3duO1xuICB9XG4gIHNldCBpc1Nob3duKHZhbHVlOiBCb29sZWFuSW5wdXQpIHtcbiAgICB0aGlzLl9pc1Nob3duID0gY29lcmNlQm9vbGVhblByb3BlcnR5KHZhbHVlKTtcbiAgfVxuICBfaXNTaG93bjogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBQbGFjZW1lbnQgb2YgZmxvYXRpbmcgY29udGVudCByZWxldmFudCB0byB0cmlnZ2VyaW5nIGVsZW1lbnQuXG4gICAqIEBkZWZhdWx0IEZsb2F0aW5nVUlQbGFjZW1lbnRzLkJPVFRPTV9TVEFSVFxuICAgKiBAc2VlICdGbG9hdGluZ1VJUGxhY2VtZW50cycuXG4gICAqL1xuICBASW5wdXQoKVxuICBnZXQgcGxhY2VtZW50KCk6IEZsb2F0aW5nVUlQbGFjZW1lbnRzIHtcbiAgICByZXR1cm4gdGhpcy5fcGxhY2VtZW50O1xuICB9XG4gIHNldCBwbGFjZW1lbnQodmFsdWU6IEZsb2F0aW5nVUlQbGFjZW1lbnRzKSB7XG4gICAgdGhpcy5fcGxhY2VtZW50ID0gdmFsdWU7XG4gIH1cbiAgX3BsYWNlbWVudDogRmxvYXRpbmdVSVBsYWNlbWVudHMgPSBGbG9hdGluZ1VJUGxhY2VtZW50cy5CT1RUT01fU1RBUlQ7XG5cbiAgLyoqXG4gICAqIE1pZGRsZXdhcmUgZm9yIEZsb2F0aW5nVUlTZXJ2aWNlLlxuICAgKiBAZGVmYXVsdCBbIG9mZnNldCgyKSwgZmxpcCgpLCBzaGlmdCgpIF0gZm9yIHRvb2x0aXAgPGJyIC8+XG4gICAqIEBkZWZhdWx0IFsgb2Zmc2V0KDApLCBmbGlwKCksIHNoaWZ0KCkgXSBmb3IgY29tYm9ib3ggPGJyIC8+XG4gICAqIEBzZWUgW0Zsb2F0aW5nIFVJXShodHRwczovL2Zsb2F0aW5nLXVpLmNvbS9kb2NzL21pZGRsZXdhcmUpIGZvciBvcHRpb25zLlxuICAgKi9cbiAgQElucHV0KClcbiAgZ2V0IG1pZGRsZXdhcmUoKTogTWlkZGxld2FyZVtdIHtcbiAgICByZXR1cm4gdGhpcy5fbWlkZGxld2FyZTtcbiAgfVxuICBzZXQgbWlkZGxld2FyZSh2YWx1ZTogTWlkZGxld2FyZVtdKSB7XG4gICAgdGhpcy5fbWlkZGxld2FyZSA9IHZhbHVlO1xuICB9XG4gIF9taWRkbGV3YXJlOiBNaWRkbGV3YXJlW107XG5cbiAgLyoqXG4gICAqIEV2ZW50cyBhcnJheSBmb3IgRmxvYXRpbmdVSVNlcnZpY2UuIDxiciAvPlxuICAgKiBUaGlzIGFycmF5IHNwZWNpZmllcyB3aGV0aGVyIHRvIHNob3cgb3IgaGlkZSB0aGUgZmxvYXRpbmcgZWxlbWVudCBvbiBhIGdpdmVuIFVJRXZlbnQuIDxiciAvPlxuICAgKiBUaGlzIHNob3VsZCBiZSBhbiBhcnJheSBvZiBbVUlFdmVudCwgRmxvYXRpbmdVSVZpc2liaWxpdHldLlxuICAgKiBAZGVmYXVsdCBbIFtuZXcgVUlFdmVudCgnbW91c2VlbnRlcicpLCBGbG9hdGluZ1VJVmlzaWJpbGl0eS5TSE9XXSwgPGJyIC8+IFtuZXcgVUlFdmVudCgnbW91c2VsZWF2ZScpLCBGbG9hdGluZ1VJVmlzaWJpbGl0eS5ISURFXSwgPGJyIC8+IFtuZXcgVUlFdmVudCgnZm9jdXMnKSwgRmxvYXRpbmdVSVZpc2liaWxpdHkuU0hPV10sIDxiciAvPiBbbmV3IFVJRXZlbnQoJ2JsdXInKSwgRmxvYXRpbmdVSVZpc2liaWxpdHkuSElERV0gPGJyIC8+XSBmb3IgdG9vbHRpcFxuICAgKiBAZGVmYXVsdCBbIFtuZXcgVUlFdmVudCgnY2xpY2snKV0gXSBmb3IgZHJvcGRvd24tbWVudSBhbmQgZmxvYXRpbmctdWktZWxlbWVudFxuICAgKiBAZGVmYXVsdCBbXSBJZS4gZXZlbnRzIGFyZSByZW1vdmVkIGZvciBjb21ib2JveC5cbiAgICovXG4gIEBJbnB1dCgpXG4gIGdldCBldmVudHNBcnJheSgpOiBVSUV2ZW50VmlzaWJpbGl0eVBhaXIge1xuICAgIHJldHVybiB0aGlzLl9ldmVudHNBcnJheTtcbiAgfVxuICBzZXQgZXZlbnRzQXJyYXkodmFsdWU6IFVJRXZlbnRWaXNpYmlsaXR5UGFpcikge1xuICAgIHRoaXMuX2V2ZW50c0FycmF5ID0gdmFsdWU7XG4gIH1cbiAgX2V2ZW50c0FycmF5OiBVSUV2ZW50VmlzaWJpbGl0eVBhaXI7XG5cbiAgLyoqXG4gICAqIENsb3NlcyB0aGUgbWVudSBvbiBpdGVtIGlzIGNsaWNrL3NlbGVjdCB3aGVuIHRydWUuIDxicj5cbiAgICogSWYgPGNvZGU+bXVsdGlzZWxlY3Q8L2NvZGU+IGlzIHNldCB0byA8Y29kZT50cnVlPC9jb2RlPiwgaXQgd2lsbCBub3QgdGFrZSBlZmZlY3QuPGJyPlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICBASW5wdXQoKVxuICBnZXQgY2xvc2VPbkNsaWNrKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9jbG9zZU9uQ2xpY2s7XG4gIH1cbiAgc2V0IGNsb3NlT25DbGljayh2YWx1ZTogQm9vbGVhbklucHV0KSB7XG4gICAgdGhpcy5fY2xvc2VPbkNsaWNrID0gY29lcmNlQm9vbGVhblByb3BlcnR5KHZhbHVlKTtcbiAgfVxuICBfY2xvc2VPbkNsaWNrOiBib29sZWFuID0gdHJ1ZTtcblxuICAvKipcbiAgICogRW1pdHMgd2hldGhlciBvciBub3QgdGhlIGZsb2F0aW5nIFVJIGVsZW1lbnQgaXMgdmlzaWJsZS5cbiAgICovXG4gIEBPdXRwdXQoKSBmbG9hdGluZ1VJVG9nZ2xlZCA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcblxuICAvLyB0aGlzIGlzIGFuIGFuZ3VsYXItc3BlY2lmaWMgb3ZlcnJpZGUuIFNwYWNpbmcgYmV0d2VlbiBkcm9wZG93bi1tZW51IGFuZCBidXR0b24vdHJpZ2dlclxuICAvLyBpcyBoYW5kbGVkIHdpdGhpbiBmbG9hdGluZy11aS5zZXJ2aWNlXG4gIEBIb3N0QmluZGluZygnc3R5bGUuLS12LWRyb3Bkb3duLW1lbnUtc3VyZmFjZS1tYXJnaW4tYmxvY2stc3RhcnQnKVxuICBnZXQgaG9zdE1hcmdpbkJsb2NrU3RhcnQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gJzAnO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIGVsOiBFbGVtZW50UmVmLFxuICAgIHB1YmxpYyBmbG9hdGluZ1VJU2VydmljZTogRmxvYXRpbmdVSVNlcnZpY2UsXG4gICAgcHJpdmF0ZSB1dWlkU2VydmljZTogVVVJRFNlcnZpY2UsXG4gICAgcHVibGljIG5vdmFMaWJTZXJ2aWNlOiBOb3ZhTGliU2VydmljZSxcbiAgICBwcml2YXRlIHJlbmRlcmVyOiBSZW5kZXJlcjIsXG4gICAgcHJpdmF0ZSBhcHBSZWFkeVNlcnZpY2U6IEFwcFJlYWR5U2VydmljZVxuICApIHsgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmNsaWNrJywgWyckZXZlbnQnXSlcbiAgY2xpY2tPdXQoZXZlbnQ6IEV2ZW50KSB7XG4gICAgLy8gbGlzdGVuIGZvciBkb2N1bWVudCBjbGljayBhbmQgY2xvc2UgbWVudSBpZiBjbGljayBpcyBvdXRzaWRlIG9mIGNvbXBvbmVudFxuICAgIGlmIChcbiAgICAgIHRoaXMuYXBwUmVhZHlTZXJ2aWNlLmlzQnJvd3NlckFuZERvbUF2YWlsYWJsZSgpICYmXG4gICAgICB0aGlzLmlzU2hvd24gJiZcbiAgICAgICF0aGlzLmVsLm5hdGl2ZUVsZW1lbnQuY29udGFpbnMoZXZlbnQudGFyZ2V0KVxuICAgICkge1xuICAgICAgdGhpcy5mbG9hdGluZ1VJU2VydmljZS5oaWRlZmxvYXRpbmdVSSgpO1xuICAgIH1cbiAgfVxuXG4gIF90YWJQcmVzc2VkID0gZmFsc2U7XG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmtleWRvd24nLCBbJyRldmVudCddKVxuICB0YWIoZXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcbiAgICBpZiAoZXZlbnQua2V5ID09PSAnVGFiJykge1xuICAgICAgLy8gdXNlZCBpbiBmb2N1c291dCBmdW5jdGlvblxuICAgICAgdGhpcy5fdGFiUHJlc3NlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZm9jdXNvdXQnLCBbJyRldmVudCddKVxuICBmb2N1c291dChldmVudDogRm9jdXNFdmVudCkge1xuICAgIGlmICh0aGlzLl90YWJQcmVzc2VkKSB7XG4gICAgICAvLyBpZiBmb2N1cyBvdXQgaXMgYSByZXN1bHQgb2YgdGFiYmluZyBvdXQgb2YgdGhpcyBjb21wb25lbnQsIGhpZGUgdGhlIGZsb2F0aW5nIFVJXG4gICAgICBpZiAoZXZlbnQucmVsYXRlZFRhcmdldCAmJiAhdGhpcy5lbC5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKGV2ZW50LnJlbGF0ZWRUYXJnZXQpKSB7XG4gICAgICAgIHRoaXMuZmxvYXRpbmdVSVNlcnZpY2UuaGlkZWZsb2F0aW5nVUkoKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX3RhYlByZXNzZWQgPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBuZ0FmdGVyQ29udGVudEluaXQoKTogdm9pZCB7XG4gICAgbGV0IGZsb2F0aW5nRWxlbTogRHJvcGRvd25NZW51RGlyZWN0aXZlIHwgVG9vbHRpcERpcmVjdGl2ZSB8IEZsb2F0aW5nVUlFbGVtZW50RGlyZWN0aXZlIHwgbnVsbCA9IG51bGw7XG4gICAgbGV0IF90b2dnbGVJY29uOiBJY29uVG9nZ2xlRGlyZWN0aXZlO1xuICAgIGxldCBfdG9nZ2xlSWNvbkNvbXBvbmVudDogSWNvblRvZ2dsZUNvbXBvbmVudDtcbiAgICBjb25zdCB0b2dnbGVJbkNoaWxkQ29udGFpbmVyID1cbiAgICAgIHRoaXMuY29udGFpbmVycy5zb21lKChjb250YWluZXIpID0+IGNvbnRhaW5lci50b2dnbGVJY29uID09PSB0aGlzLnRvZ2dsZUljb24pIHx8XG4gICAgICB0aGlzLmRpc2Nsb3N1cmVUYWJzLnNvbWUoKHRhYikgPT4gdGFiLmJ1dHRvbi50b2dnbGVJY29uID09PSB0aGlzLnRvZ2dsZUljb24pIHx8XG4gICAgICB0aGlzLmFjY29yZGlvbkhlYWRpbmdzLnNvbWUoXG4gICAgICAgIChoZWFkaW5nKSA9PlxuICAgICAgICAgIGhlYWRpbmcuaG9zdEJ1dHRvbj8udG9nZ2xlSWNvbiA9PT0gdGhpcy50b2dnbGVJY29uIHx8IGhlYWRpbmcuX2J1dHRvbkhlYWRpbmc/LnRvZ2dsZUljb24gPT09IHRoaXMudG9nZ2xlSWNvblxuICAgICAgKTtcbiAgICBjb25zdCB0b2dnbGVDb21wb25lbnRJbkNoaWxkQ29udGFpbmVyID1cbiAgICAgIHRoaXMuY29udGFpbmVycy5zb21lKChjb250YWluZXIpID0+IGNvbnRhaW5lci50b2dnbGVJY29uQ29tcG9uZW50ID09PSB0aGlzLnRvZ2dsZUljb25Db21wb25lbnQpIHx8XG4gICAgICB0aGlzLmRpc2Nsb3N1cmVUYWJzLnNvbWUoKHRhYikgPT4gdGFiLmJ1dHRvbi50b2dnbGVJY29uQ29tcG9uZW50ID09PSB0aGlzLnRvZ2dsZUljb25Db21wb25lbnQpIHx8XG4gICAgICB0aGlzLmFjY29yZGlvbkhlYWRpbmdzLnNvbWUoXG4gICAgICAgIChoZWFkaW5nKSA9PlxuICAgICAgICAgIGhlYWRpbmcuaG9zdEJ1dHRvbj8udG9nZ2xlSWNvbkNvbXBvbmVudCA9PT0gdGhpcy50b2dnbGVJY29uQ29tcG9uZW50IHx8XG4gICAgICAgICAgaGVhZGluZy5fYnV0dG9uSGVhZGluZz8udG9nZ2xlSWNvbkNvbXBvbmVudCA9PT0gdGhpcy50b2dnbGVJY29uQ29tcG9uZW50XG4gICAgICApO1xuXG4gICAgaWYgKHRoaXMudG9nZ2xlSWNvbiAmJiAhdG9nZ2xlSW5DaGlsZENvbnRhaW5lcikge1xuICAgICAgX3RvZ2dsZUljb24gPSB0aGlzLnRvZ2dsZUljb247XG4gICAgICBfdG9nZ2xlSWNvbi5pY29uLmljb24gPSB0aGlzLmlzU2hvd24gPyBfdG9nZ2xlSWNvbi5leHBhbmRlZEljb24gOiBfdG9nZ2xlSWNvbi5jb2xsYXBzZWRJY29uO1xuICAgIH0gZWxzZSBpZiAodGhpcy50b2dnbGVJY29uQ29tcG9uZW50ICYmICF0b2dnbGVDb21wb25lbnRJbkNoaWxkQ29udGFpbmVyKSB7XG4gICAgICBfdG9nZ2xlSWNvbkNvbXBvbmVudCA9IHRoaXMudG9nZ2xlSWNvbkNvbXBvbmVudDtcbiAgICAgIF90b2dnbGVJY29uQ29tcG9uZW50Ll9mbG9hdGluZ1VJVG9nZ2xlID0gdHJ1ZTtcbiAgICAgIF90b2dnbGVJY29uQ29tcG9uZW50LnJvdGF0ZWQgPSB0aGlzLmlzU2hvd247XG4gICAgfVxuXG4gICAgY29uc3QgdG9vbHRpcEluQ2hpbGRDb250YWluZXIgPSB0aGlzLmNvbnRhaW5lcnMuc29tZSgoY29udGFpbmVyKSA9PiBjb250YWluZXIudG9vbHRpcCA9PT0gdGhpcy50b29sdGlwKTtcbiAgICBjb25zdCBtZW51SW5DaGlsZENvbnRhaW5lciA9IHRoaXMuY29udGFpbmVycy5zb21lKChjb250YWluZXIpID0+IGNvbnRhaW5lci5tZW51ID09PSB0aGlzLm1lbnUpO1xuICAgIGNvbnN0IGRyb3Bkb3duSW5DaGlsZENvbnRhaW5lciA9IHRoaXMuY29udGFpbmVycy5zb21lKFxuICAgICAgKGNvbnRhaW5lcikgPT4gY29udGFpbmVyLmdlbmVyaWNEcm9wZG93biA9PT0gdGhpcy5nZW5lcmljRHJvcGRvd25cbiAgICApO1xuXG4gICAgaWYgKHRoaXMubWVudSAmJiAhbWVudUluQ2hpbGRDb250YWluZXIpIHtcbiAgICAgIGZsb2F0aW5nRWxlbSA9IHRoaXMubWVudTtcbiAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5tZW51LmVsLm5hdGl2ZUVsZW1lbnQsICdwb3NpdGlvbicsICdhYnNvbHV0ZScpO1xuICAgICAgdGhpcy50cmlnZ2VyLl90cmlnZ2Vyc0Ryb3Bkb3duTWVudSA9IHRydWU7XG4gICAgICBmbG9hdGluZ0VsZW0uaWQgPSB0aGlzLm1lbnUuaWQgPyB0aGlzLm1lbnUuaWQgOiB0aGlzLnV1aWRTZXJ2aWNlLmdldFVVSUQoJ3YtZmxvYXRpbmctJyk7XG4gICAgICB0aGlzLm1lbnUuX2lzU2hvd24gPSB0aGlzLmlzU2hvd247XG4gICAgICB0aGlzLmV2ZW50c0FycmF5ID0gdGhpcy5ldmVudHNBcnJheSA/IHRoaXMuZXZlbnRzQXJyYXkgOiB0aGlzLl9kcm9wZG93bk1lbnVEZWZhdWx0RXZlbnRzO1xuICAgICAgdGhpcy5zZXRVcExpc3RJdGVtcygpO1xuICAgIH0gZWxzZSBpZiAodGhpcy50b29sdGlwICYmICF0b29sdGlwSW5DaGlsZENvbnRhaW5lcikge1xuICAgICAgZmxvYXRpbmdFbGVtID0gdGhpcy50b29sdGlwO1xuICAgICAgdGhpcy50cmlnZ2VyLl90cmlnZ2Vyc1Rvb2x0aXAgPSB0cnVlO1xuICAgICAgdGhpcy5ldmVudHNBcnJheSA9IHRoaXMuZXZlbnRzQXJyYXkgPyB0aGlzLmV2ZW50c0FycmF5IDogdGhpcy5fdG9vbHRpcERlZmF1bHRFdmVudHM7XG4gICAgfSBlbHNlIGlmICh0aGlzLmdlbmVyaWNEcm9wZG93biAmJiAhZHJvcGRvd25JbkNoaWxkQ29udGFpbmVyKSB7XG4gICAgICBmbG9hdGluZ0VsZW0gPSB0aGlzLmdlbmVyaWNEcm9wZG93bjtcbiAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5nZW5lcmljRHJvcGRvd24uZWwubmF0aXZlRWxlbWVudCwgJ3Bvc2l0aW9uJywgJ2Fic29sdXRlJyk7XG4gICAgICB0aGlzLmV2ZW50c0FycmF5ID0gdGhpcy5ldmVudHNBcnJheSA/IHRoaXMuZXZlbnRzQXJyYXkgOiB0aGlzLl9kcm9wZG93bk1lbnVEZWZhdWx0RXZlbnRzO1xuICAgICAgdGhpcy5zZXRVcExpc3RJdGVtcygpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnRyaWdnZXI/LmVsICYmIGZsb2F0aW5nRWxlbT8uZWwpIHtcbiAgICAgIGZsb2F0aW5nRWxlbS5pZCA9IGZsb2F0aW5nRWxlbS5pZCA/IGZsb2F0aW5nRWxlbS5pZCA6IHRoaXMudXVpZFNlcnZpY2UuZ2V0VVVJRCgndi1mbG9hdGluZy0nKTtcbiAgICAgIHRoaXMudHJpZ2dlci5fZmxvYXRpbmdFbGVtSUQgPSBmbG9hdGluZ0VsZW0uaWQ7XG4gICAgICBpZiAodGhpcy50b29sdGlwPy5hcnJvdykge1xuICAgICAgICB0aGlzLmZsb2F0aW5nVUlTZXJ2aWNlLmN1c3RvbWl6ZUZsb2F0aW5nVUkoXG4gICAgICAgICAgdGhpcy5wbGFjZW1lbnQsXG4gICAgICAgICAgdGhpcy5taWRkbGV3YXJlLFxuICAgICAgICAgIHRoaXMudG9vbHRpcC5kaXNwbGF5IHx8ICdibG9jaycsXG4gICAgICAgICAgdGhpcy50b29sdGlwLmFycm93XG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoIXRoaXMubWlkZGxld2FyZSAmJiB0aGlzLl9pc0NvbWJvYm94KSB7XG4gICAgICAgICAgdGhpcy5taWRkbGV3YXJlID0gdGhpcy5mbG9hdGluZ1VJU2VydmljZS5jb21ib2JveE1pZGRsZXdhcmU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5mbG9hdGluZ1VJU2VydmljZS5jdXN0b21pemVGbG9hdGluZ1VJKHRoaXMucGxhY2VtZW50LCB0aGlzLm1pZGRsZXdhcmUpO1xuICAgICAgfVxuICAgICAgdGhpcy