UNPKG

@greg-md/ng-flex-css-layout

Version:

Flex-CSS-Layout is an alternative behaviour of Flex-Layout directives, that will still work with Angular Universal and App Shell.

535 lines 66.7 kB
/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes} checked by tsc
 */
import { DOCUMENT } from '@angular/common';
import { Injectable, Inject, InjectionToken } from '@angular/core';
import { applyCssPrefixes } from './auto-prefixer';
import { validateValue, buildCSS, isFlowHorizontal } from './layout-validator';
import { generateLayoutClassName, normalizeLayoutAlignValue, generateLayoutAlignClassName, generateLayoutGapClassName, generateFlexClassName, generateFlexOrderClassName, generateFlexOffsetClassName, generateFlexAlignClassName, generateFlexFillClassName, generateFlexShowHideClassName } from './helpers';
import { validateBasis } from './basis-validator';
/**
 * @record
 */
export function Breakpoint() { }
function Breakpoint_tsickle_Closure_declarations() {
    /** @type {?} */
    Breakpoint.prototype.alias;
    /** @type {?} */
    Breakpoint.prototype.media;
}
export const /** @type {?} */ FLEX_CSS_DEFAULT_BREAKPOINTS = [
    { alias: 'gt-xs', media: ['screen', '(min-width: 600px)'] },
    { alias: 'lt-xl', media: ['screen', '(max-width: 1919px)'] },
    { alias: 'gt-sm', media: ['screen', '(min-width: 960px)'] },
    { alias: 'lt-lg', media: ['screen', '(max-width: 1279px)'] },
    { alias: 'gt-md', media: ['screen', '(min-width: 1280px)'] },
    { alias: 'lt-md', media: ['screen', '(max-width: 959px)'] },
    { alias: 'gt-lg', media: ['screen', '(min-width: 1920px)'] },
    { alias: 'lt-sm', media: ['screen', '(max-width: 599px)'] },
    { alias: 'xl', media: ['screen', '(min-width: 1920px)', '(max-width: 5000px)'] },
    { alias: 'lg', media: ['screen', '(min-width: 1280px)', '(max-width: 1919px)'] },
    { alias: 'md', media: ['screen', '(min-width: 960px)', '(max-width: 1279px)'] },
    { alias: 'sm', media: ['screen', '(min-width: 600px)', '(max-width: 959px)'] },
    { alias: 'xs', media: ['screen', '(max-width: 599px)'] },
];
export const /** @type {?} */ FLEX_CSS_BREAKPOINTS_SMALL_TO_LARGE = [
    { alias: 'lt-sm', media: ['screen', '(max-width: 599px)'] },
    { alias: 'xs', media: ['screen', '(max-width: 599px)'] },
    { alias: 'gt-xs', media: ['screen', '(min-width: 600px)'] },
    { alias: 'lt-md', media: ['screen', '(max-width: 959px)'] },
    { alias: 'sm', media: ['screen', '(min-width: 600px)', '(max-width: 959px)'] },
    { alias: 'gt-sm', media: ['screen', '(min-width: 960px)'] },
    { alias: 'lt-lg', media: ['screen', '(max-width: 1279px)'] },
    { alias: 'md', media: ['screen', '(min-width: 960px)', '(max-width: 1279px)'] },
    { alias: 'gt-md', media: ['screen', '(min-width: 1280px)'] },
    { alias: 'lt-xl', media: ['screen', '(max-width: 1919px)'] },
    { alias: 'lg', media: ['screen', '(min-width: 1280px)', '(max-width: 1919px)'] },
    { alias: 'gt-lg', media: ['screen', '(min-width: 1920px)'] },
    { alias: 'xl', media: ['screen', '(min-width: 1920px)', '(max-width: 5000px)'] },
];
export const /** @type {?} */ FLEX_CSS_BREAKPOINTS = new InjectionToken('flex_css_breakpoints');
export class FlexCssStyleElement {
    /**
     * @param {?} style
     */
    constructor(style) {
        this.style = style;
        this.storage = {};
    }
}
function FlexCssStyleElement_tsickle_Closure_declarations() {
    /** @type {?} */
    FlexCssStyleElement.prototype.storage;
    /** @type {?} */
    FlexCssStyleElement.prototype.style;
}
export class FlexCssService {
    /**
     * @param {?} doc
     * @param {?} breakpoints
     */
    constructor(doc, breakpoints) {
        this.doc = doc;
        this.breakpoints = breakpoints;
        this.initLayout();
        this.initFlex();
        this.initFill();
    }
    /**
     * @return {?}
     */
    initLayout() {
        const /** @type {?} */ style = this.doc.createElement('style');
        style.id = 'fc-layout';
        this.doc.head.appendChild(style);
        this.layout = new FlexCssStyleElement(style);
    }
    /**
     * @return {?}
     */
    initFlex() {
        const /** @type {?} */ style = this.doc.createElement('style');
        style.id = 'fc-flex';
        this.doc.head.appendChild(style);
        this.flex = new FlexCssStyleElement(style);
    }
    /**
     * @return {?}
     */
    initFill() {
        const /** @type {?} */ style = this.doc.createElement('style');
        style.id = 'fc-fill';
        this.doc.head.appendChild(style);
        this.fill = new FlexCssStyleElement(style);
    }
    /**
     * @param {?} layout
     * @param {?} breakpoint
     * @return {?}
     */
    addLayout(layout, breakpoint) {
        const [direction, wrap, isInline] = validateValue(layout);
        const /** @type {?} */ className = generateLayoutClassName(direction, wrap, isInline, breakpoint);
        if (!this.hasInLayoutStorage(className, breakpoint)) {
            const /** @type {?} */ style = buildCSS(direction, wrap, isInline);
            this.addToLayoutStorage(className, style, breakpoint);
        }
        return className;
    }
    /**
     * @param {?} layout
     * @param {?} layoutBreakpoint
     * @param {?} align
     * @param {?} breakpoint
     * @return {?}
     */
    addLayoutAlign(layout, layoutBreakpoint, align, breakpoint) {
        const [mainAxis, crossAxis] = normalizeLayoutAlignValue(align);
        const /** @type {?} */ layoutAlignClassName = generateLayoutAlignClassName(mainAxis, crossAxis, breakpoint);
        if (!this.hasInLayoutStorage(layoutAlignClassName, breakpoint)) {
            const /** @type {?} */ style = {
                'justify-content': mainAxis,
            };
            switch (crossAxis) {
                case 'baseline':
                    style['align-items'] = crossAxis;
                    break;
                default:
                    style['align-items'] = style['align-content'] = crossAxis;
                    break;
            }
            this.addToLayoutStorage(layoutAlignClassName, style, breakpoint);
        }
        if (crossAxis === 'stretch') {
            const [direction, wrap, isInline] = validateValue(layout);
            const /** @type {?} */ layoutClassName = generateLayoutClassName(direction, wrap, isInline, layoutBreakpoint);
            const /** @type {?} */ className = layoutAlignClassName + '.' + layoutClassName;
            if (!this.hasInLayoutStorage(className, breakpoint)) {
                const /** @type {?} */ style = isFlowHorizontal(layout) ? { 'max-height': '100%' } : { 'max-width': '100%' };
                this.addToLayoutStorage(className, style, breakpoint, [layoutBreakpoint]);
            }
        }
        return layoutAlignClassName;
    }
    /**
     * @param {?} layout
     * @param {?} layoutBreakpoint
     * @param {?} value
     * @param {?} breakpoint
     * @return {?}
     */
    addLayoutGap(layout, layoutBreakpoint, value, breakpoint) {
        value = value || '0';
        const [direction, wrap, isInline] = validateValue(layout);
        const /** @type {?} */ layoutClassName = generateLayoutClassName(direction, wrap, isInline, layoutBreakpoint);
        const /** @type {?} */ layoutGapClassName = generateLayoutGapClassName(value, breakpoint);
        const /** @type {?} */ className = layoutGapClassName + '.' + layoutClassName + ' > *:not(:last-child)';
        if (!this.hasInLayoutStorage(className, breakpoint)) {
            const /** @type {?} */ style = isFlowHorizontal(layout) ? { 'margin-right': value } : { 'margin-bottom': value };
            this.addToLayoutStorage(className, style, breakpoint, [layoutBreakpoint]);
        }
        return layoutGapClassName;
    }
    /**
     * @param {?} layout
     * @param {?} layoutBreakpoint
     * @param {?} value
     * @param {?} breakpoint
     * @param {?=} grow
     * @param {?=} shrink
     * @return {?}
     */
    addFlex(layout, layoutBreakpoint, value, breakpoint, grow, shrink) {
        value = value.replace(';', '');
        let [theGrow, theShrink, theBasis] = validateBasis(value, grow, shrink);
        theGrow = (theGrow === '0') ? 0 : theGrow;
        theShrink = (theShrink === '0') ? 0 : theShrink;
        // flex-basis allows you to specify the initial/starting main-axis size of the element,
        // before anything else is computed. It can either be a percentage or an absolute value.
        // It is, however, not the breaking point for flex-grow/shrink properties
        //
        // flex-grow can be seen as this:
        //   0: Do not stretch. Either size to element's content width, or obey 'flex-basis'.
        //   1: (Default value). Stretch; will be the same size to all other flex items on
        //       the same row since they have a default value of 1.
        //   ≥2 (integer n): Stretch. Will be n times the size of other elements
        //      with 'flex-grow: 1' on the same row.
        const /** @type {?} */ style = {
            'box-sizing': 'border-box',
        };
        switch (theBasis || '') {
            case '':
                style['flex'] = `${theGrow} ${theShrink} 0.000000001px`;
                break;
            case 'initial': // default
            case 'nogrow':
                theGrow = 0;
                style['flex'] = `0 1 auto`;
                break;
            case 'grow':
                style['flex'] = `1 1 100%`;
                break;
            case 'noshrink':
                theShrink = 0;
                style['flex'] = `1 0 auto`;
                break;
            case 'auto':
                style['flex'] = `${theGrow} ${theShrink} auto`;
                break;
            case 'none':
                theGrow = 0;
                theShrink = 0;
                style['flex'] = `0 0 auto`;
                break;
            default:
                const /** @type {?} */ isCalc = String(theBasis).indexOf('calc') > -1;
                const /** @type {?} */ isPercent = !isCalc && String(theBasis).indexOf('%') > -1;
                const /** @type {?} */ isValue = isCalc || isPercent ||
                    String(theBasis).indexOf('px') > -1 ||
                    String(theBasis).indexOf('em') > -1 ||
                    String(theBasis).indexOf('vw') > -1 ||
                    String(theBasis).indexOf('vh') > -1;
                // Defaults to percentage sizing unless `px` is explicitly set
                if (!isValue && !isPercent && !isNaN(/** @type {?} */ (theBasis))) {
                    theBasis = theBasis + '%';
                }
                if (theBasis === '0px') {
                    theBasis = '0%';
                }
                style['flex-grow'] = `${theGrow}`;
                style['flex-shrink'] = `${theShrink}`;
                style['flex-basis'] = style['min-width'] = style['max-width'] = isValue ? `${theBasis}` : '100%';
                break;
        }
        const /** @type {?} */ flexClassName = generateFlexClassName(theGrow, theShrink, theBasis, breakpoint);
        if (!this.hasInFlexStorage(flexClassName, breakpoint)) {
            this.addToFlexStorage(flexClassName, style, breakpoint);
        }
        const [direction, wrap, isInline] = validateValue(layout);
        const /** @type {?} */ layoutClassName = generateLayoutClassName(direction, wrap, isInline, layoutBreakpoint);
        const /** @type {?} */ className = flexClassName + '.' + layoutClassName;
        if (!this.hasInFlexStorage(className, breakpoint)) {
            const /** @type {?} */ max = isFlowHorizontal(direction) ? 'max-width' : 'max-height';
            const /** @type {?} */ min = isFlowHorizontal(direction) ? 'min-width' : 'min-height';
            const /** @type {?} */ usingCalc = (String(theBasis).indexOf('calc') > -1) || (theBasis === 'auto');
            const /** @type {?} */ isPx = String(theBasis).indexOf('px') > -1 || usingCalc;
            // make box inflexible when shrink and grow are both zero
            // should not set a min when the grow is zero
            // should not set a max when the shrink is zero
            const /** @type {?} */ isFixed = !theGrow && !theShrink;
            const /** @type {?} */ layoutStyle = {};
            layoutStyle[min] = (theBasis === '0%') ? 0 : isFixed || (isPx && theGrow) ? theBasis : null;
            layoutStyle[max] = (theBasis === '0%') ? 0 : isFixed || (!usingCalc && theShrink) ? theBasis : null;
            this.addToFlexStorage(className, layoutStyle, breakpoint, [layoutBreakpoint]);
        }
        return flexClassName;
    }
    /**
     * @param {?} order
     * @param {?} breakpoint
     * @return {?}
     */
    addFlexOrder(order, breakpoint) {
        order = parseInt(order, 10);
        order = isNaN(order) ? 0 : order;
        const /** @type {?} */ className = generateFlexOrderClassName(order, breakpoint);
        if (!this.hasInFlexStorage(className, breakpoint)) {
            const /** @type {?} */ style = { 'order': order };
            this.addToFlexStorage(className, style, breakpoint);
        }
        return className;
    }
    /**
     * @param {?} layout
     * @param {?} layoutBreakpoint
     * @param {?} offset
     * @param {?} breakpoint
     * @return {?}
     */
    addFlexOffset(layout, layoutBreakpoint, offset, breakpoint) {
        const /** @type {?} */ isPercent = String(offset).indexOf('%') > -1;
        const /** @type {?} */ isPx = String(offset).indexOf('px') > -1;
        if (!isPx && !isPercent && !isNaN(offset)) {
            offset = offset + '%';
        }
        const [direction, wrap, isInline] = validateValue(layout);
        const /** @type {?} */ offsetClassName = generateFlexOffsetClassName(offset, breakpoint);
        const /** @type {?} */ layoutClassName = generateLayoutClassName(direction, wrap, isInline, layoutBreakpoint);
        const /** @type {?} */ className = offsetClassName + '.' + layoutClassName;
        if (!this.hasInFlexStorage(className, breakpoint)) {
            const /** @type {?} */ style = isFlowHorizontal(direction) ? { 'margin-left': `${offset}` } : { 'margin-top': `${offset}` };
            this.addToFlexStorage(className, style, breakpoint, [layoutBreakpoint]);
        }
        return offsetClassName;
    }
    /**
     * @param {?} align
     * @param {?} breakpoint
     * @return {?}
     */
    addFlexAlign(align, breakpoint) {
        align = align || 'stretch';
        // Cross-axis
        switch (align) {
            case 'start':
                align = 'flex-start';
                break;
            case 'end':
                align = 'flex-end';
                break;
        }
        const /** @type {?} */ className = generateFlexAlignClassName(align, breakpoint);
        if (!this.hasInFlexStorage(className, breakpoint)) {
            const /** @type {?} */ style = { 'align-self': align };
            this.addToFlexStorage(className, style, breakpoint);
        }
        return className;
    }
    /**
     * @return {?}
     */
    addFlexFill() {
        const /** @type {?} */ className = generateFlexFillClassName();
        if (!this.hasInFillStorage(className, 'all')) {
            const /** @type {?} */ style = {
                'margin': 0,
                'width': '100%',
                'height': '100%',
                'min-width': '100%',
                'min-height': '100%',
            };
            this.addToFillStorage(className, style, 'all');
        }
        return className;
    }
    /**
     * @param {?} display
     * @param {?} show
     * @param {?} breakpoint
     * @return {?}
     */
    addShowHide(display, show, breakpoint) {
        const /** @type {?} */ className = generateFlexShowHideClassName(display, show, breakpoint);
        if (!this.hasInFillStorage(className, breakpoint)) {
            const /** @type {?} */ style = {
                'display': show ? display || 'block' : 'none',
            };
            this.addToFillStorage(className, style, breakpoint);
        }
        return className;
    }
    /**
     * @param {?} className
     * @param {?} breakpoint
     * @return {?}
     */
    hasInLayoutStorage(className, breakpoint) {
        return this.hasInStorage(this.layout, className, breakpoint);
    }
    /**
     * @param {?} className
     * @param {?} style
     * @param {?} breakpoint
     * @param {?=} customBreakpoints
     * @return {?}
     */
    addToLayoutStorage(className, style, breakpoint, customBreakpoints) {
        return this.addToStorage(this.layout, className, style, breakpoint, customBreakpoints);
    }
    /**
     * @param {?} className
     * @param {?} breakpoint
     * @return {?}
     */
    hasInFlexStorage(className, breakpoint) {
        return this.hasInStorage(this.flex, className, breakpoint);
    }
    /**
     * @param {?} className
     * @param {?} style
     * @param {?} breakpoint
     * @param {?=} customBreakpoints
     * @return {?}
     */
    addToFlexStorage(className, style, breakpoint, customBreakpoints) {
        return this.addToStorage(this.flex, className, style, breakpoint, customBreakpoints);
    }
    /**
     * @param {?} className
     * @param {?} breakpoint
     * @return {?}
     */
    hasInFillStorage(className, breakpoint) {
        return this.hasInStorage(this.fill, className, breakpoint);
    }
    /**
     * @param {?} className
     * @param {?} style
     * @param {?} breakpoint
     * @param {?=} customBreakpoints
     * @return {?}
     */
    addToFillStorage(className, style, breakpoint, customBreakpoints) {
        return this.addToStorage(this.fill, className, style, breakpoint, customBreakpoints);
    }
    /**
     * @param {?} styleElement
     * @param {?} className
     * @param {?} breakpoint
     * @return {?}
     */
    hasInStorage(styleElement, className, breakpoint) {
        return !!(styleElement.storage[breakpoint] && styleElement.storage[breakpoint][className]);
    }
    /**
     * @param {?} styleElement
     * @param {?} className
     * @param {?} style
     * @param {?} breakpoint
     * @param {?=} customBreakpoints
     * @return {?}
     */
    addToStorage(styleElement, className, style, breakpoint, customBreakpoints) {
        customBreakpoints = customBreakpoints || [];
        const /** @type {?} */ styles = applyCssPrefixes(style);
        const /** @type {?} */ css = this.generateCss(styles);
        if (css !== '') {
            const /** @type {?} */ classCss = '.' + className + ' { ' + css + ' }';
            const /** @type {?} */ cssElement = this.doc.createTextNode(this.addBreakpoints([breakpoint].concat(customBreakpoints), classCss));
            if (!styleElement.storage[breakpoint]) {
                styleElement.storage[breakpoint] = {};
            }
            styleElement.storage[breakpoint][className] = cssElement;
            this.reorderTextElements(styleElement);
        }
    }
    /**
     * @param {?} styleElement
     * @return {?}
     */
    reorderTextElements(styleElement) {
        let /** @type {?} */ position = this.reorderBreakpointElements(styleElement, 'all');
        this.breakpoints.forEach(breakpoint => {
            position = this.reorderBreakpointElements(styleElement, breakpoint.alias, position);
        });
    }
    /**
     * @param {?} styleElement
     * @param {?} breakpoint
     * @param {?=} position
     * @return {?}
     */
    reorderBreakpointElements(styleElement, breakpoint, position = 0) {
        const /** @type {?} */ breakpointElements = styleElement.storage[breakpoint];
        if (!breakpointElements) {
            return position;
        }
        Object.keys(breakpointElements).forEach(key => {
            if (styleElement.style.children.length) {
                styleElement.style.insertBefore(breakpointElements[key], styleElement.style.children[position]);
            }
            else {
                styleElement.style.appendChild(breakpointElements[key]);
            }
            ++position;
        });
        return position;
    }
    /**
     * @param {?} styles
     * @return {?}
     */
    generateCss(styles) {
        const /** @type {?} */ css = [];
        Object.keys(styles).sort().forEach(key => {
            const /** @type {?} */ values = Array.isArray(styles[key]) ? styles[key] : [styles[key]];
            values.sort();
            values.forEach(value => {
                if (value !== null && value !== '') {
                    css.push(key + ': ' + value + ';');
                }
            });
        });
        return css.join(' ');
    }
    /**
     * @param {?} breakpointsAliases
     * @param {?} css
     * @return {?}
     */
    addBreakpoints(breakpointsAliases, css) {
        breakpointsAliases = breakpointsAliases.filter(breakpoint => breakpoint !== 'all');
        if (!breakpointsAliases.length) {
            return css;
        }
        let /** @type {?} */ theBreakpoints = [];
        this.breakpoints
            .filter(breakpoint => breakpointsAliases.indexOf(breakpoint.alias) >= 0)
            .forEach(breakpoint => theBreakpoints = theBreakpoints.concat(breakpoint.media));
        theBreakpoints = theBreakpoints.filter((value, index, self) => self.indexOf(value) === index);
        return '@media ' + theBreakpoints.join(' and ') + ' { ' + css + ' }';
    }
}
FlexCssService.decorators = [
    { type: Injectable },
];
/** @nocollapse */
FlexCssService.ctorParameters = () => [
    { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] },
    { type: undefined, decorators: [{ type: Inject, args: [FLEX_CSS_BREAKPOINTS,] }] }
];
function FlexCssService_tsickle_Closure_declarations() {
    /** @type {?} */
    FlexCssService.prototype.layout;
    /** @type {?} */
    FlexCssService.prototype.flex;
    /** @type {?} */
    FlexCssService.prototype.fill;
    /** @type {?} */
    FlexCssService.prototype.doc;
    /** @type {?} */
    FlexCssService.prototype.breakpoints;
}

//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxleC1jc3Muc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0BncmVnLW1kL25nLWZsZXgtY3NzLWxheW91dC8iLCJzb3VyY2VzIjpbImxpYi9mbGV4LWNzcy5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRW5FLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxhQUFhLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDL0UsT0FBTyxFQUNMLHVCQUF1QixFQUFFLHlCQUF5QixFQUFFLDRCQUE0QixFQUNoRiwwQkFBMEIsRUFBRSxxQkFBcUIsRUFBRSwwQkFBMEIsRUFBRSwyQkFBMkIsRUFDMUcsMEJBQTBCLEVBQUUseUJBQXlCLEVBQUUsNkJBQTZCLEVBQ3JGLE1BQU0sV0FBVyxDQUFDO0FBQ25CLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQzs7Ozs7Ozs7Ozs7QUFPbEQsTUFBTSxDQUFDLHVCQUFNLDRCQUE0QixHQUFpQjtJQUN4RCxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUMsUUFBUSxFQUFFLG9CQUFvQixDQUFDLEVBQUU7SUFDM0QsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxDQUFDLFFBQVEsRUFBRSxxQkFBcUIsQ0FBQyxFQUFFO0lBQzVELEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxRQUFRLEVBQUUsb0JBQW9CLENBQUMsRUFBRTtJQUMzRCxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUMsUUFBUSxFQUFFLHFCQUFxQixDQUFDLEVB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LElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssS0FBSyxDQUFDLENBQUM7UUFFOUYsTUFBTSxDQUFDLFNBQVMsR0FBRyxjQUFjLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEtBQUssR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDOzs7O1lBcGJ4RSxVQUFVOzs7OzRDQVNOLE1BQU0sU0FBQyxRQUFROzRDQUNmLE1BQU0sU0FBQyxvQkFBb0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBET0NVTUVOVCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBJbmplY3RhYmxlLCBJbmplY3QsIEluamVjdGlvblRva2VuIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7IGFwcGx5Q3NzUHJlZml4ZXMgfSBmcm9tICcuL2F1dG8tcHJlZml4ZXInO1xuaW1wb3J0IHsgdmFsaWRhdGVWYWx1ZSwgYnVpbGRDU1MsIGlzRmxvd0hvcml6b250YWwgfSBmcm9tICcuL2xheW91dC12YWxpZGF0b3InO1xuaW1wb3J0IHtcbiAgZ2VuZXJhdGVMYXlvdXRDbGFzc05hbWUsIG5vcm1hbGl6ZUxheW91dEFsaWduVmFsdWUsIGdlbmVyYXRlTGF5b3V0QWxpZ25DbGFzc05hbWUsXG4gIGdlbmVyYXRlTGF5b3V0R2FwQ2xhc3NOYW1lLCBnZW5lcmF0ZUZsZXhDbGFzc05hbWUsIGdlbmVyYXRlRmxleE9yZGVyQ2xhc3NOYW1lLCBnZW5lcmF0ZUZsZXhPZmZzZXRDbGFzc05hbWUsXG4gIGdlbmVyYXRlRmxleEFsaWduQ2xhc3NOYW1lLCBnZW5lcmF0ZUZsZXhGaWxsQ2xhc3NOYW1lLCBnZW5lcmF0ZUZsZXhTaG93SGlkZUNsYXNzTmFtZVxufSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHsgdmFsaWRhdGVCYXNpcyB9IGZyb20gJy4vYmFzaXMtdmFsaWRhdG9yJztcblxuZXhwb3J0IGludGVyZmFjZSBCcmVha3BvaW50IHtcbiAgYWxpYXM6IHN0cmluZztcbiAgbWVkaWE6IHN0cmluZ1tdO1xufVxuXG5leHBvcnQgY29uc3QgRkxFWF9DU1NfREVGQVVMVF9CUkVBS1BPSU5UUzogQnJlYWtwb2ludFtdID0gW1xuICB7IGFsaWFzOiAnZ3QteHMnLCBtZWRpYTogWydzY3JlZW4nLCAnKG1pbi13aWR0aDogNjAwcHgpJ10gfSxcbiAgeyBhbGlhczogJ2x0LXhsJywgbWVkaWE6IFsnc2NyZWVuJywgJyhtYXgtd2lkdGg6IDE5MTlweCknXSB9LFxuICB7IGFsaWFzOiAnZ3Qtc20nLCBtZWRpYTogWydzY3JlZW4nLCAnKG1pbi13aWR0aDogOTYwcHgpJ10gfSxcbiAgeyBhbGlhczogJ2x0LWxnJywgbWVkaWE6IFsnc2NyZWVuJywgJyhtYXgtd2lkdGg6IDEyNzlweCknXSB9LFxuICB7IGFsaWFzOiAnZ3QtbWQnLCBtZWRpYTogWydzY3JlZW4nLCAnKG1pbi13aWR0aDogMTI4MHB4KSddIH0sXG4gIHsgYWxpYXM6ICdsdC1tZCcsIG1lZGlhOiBbJ3NjcmVlbicsICcobWF4LXdpZHRoOiA5NTlweCknXSB9LFxuICB7IGFsaWFzOiAnZ3QtbGcnLCBtZWRpYTogWydzY3JlZW4nLCAnKG1pbi13aWR0aDogMTkyMHB4KSddIH0sXG4gIHsgYWxpYXM6ICdsdC1zbScsIG1lZGlhOiBbJ3NjcmVlbicsICcobWF4LXdpZHRoOiA1OTlweCknXSB9LFxuICB7IGFsaWFzOiAneGwnLCAgICBtZWRpYTogWydzY3JlZW4nLCAnKG1pbi13aWR0aDogMTkyMHB4KScsICcobWF4LXdpZHRoOiA1MDAwcHgpJ10gfSxcbiAgeyBhbGlhczogJ2xnJywgICAgbWVkaWE6IFsnc2NyZWVuJywgJyhtaW4td2lkdGg6IDEyODBweCknLCAnKG1heC13aWR0aDogMTkxOXB4KSddIH0sXG4gIHsgYWxpYXM6ICdtZCcsICAgIG1lZGlhOiBbJ3NjcmVlbicsICcobWluLXdpZHRoOiA5NjBweCknLCAnKG1heC13aWR0aDogMTI3OXB4KSddIH0sXG4gIHsgYWxpYXM6ICdzbScsICAgIG1lZGlhOiBbJ3NjcmVlbicsICcobWluLXdpZHRoOiA2MDBweCknLCAnKG1heC13aWR0aDogOTU5cHgpJ10gfSxcbiAgeyBhbGlhczogJ3hzJywgICAgbWVkaWE6IFsnc2NyZWVuJywgJyhtYXgtd2lkdGg6IDU5OXB4KSddIH0sXG5dO1xuXG5leHBvcnQgY29uc3QgRkxFWF9DU1NfQlJFQUtQT0lOVFNfU01BTExfVE9fTEFSR0U6IEJyZWFrcG9pbnRbXSA9IFtcbiAgeyBhbGlhczogJ2x0LXNtJywgbWVkaWE6IFsnc2NyZWVuJywgJyhtYXgtd2lkdGg6IDU5OXB4KSddIH0sXG4gIHsgYWxpYXM6ICd4cycsICAgIG1lZGlhOiBbJ3NjcmVlbicsICcobWF4LXdpZHRoOiA1OTlweCknXSB9LFxuICB7IGFsaWFzOiAnZ3QteHMnLCBtZWRpYTogWydzY3JlZW4nLCAnKG1pbi13aWR0aDogNjAwcHgpJ10gfSxcblxuICB7IGFsaWFzOiAnbHQtbWQnLCBtZWRpYTogWydzY3JlZW4nLCAnKG1heC13aWR0aDogOTU5cHgpJ10gfSxcbiAgeyBhbGlhczogJ3NtJywgICAgbWVkaWE6IFsnc2NyZWVuJywgJyhtaW4td2lkdGg6IDYwMHB4KScsICcobWF4LXdpZHRoOiA5NTlweCknXSB9LFxuICB7IGFsaWFzOiAnZ3Qtc20nLCBtZWRpYTogWydzY3JlZW4nLCAnKG1pbi13aWR0aDogOTYwcHgpJ10gfSxcblxuICB7IGFsaWFzOiAnbHQtbGcnLCBtZWRpYTogWydzY3JlZW4nLCAnKG1heC13aWR0aDogMTI3OXB4KSddIH0sXG4gIHsgYWxpYXM6ICdtZCcsICAgIG1lZGlhOiBbJ3NjcmVlbicsICcobWluLXdpZHRoOiA5NjBweCknLCAnKG1heC13aWR0aDogMTI3OXB4KSddIH0sXG4gIHsgYWxpYXM6ICdndC1tZCcsIG1lZGlhOiBbJ3NjcmVlbicsICcobWluLXdpZHRoOiAxMjgwcHgpJ10gfSxcblxuICB7IGFsaWFzOiAnbHQteGwnLCBtZWRpYTogWydzY3JlZW4nLCAnKG1heC13aWR0aDogMTkxOXB4KSddIH0sXG4gIHsgYWxpYXM6ICdsZycsICAgIG1lZGlhOiBbJ3NjcmVlbicsICcobWluLXdpZHRoOiAxMjgwcHgpJywgJyhtYXgtd2lkdGg6IDE5MTlweCknXSB9LFxuICB7IGFsaWFzOiAnZ3QtbGcnLCBtZWRpYTogWydzY3JlZW4nLCAnKG1pbi13aWR0aDogMTkyMHB4KSddIH0sXG5cbiAgeyBhbGlhczogJ3hsJywgICAgbWVkaWE6IFsnc2NyZWVuJywgJyhtaW4td2lkdGg6IDE5MjBweCknLCAnKG1heC13aWR0aDogNTAwMHB4KSddIH0sXG5dO1xuXG5leHBvcnQgY29uc3QgRkxFWF9DU1NfQlJFQUtQT0lOVFMgPSBuZXcgSW5qZWN0aW9uVG9rZW48c3RyaW5nPignZmxleF9jc3NfYnJlYWtwb2ludHMnKTtcblxuZXhwb3J0IHR5cGUgU3R5bGVEZWZpbml0aW9uID0gc3RyaW5nIHwgeyBbcHJvcGVydHk6IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IG51bGwgfTtcblxuZXhwb3J0IGNsYXNzIEZsZXhDc3NTdHlsZUVsZW1lbnQge1xuICBwdWJsaWMgc3RvcmFnZTogeyBbcHJvcGVydHk6IHN0cmluZ106IHsgW3Byb3BlcnR5OiBzdHJpbmddOiBUZXh0IH0gfSA9IHt9O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyBzdHlsZTogSFRNTFN0eWxlRWxlbWVudCxcbiAgKSB7fVxufVxuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgRmxleENzc1NlcnZpY2Uge1xuICBwcml2YXRlIGxheW91dDogRmxleENzc1N0eWxlRWxlbWVudDtcblxuICBwcml2YXRlIGZsZXg6IEZsZXhDc3NTdHlsZUVsZW1lbnQ7XG5cbiAgcHJpdmF0ZSBmaWxsOiBGbGV4Q3NzU3R5bGVFbGVtZW50O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBJbmplY3QoRE9DVU1FTlQpIHByaXZhdGUgZG9jLFxuICAgIEBJbmplY3QoRkxFWF9DU1NfQlJFQUtQT0lOVFMpIHByaXZhdGUgYnJlYWtwb2ludHMsXG4gICkge1xuICAgIHRoaXMuaW5pdExheW91dCgpO1xuICAgIHRoaXMuaW5pdEZsZXgoKTtcbiAgICB0aGlzLmluaXRGaWxsKCk7XG4gIH1cblxuICBpbml0TGF5b3V0KCkge1xuICAgIGNvbnN0IHN0eWxlID0gdGhpcy5kb2MuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcblxuICAgIHN0eWxlLmlkID0gJ2ZjLWxheW91dCc7XG5cbiAgICB0aGlzLmRvYy5oZWFkLmFwcGVuZENoaWxkKHN0eWxlKTtcblxuICAgIHRoaXMubGF5b3V0ID0gbmV3IEZsZXhDc3NTdHlsZUVsZW1lbnQoc3R5bGUpO1xuICB9XG5cbiAgaW5pdEZsZXgoKSB7XG4gICAgY29uc3Qgc3R5bGUgPSB0aGlzLmRvYy5jcmVhdGVFbGVtZW50KCdzdHlsZScpO1xuXG4gICAgc3R5bGUuaWQgPSAnZmMtZmxleCc7XG5cbiAgICB0aGlzLmRvYy5oZWFkLmFwcGVuZENoaWxkKHN0eWxlKTtcblxuICAgIHRoaXMuZmxleCA9IG5ldyBGbGV4Q3NzU3R5bGVFbGVtZW50KHN0eWxlKTtcbiAgfVxuXG4gIGluaXRGaWxsKCkge1xuICAgIGNvbnN0IHN0eWxlID0gdGhpcy5kb2MuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcblxuICAgIHN0eWxlLmlkID0gJ2ZjLWZpbGwnO1xuXG4gICAgdGhpcy5kb2MuaGVhZC5hcHBlbmRDaGlsZChzdHlsZSk7XG5cbiAgICB0aGlzLmZpbGwgPSBuZXcgRmxleENzc1N0eWxlRWxlbWVudChzdHlsZSk7XG4gIH1cblxuICBhZGRMYXlvdXQobGF5b3V0OiBzdHJpbmcsIGJyZWFrcG9pbnQ6IHN0cmluZykge1xuICAgIGNvbnN0IFtkaXJlY3Rpb24sIHdyYXAsIGlzSW5saW5lXSA9IHZhbGlkYXRlVmFsdWUobGF5b3V0KTtcblxuICAgIGNvbnN0IGNsYXNzTmFtZSA9IGdlbmVyYXRlTGF5b3V0Q2xhc3NOYW1lKGRpcmVjdGlvbiwgd3JhcCwgaXNJbmxpbmUsIGJyZWFrcG9pbnQpO1xuXG4gICAgaWYgKCF0aGlzLmhhc0luTGF5b3V0U3RvcmFnZShjbGFzc05hbWUsIGJyZWFrcG9pbnQpKSB7XG4gICAgICBjb25zdCBzdHlsZSA9IGJ1aWxkQ1NTKGRpcmVjdGlvbiwgd3JhcCwgaXNJbmxpbmUpO1xuXG4gICAgICB0aGlzLmFkZFRvTGF5b3V0U3RvcmFnZShjbGFzc05hbWUsIHN0eWxlLCBicmVha3BvaW50KTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2xhc3NOYW1lO1xuICB9XG5cbiAgYWRkTGF5b3V0QWxpZ24obGF5b3V0OiBzdHJpbmcsIGxheW91dEJyZWFrcG9pbnQ6IHN0cmluZywgYWxpZ246IHN0cmluZywgYnJlYWtwb2ludDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBbbWFpbkF4aXMsIGNyb3NzQXhpc10gPSBub3JtYWxpemVMYXlvdXRBbGlnblZhbHVlKGFsaWduKTtcblxuICAgIGNvbnN0IGxheW91dEFsaWduQ2xhc3NOYW1lID0gZ2VuZXJhdGVMYXlvdXRBbGlnbkNsYXNzTmFtZShtYWluQXhpcywgY3Jvc3NBeGlzLCBicmVha3BvaW50KTtcblxuICAgIGlmICghdGhpcy5oYXNJbkxheW91dFN0b3JhZ2UobGF5b3V0QWxpZ25DbGFzc05hbWUsIGJyZWFrcG9pbnQpKSB7XG4gICAgICBjb25zdCBzdHlsZSA9IHtcbiAgICAgICAgJ2p1c3RpZnktY29udGVudCc6IG1haW5BeGlzLFxuICAgICAgfTtcblxuICAgICAgc3dpdGNoIChjcm9zc0F4aXMpIHtcbiAgICAgICAgY2FzZSAnYmFzZWxpbmUnOlxuICAgICAgICAgIHN0eWxlWydhbGlnbi1pdGVtcyddID0gY3Jvc3NBeGlzO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHN0eWxlWydhbGlnbi1pdGVtcyddID0gc3R5bGVbJ2FsaWduLWNvbnRlbnQnXSA9IGNyb3NzQXhpcztcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgdGhpcy5hZGRUb0xheW91dFN0b3JhZ2UobGF5b3V0QWxpZ25DbGFzc05hbWUsIHN0eWxlLCBicmVha3BvaW50KTtcbiAgICB9XG5cbiAgICBpZiAoY3Jvc3NBeGlzID09PSAnc3RyZXRjaCcpIHtcbiAgICAgIGNvbnN0IFtkaXJlY3Rpb24sIHdyYXAsIGlzSW5saW5lXSA9IHZhbGlkYXRlVmFsdWUobGF5b3V0KTtcblxuICAgICAgY29uc3QgbGF5b3V0Q2xhc3NOYW1lID0gZ2VuZXJhdGVMYXlvdXRDbGFzc05hbWUoZGlyZWN0aW9uLCB3cmFwLCBpc0lubGluZSwgbGF5b3V0QnJlYWtwb2ludCk7XG5cbiAgICAgIGNvbnN0IGNsYXNzTmFtZSA9IGxheW91dEFsaWduQ2xhc3NOYW1lICsgJy4nICsgbGF5b3V0Q2xhc3NOYW1lO1xuXG4gICAgICBpZiAoIXRoaXMuaGFzSW5MYXlvdXRTdG9yYWdlKGNsYXNzTmFtZSwgYnJlYWtwb2ludCkpIHtcbiAgICAgICAgY29uc3Qgc3R5bGUgPSBpc0Zsb3dIb3Jpem9udGFsKGxheW91dCkgPyB7ICdtYXgtaGVpZ2h0JzogJzEwMCUnIH0gOiB7ICdtYXgtd2lkdGgnOiAnMTAwJScgfTtcblxuICAgICAgICB0aGlzLmFkZFRvTGF5b3V0U3RvcmFnZShjbGFzc05hbWUsIHN0eWxlLCBicmVha3BvaW50LCBbbGF5b3V0QnJlYWtwb2ludF0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBsYXlvdXRBbGlnbkNsYXNzTmFtZTtcbiAgfVxuXG4gIGFkZExheW91dEdhcChsYXlvdXQ6IHN0cmluZywgbGF5b3V0QnJlYWtwb2ludDogc3RyaW5nLCB2YWx1ZTogc3RyaW5nLCBicmVha3BvaW50OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHZhbHVlID0gdmFsdWUgfHwgJzAnO1xuXG4gICAgY29uc3QgW2RpcmVjdGlvbiwgd3JhcCwgaXNJbmxpbmVdID0gdmFsaWRhdGVWYWx1ZShsYXlvdXQpO1xuXG4gICAgY29uc3QgbGF5b3V0Q2xhc3NOYW1lID0gZ2VuZXJhdGVMYXlvdXRDbGFzc05hbWUoZGlyZWN0aW9uLCB3cmFwLCBpc0lubGluZSwgbGF5b3V0QnJlYWtwb2ludCk7XG5cbiAgICBjb25zdCBsYXlvdXRHYXBDbGFzc05hbWUgPSBnZW5lcmF0ZUxheW91dEdhcENsYXNzTmFtZSh2YWx1ZSwgYnJlYWtwb2ludCk7XG5cbiAgICBjb25zdCBjbGFzc05hbWUgPSBsYXlvdXRHYXBDbGFzc05hbWUgKyAnLicgKyBsYXlvdXRDbGFzc05hbWUgKyAnID4gKjpub3QoOmxhc3QtY2hpbGQpJztcblxuICAgIGlmICghdGhpcy5oYXNJbkxheW91dFN0b3JhZ2UoY2xhc3NOYW1lLCBicmVha3BvaW50KSkge1xuICAgICAgY29uc3Qgc3R5bGUgPSBpc0Zsb3dIb3Jpem9udGFsKGxheW91dCkgPyB7ICdtYXJnaW4tcmlnaHQnOiB2YWx1ZSB9IDogeyAnbWFyZ2luLWJvdHRvbSc6IHZhbHVlIH07XG5cbiAgICAgIHRoaXMuYWRkVG9MYXlvdXRTdG9yYWdlKGNsYXNzTmFtZSwgc3R5bGUsIGJyZWFrcG9pbnQsIFtsYXlvdXRCcmVha3BvaW50XSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGxheW91dEdhcENsYXNzTmFtZTtcbiAgfVxuXG4gIGFkZEZsZXgobGF5b3V0OiBzdHJpbmcsIGxheW91dEJyZWFrcG9pbnQ6IHN0cmluZywgdmFsdWU6IHN0cmluZywgYnJlYWtwb2ludDogc3RyaW5nLCBncm93Pywgc2hyaW5rPykge1xuICAgIHZhbHVlID0gdmFsdWUucmVwbGFjZSgnOycsICcnKTtcblxuICAgIGxldCBbdGhlR3JvdywgdGhlU2hyaW5rLCB0aGVCYXNpc10gPSB2YWxpZGF0ZUJhc2lzKHZhbHVlLCBncm93LCBzaHJpbmspO1xuXG4gICAgdGhlR3JvdyA9ICh0aGVHcm93ID09PSAnMCcpID8gMCA6IHRoZUdyb3c7XG4gICAgdGhlU2hyaW5rID0gKHRoZVNocmluayA9PT0gJzAnKSA/IDAgOiB0aGVTaHJpbms7XG5cbiAgICAvLyBmbGV4LWJhc2lzIGFsbG93cyB5b3UgdG8gc3BlY2lmeSB0aGUgaW5pdGlhbC9zdGFydGluZyBtYWluLWF4aXMgc2l6ZSBvZiB0aGUgZWxlbWVudCxcbiAgICAvLyBiZWZvcmUgYW55dGhpbmcgZWxzZSBpcyBjb21wdXRlZC4gSXQgY2FuIGVpdGhlciBiZSBhIHBlcmNlbnRhZ2Ugb3IgYW4gYWJzb2x1dGUgdmFsdWUuXG4gICAgLy8gSXQgaXMsIGhvd2V2ZXIsIG5vdCB0aGUgYnJlYWtpbmcgcG9pbnQgZm9yIGZsZXgtZ3Jvdy9zaHJpbmsgcHJvcGVydGllc1xuICAgIC8vXG4gICAgLy8gZmxleC1ncm93IGNhbiBiZSBzZWVuIGFzIHRoaXM6XG4gICAgLy8gICAwOiBEbyBub3Qgc3RyZXRjaC4gRWl0aGVyIHNpemUgdG8gZWxlbWVudCdzIGNvbnRlbnQgd2lkdGgsIG9yIG9iZXkgJ2ZsZXgtYmFzaXMnLlxuICAgIC8vICAgMTogKERlZmF1bHQgdmFsdWUpLiBTdHJldGNoOyB3aWxsIGJlIHRoZSBzYW1lIHNpemUgdG8gYWxsIG90aGVyIGZsZXggaXRlbXMgb25cbiAgICAvLyAgICAgICB0aGUgc2FtZSByb3cgc2luY2UgdGhleSBoYXZlIGEgZGVmYXVsdCB2YWx1ZSBvZiAxLlxuICAgIC8vICAg4omlMiAoaW50ZWdlciBuKTogU3RyZXRjaC4gV2lsbCBiZSBuIHRpbWVzIHRoZSBzaXplIG9mIG90aGVyIGVsZW1lbnRzXG4gICAgLy8gICAgICB3aXRoICdmbGV4LWdyb3c6IDEnIG9uIHRoZSBzYW1lIHJvdy5cblxuICAgIGNvbnN0IHN0eWxlID0ge1xuICAgICAgJ2JveC1zaXppbmcnOiAnYm9yZGVyLWJveCcsXG4gICAgfTtcblxuICAgIHN3aXRjaCAodGhlQmFzaXMgfHwgJycpIHtcbiAgICAgIGNhc2UgJyc6XG4gICAgICAgIHN0eWxlWydmbGV4J10gPSBgJHt0aGVHcm93fSAke3RoZVNocmlua30gMC4wMDAwMDAwMDFweGA7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaW5pdGlhbCc6ICAgLy8gZGVmYXVsdFxuICAgICAgY2FzZSAnbm9ncm93JzpcbiAgICAgICAgdGhlR3JvdyA9IDA7XG4gICAgICAgIHN0eWxlWydmbGV4J10gPSBgMCAxIGF1dG9gO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2dyb3cnOlxuICAgICAgICBzdHlsZVsnZmxleCddID0gYDEgMSAxMDAlYDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdub3Nocmluayc6XG4gICAgICAgIHRoZVNocmluayA9IDA7XG4gICAgICAgIHN0eWxlWydmbGV4J10gPSBgMSAwIGF1dG9gO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2F1dG8nOlxuICAgICAgICBzdHlsZVsnZmxleCddID0gYCR7dGhlR3Jvd30gJHt0aGVTaHJpbmt9IGF1dG9gO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ25vbmUnOlxuICAgICAgICB0aGVHcm93ID0gMDtcbiAgICAgICAgdGhlU2hyaW5rID0gMDtcbiAgICAgICAgc3R5bGVbJ2ZsZXgnXSA9IGAwIDAgYXV0b2A7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc3QgaXNDYWxjID0gU3RyaW5nKHRoZUJhc2lzKS5pbmRleE9mKCdjYWxjJykgPiAtMTtcbiAgICAgICAgY29uc3QgaXNQZXJjZW50ID0gIWlzQ2FsYyAmJiBTdHJpbmcodGhlQmFzaXMpLmluZGV4T2YoJyUnKSA+IC0xO1xuXG4gICAgICAgIGNvbnN0IGlzVmFsdWUgPSBpc0NhbGMgfHwgaXNQZXJjZW50IHx8XG4gICAgICAgICAgU3RyaW5nKHRoZUJhc2lzKS5pbmRleE9mKCdweCcpID4gLTEgfHxcbiAgICAgICAgICBTdHJpbmcodGhlQmFzaXMpLmluZGV4T2YoJ2VtJykgPiAtMSB8fFxuICAgICAgICAgIFN0cmluZyh0aGVCYXNpcykuaW5kZXhPZigndncnKSA+IC0xIHx8XG4gICAgICAgICAgU3RyaW5nKHRoZUJhc2lzKS5pbmRleE9mKCd2aCcpID4gLTE7XG5cbiAgICAgICAgLy8gRGVmYXVsdHMgdG8gcGVyY2VudGFnZSBzaXppbmcgdW5sZXNzIGBweGAgaXMgZXhwbGljaXRseSBzZXRcbiAgICAgICAgaWYgKCFpc1ZhbHVlICYmICFpc1BlcmNlbnQgJiYgIWlzTmFOKHRoZUJhc2lzIGFzIGFueSkpIHtcbiAgICAgICAgICB0aGVCYXNpcyA9IHRoZUJhc2lzICsgJyUnO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoZUJhc2lzID09PSAnMHB4Jykge1xuICAgICAgICAgIHRoZUJhc2lzID0gJzAlJztcbiAgICAgICAgfVxuXG4gICAgICAgIHN0eWxlWydmbGV4LWdyb3cnXSA9IGAke3RoZUdyb3d9YDtcbiAgICAgICAgc3R5bGVbJ2ZsZXgtc2hyaW5rJ10gPSBgJHt0aGVTaHJpbmt9YDtcbiAgICAgICAgc3R5bGVbJ2ZsZXgtYmFzaXMnXSA9IHN0eWxlWydtaW4td2lkdGgnXSA9IHN0eWxlWydtYXgtd2lkdGgnXSA9IGlzVmFsdWUgPyBgJHt0aGVCYXNpc31gIDogJzEwMCUnO1xuICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICBjb25zdCBmbGV4Q2xhc3NOYW1lID0gZ2VuZXJhdGVGbGV4Q2xhc3NOYW1lKHRoZUdyb3csIHRoZVNocmluaywgdGhlQmFzaXMsIGJyZWFrcG9pbnQpO1xuXG4gICAgaWYgKCF0aGlzLmhhc0luRmxleFN0b3JhZ2UoZmxleENsYXNzTmFtZSwgYnJlYWtwb2ludCkpIHtcbiAgICAgIHRoaXMuYWRkVG9GbGV4U3RvcmFnZShmbGV4Q2xhc3NOYW1lLCBzdHlsZSwgYnJlYWtwb2ludCk7XG4gICAgfVxuXG4gICAgY29uc3QgW2RpcmVjdGlvbiwgd3JhcCwgaXNJbmxpbmVdID0gdmFsaWRhdGVWYWx1ZShsYXlvdXQpO1xuXG4gICAgY29uc3QgbGF5b3V0Q2xhc3NOYW1lID0gZ2VuZXJhdGVMYXlvdXRDbGFzc05hbWUoZGlyZWN0aW9uLCB3cmFwLCBpc0lubGluZSwgbGF5b3V0QnJlYWtwb2ludCk7XG5cbiAgICBjb25zdCBjbGFzc05hbWUgPSBmbGV4Q2xhc3NOYW1lICsgJy4nICsgbGF5b3V0Q2xhc3NOYW1lO1xuXG4gICAgaWYgKCF0aGlzLmhhc0luRmxleFN0b3JhZ2UoY2xhc3NOYW1lLCBicmVha3BvaW50KSkge1xuICAgICAgY29uc3QgbWF4ID0gaXNGbG93SG9yaXpvbnRhbChkaXJlY3Rpb24pID8gJ21heC13aWR0aCcgOiAnbWF4LWhlaWdodCc7XG4gICAgICBjb25zdCBtaW4gPSBpc0Zsb3dIb3Jpem9udGFsKGRpcmVjdGlvbikgPyAnbWluLXdpZHRoJyA6ICdtaW4taGVpZ2h0JztcblxuICAgICAgY29uc3QgdXNpbmdDYWxjID0gKFN0cmluZyh0aGVCYXNpcykuaW5kZXhPZignY2FsYycpID4gLTEpIHx8ICh0aGVCYXNpcyA9PT0gJ2F1dG8nKTtcbiAgICAgIGNvbnN0IGlzUHggPSBTdHJpbmcodGhlQmFzaXMpLmluZGV4T2YoJ3B4JykgPiAtMSB8fCB1c2luZ0NhbGM7XG5cbiAgICAgIC8vIG1ha2UgYm94IGluZmxleGlibGUgd2hlbiBzaHJpbmsgYW5kIGdyb3cgYXJlIGJvdGggemVyb1xuICAgICAgLy8gc2hvdWxkIG5vdCBzZXQgYSBtaW4gd2hlbiB0aGUgZ3JvdyBpcyB6ZXJvXG4gICAgICAvLyBzaG91bGQgbm90IHNldCBhIG1heCB3aGVuIHRoZSBzaHJpbmsgaXMgemVyb1xuICAgICAgY29uc3QgaXNGaXhlZCA9ICF0aGVHcm93ICYmICF0aGVTaHJpbms7XG5cbiAgICAgIGNvbnN0IGxheW91dFN0eWxlID0ge307XG5cbiAgICAgIGxheW91dFN0eWxlW21pbl0gPSAodGhlQmFzaXMgPT09ICcwJScpID8gMCA6IGlzRml4ZWQgfHwgKGlzUHggJiYgdGhlR3JvdykgPyB0aGVCYXNpcyA6IG51bGw7XG4gICAgICBsYXlvdXRTdHlsZVttYXhdID0gKHRoZUJhc2lzID09PSAnMCUnKSA/IDAgOiBpc0ZpeGVkIHx8ICghdXNpbmdDYWxjICYmIHRoZVNocmluaykgPyB0aGVCYXNpcyA6IG51bGw7XG5cbiAgICAgIHRoaXMuYWRkVG9GbGV4U3RvcmFnZShjbGFzc05hbWUsIGxheW91dFN0eWxlLCBicmVha3BvaW50LCBbbGF5b3V0QnJlYWtwb2ludF0pO1xuICAgIH1cblxuICAgIHJldHVybiBmbGV4Q2xhc3NOYW1lO1xuICB9XG5cbiAgYWRkRmxleE9yZGVyKG9yZGVyLCBicmVha3BvaW50OiBzdHJpbmcpIHtcbiAgICBvcmRlciA9IHBhcnNlSW50KG9yZGVyLCAxMCk7XG5cbiAgICBvcmRlciA9IGlzTmFOKG9yZGVyKSA/IDAgOiBvcmRlcjtcblxuICAgIGNvbnN0IGNsYXNzTmFtZSA9IGdlbmVyYXRlRmxleE9yZGVyQ2xhc3NOYW1lKG9yZGVyLCBicmVha3BvaW50KTtcblxuICAgIGlmICghdGhpcy5oYXNJbkZsZXhTdG9yYWdlKGNsYXNzTmFtZSwgYnJlYWtwb2ludCkpIHtcbiAgICAgIGNvbnN0IHN0eWxlID0geydvcmRlcic6IG9yZGVyfTtcblxuICAgICAgdGhpcy5hZGRUb0ZsZXhTdG9yYWdlKGNsYXNzTmFtZSwgc3R5bGUsIGJyZWFrcG9pbnQpO1xuICAgIH1cblxuICAgIHJldHVybiBjbGFzc05hbWU7XG4gIH1cblxuICBhZGRGbGV4T2Zmc2V0KGxheW91dDogc3RyaW5nLCBsYXlvdXRCcmVha3BvaW50OiBzdHJpbmcsIG9mZnNldCwgYnJlYWtwb2ludDogc3RyaW5nKSB7XG4gICAgY29uc3QgaXNQZXJjZW50ID0gU3RyaW5nKG9mZnNldCkuaW5kZXhPZignJScpID4gLTE7XG4gICAgY29uc3QgaXNQeCA9IFN0cmluZyhvZmZzZXQpLmluZGV4T2YoJ3B4JykgPiAtMTtcblxuICAgIGlmICghaXNQeCAmJiAhaXNQZXJjZW50ICYmICFpc05hTihvZmZzZXQpKSB7XG4gICAgICBvZmZzZXQgPSBvZmZzZXQgKyAnJSc7XG4gICAgfVxuXG4gICAgY29uc3QgW2RpcmVjdGlvbiwgd3JhcCwgaXNJbmxpbmVdID0gdmFsaWRhdGVWYWx1ZShsYXlvdXQpO1xuXG4gICAgY29uc3Qgb2Zmc2V0Q2xhc3NOYW1lID0gZ2VuZXJhdGVGbGV4T2Zmc2V0Q2xhc3NOYW1lKG9mZnNldCwgYnJlYWtwb2ludCk7XG5cbiAgICBjb25zdCBsYXlvdXRDbGFzc05hbWUgPSBnZW5lcmF0ZUxheW91dENsYXNzTmFtZShkaXJlY3Rpb24sIHdyYXAsIGlzSW5saW5lLCBsYXlvdXRCcmVha3BvaW50KTtcblxuICAgIGNvbnN0IGNsYXNzTmFtZSA9IG9mZnNldENsYXNzTmFtZSArICcuJyArIGxheW91dENsYXNzTmFtZTtcblxuICAgIGlmICghdGhpcy5oYXNJbkZsZXhTdG9yYWdlKGNsYXNzTmFtZSwgYnJlYWtwb2ludCkpIHtcbiAgICAgIGNvbnN0IHN0eWxlID0gaXNGbG93SG9yaXpvbnRhbChkaXJlY3Rpb24pID8geydtYXJnaW4tbGVmdCc6IGAke29mZnNldH1gfSA6IHsnbWFyZ2luLXRvcCc6IGAke29mZnNldH1gfTtcblxuICAgICAgdGhpcy5hZGRUb0ZsZXhTdG9yYWdlKGNsYXNzTmFtZSwgc3R5bGUsIGJyZWFrcG9pbnQsIFtsYXlvdXRCcmVha3BvaW50XSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG9mZnNldENsYXNzTmFtZTtcbiAgfVxuXG4gIGFkZEZsZXhBbGlnbihhbGlnbiwgYnJlYWtwb2ludDogc3RyaW5nKSB7XG4gICAgYWxpZ24gPSBhbGlnbiB8fCAnc3RyZXRjaCc7XG5cbiAgICAvLyBDcm9zcy1heGlzXG4gICAgc3dpdGNoIChhbGlnbikge1xuICAgICAgY2FzZSAnc3RhcnQnOlxuICAgICAgICBhbGlnbiA9ICdmbGV4LXN0YXJ0JztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdlbmQnOlxuICAgICAgICBhbGlnbiA9ICdmbGV4LWVuZCc7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGNvbnN0IGNsYXNzTmFtZSA9IGdlbmVyYXRlRmxleEFsaWduQ2xhc3NOYW1lKGFsaWduLCBicmVha3BvaW50KTtcblxuICAgIGlmICghdGhpcy5oYXNJbkZsZXhTdG9yYWdlKGNsYXNzTmFtZSwgYnJlYWtwb2ludCkpIHtcbiAgICAgIGNvbnN0IHN0eWxlID0geydhbGlnbi1zZWxmJzogYWxpZ259O1xuXG4gICAgICB0aGlzLmFkZFRvRmxleFN0b3JhZ2UoY2xhc3NOYW1lLCBzdHlsZSwgYnJlYWtwb2ludCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNsYXNzTmFtZTtcbiAgfVxuXG4gIGFkZEZsZXhGaWxsKCkge1xuICAgIGNvbnN0IGNsYXNzTmFtZSA9IGdlbmVyYXRlRmxleEZpbGxDbGFzc05hbWUoKTtcblxuICAgIGlmICghdGhpcy5oYXNJbkZpbGxTdG9yYWdlKGNsYXNzTmFtZSwgJ2FsbCcpKSB7XG4gICAgICBjb25zdCBzdHlsZSA9IHtcbiAgICAgICAgJ21hcmdpbic6IDAsXG4gICAgICAgICd3aWR0aCc6ICcxMDAlJyxcbiAgICAgICAgJ2hlaWdodCc6ICcxMDAlJyxcbiAgICAgICAgJ21pbi13aWR0aCc6ICcxMDAlJyxcbiAgICAgICAgJ21pbi1oZWlnaHQnOiAnMTAwJScsXG4gICAgICB9O1xuXG4gICAgICB0aGlzLmFkZFRvRmlsbFN0b3JhZ2UoY2xhc3NOYW1lLCBzdHlsZSwgJ2FsbCcpO1xuICAgIH1cblxuICAgIHJldHVybiBjbGFzc05hbWU7XG4gIH1cblxuICBhZGRTaG93SGlkZShkaXNwbGF5OiBzdHJpbmcsIHNob3c6IGJvb2xlYW4sIGJyZWFrcG9pbnQ6IHN0cmluZykge1xuICAgIGNvbnN0IGNsYXNzTmFtZSA9IGdlbmVyYXRlRmxleFNob3dIaWRlQ2xhc3NOYW1lKGRpc3BsYXksIHNob3csIGJyZWFrcG9pbnQpO1xuXG4gICAgaWYgKCF0aGlzLmhhc0luRmlsbFN0b3JhZ2UoY2xhc3NOYW1lLCBicmVha3BvaW50KSkge1xuICAgICAgY29uc3Qgc3R5bGUgPSB7XG4gICAgICAgICdkaXNwbGF5Jzogc2hvdyA/IGRpc3BsYXkgfHwgJ2Jsb2NrJyA6ICdub25lJyxcbiAgICAgIH07XG5cbiAgICAgIHRoaXMuYWRkVG9GaWxsU3RvcmFnZShjbGFzc05hbWUsIHN0eWxlLCBicmVha3BvaW50KTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2xhc3NOYW1lO1xuICB9XG5cbiAgcHJpdmF0ZSBoYXNJbkxheW91dFN0b3JhZ2UoY2xhc3NOYW1lOiBzdHJpbmcsIGJyZWFrcG9pbnQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmhhc0luU3RvcmFnZSh0aGlzLmxheW91dCwgY2xhc3NOYW1lLCBicmVha3BvaW50KTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkVG9MYXlvdXRTdG9yYWdlKGNsYXNzTmFtZTogc3RyaW5nLCBzdHlsZTogU3R5bGVEZWZpbml0aW9uLCBicmVha3BvaW50OiBzdHJpbmcsIGN1c3RvbUJyZWFrcG9pbnRzPzogc3RyaW5nW10pIHtcbiAgICByZXR1cm4gdGhpcy5hZGRUb1N0b3JhZ2UodGhpcy5sYXlvdXQsIGNsYXNzTmFtZSwgc3R5bGUsIGJyZWFrcG9pbnQsIGN1c3RvbUJyZWFrcG9pbnRzKTtcbiAgfVxuXG4gIHByaXZhdGUgaGFzSW5GbGV4U3RvcmFnZShjbGFzc05hbWU6IHN0cmluZywgYnJlYWtwb2ludDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaGFzSW5TdG9yYWdlKHRoaXMuZmxleCwgY2xhc3NOYW1lLCBicmVha3BvaW50KTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkVG9GbGV4U3RvcmFnZShjbGFzc05hbWU6IHN0cmluZywgc3R5bGU6IFN0eWxlRGVmaW5pdGlvbiwgYnJlYWtwb2ludDogc3RyaW5nLCBjdXN0b21CcmVha3BvaW50cz86IHN0cmluZ1tdKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkVG9TdG9yYWdlKHRoaXMuZmxleCwgY2xhc3NOYW1lLCBzdHlsZSwgYnJlYWtwb2ludCwgY3VzdG9tQnJlYWtwb2ludHMpO1xuICB9XG5cbiAgcHJpdmF0ZSBoYXNJbkZpbGxTdG9yYWdlKGNsYXNzTmFtZTogc3RyaW5nLCBicmVha3BvaW50OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5oYXNJblN0b3JhZ2UodGhpcy5maWxsLCBjbGFzc05hbWUsIGJyZWFrcG9pbnQpO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRUb0ZpbGxTdG9yYWdlKGNsYXNzTmFtZTogc3RyaW5nLCBzdHlsZTogU3R5bGVEZWZpbml0aW9uLCBicmVha3BvaW50OiBzdHJpbmcsIGN1c3RvbUJyZWFrcG9pbnRzPzogc3RyaW5nW10pIHtcbiAgICByZXR1cm4gdGhpcy5hZGRUb1N0b3JhZ2UodGhpcy5maWxsLCBjbGFzc05hbWUsIHN0eWxlLCBicmVha3BvaW50LCBjdXN0b21CcmVha3BvaW50cyk7XG4gIH1cblxuICBwcml2YXRlIGhhc0luU3RvcmFnZShzdHlsZUVsZW1lbnQ6IEZsZXhDc3NTdHlsZUVsZW1lbnQsIGNsYXNzTmFtZTogc3RyaW5nLCBicmVha3BvaW50OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISEoc3R5bGVFbGVtZW50LnN0b3JhZ2VbYnJlYWtwb2ludF0gJiYgc3R5bGVFbGVtZW50LnN0b3JhZ2VbYnJlYWtwb2ludF1bY2xhc3NOYW1lXSk7XG4gIH1cblxuICBwcml2YXRlIGFkZFRvU3RvcmFnZShcbiAgICBzdHlsZUVsZW1lbnQ6IEZsZXhDc3NTdHlsZUVsZW1lbnQsIGNsYXNzTmFtZTogc3RyaW5nLCBzdHlsZTogU3R5bGVEZWZpbml0aW9uLCBicmVha3BvaW50OiBzdHJpbmcsIGN1c3RvbUJyZWFrcG9pbnRzPzogc3RyaW5nW10pIHtcbiAgICBjdXN0b21CcmVha3BvaW50cyA9IGN1c3RvbUJyZWFrcG9pbnRzIHx8IFtdO1xuXG4gICAgY29uc3Qgc3R5bGVzID0gYXBwbHlDc3NQcmVmaXhlcyhzdHlsZSk7XG5cbiAgICBjb25zdCBjc3MgPSB0aGlzLmdlbmVyYXRlQ3NzKHN0eWxlcyk7XG5cbiAgICBpZiAoY3NzICE9PSAnJykge1xuICAgICAgY29uc3QgY2xhc3NDc3MgPSAnLicgKyBjbGFzc05hbWUgKyAnIHsgJyArIGNzcyArICcgfSc7XG5cbiAgICAgIGNvbnN0IGNzc0VsZW1lbnQgPSB0aGlzLmRvYy5jcmVhdGVUZXh0Tm9kZSh0aGlzLmFkZEJyZWFrcG9pbnRzKFticmVha3BvaW50XS5jb25jYXQoY3VzdG9tQnJlYWtwb2ludHMpLCBjbGFzc0NzcykpO1xuXG4gICAgICBpZiAoIXN0eWxlRWxlbWVudC5zdG9yYWdlW2JyZWFrcG9pbnRdKSB7XG4gICAgICAgIHN0eWxlRWxlbWVudC5zdG9yYWdlW2JyZWFrcG9pbnRdID0ge307XG4gICAgICB9XG5cbiAgICAgIHN0eWxlRWxlbWVudC5zdG9yYWdlW2JyZWFrcG9pbnRdW2NsYXNzTmFtZV0gPSBjc3NFbGVtZW50O1xuXG4gICAgICB0aGlzLnJlb3JkZXJUZXh0RWxlbWVudHMoc3R5bGVFbGVtZW50KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlb3JkZXJUZXh0RWxlbWVudHMoc3R5bGVFbGVtZW50OiBGbGV4Q3NzU3R5bGVFbGVtZW50KSB7XG4gICAgbGV0IHBvc2l0aW9uID0gdGhpcy5yZW9yZGVyQnJlYWtwb2ludEVsZW1lbnRzKHN0eWxlRWxlbWVudCwgJ2FsbCcpO1xuXG4gICAgdGhpcy5icmVha3BvaW50cy5mb3JFYWNoKGJyZWFrcG9pbnQgPT4ge1xuICAgICAgcG9zaXRpb24gPSB0aGlzLnJlb3JkZXJCcmVha3BvaW50RWxlbWVudHMoc3R5bGVFbGVtZW50LCBicmVha3BvaW50LmFsaWFzLCBwb3NpdGlvbik7XG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgcmVvcmRlckJyZWFrcG9pbnRFbGVtZW50cyhzdHlsZUVsZW1lbnQ6IEZsZXhDc3NTdHlsZUVsZW1lbnQsIGJyZWFrcG9pbnQ6IHN0cmluZywgcG9zaXRpb246IG51bWJlciA9IDApIHtcbiAgICBjb25zdCBicmVha3BvaW50RWxlbWVudHMgPSBzdHlsZUVsZW1lbnQuc3RvcmFnZVticmVha3BvaW50XTtcblxuICAgIGlmICghYnJlYWtwb2ludEVsZW1lbnRzKSB7XG4gICAgICByZXR1cm4gcG9zaXRpb247XG4gICAgfVxuXG4gICAgT2JqZWN0LmtleXMoYnJlYWtwb2ludEVsZW1lbnRzKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICBpZiAoc3R5bGVFbGVtZW50LnN0eWxlLmNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICBzdHlsZUVsZW1lbnQuc3R5bGUuaW5zZXJ0QmVmb3JlKGJyZWFrcG9pbnRFbGVtZW50c1trZXldLCBzdHlsZUVsZW1lbnQuc3R5bGUuY2hpbGRyZW5bcG9zaXRpb25dKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0eWxlRWxlbWVudC5zdHlsZS5hcHBlbmRDaGlsZChicmVha3BvaW50RWxlbWVudHNba2V5XSk7XG4gICAgICB9XG5cbiAgICAgICsrcG9zaXRpb247XG4gICAgfSk7XG5cbiAgICByZXR1cm4gcG9zaXRpb247XG4gIH1cblxuICBwcml2YXRlIGdlbmVyYXRlQ3NzKHN0eWxlczogT2JqZWN0KSB7XG4gICAgY29uc3QgY3NzID0gW107XG5cbiAgICBPYmplY3Qua2V5cyhzdHlsZXMpLnNvcnQoKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICBjb25zdCB2YWx1ZXMgPSBBcnJheS5pc0FycmF5KHN0eWxlc1trZXldKSA/IHN0eWxlc1trZXldIDogW3N0eWxlc1trZXldXTtcblxuICAgICAgdmFsdWVzLnNvcnQoKTtcblxuICAgICAgdmFsdWVzLmZvckVhY2godmFsdWUgPT4ge1xuICAgICAgICBpZiAodmFsdWUgIT09IG51bGwgJiYgdmFsdWUgIT09ICcnKSB7XG4gICAgICAgICAgY3NzLnB1c2goa2V5ICsgJzogJyArIHZhbHVlICsgJzsnKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gY3NzLmpvaW4oJyAnKTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkQnJlYWtwb2ludHMoYnJlYWtwb2ludHNBbGlhc2VzOiBzdHJpbmdbXSwgY3NzOiBzdHJpbmcpIHtcbiAgICBicmVha3BvaW50c0FsaWFzZXMgPSBicmVha3BvaW50c0FsaWFzZXMuZmlsdGVyKGJyZWFrcG9pbnQgPT4gYnJlYWtwb2ludCAhPT0gJ2FsbCcpO1xuXG4gICAgaWYgKCFicmVha3BvaW50c0FsaWFzZXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gY3NzO1xuICAgIH1cblxuICAgIGxldCB0aGVCcmVha3BvaW50cyA9IFtdO1xuXG4gICAgdGhpcy5icmVha3BvaW50c1xuICAgICAgLmZpbHRlcihicmVha3BvaW50ID0+IGJyZWFrcG9pbnRzQWxpYXNlcy5pbmRleE9mKGJyZWFrcG9pbnQuYWxpYXMpID49IDApXG4gICAgICAuZm9yRWFjaChicmVha3BvaW50ID0+IHRoZUJyZWFrcG9pbnRzID0gdGhlQnJlYWtwb2ludHMuY29uY2F0KGJyZWFrcG9pbnQubWVkaWEpKTtcblxuICAgIHRoZUJyZWFrcG9pbnRzID0gdGhlQnJlYWtwb2ludHMuZmlsdGVyKCh2YWx1ZSwgaW5kZXgsIHNlbGYpID0+IHNlbGYuaW5kZXhPZih2YWx1ZSkgPT09IGluZGV4KTtcblxuICAgIHJldHVybiAnQG1lZGlhICcgKyB0aGVCcmVha3BvaW50cy5qb2luKCcgYW5kICcpICsgJyB7ICcgKyBjc3MgKyAnIH0nO1xuICB9XG59XG4iXX0=