/** * Main Markitect JavaScript Entry Point * Initializes all controls and systems when document is ready * Implements graceful degradation for missing dependencies * Supports Fail Fast strict mode for development */ // Development mode detection const MARKITECT_STRICT_MODE = ( window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1' || window.location.search.includes('strict=true') || window.markitectStrictMode === true ); // Utility functions for safe initialization const MarkitectMain = { // Safe dependency checking with timeout checkDependencies: function() { const dependencies = { debugSystem: !!window.MarkitectDebugSystem, control: !!window.Control, statusControl: !!window.StatusControl, debugControl: !!window.DebugControl, contentsControl: !!window.ContentsControl, editControl: !!window.EditControl }; console.log('📋 Dependency check results:', dependencies); return dependencies; }, // Safe logging that works even without debug system safeLog: function(message, level = 'INFO', component = 'Main', data = {}) { console.log(`[${level}] ${component}: ${message}`); // In strict mode, throw on errors for immediate development feedback if (MARKITECT_STRICT_MODE && level === 'ERROR') { console.error(`🚨 STRICT MODE: Throwing error for immediate diagnosis`); throw new Error(`${component}: ${message}`); } // Try to use debug system if available if (window.MarkitectDebugSystem && window.MarkitectDebugSystem.addMessage) { try { window.MarkitectDebugSystem.addMessage(message, level, component, { ...data, eventType: 'SYSTEM' }); } catch (error) { console.warn('Debug system logging failed:', error); if (MARKITECT_STRICT_MODE) { throw error; // Fail fast in development } } } }, // Safe control initialization with fallbacks initializeControl: function(controlClass, controlName, icon = '🔧') { const timeout = setTimeout(() => { const message = `${controlName} initialization timed out`; console.warn(message); if (MARKITECT_STRICT_MODE) { throw new Error(message); // Fail fast in development } }, 5000); try { if (!controlClass) { const message = `${controlName} class not available, skipping`; this.safeLog(message, MARKITECT_STRICT_MODE ? 'ERROR' : 'WARNING'); clearTimeout(timeout); return null; } const controlInstance = new controlClass(); if (!controlInstance || typeof controlInstance.createControl !== 'function') { throw new Error(`Invalid ${controlName} instance`); } const element = controlInstance.createControl(); if (!element) { throw new Error(`${controlName} failed to create element`); } clearTimeout(timeout); this.safeLog(`${controlName} initialized successfully`, 'SUCCESS'); return controlInstance; } catch (error) { clearTimeout(timeout); this.safeLog(`${controlName} initialization failed: ${error.message}`, 'ERROR'); // Create minimal fallback control if core Control class exists if (window.Control && controlName === 'StatusControl') { return this.createFallbackControl(controlName, icon); } return null; } }, // Create minimal fallback control for essential controls createFallbackControl: function(name, icon) { try { const fallback = Object.create(window.Control); fallback.config = { icon: icon, title: `${name} (Fallback)`, className: `${name.toLowerCase()}-fallback`, defaultContent: `${name} is running in fallback mode due to initialization issues.`, ariaLabel: `${name} Fallback Control`, position: 'e' }; const element = fallback.createControl(); if (element) { this.safeLog(`${name} fallback control created`, 'INFO'); return { control: fallback }; } } catch (error) { this.safeLog(`Fallback control creation failed: ${error.message}`, 'ERROR'); } return null; }, // Main initialization with comprehensive error handling initialize: function() { this.safeLog('🚀 Initializing Markitect controls and systems...', 'INFO'); // Check dependencies first const deps = this.checkDependencies(); if (!deps.control) { this.safeLog('❌ Core Control system not available, cannot initialize UI controls', 'ERROR'); return; } const initializedControls = {}; let successCount = 0; let totalAttempts = 0; // Initialize controls with graceful degradation const controlsToInit = [ { class: window.StatusControl, name: 'StatusControl', key: 'statusControl', icon: '📊', essential: true }, { class: window.DebugControl, name: 'DebugControl', key: 'debugControl', icon: '🪲', essential: false }, { class: window.ContentsControl, name: 'ContentsControl', key: 'contentsControl', icon: '☰', essential: false }, { class: window.EditControl, name: 'EditControl', key: 'editControl', icon: '✏️', essential: false } ]; controlsToInit.forEach(({ class: controlClass, name, key, icon, essential }) => { totalAttempts++; const instance = this.initializeControl(controlClass, name, icon); if (instance) { initializedControls[key] = instance.control || instance; window[key] = initializedControls[key]; successCount++; } else if (essential) { this.safeLog(`Essential control ${name} failed to initialize`, 'ERROR'); } }); // Report initialization results const successRate = Math.round((successCount / totalAttempts) * 100); if (successCount === totalAttempts) { this.safeLog('✅ All controls initialized successfully', 'SUCCESS'); } else if (successCount > 0) { this.safeLog(`⚠️ Partial initialization: ${successCount}/${totalAttempts} controls (${successRate}%) initialized`, 'WARNING'); } else { this.safeLog('❌ No controls could be initialized', 'ERROR'); } // Set up global error handlers for runtime protection this.setupErrorHandlers(); this.safeLog(`✅ Markitect initialization complete (${successCount}/${totalAttempts} controls active)`, 'INFO'); }, // Set up global error handlers setupErrorHandlers: function() { // Catch unhandled errors window.addEventListener('error', (event) => { this.safeLog(`Unhandled error: ${event.message} at ${event.filename}:${event.lineno}`, 'ERROR'); }); // Catch unhandled promise rejections window.addEventListener('unhandledrejection', (event) => { this.safeLog(`Unhandled promise rejection: ${event.reason}`, 'ERROR'); event.preventDefault(); // Prevent console spam }); } }; // Initialize when DOM is ready with additional safety if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { setTimeout(() => MarkitectMain.initialize(), 100); // Brief delay for dependencies }); } else { // DOM already loaded setTimeout(() => MarkitectMain.initialize(), 100); }