@blox/material
Version:
Material Components for Angular
331 lines • 45.4 kB
JavaScript
import { ContentChildren, Directive, ElementRef, HostBinding, Input, Renderer2, Output, EventEmitter, HostListener, Inject } from '@angular/core';
import { MDCMenuSurfaceFoundation, util, cssClasses, Corner } from '@material/menu-surface';
import { asBoolean } from '../../utils/value.utils';
import { DOCUMENT } from '@angular/common';
/**
* The `mdcMenuSurface` is a reusable surface that appears above the content of the page
* and can be positioned adjacent to an element. It is required as the surface for an `mdcMenu`
* but can also be used by itself.
*/
export class MdcMenuSurfaceDirective {
constructor(_elm, rndr, doc) {
this._elm = _elm;
this.rndr = rndr;
/** @internal */
this._cls = true;
this._open = false;
this._openFrom = 'ts';
// the anchor to use if no menuAnchor is provided (a direct parent MdcMenuAnchor if available):
/** @internal */
this._parentAnchor = null;
/**
* Assign an (optional) element or `mdcMenuAnchor`. If set the menu
* will position itself relative to this anchor element. Assigning this property is not needed
* if you wrap your surface inside an `mdcMenuAnchor`.
*/
this.menuAnchor = null;
/**
* Assign any `HTMLElement` to this property to use as the viewport instead of
* the window object. The menu will choose to open from the top or bottom, and
* from the left or right, based on the space available inside the viewport.
*
* You should probably not use this property. We only use it to keep the documentation
* snippets on our demo website contained in their window.
*/
this.viewport = null;
/**
* Event emitted when the menu is opened or closed. (When this event is triggered, the
* surface is starting to open/close, but the animation may not have fully completed
* yet).
*/
this.openChange = new EventEmitter();
/**
* Event emitted after the menu has fully opened. When this event is emitted the full
* opening animation has completed, and the menu is visible.
*/
this.afterOpened = new EventEmitter();
/**
* Event emitted after the menu has fully closed. When this event is emitted the full
* closing animation has completed, and the menu is not visible anymore.
*/
this.afterClosed = new EventEmitter();
this._prevFocus = null;
this._hoisted = false;
this._fixed = false;
this._handleBodyClick = (event) => this.handleBodyClick(event);
this.mdcAdapter = {
addClass: (className) => this.rndr.addClass(this._elm.nativeElement, className),
removeClass: (className) => this.rndr.removeClass(this._elm.nativeElement, className),
hasClass: (className) => {
if (className === cssClasses.ROOT)
return true;
if (className === cssClasses.OPEN)
return this._open;
return this._elm.nativeElement.classList.contains(className);
},
hasAnchor: () => !!this._parentAnchor || !!this.menuAnchor,
isElementInContainer: (el) => this._elm.nativeElement.contains(el),
isFocused: () => this.document.activeElement === this._elm.nativeElement,
isRtl: () => getComputedStyle(this._elm.nativeElement).getPropertyValue('direction') === 'rtl',
getInnerDimensions: () => ({ width: this._elm.nativeElement.offsetWidth, height: this._elm.nativeElement.offsetHeight }),
getAnchorDimensions: () => {
const anchor = this.menuAnchor || this._parentAnchor;
if (!anchor)
return null;
if (!this.viewport)
return anchor.getBoundingClientRect();
let viewportRect = this.viewport.getBoundingClientRect();
let anchorRect = anchor.getBoundingClientRect();
return {
bottom: anchorRect.bottom - viewportRect.top,
left: anchorRect.left - viewportRect.left,
right: anchorRect.right - viewportRect.left,
top: anchorRect.top - viewportRect.top,
width: anchorRect.width,
height: anchorRect.height
};
},
getWindowDimensions: () => ({
width: this.viewport ? this.viewport.clientWidth : this.document.defaultView.innerWidth,
height: this.viewport ? this.viewport.clientHeight : this.document.defaultView.innerHeight
}),
getBodyDimensions: () => ({
width: this.viewport ? this.viewport.scrollWidth : this.document.body.clientWidth,
height: this.viewport ? this.viewport.scrollHeight : this.document.body.clientHeight
}),
getWindowScroll: () => ({
x: this.viewport ? this.viewport.scrollLeft : this.document.defaultView.pageXOffset,
y: this.viewport ? this.viewport.scrollTop : this.document.defaultView.pageYOffset
}),
setPosition: (position) => {
let el = this._elm.nativeElement;
this.rndr.setStyle(el, 'left', 'left' in position ? `${position.left}px` : '');
this.rndr.setStyle(el, 'right', 'right' in position ? `${position.right}px` : '');
this.rndr.setStyle(el, 'top', 'top' in position ? `${position.top}px` : '');
this.rndr.setStyle(el, 'bottom', 'bottom' in position ? `${position.bottom}px` : '');
},
setMaxHeight: (height) => this._elm.nativeElement.style.maxHeight = height,
setTransformOrigin: (origin) => this.rndr.setStyle(this._elm.nativeElement, `${util.getTransformPropertyName(this.document.defaultView)}-origin`, origin),
saveFocus: () => this._prevFocus = this.document.activeElement,
restoreFocus: () => this._elm.nativeElement.contains(this.document.activeElement) && this._prevFocus
&& this._prevFocus['focus'] && this._prevFocus['focus'](),
notifyClose: () => {
this.afterClosed.emit();
this.document.removeEventListener('click', this._handleBodyClick);
},
notifyOpen: () => {
this.afterOpened.emit();
this.document.addEventListener('click', this._handleBodyClick);
}
};
/** @docs-private */
this.foundation = null;
this.document = doc; // work around ngc issue https://github.com/angular/angular/issues/20351
}
ngAfterContentInit() {
this.foundation = new MDCMenuSurfaceFoundation(this.mdcAdapter);
this.foundation.init();
this.foundation.setFixedPosition(this._fixed);
this.foundation.setIsHoisted(this._hoisted);
this.updateFoundationCorner();
if (this._open)
this.foundation.open();
}
ngOnDestroy() {
var _a;
// when we're destroying a closing surface, the event listener may not be removed yet:
this.document.removeEventListener('click', this._handleBodyClick);
(_a = this.foundation) === null || _a === void 0 ? void 0 : _a.destroy();
this.foundation = null;
}
/**
* When this input is defined and does not have value false, the menu will be opened,
* otherwise the menu will be closed.
*/
get open() {
return this._open;
}
set open(val) {
var _a, _b;
let newValue = asBoolean(val);
if (newValue !== this._open) {
this._open = newValue;
if (newValue)
(_a = this.foundation) === null || _a === void 0 ? void 0 : _a.open();
else
(_b = this.foundation) === null || _b === void 0 ? void 0 : _b.close();
this.openChange.emit(newValue);
}
}
/** @internal */
closeWithoutFocusRestore() {
var _a;
if (this._open) {
this._open = false;
(_a = this.foundation) === null || _a === void 0 ? void 0 : _a.close(true);
this.openChange.emit(false);
}
}
/**
* Set this value if you want to customize the direction from which the menu will be opened.
* Use `tl` for top-left, `br` for bottom-right, etc.
* When the left/right position depends on the text directionality, use `ts` for top-start,
* `te` for top-end, etc. Start will map to left in left-to-right text directionality, and to
* to right in right-to-left text directionality. End maps the other way around.
* The default value is 'ts'.
*/
get openFrom() {
return this._openFrom;
}
set openFrom(val) {
if (val !== this.openFrom) {
if (['tl', 'tr', 'bl', 'br', 'ts', 'te', 'bs', 'be'].indexOf(val) !== -1)
this._openFrom = val;
else
this._openFrom = 'ts';
this.updateFoundationCorner();
}
}
updateFoundationCorner() {
var _a;
const corner = {
'tl': Corner.TOP_LEFT,
'tr': Corner.TOP_RIGHT,
'bl': Corner.BOTTOM_LEFT,
'br': Corner.BOTTOM_RIGHT,
'ts': Corner.TOP_START,
'te': Corner.TOP_END,
'bs': Corner.BOTTOM_START,
'be': Corner.BOTTOM_END
}[this._openFrom];
(_a = this.foundation) === null || _a === void 0 ? void 0 : _a.setAnchorCorner(corner);
}
/** @internal */
setFoundationAnchorCorner(corner) {
var _a;
(_a = this.foundation) === null || _a === void 0 ? void 0 : _a.setAnchorCorner(corner);
}
/**
* Set to a value other then false to hoist the menu surface to the body so that the position offsets
* are calculated relative to the page and not the anchor. (When a `viewport` is set, hoisting is done to
* the viewport instead of the body).
*/
get hoisted() {
return this._hoisted;
}
set hoisted(val) {
var _a;
let newValue = asBoolean(val);
if (newValue !== this._hoisted) {
this._hoisted = newValue;
(_a = this.foundation) === null || _a === void 0 ? void 0 : _a.setIsHoisted(newValue);
}
}
/**
* Set to a value other then false use fixed positioning, so that the menu stays in the
* same place on the window (or viewport) even if the page (or viewport) is
* scrolled.
*/
get fixed() {
return this._fixed;
}
set fixed(val) {
var _a;
let newValue = asBoolean(val);
if (newValue !== this._fixed) {
this._fixed = newValue;
(_a = this.foundation) === null || _a === void 0 ? void 0 : _a.setFixedPosition(newValue);
}
}
// listened after notifyOpen, listening stopped after notifyClose
/** @internal */
handleBodyClick(event) {
if (this.foundation) {
this.foundation.handleBodyClick(event);
if (this._open && this._open !== this.foundation.isOpen()) { // if just closed:
this._open = false;
this.openChange.emit(false);
}
}
}
/** @internal */
handleKeydow(event) {
if (this.foundation) {
this.foundation.handleKeydown(event);
if (this._open && this._open !== this.foundation.isOpen()) { // if just closed:
this._open = false;
this.openChange.emit(false);
}
}
}
}
MdcMenuSurfaceDirective.decorators = [
{ type: Directive, args: [{
selector: '[mdcMenuSurface],[mdcMenu],[mdcSelectMenu]'
},] }
];
MdcMenuSurfaceDirective.ctorParameters = () => [
{ type: ElementRef },
{ type: Renderer2 },
{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
];
MdcMenuSurfaceDirective.propDecorators = {
_cls: [{ type: HostBinding, args: ['class.mdc-menu-surface',] }],
menuAnchor: [{ type: Input }],
viewport: [{ type: Input }],
openChange: [{ type: Output }],
afterOpened: [{ type: Output }],
afterClosed: [{ type: Output }],
open: [{ type: Input }, { type: HostBinding, args: ['class.mdc-menu-surface--open',] }],
openFrom: [{ type: Input }],
hoisted: [{ type: Input }],
fixed: [{ type: Input }, { type: HostBinding, args: ['class.mdc-menu-surface--fixed',] }],
handleKeydow: [{ type: HostListener, args: ['keydown', ['$event'],] }]
};
/**
* Defines an anchor to position an `mdcMenuSurface` to. If this directive is used as the direct parent of an `mdcMenuSurface`,
* it will automatically be used as the anchor point. (Unless de `mdcMenuSurface` sets another anchor via its `menuAnchor`property).
*/
export class MdcMenuAnchorDirective {
constructor(_elm) {
this._elm = _elm;
/** @internal */
this._cls = true;
}
ngAfterContentInit() {
this.surfaces.changes.subscribe(_ => {
this.setSurfaces(this);
});
this.setSurfaces(this);
}
ngOnDestroy() {
this.setSurfaces(null);
}
setSurfaces(anchor) {
var _a;
(_a = this.surfaces) === null || _a === void 0 ? void 0 : _a.toArray().forEach(surface => {
surface._parentAnchor = anchor;
});
}
/** @internal */
getBoundingClientRect() {
return this._elm.nativeElement.getBoundingClientRect();
}
}
MdcMenuAnchorDirective.decorators = [
{ type: Directive, args: [{
selector: '[mdcMenuAnchor]'
},] }
];
MdcMenuAnchorDirective.ctorParameters = () => [
{ type: ElementRef }
];
MdcMenuAnchorDirective.propDecorators = {
_cls: [{ type: HostBinding, args: ['class.mdc-menu-surface--anchor',] }],
surfaces: [{ type: ContentChildren, args: [MdcMenuSurfaceDirective,] }]
};
export const MENU_SURFACE_DIRECTIVES = [
MdcMenuAnchorDirective,
MdcMenuSurfaceDirective
];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWRjLm1lbnUtc3VyZmFjZS5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy9tZW51LXN1cmZhY2UvbWRjLm1lbnUtc3VyZmFjZS5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFvQixlQUFlLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQzVFLEtBQUssRUFBd0IsU0FBUyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM1RyxPQUFPLEVBQUUsd0JBQXdCLEVBQXlCLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDbkgsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3BELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUUzQzs7OztHQUlHO0FBSUgsTUFBTSxPQUFPLHVCQUF1QjtJQWlIaEMsWUFBb0IsSUFBZ0IsRUFBVSxJQUFlLEVBQW9CLEdBQVE7UUFBckUsU0FBSSxHQUFKLElBQUksQ0FBWTtRQUFVLFNBQUksR0FBSixJQUFJLENBQVc7UUFoSDdELGdCQUFnQjtRQUNnQyxTQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ3BELFVBQUssR0FBRyxLQUFLLENBQUM7UUFDZCxjQUFTLEdBQTBELElBQUksQ0FBQztRQUNoRiwrRkFBK0Y7UUFDL0YsZ0JBQWdCO1FBQ2hCLGtCQUFhLEdBQWtDLElBQUksQ0FBQztRQUNwRDs7OztXQUlHO1FBQ00sZUFBVSxHQUE0QyxJQUFJLENBQUM7UUFDcEU7Ozs7Ozs7V0FPRztRQUNNLGFBQVEsR0FBdUIsSUFBSSxDQUFDO1FBQzdDOzs7O1dBSUc7UUFDZ0IsZUFBVSxHQUEwQixJQUFJLFlBQVksRUFBRSxDQUFDO1FBQzFFOzs7V0FHRztRQUNnQixnQkFB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UyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDakMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMzQixDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0IsQ0FBQztJQUVELFdBQVc7UUFDUCxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzNCLENBQUM7SUFFTyxXQUFXLENBQUMsTUFBcUM7O1FBQ3JELE1BQUEsSUFBSSxDQUFDLFFBQVEsMENBQUUsT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUN2QyxPQUFPLENBQUMsYUFBYSxHQUFHLE1BQU0sQ0FBQztRQUNuQyxDQUFDLEVBQUU7SUFDUCxDQUFDO0lBRUQsZ0JBQWdCO0lBQ1QscUJBQXFCO1FBQ3hCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMscUJBQXFCLEVBQUUsQ0FBQztJQUMzRCxDQUFDOzs7WUEvQkosU0FBUyxTQUFDO2dCQUNQLFFBQVEsRUFBRSxpQkFBaUI7YUFDOUI7OztZQXJTc0QsVUFBVTs7O21CQXdTNUQsV0FBVyxTQUFDLGdDQUFnQzt1QkFFNUMsZUFBZSxTQUFDLHVCQUF1Qjs7QUEyQjVDLE1BQU0sQ0FBQyxNQUFNLHVCQUF1QixHQUFHO0lBQ25DLHNCQUFzQjtJQUN0Qix1QkFBdUI7Q0FDMUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyQ29udGVudEluaXQsIENvbnRlbnRDaGlsZHJlbiwgRGlyZWN0aXZlLCBFbGVtZW50UmVmLCBIb3N0QmluZGluZyxcbiAgSW5wdXQsIE9uRGVzdHJveSwgUXVlcnlMaXN0LCBSZW5kZXJlcjIsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBIb3N0TGlzdGVuZXIsIEluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTURDTWVudVN1cmZhY2VGb3VuZGF0aW9uLCBNRENNZW51U3VyZmFjZUFkYXB0ZXIsIHV0aWwsIGNzc0NsYXNzZXMsIENvcm5lciB9IGZyb20gJ0BtYXRlcmlhbC9tZW51LXN1cmZhY2UnO1xuaW1wb3J0IHsgYXNCb29sZWFuIH0gZnJvbSAnLi4vLi4vdXRpbHMvdmFsdWUudXRpbHMnO1xuaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuXG4vKipcbiAqIFRoZSBgbWRjTWVudVN1cmZhY2VgIGlzIGEgcmV1c2FibGUgc3VyZmFjZSB0aGF0IGFwcGVhcnMgYWJvdmUgdGhlIGNvbnRlbnQgb2YgdGhlIHBhZ2VcbiAqIGFuZCBjYW4gYmUgcG9zaXRpb25lZCBhZGphY2VudCB0byBhbiBlbGVtZW50LiBJdCBpcyByZXF1aXJlZCBhcyB0aGUgc3VyZmFjZSBmb3IgYW4gYG1kY01lbnVgXG4gKiBidXQgY2FuIGFsc28gYmUgdXNlZCBieSBpdHNlbGYuXG4gKi9cbkBEaXJlY3RpdmUoe1xuICAgIHNlbGVjdG9yOiAnW21kY01lbnVTdXJmYWNlXSxbbWRjTWVudV0sW21kY1NlbGVjdE1lbnVdJ1xufSlcbmV4cG9ydCBjbGFzcyBNZGNNZW51U3VyZmFjZURpcmVjdGl2ZSBpbXBsZW1lbnRzIEFmdGVyQ29udGVudEluaXQsIE9uRGVzdHJveSB7XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIEBIb3N0QmluZGluZygnY2xhc3MubWRjLW1lbnUtc3VyZmFjZScpIHJlYWRvbmx5IF9jbHMgPSB0cnVlO1xuICAgIHByaXZhdGUgX29wZW4gPSBmYWxzZTtcbiAgICBwcml2YXRlIF9vcGVuRnJvbTogJ3RsJyB8ICd0cicgfCAnYmwnIHwgJ2JyJyB8ICd0cycgfCAndGUnIHwgJ2JzJyB8ICdiZScgPSAndHMnO1xuICAgIC8vIHRoZSBhbmNob3IgdG8gdXNlIGlmIG5vIG1lbnVBbmNob3IgaXMgcHJvdmlkZWQgKGEgZGlyZWN0IHBhcmVudCBNZGNNZW51QW5jaG9yIGlmIGF2YWlsYWJsZSk6XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF9wYXJlbnRBbmNob3I6IE1kY01lbnVBbmNob3JEaXJlY3RpdmUgfCBudWxsID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBBc3NpZ24gYW4gKG9wdGlvbmFsKSBlbGVtZW50IG9yIGBtZGNNZW51QW5jaG9yYC4gSWYgc2V0IHRoZSBtZW51XG4gICAgICogd2lsbCBwb3NpdGlvbiBpdHNlbGYgcmVsYXRpdmUgdG8gdGhpcyBhbmNob3IgZWxlbWVudC4gQXNzaWduaW5nIHRoaXMgcHJvcGVydHkgaXMgbm90IG5lZWRlZFxuICAgICAqIGlmIHlvdSB3cmFwIHlvdXIgc3VyZmFjZSBpbnNpZGUgYW4gYG1kY01lbnVBbmNob3JgLlxuICAgICAqL1xuICAgIEBJbnB1dCgpIG1lbnVBbmNob3I6IE1kY01lbnVBbmNob3JEaXJlY3RpdmUgfCBFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQXNzaWduIGFueSBgSFRNTEVsZW1lbnRgIHRvIHRoaXMgcHJvcGVydHkgdG8gdXNlIGFzIHRoZSB2aWV3cG9ydCBpbnN0ZWFkIG9mXG4gICAgICogdGhlIHdpbmRvdyBvYmplY3QuIFRoZSBtZW51IHdpbGwgY2hvb3NlIHRvIG9wZW4gZnJvbSB0aGUgdG9wIG9yIGJvdHRvbSwgYW5kXG4gICAgICogZnJvbSB0aGUgbGVmdCBvciByaWdodCwgYmFzZWQgb24gdGhlIHNwYWNlIGF2YWlsYWJsZSBpbnNpZGUgdGhlIHZpZXdwb3J0LlxuICAgICAqIFxuICAgICAqIFlvdSBzaG91bGQgcHJvYmFibHkgbm90IHVzZSB0aGlzIHByb3BlcnR5LiBXZSBvbmx5IHVzZSBpdCB0byBrZWVwIHRoZSBkb2N1bWVudGF0aW9uXG4gICAgICogc25pcHBldHMgb24gb3VyIGRlbW8gd2Vic2l0ZSBjb250YWluZWQgaW4gdGhlaXIgd2luZG93LlxuICAgICAqL1xuICAgIEBJbnB1dCgpIHZpZXdwb3J0OiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEV2ZW50IGVtaXR0ZWQgd2hlbiB0aGUgbWVudSBpcyBvcGVuZWQgb3IgY2xvc2VkLiAoV2hlbiB0aGlzIGV2ZW50IGlzIHRyaWdnZXJlZCwgdGhlXG4gICAgICogc3VyZmFjZSBpcyBzdGFydGluZyB0byBvcGVuL2Nsb3NlLCBidXQgdGhlIGFuaW1hdGlvbiBtYXkgbm90IGhhdmUgZnVsbHkgY29tcGxldGVkXG4gICAgICogeWV0KS5cbiAgICAgKi9cbiAgICBAT3V0cHV0KCkgcmVhZG9ubHkgb3BlbkNoYW5nZTogRXZlbnRFbWl0dGVyPGJvb2xlYW4+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICAgIC8qKlxuICAgICAqIEV2ZW50IGVtaXR0ZWQgYWZ0ZXIgdGhlIG1lbnUgaGFzIGZ1bGx5IG9wZW5lZC4gV2hlbiB0aGlzIGV2ZW50IGlzIGVtaXR0ZWQgdGhlIGZ1bGxcbiAgICAgKiBvcGVuaW5nIGFuaW1hdGlvbiBoYXMgY29tcGxldGVkLCBhbmQgdGhlIG1lbnUgaXMgdmlzaWJsZS5cbiAgICAgKi9cbiAgICBAT3V0cHV0KCkgcmVhZG9ubHkgYWZ0ZXJPcGVuZWQ6IEV2ZW50RW1pdHRlcjx2b2lkPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICAvKipcbiAgICAgKiBFdmVudCBlbWl0dGVkIGFmdGVyIHRoZSBtZW51IGhhcyBmdWxseSBjbG9zZWQuIFdoZW4gdGhpcyBldmVudCBpcyBlbWl0dGVkIHRoZSBmdWxsXG4gICAgICogY2xvc2luZyBhbmltYXRpb24gaGFzIGNvbXBsZXRlZCwgYW5kIHRoZSBtZW51IGlzIG5vdCB2aXNpYmxlIGFueW1vcmUuXG4gICAgICovXG4gICAgQE91dHB1dCgpIHJlYWRvbmx5IGFmdGVyQ2xvc2VkOiBFdmVudEVtaXR0ZXI8dm9pZD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgcHJpdmF0ZSBfcHJldkZvY3VzOiBFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBfaG9pc3RlZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgX2ZpeGVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBfaGFuZGxlQm9keUNsaWNrID0gKGV2ZW50OiBNb3VzZUV2ZW50KSA9PiB0aGlzLmhhbmRsZUJvZHlDbGljayhldmVudCk7XG5cbiAgICBwcml2YXRlIG1kY0FkYXB0ZXI6IE1EQ01lbnVTdXJmYWNlQWRhcHRlciA9IHtcbiAgICAgICAgYWRkQ2xhc3M6IChjbGFzc05hbWU6IHN0cmluZykgPT4gdGhpcy5ybmRyLmFkZENsYXNzKHRoaXMuX2VsbS5uYXRpdmVFbGVtZW50LCBjbGFzc05hbWUpLFxuICAgICAgICByZW1vdmVDbGFzczogKGNsYXNzTmFtZTogc3RyaW5nKSA9PiB0aGlzLnJuZHIucmVtb3ZlQ2xhc3ModGhpcy5fZWxtLm5hdGl2ZUVsZW1lbnQsIGNsYXNzTmFtZSksXG4gICAgICAgIGhhc0NsYXNzOiAoY2xhc3NOYW1lOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgIGlmIChjbGFzc05hbWUgPT09IGNzc0NsYXNzZXMuUk9PVClcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIGlmIChjbGFzc05hbWUgPT09IGNzc0NsYXNzZXMuT1BFTilcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb3BlbjtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9lbG0ubmF0aXZlRWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoY2xhc3NOYW1lKTtcbiAgICAgICAgfSxcbiAgICAgICAgaGFzQW5jaG9yOiAoKSA9PiAhIXRoaXMuX3BhcmVudEFuY2hvciB8fCAhIXRoaXMubWVudUFuY2hvcixcbiAgICAgICAgaXNFbGVtZW50SW5Db250YWluZXI6IChlbDogRWxlbWVudCkgPT4gdGhpcy5fZWxtLm5hdGl2ZUVsZW1lbnQuY29udGFpbnMoZWwpLFxuICAgICAgICBpc0ZvY3VzZWQ6ICgpID0+IHRoaXMuZG9jdW1lbnQuYWN0aXZlRWxlbWVudCA9PT0gdGhpcy5fZWxtLm5hdGl2ZUVsZW1lbnQsXG4gICAgICAgIGlzUnRsOiAoKSA9PiAgZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzLl9lbG0ubmF0aXZlRWxlbWVudCkuZ2V0UHJvcGVydHlWYWx1ZSgnZGlyZWN0aW9uJykgPT09ICdydGwnLFxuICAgICAgICBnZXRJbm5lckRpbWVuc2lvbnM6ICgpID0+ICh7d2lkdGg6IHRoaXMuX2VsbS5uYXRpdmVFbGVtZW50Lm9mZnNldFdpZHRoLCBoZWlnaHQ6IHRoaXMuX2VsbS5uYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodH0pLFxuICAgICAgICBnZXRBbmNob3JEaW1lbnNpb25zOiAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBhbmNob3IgPSB0aGlzLm1lbnVBbmNob3IgfHwgdGhpcy5fcGFyZW50QW5jaG9yO1xuICAgICAgICAgICAgaWYgKCFhbmNob3IpXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICBpZiAoIXRoaXMudmlld3BvcnQpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFuY2hvci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIGxldCB2aWV3cG9ydFJlY3QgPSB0aGlzLnZpZXdwb3J0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgbGV0IGFuY2hvclJlY3QgPSBhbmNob3IuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGJvdHRvbTogYW5jaG9yUmVjdC5ib3R0b20gLSB2aWV3cG9ydFJlY3QudG9wLFxuICAgICAgICAgICAgICAgIGxlZnQ6IGFuY2hvclJlY3QubGVmdCAtIHZpZXdwb3J0UmVjdC5sZWZ0LFxuICAgICAgICAgICAgICAgIHJpZ2h0OiBhbmNob3JSZWN0LnJpZ2h0IC0gdmlld3BvcnRSZWN0LmxlZnQsXG4gICAgICAgICAgICAgICAgdG9wOiBhbmNob3JSZWN0LnRvcCAtIHZpZXdwb3J0UmVjdC50b3AsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGFuY2hvclJlY3Qud2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBhbmNob3JSZWN0LmhlaWdodFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0V2luZG93RGltZW5zaW9uczogKCkgPT4gKHtcbiAgICAgICAgICAgIHdpZHRoOiB0aGlzLnZpZXdwb3J0ID8gdGhpcy52aWV3cG9ydC5jbGllbnRXaWR0aCA6IHRoaXMuZG9jdW1lbnQuZGVmYXVsdFZpZXchLmlubmVyV2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQ6IHRoaXMudmlld3BvcnQgPyB0aGlzLnZpZXdwb3J0LmNsaWVudEhlaWdodCA6IHRoaXMuZG9jdW1lbnQuZGVmYXVsdFZpZXchLmlubmVySGVpZ2h0XG4gICAgICAgIH0pLFxuICAgICAgICBnZXRCb2R5RGltZW5zaW9uczogKCkgPT4gKHtcbiAgICAgICAgICAgIHdpZHRoOiB0aGlzLnZpZXdwb3J0ID8gdGhpcy52aWV3cG9ydC5zY3JvbGxXaWR0aCA6IHRoaXMuZG9jdW1lbnQuYm9keS5jbGllbnRXaWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogdGhpcy52aWV3cG9ydCA/IHRoaXMudmlld3BvcnQuc2Nyb2xsSGVpZ2h0IDogdGhpcy5kb2N1bWVudC5ib2R5LmNsaWVudEhlaWdodH0pLFxuICAgICAgICBnZXRXaW5kb3dTY3JvbGw6ICgpID0+ICh7XG4gICAgICAgICAgICB4OiB0aGlzLnZpZXdwb3J0ID8gdGhpcy52aWV3cG9ydC5zY3JvbGxMZWZ0IDogdGhpcy5kb2N1bWVudC5kZWZhdWx0VmlldyEucGFnZVhPZmZzZXQsXG4gICAgICAgICAgICB5OiB0aGlzLnZpZXdwb3J0ID8gdGhpcy52aWV3cG9ydC5zY3JvbGxUb3AgOiB0aGlzLmRvY3VtZW50LmRlZmF1bHRWaWV3IS5wYWdlWU9mZnNldFxuICAgICAgICB9KSxcbiAgICAgICAgc2V0UG9zaXRpb246IChwb3NpdGlvbikgPT4ge1xuICAgICAgICAgICAgbGV0IGVsID0gdGhpcy5fZWxtLm5hdGl2ZUVsZW1lbnQ7XG4gICAgICAgICAgICB0aGlzLnJuZHIuc2V0U3R5bGUoZWwsICdsZWZ0JywgJ2xlZnQnIGluIHBvc2l0aW9uID8gYCR7cG9zaXRpb24ubGVmdH1weGAgOiAnJyk7XG4gICAgICAgICAgICB0aGlzLnJuZHIuc2V0U3R5bGUoZWwsICdyaWdodCcsICdyaWdodCcgaW4gcG9zaXRpb24gPyBgJHtwb3NpdGlvbi5yaWdodH1weGAgOiAnJyk7XG4gICAgICAgICAgICB0aGlzLnJuZHIuc2V0U3R5bGUoZWwsICd0b3AnLCAndG9wJyBpbiBwb3NpdGlvbiA/IGAke3Bvc2l0aW9uLnRvcH1weGAgOiAnJyk7XG4gICAgICAgICAgICB0aGlzLnJuZHIuc2V0U3R5bGUoZWwsICdib3R0b20nLCAnYm90dG9tJyBpbiBwb3NpdGlvbiA/IGAke3Bvc2l0aW9uLmJvdHRvbX1weGAgOiAnJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHNldE1heEhlaWdodDogKGhlaWdodDogc3RyaW5nKSA9PiB0aGlzLl9lbG0ubmF0aXZlRWxlbWVudC5zdHlsZS5tYXhIZWlnaHQgPSBoZWlnaHQsXG4gICAgICAgIHNldFRyYW5zZm9ybU9yaWdpbjogKG9yaWdpbjogc3RyaW5nKSA9PiB0aGlzLnJuZHIuc2V0U3R5bGUodGhpcy5fZWxtLm5hdGl2ZUVsZW1lbnQsXG4gICAgICAgICAgICBgJHt1dGlsLmdldFRyYW5zZm9ybVByb3BlcnR5TmFtZSh0aGlzLmRvY3VtZW50LmRlZmF1bHRWaWV3ISl9LW9yaWdpbmAsIG9yaWdpbiksXG4gICAgICAgIHNhdmVGb2N1czogKCkgPT4gdGhpcy5fcHJldkZvY3VzID0gdGhpcy5kb2N1bWVudC5hY3RpdmVFbGVtZW50LFxuICAgICAgICByZXN0b3JlRm9jdXM6ICgpID0+IHRoaXMuX2VsbS5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKHRoaXMuZG9jdW1lbnQuYWN0aXZlRWxlbWVudCkgJiYgdGhpcy5fcHJldkZvY3VzXG4gICAgICAgICAgICAmJiAodGhpcy5fcHJldkZvY3VzIGFzIGFueSlbJ2ZvY3VzJ10gJiYgKHRoaXMuX3ByZXZGb2N1cyBhcyBhbnkpWydmb2N1cyddKCksXG4gICAgICAgIG5vdGlmeUNsb3NlOiAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmFmdGVyQ2xvc2VkLmVtaXQoKTtcbiAgICAgICAgICAgIHRoaXMuZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9oYW5kbGVCb2R5Q2xpY2spO1xuICAgICAgICB9LFxuICAgICAgICBub3RpZnlPcGVuOiAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmFmdGVyT3BlbmVkLmVtaXQoKTtcbiAgICAgICAgICAgIHRoaXMuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9oYW5kbGVCb2R5Q2xpY2spO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogQGRvY3MtcHJpdmF0ZSAqL1xuICAgIHByaXZhdGUgZm91bmRhdGlvbjogTURDTWVudVN1cmZhY2VGb3VuZGF0aW9uIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBkb2N1bWVudDogRG9jdW1lbnQ7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9lbG06IEVsZW1lbnRSZWYsIHByaXZhdGUgcm5kcjogUmVuZGVyZXIyLCBASW5qZWN0KERPQ1VNRU5UKSBkb2M6IGFueSkge1xuICAgICAgICB0aGlzLmRvY3VtZW50ID0gZG9jIGFzIERvY3VtZW50OyAvLyB3b3JrIGFyb3VuZCBuZ2MgaXNzdWUgaHR0cHM6Ly9naXRodWIuY29tL2FuZ3VsYXIvYW5ndWxhci9pc3N1ZXMvMjAzNTFcbiAgICB9XG5cbiAgICBuZ0FmdGVyQ29udGVudEluaXQoKSB7XG4gICAgICAgIHRoaXMuZm91bmRhdGlvbiA9IG5ldyBNRENNZW51U3VyZmFjZUZvdW5kYXRpb24odGhpcy5tZGNBZGFwdGVyKTtcbiAgICAgICAgdGhpcy5mb3VuZGF0aW9uLmluaXQoKTtcbiAgICAgICAgdGhpcy5mb3VuZGF0aW9uLnNldEZpeGVkUG9zaXRpb24odGhpcy5fZml4ZWQpO1xuICAgICAgICB0aGlzLmZvdW5kYXRpb24uc2V0SXNIb2lzdGVkKHRoaXMuX2hvaXN0ZWQpO1xuICAgICAgICB0aGlzLnVwZGF0ZUZvdW5kYXRpb25Db3JuZXIoKTtcbiAgICAgICAgaWYgKHRoaXMuX29wZW4pXG4gICAgICAgICAgICB0aGlzLmZvdW5kYXRpb24ub3BlbigpO1xuICAgIH1cbiAgXG4gICAgbmdPbkRlc3Ryb3koKSB7XG4gICAgICAgIC8vIHdoZW4gd2UncmUgZGVzdHJveWluZyBhIGNsb3Npbmcgc3VyZmFjZSwgdGhlIGV2ZW50IGxpc3RlbmVyIG1heSBub3QgYmUgcmVtb3ZlZCB5ZXQ6XG4gICAgICAgIHRoaXMuZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9oYW5kbGVCb2R5Q2xpY2spO1xuICAgICAgICB0aGlzLmZvdW5kYXRpb24/LmRlc3Ryb3koKTtcbiAgICAgICAgdGhpcy5mb3VuZGF0aW9uID0gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGVuIHRoaXMgaW5wdXQgaXMgZGVmaW5lZCBhbmQgZG9lcyBub3QgaGF2ZSB2YWx1ZSBmYWxzZSwgdGhlIG1lbnUgd2lsbCBiZSBvcGVuZWQsXG4gICAgICogb3RoZXJ3aXNlIHRoZSBtZW51IHdpbGwgYmUgY2xvc2VkLlxuICAgICAqL1xuICAgIEBJbnB1dCgpIEBIb3N0QmluZGluZygnY2xhc3MubWRjLW1lbnUtc3VyZmFjZS0tb3BlbicpXG4gICAgZ2V0IG9wZW4oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vcGVuO1xuICAgIH1cbiAgICBcbiAgICBzZXQgb3Blbih2YWw6IGJvb2xlYW4pIHtcbiAgICAgICAgbGV0IG5ld1ZhbHVlID0gYXNCb29sZWFuKHZhbCk7XG4gICAgICAgIGlmIChuZXdWYWx1ZSAhPT0gdGhpcy5fb3Blbikge1xuICAgICAgICAgICAgdGhpcy5fb3BlbiA9IG5ld1ZhbHVlO1xuICAgICAgICAgICAgaWYgKG5ld1ZhbHVlKVxuICAgICAgICAgICAgICAgIHRoaXMuZm91bmRhdGlvbj8ub3BlbigpO1xuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIHRoaXMuZm91bmRhdGlvbj8uY2xvc2UoKTtcbiAgICAgICAgICAgIHRoaXMub3BlbkNoYW5nZS5lbWl0KG5ld1ZhbHVlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9vcGVuOiBib29sZWFuIHwgJyc7XG5cbiAgICAvKiogQGludGVybmFsICovXG4gICAgY2xvc2VXaXRob3V0Rm9jdXNSZXN0b3JlKCkge1xuICAgICAgICBpZiAodGhpcy5fb3Blbikge1xuICAgICAgICAgICAgdGhpcy5fb3BlbiA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5mb3VuZGF0aW9uPy5jbG9zZSh0cnVlKTtcbiAgICAgICAgICAgIHRoaXMub3BlbkNoYW5nZS5lbWl0KGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGlzIHZhbHVlIGlmIHlvdSB3YW50IHRvIGN1c3RvbWl6ZSB0aGUgZGlyZWN0aW9uIGZyb20gd2hpY2ggdGhlIG1lbnUgd2lsbCBiZSBvcGVuZWQuXG4gICAgICogVXNlIGB0bGAgZm9yIHRvcC1sZWZ0LCBgYnJgIGZvciBib3R0b20tcmlnaHQsIGV0Yy5cbiAgICAgKiBXaGVuIHRoZSBsZWZ0L3JpZ2h0IHBvc2l0aW9uIGRlcGVuZHMgb24gdGhlIHRleHQgZGlyZWN0aW9uYWxpdHksIHVzZSBgdHNgIGZvciB0b3Atc3RhcnQsXG4gICAgICogYHRlYCBmb3IgdG9wLWVuZCwgZXRjLiBTdGFydCB3aWxsIG1hcCB0byBsZWZ0IGluIGxlZnQtdG8tcmlnaHQgdGV4dCBkaXJlY3Rpb25hbGl0eSwgYW5kIHRvXG4gICAgICogdG8gcmlnaHQgaW4gcmlnaHQtdG8tbGVmdCB0ZXh0IGRpcmVjdGlvbmFsaXR5LiBFbmQgbWFwcyB0aGUgb3RoZXIgd2F5IGFyb3VuZC5cbiAgICAgKiBUaGUgZGVmYXVsdCB2YWx1ZSBpcyAndHMnLlxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgZ2V0IG9wZW5Gcm9tKCk6ICd0bCcgfCAndHInIHwgJ2JsJyB8ICdicicgfCAndHMnIHwgJ3RlJyB8ICdicycgfCAnYmUnIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29wZW5Gcm9tO1xuICAgIH1cblxuICAgIHNldCBvcGVuRnJvbSh2YWw6ICd0bCcgfCAndHInIHwgJ2JsJyB8ICdicicgfCAndHMnIHwgJ3RlJyB8ICdicycgfCAnYmUnKSB7XG4gICAgICAgIGlmICh2YWwgIT09IHRoaXMub3BlbkZyb20pIHtcbiAgICAgICAgICAgIGlmIChbJ3RsJywgJ3RyJywgJ2JsJywgJ2JyJywgJ3RzJywgJ3RlJywgJ2JzJywgJ2JlJ10uaW5kZXhPZih2YWwpICE9PSAtMSlcbiAgICAgICAgICAgICAgICB0aGlzLl9vcGVuRnJvbSA9IHZhbDtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICB0aGlzLl9vcGVuRnJvbSA9ICd0cyc7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUZvdW5kYXRpb25Db3JuZXIoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgdXBkYXRlRm91bmRhdGlvbkNvcm5lcigpIHtcbiAgICAgICAgY29uc3QgY29ybmVyOiBDb3JuZXIgPSB7XG4gICAgICAgICAgICAndGwnOiBDb3JuZXIuVE9QX0xFRlQsXG4gICAgICAgICAgICAndHInOiBDb3JuZXIuVE9QX1JJR0hULFxuICAgICAgICAgICAgJ2JsJzogQ29ybmVyLkJPVFRPTV9MRUZULFxuICAgICAgICAgICAgJ2JyJzogQ29ybmVyLkJPVFRPTV9SSUdIVCxcbiAgICAgICAgICAgICd0cyc6IENvcm5lci5UT1BfU1RBUlQsXG4gICAgICAgICAgICAndGUnOiBDb3JuZXIuVE9QX0VORCxcbiAgICAgICAgICAgICdicyc6IENvcm5lci5CT1RUT01fU1RBUlQsXG4gICAgICAgICAgICAnYmUnOiBDb3JuZXIuQk9UVE9NX0VORFxuICAgICAgICB9W3RoaXMuX29wZW5Gcm9tXTtcbiAgICAgICAgdGhpcy5mb3VuZGF0aW9uPy5zZXRBbmNob3JDb3JuZXIoY29ybmVyKTtcbiAgICB9XG5cbiAgICAvKiogQGludGVybmFsICovXG4gICAgc2V0Rm91bmRhdGlvbkFuY2hvckNvcm5lcihjb3JuZXI6IENvcm5lcikge1xuICAgICAgICB0aGlzLmZvdW5kYXRpb24/LnNldEFuY2hvckNvcm5lcihjb3JuZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0byBhIHZhbHVlIG90aGVyIHRoZW4gZmFsc2UgdG8gaG9pc3QgdGhlIG1lbnUgc3VyZmFjZSB0byB0aGUgYm9keSBzbyB0aGF0IHRoZSBwb3NpdGlvbiBvZmZzZXRzXG4gICAgICogYXJlIGNhbGN1bGF0ZWQgcmVsYXRpdmUgdG8gdGhlIHBhZ2UgYW5kIG5vdCB0aGUgYW5jaG9yLiAoV2hlbiBhIGB2aWV3cG9ydGAgaXMgc2V0LCBob2lzdGluZyBpcyBkb25lIHRvXG4gICAgICogdGhlIHZpZXdwb3J0IGluc3RlYWQgb2YgdGhlIGJvZHkpLlxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgZ2V0IGhvaXN0ZWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ob2lzdGVkO1xuICAgIH1cblxuICAgIHNldCBob2lzdGVkKHZhbDogYm9vbGVhbikge1xuICAgICAgICBsZXQgbmV3VmFsdWUgPSBhc0Jvb2xlYW4odmFsKTtcbiAgICAgICAgaWYgKG5ld1ZhbHVlICE9PSB0aGlzLl9ob2lzdGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9ob2lzdGVkID0gbmV3VmFsdWU7XG4gICAgICAgICAgICB0aGlzLmZvdW5kYXRpb24/LnNldElzSG9pc3RlZChuZXdWYWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfaG9pc3RlZDogYm9vbGVhbiB8ICcnO1xuXG4gICAgLyoqXG4gICAgICogU2V0IHRvIGEgdmFsdWUgb3RoZXIgdGhlbiBmYWxzZSB1c2UgZml4ZWQgcG9zaXRpb25pbmcsIHNvIHRoYXQgdGhlIG1lbnUgc3RheXMgaW4gdGhlXG4gICAgICogc2FtZSBwbGFjZSBvbiB0aGUgd2luZG93IChvciB2aWV3cG9ydCkgZXZlbiBpZiB0aGUgcGFnZSAob3Igdmlld3BvcnQpIGlzXG4gICAgICogc2Nyb2xsZWQuXG4gICAgICovXG4gICAgQElucHV0KCkgIEBIb3N0QmluZGluZygnY2xhc3MubWRjLW1lbnUtc3VyZmFjZS0tZml4ZWQnKVxuICAgIGdldCBmaXhlZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2ZpeGVkO1xuICAgIH1cblxuICAgIHNldCBmaXhlZCh2YWw6IGJvb2xlYW4pIHtcbiAgICAgICAgbGV0IG5ld1ZhbHVlID0gYXNCb29sZWFuKHZhbCk7XG4gICAgICAgIGlmIChuZXdWYWx1ZSAhPT0gdGhpcy5fZml4ZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2ZpeGVkID0gbmV3VmFsdWU7XG4gICAgICAgICAgICB0aGlzLmZvdW5kYXRpb24/LnNldEZpeGVkUG9zaXRpb24obmV3VmFsdWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX2ZpeGVkOiBib29sZWFuIHwgJyc7XG5cbiAgICAvLyBsaXN0ZW5lZCBhZnRlciBub3RpZnlPcGVuLCBsaXN0ZW5pbmcgc3RvcHBlZCBhZnRlciBub3RpZnlDbG9zZVxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBoYW5kbGVCb2R5Q2xpY2soZXZlbnQ6IE1vdXNlRXZlbnQpIHtcbiAgICAgICAgaWYgKHRoaXMuZm91bmRhdGlvbikge1xuICAgICAgICAgICAgdGhpcy5mb3VuZGF0aW9uLmhhbmRsZUJvZHlDbGljayhldmVudCk7XG4gICAgICAgICAgICBpZiAodGhpcy5fb3BlbiAmJiB0aGlzLl9vcGVuICE9PSB0aGlzLmZvdW5kYXRpb24uaXNPcGVuKCkpIHsvLyBpZiBqdXN0IGNsb3NlZDpcbiAgICAgICAgICAgICAgICB0aGlzLl9vcGVuID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVuQ2hhbmdlLmVtaXQoZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIEBIb3N0TGlzdGVuZXIoJ2tleWRvd24nLCBbJyRldmVudCddKVxuICAgIGhhbmRsZUtleWRvdyhldmVudDogS2V5Ym9hcmRFdmVudCkge1xuICAgICAgICBpZiAodGhpcy5mb3VuZGF0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmZvdW5kYXRpb24uaGFuZGxlS2V5ZG93bihldmVudCk7XG4gICAgICAgICAgICBpZiAodGhpcy5fb3BlbiAmJiB0aGlzLl9vcGVuICE9PSB0aGlzLmZvdW5kYXRpb24uaXNPcGVuKCkpIHsvLyBpZiBqdXN0IGNsb3NlZDpcbiAgICAgICAgICAgICAgICB0aGlzLl9vcGVuID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVuQ2hhbmdlLmVtaXQoZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIERlZmluZXMgYW4gYW5jaG9yIHRvIHBvc2l0aW9uIGFuIGBtZGNNZW51U3VyZmFjZWAgdG8uICBJZiB0aGlzIGRpcmVjdGl2ZSBpcyB1c2VkIGFzIHRoZSBkaXJlY3QgcGFyZW50IG9mIGFuIGBtZGNNZW51U3VyZmFjZWAsXG4gKiBpdCB3aWxsIGF1dG9tYXRpY2FsbHkgYmUgdXNlZCBhcyB0aGUgYW5jaG9yIHBvaW50LiAoVW5sZXNzIGRlIGBtZGNNZW51U3VyZmFjZWAgc2V0cyBhbm90aGVyIGFuY2hvciB2aWEgaXRzIGBtZW51QW5jaG9yYHByb3BlcnR5KS5cbiAqL1xuQERpcmVjdGl2ZSh7XG4gICAgc2VsZWN0b3I6ICdbbWRjTWVudUFuY2hvcl0nXG59KVxuZXhwb3J0IGNsYXNzIE1kY01lbnVBbmNob3JEaXJlY3RpdmUgaW1wbGVtZW50cyBBZnRlckNvbnRlbnRJbml0LCBPbkRlc3Ryb3kge1xuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBASG9zdEJpbmRpbmcoJ2NsYXNzLm1kYy1tZW51LXN1cmZhY2UtLWFuY2hvcicpIHJlYWRvbmx5IF9jbHMgPSB0cnVlO1xuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBAQ29udGVudENoaWxkcmVuKE1kY01lbnVTdXJmYWNlRGlyZWN0aXZlKSBwcml2YXRlIHN1cmZhY2VzPzogUXVlcnlMaXN0PE1kY01lbnVTdXJmYWNlRGlyZWN0aXZlPjtcblxuICAgIGNvbnN0cnVjdG9yKHB1YmxpYyBfZWxtOiBFbGVtZW50UmVmKSB7fVxuXG4gICAgbmdBZnRlckNvbnRlbnRJbml0KCkge1xuICAgICAgICB0aGlzLnN1cmZhY2VzIS5jaGFuZ2VzLnN1YnNjcmliZShfID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3VyZmFjZXModGhpcyk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNldFN1cmZhY2VzKHRoaXMpO1xuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCkge1xuICAgICAgICB0aGlzLnNldFN1cmZhY2VzKG51bGwpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2V0U3VyZmFjZXMoYW5jaG9yOiBNZGNNZW51QW5jaG9yRGlyZWN0aXZlIHwgbnVsbCkge1xuICAgICAgICB0aGlzLnN1cmZhY2VzPy50b0FycmF5KCkuZm9yRWFjaChzdXJmYWNlID0+IHtcbiAgICAgICAgICAgIHN1cmZhY2UuX3BhcmVudEFuY2hvciA9IGFuY2hvcjtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIHB1YmxpYyBnZXRCb3VuZGluZ0NsaWVudFJlY3QoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbG0ubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB9XG59XG5cbmV4cG9ydCBjb25zdCBNRU5VX1NVUkZBQ0VfRElSRUNUSVZFUyA9IFtcbiAgICBNZGNNZW51QW5jaG9yRGlyZWN0aXZlLFxuICAgIE1kY01lbnVTdXJmYWNlRGlyZWN0aXZlXG5dO1xuIl19