Files
markitect-main/testdrive-jsui/static/js/config-loader.js
tegwick 8ef356af57 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>
2025-11-14 06:49:41 +01:00

168 lines
4.8 KiB
JavaScript

/**
* Configuration Loader - Clean interface between Python and JavaScript
*
* This module provides the ONLY interface for Python-generated data.
* All dynamic data from Python must be passed through this JSON configuration.
*/
class MarkitectConfig {
constructor() {
this.config = null;
this.loaded = false;
// Simple immediate loading - if script is loaded, DOM is ready
this.loadConfig();
}
loadConfig() {
try {
const configElement = document.getElementById('markitect-config');
if (!configElement) {
throw new Error('Markitect configuration not found - missing markitect-config script element');
}
this.config = JSON.parse(configElement.textContent);
this.loaded = true;
console.log('✅ Markitect configuration loaded successfully');
// Validate required fields
this.validateConfig();
} catch (error) {
console.error('❌ Failed to load Markitect configuration:', error);
this.config = this.getDefaultConfig();
}
}
validateConfig() {
const required = ['markdownContent', 'mode'];
const missing = required.filter(key => !(key in this.config));
if (missing.length > 0) {
console.warn('⚠️ Missing required config fields:', missing);
}
}
getDefaultConfig() {
return {
markdownContent: '# Default Content\n\nConfiguration failed to load.',
markdownContentWithDogtag: '# Default Content\n\nConfiguration failed to load.',
dogtagContent: '',
mode: 'edit',
theme: 'github',
keyboardShortcuts: true,
autosave: false,
sections: true,
originalFilename: 'document',
version: 'Markitect v0.8.1',
repoName: 'Markitect',
base64References: {}
};
}
// Getter methods for clean access
get markdownContent() {
return this.config.markdownContent || '';
}
get markdownContentWithDogtag() {
return this.config.markdownContentWithDogtag || this.markdownContent;
}
get dogtagContent() {
return this.config.dogtagContent || '';
}
get mode() {
return this.config.mode || 'edit';
}
get isEditMode() {
return this.mode === 'edit';
}
get isInsertMode() {
return this.mode === 'insert';
}
get theme() {
return this.config.theme || 'github';
}
get originalFilename() {
return this.config.originalFilename || 'document';
}
get version() {
return this.config.version || 'Markitect v0.8.1';
}
get repoName() {
return this.config.repoName || 'Markitect';
}
get keyboardShortcuts() {
return this.config.keyboardShortcuts !== false;
}
get base64References() {
return this.config.base64References || {};
}
get restrictedHeadingLevels() {
return this.config.restrictedHeadingLevels || [1, 2, 3];
}
// Check if config is ready for access
isReady() {
return this.loaded && this.config !== null;
}
// Wait for config to be ready
waitForReady(callback, maxWait = 5000) {
const startTime = Date.now();
const checkReady = () => {
if (this.isReady()) {
callback();
} else if (Date.now() - startTime < maxWait) {
setTimeout(checkReady, 50);
} else {
console.error('❌ Configuration loading timeout after', maxWait, 'ms');
callback(); // Call anyway with default config
}
};
checkReady();
}
// Get full editor configuration object
getEditorConfig() {
if (!this.isReady()) {
console.warn('⚠️ Configuration not ready, using defaults');
return this.getDefaultConfig();
}
return {
mode: this.mode,
theme: this.theme,
keyboardShortcuts: this.keyboardShortcuts,
autosave: this.config.autosave || false,
sections: this.config.sections !== false,
originalFilename: this.originalFilename,
version: this.version,
repoName: this.repoName,
restrictedHeadingLevels: this.restrictedHeadingLevels
};
}
}
// Global configuration instance
window.markitectConfig = new MarkitectConfig();
// Legacy compatibility - expose common config values globally
window.editorConfig = window.markitectConfig.getEditorConfig();
window.markitectBase64References = window.markitectConfig.base64References;
// Export for module use
if (typeof module !== 'undefined' && module.exports) {
module.exports = MarkitectConfig;
}