ngx-image-upload
Version:
Angular 6 image upload.
492 lines (482 loc) • 52.3 kB
JavaScript
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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