lib-portal-angular 0.0.87 → 0.0.89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/esm2022/lib/components/components.module.mjs +65 -40
  2. package/esm2022/lib/components/csv-importer/csv-importer.component.mjs +92 -0
  3. package/esm2022/lib/components/data-excel-exporter/IExcelExportConfig.mjs +2 -0
  4. package/esm2022/lib/components/data-excel-exporter/data-excel-exporter.component.mjs +126 -0
  5. package/esm2022/lib/components/data-excel-import/data-excel-importer.component.mjs +198 -0
  6. package/esm2022/lib/components/multi-select/multi-select.component.mjs +165 -115
  7. package/esm2022/lib/components/pdf-data-handler/argenta-pdf-data-handler.component.mjs +147 -0
  8. package/esm2022/lib/components/pdf-data-handler/function/formatToBrazilianNumber.mjs +7 -0
  9. package/esm2022/lib/components/pdf-data-handler/function/parseBrazilianNumber.mjs +9 -0
  10. package/esm2022/lib/components/pdf-data-handler/interface/DataRow.mjs +2 -0
  11. package/esm2022/lib/components/pdf-data-handler/interface/PdfExportConfig.mjs +2 -0
  12. package/esm2022/lib/components/pdf-data-handler/interface/PdfTableStyles.mjs +2 -0
  13. package/esm2022/lib/components/pdf-data-handler/interface/RowCalculation.mjs +2 -0
  14. package/esm2022/lib/components/pdf-data-handler/interface/TotalizerConfig.mjs +2 -0
  15. package/esm2022/lib/components/pdf-download/argenta-pdf-download.component.mjs +51 -0
  16. package/esm2022/public-api.mjs +36 -5
  17. package/fesm2022/lib-portal-angular.mjs +1095 -422
  18. package/fesm2022/lib-portal-angular.mjs.map +1 -1
  19. package/lib/components/components.module.d.ts +10 -5
  20. package/lib/components/csv-importer/csv-importer.component.d.ts +19 -0
  21. package/lib/components/data-excel-exporter/IExcelExportConfig.d.ts +21 -0
  22. package/lib/components/data-excel-exporter/data-excel-exporter.component.d.ts +9 -0
  23. package/lib/components/data-excel-import/data-excel-importer.component.d.ts +44 -0
  24. package/lib/components/multi-select/multi-select.component.d.ts +20 -9
  25. package/lib/components/pdf-data-handler/argenta-pdf-data-handler.component.d.ts +15 -0
  26. package/lib/components/pdf-data-handler/function/formatToBrazilianNumber.d.ts +1 -0
  27. package/lib/components/pdf-data-handler/function/parseBrazilianNumber.d.ts +1 -0
  28. package/lib/components/pdf-data-handler/interface/DataRow.d.ts +3 -0
  29. package/lib/components/pdf-data-handler/interface/PdfExportConfig.d.ts +12 -0
  30. package/lib/components/pdf-data-handler/interface/PdfTableStyles.d.ts +28 -0
  31. package/lib/components/pdf-data-handler/interface/RowCalculation.d.ts +4 -0
  32. package/lib/components/pdf-data-handler/interface/TotalizerConfig.d.ts +8 -0
  33. package/lib/components/pdf-download/argenta-pdf-download.component.d.ts +13 -0
  34. package/package.json +1 -1
  35. package/public-api.d.ts +34 -3
@@ -0,0 +1,198 @@
1
+ import { Component, EventEmitter, Output } from "@angular/core";
2
+ import * as XLSX from "xlsx";
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "@angular/common";
5
+ import * as i2 from "@angular/forms";
6
+ import * as i3 from "lucide-angular";
7
+ export class DataExcelImporterComponent {
8
+ constructor() {
9
+ this.excelData = new EventEmitter(); // Evento para enviar dados processados
10
+ // Configurações padrão
11
+ this.config = {
12
+ acceptedFileTypes: [".xlsx", ".xls", ".csv"],
13
+ onImport: (data) => this.defaultImportHandler(data),
14
+ excludeRows: [],
15
+ excludeColumns: [],
16
+ hasHeader: true,
17
+ headerRowIndex: 1,
18
+ titleRowIndex: 1,
19
+ };
20
+ // Controle do modal e inputs de configuração
21
+ this.userConfig = { ...this.config };
22
+ this.excludeRowsInput = ""; // Para capturar linhas a excluir
23
+ this.excludeColumnsInput = ""; // Para capturar colunas a excluir
24
+ this.showConfigModal = false;
25
+ this.buttonLabel = "Importar Dados";
26
+ }
27
+ // Abre o modal de configurações
28
+ openModal() {
29
+ this.showConfigModal = true;
30
+ }
31
+ // Fecha o modal de configurações
32
+ closeModal() {
33
+ this.showConfigModal = false;
34
+ }
35
+ // Salva as configurações ajustadas no modal
36
+ saveConfig() {
37
+ this.config = {
38
+ ...this.userConfig,
39
+ titleRowIndex: (this.userConfig.titleRowIndex ?? 1) - 1,
40
+ headerRowIndex: (this.userConfig.headerRowIndex ?? 2) - 1,
41
+ excludeRows: this.excludeRowsInput
42
+ .split(",")
43
+ .map((row) => parseInt(row.trim(), 10) - 1),
44
+ excludeColumns: this.excludeColumnsInput
45
+ .split(",")
46
+ .map((col) => this.columnLetterToIndex(col.trim())), // Converte letras para índices
47
+ };
48
+ this.closeModal();
49
+ }
50
+ // Valida que as linhas informadas sejam pelo menos 1
51
+ validateRowInput(field) {
52
+ if (field === "headerRow" && this.userConfig.headerRowIndex < 1) {
53
+ this.userConfig.headerRowIndex = 1;
54
+ }
55
+ if (field === "titleRow" && this.userConfig.titleRowIndex < 1) {
56
+ this.userConfig.titleRowIndex = 1;
57
+ }
58
+ }
59
+ // Processa o arquivo selecionado
60
+ handleFileInput(event) {
61
+ const file = event.target.files[0];
62
+ if (file) {
63
+ const fileType = file.name.split(".").pop()?.toLowerCase();
64
+ if (fileType === "csv") {
65
+ this.processCSVFile(file); // Processa o CSV de forma isolada
66
+ }
67
+ else {
68
+ this.processExcelFile(file); // Mantém o fluxo atual para Excel
69
+ }
70
+ event.target.value = ""; // Reseta o input para permitir reimportação
71
+ }
72
+ }
73
+ processExcelFile(file) {
74
+ const reader = new FileReader();
75
+ reader.onload = (e) => {
76
+ const data = new Uint8Array(e.target.result);
77
+ const workbook = XLSX.read(data, { type: "array" });
78
+ const sheetName = workbook.SheetNames[0];
79
+ const worksheet = workbook.Sheets[sheetName];
80
+ const titleRowIndex = this.config.titleRowIndex ?? 0;
81
+ const headerRowIndex = this.config.headerRowIndex ?? titleRowIndex + 1;
82
+ if (worksheet["!ref"]) {
83
+ worksheet["!ref"] = this.adjustRange(worksheet["!ref"], headerRowIndex + 1);
84
+ }
85
+ else {
86
+ console.error("Intervalo da planilha ('!ref') não encontrado.");
87
+ return;
88
+ }
89
+ const jsonData = XLSX.utils.sheet_to_json(worksheet, {
90
+ header: 1,
91
+ defval: "",
92
+ blankrows: false,
93
+ });
94
+ this.processData(jsonData);
95
+ };
96
+ reader.readAsArrayBuffer(file); // Lê o Excel como array buffer
97
+ }
98
+ processCSVFile(file) {
99
+ if (this.userConfig.hasHeader) {
100
+ if (this.config?.headerRowIndex !== undefined) {
101
+ this.config.headerRowIndex =
102
+ this.config.headerRowIndex === 0 ? 1 : this.config.headerRowIndex + 1;
103
+ }
104
+ const sum = (this.config.excludeRows ?? []).reduce((acc, value) => acc + value, 0) +
105
+ 1;
106
+ this.config.excludeRows = [sum];
107
+ }
108
+ const reader = new FileReader();
109
+ reader.onload = (e) => {
110
+ const csvData = e.target.result;
111
+ // Converte CSV em JSON usando XLSX
112
+ const workbook = XLSX.read(csvData, { type: "string" });
113
+ const sheetName = workbook.SheetNames[0];
114
+ const worksheet = workbook.Sheets[sheetName];
115
+ const jsonData = XLSX.utils.sheet_to_json(worksheet, {
116
+ header: 1,
117
+ defval: "",
118
+ blankrows: false,
119
+ });
120
+ this.processData(jsonData);
121
+ };
122
+ reader.readAsText(file); // Lê o CSV como texto
123
+ }
124
+ processData(jsonData) {
125
+ const titleRowIndex = this.config.titleRowIndex ?? 0;
126
+ const headerRowIndex = this.config.headerRowIndex ?? titleRowIndex + 1;
127
+ const headers = jsonData[0];
128
+ if (!headers) {
129
+ console.error("Cabeçalhos não encontrados. Verifique o headerRowIndex.");
130
+ return;
131
+ }
132
+ const normalizedHeaders = headers.map((header, index) => this.normalizeHeader(header || `col_${index}`));
133
+ const dataRows = jsonData.slice(1); // Remove a linha de cabeçalho
134
+ // Filtra as linhas baseando-se no índice informado pelo usuário (1-based)
135
+ const filteredRows = dataRows.filter((_, index) => !this.config.excludeRows?.includes(index + headerRowIndex + 1));
136
+ const formattedData = filteredRows.map((row) => {
137
+ const record = {};
138
+ normalizedHeaders.forEach((header, index) => {
139
+ record[header] = row[index] ?? "";
140
+ });
141
+ return record;
142
+ });
143
+ const finalData = this.filterColumns(formattedData);
144
+ this.config.onImport(finalData); // Chama o callback com os dados processados
145
+ this.excelData.emit(finalData); // Emite os dados processados para o cliente
146
+ }
147
+ // Ajusta o intervalo da planilha com base na linha do cabeçalho
148
+ adjustRange(range, startRow) {
149
+ const [start, end] = range.split(":");
150
+ const startCol = start.replace(/[0-9]/g, "");
151
+ const endCol = end.replace(/[0-9]/g, "");
152
+ const endRow = end.replace(/[A-Za-z]/g, "");
153
+ return `${startCol}${startRow}:${endCol}${endRow}`;
154
+ }
155
+ // Normaliza os cabeçalhos removendo acentos e espaços
156
+ normalizeHeader(header) {
157
+ return header
158
+ .normalize("NFD")
159
+ .replace(/[\u0300-\u036f]/g, "")
160
+ .replace(/\s+/g, "_")
161
+ .toLowerCase();
162
+ }
163
+ // Filtra as colunas configuradas para exclusão
164
+ filterColumns(data) {
165
+ const { excludeColumns } = this.config;
166
+ return data.map((row) => {
167
+ const filteredRow = {};
168
+ Object.keys(row).forEach((key, index) => {
169
+ if (!excludeColumns?.includes(index)) {
170
+ filteredRow[key] = row[key];
171
+ }
172
+ });
173
+ return filteredRow;
174
+ });
175
+ }
176
+ // Converte letra da coluna para índice (A -> 0, B -> 1, etc.)
177
+ columnLetterToIndex(letter) {
178
+ let index = 0;
179
+ for (let i = 0; i < letter.length; i++) {
180
+ index = index * 26 + (letter.charCodeAt(i) - "A".charCodeAt(0) + 1);
181
+ }
182
+ return index - 1;
183
+ }
184
+ // Callback padrão para manipular dados importados
185
+ defaultImportHandler(data) { }
186
+ transformToUppercase() {
187
+ this.excludeColumnsInput = this.excludeColumnsInput.toUpperCase();
188
+ }
189
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataExcelImporterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
190
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DataExcelImporterComponent, selector: "argenta-excel-importer", outputs: { excelData: "excelData" }, ngImport: i0, template: "<div class=\"excel-importer\">\n <input\n type=\"file\"\n (change)=\"handleFileInput($event)\"\n [accept]=\"config.acceptedFileTypes?.join(',')\"\n style=\"display: none\"\n #fileInput\n />\n <button (click)=\"fileInput.click()\">{{ buttonLabel }}</button>\n <lucide-icon\n name=\"settings\"\n [size]=\"24\"\n [strokeWidth]=\"2.25\"\n class=\"settings-icon\"\n (click)=\"openModal()\"\n ></lucide-icon>\n</div>\n\n<div class=\"modal-container\" *ngIf=\"showConfigModal\">\n <div class=\"modal-content\">\n <h4 class=\"titulo\">Configura\u00E7\u00E3o de Importa\u00E7\u00E3o</h4>\n <form (ngSubmit)=\"saveConfig()\">\n <div class=\"form-group\">\n <label for=\"acceptedFileTypes\">Tipos de Arquivo Permitidos</label>\n <input\n id=\"acceptedFileTypes\"\n type=\"text\"\n [(ngModel)]=\"userConfig.acceptedFileTypes\"\n name=\"acceptedFileTypes\"\n placeholder=\".xlsx, .xls\"\n />\n </div>\n <div class=\"form-group\" style=\"display: none\">\n <label for=\"titleRow\">Linha do T\u00EDtulo (se aplic\u00E1vel)</label>\n <input\n id=\"titleRow\"\n type=\"number\"\n [(ngModel)]=\"userConfig.titleRowIndex\"\n name=\"titleRow\"\n placeholder=\"Ex: 1\"\n (change)=\"validateRowInput('titleRow')\"\n />\n </div>\n <div class=\"form-group checkbox-group\">\n <div class=\"row\">\n <div class=\"col-md-8\">\n <label for=\"hasHeader\">A planilha cont\u00E9m cabe\u00E7alho?</label>\n </div>\n <div class=\"col-md-4\">\n <input\n id=\"hasHeader\"\n class=\"input-checkbox\"\n type=\"checkbox\"\n [(ngModel)]=\"userConfig.hasHeader\"\n name=\"hasHeader\"\n />\n </div>\n </div>\n </div>\n\n <!-- Exibe a linha do cabe\u00E7alho apenas se o checkbox estiver marcado -->\n <div class=\"form-group\" *ngIf=\"userConfig.hasHeader\">\n <label for=\"headerRow\">Linha do Cabe\u00E7alho</label>\n <input\n id=\"headerRow\"\n type=\"number\"\n [(ngModel)]=\"userConfig.headerRowIndex\"\n name=\"headerRow\"\n placeholder=\"Ex: 2\"\n (change)=\"validateRowInput('headerRow')\"\n />\n </div>\n\n <div class=\"form-group\">\n <label for=\"excludeRows\">Linhas a Excluir</label>\n <input\n id=\"excludeRows\"\n type=\"text\"\n [(ngModel)]=\"excludeRowsInput\"\n name=\"excludeRows\"\n placeholder=\"Ex: 1, 3\"\n />\n </div>\n <div class=\"form-group\">\n <label for=\"excludeColumns\">Colunas a Excluir</label>\n <input\n id=\"excludeColumns\"\n type=\"text\"\n [(ngModel)]=\"excludeColumnsInput\"\n name=\"excludeColumns\"\n placeholder=\"Ex: A, C\"\n (input)=\"transformToUppercase()\"\n />\n </div>\n <button type=\"submit\">Salvar Configura\u00E7\u00F5es</button>\n <button type=\"button\" (click)=\"closeModal()\">Fechar</button>\n </form>\n </div>\n</div>\n", styles: [".excel-importer{display:flex;align-items:center;gap:10px}.excel-importer button{background-color:var(--primary-color);color:var(--text-color);font-family:var(--font-family);padding:10px 20px;border:none;cursor:pointer;display:flex;align-items:center}.excel-importer button:hover{background-color:var(--secondary-color)}.excel-importer .settings-icon{color:var(--text-color);background-color:var(--primary-color);border-radius:50%;padding:5px;cursor:pointer;transition:background-color .3s,color .3s}.excel-importer .settings-icon:hover{background-color:var(--secondary-color);color:#fff}.modal-container{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;display:flex;justify-content:center;align-items:center}.modal-content{background:#fff;padding:20px;border-radius:5px;width:400px}.modal-content h2{margin-bottom:20px}.modal-content .form-group{margin-bottom:15px}.modal-content .form-group label{display:block;margin-bottom:5px}.modal-content .form-group input{width:100%;padding:8px;border:1px solid #ccc;border-radius:4px}.modal-content button{margin-right:10px;padding:8px 15px;border:none;cursor:pointer}.modal-content button:first-of-type{background-color:var(--primary-color);color:#fff}.modal-content button:last-of-type{background-color:#ccc}input#excludeColumns{text-transform:uppercase}.small-label{font-size:.7rem;color:#555}.input-checkbox{margin-left:-5rem}.titulo{margin-bottom:2rem}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i3.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }] }); }
191
+ }
192
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataExcelImporterComponent, decorators: [{
193
+ type: Component,
194
+ args: [{ selector: "argenta-excel-importer", template: "<div class=\"excel-importer\">\n <input\n type=\"file\"\n (change)=\"handleFileInput($event)\"\n [accept]=\"config.acceptedFileTypes?.join(',')\"\n style=\"display: none\"\n #fileInput\n />\n <button (click)=\"fileInput.click()\">{{ buttonLabel }}</button>\n <lucide-icon\n name=\"settings\"\n [size]=\"24\"\n [strokeWidth]=\"2.25\"\n class=\"settings-icon\"\n (click)=\"openModal()\"\n ></lucide-icon>\n</div>\n\n<div class=\"modal-container\" *ngIf=\"showConfigModal\">\n <div class=\"modal-content\">\n <h4 class=\"titulo\">Configura\u00E7\u00E3o de Importa\u00E7\u00E3o</h4>\n <form (ngSubmit)=\"saveConfig()\">\n <div class=\"form-group\">\n <label for=\"acceptedFileTypes\">Tipos de Arquivo Permitidos</label>\n <input\n id=\"acceptedFileTypes\"\n type=\"text\"\n [(ngModel)]=\"userConfig.acceptedFileTypes\"\n name=\"acceptedFileTypes\"\n placeholder=\".xlsx, .xls\"\n />\n </div>\n <div class=\"form-group\" style=\"display: none\">\n <label for=\"titleRow\">Linha do T\u00EDtulo (se aplic\u00E1vel)</label>\n <input\n id=\"titleRow\"\n type=\"number\"\n [(ngModel)]=\"userConfig.titleRowIndex\"\n name=\"titleRow\"\n placeholder=\"Ex: 1\"\n (change)=\"validateRowInput('titleRow')\"\n />\n </div>\n <div class=\"form-group checkbox-group\">\n <div class=\"row\">\n <div class=\"col-md-8\">\n <label for=\"hasHeader\">A planilha cont\u00E9m cabe\u00E7alho?</label>\n </div>\n <div class=\"col-md-4\">\n <input\n id=\"hasHeader\"\n class=\"input-checkbox\"\n type=\"checkbox\"\n [(ngModel)]=\"userConfig.hasHeader\"\n name=\"hasHeader\"\n />\n </div>\n </div>\n </div>\n\n <!-- Exibe a linha do cabe\u00E7alho apenas se o checkbox estiver marcado -->\n <div class=\"form-group\" *ngIf=\"userConfig.hasHeader\">\n <label for=\"headerRow\">Linha do Cabe\u00E7alho</label>\n <input\n id=\"headerRow\"\n type=\"number\"\n [(ngModel)]=\"userConfig.headerRowIndex\"\n name=\"headerRow\"\n placeholder=\"Ex: 2\"\n (change)=\"validateRowInput('headerRow')\"\n />\n </div>\n\n <div class=\"form-group\">\n <label for=\"excludeRows\">Linhas a Excluir</label>\n <input\n id=\"excludeRows\"\n type=\"text\"\n [(ngModel)]=\"excludeRowsInput\"\n name=\"excludeRows\"\n placeholder=\"Ex: 1, 3\"\n />\n </div>\n <div class=\"form-group\">\n <label for=\"excludeColumns\">Colunas a Excluir</label>\n <input\n id=\"excludeColumns\"\n type=\"text\"\n [(ngModel)]=\"excludeColumnsInput\"\n name=\"excludeColumns\"\n placeholder=\"Ex: A, C\"\n (input)=\"transformToUppercase()\"\n />\n </div>\n <button type=\"submit\">Salvar Configura\u00E7\u00F5es</button>\n <button type=\"button\" (click)=\"closeModal()\">Fechar</button>\n </form>\n </div>\n</div>\n", styles: [".excel-importer{display:flex;align-items:center;gap:10px}.excel-importer button{background-color:var(--primary-color);color:var(--text-color);font-family:var(--font-family);padding:10px 20px;border:none;cursor:pointer;display:flex;align-items:center}.excel-importer button:hover{background-color:var(--secondary-color)}.excel-importer .settings-icon{color:var(--text-color);background-color:var(--primary-color);border-radius:50%;padding:5px;cursor:pointer;transition:background-color .3s,color .3s}.excel-importer .settings-icon:hover{background-color:var(--secondary-color);color:#fff}.modal-container{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;display:flex;justify-content:center;align-items:center}.modal-content{background:#fff;padding:20px;border-radius:5px;width:400px}.modal-content h2{margin-bottom:20px}.modal-content .form-group{margin-bottom:15px}.modal-content .form-group label{display:block;margin-bottom:5px}.modal-content .form-group input{width:100%;padding:8px;border:1px solid #ccc;border-radius:4px}.modal-content button{margin-right:10px;padding:8px 15px;border:none;cursor:pointer}.modal-content button:first-of-type{background-color:var(--primary-color);color:#fff}.modal-content button:last-of-type{background-color:#ccc}input#excludeColumns{text-transform:uppercase}.small-label{font-size:.7rem;color:#555}.input-checkbox{margin-left:-5rem}.titulo{margin-bottom:2rem}\n"] }]
195
+ }], propDecorators: { excelData: [{
196
+ type: Output
197
+ }] } });
198
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YS1leGNlbC1pbXBvcnRlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9saWItcG9ydGFsLWFuZ3VsYXIvc3JjL2xpYi9jb21wb25lbnRzL2RhdGEtZXhjZWwtaW1wb3J0L2RhdGEtZXhjZWwtaW1wb3J0ZXIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbGliLXBvcnRhbC1hbmd1bGFyL3NyYy9saWIvY29tcG9uZW50cy9kYXRhLWV4Y2VsLWltcG9ydC9kYXRhLWV4Y2VsLWltcG9ydGVyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNoRSxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQzs7Ozs7QUFpQjdCLE1BQU0sT0FBTywwQkFBMEI7SUFMdkM7UUFNWSxjQUFTLEdBQUcsSUFBSSxZQUFZLEVBQVMsQ0FBQyxDQUFDLHVDQUF1QztRQUN4Rix1QkFBdUI7UUFDdkIsV0FBTSxHQUF3QjtZQUM1QixpQkFBaUIsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDO1lBQzVDLFFBQVEsRUFBRSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQztZQUNuRCxXQUFXLEVBQUUsRUFBRTtZQUNmLGNBQWMsRUFBRSxFQUFFO1lBQ2xCLFNBQVMsRUFBRSxJQUFJO1lBQ2YsY0FBYyxFQUFFLENBQUM7WUFDakIsYUFBYSxFQUFFLENBQUM7U0FDakIsQ0FBQztRQUVGLDZDQUE2QztRQUM3QyxlQUFVLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNoQyxxQkFBZ0IsR0FBVyxFQUFFLENBQUMsQ0FBQyxpQ0FBaUM7UUFDaEUs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THRDLFNBQVM7K0JBQ0Usd0JBQXdCOzhCQUt4QixTQUFTO3NCQUFsQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFdmVudEVtaXR0ZXIsIE91dHB1dCB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgKiBhcyBYTFNYIGZyb20gXCJ4bHN4XCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXhjZWxJbXBvcnRlckNvbmZpZyB7XG4gIGFjY2VwdGVkRmlsZVR5cGVzOiBzdHJpbmdbXTtcbiAgb25JbXBvcnQ6IChkYXRhOiBhbnlbXSkgPT4gdm9pZDtcbiAgZXhjbHVkZVJvd3M/OiBudW1iZXJbXTtcbiAgZXhjbHVkZUNvbHVtbnM/OiBudW1iZXJbXTtcbiAgaGFzSGVhZGVyPzogYm9vbGVhbjtcbiAgaGVhZGVyUm93SW5kZXg/OiBudW1iZXI7XG4gIHRpdGxlUm93SW5kZXg/OiBudW1iZXI7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJhcmdlbnRhLWV4Y2VsLWltcG9ydGVyXCIsXG4gIHRlbXBsYXRlVXJsOiBcIi4vZGF0YS1leGNlbC1pbXBvcnRlci5jb21wb25lbnQuaHRtbFwiLFxuICBzdHlsZVVybHM6IFtcIi4vZGF0YS1leGNlbC1pbXBvcnRlci5jb21wb25lbnQuc2Nzc1wiXSxcbn0pXG5leHBvcnQgY2xhc3MgRGF0YUV4Y2VsSW1wb3J0ZXJDb21wb25lbnQge1xuICBAT3V0cHV0KCkgZXhjZWxEYXRhID0gbmV3IEV2ZW50RW1pdHRlcjxhbnlbXT4oKTsgLy8gRXZlbnRvIHBhcmEgZW52aWFyIGRhZG9zIHByb2Nlc3NhZG9zXG4gIC8vIENvbmZpZ3VyYcOnw7VlcyBwYWRyw6NvXG4gIGNvbmZpZzogRXhjZWxJbXBvcnRlckNvbmZpZyA9IHtcbiAgICBhY2NlcHRlZEZpbGVUeXBlczogW1wiLnhsc3hcIiwgXCIueGxzXCIsIFwiLmNzdlwiXSxcbiAgICBvbkltcG9ydDogKGRhdGEpID0+IHRoaXMuZGVmYXVsdEltcG9ydEhhbmRsZXIoZGF0YSksXG4gICAgZXhjbHVkZVJvd3M6IFtdLFxuICAgIGV4Y2x1ZGVDb2x1bW5zOiBbXSxcbiAgICBoYXNIZWFkZXI6IHRydWUsXG4gICAgaGVhZGVyUm93SW5kZXg6IDEsXG4gICAgdGl0bGVSb3dJbmRleDogMSxcbiAgfTtcblxuICAvLyBDb250cm9sZSBkbyBtb2RhbCBlIGlucHV0cyBkZSBjb25maWd1cmHDp8Ojb1xuICB1c2VyQ29uZmlnID0geyAuLi50aGlzLmNvbmZpZyB9O1xuICBleGNsdWRlUm93c0lucHV0OiBzdHJpbmcgPSBcIlwiOyAvLyBQYXJhIGNhcHR1cmFyIGxpbmhhcyBhIGV4Y2x1aXJcbiAgZXhjbHVkZUNvbHVtbnNJbnB1dDogc3RyaW5nID0gXCJcIjsgLy8gUGFyYSBjYXB0dXJhciBjb2x1bmFzIGEgZXhjbHVpclxuICBzaG93Q29uZmlnTW9kYWwgPSBmYWxzZTtcbiAgYnV0dG9uTGFiZWwgPSBcIkltcG9ydGFyIERhZG9zXCI7XG5cbiAgLy8gQWJyZSBvIG1vZGFsIGRlIGNvbmZpZ3VyYcOnw7Vlc1xuICBvcGVuTW9kYWwoKTogdm9pZCB7XG4gICAgdGhpcy5zaG93Q29uZmlnTW9kYWwgPSB0cnVlO1xuICB9XG5cbiAgLy8gRmVjaGEgbyBtb2RhbCBkZSBjb25maWd1cmHDp8O1ZXNcbiAgY2xvc2VNb2RhbCgpOiB2b2lkIHtcbiAgICB0aGlzLnNob3dDb25maWdNb2RhbCA9IGZhbHNlO1xuICB9XG5cbiAgLy8gU2FsdmEgYXMgY29uZmlndXJhw6fDtWVzIGFqdXN0YWRhcyBubyBtb2RhbFxuICBzYXZlQ29uZmlnKCk6IHZvaWQge1xuICAgIHRoaXMuY29uZmlnID0ge1xuICAgICAgLi4udGhpcy51c2VyQ29uZmlnLFxuICAgICAgdGl0bGVSb3dJbmRleDogKHRoaXMudXNlckNvbmZpZy50aXRsZVJvd0luZGV4ID8/IDEpIC0gMSwgLy8gQ29udmVydGUgcGFyYSDDrW5kaWNlIHplcm8tYmFzZWRcbiAgICAgIGhlYWRlclJvd0luZGV4OiAodGhpcy51c2VyQ29uZmlnLmhlYWRlclJvd0luZGV4ID8/IDIpIC0gMSwgLy8gQ29udmVydGUgcGFyYSDDrW5kaWNlIHplcm8tYmFzZWRcbiAgICAgIGV4Y2x1ZGVSb3dzOiB0aGlzLmV4Y2x1ZGVSb3dzSW5wdXRcbiAgICAgICAgLnNwbGl0KFwiLFwiKVxuICAgICAgICAubWFwKChyb3cpID0+IHBhcnNlSW50KHJvdy50cmltKCksIDEwKSAtIDEpLCAvLyBDb252ZXJ0ZSBwYXJhIHplcm8tYmFzZWRcbiAgICAgIGV4Y2x1ZGVDb2x1bW5zOiB0aGlzLmV4Y2x1ZGVDb2x1bW5zSW5wdXRcbiAgICAgICAgLnNwbGl0KFwiLFwiKVxuICAgICAgICAubWFwKChjb2wpID0+IHRoaXMuY29sdW1uTGV0dGVyVG9JbmRleChjb2wudHJpbSgpKSksIC8vIENvbnZlcnRlIGxldHJhcyBwYXJhIMOtbmRpY2VzXG4gICAgfTtcbiAgICB0aGlzLmNsb3NlTW9kYWwoKTtcbiAgfVxuXG4gIC8vIFZhbGlkYSBxdWUgYXMgbGluaGFzIGluZm9ybWFkYXMgc2VqYW0gcGVsbyBtZW5vcyAxXG4gIHZhbGlkYXRlUm93SW5wdXQoZmllbGQ6IFwiaGVhZGVyUm93XCIgfCBcInRpdGxlUm93XCIpOiB2b2lkIHtcbiAgICBpZiAoZmllbGQgPT09IFwiaGVhZGVyUm93XCIgJiYgdGhpcy51c2VyQ29uZmlnLmhlYWRlclJvd0luZGV4ISA8IDEpIHtcbiAgICAgIHRoaXMudXNlckNvbmZpZy5oZWFkZXJSb3dJbmRleCA9IDE7XG4gICAgfVxuICAgIGlmIChmaWVsZCA9PT0gXCJ0aXRsZVJvd1wiICYmIHRoaXMudXNlckNvbmZpZy50aXRsZVJvd0luZGV4ISA8IDEpIHtcbiAgICAgIHRoaXMudXNlckNvbmZpZy50aXRsZVJvd0luZGV4ID0gMTtcbiAgICB9XG4gIH1cblxuICAvLyBQcm9jZXNzYSBvIGFycXVpdm8gc2VsZWNpb25hZG9cbiAgaGFuZGxlRmlsZUlucHV0KGV2ZW50OiBhbnkpOiB2b2lkIHtcbiAgICBjb25zdCBmaWxlID0gZXZlbnQudGFyZ2V0LmZpbGVzWzBdO1xuICAgIGlmIChmaWxlKSB7XG4gICAgICBjb25zdCBmaWxlVHlwZSA9IGZpbGUubmFtZS5zcGxpdChcIi5cIikucG9wKCk/LnRvTG93ZXJDYXNlKCk7XG5cbiAgICAgIGlmIChmaWxlVHlwZSA9PT0gXCJjc3ZcIikge1xuICAgICAgICB0aGlzLnByb2Nlc3NDU1ZGaWxlKGZpbGUpOyAvLyBQcm9jZXNzYSBvIENTViBkZSBmb3JtYSBpc29sYWRhXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnByb2Nlc3NFeGNlbEZpbGUoZmlsZSk7IC8vIE1hbnTDqW0gbyBmbHV4byBhdHVhbCBwYXJhIEV4Y2VsXG4gICAgICB9XG4gICAgICBldmVudC50YXJnZXQudmFsdWUgPSBcIlwiOyAvLyBSZXNldGEgbyBpbnB1dCBwYXJhIHBlcm1pdGlyIHJlaW1wb3J0YcOnw6NvXG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBwcm9jZXNzRXhjZWxGaWxlKGZpbGU6IEZpbGUpOiB2b2lkIHtcbiAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICAgIHJlYWRlci5vbmxvYWQgPSAoZTogYW55KSA9PiB7XG4gICAgICBjb25zdCBkYXRhID0gbmV3IFVpbnQ4QXJyYXkoZS50YXJnZXQucmVzdWx0KTtcbiAgICAgIGNvbnN0IHdvcmtib29rID0gWExTWC5yZWFkKGRhdGEsIHsgdHlwZTogXCJhcnJheVwiIH0pO1xuICAgICAgY29uc3Qgc2hlZXROYW1lID0gd29ya2Jvb2suU2hlZXROYW1lc1swXTtcbiAgICAgIGNvbnN0IHdvcmtzaGVldCA9IHdvcmtib29rLlNoZWV0c1tzaGVldE5hbWVdO1xuXG4gICAgICBjb25zdCB0aXRsZVJvd0luZGV4ID0gdGhpcy5jb25maWcudGl0bGVSb3dJbmRleCA/PyAwO1xuICAgICAgY29uc3QgaGVhZGVyUm93SW5kZXggPSB0aGlzLmNvbmZpZy5oZWFkZXJSb3dJbmRleCA/PyB0aXRsZVJvd0luZGV4ICsgMTtcblxuICAgICAgaWYgKHdvcmtzaGVldFtcIiFyZWZcIl0pIHtcbiAgICAgICAgd29ya3NoZWV0W1wiIXJlZlwiXSA9IHRoaXMuYWRqdXN0UmFuZ2UoXG4gICAgICAgICAgd29ya3NoZWV0W1wiIXJlZlwiXSxcbiAgICAgICAgICBoZWFkZXJSb3dJbmRleCArIDFcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJJbnRlcnZhbG8gZGEgcGxhbmlsaGEgKCchcmVmJykgbsOjbyBlbmNvbnRyYWRvLlwiKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBqc29uRGF0YSA9IFhMU1gudXRpbHMuc2hlZXRfdG9fanNvbjxhbnlbXT4od29ya3NoZWV0LCB7XG4gICAgICAgIGhlYWRlcjogMSxcbiAgICAgICAgZGVmdmFsOiBcIlwiLFxuICAgICAgICBibGFua3Jvd3M6IGZhbHNlLFxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMucHJvY2Vzc0RhdGEoanNvbkRhdGEpO1xuICAgIH07XG4gICAgcmVhZGVyLnJlYWRBc0FycmF5QnVmZmVyKGZpbGUpOyAvLyBMw6ogbyBFeGNlbCBjb21vIGFycmF5IGJ1ZmZlclxuICB9XG5cbiAgcHJpdmF0ZSBwcm9jZXNzQ1NWRmlsZShmaWxlOiBGaWxlKTogdm9pZCB7XG4gICAgaWYgKHRoaXMudXNlckNvbmZpZy5oYXNIZWFkZXIpIHtcbiAgICAgIGlmICh0aGlzLmNvbmZpZz8uaGVhZGVyUm93SW5kZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmNvbmZpZy5oZWFkZXJSb3dJbmRleCA9XG4gICAgICAgICAgdGhpcy5jb25maWcuaGVhZGVyUm93SW5kZXggPT09IDAgPyAxIDogdGhpcy5jb25maWcuaGVhZGVyUm93SW5kZXggKyAxO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzdW0gPVxuICAgICAgICAodGhpcy5jb25maWcuZXhjbHVkZVJvd3MgPz8gW10pLnJlZHVjZSgoYWNjLCB2YWx1ZSkgPT4gYWNjICsgdmFsdWUsIDApICtcbiAgICAgICAgMTtcblxuICAgICAgdGhpcy5jb25maWcuZXhjbHVkZVJvd3MgPSBbc3VtXTtcbiAgICB9XG5cbiAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICAgIHJlYWRlci5vbmxvYWQgPSAoZTogYW55KSA9PiB7XG4gICAgICBjb25zdCBjc3ZEYXRhID0gZS50YXJnZXQucmVzdWx0O1xuXG4gICAgICAvLyBDb252ZXJ0ZSBDU1YgZW0gSlNPTiB1c2FuZG8gWExTWFxuICAgICAgY29uc3Qgd29ya2Jvb2sgPSBYTFNYLnJlYWQoY3N2RGF0YSwgeyB0eXBlOiBcInN0cmluZ1wiIH0pO1xuICAgICAgY29uc3Qgc2hlZXROYW1lID0gd29ya2Jvb2suU2hlZXROYW1lc1swXTtcbiAgICAgIGNvbnN0IHdvcmtzaGVldCA9IHdvcmtib29rLlNoZWV0c1tzaGVldE5hbWVdO1xuXG4gICAgICBjb25zdCBqc29uRGF0YSA9IFhMU1gudXRpbHMuc2hlZXRfdG9fanNvbjxhbnlbXT4od29ya3NoZWV0LCB7XG4gICAgICAgIGhlYWRlcjogMSxcbiAgICAgICAgZGVmdmFsOiBcIlwiLFxuICAgICAgICBibGFua3Jvd3M6IGZhbHNlLFxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMucHJvY2Vzc0RhdGEoanNvbkRhdGEpO1xuICAgIH07XG4gICAgcmVhZGVyLnJlYWRBc1RleHQoZmlsZSk7IC8vIEzDqiBvIENTViBjb21vIHRleHRvXG4gIH1cblxuICBwcml2YXRlIHByb2Nlc3NEYXRhKGpzb25EYXRhOiBhbnlbXSk6IHZvaWQge1xuICAgIGNvbnN0IHRpdGxlUm93SW5kZXggPSB0aGlzLmNvbmZpZy50aXRsZVJvd0luZGV4ID8/IDA7XG4gICAgY29uc3QgaGVhZGVyUm93SW5kZXggPSB0aGlzLmNvbmZpZy5oZWFkZXJSb3dJbmRleCA/PyB0aXRsZVJvd0luZGV4ICsgMTtcblxuICAgIGNvbnN0IGhlYWRlcnMgPSBqc29uRGF0YVswXTtcbiAgICBpZiAoIWhlYWRlcnMpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJDYWJlw6dhbGhvcyBuw6NvIGVuY29udHJhZG9zLiBWZXJpZmlxdWUgbyBoZWFkZXJSb3dJbmRleC5cIik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgbm9ybWFsaXplZEhlYWRlcnMgPSBoZWFkZXJzLm1hcCgoaGVhZGVyOiBhbnksIGluZGV4OiBhbnkpID0+XG4gICAgICB0aGlzLm5vcm1hbGl6ZUhlYWRlcihoZWFkZXIgfHwgYGNvbF8ke2luZGV4fWApXG4gICAgKTtcblxuICAgIGNvbnN0IGRhdGFSb3dzID0ganNvbkRhdGEuc2xpY2UoMSk7IC8vIFJlbW92ZSBhIGxpbmhhIGRlIGNhYmXDp2FsaG9cblxuICAgIC8vIEZpbHRyYSBhcyBsaW5oYXMgYmFzZWFuZG8tc2Ugbm8gw61uZGljZSBpbmZvcm1hZG8gcGVsbyB1c3XDoXJpbyAoMS1iYXNlZClcbiAgICBjb25zdCBmaWx0ZXJlZFJvd3MgPSBkYXRhUm93cy5maWx0ZXIoXG4gICAgICAoXywgaW5kZXgpID0+XG4gICAgICAgICF0aGlzLmNvbmZpZy5leGNsdWRlUm93cz8uaW5jbHVkZXMoaW5kZXggKyBoZWFkZXJSb3dJbmRleCArIDEpXG4gICAgKTtcblxuICAgIGNvbnN0IGZvcm1hdHRlZERhdGEgPSBmaWx0ZXJlZFJvd3MubWFwKChyb3cpID0+IHtcbiAgICAgIGNvbnN0IHJlY29yZDogYW55ID0ge307XG4gICAgICBub3JtYWxpemVkSGVhZGVycy5mb3JFYWNoKChoZWFkZXI6IGFueSwgaW5kZXg6IGFueSkgPT4ge1xuICAgICAgICByZWNvcmRbaGVhZGVyXSA9IHJvd1tpbmRleF0gPz8gXCJcIjtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlY29yZDtcbiAgICB9KTtcblxuICAgIGNvbnN0IGZpbmFsRGF0YSA9IHRoaXMuZmlsdGVyQ29sdW1ucyhmb3JtYXR0ZWREYXRhKTtcbiAgICB0aGlzLmNvbmZpZy5vbkltcG9ydChmaW5hbERhdGEpOyAvLyBDaGFtYSBvIGNhbGxiYWNrIGNvbSBvcyBkYWRvcyBwcm9jZXNzYWRvc1xuICAgIHRoaXMuZXhjZWxEYXRhLmVtaXQoZmluYWxEYXRhKTsgLy8gRW1pdGUgb3MgZGFkb3MgcHJvY2Vzc2Fkb3MgcGFyYSBvIGNsaWVudGVcbiAgfVxuXG4gIC8vIEFqdXN0YSBvIGludGVydmFsbyBkYSBwbGFuaWxoYSBjb20gYmFzZSBuYSBsaW5oYSBkbyBjYWJlw6dhbGhvXG4gIHByaXZhdGUgYWRqdXN0UmFuZ2UocmFuZ2U6IHN0cmluZywgc3RhcnRSb3c6IG51bWJlcik6IHN0cmluZyB7XG4gICAgY29uc3QgW3N0YXJ0LCBlbmRdID0gcmFuZ2Uuc3BsaXQoXCI6XCIpO1xuICAgIGNvbnN0IHN0YXJ0Q29sID0gc3RhcnQucmVwbGFjZSgvWzAtOV0vZywgXCJcIik7XG4gICAgY29uc3QgZW5kQ29sID0gZW5kLnJlcGxhY2UoL1swLTldL2csIFwiXCIpO1xuICAgIGNvbnN0IGVuZFJvdyA9IGVuZC5yZXBsYWNlKC9bQS1aYS16XS9nLCBcIlwiKTtcbiAgICByZXR1cm4gYCR7c3RhcnRDb2x9JHtzdGFydFJvd306JHtlbmRDb2x9JHtlbmRSb3d9YDtcbiAgfVxuXG4gIC8vIE5vcm1hbGl6YSBvcyBjYWJlw6dhbGhvcyByZW1vdmVuZG8gYWNlbnRvcyBlIGVzcGHDp29zXG4gIHByaXZhdGUgbm9ybWFsaXplSGVhZGVyKGhlYWRlcjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gaGVhZGVyXG4gICAgICAubm9ybWFsaXplKFwiTkZEXCIpXG4gICAgICAucmVwbGFjZSgvW1xcdTAzMDAtXFx1MDM2Zl0vZywgXCJcIilcbiAgICAgIC5yZXBsYWNlKC9cXHMrL2csIFwiX1wiKVxuICAgICAgLnRvTG93ZXJDYXNlKCk7XG4gIH1cblxuICAvLyBGaWx0cmEgYXMgY29sdW5hcyBjb25maWd1cmFkYXMgcGFyYSBleGNsdXPDo29cbiAgcHJpdmF0ZSBmaWx0ZXJDb2x1bW5zKGRhdGE6IGFueVtdKTogYW55W10ge1xuICAgIGNvbnN0IHsgZXhjbHVkZUNvbHVtbnMgfSA9IHRoaXMuY29uZmlnO1xuXG4gICAgcmV0dXJuIGRhdGEubWFwKChyb3cpID0+IHtcbiAgICAgIGNvbnN0IGZpbHRlcmVkUm93OiBhbnkgPSB7fTtcbiAgICAgIE9iamVjdC5rZXlzKHJvdykuZm9yRWFjaCgoa2V5LCBpbmRleCkgPT4ge1xuICAgICAgICBpZiAoIWV4Y2x1ZGVDb2x1bW5zPy5pbmNsdWRlcyhpbmRleCkpIHtcbiAgICAgICAgICBmaWx0ZXJlZFJvd1trZXldID0gcm93W2tleV07XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGZpbHRlcmVkUm93O1xuICAgIH0pO1xuICB9XG5cbiAgLy8gQ29udmVydGUgbGV0cmEgZGEgY29sdW5hIHBhcmEgw61uZGljZSAoQSAtPiAwLCBCIC0+IDEsIGV0Yy4pXG4gIHByaXZhdGUgY29sdW1uTGV0dGVyVG9JbmRleChsZXR0ZXI6IHN0cmluZyk6IG51bWJlciB7XG4gICAgbGV0IGluZGV4ID0gMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxldHRlci5sZW5ndGg7IGkrKykge1xuICAgICAgaW5kZXggPSBpbmRleCAqIDI2ICsgKGxldHRlci5jaGFyQ29kZUF0KGkpIC0gXCJBXCIuY2hhckNvZGVBdCgwKSArIDEpO1xuICAgIH1cbiAgICByZXR1cm4gaW5kZXggLSAxO1xuICB9XG5cbiAgLy8gQ2FsbGJhY2sgcGFkcsOjbyBwYXJhIG1hbmlwdWxhciBkYWRvcyBpbXBvcnRhZG9zXG4gIHByaXZhdGUgZGVmYXVsdEltcG9ydEhhbmRsZXIoZGF0YTogYW55W10pOiB2b2lkIHt9XG5cbiAgdHJhbnNmb3JtVG9VcHBlcmNhc2UoKTogdm9pZCB7XG4gICAgdGhpcy5leGNsdWRlQ29sdW1uc0lucHV0ID0gdGhpcy5leGNsdWRlQ29sdW1uc0lucHV0LnRvVXBwZXJDYXNlKCk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJleGNlbC1pbXBvcnRlclwiPlxuICA8aW5wdXRcbiAgICB0eXBlPVwiZmlsZVwiXG4gICAgKGNoYW5nZSk9XCJoYW5kbGVGaWxlSW5wdXQoJGV2ZW50KVwiXG4gICAgW2FjY2VwdF09XCJjb25maWcuYWNjZXB0ZWRGaWxlVHlwZXM/LmpvaW4oJywnKVwiXG4gICAgc3R5bGU9XCJkaXNwbGF5OiBub25lXCJcbiAgICAjZmlsZUlucHV0XG4gIC8+XG4gIDxidXR0b24gKGNsaWNrKT1cImZpbGVJbnB1dC5jbGljaygpXCI+e3sgYnV0dG9uTGFiZWwgfX08L2J1dHRvbj5cbiAgPGx1Y2lkZS1pY29uXG4gICAgbmFtZT1cInNldHRpbmdzXCJcbiAgICBbc2l6ZV09XCIyNFwiXG4gICAgW3N0cm9rZVdpZHRoXT1cIjIuMjVcIlxuICAgIGNsYXNzPVwic2V0dGluZ3MtaWNvblwiXG4gICAgKGNsaWNrKT1cIm9wZW5Nb2RhbCgpXCJcbiAgPjwvbHVjaWRlLWljb24+XG48L2Rpdj5cblxuPGRpdiBjbGFzcz1cIm1vZGFsLWNvbnRhaW5lclwiICpuZ0lmPVwic2hvd0NvbmZpZ01vZGFsXCI+XG4gIDxkaXYgY2xhc3M9XCJtb2RhbC1jb250ZW50XCI+XG4gICAgPGg0IGNsYXNzPVwidGl0dWxvXCI+Q29uZmlndXJhw6fDo28gZGUgSW1wb3J0YcOnw6NvPC9oND5cbiAgICA8Zm9ybSAobmdTdWJtaXQpPVwic2F2ZUNvbmZpZygpXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgICA8bGFiZWwgZm9yPVwiYWNjZXB0ZWRGaWxlVHlwZXNcIj5UaXBvcyBkZSBBcnF1aXZvIFBlcm1pdGlkb3M8L2xhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBpZD1cImFjY2VwdGVkRmlsZVR5cGVzXCJcbiAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgWyhuZ01vZGVsKV09XCJ1c2VyQ29uZmlnLmFjY2VwdGVkRmlsZVR5cGVzXCJcbiAgICAgICAgICBuYW1lPVwiYWNjZXB0ZWRGaWxlVHlwZXNcIlxuICAgICAgICAgIHBsYWNlaG9sZGVyPVwiLnhsc3gsIC54bHNcIlxuICAgICAgICAvPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiIHN0eWxlPVwiZGlzcGxheTogbm9uZVwiPlxuICAgICAgICA8bGFiZWwgZm9yPVwidGl0bGVSb3dcIj5MaW5oYSBkbyBUw610dWxvIChzZSBhcGxpY8OhdmVsKTwvbGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIGlkPVwidGl0bGVSb3dcIlxuICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgIFsobmdNb2RlbCldPVwidXNlckNvbmZpZy50aXRsZVJvd0luZGV4XCJcbiAgICAgICAgICBuYW1lPVwidGl0bGVSb3dcIlxuICAgICAgICAgIHBsYWNlaG9sZGVyPVwiRXg6IDFcIlxuICAgICAgICAgIChjaGFuZ2UpPVwidmFsaWRhdGVSb3dJbnB1dCgndGl0bGVSb3cnKVwiXG4gICAgICAgIC8+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwIGNoZWNrYm94LWdyb3VwXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJyb3dcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLW1kLThcIj5cbiAgICAgICAgICAgIDxsYWJlbCBmb3I9XCJoYXNIZWFkZXJcIj5BIHBsYW5pbGhhIGNvbnTDqW0gY2FiZcOnYWxobz88L2xhYmVsPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtNFwiPlxuICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgIGlkPVwiaGFzSGVhZGVyXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJpbnB1dC1jaGVja2JveFwiXG4gICAgICAgICAgICAgIHR5cGU9XCJjaGVja2JveFwiXG4gICAgICAgICAgICAgIFsobmdNb2RlbCldPVwidXNlckNvbmZpZy5oYXNIZWFkZXJcIlxuICAgICAgICAgICAgICBuYW1lPVwiaGFzSGVhZGVyXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDwhLS0gRXhpYmUgYSBsaW5oYSBkbyBjYWJlw6dhbGhvIGFwZW5hcyBzZSBvIGNoZWNrYm94IGVzdGl2ZXIgbWFyY2FkbyAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCIgKm5nSWY9XCJ1c2VyQ29uZmlnLmhhc0hlYWRlclwiPlxuICAgICAgICA8bGFiZWwgZm9yPVwiaGVhZGVyUm93XCI+TGluaGEgZG8gQ2FiZcOnYWxobzwvbGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIGlkPVwiaGVhZGVyUm93XCJcbiAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcbiAgICAgICAgICBbKG5nTW9kZWwpXT1cInVzZXJDb25maWcuaGVhZGVyUm93SW5kZXhcIlxuICAgICAgICAgIG5hbWU9XCJoZWFkZXJSb3dcIlxuICAgICAgICAgIHBsYWNlaG9sZGVyPVwiRXg6IDJcIlxuICAgICAgICAgIChjaGFuZ2UpPVwidmFsaWRhdGVSb3dJbnB1dCgnaGVhZGVyUm93JylcIlxuICAgICAgICAvPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICAgIDxsYWJlbCBmb3I9XCJleGNsdWRlUm93c1wiPkxpbmhhcyBhIEV4Y2x1aXI8L2xhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBpZD1cImV4Y2x1ZGVSb3dzXCJcbiAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgWyhuZ01vZGVsKV09XCJleGNsdWRlUm93c0lucHV0XCJcbiAgICAgICAgICBuYW1lPVwiZXhjbHVkZVJvd3NcIlxuICAgICAgICAgIHBsYWNlaG9sZGVyPVwiRXg6IDEsIDNcIlxuICAgICAgICAvPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgICA8bGFiZWwgZm9yPVwiZXhjbHVkZUNvbHVtbnNcIj5Db2x1bmFzIGEgRXhjbHVpcjwvbGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIGlkPVwiZXhjbHVkZUNvbHVtbnNcIlxuICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICBbKG5nTW9kZWwpXT1cImV4Y2x1ZGVDb2x1bW5zSW5wdXRcIlxuICAgICAgICAgIG5hbWU9XCJleGNsdWRlQ29sdW1uc1wiXG4gICAgICAgICAgcGxhY2Vob2xkZXI9XCJFeDogQSwgQ1wiXG4gICAgICAgICAgKGlucHV0KT1cInRyYW5zZm9ybVRvVXBwZXJjYXNlKClcIlxuICAgICAgICAvPlxuICAgICAgPC9kaXY+XG4gICAgICA8YnV0dG9uIHR5cGU9XCJzdWJtaXRcIj5TYWx2YXIgQ29uZmlndXJhw6fDtWVzPC9idXR0b24+XG4gICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwiY2xvc2VNb2RhbCgpXCI+RmVjaGFyPC9idXR0b24+XG4gICAgPC9mb3JtPlxuICA8L2Rpdj5cbjwvZGl2PlxuIl19