#!/bin/bash # Regenerates everything the site reads from the analysis directory. # # The site used to hold hand-copied snapshots of books.json and friends, which drifted: # the catalogue grew to 163 books while the site still rendered 112. Nothing under # site/src/data or site/src/content/studies is authored by hand — it is all generated here, # and this runs as part of `npm run build`. set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd)" python3 "$ROOT/scripts/sync_studies.py" # Articles are written for a reader, not for the record, and carry their own front matter — # so they are copied verbatim rather than normalised the way the analyses are. ART_SRC="$ROOT/analysis/articles" ART_DST="$ROOT/site/src/content/articles" # Wipe the destination completely rather than by glob. This tree lives under Documents, # which is iCloud-synced, and conflict copies appear as "justify-that 2.md" — a file that # would publish the same article again at a second URL. Only what analysis/articles holds # may survive here. mkdir -p "$ART_DST"; find "$ART_DST" -type f -delete if [ -d "$ART_SRC" ]; then for f in "$ART_SRC"/*.md; do [ -e "$f" ] || continue rev=$(date -r "$f" +%Y-%m-%d) awk -v rev="$rev" 'NR==1&&/^---$/{print;print "revised: \"" rev "\"";next}1' "$f" > "$ART_DST/$(basename "$f")" done n_src=$(ls "$ART_SRC"/*.md 2>/dev/null | wc -l | tr -d ' ') n_dst=$(ls "$ART_DST"/*.md 2>/dev/null | wc -l | tr -d ' ') echo " articles: $n_dst" if [ "$n_src" != "$n_dst" ]; then echo " ! article count mismatch: $n_src source, $n_dst copied" >&2; exit 1 fi # A duplicated slug publishes the same piece twice; catch it here rather than in a sitemap. dupes=$(ls "$ART_DST" | sed -E 's/ [0-9]+\.md$/.md/' | sort | uniq -d) if [ -n "$dupes" ]; then echo " ! duplicate article slugs: $dupes" >&2; exit 1; fi fi for f in books comparisons findings summaries library hosting; do if [ -f "$ROOT/analysis/$f.json" ]; then cp "$ROOT/analysis/$f.json" "$ROOT/site/src/data/$f.json" n=$(python3 -c "import json,sys;d=json.load(open(sys.argv[1]));print(len(d) if isinstance(d,list) else len(d.get('books',d)))" "$ROOT/analysis/$f.json") echo " data/$f.json ($n records)" else echo " ! analysis/$f.json missing — site keeps its previous copy" fi done # Ship the pipeline itself. The method page describes these scripts; a reproducibility # claim with nothing attached is a claim, not an artefact. ART="$ROOT/site/public/artefacts" mkdir -p "$ART" for f in "$ROOT"/scripts/*.sh "$ROOT"/scripts/*.py; do [ -e "$f" ] || continue cp "$f" "$ART/$(basename "$f").txt" done cp "$ROOT/README.md" "$ART/README.md.txt" 2>/dev/null || true cp "$ROOT/URL-POLICY.md" "$ART/URL-POLICY.md.txt" 2>/dev/null || true cp "$ROOT/EDITORIAL-GUIDELINE.md" "$ART/EDITORIAL-GUIDELINE.md.txt" 2>/dev/null || true echo " artefacts: $(ls "$ART" | wc -l | tr -d ' ') files" echo "site data synced"