UNPKG

primeng

Version:

[![npm version](https://badge.fury.io/js/primeng.svg)](https://badge.fury.io/js/primeng) [![npm downloads](https://img.shields.io/npm/dm/primeng.svg)](https://www.npmjs.com/package/primeng) [![Actions CI](https://github.com/primefaces/primeng/workflows/No

494 lines 56.3 kB
import { CommonModule, DOCUMENT } from '@angular/common'; import { ChangeDetectionStrategy, Component, ContentChildren, Directive, EventEmitter, Inject, Input, NgModule, Output, ViewEncapsulation } from '@angular/core'; import { PrimeTemplate, SharedModule } from 'primeng/api'; import { DomHandler } from 'primeng/dom'; import { SpinnerIcon } from 'primeng/icons/spinner'; import { RippleModule } from 'primeng/ripple'; import { ObjectUtils } from 'primeng/utils'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "primeng/ripple"; const INTERNAL_BUTTON_CLASSES = { button: 'p-button', component: 'p-component', iconOnly: 'p-button-icon-only', disabled: 'p-disabled', loading: 'p-button-loading', labelOnly: 'p-button-loading-label-only' }; /** * Button directive is an extension to button component. * @group Components */ class ButtonDirective { el; document; /** * Position of the icon. * @group Props */ iconPos = 'left'; /** * Uses to pass attributes to the loading icon's DOM element. * @group Props */ loadingIcon; /** * Text of the button. * @group Props */ get label() { return this._label; } set label(val) { this._label = val; if (this.initialized) { this.updateLabel(); this.updateIcon(); this.setStyleClass(); } } /** * Name of the icon. * @group Props */ get icon() { return this._icon; } set icon(val) { this._icon = val; if (this.initialized) { this.updateIcon(); this.setStyleClass(); } } /** * Whether the button is in loading state. * @group Props */ get loading() { return this._loading; } set loading(val) { this._loading = val; if (this.initialized) { this.updateIcon(); this.setStyleClass(); } } _label; _icon; _loading = false; initialized; get htmlElement() { return this.el.nativeElement; } _internalClasses = Object.values(INTERNAL_BUTTON_CLASSES); spinnerIcon = `<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" class="p-icon-spin"> <g clip-path="url(#clip0_417_21408)"> <path d="M6.99701 14C5.85441 13.999 4.72939 13.7186 3.72012 13.1832C2.71084 12.6478 1.84795 11.8737 1.20673 10.9284C0.565504 9.98305 0.165424 8.89526 0.041387 7.75989C-0.0826496 6.62453 0.073125 5.47607 0.495122 4.4147C0.917119 3.35333 1.59252 2.4113 2.46241 1.67077C3.33229 0.930247 4.37024 0.413729 5.4857 0.166275C6.60117 -0.0811796 7.76026 -0.0520535 8.86188 0.251112C9.9635 0.554278 10.9742 1.12227 11.8057 1.90555C11.915 2.01493 11.9764 2.16319 11.9764 2.31778C11.9764 2.47236 11.915 2.62062 11.8057 2.73C11.7521 2.78503 11.688 2.82877 11.6171 2.85864C11.5463 2.8885 11.4702 2.90389 11.3933 2.90389C11.3165 2.90389 11.2404 2.8885 11.1695 2.85864C11.0987 2.82877 11.0346 2.78503 10.9809 2.73C9.9998 1.81273 8.73246 1.26138 7.39226 1.16876C6.05206 1.07615 4.72086 1.44794 3.62279 2.22152C2.52471 2.99511 1.72683 4.12325 1.36345 5.41602C1.00008 6.70879 1.09342 8.08723 1.62775 9.31926C2.16209 10.5513 3.10478 11.5617 4.29713 12.1803C5.48947 12.7989 6.85865 12.988 8.17414 12.7157C9.48963 12.4435 10.6711 11.7264 11.5196 10.6854C12.3681 9.64432 12.8319 8.34282 12.8328 7C12.8328 6.84529 12.8943 6.69692 13.0038 6.58752C13.1132 6.47812 13.2616 6.41667 13.4164 6.41667C13.5712 6.41667 13.7196 6.47812 13.8291 6.58752C13.9385 6.69692 14 6.84529 14 7C14 8.85651 13.2622 10.637 11.9489 11.9497C10.6356 13.2625 8.85432 14 6.99701 14Z" fill="currentColor" /> </g> <defs> <clipPath id="clip0_417_21408"> <rect width="14" height="14" fill="white" /> </clipPath> </defs> </svg>`; constructor(el, document) { this.el = el; this.document = document; } ngAfterViewInit() { DomHandler.addMultipleClasses(this.htmlElement, this.getStyleClass().join(' ')); this.createIcon(); this.createLabel(); this.initialized = true; } getStyleClass() { const styleClass = [INTERNAL_BUTTON_CLASSES.button, INTERNAL_BUTTON_CLASSES.component]; if (this.icon && !this.label && ObjectUtils.isEmpty(this.htmlElement.textContent)) { styleClass.push(INTERNAL_BUTTON_CLASSES.iconOnly); } if (this.loading) { styleClass.push(INTERNAL_BUTTON_CLASSES.disabled, INTERNAL_BUTTON_CLASSES.loading); if (!this.icon && this.label) { styleClass.push(INTERNAL_BUTTON_CLASSES.labelOnly); } if (this.icon && !this.label && !ObjectUtils.isEmpty(this.htmlElement.textContent)) { styleClass.push(INTERNAL_BUTTON_CLASSES.iconOnly); } } return styleClass; } setStyleClass() { const styleClass = this.getStyleClass(); this.htmlElement.classList.remove(...this._internalClasses); this.htmlElement.classList.add(...styleClass); } createLabel() { if (this.label) { let labelElement = this.document.createElement('span'); if (this.icon && !this.label) { labelElement.setAttribute('aria-hidden', 'true'); } labelElement.className = 'p-button-label'; labelElement.appendChild(this.document.createTextNode(this.label)); this.htmlElement.appendChild(labelElement); } } createIcon() { if (this.icon || this.loading) { let iconElement = this.document.createElement('span'); iconElement.className = 'p-button-icon'; iconElement.setAttribute('aria-hidden', 'true'); let iconPosClass = this.label ? 'p-button-icon-' + this.iconPos : null; if (iconPosClass) { DomHandler.addClass(iconElement, iconPosClass); } let iconClass = this.getIconClass(); if (iconClass) { DomHandler.addMultipleClasses(iconElement, iconClass); } if (!this.loadingIcon && this.loading) { iconElement.innerHTML = this.spinnerIcon; } this.htmlElement.insertBefore(iconElement, this.htmlElement.firstChild); } } updateLabel() { let labelElement = DomHandler.findSingle(this.htmlElement, '.p-button-label'); if (!this.label) { labelElement && this.htmlElement.removeChild(labelElement); return; } labelElement ? (labelElement.textContent = this.label) : this.createLabel(); } updateIcon() { let iconElement = DomHandler.findSingle(this.htmlElement, '.p-button-icon'); let labelElement = DomHandler.findSingle(this.htmlElement, '.p-button-label'); if (this.loading && !this.loadingIcon && iconElement) { iconElement.innerHTML = this.spinnerIcon; } else if (iconElement?.innerHTML) { iconElement.innerHTML = ''; } if (iconElement) { if (this.iconPos) { iconElement.className = 'p-button-icon ' + (labelElement ? 'p-button-icon-' + this.iconPos : '') + ' ' + this.getIconClass(); } else { iconElement.className = 'p-button-icon ' + this.getIconClass(); } } else { this.createIcon(); } } getIconClass() { return this.loading ? 'p-button-loading-icon ' + (this.loadingIcon ? this.loadingIcon : 'p-icon') : this.icon; } ngOnDestroy() { this.initialized = false; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: ButtonDirective, deps: [{ token: i0.ElementRef }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.0", type: ButtonDirective, selector: "[pButton]", inputs: { iconPos: "iconPos", loadingIcon: "loadingIcon", label: "label", icon: "icon", loading: "loading" }, host: { classAttribute: "p-element" }, ngImport: i0 }); } export { ButtonDirective }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: ButtonDirective, decorators: [{ type: Directive, args: [{ selector: '[pButton]', host: { class: 'p-element' } }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: Document, decorators: [{ type: Inject, args: [DOCUMENT] }] }]; }, propDecorators: { iconPos: [{ type: Input }], loadingIcon: [{ type: Input }], label: [{ type: Input }], icon: [{ type: Input }], loading: [{ type: Input }] } }); /** * Button is an extension to standard button element with icons and theming. * @group Components */ class Button { /** * Type of the button. * @group Props */ type = 'button'; /** * Position of the icon. * @group Props */ iconPos = 'left'; /** * Name of the icon. * @group Props */ icon; /** * Value of the badge. * @group Props */ badge; /** * Uses to pass attributes to the label's DOM element. * @group Props */ label; /** * When present, it specifies that the component should be disabled. * @group Props */ disabled; /** * Whether the button is in loading state. * @group Props */ loading = false; /** * Icon to display in loading state. * @group Props */ loadingIcon; /** * Inline style of the element. * @group Props */ style; /** * Class of the element. * @group Props */ styleClass; /** * Style class of the badge. * @group Props */ badgeClass; /** * Used to define a string that autocomplete attribute the current element. * @group Props */ ariaLabel; /** * Callback to execute when button is clicked. * This event is intended to be used with the <p-button> component. Using a regular <button> element, use (click). * @param {MouseEvent} event - Mouse event. * @group Emits */ onClick = new EventEmitter(); /** * Callback to execute when button is focused. * This event is intended to be used with the <p-button> component. Using a regular <button> element, use (focus). * @param {FocusEvent} event - Focus event. * @group Emits */ onFocus = new EventEmitter(); /** * Callback to execute when button loses focus. * This event is intended to be used with the <p-button> component. Using a regular <button> element, use (blur). * @param {FocusEvent} event - Focus event. * @group Emits */ onBlur = new EventEmitter(); contentTemplate; loadingIconTemplate; iconTemplate; templates; spinnerIconClass() { return Object.entries(this.iconClass()) .filter(([, value]) => !!value) .reduce((acc, [key]) => acc + ` ${key}`, 'p-button-loading-icon'); } iconClass() { return { 'p-button-icon': true, 'p-button-icon-left': this.iconPos === 'left' && this.label, 'p-button-icon-right': this.iconPos === 'right' && this.label, 'p-button-icon-top': this.iconPos === 'top' && this.label, 'p-button-icon-bottom': this.iconPos === 'bottom' && this.label }; } buttonClass() { return { 'p-button p-component': true, 'p-button-icon-only': (this.icon || this.iconTemplate || this.loadingIcon || this.loadingIconTemplate) && !this.label, 'p-button-vertical': (this.iconPos === 'top' || this.iconPos === 'bottom') && this.label, 'p-disabled': this.disabled || this.loading, 'p-button-loading': this.loading, 'p-button-loading-label-only': this.loading && !this.icon && this.label && !this.loadingIcon && this.iconPos === 'left' }; } ngAfterContentInit() { this.templates?.forEach((item) => { switch (item.getType()) { case 'content': this.contentTemplate = item.template; break; case 'icon': this.iconTemplate = item.template; break; case 'loadingicon': this.loadingIconTemplate = item.template; break; default: this.contentTemplate = item.template; break; } }); } badgeStyleClass() { return { 'p-badge p-component': true, 'p-badge-no-gutter': this.badge && String(this.badge).length === 1 }; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: Button, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: Button, selector: "p-button", inputs: { type: "type", iconPos: "iconPos", icon: "icon", badge: "badge", label: "label", disabled: "disabled", loading: "loading", loadingIcon: "loadingIcon", style: "style", styleClass: "styleClass", badgeClass: "badgeClass", ariaLabel: "ariaLabel" }, outputs: { onClick: "onClick", onFocus: "onFocus", onBlur: "onBlur" }, host: { properties: { "class.p-disabled": "disabled" }, classAttribute: "p-element" }, queries: [{ propertyName: "templates", predicate: PrimeTemplate }], ngImport: i0, template: ` <button [attr.type]="type" [attr.aria-label]="ariaLabel" [class]="styleClass" [ngStyle]="style" [disabled]="disabled || loading" [ngClass]="buttonClass()" (click)="onClick.emit($event)" (focus)="onFocus.emit($event)" (blur)="onBlur.emit($event)" pRipple [attr.data-pc-name]="'button'" [attr.data-pc-section]="'root'" > <ng-content></ng-content> <ng-container *ngTemplateOutlet="contentTemplate"></ng-container> <ng-container *ngIf="loading"> <ng-container *ngIf="!loadingIconTemplate"> <span *ngIf="loadingIcon" [class]="'p-button-loading-icon pi-spin ' + loadingIcon" [ngClass]="iconClass()" [attr.aria-hidden]="true" [attr.data-pc-section]="'loadingicon'"></span> <SpinnerIcon *ngIf="!loadingIcon" [styleClass]="spinnerIconClass()" [spin]="true" [attr.aria-hidden]="true" [attr.data-pc-section]="'loadingicon'" /> </ng-container> <span *ngIf="loadingIconTemplate" class="p-button-loading-icon" [ngClass]="iconClass()" [attr.aria-hidden]="true" [attr.data-pc-section]="'loadingicon'"> <ng-template *ngTemplateOutlet="loadingIconTemplate"></ng-template> </span> </ng-container> <ng-container *ngIf="!loading"> <span *ngIf="icon && !iconTemplate" [class]="icon" [ngClass]="iconClass()" [attr.data-pc-section]="'icon'"></span> <span *ngIf="!icon && iconTemplate" [ngClass]="iconClass()" [attr.data-pc-section]="'icon'"> <ng-template [ngIf]="!icon" *ngTemplateOutlet="iconTemplate"></ng-template> </span> </ng-container> <span class="p-button-label" [attr.aria-hidden]="icon && !label" *ngIf="!contentTemplate && label" [attr.data-pc-section]="'label'">{{ label }}</span> <span [ngClass]="badgeStyleClass()" [class]="badgeClass" *ngIf="!contentTemplate && badge" [attr.data-pc-section]="'badge'">{{ badge }}</span> </button> `, isInline: true, dependencies: [{ kind: "directive", type: i0.forwardRef(function () { return i1.NgClass; }), selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i0.forwardRef(function () { return i1.NgIf; }), selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i0.forwardRef(function () { return i1.NgTemplateOutlet; }), selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i0.forwardRef(function () { return i1.NgStyle; }), selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i0.forwardRef(function () { return i2.Ripple; }), selector: "[pRipple]" }, { kind: "component", type: i0.forwardRef(function () { return SpinnerIcon; }), selector: "SpinnerIcon" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } export { Button }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: Button, decorators: [{ type: Component, args: [{ selector: 'p-button', template: ` <button [attr.type]="type" [attr.aria-label]="ariaLabel" [class]="styleClass" [ngStyle]="style" [disabled]="disabled || loading" [ngClass]="buttonClass()" (click)="onClick.emit($event)" (focus)="onFocus.emit($event)" (blur)="onBlur.emit($event)" pRipple [attr.data-pc-name]="'button'" [attr.data-pc-section]="'root'" > <ng-content></ng-content> <ng-container *ngTemplateOutlet="contentTemplate"></ng-container> <ng-container *ngIf="loading"> <ng-container *ngIf="!loadingIconTemplate"> <span *ngIf="loadingIcon" [class]="'p-button-loading-icon pi-spin ' + loadingIcon" [ngClass]="iconClass()" [attr.aria-hidden]="true" [attr.data-pc-section]="'loadingicon'"></span> <SpinnerIcon *ngIf="!loadingIcon" [styleClass]="spinnerIconClass()" [spin]="true" [attr.aria-hidden]="true" [attr.data-pc-section]="'loadingicon'" /> </ng-container> <span *ngIf="loadingIconTemplate" class="p-button-loading-icon" [ngClass]="iconClass()" [attr.aria-hidden]="true" [attr.data-pc-section]="'loadingicon'"> <ng-template *ngTemplateOutlet="loadingIconTemplate"></ng-template> </span> </ng-container> <ng-container *ngIf="!loading"> <span *ngIf="icon && !iconTemplate" [class]="icon" [ngClass]="iconClass()" [attr.data-pc-section]="'icon'"></span> <span *ngIf="!icon && iconTemplate" [ngClass]="iconClass()" [attr.data-pc-section]="'icon'"> <ng-template [ngIf]="!icon" *ngTemplateOutlet="iconTemplate"></ng-template> </span> </ng-container> <span class="p-button-label" [attr.aria-hidden]="icon && !label" *ngIf="!contentTemplate && label" [attr.data-pc-section]="'label'">{{ label }}</span> <span [ngClass]="badgeStyleClass()" [class]="badgeClass" *ngIf="!contentTemplate && badge" [attr.data-pc-section]="'badge'">{{ badge }}</span> </button> `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'p-element', '[class.p-disabled]': 'disabled' || 'loading' } }] }], propDecorators: { type: [{ type: Input }], iconPos: [{ type: Input }], icon: [{ type: Input }], badge: [{ type: Input }], label: [{ type: Input }], disabled: [{ type: Input }], loading: [{ type: Input }], loadingIcon: [{ type: Input }], style: [{ type: Input }], styleClass: [{ type: Input }], badgeClass: [{ type: Input }], ariaLabel: [{ type: Input }], onClick: [{ type: Output }], onFocus: [{ type: Output }], onBlur: [{ type: Output }], templates: [{ type: ContentChildren, args: [PrimeTemplate] }] } }); class ButtonModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: ButtonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.0", ngImport: i0, type: ButtonModule, declarations: [ButtonDirective, Button], imports: [CommonModule, RippleModule, SharedModule, SpinnerIcon], exports: [ButtonDirective, Button, SharedModule] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: ButtonModule, imports: [CommonModule, RippleModule, SharedModule, SpinnerIcon, SharedModule] }); } export { ButtonModule }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: ButtonModule, decorators: [{ type: NgModule, args: [{ imports: [CommonModule, RippleModule, SharedModule, SpinnerIcon], exports: [ButtonDirective, Button, SharedModule], declarations: [ButtonDirective, Button] }] }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnV0dG9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwcC9jb21wb25lbnRzL2J1dHRvbi9idXR0b24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6RCxPQUFPLEVBQW1DLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsU0FBUyxFQUFjLFlBQVksRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBYSxNQUFNLEVBQTBCLGlCQUFpQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2pQLE9BQU8sRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzFELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDekMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3BELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZUFBZSxDQUFDOzs7O0FBSTVDLE1BQU0sdUJBQXVCLEdBQUc7SUFDNUIsTUFBTSxFQUFFLFVBQVU7SUFDbEIsU0FBUyxFQUFFLGFBQWE7SUFDeEIsUUFBUSxFQUFFLG9CQUFvQjtJQUM5QixRQUFRLEVBQUUsWUFBWTtJQUN0QixPQUFPLEVBQUUsa0JBQWtCO0lBQzNCLFNBQVMsRUFBRSw2QkFBNkI7Q0FDbEMsQ0FBQztBQUNYOzs7R0FHRztBQUNILE1BTWEsZUFBZTtJQXNGTDtJQUEwQztJQXJGN0Q7OztPQUdHO0lBQ00sT0FBTyxHQUF1QixNQUFNLENBQUM7SUFDOUM7OztPQUdHO0lBQ00sV0FBVyxDQUFxQjtJQUN6Qzs7O09BR0c7SUFDSCxJQUFhLEtBQUs7UUFDZCxPQUFPLElBQUksQ0FBQyxNQUFnQixDQUFDO0lBQ2pDLENBQUM7SUFDRCxJQUFJLEtBQUssQ0FBQyxHQUFXO1FBQ2pCLElBQUksQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDO1FBRWxCLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUNsQixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDbkIsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ2xCLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztTQUN4QjtJQUNMLENBQUM7SUFDRDs7O09BR0c7SUFDSCxJQUFhLElBQUk7UUFDYixPQUFPLElBQUksQ0FBQyxLQUFlLENBQUM7SUFDaEMsQ0FBQztJQUNELElBQUksSUFBSSxDQUFDLEdBQVc7UUFDaEIsSUFBSSxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUM7UUFFakIsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ2xCLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNsQixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7U0FDeEI7SUFDTCxDQUFDO0lBQ0Q7OztPQUdHO0lBQ0gsSUFBYSxPQUFPO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUN6QixDQUFDO0lBQ0QsSUFBSSxPQUFPLENBQUMsR0FBWTtRQUNwQixJQUFJLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQztRQUVwQixJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDbEIsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ2xCLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztTQUN4QjtJQUNMLENBQUM7SUFFTSxNQUFNLENBQXFCO0lBRTNCLEtBQUssQ0FBcUI7SUFFMUIsUUFBUSxHQUFZLEtBQUssQ0FBQztJQUUxQixXQUFXLENBQXNCO0lBRXhDLElBQVksV0FBVztRQUNuQixPQUFPLElBQUksQ0FBQyxFQUFFLENBQUMsYUFBNEIsQ0FBQztJQUNoRCxDQUFDO0lBRU8sZ0JBQWdCLEdBQWEsTUFBTSxDQUFDLE1BQU0sQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO0lBRTVFLFdBQVcsR0FBRzs7Ozs7Ozs7Ozs7O1dBWVAsQ0FBQztJQUVSLFlBQW1CLEVBQWMsRUFBNEIsUUFBa0I7UUFBNUQsT0FBRSxHQUFGLEVBQUUsQ0FBWTtRQUE0QixhQUFRLEdBQVIsUUFBUSxDQUFVO0lBQUcsQ0FBQztJQUVuRixlQUFlO1FBQ1gsVUFBVSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBRWhGLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNsQixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFFbkIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUM7SUFDNUIsQ0FBQztJQUVELGFBQWE7UUFDVCxNQUFNLFVBQVUsR0FBYSxDQUFDLHVCQUF1QixDQUFDLE1BQU0sRUFBRSx1QkFBdUIsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUVqRyxJQUFJLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLFdBQVcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsRUFBRTtZQUMvRSxVQUFVLENBQUMsSUFBSSxDQUFDLHVCQUF1QixDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQ3JEO1FBRUQsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ2QsVUFBVSxDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxRQUFRLEVBQUUsdUJBQXVCLENBQUMsT0FBTyxDQUFDLENBQUM7WUFFbkYsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRTtnQkFDMUIsVUFBVSxDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxTQUFTLENBQUMsQ0FBQzthQUN0RDtZQUVELElBQUksSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLEVBQUU7Z0JBQ2hGLFVBQVUsQ0FBQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDckQ7U0FDSjtRQUVELE9BQU8sVUFBVSxDQUFDO0lBQ3RCLENBQUM7SUFFRCxhQUFhO1FBQ1QsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ3hDLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQzVELElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRCxXQUFXO1FBQ1AsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ1osSUFBSSxZQUFZLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdkQsSUFBSSxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRTtnQkFDMUIsWUFBWSxDQUFDLFlBQVksQ0FBQyxhQUFhLEVBQUUsTUFBTSxDQUFDLENBQUM7YUFDcEQ7WUFFRCxZQUFZLENBQUMsU0FBUyxHQUFHLGdCQUFnQixDQUFDO1lBQzFDLFlBQVksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFFbkUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLENBQUM7U0FDOUM7SUFDTCxDQUFDO0lBRUQsVUFBVTtRQUNOLElBQUksSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQzNCLElBQUksV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3RELFdBQVcsQ0FBQyxTQUFTLEdBQUcsZUFBZSxDQUFDO1lBQ3hDLFdBQVcsQ0FBQyxZQUFZLENBQUMsYUFBYSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ2hELElBQUksWUFBWSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUV2RSxJQUFJLFlBQVksRUFBRTtnQkFDZCxVQUFVLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxZQUFZLENBQUMsQ0FBQzthQUNsRDtZQUVELElBQUksU0FBUyxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUVwQyxJQUFJLFNBQVMsRUFBRTtnQkFDWCxVQUFVLENBQUMsa0JBQWtCLENBQUMsV0FBVyxFQUFFLFNBQVMsQ0FBQyxDQUFDO2FBQ3pEO1lBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRTtnQkFDbkMsV0FBVyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO2FBQzVDO1lBRUQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUM7U0FDM0U7SUFDTCxDQUFDO0lBRUQsV0FBVztRQUNQLElBQUksWUFBWSxHQUFHLFVBQVUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1FBRTlFLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ2IsWUFBWSxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzNELE9BQU87U0FDVjtRQUVELFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ2hGLENBQUM7SUFFRCxVQUFVO1FBQ04sSUFBSSxXQUFXLEdBQUcsVUFBVSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFDNUUsSUFBSSxZQUFZLEdBQUcsVUFBVSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLGlCQUFpQixDQUFDLENBQUM7UUFFOUUsSUFBSSxJQUFJLENBQUMsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxXQUFXLEVBQUU7WUFDbEQsV0FBVyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO1NBQzVDO2FBQU0sSUFBSSxXQUFXLEVBQUUsU0FBUyxFQUFFO1lBQy9CLFdBQVcsQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO1NBQzlCO1FBRUQsSUFBSSxXQUFXLEVBQUU7WUFDYixJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7Z0JBQ2QsV0FBVyxDQUFDLFNBQVMsR0FBRyxnQkFBZ0IsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQzthQUNoSTtpQkFBTTtnQkFDSCxXQUFXLENBQUMsU0FBUyxHQUFHLGdCQUFnQixHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQzthQUNsRTtTQUNKO2FBQU07WUFDSCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7U0FDckI7SUFDTCxDQUFDO0lBRUQsWUFBWTtRQUNSLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsd0JBQXdCLEdBQUcsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztJQUNsSCxDQUFDO0lBRUQsV0FBVztRQUNQLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO0lBQzdCLENBQUM7dUdBMU1RLGVBQWUsNENBc0ZtQixRQUFROzJGQXRGMUMsZUFBZTs7U0FBZixlQUFlOzJGQUFmLGVBQWU7a0JBTjNCLFNBQVM7bUJBQUM7b0JBQ1AsUUFBUSxFQUFFLFdBQVc7b0JBQ3JCLElBQUksRUFBRTt3QkFDRixLQUFLLEVBQUUsV0FBVztxQkFDckI7aUJBQ0o7OzBCQXVGdUMsTUFBTTsyQkFBQyxRQUFROzRDQWpGMUMsT0FBTztzQkFBZixLQUFLO2dCQUtHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBS08sS0FBSztzQkFBakIsS0FBSztnQkFnQk8sSUFBSTtzQkFBaEIsS0FBSztnQkFlTyxPQUFPO3NCQUFuQixLQUFLOztBQThKVjs7O0dBR0c7QUFDSCxNQTZDYSxNQUFNO0lBQ2Y7OztPQUdHO0lBQ00sSUFBSSxHQUFXLFFBQVEsQ0FBQztJQUNqQzs7O09BR0c7SUFDTSxPQUFPLEdBQXVCLE1BQU0sQ0FBQztJQUM5Qzs7O09BR0c7SUFDTSxJQUFJLENBQXFCO0lBQ2xDOzs7T0FHRztJQUNNLEtBQUssQ0FBcUI7SUFDbkM7OztPQUdHO0lBQ00sS0FBSyxDQUFxQjtJQUNuQzs7O09BR0c7SUFDTSxRQUFRLENBQXNCO0lBQ3ZDOzs7T0FHRztJQUNNLE9BQU8sR0FBWSxLQUFLLENBQUM7SUFDbEM7OztPQUdHO0lBQ00sV0FBVyxDQUFxQjtJQUN6Qzs7O09BR0c7SUFDTSxLQUFLLENBQThDO0lBQzVEOzs7T0FHRztJQUNNLFVBQVUsQ0FBcUI7SUFDeEM7OztPQUdHO0lBQ00sVUFBVSxDQUFxQjtJQUN4Qzs7O09BR0c7SUFDTSxTQUFTLENBQXFCO0lBQ3ZDOzs7OztPQUtHO0lBQ08sT0FBTyxHQUE2QixJQUFJLFlBQVksRUFBRSxDQUFDO0lBQ2pFOzs7OztPQUtHO0lBQ08sT0FBTyxHQUE2QixJQUFJLFlBQVksRUFBYyxDQUFDO0lBQzdFOzs7OztPQUtHO0lBQ08sTUFBTSxHQUE2QixJQUFJLFlBQVksRUFBYyxDQUFDO0lBRTVFLGVBQWUsQ0FBK0I7SUFFOUMsbUJBQW1CLENBQStCO0lBRWxELFlBQVksQ0FBK0I7SUFFWCxTQUFTLENBQXVDO0lBRWhGLGdCQUFnQjtRQUNaLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7YUFDbEMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO2FBQzlCLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEdBQUcsSUFBSSxHQUFHLEVBQUUsRUFBRSx1QkFBdUIsQ0FBQyxDQUFDO0lBQzFFLENBQUM7SUFFRCxTQUFTO1FBQ0wsT0FBTztZQUNILGVBQWUsRUFBRSxJQUFJO1lBQ3JCLG9CQUFvQixFQUFFLElBQUksQ0FBQyxPQUFPLEtBQUssTUFBTSxJQUFJLElBQUksQ0FBQyxLQUFLO1lBQzNELHFCQUFxQixFQUFFLElBQUksQ0FBQyxPQUFPLEtBQUssT0FBTyxJQUFJLElBQUksQ0FBQyxLQUFLO1lBQzdELG1CQUFtQixFQUFFLElBQUksQ0FBQyxPQUFPLEtBQUssS0FBSyxJQUFJLElBQUksQ0FBQyxLQUFLO1lBQ3pELHNCQUFzQixFQUFFLElBQUksQ0FBQyxPQUFPLEtBQUssUUFBUSxJQUFJLElBQUksQ0FBQyxLQUFLO1NBQ2xFLENBQUM7SUFDTixDQUFDO0lBRUQsV0FBVztRQUNQLE9BQU87WUFDSCxzQkFBc0IsRUFBRSxJQUFJO1lBQzVCLG9CQUFvQixFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsWUFBWSxJQUFJLElBQUksQ0FBQyxXQUFXLElBQUksSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSztZQUNySCxtQkFBbUIsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLEtBQUssS0FBSyxJQUFJLElBQUksQ0FBQyxPQUFPLEtBQUssUUFBUSxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUs7WUFDeEYsWUFBWSxFQUFFLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLE9BQU87WUFDM0Msa0JBQWtCLEVBQUUsSUFBSSxDQUFDLE9BQU87WUFDaEMsNkJBQTZCLEVBQUUsSUFBSSxDQUFDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLElBQUksSUFBSSxDQUFDLE9BQU8sS0FBSyxNQUFNO1NBQzFILENBQUM7SUFDTixDQUFDO0lBRUQsa0JBQWtCO1FBQ2QsSUFBSSxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUM3QixRQUFRLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRTtnQkFDcEIsS0FBSyxTQUFTO29CQUNWLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztvQkFDckMsTUFBTTtnQkFFVixLQUFLLE1BQU07b0JBQ1AsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO29CQUNsQyxNQUFNO2dCQUVWLEtBQUssYUFBYTtvQkFDZCxJQUFJLENBQUMsbUJBQW1CLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztvQkFDekMsTUFBTTtnQkFFVjtvQkFDSSxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7b0JBQ3JDLE1BQU07YUFDYjtRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVELGVBQWU7UUFDWCxPQUFPO1lBQ0gscUJBQXFCLEVBQUUsSUFBSTtZQUMzQixtQkFBbUIsRUFBRSxJQUFJLENBQUMsS0FBSyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxLQUFLLENBQUM7U0FDckUsQ0FBQztJQUNOLENBQUM7dUdBakpRLE1BQU07MkZBQU4sTUFBTSxzZUF5RkUsYUFBYSw2QkFwSXBCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztLQW1DVCwreEJBNkptRCxXQUFXOztTQXJKdEQsTUFBTTsyRkFBTixNQUFNO2tCQTdDbEIsU0FBUzttQkFBQztvQkFDUCxRQUFRLEVBQUUsVUFBVTtvQkFDcEIsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztLQW1DVDtvQkFDRCxlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTtvQkFDL0MsYUFBYSxFQUFFLGlCQUFpQixDQUFDLElBQUk7b0JBQ3JDLElBQUksRUFBRTt3QkFDRixLQUFLLEVBQUUsV0FBVzt3QkFDbEIsb0JBQW9CLEVBQUUsVUFBVSxJQUFJLFNBQVM7cUJBQ2hEO2lCQUNKOzhCQU1ZLElBQUk7c0JBQVosS0FBSztnQkFLRyxPQUFPO3NCQUFmLEtBQUs7Z0JBS0csSUFBSTtzQkFBWixLQUFLO2dCQUtHLEtBQUs7c0JBQWIsS0FBSztnQkFLRyxLQUFLO3NCQUFiLEtBQUs7Z0JBS0csUUFBUTtzQkFBaEIsS0FBSztnQkFLRyxPQUFPO3NCQUFmLEtBQUs7Z0JBS0csV0FBVztzQkFBbkIsS0FBSztnQkFLRyxLQUFLO3NCQUFiLEtBQUs7Z0JBS0csVUFBVTtzQkFBbEIsS0FBSztnQkFLRyxVQUFVO3NCQUFsQixLQUFLO2dCQUtHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBT0ksT0FBTztzQkFBaEIsTUFBTTtnQkFPRyxPQUFPO3NCQUFoQixNQUFNO2dCQU9HLE1BQU07c0JBQWYsTUFBTTtnQkFReUIsU0FBUztzQkFBeEMsZUFBZTt1QkFBQyxhQUFhOztBQTJEbEMsTUFLYSxZQUFZO3VHQUFaLFlBQVk7d0dBQVosWUFBWSxpQkF0WlosZUFBZSxFQTZQZixNQUFNLGFBcUpMLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFdBQVcsYUFsWnRELGVBQWUsRUE2UGYsTUFBTSxFQXNKb0IsWUFBWTt3R0FHdEMsWUFBWSxZQUpYLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFDNUIsWUFBWTs7U0FHdEMsWUFBWTsyRkFBWixZQUFZO2tCQUx4QixRQUFRO21CQUFDO29CQUNOLE9BQU8sRUFBRSxDQUFDLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFdBQVcsQ0FBQztvQkFDaEUsT0FBTyxFQUFFLENBQUMsZUFBZSxFQUFFLE1BQU0sRUFBRSxZQUFZLENBQUM7b0JBQ2hELFlBQVksRUFBRSxDQUFDLGVBQWUsRUFBRSxNQUFNLENBQUM7aUJBQzFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlLCBET0NVTUVOVCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBBZnRlckNvbnRlbnRJbml0LCBBZnRlclZpZXdJbml0LCBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBDb250ZW50Q2hpbGRyZW4sIERpcmVjdGl2ZSwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBJbmplY3QsIElucHV0LCBOZ01vZHVsZSwgT25EZXN0cm95LCBPdXRwdXQsIFF1ZXJ5TGlzdCwgVGVtcGxhdGVSZWYsIFZpZXdFbmNhcHN1bGF0aW9uIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBQcmltZVRlbXBsYXRlLCBTaGFyZWRNb2R1bGUgfSBmcm9tICdwcmltZW5nL2FwaSc7XG5pbXBvcnQgeyBEb21IYW5kbGVyIH0gZnJvbSAncHJpbWVuZy9kb20nO1xuaW1wb3J0IHsgU3Bpbm5lckljb24gfSBmcm9tICdwcmltZW5nL2ljb25zL3NwaW5uZXInO1xuaW1wb3J0IHsgUmlwcGxlTW9kdWxlIH0gZnJvbSAncHJpbWVuZy9yaXBwbGUnO1xuaW1wb3J0IHsgT2JqZWN0VXRpbHMgfSBmcm9tICdwcmltZW5nL3V0aWxzJztcblxudHlwZSBCdXR0b25JY29uUG9zaXRpb24gPSAnbGVmdCcgfCAncmlnaHQnIHwgJ3RvcCcgfCAnYm90dG9tJztcblxuY29uc3QgSU5URVJOQUxfQlVUVE9OX0NMQVNTRVMgPSB7XG4gICAgYnV0dG9uOiAncC1idXR0b24nLFxuICAgIGNvbXBvbmVudDogJ3AtY29tcG9uZW50JyxcbiAgICBpY29uT25seTogJ3AtYnV0dG9uLWljb24tb25seScsXG4gICAgZGlzYWJsZWQ6ICdwLWRpc2FibGVkJyxcbiAgICBsb2FkaW5nOiAncC1idXR0b24tbG9hZGluZycsXG4gICAgbGFiZWxPbmx5OiAncC1idXR0b24tbG9hZGluZy1sYWJlbC1vbmx5J1xufSBhcyBjb25zdDtcbi8qKlxuICogQnV0dG9uIGRpcmVjdGl2ZSBpcyBhbiBleHRlbnNpb24gdG8gYnV0dG9uIGNvbXBvbmVudC5cbiAqIEBncm91cCBDb21wb25lbnRzXG4gKi9cbkBEaXJlY3RpdmUoe1xuICAgIHNlbGVjdG9yOiAnW3BCdXR0b25dJyxcbiAgICBob3N0OiB7XG4gICAgICAgIGNsYXNzOiAncC1lbGVtZW50J1xuICAgIH1cbn0pXG5leHBvcnQgY2xhc3MgQnV0dG9uRGlyZWN0aXZlIGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcbiAgICAvKipcbiAgICAgKiBQb3NpdGlvbiBvZiB0aGUgaWNvbi5cbiAgICAgKiBAZ3JvdXAgUHJvcHNcbiAgICAgKi9cbiAgICBASW5wdXQoKSBpY29uUG9zOiBCdXR0b25JY29uUG9zaXRpb24gPSAnbGVmdCc7XG4gICAgLyoqXG4gICAgICogVXNlcyB0byBwYXNzIGF0dHJpYnV0ZXMgdG8gdGhlIGxvYWRpbmcgaWNvbidzIERPTSBlbGVtZW50LlxuICAgICAqIEBncm91cCBQcm9wc1xuICAgICAqL1xuICAgIEBJbnB1dCgpIGxvYWRpbmdJY29uOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgLyoqXG4gICAgICogVGV4dCBvZiB0aGUgYnV0dG9uLlxuICAgICAqIEBncm91cCBQcm9wc1xuICAgICAqL1xuICAgIEBJbnB1dCgpIGdldCBsYWJlbCgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5fbGFiZWwgYXMgc3RyaW5nO1xuICAgIH1cbiAgICBzZXQgbGFiZWwodmFsOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5fbGFiZWwgPSB2YWw7XG5cbiAgICAgICAgaWYgKHRoaXMuaW5pdGlhbGl6ZWQpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlTGFiZWwoKTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlSWNvbigpO1xuICAgICAgICAgICAgdGhpcy5zZXRTdHlsZUNsYXNzKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogTmFtZSBvZiB0aGUgaWNvbi5cbiAgICAgKiBAZ3JvdXAgUHJvcHNcbiAgICAgKi9cbiAgICBASW5wdXQoKSBnZXQgaWNvbigpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5faWNvbiBhcyBzdHJpbmc7XG4gICAgfVxuICAgIHNldCBpY29uKHZhbDogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuX2ljb24gPSB2YWw7XG5cbiAgICAgICAgaWYgKHRoaXMuaW5pdGlhbGl6ZWQpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlSWNvbigpO1xuICAgICAgICAgICAgdGhpcy5zZXRTdHlsZUNsYXNzKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgYnV0dG9uIGlzIGluIGxvYWRpbmcgc3RhdGUuXG4gICAgICogQGdyb3VwIFByb3BzXG4gICAgICovXG4gICAgQElucHV0KCkgZ2V0IGxvYWRpbmcoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sb2FkaW5nO1xuICAgIH1cbiAgICBzZXQgbG9hZGluZyh2YWw6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5fbG9hZGluZyA9IHZhbDtcblxuICAgICAgICBpZiAodGhpcy5pbml0aWFsaXplZCkge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVJY29uKCk7XG4gICAgICAgICAgICB0aGlzLnNldFN0eWxlQ2xhc3MoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBfbGFiZWw6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAgIHB1YmxpYyBfaWNvbjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gICAgcHVibGljIF9sb2FkaW5nOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICBwdWJsaWMgaW5pdGlhbGl6ZWQ6IGJvb2xlYW4gfCB1bmRlZmluZWQ7XG5cbiAgICBwcml2YXRlIGdldCBodG1sRWxlbWVudCgpOiBIVE1MRWxlbWVudCB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfaW50ZXJuYWxDbGFzc2VzOiBzdHJpbmdbXSA9IE9iamVjdC52YWx1ZXMoSU5URVJOQUxfQlVUVE9OX0NMQVNTRVMpO1xuXG4gICAgc3Bpbm5lckljb24gPSBgPHN2ZyB3aWR0aD1cIjE0XCIgaGVpZ2h0PVwiMTRcIiB2aWV3Qm94PVwiMCAwIDE0IDE0XCIgZmlsbD1cIm5vbmVcIiB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgY2xhc3M9XCJwLWljb24tc3BpblwiPlxuICAgICAgICA8ZyBjbGlwLXBhdGg9XCJ1cmwoI2NsaXAwXzQxN18yMTQwOClcIj5cbiAgICAgICAgICAgIDxwYXRoXG4gICAgICAgICAgICAgICAgZD1cIk02Ljk5NzAxIDE0QzUuODU0NDEgMTMuOTk5IDQuNzI5MzkgMTMuNzE4NiAzLjcyMDEyIDEzLjE4MzJDMi43MTA4NCAxMi42NDc4IDEuODQ3OTUgMTEuODczNyAxLjIwNjczIDEwLjkyODRDMC41NjU1MDQgOS45ODMwNSAwLjE2NTQyNCA4Ljg5NTI2IDAuMDQxMzg3IDcuNzU5ODlDLTAuMDgyNjQ5NiA2LjYyNDUzIDAuMDczMTI1IDUuNDc2MDcgMC40OTUxMjIgNC40MTQ3QzAuOTE3MTE5IDMuMzUzMzMgMS41OTI1MiAyLjQxMTMgMi40NjI0MSAxLjY3MDc3QzMuMzMyMjkgMC45MzAyNDcgNC4zNzAyNCAwLjQxMzcyOSA1LjQ4NTcgMC4xNjYyNzVDNi42MDExNyAtMC4wODExNzk2IDcuNzYwMjYgLTAuMDUyMDUzNSA4Ljg2MTg4IDAuMjUxMTEyQzkuOTYzNSAwLjU1NDI3OCAxMC45NzQyIDEuMTIyMjcgMTEuODA1NyAxLjkwNTU1QzExLjkxNSAyLjAxNDkzIDExLjk3NjQgMi4xNjMxOSAxMS45NzY0IDIuMzE3NzhDMTEuOTc2NCAyLjQ3MjM2IDExLjkxNSAyLjYyMDYyIDExLjgwNTcgMi43M0MxMS43NTIxIDIuNzg1MDMgMTEuNjg4IDIuODI4NzcgMTEuNjE3MSAyLjg1ODY0QzExLjU0NjMgMi44ODg1IDExLjQ3MDIgMi45MDM4OSAxMS4zOTMzIDIuOTAzODlDMTEuMzE2NSAyLjkwMzg5IDExLjI0MDQgMi44ODg1IDExLjE2OTUgMi44NTg2NEMxMS4wOTg3IDIuODI4NzcgMTEuMDM0NiAyLjc4NTAzIDEwLjk4MDkgMi43M0M5Ljk5OTggMS44MTI3MyA4LjczMjQ2IDEuMjYxMzggNy4zOTIyNiAxLjE2ODc2QzYuMDUyMDYgMS4wNzYxNSA0LjcyMDg2IDEuNDQ3OTQgMy42MjI3OSAyLjIyMTUyQzIuNTI0NzEgMi45OTUxMSAxLjcyNjgzIDQuMTIzMjUgMS4zNjM0NSA1LjQxNjAyQzEuMDAwMDggNi43MDg3OSAxLjA5MzQyIDguMDg3MjMgMS42Mjc3NSA5LjMxOTI2QzIuMTYyMDkgMTAuNTUxMyAzLjEwNDc4IDExLjU2MTcgNC4yOTcxMyAxMi4xODAzQzUuNDg5NDcgMTIuNzk4OSA2Ljg1ODY1IDEyLjk4OCA4LjE3NDE0IDEyLjcxNTdDOS40ODk2MyAxMi40NDM1IDEwLjY3MTEgMTEuNzI2NCAxMS41MTk2IDEwLjY4NTRDMTIuMzY4MSA5LjY0NDMyIDEyLjgzMTkgOC4zNDI4MiAxMi44MzI4IDdDMTIuODMyOCA2Ljg0NTI5IDEyLjg5NDMgNi42OTY5MiAxMy4wMDM4IDYuNTg3NTJDMTMuMTEzMiA2LjQ3ODEyIDEzLjI2MTYgNi40MTY2NyAxMy40MTY0IDYuNDE2NjdDMTMuNTcxMiA2LjQxNjY3IDEzLjcxOTYgNi40NzgxMiAxMy44MjkxIDYuNTg3NTJDMTMuOTM4NSA2LjY5NjkyIDE0IDYuODQ1MjkgMTQgN0MxNCA4Ljg1NjUxIDEzLjI2MjIgMTAuNjM3IDExLjk0ODkgMTEuOTQ5N0MxMC42MzU2IDEzLjI2MjUgOC44NTQzMiAxNCA2Ljk5NzAxIDE0WlwiXG4gICAgICAgICAgICAgICAgZmlsbD1cImN1cnJlbnRDb2xvclwiXG4gICAgICAgICAgICAvPlxuICAgICAgICA8L2c+XG4gICAgICAgIDxkZWZzPlxuICAgICAgICAgICAgPGNsaXBQYXRoIGlkPVwiY2xpcDBfNDE3XzIxNDA4XCI+XG4gICAgICAgICAgICAgICAgPHJlY3Qgd2lkdGg9XCIxNFwiIGhlaWdodD1cIjE0XCIgZmlsbD1cIndoaXRlXCIgLz5cbiAgICAgICAgICAgIDwvY2xpcFBhdGg+XG4gICAgICAgIDwvZGVmcz5cbiAgICA8L3N2Zz5gO1xuXG4gICAgY29uc3RydWN0b3IocHVibGljIGVsOiBFbGVtZW50UmVmLCBASW5qZWN0KERPQ1VNRU5UKSBwcml2YXRlIGRvY3VtZW50OiBEb2N1bWVudCkge31cblxuICAgIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICAgICAgRG9tSGFuZGxlci5hZGRNdWx0aXBsZUNsYXNzZXModGhpcy5odG1sRWxlbWVudCwgdGhpcy5nZXRTdHlsZUNsYXNzKCkuam9pbignICcpKTtcblxuICAgICAgICB0aGlzLmNyZWF0ZUljb24oKTtcbiAgICAgICAgdGhpcy5jcmVhdGVMYWJlbCgpO1xuXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGdldFN0eWxlQ2xhc3MoKTogc3RyaW5nW10ge1xuICAgICAgICBjb25zdCBzdHlsZUNsYXNzOiBzdHJpbmdbXSA9IFtJTlRFUk5BTF9CVVRUT05fQ0xBU1NFUy5idXR0b24sIElOVEVSTkFMX0JVVFRPTl9DTEFTU0VTLmNvbXBvbmVudF07XG5cbiAgICAgICAgaWYgKHRoaXMuaWNvbiAmJiAhdGhpcy5sYWJlbCAmJiBPYmplY3RVdGlscy5pc0VtcHR5KHRoaXMuaHRtbEVsZW1lbnQudGV4dENvbnRlbnQpKSB7XG4gICAgICAgICAgICBzdHlsZUNsYXNzLnB1c2goSU5URVJOQUxfQlVUVE9OX0NMQVNTRVMuaWNvbk9ubHkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMubG9hZGluZykge1xuICAgICAgICAgICAgc3R5bGVDbGFzcy5wdXNoKElOVEVSTkFMX0JVVFRPTl9DTEFTU0VTLmRpc2FibGVkLCBJTlRFUk5BTF9CVVRUT05fQ0xBU1NFUy5sb2FkaW5nKTtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLmljb24gJiYgdGhpcy5sYWJlbCkge1xuICAgICAgICAgICAgICAgIHN0eWxlQ2xhc3MucHVzaChJTlRFUk5BTF9CVVRUT05fQ0xBU1NFUy5sYWJlbE9ubHkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5pY29uICYmICF0aGlzLmxhYmVsICYmICFPYmplY3RVdGlscy5pc0VtcHR5KHRoaXMuaHRtbEVsZW1lbnQudGV4dENvbnRlbnQpKSB7XG4gICAgICAgICAgICAgICAgc3R5bGVDbGFzcy5wdXNoKElOVEVSTkFMX0JVVFRPTl9DTEFTU0VTLmljb25Pbmx5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzdHlsZUNsYXNzO1xuICAgIH1cblxuICAgIHNldFN0eWxlQ2xhc3MoKSB7XG4gICAgICAgIGNvbnN0IHN0eWxlQ2xhc3MgPSB0aGlzLmdldFN0eWxlQ2xhc3MoKTtcbiAgICAgICAgdGhpcy5odG1sRWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKC4uLnRoaXMuX2ludGVybmFsQ2xhc3Nlcyk7XG4gICAgICAgIHRoaXMuaHRtbEVsZW1lbnQuY2xhc3NMaXN0LmFkZCguLi5zdHlsZUNsYXNzKTtcbiAgICB9XG5cbiAgICBjcmVhdGVMYWJlbCgpIHtcbiAgICAgICAgaWYgKHRoaXMubGFiZWwpIHtcbiAgICAgICAgICAgIGxldCBsYWJlbEVsZW1lbnQgPSB0aGlzLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmljb24gJiYgIXRoaXMubGFiZWwpIHtcbiAgICAgICAgICAgICAgICBsYWJlbEVsZW1lbnQuc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsICd0cnVlJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxhYmVsRWxlbWVudC5jbGFzc05hbWUgPSAncC1idXR0b24tbGFiZWwnO1xuICAgICAgICAgICAgbGFiZWxFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMuZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUodGhpcy5sYWJlbCkpO1xuXG4gICAgICAgICAgICB0aGlzLmh0bWxFbGVtZW50LmFwcGVuZENoaWxkKGxhYmVsRWxlbWVudCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjcmVhdGVJY29uKCkge1xuICAgICAgICBpZiAodGhpcy5pY29uIHx8IHRoaXMubG9hZGluZykge1xuICAgICAgICAgICAgbGV0IGljb25FbGVtZW50ID0gdGhpcy5kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XG4gICAgICAgICAgICBpY29uRWxlbWVudC5jbGFzc05hbWUgPSAncC1idXR0b24taWNvbic7XG4gICAgICAgICAgICBpY29uRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJywgJ3RydWUnKTtcbiAgICAgICAgICAgIGxldCBpY29uUG9zQ2xhc3MgPSB0aGlzLmxhYmVsID8gJ3AtYnV0dG9uLWljb24tJyArIHRoaXMuaWNvblBvcyA6IG51bGw7XG5cbiAgICAgICAgICAgIGlmIChpY29uUG9zQ2xhc3MpIHtcbiAgICAgICAgICAgICAgICBEb21IYW5kbGVyLmFkZENsYXNzKGljb25FbGVtZW50LCBpY29uUG9zQ2xhc3MpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgaWNvbkNsYXNzID0gdGhpcy5nZXRJY29uQ2xhc3MoKTtcblxuICAgICAgICAgICAgaWYgKGljb25DbGFzcykge1xuICAgICAgICAgICAgICAgIERvbUhhbmRsZXIuYWRkTXVsdGlwbGVDbGFzc2VzKGljb25FbGVtZW50LCBpY29uQ2xhc3MpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIXRoaXMubG9hZGluZ0ljb24gJiYgdGhpcy5sb2FkaW5nKSB7XG4gICAgICAgICAgICAgICAgaWNvbkVsZW1lbnQuaW5uZXJIVE1MID0gdGhpcy5zcGlubmVySWNvbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5odG1sRWxlbWVudC5pbnNlcnRCZWZvcmUoaWNvbkVsZW1lbnQsIHRoaXMuaHRtbEVsZW1lbnQuZmlyc3RDaGlsZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB1cGRhdGVMYWJlbCgpIHtcbiAgICAgICAgbGV0IGxhYmVsRWxlbWVudCA9IERvbUhhbmRsZXIuZmluZFNpbmdsZSh0aGlzLmh0bWxFbGVtZW50LCAnLnAtYnV0dG9uLWxhYmVsJyk7XG5cbiAgICAgICAgaWYgKCF0aGlzLmxhYmVsKSB7XG4gICAgICAgICAgICBsYWJlbEVsZW1lbnQgJiYgdGhpcy5odG1sRWxlbWVudC5yZW1vdmVDaGlsZChsYWJlbEVsZW1lbnQpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgbGFiZWxFbGVtZW50ID8gKGxhYmVsRWxlbWVudC50ZXh0Q29udGVudCA9IHRoaXMubGFiZWwpIDogdGhpcy5jcmVhdGVMYWJlbCgpO1xuICAgIH1cblxuICAgIHVwZGF0ZUljb24oKSB7XG4gICAgICAgIGxldCBpY29uRWxlbWVudCA9IERvbUhhbmRsZXIuZmluZFNpbmdsZSh0aGlzLmh0bWxFbGVtZW50LCAnLnAtYnV0dG9uLWljb24nKTtcbiAgICAgICAgbGV0IGxhYmVsRWxlbWVudCA9IERvbUhhbmRsZXIuZmluZFNpbmdsZSh0aGlzLmh0bWxFbGVtZW50LCAnLnAtYnV0dG9uLWxhYmVsJyk7XG5cbiAgICAgICAgaWYgKHRoaXMubG9hZGluZyAmJiAhdGhpcy5sb2FkaW5nSWNvbiAmJiBpY29uRWxlbWVudCkge1xuICAgICAgICAgICAgaWNvbkVsZW1lbnQuaW5uZXJIVE1MID0gdGhpcy5zcGlubmVySWNvbjtcbiAgICAgICAgfSBlbHNlIGlmIChpY29uRWxlbWVudD8uaW5uZXJIVE1MKSB7XG4gICAgICAgICAgICBpY29uRWxlbWVudC5pbm5lckhUTUwgPSAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpY29uRWxlbWVudCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuaWNvblBvcykge1xuICAgICAgICAgICAgICAgIGljb25FbGVtZW50LmNsYXNzTmFtZSA9ICdwLWJ1dHRvbi1pY29uICcgKyAobGFiZWxFbGVtZW50ID8gJ3AtYnV0dG9uLWljb24tJyArIHRoaXMuaWNvblBvcyA6ICcnKSArICcgJyArIHRoaXMuZ2V0SWNvbkNsYXNzKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGljb25FbGVtZW50LmNsYXNzTmFtZSA9ICdwLWJ1dHRvbi1pY29uICcgKyB0aGlzLmdldEljb25DbGFzcygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5jcmVhdGVJY29uKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXRJY29uQ2xhc3MoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxvYWRpbmcgPyAncC1idXR0b24tbG9hZGluZy1pY29uICcgKyAodGhpcy5sb2FkaW5nSWNvbiA/IHRoaXMubG9hZGluZ0ljb24gOiAncC1pY29uJykgOiB0aGlzLmljb247XG4gICAgfVxuXG4gICAgbmdPbkRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICB9XG59XG4vKipcbiAqIEJ1dHRvbiBpcyBhbiBleHRlbnNpb24gdG8gc3RhbmRhcmQgYnV0dG9uIGVsZW1lbnQgd2l0aCBpY29ucyBhbmQgdGhlbWluZy5cbiAqIEBncm91cCBDb21wb25lbnRzXG4gKi9cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAncC1idXR0b24nLFxuICAgIHRlbXBsYXRlOiBgXG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIFthdHRyLnR5cGVdPVwidHlwZVwiXG4gICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImFyaWFMYWJlbFwiXG4gICAgICAgICAgICBbY2xhc3NdPVwic3R5bGVDbGFzc1wiXG4gICAgICAgICAgICBbbmdTdHlsZV09XCJzdHlsZVwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWQgfHwgbG9hZGluZ1wiXG4gICAgICAgICAgICBbbmdDbGFzc109XCJidXR0b25DbGFzcygpXCJcbiAgICAgICAgICAgIChjbGljayk9XCJvbkNsaWNrLmVtaXQoJGV2ZW50KVwiXG4gICAgICAgICAgICAoZm9jdXMpPVwib25Gb2N1cy5lbWl0KCRldmVudClcIlxuICAgICAgICAgICAgKGJsdXIpPVwib25CbHVyLmVtaXQoJGV2ZW50KVwiXG4gICAgICAgICAgICBwUmlwcGxlXG4gICAgICAgICAgICBbYXR0ci5kYXRhLXBjLW5hbWVdPVwiJ2J1dHRvbidcIlxuICAgICAgICAgICAgW2F0dHIuZGF0YS1wYy1zZWN0aW9uXT1cIidyb290J1wiXG4gICAgICAgID5cbiAgICAgICAgICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJjb250ZW50VGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJsb2FkaW5nXCI+XG4gICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFsb2FkaW5nSWNvblRlbXBsYXRlXCI+XG4gICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwibG9hZGluZ0ljb25cIiBbY2xhc3NdPVwiJ3AtYnV0dG9uLWxvYWRpbmctaWNvbiBwaS1zcGluICcgKyBsb2FkaW5nSWNvblwiIFtuZ0NsYXNzXT1cImljb25DbGFzcygpXCIgW2F0dHIuYXJpYS1oaWRkZW5dPVwidHJ1ZVwiIFthdHRyLmRhdGEtcGMtc2VjdGlvbl09XCInbG9hZGluZ2ljb24nXCI+PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8U3Bpbm5lckljb24gKm5nSWY9XCIhbG9hZGluZ0ljb25cIiBbc3R5bGVDbGFzc109XCJzcGlubmVySWNvbkNsYXNzKClcIiBbc3Bpbl09XCJ0cnVlXCIgW2F0dHIuYXJpYS1oaWRkZW5dPVwidHJ1ZVwiIFthdHRyLmRhdGEtcGMtc2VjdGlvbl09XCInbG9hZGluZ2ljb24nXCIgLz5cbiAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cImxvYWRpbmdJY29uVGVtcGxhdGVcIiBjbGFzcz1cInAtYnV0dG9uLWxvYWRpbmctaWNvblwiIFtuZ0NsYXNzXT1cImljb25DbGFzcygpXCIgW2F0dHIuYXJpYS1oaWRkZW5dPVwidHJ1ZVwiIFthdHRyLmRhdGEtcGMtc2VjdGlvbl09XCInbG9hZGluZ2ljb24nXCI+XG4gICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSAqbmdUZW1wbGF0ZU91dGxldD1cImxvYWRpbmdJY29uVGVtcGxhdGVcIj48L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFsb2FkaW5nXCI+XG4gICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJpY29uICYmICFpY29uVGVtcGxhdGVcIiBbY2xhc3NdPVwiaWNvblwiIFtuZ0NsYXNzXT1cImljb25DbGFzcygpXCIgW2F0dHIuZGF0YS1wYy1zZWN0aW9uXT1cIidpY29uJ1wiPjwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cIiFpY29uICYmIGljb25UZW1wbGF0ZVwiIFtuZ0NsYXNzXT1cImljb25DbGFzcygpXCIgW2F0dHIuZGF0YS1wYy1zZWN0aW9uXT1cIidpY29uJ1wiPlxuICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwiIWljb25cIiAqbmdUZW1wbGF0ZU91dGxldD1cImljb25UZW1wbGF0ZVwiPjwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInAtYnV0dG9uLWxhYmVsXCIgW2F0dHIuYXJpYS1oaWRkZW5dPVwiaWNvbiAmJiAhbGFiZWxcIiAqbmdJZj1cIiFjb250ZW50VGVtcGxhdGUgJiYgbGFiZWxcIiBbYXR0ci5kYXRhLXBjLXNlY3Rpb25dPVwiJ2xhYmVsJ1wiPnt7IGxhYmVsIH19PC9zcGFuPlxuICAgICAgICAgICAgPHNwYW4gW25nQ2xhc3NdPVwiYmFkZ2VTdHlsZUNsYXNzKClcIiBbY2xhc3NdPVwiYmFkZ2VDbGFzc1wiICpuZ0lmPVwiIWNvbnRlbnRUZW1wbGF0ZSAmJiBiYWRnZVwiIFthdHRyLmRhdGEtcGMtc2VjdGlvbl09XCInYmFkZ2UnXCI+e3sgYmFkZ2UgfX08L3NwYW4+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgIGAsXG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gICAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgICBob3N0OiB7XG4gICAgICAgIGNsYXNzOiAncC1lbGVtZW50JyxcbiAgICAgICAgJ1tjbGFzcy5wLWRpc2FibGVkXSc6ICdkaXNhYmxlZCcgfHwgJ2xvYWRpbmcnXG4gICAgfVxufSlcbmV4cG9ydCBjbGFzcyBCdXR0b24gaW1wbGVtZW50cyBBZnRlckNvbnRlbnRJbml0IHtcbiAgICAvKipcbiAgICAgKiBUeXBlIG9mIHRoZSBidXR0b24uXG4gICAgICogQGdyb3VwIFByb3BzXG4gICAgICovXG4gICAgQElucHV0KCkgdHlwZTogc3RyaW5nID0gJ2J1dHRvbic7XG4gICAgLyoqXG4gICAgICogUG9zaXRpb24gb2YgdGhlIGljb24uXG4gICAgICogQGdyb3VwIFByb3BzXG4gICAgICovXG4gICAgQElucHV0KCkgaWNvblBvczogQnV0dG9uSWNvblBvc2l0aW9uID0gJ2xlZnQnO1xuICAgIC8qKlxuICAgICAqIE5hbWUgb2YgdGhlIGljb24uXG4gICAgICogQGdyb3VwIFByb3BzXG4gICAgICovXG4gICAgQElucHV0KCkgaWNvbjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgIC8qKlxuICAgICAqIFZhbHVlIG9mIHR