ngx-image-upload
Version:
Angular 6 image upload.
380 lines (377 loc) • 41.5 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
import * as tslib_1 from "tslib";
import { Component, Input, Output, EventEmitter, ElementRef, ViewChild } from '@angular/core';
import { NgxImageUploadService } from './ngx-image-upload.service';
export class FileHolder {
/**
* @param {?} src
* @param {?} file
*/
constructor(src, file) {
this.src = src;
this.file = file;
this.pending = false;
}
}
function FileHolder_tsickle_Closure_declarations() {
/** @type {?} */
FileHolder.prototype.pending;
/** @type {?} */
FileHolder.prototype.serverResponse;
/** @type {?} */
FileHolder.prototype.src;
/** @type {?} */
FileHolder.prototype.file;
}
export 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 tslib_1.__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)}} 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',] }]
};
function NgxImageUploadComponent_tsickle_Closure_declarations() {
/** @type {?} */
NgxImageUploadComponent.prototype.files;
/** @type {?} */
NgxImageUploadComponent.prototype.fileCounter;
/** @type {?} */
NgxImageUploadComponent.prototype.fileOver;
/** @type {?} */
NgxImageUploadComponent.prototype.showFileTooLargeMessage;
/** @type {?} */
NgxImageUploadComponent.prototype.beforeUpload;
/** @type {?} */
NgxImageUploadComponent.prototype.buttonCaption;
/** @type {?} */
NgxImageUploadComponent.prototype.disabled;
/** @type {?} */
NgxImageUploadComponent.prototype.cssClass;
/** @type {?} */
NgxImageUploadComponent.prototype.clearButtonCaption;
/** @type {?} */
NgxImageUploadComponent.prototype.dropBoxMessage;
/** @type {?} */
NgxImageUploadComponent.prototype.fileTooLargeMessage;
/** @type {?} */
NgxImageUploadComponent.prototype.headers;
/** @type {?} */
NgxImageUploadComponent.prototype.max;
/** @type {?} */
NgxImageUploadComponent.prototype.maxFileSize;
/** @type {?} */
NgxImageUploadComponent.prototype.preview;
/** @type {?} */
NgxImageUploadComponent.prototype.partName;
/** @type {?} */
NgxImageUploadComponent.prototype.style;
/** @type {?} */
NgxImageUploadComponent.prototype.supportedExtensions;
/** @type {?} */
NgxImageUploadComponent.prototype.url;
/** @type {?} */
NgxImageUploadComponent.prototype.withCredentials;
/** @type {?} */
NgxImageUploadComponent.prototype.uploadedFiles;
/** @type {?} */
NgxImageUploadComponent.prototype.removed;
/** @type {?} */
NgxImageUploadComponent.prototype.uploadStateChanged;
/** @type {?} */
NgxImageUploadComponent.prototype.uploadFinished;
/** @type {?} */
NgxImageUploadComponent.prototype.previewClicked;
/** @type {?} */
NgxImageUploadComponent.prototype.inputElement;
/** @type {?} */
NgxImageUploadComponent.prototype.pendingFilesCounter;
/** @type {?} */
NgxImageUploadComponent.prototype.onFileOver;
/** @type {?} */
NgxImageUploadComponent.prototype.countRemainingSlots;
/** @type {?} */
NgxImageUploadComponent.prototype.imageService;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWltYWdlLXVwbG9hZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtaW1hZ2UtdXBsb2FkLyIsInNvdXJjZXMiOlsibGliL25neC1pbWFnZS11cGxvYWQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBcUIsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUdqSCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUduRSxNQUFNOzs7OztJQUlKLFlBQW1CLEdBQVcsRUFBUyxJQUFVO1FBQTlCLFFBQUcsR0FBSCxHQUFHLENBQVE7UUFBUyxTQUFJLEdBQUosSUFBSSxDQUFNO3VCQUh2QixLQUFLO0tBSTlCO0NBQ0Y7Ozs7Ozs7Ozs7O0FBcURELE1BQU07Ozs7SUFpQ0osWUFBb0IsWUFBbUM7UUFBbkMsaUJBQVksR0FBWixZQUFZLENBQXVCO3FCQS9CakMsRUFBRTsyQkFDRixDQUFDO3dCQUNILEtBQUs7dUNBQ1UsS0FBSzs0QkFFcUQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJOzZCQUNoRixNQUFNO3dCQUNYLEtBQUs7d0JBQ0UsUUFBUTtrQ0FDTCxJQUFJOzhCQUNSLFNBQVM7bUJBR3BCLEdBQUc7dUJBRUMsSUFBSTsrQkFLSSxLQUFLOzZCQUMyRCxFQUFFO3VCQUN6RSxJQUFJLFlBQVksRUFBYztrQ0FDbkIsSUFBSSxZQUFZLEVBQVc7OEJBQy9CLElBQUksWUFBWSxFQUFjOzhCQUM5QixJQUFJLFlBQVksRUFBYzttQ0FJbkIsQ0FBQzswQkF5RDFCLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxHQUFHLE1BQU07bUNBRWpCLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLFdBQVc7S0F6REg7Ozs7SUFFNUQsUUFB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LEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxVQUFVLEVBQUUsSUFBSSxDQUFDLGVBQWUsQ0FBQztpQkFDOUYsU0FBUyxDQUNSLFFBQVEsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLEVBQ2pELEtBQUssQ0FBQyxFQUFFO2dCQUNOLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLFVBQVUsQ0FBQyxDQUFDO2dCQUNuQyxJQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2FBQzdCLENBQUMsQ0FBQztTQUNSO1FBQUMsSUFBSSxDQUFDLENBQUM7WUFDTixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztTQUN0Qzs7OztZQXhQSixTQUFTLFNBQUM7Z0JBQ1QsUUFBUSxFQUFFLHFCQUFxQjtnQkFDL0IsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O09BOENMO2dCQUNMLE1BQU0sRUFBRSxDQUFDLDQzRkFBNDNGLENBQUM7YUFDdjRGOzs7O1lBN0RRLHFCQUFxQjs7OzJCQXFFM0IsS0FBSzs0QkFDTCxLQUFLO3VCQUNMLEtBQUs7dUJBQ0wsS0FBSyxTQUFDLE9BQU87aUNBQ2IsS0FBSzs2QkFDTCxLQUFLO2tDQUNMLEtBQUs7c0JBQ0wsS0FBSztrQkFDTCxLQUFLOzBCQUNMLEtBQUs7c0JBQ0wsS0FBSzt1QkFDTCxLQUFLO29CQUNMLEtBQUs7a0NBQ0wsS0FBSyxTQUFDLFlBQVk7a0JBQ2xCLEtBQUs7OEJBQ0wsS0FBSzs0QkFDTCxLQUFLO3NCQUNMLE1BQU07aUNBQ04sTUFBTTs2QkFDTixNQUFNOzZCQUNOLE1BQU07MkJBRU4sU0FBUyxTQUFDLE9BQU8iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgT25DaGFuZ2VzLCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIEVsZW1lbnRSZWYsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBVcGxvYWRNZXRhZGF0YSB9IGZyb20gJy4vYmVmb3JlLXVwbG9hZC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgTmd4SW1hZ2VVcGxvYWRTZXJ2aWNlIH0gZnJvbSAnLi9uZ3gtaW1hZ2UtdXBsb2FkLnNlcnZpY2UnO1xuaW1wb3J0IHsgU3R5bGUgfSBmcm9tICcuL3N0eWxlJztcblxuZXhwb3J0IGNsYXNzIEZpbGVIb2xkZXIge1xuICBwdWJsaWMgcGVuZGluZzogYm9vbGVhbiA9IGZhbHNlO1xuICBwdWJsaWMgc2VydmVyUmVzcG9uc2U6IHsgc3RhdHVzOiBudW1iZXIsIHJlc3BvbnNlOiBhbnkgfTtcblxuICBjb25zdHJ1Y3RvcihwdWJsaWMgc3JjOiBzdHJpbmcsIHB1YmxpYyBmaWxlOiBGaWxlKSB7XG4gIH1cbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZHMtbmd4LWltYWdlLXVwbG9hZCcsXG4gIHRlbXBsYXRlOiBgPGRpdlxuICAgICBmaWxlRHJvcFxuICAgICBbYWNjZXB0XT1cInN1cHBvcnRlZEV4dGVuc2lvbnNcIlxuICAgICAoZmlsZU92ZXIpPVwib25GaWxlT3ZlcigkZXZlbnQpXCJcbiAgICAgKGZpbGVEcm9wKT1cIm9uRmlsZUNoYW5nZSgkZXZlbnQpXCJcbiAgICAgW25nQ2xhc3NdPVwiY3NzQ2xhc3NcIlxuICAgICBbbmdDbGFzc109XCJ7J2ltZy11bC1maWxlLWlzLW92ZXInOiBmaWxlT3Zlcn1cIiAgICAgXG4gICAgIFtuZ1N0eWxlXT1cInN0eWxlPy5sYXlvdXRcIlxuPlxuICA8cCBjbGFzcz1cImltZy11bC1maWxlLXRvby1sYXJnZVwiICpuZ0lmPVwic2hvd0ZpbGVUb29MYXJnZU1lc3NhZ2VcIiBbaW5uZXJUZXh0XT1cImZpbGVUb29MYXJnZU1lc3NhZ2VcIj48L3A+XG5cbiAgPGRpdiAqbmdJZj1cInByZXZpZXdcIiBjbGFzcz1cImltZy11bC1jb250YWluZXIgaW1nLXVsLWhyLWlubGluZS1ncm91cFwiIFtuZ1N0eWxlXT1cInN0eWxlPy5wcmV2aWV3UGFuZWxcIj5cbiAgICA8IS0tIGltZyAtLT5cbiAgICA8ZGl2XG4gICAgICBjbGFzcz1cImltZy11bC1pbWFnZVwiXG4gICAgICAqbmdGb3I9XCJsZXQgZmlsZSBvZiBmaWxlc1wiXG4gICAgICAoY2xpY2spPVwicHJldmlld0ZpbGVDbGlja2VkKGZpbGUpXCJcbiAgICA+XG4gICAgICA8IS0tIFtuZ1N0eWxlXT1cInsnYmFja2dyb3VuZC1pbWFnZSc6ICd1cmwoJysgZmlsZS5zcmMgKycpJ31cIiAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbWdfZGl2XCI+PGltZyBzcmM9e3tmaWxlLnNyY319IGNsYXNzPVwiaW1nc1wiPjwvZGl2PlxuICAgICAgPGRpdiAqbmdJZj1cImZpbGUucGVuZGluZ1wiIGNsYXNzPVwiaW1nLXVsLWxvYWRpbmctb3ZlcmxheVwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiaW1nLXVsLXNwaW5uaW5nLWNpcmNsZVwiPjwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2ICpuZ0lmPVwiIWZpbGUucGVuZGluZ1wiIFxuICAgICAgICBbbmdDbGFzc109XCJ7J2ltZy11bC1kaXNhYmxlZCc6IGRpc2FibGVkfVwiIFxuICAgICAgICBjbGFzcz1cImltZy11bC14LW1hcmtcIiBcbiAgICAgICAgKGNsaWNrKT1cImRlbGV0ZUZpbGUoZmlsZSlcIj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJpbWctdWwtY2xvc2VcIj48L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIFxuICA8ZGl2IGNsYXNzPVwiaW1nLXVsLWZpbGUtdXBsb2FkIGltZy11bC1oci1pbmxpbmUtZ3JvdXBcIj4gICAgXG4gICAgPGxhYmVsICpuZ0lmPVwiZmlsZUNvdW50ZXIgIT0gbWF4XCJcbiAgICAgIGNsYXNzPVwiaW1nLXVsLXVwbG9hZCBpbWctdWwtYnV0dG9uXCIgXG4gICAgICBbbmdTdHlsZV09XCJzdHlsZT8uc2VsZWN0QnV0dG9uXCJcbiAgICAgIFtuZ0NsYXNzXT1cInsnaW1nLXVsLWRpc2FibGVkJzogZGlzYWJsZWR9XCI+XG4gICAgICA8c3BhbiBbaW5uZXJUZXh0XT1cImJ1dHRvbkNhcHRpb25cIj48L3NwYW4+XG4gICAgICA8aW5wdXRcbiAgICAgICAgdHlwZT1cImZpbGVcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICBbYWNjZXB0XT1cInN1cHBvcnRlZEV4dGVuc2lvbnNcIlxuICAgICAgICBtdWx0aXBsZSAoY2hhbmdlKT1cIm9uRmlsZUNoYW5nZShpbnB1dC5maWxlcylcIlxuICAgICAgICAjaW5wdXQ+XG4gICAgPC9sYWJlbD5cbiAgPC9kaXY+XG48L2Rpdj5gLFxuICBzdHlsZXM6IFtgLmltZy11bHstLWNvbW1vbi1yYWRpdXM6M3B4O2JvcmRlci1yYWRpdXM6dmFyKC0tY29tbW9uLXJhZGl1cyk7cG9zaXRpb246cmVsYXRpdmU7Y29sb3I6IzliOWI5Yjtmb250LXdlaWdodDo0MDB9LmltZy11bC14LW1hcmt7YmFja2dyb3VuZC1jb2xvcjojMDAwO2JvcmRlci1yYWRpdXM6MTBweDtjb2xvcjojZmZmO2N1cnNvcjpwb2ludGVyO2hlaWdodDoyMHB4O29wYWNpdHk6Ljc7dGV4dC1hbGlnbjpjZW50ZXI7d2lkdGg6MjBweDtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6LThweDtyaWdodDotMTBweH0uaW1nX2Rpdntwb3NpdGlvbjpyZWxhdGl2ZTt3aWR0aDoxMjBweDtoZWlnaHQ6MTIwcHg7b3ZlcmZsb3c6aGlkZGVufS5pbWdze21heC13aWR0aDoyMDAlO2hlaWdodDphdXRvO3Bvc2l0aW9uOmFic29sdXRlO3RvcDo1MCU7bGVmdDo1MCU7LXdlYmtpdC10cmFuc2Zvcm06dHJhbnNsYXRlKC01MCUsLTUwJSk7dHJhbnNmb3JtOnRyYW5zbGF0ZSgtNTAlLC01MCUpO2JhY2tncm91bmQ6IzAwMH0uaW1nLXVsLWZpbGUtaXMtb3Zlcntib3JkZXI6dmFyKC0tYWN0aXZlLWNvbG9yKSBzb2xpZH0uaW1nLXVsLWhyLWlubGluZS1ncm91cDphZnRlcntjbGVhcjpib3RoO2NvbnRlbnQ6XCJcIjtkaXNwbGF5OnRhYmxlfS5pbWctdWwtZmlsZS11cGxvYWR7ZGlzcGxheTppbmxpbmUtYmxvY2s7d2lkdGg6MTIwcHg7aGVpZ2h0OjEyMHB4O21hcmdpbjoxMHB4O2NvbG9yOiMwMDA7dGV4dC1hbGlnbjpjZW50ZXI7bGluZS1oZWlnaHQ6MTIwcHh9LmltZy11bC1kcmFnLWJveC1tc2d7ZGlzcGxheTppbmxpbmUtYmxvY2s7Zm9udC13ZWlnaHQ6NjAwO21hcmdpbi1sZWZ0OjEycHh9bGFiZWwuaW1nLXVsLWJ1dHRvbntib3JkZXI6MXB4IGRhc2hlZCAjZDBkMGQwO2ZvbnQtc2l6ZToxZW0haW1wb3J0YW50fWxhYmVsLmltZy11bC1idXR0b24gaW5wdXRbdHlwZT1maWxlXXtkaXNwbGF5Om5vbmU7cG9zaXRpb246Zml4ZWQ7dG9wOi05OTk5OXB4fS5pbWctdWwtY2xlYXJ7YmFja2dyb3VuZC1jb2xvcjpyZWQ7Zm9udC1zaXplOjFlbSFpbXBvcnRhbnR9LmltZy11bC1jbGVhcjpkaXNhYmxlZHtiYWNrZ3JvdW5kLWNvbG9yOiNmZjY0NjQ7Y3Vyc29yOmRlZmF1bHR9LmltZy11bC11cGxvYWR7YmFja2dyb3VuZC1jb2xvcjp2YXIoLS1hY3RpdmUtY29sb3IpO3dpZHRoOjEyMHB4O2hlaWdodDoxMjBweH0uaW1nLXVsLWJ1dHRvbntib3JkZXI6bm9uZTtjdXJzb3I6cG9pbnRlcjtkaXNwbGF5OmlubGluZS1ibG9jaztmbG9hdDpsZWZ0O2ZvbnQtc2l6ZToxLjI1ZW07Zm9udC13ZWlnaHQ6NTAwO3RleHQtdHJhbnNmb3JtOnVwcGVyY2FzZX0uaW1nLXVsLWJ1dHRvbjphY3RpdmUgc3BhbntkaXNwbGF5OmJsb2NrO3Bvc2l0aW9uOnJlbGF0aXZlO3RvcDoxcHh9LmltZy11bC1jb250YWluZXJ7cG9zaXRpb246cmVsYXRpdmU7ZGlzcGxheTppbmxpbmUtYmxvY2t9LmltZy11bC1pbWFnZXtib3gtc2hhZG93OjAgMCAxMHB4IDJweCAjZDBkMGQwO2JhY2tncm91bmQ6Y2VudGVyIGNlbnRlci9jb250YWluIG5vLXJlcGVhdDtkaXNwbGF5OmlubGluZS1ibG9jaztmbG9hdDpsZWZ0O2hlaWdodDoxMjBweDttYXJnaW46NnB4O3Bvc2l0aW9uOnJlbGF0aXZlO3dpZHRoOjEyMHB4fS5pbWctdWwtY2xvc2V7aGVpZ2h0OjIwcHg7b3BhY2l0eTouNztwb3NpdGlvbjpyZWxhdGl2ZTt3aWR0aDoyMHB4fS5pbWctdWwteC1tYXJrOmhvdmVyIC5pbWctdWwtY2xvc2V7b3BhY2l0eToxfS5pbWctdWwtY2xvc2U6YWZ0ZXIsLmltZy11bC1jbG9zZTpiZWZvcmV7YmFja2dyb3VuZC1jb2xvcjojZmZmO2JvcmRlci1yYWRpdXM6MnB4O2NvbnRlbnQ6Jyc7aGVpZ2h0OjEwcHg7cG9zaXRpb246YWJzb2x1dGU7dG9wOjVweDt3aWR0aDoycHh9LmltZy11bC1jbG9zZTpiZWZvcmV7LXdlYmtpdC10cmFuc2Zvcm06cm90YXRlKDQ1ZGVnKTt0cmFuc2Zvcm06cm90YXRlKDQ1ZGVnKX0uaW1nLXVsLWNsb3NlOmFmdGVyey13ZWJraXQtdHJhbnNmb3JtOnJvdGF0ZSgtNDVkZWcpO3RyYW5zZm9ybTpyb3RhdGUoLTQ1ZGVnKX0uaW1nLXVsLXgtbWFyay5pbWctdWwtZGlzYWJsZWR7ZGlzcGxheTpub25lfS5pbWctdWwtbG9hZGluZy1vdmVybGF5e2JhY2tncm91bmQtY29sb3I6IzAwMDtib3R0b206MDtsZWZ0OjA7b3BhY2l0eTouNztwb3NpdGlvbjphYnNvbHV0ZTtyaWdodDowO3RvcDowfS5pbWctdWwtc3Bpbm5pbmctY2lyY2xle2hlaWdodDozMHB4O3dpZHRoOjMwcHg7bWFyZ2luOmF1dG87cG9zaXRpb246YWJzb2x1dGU7dG9wOjA7bGVmdDowO2JvdHRvbTowO3JpZ2h0OjA7Ym9yZGVyLXJhZGl1czo1MCU7Ym9yZGVyOjNweCBzb2xpZCByZ2JhKDI1NSwyNTUsMjU1LDApO2JvcmRlci10b3A6M3B4IHNvbGlkICNmZmY7Ym9yZGVyLXJpZ2h0OjNweCBzb2xpZCAjZmZmOy13ZWJraXQtYW5pbWF0aW9uOjJzIGN1YmljLWJlemllciguMDg1LC42MjUsLjg1NSwuMzYpIGluZmluaXRlIHNwaW5uZXI7YW5pbWF0aW9uOjJzIGN1YmljLWJlemllciguMDg1LC42MjUsLjg1NSwuMzYpIGluZmluaXRlIHNwaW5uZXJ9LmltZy11bC1maWxlLXRvby1sYXJnZXtjb2xvcjpyZWR9LmltZy11bC11cGxvYWQuaW1nLXVsLWRpc2FibGVke2JhY2tncm91bmQtY29sb3I6Izg2ZTljOTtjdXJzb3I6ZGVmYXVsdH0uaW1nLXVsLXVwbG9hZC5pbWctdWwtZGlzYWJsZWQ6YWN0aXZlIHNwYW57dG9wOjB9QC13ZWJraXQta2V5ZnJhbWVzIHNwaW5uZXJ7MCV7LXdlYmtpdC10cmFuc2Zvcm06cm90YXRlKDApO3RyYW5zZm9ybTpyb3RhdGUoMCl9MTAwJXstd2Via2l0LXRyYW5zZm9ybTpyb3RhdGUoMzYwZGVnKTt0cmFuc2Zvcm06cm90YXRlKDM2MGRlZyl9fUBrZXlmcmFtZXMgc3Bpbm5lcnswJXstd2Via2l0LXRyYW5zZm9ybTpyb3RhdGUoMCk7dHJhbnNmb3JtOnJvdGF0ZSgwKX0xMDAley13ZWJraXQtdHJhbnNmb3JtOnJvdGF0ZSgzNjBkZWcpO3RyYW5zZm9ybTpyb3RhdGUoMzYwZGVnKX19YF1cbn0pXG5leHBvcnQgY2xhc3MgTmd4SW1hZ2VVcGxvYWRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcyB7XG5cbiAgZmlsZXM6IEZpbGVIb2xkZXJbXSA9IFtdO1xuICBmaWxlQ291bnRlcjogbnVtYmVyID0gMDtcbiAgZmlsZU92ZXI6IGJvb2xlYW4gPSBmYWxzZTtcbiAgc2hvd0ZpbGVUb29MYXJnZU1lc3NhZ2U6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBASW5wdXQoKSBiZWZvcmVVcGxvYWQ6IChwYXJhbTogVXBsb2FkTWV0YWRhdGEpID0+IFVwbG9hZE1ldGFkYXRhIHwgUHJvbWlzZTxVcGxvYWRNZXRhZGF0YT4gPSBkYXRhID0+IGRhdGE7XG4gIEBJbnB1dCgpIGJ1dHRvbkNhcHRpb24gPSAn5re75Yqg5Zu+54mHJztcbiAgQElucHV0KCkgZGlzYWJsZWQgPSBmYWxzZTtcbiAgQElucHV0KCdjbGFzcycpIGNzc0NsYXNzID0gJ2ltZy11bCc7XG4gIEBJbnB1dCgpIGNsZWFyQnV0dG9uQ2FwdGlvbiA9ICfmuIXpmaQnO1xuICBASW5wdXQoKSBkcm9wQm94TWVzc2FnZSA9ICfmi5bmi73lm77niYfliLDmraTlpIQnO1xuICBASW5wdXQoKSBmaWxlVG9vTGFyZ2VNZXNzYWdlO1xuICBASW5wdXQoKSBoZWFkZXJzOiBIZWFkZXJzIHwgeyBbbmFtZTogc3RyaW5nXTogYW55IH07XG4gIEBJbnB1dCgpIG1heCA9IDEwMDtcbiAgQElucHV0KCkgbWF4RmlsZVNpemU6IG51bWJlcjtcbiAgQElucHV0KCkgcHJldmlldyA9IHRydWU7XG4gIEBJbnB1dCgpIHBhcnROYW1lOiBzdHJpbmc7XG4gIEBJbnB1dCgpIHN0eWxlOiBTdHlsZTtcbiAgQElucHV0KCdleHRlbnNpb25zJykgc3VwcG9ydGVkRXh0ZW5zaW9uczogc3RyaW5nW107XG4gIEBJbnB1dCgpIHVybDogc3RyaW5nO1xuICBASW5wdXQoKSB3aXRoQ3JlZGVudGlhbHMgPSBmYWxzZTtcbiAgQElucHV0KCkgdXBsb2FkZWRGaWxlczogc3RyaW5nW10gfCBBcnJheTx7IHVybDogc3RyaW5nLCBmaWxlTmFtZTogc3RyaW5nLCBibG9iPzogQmxvYiB9PiA9IFtdO1xuICBAT3V0cHV0KCkgcmVtb3ZlZCA9IG5ldyBFdmVudEVtaXR0ZXI8RmlsZUhvbGRlcj4oKTtcbiAgQE91dHB1dCgpIHVwbG9hZFN0YXRlQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcbiAgQE91dHB1dCgpIHVwbG9hZEZpbmlzaGVkID0gbmV3IEV2ZW50RW1pdHRlcjxGaWxlSG9sZGVyPigpO1xuICBAT3V0cHV0KCkgcHJldmlld0NsaWNrZWQgPSBuZXcgRXZlbnRFbWl0dGVyPEZpbGVIb2xkZXI+KCk7XG5cbiAgQFZpZXdDaGlsZCgnaW5wdXQnKVxuICBwcml2YXRlIGlucHV0RWxlbWVudDogRWxlbWVudFJlZjtcbiAgcHJpdmF0ZSBwZW5kaW5nRmlsZXNDb3VudGVyOiBudW1iZXIgPSAwO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgaW1hZ2VTZXJ2aWNlOiBOZ3hJbWFnZVVwbG9hZFNlcnZpY2UpIHsgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIGlmICghdGhpcy5maWxlVG9vTGFyZ2VNZXNzYWdlKSB7XG4gICAgICB0aGlzLmZpbGVUb29MYXJnZU1lc3NhZ2UgPSAn5Zu+54mH5aSq5aSn5peg5rOV5LiK5LygLicgKyAodGhpcy5tYXhGaWxlU2l6ZSA/ICgnIOacgOWkp+WFgeiuuCAnICsgdGhpcy5tYXhGaWxlU2l6ZSAvIDEwMjQpICsgJ0tpQi4nIDogJycpO1xuICAgIH1cbiAgICB0aGlzLnN1cHBvcnRlZEV4dGVuc2lvbnMgPSB0aGlzLnN1cHBvcnRlZEV4dGVuc2lvbnMgPyB0aGlzLnN1cHBvcnRlZEV4dGVuc2lvbnMubWFwKChleHQpID0+ICdpbWFnZS8nICsgZXh0KSA6IFsnaW1hZ2UvKiddO1xuICB9XG5cbiAgZGVsZXRlQWxsKCkge1xuICAgIHRoaXMuZmlsZXMuZm9yRWFjaChmID0+IHRoaXMucmVtb3ZlZC5lbWl0KGYpKTtcbiAgICB0aGlzLmZpbGVzID0gW107XG4gICAgdGhpcy5maWxlQ291bnRlciA9IDA7XG4gICAgaWYgKHRoaXMuaW5wdXRFbGVtZW50KSB7XG4gICAgICB0aGlzLmlucHV0RWxlbWVudC5uYXRpdmVFbGVtZW50LnZhbHVlID0gJyc7XG4gICAgfVxuICB9XG5cbiAgZGVsZXRlRmlsZShmaWxlOiBGaWxlSG9sZGVyKTogdm9pZCB7XG4gICAgbGV0IGluZGV4ID0gdGhpcy5maWxlcy5pbmRleE9mKGZpbGUpO1xuICAgIHRoaXMuZmlsZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICB0aGlzLmZpbGVDb3VudGVyLS07XG5cbiAgICBpZiAodGhpcy5pbnB1dEVsZW1lbnQpIHtcbiAgICAgIHRoaXMuaW5wdXRFbGVtZW50Lm5hdGl2ZUVsZW1lbnQudmFsdWUgPSAnJztcbiAgICB9XG4gICAgdGhpcy5yZW1vdmVkLmVtaXQoZmlsZSk7XG4gIH1cblxuICBwcmV2aWV3RmlsZUNsaWNrZWQoZmlsZTogRmlsZUhvbGRlcikge1xuICAgIHRoaXMucHJldmlld0NsaWNrZWQuZW1pdChmaWxlKTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXMpIHtcbiAgICBpZiAoY2hhbmdlcy51cGxvYWRlZEZpbGVzICYmIGNoYW5nZXMudXBsb2FkZWRGaWxlcy5jdXJyZW50VmFsdWUgJiYgY2hhbmdlcy51cGxvYWRlZEZpbGVzLmN1cnJlbnRWYWx1ZS5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLnByb2Nlc3NVcGxvYWRlZEZpbGVzKCk7XG4gICAgfVxuICB9XG5cbiAgb25GaWxlQ2hhbmdlKGZpbGVzOiBGaWxlTGlzdCkge1xuICAgIGlmICh0aGlzLmRpc2FibGVkKSByZXR1cm47XG5cbiAgICAvLyBsZXQgcmVtYWluaW5nU2xvdHMgPSAwO1xuICAgIGxldCByZW1haW5pbmdTbG90cyA9IHRoaXMuY291bnRSZW1haW5pbmdTbG90cygpO1xuICAgIGxldCBmaWxlc1RvVXBsb2FkTnVtID0gZmlsZXMubGVuZ3RoID4gcmVtYWluaW5nU2xvdHMgPyByZW1haW5pbmdTbG90cyA6IGZpbGVzLmxlbmd0aDtcblxuICAgIGlmICh0aGlzLnVybCAmJiBmaWxlc1RvVXBsb2FkTnVtICE9IDApIHtcbiAgICAgIHRoaXMudXBsb2FkU3RhdGVDaGFuZ2VkLmVtaXQodHJ1ZSk7XG4gICAgfVxuXG4gICAgdGhpcy5maWxlQ291bnRlciArPSBmaWxlc1RvVXBsb2FkTnVtO1xuICAgIHRoaXMuc2hvd0ZpbGVUb29MYXJnZU1lc3NhZ2UgPSBmYWxzZTtcbiAgICB0aGlzLnVwbG9hZEZpbGVzKGZpbGVzLCBmaWxlc1RvVXBsb2FkTnVtKTtcbiAgfVxuXG4gIG9uRmlsZU92ZXIgPSAoaXNPdmVyKSA9PiB0aGlzLmZpbGVPdmVyID0gaXNPdmVyO1xuXG4gIHByaXZhdGUgY291bnRSZW1haW5pbmdTbG90cyA9ICgpID0+IHRoaXMubWF4IC0gdGhpcy5maWxlQ291bnRlcjtcblxuICBwcml2YXRlIG9uUmVzcG9uc2UocmVzcG9uc2U6IFJlc3BvbnNlLCBmaWxlSG9sZGVyOiBGaWxlSG9sZGVyKSB7XG4gICAgZmlsZUhvbGRlci5zZXJ2ZXJSZXNwb25zZSA9IHsgc3RhdHVzOiByZXNwb25zZS5zdGF0dXMsIHJlc3BvbnNlIH07XG4gICAgZmlsZUhvbGRlci5wZW5kaW5nID0gZmFsc2U7XG5cbiAgICB0aGlzLnVwbG9hZEZpbmlzaGVkLmVtaXQoZmlsZUhvbGRlcik7XG5cbiAgICBpZiAoLS10aGlzLnBlbmRpbmdGaWxlc0NvdW50ZXIgPT0gMCkge1xuICAgICAgdGhpcy51cGxvYWRTdGF0ZUNoYW5nZWQuZW1pdChmYWxzZSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBwcm9jZXNzVXBsb2FkZWRGaWxlcygpIHtcbiAgICBpZiAodHlwZW9mIHRoaXMudXBsb2FkZWRGaWxlcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGxldCBkYXRhOiBhbnkgPSB0aGlzLnVwbG9hZGVkRmlsZXM7XG5cbiAgICAgIHRoaXMuZmlsZUNvdW50ZXIgPSAxO1xuICAgICAgdGhpcy5tYXggPSAxO1xuXG4gICAgICBsZXQgZmlsZUJsb2I6IEJsb2IsXG4gICAgICAgIGZpbGU6IEZpbGUsXG4gICAgICAgIGZpbGVVcmw6IHN0cmluZztcblxuICAgICAgaWYgKGRhdGEgaW5zdGFuY2VvZiBPYmplY3QpIHtcbiAgICAgICAgZmlsZVVybCA9IGRhdGEudXJsO1xuICAgICAgICBmaWxlQmxvYiA9IChkYXRhLmJsb2IpID8gZGF0YS5ibG9iIDogbmV3IEJsb2IoW2RhdGFdKTtcbiAgICAgICAgZmlsZSA9IG5ldyBGaWxlKFtmaWxlQmxvYl0sIGRhdGEuZmlsZU5hbWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZmlsZVVybCA9IGRhdGE7XG4gICAgICAgIGZpbGVCbG9iID0gbmV3IEJsb2IoW2ZpbGVVcmxdKTtcbiAgICAgICAgZmlsZSA9IG5ldyBGaWxlKFtmaWxlQmxvYl0sIGZpbGVVcmwpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmZpbGVzID0gW107XG4gICAgICB0aGlzLmZpbGVzLnB1c2gobmV3IEZpbGVIb2xkZXIoZmlsZVVybCwgZmlsZSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1heCA9IHRoaXMubWF4IC0gT2JqZWN0LmtleXModGhpcy51cGxvYWRlZEZpbGVzKS5sZW5ndGg7XG4gICAgICBmb3IgKGNvbnN0IGkgaW4gdGhpcy51cGxvYWRlZEZpbGVzKSB7XG4gICAgICAgIGxldCBkYXRhOiBhbnkgPSB0aGlzLnVwbG9hZGVkRmlsZXNbaV07XG5cbiAgICAgICAgbGV0IGZpbGVCbG9iOiBCbG9iLFxuICAgICAgICAgIGZpbGU6IEZpbGUsXG4gICAgICAgICAgZmlsZVVybDogc3RyaW5nO1xuXG4gICAgICAgIGlmIChkYXRhIGluc3RhbmNlb2YgT2JqZWN0KSB7XG4gICAgICAgICAgZmlsZVVybCA9IGRhdGEudXJsO1xuICAgICAgICAgIGZpbGVCbG9iID0gKGRhdGEuYmxvYikgPyBkYXRhLmJsb2IgOiBuZXcgQmxvYihbZGF0YV0pO1xuICAgICAgICAgIGZpbGUgPSBuZXcgRmlsZShbZmlsZUJsb2JdLCBkYXRhLmZpbGVOYW1lKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmaWxlVXJsID0gZGF0YTtcbiAgICAgICAgICBmaWxlQmxvYiA9IG5ldyBCbG9iKFtmaWxlVXJsXSk7XG4gICAgICAgICAgZmlsZSA9IG5ldyBGaWxlKFtmaWxlQmxvYl0sIGZpbGVVcmwpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5maWxlcy5wdXNoKG5ldyBGaWxlSG9sZGVyKGZpbGVVcmwsIGZpbGUpKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHVwbG9hZEZpbGVzKGZpbGVzOiBGaWxlTGlzdCwgZmlsZXNUb1VwbG9hZE51bTogbnVtYmVyKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmaWxlc1RvVXBsb2FkTnVtOyBpKyspIHtcbiAgICAgIGNvbnN0IGZpbGUgPSBmaWxlc1tpXTtcblxuICAgICAgaWYgKHRoaXMubWF4RmlsZVNpemUgJiYgZmlsZS5zaXplID4gdGhpcy5tYXhGaWxlU2l6ZSkge1xuICAgICAgICB0aGlzLmZpbGVDb3VudGVyLS07XG4gICAgICAgIHRoaXMuaW5wdXRFbGVtZW50Lm5hdGl2ZUVsZW1lbnQudmFsdWUgPSAnJztcbiAgICAgICAgdGhpcy5zaG93RmlsZVRvb0xhcmdlTWVzc2FnZSA9IHRydWU7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBiZWZvcmVVcGxvYWRSZXN1bHQ6IFVwbG9hZE1ldGFkYXRhID0gYXdhaXQgdGhpcy5iZWZvcmVVcGxvYWQoeyBmaWxlLCB1cmw6IHRoaXMudXJsLCBhYm9ydDogZmFsc2UgfSk7XG5cbiAgICAgIGlmIChiZWZvcmVVcGxvYWRSZXN1bHQuYWJvcnQpIHtcbiAgICAgICAgdGhpcy5maWxlQ291bnRlci0tO1xuICAgICAgICB0aGlzLmlucHV0RWxlbWVudC5uYXRpdmVFbGVtZW50LnZhbHVlID0gJyc7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBpbWcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcbiAgICAgIGltZy5zcmMgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTChiZWZvcmVVcGxvYWRSZXN1bHQuZmlsZSk7XG5cbiAgICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XG4gICAgICByZWFkZXIuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIChldmVudDogYW55KSA9PiB7XG4gICAgICAgIGNvbnN0IGZpbGVIb2xkZXI6IEZpbGVIb2xkZXIgPSBuZXcgRmlsZUhvbGRlcihldmVudC50YXJnZXQucmVzdWx0LCBiZWZvcmVVcGxvYWRSZXN1bHQuZmlsZSk7XG4gICAgICAgIHRoaXMudXBsb2FkU2luZ2xlRmlsZShmaWxlSG9sZGVyLCBiZWZvcmVVcGxvYWRSZXN1bHQudXJsLCBiZWZvcmVVcGxvYWRSZXN1bHQuZm9ybURhdGEpO1xuICAgICAgICB0aGlzLmZpbGVzLnB1c2goZmlsZUhvbGRlcik7XG4gICAgICB9LCBmYWxzZSk7XG4gICAgICByZWFkZXIucmVhZEFzRGF0YVVSTChiZWZvcmVVcGxvYWRSZXN1bHQuZmlsZSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGxvYWRTaW5nbGVGaWxlKGZpbGVIb2xkZXI6IEZpbGVIb2xkZXIsIHVybCA9IHRoaXMudXJsLCBjdXN0b21Gb3JtPzogeyBbbmFtZTogc3RyaW5nXTogYW55IH0pIHtcbiAgICBpZiAodXJsKSB7XG4gICAgICB0aGlzLnBlbmRpbmdGaWxlc0NvdW50ZXIrKztcbiAgICAgIGZpbGVIb2xkZXIucGVuZGluZyA9IHRydWU7XG5cbiAgICAgIHRoaXMuaW1hZ2VTZXJ2aWNlXG4gICAgICAgIC5wb3N0SW1hZ2UodXJsLCBmaWxlSG9sZGVyLmZpbGUsIHRoaXMuaGVhZGVycywgdGhpcy5wYXJ0TmFtZSwgY3VzdG9tRm9ybSwgdGhpcy53aXRoQ3JlZGVudGlhbHMpXG4gICAgICAgIC5zdWJzY3JpYmUoXG4gICAgICAgICAgcmVzcG9uc2UgPT4gdGhpcy5vblJlc3BvbnNlKHJlc3BvbnNlLCBmaWxlSG9sZGVyKSxcbiAgICAgICAgICBlcnJvciA9PiB7XG4gICAgICAgICAgICB0aGlzLm9uUmVzcG9uc2UoZXJyb3IsIGZpbGVIb2xkZXIpO1xuICAgICAgICAgICAgdGhpcy5kZWxldGVGaWxlKGZpbGVIb2xkZXIpO1xuICAgICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnVwbG9hZEZpbmlzaGVkLmVtaXQoZmlsZUhvbGRlcik7XG4gICAgfVxuICB9XG5cbn1cbiJdfQ==