cfc-ds
Version:
Design System do Conselho Federal de Contabilidade baseado no govbr-ds
242 lines • 45.9 kB
JavaScript
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/forms";
import * as i3 from "@angular/flex-layout/extended";
export class UploadComponent {
config;
parentForm;
filesChanged = new EventEmitter();
fileInput;
files = [];
isDragging = false;
isInvalid = false;
uploading = false;
message = null;
get acceptedFileTypesString() {
return this.config?.acceptedFileTypes?.join(',') || '';
}
constructor() { }
ngOnInit() {
if (!this.config) {
console.error('A configuração do componente Upload é obrigatória');
}
}
openFileSelector() {
this.fileInput.nativeElement.click();
}
onDragOver(event) {
event.preventDefault();
event.stopPropagation();
this.isDragging = true;
}
onDragLeave(event) {
event.preventDefault();
event.stopPropagation();
this.isDragging = false;
}
onDrop(event) {
event.preventDefault();
event.stopPropagation();
this.isDragging = false;
if (event.dataTransfer?.files) {
this.handleFiles(event.dataTransfer.files);
}
}
onFileSelected(event) {
const input = event.target;
if (input.files) {
this.handleFiles(input.files);
}
}
handleFiles(fileList) {
if (!this.config)
return;
// Verificar se é permitido múltiplos arquivos
if (!this.config.multiple && fileList.length > 1) {
this.showMessage({
type: 'error',
text: this.config.messages?.error || 'É permitido o envio de apenas um arquivo'
});
return;
}
// Verificar número máximo de arquivos
if (this.config.maxFiles && this.files.length + fileList.length > this.config.maxFiles) {
this.showMessage({
type: 'error',
text: this.config.messages?.maxFilesError ||
`É permitido o envio de no máximo ${this.config.maxFiles} arquivos`
});
return;
}
// Validar e processar cada arquivo
const newFiles = [];
let hasInvalidFiles = false;
this.uploading = true;
// Array para armazenar promessas de processamento de arquivos
const fileProcessingPromises = [];
for (let i = 0; i < fileList.length; i++) {
const file = fileList[i];
const isValid = this.validateFile(file);
if (isValid) {
// Criar uma promessa para cada arquivo
const filePromise = new Promise((resolve) => {
const reader = new FileReader();
reader.onload = () => {
// O arquivo foi lido completamente
if (!this.config.multiple) {
// Se não permite múltiplos arquivos, substitui o arquivo existente
if (this.files.length > 0) {
this.showMessage({
type: 'warning',
text: 'O arquivo enviado anteriormente foi substituído'
});
this.files = [file];
newFiles.push(file);
}
else {
this.files.push(file);
newFiles.push(file);
}
}
else {
this.files.push(file);
newFiles.push(file);
}
resolve();
};
// Em caso de erro na leitura
reader.onerror = () => {
hasInvalidFiles = true;
this.showMessage({
type: 'error',
text: `Erro ao processar o arquivo ${file.name}`
});
resolve();
};
// Inicia a leitura do arquivo
reader.readAsArrayBuffer(file);
});
fileProcessingPromises.push(filePromise);
}
else {
hasInvalidFiles = true;
}
}
// Aguardar o processamento de todos os arquivos
Promise.all(fileProcessingPromises)
.then(() => {
this.uploading = false;
if (newFiles.length > 0 && !hasInvalidFiles) {
this.showMessage({
type: 'success',
text: this.config?.messages?.success || 'Campo preenchido corretamente'
});
}
this.filesChanged.emit(this.files);
})
.catch(error => {
this.uploading = false;
this.showMessage({
type: 'error',
text: 'Erro no processamento dos arquivos'
});
console.error('File processing error:', error);
});
}
validateFile(file) {
if (!this.config)
return false;
// Validar tipo de arquivo
if (this.config.acceptedFileTypes && this.config.acceptedFileTypes.length > 0) {
const fileNameParts = file.name.split('.');
const fileExtension = fileNameParts.length > 1 ? fileNameParts.pop()?.toLowerCase() : '';
const fileType = file.type;
const isValidType = this.config.acceptedFileTypes.some(type => {
if (type.startsWith('.')) {
// Validação por extensão
return fileExtension ? `.${fileExtension}` === type : false;
}
else {
// Validação por MIME type
return fileType === type || (type.includes('*') && fileType.startsWith(type.replace('*', '')));
}
});
if (!isValidType) {
this.showMessage({
type: 'error',
text: this.config.messages?.fileTypeError ||
`O arquivo ${file.name} possui formato inválido`
});
return false;
}
}
// Validar tamanho do arquivo
if (this.config.maxFileSize && file.size > this.config.maxFileSize) {
this.showMessage({
type: 'error',
text: this.config.messages?.fileSizeError ||
`O arquivo ${file.name} excede o tamanho máximo permitido`
});
return false;
}
return true;
}
removeFile(file) {
const index = this.files.indexOf(file);
if (index !== -1) {
this.files.splice(index, 1);
this.filesChanged.emit(this.files);
}
}
openFile(file) {
// Abrir o arquivo em uma nova janela/guia do navegador
const url = URL.createObjectURL(file);
window.open(url, '_blank');
}
getTruncatedName(name) {
// Truncar o nome se for muito longo (por exemplo, 25 caracteres)
const maxLength = 25;
if (name.length <= maxLength) {
return name;
}
const extension = name.split('.').pop() || '';
const fileName = name.substring(0, name.length - extension.length - 1);
return `${fileName.substring(0, maxLength - extension.length - 4)}...${extension}`;
}
formatFileSize(bytes) {
if (bytes === 0)
return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
showMessage(message) {
this.message = message;
this.isInvalid = message.type === 'error';
// Limpar a mensagem após 5 segundos
setTimeout(() => {
this.message = null;
if (message.type === 'error') {
this.isInvalid = false;
}
}, 5000);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UploadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UploadComponent, selector: "cfc-upload", inputs: { config: "config", parentForm: "parentForm" }, outputs: { filesChanged: "filesChanged" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: "<div class=\"upload-container\" [formGroup]=\"parentForm\" *ngIf=\"config\">\r\n <!-- Label (opcional) -->\r\n <label *ngIf=\"config.label\" [for]=\"config.id\" class=\"upload-label\">{{ config.label }}</label>\r\n\r\n <!-- \u00C1rea de upload -->\r\n <div class=\"upload-area\" [class.dragging]=\"isDragging\" [class.invalid]=\"isInvalid\" (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\" (drop)=\"onDrop($event)\" (click)=\"openFileSelector()\">\r\n\r\n <!-- \u00CDcone de upload -->\r\n <i class=\"fa fa-upload upload-icon\"></i>\r\n\r\n <!-- Placeholder -->\r\n <span class=\"upload-placeholder\">\r\n {{ config.multiple ? 'Selecione o(s) arquivo(s)' : 'Selecione o arquivo' }}\r\n </span>\r\n\r\n <!-- Input file oculto -->\r\n <input type=\"file\" [id]=\"config.id\" class=\"file-input\" [multiple]=\"config.multiple\"\r\n [accept]=\"acceptedFileTypesString\" (change)=\"onFileSelected($event)\" #fileInput>\r\n </div>\r\n\r\n <!-- Loading durante upload -->\r\n <div *ngIf=\"uploading\" class=\"upload-loading\">\r\n <div class=\"loading-spinner\"></div>\r\n <span>Carregando...</span>\r\n </div>\r\n\r\n <!-- Mensagem de erro/sucesso -->\r\n <div *ngIf=\"message\" class=\"upload-message\" [ngClass]=\"message.type\">\r\n <i [class]=\"'fa ' + (message.type === 'error' ? 'fa-exclamation-circle' : 'fa-check-circle')\"></i>\r\n {{ message.text }}\r\n </div>\r\n\r\n <!-- Texto auxiliar -->\r\n <div *ngIf=\"config.helperText\" class=\"upload-helper-text\">\r\n {{ config.helperText }}\r\n </div>\r\n\r\n <!-- Lista de arquivos -->\r\n <div *ngIf=\"config.showFileList && files.length > 0\" class=\"file-list\">\r\n <div *ngFor=\"let file of files\" class=\"file-item\">\r\n <span class=\"file-name\" (click)=\"openFile(file)\">{{ getTruncatedName(file.name) }}</span>\r\n <span class=\"file-size\">{{ formatFileSize(file.size) }}</span>\r\n <button class=\"delete-button\" (click)=\"removeFile(file)\">\r\n <i class=\"fa fa-trash\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n</div>", styles: [".upload-container{display:flex;flex-direction:column;width:100%;font-family:Arial,sans-serif}.upload-label{margin-bottom:8px;font-size:14px;font-weight:500;color:#333}.upload-area{position:relative;display:flex;align-items:center;padding:16px;min-height:56px;border:2px dashed #ccc;border-radius:4px;background-color:#f9f9f9;cursor:pointer;transition:all .3s ease}.upload-area:hover{border-color:#999}.upload-area.dragging{border-color:#28a745;background-color:#28a7450d}.upload-area.invalid{border-color:#dc3545;background-color:#dc35450d}.upload-icon{color:#06c;margin-right:12px;font-size:20px}.upload-placeholder{color:#666;font-size:14px}.file-input{display:none}.upload-message{display:flex;align-items:center;margin-top:8px;padding:8px 12px;border-radius:4px;font-size:14px}.upload-message.success{background-color:#28a7451a;color:#28a745}.upload-message.error{background-color:#dc35451a;color:#dc3545}.upload-message.warning{background-color:#ffc1071a;color:#ffc107}.upload-message i{margin-right:8px}.upload-helper-text{margin-top:8px;font-size:12px;color:#666}.file-list{margin-top:16px;border:1px solid #eee;border-radius:4px}.file-item{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid #eee}.file-item:last-child{border-bottom:none}.file-name{color:#06c;cursor:pointer;flex-grow:1;margin-right:16px}.file-name:hover{text-decoration:underline}.file-size{color:#666;margin-right:16px}.delete-button{background:none;border:none;color:#dc3545;cursor:pointer;padding:4px;font-size:16px}.delete-button:hover{color:#bd2130}.upload-loading{display:flex;align-items:center;margin-top:12px;color:#666;font-size:14px}.loading-spinner{width:20px;height:20px;border:2px solid rgba(0,102,204,.2);border-top-color:#06c;border-radius:50%;margin-right:8px;animation:spinner .8s linear infinite}@keyframes spinner{to{transform:rotate(360deg)}}@media screen and (max-width: 768px){.file-item{flex-wrap:wrap}.file-name{width:100%;margin-bottom:8px}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.DefaultClassDirective, selector: " [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UploadComponent, decorators: [{
type: Component,
args: [{ selector: 'cfc-upload', template: "<div class=\"upload-container\" [formGroup]=\"parentForm\" *ngIf=\"config\">\r\n <!-- Label (opcional) -->\r\n <label *ngIf=\"config.label\" [for]=\"config.id\" class=\"upload-label\">{{ config.label }}</label>\r\n\r\n <!-- \u00C1rea de upload -->\r\n <div class=\"upload-area\" [class.dragging]=\"isDragging\" [class.invalid]=\"isInvalid\" (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\" (drop)=\"onDrop($event)\" (click)=\"openFileSelector()\">\r\n\r\n <!-- \u00CDcone de upload -->\r\n <i class=\"fa fa-upload upload-icon\"></i>\r\n\r\n <!-- Placeholder -->\r\n <span class=\"upload-placeholder\">\r\n {{ config.multiple ? 'Selecione o(s) arquivo(s)' : 'Selecione o arquivo' }}\r\n </span>\r\n\r\n <!-- Input file oculto -->\r\n <input type=\"file\" [id]=\"config.id\" class=\"file-input\" [multiple]=\"config.multiple\"\r\n [accept]=\"acceptedFileTypesString\" (change)=\"onFileSelected($event)\" #fileInput>\r\n </div>\r\n\r\n <!-- Loading durante upload -->\r\n <div *ngIf=\"uploading\" class=\"upload-loading\">\r\n <div class=\"loading-spinner\"></div>\r\n <span>Carregando...</span>\r\n </div>\r\n\r\n <!-- Mensagem de erro/sucesso -->\r\n <div *ngIf=\"message\" class=\"upload-message\" [ngClass]=\"message.type\">\r\n <i [class]=\"'fa ' + (message.type === 'error' ? 'fa-exclamation-circle' : 'fa-check-circle')\"></i>\r\n {{ message.text }}\r\n </div>\r\n\r\n <!-- Texto auxiliar -->\r\n <div *ngIf=\"config.helperText\" class=\"upload-helper-text\">\r\n {{ config.helperText }}\r\n </div>\r\n\r\n <!-- Lista de arquivos -->\r\n <div *ngIf=\"config.showFileList && files.length > 0\" class=\"file-list\">\r\n <div *ngFor=\"let file of files\" class=\"file-item\">\r\n <span class=\"file-name\" (click)=\"openFile(file)\">{{ getTruncatedName(file.name) }}</span>\r\n <span class=\"file-size\">{{ formatFileSize(file.size) }}</span>\r\n <button class=\"delete-button\" (click)=\"removeFile(file)\">\r\n <i class=\"fa fa-trash\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n</div>", styles: [".upload-container{display:flex;flex-direction:column;width:100%;font-family:Arial,sans-serif}.upload-label{margin-bottom:8px;font-size:14px;font-weight:500;color:#333}.upload-area{position:relative;display:flex;align-items:center;padding:16px;min-height:56px;border:2px dashed #ccc;border-radius:4px;background-color:#f9f9f9;cursor:pointer;transition:all .3s ease}.upload-area:hover{border-color:#999}.upload-area.dragging{border-color:#28a745;background-color:#28a7450d}.upload-area.invalid{border-color:#dc3545;background-color:#dc35450d}.upload-icon{color:#06c;margin-right:12px;font-size:20px}.upload-placeholder{color:#666;font-size:14px}.file-input{display:none}.upload-message{display:flex;align-items:center;margin-top:8px;padding:8px 12px;border-radius:4px;font-size:14px}.upload-message.success{background-color:#28a7451a;color:#28a745}.upload-message.error{background-color:#dc35451a;color:#dc3545}.upload-message.warning{background-color:#ffc1071a;color:#ffc107}.upload-message i{margin-right:8px}.upload-helper-text{margin-top:8px;font-size:12px;color:#666}.file-list{margin-top:16px;border:1px solid #eee;border-radius:4px}.file-item{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid #eee}.file-item:last-child{border-bottom:none}.file-name{color:#06c;cursor:pointer;flex-grow:1;margin-right:16px}.file-name:hover{text-decoration:underline}.file-size{color:#666;margin-right:16px}.delete-button{background:none;border:none;color:#dc3545;cursor:pointer;padding:4px;font-size:16px}.delete-button:hover{color:#bd2130}.upload-loading{display:flex;align-items:center;margin-top:12px;color:#666;font-size:14px}.loading-spinner{width:20px;height:20px;border:2px solid rgba(0,102,204,.2);border-top-color:#06c;border-radius:50%;margin-right:8px;animation:spinner .8s linear infinite}@keyframes spinner{to{transform:rotate(360deg)}}@media screen and (max-width: 768px){.file-item{flex-wrap:wrap}.file-name{width:100%;margin-bottom:8px}}\n"] }]
}], ctorParameters: () => [], propDecorators: { config: [{
type: Input
}], parentForm: [{
type: Input
}], filesChanged: [{
type: Output
}], fileInput: [{
type: ViewChild,
args: ['fileInput']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NmYy1kcy9zcmMvbGliL2NvbXBvbmVudHMvdXBsb2FkL3VwbG9hZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jZmMtZHMvc3JjL2xpYi9jb21wb25lbnRzL3VwbG9hZC91cGxvYWQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBUUksT0FBTyxFQUFFLFNBQVMsRUFBYyxZQUFZLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7Ozs7O0FBZ0M5RixNQUFNLE9BQU8sZUFBZTtJQUNqQixNQUFNLENBQWdCO0lBQ3RCLFVBQVUsQ0FBYTtJQUN0QixZQUFZLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztJQUU1QixTQUFTLENBQWM7SUFFL0MsS0FBSyxHQUFXLEVBQUUsQ0FBQztJQUNuQixVQUFVLEdBQUcsS0FBSyxDQUFDO0lBQ25CLFNBQVMsR0FBRyxLQUFLLENBQUM7SUFDbEIsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUNsQixPQUFPLEdBQXVCLElBQUksQ0FBQztJQUVuQyxJQUFJLHVCQUF1QjtRQUN6QixPQUFPLElBQUksQ0FBQyxNQUFNLEVBQUUsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN6RCxDQUFDO0lBRUQsZ0JBQWdCLENBQUM7SUFFakIsUUFBUTtRQUNOLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDakIsT0FBTyxDQUFDLEtBQUssQ0FBQyxtREFBbUQsQ0FBQyxDQUFDO1FBQ3JFLENBQUM7SUFDSCxDQUFDO0lBRUQsZ0JBQWdCO1FBQ2QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDdkMsQ0FBQztJQUVELFVB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WUFDZCxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztZQUNwQixJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssT0FBTyxFQUFFLENBQUM7Z0JBQzdCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1lBQ3pCLENBQUM7UUFDSCxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDWCxDQUFDO3dHQTlQVSxlQUFlOzRGQUFmLGVBQWUsNlBDeENoQyw2c0VBZ0RNOzs0RkRSVyxlQUFlO2tCQUwzQixTQUFTOytCQUNFLFlBQVk7d0RBS2IsTUFBTTtzQkFBZCxLQUFLO2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0ksWUFBWTtzQkFBckIsTUFBTTtnQkFFaUIsU0FBUztzQkFBaEMsU0FBUzt1QkFBQyxXQUFXIiwic291cmNlc0NvbnRlbnQiOlsiXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcbiAgICBcclxuICAgIGltcG9ydCB7IENvbXBvbmVudCwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT3V0cHV0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuICAgIGltcG9ydCB7IEZvcm1Hcm91cCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuICAgIFxyXG4gICAgZXhwb3J0IGludGVyZmFjZSBVcGxvYWRDb25maWcge1xyXG4gICAgICBpZDogc3RyaW5nO1xyXG4gICAgICBsYWJlbD86IHN0cmluZztcclxuICAgICAgbXVsdGlwbGU6IGJvb2xlYW47XHJcbiAgICAgIGFjY2VwdGVkRmlsZVR5cGVzPzogc3RyaW5nW107XHJcbiAgICAgIG1heEZpbGVTaXplPzogbnVtYmVyOyAvLyBlbSBieXRlc1xyXG4gICAgICBoZWxwZXJUZXh0Pzogc3RyaW5nO1xyXG4gICAgICByZXF1aXJlZD86IGJvb2xlYW47XHJcbiAgICAgIG1heEZpbGVzPzogbnVtYmVyO1xyXG4gICAgICBzaG93RmlsZUxpc3Q/OiBib29sZWFuO1xyXG4gICAgICBtZXNzYWdlcz86IHtcclxuICAgICAgICBzdWNjZXNzPzogc3RyaW5nO1xyXG4gICAgICAgIGVycm9yPzogc3RyaW5nO1xyXG4gICAgICAgIGZpbGVUeXBlRXJyb3I/OiBzdHJpbmc7XHJcbiAgICAgICAgZmlsZVNpemVFcnJvcj86IHN0cmluZztcclxuICAgICAgICBtYXhGaWxlc0Vycm9yPzogc3RyaW5nO1xyXG4gICAgICB9O1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICBpbnRlcmZhY2UgRmlsZU1lc3NhZ2Uge1xyXG4gICAgICB0eXBlOiAnc3VjY2VzcycgfCAnZXJyb3InIHwgJ3dhcm5pbmcnO1xyXG4gICAgICB0ZXh0OiBzdHJpbmc7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIEBDb21wb25lbnQoe1xyXG4gICAgICBzZWxlY3RvcjogJ2NmYy11cGxvYWQnLFxyXG4gICAgICB0ZW1wbGF0ZVVybDogJy4vdXBsb2FkLmNvbXBvbmVudC5odG1sJyxcclxuICAgICAgc3R5bGVVcmw6ICcuL3VwbG9hZC5jb21wb25lbnQuc2NzcydcclxuICAgIH0pXHJcbiAgICBleHBvcnQgY2xhc3MgVXBsb2FkQ29tcG9uZW50IHtcclxuICAgICAgQElucHV0KCkgY29uZmlnITogVXBsb2FkQ29uZmlnO1xyXG4gICAgICBASW5wdXQoKSBwYXJlbnRGb3JtITogRm9ybUdyb3VwO1xyXG4gICAgICBAT3V0cHV0KCkgZmlsZXNDaGFuZ2VkID0gbmV3IEV2ZW50RW1pdHRlcjxGaWxlW10+KCk7XHJcbiAgICAgIFxyXG4gICAgICBAVmlld0NoaWxkKCdmaWxlSW5wdXQnKSBmaWxlSW5wdXQhOiBFbGVtZW50UmVmO1xyXG4gICAgICBcclxuICAgICAgZmlsZXM6IEZpbGVbXSA9IFtdO1xyXG4gICAgICBpc0RyYWdnaW5nID0gZmFsc2U7XHJcbiAgICAgIGlzSW52YWxpZCA9IGZhbHNlO1xyXG4gICAgICB1cGxvYWRpbmcgPSBmYWxzZTtcclxuICAgICAgbWVzc2FnZTogRmlsZU1lc3NhZ2UgfCBudWxsID0gbnVsbDtcclxuICAgICAgXHJcbiAgICAgIGdldCBhY2NlcHRlZEZpbGVUeXBlc1N0cmluZygpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmNvbmZpZz8uYWNjZXB0ZWRGaWxlVHlwZXM/LmpvaW4oJywnKSB8fCAnJztcclxuICAgICAgfVxyXG4gICAgICBcclxuICAgICAgY29uc3RydWN0b3IoKSB7IH1cclxuICAgICAgXHJcbiAgICAgIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgICAgIGlmICghdGhpcy5jb25maWcpIHtcclxuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0EgY29uZmlndXJhw6fDo28gZG8gY29tcG9uZW50ZSBVcGxvYWQgw6kgb2JyaWdhdMOzcmlhJyk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIFxyXG4gICAgICBvcGVuRmlsZVNlbGVjdG9yKCk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuZmlsZUlucHV0Lm5hdGl2ZUVsZW1lbnQuY2xpY2soKTtcclxuICAgICAgfVxyXG4gICAgICBcclxuICAgICAgb25EcmFnT3ZlcihldmVudDogRHJhZ0V2ZW50KTogdm9pZCB7XHJcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgICB0aGlzLmlzRHJhZ2dpbmcgPSB0cnVlO1xyXG4gICAgICB9XHJcbiAgICAgIFxyXG4gICAgICBvbkRyYWdMZWF2ZShldmVudDogRHJhZ0V2ZW50KTogdm9pZCB7XHJcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgICB0aGlzLmlzRHJhZ2dpbmcgPSBmYWxzZTtcclxuICAgICAgfVxyXG4gICAgICBcclxuICAgICAgb25Ecm9wKGV2ZW50OiBEcmFnRXZlbnQpOiB2b2lkIHtcclxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgIHRoaXMuaXNEcmFnZ2luZyA9IGZhbHNlO1xyXG4gICAgICAgIFxyXG4gICAgICAgIGlmIChldmVudC5kYXRhVHJhbnNmZXI/LmZpbGVzKSB7XHJcbiAgICAgICAgICB0aGlzLmhhbmRsZUZpbGVzKGV2ZW50LmRhdGFUcmFuc2Zlci5maWxlcyk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIFxyXG4gICAgICBvbkZpbGVTZWxlY3RlZChldmVudDogRXZlbnQpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBpbnB1dCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50O1xyXG4gICAgICAgIGlmIChpbnB1dC5maWxlcykge1xyXG4gICAgICAgICAgdGhpcy5oYW5kbGVGaWxlcyhpbnB1dC5maWxlcyk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIFxyXG4gICAgICBoYW5kbGVGaWxlcyhmaWxlTGlzdDogRmlsZUxpc3QpOiB2b2lkIHtcclxuICAgICAgICBpZiAoIXRoaXMuY29uZmlnKSByZXR1cm47XHJcbiAgICAgICAgXHJcbiAgICAgICAgLy8gVmVyaWZpY2FyIHNlIMOpIHBlcm1pdGlkbyBtw7psdGlwbG9zIGFycXVpdm9zXHJcbiAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5tdWx0aXBsZSAmJiBmaWxlTGlzdC5sZW5ndGggPiAxKSB7XHJcbiAgICAgICAgICB0aGlzLnNob3dNZXNzYWdlKHtcclxuICAgICAgICAgICAgdHlwZTogJ2Vycm9yJyxcclxuICAgICAgICAgICAgdGV4dDogdGhpcy5jb25maWcubWVzc2FnZXM/LmVycm9yIHx8ICfDiSBwZXJtaXRpZG8gbyBlbnZpbyBkZSBhcGVuYXMgdW0gYXJxdWl2bydcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAvLyBWZXJpZmljYXIgbsO6bWVybyBtw6F4aW1vIGRlIGFycXVpdm9zXHJcbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLm1heEZpbGVzICYmIHRoaXMuZmlsZXMubGVuZ3RoICsgZmlsZUxpc3QubGVuZ3RoID4gdGhpcy5jb25maWcubWF4RmlsZXMpIHtcclxuICAgICAgICAgIHRoaXMuc2hvd01lc3NhZ2Uoe1xyXG4gICAgICAgICAgICB0eXBlOiAnZXJyb3InLFxyXG4gICAgICAgICAgICB0ZXh0OiB0aGlzLmNvbmZpZy5tZXNzYWdlcz8ubWF4RmlsZXNFcnJvciB8fCBcclxuICAgICAgICAgICAgICAgICAgYMOJIHBlcm1pdGlkbyBvIGVudmlvIGRlIG5vIG3DoXhpbW8gJHt0aGlzLmNvbmZpZy5tYXhGaWxlc30gYXJxdWl2b3NgXHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgXHJcbiAgICAgICAgLy8gVmFsaWRhciBlIHByb2Nlc3NhciBjYWRhIGFycXVpdm9cclxuICAgICAgICBjb25zdCBuZXdGaWxlczogRmlsZVtdID0gW107XHJcbiAgICAgICAgbGV0IGhhc0ludmFsaWRGaWxlcyA9IGZhbHNlO1xyXG4gICAgICAgIFxyXG4gICAgICAgIHRoaXMudXBsb2FkaW5nID0gdHJ1ZTtcclxuICAgICAgICBcclxuICAgICAgICAvLyBBcnJheSBwYXJhIGFybWF6ZW5hciBwcm9tZXNzYXMgZGUgcHJvY2Vzc2FtZW50byBkZSBhcnF1aXZvc1xyXG4gICAgICAgIGNvbnN0IGZpbGVQcm9jZXNzaW5nUHJvbWlzZXM6IFByb21pc2U8dm9pZD5bXSA9IFtdO1xyXG4gICAgICBcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZpbGVMaXN0Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICBjb25zdCBmaWxlID0gZmlsZUxpc3RbaV07XHJcbiAgICAgICAgICBjb25zdCBpc1ZhbGlkID0gdGhpcy52YWxpZGF0ZUZpbGUoZmlsZSk7XHJcbiAgICAgICAgICBcclxuICAgICAgICAgIGlmIChpc1ZhbGlkKSB7XHJcbiAgICAgICAgICAgIC8vIENyaWFyIHVtYSBwcm9tZXNzYSBwYXJhIGNhZGEgYXJxdWl2b1xyXG4gICAgICAgICAgICBjb25zdCBmaWxlUHJvbWlzZSA9IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiB7XHJcbiAgICAgICAgICAgICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcclxuICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICByZWFkZXIub25sb2FkID0gKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgLy8gTyBhcnF1aXZvIGZvaSBsaWRvIGNvbXBsZXRhbWVudGVcclxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5jb25maWcubXVsdGlwbGUpIHtcclxuICAgICAgICAgICAgICAgICAgLy8gU2UgbsOjbyBwZXJtaXRlIG3Dumx0aXBsb3MgYXJxdWl2b3MsIHN1YnN0aXR1aSBvIGFycXVpdm8gZXhpc3RlbnRlXHJcbiAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmZpbGVzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNob3dNZXNzYWdlKHtcclxuICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICd3YXJuaW5nJyxcclxuICAgICAgICAgICAgICAgICAgICAgIHRleHQ6ICdPIGFycXVpdm8gZW52aWFkbyBhbnRlcmlvcm1lbnRlIGZvaSBzdWJzdGl0dcOtZG8nXHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maWxlcyA9IFtmaWxlXTtcclxuICAgICAgICAgICAgICAgICAgICBuZXdGaWxlcy5wdXNoKGZpbGUpO1xyXG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsZXMucHVzaChmaWxlKTtcclxuICAgICAgICAgICAgICAgICAgICBuZXdGaWxlcy5wdXNoKGZpbGUpO1xyXG4gICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLmZpbGVzLnB1c2goZmlsZSk7XHJcbiAgICAgICAgICAgICAgICAgIG5ld0ZpbGVzLnB1c2goZmlsZSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XHJcbiAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAvLyBFbSBjYXNvIGRlIGVycm8gbmEgbGVpdHVyYVxyXG4gICAgICAgICAgICAgIHJlYWRlci5vbmVycm9yID0gKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaGFzSW52YWxpZEZpbGVzID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIHRoaXMuc2hvd01lc3NhZ2Uoe1xyXG4gICAgICAgICAgICAgICAgICB0eXBlOiAnZXJyb3InLFxyXG4gICAgICAgICAgICAgICAgICB0ZXh0OiBgRXJybyBhbyBwcm9jZXNzYXIgbyBhcnF1aXZvICR7ZmlsZS5uYW1lfWBcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xyXG4gICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgLy8gSW5pY2lhIGEgbGVpdHVyYSBkbyBhcnF1aXZvXHJcbiAgICAgICAgICAgICAgcmVhZGVyLnJlYWRBc0FycmF5QnVmZmVyKGZpbGUpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIGZpbGVQcm9jZXNzaW5nUHJvbWlzZXMucHVzaChmaWxlUHJvbWlzZSk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBoYXNJbnZhbGlkRmlsZXMgPSB0cnVlO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAvLyBBZ3VhcmRhciBvIHByb2Nlc3NhbWVudG8gZGUgdG9kb3Mgb3MgYXJxdWl2b3NcclxuICAgICAgICBQcm9taXNlLmFsbChmaWxlUHJvY2Vzc2luZ1Byb21pc2VzKVxyXG4gICAgICAgICAgLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLnVwbG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgaWYgKG5ld0ZpbGVzLmxlbmd0aCA+IDAgJiYgIWhhc0ludmFsaWRGaWxlcykge1xyXG4gICAgICAgICAgICAgIHRoaXMuc2hvd01lc3NhZ2Uoe1xyXG4gICAgICAgICAgICAgICAgdHlwZTogJ3N1Y2Nlc3MnLFxyXG4gICAgICAgICAgICAgICAgdGV4dDogdGhpcy5jb25maWc/Lm1lc3NhZ2VzPy5zdWNjZXNzIHx8ICdDYW1wbyBwcmVlbmNoaWRvIGNvcnJldGFtZW50ZSdcclxuICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgdGhpcy5maWxlc0NoYW5nZWQuZW1pdCh0aGlzLmZpbGVzKTtcclxuICAgICAgICAgIH0pXHJcbiAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLnVwbG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICB0aGlzLnNob3dNZXNzYWdlKHtcclxuICAgICAgICAgICAgICB0eXBlOiAnZXJyb3InLFxyXG4gICAgICAgICAgICAgIHRleHQ6ICdFcnJvIG5vIHByb2Nlc3NhbWVudG8gZG9zIGFycXVpdm9zJ1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRmlsZSBwcm9jZXNzaW5nIGVycm9yOicsIGVycm9yKTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICB9XHJcbiAgICAgIFxyXG4gICAgICB2YWxpZGF0ZUZpbGUoZmlsZTogRmlsZSk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGlmICghdGhpcy5jb25maWcpIHJldHVybiBmYWxzZTtcclxuICAgICAgICBcclxuICAgICAgICAvLyBWYWxpZGFyIHRpcG8gZGUgYXJxdWl2b1xyXG4gICAgICAgIGlmICh0aGlzLmNvbmZpZy5hY2NlcHRlZEZpbGVUeXBlcyAmJiB0aGlzLmNvbmZpZy5hY2NlcHRlZEZpbGVUeXBlcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICBjb25zdCBmaWxlTmFtZVBhcnRzID0gZmlsZS5uYW1lLnNwbGl0KCcuJyk7XHJcbiAgICAgICAgICBjb25zdCBmaWxlRXh0ZW5zaW9uID0gZmlsZU5hbWVQYXJ0cy5sZW5ndGggPiAxID8gZmlsZU5hbWVQYXJ0cy5wb3AoKT8udG9Mb3dlckNhc2UoKSA6ICcnO1xyXG4gICAgICAgICAgY29uc3QgZmlsZVR5cGUgPSBmaWxlLnR5cGU7XHJcbiAgICAgICAgICBcclxuICAgICAgICAgIGNvbnN0IGlzVmFsaWRUeXBlID0gdGhpcy5jb25maWcuYWNjZXB0ZWRGaWxlVHlwZXMuc29tZSh0eXBlID0+IHtcclxuICAgICAgICAgICAgaWYgKHR5cGUuc3RhcnRzV2l0aCgnLicpKSB7XHJcbiAgICAgICAgICAgICAgLy8gVmFsaWRhw6fDo28gcG9yIGV4dGVuc8Ojb1xyXG4gICAgICAgICAgICAgIHJldHVybiBmaWxlRXh0ZW5zaW9uID8gYC4ke2ZpbGVFeHRlbnNpb259YCA9PT0gdHlwZSA6IGZhbHNlO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIC8vIFZhbGlkYcOnw6NvIHBvciBNSU1FIHR5cGVcclxuICAgICAgICAgICAgICByZXR1cm4gZmlsZVR5cGUgPT09IHR5cGUgfHwgKHR5cGUuaW5jbHVkZXMoJyonKSAmJiBmaWxlVHlwZS5zdGFydHNXaXRoKHR5cGUucmVwbGFjZSgnKicsICcnKSkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICAgIFxyXG4gICAgICAgICAgaWYgKCFpc1ZhbGlkVHlwZSkge1xyXG4gICAgICAgICAgICB0aGlzLnNob3dNZXNzYWdlKHtcclxuICAgICAgICAgICAgICB0eXBlOiAnZXJyb3InLFxyXG4gICAgICAgICAgICAgIHRleHQ6IHRoaXMuY29uZmlnLm1lc3NhZ2VzPy5maWxlVHlwZUVycm9yIHx8IFxyXG4gICAgICAgICAgICAgICAgICAgIGBPIGFycXVpdm8gJHtmaWxlLm5hbWV9IHBvc3N1aSBmb3JtYXRvIGludsOhbGlkb2BcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgXHJcbiAgICAgICAgLy8gVmFsaWRhciB0YW1hbmhvIGRvIGFycXVpdm9cclxuICAgICAgICBpZiAodGhpcy5jb25maWcubWF4RmlsZVNpemUgJiYgZmlsZS5zaXplID4gdGhpcy5jb25maWcubWF4RmlsZVNpemUpIHtcclxuICAgICAgICAgIHRoaXMuc2hvd01lc3NhZ2Uoe1xyXG4gICAgICAgICAgICB0eXBlOiAnZXJyb3InLFxyXG4gICAgICAgICAgICB0ZXh0OiB0aGlzLmNvbmZpZy5tZXNzYWdlcz8uZmlsZVNpemVFcnJvciB8fCBcclxuICAgICAgICAgICAgICAgICAgYE8gYXJxdWl2byAke2ZpbGUubmFtZX0gZXhjZWRlIG8gdGFtYW5obyBtw6F4aW1vIHBlcm1pdGlkb2BcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgfVxyXG4gICAgICBcclxuICAgICAgcmVtb3ZlRmlsZShmaWxlOiBGaWxlKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLmZpbGVzLmluZGV4T2YoZmlsZSk7XHJcbiAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xyXG4gICAgICAgICAgdGhpcy5maWxlcy5zcGxpY2UoaW5kZXgsIDEpO1xyXG4gICAgICAgICAgdGhpcy5maWxlc0NoYW5nZWQuZW1pdCh0aGlzLmZpbGVzKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgXHJcbiAgICAgIG9wZW5GaWxlKGZpbGU6IEZpbGUpOiB2b2lkIHtcclxuICAgICAgICAvLyBBYnJpciBvIGFycXVpdm8gZW0gdW1hIG5vdmEgamFuZWxhL2d1aWEgZG8gbmF2ZWdhZG9yXHJcbiAgICAgICAgY29uc3QgdXJsID0gVVJMLmNyZWF0ZU9iamVjdFVSTChmaWxlKTtcclxuICAgICAgICB3aW5kb3cub3Blbih1cmwsICdfYmxhbmsnKTtcclxuICAgICAgfVxyXG4gICAgICBcclxuICAgICAgZ2V0VHJ1bmNhdGVkTmFtZShuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIC8vIFRydW5jYXIgbyBub21lIHNlIGZvciBtdWl0byBsb25nbyAocG9yIGV4ZW1wbG8sIDI1IGNhcmFjdGVyZXMpXHJcbiAgICAgICAgY29uc3QgbWF4TGVuZ3RoID0gMjU7XHJcbiAgICAgICAgaWYgKG5hbWUubGVuZ3RoIDw9IG1heExlbmd0aCkge1xyXG4gICAgICAgICAgcmV0dXJuIG5hbWU7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIFxyXG4gICAgICAgIGNvbnN0IGV4dGVuc2lvbiA9IG5hbWUuc3BsaXQoJy4nKS5wb3AoKSB8fCAnJztcclxuICAgICAgICBjb25zdCBmaWxlTmFtZSA9IG5hbWUuc3Vic3RyaW5nKDAsIG5hbWUubGVuZ3RoIC0gZXh0ZW5zaW9uLmxlbmd0aCAtIDEpO1xyXG4gICAgICAgIFxyXG4gICAgICAgIHJldHVybiBgJHtmaWxlTmFtZS5zdWJzdHJpbmcoMCwgbWF4TGVuZ3RoIC0gZXh0ZW5zaW9uLmxlbmd0aCAtIDQpfS4uLiR7ZXh0ZW5zaW9ufWA7XHJcbiAgICAgIH1cclxuICAgICAgXHJcbiAgICAgIGZvcm1hdEZpbGVTaXplKGJ5dGVzOiBudW1iZXIpOiBzdHJpbmcge1xyXG4gICAgICAgIGlmIChieXRlcyA9PT0gMCkgcmV0dXJuICcwIEInO1xyXG4gICAgICAgIFxyXG4gICAgICAgIGNvbnN0IGsgPSAxMDI0O1xyXG4gICAgICAgIGNvbnN0IHNpemVzID0gWydCJywgJ0tCJywgJ01CJywgJ0dCJ107XHJcbiAgICAgICAgY29uc3QgaSA9IE1hdGguZmxvb3IoTWF0aC5sb2coYnl0ZXMpIC8gTWF0aC5sb2coaykpO1xyXG4gICAgICAgIFxyXG4gICAgICAgIHJldHVybiBwYXJzZUZsb2F0KChieXRlcyAvIE1hdGgucG93KGssIGkpKS50b0ZpeGVkKDIpKSArICcgJyArIHNpemVzW2ldO1xyXG4gICAgICB9XHJcbiAgICAgIFxyXG4gICAgICBzaG93TWVzc2FnZShtZXNzYWdlOiBGaWxlTWVzc2FnZSk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XHJcbiAgICAgICAgdGhpcy5pc0ludmFsaWQgPSBtZXNzYWdlLnR5cGUgPT09ICdlcnJvcic7XHJcbiAgICAgICAgXHJcbiAgICAgICAgLy8gTGltcGFyIGEgbWVuc2FnZW0gYXDDs3MgNSBzZWd1bmRvc1xyXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5tZXNzYWdlID0gbnVsbDtcclxuICAgICAgICAgIGlmIChtZXNzYWdlLnR5cGUgPT09ICdlcnJvcicpIHtcclxuICAgICAgICAgICAgdGhpcy5pc0ludmFsaWQgPSBmYWxzZTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9LCA1MDAwKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgIiwiPGRpdiBjbGFzcz1cInVwbG9hZC1jb250YWluZXJcIiBbZm9ybUdyb3VwXT1cInBhcmVudEZvcm1cIiAqbmdJZj1cImNvbmZpZ1wiPlxyXG4gICAgPCEtLSBMYWJlbCAob3BjaW9uYWwpIC0tPlxyXG4gICAgPGxhYmVsICpuZ0lmPVwiY29uZmlnLmxhYmVsXCIgW2Zvcl09XCJjb25maWcuaWRcIiBjbGFzcz1cInVwbG9hZC1sYWJlbFwiPnt7IGNvbmZpZy5sYWJlbCB9fTwvbGFiZWw+XHJcblxyXG4gICAgPCEtLSDDgXJlYSBkZSB1cGxvYWQgLS0+XHJcbiAgICA8ZGl2IGNsYXNzPVwidXBsb2FkLWFyZWFcIiBbY2xhc3MuZHJhZ2dpbmddPVwiaXNEcmFnZ2luZ1wiIFtjbGFzcy5pbnZhbGlkXT1cImlzSW52YWxpZFwiIChkcmFnb3Zlcik9XCJvbkRyYWdPdmVyKCRldmVudClcIlxyXG4gICAgICAgIChkcmFnbGVhdmUpPVwib25EcmFnTGVhdmUoJGV2ZW50KVwiIChkcm9wKT1cIm9uRHJvcCgkZXZlbnQpXCIgKGNsaWNrKT1cIm9wZW5GaWxlU2VsZWN0b3IoKVwiPlxyXG5cclxuICAgICAgICA8IS0tIMONY29uZSBkZSB1cGxvYWQgLS0+XHJcbiAgICAgICAgPGkgY2xhc3M9XCJmYSBmYS11cGxvYWQgdXBsb2FkLWljb25cIj48L2k+XHJcblxyXG4gICAgICAgIDwhLS0gUGxhY2Vob2xkZXIgLS0+XHJcbiAgICAgICAgPHNwYW4gY2xhc3M9XCJ1cGxvYWQtcGxhY2Vob2xkZXJcIj5cclxuICAgICAgICAgICAge3sgY29uZmlnLm11bHRpcGxlID8gJ1NlbGVjaW9uZSBvKHMpIGFycXVpdm8ocyknIDogJ1NlbGVjaW9uZSBvIGFycXVpdm8nIH19XHJcbiAgICAgICAgPC9zcGFuPlxyXG5cclxuICAgICAgICA8IS0tIElucHV0IGZpbGUgb2N1bHRvIC0tPlxyXG4gICAgICAgIDxpbnB1dCB0eXBlPVwiZmlsZVwiIFtpZF09XCJjb25maWcuaWRcIiBjbGFzcz1cImZpbGUtaW5wdXRcIiBbbXVsdGlwbGVdPVwiY29uZmlnLm11bHRpcGxlXCJcclxuICAgICAgICAgICAgW2FjY2VwdF09XCJhY2NlcHRlZEZpbGVUeXBlc1N0cmluZ1wiIChjaGFuZ2UpPVwib25GaWxlU2VsZWN0ZWQoJGV2ZW50KVwiICNmaWxlSW5wdXQ+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8IS0tIExvYWRpbmcgZHVyYW50ZSB1cGxvYWQgLS0+XHJcbiAgICA8ZGl2ICpuZ0lmPVwidXBsb2FkaW5nXCIgY2xhc3M9XCJ1cGxvYWQtbG9hZGluZ1wiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJsb2FkaW5nLXNwaW5uZXJcIj48L2Rpdj5cclxuICAgICAgICA8c3Bhbj5DYXJyZWdhbmRvLi4uPC9zcGFuPlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPCEtLSBNZW5zYWdlbSBkZSBlcnJvL3N1Y2Vzc28gLS0+XHJcbiAgICA8ZGl2ICpuZ0lmPVwibWVzc2FnZVwiIGNsYXNzPVwidXBsb2FkLW1lc3NhZ2VcIiBbbmdDbGFzc109XCJtZXNzYWdlLnR5cGVcIj5cclxuICAgICAgICA8aSBbY2xhc3NdPVwiJ2ZhICcgKyAobWVzc2FnZS50eXBlID09PSAnZXJyb3InID8gJ2ZhLWV4Y2xhbWF0aW9uLWNpcmNsZScgOiAnZmEtY2hlY2stY2lyY2xlJylcIj48L2k+XHJcbiAgICAgICAge3sgbWVzc2FnZS50ZXh0IH19XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8IS0tIFRleHRvIGF1eGlsaWFyIC0tPlxyXG4gICAgPGRpdiAqbmdJZj1cImNvbmZpZy5oZWxwZXJUZXh0XCIgY2xhc3M9XCJ1cGxvYWQtaGVscGVyLXRleHRcIj5cclxuICAgICAgICB7eyBjb25maWcuaGVscGVyVGV4dCB9fVxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPCEtLSBMaXN0YSBkZSBhcnF1aXZvcyAtLT5cclxuICAgIDxkaXYgKm5nSWY9XCJjb25maWcuc2hvd0ZpbGVMaXN0ICYmIGZpbGVzLmxlbmd0aCA+IDBcIiBjbGFzcz1cImZpbGUtbGlzdFwiPlxyXG4gICAgICAgIDxkaXYgKm5nRm9yPVwibGV0IGZpbGUgb2YgZmlsZXNcIiBjbGFzcz1cImZpbGUtaXRlbVwiPlxyXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImZpbGUtbmFtZVwiIChjbGljayk9XCJvcGVuRmlsZShmaWxlKVwiPnt7IGdldFRydW5jYXRlZE5hbWUoZmlsZS5uYW1lKSB9fTwvc3Bhbj5cclxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJmaWxlLXNpemVcIj57eyBmb3JtYXRGaWxlU2l6ZShmaWxlLnNpemUpIH19PC9zcGFuPlxyXG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiZGVsZXRlLWJ1dHRvblwiIChjbGljayk9XCJyZW1vdmVGaWxlKGZpbGUpXCI+XHJcbiAgICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhIGZhLXRyYXNoXCI+PC9pPlxyXG4gICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG48L2Rpdj4iXX0=