ng-zorro-antd
Version:
An enterprise-class UI components based on Ant Design and Angular
635 lines • 53 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import * as tslib_1 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 { merge, Subject, Subscription } from 'rxjs';
import { toNumber, InputBoolean, NzConfigService, NzUpdateHostClassService, PREFIX, WithConfig } from 'ng-zorro-antd/core';
import { filter, startWith, takeUntil } from 'rxjs/operators';
import { NzTabComponent } from './nz-tab.component';
import { NzTabsNavComponent } from './nz-tabs-nav.component';
/**
* @record
*/
export function NzAnimatedInterface() { }
if (false) {
/** @type {?} */
NzAnimatedInterface.prototype.inkBar;
/** @type {?} */
NzAnimatedInterface.prototype.tabPane;
}
var NzTabChangeEvent = /** @class */ (function () {
function NzTabChangeEvent() {
}
return NzTabChangeEvent;
}());
export { NzTabChangeEvent };
if (false) {
/** @type {?} */
NzTabChangeEvent.prototype.index;
/** @type {?} */
NzTabChangeEvent.prototype.tab;
}
var NzTabSetComponent = /** @class */ (function () {
function NzTabSetComponent(nzConfigService, renderer, nzUpdateHostClassService, elementRef, cdr, router) {
this.nzConfigService = nzConfigService;
this.renderer = renderer;
this.nzUpdateHostClassService = nzUpdateHostClassService;
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.nzOnNextClick = new EventEmitter();
this.nzOnPrevClick = new EventEmitter();
this.nzSelectChange = new EventEmitter(true);
this.nzSelectedIndexChange = new EventEmitter();
}
Object.defineProperty(NzTabSetComponent.prototype, "nzSelectedIndex", {
get: /**
* @return {?}
*/
function () {
return this._selectedIndex;
},
set: /**
* @param {?} value
* @return {?}
*/
function (value) {
this.indexToSelect = value ? toNumber(value, null) : null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(NzTabSetComponent.prototype, "inkBarAnimated", {
get: /**
* @return {?}
*/
function () {
return this.nzAnimated === true || ((/** @type {?} */ (this.nzAnimated))).inkBar === true;
},
enumerable: true,
configurable: true
});
Object.defineProperty(NzTabSetComponent.prototype, "tabPaneAnimated", {
get: /**
* @return {?}
*/
function () {
return this.nzAnimated === true || ((/** @type {?} */ (this.nzAnimated))).tabPane === true;
},
enumerable: true,
configurable: true
});
/**
* @param {?} value
* @return {?}
*/
NzTabSetComponent.prototype.setPosition = /**
* @param {?} value
* @return {?}
*/
function (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);
}
}
};
/**
* @return {?}
*/
NzTabSetComponent.prototype.setClassMap = /**
* @return {?}
*/
function () {
var _a;
this.nzUpdateHostClassService.updateHostClass(this.el, (_a = {},
_a["ant-tabs"] = true,
_a["ant-tabs-vertical"] = this.nzTabPosition === 'left' || this.nzTabPosition === 'right',
_a["ant-tabs-" + this.nzTabPosition] = this.nzTabPosition,
_a["ant-tabs-no-animation"] = this.nzAnimated === false || ((/** @type {?} */ (this.nzAnimated))).tabPane === false,
_a["ant-tabs-" + this.nzType] = this.nzType,
_a["ant-tabs-large"] = this.nzSize === 'large',
_a["ant-tabs-small"] = this.nzSize === 'small',
_a));
};
/**
* @param {?} index
* @param {?} disabled
* @return {?}
*/
NzTabSetComponent.prototype.clickLabel = /**
* @param {?} index
* @param {?} disabled
* @return {?}
*/
function (index, disabled) {
if (!disabled) {
/** @type {?} */
var tabs = this.listOfNzTabComponent.toArray();
this.nzSelectedIndex = index;
tabs[index].nzClick.emit();
}
};
/**
* @param {?} index
* @return {?}
*/
NzTabSetComponent.prototype.createChangeEvent = /**
* @param {?} index
* @return {?}
*/
function (index) {
/** @type {?} */
var 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 {?}
*/
function (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. */
/**
* Clamps the given index to the bounds of 0 and the tabs length.
* @private
* @param {?} index
* @return {?}
*/
NzTabSetComponent.prototype.clampTabIndex = /**
* Clamps the given index to the bounds of 0 and the tabs length.
* @private
* @param {?} index
* @return {?}
*/
function (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 {?}
*/
NzTabSetComponent.prototype.subscribeToTabLabels = /**
* @private
* @return {?}
*/
function () {
var _this = this;
if (this.tabLabelSubscription) {
this.tabLabelSubscription.unsubscribe();
}
this.tabLabelSubscription = merge.apply(void 0, tslib_1.__spread(this.listOfNzTabComponent.map((/**
* @param {?} tab
* @return {?}
*/
function (tab) { return tab.stateChanges; })))).subscribe((/**
* @return {?}
*/
function () {
return _this.cdr.markForCheck();
}));
};
/**
* @param {?} changes
* @return {?}
*/
NzTabSetComponent.prototype.ngOnChanges = /**
* @param {?} changes
* @return {?}
*/
function (changes) {
if (changes.nzTabPosition) {
if (this.nzTabPosition === 'top' || this.nzTabPosition === 'bottom') {
this.tabPositionMode = 'horizontal';
}
else {
this.tabPositionMode = 'vertical';
}
this.setPosition(this.nzTabPosition);
}
if (changes.nzType) {
if (this.nzType === 'card') {
this.nzAnimated = false;
}
}
if (changes.nzSize || changes.nzAnimated || changes.nzTabPosition || changes.nzType) {
this.setClassMap();
}
};
/**
* @return {?}
*/
NzTabSetComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
this.setClassMap();
};
/**
* @return {?}
*/
NzTabSetComponent.prototype.ngAfterContentChecked = /**
* @return {?}
*/
function () {
var _this = this;
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 {?} */
var indexToSelect_1 = (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_1) {
/** @type {?} */
var isFirstRun_1 = this._selectedIndex == null;
if (!isFirstRun_1) {
this.nzSelectChange.emit(this.createChangeEvent(indexToSelect_1));
}
// Changing these values after change detection has run
// since the checked content may contain references to them.
Promise.resolve().then((/**
* @return {?}
*/
function () {
_this.listOfNzTabComponent.forEach((/**
* @param {?} tab
* @param {?} index
* @return {?}
*/
function (tab, index) { return (tab.isActive = index === indexToSelect_1); }));
if (!isFirstRun_1) {
_this.nzSelectedIndexChange.emit(indexToSelect_1);
}
}));
}
// Setup the position for each tab and optionally setup an origin on the next selected tab.
this.listOfNzTabComponent.forEach((/**
* @param {?} tab
* @param {?} index
* @return {?}
*/
function (tab, index) {
tab.position = index - indexToSelect_1;
// 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_1 - _this._selectedIndex;
}
}));
if (this._selectedIndex !== indexToSelect_1) {
this._selectedIndex = indexToSelect_1;
this.cdr.markForCheck();
}
}
};
/**
* @return {?}
*/
NzTabSetComponent.prototype.ngAfterContentInit = /**
* @return {?}
*/
function () {
var _this = this;
this.subscribeToTabLabels();
// 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 {?}
*/
function () {
/** @type {?} */
var 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 {?} */
var tabs = _this.listOfNzTabComponent.toArray();
for (var 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 {?}
*/
NzTabSetComponent.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this.tabsSubscription.unsubscribe();
this.tabLabelSubscription.unsubscribe();
};
/**
* @return {?}
*/
NzTabSetComponent.prototype.ngAfterViewInit = /**
* @return {?}
*/
function () {
var _this = this;
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 {?}
*/
function (e) { return e instanceof NavigationEnd; })), startWith(true))
.subscribe((/**
* @return {?}
*/
function () {
_this.updateRouterActive();
_this.cdr.markForCheck();
}));
}
};
/**
* @private
* @return {?}
*/
NzTabSetComponent.prototype.updateRouterActive = /**
* @private
* @return {?}
*/
function () {
if (this.router.navigated) {
/** @type {?} */
var index = this.findShouldActiveTabIndex();
if (index !== this._selectedIndex) {
this.nzSelectedIndex = index;
this.nzSelectedIndexChange.emit(index);
}
this.nzHideAll = index === -1;
}
};
/**
* @private
* @return {?}
*/
NzTabSetComponent.prototype.findShouldActiveTabIndex = /**
* @private
* @return {?}
*/
function () {
/** @type {?} */
var tabs = this.listOfNzTabComponent.toArray();
/** @type {?} */
var isActive = this.isLinkActive(this.router);
return tabs.findIndex((/**
* @param {?} tab
* @return {?}
*/
function (tab) {
/** @type {?} */
var c = tab.linkDirective;
return c ? isActive(c.routerLink) || isActive(c.routerLinkWithHref) : false;
}));
};
/**
* @private
* @param {?} router
* @return {?}
*/
NzTabSetComponent.prototype.isLinkActive = /**
* @private
* @param {?} router
* @return {?}
*/
function (router) {
var _this = this;
return (/**
* @param {?=} link
* @return {?}
*/
function (link) { return (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,
providers: [NzUpdateHostClassService],
template: "<ng-container *ngIf=\"listOfNzTabComponent\">\n <div nz-tabs-nav\n role=\"tablist\"\n tabindex=\"0\"\n class=\"ant-tabs-bar\"\n [class.ant-tabs-card-bar]=\"nzType === 'card'\"\n [class.ant-tabs-top-bar]=\"nzTabPosition === 'top'\"\n [class.ant-tabs-bottom-bar]=\"nzTabPosition === 'bottom'\"\n [class.ant-tabs-left-bar]=\"nzTabPosition === 'left'\"\n [class.ant-tabs-right-bar]=\"nzTabPosition === 'right'\"\n [class.ant-tabs-small-bar]=\"nzSize === 'small'\"\n [class.ant-tabs-default-bar]=\"nzSize === 'default'\"\n [class.ant-tabs-large-bar]=\"nzSize === 'large'\"\n [nzType]=\"nzType\"\n [nzShowPagination]=\"nzShowPagination\"\n [nzPositionMode]=\"tabPositionMode\"\n [nzAnimated]=\"inkBarAnimated\"\n [ngStyle]=\"nzTabBarStyle\"\n [nzHideBar]=\"nzHideAll\"\n [nzTabBarExtraContent]=\"nzTabBarExtraContent\"\n [selectedIndex]=\"nzSelectedIndex\"\n (nzOnNextClick)=\"nzOnNextClick.emit()\"\n (nzOnPrevClick)=\"nzOnPrevClick.emit()\">\n <div nz-tab-label\n role=\"tab\"\n [style.margin-right.px]=\"nzTabBarGutter\"\n [class.ant-tabs-tab-active]=\"(nzSelectedIndex == i) && !nzHideAll\"\n [disabled]=\"tab.nzDisabled\"\n (click)=\"clickLabel(i,tab.nzDisabled)\"\n *ngFor=\"let tab of listOfNzTabComponent; let i = index\">\n <ng-container *nzStringTemplateOutlet=\"tab.nzTitle || tab.title\">{{ tab.nzTitle }}</ng-container>\n </div>\n </div>\n <div #tabContent\n class=\"ant-tabs-content\"\n [class.ant-tabs-top-content]=\"nzTabPosition === 'top'\"\n [class.ant-tabs-bottom-content]=\"nzTabPosition === 'bottom'\"\n [class.ant-tabs-left-content]=\"nzTabPosition === 'left'\"\n [class.ant-tabs-right-content]=\"nzTabPosition === 'right'\"\n [class.ant-tabs-content-animated]=\"tabPaneAnimated\"\n [class.ant-tabs-card-content]=\"nzType === 'card'\"\n [class.ant-tabs-content-no-animated]=\"!tabPaneAnimated\"\n [style.margin-left.%]=\"(tabPositionMode === 'horizontal') && tabPaneAnimated && (-(nzSelectedIndex || 0 ) * 100)\">\n <div nz-tab-body\n class=\"ant-tabs-tabpane\"\n *ngFor=\"let tab of listOfNzTabComponent; let i = index\"\n [active]=\"(nzSelectedIndex == i) && !nzHideAll\"\n [forceRender]=\"tab.nzForceRender\"\n [content]=\"tab.template || tab.content\">\n </div>\n </div>\n</ng-container>",
styles: ["\n nz-tabset {\n display: block;\n }\n "]
}] }
];
/** @nocollapse */
NzTabSetComponent.ctorParameters = function () { return [
{ type: NzConfigService },
{ type: Renderer2 },
{ type: NzUpdateHostClassService },
{ 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 }],
nzOnNextClick: [{ type: Output }],
nzOnPrevClick: [{ type: Output }],
nzSelectChange: [{ type: Output }],
nzSelectedIndexChange: [{ type: Output }],
nzSelectedIndex: [{ type: Input }]
};
tslib_1.__decorate([
WithConfig(true),
tslib_1.__metadata("design:type", Boolean)
], NzTabSetComponent.prototype, "nzShowPagination", void 0);
tslib_1.__decorate([
WithConfig(true),
tslib_1.__metadata("design:type", Object)
], NzTabSetComponent.prototype, "nzAnimated", void 0);
tslib_1.__decorate([
WithConfig('default'),
tslib_1.__metadata("design:type", String)
], NzTabSetComponent.prototype, "nzSize", void 0);
tslib_1.__decorate([
WithConfig(),
tslib_1.__metadata("design:type", Number)
], NzTabSetComponent.prototype, "nzTabBarGutter", void 0);
tslib_1.__decorate([
WithConfig('line'),
tslib_1.__metadata("design:type", String)
], NzTabSetComponent.prototype, "nzType", void 0);
tslib_1.__decorate([
InputBoolean(),
tslib_1.__metadata("design:type", Object)
], NzTabSetComponent.prototype, "nzLinkRouter", void 0);
tslib_1.__decorate([
InputBoolean(),
tslib_1.__metadata("design:type", Object)
], NzTabSetComponent.prototype, "nzLinkExact", void 0);
return NzTabSetComponent;
}());
export { NzTabSetComponent };
if (false) {
/**
* @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.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.nzUpdateHostClassService;
/**
* @type {?}
* @private
*/
NzTabSetComponent.prototype.elementRef;
/**
* @type {?}
* @private
*/
NzTabSetComponent.prototype.cdr;
/**
* @type {?}
* @private
*/
NzTabSetComponent.prototype.router;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibnotdGFic2V0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25nLXpvcnJvLWFudGQvdGFicy8iLCJzb3VyY2VzIjpbIm56LXRhYnNldC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztBQVVBLE9BQU8sRUFJTCx1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxlQUFlLEVBQ2YsVUFBVSxFQUNWLFlBQVksRUFDWixLQUFLLEVBSUwsUUFBUSxFQUNSLE1BQU0sRUFDTixTQUFTLEVBQ1QsU0FBUyxFQUVULFdBQVcsRUFDWCxTQUFTLEVBQ1QsaUJBQWlCLEVBQ2xCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFrQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3hGLE9BQU8sRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUVwRCxPQUFPLEVBQ0wsUUFBUSxFQUNSLFlBQVksRUFDWixlQUFlLEVBR2Ysd0JBQXdCLEVBQ3hCLE1BQU0sRUFDTixVQUFVLEVBQ1gsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUU5RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDcEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7Ozs7QUFFN0QseUNBR0M7OztJQUZDLHFDQUFnQjs7SUFDaEIsc0NBQWlCOztBQUduQjtJQUFBO0lBR0EsQ0FBQztJQUFELHVCQUFDO0FBQUQsQ0FBQyxBQUhELElBR0M7Ozs7SUFGQyxpQ0FBYzs7SUFDZCwrQkFBb0I7O0FBT3RCO0lBMklFLDJCQUNTLGVBQWdDLEVBQy9CLFFBQW1CLEVBQ25CLHdCQUFrRCxFQUNsRCxVQUFzQixFQUN0QixHQUFzQixFQUNW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SUFDMUI7UUFBakIsVUFBVSxDQUFDLElBQUksQ0FBQzs7eURBQTJDO0lBR3JDO1FBQXRCLFVBQVUsQ0FBQyxTQUFTLENBQUM7O3FEQUF1QjtJQUMvQjtRQUFiLFVBQVUsRUFBRTs7NkRBQXdCO0lBRWpCO1FBQW5CLFVBQVUsQ0FBQyxNQUFNLENBQUM7O3FEQUFtQjtJQUV0QjtRQUFmLFlBQVksRUFBRTs7MkRBQXNCO0lBQ3JCO1FBQWYsWUFBWSxFQUFFOzswREFBb0I7SUF3UDlDLHdCQUFDO0NBQUEsQUFwU0QsSUFvU0M7U0FwUlksaUJBQWlCOzs7Ozs7SUFFNUIsMENBQXlDOzs7OztJQUN6QywrQkFBd0Q7Ozs7O0lBQ3hELDJDQUE2Qzs7Ozs7O0lBRTdDLDZDQUE4Qzs7Ozs7O0lBRTlDLGlEQUFrRDs7Ozs7SUFFbEQscUNBQXVDOztJQUV2Qyw0Q0FBa0Q7O0lBQ2xELGlEQUFpRjs7SUFDakYsK0NBQXlGOztJQUN6Rix1Q0FBbUU7O0lBRW5FLGlEQUFpRDs7SUFDakQsNkNBQXFEOztJQUNyRCx1Q0FBcUU7O0lBQ3JFLHNDQUEyQjs7SUFDM0IsMENBQThDOztJQUM5QyxtQ0FBc0Q7O0lBQ3RELDJDQUE4Qzs7SUFDOUMsMENBQWtEOztJQUNsRCxtQ0FBK0M7O0lBRS9DLHlDQUE4Qzs7SUFDOUMsd0NBQTRDOztJQUU1QywwQ0FBNEQ7O0lBQzVELDBDQUE0RDs7SUFDNUQsMkNBQTZHOztJQUM3RyxrREFBNEY7O0lBMkYxRiw0Q0FBdUM7Ozs7O0lBQ3ZDLHFDQUEyQjs7Ozs7SUFDM0IscURBQTBEOzs7OztJQUMxRCx1Q0FBOEI7Ozs7O0lBQzlCLGdDQUE4Qjs7Ozs7SUFDOUIsbUNBQWtDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEFsaWJhYmEuY29tIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9naXRodWIuY29tL05HLVpPUlJPL25nLXpvcnJvLWFudGQvYmxvYi9tYXN0ZXIvTElDRU5TRVxuICovXG5cbi8qKiBnZXQgc29tZSBjb2RlIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL2FuZ3VsYXIvbWF0ZXJpYWwyICovXG5cbmltcG9ydCB7XG4gIEFmdGVyQ29udGVudENoZWNrZWQsXG4gIEFmdGVyQ29udGVudEluaXQsXG4gIEFmdGVyVmlld0luaXQsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBDb250ZW50Q2hpbGRyZW4sXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE9wdGlvbmFsLFxuICBPdXRwdXQsXG4gIFF1ZXJ5TGlzdCxcbiAgUmVuZGVyZXIyLFxuICBTaW1wbGVDaGFuZ2VzLFxuICBUZW1wbGF0ZVJlZixcbiAgVmlld0NoaWxkLFxuICBWaWV3RW5jYXBzdWxhdGlvblxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE5hdmlnYXRpb25FbmQsIFJvdXRlciwgUm91dGVyTGluaywgUm91dGVyTGlua1dpdGhIcmVmIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IG1lcmdlLCBTdWJqZWN0LCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHtcbiAgdG9OdW1iZXIsXG4gIElucHV0Qm9vbGVhbixcbiAgTnpDb25maWdTZXJ2aWNlLFxuICBOekZvdXJEaXJlY3Rpb25UeXBlLFxuICBOelNpemVMRFNUeXBlLFxuICBOelVwZGF0ZUhvc3RDbGFzc1NlcnZpY2UsXG4gIFBSRUZJWCxcbiAgV2l0aENvbmZpZ1xufSBmcm9tICduZy16b3Jyby1hbnRkL2NvcmUnO1xuaW1wb3J0IHsgZmlsdGVyLCBzdGFydFdpdGgsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgTnpUYWJDb21wb25lbnQgfSBmcm9tICcuL256LXRhYi5jb21wb25lbnQnO1xuaW1wb3J0IHsgTnpUYWJzTmF2Q29tcG9uZW50IH0gZnJvbSAnLi9uei10YWJzLW5hdi5jb21wb25lbnQnO1xuXG5leHBvcnQgaW50ZXJmYWNlIE56QW5pbWF0ZWRJbnRlcmZhY2Uge1xuICBpbmtCYXI6IGJvb2xlYW47XG4gIHRhYlBhbmU6IGJvb2xlYW47XG59XG5cbmV4cG9ydCBjbGFzcyBOelRhYkNoYW5nZUV2ZW50IHtcbiAgaW5kZXg6IG51bWJlcjtcbiAgdGFiOiBOelRhYkNvbXBvbmVudDtcbn1cblxuZXhwb3J0IHR5cGUgTnpUYWJQb3NpdGlvbiA9IE56Rm91ckRpcmVjdGlvblR5cGU7XG5leHBvcnQgdHlwZSBOelRhYlBvc2l0aW9uTW9kZSA9ICdob3Jpem9udGFsJyB8ICd2ZXJ0aWNhbCc7XG5leHBvcnQgdHlwZSBOelRhYlR5cGUgPSAnbGluZScgfCAnY2FyZCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ256LXRhYnNldCcsXG4gIGV4cG9ydEFzOiAnbnpUYWJzZXQnLFxuICBwcmVzZXJ2ZVdoaXRlc3BhY2VzOiBmYWxzZSxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHByb3ZpZGVyczogW056VXBkYXRlSG9zdENsYXNzU2VydmljZV0sXG4gIHRlbXBsYXRlVXJsOiAnLi9uei10YWJzZXQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZXM6IFtcbiAgICBgXG4gICAgICBuei10YWJzZXQge1xuICAgICAgICBkaXNwbGF5OiBibG9jaztcbiAgICAgIH1cbiAgICBgXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgTnpUYWJTZXRDb21wb25lbnRcbiAgaW1wbGVtZW50cyBBZnRlckNvbnRlbnRDaGVja2VkLCBPbkluaXQsIEFmdGVyVmlld0luaXQsIE9uQ2hhbmdlcywgQWZ0ZXJDb250ZW50SW5pdCwgT25EZXN0cm95IHtcbiAgcHJpdmF0ZSBpbmRleFRvU2VsZWN0OiBudW1iZXIgfCBudWxsID0gMDtcbiAgcHJpdmF0ZSBlbDogSFRNTEVsZW1lbnQgPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcbiAgcHJpdmF0ZSBfc2VsZWN0ZWRJbmRleDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBTdWJzY3JpcHRpb24gdG8gdGFicyBiZWluZyBhZGRlZC9yZW1vdmVkLiAqL1xuICBwcml2YXRlIHRhYnNTdWJzY3JpcHRpb24gPSBTdWJzY3JpcHRpb24uRU1QVFk7XG4gIC8qKiBTdWJzY3JpcHRpb24gdG8gY2hhbmdlcyBpbiB0aGUgdGFiIGxhYmVscy4gKi9cbiAgcHJpdmF0ZSB0YWJMYWJlbFN1YnNjcmlwdGlvbiA9IFN1YnNjcmlwdGlvbi5FTVBUWTtcblxuICBwcml2YXRlIGRlc3Ryb3kkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICB0YWJQb3NpdGlvbk1vZGU6IE56VGFiUG9zaXRpb25Nb2RlID0gJ2hvcml6b250YWwnO1xuICBAQ29udGVudENoaWxkcmVuKE56VGFiQ29tcG9uZW50KSBsaXN0T2ZOelRhYkNvbXBvbmVudDogUXVlcnlMaXN0PE56VGFiQ29tcG9uZW50PjtcbiAgQFZpZXdDaGlsZChOelRhYnNOYXZDb21wb25lbnQsIHsgc3RhdGljOiBmYWxzZSB9KSBuelRhYnNOYXZDb21wb25lbnQ6IE56VGFic05hdkNvbXBvbmVudDtcbiAgQFZpZXdDaGlsZCgndGFiQ29udGVudCcsIHsgc3RhdGljOiBmYWxzZSB9KSB0YWJDb250ZW50OiBFbGVtZW50UmVmO1xuXG4gIEBJbnB1dCgpIG56VGFiQmFyRXh0cmFDb250ZW50OiBUZW1wbGF0ZVJlZjx2b2lkPjtcbiAgQElucHV0KCkgQFdpdGhDb25maWcodHJ1ZSkgbnpTaG93UGFnaW5hdGlvbjogYm9vbGVhbjtcbiAgQElucHV0KCkgQFdpdGhDb25maWcodHJ1ZSkgbnpBbmltYXRlZDogTnpBbmltYXRlZEludGVyZmFjZSB8IGJvb2xlYW47XG4gIEBJbnB1dCgpIG56SGlkZUFsbCA9IGZhbHNlO1xuICBASW5wdXQoKSBuelRhYlBvc2l0aW9uOiBOelRhYlBvc2l0aW9uID0gJ3RvcCc7XG4gIEBJbnB1dCgpIEBXaXRoQ29uZmlnKCdkZWZhdWx0JykgbnpTaXplOiBOelNpemVMRFNUeXBlO1xuICBASW5wdXQoKSBAV2l0aENvbmZpZygpIG56VGFiQmFyR3V0dGVyOiBudW1iZXI7XG4gIEBJbnB1dCgpIG56VGFiQmFyU3R5bGU6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XG4gIEBJbnB1dCgpIEBXaXRoQ29uZmlnKCdsaW5lJykgbnpUeXBlOiBOelRhYlR5cGU7XG5cbiAgQElucHV0KCkgQElucHV0Qm9vbGVhbigpIG56TGlua1JvdXRlciA9IGZhbHNlO1xuICBASW5wdXQoKSBASW5wdXRCb29sZWFuKCkgbnpMaW5rRXhhY3QgPSB0cnVlO1xuXG4gIEBPdXRwdXQoKSByZWFkb25seSBuek9uTmV4dENsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuICBAT3V0cHV0KCkgcmVhZG9ubHkgbnpPblByZXZDbGljayA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcbiAgQE91dHB1dCgpIHJlYWRvbmx5IG56U2VsZWN0Q2hhbmdlOiBFdmVudEVtaXR0ZXI8TnpUYWJDaGFuZ2VFdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyPE56VGFiQ2hhbmdlRXZlbnQ+KHRydWUpO1xuICBAT3V0cHV0KCkgcmVhZG9ubHkgbnpTZWxlY3RlZEluZGV4Q2hhbmdlOiBFdmVudEVtaXR0ZXI8bnVtYmVyPiA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xuXG4gIEBJbnB1dCgpXG4gIHNldCBuelNlbGVjdGVkSW5kZXgodmFsdWU6IG51bWJlciB8IG51bGwpIHtcbiAgICB0aGlzLmluZGV4VG9TZWxlY3QgPSB2YWx1ZSA/IHRvTnVtYmVyKHZhbHVlLCBudWxsKSA6IG51bGw7XG4gIH1cblxuICBnZXQgbnpTZWxlY3RlZEluZGV4KCk6IG51bWJlciB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLl9zZWxlY3RlZEluZGV4O1xuICB9XG5cbiAgZ2V0IGlua0JhckFuaW1hdGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm56QW5pbWF0ZWQgPT09IHRydWUgfHwgKHRoaXMubnpBbmltYXRlZCBhcyBOekFuaW1hdGVkSW50ZXJmYWNlKS5pbmtCYXIgPT09IHRydWU7XG4gIH1cblxuICBnZXQgdGFiUGFuZUFuaW1hdGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm56QW5pbWF0ZWQgPT09IHRydWUgfHwgKHRoaXMubnpBbmltYXRlZCBhcyBOekFuaW1hdGVkSW50ZXJmYWNlKS50YWJQYW5lID09PSB0cnVlO1xuICB9XG5cbiAgc2V0UG9zaXRpb24odmFsdWU6IE56VGFiUG9zaXRpb24pOiB2b2lkIHtcbiAgICBpZiAodGhpcy50YWJDb250ZW50KSB7XG4gICAgICBpZiAodmFsdWUgPT09ICdib3R0b20nKSB7XG4gICAgICAgIHRoaXMucmVuZGVyZXIuaW5zZXJ0QmVmb3JlKFxuICAgICAgICAgIHRoaXMuZWwsXG4gICAgICAgICAgdGhpcy50YWJDb250ZW50Lm5hdGl2ZUVsZW1lbnQsXG4gICAgICAgICAgdGhpcy5uelRhYnNOYXZDb21wb25lbnQuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50XG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnJlbmRlcmVyLmluc2VydEJlZm9yZShcbiAgICAgICAgICB0aGlzLmVsLFxuICAgICAgICAgIHRoaXMubnpUYWJzTmF2Q29tcG9uZW50LmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCxcbiAgICAgICAgICB0aGlzLnRhYkNvbnRlbnQubmF0aXZlRWxlbWVudFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHNldENsYXNzTWFwKCk6IHZvaWQge1xuICAgIHRoaXMubnpVcGRhdGVIb3N0Q2xhc3NTZXJ2aWNlLnVwZGF0ZUhvc3RDbGFzcyh0aGlzLmVsLCB7XG4gICAgICBbYGFudC10YWJzYF06IHRydWUsXG4gICAgICBbYGFudC10YWJzLXZlcnRpY2FsYF06IHRoaXMubnpUYWJQb3NpdGlvbiA9PT0gJ2xlZnQnIHx8IHRoaXMubnpUYWJQb3NpdGlvbiA9PT0gJ3JpZ2h0JyxcbiAgICAgIFtgYW50LXRhYnMtJHt0aGlzLm56VGFiUG9zaXRpb259YF06IHRoaXMubnpUYWJQb3NpdGlvbixcbiAgICAgIFtgYW50LXRhYnMtbm8tYW5pbWF0aW9uYF06XG4gICAgICAgIHRoaXMubnpBbmltYXRlZCA9PT0gZmFsc2UgfHwgKHRoaXMubnpBbmltYXRlZCBhcyBOekFuaW1hdGVkSW50ZXJmYWNlKS50YWJQYW5lID09PSBmYWxzZSxcbiAgICAgIFtgYW50LXRhYnMtJHt0aGlzLm56VHlwZX1gXTogdGhpcy5uelR5cGUsXG4gICAgICBbYGFudC10YWJzLWxhcmdlYF06IHRoaXMubnpTaXplID09PSAnbGFyZ2UnLFxuICAgICAgW2BhbnQtdGFicy1zbWFsbGBdOiB0aGlzLm56U2l6ZSA9PT0gJ3NtYWxsJ1xuICAgIH0pO1xuICB9XG5cbiAgY2xpY2tMYWJlbChpbmRleDogbnVtYmVyLCBkaXNhYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmICghZGlzYWJsZWQpIHtcbiAgICAgIGNvbnN0IHRhYnMgPSB0aGlzLmxpc3RPZk56VGFiQ29tcG9uZW50LnRvQXJyYXkoKTtcbiAgICAgIHRoaXMubnpTZWxlY3RlZEluZGV4ID0gaW5kZXg7XG4gICAgICB0YWJzW2luZGV4XS5uekNsaWNrLmVtaXQoKTtcbiAgICB9XG4gIH1cblxuICBjcmVhdGVDaGFuZ2VFdmVudChpbmRleDogbnVtYmVyKTogTnpUYWJDaGFuZ2VFdmVudCB7XG4gICAgY29uc3QgZXZlbnQgPSBuZXcgTnpUYWJDaGFuZ2VFdmVudCgpO1xuICAgIGV2ZW50LmluZGV4ID0gaW5kZXg7XG4gICAgaWYgKHRoaXMubGlzdE9mTnpUYWJDb21wb25lbnQgJiYgdGhpcy5saXN0T2ZOelRhYkNvbXBvbmVudC5sZW5ndGgpIHtcbiAgICAgIGV2ZW50LnRhYiA9IHRoaXMubGlzdE9mTnpUYWJDb21wb25lbnQudG9BcnJheSgpW2luZGV4XTtcbiAgICAgIHRoaXMubGlzdE9mTnpUYWJDb21wb25lbnQuZm9yRWFjaCgoaXRlbSwgaSkgPT4ge1xuICAgICAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgICAgICBpdGVtLm56RGVzZWxlY3QuZW1pdCgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGV2ZW50LnRhYi5uelNlbGVjdC5lbWl0KCk7XG4gICAgfVxuICAgIHJldHVybiBldmVudDtcbiAgfVxuXG4gIC8qKiBDbGFtcHMgdGhlIGdpdmVuIGluZGV4IHRvIHRoZSBib3VuZHMgb2YgMCBhbmQgdGhlIHRhYnMgbGVuZ3RoLiAqL1xuICBwcml2YXRlIGNsYW1wVGFiSW5kZXgoaW5kZXg6IG51bWJlciB8IG51bGwpOiBudW1iZXIge1xuICAgIC8vIE5vdGUgdGhlIGB8fCAwYCwgd2hpY2ggZW5zdXJlcyB0aGF0IHZhbHVlcyBsaWtlIE5hTiBjYW4ndCBnZXQgdGhyb3VnaFxuICAgIC8vIGFuZCB3aGljaCB3b3VsZCBvdGhlcndpc2UgdGhyb3cgdGhlIGNvbXBvbmVudCBpbnRvIGFuIGluZmluaXRlIGxvb3BcbiAgICAvLyAoc2luY2UgTWF0aC5tYXgoTmFOLCAwKSA9PT0gTmFOKS5cbiAgICByZXR1cm4gTWF0aC5taW4odGhpcy5saXN0T2ZOelRhYkNvbXBvbmVudC5sZW5ndGggLSAxLCBNYXRoLm1heChpbmRleCB8fCAwLCAwKSk7XG4gIH1cblxuICBwcml2YXRlIHN1YnNjcmliZVRvVGFiTGFiZWxzKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnRhYkxhYmVsU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLnRhYkxhYmVsU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICAgIHRoaXMudGFiTGFiZWxTdWJzY3JpcHRpb24gPSBtZXJnZSguLi50aGlzLmxpc3RPZk56VGFiQ29tcG9uZW50Lm1hcCh0YWIgPT4gdGFiLnN0YXRlQ2hhbmdlcykpLnN1YnNjcmliZSgoKSA9PlxuICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKClcbiAgICApO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIG56Q29uZmlnU2VydmljZTogTnpDb25maWdTZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVuZGVyZXI6IFJlbmRlcmVyMixcbiAgICBwcml2YXRlIG56VXBkYXRlSG9zdENsYXNzU2VydmljZTogTnpVcGRhdGVIb3N0Q2xhc3NTZXJ2aWNlLFxuICAgIHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZixcbiAgICBwcml2YXRlIGNkcjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgQE9wdGlvbmFsKCkgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlclxuICApIHt9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzLm56VGFiUG9zaXRpb24pIHtcbiAgICAgIGlmICh0aGlzLm56VGFiUG9zaXRpb24gPT09ICd0b3AnIHx8IHRoaXMubnpUYWJQb3NpdGlvbiA9PT0gJ2JvdHRvbScpIHtcbiAgICAgICAgdGhpcy50YWJQb3NpdGlvbk1vZGUgPSAnaG9yaXpvbnRhbCc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnRhYlBvc2l0aW9uTW9kZSA9ICd2ZXJ0aWNhbCc7XG4gICAgICB9XG4gICAgICB0aGlzLnNldFBvc2l0aW9uKHRoaXMubnpUYWJQb3NpdGlvbik7XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzLm56VHlwZSkge1xuICAgICAgaWYgKHRoaXMubnpUeXBlID09PSAnY2FyZCcpIHtcbiAgICAgICAgdGhpcy5uekFuaW1hdGVkID0gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzLm56U2l6ZSB8fCBjaGFuZ2VzLm56QW5pbWF0ZWQgfHwgY2hhbmdlcy5uelRhYlBvc2l0aW9uIHx8IGNoYW5nZXMubnpUeXBlKSB7XG4gICAgICB0aGlzLnNldENsYXNzTWFwKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zZXRDbGFzc01hcCgpO1xuICB9XG5cbiAgbmdBZnRlckNvbnRlbnRDaGVja2VkKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmxpc3RPZk56VGFiQ29tcG9uZW50ICYmIHRoaXMubGlzdE9mTnpUYWJDb21wb25lbnQubGVuZ3RoKSB7XG4gICAgICAvLyBEb24ndCBjbGFtcCB0aGUgYGluZGV4VG9TZWxlY3RgIGltbWVkaWF0ZWx5IGluIHRoZSBzZXR0ZXIgYmVjYXVzZSBpdCBjYW4gaGFwcGVuIHRoYXRcbiAgICAgIC8vIHRoZSBhbW91bnQgb2YgdGFicyBjaGFuZ2VzIGJlZm9yZSB0aGUgYWN0dWFsIGNoYW5nZSBkZXRlY3Rpb24gcnVucy5cbiAgICAgIGNvbnN0IGluZGV4VG9TZWxlY3QgPSAodGhpcy5pbmRleFRvU2VsZWN0ID0gdGhpcy5jbGFtcFRhYkluZGV4KHRoaXMuaW5kZXhUb1NlbGVjdCkpO1xuICAgICAgLy8gSWYgdGhlcmUgaXMgYSBjaGFuZ2UgaW4gc2VsZWN0ZWQgaW5kZXgsIGVtaXQgYSBjaGFuZ2UgZXZlbnQuIFNob3VsZCBub3QgdHJpZ2dlciBpZlxuICAgICAgLy8gdGhlIHNlbGVjdGVkIGluZGV4IGhhcyBub3QgeWV0IGJlZW4gaW5pdGlhbGl6ZWQuXG4gICAgICBpZiAodGhpcy5fc2VsZWN0ZWRJbmRleCAhPT0gaW5kZXhUb1NlbGVjdCkge1xuICAgICAgICBjb25zdCBpc0ZpcnN0UnVuID0gdGhpcy5fc2VsZWN0ZWRJbmRleCA9PSBudWxsO1xuICAgICAgICBpZiAoIWlzRmlyc3RSdW4pIHtcbiAgICAgICAgICB0aGlzLm56U2VsZWN0Q2hhbmdlLmVtaXQodGhpcy5jcmVhdGVDaGFuZ2VFdmVudChpbmRleFRvU2VsZWN0KSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGFuZ2luZyB0aGVzZSB2YWx1ZXMgYWZ0ZXIgY2hhbmdlIGRldGVjdGlvbiBoYXMgcnVuXG4gICAgICAgIC8vIHNpbmNlIHRoZSBjaGVja2VkIGNvbnRlbnQgbWF5IGNvbnRhaW4gcmVmZXJlbmNlcyB0byB0aGVtLlxuICAgICAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcbiAgICAgICAgICB0aGlzLmxpc3RPZk56VGFiQ29tcG9uZW50LmZvckVhY2goKHRhYiwgaW5kZXgpID0+ICh0YWIuaXNBY3RpdmUgPSBpbmRleCA9PT0gaW5kZXhUb1NlbGVjdCkpO1xuXG4gICAgICAgICAgaWYgKCFpc0ZpcnN0UnVuKSB7XG4gICAgICAgICAgICB0aGlzLm56U2VsZWN0ZWRJbmRleENoYW5nZS5lbWl0KGluZGV4VG9TZWxlY3QpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIFNldHVwIHRoZSBwb3NpdGlvbiBmb3IgZWFjaCB0YWIgYW5kIG9wdGlvbmFsbHkgc2V0dXAgYW4gb3JpZ2luIG9uIHRoZSBuZXh0IHNlbGVjdGVkIHRhYi5cbiAgICAgIHRoaXMubGlzdE9mTnpUYWJDb21wb25lbnQuZm9yRWFjaCgodGFiOiBOelRhYkNvbXBvbmVudCwgaW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgICB0YWIucG9zaXRpb24gPSBpbmRleCAtIGluZGV4VG9TZWxlY3Q7XG5cbiAgICAgICAgLy8gSWYgdGhlcmUgaXMgYWxyZWFkeSBhIHNlbGVjdGVkIHRhYiwgdGhlbiBzZXQgdXAgYW4gb3JpZ2luIGZvciB0aGUgbmV4dCBzZWxlY3RlZCB0YWJcbiAgICAgICAgLy8gaWYgaXQgZG9lc24ndCBoYXZlIG9uZSBhbHJlYWR5LlxuICAgICAgICBpZiAodGhpcy5fc2VsZWN0ZWRJbmRleCAhPSBudWxsICYmIHRhYi5wb3NpdGlvbiA9PT0gMCAmJiAhdGFiLm9yaWdpbikge1xuICAgICAgICAgIHRhYi5vcmlnaW4gPSBpbmRleFRvU2VsZWN0IC0gdGhpcy5fc2VsZWN0ZWRJbmRleDtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGlmICh0aGlzLl9zZWxlY3RlZEluZGV4ICE9PSBpbmRleFRvU2VsZWN0KSB7XG4gICAgICAgIHRoaXMuX3NlbGVjdGVkSW5kZXggPSBpbmRleFRvU2VsZWN0O1xuICAgICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBuZ0FmdGVyQ29udGVudEluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zdWJzY3JpYmVUb1RhYkxhYmVscygpO1xuXG4gICAgLy8gU3Vic2NyaWJlIHRvIGNoYW5nZXMgaW4gdGhlIGFtb3VudCBvZiB0YWJzLCBpbiBvcmRlciB0byBiZVxuICAgIC8vIGFibGUgdG8gcmUtcmVuZGVyIHRoZSBjb250ZW50IGFzIG5ldyB0YWJzIGFyZSBhZGRlZCBvciByZW1vdmVkLlxuICAgIHRoaXMudGFic1N1YnNjcmlwdGlvbiA9IHRoaXMubGlzdE9mTnpUYWJDb21wb25lbnQuY2hhbmdlcy5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgY29uc3QgaW5kZXhUb1NlbGVjdCA9IHRoaXMuY2xhbXBUYWJJbmRleCh0aGlzLmluZGV4VG9TZWxlY3QpO1xuXG4gICAgICAvLyBNYWludGFpbiB0aGUgcHJldmlvdXNseS1zZWxlY3RlZCB0YWIgaWYgYSBuZXcgdGFiIGlzIGFkZGVkIG9yIHJlbW92ZWQgYW5kIHRoZXJlIGlzIG5vXG4gICAgICAvLyBleHBsaWNpdCBjaGFuZ2UgdGhhdCBzZWxlY3RzIGEgZGlmZmVyZW50IHRhYi5