oxedyne/daimond/www/assets/typst/refresh.sh
4.5 KiB, 1 run
created by r2519314175:1071, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download · who wrote it · its history
| 1 | #!/usr/bin/env bash |
| 2 | # refresh.sh -- rebuild the vendored Typst packages under `packs/` from a local |
| 3 | # typst package cache. |
| 4 | # |
| 5 | # It is shipped BESIDE what it produces, and served with it, deliberately: the |
| 6 | # packs are sealed into `www/manifest.json` and the transparency chain, so the |
| 7 | # recipe that made them belongs inside the same seal. A reader with the same |
| 8 | # package cache runs this and gets the same bytes. |
| 9 | # |
| 10 | # bash www/assets/typst/refresh.sh # from ~/.cache/typst/packages |
| 11 | # TYPST_CACHE=/some/where bash .../refresh.sh # from another cache |
| 12 | # |
| 13 | # NOTHING IS DOWNLOADED. The cache is read; if a package named below is not in |
| 14 | # it, this script says so and stops rather than writing a set that is missing one. |
| 15 | # |
| 16 | # After running it, `www/assets/typst/packs/INDEX` has changed, and that file is |
| 17 | # `include_str!`d by `src/wasm/typst.rs` -- so the wasm must be rebuilt and the |
| 18 | # bundle resealed, or the wasm and the served packs describe different sets. |
| 19 | |
| 20 | set -euo pipefail |
| 21 | |
| 22 | HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 23 | CACHE="${TYPST_CACHE:-$HOME/.cache/typst/packages}" |
| 24 | OUT="$HERE/packs" |
| 25 | |
| 26 | # ── The set, and why each member is in it ─────────────────────────────────── |
| 27 | # |
| 28 | # Namespace, name, version. Order is the order the INDEX lists them in, and the |
| 29 | # INDEX is what a refusal reads out, so it is the order a person sees. |
| 30 | # |
| 31 | # cetz 0.3.4 the author's own book imports it; the whole reason for this |
| 32 | # oxifmt 0.2.1 cetz 0.3.4 imports it, and cetz 0.3.2 does too |
| 33 | # cetz 0.3.2 cetz-plot 0.1.1 imports THIS version, not 0.3.4 |
| 34 | # cetz-plot 0.1.1 charts and plots on top of cetz |
| 35 | # fletcher 0.5.7 arrow diagrams; imports cetz 0.3.4 |
| 36 | # |
| 37 | # cetz appears twice on purpose. A closure is not a wish list: cetz-plot names |
| 38 | # `@preview/cetz:0.3.2` in `src/cetz.typ`, so shipping cetz-plot without 0.3.2 |
| 39 | # would ship a package that resolves and then fails on its own dependency -- |
| 40 | # which is the one failure this whole mechanism is written to make impossible to |
| 41 | # mistake for something else. |
| 42 | SET=( |
| 43 | "preview cetz 0.3.4" |
| 44 | "preview oxifmt 0.2.1" |
| 45 | "preview cetz 0.3.2" |
| 46 | "preview cetz-plot 0.1.1" |
| 47 | "preview fletcher 0.5.7" |
| 48 | ) |
| 49 | |
| 50 | # ── What is taken from each package ───────────────────────────────────────── |
| 51 | # |
| 52 | # The sources, the manifest that names the entrypoint, and the licence. Not the |
| 53 | # README, not the gallery, not a built PDF: they are never read by a compile and |
| 54 | # they are the bulk of what a package directory weighs. The licence IS taken -- |
| 55 | # these are other people's LGPL and MIT work and it ships inside our bundle. |
| 56 | want() { |
| 57 | local root="$1" |
| 58 | ( cd "$root" && find . -type f \ |
| 59 | \( -name '*.typ' -o -name 'typst.toml' -o -name 'LICENSE' -o -name 'LICENSE.*' \) \ |
| 60 | -printf '%P\n' | LC_ALL=C sort ) |
| 61 | } |
| 62 | |
| 63 | rm -rf "$OUT" |
| 64 | mkdir -p "$OUT" |
| 65 | INDEX="$OUT/INDEX" |
| 66 | |
| 67 | { |
| 68 | echo "# Typst packages vendored into Daimond. Generated by www/assets/typst/refresh.sh." |
| 69 | echo "# One line per pack: namespace name version file-count pack-bytes." |
| 70 | echo "# The packs are at packs/<namespace>/<name>/<version>.pack." |
| 71 | } > "$INDEX" |
| 72 | |
| 73 | for entry in "${SET[@]}"; do |
| 74 | read -r ns name ver <<< "$entry" |
| 75 | src="$CACHE/$ns/$name/$ver" |
| 76 | if [ ! -d "$src" ]; then |
| 77 | echo "refresh.sh: $ns/$name:$ver is not in $CACHE -- nothing written." >&2 |
| 78 | exit 1 |
| 79 | fi |
| 80 | entrypoint="$(sed -n 's/^[[:space:]]*entrypoint[[:space:]]*=[[:space:]]*"\(.*\)".*/\1/p' "$src/typst.toml" | head -1)" |
| 81 | if [ -z "$entrypoint" ]; then |
| 82 | echo "refresh.sh: $ns/$name:$ver has no entrypoint in its typst.toml." >&2 |
| 83 | exit 1 |
| 84 | fi |
| 85 | |
| 86 | mapfile -t files < <(want "$src") |
| 87 | if [ "${#files[@]}" -eq 0 ]; then |
| 88 | echo "refresh.sh: $ns/$name:$ver holds no sources." >&2 |
| 89 | exit 1 |
| 90 | fi |
| 91 | |
| 92 | dest="$OUT/$ns/$name" |
| 93 | mkdir -p "$dest" |
| 94 | pack="$dest/$ver.pack" |
| 95 | |
| 96 | # The header: ASCII lines, then ONE blank line, then the file bodies |
| 97 | # concatenated in the order listed. Lengths rather than delimiters, so a |
| 98 | # source containing anything at all cannot end a file early. |
| 99 | { |
| 100 | echo "DAIMOND TYPST PACK 1" |
| 101 | echo "namespace $ns" |
| 102 | echo "name $name" |
| 103 | echo "version $ver" |
| 104 | echo "entrypoint $entrypoint" |
| 105 | for f in "${files[@]}"; do |
| 106 | echo "file $(stat -c%s "$src/$f") $f" |
| 107 | done |
| 108 | echo |
| 109 | } > "$pack" |
| 110 | for f in "${files[@]}"; do |
| 111 | cat "$src/$f" >> "$pack" |
| 112 | done |
| 113 | |
| 114 | echo "pack $ns $name $ver ${#files[@]} $(stat -c%s "$pack")" >> "$INDEX" |
| 115 | echo "packed $ns/$name:$ver -- ${#files[@]} files, $(stat -c%s "$pack") bytes" |
| 116 | done |
| 117 | |
| 118 | echo |
| 119 | echo "INDEX:" |
| 120 | cat "$INDEX" |
| 121 | echo |
| 122 | echo "src/wasm/typst.rs include_str!s that INDEX -- rebuild the wasm and reseal." |