@acorex/components 18.10.16 → 18.11.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. package/action-sheet/lib/action-sheet.class.d.ts +8 -0
  2. package/common/index.d.ts +1 -0
  3. package/common/lib/types/base/component.types.d.ts +8 -0
  4. package/common/lib/types/base/events.types.d.ts +21 -0
  5. package/common/lib/types/base/index.d.ts +2 -0
  6. package/esm2022/action-sheet/lib/action-sheet.class.mjs +1 -1
  7. package/esm2022/action-sheet/lib/action-sheet.component.mjs +3 -3
  8. package/esm2022/common/index.mjs +2 -1
  9. package/esm2022/common/lib/classes/events.class.mjs +1 -1
  10. package/esm2022/common/lib/components/base-component.class.mjs +1 -1
  11. package/esm2022/common/lib/types/base/component.types.mjs +27 -0
  12. package/esm2022/common/lib/types/base/events.types.mjs +19 -0
  13. package/esm2022/common/lib/types/base/index.mjs +3 -0
  14. package/esm2022/menu/index.mjs +4 -4
  15. package/esm2022/menu/lib/context-menu.component.mjs +232 -0
  16. package/esm2022/menu/lib/menu-item.component.mjs +310 -0
  17. package/esm2022/menu/lib/menu.component.mjs +27 -33
  18. package/esm2022/menu/lib/menu.module.mjs +7 -7
  19. package/esm2022/menu/lib/menu.service.mjs +10 -8
  20. package/esm2022/menu/lib/menu.types.mjs +14 -0
  21. package/fesm2022/acorex-components-action-sheet.mjs +2 -2
  22. package/fesm2022/acorex-components-action-sheet.mjs.map +1 -1
  23. package/fesm2022/acorex-components-common.mjs +47 -3
  24. package/fesm2022/acorex-components-common.mjs.map +1 -1
  25. package/fesm2022/acorex-components-menu.mjs +536 -161
  26. package/fesm2022/acorex-components-menu.mjs.map +1 -1
  27. package/menu/index.d.ts +3 -3
  28. package/menu/lib/context-menu.component.d.ts +52 -0
  29. package/menu/lib/menu-item.component.d.ts +60 -0
  30. package/menu/lib/menu.component.d.ts +10 -11
  31. package/menu/lib/menu.module.d.ts +9 -9
  32. package/menu/lib/menu.service.d.ts +14 -3
  33. package/menu/lib/menu.types.d.ts +38 -0
  34. package/package.json +43 -43
  35. package/esm2022/menu/lib/class/popover.class.mjs +0 -2
  36. package/esm2022/menu/lib/class/root-menu.class.mjs +0 -8
  37. package/esm2022/menu/lib/menu-item/menu-item.component.mjs +0 -160
  38. package/menu/lib/class/popover.class.d.ts +0 -2
  39. package/menu/lib/class/root-menu.class.d.ts +0 -7
  40. package/menu/lib/menu-item/menu-item.component.d.ts +0 -81
@@ -0,0 +1,232 @@
1
+ import { NXComponent, NXEvent } from '@acorex/components/common';
2
+ import { afterNextRender, ChangeDetectionStrategy, Component, HostBinding, HostListener, inject, input, output, Renderer2, signal, ViewEncapsulation, } from '@angular/core';
3
+ import { AXRootMenu } from './menu.types';
4
+ import { AXMenuService } from './menu.service';
5
+ import { AXHtmlUtil } from '@acorex/core/utils';
6
+ import { cloneDeep } from 'lodash-es';
7
+ import { isBrowser } from '@acorex/core/platform';
8
+ import * as i0 from "@angular/core";
9
+ import * as i1 from "@angular/common";
10
+ import * as i2 from "@acorex/components/decorators";
11
+ import * as i3 from "./menu-item.component";
12
+ export class AXContextMenuOpeningEvent extends NXEvent {
13
+ constructor() {
14
+ super(...arguments);
15
+ this.canceled = false;
16
+ }
17
+ }
18
+ /**
19
+ * Represents a menu component that displays context menu.
20
+ * @category Components
21
+ */
22
+ export class AXContextMenuComponent extends NXComponent {
23
+ // Constructor (Dependency Injection)
24
+ /** @ignore */
25
+ constructor() {
26
+ super();
27
+ // Inputs and Outputs
28
+ this.orientation = input('vertical');
29
+ this.openOn = input('hover');
30
+ this.closeOn = input('click');
31
+ this.orginalItems = input([], { alias: "items" });
32
+ this.target = input();
33
+ this.onItemClick = output();
34
+ this.onOpening = output();
35
+ // Injected Services
36
+ this.service = inject(AXMenuService);
37
+ this.renderer = inject(Renderer2);
38
+ this.items = signal([]);
39
+ //
40
+ afterNextRender(() => {
41
+ this.bindContextEvent();
42
+ });
43
+ this.service.closeAllContextMenu$.subscribe(() => {
44
+ this.service.closeAll$.next();
45
+ this.close();
46
+ });
47
+ this.service.openContextMenu$.subscribe((e) => {
48
+ if (e.sender == this) {
49
+ this.internalShowAt(e.point);
50
+ }
51
+ });
52
+ }
53
+ // Lifecycle Hooks
54
+ ngOnDestroy() {
55
+ if (isBrowser()) {
56
+ this.removeContextEvent();
57
+ }
58
+ }
59
+ // Public Methods
60
+ showAt(point) {
61
+ const sender = this;
62
+ this.service.closeAllContextMenu$.next({ sender });
63
+ this.service.openContextMenu$.next({ sender, point });
64
+ }
65
+ close() {
66
+ this.nativeElement.classList.remove('ax-state-open');
67
+ this.removeBackdrop();
68
+ }
69
+ // Private Methods (Internal Logic)
70
+ /** @ignore */
71
+ getTargetElements() {
72
+ const elements = typeof this.target() == 'string' ?
73
+ Array.from(document.querySelectorAll(this.target())) :
74
+ Array.isArray(this.target()) ?
75
+ this.target() :
76
+ [this.target()];
77
+ return elements;
78
+ }
79
+ /** @ignore */
80
+ bindContextEvent() {
81
+ this.getTargetElements().forEach((e) => {
82
+ e.addEventListener('contextmenu', this.handleContextMenu.bind(this));
83
+ });
84
+ }
85
+ /** @ignore */
86
+ removeContextEvent() {
87
+ this.getTargetElements().forEach((e) => {
88
+ e.removeEventListener('contextmenu', this.handleContextMenu.bind(this));
89
+ });
90
+ }
91
+ /** @ignore */
92
+ handleContextMenu(e) {
93
+ e.preventDefault();
94
+ e.stopPropagation();
95
+ //
96
+ const elementsUnderMouse = document.elementsFromPoint(e.x, e.y);
97
+ const targetElements = this.getTargetElements();
98
+ const targetElement = targetElements.find(target => elementsUnderMouse.includes(target));
99
+ //
100
+ const event = {
101
+ sender: this,
102
+ canceled: false,
103
+ targetElement: targetElement,
104
+ items: cloneDeep(this.orginalItems()),
105
+ };
106
+ this.onOpening.emit(event);
107
+ this.items.set(event.items);
108
+ //
109
+ if (!event.canceled) {
110
+ this.showAt({ x: e.clientX, y: e.clientY });
111
+ }
112
+ }
113
+ /** @ignore */
114
+ internalShowAt(point) {
115
+ const elementRef = this.nativeElement;
116
+ elementRef.classList.add('ax-state-open');
117
+ const itemRect = elementRef.getBoundingClientRect();
118
+ const windowWidth = window.innerWidth;
119
+ const windowHeight = window.innerHeight;
120
+ // Detect RTL (Right-To-Left) mode
121
+ const isRtl = AXHtmlUtil.isRtl(elementRef);
122
+ let left;
123
+ if (isRtl) {
124
+ left = point.x - itemRect.width;
125
+ if (left < 0) {
126
+ left = point.x;
127
+ }
128
+ }
129
+ else {
130
+ left = point.x;
131
+ if (left + itemRect.width > windowWidth) {
132
+ left = point.x - itemRect.width;
133
+ }
134
+ }
135
+ const bottom = point.y + itemRect.height;
136
+ let top;
137
+ if (bottom > windowHeight) {
138
+ top = point.y - itemRect.height;
139
+ if (top < 0) {
140
+ top = 0;
141
+ }
142
+ }
143
+ else {
144
+ top = point.y;
145
+ }
146
+ this.renderer.setStyle(elementRef, 'left', `${left}px`);
147
+ this.renderer.setStyle(elementRef, 'top', `${top}px`);
148
+ this.renderer.setStyle(elementRef, 'position', 'fixed');
149
+ this.createBackdrop();
150
+ }
151
+ /** @ignore */
152
+ createBackdrop() {
153
+ this.backdropElement = this.renderer.createElement('div');
154
+ this.renderer.setStyle(this.backdropElement, 'position', 'fixed');
155
+ this.renderer.setStyle(this.backdropElement, 'top', '0');
156
+ this.renderer.setStyle(this.backdropElement, 'left', '0');
157
+ this.renderer.setStyle(this.backdropElement, 'width', '100%');
158
+ this.renderer.setStyle(this.backdropElement, 'height', '100%');
159
+ this.renderer.setStyle(this.backdropElement, 'z-index', '999'); // Ensure it's below the context menu
160
+ this.renderer.setStyle(this.backdropElement, 'background', 'transparent');
161
+ const l1 = this.renderer.listen(this.backdropElement, 'click', () => {
162
+ this.close();
163
+ l1();
164
+ });
165
+ const l2 = this.renderer.listen(this.backdropElement, 'wheel', () => {
166
+ this.close();
167
+ l2();
168
+ });
169
+ const l3 = this.renderer.listen(this.backdropElement, 'contextmenu', (e) => {
170
+ this.close();
171
+ // Get all elements under the mouse pointer
172
+ const elementsUnderMouse = document.elementsFromPoint(e.x, e.y);
173
+ const targetElements = this.getTargetElements();
174
+ if (targetElements.some(target => elementsUnderMouse.includes(target))) {
175
+ e.preventDefault();
176
+ setTimeout(() => {
177
+ //this.internalShowAt({ x: e.x, y: e.y });
178
+ this.handleContextMenu(e);
179
+ });
180
+ }
181
+ l3();
182
+ });
183
+ document.body.appendChild(this.backdropElement);
184
+ }
185
+ /** @ignore */
186
+ removeBackdrop() {
187
+ if (this.backdropElement) {
188
+ if (this.backdropElement.parentNode) {
189
+ this.backdropElement.parentNode.removeChild(this.backdropElement);
190
+ }
191
+ this.backdropElement = null;
192
+ }
193
+ }
194
+ // Host Listeners (UI Interaction Handling)
195
+ /** @ignore */
196
+ onWindowEvent() {
197
+ const sender = this;
198
+ this.service.closeAllContextMenu$.next({ sender: sender }); // Close all menus on scroll or resize
199
+ }
200
+ /** @ignore */
201
+ get __hostClass() {
202
+ return ['ax-menu-container', `ax-orientation-${this.orientation()}`, 'ax-action-list', 'ax-action-list-vertical'];
203
+ }
204
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXContextMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
205
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", type: AXContextMenuComponent, selector: "ax-context-menu", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, openOn: { classPropertyName: "openOn", publicName: "openOn", isSignal: true, isRequired: false, transformFunction: null }, closeOn: { classPropertyName: "closeOn", publicName: "closeOn", isSignal: true, isRequired: false, transformFunction: null }, orginalItems: { classPropertyName: "orginalItems", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onItemClick: "onItemClick", onOpening: "onOpening" }, host: { listeners: { "window:scroll": "onWindowEvent($event)", "window:resize": "onWindowEvent($event)" }, properties: { "class": "this.__hostClass" } }, providers: [
206
+ AXMenuService,
207
+ {
208
+ provide: AXRootMenu,
209
+ useExisting: AXContextMenuComponent
210
+ }
211
+ ], usesInheritance: true, ngImport: i0, template: "<ng-content select=\"ax-menu-item,ax-title,ng-container\"></ng-content>\n\n<ng-container *ngFor=\"let node of items()\" [ngTemplateOutlet]=\"Recursion\"\n [ngTemplateOutletContext]=\"{ $implicit: node }\">\n</ng-container>\n<ng-template #Recursion let-item>\n @if(item.group?.title)\n {\n <ax-title>{{item.group?.title}}</ax-title>\n }\n <ax-menu-item [name]=\"item.name\" [data]=\"item.data\" [disabled]=\"item.disabled\" [color]=\"item.color\">\n <ax-prefix>\n @if(item.icon)\n {\n <ax-icon [icon]=\"item.icon\">\n </ax-icon>\n }\n </ax-prefix>\n @if(item.text)\n {\n <ax-text>{{ item.text }}</ax-text>\n }\n @if(item.suffix)\n {\n <ax-suffix>\n <ax-text>{{ item.suffix.text }}</ax-text>\n </ax-suffix>\n }\n <ng-container *ngFor=\"let child of item.items\" [ngTemplateOutlet]=\"Recursion\"\n [ngTemplateOutletContext]=\"{ $implicit: child }\"></ng-container>\n </ax-menu-item>\n @if(item.break)\n {\n <ax-divider></ax-divider>\n }\n</ng-template>", styles: ["ax-context-menu,ax-menu{width:100%;color:inherit;display:flex;width:max-content}ax-context-menu.ax-menu-container,ax-context-menu .ax-menu-items,ax-menu.ax-menu-container,ax-menu .ax-menu-items{padding-block:.5rem;display:flex;opacity:0;visibility:hidden;transition:opacity .3s;width:max-content;min-width:12rem;height:max-content;position:fixed;flex-direction:column;border-radius:0;border-width:1px;border-color:rgba(var(--ax-color-border-default));background-color:rgba(var(--ax-color-surface));--ax-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--ax-shadow-colored: 0 4px 6px -1px var(--ax-shadow-color), 0 2px 4px -2px var(--ax-shadow-color);box-shadow:var(--ax-ring-offset-shadow, 0 0 rgba(0, 0, 0, 0)),var(--ax-ring-shadow, 0 0 rgba(0, 0, 0, 0)),var(--ax-shadow);border-radius:var(--ax-rounded-border-default);z-index:9999}ax-context-menu.ax-menu-container.ax-state-open,ax-context-menu .ax-menu-items.ax-state-open,ax-menu.ax-menu-container.ax-state-open,ax-menu .ax-menu-items.ax-state-open{opacity:1;visibility:visible}ax-context-menu.ax-action-list-horizontal{padding-inline:1rem}ax-menu.ax-action-list-horizontal{min-width:12rem;gap:.875rem}ax-menu.ax-action-list-horizontal>ax-menu-item{font-weight:500}ax-menu.ax-action-list-horizontal>ax-menu-item>.ax-action-item-prefix{padding-inline-start:0!important}ax-menu.ax-action-list-horizontal>ax-menu-item>.ax-action-item-suffix:not(ax-menu.ax-action-list-horizontal>ax-menu-item>.ax-action-item-suffix:empty){padding-inline-end:0!important;margin-inline-start:0!important}ax-menu.ax-action-list-horizontal>ax-menu-item:hover{background-color:transparent!important}ax-menu.ax-action-list-horizontal>ax-menu-item:hover>.ax-action-item-prefix{color:rgba(var(--ax-color-primary-500))}ax-menu.ax-action-list-horizontal>ax-menu-item:hover>.ax-action-item-suffix{color:rgba(var(--ax-color-primary-500))}ax-menu.ax-action-list-vertical{width:max-content;min-width:12rem}ax-menu.ax-action-list-vertical>ax-menu-item{font-weight:500}ax-menu>ax-menu-item{padding-block:.5rem}ax-menu>ax-menu-item:hover:not(ax-menu>ax-menu-item:hover.ax-state-disabled)>ax-icon,ax-menu>ax-menu-item:hover:not(ax-menu>ax-menu-item:hover.ax-state-disabled)>ax-text{color:rgba(var(--ax-color-primary-500))}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-sub-title, ax-placeholder, ax-overlay" }, { kind: "component", type: i3.AXMenuItemComponent, selector: "ax-menu-item", inputs: ["name", "data", "disabled", "color"], outputs: ["onClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
212
+ }
213
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: AXContextMenuComponent, decorators: [{
214
+ type: Component,
215
+ args: [{ selector: 'ax-context-menu', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
216
+ AXMenuService,
217
+ {
218
+ provide: AXRootMenu,
219
+ useExisting: AXContextMenuComponent
220
+ }
221
+ ], template: "<ng-content select=\"ax-menu-item,ax-title,ng-container\"></ng-content>\n\n<ng-container *ngFor=\"let node of items()\" [ngTemplateOutlet]=\"Recursion\"\n [ngTemplateOutletContext]=\"{ $implicit: node }\">\n</ng-container>\n<ng-template #Recursion let-item>\n @if(item.group?.title)\n {\n <ax-title>{{item.group?.title}}</ax-title>\n }\n <ax-menu-item [name]=\"item.name\" [data]=\"item.data\" [disabled]=\"item.disabled\" [color]=\"item.color\">\n <ax-prefix>\n @if(item.icon)\n {\n <ax-icon [icon]=\"item.icon\">\n </ax-icon>\n }\n </ax-prefix>\n @if(item.text)\n {\n <ax-text>{{ item.text }}</ax-text>\n }\n @if(item.suffix)\n {\n <ax-suffix>\n <ax-text>{{ item.suffix.text }}</ax-text>\n </ax-suffix>\n }\n <ng-container *ngFor=\"let child of item.items\" [ngTemplateOutlet]=\"Recursion\"\n [ngTemplateOutletContext]=\"{ $implicit: child }\"></ng-container>\n </ax-menu-item>\n @if(item.break)\n {\n <ax-divider></ax-divider>\n }\n</ng-template>", styles: ["ax-context-menu,ax-menu{width:100%;color:inherit;display:flex;width:max-content}ax-context-menu.ax-menu-container,ax-context-menu .ax-menu-items,ax-menu.ax-menu-container,ax-menu .ax-menu-items{padding-block:.5rem;display:flex;opacity:0;visibility:hidden;transition:opacity .3s;width:max-content;min-width:12rem;height:max-content;position:fixed;flex-direction:column;border-radius:0;border-width:1px;border-color:rgba(var(--ax-color-border-default));background-color:rgba(var(--ax-color-surface));--ax-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--ax-shadow-colored: 0 4px 6px -1px var(--ax-shadow-color), 0 2px 4px -2px var(--ax-shadow-color);box-shadow:var(--ax-ring-offset-shadow, 0 0 rgba(0, 0, 0, 0)),var(--ax-ring-shadow, 0 0 rgba(0, 0, 0, 0)),var(--ax-shadow);border-radius:var(--ax-rounded-border-default);z-index:9999}ax-context-menu.ax-menu-container.ax-state-open,ax-context-menu .ax-menu-items.ax-state-open,ax-menu.ax-menu-container.ax-state-open,ax-menu .ax-menu-items.ax-state-open{opacity:1;visibility:visible}ax-context-menu.ax-action-list-horizontal{padding-inline:1rem}ax-menu.ax-action-list-horizontal{min-width:12rem;gap:.875rem}ax-menu.ax-action-list-horizontal>ax-menu-item{font-weight:500}ax-menu.ax-action-list-horizontal>ax-menu-item>.ax-action-item-prefix{padding-inline-start:0!important}ax-menu.ax-action-list-horizontal>ax-menu-item>.ax-action-item-suffix:not(ax-menu.ax-action-list-horizontal>ax-menu-item>.ax-action-item-suffix:empty){padding-inline-end:0!important;margin-inline-start:0!important}ax-menu.ax-action-list-horizontal>ax-menu-item:hover{background-color:transparent!important}ax-menu.ax-action-list-horizontal>ax-menu-item:hover>.ax-action-item-prefix{color:rgba(var(--ax-color-primary-500))}ax-menu.ax-action-list-horizontal>ax-menu-item:hover>.ax-action-item-suffix{color:rgba(var(--ax-color-primary-500))}ax-menu.ax-action-list-vertical{width:max-content;min-width:12rem}ax-menu.ax-action-list-vertical>ax-menu-item{font-weight:500}ax-menu>ax-menu-item{padding-block:.5rem}ax-menu>ax-menu-item:hover:not(ax-menu>ax-menu-item:hover.ax-state-disabled)>ax-icon,ax-menu>ax-menu-item:hover:not(ax-menu>ax-menu-item:hover.ax-state-disabled)>ax-text{color:rgba(var(--ax-color-primary-500))}\n"] }]
222
+ }], ctorParameters: () => [], propDecorators: { onWindowEvent: [{
223
+ type: HostListener,
224
+ args: ['window:scroll', ['$event']]
225
+ }, {
226
+ type: HostListener,
227
+ args: ['window:resize', ['$event']]
228
+ }], __hostClass: [{
229
+ type: HostBinding,
230
+ args: ['class']
231
+ }] } });
232
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dC1tZW51LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL2xpYnMvY29tcG9uZW50cy9tZW51L3NyYy9saWIvY29udGV4dC1tZW51LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL2xpYnMvY29tcG9uZW50cy9tZW51L3NyYy9saWIvbWVudS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWlCLFdBQVcsRUFBRSxPQUFPLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNoRixPQUFPLEVBQ0gsZUFBZSxFQUNmLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsV0FBVyxFQUNYLFlBQVksRUFDWixNQUFNLEVBQ04sS0FBSyxFQUNMLE1BQU0sRUFDTixTQUFTLEVBQ1QsTUFBTSxFQUNOLGlCQUFpQixHQUNwQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQStFLFVBQVUsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN2SCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFVBQVUsRUFBVyxNQUFNLG9CQUFvQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDdEMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHVCQUF1QixDQUFDOzs7OztBQUdsRCxNQUFNLE9BQU8seUJBQTBCLFNBQVEsT0FBK0I7SUFBOUU7O1FBRUksYUFBUSxHQUFHLEtBQUssQ0FBQztJQUdyQixDQUFDO0NBQUE7QUFHRDs7O0dBR0c7QUFlSCxNQUFNLE9BQU8sc0JBQXVCLFNBQVEsV0FBVztJQWtCbkQscUNBQXFDO0lBRXJDLGNBQWM7SUFDZDtRQUNJLEtBQUssRUFBRSxDQUFDO1FBcEJaLHFCQUFxQjtRQUVyQixnQkFBVyxHQUFHLEtBQUssQ0FBZ0IsVUFBVSxDQUFDLENBQUM7UUFDL0MsV0FB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ak9RLHNCQUFzQjtrR0FBdEIsc0JBQXNCLHE1QkFScEI7WUFDUCxhQUFhO1lBQ2I7Z0JBQ0ksT0FBTyxFQUFFLFVBQVU7Z0JBQ25CLFdBQVcsRUFBRSxzQkFBc0I7YUFDdEM7U0FDSixpREM3Q0wseW5DQW1DYzs7MkZEWUQsc0JBQXNCO2tCQWRsQyxTQUFTOytCQUNJLGlCQUFpQixtQkFHVix1QkFBdUIsQ0FBQyxNQUFNLGlCQUNoQyxpQkFBaUIsQ0FBQyxJQUFJLGFBQzFCO3dCQUNQLGFBQWE7d0JBQ2I7NEJBQ0ksT0FBTyxFQUFFLFVBQVU7NEJBQ25CLFdBQVcsd0JBQXdCO3lCQUN0QztxQkFDSjt3REEwTk8sYUFBYTtzQkFGcEIsWUFBWTt1QkFBQyxlQUFlLEVBQUUsQ0FBQyxRQUFRLENBQUM7O3NCQUN4QyxZQUFZO3VCQUFDLGVBQWUsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFRckMsV0FBVztzQkFEZCxXQUFXO3VCQUFDLE9BQU8iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBWE9yaWVudGF0aW9uLCBOWENvbXBvbmVudCwgTlhFdmVudCB9IGZyb20gJ0BhY29yZXgvY29tcG9uZW50cy9jb21tb24nO1xuaW1wb3J0IHtcbiAgICBhZnRlck5leHRSZW5kZXIsXG4gICAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gICAgQ29tcG9uZW50LFxuICAgIEhvc3RCaW5kaW5nLFxuICAgIEhvc3RMaXN0ZW5lcixcbiAgICBpbmplY3QsXG4gICAgaW5wdXQsXG4gICAgb3V0cHV0LFxuICAgIFJlbmRlcmVyMixcbiAgICBzaWduYWwsXG4gICAgVmlld0VuY2Fwc3VsYXRpb24sXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQVhNZW51Q2xvc2VUcmlnZ2VyLCBBWE1lbnVJdGVtLCBBWE1lbnVJdGVtQ2xpY2tCYXNlRXZlbnQsIEFYTWVudU9wZW5UcmlnZ2VyLCBBWFJvb3RNZW51IH0gZnJvbSAnLi9tZW51LnR5cGVzJztcbmltcG9ydCB7IEFYTWVudVNlcnZpY2UgfSBmcm9tICcuL21lbnUuc2VydmljZSc7XG5pbXBvcnQgeyBBWEh0bWxVdGlsLCBBWFBvaW50IH0gZnJvbSAnQGFjb3JleC9jb3JlL3V0aWxzJztcbmltcG9ydCB7IGNsb25lRGVlcCB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBpc0Jyb3dzZXIgfSBmcm9tICdAYWNvcmV4L2NvcmUvcGxhdGZvcm0nO1xuXG5cbmV4cG9ydCBjbGFzcyBBWENvbnRleHRNZW51T3BlbmluZ0V2ZW50IGV4dGVuZHMgTlhFdmVudDxBWENvbnRleHRNZW51Q29tcG9uZW50PiB7XG4gICAgaXRlbXM6IEFYTWVudUl0ZW1bXTtcbiAgICBjYW5jZWxlZCA9IGZhbHNlO1xuICAgIHRhcmdldEVsZW1lbnQ6IEhUTUxFbGVtZW50XG5cbn1cbmV4cG9ydCB0eXBlIEFYQ29udGV4dE1lbnVJdGVtc0NsaWNrRXZlbnQgPSBBWE1lbnVJdGVtQ2xpY2tCYXNlRXZlbnQ8QVhDb250ZXh0TWVudUNvbXBvbmVudD5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgbWVudSBjb21wb25lbnQgdGhhdCBkaXNwbGF5cyBjb250ZXh0IG1lbnUuXG4gKiBAY2F0ZWdvcnkgQ29tcG9uZW50c1xuICovXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ2F4LWNvbnRleHQtbWVudScsXG4gICAgdGVtcGxhdGVVcmw6ICcuL21lbnUuY29tcG9uZW50Lmh0bWwnLFxuICAgIHN0eWxlVXJsczogWycuL21lbnUuY29tcG9uZW50LnNjc3MnXSxcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICAgIHByb3ZpZGVyczogW1xuICAgICAgICBBWE1lbnVTZXJ2aWNlLFxuICAgICAgICB7XG4gICAgICAgICAgICBwcm92aWRlOiBBWFJvb3RNZW51LFxuICAgICAgICAgICAgdXNlRXhpc3Rpbmc6IEFYQ29udGV4dE1lbnVDb21wb25lbnRcbiAgICAgICAgfVxuICAgIF1cbn0pXG5leHBvcnQgY2xhc3MgQVhDb250ZXh0TWVudUNvbXBvbmVudCBleHRlbmRzIE5YQ29tcG9uZW50IHtcblxuICAgIC8vIElucHV0cyBhbmQgT3V0cHV0c1xuXG4gICAgb3JpZW50YXRpb24gPSBpbnB1dDxBWE9yaWVudGF0aW9uPigndmVydGljYWwnKTtcbiAgICBvcGVuT24gPSBpbnB1dDxBWE1lbnVPcGVuVHJpZ2dlcj4oJ2hvdmVyJyk7XG4gICAgY2xvc2VPbiA9IGlucHV0PEFYTWVudUNsb3NlVHJpZ2dlcj4oJ2NsaWNrJyk7XG4gICAgb3JnaW5hbEl0ZW1zID0gaW5wdXQ8QVhNZW51SXRlbVtdPihbXSwgeyBhbGlhczogXCJpdGVtc1wiIH0pO1xuICAgIHRhcmdldCA9IGlucHV0PEhUTUxFbGVtZW50IHwgSFRNTEVsZW1lbnRbXSB8IHN0cmluZz4oKTtcblxuICAgIG9uSXRlbUNsaWNrID0gb3V0cHV0PEFYQ29udGV4dE1lbnVJdGVtc0NsaWNrRXZlbnQ+KCk7XG4gICAgb25PcGVuaW5nID0gb3V0cHV0PEFYQ29udGV4dE1lbnVPcGVuaW5nRXZlbnQ+KCk7XG5cbiAgICAvLyBJbmplY3RlZCBTZXJ2aWNlc1xuXG4gICAgcHJpdmF0ZSBzZXJ2aWNlID0gaW5qZWN0KEFYTWVudVNlcnZpY2UpO1xuICAgIHByaXZhdGUgcmVuZGVyZXIgPSBpbmplY3QoUmVuZGVyZXIyKVxuXG4gICAgLy8gQ29uc3RydWN0b3IgKERlcGVuZGVuY3kgSW5qZWN0aW9uKVxuXG4gICAgLyoqIEBpZ25vcmUgKi9cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgLy9cbiAgICAgICAgYWZ0ZXJOZXh0UmVuZGVyKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuYmluZENvbnRleHRFdmVudCgpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnNlcnZpY2UuY2xvc2VBbGxDb250ZXh0TWVudSQuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2VydmljZS5jbG9zZUFsbCQubmV4dCgpO1xuICAgICAgICAgICAgdGhpcy5jbG9zZSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnNlcnZpY2Uub3BlbkNvbnRleHRNZW51JC5zdWJzY3JpYmUoKGUpID0+IHtcbiAgICAgICAgICAgIGlmIChlLnNlbmRlciBhcyBhbnkgPT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW50ZXJuYWxTaG93QXQoZS5wb2ludCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG5cbiAgICAvLyBMaWZlY3ljbGUgSG9va3NcblxuICAgIG5nT25EZXN0cm95KCkge1xuICAgICAgICBpZiAoaXNCcm93c2VyKCkpIHtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlQ29udGV4dEV2ZW50KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBQdWJsaWMgTWV0aG9kc1xuXG4gICAgcHVibGljIHNob3dBdChwb2ludDogQVhQb2ludCkge1xuICAgICAgICBjb25zdCBzZW5kZXIgPSB0aGlzIGFzIGFueSBhcyBBWFJvb3RNZW51O1xuICAgICAgICB0aGlzLnNlcnZpY2UuY2xvc2VBbGxDb250ZXh0TWVudSQubmV4dCh7IHNlbmRlciB9KTtcbiAgICAgICAgdGhpcy5zZXJ2aWNlLm9wZW5Db250ZXh0TWVudSQubmV4dCh7IHNlbmRlciwgcG9pbnQgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGNsb3NlKCkge1xuICAgICAgICB0aGlzLm5hdGl2ZUVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZSgnYXgtc3RhdGUtb3BlbicpO1xuICAgICAgICB0aGlzLnJlbW92ZUJhY2tkcm9wKCk7XG4gICAgfVxuXG4gICAgLy8gUHJpdmF0ZSBQcm9wZXJ0aWVzXG5cbiAgICBwcml2YXRlIGJhY2tkcm9wRWxlbWVudCE6IEhUTUxFbGVtZW50O1xuXG4gICAgcHJvdGVjdGVkIGl0ZW1zID0gc2lnbmFsPEFYTWVudUl0ZW1bXT4oW10pO1xuXG4gICAgLy8gUHJpdmF0ZSBNZXRob2RzIChJbnRlcm5hbCBMb2dpYylcblxuICAgIC8qKiBAaWdub3JlICovXG4gICAgcHJpdmF0ZSBnZXRUYXJnZXRFbGVtZW50cygpOiBIVE1MRWxlbWVudFtdIHtcbiAgICAgICAgY29uc3QgZWxlbWVudHM6IEhUTUxFbGVtZW50W10gPSB0eXBlb2YgdGhpcy50YXJnZXQoKSA9PSAnc3RyaW5nJyA/XG4gICAgICAgICAgICBBcnJheS5mcm9tKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGw8SFRNTEVsZW1lbnQ+KHRoaXMudGFyZ2V0KCkgYXMgc3RyaW5nKSkgOlxuICAgICAgICAgICAgQXJyYXkuaXNBcnJheSh0aGlzLnRhcmdldCgpKSA/XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXQoKSBhcyBIVE1MRWxlbWVudFtdIDpcbiAgICAgICAgICAgICAgICBbdGhpcy50YXJnZXQoKSBhcyBIVE1MRWxlbWVudF1cblxuICAgICAgICByZXR1cm4gZWxlbWVudHM7XG4gICAgfVxuXG4gICAgLyoqIEBpZ25vcmUgKi9cbiAgICBwcml2YXRlIGJpbmRDb250ZXh0RXZlbnQoKSB7XG4gICAgICAgIHRoaXMuZ2V0VGFyZ2V0RWxlbWVudHMoKS5mb3JFYWNoKChlKSA9PiB7XG4gICAgICAgICAgICBlLmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgdGhpcy5oYW5kbGVDb250ZXh0TWVudS5iaW5kKHRoaXMpKTtcbiAgICAgICAgfSlcbiAgICB9XG5cbiAgICAvKiogQGlnbm9yZSAqL1xuICAgIHByaXZhdGUgcmVtb3ZlQ29udGV4dEV2ZW50KCkge1xuICAgICAgICB0aGlzLmdldFRhcmdldEVsZW1lbnRzKCkuZm9yRWFjaCgoZSkgPT4ge1xuICAgICAgICAgICAgZS5yZW1vdmVFdmVudExpc3RlbmVyKCdjb250ZXh0bWVudScsIHRoaXMuaGFuZGxlQ29udGV4dE1lbnUuYmluZCh0aGlzKSk7XG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgLyoqIEBpZ25vcmUgKi9cbiAgICBwcml2YXRlIGhhbmRsZUNvbnRleHRNZW51KGU6IE1vdXNlRXZlbnQpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAvL1xuICAgICAgICBjb25zdCBlbGVtZW50c1VuZGVyTW91c2UgPSBkb2N1bWVudC5lbGVtZW50c0Zyb21Qb2ludChlLngsIGUueSkgYXMgSFRNTEVsZW1lbnRbXTtcbiAgICAgICAgY29uc3QgdGFyZ2V0RWxlbWVudHMgPSB0aGlzLmdldFRhcmdldEVsZW1lbnRzKCk7XG4gICAgICAgIGNvbnN0IHRhcmdldEVsZW1lbnQgPSB0YXJnZXRFbGVtZW50cy5maW5kKHRhcmdldCA9PiBlbGVtZW50c1VuZGVyTW91c2UuaW5jbHVkZXModGFyZ2V0KSlcbiAgICAgICAgLy9cbiAgICAgICAgY29uc3QgZXZlbnQgPSB7XG4gICAgICAgICAgICBzZW5kZXI6IHRoaXMsXG4gICAgICAgICAgICBjYW5jZWxlZDogZmFsc2UsXG4gICAgICAgICAgICB0YXJnZXRFbGVtZW50OiB0YXJnZXRFbGVtZW50LFxuICAgICAgICAgICAgaXRlbXM6IGNsb25lRGVlcCh0aGlzLm9yZ2luYWxJdGVtcygpKSxcbiAgICAgICAgfSBhcyBBWENvbnRleHRNZW51T3BlbmluZ0V2ZW50O1xuICAgICAgICB0aGlzLm9uT3BlbmluZy5lbWl0KGV2ZW50KTtcbiAgICAgICAgdGhpcy5pdGVtcy5zZXQoZXZlbnQuaXRlbXMpO1xuICAgICAgICAvL1xuICAgICAgICBpZiAoIWV2ZW50LmNhbmNlbGVkKSB7XG4gICAgICAgICAgICB0aGlzLnNob3dBdCh7IHg6IGUuY2xpZW50WCwgeTogZS5jbGllbnRZIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIEBpZ25vcmUgKi9cbiAgICBwcml2YXRlIGludGVybmFsU2hvd0F0KHBvaW50OiBBWFBvaW50KSB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnRSZWYgPSB0aGlzLm5hdGl2ZUVsZW1lbnQ7XG4gICAgICAgIGVsZW1lbnRSZWYuY2xhc3NMaXN0LmFkZCgnYXgtc3RhdGUtb3BlbicpO1xuICAgICAgICBjb25zdCBpdGVtUmVjdCA9IGVsZW1lbnRSZWYuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGNvbnN0IHdpbmRvd1dpZHRoID0gd2luZG93LmlubmVyV2lkdGg7XG4gICAgICAgIGNvbnN0IHdpbmRvd0hlaWdodCA9IHdpbmRvdy5pbm5lckhlaWdodDtcblxuICAgICAgICAvLyBEZXRlY3QgUlRMIChSaWdodC1Uby1MZWZ0KSBtb2RlXG4gICAgICAgIGNvbnN0IGlzUnRsID0gQVhIdG1sVXRpbC5pc1J0bChlbGVtZW50UmVmKTtcblxuICAgICAgICBsZXQgbGVmdDogbnVtYmVyO1xuICAgICAgICBpZiAoaXNSdGwpIHtcbiAgICAgICAgICAgIGxlZnQgPSBwb2ludC54IC0gaXRlbVJlY3Qud2lkdGg7XG4gICAgICAgICAgICBpZiAobGVmdCA8IDApIHtcbiAgICAgICAgICAgICAgICBsZWZ0ID0gcG9pbnQueDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxlZnQgPSBwb2ludC54O1xuICAgICAgICAgICAgaWYgKGxlZnQgKyBpdGVtUmVjdC53aWR0aCA+IHdpbmRvd1dpZHRoKSB7XG4gICAgICAgICAgICAgICAgbGVmdCA9IHBvaW50LnggLSBpdGVtUmVjdC53aWR0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGJvdHRvbSA9IHBvaW50LnkgKyBpdGVtUmVjdC5oZWlnaHQ7XG4gICAgICAgIGxldCB0b3A6IG51bWJlcjtcblxuICAgICAgICBpZiAoYm90dG9tID4gd2luZG93SGVpZ2h0KSB7XG4gICAgICAgICAgICB0b3AgPSBwb2ludC55IC0gaXRlbVJlY3QuaGVpZ2h0O1xuICAgICAgICAgICAgaWYgKHRvcCA8IDApIHtcbiAgICAgICAgICAgICAgICB0b3AgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdG9wID0gcG9pbnQueTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUoZWxlbWVudFJlZiwgJ2xlZnQnLCBgJHtsZWZ0fXB4YCk7XG4gICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUoZWxlbWVudFJlZiwgJ3RvcCcsIGAke3RvcH1weGApO1xuICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKGVsZW1lbnRSZWYsICdwb3NpdGlvbicsICdmaXhlZCcpO1xuXG4gICAgICAgIHRoaXMuY3JlYXRlQmFja2Ryb3AoKTtcbiAgICB9XG5cbiAgICAvKiogQGlnbm9yZSAqL1xuICAgIHByaXZhdGUgY3JlYXRlQmFja2Ryb3AoKSB7XG4gICAgICAgIHRoaXMuYmFja2Ryb3BFbGVtZW50ID0gdGhpcy5yZW5kZXJlci5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZSh0aGlzLmJhY2tkcm9wRWxlbWVudCwgJ3Bvc2l0aW9uJywgJ2ZpeGVkJyk7XG4gICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5iYWNrZHJvcEVsZW1lbnQsICd0b3AnLCAnMCcpO1xuICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuYmFja2Ryb3BFbGVtZW50LCAnbGVmdCcsICcwJyk7XG4gICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5iYWNrZHJvcEVsZW1lbnQsICd3aWR0aCcsICcxMDAlJyk7XG4gICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5iYWNrZHJvcEVsZW1lbnQsICdoZWlnaHQnLCAnMTAwJScpO1xuICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuYmFja2Ryb3BFbGVtZW50LCAnei1pbmRleCcsICc5OTknKTsgLy8gRW5zdXJlIGl0J3MgYmVsb3cgdGhlIGNvbnRleHQgbWVudVxuICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuYmFja2Ryb3BFbGVtZW50LCAnYmFja2dyb3VuZCcsICd0cmFuc3BhcmVudCcpO1xuXG4gICAgICAgIGNvbnN0IGwxID0gdGhpcy5yZW5kZXJlci5saXN0ZW4odGhpcy5iYWNrZHJvcEVsZW1lbnQsICdjbGljaycsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICAgICAgICAgIGwxKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IGwyID0gdGhpcy5yZW5kZXJlci5saXN0ZW4odGhpcy5iYWNrZHJvcEVsZW1lbnQsICd3aGVlbCcsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICAgICAgICAgIGwyKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IGwzID0gdGhpcy5yZW5kZXJlci5saXN0ZW4odGhpcy5iYWNrZHJvcEVsZW1lbnQsICdjb250ZXh0bWVudScsIChlOiBNb3VzZUV2ZW50KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNsb3NlKCk7XG4gICAgICAgICAgICAvLyBHZXQgYWxsIGVsZW1lbnRzIHVuZGVyIHRoZSBtb3VzZSBwb2ludGVyXG4gICAgICAgICAgICBjb25zdCBlbGVtZW50c1VuZGVyTW91c2UgPSBkb2N1bWVudC5lbGVtZW50c0Zyb21Qb2ludChlLngsIGUueSkgYXMgSFRNTEVsZW1lbnRbXTtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldEVsZW1lbnRzID0gdGhpcy5nZXRUYXJnZXRFbGVtZW50cygpO1xuICAgICAgICAgICAgaWYgKHRhcmdldEVsZW1lbnRzLnNvbWUodGFyZ2V0ID0+IGVsZW1lbnRzVW5kZXJNb3VzZS5pbmNsdWRlcyh0YXJnZXQpKSkge1xuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgLy90aGlzLmludGVybmFsU2hvd0F0KHsgeDogZS54LCB5OiBlLnkgfSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlQ29udGV4dE1lbnUoZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsMygpO1xuICAgICAgICB9KTtcblxuICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuYmFja2Ryb3BFbGVtZW50KTtcbiAgICB9XG5cbiAgICAvKiogQGlnbm9yZSAqL1xuICAgIHByaXZhdGUgcmVtb3ZlQmFja2Ryb3AoKSB7XG4gICAgICAgIGlmICh0aGlzLmJhY2tkcm9wRWxlbWVudCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuYmFja2Ryb3BFbGVtZW50LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmJhY2tkcm9wRWxlbWVudC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuYmFja2Ryb3BFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuYmFja2Ryb3BFbGVtZW50ID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEhvc3QgTGlzdGVuZXJzIChVSSBJbnRlcmFjdGlvbiBIYW5kbGluZylcblxuICAgIC8qKiBAaWdub3JlICovXG4gICAgQEhvc3RMaXN0ZW5lcignd2luZG93OnNjcm9sbCcsIFsnJGV2ZW50J10pXG4gICAgQEhvc3RMaXN0ZW5lcignd2luZG93OnJlc2l6ZScsIFsnJGV2ZW50J10pXG4gICAgcHJpdmF0ZSBvbldpbmRvd0V2ZW50KCkge1xuICAgICAgICBjb25zdCBzZW5kZXIgPSB0aGlzIGFzIGFueSBhcyBBWFJvb3RNZW51O1xuICAgICAgICB0aGlzLnNlcnZpY2UuY2xvc2VBbGxDb250ZXh0TWVudSQubmV4dCh7IHNlbmRlcjogc2VuZGVyIH0pOyAvLyBDbG9zZSBhbGwgbWVudXMgb24gc2Nyb2xsIG9yIHJlc2l6ZVxuICAgIH1cblxuICAgIC8qKiBAaWdub3JlICovXG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcycpXG4gICAgZ2V0IF9faG9zdENsYXNzKCk6IGFueSB7XG4gICAgICAgIHJldHVybiBbJ2F4LW1lbnUtY29udGFpbmVyJywgYGF4LW9yaWVudGF0aW9uLSR7dGhpcy5vcmllbnRhdGlvbigpfWAsICdheC1hY3Rpb24tbGlzdCcsICdheC1hY3Rpb24tbGlzdC12ZXJ0aWNhbCddO1xuICAgIH1cbn1cbiIsIjxuZy1jb250ZW50IHNlbGVjdD1cImF4LW1lbnUtaXRlbSxheC10aXRsZSxuZy1jb250YWluZXJcIj48L25nLWNvbnRlbnQ+XG5cbjxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IG5vZGUgb2YgaXRlbXMoKVwiIFtuZ1RlbXBsYXRlT3V0bGV0XT1cIlJlY3Vyc2lvblwiXG4gICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiBub2RlIH1cIj5cbjwvbmctY29udGFpbmVyPlxuPG5nLXRlbXBsYXRlICNSZWN1cnNpb24gbGV0LWl0ZW0+XG4gICAgQGlmKGl0ZW0uZ3JvdXA/LnRpdGxlKVxuICAgIHtcbiAgICA8YXgtdGl0bGU+e3tpdGVtLmdyb3VwPy50aXRsZX19PC9heC10aXRsZT5cbiAgICB9XG4gICAgPGF4LW1lbnUtaXRlbSBbbmFtZV09XCJpdGVtLm5hbWVcIiBbZGF0YV09XCJpdGVtLmRhdGFcIiBbZGlzYWJsZWRdPVwiaXRlbS5kaXNhYmxlZFwiIFtjb2xvcl09XCJpdGVtLmNvbG9yXCI+XG4gICAgICAgIDxheC1wcmVmaXg+XG4gICAgICAgICAgICBAaWYoaXRlbS5pY29uKVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgPGF4LWljb24gW2ljb25dPVwiaXRlbS5pY29uXCI+XG4gICAgICAgICAgICA8L2F4LWljb24+XG4gICAgICAgICAgICB9XG4gICAgICAgIDwvYXgtcHJlZml4PlxuICAgICAgICBAaWYoaXRlbS50ZXh0KVxuICAgICAgICB7XG4gICAgICAgIDxheC10ZXh0Pnt7IGl0ZW0udGV4dCB9fTwvYXgtdGV4dD5cbiAgICAgICAgfVxuICAgICAgICBAaWYoaXRlbS5zdWZmaXgpXG4gICAgICAgIHtcbiAgICAgICAgPGF4LXN1ZmZpeD5cbiAgICAgICAgICAgIDxheC10ZXh0Pnt7IGl0ZW0uc3VmZml4LnRleHQgfX08L2F4LXRleHQ+XG4gICAgICAgIDwvYXgtc3VmZml4PlxuICAgICAgICB9XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGNoaWxkIG9mIGl0ZW0uaXRlbXNcIiBbbmdUZW1wbGF0ZU91dGxldF09XCJSZWN1cnNpb25cIlxuICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiBjaGlsZCB9XCI+PC9uZy1jb250YWluZXI+XG4gICAgPC9heC1tZW51LWl0ZW0+XG4gICAgQGlmKGl0ZW0uYnJlYWspXG4gICAge1xuICAgIDxheC1kaXZpZGVyPjwvYXgtZGl2aWRlcj5cbiAgICB9XG48L25nLXRlbXBsYXRlPiJdfQ==