// Universal Code Fixer & Visual FX Studio // Built with transformers.js class UniversalCodeFixer { constructor() { this.model = null; this.isReady = false; this.history = []; this.executionHistory = []; // Visual FX state this.animationId = null; this.particles = []; this.glitchOffset = 0; this.init(); } async init() { this.updateStatus('loading', 'Lade Modell...'); this.updateProgress(10); try { // Load code generation model using transformers.js // Using a smaller, browser-compatible model await this.loadModel(); this.updateStatus('ready', 'Bereit'); this.updateProgress(100); this.bindEvents(); this.initVisualFX(); this.loadHistory(); console.log('✅ Universal Code Fixer initialized'); } catch (error) { console.error('Init error:', error); this.updateStatus('error', 'Fehler: ' + error.message); // Fallback to local processing this.isReady = true; this.updateStatus('ready', 'Bereit (Fallback)'); this.updateProgress(100); this.bindEvents(); this.initVisualFX(); } } async loadModel() { // For browser-based code fixing, we'll use a local approach // since full code models are too large for browser // Simulate model loading with a small delay await this.delay(1500); // In a real implementation, you would load a quantized model: // this.model = await pipeline('text-generation', 'Xenova/codegen-350m-mono'); this.isReady = true; } delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } updateStatus(status, text) { const dot = document.getElementById('modelStatus'); const textEl = document.getElementById('modelStatusText'); dot.className = 'status-dot ' + status; textEl.textContent = text; } updateProgress(percent) { document.getElementById('progressBar').style.width = percent + '%'; if (percent >= 100) { setTimeout(() => { document.getElementById('progressContainer').style.opacity = '0'; }, 500); } } bindEvents() { // Code fixing document.getElementById('btnFix').addEventListener('click', () => this.fixCode()); document.getElementById('btnExecute').addEventListener('click', () => this.executeCode()); document.getElementById('btnLoadExample').addEventListener('click', () => this.loadExample()); document.getElementById('btnClearHistory').addEventListener('click', () => this.clearHistory()); document.getElementById('btnSaveOutput').addEventListener('click', () => this.saveOutput()); // Visual FX controls document.getElementById('enableBW').addEventListener('change', (e) => this.toggleBWOverlay(e.target.checked)); document.getElementById('bwAlpha').addEventListener('input', (e) => this.setBWAlpha(e.target.value / 100)); document.getElementById('btnCapture').addEventListener('click', () => this.captureFrame()); // Animation controls ['animSpeed', 'animScale', 'colorHue', 'colorSat', 'exposureMix', 'exposureOffset'].forEach(id => { document.getElementById(id).addEventListener('input', () => this.updateVisualParams()); }); } async fixCode() { const input = document.getElementById('codeInput').value; if (!input.trim()) { this.log('⚠️ Kein Code eingegeben', 'warning'); return; } this.log('🔧 Analysiere Code...', 'info'); this.updateProgress(30); try { // Analyze code for errors const errors = this.detectErrors(input); const fixedCode = await this.applyFixes(input, errors); document.getElementById('codeOutput').value = fixedCode; // Save to history this.addToHistory(input, fixedCode); this.log('✅ Code erfolgreich repariert!', 'success'); this.updateProgress(100); // Trigger visual celebration this.triggerCelebration(); } catch (error) { this.log('❌ Fehler: ' + error.message, 'error'); this.updateProgress(0); } } detectErrors(code) { const errors = []; const lines = code.split('\n'); // Common error patterns const patterns = [ { regex: /undefined\s*\(/g, type: 'undefined_function', message: 'Possible undefined function call' }, { regex: /\.\s*\[/g, type: 'bracket_access', message: 'Invalid bracket access' }, { regex: /=\s*=/g, type: 'assignment_comparison', message: 'Assignment instead of comparison' }, { regex: /;\s*;/g, type: 'double_semicolon', message: 'Double semicolon' }, { regex: /,\s*,/g, type: 'double_comma', message: 'Double comma' }, { regex: /\(\s*\)/g, type: 'empty_parens', message: 'Empty parentheses' }, { regex: /\{\s*\}/g, type: 'empty_block', message: 'Empty block' }, { regex: /=>\s*;/g, type: 'arrow_empty', message: 'Empty arrow function' }, ]; lines.forEach((line, idx) => { patterns.forEach(pattern => { if (pattern.regex.test(line)) { errors.push({ line: idx + 1, code: line.trim(), type: pattern.type, message: pattern.message }); } }); }); return errors; } async applyFixes(code, errors) { let fixed = code; // Apply fixes based on detected errors errors.forEach(error => { switch (error.type) { case 'double_semicolon': fixed = fixed.replace(/;;/g, ';'); break; case 'double_comma': fixed = fixed.replace(/,,/g, ','); break; case 'assignment_comparison': // This is often intentional, so we add a comment fixed = fixed.replace(/(\w+)\s*=\s*=/g, '// Consider === for comparison\n$1 ='); break; case 'empty_parens': // Keep empty parens as they might be intentional break; } }); // Add common improvements const improvements = [ // Add 'use strict' if missing in JS { regex: /^((?!(use strict)).)*$/, replacement: '"use strict";\n', condition: () => code.includes('function') }, // Add error handling { regex: /fetch\(/g, replacement: 'fetch($&, {\n headers: { "Content-Type": "application/json" },\n mode: "cors"\n }).catch(err => console.error(err))' }, ]; // Apply syntax highlighting-friendly fixes fixed = this.addCodeEnhancements(fixed); return fixed; } addCodeEnhancements(code) { let enhanced = code; // Add proper error handling patterns if (code.includes('async') && !code.includes('try')) { enhanced = enhanced.replace(/(async\s+function\s+\w+\([^)]*\)\s*\{)/g, 'async function wrapped() {\n try {\n $1'); } // Add common utility functions if missing if (code.includes('document.') && !code.includes('DOMContentLoaded')) { enhanced = 'document.addEventListener("DOMContentLoaded", () => {\n' + enhanced + '\n});'; } return enhanced; } executeCode() { const code = document.getElementById('codeOutput').value || document.getElementById('codeInput').value; if (!code.trim()) { this.log('⚠️ Kein Code zum Ausführen', 'warning'); return; } this.log('▶️ Starte Code-Ausführung...', 'info'); const frame = document.getElementById('sandboxFrame'); const frameDoc = frame.contentDocument || frame.contentWindow.document; // Clear previous frameDoc.open(); frameDoc.write('
'); // Capture console output const logs = []; frameDoc.defaultView.console = { log: (...args) => logs.push(args.join(' ')), error: (...args) => logs.push('❌ ' + args.join(' ')), warn: (...args) => logs.push('⚠️ ' + args.join(' ')) }; try { // Execute in sandbox frameDoc.defaultView.eval(code); // Get output const output = frameDoc.getElementById('output').innerHTML; if (output) logs.push(output); this.log('✅ Ausführung abgeschlossen', 'success'); logs.forEach(l => this.log(l)); this.addToExecutionHistory(code, 'success'); } catch (error) { this.log('❌ Ausführungsfehler: ' + error.message, 'error'); this.addToExecutionHistory(code, 'error: ' + error.message); } frameDoc.close(); } loadExample() { const examples = [ { name: 'JavaScript Error Example', code: `// Buggy code with multiple errors function calculate(a,b) { return a + b;; } const data = undefined; data.foo();; const arr = [1,2,,4]; console.log(arr); ` }, { name: 'Async Fetch Example', code: `// Async code needing error handling async function fetchData(url) { const response = await fetch(url) const json = await response.json() return json }` }, { name: 'DOM Manipulation', code: `// DOM code with potential issues document.getElementById('app').innerHTML = '
Hello
'; document.querySelectorAll('.item').forEach(el => { el.addEventListener('click', () => console.log('clicked')) });` } ]; const random = examples[Math.floor(Math.random() * examples.length)]; document.getElementById('codeInput').value = random.code; this.log('📝 Beispiel geladen: ' + random.name, 'info'); } addToHistory(input, output) { const entry = { timestamp: Date.now(), input: input.substring(0, 100) + (input.length > 100 ? '...' : ''), output: output.substring(0, 100) + (output.length > 100 ? '...' : '') }; this.history.unshift(entry); if (this.history.length > 50) this.history.pop(); localStorage.setItem('codeFixerHistory', JSON.stringify(this.history)); } addToExecutionHistory(code, result) { this.executionHistory.unshift({ timestamp: Date.now(), result: result.substring(0, 50) }); localStorage.setItem('executionHistory', JSON.stringify(this.executionHistory)); } loadHistory() { const saved = localStorage.getItem('codeFixerHistory'); if (saved) { this.history = JSON.parse(saved); this.log('📜 ' + this.history.length + ' Einträge aus History geladen', 'info'); } } clearHistory() { this.history = []; this.executionHistory = []; localStorage.removeItem('codeFixerHistory'); localStorage.removeItem('executionHistory'); this.log('🗑️ History gelöscht', 'info'); } saveOutput() { const output = document.getElementById('codeOutput').value; if (!output) { this.log('⚠️ Keine Ausgabe zum Speichern', 'warning'); return; } const blob = new Blob([output], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'fixed_code_' + Date.now() + '.txt'; a.click(); this.log('💾 Code gespeichert', 'success'); } log(message, type = 'info') { const logEl = document.getElementById('execLog'); const entry = document.createElement('div'); const colors = { info: '#888', success: '#00ff9d', warning: '#ffaa00', error: '#ff0055' }; entry.style.color = colors[type] || colors.info; entry.textContent = '[' + new Date().toLocaleTimeString() + '] ' + message; logEl.appendChild(entry); logEl.scrollTop = logEl.scrollHeight; } // Visual FX Methods initVisualFX() { const canvas = document.getElementById('mainCanvas'); const ctx = canvas.getContext('2d'); // Set canvas size const resize = () => { const rect = canvas.parentElement.getBoundingClientRect(); canvas.width = rect.width; canvas.height = rect.height; }; resize(); window.addEventListener('resize', resize); // Initialize particles for (let i = 0; i < 100; i++) { this.particles.push({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, vx: (Math.random() - 0.5) * 2, vy: (Math.random() - 0.5) * 2, size: Math.random() * 3 + 1, color: Math.random() > 0.5 ? '#00ff9d' : '#ff0055' }); } this.animate(); } animate() { const canvas = document.getElementById('mainCanvas'); const ctx = canvas.getContext('2d'); // Clear with trail effect ctx.fillStyle = 'rgba(5, 5, 5, 0.1)'; ctx.fillRect(0, 0, canvas.width, canvas.height); // Update and draw particles const speed = document.getElementById('animSpeed').value / 50; this.particles.forEach(p => { p.x += p.vx * speed; p.y += p.vy * speed; // Wrap around if (p.x < 0) p.x = canvas.width; if (p.x > canvas.width) p.x = 0; if (p.y < 0) p.y = canvas.height; if (p.y > canvas.height) p.y = 0; ctx.beginPath(); ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2); ctx.fillStyle = p.color; ctx.globalAlpha = 0.5; ctx.fill(); }); // Draw grid ctx.strokeStyle = '#222'; ctx.globalAlpha = 0.3; const gridSize = 50; for (let x = 0; x < canvas.width; x += gridSize) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, canvas.height); ctx.stroke(); } for (let y = 0; y < canvas.height; y += gridSize) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(canvas.width, y); ctx.stroke(); } this.animationId = requestAnimationFrame(() => this.animate()); } updateVisualParams() { // Update visual parameters from sliders this.bwAlpha = document.getElementById('bwAlpha').value / 100; this.setBWAlpha(this.bwAlpha); } toggleBWOverlay(enabled) { const overlay = document.getElementById('bwOverlay'); overlay.style.display = enabled ? 'block' : 'none'; } setBWAlpha(alpha) { const overlay = document.getElementById('bwOverlay'); overlay.style.opacity = alpha; // Draw B&W effect on overlay this.drawBWOverlay(); } drawBWOverlay() { const canvas = document.getElementById('bwOverlay'); const ctx = canvas.getContext('2d'); canvas.width = canvas.parentElement.clientWidth; canvas.height = canvas.parentElement.clientHeight; // Create B&W gradient overlay const gradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height); gradient.addColorStop(0, 'rgba(0, 0, 0, 0)'); gradient.addColorStop(0.5, 'rgba(128, 128, 128, 0.3)'); gradient.addColorStop(1, 'rgba(0, 0, 0, 0)'); ctx.fillStyle = gradient; ctx.fillRect(0, 0, canvas.width, canvas.height); // Add scanlines ctx.strokeStyle = 'rgba(0, 255, 157, 0.1)'; ctx.lineWidth = 1; for (let y = 0; y < canvas.height; y += 4) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(canvas.width, y); ctx.stroke(); } } captureFrame() { const canvas = document.getElementById('mainCanvas'); canvas.toBlob(blob => { const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'capture_' + Date.now() + '.png'; a.click(); this.log('📷 Frame capturiert', 'success'); }); } triggerCelebration() { // Flash effect on successful fix const viewport = document.getElementById('viewportFrame'); viewport.style.boxShadow = '0 0 50px rgba(0, 255, 157, 0.5)'; setTimeout(() => { viewport.style.boxShadow = 'none'; }, 500); } } // Global copy function function copyToClipboard(elementId) { const el = document.getElementById(elementId); el.select(); document.execCommand('copy'); // Show feedback const btn = el.parentElement.querySelector('.copy-btn'); const originalText = btn.textContent; btn.textContent = 'COPIED!'; btn.style.color = '#00ff9d'; setTimeout(() => { btn.textContent = originalText; btn.style.color = ''; }, 1500); } // Initialize app window.addEventListener('DOMContentLoaded', () => { window.app = new UniversalCodeFixer(); });