#!/usr/bin/env bash # download-leaflet.sh — Vendor Leaflet + leaflet.markercluster into static/leaflet/. # # The /photography/map/ page (build/Photography.hs photographyMapRules) # loads Leaflet from /leaflet/ to render a map of geo-tagged photos. # This vendoring keeps the page CDN-independent: the assets ship with # the site, no third-party request at view time. # # Run once before deploying. The vendored copy is gitignored # (~150 KB total); re-running is safe — files that already exist AND # match their pinned checksum are skipped; anything missing or # mismatched is re-fetched. # # To bump the pinned versions, set LEAFLET_VERSION / MARKERCLUSTER_VERSION, # re-run, then update tools/leaflet-checksums.sha256 with the new hashes. set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" LEAFLET_DIR="$REPO_ROOT/static/leaflet" CHECKSUMS="$REPO_ROOT/tools/leaflet-checksums.sha256" LEAFLET_VERSION="${LEAFLET_VERSION:-1.9.4}" MARKERCLUSTER_VERSION="${MARKERCLUSTER_VERSION:-1.5.3}" UNPKG_LEAFLET="https://unpkg.com/leaflet@${LEAFLET_VERSION}/dist" UNPKG_MC="https://unpkg.com/leaflet.markercluster@${MARKERCLUSTER_VERSION}/dist" # Files to vendor: (URL_BASE LOCAL_PATH SOURCE_FILENAME PIN_KEY) # PIN_KEY is the version-prefixed name in the checksum file so future # version bumps don't accidentally accept files matching an older hash. files_to_fetch=( "$UNPKG_LEAFLET|leaflet.js|leaflet-${LEAFLET_VERSION}-leaflet.js" "$UNPKG_LEAFLET|leaflet.css|leaflet-${LEAFLET_VERSION}-leaflet.css" "$UNPKG_LEAFLET/images|images/marker-icon.png|leaflet-${LEAFLET_VERSION}-marker-icon.png" "$UNPKG_LEAFLET/images|images/marker-icon-2x.png|leaflet-${LEAFLET_VERSION}-marker-icon-2x.png" "$UNPKG_LEAFLET/images|images/marker-shadow.png|leaflet-${LEAFLET_VERSION}-marker-shadow.png" "$UNPKG_MC|leaflet.markercluster.js|leaflet.markercluster-${MARKERCLUSTER_VERSION}-leaflet.markercluster.js" "$UNPKG_MC|MarkerCluster.css|leaflet.markercluster-${MARKERCLUSTER_VERSION}-MarkerCluster.css" "$UNPKG_MC|MarkerCluster.Default.css|leaflet.markercluster-${MARKERCLUSTER_VERSION}-MarkerCluster.Default.css" ) mkdir -p "$LEAFLET_DIR/images" verify_or_warn() { local file="$1" local pin_key="$2" if [ ! -f "$CHECKSUMS" ]; then echo "leaflet: $CHECKSUMS not found — skipping sha256 verification" >&2 return 0 fi local want want="$(awk -v p="$pin_key" '$2 == p { print $1; exit }' "$CHECKSUMS")" if [ -z "$want" ]; then echo "leaflet: no pinned checksum for $pin_key — skipping verification" >&2 return 0 fi local got got="$(sha256sum "$file" | awk '{ print $1 }')" if [ "$got" != "$want" ]; then echo "leaflet: sha256 mismatch for $pin_key" >&2 echo " expected $want" >&2 echo " got $got" >&2 return 1 fi } # Per-file skip: existing files are skipped only after re-verifying # their checksum, so a partial or tampered file from an interrupted # earlier run can never be silently accepted. Downloads land in a # .part temp and are only moved into place after verification — a # failed verification leaves nothing at the final path. for entry in "${files_to_fetch[@]}"; do IFS='|' read -r url_base local_path pin_key <<<"$entry" src_name="${local_path##*/}" target="$LEAFLET_DIR/$local_path" mkdir -p "$(dirname "$target")" if [ -f "$target" ]; then if verify_or_warn "$target" "$pin_key"; then echo "leaflet: $local_path present and verified (skipping)" continue fi echo "leaflet: $local_path failed verification — re-fetching" >&2 rm -f "$target" fi echo "leaflet: fetching $local_path ($pin_key)" tmp="$target.part" curl -fsSL --progress-bar "$url_base/$src_name" -o "$tmp" if ! verify_or_warn "$tmp" "$pin_key"; then rm -f "$tmp" echo "leaflet: refusing to vendor unverified $local_path" >&2 exit 1 fi mv "$tmp" "$target" done echo "leaflet: vendored to $LEAFLET_DIR"