**CLI Integration:** - Added --engine parameter to md-render command - Default engine selection: testdrive-jsui for edit/insert, standard for view - Graceful fallback to standard rendering when plugin unavailable - Engine validation and mode compatibility checking **Plugin Discovery:** - Enhanced RenderingEngineManager with builtin plugin registration - Automatic discovery and registration of testdrive-jsui engine - Support for both plugin system discovery and direct registration **Configuration Management:** - Production-ready RenderingConfig for CLI usage - Asset deployment to _markitect/plugins/ structure - Configurable asset base URLs and deployment strategies **Testing Infrastructure:** - Comprehensive test suite for plugin discovery - CLI integration testing without Click framework dependencies - Complete scenario testing (default, explicit, fallback, unknown engines) - Integration verification scripts **Documentation:** - Complete PLUGIN_SYSTEM.md documentation - Architecture overview and development workflows - JavaScript-first development guide - Asset management and deployment strategies - CLI usage examples and troubleshooting guide **Key Features:** - `markitect md-render --edit` now uses testdrive-jsui by default - `markitect md-render --engine testdrive-jsui --edit` for explicit selection - `markitect md-render --engine standard --edit` for legacy behavior - Automatic fallback with user-friendly error messages This completes the plugin infrastructure implementation, enabling independent JavaScript development with seamless CLI integration. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
131 lines
5.1 KiB
HTML
131 lines
5.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>{title}</title>
|
|
{css_content}
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"
|
|
onload="window.markitectMarkedLoaded = true"
|
|
onerror="window.markitectMarkedError = true"></script>
|
|
</head>
|
|
<body class="{mode_class}">
|
|
|
|
<div id="markdown-content"></div>
|
|
|
|
<!-- Configuration Data Interface - ONLY place where Python data enters JavaScript -->
|
|
<script id="markitect-config" type="application/json">{config_json}</script>
|
|
|
|
<!-- Pure Static JavaScript Components - Embedded inline to avoid path issues -->
|
|
<script>
|
|
{js_config_loader}
|
|
</script>
|
|
<script>
|
|
{js_debug_system}
|
|
</script>
|
|
<script>
|
|
{js_section_manager}
|
|
</script>
|
|
<script>
|
|
{js_debug_panel}
|
|
</script>
|
|
<script>
|
|
{js_document_controls}
|
|
</script>
|
|
<script>
|
|
{js_dom_renderer}
|
|
</script>
|
|
<script>
|
|
{js_control_base}
|
|
</script>
|
|
<script>
|
|
{js_contents_control}
|
|
</script>
|
|
<script>
|
|
{js_status_control}
|
|
</script>
|
|
<script>
|
|
{js_debug_control}
|
|
</script>
|
|
<script>
|
|
{js_edit_control}
|
|
</script>
|
|
<script>
|
|
{js_main}
|
|
</script>
|
|
|
|
<!-- Initialization Script -->
|
|
<script>
|
|
// Clean initialization - no Python-generated code!
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
console.log('🎯 DOM loaded, starting Markitect initialization...');
|
|
|
|
// Wait for configuration to be ready before initializing
|
|
if (window.markitectConfig) {
|
|
window.markitectConfig.waitForReady(function() {
|
|
console.log('🎯 Configuration ready, initializing ' + window.markitectConfig.mode + ' mode...');
|
|
|
|
// Initialize edit/insert capabilities
|
|
if (window.markitectConfig.isEditMode || window.markitectConfig.isInsertMode) {
|
|
try {
|
|
console.log('🚀 Initializing clean ' + window.markitectConfig.mode + ' capabilities...');
|
|
|
|
// Initialize main application
|
|
if (typeof MarkitectMain !== 'undefined' && MarkitectMain.initialize) {
|
|
MarkitectMain.initialize();
|
|
}
|
|
|
|
console.log('✅ Clean ' + window.markitectConfig.mode + ' mode active - click any section to edit');
|
|
} catch (error) {
|
|
console.error('❌ Clean ' + window.markitectConfig.mode + ' mode failed to initialize:', error);
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
console.error('❌ Configuration system not available');
|
|
}
|
|
|
|
// Check if modular components are being used for content rendering
|
|
if (typeof SectionManager !== 'undefined') {
|
|
console.log('✓ Modular components detected - using modular architecture');
|
|
return;
|
|
}
|
|
|
|
// Fallback content rendering if modular components failed
|
|
const contentDiv = document.getElementById('markdown-content');
|
|
if (contentDiv) {
|
|
if (typeof marked !== 'undefined') {
|
|
try {
|
|
const html = marked.parse(window.markitectConfig.markdownContentWithDogtag);
|
|
const htmlWithTargetBlank = html.replace(/<a href="([^"]*)"([^>]*)>/g, '<a href="$1" target="_blank"$2>');
|
|
contentDiv.innerHTML = htmlWithTargetBlank;
|
|
console.log('✓ Content rendered successfully with fallback');
|
|
} catch (error) {
|
|
contentDiv.innerHTML = '<p>Error rendering markdown: ' + error.message + '</p>';
|
|
console.error('Content rendering failed:', error.message);
|
|
}
|
|
} else {
|
|
// Basic fallback without marked.js
|
|
const fallbackHtml = window.markitectConfig.markdownContent
|
|
.replace(/^# (.*$)/gim, '<h1>$1</h1>')
|
|
.replace(/^## (.*$)/gim, '<h2>$1</h2>')
|
|
.replace(/^### (.*$)/gim, '<h3>$1</h3>')
|
|
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
|
|
.replace(/\*(.*?)\*/g, '<em>$1</em>')
|
|
.replace(/\n\n/g, '<br><br>')
|
|
.replace(/\n/g, '<br>');
|
|
contentDiv.innerHTML = '<div style="white-space: pre-wrap;">' + fallbackHtml + '</div>';
|
|
console.warn('Content rendered with basic fallback parser');
|
|
}
|
|
}
|
|
});
|
|
|
|
window.addEventListener('load', function() {
|
|
if (window.markitectMarkedError) {
|
|
console.error('CDN library failed to load - network or firewall blocking marked.js');
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |