/** * Macro Processor * Handles macro execution and result rendering */ class MacroProcessor { constructor(webdavClient) { this.webdavClient = webdavClient; this.macroRegistry = new MacroRegistry(); this.includeStack = []; this.faqItems = []; this.registerDefaultPlugins(); console.log('[MacroProcessor] Initialized'); } /** * Process all macros in markdown */ async processMacros(content) { console.log('[MacroProcessor] Processing content, length:', content.length); const macros = MacroParser.extractMacros(content); console.log(`[MacroProcessor] Found ${macros.length} macros`); const errors = []; let processedContent = content; let faqOutput = ''; // Process in reverse to preserve positions for (let i = macros.length - 1; i >= 0; i--) { const macro = macros[i]; console.log(`[MacroProcessor] Processing macro ${i}:`, macro.actor, macro.method); try { const result = await this.processMacro(macro); if (result.success) { console.log(`[MacroProcessor] Macro succeeded, replacing content`); processedContent = processedContent.substring(0, macro.start) + result.content + processedContent.substring(macro.end); } else { console.error(`[MacroProcessor] Macro failed:`, result.error); errors.push({ macro: macro.fullMatch, error: result.error }); const errorMsg = `\n\n⚠️ **Macro Error**: ${result.error}\n\n`; processedContent = processedContent.substring(0, macro.start) + errorMsg + processedContent.substring(macro.end); } } catch (error) { console.error(`[MacroProcessor] Macro exception:`, error); errors.push({ macro: macro.fullMatch, error: error.message }); const errorMsg = `\n\n⚠️ **Macro Exception**: ${error.message}\n\n`; processedContent = processedContent.substring(0, macro.start) + errorMsg + processedContent.substring(macro.end); } } // Append FAQ if any FAQ macros were used if (this.faqItems.length > 0) { faqOutput = '\n\n---\n\n## FAQ\n\n'; faqOutput += this.faqItems .map((item, idx) => `### ${idx + 1}. ${item.title}\n\n${item.response}`) .join('\n\n'); processedContent += faqOutput; } console.log('[MacroProcessor] Processing complete, errors:', errors.length); return { success: errors.length === 0, content: processedContent, errors }; } /** * Process single macro */ async processMacro(macro) { const plugin = this.macroRegistry.resolve(macro.actor, macro.method); if (!plugin) { return { success: false, error: `Unknown macro: !!${macro.actor}.${macro.method}` }; } // Check for circular includes if (macro.method === 'include') { const path = macro.params.path; if (this.includeStack.includes(path)) { return { success: false, error: `Circular include: ${this.includeStack.join(' → ')} → ${path}` }; } } try { return await plugin.process(macro, this.webdavClient); } catch (error) { console.error('[MacroProcessor] Plugin error:', error); return { success: false, error: `Plugin error: ${error.message}` }; } } /** * Register default plugins */ registerDefaultPlugins() { // Include plugin this.macroRegistry.register('core', 'include', new IncludePlugin(this)); // FAQ plugin this.macroRegistry.register('core', 'faq', new FAQPlugin(this)); console.log('[MacroProcessor] Registered default plugins'); } } window.MacroProcessor = MacroProcessor;