UNPKG

ngx-image-upload

Version:
492 lines (482 loc) 52.3 kB
import { HttpClient, HttpClientModule } from '@angular/common/http'; import { Injectable, Directive, EventEmitter, HostListener, Input, Output, defineInjectable, inject, Component, ViewChild, NgModule } from '@angular/core'; import { __awaiter } from 'tslib'; import { CommonModule } from '@angular/common'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class NgxImageUploadService { /** * @param {?} http */ constructor(http) { this.http = http; } /** * @param {?} url * @param {?} image * @param {?=} headers * @param {?=} partName * @param {?=} customFormData * @param {?=} withCredentials * @return {?} */ postImage(url, image, headers, partName = 'image', customFormData, withCredentials) { if (!url || url === '') { throw new Error('请设置url参数'); } // add custom form data let /** @type {?} */ formData = new FormData(); for (let /** @type {?} */ key in customFormData) { formData.append(key, customFormData[key]); } formData.append(partName, image); return this.http.post(url, formData, { headers: headers, withCredentials: withCredentials }); } } NgxImageUploadService.decorators = [ { type: Injectable, args: [{ providedIn: 'root' },] }, ]; /** @nocollapse */ NgxImageUploadService.ctorParameters = () => [ { type: HttpClient } ]; /** @nocollapse */ NgxImageUploadService.ngInjectableDef = defineInjectable({ factory: function NgxImageUploadService_Factory() { return new NgxImageUploadService(inject(HttpClient)); }, token: NgxImageUploadService, providedIn: "root" }); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class FileHolder { /** * @param {?} src * @param {?} file */ constructor(src, file) { this.src = src; this.file = file; this.pending = false; } } class NgxImageUploadComponent { /** * @param {?} imageService */ constructor(imageService) { this.imageService = imageService; this.files = []; this.fileCounter = 0; this.fileOver = false; this.showFileTooLargeMessage = false; this.beforeUpload = data => data; this.buttonCaption = '添加图片'; this.disabled = false; this.cssClass = 'img-ul'; this.clearButtonCaption = '清除'; this.dropBoxMessage = '拖拽图片到此处'; this.max = 100; this.preview = true; this.withCredentials = false; this.uploadedFiles = []; this.removed = new EventEmitter(); this.uploadStateChanged = new EventEmitter(); this.uploadFinished = new EventEmitter(); this.previewClicked = new EventEmitter(); this.pendingFilesCounter = 0; this.onFileOver = (isOver) => this.fileOver = isOver; this.countRemainingSlots = () => this.max - this.fileCounter; } /** * @return {?} */ ngOnInit() { if (!this.fileTooLargeMessage) { this.fileTooLargeMessage = '图片太大无法上传.' + (this.maxFileSize ? (' 最大允许 ' + this.maxFileSize / 1024) + 'KiB.' : ''); } this.supportedExtensions = this.supportedExtensions ? this.supportedExtensions.map((ext) => 'image/' + ext) : ['image/*']; } /** * @return {?} */ deleteAll() { this.files.forEach(f => this.removed.emit(f)); this.files = []; this.fileCounter = 0; if (this.inputElement) { this.inputElement.nativeElement.value = ''; } } /** * @param {?} file * @return {?} */ deleteFile(file) { let /** @type {?} */ index = this.files.indexOf(file); this.files.splice(index, 1); this.fileCounter--; if (this.inputElement) { this.inputElement.nativeElement.value = ''; } this.removed.emit(file); } /** * @param {?} file * @return {?} */ previewFileClicked(file) { this.previewClicked.emit(file); } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { if (changes.uploadedFiles && changes.uploadedFiles.currentValue && changes.uploadedFiles.currentValue.length > 0) { this.processUploadedFiles(); } } /** * @param {?} files * @return {?} */ onFileChange(files) { if (this.disabled) return; // let remainingSlots = 0; let /** @type {?} */ remainingSlots = this.countRemainingSlots(); let /** @type {?} */ filesToUploadNum = files.length > remainingSlots ? remainingSlots : files.length; if (this.url && filesToUploadNum != 0) { this.uploadStateChanged.emit(true); } this.fileCounter += filesToUploadNum; this.showFileTooLargeMessage = false; this.uploadFiles(files, filesToUploadNum); } /** * @param {?} response * @param {?} fileHolder * @return {?} */ onResponse(response, fileHolder) { fileHolder.serverResponse = { status: response.status, response }; fileHolder.pending = false; this.uploadFinished.emit(fileHolder); if (--this.pendingFilesCounter == 0) { this.uploadStateChanged.emit(false); } } /** * @return {?} */ processUploadedFiles() { if (typeof this.uploadedFiles === 'string') { let /** @type {?} */ data = this.uploadedFiles; this.fileCounter = 1; this.max = 1; let /** @type {?} */ fileBlob, /** @type {?} */ file, /** @type {?} */ fileUrl; if (data instanceof Object) { fileUrl = data.url; fileBlob = (data.blob) ? data.blob : new Blob([data]); file = new File([fileBlob], data.fileName); } else { fileUrl = data; fileBlob = new Blob([fileUrl]); file = new File([fileBlob], fileUrl); } this.files = []; this.files.push(new FileHolder(fileUrl, file)); } else { this.max = this.max - Object.keys(this.uploadedFiles).length; for (const /** @type {?} */ i in this.uploadedFiles) { let /** @type {?} */ data = this.uploadedFiles[i]; let /** @type {?} */ fileBlob, /** @type {?} */ file, /** @type {?} */ fileUrl; if (data instanceof Object) { fileUrl = data.url; fileBlob = (data.blob) ? data.blob : new Blob([data]); file = new File([fileBlob], data.fileName); } else { fileUrl = data; fileBlob = new Blob([fileUrl]); file = new File([fileBlob], fileUrl); } this.files.push(new FileHolder(fileUrl, file)); } } } /** * @param {?} files * @param {?} filesToUploadNum * @return {?} */ uploadFiles(files, filesToUploadNum) { return __awaiter(this, void 0, void 0, function* () { for (let /** @type {?} */ i = 0; i < filesToUploadNum; i++) { const /** @type {?} */ file = files[i]; if (this.maxFileSize && file.size > this.maxFileSize) { this.fileCounter--; this.inputElement.nativeElement.value = ''; this.showFileTooLargeMessage = true; continue; } const /** @type {?} */ beforeUploadResult = yield this.beforeUpload({ file, url: this.url, abort: false }); if (beforeUploadResult.abort) { this.fileCounter--; this.inputElement.nativeElement.value = ''; continue; } const /** @type {?} */ img = document.createElement('img'); img.src = window.URL.createObjectURL(beforeUploadResult.file); const /** @type {?} */ reader = new FileReader(); reader.addEventListener('load', (event) => { const /** @type {?} */ fileHolder = new FileHolder(event.target.result, beforeUploadResult.file); this.uploadSingleFile(fileHolder, beforeUploadResult.url, beforeUploadResult.formData); this.files.push(fileHolder); }, false); reader.readAsDataURL(beforeUploadResult.file); } }); } /** * @param {?} fileHolder * @param {?=} url * @param {?=} customForm * @return {?} */ uploadSingleFile(fileHolder, url = this.url, customForm) { if (url) { this.pendingFilesCounter++; fileHolder.pending = true; this.imageService .postImage(url, fileHolder.file, this.headers, this.partName, customForm, this.withCredentials) .subscribe(response => this.onResponse(response, fileHolder), error => { this.onResponse(error, fileHolder); this.deleteFile(fileHolder); }); } else { this.uploadFinished.emit(fileHolder); } } } NgxImageUploadComponent.decorators = [ { type: Component, args: [{ selector: 'ds-ngx-image-upload', template: `<div fileDrop [accept]="supportedExtensions" (fileOver)="onFileOver($event)" (fileDrop)="onFileChange($event)" [ngClass]="cssClass" [ngClass]="{'img-ul-file-is-over': fileOver}" [ngStyle]="style?.layout" > <p class="img-ul-file-too-large" *ngIf="showFileTooLargeMessage" [innerText]="fileTooLargeMessage"></p> <div *ngIf="preview" class="img-ul-container img-ul-hr-inline-group" [ngStyle]="style?.previewPanel"> <!-- img --> <div class="img-ul-image" *ngFor="let file of files" (click)="previewFileClicked(file)" > <!-- [ngStyle]="{'background-image': 'url('+ file.src +')'}" --> <div class="img_div"><img src={{file.src}} class="imgs"></div> <div *ngIf="file.pending" class="img-ul-loading-overlay"> <div class="img-ul-spinning-circle"></div> </div> <div *ngIf="!file.pending" [ngClass]="{'img-ul-disabled': disabled}" class="img-ul-x-mark" (click)="deleteFile(file)"> <span class="img-ul-close"></span> </div> </div> </div> <div class="img-ul-file-upload img-ul-hr-inline-group"> <label *ngIf="fileCounter != max" class="img-ul-upload img-ul-button" [ngStyle]="style?.selectButton" [ngClass]="{'img-ul-disabled': disabled}"> <span [innerText]="buttonCaption"></span> <input type="file" [disabled]="disabled" [accept]="supportedExtensions" multiple (change)="onFileChange(input.files)" #input> </label> </div> </div>`, styles: [`.img-ul{--common-radius:3px;border-radius:var(--common-radius);position:relative;color:#9b9b9b;font-weight:400}.img-ul-x-mark{background-color:#000;border-radius:10px;color:#fff;cursor:pointer;height:20px;opacity:.7;text-align:center;width:20px;position:absolute;top:-8px;right:-10px}.img_div{position:relative;width:120px;height:120px;overflow:hidden}.imgs{max-width:200%;height:auto;position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);background:#000}.img-ul-file-is-over{border:var(--active-color) solid}.img-ul-hr-inline-group:after{clear:both;content:"";display:table}.img-ul-file-upload{display:inline-block;width:120px;height:120px;margin:10px;color:#000;text-align:center;line-height:120px}.img-ul-drag-box-msg{display:inline-block;font-weight:600;margin-left:12px}label.img-ul-button{border:1px dashed #d0d0d0;font-size:1em!important}label.img-ul-button input[type=file]{display:none;position:fixed;top:-99999px}.img-ul-clear{background-color:red;font-size:1em!important}.img-ul-clear:disabled{background-color:#ff6464;cursor:default}.img-ul-upload{background-color:var(--active-color);width:120px;height:120px}.img-ul-button{border:none;cursor:pointer;display:inline-block;float:left;font-size:1.25em;font-weight:500;text-transform:uppercase}.img-ul-button:active span{display:block;position:relative;top:1px}.img-ul-container{position:relative;display:inline-block}.img-ul-image{box-shadow:0 0 10px 2px #d0d0d0;background:center center/contain no-repeat;display:inline-block;float:left;height:120px;margin:6px;position:relative;width:120px}.img-ul-close{height:20px;opacity:.7;position:relative;width:20px}.img-ul-x-mark:hover .img-ul-close{opacity:1}.img-ul-close:after,.img-ul-close:before{background-color:#fff;border-radius:2px;content:'';height:10px;position:absolute;top:5px;width:2px}.img-ul-close:before{-webkit-transform:rotate(45deg);transform:rotate(45deg)}.img-ul-close:after{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.img-ul-x-mark.img-ul-disabled{display:none}.img-ul-loading-overlay{background-color:#000;bottom:0;left:0;opacity:.7;position:absolute;right:0;top:0}.img-ul-spinning-circle{height:30px;width:30px;margin:auto;position:absolute;top:0;left:0;bottom:0;right:0;border-radius:50%;border:3px solid rgba(255,255,255,0);border-top:3px solid #fff;border-right:3px solid #fff;-webkit-animation:2s cubic-bezier(.085,.625,.855,.36) infinite spinner;animation:2s cubic-bezier(.085,.625,.855,.36) infinite spinner}.img-ul-file-too-large{color:red}.img-ul-upload.img-ul-disabled{background-color:#86e9c9;cursor:default}.img-ul-upload.img-ul-disabled:active span{top:0}@-webkit-keyframes spinner{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}`] },] }, ]; /** @nocollapse */ NgxImageUploadComponent.ctorParameters = () => [ { type: NgxImageUploadService } ]; NgxImageUploadComponent.propDecorators = { beforeUpload: [{ type: Input }], buttonCaption: [{ type: Input }], disabled: [{ type: Input }], cssClass: [{ type: Input, args: ['class',] }], clearButtonCaption: [{ type: Input }], dropBoxMessage: [{ type: Input }], fileTooLargeMessage: [{ type: Input }], headers: [{ type: Input }], max: [{ type: Input }], maxFileSize: [{ type: Input }], preview: [{ type: Input }], partName: [{ type: Input }], style: [{ type: Input }], supportedExtensions: [{ type: Input, args: ['extensions',] }], url: [{ type: Input }], withCredentials: [{ type: Input }], uploadedFiles: [{ type: Input }], removed: [{ type: Output }], uploadStateChanged: [{ type: Output }], uploadFinished: [{ type: Output }], previewClicked: [{ type: Output }], inputElement: [{ type: ViewChild, args: ['input',] }] }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class FileDropDirective { constructor() { this.fileOver = new EventEmitter(); this.fileDrop = new EventEmitter(); } /** * @param {?} event * @return {?} */ onDrop(event) { let /** @type {?} */ dataTransfer = FileDropDirective.getDataTransfer(event); if (!FileDropDirective.hasFiles(dataTransfer.types)) { return; } event.preventDefault(); let /** @type {?} */ files = this.filterFiles(dataTransfer.files); event.preventDefault(); this.fileOver.emit(false); this.fileDrop.emit(files); } /** * @param {?} event * @return {?} */ onDragLeave(event) { this.fileOver.emit(false); } /** * @param {?} event * @return {?} */ onDragOver(event) { let /** @type {?} */ dataTransfer = FileDropDirective.getDataTransfer(event); if (!FileDropDirective.hasFiles(dataTransfer.types)) { return; } dataTransfer.dropEffect = 'copy'; event.preventDefault(); this.fileOver.emit(true); } /** * @param {?} files * @return {?} */ filterFiles(files) { if (!this.accept || this.accept.length === 0) { return files; } let /** @type {?} */ acceptedFiles = []; for (let /** @type {?} */ i = 0; i < files.length; i++) { for (let /** @type {?} */ j = 0; j < this.accept.length; j++) { if (FileDropDirective.matchRule(this.accept[j], files[i].type)) { acceptedFiles.push(files[i]); break; } } } return acceptedFiles; } /** * @param {?} event * @return {?} */ static getDataTransfer(event) { return event.dataTransfer ? event.dataTransfer : event.originalEvent.dataTransfer; } /** * @param {?} types * @return {?} */ static hasFiles(types) { if (!types) { return false; } if (types.indexOf) { return types.indexOf('Files') !== -1; } if (types.contains) { return types.contains('Files'); } return false; } /** * @param {?} rule * @param {?} candidate * @return {?} */ static matchRule(rule, candidate) { return new RegExp("^" + rule.split("*").join(".*") + "$").test(candidate); } } FileDropDirective.decorators = [ { type: Directive, args: [{ selector: '[fileDrop]' },] }, ]; FileDropDirective.propDecorators = { accept: [{ type: Input }], fileOver: [{ type: Output }], fileDrop: [{ type: Output }], onDrop: [{ type: HostListener, args: ['drop', ['$event'],] }], onDragLeave: [{ type: HostListener, args: ['dragleave', ['$event'],] }], onDragOver: [{ type: HostListener, args: ['dragover', ['$event'],] }] }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class NgxImageUploadModule { } NgxImageUploadModule.decorators = [ { type: NgModule, args: [{ imports: [ CommonModule, HttpClientModule ], declarations: [NgxImageUploadComponent, FileDropDirective], exports: [NgxImageUploadComponent] },] }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ export { NgxImageUploadService, FileHolder, NgxImageUploadComponent, NgxImageUploadModule, FileDropDirective as ɵa }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWltYWdlLXVwbG9hZC5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vbmd4LWltYWdlLXVwbG9hZC9saWIvbmd4LWltYWdlLXVwbG9hZC5zZXJ2aWNlLnRzIiwibmc6Ly9uZ3gtaW1hZ2UtdXBsb2FkL2xpYi9uZ3gtaW1hZ2UtdXBsb2FkLmNvbXBvbmVudC50cyIsIm5nOi8vbmd4LWltYWdlLXVwbG9hZC9maWxlLWRyb3AuZGlyZWN0aXZlLnRzIiwibmc6Ly9uZ3gtaW1hZ2UtdXBsb2FkL2xpYi9uZ3gtaW1hZ2UtdXBsb2FkLm1vZHVsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBIdHRwQ2xpZW50LCBIdHRwSGVhZGVycyB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgTmd4SW1hZ2VVcGxvYWRTZXJ2aWNlIHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50KSB7XG4gIH1cblxuICBwdWJsaWMgcG9zdEltYWdlKHVybDogc3RyaW5nLCBpbWFnZTogRmlsZSwgaGVhZGVycz86IEh0dHBIZWFkZXJzIHwgeyBbbmFtZTogc3RyaW5nXTogYW55IH0sIHBhcnROYW1lOiBzdHJpbmcgPSAnaW1hZ2UnLCBjdXN0b21Gb3JtRGF0YT86IHsgW25hbWU6IHN0cmluZ106IGFueSB9LCB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICBpZiAoIXVybCB8fCB1cmwgPT09ICcnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ8Oowq/Ct8Oowq7CvsOnwr3CrnVybMOlwo/CgsOmwpXCsCcpO1xuICAgIH1cblxuICAgIC8vIGFkZCBjdXN0b20gZm9ybSBkYXRhXG4gICAgbGV0IGZvcm1EYXRhID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgZm9yIChsZXQga2V5IGluIGN1c3RvbUZvcm1EYXRhKSB7XG4gICAgICBmb3JtRGF0YS5hcHBlbmQoa2V5LCBjdXN0b21Gb3JtRGF0YVtrZXldKTtcbiAgICB9XG4gICAgZm9ybURhdGEuYXBwZW5kKHBhcnROYW1lLCBpbWFnZSk7XG4gICAgcmV0dXJuIHRoaXMuaHR0cC5wb3N0KHVybCwgZm9ybURhdGEsIHsgaGVhZGVyczogaGVhZGVycywgd2l0aENyZWRlbnRpYWxzOiB3aXRoQ3JlZGVudGlhbHMgfSk7XG4gIH1cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBPbkNoYW5nZXMsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgRWxlbWVudFJlZiwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7IFVwbG9hZE1ldGFkYXRhIH0gZnJvbSAnLi9iZWZvcmUtdXBsb2FkLmludGVyZmFjZSc7XG5pbXBvcnQgeyBOZ3hJbWFnZVVwbG9hZFNlcnZpY2UgfSBmcm9tICcuL25neC1pbWFnZS11cGxvYWQuc2VydmljZSc7XG5pbXBvcnQgeyBTdHlsZSB9IGZyb20gJy4vc3R5bGUnO1xuXG5leHBvcnQgY2xhc3MgRmlsZUhvbGRlciB7XG4gIHB1YmxpYyBwZW5kaW5nOiBib29sZWFuID0gZmFsc2U7XG4gIHB1YmxpYyBzZXJ2ZXJSZXNwb25zZTogeyBzdGF0dXM6IG51bWJlciwgcmVzcG9uc2U6IGFueSB9O1xuXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBzcmM6IHN0cmluZywgcHVibGljIGZpbGU6IEZpbGUpIHtcbiAgfVxufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdkcy1uZ3gtaW1hZ2UtdXBsb2FkJyxcbiAgdGVtcGxhdGU6IGA8ZGl2XG4gICAgIGZpbGVEcm9wXG4gICAgIFthY2NlcHRdPVwic3VwcG9ydGVkRXh0ZW5zaW9uc1wiXG4gICAgIChmaWxlT3Zlcik9XCJvbkZpbGVPdmVyKCRldmVudClcIlxuICAgICAoZmlsZURyb3ApPVwib25GaWxlQ2hhbmdlKCRldmVudClcIlxuICAgICBbbmdDbGFzc109XCJjc3NDbGFzc1wiXG4gICAgIFtuZ0NsYXNzXT1cInsnaW1nLXVsLWZpbGUtaXMtb3Zlcic6IGZpbGVPdmVyfVwiICAgICBcbiAgICAgW25nU3R5bGVdPVwic3R5bGU/LmxheW91dFwiXG4+XG4gIDxwIGNsYXNzPVwiaW1nLXVsLWZpbGUtdG9vLWxhcmdlXCIgKm5nSWY9XCJzaG93RmlsZVRvb0xhcmdlTWVzc2FnZVwiIFtpbm5lclRleHRdPVwiZmlsZVRvb0xhcmdlTWVzc2FnZVwiPjwvcD5cblxuICA8ZGl2ICpuZ0lmPVwicHJldmlld1wiIGNsYXNzPVwiaW1nLXVsLWNvbnRhaW5lciBpbWctdWwtaHItaW5saW5lLWdyb3VwXCIgW25nU3R5bGVdPVwic3R5bGU/LnByZXZpZXdQYW5lbFwiPlxuICAgIDwhLS0gaW1nIC0tPlxuICAgIDxkaXZcbiAgICAgIGNsYXNzPVwiaW1nLXVsLWltYWdlXCJcbiAgICAgICpuZ0Zvcj1cImxldCBmaWxlIG9mIGZpbGVzXCJcbiAgICAgIChjbGljayk9XCJwcmV2aWV3RmlsZUNsaWNrZWQoZmlsZSlcIlxuICAgID5cbiAgICAgIDwhLS0gW25nU3R5bGVdPVwieydiYWNrZ3JvdW5kLWltYWdlJzogJ3VybCgnKyBmaWxlLnNyYyArJyknfVwiIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cImltZ19kaXZcIj48aW1nIHNyYz17e2ZpbGUuc3JjfX0gY2xhc3M9XCJpbWdzXCI+PC9kaXY+XG4gICAgICA8ZGl2ICpuZ0lmPVwiZmlsZS5wZW5kaW5nXCIgY2xhc3M9XCJpbWctdWwtbG9hZGluZy1vdmVybGF5XCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbWctdWwtc3Bpbm5pbmctY2lyY2xlXCI+PC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgKm5nSWY9XCIhZmlsZS5wZW5kaW5nXCIgXG4gICAgICAgIFtuZ0NsYXNzXT1cInsnaW1nLXVsLWRpc2FibGVkJzogZGlzYWJsZWR9XCIgXG4gICAgICAgIGNsYXNzPVwiaW1nLXVsLXgtbWFya1wiIFxuICAgICAgICAoY2xpY2spPVwiZGVsZXRlRmlsZShmaWxlKVwiPlxuICAgICAgICA8c3BhbiBjbGFzcz1cImltZy11bC1jbG9zZVwiPjwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbiAgXG4gIDxkaXYgY2xhc3M9XCJpbWctdWwtZmlsZS11cGxvYWQgaW1nLXVsLWhyLWlubGluZS1ncm91cFwiPiAgICBcbiAgICA8bGFiZWwgKm5nSWY9XCJmaWxlQ291bnRlciAhPSBtYXhcIlxuICAgICAgY2xhc3M9XCJpbWctdWwtdXBsb2FkIGltZy11bC1idXR0b25cIiBcbiAgICAgIFtuZ1N0eWxlXT1cInN0eWxlPy5zZWxlY3RCdXR0b25cIlxuICAgICAgW25nQ2xhc3NdPVwieydpbWctdWwtZGlzYWJsZWQnOiBkaXNhYmxlZH1cIj5cbiAgICAgIDxzcGFuIFtpbm5lclRleHRdPVwiYnV0dG9uQ2FwdGlvblwiPjwvc3Bhbj5cbiAgICAgIDxpbnB1dFxuICAgICAgICB0eXBlPVwiZmlsZVwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgIFthY2NlcHRdPVwic3VwcG9ydGVkRXh0ZW5zaW9uc1wiXG4gICAgICAgIG11bHRpcGxlIChjaGFuZ2UpPVwib25GaWxlQ2hhbmdlKGlucHV0LmZpbGVzKVwiXG4gICAgICAgICNpbnB1dD5cbiAgICA8L2xhYmVsPlxuICA8L2Rpdj5cbjwvZGl2PmAsXG4gIHN0eWxlczogW2AuaW1nLXVsey0tY29tbW9uLXJhZGl1czozcHg7Ym9yZGVyLXJhZGl1czp2YXIoLS1jb21tb24tcmFkaXVzKTtwb3NpdGlvbjpyZWxhdGl2ZTtjb2xvcjojOWI5YjliO2ZvbnQtd2VpZ2h0OjQwMH0uaW1nLXVsLXgtbWFya3tiYWNrZ3JvdW5kLWNvbG9yOiMwMDA7Ym9yZGVyLXJhZGl1czoxMHB4O2NvbG9yOiNmZmY7Y3Vyc29yOnBvaW50ZXI7aGVpZ2h0OjIwcHg7b3BhY2l0eTouNzt0ZXh0LWFsaWduOmNlbnRlcjt3aWR0aDoyMHB4O3Bvc2l0aW9uOmFic29sdXRlO3RvcDotOHB4O3JpZ2h0Oi0xMHB4fS5pbWdfZGl2e3Bvc2l0aW9uOnJlbGF0aXZlO3dpZHRoOjEyMHB4O2hlaWdodDoxMjBweDtvdmVyZmxvdzpoaWRkZW59LmltZ3N7bWF4LXdpZHRoOjIwMCU7aGVpZ2h0OmF1dG87cG9zaXRpb246YWJzb2x1dGU7dG9wOjUwJTtsZWZ0OjUwJTstd2Via2l0LXRyYW5zZm9ybTp0cmFuc2xhdGUoLTUwJSwtNTAlKTt0cmFuc2Zvcm06dHJhbnNsYXRlKC01MCUsLTUwJSk7YmFja2dyb3VuZDojMDAwfS5pbWctdWwtZmlsZS1pcy1vdmVye2JvcmRlcjp2YXIoLS1hY3RpdmUtY29sb3IpIHNvbGlkfS5pbWctdWwtaHItaW5saW5lLWdyb3VwOmFmdGVye2NsZWFyOmJvdGg7Y29udGVudDpcIlwiO2Rpc3BsYXk6dGFibGV9LmltZy11bC1maWxlLXVwbG9hZHtkaXNwbGF5OmlubGluZS1ibG9jazt3aWR0aDoxMjBweDtoZWlnaHQ6MTIwcHg7bWFyZ2luOjEwcHg7Y29sb3I6IzAwMDt0ZXh0LWFsaWduOmNlbnRlcjtsaW5lLWhlaWdodDoxMjBweH0uaW1nLXVsLWRyYWctYm94LW1zZ3tkaXNwbGF5OmlubGluZS1ibG9jaztmb250LXdlaWdodDo2MDA7bWFyZ2luLWxlZnQ6MTJweH1sYWJlbC5pbWctdWwtYnV0dG9ue2JvcmRlcjoxcHggZGFzaGVkICNkMGQwZDA7Zm9udC1zaXplOjFlbSFpbXBvcnRhbnR9bGFiZWwuaW1nLXVsLWJ1dHRvbiBpbnB1dFt0eXBlPWZpbGVde2Rpc3BsYXk6bm9uZTtwb3NpdGlvbjpmaXhlZDt0b3A6LTk5OTk5cHh9LmltZy11bC1jbGVhcntiYWNrZ3JvdW5kLWNvbG9yOnJlZDtmb250LXNpemU6MWVtIWltcG9ydGFudH0uaW1nLXVsLWNsZWFyOmRpc2FibGVke2JhY2tncm91bmQtY29sb3I6I2ZmNjQ2NDtjdXJzb3I6ZGVmYXVsdH0uaW1nLXVsLXVwbG9hZHtiYWNrZ3JvdW5kLWNvbG9yOnZhcigtLWFjdGl2ZS1jb2xvcik7d2lkdGg6MTIwcHg7aGVpZ2h0OjEyMHB4fS5pbWctdWwtYnV0dG9ue2JvcmRlcjpub25lO2N1cnNvcjpwb2ludGVyO2Rpc3BsYXk6aW5saW5lLWJsb2NrO2Zsb2F0OmxlZnQ7Zm9udC1zaXplOjEuMjVlbTtmb250LXdlaWdodDo1MDA7dGV4dC10cmFuc2Zvcm06dXBwZXJjYXNlfS5pbWctdWwtYnV0dG9uOmFjdGl2ZSBzcGFue2Rpc3BsYXk6YmxvY2s7cG9zaXRpb246cmVsYXRpdmU7dG9wOjFweH0uaW1nLXVsLWNvbnRhaW5lcntwb3NpdGlvbjpyZWxhdGl2ZTtkaXNwbGF5OmlubGluZS1ibG9ja30uaW1nLXVsLWltYWdle2JveC1zaGFkb3c6MCAwIDEwcHggMnB4ICNkMGQwZDA7YmFja2dyb3VuZDpjZW50ZXIgY2VudGVyL2NvbnRhaW4gbm8tcmVwZWF0O2Rpc3BsYXk6aW5saW5lLWJsb2NrO2Zsb2F0OmxlZnQ7aGVpZ2h0OjEyMHB4O21hcmdpbjo2cHg7cG9zaXRpb246cmVsYXRpdmU7d2lkdGg6MTIwcHh9LmltZy11bC1jbG9zZXtoZWlnaHQ6MjBweDtvcGFjaXR5Oi43O3Bvc2l0aW9uOnJlbGF0aXZlO3dpZHRoOjIwcHh9LmltZy11bC14LW1hcms6aG92ZXIgLmltZy11bC1jbG9zZXtvcGFjaXR5OjF9LmltZy11bC1jbG9zZTphZnRlciwuaW1nLXVsLWNsb3NlOmJlZm9yZXtiYWNrZ3JvdW5kLWNvbG9yOiNmZmY7Ym9yZGVyLXJhZGl1czoycHg7Y29udGVudDonJztoZWlnaHQ6MTBweDtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6NXB4O3dpZHRoOjJweH0uaW1nLXVsLWNsb3NlOmJlZm9yZXstd2Via2l0LXRyYW5zZm9ybTpyb3RhdGUoNDVkZWcpO3RyYW5zZm9ybTpyb3RhdGUoNDVkZWcpfS5pbWctdWwtY2xvc2U6YWZ0ZXJ7LXdlYmtpdC10cmFuc2Zvcm06cm90YXRlKC00NWRlZyk7dHJhbnNmb3JtOnJvdGF0ZSgtNDVkZWcpfS5pbWctdWwteC1tYXJrLmltZy11bC1kaXNhYmxlZHtkaXNwbGF5Om5vbmV9LmltZy11bC1sb2FkaW5nLW92ZXJsYXl7YmFja2dyb3VuZC1jb2xvcjojMDAwO2JvdHRvbTowO2xlZnQ6MDtvcGFjaXR5Oi43O3Bvc2l0aW9uOmFic29sdXRlO3JpZ2h0OjA7dG9wOjB9LmltZy11bC1zcGlubmluZy1jaXJjbGV7aGVpZ2h0OjMwcHg7d2lkdGg6MzBweDttYXJnaW46YXV0bztwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtsZWZ0OjA7Ym90dG9tOjA7cmlnaHQ6MDtib3JkZXItcmFkaXVzOjUwJTtib3JkZXI6M3B4IHNvbGlkIHJnYmEoMjU1LDI1NSwyNTUsMCk7Ym9yZGVyLXRvcDozcHggc29saWQgI2ZmZjtib3JkZXItcmlnaHQ6M3B4IHNvbGlkICNmZmY7LXdlYmtpdC1hbmltYXRpb246MnMgY3ViaWMtYmV6aWVyKC4wODUsLjYyNSwuODU1LC4zNikgaW5maW5pdGUgc3Bpbm5lcjthbmltYXRpb246MnMgY3ViaWMtYmV6aWVyKC4wODUsLjYyNSwuODU1LC4zNikgaW5maW5pdGUgc3Bpbm5lcn0uaW1nLXVsLWZpbGUtdG9vLWxhcmdle2NvbG9yOnJlZH0uaW1nLXVsLXVwbG9hZC5pbWctdWwtZGlzYWJsZWR7YmFja2dyb3VuZC1jb2xvcjojODZlOWM5O2N1cnNvcjpkZWZhdWx0fS5pbWctdWwtdXBsb2FkLmltZy11bC1kaXNhYmxlZDphY3RpdmUgc3Bhbnt0b3A6MH1ALXdlYmtpdC1rZXlmcmFtZXMgc3Bpbm5lcnswJXstd2Via2l0LXRyYW5zZm9ybTpyb3RhdGUoMCk7dHJhbnNmb3JtOnJvdGF0ZSgwKX0xMDAley13ZWJraXQtdHJhbnNmb3JtOnJvdGF0ZSgzNjBkZWcpO3RyYW5zZm9ybTpyb3RhdGUoMzYwZGVnKX19QGtleWZyYW1lcyBzcGlubmVyezAley13ZWJraXQtdHJhbnNmb3JtOnJvdGF0ZSgwKTt0cmFuc2Zvcm06cm90YXRlKDApfTEwMCV7LXdlYmtpdC10cmFuc2Zvcm06cm90YXRlKDM2MGRlZyk7dHJhbnNmb3JtOnJvdGF0ZSgzNjBkZWcpfX1gXVxufSlcbmV4cG9ydCBjbGFzcyBOZ3hJbWFnZVVwbG9hZENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcblxuICBmaWxlczogRmlsZUhvbGRlcltdID0gW107XG4gIGZpbGVDb3VudGVyOiBudW1iZXIgPSAwO1xuICBmaWxlT3ZlcjogYm9vbGVhbiA9IGZhbHNlO1xuICBzaG93RmlsZVRvb0xhcmdlTWVzc2FnZTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpIGJlZm9yZVVwbG9hZDogKHBhcmFtOiBVcGxvYWRNZXRhZGF0YSkgPT4gVXBsb2FkTWV0YWRhdGEgfCBQcm9taXNlPFVwbG9hZE1ldGFkYXRhPiA9IGRhdGEgPT4gZGF0YTtcbiAgQElucHV0KCkgYnV0dG9uQ2FwdGlvbiA9ICfDpsK3wrvDpcKKwqDDpcKbwr7Dp8KJwocnO1xuICBASW5wdXQoKSBkaXNhYmxlZCA9IGZhbHNlO1xuICBASW5wdXQoJ2NsYXNzJykgY3NzQ2xhc3MgPSAnaW1nLXVsJztcbiAgQElucHV0KCkgY2xlYXJCdXR0b25DYXB0aW9uID0gJ8OmwrjChcOpwpnCpCc7XG4gIEBJbnB1dCgpIGRyb3BCb3hNZXNzYWdlID0gJ8OmwovClsOmwovCvcOlwpvCvsOnwonCh8OlwojCsMOmwq3CpMOlwqTChCc7XG4gIEBJbnB1dCgpIGZpbGVUb29MYXJnZU1lc3NhZ2U7XG4gIEBJbnB1dCgpIGhlYWRlcnM6IEhlYWRlcnMgfCB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfTtcbiAgQElucHV0KCkgbWF4ID0gMTAwO1xuICBASW5wdXQoKSBtYXhGaWxlU2l6ZTogbnVtYmVyO1xuICBASW5wdXQoKSBwcmV2aWV3ID0gdHJ1ZTtcbiAgQElucHV0KCkgcGFydE5hbWU6IHN0cmluZztcbiAgQElucHV0KCkgc3R5bGU6IFN0eWxlO1xuICBASW5wdXQoJ2V4dGVuc2lvbnMnKSBzdXBwb3J0ZWRFeHRlbnNpb25zOiBzdHJpbmdbXTtcbiAgQElucHV0KCkgdXJsOiBzdHJpbmc7XG4gIEBJbnB1dCgpIHdpdGhDcmVkZW50aWFscyA9IGZhbHNlO1xuICBASW5wdXQoKSB1cGxvYWRlZEZpbGVzOiBzdHJpbmdbXSB8IEFycmF5PHsgdXJsOiBzdHJpbmcsIGZpbGVOYW1lOiBzdHJpbmcsIGJsb2I/OiBCbG9iIH0+ID0gW107XG4gIEBPdXRwdXQoKSByZW1vdmVkID0gbmV3IEV2ZW50RW1pdHRlcjxGaWxlSG9sZGVyPigpO1xuICBAT3V0cHV0KCkgdXBsb2FkU3RhdGVDaGFuZ2VkID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xuICBAT3V0cHV0KCkgdXBsb2FkRmluaXNoZWQgPSBuZXcgRXZlbnRFbWl0dGVyPEZpbGVIb2xkZXI+KCk7XG4gIEBPdXRwdXQoKSBwcmV2aWV3Q2xpY2tlZCA9IG5ldyBFdmVudEVtaXR0ZXI8RmlsZUhvbGRlcj4oKTtcblxuICBAVmlld0NoaWxkKCdpbnB1dCcpXG4gIHByaXZhdGUgaW5wdXRFbGVtZW50OiBFbGVtZW50UmVmO1xuICBwcml2YXRlIHBlbmRpbmdGaWxlc0NvdW50ZXI6IG51bWJlciA9IDA7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBpbWFnZVNlcnZpY2U6IE5neEltYWdlVXBsb2FkU2VydmljZSkgeyB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgaWYgKCF0aGlzLmZpbGVUb29MYXJnZU1lc3NhZ2UpIHtcbiAgICAgIHRoaXMuZmlsZVRvb0xhcmdlTWVzc2FnZSA9ICfDpcKbwr7Dp8KJwofDpcKkwqrDpcKkwqfDpsKXwqDDpsKzwpXDpMK4worDpMK8wqAuJyArICh0aGlzLm1heEZpbGVTaXplID8gKCcgw6bCnMKAw6XCpMKnw6XChcKBw6jCrsK4ICcgKyB0aGlzLm1heEZpbGVTaXplIC8gMTAyNCkgKyAnS2lCLicgOiAnJyk7XG4gICAgfVxuICAgIHRoaXMuc3VwcG9ydGVkRXh0ZW5zaW9ucyA9IHRoaXMuc3VwcG9ydGVkRXh0ZW5zaW9ucyA/IHRoaXMuc3VwcG9ydGVkRXh0ZW5zaW9ucy5tYXAoKGV4dCkgPT4gJ2ltYWdlLycgKyBleHQpIDogWydpbWFnZS8qJ107XG4gIH1cblxuICBkZWxldGVBbGwoKSB7XG4gICAgdGhpcy5maWxlcy5mb3JFYWNoKGYgPT4gdGhpcy5yZW1vdmVkLmVtaXQoZikpO1xuICAgIHRoaXMuZmlsZXMgPSBbXTtcbiAgICB0aGlzLmZpbGVDb3VudGVyID0gMDtcbiAgICBpZiAodGhpcy5pbnB1dEVsZW1lbnQpIHtcbiAgICAgIHRoaXMuaW5wdXRFbGVtZW50Lm5hdGl2ZUVsZW1lbnQudmFsdWUgPSAnJztcbiAgICB9XG4gIH1cblxuICBkZWxldGVGaWxlKGZpbGU6IEZpbGVIb2xkZXIpOiB2b2lkIHtcbiAgICBsZXQgaW5kZXggPSB0aGlzLmZpbGVzLmluZGV4T2YoZmlsZSk7XG4gICAgdGhpcy5maWxlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIHRoaXMuZmlsZUNvdW50ZXItLTtcblxuICAgIGlmICh0aGlzLmlucHV0RWxlbWVudCkge1xuICAgICAgdGhpcy5pbnB1dEVsZW1lbnQubmF0aXZlRWxlbWVudC52YWx1ZSA9ICcnO1xuICAgIH1cbiAgICB0aGlzLnJlbW92ZWQuZW1pdChmaWxlKTtcbiAgfVxuXG4gIHByZXZpZXdGaWxlQ2xpY2tlZChmaWxlOiBGaWxlSG9sZGVyKSB7XG4gICAgdGhpcy5wcmV2aWV3Q2xpY2tlZC5lbWl0KGZpbGUpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlcykge1xuICAgIGlmIChjaGFuZ2VzLnVwbG9hZGVkRmlsZXMgJiYgY2hhbmdlcy51cGxvYWRlZEZpbGVzLmN1cnJlbnRWYWx1ZSAmJiBjaGFuZ2VzLnVwbG9hZGVkRmlsZXMuY3VycmVudFZhbHVlLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMucHJvY2Vzc1VwbG9hZGVkRmlsZXMoKTtcbiAgICB9XG4gIH1cblxuICBvbkZpbGVDaGFuZ2UoZmlsZXM6IEZpbGVMaXN0KSB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQpIHJldHVybjtcblxuICAgIC8vIGxldCByZW1haW5pbmdTbG90cyA9IDA7XG4gICAgbGV0IHJlbWFpbmluZ1Nsb3RzID0gdGhpcy5jb3VudFJlbWFpbmluZ1Nsb3RzKCk7XG4gICAgbGV0IGZpbGVzVG9VcGxvYWROdW0gPSBmaWxlcy5sZW5ndGggPiByZW1haW5pbmdTbG90cyA/IHJlbWFpbmluZ1Nsb3RzIDogZmlsZXMubGVuZ3RoO1xuXG4gICAgaWYgKHRoaXMudXJsICYmIGZpbGVzVG9VcGxvYWROdW0gIT0gMCkge1xuICAgICAgdGhpcy51cGxvYWRTdGF0ZUNoYW5nZWQuZW1pdCh0cnVlKTtcbiAgICB9XG5cbiAgICB0aGlzLmZpbGVDb3VudGVyICs9IGZpbGVzVG9VcGxvYWROdW07XG4gICAgdGhpcy5zaG93RmlsZVRvb0xhcmdlTWVzc2FnZSA9IGZhbHNlO1xuICAgIHRoaXMudXBsb2FkRmlsZXMoZmlsZXMsIGZpbGVzVG9VcGxvYWROdW0pO1xuICB9XG5cbiAgb25GaWxlT3ZlciA9IChpc092ZXIpID0+IHRoaXMuZmlsZU92ZXIgPSBpc092ZXI7XG5cbiAgcHJpdmF0ZSBjb3VudFJlbWFpbmluZ1Nsb3RzID0gKCkgPT4gdGhpcy5tYXggLSB0aGlzLmZpbGVDb3VudGVyO1xuXG4gIHByaXZhdGUgb25SZXNwb25zZShyZXNwb25zZTogUmVzcG9uc2UsIGZpbGVIb2xkZXI6IEZpbGVIb2xkZXIpIHtcbiAgICBmaWxlSG9sZGVyLnNlcnZlclJlc3BvbnNlID0geyBzdGF0dXM6IHJlc3BvbnNlLnN0YXR1cywgcmVzcG9uc2UgfTtcbiAgICBmaWxlSG9sZGVyLnBlbmRpbmcgPSBmYWxzZTtcblxuICAgIHRoaXMudXBsb2FkRmluaXNoZWQuZW1pdChmaWxlSG9sZGVyKTtcblxuICAgIGlmICgtLXRoaXMucGVuZGluZ0ZpbGVzQ291bnRlciA9PSAwKSB7XG4gICAgICB0aGlzLnVwbG9hZFN0YXRlQ2hhbmdlZC5lbWl0KGZhbHNlKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHByb2Nlc3NVcGxvYWRlZEZpbGVzKCkge1xuICAgIGlmICh0eXBlb2YgdGhpcy51cGxvYWRlZEZpbGVzID09PSAnc3RyaW5nJykge1xuICAgICAgbGV0IGRhdGE6IGFueSA9IHRoaXMudXBsb2FkZWRGaWxlcztcblxuICAgICAgdGhpcy5maWxlQ291bnRlciA9IDE7XG4gICAgICB0aGlzLm1heCA9IDE7XG5cbiAgICAgIGxldCBmaWxlQmxvYjogQmxvYixcbiAgICAgICAgZmlsZTogRmlsZSxcbiAgICAgICAgZmlsZVVybDogc3RyaW5nO1xuXG4gICAgICBpZiAoZGF0YSBpbnN0YW5jZW9mIE9iamVjdCkge1xuICAgICAgICBmaWxlVXJsID0gZGF0YS51cmw7XG4gICAgICAgIGZpbGVCbG9iID0gKGRhdGEuYmxvYikgPyBkYXRhLmJsb2IgOiBuZXcgQmxvYihbZGF0YV0pO1xuICAgICAgICBmaWxlID0gbmV3IEZpbGUoW2ZpbGVCbG9iXSwgZGF0YS5maWxlTmFtZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmaWxlVXJsID0gZGF0YTtcbiAgICAgICAgZmlsZUJsb2IgPSBuZXcgQmxvYihbZmlsZVVybF0pO1xuICAgICAgICBmaWxlID0gbmV3IEZpbGUoW2ZpbGVCbG9iXSwgZmlsZVVybCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZmlsZXMgPSBbXTtcbiAgICAgIHRoaXMuZmlsZXMucHVzaChuZXcgRmlsZUhvbGRlcihmaWxlVXJsLCBmaWxlKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWF4ID0gdGhpcy5tYXggLSBPYmplY3Qua2V5cyh0aGlzLnVwbG9hZGVkRmlsZXMpLmxlbmd0aDtcbiAgICAgIGZvciAoY29uc3QgaSBpbiB0aGlzLnVwbG9hZGVkRmlsZXMpIHtcbiAgICAgICAgbGV0IGRhdGE6IGFueSA9IHRoaXMudXBsb2FkZWRGaWxlc1tpXTtcblxuICAgICAgICBsZXQgZmlsZUJsb2I6IEJsb2IsXG4gICAgICAgICAgZmlsZTogRmlsZSxcbiAgICAgICAgICBmaWxlVXJsOiBzdHJpbmc7XG5cbiAgICAgICAgaWYgKGRhdGEgaW5zdGFuY2VvZiBPYmplY3QpIHtcbiAgICAgICAgICBmaWxlVXJsID0gZGF0YS51cmw7XG4gICAgICAgICAgZmlsZUJsb2IgPSAoZGF0YS5ibG9iKSA/IGRhdGEuYmxvYiA6IG5ldyBCbG9iKFtkYXRhXSk7XG4gICAgICAgICAgZmlsZSA9IG5ldyBGaWxlKFtmaWxlQmxvYl0sIGRhdGEuZmlsZU5hbWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZpbGVVcmwgPSBkYXRhO1xuICAgICAgICAgIGZpbGVCbG9iID0gbmV3IEJsb2IoW2ZpbGVVcmxdKTtcbiAgICAgICAgICBmaWxlID0gbmV3IEZpbGUoW2ZpbGVCbG9iXSwgZmlsZVVybCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmZpbGVzLnB1c2gobmV3IEZpbGVIb2xkZXIoZmlsZVVybCwgZmlsZSkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgdXBsb2FkRmlsZXMoZmlsZXM6IEZpbGVMaXN0LCBmaWxlc1RvVXBsb2FkTnVtOiBudW1iZXIpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZpbGVzVG9VcGxvYWROdW07IGkrKykge1xuICAgICAgY29uc3QgZmlsZSA9IGZpbGVzW2ldO1xuXG4gICAgICBpZiAodGhpcy5tYXhGaWxlU2l6ZSAmJiBmaWxlLnNpemUgPiB0aGlzLm1heEZpbGVTaXplKSB7XG4gICAgICAgIHRoaXMuZmlsZUNvdW50ZXItLTtcbiAgICAgICAgdGhpcy5pbnB1dEVsZW1lbnQubmF0aXZlRWxlbWVudC52YWx1ZSA9ICcnO1xuICAgICAgICB0aGlzLnNob3dGaWxlVG9vTGFyZ2VNZXNzYWdlID0gdHJ1ZTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGJlZm9yZVVwbG9hZFJlc3VsdDogVXBsb2FkTWV0YWRhdGEgPSBhd2FpdCB0aGlzLmJlZm9yZVVwbG9hZCh7IGZpbGUsIHVybDogdGhpcy51cmwsIGFib3J0OiBmYWxzZSB9KTtcblxuICAgICAgaWYgKGJlZm9yZVVwbG9hZFJlc3VsdC5hYm9ydCkge1xuICAgICAgICB0aGlzLmZpbGVDb3VudGVyLS07XG4gICAgICAgIHRoaXMuaW5wdXRFbGVtZW50Lm5hdGl2ZUVsZW1lbnQudmFsdWUgPSAnJztcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGltZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xuICAgICAgaW1nLnNyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKGJlZm9yZVVwbG9hZFJlc3VsdC5maWxlKTtcblxuICAgICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcbiAgICAgIHJlYWRlci5hZGRFdmVudExpc3RlbmVyKCdsb2FkJywgKGV2ZW50OiBhbnkpID0+IHtcbiAgICAgICAgY29uc3QgZmlsZUhvbGRlcjogRmlsZUhvbGRlciA9IG5ldyBGaWxlSG9sZGVyKGV2ZW50LnRhcmdldC5yZXN1bHQsIGJlZm9yZVVwbG9hZFJlc3VsdC5maWxlKTtcbiAgICAgICAgdGhpcy51cGxvYWRTaW5nbGVGaWxlKGZpbGVIb2xkZXIsIGJlZm9yZVVwbG9hZFJlc3VsdC51cmwsIGJlZm9yZVVwbG9hZFJlc3VsdC5mb3JtRGF0YSk7XG4gICAgICAgIHRoaXMuZmlsZXMucHVzaChmaWxlSG9sZGVyKTtcbiAgICAgIH0sIGZhbHNlKTtcbiAgICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGJlZm9yZVVwbG9hZFJlc3VsdC5maWxlKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHVwbG9hZFNpbmdsZUZpbGUoZmlsZUhvbGRlcjogRmlsZUhvbGRlciwgdXJsID0gdGhpcy51cmwsIGN1c3RvbUZvcm0/OiB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfSkge1xuICAgIGlmICh1cmwpIHtcbiAgICAgIHRoaXMucGVuZGluZ0ZpbGVzQ291bnRlcisrO1xuICAgICAgZmlsZUhvbGRlci5wZW5kaW5nID0gdHJ1ZTtcblxuICAgICAgdGhpcy5pbWFnZVNlcnZpY2VcbiAgICAgICAgLnBvc3RJbWFnZSh1cmwsIGZpbGVIb2xkZXIuZmlsZSwgdGhpcy5oZWFkZXJzLCB0aGlzLnBhcnROYW1lLCBjdXN0b21Gb3JtLCB0aGlzLndpdGhDcmVkZW50aWFscylcbiAgICAgICAgLnN1YnNjcmliZShcbiAgICAgICAgICByZXNwb25zZSA9PiB0aGlzLm9uUmVzcG9uc2UocmVzcG9uc2UsIGZpbGVIb2xkZXIpLFxuICAgICAgICAgIGVycm9yID0+IHtcbiAgICAgICAgICAgIHRoaXMub25SZXNwb25zZShlcnJvciwgZmlsZUhvbGRlcik7XG4gICAgICAgICAgICB0aGlzLmRlbGV0ZUZpbGUoZmlsZUhvbGRlcik7XG4gICAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudXBsb2FkRmluaXNoZWQuZW1pdChmaWxlSG9sZGVyKTtcbiAgICB9XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgRGlyZWN0aXZlLCBFdmVudEVtaXR0ZXIsIEhvc3RMaXN0ZW5lciwgSW5wdXQsIE91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdbZmlsZURyb3BdJ1xufSlcbmV4cG9ydCBjbGFzcyBGaWxlRHJvcERpcmVjdGl2ZSB7XG4gIEBJbnB1dCgpIGFjY2VwdDogc3RyaW5nW107XG4gIEBPdXRwdXQoKSBmaWxlT3ZlcjogRXZlbnRFbWl0dGVyPGJvb2xlYW4+ID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xuICBAT3V0cHV0KCkgZmlsZURyb3A6IEV2ZW50RW1pdHRlcjxGaWxlTGlzdD4gPSBuZXcgRXZlbnRFbWl0dGVyPEZpbGVMaXN0PigpO1xuXG4gIEBIb3N0TGlzdGVuZXIoJ2Ryb3AnLCBbJyRldmVudCddKVxuICBvbkRyb3AoZXZlbnQ6IGFueSkge1xuICAgIGxldCBkYXRhVHJhbnNmZXIgPSBGaWxlRHJvcERpcmVjdGl2ZS5nZXREYXRhVHJhbnNmZXIoZXZlbnQpO1xuXG4gICAgaWYgKCFGaWxlRHJvcERpcmVjdGl2ZS5oYXNGaWxlcyhkYXRhVHJhbnNmZXIudHlwZXMpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgIGxldCBmaWxlcyA9IHRoaXMuZmlsdGVyRmlsZXMoZGF0YVRyYW5zZmVyLmZpbGVzKTtcblxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgdGhpcy5maWxlT3Zlci5lbWl0KGZhbHNlKTtcbiAgICB0aGlzLmZpbGVEcm9wLmVtaXQoZmlsZXMpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZHJhZ2xlYXZlJywgWyckZXZlbnQnXSlcbiAgb25EcmFnTGVhdmUoZXZlbnQpIHtcbiAgICB0aGlzLmZpbGVPdmVyLmVtaXQoZmFsc2UpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZHJhZ292ZXInLCBbJyRldmVudCddKVxuICBvbkRyYWdPdmVyKGV2ZW50OiBhbnkpIHtcbiAgICBsZXQgZGF0YVRyYW5zZmVyID0gRmlsZURyb3BEaXJlY3RpdmUuZ2V0RGF0YVRyYW5zZmVyKGV2ZW50KTtcblxuICAgIGlmICghRmlsZURyb3BEaXJlY3RpdmUuaGFzRmlsZXMoZGF0YVRyYW5zZmVyLnR5cGVzKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGRhdGFUcmFuc2Zlci5kcm9wRWZmZWN0ID0gJ2NvcHknO1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgdGhpcy5maWxlT3Zlci5lbWl0KHRydWUpO1xuICB9XG5cbiAgcHJpdmF0ZSBmaWx0ZXJGaWxlcyhmaWxlczogRmlsZUxpc3QpOiBhbnkge1xuICAgIGlmICghdGhpcy5hY2NlcHQgfHwgdGhpcy5hY2NlcHQubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gZmlsZXM7XG4gICAgfVxuXG4gICAgbGV0IGFjY2VwdGVkRmlsZXM6IEZpbGVbXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZmlsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5hY2NlcHQubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgaWYgKEZpbGVEcm9wRGlyZWN0aXZlLm1hdGNoUnVsZSh0aGlzLmFjY2VwdFtqXSwgZmlsZXNbaV0udHlwZSkpIHtcbiAgICAgICAgICBhY2NlcHRlZEZpbGVzLnB1c2goZmlsZXNbaV0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGFjY2VwdGVkRmlsZXM7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBnZXREYXRhVHJhbnNmZXIoZXZlbnQ6IGFueSk6IERhdGFUcmFuc2ZlciB7XG4gICAgcmV0dXJuIGV2ZW50LmRhdGFUcmFuc2ZlciA/IGV2ZW50LmRhdGFUcmFuc2ZlciA6IGV2ZW50Lm9yaWdpbmFsRXZlbnQuZGF0YVRyYW5zZmVyO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgaGFzRmlsZXModHlwZXM6IGFueSk6IGJvb2xlYW4ge1xuICAgIGlmICghdHlwZXMpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAodHlwZXMuaW5kZXhPZikge1xuICAgICAgcmV0dXJuIHR5cGVzLmluZGV4T2YoJ0ZpbGVzJykgIT09IC0xO1xuICAgIH1cblxuICAgIGlmICh0eXBlcy5jb250YWlucykge1xuICAgICAgcmV0dXJuIHR5cGVzLmNvbnRhaW5zKCdGaWxlcycpO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIG1hdGNoUnVsZShydWxlOiBzdHJpbmcsIGNhbmRpZGF0ZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAoXCJeXCIgKyBydWxlLnNwbGl0KFwiKlwiKS5qb2luKFwiLipcIikgKyBcIiRcIikudGVzdChjYW5kaWRhdGUpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBIdHRwQ2xpZW50TW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBOZ3hJbWFnZVVwbG9hZENvbXBvbmVudCB9IGZyb20gJy4vbmd4LWltYWdlLXVwbG9hZC5jb21wb25lbnQnO1xuaW1wb3J0IHsgRmlsZURyb3BEaXJlY3RpdmUgfSBmcm9tICcuLi9maWxlLWRyb3AuZGlyZWN0aXZlJztcblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgICBIdHRwQ2xpZW50TW9kdWxlXG4gIF0sXG4gIGRlY2xhcmF0aW9uczogW05neEltYWdlVXBsb2FkQ29tcG9uZW50LCBGaWxlRHJvcERpcmVjdGl2ZV0sXG4gIGV4cG9ydHM6IFtOZ3hJbWFnZVVwbG9hZENvbXBvbmVudF1cbn0pXG5leHBvcnQgY2xhc3MgTmd4SW1hZ2VVcGxvYWRNb2R1bGUgeyB9XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUE7Ozs7SUFRRSxZQUFvQixJQUFnQjtRQUFoQixTQUFJLEdBQUosSUFBSSxDQUFZO0tBQ25DOzs7Ozs7Ozs7O0lBRU0sU0FBUyxDQUFDLEdBQVcsRUFBRSxLQUFXLEVBQUUsT0FBK0MsRUFBRSxXQUFtQixPQUFPLEVBQUUsY0FBd0MsRUFBRSxlQUF5QjtRQUN6TCxJQUFJLENBQUMsR0FBRyxJQUFJLEdBQUcsS0FBSyxFQUFFLEVBQUU7WUFDdEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztTQUM3Qjs7UUFHRCxxQkFBSSxRQUFRLEdBQUcsSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUM5QixLQUFLLHFCQUFJLEdBQUcsSUFBSSxjQUFjLEVBQUU7WUFDOUIsUUFBUSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7U0FDM0M7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