Spaces:
Running
Running
fix
Browse files
app.py
CHANGED
|
@@ -3035,6 +3035,54 @@ def send_to_sandbox(code):
|
|
| 3035 |
iframe = f'<iframe src="{data_uri}" width="100%" height="920px" sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-presentation" allow="display-capture"></iframe>'
|
| 3036 |
return iframe
|
| 3037 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3038 |
def is_streamlit_code(code: str) -> bool:
|
| 3039 |
"""Heuristic check to determine if Python code is a Streamlit app."""
|
| 3040 |
if not code:
|
|
@@ -3894,10 +3942,14 @@ This will help me create a better design for you."""
|
|
| 3894 |
|
| 3895 |
preview_val = None
|
| 3896 |
if language == "html":
|
| 3897 |
-
|
| 3898 |
-
_mpf2 = parse_multipage_html_output(
|
| 3899 |
_mpf2 = validate_and_autofix_files(_mpf2)
|
| 3900 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3901 |
elif language == "python" and is_streamlit_code(final_content):
|
| 3902 |
preview_val = send_streamlit_to_stlite(final_content)
|
| 3903 |
yield {
|
|
@@ -4319,7 +4371,7 @@ This will help me create a better design for you."""
|
|
| 4319 |
yield {
|
| 4320 |
code_output: clean_content,
|
| 4321 |
history: _history,
|
| 4322 |
-
sandbox: ((
|
| 4323 |
history_output: history_to_chatbot_messages(_history),
|
| 4324 |
}
|
| 4325 |
else:
|
|
@@ -4348,10 +4400,14 @@ This will help me create a better design for you."""
|
|
| 4348 |
_history.append([query, final_content])
|
| 4349 |
preview_val = None
|
| 4350 |
if language == "html":
|
| 4351 |
-
|
| 4352 |
-
_mpf = parse_multipage_html_output(
|
| 4353 |
_mpf = validate_and_autofix_files(_mpf)
|
| 4354 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4355 |
elif language == "python" and is_streamlit_code(final_content):
|
| 4356 |
preview_val = send_streamlit_to_stlite(final_content)
|
| 4357 |
elif language == "gradio" or (language == "python" and is_gradio_code(final_content)):
|
|
|
|
| 3035 |
iframe = f'<iframe src="{data_uri}" width="100%" height="920px" sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-presentation" allow="display-capture"></iframe>'
|
| 3036 |
return iframe
|
| 3037 |
|
| 3038 |
+
def send_to_sandbox_with_refresh(code):
|
| 3039 |
+
"""Render HTML in a sandboxed iframe with cache-busting for media generation updates."""
|
| 3040 |
+
import time
|
| 3041 |
+
html_doc = (code or "").strip()
|
| 3042 |
+
# For preview only: inline local file URLs (e.g., file:///.../video.mp4) as data URIs so the
|
| 3043 |
+
# data: iframe can load them. The original code (shown to the user) still contains file URLs.
|
| 3044 |
+
try:
|
| 3045 |
+
import re
|
| 3046 |
+
import base64 as _b64
|
| 3047 |
+
import mimetypes as _mtypes
|
| 3048 |
+
import urllib.parse as _uparse
|
| 3049 |
+
def _file_url_to_data_uri(file_url: str) -> str | None:
|
| 3050 |
+
try:
|
| 3051 |
+
parsed = _uparse.urlparse(file_url)
|
| 3052 |
+
path = _uparse.unquote(parsed.path)
|
| 3053 |
+
if not path:
|
| 3054 |
+
return None
|
| 3055 |
+
with open(path, 'rb') as _f:
|
| 3056 |
+
raw = _f.read()
|
| 3057 |
+
mime = _mtypes.guess_type(path)[0] or 'application/octet-stream'
|
| 3058 |
+
b64 = _b64.b64encode(raw).decode()
|
| 3059 |
+
return f"data:{mime};base64,{b64}"
|
| 3060 |
+
except Exception:
|
| 3061 |
+
return None
|
| 3062 |
+
def _repl_double(m):
|
| 3063 |
+
url = m.group(1)
|
| 3064 |
+
data_uri = _file_url_to_data_uri(url)
|
| 3065 |
+
return f'src="{data_uri}"' if data_uri else m.group(0)
|
| 3066 |
+
def _repl_single(m):
|
| 3067 |
+
url = m.group(1)
|
| 3068 |
+
data_uri = _file_url_to_data_uri(url)
|
| 3069 |
+
return f"src='{data_uri}'" if data_uri else m.group(0)
|
| 3070 |
+
html_doc = re.sub(r'src="(file:[^"]+)"', _repl_double, html_doc)
|
| 3071 |
+
html_doc = re.sub(r"src='(file:[^']+)'", _repl_single, html_doc)
|
| 3072 |
+
except Exception:
|
| 3073 |
+
# Best-effort; continue without inlining
|
| 3074 |
+
pass
|
| 3075 |
+
|
| 3076 |
+
# Add cache-busting timestamp to force iframe refresh when content changes
|
| 3077 |
+
timestamp = str(int(time.time() * 1000))
|
| 3078 |
+
cache_bust_comment = f"<!-- refresh-{timestamp} -->"
|
| 3079 |
+
html_doc = cache_bust_comment + html_doc
|
| 3080 |
+
|
| 3081 |
+
encoded_html = base64.b64encode(html_doc.encode('utf-8')).decode('utf-8')
|
| 3082 |
+
data_uri = f"data:text/html;charset=utf-8;base64,{encoded_html}"
|
| 3083 |
+
iframe = f'<iframe src="{data_uri}" width="100%" height="920px" sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-presentation" allow="display-capture" key="preview-{timestamp}"></iframe>'
|
| 3084 |
+
return iframe
|
| 3085 |
+
|
| 3086 |
def is_streamlit_code(code: str) -> bool:
|
| 3087 |
"""Heuristic check to determine if Python code is a Streamlit app."""
|
| 3088 |
if not code:
|
|
|
|
| 3942 |
|
| 3943 |
preview_val = None
|
| 3944 |
if language == "html":
|
| 3945 |
+
# Use full content for multipage detection, then extract for single-page rendering
|
| 3946 |
+
_mpf2 = parse_multipage_html_output(final_content)
|
| 3947 |
_mpf2 = validate_and_autofix_files(_mpf2)
|
| 3948 |
+
if _mpf2 and _mpf2.get('index.html'):
|
| 3949 |
+
preview_val = send_to_sandbox_with_refresh(inline_multipage_into_single_preview(_mpf2))
|
| 3950 |
+
else:
|
| 3951 |
+
safe_preview = extract_html_document(final_content)
|
| 3952 |
+
preview_val = send_to_sandbox_with_refresh(safe_preview)
|
| 3953 |
elif language == "python" and is_streamlit_code(final_content):
|
| 3954 |
preview_val = send_streamlit_to_stlite(final_content)
|
| 3955 |
yield {
|
|
|
|
| 4371 |
yield {
|
| 4372 |
code_output: clean_content,
|
| 4373 |
history: _history,
|
| 4374 |
+
sandbox: ((send_to_sandbox_with_refresh(inline_multipage_into_single_preview(parse_multipage_html_output(clean_content))) if parse_multipage_html_output(clean_content).get('index.html') else send_to_sandbox_with_refresh(clean_content)) if language == "html" else (send_streamlit_to_stlite(clean_content) if (language == "python" and is_streamlit_code(clean_content)) else "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML or Streamlit-in-Python.</div>")),
|
| 4375 |
history_output: history_to_chatbot_messages(_history),
|
| 4376 |
}
|
| 4377 |
else:
|
|
|
|
| 4400 |
_history.append([query, final_content])
|
| 4401 |
preview_val = None
|
| 4402 |
if language == "html":
|
| 4403 |
+
# Use full content for multipage detection, then extract for single-page rendering
|
| 4404 |
+
_mpf = parse_multipage_html_output(final_content)
|
| 4405 |
_mpf = validate_and_autofix_files(_mpf)
|
| 4406 |
+
if _mpf and _mpf.get('index.html'):
|
| 4407 |
+
preview_val = send_to_sandbox_with_refresh(inline_multipage_into_single_preview(_mpf))
|
| 4408 |
+
else:
|
| 4409 |
+
safe_preview = extract_html_document(final_content)
|
| 4410 |
+
preview_val = send_to_sandbox_with_refresh(safe_preview)
|
| 4411 |
elif language == "python" and is_streamlit_code(final_content):
|
| 4412 |
preview_val = send_streamlit_to_stlite(final_content)
|
| 4413 |
elif language == "gradio" or (language == "python" and is_gradio_code(final_content)):
|