@avdbrink/ngx-contextmenu
Version:
An Angular component to show a context menu on an arbitrary component
818 lines (806 loc) • 81.9 kB
JavaScript
import { Directive, ElementRef, EventEmitter, Input, Output, TemplateRef, InjectionToken, ChangeDetectorRef, Component, Inject, Optional, Renderer, ViewChild, ViewChildren, QueryList, HostListener, Injectable, ContentChildren, ViewEncapsulation, NgModule } from '@angular/core';
import { Overlay, ScrollStrategyOptions, OverlayModule } from '@angular/cdk/overlay';
import { Subscription, Subject } from 'rxjs';
import { ActiveDescendantKeyManager } from '@angular/cdk/a11y';
import { ComponentPortal } from '@angular/cdk/portal';
import { first } from 'rxjs/operators';
import { CommonModule } from '@angular/common';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class ContextMenuItemDirective {
/**
* @param {?} template
* @param {?} elementRef
*/
constructor(template, elementRef) {
this.template = template;
this.elementRef = elementRef;
this.divider = false;
this.enabled = true;
this.passive = false;
this.visible = true;
this.execute = new EventEmitter();
this.isActive = false;
this.isActiveParent = false;
}
/**
* @return {?}
*/
get disabled() {
return this.passive ||
this.divider ||
!this.evaluateIfFunction(this.enabled, this.currentItem);
}
/**
* @param {?} value
* @param {?} item
* @return {?}
*/
evaluateIfFunction(value, item) {
if (value instanceof Function) {
return value(item);
}
return value;
}
/**
* @return {?}
*/
setActiveStyles() {
this.isActive = true;
}
/**
* @return {?}
*/
setInactiveStyles() {
this.isActive = false;
}
/**
* @return {?}
*/
setActiveParentStyles() {
this.isActiveParent = true;
}
/**
* @return {?}
*/
setInActiveParentStyles() {
this.isActiveParent = false;
}
/**
* @param {?} item
* @param {?=} $event
* @return {?}
*/
triggerExecute(item, $event) {
if (!this.evaluateIfFunction(this.enabled, item)) {
return;
}
this.execute.emit({ event: $event, item });
}
}
ContextMenuItemDirective.decorators = [
{ type: Directive, args: [{
/* tslint:disable:directive-selector-type */
selector: '[contextMenuItem]',
},] },
];
/** @nocollapse */
ContextMenuItemDirective.ctorParameters = () => [
{ type: TemplateRef },
{ type: ElementRef }
];
ContextMenuItemDirective.propDecorators = {
subMenu: [{ type: Input }],
divider: [{ type: Input }],
enabled: [{ type: Input }],
passive: [{ type: Input }],
visible: [{ type: Input }],
execute: [{ type: Output }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
const /** @type {?} */ CONTEXT_MENU_OPTIONS = new InjectionToken('CONTEXT_MENU_OPTIONS');
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
const /** @type {?} */ ARROW_LEFT_KEYCODE = 37;
class ContextMenuContentComponent {
/**
* @param {?} changeDetector
* @param {?} elementRef
* @param {?} options
* @param {?} renderer
*/
constructor(changeDetector, elementRef, options, renderer) {
this.changeDetector = changeDetector;
this.elementRef = elementRef;
this.options = options;
this.renderer = renderer;
this.menuItems = [];
this.isLeaf = false;
this.execute = new EventEmitter();
this.openSubMenu = new EventEmitter();
this.closeLeafMenu = new EventEmitter();
this.closeAllMenus = new EventEmitter();
this.autoFocus = false;
this.useBootstrap4 = false;
this.highlightParentItems = false;
this.subscription = new Subscription();
if (options) {
this.autoFocus = options.autoFocus;
this.useBootstrap4 = options.useBootstrap4;
this.highlightParentItems = options.highlightParentItems;
}
}
/**
* @return {?}
*/
ngOnInit() {
this.menuItems.forEach(menuItem => {
menuItem.currentItem = this.item;
this.subscription.add(menuItem.execute.subscribe(event => this.execute.emit(Object.assign({}, event, { menuItem }))));
});
const /** @type {?} */ queryList = new QueryList();
queryList.reset(this.menuItems);
this._keyManager = new ActiveDescendantKeyManager(queryList).withWrap();
}
/**
* @return {?}
*/
ngAfterViewInit() {
if (this.autoFocus) {
setTimeout(() => this.focus());
}
this.overlay.updatePosition();
}
/**
* @return {?}
*/
ngOnDestroy() {
this.subscription.unsubscribe();
}
/**
* @return {?}
*/
focus() {
if (this.autoFocus) {
this.menuElement.nativeElement.focus();
}
}
/**
* @param {?} $event
* @return {?}
*/
stopEvent($event) {
$event.stopPropagation();
}
/**
* @param {?} menuItem
* @return {?}
*/
isMenuItemEnabled(menuItem) {
return this.evaluateIfFunction(menuItem && menuItem.enabled);
}
/**
* @param {?} menuItem
* @return {?}
*/
isMenuItemVisible(menuItem) {
return this.evaluateIfFunction(menuItem && menuItem.visible);
}
/**
* @param {?} value
* @return {?}
*/
evaluateIfFunction(value) {
if (value instanceof Function) {
return value(this.item);
}
return value;
}
/**
* @param {?} link
* @return {?}
*/
isDisabled(link) {
return link.enabled && !link.enabled(this.item);
}
/**
* @param {?} event
* @return {?}
*/
onKeyEvent(event) {
if (!this.isLeaf) {
return;
}
this._keyManager.onKeydown(event);
}
/**
* @param {?=} event
* @return {?}
*/
keyboardOpenSubMenu(event) {
if (!this.isLeaf) {
return;
}
this.cancelEvent(event);
const /** @type {?} */ menuItem = this.menuItems[this._keyManager.activeItemIndex];
if (menuItem) {
this.onOpenSubMenu(menuItem);
}
}
/**
* @param {?=} event
* @return {?}
*/
keyboardMenuItemSelect(event) {
if (!this.isLeaf) {
return;
}
this.cancelEvent(event);
const /** @type {?} */ menuItem = this.menuItems[this._keyManager.activeItemIndex];
if (menuItem) {
this.onMenuItemSelect(menuItem, event);
}
}
/**
* @param {?} event
* @return {?}
*/
onCloseLeafMenu(event) {
if (!this.isLeaf) {
return;
}
this.cancelEvent(event);
this.closeLeafMenu.emit({ exceptRootMenu: event.keyCode === ARROW_LEFT_KEYCODE, event });
}
/**
* @param {?} event
* @return {?}
*/
closeMenu(event) {
if (event.type === 'click' && event.button === 2) {
return;
}
this.closeAllMenus.emit({ event });
}
/**
* @param {?} menuItem
* @param {?=} event
* @return {?}
*/
onOpenSubMenu(menuItem, event) {
const /** @type {?} */ anchorElementRef = this.menuItemElements.toArray()[this._keyManager.activeItemIndex];
const /** @type {?} */ anchorElement = anchorElementRef && anchorElementRef.nativeElement;
if (this.highlightParentItems) {
this.menuItems.forEach(item => item.isActiveParent = (item === menuItem && menuItem.subMenu));
}
this.openSubMenu.emit({
anchorElement,
contextMenu: menuItem.subMenu,
event,
item: this.item,
parentContextMenu: this,
});
}
/**
* @param {?} menuItem
* @param {?} event
* @return {?}
*/
onMenuItemSelect(menuItem, event) {
event.preventDefault();
event.stopPropagation();
this.onOpenSubMenu(menuItem, event);
if (!menuItem.subMenu) {
menuItem.triggerExecute(this.item, event);
}
}
/**
* @param {?} event
* @return {?}
*/
cancelEvent(event) {
if (!event) {
return;
}
const /** @type {?} */ target = event.target;
if (['INPUT', 'TEXTAREA', 'SELECT'].indexOf(target.tagName) > -1 || target.isContentEditable) {
return;
}
event.preventDefault();
event.stopPropagation();
}
}
ContextMenuContentComponent.decorators = [
{ type: Component, args: [{
selector: 'context-menu-content',
styles: [
`.passive {
display: block;
padding: 3px 20px;
clear: both;
font-weight: normal;
line-height: @line-height-base;
white-space: nowrap;
}
.hasSubMenu:before {
content: "\u25B6";
float: right;
}
.activeParent {
text-decoration: none;
color: #262626;
background-color: #f5f5f5;
}`,
],
template: `<div class="dropdown open show ngx-contextmenu" [ngClass]="menuClass" tabindex="0">
<ul #menu class="dropdown-menu show" style="position: static; float: none;" tabindex="0">
<li #li *ngFor="let menuItem of menuItems; let i = index" [class.disabled]="!isMenuItemEnabled(menuItem)"
[class.divider]="menuItem.divider" [class.dropdown-divider]="useBootstrap4 && menuItem.divider"
[class.active]="menuItem.isActive && isMenuItemEnabled(menuItem)"
[attr.role]="menuItem.divider ? 'separator' : undefined">
<a *ngIf="!menuItem.divider && !menuItem.passive" href [class.dropdown-item]="useBootstrap4"
[class.active]="menuItem.isActive && isMenuItemEnabled(menuItem)"
[class.activeParent]="highlightParentItems && menuItem.isActiveParent && isMenuItemEnabled(menuItem)"
[class.disabled]="useBootstrap4 && !isMenuItemEnabled(menuItem)" [class.hasSubMenu]="!!menuItem.subMenu"
(click)="onMenuItemSelect(menuItem, $event)" (mouseenter)="onOpenSubMenu(menuItem, $event)">
<ng-template [ngTemplateOutlet]="menuItem.template" [ngTemplateOutletContext]="{ $implicit: item }"></ng-template>
</a>
<span (click)="stopEvent($event)" (contextmenu)="stopEvent($event)" class="passive"
*ngIf="!menuItem.divider && menuItem.passive" [class.dropdown-item]="useBootstrap4"
[class.disabled]="useBootstrap4 && !isMenuItemEnabled(menuItem)">
<ng-template [ngTemplateOutlet]="menuItem.template" [ngTemplateOutletContext]="{ $implicit: item }"></ng-template>
</span>
</li>
</ul>
</div>
`,
},] },
];
/** @nocollapse */
ContextMenuContentComponent.ctorParameters = () => [
{ type: ChangeDetectorRef },
{ type: ElementRef },
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [CONTEXT_MENU_OPTIONS,] }] },
{ type: Renderer }
];
ContextMenuContentComponent.propDecorators = {
menuItems: [{ type: Input }],
item: [{ type: Input }],
event: [{ type: Input }],
parentContextMenu: [{ type: Input }],
menuClass: [{ type: Input }],
overlay: [{ type: Input }],
isLeaf: [{ type: Input }],
execute: [{ type: Output }],
openSubMenu: [{ type: Output }],
closeLeafMenu: [{ type: Output }],
closeAllMenus: [{ type: Output }],
menuElement: [{ type: ViewChild, args: ['menu',] }],
menuItemElements: [{ type: ViewChildren, args: ['li',] }],
onKeyEvent: [{ type: HostListener, args: ['window:keydown.ArrowDown', ['$event'],] }, { type: HostListener, args: ['window:keydown.ArrowUp', ['$event'],] }],
keyboardOpenSubMenu: [{ type: HostListener, args: ['window:keydown.ArrowRight', ['$event'],] }],
keyboardMenuItemSelect: [{ type: HostListener, args: ['window:keydown.Enter', ['$event'],] }, { type: HostListener, args: ['window:keydown.Space', ['$event'],] }],
onCloseLeafMenu: [{ type: HostListener, args: ['window:keydown.Escape', ['$event'],] }, { type: HostListener, args: ['window:keydown.ArrowLeft', ['$event'],] }],
closeMenu: [{ type: HostListener, args: ['document:click', ['$event'],] }, { type: HostListener, args: ['document:contextmenu', ['$event'],] }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class ContextMenuService {
/**
* @param {?} overlay
* @param {?} scrollStrategy
*/
constructor(overlay, scrollStrategy) {
this.overlay = overlay;
this.scrollStrategy = scrollStrategy;
this.isDestroyingLeafMenu = false;
this.show = new Subject();
this.triggerClose = new Subject();
this.close = new Subject();
this.overlays = [];
this.fakeElement = {
getBoundingClientRect: () => ({
bottom: 0,
height: 0,
left: 0,
right: 0,
top: 0,
width: 0,
})
};
}
/**
* @param {?} context
* @return {?}
*/
openContextMenu(context) {
const { anchorElement, event, parentContextMenu } = context;
if (!parentContextMenu) {
const /** @type {?} */ mouseEvent = /** @type {?} */ (event);
this.fakeElement.getBoundingClientRect = () => ({
bottom: mouseEvent.clientY,
height: 0,
left: mouseEvent.clientX,
right: mouseEvent.clientX,
top: mouseEvent.clientY,
width: 0,
});
this.closeAllContextMenus({ eventType: 'cancel', event });
const /** @type {?} */ positionStrategy = this.overlay.position().connectedTo(new ElementRef(anchorElement || this.fakeElement), { originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'top' })
.withFallbackPosition({ originX: 'start', originY: 'top' }, { overlayX: 'start', overlayY: 'bottom' })
.withFallbackPosition({ originX: 'end', originY: 'top' }, { overlayX: 'start', overlayY: 'top' })
.withFallbackPosition({ originX: 'start', originY: 'top' }, { overlayX: 'end', overlayY: 'top' })
.withFallbackPosition({ originX: 'end', originY: 'center' }, { overlayX: 'start', overlayY: 'center' })
.withFallbackPosition({ originX: 'start', originY: 'center' }, { overlayX: 'end', overlayY: 'center' });
this.overlays = [this.overlay.create({
positionStrategy,
panelClass: 'ngx-contextmenu',
scrollStrategy: this.scrollStrategy.close(),
})];
this.attachContextMenu(this.overlays[0], context);
}
else {
const /** @type {?} */ positionStrategy = this.overlay.position().connectedTo(new ElementRef(event ? event.target : anchorElement), { originX: 'end', originY: 'top' }, { overlayX: 'start', overlayY: 'top' })
.withFallbackPosition({ originX: 'start', originY: 'top' }, { overlayX: 'end', overlayY: 'top' })
.withFallbackPosition({ originX: 'end', originY: 'bottom' }, { overlayX: 'start', overlayY: 'bottom' })
.withFallbackPosition({ originX: 'start', originY: 'bottom' }, { overlayX: 'end', overlayY: 'bottom' });
const /** @type {?} */ newOverlay = this.overlay.create({
positionStrategy,
panelClass: 'ngx-contextmenu',
scrollStrategy: this.scrollStrategy.close(),
});
this.destroySubMenus(parentContextMenu);
this.overlays = this.overlays.concat(newOverlay);
this.attachContextMenu(newOverlay, context);
}
}
/**
* @param {?} overlay
* @param {?} context
* @return {?}
*/
attachContextMenu(overlay, context) {
const { event, item, menuItems, menuClass } = context;
const /** @type {?} */ contextMenuContent = overlay.attach(new ComponentPortal(ContextMenuContentComponent));
contextMenuContent.instance.event = event;
contextMenuContent.instance.item = item;
contextMenuContent.instance.menuItems = menuItems;
contextMenuContent.instance.overlay = overlay;
contextMenuContent.instance.isLeaf = true;
contextMenuContent.instance.menuClass = menuClass;
(/** @type {?} */ (overlay)).contextMenu = contextMenuContent.instance;
const /** @type {?} */ subscriptions = new Subscription();
subscriptions.add(contextMenuContent.instance.execute.asObservable()
.subscribe((executeEvent) => this.closeAllContextMenus(Object.assign({ eventType: 'execute' }, executeEvent))));
subscriptions.add(contextMenuContent.instance.closeAllMenus.asObservable()
.subscribe((closeAllEvent) => this.closeAllContextMenus(Object.assign({ eventType: 'cancel' }, closeAllEvent))));
subscriptions.add(contextMenuContent.instance.closeLeafMenu.asObservable()
.subscribe(closeLeafMenuEvent => this.destroyLeafMenu(closeLeafMenuEvent)));
subscriptions.add(contextMenuContent.instance.openSubMenu.asObservable()
.subscribe((subMenuEvent) => {
this.destroySubMenus(contextMenuContent.instance);
if (!subMenuEvent.contextMenu) {
contextMenuContent.instance.isLeaf = true;
return;
}
contextMenuContent.instance.isLeaf = false;
this.show.next(subMenuEvent);
}));
contextMenuContent.onDestroy(() => {
menuItems.forEach(menuItem => menuItem.isActive = false);
subscriptions.unsubscribe();
});
contextMenuContent.changeDetectorRef.detectChanges();
}
/**
* @param {?} closeEvent
* @return {?}
*/
closeAllContextMenus(closeEvent) {
if (this.overlays) {
this.close.next(closeEvent);
this.overlays.forEach((overlay, index) => {
overlay.detach();
overlay.dispose();
});
}
this.overlays = [];
}
/**
* @return {?}
*/
getLastAttachedOverlay() {
let /** @type {?} */ overlay = this.overlays[this.overlays.length - 1];
while (this.overlays.length > 1 && overlay && !overlay.hasAttached()) {
overlay.detach();
overlay.dispose();
this.overlays = this.overlays.slice(0, -1);
overlay = this.overlays[this.overlays.length - 1];
}
return overlay;
}
/**
* @param {?=} __0
* @return {?}
*/
destroyLeafMenu({ exceptRootMenu, event } = {}) {
if (this.isDestroyingLeafMenu) {
return;
}
this.isDestroyingLeafMenu = true;
setTimeout(() => {
const /** @type {?} */ overlay = this.getLastAttachedOverlay();
if (this.overlays.length > 1 && overlay) {
overlay.detach();
overlay.dispose();
}
if (!exceptRootMenu && this.overlays.length > 0 && overlay) {
this.close.next({ eventType: 'cancel', event });
overlay.detach();
overlay.dispose();
}
const /** @type {?} */ newLeaf = this.getLastAttachedOverlay();
if (newLeaf) {
newLeaf.contextMenu.isLeaf = true;
}
this.isDestroyingLeafMenu = false;
});
}
/**
* @param {?} contextMenu
* @return {?}
*/
destroySubMenus(contextMenu) {
const /** @type {?} */ overlay = contextMenu.overlay;
const /** @type {?} */ index = this.overlays.indexOf(overlay);
this.overlays.slice(index + 1).forEach(subMenuOverlay => {
subMenuOverlay.detach();
subMenuOverlay.dispose();
});
}
/**
* @param {?} contextMenuContent
* @return {?}
*/
isLeafMenu(contextMenuContent) {
const /** @type {?} */ overlay = this.getLastAttachedOverlay();
return contextMenuContent.overlay === overlay;
}
}
ContextMenuService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
ContextMenuService.ctorParameters = () => [
{ type: Overlay },
{ type: ScrollStrategyOptions }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class ContextMenuComponent {
/**
* @param {?} _contextMenuService
* @param {?} changeDetector
* @param {?} elementRef
* @param {?} options
*/
constructor(_contextMenuService, changeDetector, elementRef, options) {
this._contextMenuService = _contextMenuService;
this.changeDetector = changeDetector;
this.elementRef = elementRef;
this.options = options;
this.menuClass = "";
this.autoFocus = false;
this.useBootstrap4 = false;
this.highlightParentItems = false;
this.disabled = false;
this.close = new EventEmitter();
this.open = new EventEmitter();
this.visibleMenuItems = [];
this.links = [];
this.subscription = new Subscription();
if (options) {
this.autoFocus = options.autoFocus;
this.useBootstrap4 = options.useBootstrap4;
this.highlightParentItems = options.highlightParentItems;
}
this.subscription.add(_contextMenuService.show.subscribe(menuEvent => {
this.onMenuEvent(menuEvent);
}));
}
/**
* @return {?}
*/
ngOnDestroy() {
this.subscription.unsubscribe();
}
/**
* @param {?} menuEvent
* @return {?}
*/
onMenuEvent(menuEvent) {
if (this.disabled) {
return;
}
const { contextMenu, event, item } = menuEvent;
if (contextMenu && contextMenu !== this) {
return;
}
this.event = event;
this.item = item;
this.setVisibleMenuItems();
this._contextMenuService.openContextMenu(Object.assign({}, menuEvent, { menuItems: this.visibleMenuItems, menuClass: this.menuClass }));
this._contextMenuService.close.asObservable().pipe(first()).subscribe(closeEvent => this.close.emit(closeEvent));
this.open.next(menuEvent);
}
/**
* @param {?} menuItem
* @return {?}
*/
isMenuItemVisible(menuItem) {
return this.evaluateIfFunction(menuItem.visible);
}
/**
* @return {?}
*/
setVisibleMenuItems() {
this.visibleMenuItems = this.menuItems.filter(menuItem => this.isMenuItemVisible(menuItem));
}
/**
* @param {?} value
* @return {?}
*/
evaluateIfFunction(value) {
if (value instanceof Function) {
return value(this.item);
}
return value;
}
}
ContextMenuComponent.decorators = [
{ type: Component, args: [{
encapsulation: ViewEncapsulation.None,
selector: 'context-menu',
styles: [`
.cdk-overlay-container {
position: fixed;
z-index: 1000;
pointer-events: none;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.ngx-contextmenu.cdk-overlay-pane {
position: absolute;
pointer-events: auto;
box-sizing: border-box;
}
`],
template: ` `,
},] },
];
/** @nocollapse */
ContextMenuComponent.ctorParameters = () => [
{ type: ContextMenuService },
{ type: ChangeDetectorRef },
{ type: ElementRef },
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [CONTEXT_MENU_OPTIONS,] }] }
];
ContextMenuComponent.propDecorators = {
menuClass: [{ type: Input }],
autoFocus: [{ type: Input }],
useBootstrap4: [{ type: Input }],
highlightParentItems: [{ type: Input }],
disabled: [{ type: Input }],
close: [{ type: Output }],
open: [{ type: Output }],
menuItems: [{ type: ContentChildren, args: [ContextMenuItemDirective,] }],
menuElement: [{ type: ViewChild, args: ['menu',] }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class ContextMenuAttachDirective {
/**
* @param {?} contextMenuService
*/
constructor(contextMenuService) {
this.contextMenuService = contextMenuService;
}
/**
* @param {?} event
* @return {?}
*/
onContextMenu(event) {
if (!this.contextMenu.disabled) {
this.contextMenuService.show.next({
contextMenu: this.contextMenu,
event,
item: this.contextMenuSubject,
});
event.preventDefault();
event.stopPropagation();
}
}
}
ContextMenuAttachDirective.decorators = [
{ type: Directive, args: [{
selector: '[contextMenu]',
},] },
];
/** @nocollapse */
ContextMenuAttachDirective.ctorParameters = () => [
{ type: ContextMenuService }
];
ContextMenuAttachDirective.propDecorators = {
contextMenuSubject: [{ type: Input }],
contextMenu: [{ type: Input }],
onContextMenu: [{ type: HostListener, args: ['contextmenu', ['$event'],] }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class ContextMenuModule {
/**
* @param {?=} options
* @return {?}
*/
static forRoot(options) {
return {
ngModule: ContextMenuModule,
providers: [
ContextMenuService,
{
provide: CONTEXT_MENU_OPTIONS,
useValue: options,
},
],
};
}
}
ContextMenuModule.decorators = [
{ type: NgModule, args: [{
declarations: [
ContextMenuAttachDirective,
ContextMenuComponent,
ContextMenuContentComponent,
ContextMenuItemDirective,
],
entryComponents: [
ContextMenuContentComponent,
],
exports: [
ContextMenuAttachDirective,
ContextMenuComponent,
ContextMenuItemDirective,
],
imports: [
CommonModule,
OverlayModule,
],
},] },
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
export { ContextMenuModule, ContextMenuComponent, ContextMenuService, ContextMenuAttachDirective as ɵa, ContextMenuItemDirective as ɵb, CONTEXT_MENU_OPTIONS as ɵc, ContextMenuContentComponent as ɵd };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWNvbnRleHRtZW51LmpzLm1hcCIsInNvdXJjZXMiOlsibmc6Ly9uZ3gtY29udGV4dG1lbnUvbGliL2NvbnRleHRNZW51Lml0ZW0uZGlyZWN0aXZlLnRzIiwibmc6Ly9uZ3gtY29udGV4dG1lbnUvbGliL2NvbnRleHRNZW51LnRva2Vucy50cyIsIm5nOi8vbmd4LWNvbnRleHRtZW51L2xpYi9jb250ZXh0TWVudUNvbnRlbnQuY29tcG9uZW50LnRzIiwibmc6Ly9uZ3gtY29udGV4dG1lbnUvbGliL2NvbnRleHRNZW51LnNlcnZpY2UudHMiLCJuZzovL25neC1jb250ZXh0bWVudS9saWIvY29udGV4dE1lbnUuY29tcG9uZW50LnRzIiwibmc6Ly9uZ3gtY29udGV4dG1lbnUvbGliL2NvbnRleHRNZW51LmF0dGFjaC5kaXJlY3RpdmUudHMiLCJuZzovL25neC1jb250ZXh0bWVudS9saWIvbmd4LWNvbnRleHRtZW51LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEhpZ2hsaWdodGFibGUgfSBmcm9tICdAYW5ndWxhci9jZGsvYTExeSc7XG5pbXBvcnQgeyBEaXJlY3RpdmUsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE91dHB1dCwgVGVtcGxhdGVSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuQERpcmVjdGl2ZSh7XG4gIC8qIHRzbGludDpkaXNhYmxlOmRpcmVjdGl2ZS1zZWxlY3Rvci10eXBlICovXG4gIHNlbGVjdG9yOiAnW2NvbnRleHRNZW51SXRlbV0nLFxuICAvKiB0c2xpbnQ6ZW5hYmxlOmRpcmVjdGl2ZS1zZWxlY3Rvci10eXBlICovXG59KVxuZXhwb3J0IGNsYXNzIENvbnRleHRNZW51SXRlbURpcmVjdGl2ZSBpbXBsZW1lbnRzIEhpZ2hsaWdodGFibGUge1xuICBASW5wdXQoKSBwdWJsaWMgc3ViTWVudTogYW55O1xuICBASW5wdXQoKSBwdWJsaWMgZGl2aWRlciA9IGZhbHNlO1xuICBASW5wdXQoKSBwdWJsaWMgZW5hYmxlZDogYm9vbGVhbiB8ICgoaXRlbTogYW55KSA9PiBib29sZWFuKSA9IHRydWU7XG4gIEBJbnB1dCgpIHB1YmxpYyBwYXNzaXZlID0gZmFsc2U7XG4gIEBJbnB1dCgpIHB1YmxpYyB2aXNpYmxlOiBib29sZWFuIHwgKChpdGVtOiBhbnkpID0+IGJvb2xlYW4pID0gdHJ1ZTtcbiAgQE91dHB1dCgpIHB1YmxpYyBleGVjdXRlOiBFdmVudEVtaXR0ZXI8eyBldmVudDogRXZlbnQsIGl0ZW06IGFueSB9PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBwdWJsaWMgY3VycmVudEl0ZW06IGFueTtcbiAgcHVibGljIGlzQWN0aXZlID0gZmFsc2U7XG4gIHB1YmxpYyBpc0FjdGl2ZVBhcmVudCA9IGZhbHNlO1xuICBwdWJsaWMgZ2V0IGRpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLnBhc3NpdmUgfHxcbiAgICAgIHRoaXMuZGl2aWRlciB8fFxuICAgICAgIXRoaXMuZXZhbHVhdGVJZkZ1bmN0aW9uKHRoaXMuZW5hYmxlZCwgdGhpcy5jdXJyZW50SXRlbSk7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihwdWJsaWMgdGVtcGxhdGU6IFRlbXBsYXRlUmVmPHsgaXRlbTogYW55IH0+LCBwdWJsaWMgZWxlbWVudFJlZjogRWxlbWVudFJlZikgeyB9XG5cbiAgcHVibGljIGV2YWx1YXRlSWZGdW5jdGlvbih2YWx1ZTogYW55LCBpdGVtOiBhbnkpOiBhbnkge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gdmFsdWUoaXRlbSk7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRBY3RpdmVTdHlsZXMoKTogdm9pZCB7XG4gICAgdGhpcy5pc0FjdGl2ZSA9IHRydWU7XG4gIH1cbiAgcHVibGljIHNldEluYWN0aXZlU3R5bGVzKCk6IHZvaWQge1xuICAgIHRoaXMuaXNBY3RpdmUgPSBmYWxzZTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRBY3RpdmVQYXJlbnRTdHlsZXMoKTogdm9pZCB7XG4gICAgdGhpcy5pc0FjdGl2ZVBhcmVudCA9IHRydWU7XG4gIH1cbiAgcHVibGljIHNldEluQWN0aXZlUGFyZW50U3R5bGVzKCk6IHZvaWQge1xuICAgIHRoaXMuaXNBY3RpdmVQYXJlbnQgPSBmYWxzZTtcbiAgfVxuXG4gIHB1YmxpYyB0cmlnZ2VyRXhlY3V0ZShpdGVtOiBhbnksICRldmVudD86IE1vdXNlRXZlbnQgfCBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmV2YWx1YXRlSWZGdW5jdGlvbih0aGlzLmVuYWJsZWQsIGl0ZW0pKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuZXhlY3V0ZS5lbWl0KHsgZXZlbnQ6ICRldmVudCwgaXRlbSB9KTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgSW5qZWN0aW9uVG9rZW4gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuZXhwb3J0IGNvbnN0IENPTlRFWFRfTUVOVV9PUFRJT05TID0gbmV3IEluamVjdGlvblRva2VuKCdDT05URVhUX01FTlVfT1BUSU9OUycpO1xuIiwiaW1wb3J0IHsgQ2xvc2VMZWFmTWVudUV2ZW50LCBJQ29udGV4dE1lbnVDbGlja0V2ZW50IH0gZnJvbSAnLi9jb250ZXh0TWVudS5zZXJ2aWNlJztcbmltcG9ydCB7IE92ZXJsYXlSZWYgfSBmcm9tICdAYW5ndWxhci9jZGsvb3ZlcmxheSc7XG5pbXBvcnQge1xuICAgIEFmdGVyVmlld0luaXQsXG4gICAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgQ29tcG9uZW50LFxuICAgIEVsZW1lbnRSZWYsXG4gICAgSW5qZWN0LFxuICAgIElucHV0LFxuICAgIE9wdGlvbmFsLFxuICAgIFJlbmRlcmVyLFxuICAgIFZpZXdDaGlsZCxcbiAgICBWaWV3Q2hpbGRyZW4sXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyLCBPbkRlc3Ryb3ksIE9uSW5pdCwgT3V0cHV0LCBRdWVyeUxpc3QsIEhvc3RMaXN0ZW5lciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IENvbnRleHRNZW51SXRlbURpcmVjdGl2ZSB9IGZyb20gJy4vY29udGV4dE1lbnUuaXRlbS5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgSUNvbnRleHRNZW51T3B0aW9ucyB9IGZyb20gJy4vY29udGV4dE1lbnUub3B0aW9ucyc7XG5pbXBvcnQgeyBDT05URVhUX01FTlVfT1BUSU9OUyB9IGZyb20gJy4vY29udGV4dE1lbnUudG9rZW5zJztcbmltcG9ydCB7IEFjdGl2ZURlc2NlbmRhbnRLZXlNYW5hZ2VyIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2ExMXknO1xuXG5leHBvcnQgaW50ZXJmYWNlIElMaW5rQ29uZmlnIHtcbiAgY2xpY2s6IChpdGVtOiBhbnksICRldmVudD86IE1vdXNlRXZlbnQpID0+IHZvaWQ7XG4gIGVuYWJsZWQ/OiAoaXRlbTogYW55KSA9PiBib29sZWFuO1xuICBodG1sOiAoaXRlbTogYW55KSA9PiBzdHJpbmc7XG59XG5cbmNvbnN0IEFSUk9XX0xFRlRfS0VZQ09ERSA9IDM3O1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjb250ZXh0LW1lbnUtY29udGVudCcsXG4gIHN0eWxlczogW1xuICAgIGAucGFzc2l2ZSB7XG4gICAgICAgZGlzcGxheTogYmxvY2s7XG4gICAgICAgcGFkZGluZzogM3B4IDIwcHg7XG4gICAgICAgY2xlYXI6IGJvdGg7XG4gICAgICAgZm9udC13ZWlnaHQ6IG5vcm1hbDtcbiAgICAgICBsaW5lLWhlaWdodDogQGxpbmUtaGVpZ2h0LWJhc2U7XG4gICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbiAgICAgfVxuICAgIC5oYXNTdWJNZW51OmJlZm9yZSB7XG4gICAgICBjb250ZW50OiBcIlxcdTI1QjZcIjtcbiAgICAgIGZsb2F0OiByaWdodDtcbiAgICB9XG4gICAgLmFjdGl2ZVBhcmVudCB7XG4gICAgdGV4dC1kZWNvcmF0aW9uOiBub25lO1xuICAgICAgY29sb3I6ICMyNjI2MjY7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjVmNWY1O1xuICAgIH1gLFxuICBdLFxuICB0ZW1wbGF0ZTpcbiAgYDxkaXYgY2xhc3M9XCJkcm9wZG93biBvcGVuIHNob3cgbmd4LWNvbnRleHRtZW51XCIgW25nQ2xhc3NdPVwibWVudUNsYXNzXCIgdGFiaW5kZXg9XCIwXCI+XG4gICAgICA8dWwgI21lbnUgY2xhc3M9XCJkcm9wZG93bi1tZW51IHNob3dcIiBzdHlsZT1cInBvc2l0aW9uOiBzdGF0aWM7IGZsb2F0OiBub25lO1wiIHRhYmluZGV4PVwiMFwiPlxuICAgICAgICA8bGkgI2xpICpuZ0Zvcj1cImxldCBtZW51SXRlbSBvZiBtZW51SXRlbXM7IGxldCBpID0gaW5kZXhcIiBbY2xhc3MuZGlzYWJsZWRdPVwiIWlzTWVudUl0ZW1FbmFibGVkKG1lbnVJdGVtKVwiXG4gICAgICAgICAgICBbY2xhc3MuZGl2aWRlcl09XCJtZW51SXRlbS5kaXZpZGVyXCIgW2NsYXNzLmRyb3Bkb3duLWRpdmlkZXJdPVwidXNlQm9vdHN0cmFwNCAmJiBtZW51SXRlbS5kaXZpZGVyXCJcbiAgICAgICAgICAgIFtjbGFzcy5hY3RpdmVdPVwibWVudUl0ZW0uaXNBY3RpdmUgJiYgaXNNZW51SXRlbUVuYWJsZWQobWVudUl0ZW0pXCJcbiAgICAgICAgICAgIFthdHRyLnJvbGVdPVwibWVudUl0ZW0uZGl2aWRlciA/ICdzZXBhcmF0b3InIDogdW5kZWZpbmVkXCI+XG4gICAgICAgICAgPGEgKm5nSWY9XCIhbWVudUl0ZW0uZGl2aWRlciAmJiAhbWVudUl0ZW0ucGFzc2l2ZVwiIGhyZWYgW2NsYXNzLmRyb3Bkb3duLWl0ZW1dPVwidXNlQm9vdHN0cmFwNFwiXG4gICAgICAgICAgICBbY2xhc3MuYWN0aXZlXT1cIm1lbnVJdGVtLmlzQWN0aXZlICYmIGlzTWVudUl0ZW1FbmFibGVkKG1lbnVJdGVtKVwiXG4gICAgICAgICAgICBbY2xhc3MuYWN0aXZlUGFyZW50XT1cImhpZ2hsaWdodFBhcmVudEl0ZW1zICYmIG1lbnVJdGVtLmlzQWN0aXZlUGFyZW50ICYmIGlzTWVudUl0ZW1FbmFibGVkKG1lbnVJdGVtKVwiXG4gICAgICAgICAgICBbY2xhc3MuZGlzYWJsZWRdPVwidXNlQm9vdHN0cmFwNCAmJiAhaXNNZW51SXRlbUVuYWJsZWQobWVudUl0ZW0pXCIgW2NsYXNzLmhhc1N1Yk1lbnVdPVwiISFtZW51SXRlbS5zdWJNZW51XCJcbiAgICAgICAgICAgIChjbGljayk9XCJvbk1lbnVJdGVtU2VsZWN0KG1lbnVJdGVtLCAkZXZlbnQpXCIgKG1vdXNlZW50ZXIpPVwib25PcGVuU3ViTWVudShtZW51SXRlbSwgJGV2ZW50KVwiPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ1RlbXBsYXRlT3V0bGV0XT1cIm1lbnVJdGVtLnRlbXBsYXRlXCIgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiBpdGVtIH1cIj48L25nLXRlbXBsYXRlPlxuICAgICAgICAgIDwvYT5cblxuICAgICAgICAgIDxzcGFuIChjbGljayk9XCJzdG9wRXZlbnQoJGV2ZW50KVwiIChjb250ZXh0bWVudSk9XCJzdG9wRXZlbnQoJGV2ZW50KVwiIGNsYXNzPVwicGFzc2l2ZVwiXG4gICAgICAgICAgICAgICAgKm5nSWY9XCIhbWVudUl0ZW0uZGl2aWRlciAmJiBtZW51SXRlbS5wYXNzaXZlXCIgW2NsYXNzLmRyb3Bkb3duLWl0ZW1dPVwidXNlQm9vdHN0cmFwNFwiXG4gICAgICAgICAgICAgICAgW2NsYXNzLmRpc2FibGVkXT1cInVzZUJvb3RzdHJhcDQgJiYgIWlzTWVudUl0ZW1FbmFibGVkKG1lbnVJdGVtKVwiPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ1RlbXBsYXRlT3V0bGV0XT1cIm1lbnVJdGVtLnRlbXBsYXRlXCIgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiBpdGVtIH1cIj48L25nLXRlbXBsYXRlPlxuICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPC9saT5cbiAgICAgIDwvdWw+XG4gICAgPC9kaXY+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIENvbnRleHRNZW51Q29udGVudENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95LCBBZnRlclZpZXdJbml0IHtcbiAgQElucHV0KCkgcHVibGljIG1lbnVJdGVtczogQ29udGV4dE1lbnVJdGVtRGlyZWN0aXZlW10gPSBbXTtcbiAgQElucHV0KCkgcHVibGljIGl0ZW06IGFueTtcbiAgQElucHV0KCkgcHVibGljIGV2ZW50OiBNb3VzZUV2ZW50IHwgS2V5Ym9hcmRFdmVudDtcbiAgQElucHV0KCkgcHVibGljIHBhcmVudENvbnRleHRNZW51OiBDb250ZXh0TWVudUNvbnRlbnRDb21wb25lbnQ7XG4gIEBJbnB1dCgpIHB1YmxpYyBtZW51Q2xhc3M6IHN0cmluZztcbiAgQElucHV0KCkgcHVibGljIG92ZXJsYXk6IE92ZXJsYXlSZWY7XG4gIEBJbnB1dCgpIHB1YmxpYyBpc0xlYWYgPSBmYWxzZTtcbiAgQE91dHB1dCgpIHB1YmxpYyBleGVjdXRlOiBFdmVudEVtaXR0ZXI8eyBldmVudDogTW91c2VFdmVudCB8IEtleWJvYXJkRXZlbnQsIGl0ZW06IGFueSwgbWVudUl0ZW06IENvbnRleHRNZW51SXRlbURpcmVjdGl2ZSB9PlxuICAgID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgcHVibGljIG9wZW5TdWJNZW51OiBFdmVudEVtaXR0ZXI8SUNvbnRleHRNZW51Q2xpY2tFdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBwdWJsaWMgY2xvc2VMZWFmTWVudTogRXZlbnRFbWl0dGVyPENsb3NlTGVhZk1lbnVFdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBwdWJsaWMgY2xvc2VBbGxNZW51czogRXZlbnRFbWl0dGVyPHsgZXZlbnQ6IE1vdXNlRXZlbnQgfT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBWaWV3Q2hpbGQoJ21lbnUnKSBwdWJsaWMgbWVudUVsZW1lbnQ6IEVsZW1lbnRSZWY7XG4gIEBWaWV3Q2hpbGRyZW4oJ2xpJykgcHVibGljIG1lbnVJdGVtRWxlbWVudHM6IFF1ZXJ5TGlzdDxFbGVtZW50UmVmPjtcblxuICBwdWJsaWMgYXV0b0ZvY3VzID0gZmFsc2U7XG4gIHB1YmxpYyB1c2VCb290c3RyYXA0ID0gZmFsc2U7XG4gIHB1YmxpYyBoaWdobGlnaHRQYXJlbnRJdGVtcyA9IGZhbHNlO1xuICBwcml2YXRlIF9rZXlNYW5hZ2VyOiBBY3RpdmVEZXNjZW5kYW50S2V5TWFuYWdlcjxDb250ZXh0TWVudUl0ZW1EaXJlY3RpdmU+O1xuICBwcml2YXRlIHN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uID0gbmV3IFN1YnNjcmlwdGlvbigpO1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGNoYW5nZURldGVjdG9yOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBwcml2YXRlIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsXG4gICAgQE9wdGlvbmFsKClcbiAgICBASW5qZWN0KENPTlRFWFRfTUVOVV9PUFRJT05TKSBwcml2YXRlIG9wdGlvbnM6IElDb250ZXh0TWVudU9wdGlvbnMsXG4gICAgcHVibGljIHJlbmRlcmVyOiBSZW5kZXJlcixcbiAgKSB7XG4gICAgaWYgKG9wdGlvbnMpIHtcbiAgICAgIHRoaXMuYXV0b0ZvY3VzID0gb3B0aW9ucy5hdXRvRm9jdXM7XG4gICAgICB0aGlzLnVzZUJvb3RzdHJhcDQgPSBvcHRpb25zLnVzZUJvb3RzdHJhcDQ7XG4gICAgICB0aGlzLmhpZ2hsaWdodFBhcmVudEl0ZW1zID0gb3B0aW9ucy5oaWdobGlnaHRQYXJlbnRJdGVtcztcbiAgICB9XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLm1lbnVJdGVtcy5mb3JFYWNoKG1lbnVJdGVtID0+IHtcbiAgICAgIG1lbnVJdGVtLmN1cnJlbnRJdGVtID0gdGhpcy5pdGVtO1xuICAgICAgdGhpcy5zdWJzY3JpcHRpb24uYWRkKG1lbnVJdGVtLmV4ZWN1dGUuc3Vic2NyaWJlKGV2ZW50ID0+IHRoaXMuZXhlY3V0ZS5lbWl0KHsgLi4uZXZlbnQsIG1lbnVJdGVtIH0pKSk7XG4gICAgfSk7XG4gICAgY29uc3QgcXVlcnlMaXN0ID0gbmV3IFF1ZXJ5TGlzdDxDb250ZXh0TWVudUl0ZW1EaXJlY3RpdmU+KCk7XG4gICAgcXVlcnlMaXN0LnJlc2V0KHRoaXMubWVudUl0ZW1zKTtcbiAgICB0aGlzLl9rZXlNYW5hZ2VyID0gbmV3IEFjdGl2ZURlc2NlbmRhbnRLZXlNYW5hZ2VyPENvbnRleHRNZW51SXRlbURpcmVjdGl2ZT4ocXVlcnlMaXN0KS53aXRoV3JhcCgpO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIGlmICh0aGlzLmF1dG9Gb2N1cykge1xuICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLmZvY3VzKCkpO1xuICAgIH1cbiAgICB0aGlzLm92ZXJsYXkudXBkYXRlUG9zaXRpb24oKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gIH1cblxuICBmb2N1cygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5hdXRvRm9jdXMpIHtcbiAgICAgIHRoaXMubWVudUVsZW1lbnQubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICAgIH1cbiAgfVxuXG4gIHN0b3BFdmVudCgkZXZlbnQ6IE1vdXNlRXZlbnQpIHtcbiAgICAkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH1cblxuICBwdWJsaWMgaXNNZW51SXRlbUVuYWJsZWQobWVudUl0ZW06IENvbnRleHRNZW51SXRlbURpcmVjdGl2ZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmV2YWx1YXRlSWZGdW5jdGlvbihtZW51SXRlbSAmJiBtZW51SXRlbS5lbmFibGVkKTtcbiAgfVxuXG4gIHB1YmxpYyBpc01lbnVJdGVtVmlzaWJsZShtZW51SXRlbTogQ29udGV4dE1lbnVJdGVtRGlyZWN0aXZlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZXZhbHVhdGVJZkZ1bmN0aW9uKG1lbnVJdGVtICYmIG1lbnVJdGVtLnZpc2libGUpO1xuICB9XG5cbiAgcHVibGljIGV2YWx1YXRlSWZGdW5jdGlvbih2YWx1ZTogYW55KTogYW55IHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIHZhbHVlKHRoaXMuaXRlbSk7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHB1YmxpYyBpc0Rpc2FibGVkKGxpbms6IElMaW5rQ29uZmlnKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGxpbmsuZW5hYmxlZCAmJiAhbGluay5lbmFibGVkKHRoaXMuaXRlbSk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6a2V5ZG93bi5BcnJvd0Rvd24nLCBbJyRldmVudCddKVxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6a2V5ZG93bi5BcnJvd1VwJywgWyckZXZlbnQnXSlcbiAgcHVibGljIG9uS2V5RXZlbnQoZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaXNMZWFmKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuX2tleU1hbmFnZXIub25LZXlkb3duKGV2ZW50KTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzprZXlkb3duLkFycm93UmlnaHQnLCBbJyRldmVudCddKVxuICBwdWJsaWMga2V5Ym9hcmRPcGVuU3ViTWVudShldmVudD86IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaXNMZWFmKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuY2FuY2VsRXZlbnQoZXZlbnQpO1xuICAgIGNvbnN0IG1lbnVJdGVtID0gdGhpcy5tZW51SXRlbXNbdGhpcy5fa2V5TWFuYWdlci5hY3RpdmVJdGVtSW5kZXhdO1xuICAgIGlmIChtZW51SXRlbSkge1xuICAgICAgdGhpcy5vbk9wZW5TdWJNZW51KG1lbnVJdGVtKTtcbiAgICB9XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6a2V5ZG93bi5FbnRlcicsIFsnJGV2ZW50J10pXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzprZXlkb3duLlNwYWNlJywgWyckZXZlbnQnXSlcbiAgcHVibGljIGtleWJvYXJkTWVudUl0ZW1TZWxlY3QoZXZlbnQ/OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmlzTGVhZikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmNhbmNlbEV2ZW50KGV2ZW50KTtcbiAgICBjb25zdCBtZW51SXRlbSA9IHRoaXMubWVudUl0ZW1zW3RoaXMuX2tleU1hbmFnZXIuYWN0aXZlSXRlbUluZGV4XTtcbiAgICBpZiAobWVudUl0ZW0pIHtcbiAgICAgIHRoaXMub25NZW51SXRlbVNlbGVjdChtZW51SXRlbSwgZXZlbnQpO1xuICAgIH1cbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzprZXlkb3duLkVzY2FwZScsIFsnJGV2ZW50J10pXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzprZXlkb3duLkFycm93TGVmdCcsIFsnJGV2ZW50J10pXG4gIHB1YmxpYyBvbkNsb3NlTGVhZk1lbnUoZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaXNMZWFmKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuY2FuY2VsRXZlbnQoZXZlbnQpO1xuICAgIHRoaXMuY2xvc2VMZWFmTWVudS5lbWl0KHsgZXhjZXB0Um9vdE1lbnU6IGV2ZW50LmtleUNvZGUgPT09IEFSUk9XX0xFRlRfS0VZQ09ERSwgZXZlbnQgfSk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDpjbGljaycsIFsnJGV2ZW50J10pXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmNvbnRleHRtZW51JywgWyckZXZlbnQnXSlcbiAgcHVibGljIGNsb3NlTWVudShldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGlmIChldmVudC50eXBlID09PSAnY2xpY2snICYmIGV2ZW50LmJ1dHRvbiA9PT0gMikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmNsb3NlQWxsTWVudXMuZW1pdCh7ZXZlbnR9KTtcbiAgfVxuXG4gIHB1YmxpYyBvbk9wZW5TdWJNZW51KG1lbnVJdGVtOiBDb250ZXh0TWVudUl0ZW1EaXJlY3RpdmUsIGV2ZW50PzogTW91c2VFdmVudCB8IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBhbmNob3JFbGVtZW50UmVmID0gdGhpcy5tZW51SXRlbUVsZW1lbnRzLnRvQXJyYXkoKVt0aGlzLl9rZXlNYW5hZ2VyLmFjdGl2ZUl0ZW1JbmRleF07XG4gICAgY29uc3QgYW5jaG9yRWxlbWVudCA9IGFuY2hvckVsZW1lbnRSZWYgJiYgYW5jaG9yRWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xuICAgIGlmICh0aGlzLmhpZ2hsaWdodFBhcmVudEl0ZW1zKSB7IFxuICAgICAgdGhpcy5tZW51SXRlbXMuZm9yRWFjaChpdGVtID0+IGl0ZW0uaXNBY3RpdmVQYXJlbnQgPSAoaXRlbSA9PT0gbWVudUl0ZW0gJiYgbWVudUl0ZW0uc3ViTWVudSkgKTtcbiAgICB9XG4gICAgdGhpcy5vcGVuU3ViTWVudS5lbWl0KHtcbiAgICAgIGFuY2hvckVsZW1lbnQsXG4gICAgICBjb250ZXh0TWVudTogbWVudUl0ZW0uc3ViTWVudSxcbiAgICAgIGV2ZW50LFxuICAgICAgaXRlbTogdGhpcy5pdGVtLFxuICAgICAgcGFyZW50Q29udGV4dE1lbnU6IHRoaXMsXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgb25NZW51SXRlbVNlbGVjdChtZW51SXRlbTogQ29udGV4dE1lbnVJdGVtRGlyZWN0aXZlLCBldmVudDogTW91c2VFdmVudCB8IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIHRoaXMub25PcGVuU3ViTWVudShtZW51SXRlbSwgZXZlbnQpO1xuICAgIGlmICghbWVudUl0ZW0uc3ViTWVudSkge1xuICAgICAgbWVudUl0ZW0udHJpZ2dlckV4ZWN1dGUodGhpcy5pdGVtLCBldmVudCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjYW5jZWxFdmVudChldmVudCk6IHZvaWQge1xuICAgIGlmICghZXZlbnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB0YXJnZXQ6IEhUTUxFbGVtZW50ID0gZXZlbnQudGFyZ2V0O1xuICAgIGlmIChbJ0lOUFVUJywgJ1RFWFRBUkVBJywgJ1NFTEVDVCddLmluZGV4T2YodGFyZ2V0LnRhZ05hbWUpID4gLTEgfHwgdGFyZ2V0LmlzQ29udGVudEVkaXRhYmxlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgT3ZlcmxheSwgT3ZlcmxheVJlZiwgU2Nyb2xsU3RyYXRlZ3lPcHRpb25zIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL292ZXJsYXknO1xuaW1wb3J0IHsgQ29tcG9uZW50UG9ydGFsIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL3BvcnRhbCc7XG5pbXBvcnQgeyBDb21wb25lbnRSZWYsIEluamVjdGFibGUsIEVsZW1lbnRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBDb250ZXh0TWVudUNvbXBvbmVudCB9IGZyb20gJy4vY29udGV4dE1lbnUuY29tcG9uZW50JztcbmltcG9ydCB7IENvbnRleHRNZW51SXRlbURpcmVjdGl2ZSB9IGZyb20gJy4vY29udGV4dE1lbnUuaXRlbS5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgQ29udGV4dE1lbnVDb250ZW50Q29tcG9uZW50IH0gZnJvbSAnLi9jb250ZXh0TWVudUNvbnRlbnQuY29tcG9uZW50JztcblxuZXhwb3J0IGludGVyZmFjZSBJQ29udGV4dE1lbnVDbGlja0V2ZW50IHtcbiAgYW5jaG9yRWxlbWVudD86IEVsZW1lbnQgfCBFdmVudFRhcmdldDtcbiAgY29udGV4dE1lbnU/OiBDb250ZXh0TWVudUNvbXBvbmVudDtcbiAgZXZlbnQ/OiBNb3VzZUV2ZW50IHwgS2V5Ym9hcmRFdmVudDtcbiAgcGFyZW50Q29udGV4dE1lbnU/OiBDb250ZXh0TWVudUNvbnRlbnRDb21wb25lbnQ7XG4gIGl0ZW06IGFueTtcbiAgYWN0aXZlTWVudUl0ZW1JbmRleD86IG51bWJlcjtcbn1cbmV4cG9ydCBpbnRlcmZhY2UgSUNvbnRleHRNZW51Q29udGV4dCBleHRlbmRzIElDb250ZXh0TWVudUNsaWNrRXZlbnQge1xuICBtZW51SXRlbXM6IENvbnRleHRNZW51SXRlbURpcmVjdGl2ZVtdO1xuICBtZW51Q2xhc3M6IHN0cmluZztcbn1cbmV4cG9ydCBpbnRlcmZhY2UgQ2xvc2VMZWFmTWVudUV2ZW50IHtcbiAgZXhjZXB0Um9vdE1lbnU/OiBib29sZWFuO1xuICBldmVudD86IE1vdXNlRXZlbnQgfCBLZXlib2FyZEV2ZW50O1xufVxuZXhwb3J0IGludGVyZmFjZSBPdmVybGF5UmVmV2l0aENvbnRleHRNZW51IGV4dGVuZHMgT3ZlcmxheVJlZiB7XG4gIGNvbnRleHRNZW51PzogQ29udGV4dE1lbnVDb250ZW50Q29tcG9uZW50O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENhbmNlbENvbnRleHRNZW51RXZlbnQge1xuICBldmVudFR5cGU6ICdjYW5jZWwnO1xuICBldmVudD86IE1vdXNlRXZlbnQgfCBLZXlib2FyZEV2ZW50O1xufVxuZXhwb3J0IGludGVyZmFjZSBFeGVjdXRlQ29udGV4dE1lbnVFdmVudCB7XG4gIGV2ZW50VHlwZTogJ2V4ZWN1dGUnO1xuICBldmVudD86IE1vdXNlRXZlbnQgfCBLZXlib2FyZEV2ZW50O1xuICBpdGVtOiBhbnk7XG4gIG1lbnVJdGVtOiBDb250ZXh0TWVudUl0ZW1EaXJlY3RpdmU7XG59XG5leHBvcnQgdHlwZSBDbG9zZUNvbnRleHRNZW51RXZlbnQgPSBFeGVjdXRlQ29udGV4dE1lbnVFdmVudCB8IENhbmNlbENvbnRleHRNZW51RXZlbnQ7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBDb250ZXh0TWVudVNlcnZpY2Uge1xuICBwdWJsaWMgaXNEZXN0cm95aW5nTGVhZk1lbnUgPSBmYWxzZTtcblxuICBwdWJsaWMgc2hvdzogU3ViamVjdDxJQ29udGV4dE1lbnVDbGlja0V2ZW50PiA9IG5ldyBTdWJqZWN0PElDb250ZXh0TWVudUNsaWNrRXZlbnQ+KCk7XG4gIHB1YmxpYyB0cmlnZ2VyQ2xvc2U6IFN1YmplY3Q8Q29udGV4dE1lbnVDb250ZW50Q29tcG9uZW50PiA9IG5ldyBTdWJqZWN0KCk7XG4gIHB1YmxpYyBjbG9zZTogU3ViamVjdDxDbG9zZUNvbnRleHRNZW51RXZlbnQ+ID0gbmV3IFN1YmplY3QoKTtcblxuICBwcml2YXRlIGNvbnRleHRNZW51Q29udGVudDogQ29tcG9uZW50UmVmPENvbnRleHRNZW51Q29udGVudENvbXBvbmVudD47XG4gIHByaXZhdGUgb3ZlcmxheXM6IE92ZXJsYXlSZWZbXSA9IFtdO1xuICBwcml2YXRlIGZha2VFbGVtZW50OiBhbnkgPSB7XG4gICAgZ2V0Qm91bmRpbmdDbGllbnRSZWN0OiAoKTogQ2xpZW50UmVjdCA9PiAoe1xuICAgICAgYm90dG9tOiAwLFxuICAgICAgaGVpZ2h0OiAwLFxuICAgICAgbGVmdDogMCxcbiAgICAgIHJpZ2h0OiAwLFxuICAgICAgdG9wOiAwLFxuICAgICAgd2lkdGg6IDAsXG4gICAgfSlcbiAgfTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIG92ZXJsYXk6IE92ZXJsYXksXG4gICAgcHJpdmF0ZSBzY3JvbGxTdHJhdGVneTogU2Nyb2xsU3RyYXRlZ3lPcHRpb25zLFxuICApIHsgfVxuXG4gIHB1YmxpYyBvcGVuQ29udGV4dE1lbnUoY29udGV4dDogSUNvbnRleHRNZW51Q29udGV4dCkge1xuICAgIGNvbnN0IHsgYW5jaG9yRWxlbWVudCwgZXZlbnQsIHBhcmVudENvbnRleHRNZW51IH0gPSBjb250ZXh0O1xuXG4gICAgaWYgKCFwYXJlbnRDb250ZXh0TWVudSkge1xuICAgICAgY29uc3QgbW91c2VFdmVudCA9IGV2ZW50IGFzIE1vdXNlRXZlbnQ7XG4gICAgICB0aGlzLmZha2VFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCA9ICgpOiBDbGllbnRSZWN0ID0+ICh7XG4gICAgICAgIGJvdHRvbTogbW91c2VFdmVudC5jbGllbnRZLFxuICAgICAgICBoZWlnaHQ6IDAsXG4gICAgICAgIGxlZnQ6IG1vdXNlRXZlbnQuY2xpZW50WCxcbiAgICAgICAgcmlnaHQ6IG1vdXNlRXZlbnQuY2xpZW50WCxcbiAgICAgICAgdG9wOiBtb3VzZUV2ZW50LmNsaWVudFksXG4gICAgICAgIHdpZHRoOiAwLFxuICAgICAgfSk7XG4gICAgICB0aGlzLmNsb3NlQWxsQ29udGV4dE1lbnVzKHsgZXZlbnRUeXBlOiAnY2FuY2VsJywgZXZlbnQgfSk7XG4gICAgICBjb25zdCBwb3NpdGlvblN0cmF0ZWd5ID0gdGhpcy5vdmVybGF5LnBvc2l0aW9uKCkuY29ubmVjdGVkVG8oXG4gICAgICAgIG5ldyBFbGVtZW50UmVmKGFuY2hvckVsZW1lbnQgfHwgdGhpcy5mYWtlRWxlbWVudCksXG4gICAgICAgIHsgb3JpZ2luWDogJ3N0YXJ0Jywgb3JpZ2luWTogJ2JvdHRvbScgfSxcbiAgICAgICAgeyBvdmVybGF5WDogJ3N0YXJ0Jywgb3ZlcmxheVk6ICd0b3AnIH0pXG4gICAgICAgIC53aXRoRmFsbGJhY2tQb3NpdGlvbihcbiAgICAgICAgeyBvcmlnaW5YOiAnc3RhcnQnLCBvcmlnaW5ZOiAndG9wJyB9LFxuICAgICAgICB7IG92ZXJsYXlYOiAnc3RhcnQnLCBvdmVybGF5WTogJ2JvdHRvbScgfSlcbiAgICAgICAgLndpdGhGYWxsYmFja1Bvc2l0aW9uKFxuICAgICAgICB7IG9yaWdpblg6ICdlbmQnLCBvcmlnaW5ZOiAndG9wJyB9LFxuICAgICAgICB7IG92ZXJsYXlYOiAnc3RhcnQnLCBvdmVybGF5WTogJ3RvcCcgfSlcbiAgICAgICAgLndpdGhGYWxsYmFja1Bvc2l0aW9uKFxuICAgICAgICB7IG9yaWdpblg6ICdzdGFydCcsIG9yaWdpblk6ICd0b3AnIH0sXG4gICAgICAgIHsgb3ZlcmxheVg6ICdlbmQnLCBvdmVybGF5WTogJ3RvcCcgfSlcbiAgICAgICAgLndpdGhGYWxsYmFja1Bvc2l0aW9uKFxuICAgICAgICB7IG9yaWdpblg6ICdlbmQnLCBvcmlnaW5ZOiAnY2VudGVyJyB9LFxuICAgICAgICB7IG92ZXJsYXlYOiAnc3RhcnQnLCBvdmVybGF5WTogJ2NlbnRlcicgfSlcbiAgICAgICAgLndpdGhGYWxsYmFja1Bvc2l0aW9uKFxuICAgICAgICB7IG9yaWdpblg6ICdzdGFydCcsIG9yaWdpblk6ICdjZW50ZXInIH0sXG4gICAgICAgIHsgb3ZlcmxheVg6ICdlbmQnLCBvdmVybGF5WTogJ2NlbnRlcicgfSlcbiAgICAgICAgO1xuICAgICAgdGhpcy5vdmVybGF5cyA9IFt0aGlzLm92ZXJsYXkuY3JlYXRlKHtcbiAgICAgICAgcG9zaXRpb25TdHJhdGVneSxcbiAgICAgICAgcGFuZWxDbGFzczogJ25neC1jb250ZXh0bWVudScsXG4gICAgICAgIHNjcm9sbFN0cmF0ZWd5OiB0aGlzLnNjcm9sbFN0cmF0ZWd5LmNsb3NlKCksXG4gICAgICB9KV07XG4gICAgICB0aGlzLmF0dGFjaENvbnRleHRNZW51KHRoaXMub3ZlcmxheXNbMF0sIGNvbnRleHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBwb3NpdGlvblN0cmF0ZWd5ID0gdGhpcy5vdmVybGF5LnBvc2l0aW9uKCkuY29ubmVjdGVkVG8oXG4gICAgICAgIG5ldyBFbGVtZW50UmVmKGV2ZW50ID8gZXZlbnQudGFyZ2V0IDogYW5jaG9yRWxlbWVudCksXG4gICAgICAgIHsgb3JpZ2luWDogJ2VuZCcsIG9yaWdpblk6ICd0b3AnIH0sXG4gICAgICAgIHsgb3ZlcmxheVg6ICdzdGFydCcsIG92ZXJsYXlZOiAndG9wJyB9KVxuICAgICAgICAud2l0aEZhbGxiYWNrUG9zaXRpb24oXG4gICAgICAgIHsgb3JpZ2luWDogJ3N0YXJ0Jywgb3JpZ2luWTogJ3RvcCcgfSxcbiAgICAgICAgeyBvdmVybGF5WDogJ2VuZCcsIG92ZXJsYXlZOiAndG9wJyB9KVxuICAgICAgICAud2l0aEZhbGxiYWNrUG9zaXRpb24oXG4gICAgICAgIHsgb3JpZ2luWDogJ2VuZCcsIG9yaWdpblk6ICdib3R0b20nIH0sXG4gICAgICAgIHsgb3ZlcmxheVg6ICdzdGFydCcsIG92ZXJsYXlZOiAnYm90dG9tJyB9KVxuICAgICAgICAud2l0aEZhbGxiYWNrUG9zaXRpb24oXG4gICAgICAgIHsgb3JpZ2luWDogJ3N0YXJ0Jywgb3JpZ2luWTogJ2JvdHRvbScgfSxcbiAgICAgICAgeyBvdmVybGF5WDogJ2VuZCcsIG92ZXJsYXlZOiAnYm90dG9tJyB9KVxuICAgICAgICA7XG4gICAgICBjb25zdCBuZXdPdmVybGF5ID0gdGhpcy5vdmVybGF5LmNyZWF0ZSh7XG4gICAgICAgIHBvc2l0aW9uU3RyYXRlZ3ksXG4gICAgICAgIHBhbmVsQ2xhc3M6ICduZ3gtY29udGV4dG1lbnUnLFxuICAgICAgICBzY3JvbGxTdHJhdGVneTogdGhpcy5zY3JvbGxTdHJhdGVneS5jbG9zZSgpLFxuICAgICAgfSk7XG4gICAgICB0aGlzLmRlc3Ryb3lTdWJNZW51cyhwYXJlbnRDb250ZXh0TWVudSk7XG4gICAgICB0aGlzLm92ZXJsYXlzID0gdGhpcy5vdmVybGF5cy5jb25jYXQobmV3T3ZlcmxheSk7XG4gICAgICB0aGlzLmF0dGFjaENvbnRleHRNZW51KG5ld092ZXJsYXksIGNvbnRleHQpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhdHRhY2hDb250ZXh0TWVudShvdmVybGF5OiBPdmVybGF5UmVmLCBjb250ZXh0OiBJQ29udGV4dE1lbnVDb250ZXh0KTogdm9pZCB7XG4gICAgY29uc3QgeyBldmVudCwgaXRlbSwgbWVudUl0ZW1zLCBtZW51Q2xhc3MgfSA9IGNvbnRleHQ7XG5cbiAgICBjb25zdCBjb250ZXh0TWVudUNvbnRlbnQ6IENvbXBvbmVudFJlZjxDb250ZXh0TWVudUNvbnRlbnRDb21wb25lbnQ+ID0gb3ZlcmxheS5hdHRhY2gobmV3IENvbXBvbmVudFBvcnRhbChDb250ZXh0TWVudUNvbnRlbnRDb21wb25lbnQpKTtcbiAgICBjb250ZXh0TWVudUNvbnRlbnQuaW5zdGFuY2UuZXZlbnQgPSBldmVudDtcbiAgICBjb250ZXh0TWVudUNvbnRlbnQuaW5zdGFuY2UuaXRlbSA9IGl0ZW07XG4gICAgY29udGV4dE1lbnVDb250ZW50Lmluc3RhbmNlLm1lbnVJdGVtcyA9IG1lbnVJdGVtcztcbiAgICBjb250ZXh0TWVudUNvbnRlbnQuaW5zdGFuY2Uub3ZlcmxheSA9IG92ZXJsYXk7XG4gICAgY29udGV4dE1lbnVDb250ZW50Lmluc3RhbmNlLmlzTGVhZiA9IHRydWU7XG4gICAgY29udGV4dE1lbnVDb250ZW50Lmluc3RhbmNlLm1lbnVDbGFzcyA9IG1lbnVDbGFzcztcbiAgICAoPE92ZXJsYXlSZWZXaXRoQ29udGV4dE1lbnU+b3ZlcmxheSkuY29udGV4dE1lbnUgPSBjb250ZXh0TWVudUNvbnRlbnQuaW5zdGFuY2U7XG5cbiAgICBjb25zdCBzdWJzY3JpcHRpb25zOiBTdWJzY3JpcHRpb24gPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG4gICAgc3Vic2NyaXB0aW9ucy5hZGQoY29udGV4dE1lbnVDb250ZW50Lmluc3RhbmNlLmV4ZWN1dGUuYXNPYnNlcnZhYmxlKClcbiAgICAgIC5zdWJzY3JpYmUoKGV4ZWN1dGVFdmVudCkgPT4gdGhpcy5jbG9zZUFsbENvbnRleHRNZW51cyh7IGV2ZW50VHlwZTogJ2V4ZWN1dGUnLCAuLi5