UNPKG

@dollhousemcp/mcp-server

Version:

DollhouseMCP - A Model Context Protocol (MCP) server that enables dynamic AI persona management from markdown files, allowing Claude and other compatible AI assistants to activate and switch between different behavioral personas.

213 lines 28.1 kB
/** * ContentExtractor - Extracts components from DollhouseMCP skills for Anthropic conversion * * Identifies and extracts: * - Code blocks (bash, python, etc.) → scripts/ * - Documentation sections → reference/ * - Examples → examples/ * - Main instructions (preserved in SKILL.md) * * SECURITY MODEL: * - This is a FORMAT ANALYSIS tool, not a security boundary * - Preserves content exactly as-is for mechanical transformation * - No modification, sanitization, or validation * - Used by converters which are format transformers, not security gates */ export class ContentExtractor { /** * Parse DollhouseMCP markdown content and identify extractable sections * REFACTORED: Simplified by extracting code block and section handling logic */ extractSections(content) { // NOTE: No Unicode normalization - preserves content fidelity for conversion const sections = []; const lines = content.split('\n'); const state = { inCodeBlock: false, codeBlockStart: 0, codeBlockLanguage: '', codeBlockContent: [], currentSection: '', sectionStart: 0 }; for (let i = 0; i < lines.length; i++) { const line = lines[i]; this.processLine(line, i, state, sections); } return sections; } /** * Process a single line and update state * REFACTORED: Extracted to reduce cognitive complexity */ processLine(line, lineIndex, state, sections) { if (line.startsWith('```')) { this.handleCodeBlockBoundary(line, lineIndex, state, sections); } else if (state.inCodeBlock) { state.codeBlockContent.push(line); } else if (line.startsWith('##')) { this.handleSectionHeader(line, lineIndex, state); } } /** * Handle code block start/end boundary * REFACTORED: Extracted to reduce cognitive complexity */ handleCodeBlockBoundary(line, lineIndex, state, sections) { if (state.inCodeBlock) { // End of code block state.inCodeBlock = false; this.addCodeBlockIfExtractable(lineIndex, state, sections); } else { // Start of code block state.inCodeBlock = true; state.codeBlockStart = lineIndex; state.codeBlockLanguage = line.substring(3).trim(); state.codeBlockContent = []; } } /** * Add code block to sections if it should be extracted * REFACTORED: Extracted to reduce cognitive complexity */ addCodeBlockIfExtractable(endLineIndex, state, sections) { if (!this.shouldExtractCodeBlock(state.codeBlockLanguage, state.codeBlockContent)) { return; } sections.push({ type: 'code', language: state.codeBlockLanguage, title: this.inferCodeBlockTitle(state.codeBlockContent, state.currentSection), content: state.codeBlockContent.join('\n'), startLine: state.codeBlockStart, endLine: endLineIndex, filename: this.generateScriptFilename(state.codeBlockLanguage, state.codeBlockContent, state.currentSection) }); } /** * Handle section header * REFACTORED: Extracted to reduce cognitive complexity */ handleSectionHeader(line, lineIndex, state) { state.currentSection = line.substring(2).trim(); state.sectionStart = lineIndex; // Check if this section should be extracted // (Currently just tracking for context - full extraction logic not implemented) // Future enhancement: use shouldExtractSection result for section extraction } /** * Determine if a code block should be extracted to a separate file */ shouldExtractCodeBlock(language, content) { // Extract bash, python, javascript scripts const extractableLanguages = ['bash', 'sh', 'python', 'py', 'javascript', 'js', 'typescript', 'ts']; if (!extractableLanguages.includes(language.toLowerCase())) { return false; } // Extract if it's substantial (more than 3 lines) return content.length > 3; } /** * Determine if a documentation section should be extracted */ shouldExtractSection(sectionTitle) { const extractableSections = [ 'input formats', 'error handling', 'supported clients', 'command building', 'configuration', 'api reference', 'troubleshooting' ]; return extractableSections.some(pattern => sectionTitle.toLowerCase().includes(pattern)); } /** * Generate appropriate filename for extracted script */ generateScriptFilename(language, content, section) { // Look for meaningful names in comments const firstLine = content[0] || ''; // Common patterns: "# Pre-execution checks", "# Install server", etc. if (firstLine.startsWith('#')) { const titleMatch = /^#\s*(.+)/.exec(firstLine); if (titleMatch) { const title = titleMatch[1].toLowerCase() .replaceAll(/[^a-z0-9\s-]/g, '') .replaceAll(/\s+/g, '-'); return `${title}.${this.getExtension(language)}`; } } // Use section name if (section) { const sectionSlug = section.toLowerCase() .replaceAll(/[^a-z0-9\s-]/g, '') .replaceAll(/\s+/g, '-'); return `${sectionSlug}.${this.getExtension(language)}`; } return `script.${this.getExtension(language)}`; } /** * Infer title for code block from surrounding context */ inferCodeBlockTitle(content, section) { const firstLine = content[0] || ''; // Check for comment at start if (firstLine.startsWith('#') || firstLine.startsWith('//')) { return firstLine.replace(/^[#/\s]+/, '').trim(); } return section || 'Script'; } /** * Get file extension for language */ getExtension(language) { const extensions = { bash: 'sh', sh: 'sh', python: 'py', py: 'py', javascript: 'js', js: 'js', typescript: 'ts', ts: 'ts' }; return extensions[language.toLowerCase()] || 'txt'; } /** * Extract complete documentation section (including subsections) */ extractDocumentationSection(content, sectionTitle) { // NOTE: No Unicode normalization - preserves content fidelity const lines = content.split('\n'); let capturing = false; let sectionContent = []; let sectionLevel = 0; for (const line of lines) { if (line.startsWith('##')) { const level = /^#+/.exec(line)?.[0].length || 0; const title = line.substring(level).trim(); if (!capturing && title.toLowerCase().includes(sectionTitle.toLowerCase())) { capturing = true; sectionLevel = level; sectionContent.push(line); } else if (capturing && level <= sectionLevel) { // End of section break; } else if (capturing) { sectionContent.push(line); } } else if (capturing) { sectionContent.push(line); } } return sectionContent.length > 0 ? sectionContent.join('\n') : null; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29udGVudEV4dHJhY3Rvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb252ZXJ0ZXJzL0NvbnRlbnRFeHRyYWN0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7O0dBY0c7QUFZSCxNQUFNLE9BQU8sZ0JBQWdCO0lBQ3pCOzs7T0FHRztJQUNILGVBQWUsQ0FBQyxPQUFlO1FBQzNCLDZFQUE2RTtRQUM3RSxNQUFNLFFBQVEsR0FBdUIsRUFBRSxDQUFDO1FBQ3hDLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFbEMsTUFBTSxLQUFLLEdBQUc7WUFDVixXQUFXLEVBQUUsS0FBSztZQUNsQixjQUFjLEVBQUUsQ0FBQztZQUNqQixpQkFBaUIsRUFBRSxFQUFFO1lBQ3JCLGdCQUFnQixFQUFFLEVBQWM7WUFDaEMsY0FBYyxFQUFFLEVBQUU7WUFDbEIsWUFBWSxFQUFFLENBQUM7U0FDbEIsQ0FBQztRQUVGLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDcEMsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3RCLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDL0MsQ0FBQztRQUVELE9BQU8sUUFBUSxDQUFDO0lBQ3BCLENBQUM7SUFFRDs7O09BR0c7SUFDSyxXQUFXLENBQ2YsSUFBWSxFQUNaLFNBQWlCLEVBQ2pCLEtBT0MsRUFDRCxRQUE0QjtRQUU1QixJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsdUJBQXVCLENBQUMsSUFBSSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsUUFBUSxD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QUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUN4RSxDQUFDO0NBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvbnRlbnRFeHRyYWN0b3IgLSBFeHRyYWN0cyBjb21wb25lbnRzIGZyb20gRG9sbGhvdXNlTUNQIHNraWxscyBmb3IgQW50aHJvcGljIGNvbnZlcnNpb25cbiAqXG4gKiBJZGVudGlmaWVzIGFuZCBleHRyYWN0czpcbiAqIC0gQ29kZSBibG9ja3MgKGJhc2gsIHB5dGhvbiwgZXRjLikg4oaSIHNjcmlwdHMvXG4gKiAtIERvY3VtZW50YXRpb24gc2VjdGlvbnMg4oaSIHJlZmVyZW5jZS9cbiAqIC0gRXhhbXBsZXMg4oaSIGV4YW1wbGVzL1xuICogLSBNYWluIGluc3RydWN0aW9ucyAocHJlc2VydmVkIGluIFNLSUxMLm1kKVxuICpcbiAqIFNFQ1VSSVRZIE1PREVMOlxuICogLSBUaGlzIGlzIGEgRk9STUFUIEFOQUxZU0lTIHRvb2wsIG5vdCBhIHNlY3VyaXR5IGJvdW5kYXJ5XG4gKiAtIFByZXNlcnZlcyBjb250ZW50IGV4YWN0bHkgYXMtaXMgZm9yIG1lY2hhbmljYWwgdHJhbnNmb3JtYXRpb25cbiAqIC0gTm8gbW9kaWZpY2F0aW9uLCBzYW5pdGl6YXRpb24sIG9yIHZhbGlkYXRpb25cbiAqIC0gVXNlZCBieSBjb252ZXJ0ZXJzIHdoaWNoIGFyZSBmb3JtYXQgdHJhbnNmb3JtZXJzLCBub3Qgc2VjdXJpdHkgZ2F0ZXNcbiAqL1xuXG5leHBvcnQgaW50ZXJmYWNlIEV4dHJhY3RlZFNlY3Rpb24ge1xuICAgIHR5cGU6ICdjb2RlJyB8ICdkb2N1bWVudGF0aW9uJyB8ICdleGFtcGxlJyB8ICdtYWluJztcbiAgICBsYW5ndWFnZT86IHN0cmluZztcbiAgICB0aXRsZTogc3RyaW5nO1xuICAgIGNvbnRlbnQ6IHN0cmluZztcbiAgICBzdGFydExpbmU6IG51bWJlcjtcbiAgICBlbmRMaW5lOiBudW1iZXI7XG4gICAgZmlsZW5hbWU/OiBzdHJpbmc7IC8vIFN1Z2dlc3RlZCBmaWxlbmFtZSBmb3IgZXh0cmFjdGlvblxufVxuXG5leHBvcnQgY2xhc3MgQ29udGVudEV4dHJhY3RvciB7XG4gICAgLyoqXG4gICAgICogUGFyc2UgRG9sbGhvdXNlTUNQIG1hcmtkb3duIGNvbnRlbnQgYW5kIGlkZW50aWZ5IGV4dHJhY3RhYmxlIHNlY3Rpb25zXG4gICAgICogUkVGQUNUT1JFRDogU2ltcGxpZmllZCBieSBleHRyYWN0aW5nIGNvZGUgYmxvY2sgYW5kIHNlY3Rpb24gaGFuZGxpbmcgbG9naWNcbiAgICAgKi9cbiAgICBleHRyYWN0U2VjdGlvbnMoY29udGVudDogc3RyaW5nKTogRXh0cmFjdGVkU2VjdGlvbltdIHtcbiAgICAgICAgLy8gTk9URTogTm8gVW5pY29kZSBub3JtYWxpemF0aW9uIC0gcHJlc2VydmVzIGNvbnRlbnQgZmlkZWxpdHkgZm9yIGNvbnZlcnNpb25cbiAgICAgICAgY29uc3Qgc2VjdGlvbnM6IEV4dHJhY3RlZFNlY3Rpb25bXSA9IFtdO1xuICAgICAgICBjb25zdCBsaW5lcyA9IGNvbnRlbnQuc3BsaXQoJ1xcbicpO1xuXG4gICAgICAgIGNvbnN0IHN0YXRlID0ge1xuICAgICAgICAgICAgaW5Db2RlQmxvY2s6IGZhbHNlLFxuICAgICAgICAgICAgY29kZUJsb2NrU3RhcnQ6IDAsXG4gICAgICAgICAgICBjb2RlQmxvY2tMYW5ndWFnZTogJycsXG4gICAgICAgICAgICBjb2RlQmxvY2tDb250ZW50OiBbXSBhcyBzdHJpbmdbXSxcbiAgICAgICAgICAgIGN1cnJlbnRTZWN0aW9uOiAnJyxcbiAgICAgICAgICAgIHNlY3Rpb25TdGFydDogMFxuICAgICAgICB9O1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGxpbmUgPSBsaW5lc1tpXTtcbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc0xpbmUobGluZSwgaSwgc3RhdGUsIHNlY3Rpb25zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzZWN0aW9ucztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcm9jZXNzIGEgc2luZ2xlIGxpbmUgYW5kIHVwZGF0ZSBzdGF0ZVxuICAgICAqIFJFRkFDVE9SRUQ6IEV4dHJhY3RlZCB0byByZWR1Y2UgY29nbml0aXZlIGNvbXBsZXhpdHlcbiAgICAgKi9cbiAgICBwcml2YXRlIHByb2Nlc3NMaW5lKFxuICAgICAgICBsaW5lOiBzdHJpbmcsXG4gICAgICAgIGxpbmVJbmRleDogbnVtYmVyLFxuICAgICAgICBzdGF0ZToge1xuICAgICAgICAgICAgaW5Db2RlQmxvY2s6IGJvb2xlYW47XG4gICAgICAgICAgICBjb2RlQmxvY2tTdGFydDogbnVtYmVyO1xuICAgICAgICAgICAgY29kZUJsb2NrTGFuZ3VhZ2U6IHN0cmluZztcbiAgICAgICAgICAgIGNvZGVCbG9ja0NvbnRlbnQ6IHN0cmluZ1tdO1xuICAgICAgICAgICAgY3VycmVudFNlY3Rpb246IHN0cmluZztcbiAgICAgICAgICAgIHNlY3Rpb25TdGFydDogbnVtYmVyO1xuICAgICAgICB9LFxuICAgICAgICBzZWN0aW9uczogRXh0cmFjdGVkU2VjdGlvbltdXG4gICAgKTogdm9pZCB7XG4gICAgICAgIGlmIChsaW5lLnN0YXJ0c1dpdGgoJ2BgYCcpKSB7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZUNvZGVCbG9ja0JvdW5kYXJ5KGxpbmUsIGxpbmVJbmRleCwgc3RhdGUsIHNlY3Rpb25zKTtcbiAgICAgICAgfSBlbHNlIGlmIChzdGF0ZS5pbkNvZGVCbG9jaykge1xuICAgICAgICAgICAgc3RhdGUuY29kZUJsb2NrQ29udGVudC5wdXNoKGxpbmUpO1xuICAgICAgICB9IGVsc2UgaWYgKGxpbmUuc3RhcnRzV2l0aCgnIyMnKSkge1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVTZWN0aW9uSGVhZGVyKGxpbmUsIGxpbmVJbmRleCwgc3RhdGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlIGNvZGUgYmxvY2sgc3RhcnQvZW5kIGJvdW5kYXJ5XG4gICAgICogUkVGQUNUT1JFRDogRXh0cmFjdGVkIHRvIHJlZHVjZSBjb2duaXRpdmUgY29tcGxleGl0eVxuICAgICAqL1xuICAgIHByaXZhdGUgaGFuZGxlQ29kZUJsb2NrQm91bmRhcnkoXG4gICAgICAgIGxpbmU6IHN0cmluZyxcbiAgICAgICAgbGluZUluZGV4OiBudW1iZXIsXG4gICAgICAgIHN0YXRlOiB7XG4gICAgICAgICAgICBpbkNvZGVCbG9jazogYm9vbGVhbjtcbiAgICAgICAgICAgIGNvZGVCbG9ja1N0YXJ0OiBudW1iZXI7XG4gICAgICAgICAgICBjb2RlQmxvY2tMYW5ndWFnZTogc3RyaW5nO1xuICAgICAgICAgICAgY29kZUJsb2NrQ29udGVudDogc3RyaW5nW107XG4gICAgICAgICAgICBjdXJyZW50U2VjdGlvbjogc3RyaW5nO1xuICAgICAgICB9LFxuICAgICAgICBzZWN0aW9uczogRXh0cmFjdGVkU2VjdGlvbltdXG4gICAgKTogdm9pZCB7XG4gICAgICAgIGlmIChzdGF0ZS5pbkNvZGVCbG9jaykge1xuICAgICAgICAgICAgLy8gRW5kIG9mIGNvZGUgYmxvY2tcbiAgICAgICAgICAgIHN0YXRlLmluQ29kZUJsb2NrID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmFkZENvZGVCbG9ja0lmRXh0cmFjdGFibGUobGluZUluZGV4LCBzdGF0ZSwgc2VjdGlvbnMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gU3RhcnQgb2YgY29kZSBibG9ja1xuICAgICAgICAgICAgc3RhdGUuaW5Db2RlQmxvY2sgPSB0cnVlO1xuICAgICAgICAgICAgc3RhdGUuY29kZUJsb2NrU3RhcnQgPSBsaW5lSW5kZXg7XG4gICAgICAgICAgICBzdGF0ZS5jb2RlQmxvY2tMYW5ndWFnZSA9IGxpbmUuc3Vic3RyaW5nKDMpLnRyaW0oKTtcbiAgICAgICAgICAgIHN0YXRlLmNvZGVCbG9ja0NvbnRlbnQgPSBbXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCBjb2RlIGJsb2NrIHRvIHNlY3Rpb25zIGlmIGl0IHNob3VsZCBiZSBleHRyYWN0ZWRcbiAgICAgKiBSRUZBQ1RPUkVEOiBFeHRyYWN0ZWQgdG8gcmVkdWNlIGNvZ25pdGl2ZSBjb21wbGV4aXR5XG4gICAgICovXG4gICAgcHJpdmF0ZSBhZGRDb2RlQmxvY2tJZkV4dHJhY3RhYmxlKFxuICAgICAgICBlbmRMaW5lSW5kZXg6IG51bWJlcixcbiAgICAgICAgc3RhdGU6IHtcbiAgICAgICAgICAgIGNvZGVCbG9ja1N0YXJ0OiBudW1iZXI7XG4gICAgICAgICAgICBjb2RlQmxvY2tMYW5ndWFnZTogc3RyaW5nO1xuICAgICAgICAgICAgY29kZUJsb2NrQ29udGVudDogc3RyaW5nW107XG4gICAgICAgICAgICBjdXJyZW50U2VjdGlvbjogc3RyaW5nO1xuICAgICAgICB9LFxuICAgICAgICBzZWN0aW9uczogRXh0cmFjdGVkU2VjdGlvbltdXG4gICAgKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5zaG91bGRFeHRyYWN0Q29kZUJsb2NrKHN0YXRlLmNvZGVCbG9ja0xhbmd1YWdlLCBzdGF0ZS5jb2RlQmxvY2tDb250ZW50KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgc2VjdGlvbnMucHVzaCh7XG4gICAgICAgICAgICB0eXBlOiAnY29kZScsXG4gICAgICAgICAgICBsYW5ndWFnZTogc3RhdGUuY29kZUJsb2NrTGFuZ3VhZ2UsXG4gICAgICAgICAgICB0aXRsZTogdGhpcy5pbmZlckNvZGVCbG9ja1RpdGxlKHN0YXRlLmNvZGVCbG9ja0NvbnRlbnQsIHN0YXRlLmN1cnJlbnRTZWN0aW9uKSxcbiAgICAgICAgICAgIGNvbnRlbnQ6IHN0YXRlLmNvZGVCbG9ja0NvbnRlbnQuam9pbignXFxuJyksXG4gICAgICAgICAgICBzdGFydExpbmU6IHN0YXRlLmNvZGVCbG9ja1N0YXJ0LFxuICAgICAgICAgICAgZW5kTGluZTogZW5kTGluZUluZGV4LFxuICAgICAgICAgICAgZmlsZW5hbWU6IHRoaXMuZ2VuZXJhdGVTY3JpcHRGaWxlbmFtZShcbiAgICAgICAgICAgICAgICBzdGF0ZS5jb2RlQmxvY2tMYW5ndWFnZSxcbiAgICAgICAgICAgICAgICBzdGF0ZS5jb2RlQmxvY2tDb250ZW50LFxuICAgICAgICAgICAgICAgIHN0YXRlLmN1cnJlbnRTZWN0aW9uXG4gICAgICAgICAgICApXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZSBzZWN0aW9uIGhlYWRlclxuICAgICAqIFJFRkFDVE9SRUQ6IEV4dHJhY3RlZCB0byByZWR1Y2UgY29nbml0aXZlIGNvbXBsZXhpdHlcbiAgICAgKi9cbiAgICBwcml2YXRlIGhhbmRsZVNlY3Rpb25IZWFkZXIoXG4gICAgICAgIGxpbmU6IHN0cmluZyxcbiAgICAgICAgbGluZUluZGV4OiBudW1iZXIsXG4gICAgICAgIHN0YXRlOiB7XG4gICAgICAgICAgICBjdXJyZW50U2VjdGlvbjogc3RyaW5nO1xuICAgICAgICAgICAgc2VjdGlvblN0YXJ0OiBudW1iZXI7XG4gICAgICAgIH1cbiAgICApOiB2b2lkIHtcbiAgICAgICAgc3RhdGUuY3VycmVudFNlY3Rpb24gPSBsaW5lLnN1YnN0cmluZygyKS50cmltKCk7XG4gICAgICAgIHN0YXRlLnNlY3Rpb25TdGFydCA9IGxpbmVJbmRleDtcblxuICAgICAgICAvLyBDaGVjayBpZiB0aGlzIHNlY3Rpb24gc2hvdWxkIGJlIGV4dHJhY3RlZFxuICAgICAgICAvLyAoQ3VycmVudGx5IGp1c3QgdHJhY2tpbmcgZm9yIGNvbnRleHQgLSBmdWxsIGV4dHJhY3Rpb24gbG9naWMgbm90IGltcGxlbWVudGVkKVxuICAgICAgICAvLyBGdXR1cmUgZW5oYW5jZW1lbnQ6IHVzZSBzaG91bGRFeHRyYWN0U2VjdGlvbiByZXN1bHQgZm9yIHNlY3Rpb24gZXh0cmFjdGlvblxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERldGVybWluZSBpZiBhIGNvZGUgYmxvY2sgc2hvdWxkIGJlIGV4dHJhY3RlZCB0byBhIHNlcGFyYXRlIGZpbGVcbiAgICAgKi9cbiAgICBwcml2YXRlIHNob3VsZEV4dHJhY3RDb2RlQmxvY2sobGFuZ3VhZ2U6IHN0cmluZywgY29udGVudDogc3RyaW5nW10pOiBib29sZWFuIHtcbiAgICAgICAgLy8gRXh0cmFjdCBiYXNoLCBweXRob24sIGphdmFzY3JpcHQgc2NyaXB0c1xuICAgICAgICBjb25zdCBleHRyYWN0YWJsZUxhbmd1YWdlcyA9IFsnYmFzaCcsICdzaCcsICdweXRob24nLCAncHknLCAnamF2YXNjcmlwdCcsICdqcycsICd0eXBlc2NyaXB0JywgJ3RzJ107XG5cbiAgICAgICAgaWYgKCFleHRyYWN0YWJsZUxhbmd1YWdlcy5pbmNsdWRlcyhsYW5ndWFnZS50b0xvd2VyQ2FzZSgpKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRXh0cmFjdCBpZiBpdCdzIHN1YnN0YW50aWFsIChtb3JlIHRoYW4gMyBsaW5lcylcbiAgICAgICAgcmV0dXJuIGNvbnRlbnQubGVuZ3RoID4gMztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZXRlcm1pbmUgaWYgYSBkb2N1bWVudGF0aW9uIHNlY3Rpb24gc2hvdWxkIGJlIGV4dHJhY3RlZFxuICAgICAqL1xuICAgIHByaXZhdGUgc2hvdWxkRXh0cmFjdFNlY3Rpb24oc2VjdGlvblRpdGxlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgZXh0cmFjdGFibGVTZWN0aW9ucyA9IFtcbiAgICAgICAgICAgICdpbnB1dCBmb3JtYXRzJyxcbiAgICAgICAgICAgICdlcnJvciBoYW5kbGluZycsXG4gICAgICAgICAgICAnc3VwcG9ydGVkIGNsaWVudHMnLFxuICAgICAgICAgICAgJ2NvbW1hbmQgYnVpbGRpbmcnLFxuICAgICAgICAgICAgJ2NvbmZpZ3VyYXRpb24nLFxuICAgICAgICAgICAgJ2FwaSByZWZlcmVuY2UnLFxuICAgICAgICAgICAgJ3Ryb3VibGVzaG9vdGluZydcbiAgICAgICAgXTtcblxuICAgICAgICByZXR1cm4gZXh0cmFjdGFibGVTZWN0aW9ucy5zb21lKHBhdHRlcm4gPT5cbiAgICAgICAgICAgIHNlY3Rpb25UaXRsZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHBhdHRlcm4pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgYXBwcm9wcmlhdGUgZmlsZW5hbWUgZm9yIGV4dHJhY3RlZCBzY3JpcHRcbiAgICAgKi9cbiAgICBwcml2YXRlIGdlbmVyYXRlU2NyaXB0RmlsZW5hbWUobGFuZ3VhZ2U6IHN0cmluZywgY29udGVudDogc3RyaW5nW10sIHNlY3Rpb246IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIC8vIExvb2sgZm9yIG1lYW5pbmdmdWwgbmFtZXMgaW4gY29tbWVudHNcbiAgICAgICAgY29uc3QgZmlyc3RMaW5lID0gY29udGVudFswXSB8fCAnJztcblxuICAgICAgICAvLyBDb21tb24gcGF0dGVybnM6IFwiIyBQcmUtZXhlY3V0aW9uIGNoZWNrc1wiLCBcIiMgSW5zdGFsbCBzZXJ2ZXJcIiwgZXRjLlxuICAgICAgICBpZiAoZmlyc3RMaW5lLnN0YXJ0c1dpdGgoJyMnKSkge1xuICAgICAgICAgICAgY29uc3QgdGl0bGVNYXRjaCA9IC9eI1xccyooLispLy5leGVjKGZpcnN0TGluZSk7XG4gICAgICAgICAgICBpZiAodGl0bGVNYXRjaCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHRpdGxlID0gdGl0bGVNYXRjaFsxXS50b0xvd2VyQ2FzZSgpXG4gICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlQWxsKC9bXmEtejAtOVxccy1dL2csICcnKVxuICAgICAgICAgICAgICAgICAgICAucmVwbGFjZUFsbCgvXFxzKy9nLCAnLScpO1xuICAgICAgICAgICAgICAgIHJldHVybiBgJHt0aXRsZX0uJHt0aGlzLmdldEV4dGVuc2lvbihsYW5ndWFnZSl9YDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFVzZSBzZWN0aW9uIG5hbWVcbiAgICAgICAgaWYgKHNlY3Rpb24pIHtcbiAgICAgICAgICAgIGNvbnN0IHNlY3Rpb25TbHVnID0gc2VjdGlvbi50b0xvd2VyQ2FzZSgpXG4gICAgICAgICAgICAgICAgLnJlcGxhY2VBbGwoL1teYS16MC05XFxzLV0vZywgJycpXG4gICAgICAgICAgICAgICAgLnJlcGxhY2VBbGwoL1xccysvZywgJy0nKTtcbiAgICAgICAgICAgIHJldHVybiBgJHtzZWN0aW9uU2x1Z30uJHt0aGlzLmdldEV4dGVuc2lvbihsYW5ndWFnZSl9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBgc2NyaXB0LiR7dGhpcy5nZXRFeHRlbnNpb24obGFuZ3VhZ2UpfWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5mZXIgdGl0bGUgZm9yIGNvZGUgYmxvY2sgZnJvbSBzdXJyb3VuZGluZyBjb250ZXh0XG4gICAgICovXG4gICAgcHJpdmF0ZSBpbmZlckNvZGVCbG9ja1RpdGxlKGNvbnRlbnQ6IHN0cmluZ1tdLCBzZWN0aW9uOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICBjb25zdCBmaXJzdExpbmUgPSBjb250ZW50WzBdIHx8ICcnO1xuXG4gICAgICAgIC8vIENoZWNrIGZvciBjb21tZW50IGF0IHN0YXJ0XG4gICAgICAgIGlmIChmaXJzdExpbmUuc3RhcnRzV2l0aCgnIycpIHx8IGZpcnN0TGluZS5zdGFydHNXaXRoKCcvLycpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmlyc3RMaW5lLnJlcGxhY2UoL15bIy9cXHNdKy8sICcnKS50cmltKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc2VjdGlvbiB8fCAnU2NyaXB0JztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgZmlsZSBleHRlbnNpb24gZm9yIGxhbmd1YWdlXG4gICAgICovXG4gICAgcHJpdmF0ZSBnZXRFeHRlbnNpb24obGFuZ3VhZ2U6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IGV4dGVuc2lvbnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICAgICAgICBiYXNoOiAnc2gnLFxuICAgICAgICAgICAgc2g6ICdzaCcsXG4gICAgICAgICAgICBweXRob246ICdweScsXG4gICAgICAgICAgICBweTogJ3B5JyxcbiAgICAgICAgICAgIGphdmFzY3JpcHQ6ICdqcycsXG4gICAgICAgICAgICBqczogJ2pzJyxcbiAgICAgICAgICAgIHR5cGVzY3JpcHQ6ICd0cycsXG4gICAgICAgICAgICB0czogJ3RzJ1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBleHRlbnNpb25zW2xhbmd1YWdlLnRvTG93ZXJDYXNlKCldIHx8ICd0eHQnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4dHJhY3QgY29tcGxldGUgZG9jdW1lbnRhdGlvbiBzZWN0aW9uIChpbmNsdWRpbmcgc3Vic2VjdGlvbnMpXG4gICAgICovXG4gICAgZXh0cmFjdERvY3VtZW50YXRpb25TZWN0aW9uKGNvbnRlbnQ6IHN0cmluZywgc2VjdGlvblRpdGxlOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgLy8gTk9URTogTm8gVW5pY29kZSBub3JtYWxpemF0aW9uIC0gcHJlc2VydmVzIGNvbnRlbnQgZmlkZWxpdHlcbiAgICAgICAgY29uc3QgbGluZXMgPSBjb250ZW50LnNwbGl0KCdcXG4nKTtcbiAgICAgICAgbGV0IGNhcHR1cmluZyA9IGZhbHNlO1xuICAgICAgICBsZXQgc2VjdGlvbkNvbnRlbnQ6IHN0cmluZ1tdID0gW107XG4gICAgICAgIGxldCBzZWN0aW9uTGV2ZWwgPSAwO1xuXG4gICAgICAgIGZvciAoY29uc3QgbGluZSBvZiBsaW5lcykge1xuICAgICAgICAgICAgaWYgKGxpbmUuc3RhcnRzV2l0aCgnIyMnKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGxldmVsID0gL14jKy8uZXhlYyhsaW5lKT8uWzBdLmxlbmd0aCB8fCAwO1xuICAgICAgICAgICAgICAgIGNvbnN0IHRpdGxlID0gbGluZS5zdWJzdHJpbmcobGV2ZWwpLnRyaW0oKTtcblxuICAgICAgICAgICAgICAgIGlmICghY2FwdHVyaW5nICYmIHRpdGxlLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoc2VjdGlvblRpdGxlLnRvTG93ZXJDYXNlKCkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhcHR1cmluZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHNlY3Rpb25MZXZlbCA9IGxldmVsO1xuICAgICAgICAgICAgICAgICAgICBzZWN0aW9uQ29udGVudC5wdXNoKGxpbmUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY2FwdHVyaW5nICYmIGxldmVsIDw9IHNlY3Rpb25MZXZlbCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBFbmQgb2Ygc2VjdGlvblxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNhcHR1cmluZykge1xuICAgICAgICAgICAgICAgICAgICBzZWN0aW9uQ29udGVudC5wdXNoKGxpbmUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY2FwdHVyaW5nKSB7XG4gICAgICAgICAgICAgICAgc2VjdGlvbkNvbnRlbnQucHVzaChsaW5lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzZWN0aW9uQ29udGVudC5sZW5ndGggPiAwID8gc2VjdGlvbkNvbnRlbnQuam9pbignXFxuJykgOiBudWxsO1xuICAgIH1cbn1cbiJdfQ==