UNPKG

ngx-text-diff

Version:
270 lines 41.1 kB
import { __awaiter, __decorate, __generator, __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'; var NgxTextDiffComponent = /** @class */ (function () { function NgxTextDiffComponent(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', }, ]; } Object.defineProperty(NgxTextDiffComponent.prototype, "hideMatchingLines", { get: function () { return this._hideMatchingLines; }, set: function (hide) { this.hideMatchingLinesChanged(hide); }, enumerable: true, configurable: true }); NgxTextDiffComponent.prototype.ngOnInit = function () { var _this = this; this.loading = true; if (this.diffContent) { this.subscriptions.push(this.diffContent.subscribe(function (content) { _this.loading = true; _this.left = content.leftContent; _this.right = content.rightContent; _this.renderDiffs() .then(function () { _this.cd.detectChanges(); _this.loading = false; }) .catch(function () { return (_this.loading = false); }); })); } this.renderDiffs() .then(function () { return (_this.loading = false); }) .catch(function (e) { return (_this.loading = false); }); }; NgxTextDiffComponent.prototype.ngAfterViewInit = function () { this.initScrollListener(); }; NgxTextDiffComponent.prototype.ngOnDestroy = function () { if (this.subscriptions) { this.subscriptions.forEach(function (subscription) { return subscription.unsubscribe(); }); } }; NgxTextDiffComponent.prototype.hideMatchingLinesChanged = function (value) { this._hideMatchingLines = value; if (this.hideMatchingLines) { this.filteredTableRows = this.tableRows.filter(function (row) { return (row.leftContent && row.leftContent.prefix === '-') || (row.rightContent && row.rightContent.prefix === '+'); }); this.filteredTableRowsLineByLine = this.tableRowsLineByLine.filter(function (row) { return (row.leftContent && row.leftContent.prefix === '-') || (row.rightContent && row.rightContent.prefix === '+'); }); } else { this.filteredTableRows = this.tableRows; this.filteredTableRowsLineByLine = this.tableRowsLineByLine; } }; NgxTextDiffComponent.prototype.setDiffTableFormat = function (format) { this.format = format; }; NgxTextDiffComponent.prototype.renderDiffs = function () { return __awaiter(this, void 0, void 0, function () { var _a, e_1; return __generator(this, function (_b) { switch (_b.label) { case 0: _b.trys.push([0, 2, , 3]); this.diffsCount = 0; _a = this; return [4 /*yield*/, this.diff.getDiffsByLines(this.left, this.right)]; case 1: _a.tableRows = _b.sent(); this.tableRowsLineByLine = this.tableRows.reduce(function (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(function (row) { return row.hasDiffs; }).length; this.filteredTableRows = this.tableRows; this.filteredTableRowsLineByLine = this.tableRowsLineByLine; this.emitCompareResultsEvent(); return [3 /*break*/, 3]; case 2: e_1 = _b.sent(); throw e_1; case 3: return [2 /*return*/]; } }); }); }; NgxTextDiffComponent.prototype.emitCompareResultsEvent = function () { var diffResults = { hasDiff: this.diffsCount > 0, diffsCount: this.diffsCount, rowsWithDiff: this.tableRows .filter(function (row) { return row.hasDiffs; }) .map(function (row) { return ({ leftLineNumber: row.leftContent ? row.leftContent.lineNumber : null, rightLineNumber: row.rightContent ? row.rightContent.lineNumber : null, numDiffs: row.numDiffs, }); }), }; this.compareResults.next(diffResults); }; NgxTextDiffComponent.prototype.trackTableRows = function (index, row) { return row && row.leftContent ? row.leftContent.lineContent : row && row.rightContent ? row.rightContent.lineContent : undefined; }; NgxTextDiffComponent.prototype.trackDiffs = function (index, diff) { return diff && diff.content ? diff.content : undefined; }; NgxTextDiffComponent.prototype.initScrollListener = function () { var _this = this; this.subscriptions.push(this.scrollService.scrolled().subscribe(function (scrollableEv) { if (scrollableEv && _this.synchronizeScrolling) { var scrollableId_1 = scrollableEv.getElementRef().nativeElement.id; var nonScrolledContainer = _this.containers.find(function (container) { return container.id !== scrollableId_1; }); if (nonScrolledContainer) { nonScrolledContainer.element.scrollTo({ top: scrollableEv.measureScrollOffset('top'), left: scrollableEv.measureScrollOffset('left'), }); } } })); }; NgxTextDiffComponent.ctorParameters = function () { return [ { 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); return NgxTextDiffComponent; }()); export { NgxTextDiffComponent }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXRleHQtZGlmZi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtdGV4dC1kaWZmLyIsInNvdXJjZXMiOlsibGliL25neC10ZXh0LWRpZmYuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxLQUFLLEVBQ0wsU0FBUyxFQUNULE1BQU0sRUFDTixNQUFNLEVBQ04sWUFBWSxFQUNaLFlBQVksRUFDWixTQUFTLEVBQ1QsYUFBYSxFQUNkLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzdELE9BQU8sRUFBRSxVQUFVLEVBQWdCLE1BQU0sTUFBTSxDQUFDO0FBQ2hELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQU96RTtJQWtERSw4QkFBb0IsYUFBK0IsRUFBVSxJQUF3QixFQUFVLEVBQXFCO1FBQWhHLGtCQUFhLEdBQWIsYUFBYSxDQUFrQjtRQUFVLFNBQUksR0FBSixJQUFJLENBQW9CO1FBQVUsT0FBRSxHQUFGLEVBQUUsQ0FBbUI7UUFqRDVHLHVCQUFrQixHQUFHLEtBQUssQ0FBQztRQUUxQixXQUFNLEdBQW9CLFlBQVksQ0FBQztRQUN2QyxTQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ1YsVUFBSyxHQUFHLEVBQUUsQ0FBQztRQUVYLFlBQU8sR0FBRyxLQUFLLENBQUM7UUFDaEIsZ0JBQVcsR0FBRyxJQUFJLENBQUM7UUFDbkIsbUJBQWMsR0FBRyxJQUFJLENBQUM7UUFldEIseUJBQW9CLEdBQUcsSUFBSSxDQUFDO1FBQzNCLG1CQUFjLEdBQUcsSUFBSSxZQUFZLEVBQWUsQ0FBQztRQUMzRCxrQkFBYSxHQUFtQixFQUFFLENBQUM7UUFDbkMsY0FBUyxHQUF5QixFQUFF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SyxFQUFFOztxRUFBMEI7SUFDekI7UUFBUixLQUFLLEVBQUU7OzhEQUFzQjtJQUNyQjtRQUFSLEtBQUssRUFBRTs7OERBQW1CO0lBQ2xCO1FBQVIsS0FBSyxFQUFFOztrRUFBMEI7SUFDekI7UUFBUixLQUFLLEVBQUU7O2tFQUF1QjtJQUN0QjtRQUFSLEtBQUssRUFBRTs7c0VBQTZCO0lBQzNCO1FBQVQsTUFBTSxFQUFFOztnRUFBa0Q7SUF6QmhELG9CQUFvQjtRQUxoQyxTQUFTLENBQUM7WUFDVCxRQUFRLEVBQUUsa0JBQWtCO1lBQzVCLHcvT0FBNkM7O1NBRTlDLENBQUM7eUNBbURtQyxnQkFBZ0IsRUFBZ0Isa0JBQWtCLEVBQWMsaUJBQWlCO09BbER6RyxvQkFBb0IsQ0F1TGhDO0lBQUQsMkJBQUM7Q0FBQSxBQXZMRCxJQXVMQztTQXZMWSxvQkFBb0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIENoYW5nZURldGVjdG9yUmVmLFxyXG4gIENvbXBvbmVudCxcclxuICBJbnB1dCxcclxuICBPbkRlc3Ryb3ksXHJcbiAgT25Jbml0LFxyXG4gIE91dHB1dCxcclxuICBFdmVudEVtaXR0ZXIsXHJcbiAgVmlld0NoaWxkcmVuLFxyXG4gIFF1ZXJ5TGlzdCxcclxuICBBZnRlclZpZXdJbml0XHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IERpZmZDb250ZW50LCBEaWZmUGFydCwgRGlmZlRhYmxlRm9ybWF0LCBEaWZmVGFibGVGb3JtYXRPcHRpb24sIERpZmZUYWJsZVJvd1Jlc3VsdCwgRGlmZlJlc3VsdHMgfSBmcm9tICcuL25neC10ZXh0LWRpZmYubW9kZWwnO1xyXG5pbXBvcnQgeyBOZ3hUZXh0RGlmZlNlcnZpY2UgfSBmcm9tICcuL25neC10ZXh0LWRpZmYuc2VydmljZSc7XHJcbmltcG9ydCB7IE9ic2VydmFibGUsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBDb250YWluZXJEaXJlY3RpdmUgfSBmcm9tICcuL25neC10ZXh0LWRpZmYtY29udGFpbmVyLmRpcmVjdGl2ZSc7XHJcbmltcG9ydCB7IFNjcm9sbERpc3BhdGNoZXIsIENka1Njcm9sbGFibGUgfSBmcm9tICdAYW5ndWxhci9jZGsvc2Nyb2xsaW5nJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAndGQtbmd4LXRleHQtZGlmZicsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL25neC10ZXh0LWRpZmYuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL25neC10ZXh0LWRpZmYuY29tcG9uZW50LmNzcyddLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgTmd4VGV4dERpZmZDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XHJcbiAgcHJpdmF0ZSBfaGlkZU1hdGNoaW5nTGluZXMgPSBmYWxzZTtcclxuICBAVmlld0NoaWxkcmVuKENvbnRhaW5lckRpcmVjdGl2ZSkgY29udGFpbmVyczogUXVlcnlMaXN0PENvbnRhaW5lckRpcmVjdGl2ZT47XHJcbiAgQElucHV0KCkgZm9ybWF0OiBEaWZmVGFibGVGb3JtYXQgPSAnU2lkZUJ5U2lkZSc7XHJcbiAgQElucHV0KCkgbGVmdCA9ICcnO1xyXG4gIEBJbnB1dCgpIHJpZ2h0ID0gJyc7XHJcbiAgQElucHV0KCkgZGlmZkNvbnRlbnQ6IE9ic2VydmFibGU8RGlmZkNvbnRlbnQ+O1xyXG4gIEBJbnB1dCgpIGxvYWRpbmcgPSBmYWxzZTtcclxuICBASW5wdXQoKSBzaG93VG9vbGJhciA9IHRydWU7XHJcbiAgQElucHV0KCkgc2hvd0J0blRvb2xiYXIgPSB0cnVlO1xyXG4gIEBJbnB1dCgpXHJcbiAgZ2V0IGhpZGVNYXRjaGluZ0xpbmVzKCkge1xyXG4gICAgcmV0dXJuIHRoaXMuX2hpZGVNYXRjaGluZ0xpbmVzO1xyXG4gIH1cclxuXHJcbiAgc2V0IGhpZGVNYXRjaGluZ0xpbmVzKGhpZGU6IGJvb2xlYW4pIHtcclxuICAgIHRoaXMuaGlkZU1hdGNoaW5nTGluZXNDaGFuZ2VkKGhpZGUpO1xyXG4gIH1cclxuICBASW5wdXQoKSBvdXRlckNvbnRhaW5lckNsYXNzOiBzdHJpbmc7XHJcbiAgQElucHV0KCkgb3V0ZXJDb250YWluZXJTdHlsZTogYW55O1xyXG4gIEBJbnB1dCgpIHRvb2xiYXJDbGFzczogc3RyaW5nO1xyXG4gIEBJbnB1dCgpIHRvb2xiYXJTdHlsZTogYW55O1xyXG4gIEBJbnB1dCgpIGNvbXBhcmVSb3dzQ2xhc3M6IHN0cmluZztcclxuICBASW5wdXQoKSBjb21wYXJlUm93c1N0eWxlOiBhbnk7XHJcbiAgQElucHV0KCkgc3luY2hyb25pemVTY3JvbGxpbmcgPSB0cnVlO1xyXG4gIEBPdXRwdXQoKSBjb21wYXJlUmVzdWx0cyA9IG5ldyBFdmVudEVtaXR0ZXI8RGlmZlJlc3VsdHM+KCk7XHJcbiAgc3Vic2NyaXB0aW9uczogU3Vic2NyaXB0aW9uW10gPSBbXTtcclxuICB0YWJsZVJvd3M6IERpZmZUYWJsZVJvd1Jlc3VsdFtdID0gW107XHJcbiAgZmlsdGVyZWRUYWJsZVJvd3M6IERpZmZUYWJsZVJvd1Jlc3VsdFtdID0gW107XHJcbiAgdGFibGVSb3dzTGluZUJ5TGluZTogRGlmZlRhYmxlUm93UmVzdWx0W10gPSBbXTtcclxuICBmaWx0ZXJlZFRhYmxlUm93c0xpbmVCeUxpbmU6IERpZmZUYWJsZVJvd1Jlc3VsdFtdID0gW107XHJcbiAgZGlmZnNDb3VudCA9IDA7XHJcblxyXG4gIGZvcm1hdE9wdGlvbnM6IERpZmZUYWJsZUZvcm1hdE9wdGlvbltdID0gW1xyXG4gICAge1xyXG4gICAgICBpZDogJ3NpZGUtYnktc2lkZScsXHJcbiAgICAgIG5hbWU6ICdzaWRlLWJ5LXNpZGUnLFxyXG4gICAgICBsYWJlbDogJ1NpZGUgYnkgU2lkZScsXHJcbiAgICAgIHZhbHVlOiAnU2lkZUJ5U2lkZScsXHJcbiAgICAgIGljb246ICdsYS1jb2RlJyxcclxuICAgIH0sXHJcbiAgICB7XHJcbiAgICAgIGlkOiAnbGluZS1ieS1saW5lJyxcclxuICAgICAgbmFtZTogJ2xpbmUtYnktbGluZScsXHJcbiAgICAgIGxhYmVsOiAnTGluZSBieSBMaW5lJyxcclxuICAgICAgdmFsdWU6ICdMaW5lQnlMaW5lJyxcclxuICAgICAgaWNvbjogJ2xhLWZpbGUtdGV4dCcsXHJcbiAgICB9LFxyXG4gIF07XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Nyb2xsU2VydmljZTogU2Nyb2xsRGlzcGF0Y2hlciwgcHJpdmF0ZSBkaWZmOiBOZ3hUZXh0RGlmZlNlcnZpY2UsIHByaXZhdGUgY2Q6IENoYW5nZURldGVjdG9yUmVmKSB7fVxyXG5cclxuICBuZ09uSW5pdCgpIHtcclxuICAgIHRoaXMubG9hZGluZyA9IHRydWU7XHJcbiAgICBpZiAodGhpcy5kaWZmQ29udGVudCkge1xyXG4gICAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcclxuICAgICAgICB0aGlzLmRpZmZDb250ZW50LnN1YnNjcmliZShjb250ZW50ID0+IHtcclxuICAgICAgICAgIHRoaXMubG9hZGluZyA9IHRydWU7XHJcbiAgICAgICAgICB0aGlzLmxlZnQgPSBjb250ZW50LmxlZnRDb250ZW50O1xyXG4gICAgICAgICAgdGhpcy5yaWdodCA9IGNvbnRlbnQucmlnaHRDb250ZW50O1xyXG4gICAgICAgICAgdGhpcy5yZW5kZXJEaWZmcygpXHJcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcclxuICAgICAgICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgLmNhdGNoKCgpID0+ICh0aGlzLmxvYWRpbmcgPSBmYWxzZSkpO1xyXG4gICAgICAgIH0pXHJcbiAgICAgICk7XHJcbiAgICB9XHJcbiAgICB0aGlzLnJlbmRlckRpZmZzKClcclxuICAgICAgLnRoZW4oKCkgPT4gKHRoaXMubG9hZGluZyA9IGZhbHNlKSlcclxuICAgICAgLmNhdGNoKGUgPT4gKHRoaXMubG9hZGluZyA9IGZhbHNlKSk7XHJcbiAgfVxyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKSB7XHJcbiAgICB0aGlzLmluaXRTY3JvbGxMaXN0ZW5lcigpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5zdWJzY3JpcHRpb25zKSB7XHJcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5mb3JFYWNoKHN1YnNjcmlwdGlvbiA9PiBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBoaWRlTWF0Y2hpbmdMaW5lc0NoYW5nZWQodmFsdWU6IGJvb2xlYW4pIHtcclxuICAgIHRoaXMuX2hpZGVNYXRjaGluZ0xpbmVzID0gdmFsdWU7XHJcbiAgICBpZiAodGhpcy5oaWRlTWF0Y2hpbmdMaW5lcykge1xyXG4gICAgICB0aGlzLmZpbHRlcmVkVGFibGVSb3dzID0gdGhpcy50YWJsZVJvd3MuZmlsdGVyKFxyXG4gICAgICAgIHJvdyA9PiAocm93LmxlZnRDb250ZW50ICYmIHJvdy5sZWZ0Q29udGVudC5wcmVmaXggPT09ICctJykgfHwgKHJvdy5yaWdodENvbnRlbnQgJiYgcm93LnJpZ2h0Q29udGVudC5wcmVmaXggPT09ICcrJylcclxuICAgICAgKTtcclxuICAgICAgdGhpcy5maWx0ZXJlZFRhYmxlUm93c0xpbmVCeUxpbmUgPSB0aGlzLnRhYmxlUm93c0xpbmVCeUxpbmUuZmlsdGVyKFxyXG4gICAgICAgIHJvdyA9PiAocm93LmxlZnRDb250ZW50ICYmIHJvdy5sZWZ0Q29udGVudC5wcmVmaXggPT09ICctJykgfHwgKHJvdy5yaWdodENvbnRlbnQgJiYgcm93LnJpZ2h0Q29udGVudC5wcmVmaXggPT09ICcrJylcclxuICAgICAgKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuZmlsdGVyZWRUYWJsZVJvd3MgPSB0aGlzLnRhYmxlUm93cztcclxuICAgICAgdGhpcy5maWx0ZXJlZFRhYmxlUm93c0xpbmVCeUxpbmUgPSB0aGlzLnRhYmxlUm93c0xpbmVCeUxpbmU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBzZXREaWZmVGFibGVGb3JtYXQoZm9ybWF0OiBEaWZmVGFibGVGb3JtYXQpIHtcclxuICAgIHRoaXMuZm9ybWF0ID0gZm9ybWF0O1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgcmVuZGVyRGlmZnMoKSB7XHJcbiAgICB0cnkge1xyXG4gICAgICB0aGlzLmRpZmZzQ291bnQgPSAwO1xyXG4gICAgICB0aGlzLnRhYmxlUm93cyA9IGF3YWl0IHRoaXMuZGlmZi5nZXREaWZmc0J5TGluZXModGhpcy5sZWZ0LCB0aGlzLnJpZ2h0KTtcclxuICAgICAgdGhpcy50YWJsZVJvd3NMaW5lQnlMaW5lID0gdGhpcy50YWJsZVJvd3MucmVkdWNlKCh0YWJsZUxpbmVCeUxpbmU6IERpZmZUYWJsZVJvd1Jlc3VsdFtdLCByb3c6IERpZmZUYWJsZVJvd1Jlc3VsdCkgPT4ge1xyXG4gICAgICAgIGlmICghdGFibGVMaW5lQnlMaW5lKSB7XHJcbiAgICAgICAgICB0YWJsZUxpbmVCeUxpbmUgPSBbXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHJvdy5oYXNEaWZmcykge1xyXG4gICAgICAgICAgaWYgKHJvdy5sZWZ0Q29udGVudCkge1xyXG4gICAgICAgICAgICB0YWJsZUxpbmVCeUxpbmUucHVzaCh7XHJcbiAgICAgICAgICAgICAgbGVmdENvbnRlbnQ6IHJvdy5sZWZ0Q29udGVudCxcclxuICAgICAgICAgICAgICByaWdodENvbnRlbnQ6IG51bGwsXHJcbiAgICAgICAgICAgICAgYmVsb25nVG86IHJvdy5iZWxvbmdUbyxcclxuICAgICAgICAgICAgICBoYXNEaWZmczogdHJ1ZSxcclxuICAgICAgICAgICAgICBudW1EaWZmczogcm93Lm51bURpZmZzLFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGlmIChyb3cucmlnaHRDb250ZW50KSB7XHJcbiAgICAgICAgICAgIHRhYmxlTGluZUJ5TGluZS5wdXNoKHtcclxuICAgICAgICAgICAgICBsZWZ0Q29udGVudDogbnVsbCxcclxuICAgICAgICAgICAgICByaWdodENvbnRlbnQ6IHJvdy5yaWdodENvbnRlbnQsXHJcbiAgICAgICAgICAgICAgYmVsb25nVG86IHJvdy5iZWxvbmdUbyxcclxuICAgICAgICAgICAgICBoYXNEaWZmczogdHJ1ZSxcclxuICAgICAgICAgICAgICBudW1EaWZmczogcm93Lm51bURpZmZzLFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgdGFibGVMaW5lQnlMaW5lLnB1c2gocm93KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0YWJsZUxpbmVCeUxpbmU7XHJcbiAgICAgIH0sIFtdKTtcclxuICAgICAgdGhpcy5kaWZmc0NvdW50ID0gdGhpcy50YWJsZVJvd3MuZmlsdGVyKHJvdyA9PiByb3cuaGFzRGlmZnMpLmxlbmd0aDtcclxuICAgICAgdGhpcy5maWx0ZXJlZFRhYmxlUm93cyA9IHRoaXMudGFibGVSb3dzO1xyXG4gICAgICB0aGlzLmZpbHRlcmVkVGFibGVSb3dzTGluZUJ5TGluZSA9IHRoaXMudGFibGVSb3dzTGluZUJ5TGluZTtcclxuICAgICAgdGhpcy5lbWl0Q29tcGFyZVJlc3VsdHNFdmVudCgpO1xyXG4gICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICB0aHJvdyBlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZW1pdENvbXBhcmVSZXN1bHRzRXZlbnQoKSB7XHJcbiAgICBjb25zdCBkaWZmUmVzdWx0czogRGlmZlJlc3VsdHMgPSB7XHJcbiAgICAgIGhhc0RpZmY6IHRoaXMuZGlmZnNDb3VudCA+IDAsXHJcbiAgICAgIGRpZmZzQ291bnQ6IHRoaXMuZGlmZnNDb3VudCxcclxuICAgICAgcm93c1dpdGhEaWZmOiB0aGlzLnRhYmxlUm93c1xyXG4gICAgICAgIC5maWx0ZXIocm93ID0+IHJvdy5oYXNEaWZmcylcclxuICAgICAgICAubWFwKHJvdyA9PiAoe1xyXG4gICAgICAgICAgbGVmdExpbmVOdW1iZXI6IHJvdy5sZWZ0Q29udGVudCA/IHJvdy5sZWZ0Q29udGVudC5saW5lTnVtYmVyIDogbnVsbCxcclxuICAgICAgICAgIHJpZ2h0TGluZU51bWJlcjogcm93LnJpZ2h0Q29udGVudCA/IHJvdy5yaWdodENvbnRlbnQubGluZU51bWJlciA6IG51bGwsXHJcbiAgICAgICAgICBudW1EaWZmczogcm93Lm51bURpZmZzLFxyXG4gICAgICAgIH0pKSxcclxuICAgIH07XHJcblxyXG4gICAgdGhpcy5jb21wYXJlUmVzdWx0cy5uZXh0KGRpZmZSZXN1bHRzKTtcclxuICB9XHJcblxyXG4gIHRyYWNrVGFibGVSb3dzKGluZGV4LCByb3c6IERpZmZUYWJsZVJvd1Jlc3VsdCkge1xyXG4gICAgcmV0dXJuIHJvdyAmJiByb3cubGVmdENvbnRlbnQgPyByb3cubGVmdENvbnRlbnQubGluZUNvbnRlbnQgOiByb3cgJiYgcm93LnJpZ2h0Q29udGVudCA/IHJvdy5yaWdodENvbnRlbnQubGluZUNvbnRlbnQgOiB1bmRlZmluZWQ7XHJcbiAgfVxyXG5cclxuICB0cmFja0RpZmZzKGluZGV4LCBkaWZmOiBEaWZmUGFydCkge1xyXG4gICAgcmV0dXJuIGRpZmYgJiYgZGlmZi5jb250ZW50ID8gZGlmZi5jb250ZW50IDogdW5kZWZpbmVkO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBpbml0U2Nyb2xsTGlzdGVuZXIoKSB7XHJcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaCh0aGlzLnNjcm9sbFNlcnZpY2Uuc2Nyb2xsZWQoKS5zdWJzY3JpYmUoKHNjcm9sbGFibGVFdjogQ2RrU2Nyb2xsYWJsZSkgPT4ge1xyXG4gICAgICBpZiAoc2Nyb2xsYWJsZUV2ICYmIHRoaXMuc3luY2hyb25pemVTY3JvbGxpbmcpIHtcclxuICAgICAgICBjb25zdCBzY3JvbGxhYmxlSWQgPSBzY3JvbGxhYmxlRXYuZ2V0RWxlbWVudFJlZigpLm5hdGl2ZUVsZW1lbnQuaWQ7XHJcbiAgICAgICAgY29uc3Qgbm9uU2Nyb2xsZWRDb250YWluZXI6IENvbnRhaW5lckRpcmVjdGl2ZSA9IHRoaXMuY29udGFpbmVycy5maW5kKGNvbnRhaW5lciA9PiBjb250YWluZXIuaWQgIT09IHNjcm9sbGFibGVJZCk7XHJcbiAgICAgICAgaWYgKG5vblNjcm9sbGVkQ29udGFpbmVyKSB7XHJcbiAgICAgICAgICBub25TY3JvbGxlZENvbnRhaW5lci5lbGVtZW50LnNjcm9sbFRvKHtcclxuICAgICAgICAgICAgdG9wOiBzY3JvbGxhYmxlRXYubWVhc3VyZVNjcm9sbE9mZnNldCgndG9wJyksXHJcbiAgICAgICAgICAgIGxlZnQ6IHNjcm9sbGFibGVFdi5tZWFzdXJlU2Nyb2xsT2Zmc2V0KCdsZWZ0JyksXHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0pKTtcclxuICB9XHJcbn1cclxuIl19