from __future__ import annotations import inspect import os import re import socket from pathlib import Path import gradio as gr ROOT = Path(__file__).resolve().parent DIST_DIR = ROOT / "dist" ASSETS_DIR = DIST_DIR / "assets" PATCHED_DIR = ROOT / ".gradio_static" PORT = int(os.environ.get("GRADIO_PORT", "7899")) def get_free_port() -> int: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: sock.bind(("127.0.0.1", 0)) return int(sock.getsockname()[1]) def file_url(path: Path) -> str: return f"/gradio_api/file={path.resolve()}" def patched_js_url(index_html: str) -> str: match = re.search(r'src="/assets/([^"]+\.js)"', index_html) if not match: raise RuntimeError("Could not find built JS bundle in dist/index.html") source_path = ASSETS_DIR / match.group(1) source = source_path.read_text() # The worker is referenced by an ABSOLUTE "/assets/worker-*.js" URL, which # cannot resolve inside the Gradio iframe — rewrite it to a file= URL. worker_match = re.search(r'worker-[^"]+\.js', source) if worker_match: worker_path = ASSETS_DIR / worker_match.group(0) source = source.replace(f'"/assets/{worker_path.name}"', f'"{file_url(worker_path)}"') source = source.replace('"logo.png"', f'"{file_url(DIST_DIR / "logo.png")}"') source = source.replace('"banner.png"', f'"{file_url(DIST_DIR / "banner.png")}"') source = source.replace('"yeSound.mp3"', f'"{file_url(DIST_DIR / "yeSound.mp3")}"') for _img in ("Image1.jpg", "Image2.jpg", "Image3.jpg"): source = source.replace(f'"{_img}"', f'"{file_url(DIST_DIR / _img)}"') # CRITICAL: lazily-imported chunks (e.g. the transformers.js bundle used by # =VISION()) are referenced RELATIVELY, like import("./transformers.web-*.js"), # resolved against this file's URL. So the patched bundle MUST live next to # those chunks (dist/assets/) — not in .gradio_static/ — or they 404 in the # iframe and on-device WebGPU inference silently fails. patched_path = ASSETS_DIR / (source_path.stem + ".patched.js") patched_path.write_text(source) return file_url(patched_path) def patched_index_url() -> str: index_path = DIST_DIR / "index.html" if not index_path.exists(): raise RuntimeError("Missing dist/index.html. Run `npm run build` first.") PATCHED_DIR.mkdir(exist_ok=True) index_html = index_path.read_text() # Never cache the entry document, so a rebuild is always picked up (the # hashed JS bundle name changes each build; a cached index.html would point # at a stale one). index_html = index_html.replace( "
", '\n ', 1, ) index_html = re.sub( r'', f'', index_html, ) index_html = re.sub( r'href="/assets/([^"]+)"', lambda m: f'href="{file_url(ASSETS_DIR / m.group(1))}"', index_html, ) index_html = index_html.replace('href="/logo.png"', f'href="{file_url(DIST_DIR / "logo.png")}"') index_html = index_html.replace('src="logo.png"', f'src="{file_url(DIST_DIR / "logo.png")}"') index_html = index_html.replace('src="banner.png"', f'src="{file_url(DIST_DIR / "banner.png")}"') patched_index = PATCHED_DIR / "index.html" patched_index.write_text(index_html) return file_url(patched_index) def build_ui() -> gr.Blocks: css = """ html, body, #root, gradio-app, .gradio-container { width: 100vw !important; max-width: 100vw !important; height: 100%; margin: 0 !important; padding: 0 !important; overflow: hidden !important; background: #fff1a8 !important; } .gradio-container { max-width: none !important; } main.app, .main, .contain, .wrap, .block, .html-container, .html-container.padding, .prose, #component-0, #component-0 > div, .form { width: 100vw !important; max-width: 100vw !important; flex-basis: 100vw !important; align-self: stretch !important; height: 100% !important; min-height: 100% !important; margin: 0 !important; padding: 0 !important; overflow: hidden !important; transform: none !important; } .spreadsheet-host { position: relative; width: 100vw !important; max-width: 100vw !important; height: 100vh; height: 100dvh; margin: 0; padding: 0; overflow: hidden; background: white; } .spreadsheet-frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; background: white; } .yellow-tint { position: absolute; inset: 0; pointer-events: none; z-index: 9999; background: rgba(255, 232, 83, 0.34); mix-blend-mode: multiply; } footer { display: none !important; } """ # Keep the iframe in normal layout flow. Hugging Face/Gradio measure the # document to size the outer Space iframe; hoisting a fixed-position child to # gives that measurer no stable height and can make the whole UI drift. head = """ """ # NOTE: Gradio 6 applies css/head at launch(); older Gradio applies them on # Blocks(). We support both so local verification does not depend on one # specific Gradio version. blocks_kwargs = {"title": "The Backrooms Spreadsheet", "fill_height": True} if "css" in inspect.signature(gr.Blocks).parameters: blocks_kwargs.update({"css": css, "head": head}) with gr.Blocks(**blocks_kwargs) as demo: gr.HTML( f"""