133 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * 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; |