ng-material-multilevel-menu-2
Version:
697 lines (685 loc) • 73.4 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/material'), require('@angular/router'), require('@angular/animations'), require('@angular/common')) :
typeof define === 'function' && define.amd ? define('ng-material-multilevel-menu-2', ['exports', '@angular/core', '@angular/material', '@angular/router', '@angular/animations', '@angular/common'], factory) :
(factory((global['ng-material-multilevel-menu-2'] = {}),global.ng.core,global.ng.material,global.ng.router,global.ng.animations,global.ng.common));
}(this, (function (exports,i0,material,router,animations,common) { 'use strict';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var MaterialsModule = /** @class */ (function () {
function MaterialsModule() {
}
MaterialsModule.decorators = [
{ type: i0.NgModule, args: [{
imports: [
material.MatIconModule,
material.MatListModule,
material.MatRippleModule,
],
declarations: [],
exports: [
material.MatIconModule,
material.MatListModule,
material.MatRippleModule,
]
},] },
];
return MaterialsModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var MultilevelMenuService = /** @class */ (function () {
function MultilevelMenuService() {
}
/**
* @return {?}
*/
MultilevelMenuService.prototype.generateId = /**
* @return {?}
*/
function () {
/** @type {?} */
var text = '';
/** @type {?} */
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (var i = 0; i < 20; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
};
/**
* @param {?} nodes
* @return {?}
*/
MultilevelMenuService.prototype.addRandomId = /**
* @param {?} nodes
* @return {?}
*/
function (nodes) {
var _this = this;
nodes.forEach(function (node) {
node.id = _this.generateId();
if (node.items !== undefined) {
_this.addRandomId(node.items);
}
});
};
/**
* @param {?} node
* @param {?} nodeId
* @return {?}
*/
MultilevelMenuService.prototype.recursiveCheckId = /**
* @param {?} node
* @param {?} nodeId
* @return {?}
*/
function (node, nodeId) {
var _this = this;
if (node.id === nodeId) {
return true;
}
else {
if (node.items !== undefined) {
return node.items.some(function (nestedNode) {
return _this.recursiveCheckId(nestedNode, nodeId);
});
}
}
};
/**
* @param {?} nodes
* @param {?} link
* @return {?}
*/
MultilevelMenuService.prototype.recursiveCheckLink = /**
* @param {?} nodes
* @param {?} link
* @return {?}
*/
function (nodes, link) {
for (var nodeIndex = 0; nodeIndex < nodes.length; nodeIndex++) {
/** @type {?} */
var node = nodes[nodeIndex];
for (var key in node) {
if (node.hasOwnProperty(key)) {
if (encodeURI(node.link) === link) {
this.foundLinkObject = node;
}
else {
if (node.items !== undefined) {
this.recursiveCheckLink(node.items, link);
}
}
}
}
}
};
/**
* @param {?} node
* @param {?} link
* @return {?}
*/
MultilevelMenuService.prototype.getMatchedObjectByUrl = /**
* @param {?} node
* @param {?} link
* @return {?}
*/
function (node, link) {
this.recursiveCheckLink(node, link);
return this.foundLinkObject;
};
MultilevelMenuService.decorators = [
{ type: i0.Injectable, args: [{
providedIn: 'root'
},] },
];
/** @nocollapse */ MultilevelMenuService.ngInjectableDef = i0.defineInjectable({ factory: function MultilevelMenuService_Factory() { return new MultilevelMenuService(); }, token: MultilevelMenuService, providedIn: "root" });
return MultilevelMenuService;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/** @type {?} */
var CONSTANT = {
PADDING_AT_START: true,
DEFAULT_CLASS_NAME: "amml-container",
DEFAULT_LIST_CLASS_NAME: "amml-item",
SELECTED_LIST_CLASS_NAME: "selected-amml-item",
DEFAULT_SELECTED_FONT_COLOR: "#1976d2",
DEFAULT_LIST_BACKGROUND_COLOR: "transparent",
DEFAULT_LIST_FONT_COLOR: "rgba(0,0,0,.87)",
ERROR_MESSAGE: "Invalid data for material Multilevel List Component"
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var NgMaterialMultilevelMenuComponent = /** @class */ (function () {
function NgMaterialMultilevelMenuComponent(router$$1, multilevelMenuService) {
this.router = router$$1;
this.multilevelMenuService = multilevelMenuService;
this.configuration = null;
this.selectedItem = new i0.EventEmitter();
this.selectedLabel = new i0.EventEmitter();
this.hasDivider = true;
this.nodeConfig = {
paddingAtStart: true,
listBackgroundColor: null,
fontColor: null,
selectedListFontColor: null,
interfaceWithRoute: null,
collapseOnSelect: null,
highlightOnSelect: false,
rtlLayout: false
};
this.isInvalidConfig = true;
}
/**
* @return {?}
*/
NgMaterialMultilevelMenuComponent.prototype.ngOnChanges = /**
* @return {?}
*/
function () {
this.checkValiddata();
this.detectInvalidConfig();
};
/**
* @return {?}
*/
NgMaterialMultilevelMenuComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
var _this = this;
if (this.configuration !== null &&
this.configuration !== undefined &&
this.configuration !== '' &&
this.configuration.interfaceWithRoute !== null &&
this.configuration.interfaceWithRoute) {
this.router.events.subscribe(function (event) {
if (event instanceof router.NavigationEnd) {
_this.updateNodeByURL(event.url);
}
});
this.updateNodeByURL(this.router.url);
}
};
/**
* @param {?} url
* @return {?}
*/
NgMaterialMultilevelMenuComponent.prototype.updateNodeByURL = /**
* @param {?} url
* @return {?}
*/
function (url) {
/** @type {?} */
var foundNode = this.multilevelMenuService.getMatchedObjectByUrl(this.items, url);
if (foundNode !== undefined &&
foundNode.link !== undefined &&
foundNode.link !== null &&
foundNode.link !== '') {
this.currentNode = foundNode;
this.selectedListItem(foundNode);
}
};
/**
* @return {?}
*/
NgMaterialMultilevelMenuComponent.prototype.checkValiddata = /**
* @return {?}
*/
function () {
if (this.items.length === 0) {
console.warn(CONSTANT.ERROR_MESSAGE);
}
else {
this.items = this.items.filter(function (n) { return !n.hidden; });
this.multilevelMenuService.addRandomId(this.items);
}
};
/**
* @return {?}
*/
NgMaterialMultilevelMenuComponent.prototype.detectInvalidConfig = /**
* @return {?}
*/
function () {
if (this.configuration === null ||
this.configuration === undefined ||
this.configuration === '') {
this.isInvalidConfig = true;
}
else {
this.isInvalidConfig = false;
/** @type {?} */
var config = this.configuration;
if (config.paddingAtStart !== undefined &&
config.paddingAtStart !== null &&
typeof config.paddingAtStart === 'boolean') {
this.nodeConfig.paddingAtStart = config.paddingAtStart;
}
if (config.listBackgroundColor !== '' &&
config.listBackgroundColor !== null &&
config.listBackgroundColor !== undefined) {
this.nodeConfig.listBackgroundColor = config.listBackgroundColor;
}
if (config.fontColor !== '' &&
config.fontColor !== null &&
config.fontColor !== undefined) {
this.nodeConfig.fontColor = config.fontColor;
}
if (config.selectedListFontColor !== '' &&
config.selectedListFontColor !== null &&
config.selectedListFontColor !== undefined) {
this.nodeConfig.selectedListFontColor = config.selectedListFontColor;
}
if (config.interfaceWithRoute !== null &&
config.interfaceWithRoute !== undefined &&
typeof config.interfaceWithRoute === 'boolean') {
this.nodeConfig.interfaceWithRoute = config.interfaceWithRoute;
}
if (config.collapseOnSelect !== null &&
config.collapseOnSelect !== undefined &&
typeof config.collapseOnSelect === 'boolean') {
this.nodeConfig.collapseOnSelect = config.collapseOnSelect;
}
if (config.highlightOnSelect !== null &&
config.highlightOnSelect !== undefined &&
typeof config.highlightOnSelect === 'boolean') {
this.nodeConfig.highlightOnSelect = config.highlightOnSelect;
}
if (config.rtlLayout !== null &&
config.rtlLayout !== undefined &&
typeof config.rtlLayout === 'boolean') {
this.nodeConfig.rtlLayout = config.rtlLayout;
}
}
};
/**
* @return {?}
*/
NgMaterialMultilevelMenuComponent.prototype.getClassName = /**
* @return {?}
*/
function () {
if (this.isInvalidConfig) {
return CONSTANT.DEFAULT_CLASS_NAME;
}
else {
if (this.configuration.classname !== '' &&
this.configuration.classname !== null &&
this.configuration.classname !== undefined) {
return CONSTANT.DEFAULT_CLASS_NAME + " " + this.configuration.classname;
}
else {
return CONSTANT.DEFAULT_CLASS_NAME;
}
}
};
/**
* @return {?}
*/
NgMaterialMultilevelMenuComponent.prototype.getGlobalStyle = /**
* @return {?}
*/
function () {
if (!this.isInvalidConfig) {
/** @type {?} */
var styles = {
background: null
};
if (this.configuration.backgroundColor !== '' &&
this.configuration.backgroundColor !== null &&
this.configuration.backgroundColor !== undefined) {
styles.background = this.configuration.backgroundColor;
}
return styles;
}
};
/**
* @return {?}
*/
NgMaterialMultilevelMenuComponent.prototype.isRtlLayout = /**
* @return {?}
*/
function () {
return this.nodeConfig.rtlLayout;
};
/**
* @param {?} event
* @return {?}
*/
NgMaterialMultilevelMenuComponent.prototype.selectedListItem = /**
* @param {?} event
* @return {?}
*/
function (event) {
this.currentNode = event;
if (event.items === undefined &&
(!event.onSelected || typeof event.onSelected !== 'function')) {
this.selectedItem.emit(event);
}
else {
this.selectedLabel.emit(event);
}
};
NgMaterialMultilevelMenuComponent.decorators = [
{ type: i0.Component, args: [{
selector: 'ng-material-multilevel-menu',
template: "<div [ngClass]=\"getClassName()\" [ngStyle]=\"getGlobalStyle()\" *ngIf='items.length !== 0' [dir]=\"isRtlLayout() ? 'rtl' : 'ltr'\">\n <mat-list>\n <ng-list-item *ngFor=\"let node of items\" [nodeConfiguration]='nodeConfig' [node]='node' [selectedNode]='currentNode' [hasDivider]=\"hasDivider\" (selectedItem)=\"selectedListItem($event)\n \">\n </ng-list-item>\n </mat-list>\n</div>",
styles: [".amml-item{line-height:48px;display:flex;justify-content:space-between;position:relative}.anml-data{width:100%;text-transform:capitalize;display:flex;justify-content:start}.amml-icon-fa{font-size:20px}.amml-icon{line-height:48px}.active{color:#1976d2}div[dir=ltr] .amml-icon{margin-right:15px}div[dir=ltr] .amml-submenu{margin-left:16px}div[dir=rtl] .amml-icon{margin-left:15px}div[dir=rtl] .amml-submenu{margin-right:16px}"]
},] },
];
NgMaterialMultilevelMenuComponent.ctorParameters = function () {
return [
{ type: router.Router },
{ type: MultilevelMenuService }
];
};
NgMaterialMultilevelMenuComponent.propDecorators = {
items: [{ type: i0.Input }],
configuration: [{ type: i0.Input }],
selectedItem: [{ type: i0.Output }],
selectedLabel: [{ type: i0.Output }],
hasDivider: [{ type: i0.Input }]
};
return NgMaterialMultilevelMenuComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var ListItemComponent = /** @class */ (function () {
function ListItemComponent(router$$1, multilevelMenuService) {
var _a;
this.router = router$$1;
this.multilevelMenuService = multilevelMenuService;
this.level = 1;
this.nodeConfiguration = null;
this.selectedItem = new i0.EventEmitter();
this.hasDivider = true;
this.isSelected = false;
this.expanded = false;
this.firstInitializer = false;
this.selectedListClasses = (_a = {},
_a[CONSTANT.DEFAULT_LIST_CLASS_NAME] = true,
_a[CONSTANT.SELECTED_LIST_CLASS_NAME] = false,
_a);
}
/**
* @return {?}
*/
ListItemComponent.prototype.ngOnChanges = /**
* @return {?}
*/
function () {
this.nodeChildren =
this.node && this.node.items
? this.node.items.filter(function (n) { return !n.hidden; })
: [];
if (this.selectedNode !== undefined && this.selectedNode !== null) {
this.setSelectedClass(this.multilevelMenuService.recursiveCheckId(this.node, this.selectedNode.id));
}
};
/**
* @param {?} isFound
* @return {?}
*/
ListItemComponent.prototype.setSelectedClass = /**
* @param {?} isFound
* @return {?}
*/
function (isFound) {
var _a;
if (isFound) {
if (!this.firstInitializer) {
this.expanded = true;
}
this.isSelected =
this.nodeConfiguration.highlightOnSelect ||
this.selectedNode.items === undefined
? true
: false;
}
else {
this.isSelected = false;
if (this.nodeConfiguration.collapseOnSelect) {
this.expanded = false;
}
}
this.selectedListClasses = (_a = {},
_a[CONSTANT.DEFAULT_LIST_CLASS_NAME] = true,
_a[CONSTANT.SELECTED_LIST_CLASS_NAME] = this.isSelected,
_a);
this.setClasses();
};
/**
* @return {?}
*/
ListItemComponent.prototype.getPaddingAtStart = /**
* @return {?}
*/
function () {
return this.nodeConfiguration.paddingAtStart ? true : false;
};
/**
* @return {?}
*/
ListItemComponent.prototype.getListStyle = /**
* @return {?}
*/
function () {
/** @type {?} */
var styles = {
background: CONSTANT.DEFAULT_LIST_BACKGROUND_COLOR,
color: CONSTANT.DEFAULT_LIST_FONT_COLOR
};
if (this.nodeConfiguration.listBackgroundColor !== null) {
styles.background = this.nodeConfiguration.listBackgroundColor;
}
if (this.isSelected) {
this.nodeConfiguration.selectedListFontColor !== null
? (styles.color = this.nodeConfiguration.selectedListFontColor)
: (styles.color = CONSTANT.DEFAULT_SELECTED_FONT_COLOR);
}
else if (this.nodeConfiguration.fontColor !== null) {
styles.color = this.nodeConfiguration.fontColor;
}
return styles;
};
/**
* @param {?} node
* @return {?}
*/
ListItemComponent.prototype.getListIcon = /**
* @param {?} node
* @return {?}
*/
function (node) {
if (node.icon !== null && node.icon !== undefined && node.icon !== '') {
return "icon";
}
else if (node.faIcon !== null &&
node.faIcon !== undefined &&
node.faIcon !== '') {
return "faicon";
}
else if (node.imageIcon !== null &&
node.imageIcon !== undefined &&
node.imageIcon !== '') {
return "imageicon";
}
else {
return "";
}
};
/**
* @return {?}
*/
ListItemComponent.prototype.hasItems = /**
* @return {?}
*/
function () {
return this.nodeChildren.length > 0 ? true : false;
};
/**
* @return {?}
*/
ListItemComponent.prototype.isRtlLayout = /**
* @return {?}
*/
function () {
return this.nodeConfiguration.rtlLayout;
};
/**
* @return {?}
*/
ListItemComponent.prototype.setClasses = /**
* @return {?}
*/
function () {
var _a;
this.classes = (_a = {},
_a['level-' + this.level] = true,
_a['amml-submenu'] = this.hasItems() && this.getPaddingAtStart(),
_a);
};
/**
* @param {?} node
* @return {?}
*/
ListItemComponent.prototype.expand = /**
* @param {?} node
* @return {?}
*/
function (node) {
this.expanded = !this.expanded;
this.firstInitializer = true;
this.setClasses();
if (this.nodeConfiguration.interfaceWithRoute !== null &&
this.nodeConfiguration.interfaceWithRoute &&
node.link !== undefined &&
node.link) {
if (node.externalRedirect !== undefined && node.externalRedirect) {
window.location.href = node.link;
}
else {
this.router.navigate([node.link]);
}
}
else if (node.onSelected && typeof node.onSelected === 'function') {
node.onSelected(node);
this.selectedListItem(node);
}
else if (node.items === undefined ||
this.nodeConfiguration.collapseOnSelect) {
this.selectedListItem(node);
}
};
/**
* @param {?} node
* @return {?}
*/
ListItemComponent.prototype.selectedListItem = /**
* @param {?} node
* @return {?}
*/
function (node) {
this.selectedItem.emit(node);
};
ListItemComponent.decorators = [
{ type: i0.Component, args: [{
selector: 'ng-list-item',
template: "<mat-list-item matRipple [ngClass]=\"selectedListClasses\" *ngIf=\"!node.hidden\" (click)=\"expand(node)\" title=\"{{node.label}}\" [ngStyle]=\"getListStyle()\">\n <div class=\"anml-data\" [dir]=\"isRtlLayout() ? 'rtl' : 'ltr'\">\n <div class=\"icon-container\" [ngSwitch]=\"getListIcon(node)\">\n <span *ngSwitchCase=\"'faicon'\" class=\"amml-icon amml-icon-fa\">\n <i [ngClass]=\"node.faIcon\"></i>\n </span>\n <mat-icon *ngSwitchCase=\"'icon'\" class=\"amml-icon\">\n {{node.icon}}\n </mat-icon>\n <img matListAvatar *ngSwitchCase=\"'imageicon'\" class=\"amml-icon\" src=\"{{node.imageIcon}}\" alt=\"{{node.label}}\" />\n </div>\n <span class=\"label\">{{node.label}}</span>\n </div>\n <ng-container *ngIf='hasItems()'>\n <mat-icon *ngIf='!isRtlLayout()' [@isExpandedLTR]=\"hasItems() && expanded ? 'yes' : 'no'\">\n keyboard_arrow_down\n </mat-icon>\n <mat-icon *ngIf='isRtlLayout()' [@isExpandedRTL]=\"hasItems() && expanded ? 'yes' : 'no'\">\n keyboard_arrow_down\n </mat-icon>\n </ng-container>\n</mat-list-item>\n\n<mat-divider *ngIf=\"hasDivider\"></mat-divider>\n\n<div *ngIf=\"hasItems() && expanded\" [@slideInOut] [dir]=\"isRtlLayout() ? 'rtl' : 'ltr'\" [ngClass]=\"classes\">\n <ng-list-item *ngFor=\"let singleNode of nodeChildren\" [hasDivider]=\"hasDivider\" [nodeConfiguration]='nodeConfiguration' [node]='singleNode' [level]=\"level + 1\" [selectedNode]='selectedNode' (selectedItem)=\"selectedListItem($event)\">\n </ng-list-item>\n</div>",
styles: [".amml-item{line-height:48px;position:relative;cursor:pointer}.anml-data{width:100%;text-transform:capitalize;display:flex;justify-content:start;height:48px}.amml-icon-fa{font-size:20px}.amml-icon,.label{line-height:48px}div[dir=ltr] .amml-icon{margin-right:16px}div[dir=ltr].amml-submenu,div[dir=rtl] .amml-icon{margin-left:16px}div[dir=rtl].amml-submenu{margin-right:16px}"],
animations: [
animations.trigger('slideInOut', [
animations.state('in', animations.style({ height: '*', opacity: 0 })),
animations.transition(':leave', [
animations.style({ height: '*', opacity: 0.2 }),
animations.group([
animations.animate(200, animations.style({ height: 0 })),
animations.animate('200ms ease-out', animations.style({ opacity: 0 }))
])
]),
animations.transition(':enter', [
animations.style({ height: '0', opacity: 0 }),
animations.group([
animations.animate(200, animations.style({ height: '*' })),
animations.animate('400ms ease-out', animations.style({ opacity: 1 }))
])
])
]),
animations.trigger('isExpandedLTR', [
animations.state('no', animations.style({ transform: 'rotate(-90deg)' })),
animations.state('yes', animations.style({ transform: 'rotate(0deg)' })),
animations.transition('no => yes', animations.animate(200)),
animations.transition('yes => no', animations.animate(200))
]),
animations.trigger('isExpandedRTL', [
animations.state('no', animations.style({ transform: 'rotate(90deg)' })),
animations.state('yes', animations.style({ transform: 'rotate(0deg)' })),
animations.transition('no => yes', animations.animate(200)),
animations.transition('yes => no', animations.animate(200))
])
]
},] },
];
ListItemComponent.ctorParameters = function () {
return [
{ type: router.Router },
{ type: MultilevelMenuService }
];
};
ListItemComponent.propDecorators = {
node: [{ type: i0.Input }],
level: [{ type: i0.Input }],
selectedNode: [{ type: i0.Input }],
nodeConfiguration: [{ type: i0.Input }],
selectedItem: [{ type: i0.Output }],
hasDivider: [{ type: i0.Input }]
};
return ListItemComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var NgMaterialMultilevelMenuModule = /** @class */ (function () {
function NgMaterialMultilevelMenuModule() {
}
NgMaterialMultilevelMenuModule.decorators = [
{ type: i0.NgModule, args: [{
imports: [
common.CommonModule,
MaterialsModule
],
declarations: [NgMaterialMultilevelMenuComponent, ListItemComponent],
exports: [NgMaterialMultilevelMenuComponent]
},] },
];
return NgMaterialMultilevelMenuModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
exports.NgMaterialMultilevelMenuModule = NgMaterialMultilevelMenuModule;
exports.ɵd = ListItemComponent;
exports.ɵa = MaterialsModule;
exports.ɵc = MultilevelMenuService;
exports.ɵb = NgMaterialMultilevelMenuComponent;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctbWF0ZXJpYWwtbXVsdGlsZXZlbC1tZW51LTIudW1kLmpzLm1hcCIsInNvdXJjZXMiOlsibmc6Ly9uZy1tYXRlcmlhbC1tdWx0aWxldmVsLW1lbnUtMi9saWIvbWF0ZXJpYWxzLm1vZHVsZS50cyIsIm5nOi8vbmctbWF0ZXJpYWwtbXVsdGlsZXZlbC1tZW51LTIvbGliL211bHRpbGV2ZWwtbWVudS5zZXJ2aWNlLnRzIiwibmc6Ly9uZy1tYXRlcmlhbC1tdWx0aWxldmVsLW1lbnUtMi9saWIvY29uc3RhbnRzLnRzIiwibmc6Ly9uZy1tYXRlcmlhbC1tdWx0aWxldmVsLW1lbnUtMi9saWIvbmctbWF0ZXJpYWwtbXVsdGlsZXZlbC1tZW51LmNvbXBvbmVudC50cyIsIm5nOi8vbmctbWF0ZXJpYWwtbXVsdGlsZXZlbC1tZW51LTIvbGliL2xpc3QtaXRlbS9saXN0LWl0ZW0uY29tcG9uZW50LnRzIiwibmc6Ly9uZy1tYXRlcmlhbC1tdWx0aWxldmVsLW1lbnUtMi9saWIvbmctbWF0ZXJpYWwtbXVsdGlsZXZlbC1tZW51Lm1vZHVsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuaW1wb3J0IHtcclxuICBNYXRJY29uTW9kdWxlLFxyXG4gIE1hdExpc3RNb2R1bGUsXHJcbiAgTWF0UmlwcGxlTW9kdWxlLFxyXG59IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsJztcclxuXHJcbkBOZ01vZHVsZSh7XHJcbiAgaW1wb3J0czogW1xyXG4gICAgTWF0SWNvbk1vZHVsZSxcclxuICAgIE1hdExpc3RNb2R1bGUsXHJcbiAgICBNYXRSaXBwbGVNb2R1bGUsXHJcbiAgXSxcclxuICBkZWNsYXJhdGlvbnM6IFtdLFxyXG4gIGV4cG9ydHM6IFtcclxuICAgIE1hdEljb25Nb2R1bGUsXHJcbiAgICBNYXRMaXN0TW9kdWxlLFxyXG4gICAgTWF0UmlwcGxlTW9kdWxlLFxyXG4gIF1cclxufSlcclxuZXhwb3J0IGNsYXNzIE1hdGVyaWFsc01vZHVsZSB7IH1cclxuIiwiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBNdWx0aWxldmVsTm9kZXMgfSBmcm9tICcuL2FwcC5tb2RlbCc7XHJcblxyXG5ASW5qZWN0YWJsZSh7XHJcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBNdWx0aWxldmVsTWVudVNlcnZpY2Uge1xyXG4gIGZvdW5kTGlua09iamVjdDogTXVsdGlsZXZlbE5vZGVzO1xyXG4gIGdlbmVyYXRlSWQoKTogc3RyaW5nIHtcclxuICAgIGxldCB0ZXh0ID0gJyc7XHJcbiAgICBjb25zdCBwb3NzaWJsZSA9ICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSc7XHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDIwOyBpKyspIHtcclxuICAgICAgdGV4dCArPSBwb3NzaWJsZS5jaGFyQXQoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogcG9zc2libGUubGVuZ3RoKSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdGV4dDtcclxuICB9XHJcbiAgYWRkUmFuZG9tSWQobm9kZXM6IE11bHRpbGV2ZWxOb2Rlc1tdKTogdm9pZCB7XHJcbiAgICBub2Rlcy5mb3JFYWNoKChub2RlOiBNdWx0aWxldmVsTm9kZXMpID0+IHtcclxuICAgICAgbm9kZS5pZCA9IHRoaXMuZ2VuZXJhdGVJZCgpO1xyXG4gICAgICBpZiAobm9kZS5pdGVtcyAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgdGhpcy5hZGRSYW5kb21JZChub2RlLml0ZW1zKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG4gIHJlY3Vyc2l2ZUNoZWNrSWQobm9kZTogTXVsdGlsZXZlbE5vZGVzLCBub2RlSWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKG5vZGUuaWQgPT09IG5vZGVJZCkge1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmIChub2RlLml0ZW1zICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICByZXR1cm4gbm9kZS5pdGVtcy5zb21lKChuZXN0ZWROb2RlOiBNdWx0aWxldmVsTm9kZXMpID0+IHtcclxuICAgICAgICAgIHJldHVybiB0aGlzLnJlY3Vyc2l2ZUNoZWNrSWQobmVzdGVkTm9kZSwgbm9kZUlkKTtcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuICByZWN1cnNpdmVDaGVja0xpbmsobm9kZXM6IE11bHRpbGV2ZWxOb2Rlc1tdLCBsaW5rOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGZvciAobGV0IG5vZGVJbmRleCA9IDA7IG5vZGVJbmRleCA8IG5vZGVzLmxlbmd0aDsgbm9kZUluZGV4KyspIHtcclxuICAgICAgY29uc3Qgbm9kZSA9IG5vZGVzW25vZGVJbmRleF07XHJcbiAgICAgIGZvciAoY29uc3Qga2V5IGluIG5vZGUpIHtcclxuICAgICAgICBpZiAobm9kZS5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XHJcbiAgICAgICAgICBpZiAoZW5jb2RlVVJJKG5vZGUubGluaykgPT09IGxpbmspIHtcclxuICAgICAgICAgICAgdGhpcy5mb3VuZExpbmtPYmplY3QgPSBub2RlO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgaWYgKG5vZGUuaXRlbXMgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgIHRoaXMucmVjdXJzaXZlQ2hlY2tMaW5rKG5vZGUuaXRlbXMsIGxpbmspO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG4gIGdldE1hdGNoZWRPYmplY3RCeVVybChub2RlOiBNdWx0aWxldmVsTm9kZXNbXSwgbGluazogc3RyaW5nKTogTXVsdGlsZXZlbE5vZGVzIHtcclxuICAgIHRoaXMucmVjdXJzaXZlQ2hlY2tMaW5rKG5vZGUsIGxpbmspO1xyXG4gICAgcmV0dXJuIHRoaXMuZm91bmRMaW5rT2JqZWN0O1xyXG4gIH1cclxufVxyXG4iLCJleHBvcnQgY29uc3QgQ09OU1RBTlQgPSB7XHJcbiAgICBQQURESU5HX0FUX1NUQVJUOiB0cnVlLFxyXG4gICAgREVGQVVMVF9DTEFTU19OQU1FOiBgYW1tbC1jb250YWluZXJgLFxyXG4gICAgREVGQVVMVF9MSVNUX0NMQVNTX05BTUU6IGBhbW1sLWl0ZW1gLFxyXG4gICAgU0VMRUNURURfTElTVF9DTEFTU19OQU1FOiBgc2VsZWN0ZWQtYW1tbC1pdGVtYCxcclxuICAgIERFRkFVTFRfU0VMRUNURURfRk9OVF9DT0xPUjogYCMxOTc2ZDJgLFxyXG4gICAgREVGQVVMVF9MSVNUX0JBQ0tHUk9VTkRfQ09MT1I6IGB0cmFuc3BhcmVudGAsXHJcbiAgICBERUZBVUxUX0xJU1RfRk9OVF9DT0xPUjogYHJnYmEoMCwwLDAsLjg3KWAsXHJcbiAgICBFUlJPUl9NRVNTQUdFOiBgSW52YWxpZCBkYXRhIGZvciBtYXRlcmlhbCBNdWx0aWxldmVsIExpc3QgQ29tcG9uZW50YFxyXG59O1xyXG4iLCJpbXBvcnQge1xyXG4gIENvbXBvbmVudCxcclxuICBPbkluaXQsXHJcbiAgT25DaGFuZ2VzLFxyXG4gIElucHV0LFxyXG4gIE91dHB1dCxcclxuICBFdmVudEVtaXR0ZXJcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgUm91dGVyLCBOYXZpZ2F0aW9uRW5kIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcclxuXHJcbmltcG9ydCB7IE11bHRpbGV2ZWxNZW51U2VydmljZSB9IGZyb20gJy4vbXVsdGlsZXZlbC1tZW51LnNlcnZpY2UnO1xyXG5cclxuaW1wb3J0IHsgQ29uZmlndXJhdGlvbiwgTXVsdGlsZXZlbE5vZGVzLCBCYWNrZ3JvdW5kU3R5bGUgfSBmcm9tICcuL2FwcC5tb2RlbCc7XHJcbmltcG9ydCB7IENPTlNUQU5UIH0gZnJvbSAnLi9jb25zdGFudHMnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICduZy1tYXRlcmlhbC1tdWx0aWxldmVsLW1lbnUnLFxyXG4gIHRlbXBsYXRlOiBgPGRpdiBbbmdDbGFzc109XCJnZXRDbGFzc05hbWUoKVwiIFtuZ1N0eWxlXT1cImdldEdsb2JhbFN0eWxlKClcIiAqbmdJZj0naXRlbXMubGVuZ3RoICE9PSAwJyBbZGlyXT1cImlzUnRsTGF5b3V0KCkgPyAncnRsJyA6ICdsdHInXCI+XHJcbiAgICA8bWF0LWxpc3Q+XHJcbiAgICAgICAgPG5nLWxpc3QtaXRlbSAqbmdGb3I9XCJsZXQgbm9kZSBvZiBpdGVtc1wiIFtub2RlQ29uZmlndXJhdGlvbl09J25vZGVDb25maWcnIFtub2RlXT0nbm9kZScgW3NlbGVjdGVkTm9kZV09J2N1cnJlbnROb2RlJyBbaGFzRGl2aWRlcl09XCJoYXNEaXZpZGVyXCIgKHNlbGVjdGVkSXRlbSk9XCJzZWxlY3RlZExpc3RJdGVtKCRldmVudClcclxuICAgIFwiPlxyXG4gICAgICAgIDwvbmctbGlzdC1pdGVtPlxyXG4gICAgPC9tYXQtbGlzdD5cclxuPC9kaXY+YCxcclxuICBzdHlsZXM6IFtgLmFtbWwtaXRlbXtsaW5lLWhlaWdodDo0OHB4O2Rpc3BsYXk6ZmxleDtqdXN0aWZ5LWNvbnRlbnQ6c3BhY2UtYmV0d2Vlbjtwb3NpdGlvbjpyZWxhdGl2ZX0uYW5tbC1kYXRhe3dpZHRoOjEwMCU7dGV4dC10cmFuc2Zvcm06Y2FwaXRhbGl6ZTtkaXNwbGF5OmZsZXg7anVzdGlmeS1jb250ZW50OnN0YXJ0fS5hbW1sLWljb24tZmF7Zm9udC1zaXplOjIwcHh9LmFtbWwtaWNvbntsaW5lLWhlaWdodDo0OHB4fS5hY3RpdmV7Y29sb3I6IzE5NzZkMn1kaXZbZGlyPWx0cl0gLmFtbWwtaWNvbnttYXJnaW4tcmlnaHQ6MTVweH1kaXZbZGlyPWx0cl0gLmFtbWwtc3VibWVudXttYXJnaW4tbGVmdDoxNnB4fWRpdltkaXI9cnRsXSAuYW1tbC1pY29ue21hcmdpbi1sZWZ0OjE1cHh9ZGl2W2Rpcj1ydGxdIC5hbW1sLXN1Ym1lbnV7bWFyZ2luLXJpZ2h0OjE2cHh9YF1cclxufSlcclxuZXhwb3J0IGNsYXNzIE5nTWF0ZXJpYWxNdWx0aWxldmVsTWVudUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcclxuICBASW5wdXQoKSBpdGVtczogTXVsdGlsZXZlbE5vZGVzW107XHJcbiAgQElucHV0KCkgY29uZmlndXJhdGlvbjogQ29uZmlndXJhdGlvbiA9IG51bGw7XHJcbiAgQE91dHB1dCgpIHNlbGVjdGVkSXRlbSA9IG5ldyBFdmVudEVtaXR0ZXI8TXVsdGlsZXZlbE5vZGVzPigpO1xyXG4gIEBPdXRwdXQoKSBzZWxlY3RlZExhYmVsID0gbmV3IEV2ZW50RW1pdHRlcjxNdWx0aWxldmVsTm9kZXM+KCk7XHJcbiAgQElucHV0KCkgaGFzRGl2aWRlciA9IHRydWU7XHJcbiAgY3VycmVudE5vZGU6IE11bHRpbGV2ZWxOb2RlcztcclxuICBub2RlQ29uZmlnOiBDb25maWd1cmF0aW9uID0ge1xyXG4gICAgcGFkZGluZ0F0U3RhcnQ6IHRydWUsXHJcbiAgICBsaXN0QmFja2dyb3VuZENvbG9yOiBudWxsLFxyXG4gICAgZm9udENvbG9yOiBudWxsLFxyXG4gICAgc2VsZWN0ZWRMaXN0Rm9udENvbG9yOiBudWxsLFxyXG4gICAgaW50ZXJmYWNlV2l0aFJvdXRlOiBudWxsLFxyXG4gICAgY29sbGFwc2VPblNlbGVjdDogbnVsbCxcclxuICAgIGhpZ2hsaWdodE9uU2VsZWN0OiBmYWxzZSxcclxuICAgIHJ0bExheW91dDogZmFsc2VcclxuICB9O1xyXG4gIGlzSW52YWxpZENvbmZpZyA9IHRydWU7XHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBwcml2YXRlIHJvdXRlcjogUm91dGVyLFxyXG4gICAgcHJpdmF0ZSBtdWx0aWxldmVsTWVudVNlcnZpY2U6IE11bHRpbGV2ZWxNZW51U2VydmljZVxyXG4gICkge31cclxuICBuZ09uQ2hhbmdlcygpIHtcclxuICAgIHRoaXMuY2hlY2tWYWxpZGRhdGEoKTtcclxuICAgIHRoaXMuZGV0ZWN0SW52YWxpZENvbmZpZygpO1xyXG4gIH1cclxuICBuZ09uSW5pdCgpIHtcclxuICAgIGlmIChcclxuICAgICAgdGhpcy5jb25maWd1cmF0aW9uICE9PSBudWxsICYmXHJcbiAgICAgIHRoaXMuY29uZmlndXJhdGlvbiAhPT0gdW5kZWZpbmVkICYmXHJcbiAgICAgIHRoaXMuY29uZmlndXJhdGlvbiAhPT0gJycgJiZcclxuICAgICAgdGhpcy5jb25maWd1cmF0aW9uLmludGVyZmFjZVdpdGhSb3V0ZSAhPT0gbnVsbCAmJlxyXG4gICAgICB0aGlzLmNvbmZpZ3VyYXRpb24uaW50ZXJmYWNlV2l0aFJvdXRlXHJcbiAgICApIHtcclxuICAgICAgdGhpcy5yb3V0ZXIuZXZlbnRzLnN1YnNjcmliZShldmVudCA9PiB7XHJcbiAgICAgICAgaWYgKGV2ZW50IGluc3RhbmNlb2YgTmF2aWdhdGlvbkVuZCkge1xyXG4gICAgICAgICAgdGhpcy51cGRhdGVOb2RlQnlVUkwoZXZlbnQudXJsKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgICB0aGlzLnVwZGF0ZU5vZGVCeVVSTCh0aGlzLnJvdXRlci51cmwpO1xyXG4gICAgfVxyXG4gIH1cclxuICB1cGRhdGVOb2RlQnlVUkwodXJsOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGNvbnN0IGZvdW5kTm9kZSA9IHRoaXMubXVsdGlsZXZlbE1lbnVTZXJ2aWNlLmdldE1hdGNoZWRPYmplY3RCeVVybChcclxuICAgICAgdGhpcy5pdGVtcyxcclxuICAgICAgdXJsXHJcbiAgICApO1xyXG4gICAgaWYgKFxyXG4gICAgICBmb3VuZE5vZGUgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICBmb3VuZE5vZGUubGluayAhPT0gdW5kZWZpbmVkICYmXHJcbiAgICAgIGZvdW5kTm9kZS5saW5rICE9PSBudWxsICYmXHJcbiAgICAgIGZvdW5kTm9kZS5saW5rICE9PSAnJ1xyXG4gICAgKSB7XHJcbiAgICAgIHRoaXMuY3VycmVudE5vZGUgPSBmb3VuZE5vZGU7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRMaXN0SXRlbShmb3VuZE5vZGUpO1xyXG4gICAgfVxyXG4gIH1cclxuICBjaGVja1ZhbGlkZGF0YSgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLml0ZW1zLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICBjb25zb2xlLndhcm4oQ09OU1RBTlQuRVJST1JfTUVTU0FHRSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLml0ZW1zID0gdGhpcy5pdGVtcy5maWx0ZXIobiA9PiAhbi5oaWRkZW4pO1xyXG4gICAgICB0aGlzLm11bHRpbGV2ZWxNZW51U2VydmljZS5hZGRSYW5kb21JZCh0aGlzLml0ZW1zKTtcclxuICAgIH1cclxuICB9XHJcbiAgZGV0ZWN0SW52YWxpZENvbmZpZygpOiB2b2lkIHtcclxuICAgIGlmIChcclxuICAgICAgdGhpcy5jb25maWd1cmF0aW9uID09PSBudWxsIHx8XHJcbiAgICAgIHRoaXMuY29uZmlndXJhdGlvbiA9PT0gdW5kZWZpbmVkIHx8XHJcbiAgICAgIHRoaXMuY29uZmlndXJhdGlvbiA9PT0gJydcclxuICAgICkge1xyXG4gICAgICB0aGlzLmlzSW52YWxpZENvbmZpZyA9IHRydWU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmlzSW52YWxpZENvbmZpZyA9IGZhbHNlO1xyXG4gICAgICBjb25zdCBjb25maWcgPSB0aGlzLmNvbmZpZ3VyYXRpb247XHJcbiAgICAgIGlmIChcclxuICAgICAgICBjb25maWcucGFkZGluZ0F0U3RhcnQgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgIGNvbmZpZy5wYWRkaW5nQXRTdGFydCAhPT0gbnVsbCAmJlxyXG4gICAgICAgIHR5cGVvZiBjb25maWcucGFkZGluZ0F0U3RhcnQgPT09ICdib29sZWFuJ1xyXG4gICAgICApIHtcclxuICAgICAgICB0aGlzLm5vZGVDb25maWcucGFkZGluZ0F0U3RhcnQgPSBjb25maWcucGFkZGluZ0F0U3RhcnQ7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKFxyXG4gICAgICAgIGNvbmZpZy5saXN0QmFja2dyb3VuZENvbG9yICE9PSAnJyAmJlxyXG4gICAgICAgIGNvbmZpZy5saXN0QmFja2dyb3VuZENvbG9yICE9PSBudWxsICYmXHJcbiAgICAgICAgY29uZmlnLmxpc3RCYWNrZ3JvdW5kQ29sb3IgIT09IHVuZGVmaW5lZFxyXG4gICAgICApIHtcclxuICAgICAgICB0aGlzLm5vZGVDb25maWcubGlzdEJhY2tncm91bmRDb2xvciA9IGNvbmZpZy5saXN0QmFja2dyb3VuZENvbG9yO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChcclxuICAgICAgICBjb25maWcuZm9udENvbG9yICE9PSAnJyAmJlxyXG4gICAgICAgIGNvbmZpZy5mb250Q29sb3IgIT09IG51bGwgJiZcclxuICAgICAgICBjb25maWcuZm9udENvbG9yICE9PSB1bmRlZmluZWRcclxuICAgICAgKSB7XHJcbiAgICAgICAgdGhpcy5ub2RlQ29uZmlnLmZvbnRDb2xvciA9IGNvbmZpZy5mb250Q29sb3I7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKFxyXG4gICAgICAgIGNvbmZpZy5zZWxlY3RlZExpc3RGb250Q29sb3IgIT09ICcnICYmXHJcbiAgICAgICAgY29uZmlnLnNlbGVjdGVkTGlzdEZvbnRDb2xvciAhPT0gbnVsbCAmJlxyXG4gICAgICAgIGNvbmZpZy5zZWxlY3RlZExpc3RGb250Q29sb3IgIT09IHVuZGVmaW5lZFxyXG4gICAgICApIHtcclxuICAgICAgICB0aGlzLm5vZGVDb25maWcuc2VsZWN0ZWRMaXN0Rm9udENvbG9yID0gY29uZmlnLnNlbGVjdGVkTGlzdEZvbnRDb2xvcjtcclxuICAgICAgfVxyXG4gICAgICBpZiAoXHJcbiAgICAgICAgY29uZmlnLmludGVyZmFjZVdpdGhSb3V0ZSAhPT0gbnVsbCAmJlxyXG4gICAgICAgIGNvbmZpZy5pbnRlcmZhY2VXaXRoUm91dGUgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgIHR5cGVvZiBjb25maWcuaW50ZXJmYWNlV2l0aFJvdXRlID09PSAnYm9vbGVhbidcclxuICAgICAgKSB7XHJcbiAgICAgICAgdGhpcy5ub2RlQ29uZmlnLmludGVyZmFjZVdpdGhSb3V0ZSA9IGNvbmZpZy5pbnRlcmZhY2VXaXRoUm91dGU7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKFxyXG4gICAgICAgIGNvbmZpZy5jb2xsYXBzZU9uU2VsZWN0ICE9PSBudWxsICYmXHJcbiAgICAgICAgY29uZmlnLmNvbGxhcHNlT25TZWxlY3QgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgIHR5cGVvZiBjb25maWcuY29sbGFwc2VPblNlbGVjdCA9PT0gJ2Jvb2xlYW4nXHJcbiAgICAgICkge1xyXG4gICAgICAgIHRoaXMubm9kZUNvbmZpZy5jb2xsYXBzZU9uU2VsZWN0ID0gY29uZmlnLmNvbGxhcHNlT25TZWxlY3Q7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKFxyXG4gICAgICAgIGNvbmZpZy5oaWdobGlnaHRPblNlbGVjdCAhPT0gbnVsbCAmJlxyXG4gICAgICAgIGNvbmZpZy5oaWdobGlnaHRPblNlbGVjdCAhPT0gdW5kZWZpbmVkICYmXHJcbiAgICAgICAgdHlwZW9mIGNvbmZpZy5oaWdobGlnaHRPblNlbGVjdCA9PT0gJ2Jvb2xlYW4nXHJcbiAgICAgICkge1xyXG4gICAgICAgIHRoaXMubm9kZUNvbmZpZy5oaWdobGlnaHRPblNlbGVjdCA9IGNvbmZpZy5oaWdobGlnaHRPblNlbGVjdDtcclxuICAgICAgfVxyXG4gICAgICBpZiAoXHJcbiAgICAgICAgY29uZmlnLnJ0bExheW91dCAhPT0gbnVsbCAmJlxyXG4gICAgICAgIGNvbmZpZy5ydGxMYXlvdXQgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgIHR5cGVvZiBjb25maWcucnRsTGF5b3V0ID09PSAnYm9vbGVhbidcclxuICAgICAgKSB7XHJcbiAgICAgICAgdGhpcy5ub2RlQ29uZmlnLnJ0bExheW91dCA9IGNvbmZpZy5ydGxMYXlvdXQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbiAgZ2V0Q2xhc3NOYW1lKCk6IHN0cmluZyB7XHJcbiAgICBpZiAodGhpcy5pc0ludmFsaWRDb25maWcpIHtcclxuICAgICAgcmV0dXJuIENPTlNUQU5ULkRFRkFVTFRfQ0xBU1NfTkFNRTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmIChcclxuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24uY2xhc3NuYW1lICE9PSAnJyAmJlxyXG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5jbGFzc25hbWUgIT09IG51bGwgJiZcclxuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24uY2xhc3NuYW1lICE9PSB1bmRlZmluZWRcclxuICAgICAgKSB7XHJcbiAgICAgICAgcmV0dXJuIGAke0NPTlNUQU5ULkRFRkFVTFRfQ0xBU1NfTkFNRX0gJHt0aGlzLmNvbmZpZ3VyYXRpb24uY2xhc3NuYW1lfWA7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgcmV0dXJuIENPTlNUQU5ULkRFRkFVTFRfQ0xBU1NfTkFNRTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuICBnZXRHbG9iYWxTdHlsZSgpOiBCYWNrZ3JvdW5kU3R5bGUge1xyXG4gICAgaWYgKCF0aGlzLmlzSW52YWxpZENvbmZpZykge1xyXG4gICAgICBjb25zdCBzdHlsZXMgPSB7XHJcbiAgICAgICAgYmFja2dyb3VuZDogbnVsbFxyXG4gICAgICB9O1xyXG4gICAgICBpZiAoXHJcbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLmJhY2tncm91bmRDb2xvciAhPT0gJycgJiZcclxuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24uYmFja2dyb3VuZENvbG9yICE9PSBudWxsICYmXHJcbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLmJhY2tncm91bmRDb2xvciAhPT0gdW5kZWZpbmVkXHJcbiAgICAgICkge1xyXG4gICAgICAgIHN0eWxlcy5iYWNrZ3JvdW5kID0gdGhpcy5jb25maWd1cmF0aW9uLmJhY2tncm91bmRDb2xvcjtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gc3R5bGVzO1xyXG4gICAgfVxyXG4gIH1cclxuICBpc1J0bExheW91dCgpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLm5vZGVDb25maWcucnRsTGF5b3V0O1xyXG4gIH1cclxuICBzZWxlY3RlZExpc3RJdGVtKGV2ZW50OiBNdWx0aWxldmVsTm9kZXMpOiB2b2lkIHtcclxuICAgIHRoaXMuY3VycmVudE5vZGUgPSBldmVudDtcclxuICAgIGlmIChcclxuICAgICAgZXZlbnQuaXRlbXMgPT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAoIWV2ZW50Lm9uU2VsZWN0ZWQgfHwgdHlwZW9mIGV2ZW50Lm9uU2VsZWN0ZWQgIT09ICdmdW5jdGlvbicpXHJcbiAgICApIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZEl0ZW0uZW1pdChldmVudCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnNlbGVjdGVkTGFiZWwuZW1pdChldmVudCk7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7XHJcbiAgQ29tcG9uZW50LFxyXG4gIE9uQ2hhbmdlcyxcclxuICBJbnB1dCxcclxuICBPdXRwdXQsXHJcbiAgRXZlbnRFbWl0dGVyXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XHJcbmltcG9ydCB7XHJcbiAgdHJpZ2dlcixcclxuICBzdHlsZSxcclxuICB0cmFuc2l0aW9uLFxyXG4gIGFuaW1hdGUsXHJcbiAgc3RhdGUsXHJcbiAgZ3JvdXBcclxufSBmcm9tICdAYW5ndWxhci9hbmltYXRpb25zJztcclxuXHJcbmltcG9ydCB7IE11bHRpbGV2ZWxNZW51U2VydmljZSB9IGZyb20gJy4vLi4vbXVsdGlsZXZlbC1tZW51LnNlcnZpY2UnO1xyXG5cclxuaW1wb3J0IHsgQ29uZmlndXJhdGlvbiwgTXVsdGlsZXZlbE5vZGVzLCBMaXN0U3R5bGUgfSBmcm9tICcuLy4uL2FwcC5tb2RlbCc7XHJcbmltcG9ydCB7IENPTlNUQU5UIH0gZnJvbSAnLi8uLi9jb25zdGFudHMnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICduZy1saXN0LWl0ZW0nLFxyXG4gIHRlbXBsYXRlOiBgPG1hdC1saXN0LWl0ZW0gbWF0UmlwcGxlIFtuZ0NsYXNzXT1cInNlbGVjdGVkTGlzdENsYXNzZXNcIiAqbmdJZj1cIiFub2RlLmhpZGRlblwiIChjbGljayk9XCJleHBhbmQobm9kZSlcIiB0aXRsZT1cInt7bm9kZS5sYWJlbH19XCIgW25nU3R5bGVdPVwiZ2V0TGlzdFN0eWxlKClcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJhbm1sLWRhdGFcIiBbZGlyXT1cImlzUnRsTGF5b3V0KCkgPyAncnRsJyA6ICdsdHInXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImljb24tY29udGFpbmVyXCIgW25nU3dpdGNoXT1cImdldExpc3RJY29uKG5vZGUpXCI+XHJcbiAgICAgICAgICAgIDxzcGFuICpuZ1N3aXRjaENhc2U9XCInZmFpY29uJ1wiIGNsYXNzPVwiYW1tbC1pY29uIGFtbWwtaWNvbi1mYVwiPlxyXG4gICAgICAgIDxpIFtuZ0NsYXNzXT1cIm5vZGUuZmFJY29uXCI+PC9pPlxyXG4gICAgICA8L3NwYW4+XHJcbiAgICAgICAgICAgIDxtYXQtaWNvbiAqbmdTd2l0Y2hDYXNlPVwiJ2ljb24nXCIgY2xhc3M9XCJhbW1sLWljb25cIj5cclxuICAgICAgICAgICAgICAgIHt7bm9kZS5pY29ufX1cclxuICAgICAgICAgICAgPC9tYXQtaWNvbj5cclxuICAgICAgICAgICAgPGltZyBtYXRMaXN0QXZhdGFyICpuZ1N3aXRjaENhc2U9XCInaW1hZ2VpY29uJ1wiIGNsYXNzPVwiYW1tbC1pY29uXCIgc3JjPVwie3tub2RlLmltYWdlSWNvbn19XCIgYWx0PVwie3tub2RlLmxhYmVsfX1cIiAvPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDxzcGFuIGNsYXNzPVwibGFiZWxcIj57e25vZGUubGFiZWx9fTwvc3Bhbj5cclxuICAgIDwvZGl2PlxyXG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj0naGFzSXRlbXMoKSc+XHJcbiAgICAgICAgPG1hdC1pY29uICpuZ0lmPSchaXNSdGxMYXlvdXQoKScgW0Bpc0V4cGFuZGVkTFRSXT1cImhhc0l0ZW1zKCkgJiYgZXhwYW5kZWQgPyAneWVzJyA6ICdubydcIj5cclxuICAgICAgICAgICAga2V5Ym9hcmRfYXJyb3dfZG93blxyXG4gICAgICAgIDwvbWF0LWljb24+XHJcbiAgICAgICAgPG1hdC1pY29uICpuZ0lmPSdpc1J0bExheW91dCgpJyBbQGlzRXhwYW5kZWRSVExdPVwiaGFzSXRlbXMoKSAmJiBleHBhbmRlZCA/ICd5ZXMnIDogJ25vJ1wiPlxyXG4gICAgICAgICAgICBrZXlib2FyZF9hcnJvd19kb3duXHJcbiAgICAgICAgPC9tYXQtaWNvbj5cclxuICAgIDwvbmctY29udGFpbmVyPlxyXG48L21hdC1saXN0LWl0ZW0+XHJcblxyXG48bWF0LWRpdmlkZXIgKm5nSWY9XCJoYXNEaXZpZGVyXCI+PC9tYXQtZGl2aWRlcj5cclxuXHJcbjxkaXYgKm5nSWY9XCJoYXNJdGVtcygpICYmIGV4cGFuZGVkXCIgW0BzbGlkZUluT3V0XSBbZGlyXT1cImlzUnRsTGF5b3V0KCkgPyAncnRsJyA6ICdsdHInXCIgW25nQ2xhc3NdPVwiY2xhc3Nlc1wiPlxyXG4gICAgPG5nLWxpc3QtaXRlbSAqbmdGb3I9XCJsZXQgc2luZ2xlTm9kZSBvZiBub2RlQ2hpbGRyZW5cIiBbaGFzRGl2aWRlcl09XCJoYXNEaXZpZGVyXCIgW25vZGVDb25maWd1cmF0aW9uXT0nbm9kZUNvbmZpZ3VyYXRpb24nIFtub2RlXT0nc2luZ2xlTm9kZScgW2xldmVsXT1cImxldmVsICsgMVwiIFtzZWxlY3RlZE5vZGVdPSdzZWxlY3RlZE5vZGUnIChzZWxlY3RlZEl0ZW0pPVwic2VsZWN0ZWRMaXN0SXRlbSgkZXZlbnQpXCI+XHJcbiAgICA8L25nLWxpc3QtaXRlbT5cclxuPC9kaXY+YCxcclxuICBzdHlsZXM6IFtgLmFtbWwtaXRlbXtsaW5lLWhlaWdodDo0OHB4O3Bvc2l0aW9uOnJlbGF0aXZlO2N1cnNvcjpwb2ludGVyfS5hbm1sLWRhdGF7d2lkdGg6MTAwJTt0ZXh0LXRyYW5zZm9ybTpjYXBpdGFsaXplO2Rpc3BsYXk6ZmxleDtqdXN0aWZ5LWNvbnRlbnQ6c3RhcnQ7aGVpZ2h0OjQ4cHh9LmFtbWwtaWNvbi1mYXtmb250LXNpemU6MjBweH0uYW1tbC1pY29uLC5sYWJlbHtsaW5lLWhlaWdodDo0OHB4fWRpdltkaXI9bHRyXSAuYW1tbC1pY29ue21hcmdpbi1yaWdodDoxNnB4fWRpdltkaXI9bHRyXS5hbW1sLXN1Ym1lbnUsZGl2W2Rpcj1ydGxdIC5hbW1sLWljb257bWFyZ2luLWxlZnQ6MTZweH1kaXZbZGlyPXJ0bF0uYW1tbC1zdWJtZW51e21hcmdpbi1yaWdodDoxNnB4fWBdLFxyXG4gIGFuaW1hdGlvbnM6IFtcclxuICAgIHRyaWdnZXIoJ3NsaWRlSW5PdXQnLCBbXHJcbiAgICAgIHN0YXRlKCdpbicsIHN0eWxlKHsgaGVpZ2h0OiAnKicsIG9wYWNpdHk6IDAgfSkpLFxyXG4gICAgICB0cmFuc2l0aW9uKCc6bGVhdmUnLCBbXHJcbiAgICAgICAgc3R5bGUoeyBoZWlnaHQ6ICcqJywgb3BhY2l0eTogMC4yIH0pLFxyXG4gICAgICAgIGdyb3VwKFtcclxuICAgICAgICAgIGFuaW1hdGUoMjAwLCBzdHlsZSh7IGhlaWdodDogMCB9KSksXHJcbiAgICAgICAgICBhbmltYXRlKCcyMDBtcyBlYXNlLW91dCcsIHN0eWxlKHsgb3BhY2l0eTogMCB9KSlcclxuICAgICAgICBdKVxyXG4gICAgICBdKSxcclxuICAgICAgdHJhbnNpdGlvbignOmVudGVyJywgW1xyXG4gICAgICAgIHN0eWxlKHsgaGVpZ2h0OiAnMCcsIG9wYWNpdHk6IDAgfSksXHJcbiAgICAgICAgZ3JvdXAoW1xyXG4gICAgICAgICAgYW5pbWF0ZSgyMDAsIHN0eWxlKHsgaGVpZ2h0OiAnKicgfSkpLFxyXG4gICAgICAgICAgYW5pbWF0ZSgnNDAwbXMgZWFzZS1vdXQnLCBzdHlsZSh7IG9wYWNpdHk6IDEgfSkpXHJcbiAgICAgICAgXSlcclxuICAgICAgXSlcclxuICAgIF0pLFxyXG4gICAgdHJpZ2dlcignaXNFeHBhbmRlZExUUicsIFtcclxuICAgICAgc3RhdGUoJ25vJywgc3R5bGUoeyB0cmFuc2Zvcm06ICdyb3RhdGUoLTkwZGVnKScgfSkpLFxyXG4gICAgICBzdGF0ZSgneWVzJywgc3R5bGUoeyB0cmFuc2Zvcm06ICdyb3RhdGUoMGRlZyknIH0pKSxcclxuXHJcbiAgICAgIHRyYW5zaXRpb24oJ25vID0+IHllcycsIGFuaW1hdGUoMjAwKSksXHJcbiAgICAgIHRyYW5zaXRpb24oJ3llcyA9PiBubycsIGFuaW1hdGUoMjAwKSlcclxuICAgIF0pLFxyXG4gICAgdHJpZ2dlcignaXNFeHBhbmRlZFJUTCcsIFtcclxuICAgICAgc3RhdGUoJ25vJywgc3R5bGUoeyB0cmFuc2Zvcm06ICdyb3RhdGUoOTBkZWcpJyB9KSksXHJcbiAgICAgIHN0YXRlKCd5ZXMnLCBzdHlsZSh7IHRyYW5zZm9ybTogJ3JvdGF0ZSgwZGVnKScgfSkpLFxyXG5cclxuICAgICAgdHJhbnNpdGlvbignbm8gPT4geWVzJywgYW5pbWF0ZSgyMDApKSxcclxuICAgICAgdHJhbnNpdGlvbigneWVzID0+IG5vJywgYW5pbWF0ZSgyMDApKVxyXG4gICAgXSlcclxuICBdXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBMaXN0SXRlbUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcyB7XHJcbiAgQElucHV0KCkgbm9kZTogTXVsdGlsZXZlbE5vZGVzO1xyXG4gIEBJbnB1dCgpIGxldmVsID0gMTtcclxuICBASW5wdXQoKSBzZWxlY3RlZE5vZGU6IE11bHRpbGV2ZWxOb2RlcztcclxuICBASW5wdXQoKSBub2Rl