/** * Clean Editor Integration * * This file provides a complete, drop-in replacement for the existing * section editing functionality using our clean object-oriented architecture. */ // Include the core classes (in real implementation, these would be imported) // For now, assuming they're loaded separately /** * MarkitectCleanEditor - Main integration class * * This replaces the existing complex editor implementation with our * clean, testable architecture. */ class MarkitectCleanEditor { constructor(markdownContent, containerElement, options = {}) { this.options = { theme: 'github', keyboardShortcuts: true, autosave: false, ...options }; // Initialize the core system this.sectionManager = new MarkitectEditor.SectionManager(); this.domRenderer = new MarkitectEditor.DOMRenderer(this.sectionManager, containerElement); // Store original content this.originalMarkdown = markdownContent; // Event handlers for external integration this.onDocumentChange = null; this.onSectionChange = null; // Setup external event forwarding this.setupEventForwarding(); // Initialize sections this.initialize(); } /** * Initialize the editor with the markdown content */ initialize() { try { // Create sections from markdown const sections = this.sectionManager.createSectionsFromMarkdown(this.originalMarkdown); console.log(`✓ Initialized clean editor with ${sections.length} sections`); // Set up global keyboard shortcuts this.setupGlobalKeyboardShortcuts(); return true; } catch (error) { console.error('Failed to initialize clean editor:', error); return false; } } /** * Setup event forwarding to external callbacks */ setupEventForwarding() { // Forward document-level changes this.sectionManager.on('changes-accepted', () => { if (this.onDocumentChange) { this.onDocumentChange(this.getDocumentStatus()); } }); this.sectionManager.on('changes-cancelled', () => { if (this.onDocumentChange) { this.onDocumentChange(this.getDocumentStatus()); } }); // Forward section-level changes this.sectionManager.on('content-updated', (data) => { if (this.onSectionChange) { this.onSectionChange(data); } }); } /** * Setup global keyboard shortcuts */ setupGlobalKeyboardShortcuts() { if (!this.options.keyboardShortcuts) return; document.addEventListener('keydown', (event) => { if (event.ctrlKey || event.metaKey) { switch (event.key) { case 's': event.preventDefault(); this.saveDocument(); break; case 'z': if (event.shiftKey) { event.preventDefault(); // Could implement redo } else { event.preventDefault(); // Could implement undo } break; case 'r': event.preventDefault(); this.resetAllSections(); break; } } }); } /** * Get current document markdown * @returns {string} The complete document markdown */ getDocumentMarkdown() { return this.sectionManager.getDocumentMarkdown(); } /** * Get document status * @returns {Object} Document status object */ getDocumentStatus() { return this.sectionManager.getDocumentStatus(); } /** * Check if document has unsaved changes * @returns {boolean} True if there are unsaved changes */ hasUnsavedChanges() { const status = this.getDocumentStatus(); return status.hasUnsavedChanges; } /** * Save document (triggers download) */ saveDocument() { const markdown = this.getDocumentMarkdown(); const status = this.getDocumentStatus(); // Create download const blob = new Blob([markdown], { type: 'text/markdown' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'document.md'; a.style.display = 'none'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); console.log('📄 Document saved:', status); this.showMessage('Document saved successfully!', 'success'); } /** * Reset all sections to original state */ resetAllSections() { if (confirm('Reset all content to original markdown? This will lose all edits.')) { this.domRenderer.resetAllSections(); this.showMessage('All sections reset to original content', 'info'); } } /** * Show message to user * @param {string} message - The message to show * @param {string} type - Message type: 'success', 'error', 'info' */ showMessage(message, type = 'info') { // Create message element const messageDiv = document.createElement('div'); messageDiv.className = `markitect-message markitect-message-${type}`; messageDiv.textContent = message; // Style the message const styles = { 'success': { bg: '#4caf50', color: 'white' }, 'error': { bg: '#f44336', color: 'white' }, 'info': { bg: '#2196f3', color: 'white' } }; const style = styles[type] || styles.info; messageDiv.style.cssText = ` position: fixed; top: 20px; right: 20px; background: ${style.bg}; color: ${style.color}; padding: 12px 20px; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.2); z-index: 10000; font-size: 14px; max-width: 300px; animation: slideIn 0.3s ease; `; // Add animation const styleSheet = document.createElement('style'); styleSheet.textContent = ` @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } `; document.head.appendChild(styleSheet); document.body.appendChild(messageDiv); // Remove after 3 seconds setTimeout(() => { if (messageDiv.parentNode) { messageDiv.style.animation = 'slideIn 0.3s ease reverse'; setTimeout(() => { if (messageDiv.parentNode) { messageDiv.parentNode.removeChild(messageDiv); } }, 300); } }, 3000); } /** * Add control panel to the page */ addControlPanel() { const panel = document.createElement('div'); panel.className = 'markitect-control-panel-clean'; panel.innerHTML = `