File size: 11,060 Bytes
2e7546e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320

import re
from pathlib import Path
from typing import Dict, Optional, Tuple
from dataclasses import dataclass
from enum import Enum

class Language(Enum):
    PYTHON = "python"
    JAVASCRIPT = "javascript"
    HTML = "html"
    CSS = "css"
    JSON = "json"
    MARKDOWN = "markdown"
    PLAINTEXT = "plaintext"
    JAVA = "java"
    CPP = "cpp"
    TYPESCRIPT = "typescript"
    SQL = "sql"

@dataclass
class CodeFile:
    name: str
    content: str
    language: Language
    logo: str
    extension: str
    can_preview: bool = False

class FileManager:
    """Manages code files, language detection, and logos"""
    
    # Language detection mapping
    LANGUAGE_MAP = {
        # Extensions to Language
        ".py": Language.PYTHON,
        ".js": Language.JAVASCRIPT,
        ".html": Language.HTML,
        ".htm": Language.HTML,
        ".css": Language.CSS,
        ".json": Language.JSON,
        ".md": Language.MARKDOWN,
        ".java": Language.JAVA,
        ".cpp": Language.CPP,
        ".c": Language.CPP,
        ".ts": Language.TYPESCRIPT,
        ".sql": Language.SQL,
        
        # Shebang detection for Python
        "#!/usr/bin/env python": Language.PYTHON,
        "#!/usr/bin/python": Language.PYTHON,
    }
    
    # Logo mappings (emoji fallbacks, can be replaced with image URLs)
    LOGO_MAP = {
        Language.PYTHON: "🐍",        # Or use: "https://cdn.jsdelivr.net/npm/simple-icons@v13/icons/python.svg"
        Language.JAVASCRIPT: "🟨",
        Language.HTML: "🌐",
        Language.CSS: "🎨",
        Language.JSON: "πŸ“‹",
        Language.MARKDOWN: "πŸ“",
        Language.JAVA: "β˜•",
        Language.CPP: "βš™οΈ",
        Language.TYPESCRIPT: "πŸ“˜",
        Language.SQL: "πŸ—„οΈ",
        Language.PLAINTEXT: "πŸ“„",
    }
    
    # Previewable languages
    PREVIEWABLE = {Language.HTML, Language.JAVASCRIPT, Language.CSS}
    
    @classmethod
    def detect_language(cls, filename: str, content: str = "") -> Language:
        """Detect language from filename and content"""
        # Check by extension
        ext = Path(filename).suffix.lower()
        if ext in cls.LANGUAGE_MAP:
            return cls.LANGUAGE_MAP[ext]
        
        # Check for shebang in first line
        if content:
            first_line = content.split('\n')[0].strip()
            if first_line in cls.LANGUAGE_MAP:
                return cls.LANGUAGE_MAP[first_line]
        
        # Heuristic detection
        if content:
            if "<html" in content.lower() or "<body" in content.lower():
                return Language.HTML
            if "def " in content and "import " in content:
                return Language.PYTHON
            if "function " in content or "const " in content:
                return Language.JAVASCRIPT
        
        return Language.PLAINTEXT
    
    @classmethod
    def get_logo(cls, language: Language, use_emoji: bool = True) -> str:
        """Get logo for language (emoji or HTML img tag)"""
        if use_emoji:
            return cls.LOGO_MAP.get(language, "πŸ“„")
        # For image URLs, you can use:
        # return f'<img src="https://cdn.jsdelivr.net/npm/simple-icons@v13/icons/{language.value}.svg" width="16" height="16">'
        return cls.LOGO_MAP.get(language, "πŸ“„")
    
    @classmethod
    def extract_files_from_code(cls, code: str) -> Dict[str, CodeFile]:
        """Extract multiple files from code block (e.g., from AI response)"""
        files = {}
        
        # Pattern for markdown code blocks with filenames
        # Matches: ```python filename.py\ncode```
        pattern = r'```(\w+)(?:\s+([\/\w\.-]+))?\n(.*?)```'
        
        matches = re.findall(pattern, code, re.DOTALL)
        
        for lang, filename, content in matches:
            if not filename:
                # Generate filename from language
                ext_map = {
                    "python": "script.py",
                    "javascript": "script.js",
                    "html": "index.html",
                    "css": "styles.css",
                    "json": "data.json",
                    "java": "Main.java",
                    "cpp": "program.cpp",
                }
                filename = ext_map.get(lang.lower(), f"code.{lang}")
            
            language = cls.detect_language(filename, content)
            files[filename] = CodeFile(
                name=filename,
                content=content.strip(),
                language=language,
                logo=cls.get_logo(language),
                extension=Path(filename).suffix,
                can_preview=language in cls.PREVIEWABLE
            )
        
        return files
    
    @classmethod
    def format_file_tree(cls, files: Dict[str, CodeFile]) -> str:
        """Generate HTML for file tree with logos"""
        html = '<div class="file-tree">'
        for name, file in files.items():
            html += f'''
            <div class="file-item" data-filename="{name}" data-language="{file.language.value}">
                <span class="file-logo">{file.logo}</span>
                <span class="file-name">{name}</span>
                <span class="file-badge">{file.language.value}</span>
            </div>
            '''
        html += '</div>'
        return html

# Test
if __name__ == "__main__":
    test_code = """
    Here's a Python function:
    ```python
    def hello():
        print("Hello World")
And an HTML file:

html
<h1>Hello</h1>
"""
files = FileManager.extract_files_from_code(test_code)
for name, file in files.items():
print(f"{file.logo} {name} ({file.language.value})")

text

## πŸ“„ File 3: `preview_handler.py`

```python
import base64
import re
from typing import Dict, Optional
from file_manager import CodeFile, Language

class PreviewHandler:
    """Handles live previews for different code types"""
    
    @staticmethod
    def create_html_preview(content: str) -> str:
        """Create an iframe-ready HTML preview"""
        # Sanitize content (basic)
        # In production, use a proper sanitizer like bleach
        return f"""
        <div class="preview-container">
            <iframe srcdoc="{content.replace('"', '&quot;')}" 
                    style="width:100%; height:500px; border:none; border-radius:8px;"
                    sandbox="allow-same-origin allow-scripts allow-popups allow-forms">
            </iframe>
        </div>
        """
    
    @staticmethod
    def create_js_preview(content: str) -> str:
        """Run JavaScript code in a sandboxed environment"""
        # Wrap JS in HTML for preview
        html = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="utf-8">
            <title>JavaScript Preview</title>
            <style>
                body {{ font-family: monospace; padding: 20px; background: #1e1e1e; color: #d4d4d4; }}
                #output {{ background: #2d2d2d; padding: 10px; border-radius: 5px; margin-top: 10px; }}
            </style>
        </head>
        <body>
            <div id="output">Console output will appear here...</div>
            <script>
                // Capture console.log
                (function() {{
                    const output = document.getElementById('output');
                    const originalLog = console.log;
                    console.log = function(...args) {{
                        output.innerHTML += args.map(a => String(a)).join(' ') + '<br>';
                        originalLog.apply(console, args);
                    }};
                }})();
                
                // User code
                try {{
                    {content}
                }} catch(e) {{
                    console.log('Error:', e.message);
                }}
            </script>
        </body>
        </html>
        """
        return PreviewHandler.create_html_preview(html)
    
    @staticmethod
    def create_python_preview(content: str) -> str:
        """
        Create a Python preview using PyScript (runs in browser)
        Note: Limited functionality - no file I/O, no network requests
        """
        # Encode content for safe embedding
        encoded_content = base64.b64encode(content.encode()).decode()
        
        return f"""
        <div class="preview-container">
            <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
            <script defer src="https://pyscript.net/latest/pyscript.js"></script>
            
            <py-script>
                import base64
                # Decode and execute user code
                code = base64.b64decode("{encoded_content}").decode()
                exec(code)
            </py-script>
            
            <div class="pyscript-output" style="background:#1e1e1e; padding:10px; border-radius:5px;">
                Python output will appear here...
            </div>
        </div>
        """
    
    @staticmethod
    def create_preview(file: CodeFile) -> str:
        """Generate appropriate preview based on file language"""
        if not file.can_preview:
            return f"""
            <div class="preview-error">
                ⚠️ Preview not available for {file.language.value.upper()} files.
                <br>Supported preview formats: HTML, CSS, JavaScript
            </div>
            """
        
        if file.language == Language.HTML:
            return PreviewHandler.create_html_preview(file.content)
        elif file.language == Language.JAVASCRIPT:
            return PreviewHandler.create_js_preview(file.content)
        elif file.language == Language.CSS:
            # Wrap CSS in minimal HTML
            html = f"""
            <!DOCTYPE html>
            <html>
            <head><style>{file.content}</style></head>
            <body>
                <div class="preview-demo">
                    <h1>CSS Preview</h1>
                    <p>Your styles are applied to this page.</p>
                    <button>Test Button</button>
                </div>
            </body>
            </html>
            """
            return PreviewHandler.create_html_preview(html)
        elif file.language == Language.PYTHON:
            return PreviewHandler.create_python_preview(file.content)
        
        return "<div>Preview not available</div>"

    @staticmethod
    def format_code_with_syntax(content: str, language: str) -> str:
        """Return formatted code HTML (for the 'View Code' tab)"""
        # Escape HTML
        escaped = content.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
        
        return f"""
        <div class="code-viewer">
            <div class="code-header">
                <span class="code-lang">{language.upper()}</span>
                <button class="copy-btn" onclick="navigator.clipboard.writeText(`{escaped.replace('`', '\\`')}`)">
                    πŸ“‹ Copy
                </button>
            </div>
            <pre class="code-block"><code class="language-{language}">{escaped}</code></pre>
        </div>
        """