feat: implement plugin infrastructure for rendering engines
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>
This commit is contained in:
70
testdrive-jsui/static/js/controls/edit-control.js
Normal file
70
testdrive-jsui/static/js/controls/edit-control.js
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Edit Control - Document editing tools and actions
|
||||
* Implements the Robustness Principle with Fail Fast mode support
|
||||
*/
|
||||
|
||||
class EditControl {
|
||||
constructor() {
|
||||
this.control = Object.create(Control);
|
||||
this.control.config = {
|
||||
icon: '✏️',
|
||||
title: 'Edit',
|
||||
className: 'edit-control',
|
||||
defaultContent: 'Document editing tools',
|
||||
ariaLabel: 'Edit Control',
|
||||
position: 'e'
|
||||
};
|
||||
|
||||
// Bind methods to control
|
||||
this.control.buildContent = () => {
|
||||
const content = this.control.element.querySelector('.control-content');
|
||||
|
||||
content.innerHTML = `
|
||||
<div style="padding: 1rem; font-size: 0.8rem;">
|
||||
<h4 style="margin-top: 0;">Edit Tools</h4>
|
||||
|
||||
<div style="margin-bottom: 1rem;">
|
||||
<button onclick="window.print()"
|
||||
style="width: 100%; padding: 0.5rem; margin-bottom: 0.5rem; background: #28a745; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 0.8rem;">
|
||||
🖨️ Print Document
|
||||
</button>
|
||||
|
||||
<button onclick="navigator.clipboard?.writeText(window.location.href) || prompt('Copy this URL:', window.location.href)"
|
||||
style="width: 100%; padding: 0.5rem; margin-bottom: 0.5rem; background: #17a2b8; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 0.8rem;">
|
||||
📋 Copy Link
|
||||
</button>
|
||||
|
||||
<button onclick="window.scrollTo({top: 0, behavior: 'smooth'})"
|
||||
style="width: 100%; padding: 0.5rem; margin-bottom: 0.5rem; background: #6c757d; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 0.8rem;">
|
||||
⬆️ Scroll to Top
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 1rem; font-size: 0.7rem; color: #666; border-top: 1px solid #dee2e6; padding-top: 0.5rem;">
|
||||
<strong>Page Info:</strong><br>
|
||||
Title: ${document.title}<br>
|
||||
Words: ~${(document.body.textContent || '').split(/\\s+/).filter(w => w.length > 0).length}<br>
|
||||
Modified: ${document.lastModified}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
this.control.isExpanded = true;
|
||||
};
|
||||
|
||||
this.control.toggle = () => {
|
||||
if (this.control.isExpanded) {
|
||||
this.control.element.querySelector('.control-content').style.display = 'none';
|
||||
this.control.isExpanded = false;
|
||||
} else {
|
||||
this.control.buildContent();
|
||||
this.control.element.querySelector('.control-content').style.display = 'block';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
createControl() {
|
||||
return this.control.createControl();
|
||||
}
|
||||
}
|
||||
|
||||
window.EditControl = EditControl;
|
||||
Reference in New Issue
Block a user