UNPKG

ngx-text-diff

Version:
253 lines 38.9 kB
import { __awaiter, __decorate, __metadata } from "tslib"; import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit, Output, EventEmitter, ViewChildren, QueryList, AfterViewInit } from '@angular/core'; import { NgxTextDiffService } from './ngx-text-diff.service'; import { Observable } from 'rxjs'; import { ContainerDirective } from './ngx-text-diff-container.directive'; import { ScrollDispatcher, CdkScrollable } from '@angular/cdk/scrolling'; let NgxTextDiffComponent = class NgxTextDiffComponent { constructor(scrollService, diff, cd) { this.scrollService = scrollService; this.diff = diff; this.cd = cd; this._hideMatchingLines = false; this.format = 'SideBySide'; this.left = ''; this.right = ''; this.loading = false; this.showToolbar = true; this.showBtnToolbar = true; this.synchronizeScrolling = true; this.compareResults = new EventEmitter(); this.subscriptions = []; this.tableRows = []; this.filteredTableRows = []; this.tableRowsLineByLine = []; this.filteredTableRowsLineByLine = []; this.diffsCount = 0; this.formatOptions = [ { id: 'side-by-side', name: 'side-by-side', label: 'Side by Side', value: 'SideBySide', icon: 'la-code', }, { id: 'line-by-line', name: 'line-by-line', label: 'Line by Line', value: 'LineByLine', icon: 'la-file-text', }, ]; } get hideMatchingLines() { return this._hideMatchingLines; } set hideMatchingLines(hide) { this.hideMatchingLinesChanged(hide); } ngOnInit() { this.loading = true; if (this.diffContent) { this.subscriptions.push(this.diffContent.subscribe(content => { this.loading = true; this.left = content.leftContent; this.right = content.rightContent; this.renderDiffs() .then(() => { this.cd.detectChanges(); this.loading = false; }) .catch(() => (this.loading = false)); })); } this.renderDiffs() .then(() => (this.loading = false)) .catch(e => (this.loading = false)); } ngAfterViewInit() { this.initScrollListener(); } ngOnDestroy() { if (this.subscriptions) { this.subscriptions.forEach(subscription => subscription.unsubscribe()); } } hideMatchingLinesChanged(value) { this._hideMatchingLines = value; if (this.hideMatchingLines) { this.filteredTableRows = this.tableRows.filter(row => (row.leftContent && row.leftContent.prefix === '-') || (row.rightContent && row.rightContent.prefix === '+')); this.filteredTableRowsLineByLine = this.tableRowsLineByLine.filter(row => (row.leftContent && row.leftContent.prefix === '-') || (row.rightContent && row.rightContent.prefix === '+')); } else { this.filteredTableRows = this.tableRows; this.filteredTableRowsLineByLine = this.tableRowsLineByLine; } } setDiffTableFormat(format) { this.format = format; } renderDiffs() { return __awaiter(this, void 0, void 0, function* () { try { this.diffsCount = 0; this.tableRows = yield this.diff.getDiffsByLines(this.left, this.right); this.tableRowsLineByLine = this.tableRows.reduce((tableLineByLine, row) => { if (!tableLineByLine) { tableLineByLine = []; } if (row.hasDiffs) { if (row.leftContent) { tableLineByLine.push({ leftContent: row.leftContent, rightContent: null, belongTo: row.belongTo, hasDiffs: true, numDiffs: row.numDiffs, }); } if (row.rightContent) { tableLineByLine.push({ leftContent: null, rightContent: row.rightContent, belongTo: row.belongTo, hasDiffs: true, numDiffs: row.numDiffs, }); } } else { tableLineByLine.push(row); } return tableLineByLine; }, []); this.diffsCount = this.tableRows.filter(row => row.hasDiffs).length; this.filteredTableRows = this.tableRows; this.filteredTableRowsLineByLine = this.tableRowsLineByLine; this.emitCompareResultsEvent(); } catch (e) { throw e; } }); } emitCompareResultsEvent() { const diffResults = { hasDiff: this.diffsCount > 0, diffsCount: this.diffsCount, rowsWithDiff: this.tableRows .filter(row => row.hasDiffs) .map(row => ({ leftLineNumber: row.leftContent ? row.leftContent.lineNumber : null, rightLineNumber: row.rightContent ? row.rightContent.lineNumber : null, numDiffs: row.numDiffs, })), }; this.compareResults.next(diffResults); } trackTableRows(index, row) { return row && row.leftContent ? row.leftContent.lineContent : row && row.rightContent ? row.rightContent.lineContent : undefined; } trackDiffs(index, diff) { return diff && diff.content ? diff.content : undefined; } initScrollListener() { this.subscriptions.push(this.scrollService.scrolled().subscribe((scrollableEv) => { if (scrollableEv && this.synchronizeScrolling) { const scrollableId = scrollableEv.getElementRef().nativeElement.id; const nonScrolledContainer = this.containers.find(container => container.id !== scrollableId); if (nonScrolledContainer) { nonScrolledContainer.element.scrollTo({ top: scrollableEv.measureScrollOffset('top'), left: scrollableEv.measureScrollOffset('left'), }); } } })); } }; NgxTextDiffComponent.ctorParameters = () => [ { type: ScrollDispatcher }, { type: NgxTextDiffService }, { type: ChangeDetectorRef } ]; __decorate([ ViewChildren(ContainerDirective), __metadata("design:type", QueryList) ], NgxTextDiffComponent.prototype, "containers", void 0); __decorate([ Input(), __metadata("design:type", String) ], NgxTextDiffComponent.prototype, "format", void 0); __decorate([ Input(), __metadata("design:type", Object) ], NgxTextDiffComponent.prototype, "left", void 0); __decorate([ Input(), __metadata("design:type", Object) ], NgxTextDiffComponent.prototype, "right", void 0); __decorate([ Input(), __metadata("design:type", Observable) ], NgxTextDiffComponent.prototype, "diffContent", void 0); __decorate([ Input(), __metadata("design:type", Object) ], NgxTextDiffComponent.prototype, "loading", void 0); __decorate([ Input(), __metadata("design:type", Object) ], NgxTextDiffComponent.prototype, "showToolbar", void 0); __decorate([ Input(), __metadata("design:type", Object) ], NgxTextDiffComponent.prototype, "showBtnToolbar", void 0); __decorate([ Input(), __metadata("design:type", Boolean), __metadata("design:paramtypes", [Boolean]) ], NgxTextDiffComponent.prototype, "hideMatchingLines", null); __decorate([ Input(), __metadata("design:type", String) ], NgxTextDiffComponent.prototype, "outerContainerClass", void 0); __decorate([ Input(), __metadata("design:type", Object) ], NgxTextDiffComponent.prototype, "outerContainerStyle", void 0); __decorate([ Input(), __metadata("design:type", String) ], NgxTextDiffComponent.prototype, "toolbarClass", void 0); __decorate([ Input(), __metadata("design:type", Object) ], NgxTextDiffComponent.prototype, "toolbarStyle", void 0); __decorate([ Input(), __metadata("design:type", String) ], NgxTextDiffComponent.prototype, "compareRowsClass", void 0); __decorate([ Input(), __metadata("design:type", Object) ], NgxTextDiffComponent.prototype, "compareRowsStyle", void 0); __decorate([ Input(), __metadata("design:type", Object) ], NgxTextDiffComponent.prototype, "synchronizeScrolling", void 0); __decorate([ Output(), __metadata("design:type", Object) ], NgxTextDiffComponent.prototype, "compareResults", void 0); NgxTextDiffComponent = __decorate([ Component({ selector: 'td-ngx-text-diff', template: "<td-loader-spinner [active]=\"loading\"></td-loader-spinner>\r\n<div class=\"td-wrapper\" [ngClass]=\"outerContainerClass\" [ngStyle]=\"outerContainerStyle\" *ngIf=\"!loading\">\r\n\r\n <div [ngClass]=\"toolbarClass\" [ngStyle]=\"toolbarStyle\" *ngIf=\"showToolbar\">\r\n <div class=\"td-toolbar-show-diff\">\r\n <label class=\"td-checkbox-container\">\r\n Only Show Lines with Differences ({{ diffsCount }})\r\n <input type=\"checkbox\" id=\"showDiffs\" [ngModel]=\"hideMatchingLines\" (ngModelChange)=\"hideMatchingLinesChanged($event)\" />\r\n <span class=\"checkmark\"></span>\r\n </label>\r\n </div>\r\n </div>\r\n\r\n <div class=\"td-toolbar-select-format\" *ngIf=\"showToolbar && showBtnToolbar\">\r\n <div class=\"td-btn-group td-btn-group-toggle\" data-toggle=\"buttons\">\r\n <button\r\n *ngFor=\"let option of formatOptions\"\r\n [ngClass]=\"{ active: format === option.value, disabled: !!option.disabled }\"\r\n [name]=\"option.name\"\r\n [id]=\"option.id\"\r\n [disabled]=\"!!option.disabled\"\r\n (click)=\"setDiffTableFormat(option.value)\"\r\n >\r\n {{ option.label }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"td-table-wrapper\" [ngClass]=\"compareRowsClass\" [ngStyle]=\"compareRowsStyle\">\r\n <!-- Right side-by-side -->\r\n <div class=\"td-table-container side-by-side\" *ngIf=\"format === 'SideBySide'\" id=\"td-left-compare-container\" tdContainer cdkScrollable>\r\n <table class=\"td-table\">\r\n <tbody>\r\n <tr *ngFor=\"let row of filteredTableRows; trackBy: trackTableRows\">\r\n <td\r\n scope=\"row\"\r\n class=\"fit-column line-number-col\"\r\n [ngClass]=\"{ 'delete-row': row.leftContent?.prefix === '-', 'empty-row': !row.leftContent?.lineContent }\"\r\n >\r\n {{ row.leftContent?.lineNumber !== -1 ? row.leftContent?.lineNumber : ' ' }}\r\n </td>\r\n <td\r\n class=\"fit-column prefix-col\"\r\n [ngClass]=\"{ 'delete-row': row.leftContent?.prefix === '-', 'empty-row': !row.leftContent?.lineContent }\"\r\n >\r\n <span>{{ row.leftContent?.prefix || ' ' }}</span>\r\n </td>\r\n <td\r\n class=\"content-col\"\r\n [ngClass]=\"{ 'delete-row': row.leftContent?.prefix === '-', 'empty-row': !row.leftContent?.lineContent }\"\r\n *ngIf=\"!row.hasDiffs\"\r\n >\r\n <span [innerHTML]=\"row.leftContent?.lineContent | formatLine\"></span>\r\n </td>\r\n <td\r\n class=\"content-col\"\r\n [ngClass]=\"{ 'delete-row': row.leftContent?.prefix === '-', 'empty-row': !row.leftContent?.lineContent }\"\r\n *ngIf=\"row.hasDiffs\"\r\n >\r\n <span\r\n [innerHTML]=\"diff.content | formatLine\"\r\n [ngClass]=\"{ highlight: diff.isDiff }\"\r\n *ngFor=\"let diff of row.leftContent?.lineDiffs; trackBy: trackDiffs\"\r\n ></span>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n <!-- Left side-by-side -->\r\n <div class=\"td-table-container side-by-side\" *ngIf=\"format === 'SideBySide'\" id=\"td-right-compare-container\" tdContainer cdkScrollable>\r\n <table class=\"td-table\">\r\n <tbody>\r\n <tr *ngFor=\"let row of filteredTableRows; trackBy: trackTableRows\">\r\n <td\r\n scope=\"row\"\r\n class=\"fit-column line-number-col\"\r\n [ngClass]=\"{ 'insert-row': row.rightContent?.prefix === '+', 'empty-row': !row.rightContent?.lineContent }\"\r\n >\r\n {{ row.rightContent?.lineNumber !== -1 ? row.rightContent?.lineNumber : ' ' }}\r\n </td>\r\n <td\r\n class=\"fit-column prefix-col\"\r\n [ngClass]=\"{ 'insert-row': row.rightContent?.prefix === '+', 'empty-row': !row.rightContent?.lineContent }\"\r\n >\r\n <span>{{ row.rightContent?.prefix || ' ' }}</span>\r\n </td>\r\n <td\r\n class=\"content-col\"\r\n [ngClass]=\"{ 'insert-row': row.rightContent?.prefix === '+', 'empty-row': !row.rightContent?.lineContent }\"\r\n *ngIf=\"!row.hasDiffs\"\r\n >\r\n <span [innerHTML]=\"row.rightContent?.lineContent | formatLine\"></span>\r\n </td>\r\n <td\r\n class=\"content-col\"\r\n [ngClass]=\"{ 'insert-row': row.rightContent?.prefix === '+', 'empty-row': !row.rightContent?.lineContent }\"\r\n *ngIf=\"row.hasDiffs\"\r\n >\r\n <span\r\n [innerHTML]=\"diff.content | formatLine\"\r\n [ngClass]=\"{ highlight: diff.isDiff }\"\r\n *ngFor=\"let diff of row.rightContent?.lineDiffs; trackBy: trackDiffs\"\r\n ></span>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n <!-- Line By Line - combined table -->\r\n <div class=\"td-table-container line-by-line\" *ngIf=\"format === 'LineByLine'\">\r\n <table class=\"td-table\">\r\n <tbody>\r\n <tr *ngFor=\"let row of filteredTableRowsLineByLine; trackBy: trackTableRows\">\r\n <td scope=\"row\" class=\"fit-column line-number-col-left\">{{ row.leftContent?.lineNumber }}</td>\r\n <td scope=\"row\" class=\"fit-column line-number-col\">{{ row.rightContent?.lineNumber }}</td>\r\n <td\r\n class=\"fit-column prefix-col\"\r\n [ngClass]=\"{ 'delete-row': row.leftContent?.prefix === '-', 'insert-row': row.rightContent?.prefix === '+' }\"\r\n >\r\n <span>{{ row.leftContent?.prefix || row.rightContent?.prefix || ' ' }}</span>\r\n </td>\r\n <td\r\n class=\"content-col\"\r\n [ngClass]=\"{ 'delete-row': row.leftContent?.prefix === '-', 'insert-row': row.rightContent?.prefix === '+' }\"\r\n *ngIf=\"!row.hasDiffs\"\r\n >\r\n <span [innerHTML]=\"row.leftContent?.lineContent | formatLine\"></span>\r\n </td>\r\n <td\r\n class=\"content-col\"\r\n [ngClass]=\"{ 'delete-row': row.leftContent?.prefix === '-', 'insert-row': row.rightContent?.prefix === '+' }\"\r\n *ngIf=\"row.hasDiffs && row.leftContent && row.leftContent?.lineDiffs.length !== 0\"\r\n >\r\n <span\r\n [innerHTML]=\"diff.content | formatLine\"\r\n [ngClass]=\"{ highlight: diff.isDiff }\"\r\n *ngFor=\"let diff of row.leftContent?.lineDiffs; trackBy: trackDiffs\"\r\n ></span>\r\n </td>\r\n <td\r\n class=\"content-col\"\r\n [ngClass]=\"{ 'delete-row': row.leftContent?.prefix === '-', 'insert-row': row.rightContent?.prefix === '+' }\"\r\n *ngIf=\"row.hasDiffs && row.rightContent && row.rightContent?.lineDiffs.length !== 0\"\r\n >\r\n <span\r\n [innerHTML]=\"diff.content | formatLine\"\r\n [ngClass]=\"{ highlight: diff.isDiff }\"\r\n *ngFor=\"let diff of row.rightContent?.lineDiffs; trackBy: trackDiffs\"\r\n ></span>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".td-wrapper{display:grid;width:100%;grid-row-gap:10px;grid-template-columns:repeat(2,[col] 50%);grid-template-rows:repeat(2,[row] auto);background-color:#fff;color:#444}.td-toolbar-show-diff{grid-column:1;grid-row:1}.td-toolbar-select-format{margin-left:auto;grid-column:2;grid-row:1}.td-table-container{grid-column:1/2;grid-row:2;width:100%;max-width:100%;overflow-x:auto}.td-table-wrapper{display:flex;width:200%}.td-table{border:1px solid #a9a9a9;max-height:50vh;width:100%;max-width:100%}.fit-column{width:1px;white-space:nowrap}.line-number-col{position:relative;position:-webkit-sticky;position:sticky;left:0;top:auto;border-right:1px solid #ddd;color:#999;text-align:right;background-color:#f7f7f7;padding-left:10px;padding-right:10px;font-size:87.5%}.line-number-col-left{color:#999;padding-left:10px;padding-right:10px;text-align:right;background-color:#f7f7f7;font-size:87.5%}.insert-row,.insert-row>.line-number-col{background-color:#dfd;border-color:#b4e2b4}.delete-row,.delete-row>.line-number-col{background-color:#fee8e9;border-color:#e9aeae}.empty-row{background-color:#f7f7f7;height:24px}.td-table td{border-top:0;padding-top:0;padding-bottom:0;white-space:nowrap;max-width:50%}pre{margin-bottom:0}td.content-col{padding:0;margin:0;line-height:24px}td.prefix-col{padding-left:10px;padding-right:10px;line-height:24px}.td-btn-group{border-radius:4px}.td-btn-group button{background-color:rgba(23,162,184,.7);border:1px solid #17a2b8;color:#fff;cursor:pointer;float:left}.td-btn-group button:not(:last-child){border-right:none}.td-btn-group button:first-child{-webkit-border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-topleft:4px;-moz-border-radius-bottomleft:4px;border-top-left-radius:4px;border-bottom-left-radius:4px}.td-btn-group button:last-child{-webkit-border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px;border-top-right-radius:4px;border-bottom-right-radius:4px}.td-btn-group:after{content:'';clear:both;display:table}.td-btn-group button.active,.td-btn-group button:hover{background-color:#17a2b8}.td-checkbox-container{display:block;position:relative;padding-left:21px;margin-bottom:0;cursor:pointer;font-size:16px;line-height:28px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.td-checkbox-container input{position:absolute;opacity:0;cursor:pointer;height:0;width:0}.checkmark{position:absolute;top:7px;left:0;height:16px;width:16px;background-color:#eee}.td-checkbox-container:hover input~.checkmark{background-color:#ccc}.td-checkbox-container input:checked~.checkmark{background-color:#17a2b8}.checkmark:after{content:\"\";position:absolute;display:none}.td-checkbox-container input:checked~.checkmark:after{display:block}.td-checkbox-container .checkmark:after{left:5px;top:3px;width:5px;height:10px;border:solid #fff;border-width:0 3px 3px 0;transform:rotate(45deg)}.insert-row>.highlight{background-color:#acf2bd!important}.delete-row>.highlight{background-color:#fdb8c0!important}"] }), __metadata("design:paramtypes", [ScrollDispatcher, NgxTextDiffService, ChangeDetectorRef]) ], NgxTextDiffComponent); export { NgxTextDiffComponent }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXRleHQtZGlmZi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtdGV4dC1kaWZmLyIsInNvdXJjZXMiOlsibGliL25neC10ZXh0LWRpZmYuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxLQUFLLEVBQ0wsU0FBUyxFQUNULE1BQU0sRUFDTixNQUFNLEVBQ04sWUFBWSxFQUNaLFlBQVksRUFDWixTQUFTLEVBQ1QsYUFBYSxFQUNkLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzdELE9BQU8sRUFBRSxVQUFVLEVBQWdCLE1BQU0sTUFBTSxDQUFDO0FBQ2hELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQU96RSxJQUFhLG9CQUFvQixHQUFqQyxNQUFhLG9CQUFvQjtJQWtEL0IsWUFBb0IsYUFBK0IsRUFBVSxJQUF3QixFQUFVLEVBQXFCO1FBQWhHLGtCQUFhLEdBQWIsYUFBYSxDQUFrQjtRQUFVLFNBQUksR0FBSixJQUFJLENBQW9CO1FBQVUsT0FBRSxHQUFGLEVBQUUsQ0FBbUI7UUFqRDVHLHVCQUFrQixHQUFHLEtBQUssQ0FBQztRQUUxQixXQUFNLEdBQW9CLFlBQVksQ0FBQztRQUN2QyxTQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ1YsVUFBSyxHQUFHLEVBQUUsQ0FBQztRQUVYLFlBQU8sR0FBRyxLQUFLLENBQUM7UUFDaEIsZ0JBQVcsR0FBRyxJQUFJLENBQUM7UUFDbkIsbUJBQWMsR0FBRyxJQUFJLENBQUM7UUFldEIseUJBQW9CLEdBQUcsSUFBSSxDQUFDO1FBQzNCLG1CQUFjLEdBQUcsSUFBSSxZQUFZLEVBQWUsQ0FBQztRQUMzRCxrQkFBYSxHQUFtQixF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LEVBQUU7OzhEQUF1QjtBQUN0QjtJQUFSLEtBQUssRUFBRTs7a0VBQTZCO0FBQzNCO0lBQVQsTUFBTSxFQUFFOzs0REFBa0Q7QUF6QmhELG9CQUFvQjtJQUxoQyxTQUFTLENBQUM7UUFDVCxRQUFRLEVBQUUsa0JBQWtCO1FBQzVCLHcvT0FBNkM7O0tBRTlDLENBQUM7cUNBbURtQyxnQkFBZ0IsRUFBZ0Isa0JBQWtCLEVBQWMsaUJBQWlCO0dBbER6RyxvQkFBb0IsQ0F1TGhDO1NBdkxZLG9CQUFvQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXHJcbiAgQ29tcG9uZW50LFxyXG4gIElucHV0LFxyXG4gIE9uRGVzdHJveSxcclxuICBPbkluaXQsXHJcbiAgT3V0cHV0LFxyXG4gIEV2ZW50RW1pdHRlcixcclxuICBWaWV3Q2hpbGRyZW4sXHJcbiAgUXVlcnlMaXN0LFxyXG4gIEFmdGVyVmlld0luaXRcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRGlmZkNvbnRlbnQsIERpZmZQYXJ0LCBEaWZmVGFibGVGb3JtYXQsIERpZmZUYWJsZUZvcm1hdE9wdGlvbiwgRGlmZlRhYmxlUm93UmVzdWx0LCBEaWZmUmVzdWx0cyB9IGZyb20gJy4vbmd4LXRleHQtZGlmZi5tb2RlbCc7XHJcbmltcG9ydCB7IE5neFRleHREaWZmU2VydmljZSB9IGZyb20gJy4vbmd4LXRleHQtZGlmZi5zZXJ2aWNlJztcclxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IENvbnRhaW5lckRpcmVjdGl2ZSB9IGZyb20gJy4vbmd4LXRleHQtZGlmZi1jb250YWluZXIuZGlyZWN0aXZlJztcclxuaW1wb3J0IHsgU2Nyb2xsRGlzcGF0Y2hlciwgQ2RrU2Nyb2xsYWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9zY3JvbGxpbmcnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICd0ZC1uZ3gtdGV4dC1kaWZmJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vbmd4LXRleHQtZGlmZi5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmxzOiBbJy4vbmd4LXRleHQtZGlmZi5jb21wb25lbnQuY3NzJ10sXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBOZ3hUZXh0RGlmZkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcclxuICBwcml2YXRlIF9oaWRlTWF0Y2hpbmdMaW5lcyA9IGZhbHNlO1xyXG4gIEBWaWV3Q2hpbGRyZW4oQ29udGFpbmVyRGlyZWN0aXZlKSBjb250YWluZXJzOiBRdWVyeUxpc3Q8Q29udGFpbmVyRGlyZWN0aXZlPjtcclxuICBASW5wdXQoKSBmb3JtYXQ6IERpZmZUYWJsZUZvcm1hdCA9ICdTaWRlQnlTaWRlJztcclxuICBASW5wdXQoKSBsZWZ0ID0gJyc7XHJcbiAgQElucHV0KCkgcmlnaHQgPSAnJztcclxuICBASW5wdXQoKSBkaWZmQ29udGVudDogT2JzZXJ2YWJsZTxEaWZmQ29udGVudD47XHJcbiAgQElucHV0KCkgbG9hZGluZyA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIHNob3dUb29sYmFyID0gdHJ1ZTtcclxuICBASW5wdXQoKSBzaG93QnRuVG9vbGJhciA9IHRydWU7XHJcbiAgQElucHV0KClcclxuICBnZXQgaGlkZU1hdGNoaW5nTGluZXMoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5faGlkZU1hdGNoaW5nTGluZXM7XHJcbiAgfVxyXG5cclxuICBzZXQgaGlkZU1hdGNoaW5nTGluZXMoaGlkZTogYm9vbGVhbikge1xyXG4gICAgdGhpcy5oaWRlTWF0Y2hpbmdMaW5lc0NoYW5nZWQoaGlkZSk7XHJcbiAgfVxyXG4gIEBJbnB1dCgpIG91dGVyQ29udGFpbmVyQ2xhc3M6IHN0cmluZztcclxuICBASW5wdXQoKSBvdXRlckNvbnRhaW5lclN0eWxlOiBhbnk7XHJcbiAgQElucHV0KCkgdG9vbGJhckNsYXNzOiBzdHJpbmc7XHJcbiAgQElucHV0KCkgdG9vbGJhclN0eWxlOiBhbnk7XHJcbiAgQElucHV0KCkgY29tcGFyZVJvd3NDbGFzczogc3RyaW5nO1xyXG4gIEBJbnB1dCgpIGNvbXBhcmVSb3dzU3R5bGU6IGFueTtcclxuICBASW5wdXQoKSBzeW5jaHJvbml6ZVNjcm9sbGluZyA9IHRydWU7XHJcbiAgQE91dHB1dCgpIGNvbXBhcmVSZXN1bHRzID0gbmV3IEV2ZW50RW1pdHRlcjxEaWZmUmVzdWx0cz4oKTtcclxuICBzdWJzY3JpcHRpb25zOiBTdWJzY3JpcHRpb25bXSA9IFtdO1xyXG4gIHRhYmxlUm93czogRGlmZlRhYmxlUm93UmVzdWx0W10gPSBbXTtcclxuICBmaWx0ZXJlZFRhYmxlUm93czogRGlmZlRhYmxlUm93UmVzdWx0W10gPSBbXTtcclxuICB0YWJsZVJvd3NMaW5lQnlMaW5lOiBEaWZmVGFibGVSb3dSZXN1bHRbXSA9IFtdO1xyXG4gIGZpbHRlcmVkVGFibGVSb3dzTGluZUJ5TGluZTogRGlmZlRhYmxlUm93UmVzdWx0W10gPSBbXTtcclxuICBkaWZmc0NvdW50ID0gMDtcclxuXHJcbiAgZm9ybWF0T3B0aW9uczogRGlmZlRhYmxlRm9ybWF0T3B0aW9uW10gPSBbXHJcbiAgICB7XHJcbiAgICAgIGlkOiAnc2lkZS1ieS1zaWRlJyxcclxuICAgICAgbmFtZTogJ3NpZGUtYnktc2lkZScsXHJcbiAgICAgIGxhYmVsOiAnU2lkZSBieSBTaWRlJyxcclxuICAgICAgdmFsdWU6ICdTaWRlQnlTaWRlJyxcclxuICAgICAgaWNvbjogJ2xhLWNvZGUnLFxyXG4gICAgfSxcclxuICAgIHtcclxuICAgICAgaWQ6ICdsaW5lLWJ5LWxpbmUnLFxyXG4gICAgICBuYW1lOiAnbGluZS1ieS1saW5lJyxcclxuICAgICAgbGFiZWw6ICdMaW5lIGJ5IExpbmUnLFxyXG4gICAgICB2YWx1ZTogJ0xpbmVCeUxpbmUnLFxyXG4gICAgICBpY29uOiAnbGEtZmlsZS10ZXh0JyxcclxuICAgIH0sXHJcbiAgXTtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBzY3JvbGxTZXJ2aWNlOiBTY3JvbGxEaXNwYXRjaGVyLCBwcml2YXRlIGRpZmY6IE5neFRleHREaWZmU2VydmljZSwgcHJpdmF0ZSBjZDogQ2hhbmdlRGV0ZWN0b3JSZWYpIHt9XHJcblxyXG4gIG5nT25Jbml0KCkge1xyXG4gICAgdGhpcy5sb2FkaW5nID0gdHJ1ZTtcclxuICAgIGlmICh0aGlzLmRpZmZDb250ZW50KSB7XHJcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKFxyXG4gICAgICAgIHRoaXMuZGlmZkNvbnRlbnQuc3Vic2NyaWJlKGNvbnRlbnQgPT4ge1xyXG4gICAgICAgICAgdGhpcy5sb2FkaW5nID0gdHJ1ZTtcclxuICAgICAgICAgIHRoaXMubGVmdCA9IGNvbnRlbnQubGVmdENvbnRlbnQ7XHJcbiAgICAgICAgICB0aGlzLnJpZ2h0ID0gY29udGVudC5yaWdodENvbnRlbnQ7XHJcbiAgICAgICAgICB0aGlzLnJlbmRlckRpZmZzKClcclxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICAgIHRoaXMuY2QuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gICAgICAgICAgICAgIHRoaXMubG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAuY2F0Y2goKCkgPT4gKHRoaXMubG9hZGluZyA9IGZhbHNlKSk7XHJcbiAgICAgICAgfSlcclxuICAgICAgKTtcclxuICAgIH1cclxuICAgIHRoaXMucmVuZGVyRGlmZnMoKVxyXG4gICAgICAudGhlbigoKSA9PiAodGhpcy5sb2FkaW5nID0gZmFsc2UpKVxyXG4gICAgICAuY2F0Y2goZSA9PiAodGhpcy5sb2FkaW5nID0gZmFsc2UpKTtcclxuICB9XHJcblxyXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcclxuICAgIHRoaXMuaW5pdFNjcm9sbExpc3RlbmVyKCk7XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnN1YnNjcmlwdGlvbnMpIHtcclxuICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLmZvckVhY2goc3Vic2NyaXB0aW9uID0+IHN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGhpZGVNYXRjaGluZ0xpbmVzQ2hhbmdlZCh2YWx1ZTogYm9vbGVhbikge1xyXG4gICAgdGhpcy5faGlkZU1hdGNoaW5nTGluZXMgPSB2YWx1ZTtcclxuICAgIGlmICh0aGlzLmhpZGVNYXRjaGluZ0xpbmVzKSB7XHJcbiAgICAgIHRoaXMuZmlsdGVyZWRUYWJsZVJvd3MgPSB0aGlzLnRhYmxlUm93cy5maWx0ZXIoXHJcbiAgICAgICAgcm93ID0+IChyb3cubGVmdENvbnRlbnQgJiYgcm93LmxlZnRDb250ZW50LnByZWZpeCA9PT0gJy0nKSB8fCAocm93LnJpZ2h0Q29udGVudCAmJiByb3cucmlnaHRDb250ZW50LnByZWZpeCA9PT0gJysnKVxyXG4gICAgICApO1xyXG4gICAgICB0aGlzLmZpbHRlcmVkVGFibGVSb3dzTGluZUJ5TGluZSA9IHRoaXMudGFibGVSb3dzTGluZUJ5TGluZS5maWx0ZXIoXHJcbiAgICAgICAgcm93ID0+IChyb3cubGVmdENvbnRlbnQgJiYgcm93LmxlZnRDb250ZW50LnByZWZpeCA9PT0gJy0nKSB8fCAocm93LnJpZ2h0Q29udGVudCAmJiByb3cucmlnaHRDb250ZW50LnByZWZpeCA9PT0gJysnKVxyXG4gICAgICApO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5maWx0ZXJlZFRhYmxlUm93cyA9IHRoaXMudGFibGVSb3dzO1xyXG4gICAgICB0aGlzLmZpbHRlcmVkVGFibGVSb3dzTGluZUJ5TGluZSA9IHRoaXMudGFibGVSb3dzTGluZUJ5TGluZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHNldERpZmZUYWJsZUZvcm1hdChmb3JtYXQ6IERpZmZUYWJsZUZvcm1hdCkge1xyXG4gICAgdGhpcy5mb3JtYXQgPSBmb3JtYXQ7XHJcbiAgfVxyXG5cclxuICBhc3luYyByZW5kZXJEaWZmcygpIHtcclxuICAgIHRyeSB7XHJcbiAgICAgIHRoaXMuZGlmZnNDb3VudCA9IDA7XHJcbiAgICAgIHRoaXMudGFibGVSb3dzID0gYXdhaXQgdGhpcy5kaWZmLmdldERpZmZzQnlMaW5lcyh0aGlzLmxlZnQsIHRoaXMucmlnaHQpO1xyXG4gICAgICB0aGlzLnRhYmxlUm93c0xpbmVCeUxpbmUgPSB0aGlzLnRhYmxlUm93cy5yZWR1Y2UoKHRhYmxlTGluZUJ5TGluZTogRGlmZlRhYmxlUm93UmVzdWx0W10sIHJvdzogRGlmZlRhYmxlUm93UmVzdWx0KSA9PiB7XHJcbiAgICAgICAgaWYgKCF0YWJsZUxpbmVCeUxpbmUpIHtcclxuICAgICAgICAgIHRhYmxlTGluZUJ5TGluZSA9IFtdO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAocm93Lmhhc0RpZmZzKSB7XHJcbiAgICAgICAgICBpZiAocm93LmxlZnRDb250ZW50KSB7XHJcbiAgICAgICAgICAgIHRhYmxlTGluZUJ5TGluZS5wdXNoKHtcclxuICAgICAgICAgICAgICBsZWZ0Q29udGVudDogcm93LmxlZnRDb250ZW50LFxyXG4gICAgICAgICAgICAgIHJpZ2h0Q29udGVudDogbnVsbCxcclxuICAgICAgICAgICAgICBiZWxvbmdUbzogcm93LmJlbG9uZ1RvLFxyXG4gICAgICAgICAgICAgIGhhc0RpZmZzOiB0cnVlLFxyXG4gICAgICAgICAgICAgIG51bURpZmZzOiByb3cubnVtRGlmZnMsXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgaWYgKHJvdy5yaWdodENvbnRlbnQpIHtcclxuICAgICAgICAgICAgdGFibGVMaW5lQnlMaW5lLnB1c2goe1xyXG4gICAgICAgICAgICAgIGxlZnRDb250ZW50OiBudWxsLFxyXG4gICAgICAgICAgICAgIHJpZ2h0Q29udGVudDogcm93LnJpZ2h0Q29udGVudCxcclxuICAgICAgICAgICAgICBiZWxvbmdUbzogcm93LmJlbG9uZ1RvLFxyXG4gICAgICAgICAgICAgIGhhc0RpZmZzOiB0cnVlLFxyXG4gICAgICAgICAgICAgIG51bURpZmZzOiByb3cubnVtRGlmZnMsXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0YWJsZUxpbmVCeUxpbmUucHVzaChyb3cpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHRhYmxlTGluZUJ5TGluZTtcclxuICAgICAgfSwgW10pO1xyXG4gICAgICB0aGlzLmRpZmZzQ291bnQgPSB0aGlzLnRhYmxlUm93cy5maWx0ZXIocm93ID0+IHJvdy5oYXNEaWZmcykubGVuZ3RoO1xyXG4gICAgICB0aGlzLmZpbHRlcmVkVGFibGVSb3dzID0gdGhpcy50YWJsZVJvd3M7XHJcbiAgICAgIHRoaXMuZmlsdGVyZWRUYWJsZVJvd3NMaW5lQnlMaW5lID0gdGhpcy50YWJsZVJvd3NMaW5lQnlMaW5lO1xyXG4gICAgICB0aGlzLmVtaXRDb21wYXJlUmVzdWx0c0V2ZW50KCk7XHJcbiAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgIHRocm93IGU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBlbWl0Q29tcGFyZVJlc3VsdHNFdmVudCgpIHtcclxuICAgIGNvbnN0IGRpZmZSZXN1bHRzOiBEaWZmUmVzdWx0cyA9IHtcclxuICAgICAgaGFzRGlmZjogdGhpcy5kaWZmc0NvdW50ID4gMCxcclxuICAgICAgZGlmZnNDb3VudDogdGhpcy5kaWZmc0NvdW50LFxyXG4gICAgICByb3dzV2l0aERpZmY6IHRoaXMudGFibGVSb3dzXHJcbiAgICAgICAgLmZpbHRlcihyb3cgPT4gcm93Lmhhc0RpZmZzKVxyXG4gICAgICAgIC5tYXAocm93ID0+ICh7XHJcbiAgICAgICAgICBsZWZ0TGluZU51bWJlcjogcm93LmxlZnRDb250ZW50ID8gcm93LmxlZnRDb250ZW50LmxpbmVOdW1iZXIgOiBudWxsLFxyXG4gICAgICAgICAgcmlnaHRMaW5lTnVtYmVyOiByb3cucmlnaHRDb250ZW50ID8gcm93LnJpZ2h0Q29udGVudC5saW5lTnVtYmVyIDogbnVsbCxcclxuICAgICAgICAgIG51bURpZmZzOiByb3cubnVtRGlmZnMsXHJcbiAgICAgICAgfSkpLFxyXG4gICAgfTtcclxuXHJcbiAgICB0aGlzLmNvbXBhcmVSZXN1bHRzLm5leHQoZGlmZlJlc3VsdHMpO1xyXG4gIH1cclxuXHJcbiAgdHJhY2tUYWJsZVJvd3MoaW5kZXgsIHJvdzogRGlmZlRhYmxlUm93UmVzdWx0KSB7XHJcbiAgICByZXR1cm4gcm93ICYmIHJvdy5sZWZ0Q29udGVudCA/IHJvdy5sZWZ0Q29udGVudC5saW5lQ29udGVudCA6IHJvdyAmJiByb3cucmlnaHRDb250ZW50ID8gcm93LnJpZ2h0Q29udGVudC5saW5lQ29udGVudCA6IHVuZGVmaW5lZDtcclxuICB9XHJcblxyXG4gIHRyYWNrRGlmZnMoaW5kZXgsIGRpZmY6IERpZmZQYXJ0KSB7XHJcbiAgICByZXR1cm4gZGlmZiAmJiBkaWZmLmNvbnRlbnQgPyBkaWZmLmNvbnRlbnQgOiB1bmRlZmluZWQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGluaXRTY3JvbGxMaXN0ZW5lcigpIHtcclxuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKHRoaXMuc2Nyb2xsU2VydmljZS5zY3JvbGxlZCgpLnN1YnNjcmliZSgoc2Nyb2xsYWJsZUV2OiBDZGtTY3JvbGxhYmxlKSA9PiB7XHJcbiAgICAgIGlmIChzY3JvbGxhYmxlRXYgJiYgdGhpcy5zeW5jaHJvbml6ZVNjcm9sbGluZykge1xyXG4gICAgICAgIGNvbnN0IHNjcm9sbGFibGVJZCA9IHNjcm9sbGFibGVFdi5nZXRFbGVtZW50UmVmKCkubmF0aXZlRWxlbWVudC5pZDtcclxuICAgICAgICBjb25zdCBub25TY3JvbGxlZENvbnRhaW5lcjogQ29udGFpbmVyRGlyZWN0aXZlID0gdGhpcy5jb250YWluZXJzLmZpbmQoY29udGFpbmVyID0+IGNvbnRhaW5lci5pZCAhPT0gc2Nyb2xsYWJsZUlkKTtcclxuICAgICAgICBpZiAobm9uU2Nyb2xsZWRDb250YWluZXIpIHtcclxuICAgICAgICAgIG5vblNjcm9sbGVkQ29udGFpbmVyLmVsZW1lbnQuc2Nyb2xsVG8oe1xyXG4gICAgICAgICAgICB0b3A6IHNjcm9sbGFibGVFdi5tZWFzdXJlU2Nyb2xsT2Zmc2V0KCd0b3AnKSxcclxuICAgICAgICAgICAgbGVmdDogc2Nyb2xsYWJsZUV2Lm1lYXN1cmVTY3JvbGxPZmZzZXQoJ2xlZnQnKSxcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSkpO1xyXG4gIH1cclxufVxyXG4iXX0=