feat: add comprehensive testing and error tracking for edit mode

Add robust testing framework to prevent regression of edit mode:
- Comprehensive regression tests for JavaScript syntax validation
- Build-time JavaScript validation tool with Node.js integration
- Enhanced error tracking with detailed logging and recovery
- Makefile integration for `make validate-js` command

Features:
- Validates JavaScript syntax in generated HTML templates
- Detects common issues like broken string literals and brace escaping
- Enhanced error reporting with timestamps and context
- Automatic error recovery for graceful degradation
- Build validation to catch syntax errors before deployment

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-25 16:53:09 +02:00
parent 1022e2597f
commit 64d1606740
4 changed files with 774 additions and 10 deletions

View File

@@ -659,18 +659,115 @@ class DocumentManager:
// Define editor class first (if in edit mode)
{editor_scripts if edit_mode else ''}
// Error reporting utility
function reportEditModeError(errorMsg, technicalDetails) {{
// Enhanced error reporting utility
function reportEditModeError(errorMsg, technicalDetails, errorType = 'error') {{
const statusDiv = document.getElementById('markitect-status');
const errorDiv = document.getElementById('error-details');
const errorText = document.getElementById('error-text');
const statusMsg = document.getElementById('status-message');
const browserInfo = document.getElementById('browser-info');
if (statusMsg) statusMsg.textContent = 'Edit mode unavailable - content displayed in read-only mode';
// Log to console for debugging
console.error('[MarkiTect Edit Mode Error]', errorMsg, technicalDetails);
// Create error report object
const errorReport = {{
timestamp: new Date().toISOString(),
error: errorMsg,
details: technicalDetails,
type: errorType,
userAgent: navigator.userAgent,
url: window.location.href,
markdownContent: typeof markdownContent !== 'undefined' ? markdownContent.length + ' chars' : 'unavailable'
}};
// Store error for potential reporting
if (!window.markitectErrors) window.markitectErrors = [];
window.markitectErrors.push(errorReport);
// Update UI
if (statusMsg) {{
const statusText = errorType === 'warning'
? 'Edit mode partially available - some features may not work'
: 'Edit mode unavailable - content displayed in read-only mode';
statusMsg.textContent = statusText;
}}
if (errorDiv) errorDiv.style.display = 'block';
if (errorText) errorText.textContent = errorMsg + (technicalDetails ? ' (' + technicalDetails + ')' : '');
if (errorText) {{
const fullError = errorMsg + (technicalDetails ? ' (' + technicalDetails + ')' : '');
errorText.textContent = fullError;
}}
if (browserInfo) browserInfo.textContent = navigator.userAgent.split(' ').slice(-2).join(' ');
// Auto-hide warnings after 10 seconds
if (errorType === 'warning' && errorDiv) {{
setTimeout(() => {{
errorDiv.style.display = 'none';
}}, 10000);
}}
}}
// Enhanced error recovery utility
function attemptErrorRecovery(error, context) {{
console.warn('[MarkiTect] Attempting error recovery for:', context, error);
try {{
// Try to ensure content is still visible
const contentDiv = document.getElementById('markdown-content');
if (contentDiv && !contentDiv.innerHTML.trim()) {{
// Fallback content rendering
const fallbackHtml = markdownContent
.replace(/^# (.*$)/gim, '<h1>$1</h1>')
.replace(/^## (.*$)/gim, '<h2>$1</h2>')
.replace(/\\n\\n/g, '<br><br>')
.replace(/\\n/g, '<br>');
contentDiv.innerHTML = '<div style="white-space: pre-wrap;">' + fallbackHtml + '</div>';
reportEditModeError('Recovered with fallback rendering', 'Edit features disabled', 'warning');
return true;
}}
}} catch (recoveryError) {{
console.error('[MarkiTect] Recovery failed:', recoveryError);
}}
return false;
}}
// Validation utility for edit mode state
function validateEditModeState() {{
const issues = [];
// Check required elements
if (!document.getElementById('markdown-content')) {{
issues.push('Missing markdown-content container');
}}
if (!document.getElementById('markitect-status')) {{
issues.push('Missing status display');
}}
// Check JavaScript dependencies
if (typeof marked === 'undefined') {{
issues.push('marked.js library not available');
}}
if (typeof MARKITECT_EDIT_MODE === 'undefined') {{
issues.push('Edit mode configuration missing');
}}
// Check for MarkitectEditor
if (typeof MarkitectEditor === 'undefined') {{
issues.push('MarkitectEditor class not defined');
}}
if (issues.length > 0) {{
console.warn('[MarkiTect] Edit mode validation issues:', issues);
reportEditModeError('Edit mode validation failed', issues.join(', '), 'warning');
return false;
}}
return true;
}}
// Status update utility
@@ -718,19 +815,44 @@ class DocumentManager:
}}
// Step 2: Try to enhance with edit capabilities (if in edit mode)
{'''if (typeof MARKITECT_EDIT_MODE !== 'undefined' && MARKITECT_EDIT_MODE) {
{'''if (typeof MARKITECT_EDIT_MODE !== 'undefined' && MARKITECT_EDIT_MODE) {{
updateStatus("Initializing edit capabilities...");
try {
// Validate edit mode prerequisites
if (!validateEditModeState()) {{
if (!attemptErrorRecovery('validation failed', 'edit mode prerequisites')) {{
return; // Stop here if recovery fails
}}
}}
try {{
updateStatus("Creating editor instance...");
markitectEditor = new MarkitectEditor();
updateStatus("✓ Edit mode active - click any section to edit");
console.log("✓ Edit mode initialized successfully");
} catch (error) {
// Final validation check
setTimeout(() => {{
const sections = document.querySelectorAll('.markitect-section-editable');
if (sections.length === 0) {{
reportEditModeError('No editable sections found', 'Content may not be compatible with edit mode', 'warning');
}} else {{
console.log(`[MarkiTect] Found ${{sections.length}} editable sections`);
}}
}}, 1000);
}} catch (error) {{
updateStatus("Edit mode failed to initialize", true);
reportEditModeError("Edit mode initialization failed", error.message);
console.error("Edit mode error:", error);
}
}''' if edit_mode else ''}
// Try error recovery
if (attemptErrorRecovery(error, 'editor initialization')) {{
reportEditModeError("Edit mode partially recovered", error.message, 'warning');
}} else {{
reportEditModeError("Edit mode initialization failed", error.message);
}}
}}
}}''' if edit_mode else ''}
}});
// Handle CDN loading errors