""" TestDrive JSUI Rendering Engine Plugin Independent JavaScript UI rendering engine for Markitect edit mode. Designed for standalone development and testing of JavaScript components. """ from pathlib import Path from typing import Dict, List, Optional import json from .base import PluginMetadata, PluginType from .rendering import RenderingEnginePlugin, RenderingConfig class TestDriveJSUIEngine(RenderingEnginePlugin): """TestDrive JavaScript UI rendering engine.""" def __init__(self): super().__init__() self._metadata = PluginMetadata( name="testdrive-jsui", version="1.0.0", description="Independent JavaScript UI engine for markdown editing", author="Markitect Team", plugin_type=PluginType.RENDERING ) @property def metadata(self) -> PluginMetadata: """Return plugin metadata.""" return self._metadata def get_supported_modes(self) -> List[str]: """Support edit and view modes.""" return ["edit", "view"] def get_required_assets(self) -> Dict[str, List[str]]: """Define required JavaScript, CSS, and other assets.""" 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", "static/js/controls/control-base.js", "static/js/controls/contents-control.js", "static/js/controls/status-control.js", "static/js/controls/debug-control.js", "static/js/controls/edit-control.js", "static/js/config-loader.js", "static/js/main-updated.js" ], "css": [ "static/css/editor.css", "static/css/controls.css", "static/css/themes/github.css" ], "images": [ "images/icons/edit.png", "images/icons/save.png", "images/icons/reset.png" ], "external": [ "https://cdn.jsdelivr.net/npm/marked/marked.min.js" ] } 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" if template_path.exists(): return template_path # Fallback to current template location return Path(__file__).parent.parent / "templates" / "edit-mode-fixed.html" def render_document(self, content: str, mode: str, config: RenderingConfig) -> str: """ Render markdown content using TestDrive JSUI. Args: content: Markdown content to render mode: Rendering mode ('edit' or 'view') config: Rendering configuration Returns: Complete HTML document """ if not self.validate_mode(mode): raise ValueError(f"Mode '{mode}' not supported by TestDrive JSUI engine") # Get template template_path = self.get_template_path() if not template_path or not template_path.exists(): raise FileNotFoundError(f"Template not found: {template_path}") # Load template content with open(template_path, 'r', encoding='utf-8') as f: template_content = f.read() # Generate asset URLs assets = self.get_required_assets() js_scripts = [] css_links = [] # External dependencies for external_url in assets.get("external", []): js_scripts.append(f'') # Plugin assets for js_file in assets.get("js", []): url = config.get_asset_url(self.metadata.name, js_file) js_scripts.append(f'') for css_file in assets.get("css", []): url = config.get_asset_url(self.metadata.name, css_file) css_links.append(f'') # Generate configuration JSON for JavaScript js_config = { "markdownContent": content, "markdownContentWithDogtag": content, # Could add dogtag here "dogtagContent": "", "mode": mode, "theme": "github", "keyboardShortcuts": True, "autosave": False, "sections": True, "originalFilename": "document", "base64References": {}, "version": f"Markitect {self.metadata.version}", "repoName": "Markitect" } # Basic fallback content rendering (simple markdown to HTML) fallback_html = self._render_markdown_fallback(content) # Replace template placeholders using safe substitution html_content = template_content html_content = html_content.replace("{title}", "TestDrive JSUI Document") html_content = html_content.replace("{version}", f"Markitect {self.metadata.version}") html_content = html_content.replace("{mode_class}", f"markitect-{mode}-mode") html_content = html_content.replace("{css_content}", "\n".join(css_links)) html_content = html_content.replace("{js_scripts}", "\n".join(js_scripts)) html_content = html_content.replace("{config_json}", json.dumps(js_config, indent=2)) html_content = html_content.replace("{fallback_content}", fallback_html) return html_content def _render_markdown_fallback(self, content: str) -> str: """ Render basic markdown to HTML for fallback content. Args: content: Markdown content Returns: Basic HTML rendering """ import re # Very basic markdown to HTML conversion for fallback html = content # Headers html = re.sub(r'^# (.+)$', r'

\1

', html, flags=re.MULTILINE) html = re.sub(r'^## (.+)$', r'

\1

', html, flags=re.MULTILINE) html = re.sub(r'^### (.+)$', r'

\1

', html, flags=re.MULTILINE) # Paragraphs html = re.sub(r'\n\n', '

', html) html = re.sub(r'\n', '
', html) # Wrap in paragraph tags if html.strip() and not html.startswith('<'): html = f'

{html}

' return html def get_development_config(self, source_dir: Path) -> RenderingConfig: """ Get development configuration for standalone testing. Args: source_dir: Path to testdrive-jsui source directory Returns: Development rendering configuration """ return RenderingConfig( asset_base_url=".", # Serve from current directory in dev development_mode=True, plugin_source_dirs={self.metadata.name: source_dir} ) def create_standalone_test_document(self, test_content: str, output_path: Path) -> None: """ Create a standalone HTML document for testing. Args: test_content: Markdown content to test with output_path: Where to write the test HTML file """ config = self.get_development_config(output_path.parent) html_content = self.render_document(test_content, "edit", config) output_path.write_text(html_content, encoding='utf-8') print(f"✅ Created standalone test document: {output_path}")