ng-image-slider-v17
Version:
Angular Image slider with lightbox. An Angular responsive image slider with lightbox popup. Also support youtube url, image base64 string and mp4 video urls and base64 string.
240 lines • 41.6 kB
JavaScript
import { Component, Inject, Input, Output, EventEmitter, ViewChild, HostListener } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import * as i0 from "@angular/core";
import * as i1 from "@angular/platform-browser";
import * as i2 from "@angular/common";
import * as i3 from "../slider-custom-image/slider-custom-image.component";
const LIGHTBOX_NEXT_ARROW_CLICK_MESSAGE = 'lightbox next', LIGHTBOX_PREV_ARROW_CLICK_MESSAGE = 'lightbox previous';
export class SliderLightboxComponent {
set imageIndex(index) {
if (index !== undefined && index > -1 && index < this.images.length) {
this.currentImageIndex = index;
}
this.nextPrevDisable();
}
set show(visiableFlag) {
this.imageFullscreenView = visiableFlag;
this.elRef.nativeElement.ownerDocument.body.style.overflow = '';
if (visiableFlag === true) {
this.elRef.nativeElement.ownerDocument.body.style.overflow = 'hidden';
// this.getImageData();
this.setPopupSliderWidth();
}
}
set animationSpeed(data) {
if (data
&& typeof (data) === 'number'
&& data >= 0.1
&& data <= 5) {
this.speed = data;
}
}
onResize(event) {
this.effectStyle = 'none';
this.setPopupSliderWidth();
}
handleKeyboardEvent(event) {
if (event && event.key && this.arrowKeyMove) {
if (event.key.toLowerCase() === 'arrowright') {
this.nextImageLightbox();
}
if (event.key.toLowerCase() === 'arrowleft') {
this.prevImageLightbox();
}
if (event.key.toLowerCase() === 'escape') {
this.closeLightbox();
}
}
}
constructor(cdRef, sanitizer, elRef, document) {
this.cdRef = cdRef;
this.sanitizer = sanitizer;
this.elRef = elRef;
this.document = document;
this.totalImages = 0;
this.nextImageIndex = -1;
this.popupWidth = 1200;
this.marginLeft = 0;
this.imageFullscreenView = false;
this.lightboxPrevDisable = false;
this.lightboxNextDisable = false;
this.showLoading = true;
this.effectStyle = 'none';
this.speed = 1; // default speed in second
this.title = '';
this.currentImageIndex = 0;
// @Inputs
this.images = [];
this.videoAutoPlay = false;
this.direction = 'ltr';
this.paginationShow = false;
this.infinite = false;
this.arrowKeyMove = true;
this.showVideoControls = true;
// @Output
this.close = new EventEmitter();
this.prevImage = new EventEmitter();
this.nextImage = new EventEmitter();
}
ngOnInit() {
}
ngAfterViewInit() {
}
ngOnDestroy() {
this.resetState();
}
setPopupSliderWidth() {
if (window && window.innerWidth) {
this.popupWidth = window.innerWidth;
this.totalImages = this.images.length;
if (typeof (this.currentImageIndex) === 'number' && this.currentImageIndex !== undefined) {
this.marginLeft = -1 * this.popupWidth * this.currentImageIndex;
this.getImageData();
this.nextPrevDisable();
setTimeout(() => {
this.showLoading = false;
}, 500);
}
}
}
closeLightbox() {
this.close.emit();
}
prevImageLightbox() {
this.effectStyle = `all ${this.speed}s ease-in-out`;
if (this.currentImageIndex > 0 && !this.lightboxPrevDisable) {
this.currentImageIndex--;
this.prevImage.emit(LIGHTBOX_PREV_ARROW_CLICK_MESSAGE);
this.marginLeft = -1 * this.popupWidth * this.currentImageIndex;
this.getImageData();
this.nextPrevDisable();
}
}
nextImageLightbox() {
this.effectStyle = `all ${this.speed}s ease-in-out`;
if (this.currentImageIndex < this.images.length - 1 && !this.lightboxNextDisable) {
this.currentImageIndex++;
this.nextImage.emit(LIGHTBOX_NEXT_ARROW_CLICK_MESSAGE);
this.marginLeft = -1 * this.popupWidth * this.currentImageIndex;
this.getImageData();
this.nextPrevDisable();
}
}
nextPrevDisable() {
this.lightboxNextDisable = true;
this.lightboxPrevDisable = true;
setTimeout(() => {
this.applyButtonDisableCondition();
}, this.speed * 1000);
}
applyButtonDisableCondition() {
this.lightboxNextDisable = false;
this.lightboxPrevDisable = false;
if (!this.infinite && this.currentImageIndex >= this.images.length - 1) {
this.lightboxNextDisable = true;
}
if (!this.infinite && this.currentImageIndex <= 0) {
this.lightboxPrevDisable = true;
}
}
getImageData() {
if (this.images
&& this.images.length
&& typeof (this.currentImageIndex) === 'number'
&& this.currentImageIndex !== undefined
&& this.images[this.currentImageIndex]
&& (this.images[this.currentImageIndex]['image'] || this.images[this.currentImageIndex]['video'])) {
this.title = this.images[this.currentImageIndex]['title'] || '';
this.totalImages = this.images.length;
for (const iframeI in this.document.getElementsByTagName('iframe')) {
if (this.document.getElementsByTagName('iframe')[iframeI]
&& this.document.getElementsByTagName('iframe')[iframeI].contentWindow
&& this.document.getElementsByTagName('iframe')[iframeI].contentWindow.postMessage) {
this.document.getElementsByTagName('iframe')[iframeI].contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*');
}
}
for (const videoI in this.document.getElementsByTagName('video')) {
if (this.document.getElementsByTagName('video')[videoI] && this.document.getElementsByTagName('video')[videoI].pause) {
this.document.getElementsByTagName('video')[videoI].pause();
}
}
}
}
resetState() {
this.images = [];
}
/**
* Swipe event handler
* Reference from https://stackoverflow.com/a/44511007/2067646
*/
swipeLightboxImg(e, when) {
const coord = [e.changedTouches[0].pageX, e.changedTouches[0].pageY];
const time = new Date().getTime();
if (when === 'start') {
this.swipeLightboxImgCoord = coord;
this.swipeLightboxImgTime = time;
}
else if (when === 'end') {
const direction = [coord[0] - this.swipeLightboxImgCoord[0], coord[1] - this.swipeLightboxImgCoord[1]];
const duration = time - this.swipeLightboxImgTime;
if (duration < 1000 //
&& Math.abs(direction[0]) > 30 // Long enough
&& Math.abs(direction[0]) > Math.abs(direction[1] * 3)) { // Horizontal enough
if (direction[0] < 0) {
this.nextImageLightbox();
}
else {
this.prevImageLightbox();
}
}
}
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: SliderLightboxComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.DomSanitizer }, { token: i0.ElementRef }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); }
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.8", type: SliderLightboxComponent, selector: "slider-lightbox", inputs: { images: "images", imageIndex: "imageIndex", show: "show", videoAutoPlay: "videoAutoPlay", direction: "direction", paginationShow: "paginationShow", animationSpeed: "animationSpeed", infinite: "infinite", arrowKeyMove: "arrowKeyMove", showVideoControls: "showVideoControls" }, outputs: { close: "close", prevImage: "prevImage", nextImage: "nextImage" }, host: { listeners: { "window:resize": "onResize($event)", "document:keyup": "handleKeyboardEvent($event)" } }, viewQueries: [{ propertyName: "lightboxDiv", first: true, predicate: ["lightboxDiv"], descendants: true }, { propertyName: "lightboxImageDiv", first: true, predicate: ["lightboxImageDiv"], descendants: true }], ngImport: i0, template: "<div *ngIf=\"imageFullscreenView\" class=\"ng-image-fullscreen-view\">\r\n <div class=\"lightbox-wrapper\">\r\n <a class=\"close\" (click)=\"closeLightbox()\"></a>\r\n <div class=\"lightbox-div\" #lightboxDiv>\r\n <div *ngIf=\"showLoading\" class=\"pre-loader\">\r\n <div class=\"mnml-spinner\"></div>\r\n </div>\r\n <div class=\"lightbox-image-main\"\r\n [ngStyle]=\"{'margin-left': marginLeft + 'px', 'grid-template-columns': 'repeat('+images.length+',1fr)', 'transition': effectStyle}\">\r\n <div class=\"lightbox-image\"\r\n [ngStyle]=\"{'width': popupWidth + 'px'}\"\r\n *ngFor=\"let img of images; let i = index\"\r\n [attr.id]=\"'ng-lightbox-image-' + i\"\r\n (touchstart)=\"swipeLightboxImg($event, 'start')\"\r\n (touchend)=\"swipeLightboxImg($event, 'end')\"\r\n #lightboxImageDiv>\r\n <div class=\"close-outside\" (click)=\"!img?.video && closeLightbox()\"></div>\r\n <custom-img\r\n [imageUrl]=\"img?.image || img?.video\"\r\n [isVideo]=\"!!(img?.posterImage || img?.video)\"\r\n [currentImageIndex]=\"currentImageIndex\"\r\n [imageIndex]=\"i\"\r\n [speed]=\"speed\"\r\n [videoAutoPlay]=\"videoAutoPlay && i == currentImageIndex\"\r\n [showVideoControls]=\"showVideoControls ? 1 : 0\"\r\n [alt]=\"img?.alt || img?.title || ''\"\r\n [title]=\"img?.title || img?.alt || ''\"\r\n [showVideo]=\"true\"\r\n [direction]=\"direction\">\r\n </custom-img>\r\n </div>\r\n </div>\r\n <div [dir]=\"direction\" [ngClass]=\"{'show': title, 'hide': !title}\" class=\"caption\">{{ title }}</div>\r\n <a *ngIf=\"images.length > 1\" [ngClass]=\"{'disable': lightboxPrevDisable}\" class=\"prev icons prev-icon\" (click)=\"prevImageLightbox()\">‹</a>\r\n <a *ngIf=\"images.length > 1\" [ngClass]=\"{'disable': lightboxNextDisable}\" class=\"next icons next-icon\" (click)=\"nextImageLightbox()\">›</a>\r\n </div>\r\n </div>\r\n <div *ngIf=\"paginationShow\" class=\"popup-pagination\">{{currentImageIndex + 1}} of {{totalImages}}</div>\r\n</div>\r\n", dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i3.SliderCustomImageComponent, selector: "custom-img", inputs: ["showVideo", "videoAutoPlay", "showVideoControls", "currentImageIndex", "imageIndex", "speed", "imageUrl", "isVideo", "alt", "title", "direction", "ratio", "lazy"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: SliderLightboxComponent, decorators: [{
type: Component,
args: [{ selector: 'slider-lightbox', template: "<div *ngIf=\"imageFullscreenView\" class=\"ng-image-fullscreen-view\">\r\n <div class=\"lightbox-wrapper\">\r\n <a class=\"close\" (click)=\"closeLightbox()\"></a>\r\n <div class=\"lightbox-div\" #lightboxDiv>\r\n <div *ngIf=\"showLoading\" class=\"pre-loader\">\r\n <div class=\"mnml-spinner\"></div>\r\n </div>\r\n <div class=\"lightbox-image-main\"\r\n [ngStyle]=\"{'margin-left': marginLeft + 'px', 'grid-template-columns': 'repeat('+images.length+',1fr)', 'transition': effectStyle}\">\r\n <div class=\"lightbox-image\"\r\n [ngStyle]=\"{'width': popupWidth + 'px'}\"\r\n *ngFor=\"let img of images; let i = index\"\r\n [attr.id]=\"'ng-lightbox-image-' + i\"\r\n (touchstart)=\"swipeLightboxImg($event, 'start')\"\r\n (touchend)=\"swipeLightboxImg($event, 'end')\"\r\n #lightboxImageDiv>\r\n <div class=\"close-outside\" (click)=\"!img?.video && closeLightbox()\"></div>\r\n <custom-img\r\n [imageUrl]=\"img?.image || img?.video\"\r\n [isVideo]=\"!!(img?.posterImage || img?.video)\"\r\n [currentImageIndex]=\"currentImageIndex\"\r\n [imageIndex]=\"i\"\r\n [speed]=\"speed\"\r\n [videoAutoPlay]=\"videoAutoPlay && i == currentImageIndex\"\r\n [showVideoControls]=\"showVideoControls ? 1 : 0\"\r\n [alt]=\"img?.alt || img?.title || ''\"\r\n [title]=\"img?.title || img?.alt || ''\"\r\n [showVideo]=\"true\"\r\n [direction]=\"direction\">\r\n </custom-img>\r\n </div>\r\n </div>\r\n <div [dir]=\"direction\" [ngClass]=\"{'show': title, 'hide': !title}\" class=\"caption\">{{ title }}</div>\r\n <a *ngIf=\"images.length > 1\" [ngClass]=\"{'disable': lightboxPrevDisable}\" class=\"prev icons prev-icon\" (click)=\"prevImageLightbox()\">‹</a>\r\n <a *ngIf=\"images.length > 1\" [ngClass]=\"{'disable': lightboxNextDisable}\" class=\"next icons next-icon\" (click)=\"nextImageLightbox()\">›</a>\r\n </div>\r\n </div>\r\n <div *ngIf=\"paginationShow\" class=\"popup-pagination\">{{currentImageIndex + 1}} of {{totalImages}}</div>\r\n</div>\r\n" }]
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.DomSanitizer }, { type: i0.ElementRef }, { type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }], propDecorators: { lightboxDiv: [{
type: ViewChild,
args: ['lightboxDiv', { static: false }]
}], lightboxImageDiv: [{
type: ViewChild,
args: ['lightboxImageDiv', { static: false }]
}], images: [{
type: Input
}], imageIndex: [{
type: Input
}], show: [{
type: Input
}], videoAutoPlay: [{
type: Input
}], direction: [{
type: Input
}], paginationShow: [{
type: Input
}], animationSpeed: [{
type: Input
}], infinite: [{
type: Input
}], arrowKeyMove: [{
type: Input
}], showVideoControls: [{
type: Input
}], close: [{
type: Output
}], prevImage: [{
type: Output
}], nextImage: [{
type: Output
}], onResize: [{
type: HostListener,
args: ['window:resize', ['$event']]
}], handleKeyboardEvent: [{
type: HostListener,
args: ['document:keyup', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2xpZGVyLWxpZ2h0Ym94LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25nLWltYWdlLXNsaWRlci9zcmMvbGliL3NsaWRlci1saWdodGJveC9zbGlkZXItbGlnaHRib3guY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctaW1hZ2Utc2xpZGVyL3NyYy9saWIvc2xpZGVyLWxpZ2h0Ym94L3NsaWRlci1saWdodGJveC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUgsU0FBUyxFQUlULE1BQU0sRUFHTixLQUFLLEVBQ0wsTUFBTSxFQUNOLFlBQVksRUFDWixTQUFTLEVBQ1QsWUFBWSxFQUVmLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQzs7Ozs7QUFHM0MsTUFBTSxpQ0FBaUMsR0FBRyxlQUFlLEVBQ3JELGlDQUFpQyxHQUFHLG1CQUFtQixDQUFBO0FBTTNELE1BQU0sT0FBTyx1QkFBdUI7SUF1QmhDLElBQ0ksVUFBVSxDQUFDLEtBQWE7UUFDeEIsSUFBSSxLQUFLLEtBQUssU0FBUyxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUMsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUU7WUFDakUsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEtBQUssQ0FBQztTQUNsQztRQUNELElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBQ0QsSUFDSSxJQUFJLENBQUMsWUFBcUI7UUFDMUIsSUFBSSxDQUFDLG1CQUFtQixHQUFHLFlBQVksQ0FBQztRQUN4QyxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO1FBQ2hFLElBQUksWUFBWSxLQUFL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O3NCQUF0QixLQUFLO2dCQUVGLGNBQWM7c0JBRGpCLEtBQUs7Z0JBU0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxZQUFZO3NCQUFwQixLQUFLO2dCQUNHLGlCQUFpQjtzQkFBekIsS0FBSztnQkFHSSxLQUFLO3NCQUFkLE1BQU07Z0JBQ0csU0FBUztzQkFBbEIsTUFBTTtnQkFDRyxTQUFTO3NCQUFsQixNQUFNO2dCQUdQLFFBQVE7c0JBRFAsWUFBWTt1QkFBQyxlQUFlLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBTXpDLG1CQUFtQjtzQkFEbEIsWUFBWTt1QkFBQyxnQkFBZ0IsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgICBDaGFuZ2VEZXRlY3RvclJlZixcclxuICAgIENvbXBvbmVudCxcclxuICAgIE9uSW5pdCxcclxuICAgIE9uQ2hhbmdlcyxcclxuICAgIFNpbXBsZUNoYW5nZXMsXHJcbiAgICBJbmplY3QsXHJcbiAgICBBZnRlclZpZXdJbml0LFxyXG4gICAgT25EZXN0cm95LFxyXG4gICAgSW5wdXQsXHJcbiAgICBPdXRwdXQsXHJcbiAgICBFdmVudEVtaXR0ZXIsXHJcbiAgICBWaWV3Q2hpbGQsXHJcbiAgICBIb3N0TGlzdGVuZXIsXHJcbiAgICBFbGVtZW50UmVmXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IERPQ1VNRU5UIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHsgRG9tU2FuaXRpemVyIH0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlcic7XHJcblxyXG5jb25zdCBMSUdIVEJPWF9ORVhUX0FSUk9XX0NMSUNLX01FU1NBR0UgPSAnbGlnaHRib3ggbmV4dCcsXHRcclxuICAgIExJR0hUQk9YX1BSRVZfQVJST1dfQ0xJQ0tfTUVTU0FHRSA9ICdsaWdodGJveCBwcmV2aW91cydcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gICAgc2VsZWN0b3I6ICdzbGlkZXItbGlnaHRib3gnLFxyXG4gICAgdGVtcGxhdGVVcmw6ICcuL3NsaWRlci1saWdodGJveC5jb21wb25lbnQuaHRtbCdcclxufSlcclxuZXhwb3J0IGNsYXNzIFNsaWRlckxpZ2h0Ym94Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xyXG4gICAgdG90YWxJbWFnZXM6IG51bWJlciA9IDA7XHJcbiAgICBuZXh0SW1hZ2VJbmRleDogbnVtYmVyID0gLTE7XHJcbiAgICBwb3B1cFdpZHRoOiBudW1iZXIgPSAxMjAwO1xyXG4gICAgbWFyZ2luTGVmdDogbnVtYmVyID0gMDtcclxuICAgIGltYWdlRnVsbHNjcmVlblZpZXc6IGJvb2xlYW4gPSBmYWxzZTtcclxuICAgIGxpZ2h0Ym94UHJldkRpc2FibGU6IGJvb2xlYW4gPSBmYWxzZTtcclxuICAgIGxpZ2h0Ym94TmV4dERpc2FibGU6IGJvb2xlYW4gPSBmYWxzZTtcclxuICAgIHNob3dMb2FkaW5nOiBib29sZWFuID0gdHJ1ZTtcclxuICAgIGVmZmVjdFN0eWxlOiBzdHJpbmcgPSAnbm9uZSc7XHJcbiAgICBzcGVlZDogbnVtYmVyID0gMTsgLy8gZGVmYXVsdCBzcGVlZCBpbiBzZWNvbmRcclxuICAgIHRpdGxlOiBzdHJpbmcgPSAnJztcclxuICAgIGN1cnJlbnRJbWFnZUluZGV4OiBudW1iZXIgPSAwO1xyXG5cclxuICAgIC8vIGZvciBzd2lwZSBldmVudFxyXG4gICAgcHJpdmF0ZSBzd2lwZUxpZ2h0Ym94SW1nQ29vcmQ/OiBbbnVtYmVyLCBudW1iZXJdO1xyXG4gICAgcHJpdmF0ZSBzd2lwZUxpZ2h0Ym94SW1nVGltZT86IG51bWJlcjtcclxuXHJcbiAgICBAVmlld0NoaWxkKCdsaWdodGJveERpdicsIHsgc3RhdGljOiBmYWxzZSB9KSBsaWdodGJveERpdjtcclxuICAgIEBWaWV3Q2hpbGQoJ2xpZ2h0Ym94SW1hZ2VEaXYnLCB7IHN0YXRpYzogZmFsc2UgfSkgbGlnaHRib3hJbWFnZURpdjtcclxuXHJcbiAgICAvLyBASW5wdXRzXHJcbiAgICBASW5wdXQoKSBpbWFnZXM6IEFycmF5PG9iamVjdD4gPSBbXTtcclxuICAgIEBJbnB1dCgpXHJcbiAgICBzZXQgaW1hZ2VJbmRleChpbmRleDogbnVtYmVyKSB7XHJcbiAgICAgICAgaWYgKGluZGV4ICE9PSB1bmRlZmluZWQgJiYgaW5kZXggPiAtMSAmJiBpbmRleCA8IHRoaXMuaW1hZ2VzLmxlbmd0aCkge1xyXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRJbWFnZUluZGV4ID0gaW5kZXg7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMubmV4dFByZXZEaXNhYmxlKCk7XHJcbiAgICB9XHJcbiAgICBASW5wdXQoKVxyXG4gICAgc2V0IHNob3codmlzaWFibGVGbGFnOiBib29sZWFuKSB7XHJcbiAgICAgICAgdGhpcy5pbWFnZUZ1bGxzY3JlZW5WaWV3ID0gdmlzaWFibGVGbGFnO1xyXG4gICAgICAgIHRoaXMuZWxSZWYubmF0aXZlRWxlbWVudC5vd25lckRvY3VtZW50LmJvZHkuc3R5bGUub3ZlcmZsb3cgPSAnJztcclxuICAgICAgICBpZiAodmlzaWFibGVGbGFnID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuZWxSZWYubmF0aXZlRWxlbWVudC5vd25lckRvY3VtZW50LmJvZHkuc3R5bGUub3ZlcmZsb3cgPSAnaGlkZGVuJztcclxuICAgICAgICAgICAgLy8gdGhpcy5nZXRJbWFnZURhdGEoKTtcclxuICAgICAgICAgICAgdGhpcy5zZXRQb3B1cFNsaWRlcldpZHRoKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgQElucHV0KCkgdmlkZW9BdXRvUGxheTogYm9vbGVhbiA9IGZhbHNlO1xyXG4gICAgQElucHV0KCkgZGlyZWN0aW9uOiBzdHJpbmcgPSAnbHRyJztcclxuICAgIEBJbnB1dCgpIHBhZ2luYXRpb25TaG93OiBib29sZWFuID0gZmFsc2U7XHJcbiAgICBASW5wdXQoKVxyXG4gICAgc2V0IGFuaW1hdGlvblNwZWVkKGRhdGE6IG51bWJlcikge1xyXG4gICAgICAgIGlmIChkYXRhXHJcbiAgICAgICAgICAgICYmIHR5cGVvZiAoZGF0YSkgPT09ICdudW1iZXInXHJcbiAgICAgICAgICAgICYmIGRhdGEgPj0gMC4xXHJcbiAgICAgICAgICAgICYmIGRhdGEgPD0gNSkge1xyXG4gICAgICAgICAgICB0aGlzLnNwZWVkID0gZGF0YTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBASW5wdXQoKSBpbmZpbml0ZTogYm9vbGVhbiA9IGZhbHNlO1xyXG4gICAgQElucHV0KCkgYXJyb3dLZXlNb3ZlOiBib29sZWFuID0gdHJ1ZTtcclxuICAgIEBJbnB1dCgpIHNob3dWaWRlb0NvbnRyb2xzOiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgICAvLyBAT3V0cHV0XHJcbiAgICBAT3V0cHV0KCkgY2xvc2UgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcclxuICAgIEBPdXRwdXQoKSBwcmV2SW1hZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcclxuICAgIEBPdXRwdXQoKSBuZXh0SW1hZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcclxuXHJcbiAgICBASG9zdExpc3RlbmVyKCd3aW5kb3c6cmVzaXplJywgWyckZXZlbnQnXSlcclxuICAgIG9uUmVzaXplKGV2ZW50KSB7XHJcbiAgICAgICAgdGhpcy5lZmZlY3RTdHlsZSA9ICdub25lJztcclxuICAgICAgICB0aGlzLnNldFBvcHVwU2xpZGVyV2lkdGgoKTtcclxuICAgIH1cclxuICAgIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmtleXVwJywgWyckZXZlbnQnXSlcclxuICAgIGhhbmRsZUtleWJvYXJkRXZlbnQoZXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcclxuICAgICAgICBpZiAoZXZlbnQgJiYgZXZlbnQua2V5ICYmIHRoaXMuYXJyb3dLZXlNb3ZlKSB7XHJcbiAgICAgICAgICAgIGlmIChldmVudC5rZXkudG9Mb3dlckNhc2UoKSA9PT0gJ2Fycm93cmlnaHQnKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm5leHRJbWFnZUxpZ2h0Ym94KCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmIChldmVudC5rZXkudG9Mb3dlckNhc2UoKSA9PT0gJ2Fycm93bGVmdCcpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucHJldkltYWdlTGlnaHRib3goKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKGV2ZW50LmtleS50b0xvd2VyQ2FzZSgpID09PSAnZXNjYXBlJykge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jbG9zZUxpZ2h0Ym94KCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3RydWN0b3IoXHJcbiAgICAgICAgcHJpdmF0ZSBjZFJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXHJcbiAgICAgICAgcHJpdmF0ZSBzYW5pdGl6ZXI6IERvbVNhbml0aXplcixcclxuICAgICAgICBwcml2YXRlIGVsUmVmOiBFbGVtZW50UmVmLFxyXG4gICAgICAgIEBJbmplY3QoRE9DVU1FTlQpIHByaXZhdGUgZG9jdW1lbnQ6IGFueSkgeyB9XHJcblxyXG4gICAgbmdPbkluaXQoKSB7XHJcbiAgICB9XHJcblxyXG4gICAgbmdBZnRlclZpZXdJbml0KCkge1xyXG4gICAgfVxyXG5cclxuICAgIG5nT25EZXN0cm95KCkge1xyXG4gICAgICAgIHRoaXMucmVzZXRTdGF0ZSgpO1xyXG4gICAgfVxyXG5cclxuICAgIHNldFBvcHVwU2xpZGVyV2lkdGgoKSB7XHJcbiAgICAgICAgaWYgKHdpbmRvdyAmJiB3aW5kb3cuaW5uZXJXaWR0aCkge1xyXG4gICAgICAgICAgICB0aGlzLnBvcHVwV2lkdGggPSB3aW5kb3cuaW5uZXJXaWR0aDtcclxuICAgICAgICAgICAgdGhpcy50b3RhbEltYWdlcyA9IHRoaXMuaW1hZ2VzLmxlbmd0aDtcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiAodGhpcy5jdXJyZW50SW1hZ2VJbmRleCkgPT09ICdudW1iZXInICYmIHRoaXMuY3VycmVudEltYWdlSW5kZXggIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5tYXJnaW5MZWZ0ID0gLTEgKiB0aGlzLnBvcHVwV2lkdGggKiB0aGlzLmN1cnJlbnRJbWFnZUluZGV4O1xyXG4gICAgICAgICAgICAgICAgdGhpcy5nZXRJbWFnZURhdGEoKTtcclxuICAgICAgICAgICAgICAgIHRoaXMubmV4dFByZXZEaXNhYmxlKCk7XHJcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNob3dMb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICB9LCA1MDApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGNsb3NlTGlnaHRib3goKSB7XHJcbiAgICAgICAgdGhpcy5jbG9zZS5lbWl0KCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJldkltYWdlTGlnaHRib3goKSB7XHJcbiAgICAgICAgdGhpcy5lZmZlY3RTdHlsZSA9IGBhbGwgJHt0aGlzLnNwZWVkfXMgZWFzZS1pbi1vdXRgO1xyXG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRJbWFnZUluZGV4ID4gMCAmJiAhdGhpcy5saWdodGJveFByZXZEaXNhYmxlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuY3VycmVudEltYWdlSW5kZXgtLTtcclxuICAgICAgICAgICAgdGhpcy5wcmV2SW1hZ2UuZW1pdChMSUdIVEJPWF9QUkVWX0FSUk9XX0NMSUNLX01FU1NBR0UpO1xyXG4gICAgICAgICAgICB0aGlzLm1hcmdpbkxlZnQgPSAtMSAqIHRoaXMucG9wdXBXaWR0aCAqIHRoaXMuY3VycmVudEltYWdlSW5kZXg7XHJcbiAgICAgICAgICAgIHRoaXMuZ2V0SW1hZ2VEYXRhKCk7XHJcbiAgICAgICAgICAgIHRoaXMubmV4dFByZXZEaXNhYmxlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIG5leHRJbWFnZUxpZ2h0Ym94KCkge1xyXG4gICAgICAgIHRoaXMuZWZmZWN0U3R5bGUgPSBgYWxsICR7dGhpcy5zcGVlZH1zIGVhc2UtaW4tb3V0YDtcclxuICAgICAgICBpZiAodGhpcy5jdXJyZW50SW1hZ2VJbmRleCA8IHRoaXMuaW1hZ2VzLmxlbmd0aCAtIDEgJiYgIXRoaXMubGlnaHRib3hOZXh0RGlzYWJsZSkge1xyXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRJbWFnZUluZGV4Kys7XHJcbiAgICAgICAgICAgIHRoaXMubmV4dEltYWdlLmVtaXQoTElHSFRCT1hfTkVYVF9BUlJPV19DTElDS19NRVNTQUdFKTtcclxuICAgICAgICAgICAgdGhpcy5tYXJnaW5MZWZ0ID0gLTEgKiB0aGlzLnBvcHVwV2lkdGggKiB0aGlzLmN1cnJlbnRJbWFnZUluZGV4O1xyXG4gICAgICAgICAgICB0aGlzLmdldEltYWdlRGF0YSgpO1xyXG4gICAgICAgICAgICB0aGlzLm5leHRQcmV2RGlzYWJsZSgpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBuZXh0UHJldkRpc2FibGUoKSB7XHJcbiAgICAgICAgdGhpcy5saWdodGJveE5leHREaXNhYmxlID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLmxpZ2h0Ym94UHJldkRpc2FibGUgPSB0cnVlO1xyXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLmFwcGx5QnV0dG9uRGlzYWJsZUNvbmRpdGlvbigpO1xyXG4gICAgICAgIH0sIHRoaXMuc3BlZWQgKiAxMDAwKTtcclxuICAgIH1cclxuXHJcbiAgICBhcHBseUJ1dHRvbkRpc2FibGVDb25kaXRpb24oKSB7XHJcbiAgICAgICAgdGhpcy5saWdodGJveE5leHREaXNhYmxlID0gZmFsc2U7XHJcbiAgICAgICAgdGhpcy5saWdodGJveFByZXZEaXNhYmxlID0gZmFsc2U7XHJcbiAgICAgICAgaWYgKCF0aGlzLmluZmluaXRlICYmIHRoaXMuY3VycmVudEltYWdlSW5kZXggPj0gdGhpcy5pbWFnZXMubGVuZ3RoIC0gMSkge1xyXG4gICAgICAgICAgICB0aGlzLmxpZ2h0Ym94TmV4dERpc2FibGUgPSB0cnVlO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoIXRoaXMuaW5maW5pdGUgJiYgdGhpcy5jdXJyZW50SW1hZ2VJbmRleCA8PSAwKSB7XHJcbiAgICAgICAgICAgIHRoaXMubGlnaHRib3hQcmV2RGlzYWJsZSA9IHRydWU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGdldEltYWdlRGF0YSgpIHtcclxuICAgICAgICBpZiAodGhpcy5pbWFnZXNcclxuICAgICAgICAgICAgJiYgdGhpcy5pbWFnZXMubGVuZ3RoXHJcbiAgICAgICAgICAgICYmIHR5cGVvZiAodGhpcy5jdXJyZW50SW1hZ2VJbmRleCkgPT09ICdudW1iZXInXHJcbiAgICAgICAgICAgICYmIHRoaXMuY3VycmVudEltYWdlSW5kZXggIT09IHVuZGVmaW5lZFxyXG4gICAgICAgICAgICAmJiB0aGlzLmltYWdlc1t0aGlzLmN1cnJlbnRJbWFnZUluZGV4XVxyXG4gICAgICAgICAgICAmJiAodGhpcy5pbWFnZXNbdGhpcy5jdXJyZW50SW1hZ2VJbmRleF1bJ2ltYWdlJ10gfHwgdGhpcy5pbWFnZXNbdGhpcy5jdXJyZW50SW1hZ2VJbmRleF1bJ3ZpZGVvJ10pKSB7XHJcbiAgICAgICAgICAgIHRoaXMudGl0bGUgPSB0aGlzLmltYWdlc1t0aGlzLmN1cnJlbnRJbWFnZUluZGV4XVsndGl0bGUnXSB8fCAnJztcclxuICAgICAgICAgICAgdGhpcy50b3RhbEltYWdlcyA9IHRoaXMuaW1hZ2VzLmxlbmd0aDtcclxuICAgICAgICAgICAgZm9yIChjb25zdCBpZnJhbWVJIGluIHRoaXMuZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2lmcmFtZScpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaWZyYW1lJylbaWZyYW1lSV1cclxuICAgICAgICAgICAgICAgICAgICAmJiB0aGlzLmRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdpZnJhbWUnKVtpZnJhbWVJXS5jb250ZW50V2luZG93XHJcbiAgICAgICAgICAgICAgICAgICAgJiYgdGhpcy5kb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaWZyYW1lJylbaWZyYW1lSV0uY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2lmcmFtZScpW2lmcmFtZUldLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2UoJ3tcImV2ZW50XCI6XCJjb21tYW5kXCIsXCJmdW5jXCI6XCJwYXVzZVZpZGVvXCIsXCJhcmdzXCI6XCJcIn0nLCAnKicpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGZvciAoY29uc3QgdmlkZW9JIGluIHRoaXMuZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ3ZpZGVvJykpIHtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCd2aWRlbycpW3ZpZGVvSV0gJiYgdGhpcy5kb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgndmlkZW8nKVt2aWRlb0ldLnBhdXNlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgndmlkZW8nKVt2aWRlb0ldLnBhdXNlKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmVzZXRTdGF0ZSgpIHtcclxuICAgICAgICB0aGlzLmltYWdlcyA9IFtdO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU3dpcGUgZXZlbnQgaGFuZGxlclxyXG4gICAgICogUmVmZXJlbmNlIGZyb20gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzQ0NTExMDA3LzIwNjc2NDZcclxuICAgICAqL1xyXG4gICAgc3dpcGVMaWdodGJveEltZyhlOiBUb3VjaEV2ZW50LCB3aGVuOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBjb29yZDogW251bWJlciwgbnVtYmVyXSA9IFtlLmNoYW5nZWRUb3VjaGVzWzBdLnBhZ2VYLCBlLmNoYW5nZWRUb3VjaGVzWzBdLnBhZ2VZXTtcclxuICAgICAgICBjb25zdCB0aW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XHJcblxyXG4gICAgICAgIGlmICh3aGVuID09PSAnc3RhcnQnKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc3dpcGVMaWdodGJveEltZ0Nvb3JkID0gY29vcmQ7XHJcbiAgICAgICAgICAgIHRoaXMuc3dpcGVMaWdodGJveEltZ1RpbWUgPSB0aW1lO1xyXG4gICAgICAgIH0gZWxzZSBpZiAod2hlbiA9PT0gJ2VuZCcpIHtcclxuICAgICAgICAgICAgY29uc3QgZGlyZWN0aW9uID0gW2Nvb3JkWzBdIC0gdGhpcy5zd2lwZUxpZ2h0Ym94SW1nQ29vcmRbMF0sIGNvb3JkWzFdIC0gdGhpcy5zd2lwZUxpZ2h0Ym94SW1nQ29vcmRbMV1dO1xyXG4gICAgICAgICAgICBjb25zdCBkdXJhdGlvbiA9IHRpbWUgLSB0aGlzLnN3aXBlTGlnaHRib3hJbWdUaW1lO1xyXG5cclxuICAgICAgICAgICAgaWYgKGR1cmF0aW9uIDwgMTAwMCAvL1xyXG4gICAgICAgICAgICAgICAgJiYgTWF0aC5hYnMoZGlyZWN0aW9uWzBdKSA+IDMwIC8vIExvbmcgZW5vdWdoXHJcbiAgICAgICAgICAgICAgICAmJiBNYXRoLmFicyhkaXJlY3Rpb25bMF0pID4gTWF0aC5hYnMoZGlyZWN0aW9uWzFdICogMykpIHsgLy8gSG9yaXpvbnRhbCBlbm91Z2hcclxuICAgICAgICAgICAgICAgIGlmIChkaXJlY3Rpb25bMF0gPCAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5uZXh0SW1hZ2VMaWdodGJveCgpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnByZXZJbWFnZUxpZ2h0Ym94KCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuIiwiPGRpdiAqbmdJZj1cImltYWdlRnVsbHNjcmVlblZpZXdcIiBjbGFzcz1cIm5nLWltYWdlLWZ1bGxzY3JlZW4tdmlld1wiPlxyXG4gICAgPGRpdiBjbGFzcz1cImxpZ2h0Ym94LXdyYXBwZXJcIj5cclxuICAgICAgICA8YSBjbGFzcz1cImNsb3NlXCIgKGNsaWNrKT1cImNsb3NlTGlnaHRib3goKVwiPjwvYT5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwibGlnaHRib3gtZGl2XCIgI2xpZ2h0Ym94RGl2PlxyXG4gICAgICAgICAgICA8ZGl2ICpuZ0lmPVwic2hvd0xvYWRpbmdcIiBjbGFzcz1cInByZS1sb2FkZXJcIj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtbm1sLXNwaW5uZXJcIj48L2Rpdj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJsaWdodGJveC1pbWFnZS1tYWluXCJcclxuICAgICAgICAgICAgICAgIFtuZ1N0eWxlXT1cInsnbWFyZ2luLWxlZnQnOiBtYXJnaW5MZWZ0ICsgJ3B4JywgJ2dyaWQtdGVtcGxhdGUtY29sdW1ucyc6ICdyZXBlYXQoJytpbWFnZXMubGVuZ3RoKycsMWZyKScsICd0cmFuc2l0aW9uJzogZWZmZWN0U3R5bGV9XCI+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGlnaHRib3gtaW1hZ2VcIlxyXG4gICAgICAgICAgICAgICAgICAgIFtuZ1N0eWxlXT1cInsnd2lkdGgnOiBwb3B1cFdpZHRoICsgJ3B4J31cIlxyXG4gICAgICAgICAgICAgICAgICAgICpuZ0Zvcj1cImxldCBpbWcgb2YgaW1hZ2VzOyBsZXQgaSA9IGluZGV4XCJcclxuICAgICAgICAgICAgICAgICAgICBbYXR0ci5pZF09XCInbmctbGlnaHRib3gtaW1hZ2UtJyArIGlcIlxyXG4gICAgICAgICAgICAgICAgICAgICh0b3VjaHN0YXJ0KT1cInN3aXBlTGlnaHRib3hJbWcoJGV2ZW50LCAnc3RhcnQnKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgKHRvdWNoZW5kKT1cInN3aXBlTGlnaHRib3hJbWcoJGV2ZW50LCAnZW5kJylcIlxyXG4gICAgICAgICAgICAgICAgICAgICNsaWdodGJveEltYWdlRGl2PlxyXG4gICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNsb3NlLW91dHNpZGVcIiAoY2xpY2spPVwiIWltZz8udmlkZW8gJiYgY2xvc2VMaWdodGJveCgpXCI+PC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPGN1c3RvbS1pbWdcclxuICAgICAgICAgICAgICAgICAgICAgICAgW2ltYWdlVXJsXT1cImltZz8uaW1hZ2UgfHwgaW1nPy52aWRlb1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtpc1ZpZGVvXT1cIiEhKGltZz8ucG9zdGVySW1hZ2UgfHwgaW1nPy52aWRlbylcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbY3VycmVudEltYWdlSW5kZXhdPVwiY3VycmVudEltYWdlSW5kZXhcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbaW1hZ2VJbmRleF09XCJpXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW3NwZWVkXT1cInNwZWVkXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW3ZpZGVvQXV0b1BsYXldPVwidmlkZW9BdXRvUGxheSAmJiBpID09IGN1cnJlbnRJbWFnZUluZGV4XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW3Nob3dWaWRlb0NvbnRyb2xzXT1cInNob3dWaWRlb0NvbnRyb2xzID8gMSA6IDBcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbYWx0XT1cImltZz8uYWx0IHx8IGltZz8udGl0bGUgfHwgJydcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbdGl0bGVdPVwiaW1nPy50aXRsZSB8fCBpbWc/LmFsdCB8fCAnJ1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtzaG93VmlkZW9dPVwidHJ1ZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkaXJlY3Rpb25dPVwiZGlyZWN0aW9uXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9jdXN0b20taW1nPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8ZGl2IFtkaXJdPVwiZGlyZWN0aW9uXCIgW25nQ2xhc3NdPVwieydzaG93JzogdGl0bGUsICdoaWRlJzogIXRpdGxlfVwiIGNsYXNzPVwiY2FwdGlvblwiPnt7IHRpdGxlIH19PC9kaXY+XHJcbiAgICAgICAgICAgIDxhICpuZ0lmPVwiaW1hZ2VzLmxlbmd0aCA+IDFcIiBbbmdDbGFzc109XCJ7J2Rpc2FibGUnOiBsaWdodGJveFByZXZEaXNhYmxlfVwiIGNsYXNzPVwicHJldiBpY29ucyBwcmV2LWljb25cIiAoY2xpY2spPVwicHJldkltYWdlTGlnaHRib3goKVwiPiZsc2FxdW87PC9hPlxyXG4gICAgICAgICAgICA8YSAqbmdJZj1cImltYWdlcy5sZW5ndGggPiAxXCIgW25nQ2xhc3NdPVwieydkaXNhYmxlJzogbGlnaHRib3hOZXh0RGlzYWJsZX1cIiBjbGFzcz1cIm5leHQgaWNvbnMgbmV4dC1pY29uXCIgKGNsaWNrKT1cIm5leHRJbWFnZUxpZ2h0Ym94KClcIj4mcnNhcXVvOzwvYT5cclxuICAgICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG4gICAgPGRpdiAqbmdJZj1cInBhZ2luYXRpb25TaG93XCIgY2xhc3M9XCJwb3B1cC1wYWdpbmF0aW9uXCI+e3tjdXJyZW50SW1hZ2VJbmRleCArIDF9fSBvZiB7e3RvdGFsSW1hZ2VzfX08L2Rpdj5cclxuPC9kaXY+XHJcbiJdfQ==