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

View File

@@ -35,21 +35,45 @@ class TestDriveJSUIEngine(RenderingEnginePlugin):
"""Support edit and view modes."""
return ["edit", "view"]
def get_plugin_source_dir(self) -> Path:
"""
Return the source directory for this plugin.
This allows the plugin to declare its own location.
"""
# Plugin is located in capabilities/testdrive-jsui/
return Path(__file__).parent.parent.parent / "capabilities" / "testdrive-jsui"
def get_asset_paths(self) -> Dict[str, Path]:
"""
Return paths to asset directories relative to plugin source.
This allows flexible asset organization within the plugin.
"""
base = self.get_plugin_source_dir()
return {
'js': base / 'js',
'css': base / 'static' / 'css',
'images': base / 'static' / 'images',
'templates': base / 'static' / 'templates',
}
def get_required_assets(self) -> Dict[str, List[str]]:
"""Define required JavaScript, CSS, and other assets."""
"""
Define required JavaScript, CSS, and other assets.
All paths are relative to the plugin source directory.
"""
return {
"js": [
"static/js/core/debug-system.js",
"static/js/core/section-manager.js",
"static/js/components/debug-panel.js",
"static/js/components/dom-renderer.js",
"../capabilities/testdrive-jsui/js/controls/control-base.js",
"../capabilities/testdrive-jsui/js/controls/contents-control.js",
"../capabilities/testdrive-jsui/js/controls/status-control.js",
"../capabilities/testdrive-jsui/js/controls/debug-control.js",
"../capabilities/testdrive-jsui/js/controls/edit-control.js",
"static/js/config-loader.js",
"static/js/main-updated.js"
"js/core/debug-system.js",
"js/core/section-manager.js",
"js/components/debug-panel.js",
"js/components/dom-renderer.js",
"js/controls/control-base.js",
"js/controls/contents-control.js",
"js/controls/status-control.js",
"js/controls/debug-control.js",
"js/controls/edit-control.js",
"js/config-loader.js",
"js/main-updated.js"
],
"css": [
"static/css/editor.css",
@@ -57,9 +81,9 @@ class TestDriveJSUIEngine(RenderingEnginePlugin):
"static/css/themes/github.css"
],
"images": [
"images/icons/edit.png",
"images/icons/save.png",
"images/icons/reset.png"
"static/images/icons/edit.png",
"static/images/icons/save.png",
"static/images/icons/reset.png"
],
"external": [
"https://cdn.jsdelivr.net/npm/marked/marked.min.js"
@@ -68,15 +92,16 @@ class TestDriveJSUIEngine(RenderingEnginePlugin):
def get_template_path(self) -> Optional[Path]:
"""Return path to the HTML template."""
# Look for template in plugin directory structure
plugin_dir = Path(__file__).parent.parent.parent / "testdrive-jsui"
template_path = plugin_dir / "templates" / "index.html"
# Template is in the plugin's static/templates directory
template_path = self.get_asset_paths()['templates'] / "index.html"
if template_path.exists():
return template_path
# Fallback to current template location
return Path(__file__).parent.parent / "templates" / "edit-mode-fixed.html"
raise FileNotFoundError(
f"Template not found at {template_path}. "
f"Ensure testdrive-jsui is properly installed in capabilities/"
)
def render_document(self,
content: str,