Eeppa commited on
Commit
2e7546e
·
verified ·
1 Parent(s): b7823b4

Create file_manager.py

Browse files
Files changed (1) hide show
  1. file_manager.py +320 -0
file_manager.py ADDED
@@ -0,0 +1,320 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import re
3
+ from pathlib import Path
4
+ from typing import Dict, Optional, Tuple
5
+ from dataclasses import dataclass
6
+ from enum import Enum
7
+
8
+ class Language(Enum):
9
+ PYTHON = "python"
10
+ JAVASCRIPT = "javascript"
11
+ HTML = "html"
12
+ CSS = "css"
13
+ JSON = "json"
14
+ MARKDOWN = "markdown"
15
+ PLAINTEXT = "plaintext"
16
+ JAVA = "java"
17
+ CPP = "cpp"
18
+ TYPESCRIPT = "typescript"
19
+ SQL = "sql"
20
+
21
+ @dataclass
22
+ class CodeFile:
23
+ name: str
24
+ content: str
25
+ language: Language
26
+ logo: str
27
+ extension: str
28
+ can_preview: bool = False
29
+
30
+ class FileManager:
31
+ """Manages code files, language detection, and logos"""
32
+
33
+ # Language detection mapping
34
+ LANGUAGE_MAP = {
35
+ # Extensions to Language
36
+ ".py": Language.PYTHON,
37
+ ".js": Language.JAVASCRIPT,
38
+ ".html": Language.HTML,
39
+ ".htm": Language.HTML,
40
+ ".css": Language.CSS,
41
+ ".json": Language.JSON,
42
+ ".md": Language.MARKDOWN,
43
+ ".java": Language.JAVA,
44
+ ".cpp": Language.CPP,
45
+ ".c": Language.CPP,
46
+ ".ts": Language.TYPESCRIPT,
47
+ ".sql": Language.SQL,
48
+
49
+ # Shebang detection for Python
50
+ "#!/usr/bin/env python": Language.PYTHON,
51
+ "#!/usr/bin/python": Language.PYTHON,
52
+ }
53
+
54
+ # Logo mappings (emoji fallbacks, can be replaced with image URLs)
55
+ LOGO_MAP = {
56
+ Language.PYTHON: "🐍", # Or use: "https://cdn.jsdelivr.net/npm/simple-icons@v13/icons/python.svg"
57
+ Language.JAVASCRIPT: "🟨",
58
+ Language.HTML: "🌐",
59
+ Language.CSS: "🎨",
60
+ Language.JSON: "📋",
61
+ Language.MARKDOWN: "📝",
62
+ Language.JAVA: "☕",
63
+ Language.CPP: "⚙️",
64
+ Language.TYPESCRIPT: "📘",
65
+ Language.SQL: "🗄️",
66
+ Language.PLAINTEXT: "📄",
67
+ }
68
+
69
+ # Previewable languages
70
+ PREVIEWABLE = {Language.HTML, Language.JAVASCRIPT, Language.CSS}
71
+
72
+ @classmethod
73
+ def detect_language(cls, filename: str, content: str = "") -> Language:
74
+ """Detect language from filename and content"""
75
+ # Check by extension
76
+ ext = Path(filename).suffix.lower()
77
+ if ext in cls.LANGUAGE_MAP:
78
+ return cls.LANGUAGE_MAP[ext]
79
+
80
+ # Check for shebang in first line
81
+ if content:
82
+ first_line = content.split('\n')[0].strip()
83
+ if first_line in cls.LANGUAGE_MAP:
84
+ return cls.LANGUAGE_MAP[first_line]
85
+
86
+ # Heuristic detection
87
+ if content:
88
+ if "<html" in content.lower() or "<body" in content.lower():
89
+ return Language.HTML
90
+ if "def " in content and "import " in content:
91
+ return Language.PYTHON
92
+ if "function " in content or "const " in content:
93
+ return Language.JAVASCRIPT
94
+
95
+ return Language.PLAINTEXT
96
+
97
+ @classmethod
98
+ def get_logo(cls, language: Language, use_emoji: bool = True) -> str:
99
+ """Get logo for language (emoji or HTML img tag)"""
100
+ if use_emoji:
101
+ return cls.LOGO_MAP.get(language, "📄")
102
+ # For image URLs, you can use:
103
+ # return f'<img src="https://cdn.jsdelivr.net/npm/simple-icons@v13/icons/{language.value}.svg" width="16" height="16">'
104
+ return cls.LOGO_MAP.get(language, "📄")
105
+
106
+ @classmethod
107
+ def extract_files_from_code(cls, code: str) -> Dict[str, CodeFile]:
108
+ """Extract multiple files from code block (e.g., from AI response)"""
109
+ files = {}
110
+
111
+ # Pattern for markdown code blocks with filenames
112
+ # Matches: ```python filename.py\ncode```
113
+ pattern = r'```(\w+)(?:\s+([\/\w\.-]+))?\n(.*?)```'
114
+
115
+ matches = re.findall(pattern, code, re.DOTALL)
116
+
117
+ for lang, filename, content in matches:
118
+ if not filename:
119
+ # Generate filename from language
120
+ ext_map = {
121
+ "python": "script.py",
122
+ "javascript": "script.js",
123
+ "html": "index.html",
124
+ "css": "styles.css",
125
+ "json": "data.json",
126
+ "java": "Main.java",
127
+ "cpp": "program.cpp",
128
+ }
129
+ filename = ext_map.get(lang.lower(), f"code.{lang}")
130
+
131
+ language = cls.detect_language(filename, content)
132
+ files[filename] = CodeFile(
133
+ name=filename,
134
+ content=content.strip(),
135
+ language=language,
136
+ logo=cls.get_logo(language),
137
+ extension=Path(filename).suffix,
138
+ can_preview=language in cls.PREVIEWABLE
139
+ )
140
+
141
+ return files
142
+
143
+ @classmethod
144
+ def format_file_tree(cls, files: Dict[str, CodeFile]) -> str:
145
+ """Generate HTML for file tree with logos"""
146
+ html = '<div class="file-tree">'
147
+ for name, file in files.items():
148
+ html += f'''
149
+ <div class="file-item" data-filename="{name}" data-language="{file.language.value}">
150
+ <span class="file-logo">{file.logo}</span>
151
+ <span class="file-name">{name}</span>
152
+ <span class="file-badge">{file.language.value}</span>
153
+ </div>
154
+ '''
155
+ html += '</div>'
156
+ return html
157
+
158
+ # Test
159
+ if __name__ == "__main__":
160
+ test_code = """
161
+ Here's a Python function:
162
+ ```python
163
+ def hello():
164
+ print("Hello World")
165
+ And an HTML file:
166
+
167
+ html
168
+ <h1>Hello</h1>
169
+ """
170
+ files = FileManager.extract_files_from_code(test_code)
171
+ for name, file in files.items():
172
+ print(f"{file.logo} {name} ({file.language.value})")
173
+
174
+ text
175
+
176
+ ## 📄 File 3: `preview_handler.py`
177
+
178
+ ```python
179
+ import base64
180
+ import re
181
+ from typing import Dict, Optional
182
+ from file_manager import CodeFile, Language
183
+
184
+ class PreviewHandler:
185
+ """Handles live previews for different code types"""
186
+
187
+ @staticmethod
188
+ def create_html_preview(content: str) -> str:
189
+ """Create an iframe-ready HTML preview"""
190
+ # Sanitize content (basic)
191
+ # In production, use a proper sanitizer like bleach
192
+ return f"""
193
+ <div class="preview-container">
194
+ <iframe srcdoc="{content.replace('"', '&quot;')}"
195
+ style="width:100%; height:500px; border:none; border-radius:8px;"
196
+ sandbox="allow-same-origin allow-scripts allow-popups allow-forms">
197
+ </iframe>
198
+ </div>
199
+ """
200
+
201
+ @staticmethod
202
+ def create_js_preview(content: str) -> str:
203
+ """Run JavaScript code in a sandboxed environment"""
204
+ # Wrap JS in HTML for preview
205
+ html = f"""
206
+ <!DOCTYPE html>
207
+ <html>
208
+ <head>
209
+ <meta charset="utf-8">
210
+ <title>JavaScript Preview</title>
211
+ <style>
212
+ body {{ font-family: monospace; padding: 20px; background: #1e1e1e; color: #d4d4d4; }}
213
+ #output {{ background: #2d2d2d; padding: 10px; border-radius: 5px; margin-top: 10px; }}
214
+ </style>
215
+ </head>
216
+ <body>
217
+ <div id="output">Console output will appear here...</div>
218
+ <script>
219
+ // Capture console.log
220
+ (function() {{
221
+ const output = document.getElementById('output');
222
+ const originalLog = console.log;
223
+ console.log = function(...args) {{
224
+ output.innerHTML += args.map(a => String(a)).join(' ') + '<br>';
225
+ originalLog.apply(console, args);
226
+ }};
227
+ }})();
228
+
229
+ // User code
230
+ try {{
231
+ {content}
232
+ }} catch(e) {{
233
+ console.log('Error:', e.message);
234
+ }}
235
+ </script>
236
+ </body>
237
+ </html>
238
+ """
239
+ return PreviewHandler.create_html_preview(html)
240
+
241
+ @staticmethod
242
+ def create_python_preview(content: str) -> str:
243
+ """
244
+ Create a Python preview using PyScript (runs in browser)
245
+ Note: Limited functionality - no file I/O, no network requests
246
+ """
247
+ # Encode content for safe embedding
248
+ encoded_content = base64.b64encode(content.encode()).decode()
249
+
250
+ return f"""
251
+ <div class="preview-container">
252
+ <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
253
+ <script defer src="https://pyscript.net/latest/pyscript.js"></script>
254
+
255
+ <py-script>
256
+ import base64
257
+ # Decode and execute user code
258
+ code = base64.b64decode("{encoded_content}").decode()
259
+ exec(code)
260
+ </py-script>
261
+
262
+ <div class="pyscript-output" style="background:#1e1e1e; padding:10px; border-radius:5px;">
263
+ Python output will appear here...
264
+ </div>
265
+ </div>
266
+ """
267
+
268
+ @staticmethod
269
+ def create_preview(file: CodeFile) -> str:
270
+ """Generate appropriate preview based on file language"""
271
+ if not file.can_preview:
272
+ return f"""
273
+ <div class="preview-error">
274
+ ⚠️ Preview not available for {file.language.value.upper()} files.
275
+ <br>Supported preview formats: HTML, CSS, JavaScript
276
+ </div>
277
+ """
278
+
279
+ if file.language == Language.HTML:
280
+ return PreviewHandler.create_html_preview(file.content)
281
+ elif file.language == Language.JAVASCRIPT:
282
+ return PreviewHandler.create_js_preview(file.content)
283
+ elif file.language == Language.CSS:
284
+ # Wrap CSS in minimal HTML
285
+ html = f"""
286
+ <!DOCTYPE html>
287
+ <html>
288
+ <head><style>{file.content}</style></head>
289
+ <body>
290
+ <div class="preview-demo">
291
+ <h1>CSS Preview</h1>
292
+ <p>Your styles are applied to this page.</p>
293
+ <button>Test Button</button>
294
+ </div>
295
+ </body>
296
+ </html>
297
+ """
298
+ return PreviewHandler.create_html_preview(html)
299
+ elif file.language == Language.PYTHON:
300
+ return PreviewHandler.create_python_preview(file.content)
301
+
302
+ return "<div>Preview not available</div>"
303
+
304
+ @staticmethod
305
+ def format_code_with_syntax(content: str, language: str) -> str:
306
+ """Return formatted code HTML (for the 'View Code' tab)"""
307
+ # Escape HTML
308
+ escaped = content.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
309
+
310
+ return f"""
311
+ <div class="code-viewer">
312
+ <div class="code-header">
313
+ <span class="code-lang">{language.upper()}</span>
314
+ <button class="copy-btn" onclick="navigator.clipboard.writeText(`{escaped.replace('`', '\\`')}`)">
315
+ 📋 Copy
316
+ </button>
317
+ </div>
318
+ <pre class="code-block"><code class="language-{language}">{escaped}</code></pre>
319
+ </div>
320
+ """