This commit preserves work from a refactoring session that attempted to: ACHIEVEMENTS: - Implemented Robustness Principle with dual-mode error handling - Created sophisticated error detection for edit mode failures - Added comprehensive safety utilities in control-base.js - Successfully recovered JavaScript components from git history - Fixed template variable substitution and initialization flow - Added detailed documentation (REFACTORING_SESSION_REPORT.md) PROBLEMS: - Violated GUARDRAILS.md by embedding JavaScript in Python strings - Mixed old and new component systems without proper migration - Content rendering issues - no visible content despite initialization - Became overly complex trying to solve multiple problems simultaneously LESSONS LEARNED: - Focus is critical - solve one problem at a time - Respect architectural constraints (keep JS separate from Python) - Component migration requires explicit planning - Incremental testing prevents complexity accumulation RECOMMENDATION: Reset to working commit and take focused, incremental approach that respects GUARDRAILS.md while achieving core edit mode functionality. See REFACTORING_SESSION_REPORT.md for detailed analysis. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
473 lines
16 KiB
HTML
473 lines
16 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="generator" content="Markitect Test">
|
|
<title>Strict Mode Test - Fail Fast + Robustness</title>
|
|
|
|
<!-- Base styling for document content -->
|
|
<style>
|
|
body {
|
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
line-height: 1.6;
|
|
color: #333;
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
padding: 2rem;
|
|
background-color: #ffffff;
|
|
}
|
|
|
|
h1, h2, h3 { color: #2c3e50; margin-top: 2rem; margin-bottom: 1rem; }
|
|
h1 { font-size: 2.5em; border-bottom: 3px solid #3498db; padding-bottom: 0.5rem; }
|
|
h2 { font-size: 2em; border-bottom: 2px solid #3498db; padding-bottom: 0.3rem; }
|
|
h3 { font-size: 1.5em; color: #34495e; }
|
|
|
|
p { margin-bottom: 1.2rem; text-align: justify; }
|
|
code { background-color: #f8f9fa; padding: 0.2rem 0.4rem; border-radius: 3px; font-family: 'Courier New', monospace; }
|
|
|
|
.test-status {
|
|
padding: 1rem;
|
|
margin: 1rem 0;
|
|
border-radius: 5px;
|
|
font-weight: bold;
|
|
}
|
|
.test-success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
|
|
.test-error { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
|
|
.test-warning { background: #fff3cd; color: #856404; border: 1px solid #ffeaa7; }
|
|
|
|
/* Control system styles for testing */
|
|
.control-panel {
|
|
position: fixed;
|
|
z-index: 1000;
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.control-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0.5rem;
|
|
background: #f8f9fa;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
user-select: none;
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
border: 1px solid #dee2e6;
|
|
transition: all 0.2s ease;
|
|
min-width: 120px;
|
|
}
|
|
|
|
.control-content {
|
|
display: none;
|
|
background: white;
|
|
border: 1px solid #dee2e6;
|
|
border-radius: 6px;
|
|
margin-top: 0.5rem;
|
|
max-width: 350px;
|
|
min-width: 250px;
|
|
max-height: 400px;
|
|
overflow-y: auto;
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
}
|
|
|
|
@media print {
|
|
.control-panel { display: none !important; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="markitect-content">
|
|
<h1>Strict Mode Test - Fail Fast + Robustness Balance</h1>
|
|
|
|
<p>This test page verifies that our <strong>Fail Fast</strong> strict mode works correctly in development while maintaining <strong>Robustness Principle</strong> protection in production.</p>
|
|
|
|
<h2>Test Content</h2>
|
|
|
|
<h3>Document Statistics Test</h3>
|
|
<p>This paragraph should be counted by the status control. It contains <code>inline code</code> and various formatting.</p>
|
|
|
|
<h3>List Test</h3>
|
|
<ul>
|
|
<li>First list item for counting</li>
|
|
<li>Second list item with <strong>bold text</strong></li>
|
|
<li>Third item with <em>italic emphasis</em></li>
|
|
</ul>
|
|
|
|
<h3>Table Test</h3>
|
|
<table border="1" style="border-collapse: collapse; width: 100%;">
|
|
<thead>
|
|
<tr>
|
|
<th style="padding: 8px; background: #f8f9fa;">Feature</th>
|
|
<th style="padding: 8px; background: #f8f9fa;">Development Mode</th>
|
|
<th style="padding: 8px; background: #f8f9fa;">Production Mode</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td style="padding: 8px;">Error Handling</td>
|
|
<td style="padding: 8px;">Fail Fast (throw errors)</td>
|
|
<td style="padding: 8px;">Graceful degradation</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 8px;">Missing Dependencies</td>
|
|
<td style="padding: 8px;">Throw error immediately</td>
|
|
<td style="padding: 8px;">Skip with warning</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 8px;">Validation Failures</td>
|
|
<td style="padding: 8px;">Stop execution</td>
|
|
<td style="padding: 8px;">Use fallback values</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<div id="test-results">
|
|
<h2>Test Results</h2>
|
|
<div id="test-output">Loading tests...</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Embed JavaScript directly for testing (avoiding HTTP path issues) -->
|
|
<script>
|
|
// Enable strict mode for testing
|
|
window.markitectStrictMode = true;
|
|
</script>
|
|
|
|
<script>
|
|
// Debug System (embedded)
|
|
window.MarkitectDebugSystem = {
|
|
messages: [],
|
|
|
|
addMessage: function(message, category = 'INFO', component = 'System', metadata = {}) {
|
|
const entry = {
|
|
id: Date.now() + Math.random(),
|
|
message: String(message).slice(0, 1000), // Limit message length
|
|
category: ['INFO', 'WARNING', 'ERROR', 'SUCCESS', 'DEBUG'].includes(category) ? category : 'INFO',
|
|
component: String(component).slice(0, 50),
|
|
timestamp: new Date().toISOString(),
|
|
displayTime: new Date().toLocaleTimeString(),
|
|
metadata: metadata || {}
|
|
};
|
|
|
|
this.messages.push(entry);
|
|
console.log(`[${entry.category}] ${entry.component}: ${entry.message}`);
|
|
|
|
// Trigger update if UI exists
|
|
if (this.updateCallback) {
|
|
this.updateCallback(entry);
|
|
}
|
|
|
|
return entry;
|
|
},
|
|
|
|
clearMessages: function() {
|
|
this.messages = [];
|
|
},
|
|
|
|
getMessages: function(category = null, limit = null) {
|
|
let filtered = category ?
|
|
this.messages.filter(msg => msg.category === category) :
|
|
this.messages;
|
|
|
|
return limit ? filtered.slice(-limit) : filtered;
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<script>
|
|
// Control Base (embedded with strict mode)
|
|
const MARKITECT_STRICT_MODE = (
|
|
window.location.hostname === 'localhost' ||
|
|
window.location.hostname === '127.0.0.1' ||
|
|
window.location.search.includes('strict=true') ||
|
|
window.markitectStrictMode === true
|
|
);
|
|
|
|
const Control = {
|
|
config: {
|
|
icon: '🔧',
|
|
title: 'Control',
|
|
className: 'base-control',
|
|
defaultContent: 'Control content',
|
|
ariaLabel: 'Base Control',
|
|
position: 'w',
|
|
footer: null
|
|
},
|
|
|
|
safeOperation: function(operation, fallback = null, context = 'Unknown') {
|
|
try {
|
|
return operation();
|
|
} catch (error) {
|
|
console.warn(`Control operation failed in ${context}:`, error);
|
|
|
|
// Fail Fast in development mode
|
|
if (MARKITECT_STRICT_MODE) {
|
|
console.error(`🚨 STRICT MODE: Control operation failed in ${context}`);
|
|
throw error; // Re-throw for immediate debugging
|
|
}
|
|
|
|
if (window.MarkitectDebugSystem) {
|
|
window.MarkitectDebugSystem.addMessage(
|
|
`Safe operation failed: ${error.message}`,
|
|
'WARNING',
|
|
'Control',
|
|
{ context, eventType: 'ERROR' }
|
|
);
|
|
}
|
|
return typeof fallback === 'function' ? fallback() : fallback;
|
|
}
|
|
},
|
|
|
|
compassPositions: {
|
|
'w': { top: '50vh', left: '20px', transform: 'translateY(-20px)' },
|
|
'e': { top: '50vh', right: '20px', transform: 'translateY(-20px)' }
|
|
},
|
|
|
|
isExpanded: false,
|
|
element: null,
|
|
|
|
createControl: function() {
|
|
return this.safeOperation(() => {
|
|
console.log(`Creating ${this.config.title} control...`);
|
|
|
|
if (!this.config || !this.config.title) {
|
|
throw new Error('Invalid control configuration');
|
|
}
|
|
|
|
if (!document.body) {
|
|
throw new Error('Document body not available');
|
|
}
|
|
|
|
this.element = document.createElement('div');
|
|
this.element.className = `control-panel ${this.config.className || ''}`;
|
|
this.element.setAttribute('role', 'dialog');
|
|
this.element.setAttribute('aria-label', this.config.ariaLabel || this.config.title);
|
|
|
|
const position = this.compassPositions[this.config.position] || this.compassPositions['w'];
|
|
Object.assign(this.element.style, {
|
|
position: 'fixed',
|
|
zIndex: '1000',
|
|
...position
|
|
});
|
|
|
|
this.buildControlStructure();
|
|
document.body.appendChild(this.element);
|
|
|
|
console.log(`${this.config.title} control created successfully`);
|
|
return this.element;
|
|
}, () => {
|
|
console.error(`Failed to create ${this.config?.title || 'Unknown'} control`);
|
|
return null;
|
|
}, 'createControl');
|
|
},
|
|
|
|
buildControlStructure: function() {
|
|
const safeIcon = (this.config.icon || '🔧').replace(/[<>"'&]/g, '');
|
|
const safeTitle = (this.config.title || 'Control').replace(/[<>"'&]/g, '');
|
|
|
|
this.element.innerHTML = `
|
|
<div class="control-header">
|
|
<div style="display: flex; align-items: center; gap: 0.5rem;">
|
|
<span style="font-size: 1.2rem;">${safeIcon}</span>
|
|
<span class="control-title" style="font-weight: 500; color: #495057;">${safeTitle}</span>
|
|
</div>
|
|
</div>
|
|
<div class="control-content">
|
|
<div style="padding: 1rem;">
|
|
${this.config.defaultContent || 'Control loaded successfully'}
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
this.element.querySelector('.control-header').addEventListener('click', () => {
|
|
this.toggle();
|
|
});
|
|
},
|
|
|
|
toggle: function() {
|
|
const content = this.element.querySelector('.control-content');
|
|
if (this.isExpanded) {
|
|
content.style.display = 'none';
|
|
this.isExpanded = false;
|
|
} else {
|
|
content.style.display = 'block';
|
|
this.isExpanded = true;
|
|
}
|
|
}
|
|
};
|
|
|
|
window.Control = Control;
|
|
</script>
|
|
|
|
<script>
|
|
// Status Control (embedded)
|
|
class StatusControl {
|
|
constructor() {
|
|
this.control = Object.create(Control);
|
|
this.control.config = {
|
|
icon: '📊',
|
|
title: 'Status',
|
|
className: 'status-control',
|
|
defaultContent: 'Click to see document statistics',
|
|
ariaLabel: 'Status Control',
|
|
position: 'e'
|
|
};
|
|
|
|
this.control.buildContent = () => {
|
|
const stats = this.calculateBasicStats();
|
|
const content = this.control.element.querySelector('.control-content');
|
|
|
|
content.innerHTML = `
|
|
<div style="padding: 1rem; font-size: 0.8rem;">
|
|
<h4 style="margin-top: 0;">Document Statistics</h4>
|
|
<p><strong>Headings:</strong> ${stats.headings}</p>
|
|
<p><strong>Paragraphs:</strong> ${stats.paragraphs}</p>
|
|
<p><strong>Lists:</strong> ${stats.lists}</p>
|
|
<p><strong>Tables:</strong> ${stats.tables}</p>
|
|
<p><strong>Total Words:</strong> ${stats.words}</p>
|
|
|
|
<div style="margin-top: 1rem; font-size: 0.7rem; color: #666;">
|
|
Mode: ${MARKITECT_STRICT_MODE ? '🚨 STRICT (Fail Fast)' : '🛡️ PRODUCTION (Robust)'}
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
this.control.isExpanded = true;
|
|
};
|
|
|
|
this.control.toggle = () => {
|
|
if (this.control.isExpanded) {
|
|
this.control.element.querySelector('.control-content').style.display = 'none';
|
|
this.control.isExpanded = false;
|
|
} else {
|
|
this.control.buildContent();
|
|
this.control.element.querySelector('.control-content').style.display = 'block';
|
|
}
|
|
};
|
|
}
|
|
|
|
calculateBasicStats() {
|
|
return {
|
|
headings: document.querySelectorAll('h1, h2, h3, h4, h5, h6').length,
|
|
paragraphs: document.querySelectorAll('p').length,
|
|
lists: document.querySelectorAll('ul, ol').length,
|
|
tables: document.querySelectorAll('table').length,
|
|
words: (document.body.textContent || '').split(/\s+/).filter(w => w.length > 0).length
|
|
};
|
|
}
|
|
|
|
createControl() {
|
|
return this.control.createControl();
|
|
}
|
|
}
|
|
|
|
window.StatusControl = StatusControl;
|
|
</script>
|
|
|
|
<script>
|
|
// Main initialization with strict mode
|
|
const MarkitectMain = {
|
|
initialize: function() {
|
|
console.log(`🚀 Initializing Markitect (Strict Mode: ${MARKITECT_STRICT_MODE})`);
|
|
|
|
const testOutput = document.getElementById('test-output');
|
|
const results = [];
|
|
|
|
// Test 1: Control System
|
|
try {
|
|
const statusControl = new StatusControl();
|
|
const element = statusControl.createControl();
|
|
|
|
if (element) {
|
|
window.statusControl = statusControl.control;
|
|
results.push({
|
|
test: 'Status Control Creation',
|
|
status: 'success',
|
|
message: 'Control created successfully'
|
|
});
|
|
} else {
|
|
throw new Error('Control creation returned null');
|
|
}
|
|
} catch (error) {
|
|
results.push({
|
|
test: 'Status Control Creation',
|
|
status: MARKITECT_STRICT_MODE ? 'error' : 'warning',
|
|
message: `Control failed: ${error.message}`
|
|
});
|
|
}
|
|
|
|
// Test 2: Debug System
|
|
try {
|
|
window.MarkitectDebugSystem.addMessage('Test message', 'INFO', 'Test');
|
|
results.push({
|
|
test: 'Debug System',
|
|
status: 'success',
|
|
message: 'Debug system working'
|
|
});
|
|
} catch (error) {
|
|
results.push({
|
|
test: 'Debug System',
|
|
status: MARKITECT_STRICT_MODE ? 'error' : 'warning',
|
|
message: `Debug system failed: ${error.message}`
|
|
});
|
|
}
|
|
|
|
// Test 3: Strict Mode Detection
|
|
results.push({
|
|
test: 'Strict Mode Detection',
|
|
status: 'success',
|
|
message: `Strict mode is ${MARKITECT_STRICT_MODE ? 'ENABLED' : 'DISABLED'}`
|
|
});
|
|
|
|
// Render results
|
|
testOutput.innerHTML = results.map(result => {
|
|
const statusClass = `test-${result.status}`;
|
|
const icon = result.status === 'success' ? '✅' : result.status === 'error' ? '❌' : '⚠️';
|
|
return `
|
|
<div class="test-status ${statusClass}">
|
|
${icon} <strong>${result.test}:</strong> ${result.message}
|
|
</div>
|
|
`;
|
|
}).join('');
|
|
|
|
console.log('✅ Markitect initialization complete');
|
|
}
|
|
};
|
|
|
|
// Initialize when ready
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
setTimeout(() => MarkitectMain.initialize(), 100);
|
|
});
|
|
} else {
|
|
setTimeout(() => MarkitectMain.initialize(), 100);
|
|
}
|
|
</script>
|
|
|
|
<!-- Test button -->
|
|
<script>
|
|
window.addEventListener('load', function() {
|
|
const button = document.createElement('button');
|
|
button.textContent = '🧪 Test Error Handling';
|
|
button.style.cssText = 'position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); padding: 10px 20px; background: #dc3545; color: white; border: none; border-radius: 5px; cursor: pointer; font-weight: bold;';
|
|
|
|
button.addEventListener('click', function() {
|
|
try {
|
|
// This should trigger different behavior in strict vs normal mode
|
|
if (window.statusControl) {
|
|
window.statusControl.safeOperation(() => {
|
|
throw new Error('Intentional test error for demonstration');
|
|
}, 'Fallback value', 'ErrorTest');
|
|
}
|
|
} catch (error) {
|
|
alert(`Strict mode caught error: ${error.message}`);
|
|
}
|
|
});
|
|
|
|
document.body.appendChild(button);
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |