UNPKG

@blox/material

Version:

Material Components for Angular

425 lines 53 kB
import { ContentChildren, Directive, ElementRef, HostBinding, Inject, Input, NgZone, Renderer2 } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { MDCTopAppBarFoundation, MDCFixedTopAppBarFoundation, MDCShortTopAppBarFoundation } from '@material/top-app-bar';
import { events } from '@material/dom';
import { asBoolean, asBooleanOrNull } from '../../utils/value.utils';
/**
 * A directive for a top-app-bar row. The content of a top-app-bar should always be embedded
 * in <code>mdcTopAppBarRow</code> rows. Multiple rows are allowed, which rows are visible
 * depends on the style of the toolbar, and the scroll position of the content of
 * the page.
 */
export class MdcTopAppBarRowDirective {
    constructor(_elm) {
        this._elm = _elm;
        /** @internal */
        this._cls = true;
    }
}
MdcTopAppBarRowDirective.decorators = [
    { type: Directive, args: [{
                selector: '[mdcTopAppBarRow]'
            },] }
];
MdcTopAppBarRowDirective.ctorParameters = () => [
    { type: ElementRef }
];
MdcTopAppBarRowDirective.propDecorators = {
    _cls: [{ type: HostBinding, args: ['class.mdc-top-app-bar__row',] }]
};
/**
 * A directive for a top-app-bar section. A top-app-bar row should always be composed of
 * <code>mdcTopAppBarSection</code> sections. Multiple sections, with different alignment options,
 * are allowed per row.
 */
export class MdcTopAppBarSectionDirective {
    constructor() {
        /** @internal */
        this._cls = true;
        this._alignEnd = false;
        this._alignStart = false;
    }
    /**
     * Make the section align to the start of the toolbar row (default alignment is to the
     * center).
     */
    get alignStart() {
        return this._alignStart;
    }
    set alignStart(val) {
        this._alignStart = asBoolean(val);
    }
    /**
     * Make the section align to the end of the toolbar row (default alignment is to the
     * center).
     */
    get alignEnd() {
        return this._alignEnd;
    }
    set alignEnd(val) {
        this._alignEnd = asBoolean(val);
    }
}
MdcTopAppBarSectionDirective.decorators = [
    { type: Directive, args: [{
                selector: '[mdcTopAppBarSection]'
            },] }
];
MdcTopAppBarSectionDirective.propDecorators = {
    _cls: [{ type: HostBinding, args: ['class.mdc-top-app-bar__section',] }],
    alignStart: [{ type: Input }, { type: HostBinding, args: ['class.mdc-top-app-bar__section--align-start',] }],
    alignEnd: [{ type: Input }, { type: HostBinding, args: ['class.mdc-top-app-bar__section--align-end',] }]
};
/**
 * This directive adds extra styling to toolbar text that represents the title of the toolbar.
 * The directive should be a child of an element with the <code>mdcTopAppBarSection</code> directive.
 */
export class MdcTopAppBarTitleDirective {
    constructor(_elm) {
        this._elm = _elm;
        /** @internal */
        this._cls = true;
    }
}
MdcTopAppBarTitleDirective.decorators = [
    { type: Directive, args: [{
                selector: '[mdcTopAppBarTitle]'
            },] }
];
MdcTopAppBarTitleDirective.ctorParameters = () => [
    { type: ElementRef }
];
MdcTopAppBarTitleDirective.propDecorators = {
    _cls: [{ type: HostBinding, args: ['class.mdc-top-app-bar__title',] }]
};
/**
 * Directive for the navigation icon of a top-app-bar. Typically placed on the
 * far left (for left-to-right languages). The <code>mdcTopAppBarNavIcon</code>
 * directive should be used on a child of an element with the
 * <code>mdcTopAppBarSection</code> directive. It typically opens a navigation menu
 * or drawer.
 */
export class MdcTopAppBarNavIconDirective {
    constructor(_elm) {
        this._elm = _elm;
        /** @internal */
        this._cls = true;
    }
}
MdcTopAppBarNavIconDirective.decorators = [
    { type: Directive, args: [{
                selector: '[mdcTopAppBarNavIcon]'
            },] }
];
MdcTopAppBarNavIconDirective.ctorParameters = () => [
    { type: ElementRef }
];
MdcTopAppBarNavIconDirective.propDecorators = {
    _cls: [{ type: HostBinding, args: ['class.mdc-top-app-bar__navigation-icon',] }]
};
/**
 * Directive for action items of a top-app-bar. Typically placed on the side
 * opposite the navigation item. The <code>mdcTopAppBarAction</code> directive
 * should be used on a child of an element with the <code>mdcTopAppBarSection</code>
 * directive.
 */
export class MdcTopAppBarActionDirective {
    constructor(_elm) {
        this._elm = _elm;
        /** @internal */
        this._cls = true;
        /**
         * A label for the action item. The value will be applied to both the
         * <code>aria-label</code>, and <code>alt</code> attribute of the item.
         */
        this.label = null;
    }
}
MdcTopAppBarActionDirective.decorators = [
    { type: Directive, args: [{
                selector: '[mdcTopAppBarAction]'
            },] }
];
MdcTopAppBarActionDirective.ctorParameters = () => [
    { type: ElementRef }
];
MdcTopAppBarActionDirective.propDecorators = {
    _cls: [{ type: HostBinding, args: ['class.mdc-top-app-bar__action-item',] }],
    label: [{ type: Input }, { type: HostBinding, args: ['attr.aria-label',] }, { type: HostBinding, args: ['attr.alt',] }]
};
/**
 * A directive for a top-app-bar. All content inside a top-app-bar should be
 * embedded inside <code>mdcTopAppBarRow</code> rows.
 */
export class MdcTopAppBarDirective {
    constructor(_rndr, _elm, zone, doc) {
        this._rndr = _rndr;
        this._elm = _elm;
        this.zone = zone;
        /** @internal */
        this._cls = true;
        this.handleScroll = () => {
            var _a;
            if (this.viewport && (this._type === 'short' || this._type === 'fixed'))
                this._updateViewPort();
            (_a = this.foundation) === null || _a === void 0 ? void 0 : _a.handleTargetScroll();
        };
        this.handleResize = () => {
            var _a;
            if (this.viewport && (this._type === 'short' || this._type === 'fixed'))
                this._updateViewPort();
            (_a = this.foundation) === null || _a === void 0 ? void 0 : _a.handleWindowResize();
        };
        this.updateViewport = () => {
            if (this.viewport && (this._type === 'short' || this._type === 'fixed'))
                this._updateViewPort();
        };
        this._viewport = null;
        this._fixedAdjust = null;
        this._type = 'default';
        this._prominent = false;
        this._dense = false;
        this._collapsedOverride = null;
        this._collapsedState = null;
        this.mdcAdapter = {
            hasClass: (className) => {
                if (className === 'mdc-top-app-bar--short-collapsed')
                    // the foundation uses this during initialisation to determine whether
                    // a short top-app-bar should always be displayed collapsed.
                    // our component instead uses the _collapsed field value to override
                    // the collapsed state
                    return false;
                return this._elm.nativeElement.classList.contains(className);
            },
            addClass: (className) => {
                if (className === 'mdc-top-app-bar--short-collapsed')
                    this._collapsedState = true;
                else if (className !== 'mdc-top-app-bar--short-has-action-item')
                    // we add/remove mdc-top-app-bar--short-has-action-item dynamically based on the actual number of items
                    // this is better than the foundation that looks only at the nr of items during initialisation
                    this._rndr.addClass(this._elm.nativeElement, className);
            },
            removeClass: (className) => {
                if (className === 'mdc-top-app-bar--short-collapsed')
                    this._collapsedState = false;
                else
                    this._rndr.removeClass(this._elm.nativeElement, className);
            },
            setStyle: (property, value) => this._rndr.setStyle(this._elm.nativeElement, property, value),
            getTopAppBarHeight: () => this._elm.nativeElement.clientHeight,
            notifyNavigationIconClicked: () => { },
            getViewportScrollY: () => this._viewport ? this._viewport.scrollTop : this.document.defaultView.pageYOffset,
            getTotalActionItems: () => this._actionItems.length
        };
        this.foundation = null;
        /** @internal */
        this._updateViewPort = () => {
            // simulate 'fixed' relative to view position of parent:
            this._elm.nativeElement.style.top = this._viewport.scrollTop + 'px';
        };
        this.document = doc;
    }
    ngAfterContentInit() {
        this.foundationReInit();
    }
    ngOnDestroy() {
        var _a;
        this.removeScrollListeners();
        (_a = this.foundation) === null || _a === void 0 ? void 0 : _a.destroy();
        this.foundation = null;
    }
    foundationReInit() {
        if (this.foundation)
            this.foundation.destroy();
        // undo viewport init specific for a foundation implementation:
        this.removeScrollListeners();
        this._elm.nativeElement.style.top = null;
        // remove classes set by foundations, if we reinitialize/switch foundation:
        this._rndr.removeClass(this._elm.nativeElement, 'mdc-top-app-bar--fixed-scrolled');
        if (this._type === 'short')
            this.foundation = new MDCShortTopAppBarFoundation(this.mdcAdapter);
        else if (this._type === 'fixed')
            this.foundation = new MDCFixedTopAppBarFoundation(this.mdcAdapter);
        else
            this.foundation = new MDCTopAppBarFoundation(this.mdcAdapter);
        this.initFixedAdjust();
        this.zone.runOutsideAngular(() => {
            (this._viewport || this.document.defaultView).addEventListener('scroll', this.handleScroll, events.applyPassive());
            (this._viewport || this.document.defaultView).addEventListener('touchmove', this.updateViewport, events.applyPassive());
            this.document.defaultView.addEventListener('resize', this.handleResize, events.applyPassive());
        });
        if (this.viewport && (this._type === 'short' || this._type === 'fixed'))
            this._updateViewPort();
        this.foundation.init();
    }
    initFixedAdjust() {
        if (this.foundation && this._fixedAdjust) {
            this._rndr.removeClass(this._fixedAdjust, 'mdc-top-app-bar--fixed-adjust');
            this._rndr.removeClass(this._fixedAdjust, 'mdc-top-app-bar--dense-fixed-adjust');
            this._rndr.removeClass(this._fixedAdjust, 'mdc-top-app-bar--short-fixed-adjust');
            this._rndr.removeClass(this._fixedAdjust, 'mdc-top-app-bar--prominent-fixed-adjust');
            this._rndr.removeClass(this._fixedAdjust, 'mdc-top-app-bar--dense-prominent-fixed-adjust');
            if (this.prominent && this.dense)
                this._rndr.addClass(this._fixedAdjust, 'mdc-top-app-bar--dense-prominent-fixed-adjust');
            else if (this._prominent)
                this._rndr.addClass(this._fixedAdjust, 'mdc-top-app-bar--prominent-fixed-adjust');
            else if (this._type === 'short')
                this._rndr.addClass(this._fixedAdjust, 'mdc-top-app-bar--short-fixed-adjust');
            else if (this._dense)
                this._rndr.addClass(this._fixedAdjust, 'mdc-top-app-bar--dense-fixed-adjust');
            else
                this._rndr.addClass(this._fixedAdjust, 'mdc-top-app-bar--fixed-adjust');
        }
    }
    removeScrollListeners() {
        (this._viewport || this.document.defaultView).removeEventListener('scroll', this.handleScroll, events.applyPassive());
        (this._viewport || this.document.defaultView).removeEventListener('touchmove', this.updateViewport, events.applyPassive());
        this.document.defaultView.removeEventListener('resize', this.handleResize, events.applyPassive());
    }
    /**
     * The top-app-bar can have different styles. Set this property to <code>fixed</code>
     * for a top-app-bar fixed to the top of the screen or viewport.
     * Set to <code>short</code> for a top-app-bar that will collapse to the navigation
     * icon side when scrolled.
     * Otherwise, the default is a top-app-bar that scrolls with the content.
     */
    get mdcTopAppBar() {
        return this._type;
    }
    set mdcTopAppBar(val) {
        if (val !== 'short' && val !== 'fixed')
            val = 'default';
        if (val !== this._type) {
            this._type = val;
            if (this.foundation)
                this.foundationReInit();
        }
    }
    /**
     * If set to a value other than false, the top-app-bar will be styled as a taller
     * bar.
     */
    get prominent() {
        return this._prominent;
    }
    set prominent(val) {
        let newValue = asBoolean(val);
        if (newValue !== this._prominent) {
            this._prominent = asBoolean(val);
            this.initFixedAdjust();
        }
    }
    /**
     * If set to a value other than false, the top-app-bar will be styled a bit more
     * compact.
     */
    get dense() {
        return this._dense;
    }
    set dense(val) {
        let newValue = asBoolean(val);
        if (newValue !== this._dense) {
            this._dense = asBoolean(val);
            this.initFixedAdjust();
        }
    }
    /**
     * Set this property to true or false to force the collapsed/uncollapsed state of a short
     * top-app-bar. Set this property to null to return to the default handling, where
     * <code>collapsed</code> is based on the scroll position of the viewport.
     * This property has no effect if the <code>mdcTopAppBar</code> has a value other than
     * <code>short</code>.
     */
    get collapsed() {
        if (this._type !== 'short')
            return false;
        return this._collapsedOverride == null ? !!this._collapsedState : this._collapsedOverride;
    }
    set collapsed(val) {
        this._collapsedOverride = asBooleanOrNull(val);
    }
    /**
     * Top-app-bars are positioned over the rest of their viewport. This means that
     * some of the content will be hidden under the bar, unless the position of that
     * content is changed relative to the bar. Assign the <code>HTMLElement</code>
     * of the content to this property, so that the <code>mdcTopAppBar</code>
     * can add spacing to the content making the top visible when the content is scrolled
     * up.
     */
    get fixedAdjust() {
        return this._fixedAdjust;
    }
    set fixedAdjust(el) {
        if (this._fixedAdjust !== el) {
            this._fixedAdjust = el;
            this.initFixedAdjust();
        }
    }
    /**
     * Assign any <code>HTMLElement</code> to this property to place a top-app-bar fixed to that element
     * (usually the parent container), instead of to the browser window. This property is mainly added for creating nice
     * demos of toolbars embedded inside other pages (such as on this documentation page). It is not recommended to use
     * this for a real application toolbar. The position is kept fixed to the container element by listening
     * for scroll/resize events, and using javascript to recompute the position. This may influence the smoothness
     * of the scrolling experience, especially on mobile devices.
     * The viewport element must have css styling: <code>position: relative</code>, and should have a fixed
     * height.
     */
    get viewport() {
        return this._viewport;
    }
    set viewport(elm) {
        if (this._viewport !== elm) {
            this.removeScrollListeners();
            this._viewport = elm;
            if (this.foundation)
                this.foundationReInit();
        }
    }
    /** @internal */
    get _hasActionItems() {
        return this._type === 'short' && this._actionItems.length > 0;
    }
    /** @internal */
    get _fixed() {
        return this._type === 'fixed';
    }
    /** @internal */
    get _short() {
        return this._type === 'short';
    }
    /** @internal */
    get _position() {
        return this._viewport ? 'absolute' : null;
    }
}
MdcTopAppBarDirective.decorators = [
    { type: Directive, args: [{
                selector: '[mdcTopAppBar]'
            },] }
];
MdcTopAppBarDirective.ctorParameters = () => [
    { type: Renderer2 },
    { type: ElementRef },
    { type: NgZone },
    { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
];
MdcTopAppBarDirective.propDecorators = {
    _cls: [{ type: HostBinding, args: ['class.mdc-top-app-bar',] }],
    _actionItems: [{ type: ContentChildren, args: [MdcTopAppBarActionDirective, { descendants: true },] }],
    mdcTopAppBar: [{ type: Input }],
    prominent: [{ type: Input }, { type: HostBinding, args: ['class.mdc-top-app-bar--prominent',] }],
    dense: [{ type: Input }, { type: HostBinding, args: ['class.mdc-top-app-bar--dense',] }],
    collapsed: [{ type: Input }, { type: HostBinding, args: ['class.mdc-top-app-bar--short-collapsed',] }],
    fixedAdjust: [{ type: Input }],
    viewport: [{ type: Input }],
    _hasActionItems: [{ type: HostBinding, args: ['class.mdc-top-app-bar--short-has-action-item',] }],
    _fixed: [{ type: HostBinding, args: ['class.mdc-top-app-bar--fixed',] }],
    _short: [{ type: HostBinding, args: ['class.mdc-top-app-bar--short',] }],
    _position: [{ type: HostBinding, args: ['style.position',] }]
};
export const TOP_APP_BAR_DIRECTIVES = [
    MdcTopAppBarRowDirective, MdcTopAppBarSectionDirective, MdcTopAppBarTitleDirective, MdcTopAppBarNavIconDirective,
    MdcTopAppBarActionDirective, MdcTopAppBarDirective
];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWRjLnRvcC1hcHAtYmFyLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3RvcC1hcHAtYmFyL21kYy50b3AtYXBwLWJhci5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFvQixlQUFlLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFDekYsTUFBTSxFQUF3QixTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzNDLE9BQU8sRUFDSCxzQkFBc0IsRUFBRSwyQkFBMkIsRUFBRSwyQkFBMkIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3BILE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdkMsT0FBTyxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUVyRTs7Ozs7R0FLRztBQUlILE1BQU0sT0FBTyx3QkFBd0I7SUFJakMsWUFBbUIsSUFBZ0I7UUFBaEIsU0FBSSxHQUFKLElBQUksQ0FBWTtRQUhuQyxnQkFBZ0I7UUFDb0MsU0FBSSxHQUFHLElBQUksQ0FBQztJQUdoRSxDQUFDOzs7WUFSSixTQUFTLFNBQUM7Z0JBQ1AsUUFBUSxFQUFFLG1CQUFtQjthQUNoQzs7O1lBaEJzRCxVQUFVOzs7bUJBbUI1RCxXQUFXLFNBQUMsNEJBQTRCOztBQU03Qzs7OztHQUlHO0FBSUgsTUFBTSxPQUFPLDRCQUE0QjtJQUh6QztRQUlJLGdCQUFnQjtRQUN3QyxTQUFJLEdBQUcsSUFBSSxDQUFDO1FBQzVELGNBQVMsR0FBRyxLQUFLLENBQUM7UUFDbEIsZ0JBQVcsR0FBRyxLQUFLLENBQUM7SUE2QmhDLENBQUM7SUEzQkc7OztPQUdHO0lBQ0gsSUFBeUUsVUFBVTtRQUMvRSxPQUFPLElBQUks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QUFDO0lBQ25FLENBQUM7SUFRRCxnQkFBZ0I7SUFDaEIsSUFBaUQsTUFBTTtRQUNuRCxPQUFPLElBQUksQ0FBQyxLQUFLLEtBQUssT0FBTyxDQUFDO0lBQ2xDLENBQUM7SUFFRCxnQkFBZ0I7SUFDaEIsSUFBaUQsTUFBTTtRQUNuRCxPQUFPLElBQUksQ0FBQyxLQUFLLEtBQUssT0FBTyxDQUFDO0lBQ2xDLENBQUM7SUFFRCxnQkFBZ0I7SUFDaEIsSUFBbUMsU0FBUztRQUN4QyxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQzlDLENBQUM7OztZQXJSSixTQUFTLFNBQUM7Z0JBQ1AsUUFBUSxFQUFFLGdCQUFnQjthQUM3Qjs7O1lBaElpQyxTQUFTO1lBRFksVUFBVTtZQUM3RCxNQUFNOzRDQTZMaUYsTUFBTSxTQUFDLFFBQVE7OzttQkExRHJHLFdBQVcsU0FBQyx1QkFBdUI7MkJBR25DLGVBQWUsU0FBQywyQkFBMkIsRUFBRSxFQUFDLFdBQVcsRUFBRSxJQUFJLEVBQUM7MkJBb0loRSxLQUFLO3dCQW9CTCxLQUFLLFlBQUksV0FBVyxTQUFDLGtDQUFrQztvQkFrQnZELEtBQUssWUFBSSxXQUFXLFNBQUMsOEJBQThCO3dCQXFCbkQsS0FBSyxZQUFJLFdBQVcsU0FBQyx3Q0FBd0M7MEJBb0I3RCxLQUFLO3VCQXFCTCxLQUFLOzhCQWNMLFdBQVcsU0FBQyw4Q0FBOEM7cUJBVzFELFdBQVcsU0FBQyw4QkFBOEI7cUJBSzFDLFdBQVcsU0FBQyw4QkFBOEI7d0JBSzFDLFdBQVcsU0FBQyxnQkFBZ0I7O0FBS2pDLE1BQU0sQ0FBQyxNQUFNLHNCQUFzQixHQUFHO0lBQ2xDLHdCQUF3QixFQUFFLDRCQUE0QixFQUFFLDBCQUEwQixFQUFFLDRCQUE0QjtJQUNoSCwyQkFBMkIsRUFBRSxxQkFBcUI7Q0FDckQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyQ29udGVudEluaXQsIENvbnRlbnRDaGlsZHJlbiwgRGlyZWN0aXZlLCBFbGVtZW50UmVmLCBIb3N0QmluZGluZywgSW5qZWN0LCBJbnB1dCxcbiAgICBOZ1pvbmUsIE9uRGVzdHJveSwgUXVlcnlMaXN0LCBSZW5kZXJlcjIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERPQ1VNRU5UIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IE1EQ1RvcEFwcEJhckFkYXB0ZXIsIE1EQ1RvcEFwcEJhckJhc2VGb3VuZGF0aW9uLFxuICAgIE1EQ1RvcEFwcEJhckZvdW5kYXRpb24sIE1EQ0ZpeGVkVG9wQXBwQmFyRm91bmRhdGlvbiwgTURDU2hvcnRUb3BBcHBCYXJGb3VuZGF0aW9uIH0gZnJvbSAnQG1hdGVyaWFsL3RvcC1hcHAtYmFyJztcbmltcG9ydCB7IGV2ZW50cyB9IGZyb20gJ0BtYXRlcmlhbC9kb20nO1xuaW1wb3J0IHsgYXNCb29sZWFuLCBhc0Jvb2xlYW5Pck51bGwgfSBmcm9tICcuLi8uLi91dGlscy92YWx1ZS51dGlscyc7XG5cbi8qKlxuICogQSBkaXJlY3RpdmUgZm9yIGEgdG9wLWFwcC1iYXIgcm93LiBUaGUgY29udGVudCBvZiBhIHRvcC1hcHAtYmFyIHNob3VsZCBhbHdheXMgYmUgZW1iZWRkZWRcbiAqIGluIDxjb2RlPm1kY1RvcEFwcEJhclJvdzwvY29kZT4gcm93cy4gTXVsdGlwbGUgcm93cyBhcmUgYWxsb3dlZCwgd2hpY2ggcm93cyBhcmUgdmlzaWJsZVxuICogZGVwZW5kcyBvbiB0aGUgc3R5bGUgb2YgdGhlIHRvb2xiYXIsIGFuZCB0aGUgc2Nyb2xsIHBvc2l0aW9uIG9mIHRoZSBjb250ZW50IG9mXG4gKiB0aGUgcGFnZS5cbiAqL1xuQERpcmVjdGl2ZSh7XG4gICAgc2VsZWN0b3I6ICdbbWRjVG9wQXBwQmFyUm93XSdcbn0pXG5leHBvcnQgY2xhc3MgTWRjVG9wQXBwQmFyUm93RGlyZWN0aXZlIHtcbiAgICAvKiogQGludGVybmFsICovXG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcy5tZGMtdG9wLWFwcC1iYXJfX3JvdycpIHJlYWRvbmx5IF9jbHMgPSB0cnVlO1xuXG4gICAgY29uc3RydWN0b3IocHVibGljIF9lbG06IEVsZW1lbnRSZWYpIHtcbiAgICB9XG59XG5cbi8qKlxuICogQSBkaXJlY3RpdmUgZm9yIGEgdG9wLWFwcC1iYXIgc2VjdGlvbi4gQSB0b3AtYXBwLWJhciByb3cgc2hvdWxkIGFsd2F5cyBiZSBjb21wb3NlZCBvZlxuICogPGNvZGU+bWRjVG9wQXBwQmFyU2VjdGlvbjwvY29kZT4gc2VjdGlvbnMuIE11bHRpcGxlIHNlY3Rpb25zLCB3aXRoIGRpZmZlcmVudCBhbGlnbm1lbnQgb3B0aW9ucyxcbiAqIGFyZSBhbGxvd2VkIHBlciByb3cuXG4gKi9cbkBEaXJlY3RpdmUoe1xuICAgIHNlbGVjdG9yOiAnW21kY1RvcEFwcEJhclNlY3Rpb25dJ1xufSlcbmV4cG9ydCBjbGFzcyBNZGNUb3BBcHBCYXJTZWN0aW9uRGlyZWN0aXZlIHtcbiAgICAvKiogQGludGVybmFsICovXG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcy5tZGMtdG9wLWFwcC1iYXJfX3NlY3Rpb24nKSByZWFkb25seSBfY2xzID0gdHJ1ZTtcbiAgICBwcml2YXRlIF9hbGlnbkVuZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgX2FsaWduU3RhcnQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIE1ha2UgdGhlIHNlY3Rpb24gYWxpZ24gdG8gdGhlIHN0YXJ0IG9mIHRoZSB0b29sYmFyIHJvdyAoZGVmYXVsdCBhbGlnbm1lbnQgaXMgdG8gdGhlXG4gICAgICogY2VudGVyKS5cbiAgICAgKi9cbiAgICBASW5wdXQoKSBASG9zdEJpbmRpbmcoJ2NsYXNzLm1kYy10b3AtYXBwLWJhcl9fc2VjdGlvbi0tYWxpZ24tc3RhcnQnKSBnZXQgYWxpZ25TdGFydCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FsaWduU3RhcnQ7XG4gICAgfVxuXG4gICAgc2V0IGFsaWduU3RhcnQodmFsOiBib29sZWFuKSB7XG4gICAgICAgIHRoaXMuX2FsaWduU3RhcnQgPSBhc0Jvb2xlYW4odmFsKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfYWxpZ25TdGFydDogYm9vbGVhbiB8ICcnO1xuXG4gICAgLyoqXG4gICAgICogTWFrZSB0aGUgc2VjdGlvbiBhbGlnbiB0byB0aGUgZW5kIG9mIHRoZSB0b29sYmFyIHJvdyAoZGVmYXVsdCBhbGlnbm1lbnQgaXMgdG8gdGhlXG4gICAgICogY2VudGVyKS5cbiAgICAgKi9cbiAgICBASW5wdXQoKSBASG9zdEJpbmRpbmcoJ2NsYXNzLm1kYy10b3AtYXBwLWJhcl9fc2VjdGlvbi0tYWxpZ24tZW5kJykgZ2V0IGFsaWduRW5kKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWxpZ25FbmQ7XG4gICAgfVxuXG4gICAgc2V0IGFsaWduRW5kKHZhbDogYm9vbGVhbikge1xuICAgICAgICB0aGlzLl9hbGlnbkVuZCA9IGFzQm9vbGVhbih2YWwpO1xuICAgIH1cblxuICAgIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9hbGlnbkVuZDogYm9vbGVhbiB8ICcnO1xufVxuXG4vKipcbiAqIFRoaXMgZGlyZWN0aXZlIGFkZHMgZXh0cmEgc3R5bGluZyB0byB0b29sYmFyIHRleHQgdGhhdCByZXByZXNlbnRzIHRoZSB0aXRsZSBvZiB0aGUgdG9vbGJhci5cbiAqIFRoZSBkaXJlY3RpdmUgc2hvdWxkIGJlIGEgY2hpbGQgb2YgYW4gZWxlbWVudCB3aXRoIHRoZSA8Y29kZT5tZGNUb3BBcHBCYXJTZWN0aW9uPC9jb2RlPiBkaXJlY3RpdmUuXG4gKi9cbkBEaXJlY3RpdmUoe1xuICAgIHNlbGVjdG9yOiAnW21kY1RvcEFwcEJhclRpdGxlXSdcbn0pXG5leHBvcnQgY2xhc3MgTWRjVG9wQXBwQmFyVGl0bGVEaXJlY3RpdmUge1xuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBASG9zdEJpbmRpbmcoJ2NsYXNzLm1kYy10b3AtYXBwLWJhcl9fdGl0bGUnKSByZWFkb25seSBfY2xzID0gdHJ1ZTtcblxuICAgIGNvbnN0cnVjdG9yKHB1YmxpYyBfZWxtOiBFbGVtZW50UmVmKSB7XG4gICAgfVxufVxuXG4vKipcbiAqIERpcmVjdGl2ZSBmb3IgdGhlIG5hdmlnYXRpb24gaWNvbiBvZiBhIHRvcC1hcHAtYmFyLiBUeXBpY2FsbHkgcGxhY2VkIG9uIHRoZVxuICogZmFyIGxlZnQgKGZvciBsZWZ0LXRvLXJpZ2h0IGxhbmd1YWdlcykuIFRoZSA8Y29kZT5tZGNUb3BBcHBCYXJOYXZJY29uPC9jb2RlPlxuICogZGlyZWN0aXZlIHNob3VsZCBiZSB1c2VkIG9uIGEgY2hpbGQgb2YgYW4gZWxlbWVudCB3aXRoIHRoZVxuICogPGNvZGU+bWRjVG9wQXBwQmFyU2VjdGlvbjwvY29kZT4gZGlyZWN0aXZlLiBJdCB0eXBpY2FsbHkgb3BlbnMgYSBuYXZpZ2F0aW9uIG1lbnVcbiAqIG9yIGRyYXdlci5cbiAqL1xuQERpcmVjdGl2ZSh7XG4gICAgc2VsZWN0b3I6ICdbbWRjVG9wQXBwQmFyTmF2SWNvbl0nXG59KVxuZXhwb3J0IGNsYXNzIE1kY1RvcEFwcEJhck5hdkljb25EaXJlY3RpdmUge1xuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBASG9zdEJpbmRpbmcoJ2NsYXNzLm1kYy10b3AtYXBwLWJhcl9fbmF2aWdhdGlvbi1pY29uJykgcmVhZG9ubHkgX2NscyA9IHRydWU7XG5cbiAgICBjb25zdHJ1Y3RvcihwdWJsaWMgX2VsbTogRWxlbWVudFJlZikge1xuICAgIH1cbn1cblxuLyoqXG4gKiBEaXJlY3RpdmUgZm9yIGFjdGlvbiBpdGVtcyBvZiBhIHRvcC1hcHAtYmFyLiBUeXBpY2FsbHkgcGxhY2VkIG9uIHRoZSBzaWRlXG4gKiBvcHBvc2l0ZSB0aGUgbmF2aWdhdGlvbiBpdGVtLiBUaGUgPGNvZGU+bWRjVG9wQXBwQmFyQWN0aW9uPC9jb2RlPiBkaXJlY3RpdmVcbiAqIHNob3VsZCBiZSB1c2VkIG9uIGEgY2hpbGQgb2YgYW4gZWxlbWVudCB3aXRoIHRoZSA8Y29kZT5tZGNUb3BBcHBCYXJTZWN0aW9uPC9jb2RlPlxuICogZGlyZWN0aXZlLlxuICovXG5ARGlyZWN0aXZlKHtcbiAgICBzZWxlY3RvcjogJ1ttZGNUb3BBcHBCYXJBY3Rpb25dJ1xufSlcbmV4cG9ydCBjbGFzcyBNZGNUb3BBcHBCYXJBY3Rpb25EaXJlY3RpdmUge1xuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBASG9zdEJpbmRpbmcoJ2NsYXNzLm1kYy10b3AtYXBwLWJhcl9fYWN0aW9uLWl0ZW0nKSByZWFkb25seSBfY2xzID0gdHJ1ZTtcbiAgICAvKipcbiAgICAgKiBBIGxhYmVsIGZvciB0aGUgYWN0aW9uIGl0ZW0uIFRoZSB2YWx1ZSB3aWxsIGJlIGFwcGxpZWQgdG8gYm90aCB0aGVcbiAgICAgKiA8Y29kZT5hcmlhLWxhYmVsPC9jb2RlPiwgYW5kIDxjb2RlPmFsdDwvY29kZT4gYXR0cmlidXRlIG9mIHRoZSBpdGVtLlxuICAgICAqL1xuICAgIEBJbnB1dCgpIEBIb3N0QmluZGluZygnYXR0ci5hcmlhLWxhYmVsJykgQEhvc3RCaW5kaW5nKCdhdHRyLmFsdCcpIGxhYmVsOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcblxuICAgIGNvbnN0cnVjdG9yKHB1YmxpYyBfZWxtOiBFbGVtZW50UmVmKSB7XG4gICAgfVxufVxuXG4vKipcbiAqIEEgZGlyZWN0aXZlIGZvciBhIHRvcC1hcHAtYmFyLiBBbGwgY29udGVudCBpbnNpZGUgYSB0b3AtYXBwLWJhciBzaG91bGQgYmVcbiAqIGVtYmVkZGVkIGluc2lkZSA8Y29kZT5tZGNUb3BBcHBCYXJSb3c8L2NvZGU+IHJvd3MuXG4gKi9cbkBEaXJlY3RpdmUoe1xuICAgIHNlbGVjdG9yOiAnW21kY1RvcEFwcEJhcl0nXG59KVxuZXhwb3J0IGNsYXNzIE1kY1RvcEFwcEJhckRpcmVjdGl2ZSBpbXBsZW1lbnRzIEFmdGVyQ29udGVudEluaXQsIE9uRGVzdHJveSB7XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIEBIb3N0QmluZGluZygnY2xhc3MubWRjLXRvcC1hcHAtYmFyJykgcmVhZG9ubHkgX2NscyA9IHRydWU7XG4gICAgcHJpdmF0ZSBkb2N1bWVudDogRG9jdW1lbnQ7XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIEBDb250ZW50Q2hpbGRyZW4oTWRjVG9wQXBwQmFyQWN0aW9uRGlyZWN0aXZlLCB7ZGVzY2VuZGFudHM6IHRydWV9KSBfYWN0aW9uSXRlbXM/OiBRdWVyeUxpc3Q8TWRjVG9wQXBwQmFyQWN0aW9uRGlyZWN0aXZlPjtcbiAgICBwcml2YXRlIGhhbmRsZVNjcm9sbCA9ICgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMudmlld3BvcnQgJiYgKHRoaXMuX3R5cGUgPT09ICdzaG9ydCcgfHwgdGhpcy5fdHlwZSA9PT0gJ2ZpeGVkJykpXG4gICAgICAgICAgICB0aGlzLl91cGRhdGVWaWV3UG9ydCgpO1xuICAgICAgICB0aGlzLmZvdW5kYXRpb24/LmhhbmRsZVRhcmdldFNjcm9sbCgpO1xuICAgIH1cbiAgICBwcml2YXRlIGhhbmRsZVJlc2l6ZSA9ICgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMudmlld3BvcnQgJiYgKHRoaXMuX3R5cGUgPT09ICdzaG9ydCcgfHwgdGhpcy5fdHlwZSA9PT0gJ2ZpeGVkJykpXG4gICAgICAgICAgICB0aGlzLl91cGRhdGVWaWV3UG9ydCgpO1xuICAgICAgICB0aGlzLmZvdW5kYXRpb24/LmhhbmRsZVdpbmRvd1Jlc2l6ZSgpO1xuICAgIH1cbiAgICBwcml2YXRlIHVwZGF0ZVZpZXdwb3J0ID0gKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy52aWV3cG9ydCAmJiAodGhpcy5fdHlwZSA9PT0gJ3Nob3J0JyB8fCB0aGlzLl90eXBlID09PSAnZml4ZWQnKSlcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZVZpZXdQb3J0KCk7XG4gICAgfVxuICAgIHByaXZhdGUgX3ZpZXdwb3J0OiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgX2ZpeGVkQWRqdXN0OiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgX3R5cGU6ICdzaG9ydCcgfCAnZml4ZWQnIHwgJ2RlZmF1bHQnID0gJ2RlZmF1bHQnO1xuICAgIHByaXZhdGUgX3Byb21pbmVudCA9IGZhbHNlO1xuICAgIHByaXZhdGUgX2RlbnNlID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBfY29sbGFwc2VkT3ZlcnJpZGU6IGJvb2xlYW4gfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIF9jb2xsYXBzZWRTdGF0ZTogYm9vbGVhbiB8IG51bGwgPSBudWxsO1xuXG4gICAgcHJpdmF0ZSBtZGNBZGFwdGVyOiBNRENUb3BBcHBCYXJBZGFwdGVyID0ge1xuICAgICAgICBoYXNDbGFzczogKGNsYXNzTmFtZTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICBpZiAoY2xhc3NOYW1lID09PSAnbWRjLXRvcC1hcHAtYmFyLS1zaG9ydC1jb2xsYXBzZWQnKVxuICAgICAgICAgICAgICAgIC8vIHRoZSBmb3VuZGF0aW9uIHVzZXMgdGhpcyBkdXJpbmcgaW5pdGlhbGlzYXRpb24gdG8gZGV0ZXJtaW5lIHdoZXRoZXJcbiAgICAgICAgICAgICAgICAvLyBhIHNob3J0IHRvcC1hcHAtYmFyIHNob3VsZCBhbHdheXMgYmUgZGlzcGxheWVkIGNvbGxhcHNlZC5cbiAgICAgICAgICAgICAgICAvLyBvdXIgY29tcG9uZW50IGluc3RlYWQgdXNlcyB0aGUgX2NvbGxhcHNlZCBmaWVsZCB2YWx1ZSB0byBvdmVycmlkZVxuICAgICAgICAgICAgICAgIC8vIHRoZSBjb2xsYXBzZWQgc3RhdGVcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7IFxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2VsbS5uYXRpdmVFbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhjbGFzc05hbWUpO1xuICAgICAgICB9LFxuICAgICAgICBhZGRDbGFzczogKGNsYXNzTmFtZTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICBpZiAoY2xhc3NOYW1lID09PSAnbWRjLXRvcC1hcHAtYmFyLS1zaG9ydC1jb2xsYXBzZWQnKVxuICAgICAgICAgICAgICAgIHRoaXMuX2NvbGxhcHNlZFN0YXRlID0gdHJ1ZTtcbiAgICAgICAgICAgIGVsc2UgaWYgKGNsYXNzTmFtZSAhPT0gJ21kYy10b3AtYXBwLWJhci0tc2hvcnQtaGFzLWFjdGlvbi1pdGVtJylcbiAgICAgICAgICAgICAgICAvLyB3ZSBhZGQvcmVtb3ZlIG1kYy10b3AtYXBwLWJhci0tc2hvcnQtaGFzLWFjdGlvbi1pdGVtIGR5bmFtaWNhbGx5IGJhc2VkIG9uIHRoZSBhY3R1YWwgbnVtYmVyIG9mIGl0ZW1zXG4gICAgICAgICAgICAgICAgLy8gdGhpcyBpcyBiZXR0ZXIgdGhhbiB0aGUgZm91bmRhdGlvbiB0aGF0IGxvb2tzIG9ubHkgYXQgdGhlIG5yIG9mIGl0ZW1zIGR1cmluZyBpbml0aWFsaXNhdGlvblxuICAgICAgICAgICAgICAgIHRoaXMuX3JuZHIuYWRkQ2xhc3ModGhpcy5fZWxtLm5hdGl2ZUVsZW1lbnQsIGNsYXNzTmFtZSk7XG4gICAgICAgIH0sXG4gICAgICAgIHJlbW92ZUNsYXNzOiAoY2xhc3NOYW1lOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgIGlmIChjbGFzc05hbWUgPT09ICdtZGMtdG9wLWFwcC1iYXItLXNob3J0LWNvbGxhcHNlZCcpXG4gICAgICAgICAgICAgICAgdGhpcy5fY29sbGFwc2VkU3RhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICB0aGlzLl9ybmRyLnJlbW92ZUNsYXNzKHRoaXMuX2VsbS5uYXRpdmVFbGVtZW50LCBjbGFzc05hbWUpO1xuICAgICAgICB9LFxuICAgICAgICBzZXRTdHlsZTogKHByb3BlcnR5LCB2YWx1ZSkgPT4gdGhpcy5fcm5kci5zZXRTdHlsZSh0aGlzLl9lbG0ubmF0aXZlRWxlbWVudCwgcHJvcGVydHksIHZhbHVlKSxcbiAgICAgICAgZ2V0VG9wQXBwQmFySGVpZ2h0OiAoKSA9PiB0aGlzLl9lbG0ubmF0aXZlRWxlbWVudC5jbGllbnRIZWlnaHQsXG4gICAgICAgIG5vdGlmeU5hdmlnYXRpb25JY29uQ2xpY2tlZDogKCkgPT4ge30sIC8vIG5vdCBhIHNwZWNpYWwgZXZlbnQgaW4gb3VyIGltcGxlbWVudGF0aW9uXG4gICAgICAgIGdldFZpZXdwb3J0U2Nyb2xsWTogKCkgPT4gdGhpcy5fdmlld3BvcnQgPyB0aGlzLl92aWV3cG9ydC5zY3JvbGxUb3AgOiB0aGlzLmRvY3VtZW50LmRlZmF1bHRWaWV3IS5wYWdlWU9mZnNldCxcbiAgICAgICAgZ2V0VG90YWxBY3Rpb25JdGVtczogKCkgPT4gdGhpcy5fYWN0aW9uSXRlbXMhLmxlbmd0aFxuICAgIH07XG4gICAgcHJpdmF0ZSBmb3VuZGF0aW9uOiBNRENUb3BBcHBCYXJCYXNlRm91bmRhdGlvbiB8IG51bGwgPSBudWxsO1xuICAgIFxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgX3JuZHI6IFJlbmRlcmVyMiwgcHJpdmF0ZSBfZWxtOiBFbGVtZW50UmVmLCBwcml2YXRlIHpvbmU6IE5nWm9uZSwgQEluamVjdChET0NVTUVOVCkgZG9jOiBhbnkpIHtcbiAgICAgICAgdGhpcy5kb2N1bWVudCA9IGRvYyBhcyBEb2N1bWVudDtcbiAgICB9XG5cbiAgICBuZ0FmdGVyQ29udGVudEluaXQoKSB7XG4gICAgICAgIHRoaXMuZm91bmRhdGlvblJlSW5pdCgpO1xuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCkge1xuICAgICAgICB0aGlzLnJlbW92ZVNjcm9sbExpc3RlbmVycygpO1xuICAgICAgICB0aGlzLmZvdW5kYXRpb24/LmRlc3Ryb3koKTtcbiAgICAgICAgdGhpcy5mb3VuZGF0aW9uID0gbnVsbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGZvdW5kYXRpb25SZUluaXQoKSB7XG4gICAgICAgIGlmICh0aGlzLmZvdW5kYXRpb24pXG4gICAgICAgICAgICB0aGlzLmZvdW5kYXRpb24uZGVzdHJveSgpO1xuXG4gICAgICAgIC8vIHVuZG8gdmlld3BvcnQgaW5pdCBzcGVjaWZpYyBmb3IgYSBmb3VuZGF0aW9uIGltcGxlbWVudGF0aW9uOlxuICAgICAgICB0aGlzLnJlbW92ZVNjcm9sbExpc3RlbmVycygpO1xuICAgICAgICB0aGlzLl9lbG0ubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSBudWxsO1xuXG4gICAgICAgIC8vIHJlbW92ZSBjbGFzc2VzIHNldCBieSBmb3VuZGF0aW9ucywgaWYgd2UgcmVpbml0aWFsaXplL3N3aXRjaCBmb3VuZGF0aW9uOlxuICAgICAgICB0aGlzLl9ybmRyLnJlbW92ZUNsYXNzKHRoaXMuX2VsbS5uYXRpdmVFbGVtZW50LCAnbWRjLXRvcC1hcHAtYmFyLS1maXhlZC1zY3JvbGxlZCcpO1xuXG4gICAgICAgIGlmICh0aGlzLl90eXBlID09PSAnc2hvcnQnKVxuICAgICAgICAgICAgdGhpcy5mb3VuZGF0aW9uID0gbmV3IE1EQ1Nob3J0VG9wQXBwQmFyRm91bmRhdGlvbih0aGlzLm1kY0FkYXB0ZXIpO1xuICAgICAgICBlbHNlIGlmICh0aGlzLl90eXBlID09PSAnZml4ZWQnKVxuICAgICAgICAgICAgdGhpcy5mb3VuZGF0aW9uID0gbmV3IE1EQ0ZpeGVkVG9wQXBwQmFyRm91bmRhdGlvbih0aGlzLm1kY0FkYXB0ZXIpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aGlzLmZvdW5kYXRpb24gPSBuZXcgTURDVG9wQXBwQmFyRm91bmRhdGlvbih0aGlzLm1kY0FkYXB0ZXIpO1xuICAgICAgICB0aGlzLmluaXRGaXhlZEFkanVzdCgpO1xuXG4gICAgICAgIHRoaXMuem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgICAodGhpcy5fdmlld3BvcnQgfHwgdGhpcy5kb2N1bWVudC5kZWZhdWx0VmlldyEpLmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuaGFuZGxlU2Nyb2xsLCBldmVudHMuYXBwbHlQYXNzaXZlKCkpO1xuICAgICAgICAgICAgKHRoaXMuX3ZpZXdwb3J0IHx8IHRoaXMuZG9jdW1lbnQuZGVmYXVsdFZpZXchKS5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLnVwZGF0ZVZpZXdwb3J0LCBldmVudHMuYXBwbHlQYXNzaXZlKCkpO1xuICAgICAgICAgICAgdGhpcy5kb2N1bWVudC5kZWZhdWx0VmlldyEuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5oYW5kbGVSZXNpemUsIGV2ZW50cy5hcHBseVBhc3NpdmUoKSk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodGhpcy52aWV3cG9ydCAmJiAodGhpcy5fdHlwZSA9PT0gJ3Nob3J0JyB8fCB0aGlzLl90eXBlID09PSAnZml4ZWQnKSlcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZVZpZXdQb3J0KCk7XG4gICAgICAgIHRoaXMuZm91bmRhdGlvbi5pbml0KCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0Rml4ZWRBZGp1c3QoKSB7XG4gICAgICAgIGlmICh0aGlzLmZvdW5kYXRpb24gJiYgdGhpcy5fZml4ZWRBZGp1c3QpIHtcbiAgICAgICAgICAgIHRoaXMuX3JuZHIucmVtb3ZlQ2xhc3ModGhpcy5fZml4ZWRBZGp1c3QsICdtZGMtdG9wLWFwcC1iYXItLWZpeGVkLWFkanVzdCcpO1xuICAgICAgICAgICAgdGhpcy5fcm5kci5yZW1vdmVDbGFzcyh0aGlzLl9maXhlZEFkanVzdCwgJ21kYy10b3AtYXBwLWJhci0tZGVuc2UtZml4ZWQtYWRqdXN0Jyk7XG4gICAgICAgICAgICB0aGlzLl9ybmRyLnJlbW92ZUNsYXNzKHRoaXMuX2ZpeGVkQWRqdXN0LCAnbWRjLXRvcC1hcHAtYmFyLS1zaG9ydC1maXhlZC1hZGp1c3QnKTtcbiAgICAgICAgICAgIHRoaXMuX3JuZHIucmVtb3ZlQ2xhc3ModGhpcy5fZml4ZWRBZGp1c3QsICdtZGMtdG9wLWFwcC1iYXItLXByb21pbmVudC1maXhlZC1hZGp1c3QnKTtcbiAgICAgICAgICAgIHRoaXMuX3JuZHIucmVtb3ZlQ2xhc3ModGhpcy5fZml4ZWRBZGp1c3QsICdtZGMtdG9wLWFwcC1iYXItLWRlbnNlLXByb21pbmVudC1maXhlZC1hZGp1c3QnKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMucHJvbWluZW50ICYmIHRoaXMuZGVuc2UpXG4gICAgICAgICAgICAgICAgdGhpcy5fcm5kci5hZGRDbGFzcyh0aGlzLl9maXhlZEFkanVzdCwgJ21kYy10b3AtYXBwLWJhci0tZGVuc2UtcHJvbWluZW50LWZpeGVkLWFkanVzdCcpO1xuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5fcHJvbWluZW50KVxuICAgICAgICAgICAgICAgIHRoaXMuX3JuZHIuYWRkQ2xhc3ModGhpcy5fZml4ZWRBZGp1c3QsICdtZGMtdG9wLWFwcC1iYXItLXByb21pbmVudC1maXhlZC1hZGp1c3QnKTtcbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuX3R5cGUgPT09ICdzaG9ydCcpXG4gICAgICAgICAgICAgICAgdGhpcy5fcm5kci5hZGRDbGFzcyh0aGlzLl9maXhlZEFkanVzdCwgJ21kYy10b3AtYXBwLWJhci0tc2hvcnQtZml4ZWQtYWRqdXN0Jyk7XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLl9kZW5zZSlcbiAgICAgICAgICAgICAgICB0aGlzLl9ybmRyLmFkZENsYXNzKHRoaXMuX2ZpeGVkQWRqdXN0LCAnbWRjLXRvcC1hcHAtYmFyLS1kZW5zZS1maXhlZC1hZGp1c3QnKTtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICB0aGlzLl9ybmRyLmFkZENsYXNzKHRoaXMuX2ZpeGVkQWRqdXN0LCAnbWRjLXRvcC1hcHAtYmFyLS1maXhlZC1hZGp1c3QnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcmVtb3ZlU2Nyb2xsTGlzdGVuZXJzKCkge1xuICAgICAgICAodGhpcy5fdmlld3BvcnQgfHwgdGhpcy5kb2N1bWVudC5kZWZhdWx0VmlldyEpLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuaGFuZGxlU2Nyb2xsLCBldmVudHMuYXBwbHlQYXNzaXZlKCkpO1xuICAgICAgICAodGhpcy5fdmlld3BvcnQgfHwgdGhpcy5kb2N1bWVudC5kZWZhdWx0VmlldyEpLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMudXBkYXRlVmlld3BvcnQsIGV2ZW50cy5hcHBseVBhc3NpdmUoKSk7XG4gICAgICAgIHRoaXMuZG9jdW1lbnQuZGVmYXVsdFZpZXchLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIHRoaXMuaGFuZGxlUmVzaXplLCBldmVudHMuYXBwbHlQYXNzaXZlKCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSB0b3AtYXBwLWJhciBjYW4gaGF2ZSBkaWZmZXJlbnQgc3R5bGVzLiBTZXQgdGhpcyBwcm9wZXJ0eSB0byA8Y29kZT5maXhlZDwvY29kZT5cbiAgICAgKiBmb3IgYSB0b3AtYXBwLWJhciBmaXhlZCB0byB0aGUgdG9wIG9mIHRoZSBzY3JlZW4gb3Igdmlld3BvcnQuXG4gICAgICogU2V0IHRvIDxjb2RlPnNob3J0PC9jb2RlPiBmb3IgYSB0b3AtYXBwLWJhciB0aGF0IHdpbGwgY29sbGFwc2UgdG8gdGhlIG5hdmlnYXRpb25cbiAgICAgKiBpY29uIHNpZGUgd2hlbiBzY3JvbGxlZC5cbiAgICAgKiBPdGhlcndpc2UsIHRoZSBkZWZhdWx0IGlzIGEgdG9wLWFwcC1iYXIgdGhhdCBzY3JvbGxzIHdpdGggdGhlIGNvbnRlbnQuXG4gICAgICovXG4gICAgQElucHV0KCkgZ2V0IG1kY1RvcEFwcEJhcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3R5cGU7XG4gICAgfVxuXG4gICAgc2V0IG1kY1RvcEFwcEJhcih2YWwpIHtcbiAgICAgICAgaWYgKHZhbCAhPT0gJ3Nob3J0JyAmJiB2YWwgIT09ICdmaXhlZCcpXG4gICAgICAgICAgICB2YWwgPSAnZGVmYXVsdCc7XG4gICAgICAgIGlmICh2YWwgIT09IHRoaXMuX3R5cGUpIHtcbiAgICAgICAgICAgIHRoaXMuX3R5cGUgPSB2YWw7XG4gICAgICAgICAgICBpZiAodGhpcy5mb3VuZGF0aW9uKVxuICAgICAgICAgICAgICAgIHRoaXMuZm91bmRhdGlvblJlSW5pdCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX21kY1RvcEFwcEJhcjogJ3Nob3J0JyB8ICdmaXhlZCcgfCAnZGVmYXVsdCcgfCAnJztcblxuICAgIC8qKlxuICAgICAqIElmIHNldCB0byBhIHZhbHVlIG90aGVyIHRoYW4gZmFsc2UsIHRoZSB0b3AtYXBwLWJhciB3aWxsIGJlIHN0eWxlZCBhcyBhIHRhbGxlclxuICAgICAqIGJhci5cbiAgICAgKi9cbiAgICBASW5wdXQoKSBASG9zdEJpbmRpbmcoJ2NsYXNzLm1kYy10b3AtYXBwLWJhci0tcHJvbWluZW50JykgZ2V0IHByb21pbmVudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Byb21pbmVudDtcbiAgICB9XG5cbiAgICBzZXQgcHJvbWluZW50KHZhbDogYm9vbGVhbikge1xuICAgICAgICBsZXQgbmV3VmFsdWUgPSBhc0Jvb2xlYW4odmFsKTtcbiAgICAgICAgaWYgKG5ld1ZhbHVlICE9PSB0aGlzLl9wcm9taW5lbnQpIHtcbiAgICAgICAgICAgIHRoaXMuX3Byb21pbmVudCA9IGFzQm9vbGVhbih2YWwpO1xuICAgICAgICAgICAgdGhpcy5pbml0Rml4ZWRBZGp1c3QoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9wcm9taW5lbnQ6IGJvb2xlYW4gfCAnJztcblxuICAgIC8qKlxuICAgICAqIElmIHNldCB0byBhIHZhbHVlIG90aGVyIHRoYW4gZmFsc2UsIHRoZSB0b3AtYXBwLWJhciB3aWxsIGJlIHN0eWxlZCBhIGJpdCBtb3JlXG4gICAgICogY29tcGFjdC5cbiAgICAgKi9cbiAgICBASW5wdXQoKSBASG9zdEJpbmRpbmcoJ2NsYXNzLm1kYy10b3AtYXBwLWJhci0tZGVuc2UnKSBnZXQgZGVuc2UoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZW5zZTtcbiAgICB9XG5cbiAgICBzZXQgZGVuc2UodmFsOiBib29sZWFuKSB7XG4gICAgICAgIGxldCBuZXdWYWx1ZSA9IGFzQm9vbGVhbih2YWwpO1xuICAgICAgICBpZiAobmV3VmFsdWUgIT09IHRoaXMuX2RlbnNlKSB7XG4gICAgICAgICAgICB0aGlzLl9kZW5zZSA9IGFzQm9vbGVhbih2YWwpO1xuICAgICAgICAgICAgdGhpcy5pbml0Rml4ZWRBZGp1c3QoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9kZW5zZTogYm9vbGVhbiB8ICcnO1xuICAgIFxuICAgIC8qKlxuICAgICAqIFNldCB0aGlzIHByb3BlcnR5IHRvIHRydWUgb3IgZmFsc2UgdG8gZm9yY2UgdGhlIGNvbGxhcHNlZC91bmNvbGxhcHNlZCBzdGF0ZSBvZiBhIHNob3J0XG4gICAgICogdG9wLWFwcC1iYXIuIFNldCB0aGlzIHByb3BlcnR5IHRvIG51bGwgdG8gcmV0dXJuIHRvIHRoZSBkZWZhdWx0IGhhbmRsaW5nLCB3aGVyZVxuICAgICAqIDxjb2RlPmNvbGxhcHNlZDwvY29kZT4gaXMgYmFzZWQgb24gdGhlIHNjcm9sbCBwb3NpdGlvbiBvZiB0aGUgdmlld3BvcnQuXG4gICAgICogVGhpcyBwcm9wZXJ0eSBoYXMgbm8gZWZmZWN0IGlmIHRoZSA8Y29kZT5tZGNUb3BBcHBCYXI8L2NvZGU+IGhhcyBhIHZhbHVlIG90aGVyIHRoYW5cbiAgICAgKiA8Y29kZT5zaG9ydDwvY29kZT4uXG4gICAgICovXG4gICAgQElucHV0KCkgQEhvc3RCaW5kaW5nKCdjbGFzcy5tZGMtdG9wLWFwcC1iYXItLXNob3J0LWNvbGxhcHNlZCcpIGdldCBjb2xsYXBzZWQoKSB7XG4gICAgICAgIGlmICh0aGlzLl90eXBlICE9PSAnc2hvcnQnKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICByZXR1cm4gdGhpcy5fY29sbGFwc2VkT3ZlcnJpZGUgPT0gbnVsbCA/ICEhdGhpcy5fY29sbGFwc2VkU3RhdGUgOiB0aGlzLl9jb2xsYXBzZWRPdmVycmlkZTtcbiAgICB9XG5cbiAgICBzZXQgY29sbGFwc2VkKHZhbDogYm9vbGVhbikge1xuICAgICAgICB0aGlzLl9jb2xsYXBzZWRPdmVycmlkZSA9IGFzQm9vbGVhbk9yTnVsbCh2YWwpO1xuICAgIH1cblxuICAgIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9jb2xsYXBzZWQ6IGJvb2xlYW4gfCAnJztcblxuICAgIC8qKlxuICAgICAqIFRvcC1hcHAtYmFycyBhcmUgcG9zaXRpb25lZCBvdmVyIHRoZSByZXN0IG9mIHRoZWlyIHZpZXdwb3J0LiBUaGlzIG1lYW5zIHRoYXRcbiAgICAgKiBzb21lIG9mIHRoZSBjb250ZW50IHdpbGwgYmUgaGlkZGVuIHVuZGVyIHRoZSBiYXIsIHVubGVzcyB0aGUgcG9zaXRpb24gb2YgdGhhdFxuICAgICAqIGNvbnRlbnQgaXMgY2hhbmdlZCByZWxhdGl2ZSB0byB0aGUgYmFyLiBBc3NpZ24gdGhlIDxjb2RlPkhUTUxFbGVtZW50PC9jb2RlPlxuICAgICAqIG9mIHRoZSBjb250ZW50IHRvIHRoaXMgcHJvcGVydHksIHNvIHRoYXQgdGhlIDxjb2RlPm1kY1RvcEFwcEJhcjwvY29kZT5cbiAgICAgKiBjYW4gYWRkIHNwYWNpbmcgdG8gdGhlIGNvbnRlbnQgbWFraW5nIHRoZSB0b3AgdmlzaWJsZSB3aGVuIHRoZSBjb250ZW50IGlzIHNjcm9sbGVkXG4gICAgICogdXAuXG4gICAgICovXG4gICAgQElucHV0KCkgZ2V0IGZpeGVkQWRqdXN0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZml4ZWRBZGp1c3Q7XG4gICAgfVxuXG4gICAgc2V0IGZpeGVkQWRqdXN0KGVsOiBIVE1MRWxlbWVudCB8IG51bGwpIHtcbiAgICAgICAgaWYgKHRoaXMuX2ZpeGVkQWRqdXN0ICE9PSBlbCkge1xuICAgICAgICAgICAgdGhpcy5fZml4ZWRBZGp1c3QgPSBlbDtcbiAgICAgICAgICAgIHRoaXMuaW5pdEZpeGVkQWRqdXN0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBc3NpZ24gYW55IDxjb2RlPkhUTUxFbGVtZW50PC9jb2RlPiB0byB0aGlzIHByb3BlcnR5IHRvIHBsYWNlIGEgdG9wLWFwcC1iYXIgZml4ZWQgdG8gdGhhdCBlbGVtZW50XG4gICAgICogKHVzdWFsbHkgdGhlIHBhcmVudCBjb250YWluZXIpLCBpbnN0ZWFkIG9mIHRvIHRoZSBicm93c2VyIHdpbmRvdy4gVGhpcyBwcm9wZXJ0eSBpcyBtYWlubHkgYWRkZWQgZm9yIGNyZWF0aW5nIG5pY2VcbiAgICAgKiBkZW1vcyBvZiB0b29sYmFycyBlbWJlZGRlZCBpbnNpZGUgb3RoZXIgcGFnZXMgKHN1Y2ggYXMgb24gdGhpcyBkb2N1bWVudGF0aW9uIHBhZ2UpLiBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gdXNlXG4gICAgICogdGhpcyBmb3IgYSByZWFsIGFwcGxpY2F0aW9uIHRvb2xiYXIuIFRoZSBwb3NpdGlvbiBpcyBrZXB0IGZpeGVkIHRvIHRoZSBjb250YWluZXIgZWxlbWVudCBieSBsaXN0ZW5pbmdcbiAgICAgKiBmb3Igc2Nyb2xsL3Jlc2l6ZSBldmVudHMsIGFuZCB1c2luZyBqYXZhc2NyaXB0IHRvIHJlY29tcHV0ZSB0aGUgcG9zaXRpb24uIFRoaXMgbWF5IGluZmx1ZW5jZSB0aGUgc21vb3RobmVzc1xuICAgICAqIG9mIHRoZSBzY3JvbGxpbmcgZXhwZXJpZW5jZSwgZXNwZWNpYWxseSBvbiBtb2JpbGUgZGV2aWNlcy5cbiAgICAgKiBUaGUgdmlld3BvcnQgZWxlbWVudCBtdXN0IGhhdmUgY3NzIHN0eWxpbmc6IDxjb2RlPnBvc2l0aW9uOiByZWxhdGl2ZTwvY29kZT4sIGFuZCBzaG91bGQgaGF2ZSBhIGZpeGVkXG4gICAgICogaGVpZ2h0LlxuICAgICAqL1xuICAgIEBJbnB1dCgpIGdldCB2aWV3cG9ydCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZpZXdwb3J0O1xuICAgIH1cblxuICAgIHNldCB2aWV3cG9ydChlbG06IEhUTUxFbGVtZW50IHwgbnVsbCkge1xuICAgICAgICBpZiAodGhpcy5fdmlld3BvcnQgIT09IGVsbSkge1xuICAgICAgICAgICAgdGhpcy5yZW1vdmVTY3JvbGxMaXN0ZW5lcnMoKTtcbiAgICAgICAgICAgIHRoaXMuX3ZpZXdwb3J0ID0gZWxtO1xuICAgICAgICAgICAgaWYgKHRoaXMuZm91bmRhdGlvbilcbiAgICAgICAgICAgICAgICB0aGlzLmZvdW5kYXRpb25SZUluaXQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBASG9zdEJpbmRpbmcoJ2NsYXNzLm1kYy10b3AtYXBwLWJhci0tc2hvcnQtaGFzLWFjdGlvbi1pdGVtJykgZ2V0IF9oYXNBY3Rpb25JdGVtcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3R5cGUgPT09ICdzaG9ydCcgJiYgdGhpcy5fYWN0aW9uSXRlbXMhLmxlbmd0aCA+IDA7XG4gICAgfVxuXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIF91cGRhdGVWaWV3UG9ydCA9ICgpID0+IHtcbiAgICAgICAgLy8gc2ltdWxhdGUgJ2ZpeGVkJyByZWxhdGl2ZSB0byB2aWV3IHBvc2l0aW9uIG9mIHBhcmVudDpcbiAgICAgICAgdGhpcy5fZWxtLm5hdGl2ZUVsZW1lbnQuc3R5bGUudG9wID0gdGhpcy5fdmlld3BvcnQhLnNjcm9sbFRvcCArICdweCc7XG4gICAgfVxuXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIEBIb3N0QmluZGluZygnY2xhc3MubWRjLXRvcC1hcHAtYmFyLS1maXhlZCcpIGdldCBfZml4ZWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl90eXBlID09PSAnZml4ZWQnO1xuICAgIH1cblxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBASG9zdEJpbmRpbmcoJ2NsYXNzLm1kYy10b3AtYXBwLWJhci0tc2hvcnQnKSBnZXQgX3Nob3J0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fdHlwZSA9PT0gJ3Nob3J0JztcbiAgICB9XG5cbiAgICAvKiogQGludGVybmFsICovXG4gICAgQEhvc3RCaW5kaW5nKCdzdHlsZS5wb3NpdGlvbicpIGdldCBfcG9zaXRpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl92aWV3cG9ydCA/ICdhYnNvbHV0ZScgOiBudWxsO1xuICAgIH1cbn1cblxuZXhwb3J0IGNvbnN0IFRPUF9BUFBfQkFSX0RJUkVDVElWRVMgPSBbXG4gICAgTWRjVG9wQXBwQmFyUm93RGlyZWN0aXZlLCBNZGNUb3BBcHBCYXJTZWN0aW9uRGlyZWN0aXZlLCBNZGNUb3BBcHBCYXJUaXRsZURpcmVjdGl2ZSwgTWRjVG9wQXBwQmFyTmF2SWNvbkRpcmVjdGl2ZSxcbiAgICBNZGNUb3BBcHBCYXJBY3Rpb25EaXJlY3RpdmUsIE1kY1RvcEFwcEJhckRpcmVjdGl2ZVxuXTtcbiJdfQ==