akhaliq HF Staff commited on
Commit
dc37bd7
·
1 Parent(s): ece97e8

dynamic files

Browse files
Files changed (1) hide show
  1. app.py +119 -2
app.py CHANGED
@@ -428,6 +428,45 @@ Follow the same file output format and project structure as specified:
428
  Use search results to apply current best practices in accessibility, semantics, responsive meta tags, and performance (preconnect, responsive images).
429
  """
430
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
431
  GENERIC_SYSTEM_PROMPT_WITH_SEARCH = """You are an expert {language} developer. You have access to real-time web search. When needed, use web search to find the latest information, best practices, or specific technologies for {language}.
432
 
433
  Write clean, idiomatic, and runnable {language} code for the user's request. If possible, include comments and best practices. Output ONLY the code inside a ``` code block, and do not include any explanations or extra text. If the user provides a file or other context, use it as a reference. If the code is for a script or app, make it as self-contained as possible. Do NOT add the language name at the top of the code output."""
@@ -1243,6 +1282,73 @@ def parse_multipage_html_output(text: str) -> Dict[str, str]:
1243
  files[name] = content
1244
  return files
1245
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1246
  def inline_multipage_into_single_preview(files: Dict[str, str]) -> str:
1247
  """Inline local CSS/JS referenced by index.html for preview inside a data: iframe.
1248
 
@@ -3286,8 +3392,8 @@ def generation_code(query: Optional[str], vlm_image: Optional[gr.Image], gen_ima
3286
  else:
3287
  # Use language-specific prompt
3288
  if language == "html":
3289
- # Use multi-page format prompt to encourage production multi-file output
3290
- system_prompt = MULTIPAGE_HTML_SYSTEM_PROMPT_WITH_SEARCH if enable_search else MULTIPAGE_HTML_SYSTEM_PROMPT
3291
  elif language == "transformers.js":
3292
  system_prompt = TRANSFORMERS_JS_SYSTEM_PROMPT_WITH_SEARCH if enable_search else TRANSFORMERS_JS_SYSTEM_PROMPT
3293
  elif language == "svelte":
@@ -3358,6 +3464,7 @@ This will help me create a better design for you."""
3358
  preview_val = None
3359
  if language == "html":
3360
  _mp = parse_multipage_html_output(clean_code)
 
3361
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mp)) if _mp.get('index.html') else send_to_sandbox(clean_code)
3362
  elif language == "python" and is_streamlit_code(clean_code):
3363
  preview_val = send_streamlit_to_stlite(clean_code)
@@ -3588,6 +3695,7 @@ This will help me create a better design for you."""
3588
  preview_val = None
3589
  if language == "html":
3590
  _mpf2 = parse_multipage_html_output(final_content)
 
3591
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mpf2)) if _mpf2.get('index.html') else send_to_sandbox(final_content)
3592
  elif language == "python" and is_streamlit_code(final_content):
3593
  preview_val = send_streamlit_to_stlite(final_content)
@@ -3655,6 +3763,7 @@ This will help me create a better design for you."""
3655
  preview_val = None
3656
  if language == "html":
3657
  _mpc = parse_multipage_html_output(clean_code)
 
3658
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mpc)) if _mpc.get('index.html') else send_to_sandbox(clean_code)
3659
  elif language == "python" and is_streamlit_code(clean_code):
3660
  preview_val = send_streamlit_to_stlite(clean_code)
@@ -3675,6 +3784,7 @@ This will help me create a better design for you."""
3675
  preview_val = None
3676
  if language == "html":
3677
  _mpc2 = parse_multipage_html_output(clean_code)
 
3678
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mpc2)) if _mpc2.get('index.html') else send_to_sandbox(clean_code)
3679
  elif language == "python" and is_streamlit_code(clean_code):
3680
  preview_val = send_streamlit_to_stlite(clean_code)
@@ -3852,6 +3962,7 @@ This will help me create a better design for you."""
3852
  preview_val = None
3853
  if language == "html":
3854
  _mpc3 = parse_multipage_html_output(clean_code)
 
3855
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mpc3)) if _mpc3.get('index.html') else send_to_sandbox(clean_code)
3856
  elif language == "python" and is_streamlit_code(clean_code):
3857
  preview_val = send_streamlit_to_stlite(clean_code)
@@ -3870,6 +3981,7 @@ This will help me create a better design for you."""
3870
  preview_val = None
3871
  if language == "html":
3872
  _mpc4 = parse_multipage_html_output(clean_content)
 
3873
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mpc4)) if _mpc4.get('index.html') else send_to_sandbox(clean_content)
3874
  elif language == "python" and is_streamlit_code(clean_content):
3875
  preview_val = send_streamlit_to_stlite(clean_content)
@@ -3884,6 +3996,7 @@ This will help me create a better design for you."""
3884
  preview_val = None
3885
  if language == "html":
3886
  _mpc5 = parse_multipage_html_output(clean_code)
 
3887
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mpc5)) if _mpc5.get('index.html') else send_to_sandbox(clean_code)
3888
  elif language == "python" and is_streamlit_code(clean_code):
3889
  preview_val = send_streamlit_to_stlite(clean_code)
@@ -4030,6 +4143,7 @@ This will help me create a better design for you."""
4030
  preview_val = None
4031
  if language == "html":
4032
  _mpf = parse_multipage_html_output(final_content)
 
4033
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mpf)) if _mpf.get('index.html') else send_to_sandbox(final_content)
4034
  elif language == "python" and is_streamlit_code(final_content):
4035
  preview_val = send_streamlit_to_stlite(final_content)
@@ -5173,6 +5287,7 @@ with gr.Blocks(
5173
  value=False,
5174
  visible=True
5175
  )
 
5176
  # Image generation toggles
5177
  image_generation_toggle = gr.Checkbox(
5178
  label="🎨 Generate Images (text → image)",
@@ -5491,6 +5606,7 @@ with gr.Blocks(
5491
  if language == "html":
5492
  # If the content is a multi-page block, inline for preview; else render directly
5493
  files = parse_multipage_html_output(code)
 
5494
  if files and files.get('index.html'):
5495
  merged = inline_multipage_into_single_preview(files)
5496
  return send_to_sandbox(merged)
@@ -6381,6 +6497,7 @@ with gr.Blocks(
6381
  files = {}
6382
  try:
6383
  files = parse_multipage_html_output(code)
 
6384
  except Exception:
6385
  files = {}
6386
 
 
428
  Use search results to apply current best practices in accessibility, semantics, responsive meta tags, and performance (preconnect, responsive images).
429
  """
430
 
431
+ # Dynamic multi-page (model decides files) prompts
432
+ DYNAMIC_MULTIPAGE_HTML_SYSTEM_PROMPT = """You are an expert front-end developer.
433
+
434
+ Create a production-ready website using ONLY HTML, CSS, and vanilla JavaScript. Do NOT use SPA frameworks.
435
+
436
+ File selection policy:
437
+ - Generate ONLY the files actually needed for the user's request.
438
+ - Include at least one HTML entrypoint (default: index.html) unless the user explicitly requests a non-HTML asset only.
439
+ - If any local asset (CSS/JS/image) is referenced, include that file in the output.
440
+ - Use relative paths between files (e.g., assets/css/styles.css).
441
+
442
+ Output format (CRITICAL):
443
+ - Return ONLY a series of file sections, each starting with a filename line:
444
+ === index.html ===
445
+ ...file content...
446
+
447
+ === assets/css/styles.css ===
448
+ ...file content...
449
+
450
+ (repeat for all files)
451
+ - Do NOT wrap files in Markdown code fences
452
+
453
+ General requirements:
454
+ - Use modern, semantic HTML
455
+ - Mobile-first responsive design
456
+ - Include basic SEO meta tags in <head> for the entrypoint
457
+ - Include a footer on all major pages when multiple pages are present
458
+ - Avoid external CSS/JS frameworks (optional: CDN fonts/icons allowed)
459
+ """
460
+
461
+ DYNAMIC_MULTIPAGE_HTML_SYSTEM_PROMPT_WITH_SEARCH = """You are an expert front-end developer. You have access to real-time web search.
462
+
463
+ Create a production-ready website using ONLY HTML, CSS, and vanilla JavaScript. Do NOT use SPA frameworks.
464
+
465
+ Follow the same output format and file selection policy as above (=== filename === blocks; model decides which files to create; ensure index.html unless explicitly not needed).
466
+
467
+ Use search results to apply current best practices in accessibility, semantics, responsive meta tags, and performance (preconnect, responsive images).
468
+ """
469
+
470
  GENERIC_SYSTEM_PROMPT_WITH_SEARCH = """You are an expert {language} developer. You have access to real-time web search. When needed, use web search to find the latest information, best practices, or specific technologies for {language}.
471
 
472
  Write clean, idiomatic, and runnable {language} code for the user's request. If possible, include comments and best practices. Output ONLY the code inside a ``` code block, and do not include any explanations or extra text. If the user provides a file or other context, use it as a reference. If the code is for a script or app, make it as self-contained as possible. Do NOT add the language name at the top of the code output."""
 
1282
  files[name] = content
1283
  return files
1284
 
1285
+ def validate_and_autofix_files(files: Dict[str, str]) -> Dict[str, str]:
1286
+ """Ensure minimal contract for multi-file sites; auto-fix missing pieces.
1287
+
1288
+ Rules:
1289
+ - Ensure at least one HTML entrypoint (index.html). If none, synthesize a simple index.html linking discovered pages.
1290
+ - For each HTML file, ensure referenced local assets exist in files; if missing, add minimal stubs.
1291
+ - Normalize relative paths (strip leading '/').
1292
+ """
1293
+ if not isinstance(files, dict) or not files:
1294
+ return files or {}
1295
+ import re as _re
1296
+
1297
+ normalized: Dict[str, str] = {}
1298
+ for k, v in files.items():
1299
+ safe_key = k.strip().lstrip('/')
1300
+ normalized[safe_key] = v
1301
+
1302
+ html_files = [p for p in normalized.keys() if p.lower().endswith('.html')]
1303
+ has_index = 'index.html' in normalized
1304
+
1305
+ # If no index.html but some HTML pages exist, create a simple hub index linking to them
1306
+ if not has_index and html_files:
1307
+ links = '\n'.join([f"<li><a href=\"{p}\">{p}</a></li>" for p in html_files])
1308
+ normalized['index.html'] = (
1309
+ "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\"/>\n"
1310
+ "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n"
1311
+ "<title>Site Index</title>\n</head>\n<body>\n<h1>Site</h1>\n<ul>\n"
1312
+ + links + "\n</ul>\n</body>\n</html>"
1313
+ )
1314
+
1315
+ # Collect references from HTML files
1316
+ asset_refs: set[str] = set()
1317
+ link_href = _re.compile(r"<link[^>]+href=\"([^\"]+)\"")
1318
+ script_src = _re.compile(r"<script[^>]+src=\"([^\"]+)\"")
1319
+ img_src = _re.compile(r"<img[^>]+src=\"([^\"]+)\"")
1320
+ a_href = _re.compile(r"<a[^>]+href=\"([^\"]+)\"")
1321
+
1322
+ for path, content in list(normalized.items()):
1323
+ if not path.lower().endswith('.html'):
1324
+ continue
1325
+ for patt in (link_href, script_src, img_src, a_href):
1326
+ for m in patt.finditer(content or ""):
1327
+ ref = (m.group(1) or "").strip()
1328
+ if not ref or ref.startswith('http://') or ref.startswith('https://') or ref.startswith('data:') or '#' in ref:
1329
+ continue
1330
+ asset_refs.add(ref.lstrip('/'))
1331
+
1332
+ # Add minimal stubs for missing local references (CSS/JS/images/pages)
1333
+ for ref in list(asset_refs):
1334
+ if ref not in normalized:
1335
+ if ref.lower().endswith('.css'):
1336
+ normalized[ref] = "/* generated stub */\n"
1337
+ elif ref.lower().endswith('.js'):
1338
+ normalized[ref] = "// generated stub\n"
1339
+ elif any(ref.lower().endswith(ext) for ext in ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp']):
1340
+ # Use a tiny inline SVG as placeholder content
1341
+ normalized[ref] = (
1342
+ "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1\" height=\"1\"></svg>\n"
1343
+ )
1344
+ elif ref.lower().endswith('.html'):
1345
+ normalized[ref] = (
1346
+ "<!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"
1347
+ "<body><main><h1>Placeholder page</h1><p>This page was auto-created to satisfy an internal link.</p></main></body>\n</html>"
1348
+ )
1349
+
1350
+ return normalized
1351
+
1352
  def inline_multipage_into_single_preview(files: Dict[str, str]) -> str:
1353
  """Inline local CSS/JS referenced by index.html for preview inside a data: iframe.
1354
 
 
3392
  else:
3393
  # Use language-specific prompt
3394
  if language == "html":
3395
+ # Dynamic file selection always enabled
3396
+ system_prompt = DYNAMIC_MULTIPAGE_HTML_SYSTEM_PROMPT_WITH_SEARCH if enable_search else DYNAMIC_MULTIPAGE_HTML_SYSTEM_PROMPT
3397
  elif language == "transformers.js":
3398
  system_prompt = TRANSFORMERS_JS_SYSTEM_PROMPT_WITH_SEARCH if enable_search else TRANSFORMERS_JS_SYSTEM_PROMPT
3399
  elif language == "svelte":
 
3464
  preview_val = None
3465
  if language == "html":
3466
  _mp = parse_multipage_html_output(clean_code)
3467
+ _mp = validate_and_autofix_files(_mp)
3468
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mp)) if _mp.get('index.html') else send_to_sandbox(clean_code)
3469
  elif language == "python" and is_streamlit_code(clean_code):
3470
  preview_val = send_streamlit_to_stlite(clean_code)
 
3695
  preview_val = None
3696
  if language == "html":
3697
  _mpf2 = parse_multipage_html_output(final_content)
3698
+ _mpf2 = validate_and_autofix_files(_mpf2)
3699
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mpf2)) if _mpf2.get('index.html') else send_to_sandbox(final_content)
3700
  elif language == "python" and is_streamlit_code(final_content):
3701
  preview_val = send_streamlit_to_stlite(final_content)
 
3763
  preview_val = None
3764
  if language == "html":
3765
  _mpc = parse_multipage_html_output(clean_code)
3766
+ _mpc = validate_and_autofix_files(_mpc)
3767
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mpc)) if _mpc.get('index.html') else send_to_sandbox(clean_code)
3768
  elif language == "python" and is_streamlit_code(clean_code):
3769
  preview_val = send_streamlit_to_stlite(clean_code)
 
3784
  preview_val = None
3785
  if language == "html":
3786
  _mpc2 = parse_multipage_html_output(clean_code)
3787
+ _mpc2 = validate_and_autofix_files(_mpc2)
3788
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mpc2)) if _mpc2.get('index.html') else send_to_sandbox(clean_code)
3789
  elif language == "python" and is_streamlit_code(clean_code):
3790
  preview_val = send_streamlit_to_stlite(clean_code)
 
3962
  preview_val = None
3963
  if language == "html":
3964
  _mpc3 = parse_multipage_html_output(clean_code)
3965
+ _mpc3 = validate_and_autofix_files(_mpc3)
3966
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mpc3)) if _mpc3.get('index.html') else send_to_sandbox(clean_code)
3967
  elif language == "python" and is_streamlit_code(clean_code):
3968
  preview_val = send_streamlit_to_stlite(clean_code)
 
3981
  preview_val = None
3982
  if language == "html":
3983
  _mpc4 = parse_multipage_html_output(clean_content)
3984
+ _mpc4 = validate_and_autofix_files(_mpc4)
3985
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mpc4)) if _mpc4.get('index.html') else send_to_sandbox(clean_content)
3986
  elif language == "python" and is_streamlit_code(clean_content):
3987
  preview_val = send_streamlit_to_stlite(clean_content)
 
3996
  preview_val = None
3997
  if language == "html":
3998
  _mpc5 = parse_multipage_html_output(clean_code)
3999
+ _mpc5 = validate_and_autofix_files(_mpc5)
4000
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mpc5)) if _mpc5.get('index.html') else send_to_sandbox(clean_code)
4001
  elif language == "python" and is_streamlit_code(clean_code):
4002
  preview_val = send_streamlit_to_stlite(clean_code)
 
4143
  preview_val = None
4144
  if language == "html":
4145
  _mpf = parse_multipage_html_output(final_content)
4146
+ _mpf = validate_and_autofix_files(_mpf)
4147
  preview_val = send_to_sandbox(inline_multipage_into_single_preview(_mpf)) if _mpf.get('index.html') else send_to_sandbox(final_content)
4148
  elif language == "python" and is_streamlit_code(final_content):
4149
  preview_val = send_streamlit_to_stlite(final_content)
 
5287
  value=False,
5288
  visible=True
5289
  )
5290
+ # Dynamic multipage is always enabled; no toggle in UI
5291
  # Image generation toggles
5292
  image_generation_toggle = gr.Checkbox(
5293
  label="🎨 Generate Images (text → image)",
 
5606
  if language == "html":
5607
  # If the content is a multi-page block, inline for preview; else render directly
5608
  files = parse_multipage_html_output(code)
5609
+ files = validate_and_autofix_files(files)
5610
  if files and files.get('index.html'):
5611
  merged = inline_multipage_into_single_preview(files)
5612
  return send_to_sandbox(merged)
 
6497
  files = {}
6498
  try:
6499
  files = parse_multipage_html_output(code)
6500
+ files = validate_and_autofix_files(files)
6501
  except Exception:
6502
  files = {}
6503