Added comprehensive plugin system for independent JavaScript UI development: **Plugin Infrastructure:** - Extended existing MarkiTect plugin system with RenderingEnginePlugin base class - Added RENDERING plugin type to PluginType enum - Created RenderingConfig for asset management and deployment - Implemented RenderingEngineManager for plugin discovery and lifecycle **TestDrive JSUI Plugin:** - Extracted JavaScript UI components to independent testdrive-jsui plugin - Created standalone development environment (no Python required) - Implemented compass-positioned control panels (NW, NE, E, SE) - Added clean JSON configuration interface for Python↔JavaScript data transfer **Asset Management:** - Development mode: serve assets directly from plugin source directory - Production mode: deploy to _markitect/plugins/[plugin-name]/ structure - Configurable asset URLs and deployment strategies - Support for external dependencies (CDN resources) **Standalone Development:** - testdrive-jsui/test.html for browser-based development - Package.json with npm scripts for development server - Complete separation of JavaScript development from Python environment - Hot reload and standard web development workflow **Integration Demo:** - demo_plugin_integration.py showcasing all plugin capabilities - Standalone, plugin discovery, production deployment examples - Asset URL generation for different deployment modes This enables JavaScript-first development while maintaining clean integration with the MarkiTect Python ecosystem. Developers can now work on UI components independently using standard web development tools and workflows. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
212 lines
6.4 KiB
Python
212 lines
6.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Demo script showing TestDrive JSUI plugin integration with Markitect
|
|
|
|
This script demonstrates:
|
|
1. Plugin discovery and registration
|
|
2. Asset management and deployment
|
|
3. Standalone development vs production rendering
|
|
4. Clean separation between Python and JavaScript
|
|
"""
|
|
|
|
from pathlib import Path
|
|
import json
|
|
|
|
# Import the new plugin system
|
|
from markitect.plugins import (
|
|
PluginManager,
|
|
RenderingEngineManager,
|
|
RenderingConfig
|
|
)
|
|
from markitect.plugins.testdrive_jsui import TestDriveJSUIEngine
|
|
|
|
|
|
def demo_standalone_development():
|
|
"""Demo standalone development workflow."""
|
|
print("🧪 Demonstrating Standalone Development Workflow")
|
|
print("=" * 50)
|
|
|
|
# Initialize the TestDrive JSUI engine directly
|
|
engine = TestDriveJSUIEngine()
|
|
|
|
# Read test content
|
|
test_content_path = Path("testdrive-jsui/test-documents/sample.md")
|
|
if test_content_path.exists():
|
|
test_content = test_content_path.read_text()
|
|
else:
|
|
test_content = "# Demo Content\n\nThis is demo content for testing."
|
|
|
|
# Create standalone test document
|
|
output_path = Path("/tmp/testdrive_standalone_demo.html")
|
|
|
|
print(f"📄 Creating standalone test document: {output_path}")
|
|
|
|
try:
|
|
engine.create_standalone_test_document(test_content, output_path)
|
|
print(f"✅ Success! Open in browser: file://{output_path}")
|
|
except Exception as e:
|
|
print(f"❌ Error creating standalone document: {e}")
|
|
|
|
return engine
|
|
|
|
|
|
def demo_plugin_discovery():
|
|
"""Demo plugin discovery through the main system."""
|
|
print("\n🔍 Demonstrating Plugin Discovery")
|
|
print("=" * 50)
|
|
|
|
# Initialize plugin manager
|
|
plugin_manager = PluginManager()
|
|
|
|
print("📋 Discovering all plugins...")
|
|
all_plugins = plugin_manager.discover_plugins()
|
|
|
|
# Show all discovered plugins
|
|
for plugin_name, plugin_info in all_plugins.items():
|
|
print(f" 🔌 {plugin_name}: {plugin_info.get('type', 'unknown')}")
|
|
|
|
# Initialize rendering engine manager
|
|
rendering_manager = RenderingEngineManager(plugin_manager)
|
|
|
|
print("\n🎨 Available rendering engines:")
|
|
for engine_name in rendering_manager.list_engines():
|
|
engine = rendering_manager.get_engine(engine_name)
|
|
if engine:
|
|
print(f" 🎯 {engine_name}: modes={engine.get_supported_modes()}")
|
|
|
|
return rendering_manager
|
|
|
|
|
|
def demo_production_deployment():
|
|
"""Demo production deployment with asset management."""
|
|
print("\n🚀 Demonstrating Production Deployment")
|
|
print("=" * 50)
|
|
|
|
# Create production configuration
|
|
output_dir = Path("/tmp/demo_production_output")
|
|
output_dir.mkdir(exist_ok=True)
|
|
|
|
config = RenderingConfig(
|
|
asset_base_url="_markitect",
|
|
development_mode=False,
|
|
output_directory=output_dir
|
|
)
|
|
|
|
# Initialize engine
|
|
engine = TestDriveJSUIEngine()
|
|
|
|
# Demo content
|
|
demo_content = """# Production Demo
|
|
|
|
This demonstrates production deployment of the TestDrive JSUI plugin.
|
|
|
|
## Features
|
|
- Asset deployment to `_markitect/plugins/testdrive-jsui/`
|
|
- Production-ready HTML generation
|
|
- Clean JavaScript-Python separation
|
|
|
|
## Testing
|
|
Open the generated HTML file to test the production deployment.
|
|
"""
|
|
|
|
print(f"📁 Output directory: {output_dir}")
|
|
print(f"🔧 Asset base URL: {config.asset_base_url}")
|
|
|
|
# Render document
|
|
try:
|
|
html_content = engine.render_document(demo_content, "edit", config)
|
|
|
|
# Save to output directory
|
|
output_file = output_dir / "demo_production.html"
|
|
output_file.write_text(html_content)
|
|
|
|
print(f"✅ Production document created: {output_file}")
|
|
print(f"🌐 Open in browser: file://{output_file}")
|
|
|
|
# Show asset requirements
|
|
assets = engine.get_required_assets()
|
|
print(f"\n📦 Required assets:")
|
|
for asset_type, asset_list in assets.items():
|
|
print(f" {asset_type}: {len(asset_list)} files")
|
|
for asset in asset_list[:3]: # Show first 3
|
|
print(f" - {asset}")
|
|
if len(asset_list) > 3:
|
|
print(f" ... and {len(asset_list) - 3} more")
|
|
|
|
except Exception as e:
|
|
print(f"❌ Error in production deployment: {e}")
|
|
|
|
return output_dir
|
|
|
|
|
|
def demo_asset_url_generation():
|
|
"""Demo asset URL generation for different modes."""
|
|
print("\n🔗 Demonstrating Asset URL Generation")
|
|
print("=" * 50)
|
|
|
|
engine = TestDriveJSUIEngine()
|
|
|
|
# Development configuration
|
|
dev_config = RenderingConfig(
|
|
asset_base_url=".",
|
|
development_mode=True,
|
|
plugin_source_dirs={
|
|
"testdrive-jsui": Path("testdrive-jsui")
|
|
}
|
|
)
|
|
|
|
# Production configuration
|
|
prod_config = RenderingConfig(
|
|
asset_base_url="_markitect",
|
|
development_mode=False
|
|
)
|
|
|
|
sample_assets = ["static/js/main.js", "static/css/editor.css", "images/icon.png"]
|
|
|
|
print("Development URLs:")
|
|
for asset in sample_assets:
|
|
url = dev_config.get_asset_url("testdrive-jsui", asset)
|
|
print(f" {asset} → {url}")
|
|
|
|
print("\nProduction URLs:")
|
|
for asset in sample_assets:
|
|
url = prod_config.get_asset_url("testdrive-jsui", asset)
|
|
print(f" {asset} → {url}")
|
|
|
|
# Show JSON config generation
|
|
print(f"\nDevelopment JSON config:")
|
|
print(dev_config.to_json_config("testdrive-jsui"))
|
|
|
|
|
|
def main():
|
|
"""Run all demo workflows."""
|
|
print("🎯 TestDrive JSUI Plugin Integration Demo")
|
|
print("🔬 Demonstrating JavaScript-first development approach")
|
|
print("🏗️ Clean separation between Python and JavaScript\n")
|
|
|
|
try:
|
|
# Demo workflows
|
|
engine = demo_standalone_development()
|
|
rendering_manager = demo_plugin_discovery()
|
|
output_dir = demo_production_deployment()
|
|
demo_asset_url_generation()
|
|
|
|
print(f"\n✅ All demos completed successfully!")
|
|
print(f"🔬 Standalone test: testdrive-jsui/test.html")
|
|
print(f"📄 Generated files in: {output_dir}")
|
|
|
|
# Show next steps
|
|
print(f"\n📚 Next Steps:")
|
|
print(f" 1. Open testdrive-jsui/test.html in browser for standalone dev")
|
|
print(f" 2. Start development server: cd testdrive-jsui && python -m http.server 8080")
|
|
print(f" 3. Integrate with markitect md-render command")
|
|
print(f" 4. Add more rendering engines to the plugin system")
|
|
|
|
except Exception as e:
|
|
print(f"❌ Demo failed: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |