#!/bin/bash # Simple Static Gallery Generator # Generates a single-page gallery from images in the images/ directory set -e IMAGES_DIR="images" OUTPUT_DIR="output" TEMPLATES_DIR="templates" ASSETS_DIR="assets" # Load .env if present; see .env.example for every option and its default. # Precedence: command line flags > environment > .env > built-in defaults. ENV_FILE="${ENV_FILE:-.env}" if [[ -f "$ENV_FILE" ]]; then # Remember caller-supplied values so the file cannot clobber them env_override=$(export -p | grep -E '^declare -x (STRIP_EXIF|GALLERY_TITLE|SHOW_FOOTER)=' || true) # shellcheck source=/dev/null source "$ENV_FILE" if [[ -n "$env_override" ]]; then eval "$env_override" fi unset env_override fi # Image metadata (EXIF/GPS/IPTC/XMP) is stripped by default. # Opt out with STRIP_EXIF=0 or --keep-exif. STRIP_EXIF="${STRIP_EXIF:-1}" # Page title, used for both and the <h1> header GALLERY_TITLE="${GALLERY_TITLE:-Gallery}" # Show the "Powered by shellery" footer; set to 0 to hide it SHOW_FOOTER="${SHOW_FOOTER:-1}" for arg in "$@"; do case "$arg" in --keep-exif) STRIP_EXIF=0 ;; --no-footer) SHOW_FOOTER=0 ;; --title=*) GALLERY_TITLE="${arg#--title=}" ;; -h|--help) echo "usage: ./build.sh [--keep-exif] [--no-footer] [--title=TEXT]" echo " --keep-exif do not strip image metadata (env: STRIP_EXIF=0)" echo " --no-footer hide the 'Powered by shellery' footer (env: SHOW_FOOTER=0)" echo " --title=TEXT page title and header, default 'Gallery' (env: GALLERY_TITLE)" echo "" echo "Options may also be set in .env (see .env.example)." echo "Precedence: flags > environment > .env > defaults." exit 0 ;; *) echo "unknown option: $arg" >&2; exit 1 ;; esac done # Fail before writing any output if the default cannot be honoured if [[ "$STRIP_EXIF" == "1" ]] && ! command -v exiftool >/dev/null 2>&1; then echo "error: exiftool is required to strip image metadata." >&2 echo " install: apt install libimage-exiftool-perl (or: brew install exiftool)" >&2 echo " bypass: STRIP_EXIF=0 ./build.sh or ./build.sh --keep-exif" >&2 exit 1 fi # Escape text destined for HTML body content html_escape() { local s=$1 # Replacements are quoted: bash 5.2+ expands an unquoted & to the matched text s="${s//&/"&"}" s="${s//</"<"}" s="${s//>/">"}" printf '%s' "$s" } TITLE_HTML=$(html_escape "$GALLERY_TITLE") # Create output directory mkdir -p "$OUTPUT_DIR" # Start building the HTML file OUTPUT_FILE="$OUTPUT_DIR/index.html" > "$OUTPUT_FILE" # Assemble templates in order for template in $(ls "$TEMPLATES_DIR"/*.tmpl | sort); do skip_block=0 # Process each template line by line to handle placeholders while IFS= read -r line; do # Optional block: <!-- IF_FOOTER --> ... <!-- ENDIF_FOOTER --> if [[ "$line" == *"<!-- IF_FOOTER -->"* ]]; then if [[ "$SHOW_FOOTER" != "1" ]]; then skip_block=1 fi continue fi if [[ "$line" == *"<!-- ENDIF_FOOTER -->"* ]]; then skip_block=0 continue fi if [[ "$skip_block" == "1" ]]; then continue fi # Replacement is quoted: bash 5.2+ expands an unquoted & to the matched text line="${line//<!-- TITLE -->/"$TITLE_HTML"}" if [[ "$line" == *"<!-- IMAGES -->"* ]]; then # Generate gallery items (reversed order) images=("$IMAGES_DIR"/*) for ((i=${#images[@]}-1; i>=0; i--)); do img="${images[$i]}" if [[ -f "$img" ]]; then img_name=$(basename "$img") echo " <div class=\"gallery-item\">" >> "$OUTPUT_FILE" echo " <a href=\"#$img_name\">" >> "$OUTPUT_FILE" echo " <img src=\"images/$img_name\" alt=\"$img_name\" loading=\"lazy\">" >> "$OUTPUT_FILE" echo " </a>" >> "$OUTPUT_FILE" echo " </div>" >> "$OUTPUT_FILE" fi done elif [[ "$line" == *"<!-- LIGHTBOXES -->"* ]]; then # Generate lightboxes outside the gallery grid (reversed order) images=("$IMAGES_DIR"/*) for ((i=${#images[@]}-1; i>=0; i--)); do img="${images[$i]}" if [[ -f "$img" ]]; then img_name=$(basename "$img") echo " <div id=\"$img_name\" class=\"lightbox\">" >> "$OUTPUT_FILE" echo " <a href=\"#\" class=\"lightbox-close\">×</a>" >> "$OUTPUT_FILE" echo " <img src=\"images/$img_name\" alt=\"$img_name\">" >> "$OUTPUT_FILE" echo " </div>" >> "$OUTPUT_FILE" fi done else echo "$line" >> "$OUTPUT_FILE" fi done < "$template" done # Copy assets cp -r "$ASSETS_DIR"/* "$OUTPUT_DIR/" # Copy images, then strip metadata from the copies (originals are never touched) cp -r "$IMAGES_DIR" "$OUTPUT_DIR/" if [[ "$STRIP_EXIF" == "1" ]]; then if compgen -G "$OUTPUT_DIR/$IMAGES_DIR/*" > /dev/null; then if ! exiftool -all= -overwrite_original -q -q "$OUTPUT_DIR/$IMAGES_DIR"; then echo "error: exiftool failed; output images may still contain metadata" >&2 exit 1 fi fi else echo "warning: EXIF stripping disabled, image metadata will be published as-is" >&2 fi echo "Gallery generated successfully in $OUTPUT_DIR/index.html"