Clean, dependency-light front page. Only three things ship here: - index.html — two-button landing: Mobile -> mobile.html, Desktop -> pm_e-2.html - mobile.html — touch-first PWA (+ mobile-sessions.html practice journal) - pm_e-2.html — engraved-notation editor build.sh/deploy.sh trimmed to just these; deploy mirrors dist/ to the web root with rsync --delete. README/CLAUDE.md rewritten for the slim scope. The full project (PM_E-1 editor, embeddable widget, all hardware form-factor pages, Pico firmware editions, the Rust port, and the KiCad/SPICE hardware design) is preserved on the `concepts` branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
49 lines
2.7 KiB
Bash
Executable file
49 lines
2.7 KiB
Bash
Executable file
#!/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/<file>@*/ 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
|