@ngrdt/menu 0.0.17 → 0.0.18

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.
@@ -1,597 +0,0 @@
1
- import { DOCUMENT } from '@angular/common';
2
- import { ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, ElementRef, HostBinding, HostListener, Input, QueryList, Renderer2, ViewChild, ViewChildren, inject, } from '@angular/core';
3
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
- import { Router } from '@angular/router';
5
- import { RdtShortcut, RdtShortcutService, } from '@ngrdt/shortcuts';
6
- import { KB_CODE, RdtObjectUtils, RdtStringUtils, } from '@ngrdt/utils';
7
- import { delay, first, map, of } from 'rxjs';
8
- import { RdtMenuBaseComponent } from '../menu-base/rdt-menu-base.component';
9
- import { DEFAULT_MENU_HORIZONTAL_DIR, DEFAULT_MENU_VERTICAL_DIR, } from '../models';
10
- import { RdtMenuExpandSource, } from '../private-models';
11
- import { FOCUS_VISIBLE, areHorDirsEqual, areVertDirsEqual, findNextItemWithPrefix, menuItemHasChildren, menuItemHasRoute, } from '../utils';
12
- import * as i0 from "@angular/core";
13
- import * as i1 from "@angular/common";
14
- import * as i2 from "@angular/router";
15
- import * as i3 from "@ngrdt/router";
16
- import * as i4 from "@ngrdt/shortcuts";
17
- // TODO: Split positioning and shortcut/focus management in separate classes
18
- export class RdtMenuOverlayComponent {
19
- elRef = inject((ElementRef));
20
- destroyRef = inject(DestroyRef);
21
- renderer = inject(Renderer2);
22
- topLevelMenu = inject(RdtMenuBaseComponent);
23
- parentMenu = inject(RdtMenuOverlayComponent, {
24
- optional: true,
25
- skipSelf: true,
26
- });
27
- cd = inject(ChangeDetectorRef);
28
- router = inject(Router);
29
- document = inject(DOCUMENT);
30
- shortcutService = inject(RdtShortcutService);
31
- children;
32
- focusableElements;
33
- menuItemContainer;
34
- item;
35
- level;
36
- preferredHorizontalDir = DEFAULT_MENU_HORIZONTAL_DIR;
37
- preferredVerticalDir = DEFAULT_MENU_VERTICAL_DIR;
38
- expanded = false;
39
- autofocusItem = null;
40
- // Element used to relatively position menu,
41
- // typically parent element.
42
- // If not specified, parent element is used.
43
- anchorElement;
44
- roleAttr = 'menu';
45
- tabindexAttr = '-1';
46
- get zIndex() {
47
- return this.level + 10;
48
- }
49
- get isRootLevel() {
50
- return this.level === 0;
51
- }
52
- // Bounding box of this excluding any extra offset.
53
- _box;
54
- get box() {
55
- return this._box;
56
- }
57
- // Bounding box of parent element.
58
- _anchorBox;
59
- _containerPadding = { top: 0, bottom: 0 };
60
- // Recalculate child components only after they are initialized.
61
- _viewWasInit = false;
62
- // Currently applied vertical and horizontal directions.
63
- verticalDir = null;
64
- horizontalDir = null;
65
- expandedChild = null;
66
- autofocusSubmenuItem = null;
67
- keyActions = {
68
- [KB_CODE.ARROW.UP]: (index) => this.focusPrevItem(index),
69
- [KB_CODE.ARROW.DOWN]: (index) => this.focusNextItem(index),
70
- [KB_CODE.ARROW.RIGHT]: (index) => this.openSubmenu(index, 'first', RdtMenuExpandSource.Shortcut),
71
- [KB_CODE.ARROW.LEFT]: () => this.closeSelf(),
72
- [KB_CODE.HOME]: () => this.focusItem(0),
73
- [KB_CODE.END]: () => this.focusItem(this.item.items.length - 1),
74
- [KB_CODE.ESCAPE]: () => this.closeSelf(),
75
- [KB_CODE.ENTER]: (index) => this.invokeItemClickByIndex(index),
76
- [KB_CODE.SPACEBAR]: (index) => this.invokeItemClickByIndex(index),
77
- };
78
- get selfExpandSrc() {
79
- if (this.expanded) {
80
- if (this.parentMenu) {
81
- return this.parentMenu.expandedChild?.src;
82
- }
83
- else {
84
- return this.topLevelMenu.expandedChild?.src;
85
- }
86
- }
87
- return undefined;
88
- }
89
- ngOnInit() {
90
- this.setClasses();
91
- this.listenTabKeyPress();
92
- }
93
- ngOnChanges(changes) {
94
- const recalcTriggers = [
95
- 'preferredHorizontalDir',
96
- 'preferredVerticalDir',
97
- 'expanded',
98
- ];
99
- if (recalcTriggers.some((key) => key in changes) && this._viewWasInit) {
100
- this.recalculatePosition(this.preferredHorizontalDir, this.preferredVerticalDir);
101
- }
102
- if (!this.expanded) {
103
- this.expandedChild = null;
104
- }
105
- if ('expanded' in changes && this.expanded) {
106
- // Wait for Angular to set .expanded class,
107
- // because invisible elements cannot be focused.
108
- setTimeout(() => {
109
- switch (this.autofocusItem) {
110
- case null:
111
- this.focusItem(0, false);
112
- break;
113
- case 'first':
114
- this.focusItem(0, true);
115
- break;
116
- case 'last':
117
- this.focusItem(this.item.items.length - 1, true);
118
- }
119
- });
120
- }
121
- }
122
- ngAfterViewInit() {
123
- this.measureContainerPadding();
124
- this.recalculatePosition(this.preferredHorizontalDir, this.preferredVerticalDir);
125
- this._viewWasInit = true;
126
- }
127
- getMinOffsetLeft() {
128
- return this.topLevelMenu.bodyMargin.left;
129
- }
130
- getMaxOffsetLeft() {
131
- return (this.topLevelMenu.clientSize.width -
132
- this._box.width -
133
- this.topLevelMenu.bodyMargin.right);
134
- }
135
- getMinOffsetTop() {
136
- return this.topLevelMenu.bodyMargin.top;
137
- }
138
- getMaxOffsetTop() {
139
- return (this.topLevelMenu.clientSize.height -
140
- this._box.height -
141
- this.topLevelMenu.bodyMargin.bottom);
142
- }
143
- recalculatePosition(preferredHorizontalDir, preferredVerticalDir) {
144
- // Make menu invisible so the menu does not move around in case of slow computer.
145
- this.measureBoundingRect();
146
- if (!this._box || !this._anchorBox) {
147
- return;
148
- }
149
- const newHorDir = this.getRealHorizontalDir(preferredHorizontalDir);
150
- const newVertDir = this.getRealVerticalDir(preferredVerticalDir);
151
- // Horizontal direction
152
- if (newHorDir.dir === 'right') {
153
- newHorDir.left += this._anchorBox.left;
154
- if (!this.isRootLevel) {
155
- newHorDir.left += this._anchorBox.width;
156
- }
157
- }
158
- else if (newHorDir.dir === 'left') {
159
- newHorDir.left += this._anchorBox.left - this._box.width;
160
- if (this.isRootLevel) {
161
- newHorDir.left += this._anchorBox.width;
162
- }
163
- }
164
- // Restrictions from left menu and right menu
165
- newHorDir.left = Math.min(Math.max(this.getMinOffsetLeft(), newHorDir.left), this.getMaxOffsetLeft());
166
- // Vertical direction
167
- if (newVertDir.dir === 'down') {
168
- newVertDir.top = this._anchorBox.top;
169
- if (this.isRootLevel) {
170
- newVertDir.top += this._anchorBox.height;
171
- }
172
- else {
173
- newVertDir.top -= this._containerPadding.top;
174
- }
175
- }
176
- else if (newVertDir.dir === 'up') {
177
- newVertDir.top = this._anchorBox.top - this._box.height;
178
- if (!this.isRootLevel) {
179
- newVertDir.top += this._anchorBox.height + this._containerPadding.top;
180
- }
181
- }
182
- // Restrictions from header and footer
183
- newVertDir.top = Math.min(Math.max(this.getMinOffsetTop(), newVertDir.top), this.getMaxOffsetTop());
184
- if (!areHorDirsEqual(this.horizontalDir, newHorDir) ||
185
- !areVertDirsEqual(this.verticalDir, newVertDir)) {
186
- this.horizontalDir = newHorDir;
187
- this.verticalDir = newVertDir;
188
- this.setClasses();
189
- this.measureBoundingRect();
190
- }
191
- this.recalculateChildren();
192
- }
193
- onItemPointerEnter(item) {
194
- if (this.topLevelMenu.openOnHover &&
195
- this.expandedChild?.src !== RdtMenuExpandSource.Click) {
196
- this.autofocusSubmenuItem = null;
197
- if (menuItemHasChildren(item)) {
198
- this.expandedChild = { item, src: RdtMenuExpandSource.Hover };
199
- this.expanded = true;
200
- }
201
- else {
202
- //console.log('expanded child', this.expandedChild);
203
- this.expandedChild = null;
204
- }
205
- }
206
- }
207
- onItemClick(item) {
208
- const hasChildren = menuItemHasChildren(item);
209
- if ((hasChildren && this.expandedChild?.item !== item) ||
210
- (this.topLevelMenu.openOnHover &&
211
- this.expandedChild?.src === RdtMenuExpandSource.Hover)) {
212
- this.autofocusSubmenuItem = null;
213
- this.expandedChild = { item, src: RdtMenuExpandSource.Click };
214
- }
215
- else {
216
- this.expandedChild = null;
217
- }
218
- // Could also listen to router events, but might be triggered by
219
- // child router navigation.
220
- if (!hasChildren) {
221
- this.topLevelMenu.closeSubmenus();
222
- }
223
- if (typeof item.command === 'function') {
224
- item.command();
225
- }
226
- }
227
- invokeItemClick(item) {
228
- if (menuItemHasRoute(item) && item.routerLink) {
229
- this.router.navigate(item.routerLink);
230
- }
231
- this.onItemClick(item);
232
- this.autofocusSubmenuItem = 'first';
233
- }
234
- getChildRoutes(item) {
235
- return this.topLevelMenu.getChildRoutes(item);
236
- }
237
- closeSubmenus(focusExpanded = false) {
238
- if (focusExpanded && this.expandedChild) {
239
- this.focusItem(this.expandedChild.item);
240
- }
241
- this.expandedChild = null;
242
- this.cd.markForCheck();
243
- }
244
- focusItemRecursively(path) {
245
- const children = [...path];
246
- const thisItem = children.shift();
247
- this.autofocusSubmenuItem = null;
248
- this.autofocusItem = null;
249
- if (children.length > 0) {
250
- this.expandAndGetChild(thisItem, RdtMenuExpandSource.Focus)
251
- .pipe(delay(1))
252
- .subscribe((overlay) => {
253
- overlay.focusItemRecursively(children);
254
- });
255
- }
256
- else {
257
- // First focus the correct item because submenu might have focus on it.
258
- // Removing focused element from DOM results in window:focusout event
259
- // and that closes all menus
260
- this.focusItem(thisItem);
261
- // Now close submenus and therefore remove them from DOM
262
- this.closeSubmenus();
263
- // Wait until they are removed and focus the correct item again
264
- setTimeout(() => this.focusItem(thisItem), 1);
265
- }
266
- }
267
- expandAndGetChild(item, src) {
268
- if (this.item.items.indexOf(item) < 0) {
269
- throw new Error('Attempting to expand item that is not child item of this.item');
270
- }
271
- this.expandedChild = { item, src };
272
- this.cd.markForCheck();
273
- const child = this.children.find((child) => child.item === item);
274
- if (child) {
275
- return of(child);
276
- }
277
- else {
278
- return this.children.changes.pipe(map(() => this.children.find((child) => child.item === item)), first(RdtObjectUtils.notNullGuard));
279
- }
280
- }
281
- onKeyDown(itemIndex, event) {
282
- const hasAction = event.code in this.keyActions;
283
- const isLetter = RdtStringUtils.isAlphabetCharacter(event.key) ||
284
- RdtStringUtils.isNumericCharacter(event.key);
285
- if (hasAction || isLetter) {
286
- event.preventDefault();
287
- }
288
- if (hasAction) {
289
- event.stopPropagation();
290
- }
291
- if (hasAction) {
292
- this.keyActions[event.code](itemIndex);
293
- }
294
- else if (isLetter) {
295
- const next = findNextItemWithPrefix(this.item.items, itemIndex, event.key);
296
- if (next !== null) {
297
- this.focusItem(next);
298
- }
299
- }
300
- }
301
- onTabKeyPress(event) {
302
- // Do not prevent default to correctly switch to previous element
303
- event.originalEvent.stopPropagation();
304
- // Wait for document.activeElement to switch to new element
305
- setTimeout(() => {
306
- if (!this.elRef.nativeElement.contains(this.document.activeElement)) {
307
- this.closeSelf(false);
308
- }
309
- }, 1);
310
- }
311
- invokeItemClickByIndex(itemIndex) {
312
- const item = this.item.items[itemIndex];
313
- if (!item) {
314
- return;
315
- }
316
- this.invokeItemClick(item);
317
- }
318
- focusItem(item, visibleFocus = true) {
319
- let itemIndex;
320
- if (typeof item === 'number') {
321
- itemIndex = item;
322
- }
323
- else {
324
- itemIndex = this.item.items.indexOf(item);
325
- }
326
- if (itemIndex >= 0 && itemIndex < this.focusableElements.length) {
327
- this.blurAllFocusable();
328
- this.focusFocusable(itemIndex, visibleFocus);
329
- }
330
- }
331
- blurAllFocusable() {
332
- this.focusableElements.forEach((el) => this.renderer.removeClass(el.nativeElement, FOCUS_VISIBLE));
333
- }
334
- focusFocusable(itemIndex, visibleFocus) {
335
- const elRef = this.focusableElements.get(itemIndex);
336
- if (elRef) {
337
- if (visibleFocus) {
338
- this.renderer.addClass(elRef.nativeElement, FOCUS_VISIBLE);
339
- }
340
- elRef.nativeElement.focus();
341
- }
342
- }
343
- focusNextItem(itemIndex) {
344
- const next = (itemIndex + 1) % this.item.items.length;
345
- this.focusItem(next);
346
- }
347
- focusPrevItem(itemIndex) {
348
- const prev = (itemIndex - 1 + this.item.items.length) % this.item.items.length;
349
- this.focusItem(prev);
350
- }
351
- openSubmenu(itemIndex, visibleFocus, src) {
352
- if (itemIndex < this.item.items.length &&
353
- menuItemHasChildren(this.item.items[itemIndex])) {
354
- this.expandedChild = { item: this.item.items[itemIndex], src };
355
- this.autofocusSubmenuItem = visibleFocus;
356
- }
357
- }
358
- closeSelf(focusExpanded = true) {
359
- if (this.parentMenu) {
360
- this.parentMenu.closeSubmenus(focusExpanded);
361
- }
362
- else {
363
- this.topLevelMenu.closeSubmenus(focusExpanded);
364
- }
365
- }
366
- checkActiveElement(event) {
367
- if (this.topLevelMenu.closeOnFocusOut && !this.topLevelMenu.openOnHover) {
368
- const thisEl = this.elRef.nativeElement;
369
- const target = event.relatedTarget;
370
- if (!(target instanceof HTMLElement) || !thisEl.contains(target)) {
371
- this.expandedChild = null;
372
- }
373
- }
374
- }
375
- // Calculates direction of this menu and offset in case
376
- // menu won't fit in left nor right of parent menu.
377
- getRealHorizontalDir(preferredHorizontalDir) {
378
- let left;
379
- let right;
380
- // This menu is directly under menubar
381
- if (this.level === 0) {
382
- left = this._anchorBox.right - this._box.width;
383
- right =
384
- this.topLevelMenu.clientSize.width -
385
- (this._anchorBox.left + this._box.width);
386
- }
387
- else {
388
- // Menu is nested
389
- right =
390
- this.topLevelMenu.clientSize.width -
391
- (this._anchorBox.right + this._box.width);
392
- left = this._anchorBox.left - this._box.width;
393
- }
394
- left -= this.topLevelMenu.bodyMargin.left;
395
- right -= this.topLevelMenu.bodyMargin.right;
396
- if (preferredHorizontalDir === 'right') {
397
- // We use preferred if possible.
398
- if (right >= 0) {
399
- return { dir: 'right', left: 0 };
400
- // Then the other one.
401
- }
402
- else if (left >= 0) {
403
- return { dir: 'left', left: 0 };
404
- // Edge case if neither direction can be used (ultra narrow screen).
405
- // Choose direction that covers least of parent menu.
406
- }
407
- else {
408
- return this.getNarrowScreenHorizontalDir(left, right);
409
- }
410
- }
411
- else {
412
- if (left >= 0) {
413
- return { dir: 'left', left: 0 };
414
- }
415
- else if (right >= 0) {
416
- return { dir: 'right', left: 0 };
417
- }
418
- else {
419
- return this.getNarrowScreenHorizontalDir(left, right);
420
- }
421
- }
422
- }
423
- // Finds out where to put menu in case screen is too narrow for two menus
424
- // to fit next to each other. Minimizes area of parent menu covered by this.
425
- getNarrowScreenHorizontalDir(left, right) {
426
- const screenStart = this.topLevelMenu.bodyMargin.left;
427
- const screenEnd = this.topLevelMenu.clientSize.width - this.topLevelMenu.bodyMargin.right;
428
- const screenCenter = (screenStart - screenEnd) / 2;
429
- const leftStart = Math.max(this._anchorBox.left, screenStart);
430
- const leftEnd = Math.min(this._anchorBox.left + this._anchorBox.width, screenCenter);
431
- const rightStart = Math.max(screenCenter, leftEnd);
432
- const rightEnd = Math.min(this._anchorBox.left + this._anchorBox.width, screenEnd);
433
- if (leftEnd - leftStart > rightEnd - rightStart) {
434
- return { dir: 'right', left: right };
435
- }
436
- else {
437
- return { dir: 'left', left: -left };
438
- }
439
- }
440
- getRealVerticalDir(preferredVerticalDir) {
441
- let bottom;
442
- let top;
443
- if (this.level === 0) {
444
- bottom =
445
- this.topLevelMenu.clientSize.height +
446
- this._anchorBox.bottom -
447
- this._box.height;
448
- top = this._anchorBox.top - this._box.height;
449
- }
450
- else {
451
- bottom =
452
- this.topLevelMenu.clientSize.height -
453
- this._anchorBox.top -
454
- this._box.height;
455
- top = this._anchorBox.bottom - this._box.height;
456
- }
457
- top -= this.topLevelMenu.bodyMargin.top;
458
- bottom -= this.topLevelMenu.bodyMargin.bottom;
459
- if (preferredVerticalDir === 'down') {
460
- if (bottom >= 0) {
461
- return { dir: 'down', top: 0 };
462
- }
463
- else if (top >= 0) {
464
- return { dir: 'up', top: 0 };
465
- }
466
- else {
467
- return { dir: preferredVerticalDir, top: 0 };
468
- }
469
- }
470
- else {
471
- if (top >= 0) {
472
- return { dir: 'up', top: 0 };
473
- }
474
- else if (bottom >= 0) {
475
- return { dir: 'down', top: 0 };
476
- }
477
- else {
478
- return { dir: preferredVerticalDir, top: 0 };
479
- }
480
- }
481
- }
482
- // Measures bounding rect of this and offset container
483
- // Should always be called after parent menu has already been measured.
484
- measureBoundingRect() {
485
- this._box = this.elRef.nativeElement.getBoundingClientRect();
486
- const anchor = this.anchorElement ?? this.elRef.nativeElement.parentElement;
487
- this._anchorBox = anchor.getBoundingClientRect();
488
- }
489
- measureContainerPadding() {
490
- const computedStyles = getComputedStyle(this.menuItemContainer.nativeElement);
491
- const paddingTop = parseFloat(computedStyles.paddingTop);
492
- const paddingBottom = parseFloat(computedStyles.paddingBottom);
493
- this._containerPadding = { top: paddingTop, bottom: paddingBottom };
494
- }
495
- recalculateChildren() {
496
- if (this.expanded && this.horizontalDir && this.verticalDir) {
497
- this.children.forEach((child) => child.recalculatePosition(this.horizontalDir.dir, this.verticalDir.dir));
498
- }
499
- }
500
- setClasses() {
501
- if (this.verticalDir) {
502
- if (this.verticalDir.dir === 'up') {
503
- this.setClass('rdt-overlay-up');
504
- this.removeClass('rdt-overlay-down');
505
- }
506
- else {
507
- this.removeClass('rdt-overlay-up');
508
- this.setClass('rdt-overlay-down');
509
- }
510
- this.setOffset('top', this.verticalDir.top);
511
- }
512
- if (this.horizontalDir) {
513
- if (this.horizontalDir.dir === 'left') {
514
- this.setClass('rdt-overlay-left');
515
- this.removeClass('rdt-overlay-right');
516
- }
517
- else {
518
- this.removeClass('rdt-overlay-left');
519
- this.setClass('rdt-overlay-right');
520
- }
521
- this.setOffset('left', this.horizontalDir.left);
522
- }
523
- if (this.isRootLevel) {
524
- this.setClass('rdt-menu-root');
525
- this.removeClass('rdt-menu-sub');
526
- }
527
- else {
528
- this.removeClass('rdt-menu-root');
529
- this.setClass('rdt-menu-sub');
530
- }
531
- }
532
- setClass(className) {
533
- this.renderer.addClass(this.elRef.nativeElement, className);
534
- }
535
- removeClass(className) {
536
- this.renderer.removeClass(this.elRef.nativeElement, className);
537
- }
538
- setOffset(direction, value) {
539
- this.renderer.setStyle(this.elRef.nativeElement, direction, `${value}px`);
540
- }
541
- listenTabKeyPress() {
542
- const shiftTab = RdtShortcut.createUnsafe('shift', 'tab');
543
- const tab = RdtShortcut.createUnsafe('tab');
544
- this.shortcutService
545
- .listen([tab, shiftTab], {
546
- element: this.elRef.nativeElement,
547
- preventDefault: false,
548
- })
549
- .pipe(takeUntilDestroyed(this.destroyRef))
550
- .subscribe((event) => this.onTabKeyPress(event));
551
- }
552
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
553
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: RdtMenuOverlayComponent, selector: "rdt-menu-overlay", inputs: { item: "item", level: "level", preferredHorizontalDir: "preferredHorizontalDir", preferredVerticalDir: "preferredVerticalDir", expanded: "expanded", autofocusItem: "autofocusItem", anchorElement: "anchorElement" }, host: { listeners: { "window:focusout": "checkActiveElement($event)" }, properties: { "class.expanded": "this.expanded", "attr.role": "this.roleAttr", "attr.tabindex": "this.tabindexAttr", "style.z-index": "this.zIndex" } }, viewQueries: [{ propertyName: "menuItemContainer", first: true, predicate: ["menuItemContainer"], descendants: true }, { propertyName: "children", predicate: RdtMenuOverlayComponent, descendants: true }, { propertyName: "focusableElements", predicate: ["focusableItem"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<ul class=\"menu-item-container\" role=\"presentation\" #menuItemContainer>\r\n <li\r\n *ngFor=\"let item of item.items; let i = index\"\r\n role=\"presentation\"\r\n class=\"menu-item\"\r\n (rdtKeyListener)=\"onKeyDown(i, $event)\"\r\n (pointerenter)=\"onItemPointerEnter(item)\"\r\n rdtAnyRouteActive=\"menu-item-route-active\"\r\n [watchedRoutes]=\"getChildRoutes(item)\"\r\n #anchorEl\r\n >\r\n <ng-container *ngIf=\"!item.routerLink && !item.externalLink\">\r\n <button\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [attr.aria-haspopup]=\"item.items ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item === expandedChild?.item\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n <span *ngIf=\"item.shortcut\" class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.items\"\r\n name=\"chevron_right\"\r\n class=\"menu-item-icon\"\r\n />\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n -->\r\n <span\r\n class=\"menu-item-icon rdt-menu-icon-right\"\r\n *ngIf=\"item.items\"\r\n ></span>\r\n </div>\r\n </button>\r\n </ng-container>\r\n\r\n <ng-template #linkBody let-item>\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n <span *ngIf=\"item.shortcut\" class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n --></div>\r\n </ng-template>\r\n\r\n <ng-container *ngIf=\"item.routerLink\">\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [routerLink]=\"item.routerLink\"\r\n [queryParams]=\"item.queryParams\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"item.externalLink\">\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [href]=\"item.externalLink\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n </ng-container>\r\n\r\n <!-- Child menus exist only if this menu is expanded. -->\r\n <!-- Only one invisible level is always attached to DOM, the rest does not exist. -->\r\n <rdt-menu-overlay\r\n *ngIf=\"item.items && expanded\"\r\n [item]=\"$any(item)\"\r\n [expanded]=\"item === expandedChild?.item\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"horizontalDir?.dir!\"\r\n [preferredVerticalDir]=\"verticalDir?.dir!\"\r\n [level]=\"level + 1\"\r\n [anchorElement]=\"anchorEl\"\r\n />\r\n </li>\r\n</ul>\r\n", styles: [":host{visibility:hidden;position:fixed;min-width:var(--rdt-menu-min-width);box-shadow:var(--rdt-menu-box-shadow);border-radius:var(--rdt-menu-border-radius);overflow-x:hidden;overflow-y:auto;max-height:calc(100vh - var(--rdt-menu-margin-top, 0px) - var(--rdt-menu-margin-bottom, 0px))}:host.expanded{visibility:visible}ul.menu-item-container{list-style-type:none;padding:var(--rdt-menu-padding-horizontal-padding) 0;border-radius:var(--rdt-menu-border-radius);background-color:var(--rdt-menu-background);margin-top:0;margin-bottom:0;margin-block-start:0;margin-block-end:0}.menu-item-content{cursor:pointer;display:flex;align-items:center;width:100%;padding:var(--rdt-menu-item-padding);background-color:var(--rdt-menu-item-background);color:var(--rdt-menu-item-text-color);font-size:var(--rdt-menu-item-font-size);font-weight:var(--rdt-menu-item-font-weight);border:var(--rdt-menu-item-border);outline:var(--rdt-menu-item-outline)}.menu-item{display:flex;position:relative;box-sizing:border-box}.menu-item.menu-item-route-active>.menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-route-active-background);--rdt-menu-item-text-color: var(--rdt-menu-item-route-active-text-color);--rdt-menu-item-border: var(--rdt-menu-item-route-active-border);--rdt-menu-item-outline: var(--rdt-menu-item-route-active-outline)}.menu-item .menu-item-content:hover{--rdt-menu-item-background: var(--rdt-menu-item-hover-background);--rdt-menu-item-text-color: var(--rdt-menu-item-hover-text-color);--rdt-menu-item-border: var(--rdt-menu-item-hover-border);--rdt-menu-item-outline: var(--rdt-menu-item-hover-outline)}.menu-item [aria-expanded=true].menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-expanded-background);--rdt-menu-item-text-color: var(--rdt-menu-item-expanded-text-color);--rdt-menu-item-border: var(--rdt-menu-item-expanded-border);--rdt-menu-item-outline: var(--rdt-menu-item-expanded-outline)}.menu-item .menu-item-content.focus-visible:focus,.menu-item .menu-item-content:focus-visible{--rdt-menu-item-background: var(--rdt-menu-item-focus-background);--rdt-menu-item-text-color: var(--rdt-menu-item-focus-text-color);--rdt-menu-item-border: var(--rdt-menu-item-focus-border);--rdt-menu-item-outline: var(--rdt-menu-item-focus-outline)}.menu-item-icon.rdt-menu-icon-right{width:0;height:0;border-top:var(--rdt-menu-default-icon-size) solid transparent;border-bottom:var(--rdt-menu-default-icon-size) solid transparent;border-left:var(--rdt-menu-default-icon-size) solid var(--rdt-menu-item-text-color)}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i3.RdtAnyRouteActiveDirective, selector: "[rdtAnyRouteActive]", inputs: ["rdtAnyRouteActive", "watchedRoutes", "anyRouteActiveOptions", "ariaCurrentWhenActive"] }, { kind: "directive", type: i4.RdtKeyListenerDirective, selector: "[rdtKeyListener]", outputs: ["rdtKeyListener"] }, { kind: "component", type: RdtMenuOverlayComponent, selector: "rdt-menu-overlay", inputs: ["item", "level", "preferredHorizontalDir", "preferredVerticalDir", "expanded", "autofocusItem", "anchorElement"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
554
- }
555
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuOverlayComponent, decorators: [{
556
- type: Component,
557
- args: [{ selector: 'rdt-menu-overlay', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ul class=\"menu-item-container\" role=\"presentation\" #menuItemContainer>\r\n <li\r\n *ngFor=\"let item of item.items; let i = index\"\r\n role=\"presentation\"\r\n class=\"menu-item\"\r\n (rdtKeyListener)=\"onKeyDown(i, $event)\"\r\n (pointerenter)=\"onItemPointerEnter(item)\"\r\n rdtAnyRouteActive=\"menu-item-route-active\"\r\n [watchedRoutes]=\"getChildRoutes(item)\"\r\n #anchorEl\r\n >\r\n <ng-container *ngIf=\"!item.routerLink && !item.externalLink\">\r\n <button\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [attr.aria-haspopup]=\"item.items ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item === expandedChild?.item\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n <span *ngIf=\"item.shortcut\" class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.items\"\r\n name=\"chevron_right\"\r\n class=\"menu-item-icon\"\r\n />\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n -->\r\n <span\r\n class=\"menu-item-icon rdt-menu-icon-right\"\r\n *ngIf=\"item.items\"\r\n ></span>\r\n </div>\r\n </button>\r\n </ng-container>\r\n\r\n <ng-template #linkBody let-item>\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n <span *ngIf=\"item.shortcut\" class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n --></div>\r\n </ng-template>\r\n\r\n <ng-container *ngIf=\"item.routerLink\">\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [routerLink]=\"item.routerLink\"\r\n [queryParams]=\"item.queryParams\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"item.externalLink\">\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [href]=\"item.externalLink\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n </ng-container>\r\n\r\n <!-- Child menus exist only if this menu is expanded. -->\r\n <!-- Only one invisible level is always attached to DOM, the rest does not exist. -->\r\n <rdt-menu-overlay\r\n *ngIf=\"item.items && expanded\"\r\n [item]=\"$any(item)\"\r\n [expanded]=\"item === expandedChild?.item\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"horizontalDir?.dir!\"\r\n [preferredVerticalDir]=\"verticalDir?.dir!\"\r\n [level]=\"level + 1\"\r\n [anchorElement]=\"anchorEl\"\r\n />\r\n </li>\r\n</ul>\r\n", styles: [":host{visibility:hidden;position:fixed;min-width:var(--rdt-menu-min-width);box-shadow:var(--rdt-menu-box-shadow);border-radius:var(--rdt-menu-border-radius);overflow-x:hidden;overflow-y:auto;max-height:calc(100vh - var(--rdt-menu-margin-top, 0px) - var(--rdt-menu-margin-bottom, 0px))}:host.expanded{visibility:visible}ul.menu-item-container{list-style-type:none;padding:var(--rdt-menu-padding-horizontal-padding) 0;border-radius:var(--rdt-menu-border-radius);background-color:var(--rdt-menu-background);margin-top:0;margin-bottom:0;margin-block-start:0;margin-block-end:0}.menu-item-content{cursor:pointer;display:flex;align-items:center;width:100%;padding:var(--rdt-menu-item-padding);background-color:var(--rdt-menu-item-background);color:var(--rdt-menu-item-text-color);font-size:var(--rdt-menu-item-font-size);font-weight:var(--rdt-menu-item-font-weight);border:var(--rdt-menu-item-border);outline:var(--rdt-menu-item-outline)}.menu-item{display:flex;position:relative;box-sizing:border-box}.menu-item.menu-item-route-active>.menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-route-active-background);--rdt-menu-item-text-color: var(--rdt-menu-item-route-active-text-color);--rdt-menu-item-border: var(--rdt-menu-item-route-active-border);--rdt-menu-item-outline: var(--rdt-menu-item-route-active-outline)}.menu-item .menu-item-content:hover{--rdt-menu-item-background: var(--rdt-menu-item-hover-background);--rdt-menu-item-text-color: var(--rdt-menu-item-hover-text-color);--rdt-menu-item-border: var(--rdt-menu-item-hover-border);--rdt-menu-item-outline: var(--rdt-menu-item-hover-outline)}.menu-item [aria-expanded=true].menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-expanded-background);--rdt-menu-item-text-color: var(--rdt-menu-item-expanded-text-color);--rdt-menu-item-border: var(--rdt-menu-item-expanded-border);--rdt-menu-item-outline: var(--rdt-menu-item-expanded-outline)}.menu-item .menu-item-content.focus-visible:focus,.menu-item .menu-item-content:focus-visible{--rdt-menu-item-background: var(--rdt-menu-item-focus-background);--rdt-menu-item-text-color: var(--rdt-menu-item-focus-text-color);--rdt-menu-item-border: var(--rdt-menu-item-focus-border);--rdt-menu-item-outline: var(--rdt-menu-item-focus-outline)}.menu-item-icon.rdt-menu-icon-right{width:0;height:0;border-top:var(--rdt-menu-default-icon-size) solid transparent;border-bottom:var(--rdt-menu-default-icon-size) solid transparent;border-left:var(--rdt-menu-default-icon-size) solid var(--rdt-menu-item-text-color)}\n"] }]
558
- }], propDecorators: { children: [{
559
- type: ViewChildren,
560
- args: [RdtMenuOverlayComponent]
561
- }], focusableElements: [{
562
- type: ViewChildren,
563
- args: ['focusableItem']
564
- }], menuItemContainer: [{
565
- type: ViewChild,
566
- args: ['menuItemContainer']
567
- }], item: [{
568
- type: Input
569
- }], level: [{
570
- type: Input
571
- }], preferredHorizontalDir: [{
572
- type: Input
573
- }], preferredVerticalDir: [{
574
- type: Input
575
- }], expanded: [{
576
- type: HostBinding,
577
- args: ['class.expanded']
578
- }, {
579
- type: Input
580
- }], autofocusItem: [{
581
- type: Input
582
- }], anchorElement: [{
583
- type: Input
584
- }], roleAttr: [{
585
- type: HostBinding,
586
- args: ['attr.role']
587
- }], tabindexAttr: [{
588
- type: HostBinding,
589
- args: ['attr.tabindex']
590
- }], zIndex: [{
591
- type: HostBinding,
592
- args: ['style.z-index']
593
- }], checkActiveElement: [{
594
- type: HostListener,
595
- args: ['window:focusout', ['$event']]
596
- }] } });
597
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmR0LW1lbnUtb3ZlcmxheS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9AbmdyZHQvbWVudS9zcmMvbGliL21lbnUtb3ZlcmxheS9yZHQtbWVudS1vdmVybGF5LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL0BuZ3JkdC9tZW51L3NyYy9saWIvbWVudS1vdmVybGF5L3JkdC1tZW51LW92ZXJsYXkuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzNDLE9BQU8sRUFFTCx1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsVUFBVSxFQUNWLFdBQVcsRUFDWCxZQUFZLEVBQ1osS0FBSyxFQUdMLFNBQVMsRUFDVCxTQUFTLEVBRVQsU0FBUyxFQUNULFlBQVksRUFDWixNQUFNLEdBQ1AsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDaEUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sRUFDTCxXQUFXLEVBRVgsa0JBQWtCLEdBQ25CLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUNMLE9BQU8sRUFFUCxjQUFjLEVBQ2QsY0FBYyxHQUVmLE1BQU0sY0FBYyxDQUFDO0FBQ3RCLE9BQU8sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDN0MsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDNUUsT0FBTyxFQUNMLDJCQUEyQixFQUMzQix5QkFBeUIsR0FDMUIsTUFBTSxXQUFXLENBQUM7QUFDbkIsT0FBTyxFQUdMLG1CQUFtQixHQUNwQixNQUFNLG1CQUFtQixD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QUFDLG1CQUFtQjtnQkFJOUIsSUFBSTtzQkFESCxLQUFLO2dCQUlOLEtBQUs7c0JBREosS0FBSztnQkFJTixzQkFBc0I7c0JBRHJCLEtBQUs7Z0JBSU4sb0JBQW9CO3NCQURuQixLQUFLO2dCQUtOLFFBQVE7c0JBRlAsV0FBVzt1QkFBQyxnQkFBZ0I7O3NCQUM1QixLQUFLO2dCQUlOLGFBQWE7c0JBRFosS0FBSztnQkFPTixhQUFhO3NCQURaLEtBQUs7Z0JBSUUsUUFBUTtzQkFEZixXQUFXO3VCQUFDLFdBQVc7Z0JBSWhCLFlBQVk7c0JBRG5CLFdBQVc7dUJBQUMsZUFBZTtnQkFJeEIsTUFBTTtzQkFEVCxXQUFXO3VCQUFDLGVBQWU7Z0JBMFpwQixrQkFBa0I7c0JBRHpCLFlBQVk7dUJBQUMsaUJBQWlCLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBET0NVTUVOVCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7XHJcbiAgQWZ0ZXJWaWV3SW5pdCxcclxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcclxuICBDaGFuZ2VEZXRlY3RvclJlZixcclxuICBDb21wb25lbnQsXHJcbiAgRGVzdHJveVJlZixcclxuICBFbGVtZW50UmVmLFxyXG4gIEhvc3RCaW5kaW5nLFxyXG4gIEhvc3RMaXN0ZW5lcixcclxuICBJbnB1dCxcclxuICBPbkNoYW5nZXMsXHJcbiAgT25Jbml0LFxyXG4gIFF1ZXJ5TGlzdCxcclxuICBSZW5kZXJlcjIsXHJcbiAgU2ltcGxlQ2hhbmdlcyxcclxuICBWaWV3Q2hpbGQsXHJcbiAgVmlld0NoaWxkcmVuLFxyXG4gIGluamVjdCxcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xyXG5pbXBvcnQgeyBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xyXG5pbXBvcnQge1xyXG4gIFJkdFNob3J0Y3V0LFxyXG4gIFJkdFNob3J0Y3V0RXZlbnQsXHJcbiAgUmR0U2hvcnRjdXRTZXJ2aWNlLFxyXG59IGZyb20gJ0BuZ3JkdC9zaG9ydGN1dHMnO1xyXG5pbXBvcnQge1xyXG4gIEtCX0NPREUsXHJcbiAgUmR0SG9yaXpvbnRhbERpcmVjdGlvbixcclxuICBSZHRPYmplY3RVdGlscyxcclxuICBSZHRTdHJpbmdVdGlscyxcclxuICBSZHRWZXJ0aWNhbERpcmVjdGlvbixcclxufSBmcm9tICdAbmdyZHQvdXRpbHMnO1xyXG5pbXBvcnQgeyBkZWxheSwgZmlyc3QsIG1hcCwgb2YgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgUmR0TWVudUJhc2VDb21wb25lbnQgfSBmcm9tICcuLi9tZW51LWJhc2UvcmR0LW1lbnUtYmFzZS5jb21wb25lbnQnO1xyXG5pbXBvcnQge1xyXG4gIERFRkFVTFRfTUVOVV9IT1JJWk9OVEFMX0RJUixcclxuICBERUZBVUxUX01FTlVfVkVSVElDQUxfRElSLFxyXG59IGZyb20gJy4uL21vZGVscyc7XHJcbmltcG9ydCB7XHJcbiAgUGFyc2VkUmR0TWVudUl0ZW0sXHJcbiAgUGFyc2VkUmR0TWVudUl0ZW1XaXRoQ2hpbGRyZW4sXHJcbiAgUmR0TWVudUV4cGFuZFNvdXJjZSxcclxufSBmcm9tICcuLi9wcml2YXRlLW1vZGVscyc7XHJcbmltcG9ydCB7XHJcbiAgRk9DVVNfVklTSUJMRSxcclxuICBIb3JEaXJXaXRoT2Zmc2V0LFxyXG4gIFZlcnREaXJXaXRoT2Zmc2V0LFxyXG4gIGFyZUhvckRpcnNFcXVhbCxcclxuICBhcmVWZXJ0RGlyc0VxdWFsLFxyXG4gIGZpbmROZXh0SXRlbVdpdGhQcmVmaXgsXHJcbiAgbWVudUl0ZW1IYXNDaGlsZHJlbixcclxuICBtZW51SXRlbUhhc1JvdXRlLFxyXG59IGZyb20gJy4uL3V0aWxzJztcclxuXHJcbi8vIFRPRE86IFNwbGl0IHBvc2l0aW9uaW5nIGFuZCBzaG9ydGN1dC9mb2N1cyBtYW5hZ2VtZW50IGluIHNlcGFyYXRlIGNsYXNzZXNcclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdyZHQtbWVudS1vdmVybGF5JyxcclxuICB0ZW1wbGF0ZVVybDogJy4vcmR0LW1lbnUtb3ZlcmxheS5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmxzOiBbJy4vcmR0LW1lbnUtb3ZlcmxheS5jb21wb25lbnQuc2NzcyddLFxyXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgUmR0TWVudU92ZXJsYXlDb21wb25lbnRcclxuICBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBBZnRlclZpZXdJbml0XHJcbntcclxuICByZWFkb25seSBlbFJlZjogRWxlbWVudFJlZjxIVE1MRWxlbWVudD4gPSBpbmplY3QoRWxlbWVudFJlZjxIVE1MRWxlbWVudD4pO1xyXG4gIHJlYWRvbmx5IGRlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XHJcblxyXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVuZGVyZXIgPSBpbmplY3QoUmVuZGVyZXIyKTtcclxuICBwcml2YXRlIHJlYWRvbmx5IHRvcExldmVsTWVudSA9IGluamVjdChSZHRNZW51QmFzZUNvbXBvbmVudCk7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBwYXJlbnRNZW51ID0gaW5qZWN0KFJkdE1lbnVPdmVybGF5Q29tcG9uZW50LCB7XHJcbiAgICBvcHRpb25hbDogdHJ1ZSxcclxuICAgIHNraXBTZWxmOiB0cnVlLFxyXG4gIH0pO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgY2QgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgcm91dGVyID0gaW5qZWN0KFJvdXRlcik7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBkb2N1bWVudCA9IGluamVjdChET0NVTUVOVCk7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBzaG9ydGN1dFNlcnZpY2UgPSBpbmplY3QoUmR0U2hvcnRjdXRTZXJ2aWNlKTtcclxuXHJcbiAgQFZpZXdDaGlsZHJlbihSZHRNZW51T3ZlcmxheUNvbXBvbmVudClcclxuICByZWFkb25seSBjaGlsZHJlbiE6IFF1ZXJ5TGlzdDxSZHRNZW51T3ZlcmxheUNvbXBvbmVudD47XHJcblxyXG4gIEBWaWV3Q2hpbGRyZW4oJ2ZvY3VzYWJsZUl0ZW0nKVxyXG4gIHByaXZhdGUgZm9jdXNhYmxlRWxlbWVudHMhOiBRdWVyeUxpc3Q8RWxlbWVudFJlZjxIVE1MTElFbGVtZW50Pj47XHJcblxyXG4gIEBWaWV3Q2hpbGQoJ21lbnVJdGVtQ29udGFpbmVyJylcclxuICBwcml2YXRlIG1lbnVJdGVtQ29udGFpbmVyITogRWxlbWVudFJlZjxIVE1MVUxpc3RFbGVtZW50PjtcclxuXHJcbiAgQElucHV0KClcclxuICBpdGVtITogUGFyc2VkUmR0TWVudUl0ZW1XaXRoQ2hpbGRyZW47XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgbGV2ZWwhOiBudW1iZXI7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgcHJlZmVycmVkSG9yaXpvbnRhbERpcjogUmR0SG9yaXpvbnRhbERpcmVjdGlvbiA9IERFRkFVTFRfTUVOVV9IT1JJWk9OVEFMX0RJUjtcclxuXHJcbiAgQElucHV0KClcclxuICBwcmVmZXJyZWRWZXJ0aWNhbERpcjogUmR0VmVydGljYWxEaXJlY3Rpb24gPSBERUZBVUxUX01FTlVfVkVSVElDQUxfRElSO1xyXG5cclxuICBASG9zdEJpbmRpbmcoJ2NsYXNzLmV4cGFuZGVkJylcclxuICBASW5wdXQoKVxyXG4gIGV4cGFuZGVkID0gZmFsc2U7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgYXV0b2ZvY3VzSXRlbTogJ2ZpcnN0JyB8ICdsYXN0JyB8IG51bGwgPSBudWxsO1xyXG5cclxuICAvLyBFbGVtZW50IHVzZWQgdG8gcmVsYXRpdmVseSBwb3NpdGlvbiBtZW51LFxyXG4gIC8vIHR5cGljYWxseSBwYXJlbnQgZWxlbWVudC5cclxuICAvLyBJZiBub3Qgc3BlY2lmaWVkLCBwYXJlbnQgZWxlbWVudCBpcyB1c2VkLlxyXG4gIEBJbnB1dCgpXHJcbiAgYW5jaG9yRWxlbWVudD86IEhUTUxFbGVtZW50O1xyXG5cclxuICBASG9zdEJpbmRpbmcoJ2F0dHIucm9sZScpXHJcbiAgcHJpdmF0ZSByb2xlQXR0ciA9ICdtZW51JztcclxuXHJcbiAgQEhvc3RCaW5kaW5nKCdhdHRyLnRhYmluZGV4JylcclxuICBwcml2YXRlIHRhYmluZGV4QXR0ciA9ICctMSc7XHJcblxyXG4gIEBIb3N0QmluZGluZygnc3R5bGUuei1pbmRleCcpXHJcbiAgZ2V0IHpJbmRleCgpIHtcclxuICAgIHJldHVybiB0aGlzLmxldmVsICsgMTA7XHJcbiAgfVxyXG5cclxuICBnZXQgaXNSb290TGV2ZWwoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5sZXZlbCA9PT0gMDtcclxuICB9XHJcblxyXG4gIC8vIEJvdW5kaW5nIGJveCBvZiB0aGlzIGV4Y2x1ZGluZyBhbnkgZXh0cmEgb2Zmc2V0LlxyXG4gIHByaXZhdGUgX2JveCE6IERPTVJlY3Q7XHJcbiAgZ2V0IGJveCgpIHtcclxuICAgIHJldHVybiB0aGlzLl9ib3g7XHJcbiAgfVxyXG5cclxuICAvLyBCb3VuZGluZyBib3ggb2YgcGFyZW50IGVsZW1lbnQuXHJcbiAgcHJpdmF0ZSBfYW5jaG9yQm94ITogRE9NUmVjdDtcclxuICBwcml2YXRlIF9jb250YWluZXJQYWRkaW5nID0geyB0b3A6IDAsIGJvdHRvbTogMCB9O1xyXG5cclxuICAvLyBSZWNhbGN1bGF0ZSBjaGlsZCBjb21wb25lbnRzIG9ubHkgYWZ0ZXIgdGhleSBhcmUgaW5pdGlhbGl6ZWQuXHJcbiAgcHJpdmF0ZSBfdmlld1dhc0luaXQgPSBmYWxzZTtcclxuXHJcbiAgLy8gQ3VycmVudGx5IGFwcGxpZWQgdmVydGljYWwgYW5kIGhvcml6b250YWwgZGlyZWN0aW9ucy5cclxuICBwcm90ZWN0ZWQgdmVydGljYWxEaXI6IFZlcnREaXJXaXRoT2Zmc2V0IHwgbnVsbCA9IG51bGw7XHJcbiAgcHJvdGVjdGVkIGhvcml6b250YWxEaXI6IEhvckRpcldpdGhPZmZzZXQgfCBudWxsID0gbnVsbDtcclxuXHJcbiAgcHJvdGVjdGVkIGV4cGFuZGVkQ2hpbGQ6IHtcclxuICAgIGl0ZW06IFBhcnNlZFJkdE1lbnVJdGVtO1xyXG4gICAgc3JjOiBSZHRNZW51RXhwYW5kU291cmNlO1xyXG4gIH0gfCBudWxsID0gbnVsbDtcclxuICBwcm90ZWN0ZWQgYXV0b2ZvY3VzU3VibWVudUl0ZW06ICdmaXJzdCcgfCAnbGFzdCcgfCBudWxsID0gbnVsbDtcclxuXHJcbiAgcmVhZG9ubHkga2V5QWN0aW9ucyA9IHtcclxuICAgIFtLQl9DT0RFLkFSUk9XLlVQXTogKGluZGV4OiBudW1iZXIpID0+IHRoaXMuZm9jdXNQcmV2SXRlbShpbmRleCksXHJcbiAgICBbS0JfQ09ERS5BUlJPVy5ET1dOXTogKGluZGV4OiBudW1iZXIpID0+IHRoaXMuZm9jdXNOZXh0SXRlbShpbmRleCksXHJcbiAgICBbS0JfQ09ERS5BUlJPVy5SSUdIVF06IChpbmRleDogbnVtYmVyKSA9PlxyXG4gICAgICB0aGlzLm9wZW5TdWJtZW51KGluZGV4LCAnZmlyc3QnLCBSZHRNZW51RXhwYW5kU291cmNlLlNob3J0Y3V0KSxcclxuICAgIFtLQl9DT0RFLkFSUk9XLkxFRlRdOiAoKSA9PiB0aGlzLmNsb3NlU2VsZigpLFxyXG4gICAgW0tCX0NPREUuSE9NRV06ICgpID0+IHRoaXMuZm9jdXNJdGVtKDApLFxyXG4gICAgW0tCX0NPREUuRU5EXTogKCkgPT4gdGhpcy5mb2N1c0l0ZW0odGhpcy5pdGVtLml0ZW1zLmxlbmd0aCAtIDEpLFxyXG4gICAgW0tCX0NPREUuRVNDQVBFXTogKCkgPT4gdGhpcy5jbG9zZVNlbGYoKSxcclxuICAgIFtLQl9DT0RFLkVOVEVSXTogKGluZGV4OiBudW1iZXIpID0+IHRoaXMuaW52b2tlSXRlbUNsaWNrQnlJbmRleChpbmRleCksXHJcbiAgICBbS0JfQ09ERS5TUEFDRUJBUl06IChpbmRleDogbnVtYmVyKSA9PiB0aGlzLmludm9rZUl0ZW1DbGlja0J5SW5kZXgoaW5kZXgpLFxyXG4gIH07XHJcbiAgZ2V0IHNlbGZFeHBhbmRTcmMoKSB7XHJcbiAgICBpZiAodGhpcy5leHBhbmRlZCkge1xyXG4gICAgICBpZiAodGhpcy5wYXJlbnRNZW51KSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMucGFyZW50TWVudS5leHBhbmRlZENoaWxkPy5zcmM7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMudG9wTGV2ZWxNZW51LmV4cGFuZGVkQ2hpbGQ/LnNyYztcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuICB9XHJcblxyXG4gIG5nT25Jbml0KCkge1xyXG4gICAgdGhpcy5zZXRDbGFzc2VzKCk7XHJcbiAgICB0aGlzLmxpc3RlblRhYktleVByZXNzKCk7XHJcbiAgfVxyXG5cclxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XHJcbiAgICBjb25zdCByZWNhbGNUcmlnZ2VycyA9IFtcclxuICAgICAgJ3ByZWZlcnJlZEhvcml6b250YWxEaXInLFxyXG4gICAgICAncHJlZmVycmVkVmVydGljYWxEaXInLFxyXG4gICAgICAnZXhwYW5kZWQnLFxyXG4gICAgXTtcclxuICAgIGlmIChyZWNhbGNUcmlnZ2Vycy5zb21lKChrZXkpID0+IGtleSBpbiBjaGFuZ2VzKSAmJiB0aGlzLl92aWV3V2FzSW5pdCkge1xyXG4gICAgICB0aGlzLnJlY2FsY3VsYXRlUG9zaXRpb24oXHJcbiAgICAgICAgdGhpcy5wcmVmZXJyZWRIb3Jpem9udGFsRGlyLFxyXG4gICAgICAgIHRoaXMucHJlZmVycmVkVmVydGljYWxEaXJcclxuICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoIXRoaXMuZXhwYW5kZWQpIHtcclxuICAgICAgdGhpcy5leHBhbmRlZENoaWxkID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoJ2V4cGFuZGVkJyBpbiBjaGFuZ2VzICYmIHRoaXMuZXhwYW5kZWQpIHtcclxuICAgICAgLy8gV2FpdCBmb3IgQW5ndWxhciB0byBzZXQgLmV4cGFuZGVkIGNsYXNzLFxyXG4gICAgICAvLyBiZWNhdXNlIGludmlzaWJsZSBlbGVtZW50cyBjYW5ub3QgYmUgZm9jdXNlZC5cclxuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgc3dpdGNoICh0aGlzLmF1dG9mb2N1c0l0ZW0pIHtcclxuICAgICAgICAgIGNhc2UgbnVsbDpcclxuICAgICAgICAgICAgdGhpcy5mb2N1c0l0ZW0oMCwgZmFsc2UpO1xyXG4gICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgIGNhc2UgJ2ZpcnN0JzpcclxuICAgICAgICAgICAgdGhpcy5mb2N1c0l0ZW0oMCwgdHJ1ZSk7XHJcbiAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgY2FzZSAnbGFzdCc6XHJcbiAgICAgICAgICAgIHRoaXMuZm9jdXNJdGVtKHRoaXMuaXRlbS5pdGVtcy5sZW5ndGggLSAxLCB0cnVlKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCkge1xyXG4gICAgdGhpcy5tZWFzdXJlQ29udGFpbmVyUGFkZGluZygpO1xyXG4gICAgdGhpcy5yZWNhbGN1bGF0ZVBvc2l0aW9uKFxyXG4gICAgICB0aGlzLnByZWZlcnJlZEhvcml6b250YWxEaXIsXHJcbiAgICAgIHRoaXMucHJlZmVycmVkVmVydGljYWxEaXJcclxuICAgICk7XHJcbiAgICB0aGlzLl92aWV3V2FzSW5pdCA9IHRydWU7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldE1pbk9mZnNldExlZnQoKSB7XHJcbiAgICByZXR1cm4gdGhpcy50b3BMZXZlbE1lbnUuYm9keU1hcmdpbi5sZWZ0O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZXRNYXhPZmZzZXRMZWZ0KCkge1xyXG4gICAgcmV0dXJuIChcclxuICAgICAgdGhpcy50b3BMZXZlbE1lbnUuY2xpZW50U2l6ZS53aWR0aCAtXHJcbiAgICAgIHRoaXMuX2JveC53aWR0aCAtXHJcbiAgICAgIHRoaXMudG9wTGV2ZWxNZW51LmJvZHlNYXJnaW4ucmlnaHRcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldE1pbk9mZnNldFRvcCgpIHtcclxuICAgIHJldHVybiB0aGlzLnRvcExldmVsTWVudS5ib2R5TWFyZ2luLnRvcDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0TWF4T2Zmc2V0VG9wKCkge1xyXG4gICAgcmV0dXJuIChcclxuICAgICAgdGhpcy50b3BMZXZlbE1lbnUuY2xpZW50U2l6ZS5oZWlnaHQgLVxyXG4gICAgICB0aGlzLl9ib3guaGVpZ2h0IC1cclxuICAgICAgdGhpcy50b3BMZXZlbE1lbnUuYm9keU1hcmdpbi5ib3R0b21cclxuICAgICk7XHJcbiAgfVxyXG5cclxuICByZWNhbGN1bGF0ZVBvc2l0aW9uKFxyXG4gICAgcHJlZmVycmVkSG9yaXpvbnRhbERpcjogUmR0SG9yaXpvbnRhbERpcmVjdGlvbixcclxuICAgIHByZWZlcnJlZFZlcnRpY2FsRGlyOiBSZHRWZXJ0aWNhbERpcmVjdGlvblxyXG4gICkge1xyXG4gICAgLy8gTWFrZSBtZW51IGludmlzaWJsZSBzbyB0aGUgbWVudSBkb2VzIG5vdCBtb3ZlIGFyb3VuZCBpbiBjYXNlIG9mIHNsb3cgY29tcHV0ZXIuXHJcbiAgICB0aGlzLm1lYXN1cmVCb3VuZGluZ1JlY3QoKTtcclxuXHJcbiAgICBpZiAoIXRoaXMuX2JveCB8fCAhdGhpcy5fYW5jaG9yQm94KSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBuZXdIb3JEaXIgPSB0aGlzLmdldFJlYWxIb3Jpem9udGFsRGlyKHByZWZlcnJlZEhvcml6b250YWxEaXIpO1xyXG4gICAgY29uc3QgbmV3VmVydERpciA9IHRoaXMuZ2V0UmVhbFZlcnRpY2FsRGlyKHByZWZlcnJlZFZlcnRpY2FsRGlyKTtcclxuXHJcbiAgICAvLyBIb3Jpem9udGFsIGRpcmVjdGlvblxyXG4gICAgaWYgKG5ld0hvckRpci5kaXIgPT09ICdyaWdodCcpIHtcclxuICAgICAgbmV3SG9yRGlyLmxlZnQgKz0gdGhpcy5fYW5jaG9yQm94LmxlZnQ7XHJcbiAgICAgIGlmICghdGhpcy5pc1Jvb3RMZXZlbCkge1xyXG4gICAgICAgIG5ld0hvckRpci5sZWZ0ICs9IHRoaXMuX2FuY2hvckJveC53aWR0aDtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIGlmIChuZXdIb3JEaXIuZGlyID09PSAnbGVmdCcpIHtcclxuICAgICAgbmV3SG9yRGlyLmxlZnQgKz0gdGhpcy5fYW5jaG9yQm94LmxlZnQgLSB0aGlzLl9ib3gud2lkdGg7XHJcblxyXG4gICAgICBpZiAodGhpcy5pc1Jvb3RMZXZlbCkge1xyXG4gICAgICAgIG5ld0hvckRpci5sZWZ0ICs9IHRoaXMuX2FuY2hvckJveC53aWR0aDtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIFJlc3RyaWN0aW9ucyBmcm9tIGxlZnQgbWVudSBhbmQgcmlnaHQgbWVudVxyXG4gICAgbmV3SG9yRGlyLmxlZnQgPSBNYXRoLm1pbihcclxuICAgICAgTWF0aC5tYXgodGhpcy5nZXRNaW5PZmZzZXRMZWZ0KCksIG5ld0hvckRpci5sZWZ0KSxcclxuICAgICAgdGhpcy5nZXRNYXhPZmZzZXRMZWZ0KClcclxuICAgICk7XHJcblxyXG4gICAgLy8gVmVydGljYWwgZGlyZWN0aW9uXHJcbiAgICBpZiAobmV3VmVydERpci5kaXIgPT09ICdkb3duJykge1xyXG4gICAgICBuZXdWZXJ0RGlyLnRvcCA9IHRoaXMuX2FuY2hvckJveC50b3A7XHJcbiAgICAgIGlmICh0aGlzLmlzUm9vdExldmVsKSB7XHJcbiAgICAgICAgbmV3VmVydERpci50b3AgKz0gdGhpcy5fYW5jaG9yQm94LmhlaWdodDtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBuZXdWZXJ0RGlyLnRvcCAtPSB0aGlzLl9jb250YWluZXJQYWRkaW5nLnRvcDtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIGlmIChuZXdWZXJ0RGlyLmRpciA9PT0gJ3VwJykge1xyXG4gICAgICBuZXdWZXJ0RGlyLnRvcCA9IHRoaXMuX2FuY2hvckJveC50b3AgLSB0aGlzLl9ib3guaGVpZ2h0O1xyXG4gICAgICBpZiAoIXRoaXMuaXNSb290TGV2ZWwpIHtcclxuICAgICAgICBuZXdWZXJ0RGlyLnRvcCArPSB0aGlzLl9hbmNob3JCb3guaGVpZ2h0ICsgdGhpcy5fY29udGFpbmVyUGFkZGluZy50b3A7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBSZXN0cmljdGlvbnMgZnJvbSBoZWFkZXIgYW5kIGZvb3RlclxyXG4gICAgbmV3VmVydERpci50b3AgPSBNYXRoLm1pbihcclxuICAgICAgTWF0aC5tYXgodGhpcy5nZXRNaW5PZmZzZXRUb3AoKSwgbmV3VmVydERpci50b3ApLFxyXG4gICAgICB0aGlzLmdldE1heE9mZnNldFRvcCgpXHJcbiAgICApO1xyXG5cclxuICAgIGlmIChcclxuICAgICAgIWFyZUhvckRpcnNFcXVhbCh0aGlzLmhvcml6b250YWxEaXIsIG5ld0hvckRpcikgfHxcclxuICAgICAgIWFyZVZlcnREaXJzRXF1YWwodGhpcy52ZXJ0aWNhbERpciwgbmV3VmVydERpcilcclxuICAgICkge1xyXG4gICAgICB0aGlzLmhvcml6b250YWxEaXIgPSBuZXdIb3JEaXI7XHJcbiAgICAgIHRoaXMudmVydGljYWxEaXIgPSBuZXdWZXJ0RGlyO1xyXG4gICAgICB0aGlzLnNldENsYXNzZXMoKTtcclxuICAgICAgdGhpcy5tZWFzdXJlQm91bmRpbmdSZWN0KCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5yZWNhbGN1bGF0ZUNoaWxkcmVuKCk7XHJcbiAgfVxyXG5cclxuICBvbkl0ZW1Qb2ludGVyRW50ZXIoaXRlbTogUGFyc2VkUmR0TWVudUl0ZW0pIHtcclxuICAgIGlmIChcclxuICAgICAgdGhpcy50b3BMZXZlbE1lbnUub3Blbk9uSG92ZXIgJiZcclxuICAgICAgdGhpcy5leHBhbmRlZENoaWxkPy5zcmMgIT09IFJkdE1lbnVFeHBhbmRTb3VyY2UuQ2xpY2tcclxuICAgICkge1xyXG4gICAgICB0aGlzLmF1dG9mb2N1c1N1Ym1lbnVJdGVtID0gbnVsbDtcclxuICAgICAgaWYgKG1lbnVJdGVtSGFzQ2hpbGRyZW4oaXRlbSkpIHtcclxuICAgICAgICB0aGlzLmV4cGFuZGVkQ2hpbGQgPSB7IGl0ZW0sIHNyYzogUmR0TWVudUV4cGFuZFNvdXJjZS5Ib3ZlciB9O1xyXG4gICAgICAgIHRoaXMuZXhwYW5kZWQgPSB0cnVlO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vY29uc29sZS5sb2coJ2V4cGFuZGVkIGNoaWxkJywgdGhpcy5leHBhbmRlZENoaWxkKTtcclxuICAgICAgICB0aGlzLmV4cGFuZGVkQ2hpbGQgPSBudWxsO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBvbkl0ZW1DbGljayhpdGVtOiBQYXJzZWRSZHRNZW51SXRlbSkge1xyXG4gICAgY29uc3QgaGFzQ2hpbGRyZW4gPSBtZW51SXRlbUhhc0NoaWxkcmVuKGl0ZW0pO1xyXG4gICAgaWYgKFxyXG4gICAgICAoaGFzQ2hpbGRyZW4gJiYgdGhpcy5leHBhbmRlZENoaWxkPy5pdGVtICE9PSBpdGVtKSB8fFxyXG4gICAgICAodGhpcy50b3BMZXZlbE1lbnUub3Blbk9uSG92ZXIgJiZcclxuICAgICAgICB0aGlzLmV4cGFuZGVkQ2hpbGQ/LnNyYyA9PT0gUmR0TWVudUV4cGFuZFNvdXJjZS5Ib3ZlcilcclxuICAgICkge1xyXG4gICAgICB0aGlzLmF1dG9mb2N1c1N1Ym1lbnVJdGVtID0gbnVsbDtcclxuICAgICAgdGhpcy5leHBhbmRlZENoaWxkID0geyBpdGVtLCBzcmM6IFJkdE1lbnVFeHBhbmRTb3VyY2UuQ2xpY2sgfTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuZXhwYW5kZWRDaGlsZCA9IG51bGw7XHJcbiAgICB9XHJcbiAgICAvLyBDb3VsZCBhbHNvIGxpc3RlbiB0byByb3V0ZXIgZXZlbnRzLCBidXQgbWlnaHQgYmUgdHJpZ2dlcmVkIGJ5XHJcbiAgICAvLyBjaGlsZCByb3V0ZXIgbmF2aWdhdGlvbi5cclxuICAgIGlmICghaGFzQ2hpbGRyZW4pIHtcclxuICAgICAgdGhpcy50b3BMZXZlbE1lbnUuY2xvc2VTdWJtZW51cygpO1xyXG4gICAgfVxyXG4gICAgaWYgKHR5cGVvZiBpdGVtLmNvbW1hbmQgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgaXRlbS5jb21tYW5kKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBpbnZva2VJdGVtQ2xpY2soaXRlbTogUGFyc2VkUmR0TWVudUl0ZW0pIHtcclxuICAgIGlmIChtZW51SXRlbUhhc1JvdXRlKGl0ZW0pICYmIGl0ZW0ucm91dGVyTGluaykge1xyXG4gICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShpdGVtLnJvdXRlckxpbmspO1xyXG4gICAgfVxyXG4gICAgdGhpcy5vbkl0ZW1DbGljayhpdGVtKTtcclxuICAgIHRoaXMuYXV0b2ZvY3VzU3VibWVudUl0ZW0gPSAnZmlyc3QnO1xyXG4gIH1cclxuXHJcbiAgZ2V0Q2hpbGRSb3V0ZXMoaXRlbTogUGFyc2VkUmR0TWVudUl0ZW0pIHtcclxuICAgIHJldHVybiB0aGlzLnRvcExldmVsTWVudS5nZXRDaGlsZFJvdXRlcyhpdGVtKTtcclxuICB9XHJcblxyXG4gIGNsb3NlU3VibWVudXMoZm9jdXNFeHBhbmRlZCA9IGZhbHNlKSB7XHJcbiAgICBpZiAoZm9jdXNFeHBhbmRlZCAmJiB0aGlzLmV4cGFuZGVkQ2hpbGQpIHtcclxuICAgICAgdGhpcy5mb2N1c0l0ZW0odGhpcy5leHBhbmRlZENoaWxkLml0ZW0pO1xyXG4gICAgfVxyXG4gICAgdGhpcy5leHBhbmRlZENoaWxkID0gbnVsbDtcclxuICAgIHRoaXMuY2QubWFya0ZvckNoZWNrKCk7XHJcbiAgfVxyXG5cclxuICBmb2N1c0l0ZW1SZWN1cnNpdmVseShwYXRoOiBQYXJzZWRSZHRNZW51SXRlbVtdKSB7XHJcbiAgICBjb25zdCBjaGlsZHJlbiA9IFsuLi5wYXRoXTtcclxuICAgIGNvbnN0IHRoaXNJdGVtID0gY2hpbGRyZW4uc2hpZnQoKSE7XHJcblxyXG4gICAgdGhpcy5hdXRvZm9jdXNTdWJtZW51SXRlbSA9IG51bGw7XHJcbiAgICB0aGlzLmF1dG9mb2N1c0l0ZW0gPSBudWxsO1xyXG5cclxuICAgIGlmIChjaGlsZHJlbi5sZW5ndGggPiAwKSB7XHJcbiAgICAgIHRoaXMuZXhwYW5kQW5kR2V0Q2hpbGQodGhpc0l0ZW0sIFJkdE1lbnVFeHBhbmRTb3VyY2UuRm9jdXMpXHJcbiAgICAgICAgLnBpcGUoZGVsYXkoMSkpXHJcbiAgICAgICAgLnN1YnNjcmliZSgob3ZlcmxheSkgPT4ge1xyXG4gICAgICAgICAgb3ZlcmxheS5mb2N1c0l0ZW1SZWN1cnNpdmVseShjaGlsZHJlbik7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBGaXJzdCBmb2N1cyB0aGUgY29ycmVjdCBpdGVtIGJlY2F1c2Ugc3VibWVudSBtaWdodCBoYXZlIGZvY3VzIG9uIGl0LlxyXG4gICAgICAvLyBSZW1vdmluZyBmb2N1c2VkIGVsZW1lbnQgZnJvbSBET00gcmVzdWx0cyBpbiB3aW5kb3c6Zm9jdXNvdXQgZXZlbnRcclxuICAgICAgLy8gYW5kIHRoYXQgY2xvc2VzIGFsbCBtZW51c1xyXG4gICAgICB0aGlzLmZvY3VzSXRlbSh0aGlzSXRlbSk7XHJcbiAgICAgIC8vIE5vdyBjbG9zZSBzdWJtZW51cyBhbmQgdGhlcmVmb3JlIHJlbW92ZSB0aGVtIGZyb20gRE9NXHJcbiAgICAgIHRoaXMuY2xvc2VTdWJtZW51cygpO1xyXG4gICAgICAvLyBXYWl0IHVudGlsIHRoZXkgYXJlIHJlbW92ZWQgYW5kIGZvY3VzIHRoZSBjb3JyZWN0IGl0ZW0gYWdhaW5cclxuICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLmZvY3VzSXRlbSh0aGlzSXRlbSksIDEpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBleHBhbmRBbmRHZXRDaGlsZChpdGVtOiBQYXJzZWRSZHRNZW51SXRlbSwgc3JjOiBSZHRNZW51RXhwYW5kU291cmNlKSB7XHJcbiAgICBpZiAodGhpcy5pdGVtLml0ZW1zLmluZGV4T2YoaXRlbSkgPCAwKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcclxuICAgICAgICAnQXR0ZW1wdGluZyB0byBleHBhbmQgaXRlbSB0aGF0IGlzIG5vdCBjaGlsZCBpdGVtIG9mIHRoaXMuaXRlbSdcclxuICAgICAgKTtcclxuICAgIH1cclxuICAgIHRoaXMuZXhwYW5kZWRDaGlsZCA9IHsgaXRlbSwgc3JjIH07XHJcbiAgICB0aGlzLmNkLm1hcmtGb3JDaGVjaygpO1xyXG5cclxuICAgIGNvbnN0IGNoaWxkID0gdGhpcy5jaGlsZHJlbi5maW5kKChjaGlsZCkgPT4gY2hpbGQuaXRlbSA9PT0gaXRlbSk7XHJcbiAgICBpZiAoY2hpbGQpIHtcclxuICAgICAgcmV0dXJuIG9mKGNoaWxkKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHJldHVybiB0aGlzLmNoaWxkcmVuLmNoYW5nZXMucGlwZShcclxuICAgICAgICBtYXAoKCkgPT4gdGhpcy5jaGlsZHJlbi5maW5kKChjaGlsZCkgPT4gY2hpbGQuaXRlbSA9PT0gaXRlbSkpLFxyXG4gICAgICAgIGZpcnN0KFJkdE9iamVjdFV0aWxzLm5vdE51bGxHdWFyZClcclxuICAgICAgKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByb3RlY3RlZCBvbktleURvd24oaXRlbUluZGV4OiBudW1iZXIsIGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XHJcbiAgICBjb25zdCBoYXNBY3Rpb24gPSBldmVudC5jb2RlIGluIHRoaXMua2V5QWN0aW9ucztcclxuICAgIGNvbnN0IGlzTGV0dGVyID1cclxuICAgICAgUmR0U3RyaW5nVXRpbHMuaXNBbHBoYWJldENoYXJhY3RlcihldmVudC5rZXkpIHx8XHJcbiAgICAgIFJkdFN0cmluZ1V0aWxzLmlzTnVtZXJpY0NoYXJhY3RlcihldmVudC5rZXkpO1xyXG5cclxuICAgIGlmIChoYXNBY3Rpb24gfHwgaXNMZXR0ZXIpIHtcclxuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgIH1cclxuICAgIGlmIChoYXNBY3Rpb24pIHtcclxuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGhhc0FjdGlvbikge1xyXG4gICAgICB0aGlzLmtleUFjdGlvbnNbZXZlbnQuY29kZV0oaXRlbUluZGV4KTtcclxuICAgIH0gZWxzZSBpZiAoaXNMZXR0ZXIpIHtcclxuICAgICAgY29uc3QgbmV4dCA9IGZpbmROZXh0SXRlbVdpdGhQcmVmaXgoXHJcbiAgICAgICAgdGhpcy5pdGVtLml0ZW1zLFxyXG4gICAgICAgIGl0ZW1JbmRleCxcclxuICAgICAgICBldmVudC5rZXlcclxuICAgICAgKTtcclxuICAgICAgaWYgKG5leHQgIT09IG51bGwpIHtcclxuICAgICAgICB0aGlzLmZvY3VzSXRlbShuZXh0KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBvblRhYktleVByZXNzKGV2ZW50OiBSZHRTaG9ydGN1dEV2ZW50KSB7XHJcbiAgICAvLyBEbyBub3QgcHJldmVudCBkZWZhdWx0IHRvIGNvcnJlY3RseSBzd2l0Y2ggdG8gcHJldmlvdXMgZWxlbWVudFxyXG4gICAgZXZlbnQub3JpZ2luYWxFdmVudC5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgIC8vIFdhaXQgZm9yIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgdG8gc3dpdGNoIHRvIG5ldyBlbGVtZW50XHJcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgaWYgKCF0aGlzLmVsUmVmLm5hdGl2ZUVsZW1lbnQuY29udGFpbnModGhpcy5kb2N1bWVudC5hY3RpdmVFbGVtZW50KSkge1xyXG4gICAgICAgIHRoaXMuY2xvc2VTZWxmKGZhbHNlKTtcclxuICAgICAgfVxyXG4gICAgfSwgMSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGludm9rZUl0ZW1DbGlja0J5SW5kZXgoaXRlbUluZGV4OiBudW1iZXIpIHtcclxuICAgIGNvbnN0IGl0ZW0gPSB0aGlzLml0ZW0uaXRlbXNbaXRlbUluZGV4XTtcclxuICAgIGlmICghaXRlbSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLmludm9rZUl0ZW1DbGljayhpdGVtKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZm9jdXNJdGVtKGl0ZW06IG51bWJlciB8IFBhcnNlZFJkdE1lbnVJdGVtLCB2aXNpYmxlRm9jdXMgPSB0cnVlKSB7XHJcbiAgICBsZXQgaXRlbUluZGV4OiBudW1iZXI7XHJcblxyXG4gICAgaWYgKHR5cGVvZiBpdGVtID09PSAnbnVtYmVyJykge1xyXG4gICAgICBpdGVtSW5kZXggPSBpdGVtO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaXRlbUluZGV4ID0gdGhpcy5pdGVtLml0ZW1zLmluZGV4T2YoaXRlbSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGl0ZW1JbmRleCA+PSAwICYmIGl0ZW1JbmRleCA8IHRoaXMuZm9jdXNhYmxlRWxlbWVudHMubGVuZ3RoKSB7XHJcbiAgICAgIHRoaXMuYmx1ckFsbEZvY3VzYWJsZSgpO1xyXG4gICAgICB0aGlzLmZvY3VzRm9jdXNhYmxlKGl0ZW1JbmRleCwgdmlzaWJsZUZvY3VzKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgYmx1ckFsbEZvY3VzYWJsZSgpIHtcclxuICAgIHRoaXMuZm9jdXNhYmxlRWxlbWVudHMuZm9yRWFjaCgoZWwpID0+XHJcbiAgICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlQ2xhc3MoZWwubmF0aXZlRWxlbWVudCwgRk9DVVNfVklTSUJMRSlcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGZvY3VzRm9jdXNhYmxlKGl0ZW1JbmRleDogbnVtYmVyLCB2aXNpYmxlRm9jdXM6IGJvb2xlYW4pIHtcclxuICAgIGNvbnN0IGVsUmVmID0gdGhpcy5mb2N1c2FibGVFbGVtZW50cy5nZXQoaXRlbUluZGV4KTtcclxuICAgIGlmIChlbFJlZikge1xyXG4gICAgICBpZiAodmlzaWJsZUZvY3VzKSB7XHJcbiAgICAgICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyhlbFJlZi5uYXRpdmVFbGVtZW50LCBGT0NVU19WSVNJQkxFKTtcclxuICAgICAgfVxyXG4gICAgICBlbFJlZi5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGZvY3VzTmV4dEl0ZW0oaXRlbUluZGV4OiBudW1iZXIpIHtcclxuICAgIGNvbnN0IG5leHQgPSAoaXRlbUluZGV4ICsgMSkgJSB0aGlzLml0ZW0uaXRlbXMubGVuZ3RoO1xyXG4gICAgdGhpcy5mb2N1c0l0ZW0obmV4dCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGZvY3VzUHJldkl0ZW0oaXRlbUluZGV4OiBudW1iZXIpIHtcclxuICAgIGNvbnN0IHByZXYgPVxyXG4gICAgICAoaXRlbUluZGV4IC0gMSArIHRoaXMuaXRlbS5pdGVtcy5sZW5ndGgpICUgdGhpcy5pdGVtLml0ZW1zLmxlbmd0aDtcclxuICAgIHRoaXMuZm9jdXNJdGVtKHByZXYpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBvcGVuU3VibWVudShcclxuICAgIGl0ZW1JbmRleDogbnVtYmVyLFxyXG4gICAgdmlzaWJsZUZvY3VzOiAnZmlyc3QnIHwgJ2xhc3QnLFxyXG4gICAgc3JjOiBSZHRNZW51RXhwYW5kU291cmNlXHJcbiAgKSB7XHJcbiAgICBpZiAoXHJcbiAgICAgIGl0ZW1JbmRleCA8IHRoaXMuaXRlbS5pdGVtcy5sZW5ndGggJiZcclxuICAgICAgbWVudUl0ZW1IYXNDaGlsZHJlbih0aGlzLml0ZW0uaXRlbXNbaXRlbUluZGV4XSlcclxuICAgICkge1xyXG4gICAgICB0aGlzLmV4cGFuZGVkQ2hpbGQgPSB7IGl0ZW06IHRoaXMuaXRlbS5pdGVtc1tpdGVtSW5kZXhdLCBzcmMgfTtcclxuICAgICAgdGhpcy5hdXRvZm9jdXNTdWJtZW51SXRlbSA9IHZpc2libGVGb2N1cztcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNsb3NlU2VsZihmb2N1c0V4cGFuZGVkID0gdHJ1ZSkge1xyXG4gICAgaWYgKHRoaXMucGFyZW50TWVudSkge1xyXG4gICAgICB0aGlzLnBhcmVudE1lbnUuY2xvc2VTdWJtZW51cyhmb2N1c0V4cGFuZGVkKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMudG9wTGV2ZWxNZW51LmNsb3NlU3VibWVudXMoZm9jdXNFeHBhbmRlZCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6Zm9jdXNvdXQnLCBbJyRldmVudCddKVxyXG4gIHByaXZhdGUgY2hlY2tBY3RpdmVFbGVtZW50KGV2ZW50OiBGb2N1c0V2ZW50KSB7XHJcbiAgICBpZiAodGhpcy50b3BMZXZlbE1lbnUuY2xvc2VPbkZvY3VzT3V0ICYmICF0aGlzLnRvcExldmVsTWVudS5vcGVuT25Ib3Zlcikge1xyXG4gICAgICBjb25zdCB0aGlzRWwgPSB0aGlzLmVsUmVmLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnJlbGF0ZWRUYXJnZXQ7XHJcbiAgICAgIGlmICghKHRhcmdldCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB8fCAhdGhpc0VsLmNvbnRhaW5zKHRhcmdldCkpIHtcclxuICAgICAgICB0aGlzLmV4cGFuZGVkQ2hpbGQgPSBudWxsO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLyBDYWxjdWxhdGVzIGRpcmVjdGlvbiBvZiB0aGlzIG1lbnUgYW5kIG9mZnNldCBpbiBjYXNlXHJcbiAgLy8gbWVudSB3b24ndCBmaXQgaW4gbGVmdCBub3IgcmlnaHQgb2YgcGFyZW50IG1lbnUuXHJcbiAgcHJpdmF0ZSBnZXRSZWFsSG9yaXpvbnRhbERpcihcclxuICAgIHByZWZlcnJlZEhvcml6b250YWxEaXI6IFJkdEhvcml6b250YWxEaXJlY3Rpb25cclxuICApOiBIb3JEaXJXaXRoT2Zmc2V0IHtcclxuICAgIGxldCBsZWZ0OiBudW1iZXI7XHJcbiAgICBsZXQgcmlnaHQ6IG51bWJlcjtcclxuICAgIC8vIFRoaXMgbWVudSBpcyBkaXJlY3RseSB1bmRlciBtZW51YmFyXHJcbiAgICBpZiAodGhpcy5sZXZlbCA9PT0gMCkge1xyXG4gICAgICBsZWZ0ID0gdGhpcy5fYW5jaG9yQm94LnJpZ2h0IC0gdGhpcy5fYm94LndpZHRoO1xyXG4gICAgICByaWdodCA9XHJcbiAgICAgICAgdGhpcy50b3BMZXZlbE1lbnUuY2xpZW50U2l6ZS53aWR0aCAtXHJcbiAgICAgICAgKHRoaXMuX2FuY2hvckJveC5sZWZ0ICsgdGhpcy5fYm94LndpZHRoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIE1lbnUgaXMgbmVzdGVkXHJcbiAgICAgIHJpZ2h0ID1cclxuICAgICAgICB0aGlzLnRvcExldmVsTWVudS5jbGllbnRTaXplLndpZHRoIC1cclxuICAgICAgICAodGhpcy5fYW5jaG9yQm94LnJpZ2h0ICsgdGhpcy5fYm94LndpZHRoKTtcclxuICAgICAgbGVmdCA9IHRoaXMuX2FuY2hvckJveC5sZWZ0IC0gdGhpcy5fYm94LndpZHRoO1xyXG4gICAgfVxyXG5cclxuICAgIGxlZnQgLT0gdGhpcy50b3BMZXZlbE1lbnUuYm9keU1hcmdpbi5sZWZ0O1xyXG4gICAgcmlnaHQgLT0gdGhpcy50b3BMZXZlbE1lbnUuYm9keU1hcmdpbi5yaWdodDtcclxuXHJcbiAgICBpZiAocHJlZmVycmVkSG9yaXpvbnRhbERpciA9PT0gJ3JpZ2h0Jykge1xyXG4gICAgICAvLyBXZSB1c2UgcHJlZmVycmVkIGlmIHBvc3NpYmxlLlxyXG4gICAgICBpZiAocmlnaHQgPj0gMCkge1xyXG4gICAgICAgIHJldHVybiB7IGRpcjogJ3JpZ2h0JywgbGVmdDogMCB9O1xyXG4gICAgICAgIC8vIFRoZW4gdGhlIG90aGVyIG9uZS5cclxuICAgICAgfSBlbHNlIGlmIChsZWZ0ID49IDApIHtcclxuICAgICAgICByZXR1cm4geyBkaXI6ICdsZWZ0JywgbGVmdDogMCB9O1xyXG4gICAgICAgIC8vIEVkZ2UgY2FzZSBpZiBuZWl0aGVyIGRpcmVjdGlvbiBjYW4gYmUgdXNlZCAodWx0cmEgbmFycm93IHNjcmVlbikuXHJcbiAgICAgICAgLy8gQ2hvb3NlIGRpcmVjdGlvbiB0aGF0IGNvdmVycyBsZWFzdCBvZiBwYXJlbnQgbWVudS5cclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5nZXROYXJyb3dTY3JlZW5Ib3Jpem9udGFsRGlyKGxlZnQsIHJpZ2h0KTtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaWYgKGxlZnQgPj0gMCkge1xyXG4gICAgICAgIHJldHVybiB7IGRpcjogJ2xlZnQnLCBsZWZ0OiAwIH07XHJcbiAgICAgIH0gZWxzZSBpZiAocmlnaHQgPj0gMCkge1xyXG4gICAgICAgIHJldHVybiB7IGRpcjogJ3JpZ2h0JywgbGVmdDogMCB9O1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmdldE5hcnJvd1NjcmVlbkhvcml6b250YWxEaXIobGVmdCwgcmlnaHQpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLyBGaW5kcyBvdXQgd2hlcmUgdG8gcHV0IG1lbnUgaW4gY2FzZSBzY3JlZW4gaXMgdG9vIG5hcnJvdyBmb3IgdHdvIG1lbnVzXHJcbiAgLy8gdG8gZml0IG5leHQgdG8gZWFjaCBvdGhlci4gTWluaW1pemVzIGFyZWEgb2YgcGFyZW50IG1lbnUgY292ZXJlZCBieSB0aGlzLlxyXG4gIHByaXZhdGUgZ2V0TmFycm93U2NyZWVuSG9yaXpvbnRhbERpcihcclxuICAgIGxlZnQ6IG51bWJlcixcclxuICAgIHJpZ2h0OiBudW1iZXJcclxuICApOiBIb3JEaXJXaXRoT2Zmc2V0IHtcclxuICAgIGNvbnN0IHNjcmVlblN0YXJ0ID0gdGhpcy50b3BMZXZlbE1lbnUuYm9keU1hcmdpbi5sZWZ0O1xyXG4gICAgY29uc3Qgc2NyZWVuRW5kID1cclxuICAgICAgdGhpcy50b3BMZXZlbE1lbnUuY2xpZW50U2l6ZS53aWR0aCAtIHRoaXMudG9wTGV2ZWxNZW51LmJvZHlNYXJnaW4ucmlnaHQ7XHJcbiAgICBjb25zdCBzY3JlZW5DZW50ZXIgPSAoc2NyZWVuU3RhcnQgLSBzY3JlZW5FbmQpIC8gMjtcclxuXHJcbiAgICBjb25zdCBsZWZ0U3RhcnQgPSBNYXRoLm1heCh0aGlzLl9hbmNob3JCb3gubGVmdCwgc2NyZWVuU3RhcnQpO1xyXG4gICAgY29uc3QgbGVmdEVuZCA9IE1hdGgubWluKFxyXG4gICAgICB0aGlzLl9hbmNob3JCb3gubGVmdCArIHRoaXMuX2FuY2hvckJveC53aWR0aCxcclxuICAgICAgc2NyZWVuQ2VudGVyXHJcbiAgICApO1xyXG5cclxuICAgIGNvbnN0IHJpZ2h0U3RhcnQgPSBNYXRoLm1heChzY3JlZW5DZW50ZXIsIGxlZnRFbmQpO1xyXG4gICAgY29uc3QgcmlnaHRFbmQgPSBNYXRoLm1pbihcclxuICAgICAgdGhpcy5fYW5jaG9yQm94LmxlZnQgKyB0aGlzLl9hbmNob3JCb3gud2lkdGgsXHJcbiAgICAgIHNjcmVlbkVuZFxyXG4gICAgKTtcclxuXHJcbiAgICBpZiAobGVmdEVuZCAtIGxlZnRTdGFydCA+IHJpZ2h0RW5kIC0gcmlnaHRTdGFydCkge1xyXG4gICAgICByZXR1cm4geyBkaXI6ICdyaWdodCcsIGxlZnQ6IHJpZ2h0IH07XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZXR1cm4geyBkaXI6ICdsZWZ0JywgbGVmdDogLWxlZnQgfTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0UmVhbFZlcnRpY2FsRGlyKFxyXG4gICAgcHJlZmVycmVkVmVydGljYWxEaXI6IFJkdFZlcnRpY2FsRGlyZWN0aW9uXHJcbiAgKTogVmVydERpcldpdGhPZmZzZXQge1xyXG4gICAgbGV0IGJvdHRvbTogbnVtYmVyO1xyXG4gICAgbGV0IHRvcDogbnVtYmVyO1xyXG5cclxuICAgIGlmICh0aGlzLmxldmVsID09PSAwKSB7XHJcbiAgICAgIGJvdHRvbSA9XHJcbiAgICAgICAgdGhpcy50b3BMZXZlbE1lbnUuY2xpZW50U2l6ZS5oZWlnaHQgK1xyXG4gICAgICAgIHRoaXMuX2FuY2hvckJveC5ib3R0b20gLVxyXG4gICAgICAgIHRoaXMuX2JveC5oZWlnaHQ7XHJcbiAgICAgIHRvcCA9IHRoaXMuX2FuY2hvckJveC50b3AgLSB0aGlzLl9ib3guaGVpZ2h0O1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgYm90dG9tID1cclxuICAgICAgICB0aGlzLnRvcExldmVsTWVudS5jbGllbnRTaXplLmhlaWdodCAtXHJcbiAgICAgICAgdGhpcy5fYW5jaG9yQm94LnRvcCAtXHJcbiAgICAgICAgdGhpcy5fYm94LmhlaWdodDtcclxuICAgICAgdG9wID0gdGhpcy5fYW5jaG9yQm94LmJvdHRvbSAtIHRoaXMuX2JveC5oZWlnaHQ7XHJcbiAgICB9XHJcblxyXG4gICAgdG9wIC09IHRoaXMudG9wTGV2ZWxNZW51LmJvZHlNYXJnaW4udG9wO1xyXG4gICAgYm90dG9tIC09IHRoaXMudG9wTGV2ZWxNZW51LmJvZHlNYXJnaW4uYm90dG9tO1xyXG5cclxuICAgIGlmIChwcmVmZXJyZWRWZXJ0aWNhbERpciA9PT0gJ2Rvd24nKSB7XHJcbiAgICAgIGlmIChib3R0b20gPj0gMCkge1xyXG4gICAgICAgIHJldHVybiB7IGRpcjogJ2Rvd24nLCB0b3A6IDAgfTtcclxuICAgICAgfSBlbHNlIGlmICh0b3AgPj0gMCkge1xyXG4gICAgICAgIHJldHVybiB7IGRpcjogJ3VwJywgdG9wOiAwIH07XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgcmV0dXJuIHsgZGlyOiBwcmVmZXJyZWRWZXJ0aWNhbERpciwgdG9wOiAwIH07XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmICh0b3AgPj0gMCkge1xyXG4gICAgICAgIHJldHVybiB7IGRpcjogJ3VwJywgdG9wOiAwIH07XHJcbiAgICAgIH0gZWxzZSBpZiAoYm90dG9tID49IDApIHtcclxuICAgICAgICByZXR1cm4geyBkaXI6ICdkb3duJywgdG9wOiAwIH07XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgcmV0dXJuIHsgZGlyOiBwcmVmZXJyZWRWZXJ0aWNhbERpciwgdG9wOiAwIH07XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIE1lYXN1cmVzIGJvdW5kaW5nIHJlY3Qgb2YgdGhpcyBhbmQgb2Zmc2V0IGNvbnRhaW5lclxyXG4gIC8vIFNob3VsZCBhbHdheXMgYmUgY2FsbGVkIGFmdGVyIHBhcmVudCBtZW51IGhhcyBhbHJlYWR5IGJlZW4gbWVhc3VyZWQuXHJcbiAgcHJpdmF0ZSBtZWFzdXJlQm91bmRpbmdSZWN0KCkge1xyXG4gICAgdGhpcy5fYm94ID0gdGhpcy5lbFJlZi5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgY29uc3QgYW5jaG9yID1cclxuICAgICAgdGhpcy5hbmNob3JFbGVtZW50ID8/IHRoaXMuZWxSZWYubmF0aXZlRWxlbWVudC5wYXJlbnRFbGVtZW50ITtcclxuICAgIHRoaXMuX2FuY2hvckJveCA9IGFuY2hvci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgbWVhc3VyZUNvbnRhaW5lclBhZGRpbmcoKSB7XHJcbiAgICBjb25zdCBjb21wdXRlZFN0eWxlcyA9IGdldENvbXB1dGVkU3R5bGUoXHJcbiAgICAgIHRoaXMubWVudUl0ZW1Db250YWluZXIubmF0aXZlRWxlbWVudFxyXG4gICAgKTtcclxuICAgIGNvbnN0IHBhZGRpbmdUb3AgPSBwYXJzZUZsb2F0KGNvbXB1dGVkU3R5bGVzLnBhZGRpbmdUb3ApO1xyXG4gICAgY29uc3QgcGFkZGluZ0JvdHRvbSA9IHBhcnNlRmxvYXQoY29tcHV0ZWRTdHlsZXMucGFkZGluZ0JvdHRvbSk7XHJcbiAgICB0aGlzLl9jb250YWluZXJQYWRkaW5nID0geyB0b3A6IHBhZGRpbmdUb3AsIGJvdHRvbTogcGFkZGluZ0JvdHRvbSB9O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSByZWNhbGN1bGF0ZUNoaWxkcmVuKCkge1xyXG4gICAgaWYgKHRoaXMuZXhwYW5kZWQgJiYgdGhpcy5ob3Jpem9udGFsRGlyICYmIHRoaXMudmVydGljYWxEaXIpIHtcclxuICAgICAgdGhpcy5jaGlsZHJlbi5mb3JFYWNoKChjaGlsZCkgPT5cclxuICAgICAgICBjaGlsZC5yZWNhbGN1bGF0ZVBvc2l0aW9uKFxyXG4gICAgICAgICAgdGhpcy5ob3Jpem9udGFsRGlyIS5kaXIsXHJcbiAgICAgICAgICB0aGlzLnZlcnRpY2FsRGlyIS5kaXJcclxuICAgICAgICApXHJcbiAgICAgICk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldENsYXNzZXMoKSB7XHJcbiAgICBpZiAodGhpcy52ZXJ0aWNhbERpcikge1xyXG4gICAgICBpZiAodGhpcy52ZXJ0aWNhbERpci5kaXIgPT09ICd1cCcpIHtcclxuICAgICAgICB0aGlzLnNldENsYXNzKCdyZHQtb3ZlcmxheS11cCcpO1xyXG4gICAgICAgIHRoaXMucmVtb3ZlQ2xhc3MoJ3JkdC1vdmVybGF5LWRvd24nKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLnJlbW92ZUNsYXNzKCdyZHQtb3ZlcmxheS11cCcpO1xyXG4gICAgICAgIHRoaXMuc2V0Q2xhc3MoJ3JkdC1vdmVybGF5LWRvd24nKTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLnNldE9mZnNldCgndG9wJywgdGhpcy52ZXJ0aWNhbERpci50b3ApO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmhvcml6b250YWxEaXIpIHtcclxuICAgICAgaWYgKHRoaXMuaG9yaXpvbnRhbERpci5kaXIgPT09ICdsZWZ0Jykge1xyXG4gICAgICAgIHRoaXMuc2V0Q2xhc3MoJ3JkdC1vdmVybGF5LWxlZnQnKTtcclxuICAgICAgICB0aGlzLnJlbW92ZUNsYXNzKCdyZHQtb3ZlcmxheS1yaWdodCcpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMucmVtb3ZlQ2xhc3MoJ3JkdC1vdmVybGF5LWxlZnQnKTtcclxuICAgICAgICB0aGlzLnNldENsYXNzKCdyZHQtb3ZlcmxheS1yaWdodCcpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuc2V0T2Zmc2V0KCdsZWZ0JywgdGhpcy5ob3Jpem9udGFsRGlyLmxlZnQpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmlzUm9vdExldmVsKSB7XHJcbiAgICAgIHRoaXMuc2V0Q2xhc3MoJ3JkdC1tZW51LXJvb3QnKTtcclxuICAgICAgdGhpcy5yZW1vdmVDbGFzcygncmR0LW1lbnUtc3ViJyk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnJlbW92ZUNsYXNzKCdyZHQtbWVudS1yb290Jyk7XHJcbiAgICAgIHRoaXMuc2V0Q2xhc3MoJ3JkdC1tZW51LXN1YicpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzZXRDbGFzcyhjbGFzc05hbWU6IHN0cmluZykge1xyXG4gICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyh0aGlzLmVsUmVmLm5hdGl2ZUVsZW1lbnQsIGNsYXNzTmFtZSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHJlbW92ZUNsYXNzKGNsYXNzTmFtZTogc3RyaW5nKSB7XHJcbiAgICB0aGlzLnJlbmRlcmVyLnJlbW92ZUNsYXNzKHRoaXMuZWxSZWYubmF0aXZlRWxlbWVudCwgY2xhc3NOYW1lKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2V0T2Zmc2V0KGRpcmVjdGlvbjogJ3RvcCcgfCAnbGVmdCcsIHZhbHVlOiBudW1iZXIpIHtcclxuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5lbFJlZi5uYXRpdmVFbGVtZW50LCBkaXJlY3Rpb24sIGAke3ZhbHVlfXB4YCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGxpc3RlblRhYktleVByZXNzKCkge1xyXG4gICAgY29uc3Qgc2hpZnRUYWIgPSBSZHRTaG9ydGN1dC5jcmVhdGVVbnNhZmUoJ3NoaWZ0JywgJ3RhYicpO1xyXG4gICAgY29uc3QgdGFiID0gUmR0U2hvcnRjdXQuY3JlYXRlVW5zYWZlKCd0YWInKTtcclxuICAgIHRoaXMuc2hvcnRjdXRTZXJ2aWNlXHJcbiAgICAgIC5saXN0ZW4oW3RhYiwgc2hpZnRUYWJdLCB7XHJcbiAgICAgICAgZWxlbWVudDogdGhpcy5lbFJlZi5uYXRpdmVFbGVtZW50LFxyXG4gICAgICAgIHByZXZlbnREZWZhdWx0OiBmYWxzZSxcclxuICAgICAgfSlcclxuICAgICAgLnBpcGUodGFrZVVudGlsRGVzdHJveWVkKHRoaXMuZGVzdHJveVJlZikpXHJcbiAgICAgIC5zdWJzY3JpYmUoKGV2ZW50KSA9PiB0aGlzLm9uVGFiS2V5UHJlc3MoZXZlbnQpKTtcclxuICB9XHJcbn1cclxuIiwiPHVsIGNsYXNzPVwibWVudS1pdGVtLWNvbnRhaW5lclwiIHJvbGU9XCJwcmVzZW50YXRpb25cIiAjbWVudUl0ZW1Db250YWluZXI+XHJcbiAgPGxpXHJcbiAgICAqbmdGb3I9XCJsZXQgaXRlbSBvZiBpdGVtLml0ZW1zOyBsZXQgaSA9IGluZGV4XCJcclxuICAgIHJvbGU9XCJwcmVzZW50YXRpb25cIlxyXG4gICAgY2xhc3M9XCJtZW51LWl0ZW1cIlxyXG4gICAgKHJkdEtleUxpc3RlbmVyKT1cIm9uS2V5RG93bihpLCAkZXZlbnQpXCJcclxuICAgIChwb2ludGVyZW50ZXIpPVwib25JdGVtUG9pbnRlckVudGVyKGl0ZW0pXCJcclxuICAgIHJkdEFueVJvdXRlQWN0aXZlPVwibWVudS1pdGVtLXJvdXRlLWFjdGl2ZVwiXHJcbiAgICBbd2F0Y2hlZFJvdXRlc109XCJnZXRDaGlsZFJvdXRlcyhpdGVtKVwiXHJcbiAgICAjYW5jaG9yRWxcclxuICA+XHJcbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWl0ZW0ucm91dGVyTGluayAmJiAhaXRlbS5leHRlcm5hbExpbmtcIj5cclxuICAgICAgPGJ1dHRvblxyXG4gICAgICAgICNmb2N1c2FibGVJdGVtXHJcbiAgICAgICAgY2xhc3M9XCJtZW51LWl0ZW0tY29udGVudFwiXHJcbiAgICAgICAgcm9sZT1cIm1lbnVpdGVtXCJcclxuICAgICAgICAoY2xpY2spPVwib25JdGVtQ2xpY2soaXRlbSlcIlxyXG4gICAgICAgIFthdHRyLmFyaWEtaGFzcG9wdXBdPVwiaXRlbS5pdGVtcyA/ICdtZW51JyA6IG51bGxcIlxyXG4gICAgICAgIFthdHRyLmFyaWEtZXhwYW5kZWRdPVwiaXRlbSA9PT0gZXhwYW5kZWRDaGlsZD8uaXRlbVwiXHJcbiAgICAgICAgW2F0dHIudGFiaW5kZXhdPVwiMFwiXHJcbiAgICAgICAgW2F0dHIuZGF0YS10ZXN0aWRdPVwiaXRlbS5kYXRhVGVzdElkXCJcclxuICAgICAgPlxyXG4gICAgICAgIHt7IGl0ZW0ubGFiZWwgfX1cclxuXHJcbiAgICAgICAgPGRpdiBjbGFzcz1cIm1lbnUtaXRlbS1yaWdodC1jb250ZW50XCI+XHJcbiAgICAgICAgICA8c3BhbiAqbmdJZj1cIml0ZW0uc2hvcnRjdXRcIiBjbGFzcz1cIm1lbnUtaXRlbS1zaG9ydGN1dFwiPlxyXG4gICAgICAgICAgICB7eyBpdGVtLnNob3J0Y3V0LmxhYmVsIH19XHJcbiAgICAgICAgICA8L3NwYW4+XHJcbiAgICAgICAgICA8IS0tIFRPRE86XHJcbiAgICAgICAgICA8cmR0LWljb25cclxuICAgICAgICAgICAgKm5nSWY9XCJpdGVtLml0ZW1zXCJcclxuICAgICAgICAgICAgbmFtZT1cImNoZXZyb25fcmlnaHRcIlxyXG4gICAgICAgICAgICBjbGFzcz1cIm1lbnUtaXRlbS1pY29uXCJcclxuICAgICAgICAgIC8+XHJcbiAgICAgICAgICA8cmR0LWljb25cclxuICAgICAgICAgICAgKm5nSWY9XCJpdGVtLmljb25cIlxyXG4gICAgICAgICAgICBbbmFtZV09XCJpdGVtLmljb25cIlxyXG4gICAgICAgICAgICBjbGFzcz1cIm1lbnUtaXRlbS1pY29uXCJcclxuICAgICAgICAgIC8+XHJcbiAgICAgICAgLS0+XHJcbiAgICAgICAgICA8c3BhblxyXG4gICAgICAgICAgICBjbGFzcz1cIm1lbnUtaXRlbS1pY29uIHJkdC1tZW51LWljb24tcmlnaHRcIlxyXG4gICAgICAgICAgICAqbmdJZj1cIml0ZW0uaXRlbXNcIlxyXG4gICAgICAgICAgPjwvc3Bhbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9idXR0b24+XHJcbiAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICA8bmctdGVtcGxhdGUgI2xpbmtCb2R5IGxldC1pdGVtPlxyXG4gICAgICB7eyBpdGVtLmxhYmVsIH19XHJcblxyXG4gICAgICA8ZGl2IGNsYXNzPVwibWVudS1pdGVtLXJpZ2h0LWNvbnRlbnRcIj5cclxuICAgICAgICA8c3BhbiAqbmdJZj1cIml0ZW0uc2hvcnRjdXRcIiBjbGFzcz1cIm1lbnUtaXRlbS1zaG9ydGN1dFwiPlxyXG4gICAgICAgICAge3sgaXRlbS5zaG9ydGN1dC5sYWJlbCB9fVxyXG4gICAgICAgIDwvc3Bhbj5cclxuICAgICAgICA8IS0tIFRPRE86XHJcbiAgICAgICAgPHJkdC1pY29uXHJcbiAgICAgICAgICAqbmdJZj1cIml0ZW0uaWNvblwiXHJcbiAgICAgICAgICBbbmFtZV09XCJpdGVtLmljb25cIlxyXG4gICAgICAgICAgY2xhc3M9XCJtZW51LWl0ZW0taWNvblwiXHJcbiAgICAgICAgLz5cclxuICAgICAgLS0+PC9kaXY+XHJcbiAgICA8L25nLXRlbXBsYXRlPlxyXG5cclxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJpdGVtLnJvdXRlckxpbmtcIj5cclxuICAgICAgPGFcclxuICAgICAgICAjZm9jdXNhYmxlSXRlbVxyXG4gICAgICAgIGNsYXNzPVwibWVudS1pdGVtLWNvbnRlbnRcIlxyXG4gICAgICAgIHJvbGU9XCJtZW51aXRlbVwiXHJcbiAgICAgICAgKGNsaWNrKT1cIm9uSXRlbUNsaWNrKGl0ZW0pXCJcclxuICAgICAgICBbcm91dGVyTGlua109XCJpdGVtLnJvdXRlckxpbmtcIlxyXG4gICAgICAgIFtxdWVyeVBhcmFtc109XCJpdGVtLnF1ZXJ5UGFyYW1zXCJcclxuICAgICAgICBbdGFyZ2V0XT1cIml0ZW0udGFyZ2V0XCJcclxuICAgICAgICBbYXR0ci50YWJpbmRleF09XCIwXCJcclxuICAgICAgICBbYXR0ci5kYXRhLXRlc3RpZF09XCJpdGVtLmRhdGFUZXN0SWRcIlxyXG4gICAgICA+XHJcbiAgICAgICAgPG5nLWNvbnRhaW5lclxyXG4gICAgICAgICAgKm5nVGVtcGxhdGVPdXRsZXQ9XCJsaW5rQm9keTsgY29udGV4dDogeyAkaW1wbGljaXQ6IGl0ZW0gfVwiXHJcbiAgICAgICAgLz5cclxuICAgICAgPC9hPlxyXG4gICAgPC9uZy1jb250YWluZXI+XHJcblxyXG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIml0ZW0uZXh0ZXJuYWxMaW5rXCI+XHJcbiAgICAgIDxhXHJcbiAgICAgICAgI2ZvY3VzYWJsZUl0ZW1cclxuICAgICAgICBjbGFzcz1cIm1lbnUtaXRlbS1jb250ZW50XCJcclxuICAgICAgICByb2xlPVwibWVudWl0ZW1cIlxyXG4gICAgICAgIChjbGljayk9XCJvbkl0ZW1DbGljayhpdGVtKVwiXHJcbiAgICAgICAgW2hyZWZdPVwiaXRlbS5leHRlcm5hbExpbmtcIlxyXG4gICAgICAgIFt0YXJnZXRdPVwiaXRlbS50YXJnZXRcIlxyXG4gICAgICAgIFthdHRyLnRhYmluZGV4XT1cIjBcIlxyXG4gICAgICAgIFthdHRyLmRhdGEtdGVzdGlkXT1cIml0ZW0uZGF0YVRlc3RJZFwiXHJcbiAgICAgID5cclxuICAgICAgICA8bmctY29udGFpbmVyXHJcbiAgICAgICAgICAqbmdUZW1wbGF0ZU91dGxldD1cImxpbmtCb2R5OyBjb250ZXh0OiB7ICRpbXBsaWNpdDogaXRlbSB9XCJcclxuICAgICAgICAvPlxyXG4gICAgICA8L2E+XHJcbiAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICA8IS0tIENoaWxkIG1lbnVzIGV4aXN0IG9ubHkgaWYgdGhpcyBtZW51IGlzIGV4cGFuZGVkLiAtLT5cclxuICAgIDwhLS0gT25seSBvbmUgaW52aXNpYmxlIGxldmVsIGlzIGFsd2F5cyBhdHRhY2hlZCB0byBET00sIHRoZSByZXN0IGRvZXMgbm90IGV4aXN0LiAtLT5cclxuICAgIDxyZHQtbWVudS1vdmVybGF5XHJcbiAgICAgICpuZ0lmPVwiaXRlbS5pdGVtcyAmJiBleHBhbmRlZFwiXHJcbiAgICAgIFtpdGVtXT1cIiRhbnkoaXRlbSlcIlxyXG4gICAgICBbZXhwYW5kZWRdPVwiaXRlbSA9PT0gZXhwYW5kZWRDaGlsZD8uaXRlbVwiXHJcbiAgICAgIFthdXRvZm9jdXNJdGVtXT1cImF1dG9mb2N1c1N1Ym1lbnVJdGVtXCJcclxuICAgICAgW3ByZWZlcnJlZEhvcml6b250YWxEaXJdPVwiaG9yaXpvbnRhbERpcj8uZGlyIVwiXHJcbiAgICAgIFtwcmVmZXJyZWRWZXJ0aWNhbERpcl09XCJ2ZXJ0aWNhbERpcj8uZGlyIVwiXHJcbiAgICAgIFtsZXZlbF09XCJsZXZlbCArIDFcIlxyXG4gICAgICBbYW5jaG9yRWxlbWVudF09XCJhbmNob3JFbFwiXHJcbiAgICAvPlxyXG4gIDwvbGk+XHJcbjwvdWw+XHJcbiJdfQ==