#!/usr/bin/env python3 """Embeds web/ (the browser UI) into src/webui_assets.hpp. Run this after editing anything in web/: python3 tools/embed_web.py Each file becomes a few C++ raw string literals of at most ~12 KB, because MSVC rejects longer string literals. The generated header is checked in, so building antlrlab does not need Python. """ import glob import os import sys ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) WEB = os.path.join(ROOT, "web") OUT = os.path.join(ROOT, "src", "webui_assets.hpp") DELIM = "__WEB__" CHUNK = 12000 def read(path): with open(path, encoding="utf-8") as f: text = f.read() try: text.encode("ascii") except UnicodeEncodeError as e: sys.exit("%s contains non-ASCII text (%s). Use \\u escapes or entities." % (path, e)) if ")" + DELIM + '"' in text: sys.exit("%s contains the raw string terminator" % path) return text def chunks(text): out, cur = [], "" for line in text.splitlines(keepends=True): if len(cur) + len(line) > CHUNK and cur: out.append(cur) cur = "" cur += line if cur: out.append(cur) return out def function(name, text): body = "".join(' s += R"%s(%s)%s";\n' % (DELIM, c, DELIM) for c in chunks(text)) return "inline std::string %s() {\n std::string s;\n%s return s;\n}\n" % (name, body) def main(): js = "".join(read(p) for p in sorted(glob.glob(os.path.join(WEB, "[0-9]*.js")))) parts = [ "// GENERATED by tools/embed_web.py from web/ - do not edit by hand.\n", "#pragma once\n\n#include \n\nnamespace lab {\n\n", function("webIndexHtml", read(os.path.join(WEB, "index.html"))), "\n", function("webCss", read(os.path.join(WEB, "app.css"))), "\n", function("webJs", js), "\n} // namespace lab\n", ] with open(OUT, "w", encoding="utf-8", newline="\n") as f: f.write("".join(parts)) print("wrote %s (%d bytes of JS, %d files)" % (OUT, len(js), len(glob.glob(os.path.join(WEB, "[0-9]*.js"))))) main()