UNPKG

@mseep/webgl-mcp

Version:

A Model Context Protocol server for analyzing and optimizing WebGL games

155 lines (135 loc) 4.68 kB
import { promises as fs } from 'fs'; import * as path from 'path'; export interface TemplateOptions { title?: string; loadingBar?: boolean; loadingText?: boolean; compression?: boolean; memoryLimit?: number; customStyles?: string; customScripts?: string[]; } export interface Template { name: string; description: string; options: TemplateOptions; defaults: TemplateOptions; } export class WebGLTemplateModifier { constructor(private templatesPath: string) {} public async modifyTemplate(options: TemplateOptions): Promise<void> { try { // Read the template HTML file const indexPath = path.join(this.templatesPath, 'index.html'); let html = await fs.readFile(indexPath, 'utf-8'); // Apply modifications based on options html = await this.applyTemplateModifications(html, options); // Write back the modified template await fs.writeFile(indexPath, html, 'utf-8'); // Handle additional files if needed if (options.loadingBar || options.loadingText) { await this.addLoadingIndicators(options); } if (options.compression) { await this.setupCompression(); } } catch (error) { console.error('Error modifying template:', error); throw error; } } private async applyTemplateModifications(html: string, options: TemplateOptions): Promise<string> { // Update title if provided if (options.title) { html = html.replace(/<title>.*?<\/title>/, `<title>${options.title}</title>`); } // Add custom styles if (options.customStyles) { const styleTag = `<style>${options.customStyles}</style>`; html = html.replace('</head>', `${styleTag}\n</head>`); } // Add custom scripts if (options.customScripts?.length) { const scriptTags = options.customScripts .map(script => `<script src="${script}"></script>`) .join('\n'); html = html.replace('</body>', `${scriptTags}\n</body>`); } // Add memory limit configuration if (options.memoryLimit) { const memoryConfig = ` <script> var TOTAL_MEMORY = ${options.memoryLimit * 1024 * 1024}; </script>`; html = html.replace('</head>', `${memoryConfig}\n</head>`); } return html; } private async addLoadingIndicators(options: TemplateOptions): Promise<void> { const loadingStyles = ` .webgl-loading-bar { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 200px; height: 20px; background: #f0f0f0; border: 1px solid #333; } .webgl-loading-bar-fill { width: 0%; height: 100%; background: #4CAF50; transition: width 0.3s ease; } .webgl-loading-text { position: absolute; left: 50%; top: calc(50% + 30px); transform: translateX(-50%); font-family: Arial, sans-serif; color: #333; }`; const loadingScript = ` function updateLoadingProgress(progress) { ${options.loadingBar ? ` var fill = document.querySelector('.webgl-loading-bar-fill'); if (fill) fill.style.width = (progress * 100) + '%'; ` : ''} ${options.loadingText ? ` var text = document.querySelector('.webgl-loading-text'); if (text) text.textContent = 'Loading: ' + Math.round(progress * 100) + '%'; ` : ''} }`; // Write the loading indicator files const stylesPath = path.join(this.templatesPath, 'loading-styles.css'); const scriptPath = path.join(this.templatesPath, 'loading-script.js'); await fs.writeFile(stylesPath, loadingStyles, 'utf-8'); await fs.writeFile(scriptPath, loadingScript, 'utf-8'); } private async setupCompression(): Promise<void> { // Add compression-related configurations and scripts const compressionConfig = ` <script> // Enable compression for runtime loading var Module = { compressedDataHandler: function(data) { // Handle compressed data return new Promise(function(resolve) { // Decompress data using WebAssembly resolve(data); }); } }; </script>`; const indexPath = path.join(this.templatesPath, 'index.html'); let html = await fs.readFile(indexPath, 'utf-8'); html = html.replace('</head>', `${compressionConfig}\n</head>`); await fs.writeFile(indexPath, html, 'utf-8'); } public async getTemplatesForEngine(engineId: string): Promise<Template[]> { // Implementation return []; } }