@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
JavaScript
/**
* 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==