/** * HTML Generator - Create standalone or external-resources HTML files * * Generates complete HTML documents that use TestDrive-JSUI with two modes: * 1. Standalone (default): All JS/CSS embedded inline * 2. External: References external files under _jsui/ directory * * Usage: * ```javascript * const generator = new HTMLGenerator({ * title: 'My Document', * markdown: '# Hello World', * standalone: true // or false for external mode * }); * * const html = generator.generate(); * ``` */ class HTMLGenerator { constructor(options = {}) { this.options = { title: options.title || 'TestDrive-JSUI Editor', description: options.description || 'Interactive markdown editor', markdown: options.markdown || '# Welcome\n\nStart editing...', mode: options.mode || 'edit', // 'edit' or 'view' theme: options.theme || 'github', standalone: options.standalone !== false, // default true controls: { editControl: options.controls?.editControl !== false, statusControl: options.controls?.statusControl !== false, contentsControl: options.controls?.contentsControl !== false, debugControl: options.controls?.debugControl || false }, shortcuts: options.shortcuts !== false, autosave: options.autosave || false, baseUrl: options.baseUrl || '_jsui', // For external mode includeMarkedJS: options.includeMarkedJS !== false // Include marked.js CDN }; } /** * Generate HTML document */ generate() { if (this.options.standalone) { return this.generateStandalone(); } else { return this.generateExternal(); } } /** * Generate standalone HTML with all resources embedded */ generateStandalone() { return ` ${this.escapeHtml(this.options.title)} ${this.generateInlineStyles()} ${this.generateHeader()} ${this.generateContainer()} ${this.generateMarkedJS()} ${this.generateInlineScripts()} ${this.generateInitScript()} `; } /** * Generate HTML with external resource references */ generateExternal() { const baseUrl = this.options.baseUrl; return ` ${this.escapeHtml(this.options.title)} ${this.generateHeader()} ${this.generateContainer()} ${this.generateMarkedJS()} ${this.generateInitScript()} `; } /** * Generate header section */ generateHeader() { if (!this.options.description) { return ''; } return `

${this.escapeHtml(this.options.title)}

${this.escapeHtml(this.options.description)}

`; } /** * Generate container div */ generateContainer() { return `
`; } /** * Generate marked.js CDN script */ generateMarkedJS() { if (!this.options.includeMarkedJS) { return ''; } return ` `; } /** * Generate inline styles for standalone mode */ generateInlineStyles() { return ` `; } /** * Generate inline JavaScript for standalone mode * * Note: In a real implementation, this would read and embed actual JS files. * For now, it provides a placeholder comment. */ generateInlineScripts() { return ` `; } /** * Generate initialization script */ generateInitScript() { const config = { container: '#editor-container', markdown: this.options.markdown, mode: this.options.mode, theme: this.options.theme, controls: this.options.controls, shortcuts: this.options.shortcuts, autosave: this.options.autosave }; return ` `; } /** * Escape HTML special characters */ escapeHtml(text) { const map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }; return text.replace(/[&<>"']/g, m => map[m]); } /** * Save generated HTML to file (Node.js only) */ saveToFile(filename) { if (typeof require === 'undefined') { throw new Error('saveToFile() requires Node.js environment'); } const fs = require('fs'); const html = this.generate(); fs.writeFileSync(filename, html, 'utf8'); return filename; } /** * Download generated HTML (browser only) */ download(filename = 'testdrive-jsui-editor.html') { const html = this.generate(); const blob = new Blob([html], { type: 'text/html' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = filename; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); } } // Export for module systems or attach to global if (typeof module !== 'undefined' && module.exports) { module.exports = HTMLGenerator; } else { window.HTMLGenerator = HTMLGenerator; }