Advanced Markdown custom HTML components and extensions enable the creation of dynamic, interactive documentation that transcends traditional static content limitations through sophisticated templating systems, reusable component architectures, and seamless integration with modern web technologies. By implementing custom component libraries, dynamic content generation systems, and intelligent templating frameworks, technical teams can build rich documentation experiences that provide interactive examples, dynamic data visualization, and enhanced reader engagement while maintaining the simplicity and portability that makes Markdown an effective content format.

Why Implement Custom Markdown Components?

Professional custom component systems provide essential benefits for advanced documentation:

  • Enhanced Interactivity: Create interactive code examples, live demos, and dynamic content that engages readers
  • Consistent Design: Implement reusable components that maintain design consistency across large documentation sites
  • Dynamic Content: Generate content programmatically based on data sources, APIs, and real-time information
  • Extended Functionality: Add specialized features like tabs, accordions, callouts, and complex layouts
  • Integration Flexibility: Seamlessly blend static content with dynamic web applications and services

Foundation Component Architecture

Basic Custom Component System

Understanding how to create and integrate custom HTML components within Markdown workflows:

// markdown-components.js - Custom component system for Markdown
class MarkdownComponentSystem {
    constructor(options = {}) {
        this.components = new Map();
        this.options = {
            prefix: options.prefix || 'md',
            allowUnsafe: options.allowUnsafe || false,
            templateCache: options.templateCache !== false,
            asyncComponents: options.asyncComponents || false,
            ...options
        };
        
        this.templateCache = new Map();
        this.renderer = null;
        this.context = {};
        
        this.initializeBuiltinComponents();
    }
    
    initializeBuiltinComponents() {
        // Register commonly used components
        this.registerComponent('alert', this.createAlertComponent());
        this.registerComponent('tabs', this.createTabsComponent());
        this.registerComponent('accordion', this.createAccordionComponent());
        this.registerComponent('code-example', this.createCodeExampleComponent());
        this.registerComponent('api-reference', this.createApiReferenceComponent());
        this.registerComponent('feature-matrix', this.createFeatureMatrixComponent());
    }
    
    registerComponent(name, component) {
        if (typeof component !== 'function') {
            throw new Error(`Component '${name}' must be a function`);
        }
        
        this.components.set(name, {
            render: component,
            name,
            registered: Date.now()
        });
        
        console.log(`✅ Registered component: ${name}`);
    }
    
    async processContent(markdown) {
        // Find and process all custom components
        const componentRegex = new RegExp(
            `<${this.options.prefix}-(\\w+)([^>]*)>([\\s\\S]*?)</${this.options.prefix}-\\1>`,
            'g'
        );
        
        let processedContent = markdown;
        let match;
        
        while ((match = componentRegex.exec(markdown)) !== null) {
            const [fullMatch, componentName, attributes, content] = match;
            
            try {
                const replacement = await this.renderComponent(
                    componentName, 
                    attributes, 
                    content
                );
                processedContent = processedContent.replace(fullMatch, replacement);
            } catch (error) {
                console.error(`Error rendering component '${componentName}':`, error);
                
                // Replace with error placeholder
                const errorPlaceholder = this.createErrorPlaceholder(componentName, error.message);
                processedContent = processedContent.replace(fullMatch, errorPlaceholder);
            }
        }
        
        // Process shortcode style components
        processedContent = await this.processShortcodes(processedContent);
        
        return processedContent;
    }
    
    async renderComponent(componentName, attributesString, content) {
        const component = this.components.get(componentName);
        if (!component) {
            throw new Error(`Unknown component: ${componentName}`);
        }
        
        // Parse attributes
        const attributes = this.parseAttributes(attributesString);
        
        // Prepare component context
        const componentContext = {
            attributes,
            content: content.trim(),
            context: this.context,
            componentName,
            utils: this.createComponentUtils()
        };
        
        // Render component
        const result = await component.render(componentContext);
        
        // Cache if enabled
        if (this.options.templateCache) {
            const cacheKey = this.generateCacheKey(componentName, attributes, content);
            this.templateCache.set(cacheKey, result);
        }
        
        return result;
    }
    
    parseAttributes(attributesString) {
        const attributes = {};
        
        if (!attributesString.trim()) {
            return attributes;
        }
        
        // Parse attribute string using regex
        const attributeRegex = /([\w-]+)=(?:"([^"]*)"|'([^']*)'|(\S+))/g;
        let match;
        
        while ((match = attributeRegex.exec(attributesString)) !== null) {
            const [, name, doubleQuoted, singleQuoted, unquoted] = match;
            const value = doubleQuoted || singleQuoted || unquoted;
            
            // Try to parse as JSON for complex values
            try {
                attributes[name] = JSON.parse(value);
            } catch {
                attributes[name] = value;
            }
        }
        
        return attributes;
    }
    
    async processShortcodes(content) {
        // Process Hugo-style shortcodes: 
        const shortcodeRegex = /\{\{\<\s*(\w+)\s*([^>]*?)\s*\>\}\}/g;
        let processedContent = content;
        let match;
        
        while ((match = shortcodeRegex.exec(content)) !== null) {
            const [fullMatch, componentName, attributesString] = match;
            
            try {
                const replacement = await this.renderComponent(
                    componentName, 
                    attributesString, 
                    ''
                );
                processedContent = processedContent.replace(fullMatch, replacement);
            } catch (error) {
                console.error(`Error rendering shortcode '${componentName}':`, error);
                const errorPlaceholder = this.createErrorPlaceholder(componentName, error.message);
                processedContent = processedContent.replace(fullMatch, errorPlaceholder);
            }
        }
        
        return processedContent;
    }
    
    createComponentUtils() {
        return {
            escapeHtml: (text) => {
                const div = document.createElement('div');
                div.textContent = text;
                return div.innerHTML;
            },
            
            generateId: (prefix = 'comp') => {
                return `${prefix}-${Math.random().toString(36).substr(2, 9)}`;
            },
            
            parseMarkdown: async (markdown) => {
                if (this.renderer) {
                    return await this.renderer.render(markdown);
                }
                // Fallback to simple processing
                return markdown.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
                              .replace(/\*(.*?)\*/g, '<em>$1</em>');
            },
            
            loadTemplate: async (templateName) => {
                if (this.templateCache.has(templateName)) {
                    return this.templateCache.get(templateName);
                }
                
                // Load template from file system or cache
                try {
                    const template = await this.loadTemplateFile(templateName);
                    if (this.options.templateCache) {
                        this.templateCache.set(templateName, template);
                    }
                    return template;
                } catch (error) {
                    throw new Error(`Failed to load template '${templateName}': ${error.message}`);
                }
            }
        };
    }
    
    // Built-in component implementations
    createAlertComponent() {
        return ({ attributes, content, utils }) => {
            const { type = 'info', title, dismissible = false } = attributes;
            const id = utils.generateId('alert');
            
            const alertClass = `alert alert-${type}`;
            const dismissButton = dismissible ? 
                `<button type="button" class="alert-dismiss" onclick="document.getElementById('${id}').remove()">×</button>` : '';
            
            const titleHtml = title ? `<h4 class="alert-title">${utils.escapeHtml(title)}</h4>` : '';
            
            return `
                <div id="${id}" class="${alertClass}" role="alert">
                    ${dismissButton}
                    ${titleHtml}
                    <div class="alert-content">${content}</div>
                </div>
            `;
        };
    }
    
    createTabsComponent() {
        return ({ attributes, content, utils }) => {
            const { defaultTab = 0 } = attributes;
            const tabsId = utils.generateId('tabs');
            
            // Parse tab content
            const tabSections = content.split(/^##\s+(.+)$/m);
            const tabs = [];
            
            for (let i = 1; i < tabSections.length; i += 2) {
                tabs.push({
                    title: tabSections[i].trim(),
                    content: tabSections[i + 1] ? tabSections[i + 1].trim() : ''
                });
            }
            
            if (tabs.length === 0) {
                return '<div class="alert alert-warning">No tabs defined</div>';
            }
            
            // Generate tab navigation
            const tabNavigation = tabs.map((tab, index) => 
                `<button class="tab-button ${index === defaultTab ? 'active' : ''}" 
                         onclick="showTab('${tabsId}', ${index})" 
                         data-tab="${index}">
                    ${utils.escapeHtml(tab.title)}
                </button>`
            ).join('');
            
            // Generate tab content
            const tabContent = tabs.map((tab, index) => 
                `<div class="tab-content ${index === defaultTab ? 'active' : ''}" 
                      data-tab="${index}">
                    ${tab.content}
                </div>`
            ).join('');
            
            return `
                <div class="tabs-container" id="${tabsId}">
                    <div class="tab-navigation">
                        ${tabNavigation}
                    </div>
                    <div class="tab-content-container">
                        ${tabContent}
                    </div>
                </div>
                
                <script>
                function showTab(containerId, tabIndex) {
                    const container = document.getElementById(containerId);
                    const buttons = container.querySelectorAll('.tab-button');
                    const contents = container.querySelectorAll('.tab-content');
                    
                    buttons.forEach(btn => btn.classList.remove('active'));
                    contents.forEach(content => content.classList.remove('active'));
                    
                    buttons[tabIndex].classList.add('active');
                    contents[tabIndex].classList.add('active');
                }
                </script>
            `;
        };
    }
    
    createAccordionComponent() {
        return ({ attributes, content, utils }) => {
            const { allowMultiple = false, defaultOpen } = attributes;
            const accordionId = utils.generateId('accordion');
            
            // Parse accordion sections
            const sections = content.split(/^###\s+(.+)$/m);
            const accordionItems = [];
            
            for (let i = 1; i < sections.length; i += 2) {
                accordionItems.push({
                    title: sections[i].trim(),
                    content: sections[i + 1] ? sections[i + 1].trim() : ''
                });
            }
            
            if (accordionItems.length === 0) {
                return '<div class="alert alert-warning">No accordion items defined</div>';
            }
            
            const accordionHtml = accordionItems.map((item, index) => {
                const itemId = `${accordionId}-item-${index}`;
                const isOpen = defaultOpen === index || (Array.isArray(defaultOpen) && defaultOpen.includes(index));
                
                return `
                    <div class="accordion-item">
                        <h3 class="accordion-header">
                            <button class="accordion-button ${isOpen ? 'active' : ''}" 
                                    onclick="toggleAccordion('${accordionId}', ${index}, ${allowMultiple})"
                                    aria-expanded="${isOpen}">
                                ${utils.escapeHtml(item.title)}
                                <span class="accordion-icon">${isOpen ? '' : '+'}</span>
                            </button>
                        </h3>
                        <div class="accordion-content ${isOpen ? 'active' : ''}" id="${itemId}">
                            <div class="accordion-body">
                                ${item.content}
                            </div>
                        </div>
                    </div>
                `;
            }).join('');
            
            return `
                <div class="accordion" id="${accordionId}">
                    ${accordionHtml}
                </div>
                
                <script>
                function toggleAccordion(accordionId, itemIndex, allowMultiple) {
                    const accordion = document.getElementById(accordionId);
                    const items = accordion.querySelectorAll('.accordion-item');
                    const currentItem = items[itemIndex];
                    const button = currentItem.querySelector('.accordion-button');
                    const content = currentItem.querySelector('.accordion-content');
                    const icon = button.querySelector('.accordion-icon');
                    
                    const isActive = content.classList.contains('active');
                    
                    if (!allowMultiple) {
                        // Close all other items
                        items.forEach((item, index) => {
                            if (index !== itemIndex) {
                                item.querySelector('.accordion-button').classList.remove('active');
                                item.querySelector('.accordion-content').classList.remove('active');
                                item.querySelector('.accordion-icon').textContent = '+';
                                item.querySelector('.accordion-button').setAttribute('aria-expanded', 'false');
                            }
                        });
                    }
                    
                    // Toggle current item
                    if (isActive) {
                        button.classList.remove('active');
                        content.classList.remove('active');
                        icon.textContent = '+';
                        button.setAttribute('aria-expanded', 'false');
                    } else {
                        button.classList.add('active');
                        content.classList.add('active');
                        icon.textContent = '−';
                        button.setAttribute('aria-expanded', 'true');
                    }
                }
                </script>
            `;
        };
    }
    
    createCodeExampleComponent() {
        return ({ attributes, content, utils }) => {
            const { 
                language = 'javascript', 
                title, 
                showLineNumbers = true,
                highlightLines,
                editable = false,
                runnable = false
            } = attributes;
            
            const exampleId = utils.generateId('code-example');
            const lineNumbers = showLineNumbers ? 'line-numbers' : '';
            
            let codeContent = content;
            if (highlightLines) {
                const linesToHighlight = highlightLines.split(',').map(n => parseInt(n.trim()));
                // Implementation would add highlighting markup
            }
            
            const titleHtml = title ? 
                `<div class="code-example-title">${utils.escapeHtml(title)}</div>` : '';
            
            const editableHtml = editable ? 
                `<button class="code-edit-btn" onclick="makeEditable('${exampleId}')">Edit</button>` : '';
                
            const runnableHtml = runnable ? 
                `<button class="code-run-btn" onclick="runCode('${exampleId}')">Run</button>` : '';
            
            return `
                <div class="code-example" id="${exampleId}">
                    ${titleHtml}
                    <div class="code-example-header">
                        <span class="code-language">${language}</span>
                        <div class="code-actions">
                            ${editableHtml}
                            ${runnableHtml}
                            <button class="code-copy-btn" onclick="copyCode('${exampleId}')">Copy</button>
                        </div>
                    </div>
                    <pre class="code-content ${lineNumbers}"><code class="language-${language}">${utils.escapeHtml(codeContent)}</code></pre>
                    ${runnable ? '<div class="code-output" id="' + exampleId + '-output"></div>' : ''}
                </div>
                
                <script>
                function copyCode(exampleId) {
                    const codeElement = document.querySelector('#' + exampleId + ' code');
                    navigator.clipboard.writeText(codeElement.textContent);
                    
                    const btn = document.querySelector('#' + exampleId + ' .code-copy-btn');
                    const originalText = btn.textContent;
                    btn.textContent = 'Copied!';
                    setTimeout(() => btn.textContent = originalText, 2000);
                }
                
                function makeEditable(exampleId) {
                    const codeElement = document.querySelector('#' + exampleId + ' code');
                    const pre = codeElement.parentElement;
                    
                    const textarea = document.createElement('textarea');
                    textarea.value = codeElement.textContent;
                    textarea.className = 'code-editor';
                    
                    pre.parentElement.replaceChild(textarea, pre);
                }
                
                function runCode(exampleId) {
                    const codeElement = document.querySelector('#' + exampleId + ' code, #' + exampleId + ' .code-editor');
                    const outputElement = document.getElementById(exampleId + '-output');
                    
                    try {
                        // Simple JavaScript execution (extend for other languages)
                        const result = new Function(codeElement.value || codeElement.textContent)();
                        outputElement.innerHTML = '<div class="output-success">Output: ' + JSON.stringify(result) + '</div>';
                    } catch (error) {
                        outputElement.innerHTML = '<div class="output-error">Error: ' + error.message + '</div>';
                    }
                }
                </script>
            `;
        };
    }
    
    createApiReferenceComponent() {
        return async ({ attributes, content, utils }) => {
            const { endpoint, method = 'GET', baseUrl } = attributes;
            
            if (!endpoint) {
                return '<div class="alert alert-error">API Reference requires endpoint attribute</div>';
            }
            
            // Parse API documentation from content
            const sections = this.parseApiContent(content);
            const referenceId = utils.generateId('api-ref');
            
            return `
                <div class="api-reference" id="${referenceId}">
                    <div class="api-header">
                        <span class="api-method method-${method.toLowerCase()}">${method}</span>
                        <span class="api-endpoint">${baseUrl || ''}${endpoint}</span>
                    </div>
                    
                    ${sections.description ? `<div class="api-description">${sections.description}</div>` : ''}
                    
                    ${sections.parameters ? `
                        <div class="api-section">
                            <h4>Parameters</h4>
                            ${sections.parameters}
                        </div>
                    ` : ''}
                    
                    ${sections.examples ? `
                        <div class="api-section">
                            <h4>Examples</h4>
                            ${sections.examples}
                        </div>
                    ` : ''}
                    
                    ${sections.responses ? `
                        <div class="api-section">
                            <h4>Responses</h4>
                            ${sections.responses}
                        </div>
                    ` : ''}
                </div>
            `;
        };
    }
    
    createFeatureMatrixComponent() {
        return ({ attributes, content, utils }) => {
            const { features, products } = attributes;
            
            if (!features || !products) {
                return '<div class="alert alert-error">Feature Matrix requires features and products attributes</div>';
            }
            
            const featureList = Array.isArray(features) ? features : features.split(',');
            const productList = Array.isArray(products) ? products : products.split(',');
            
            // Parse feature data from content
            const featureData = this.parseFeatureMatrix(content);
            const matrixId = utils.generateId('feature-matrix');
            
            const headerRow = `
                <tr>
                    <th>Feature</th>
                    ${productList.map(product => `<th>${utils.escapeHtml(product.trim())}</th>`).join('')}
                </tr>
            `;
            
            const featureRows = featureList.map(feature => {
                const featureName = feature.trim();
                const featureInfo = featureData[featureName] || {};
                
                return `
                    <tr>
                        <td class="feature-name">${utils.escapeHtml(featureName)}</td>
                        ${productList.map(product => {
                            const productName = product.trim();
                            const support = featureInfo[productName] || 'unknown';
                            const supportClass = this.getSupportClass(support);
                            const supportIcon = this.getSupportIcon(support);
                            
                            return `<td class="support-cell ${supportClass}" title="${support}">
                                ${supportIcon}
                            </td>`;
                        }).join('')}
                    </tr>
                `;
            }).join('');
            
            return `
                <div class="feature-matrix" id="${matrixId}">
                    <table class="feature-table">
                        <thead>${headerRow}</thead>
                        <tbody>${featureRows}</tbody>
                    </table>
                </div>
            `;
        };
    }
    
    parseApiContent(content) {
        const sections = {};
        const lines = content.split('\n');
        let currentSection = null;
        let currentContent = [];
        
        for (const line of lines) {
            if (line.startsWith('### ')) {
                if (currentSection) {
                    sections[currentSection] = currentContent.join('\n');
                }
                currentSection = line.substring(4).toLowerCase().trim();
                currentContent = [];
            } else {
                currentContent.push(line);
            }
        }
        
        if (currentSection) {
            sections[currentSection] = currentContent.join('\n');
        }
        
        return sections;
    }
    
    parseFeatureMatrix(content) {
        const data = {};
        const lines = content.split('\n');
        
        for (const line of lines) {
            const match = line.match(/^(\w+):\s*(.+)$/);
            if (match) {
                const [, feature, supportData] = match;
                const products = {};
                
                const pairs = supportData.split(',');
                for (const pair of pairs) {
                    const [product, support] = pair.split('=');
                    if (product && support) {
                        products[product.trim()] = support.trim();
                    }
                }
                
                data[feature] = products;
            }
        }
        
        return data;
    }
    
    getSupportClass(support) {
        const supportLower = support.toLowerCase();
        if (supportLower === 'full' || supportLower === 'yes') return 'support-full';
        if (supportLower === 'partial') return 'support-partial';
        if (supportLower === 'no' || supportLower === 'none') return 'support-none';
        return 'support-unknown';
    }
    
    getSupportIcon(support) {
        const supportLower = support.toLowerCase();
        if (supportLower === 'full' || supportLower === 'yes') return '';
        if (supportLower === 'partial') return '';
        if (supportLower === 'no' || supportLower === 'none') return '';
        return '?';
    }
    
    generateCacheKey(componentName, attributes, content) {
        const data = JSON.stringify({ componentName, attributes, content });
        return btoa(data).substring(0, 32);
    }
    
    createErrorPlaceholder(componentName, errorMessage) {
        return `
            <div class="component-error">
                <h4>Component Error: ${componentName}</h4>
                <p>${errorMessage}</p>
                <details>
                    <summary>Debug Information</summary>
                    <pre>Component: ${componentName}
Error: ${errorMessage}
Timestamp: ${new Date().toISOString()}</pre>
                </details>
            </div>
        `;
    }
    
    async loadTemplateFile(templateName) {
        // Implementation would load from file system
        // For browser environment, could fetch from server
        throw new Error('Template loading not implemented');
    }
    
    setContext(key, value) {
        this.context[key] = value;
    }
    
    setRenderer(renderer) {
        this.renderer = renderer;
    }
}

// CSS for component styling
const componentStyles = `
/* Alert Component Styles */
.alert {
    padding: 1rem;
    margin: 1rem 0;
    border-radius: 4px;
    border: 1px solid;
    position: relative;
}

.alert-info {
    color: #0c5460;
    background-color: #d1ecf1;
    border-color: #b8daff;
}

.alert-warning {
    color: #856404;
    background-color: #fff3cd;
    border-color: #ffeaa7;
}

.alert-error {
    color: #721c24;
    background-color: #f8d7da;
    border-color: #f5c6cb;
}

.alert-dismiss {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    background: none;
    border: none;
    font-size: 1.2rem;
    cursor: pointer;
}

.alert-title {
    margin-top: 0;
    margin-bottom: 0.5rem;
    font-weight: 600;
}

/* Tabs Component Styles */
.tabs-container {
    border: 1px solid #dee2e6;
    border-radius: 4px;
    margin: 1rem 0;
}

.tab-navigation {
    display: flex;
    background-color: #f8f9fa;
    border-bottom: 1px solid #dee2e6;
}

.tab-button {
    padding: 0.75rem 1rem;
    background: none;
    border: none;
    border-right: 1px solid #dee2e6;
    cursor: pointer;
    transition: background-color 0.2s;
}

.tab-button:hover {
    background-color: #e9ecef;
}

.tab-button.active {
    background-color: white;
    font-weight: 600;
    border-bottom: 1px solid white;
    margin-bottom: -1px;
}

.tab-content-container {
    background-color: white;
}

.tab-content {
    display: none;
    padding: 1rem;
}

.tab-content.active {
    display: block;
}

/* Accordion Component Styles */
.accordion {
    border: 1px solid #dee2e6;
    border-radius: 4px;
    margin: 1rem 0;
}

.accordion-item {
    border-bottom: 1px solid #dee2e6;
}

.accordion-item:last-child {
    border-bottom: none;
}

.accordion-button {
    width: 100%;
    padding: 1rem;
    background: #f8f9fa;
    border: none;
    text-align: left;
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-weight: 500;
    transition: background-color 0.2s;
}

.accordion-button:hover {
    background: #e9ecef;
}

.accordion-button.active {
    background: white;
}

.accordion-content {
    display: none;
    background: white;
}

.accordion-content.active {
    display: block;
}

.accordion-body {
    padding: 1rem;
}

.accordion-icon {
    font-weight: bold;
    font-size: 1.2rem;
}

/* Code Example Component Styles */
.code-example {
    margin: 1rem 0;
    border: 1px solid #dee2e6;
    border-radius: 4px;
    overflow: hidden;
}

.code-example-title {
    padding: 0.5rem 1rem;
    background: #f8f9fa;
    border-bottom: 1px solid #dee2e6;
    font-weight: 600;
}

.code-example-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.5rem 1rem;
    background: #f8f9fa;
    border-bottom: 1px solid #dee2e6;
}

.code-language {
    font-size: 0.875rem;
    color: #6c757d;
    text-transform: uppercase;
}

.code-actions {
    display: flex;
    gap: 0.5rem;
}

.code-actions button {
    padding: 0.25rem 0.5rem;
    background: #007bff;
    color: white;
    border: none;
    border-radius: 3px;
    cursor: pointer;
    font-size: 0.75rem;
}

.code-actions button:hover {
    background: #0056b3;
}

.code-content {
    margin: 0;
    padding: 1rem;
    background: #f8f9fa;
    overflow-x: auto;
}

.code-editor {
    width: 100%;
    min-height: 200px;
    padding: 1rem;
    font-family: 'Courier New', monospace;
    border: none;
    background: #f8f9fa;
    resize: vertical;
}

.code-output {
    padding: 1rem;
    background: #ffffff;
    border-top: 1px solid #dee2e6;
}

.output-success {
    color: #155724;
    background-color: #d4edda;
    border: 1px solid #c3e6cb;
    padding: 0.5rem;
    border-radius: 3px;
}

.output-error {
    color: #721c24;
    background-color: #f8d7da;
    border: 1px solid #f5c6cb;
    padding: 0.5rem;
    border-radius: 3px;
}

/* API Reference Component Styles */
.api-reference {
    margin: 1rem 0;
    border: 1px solid #dee2e6;
    border-radius: 4px;
    overflow: hidden;
}

.api-header {
    padding: 1rem;
    background: #f8f9fa;
    border-bottom: 1px solid #dee2e6;
    display: flex;
    align-items: center;
    gap: 1rem;
}

.api-method {
    padding: 0.25rem 0.5rem;
    border-radius: 3px;
    font-weight: bold;
    font-size: 0.875rem;
    text-transform: uppercase;
}

.method-get { background: #28a745; color: white; }
.method-post { background: #007bff; color: white; }
.method-put { background: #ffc107; color: black; }
.method-delete { background: #dc3545; color: white; }

.api-endpoint {
    font-family: 'Courier New', monospace;
    background: white;
    padding: 0.25rem 0.5rem;
    border-radius: 3px;
    border: 1px solid #dee2e6;
}

.api-section {
    padding: 1rem;
    border-bottom: 1px solid #dee2e6;
}

.api-section:last-child {
    border-bottom: none;
}

.api-section h4 {
    margin-top: 0;
    margin-bottom: 0.5rem;
    color: #495057;
}

/* Feature Matrix Component Styles */
.feature-matrix {
    margin: 1rem 0;
    overflow-x: auto;
}

.feature-table {
    width: 100%;
    border-collapse: collapse;
    border: 1px solid #dee2e6;
}

.feature-table th,
.feature-table td {
    padding: 0.75rem;
    border: 1px solid #dee2e6;
    text-align: left;
}

.feature-table th {
    background: #f8f9fa;
    font-weight: 600;
}

.feature-name {
    font-weight: 500;
}

.support-cell {
    text-align: center;
    font-weight: bold;
}

.support-full { color: #28a745; }
.support-partial { color: #ffc107; }
.support-none { color: #dc3545; }
.support-unknown { color: #6c757d; }

/* Error Component Styles */
.component-error {
    padding: 1rem;
    margin: 1rem 0;
    background: #f8d7da;
    border: 1px solid #f5c6cb;
    border-radius: 4px;
    color: #721c24;
}

.component-error h4 {
    margin-top: 0;
    margin-bottom: 0.5rem;
}

.component-error details {
    margin-top: 0.5rem;
}

.component-error pre {
    background: rgba(0,0,0,0.1);
    padding: 0.5rem;
    border-radius: 3px;
    font-size: 0.875rem;
}
`;

module.exports = { MarkdownComponentSystem, componentStyles };

Advanced Template System Integration

Creating sophisticated templating systems for dynamic content generation:

# markdown_templates.py - Advanced templating system for Markdown components
import re
import json
import yaml
from pathlib import Path
from typing import Dict, Any, List, Optional, Callable
from dataclasses import dataclass
from datetime import datetime
import asyncio
import aiohttp

@dataclass
class ComponentTemplate:
    name: str
    template: str
    schema: Dict[str, Any]
    async_data: bool = False
    cache_ttl: int = 3600
    
class AdvancedTemplateSystem:
    def __init__(self, template_dir: str = "templates", data_sources: Dict = None):
        self.template_dir = Path(template_dir)
        self.templates: Dict[str, ComponentTemplate] = {}
        self.data_sources = data_sources or {}
        self.template_cache = {}
        self.data_cache = {}
        self.template_functions = {
            'now': lambda: datetime.now().isoformat(),
            'format_date': self.format_date,
            'fetch_data': self.fetch_data,
            'render_partial': self.render_partial,
            'include': self.include_template,
            'loop': self.loop_helper,
            'condition': self.condition_helper
        }
        
        self.load_templates()
    
    def load_templates(self):
        """Load all templates from the template directory"""
        if not self.template_dir.exists():
            self.template_dir.mkdir(parents=True)
            return
        
        for template_file in self.template_dir.glob("*.md"):
            self.load_template_file(template_file)
        
        for template_file in self.template_dir.glob("*.html"):
            self.load_template_file(template_file)
    
    def load_template_file(self, file_path: Path):
        """Load a single template file with metadata"""
        content = file_path.read_text(encoding='utf-8')
        
        # Extract template metadata from frontmatter
        frontmatter_match = re.match(r'^---\n(.*?)\n---\n(.*)$', content, re.DOTALL)
        
        if frontmatter_match:
            metadata_str, template_content = frontmatter_match.groups()
            try:
                metadata = yaml.safe_load(metadata_str)
            except yaml.YAMLError:
                metadata = {}
            
            template_name = metadata.get('name', file_path.stem)
            
            template = ComponentTemplate(
                name=template_name,
                template=template_content,
                schema=metadata.get('schema', {}),
                async_data=metadata.get('async_data', False),
                cache_ttl=metadata.get('cache_ttl', 3600)
            )
            
            self.templates[template_name] = template
            print(f"✅ Loaded template: {template_name}")
        else:
            # No frontmatter, use filename as template name
            template_name = file_path.stem
            template = ComponentTemplate(
                name=template_name,
                template=content,
                schema={}
            )
            
            self.templates[template_name] = template
    
    async def render_component(self, component_name: str, attributes: Dict[str, Any], 
                              content: str = "", context: Dict[str, Any] = None) -> str:
        """Render a component using the template system"""
        if component_name not in self.templates:
            raise ValueError(f"Unknown template: {component_name}")
        
        template = self.templates[component_name]
        
        # Validate attributes against schema
        if template.schema:
            validation_errors = self.validate_attributes(attributes, template.schema)
            if validation_errors:
                raise ValueError(f"Validation errors: {', '.join(validation_errors)}")
        
        # Prepare template context
        template_context = {
            'attributes': attributes,
            'content': content,
            'context': context or {},
            'functions': self.template_functions,
            'template_name': component_name
        }
        
        # Fetch async data if needed
        if template.async_data:
            async_data = await self.fetch_async_data(component_name, attributes)
            template_context['data'] = async_data
        
        # Render template
        rendered = await self.process_template(template.template, template_context)
        
        return rendered
    
    def validate_attributes(self, attributes: Dict[str, Any], schema: Dict[str, Any]) -> List[str]:
        """Validate component attributes against schema"""
        errors = []
        
        required_fields = schema.get('required', [])
        for field in required_fields:
            if field not in attributes:
                errors.append(f"Required field '{field}' is missing")
        
        properties = schema.get('properties', {})
        for attr_name, attr_value in attributes.items():
            if attr_name in properties:
                property_schema = properties[attr_name]
                validation_error = self.validate_property(attr_name, attr_value, property_schema)
                if validation_error:
                    errors.append(validation_error)
        
        return errors
    
    def validate_property(self, name: str, value: Any, schema: Dict[str, Any]) -> Optional[str]:
        """Validate a single property against its schema"""
        expected_type = schema.get('type')
        
        if expected_type == 'string' and not isinstance(value, str):
            return f"Property '{name}' must be a string"
        elif expected_type == 'number' and not isinstance(value, (int, float)):
            return f"Property '{name}' must be a number"
        elif expected_type == 'boolean' and not isinstance(value, bool):
            return f"Property '{name}' must be a boolean"
        elif expected_type == 'array' and not isinstance(value, list):
            return f"Property '{name}' must be an array"
        
        # Check enum values
        if 'enum' in schema and value not in schema['enum']:
            return f"Property '{name}' must be one of: {', '.join(map(str, schema['enum']))}"
        
        # Check string patterns
        if expected_type == 'string' and 'pattern' in schema:
            if not re.match(schema['pattern'], value):
                return f"Property '{name}' does not match required pattern"
        
        return None
    
    async def fetch_async_data(self, component_name: str, attributes: Dict[str, Any]) -> Dict[str, Any]:
        """Fetch asynchronous data for a component"""
        cache_key = f"{component_name}_{hash(str(attributes))}"
        
        if cache_key in self.data_cache:
            cached_data, cache_time = self.data_cache[cache_key]
            if datetime.now().timestamp() - cache_time < self.templates[component_name].cache_ttl:
                return cached_data
        
        # Fetch data from configured sources
        data = {}
        
        if 'api_endpoint' in attributes:
            try:
                async with aiohttp.ClientSession() as session:
                    async with session.get(attributes['api_endpoint']) as response:
                        if response.status == 200:
                            api_data = await response.json()
                            data['api'] = api_data
            except Exception as e:
                print(f"Failed to fetch API data: {e}")
                data['api'] = {'error': str(e)}
        
        if 'data_source' in attributes:
            source_name = attributes['data_source']
            if source_name in self.data_sources:
                try:
                    source_data = await self.data_sources[source_name](attributes)
                    data['source'] = source_data
                except Exception as e:
                    print(f"Failed to fetch source data: {e}")
                    data['source'] = {'error': str(e)}
        
        # Cache the data
        self.data_cache[cache_key] = (data, datetime.now().timestamp())
        
        return data
    
    async def process_template(self, template: str, context: Dict[str, Any]) -> str:
        """Process template with advanced templating features"""
        # Replace simple variables
        processed = template
        
        # Process {{ variable }} expressions
        var_pattern = r'\{\{\s*([^}]+)\s*\}\}'
        
        def replace_variable(match):
            expression = match.group(1).strip()
            try:
                return str(self.evaluate_expression(expression, context))
            except Exception as e:
                return f"{{{{ ERROR: {e} }}}}"
        
        processed = re.sub(var_pattern, replace_variable, processed)
        
        # Process {% control %} blocks
        processed = await self.process_control_blocks(processed, context)
        
        return processed
    
    def evaluate_expression(self, expression: str, context: Dict[str, Any]) -> Any:
        """Safely evaluate template expressions"""
        # Simple dot notation support
        parts = expression.split('.')
        value = context
        
        try:
            for part in parts:
                if '[' in part and ']' in part:
                    # Handle array/object access like items[0] or obj['key']
                    key_match = re.match(r'(\w+)\[([^\]]+)\]', part)
                    if key_match:
                        obj_name, key = key_match.groups()
                        value = value[obj_name]
                        
                        # Try as integer index first, then as string key
                        try:
                            key = int(key.strip('"\''))
                        except ValueError:
                            key = key.strip('"\'')
                        
                        value = value[key]
                    else:
                        value = value[part]
                elif '(' in part and ')' in part:
                    # Function call
                    func_match = re.match(r'(\w+)\((.*?)\)', part)
                    if func_match:
                        func_name, args_str = func_match.groups()
                        
                        if func_name in context.get('functions', {}):
                            func = context['functions'][func_name]
                            
                            # Parse arguments
                            args = []
                            if args_str.strip():
                                # Simple argument parsing
                                for arg in args_str.split(','):
                                    arg = arg.strip().strip('"\'')
                                    args.append(arg)
                            
                            return func(*args)
                        else:
                            return f"Function {func_name} not found"
                    else:
                        value = value[part]
                else:
                    value = value[part]
            
            return value
            
        except (KeyError, TypeError, IndexError) as e:
            return f"Error accessing {expression}: {e}"
    
    async def process_control_blocks(self, template: str, context: Dict[str, Any]) -> str:
        """Process control blocks like {% if %}, {% for %}, etc."""
        processed = template
        
        # Process {% if %} blocks
        if_pattern = r'\{\%\s*if\s+(.+?)\s*\%\}(.*?)\{\%\s*endif\s*\%\}'
        
        def process_if(match):
            condition, content = match.groups()
            try:
                if self.evaluate_condition(condition, context):
                    return content
                else:
                    return ''
            except Exception as e:
                return f"Error in if condition: {e}"
        
        processed = re.sub(if_pattern, process_if, processed, flags=re.DOTALL)
        
        # Process {% for %} blocks
        for_pattern = r'\{\%\s*for\s+(\w+)\s+in\s+(.+?)\s*\%\}(.*?)\{\%\s*endfor\s*\%\}'
        
        def process_for(match):
            var_name, iterable_expr, content = match.groups()
            try:
                iterable = self.evaluate_expression(iterable_expr, context)
                if not hasattr(iterable, '__iter__'):
                    return f"Error: {iterable_expr} is not iterable"
                
                result = []
                for item in iterable:
                    item_context = context.copy()
                    item_context[var_name] = item
                    item_content = content
                    
                    # Process nested variables in the loop content
                    var_pattern = r'\{\{\s*([^}]+)\s*\}\}'
                    
                    def replace_loop_var(inner_match):
                        expression = inner_match.group(1).strip()
                        try:
                            return str(self.evaluate_expression(expression, item_context))
                        except Exception as e:
                            return f"{{{{ ERROR: {e} }}}}"
                    
                    item_content = re.sub(var_pattern, replace_loop_var, item_content)
                    result.append(item_content)
                
                return ''.join(result)
                
            except Exception as e:
                return f"Error in for loop: {e}"
        
        processed = re.sub(for_pattern, process_for, processed, flags=re.DOTALL)
        
        return processed
    
    def evaluate_condition(self, condition: str, context: Dict[str, Any]) -> bool:
        """Evaluate conditional expressions"""
        # Simple condition evaluation
        condition = condition.strip()
        
        # Handle negation
        negated = False
        if condition.startswith('not '):
            negated = True
            condition = condition[4:].strip()
        
        # Handle comparison operators
        for op in ['==', '!=', '>', '<', '>=', '<=']:
            if op in condition:
                left, right = condition.split(op, 1)
                left_val = self.evaluate_expression(left.strip(), context)
                right_val = self.evaluate_expression(right.strip(), context)
                
                if op == '==':
                    result = left_val == right_val
                elif op == '!=':
                    result = left_val != right_val
                elif op == '>':
                    result = float(left_val) > float(right_val)
                elif op == '<':
                    result = float(left_val) < float(right_val)
                elif op == '>=':
                    result = float(left_val) >= float(right_val)
                elif op == '<=':
                    result = float(left_val) <= float(right_val)
                
                return not result if negated else result
        
        # Simple truthiness check
        value = self.evaluate_expression(condition, context)
        result = bool(value)
        
        return not result if negated else result
    
    # Template helper functions
    def format_date(self, date_str: str, format_str: str = "%Y-%m-%d") -> str:
        """Format date string"""
        try:
            if isinstance(date_str, str):
                date_obj = datetime.fromisoformat(date_str.replace('Z', '+00:00'))
            else:
                date_obj = date_str
            return date_obj.strftime(format_str)
        except Exception:
            return str(date_str)
    
    async def fetch_data(self, url: str) -> Dict[str, Any]:
        """Fetch data from URL"""
        try:
            async with aiohttp.ClientSession() as session:
                async with session.get(url) as response:
                    if response.status == 200:
                        return await response.json()
                    else:
                        return {'error': f'HTTP {response.status}'}
        except Exception as e:
            return {'error': str(e)}
    
    def render_partial(self, template_name: str, context: Dict[str, Any]) -> str:
        """Render a partial template"""
        if template_name not in self.templates:
            return f"Partial template '{template_name}' not found"
        
        try:
            return asyncio.run(self.process_template(
                self.templates[template_name].template, 
                context
            ))
        except Exception as e:
            return f"Error rendering partial: {e}"
    
    def include_template(self, template_name: str) -> str:
        """Include another template"""
        if template_name not in self.templates:
            return f"Template '{template_name}' not found"
        
        return self.templates[template_name].template
    
    def loop_helper(self, items: List[Any], template: str) -> str:
        """Loop helper for templates"""
        result = []
        for item in items:
            # Simple template processing for loop items
            processed = template.replace('{{ item }}', str(item))
            result.append(processed)
        return ''.join(result)
    
    def condition_helper(self, condition: bool, true_content: str, false_content: str = "") -> str:
        """Condition helper for templates"""
        return true_content if condition else false_content
    
    def register_data_source(self, name: str, source_func: Callable):
        """Register a custom data source"""
        self.data_sources[name] = source_func
    
    def register_template_function(self, name: str, func: Callable):
        """Register a custom template function"""
        self.template_functions[name] = func
    
    def get_template_names(self) -> List[str]:
        """Get list of available template names"""
        return list(self.templates.keys())
    
    def reload_templates(self):
        """Reload all templates from disk"""
        self.templates.clear()
        self.template_cache.clear()
        self.load_templates()

# Example template files that would be created

# templates/github-stats.md
github_stats_template = """---
name: github-stats
schema:
  required: [repo, owner]
  properties:
    repo:
      type: string
    owner:
      type: string
    token:
      type: string
async_data: true
cache_ttl: 1800
---
<div class="github-stats">
  <h3>📊 GitHub Repository Stats</h3>
  
  {% if data.api %}
    <div class="stats-grid">
      <div class="stat-item">
        <div class="stat-value">{{ data.api.stargazers_count }}</div>
        <div class="stat-label">Stars</div>
      </div>
      <div class="stat-item">
        <div class="stat-value">{{ data.api.forks_count }}</div>
        <div class="stat-label">Forks</div>
      </div>
      <div class="stat-item">
        <div class="stat-value">{{ data.api.open_issues_count }}</div>
        <div class="stat-label">Issues</div>
      </div>
      <div class="stat-item">
        <div class="stat-value">{{ functions.format_date(data.api.updated_at, "%Y-%m-%d") }}</div>
        <div class="stat-label">Last Updated</div>
      </div>
    </div>
    
    {% if data.api.description %}
      <p class="repo-description">{{ data.api.description }}</p>
    {% endif %}
    
    <a href="{{ data.api.html_url }}" class="repo-link">View on GitHub</a>
  {% else %}
    <div class="error">Failed to load repository data</div>
  {% endif %}
</div>"""

# templates/blog-post-list.md
blog_post_list_template = """---
name: blog-post-list  
schema:
  properties:
    category:
      type: string
    limit:
      type: number
    sort:
      type: string
      enum: [date, title, popularity]
async_data: true
---
<div class="blog-post-list">
  {% if attributes.category %}
    <h3>{{ attributes.category }} Posts</h3>
  {% else %}
    <h3>Recent Blog Posts</h3>
  {% endif %}
  
  {% if data.source %}
    <div class="post-grid">
      {% for post in data.source.posts %}
        <article class="post-card">
          <h4><a href="{{ post.url }}">{{ post.title }}</a></h4>
          <div class="post-meta">
            <span class="post-date">{{ functions.format_date(post.date) }}</span>
            {% if post.author %}
              <span class="post-author">by {{ post.author }}</span>
            {% endif %}
          </div>
          {% if post.excerpt %}
            <p class="post-excerpt">{{ post.excerpt }}</p>
          {% endif %}
          <div class="post-tags">
            {% for tag in post.tags %}
              <span class="tag">{{ tag }}</span>
            {% endfor %}
          </div>
        </article>
      {% endfor %}
    </div>
  {% else %}
    <div class="error">No posts available</div>
  {% endif %}
</div>"""

# Usage example
async def main():
    # Initialize template system
    template_system = AdvancedTemplateSystem("templates")
    
    # Create example templates
    Path("templates").mkdir(exist_ok=True)
    Path("templates/github-stats.md").write_text(github_stats_template)
    Path("templates/blog-post-list.md").write_text(blog_post_list_template)
    
    # Reload templates
    template_system.reload_templates()
    
    # Register data sources
    async def fetch_github_data(attributes):
        repo = attributes['repo']
        owner = attributes['owner']
        token = attributes.get('token')
        
        headers = {}
        if token:
            headers['Authorization'] = f'token {token}'
        
        async with aiohttp.ClientSession() as session:
            async with session.get(
                f'https://api.github.com/repos/{owner}/{repo}',
                headers=headers
            ) as response:
                if response.status == 200:
                    return await response.json()
                else:
                    return {'error': f'GitHub API error: {response.status}'}
    
    template_system.register_data_source('github', fetch_github_data)
    
    # Example usage
    github_component = await template_system.render_component(
        'github-stats',
        {
            'repo': 'markdown-tools',
            'owner': 'example-org',
            'api_endpoint': 'https://api.github.com/repos/example-org/markdown-tools'
        }
    )
    
    print("Rendered GitHub Stats Component:")
    print(github_component)

if __name__ == '__main__':
    asyncio.run(main())

Interactive Component Development

Real-time Preview and Testing System

Building comprehensive development environments for component creation:

// component-dev-server.js - Development server for Markdown components
const express = require('express');
const WebSocket = require('ws');
const chokidar = require('chokidar');
const path = require('path');
const fs = require('fs').promises;
const { MarkdownComponentSystem } = require('./markdown-components');

class ComponentDevelopmentServer {
    constructor(options = {}) {
        this.options = {
            port: options.port || 3000,
            host: options.host || 'localhost',
            componentsDir: options.componentsDir || './components',
            templatesDir: options.templatesDir || './templates',
            examplesDir: options.examplesDir || './examples',
            hotReload: options.hotReload !== false,
            ...options
        };
        
        this.app = express();
        this.server = null;
        this.wss = null;
        this.componentSystem = new MarkdownComponentSystem();
        this.connections = new Set();
        
        this.setupServer();
        this.setupFileWatching();
    }
    
    setupServer() {
        this.app.use(express.static('public'));
        this.app.use(express.json());
        
        // Serve component development interface
        this.app.get('/', (req, res) => {
            res.send(this.generateDevelopmentUI());
        });
        
        // API endpoint to render components
        this.app.post('/api/render', async (req, res) => {
            try {
                const { componentName, attributes, content, markdown } = req.body;
                
                let result;
                if (markdown) {
                    result = await this.componentSystem.processContent(markdown);
                } else {
                    result = await this.componentSystem.renderComponent(
                        componentName, 
                        attributes, 
                        content
                    );
                }
                
                res.json({ success: true, html: result });
            } catch (error) {
                res.json({ success: false, error: error.message });
            }
        });
        
        // API endpoint to get component list
        this.app.get('/api/components', async (req, res) => {
            try {
                const components = Array.from(this.componentSystem.components.keys());
                const examples = await this.loadExamples();
                
                res.json({
                    components,
                    examples
                });
            } catch (error) {
                res.json({ error: error.message });
            }
        });
        
        // API endpoint to get component schema
        this.app.get('/api/components/:name/schema', (req, res) => {
            const componentName = req.params.name;
            const component = this.componentSystem.components.get(componentName);
            
            if (component) {
                res.json({ schema: component.schema || {} });
            } else {
                res.status(404).json({ error: 'Component not found' });
            }
        });
        
        // API endpoint to save component
        this.app.post('/api/components/:name', async (req, res) => {
            try {
                const componentName = req.params.name;
                const { code, schema } = req.body;
                
                await this.saveComponent(componentName, code, schema);
                
                res.json({ success: true });
            } catch (error) {
                res.json({ success: false, error: error.message });
            }
        });
    }
    
    async loadExamples() {
        const examples = {};
        
        try {
            const exampleFiles = await fs.readdir(this.options.examplesDir);
            
            for (const file of exampleFiles) {
                if (file.endsWith('.md')) {
                    const componentName = path.basename(file, '.md');
                    const exampleContent = await fs.readFile(
                        path.join(this.options.examplesDir, file), 
                        'utf8'
                    );
                    examples[componentName] = exampleContent;
                }
            }
        } catch (error) {
            console.warn('Could not load examples:', error.message);
        }
        
        return examples;
    }
    
    async saveComponent(name, code, schema) {
        const componentFile = path.join(this.options.componentsDir, `${name}.js`);
        
        const componentCode = `
// Generated component: ${name}
module.exports = function(componentSystem) {
    const component = ${code};
    
    componentSystem.registerComponent('${name}', component);
    
    // Schema definition
    component.schema = ${JSON.stringify(schema, null, 2)};
    
    return component;
};
`;
        
        await fs.mkdir(this.options.componentsDir, { recursive: true });
        await fs.writeFile(componentFile, componentCode);
        
        // Reload component system
        await this.reloadComponents();
    }
    
    async reloadComponents() {
        // Clear existing components
        this.componentSystem.components.clear();
        this.componentSystem.initializeBuiltinComponents();
        
        // Load custom components
        try {
            const componentFiles = await fs.readdir(this.options.componentsDir);
            
            for (const file of componentFiles) {
                if (file.endsWith('.js')) {
                    const componentPath = path.join(this.options.componentsDir, file);
                    
                    // Clear require cache
                    delete require.cache[require.resolve(componentPath)];
                    
                    // Load component
                    const componentLoader = require(componentPath);
                    componentLoader(this.componentSystem);
                }
            }
        } catch (error) {
            console.warn('Could not load custom components:', error.message);
        }
        
        // Notify connected clients
        this.broadcastReload();
    }
    
    setupFileWatching() {
        if (!this.options.hotReload) return;
        
        const watcher = chokidar.watch([
            this.options.componentsDir,
            this.options.templatesDir,
            this.options.examplesDir
        ], {
            ignored: /node_modules/,
            persistent: true
        });
        
        watcher.on('change', async () => {
            console.log('Files changed, reloading components...');
            await this.reloadComponents();
        });
        
        watcher.on('add', async () => {
            await this.reloadComponents();
        });
        
        watcher.on('unlink', async () => {
            await this.reloadComponents();
        });
    }
    
    generateDevelopmentUI() {
        return `
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Markdown Component Development Server</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            background: #f5f5f5;
        }
        
        .header {
            background: #2c3e50;
            color: white;
            padding: 1rem 2rem;
            display: flex;
            justify-content: between;
            align-items: center;
        }
        
        .container {
            display: grid;
            grid-template-columns: 300px 1fr 1fr;
            height: calc(100vh - 80px);
            gap: 1rem;
            padding: 1rem;
        }
        
        .sidebar {
            background: white;
            border-radius: 8px;
            padding: 1rem;
            overflow-y: auto;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        
        .editor-panel, .preview-panel {
            background: white;
            border-radius: 8px;
            display: flex;
            flex-direction: column;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        
        .panel-header {
            padding: 1rem;
            border-bottom: 1px solid #e0e0e0;
            font-weight: 600;
            display: flex;
            justify-content: between;
            align-items: center;
        }
        
        .panel-content {
            flex: 1;
            overflow-y: auto;
        }
        
        .component-list {
            list-style: none;
        }
        
        .component-item {
            padding: 0.5rem;
            margin: 0.25rem 0;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.2s;
        }
        
        .component-item:hover {
            background: #f0f0f0;
        }
        
        .component-item.active {
            background: #3498db;
            color: white;
        }
        
        .editor {
            font-family: 'Courier New', monospace;
            padding: 1rem;
            border: none;
            resize: none;
            outline: none;
            font-size: 14px;
            line-height: 1.5;
        }
        
        .preview-content {
            padding: 1rem;
        }
        
        .error {
            color: #e74c3c;
            background: #fdf2f2;
            padding: 1rem;
            border-radius: 4px;
            margin: 1rem;
        }
        
        .success {
            color: #27ae60;
            background: #f2fdf2;
            padding: 0.5rem;
            border-radius: 4px;
            margin: 0.5rem 0;
        }
        
        .toolbar {
            display: flex;
            gap: 0.5rem;
            padding: 0.5rem 1rem;
            background: #f8f9fa;
            border-bottom: 1px solid #e0e0e0;
        }
        
        .btn {
            padding: 0.5rem 1rem;
            background: #3498db;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 0.875rem;
        }
        
        .btn:hover {
            background: #2980b9;
        }
        
        .btn-secondary {
            background: #95a5a6;
        }
        
        .btn-secondary:hover {
            background: #7f8c8d;
        }
        
        .attribute-form {
            padding: 1rem;
            background: #f8f9fa;
        }
        
        .form-group {
            margin-bottom: 1rem;
        }
        
        .form-label {
            display: block;
            margin-bottom: 0.25rem;
            font-weight: 500;
            font-size: 0.875rem;
        }
        
        .form-input {
            width: 100%;
            padding: 0.5rem;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 0.875rem;
        }
        
        .loading {
            text-align: center;
            color: #666;
            padding: 2rem;
        }
        
        .status-indicator {
            display: inline-block;
            width: 8px;
            height: 8px;
            border-radius: 50%;
            margin-right: 0.5rem;
        }
        
        .status-connected { background: #27ae60; }
        .status-disconnected { background: #e74c3c; }
        
        .tabs {
            display: flex;
            background: #f8f9fa;
        }
        
        .tab {
            padding: 0.75rem 1rem;
            background: none;
            border: none;
            cursor: pointer;
            border-bottom: 2px solid transparent;
        }
        
        .tab.active {
            background: white;
            border-bottom-color: #3498db;
        }
        
        .tab-content {
            display: none;
        }
        
        .tab-content.active {
            display: block;
        }
        
        ${this.getComponentStyles()}
    </style>
</head>
<body>
    <header class="header">
        <h1>Markdown Component Development</h1>
        <div>
            <span class="status-indicator" id="connectionStatus"></span>
            <span id="connectionText">Connecting...</span>
        </div>
    </header>
    
    <div class="container">
        <aside class="sidebar">
            <h3>Components</h3>
            <ul class="component-list" id="componentList">
                <li class="loading">Loading components...</li>
            </ul>
            
            <div class="attribute-form" id="attributeForm" style="display: none;">
                <h4>Attributes</h4>
                <div id="attributeInputs"></div>
            </div>
        </aside>
        
        <div class="editor-panel">
            <div class="panel-header">
                <span>Editor</span>
                <div class="toolbar">
                    <button class="btn" onclick="renderPreview()">Render</button>
                    <button class="btn btn-secondary" onclick="loadExample()">Load Example</button>
                </div>
            </div>
            
            <div class="tabs">
                <button class="tab active" onclick="switchTab('markdown')">Markdown</button>
                <button class="tab" onclick="switchTab('component')">Component</button>
            </div>
            
            <div class="tab-content active" id="markdown-content">
                <textarea class="editor" id="markdownEditor" placeholder="Enter your Markdown with components here...">
# Example Markdown with Components

<md-alert type="info" title="Welcome">
This is an example of a custom Markdown component!
</md-alert>

<md-tabs defaultTab="0">
## First Tab
Content for the first tab goes here.

## Second Tab  
Content for the second tab goes here.
</md-tabs>
                </textarea>
            </div>
            
            <div class="tab-content" id="component-content">
                <textarea class="editor" id="componentEditor" placeholder="Component-specific content..."></textarea>
            </div>
        </div>
        
        <div class="preview-panel">
            <div class="panel-header">
                <span>Preview</span>
                <div class="toolbar">
                    <button class="btn btn-secondary" onclick="copyPreviewHTML()">Copy HTML</button>
                </div>
            </div>
            <div class="panel-content">
                <div class="preview-content" id="previewContent">
                    <div class="loading">Click "Render" to preview your components</div>
                </div>
            </div>
        </div>
    </div>
    
    <script>
        let ws = null;
        let currentComponent = null;
        let components = [];
        let examples = {};
        
        // Initialize WebSocket connection
        function initWebSocket() {
            const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
            ws = new WebSocket(\`\${protocol}//\${window.location.host}\`);
            
            ws.onopen = () => {
                updateConnectionStatus(true);
            };
            
            ws.onclose = () => {
                updateConnectionStatus(false);
                setTimeout(initWebSocket, 3000); // Reconnect after 3 seconds
            };
            
            ws.onmessage = (event) => {
                const data = JSON.parse(event.data);
                
                if (data.type === 'reload') {
                    loadComponents();
                    renderPreview();
                }
            };
        }
        
        function updateConnectionStatus(connected) {
            const indicator = document.getElementById('connectionStatus');
            const text = document.getElementById('connectionText');
            
            if (connected) {
                indicator.className = 'status-indicator status-connected';
                text.textContent = 'Connected';
            } else {
                indicator.className = 'status-indicator status-disconnected';
                text.textContent = 'Disconnected';
            }
        }
        
        // Load available components
        async function loadComponents() {
            try {
                const response = await fetch('/api/components');
                const data = await response.json();
                
                components = data.components || [];
                examples = data.examples || {};
                
                updateComponentList();
            } catch (error) {
                console.error('Failed to load components:', error);
            }
        }
        
        function updateComponentList() {
            const list = document.getElementById('componentList');
            
            if (components.length === 0) {
                list.innerHTML = '<li class="loading">No components found</li>';
                return;
            }
            
            list.innerHTML = components.map(name => 
                \`<li class="component-item" onclick="selectComponent('\${name}')">\${name}</li>\`
            ).join('');
        }
        
        function selectComponent(name) {
            currentComponent = name;
            
            // Update active state
            document.querySelectorAll('.component-item').forEach(item => {
                item.classList.remove('active');
                if (item.textContent === name) {
                    item.classList.add('active');
                }
            });
            
            // Load component schema and show attribute form
            loadComponentSchema(name);
            
            // Load example if available
            if (examples[name]) {
                document.getElementById('componentEditor').value = examples[name];
            }
        }
        
        async function loadComponentSchema(name) {
            try {
                const response = await fetch(\`/api/components/\${name}/schema\`);
                const data = await response.json();
                
                if (data.schema && data.schema.properties) {
                    showAttributeForm(data.schema);
                } else {
                    hideAttributeForm();
                }
            } catch (error) {
                console.error('Failed to load component schema:', error);
                hideAttributeForm();
            }
        }
        
        function showAttributeForm(schema) {
            const form = document.getElementById('attributeForm');
            const inputs = document.getElementById('attributeInputs');
            
            const properties = schema.properties || {};
            const required = schema.required || [];
            
            let formHTML = '';
            
            for (const [name, prop] of Object.entries(properties)) {
                const isRequired = required.includes(name);
                const label = isRequired ? \`\${name} *\` : name;
                
                formHTML += \`
                    <div class="form-group">
                        <label class="form-label">\${label}</label>
                        <input 
                            type="text" 
                            class="form-input" 
                            id="attr-\${name}"
                            placeholder="\${prop.description || ''}"
                            \${prop.default ? \`value="\${prop.default}"\` : ''}
                        >
                    </div>
                \`;
            }
            
            inputs.innerHTML = formHTML;
            form.style.display = 'block';
        }
        
        function hideAttributeForm() {
            document.getElementById('attributeForm').style.display = 'none';
        }
        
        async function renderPreview() {
            const previewContent = document.getElementById('previewContent');
            const markdownContent = document.getElementById('markdownEditor').value;
            
            previewContent.innerHTML = '<div class="loading">Rendering...</div>';
            
            try {
                const response = await fetch('/api/render', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        markdown: markdownContent
                    })
                });
                
                const result = await response.json();
                
                if (result.success) {
                    previewContent.innerHTML = result.html;
                } else {
                    previewContent.innerHTML = \`<div class="error">Error: \${result.error}</div>\`;
                }
            } catch (error) {
                previewContent.innerHTML = \`<div class="error">Network error: \${error.message}</div>\`;
            }
        }
        
        function loadExample() {
            if (currentComponent && examples[currentComponent]) {
                document.getElementById('markdownEditor').value = examples[currentComponent];
                renderPreview();
            }
        }
        
        function copyPreviewHTML() {
            const previewContent = document.getElementById('previewContent').innerHTML;
            navigator.clipboard.writeText(previewContent).then(() => {
                // Show success message
                const originalContent = previewContent;
                document.getElementById('previewContent').innerHTML = 
                    '<div class="success">HTML copied to clipboard!</div>' + originalContent;
                
                setTimeout(() => {
                    document.getElementById('previewContent').innerHTML = originalContent;
                }, 2000);
            });
        }
        
        function switchTab(tabName) {
            // Update tab buttons
            document.querySelectorAll('.tab').forEach(tab => tab.classList.remove('active'));
            event.target.classList.add('active');
            
            // Update tab content
            document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
            document.getElementById(\`\${tabName}-content\`).classList.add('active');
        }
        
        // Auto-render on input
        document.getElementById('markdownEditor').addEventListener('input', 
            debounce(renderPreview, 1000)
        );
        
        function debounce(func, wait) {
            let timeout;
            return function executedFunction(...args) {
                const later = () => {
                    clearTimeout(timeout);
                    func(...args);
                };
                clearTimeout(timeout);
                timeout = setTimeout(later, wait);
            };
        }
        
        // Initialize
        initWebSocket();
        loadComponents();
        renderPreview();
    </script>
</body>
</html>
        `;
    }
    
    getComponentStyles() {
        return `
            /* Include the component styles from the main system */
            ${require('./markdown-components').componentStyles}
        `;
    }
    
    start() {
        return new Promise((resolve) => {
            this.server = this.app.listen(this.options.port, this.options.host, () => {
                console.log(`🚀 Component development server running at http://${this.options.host}:${this.options.port}`);
                
                // Setup WebSocket server
                this.wss = new WebSocket.Server({ server: this.server });
                
                this.wss.on('connection', (ws) => {
                    this.connections.add(ws);
                    
                    ws.on('close', () => {
                        this.connections.delete(ws);
                    });
                });
                
                resolve();
            });
        });
    }
    
    broadcastReload() {
        const message = JSON.stringify({ type: 'reload' });
        
        for (const ws of this.connections) {
            if (ws.readyState === WebSocket.OPEN) {
                ws.send(message);
            }
        }
    }
    
    stop() {
        if (this.server) {
            this.server.close();
        }
        
        if (this.wss) {
            this.wss.close();
        }
    }
}

module.exports = ComponentDevelopmentServer;

// CLI usage
if (require.main === module) {
    const server = new ComponentDevelopmentServer({
        port: process.env.PORT || 3000,
        host: process.env.HOST || 'localhost'
    });
    
    server.start().then(() => {
        console.log('Development server started successfully');
    }).catch((error) => {
        console.error('Failed to start development server:', error);
        process.exit(1);
    });
    
    // Graceful shutdown
    process.on('SIGINT', () => {
        console.log('\nShutting down development server...');
        server.stop();
        process.exit(0);
    });
}

Integration with Documentation Systems

Custom component systems integrate seamlessly with comprehensive documentation workflows. When combined with performance optimization and rendering systems, custom components maintain fast loading times while providing enhanced functionality, ensuring optimal user experience across both static and interactive content elements.

For sophisticated content management, custom components work effectively with version control and collaborative workflows to ensure that component definitions are versioned alongside content, maintaining consistency and enabling collaborative development of reusable documentation elements across distributed teams.

When building comprehensive documentation architectures, custom HTML components complement Progressive Web App documentation systems by providing interactive functionality that enhances offline experiences, caches efficiently, and integrates seamlessly with service workers and background sync capabilities.

Advanced Component Patterns and Best Practices

Component Lifecycle Management

Implementing sophisticated lifecycle hooks and state management for complex components:

// component-lifecycle.js - Advanced component lifecycle management
class ComponentLifecycleManager {
    constructor() {
        this.lifecycleHooks = new Map();
        this.componentInstances = new Map();
        this.globalState = new Map();
        this.eventBus = new EventTarget();
        
        this.registerDefaultHooks();
    }
    
    registerDefaultHooks() {
        // Default lifecycle hooks
        this.lifecycleHooks.set('beforeCreate', []);
        this.lifecycleHooks.set('created', []);
        this.lifecycleHooks.set('beforeMount', []);
        this.lifecycleHooks.set('mounted', []);
        this.lifecycleHooks.set('beforeUpdate', []);
        this.lifecycleHooks.set('updated', []);
        this.lifecycleHooks.set('beforeDestroy', []);
        this.lifecycleHooks.set('destroyed', []);
    }
    
    registerLifecycleHook(phase, handler) {
        if (!this.lifecycleHooks.has(phase)) {
            this.lifecycleHooks.set(phase, []);
        }
        this.lifecycleHooks.get(phase).push(handler);
    }
    
    async executeLifecycleHooks(phase, component, context) {
        const hooks = this.lifecycleHooks.get(phase) || [];
        
        for (const hook of hooks) {
            try {
                await hook(component, context);
            } catch (error) {
                console.error(`Lifecycle hook error in ${phase}:`, error);
            }
        }
    }
    
    async createComponent(componentName, attributes, content, context) {
        const componentId = this.generateComponentId(componentName);
        
        const componentInstance = {
            id: componentId,
            name: componentName,
            attributes,
            content,
            context,
            state: new Map(),
            mounted: false,
            destroyed: false,
            element: null
        };
        
        // Execute lifecycle hooks
        await this.executeLifecycleHooks('beforeCreate', componentInstance, context);
        
        // Store instance
        this.componentInstances.set(componentId, componentInstance);
        
        await this.executeLifecycleHooks('created', componentInstance, context);
        
        return componentInstance;
    }
    
    async mountComponent(componentInstance, element) {
        if (componentInstance.mounted) {
            return;
        }
        
        await this.executeLifecycleHooks('beforeMount', componentInstance);
        
        componentInstance.element = element;
        componentInstance.mounted = true;
        
        await this.executeLifecycleHooks('mounted', componentInstance);
        
        // Set up event listeners and observers
        this.setupComponentEventListeners(componentInstance);
        this.setupComponentObservers(componentInstance);
    }
    
    async updateComponent(componentInstance, newAttributes, newContent) {
        if (componentInstance.destroyed) {
            return;
        }
        
        await this.executeLifecycleHooks('beforeUpdate', componentInstance);
        
        componentInstance.attributes = { ...componentInstance.attributes, ...newAttributes };
        if (newContent !== undefined) {
            componentInstance.content = newContent;
        }
        
        await this.executeLifecycleHooks('updated', componentInstance);
    }
    
    async destroyComponent(componentId) {
        const componentInstance = this.componentInstances.get(componentId);
        
        if (!componentInstance || componentInstance.destroyed) {
            return;
        }
        
        await this.executeLifecycleHooks('beforeDestroy', componentInstance);
        
        // Clean up event listeners and observers
        this.cleanupComponentEventListeners(componentInstance);
        this.cleanupComponentObservers(componentInstance);
        
        componentInstance.destroyed = true;
        componentInstance.element = null;
        
        await this.executeLifecycleHooks('destroyed', componentInstance);
        
        this.componentInstances.delete(componentId);
    }
    
    setupComponentEventListeners(componentInstance) {
        if (!componentInstance.element) return;
        
        const element = componentInstance.element;
        
        // Set up custom event handlers defined in attributes
        if (componentInstance.attributes.onClick) {
            element.addEventListener('click', (event) => {
                this.handleComponentEvent(componentInstance, 'click', event);
            });
        }
        
        if (componentInstance.attributes.onHover) {
            element.addEventListener('mouseenter', (event) => {
                this.handleComponentEvent(componentInstance, 'hover', event);
            });
        }
        
        // Set up intersection observer for lazy loading
        if (componentInstance.attributes.lazy) {
            this.setupIntersectionObserver(componentInstance);
        }
    }
    
    setupIntersectionObserver(componentInstance) {
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    this.handleComponentEvent(componentInstance, 'visible', entry);
                    observer.unobserve(entry.target);
                }
            });
        });
        
        observer.observe(componentInstance.element);
        componentInstance._intersectionObserver = observer;
    }
    
    setupComponentObservers(componentInstance) {
        // Set up mutation observer for dynamic content
        if (componentInstance.attributes.watchMutations) {
            const observer = new MutationObserver((mutations) => {
                this.handleComponentEvent(componentInstance, 'mutation', mutations);
            });
            
            observer.observe(componentInstance.element, {
                childList: true,
                subtree: true,
                attributes: true
            });
            
            componentInstance._mutationObserver = observer;
        }
    }
    
    cleanupComponentEventListeners(componentInstance) {
        // Event listeners are automatically removed when element is removed from DOM
        // But clean up custom observers
        this.cleanupComponentObservers(componentInstance);
    }
    
    cleanupComponentObservers(componentInstance) {
        if (componentInstance._intersectionObserver) {
            componentInstance._intersectionObserver.disconnect();
            delete componentInstance._intersectionObserver;
        }
        
        if (componentInstance._mutationObserver) {
            componentInstance._mutationObserver.disconnect();
            delete componentInstance._mutationObserver;
        }
    }
    
    handleComponentEvent(componentInstance, eventType, eventData) {
        // Emit component event
        const customEvent = new CustomEvent('component-event', {
            detail: {
                componentId: componentInstance.id,
                componentName: componentInstance.name,
                eventType,
                eventData,
                component: componentInstance
            }
        });
        
        this.eventBus.dispatchEvent(customEvent);
        
        // Call component-specific handler if defined
        const handlerName = `on${eventType.charAt(0).toUpperCase()}${eventType.slice(1)}`;
        if (componentInstance.attributes[handlerName]) {
            try {
                const handler = new Function('event', 'component', componentInstance.attributes[handlerName]);
                handler(eventData, componentInstance);
            } catch (error) {
                console.error(`Component event handler error:`, error);
            }
        }
    }
    
    generateComponentId(componentName) {
        return `${componentName}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    }
    
    // State management methods
    setGlobalState(key, value) {
        this.globalState.set(key, value);
        
        // Notify components that might be interested
        const stateChangeEvent = new CustomEvent('global-state-change', {
            detail: { key, value }
        });
        this.eventBus.dispatchEvent(stateChangeEvent);
    }
    
    getGlobalState(key) {
        return this.globalState.get(key);
    }
    
    setComponentState(componentId, key, value) {
        const component = this.componentInstances.get(componentId);
        if (component) {
            component.state.set(key, value);
        }
    }
    
    getComponentState(componentId, key) {
        const component = this.componentInstances.get(componentId);
        return component ? component.state.get(key) : undefined;
    }
    
    // Event bus methods
    on(eventType, handler) {
        this.eventBus.addEventListener(eventType, handler);
    }
    
    off(eventType, handler) {
        this.eventBus.removeEventListener(eventType, handler);
    }
    
    emit(eventType, detail) {
        const event = new CustomEvent(eventType, { detail });
        this.eventBus.dispatchEvent(event);
    }
    
    // Component communication
    sendMessage(fromComponentId, toComponentId, message) {
        const toComponent = this.componentInstances.get(toComponentId);
        
        if (toComponent) {
            this.handleComponentEvent(toComponent, 'message', {
                from: fromComponentId,
                message
            });
        }
    }
    
    broadcast(fromComponentId, message) {
        for (const [componentId, component] of this.componentInstances) {
            if (componentId !== fromComponentId) {
                this.handleComponentEvent(component, 'broadcast', {
                    from: fromComponentId,
                    message
                });
            }
        }
    }
    
    // Query components
    findComponentsByName(componentName) {
        return Array.from(this.componentInstances.values())
            .filter(component => component.name === componentName);
    }
    
    findComponentsWithAttribute(attributeName, attributeValue) {
        return Array.from(this.componentInstances.values())
            .filter(component => {
                const attrValue = component.attributes[attributeName];
                return attributeValue === undefined ? attrValue !== undefined : attrValue === attributeValue;
            });
    }
    
    getAllComponents() {
        return Array.from(this.componentInstances.values());
    }
    
    getComponentStats() {
        const stats = {
            totalComponents: this.componentInstances.size,
            componentsByType: {},
            mountedComponents: 0,
            destroyedComponents: 0
        };
        
        for (const component of this.componentInstances.values()) {
            stats.componentsByType[component.name] = 
                (stats.componentsByType[component.name] || 0) + 1;
            
            if (component.mounted) stats.mountedComponents++;
            if (component.destroyed) stats.destroyedComponents++;
        }
        
        return stats;
    }
}

// Enhanced component system with lifecycle management
class LifecycleAwareComponentSystem extends MarkdownComponentSystem {
    constructor(options = {}) {
        super(options);
        this.lifecycleManager = new ComponentLifecycleManager();
        
        this.setupLifecycleHooks();
    }
    
    setupLifecycleHooks() {
        // Register default lifecycle hooks
        this.lifecycleManager.registerLifecycleHook('created', async (component) => {
            console.log(`Component created: ${component.name} (${component.id})`);
        });
        
        this.lifecycleManager.registerLifecycleHook('mounted', async (component) => {
            console.log(`Component mounted: ${component.name} (${component.id})`);
            
            // Initialize component-specific features
            await this.initializeComponentFeatures(component);
        });
        
        this.lifecycleManager.registerLifecycleHook('destroyed', async (component) => {
            console.log(`Component destroyed: ${component.name} (${component.id})`);
        });
    }
    
    async initializeComponentFeatures(component) {
        // Auto-initialize syntax highlighting
        if (component.name === 'code-example') {
            await this.initializeSyntaxHighlighting(component);
        }
        
        // Auto-initialize interactive features
        if (component.attributes.interactive) {
            await this.initializeInteractiveFeatures(component);
        }
        
        // Auto-initialize analytics tracking
        if (component.attributes.trackAnalytics) {
            this.initializeAnalyticsTracking(component);
        }
    }
    
    async initializeSyntaxHighlighting(component) {
        if (component.element && window.Prism) {
            const codeElements = component.element.querySelectorAll('code[class*="language-"]');
            codeElements.forEach(el => window.Prism.highlightElement(el));
        }
    }
    
    async initializeInteractiveFeatures(component) {
        // Add interactive capabilities based on component type
        if (component.element) {
            component.element.classList.add('interactive-component');
            
            // Enable keyboard navigation
            component.element.setAttribute('tabindex', '0');
            
            // Add ARIA attributes
            component.element.setAttribute('role', 'application');
            component.element.setAttribute('aria-label', `Interactive ${component.name} component`);
        }
    }
    
    initializeAnalyticsTracking(component) {
        // Track component interactions
        this.lifecycleManager.on('component-event', (event) => {
            if (event.detail.componentId === component.id) {
                this.trackComponentEvent(component, event.detail.eventType, event.detail.eventData);
            }
        });
    }
    
    trackComponentEvent(component, eventType, eventData) {
        // Send analytics event (implementation depends on your analytics system)
        if (typeof gtag !== 'undefined') {
            gtag('event', 'component_interaction', {
                component_name: component.name,
                event_type: eventType,
                component_id: component.id
            });
        }
    }
    
    async renderComponent(componentName, attributes, content) {
        // Create component instance with lifecycle management
        const componentInstance = await this.lifecycleManager.createComponent(
            componentName, 
            attributes, 
            content, 
            this.context
        );
        
        // Render using parent method
        const html = await super.renderComponent(componentName, attributes, content);
        
        // Parse HTML to get DOM element (in browser environment)
        if (typeof document !== 'undefined') {
            const tempDiv = document.createElement('div');
            tempDiv.innerHTML = html;
            const element = tempDiv.firstElementChild;
            
            if (element) {
                // Add component ID to element
                element.setAttribute('data-component-id', componentInstance.id);
                
                // Mount component when element is added to DOM
                const observer = new MutationObserver((mutations) => {
                    mutations.forEach(mutation => {
                        if (mutation.type === 'childList') {
                            mutation.addedNodes.forEach(node => {
                                if (node.nodeType === Node.ELEMENT_NODE) {
                                    const componentEl = node.querySelector(`[data-component-id="${componentInstance.id}"]`) || 
                                                       (node.getAttribute('data-component-id') === componentInstance.id ? node : null);
                                    
                                    if (componentEl) {
                                        this.lifecycleManager.mountComponent(componentInstance, componentEl);
                                        observer.disconnect();
                                    }
                                }
                            });
                        }
                    });
                });
                
                observer.observe(document.body, { childList: true, subtree: true });
                
                // Auto-disconnect observer after 10 seconds to prevent memory leaks
                setTimeout(() => observer.disconnect(), 10000);
            }
        }
        
        return html;
    }
    
    // Utility methods for component management
    destroyAllComponents() {
        const components = this.lifecycleManager.getAllComponents();
        components.forEach(component => {
            this.lifecycleManager.destroyComponent(component.id);
        });
    }
    
    getComponentStats() {
        return this.lifecycleManager.getComponentStats();
    }
    
    findComponents(selector) {
        if (selector.startsWith('.')) {
            // Find by name
            return this.lifecycleManager.findComponentsByName(selector.substring(1));
        } else if (selector.startsWith('[') && selector.endsWith(']')) {
            // Find by attribute
            const match = selector.match(/^\[(\w+)(?:=(.+))?\]$/);
            if (match) {
                const [, attrName, attrValue] = match;
                return this.lifecycleManager.findComponentsWithAttribute(attrName, attrValue);
            }
        }
        
        return [];
    }
}

module.exports = { ComponentLifecycleManager, LifecycleAwareComponentSystem };

Conclusion

Advanced Markdown custom HTML components and extensions represent a powerful approach to creating dynamic, interactive documentation that bridges the gap between static content and modern web applications. Through sophisticated component architectures, advanced templating systems, and comprehensive lifecycle management, technical teams can build rich documentation experiences that engage readers, provide interactive learning opportunities, and maintain the simplicity that makes Markdown an effective content format.

The key to successful custom component implementation lies in balancing functionality with maintainability, ensuring that enhanced capabilities serve content quality and user experience rather than introducing unnecessary complexity. Whether you’re building interactive code examples, dynamic data visualizations, or comprehensive component libraries, the techniques covered in this guide provide the foundation for creating scalable, reusable documentation elements that enhance reader engagement and learning outcomes.

Remember to implement proper testing and validation systems for your custom components, establish clear documentation and usage guidelines for content creators, and continuously monitor component performance and user interactions to optimize the documentation experience. With thoughtful implementation of advanced custom component systems, your Markdown-based documentation can achieve the same level of interactivity and user engagement that modern web applications provide while maintaining the efficiency and portability that makes Markdown such an effective format for technical content creation.