feat: consolidate testdrive-jsui to capabilities and implement plugin self-declaration

## Major Changes
- Moved all testdrive-jsui assets from root to capabilities/testdrive-jsui/
- Consolidated directory structure: js/, static/css/, static/images/, static/templates/
- Implemented plugin self-declaration (get_plugin_source_dir, get_asset_paths)
- Removed hardcoded plugin discovery from rendering.py
- Updated all asset paths to be relative to capability root

## Architecture Improvements
- Single source of truth for all testdrive-jsui assets
- Plugin declares its own location (no hardcoded paths)
- Generic plugin discovery using hasattr check
- Clean separation: all JS in .js files, no code mixing
- Standalone capability ready for independent use

## Files Changed
- markitect/plugins/testdrive_jsui.py: Added self-declaration methods
- markitect/plugins/rendering.py: Removed hardcoded discovery
- capabilities/testdrive-jsui/README.md: Added standalone usage documentation
- Moved 17 asset files to consolidated structure
- Deleted obsolete /testdrive-jsui/ root directory

## Testing
- All 17 assets verified and working
- Tested via CLI: markitect md-render --engine testdrive-jsui
- Full document rendering successful

Prepares testdrive-jsui to become a git submodule with proper dependency management.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-15 23:42:54 +01:00
parent d0a1c91b8e
commit ab3f0db86f
41 changed files with 223 additions and 6073 deletions

View File

@@ -296,17 +296,21 @@ class RenderingEngineManager:
return deployed_assets
def _get_plugin_source_dir(self, engine_name: str) -> Optional[Path]:
"""Get the source directory for a plugin."""
if engine_name == 'testdrive-jsui':
# Look for testdrive-jsui directory relative to current directory
candidates = [
Path('testdrive-jsui'),
Path(__file__).parent.parent.parent / 'testdrive-jsui',
Path('.') / 'testdrive-jsui'
]
"""
Get the source directory for a plugin.
Uses plugin self-declaration if available, no hardcoded paths.
"""
engine = self.get_engine(engine_name)
if not engine:
return None
for candidate in candidates:
if candidate.exists() and candidate.is_dir():
return candidate
# Use plugin's self-declared source directory if available
if hasattr(engine, 'get_plugin_source_dir'):
try:
source_dir = engine.get_plugin_source_dir()
if source_dir and source_dir.exists():
return source_dir
except Exception as e:
print(f"⚠️ Error getting plugin source dir for {engine_name}: {e}")
return None