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

171
test_cli_integration.py Normal file
View File

@@ -0,0 +1,171 @@
#!/usr/bin/env python3
"""
Test CLI integration with plugin system
"""
import sys
from pathlib import Path
# Add current directory to path for imports
sys.path.insert(0, str(Path(__file__).parent))
def test_plugin_cli_integration():
"""Test the CLI integration with plugin system."""
# Import the command function
from markitect.plugins.builtin.markdown_commands import md_render_command
import click
# Create a mock context
class MockContext:
def __init__(self):
self.obj = {}
self.resilient_parsing = False
self.allow_extra_args = False
self.allow_interspersed_args = True
self.ignore_unknown_options = False
self.help_option_names = ['--help']
self.token_normalize_func = None
self.color = None
self.terminal_width = None
self.max_content_width = None
ctx = MockContext()
# Test parameters
input_file = "test_cli_plugin.md"
output = "/tmp/test_cli_plugin_default.html"
print("🧪 Testing CLI Plugin Integration")
print("=" * 50)
try:
# Test 1: Default engine (should use testdrive-jsui for edit mode)
print("\n1⃣ Testing default engine for edit mode...")
md_render_command(
ctx=ctx,
input_file=input_file,
output=output,
theme=None,
css=None,
edit=True,
insert=False,
engine=None, # Should default to testdrive-jsui
editor_theme='github',
keyboard_shortcuts=True,
use_publication_dir=False,
dont_use_publication_dir=False,
nodogtag=False,
ship_assets=None,
no_ship_assets=False,
verbose=True,
silent=False,
image_max_width=None,
image_max_height=None
)
print("✅ Default engine test completed")
# Test 2: Explicit testdrive-jsui engine
print("\n2⃣ Testing explicit testdrive-jsui engine...")
output2 = "/tmp/test_cli_plugin_explicit.html"
md_render_command(
ctx=ctx,
input_file=input_file,
output=output2,
theme=None,
css=None,
edit=True,
insert=False,
engine='testdrive-jsui', # Explicit engine
editor_theme='github',
keyboard_shortcuts=True,
use_publication_dir=False,
dont_use_publication_dir=False,
nodogtag=False,
ship_assets=None,
no_ship_assets=False,
verbose=True,
silent=False,
image_max_width=None,
image_max_height=None
)
print("✅ Explicit engine test completed")
# Test 3: Standard engine fallback
print("\n3⃣ Testing standard engine fallback...")
output3 = "/tmp/test_cli_plugin_standard.html"
md_render_command(
ctx=ctx,
input_file=input_file,
output=output3,
theme=None,
css=None,
edit=True,
insert=False,
engine='standard', # Explicit standard engine
editor_theme='github',
keyboard_shortcuts=True,
use_publication_dir=False,
dont_use_publication_dir=False,
nodogtag=False,
ship_assets=None,
no_ship_assets=False,
verbose=True,
silent=False,
image_max_width=None,
image_max_height=None
)
print("✅ Standard engine test completed")
# Test 4: Unknown engine (should fallback)
print("\n4⃣ Testing unknown engine (should fallback to standard)...")
output4 = "/tmp/test_cli_plugin_unknown.html"
md_render_command(
ctx=ctx,
input_file=input_file,
output=output4,
theme=None,
css=None,
edit=True,
insert=False,
engine='unknown-engine', # Unknown engine
editor_theme='github',
keyboard_shortcuts=True,
use_publication_dir=False,
dont_use_publication_dir=False,
nodogtag=False,
ship_assets=None,
no_ship_assets=False,
verbose=True,
silent=False,
image_max_width=None,
image_max_height=None
)
print("✅ Unknown engine test completed")
print("\n🎉 All CLI integration tests completed!")
print("\nGenerated files:")
for output_file in [output, output2, output3, output4]:
if Path(output_file).exists():
size = Path(output_file).stat().st_size
print(f" 📄 {output_file} ({size:,} bytes)")
except Exception as e:
print(f"❌ CLI integration test failed: {e}")
import traceback
traceback.print_exc()
return False
return True
if __name__ == "__main__":
success = test_plugin_cli_integration()
sys.exit(0 if success else 1)