UNPKG

@clarivate/angular-image-viewer

Version:

This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 13.3.0.

247 lines 48.2 kB
import { Component, HostListener, Optional, Inject, Input, Output, EventEmitter, ViewChild } from '@angular/core'; import { CustomImageEvent } from './models/custom-image-event-model'; import { CdkDrag } from '@angular/cdk/drag-drop'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "@angular/cdk/drag-drop"; import * as i3 from "./directives/full-screen.directive"; const DEFAULT_CONFIG = { btnClass: 'default', zoomFactor: 0.1, containerBackgroundColor: '#e4dede', primaryColor: '', wheelZoom: false, allowFullscreen: true, allowKeyboardNavigation: true, btnShow: { zoomIn: true, zoomOut: true, rotateClockwise: true, rotateCounterClockwise: true, next: true, prev: true }, btnIcons: { zoomIn: 'fa fa-plus', zoomOut: 'fa fa-minus', rotateClockwise: 'fa fa-refresh', rotateCounterClockwise: 'fa fa-undo', next: 'fa fa-chevron-right', prev: 'fa fa-chevron-left', fullscreen: 'fa fa-arrows-alt', }, isZoomPersistent: false }; export class AngularImageViewerComponent { constructor(moduleConfig) { this.moduleConfig = moduleConfig; this.src = []; this.screenHeightOccupied = 0; // In Px this.index = 0; this.footerTexts = [ 'Image', 'of', 'View previous or next image', 'using < > on the keyboard' ]; this.scaleInput = 1; this.indexChange = new EventEmitter(); this.configChange = new EventEmitter(); this.customImageEvent = new EventEmitter(); this.styleHeight = '98vh'; this.style = { transform: '', msTransform: '', oTransform: '', webkitTransform: '' }; this.fullscreen = false; this.loading = true; this.isDragOn = false; this.scale = 1; this.rotation = 0; this.hovered = false; this.unwrap = (n) => n ? n : 0; } ngOnChanges(changes) { if (changes['screenHeightOccupied']) { this.styleHeight = 'calc(98vh - ' + this.screenHeightOccupied + 'px)'; } else if (changes['index']) { this.reset(); } if (changes['scaleInput'] && this.config['isZoomPersistent']) { this.scale = changes['scaleInput'].currentValue; this.updateStyle(); } } ngOnInit() { const merged = this.mergeConfig(DEFAULT_CONFIG, this.moduleConfig); this.config = this.mergeConfig(merged, this.config); this.triggerConfigBinding(); } ngAfterContentChecked() { if (document.querySelectorAll('.drag-element')[0]) { let dragElement = document.querySelectorAll('.drag-element')[0]; let imgElem = dragElement.querySelector('img'); imgElem.style.transform = `rotate(${this.rotation}deg) scale(${this.scale})`; } } nextImage(event) { if (this.canNavigate(event) && this.index < this.src.length - 1) { this.loading = true; this.index++; this.triggerIndexBinding(); this.fireCustomEvent('next', this.index); this.reset(); } } prevImage(event) { if (this.canNavigate(event) && this.index > 0) { this.loading = true; this.index--; this.triggerIndexBinding(); this.fireCustomEvent('prev', this.index); this.reset(); } } zoomIn() { this.scale *= (1 + this.unwrap(this.config.zoomFactor)); this.fireCustomEvent('zoomIn', this.scale); this.updateStyle(); } zoomOut() { if (this.scale > this.unwrap(this.config.zoomFactor)) { this.scale /= (1 + this.unwrap(this.config.zoomFactor)); } this.fireCustomEvent('zoomOut', this.scale); this.updateStyle(); } scrollZoom(evt) { if (this.config.wheelZoom) { evt.deltaY > 0 ? this.zoomOut() : this.zoomIn(); return false; } return true; } rotateClockwise() { this.rotation += 90; this.fireCustomEvent('rotateClockwise', this.rotation); this.updateStyle(); } rotateCounterClockwise() { this.rotation -= 90; this.updateStyle(); } onLoad() { this.loading = false; } onLoadStart() { this.loading = true; } imageNotFound() { } onDragStart(evt) { if (evt.source._dragRef._initialTransform && evt.source._dragRef._initialTransform.length > 0) { const myTranslate = evt.source._dragRef._initialTransform.split(' rotate')[0]; const myRotate = this.style.transform.split(' rotate')[1]; evt.source._dragRef._initialTransform = `${myTranslate} rotate${myRotate}`; } else { evt.source._dragRef._initialTransform = this.style.transform; } } toggleFullscreen() { this.fullscreen = !this.fullscreen; if (!this.fullscreen) { this.reset(); } } triggerIndexBinding() { this.indexChange.emit(this.index); } triggerConfigBinding() { this.configChange.next(this.config); } fireCustomEvent(name, imageIndex) { this.customImageEvent.emit(new CustomImageEvent(name, imageIndex)); } reset() { if (!this.config.isZoomPersistent) { this.scale = 1; this.rotation = 0; this.updateStyle(); this.cdkDrag.reset(); } } onMouseOver() { this.hovered = true; } onMouseLeave() { this.hovered = false; } canNavigate(event) { if (event.type === 'keyup') { return (this.config.allowKeyboardNavigation && this.hovered); } else if (event.type === 'click') { return this.hovered; } return null; } updateStyle() { this.style.transform = `rotate(${this.rotation}deg) scale(${this.scale})`; } mergeConfig(defaultValues, overrideValues) { let result = { ...defaultValues }; if (overrideValues) { result = { ...defaultValues, ...overrideValues }; if (overrideValues.btnIcons) { result.btnIcons = { ...defaultValues.btnIcons, ...overrideValues.btnIcons }; } } return result; } } AngularImageViewerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AngularImageViewerComponent, deps: [{ token: 'config', optional: true }], target: i0.ɵɵFactoryTarget.Component }); AngularImageViewerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: AngularImageViewerComponent, selector: "angular-image-viewer", inputs: { src: "src", config: "config", screenHeightOccupied: "screenHeightOccupied", index: "index", imageName: "imageName", footerTexts: "footerTexts", scaleInput: "scaleInput" }, outputs: { indexChange: "indexChange", configChange: "configChange", customImageEvent: "customImageEvent" }, host: { listeners: { "window:keyup.ArrowRight": "nextImage($event)", "window:keyup.ArrowLeft": "prevImage($event)", "mouseover": "onMouseOver()", "mouseleave": "onMouseLeave()" } }, viewQueries: [{ propertyName: "cdkDrag", first: true, predicate: CdkDrag, descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div [appScreenfull]=\"fullscreen\" class=\"img-container\" [style.backgroundColor]=\"config.containerBackgroundColor\"\r\n (wheel)=\"scrollZoom($event)\">\r\n <div class=\"image-name\" *ngIf=\"imageName\">\r\n <span>{{imageName}}</span>\r\n </div>\r\n\r\n <div cdkDrag class=\"drag-element\">\r\n <img [src]=\"src[index]\" [ngStyle]=\"style\" alt=\"\"\r\n (cdkDragStarted)=\"onDragStart($event)\"\r\n (load)=\"onLoad()\" (loadstart)=\"onLoadStart()\" (error)=\"imageNotFound()\" />\r\n </div>\r\n\r\n <div class=\"spinner-container\" *ngIf=\"loading\">\r\n <div class=\"spinner\"></div>\r\n </div>\r\n\r\n <div class=\"button-container\">\r\n <button type=\"button\" id=\"ngx-fs-btn\" [class]=\"config.btnClass\" (click)=\"toggleFullscreen()\"\r\n [style.color]=\"config.primaryColor\" *ngIf=\"config.allowFullscreen\">\r\n <span [class]=\"config.btnIcons?.fullscreen\"></span>\r\n </button>\r\n\r\n <div class=\"button-container-bottom\">\r\n <button type=\"button\" [class]=\"config.btnClass\" *ngFor=\"let cBtn of config.customBtns\"\r\n [style.color]=\"config.primaryColor\" (click)=\"fireCustomEvent(cBtn.name, index)\">\r\n <span [class]=\"cBtn.icon\"></span>\r\n </button>\r\n\r\n <button type=\"button\" [class]=\"config.btnClass\" *ngIf=\"config.btnShow?.rotateCounterClockwise\"\r\n [style.color]=\"config.primaryColor\" (click)=\"rotateCounterClockwise()\">\r\n <span [class]=\"config.btnIcons?.rotateCounterClockwise\"></span>\r\n </button>\r\n <button type=\"button\" [class]=\"config.btnClass\" *ngIf=\"config.btnShow?.rotateClockwise\"\r\n [style.color]=\"config.primaryColor\" (click)=\"rotateClockwise()\">\r\n <span [class]=\"config.btnIcons?.rotateClockwise\"></span>\r\n </button>\r\n\r\n <div class=\"button-zoom-in-out-container\">\r\n <button type=\"button\" [class]=\"config.btnClass\" *ngIf=\"config.btnShow?.zoomIn\"\r\n [style.color]=\"config.primaryColor\" (click)=\"zoomIn()\">\r\n <span [class]=\"config.btnIcons?.zoomIn\"></span>\r\n </button>\r\n <button type=\"button\" [class]=\"config.btnClass\" *ngIf=\"config.btnShow?.zoomOut\"\r\n [style.color]=\"config.primaryColor\" (click)=\"zoomOut()\">\r\n <span [class]=\"config.btnIcons?.zoomOut\"></span>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"nav-button-container\" *ngIf=\"src.length > 1\">\r\n <button type=\"button\" #prevImg [class]=\"config.btnClass\" (click)=\"prevImage($event); prevImg.blur()\"\r\n [style.color]=\"config.primaryColor\" [disabled]=\"index === 0\">\r\n <span [class]=\"config.btnIcons?.prev\"></span>\r\n </button>\r\n <button type=\"button\" #nextImg [class]=\"config.btnClass\" (click)=\"nextImage($event); nextImg.blur()\"\r\n [style.color]=\"config.primaryColor\" [disabled]=\"index === src.length - 1\">\r\n <span [class]=\"config.btnIcons?.next\"></span>\r\n </button>\r\n </div>\r\n <div class=\"footer-section\">\r\n <div class=\"image-txt-count-left-align\"><span>{{footerTexts[0]}} {{index + 1}} {{footerTexts[1]}} {{src.length}}</span></div>\r\n <div class=\"footer-txt-right-align\">\r\n <span class=\"footer-txt-right-align-title\" [style.color]=\"config.primaryColor\">{{footerTexts[2]}}</span>\r\n <span class=\"footer-txt-right-align-note\">{{footerTexts[3]}}</span>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".img-container{position:relative;width:100%;height:100%;display:flex;justify-content:center;align-items:center;overflow:hidden}.img-container .drag-element{position:absolute;top:35px;right:78px;width:calc(100% - 156px);height:calc(100% - 85px);cursor:grab;text-align:center}.img-container .drag-element img{padding:0;max-width:100%;max-height:100%}.img-container .drag-element:active{cursor:grabbing}.img-container button{z-index:99}.img-container button:not(:disabled){cursor:pointer}#ngx-fs-btn{top:15px}button.default{height:24px;width:24px;opacity:.9;transition:opacity .2s;font-size:12px;background:inherit;background-color:#fff;border:none;border-radius:31px;box-shadow:0 0 5px #00000059}button.default:focus{outline:none;opacity:1}button.default:hover{opacity:1}button.default:disabled{opacity:.3}.nav-button-container>button{position:relative;right:0;margin:0 10px}.nav-button-container{text-align:right;position:absolute;z-index:98;bottom:60px;left:0;right:10px}.nav-button-container button.default{height:30px;margin:0;font-size:14px}.nav-button-container button.default:first-child{border-radius:4px 0 0 4px}.nav-button-container button.default:last-child{margin-left:10px;border-radius:0 4px 4px 0}.button-container{position:absolute;top:10px;right:10px;width:24px;height:calc(100% - 115px);z-index:98}.button-container .button-container-bottom{position:absolute;bottom:0}.button-container .button-container-bottom button.default{margin-top:10px}.button-container .button-container-bottom .button-zoom-in-out-container{margin-top:15px}.button-container .button-container-bottom .button-zoom-in-out-container button.default{margin:0;border-radius:0;height:30px}.button-container .button-container-bottom .button-zoom-in-out-container button.default:first-child{margin-bottom:1px}.spinner-container{position:absolute;inset:0;width:60px;height:60px;margin:auto;padding:10px;background-color:#0006;border-radius:25%}.spinner{border-width:7px;border-style:solid;border-color:#ccc;border-bottom-color:#222;border-radius:50%;height:100%;width:100%;box-sizing:border-box;animation:rotation 2s linear infinite}.footer-section{position:absolute;bottom:10px;left:0;width:100%;line-height:18px;z-index:98}.footer-section .image-txt-count-left-align{float:left;padding:0 10px;font-family:Source Sans Pro SemiBold;font-size:14;color:#333}.footer-section .footer-txt-right-align{float:right;padding:0 10px;text-align:right}.footer-section .footer-txt-right-align span.footer-txt-right-align-title{display:block;font-family:Source Sans Pro SemiBold;font-size:14}.footer-section .footer-txt-right-align span.footer-txt-right-align-note{color:#767676;font-family:Source Sans Pro;font-size:12}.image-name{position:absolute;top:10px;left:10px;z-index:98;font-family:Source Sans Pro SemiBold;font-size:16;color:#333}@keyframes rotation{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(359deg)}}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i3.FullScreenDirective, selector: "[appScreenfull]", inputs: ["appScreenfull"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AngularImageViewerComponent, decorators: [{ type: Component, args: [{ selector: 'angular-image-viewer', template: "<div [appScreenfull]=\"fullscreen\" class=\"img-container\" [style.backgroundColor]=\"config.containerBackgroundColor\"\r\n (wheel)=\"scrollZoom($event)\">\r\n <div class=\"image-name\" *ngIf=\"imageName\">\r\n <span>{{imageName}}</span>\r\n </div>\r\n\r\n <div cdkDrag class=\"drag-element\">\r\n <img [src]=\"src[index]\" [ngStyle]=\"style\" alt=\"\"\r\n (cdkDragStarted)=\"onDragStart($event)\"\r\n (load)=\"onLoad()\" (loadstart)=\"onLoadStart()\" (error)=\"imageNotFound()\" />\r\n </div>\r\n\r\n <div class=\"spinner-container\" *ngIf=\"loading\">\r\n <div class=\"spinner\"></div>\r\n </div>\r\n\r\n <div class=\"button-container\">\r\n <button type=\"button\" id=\"ngx-fs-btn\" [class]=\"config.btnClass\" (click)=\"toggleFullscreen()\"\r\n [style.color]=\"config.primaryColor\" *ngIf=\"config.allowFullscreen\">\r\n <span [class]=\"config.btnIcons?.fullscreen\"></span>\r\n </button>\r\n\r\n <div class=\"button-container-bottom\">\r\n <button type=\"button\" [class]=\"config.btnClass\" *ngFor=\"let cBtn of config.customBtns\"\r\n [style.color]=\"config.primaryColor\" (click)=\"fireCustomEvent(cBtn.name, index)\">\r\n <span [class]=\"cBtn.icon\"></span>\r\n </button>\r\n\r\n <button type=\"button\" [class]=\"config.btnClass\" *ngIf=\"config.btnShow?.rotateCounterClockwise\"\r\n [style.color]=\"config.primaryColor\" (click)=\"rotateCounterClockwise()\">\r\n <span [class]=\"config.btnIcons?.rotateCounterClockwise\"></span>\r\n </button>\r\n <button type=\"button\" [class]=\"config.btnClass\" *ngIf=\"config.btnShow?.rotateClockwise\"\r\n [style.color]=\"config.primaryColor\" (click)=\"rotateClockwise()\">\r\n <span [class]=\"config.btnIcons?.rotateClockwise\"></span>\r\n </button>\r\n\r\n <div class=\"button-zoom-in-out-container\">\r\n <button type=\"button\" [class]=\"config.btnClass\" *ngIf=\"config.btnShow?.zoomIn\"\r\n [style.color]=\"config.primaryColor\" (click)=\"zoomIn()\">\r\n <span [class]=\"config.btnIcons?.zoomIn\"></span>\r\n </button>\r\n <button type=\"button\" [class]=\"config.btnClass\" *ngIf=\"config.btnShow?.zoomOut\"\r\n [style.color]=\"config.primaryColor\" (click)=\"zoomOut()\">\r\n <span [class]=\"config.btnIcons?.zoomOut\"></span>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"nav-button-container\" *ngIf=\"src.length > 1\">\r\n <button type=\"button\" #prevImg [class]=\"config.btnClass\" (click)=\"prevImage($event); prevImg.blur()\"\r\n [style.color]=\"config.primaryColor\" [disabled]=\"index === 0\">\r\n <span [class]=\"config.btnIcons?.prev\"></span>\r\n </button>\r\n <button type=\"button\" #nextImg [class]=\"config.btnClass\" (click)=\"nextImage($event); nextImg.blur()\"\r\n [style.color]=\"config.primaryColor\" [disabled]=\"index === src.length - 1\">\r\n <span [class]=\"config.btnIcons?.next\"></span>\r\n </button>\r\n </div>\r\n <div class=\"footer-section\">\r\n <div class=\"image-txt-count-left-align\"><span>{{footerTexts[0]}} {{index + 1}} {{footerTexts[1]}} {{src.length}}</span></div>\r\n <div class=\"footer-txt-right-align\">\r\n <span class=\"footer-txt-right-align-title\" [style.color]=\"config.primaryColor\">{{footerTexts[2]}}</span>\r\n <span class=\"footer-txt-right-align-note\">{{footerTexts[3]}}</span>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".img-container{position:relative;width:100%;height:100%;display:flex;justify-content:center;align-items:center;overflow:hidden}.img-container .drag-element{position:absolute;top:35px;right:78px;width:calc(100% - 156px);height:calc(100% - 85px);cursor:grab;text-align:center}.img-container .drag-element img{padding:0;max-width:100%;max-height:100%}.img-container .drag-element:active{cursor:grabbing}.img-container button{z-index:99}.img-container button:not(:disabled){cursor:pointer}#ngx-fs-btn{top:15px}button.default{height:24px;width:24px;opacity:.9;transition:opacity .2s;font-size:12px;background:inherit;background-color:#fff;border:none;border-radius:31px;box-shadow:0 0 5px #00000059}button.default:focus{outline:none;opacity:1}button.default:hover{opacity:1}button.default:disabled{opacity:.3}.nav-button-container>button{position:relative;right:0;margin:0 10px}.nav-button-container{text-align:right;position:absolute;z-index:98;bottom:60px;left:0;right:10px}.nav-button-container button.default{height:30px;margin:0;font-size:14px}.nav-button-container button.default:first-child{border-radius:4px 0 0 4px}.nav-button-container button.default:last-child{margin-left:10px;border-radius:0 4px 4px 0}.button-container{position:absolute;top:10px;right:10px;width:24px;height:calc(100% - 115px);z-index:98}.button-container .button-container-bottom{position:absolute;bottom:0}.button-container .button-container-bottom button.default{margin-top:10px}.button-container .button-container-bottom .button-zoom-in-out-container{margin-top:15px}.button-container .button-container-bottom .button-zoom-in-out-container button.default{margin:0;border-radius:0;height:30px}.button-container .button-container-bottom .button-zoom-in-out-container button.default:first-child{margin-bottom:1px}.spinner-container{position:absolute;inset:0;width:60px;height:60px;margin:auto;padding:10px;background-color:#0006;border-radius:25%}.spinner{border-width:7px;border-style:solid;border-color:#ccc;border-bottom-color:#222;border-radius:50%;height:100%;width:100%;box-sizing:border-box;animation:rotation 2s linear infinite}.footer-section{position:absolute;bottom:10px;left:0;width:100%;line-height:18px;z-index:98}.footer-section .image-txt-count-left-align{float:left;padding:0 10px;font-family:Source Sans Pro SemiBold;font-size:14;color:#333}.footer-section .footer-txt-right-align{float:right;padding:0 10px;text-align:right}.footer-section .footer-txt-right-align span.footer-txt-right-align-title{display:block;font-family:Source Sans Pro SemiBold;font-size:14}.footer-section .footer-txt-right-align span.footer-txt-right-align-note{color:#767676;font-family:Source Sans Pro;font-size:12}.image-name{position:absolute;top:10px;left:10px;z-index:98;font-family:Source Sans Pro SemiBold;font-size:16;color:#333}@keyframes rotation{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(359deg)}}\n"] }] }], ctorParameters: function () { return [{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: ['config'] }] }]; }, propDecorators: { cdkDrag: [{ type: ViewChild, args: [CdkDrag, { static: true }] }], src: [{ type: Input }], config: [{ type: Input }], screenHeightOccupied: [{ type: Input }], index: [{ type: Input }], imageName: [{ type: Input }], footerTexts: [{ type: Input }], scaleInput: [{ type: Input }], indexChange: [{ type: Output }], configChange: [{ type: Output }], customImageEvent: [{ type: Output }], nextImage: [{ type: HostListener, args: ['window:keyup.ArrowRight', ['$event']] }], prevImage: [{ type: HostListener, args: ['window:keyup.ArrowLeft', ['$event']] }], onMouseOver: [{ type: HostListener, args: ['mouseover'] }], onMouseLeave: [{ type: HostListener, args: ['mouseleave'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1pbWFnZS12aWV3ZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhci1pbWFnZS12aWV3ZXIvc3JjL2xpYi9hbmd1bGFyLWltYWdlLXZpZXdlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWltYWdlLXZpZXdlci9zcmMvbGliL2FuZ3VsYXItaW1hZ2Utdmlld2VyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQStCLFlBQVksRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQzVGLFlBQVksRUFBNEIsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRTNFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3JFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQzs7Ozs7QUFFakQsTUFBTSxjQUFjLEdBQXNCO0lBQ3hDLFFBQVEsRUFBRSxTQUFTO0lBQ25CLFVBQVUsRUFBRSxHQUFHO0lBQ2Ysd0JBQXdCLEVBQUUsU0FBUztJQUNuQyxZQUFZLEVBQUUsRUFBRTtJQUNoQixTQUFTLEVBQUUsS0FBSztJQUNoQixlQUFlLEVBQUUsSUFBSTtJQUNyQix1QkFBdUIsRUFBRSxJQUFJO0lBQzdCLE9BQU8sRUFBRTtRQUNQLE1BQU0sRUFBRSxJQUFJO1FBQ1osT0FBTyxFQUFFLElBQUk7UUFDYixlQUFlLEVBQUUsSUFBSTtRQUNyQixzQkFBc0IsRUFBRSxJQUFJO1FBQzVCLElBQUksRUFBRSxJQUFJO1FBQ1YsSUFBSSxFQUFFLElBQUk7S0FDWDtJQUNELFFBQVEsRUFBRTtRQUNSLE1BQU0sRUFBRSxZQUFZO1FBQ3BCLE9BQU8sRUFBRSxhQUFhO1FBQ3RCLGVBQWUsRUFBRSxlQUFlO1FBQ2hDLHNCQUFzQixFQUFFLFlB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QUcsY0FBYyxDQUFDLFFBQVEsRUFBRSxDQUFDO2FBQzdFO1NBQ0Y7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDOzt5SEF6TlUsMkJBQTJCLGtCQWlETixRQUFROzZHQWpEN0IsMkJBQTJCLDhqQkFFM0IsT0FBTyxtRkMxQ3BCLHdzSEFvRUE7NEZENUJhLDJCQUEyQjtrQkFOdkMsU0FBUzsrQkFFRSxzQkFBc0I7OzBCQXFEbkIsUUFBUTs7MEJBQUksTUFBTTsyQkFBQyxRQUFROzRDQS9DRixPQUFPO3NCQUE1QyxTQUFTO3VCQUFDLE9BQU8sRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBR3BDLEdBQUc7c0JBREYsS0FBSztnQkFJTixNQUFNO3NCQURMLEtBQUs7Z0JBSU4sb0JBQW9CO3NCQURuQixLQUFLO2dCQUlOLEtBQUs7c0JBREosS0FBSztnQkFJTixTQUFTO3NCQURSLEtBQUs7Z0JBSU4sV0FBVztzQkFEVixLQUFLO2dCQVNOLFVBQVU7c0JBRFQsS0FBSztnQkFJTixXQUFXO3NCQURWLE1BQU07Z0JBSVAsWUFBWTtzQkFEWCxNQUFNO2dCQUlQLGdCQUFnQjtzQkFEZixNQUFNO2dCQTJDUCxTQUFTO3NCQURSLFlBQVk7dUJBQUMseUJBQXlCLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBWW5ELFNBQVM7c0JBRFIsWUFBWTt1QkFBQyx3QkFBd0IsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkErRmxELFdBQVc7c0JBRFYsWUFBWTt1QkFBQyxXQUFXO2dCQU16QixZQUFZO3NCQURYLFlBQVk7dUJBQUMsWUFBWSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBBZnRlckNvbnRlbnRDaGVja2VkLCBIb3N0TGlzdGVuZXIsIE9wdGlvbmFsLCBJbmplY3QsIElucHV0LCBPdXRwdXQsXHJcbiAgRXZlbnRFbWl0dGVyLCBPbkNoYW5nZXMsIFNpbXBsZUNoYW5nZXMsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBJbWFnZVZpZXdlckNvbmZpZyB9IGZyb20gJy4vbW9kZWxzL2ltYWdlLXZpZXdlci1jb25maWcubW9kZWwnO1xyXG5pbXBvcnQgeyBDdXN0b21JbWFnZUV2ZW50IH0gZnJvbSAnLi9tb2RlbHMvY3VzdG9tLWltYWdlLWV2ZW50LW1vZGVsJztcclxuaW1wb3J0IHsgQ2RrRHJhZyB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9kcmFnLWRyb3AnO1xyXG5cclxuY29uc3QgREVGQVVMVF9DT05GSUc6IEltYWdlVmlld2VyQ29uZmlnID0ge1xyXG4gIGJ0bkNsYXNzOiAnZGVmYXVsdCcsXHJcbiAgem9vbUZhY3RvcjogMC4xLFxyXG4gIGNvbnRhaW5lckJhY2tncm91bmRDb2xvcjogJyNlNGRlZGUnLFxyXG4gIHByaW1hcnlDb2xvcjogJycsXHJcbiAgd2hlZWxab29tOiBmYWxzZSxcclxuICBhbGxvd0Z1bGxzY3JlZW46IHRydWUsXHJcbiAgYWxsb3dLZXlib2FyZE5hdmlnYXRpb246IHRydWUsXHJcbiAgYnRuU2hvdzoge1xyXG4gICAgem9vbUluOiB0cnVlLFxyXG4gICAgem9vbU91dDogdHJ1ZSxcclxuICAgIHJvdGF0ZUNsb2Nrd2lzZTogdHJ1ZSxcclxuICAgIHJvdGF0ZUNvdW50ZXJDbG9ja3dpc2U6IHRydWUsXHJcbiAgICBuZXh0OiB0cnVlLFxyXG4gICAgcHJldjogdHJ1ZVxyXG4gIH0sXHJcbiAgYnRuSWNvbnM6IHtcclxuICAgIHpvb21JbjogJ2ZhIGZhLXBsdXMnLFxyXG4gICAgem9vbU91dDogJ2ZhIGZhLW1pbnVzJyxcclxuICAgIHJvdGF0ZUNsb2Nrd2lzZTogJ2ZhIGZhLXJlZnJlc2gnLFxyXG4gICAgcm90YXRlQ291bnRlckNsb2Nrd2lzZTogJ2ZhIGZhLXVuZG8nLFxyXG4gICAgbmV4dDogJ2ZhIGZhLWNoZXZyb24tcmlnaHQnLFxyXG4gICAgcHJldjogJ2ZhIGZhLWNoZXZyb24tbGVmdCcsXHJcbiAgICBmdWxsc2NyZWVuOiAnZmEgZmEtYXJyb3dzLWFsdCcsXHJcbiAgfSxcclxuICBpc1pvb21QZXJzaXN0ZW50OiBmYWxzZVxyXG59O1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmNvbXBvbmVudC1zZWxlY3RvclxyXG4gIHNlbGVjdG9yOiAnYW5ndWxhci1pbWFnZS12aWV3ZXInLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9hbmd1bGFyLWltYWdlLXZpZXdlci5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmxzOiBbJy4vYW5ndWxhci1pbWFnZS12aWV3ZXIuY29tcG9uZW50LnNjc3MnXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgQW5ndWxhckltYWdlVmlld2VyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIEFmdGVyQ29udGVudENoZWNrZWQge1xyXG5cclxuICBAVmlld0NoaWxkKENka0RyYWcsIHsgc3RhdGljOiB0cnVlIH0pIGNka0RyYWchOiBDZGtEcmFnO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIHNyYzogc3RyaW5nW10gPSBbXTtcclxuXHJcbiAgQElucHV0KClcclxuICBjb25maWchOiBJbWFnZVZpZXdlckNvbmZpZztcclxuXHJcbiAgQElucHV0KClcclxuICBzY3JlZW5IZWlnaHRPY2N1cGllZCA9IDA7ICAgICAgICAgICAgIC8vIEluIFB4XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgaW5kZXggPSAwO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIGltYWdlTmFtZSE6IHN0cmluZztcclxuXHJcbiAgQElucHV0KClcclxuICBmb290ZXJUZXh0cyA9IFtcclxuICAgICdJbWFnZScsXHJcbiAgICAnb2YnLFxyXG4gICAgJ1ZpZXcgcHJldmlvdXMgb3IgbmV4dCBpbWFnZScsXHJcbiAgICAndXNpbmcgPCA+IG9uIHRoZSBrZXlib2FyZCdcclxuICBdO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIHNjYWxlSW5wdXQgPSAxO1xyXG5cclxuICBAT3V0cHV0KClcclxuICBpbmRleENoYW5nZTogRXZlbnRFbWl0dGVyPG51bWJlcj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcblxyXG4gIEBPdXRwdXQoKVxyXG4gIGNvbmZpZ0NoYW5nZTogRXZlbnRFbWl0dGVyPEltYWdlVmlld2VyQ29uZmlnPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcclxuXHJcbiAgQE91dHB1dCgpXHJcbiAgY3VzdG9tSW1hZ2VFdmVudDogRXZlbnRFbWl0dGVyPEN1c3RvbUltYWdlRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xyXG5cclxuICBzdHlsZUhlaWdodCA9ICc5OHZoJztcclxuXHJcbiAgcHVibGljIHN0eWxlID0geyB0cmFuc2Zvcm06ICcnLCBtc1RyYW5zZm9ybTogJycsIG9UcmFuc2Zvcm06ICcnLCB3ZWJraXRUcmFuc2Zvcm06ICcnIH07XHJcbiAgcHVibGljIGZ1bGxzY3JlZW4gPSBmYWxzZTtcclxuICBwdWJsaWMgbG9hZGluZyA9IHRydWU7XHJcbiAgcHVibGljIGlzRHJhZ09uID0gZmFsc2U7XHJcbiAgcHJpdmF0ZSBzY2FsZSA9IDE7XHJcbiAgcHJpdmF0ZSByb3RhdGlvbiA9IDA7XHJcbiAgcHJpdmF0ZSBob3ZlcmVkID0gZmFsc2U7XHJcblxyXG4gIGNvbnN0cnVjdG9yKEBPcHRpb25hbCgpIEBJbmplY3QoJ2NvbmZpZycpIHB1YmxpYyBtb2R1bGVDb25maWc6IEltYWdlVmlld2VyQ29uZmlnKSB7IH1cclxuXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xyXG4gICAgaWYgKGNoYW5nZXNbJ3NjcmVlbkhlaWdodE9jY3VwaWVkJ10pIHtcclxuICAgICAgdGhpcy5zdHlsZUhlaWdodCA9ICdjYWxjKDk4dmggLSAnICsgdGhpcy5zY3JlZW5IZWlnaHRPY2N1cGllZCArICdweCknO1xyXG4gICAgfSBlbHNlIGlmIChjaGFuZ2VzWydpbmRleCddKSB7XHJcbiAgICAgIHRoaXMucmVzZXQoKTtcclxuICAgIH1cclxuXHJcbiAgICBpZihjaGFuZ2VzWydzY2FsZUlucHV0J10gJiYgdGhpcy5jb25maWdbJ2lzWm9vbVBlcnNpc3RlbnQnXSkge1xyXG4gICAgICB0aGlzLnNjYWxlID0gY2hhbmdlc1snc2NhbGVJbnB1dCddLmN1cnJlbnRWYWx1ZTtcclxuICAgICAgdGhpcy51cGRhdGVTdHlsZSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcbiAgICBjb25zdCBtZXJnZWQgPSB0aGlzLm1lcmdlQ29uZmlnKERFRkFVTFRfQ09ORklHLCB0aGlzLm1vZHVsZUNvbmZpZyk7XHJcbiAgICB0aGlzLmNvbmZpZyA9IHRoaXMubWVyZ2VDb25maWcobWVyZ2VkLCB0aGlzLmNvbmZpZyk7XHJcbiAgICB0aGlzLnRyaWdnZXJDb25maWdCaW5kaW5nKCk7XHJcbiAgfVxyXG5cclxuICBuZ0FmdGVyQ29udGVudENoZWNrZWQoKTogdm9pZCB7XHJcbiAgICBpZiAoZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmRyYWctZWxlbWVudCcpWzBdKSB7XHJcbiAgICAgIGxldCBkcmFnRWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5kcmFnLWVsZW1lbnQnKVswXTtcclxuICAgICAgbGV0IGltZ0VsZW0gPSBkcmFnRWxlbWVudC5xdWVyeVNlbGVjdG9yKCdpbWcnKTtcclxuICAgICAgKGltZ0VsZW0gYXMgSFRNTEVsZW1lbnQpLnN0eWxlLnRyYW5zZm9ybSA9IGByb3RhdGUoJHt0aGlzLnJvdGF0aW9ufWRlZykgc2NhbGUoJHt0aGlzLnNjYWxlfSlgO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OmtleXVwLkFycm93UmlnaHQnLCBbJyRldmVudCddKVxyXG4gIG5leHRJbWFnZShldmVudDogTW91c2VFdmVudCkge1xyXG4gICAgaWYgKHRoaXMuY2FuTmF2aWdhdGUoZXZlbnQpICYmIHRoaXMuaW5kZXggPCB0aGlzLnNyYy5sZW5ndGggLSAxKSB7XHJcbiAgICAgIHRoaXMubG9hZGluZyA9IHRydWU7XHJcbiAgICAgIHRoaXMuaW5kZXgrKztcclxuICAgICAgdGhpcy50cmlnZ2VySW5kZXhCaW5kaW5nKCk7XHJcbiAgICAgIHRoaXMuZmlyZUN1c3RvbUV2ZW50KCduZXh0JywgdGhpcy5pbmRleCk7XHJcbiAgICAgIHRoaXMucmVzZXQoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzprZXl1cC5BcnJvd0xlZnQnLCBbJyRldmVudCddKVxyXG4gIHByZXZJbWFnZShldmVudDogTW91c2VFdmVudCkge1xyXG4gICAgaWYgKHRoaXMuY2FuTmF2aWdhdGUoZXZlbnQpICYmIHRoaXMuaW5kZXggPiAwKSB7XHJcbiAgICAgIHRoaXMubG9hZGluZyA9IHRydWU7XHJcbiAgICAgIHRoaXMuaW5kZXgtLTtcclxuICAgICAgdGhpcy50cmlnZ2VySW5kZXhCaW5kaW5nKCk7XHJcbiAgICAgIHRoaXMuZmlyZUN1c3RvbUV2ZW50KCdwcmV2JywgdGhpcy5pbmRleCk7XHJcbiAgICAgIHRoaXMucmVzZXQoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHpvb21JbigpIHtcclxuICAgIHRoaXMuc2NhbGUgKj0gKDEgKyB0aGlzLnVud3JhcCh0aGlzLmNvbmZpZy56b29tRmFjdG9yKSk7XHJcbiAgICB0aGlzLmZpcmVDdXN0b21FdmVudCgnem9vbUluJywgdGhpcy5zY2FsZSk7XHJcbiAgICB0aGlzLnVwZGF0ZVN0eWxlKCk7XHJcbiAgfVxyXG5cclxuICB6b29tT3V0KCkge1xyXG4gICAgaWYgKHRoaXMuc2NhbGUgPiB0aGlzLnVud3JhcCh0aGlzLmNvbmZpZy56b29tRmFjdG9yKSkge1xyXG4gICAgICB0aGlzLnNjYWxlIC89ICgxICsgdGhpcy51bndyYXAodGhpcy5jb25maWcuem9vbUZhY3RvcikpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5maXJlQ3VzdG9tRXZlbnQoJ3pvb21PdXQnLCB0aGlzLnNjYWxlKTtcclxuICAgIHRoaXMudXBkYXRlU3R5bGUoKTtcclxuICB9XHJcblxyXG4gIHNjcm9sbFpvb20oZXZ0OiBXaGVlbEV2ZW50KSB7XHJcbiAgICBpZiAodGhpcy5jb25maWcud2hlZWxab29tKSB7XHJcbiAgICAgIGV2dC5kZWx0YVkgPiAwID8gdGhpcy56b29tT3V0KCkgOiB0aGlzLnpvb21JbigpO1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRydWU7XHJcbiAgfVxyXG5cclxuICByb3RhdGVDbG9ja3dpc2UoKSB7XHJcbiAgICB0aGlzLnJvdGF0aW9uICs9IDkwO1xyXG4gICAgdGhpcy5maXJlQ3VzdG9tRXZlbnQoJ3JvdGF0ZUNsb2Nrd2lzZScsIHRoaXMucm90YXRpb24pO1xyXG4gICAgdGhpcy51cGRhdGVTdHlsZSgpO1xyXG4gIH1cclxuXHJcbiAgcm90YXRlQ291bnRlckNsb2Nrd2lzZSgpIHtcclxuICAgIHRoaXMucm90YXRpb24gLT0gOTA7XHJcbiAgICB0aGlzLnVwZGF0ZVN0eWxlKCk7XHJcbiAgfVxyXG5cclxuICBvbkxvYWQoKSB7XHJcbiAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcclxuICB9XHJcblxyXG4gIG9uTG9hZFN0YXJ0KCkge1xyXG4gICAgdGhpcy5sb2FkaW5nID0gdHJ1ZTtcclxuICB9XHJcblxyXG4gIGltYWdlTm90Rm91bmQoKSB7XHJcbiAgfVxyXG5cclxuICBvbkRyYWdTdGFydChldnQ6IGFueSkge1xyXG4gICAgaWYgKGV2dC5zb3VyY2UuX2RyYWdSZWYuX2luaXRpYWxUcmFuc2Zvcm0gJiYgZXZ0LnNvdXJjZS5fZHJhZ1JlZi5faW5pdGlhbFRyYW5zZm9ybS5sZW5ndGggPiAwKSB7XHJcbiAgICAgIGNvbnN0IG15VHJhbnNsYXRlID0gZXZ0LnNvdXJjZS5fZHJhZ1JlZi5faW5pdGlhbFRyYW5zZm9ybS5zcGxpdCgnIHJvdGF0ZScpWzBdO1xyXG4gICAgICBjb25zdCBteVJvdGF0ZSA9IHRoaXMuc3R5bGUudHJhbnNmb3JtLnNwbGl0KCcgcm90YXRlJylbMV07XHJcbiAgICAgIGV2dC5zb3VyY2UuX2RyYWdSZWYuX2luaXRpYWxUcmFuc2Zvcm0gPSBgJHtteVRyYW5zbGF0ZX0gcm90YXRlJHtteVJvdGF0ZX1gO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgZXZ0LnNvdXJjZS5fZHJhZ1JlZi5faW5pdGlhbFRyYW5zZm9ybSA9IHRoaXMuc3R5bGUudHJhbnNmb3JtO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgdG9nZ2xlRnVsbHNjcmVlbigpIHtcclxuICAgIHRoaXMuZnVsbHNjcmVlbiA9ICF0aGlzLmZ1bGxzY3JlZW47XHJcbiAgICBpZiAoIXRoaXMuZnVsbHNjcmVlbikge1xyXG4gICAgICB0aGlzLnJlc2V0KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB0cmlnZ2VySW5kZXhCaW5kaW5nKCkge1xyXG4gICAgdGhpcy5pbmRleENoYW5nZS5lbWl0KHRoaXMuaW5kZXgpO1xyXG4gIH1cclxuXHJcbiAgdHJpZ2dlckNvbmZpZ0JpbmRpbmcoKSB7XHJcbiAgICB0aGlzLmNvbmZpZ0NoYW5nZS5uZXh0KHRoaXMuY29uZmlnKTtcclxuICB9XHJcblxyXG4gIGZpcmVDdXN0b21FdmVudChuYW1lOiBzdHJpbmcsIGltYWdlSW5kZXg6IG51bWJlcikge1xyXG4gICAgdGhpcy5jdXN0b21JbWFnZUV2ZW50LmVtaXQobmV3IEN1c3RvbUltYWdlRXZlbnQobmFtZSwgaW1hZ2VJbmRleCkpO1xyXG4gIH1cclxuXHJcbiAgcmVzZXQoKSB7XHJcbiAgICBpZighdGhpcy5jb25maWcuaXNab29tUGVyc2lzdGVudCkge1xyXG4gICAgICB0aGlzLnNjYWxlID0gMTtcclxuICAgICAgdGhpcy5yb3RhdGlvbiA9IDA7XHJcbiAgICAgIHRoaXMudXBkYXRlU3R5bGUoKTtcclxuICAgICAgdGhpcy5jZGtEcmFnLnJlc2V0KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBASG9zdExpc3RlbmVyKCdtb3VzZW92ZXInKVxyXG4gIG9uTW91c2VPdmVyKCkge1xyXG4gICAgdGhpcy5ob3ZlcmVkID0gdHJ1ZTtcclxuICB9XHJcblxyXG4gIEBIb3N0TGlzdGVuZXIoJ21vdXNlbGVhdmUnKVxyXG4gIG9uTW91c2VMZWF2ZSgpIHtcclxuICAgIHRoaXMuaG92ZXJlZCA9IGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjYW5OYXZpZ2F0ZShldmVudDogYW55KSB7XHJcbiAgICBpZiAoZXZlbnQudHlwZSA9PT0gJ2tleXVwJykge1xyXG4gICAgICByZXR1cm4gKHRoaXMuY29uZmlnLmFsbG93S2V5Ym9hcmROYXZpZ2F0aW9uICYmIHRoaXMuaG92ZXJlZCk7XHJcbiAgICB9IGVsc2UgaWYgKGV2ZW50LnR5cGUgPT09ICdjbGljaycpIHtcclxuICAgICAgcmV0dXJuIHRoaXMuaG92ZXJlZDtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdXBkYXRlU3R5bGUoKSB7XHJcbiAgICB0aGlzLnN0eWxlLnRyYW5zZm9ybSA9IGByb3RhdGUoJHt0aGlzLnJvdGF0aW9ufWRlZykgc2NhbGUoJHt0aGlzLnNjYWxlfSlgO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBtZXJnZUNvbmZpZyhkZWZhdWx0VmFsdWVzOiBJbWFnZVZpZXdlckNvbmZpZywgb3ZlcnJpZGVWYWx1ZXM6IEltYWdlVmlld2VyQ29uZmlnKTogSW1hZ2VWaWV3ZXJDb25maWcge1xyXG4gICAgbGV0IHJlc3VsdDogSW1hZ2VWaWV3ZXJDb25maWcgPSB7IC4uLmRlZmF1bHRWYWx1ZXMgfTtcclxuICAgIGlmIChvdmVycmlkZVZhbHVlcykge1xyXG4gICAgICByZXN1bHQgPSB7IC4uLmRlZmF1bHRWYWx1ZXMsIC4uLm92ZXJyaWRlVmFsdWVzIH07XHJcblxyXG4gICAgICBpZiAob3ZlcnJpZGVWYWx1ZXMuYnRuSWNvbnMpIHtcclxuICAgICAgICByZXN1bHQuYnRuSWNvbnMgPSB7IC4uLmRlZmF1bHRWYWx1ZXMuYnRuSWNvbnMsIC4uLm92ZXJyaWRlVmFsdWVzLmJ0bkljb25zIH07XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHVud3JhcCA9IChuOiBudW1iZXJ8dW5kZWZpbmVkKTogbnVtYmVyID0+IG4/bjowO1xyXG59XHJcbiIsIjxkaXYgW2FwcFNjcmVlbmZ1bGxdPVwiZnVsbHNjcmVlblwiIGNsYXNzPVwiaW1nLWNvbnRhaW5lclwiIFtzdHlsZS5iYWNrZ3JvdW5kQ29sb3JdPVwiY29uZmlnLmNvbnRhaW5lckJhY2tncm91bmRDb2xvclwiXHJcbiAgICAod2hlZWwpPVwic2Nyb2xsWm9vbSgkZXZlbnQpXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwiaW1hZ2UtbmFtZVwiICpuZ0lmPVwiaW1hZ2VOYW1lXCI+XHJcbiAgICAgIDxzcGFuPnt7aW1hZ2VOYW1lfX08L3NwYW4+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8ZGl2IGNka0RyYWcgY2xhc3M9XCJkcmFnLWVsZW1lbnRcIj5cclxuICAgICAgICA8aW1nIFtzcmNdPVwic3JjW2luZGV4XVwiIFtuZ1N0eWxlXT1cInN0eWxlXCIgYWx0PVwiXCJcclxuICAgICAgICAgICAgKGNka0RyYWdTdGFydGVkKT1cIm9uRHJhZ1N0YXJ0KCRldmVudClcIlxyXG4gICAgICAgICAgICAobG9hZCk9XCJvbkxvYWQoKVwiIChsb2Fkc3RhcnQpPVwib25Mb2FkU3RhcnQoKVwiIChlcnJvcik9XCJpbWFnZU5vdEZvdW5kKClcIiAvPlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPGRpdiBjbGFzcz1cInNwaW5uZXItY29udGFpbmVyXCIgKm5nSWY9XCJsb2FkaW5nXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInNwaW5uZXJcIj48L2Rpdj5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDxkaXYgY2xhc3M9XCJidXR0b24tY29udGFpbmVyXCI+XHJcbiAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgaWQ9XCJuZ3gtZnMtYnRuXCIgW2NsYXNzXT1cImNvbmZpZy5idG5DbGFzc1wiIChjbGljayk9XCJ0b2dnbGVGdWxsc2NyZWVuKClcIlxyXG4gICAgICAgIFtzdHlsZS5jb2xvcl09XCJjb25maWcucHJpbWFyeUNvbG9yXCIgKm5nSWY9XCJjb25maWcuYWxsb3dGdWxsc2NyZWVuXCI+XHJcbiAgICAgICAgICAgIDxzcGFuIFtjbGFzc109XCJjb25maWcuYnRuSWNvbnM/LmZ1bGxzY3JlZW5cIj48L3NwYW4+XHJcbiAgICAgICAgPC9idXR0b24+XHJcblxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJidXR0b24tY29udGFpbmVyLWJvdHRvbVwiPlxyXG4gICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBbY2xhc3NdPVwiY29uZmlnLmJ0bkNsYXNzXCIgKm5nRm9yPVwibGV0IGNCdG4gb2YgY29uZmlnLmN1c3RvbUJ0bnNcIlxyXG4gICAgICAgICAgICBbc3R5bGUuY29sb3JdPVwiY29uZmlnLnByaW1hcnlDb2xvclwiIChjbGljayk9XCJmaXJlQ3VzdG9tRXZlbnQoY0J0bi5uYW1lLCBpbmRleClcIj5cclxuICAgICAgICAgICAgICAgIDxzcGFuIFtjbGFzc109XCJjQnRuLmljb25cIj48L3NwYW4+XHJcbiAgICAgICAgICAgIDwvYnV0dG9uPlxyXG5cclxuICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgW2NsYXNzXT1cImNvbmZpZy5idG5DbGFzc1wiICpuZ0lmPVwiY29uZmlnLmJ0blNob3c/LnJvdGF0ZUNvdW50ZXJDbG9ja3dpc2VcIlxyXG4gICAgICAgICAgICBbc3R5bGUuY29sb3JdPVwiY29uZmlnLnByaW1hcnlDb2xvclwiIChjbGljayk9XCJyb3RhdGVDb3VudGVyQ2xvY2t3aXNlKClcIj5cclxuICAgICAgICAgICAgICAgIDxzcGFuIFtjbGFzc109XCJjb25maWcuYnRuSWNvbnM/LnJvdGF0ZUNvdW50ZXJDbG9ja3dpc2VcIj48L3NwYW4+XHJcbiAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBbY2xhc3NdPVwiY29uZmlnLmJ0bkNsYXNzXCIgKm5nSWY9XCJjb25maWcuYnRuU2hvdz8ucm90YXRlQ2xvY2t3aXNlXCJcclxuICAgICAgICAgICAgW3N0eWxlLmNvbG9yXT1cImNvbmZpZy5wcmltYXJ5Q29sb3JcIiAoY2xpY2spPVwicm90YXRlQ2xvY2t3aXNlKClcIj5cclxuICAgICAgICAgICAgICAgIDxzcGFuIFtjbGFzc109XCJjb25maWcuYnRuSWNvbnM/LnJvdGF0ZUNsb2Nrd2lzZVwiPjwvc3Bhbj5cclxuICAgICAgICAgICAgPC9idXR0b24+XHJcblxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYnV0dG9uLXpvb20taW4tb3V0LWNvbnRhaW5lclwiPlxyXG4gICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgW2NsYXNzXT1cImNvbmZpZy5idG5DbGFzc1wiICpuZ0lmPVwiY29uZmlnLmJ0blNob3c/Lnpvb21JblwiXHJcbiAgICAgICAgICAgICAgICBbc3R5bGUuY29sb3JdPVwiY29uZmlnLnByaW1hcnlDb2xvclwiIChjbGljayk9XCJ6b29tSW4oKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxzcGFuIFtjbGFzc109XCJjb25maWcuYnRuSWNvbnM/Lnpvb21JblwiPjwvc3Bhbj5cclxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgW2NsYXNzXT1cImNvbmZpZy5idG5DbGFzc1wiICpuZ0lmPVwiY29uZmlnLmJ0blNob3c/Lnpvb21PdXRcIlxyXG4gICAgICAgICAgICAgICAgW3N0eWxlLmNvbG9yXT1cImNvbmZpZy5wcmltYXJ5Q29sb3JcIiAoY2xpY2spPVwiem9vbU91dCgpXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gW2NsYXNzXT1cImNvbmZpZy5idG5JY29ucz8uem9vbU91dFwiPjwvc3Bhbj5cclxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDxkaXYgY2xhc3M9XCJuYXYtYnV0dG9uLWNvbnRhaW5lclwiICpuZ0lmPVwic3JjLmxlbmd0aCA+IDFcIj5cclxuICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiAjcHJldkltZyBbY2xhc3NdPVwiY29uZmlnLmJ0bkNsYXNzXCIgKGNsaWNrKT1cInByZXZJbWFnZSgkZXZlbnQpOyBwcmV2SW1nLmJsdXIoKVwiXHJcbiAgICAgICAgW3N0eWxlLmNvbG9yXT1cImNvbmZpZy5wcmltYXJ5Q29sb3JcIiAgW2Rpc2FibGVkXT1cImluZGV4ID09PSAwXCI+XHJcbiAgICAgICAgICAgIDxzcGFuIFtjbGFzc109XCJjb25maWcuYnRuSWNvbnM/LnByZXZcIj48L3NwYW4+XHJcbiAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgI25leHRJbWcgW2NsYXNzXT1cImNvbmZpZy5idG5DbGFzc1wiIChjbGljayk9XCJuZXh0SW1hZ2UoJGV2ZW50KTsgbmV4dEltZy5ibHVyKClcIlxyXG4gICAgICAgIFtzdHlsZS5jb2xvcl09XCJjb25maWcucHJpbWFyeUNvbG9yXCIgIFtkaXNhYmxlZF09XCJpbmRleCA9PT0gc3JjLmxlbmd0aCAtIDFcIj5cclxuICAgICAgICAgICAgPHNwYW4gW2NsYXNzXT1cImNvbmZpZy5idG5JY29ucz8ubmV4dFwiPjwvc3Bhbj5cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgIDwvZGl2PlxyXG4gICAgPGRpdiBjbGFzcz1cImZvb3Rlci1zZWN0aW9uXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImltYWdlLXR4dC1jb3VudC1sZWZ0LWFsaWduXCI+PHNwYW4+e3tmb290ZXJUZXh0c1swXX19IHt7aW5kZXggKyAxfX0ge3tmb290ZXJUZXh0c1sxXX19IHt7c3JjLmxlbmd0aH19PC9zcGFuPjwvZGl2PlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJmb290ZXItdHh0LXJpZ2h0LWFsaWduXCI+XHJcbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZm9vdGVyLXR4dC1yaWdodC1hbGlnbi10aXRsZVwiIFtzdHlsZS5jb2xvcl09XCJjb25maWcucHJpbWFyeUNvbG9yXCI+e3tmb290ZXJUZXh0c1syXX19PC9zcGFuPlxyXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImZvb3Rlci10eHQtcmlnaHQtYWxpZ24tbm90ZVwiPnt7Zm9vdGVyVGV4dHNbM119fTwvc3Bhbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG48L2Rpdj5cclxuIl19