UNPKG

ngx-smart-modal

Version:

Smart modal handler to manage modals and data everywhere in Angular apps.

429 lines 46.9 kB
import { DOCUMENT, isPlatformBrowser } from '@angular/common'; import { Component, EventEmitter, HostListener, Inject, Input, Output, PLATFORM_ID, ViewChild, ViewChildren, ViewContainerRef } from '@angular/core'; import { NgxSmartModalConfig } from '../config/ngx-smart-modal.config'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; export class NgxSmartModalComponent { constructor(_renderer, _changeDetectorRef, _viewContainerRef, elementRef, _document, _platformId) { this._renderer = _renderer; this._changeDetectorRef = _changeDetectorRef; this._viewContainerRef = _viewContainerRef; this.elementRef = elementRef; this._document = _document; this._platformId = _platformId; this.closable = true; this.escapable = true; this.dismissable = true; this.identifier = ''; this.customClass = 'nsm-dialog-animation-fade'; this.visible = false; this.backdrop = true; this.force = true; this.hideDelay = 500; this.autostart = false; this.target = ''; this.ariaLabel = null; this.ariaLabelledBy = null; this.ariaDescribedBy = null; this.refocus = true; this.visibleChange = new EventEmitter(); this.onClose = new EventEmitter(); this.onCloseFinished = new EventEmitter(); this.onDismiss = new EventEmitter(); this.onDismissFinished = new EventEmitter(); this.onAnyCloseEvent = new EventEmitter(); this.onAnyCloseEventFinished = new EventEmitter(); this.onOpen = new EventEmitter(); this.onOpenFinished = new EventEmitter(); this.onEscape = new EventEmitter(); this.onDataAdded = new EventEmitter(); this.onDataRemoved = new EventEmitter(); this.layerPosition = 1041; this.overlayVisible = false; this.openedClass = false; this.createFrom = 'html'; } ngOnInit() { if (!this.identifier || !this.identifier.length) { throw new Error('identifier field isn’t set. Please set one before calling <ngx-smart-modal> in a template.'); } this._sendEvent('create'); } ngAfterViewChecked() { if (this.overlayVisible && this.contentComponent && this.dynamicContentContainer && this.dynamicContentContainer.length === 0) { this.createDynamicContent(); } } ngOnDestroy() { this._sendEvent('delete'); } /** * Open the modal instance * * @param top open the modal top of all other * @returns the modal component */ open(top) { this._sendEvent('open', { top: top }); return this; } /** * Close the modal instance * * @returns the modal component */ close() { this._sendEvent('close'); return this; } /** * Dismiss the modal instance * * @param e the event sent by the browser * @returns the modal component */ dismiss(e) { if (!this.dismissable || !e?.target?.classList.contains('overlay')) { return this; } this._sendEvent('dismiss'); return this; } /** * Toggle visibility of the modal instance * * @param top open the modal top of all other * @returns the modal component */ toggle(top) { this._sendEvent('toggle', { top: top }); return this; } /** * Add a custom class to the modal instance * * @param className the class to add * @returns the modal component */ addCustomClass(className) { if (!this.customClass.length) { this.customClass = className; } else { this.customClass += ' ' + className; } return this; } /** * Remove a custom class to the modal instance * * @param className the class to remove * @returns the modal component */ removeCustomClass(className) { if (className) { this.customClass = this.customClass.replace(className, '').trim(); } else { this.customClass = ''; } return this; } /** * Returns the visibility state of the modal instance */ isVisible() { return this.visible; } /** * Checks if data is attached to the modal instance */ hasData() { return this._data !== undefined; } /** * Attach data to the modal instance * * @param data the data to attach * @param force override potentially attached data * @returns the modal component */ setData(data, force) { if (!this.hasData() || (this.hasData() && force)) { this._data = data; this.assignModalDataToComponentData(this._componentRef); this.onDataAdded.emit(this._data); this.markForCheck(); } return this; } /** * Retrieve the data attached to the modal instance */ getData() { this.assignComponentDataToModalData(this._componentRef); return this._data; } /** * Remove the data attached to the modal instance * * @returns the modal component */ removeData() { this._data = undefined; this.onDataRemoved.emit(true); this.markForCheck(); return this; } /** * Add body class modal opened * * @returns the modal component */ addBodyClass() { this._renderer.addClass(this._document.body, NgxSmartModalConfig.bodyClassOpen); return this; } /** * Add body class modal opened * * @returns the modal component */ removeBodyClass() { this._renderer.removeClass(this._document.body, NgxSmartModalConfig.bodyClassOpen); return this; } markForCheck() { try { this._changeDetectorRef.detectChanges(); } catch (e) { /* empty */ } this._changeDetectorRef.markForCheck(); } /** * Listens for window resize event and recalculates modal instance position if it is element-relative */ targetPlacement() { if (!this.isBrowser || !this.nsmDialog.length || !this.nsmContent.length || !this.nsmOverlay.length || !this.target) { return false; } const targetElement = this._document.querySelector(this.target); if (!targetElement) { return false; } const targetElementRect = targetElement.getBoundingClientRect(); const bodyRect = this.nsmOverlay.first.nativeElement.getBoundingClientRect(); const nsmContentRect = this.nsmContent.first.nativeElement.getBoundingClientRect(); const nsmDialogRect = this.nsmDialog.first.nativeElement.getBoundingClientRect(); const marginLeft = parseInt(getComputedStyle(this.nsmContent.first.nativeElement).marginLeft, 10); const marginTop = parseInt(getComputedStyle(this.nsmContent.first.nativeElement).marginTop, 10); let offsetTop = targetElementRect.top - nsmDialogRect.top - ((nsmContentRect.height - targetElementRect.height) / 2); let offsetLeft = targetElementRect.left - nsmDialogRect.left - ((nsmContentRect.width - targetElementRect.width) / 2); if (offsetLeft + nsmDialogRect.left + nsmContentRect.width + (marginLeft * 2) > bodyRect.width) { offsetLeft = bodyRect.width - (nsmDialogRect.left + nsmContentRect.width) - (marginLeft * 2); } else if (offsetLeft + nsmDialogRect.left < 0) { offsetLeft = -nsmDialogRect.left; } if (offsetTop + nsmDialogRect.top + nsmContentRect.height + marginTop > bodyRect.height) { offsetTop = bodyRect.height - (nsmDialogRect.top + nsmContentRect.height) - marginTop; } this._renderer.setStyle(this.nsmContent.first.nativeElement, 'top', (offsetTop < 0 ? 0 : offsetTop) + 'px'); this._renderer.setStyle(this.nsmContent.first.nativeElement, 'left', offsetLeft + 'px'); } _sendEvent(name, extraData) { if (!this.isBrowser) { return false; } const data = { extraData: extraData, instance: { id: this.identifier, modal: this } }; const event = new CustomEvent(NgxSmartModalConfig.prefixEvent + name, { detail: data }); return window.dispatchEvent(event); } /** * Is current platform browser */ get isBrowser() { return isPlatformBrowser(this._platformId); } /** * Creates content inside provided ViewContainerRef */ createDynamicContent() { this.dynamicContentContainer.clear(); this._componentRef = this.dynamicContentContainer.createComponent(this.contentComponent); this.assignModalDataToComponentData(this._componentRef); this.markForCheck(); } /** * Assigns the modal data to the ComponentRef instance properties */ assignModalDataToComponentData(componentRef) { if (componentRef) { Object.assign(componentRef.instance, this._data); } } /** * Assigns the ComponentRef instance properties to the modal data object */ assignComponentDataToModalData(componentRef) { if (componentRef) { Object.assign(this._data, componentRef.instance); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.10", ngImport: i0, type: NgxSmartModalComponent, deps: [{ token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i0.ViewContainerRef }, { token: i0.ElementRef }, { token: DOCUMENT }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.10", type: NgxSmartModalComponent, selector: "ngx-smart-modal", inputs: { closable: "closable", escapable: "escapable", dismissable: "dismissable", identifier: "identifier", customClass: "customClass", visible: "visible", backdrop: "backdrop", force: "force", hideDelay: "hideDelay", autostart: "autostart", target: "target", ariaLabel: "ariaLabel", ariaLabelledBy: "ariaLabelledBy", ariaDescribedBy: "ariaDescribedBy", refocus: "refocus" }, outputs: { visibleChange: "visibleChange", onClose: "onClose", onCloseFinished: "onCloseFinished", onDismiss: "onDismiss", onDismissFinished: "onDismissFinished", onAnyCloseEvent: "onAnyCloseEvent", onAnyCloseEventFinished: "onAnyCloseEventFinished", onOpen: "onOpen", onOpenFinished: "onOpenFinished", onEscape: "onEscape", onDataAdded: "onDataAdded", onDataRemoved: "onDataRemoved" }, host: { listeners: { "window:resize": "targetPlacement()" } }, viewQueries: [{ propertyName: "dynamicContentContainer", first: true, predicate: ["dynamicContent"], descendants: true, read: ViewContainerRef }, { propertyName: "nsmContent", predicate: ["nsmContent"], descendants: true }, { propertyName: "nsmDialog", predicate: ["nsmDialog"], descendants: true }, { propertyName: "nsmOverlay", predicate: ["nsmOverlay"], descendants: true }], ngImport: i0, template: ` <div *ngIf="overlayVisible" [style.z-index]="visible ? layerPosition-1 : -1" [ngClass]="{'transparent':!backdrop, 'overlay':true, 'nsm-overlay-open':openedClass}" (click)="dismiss($event)" #nsmOverlay> <div [style.z-index]="visible ? layerPosition : -1" [ngClass]="['nsm-dialog', customClass, openedClass ? 'nsm-dialog-open': 'nsm-dialog-close']" #nsmDialog [attr.aria-hidden]="openedClass ? false : true" [attr.aria-label]="ariaLabel" [attr.aria-labelledby]="ariaLabelledBy" [attr.aria-describedby]="ariaDescribedBy"> <div class="nsm-content" #nsmContent> <div class="nsm-body"> <ng-template #dynamicContent></ng-template> <ng-content></ng-content> </div> <button type="button" *ngIf="closable" (click)="close()" aria-label="Close" class="nsm-dialog-btn-close"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 512 512" xml:space="preserve" width="16px" height="16px" role="img" aria-labelledby="closeIconTitle closeIconDesc"> <title id="closeIconTitle">Close Icon</title> <desc id="closeIconDesc">A light-gray close icon used to close the modal</desc> <g> <path d="M505.943,6.058c-8.077-8.077-21.172-8.077-29.249,0L6.058,476.693c-8.077,8.077-8.077,21.172,0,29.249 C10.096,509.982,15.39,512,20.683,512c5.293,0,10.586-2.019,14.625-6.059L505.943,35.306 C514.019,27.23,514.019,14.135,505.943,6.058z" fill="currentColor"/> </g> <g> <path d="M505.942,476.694L35.306,6.059c-8.076-8.077-21.172-8.077-29.248,0c-8.077,8.076-8.077,21.171,0,29.248l470.636,470.636 c4.038,4.039,9.332,6.058,14.625,6.058c5.293,0,10.587-2.019,14.624-6.057C514.018,497.866,514.018,484.771,505.942,476.694z" fill="currentColor"/> </g> </svg> </button> </div> </div> </div> `, isInline: true, dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.10", ngImport: i0, type: NgxSmartModalComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-smart-modal', template: ` <div *ngIf="overlayVisible" [style.z-index]="visible ? layerPosition-1 : -1" [ngClass]="{'transparent':!backdrop, 'overlay':true, 'nsm-overlay-open':openedClass}" (click)="dismiss($event)" #nsmOverlay> <div [style.z-index]="visible ? layerPosition : -1" [ngClass]="['nsm-dialog', customClass, openedClass ? 'nsm-dialog-open': 'nsm-dialog-close']" #nsmDialog [attr.aria-hidden]="openedClass ? false : true" [attr.aria-label]="ariaLabel" [attr.aria-labelledby]="ariaLabelledBy" [attr.aria-describedby]="ariaDescribedBy"> <div class="nsm-content" #nsmContent> <div class="nsm-body"> <ng-template #dynamicContent></ng-template> <ng-content></ng-content> </div> <button type="button" *ngIf="closable" (click)="close()" aria-label="Close" class="nsm-dialog-btn-close"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 512 512" xml:space="preserve" width="16px" height="16px" role="img" aria-labelledby="closeIconTitle closeIconDesc"> <title id="closeIconTitle">Close Icon</title> <desc id="closeIconDesc">A light-gray close icon used to close the modal</desc> <g> <path d="M505.943,6.058c-8.077-8.077-21.172-8.077-29.249,0L6.058,476.693c-8.077,8.077-8.077,21.172,0,29.249 C10.096,509.982,15.39,512,20.683,512c5.293,0,10.586-2.019,14.625-6.059L505.943,35.306 C514.019,27.23,514.019,14.135,505.943,6.058z" fill="currentColor"/> </g> <g> <path d="M505.942,476.694L35.306,6.059c-8.076-8.077-21.172-8.077-29.248,0c-8.077,8.076-8.077,21.171,0,29.248l470.636,470.636 c4.038,4.039,9.332,6.058,14.625,6.058c5.293,0,10.587-2.019,14.624-6.057C514.018,497.866,514.018,484.771,505.942,476.694z" fill="currentColor"/> </g> </svg> </button> </div> </div> </div> ` }] }], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i0.ViewContainerRef }, { type: i0.ElementRef }, { type: Document, decorators: [{ type: Inject, args: [DOCUMENT] }] }, { type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID] }] }]; }, propDecorators: { closable: [{ type: Input }], escapable: [{ type: Input }], dismissable: [{ type: Input }], identifier: [{ type: Input }], customClass: [{ type: Input }], visible: [{ type: Input }], backdrop: [{ type: Input }], force: [{ type: Input }], hideDelay: [{ type: Input }], autostart: [{ type: Input }], target: [{ type: Input }], ariaLabel: [{ type: Input }], ariaLabelledBy: [{ type: Input }], ariaDescribedBy: [{ type: Input }], refocus: [{ type: Input }], visibleChange: [{ type: Output }], onClose: [{ type: Output }], onCloseFinished: [{ type: Output }], onDismiss: [{ type: Output }], onDismissFinished: [{ type: Output }], onAnyCloseEvent: [{ type: Output }], onAnyCloseEventFinished: [{ type: Output }], onOpen: [{ type: Output }], onOpenFinished: [{ type: Output }], onEscape: [{ type: Output }], onDataAdded: [{ type: Output }], onDataRemoved: [{ type: Output }], nsmContent: [{ type: ViewChildren, args: ['nsmContent'] }], nsmDialog: [{ type: ViewChildren, args: ['nsmDialog'] }], nsmOverlay: [{ type: ViewChildren, args: ['nsmOverlay'] }], dynamicContentContainer: [{ type: ViewChild, args: ['dynamicContent', { read: ViewContainerRef }] }], targetPlacement: [{ type: HostListener, args: ['window:resize'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXNtYXJ0LW1vZGFsLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zbWFydC1tb2RhbC9zcmMvbGliL2NvbXBvbmVudHMvbmd4LXNtYXJ0LW1vZGFsLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDOUQsT0FBTyxFQUdMLFNBQVMsRUFHVCxZQUFZLEVBQ1osWUFBWSxFQUNaLE1BQU0sRUFDTixLQUFLLEVBR0wsTUFBTSxFQUNOLFdBQVcsRUFJWCxTQUFTLEVBQ1QsWUFBWSxFQUNaLGdCQUFnQixFQUNqQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQzs7O0FBMEN2RSxNQUFNLE9BQU8sc0JBQXNCO0lBOENqQyxZQUNVLFNBQW9CLEVBQ3BCLGtCQUFxQyxFQUNyQyxpQkFBbUMsRUFDM0IsVUFBc0IsRUFDWixTQUFtQixFQUNoQixXQUFtQjtRQUx4QyxjQUFTLEdBQVQsU0FBUyxDQUFXO1FBQ3BCLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBbUI7UUFDckMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFrQjtRQUMzQixlQUFVLEdBQVYsVUFBVSxDQUFZO1FBQ1osY0FBUyxHQUFULFNBQVMsQ0FBVTtRQUNoQixnQkFBVyxHQUFYLFdBQVcsQ0FBUTtRQWxEbEMsYUFBUSxHQUFHLElBQUksQ0FBQztRQUNoQixjQUFTLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLGdCQUFXLEdBQUcsSUFBSSxDQUFDO1FBQ25CLGVBQVUsR0FBRyxFQUFFLENBQUM7UUFDaEIsZ0JBQVcsR0FBRywyQkFBMkIsQ0FBQztRQUMxQyxZQUFPLEdBQUcsS0FBSyxDQUFDO1FBQ2hCLGFBQVEsR0FBRyxJQUFJLENBQUM7UUFDaEIsVUFBSyxHQUFH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VSxXQUFXO3NCQUEzQixNQUFNO2dCQUNVLGFBQWE7c0JBQTdCLE1BQU07Z0JBWTZCLFVBQVU7c0JBQTdDLFlBQVk7dUJBQUMsWUFBWTtnQkFDUSxTQUFTO3NCQUExQyxZQUFZO3VCQUFDLFdBQVc7Z0JBQ1csVUFBVTtzQkFBN0MsWUFBWTt1QkFBQyxZQUFZO2dCQUN1Qyx1QkFBdUI7c0JBQXZGLFNBQVM7dUJBQUMsZ0JBQWdCLEVBQUUsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUU7Z0JBNE1oRCxlQUFlO3NCQURyQixZQUFZO3VCQUFDLGVBQWUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBET0NVTUVOVCwgaXNQbGF0Zm9ybUJyb3dzZXIgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3Q2hlY2tlZCxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgQ29tcG9uZW50UmVmLFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIEhvc3RMaXN0ZW5lcixcbiAgSW5qZWN0LFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgUExBVEZPUk1fSUQsXG4gIFF1ZXJ5TGlzdCxcbiAgUmVuZGVyZXIyLFxuICBUeXBlLFxuICBWaWV3Q2hpbGQsXG4gIFZpZXdDaGlsZHJlbixcbiAgVmlld0NvbnRhaW5lclJlZlxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE5neFNtYXJ0TW9kYWxDb25maWcgfSBmcm9tICcuLi9jb25maWcvbmd4LXNtYXJ0LW1vZGFsLmNvbmZpZyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1zbWFydC1tb2RhbCcsXG4gIHRlbXBsYXRlOiBgXG4gIDxkaXYgKm5nSWY9XCJvdmVybGF5VmlzaWJsZVwiXG4gICAgICAgW3N0eWxlLnotaW5kZXhdPVwidmlzaWJsZSA/IGxheWVyUG9zaXRpb24tMSA6IC0xXCJcbiAgICAgICBbbmdDbGFzc109XCJ7J3RyYW5zcGFyZW50JzohYmFja2Ryb3AsICdvdmVybGF5Jzp0cnVlLCAnbnNtLW92ZXJsYXktb3Blbic6b3BlbmVkQ2xhc3N9XCJcbiAgICAgICAoY2xpY2spPVwiZGlzbWlzcygkZXZlbnQpXCIgI25zbU92ZXJsYXk+XG4gICAgPGRpdiBbc3R5bGUuei1pbmRleF09XCJ2aXNpYmxlID8gbGF5ZXJQb3NpdGlvbiA6IC0xXCJcbiAgICAgICAgIFtuZ0NsYXNzXT1cIlsnbnNtLWRpYWxvZycsIGN1c3RvbUNsYXNzLCBvcGVuZWRDbGFzcyA/ICduc20tZGlhbG9nLW9wZW4nOiAnbnNtLWRpYWxvZy1jbG9zZSddXCIgI25zbURpYWxvZ1xuICAgICAgICAgW2F0dHIuYXJpYS1oaWRkZW5dPVwib3BlbmVkQ2xhc3MgPyBmYWxzZSA6IHRydWVcIlxuICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWxcIlxuICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbGxlZGJ5XT1cImFyaWFMYWJlbGxlZEJ5XCJcbiAgICAgICAgIFthdHRyLmFyaWEtZGVzY3JpYmVkYnldPVwiYXJpYURlc2NyaWJlZEJ5XCI+XG4gICAgICA8ZGl2IGNsYXNzPVwibnNtLWNvbnRlbnRcIiAjbnNtQ29udGVudD5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm5zbS1ib2R5XCI+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNkeW5hbWljQ29udGVudD48L25nLXRlbXBsYXRlPlxuICAgICAgICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiICpuZ0lmPVwiY2xvc2FibGVcIiAoY2xpY2spPVwiY2xvc2UoKVwiIGFyaWEtbGFiZWw9XCJDbG9zZVwiIGNsYXNzPVwibnNtLWRpYWxvZy1idG4tY2xvc2VcIj5cbiAgICAgICAgICA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB2ZXJzaW9uPVwiMS4xXCIgaWQ9XCJMYXllcl8xXCIgeD1cIjBweFwiIHk9XCIwcHhcIiB2aWV3Qm94PVwiMCAwIDUxMiA1MTJcIlxuICAgICAgICAgICAgICAgeG1sOnNwYWNlPVwicHJlc2VydmVcIiB3aWR0aD1cIjE2cHhcIiBoZWlnaHQ9XCIxNnB4XCIgcm9sZT1cImltZ1wiIGFyaWEtbGFiZWxsZWRieT1cImNsb3NlSWNvblRpdGxlIGNsb3NlSWNvbkRlc2NcIj5cbiAgICAgICAgICAgIDx0aXRsZSBpZD1cImNsb3NlSWNvblRpdGxlXCI+Q2xvc2UgSWNvbjwvdGl0bGU+XG4gICAgICAgICAgICA8ZGVzYyBpZD1cImNsb3NlSWNvbkRlc2NcIj5BIGxpZ2h0LWdyYXkgY2xvc2UgaWNvbiB1c2VkIHRvIGNsb3NlIHRoZSBtb2RhbDwvZGVzYz5cbiAgICAgICAgICAgIDxnPlxuICAgICAgICAgICAgICA8cGF0aCBkPVwiTTUwNS45NDMsNi4wNThjLTguMDc3LTguMDc3LTIxLjE3Mi04LjA3Ny0yOS4yNDksMEw2LjA1OCw0NzYuNjkzYy04LjA3Nyw4LjA3Ny04LjA3NywyMS4xNzIsMCwyOS4yNDkgICAgQzEwLjA5Niw1MDkuOTgyLDE1LjM5LDUxMiwyMC42ODMsNTEyYzUuMjkzLDAsMTAuNTg2LTIuMDE5LDE0LjYyNS02LjA1OUw1MDUuOTQzLDM1LjMwNiAgICBDNTE0LjAxOSwyNy4yMyw1MTQuMDE5LDE0LjEzNSw1MDUuOTQzLDYuMDU4elwiXG4gICAgICAgICAgICAgICAgICAgIGZpbGw9XCJjdXJyZW50Q29sb3JcIi8+XG4gICAgICAgICAgICA8L2c+XG4gICAgICAgICAgICA8Zz5cbiAgICAgICAgICAgICAgPHBhdGggZD1cIk01MDUuOTQyLDQ3Ni42OTRMMzUuMzA2LDYuMDU5Yy04LjA3Ni04LjA3Ny0yMS4xNzItOC4wNzctMjkuMjQ4LDBjLTguMDc3LDguMDc2LTguMDc3LDIxLjE3MSwwLDI5LjI0OGw0NzAuNjM2LDQ3MC42MzYgICAgYzQuMDM4LDQuMDM5LDkuMzMyLDYuMDU4LDE0LjYyNSw2LjA1OGM1LjI5MywwLDEwLjU4Ny0yLjAxOSwxNC42MjQtNi4wNTdDNTE0LjAxOCw0OTcuODY2LDUxNC4wMTgsNDg0Ljc3MSw1MDUuOTQyLDQ3Ni42OTR6XCJcbiAgICAgICAgICAgICAgICAgICAgZmlsbD1cImN1cnJlbnRDb2xvclwiLz5cbiAgICAgICAgICAgIDwvZz5cbiAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG5gLFxuICBzdHlsZXM6IFtcbiAgXVxufSlcbmV4cG9ydCBjbGFzcyBOZ3hTbWFydE1vZGFsQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIEFmdGVyVmlld0NoZWNrZWQge1xuXG4gIEBJbnB1dCgpIHB1YmxpYyBjbG9zYWJsZSA9IHRydWU7XG4gIEBJbnB1dCgpIHB1YmxpYyBlc2NhcGFibGUgPSB0cnVlO1xuICBASW5wdXQoKSBwdWJsaWMgZGlzbWlzc2FibGUgPSB0cnVlO1xuICBASW5wdXQoKSBwdWJsaWMgaWRlbnRpZmllciA9ICcnO1xuICBASW5wdXQoKSBwdWJsaWMgY3VzdG9tQ2xhc3MgPSAnbnNtLWRpYWxvZy1hbmltYXRpb24tZmFkZSc7XG4gIEBJbnB1dCgpIHB1YmxpYyB2aXNpYmxlID0gZmFsc2U7XG4gIEBJbnB1dCgpIHB1YmxpYyBiYWNrZHJvcCA9IHRydWU7XG4gIEBJbnB1dCgpIHB1YmxpYyBmb3JjZSA9IHRydWU7XG4gIEBJbnB1dCgpIHB1YmxpYyBoaWRlRGVsYXkgPSA1MDA7XG4gIEBJbnB1dCgpIHB1YmxpYyBhdXRvc3RhcnQgPSBmYWxzZTtcbiAgQElucHV0KCkgcHVibGljIHRhcmdldCA9ICcnO1xuICBASW5wdXQoKSBwdWJsaWMgYXJpYUxhYmVsOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgQElucHV0KCkgcHVibGljIGFyaWFMYWJlbGxlZEJ5OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgQElucHV0KCkgcHVibGljIGFyaWFEZXNjcmliZWRCeTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIEBJbnB1dCgpIHB1YmxpYyByZWZvY3VzID0gdHJ1ZTtcblxuICBAT3V0cHV0KCkgcHVibGljIHZpc2libGVDaGFuZ2U6IEV2ZW50RW1pdHRlcjxib29sZWFuPiA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcbiAgQE91dHB1dCgpIHB1YmxpYyBvbkNsb3NlOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHB1YmxpYyBvbkNsb3NlRmluaXNoZWQ6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgcHVibGljIG9uRGlzbWlzczogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBwdWJsaWMgb25EaXNtaXNzRmluaXNoZWQ6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgcHVibGljIG9uQW55Q2xvc2VFdmVudDogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBwdWJsaWMgb25BbnlDbG9zZUV2ZW50RmluaXNoZWQ6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgcHVibGljIG9uT3BlbjogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBwdWJsaWMgb25PcGVuRmluaXNoZWQ6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgcHVibGljIG9uRXNjYXBlOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHB1YmxpYyBvbkRhdGFBZGRlZDogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBwdWJsaWMgb25EYXRhUmVtb3ZlZDogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgcHVibGljIGNvbnRlbnRDb21wb25lbnQhOiBUeXBlPGFueT47XG4gIHB1YmxpYyBsYXllclBvc2l0aW9uID0gMTA0MTtcbiAgcHVibGljIG92ZXJsYXlWaXNpYmxlID0gZmFsc2U7XG4gIHB1YmxpYyBvcGVuZWRDbGFzcyA9IGZhbHNlO1xuXG4gIHB1YmxpYyBjcmVhdGVGcm9tID0gJ2h0bWwnO1xuXG4gIHByaXZhdGUgX2RhdGE6IGFueTtcbiAgcHJpdmF0ZSBfY29tcG9uZW50UmVmITogQ29tcG9uZW50UmVmPENvbXBvbmVudD47XG5cbiAgQFZpZXdDaGlsZHJlbignbnNtQ29udGVudCcpIHByaXZhdGUgbnNtQ29udGVudCE6IFF1ZXJ5TGlzdDxFbGVtZW50UmVmPjtcbiAgQFZpZXdDaGlsZHJlbignbnNtRGlhbG9nJykgcHVibGljIG5zbURpYWxvZyE6IFF1ZXJ5TGlzdDxFbGVtZW50UmVmPjtcbiAgQFZpZXdDaGlsZHJlbignbnNtT3ZlcmxheScpIHByaXZhdGUgbnNtT3ZlcmxheSE6IFF1ZXJ5TGlzdDxFbGVtZW50UmVmPjtcbiAgQFZpZXdDaGlsZCgnZHluYW1pY0NvbnRlbnQnLCB7IHJlYWQ6IFZpZXdDb250YWluZXJSZWYgfSkgcHJpdmF0ZSBkeW5hbWljQ29udGVudENvbnRhaW5lciE6IFZpZXdDb250YWluZXJSZWY7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfcmVuZGVyZXI6IFJlbmRlcmVyMixcbiAgICBwcml2YXRlIF9jaGFuZ2VEZXRlY3RvclJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgcHJpdmF0ZSBfdmlld0NvbnRhaW5lclJlZjogVmlld0NvbnRhaW5lclJlZixcbiAgICBwdWJsaWMgcmVhZG9ubHkgZWxlbWVudFJlZjogRWxlbWVudFJlZixcbiAgICBASW5qZWN0KERPQ1VNRU5UKSBwcml2YXRlIF9kb2N1bWVudDogRG9jdW1lbnQsXG4gICAgQEluamVjdChQTEFURk9STV9JRCkgcHJpdmF0ZSBfcGxhdGZvcm1JZDogb2JqZWN0LFxuICApIHsgfVxuXG4gIHB1YmxpYyBuZ09uSW5pdCgpIHtcbiAgICBpZiAoIXRoaXMuaWRlbnRpZmllciB8fCAhdGhpcy5pZGVudGlmaWVyLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpZGVudGlmaWVyIGZpZWxkIGlzbuKAmXQgc2V0LiBQbGVhc2Ugc2V0IG9uZSBiZWZvcmUgY2FsbGluZyA8bmd4LXNtYXJ0LW1vZGFsPiBpbiBhIHRlbXBsYXRlLicpO1xuICAgIH1cblxuICAgIHRoaXMuX3NlbmRFdmVudCgnY3JlYXRlJyk7XG4gIH1cblxuICBwdWJsaWMgbmdBZnRlclZpZXdDaGVja2VkKCkge1xuICAgIGlmIChcbiAgICAgIHRoaXMub3ZlcmxheVZpc2libGUgJiZcbiAgICAgIHRoaXMuY29udGVudENvbXBvbmVudCAmJlxuICAgICAgdGhpcy5keW5hbWljQ29udGVudENvbnRhaW5lciAmJlxuICAgICAgdGhpcy5keW5hbWljQ29udGVudENvbnRhaW5lci5sZW5ndGggPT09IDBcbiAgICApIHtcbiAgICAgIHRoaXMuY3JlYXRlRHluYW1pY0NvbnRlbnQoKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5fc2VuZEV2ZW50KCdkZWxldGUnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPcGVuIHRoZSBtb2RhbCBpbnN0YW5jZVxuICAgKlxuICAgKiBAcGFyYW0gdG9wIG9wZW4gdGhlIG1vZGFsIHRvcCBvZiBhbGwgb3RoZXJcbiAgICogQHJldHVybnMgdGhlIG1vZGFsIGNvbXBvbmVudFxuICAgKi9cbiAgcHVibGljIG9wZW4odG9wPzogYm9vbGVhbik6IE5neFNtYXJ0TW9kYWxDb21wb25lbnQge1xuICAgIHRoaXMuX3NlbmRFdmVudCgnb3BlbicsIHsgdG9wOiB0b3AgfSk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZSB0aGUgbW9kYWwgaW5zdGFuY2VcbiAgICpcbiAgICogQHJldHVybnMgdGhlIG1vZGFsIGNvbXBvbmVudFxuICAgKi9cbiAgcHVibGljIGNsb3NlKCk6IE5neFNtYXJ0TW9kYWxDb21wb25lbnQge1xuICAgIHRoaXMuX3NlbmRFdmVudCgnY2xvc2UnKTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc21pc3MgdGhlIG1vZGFsIGluc3RhbmNlXG4gICAqXG4gICAqIEBwYXJhbSBlIHRoZSBldmVudCBzZW50IGJ5IHRoZSBicm93c2VyXG4gICAqIEByZXR1cm5zIHRoZSBtb2RhbCBjb21wb25lbnRcbiAgICovXG4gIHB1YmxpYyBkaXNtaXNzKGU6IE1vdXNlRXZlbnQpOiBOZ3hTbWFydE1vZGFsQ29tcG9uZW50IHtcbiAgICBpZiAoIXRoaXMuZGlzbWlzc2FibGUgfHwgIShlPy50YXJnZXQgYXMgRWxlbWVudCk/LmNsYXNzTGlzdC5jb250YWlucygnb3ZlcmxheScpKSB7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICB0aGlzLl9zZW5kRXZlbnQoJ2Rpc21pc3MnKTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIFRvZ2dsZSB2aXNpYmlsaXR5IG9mIHRoZSBtb2RhbCBpbnN0YW5jZVxuICAgKlxuICAgKiBAcGFyYW0gdG9wIG9wZW4gdGhlIG1vZGFsIHRvcCBvZiBhbGwgb3RoZXJcbiAgICogQHJldHVybnMgdGhlIG1vZGFsIGNvbXBvbmVudFxuICAgKi9cbiAgcHVibGljIHRvZ2dsZSh0b3A/OiBib29sZWFuKTogTmd4U21hcnRNb2RhbENvbXBvbmVudCB7XG4gICAgdGhpcy5fc2VuZEV2ZW50KCd0b2dnbGUnLCB7IHRvcDogdG9wIH0pO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgY3VzdG9tIGNsYXNzIHRvIHRoZSBtb2RhbCBpbnN0YW5jZVxuICAgKlxuICAgKiBAcGFyYW0gY2xhc3NOYW1lIHRoZSBjbGFzcyB0byBhZGRcbiAgICogQHJldHVybnMgdGhlIG1vZGFsIGNvbXBvbmVudFxuICAgKi9cbiAgcHVibGljIGFkZEN1c3RvbUNsYXNzKGNsYXNzTmFtZTogc3RyaW5nKTogTmd4U21hcnRNb2RhbENvbXBvbmVudCB7XG4gICAgaWYgKCF0aGlzLmN1c3RvbUNsYXNzLmxlbmd0aCkge1xuICAgICAgdGhpcy5jdXN0b21DbGFzcyA9IGNsYXNzTmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5jdXN0b21DbGFzcyArPSAnICcgKyBjbGFzc05hbWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIGEgY3VzdG9tIGNsYXNzIHRvIHRoZSBtb2RhbCBpbnN0YW5jZVxuICAgKlxuICAgKiBAcGFyYW0gY2xhc3NOYW1lIHRoZSBjbGFzcyB0byByZW1vdmVcbiAgICogQHJldHVybnMgdGhlIG1vZGFsIGNvbXBvbmVudFxuICAgKi9cbiAgcHVibGljIHJlbW92ZUN1c3RvbUNsYXNzKGNsYXNzTmFtZT86IHN0cmluZyk6IE5neFNtYXJ0TW9kYWxDb21wb25lbnQge1xuICAgIGlmIChjbGFzc05hbWUpIHtcbiAgICAgIHRoaXMuY3VzdG9tQ2xhc3MgPSB0aGlzLmN1c3RvbUNsYXNzLnJlcGxhY2UoY2xhc3NOYW1lLCAnJykudHJpbSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmN1c3RvbUNsYXNzID0gJyc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgdmlzaWJpbGl0eSBzdGF0ZSBvZiB0aGUgbW9kYWwgaW5zdGFuY2VcbiAgICovXG4gIHB1YmxpYyBpc1Zpc2libGUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMudmlzaWJsZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgZGF0YSBpcyBhdHRhY2hlZCB0byB0aGUgbW9kYWwgaW5zdGFuY2VcbiAgICovXG4gIHB1YmxpYyBoYXNEYXRhKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9kYXRhICE9PSB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogQXR0YWNoIGRhdGEgdG8gdGhlIG1vZGFsIGluc3RhbmNlXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIHRoZSBkYXRhIHRvIGF0dGFjaFxuICAgKiBAcGFyYW0gZm9yY2Ugb3ZlcnJpZGUgcG90ZW50aWFsbHkgYXR0YWNoZWQgZGF0YVxuICAgKiBAcmV0dXJucyB0aGUgbW9kYWwgY29tcG9uZW50XG4gICAqL1xuICBwdWJsaWMgc2V0RGF0YShkYXRhOiB1bmtub3duLCBmb3JjZT86IGJvb2xlYW4pOiBOZ3hTbWFydE1vZGFsQ29tcG9uZW50IHtcbiAgICBpZiAoIXRoaXMuaGFzRGF0YSgpIHx8ICh0aGlzLmhhc0RhdGEoKSAmJiBmb3JjZSkpIHtcbiAgICAgIHRoaXMuX2RhdGEgPSBkYXRhO1xuICAgICAgdGhpcy5hc3NpZ25Nb2RhbERhdGFUb0NvbXBvbmVudERhdGEodGhpcy5fY29tcG9uZW50UmVmKTtcbiAgICAgIHRoaXMub25EYXRhQWRkZWQuZW1pdCh0aGlzLl9kYXRhKTtcbiAgICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmUgdGhlIGRhdGEgYXR0YWNoZWQgdG8gdGhlIG1vZGFsIGluc3RhbmNlXG4gICAqL1xuICBwdWJsaWMgZ2V0RGF0YSgpOiB1bmtub3duIHtcbiAgICB0aGlzLmFzc2lnbkNvbXBvbmVudERhdGFUb01vZGFsRGF0YSh0aGlzLl9jb21wb25lbnRSZWYpO1xuICAgIHJldHVybiB0aGlzLl9kYXRhO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZSB0aGUgZGF0YSBhdHRhY2hlZCB0byB0aGUgbW9kYWwgaW5zdGFuY2VcbiAgICpcbiAgICogQHJldHVybnMgdGhlIG1vZGFsIGNvbXBvbmVudFxuICAgKi9cbiAgcHVibGljIHJlbW92ZURhdGEoKTogTmd4U21hcnRNb2RhbENvbXBvbmVudCB7XG4gICAgdGhpcy5fZGF0YSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLm9uRGF0YVJlbW92ZWQuZW1pdCh0cnVlKTtcbiAgICB0aGlzLm1hcmtGb3JDaGVjaygpO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGJvZHkgY2xhc3MgbW9kYWwgb3BlbmVkXG4gICAqXG4gICAqIEByZXR1cm5zIHRoZSBtb2RhbCBjb21wb25lbnRcbiAgICovXG4gIHB1YmxpYyBhZGRCb2R5Q2xhc3MoKTogTmd4U21hcnRNb2RhbENvbXBvbmVudCB7XG4gICAgdGhpcy5fcmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5fZG9jdW1lbnQuYm9keSwgTmd4U21hcnRNb2RhbENvbmZpZy5ib2R5Q2xhc3NPcGVuKTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBib2R5IGNsYXNzIG1vZGFsIG9wZW5lZFxuICAgKlxuICAgKiBAcmV0dXJucyB0aGUgbW9kYWwgY29tcG9uZW50XG4gICAqL1xuICBwdWJsaWMgcmVtb3ZlQm9keUNsYXNzKCk6IE5neFNtYXJ0TW9kYWxDb21wb25lbnQge1xuICAgIHRoaXMuX3JlbmRlcmVyLnJlbW92ZUNsYXNzKHRoaXMuX2RvY3VtZW50LmJvZHksIE5neFNtYXJ0TW9kYWxDb25maWcuYm9keUNsYXNzT3Blbik7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHB1YmxpYyBtYXJrRm9yQ2hlY2soKSB7XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuX2NoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcbiAgICB9IGNhdGNoIChlKSB7IC8qIGVtcHR5ICovIH1cblxuICAgIHRoaXMuX2NoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3RlbnMgZm9yIHdpbmRvdyByZXNpemUgZXZlbnQgYW5kIHJlY2FsY3VsYXRlcyBtb2RhbCBpbnN0YW5jZSBwb3NpdGlvbiBpZiBpdCBpcyBlbGVtZW50LXJlbGF0aXZlXG4gICAqL1xuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6cmVzaXplJylcbiAgcHVibGljIHRhcmdldFBsYWNlbWVudCgpOiBib29sZWFuIHwgdm9pZCB7XG4gICAgaWYgKCF0aGlzLmlzQnJvd3NlciB8fCAhdGhpcy5uc21EaWFsb2cubGVuZ3RoIHx8ICF0aGlzLm5zbUNvbnRlbnQubGVuZ3RoIHx8ICF0aGlzLm5zbU92ZXJsYXkubGVuZ3RoIHx8ICF0aGlzLnRhcmdldCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCB0YXJnZXRFbGVtZW50ID0gdGhpcy5fZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0aGlzLnRhcmdldCk7XG5cbiAgICBpZiAoIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCB0YXJnZXRFbGVtZW50UmVjdCA9IHRhcmdldEVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgY29uc3QgYm9keVJlY3QgPSB0aGlzLm5zbU92ZXJsYXkuZmlyc3QubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgIGNvbnN0IG5zbUNvbnRlbnRSZWN0ID0gdGhpcy5uc21Db250ZW50LmZpcnN0Lm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgY29uc3QgbnNtRGlhbG9nUmVjdCA9IHRoaXMubnNtRGlhbG9nLmZpcnN0Lm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICBjb25zdCBtYXJnaW5MZWZ0ID0gcGFyc2VJbnQoZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzLm5zbUNvbnRlbnQuZmlyc3QubmF0aXZlRWxlbWVudCkubWFyZ2luTGVmdCwgMTApO1xuICAgIGNvbnN0IG1hcmdpblRvcCA9IHBhcnNlSW50KGdldENvbXB1dGVkU3R5bGUodGhpcy5uc21Db250ZW50LmZpcnN0Lm5hdGl2ZUVsZW1lbnQpLm1hcmdpblRvcCwgMTApO1xuXG4gICAgbGV0IG9mZnNldFRvcCA9IHRhcmdldEVsZW1lbnRSZWN0LnRvcCAtIG5zbURpYWxvZ1JlY3QudG9wIC0gKChuc21Db250ZW50UmVjdC5oZWlnaHQgLSB0YXJnZXRFbGVtZW50UmVjdC5oZWlnaHQpIC8gMik7XG4gICAgbGV0IG9mZnNldExlZnQgPSB0YXJnZXRFbGVtZW50UmVjdC5sZWZ0IC0gbnNtRGlhbG9nUmVjdC5sZWZ0IC0gKChuc21Db250ZW50UmVjdC53aWR0aCAtIHRhcmdldEVsZW1lbnRSZWN0LndpZHRoKSAvIDIpO1xuXG4gICAgaWYgKG9mZnNldExlZnQgKyBuc21EaWFsb2dSZWN0LmxlZnQgKyBuc21Db250ZW50UmVjdC53aWR0aCArIChtYXJnaW5MZWZ0ICogMikgPiBib2R5UmVjdC53aWR0aCkge1xuICAgICAgb2Zmc2V0TGVmdCA9IGJvZHlSZWN0LndpZHRoIC0gKG5zbURpYWxvZ1JlY3QubGVmdCArIG5zbUNvbnRlbnRSZWN0LndpZHRoKSAtIChtYXJnaW5MZWZ0ICogMik7XG4gICAgfSBlbHNlIGlmIChvZmZzZXRMZWZ0ICsgbnNtRGlhbG9nUmVjdC5sZWZ0IDwgMCkge1xuICAgICAgb2Zmc2V0TGVmdCA9IC1uc21EaWFsb2dSZWN0LmxlZnQ7XG4gICAgfVxuXG4gICAgaWYgKG9mZnNldFRvcCArIG5zbURpYWxvZ1JlY3QudG9wICsgbnNtQ29udGVudFJlY3QuaGVpZ2h0ICsgbWFyZ2luVG9wID4gYm9keVJlY3QuaGVpZ2h0KSB7XG4gICAgICBvZmZzZXRUb3AgPSBib2R5UmVjdC5oZWlnaHQgLSAobnNtRGlhbG9nUmVjdC50b3AgKyBuc21Db250ZW50UmVjdC5oZWlnaHQpIC0gbWFyZ2luVG9wO1xuICAgIH1cblxuICAgIHRoaXMuX3JlbmRlcmVyLnNldFN0eWxlKHRoaXMubnNtQ29udGVudC5maXJzdC5uYXRpdmVFbGVtZW50LCAndG9wJywgKG9mZnNldFRvcCA8IDAgPyAwIDogb2Zmc2V0VG9wKSArICdweCcpO1xuICAgIHRoaXMuX3JlbmRlcmVyLnNldFN0eWxlKHRoaXMubnNtQ29udGVudC5maXJzdC5uYXRpdmVFbGVtZW50LCAnbGVmdCcsIG9mZnNldExlZnQgKyAncHgnKTtcbiAgfVxuXG4gIHByaXZhdGUgX3NlbmRFdmVudChuYW1lOiBzdHJpbmcsIGV4dHJhRGF0YT86IHVua25vd24pOiBib29sZWFuIHtcbiAgICBpZiAoIXRoaXMuaXNCcm93c2VyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgZGF0YSA9IHtcbiAgICAgIGV4dHJhRGF0YTogZXh0cmFEYXRhLFxuICAgICAgaW5zdGFuY2U6IHsgaWQ6IHRoaXMuaWRlbnRpZmllciwgbW9kYWw6IHRoaXMgfVxuICAgIH07XG5cbiAgICBjb25zdCBldmVudCA9IG5ldyBDdXN0b21FdmVudChOZ3hTbWFydE1vZGFsQ29uZmlnLnByZWZpeEV2ZW50ICsgbmFtZSwgeyBkZXRhaWw6IGRhdGEgfSk7XG5cbiAgICByZXR1cm4gd2luZG93LmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIElzIGN1cnJlbnQgcGxhdGZvcm0gYnJvd3NlclxuICAgKi9cbiAgcHJpdmF0ZSBnZXQgaXNCcm93c2VyKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLl9wbGF0Zm9ybUlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGNvbnRlbnQgaW5zaWRlIHByb3ZpZGVkIFZpZXdDb250YWluZXJSZWZcbiAgICovXG4gIHByaXZhdGUgY3JlYXRlRHluYW1pY0NvbnRlbnQoKTogdm9pZCB7XG4gICAgdGhpcy5keW5hbWljQ29udGVudENvbnRhaW5lci5jbGVhcigpO1xuICAgIHRoaXMuX2NvbXBvbmVudFJlZiA9IHRoaXMuZHluYW1pY0NvbnRlbnRDb250YWluZXIuY3JlYXRlQ29tcG9uZW50KHRoaXMuY29udGVudENvbXBvbmVudCk7XG4gICAgdGhpcy5hc3NpZ25Nb2RhbERhdGFUb0NvbXBvbmVudERhdGEodGhpcy5fY29tcG9uZW50UmVmKTtcbiAgICB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFzc2lnbnMgdGhlIG1vZGFsIGRhdGEgdG8gdGhlIENvbXBvbmVudFJlZiBpbnN0YW5jZSBwcm9wZXJ0aWVzXG4gICAqL1xuICBwcml2YXRlIGFzc2lnbk1vZGFsRGF0YVRvQ29tcG9uZW50RGF0YShjb21wb25lbnRSZWY6IENvbXBvbmVudFJlZjxDb21wb25lbnQ+KTogdm9pZCB7XG4gICAgaWYgKGNvbXBvbmVudFJlZikge1xuICAgICAgT2JqZWN0LmFzc2lnbihjb21wb25lbnRSZWYuaW5zdGFuY2UsIHRoaXMuX2RhdGEpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBc3NpZ25zIHRoZSBDb21wb25lbnRSZWYgaW5zdGFuY2UgcHJvcGVydGllcyB0byB0aGUgbW9kYWwgZGF0YSBvYmplY3RcbiAgICovXG4gIHByaXZhdGUgYXNzaWduQ29tcG9uZW50RGF0YVRvTW9kYWxEYXRhKGNvbXBvbmVudFJlZjogQ29tcG9uZW50UmVmPENvbXBvbmVudD4pOiB2b2lkIHtcbiAgICBpZiAoY29tcG9uZW50UmVmKSB7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMuX2RhdGEsIGNvbXBvbmVudFJlZi5pbnN0YW5jZSk7XG4gICAgfVxuICB9XG5cbn1cbiJdfQ==