ng-zorro-antd
Version:
An enterprise-class UI components based on Ant Design and Angular
640 lines • 59 kB
JavaScript
/**
* @fileoverview added by tsickle
* Generated from: picker.component.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { __assign } 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
*/
import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
import { DOCUMENT } from '@angular/common';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, Inject, Input, Output, QueryList, ViewChild, ViewChildren, ViewEncapsulation } from '@angular/core';
import { slideMotion } from 'ng-zorro-antd/core/animation';
import { CandyDate } from 'ng-zorro-antd/core/time';
import { DateHelperService } from 'ng-zorro-antd/i18n';
import { fromEvent, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { DatePickerService } from './date-picker.service';
import { DateRangePopupComponent } from './date-range-popup.component';
import { PREFIX_CLASS } from './util';
var NzPickerComponent = /** @class */ (function () {
function NzPickerComponent(elementRef, dateHelper, changeDetector, datePickerService, doc) {
this.elementRef = elementRef;
this.dateHelper = dateHelper;
this.changeDetector = changeDetector;
this.datePickerService = datePickerService;
this.noAnimation = false;
this.isRange = false;
this.open = undefined;
this.focusChange = new EventEmitter();
this.valueChange = new EventEmitter();
this.openChange = new EventEmitter(); // Emitted when overlay's open state change
this.destroy$ = new Subject();
this.prefixCls = PREFIX_CLASS;
this.activeBarStyle = { position: 'absolute' };
this.animationOpenState = false;
this.overlayOpen = false; // Available when "open"=undefined
// Available when "open"=undefined
this.overlayPositions = (/** @type {?} */ ([
{
// offsetX: -10, // TODO: What a pity, cdk/overlay current not support offset configs even though it already provide these properties
// offsetY: -10,
originX: 'start',
originY: 'bottom',
overlayX: 'start',
overlayY: 'top'
},
{
originX: 'start',
originY: 'top',
overlayX: 'start',
overlayY: 'bottom'
},
{
originX: 'end',
originY: 'bottom',
overlayX: 'end',
overlayY: 'top'
},
{
originX: 'end',
originY: 'top',
overlayX: 'end',
overlayY: 'bottom'
}
]));
this.currentPositionX = 'start';
this.currentPositionY = 'bottom';
this.document = doc;
this.origin = new CdkOverlayOrigin(this.elementRef);
this.updateInputValue();
}
Object.defineProperty(NzPickerComponent.prototype, "realOpenState", {
get: /**
* @return {?}
*/
function () {
// The value that really decide the open state of overlay
return this.isOpenHandledByUser() ? !!this.open : this.overlayOpen;
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
NzPickerComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
var _this = this;
this.inputSize = Math.max(10, this.format.length) + 2;
this.datePickerService.valueChange$.pipe(takeUntil(this.destroy$)).subscribe((/**
* @return {?}
*/
function () {
_this.updateInputValue();
_this.changeDetector.markForCheck();
}));
};
/**
* @return {?}
*/
NzPickerComponent.prototype.ngAfterViewInit = /**
* @return {?}
*/
function () {
var _this = this;
if (this.autoFocus) {
this.focus();
}
if (this.isRange) {
this.resetInputWidthAndArrowLeft();
fromEvent(window, 'resize')
.pipe(takeUntil(this.destroy$))
.subscribe((/**
* @return {?}
*/
function () {
_this.resetInputWidthAndArrowLeft();
}));
}
this.datePickerService.inputPartChange$.pipe(takeUntil(this.destroy$)).subscribe((/**
* @param {?} partType
* @return {?}
*/
function (partType) {
var _a;
if (partType) {
_this.datePickerService.activeInput = partType;
}
_this.datePickerService.arrowPositionStyle = {
left: _this.datePickerService.activeInput === 'left' ? '0px' : _this.arrowLeft + "px"
};
_this.activeBarStyle = __assign(__assign(__assign({}, _this.activeBarStyle), _this.datePickerService.arrowPositionStyle), { width: _this.inputWidth + "px" });
if (_this.document.activeElement !== _this.getInput(_this.datePickerService.activeInput)) {
_this.focus();
}
(_a = _this.panel) === null || _a === void 0 ? void 0 : _a.cdr.markForCheck();
_this.changeDetector.markForCheck();
}));
};
/**
* @return {?}
*/
NzPickerComponent.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this.destroy$.next();
this.destroy$.complete();
};
/**
* @param {?} changes
* @return {?}
*/
NzPickerComponent.prototype.ngOnChanges = /**
* @param {?} changes
* @return {?}
*/
function (changes) {
if (changes.open) {
this.animationStart();
}
};
/**
* @return {?}
*/
NzPickerComponent.prototype.resetInputWidthAndArrowLeft = /**
* @return {?}
*/
function () {
var _a, _b;
this.inputWidth = ((_a = this.rangePickerInputs) === null || _a === void 0 ? void 0 : _a.first.nativeElement.offsetWidth) || 0;
this.arrowLeft = this.inputWidth + ((_b = this.separatorElement) === null || _b === void 0 ? void 0 : _b.nativeElement.offsetWidth) || 0;
};
/**
* @param {?=} partType
* @return {?}
*/
NzPickerComponent.prototype.getInput = /**
* @param {?=} partType
* @return {?}
*/
function (partType) {
return this.isRange
? partType === 'left'
? this.rangePickerInputs.first.nativeElement
: this.rangePickerInputs.last.nativeElement
: this.pickerInput.nativeElement;
};
/**
* @return {?}
*/
NzPickerComponent.prototype.focus = /**
* @return {?}
*/
function () {
this.getInput(this.datePickerService.activeInput).focus(); // Focus on the first input
};
/**
* @param {?=} partType
* @return {?}
*/
NzPickerComponent.prototype.onFocus = /**
* @param {?=} partType
* @return {?}
*/
function (partType) {
if (partType) {
this.datePickerService.inputPartChange$.next(partType);
}
this.focusChange.emit(true);
};
/**
* @return {?}
*/
NzPickerComponent.prototype.onBlur = /**
* @return {?}
*/
function () {
this.focusChange.emit(false);
};
// Show overlay content
// Show overlay content
/**
* @return {?}
*/
NzPickerComponent.prototype.showOverlay =
// Show overlay content
/**
* @return {?}
*/
function () {
var _this = this;
if (!this.realOpenState) {
this.overlayOpen = true;
this.animationStart();
this.focus();
this.openChange.emit(true);
setTimeout((/**
* @return {?}
*/
function () {
if (_this.cdkConnectedOverlay && _this.cdkConnectedOverlay.overlayRef) {
_this.cdkConnectedOverlay.overlayRef.updatePosition();
}
}));
}
};
/**
* @return {?}
*/
NzPickerComponent.prototype.hideOverlay = /**
* @return {?}
*/
function () {
if (this.realOpenState) {
this.overlayOpen = false;
this.openChange.emit(false);
this.focus();
}
};
/**
* @return {?}
*/
NzPickerComponent.prototype.showClear = /**
* @return {?}
*/
function () {
return !this.disabled && !this.isEmptyValue(this.datePickerService.value) && this.allowClear;
};
/**
* @param {?=} partType
* @return {?}
*/
NzPickerComponent.prototype.onClickInputBox = /**
* @param {?=} partType
* @return {?}
*/
function (partType) {
if (!this.disabled && !this.isOpenHandledByUser()) {
this.showOverlay();
}
this.onFocus(partType);
};
/**
* @return {?}
*/
NzPickerComponent.prototype.onClickBackdrop = /**
* @return {?}
*/
function () {
if (this.panel.isAllowed((/** @type {?} */ (this.datePickerService.value)), true)) {
this.updateInputValue();
this.datePickerService.emitValue$.next();
}
else {
this.datePickerService.setValue(this.datePickerService.initialValue);
this.hideOverlay();
}
};
/**
* @return {?}
*/
NzPickerComponent.prototype.onOverlayDetach = /**
* @return {?}
*/
function () {
this.hideOverlay();
};
/**
* @param {?} event
* @return {?}
*/
NzPickerComponent.prototype.onOverlayKeydown = /**
* @param {?} event
* @return {?}
*/
function (event) {
if (event.key === 'Escape') {
this.datePickerService.setValue(this.datePickerService.initialValue);
}
};
// NOTE: A issue here, the first time position change, the animation will not be triggered.
// Because the overlay's "positionChange" event is emitted after the content's full shown up.
// All other components like "nz-dropdown" which depends on overlay also has the same issue.
// See: https://github.com/NG-ZORRO/ng-zorro-antd/issues/1429
// NOTE: A issue here, the first time position change, the animation will not be triggered.
// Because the overlay's "positionChange" event is emitted after the content's full shown up.
// All other components like "nz-dropdown" which depends on overlay also has the same issue.
// See: https://github.com/NG-ZORRO/ng-zorro-antd/issues/1429
/**
* @param {?} position
* @return {?}
*/
NzPickerComponent.prototype.onPositionChange =
// NOTE: A issue here, the first time position change, the animation will not be triggered.
// Because the overlay's "positionChange" event is emitted after the content's full shown up.
// All other components like "nz-dropdown" which depends on overlay also has the same issue.
// See: https://github.com/NG-ZORRO/ng-zorro-antd/issues/1429
/**
* @param {?} position
* @return {?}
*/
function (position) {
this.currentPositionX = position.connectionPair.originX;
this.currentPositionY = position.connectionPair.originY;
this.changeDetector.detectChanges(); // Take side-effects to position styles
};
/**
* @param {?} event
* @return {?}
*/
NzPickerComponent.prototype.onClickClear = /**
* @param {?} event
* @return {?}
*/
function (event) {
event.preventDefault();
event.stopPropagation();
this.datePickerService.setValue(this.isRange ? [] : null);
this.datePickerService.emitValue$.next();
};
/**
* @return {?}
*/
NzPickerComponent.prototype.updateInputValue = /**
* @return {?}
*/
function () {
var _this = this;
/** @type {?} */
var newValue = this.datePickerService.value;
if (this.isRange) {
this.inputValue = newValue ? ((/** @type {?} */ (newValue))).map((/**
* @param {?} v
* @return {?}
*/
function (v) { return _this.formatValue(v); })) : ['', ''];
}
else {
this.inputValue = this.formatValue((/** @type {?} */ (newValue)));
}
};
/**
* @param {?} value
* @return {?}
*/
NzPickerComponent.prototype.formatValue = /**
* @param {?} value
* @return {?}
*/
function (value) {
return this.dateHelper.format(value && ((/** @type {?} */ (value))).nativeDate, this.format);
};
/**
* @param {?} event
* @param {?=} isEnter
* @return {?}
*/
NzPickerComponent.prototype.onInputKeyup = /**
* @param {?} event
* @param {?=} isEnter
* @return {?}
*/
function (event, isEnter) {
if (isEnter === void 0) { isEnter = false; }
if (isEnter && !this.realOpenState) {
this.showOverlay();
return;
}
/** @type {?} */
var date = this.checkValidInputDate((/** @type {?} */ (((/** @type {?} */ (event))).target)));
if (this.panel && date) {
this.panel.changeValueFromSelect(date, isEnter);
}
};
/**
* @private
* @param {?} inputTarget
* @return {?}
*/
NzPickerComponent.prototype.checkValidInputDate = /**
* @private
* @param {?} inputTarget
* @return {?}
*/
function (inputTarget) {
/** @type {?} */
var input = ((/** @type {?} */ (inputTarget))).value;
/** @type {?} */
var date = new CandyDate(this.dateHelper.parseDate(input, this.format));
if (!date.isValid() || input !== this.dateHelper.format(date.nativeDate, this.format)) {
return null;
}
return date;
};
/**
* @param {?=} partType
* @return {?}
*/
NzPickerComponent.prototype.getPlaceholder = /**
* @param {?=} partType
* @return {?}
*/
function (partType) {
return this.isRange ? this.placeholder[this.datePickerService.getActiveIndex((/** @type {?} */ (partType)))] : ((/** @type {?} */ (this.placeholder)));
};
/**
* @param {?} value
* @return {?}
*/
NzPickerComponent.prototype.isEmptyValue = /**
* @param {?} value
* @return {?}
*/
function (value) {
if (value === null) {
return true;
}
else if (this.isRange) {
return !value || !Array.isArray(value) || value.every((/**
* @param {?} val
* @return {?}
*/
function (val) { return !val; }));
}
else {
return !value;
}
};
// Whether open state is permanently controlled by user himself
// Whether open state is permanently controlled by user himself
/**
* @return {?}
*/
NzPickerComponent.prototype.isOpenHandledByUser =
// Whether open state is permanently controlled by user himself
/**
* @return {?}
*/
function () {
return this.open !== undefined;
};
/**
* @return {?}
*/
NzPickerComponent.prototype.animationStart = /**
* @return {?}
*/
function () {
if (this.realOpenState) {
this.animationOpenState = true;
}
};
/**
* @return {?}
*/
NzPickerComponent.prototype.animationDone = /**
* @return {?}
*/
function () {
if (!this.realOpenState) {
this.animationOpenState = false;
this.changeDetector.markForCheck();
}
};
NzPickerComponent.decorators = [
{ type: Component, args: [{
encapsulation: ViewEncapsulation.None,
selector: '[nz-picker]',
exportAs: 'nzPicker',
template: "\n <!-- Content of single picker -->\n <div *ngIf=\"!isRange\" class=\"{{ prefixCls }}-input\">\n <input\n #pickerInput\n [class.ant-input-disabled]=\"disabled\"\n [disabled]=\"disabled\"\n [(ngModel)]=\"inputValue\"\n placeholder=\"{{ getPlaceholder() }}\"\n [size]=\"inputSize\"\n (click)=\"onClickInputBox()\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (input)=\"onInputKeyup($event)\"\n (keyup.enter)=\"onInputKeyup($event, true)\"\n />\n <ng-container *ngTemplateOutlet=\"tplRightRest\"></ng-container>\n </div>\n\n <!-- Content of range picker -->\n <ng-container *ngIf=\"isRange\">\n <div class=\"{{ prefixCls }}-input\">\n <ng-container *ngTemplateOutlet=\"tplRangeInput; context: { partType: 'left' }\"></ng-container>\n </div>\n <div #separatorElement class=\"{{ prefixCls }}-range-separator\">\n <span class=\"{{ prefixCls }}-separator\">\n <ng-container *ngIf=\"separator; else defaultSeparator\">{{ separator }}</ng-container>\n </span>\n <ng-template #defaultSeparator>\n <i nz-icon nzType=\"swap-right\" nzTheme=\"outline\"></i>\n </ng-template>\n </div>\n <div class=\"{{ prefixCls }}-input\">\n <ng-container *ngTemplateOutlet=\"tplRangeInput; context: { partType: 'right' }\"></ng-container>\n </div>\n <ng-container *ngTemplateOutlet=\"tplRightRest\"></ng-container>\n </ng-container>\n <!-- Input for Range ONLY -->\n <ng-template #tplRangeInput let-partType=\"partType\">\n <input\n #rangePickerInput\n [disabled]=\"disabled\"\n [size]=\"inputSize\"\n (click)=\"onClickInputBox(partType)\"\n (blur)=\"onBlur()\"\n (input)=\"onInputKeyup($event, false)\"\n (focus)=\"onFocus(partType)\"\n (keyup.enter)=\"onInputKeyup($event, true)\"\n [(ngModel)]=\"inputValue[datePickerService?.getActiveIndex(partType)]\"\n placeholder=\"{{ getPlaceholder(partType) }}\"\n />\n </ng-template>\n\n <!-- Right operator icons -->\n <ng-template #tplRightRest>\n <div class=\"{{ prefixCls }}-active-bar\" [style]=\"activeBarStyle\"></div>\n <span *ngIf=\"showClear()\" class=\"{{ prefixCls }}-clear\" (click)=\"onClickClear($event)\">\n <i nz-icon nzType=\"close-circle\" nzTheme=\"fill\"></i>\n </span>\n <span class=\"{{ prefixCls }}-suffix\">\n <i nz-icon nzType=\"calendar\"></i>\n </span>\n </ng-template>\n\n <!-- Overlay -->\n <ng-template\n cdkConnectedOverlay\n nzConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"realOpenState\"\n [cdkConnectedOverlayHasBackdrop]=\"!isOpenHandledByUser()\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n (positionChange)=\"onPositionChange($event)\"\n (backdropClick)=\"onClickBackdrop()\"\n (detach)=\"onOverlayDetach()\"\n (overlayKeydown)=\"onOverlayKeydown($event)\"\n >\n <div\n [nzNoAnimation]=\"noAnimation\"\n [@slideMotion]=\"currentPositionY\"\n (@slideMotion.done)=\"animationDone()\"\n style=\"position: relative;\"\n [style.left]=\"currentPositionX === 'start' ? '-12px' : '12px'\"\n [style.top]=\"currentPositionY === 'top' ? '-8px' : '8px'\"\n >\n <div\n class=\"{{ prefixCls }}-dropdown {{ dropdownClassName }}\"\n [class.ant-picker-dropdown-placement-bottomLeft]=\"currentPositionY === 'bottom' && currentPositionX === 'start'\"\n [class.ant-picker-dropdown-placement-topLeft]=\"currentPositionY === 'top' && currentPositionX === 'start'\"\n [class.ant-picker-dropdown-placement-bottomRight]=\"currentPositionY === 'bottom' && currentPositionX === 'end'\"\n [class.ant-picker-dropdown-placement-topRight]=\"currentPositionY === 'top' && currentPositionX === 'end'\"\n [class.ant-picker-dropdown-range]=\"isRange\"\n [ngStyle]=\"popupStyle\"\n >\n <!-- Compatible for overlay that not support offset dynamically and immediately -->\n <ng-content></ng-content>\n </div>\n </div>\n </ng-template>\n ",
animations: [slideMotion],
changeDetection: ChangeDetectionStrategy.OnPush
}] }
];
/** @nocollapse */
NzPickerComponent.ctorParameters = function () { return [
{ type: ElementRef },
{ type: DateHelperService },
{ type: ChangeDetectorRef },
{ type: DatePickerService },
{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
]; };
NzPickerComponent.propDecorators = {
noAnimation: [{ type: Input }],
isRange: [{ type: Input }],
open: [{ type: Input }],
disabled: [{ type: Input }],
placeholder: [{ type: Input }],
allowClear: [{ type: Input }],
autoFocus: [{ type: Input }],
format: [{ type: Input }],
separator: [{ type: Input }],
popupStyle: [{ type: Input }],
dropdownClassName: [{ type: Input }],
focusChange: [{ type: Output }],
valueChange: [{ type: Output }],
openChange: [{ type: Output }],
cdkConnectedOverlay: [{ type: ViewChild, args: [CdkConnectedOverlay, { static: false },] }],
separatorElement: [{ type: ViewChild, args: ['separatorElement', { static: false },] }],
pickerInput: [{ type: ViewChild, args: ['pickerInput', { static: false },] }],
rangePickerInputs: [{ type: ViewChildren, args: ['rangePickerInput',] }],
panel: [{ type: ContentChild, args: [DateRangePopupComponent,] }]
};
return NzPickerComponent;
}());
export { NzPickerComponent };
if (false) {
/** @type {?} */
NzPickerComponent.prototype.noAnimation;
/** @type {?} */
NzPickerComponent.prototype.isRange;
/** @type {?} */
NzPickerComponent.prototype.open;
/** @type {?} */
NzPickerComponent.prototype.disabled;
/** @type {?} */
NzPickerComponent.prototype.placeholder;
/** @type {?} */
NzPickerComponent.prototype.allowClear;
/** @type {?} */
NzPickerComponent.prototype.autoFocus;
/** @type {?} */
NzPickerComponent.prototype.format;
/** @type {?} */
NzPickerComponent.prototype.separator;
/** @type {?} */
NzPickerComponent.prototype.popupStyle;
/** @type {?} */
NzPickerComponent.prototype.dropdownClassName;
/** @type {?} */
NzPickerComponent.prototype.focusChange;
/** @type {?} */
NzPickerComponent.prototype.valueChange;
/** @type {?} */
NzPickerComponent.prototype.openChange;
/** @type {?} */
NzPickerComponent.prototype.cdkConnectedOverlay;
/** @type {?} */
NzPickerComponent.prototype.separatorElement;
/** @type {?} */
NzPickerComponent.prototype.pickerInput;
/** @type {?} */
NzPickerComponent.prototype.rangePickerInputs;
/** @type {?} */
NzPickerComponent.prototype.panel;
/** @type {?} */
NzPickerComponent.prototype.origin;
/** @type {?} */
NzPickerComponent.prototype.document;
/** @type {?} */
NzPickerComponent.prototype.inputSize;
/** @type {?} */
NzPickerComponent.prototype.inputWidth;
/** @type {?} */
NzPickerComponent.prototype.arrowLeft;
/** @type {?} */
NzPickerComponent.prototype.destroy$;
/** @type {?} */
NzPickerComponent.prototype.prefixCls;
/** @type {?} */
NzPickerComponent.prototype.inputValue;
/** @type {?} */
NzPickerComponent.prototype.activeBarStyle;
/** @type {?} */
NzPickerComponent.prototype.animationOpenState;
/** @type {?} */
NzPickerComponent.prototype.overlayOpen;
/** @type {?} */
NzPickerComponent.prototype.overlayPositions;
/** @type {?} */
NzPickerComponent.prototype.currentPositionX;
/** @type {?} */
NzPickerComponent.prototype.currentPositionY;
/**
* @type {?}
* @private
*/
NzPickerComponent.prototype.elementRef;
/**
* @type {?}
* @private
*/
NzPickerComponent.prototype.dateHelper;
/**
* @type {?}
* @private
*/
NzPickerComponent.prototype.changeDetector;
/** @type {?} */
NzPickerComponent.prototype.datePickerService;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGlja2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25nLXpvcnJvLWFudGQvZGF0ZS1waWNrZXIvIiwic291cmNlcyI6WyJwaWNrZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFRQSxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLGdCQUFnQixFQUtqQixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMzQyxPQUFPLEVBRUwsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsWUFBWSxFQUNaLFVBQVUsRUFDVixZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFJTCxNQUFNLEVBQ04sU0FBUyxFQUVULFNBQVMsRUFDVCxZQUFZLEVBQ1osaUJBQWlCLEVBQ2xCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUUzRCxPQUFPLEVBQUUsU0FBUyxFQUFtQixNQUFNLHlCQUF5QixDQUFDO0FBRXJFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzFDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUV2RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBRXRDO0lBbUxFLDJCQUNVLFVBQXNCLEVBQ3RCLFVBQTZCLEVBQzdCLGNBQWlDLEVBQ2xDLGlCQUFvQyxFQUN6QixHQUFjO1FBSnhCLGVBQVUsR0FBVixVQUFVLENBQVk7UUFDdEIsZUFBVSxHQUFW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Qjs7SUFDbEIscUNBQXlCOztJQUN6QixzQ0FBeUI7O0lBRXpCLHVDQUFzQjs7SUFDdEIsMkNBQWtEOztJQUNsRCwrQ0FBMkI7O0lBQzNCLHdDQUE2Qjs7SUFDN0IsNkNBMkI4Qjs7SUFDOUIsNkNBQW9EOztJQUNwRCw2Q0FBbUQ7Ozs7O0lBUWpELHVDQUE4Qjs7Ozs7SUFDOUIsdUNBQXFDOzs7OztJQUNyQywyQ0FBeUM7O0lBQ3pDLDhDQUEyQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBBbGliYWJhLmNvbSBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vZ2l0aHViLmNvbS9ORy1aT1JSTy9uZy16b3Jyby1hbnRkL2Jsb2IvbWFzdGVyL0xJQ0VOU0VcbiAqL1xuXG5pbXBvcnQge1xuICBDZGtDb25uZWN0ZWRPdmVybGF5LFxuICBDZGtPdmVybGF5T3JpZ2luLFxuICBDb25uZWN0ZWRPdmVybGF5UG9zaXRpb25DaGFuZ2UsXG4gIENvbm5lY3Rpb25Qb3NpdGlvblBhaXIsXG4gIEhvcml6b250YWxDb25uZWN0aW9uUG9zLFxuICBWZXJ0aWNhbENvbm5lY3Rpb25Qb3Ncbn0gZnJvbSAnQGFuZ3VsYXIvY2RrL292ZXJsYXknO1xuaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIENvbnRlbnRDaGlsZCxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBJbmplY3QsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIFF1ZXJ5TGlzdCxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVmlld0NoaWxkLFxuICBWaWV3Q2hpbGRyZW4sXG4gIFZpZXdFbmNhcHN1bGF0aW9uXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgc2xpZGVNb3Rpb24gfSBmcm9tICduZy16b3Jyby1hbnRkL2NvcmUvYW5pbWF0aW9uJztcblxuaW1wb3J0IHsgQ2FuZHlEYXRlLCBDb21wYXRpYmxlVmFsdWUgfSBmcm9tICduZy16b3Jyby1hbnRkL2NvcmUvdGltZSc7XG5pbXBvcnQgeyBOelNhZmVBbnkgfSBmcm9tICduZy16b3Jyby1hbnRkL2NvcmUvdHlwZXMnO1xuaW1wb3J0IHsgRGF0ZUhlbHBlclNlcnZpY2UgfSBmcm9tICduZy16b3Jyby1hbnRkL2kxOG4nO1xuaW1wb3J0IHsgZnJvbUV2ZW50LCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBEYXRlUGlja2VyU2VydmljZSB9IGZyb20gJy4vZGF0ZS1waWNrZXIuc2VydmljZSc7XG5pbXBvcnQgeyBEYXRlUmFuZ2VQb3B1cENvbXBvbmVudCB9IGZyb20gJy4vZGF0ZS1yYW5nZS1wb3B1cC5jb21wb25lbnQnO1xuaW1wb3J0IHsgUmFuZ2VQYXJ0VHlwZSB9IGZyb20gJy4vc3RhbmRhcmQtdHlwZXMnO1xuaW1wb3J0IHsgUFJFRklYX0NMQVNTIH0gZnJvbSAnLi91dGlsJztcblxuQENvbXBvbmVudCh7XG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIHNlbGVjdG9yOiAnW256LXBpY2tlcl0nLFxuICBleHBvcnRBczogJ256UGlja2VyJyxcbiAgdGVtcGxhdGU6IGBcbiAgICA8IS0tIENvbnRlbnQgb2Ygc2luZ2xlIHBpY2tlciAtLT5cbiAgICA8ZGl2ICpuZ0lmPVwiIWlzUmFuZ2VcIiBjbGFzcz1cInt7IHByZWZpeENscyB9fS1pbnB1dFwiPlxuICAgICAgPGlucHV0XG4gICAgICAgICNwaWNrZXJJbnB1dFxuICAgICAgICBbY2xhc3MuYW50LWlucHV0LWRpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgICAgWyhuZ01vZGVsKV09XCJpbnB1dFZhbHVlXCJcbiAgICAgICAgcGxhY2Vob2xkZXI9XCJ7eyBnZXRQbGFjZWhvbGRlcigpIH19XCJcbiAgICAgICAgW3NpemVdPVwiaW5wdXRTaXplXCJcbiAgICAgICAgKGNsaWNrKT1cIm9uQ2xpY2tJbnB1dEJveCgpXCJcbiAgICAgICAgKGZvY3VzKT1cIm9uRm9jdXMoKVwiXG4gICAgICAgIChibHVyKT1cIm9uQmx1cigpXCJcbiAgICAgICAgKGlucHV0KT1cIm9uSW5wdXRLZXl1cCgkZXZlbnQpXCJcbiAgICAgICAgKGtleXVwLmVudGVyKT1cIm9uSW5wdXRLZXl1cCgkZXZlbnQsIHRydWUpXCJcbiAgICAgIC8+XG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidHBsUmlnaHRSZXN0XCI+PC9uZy1jb250YWluZXI+XG4gICAgPC9kaXY+XG5cbiAgICA8IS0tIENvbnRlbnQgb2YgcmFuZ2UgcGlja2VyIC0tPlxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJpc1JhbmdlXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwie3sgcHJlZml4Q2xzIH19LWlucHV0XCI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0cGxSYW5nZUlucHV0OyBjb250ZXh0OiB7IHBhcnRUeXBlOiAnbGVmdCcgfVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2ICNzZXBhcmF0b3JFbGVtZW50IGNsYXNzPVwie3sgcHJlZml4Q2xzIH19LXJhbmdlLXNlcGFyYXRvclwiPlxuICAgICAgICA8c3BhbiBjbGFzcz1cInt7IHByZWZpeENscyB9fS1zZXBhcmF0b3JcIj5cbiAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwic2VwYXJhdG9yOyBlbHNlIGRlZmF1bHRTZXBhcmF0b3JcIj57eyBzZXBhcmF0b3IgfX08L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPC9zcGFuPlxuICAgICAgICA8bmctdGVtcGxhdGUgI2RlZmF1bHRTZXBhcmF0b3I+XG4gICAgICAgICAgPGkgbnotaWNvbiBuelR5cGU9XCJzd2FwLXJpZ2h0XCIgbnpUaGVtZT1cIm91dGxpbmVcIj48L2k+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJ7eyBwcmVmaXhDbHMgfX0taW5wdXRcIj5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInRwbFJhbmdlSW5wdXQ7IGNvbnRleHQ6IHsgcGFydFR5cGU6ICdyaWdodCcgfVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgPC9kaXY+XG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidHBsUmlnaHRSZXN0XCI+PC9uZy1jb250YWluZXI+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPCEtLSBJbnB1dCBmb3IgUmFuZ2UgT05MWSAtLT5cbiAgICA8bmctdGVtcGxhdGUgI3RwbFJhbmdlSW5wdXQgbGV0LXBhcnRUeXBlPVwicGFydFR5cGVcIj5cbiAgICAgIDxpbnB1dFxuICAgICAgICAjcmFuZ2VQaWNrZXJJbnB1dFxuICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICBbc2l6ZV09XCJpbnB1dFNpemVcIlxuICAgICAgICAoY2xpY2spPVwib25DbGlja0lucHV0Qm94KHBhcnRUeXBlKVwiXG4gICAgICAgIChibHVyKT1cIm9uQmx1cigpXCJcbiAgICAgICAgKGlucHV0KT1cIm9uSW5wdXRLZXl1cCgkZXZlbnQsIGZhbHNlKVwiXG4gICAgICAgIChmb2N1cyk9XCJvbkZvY3VzKHBhcnRUeXBlKVwiXG4gICAgICAgIChrZXl1cC5lbnRlcik9XCJvbklucHV0S2V5dXAoJGV2ZW50LCB0cnVlKVwiXG4gICAgICAgIFsobmdNb2RlbCldPVwiaW5wdXRWYWx1ZVtkYXRlUGlja2VyU2VydmljZT8uZ2V0QWN0aXZlSW5kZXgocGFydFR5cGUpXVwiXG4gICAgICAgIHBsYWNlaG9sZGVyPVwie3sgZ2V0UGxhY2Vob2xkZXIocGFydFR5cGUpIH19XCJcbiAgICAgIC8+XG4gICAgPC9uZy10ZW1wbGF0ZT5cblxuICAgIDwhLS0gUmlnaHQgb3BlcmF0b3IgaWNvbnMgLS0+XG4gICAgPG5nLXRlbXBsYXRlICN0cGxSaWdodFJlc3Q+XG4gICAgICA8ZGl2IGNsYXNzPVwie3sgcHJlZml4Q2xzIH19LWFjdGl2ZS1iYXJcIiBbc3R5bGVdPVwiYWN0aXZlQmFyU3R5bGVcIj48L2Rpdj5cbiAgICAgIDxzcGFuICpuZ0lmPVwic2hvd0NsZWFyKClcIiBjbGFzcz1cInt7IHByZWZpeENscyB9fS1jbGVhclwiIChjbGljayk9XCJvbkNsaWNrQ2xlYXIoJGV2ZW50KVwiPlxuICAgICAgICA8aSBuei1pY29uIG56VHlwZT1cImNsb3NlLWNpcmNsZVwiIG56VGhlbWU9XCJmaWxsXCI+PC9pPlxuICAgICAgPC9zcGFuPlxuICAgICAgPHNwYW4gY2xhc3M9XCJ7eyBwcmVmaXhDbHMgfX0tc3VmZml4XCI+XG4gICAgICAgIDxpIG56LWljb24gbnpUeXBlPVwiY2FsZW5kYXJcIj48L2k+XG4gICAgICA8L3NwYW4+XG4gICAgPC9uZy10ZW1wbGF0ZT5cblxuICAgIDwhLS0gT3ZlcmxheSAtLT5cbiAgICA8bmctdGVtcGxhdGVcbiAgICAgIGNka0Nvbm5lY3RlZE92ZXJsYXlcbiAgICAgIG56Q29ubmVjdGVkT3ZlcmxheVxuICAgICAgW2Nka0Nvbm5lY3RlZE92ZXJsYXlPcmlnaW5dPVwib3JpZ2luXCJcbiAgICAgIFtjZGtDb25uZWN0ZWRPdmVybGF5T3Blbl09XCJyZWFsT3BlblN0YXRlXCJcbiAgICAgIFtjZGtDb25uZWN0ZWRPdmVybGF5SGFzQmFja2Ryb3BdPVwiIWlzT3BlbkhhbmRsZWRCeVVzZXIoKVwiXG4gICAgICBbY2RrQ29ubmVjdGVkT3ZlcmxheVBvc2l0aW9uc109XCJvdmVybGF5UG9zaXRpb25zXCJcbiAgICAgIChwb3NpdGlvbkNoYW5nZSk9XCJvblBvc2l0aW9uQ2hhbmdlKCRldmVudClcIlxuICAgICAgKGJhY2tkcm9wQ2xpY2spPVwib25DbGlja0JhY2tkcm9wKClcIlxuICAgICAgKGRldGFjaCk9XCJvbk92ZXJsYXlEZXRhY2goKVwiXG4gICAgICAob3ZlcmxheUtleWRvd24pPVwib25PdmVybGF5S2V5ZG93bigkZXZlbnQpXCJcbiAgICA+XG4gICAgICA8ZGl2XG4gICAgICAgIFtuek5vQW5pbWF0aW9uXT1cIm5vQW5pbWF0aW9uXCJcbiAgICAgICAgW0BzbGlkZU1vdGlvbl09XCJjdXJyZW50UG9zaXRpb25ZXCJcbiAgICAgICAgKEBzbGlkZU1vdGlvbi5kb25lKT1cImFuaW1hdGlvbkRvbmUoKVwiXG4gICAgICAgIHN0eWxlPVwicG9zaXRpb246IHJlbGF0aXZlO1wiXG4gICAgICAgIFtzdHlsZS5sZWZ0XT1cImN1cnJlbnRQb3NpdGlvblggPT09ICdzdGFydCcgPyAnLTEycHgnIDogJzEycHgnXCJcbiAgICAgICAgW3N0eWxlLnRvcF09XCJjdXJyZW50UG9zaXRpb25ZID09PSAndG9wJyA/ICctOHB4JyA6ICc4cHgnXCJcbiAgICAgID5cbiAgICAgICAgPGRpdlxuICAgICAgICAgIGNsYXNzPVwie3sgcHJlZml4Q2xzIH19LWRyb3Bkb3duIHt7IGRyb3Bkb3duQ2xhc3NOYW1lIH19XCJcbiAgICAgICAgICBbY2xhc3MuYW50LXBpY2tlci1kcm9wZG93bi1wbGFjZW1lbnQtYm90dG9tTGVmdF09XCJjdXJyZW50UG9zaXRpb25ZID09PSAnYm90dG9tJyAmJiBjdXJyZW50UG9zaXRpb25YID09PSAnc3RhcnQnXCJcbiAgICAgICAgICBbY2xhc3MuYW50LXBpY2tlci1kcm9wZG93bi1wbGFjZW1lbnQtdG9wTGVmdF09XCJjdXJyZW50UG9zaXRpb25ZID09PSAndG9wJyAmJiBjdXJyZW50UG9zaXRpb25YID09PSAnc3RhcnQnXCJcbiAgICAgICAgICBbY2xhc3MuYW50LXBpY2tlci1kcm9wZG93bi1wbGFjZW1lbnQtYm90dG9tUmlnaHRdPVwiY3VycmVudFBvc2l0aW9uWSA9PT0gJ2JvdHRvbScgJiYgY3VycmVudFBvc2l0aW9uWCA9PT0gJ2VuZCdcIlxuICAgICAgICAgIFtjbGFzcy5hbnQtcGlja2VyLWRyb3Bkb3duLXBsYWNlbWVudC10b3BSaWdodF09XCJjdXJyZW50UG9zaXRpb25ZID09PSAndG9wJyAmJiBjdXJyZW50UG9zaXRpb25YID09PSAnZW5kJ1wiXG4gICAgICAgICAgW2NsYXNzLmFudC1waWNrZXItZHJvcGRvd24tcmFuZ2VdPVwiaXNSYW5nZVwiXG4gICAgICAgICAgW25nU3R5bGVdPVwicG9wdXBTdHlsZVwiXG4gICAgICAgID5cbiAgICAgICAgICA8IS0tIENvbXBhdGlibGUgZm9yIG92ZXJsYXkgdGhhdCBub3Qgc3VwcG9ydCBvZmZzZXQgZHluYW1pY2FsbHkgYW5kIGltbWVkaWF0ZWx5IC0tPlxuICAgICAgICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L25nLXRlbXBsYXRlPlxuICBgLFxuICBhbmltYXRpb25zOiBbc2xpZGVNb3Rpb25dLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaFxufSlcbmV4cG9ydCBjbGFzcyBOelBpY2tlckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuICBASW5wdXQoKSBub0FuaW1hdGlvbjogYm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKSBpc1JhbmdlOiBib29sZWFuID0gZmFsc2U7XG4gIEBJbnB1dCgpIG9wZW46IGJvb2xlYW4gfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gIEBJbnB1dCgpIGRpc2FibGVkOiBib29sZWFuO1xuICBASW5wdXQoKSBwbGFjZWhvbGRlcjogc3RyaW5nIHwgc3RyaW5nW107XG4gIEBJbnB1dCgpIGFsbG93Q2xlYXI6IGJvb2xlYW47XG4gIEBJbnB1dCgpIGF1dG9Gb2N1czogYm9vbGVhbjtcbiAgQElucHV0KCkgZm9ybWF0OiBzdHJpbmc7XG4gIEBJbnB1dCgpIHNlcGFyYXRvcjogc3RyaW5nO1xuICBASW5wdXQoKSBwb3B1cFN0eWxlOiBvYmplY3Q7XG4gIEBJbnB1dCgpIGRyb3Bkb3duQ2xhc3NOYW1lOiBzdHJpbmc7XG5cbiAgQE91dHB1dCgpIHJlYWRvbmx5IGZvY3VzQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xuICBAT3V0cHV0KCkgcmVhZG9ubHkgdmFsdWVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPENhbmR5RGF0ZSB8IENhbmR5RGF0ZVtdIHwgbnVsbD4oKTtcbiAgQE91dHB1dCgpIHJlYWRvbmx5IG9wZW5DaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7IC8vIEVtaXR0ZWQgd2hlbiBvdmVybGF5J3Mgb3BlbiBzdGF0ZSBjaGFuZ2VcblxuICBAVmlld0NoaWxkKENka0Nvbm5lY3RlZE92ZXJsYXksIHsgc3RhdGljOiBmYWxzZSB9KSBjZGtDb25uZWN0ZWRPdmVybGF5OiBDZGtDb25uZWN0ZWRPdmVybGF5O1xuICBAVmlld0NoaWxkKCdzZXBhcmF0b3JFbGVtZW50JywgeyBzdGF0aWM6IGZhbHNlIH0pIHNlcGFyYXRvckVsZW1lbnQ6IEVsZW1lbnRSZWY7XG4gIEBWaWV3Q2hpbGQoJ3BpY2tlcklucHV0JywgeyBzdGF0aWM6IGZhbHNlIH0pIHBpY2tlcklucHV0OiBFbGVtZW50UmVmPEhUTUxJbnB1dEVsZW1lbnQ+O1xuICBAVmlld0NoaWxkcmVuKCdyYW5nZVBpY2tlcklucHV0JykgcmFuZ2VQaWNrZXJJbnB1dHM6IFF1ZXJ5TGlzdDxFbGVtZW50UmVmPEhUTUxJbnB1dEVsZW1lbnQ+PjtcblxuICBAQ29udGVudENoaWxkKERhdGVSYW5nZVBvcHVwQ29tcG9uZW50KSBwYW5lbDogRGF0ZVJhbmdlUG9wdXBDb21wb25lbnQ7XG5cbiAgb3JpZ2luOiBDZGtPdmVybGF5T3JpZ2luO1xuICBkb2N1bWVudDogRG9jdW1lbnQ7XG4gIGlucHV0U2l6ZTogbnVtYmVyO1xuICBpbnB1dFdpZHRoOiBudW1iZXI7XG4gIGFycm93TGVmdDogbnVtYmVyO1xuICBkZXN0cm95JCA9IG5ldyBTdWJqZWN0KCk7XG4gIHByZWZpeENscyA9IFBSRUZJWF9DTEFTUztcbiAgLy8gSW5kZXggc2lnbmF0dXJlIGluIHR5cGUgJ3N0cmluZyB8IHN0cmluZ1tdJyBvbmx5IHBlcm1pdHMgcmVhZGluZ1xuICBpbnB1dFZhbHVlOiBOelNhZmVBbnk7XG4gIGFjdGl2ZUJhclN0eWxlOiBvYmplY3QgPSB7IHBvc2l0aW9uOiAnYWJzb2x1dGUnIH07XG4gIGFuaW1hdGlvbk9wZW5TdGF0ZSA9IGZhbHNlO1xuICBvdmVybGF5T3BlbjogYm9vbGVhbiA9IGZhbHNlOyAvLyBBdmFpbGFibGUgd2hlbiBcIm9wZW5cIj11bmRlZmluZWRcbiAgb3ZlcmxheVBvc2l0aW9uczogQ29ubmVjdGlvblBvc2l0aW9uUGFpcltdID0gW1xuICAgIHtcbiAgICAgIC8vIG9mZnNldFg6IC0xMCwgLy8gVE9ETzogV2hhdCBhIHBpdHksIGNkay9vdmVybGF5IGN1cnJlbnQgbm90IHN1cHBvcnQgb2Zmc2V0IGNvbmZpZ3MgZXZlbiB0aG91Z2ggaXQgYWxyZWFkeSBwcm92aWRlIHRoZXNlIHByb3BlcnRpZXNcbiAgICAgIC8vIG9mZnNldFk6IC0xMCxcbiAgICAgIG9yaWdpblg6ICdzdGFydCcsXG4gICAgICBvcmlnaW5ZOiAnYm90dG9tJyxcbiAgICAgIG92ZXJsYXlYOiAnc3RhcnQnLFxuICAgICAgb3ZlcmxheVk6ICd0b3AnXG4gICAgfSxcbiAgICB7XG4gICAgICBvcmlnaW5YOiAnc3RhcnQnLFxuICAgICAgb3JpZ2luWTogJ3RvcCcsXG4gICAgICBvdmVybGF5WDogJ3N0YXJ0JyxcbiAgICAgIG92ZXJsYXlZOiAnYm90dG9tJ1xuICAgIH0sXG4gICAge1xuICAgICAgb3JpZ2luWDogJ2VuZCcsXG4gICAgICBvcmlnaW5ZOiAnYm90dG9tJyxcbiAgICAgIG92ZXJsYXlYOiAnZW5kJyxcbiAgICAgIG92ZXJsYXlZOiAndG9wJ1xuICAgIH0sXG4gICAge1xuICAgICAgb3JpZ2luWDogJ2VuZCcsXG4gICAgICBvcmlnaW5ZOiAndG9wJyxcbiAgICAgIG92ZXJsYXlYOiAnZW5kJyxcbiAgICAgIG92ZXJsYXlZOiAnYm90dG9tJ1xuICAgIH1cbiAgXSBhcyBDb25uZWN0aW9uUG9zaXRpb25QYWlyW107XG4gIGN1cnJlbnRQb3NpdGlvblg6IEhvcml6b250YWxDb25uZWN0aW9uUG9zID0gJ3N0YXJ0JztcbiAgY3VycmVudFBvc2l0aW9uWTogVmVydGljYWxDb25uZWN0aW9uUG9zID0gJ2JvdHRvbSc7XG5cbiAgZ2V0IHJlYWxPcGVuU3RhdGUoKTogYm9vbGVhbiB7XG4gICAgLy8gVGhlIHZhbHVlIHRoYXQgcmVhbGx5IGRlY2lkZSB0aGUgb3BlbiBzdGF0ZSBvZiBvdmVybGF5XG4gICAgcmV0dXJuIHRoaXMuaXNPcGVuSGFuZGxlZEJ5VXNlcigpID8gISF0aGlzLm9wZW4gOiB0aGlzLm92ZXJsYXlPcGVuO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBlbGVtZW50UmVmOiBFbGVtZW50UmVmLFxuICAgIHByaXZhdGUgZGF0ZUhlbHBlcjogRGF0ZUhlbHBlclNlcnZpY2UsXG4gICAgcHJpdmF0ZSBjaGFuZ2VEZXRlY3RvcjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgcHVibGljIGRhdGVQaWNrZXJTZXJ2aWNlOiBEYXRlUGlja2VyU2VydmljZSxcbiAgICBASW5qZWN0KERPQ1VNRU5UKSBkb2M6IE56U2FmZUFueVxuICApIHtcbiAgICB0aGlzLmRvY3VtZW50ID0gZG9jO1xuICAgIHRoaXMub3JpZ2luID0gbmV3IENka092ZXJsYXlPcmlnaW4odGhpcy5lbGVtZW50UmVmKTtcbiAgICB0aGlzLnVwZGF0ZUlucHV0VmFsdWUoKTtcbiAgfVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuaW5wdXRTaXplID0gTWF0aC5tYXgoMTAsIHRoaXMuZm9ybWF0Lmxlbmd0aCkgKyAyO1xuXG4gICAgdGhpcy5kYXRlUGlja2VyU2VydmljZS52YWx1ZUNoYW5nZSQucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICB0aGlzLnVwZGF0ZUlucHV0VmFsdWUoKTtcbiAgICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3IubWFya0ZvckNoZWNrKCk7XG4gICAgfSk7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuYXV0b0ZvY3VzKSB7XG4gICAgICB0aGlzLmZvY3VzKCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaXNSYW5nZSkge1xuICAgICAgdGhpcy5yZXNldElucHV0V2lkdGhBbmRBcnJvd0xlZnQoKTtcbiAgICAgIGZyb21FdmVudCh3aW5kb3csICdyZXNpemUnKVxuICAgICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXG4gICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgIHRoaXMucmVzZXRJbnB1dFdpZHRoQW5kQXJyb3dMZWZ0KCk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICB0aGlzLmRhdGVQaWNrZXJTZXJ2aWNlLmlucHV0UGFydENoYW5nZSQucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpLnN1YnNjcmliZShwYXJ0VHlwZSA9PiB7XG4gICAgICBpZiAocGFydFR5cGUpIHtcbiAgICAgICAgdGhpcy5kYXRlUGlja2VyU2VydmljZS5hY3RpdmVJbnB1dCA9IHBhcnRUeXBlO1xuICAgICAgfVxuICAgICAgdGhpcy5kYXRlUGlja2VyU2VydmljZS5hcnJvd1Bvc2l0aW9uU3R5bGUgPSB7XG4gICAgICAgIGxlZnQ6IHRoaXMuZGF0ZVBpY2tlclNlcnZpY2UuYWN0aXZlSW5wdXQgPT09ICdsZWZ0JyA/ICcwcHgnIDogYCR7dGhpcy5hcnJvd0xlZnR9cHhgXG4gICAgICB9O1xuICAgICAgdGhpcy5hY3RpdmVCYXJTdHlsZSA9IHtcbiAgICAgICAgLi4udGhpcy5hY3RpdmVCYXJTdHlsZSxcbiAgICAgICAgLi4udGhpcy5kYXRlUGlja2VyU2VydmljZS5hcnJvd1Bvc2l0aW9uU3R5bGUsXG4gICAgICAgIHdpZHRoOiBgJHt0aGlzLmlucHV0V2lkdGh9cHhgXG4gICAgICB9O1xuICAgICAgaWYgKHRoaXMuZG9jdW1lbnQuYWN0aXZlRWxlbWVudCAhPT0gdGhpcy5nZXRJbnB1dCh0aGlzLmRhdGVQaWNrZXJTZXJ2aWNlLmFjdGl2ZUlucHV0KSkge1xuICAgICAgICB0aGlzLmZvY3VzKCk7XG4gICAgICB9XG4gICAgICB0aGlzLnBhbmVsPy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgICB0aGlzLmNoYW5nZURldGVjdG9yLm1hcmtGb3JDaGVjaygpO1xuICAgIH0pO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KCk7XG4gICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzLm9wZW4pIHtcbiAgICAgIHRoaXMuYW5pbWF0aW9uU3RhcnQoKTtcbiAgICB9XG4gIH1cblxuICByZXNldElucHV0V2lkdGhBbmRBcnJvd0xlZnQoKTogdm9pZCB7XG4gICAgdGhpcy5pbnB1dFdpZHRoID0gdGhpcy5yYW5nZVBpY2tlcklucHV0cz8uZmlyc3QubmF0aXZlRWxlbWVudC5vZmZzZXRXaWR0aCB8fCAwO1xuICAgIHRoaXMuYXJyb3dMZWZ0ID0gdGhpcy5pbnB1dFdpZHRoICsgdGhpcy5zZXBhcmF0b3JFbGVtZW50Py5uYXRpdmVFbGVtZW50Lm9mZnNldFdpZHRoIHx8IDA7XG4gIH1cblxuICBnZXRJbnB1dChwYXJ0VHlwZT86IFJhbmdlUGFydFR5cGUpOiBIVE1MSW5wdXRFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5pc1JhbmdlXG4gICAgICA/IHBhcnRUeXBlID09PSAnbGVmdCdcbiAgICAgICAgPyB0aGlzLnJhbmdlUGlja2VySW5wdXRzLmZpcnN0Lm5hdGl2ZUVsZW1lbnRcbiAgICAgICAgOiB0aGlzLnJhbmdlUGlja2VySW5wdXRzLmxhc3QubmF0aXZlRWxlbWVudFxuICAgICAgOiB0aGlzLnBpY2tlcklucHV0Lm5hdGl2ZUVsZW1lbnQ7XG4gIH1cblxuICBmb2N1cygpOiB2b2lkIHtcbiAgICB0aGlzLmdldElucHV0KHRoaXMuZGF0ZVBpY2tlclNlcnZpY2UuYWN0aXZlSW5wdXQpLmZvY3VzKCk7IC8vIEZvY3VzIG9uIHRoZSBmaXJzdCBpbnB1dFxuICB9XG5cbiAgb25Gb2N1cyhwYXJ0VHlwZT86IFJhbmdlUGFydFR5cGUpOiB2b2lkIHtcbiAgICBpZiAocGFydFR5cGUpIHtcbiAgICAgIHRoaXMuZGF0ZVBpY2tlclNlcnZpY2UuaW5wdXRQYXJ0Q2hhbmdlJC5uZXh0KHBhcnRUeXBlKTtcbiAgICB9XG4gICAgdGhpcy5mb2N1c0NoYW5nZS5lbWl0KHRydWUpO1xuICB9XG5cbiAgb25CbHVyKCk6IHZvaWQge1xuICAgIHRoaXMuZm9jdXNDaGFuZ2UuZW1pdChmYWxzZSk7XG4gIH1cblxuICAvLyBTaG93IG92ZXJsYXkgY29udGVudFxuICBzaG93T3ZlcmxheSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMucmVhbE9wZW5TdGF0ZSkge1xuICAgICAgdGhpcy5vdmVybGF5T3BlbiA9IHRydWU7XG4gICAgICB0aGlzLmFuaW1hdGlvblN0YXJ0KCk7XG4gICAgICB0aGlzLmZvY3VzKCk7XG4gICAgICB0aGlzLm9wZW5DaGFuZ2UuZW1pdCh0cnVlKTtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5jZGtDb25uZWN0ZWRPdmVybGF5ICYmIHRoaXMuY2RrQ29ubmVjdGVkT3ZlcmxheS5vdmVybGF5UmVmKSB7XG4gICAgICAgICAgdGhpcy5jZGtDb25uZWN0ZWRPdmVybGF5Lm92ZXJsYXlSZWYudXBkYXRlUG9zaXRpb24oKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgaGlkZU92ZXJsYXkoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucmVhbE9wZW5TdGF0ZSkge1xuICAgICAgdGhpcy5vdmVybGF5T3BlbiA9IGZhbHNlO1xuICAgICAgdGhpcy5vcGVuQ2hhbmdlLmVtaXQoZmFsc2UpO1xuICAgICAgdGhpcy5mb2N1cygpO1xuICAgIH1cbiAgfVxuXG4gIHNob3dDbGVhcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gIXRoaXMuZGlzYWJsZWQgJiYgIXRoaXMuaXNFbXB0eVZhbHVlKHRoaXMuZGF0ZVBpY2tlclNlcnZpY2UudmFsdWUpICYmIHRoaXMuYWxsb3dDbGVhcjtcbiAgfVxuXG4gIG9uQ2xpY2tJbnB1dEJveChwYXJ0VHlwZT86IFJhbmdlUGFydFR5cGUpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuZGlzYWJsZWQgJiYgIXRoaXMuaXNPcGVuSGFuZGxlZEJ5VXNlcigpKSB7XG4gICAgICB0aGlzLnNob3dPdmVybGF5KCk7XG4gICAgfVxuICAgIHRoaXMub25Gb2N1cyhwYXJ0VHlwZSk7XG4gIH1cblxuICBvbkNsaWNrQmFja2Ryb3AoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucGFuZWwuaXNBbGxvd2VkKHRoaXMuZGF0ZVBpY2tlclNlcnZpY2UudmFsdWUhLCB0cnVlKSkge1xuICAgICAgdGhpcy51cGRhdGVJbnB1dFZhbHVlKCk7XG4gICAgICB0aGlzLmRhdGVQaWNrZXJTZXJ2aWNlLmVtaXRWYWx1ZSQubmV4dCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmRhdGVQaWNrZXJTZXJ2aWNlLnNldFZhbHVlKHRoaXMuZGF0ZVBpY2tlclNlcnZpY2UuaW5pdGlhbFZhbHVlKTtcbiAgICAgIHRoaXMuaGlkZU92ZXJsYXkoKTtcbiAgICB9XG4gIH1cblxuICBvbk92ZXJsYXlEZXRhY2goKTogdm9pZCB7XG4gICAgdGhpcy5oaWRlT3ZlcmxheSgpO1xuICB9XG5cbiAgb25PdmVybGF5S2V5ZG93bihldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGlmIChldmVudC5rZXkgPT09ICdFc2NhcGUnKSB7XG4gICAgICB0aGlzLmRhdGVQaWNrZXJTZXJ2aWNlLnNldFZhbHVlKHRoaXMuZGF0ZVBpY2tlclNlcnZpY2UuaW5pdGlhbFZhbHVlKTtcbiAgICB9XG4gIH1cblxuICAvLyBOT1RFOiBBIGlzc3VlIGhlcmUsIHRoZSBmaXJzdCB0aW1lIHBvc2l0aW9uIGNoYW5nZSwgdGhlIGFuaW1hdGlvbiB3aWxsIG5vdCBiZSB0cmlnZ2VyZWQuXG4gIC8vIEJlY2F1c2UgdGhlIG92ZXJsYXkncyBcInBvc2l0aW9uQ2hhbmdlXCIgZXZlbnQgaXMgZW1pdHRlZCBhZnRlciB0aGUgY29udGVudCdzIGZ1bGwgc2hvd24gdXAuXG4gIC8vIEFsbCBvdGhlciBjb21wb25lbnRzIGxpa2UgXCJuei1kcm9wZG93blwiIHdoaWNoIGRlcGVuZHMgb24gb3ZlcmxheSBhbHNvIGhhcyB0aGUgc2FtZSBpc3N1ZS5cbiAgLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vTkctWk9SUk8vbmctem9ycm8tYW50ZC9pc3N1ZXMvMTQyOVxuICBvblBvc2l0aW9uQ2hhbmdlKHBvc2l0aW9uOiBDb25uZWN0ZWRPdmVybGF5UG9zaXRpb25DaGFuZ2UpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnRQb3NpdGlvblggPSBwb3NpdGlvbi5jb25uZWN0aW9uUGFpci5vcmlnaW5YO1xuICAgIHRoaXMuY3VycmVudFBvc2l0aW9uWSA9IHBvc2l0aW9uLmNvbm5lY3Rpb25QYWlyLm9yaWdpblk7XG4gICAgdGhpcy5jaGFuZ2VEZXRlY3Rvci5kZXRlY3RDaGFuZ2VzKCk7IC8vIFRha2Ugc2lkZS1lZmZlY3RzIHRvIHBvc2l0aW9uIHN0eWxlc1xuICB9XG5cbiAgb25DbGlja0NsZWFyKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIHRoaXMuZGF0ZVBpY2tlclNlcnZpY2Uuc2V0VmFsdWUodGhpcy5pc1JhbmdlID8gW10gOiBudWxsKTtcbiAgICB0aGlzLmRhdGVQaWNrZXJTZXJ2aWNlLmVtaXRWYWx1ZSQubmV4dCgpO1xuICB9XG5cbiAgdXBkYXRlSW5wdXRWYWx1ZSgpOiB2b2lkIHtcbiAgICBjb25zdCBuZXdWYWx1ZSA9IHRoaXMuZGF0ZVBpY2tlclNlcnZpY2UudmFsdWU7XG4gICAgaWYgKHRoaXMuaXNSYW5nZSkge1xuICAgICAgdGhpcy5pbnB1dFZhbHVlID0gbmV3VmFsdWUgPyAobmV3VmFsdWUgYXMgQ2FuZHlEYXRlW10pLm1hcCh2ID0+IHRoaXMuZm9ybWF0VmFsdWUodikpIDogWycnLCAnJ107XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuaW5wdXRWYWx1ZSA9IHRoaXMuZm9ybWF0VmFsdWUobmV3VmFsdWUgYXMgQ2FuZHlEYXRlKTtcbiAgICB9XG4gIH1cblxuICBmb3JtYXRWYWx1ZSh2YWx1ZTogQ2FuZHlEYXRlKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5kYXRlSGVscGVyLmZvcm1hdCh2YWx1ZSAmJiAodmFsdWUgYXMgQ2FuZHlEYXRlKS5uYXRpdmVEYXRlLCB0aGlzLmZvcm1hdCk7XG4gIH1cblxuICBvbklucHV0S2V5dXAoZXZlbnQ6IEV2ZW50LCBpc0VudGVyOiBib29sZWFuID0gZmFsc2UpOiB2b2lkIHtcbiAgICBpZiAoaXNFbnRlciAmJiAhdGhpcy5yZWFsT3BlblN0YXRlKSB7XG4gICAgICB0aGlzLnNob3dPdmVybGF5KCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGRhdGUgPSB0aGlzLmNoZWNrVmFsaWRJbnB1dERhdGUoKGV2ZW50IGFzIEtleWJvYXJkRXZlbnQpLnRhcmdldCEpO1xuICAgIGlmICh0aGlzLnBhbmVsICYmIGRhdGUpIHtcbiAgICAgIHRoaXMucGFuZWwuY2hhbmdlVmFsdWVGcm9tU2VsZWN0KGRhdGUsIGlzRW50ZXIpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY2hlY2tWYWxpZElucHV0RGF0ZShpbnB1dFRhcmdldDogRXZlbnRUYXJnZXQpOiBDYW5keURhdGUgfCBudWxsIHtcbiAgICBjb25zdCBpbnB1dCA9IChpbnB1dFRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZTtcbiAgICBjb25zdCBkYXRlID0gbmV3IENhbmR5RGF0ZSh0aGlzLmRhdGVIZWxwZXIucGFyc2VEYXRlKGlucHV0LCB0aGlzLmZvcm1hdCkpO1xuXG4gICAgaWYgKCFkYXRlLmlzVmFsaWQoKSB8fCBpbnB1dCAhPT0gdGhpcy5kYXRlSGVscGVyLmZvcm1hdChkYXRlLm5hdGl2ZURhdGUsIHRoaXMuZm9ybWF0KSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRhdGU7XG4gIH1cblxuICBnZXRQbGFjZWhvbGRlcihwYXJ0VHlwZT86IFJhbmdlUGFydFR5cGUpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmlzUmFuZ2UgPyB0aGlzLnBsYWNlaG9sZGVyW3RoaXMuZGF0ZVBpY2tlclNlcnZpY2UuZ2V0QWN0aXZlSW5kZXgocGFydFR5cGUhKV0gOiAodGhpcy5wbGFjZWhvbGRlciBhcyBzdHJpbmcpO1xuICB9XG5cbiAgaXNFbXB0eVZhbHVlKHZhbHVlOiBDb21wYXRpYmxlVmFsdWUpOiBib29sZWFuIHtcbiAgICBpZiAodmFsdWUgPT09IG51bGwpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSBpZiAodGhpcy5pc1JhbmdlKSB7XG4gICAgICByZXR1cm4gIXZhbHVlIHx8ICFBcnJheS5pc0FycmF5KHZhbHVlKSB8fCB2YWx1ZS5ldmVyeSh2YWwgPT4gIXZhbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAhdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgLy8gV2hldGhlciBvcGVuIHN0YXRlIGlzIHBlcm1hbmVudGx5IGNvbnRyb2xsZWQgYnkgdXNlciBoaW1zZWxmXG4gIGlzT3BlbkhhbmRsZWRCeVVzZXIoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMub3BlbiAhPT0gdW5kZWZpbmVkO1xuICB9XG5cbiAgYW5pbWF0aW9uU3RhcnQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucmVhbE9wZW5TdGF0ZSkge1xuICAgICAgdGhpcy5hbmltYXRpb25PcGVuU3RhdGUgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIGFuaW1hdGlvbkRvbmUoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnJlYWxPcGVuU3RhdGUpIHtcbiAgICAgIHRoaXMuYW5pbWF0aW9uT3BlblN0YXRlID0gZmFsc2U7XG4gICAgICB0aGlzLmNoYW5nZURldGVjdG9yLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cbiAgfVxufVxuIl19