UNPKG

@cisstech/nge

Version:

NG Essentials is a collection of libraries for Angular developers.

326 lines 51 kB
import { Injectable } from '@angular/core';
import * as i0 from "@angular/core";
import * as i1 from "./monaco-loader.service";
import * as i2 from "./monaco-theme.service";
export class NgeMonacoColorizerService {
    constructor(loader, theming) {
        this.loader = loader;
        this.theming = theming;
    }
    async colorizeElement(options) {
        await this.loader.loadAsync();
        if (options.theme) {
            await this.theming.defineTheme(options.theme);
        }
        const { element } = options;
        element.innerHTML = this.escapeHtml(options.code || '');
        element.style.padding = '4px';
        element.style.display = 'block';
        const pre = element.parentElement;
        if (pre?.tagName === 'PRE') {
            if (!pre.classList.contains('monaco-editor')) {
                pre.classList.add('monaco-editor');
            }
            if (!pre.classList.contains('monaco-editor-background')) {
                pre.classList.add('monaco-editor-background');
            }
        }
        element.className = '';
        const languages = monaco.languages.getLanguages();
        const language = languages.find((e) => {
            return e.id === options.language || e.aliases?.find((a) => a === options.language);
        })?.id;
        await monaco.editor.colorizeElement(element, {
            mimeType: language || 'plaintext',
            theme: options.theme || this.theming.theme?.themeName || 'vs',
        });
        this.highlightLines(options);
        this.showLineNumbers(options);
        this.addFileTab(options);
    }
    escapeHtml(input) {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const map = {
            '<': '&lt;',
            '>': '&gt;',
        };
        return input.replace(/[<>]/g, (tag) => map[tag] || tag);
    }
    highlightLines(options) {
        if (!options.highlights) {
            return;
        }
        const { element } = options;
        const linesToHighlight = this.lineNumbersFromString(options.highlights.toString());
        let newLine = true;
        let lineNumber = 1;
        element.childNodes.forEach((e) => {
            const node = e;
            if (newLine) {
                const div = document.createElement('div');
                div.style.height = '18px';
                if (linesToHighlight.includes(lineNumber)) {
                    div.classList.add('rangeHighlight');
                    div.classList.add('selected-text');
                }
                element.insertBefore(div, node);
                element.removeChild(node);
                div.appendChild(node);
                newLine = false;
            }
            else if (node.tagName === 'BR') {
                lineNumber++;
                newLine = true;
            }
        });
        Array.from(element.getElementsByTagName('br')).forEach((node) => node.remove());
    }
    showLineNumbers(options) {
        if (!options.lines) {
            return;
        }
        const { element } = options;
        const lines = this.lineNumbersFromString(options.lines.toString());
        const length = (options.code || '').split('\n').length;
        if (lines.length === 1) {
            for (let i = lines[0] + 1; i <= length; i++) {
                lines.push(i);
            }
        }
        const side = ['<div style="padding:0  12px; text-align: right;">'];
        for (let i = 0; i < length; i++) {
            let num = '';
            if (lines.includes(i + 1)) {
                num = '' + (i + 1);
            }
            side.push(`<div class="line-numbers" style="height: 18px">${num}</div>`);
        }
        side.push('</div>');
        element.style.display = 'flex';
        element.innerHTML = `
            ${side.join('')}
            <div style="flex: 1;">${element.innerHTML}</div>
        `;
    }
    lineNumbersFromString(input) {
        const tokens = (input || '').trim().split(' ');
        const lines = [];
        for (const token of tokens) {
            if (token.includes('-')) {
                const range = token.split('-');
                const start = Number.parseInt(range[0], 10);
                const end = Number.parseInt(range[1], 10);
                if (start && end) {
                    for (let i = start; i <= end; i++) {
                        if (!lines.includes(i)) {
                            lines.push(i);
                        }
                    }
                }
            }
            else {
                const n = Number.parseInt(token, 10);
                if (n) {
                    lines.push(n);
                }
            }
        }
        return lines;
    }
    addFileTab(options) {
        const { element, code, filename } = options;
        const container = element.parentElement;
        // Force remove padding from pre element
        if (container) {
            container.style.padding = '0';
            container.style.margin = '0';
            container.style.width = '100%';
        }
        // Create tab container that takes full width
        const tabContainer = document.createElement('div');
        tabContainer.style.display = 'flex';
        tabContainer.style.justifyContent = 'space-between';
        tabContainer.style.alignItems = 'center';
        tabContainer.style.padding = '8px 16px';
        tabContainer.style.borderBottom = '1px solid var(--vscode-dropdown-border, #e8e8e8)';
        tabContainer.style.backgroundColor = 'var(--vscode-editor-background, #fafafa)';
        tabContainer.style.fontSize = '14px';
        tabContainer.style.width = '100%';
        tabContainer.style.boxSizing = 'border-box';
        tabContainer.style.fontFamily = 'var(--monaco-monospace-font, "SF Mono", Monaco, Menlo, Consolas, "Ubuntu Mono", monospace)';
        // Add filename on left side
        const filenameSpan = document.createElement('span');
        filenameSpan.textContent = filename || '';
        filenameSpan.style.overflow = 'hidden';
        filenameSpan.style.textOverflow = 'ellipsis';
        filenameSpan.style.whiteSpace = 'nowrap';
        filenameSpan.style.fontWeight = '500';
        filenameSpan.style.color = 'var(--vscode-editor-foreground, rgba(0, 0, 0, 0.85))';
        filenameSpan.title = filename || '';
        // Add file actions container (right side)
        const fileActions = document.createElement('div');
        fileActions.className = 'file-actions';
        fileActions.style.display = 'flex';
        fileActions.style.gap = '4px';
        // Create copy button with icon
        const copyButton = document.createElement('button');
        copyButton.style.border = 'none';
        copyButton.style.background = 'none';
        copyButton.style.cursor = 'pointer';
        copyButton.style.color = 'var(--vscode-editor-foreground, rgba(0, 0, 0, 0.85))';
        copyButton.style.display = 'flex';
        copyButton.style.alignItems = 'center';
        copyButton.style.justifyContent = 'center';
        copyButton.style.width = '32px';
        copyButton.style.height = '32px';
        copyButton.style.padding = '0';
        copyButton.style.borderRadius = '4px';
        copyButton.style.transition = 'all 0.3s';
        copyButton.title = 'Copy code to clipboard';
        // Hover effect
        copyButton.addEventListener('mouseover', () => {
            copyButton.style.color = '#1890ff';
            copyButton.style.backgroundColor = 'rgba(0, 0, 0, 0.04)';
        });
        copyButton.addEventListener('mouseout', () => {
            copyButton.style.color = 'var(--vscode-editor-foreground, rgba(0, 0, 0, 0.85))';
            copyButton.style.backgroundColor = 'transparent';
        });
        // Copy functionality
        copyButton.addEventListener('click', async (event) => {
            // Prevent default action and event bubbling
            event.preventDefault();
            event.stopPropagation();
            try {
                await navigator.clipboard.writeText(code || '');
                // Show feedback
                copyButton.innerHTML = `<svg viewBox="0 0 24 24" width="16" height="16" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></svg>`;
                copyButton.style.color = '#52c41a';
                setTimeout(() => {
                    // Use requestAnimationFrame to ensure smooth transition
                    requestAnimationFrame(() => {
                        copyButton.innerHTML = copySvg;
                        copyButton.style.color = 'var(--vscode-editor-foreground, rgba(0, 0, 0, 0.85))';
                    });
                }, 2000);
            }
            catch (err) {
                console.error('Failed to copy code:', err);
            }
            // Return false to ensure no further action
            return false;
        });
        // Create download button with icon
        const downloadButton = document.createElement('button');
        downloadButton.style.border = 'none';
        downloadButton.style.background = 'none';
        downloadButton.style.cursor = 'pointer';
        downloadButton.style.color = 'var(--vscode-editor-foreground, rgba(0, 0, 0, 0.85))';
        downloadButton.style.display = 'flex';
        downloadButton.style.alignItems = 'center';
        downloadButton.style.justifyContent = 'center';
        downloadButton.style.width = '32px';
        downloadButton.style.height = '32px';
        downloadButton.style.padding = '0';
        downloadButton.style.borderRadius = '4px';
        downloadButton.style.transition = 'all 0.3s';
        downloadButton.title = 'Download code as file';
        // Hover effect
        downloadButton.addEventListener('mouseover', () => {
            downloadButton.style.color = '#1890ff';
            downloadButton.style.backgroundColor = 'rgba(0, 0, 0, 0.04)';
        });
        downloadButton.addEventListener('mouseout', () => {
            downloadButton.style.color = 'var(--vscode-editor-foreground, rgba(0, 0, 0, 0.85))';
            downloadButton.style.backgroundColor = 'transparent';
        });
        // Download functionality
        downloadButton.addEventListener('click', (event) => {
            // Prevent default action and event bubbling
            event.preventDefault();
            event.stopPropagation();
            // Save original content
            const originalInnerHTML = downloadButton.innerHTML;
            try {
                const blob = new Blob([code || ''], { type: 'text/plain' });
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = filename || 'code.txt';
                a.style.display = 'none';
                a.setAttribute('data-no-scroll', 'true'); // Mark as no-scroll
                // Execute download
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                // Show success feedback similar to copy button
                downloadButton.innerHTML = `<svg viewBox="0 0 24 24" width="16" height="16" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></svg>`;
                downloadButton.style.color = '#52c41a';
                // Reset button after timeout
                setTimeout(() => {
                    // Use requestAnimationFrame for smoother transition
                    requestAnimationFrame(() => {
                        downloadButton.innerHTML = downloadSvg;
                        downloadButton.style.color = 'var(--vscode-editor-foreground, rgba(0, 0, 0, 0.85))';
                        URL.revokeObjectURL(url); // Clean up URL object
                    });
                }, 2000);
            }
            catch (err) {
                console.error('Failed to download code:', err);
                downloadButton.innerHTML = originalInnerHTML;
            }
            // Return false to ensure no further action
            return false;
        });
        // Copy icon SVG
        const copySvg = `<svg viewBox="0 0 24 24" width="16" height="16" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>`;
        // Download icon SVG
        const downloadSvg = `<svg viewBox="0 0 24 24" width="16" height="16" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>`;
        copyButton.innerHTML = copySvg;
        downloadButton.innerHTML = downloadSvg;
        // Add buttons to actions container
        fileActions.appendChild(copyButton);
        fileActions.appendChild(downloadButton);
        // Build the tab
        tabContainer.appendChild(filenameSpan);
        tabContainer.appendChild(fileActions);
        // Insert tab before the editor content
        if (container) {
            container.insertBefore(tabContainer, element);
            // Add some styling to the container for better appearance
            container.style.border = '1px solid #e8e8e8';
            container.style.borderRadius = '2px';
            container.style.overflow = 'hidden';
            container.style.marginBottom = '16px';
            container.style.padding = '0';
            // Add inner padding to code content
            element.style.padding = '16px';
        }
        else {
            // If no container, wrap the element with one
            const wrapper = document.createElement('div');
            wrapper.style.border = '1px solid #e8e8e8';
            wrapper.style.borderRadius = '2px';
            wrapper.style.overflow = 'hidden';
            wrapper.style.marginBottom = '16px';
            wrapper.style.padding = '0';
            wrapper.style.width = '100%';
            const parent = element.parentElement;
            if (parent) {
                parent.insertBefore(wrapper, element);
                wrapper.appendChild(tabContainer);
                wrapper.appendChild(element);
                // Add inner padding to code content
                element.style.padding = '16px';
            }
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: NgeMonacoColorizerService, deps: [{ token: i1.NgeMonacoLoaderService }, { token: i2.NgeMonacoThemeService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: NgeMonacoColorizerService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: NgeMonacoColorizerService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: i1.NgeMonacoLoaderService }, { type: i2.NgeMonacoThemeService }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9uYWNvLWNvbG9yaXplci5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmdlL21vbmFjby9zcmMvc2VydmljZXMvbW9uYWNvLWNvbG9yaXplci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUE7Ozs7QUFLMUMsTUFBTSxPQUFPLHlCQUF5QjtJQUNwQyxZQUNtQixNQUE4QixFQUM5QixPQUE4QjtRQUQ5QixXQUFNLEdBQU4sTUFBTSxDQUF3QjtRQUM5QixZQUFPLEdBQVAsT0FBTyxDQUF1QjtJQUM5QyxDQUFDO0lBRUosS0FBSyxDQUFDLGVBQWUsQ0FBQyxPQUFpQztRQUNyRCxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUE7UUFDN0IsSUFBSSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbEIsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDL0MsQ0FBQztRQUVELE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxPQUFPLENBQUE7UUFFM0IsT0FBTyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUE7UUFDdkQsT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFBO1FBQzdCLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQTtRQUUvQixNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsYUFBYSxDQUFBO1FBQ2pDLElBQUksR0FBRyxFQUFFLE9BQU8sS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUMzQixJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQztn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LENBQUMsQ0FBQTtnQkFDckMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUMsQ0FBQTtnQkFDakMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQTtnQkFFNUIsb0NBQW9DO2dCQUNwQyxPQUFPLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUE7WUFDaEMsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDOzhHQTNXVSx5QkFBeUI7a0hBQXpCLHlCQUF5QixjQURaLE1BQU07OzJGQUNuQix5QkFBeUI7a0JBRHJDLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnXG5pbXBvcnQgeyBOZ2VNb25hY29Mb2FkZXJTZXJ2aWNlIH0gZnJvbSAnLi9tb25hY28tbG9hZGVyLnNlcnZpY2UnXG5pbXBvcnQgeyBOZ2VNb25hY29UaGVtZVNlcnZpY2UgfSBmcm9tICcuL21vbmFjby10aGVtZS5zZXJ2aWNlJ1xuXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIE5nZU1vbmFjb0NvbG9yaXplclNlcnZpY2Uge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGxvYWRlcjogTmdlTW9uYWNvTG9hZGVyU2VydmljZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHRoZW1pbmc6IE5nZU1vbmFjb1RoZW1lU2VydmljZVxuICApIHt9XG5cbiAgYXN5bmMgY29sb3JpemVFbGVtZW50KG9wdGlvbnM6IE5nZU1vbmFjb0NvbG9yaXplT3B0aW9ucykge1xuICAgIGF3YWl0IHRoaXMubG9hZGVyLmxvYWRBc3luYygpXG4gICAgaWYgKG9wdGlvbnMudGhlbWUpIHtcbiAgICAgIGF3YWl0IHRoaXMudGhlbWluZy5kZWZpbmVUaGVtZShvcHRpb25zLnRoZW1lKVxuICAgIH1cblxuICAgIGNvbnN0IHsgZWxlbWVudCB9ID0gb3B0aW9uc1xuXG4gICAgZWxlbWVudC5pbm5lckhUTUwgPSB0aGlzLmVzY2FwZUh0bWwob3B0aW9ucy5jb2RlIHx8ICcnKVxuICAgIGVsZW1lbnQuc3R5bGUucGFkZGluZyA9ICc0cHgnXG4gICAgZWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJ1xuXG4gICAgY29uc3QgcHJlID0gZWxlbWVudC5wYXJlbnRFbGVtZW50XG4gICAgaWYgKHByZT8udGFnTmFtZSA9PT0gJ1BSRScpIHtcbiAgICAgIGlmICghcHJlLmNsYXNzTGlzdC5jb250YWlucygnbW9uYWNvLWVkaXRvcicpKSB7XG4gICAgICAgIHByZS5jbGFzc0xpc3QuYWRkKCdtb25hY28tZWRpdG9yJylcbiAgICAgIH1cbiAgICAgIGlmICghcHJlLmNsYXNzTGlzdC5jb250YWlucygnbW9uYWNvLWVkaXRvci1iYWNrZ3JvdW5kJykpIHtcbiAgICAgICAgcHJlLmNsYXNzTGlzdC5hZGQoJ21vbmFjby1lZGl0b3ItYmFja2dyb3VuZCcpXG4gICAgICB9XG4gICAgfVxuXG4gICAgZWxlbWVudC5jbGFzc05hbWUgPSAnJ1xuXG4gICAgY29uc3QgbGFuZ3VhZ2VzID0gbW9uYWNvLmxhbmd1YWdlcy5nZXRMYW5ndWFnZXMoKVxuICAgIGNvbnN0IGxhbmd1YWdlID0gbGFuZ3VhZ2VzLmZpbmQoKGUpID0+IHtcbiAgICAgIHJldHVybiBlLmlkID09PSBvcHRpb25zLmxhbmd1YWdlIHx8IGUuYWxpYXNlcz8uZmluZCgoYSkgPT4gYSA9PT0gb3B0aW9ucy5sYW5ndWFnZSlcbiAgICB9KT8uaWRcblxuICAgIGF3YWl0IG1vbmFjby5lZGl0b3IuY29sb3JpemVFbGVtZW50KGVsZW1lbnQsIHtcbiAgICAgIG1pbWVUeXBlOiBsYW5ndWFnZSB8fCAncGxhaW50ZXh0JyxcbiAgICAgIHRoZW1lOiBvcHRpb25zLnRoZW1lIHx8IHRoaXMudGhlbWluZy50aGVtZT8udGhlbWVOYW1lIHx8ICd2cycsXG4gICAgfSlcblxuICAgIHRoaXMuaGlnaGxpZ2h0TGluZXMob3B0aW9ucylcbiAgICB0aGlzLnNob3dMaW5lTnVtYmVycyhvcHRpb25zKVxuXG4gICAgdGhpcy5hZGRGaWxlVGFiKG9wdGlvbnMpXG4gIH1cblxuICBwcml2YXRlIGVzY2FwZUh0bWwoaW5wdXQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICBjb25zdCBtYXA6IGFueSA9IHtcbiAgICAgICc8JzogJyZsdDsnLFxuICAgICAgJz4nOiAnJmd0OycsXG4gICAgfVxuICAgIHJldHVybiBpbnB1dC5yZXBsYWNlKC9bPD5dL2csICh0YWcpID0+IG1hcFt0YWddIHx8IHRhZylcbiAgfVxuXG4gIHByaXZhdGUgaGlnaGxpZ2h0TGluZXMob3B0aW9uczogTmdlTW9uYWNvQ29sb3JpemVPcHRpb25zKTogdm9pZCB7XG4gICAgaWYgKCFvcHRpb25zLmhpZ2hsaWdodHMpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNvbnN0IHsgZWxlbWVudCB9ID0gb3B0aW9uc1xuXG4gICAgY29uc3QgbGluZXNUb0hpZ2hsaWdodCA9IHRoaXMubGluZU51bWJlcnNGcm9tU3RyaW5nKG9wdGlvbnMuaGlnaGxpZ2h0cy50b1N0cmluZygpKVxuXG4gICAgbGV0IG5ld0xpbmUgPSB0cnVlXG4gICAgbGV0IGxpbmVOdW1iZXIgPSAxXG4gICAgZWxlbWVudC5jaGlsZE5vZGVzLmZvckVhY2goKGUpID0+IHtcbiAgICAgIGNvbnN0IG5vZGUgPSBlIGFzIEhUTUxFbGVtZW50XG4gICAgICBpZiAobmV3TGluZSkge1xuICAgICAgICBjb25zdCBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgICAgICBkaXYuc3R5bGUuaGVpZ2h0ID0gJzE4cHgnXG4gICAgICAgIGlmIChsaW5lc1RvSGlnaGxpZ2h0LmluY2x1ZGVzKGxpbmVOdW1iZXIpKSB7XG4gICAgICAgICAgZGl2LmNsYXNzTGlzdC5hZGQoJ3JhbmdlSGlnaGxpZ2h0JylcbiAgICAgICAgICBkaXYuY2xhc3NMaXN0LmFkZCgnc2VsZWN0ZWQtdGV4dCcpXG4gICAgICAgIH1cbiAgICAgICAgZWxlbWVudC5pbnNlcnRCZWZvcmUoZGl2LCBub2RlKVxuICAgICAgICBlbGVtZW50LnJlbW92ZUNoaWxkKG5vZGUpXG4gICAgICAgIGRpdi5hcHBlbmRDaGlsZChub2RlKVxuICAgICAgICBuZXdMaW5lID0gZmFsc2VcbiAgICAgIH0gZWxzZSBpZiAobm9kZS50YWdOYW1lID09PSAnQlInKSB7XG4gICAgICAgIGxpbmVOdW1iZXIrK1xuICAgICAgICBuZXdMaW5lID0gdHJ1ZVxuICAgICAgfVxuICAgIH0pXG4gICAgQXJyYXkuZnJvbShlbGVtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdicicpKS5mb3JFYWNoKChub2RlKSA9PiBub2RlLnJlbW92ZSgpKVxuICB9XG5cbiAgcHJpdmF0ZSBzaG93TGluZU51bWJlcnMob3B0aW9uczogTmdlTW9uYWNvQ29sb3JpemVPcHRpb25zKTogdm9pZCB7XG4gICAgaWYgKCFvcHRpb25zLmxpbmVzKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBjb25zdCB7IGVsZW1lbnQgfSA9IG9wdGlvbnNcbiAgICBjb25zdCBsaW5lcyA9IHRoaXMubGluZU51bWJlcnNGcm9tU3RyaW5nKG9wdGlvbnMubGluZXMudG9TdHJpbmcoKSlcbiAgICBjb25zdCBsZW5ndGggPSAob3B0aW9ucy5jb2RlIHx8ICcnKS5zcGxpdCgnXFxuJykubGVuZ3RoXG4gICAgaWYgKGxpbmVzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgZm9yIChsZXQgaSA9IGxpbmVzWzBdICsgMTsgaSA8PSBsZW5ndGg7IGkrKykge1xuICAgICAgICBsaW5lcy5wdXNoKGkpXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgc2lkZSA9IFsnPGRpdiBzdHlsZT1cInBhZGRpbmc6MCAgMTJweDsgdGV4dC1hbGlnbjogcmlnaHQ7XCI+J11cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBsZXQgbnVtID0gJydcbiAgICAgIGlmIChsaW5lcy5pbmNsdWRlcyhpICsgMSkpIHtcbiAgICAgICAgbnVtID0gJycgKyAoaSArIDEpXG4gICAgICB9XG4gICAgICBzaWRlLnB1c2goYDxkaXYgY2xhc3M9XCJsaW5lLW51bWJlcnNcIiBzdHlsZT1cImhlaWdodDogMThweFwiPiR7bnVtfTwvZGl2PmApXG4gICAgfVxuICAgIHNpZGUucHVzaCgnPC9kaXY+JylcblxuICAgIGVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdmbGV4J1xuICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gYFxuICAgICAgICAgICAgJHtzaWRlLmpvaW4oJycpfVxuICAgICAgICAgICAgPGRpdiBzdHlsZT1cImZsZXg6IDE7XCI+JHtlbGVtZW50LmlubmVySFRNTH08L2Rpdj5cbiAgICAgICAgYFxuICB9XG5cbiAgcHJpdmF0ZSBsaW5lTnVtYmVyc0Zyb21TdHJpbmcoaW5wdXQ6IHN0cmluZyk6IG51bWJlcltdIHtcbiAgICBjb25zdCB0b2tlbnMgPSAoaW5wdXQgfHwgJycpLnRyaW0oKS5zcGxpdCgnICcpXG4gICAgY29uc3QgbGluZXM6IG51bWJlcltdID0gW11cbiAgICBmb3IgKGNvbnN0IHRva2VuIG9mIHRva2Vucykge1xuICAgICAgaWYgKHRva2VuLmluY2x1ZGVzKCctJykpIHtcbiAgICAgICAgY29uc3QgcmFuZ2UgPSB0b2tlbi5zcGxpdCgnLScpXG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gTnVtYmVyLnBhcnNlSW50KHJhbmdlWzBdLCAxMClcbiAgICAgICAgY29uc3QgZW5kID0gTnVtYmVyLnBhcnNlSW50KHJhbmdlWzFdLCAxMClcbiAgICAgICAgaWYgKHN0YXJ0ICYmIGVuZCkge1xuICAgICAgICAgIGZvciAobGV0IGkgPSBzdGFydDsgaSA8PSBlbmQ7IGkrKykge1xuICAgICAgICAgICAgaWYgKCFsaW5lcy5pbmNsdWRlcyhpKSkge1xuICAgICAgICAgICAgICBsaW5lcy5wdXNoKGkpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBuID0gTnVtYmVyLnBhcnNlSW50KHRva2VuLCAxMClcbiAgICAgICAgaWYgKG4pIHtcbiAgICAgICAgICBsaW5lcy5wdXNoKG4pXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGxpbmVzXG4gIH1cblxuICBwcml2YXRlIGFkZEZpbGVUYWIob3B0aW9uczogTmdlTW9uYWNvQ29sb3JpemVPcHRpb25zKTogdm9pZCB7XG4gICAgY29uc3QgeyBlbGVtZW50LCBjb2RlLCBmaWxlbmFtZSB9ID0gb3B0aW9uc1xuICAgIGNvbnN0IGNvbnRhaW5lciA9IGVsZW1lbnQucGFyZW50RWxlbWVudCBhcyBIVE1MRWxlbWVudFxuXG4gICAgLy8gRm9yY2UgcmVtb3ZlIHBhZGRpbmcgZnJvbSBwcmUgZWxlbWVudFxuICAgIGlmIChjb250YWluZXIpIHtcbiAgICAgIGNvbnRhaW5lci5zdHlsZS5wYWRkaW5nID0gJzAnXG4gICAgICBjb250YWluZXIuc3R5bGUubWFyZ2luID0gJzAnXG4gICAgICBjb250YWluZXIuc3R5bGUud2lkdGggPSAnMTAwJSdcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgdGFiIGNvbnRhaW5lciB0aGF0IHRha2VzIGZ1bGwgd2lkdGhcbiAgICBjb25zdCB0YWJDb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgIHRhYkNvbnRhaW5lci5zdHlsZS5kaXNwbGF5ID0gJ2ZsZXgnXG4gICAgdGFiQ29udGFpbmVyLnN0eWxlLmp1c3RpZnlDb250ZW50ID0gJ3NwYWNlLWJldHdlZW4nXG4gICAgdGFiQ29udGFpbmVyLnN0eWxlLmFsaWduSXRlbXMgPSAnY2VudGVyJ1xuICAgIHRhYkNvbnRhaW5lci5zdHlsZS5wYWRkaW5nID0gJzhweCAxNnB4J1xuICAgIHRhYkNvbnRhaW5lci5zdHlsZS5ib3JkZXJCb3R0b20gPSAnMXB4IHNvbGlkIHZhcigtLXZzY29kZS1kcm9wZG93bi1ib3JkZXIsICNlOGU4ZTgpJ1xuICAgIHRhYkNvbnRhaW5lci5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSAndmFyKC0tdnNjb2RlLWVkaXRvci1iYWNrZ3JvdW5kLCAjZmFmYWZhKSdcbiAgICB0YWJDb250YWluZXIuc3R5bGUuZm9udFNpemUgPSAnMTRweCdcbiAgICB0YWJDb250YWluZXIuc3R5bGUud2lkdGggPSAnMTAwJSdcbiAgICB0YWJDb250YWluZXIuc3R5bGUuYm94U2l6aW5nID0gJ2JvcmRlci1ib3gnXG4gICAgdGFiQ29udGFpbmVyLnN0eWxlLmZvbnRGYW1pbHkgPSAndmFyKC0tbW9uYWNvLW1vbm9zcGFjZS1mb250LCBcIlNGIE1vbm9cIiwgTW9uYWNvLCBNZW5sbywgQ29uc29sYXMsIFwiVWJ1bnR1IE1vbm9cIiwgbW9ub3NwYWNlKSdcblxuICAgIC8vIEFkZCBmaWxlbmFtZSBvbiBsZWZ0IHNpZGVcbiAgICBjb25zdCBmaWxlbmFtZVNwYW4gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJylcbiAgICBmaWxlbmFtZVNwYW4udGV4dENvbnRlbnQgPSBmaWxlbmFtZSB8fCAnJ1xuICAgIGZpbGVuYW1lU3Bhbi5zdHlsZS5vdmVyZmxvdyA9ICdoaWRkZW4nXG4gICAgZmlsZW5hbWVTcGFuLnN0eWxlLnRleHRPdmVyZmxvdyA9ICdlbGxpcHNpcydcbiAgICBmaWxlbmFtZVNwYW4uc3R5bGUud2hpdGVTcGFjZSA9ICdub3dyYXAnXG4gICAgZmlsZW5hbWVTcGFuLnN0eWxlLmZvbnRXZWlnaHQgPSAnNTAwJ1xuICAgIGZpbGVuYW1lU3Bhbi5zdHlsZS5jb2xvciA9ICd2YXIoLS12c2NvZGUtZWRpdG9yLWZvcmVncm91bmQsIHJnYmEoMCwgMCwgMCwgMC44NSkpJ1xuICAgIGZpbGVuYW1lU3Bhbi50aXRsZSA9IGZpbGVuYW1lIHx8ICcnXG5cbiAgICAvLyBBZGQgZmlsZSBhY3Rpb25zIGNvbnRhaW5lciAocmlnaHQgc2lkZSlcbiAgICBjb25zdCBmaWxlQWN0aW9ucyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpXG4gICAgZmlsZUFjdGlvbnMuY2xhc3NOYW1lID0gJ2ZpbGUtYWN0aW9ucydcbiAgICBmaWxlQWN0aW9ucy5zdHlsZS5kaXNwbGF5ID0gJ2ZsZXgnXG4gICAgZmlsZUFjdGlvbnMuc3R5bGUuZ2FwID0gJzRweCdcblxuICAgIC8vIENyZWF0ZSBjb3B5IGJ1dHRvbiB3aXRoIGljb25cbiAgICBjb25zdCBjb3B5QnV0dG9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJylcbiAgICBjb3B5QnV0dG9uLnN0eWxlLmJvcmRlciA9ICdub25lJ1xuICAgIGNvcHlCdXR0b24uc3R5bGUuYmFja2dyb3VuZCA9ICdub25lJ1xuICAgIGNvcHlCdXR0b24uc3R5bGUuY3Vyc29yID0gJ3BvaW50ZXInXG4gICAgY29weUJ1dHRvbi5zdHlsZS5jb2xvciA9ICd2YXIoLS12c2NvZGUtZWRpdG9yLWZvcmVncm91bmQsIHJnYmEoMCwgMCwgMCwgMC44NSkpJ1xuICAgIGNvcHlCdXR0b24uc3R5bGUuZGlzcGxheSA9ICdmbGV4J1xuICAgIGNvcHlCdXR0b24uc3R5bGUuYWxpZ25JdGVtcyA9ICdjZW50ZXInXG4gICAgY29weUJ1dHRvbi5zdHlsZS5qdXN0aWZ5Q29udGVudCA9ICdjZW50ZXInXG4gICAgY29weUJ1dHRvbi5zdHlsZS53aWR0aCA9ICczMnB4J1xuICAgIGNvcHlCdXR0b24uc3R5bGUuaGVpZ2h0ID0gJzMycHgnXG4gICAgY29weUJ1dHRvbi5zdHlsZS5wYWRkaW5nID0gJzAnXG4gICAgY29weUJ1dHRvbi5zdHlsZS5ib3JkZXJSYWRpdXMgPSAnNHB4J1xuICAgIGNvcHlCdXR0b24uc3R5bGUudHJhbnNpdGlvbiA9ICdhbGwgMC4zcydcbiAgICBjb3B5QnV0dG9uLnRpdGxlID0gJ0NvcHkgY29kZSB0byBjbGlwYm9hcmQnXG5cbiAgICAvLyBIb3ZlciBlZmZlY3RcbiAgICBjb3B5QnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3ZlcicsICgpID0+IHtcbiAgICAgIGNvcHlCdXR0b24uc3R5bGUuY29sb3IgPSAnIzE4OTBmZidcbiAgICAgIGNvcHlCdXR0b24uc3R5bGUuYmFja2dyb3VuZENvbG9yID0gJ3JnYmEoMCwgMCwgMCwgMC4wNCknXG4gICAgfSlcbiAgICBjb3B5QnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3V0JywgKCkgPT4ge1xuICAgICAgY29weUJ1dHRvbi5zdHlsZS5jb2xvciA9ICd2YXIoLS12c2NvZGUtZWRpdG9yLWZvcmVncm91bmQsIHJnYmEoMCwgMCwgMCwgMC44NSkpJ1xuICAgICAgY29weUJ1dHRvbi5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSAndHJhbnNwYXJlbnQnXG4gICAgfSlcblxuICAgIC8vIENvcHkgZnVuY3Rpb25hbGl0eVxuICAgIGNvcHlCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBhc3luYyAoZXZlbnQpID0+IHtcbiAgICAgIC8vIFByZXZlbnQgZGVmYXVsdCBhY3Rpb24gYW5kIGV2ZW50IGJ1YmJsaW5nXG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IG5hdmlnYXRvci5jbGlwYm9hcmQud3JpdGVUZXh0KGNvZGUgfHwgJycpO1xuXG4gICAgICAgIC8vIFNob3cgZmVlZGJhY2tcbiAgICAgICAgY29weUJ1dHRvbi5pbm5lckhUTUwgPSBgPHN2ZyB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCIgc3Ryb2tlPVwiY3VycmVudENvbG9yXCIgc3Ryb2tlLXdpZHRoPVwiMlwiIGZpbGw9XCJub25lXCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCI+PHBhdGggZD1cIk05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXpcIj48L3BhdGg+PC9zdmc+YDtcbiAgICAgICAgY29weUJ1dHRvbi5zdHlsZS5jb2xvciA9ICcjNTJjNDFhJztcblxuXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIC8vIFVzZSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUgdG8gZW5zdXJlIHNtb290aCB0cmFuc2l0aW9uXG4gICAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcbiAgICAgICAgICAgIGNvcHlCdXR0b24uaW5uZXJIVE1MID0gY29weVN2ZztcbiAgICAgICAgICAgIGNvcHlCdXR0b24uc3R5bGUuY29sb3IgPSAndmFyKC0tdnNjb2RlLWVkaXRvci1mb3JlZ3JvdW5kLCByZ2JhKDAsIDAsIDAsIDAuODUpKSc7XG5cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSwgMjAwMCk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGNvcHkgY29kZTonLCBlcnIpO1xuXG4gICAgICB9XG5cbiAgICAgIC8vIFJldHVybiBmYWxzZSB0byBlbnN1cmUgbm8gZnVydGhlciBhY3Rpb25cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9KVxuXG4gICAgLy8gQ3JlYXRlIGRvd25sb2FkIGJ1dHRvbiB3aXRoIGljb25cbiAgICBjb25zdCBkb3dubG9hZEJ1dHRvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2J1dHRvbicpXG4gICAgZG93bmxvYWRCdXR0b24uc3R5bGUuYm9yZGVyID0gJ25vbmUnXG4gICAgZG93bmxvYWRCdXR0b24uc3R5bGUuYmFja2dyb3VuZCA9ICdub25lJ1xuICAgIGRvd25sb2FkQnV0dG9uLnN0eWxlLmN1cnNvciA9ICdwb2ludGVyJ1xuICAgIGRvd25sb2FkQnV0dG9uLnN0eWxlLmNvbG9yID0gJ3ZhcigtLXZzY29kZS1lZGl0b3ItZm9yZWdyb3VuZCwgcmdiYSgwLCAwLCAwLCAwLjg1KSknXG4gICAgZG93bmxvYWRCdXR0b24uc3R5bGUuZGlzcGxheSA9ICdmbGV4J1xuICAgIGRvd25sb2FkQnV0dG9uLnN0eWxlLmFsaWduSXRlbXMgPSAnY2VudGVyJ1xuICAgIGRvd25sb2FkQnV0dG9uLnN0eWxlLmp1c3RpZnlDb250ZW50ID0gJ2NlbnRlcidcbiAgICBkb3dubG9hZEJ1dHRvbi5zdHlsZS53aWR0aCA9ICczMnB4J1xuICAgIGRvd25sb2FkQnV0dG9uLnN0eWxlLmhlaWdodCA9ICczMnB4J1xuICAgIGRvd25sb2FkQnV0dG9uLnN0eWxlLnBhZGRpbmcgPSAnMCdcbiAgICBkb3dubG9hZEJ1dHRvbi5zdHlsZS5ib3JkZXJSYWRpdXMgPSAnNHB4J1xuICAgIGRvd25sb2FkQnV0dG9uLnN0eWxlLnRyYW5zaXRpb24gPSAnYWxsIDAuM3MnXG4gICAgZG93bmxvYWRCdXR0b24udGl0bGUgPSAnRG93bmxvYWQgY29kZSBhcyBmaWxlJ1xuXG4gICAgLy8gSG92ZXIgZWZmZWN0XG4gICAgZG93bmxvYWRCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignbW91c2VvdmVyJywgKCkgPT4ge1xuICAgICAgZG93bmxvYWRCdXR0b24uc3R5bGUuY29sb3IgPSAnIzE4OTBmZidcbiAgICAgIGRvd25sb2FkQnV0dG9uLnN0eWxlLmJhY2tncm91bmRDb2xvciA9ICdyZ2JhKDAsIDAsIDAsIDAuMDQpJ1xuICAgIH0pXG4gICAgZG93bmxvYWRCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignbW91c2VvdXQnLCAoKSA9PiB7XG4gICAgICBkb3dubG9hZEJ1dHRvbi5zdHlsZS5jb2xvciA9ICd2YXIoLS12c2NvZGUtZWRpdG9yLWZvcmVncm91bmQsIHJnYmEoMCwgMCwgMCwgMC44NSkpJ1xuICAgICAgZG93bmxvYWRCdXR0b24uc3R5bGUuYmFja2dyb3VuZENvbG9yID0gJ3RyYW5zcGFyZW50J1xuICAgIH0pXG5cbiAgICAvLyBEb3dubG9hZCBmdW5jdGlvbmFsaXR5XG4gICAgZG93bmxvYWRCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoZXZlbnQpID0+IHtcbiAgICAgIC8vIFByZXZlbnQgZGVmYXVsdCBhY3Rpb24gYW5kIGV2ZW50IGJ1YmJsaW5nXG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgIC8vIFNhdmUgb3JpZ2luYWwgY29udGVudFxuICAgICAgY29uc3Qgb3JpZ2luYWxJbm5lckhUTUwgPSBkb3dubG9hZEJ1dHRvbi5pbm5lckhUTUw7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGJsb2IgPSBuZXcgQmxvYihbY29kZSB8fCAnJ10sIHsgdHlwZTogJ3RleHQvcGxhaW4nIH0pO1xuICAgICAgICBjb25zdCB1cmwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKGJsb2IpO1xuICAgICAgICBjb25zdCBhID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgICAgICBhLmhyZWYgPSB1cmw7XG4gICAgICAgIGEuZG93bmxvYWQgPSBmaWxlbmFtZSB8fCAnY29kZS50eHQnO1xuICAgICAgICBhLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgIGEuc2V0QXR0cmlidXRlKCdkYXRhLW5vLXNjcm9sbCcsICd0cnVlJyk7IC8vIE1hcmsgYXMgbm8tc2Nyb2xsXG5cbiAgICAgICAgLy8gRXhlY3V0ZSBkb3dubG9hZFxuICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGEpO1xuICAgICAgICBhLmNsaWNrKCk7XG4gICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoYSk7XG5cbiAgICAgICAgLy8gU2hvdyBzdWNjZXNzIGZlZWRiYWNrIHNpbWlsYXIgdG8gY29weSBidXR0b25cbiAgICAgICAgZG93bmxvYWRCdXR0b24uaW5uZXJIVE1MID0gYDxzdmcgdmlld0JveD1cIjAgMCAyNCAyNFwiIHdpZHRoPVwiMTZcIiBoZWlnaHQ9XCIxNlwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiIHN0cm9rZS13aWR0aD1cIjJcIiBmaWxsPVwibm9uZVwiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiPjxwYXRoIGQ9XCJNOSAxNi4xN0w0LjgzIDEybC0xLjQyIDEuNDFMOSAxOSAyMSA3bC0xLjQxLTEuNDF6XCI+PC9wYXRoPjwvc3ZnPmA7XG4gICAgICAgIGRvd25sb2FkQnV0dG9uLnN0eWxlLmNvbG9yID0gJyM1MmM0MWEnO1xuXG5cbiAgICAgICAgLy8gUmVzZXQgYnV0dG9uIGFmdGVyIHRpbWVvdXRcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgLy8gVXNlIHJlcXVlc3RBbmltYXRpb25GcmFtZSBmb3Igc21vb3RoZXIgdHJhbnNpdGlvblxuICAgICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XG4gICAgICAgICAgICBkb3dubG9hZEJ1dHRvbi5pbm5lckhUTUwgPSBkb3dubG9hZFN2ZztcbiAgICAgICAgICAgIGRvd25sb2FkQnV0dG9uLnN0eWxlLmNvbG9yID0gJ3ZhcigtLXZzY29kZS1lZGl0b3ItZm9yZWdyb3VuZCwgcmdiYSgwLCAwLCAwLCAwLjg1KSknO1xuICAgICAgICAgICAgVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpOyAvLyBDbGVhbiB1cCBVUkwgb2JqZWN0XG5cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSwgMjAwMCk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGRvd25sb2FkIGNvZGU6JywgZXJyKTtcbiAgICAgICAgZG93bmxvYWRCdXR0b24uaW5uZXJIVE1MID0gb3JpZ2luYWxJbm5lckhUTUw7XG4gICAgICB9XG5cbiAgICAgIC8vIFJldHVybiBmYWxzZSB0byBlbnN1cmUgbm8gZnVydGhlciBhY3Rpb25cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9KVxuXG4gICAgLy8gQ29weSBpY29uIFNWR1xuICAgIGNvbnN0IGNvcHlTdmcgPSBgPHN2ZyB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCIgc3Ryb2tlPVwiY3VycmVudENvbG9yXCIgc3Ryb2tlLXdpZHRoPVwiMlwiIGZpbGw9XCJub25lXCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCI+PHJlY3QgeD1cIjlcIiB5PVwiOVwiIHdpZHRoPVwiMTNcIiBoZWlnaHQ9XCIxM1wiIHJ4PVwiMlwiIHJ5PVwiMlwiPjwvcmVjdD48cGF0aCBkPVwiTTUgMTVINGEyIDIgMCAwIDEtMi0yVjRhMiAyIDAgMCAxIDItMmg5YTIgMiAwIDAgMSAyIDJ2MVwiPjwvcGF0aD48L3N2Zz5gO1xuXG4gICAgLy8gRG93bmxvYWQgaWNvbiBTVkdcbiAgICBjb25zdCBkb3dubG9hZFN2ZyA9IGA8c3ZnIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiB3aWR0aD1cIjE2XCIgaGVpZ2h0PVwiMTZcIiBzdHJva2U9XCJjdXJyZW50Q29sb3JcIiBzdHJva2Utd2lkdGg9XCIyXCIgZmlsbD1cIm5vbmVcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIj48cGF0aCBkPVwiTTIxIDE1djRhMiAyIDAgMCAxLTIgMkg1YTIgMiAwIDAgMS0yLTJ2LTRcIj48L3BhdGg+PHBvbHlsaW5lIHBvaW50cz1cIjcgMTAgMTIgMTUgMTcgMTBcIj48L3BvbHlsaW5lPjxsaW5lIHgxPVwiMTJcIiB5MT1cIjE1XCIgeDI9XCIxMlwiIHkyPVwiM1wiPjwvbGluZT48L3N2Zz5gO1xuXG4gICAgY29weUJ1dHRvbi5pbm5lckhUTUwgPSBjb3B5U3ZnO1xuICAgIGRvd25sb2FkQnV0dG9uLmlubmVySFRNTCA9IGRvd25sb2FkU3ZnO1xuXG4gICAgLy8gQWRkIGJ1dHRvbnMgdG8gYWN0aW9ucyBjb250YWluZXJcbiAgICBmaWxlQWN0aW9ucy5hcHBlbmRDaGlsZChjb3B5QnV0dG9uKVxuICAgIGZpbGVBY3Rpb25zLmFwcGVuZENoaWxkKGRvd25sb2FkQnV0dG9uKVxuXG4gICAgLy8gQnVpbGQgdGhlIHRhYlxuICAgIHRhYkNvbnRhaW5lci5hcHBlbmRDaGlsZChmaWxlbmFtZVNwYW4pXG4gICAgdGFiQ29udGFpbmVyLmFwcGVuZENoaWxkKGZpbGVBY3Rpb25zKVxuXG4gICAgLy8gSW5zZXJ0IHRhYiBiZWZvcmUgdGhlIGVkaXRvciBjb250ZW50XG4gICAgaWYgKGNvbnRhaW5lcikge1xuICAgICAgY29udGFpbmVyLmluc2VydEJlZm9yZSh0YWJDb250YWluZXIsIGVsZW1lbnQpXG5cbiAgICAgIC8vIEFkZCBzb21lIHN0eWxpbmcgdG8gdGhlIGNvbnRhaW5lciBmb3IgYmV0dGVyIGFwcGVhcmFuY2VcbiAgICAgIGNvbnRhaW5lci5zdHlsZS5ib3JkZXIgPSAnMXB4IHNvbGlkICNlOGU4ZTgnXG4gICAgICBjb250YWluZXIuc3R5bGUuYm9yZGVyUmFkaXVzID0gJzJweCdcbiAgICAgIGNvbnRhaW5lci5zdHlsZS5vdmVyZmxvdyA9ICdoaWRkZW4nXG4gICAgICBjb250YWluZXIuc3R5bGUubWFyZ2luQm90dG9tID0gJzE2cHgnXG4gICAgICBjb250YWluZXIuc3R5bGUucGFkZGluZyA9ICcwJ1xuXG4gICAgICAvLyBBZGQgaW5uZXIgcGFkZGluZyB0byBjb2RlIGNvbnRlbnRcbiAgICAgIGVsZW1lbnQuc3R5bGUucGFkZGluZyA9ICcxNnB4J1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBJZiBubyBjb250YWluZXIsIHdyYXAgdGhlIGVsZW1lbnQgd2l0aCBvbmVcbiAgICAgIGNvbnN0IHdyYXBwZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgICAgd3JhcHBlci5zdHlsZS5ib3JkZXIgPSAnMXB4IHNvbGlkICNlOGU4ZTgnXG4gICAgICB3cmFwcGVyLnN0eWxlLmJvcmRlclJhZGl1cyA9ICcycHgnXG4gICAgICB3cmFwcGVyLnN0eWxlLm92ZXJmbG93ID0gJ2hpZGRlbidcbiAgICAgIHdyYXBwZXIuc3R5bGUubWFyZ2luQm90dG9tID0gJzE2cHgnXG4gICAgICB3cmFwcGVyLnN0eWxlLnBhZGRpbmcgPSAnMCdcbiAgICAgIHdyYXBwZXIuc3R5bGUud2lkdGggPSAnMTAwJSdcblxuICAgICAgY29uc3QgcGFyZW50ID0gZWxlbWVudC5wYXJlbnRFbGVtZW50XG4gICAgICBpZiAocGFyZW50KSB7XG4gICAgICAgIHBhcmVudC5pbnNlcnRCZWZvcmUod3JhcHBlciwgZWxlbWVudClcbiAgICAgICAgd3JhcHBlci5hcHBlbmRDaGlsZCh0YWJDb250YWluZXIpXG4gICAgICAgIHdyYXBwZXIuYXBwZW5kQ2hpbGQoZWxlbWVudClcblxuICAgICAgICAvLyBBZGQgaW5uZXIgcGFkZGluZyB0byBjb2RlIGNvbnRlbnRcbiAgICAgICAgZWxlbWVudC5zdHlsZS5wYWRkaW5nID0gJzE2cHgnXG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmdlTW9uYWNvQ29sb3JpemVPcHRpb25zIHtcbiAgLyoqIEVsZW1lbnQgdG8gY29sb3JpemUgKCZsdDtjb2RlJmd0OyBlbGVtZW50KS4gKi9cbiAgZWxlbWVudDogSFRNTEVsZW1lbnRcblxuICAvKiogQ29kZSB0byBoaWdobGlnaHQgKi9cbiAgY29kZTogc3RyaW5nXG5cbiAgLyoqIFRoZW1lIHRvIHVzZSBmb3IgdGhlIHN5bnRheCBoaWdobGlnaHRpbmcgICovXG4gIHRoZW1lPzogc3RyaW5nXG5cbiAgLyoqIFRhcmdldCBsYW5ndWFnZSAoZGVmYXVsdCBwbGFpbnRleHQpLiAqL1xuICBsYW5ndWFnZT86IHN0cmluZ1xuXG4gIC8qKlxuICAgKiBTdGFydCBsaW5lIG51bWJlciBvciBhIHNwYWNlIHNlcGFyYXRlZCBsaXN0IG9mIGxpbmUgbnVtYmVycyB0byBzaG93LlxuICAgKlxuICAgKiBFeGFtcGxlOlxuICAgKlxuICAgKiAqU2hvdyBhbGwgbGluZSBudW1iZXJzIHN0YXJ0aW5nIDEqXG4gICAqXG4gICAqIGBcIjFcImBcbiAgICpcbiAgICogKlNob3cgYWxsIGxpbmUgbnVtYmVycyBmcm9tIDEgdG8gNCpcbiAgICpcbiAgICogYFwiMS00XCJgXG4gICAqXG4gICAqICpTaG93IGxpbmVzIDIgNCA1IDYgNyA5KlxuICAgKlxuICAgKiBgXCIyIDQtNyA5XCJgXG4gICAqL1xuICBsaW5lcz86IHN0cmluZyB8IG51bWJlclxuXG4gIC8qKlxuICAgKiBBIHNwYWNlIHNlcGFyYXRlZCBsaXN0IG9mIGxpbmUgbnVtYmVycyB0byBoaWdobGlnaHQuXG4gICAqXG4gICAqIEV4YW1wbGU6XG4gICAqXG4gICAqICpIaWdobGlnaHQgbGluZSAxKlxuICAgKlxuICAgKiBgXCIxXCJgXG4gICAqXG4gICAqICpIaWdobGlnaHQgYWxsIGxpbmVzIGZyb20gMSB0byA0KlxuICAgKlxuICAgKiBgXCIxLTRcImBcbiAgICpcbiAgICogKkhpZ2hsaWdodCBsaW5lcyAyIDQgNSA2IDcgOSpcbiAgICpcbiAgICogYFwiMiA0LTcgOVwiYFxuICAgKi9cbiAgaGlnaGxpZ2h0cz86IHN0cmluZyB8IG51bWJlclxuXG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIGZpbGVuYW1lIHRvIGRpc3BsYXkgaW4gdGhlIHRhYiBoZWFkZXIuXG4gICAqL1xuICBmaWxlbmFtZT86IHN0cmluZ1xufVxuIl19