feat: complete CLI integration with plugin system

**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>
This commit is contained in:
2025-11-14 08:47:30 +01:00
parent 8ef356af57
commit 8f1cc0faf9
9 changed files with 1268 additions and 23 deletions

121
test_cli_simple.py Normal file
View File

@@ -0,0 +1,121 @@
#!/usr/bin/env python3
"""
Test CLI plugin integration by directly calling the core logic
"""
import sys
from pathlib import Path
# Add current directory to path for imports
sys.path.insert(0, str(Path(__file__).parent))
def test_cli_integration():
"""Test CLI integration logic without Click framework."""
print("🧪 Testing CLI Plugin Integration Logic")
print("=" * 50)
try:
# Import required components
from markitect.plugins import PluginManager, RenderingEngineManager, RenderingConfig
# Test input
input_file = "test_cli_plugin.md"
output_file = "/tmp/test_cli_integration.html"
if not Path(input_file).exists():
print(f"❌ Test file {input_file} not found")
return False
# Read markdown content
content = Path(input_file).read_text(encoding='utf-8')
print(f"📄 Read test content ({len(content)} characters)")
# Test 1: Plugin system initialization
print("\n1⃣ Initializing plugin system...")
plugin_manager = PluginManager()
rendering_manager = RenderingEngineManager(plugin_manager)
print(" ✅ Plugin system initialized")
# Test 2: Engine selection logic (same as CLI)
engine_name = None
edit_mode = True
# Default engine selection (copied from CLI logic)
if engine_name is None:
if edit_mode:
engine_name = 'testdrive-jsui' # Default to testdrive-jsui for interactive modes
else:
engine_name = 'standard' # Use standard CleanDocumentManager for non-interactive
print(f" 🎯 Selected engine: {engine_name}")
# Test 3: Engine loading
print(f"\n2⃣ Loading rendering engine '{engine_name}'...")
rendering_engine = rendering_manager.get_engine(engine_name)
if rendering_engine is None:
print(f" ❌ Rendering engine '{engine_name}' not found")
return False
print(f" ✅ Engine loaded: {rendering_engine.metadata.name}")
print(f" 📝 Description: {rendering_engine.metadata.description}")
print(f" 🎯 Supported modes: {rendering_engine.get_supported_modes()}")
# Test 4: Mode validation
current_mode = 'edit'
if not rendering_engine.validate_mode(current_mode):
print(f" ❌ Engine doesn't support mode '{current_mode}'")
return False
print(f" ✅ Mode '{current_mode}' is supported")
# Test 5: Rendering configuration
print(f"\n3⃣ Setting up rendering configuration...")
render_config = RenderingConfig(
asset_base_url="_markitect",
development_mode=False, # Production deployment for CLI usage
output_directory=Path(output_file).parent
)
print(f" ✅ Configuration created")
print(f" 📁 Output directory: {render_config.output_directory}")
print(f" 🔗 Asset base URL: {render_config.asset_base_url}")
# Test 6: Document rendering
print(f"\n4⃣ Rendering document...")
html_content = rendering_engine.render_document(content, current_mode, render_config)
print(f" ✅ Document rendered ({len(html_content):,} characters)")
# Test 7: Output writing
print(f"\n5⃣ Writing output file...")
Path(output_file).write_text(html_content, encoding='utf-8')
output_size = Path(output_file).stat().st_size
print(f" ✅ Output written: {output_file} ({output_size:,} bytes)")
# Test 8: Verification
print(f"\n6⃣ Verifying output...")
if Path(output_file).exists() and output_size > 0:
print(f" ✅ Output file exists and has content")
print(f" 🌐 Open in browser: file://{Path(output_file).absolute()}")
else:
print(f" ❌ Output file missing or empty")
return False
print(f"\n🎉 CLI integration test completed successfully!")
print(f"\n📊 Summary:")
print(f" Engine: {engine_name}")
print(f" Mode: {current_mode}")
print(f" Input: {input_file} ({len(content)} chars)")
print(f" Output: {output_file} ({output_size:,} bytes)")
return True
except Exception as e:
print(f"❌ CLI integration test failed: {e}")
import traceback
traceback.print_exc()
return False
if __name__ == "__main__":
success = test_cli_integration()
sys.exit(0 if success else 1)