mgbam commited on
Commit
59c1021
·
verified ·
1 Parent(s): bf83f57

Delete code _processing.py

Browse files
Files changed (1) hide show
  1. code _processing.py +0 -698
code _processing.py DELETED
@@ -1,698 +0,0 @@
1
-
2
-
3
- import re
4
- import base64
5
- import json
6
- from typing import Dict, List, Optional, Tuple, Union
7
- from pathlib import Path
8
-
9
- from utils import apply_search_replace_changes, validate_video_html
10
- from media_generation import generate_image_with_qwen, generate_image_to_image, generate_video_from_image, generate_video_from_text, generate_music_from_text
11
- from config import SEARCH_START, DIVIDER, REPLACE_END
12
-
13
- class CodeProcessor:
14
- """Handles processing and transformation of various code formats"""
15
-
16
- @staticmethod
17
- def is_streamlit_code(code: str) -> bool:
18
- """Check if Python code is a Streamlit app"""
19
- if not code:
20
- return False
21
- lowered = code.lower()
22
- return ("import streamlit" in lowered) or ("from streamlit" in lowered) or ("st." in code and "streamlit" in lowered)
23
-
24
- @staticmethod
25
- def is_gradio_code(code: str) -> bool:
26
- """Check if Python code is a Gradio app"""
27
- if not code:
28
- return False
29
- lowered = code.lower()
30
- return (
31
- "import gradio" in lowered or
32
- "from gradio" in lowered or
33
- "gr.Interface(" in code or
34
- "gr.Blocks(" in code
35
- )
36
-
37
- @staticmethod
38
- def extract_html_document(text: str) -> str:
39
- """Extract HTML document from text, ignoring planning notes"""
40
- if not text:
41
- return text
42
- lower = text.lower()
43
- idx = lower.find("<!doctype html")
44
- if idx == -1:
45
- idx = lower.find("<html")
46
- return text[idx:] if idx != -1 else text
47
-
48
- class TransformersJSProcessor:
49
- """Handles Transformers.js specific code processing"""
50
-
51
- @staticmethod
52
- def parse_transformers_js_output(text: str) -> Dict[str, str]:
53
- """Parse transformers.js output and extract the three files"""
54
- files = {
55
- 'index.html': '',
56
- 'index.js': '',
57
- 'style.css': ''
58
- }
59
-
60
- if not text:
61
- return files
62
-
63
- # Multiple patterns for different code block variations
64
- html_patterns = [
65
- r'```html\s*\n([\s\S]*?)(?:```|\Z)',
66
- r'```htm\s*\n([\s\S]*?)(?:```|\Z)',
67
- r'```\s*(?:index\.html|html)\s*\n([\s\S]*?)(?:```|\Z)'
68
- ]
69
-
70
- js_patterns = [
71
- r'```javascript\s*\n([\s\S]*?)(?:```|\Z)',
72
- r'```js\s*\n([\s\S]*?)(?:```|\Z)',
73
- r'```\s*(?:index\.js|javascript|js)\s*\n([\s\S]*?)(?:```|\Z)'
74
- ]
75
-
76
- css_patterns = [
77
- r'```css\s*\n([\s\S]*?)(?:```|\Z)',
78
- r'```\s*(?:style\.css|css)\s*\n([\s\S]*?)(?:```|\Z)'
79
- ]
80
-
81
- # Extract content using patterns
82
- for pattern in html_patterns:
83
- html_match = re.search(pattern, text, re.IGNORECASE)
84
- if html_match:
85
- files['index.html'] = html_match.group(1).strip()
86
- break
87
-
88
- for pattern in js_patterns:
89
- js_match = re.search(pattern, text, re.IGNORECASE)
90
- if js_match:
91
- files['index.js'] = js_match.group(1).strip()
92
- break
93
-
94
- for pattern in css_patterns:
95
- css_match = re.search(pattern, text, re.IGNORECASE)
96
- if css_match:
97
- files['style.css'] = css_match.group(1).strip()
98
- break
99
-
100
- # Fallback: support === filename === format
101
- if not (files['index.html'] and files['index.js'] and files['style.css']):
102
- fallback_files = MultipageProcessor.parse_multipage_html_output(text)
103
- for key in files.keys():
104
- if key in fallback_files:
105
- files[key] = fallback_files[key]
106
-
107
- return files
108
-
109
- @staticmethod
110
- def format_transformers_js_output(files: Dict[str, str]) -> str:
111
- """Format the three files into a single display string"""
112
- output = []
113
- output.append("=== index.html ===")
114
- output.append(files.get('index.html', ''))
115
- output.append("\n=== index.js ===")
116
- output.append(files.get('index.js', ''))
117
- output.append("\n=== style.css ===")
118
- output.append(files.get('style.css', ''))
119
- return '\n'.join(output)
120
-
121
- @staticmethod
122
- def build_transformers_inline_html(files: Dict[str, str]) -> str:
123
- """Merge transformers.js files into a single HTML document"""
124
- html = files.get('index.html') or ''
125
- js = files.get('index.js') or ''
126
- css = files.get('style.css') or ''
127
-
128
- # Normalize JS imports to stable CDN
129
- cdn_url = "https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.7.2"
130
-
131
- def _normalize_imports(_code: str) -> str:
132
- if not _code:
133
- return _code or ""
134
- _code = re.sub(r"from\s+['\"]@huggingface/transformers['\"]", f"from '{cdn_url}'", _code)
135
- _code = re.sub(r"from\s+['\"]@xenova/transformers['\"]", f"from '{cdn_url}'", _code)
136
- _code = re.sub(r"from\s+['\"]https://cdn.jsdelivr.net/npm/@huggingface/transformers@[^'\"]+['\"]", f"from '{cdn_url}'", _code)
137
- _code = re.sub(r"from\s+['\"]https://cdn.jsdelivr.net/npm/@xenova/transformers@[^'\"]+['\"]", f"from '{cdn_url}'", _code)
138
- return _code
139
-
140
- # Extract and merge inline module scripts
141
- inline_modules = []
142
- try:
143
- for _m in re.finditer(r"<script\b[^>]*type=[\"']module[\"'][^>]*>([\s\S]*?)</script>", html, flags=re.IGNORECASE):
144
- inline_modules.append(_m.group(1))
145
- if inline_modules:
146
- html = re.sub(r"<script\b[^>]*type=[\"']module[\"'][^>]*>[\s\S]*?</script>\s*", "", html, flags=re.IGNORECASE)
147
- except Exception:
148
- pass
149
-
150
- # Combine JS code
151
- combined_js_parts = []
152
- if inline_modules:
153
- combined_js_parts.append("\n\n".join(inline_modules))
154
- if js:
155
- combined_js_parts.append(js)
156
- js = "\n\n".join([p for p in combined_js_parts if (p and p.strip())])
157
- js = _normalize_imports(js)
158
-
159
- # Add prelude for better compatibility
160
- if js.strip():
161
- prelude = (
162
- f"import {{ env }} from '{cdn_url}';\n"
163
- "try { env.useBrowserCache = false; } catch (e) {}\n"
164
- "try { if (env && env.backends && env.backends.onnx && env.backends.onnx.wasm) { env.backends.onnx.wasm.numThreads = 1; env.backends.onnx.wasm.proxy = false; } } catch (e) {}\n"
165
- f"(async () => {{ try {{ if (typeof globalThis.transformers === 'undefined') {{ const m = await import('{cdn_url}'); globalThis.transformers = m; }} }} catch (e) {{}} }})();\n"
166
- )
167
- js = prelude + js
168
-
169
- # Create minimal shell if needed
170
- doc = html.strip()
171
- if not doc or ('<html' not in doc.lower()):
172
- doc = (
173
- "<!DOCTYPE html>\n"
174
- "<html>\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Transformers.js App</title>\n</head>\n"
175
- "<body>\n<div id=\"app\"></div>\n</body>\n</html>"
176
- )
177
-
178
- # Remove local file references
179
- doc = re.sub(r"<link[^>]+href=\"[^\"]*style\.css\"[^>]*>\s*", "", doc, flags=re.IGNORECASE)
180
- doc = re.sub(r"<script[^>]+src=\"[^\"]*index\.js\"[^>]*>\s*</script>\s*", "", doc, flags=re.IGNORECASE)
181
-
182
- # Inline CSS
183
- if css:
184
- style_tag = f"<style>\n{css}\n</style>"
185
- if '</head>' in doc.lower():
186
- match = re.search(r"</head>", doc, flags=re.IGNORECASE)
187
- if match:
188
- idx = match.start()
189
- doc = doc[:idx] + style_tag + doc[idx:]
190
- else:
191
- match = re.search(r"<body[^>]*>", doc, flags=re.IGNORECASE)
192
- if match:
193
- idx = match.end()
194
- doc = doc[:idx] + "\n" + style_tag + doc[idx:]
195
- else:
196
- doc = style_tag + doc
197
-
198
- # Inline JS with debugging and cleanup
199
- if js:
200
- script_tag = f"<script type=\"module\">\n{js}\n</script>"
201
- debug_overlay = TransformersJSProcessor._create_debug_overlay()
202
- cleanup_tag = TransformersJSProcessor._create_cleanup_script()
203
-
204
- match = re.search(r"</body>", doc, flags=re.IGNORECASE)
205
- if match:
206
- idx = match.start()
207
- doc = doc[:idx] + debug_overlay + script_tag + cleanup_tag + doc[idx:]
208
- else:
209
- doc = doc + debug_overlay + script_tag + cleanup_tag
210
-
211
- return doc
212
-
213
- @staticmethod
214
- def _create_debug_overlay() -> str:
215
- """Create debug overlay for transformers.js apps"""
216
- return (
217
- "<style>\n"
218
- "#anycoder-debug{position:fixed;left:0;right:0;bottom:0;max-height:45%;overflow:auto;"
219
- "background:rgba(0,0,0,.85);color:#9eff9e;padding:.5em;font:12px/1.4 monospace;z-index:2147483647;display:none}"
220
- "#anycoder-debug pre{margin:0;white-space:pre-wrap;word-break:break-word}"
221
- "</style>\n"
222
- "<div id=\"anycoder-debug\"></div>\n"
223
- "<script>\n"
224
- "(function(){\n"
225
- " const el = document.getElementById('anycoder-debug');\n"
226
- " function show(){ if(el && el.style.display!=='block'){ el.style.display='block'; } }\n"
227
- " function log(msg){ try{ show(); const pre=document.createElement('pre'); pre.textContent=msg; el.appendChild(pre);}catch(e){} }\n"
228
- " const origError = console.error.bind(console);\n"
229
- " console.error = function(){ origError.apply(console, arguments); try{ log('console.error: ' + Array.from(arguments).map(a=>{try{return (typeof a==='string')?a:JSON.stringify(a);}catch(e){return String(a);}}).join(' ')); }catch(e){} };\n"
230
- " window.addEventListener('error', e => { log('window.onerror: ' + (e && e.message ? e.message : 'Unknown error')); });\n"
231
- " window.addEventListener('unhandledrejection', e => { try{ const r=e && e.reason; log('unhandledrejection: ' + (r && (r.message || JSON.stringify(r)))); }catch(err){ log('unhandledrejection'); } });\n"
232
- "})();\n"
233
- "</script>"
234
- )
235
-
236
- @staticmethod
237
- def _create_cleanup_script() -> str:
238
- """Create cleanup script for transformers.js apps"""
239
- return (
240
- "<script>\n"
241
- "(function(){\n"
242
- " function cleanup(){\n"
243
- " try { if (window.caches && caches.keys) { caches.keys().then(keys => keys.forEach(k => caches.delete(k))); } } catch(e){}\n"
244
- " try { if (window.indexedDB && indexedDB.databases) { indexedDB.databases().then(dbs => dbs.forEach(db => db && db.name && indexedDB.deleteDatabase(db.name))); } } catch(e){}\n"
245
- " }\n"
246
- " window.addEventListener('pagehide', cleanup, { once: true });\n"
247
- " window.addEventListener('beforeunload', cleanup, { once: true });\n"
248
- "})();\n"
249
- "</script>"
250
- )
251
-
252
- class SvelteProcessor:
253
- """Handles Svelte specific code processing"""
254
-
255
- @staticmethod
256
- def parse_svelte_output(text: str) -> Dict[str, str]:
257
- """Parse Svelte output to extract individual files"""
258
- files = {
259
- 'src/App.svelte': '',
260
- 'src/app.css': ''
261
- }
262
-
263
- if not text:
264
- return files
265
-
266
- # Extract using code block patterns
267
- svelte_pattern = r'```svelte\s*\n([\s\S]+?)\n```'
268
- css_pattern = r'```css\s*\n([\s\S]+?)\n```'
269
-
270
- svelte_match = re.search(svelte_pattern, text, re.IGNORECASE)
271
- css_match = re.search(css_pattern, text, re.IGNORECASE)
272
-
273
- if svelte_match:
274
- files['src/App.svelte'] = svelte_match.group(1).strip()
275
- if css_match:
276
- files['src/app.css'] = css_match.group(1).strip()
277
-
278
- # Fallback: support === filename === format
279
- if not (files['src/App.svelte'] and files['src/app.css']):
280
- fallback_files = MultipageProcessor.parse_multipage_html_output(text)
281
- for key in files.keys():
282
- if key in fallback_files:
283
- files[key] = fallback_files[key]
284
-
285
- return files
286
-
287
- @staticmethod
288
- def format_svelte_output(files: Dict[str, str]) -> str:
289
- """Format Svelte files into a single display string"""
290
- output = []
291
- output.append("=== src/App.svelte ===")
292
- output.append(files.get('src/App.svelte', ''))
293
- output.append("\n=== src/app.css ===")
294
- output.append(files.get('src/app.css', ''))
295
- return '\n'.join(output)
296
-
297
- class MultipageProcessor:
298
- """Handles multi-page HTML projects"""
299
-
300
- @staticmethod
301
- def parse_multipage_html_output(text: str) -> Dict[str, str]:
302
- """Parse multi-page HTML output formatted as === filename === sections"""
303
- if not text:
304
- return {}
305
-
306
- from utils import remove_code_block
307
- cleaned = remove_code_block(text)
308
- files: Dict[str, str] = {}
309
-
310
- pattern = re.compile(r"^===\s*([^=\n]+?)\s*===\s*\n([\s\S]*?)(?=\n===\s*[^=\n]+?\s*===|\Z)", re.MULTILINE)
311
-
312
- for m in pattern.finditer(cleaned):
313
- name = m.group(1).strip()
314
- content = m.group(2).strip()
315
- # Remove accidental trailing fences
316
- content = re.sub(r"^```\w*\s*\n|\n```\s*$", "", content)
317
- files[name] = content
318
-
319
- return files
320
-
321
- @staticmethod
322
- def format_multipage_output(files: Dict[str, str]) -> str:
323
- """Format files back into === filename === sections"""
324
- if not isinstance(files, dict) or not files:
325
- return ""
326
-
327
- # Order with index.html first
328
- ordered_paths = []
329
- if 'index.html' in files:
330
- ordered_paths.append('index.html')
331
- for path in sorted(files.keys()):
332
- if path == 'index.html':
333
- continue
334
- ordered_paths.append(path)
335
-
336
- parts: List[str] = []
337
- for path in ordered_paths:
338
- parts.append(f"=== {path} ===")
339
- parts.append((files.get(path) or '').rstrip())
340
-
341
- return "\n".join(parts)
342
-
343
- @staticmethod
344
- def validate_and_autofix_files(files: Dict[str, str]) -> Dict[str, str]:
345
- """Ensure minimal contract for multi-file sites"""
346
- if not isinstance(files, dict) or not files:
347
- return files or {}
348
-
349
- normalized: Dict[str, str] = {}
350
- for k, v in files.items():
351
- safe_key = k.strip().lstrip('/')
352
- normalized[safe_key] = v
353
-
354
- html_files = [p for p in normalized.keys() if p.lower().endswith('.html')]
355
- has_index = 'index.html' in normalized
356
-
357
- # Create index.html if missing but other HTML files exist
358
- if not has_index and html_files:
359
- links = '\n'.join([f"<li><a href=\"{p}\">{p}</a></li>" for p in html_files])
360
- normalized['index.html'] = (
361
- "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\"/>\n"
362
- "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n"
363
- "<title>Site Index</title>\n</head>\n<body>\n<h1>Site</h1>\n<ul>\n"
364
- + links + "\n</ul>\n</body>\n</html>"
365
- )
366
-
367
- # Collect asset references
368
- asset_refs: set[str] = set()
369
- patterns = [
370
- re.compile(r"<link[^>]+href=\"([^\"]+)\""),
371
- re.compile(r"<script[^>]+src=\"([^\"]+)\""),
372
- re.compile(r"<img[^>]+src=\"([^\"]+)\""),
373
- re.compile(r"<a[^>]+href=\"([^\"]+)\"")
374
- ]
375
-
376
- for path, content in list(normalized.items()):
377
- if not path.lower().endswith('.html'):
378
- continue
379
- for patt in patterns:
380
- for m in patt.finditer(content or ""):
381
- ref = (m.group(1) or "").strip()
382
- if not ref or ref.startswith(('http://', 'https://', 'data:', '#')):
383
- continue
384
- asset_refs.add(ref.lstrip('/'))
385
-
386
- # Add minimal stubs for missing references
387
- for ref in list(asset_refs):
388
- if ref not in normalized:
389
- if ref.lower().endswith('.css'):
390
- normalized[ref] = "/* generated stub */\n"
391
- elif ref.lower().endswith('.js'):
392
- normalized[ref] = "// generated stub\n"
393
- elif ref.lower().endswith('.html'):
394
- normalized[ref] = (
395
- "<!DOCTYPE html>\n<html lang=\"en\">\n<head><meta charset=\"utf-8\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/><title>Page</title></head>\n"
396
- "<body><main><h1>Placeholder page</h1><p>This page was auto-created to satisfy an internal link.</p></main></body>\n</html>"
397
- )
398
-
399
- return normalized
400
-
401
- @staticmethod
402
- def inline_multipage_into_single_preview(files: Dict[str, str]) -> str:
403
- """Inline local CSS/JS for iframe preview"""
404
- html = files.get('index.html', '')
405
- if not html:
406
- return ""
407
-
408
- doc = html
409
-
410
- # Inline CSS links
411
- def _inline_css(match):
412
- href = match.group(1)
413
- if href in files:
414
- return f"<style>\n{files[href]}\n</style>"
415
- return match.group(0)
416
-
417
- doc = re.sub(r"<link[^>]+href=\"([^\"]+)\"[^>]*/?>", _inline_css, doc, flags=re.IGNORECASE)
418
-
419
- # Inline JS scripts
420
- def _inline_js(match):
421
- src = match.group(1)
422
- if src in files:
423
- return f"<script>\n{files[src]}\n</script>"
424
- return match.group(0)
425
-
426
- doc = re.sub(r"<script[^>]+src=\"([^\"]+)\"[^>]*>\s*</script>", _inline_js, doc, flags=re.IGNORECASE)
427
-
428
- # Add client-side navigation for other pages
429
- MultipageProcessor._add_client_side_navigation(doc, files)
430
-
431
- return doc
432
-
433
- @staticmethod
434
- def _add_client_side_navigation(doc: str, files: Dict[str, str]) -> str:
435
- """Add client-side navigation for multi-page preview"""
436
- try:
437
- html_pages = {k: v for k, v in files.items() if k.lower().endswith('.html')}
438
-
439
- # Extract body content for each page
440
- _index_body = re.search(r"<body[^>]*>([\s\S]*?)</body>", doc, flags=re.IGNORECASE)
441
- html_pages['index.html'] = _index_body.group(1) if _index_body else doc
442
-
443
- encoded = base64.b64encode(json.dumps(html_pages).encode('utf-8')).decode('ascii')
444
-
445
- nav_script = (
446
- "<script>\n"
447
- "(function(){\n"
448
- f" const MP_FILES = JSON.parse(atob('{encoded}'));\n"
449
- " function extractBody(html){\n"
450
- " try {\n"
451
- " const doc = new DOMParser().parseFromString(html, 'text/html');\n"
452
- " const title = doc.querySelector('title'); if (title) document.title = title.textContent || document.title;\n"
453
- " return doc.body ? doc.body.innerHTML : html;\n"
454
- " } catch(e){ return html; }\n"
455
- " }\n"
456
- " function loadPage(path){\n"
457
- " if (!MP_FILES[path]) return false;\n"
458
- " const bodyHTML = extractBody(MP_FILES[path]);\n"
459
- " document.body.innerHTML = bodyHTML;\n"
460
- " attach();\n"
461
- " try { history.replaceState({}, '', '#'+path); } catch(e){}\n"
462
- " return true;\n"
463
- " }\n"
464
- " function clickHandler(e){\n"
465
- " const a = e.target && e.target.closest ? e.target.closest('a') : null;\n"
466
- " if (!a) return;\n"
467
- " const href = a.getAttribute('href') || '';\n"
468
- " if (!href || href.startsWith('#') || /^https?:/i.test(href) || href.startsWith('mailto:') || href.startsWith('tel:')) return;\n"
469
- " const clean = href.split('#')[0].split('?')[0];\n"
470
- " if (MP_FILES[clean]) { e.preventDefault(); loadPage(clean); }\n"
471
- " }\n"
472
- " function attach(){ document.removeEventListener('click', clickHandler, true); document.addEventListener('click', clickHandler, true); }\n"
473
- " document.addEventListener('DOMContentLoaded', function(){ attach(); const initial = (location.hash||'').slice(1); if (initial && MP_FILES[initial]) loadPage(initial); }, { once:true });\n"
474
- "})();\n"
475
- "</script>"
476
- )
477
-
478
- m = re.search(r"</body>", doc, flags=re.IGNORECASE)
479
- if m:
480
- i = m.start()
481
- doc = doc[:i] + nav_script + doc[i:]
482
- else:
483
- doc = doc + nav_script
484
-
485
- except Exception:
486
- pass # Non-fatal in preview
487
-
488
- return doc
489
-
490
- class MediaIntegrator:
491
- """Handles integration of generated media into code"""
492
-
493
- @staticmethod
494
- def apply_generated_media_to_html(html_content: str, user_prompt: str,
495
- enable_text_to_image: bool = False,
496
- enable_image_to_image: bool = False,
497
- input_image_data=None,
498
- image_to_image_prompt: Optional[str] = None,
499
- text_to_image_prompt: Optional[str] = None,
500
- enable_image_to_video: bool = False,
501
- image_to_video_prompt: Optional[str] = None,
502
- session_id: Optional[str] = None,
503
- enable_text_to_video: bool = False,
504
- text_to_video_prompt: Optional[str] = None,
505
- enable_text_to_music: bool = False,
506
- text_to_music_prompt: Optional[str] = None,
507
- token=None) -> str:
508
- """Apply media generation to HTML content"""
509
-
510
- # Detect multi-page structure
511
- is_multipage = False
512
- multipage_files = {}
513
- entry_html_path = None
514
-
515
- try:
516
- multipage_files = MultipageProcessor.parse_multipage_html_output(html_content) or {}
517
- if multipage_files:
518
- is_multipage = True
519
- entry_html_path = 'index.html' if 'index.html' in multipage_files else next((p for p in multipage_files.keys() if p.lower().endswith('.html')), None)
520
- except Exception:
521
- pass
522
-
523
- result = multipage_files.get(entry_html_path, html_content) if is_multipage and entry_html_path else html_content
524
-
525
- try:
526
- # Process media generation based on priority
527
- if enable_image_to_video and input_image_data is not None:
528
- result = MediaIntegrator._apply_image_to_video(result, user_prompt, image_to_video_prompt, input_image_data, session_id, token)
529
- elif enable_text_to_video:
530
- result = MediaIntegrator._apply_text_to_video(result, user_prompt, text_to_video_prompt, session_id, token)
531
- elif enable_text_to_music:
532
- result = MediaIntegrator._apply_text_to_music(result, user_prompt, text_to_music_prompt, session_id, token)
533
- elif enable_image_to_image and input_image_data is not None:
534
- result = MediaIntegrator._apply_image_to_image(result, user_prompt, image_to_image_prompt, input_image_data, token)
535
- elif enable_text_to_image:
536
- result = MediaIntegrator._apply_text_to_image(result, user_prompt, text_to_image_prompt, token)
537
- except Exception as e:
538
- print(f"[MediaApply] Error during media generation: {str(e)}")
539
-
540
- # Return updated content
541
- if is_multipage and entry_html_path:
542
- multipage_files[entry_html_path] = result
543
- return MultipageProcessor.format_multipage_output(multipage_files)
544
-
545
- return result
546
-
547
- @staticmethod
548
- def _apply_image_to_video(html_content: str, user_prompt: str, prompt: Optional[str],
549
- input_image_data, session_id: Optional[str], token) -> str:
550
- """Apply image-to-video generation"""
551
- i2v_prompt = (prompt or user_prompt or "").strip()
552
- print(f"[MediaApply] Applying image-to-video with prompt: {i2v_prompt}")
553
-
554
- try:
555
- video_html_tag = generate_video_from_image(input_image_data, i2v_prompt, session_id=session_id, token=token)
556
- if not video_html_tag.startswith("Error") and validate_video_html(video_html_tag):
557
- return MediaIntegrator._place_media_in_html(html_content, video_html_tag, "video")
558
- except Exception as e:
559
- print(f"[MediaApply] Image-to-video generation failed: {str(e)}")
560
-
561
- return html_content
562
-
563
- @staticmethod
564
- def _apply_text_to_video(html_content: str, user_prompt: str, prompt: Optional[str],
565
- session_id: Optional[str], token) -> str:
566
- """Apply text-to-video generation"""
567
- t2v_prompt = (prompt or user_prompt or "").strip()
568
- print(f"[MediaApply] Applying text-to-video with prompt: {t2v_prompt}")
569
-
570
- try:
571
- video_html_tag = generate_video_from_text(t2v_prompt, session_id=session_id, token=token)
572
- if not video_html_tag.startswith("Error") and validate_video_html(video_html_tag):
573
- return MediaIntegrator._place_media_in_html(html_content, video_html_tag, "video")
574
- except Exception as e:
575
- print(f"[MediaApply] Text-to-video generation failed: {str(e)}")
576
-
577
- return html_content
578
-
579
- @staticmethod
580
- def _apply_text_to_music(html_content: str, user_prompt: str, prompt: Optional[str],
581
- session_id: Optional[str], token) -> str:
582
- """Apply text-to-music generation"""
583
- t2m_prompt = (prompt or user_prompt or "").strip()
584
- print(f"[MediaApply] Applying text-to-music with prompt: {t2m_prompt}")
585
-
586
- try:
587
- audio_html_tag = generate_music_from_text(t2m_prompt, session_id=session_id, token=token)
588
- if not audio_html_tag.startswith("Error"):
589
- return MediaIntegrator._place_media_in_html(html_content, audio_html_tag, "audio")
590
- except Exception as e:
591
- print(f"[MediaApply] Text-to-music generation failed: {str(e)}")
592
-
593
- return html_content
594
-
595
- @staticmethod
596
- def _apply_image_to_image(html_content: str, user_prompt: str, prompt: Optional[str],
597
- input_image_data, token) -> str:
598
- """Apply image-to-image generation"""
599
- i2i_prompt = (prompt or user_prompt or "").strip()
600
- print(f"[MediaApply] Applying image-to-image with prompt: {i2i_prompt}")
601
-
602
- try:
603
- image_html_tag = generate_image_to_image(input_image_data, i2i_prompt, token=token)
604
- if not image_html_tag.startswith("Error"):
605
- return MediaIntegrator._place_media_in_html(html_content, image_html_tag, "image")
606
- except Exception as e:
607
- print(f"[MediaApply] Image-to-image generation failed: {str(e)}")
608
-
609
- return html_content
610
-
611
- @staticmethod
612
- def _apply_text_to_image(html_content: str, user_prompt: str, prompt: Optional[str], token) -> str:
613
- """Apply text-to-image generation"""
614
- t2i_prompt = (prompt or user_prompt or "").strip()
615
- print(f"[MediaApply] Applying text-to-image with prompt: {t2i_prompt}")
616
-
617
- try:
618
- image_html_tag = generate_image_with_qwen(t2i_prompt, 0, token=token)
619
- if not image_html_tag.startswith("Error"):
620
- return MediaIntegrator._place_media_in_html(html_content, image_html_tag, "image")
621
- except Exception as e:
622
- print(f"[MediaApply] Text-to-image generation failed: {str(e)}")
623
-
624
- return html_content
625
-
626
- @staticmethod
627
- def _place_media_in_html(html_content: str, media_html: str, media_type: str) -> str:
628
- """Place generated media in appropriate location in HTML"""
629
- # Find good insertion points
630
- insertion_patterns = [
631
- r'(<main[^>]*>)',
632
- r'(<section[^>]*class="[^"]*hero[^"]*"[^>]*>)',
633
- r'(<div[^>]*class="[^"]*container[^"]*"[^>]*>)',
634
- r'(<body[^>]*>)'
635
- ]
636
-
637
- for pattern in insertion_patterns:
638
- match = re.search(pattern, html_content, re.IGNORECASE)
639
- if match:
640
- insertion_point = match.end()
641
- container_class = "video-container" if media_type == "video" else f"{media_type}-container"
642
- media_with_container = f'\n <div class="{container_class}" style="margin: 20px 0; text-align: center;">\n {media_html}\n </div>'
643
- return html_content[:insertion_point] + media_with_container + html_content[insertion_point:]
644
-
645
- # Fallback: append before closing body
646
- body_close = html_content.rfind('</body>')
647
- if body_close != -1:
648
- return html_content[:body_close] + f'\n {media_html}\n' + html_content[body_close:]
649
-
650
- # Last resort: append at end
651
- return html_content + f'\n{media_html}'
652
-
653
- # Export main functions and classes
654
- code_processor = CodeProcessor()
655
- transformers_processor = TransformersJSProcessor()
656
- svelte_processor = SvelteProcessor()
657
- multipage_processor = MultipageProcessor()
658
- media_integrator = MediaIntegrator()
659
-
660
- # Main exports
661
- def is_streamlit_code(code: str) -> bool:
662
- return code_processor.is_streamlit_code(code)
663
-
664
- def is_gradio_code(code: str) -> bool:
665
- return code_processor.is_gradio_code(code)
666
-
667
- def extract_html_document(text: str) -> str:
668
- return code_processor.extract_html_document(text)
669
-
670
- def parse_transformers_js_output(text: str) -> Dict[str, str]:
671
- return transformers_processor.parse_transformers_js_output(text)
672
-
673
- def format_transformers_js_output(files: Dict[str, str]) -> str:
674
- return transformers_processor.format_transformers_js_output(files)
675
-
676
- def build_transformers_inline_html(files: Dict[str, str]) -> str:
677
- return transformers_processor.build_transformers_inline_html(files)
678
-
679
- def parse_svelte_output(text: str) -> Dict[str, str]:
680
- return svelte_processor.parse_svelte_output(text)
681
-
682
- def format_svelte_output(files: Dict[str, str]) -> str:
683
- return svelte_processor.format_svelte_output(files)
684
-
685
- def parse_multipage_html_output(text: str) -> Dict[str, str]:
686
- return multipage_processor.parse_multipage_html_output(text)
687
-
688
- def format_multipage_output(files: Dict[str, str]) -> str:
689
- return multipage_processor.format_multipage_output(files)
690
-
691
- def validate_and_autofix_files(files: Dict[str, str]) -> Dict[str, str]:
692
- return multipage_processor.validate_and_autofix_files(files)
693
-
694
- def inline_multipage_into_single_preview(files: Dict[str, str]) -> str:
695
- return multipage_processor.inline_multipage_into_single_preview(files)
696
-
697
- def apply_generated_media_to_html(html_content: str, user_prompt: str, **kwargs) -> str:
698
- return media_integrator.apply_generated_media_to_html(html_content, user_prompt, **kwargs)