catalog / scripts /wrap_plots.py
bruAristimunha's picture
Embed plots via iframes — gradio gr.HTML strips <script>, plots stayed blank
14a45ea
#!/usr/bin/env python
"""Wrap Plotly fragment HTMLs into standalone documents for iframe embedding.
Gradio 5 strips ``<script>`` tags from ``gr.HTML``, so inline plotly plots
never execute. Loading them through an ``<iframe>`` sidesteps that: the
iframe contains its own document where scripts run normally.
Reads every ``assets/plots/*.html`` that still looks like a bare fragment
(no ``<!DOCTYPE``) and replaces it with a full document that pulls plotly
from CDN and inherits a neutral surface.
"""
from __future__ import annotations
from pathlib import Path
import sys
PLOTLY_CDN = "https://cdn.plot.ly/plotly-2.35.2.min.js"
WRAPPER_HEAD = """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="{cdn}" charset="utf-8"></script>
<style>
html, body {{ margin: 0; padding: 0; background: transparent;
font-family: Inter, ui-sans-serif, system-ui, sans-serif;
color: #0f172a; }}
@media (prefers-color-scheme: dark) {{
html, body {{ color: #e2e8f0; }}
}}
.eegdash-figure {{ border: 0 !important; box-shadow: none !important;
background: transparent !important; padding: 0 !important; margin: 0 !important; }}
.eegdash-branding {{ display: none !important; }}
</style>
</head>
<body>
"""
WRAPPER_FOOT = "</body></html>\n"
def wrap(path: Path) -> bool:
raw = path.read_text(encoding="utf-8")
if raw.lstrip().startswith("<!DOCTYPE"):
return False # already wrapped
wrapped = WRAPPER_HEAD.format(cdn=PLOTLY_CDN) + raw + WRAPPER_FOOT
path.write_text(wrapped, encoding="utf-8")
return True
def main() -> int:
root = Path(__file__).resolve().parents[1] / "assets" / "plots"
if not root.exists():
print(f"missing {root}", file=sys.stderr)
return 1
for p in sorted(root.glob("*.html")):
changed = wrap(p)
print(f"{'wrapped' if changed else 'skipped'} {p.name}")
return 0
if __name__ == "__main__":
sys.exit(main())