ngx-smart-spreadsheet
Version:
Lightweight spreadsheet module for Angular
361 lines • 60.2 kB
JavaScript
import { Component, EventEmitter, HostListener, Input, Output, ViewChild } from '@angular/core';
import csvToArray from './csv-converter';
import Anchor from './model/anchor';
import Range from './model/range';
import Table from './model/table';
import * as i0 from "@angular/core";
import * as i1 from "./ngx-context-menu.component";
import * as i2 from "./ngx-context-menu-item.component";
import * as i3 from "@angular/common";
import * as i4 from "./content-editable.directive";
export class NgxSmartSpreadsheetComponent {
constructor() {
this.settings = null;
this.copied = new EventEmitter();
this.table = null;
this.activatedCell = null;
this.range = null;
this.anchor = null;
this.activeTheadIndex = -1;
this.activeTbodyIndex = -1;
}
ngOnInit() {
if (this.settings?.rows && this.settings?.cols) {
this.table = Table.empty(this.settings.rows, this.settings.cols);
}
else if (this.settings?.data) {
this.table = Table.load(this.settings.data);
}
}
get data() {
if (!this.table) {
return [[]];
}
return this.table.body.map(row => row.map(cell => cell.value));
}
mousedown(ev) {
const { row, col, valid } = this.getPositionFromId(ev.target);
if (!valid) {
return;
}
this.range = Range.of(row, col);
if (!ev.shiftKey || !this.anchor) {
this.anchor = new Anchor(row, col);
}
}
mousemove(ev) {
if (!this.range || !this.anchor) {
return;
}
const self = this.getPositionFromId(ev.target);
if (self.valid) {
const range = Range.marge({ r: self.row, c: self.col }, this.anchor);
if (!this.range?.equals(range)) {
this.range = range;
}
}
}
mouseup(ev) {
if (ev.shiftKey && this.anchor) {
const self = this.getPositionFromId(ev.target);
if (self.valid) {
const range = Range.marge({ r: self.row, c: self.col }, this.anchor);
if (!this.range?.equals(range)) {
this.range = range;
}
}
}
this.anchor = null;
}
onKeyDown(ev) {
const key = ev.key.toLowerCase();
const isCtrl = ((ev.ctrlKey && !ev.metaKey) || (!ev.ctrlKey && ev.metaKey));
if (!this.table) {
return;
}
if (!this.anchor && ev.shiftKey && this.activatedCell) {
const { row, col } = this.activatedCell;
this.anchor = new Anchor(row, col);
}
if (key === 'enter' && this.activatedCell) {
const { row, col, editable } = this.activatedCell;
if (editable && ev.shiftKey) {
ev.preventDefault();
this.moveTo(row + 1, col, false, editable);
}
}
else if (key === 'tab' && this.activatedCell) {
ev.preventDefault();
const { rowCount, colCount } = this.table;
const { row, col, editable } = this.activatedCell;
const next = ev.shiftKey ? col - 1 : col + 1;
if (next < 0 && row > 0) {
this.moveTo(row - 1, colCount - 1, false, editable);
}
else if (next >= colCount && row < rowCount) {
this.moveTo(row + 1, 0, false, editable);
}
else {
this.moveTo(row, next, false, editable);
}
}
else if (key === 'f2') {
this.setEditable(ev, true);
}
else if (key === 'escape') {
this.setEditable(ev, false);
}
else if (key === 'c' && isCtrl) {
this.copy();
}
else if (key === 'v' && isCtrl) {
this.paste();
}
else if (key === 'delete') {
this.delete();
}
}
onKeyUp(ev) {
if (!this.activatedCell || this.activatedCell.editable) {
return;
}
if (!ev.shiftKey) {
this.anchor = null;
}
const { row, col } = this.activatedCell;
switch (ev.key.toLowerCase()) {
case 'arrowup':
this.moveTo(row - 1, col, ev.shiftKey, false);
break;
case 'arrowdown':
this.moveTo(row + 1, col, ev.shiftKey, false);
break;
case 'arrowleft':
this.moveTo(row, col - 1, ev.shiftKey, false);
break;
case 'arrowright':
this.moveTo(row, col + 1, ev.shiftKey, false);
break;
}
}
trackByCell(index, value) {
return value ? value.id : null;
}
clickHeader(colIndex) {
const rowLength = this.table?.body.length || 0;
if (rowLength > 0) {
this.range = Range.of(0, colIndex, rowLength, colIndex);
}
}
clickRow(rowIndex) {
if (!this.table) {
return;
}
if (rowIndex >= 0 && rowIndex < this.table.body.length) {
const cols = this.table.body[rowIndex];
this.range = Range.of(rowIndex, 0, rowIndex, cols.length);
}
}
focus(ev) {
const found = this.findCellByEventTarget(ev.target);
this.activatedCell = found;
}
blur(ev) {
const found = this.findCellByEventTarget(ev.target);
if (found) {
found.editable = false;
}
}
dblclick(ev, target) {
const td = ev.target;
if (target === this.activatedCell) {
target.editable = true;
}
}
setValue(ev, target) {
const value = ev.target.innerText || '';
target.value = value;
}
setEditable(ev, editable) {
ev.stopPropagation();
const found = this.findCellByEventTarget(ev.target);
if (found) {
found.editable = editable;
}
}
//#region menu event handle
showTheadMenu(ev, index) {
ev.stopPropagation();
this.theadContextMenu.show(ev, index);
}
showTbodyMenu(ev, index) {
ev.stopPropagation();
this.tbodyContextMenu.show(ev, index);
}
//#endregion
moveTo(row, col, shiftKey, editable) {
if (!this.table) {
return;
}
const { body } = this.table;
if (row >= 0 && row < body.length) {
const cols = body[row];
if (col >= 0 && col < cols.length) {
const cell = cols[col];
const e = document.getElementById(cell.id);
if (e) {
e.focus();
const s = window.getSelection();
const r = document.createRange();
r.setStart(e, e.childElementCount);
r.setEnd(e, e.childElementCount);
s?.removeAllRanges();
s?.addRange(r);
}
if (shiftKey && this.range && this.anchor) {
this.range = Range.marge(this.anchor, { r: row, c: col });
}
else {
this.range = Range.of(cell.row, cell.col);
}
if (editable) {
cell.editable = true;
}
}
}
}
findCellByEventTarget(target) {
const { row, col, valid } = this.getPositionFromId(target);
return valid ? (this.table?.findCell(row, col) || null) : null;
}
getPositionFromId(target) {
const element = target;
if (!this.table || !element?.id?.match(/(\w+)-(\d+)-(\d+)/)) {
return { row: NaN, col: NaN, valid: false };
}
const valid = RegExp.$1 === this.table.id;
const row = parseInt(RegExp.$2 || '', 10);
const col = parseInt(RegExp.$3 || '', 10);
return { row, col, valid };
}
copy() {
if (!this.table || !this.range) {
return;
}
const lines = [];
for (let r = this.range.r1; r <= this.range.r2; r++) {
const line = [];
for (let c = this.range.c1; c <= this.range.c2; c++) {
const cell = this.table.findCell(r, c);
if (cell) {
const value = (cell.value.match(/[\t\n\r "]+/))
? '"' + cell.value.split('"').join('""') + '"'
: cell.value;
line.push(value);
}
}
lines.push(line.join('\t'));
}
const text = lines.join('\n');
if (text) {
navigator.clipboard.writeText(text)
.then(() => this.copied.emit(text));
}
}
paste() {
if (!this.table || !this.range) {
return;
}
const { r1, c1, r2, c2 } = this.range;
navigator.clipboard.readText()
.then((data) => {
const ar = csvToArray(data);
if (!ar.length) {
return;
}
if (ar.length === 1 && ar[0].length === 1) {
const clipboardText = ar[0][0];
for (let r = r1; r <= r2; r++) {
for (let c = c1; c <= c2; c++) {
const cell = this.table.findCell(r, c);
if (cell) {
cell.value = clipboardText;
}
}
}
}
else if ((r2 - r1 + 1) === ar.length && (c2 - c1 + 1) === ar[0].length) {
for (let r = r1; r <= r2; r++) {
for (let c = c1; c <= c2; c++) {
const cell = this.table.findCell(r, c);
if (cell) {
cell.value = ar[r][c];
}
}
}
}
else {
let cell = null;
for (let r = 0, tableRow = r1; r < ar.length; r++, tableRow++) {
const row = ar[r];
for (let c = 0, tableCol = c1; c < row.length; c++, tableCol++) {
const col = row[c];
cell = this.table.findCell(tableRow, tableCol);
if (cell) {
cell.value = col;
}
}
}
if (cell) {
this.range = Range.of(r1, c1, cell.row, cell.col);
}
}
});
}
delete() {
if (!this.table || !this.range) {
return;
}
const { r1, c1, r2, c2 } = this.range;
for (let r = r1; r <= r2; r++) {
for (let c = c1; c <= c2; c++) {
const cell = this.table.findCell(r, c);
if (cell) {
cell.value = '';
}
}
}
}
}
NgxSmartSpreadsheetComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: NgxSmartSpreadsheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
NgxSmartSpreadsheetComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.2", type: NgxSmartSpreadsheetComponent, selector: "ngx-smart-spreadsheet", inputs: { settings: "settings" }, outputs: { copied: "copied" }, host: { listeners: { "mousedown": "mousedown($event)", "document:mousemove": "mousemove($event)", "document:mouseup": "mouseup($event)", "document:keydown": "onKeyDown($event)", "document:keyup": "onKeyUp($event)" } }, viewQueries: [{ propertyName: "theadContextMenu", first: true, predicate: ["theadMenu"], descendants: true }, { propertyName: "tbodyContextMenu", first: true, predicate: ["tbodyMenu"], descendants: true }], ngImport: i0, template: "<ng-container *ngIf=\"settings && table\">\n <div class=\"container\">\n <table>\n <thead>\n <tr>\n <th></th>\n <th *ngFor=\"let col of table.head; let c = index\" (click)=\"clickHeader(c)\"\n (mouseenter)=\"activeTheadIndex = c\" (mouseleave)=\"activeTheadIndex = -1\">\n <div class=\"head\">\n <div class=\"label\">{{col}}</div>\n <div class=\"dropdown\" *ngIf=\"activeTheadIndex === c\">\n <button class=\"dropbtn\" (click)=\"showTheadMenu($event, c)\">></button>\n </div>\n </div>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of table.body; let r = index;\">\n <th (click)=\"clickRow(r)\" (mouseenter)=\"activeTbodyIndex = r\" (mouseleave)=\"activeTbodyIndex = -1\">\n <div class=\"head\">\n <div class=\"label\">{{r + 1}}</div>\n <div class=\"dropdown\" *ngIf=\"activeTbodyIndex === r\">\n <button class=\"dropbtn\" (click)=\"showTbodyMenu($event, r)\">></button>\n </div>\n </div>\n </th>\n <td [id]=\"cell.id\" *ngFor=\"let cell of row; let c = index; trackBy: trackByCell\"\n [class.focus]=\"cell === activatedCell\" [class.sel]=\"range?.includes(cell.row, cell.col)\"\n nssContentEditable [(model)]=\"cell.value\" (focus)=\"focus($event)\" (blur)=\"blur($event)\"\n (dblclick)=\"dblclick($event, cell)\" [attr.contenteditable]=\"cell.editable\">\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <ngx-context-menu #theadMenu (closed)=\"activeTheadIndex = -1\">\n <ngx-context-menu-item [label]=\"settings.options?.contextMenuColLabel?.INSERT_COLUMN_LEFT\"\n (click)=\"table.insertColumn($event)\">\n </ngx-context-menu-item>\n <ngx-context-menu-item [label]=\"settings.options?.contextMenuColLabel?.INSERT_COLUMN_RIGHT\"\n (click)=\"table.insertColumn($event + 1)\">\n </ngx-context-menu-item>\n <ngx-context-menu-item [divider]=\"true\"></ngx-context-menu-item>\n <ngx-context-menu-item [label]=\"settings.options?.contextMenuColLabel?.DELETE_COLUMN\"\n [disabled]=\"table.colCount <= 1\" (click)=\"table.deleteColumn($event)\">\n </ngx-context-menu-item>\n </ngx-context-menu>\n\n <ngx-context-menu #tbodyMenu (closed)=\"activeTbodyIndex = -1\">\n <ngx-context-menu-item [label]=\"settings.options?.contextMenuRowLabel?.INSERT_ROW_ABOVE\"\n (click)=\"table.insertRow($event)\">\n </ngx-context-menu-item>\n <ngx-context-menu-item [label]=\"settings.options?.contextMenuRowLabel?.INSERT_ROW_BELOW\"\n (click)=\"table.insertRow($event + 1)\">\n </ngx-context-menu-item>\n <ngx-context-menu-item [divider]=\"true\"></ngx-context-menu-item>\n <ngx-context-menu-item [label]=\"settings.options?.contextMenuRowLabel?.DELETE_ROW\"\n [disabled]=\"table.rowCount <= 1\" (click)=\"table.deleteRow($event)\">\n </ngx-context-menu-item>\n </ngx-context-menu>\n</ng-container>", styles: [".container{font-size:14px}.container table,.container td,.container th,.container tr{height:2.5rem;border-spacing:0;height:100%}.container table{margin-bottom:2px}.container table thead{background:#f1f1f1;position:sticky;top:0;z-index:2}.container table thead th:first-child{background:#f1f1f1;z-index:3}.container table tbody th{min-width:5rem;background:#fafafa;z-index:1}.container table th{font-weight:400;padding:.2rem .4rem;border:1px solid #ddd;-webkit-user-select:none;user-select:none}.container table th:first-child{position:sticky;left:0}.container table th .head{display:grid;grid-template-columns:1fr auto}.container table th .head .label{grid-column:1/3;grid-row:1}.container table th .head .dropdown{grid-column:2/3;grid-row:1}.container table th .head .dropdown button{background-color:#e2e2e2d0;color:#00000080;padding:0rem .3rem;border:none;cursor:pointer;transition:ease .4s;transform:rotate(90deg);font-family:ui-monospace;-webkit-user-select:none;user-select:none}.container table td{min-width:10rem;padding:.2rem .5rem;border:1px solid #ddd;-webkit-user-select:none;user-select:none}.container table td.focus{outline:2px solid dodgerblue;-webkit-user-select:auto;user-select:auto}.container table td.sel{background:#eaf1fd}.container table td[contenteditable=true]{-webkit-user-select:auto;user-select:auto;outline:2px solid #48c21a;background:#eaffe2}\n"], components: [{ type: i1.NgxContextMenuComponent, selector: "ngx-context-menu", outputs: ["closed"] }, { type: i2.NgxContextMenuItemComponent, selector: "ngx-context-menu-item", inputs: ["label", "disabled", "divider"], outputs: ["click"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4.ContentEditableDirective, selector: "[nssContentEditable]", inputs: ["model"], outputs: ["modelChange"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: NgxSmartSpreadsheetComponent, decorators: [{
type: Component,
args: [{ selector: 'ngx-smart-spreadsheet', template: "<ng-container *ngIf=\"settings && table\">\n <div class=\"container\">\n <table>\n <thead>\n <tr>\n <th></th>\n <th *ngFor=\"let col of table.head; let c = index\" (click)=\"clickHeader(c)\"\n (mouseenter)=\"activeTheadIndex = c\" (mouseleave)=\"activeTheadIndex = -1\">\n <div class=\"head\">\n <div class=\"label\">{{col}}</div>\n <div class=\"dropdown\" *ngIf=\"activeTheadIndex === c\">\n <button class=\"dropbtn\" (click)=\"showTheadMenu($event, c)\">></button>\n </div>\n </div>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of table.body; let r = index;\">\n <th (click)=\"clickRow(r)\" (mouseenter)=\"activeTbodyIndex = r\" (mouseleave)=\"activeTbodyIndex = -1\">\n <div class=\"head\">\n <div class=\"label\">{{r + 1}}</div>\n <div class=\"dropdown\" *ngIf=\"activeTbodyIndex === r\">\n <button class=\"dropbtn\" (click)=\"showTbodyMenu($event, r)\">></button>\n </div>\n </div>\n </th>\n <td [id]=\"cell.id\" *ngFor=\"let cell of row; let c = index; trackBy: trackByCell\"\n [class.focus]=\"cell === activatedCell\" [class.sel]=\"range?.includes(cell.row, cell.col)\"\n nssContentEditable [(model)]=\"cell.value\" (focus)=\"focus($event)\" (blur)=\"blur($event)\"\n (dblclick)=\"dblclick($event, cell)\" [attr.contenteditable]=\"cell.editable\">\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <ngx-context-menu #theadMenu (closed)=\"activeTheadIndex = -1\">\n <ngx-context-menu-item [label]=\"settings.options?.contextMenuColLabel?.INSERT_COLUMN_LEFT\"\n (click)=\"table.insertColumn($event)\">\n </ngx-context-menu-item>\n <ngx-context-menu-item [label]=\"settings.options?.contextMenuColLabel?.INSERT_COLUMN_RIGHT\"\n (click)=\"table.insertColumn($event + 1)\">\n </ngx-context-menu-item>\n <ngx-context-menu-item [divider]=\"true\"></ngx-context-menu-item>\n <ngx-context-menu-item [label]=\"settings.options?.contextMenuColLabel?.DELETE_COLUMN\"\n [disabled]=\"table.colCount <= 1\" (click)=\"table.deleteColumn($event)\">\n </ngx-context-menu-item>\n </ngx-context-menu>\n\n <ngx-context-menu #tbodyMenu (closed)=\"activeTbodyIndex = -1\">\n <ngx-context-menu-item [label]=\"settings.options?.contextMenuRowLabel?.INSERT_ROW_ABOVE\"\n (click)=\"table.insertRow($event)\">\n </ngx-context-menu-item>\n <ngx-context-menu-item [label]=\"settings.options?.contextMenuRowLabel?.INSERT_ROW_BELOW\"\n (click)=\"table.insertRow($event + 1)\">\n </ngx-context-menu-item>\n <ngx-context-menu-item [divider]=\"true\"></ngx-context-menu-item>\n <ngx-context-menu-item [label]=\"settings.options?.contextMenuRowLabel?.DELETE_ROW\"\n [disabled]=\"table.rowCount <= 1\" (click)=\"table.deleteRow($event)\">\n </ngx-context-menu-item>\n </ngx-context-menu>\n</ng-container>", styles: [".container{font-size:14px}.container table,.container td,.container th,.container tr{height:2.5rem;border-spacing:0;height:100%}.container table{margin-bottom:2px}.container table thead{background:#f1f1f1;position:sticky;top:0;z-index:2}.container table thead th:first-child{background:#f1f1f1;z-index:3}.container table tbody th{min-width:5rem;background:#fafafa;z-index:1}.container table th{font-weight:400;padding:.2rem .4rem;border:1px solid #ddd;-webkit-user-select:none;user-select:none}.container table th:first-child{position:sticky;left:0}.container table th .head{display:grid;grid-template-columns:1fr auto}.container table th .head .label{grid-column:1/3;grid-row:1}.container table th .head .dropdown{grid-column:2/3;grid-row:1}.container table th .head .dropdown button{background-color:#e2e2e2d0;color:#00000080;padding:0rem .3rem;border:none;cursor:pointer;transition:ease .4s;transform:rotate(90deg);font-family:ui-monospace;-webkit-user-select:none;user-select:none}.container table td{min-width:10rem;padding:.2rem .5rem;border:1px solid #ddd;-webkit-user-select:none;user-select:none}.container table td.focus{outline:2px solid dodgerblue;-webkit-user-select:auto;user-select:auto}.container table td.sel{background:#eaf1fd}.container table td[contenteditable=true]{-webkit-user-select:auto;user-select:auto;outline:2px solid #48c21a;background:#eaffe2}\n"] }]
}], propDecorators: { theadContextMenu: [{
type: ViewChild,
args: ['theadMenu']
}], tbodyContextMenu: [{
type: ViewChild,
args: ['tbodyMenu']
}], settings: [{
type: Input
}], copied: [{
type: Output
}], mousedown: [{
type: HostListener,
args: ['mousedown', ['$event']]
}], mousemove: [{
type: HostListener,
args: ['document:mousemove', ['$event']]
}], mouseup: [{
type: HostListener,
args: ['document:mouseup', ['$event']]
}], onKeyDown: [{
type: HostListener,
args: ['document:keydown', ['$event']]
}], onKeyUp: [{
type: HostListener,
args: ['document:keyup', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXNtYXJ0LXNwcmVhZHNoZWV0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zbWFydC1zcHJlYWRzaGVldC9zcmMvbGliL25neC1zbWFydC1zcHJlYWRzaGVldC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc21hcnQtc3ByZWFkc2hlZXQvc3JjL2xpYi9uZ3gtc21hcnQtc3ByZWFkc2hlZXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBVSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3hHLE9BQU8sVUFBVSxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sTUFBTSxNQUFNLGdCQUFnQixDQUFDO0FBRXBDLE9BQU8sS0FBSyxNQUFNLGVBQWUsQ0FBQztBQUNsQyxPQUFPLEtBQUssTUFBTSxlQUFlLENBQUM7Ozs7OztBQVNsQyxNQUFNLE9BQU8sNEJBQTRCO0lBTHpDO1FBWUUsYUFBUSxHQUErQixJQUFJLENBQUM7UUFHNUMsV0FBTSxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFFcEMsVUFBSyxHQUFpQixJQUFJLENBQUM7UUFDM0Isa0JBQWEsR0FBZ0IsSUFBSSxDQUFDO1FBQ2xDLFVBQUssR0FBaUIsSUFBSSxDQUFDO1FBQzNCLFdBQU0sR0FBa0IsSUFBSSxDQUFDO1FBRTdCLHFCQUFnQixHQUFXLENBQUMsQ0FBQyxDQUFDO1FBQzlCLHFCQUFnQixHQUFXLENBQUMsQ0FBQyxDQUFDO0tBdVUvQjtJQXJVQyxRQUFRO1FBQ04sSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRTtZQUM5QyxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQyxL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LE1BQU07c0JBREwsTUFBTTtnQkEyQkMsU0FBUztzQkFEaEIsWUFBWTt1QkFBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBYTdCLFNBQVM7c0JBRGhCLFlBQVk7dUJBQUMsb0JBQW9CLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBZXRDLE9BQU87c0JBRGQsWUFBWTt1QkFBQyxrQkFBa0IsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFlcEMsU0FBUztzQkFEaEIsWUFBWTt1QkFBQyxrQkFBa0IsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkE2Q3BDLE9BQU87c0JBRGQsWUFBWTt1QkFBQyxnQkFBZ0IsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBIb3N0TGlzdGVuZXIsIElucHV0LCBPbkluaXQsIE91dHB1dCwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgY3N2VG9BcnJheSBmcm9tICcuL2Nzdi1jb252ZXJ0ZXInO1xuaW1wb3J0IEFuY2hvciBmcm9tICcuL21vZGVsL2FuY2hvcic7XG5pbXBvcnQgQ2VsbCBmcm9tICcuL21vZGVsL2NlbGwnO1xuaW1wb3J0IFJhbmdlIGZyb20gJy4vbW9kZWwvcmFuZ2UnO1xuaW1wb3J0IFRhYmxlIGZyb20gJy4vbW9kZWwvdGFibGUnO1xuaW1wb3J0IHsgTmd4Q29udGV4dE1lbnVDb21wb25lbnQgfSBmcm9tICcuL25neC1jb250ZXh0LW1lbnUuY29tcG9uZW50JztcbmltcG9ydCB7IFNwcmVhZHNoZWV0U2V0dGluZ3MgfSBmcm9tICcuL3NwcmVhZHNoZWV0LXNldHRpbmdzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LXNtYXJ0LXNwcmVhZHNoZWV0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL25neC1zbWFydC1zcHJlYWRzaGVldC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL25neC1zbWFydC1zcHJlYWRzaGVldC5jb21wb25lbnQuc2NzcyddXG59KVxuZXhwb3J0IGNsYXNzIE5neFNtYXJ0U3ByZWFkc2hlZXRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBAVmlld0NoaWxkKCd0aGVhZE1lbnUnKVxuICB0aGVhZENvbnRleHRNZW51ITogTmd4Q29udGV4dE1lbnVDb21wb25lbnQ7XG4gIEBWaWV3Q2hpbGQoJ3Rib2R5TWVudScpXG4gIHRib2R5Q29udGV4dE1lbnUhOiBOZ3hDb250ZXh0TWVudUNvbXBvbmVudDtcblxuICBASW5wdXQoKVxuICBzZXR0aW5nczogU3ByZWFkc2hlZXRTZXR0aW5ncyB8IG51bGwgPSBudWxsO1xuXG4gIEBPdXRwdXQoKVxuICBjb3BpZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcblxuICB0YWJsZTogVGFibGUgfCBudWxsID0gbnVsbDtcbiAgYWN0aXZhdGVkQ2VsbDogQ2VsbCB8IG51bGwgPSBudWxsO1xuICByYW5nZTogUmFuZ2UgfCBudWxsID0gbnVsbDtcbiAgYW5jaG9yOiBBbmNob3IgfCBudWxsID0gbnVsbDtcblxuICBhY3RpdmVUaGVhZEluZGV4OiBudW1iZXIgPSAtMTtcbiAgYWN0aXZlVGJvZHlJbmRleDogbnVtYmVyID0gLTE7XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2V0dGluZ3M/LnJvd3MgJiYgdGhpcy5zZXR0aW5ncz8uY29scykge1xuICAgICAgdGhpcy50YWJsZSA9IFRhYmxlLmVtcHR5KHRoaXMuc2V0dGluZ3Mucm93cywgdGhpcy5zZXR0aW5ncy5jb2xzKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuc2V0dGluZ3M/LmRhdGEpIHtcbiAgICAgIHRoaXMudGFibGUgPSBUYWJsZS5sb2FkKHRoaXMuc2V0dGluZ3MuZGF0YSk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGdldCBkYXRhKCk6IHN0cmluZ1tdW10ge1xuICAgIGlmICghdGhpcy50YWJsZSkge1xuICAgICAgcmV0dXJuIFtbXV07XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnRhYmxlLmJvZHkubWFwKHJvdyA9PiByb3cubWFwKGNlbGwgPT4gY2VsbC52YWx1ZSkpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignbW91c2Vkb3duJywgWyckZXZlbnQnXSlcbiAgcHJpdmF0ZSBtb3VzZWRvd24oZXY6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCB7IHJvdywgY29sLCB2YWxpZCB9ID0gdGhpcy5nZXRQb3NpdGlvbkZyb21JZChldi50YXJnZXQpO1xuICAgIGlmICghdmFsaWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5yYW5nZSA9IFJhbmdlLm9mKHJvdywgY29sKTtcbiAgICBpZiAoIWV2LnNoaWZ0S2V5IHx8ICF0aGlzLmFuY2hvcikge1xuICAgICAgdGhpcy5hbmNob3IgPSBuZXcgQW5jaG9yKHJvdywgY29sKTtcbiAgICB9XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDptb3VzZW1vdmUnLCBbJyRldmVudCddKVxuICBwcml2YXRlIG1vdXNlbW92ZShldjogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5yYW5nZSB8fCAhdGhpcy5hbmNob3IpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3Qgc2VsZiA9IHRoaXMuZ2V0UG9zaXRpb25Gcm9tSWQoZXYudGFyZ2V0KTtcbiAgICBpZiAoc2VsZi52YWxpZCkge1xuICAgICAgY29uc3QgcmFuZ2UgPSBSYW5nZS5tYXJnZSh7IHI6IHNlbGYucm93LCBjOiBzZWxmLmNvbCB9LCB0aGlzLmFuY2hvcik7XG4gICAgICBpZiAoIXRoaXMucmFuZ2U/LmVxdWFscyhyYW5nZSkpIHtcbiAgICAgICAgdGhpcy5yYW5nZSA9IHJhbmdlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50Om1vdXNldXAnLCBbJyRldmVudCddKVxuICBwcml2YXRlIG1vdXNldXAoZXY6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoZXYuc2hpZnRLZXkgJiYgdGhpcy5hbmNob3IpIHtcbiAgICAgIGNvbnN0IHNlbGYgPSB0aGlzLmdldFBvc2l0aW9uRnJvbUlkKGV2LnRhcmdldCk7XG4gICAgICBpZiAoc2VsZi52YWxpZCkge1xuICAgICAgICBjb25zdCByYW5nZSA9IFJhbmdlLm1hcmdlKHsgcjogc2VsZi5yb3csIGM6IHNlbGYuY29sIH0sIHRoaXMuYW5jaG9yKTtcbiAgICAgICAgaWYgKCF0aGlzLnJhbmdlPy5lcXVhbHMocmFuZ2UpKSB7XG4gICAgICAgICAgdGhpcy5yYW5nZSA9IHJhbmdlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMuYW5jaG9yID0gbnVsbDtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmtleWRvd24nLCBbJyRldmVudCddKVxuICBwcml2YXRlIG9uS2V5RG93bihldjogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGtleSA9IGV2LmtleS50b0xvd2VyQ2FzZSgpO1xuICAgIGNvbnN0IGlzQ3RybCA9ICgoZXYuY3RybEtleSAmJiAhZXYubWV0YUtleSkgfHwgKCFldi5jdHJsS2V5ICYmIGV2Lm1ldGFLZXkpKTtcbiAgICBpZiAoIXRoaXMudGFibGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuYW5jaG9yICYmIGV2LnNoaWZ0S2V5ICYmIHRoaXMuYWN0aXZhdGVkQ2VsbCkge1xuICAgICAgY29uc3QgeyByb3csIGNvbCB9ID0gdGhpcy5hY3RpdmF0ZWRDZWxsO1xuICAgICAgdGhpcy5hbmNob3IgPSBuZXcgQW5jaG9yKHJvdywgY29sKTtcbiAgICB9XG5cbiAgICBpZiAoa2V5ID09PSAnZW50ZXInICYmIHRoaXMuYWN0aXZhdGVkQ2VsbCkge1xuICAgICAgY29uc3QgeyByb3csIGNvbCwgZWRpdGFibGUgfSA9IHRoaXMuYWN0aXZhdGVkQ2VsbDtcbiAgICAgIGlmIChlZGl0YWJsZSAmJiBldi5zaGlmdEtleSkge1xuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLm1vdmVUbyhyb3cgKyAxLCBjb2wsIGZhbHNlLCBlZGl0YWJsZSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChrZXkgPT09ICd0YWInICYmIHRoaXMuYWN0aXZhdGVkQ2VsbCkge1xuICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGNvbnN0IHsgcm93Q291bnQsIGNvbENvdW50IH0gPSB0aGlzLnRhYmxlO1xuICAgICAgY29uc3QgeyByb3csIGNvbCwgZWRpdGFibGUgfSA9IHRoaXMuYWN0aXZhdGVkQ2VsbDtcbiAgICAgIGNvbnN0IG5leHQgPSBldi5zaGlmdEtleSA/IGNvbCAtIDEgOiBjb2wgKyAxO1xuICAgICAgaWYgKG5leHQgPCAwICYmIHJvdyA+IDApIHtcbiAgICAgICAgdGhpcy5tb3ZlVG8ocm93IC0gMSwgY29sQ291bnQgLSAxLCBmYWxzZSwgZWRpdGFibGUpO1xuICAgICAgfSBlbHNlIGlmIChuZXh0ID49IGNvbENvdW50ICYmIHJvdyA8IHJvd0NvdW50KSB7XG4gICAgICAgIHRoaXMubW92ZVRvKHJvdyArIDEsIDAsIGZhbHNlLCBlZGl0YWJsZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLm1vdmVUbyhyb3csIG5leHQsIGZhbHNlLCBlZGl0YWJsZSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChrZXkgPT09ICdmMicpIHtcbiAgICAgIHRoaXMuc2V0RWRpdGFibGUoZXYsIHRydWUpO1xuICAgIH0gZWxzZSBpZiAoa2V5ID09PSAnZXNjYXBlJykge1xuICAgICAgdGhpcy5zZXRFZGl0YWJsZShldiwgZmFsc2UpO1xuICAgIH0gZWxzZSBpZiAoa2V5ID09PSAnYycgJiYgaXNDdHJsKSB7XG4gICAgICB0aGlzLmNvcHkoKTtcbiAgICB9IGVsc2UgaWYgKGtleSA9PT0gJ3YnICYmIGlzQ3RybCkge1xuICAgICAgdGhpcy5wYXN0ZSgpO1xuICAgIH0gZWxzZSBpZiAoa2V5ID09PSAnZGVsZXRlJykge1xuICAgICAgdGhpcy5kZWxldGUoKTtcbiAgICB9XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDprZXl1cCcsIFsnJGV2ZW50J10pXG4gIHByaXZhdGUgb25LZXlVcChldjogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5hY3RpdmF0ZWRDZWxsIHx8IHRoaXMuYWN0aXZhdGVkQ2VsbC5lZGl0YWJsZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIWV2LnNoaWZ0S2V5KSB7XG4gICAgICB0aGlzLmFuY2hvciA9IG51bGw7XG4gICAgfVxuICAgIGNvbnN0IHsgcm93LCBjb2wgfSA9IHRoaXMuYWN0aXZhdGVkQ2VsbDtcbiAgICBzd2l0Y2ggKGV2LmtleS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICBjYXNlICdhcnJvd3VwJzpcbiAgICAgICAgdGhpcy5tb3ZlVG8ocm93IC0gMSwgY29sLCBldi5zaGlmdEtleSwgZmFsc2UpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2Fycm93ZG93bic6XG4gICAgICAgIHRoaXMubW92ZVRvKHJvdyArIDEsIGNvbCwgZXYuc2hpZnRLZXksIGZhbHNlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdhcnJvd2xlZnQnOlxuICAgICAgICB0aGlzLm1vdmVUbyhyb3csIGNvbCAtIDEsIGV2LnNoaWZ0S2V5LCBmYWxzZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnYXJyb3dyaWdodCc6XG4gICAgICAgIHRoaXMubW92ZVRvKHJvdywgY29sICsgMSwgZXYuc2hpZnRLZXksIGZhbHNlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgdHJhY2tCeUNlbGwoaW5kZXg6IG51bWJlciwgdmFsdWU6IENlbGwpOiBzdHJpbmcgfCBudWxsIHtcbiAgICByZXR1cm4gdmFsdWUgPyB2YWx1ZS5pZCA6IG51bGw7XG4gIH1cblxuICBjbGlja0hlYWRlcihjb2xJbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3Qgcm93TGVuZ3RoID0gdGhpcy50YWJsZT8uYm9keS5sZW5ndGggfHwgMDtcbiAgICBpZiAocm93TGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5yYW5nZSA9IFJhbmdlLm9mKDAsIGNvbEluZGV4LCByb3dMZW5ndGgsIGNvbEluZGV4KTtcbiAgICB9XG4gIH1cblxuICBjbGlja1Jvdyhyb3dJbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnRhYmxlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChyb3dJbmRleCA+PSAwICYmIHJvd0luZGV4IDwgdGhpcy50YWJsZS5ib2R5Lmxlbmd0aCkge1xuICAgICAgY29uc3QgY29scyA9IHRoaXMudGFibGUuYm9keVtyb3dJbmRleF07XG4gICAgICB0aGlzLnJhbmdlID0gUmFuZ2Uub2Yocm93SW5kZXgsIDAsIHJvd0luZGV4LCBjb2xzLmxlbmd0aCk7XG4gICAgfVxuICB9XG5cbiAgZm9jdXMoZXY6IEZvY3VzRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBmb3VuZCA9IHRoaXMuZmluZENlbGxCeUV2ZW50VGFyZ2V0KGV2LnRhcmdldCk7XG4gICAgdGhpcy5hY3RpdmF0ZWRDZWxsID0gZm91bmQ7XG4gIH1cblxuICBibHVyKGV2OiBGb2N1c0V2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgZm91bmQgPSB0aGlzLmZpbmRDZWxsQnlFdmVudFRhcmdldChldi50YXJnZXQpO1xuICAgIGlmIChmb3VuZCkge1xuICAgICAgZm91bmQuZWRpdGFibGUgPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBkYmxjbGljayhldjogRXZlbnQsIHRhcmdldDogQ2VsbCk6IHZvaWQge1xuICAgIGNvbnN0IHRkID0gZXYudGFyZ2V0IGFzIEhUTUxUYWJsZUNlbGxFbGVtZW50O1xuICAgIGlmICh0YXJnZXQgPT09IHRoaXMuYWN0aXZhdGVkQ2VsbCkge1xuICAgICAgdGFyZ2V0LmVkaXRhYmxlID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBzZXRWYWx1ZShldjogRXZlbnQsIHRhcmdldDogQ2VsbCk6IHZvaWQge1xuICAgIGNvbnN0IHZhbHVlID0gKGV2LnRhcmdldCBhcyBIVE1MVGFibGVDZWxsRWxlbWVudCkuaW5uZXJUZXh0IHx8ICcnO1xuICAgIHRhcmdldC52YWx1ZSA9IHZhbHVlO1xuICB9XG5cbiAgc2V0RWRpdGFibGUoZXY6IEV2ZW50LCBlZGl0YWJsZTogYm9vbGVhbik6IHZvaWQge1xuICAgIGV2LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIGNvbnN0IGZvdW5kID0gdGhpcy5maW5kQ2VsbEJ5RXZlbnRUYXJnZXQoZXYudGFyZ2V0KTtcbiAgICBpZiAoZm91bmQpIHtcbiAgICAgIGZvdW5kLmVkaXRhYmxlID0gZWRpdGFibGU7XG4gICAgfVxuICB9XG5cbiAgLy8jcmVnaW9uIG1lbnUgZXZlbnQgaGFuZGxlXG4gIHNob3dUaGVhZE1lbnUoZXY6IE1vdXNlRXZlbnQsIGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBldi5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB0aGlzLnRoZWFkQ29udGV4dE1lbnUuc2hvdyhldiwgaW5kZXgpO1xuICB9XG5cbiAgc2hvd1Rib2R5TWVudShldjogTW91c2VFdmVudCwgaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGV2LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIHRoaXMudGJvZHlDb250ZXh0TWVudS5zaG93KGV2LCBpbmRleCk7XG4gIH1cbiAgLy8jZW5kcmVnaW9uXG5cbiAgcHJpdmF0ZSBtb3ZlVG8ocm93OiBudW1iZXIsIGNvbDogbnVtYmVyLCBzaGlmdEtleTogYm9vbGVhbiwgZWRpdGFibGU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMudGFibGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgeyBib2R5IH0gPSB0aGlzLnRhYmxlO1xuICAgIGlmIChyb3cgPj0g