ngx-extended-pdf-viewer
Version:
Embedding PDF files in your Angular application. Highly configurable viewer including the toolbar, sidebar, and all the features you're used to.
179 lines • 30.4 kB
JavaScript
import { isPlatformBrowser } from '@angular/common';
import { Component, EventEmitter, HostListener, Inject, Input, Output, PLATFORM_ID, } from '@angular/core';
import { take } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "./../../pdf-notification-service";
import * as i2 from "../../toolbar/pdf-shy-button/pdf-shy-button-service";
import * as i3 from "../../ngx-extended-pdf-viewer.service";
import * as i4 from "@angular/common";
import * as i5 from "../../responsive-visibility";
export class PdfSecondaryToolbarComponent {
element;
notificationService;
platformId;
pdfShyButtonService;
ngxExtendedPdfViewerService;
customSecondaryToolbar;
secondaryToolbarTop;
mobileFriendlyZoomScale;
localizationInitialized;
spreadChange = new EventEmitter();
disablePreviousPage = true;
disableNextPage = true;
classMutationObserver;
constructor(element, notificationService, platformId, pdfShyButtonService, ngxExtendedPdfViewerService) {
this.element = element;
this.notificationService = notificationService;
this.platformId = platformId;
this.pdfShyButtonService = pdfShyButtonService;
this.ngxExtendedPdfViewerService = ngxExtendedPdfViewerService;
this.notificationService.onPDFJSInit.pipe(take(1)).subscribe(() => {
this.onPdfJsInit();
});
}
onPdfJsInit() {
const PDFViewerApplication = window.PDFViewerApplication;
PDFViewerApplication.eventBus.on('pagechanging', () => {
this.updateUIState();
});
PDFViewerApplication.eventBus.on('pagerendered', () => {
this.updateUIState();
});
}
updateUIState() {
setTimeout(() => {
const PDFViewerApplication = window.PDFViewerApplication;
const currentPage = PDFViewerApplication.pdfViewer.currentPageNumber;
const previousButton = document.getElementById('previousPage');
if (previousButton) {
this.disablePreviousPage = Number(currentPage) <= 1;
previousButton.disabled = this.disablePreviousPage;
}
const nextButton = document.getElementById('nextPage');
if (nextButton) {
this.disableNextPage = currentPage === PDFViewerApplication.pagesCount;
nextButton.disabled = this.disableNextPage;
}
});
}
onSpreadChange(newSpread) {
this.spreadChange.emit(newSpread);
}
ngOnChanges(changes) {
setTimeout(() => this.checkVisibility());
}
onResize() {
setTimeout(() => this.checkVisibility());
}
ngAfterViewInit() {
if (isPlatformBrowser(this.platformId)) {
const targetNode = this.element.nativeElement;
const config = { attributes: true, childList: true, subtree: true };
this.classMutationObserver = new MutationObserver((mutationList, observer) => {
for (const mutation of mutationList) {
if (mutation.type === 'attributes') {
if (mutation.attributeName === 'class') {
this.checkVisibility();
break;
}
}
else if (mutation.type === 'childList') {
this.checkVisibility();
break;
}
}
});
this.classMutationObserver.observe(targetNode, config);
}
}
ngOnDestroy() {
if (this.classMutationObserver) {
this.classMutationObserver.disconnect();
this.classMutationObserver = undefined;
}
}
checkVisibility() {
let visibleButtons = 0;
const e = this.element.nativeElement;
const f = e.children.item(0);
if (f) {
const g = f.children.item(0);
if (g && g instanceof HTMLElement) {
visibleButtons = this.checkVisibilityRecursively(g);
}
}
this.ngxExtendedPdfViewerService.secondaryMenuIsEmpty = visibleButtons === 0;
}
checkVisibilityRecursively(e) {
if (typeof window === 'undefined') {
// server-side rendering
return 0;
}
if (e.style.display === 'none') {
return 0;
}
if (e.classList.contains('hidden')) {
return 0;
}
if (e.classList.contains('invisible')) {
return 0;
}
const style = window.getComputedStyle(e);
if (style.display === 'none') {
return 0;
}
if (e instanceof HTMLButtonElement || e instanceof HTMLAnchorElement) {
return 1;
}
let count = 0;
const children = e.children;
if (children?.length) {
for (let i = 0; i < children.length && count === 0; i++) {
const child = children.item(i);
if (child && child instanceof HTMLElement) {
count += this.checkVisibilityRecursively(child);
}
}
}
return count;
}
onClick(htmlevent, action, eventBusName, closeOnClick) {
const PDFViewerApplication = window.PDFViewerApplication;
const origin = htmlevent.target;
origin?.classList.add('toggled');
if (action) {
action(htmlevent, true);
htmlevent.preventDefault();
}
else if (eventBusName) {
PDFViewerApplication.eventBus.dispatch(eventBusName);
htmlevent.preventDefault();
}
if (closeOnClick) {
PDFViewerApplication.secondaryToolbar.close();
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: PdfSecondaryToolbarComponent, deps: [{ token: i0.ElementRef }, { token: i1.PDFNotificationService }, { token: PLATFORM_ID }, { token: i2.PdfShyButtonService }, { token: i3.NgxExtendedPdfViewerService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.9", type: PdfSecondaryToolbarComponent, selector: "pdf-secondary-toolbar", inputs: { customSecondaryToolbar: "customSecondaryToolbar", secondaryToolbarTop: "secondaryToolbarTop", mobileFriendlyZoomScale: "mobileFriendlyZoomScale", localizationInitialized: "localizationInitialized" }, outputs: { spreadChange: "spreadChange" }, host: { listeners: { "window:resize": "onResize()" } }, usesOnChanges: true, ngImport: i0, template: "<ng-container [ngTemplateOutlet]=\"customSecondaryToolbar ? customSecondaryToolbar : defaultSecondaryToolbar\"> </ng-container>\n\n<ng-template #defaultSecondaryToolbar>\n <div\n id=\"secondaryToolbar\"\n class=\"secondaryToolbar hidden doorHangerRight\"\n [style.top]=\"secondaryToolbarTop\"\n [style.transform]=\"'scale(' + mobileFriendlyZoomScale + ')'\"\n [style.transformOrigin]=\"'right top'\"\n >\n <div id=\"secondaryToolbarButtonContainer\">\n <button\n *ngFor=\"let button of pdfShyButtonService.buttons\"\n type=\"button\"\n [id]=\"button.id\"\n [ngClass]=\"button.cssClass | invertForSecondaryToolbar\"\n [class.toggled]=\"button.toggled\"\n class=\"secondaryToolbarButton\"\n [title]=\"button.title\"\n [attr.data-l10n-id]=\"button.l10nId\"\n (click)=\"onClick($event, button.action, button.eventBusName, button.closeOnClick)\"\n [attr.aria-label]=\"button.title\"\n role=\"button\"\n >\n <span class=\"icon\" role=\"img\" aria-hidden=\"true\" [attr.aria-label]=\"button.title\" *ngIf=\"button.image\" [innerHTML]=\"button.image\"></span>\n <span class=\"toolbar-caption\" [attr.data-l10n-id]=\"button.l10nLabel\">{{ button.title }}</span>\n </button>\n </div>\n </div>\n</ng-template>\n", styles: ["svg{position:absolute;display:inline-block;top:0;left:0}.secondaryToolbarButton{display:inline-flex;align-items:center;justify-content:flex-start;border:0 none;background:none;width:calc(100% - 4px);height:25px;position:relative;margin:0 0 4px;padding:3px 0 1px;min-height:25px;white-space:normal}.secondaryToolbarButton span{display:inline-block}.secondaryToolbarButton[disabled]{opacity:.5}::ng-deep html[dir=ltr] ngx-extended-pdf-viewer .secondaryToolbarButton{padding-left:4px;text-align:left}::ng-deep html[dir=rtl] ngx-extended-pdf-viewer .secondaryToolbarButton{padding-right:4px;text-align:right}::ng-deep html[dir=ltr] ngx-extended-pdf-viewer .secondaryToolbarButton>span{padding-right:4px}::ng-deep html[dir=rtl] ngx-extended-pdf-viewer .secondaryToolbarButton>span{padding-left:4px}.secondaryToolbar{height:auto;z-index:3000}::ng-deep html[dir=ltr] ngx-extended-pdf-viewer .secondaryToolbar{right:4px}::ng-deep [dir=rtl] ngx-extended-pdf-viewer .secondaryToolbar{left:4px}#secondaryToolbarButtonContainer{width:250px;max-height:775px;overflow-y:auto;-webkit-overflow-scrolling:touch}.toolbar-caption{position:relative;top:-3px}.icon{width:24px}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i5.NegativeResponsiveCSSClassPipe, name: "invertForSecondaryToolbar" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: PdfSecondaryToolbarComponent, decorators: [{
type: Component,
args: [{ selector: 'pdf-secondary-toolbar', template: "<ng-container [ngTemplateOutlet]=\"customSecondaryToolbar ? customSecondaryToolbar : defaultSecondaryToolbar\"> </ng-container>\n\n<ng-template #defaultSecondaryToolbar>\n <div\n id=\"secondaryToolbar\"\n class=\"secondaryToolbar hidden doorHangerRight\"\n [style.top]=\"secondaryToolbarTop\"\n [style.transform]=\"'scale(' + mobileFriendlyZoomScale + ')'\"\n [style.transformOrigin]=\"'right top'\"\n >\n <div id=\"secondaryToolbarButtonContainer\">\n <button\n *ngFor=\"let button of pdfShyButtonService.buttons\"\n type=\"button\"\n [id]=\"button.id\"\n [ngClass]=\"button.cssClass | invertForSecondaryToolbar\"\n [class.toggled]=\"button.toggled\"\n class=\"secondaryToolbarButton\"\n [title]=\"button.title\"\n [attr.data-l10n-id]=\"button.l10nId\"\n (click)=\"onClick($event, button.action, button.eventBusName, button.closeOnClick)\"\n [attr.aria-label]=\"button.title\"\n role=\"button\"\n >\n <span class=\"icon\" role=\"img\" aria-hidden=\"true\" [attr.aria-label]=\"button.title\" *ngIf=\"button.image\" [innerHTML]=\"button.image\"></span>\n <span class=\"toolbar-caption\" [attr.data-l10n-id]=\"button.l10nLabel\">{{ button.title }}</span>\n </button>\n </div>\n </div>\n</ng-template>\n", styles: ["svg{position:absolute;display:inline-block;top:0;left:0}.secondaryToolbarButton{display:inline-flex;align-items:center;justify-content:flex-start;border:0 none;background:none;width:calc(100% - 4px);height:25px;position:relative;margin:0 0 4px;padding:3px 0 1px;min-height:25px;white-space:normal}.secondaryToolbarButton span{display:inline-block}.secondaryToolbarButton[disabled]{opacity:.5}::ng-deep html[dir=ltr] ngx-extended-pdf-viewer .secondaryToolbarButton{padding-left:4px;text-align:left}::ng-deep html[dir=rtl] ngx-extended-pdf-viewer .secondaryToolbarButton{padding-right:4px;text-align:right}::ng-deep html[dir=ltr] ngx-extended-pdf-viewer .secondaryToolbarButton>span{padding-right:4px}::ng-deep html[dir=rtl] ngx-extended-pdf-viewer .secondaryToolbarButton>span{padding-left:4px}.secondaryToolbar{height:auto;z-index:3000}::ng-deep html[dir=ltr] ngx-extended-pdf-viewer .secondaryToolbar{right:4px}::ng-deep [dir=rtl] ngx-extended-pdf-viewer .secondaryToolbar{left:4px}#secondaryToolbarButtonContainer{width:250px;max-height:775px;overflow-y:auto;-webkit-overflow-scrolling:touch}.toolbar-caption{position:relative;top:-3px}.icon{width:24px}\n"] }]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.PDFNotificationService }, { type: Object, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }, { type: i2.PdfShyButtonService }, { type: i3.NgxExtendedPdfViewerService }], propDecorators: { customSecondaryToolbar: [{
type: Input
}], secondaryToolbarTop: [{
type: Input
}], mobileFriendlyZoomScale: [{
type: Input
}], localizationInitialized: [{
type: Input
}], spreadChange: [{
type: Output
}], onResize: [{
type: HostListener,
args: ['window:resize']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGRmLXNlY29uZGFyeS10b29sYmFyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1leHRlbmRlZC1wZGYtdmlld2VyL3NyYy9saWIvc2Vjb25kYXJ5LXRvb2xiYXIvcGRmLXNlY29uZGFyeS10b29sYmFyL3BkZi1zZWNvbmRhcnktdG9vbGJhci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZXh0ZW5kZWQtcGRmLXZpZXdlci9zcmMvbGliL3NlY29uZGFyeS10b29sYmFyL3BkZi1zZWNvbmRhcnktdG9vbGJhci9wZGYtc2Vjb25kYXJ5LXRvb2xiYXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDcEQsT0FBTyxFQUVMLFNBQVMsRUFFVCxZQUFZLEVBQ1osWUFBWSxFQUNaLE1BQU0sRUFDTixLQUFLLEVBR0wsTUFBTSxFQUNOLFdBQVcsR0FHWixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7Ozs7QUFXdEMsTUFBTSxPQUFPLDRCQUE0QjtJQXVCN0I7SUFDRDtJQUNzQjtJQUN0QjtJQUNDO0lBekJILHNCQUFzQixDQUErQjtJQUdyRCxtQkFBbUIsQ0FBQztJQUdwQix1QkFBdUIsQ0FBUztJQUdoQyx1QkFBdUIsQ0FBVTtJQUdqQyxZQUFZLEdBQUcsSUFBSSxZQUFZLEVBQTBCLENBQUM7SUFFMUQsbUJBQW1CLEdBQUcsSUFBSSxDQUFDO0lBRTNCLGVBQWUsR0FBRyxJQUFJLENBQUM7SUFFdEIscUJBQXFCLENBQStCO0lBRTVELFlBQ1UsT0FBbUIsRUFDcEIsbUJBQTJDLEVBQ3JCLFVBQWtCLEVBQ3hDLG1CQUF3QyxFQUN2QywyQkFBd0Q7UUFKeEQsWUFBTyxHQUFQLE9BQU8sQ0FBWTtRQUNwQix3QkFBbUIsR0FBbkIsbUJBQW1CLENBQXdCO1FBQ3JCLGVBQVUsR0FBVixVQUFVLENBQVE7UUFDeEMsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFxQjtRQUN2QyxnQ0FBMkIsR0FBM0IsMkJBQTJCLENBQTZCO1FBRWhFLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7WUFDaEUsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ3JCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLFdBQVc7UUFDaEIsTUFBTSxvQkFBb0IsR0FBMkIsTUFBYyxDQUFDLG9CQUFvQixDQUFDO1FBQ3pGLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsY0FBYyxFQUFFLEdBQUcsRUFBRTtZQUNwRCxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDdkIsQ0FBQyxDQUFDLENBQUM7UUFDSCxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLGNBQWMsRUFBRSxHQUFHLEVBQUU7WUFDcEQsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ3ZCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLGFBQWE7UUFDbEIsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUNkLE1BQU0sb0JBQW9CLEdBQTJCLE1BQWMsQ0FBQyxvQkFBb0IsQ0FBQztZQUN6RixNQUFNLFdBQVcsR0FBRyxvQkFBb0IsQ0FBQyxTQUFTLENBQUMsaUJBQWlCLENBQUM7WUFDckUsTUFBTSxjQUFjLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxjQUFjLENBQXNCLENBQUM7WUFDcEYsSUFBSSxjQUFjLEVBQUU7Z0JBQ2xCLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNwRCxjQUFjLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQzthQUNwRDtZQUNELE1BQU0sVUFBVSxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFzQixDQUFDO1lBQzVFLElBQUksVUFBVSxFQUFFO2dCQUNkLElBQUksQ0FBQyxlQUFlLEdBQUcsV0FBVyxLQUFLLG9CQUFvQixDQUFDLFVBQVUsQ0FBQztnQkFDdkUsVUFBVSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDO2FBQzVDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU0sY0FBYyxDQUFDLFNBQWlDO1FBQ3JELElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFTSxXQUFXLENBQUMsT0FBc0I7UUFDdkMsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFHTSxRQUFRO1FBQ2IsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFTSxlQUFlO1FBQ3BCLElBQUksaUJBQWlCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1lBQ3RDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBNEIsQ0FBQztZQUU3RCxNQUFNLE1BQU0sR0FBRyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUM7WUFFcEUsSUFBSSxDQUFDLHFCQUFxQixHQUFHLElBQUksZ0JBQWdCLENBQUMsQ0FBQyxZQUE4QixFQUFFLFFBQVEsRUFBRSxFQUFFO2dCQUM3RixLQUFLLE1BQU0sUUFBUSxJQUFJLFlBQVksRUFBRTtvQkFDbkMsSUFBSSxRQUFRLENBQUMsSUFBSSxLQUFLLFlBQVksRUFBRTt3QkFDbEMsSUFBSSxRQUFRLENBQUMsYUFBYSxLQUFLLE9BQU8sRUFBRTs0QkFDdEMsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDOzRCQUN2QixNQUFNO3lCQUNQO3FCQUNGO3lCQUFNLElBQUksUUFBUSxDQUFDLElBQUksS0FBSyxXQUFXLEVBQUU7d0JBQ3hDLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQzt3QkFDdkIsTUFBTTtxQkFDUDtpQkFDRjtZQUNILENBQUMsQ0FBQyxDQUFDO1lBRUgsSUFBSSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLENBQUM7U0FDeEQ7SUFDSCxDQUFDO0lBRU0sV0FBVztRQUNoQixJQUFJLElBQUksQ0FBQyxxQkFBcUIsRUFBRTtZQUM5QixJQUFJLENBQUMscUJBQXFCLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDeEMsSUFBSSxDQUFDLHFCQUFxQixHQUFHLFNBQVMsQ0FBQztTQUN4QztJQUNILENBQUM7SUFFTSxlQUFlO1FBQ3BCLElBQUksY0FBYyxHQUFHLENBQUMsQ0FBQztRQUN2QixNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQTRCLENBQUM7UUFDcEQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0IsSUFBSSxDQUFDLEVBQUU7WUFDTCxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM3QixJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksV0FBVyxFQUFFO2dCQUNqQyxjQUFjLEdBQUcsSUFBSSxDQUFDLDBCQUEwQixDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ3JEO1NBQ0Y7UUFDRCxJQUFJLENBQUMsMkJBQTJCLENBQUMsb0JBQW9CLEdBQUcsY0FBYyxLQUFLLENBQUMsQ0FBQztJQUMvRSxDQUFDO0lBRU8sMEJBQTBCLENBQUMsQ0FBYztRQUMvQyxJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVcsRUFBRTtZQUNqQyx3QkFBd0I7WUFDeEIsT0FBTyxDQUFDLENBQUM7U0FDVjtRQUNELElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLEtBQUssTUFBTSxFQUFFO1lBQzlCLE9BQU8sQ0FBQyxDQUFDO1NBQ1Y7UUFDRCxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxFQUFFO1lBQ2xDLE9BQU8sQ0FBQyxDQUFDO1NBQ1Y7UUFDRCxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxFQUFFO1lBQ3JDLE9BQU8sQ0FBQyxDQUFDO1NBQ1Y7UUFFRCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDekMsSUFBSSxLQUFLLENBQUMsT0FBTyxLQUFLLE1BQU0sRUFBRTtZQUM1QixPQUFPLENBQUMsQ0FBQztTQUNWO1FBRUQsSUFBSSxDQUFDLFlBQVksaUJBQWlCLElBQUksQ0FBQyxZQUFZLGlCQUFpQixFQUFFO1lBQ3BFLE9BQU8sQ0FBQyxDQUFDO1NBQ1Y7UUFDRCxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7UUFDZCxNQUFNLFFBQVEsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDO1FBQzVCLElBQUksUUFBUSxFQUFFLE1BQU0sRUFBRTtZQUNwQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sSUFBSSxLQUFLLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO2dCQUN2RCxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUMvQixJQUFJLEtBQUssSUFBSSxLQUFLLFlBQVksV0FBVyxFQUFFO29CQUN6QyxLQUFLLElBQUksSUFBSSxDQUFDLDBCQUEwQixDQUFDLEtBQUssQ0FBQyxDQUFDO2lCQUNqRDthQUNGO1NBQ0Y7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFTSxPQUFPLENBQ1osU0FBZ0IsRUFDaEIsTUFBMkUsRUFDM0UsWUFBcUIsRUFDckIsWUFBc0I7UUFFdEIsTUFBTSxvQkFBb0IsR0FBMkIsTUFBYyxDQUFDLG9CQUFvQixDQUFDO1FBQ3pGLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxNQUFxQixDQUFDO1FBQy9DLE1BQU0sRUFBRSxTQUFTLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ2pDLElBQUksTUFBTSxFQUFFO1lBQ1YsTUFBTSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUN4QixTQUFTLENBQUMsY0FBYyxFQUFFLENBQUM7U0FDNUI7YUFBTSxJQUFJLFlBQVksRUFBRTtZQUN2QixvQkFBb0IsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3JELFNBQVMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztTQUM1QjtRQUNELElBQUksWUFBWSxFQUFFO1lBQ2hCLG9CQUFvQixDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxDQUFDO1NBQy9DO0lBQ0gsQ0FBQzt1R0E3S1UsNEJBQTRCLGtGQXlCN0IsV0FBVzsyRkF6QlYsNEJBQTRCLHVZQzNCekMsb3pDQThCQTs7MkZESGEsNEJBQTRCO2tCQUx4QyxTQUFTOytCQUNFLHVCQUF1Qjs7MEJBNkI5QixNQUFNOzJCQUFDLFdBQVc7cUhBdkJkLHNCQUFzQjtzQkFENUIsS0FBSztnQkFJQyxtQkFBbUI7c0JBRHpCLEtBQUs7Z0JBSUMsdUJBQXVCO3NCQUQ3QixLQUFLO2dCQUlDLHVCQUF1QjtzQkFEN0IsS0FBSztnQkFJQyxZQUFZO3NCQURsQixNQUFNO2dCQXlEQSxRQUFRO3NCQURkLFlBQVk7dUJBQUMsZUFBZSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGlzUGxhdGZvcm1Ccm93c2VyIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7XG4gIEFmdGVyVmlld0luaXQsXG4gIENvbXBvbmVudCxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBIb3N0TGlzdGVuZXIsXG4gIEluamVjdCxcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPdXRwdXQsXG4gIFBMQVRGT1JNX0lELFxuICBTaW1wbGVDaGFuZ2VzLFxuICBUZW1wbGF0ZVJlZixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyB0YWtlIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgSVBERlZpZXdlckFwcGxpY2F0aW9uIH0gZnJvbSAnLi4vLi4vb3B0aW9ucy9wZGYtdmlld2VyLWFwcGxpY2F0aW9uJztcbmltcG9ydCB7IFBkZlNoeUJ1dHRvblNlcnZpY2UgfSBmcm9tICcuLi8uLi90b29sYmFyL3BkZi1zaHktYnV0dG9uL3BkZi1zaHktYnV0dG9uLXNlcnZpY2UnO1xuaW1wb3J0IHsgUERGTm90aWZpY2F0aW9uU2VydmljZSB9IGZyb20gJy4vLi4vLi4vcGRmLW5vdGlmaWNhdGlvbi1zZXJ2aWNlJztcbmltcG9ydCB7IE5neEV4dGVuZGVkUGRmVmlld2VyU2VydmljZSB9IGZyb20gJy4uLy4uL25neC1leHRlbmRlZC1wZGYtdmlld2VyLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdwZGYtc2Vjb25kYXJ5LXRvb2xiYXInLFxuICB0ZW1wbGF0ZVVybDogJy4vcGRmLXNlY29uZGFyeS10b29sYmFyLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vcGRmLXNlY29uZGFyeS10b29sYmFyLmNvbXBvbmVudC5jc3MnXSxcbn0pXG5leHBvcnQgY2xhc3MgUGRmU2Vjb25kYXJ5VG9vbGJhckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcbiAgQElucHV0KClcbiAgcHVibGljIGN1c3RvbVNlY29uZGFyeVRvb2xiYXI6IFRlbXBsYXRlUmVmPGFueT4gfCB1bmRlZmluZWQ7XG5cbiAgQElucHV0KClcbiAgcHVibGljIHNlY29uZGFyeVRvb2xiYXJUb3A7XG5cbiAgQElucHV0KClcbiAgcHVibGljIG1vYmlsZUZyaWVuZGx5Wm9vbVNjYWxlOiBudW1iZXI7XG5cbiAgQElucHV0KClcbiAgcHVibGljIGxvY2FsaXphdGlvbkluaXRpYWxpemVkOiBib29sZWFuO1xuXG4gIEBPdXRwdXQoKVxuICBwdWJsaWMgc3ByZWFkQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjwnb2ZmJyB8ICdldmVuJyB8ICdvZGQnPigpO1xuXG4gIHB1YmxpYyBkaXNhYmxlUHJldmlvdXNQYWdlID0gdHJ1ZTtcblxuICBwdWJsaWMgZGlzYWJsZU5leHRQYWdlID0gdHJ1ZTtcblxuICBwcml2YXRlIGNsYXNzTXV0YXRpb25PYnNlcnZlcjogTXV0YXRpb25PYnNlcnZlciB8IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGVsZW1lbnQ6IEVsZW1lbnRSZWYsXG4gICAgcHVibGljIG5vdGlmaWNhdGlvblNlcnZpY2U6IFBERk5vdGlmaWNhdGlvblNlcnZpY2UsXG4gICAgQEluamVjdChQTEFURk9STV9JRCkgcHJpdmF0ZSBwbGF0Zm9ybUlkOiBPYmplY3QsXG4gICAgcHVibGljIHBkZlNoeUJ1dHRvblNlcnZpY2U6IFBkZlNoeUJ1dHRvblNlcnZpY2UsXG4gICAgcHJpdmF0ZSBuZ3hFeHRlbmRlZFBkZlZpZXdlclNlcnZpY2U6IE5neEV4dGVuZGVkUGRmVmlld2VyU2VydmljZVxuICApIHtcbiAgICB0aGlzLm5vdGlmaWNhdGlvblNlcnZpY2Uub25QREZKU0luaXQucGlwZSh0YWtlKDEpKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgdGhpcy5vblBkZkpzSW5pdCgpO1xuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIG9uUGRmSnNJbml0KCk6IHZvaWQge1xuICAgIGNvbnN0IFBERlZpZXdlckFwcGxpY2F0aW9uOiBJUERGVmlld2VyQXBwbGljYXRpb24gPSAod2luZG93IGFzIGFueSkuUERGVmlld2VyQXBwbGljYXRpb247XG4gICAgUERGVmlld2VyQXBwbGljYXRpb24uZXZlbnRCdXMub24oJ3BhZ2VjaGFuZ2luZycsICgpID0+IHtcbiAgICAgIHRoaXMudXBkYXRlVUlTdGF0ZSgpO1xuICAgIH0pO1xuICAgIFBERlZpZXdlckFwcGxpY2F0aW9uLmV2ZW50QnVzLm9uKCdwYWdlcmVuZGVyZWQnLCAoKSA9PiB7XG4gICAgICB0aGlzLnVwZGF0ZVVJU3RhdGUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyB1cGRhdGVVSVN0YXRlKCk6IHZvaWQge1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgY29uc3QgUERGVmlld2VyQXBwbGljYXRpb246IElQREZWaWV3ZXJBcHBsaWNhdGlvbiA9ICh3aW5kb3cgYXMgYW55KS5QREZWaWV3ZXJBcHBsaWNhdGlvbjtcbiAgICAgIGNvbnN0IGN1cnJlbnRQYWdlID0gUERGVmlld2VyQXBwbGljYXRpb24ucGRmVmlld2VyLmN1cnJlbnRQYWdlTnVtYmVyO1xuICAgICAgY29uc3QgcHJldmlvdXNCdXR0b24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncHJldmlvdXNQYWdlJykgYXMgSFRNTEJ1dHRvbkVsZW1lbnQ7XG4gICAgICBpZiAocHJldmlvdXNCdXR0b24pIHtcbiAgICAgICAgdGhpcy5kaXNhYmxlUHJldmlvdXNQYWdlID0gTnVtYmVyKGN1cnJlbnRQYWdlKSA8PSAxO1xuICAgICAgICBwcmV2aW91c0J1dHRvbi5kaXNhYmxlZCA9IHRoaXMuZGlzYWJsZVByZXZpb3VzUGFnZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG5leHRCdXR0b24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbmV4dFBhZ2UnKSBhcyBIVE1MQnV0dG9uRWxlbWVudDtcbiAgICAgIGlmIChuZXh0QnV0dG9uKSB7XG4gICAgICAgIHRoaXMuZGlzYWJsZU5leHRQYWdlID0gY3VycmVudFBhZ2UgPT09IFBERlZpZXdlckFwcGxpY2F0aW9uLnBhZ2VzQ291bnQ7XG4gICAgICAgIG5leHRCdXR0b24uZGlzYWJsZWQgPSB0aGlzLmRpc2FibGVOZXh0UGFnZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBvblNwcmVhZENoYW5nZShuZXdTcHJlYWQ6ICdvZmYnIHwgJ29kZCcgfCAnZXZlbicpOiB2b2lkIHtcbiAgICB0aGlzLnNwcmVhZENoYW5nZS5lbWl0KG5ld1NwcmVhZCk7XG4gIH1cblxuICBwdWJsaWMgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy5jaGVja1Zpc2liaWxpdHkoKSk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6cmVzaXplJylcbiAgcHVibGljIG9uUmVzaXplKCkge1xuICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy5jaGVja1Zpc2liaWxpdHkoKSk7XG4gIH1cblxuICBwdWJsaWMgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIGlmIChpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpKSB7XG4gICAgICBjb25zdCB0YXJnZXROb2RlID0gdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnQ7XG5cbiAgICAgIGNvbnN0IGNvbmZpZyA9IHsgYXR0cmlidXRlczogdHJ1ZSwgY2hpbGRMaXN0OiB0cnVlLCBzdWJ0cmVlOiB0cnVlIH07XG5cbiAgICAgIHRoaXMuY2xhc3NNdXRhdGlvbk9ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoKG11dGF0aW9uTGlzdDogTXV0YXRpb25SZWNvcmRbXSwgb2JzZXJ2ZXIpID0+IHtcbiAgICAgICAgZm9yIChjb25zdCBtdXRhdGlvbiBvZiBtdXRhdGlvbkxpc3QpIHtcbiAgICAgICAgICBpZiAobXV0YXRpb24udHlwZSA9PT0gJ2F0dHJpYnV0ZXMnKSB7XG4gICAgICAgICAgICBpZiAobXV0YXRpb24uYXR0cmlidXRlTmFtZSA9PT0gJ2NsYXNzJykge1xuICAgICAgICAgICAgICB0aGlzLmNoZWNrVmlzaWJpbGl0eSgpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKG11dGF0aW9uLnR5cGUgPT09ICdjaGlsZExpc3QnKSB7XG4gICAgICAgICAgICB0aGlzLmNoZWNrVmlzaWJpbGl0eSgpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgdGhpcy5jbGFzc011dGF0aW9uT2JzZXJ2ZXIub2JzZXJ2ZSh0YXJnZXROb2RlLCBjb25maWcpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5jbGFzc011dGF0aW9uT2JzZXJ2ZXIpIHtcbiAgICAgIHRoaXMuY2xhc3NNdXRhdGlvbk9ic2VydmVyLmRpc2Nvbm5lY3QoKTtcbiAgICAgIHRoaXMuY2xhc3NNdXRhdGlvbk9ic2VydmVyID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBjaGVja1Zpc2liaWxpdHkoKTogdm9pZCB7XG4gICAgbGV0IHZpc2libGVCdXR0b25zID0gMDtcbiAgICBjb25zdCBlID0gdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnQ7XG4gICAgY29uc3QgZiA9IGUuY2hpbGRyZW4uaXRlbSgwKTtcbiAgICBpZiAoZikge1xuICAgICAgY29uc3QgZyA9IGYuY2hpbGRyZW4uaXRlbSgwKTtcbiAgICAgIGlmIChnICYmIGcgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICB2aXNpYmxlQnV0dG9ucyA9IHRoaXMuY2hlY2tWaXNpYmlsaXR5UmVjdXJzaXZlbHkoZyk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMubmd4RXh0ZW5kZWRQZGZWaWV3ZXJTZXJ2aWNlLnNlY29uZGFyeU1lbnVJc0VtcHR5ID0gdmlzaWJsZUJ1dHRvbnMgPT09IDA7XG4gIH1cblxuICBwcml2YXRlIGNoZWNrVmlzaWJpbGl0eVJlY3Vyc2l2ZWx5KGU6IEhUTUxFbGVtZW50KTogbnVtYmVyIHtcbiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIC8vIHNlcnZlci1zaWRlIHJlbmRlcmluZ1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGlmIChlLnN0eWxlLmRpc3BsYXkgPT09ICdub25lJykge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGlmIChlLmNsYXNzTGlzdC5jb250YWlucygnaGlkZGVuJykpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICBpZiAoZS5jbGFzc0xpc3QuY29udGFpbnMoJ2ludmlzaWJsZScpKSB7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICBjb25zdCBzdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGUpO1xuICAgIGlmIChzdHlsZS5kaXNwbGF5ID09PSAnbm9uZScpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIGlmIChlIGluc3RhbmNlb2YgSFRNTEJ1dHRvbkVsZW1lbnQgfHwgZSBpbnN0YW5jZW9mIEhUTUxBbmNob3JFbGVtZW50KSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG4gICAgbGV0IGNvdW50ID0gMDtcbiAgICBjb25zdCBjaGlsZHJlbiA9IGUuY2hpbGRyZW47XG4gICAgaWYgKGNoaWxkcmVuPy5sZW5ndGgpIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoICYmIGNvdW50ID09PSAwOyBpKyspIHtcbiAgICAgICAgY29uc3QgY2hpbGQgPSBjaGlsZHJlbi5pdGVtKGkpO1xuICAgICAgICBpZiAoY2hpbGQgJiYgY2hpbGQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgIGNvdW50ICs9IHRoaXMuY2hlY2tWaXNpYmlsaXR5UmVjdXJzaXZlbHkoY2hpbGQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjb3VudDtcbiAgfVxuXG4gIHB1YmxpYyBvbkNsaWNrKFxuICAgIGh0bWxldmVudDogRXZlbnQsXG4gICAgYWN0aW9uOiB1bmRlZmluZWQgfCAoKGh0bWxldmVudDogRXZlbnQsIHNlY29uZGFyeVRvb2xiYXI6IGJvb2xlYW4pID0+IHZvaWQpLFxuICAgIGV2ZW50QnVzTmFtZT86IHN0cmluZyxcbiAgICBjbG9zZU9uQ2xpY2s/OiBib29sZWFuXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IFBERlZpZXdlckFwcGxpY2F0aW9uOiBJUERGVmlld2VyQXBwbGljYXRpb24gPSAod2luZG93IGFzIGFueSkuUERGVmlld2VyQXBwbGljYXRpb247XG4gICAgY29uc3Qgb3JpZ2luID0gaHRtbGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudDtcbiAgICBvcmlnaW4/LmNsYXNzTGlzdC5hZGQoJ3RvZ2dsZWQnKTtcbiAgICBpZiAoYWN0aW9uKSB7XG4gICAgICBhY3Rpb24oaHRtbGV2ZW50LCB0cnVlKTtcbiAgICAgIGh0bWxldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0gZWxzZSBpZiAoZXZlbnRCdXNOYW1lKSB7XG4gICAgICBQREZWaWV3ZXJBcHBsaWNhdGlvbi5ldmVudEJ1cy5kaXNwYXRjaChldmVudEJ1c05hbWUpO1xuICAgICAgaHRtbGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuICAgIGlmIChjbG9zZU9uQ2xpY2spIHtcbiAgICAgIFBERlZpZXdlckFwcGxpY2F0aW9uLnNlY29uZGFyeVRvb2xiYXIuY2xvc2UoKTtcbiAgICB9XG4gIH1cbn1cbiIsIjxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwiY3VzdG9tU2Vjb25kYXJ5VG9vbGJhciA/IGN1c3RvbVNlY29uZGFyeVRvb2xiYXIgOiBkZWZhdWx0U2Vjb25kYXJ5VG9vbGJhclwiPiA8L25nLWNvbnRhaW5lcj5cblxuPG5nLXRlbXBsYXRlICNkZWZhdWx0U2Vjb25kYXJ5VG9vbGJhcj5cbiAgPGRpdlxuICAgIGlkPVwic2Vjb25kYXJ5VG9vbGJhclwiXG4gICAgY2xhc3M9XCJzZWNvbmRhcnlUb29sYmFyIGhpZGRlbiBkb29ySGFuZ2VyUmlnaHRcIlxuICAgIFtzdHlsZS50b3BdPVwic2Vjb25kYXJ5VG9vbGJhclRvcFwiXG4gICAgW3N0eWxlLnRyYW5zZm9ybV09XCInc2NhbGUoJyArIG1vYmlsZUZyaWVuZGx5Wm9vbVNjYWxlICsgJyknXCJcbiAgICBbc3R5bGUudHJhbnNmb3JtT3JpZ2luXT1cIidyaWdodCB0b3AnXCJcbiAgPlxuICAgIDxkaXYgaWQ9XCJzZWNvbmRhcnlUb29sYmFyQnV0dG9uQ29udGFpbmVyXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgICpuZ0Zvcj1cImxldCBidXR0b24gb2YgcGRmU2h5QnV0dG9uU2VydmljZS5idXR0b25zXCJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIFtpZF09XCJidXR0b24uaWRcIlxuICAgICAgICBbbmdDbGFzc109XCJidXR0b24uY3NzQ2xhc3MgfCBpbnZlcnRGb3JTZWNvbmRhcnlUb29sYmFyXCJcbiAgICAgICAgW2NsYXNzLnRvZ2dsZWRdPVwiYnV0dG9uLnRvZ2dsZWRcIlxuICAgICAgICBjbGFzcz1cInNlY29uZGFyeVRvb2xiYXJCdXR0b25cIlxuICAgICAgICBbdGl0bGVdPVwiYnV0dG9uLnRpdGxlXCJcbiAgICAgICAgW2F0dHIuZGF0YS1sMTBuLWlkXT1cImJ1dHRvbi5sMTBuSWRcIlxuICAgICAgICAoY2xpY2spPVwib25DbGljaygkZXZlbnQsIGJ1dHRvbi5hY3Rpb24sIGJ1dHRvbi5ldmVudEJ1c05hbWUsIGJ1dHRvbi5jbG9zZU9uQ2xpY2spXCJcbiAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJidXR0b24udGl0bGVcIlxuICAgICAgICByb2xlPVwiYnV0dG9uXCJcbiAgICAgID5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJpY29uXCIgcm9sZT1cImltZ1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiIFthdHRyLmFyaWEtbGFiZWxdPVwiYnV0dG9uLnRpdGxlXCIgKm5nSWY9XCJidXR0b24uaW1hZ2VcIiBbaW5uZXJIVE1MXT1cImJ1dHRvbi5pbWFnZVwiPjwvc3Bhbj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJ0b29sYmFyLWNhcHRpb25cIiBbYXR0ci5kYXRhLWwxMG4taWRdPVwiYnV0dG9uLmwxMG5MYWJlbFwiPnt7IGJ1dHRvbi50aXRsZSB9fTwvc3Bhbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG4iXX0=