#!/usr/bin/env bash # Bake the theme and its parts into the pages that use them. # # Usage: # ./ctrl/theme.sh # bake — rewrite every generated block # ./ctrl/theme.sh check # fail if any page is stale; changes nothing # ./ctrl/theme.sh new [title] # a scaffold page to start from # ./ctrl/theme.sh run FILE [--list|--check] [--only NAME] # # every page a run file lists, each with a contract # ./ctrl/theme.sh parts # what can be added, and the markup that adds it # ./ctrl/theme.sh export [name...] # the contract for a subset, as one doc # # `export` is for handing a vetted LLM what it needs to write an ad-hoc page — # the chosen parts, their markup, and the tokens resolved to literal values, so # the document stands alone. Naming parts is the point: hand over everything and # you get back a page built from Vue components that cannot run standalone. # # ./ctrl/theme.sh export panel split > /tmp/contract.md # # Call the script directly when piping; `make` echoes its recipe to stdout. # For whole-repo context this is the wrong tool — station/tools/distill already # flattens a tree to one budgeted document. # # A page that says `background: var(--bg)` and never gets `--bg` is UNSTYLED, # not merely unbranded — the declaration is invalid at computed-value time. That # is why every page carries a baked default, and why `check` is worth running. # # This exists because bake.py was reachable by no command at all: not from the # Makefile, not from ctrl/, not from build.py. A drift check nobody runs is a # drift check that reports nothing, and the evidence was already on disk — # histgen's page linked /theme.css for months, was missing from the old # hardcoded page list, and so was never baked once. set -e # Where the caller stood. A run file is named relative to there, and the cd below # would otherwise make `run ./theme.toml` mean a different file. CALLER_DIR="$PWD" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(dirname "$SCRIPT_DIR")" cd "$ROOT_DIR/soleprint" PYTHON="${PYTHON:-python3}" case "${1:-bake}" in bake) exec "$PYTHON" common/theme/bake.py ;; check) exec "$PYTHON" common/theme/bake.py --check ;; parts) exec "$PYTHON" common/theme/bake.py --parts ;; run) # A run file: every page a project has, its context, and a contract per # page for the LLM. See soleprint/common/theme/theme.example.toml. shift args=() file="" prev="" for a in "$@"; do if [[ -z "$file" && "$a" != -* && "$prev" != "--only" ]]; then file="$(cd "$CALLER_DIR" && realpath -m -- "$a")" args+=("$file") else args+=("$a") fi prev="$a" done exec "$PYTHON" common/theme/bake.py --run "${args[@]}" ;; new) shift exec "$PYTHON" common/theme/bake.py --new "$@" ;; export) shift exec "$PYTHON" common/theme/bake.py --export "$@" ;; *) echo "Unknown: $1" >&2 echo "Usage: ./ctrl/theme.sh [new [title]|parts|bake|check|export [name...]|run FILE]" >&2 exit 1 ;; esac