Files
aetherbound-guild/tools/build_gallery_bundle.py
T

63 lines
2.2 KiB
Python

#!/usr/bin/env python3
"""Build a self-contained HTML artifact for sandboxed Gallery viewers."""
from __future__ import annotations
import base64
import json
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SITE = ROOT / "prototype" / "site"
DEFAULT_OUTPUT = ROOT / "prototype" / "gallery" / "aetherbound-guild-prototype.html"
def data_uri(path: Path) -> str:
mime = "image/webp" if path.suffix == ".webp" else "application/octet-stream"
encoded = base64.b64encode(path.read_bytes()).decode("ascii")
return f"data:{mime};base64,{encoded}"
def main() -> None:
index = (SITE / "index.html").read_text(encoding="utf-8")
styles = (SITE / "styles.css").read_text(encoding="utf-8")
app = (SITE / "app.js").read_text(encoding="utf-8")
catalog = json.loads((SITE / "data" / "catalog.json").read_text(encoding="utf-8"))
asset_paths = sorted((SITE / "assets" / "web").glob("*.webp"))
asset_paths.append(SITE / "favicon.webp")
for path in asset_paths:
relative = path.relative_to(SITE).as_posix()
uri = data_uri(path)
index = index.replace(relative, uri)
app = app.replace(relative, uri)
catalog_json = json.dumps(catalog, ensure_ascii=False, separators=(",", ":"))
catalog_json = catalog_json.replace("<", "\\u003c")
app = app.replace("</script", "<\\/script")
styles = styles.replace("</style", "<\\/style")
index = index.replace(
'<link rel="stylesheet" href="styles.css" />',
f"<style>\n{styles}\n</style>",
)
index = index.replace(
'<script src="app.js" defer></script>',
f'<script id="prototype-data" type="application/json">{catalog_json}</script>\n'
f"<script>\n{app}\n</script>",
)
if 'href="styles.css"' in index or 'src="app.js"' in index:
raise RuntimeError("external stylesheet or script remains in bundle")
if "assets/web/" in index:
raise RuntimeError("external prototype asset remains in bundle")
DEFAULT_OUTPUT.parent.mkdir(parents=True, exist_ok=True)
DEFAULT_OUTPUT.write_text(index, encoding="utf-8")
print(f"ABG_GALLERY_BUNDLE_OK bytes={DEFAULT_OUTPUT.stat().st_size} output={DEFAULT_OUTPUT}")
if __name__ == "__main__":
main()