UNPKG

@notiz/ngx-tablo

Version:

JSON powered material table for Angular

423 lines (415 loc) 39.8 kB
import { CommonModule } from '@angular/common'; import { Component, computed, effect, input, model, output, viewChild, } from '@angular/core'; import { MatPaginator, MatPaginatorModule, } from '@angular/material/paginator'; import { MatSort, MatSortModule, } from '@angular/material/sort'; import { MatTableDataSource, MatTableModule } from '@angular/material/table'; import { Observable, Subject, takeUntil } from 'rxjs'; import { CellValuePipe } from './cell-value.pipe'; import { HasCellValuePipe } from './has-cell-value.pipe'; import { NestedColumnNamePipe } from './nested-column-name.pipe'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "@angular/material/table"; import * as i3 from "@angular/material/paginator"; import * as i4 from "@angular/material/sort"; export class Tablo { constructor() { this.tableClasses = input(''); /** * Add custom dataSource. * * Default: MatTableDataSource */ this.dataSource = input(new MatTableDataSource()); this.data = model(); this.columns = input([]); this.displayedColumns = computed(() => this.columns().map((column) => column.columnName)); this.mode = input('client'); /** * Sorting */ this.sortActive = model(''); this.sortDirection = model(''); /** * Custom sorting function for `MatTableDataSource`. * * Use this if data properties don't match column names or for complex data objects. * * Default expects column `xyz` to represent `data['xyz']`. * */ this.sortingDataAccessor = input(); /** * Filter value for `MatTableDataSource`. */ this.filter = input(); /** * Custom filter function for `MatTableDataSource`. */ this.filterPredicate = input(); /** * Paging */ this.showPaging = model(false); this.pagingDisabled = model(false); this.hidePageSize = model(false); this.showFirstLastButtons = model(true); this.pageSize = model(0); this.pageIndex = model(0); this.length = model(0); this.pageSizeOptions = model([10, 20, 50, 100]); this.pageAriaLabel = model('Select page'); /** * default to false */ this.resetPageOnSort = model(false); /** * Outputs */ this.rowClick = output(); this.pageChange = output(); this.sortChange = output(); this.paginator = viewChild(MatPaginator); this.sort = viewChild.required(MatSort); this.destroy$ = new Subject(); effect(() => { this.fillData(); }, { allowSignalWrites: true }); effect(() => { const filter = this.filter(); if (this.dataSource() instanceof MatTableDataSource) { this.getMatTableDataSource().filter = filter || ''; } }, { allowSignalWrites: true }); } ngOnInit() { this.columns().forEach((column) => { if (column.lifecycle?.onInit) { column.lifecycle.onInit(column); } }); if (this.dataSource() instanceof MatTableDataSource) { if (this.filterPredicate()) { this.getMatTableDataSource().filterPredicate = this.filterPredicate(); } if (this.sortingDataAccessor()) { this.getMatTableDataSource().sortingDataAccessor = this.sortingDataAccessor(); } } } ngAfterViewInit() { this.columns().forEach((column) => { if (column.lifecycle?.afterViewInit) { column.lifecycle.afterViewInit(column); } }); this.sort().sortChange.subscribe((sort) => { this.sortChange.emit(sort); if (this.resetPageOnSort()) { this.firstPage(); } }); if (this.paginator()) { this.paginator().page.subscribe((page) => this.pageChange.emit(page)); } if (this.mode() === 'client' && this.dataSource() instanceof MatTableDataSource) { this.getMatTableDataSource().paginator = this.paginator(); this.getMatTableDataSource().sort = this.sort(); } } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); } firstPage() { if (this.paginator()) { this.paginator().firstPage(); } } lastPage() { if (this.paginator()) { this.paginator().lastPage(); } } clearFilter() { if (this.dataSource() instanceof MatTableDataSource) { this.getMatTableDataSource().filter = ''; } } fillData() { if (this.data() && this.dataSource() instanceof MatTableDataSource) { if (this.data() instanceof Observable) { this.data() .pipe(takeUntil(this.destroy$)) .subscribe((data) => (this.getMatTableDataSource().data = data)); } else { this.getMatTableDataSource().data = this.data(); } } } getMatTableDataSource() { return this.dataSource(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: Tablo, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.8", type: Tablo, isStandalone: true, selector: "ngx-tablo", inputs: { tableClasses: { classPropertyName: "tableClasses", publicName: "tableClasses", isSignal: true, isRequired: false, transformFunction: null }, dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, sortActive: { classPropertyName: "sortActive", publicName: "sortActive", isSignal: true, isRequired: false, transformFunction: null }, sortDirection: { classPropertyName: "sortDirection", publicName: "sortDirection", isSignal: true, isRequired: false, transformFunction: null }, sortingDataAccessor: { classPropertyName: "sortingDataAccessor", publicName: "sortingDataAccessor", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterPredicate: { classPropertyName: "filterPredicate", publicName: "filterPredicate", isSignal: true, isRequired: false, transformFunction: null }, showPaging: { classPropertyName: "showPaging", publicName: "showPaging", isSignal: true, isRequired: false, transformFunction: null }, pagingDisabled: { classPropertyName: "pagingDisabled", publicName: "pagingDisabled", isSignal: true, isRequired: false, transformFunction: null }, hidePageSize: { classPropertyName: "hidePageSize", publicName: "hidePageSize", isSignal: true, isRequired: false, transformFunction: null }, showFirstLastButtons: { classPropertyName: "showFirstLastButtons", publicName: "showFirstLastButtons", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, pageIndex: { classPropertyName: "pageIndex", publicName: "pageIndex", isSignal: true, isRequired: false, transformFunction: null }, length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, pageAriaLabel: { classPropertyName: "pageAriaLabel", publicName: "pageAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, resetPageOnSort: { classPropertyName: "resetPageOnSort", publicName: "resetPageOnSort", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { data: "dataChange", sortActive: "sortActiveChange", sortDirection: "sortDirectionChange", showPaging: "showPagingChange", pagingDisabled: "pagingDisabledChange", hidePageSize: "hidePageSizeChange", showFirstLastButtons: "showFirstLastButtonsChange", pageSize: "pageSizeChange", pageIndex: "pageIndexChange", length: "lengthChange", pageSizeOptions: "pageSizeOptionsChange", pageAriaLabel: "pageAriaLabelChange", resetPageOnSort: "resetPageOnSortChange", rowClick: "rowClick", pageChange: "pageChange", sortChange: "sortChange" }, viewQueries: [{ propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, isSignal: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true, isSignal: true }], ngImport: i0, template: ` <table [class]="tableClasses()" mat-table [dataSource]="dataSource()" matSort [matSortActive]="sortActive()" [matSortDirection]="sortDirection()" > @for (column of columns(); track column; let i = $index) { <ng-container [matColumnDef]="column.columnName"> <th mat-header-cell [mat-sort-header]="column.sortHeader || column.columnName" [disabled]="!column.sort" *matHeaderCellDef > @if (column.headerTemplate; as content) { <ng-container [ngTemplateOutlet]="headerContentTemplate" [ngTemplateOutletContext]="{ content: content, column: column }" ></ng-container> } @else { @if ( (column.headerHTMLContent && column.headerHTMLContent(column)) || column.header; as content ) { <div [class]="column.headerClassName" [innerHTML]="content" ></div> } } </th> <td mat-cell *matCellDef="let row"> @if (row | hasCellValue: column; as content) { <ng-container [ngTemplateOutlet]="cellContentTemplate" [ngTemplateOutletContext]="{ content: row | cellValue: column, row: row, className: column.className, format: column.format }" > </ng-container> } </td> </ng-container> } <tr mat-header-row *matHeaderRowDef="displayedColumns()"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns()" (click)="rowClick.emit(row)" ></tr> </table> @if (showPaging()) { <mat-paginator [disabled]="pagingDisabled()" [hidePageSize]="hidePageSize()" [pageSizeOptions]="pageSizeOptions()" [pageSize]="pageSize()" [pageIndex]="pageIndex()" [length]="length()" [showFirstLastButtons]="showFirstLastButtons()" [attr.aria-label]="pageAriaLabel()" > </mat-paginator> } <ng-template #headerContentTemplate let-content="content" let-column="column" > <ng-container [ngTemplateOutlet]="content" [ngTemplateOutletContext]="{ column: column }" ></ng-container> </ng-template> <ng-template #cellContentTemplate let-content="content" let-row="row" let-className="className" let-format="format" > @if (!content.createEmbeddedView) { @if (format) { <div [class]="className"> <!-- NOTE: each specified format will be displayed currently --> @if (format.date) { {{ content | date: format.date }} } @if (format.decimal) { {{ content | number: format.decimal }} } @if (format.percent) { {{ content | percent: format.percent }} } @if (format.currency) { {{ content | currency: format.currency }} } @if (format.titleCase) { {{ content | titlecase }} } </div> } @else { <div [class]="className" [innerHTML]="content"></div> } } @else { <ng-container [ngTemplateOutlet]="content" [ngTemplateOutletContext]="{ row: row }" ></ng-container> } </ng-template> `, isInline: true, styles: ["table{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }, { kind: "pipe", type: i1.PercentPipe, name: "percent" }, { kind: "pipe", type: i1.TitleCasePipe, name: "titlecase" }, { kind: "pipe", type: i1.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i1.DatePipe, name: "date" }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i2.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i2.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i2.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i2.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i2.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i2.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i2.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i2.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i2.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i2.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i4.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i4.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "pipe", type: HasCellValuePipe, name: "hasCellValue" }, { kind: "pipe", type: CellValuePipe, name: "cellValue" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: Tablo, decorators: [{ type: Component, args: [{ selector: 'ngx-tablo', standalone: true, imports: [ CommonModule, MatTableModule, MatPaginatorModule, MatSortModule, NestedColumnNamePipe, HasCellValuePipe, CellValuePipe, ], template: ` <table [class]="tableClasses()" mat-table [dataSource]="dataSource()" matSort [matSortActive]="sortActive()" [matSortDirection]="sortDirection()" > @for (column of columns(); track column; let i = $index) { <ng-container [matColumnDef]="column.columnName"> <th mat-header-cell [mat-sort-header]="column.sortHeader || column.columnName" [disabled]="!column.sort" *matHeaderCellDef > @if (column.headerTemplate; as content) { <ng-container [ngTemplateOutlet]="headerContentTemplate" [ngTemplateOutletContext]="{ content: content, column: column }" ></ng-container> } @else { @if ( (column.headerHTMLContent && column.headerHTMLContent(column)) || column.header; as content ) { <div [class]="column.headerClassName" [innerHTML]="content" ></div> } } </th> <td mat-cell *matCellDef="let row"> @if (row | hasCellValue: column; as content) { <ng-container [ngTemplateOutlet]="cellContentTemplate" [ngTemplateOutletContext]="{ content: row | cellValue: column, row: row, className: column.className, format: column.format }" > </ng-container> } </td> </ng-container> } <tr mat-header-row *matHeaderRowDef="displayedColumns()"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns()" (click)="rowClick.emit(row)" ></tr> </table> @if (showPaging()) { <mat-paginator [disabled]="pagingDisabled()" [hidePageSize]="hidePageSize()" [pageSizeOptions]="pageSizeOptions()" [pageSize]="pageSize()" [pageIndex]="pageIndex()" [length]="length()" [showFirstLastButtons]="showFirstLastButtons()" [attr.aria-label]="pageAriaLabel()" > </mat-paginator> } <ng-template #headerContentTemplate let-content="content" let-column="column" > <ng-container [ngTemplateOutlet]="content" [ngTemplateOutletContext]="{ column: column }" ></ng-container> </ng-template> <ng-template #cellContentTemplate let-content="content" let-row="row" let-className="className" let-format="format" > @if (!content.createEmbeddedView) { @if (format) { <div [class]="className"> <!-- NOTE: each specified format will be displayed currently --> @if (format.date) { {{ content | date: format.date }} } @if (format.decimal) { {{ content | number: format.decimal }} } @if (format.percent) { {{ content | percent: format.percent }} } @if (format.currency) { {{ content | currency: format.currency }} } @if (format.titleCase) { {{ content | titlecase }} } </div> } @else { <div [class]="className" [innerHTML]="content"></div> } } @else { <ng-container [ngTemplateOutlet]="content" [ngTemplateOutletContext]="{ row: row }" ></ng-container> } </ng-template> `, styles: ["table{width:100%}\n"] }] }], ctorParameters: () => [] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXRhYmxvLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC10YWJsby9zcmMvbGliL25neC10YWJsby5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFFTCxTQUFTLEVBR1QsUUFBUSxFQUNSLE1BQU0sRUFDTixLQUFLLEVBQ0wsS0FBSyxFQUNMLE1BQU0sRUFDTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUNMLFlBQVksRUFDWixrQkFBa0IsR0FFbkIsTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEVBQ0wsT0FBTyxFQUNQLGFBQWEsR0FHZCxNQUFNLHdCQUF3QixDQUFDO0FBQ2hDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxjQUFjLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM3RSxPQUFPLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3pELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDOzs7Ozs7QUFzSmpFLE1BQU0sT0FBTyxLQUFLO0lBMkVoQjtRQTFFQSxpQkFBWSxHQUFHLEtBQUssQ0FBUyxFQUFFLENBQUMsQ0FBQztRQUVqQzs7OztXQUlHO1FBQ0gsZUFBVSxHQUFHLEtBQUssQ0FBZ0IsSUFBSSxrQkFBa0IsRUFBRSxDQUFDLENBQUM7UUFFNUQsU0FBSSxHQUFHLEtBQUssRUFBcUMsQ0FBQztRQUVsRCxZQUFPLEdBQUcsS0FBSyxDQUFrQixFQUFFLENBQUMsQ0FBQztRQUUzQixxQkFBZ0IsR0FBRyxRQUFR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QUksR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3JFLENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBUyxDQUFDO1lBQ3pELENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVPLHFCQUFxQjtRQUMzQixPQUFPLElBQUksQ0FBQyxVQUFVLEVBQTJCLENBQUM7SUFDcEQsQ0FBQzs4R0FsTFUsS0FBSztrR0FBTCxLQUFLLHUyR0FzRTRCLFlBQVksdUZBQ3RCLE9BQU8sZ0VBOU0vQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBOEhULDRGQXRJQyxZQUFZLGllQUNaLGNBQWMsc2dDQUNkLGtCQUFrQixtU0FDbEIsYUFBYSw2Y0FFYixnQkFBZ0IsZ0RBQ2hCLGFBQWE7OzJGQXlJSixLQUFLO2tCQW5KakIsU0FBUzsrQkFDRSxXQUFXLGNBQ1QsSUFBSSxXQUNQO3dCQUNQLFlBQVk7d0JBQ1osY0FBYzt3QkFDZCxrQkFBa0I7d0JBQ2xCLGFBQWE7d0JBQ2Isb0JBQW9CO3dCQUNwQixnQkFBZ0I7d0JBQ2hCLGFBQWE7cUJBQ2QsWUFDUzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBOEhUIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGF0YVNvdXJjZSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2xsZWN0aW9ucyc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgQ29tcG9uZW50LFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgY29tcHV0ZWQsXG4gIGVmZmVjdCxcbiAgaW5wdXQsXG4gIG1vZGVsLFxuICBvdXRwdXQsXG4gIHZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBNYXRQYWdpbmF0b3IsXG4gIE1hdFBhZ2luYXRvck1vZHVsZSxcbiAgUGFnZUV2ZW50LFxufSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9wYWdpbmF0b3InO1xuaW1wb3J0IHtcbiAgTWF0U29ydCxcbiAgTWF0U29ydE1vZHVsZSxcbiAgU29ydCxcbiAgU29ydERpcmVjdGlvbixcbn0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvc29ydCc7XG5pbXBvcnQgeyBNYXRUYWJsZURhdGFTb3VyY2UsIE1hdFRhYmxlTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdGFibGUnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgU3ViamVjdCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBDZWxsVmFsdWVQaXBlIH0gZnJvbSAnLi9jZWxsLXZhbHVlLnBpcGUnO1xuaW1wb3J0IHsgSGFzQ2VsbFZhbHVlUGlwZSB9IGZyb20gJy4vaGFzLWNlbGwtdmFsdWUucGlwZSc7XG5pbXBvcnQgeyBOZXN0ZWRDb2x1bW5OYW1lUGlwZSB9IGZyb20gJy4vbmVzdGVkLWNvbHVtbi1uYW1lLnBpcGUnO1xuaW1wb3J0IHsgVGFibG9Db2x1bW5zIH0gZnJvbSAnLi90YWJsby1jb2x1bW4nO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtdGFibG8nLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXG4gICAgQ29tbW9uTW9kdWxlLFxuICAgIE1hdFRhYmxlTW9kdWxlLFxuICAgIE1hdFBhZ2luYXRvck1vZHVsZSxcbiAgICBNYXRTb3J0TW9kdWxlLFxuICAgIE5lc3RlZENvbHVtbk5hbWVQaXBlLFxuICAgIEhhc0NlbGxWYWx1ZVBpcGUsXG4gICAgQ2VsbFZhbHVlUGlwZSxcbiAgXSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8dGFibGVcbiAgICAgIFtjbGFzc109XCJ0YWJsZUNsYXNzZXMoKVwiXG4gICAgICBtYXQtdGFibGVcbiAgICAgIFtkYXRhU291cmNlXT1cImRhdGFTb3VyY2UoKVwiXG4gICAgICBtYXRTb3J0XG4gICAgICBbbWF0U29ydEFjdGl2ZV09XCJzb3J0QWN0aXZlKClcIlxuICAgICAgW21hdFNvcnREaXJlY3Rpb25dPVwic29ydERpcmVjdGlvbigpXCJcbiAgICA+XG4gICAgICBAZm9yIChjb2x1bW4gb2YgY29sdW1ucygpOyB0cmFjayBjb2x1bW47IGxldCBpID0gJGluZGV4KSB7XG4gICAgICAgIDxuZy1jb250YWluZXIgW21hdENvbHVtbkRlZl09XCJjb2x1bW4uY29sdW1uTmFtZVwiPlxuICAgICAgICAgIDx0aFxuICAgICAgICAgICAgbWF0LWhlYWRlci1jZWxsXG4gICAgICAgICAgICBbbWF0LXNvcnQtaGVhZGVyXT1cImNvbHVtbi5zb3J0SGVhZGVyIHx8IGNvbHVtbi5jb2x1bW5OYW1lXCJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhY29sdW1uLnNvcnRcIlxuICAgICAgICAgICAgKm1hdEhlYWRlckNlbGxEZWZcbiAgICAgICAgICA+XG4gICAgICAgICAgICBAaWYgKGNvbHVtbi5oZWFkZXJUZW1wbGF0ZTsgYXMgY29udGVudCkge1xuICAgICAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiaGVhZGVyQ29udGVudFRlbXBsYXRlXCJcbiAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwie1xuICAgICAgICAgICAgICAgICAgY29udGVudDogY29udGVudCxcbiAgICAgICAgICAgICAgICAgIGNvbHVtbjogY29sdW1uXG4gICAgICAgICAgICAgICAgfVwiXG4gICAgICAgICAgICAgID48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICBAaWYgKFxuICAgICAgICAgICAgICAgIChjb2x1bW4uaGVhZGVySFRNTENvbnRlbnQgJiZcbiAgICAgICAgICAgICAgICAgIGNvbHVtbi5oZWFkZXJIVE1MQ29udGVudChjb2x1bW4pKSB8fFxuICAgICAgICAgICAgICAgICAgY29sdW1uLmhlYWRlcjtcbiAgICAgICAgICAgICAgICBhcyBjb250ZW50XG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgICAgIFtjbGFzc109XCJjb2x1bW4uaGVhZGVyQ2xhc3NOYW1lXCJcbiAgICAgICAgICAgICAgICAgIFtpbm5lckhUTUxdPVwiY29udGVudFwiXG4gICAgICAgICAgICAgICAgPjwvZGl2PlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC90aD5cbiAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgcm93XCI+XG4gICAgICAgICAgICBAaWYgKHJvdyB8IGhhc0NlbGxWYWx1ZTogY29sdW1uOyBhcyBjb250ZW50KSB7XG4gICAgICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJjZWxsQ29udGVudFRlbXBsYXRlXCJcbiAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwie1xuICAgICAgICAgICAgICAgICAgY29udGVudDogcm93IHwgY2VsbFZhbHVlOiBjb2x1bW4sXG4gICAgICAgICAgICAgICAgICByb3c6IHJvdyxcbiAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZTogY29sdW1uLmNsYXNzTmFtZSxcbiAgICAgICAgICAgICAgICAgIGZvcm1hdDogY29sdW1uLmZvcm1hdFxuICAgICAgICAgICAgICAgIH1cIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgfVxuICAgICAgICAgIDwvdGQ+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgfVxuXG4gICAgICA8dHIgbWF0LWhlYWRlci1yb3cgKm1hdEhlYWRlclJvd0RlZj1cImRpc3BsYXllZENvbHVtbnMoKVwiPjwvdHI+XG4gICAgICA8dHJcbiAgICAgICAgbWF0LXJvd1xuICAgICAgICAqbWF0Um93RGVmPVwibGV0IHJvdzsgY29sdW1uczogZGlzcGxheWVkQ29sdW1ucygpXCJcbiAgICAgICAgKGNsaWNrKT1cInJvd0NsaWNrLmVtaXQocm93KVwiXG4gICAgICA+PC90cj5cbiAgICA8L3RhYmxlPlxuXG4gICAgQGlmIChzaG93UGFnaW5nKCkpIHtcbiAgICAgIDxtYXQtcGFnaW5hdG9yXG4gICAgICAgIFtkaXNhYmxlZF09XCJwYWdpbmdEaXNhYmxlZCgpXCJcbiAgICAgICAgW2hpZGVQYWdlU2l6ZV09XCJoaWRlUGFnZVNpemUoKVwiXG4gICAgICAgIFtwYWdlU2l6ZU9wdGlvbnNdPVwicGFnZVNpemVPcHRpb25zKClcIlxuICAgICAgICBbcGFnZVNpemVdPVwicGFnZVNpemUoKVwiXG4gICAgICAgIFtwYWdlSW5kZXhdPVwicGFnZUluZGV4KClcIlxuICAgICAgICBbbGVuZ3RoXT1cImxlbmd0aCgpXCJcbiAgICAgICAgW3Nob3dGaXJzdExhc3RCdXR0b25zXT1cInNob3dGaXJzdExhc3RCdXR0b25zKClcIlxuICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cInBhZ2VBcmlhTGFiZWwoKVwiXG4gICAgICA+XG4gICAgICA8L21hdC1wYWdpbmF0b3I+XG4gICAgfVxuXG4gICAgPG5nLXRlbXBsYXRlXG4gICAgICAjaGVhZGVyQ29udGVudFRlbXBsYXRlXG4gICAgICBsZXQtY29udGVudD1cImNvbnRlbnRcIlxuICAgICAgbGV0LWNvbHVtbj1cImNvbHVtblwiXG4gICAgPlxuICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJjb250ZW50XCJcbiAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgY29sdW1uOiBjb2x1bW4gfVwiXG4gICAgICA+PC9uZy1jb250YWluZXI+XG4gICAgPC9uZy10ZW1wbGF0ZT5cblxuICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgI2NlbGxDb250ZW50VGVtcGxhdGVcbiAgICAgIGxldC1jb250ZW50PVwiY29udGVudFwiXG4gICAgICBsZXQtcm93PVwicm93XCJcbiAgICAgIGxldC1jbGFzc05hbWU9XCJjbGFzc05hbWVcIlxuICAgICAgbGV0LWZvcm1hdD1cImZvcm1hdFwiXG4gICAgPlxuICAgICAgQGlmICghY29udGVudC5jcmVhdGVFbWJlZGRlZFZpZXcpIHtcbiAgICAgICAgQGlmIChmb3JtYXQpIHtcbiAgICAgICAgICA8ZGl2IFtjbGFzc109XCJjbGFzc05hbWVcIj5cbiAgICAgICAgICAgIDwhLS0gTk9URTogZWFjaCBzcGVjaWZpZWQgZm9ybWF0IHdpbGwgYmUgZGlzcGxheWVkIGN1cnJlbnRseSAtLT5cbiAgICAgICAgICAgIEBpZiAoZm9ybWF0LmRhdGUpIHtcbiAgICAgICAgICAgICAge3sgY29udGVudCB8IGRhdGU6IGZvcm1hdC5kYXRlIH19XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBAaWYgKGZvcm1hdC5kZWNpbWFsKSB7XG4gICAgICAgICAgICAgIHt7IGNvbnRlbnQgfCBudW1iZXI6IGZvcm1hdC5kZWNpbWFsIH19XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBAaWYgKGZvcm1hdC5wZXJjZW50KSB7XG4gICAgICAgICAgICAgIHt7IGNvbnRlbnQgfCBwZXJjZW50OiBmb3JtYXQucGVyY2VudCB9fVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgQGlmIChmb3JtYXQuY3VycmVuY3kpIHtcbiAgICAgICAgICAgICAge3sgY29udGVudCB8IGN1cnJlbmN5OiBmb3JtYXQuY3VycmVuY3kgfX1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIEBpZiAoZm9ybWF0LnRpdGxlQ2FzZSkge1xuICAgICAgICAgICAgICB7eyBjb250ZW50IHwgdGl0bGVjYXNlIH19XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgIDxkaXYgW2NsYXNzXT1cImNsYXNzTmFtZVwiIFtpbm5lckhUTUxdPVwiY29udGVudFwiPjwvZGl2PlxuICAgICAgICB9XG4gICAgICB9IEBlbHNlIHtcbiAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImNvbnRlbnRcIlxuICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7IHJvdzogcm93IH1cIlxuICAgICAgICA+PC9uZy1jb250YWluZXI+XG4gICAgICB9XG4gICAgPC9uZy10ZW1wbGF0ZT5cbiAgYCxcbiAgc3R5bGVzOiBbXG4gICAgYFxuICAgICAgdGFibGUge1xuICAgICAgICB3aWR0aDogMTAwJTtcbiAgICAgIH1cbiAgICBgLFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBUYWJsbzxUPiBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcbiAgdGFibGVDbGFzc2VzID0gaW5wdXQ8c3RyaW5nPignJyk7XG5cbiAgLyoqXG4gICAqIEFkZCBjdXN0b20gZGF0YVNvdXJjZS5cbiAgICpcbiAgICogRGVmYXVsdDogTWF0VGFibGVEYXRhU291cmNlXG4gICAqL1xuICBkYXRhU291cmNlID0gaW5wdXQ8RGF0YVNvdXJjZTxUPj4obmV3IE1hdFRhYmxlRGF0YVNvdXJjZSgpKTtcblxuICBkYXRhID0gbW9kZWw8VFtdIHwgT2JzZXJ2YWJsZTxUW10+IHwgdW5kZWZpbmVkPigpO1xuXG4gIGNvbHVtbnMgPSBpbnB1dDxUYWJsb0NvbHVtbnM8VD4+KFtdKTtcblxuICBwcm90ZWN0ZWQgZGlzcGxheWVkQ29sdW1ucyA9IGNvbXB1dGVkKCgpID0+XG4gICAgdGhpcy5jb2x1bW5zKCkubWFwKChjb2x1bW4pID0+IGNvbHVtbi5jb2x1bW5OYW1lKSxcbiAgKTtcblxuICBtb2RlID0gaW5wdXQ8J2NsaWVudCcgfCAnc2VydmVyJz4oJ2NsaWVudCcpO1xuXG4gIC8qKlxuICAgKiBTb3J0aW5nXG4gICAqL1xuICBzb3J0QWN0aXZlID0gbW9kZWwoJycpO1xuICBzb3J0RGlyZWN0aW9uID0gbW9kZWw8U29ydERpcmVjdGlvbj4oJycpO1xuICAvKipcbiAgICogQ3VzdG9tIHNvcnRpbmcgZnVuY3Rpb24gZm9yIGBNYXRUYWJsZURhdGFTb3VyY2VgLlxuICAgKlxuICAgKiBVc2UgdGhpcyBpZiBkYXRhIHByb3BlcnRpZXMgZG9uJ3QgbWF0Y2ggY29sdW1uIG5hbWVzIG9yIGZvciBjb21wbGV4IGRhdGEgb2JqZWN0cy5cbiAgICpcbiAgICogRGVmYXVsdCBleHBlY3RzIGNvbHVtbiBgeHl6YCB0byByZXByZXNlbnQgYGRhdGFbJ3h5eiddYC5cbiAgICpcbiAgICovXG4gIHNvcnRpbmdEYXRhQWNjZXNzb3IgPVxuICAgIGlucHV0PChkYXRhOiBULCBzb3J0SGVhZGVySWQ6IHN0cmluZykgPT4gc3RyaW5nIHwgbnVtYmVyPigpO1xuXG4gIC8qKlxuICAgKiBGaWx0ZXIgdmFsdWUgZm9yIGBNYXRUYWJsZURhdGFTb3VyY2VgLlxuICAgKi9cbiAgZmlsdGVyID0gaW5wdXQ8c3RyaW5nPigpO1xuXG4gIC8qKlxuICAgKiBDdXN0b20gZmlsdGVyIGZ1bmN0aW9uIGZvciBgTWF0VGFibGVEYXRhU291cmNlYC5cbiAgICovXG4gIGZpbHRlclByZWRpY2F0ZSA9IGlucHV0PChkYXRhOiBULCBmaWx0ZXI6IHN0cmluZykgPT4gYm9vbGVhbj4oKTtcblxuICAvKipcbiAgICogUGFnaW5nXG4gICAqL1xuICBzaG93UGFnaW5nID0gbW9kZWwoZmFsc2UpO1xuICBwYWdpbmdEaXNhYmxlZCA9IG1vZGVsKGZhbHNlKTtcbiAgaGlkZVBhZ2VTaXplID0gbW9kZWwoZmFsc2UpO1xuICBzaG93Rmlyc3RMYXN0QnV0dG9ucyA9IG1vZGVsKHRydWUpO1xuICBwYWdlU2l6ZSA9IG1vZGVsKDApO1xuICBwYWdlSW5kZXggPSBtb2RlbCgwKTtcbiAgbGVuZ3RoID0gbW9kZWw8bnVtYmVyPigwKTtcbiAgcGFnZVNpemVPcHRpb25zID0gbW9kZWwoWzEwLCAyMCwgNTAsIDEwMF0pO1xuICBwYWdlQXJpYUxhYmVsID0gbW9kZWwoJ1NlbGVjdCBwYWdlJyk7XG4gIC8qKlxuICAgKiBkZWZhdWx0IHRvIGZhbHNlXG4gICAqL1xuICByZXNldFBhZ2VPblNvcnQgPSBtb2RlbDxib29sZWFuPihmYWxzZSk7XG5cbiAgLyoqXG4gICAqIE91dHB1dHNcbiAgICovXG4gIHJvd0NsaWNrID0gb3V0cHV0PFQ+KCk7XG4gIHBhZ2VDaGFuZ2UgPSBvdXRwdXQ8UGFnZUV2ZW50PigpO1xuICBzb3J0Q2hhbmdlID0gb3V0cHV0PFNvcnQ+KCk7XG5cbiAgcHJpdmF0ZSBwYWdpbmF0b3IgPSB2aWV3Q2hpbGQ8TWF0UGFnaW5hdG9yPihNYXRQYWdpbmF0b3IpO1xuICBwcml2YXRlIHNvcnQgPSB2aWV3Q2hpbGQucmVxdWlyZWQoTWF0U29ydCk7XG5cbiAgcHJpdmF0ZSBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgZWZmZWN0KFxuICAgICAgKCkgPT4ge1xuICAgICAgICB0aGlzLmZpbGxEYXRhKCk7XG4gICAgICB9LFxuICAgICAgeyBhbGxvd1NpZ25hbFdyaXRlczogdHJ1ZSB9LFxuICAgICk7XG5cbiAgICBlZmZlY3QoXG4gICAgICAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGZpbHRlciA9IHRoaXMuZmlsdGVyKCk7XG5cbiAgICAgICAgaWYgKHRoaXMuZGF0YVNvdXJjZSgpIGluc3RhbmNlb2YgTWF0VGFibGVEYXRhU291cmNlKSB7XG4gICAgICAgICAgdGhpcy5nZXRNYXRUYWJsZURhdGFTb3VyY2UoKS5maWx0ZXIgPSBmaWx0ZXIgfHwgJyc7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICB7IGFsbG93U2lnbmFsV3JpdGVzOiB0cnVlIH0sXG4gICAgKTtcbiAgfVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuY29sdW1ucygpLmZvckVhY2goKGNvbHVtbikgPT4ge1xuICAgICAgaWYgKGNvbHVtbi5saWZlY3ljbGU/Lm9uSW5pdCkge1xuICAgICAgICBjb2x1bW4ubGlmZWN5Y2xlLm9uSW5pdChjb2x1bW4pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYgKHRoaXMuZGF0YVNvdXJjZSgpIGluc3RhbmNlb2YgTWF0VGFibGVEYXRhU291cmNlKSB7XG4gICAgICBpZiAodGhpcy5maWx0ZXJQcmVkaWNhdGUoKSkge1xuICAgICAgICB0aGlzLmdldE1hdFRhYmxlRGF0YVNvdXJjZSgpLmZpbHRlclByZWRpY2F0ZSA9IHRoaXMuZmlsdGVyUHJlZGljYXRlKCkhO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5zb3J0aW5nRGF0YUFjY2Vzc29yKCkpIHtcbiAgICAgICAgdGhpcy5nZXRNYXRUYWJsZURhdGFTb3VyY2UoKS5zb3J0aW5nRGF0YUFjY2Vzc29yID1cbiAgICAgICAgICB0aGlzLnNvcnRpbmdEYXRhQWNjZXNzb3IoKSE7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHRoaXMuY29sdW1ucygpLmZvckVhY2goKGNvbHVtbikgPT4ge1xuICAgICAgaWYgKGNvbHVtbi5saWZlY3ljbGU/LmFmdGVyVmlld0luaXQpIHtcbiAgICAgICAgY29sdW1uLmxpZmVjeWNsZS5hZnRlclZpZXdJbml0KGNvbHVtbik7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLnNvcnQoKS5zb3J0Q2hhbmdlLnN1YnNjcmliZSgoc29ydCkgPT4ge1xuICAgICAgdGhpcy5zb3J0Q2hhbmdlLmVtaXQoc29ydCk7XG4gICAgICBpZiAodGhpcy5yZXNldFBhZ2VPblNvcnQoKSkge1xuICAgICAgICB0aGlzLmZpcnN0UGFnZSgpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYgKHRoaXMucGFnaW5hdG9yKCkpIHtcbiAgICAgIHRoaXMucGFnaW5hdG9yKCkhLnBhZ2Uuc3Vic2NyaWJlKChwYWdlKSA9PiB0aGlzLnBhZ2VDaGFuZ2UuZW1pdChwYWdlKSk7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgdGhpcy5tb2RlKCkgPT09ICdjbGllbnQnICYmXG4gICAgICB0aGlzLmRhdGFTb3VyY2UoKSBpbnN0YW5jZW9mIE1hdFRhYmxlRGF0YVNvdXJjZVxuICAgICkge1xuICAgICAgdGhpcy5nZXRNYXRUYWJsZURhdGFTb3VyY2UoKS5wYWdpbmF0b3IgPSB0aGlzLnBhZ2luYXRvcigpITtcbiAgICAgIHRoaXMuZ2V0TWF0VGFibGVEYXRhU291cmNlKCkuc29ydCA9IHRoaXMuc29ydCgpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuZGVzdHJveSQubmV4dCgpO1xuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcbiAgfVxuXG4gIGZpcnN0UGFnZSgpIHtcbiAgICBpZiAodGhpcy5wYWdpbmF0b3IoKSkge1xuICAgICAgdGhpcy5wYWdpbmF0b3IoKSEuZmlyc3RQYWdlKCk7XG4gICAgfVxuICB9XG5cbiAgbGFzdFBhZ2UoKSB7XG4gICAgaWYgKHRoaXMucGFnaW5hdG9yKCkpIHtcbiAgICAgIHRoaXMucGFnaW5hdG9yKCkhLmxhc3RQYWdlKCk7XG4gICAgfVxuICB9XG5cbiAgY2xlYXJGaWx0ZXIoKSB7XG4gICAgaWYgKHRoaXMuZGF0YVNvdXJjZSgpIGluc3RhbmNlb2YgTWF0VGFibGVEYXRhU291cmNlKSB7XG4gICAgICB0aGlzLmdldE1hdFRhYmxlRGF0YVNvdXJjZSgpLmZpbHRlciA9ICcnO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZmlsbERhdGEoKSB7XG4gICAgaWYgKHRoaXMuZGF0YSgpICYmIHRoaXMuZGF0YVNvdXJjZSgpIGluc3RhbmNlb2YgTWF0VGFibGVEYXRhU291cmNlKSB7XG4gICAgICBpZiAodGhpcy5kYXRhKCkgaW5zdGFuY2VvZiBPYnNlcnZhYmxlKSB7XG4gICAgICAgICh0aGlzLmRhdGEoKSBhcyBPYnNlcnZhYmxlPFRbXT4pXG4gICAgICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKVxuICAgICAgICAgIC5zdWJzY3JpYmUoKGRhdGEpID0+ICh0aGlzLmdldE1hdFRhYmxlRGF0YVNvdXJjZSgpLmRhdGEgPSBkYXRhKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmdldE1hdFRhYmxlRGF0YVNvdXJjZSgpLmRhdGEgPSB0aGlzLmRhdGEoKSBhcyBUW107XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRNYXRUYWJsZURhdGFTb3VyY2UoKTogTWF0VGFibGVEYXRhU291cmNlPFQ+IHtcbiAgICByZXR1cm4gdGhpcy5kYXRhU291cmNlKCkgYXMgTWF0VGFibGVEYXRhU291cmNlPFQ+O1xuICB9XG59XG4iXX0=