#!/usr/bin/env bash # Assemble the deployed single-file pages from source + shared partials + assets/. # # Each page is a source that shares code via markers: # /*@BUILD:include:src/@*/ inlines a shared partial (engine, seed lists, base CSS, header/footer/chrome) # @BUILD:favicon@ / @BUILD:logo-*@ / @BUILD:bravura@ inline base64 assets # This resolves them so each built page in dist/ is one self-contained file # (zero deps, works fully offline). deploy.sh runs this first. dist/ is generated — # don't edit or commit it. # # NOTE: this is the slim `main` branch — only the landing chooser, the mobile app # (+ its practice journal) and the pm_e-2 notation editor ship. The full # multi-form-factor project (all device pages, firmware, Rust, hardware) lives on # the `concepts` branch. set -euo pipefail cd "$(dirname "${BASH_SOURCE[0]}")" rm -rf dist && mkdir -p dist # start clean so no stale artifact survives into deploy's rsync --delete python3 - <<'PY' import pathlib, re A = pathlib.Path("assets") def build(name): src = pathlib.Path(name).read_text() # 1) inline shared partials (function-replacement: no backslash/group interpretation) src = re.sub(r"/\*@BUILD:include:([^@]+)@\*/", lambda m: pathlib.Path(m.group(1)).read_text().rstrip("\n"), src) # 2) inline base64 assets (all voices are synthesized — no audio samples) src = src.replace("@BUILD:favicon@", (A / "favicon.b64").read_text().strip()) src = src.replace("@BUILD:logo-dark@", (A / "logo-dark.b64").read_text().strip()) src = src.replace("@BUILD:logo-light@", (A / "logo-light.b64").read_text().strip()) src = src.replace("@BUILD:logo-side-dark@", (A / "logo-side-dark.b64").read_text().strip()) src = src.replace("@BUILD:logo-side-light@", (A / "logo-side-light.b64").read_text().strip()) src = src.replace("@BUILD:bravura@", (A / "bravura.woff2.b64").read_text().strip()) # SMuFL music font subset (PM_E-2 notation) assert "@BUILD:" not in src, f"unresolved build marker(s) remain in {name}" out = pathlib.Path("dist") / name out.write_text(src) return out.stat().st_size for name in ("index.html", "mobile.html", "mobile-sessions.html", "pm_e-2.html"): print("built %s (%dKB)" % (name, build(name) // 1024)) # PWA support files for mobile.html (the phone/tablet app): manifest, service worker, icons. for f in ("manifest.webmanifest", "mobile-sw.js"): pathlib.Path("dist/" + f).write_text(pathlib.Path(f).read_text()) for f in ("icon-192.png", "icon-512.png", "icon-180.png"): pathlib.Path("dist/" + f).write_bytes((A / f).read_bytes()) print("copied PWA files (manifest.webmanifest, mobile-sw.js, icon-{192,512,180}.png)") PY