metronome/build.sh
Me Here 4babd1f4ef Phase A — engine v2: drop samples, add conventions + per-lane dB gain
- Remove the VCSL sample kit entirely (editor 351K → 141K). All voices are
  synthesized; the friendly GM names now alias to the punchier 808/909 renders
  (KIT_ALIAS). build.sh drops the @BUILD:samples inlining; assets/samples.json gone.
- Conventions (backward-compatible): GM note-number aliases (36=kick…), '-'/'_'
  rest aliases in step patterns, Euclidean (k,n[,rot]) shorthand.
- Per-lane gain in dB (@<db> in the grammar) applied as a velocity multiplier at
  schedule time — no stutter; threaded through every host's buildMeters + the
  editor's lanes (knob UI comes in Phase B).
- 15/15 engine round-trip tests pass; pages console-clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 10:33:56 -05:00

37 lines
1.9 KiB
Bash
Executable file

#!/usr/bin/env bash
# Assemble the deployed single-file pages from source + shared partials + assets/.
#
# Every page (the Concepts landing, the editor app, and the device/form-factor
# pages) 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-*@ inline base64 assets (voices are all synthesized — no samples)
# 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.
set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")"
mkdir -p dist
python3 - <<'PY'
import os, 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 (voices are all synthesized now — no 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())
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","editor.html","player.html","teacher.html","stage.html","micro.html","showcase.html",
"embed.html"):
print("built %s (%dKB)" % (name, build(name) // 1024))
pathlib.Path("dist/embed.js").write_text(pathlib.Path("embed.js").read_text()) # loader, served as-is
print("copied embed.js")
PY