UNPKG

ng-zorro-antd

Version:

An enterprise-class UI components based on Ant Design and Angular

612 lines 54.6 kB
/** * @fileoverview added by tsickle * Generated from: tabset.component.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { __decorate, __metadata } from "tslib"; /** * @license * Copyright Alibaba.com All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE */ /** get some code from https://github.com/angular/material2 */ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChildren, ElementRef, EventEmitter, Input, Optional, Output, QueryList, Renderer2, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core'; import { NavigationEnd, Router } from '@angular/router'; import { NzConfigService, WithConfig } from 'ng-zorro-antd/core/config'; import { PREFIX } from 'ng-zorro-antd/core/logger'; import { InputBoolean, toNumber, wrapIntoObservable } from 'ng-zorro-antd/core/util'; import { merge, Subject, Subscription } from 'rxjs'; import { filter, first, startWith, takeUntil } from 'rxjs/operators'; import { NzTabComponent } from './tab.component'; import { NzTabChangeEvent } from './table.types'; import { NzTabsNavComponent } from './tabs-nav.component'; /** @type {?} */ const NZ_CONFIG_COMPONENT_NAME = 'tabs'; export class NzTabSetComponent { /** * @param {?} nzConfigService * @param {?} renderer * @param {?} elementRef * @param {?} cdr * @param {?} router */ constructor(nzConfigService, renderer, elementRef, cdr, router) { this.nzConfigService = nzConfigService; this.renderer = renderer; this.elementRef = elementRef; this.cdr = cdr; this.router = router; this.indexToSelect = 0; this.el = this.elementRef.nativeElement; this._selectedIndex = null; /** * Subscription to tabs being added/removed. */ this.tabsSubscription = Subscription.EMPTY; /** * Subscription to changes in the tab labels. */ this.tabLabelSubscription = Subscription.EMPTY; this.destroy$ = new Subject(); this.tabPositionMode = 'horizontal'; this.nzHideAll = false; this.nzTabPosition = 'top'; this.nzLinkRouter = false; this.nzLinkExact = true; this.nzCanDeactivate = null; this.nzOnNextClick = new EventEmitter(); this.nzOnPrevClick = new EventEmitter(); this.nzSelectChange = new EventEmitter(true); this.nzSelectedIndexChange = new EventEmitter(); } /** * @param {?} value * @return {?} */ set nzSelectedIndex(value) { this.indexToSelect = value ? toNumber(value, null) : null; } /** * @return {?} */ get nzSelectedIndex() { return this._selectedIndex; } /** * @return {?} */ get inkBarAnimated() { return this.nzAnimated === true || ((/** @type {?} */ (this.nzAnimated))).inkBar === true; } /** * @return {?} */ get tabPaneAnimated() { return this.nzAnimated === true || ((/** @type {?} */ (this.nzAnimated))).tabPane === true; } /** * @return {?} */ get isAnimationDisabled() { return this.nzAnimated === false || ((/** @type {?} */ (this.nzAnimated))).tabPane === false; } /** * @param {?} value * @return {?} */ setPosition(value) { if (this.tabContent) { if (value === 'bottom') { this.renderer.insertBefore(this.el, this.tabContent.nativeElement, this.nzTabsNavComponent.elementRef.nativeElement); } else { this.renderer.insertBefore(this.el, this.nzTabsNavComponent.elementRef.nativeElement, this.tabContent.nativeElement); } } } /** * @param {?} index * @param {?} disabled * @return {?} */ clickLabel(index, disabled) { if (!disabled) { if (this.nzSelectedIndex !== null && this.nzSelectedIndex !== index && typeof this.nzCanDeactivate === 'function') { /** @type {?} */ const observable = wrapIntoObservable(this.nzCanDeactivate(this.nzSelectedIndex, index)); observable.pipe(first(), takeUntil(this.destroy$)).subscribe((/** * @param {?} canChange * @return {?} */ canChange => canChange && this.emitClickEvent(index))); } else { this.emitClickEvent(index); } } } /** * @private * @param {?} index * @return {?} */ emitClickEvent(index) { /** @type {?} */ const tabs = this.listOfNzTabComponent.toArray(); this.nzSelectedIndex = index; tabs[index].nzClick.emit(); this.cdr.markForCheck(); } /** * @param {?} index * @return {?} */ createChangeEvent(index) { /** @type {?} */ const event = new NzTabChangeEvent(); event.index = index; if (this.listOfNzTabComponent && this.listOfNzTabComponent.length) { event.tab = this.listOfNzTabComponent.toArray()[index]; this.listOfNzTabComponent.forEach((/** * @param {?} item * @param {?} i * @return {?} */ (item, i) => { if (i !== index) { item.nzDeselect.emit(); } })); event.tab.nzSelect.emit(); } return event; } /** * Clamps the given index to the bounds of 0 and the tabs length. * @private * @param {?} index * @return {?} */ clampTabIndex(index) { // Note the `|| 0`, which ensures that values like NaN can't get through // and which would otherwise throw the component into an infinite loop // (since Math.max(NaN, 0) === NaN). return Math.min(this.listOfNzTabComponent.length - 1, Math.max(index || 0, 0)); } /** * @private * @return {?} */ subscribeToTabLabels() { if (this.tabLabelSubscription) { this.tabLabelSubscription.unsubscribe(); } this.tabLabelSubscription = merge(...this.listOfNzTabComponent.map((/** * @param {?} tab * @return {?} */ tab => tab.stateChanges))).subscribe((/** * @return {?} */ () => this.cdr.markForCheck())); } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { const { nzTabPosition, nzType } = changes; if (nzTabPosition) { if (this.nzTabPosition === 'top' || this.nzTabPosition === 'bottom') { this.tabPositionMode = 'horizontal'; } else { this.tabPositionMode = 'vertical'; } this.setPosition(this.nzTabPosition); } if (nzType) { if (this.nzType === 'card') { this.nzAnimated = false; } } } /** * @return {?} */ ngAfterContentChecked() { if (this.listOfNzTabComponent && this.listOfNzTabComponent.length) { // Don't clamp the `indexToSelect` immediately in the setter because it can happen that // the amount of tabs changes before the actual change detection runs. /** @type {?} */ const indexToSelect = (this.indexToSelect = this.clampTabIndex(this.indexToSelect)); // If there is a change in selected index, emit a change event. Should not trigger if // the selected index has not yet been initialized. if (this._selectedIndex !== indexToSelect) { /** @type {?} */ const isFirstRun = this._selectedIndex == null; if (!isFirstRun) { this.nzSelectChange.emit(this.createChangeEvent(indexToSelect)); } // Changing these values after change detection has run // since the checked content may contain references to them. Promise.resolve().then((/** * @return {?} */ () => { this.listOfNzTabComponent.forEach((/** * @param {?} tab * @param {?} index * @return {?} */ (tab, index) => (tab.isActive = index === indexToSelect))); if (!isFirstRun) { this.nzSelectedIndexChange.emit(indexToSelect); } })); } // Setup the position for each tab and optionally setup an origin on the next selected tab. this.listOfNzTabComponent.forEach((/** * @param {?} tab * @param {?} index * @return {?} */ (tab, index) => { tab.position = index - indexToSelect; // If there is already a selected tab, then set up an origin for the next selected tab // if it doesn't have one already. if (this._selectedIndex != null && tab.position === 0 && !tab.origin) { tab.origin = indexToSelect - this._selectedIndex; } })); if (this._selectedIndex !== indexToSelect) { this._selectedIndex = indexToSelect; this.cdr.markForCheck(); } } } /** * @return {?} */ ngAfterContentInit() { this.subscribeToTabLabels(); this.setPosition(this.nzTabPosition); if (this.nzLinkRouter) { if (!this.router) { throw new Error(`${PREFIX} you should import 'RouterModule' if you want to use 'nzLinkRouter'!`); } this.router.events .pipe(takeUntil(this.destroy$), filter((/** * @param {?} e * @return {?} */ e => e instanceof NavigationEnd)), startWith(true)) .subscribe((/** * @return {?} */ () => { this.updateRouterActive(); this.cdr.markForCheck(); })); } // Subscribe to changes in the amount of tabs, in order to be // able to re-render the content as new tabs are added or removed. this.tabsSubscription = this.listOfNzTabComponent.changes.subscribe((/** * @return {?} */ () => { /** @type {?} */ const indexToSelect = this.clampTabIndex(this.indexToSelect); // Maintain the previously-selected tab if a new tab is added or removed and there is no // explicit change that selects a different tab. if (indexToSelect === this._selectedIndex) { /** @type {?} */ const tabs = this.listOfNzTabComponent.toArray(); for (let i = 0; i < tabs.length; i++) { if (tabs[i].isActive) { // Assign both to the `_indexToSelect` and `_selectedIndex` so we don't fire a changed // event, otherwise the consumer may end up in an infinite loop in some edge cases like // adding a tab within the `selectedIndexChange` event. this.indexToSelect = this._selectedIndex = i; break; } } } this.subscribeToTabLabels(); this.cdr.markForCheck(); })); } /** * @return {?} */ ngOnDestroy() { this.tabsSubscription.unsubscribe(); this.tabLabelSubscription.unsubscribe(); this.destroy$.next(); this.destroy$.complete(); } /** * @private * @return {?} */ updateRouterActive() { if (this.router.navigated) { /** @type {?} */ const index = this.findShouldActiveTabIndex(); if (index !== this._selectedIndex) { this.nzSelectedIndex = index; this.nzSelectedIndexChange.emit(index); } this.nzHideAll = index === -1; } } /** * @private * @return {?} */ findShouldActiveTabIndex() { /** @type {?} */ const tabs = this.listOfNzTabComponent.toArray(); /** @type {?} */ const isActive = this.isLinkActive(this.router); return tabs.findIndex((/** * @param {?} tab * @return {?} */ tab => { /** @type {?} */ const c = tab.linkDirective; return c ? isActive(c.routerLink) || isActive(c.routerLinkWithHref) : false; })); } /** * @private * @param {?} router * @return {?} */ isLinkActive(router) { return (/** * @param {?=} link * @return {?} */ (link) => (link ? router.isActive(link.urlTree, this.nzLinkExact) : false)); } } NzTabSetComponent.decorators = [ { type: Component, args: [{ selector: 'nz-tabset', exportAs: 'nzTabset', preserveWhitespaces: false, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: ` <ng-container *ngIf="listOfNzTabComponent"> <nz-tabs-nav role="tablist" tabindex="0" [nzSize]="nzSize" [nzTabPosition]="nzTabPosition" [nzType]="nzType" [nzShowPagination]="nzShowPagination" [nzPositionMode]="tabPositionMode" [nzAnimated]="inkBarAnimated" [ngStyle]="nzTabBarStyle" [nzHideBar]="nzHideAll" [nzTabBarExtraContent]="nzTabBarExtraContent" [selectedIndex]="nzSelectedIndex" (nzOnNextClick)="nzOnNextClick.emit()" (nzOnPrevClick)="nzOnPrevClick.emit()" > <div nz-tab-label role="tab" [style.margin-right.px]="nzTabBarGutter" [class.ant-tabs-tab-active]="nzSelectedIndex == i && !nzHideAll" [disabled]="tab.nzDisabled" (click)="clickLabel(i, tab.nzDisabled)" *ngFor="let tab of listOfNzTabComponent; let i = index" > <ng-container *nzStringTemplateOutlet="tab.nzTitle || tab.title">{{ tab.nzTitle }}</ng-container> </div> </nz-tabs-nav> <div #tabContent class="ant-tabs-content" [class.ant-tabs-top-content]="nzTabPosition === 'top'" [class.ant-tabs-bottom-content]="nzTabPosition === 'bottom'" [class.ant-tabs-left-content]="nzTabPosition === 'left'" [class.ant-tabs-right-content]="nzTabPosition === 'right'" [class.ant-tabs-content-animated]="tabPaneAnimated" [class.ant-tabs-card-content]="nzType === 'card'" [class.ant-tabs-content-no-animated]="!tabPaneAnimated" [style.margin-left.%]="tabPositionMode === 'horizontal' && tabPaneAnimated && -(nzSelectedIndex || 0) * 100" > <div nz-tab-body class="ant-tabs-tabpane" *ngFor="let tab of listOfNzTabComponent; let i = index" [active]="nzSelectedIndex == i && !nzHideAll" [forceRender]="tab.nzForceRender" [content]="tab.template || tab.content" ></div> </div> </ng-container> `, host: { '[class.ant-tabs]': `true`, '[class.ant-tabs-no-animation]': `isAnimationDisabled`, '[class.ant-tabs-line]': `nzType === 'line'`, '[class.ant-tabs-card]': `nzType === 'card'`, '[class.ant-tabs-top]': `nzTabPosition === 'top'`, '[class.ant-tabs-bottom]': `nzTabPosition === 'bottom'`, '[class.ant-tabs-left]': `nzTabPosition === 'left'`, '[class.ant-tabs-right]': `nzTabPosition === 'right'`, '[class.ant-tabs-vertical]': `nzTabPosition === 'left' || nzTabPosition === 'right'`, '[class.ant-tabs-large]': `nzSize === 'large'`, '[class.ant-tabs-small]': `nzSize === 'small'` } }] } ]; /** @nocollapse */ NzTabSetComponent.ctorParameters = () => [ { type: NzConfigService }, { type: Renderer2 }, { type: ElementRef }, { type: ChangeDetectorRef }, { type: Router, decorators: [{ type: Optional }] } ]; NzTabSetComponent.propDecorators = { listOfNzTabComponent: [{ type: ContentChildren, args: [NzTabComponent,] }], nzTabsNavComponent: [{ type: ViewChild, args: [NzTabsNavComponent, { static: false },] }], tabContent: [{ type: ViewChild, args: ['tabContent', { static: false },] }], nzTabBarExtraContent: [{ type: Input }], nzShowPagination: [{ type: Input }], nzAnimated: [{ type: Input }], nzHideAll: [{ type: Input }], nzTabPosition: [{ type: Input }], nzSize: [{ type: Input }], nzTabBarGutter: [{ type: Input }], nzTabBarStyle: [{ type: Input }], nzType: [{ type: Input }], nzLinkRouter: [{ type: Input }], nzLinkExact: [{ type: Input }], nzCanDeactivate: [{ type: Input }], nzOnNextClick: [{ type: Output }], nzOnPrevClick: [{ type: Output }], nzSelectChange: [{ type: Output }], nzSelectedIndexChange: [{ type: Output }], nzSelectedIndex: [{ type: Input }] }; __decorate([ WithConfig(NZ_CONFIG_COMPONENT_NAME, true), __metadata("design:type", Boolean) ], NzTabSetComponent.prototype, "nzShowPagination", void 0); __decorate([ WithConfig(NZ_CONFIG_COMPONENT_NAME, true), __metadata("design:type", Object) ], NzTabSetComponent.prototype, "nzAnimated", void 0); __decorate([ WithConfig(NZ_CONFIG_COMPONENT_NAME, 'default'), __metadata("design:type", String) ], NzTabSetComponent.prototype, "nzSize", void 0); __decorate([ WithConfig(NZ_CONFIG_COMPONENT_NAME), __metadata("design:type", Number) ], NzTabSetComponent.prototype, "nzTabBarGutter", void 0); __decorate([ WithConfig(NZ_CONFIG_COMPONENT_NAME, 'line'), __metadata("design:type", String) ], NzTabSetComponent.prototype, "nzType", void 0); __decorate([ InputBoolean(), __metadata("design:type", Object) ], NzTabSetComponent.prototype, "nzLinkRouter", void 0); __decorate([ InputBoolean(), __metadata("design:type", Object) ], NzTabSetComponent.prototype, "nzLinkExact", void 0); if (false) { /** @type {?} */ NzTabSetComponent.ngAcceptInputType_nzLinkRouter; /** @type {?} */ NzTabSetComponent.ngAcceptInputType_nzLinkExact; /** @type {?} */ NzTabSetComponent.ngAcceptInputType_nzSelectedIndex; /** * @type {?} * @private */ NzTabSetComponent.prototype.indexToSelect; /** * @type {?} * @private */ NzTabSetComponent.prototype.el; /** * @type {?} * @private */ NzTabSetComponent.prototype._selectedIndex; /** * Subscription to tabs being added/removed. * @type {?} * @private */ NzTabSetComponent.prototype.tabsSubscription; /** * Subscription to changes in the tab labels. * @type {?} * @private */ NzTabSetComponent.prototype.tabLabelSubscription; /** * @type {?} * @private */ NzTabSetComponent.prototype.destroy$; /** @type {?} */ NzTabSetComponent.prototype.tabPositionMode; /** @type {?} */ NzTabSetComponent.prototype.listOfNzTabComponent; /** @type {?} */ NzTabSetComponent.prototype.nzTabsNavComponent; /** @type {?} */ NzTabSetComponent.prototype.tabContent; /** @type {?} */ NzTabSetComponent.prototype.nzTabBarExtraContent; /** @type {?} */ NzTabSetComponent.prototype.nzShowPagination; /** @type {?} */ NzTabSetComponent.prototype.nzAnimated; /** @type {?} */ NzTabSetComponent.prototype.nzHideAll; /** @type {?} */ NzTabSetComponent.prototype.nzTabPosition; /** @type {?} */ NzTabSetComponent.prototype.nzSize; /** @type {?} */ NzTabSetComponent.prototype.nzTabBarGutter; /** @type {?} */ NzTabSetComponent.prototype.nzTabBarStyle; /** @type {?} */ NzTabSetComponent.prototype.nzType; /** @type {?} */ NzTabSetComponent.prototype.nzLinkRouter; /** @type {?} */ NzTabSetComponent.prototype.nzLinkExact; /** @type {?} */ NzTabSetComponent.prototype.nzCanDeactivate; /** @type {?} */ NzTabSetComponent.prototype.nzOnNextClick; /** @type {?} */ NzTabSetComponent.prototype.nzOnPrevClick; /** @type {?} */ NzTabSetComponent.prototype.nzSelectChange; /** @type {?} */ NzTabSetComponent.prototype.nzSelectedIndexChange; /** @type {?} */ NzTabSetComponent.prototype.nzConfigService; /** * @type {?} * @private */ NzTabSetComponent.prototype.renderer; /** * @type {?} * @private */ NzTabSetComponent.prototype.elementRef; /** * @type {?} * @private */ NzTabSetComponent.prototype.cdr; /** * @type {?} * @private */ NzTabSetComponent.prototype.router; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFic2V0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25nLXpvcnJvLWFudGQvdGFicy8iLCJzb3VyY2VzIjpbInRhYnNldC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7QUFVQSxPQUFPLEVBR0wsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsZUFBZSxFQUNmLFVBQVUsRUFDVixZQUFZLEVBQ1osS0FBSyxFQUdMLFFBQVEsRUFDUixNQUFNLEVBQ04sU0FBUyxFQUNULFNBQVMsRUFFVCxXQUFXLEVBQ1gsU0FBUyxFQUNULGlCQUFpQixFQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBa0MsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RixPQUFPLEVBQUUsZUFBZSxFQUFFLFVBQVUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3hFLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUVuRCxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRXJGLE9BQU8sRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNwRCxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDckUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2pELE9BQU8sRUFBdUIsZ0JBQWdCLEVBQXNFLE1BQU0sZUFBZSxDQUFDO0FBQzFJLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDOztNQUVwRCx3QkFBd0IsR0FBRyxNQUFNO0FBMkV2QyxNQUFNLE9BQU8saUJBQWlCOzs7Ozs7OztJQW9INUIsWUFDUyxlQUFnQyxFQUMvQixRQUFtQixF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QzlCLG1DQUFrQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBBbGliYWJhLmNvbSBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vZ2l0aHViLmNvbS9ORy1aT1JSTy9uZy16b3Jyby1hbnRkL2Jsb2IvbWFzdGVyL0xJQ0VOU0VcbiAqL1xuXG4vKiogZ2V0IHNvbWUgY29kZSBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL21hdGVyaWFsMiAqL1xuXG5pbXBvcnQge1xuICBBZnRlckNvbnRlbnRDaGVja2VkLFxuICBBZnRlckNvbnRlbnRJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgQ29udGVudENoaWxkcmVuLFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE9uRGVzdHJveSxcbiAgT3B0aW9uYWwsXG4gIE91dHB1dCxcbiAgUXVlcnlMaXN0LFxuICBSZW5kZXJlcjIsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFRlbXBsYXRlUmVmLFxuICBWaWV3Q2hpbGQsXG4gIFZpZXdFbmNhcHN1bGF0aW9uXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTmF2aWdhdGlvbkVuZCwgUm91dGVyLCBSb3V0ZXJMaW5rLCBSb3V0ZXJMaW5rV2l0aEhyZWYgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgTnpDb25maWdTZXJ2aWNlLCBXaXRoQ29uZmlnIH0gZnJvbSAnbmctem9ycm8tYW50ZC9jb3JlL2NvbmZpZyc7XG5pbXBvcnQgeyBQUkVGSVggfSBmcm9tICduZy16b3Jyby1hbnRkL2NvcmUvbG9nZ2VyJztcbmltcG9ydCB7IEJvb2xlYW5JbnB1dCwgTnVtYmVySW5wdXQsIE56U2l6ZUxEU1R5cGUgfSBmcm9tICduZy16b3Jyby1hbnRkL2NvcmUvdHlwZXMnO1xuaW1wb3J0IHsgSW5wdXRCb29sZWFuLCB0b051bWJlciwgd3JhcEludG9PYnNlcnZhYmxlIH0gZnJvbSAnbmctem9ycm8tYW50ZC9jb3JlL3V0aWwnO1xuXG5pbXBvcnQgeyBtZXJnZSwgU3ViamVjdCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBmaWx0ZXIsIGZpcnN0LCBzdGFydFdpdGgsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IE56VGFiQ29tcG9uZW50IH0gZnJvbSAnLi90YWIuY29tcG9uZW50JztcbmltcG9ydCB7IE56QW5pbWF0ZWRJbnRlcmZhY2UsIE56VGFiQ2hhbmdlRXZlbnQsIE56VGFiUG9zaXRpb24sIE56VGFiUG9zaXRpb25Nb2RlLCBOelRhYnNDYW5EZWFjdGl2YXRlRm4sIE56VGFiVHlwZSB9IGZyb20gJy4vdGFibGUudHlwZXMnO1xuaW1wb3J0IHsgTnpUYWJzTmF2Q29tcG9uZW50IH0gZnJvbSAnLi90YWJzLW5hdi5jb21wb25lbnQnO1xuXG5jb25zdCBOWl9DT05GSUdfQ09NUE9ORU5UX05BTUUgPSAndGFicyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ256LXRhYnNldCcsXG4gIGV4cG9ydEFzOiAnbnpUYWJzZXQnLFxuICBwcmVzZXJ2ZVdoaXRlc3BhY2VzOiBmYWxzZSxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHRlbXBsYXRlOiBgXG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImxpc3RPZk56VGFiQ29tcG9uZW50XCI+XG4gICAgICA8bnotdGFicy1uYXZcbiAgICAgICAgcm9sZT1cInRhYmxpc3RcIlxuICAgICAgICB0YWJpbmRleD1cIjBcIlxuICAgICAgICBbbnpTaXplXT1cIm56U2l6ZVwiXG4gICAgICAgIFtuelRhYlBvc2l0aW9uXT1cIm56VGFiUG9zaXRpb25cIlxuICAgICAgICBbbnpUeXBlXT1cIm56VHlwZVwiXG4gICAgICAgIFtuelNob3dQYWdpbmF0aW9uXT1cIm56U2hvd1BhZ2luYXRpb25cIlxuICAgICAgICBbbnpQb3NpdGlvbk1vZGVdPVwidGFiUG9zaXRpb25Nb2RlXCJcbiAgICAgICAgW256QW5pbWF0ZWRdPVwiaW5rQmFyQW5pbWF0ZWRcIlxuICAgICAgICBbbmdTdHlsZV09XCJuelRhYkJhclN0eWxlXCJcbiAgICAgICAgW256SGlkZUJhcl09XCJuekhpZGVBbGxcIlxuICAgICAgICBbbnpUYWJCYXJFeHRyYUNvbnRlbnRdPVwibnpUYWJCYXJFeHRyYUNvbnRlbnRcIlxuICAgICAgICBbc2VsZWN0ZWRJbmRleF09XCJuelNlbGVjdGVkSW5kZXhcIlxuICAgICAgICAobnpPbk5leHRDbGljayk9XCJuek9uTmV4dENsaWNrLmVtaXQoKVwiXG4gICAgICAgIChuek9uUHJldkNsaWNrKT1cIm56T25QcmV2Q2xpY2suZW1pdCgpXCJcbiAgICAgID5cbiAgICAgICAgPGRpdlxuICAgICAgICAgIG56LXRhYi1sYWJlbFxuICAgICAgICAgIHJvbGU9XCJ0YWJcIlxuICAgICAgICAgIFtzdHlsZS5tYXJnaW4tcmlnaHQucHhdPVwibnpUYWJCYXJHdXR0ZXJcIlxuICAgICAgICAgIFtjbGFzcy5hbnQtdGFicy10YWItYWN0aXZlXT1cIm56U2VsZWN0ZWRJbmRleCA9PSBpICYmICFuekhpZGVBbGxcIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCJ0YWIubnpEaXNhYmxlZFwiXG4gICAgICAgICAgKGNsaWNrKT1cImNsaWNrTGFiZWwoaSwgdGFiLm56RGlzYWJsZWQpXCJcbiAgICAgICAgICAqbmdGb3I9XCJsZXQgdGFiIG9mIGxpc3RPZk56VGFiQ29tcG9uZW50OyBsZXQgaSA9IGluZGV4XCJcbiAgICAgICAgPlxuICAgICAgICAgIDxuZy1jb250YWluZXIgKm56U3RyaW5nVGVtcGxhdGVPdXRsZXQ9XCJ0YWIubnpUaXRsZSB8fCB0YWIudGl0bGVcIj57eyB0YWIubnpUaXRsZSB9fTwvbmctY29udGFpbmVyPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvbnotdGFicy1uYXY+XG4gICAgICA8ZGl2XG4gICAgICAgICN0YWJDb250ZW50XG4gICAgICAgIGNsYXNzPVwiYW50LXRhYnMtY29udGVudFwiXG4gICAgICAgIFtjbGFzcy5hbnQtdGFicy10b3AtY29udGVudF09XCJuelRhYlBvc2l0aW9uID09PSAndG9wJ1wiXG4gICAgICAgIFtjbGFzcy5hbnQtdGFicy1ib3R0b20tY29udGVudF09XCJuelRhYlBvc2l0aW9uID09PSAnYm90dG9tJ1wiXG4gICAgICAgIFtjbGFzcy5hbnQtdGFicy1sZWZ0LWNvbnRlbnRdPVwibnpUYWJQb3NpdGlvbiA9PT0gJ2xlZnQnXCJcbiAgICAgICAgW2NsYXNzLmFudC10YWJzLXJpZ2h0LWNvbnRlbnRdPVwibnpUYWJQb3NpdGlvbiA9PT0gJ3JpZ2h0J1wiXG4gICAgICAgIFtjbGFzcy5hbnQtdGFicy1jb250ZW50LWFuaW1hdGVkXT1cInRhYlBhbmVBbmltYXRlZFwiXG4gICAgICAgIFtjbGFzcy5hbnQtdGFicy1jYXJkLWNvbnRlbnRdPVwibnpUeXBlID09PSAnY2FyZCdcIlxuICAgICAgICBbY2xhc3MuYW50LXRhYnMtY29udGVudC1uby1hbmltYXRlZF09XCIhdGFiUGFuZUFuaW1hdGVkXCJcbiAgICAgICAgW3N0eWxlLm1hcmdpbi1sZWZ0LiVdPVwidGFiUG9zaXRpb25Nb2RlID09PSAnaG9yaXpvbnRhbCcgJiYgdGFiUGFuZUFuaW1hdGVkICYmIC0obnpTZWxlY3RlZEluZGV4IHx8IDApICogMTAwXCJcbiAgICAgID5cbiAgICAgICAgPGRpdlxuICAgICAgICAgIG56LXRhYi1ib2R5XG4gICAgICAgICAgY2xhc3M9XCJhbnQtdGFicy10YWJwYW5lXCJcbiAgICAgICAgICAqbmdGb3I9XCJsZXQgdGFiIG9mIGxpc3RPZk56VGFiQ29tcG9uZW50OyBsZXQgaSA9IGluZGV4XCJcbiAgICAgICAgICBbYWN0aXZlXT1cIm56U2VsZWN0ZWRJbmRleCA9PSBpICYmICFuekhpZGVBbGxcIlxuICAgICAgICAgIFtmb3JjZVJlbmRlcl09XCJ0YWIubnpGb3JjZVJlbmRlclwiXG4gICAgICAgICAgW2NvbnRlbnRdPVwidGFiLnRlbXBsYXRlIHx8IHRhYi5jb250ZW50XCJcbiAgICAgICAgPjwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9uZy1jb250YWluZXI+XG4gIGAsXG4gIGhvc3Q6IHtcbiAgICAnW2NsYXNzLmFudC10YWJzXSc6IGB0cnVlYCxcbiAgICAnW2NsYXNzLmFudC10YWJzLW5vLWFuaW1hdGlvbl0nOiBgaXNBbmltYXRpb25EaXNhYmxlZGAsXG4gICAgJ1tjbGFzcy5hbnQtdGFicy1saW5lXSc6IGBuelR5cGUgPT09ICdsaW5lJ2AsXG4gICAgJ1tjbGFzcy5hbnQtdGFicy1jYXJkXSc6IGBuelR5cGUgPT09ICdjYXJkJ2AsXG4gICAgJ1tjbGFzcy5hbnQtdGFicy10b3BdJzogYG56VGFiUG9zaXRpb24gPT09ICd0b3AnYCxcbiAgICAnW2NsYXNzLmFudC10YWJzLWJvdHRvbV0nOiBgbnpUYWJQb3NpdGlvbiA9PT0gJ2JvdHRvbSdgLFxuICAgICdbY2xhc3MuYW50LXRhYnMtbGVmdF0nOiBgbnpUYWJQb3NpdGlvbiA9PT0gJ2xlZnQnYCxcbiAgICAnW2NsYXNzLmFudC10YWJzLXJpZ2h0XSc6IGBuelRhYlBvc2l0aW9uID09PSAncmlnaHQnYCxcbiAgICAnW2NsYXNzLmFudC10YWJzLXZlcnRpY2FsXSc6IGBuelRhYlBvc2l0aW9uID09PSAnbGVmdCcgfHwgbnpUYWJQb3NpdGlvbiA9PT0gJ3JpZ2h0J2AsXG4gICAgJ1tjbGFzcy5hbnQtdGFicy1sYXJnZV0nOiBgbnpTaXplID09PSAnbGFyZ2UnYCxcbiAgICAnW2NsYXNzLmFudC10YWJzLXNtYWxsXSc6IGBuelNpemUgPT09ICdzbWFsbCdgXG4gIH1cbn0pXG5leHBvcnQgY2xhc3MgTnpUYWJTZXRDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlckNvbnRlbnRDaGVja2VkLCBPbkNoYW5nZXMsIEFmdGVyQ29udGVudEluaXQsIE9uRGVzdHJveSB7XG4gIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9uekxpbmtSb3V0ZXI6IEJvb2xlYW5JbnB1dDtcbiAgc3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX256TGlua0V4YWN0OiBCb29sZWFuSW5wdXQ7XG4gIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9uelNlbGVjdGVkSW5kZXg6IE51bWJlcklucHV0O1xuXG4gIHByaXZhdGUgaW5kZXhUb1NlbGVjdDogbnVtYmVyIHwgbnVsbCA9IDA7XG4gIHByaXZhdGUgZWw6IEhUTUxFbGVtZW50ID0gdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gIHByaXZhdGUgX3NlbGVjdGVkSW5kZXg6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICAvKiogU3Vic2NyaXB0aW9uIHRvIHRhYnMgYmVpbmcgYWRkZWQvcmVtb3ZlZC4gKi9cbiAgcHJpdmF0ZSB0YWJzU3Vic2NyaXB0aW9uID0gU3Vic2NyaXB0aW9uLkVNUFRZO1xuICAvKiogU3Vic2NyaXB0aW9uIHRvIGNoYW5nZXMgaW4gdGhlIHRhYiBsYWJlbHMuICovXG4gIHByaXZhdGUgdGFiTGFiZWxTdWJzY3JpcHRpb24gPSBTdWJzY3JpcHRpb24uRU1QVFk7XG4gIHByaXZhdGUgZGVzdHJveSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICB0YWJQb3NpdGlvbk1vZGU6IE56VGFiUG9zaXRpb25Nb2RlID0gJ2hvcml6b250YWwnO1xuICBAQ29udGVudENoaWxkcmVuKE56VGFiQ29tcG9uZW50KSBsaXN0T2ZOelRhYkNvbXBvbmVudDogUXVlcnlMaXN0PE56VGFiQ29tcG9uZW50PjtcbiAgQFZpZXdDaGlsZChOelRhYnNOYXZDb21wb25lbnQsIHsgc3RhdGljOiBmYWxzZSB9KSBuelRhYnNOYXZDb21wb25lbnQ6IE56VGFic05hdkNvbXBvbmVudDtcbiAgQFZpZXdDaGlsZCgndGFiQ29udGVudCcsIHsgc3RhdGljOiBmYWxzZSB9KSB0YWJDb250ZW50OiBFbGVtZW50UmVmO1xuXG4gIEBJbnB1dCgpIG56VGFiQmFyRXh0cmFDb250ZW50OiBUZW1wbGF0ZVJlZjx2b2lkPjtcbiAgQElucHV0KCkgQFdpdGhDb25maWcoTlpfQ09ORklHX0NPTVBPTkVOVF9OQU1FLCB0cnVlKSBuelNob3dQYWdpbmF0aW9uOiBib29sZWFuO1xuICBASW5wdXQoKSBAV2l0aENvbmZpZyhOWl9DT05GSUdfQ09NUE9ORU5UX05BTUUsIHRydWUpIG56QW5pbWF0ZWQ6IE56QW5pbWF0ZWRJbnRlcmZhY2UgfCBib29sZWFuO1xuICBASW5wdXQoKSBuekhpZGVBbGwgPSBmYWxzZTtcbiAgQElucHV0KCkgbnpUYWJQb3NpdGlvbjogTnpUYWJQb3NpdGlvbiA9ICd0b3AnO1xuICBASW5wdXQoKSBAV2l0aENvbmZpZyhOWl9DT05GSUdfQ09NUE9ORU5UX05BTUUsICdkZWZhdWx0JykgbnpTaXplOiBOelNpemVMRFNUeXBlO1xuICBASW5wdXQoKSBAV2l0aENvbmZpZyhOWl9DT05GSUdfQ09NUE9ORU5UX05BTUUpIG56VGFiQmFyR3V0dGVyOiBudW1iZXI7XG4gIEBJbnB1dCgpIG56VGFiQmFyU3R5bGU6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XG4gIEBJbnB1dCgpIEBXaXRoQ29uZmlnKE5aX0NPTkZJR19DT01QT05FTlRfTkFNRSwgJ2xpbmUnKSBuelR5cGU6IE56VGFiVHlwZTtcblxuICBASW5wdXQoKSBASW5wdXRCb29sZWFuKCkgbnpMaW5rUm91dGVyID0gZmFsc2U7XG4gIEBJbnB1dCgpIEBJbnB1dEJvb2xlYW4oKSBuekxpbmtFeGFjdCA9IHRydWU7XG4gIEBJbnB1dCgpIG56Q2FuRGVhY3RpdmF0ZTogTnpUYWJzQ2FuRGVhY3RpdmF0ZUZuIHwgbnVsbCA9IG51bGw7XG5cbiAgQE91dHB1dCgpIHJlYWRvbmx5IG56T25OZXh0Q2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG4gIEBPdXRwdXQoKSByZWFkb25seSBuek9uUHJldkNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuICBAT3V0cHV0KCkgcmVhZG9ubHkgbnpTZWxlY3RDaGFuZ2U6IEV2ZW50RW1pdHRlcjxOelRhYkNoYW5nZUV2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXI8TnpUYWJDaGFuZ2VFdmVudD4odHJ1ZSk7XG4gIEBPdXRwdXQoKSByZWFkb25seSBuelNlbGVjdGVkSW5kZXhDaGFuZ2U6IEV2ZW50RW1pdHRlcjxudW1iZXI+ID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXI+KCk7XG5cbiAgQElucHV0KClcbiAgc2V0IG56U2VsZWN0ZWRJbmRleCh2YWx1ZTogbnVtYmVyIHwgbnVsbCkge1xuICAgIHRoaXMuaW5kZXhUb1NlbGVjdCA9IHZhbHVlID8gdG9OdW1iZXIodmFsdWUsIG51bGwpIDogbnVsbDtcbiAgfVxuXG4gIGdldCBuelNlbGVjdGVkSW5kZXgoKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuX3NlbGVjdGVkSW5kZXg7XG4gIH1cblxuICBnZXQgaW5rQmFyQW5pbWF0ZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubnpBbmltYXRlZCA9PT0gdHJ1ZSB8fCAodGhpcy5uekFuaW1hdGVkIGFzIE56QW5pbWF0ZWRJbnRlcmZhY2UpLmlua0JhciA9PT0gdHJ1ZTtcbiAgfVxuXG4gIGdldCB0YWJQYW5lQW5pbWF0ZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubnpBbmltYXRlZCA9PT0gdHJ1ZSB8fCAodGhpcy5uekFuaW1hdGVkIGFzIE56QW5pbWF0ZWRJbnRlcmZhY2UpLnRhYlBhbmUgPT09IHRydWU7XG4gIH1cblxuICBnZXQgaXNBbmltYXRpb25EaXNhYmxlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5uekFuaW1hdGVkID09PSBmYWxzZSB8fCAodGhpcy5uekFuaW1hdGVkIGFzIE56QW5pbWF0ZWRJbnRlcmZhY2UpLnRhYlBhbmUgPT09IGZhbHNlO1xuICB9XG5cbiAgc2V0UG9zaXRpb24odmFsdWU6IE56VGFiUG9zaXRpb24pOiB2b2lkIHtcbiAgICBpZiAodGhpcy50YWJDb250ZW50KSB7XG4gICAgICBpZiAodmFsdWUgPT09ICdib3R0b20nKSB7XG4gICAgICAgIHRoaXMucmVuZGVyZXIuaW5zZXJ0QmVmb3JlKHRoaXMuZWwsIHRoaXMudGFiQ29udGVudC5uYXRpdmVFbGVtZW50LCB0aGlzLm56VGFic05hdkNvbXBvbmVudC5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5yZW5kZXJlci5pbnNlcnRCZWZvcmUodGhpcy5lbCwgdGhpcy5uelRhYnNOYXZDb21wb25lbnQuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCB0aGlzLnRhYkNvbnRlbnQubmF0aXZlRWxlbWVudCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY2xpY2tMYWJlbChpbmRleDogbnVtYmVyLCBkaXNhYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmICghZGlzYWJsZWQpIHtcbiAgICAgIGlmICh0aGlzLm56U2VsZWN0ZWRJbmRleCAhPT0gbnVsbCAmJiB0aGlzLm56U2VsZWN0ZWRJbmRleCAhPT0gaW5kZXggJiYgdHlwZW9mIHRoaXMubnpDYW5EZWFjdGl2YXRlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGNvbnN0IG9ic2VydmFibGUgPSB3cmFwSW50b09ic2VydmFibGUodGhpcy5uekNhbkRlYWN0aXZhdGUodGhpcy5uelNlbGVjdGVkSW5kZXgsIGluZGV4KSk7XG4gICAgICAgIG9ic2VydmFibGUucGlwZShmaXJzdCgpLCB0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpLnN1YnNjcmliZShjYW5DaGFuZ2UgPT4gY2FuQ2hhbmdlICYmIHRoaXMuZW1pdENsaWNrRXZlbnQoaW5kZXgpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuZW1pdENsaWNrRXZlbnQoaW5kZXgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZW1pdENsaWNrRXZlbnQoaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHRhYnMgPSB0aGlzLmxpc3RPZk56VGFiQ29tcG9uZW50LnRvQXJyYXkoKTtcbiAgICB0aGlzLm56U2VsZWN0ZWRJbmRleCA9IGluZGV4O1xuICAgIHRhYnNbaW5kZXhdLm56Q2xpY2suZW1pdCgpO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgY3JlYXRlQ2hhbmdlRXZlbnQoaW5kZXg6IG51bWJlcik6IE56VGFiQ2hhbmdlRXZlbnQge1xuICAgIGNvbnN0IGV2ZW50ID0gbmV3IE56VGFiQ2hhbmdlRXZlbnQoKTtcbiAgICBldmVudC5pbmRleCA9IGluZGV4O1xuICAgIGlmICh0aGlzLmxpc3RPZk56VGFiQ29tcG9uZW50ICYmIHRoaXMubGlzdE9mTnpUYWJDb21wb25lbnQubGVuZ3RoKSB7XG4gICAgICBldmVudC50YWIgPSB0aGlzLmxpc3RPZk56VGFiQ29tcG9uZW50LnRvQXJyYXkoKVtpbmRleF07XG4gICAgICB0aGlzLmxpc3RPZk56VGFiQ29tcG9uZW50LmZvckVhY2goKGl0ZW0sIGkpID0+IHtcbiAgICAgICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICAgICAgaXRlbS5uekRlc2VsZWN0LmVtaXQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBldmVudC50YWIubnpTZWxlY3QuZW1pdCgpO1xuICAgIH1cbiAgICByZXR1cm4gZXZlbnQ7XG4gIH1cblxuICAvKiogQ2xhbXBzIHRoZSBnaXZlbiBpbmRleCB0byB0aGUgYm91bmRzIG9mIDAgYW5kIHRoZSB0YWJzIGxlbmd0aC4gKi9cbiAgcHJpdmF0ZSBjbGFtcFRhYkluZGV4KGluZGV4OiBudW1iZXIgfCBudWxsKTogbnVtYmVyIHtcbiAgICAvLyBOb3RlIHRoZSBgfHwgMGAsIHdoaWNoIGVuc3VyZXMgdGhhdCB2YWx1ZXMgbGlrZSBOYU4gY2FuJ3QgZ2V0IHRocm91Z2hcbiAgICAvLyBhbmQgd2hpY2ggd291bGQgb3RoZXJ3aXNlIHRocm93IHRoZSBjb21wb25lbnQgaW50byBhbiBpbmZpbml0ZSBsb29wXG4gICAgLy8gKHNpbmNlIE1hdGgubWF4KE5hTiwgMCkgPT09IE5hTikuXG4gICAgcmV0dXJuIE1hdGgubWluKHRoaXMubGlzdE9mTnpUYWJDb21wb25lbnQubGVuZ3RoIC0gMSwgTWF0aC5tYXgoaW5kZXggfHwgMCwgMCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBzdWJzY3JpYmVUb1RhYkxhYmVscygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy50YWJMYWJlbFN1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy50YWJMYWJlbFN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgIH1cbiAgICB0aGlzLnRhYkxhYmVsU3Vic2NyaXB0aW9uID0gbWVyZ2UoLi4udGhpcy5saXN0T2ZOelRhYkNvbXBvbmVudC5tYXAodGFiID0+IHRhYi5zdGF0ZUNoYW5nZXMpKS5zdWJzY3JpYmUoKCkgPT4gdGhpcy5jZHIubWFya0ZvckNoZWNrKCkpO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIG56Q29uZmlnU2VydmljZTogTnpDb25maWdTZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVuZGVyZXI6IFJlbmRlcmVyMixcbiAgICBwcml2YXRlIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsXG4gICAgcHJpdmF0ZSBjZHI6IENoYW5nZURldGVjdG9yUmVmLFxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgcm91dGVyOiBSb3V0ZXJcbiAgKSB7fVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICBjb25zdCB7IG56VGFiUG9zaXRpb24sIG56VHlwZSB9ID0gY2hhbmdlcztcbiAgICBpZiAobnpUYWJQb3NpdGlvbikge1xuICAgICAgaWYgKHRoaXMubnpUYWJQb3NpdGlvbiA9PT0gJ3RvcCcgfHwgdGhpcy5uelRhYlBvc2l0aW9uID09PSAnYm90dG9tJykge1xuICAgICAgICB0aGlzLnRhYlBvc2l0aW9uTW9kZSA9ICdob3Jpem9udGFsJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMudGFiUG9zaXRpb25Nb2RlID0gJ3ZlcnRpY2FsJztcbiAgICAgIH1cbiAgICAgIHRoaXMuc2V0UG9zaXRpb24odGhpcy5uelRhYlBvc2l0aW9uKTtcbiAgICB9XG4gICAgaWYgKG56VHlwZSkge1xuICAgICAgaWYgKHRoaXMubnpUeXBlID09PSAnY2FyZCcpIHtcbiAgICAgICAgdGhpcy5uekFuaW1hdGVkID0gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgbmdBZnRlckNvbnRlbnRDaGVja2VkKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmxpc3RPZk56VGFiQ29tcG9uZW50ICYmIHRoaXMubGlzdE9mTnpUYWJDb21wb25lbnQubGVuZ3RoKSB7XG4gICAgICAvLyBEb24ndCBjbGFtcCB0aGUgYGluZGV4VG9TZWxlY3RgIGltbWVkaWF0ZWx5IGluIHRoZSBzZXR0ZXIgYmVjYXVzZSBpdCBjYW4gaGFwcGVuIHRoYXRcbiAgICAgIC8vIHRoZSBhbW91bnQgb2YgdGFicyBjaGFuZ2VzIGJlZm9yZSB0aGUgYWN0dWFsIGNoYW5nZSBkZXRlY3Rpb24gcnVucy5cbiAgICAgIGNvbnN0IGluZGV4VG9TZWxlY3QgPSAodGhpcy5pbmRleFRvU2VsZWN0ID0gdGhpcy5jbGFtcFRhYkluZGV4KHRoaXMuaW5kZXhUb1NlbGVjdCkpO1xuICAgICAgLy8gSWYgdGhlcmUgaXMgYSBjaGFuZ2UgaW4gc2VsZWN0ZWQgaW5kZXgsIGVtaXQgYSBjaGFuZ2UgZXZlbnQuIFNob3VsZCBub3QgdHJpZ2dlciBpZlxuICAgICAgLy8gdGhlIHNlbGVjdGVkIGluZGV4IGhhcyBub3QgeWV0IGJlZW4gaW5pdGlhbGl6ZWQuXG4gICAgICBpZiAodGhpcy5fc2VsZWN0ZWRJbmRleCAhPT0gaW5kZXhUb1NlbGVjdCkge1xuICAgICAgICBjb25zdCBpc0ZpcnN0UnVuID0gdGhpcy5fc2VsZWN0ZWRJbmRleCA9PSBudWxsO1xuICAgICAgICBpZiAoIWlzRmlyc3RSdW4pIHtcbiAgICAgICAgICB0aGlzLm56U2VsZWN0Q2hhbmdlLmVtaXQodGhpcy5jcmVhdGVDaGFuZ2VFdmVudChpbmRleFRvU2VsZWN0KSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGFuZ2luZyB0aGVzZSB2YWx1ZXMgYWZ0ZXIgY2hhbmdlIGRldGVjdGlvbiBoYXMgcnVuXG4gICAgICAgIC8vIHNpbmNlIHRoZSBjaGVja2VkIGNvbnRlbnQgbWF5IGNvbnRhaW4gcmVmZXJlbmNlcyB0byB0aGVtLlxuICAgICAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcbiAgICAgICAgICB0aGlzLmxpc3RPZk56VGFiQ29tcG9uZW50LmZvckVhY2goKHRhYiwgaW5kZXgpID0+ICh0YWIuaXNBY3RpdmUgPSBpbmRleCA9PT0gaW5kZXhUb1NlbGVjdCkpO1xuXG4gICAgICAgICAgaWYgKCFpc0ZpcnN0UnVuKSB7XG4gICAgICAgICAgICB0aGlzLm56U2VsZWN0ZWRJbmRleENoYW5nZS5lbWl0KGluZGV4VG9TZWxlY3QpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIFNldHVwIHRoZSBwb3N