@one-grid-core/angular 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +55 -9
  2. package/esm2022/lib/components/one-grid/one-grid.component.mjs +244 -11
  3. package/esm2022/lib/components/one-grid-body/one-grid-body.component.mjs +446 -34
  4. package/esm2022/lib/components/one-grid-cell-currency/one-grid-cell-currency.component.mjs +6 -5
  5. package/esm2022/lib/components/one-grid-cell-group-renderer/one-grid-cell-group-renderer.component.mjs +3 -3
  6. package/esm2022/lib/components/one-grid-cell-option-menu/one-grid-cell-option-menu.component.mjs +3 -3
  7. package/esm2022/lib/components/one-grid-checkbox/one-grid-checkbox.component.mjs +7 -18
  8. package/esm2022/lib/components/one-grid-checkbox-header/one-grid-checkbox-header.component.mjs +6 -6
  9. package/esm2022/lib/components/one-grid-header/one-grid-header.component.mjs +221 -17
  10. package/esm2022/lib/components/one-grid-header-menu/one-grid-header-menu.component.mjs +137 -0
  11. package/esm2022/lib/components/one-grid-pagination/one-grid-pagination.component.mjs +6 -5
  12. package/esm2022/lib/components/one-grid-row-action/one-grid-row-action.component.mjs +4 -4
  13. package/esm2022/lib/components/one-grid-row-drag-handle/one-grid-row-drag-handle.component.mjs +5 -3
  14. package/esm2022/lib/components/one-grid-status/one-grid-status.component.mjs +4 -4
  15. package/esm2022/lib/core/directives/one-cell-input-validator.directive.mjs +3 -3
  16. package/esm2022/lib/core/directives/one-cell-renderer-component.directive.mjs +3 -3
  17. package/esm2022/lib/core/directives/one-cell-text-expand.directive.mjs +3 -3
  18. package/esm2022/lib/core/icons/one-grid-icons.mjs +38 -0
  19. package/esm2022/lib/core/instants/one-grid-api.class.mjs +296 -3
  20. package/esm2022/lib/core/models/one-column-def-types.model.mjs +1 -1
  21. package/esm2022/lib/core/models/one-event-types.model.mjs +1 -1
  22. package/esm2022/lib/core/models/one-filter.model.mjs +1 -1
  23. package/esm2022/lib/core/pipes/aria-sort.pipe.mjs +31 -0
  24. package/esm2022/lib/core/pipes/cell-action-button-enable.pipe.mjs +3 -3
  25. package/esm2022/lib/core/pipes/cell-editable.pipe.mjs +3 -3
  26. package/esm2022/lib/core/pipes/cell-invalid.pipe.mjs +3 -3
  27. package/esm2022/lib/core/pipes/cell-key.pipe.mjs +3 -3
  28. package/esm2022/lib/core/pipes/cell-level-padding.pipe.mjs +3 -3
  29. package/esm2022/lib/core/pipes/cell-selected.pipe.mjs +3 -3
  30. package/esm2022/lib/core/pipes/cell-state-renderer.pipe.mjs +3 -3
  31. package/esm2022/lib/core/pipes/column-sort-state.pipe.mjs +3 -3
  32. package/esm2022/lib/core/pipes/header-checkbox-checked.pipe.mjs +3 -3
  33. package/esm2022/lib/core/pipes/header-checkbox-disabled.pipe.mjs +3 -3
  34. package/esm2022/lib/core/pipes/header-checkbox-indeterminate.pipe.mjs +3 -3
  35. package/esm2022/lib/core/services/og-column.service.mjs +153 -30
  36. package/esm2022/lib/core/services/one-grid-cell.service.mjs +39 -15
  37. package/esm2022/lib/helpers/one-cell.helper.mjs +30 -1
  38. package/esm2022/lib/helpers/one-column-def.helper.mjs +16 -1
  39. package/esm2022/lib/helpers/one-csv.helper.mjs +58 -0
  40. package/esm2022/lib/helpers/one-filter.helper.mjs +11 -1
  41. package/esm2022/lib/helpers/one-row-grouping.helper.mjs +103 -0
  42. package/esm2022/lib/index.mjs +3 -1
  43. package/esm2022/lib/one-grid.module.mjs +24 -114
  44. package/fesm2022/one-grid-core-angular.mjs +2322 -823
  45. package/fesm2022/one-grid-core-angular.mjs.map +1 -1
  46. package/lib/components/one-grid/one-grid.component.d.ts +101 -4
  47. package/lib/components/one-grid-body/one-grid-body.component.d.ts +83 -2
  48. package/lib/components/one-grid-cell-currency/one-grid-cell-currency.component.d.ts +1 -1
  49. package/lib/components/one-grid-cell-group-renderer/one-grid-cell-group-renderer.component.d.ts +1 -1
  50. package/lib/components/one-grid-cell-option-menu/one-grid-cell-option-menu.component.d.ts +1 -1
  51. package/lib/components/one-grid-checkbox/one-grid-checkbox.component.d.ts +1 -1
  52. package/lib/components/one-grid-checkbox-header/one-grid-checkbox-header.component.d.ts +1 -1
  53. package/lib/components/one-grid-header/one-grid-header.component.d.ts +69 -4
  54. package/lib/components/one-grid-header-menu/one-grid-header-menu.component.d.ts +52 -0
  55. package/lib/components/one-grid-pagination/one-grid-pagination.component.d.ts +1 -1
  56. package/lib/components/one-grid-row-action/one-grid-row-action.component.d.ts +1 -1
  57. package/lib/components/one-grid-row-drag-handle/one-grid-row-drag-handle.component.d.ts +1 -1
  58. package/lib/components/one-grid-status/one-grid-status.component.d.ts +1 -1
  59. package/lib/core/directives/one-cell-input-validator.directive.d.ts +1 -1
  60. package/lib/core/directives/one-cell-renderer-component.directive.d.ts +1 -1
  61. package/lib/core/directives/one-cell-text-expand.directive.d.ts +1 -1
  62. package/lib/core/icons/one-grid-icons.d.ts +35 -0
  63. package/lib/core/instants/one-grid-api.class.d.ts +115 -1
  64. package/lib/core/models/one-column-def-types.model.d.ts +77 -2
  65. package/lib/core/models/one-event-types.model.d.ts +19 -0
  66. package/lib/core/models/one-filter.model.d.ts +8 -1
  67. package/lib/core/pipes/aria-sort.pipe.d.ts +15 -0
  68. package/lib/core/pipes/cell-action-button-enable.pipe.d.ts +1 -1
  69. package/lib/core/pipes/cell-editable.pipe.d.ts +1 -1
  70. package/lib/core/pipes/cell-invalid.pipe.d.ts +1 -1
  71. package/lib/core/pipes/cell-key.pipe.d.ts +1 -1
  72. package/lib/core/pipes/cell-level-padding.pipe.d.ts +1 -1
  73. package/lib/core/pipes/cell-selected.pipe.d.ts +1 -1
  74. package/lib/core/pipes/cell-state-renderer.pipe.d.ts +1 -1
  75. package/lib/core/pipes/column-sort-state.pipe.d.ts +1 -1
  76. package/lib/core/pipes/header-checkbox-checked.pipe.d.ts +1 -1
  77. package/lib/core/pipes/header-checkbox-disabled.pipe.d.ts +1 -1
  78. package/lib/core/pipes/header-checkbox-indeterminate.pipe.d.ts +1 -1
  79. package/lib/core/services/og-column.service.d.ts +46 -2
  80. package/lib/core/services/one-grid-cell.service.d.ts +16 -3
  81. package/lib/helpers/one-cell.helper.d.ts +17 -0
  82. package/lib/helpers/one-column-def.helper.d.ts +9 -0
  83. package/lib/helpers/one-csv.helper.d.ts +29 -0
  84. package/lib/helpers/one-row-grouping.helper.d.ts +35 -0
  85. package/lib/index.d.ts +2 -0
  86. package/lib/one-grid.module.d.ts +15 -37
  87. package/package.json +1 -1
  88. package/scss/_one-grid.scss +127 -0
  89. package/esm2022/lib/core/pipes/cell-action-button-visible.pipe.mjs +0 -17
  90. package/esm2022/lib/core/pipes/cell-field-value-empty.pipe.mjs +0 -26
  91. package/esm2022/lib/core/pipes/cell-field-value.pipe.mjs +0 -25
  92. package/esm2022/lib/core/pipes/cell-field.pipe.mjs +0 -20
  93. package/esm2022/lib/core/pipes/cell-number-value.pipe.mjs +0 -19
  94. package/esm2022/lib/core/pipes/cell-state-group-renderer.pipe.mjs +0 -21
  95. package/esm2022/lib/core/pipes/cell-value-getter.pipe.mjs +0 -23
  96. package/lib/core/pipes/cell-action-button-visible.pipe.d.ts +0 -9
  97. package/lib/core/pipes/cell-field-value-empty.pipe.d.ts +0 -7
  98. package/lib/core/pipes/cell-field-value.pipe.d.ts +0 -7
  99. package/lib/core/pipes/cell-field.pipe.d.ts +0 -7
  100. package/lib/core/pipes/cell-number-value.pipe.d.ts +0 -7
  101. package/lib/core/pipes/cell-state-group-renderer.pipe.d.ts +0 -9
  102. package/lib/core/pipes/cell-value-getter.pipe.d.ts +0 -9
@@ -1,12 +1,17 @@
1
- import { Component, Input, ViewChild } from '@angular/core';
2
- import { Subscription } from 'rxjs';
1
+ import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
2
+ import { Subject, Subscription } from 'rxjs';
3
+ import { debounceTime } from 'rxjs/operators';
3
4
  import { resolveColumnWidth } from '../../helpers/one-column-def.helper';
5
+ import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common';
6
+ import { LucideAngularModule } from 'lucide-angular';
7
+ import { ONE_GRID_ICON_PROVIDERS } from '../../core/icons/one-grid-icons';
8
+ import { OneGridCheckboxHeaderComponent } from '../one-grid-checkbox-header/one-grid-checkbox-header.component';
9
+ import { OneGridHeaderMenuComponent } from '../one-grid-header-menu/one-grid-header-menu.component';
10
+ import { ColumnSortStatePipe } from '../../core/pipes/column-sort-state.pipe';
11
+ import { AriaSortPipe } from '../../core/pipes/aria-sort.pipe';
4
12
  import * as i0 from "@angular/core";
5
13
  import * as i1 from "../../core/services/one-grid-event.service";
6
- import * as i2 from "@angular/common";
7
- import * as i3 from "lucide-angular";
8
- import * as i4 from "../one-grid-checkbox-header/one-grid-checkbox-header.component";
9
- import * as i5 from "../../core/pipes/column-sort-state.pipe";
14
+ import * as i2 from "lucide-angular";
10
15
  export class OneGridHeaderComponent {
11
16
  /**
12
17
  * Horizontal offset of the body, mirrored here so the header tracks it.
@@ -22,9 +27,10 @@ export class OneGridHeaderComponent {
22
27
  get scrollLeft() {
23
28
  return this._scrollLeft;
24
29
  }
25
- constructor(eventService, cdr) {
30
+ constructor(eventService, cdr, elementRef) {
26
31
  this.eventService = eventService;
27
32
  this.cdr = cdr;
33
+ this.elementRef = elementRef;
28
34
  this._scrollLeft = 0;
29
35
  this.allowedEdit = false;
30
36
  this.enableGroupColumnDefs = false;
@@ -33,11 +39,51 @@ export class OneGridHeaderComponent {
33
39
  this.sortModel = [];
34
40
  this.subscriptions = new Subscription();
35
41
  this.draggedIndex = null;
42
+ /** Where the drag started, for reporting the completed move as one event. */
43
+ this.dragSourceIndex = null;
36
44
  // Track resize state
37
45
  this.resizing = false;
38
46
  this.resizeColumnIndex = null;
39
47
  this.startX = 0;
40
48
  this.startWidth = 0;
49
+ /**
50
+ * Render a filter input under each column whose `filterable` resolves true.
51
+ *
52
+ * The inputs build a contains-filter per column and hand it to
53
+ * `api.setFilterModel`, debounced. Fields without a filter input are left
54
+ * alone: a programmatic filter on a non-filterable column survives typing
55
+ * here, while the filterable fields belong to the row — last writer wins.
56
+ */
57
+ this.filterRow = false;
58
+ /** Current filter text per field. */
59
+ this.filterTexts = {};
60
+ this.filterInput$ = new Subject();
61
+ /**
62
+ * Minimum a column can be resized to, by pointer or keyboard.
63
+ *
64
+ * Exposed to the template for `aria-valuemin`, so what the resizer announces
65
+ * and what it enforces cannot drift apart.
66
+ */
67
+ this.MIN_COLUMN_WIDTH = 50;
68
+ /**
69
+ * The header's ⋮ button was a div with an empty handler — it rendered,
70
+ * looked interactive, and did nothing at all. Making it keyboard-reachable
71
+ * without giving it a purpose would only have added a dead tab stop per
72
+ * column, so it now reports the press the same way every row action does and
73
+ * the host decides what a column menu means.
74
+ */
75
+ this.headerMenuClick = new EventEmitter();
76
+ /**
77
+ * Render the grid's default column menu behind the ⋮ button.
78
+ *
79
+ * Opt-in: hosts that bound `(headerMenuClick)` to open their own menu keep
80
+ * exactly the behaviour they had — the intent still emits either way.
81
+ */
82
+ this.headerMenu = false;
83
+ /** The column whose default menu is open, or null. */
84
+ this.openMenuColumn = null;
85
+ /** Distance from the header's right edge to the open column's, in px. */
86
+ this.menuOffsetRight = 0;
41
87
  // Arrow function to preserve 'this' context
42
88
  this.onResizeMove = (event) => {
43
89
  if (!this.resizing || this.resizeColumnIndex === null)
@@ -45,11 +91,21 @@ export class OneGridHeaderComponent {
45
91
  // Calculate how far the mouse has moved
46
92
  const deltaX = event.clientX - this.startX;
47
93
  // Calculate new width (with minimum of 50px)
48
- const newWidth = Math.max(50, this.startWidth + deltaX);
49
- // Update the column width
50
- this.api.updateColumn(this.columnDefs[this.resizeColumnIndex].id, { width: newWidth });
94
+ const newWidth = Math.max(this.MIN_COLUMN_WIDTH, this.startWidth + deltaX);
95
+ // Update the column width. A hand-resized column stops flexing, or the
96
+ // next reflow would overwrite the width the user is dragging out.
97
+ this.api.updateColumn(this.columnDefs[this.resizeColumnIndex].id, { width: newWidth, flex: undefined });
51
98
  };
52
99
  this.onResizeEnd = () => {
100
+ // One event per completed gesture, not one per mousemove — and none at all
101
+ // for a click on the handle that never moved.
102
+ if (this.resizeColumnIndex !== null) {
103
+ const column = this.columnDefs[this.resizeColumnIndex];
104
+ const newWidth = column?.width ?? this.startWidth;
105
+ if (column && newWidth !== this.startWidth) {
106
+ this.eventService.dispatchEvent('columnResized', { columnId: column.id, newWidth });
107
+ }
108
+ }
53
109
  // Clean up
54
110
  this.resizing = false;
55
111
  this.resizeColumnIndex = null;
@@ -59,7 +115,30 @@ export class OneGridHeaderComponent {
59
115
  document.removeEventListener('mouseup', this.onResizeEnd);
60
116
  };
61
117
  }
118
+ /** Debounce for the filter row, in ms. */
119
+ static { this.FILTER_DEBOUNCE = 200; }
120
+ onFilterInput(col, event) {
121
+ this.filterTexts[col.field] = event.target.value;
122
+ this.filterInput$.next();
123
+ }
124
+ applyFilterRow() {
125
+ const managed = new Set(this.columnDefs
126
+ .filter(column => column._resolvedFilterable && column.field)
127
+ .map(column => column.field));
128
+ const preserved = this.api.getFilterModel().filter(entry => !managed.has(entry.field));
129
+ const own = Object.entries(this.filterTexts)
130
+ .filter(([field, text]) => managed.has(field) && text.trim() !== '')
131
+ .map(([field, text]) => ({
132
+ field,
133
+ logicOperator: 'AND',
134
+ conditions: [{ operator: 'contains', value: text.trim() }],
135
+ }));
136
+ this.api.setFilterModel([...preserved, ...own]);
137
+ }
62
138
  ngOnInit() {
139
+ this.subscriptions.add(this.filterInput$
140
+ .pipe(debounceTime(OneGridHeaderComponent.FILTER_DEBOUNCE))
141
+ .subscribe(() => this.applyFilterRow()));
63
142
  // Listen Column Changed Event
64
143
  this.subscriptions.add(this.eventService.addEventListener('columnChanged', (payload) => {
65
144
  const { groups, columns } = payload;
@@ -82,7 +161,100 @@ export class OneGridHeaderComponent {
82
161
  this.headerViewport.nativeElement.scrollLeft = this._scrollLeft;
83
162
  }
84
163
  }
85
- onHeaderMenuOptionClick(columnDef) {
164
+ onHeaderMenuOptionClick(columnDef, event) {
165
+ this.headerMenuClick.emit(columnDef);
166
+ if (!this.headerMenu)
167
+ return;
168
+ if (this.openMenuColumn?.id === columnDef.id) {
169
+ this.openMenuColumn = null;
170
+ return;
171
+ }
172
+ // Right-aligned under the opening column. Measured because the menu
173
+ // cannot render inside the column — every box in the header clips — so
174
+ // it sits outside and has to be told where the column is.
175
+ const columnElement = event?.target?.closest('.one-grid-header-column');
176
+ const hostElement = this.elementRef.nativeElement;
177
+ this.menuOffsetRight = columnElement
178
+ ? Math.max(hostElement.getBoundingClientRect().right - columnElement.getBoundingClientRect().right, 0)
179
+ : 0;
180
+ this.openMenuColumn = columnDef;
181
+ }
182
+ /** The open column's current sort, so the menu offers the other states. */
183
+ menuSortState(col) {
184
+ return this.api.sortModel.find(entry => entry.colId === col.field)?.sort ?? null;
185
+ }
186
+ onHeaderMenuAction(action, col) {
187
+ switch (action) {
188
+ case 'sortAsc':
189
+ case 'sortDesc': {
190
+ // Mirrors a sort-button click: a single-column model. The header's own
191
+ // cycle state follows, so the sort button keeps cycling from here.
192
+ this.sortModel = [{ colId: col.field, sort: action === 'sortAsc' ? 'asc' : 'desc' }];
193
+ this.api.onSortChanged(this.sortModel);
194
+ return;
195
+ }
196
+ case 'clearSort':
197
+ this.sortModel = [];
198
+ this.api.onSortChanged(this.sortModel);
199
+ return;
200
+ case 'pinLeft':
201
+ this.api.updateColumn(col.id, { pinned: 'left' });
202
+ return;
203
+ case 'pinRight':
204
+ this.api.updateColumn(col.id, { pinned: 'right' });
205
+ return;
206
+ case 'unpin':
207
+ this.api.updateColumn(col.id, { pinned: undefined });
208
+ return;
209
+ case 'hide':
210
+ this.api.setColumnVisible(col.id, false);
211
+ return;
212
+ }
213
+ }
214
+ closeHeaderMenu() {
215
+ this.openMenuColumn = null;
216
+ }
217
+ /**
218
+ * Resize from the keyboard.
219
+ *
220
+ * The pointer path is a drag, and WCAG 2.5.7 requires a single-pointer
221
+ * alternative that is not one. Arrows step, shift steps coarser, and
222
+ * Home/End go to the column's own bounds.
223
+ */
224
+ onResizeKeydown(event, columnIndex) {
225
+ const column = this.columnDefs[columnIndex];
226
+ if (!column)
227
+ return;
228
+ const step = event.shiftKey ? 50 : 10;
229
+ const current = column.width ?? resolveColumnWidth(column);
230
+ let width;
231
+ switch (event.key) {
232
+ case 'ArrowLeft':
233
+ width = current - step;
234
+ break;
235
+ case 'ArrowRight':
236
+ width = current + step;
237
+ break;
238
+ case 'Home':
239
+ width = column.minWidth ?? this.MIN_COLUMN_WIDTH;
240
+ break;
241
+ case 'End':
242
+ width = column.maxWidth ?? current + step;
243
+ break;
244
+ default: return;
245
+ }
246
+ event.preventDefault();
247
+ const min = Math.max(column.minWidth ?? 0, this.MIN_COLUMN_WIDTH);
248
+ const max = column.maxWidth ?? Number.POSITIVE_INFINITY;
249
+ const newWidth = Math.min(Math.max(width, min), max);
250
+ // Home at the minimum, End at the maximum: already clamped there, nothing
251
+ // changed, nothing to announce.
252
+ if (newWidth === current)
253
+ return;
254
+ // A hand-resized column stops flexing — otherwise the next reflow would
255
+ // overwrite the width the user just chose.
256
+ this.api.updateColumn(column.id, { width: newWidth, flex: undefined });
257
+ this.eventService.dispatchEvent('columnResized', { columnId: column.id, newWidth });
86
258
  }
87
259
  onHeaderMenuSortClick(colId) {
88
260
  const currentSort = this.sortModel.find(sort => sort.colId === colId)?.sort ?? null;
@@ -122,6 +294,7 @@ export class OneGridHeaderComponent {
122
294
  // Track the dragged column index
123
295
  onDragColumnStart(event, index) {
124
296
  this.draggedIndex = index;
297
+ this.dragSourceIndex = index;
125
298
  // Optional: Set drag image/effect
126
299
  if (event.dataTransfer) {
127
300
  event.dataTransfer.effectAllowed = 'move';
@@ -139,11 +312,27 @@ export class OneGridHeaderComponent {
139
312
  this.draggedIndex = targetIndex;
140
313
  }
141
314
  onDragColumnEnd(event) {
142
- this.draggedIndex = null;
315
+ this.finishColumnDrag();
143
316
  }
144
317
  onDropColumn(event) {
145
318
  event.preventDefault();
319
+ this.finishColumnDrag();
320
+ }
321
+ /**
322
+ * The reorder itself already happened, step by step, during dragover — this
323
+ * only reports the completed move. Both `drop` and `dragend` funnel here and
324
+ * both can fire for one gesture; nulling the indexes makes the second call a
325
+ * no-op, so one gesture reports once.
326
+ */
327
+ finishColumnDrag() {
328
+ if (this.draggedIndex !== null && this.dragSourceIndex !== null && this.draggedIndex !== this.dragSourceIndex) {
329
+ const column = this.columnDefs[this.draggedIndex];
330
+ if (column) {
331
+ this.eventService.dispatchEvent('columnMoved', { columnId: column.id, toIndex: this.draggedIndex });
332
+ }
333
+ }
146
334
  this.draggedIndex = null;
335
+ this.dragSourceIndex = null;
147
336
  }
148
337
  ngOnDestroy() {
149
338
  // This completed an unused Subject and left the real subscription running.
@@ -156,13 +345,22 @@ export class OneGridHeaderComponent {
156
345
  this.onResizeEnd();
157
346
  }
158
347
  }
159
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OneGridHeaderComponent, deps: [{ token: i1.OneGridEventService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
160
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: OneGridHeaderComponent, selector: "one-grid-header", inputs: { scrollLeft: "scrollLeft", allowedEdit: "allowedEdit", enableGroupColumnDefs: "enableGroupColumnDefs", api: "api" }, viewQueries: [{ propertyName: "headerViewport", first: true, predicate: ["headerViewport"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"one-grid-header\">\n @if (enableGroupColumnDefs) {\n <div class=\"one-group-header-row\" [style.transform]=\"'translateX(-' + scrollLeft + 'px)'\">\n <ng-container *ngTemplateOutlet=\"groupColumns; context: { groups: groupColumnDefs }\"></ng-container>\n </div>\n }\n <!-- The column row is scrolled rather than translated. `position: sticky`\n resolves against the nearest scrollport, and a transformed ancestor is\n not one \u2014 pinned headers could never hold their place inside it. The\n group row above keeps its transform: groups span contiguous columns,\n which pinning reorders, so the two features do not combine. -->\n <div #headerViewport class=\"one-grid-header-viewport\">\n <div class=\"one-header-row\">\n <ng-container *ngTemplateOutlet=\"headerColumns; context: { columns: columnDefs }\"></ng-container>\n </div>\n </div>\n</div>\n\n<!-- Group Header Cell Template -->\n<ng-template #groupColumns let-groups=\"groups\">\n @for(group of groups; track group.id) {\n <div class=\"one-group-header-cell\"\n [style.width.px]=\"group.width\"\n [ngClass]=\"group._resolvedGroupClass\"\n [ngStyle]=\"group._resolvedGroupStyle\">\n <div class=\"one-group-header-cell-text\">\n {{ group.headerName }}\n </div>\n </div>\n }\n</ng-template>\n\n<!-- Header Cell Template -->\n<ng-template #headerColumns let-columns=\"columns\">\n @for (col of columns; let colIndex = $index; track col.id) {\n <div class=\"one-grid-header-column\"\n [attr.data-index]=\"colIndex\"\n [class.one-column-pinned-left]=\"col.pinned === 'left'\"\n [class.one-column-pinned-right]=\"col.pinned === 'right'\"\n [class.one-column-pinned-edge]=\"col._pinnedEdge\"\n [class.one-column-pinned-edge]=\"col._pinnedEdge\"\n [style.left.px]=\"col.pinned === 'left' ? col._pinnedOffset : null\"\n [style.right.px]=\"col.pinned === 'right' ? col._pinnedOffset : null\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.minWidth\"\n [style.max-width.px]=\"col.maxWidth\"\n [draggable]=\"col._resolvedDragable\"\n (dragstart)=\"onDragColumnStart($event, colIndex)\"\n (dragover)=\"onDragColumnOver($event, colIndex)\"\n (dragend)=\"onDragColumnEnd($event)\"\n (drop)=\"onDropColumn($event)\">\n <div class=\"one-grid-header-cell\"\n [ngClass]=\"col._resolvedHeaderClass\"\n [ngStyle]=\"col._resolvedHeaderStyle\"\n >\n <span class=\"one-grid-header-cell-group\">\n @if (col?.headerCheckboxSelection) {\n <one-grid-checkbox-header\n [api]=\"api\"\n [allowedEdit]=\"allowedEdit\"\n />\n }\n\n {{ col?.headerName ?? '' }}\n </span>\n\n <!-- Og Resize Handler -->\n @if (col._resolvedResizable) {\n <div class=\"og-resize-handle\" (mousedown)=\"onResizeStart($event, colIndex)\">\n <i class=\"bi bi-grip-vertical\"></i>\n </div>\n }\n\n <div class=\"one-grid-header-cell-group\">\n\n <!-- Sort Menu Button -->\n @if (col._resolvedSortable) {\n <div class=\"one-grid-header-menu-button\" (click)=\"onHeaderMenuSortClick(col.field)\">\n\n @if ((col.field | columnSortState:api.sortModel) === 'asc') {\n <lucide-icon name=\"arrow-up-a-z\" [size]=\"16\" [strokeWidth]=\"2\"></lucide-icon>\n }\n @else if ((col.field | columnSortState:api.sortModel) === 'desc') {\n <lucide-icon name=\"arrow-down-z-a\" [size]=\"16\" [strokeWidth]=\"2\"></lucide-icon>\n }\n @else {\n <lucide-icon name=\"arrow-down-up\" [size]=\"16\" [strokeWidth]=\"2\"></lucide-icon>\n }\n </div>\n }\n\n <!-- Og Option Menu Button -->\n @if (col && !col._resolvedSuppressHeaderMenuButton) {\n <div class=\"one-grid-header-menu-button\" (click)=\"onHeaderMenuOptionClick(col)\">\n <i class=\"bi bi-three-dots-vertical\"></i>\n </div>\n }\n </div>\n </div>\n </div>\n }\n</ng-template>\n", styles: [""], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i3.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: i4.OneGridCheckboxHeaderComponent, selector: "one-grid-checkbox-header", inputs: ["api", "allowedEdit"] }, { kind: "pipe", type: i5.ColumnSortStatePipe, name: "columnSortState" }] }); }
348
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OneGridHeaderComponent, deps: [{ token: i1.OneGridEventService }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
349
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: OneGridHeaderComponent, isStandalone: true, selector: "one-grid-header", inputs: { scrollLeft: "scrollLeft", allowedEdit: "allowedEdit", enableGroupColumnDefs: "enableGroupColumnDefs", api: "api", filterRow: "filterRow", headerMenu: "headerMenu" }, outputs: { headerMenuClick: "headerMenuClick" }, host: { attributes: { "role": "presentation" } }, providers: [ONE_GRID_ICON_PROVIDERS], viewQueries: [{ propertyName: "headerViewport", first: true, predicate: ["headerViewport"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"one-grid-header\" role=\"rowgroup\">\n @if (enableGroupColumnDefs) {\n <div class=\"one-group-header-row\" role=\"presentation\" [style.transform]=\"'translateX(-' + scrollLeft + 'px)'\">\n <ng-container *ngTemplateOutlet=\"groupColumns; context: { groups: groupColumnDefs }\"></ng-container>\n </div>\n }\n <!-- The column row is scrolled rather than translated. `position: sticky`\n resolves against the nearest scrollport, and a transformed ancestor is\n not one \u2014 pinned headers could never hold their place inside it. The\n group row above keeps its transform: groups span contiguous columns,\n which pinning reorders, so the two features do not combine. -->\n <div #headerViewport class=\"one-grid-header-viewport\" role=\"presentation\">\n <div class=\"one-header-row\" role=\"row\" aria-rowindex=\"1\">\n <ng-container *ngTemplateOutlet=\"headerColumns; context: { columns: columnDefs }\"></ng-container>\n </div>\n\n <!-- Filter Row (grid opt-in). Lives inside the header viewport so it\n scrolls with the columns and its pinned cells stick the same way. -->\n @if (filterRow) {\n <div class=\"one-filter-row\" role=\"row\" aria-rowindex=\"2\">\n @for (col of columnDefs; track col.id) {\n <div class=\"one-filter-cell\"\n role=\"gridcell\"\n [attr.aria-colindex]=\"$index + 1\"\n [class.one-column-pinned-left]=\"col.pinned === 'left'\"\n [class.one-column-pinned-right]=\"col.pinned === 'right'\"\n [class.one-column-pinned-edge]=\"col._pinnedEdge\"\n [style.left.px]=\"col.pinned === 'left' ? col._pinnedOffset : null\"\n [style.right.px]=\"col.pinned === 'right' ? col._pinnedOffset : null\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.minWidth\"\n [style.max-width.px]=\"col.maxWidth\">\n @if (col._resolvedFilterable && col.field) {\n <input class=\"one-filter-input\"\n type=\"text\"\n [attr.aria-label]=\"'Filter ' + (col.headerName || col.field)\"\n [value]=\"filterTexts[col.field] ?? ''\"\n (input)=\"onFilterInput(col, $event)\" />\n }\n </div>\n }\n </div>\n }\n </div>\n</div>\n\n<!-- The default column menu (grid opt-in). A sibling of the header block\n because everything inside it clips with overflow: hidden; the host\n positions it just below, right-aligned to the opening column. -->\n@if (headerMenu && openMenuColumn) {\n <one-grid-header-menu\n [style.right.px]=\"menuOffsetRight\"\n [column]=\"openMenuColumn\"\n [sortState]=\"menuSortState(openMenuColumn)\"\n [canHide]=\"columnDefs.length > 1\"\n (menuAction)=\"onHeaderMenuAction($event, openMenuColumn)\"\n (menuClose)=\"closeHeaderMenu()\" />\n}\n\n<!-- Group Header Cell Template -->\n<ng-template #groupColumns let-groups=\"groups\">\n @for(group of groups; track group.id) {\n <div class=\"one-group-header-cell\"\n [style.width.px]=\"group.width\"\n [ngClass]=\"group._resolvedGroupClass\"\n [ngStyle]=\"group._resolvedGroupStyle\">\n <div class=\"one-group-header-cell-text\">\n {{ group.headerName }}\n </div>\n </div>\n }\n</ng-template>\n\n<!-- Header Cell Template -->\n<ng-template #headerColumns let-columns=\"columns\">\n @for (col of columns; let colIndex = $index; track col.id) {\n <div class=\"one-grid-header-column\"\n role=\"columnheader\"\n [attr.aria-colindex]=\"colIndex + 1\"\n [attr.aria-sort]=\"col.field | columnSortState:api.sortModel | ariaSort:col._resolvedSortable\"\n [attr.data-index]=\"colIndex\"\n [class.one-column-pinned-left]=\"col.pinned === 'left'\"\n [class.one-column-pinned-right]=\"col.pinned === 'right'\"\n [class.one-column-pinned-edge]=\"col._pinnedEdge\"\n [class.one-column-pinned-edge]=\"col._pinnedEdge\"\n [style.left.px]=\"col.pinned === 'left' ? col._pinnedOffset : null\"\n [style.right.px]=\"col.pinned === 'right' ? col._pinnedOffset : null\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.minWidth\"\n [style.max-width.px]=\"col.maxWidth\"\n [draggable]=\"col._resolvedDragable\"\n (dragstart)=\"onDragColumnStart($event, colIndex)\"\n (dragover)=\"onDragColumnOver($event, colIndex)\"\n (dragend)=\"onDragColumnEnd($event)\"\n (drop)=\"onDropColumn($event)\">\n <div class=\"one-grid-header-cell\"\n [ngClass]=\"col._resolvedHeaderClass\"\n [ngStyle]=\"col._resolvedHeaderStyle\"\n >\n <span class=\"one-grid-header-cell-group\">\n @if (col?.headerCheckboxSelection) {\n <one-grid-checkbox-header\n [api]=\"api\"\n [allowedEdit]=\"allowedEdit\"\n />\n }\n\n {{ col?.headerName ?? '' }}\n </span>\n\n <!-- Og Resize Handler -->\n @if (col._resolvedResizable) {\n <!-- `separator` is the ARIA window-splitter pattern, which is\n what a column resizer is. Focusable and arrow-operable\n because WCAG 2.5.7 requires everything achievable by\n dragging to have a non-dragging alternative. -->\n <div\n class=\"og-resize-handle\"\n role=\"separator\"\n tabindex=\"0\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"'Resize ' + (col.headerName || col.field)\"\n [attr.aria-valuenow]=\"col.width\"\n [attr.aria-valuemin]=\"col.minWidth || MIN_COLUMN_WIDTH\"\n [attr.aria-valuemax]=\"col.maxWidth || null\"\n (mousedown)=\"onResizeStart($event, colIndex)\"\n (keydown)=\"onResizeKeydown($event, colIndex)\">\n <i class=\"bi bi-grip-vertical\"></i>\n </div>\n }\n\n <div class=\"one-grid-header-cell-group\">\n\n <!-- Sort Menu Button -->\n @if (col._resolvedSortable) {\n <!-- A button, not a div with a click handler: sorting was\n pointer-only. The current state is not repeated here \u2014\n it is on the columnheader's `aria-sort`, and saying it\n twice makes a screen reader read it twice. -->\n <button\n type=\"button\"\n class=\"one-grid-header-menu-button\"\n [attr.aria-label]=\"'Sort by ' + (col.headerName || col.field)\"\n [title]=\"'Sort by ' + (col.headerName || col.field)\"\n (click)=\"onHeaderMenuSortClick(col.field)\">\n\n @if ((col.field | columnSortState:api.sortModel) === 'asc') {\n <lucide-icon name=\"arrow-up-a-z\" [size]=\"16\" [strokeWidth]=\"2\"></lucide-icon>\n }\n @else if ((col.field | columnSortState:api.sortModel) === 'desc') {\n <lucide-icon name=\"arrow-down-z-a\" [size]=\"16\" [strokeWidth]=\"2\"></lucide-icon>\n }\n @else {\n <lucide-icon name=\"arrow-down-up\" [size]=\"16\" [strokeWidth]=\"2\"></lucide-icon>\n }\n </button>\n }\n\n <!-- Og Option Menu Button -->\n @if (col && !col._resolvedSuppressHeaderMenuButton) {\n <button\n type=\"button\"\n class=\"one-grid-header-menu-button\"\n [attr.aria-label]=\"'Options for ' + (col.headerName || col.field)\"\n [attr.aria-haspopup]=\"headerMenu ? 'menu' : null\"\n [attr.aria-expanded]=\"headerMenu ? openMenuColumn?.id === col.id : null\"\n [title]=\"'Options for ' + (col.headerName || col.field)\"\n (click)=\"onHeaderMenuOptionClick(col, $event)\">\n <i class=\"bi bi-three-dots-vertical\"></i>\n </button>\n }\n </div>\n </div>\n </div>\n }\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{display:block;position:relative}one-grid-header-menu{position:absolute;top:100%;z-index:1000}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i2.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: OneGridCheckboxHeaderComponent, selector: "one-grid-checkbox-header", inputs: ["api", "allowedEdit"] }, { kind: "component", type: OneGridHeaderMenuComponent, selector: "one-grid-header-menu", inputs: ["column", "sortState", "canHide"], outputs: ["menuAction", "menuClose"] }, { kind: "pipe", type: ColumnSortStatePipe, name: "columnSortState" }, { kind: "pipe", type: AriaSortPipe, name: "ariaSort" }] }); }
161
350
  }
162
351
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OneGridHeaderComponent, decorators: [{
163
352
  type: Component,
164
- args: [{ standalone: false, selector: 'one-grid-header', template: "<div class=\"one-grid-header\">\n @if (enableGroupColumnDefs) {\n <div class=\"one-group-header-row\" [style.transform]=\"'translateX(-' + scrollLeft + 'px)'\">\n <ng-container *ngTemplateOutlet=\"groupColumns; context: { groups: groupColumnDefs }\"></ng-container>\n </div>\n }\n <!-- The column row is scrolled rather than translated. `position: sticky`\n resolves against the nearest scrollport, and a transformed ancestor is\n not one \u2014 pinned headers could never hold their place inside it. The\n group row above keeps its transform: groups span contiguous columns,\n which pinning reorders, so the two features do not combine. -->\n <div #headerViewport class=\"one-grid-header-viewport\">\n <div class=\"one-header-row\">\n <ng-container *ngTemplateOutlet=\"headerColumns; context: { columns: columnDefs }\"></ng-container>\n </div>\n </div>\n</div>\n\n<!-- Group Header Cell Template -->\n<ng-template #groupColumns let-groups=\"groups\">\n @for(group of groups; track group.id) {\n <div class=\"one-group-header-cell\"\n [style.width.px]=\"group.width\"\n [ngClass]=\"group._resolvedGroupClass\"\n [ngStyle]=\"group._resolvedGroupStyle\">\n <div class=\"one-group-header-cell-text\">\n {{ group.headerName }}\n </div>\n </div>\n }\n</ng-template>\n\n<!-- Header Cell Template -->\n<ng-template #headerColumns let-columns=\"columns\">\n @for (col of columns; let colIndex = $index; track col.id) {\n <div class=\"one-grid-header-column\"\n [attr.data-index]=\"colIndex\"\n [class.one-column-pinned-left]=\"col.pinned === 'left'\"\n [class.one-column-pinned-right]=\"col.pinned === 'right'\"\n [class.one-column-pinned-edge]=\"col._pinnedEdge\"\n [class.one-column-pinned-edge]=\"col._pinnedEdge\"\n [style.left.px]=\"col.pinned === 'left' ? col._pinnedOffset : null\"\n [style.right.px]=\"col.pinned === 'right' ? col._pinnedOffset : null\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.minWidth\"\n [style.max-width.px]=\"col.maxWidth\"\n [draggable]=\"col._resolvedDragable\"\n (dragstart)=\"onDragColumnStart($event, colIndex)\"\n (dragover)=\"onDragColumnOver($event, colIndex)\"\n (dragend)=\"onDragColumnEnd($event)\"\n (drop)=\"onDropColumn($event)\">\n <div class=\"one-grid-header-cell\"\n [ngClass]=\"col._resolvedHeaderClass\"\n [ngStyle]=\"col._resolvedHeaderStyle\"\n >\n <span class=\"one-grid-header-cell-group\">\n @if (col?.headerCheckboxSelection) {\n <one-grid-checkbox-header\n [api]=\"api\"\n [allowedEdit]=\"allowedEdit\"\n />\n }\n\n {{ col?.headerName ?? '' }}\n </span>\n\n <!-- Og Resize Handler -->\n @if (col._resolvedResizable) {\n <div class=\"og-resize-handle\" (mousedown)=\"onResizeStart($event, colIndex)\">\n <i class=\"bi bi-grip-vertical\"></i>\n </div>\n }\n\n <div class=\"one-grid-header-cell-group\">\n\n <!-- Sort Menu Button -->\n @if (col._resolvedSortable) {\n <div class=\"one-grid-header-menu-button\" (click)=\"onHeaderMenuSortClick(col.field)\">\n\n @if ((col.field | columnSortState:api.sortModel) === 'asc') {\n <lucide-icon name=\"arrow-up-a-z\" [size]=\"16\" [strokeWidth]=\"2\"></lucide-icon>\n }\n @else if ((col.field | columnSortState:api.sortModel) === 'desc') {\n <lucide-icon name=\"arrow-down-z-a\" [size]=\"16\" [strokeWidth]=\"2\"></lucide-icon>\n }\n @else {\n <lucide-icon name=\"arrow-down-up\" [size]=\"16\" [strokeWidth]=\"2\"></lucide-icon>\n }\n </div>\n }\n\n <!-- Og Option Menu Button -->\n @if (col && !col._resolvedSuppressHeaderMenuButton) {\n <div class=\"one-grid-header-menu-button\" (click)=\"onHeaderMenuOptionClick(col)\">\n <i class=\"bi bi-three-dots-vertical\"></i>\n </div>\n }\n </div>\n </div>\n </div>\n }\n</ng-template>\n" }]
165
- }], ctorParameters: () => [{ type: i1.OneGridEventService }, { type: i0.ChangeDetectorRef }], propDecorators: { headerViewport: [{
353
+ args: [{ standalone: true, imports: [
354
+ NgClass,
355
+ NgStyle,
356
+ NgTemplateOutlet,
357
+ LucideAngularModule,
358
+ OneGridCheckboxHeaderComponent,
359
+ OneGridHeaderMenuComponent,
360
+ ColumnSortStatePipe,
361
+ AriaSortPipe,
362
+ ], selector: 'one-grid-header', host: { 'role': 'presentation' }, providers: [ONE_GRID_ICON_PROVIDERS], template: "<div class=\"one-grid-header\" role=\"rowgroup\">\n @if (enableGroupColumnDefs) {\n <div class=\"one-group-header-row\" role=\"presentation\" [style.transform]=\"'translateX(-' + scrollLeft + 'px)'\">\n <ng-container *ngTemplateOutlet=\"groupColumns; context: { groups: groupColumnDefs }\"></ng-container>\n </div>\n }\n <!-- The column row is scrolled rather than translated. `position: sticky`\n resolves against the nearest scrollport, and a transformed ancestor is\n not one \u2014 pinned headers could never hold their place inside it. The\n group row above keeps its transform: groups span contiguous columns,\n which pinning reorders, so the two features do not combine. -->\n <div #headerViewport class=\"one-grid-header-viewport\" role=\"presentation\">\n <div class=\"one-header-row\" role=\"row\" aria-rowindex=\"1\">\n <ng-container *ngTemplateOutlet=\"headerColumns; context: { columns: columnDefs }\"></ng-container>\n </div>\n\n <!-- Filter Row (grid opt-in). Lives inside the header viewport so it\n scrolls with the columns and its pinned cells stick the same way. -->\n @if (filterRow) {\n <div class=\"one-filter-row\" role=\"row\" aria-rowindex=\"2\">\n @for (col of columnDefs; track col.id) {\n <div class=\"one-filter-cell\"\n role=\"gridcell\"\n [attr.aria-colindex]=\"$index + 1\"\n [class.one-column-pinned-left]=\"col.pinned === 'left'\"\n [class.one-column-pinned-right]=\"col.pinned === 'right'\"\n [class.one-column-pinned-edge]=\"col._pinnedEdge\"\n [style.left.px]=\"col.pinned === 'left' ? col._pinnedOffset : null\"\n [style.right.px]=\"col.pinned === 'right' ? col._pinnedOffset : null\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.minWidth\"\n [style.max-width.px]=\"col.maxWidth\">\n @if (col._resolvedFilterable && col.field) {\n <input class=\"one-filter-input\"\n type=\"text\"\n [attr.aria-label]=\"'Filter ' + (col.headerName || col.field)\"\n [value]=\"filterTexts[col.field] ?? ''\"\n (input)=\"onFilterInput(col, $event)\" />\n }\n </div>\n }\n </div>\n }\n </div>\n</div>\n\n<!-- The default column menu (grid opt-in). A sibling of the header block\n because everything inside it clips with overflow: hidden; the host\n positions it just below, right-aligned to the opening column. -->\n@if (headerMenu && openMenuColumn) {\n <one-grid-header-menu\n [style.right.px]=\"menuOffsetRight\"\n [column]=\"openMenuColumn\"\n [sortState]=\"menuSortState(openMenuColumn)\"\n [canHide]=\"columnDefs.length > 1\"\n (menuAction)=\"onHeaderMenuAction($event, openMenuColumn)\"\n (menuClose)=\"closeHeaderMenu()\" />\n}\n\n<!-- Group Header Cell Template -->\n<ng-template #groupColumns let-groups=\"groups\">\n @for(group of groups; track group.id) {\n <div class=\"one-group-header-cell\"\n [style.width.px]=\"group.width\"\n [ngClass]=\"group._resolvedGroupClass\"\n [ngStyle]=\"group._resolvedGroupStyle\">\n <div class=\"one-group-header-cell-text\">\n {{ group.headerName }}\n </div>\n </div>\n }\n</ng-template>\n\n<!-- Header Cell Template -->\n<ng-template #headerColumns let-columns=\"columns\">\n @for (col of columns; let colIndex = $index; track col.id) {\n <div class=\"one-grid-header-column\"\n role=\"columnheader\"\n [attr.aria-colindex]=\"colIndex + 1\"\n [attr.aria-sort]=\"col.field | columnSortState:api.sortModel | ariaSort:col._resolvedSortable\"\n [attr.data-index]=\"colIndex\"\n [class.one-column-pinned-left]=\"col.pinned === 'left'\"\n [class.one-column-pinned-right]=\"col.pinned === 'right'\"\n [class.one-column-pinned-edge]=\"col._pinnedEdge\"\n [class.one-column-pinned-edge]=\"col._pinnedEdge\"\n [style.left.px]=\"col.pinned === 'left' ? col._pinnedOffset : null\"\n [style.right.px]=\"col.pinned === 'right' ? col._pinnedOffset : null\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.minWidth\"\n [style.max-width.px]=\"col.maxWidth\"\n [draggable]=\"col._resolvedDragable\"\n (dragstart)=\"onDragColumnStart($event, colIndex)\"\n (dragover)=\"onDragColumnOver($event, colIndex)\"\n (dragend)=\"onDragColumnEnd($event)\"\n (drop)=\"onDropColumn($event)\">\n <div class=\"one-grid-header-cell\"\n [ngClass]=\"col._resolvedHeaderClass\"\n [ngStyle]=\"col._resolvedHeaderStyle\"\n >\n <span class=\"one-grid-header-cell-group\">\n @if (col?.headerCheckboxSelection) {\n <one-grid-checkbox-header\n [api]=\"api\"\n [allowedEdit]=\"allowedEdit\"\n />\n }\n\n {{ col?.headerName ?? '' }}\n </span>\n\n <!-- Og Resize Handler -->\n @if (col._resolvedResizable) {\n <!-- `separator` is the ARIA window-splitter pattern, which is\n what a column resizer is. Focusable and arrow-operable\n because WCAG 2.5.7 requires everything achievable by\n dragging to have a non-dragging alternative. -->\n <div\n class=\"og-resize-handle\"\n role=\"separator\"\n tabindex=\"0\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"'Resize ' + (col.headerName || col.field)\"\n [attr.aria-valuenow]=\"col.width\"\n [attr.aria-valuemin]=\"col.minWidth || MIN_COLUMN_WIDTH\"\n [attr.aria-valuemax]=\"col.maxWidth || null\"\n (mousedown)=\"onResizeStart($event, colIndex)\"\n (keydown)=\"onResizeKeydown($event, colIndex)\">\n <i class=\"bi bi-grip-vertical\"></i>\n </div>\n }\n\n <div class=\"one-grid-header-cell-group\">\n\n <!-- Sort Menu Button -->\n @if (col._resolvedSortable) {\n <!-- A button, not a div with a click handler: sorting was\n pointer-only. The current state is not repeated here \u2014\n it is on the columnheader's `aria-sort`, and saying it\n twice makes a screen reader read it twice. -->\n <button\n type=\"button\"\n class=\"one-grid-header-menu-button\"\n [attr.aria-label]=\"'Sort by ' + (col.headerName || col.field)\"\n [title]=\"'Sort by ' + (col.headerName || col.field)\"\n (click)=\"onHeaderMenuSortClick(col.field)\">\n\n @if ((col.field | columnSortState:api.sortModel) === 'asc') {\n <lucide-icon name=\"arrow-up-a-z\" [size]=\"16\" [strokeWidth]=\"2\"></lucide-icon>\n }\n @else if ((col.field | columnSortState:api.sortModel) === 'desc') {\n <lucide-icon name=\"arrow-down-z-a\" [size]=\"16\" [strokeWidth]=\"2\"></lucide-icon>\n }\n @else {\n <lucide-icon name=\"arrow-down-up\" [size]=\"16\" [strokeWidth]=\"2\"></lucide-icon>\n }\n </button>\n }\n\n <!-- Og Option Menu Button -->\n @if (col && !col._resolvedSuppressHeaderMenuButton) {\n <button\n type=\"button\"\n class=\"one-grid-header-menu-button\"\n [attr.aria-label]=\"'Options for ' + (col.headerName || col.field)\"\n [attr.aria-haspopup]=\"headerMenu ? 'menu' : null\"\n [attr.aria-expanded]=\"headerMenu ? openMenuColumn?.id === col.id : null\"\n [title]=\"'Options for ' + (col.headerName || col.field)\"\n (click)=\"onHeaderMenuOptionClick(col, $event)\">\n <i class=\"bi bi-three-dots-vertical\"></i>\n </button>\n }\n </div>\n </div>\n </div>\n }\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{display:block;position:relative}one-grid-header-menu{position:absolute;top:100%;z-index:1000}\n"] }]
363
+ }], ctorParameters: () => [{ type: i1.OneGridEventService }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { headerViewport: [{
166
364
  type: ViewChild,
167
365
  args: ['headerViewport', { static: true }]
168
366
  }], scrollLeft: [{
@@ -173,5 +371,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
173
371
  type: Input
174
372
  }], api: [{
175
373
  type: Input
374
+ }], filterRow: [{
375
+ type: Input
376
+ }], headerMenuClick: [{
377
+ type: Output
378
+ }], headerMenu: [{
379
+ type: Input
176
380
  }] } });
177
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib25lLWdyaWQtaGVhZGVyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL29uZS1ncmlkL3NyYy9saWIvY29tcG9uZW50cy9vbmUtZ3JpZC1oZWFkZXIvb25lLWdyaWQtaGVhZGVyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL29uZS1ncmlkL3NyYy9saWIvY29tcG9uZW50cy9vbmUtZ3JpZC1oZWFkZXIvb25lLWdyaWQtaGVhZGVyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBb0MsU0FBUyxFQUFjLEtBQUssRUFBcUIsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRTdILE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFLcEMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0scUNBQXFDLENBQUM7Ozs7Ozs7QUFRekUsTUFBTSxPQUFPLHNCQUFzQjtJQUlqQzs7Ozs7O09BTUc7SUFDSCxJQUNJLFVBQVUsQ0FBQyxLQUFhO1FBRTFCLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxJQUFJLENBQUMsQ0FBQztRQUU5QixJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDekIsQ0FBQztJQUVELElBQUksVUFBVTtRQUVaLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQztJQUMxQixDQUFDO0lBb0JELFlBQ1UsWUFBaUMsRUFDakMsR0FBc0I7UUFEdEIsaUJBQVksR0FBWixZQUFZLENBQXFCO1FBQ2pDLFFBQUcsR0FBSCxHQUFHLENBQW1CO1FBcEJ4QixnQkFBVyxHQUFHLENBQUMsQ0FBQztRQUNmLGdCQUFXLEdBQVksS0FBSyxDQUFDO1FBQzdCLDBCQUFxQixHQUFZLEtBQUssQ0FBQztRQUd0QyxvQkFBZSxHQUF3QixFQUFFLENBQUM7UUFDMUMsZUFBVSxHQUFzQixFQUFFLENBQUM7UUFFckMsY0FB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V0FBVztRQUVULDJFQUEyRTtRQUMzRSx1RUFBdUU7UUFDdkUsNkVBQTZFO1FBQzdFLElBQUksQ0FBQyxhQUFhLENBQUMsV0FBVyxFQUFFLENBQUM7UUFFakMseUVBQXlFO1FBQ3pFLHFFQUFxRTtRQUNyRSxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUVsQixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDckIsQ0FBQztJQUNILENBQUM7K0dBN05VLHNCQUFzQjttR0FBdEIsc0JBQXNCLHFUQ2ZuQyx5eEpBc0dBOzs0RkR2RmEsc0JBQXNCO2tCQU5sQyxTQUFTO2lDQUNJLEtBQUssWUFDUCxpQkFBaUI7d0hBTTRCLGNBQWM7c0JBQXBFLFNBQVM7dUJBQUMsZ0JBQWdCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQVV6QyxVQUFVO3NCQURiLEtBQUs7Z0JBY0csV0FBVztzQkFBbkIsS0FBSztnQkFDRyxxQkFBcUI7c0JBQTdCLEtBQUs7Z0JBQ0csR0FBRztzQkFBWCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgQ2hhbmdlRGV0ZWN0b3JSZWYsIENvbXBvbmVudCwgRWxlbWVudFJlZiwgSW5wdXQsIE9uRGVzdHJveSwgT25Jbml0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9uZUNvbHVtbkRlZiwgT25lR3JvdXBDb2x1bW5EZWYgfSBmcm9tICcuLi8uLi9jb3JlL21vZGVscy9vbmUtY29sdW1uLWRlZi10eXBlcy5tb2RlbCc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IE9uZUdyaWRBcGkgfSBmcm9tICcuLi8uLi9jb3JlL2luc3RhbnRzL29uZS1ncmlkLWFwaS5jbGFzcyc7XG5pbXBvcnQgeyBPbmVTb3J0TW9kZWwgfSBmcm9tICcuLi8uLi9jb3JlL21vZGVscy9vbmUtZ3JpZC10eXBlcy5tb2RlbCc7XG5pbXBvcnQgeyBDb2x1bW5DaGFuZ2VkRXZlbnQgfSBmcm9tICcuLi8uLi9jb3JlL21vZGVscy9vbmUtZXZlbnQtdHlwZXMubW9kZWwnO1xuaW1wb3J0IHsgT25lR3JpZEV2ZW50U2VydmljZSB9IGZyb20gJy4uLy4uL2NvcmUvc2VydmljZXMvb25lLWdyaWQtZXZlbnQuc2VydmljZSc7XG5pbXBvcnQgeyByZXNvbHZlQ29sdW1uV2lkdGggfSBmcm9tICcuLi8uLi9oZWxwZXJzL29uZS1jb2x1bW4tZGVmLmhlbHBlcic7XG5cbkBDb21wb25lbnQoe1xuICBzdGFuZGFsb25lOiBmYWxzZSxcbiAgc2VsZWN0b3I6ICdvbmUtZ3JpZC1oZWFkZXInLFxuICB0ZW1wbGF0ZVVybDogJy4vb25lLWdyaWQtaGVhZGVyLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL29uZS1ncmlkLWhlYWRlci5jb21wb25lbnQuc2Nzcydcbn0pXG5leHBvcnQgY2xhc3MgT25lR3JpZEhlYWRlckNvbXBvbmVudDxUPiBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcblxuICBAVmlld0NoaWxkKCdoZWFkZXJWaWV3cG9ydCcsIHsgc3RhdGljOiB0cnVlIH0pIHByaXZhdGUgaGVhZGVyVmlld3BvcnQ/OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PjtcblxuICAvKipcbiAgICogSG9yaXpvbnRhbCBvZmZzZXQgb2YgdGhlIGJvZHksIG1pcnJvcmVkIGhlcmUgc28gdGhlIGhlYWRlciB0cmFja3MgaXQuXG4gICAqXG4gICAqIEFwcGxpZWQgdG8gdGhlIHZpZXdwb3J0J3MgYHNjcm9sbExlZnRgIHJhdGhlciB0aGFuIGFzIGEgdHJhbnNmb3JtIG9uIHRoZVxuICAgKiByb3c6IHN0aWNreSBwb3NpdGlvbmluZyBuZWVkcyBhIHJlYWwgc2Nyb2xscG9ydCBhYm92ZSBpdC4gVGhlIGdyb3VwIHJvdyxcbiAgICogd2hpY2ggaXMgYSBzaWJsaW5nIG9mIHRoYXQgdmlld3BvcnQsIHN0aWxsIHJlYWRzIHRoaXMgZm9yIGl0cyB0cmFuc2Zvcm0uXG4gICAqL1xuICBASW5wdXQoKVxuICBzZXQgc2Nyb2xsTGVmdCh2YWx1ZTogbnVtYmVyKSB7XG5cbiAgICB0aGlzLl9zY3JvbGxMZWZ0ID0gdmFsdWUgPz8gMDtcblxuICAgIHRoaXMuYXBwbHlTY3JvbGxMZWZ0KCk7XG4gIH1cblxuICBnZXQgc2Nyb2xsTGVmdCgpOiBudW1iZXIge1xuXG4gICAgcmV0dXJuIHRoaXMuX3Njcm9sbExlZnQ7XG4gIH1cblxuICBwcml2YXRlIF9zY3JvbGxMZWZ0ID0gMDtcbiAgQElucHV0KCkgYWxsb3dlZEVkaXQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgZW5hYmxlR3JvdXBDb2x1bW5EZWZzOiBib29sZWFuID0gZmFsc2U7XG4gIEBJbnB1dCgpIGFwaSE6IE9uZUdyaWRBcGk8VD47XG5cbiAgcHJvdGVjdGVkIGdyb3VwQ29sdW1uRGVmczogT25lR3JvdXBDb2x1bW5EZWZbXSA9IFtdO1xuICBwcm90ZWN0ZWQgY29sdW1uRGVmczogT25lQ29sdW1uRGVmPFQ+W10gPSBbXTtcblxuICBwcml2YXRlIHNvcnRNb2RlbDogT25lU29ydE1vZGVsPFQ+W10gPSBbXTtcbiAgcHJpdmF0ZSBzdWJzY3JpcHRpb25zID0gbmV3IFN1YnNjcmlwdGlvbigpO1xuICBwcml2YXRlIGRyYWdnZWRJbmRleDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG5cbiAgLy8gVHJhY2sgcmVzaXplIHN0YXRlXG4gIHByaXZhdGUgcmVzaXppbmcgPSBmYWxzZTtcbiAgcHJpdmF0ZSByZXNpemVDb2x1bW5JbmRleDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgc3RhcnRYID0gMDtcbiAgcHJpdmF0ZSBzdGFydFdpZHRoID0gMDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGV2ZW50U2VydmljZTogT25lR3JpZEV2ZW50U2VydmljZSxcbiAgICBwcml2YXRlIGNkcjogQ2hhbmdlRGV0ZWN0b3JSZWZcbiAgICkge31cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcblxuICAgIC8vIExpc3RlbiBDb2x1bW4gQ2hhbmdlZCBFdmVudFxuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5hZGQodGhpcy5ldmVudFNlcnZpY2UuYWRkRXZlbnRMaXN0ZW5lcignY29sdW1uQ2hhbmdlZCcsIChwYXlsb2FkOiBDb2x1bW5DaGFuZ2VkRXZlbnQpID0+IHtcblxuICAgICAgY29uc3QgeyBncm91cHMsIGNvbHVtbnMgfSA9IHBheWxvYWQ7XG5cbiAgICAgIGlmIChncm91cHMpIHtcblxuICAgICAgICB0aGlzLmdyb3VwQ29sdW1uRGVmcyA9IGdyb3VwcyBhcyBPbmVHcm91cENvbHVtbkRlZltdO1xuICAgICAgfVxuXG4gICAgICBpZiAoY29sdW1ucykge1xuXG4gICAgICAgIHRoaXMuY29sdW1uRGVmcyA9IGNvbHVtbnMgYXMgT25lQ29sdW1uRGVmW107XG4gICAgICB9XG5cbiAgICAgIC8vIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgIH0pKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcblxuICAgIC8vIFRoZSBpbnB1dCBzZXR0ZXIgY2FuIHJ1biBiZWZvcmUgdGhlIHZpZXcgZXhpc3RzLCBzbyB3aGF0ZXZlciBhcnJpdmVkXG4gICAgLy8gZmlyc3QgaXMgYXBwbGllZCBvbmNlIGhlcmUuXG4gICAgdGhpcy5hcHBseVNjcm9sbExlZnQoKTtcbiAgfVxuXG4gIHByaXZhdGUgYXBwbHlTY3JvbGxMZWZ0KCk6IHZvaWQge1xuXG4gICAgaWYgKHRoaXMuaGVhZGVyVmlld3BvcnQpIHtcblxuICAgICAgdGhpcy5oZWFkZXJWaWV3cG9ydC5uYXRpdmVFbGVtZW50LnNjcm9sbExlZnQgPSB0aGlzLl9zY3JvbGxMZWZ0O1xuICAgIH1cbiAgfVxuXG4gIG9uSGVhZGVyTWVudU9wdGlvbkNsaWNrKGNvbHVtbkRlZjogT25lQ29sdW1uRGVmPFQ+KSB7XG5cbiAgfVxuXG4gIG9uSGVhZGVyTWVudVNvcnRDbGljayhjb2xJZDoga2V5b2YgVCkge1xuXG4gICAgY29uc3QgY3VycmVudFNvcnQgPSB0aGlzLnNvcnRNb2RlbC5maW5kKHNvcnQgPT4gc29ydC5jb2xJZCA9PT0gY29sSWQpPy5zb3J0ID8/IG51bGw7XG5cbiAgICBjb25zdCBuZXh0U29ydCA9IHRoaXMuY3ljbGVTb3J0KGN1cnJlbnRTb3J0KTtcblxuICAgIHRoaXMuc29ydE1vZGVsID0gbmV4dFNvcnQgPyBbeyBjb2xJZCwgc29ydDogbmV4dFNvcnQgfV0gOiBbXTtcblxuICAgIHRoaXMuYXBpLm9uU29ydENoYW5nZWQodGhpcy5zb3J0TW9kZWwpO1xuICB9XG5cbiAgLy8gQ3ljbGUgU29ydGluZyBNb2RlbFxuICBwcml2YXRlIGN5Y2xlU29ydChjdXJyZW50OiAnYXNjJyB8ICdkZXNjJyB8IG51bGwpOiAnYXNjJyB8ICdkZXNjJyB8IG51bGwge1xuXG4gICAgc3dpdGNoIChjdXJyZW50KSB7XG5cbiAgICAgIGNhc2UgbnVsbDogcmV0dXJuICdhc2MnO1xuXG4gICAgICBjYXNlICdhc2MnOiByZXR1cm4gJ2Rlc2MnO1xuXG4gICAgICBjYXNlICdkZXNjJzogcmV0dXJuIG51bGw7XG5cbiAgICAgIGRlZmF1bHQ6IHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIG9uUmVzaXplU3RhcnQoZXZlbnQ6IE1vdXNlRXZlbnQsIGNvbHVtbkluZGV4OiBudW1iZXIpOiB2b2lkIHtcblxuICAgIC8vIFByZXZlbnQgdGV4dCBzZWxlY3Rpb24gYW5kIGRlZmF1bHQgYmVoYXZpb3JcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgLy8gU3RvcmUgaW5pdGlhbCB2YWx1ZXNcbiAgICB0aGlzLnJlc2l6aW5nID0gdHJ1ZTtcbiAgICB0aGlzLnJlc2l6ZUNvbHVtbkluZGV4ID0gY29sdW1uSW5kZXg7XG4gICAgdGhpcy5zdGFydFggPSBldmVudC5jbGllbnRYO1xuXG4gICAgLy8gTWVhc3VyZSB3aGF0IGlzIG9uIHNjcmVlbiByYXRoZXIgdGhhbiB0cnVzdGluZyBgY29sLndpZHRoYCwgd2hpY2ggaXNcbiAgICAvLyBvcHRpb25hbDogYSBjb2x1bW4gc2l6ZWQgcHVyZWx5IGJ5IG1pbldpZHRoIGhhZCBgdW5kZWZpbmVkYCBoZXJlLCBhbmRcbiAgICAvLyBgTWF0aC5tYXgoNTAsIHVuZGVmaW5lZCArIGRlbHRhWClgIGlzIE5hTiDigJQgdGhlIGNvbHVtbiBjb2xsYXBzZWQgb24gdGhlXG4gICAgLy8gZmlyc3QgbW91c2UgbW92ZSBhbmQgY291bGQgbm90IGJlIHJlY292ZXJlZC5cbiAgICBjb25zdCBjb2x1bW5FbGVtZW50ID0gKGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudCk/LmNsb3Nlc3Q8SFRNTEVsZW1lbnQ+KCcub25lLWdyaWQtaGVhZGVyLWNvbHVtbicpO1xuXG4gICAgdGhpcy5zdGFydFdpZHRoID0gY29sdW1uRWxlbWVudD8ub2Zmc2V0V2lkdGggfHwgcmVzb2x2ZUNvbHVtbldpZHRoKHRoaXMuY29sdW1uRGVmc1tjb2x1bW5JbmRleF0pO1xuXG4gICAgLy8gQWRkIGRvY3VtZW50LWxldmVsIGxpc3RlbmVycyBmb3IgZHJhZyBhbmQgcmVsZWFzZVxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMub25SZXNpemVNb3ZlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5vblJlc2l6ZUVuZCk7XG5cbiAgICAvLyBBZGQgYSBjbGFzcyB0byBib2R5IHRvIG1haW50YWluIGN1cnNvciBkdXJpbmcgZHJhZ1xuICAgIGRvY3VtZW50LmJvZHkuc3R5bGUuY3Vyc29yID0gJ2NvbC1yZXNpemUnO1xuICB9XG5cbiAgLy8gQXJyb3cgZnVuY3Rpb24gdG8gcHJlc2VydmUgJ3RoaXMnIGNvbnRleHRcbiAgcHJpdmF0ZSBvblJlc2l6ZU1vdmUgPSAoZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkID0+IHtcblxuICAgIGlmICghdGhpcy5yZXNpemluZyB8fCB0aGlzLnJlc2l6ZUNvbHVtbkluZGV4ID09PSBudWxsKSByZXR1cm47XG5cbiAgICAvLyBDYWxjdWxhdGUgaG93IGZhciB0aGUgbW91c2UgaGFzIG1vdmVkXG4gICAgY29uc3QgZGVsdGFYID0gZXZlbnQuY2xpZW50WCAtIHRoaXMuc3RhcnRYO1xuXG4gICAgLy8gQ2FsY3VsYXRlIG5ldyB3aWR0aCAod2l0aCBtaW5pbXVtIG9mIDUwcHgpXG4gICAgY29uc3QgbmV3V2lkdGggPSBNYXRoLm1heCg1MCwgdGhpcy5zdGFydFdpZHRoICsgZGVsdGFYKTtcblxuICAgIC8vIFVwZGF0ZSB0aGUgY29sdW1uIHdpZHRoXG4gICAgdGhpcy5hcGkudXBkYXRlQ29sdW1uKHRoaXMuY29sdW1uRGVmc1t0aGlzLnJlc2l6ZUNvbHVtbkluZGV4XS5pZCwgeyB3aWR0aDogbmV3V2lkdGggfSk7XG4gIH1cblxuICBwcml2YXRlIG9uUmVzaXplRW5kID0gKCk6IHZvaWQgPT4ge1xuXG4gICAgLy8gQ2xlYW4gdXBcbiAgICB0aGlzLnJlc2l6aW5nID0gZmFsc2U7XG4gICAgdGhpcy5yZXNpemVDb2x1bW5JbmRleCA9IG51bGw7XG4gICAgZG9jdW1lbnQuYm9keS5zdHlsZS5jdXJzb3IgPSAnJztcblxuICAgIC8vIFJlbW92ZSBkb2N1bWVudCBsaXN0ZW5lcnNcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLm9uUmVzaXplTW92ZSk7XG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMub25SZXNpemVFbmQpO1xuICB9XG5cbiAgLy8gVHJhY2sgdGhlIGRyYWdnZWQgY29sdW1uIGluZGV4XG4gIG9uRHJhZ0NvbHVtblN0YXJ0KGV2ZW50OiBEcmFnRXZlbnQsIGluZGV4OiBudW1iZXIpOiB2b2lkIHtcblxuICAgIHRoaXMuZHJhZ2dlZEluZGV4ID0gaW5kZXg7XG5cbiAgICAvLyBPcHRpb25hbDogU2V0IGRyYWcgaW1hZ2UvZWZmZWN0XG4gICAgaWYgKGV2ZW50LmRhdGFUcmFuc2Zlcikge1xuXG4gICAgICBldmVudC5kYXRhVHJhbnNmZXIuZWZmZWN0QWxsb3dlZCA9ICdtb3ZlJztcbiAgICB9XG4gIH1cblxuICBvbkRyYWdDb2x1bW5PdmVyKGV2ZW50OiBEcmFnRXZlbnQsIHRhcmdldEluZGV4OiBudW1iZXIpOiB2b2lkIHtcblxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAvLyBTa2lwIGlmIGRyYWdnaW5nIG92ZXIgaXRzZWxmIG9yIG5vIGRyYWcgaW4gcHJvZ3Jlc3NcbiAgICBpZiAodGhpcy5kcmFnZ2VkSW5kZXggPT09IG51bGwgfHwgdGhpcy5kcmFnZ2VkSW5kZXggPT09IHRhcmdldEluZGV4KSB7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBJTU1FRElBVEVMWSByZW9yZGVyIGNvbHVtbnNcbiAgICB0aGlzLmFwaS5yZW9yZGVyQ29sdW1uRGVmcyh0aGlzLmRyYWdnZWRJbmRleCwgdGFyZ2V0SW5kZXgpO1xuXG4gICAgLy8gVXBkYXRlIGRyYWdnZWRJbmRleCB0byB0aGUgbmV3IHBvc2l0aW9uXG4gICAgdGhpcy5kcmFnZ2VkSW5kZXggPSB0YXJnZXRJbmRleDtcbiAgfVxuXG4gIG9uRHJhZ0NvbHVtbkVuZChldmVudDogRHJhZ0V2ZW50KTogdm9pZCB7XG5cbiAgICB0aGlzLmRyYWdnZWRJbmRleCA9IG51bGw7XG4gIH1cblxuICBvbkRyb3BDb2x1bW4oZXZlbnQ6IERyYWdFdmVudCk6IHZvaWQge1xuXG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgIHRoaXMuZHJhZ2dlZEluZGV4ID0gbnVsbDtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuXG4gICAgLy8gVGhpcyBjb21wbGV0ZWQgYW4gdW51c2VkIFN1YmplY3QgYW5kIGxlZnQgdGhlIHJlYWwgc3Vic2NyaXB0aW9uIHJ1bm5pbmcuXG4gICAgLy8gSXQgc3Vydml2ZWQgb25seSBiZWNhdXNlIE9uZUdyaWRFdmVudFNlcnZpY2UgaXMgY29tcG9uZW50LXNjb3BlZCBhbmRcbiAgICAvLyB0ZWFycyBpdHMgb3duIGxpc3RlbmVycyBkb3duIOKAlCB0aGUgaGVhZGVyIHdhcyByZWx5aW5nIG9uIHRoYXQgYnkgYWNjaWRlbnQuXG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnVuc3Vic2NyaWJlKCk7XG5cbiAgICAvLyBBIHJlc2l6ZSBpbiBmbGlnaHQgb3ducyB0d28gbGlzdGVuZXJzIG9uIGBkb2N1bWVudGAuIFdpdGhvdXQgdGhpcyB0aGV5XG4gICAgLy8gb3V0bGl2ZSB0aGUgY29tcG9uZW50LCBhbmQgdGhlaXIgY2xvc3VyZXMga2VlcCBpdCBhbGl2ZSB3aXRoIHRoZW0uXG4gICAgaWYgKHRoaXMucmVzaXppbmcpIHtcblxuICAgICAgdGhpcy5vblJlc2l6ZUVuZCgpO1xuICAgIH1cbiAgfVxufVxuIiwiPGRpdiBjbGFzcz1cIm9uZS1ncmlkLWhlYWRlclwiPlxuICAgIEBpZiAoZW5hYmxlR3JvdXBDb2x1bW5EZWZzKSB7XG4gICAgICAgIDxkaXYgY2xhc3M9XCJvbmUtZ3JvdXAtaGVhZGVyLXJvd1wiIFtzdHlsZS50cmFuc2Zvcm1dPVwiJ3RyYW5zbGF0ZVgoLScgKyBzY3JvbGxMZWZ0ICsgJ3B4KSdcIj5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJncm91cENvbHVtbnM7IGNvbnRleHQ6IHsgZ3JvdXBzOiBncm91cENvbHVtbkRlZnMgfVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICA8L2Rpdj5cbiAgICB9XG4gICAgPCEtLSBUaGUgY29sdW1uIHJvdyBpcyBzY3JvbGxlZCByYXRoZXIgdGhhbiB0cmFuc2xhdGVkLiBgcG9zaXRpb246IHN0aWNreWBcbiAgICAgICAgIHJlc29sdmVzIGFnYWluc3QgdGhlIG5lYXJlc3Qgc2Nyb2xscG9ydCwgYW5kIGEgdHJhbnNmb3JtZWQgYW5jZXN0b3IgaXNcbiAgICAgICAgIG5vdCBvbmUg4oCUIHBpbm5lZCBoZWFkZXJzIGNvdWxkIG5ldmVyIGhvbGQgdGhlaXIgcGxhY2UgaW5zaWRlIGl0LiBUaGVcbiAgICAgICAgIGdyb3VwIHJvdyBhYm92ZSBrZWVwcyBpdHMgdHJhbnNmb3JtOiBncm91cHMgc3BhbiBjb250aWd1b3VzIGNvbHVtbnMsXG4gICAgICAgICB3aGljaCBwaW5uaW5nIHJlb3JkZXJzLCBzbyB0aGUgdHdvIGZlYXR1cmVzIGRvIG5vdCBjb21iaW5lLiAtLT5cbiAgICA8ZGl2ICNoZWFkZXJWaWV3cG9ydCBjbGFzcz1cIm9uZS1ncmlkLWhlYWRlci12aWV3cG9ydFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwib25lLWhlYWRlci1yb3dcIj5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJoZWFkZXJDb2x1bW5zOyBjb250ZXh0OiB7IGNvbHVtbnM6IGNvbHVtbkRlZnMgfVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbjwvZGl2PlxuXG48IS0tIEdyb3VwIEhlYWRlciBDZWxsIFRlbXBsYXRlIC0tPlxuPG5nLXRlbXBsYXRlICNncm91cENvbHVtbnMgbGV0LWdyb3Vwcz1cImdyb3Vwc1wiPlxuICAgIEBmb3IoZ3JvdXAgb2YgZ3JvdXBzOyB0cmFjayBncm91cC5pZCkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwib25lLWdyb3VwLWhlYWRlci1jZWxsXCJcbiAgICAgICAgICAgIFtzdHlsZS53aWR0aC5weF09XCJncm91cC53aWR0aFwiXG4gICAgICAgICAgICBbbmdDbGFzc109XCJncm91cC5fcmVzb2x2ZWRHcm91cENsYXNzXCJcbiAgICAgICAgICAgIFtuZ1N0eWxlXT1cImdyb3VwLl9yZXNvbHZlZEdyb3VwU3R5bGVcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJvbmUtZ3JvdXAtaGVhZGVyLWNlbGwtdGV4dFwiPlxuICAgICAgICAgICAgICAgIHt7IGdyb3VwLmhlYWRlck5hbWUgfX1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICB9XG48L25nLXRlbXBsYXRlPlxuXG48IS0tIEhlYWRlciBDZWxsIFRlbXBsYXRlIC0tPlxuPG5nLXRlbXBsYXRlICNoZWFkZXJDb2x1bW5zIGxldC1jb2x1bW5zPVwiY29sdW1uc1wiPlxuICAgIEBmb3IgKGNvbCBvZiBjb2x1bW5zOyBsZXQgY29sSW5kZXggPSAkaW5kZXg7IHRyYWNrIGNvbC5pZCkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwib25lLWdyaWQtaGVhZGVyLWNvbHVtblwiXG4gICAgICAgICAgICBbYXR0ci5kYXRhLWluZGV4XT1cImNvbEluZGV4XCJcbiAgICAgICAgICAgIFtjbGFzcy5vbmUtY29sdW1uLXBpbm5lZC1sZWZ0XT1cImNvbC5waW5uZWQgPT09ICdsZWZ0J1wiXG4gICAgICAgICAgICBbY2xhc3Mub25lLWNvbHVtbi1waW5uZWQtcmlnaHRdPVwiY29sLnBpbm5lZCA9PT0gJ3JpZ2h0J1wiXG4gICAgICAgIFtjbGFzcy5vbmUtY29sdW1uLXBpbm5lZC1lZGdlXT1cImNvbC5fcGlubmVkRWRnZVwiXG4gICAgICAgICAgICBbY2xhc3Mub25lLWNvbHVtbi1waW5uZWQtZWRnZV09XCJjb2wuX3Bpbm5lZEVkZ2VcIlxuICAgICAgICAgICAgW3N0eWxlLmxlZnQucHhdPVwiY29sLnBpbm5lZCA9PT0gJ2xlZnQnID8gY29sLl9waW5uZWRPZmZzZXQgOiBudWxsXCJcbiAgICAgICAgICAgIFtzdHlsZS5yaWdodC5weF09XCJjb2wucGlubmVkID09PSAncmlnaHQnID8gY29sLl9waW5uZWRPZmZzZXQgOiBudWxsXCJcbiAgICAgICAgICAgIFtzdHlsZS53aWR0aC5weF09XCJjb2wud2lkdGhcIlxuICAgICAgICAgICAgW3N0eWxlLm1pbi13aWR0aC5weF09XCJjb2wubWluV2lkdGhcIlxuICAgICAgICAgICAgW3N0eWxlLm1heC13aWR0aC5weF09XCJjb2wubWF4V2lkdGhcIlxuICAgICAgICAgICAgW2RyYWdnYWJsZV09XCJjb2wuX3Jlc29sdmVkRHJhZ2FibGVcIlxuICAgICAgICAgICAgKGRyYWdzdGFydCk9XCJvbkRyYWdDb2x1bW5TdGFydCgkZXZlbnQsIGNvbEluZGV4KVwiXG4gICAgICAgICAgICAoZHJhZ292ZXIpPVwib25EcmFnQ29sdW1uT3ZlcigkZXZlbnQsIGNvbEluZGV4KVwiXG4gICAgICAgICAgICAoZHJhZ2VuZCk9XCJvbkRyYWdDb2x1bW5FbmQoJGV2ZW50KVwiXG4gICAgICAgICAgICAoZHJvcCk9XCJvbkRyb3BDb2x1bW4oJGV2ZW50KVwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm9uZS1ncmlkLWhlYWRlci1jZWxsXCJcbiAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJjb2wuX3Jlc29sdmVkSGVhZGVyQ2xhc3NcIlxuICAgICAgICAgICAgICAgIFtuZ1N0eWxlXT1cImNvbC5fcmVzb2x2ZWRIZWFkZXJTdHlsZVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwib25lLWdyaWQtaGVhZGVyLWNlbGwtZ3JvdXBcIj5cbiAgICAgICAgICAgICAgICAgICAgQGlmIChjb2w/LmhlYWRlckNoZWNrYm94U2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8b25lLWdyaWQtY2hlY2tib3gtaGVhZGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2FwaV09XCJhcGlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthbGxvd2VkRWRpdF09XCJhbGxvd2VkRWRpdFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAge3sgY29sPy5oZWFkZXJOYW1lID8/ICcnIH19XG4gICAgICAgICAgICAgICAgPC9zcGFuPlxuXG4gICAgICAgICAgICAgICAgPCEtLSBPZyBSZXNpemUgSGFuZGxlciAtLT5cbiAgICAgICAgICAgICAgICBAaWYgKGNvbC5fcmVzb2x2ZWRSZXNpemFibGUpIHtcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm9nLXJlc2l6ZS1oYW5kbGVcIiAobW91c2Vkb3duKT1cIm9uUmVzaXplU3RhcnQoJGV2ZW50LCBjb2xJbmRleClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiYmkgYmktZ3JpcC12ZXJ0aWNhbFwiPjwvaT5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm9uZS1ncmlkLWhlYWRlci1jZWxsLWdyb3VwXCI+XG5cbiAgICAgICAgICAgICAgICAgICAgPCEtLSBTb3J0IE1lbnUgQnV0dG9uIC0tPlxuICAgICAgICAgICAgICAgICAgICBAaWYgKGNvbC5fcmVzb2x2ZWRTb3J0YWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm9uZS1ncmlkLWhlYWRlci1tZW51LWJ1dHRvblwiIChjbGljayk9XCJvbkhlYWRlck1lbnVTb3J0Q2xpY2soY29sLmZpZWxkKVwiPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQGlmICgoY29sLmZpZWxkIHwgY29sdW1uU29ydFN0YXRlOmFwaS5zb3J0TW9kZWwpID09PSAnYXNjJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bHVjaWRlLWljb24gbmFtZT1cImFycm93LXVwLWEtelwiIFtzaXplXT1cIjE2XCIgW3N0cm9rZVdpZHRoXT1cIjJcIj48L2x1Y2lkZS1pY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBAZWxzZSBpZiAoKGNvbC5maWVsZCB8IGNvbHVtblNvcnRTdGF0ZTphcGkuc29ydE1vZGVsKSA9PT0gJ2Rlc2MnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsdWNpZGUtaWNvbiBuYW1lPVwiYXJyb3ctZG93bi16LWFcIiBbc2l6ZV09XCIxNlwiIFtzdHJva2VXaWR0aF09XCIyXCI+PC9sdWNpZGUtaWNvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bHVjaWRlLWljb24gbmFtZT1cImFycm93LWRvd24tdXBcIiBbc2l6ZV09XCIxNlwiIFtzdHJva2VXaWR0aF09XCIyXCI+PC9sdWNpZGUtaWNvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIDwhLS0gT2cgT3B0aW9uIE1lbnUgQnV0dG9uIC0tPlxuICAgICAgICAgICAgICAgICAgICBAaWYgKGNvbCAmJiAhY29sLl9yZXNvbHZlZFN1cHByZXNzSGVhZGVyTWVudUJ1dHRvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm9uZS1ncmlkLWhlYWRlci1tZW51LWJ1dHRvblwiIChjbGljayk9XCJvbkhlYWRlck1lbnVPcHRpb25DbGljayhjb2wpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJiaSBiaS10aHJlZS1kb3RzLXZlcnRpY2FsXCI+PC9pPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICB9XG48L25nLXRlbXBsYXRlPlxuIl19
381
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib25lLWdyaWQtaGVhZGVyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL29uZS1ncmlkL3NyYy9saWIvY29tcG9uZW50cy9vbmUtZ3JpZC1oZWFkZXIvb25lLWdyaWQtaGVhZGVyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL29uZS1ncmlkL3NyYy9saWIvY29tcG9uZW50cy9vbmUtZ3JpZC1oZWFkZXIvb25lLWdyaWQtaGVhZGVyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBb0MsU0FBUyxFQUFjLFlBQVksRUFBRSxLQUFLLEVBQXFCLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFbkosT0FBTyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDN0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBTTlDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDckUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDckQsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUUsT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0sZ0VBQWdFLENBQUM7QUFDaEgsT0FBTyxFQUFFLDBCQUEwQixFQUF1QixNQUFNLHdEQUF3RCxDQUFDO0FBQ3pILE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBQzlFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQzs7OztBQXNCL0QsTUFBTSxPQUFPLHNCQUFzQjtJQUlqQzs7Ozs7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LGtMRDNKSSxPQUFPLG9GQUNQLE9BQU8sMkVBQ1AsZ0JBQWdCLG1KQUNoQixtQkFBbUIsZ1BBQ25CLDhCQUE4QixxR0FDOUIsMEJBQTBCLDhJQUMxQixtQkFBbUIsbURBQ25CLFlBQVk7OzRGQVVILHNCQUFzQjtrQkFwQmxDLFNBQVM7aUNBQ0ksSUFBSSxXQUNQO3dCQUNQLE9BQU87d0JBQ1AsT0FBTzt3QkFDUCxnQkFBZ0I7d0JBQ2hCLG1CQUFtQjt3QkFDbkIsOEJBQThCO3dCQUM5QiwwQkFBMEI7d0JBQzFCLG1CQUFtQjt3QkFDbkIsWUFBWTtxQkFDYixZQUNTLGlCQUFpQixRQUdyQixFQUFFLE1BQU0sRUFBRSxjQUFjLEVBQUUsYUFDckIsQ0FBQyx1QkFBdUIsQ0FBQztpSkFNbUIsY0FBYztzQkFBcEUsU0FBUzt1QkFBQyxnQkFBZ0IsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBVXpDLFVBQVU7c0JBRGIsS0FBSztnQkFjRyxXQUFXO3NCQUFuQixLQUFLO2dCQUNHLHFCQUFxQjtzQkFBN0IsS0FBSztnQkFDRyxHQUFHO3NCQUFYLEtBQUs7Z0JBK0JHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBK0ZJLGVBQWU7c0JBQXhCLE1BQU07Z0JBUUUsVUFBVTtzQkFBbEIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyVmlld0luaXQsIENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uRGVzdHJveSwgT25Jbml0LCBPdXRwdXQsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgT25lQ29sdW1uRGVmLCBPbmVHcm91cENvbHVtbkRlZiB9IGZyb20gJy4uLy4uL2NvcmUvbW9kZWxzL29uZS1jb2x1bW4tZGVmLXR5cGVzLm1vZGVsJztcbmltcG9ydCB7IFN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgT25lR3JpZEFwaSB9IGZyb20gJy4uLy4uL2NvcmUvaW5zdGFudHMvb25lLWdyaWQtYXBpLmNsYXNzJztcbmltcG9ydCB7IE9uZVNvcnRNb2RlbCB9IGZyb20gJy4uLy4uL2NvcmUvbW9kZWxzL29uZS1ncmlkLXR5cGVzLm1vZGVsJztcbmltcG9ydCB7IENvbHVtbkNoYW5nZWRFdmVudCB9IGZyb20gJy4uLy4uL2NvcmUvbW9kZWxzL29uZS1ldmVudC10eXBlcy5tb2RlbCc7XG5pbXBvcnQgeyBPbmVGaWx0ZXJNb2RlbCB9IGZyb20gJy4uLy4uL2NvcmUvbW9kZWxzL29uZS1maWx0ZXIubW9kZWwnO1xuaW1wb3J0IHsgT25lR3JpZEV2ZW50U2VydmljZSB9IGZyb20gJy4uLy4uL2NvcmUvc2VydmljZXMvb25lLWdyaWQtZXZlbnQuc2VydmljZSc7XG5pbXBvcnQgeyByZXNvbHZlQ29sdW1uV2lkdGggfSBmcm9tICcuLi8uLi9oZWxwZXJzL29uZS1jb2x1bW4tZGVmLmhlbHBlcic7XG5pbXBvcnQgeyBOZ0NsYXNzLCBOZ1N0eWxlLCBOZ1RlbXBsYXRlT3V0bGV0IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IEx1Y2lkZUFuZ3VsYXJNb2R1bGUgfSBmcm9tICdsdWNpZGUtYW5ndWxhcic7XG5pbXBvcnQgeyBPTkVfR1JJRF9JQ09OX1BST1ZJREVSUyB9IGZyb20gJy4uLy4uL2NvcmUvaWNvbnMvb25lLWdyaWQtaWNvbnMnO1xuaW1wb3J0IHsgT25lR3JpZENoZWNrYm94SGVhZGVyQ29tcG9uZW50IH0gZnJvbSAnLi4vb25lLWdyaWQtY2hlY2tib3gtaGVhZGVyL29uZS1ncmlkLWNoZWNrYm94LWhlYWRlci5jb21wb25lbnQnO1xuaW1wb3J0IHsgT25lR3JpZEhlYWRlck1lbnVDb21wb25lbnQsIE9uZUhlYWRlck1lbnVBY3Rpb24gfSBmcm9tICcuLi9vbmUtZ3JpZC1oZWFkZXItbWVudS9vbmUtZ3JpZC1oZWFkZXItbWVudS5jb21wb25lbnQnO1xuaW1wb3J0IHsgQ29sdW1uU29ydFN0YXRlUGlwZSB9IGZyb20gJy4uLy4uL2NvcmUvcGlwZXMvY29sdW1uLXNvcnQtc3RhdGUucGlwZSc7XG5pbXBvcnQgeyBBcmlhU29ydFBpcGUgfSBmcm9tICcuLi8uLi9jb3JlL3BpcGVzL2FyaWEtc29ydC5waXBlJztcblxuQENvbXBvbmVudCh7XG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBOZ0NsYXNzLFxuICAgIE5nU3R5bGUsXG4gICAgTmdUZW1wbGF0ZU91dGxldCxcbiAgICBMdWNpZGVBbmd1bGFyTW9kdWxlLFxuICAgIE9uZUdyaWRDaGVja2JveEhlYWRlckNvbXBvbmVudCxcbiAgICBPbmVHcmlkSGVhZGVyTWVudUNvbXBvbmVudCxcbiAgICBDb2x1bW5Tb3J0U3RhdGVQaXBlLFxuICAgIEFyaWFTb3J0UGlwZSxcbiAgXSxcbiAgc2VsZWN0b3I6ICdvbmUtZ3JpZC1oZWFkZXInLFxuICAvLyBUaGUgaG9zdCBzaXRzIGJldHdlZW4gcm9sZT1cImdyaWRcIiBhbmQgdGhlIHJvd3MgaXQgbXVzdCBvd247IGEgZ2VuZXJpY1xuICAvLyBlbGVtZW50IHRoZXJlIGJyZWFrcyB0aGUgb3duZXJzaGlwIGNoYWluLCBzbyBpdCBsZWF2ZXMgdGhlIGExMXkgdHJlZS5cbiAgaG9zdDogeyAncm9sZSc6ICdwcmVzZW50YXRpb24nIH0sXG4gIHByb3ZpZGVyczogW09ORV9HUklEX0lDT05fUFJPVklERVJTXSxcbiAgdGVtcGxhdGVVcmw6ICcuL29uZS1ncmlkLWhlYWRlci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsOiAnLi9vbmUtZ3JpZC1oZWFkZXIuY29tcG9uZW50LnNjc3MnXG59KVxuZXhwb3J0IGNsYXNzIE9uZUdyaWRIZWFkZXJDb21wb25lbnQ8VD4gaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG5cbiAgQFZpZXdDaGlsZCgnaGVhZGVyVmlld3BvcnQnLCB7IHN0YXRpYzogdHJ1ZSB9KSBwcml2YXRlIGhlYWRlclZpZXdwb3J0PzogRWxlbWVudFJlZjxIVE1MRWxlbWVudD47XG5cbiAgLyoqXG4gICAqIEhvcml6b250YWwgb2Zmc2V0IG9mIHRoZSBib2R5LCBtaXJyb3JlZCBoZXJlIHNvIHRoZSBoZWFkZXIgdHJhY2tzIGl0LlxuICAgKlxuICAgKiBBcHBsaWVkIHRvIHRoZSB2aWV3cG9ydCdzIGBzY3JvbGxMZWZ0YCByYXRoZXIgdGhhbiBhcyBhIHRyYW5zZm9ybSBvbiB0aGVcbiAgICogcm93OiBzdGlja3kgcG9zaXRpb25pbmcgbmVlZHMgYSByZWFsIHNjcm9sbHBvcnQgYWJvdmUgaXQuIFRoZSBncm91cCByb3csXG4gICAqIHdoaWNoIGlzIGEgc2libGluZyBvZiB0aGF0IHZpZXdwb3J0LCBzdGlsbCByZWFkcyB0aGlzIGZvciBpdHMgdHJhbnNmb3JtLlxuICAgKi9cbiAgQElucHV0KClcbiAgc2V0IHNjcm9sbExlZnQodmFsdWU6IG51bWJlcikge1xuXG4gICAgdGhpcy5fc2Nyb2xsTGVmdCA9IHZhbHVlID8/IDA7XG5cbiAgICB0aGlzLmFwcGx5U2Nyb2xsTGVmdCgpO1xuICB9XG5cbiAgZ2V0IHNjcm9sbExlZnQoKTogbnVtYmVyIHtcblxuICAgIHJldHVybiB0aGlzLl9zY3JvbGxMZWZ0O1xuICB9XG5cbiAgcHJpdmF0ZSBfc2Nyb2xsTGVmdCA9IDA7XG4gIEBJbnB1dCgpIGFsbG93ZWRFZGl0OiBib29sZWFuID0gZmFsc2U7XG4gIEBJbnB1dCgpIGVuYWJsZUdyb3VwQ29sdW1uRGVmczogYm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKSBhcGkhOiBPbmVHcmlkQXBpPFQ+O1xuXG4gIHByb3RlY3RlZCBncm91cENvbHVtbkRlZnM6IE9uZUdyb3VwQ29sdW1uRGVmW10gPSBbXTtcbiAgcHJvdGVjdGVkIGNvbHVtbkRlZnM6IE9uZUNvbHVtbkRlZjxUPltdID0gW107XG5cbiAgcHJpdmF0ZSBzb3J0TW9kZWw6IE9uZVNvcnRNb2RlbDxUPltdID0gW107XG4gIHByaXZhdGUgc3Vic2NyaXB0aW9ucyA9IG5ldyBTdWJzY3JpcHRpb24oKTtcbiAgcHJpdmF0ZSBkcmFnZ2VkSW5kZXg6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICAvKiogV2hlcmUgdGhlIGRyYWcgc3RhcnRlZCwgZm9yIHJlcG9ydGluZyB0aGUgY29tcGxldGVkIG1vdmUgYXMgb25lIGV2ZW50LiAqL1xuICBwcml2YXRlIGRyYWdTb3VyY2VJbmRleDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG5cbiAgLy8gVHJhY2sgcmVzaXplIHN0YXRlXG4gIHByaXZhdGUgcmVzaXppbmcgPSBmYWxzZTtcbiAgcHJpdmF0ZSByZXNpemVDb2x1bW5JbmRleDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgc3RhcnRYID0gMDtcbiAgcHJpdmF0ZSBzdGFydFdpZHRoID0gMDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGV2ZW50U2VydmljZTogT25lR3JpZEV2ZW50U2VydmljZSxcbiAgICBwcml2YXRlIGNkcjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgcHJpdmF0ZSBlbGVtZW50UmVmOiBFbGVtZW50UmVmLFxuICAgKSB7fVxuXG4gIC8qKlxuICAgKiBSZW5kZXIgYSBmaWx0ZXIgaW5wdXQgdW5kZXIgZWFjaCBjb2x1bW4gd2hvc2UgYGZpbHRlcmFibGVgIHJlc29sdmVzIHRydWUuXG4gICAqXG4gICAqIFRoZSBpbnB1dHMgYnVpbGQgYSBjb250YWlucy1maWx0ZXIgcGVyIGNvbHVtbiBhbmQgaGFuZCBpdCB0b1xuICAgKiBgYXBpLnNldEZpbHRlck1vZGVsYCwgZGVib3VuY2VkLiBGaWVsZHMgd2l0aG91dCBhIGZpbHRlciBpbnB1dCBhcmUgbGVmdFxuICAgKiBhbG9uZTogYSBwcm9ncmFtbWF0aWMgZmlsdGVyIG9uIGEgbm9uLWZpbHRlcmFibGUgY29sdW1uIHN1cnZpdmVzIHR5cGluZ1xuICAgKiBoZXJlLCB3aGlsZSB0aGUgZmlsdGVyYWJsZSBmaWVsZHMgYmVsb25nIHRvIHRoZSByb3cg4oCUIGxhc3Qgd3JpdGVyIHdpbnMuXG4gICAqL1xuICBASW5wdXQoKSBmaWx0ZXJSb3c6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKiogQ3VycmVudCBmaWx0ZXIgdGV4dCBwZXIgZmllbGQuICovXG4gIHByb3RlY3RlZCBmaWx0ZXJUZXh0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG4gIHByaXZhdGUgZmlsdGVySW5wdXQkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAvKiogRGVib3VuY2UgZm9yIHRoZSBmaWx0ZXIgcm93LCBpbiBtcy4gKi9cbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgRklMVEVSX0RFQk9VTkNFID0gMjAwO1xuXG4gIHByb3RlY3RlZCBvbkZpbHRlcklucHV0KGNvbDogT25lQ29sdW1uRGVmPFQ+LCBldmVudDogRXZlbnQpOiB2b2lkIHtcblxuICAgIHRoaXMuZmlsdGVyVGV4dHNbY29sLmZpZWxkIGFzIHN0cmluZ10gPSAoZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQpLnZhbHVlO1xuXG4gICAgdGhpcy5maWx0ZXJJbnB1dCQubmV4dCgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhcHBseUZpbHRlclJvdygpOiB2b2lkIHtcblxuICAgIGNvbnN0IG1hbmFnZWQgPSBuZXcgU2V0KFxuICAgICAgdGhpcy5jb2x1bW5EZWZzXG4gICAgICAgIC5maWx0ZXIoY29sdW1uID0+IGNvbHVtbi5fcmVzb2x2ZWRGaWx0ZXJhYmxlICYmIGNvbHVtbi5maWVsZClcbiAgICAgICAgLm1hcChjb2x1bW4gPT4gY29sdW1uLmZpZWxkIGFzIHN0cmluZyksXG4gICAgKTtcblxuICAgIGNvbnN0IHByZXNlcnZlZCA9IHRoaXMuYXBpLmdldEZpbHRlck1vZGVsKCkuZmlsdGVyKGVudHJ5ID0+ICFtYW5hZ2VkLmhhcyhlbnRyeS5maWVsZCkpO1xuXG4gICAgY29uc3Qgb3duOiBPbmVGaWx0ZXJNb2RlbFtdID0gT2JqZWN0LmVudHJpZXModGhpcy5maWx0ZXJUZXh0cylcbiAgICAgIC5maWx0ZXIoKFtmaWVsZCwgdGV4dF0pID0+IG1hbmFnZWQuaGFzKGZpZWxkKSAmJiB0ZXh0LnRyaW0oKSAhPT0gJycpXG4gICAgICAubWFwKChbZmllbGQsIHRleHRdKSA9PiAoe1xuICAgICAgICBmaWVsZCxcbiAgICAgICAgbG9naWNPcGVyYXRvcjogJ0FORCcgYXMgY29uc3QsXG4gICAgICAgIGNvbmRpdGlvbnM6IFt7IG9wZXJhdG9yOiAnY29udGFpbnMnIGFzIGNvbnN0LCB2YWx1ZTogdGV4dC50cmltKCkgfV0sXG4gICAgICB9KSk7XG5cbiAgICB0aGlzLmFwaS5zZXRGaWx0ZXJNb2RlbChbLi4ucHJlc2VydmVkLCAuLi5vd25dKTtcbiAgfVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuXG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLmFkZChcbiAgICAgIHRoaXMuZmlsdGVySW5wdXQkXG4gICAgICAgIC5waXBlKGRlYm91bmNlVGltZShPbmVHcmlkSGVhZGVyQ29tcG9uZW50LkZJTFRFUl9ERUJPVU5DRSkpXG4gICAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5hcHBseUZpbHRlclJvdygpKSxcbiAgICApO1xuXG4gICAgLy8gTGlzdGVuIENvbHVtbiBDaGFuZ2VkIEV2ZW50XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLmFkZCh0aGlzLmV2ZW50U2VydmljZS5hZGRFdmVudExpc3RlbmVyKCdjb2x1bW5DaGFuZ2VkJywgKHBheWxvYWQ6IENvbHVtbkNoYW5nZWRFdmVudCkgPT4ge1xuXG4gICAgICBjb25zdCB7IGdyb3VwcywgY29sdW1ucyB9ID0gcGF5bG9hZDtcblxuICAgICAgaWYgKGdyb3Vwcykge1xuXG4gICAgICAgIHRoaXMuZ3JvdXBDb2x1bW5EZWZzID0gZ3JvdXBzIGFzIE9uZUdyb3VwQ29sdW1uRGVmW107XG4gICAgICB9XG5cbiAgICAgIGlmIChjb2x1bW5zKSB7XG5cbiAgICAgICAgdGhpcy5jb2x1bW5EZWZzID0gY29sdW1ucyBhcyBPbmVDb2x1bW5EZWZbXTtcbiAgICAgIH1cblxuICAgICAgLy8gdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgfSkpO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuXG4gICAgLy8gVGhlIGlucHV0IHNldHRlciBjYW4gcnVuIGJlZm9yZSB0aGUgdmlldyBleGlzdHMsIHNvIHdoYXRldmVyIGFycml2ZWRcbiAgICAvLyBmaXJzdCBpcyBhcHBsaWVkIG9uY2UgaGVyZS5cbiAgICB0aGlzLmFwcGx5U2Nyb2xsTGVmdCgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhcHBseVNjcm9sbExlZnQoKTogdm9pZCB7XG5cbiAgICBpZiAodGhpcy5oZWFkZXJWaWV3cG9ydCkge1xuXG4gICAgICB0aGlzLmhlYWRlclZpZXdwb3J0Lm5hdGl2ZUVsZW1lbnQuc2Nyb2xsTGVmdCA9IHRoaXMuX3Njcm9sbExlZnQ7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1pbmltdW0gYSBjb2x1bW4gY2FuIGJlIHJlc2l6ZWQgdG8sIGJ5IHBvaW50ZXIgb3Iga2V5Ym9hcmQuXG4gICAqXG4gICAqIEV4cG9zZWQgdG8gdGhlIHRlbXBsYXRlIGZvciBgYXJpYS12YWx1ZW1pbmAsIHNvIHdoYXQgdGhlIHJlc2l6ZXIgYW5ub3VuY2VzXG4gICAqIGFuZCB3aGF0IGl0IGVuZm9yY2VzIGNhbm5vdCBkcmlmdCBhcGFydC5cbiAgICovXG4gIHByb3RlY3RlZCByZWFkb25seSBNSU5fQ09MVU1OX1dJRFRIID0gNTA7XG5cbiAgLyoqXG4gICAqIFRoZSBoZWFkZXIncyDii64gYnV0dG9uIHdhcyBhIGRpdiB3aXRoIGFuIGVtcHR5IGhhbmRsZXIg4oCUIGl0IHJlbmRlcmVkLFxuICAgKiBsb29rZWQgaW50ZXJhY3RpdmUsIGFuZCBkaWQgbm90aGluZyBhdCBhbGwuIE1ha2luZyBpdCBrZXlib2FyZC1yZWFjaGFibGVcbiAgICogd2l0aG91dCBnaXZpbmcgaXQgYSBwdXJwb3NlIHdvdWxkIG9ubHkgaGF2ZSBhZGRlZCBhIGRlYWQgdGFiIHN0b3AgcGVyXG4gICAqIGNvbHVtbiwgc28gaXQgbm93IHJlcG9ydHMgdGhlIHByZXNzIHRoZSBzYW1lIHdheSBldmVyeSByb3cgYWN0aW9uIGRvZXMgYW5kXG4gICAqIHRoZSBob3N0IGRlY2lkZXMgd2hhdCBhIGNvbHVtbiBtZW51IG1lYW5zLlxuICAgKi9cbiAgQE91dHB1dCgpIGhlYWRlck1lbnVDbGljayA9IG5ldyBFdmVudEVtaXR0ZXI8T25lQ29sdW1uRGVmPFQ+PigpO1xuXG4gIC8qKlxuICAgKiBSZW5kZXIgdGhlIGdyaWQncyBkZWZhdWx0IGNvbHVtbiBtZW51IGJlaGluZCB0aGUg4ouuIGJ1dHRvbi5cbiAgICpcbiAgICogT3B0LWluOiBob3N0cyB0aGF0IGJvdW5kIGAoaGVhZGVyTWVudUNsaWNrKWAgdG8gb3BlbiB0aGVpciBvd24gbWVudSBrZWVwXG4gICAqIGV4YWN0bHkgdGhlIGJlaGF2aW91ciB0aGV5IGhhZCDigJQgdGhlIGludGVudCBzdGlsbCBlbWl0cyBlaXRoZXIgd2F5LlxuICAgKi9cbiAgQElucHV0KCkgaGVhZGVyTWVudTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKiBUaGUgY29sdW1uIHdob3NlIGRlZmF1bHQgbWVudSBpcyBvcGVuLCBvciBudWxsLiAqL1xuICBwcm90ZWN0ZWQgb3Blbk1lbnVDb2x1bW46IE9uZUNvbHVtbkRlZjxUPiB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBEaXN0YW5jZSBmcm9tIHRoZSBoZWFkZXIncyByaWdodCBlZGdlIHRvIHRoZSBvcGVuIGNvbHVtbidzLCBpbiBweC4gKi9cbiAgcHJvdGVjdGVkIG1lbnVPZmZzZXRSaWdodCA9IDA7XG5cbiAgb25IZWFkZXJNZW51T3B0aW9uQ2xpY2soY29sdW1uRGVmOiBPbmVDb2x1bW5EZWY8VD4sIGV2ZW50PzogTW91c2VFdmVudCkge1xuXG4gICAgdGhpcy5oZWFkZXJNZW51Q2xpY2suZW1pdChjb2x1bW5EZWYpO1xuXG4gICAgaWYgKCF0aGlzLmhlYWRlck1lbnUpIHJldHVybjtcblxuICAgIGlmICh0aGlzLm9wZW5NZW51Q29sdW1uPy5pZCA9PT0gY29sdW1uRGVmLmlkKSB7XG5cbiAgICAgIHRoaXMub3Blbk1lbnVDb2x1bW4gPSBudWxsO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gUmlnaHQtYWxpZ25lZCB1bmRlciB0aGUgb3BlbmluZyBjb2x1bW4uIE1lYXN1cmVkIGJlY2F1c2UgdGhlIG1lbnVcbiAgICAvLyBjYW5ub3QgcmVuZGVyIGluc2lkZSB0aGUgY29sdW1uIOKAlCBldmVyeSBib3ggaW4gdGhlIGhlYWRlciBjbGlwcyDigJQgc29cbiAgICAvLyBpdCBzaXRzIG91dHNpZGUgYW5kIGhhcyB0byBiZSB0b2xkIHdoZXJlIHRoZSBjb2x1bW4gaXMuXG4gICAgY29uc3QgY29sdW1uRWxlbWVudCA9IChldmVudD8udGFyZ2V0IGFzIEhUTUxFbGVtZW50KT8uY2xvc2VzdCgnLm9uZS1ncmlkLWhlYWRlci1jb2x1bW4nKTtcbiAgICBjb25zdCBob3N0RWxlbWVudCA9IHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50O1xuXG4gICAgdGhpcy5tZW51T2Zmc2V0UmlnaHQgPSBjb2x1bW5FbGVtZW50XG4gICAgICA/IE1hdGgubWF4KGhvc3RFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnJpZ2h0IC0gY29sdW1uRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5yaWdodCwgMClcbiAgICAgIDogMDtcblxuICAgIHRoaXMub3Blbk1lbnVDb2x1bW4gPSBjb2x1bW5EZWY7XG4gIH1cblxuICAvKiogVGhlIG9wZW4gY29sdW1uJ3MgY3VycmVudCBzb3J0LCBzbyB0aGUgbWVudSBvZmZlcnMgdGhlIG90aGVyIHN0YXRlcy4gKi9cbiAgcHJvdGVjdGVkIG1lbnVTb3J0U3RhdGUoY29sOiBPbmVDb2x1bW5EZWY8VD4pOiAnYXNjJyB8ICdkZXNjJyB8IG51bGwge1xuXG4gICAgcmV0dXJuIHRoaXMuYXBpLnNvcnRNb2RlbC5maW5kKGVudHJ5ID0+IGVudHJ5LmNvbElkID09PSBjb2wuZmllbGQpPy5zb3J0ID8/IG51bGw7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25IZWFkZXJNZW51QWN0aW9uKGFjdGlvbjogT25lSGVhZGVyTWVudUFjdGlvbiwgY29sOiBPbmVDb2x1bW5EZWY8VD4pOiB2b2lkIHtcblxuICAgIHN3aXRjaCAoYWN0aW9uKSB7XG5cbiAgICAgIGNhc2UgJ3NvcnRBc2MnOlxuICAgICAgY2FzZSAnc29ydERlc2MnOiB7XG5cbiAgICAgICAgLy8gTWlycm9ycyBhIHNvcnQtYnV0dG9uIGNsaWNrOiBhIHNpbmdsZS1jb2x1bW4gbW9kZWwuIFRoZSBoZWFkZXIncyBvd25cbiAgICAgICAgLy8gY3ljbGUgc3RhdGUgZm9sbG93cywgc28gdGhlIHNvcnQgYnV0dG9uIGtlZXBzIGN5Y2xpbmcgZnJvbSBoZXJlLlxuICAgICAgICB0aGlzLnNvcnRNb2RlbCA9IFt7IGNvbElkOiBjb2wuZmllbGQgYXMga2V5b2YgVCwgc29ydDogYWN0aW9uID09PSAnc29ydEFzYycgPyAnYXNjJyA6ICdkZXNjJyB9XTtcbiAgICAgICAgdGhpcy5hcGkub25Tb3J0Q2hhbmdlZCh0aGlzLnNvcnRNb2RlbCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY2FzZSAnY2xlYXJTb3J0JzpcbiAgICAgICAgdGhpcy5zb3J0TW9kZWwgPSBbXTtcbiAgICAgICAgdGhpcy5hcGkub25Tb3J0Q2hhbmdlZCh0aGlzLnNvcnRNb2RlbCk7XG4gICAgICAgIHJldHVybjtcblxuICAgICAgY2FzZSAncGluTGVmdCc6XG4gICAgICAgIHRoaXMuYXBpLnVwZGF0ZUNvbHVtbihjb2wuaWQsIHsgcGlubmVkOiAnbGVmdCcgfSk7XG4gICAgICAgIHJldHVybjtcblxuICAgICAgY2FzZSAncGluUmlnaHQnOlxuICAgICAgICB0aGlzLmFwaS51cGRhdGVDb2x1bW4oY29sLmlkLCB7IHBpbm5lZDogJ3JpZ2h0JyB9KTtcbiAgICAgICAgcmV0dXJuO1xuXG4gICAgICBjYXNlICd1bnBpbic6XG4gICAgICAgIHRoaXMuYXBpLnVwZGF0ZUNvbHVtbihjb2wuaWQsIHsgcGlubmVkOiB1bmRlZmluZWQgfSk7XG4gICAgICAgIHJldHVybjtcblxuICAgICAgY2FzZSAnaGlkZSc6XG4gICAgICAgIHRoaXMuYXBpLnNldENvbHVtblZpc2libGUoY29sLmlkLCBmYWxzZSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgY2xvc2VIZWFkZXJNZW51KCk6IHZvaWQge1xuXG4gICAgdGhpcy5vcGVuTWVudUNvbHVtbiA9IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmVzaXplIGZyb20gdGhlIGtleWJvYXJkLlxuICAgKlxuICAgKiBUaGUgcG9pbnRlciBwYXRoIGlzIGEgZHJhZywgYW5kIFdDQUcgMi41LjcgcmVxdWlyZXMgYSBzaW5nbGUtcG9pbnRlclxuICAgKiBhbHRlcm5hdGl2ZSB0aGF0IGlzIG5vdCBvbmUuIEFycm93cyBzdGVwLCBzaGlmdCBzdGVwcyBjb2Fyc2VyLCBhbmRcbiAgICogSG9tZS9FbmQgZ28gdG8gdGhlIGNvbHVtbidzIG93biBib3VuZHMuXG4gICAqL1xuICBwcm90ZWN0ZWQgb25SZXNpemVLZXlkb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50LCBjb2x1bW5JbmRleDogbnVtYmVyKTogdm9pZCB7XG5cbiAgICBjb25zdCBjb2x1bW4gPSB0aGlzLmNvbHVtbkRlZnNbY29sdW1uSW5kZXhdO1xuXG4gICAgaWYgKCFjb2x1bW4pIHJldHVybjtcblxuICAgIGNvbnN0IHN0ZXAgPSBldmVudC5zaGlmdEtleSA/IDUwIDogMTA7XG4gICAgY29uc3QgY3VycmVudCA9IGNvbHVtbi53aWR0aCA/PyByZXNvbHZlQ29sdW1uV2lkdGgoY29sdW1uKTtcblxuICAgIGxldCB3aWR0aDogbnVtYmVyO1xuXG4gICAgc3dpdGNoIChldmVudC5rZXkpIHtcblxuICAgICAgY2FzZSAnQXJyb3dMZWZ0JzogIHdpZHRoID0gY3VycmVudCAtIHN0ZXA7IGJyZWFrO1xuICAgICAgY2FzZSAnQXJyb3dSaWdodCc6IHdpZHRoID0gY3VycmVudCArIHN0ZXA7IGJyZWFrO1xuICAgICAgY2FzZSAnSG9tZSc6ICAgICAgIHdpZHRoID0gY29sdW1uLm1pbldpZHRoID8/IHRoaXMuTUlOX0NPTFVNTl9XSURUSDsgYnJlYWs7XG4gICAgICBjYXNlICdFbmQnOiAgICAgICAgd2lkdGggPSBjb2x1bW4ubWF4V2lkdGggPz8gY3VycmVudCArIHN0ZXA7IGJyZWFrO1xuICAgICAgZGVmYXVsdDogcmV0dXJuO1xuICAgIH1cblxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICBjb25zdCBtaW4gPSBNYXRoLm1heChjb2x1bW4ubWluV2lkdGggPz8gMCwgdGhpcy5NSU5fQ09MVU1OX1dJRFRIKTtcbiAgICBjb25zdCBtYXggPSBjb2x1bW4ubWF4V2lkdGggPz8gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZO1xuXG4gICAgY29uc3QgbmV3V2lkdGggPSBNYXRoLm1pbihNYXRoLm1heCh3aWR0aCwgbWluKSwgbWF4KTtcblxuICAgIC8vIEhvbWUgYXQgdGhlIG1pbmltdW0sIEVuZCBhdCB0aGUgbWF4aW11bTogYWxyZWFkeSBjbGFtcGVkIHRoZXJlLCBub3RoaW5nXG4gICAgLy8gY2hhbmdlZCwgbm90aGluZyB0byBhbm5vdW5jZS5cbiAgICBpZiAobmV3V2lkdGggPT09IGN1cnJlbnQpIHJldHVybjtcblxuICAgIC8vIEEgaGFuZC1yZXNpemVkIGNvbHVtbiBzdG9wcyBmbGV4aW5nIOKAlCBvdGhlcndpc2UgdGhlIG5leHQgcmVmbG93IHdvdWxkXG4gICAgLy8gb3ZlcndyaXRlIHRoZSB3aWR0aCB0aGUgdXNlciBqdXN0IGNob3NlLlxuICAgIHRoaXMuYXBpLnVwZGF0ZUNvbHVtbihjb2x1bW4uaWQsIHsgd2lkdGg6IG5ld1dpZHRoLCBmbGV4OiB1bmRlZmluZWQgfSk7XG5cbiAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KCdjb2x1bW5SZXNpemVkJywgeyBjb2x1bW5JZDogY29sdW1uLmlkLCBuZXdXaWR0aCB9KTtcbiAgfVxuXG4gIG9uSGVhZGVyTWVudVNvcnRDbGljayhjb2xJZDoga2V5b2YgVCkge1xuXG4gICAgY29uc3QgY3VycmVudFNvcnQgPSB0aGlzLnNvcnRNb2RlbC5maW5kKHNvcnQgPT4gc29ydC5jb2xJZCA9PT0gY29sSWQpPy5zb3J0ID8/IG51bGw7XG5cbiAgICBjb25zdCBuZXh0U29ydCA9IHRoaXMuY3ljbGVTb3J0KGN1cnJlbnRTb3J0KTtcblxuICAgIHRoaXMuc29ydE1vZGVsID0gbmV4dFNvcnQgPyBbeyBjb2xJZCwgc29ydDogbmV4dFNvcnQgfV0gOiBbXTtcblxuICAgIHRoaXMuYXBpLm9uU29ydENoYW5nZWQodGhpcy5zb3J0TW9kZWwpO1xuICB9XG5cbiAgLy8gQ3ljbGUgU29ydGluZyBNb2RlbFxuICBwcml2YXRlIGN5Y2xlU29ydChjdXJyZW50OiAnYXNjJyB8ICdkZXNjJyB8IG51bGwpOiAnYXNjJyB8ICdkZXNjJyB8IG51bGwge1xuXG4gICAgc3dpdGNoIChjdXJyZW50KSB7XG5cbiAgICAgIGNhc2UgbnVsbDogcmV0dXJuICdhc2MnO1xuXG4gICAgICBjYXNlICdhc2MnOiByZXR1cm4gJ2Rlc2MnO1xuXG4gICAgICBjYXNlICdkZXNjJzogcmV0dXJuIG51bGw7XG5cbiAgICAgIGRlZmF1bHQ6IHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIG9uUmVzaXplU3RhcnQoZXZlbnQ6IE1vdXNlRXZlbnQsIGNvbHVtbkluZGV4OiBudW1iZXIpOiB2b2lkIHtcblxuICAgIC8vIFByZXZlbnQgdGV4dCBzZWxlY3Rpb24gYW5kIGRlZmF1bHQgYmVoYXZpb3JcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgLy8gU3RvcmUgaW5pdGlhbCB2YWx1ZXNcbiAgICB0aGlzLnJlc2l6aW5nID0gdHJ1ZTtcbiAgICB0aGlzLnJlc2l6ZUNvbHVtbkluZGV4ID0gY29sdW1uSW5kZXg7XG4gICAgdGhpcy5zdGFydFggPSBldmVudC5jbGllbnRYO1xuXG4gICAgLy8gTWVhc3VyZSB3aGF0IGlzIG9uIHNjcmVlbiByYXRoZXIgdGhhbiB0cnVzdGluZyBgY29sLndpZHRoYCwgd2hpY2ggaXNcbiAgICAvLyBvcHRpb25hbDogYSBjb2x1bW4gc2l6ZWQgcHVyZWx5IGJ5IG1pbldpZHRoIGhhZCBgdW5kZWZpbmVkYCBoZXJlLCBhbmRcbiAgICAvLyBgTWF0aC5tYXgoNTAsIHVuZGVmaW5lZCArIGRlbHRhWClgIGlzIE5hTiDigJQgdGhlIGNvbHVtbiBjb2xsYXBzZWQgb24gdGhlXG4gICAgLy8gZmlyc3QgbW91c2UgbW92ZSBhbmQgY291bGQgbm90IGJlIHJlY292ZXJlZC5cbiAgICBjb25zdCBjb2x1bW5FbGVtZW50ID0gKGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudCk/LmNsb3Nlc3Q8SFRNTEVsZW1lbnQ+KCcub25lLWdyaWQtaGVhZGVyLWNvbHVtbicpO1xuXG4gICAgdGhpcy5zdGFydFdpZHRoID0gY29sdW1uRWxlbWVudD8ub2Zmc2V0V2lkdGggfHwgcmVzb2x2ZUNvbHVtbldpZHRoKHRoaXMuY29sdW1uRGVmc1tjb2x1bW5JbmRleF0pO1xuXG4gICAgLy8gQWRkIGRvY3VtZW50LWxldmVsIGxpc3RlbmVycyBmb3IgZHJhZyBhbmQgcmVsZWFzZVxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMub25SZXNpemVNb3ZlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5vblJlc2l6ZUVuZCk7XG5cbiAgICAvLyBBZGQgYSBjbGFzcyB0byBib2R5IHRvIG1haW50YWluIGN1cnNvciBkdXJpbmcgZHJhZ1xuICAgIGRvY3VtZW50LmJvZHkuc3R5bGUuY3Vyc29yID0gJ2NvbC1yZXNpemUnO1xuICB9XG5cbiAgLy8gQXJyb3cgZnVuY3Rpb24gdG8gcHJlc2VydmUgJ3RoaXMnIGNvbnRleHRcbiAgcHJpdmF0ZSBvblJlc2l6ZU1vdmUgPSAoZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkID0+IHtcblxuICAgIGlmICghdGhpcy5yZXNpemluZyB8fCB0aGlzLnJlc2l6ZUNvbHVtbkluZGV4ID09PSBudWxsKSByZXR1cm47XG5cbiAgICAvLyBDYWxjdWxhdGUgaG93IGZhciB0aGUgbW91c2UgaGFzIG1vdmVkXG4gICAgY29uc3QgZGVsdGFYID0gZXZlbnQuY2xpZW50WCAtIHRoaXMuc3RhcnRYO1xuXG4gICAgLy8gQ2FsY3VsYXRlIG5ldyB3aWR0aCAod2l0aCBtaW5pbXVtIG9mIDUwcHgpXG4gICAgY29uc3QgbmV3V2lkdGggPSBNYXRoLm1heCh0aGlzLk1JTl9DT0xVTU5fV0lEVEgsIHRoaXMuc3RhcnRXaWR0aCArIGRlbHRhWCk7XG5cbiAgICAvLyBVcGRhdGUgdGhlIGNvbHVtbiB3aWR0aC4gQSBoYW5kLXJlc2l6ZWQgY29sdW1uIHN0b3BzIGZsZXhpbmcsIG9yIHRoZVxuICAgIC8vIG5leHQgcmVmbG93IHdvdWxkIG92ZXJ3cml0ZSB0aGUgd2lkdGggdGhlIHVzZXIgaXMgZHJhZ2dpbmcgb3V0LlxuICAgIHRoaXMuYXBpLnVwZGF0ZUNvbHVtbih0aGlzLmNvbHVtbkRlZnNbdGhpcy5yZXNpemVDb2x1bW5JbmRleF0uaWQsIHsgd2lkdGg6IG5ld1dpZHRoLCBmbGV4OiB1bmRlZmluZWQgfSk7XG4gIH1cblxuICBwcml2YXRlIG9uUmVzaXplRW5kID0gKCk6IHZvaWQgPT4ge1xuXG4gICAgLy8gT25lIGV2ZW50IHBlciBjb21wbGV0ZWQgZ2VzdHVyZSwgbm90IG9uZSBwZXIgbW91c2Vtb3ZlIOKAlCBhbmQgbm9uZSBhdCBhbGxcbiAgICAvLyBmb3IgYSBjbGljayBvbiB0aGUgaGFuZGxlIHRoYXQgbmV2ZXIgbW92ZWQuXG4gICAgaWYgKHRoaXMucmVzaXplQ29sdW1uSW5kZXggIT09IG51bGwpIHtcblxuICAgICAgY29uc3QgY29sdW1uID0gdGhpcy5jb2x1bW5EZWZzW3RoaXMucmVzaXplQ29sdW1uSW5kZXhdO1xuICAgICAgY29uc3QgbmV3V2lkdGggPSBjb2x1bW4/LndpZHRoID8/IHRoaXMuc3RhcnRXaWR0aDtcblxuICAgICAgaWYgKGNvbHVtbiAmJiBuZXdXaWR0aCAhPT0gdGhpcy5zdGFydFdpZHRoKSB7XG5cbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudCgnY29sdW1uUmVzaXplZCcsIHsgY29sdW1uSWQ6IGNvbHVtbi5pZCwgbmV3V2lkdGggfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2xlYW4gdXBcbiAgICB0aGlzLnJlc2l6aW5nID0gZmFsc2U7XG4gICAgdGhpcy5yZXNpemVDb2x1bW5JbmRleCA9IG51bGw7XG4gICAgZG9jdW1lbnQuYm9keS5zdHlsZS5jdXJzb3IgPSAnJztcblxuICAgIC8vIFJlbW92ZSBkb2N1bWVudCBsaXN0ZW5lcnNcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLm9uUmVzaXplTW92ZSk7XG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMub25SZXNpemVFbmQpO1xuICB9XG5cbiAgLy8gVHJhY2sgdGhlIGRyYWdnZWQgY29sdW1uIGluZGV4XG4gIG9uRHJhZ0NvbHVtblN0YXJ0KGV2ZW50OiBEcmFnRXZlbnQsIGluZGV4OiBudW1iZXIpOiB2b2lkIHtcblxuICAgIHRoaXMuZHJhZ2dlZEluZGV4ID0gaW5kZXg7XG4gICAgdGhpcy5kcmFnU291cmNlSW5kZXggPSBpbmRleDtcblxuICAgIC8vIE9wdGlvbmFsOiBTZXQgZHJhZyBpbWFnZS9lZmZlY3RcbiAgICBpZiAoZXZlbnQuZGF0YVRyYW5zZmVyKSB7XG5cbiAgICAgIGV2ZW50LmRhdGFUcmFuc2Zlci5lZmZlY3RBbGxvd2VkID0gJ21vdmUnO1xuICAgIH1cbiAgfVxuXG4gIG9uRHJhZ0NvbHVtbk92ZXIoZXZlbnQ6IERyYWdFdmVudCwgdGFyZ2V0SW5kZXg6IG51bWJlcik6IHZvaWQge1xuXG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgIC8vIFNraXAgaWYgZHJhZ2dpbmcgb3ZlciBpdHNlbGYgb3Igbm8gZHJhZyBpbiBwcm9ncmVzc1xuICAgIGlmICh0aGlzLmRyYWdnZWRJbmRleCA9PT0gbnVsbCB8fCB0aGlzLmRyYWdnZWRJbmRleCA9PT0gdGFyZ2V0SW5kZXgpIHtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIElNTUVESUFURUxZIHJlb3JkZXIgY29sdW1uc1xuICAgIHRoaXMuYXBpLnJlb3JkZXJDb2x1bW5EZWZzKHRoaXMuZHJhZ2dlZEluZGV4LCB0YXJnZXRJbmRleCk7XG5cbiAgICAvLyBVcGRhdGUgZHJhZ2dlZEluZGV4IHRvIHRoZSBuZXcgcG9zaXRpb25cbiAgICB0aGlzLmRyYWdnZWRJbmRleCA9IHRhcmdldEluZGV4O1xuICB9XG5cbiAgb25EcmFnQ29sdW1uRW5kKGV2ZW50OiBEcmFnRXZlbnQpOiB2b2lkIHtcblxuICAgIHRoaXMuZmluaXNoQ29sdW1uRHJhZygpO1xuICB9XG5cbiAgb25Ecm9wQ29sdW1uKGV2ZW50OiBEcmFnRXZlbnQpOiB2b2lkIHtcblxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICB0aGlzLmZpbmlzaENvbHVtbkRyYWcoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgcmVvcmRlciBpdHNlbGYgYWxyZWFkeSBoYXBwZW5lZCwgc3RlcCBieSBzdGVwLCBkdXJpbmcgZHJhZ292ZXIg4oCUIHRoaXNcbiAgICogb25seSByZXBvcnRzIHRoZSBjb21wbGV0ZWQgbW92ZS4gQm90aCBgZHJvcGAgYW5kIGBkcmFnZW5kYCBmdW5uZWwgaGVyZSBhbmRcbiAgICogYm90aCBjYW4gZmlyZSBmb3Igb25lIGdlc3R1cmU7IG51bGxpbmcgdGhlIGluZGV4ZXMgbWFrZXMgdGhlIHNlY29uZCBjYWxsIGFcbiAgICogbm8tb3AsIHNvIG9uZSBnZXN0dXJlIHJlcG9ydHMgb25jZS5cbiAgICovXG4gIHByaXZhdGUgZmluaXNoQ29sdW1uRHJhZygpOiB2b2lkIHtcblxuICAgIGlmICh0aGlzLmRyYWdnZWRJbmRleCAhPT0gbnVsbCAmJiB0aGlzLmRyYWdTb3VyY2VJbmRleCAhPT0gbnVsbCAmJiB0aGlzLmRyYWdnZWRJbmRleCAhPT0gdGhpcy5kcmFnU291cmNlSW5kZXgpIHtcblxuICAgICAgY29uc3QgY29sdW1uID0gdGhpcy5jb2x1bW5EZWZzW3RoaXMuZHJhZ2dlZEluZGV4XTtcblxuICAgICAgaWYgKGNvbHVtbikge1xuXG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoJ2NvbHVtbk1vdmVkJywgeyBjb2x1bW5JZDogY29sdW1uLmlkLCB0b0luZGV4OiB0aGlzLmRyYWdnZWRJbmRleCB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmRyYWdnZWRJbmRleCA9IG51bGw7XG4gICAgdGhpcy5kcmFnU291cmNlSW5kZXggPSBudWxsO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG5cbiAgICAvLyBUaGlzIGNvbXBsZXRlZCBhbiB1bnVzZWQgU3ViamVjdCBhbmQgbGVmdCB0aGUgcmVhbCBzdWJzY3JpcHRpb24gcnVubmluZy5cbiAgICAvLyBJdCBzdXJ2aXZlZCBvbmx5IGJlY2F1c2UgT25lR3JpZEV2ZW50U2VydmljZSBpcyBjb21wb25lbnQtc2NvcGVkIGFuZFxuICAgIC8vIHRlYXJzIGl0cyBvd24gbGlzdGVuZXJzIGRvd24g4oCUIHRoZSBoZWFkZXIgd2FzIHJlbHlpbmcgb24gdGhhdCBieSBhY2NpZGVudC5cbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMudW5zdWJzY3JpYmUoKTtcblxuICAgIC8vIEEgcmVzaXplIGluIGZsaWdodCBvd25zIHR3byBsaXN0ZW5lcnMgb24gYGRvY3VtZW50YC4gV2l0aG91dCB0aGlzIHRoZXlcbiAgICAvLyBvdXRsaXZlIHRoZSBjb21wb25lbnQsIGFuZCB0aGVpciBjbG9zdXJlcyBrZWVwIGl0IGFsaXZlIHdpdGggdGhlbS5cbiAgICBpZiAodGhpcy5yZXNpemluZykge1xuXG4gICAgICB0aGlzLm9uUmVzaXplRW5kKCk7XG4gICAgfVxuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwib25lLWdyaWQtaGVhZGVyXCIgcm9sZT1cInJvd2dyb3VwXCI+XG4gICAgQGlmIChlbmFibGVHcm91cENvbHVtbkRlZnMpIHtcbiAgICAgICAgPGRpdiBjbGFzcz1cIm9uZS1ncm91cC1oZWFkZXItcm93XCIgcm9sZT1cInByZXNlbnRhdGlvblwiIFtzdHlsZS50cmFuc2Zvcm1dPVwiJ3RyYW5zbGF0ZVgoLScgKyBzY3JvbGxMZWZ0ICsgJ3B4KSdcIj5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJncm91cENvbHVtbnM7IGNvbnRleHQ6IHsgZ3JvdXBzOiBncm91cENvbHVtbkRlZnMgfVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICA8L2Rpdj5cbiAgICB9XG4gICAgPCEtLSBUaGUgY29sdW1uIHJvdyBpcyBzY3JvbGxlZCByYXRoZXIgdGhhbiB0cmFuc2xhdGVkLiBgcG9zaXRpb246IHN0aWNreWBcbiAgICAgICAgIHJlc29sdmVzIGFnYWluc3QgdGhlIG5lYXJlc3Qgc2Nyb2xscG9ydCwgYW5kIGEgdHJhbnNmb3JtZWQgYW5jZXN0b3IgaXNcbiAgICAgICAgIG5vdCBvbmUg4oCUIHBpbm5lZCBoZWFkZXJzIGNvdWxkIG5ldmVyIGhvbGQgdGhlaXIgcGxhY2UgaW5zaWRlIGl0LiBUaGVcbiAgICAgICAgIGdyb3VwIHJvdyBhYm92ZSBrZWVwcyBpdHMgdHJhbnNmb3JtOiBncm91cHMgc3BhbiBjb250aWd1b3VzIGNvbHVtbnMsXG4gICAgICAgICB3aGljaCBwaW5uaW5nIHJlb3JkZXJzLCBzbyB0aGUgdHdvIGZlYXR1cmVzIGRvIG5vdCBjb21iaW5lLiAtLT5cbiAgICA8ZGl2ICNoZWFkZXJWaWV3cG9ydCBjbGFzcz1cIm9uZS1ncmlkLWhlYWRlci12aWV3cG9ydFwiIHJvbGU9XCJwcmVzZW50YXRpb25cIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm9uZS1oZWFkZXItcm93XCIgcm9sZT1cInJvd1wiIGFyaWEtcm93aW5kZXg9XCIxXCI+XG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiaGVhZGVyQ29sdW1uczsgY29udGV4dDogeyBjb2x1bW5zOiBjb2x1bW5EZWZzIH1cIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPCEtLSBGaWx0ZXIgUm93IChncmlkIG9wdC1pbikuIExpdmVzIGluc2lkZSB0aGUgaGVhZGVyIHZpZXdwb3J0IHNvIGl0XG4gICAgICAgICAgICAgc2Nyb2xscyB3aXRoIHRoZSBjb2x1bW5zIGFuZCBpdHMgcGlubmVkIGNlbGxzIHN0aWNrIHRoZSBzYW1lIHdheS4gLS0+XG4gICAgICAgIEBpZiAoZmlsdGVyUm93KSB7XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwib25lLWZpbHRlci1yb3dcIiByb2xlPVwicm93XCIgYXJpYS1yb3dpbmRleD1cIjJcIj5cbiAgICAgICAgICAgICAgICBAZm9yIChjb2wgb2YgY29sdW1uRGVmczsgdHJhY2sgY29sLmlkKSB7XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJvbmUtZmlsdGVyLWNlbGxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgcm9sZT1cImdyaWRjZWxsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtY29saW5kZXhdPVwiJGluZGV4ICsgMVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbY2xhc3Mub25lLWNvbHVtbi1waW5uZWQtbGVmdF09XCJjb2wucGlubmVkID09PSAnbGVmdCdcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2NsYXNzLm9uZS1jb2x1bW4tcGlubmVkLXJpZ2h0XT1cImNvbC5waW5uZWQgPT09ICdyaWdodCdcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2NsYXNzLm9uZS1jb2x1bW4tcGlubmVkLWVkZ2VdPVwiY29sLl9waW5uZWRFZGdlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS5sZWZ0LnB4XT1cImNvbC5waW5uZWQgPT09ICdsZWZ0JyA/IGNvbC5fcGlubmVkT2Zmc2V0IDogbnVsbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUucmlnaHQucHhdPVwiY29sLnBpbm5lZCA9PT0gJ3JpZ2h0JyA/IGNvbC5fcGlubmVkT2Zmc2V0IDogbnVsbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUud2lkdGgucHhdPVwiY29sLndpZHRoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS5taW4td2lkdGgucHhdPVwiY29sLm1pbldpZHRoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS5tYXgtd2lkdGgucHhdPVwiY29sLm1heFdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICBAaWYgKGNvbC5fcmVzb2x2ZWRGaWx0ZXJhYmxlICYmIGNvbC5maWVsZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBjbGFzcz1cIm9uZS1maWx0ZXItaW5wdXRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ0ZpbHRlciAnICsgKGNvbC5oZWFkZXJOYW1lIHx8IGNvbC5maWVsZClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdmFsdWVdPVwiZmlsdGVyVGV4dHNbY29sLmZpZWxkXSA/PyAnJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChpbnB1dCk9XCJvbkZpbHRlcklucHV0KGNvbCwgJGV2ZW50KVwiIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG4gICAgPC9kaXY+XG48L2Rpdj5cblxuPCEtLSBUaGUgZGVmYXVsdCBjb2x1bW4gbWVudSAoZ3JpZCBvcHQtaW4pLiBBIHNpYmxpbmcgb2YgdGhlIGhlYWRlciBibG9ja1xuICAgICBiZWNhdXNlIGV2ZXJ5dGhpbmcgaW5zaWRlIGl0IGNsaXBzIHdpdGggb3ZlcmZsb3c6IGhpZGRlbjsgdGhlIGhvc3RcbiAgICAgcG9zaXRpb25zIGl0IGp1c3QgYmVsb3csIHJpZ2h0LWFsaWduZWQgdG8gdGhlIG9wZW5pbmcgY29sdW1uLiAtLT5cbkBpZiAoaGVhZGVyTWVudSAmJiBvcGVuTWVudUNvbHVtbikge1xuICAgIDxvbmUtZ3JpZC1oZWFkZXItbWVudVxuICAgICAgICBbc3R5bGUucmlnaHQucHhdPVwibWVudU9mZnNldFJpZ2h0XCJcbiAgICAgICAgW2NvbHVtbl09XCJvcGVuTWVudUNvbHVtblwiXG4gICAgICAgIFtzb3J0U3RhdGVdPVwibWVudVNvcnRTdGF0ZShvcGVuTWVudUNvbHVtbilcIlxuICAgICAgICBbY2FuSGlkZV09XCJjb2x1bW5EZWZzLmxlbmd0aCA+IDFcIlxuICAgICAgICAobWVudUFjdGlvbik9XCJvbkhlYWRlck1lbnVBY3Rpb24oJGV2ZW50LCBvcGVuTWVudUNvbHVtbilcIlxuICAgICAgICAobWVudUNsb3NlKT1cImNsb3NlSGVhZGVyTWVudSgpXCIgLz5cbn1cblxuPCEtLSBHcm91cCBIZWFkZXIgQ2VsbCBUZW1wbGF0ZSAtLT5cbjxuZy10ZW1wbGF0ZSAjZ3JvdXBDb2x1bW5zIGxldC1ncm91cHM9XCJncm91cHNcIj5cbiAgICBAZm9yKGdyb3VwIG9mIGdyb3VwczsgdHJhY2sgZ3JvdXAuaWQpIHtcbiAgICAgICAgPGRpdiBjbGFzcz1cIm9uZS1ncm91cC1oZWFkZXItY2VsbFwiXG4gICAgICAgICAgICBbc3R5bGUud2lkdGgucHhdPVwiZ3JvdXAud2lkdGhcIlxuICAgICAgICAgICAgW25nQ2xhc3NdPVwiZ3JvdXAuX3Jlc29sdmVkR3JvdXBDbGFzc1wiXG4gICAgICAgICAgICBbbmdTdHlsZV09XCJncm91cC5fcmVzb2x2ZWRHcm91cFN0eWxlXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwib25lLWdyb3VwLWhlYWRlci1jZWxsLXRleHRcIj5cbiAgICAgICAgICAgICAgICB7eyBncm91cC5oZWFkZXJOYW1lIH19XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgfVxuPC9uZy10ZW1wbGF0ZT5cblxuPCEtLSBIZWFkZXIgQ2VsbCBUZW1wbGF0ZSAtLT5cbjxuZy10ZW1wbGF0ZSAjaGVhZGVyQ29sdW1ucyBsZXQtY29sdW1ucz1cImNvbHVtbnNcIj5cbiAgICBAZm9yIChjb2wgb2YgY29sdW1uczsgbGV0IGNvbEluZGV4ID0gJGluZGV4OyB0cmFjayBjb2wuaWQpIHtcbiAgICAgICAgPGRpdiBjbGFzcz1cIm9uZS1ncmlkLWhlYWRlci1jb2x1bW5cIlxuICAgICAgICAgICAgcm9sZT1cImNvbHVtbmhlYWRlclwiXG4gICAgICAgICAgICBbYXR0ci5hcmlhLWNvbGluZGV4XT1cImNvbEluZGV4ICsgMVwiXG4gICAgICAgICAgICBbYXR0ci5hcmlhLXNvcnRdPVwiY29sLmZpZWxkIHwgY29sdW1uU29ydFN0YXRlOmFwaS5zb3J0TW9kZWwgfCBhcmlhU29ydDpjb2wuX3Jlc29sdmVkU29ydGFibGVcIlxuICAgICAgICAgICAgW2F0dHIuZGF0YS1pbmRleF09XCJjb2xJbmRleFwiXG4gICAgICAgICAgICBbY2xhc3Mub25lLWNvbHVtbi1waW5uZWQtbGVmdF09XCJjb2wucGlubmVkID09PSAnbGVmdCdcIlxuICAgICAgICAgICAgW2NsYXNzLm9uZS1jb2x1bW4tcGlubmVkLXJpZ2h0XT1cImNvbC5waW5uZWQgPT09ICdyaWdodCdcIlxuICAgICAgICBbY2xhc3Mub25lLWNvbHVtbi1waW5uZWQtZWRnZV09XCJjb2wuX3Bpbm5lZEVkZ2VcIlxuICAgICAgICAgICAgW2NsYXNzLm9uZS1jb2x1bW4tcGlubmVkLWVkZ2VdPVwiY29sLl9waW5uZWRFZGdlXCJcbiAgICAgICAgICAgIFtzdHlsZS5sZWZ0LnB4XT1cImNvbC5waW5uZWQgPT09ICdsZWZ0JyA/IGNvbC5fcGlubmVkT2Zmc2V0IDogbnVsbFwiXG4gICAgICAgICAgICBbc3R5bGUucmlnaHQucHhdPVwiY29sLnBpbm5lZCA9PT0gJ3JpZ2h0JyA/IGNvbC5fcGlubmVkT2Zmc2V0IDogbnVsbFwiXG4gICAgICAgICAgICBbc3R5bGUud2lkdGgucHhdPVwiY29sLndpZHRoXCJcbiAgICAgICAgICAgIFtzdHlsZS5taW4td2lkdGgucHhdPVwiY29sLm1pbldpZHRoXCJcbiAgICAgICAgICAgIFtzdHlsZS5tYXgtd2lkdGgucHhdPVwiY29sLm1heFdpZHRoXCJcbiAgICAgICAgICAgIFtkcmFnZ2FibGVdPVwiY29sLl9yZXNvbHZlZERyYWdhYmxlXCJcbiAgICAgICAgICAgIChkcmFnc3RhcnQpPVwib25EcmFnQ29sdW1uU3RhcnQoJGV2ZW50LCBjb2xJbmRleClcIlxuICAgICAgICAgICAgKGRyYWdvdmVyKT1cIm9uRHJhZ0NvbHVtbk92ZXIoJGV2ZW50LCBjb2xJbmRleClcIlxuICAgICAgICAgICAgKGRyYWdlbmQpPVwib25EcmFnQ29sdW1uRW5kKCRldmVudClcIlxuICAgICAgICAgICAgKGRyb3ApPVwib25Ecm9wQ29sdW1uKCRldmVudClcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJvbmUtZ3JpZC1oZWFkZXItY2VsbFwiXG4gICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwiY29sLl9yZXNvbHZlZEhlYWRlckNsYXNzXCJcbiAgICAgICAgICAgICAgICBbbmdTdHlsZV09XCJjb2wuX3Jlc29sdmVkSGVhZGVyU3R5bGVcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm9uZS1ncmlkLWhlYWRlci1jZWxsLWdyb3VwXCI+XG4gICAgICAgICAgICAgICAgICAgIEBpZiAoY29sPy5oZWFkZXJDaGVja2JveFNlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgPG9uZS1ncmlkLWNoZWNrYm94LWhlYWRlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthcGldPVwiYXBpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbYWxsb3dlZEVkaXRdPVwiYWxsb3dlZEVkaXRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHt7IGNvbD8uaGVhZGVyTmFtZSA/PyAnJyB9fVxuICAgICAgICAgICAgICAgIDwvc3Bhbj5cblxuICAgICAgICAgICAgICAgIDwhLS0gT2cgUmVzaXplIEhhbmRsZXIgLS0+XG4gICAgICAgICAgICAgICAgQGlmIChjb2wuX3Jlc29sdmVkUmVzaXphYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIDwhLS0gYHNlcGFyYXRvcmAgaXMgdGhlIEFSSUEgd2luZG93LXNwbGl0dGVyIHBhdHRlcm4sIHdoaWNoIGlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgd2hhdCBhIGNvbHVtbiByZXNpemVyIGlzLiBGb2N1c2FibGUgYW5kIGFycm93LW9wZXJhYmxlXG4gICAgICAgICAgICAgICAgICAgICAgICAgYmVjYXVzZSBXQ0FHIDIuNS43IHJlcXVpcmVzIGV2ZXJ5dGhpbmcgYWNoaWV2YWJsZSBieVxuICAgICAgICAgICAgICAgICAgICAgICAgIGRyYWdnaW5nIHRvIGhhdmUgYSBub24tZHJhZ2dpbmcgYWx0ZXJuYXRpdmUuIC0tPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cIm9nLXJlc2l6ZS1oYW5kbGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgcm9sZT1cInNlcGFyYXRvclwiXG4gICAgICAgICAgICAgICAgICAgICAgICB0YWJpbmRleD1cIjBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJpYS1vcmllbnRhdGlvbj1cInZlcnRpY2FsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ1Jlc2l6ZSAnICsgKGNvbC5oZWFkZXJOYW1lIHx8IGNvbC5maWVsZClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS12YWx1ZW5vd109XCJjb2wud2lkdGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS12YWx1ZW1pbl09XCJjb2wubWluV2lkdGggfHwgTUlOX0NPTFVNTl9XSURUSFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLXZhbHVlbWF4XT1cImNvbC5tYXhXaWR0aCB8fCBudWxsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIChtb3VzZWRvd24pPVwib25SZXNpemVTdGFydCgkZXZlbnQsIGNvbEluZGV4KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAoa2V5ZG93bik9XCJvblJlc2l6ZUtleWRvd24oJGV2ZW50LCBjb2xJbmRleClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiYmkgYmktZ3JpcC12ZXJ0aWNhbFwiPjwvaT5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm9uZS1ncmlkLWhlYWRlci1jZWxsLWdyb3VwXCI+XG5cbiAgICAgICAgICAgICAgICAgICAgPCEtLSBTb3J0IE1lbnUgQnV0dG9uIC0tPlxuICAgICAgICAgICAgICAgICAgICBAaWYgKGNvbC5fcmVzb2x2ZWRTb3J0YWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSBBIGJ1dHRvbiwgbm90IGEgZGl2IHdpdGggYSBjbGljayBoYW5kbGVyOiBzb3J0aW5nIHdhc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludGVyLW9ubHkuIFRoZSBjdXJyZW50IHN0YXRlIGlzIG5vdCByZXBlYXRlZCBoZXJlIOKAlFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdCBpcyBvbiB0aGUgY29sdW1uaGVhZGVyJ3MgYGFyaWEtc29ydGAsIGFuZCBzYXlpbmcgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHdpY2UgbWFrZXMgYSBzY3JlZW4gcmVhZGVyIHJlYWQgaXQgdHdpY2UuIC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwib25lLWdyaWQtaGVhZGVyLW1lbnUtYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidTb3J0IGJ5ICcgKyAoY29sLmhlYWRlck5hbWUgfHwgY29sLmZpZWxkKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3RpdGxlXT1cIidTb3J0IGJ5ICcgKyAoY29sLmhlYWRlck5hbWUgfHwgY29sLmZpZWxkKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uSGVhZGVyTWVudVNvcnRDbGljayhjb2wuZmllbGQpXCI+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBAaWYgKChjb2wuZmllbGQgfCBjb2x1bW5Tb3J0U3RhdGU6YXBpLnNvcnRNb2RlbCkgPT09ICdhc2MnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsdWNpZGUtaWNvbiBuYW1lPVwiYXJyb3ctdXAtYS16XCIgW3NpemVdPVwiMTZcIiBbc3Ryb2tlV2lkdGhdPVwiMlwiPjwvbHVjaWRlLWljb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBlbHNlIGlmICgoY29sLmZpZWxkIHwgY29sdW1uU29ydFN0YXRlOmFwaS5zb3J0TW9kZWwpID09PSAnZGVzYycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGx1Y2lkZS1pY29uIG5hbWU9XCJhcnJvdy1kb3duLXotYVwiIFtzaXplXT1cIjE2XCIgW3N0cm9rZVdpZHRoXT1cIjJcIj48L2x1Y2lkZS1pY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBAZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsdWNpZGUtaWNvbiBuYW1lPVwiYXJyb3ctZG93bi11cFwiIFtzaXplXT1cIjE2XCIgW3N0cm9rZVdpZHRoXT1cIjJcIj48L2x1Y2lkZS1pY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgPCEtLSBPZyBPcHRpb24gTWVudSBCdXR0b24gLS0+XG4gICAgICAgICAgICAgICAgICAgIEBpZiAoY29sICYmICFjb2wuX3Jlc29sdmVkU3VwcHJlc3NIZWFkZXJNZW51QnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJvbmUtZ3JpZC1oZWFkZXItbWVudS1idXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ09wdGlvbnMgZm9yICcgKyAoY29sLmhlYWRlck5hbWUgfHwgY29sLmZpZWxkKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1oYXNwb3B1cF09XCJoZWFkZXJNZW51ID8gJ21lbnUnIDogbnVsbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1leHBhbmRlZF09XCJoZWFkZXJNZW51ID8gb3Blbk1lbnVDb2x1bW4/LmlkID09PSBjb2wuaWQgOiBudWxsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdGl0bGVdPVwiJ09wdGlvbnMgZm9yICcgKyAoY29sLmhlYWRlck5hbWUgfHwgY29sLmZpZWxkKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uSGVhZGVyTWVudU9wdGlvbkNsaWNrKGNvbCwgJGV2ZW50KVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiYmkgYmktdGhyZWUtZG90cy12ZXJ0aWNhbFwiPjwvaT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgfVxuPC9uZy10ZW1wbGF0ZT5cbiJdfQ==