diff options
| author | Paul Buetow <paul@buetow.org> | 2026-06-05 00:25:18 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-06-05 00:25:18 +0300 |
| commit | 3cf33952612d27f48258d4084f5d651d01931613 (patch) | |
| tree | e5fa62339e34db2a8084834eec9bbdac77c82699 | |
| parent | bba997dffebb35792165c5aebb4b1a1893f21422 (diff) | |
Add splash page support for task 8j0
| -rw-r--r-- | README.md | 29 | ||||
| -rwxr-xr-x | bin/photoalbum | 83 | ||||
| -rw-r--r-- | share/templates/default/splash.tmpl | 78 | ||||
| -rw-r--r-- | src/photoalbum.default.conf | 2 | ||||
| -rwxr-xr-x | src/photoalbum.sh | 83 | ||||
| -rwxr-xr-x | tests/cli.sh | 118 | ||||
| -rwxr-xr-x | tests/helpers.sh | 1 |
7 files changed, 374 insertions, 20 deletions
@@ -68,7 +68,7 @@ missing, run `photoalbum --init` first. The config file is a Bash file with assignments such as `INCOMING_DIR`, `DIST_DIR`, `TEMPLATE_DIR`, `TITLE`, `HEIGHT`, `THUMBHEIGHT`, `MAXPREVIEWS`, -`RANDOM_SEED`, `SHUFFLE`, and `TARBALL_INCLUDE`. +`RANDOM_SEED`, `SHUFFLE`, `SPLASH_PAGE`, and `TARBALL_INCLUDE`. Before generating, `photoalbum` validates the loaded config and command-line overrides. It checks required values, positive integer settings, `yes`/`no` @@ -87,11 +87,12 @@ tarball filename uses `<timestamp>` as a placeholder so the output is stable. `--print-config` writes stable shell-style assignments to stdout in this order: `CONFIG_SOURCE`, `INCOMING_DIR`, `DIST_DIR`, `TEMPLATE_DIR`, `TITLE`, `HEIGHT`, -`THUMBHEIGHT`, `MAXPREVIEWS`, `RANDOM_SEED`, `SHUFFLE`, `TARBALL_INCLUDE`, -`TARBALL_SUFFIX`, `TAR_OPTS`, and `ORIGINAL_BASEPATH`. Scalar values use Bash -`%q` quoting and `TAR_OPTS` is normalized to a Bash array assignment, so the -output can be parsed by shell tooling. `--quiet` does not suppress this output, -and `--verbose` does not add human-readable diagnostics to it. +`THUMBHEIGHT`, `MAXPREVIEWS`, `RANDOM_SEED`, `SHUFFLE`, `SPLASH_PAGE`, +`TARBALL_INCLUDE`, `TARBALL_SUFFIX`, `TAR_OPTS`, and `ORIGINAL_BASEPATH`. +Scalar values use Bash `%q` quoting and `TAR_OPTS` is normalized to a Bash array +assignment, so the output can be parsed by shell tooling. `--quiet` does not +suppress this output, and `--verbose` does not add human-readable diagnostics to +it. Successful generation writes `photoalbum.json` into the output directory. This metadata records the generator version and timestamp, config source, template @@ -112,14 +113,20 @@ The following long options override config values: | `--random-seed VALUE` | `RANDOM_SEED` | | `--shuffle` | `SHUFFLE=yes` | | `--no-shuffle` | `SHUFFLE=no` | +| `--splash` | `SPLASH_PAGE=yes` | +| `--no-splash` | `SPLASH_PAGE=no` | | `--tarball` | `TARBALL_INCLUDE=yes` | | `--no-tarball` | `TARBALL_INCLUDE=no` | -By default, background photos, animation classes, generated timestamps, and -`--shuffle` preview order remain non-deterministic. Set `RANDOM_SEED` in the -config, or pass `--random-seed VALUE`, to make those choices repeatable for -stable tests or reproducible album builds. Use the same seed and inputs to -produce the same HTML. +By default, the generated root `index.html` is a no-JavaScript splash page using +a randomly selected album photo. Set `SPLASH_PAGE=no` or pass `--no-splash` to +restore the top-level redirect to `page-1.html`. + +By default, splash and background photos, animation classes, generated +timestamps, and `--shuffle` preview order remain non-deterministic. Set +`RANDOM_SEED` in the config, or pass `--random-seed VALUE`, to make those +choices repeatable for stable tests or reproducible album builds. Use the same +seed and inputs to produce the same HTML. `--dry-run` and `--print-config` accept the same override options as `--generate`. `--clean` accepts the same override options, but only `--dist` diff --git a/bin/photoalbum b/bin/photoalbum index 3036718..e64f433 100755 --- a/bin/photoalbum +++ b/bin/photoalbum @@ -31,6 +31,8 @@ usage() { --thumbheight VALUE --maxpreviews N --random-seed VALUE + --splash + --no-splash --shuffle --no-shuffle --tarball @@ -425,6 +427,16 @@ validate_template_context() { redirect) required_vars+=(redirect_page) ;; + splash) + required_vars+=( + backhref + background_image + blurs_dir + enter_page + photo + photos_dir + ) + ;; details) required_vars+=( animation_class @@ -464,6 +476,7 @@ source_template_file() { render_background_image_css="$render_background_image_css" \ render_blurs_dir_css="$render_blurs_dir_css" \ render_current_date_text="$render_current_date_text" \ + render_enter_page_html="$render_enter_page_html" \ render_exif_details_html="$render_exif_details_html" \ render_height_html="$render_height_html" \ render_html_dir_html="$render_html_dir_html" \ @@ -535,6 +548,9 @@ prepare_template_render_vars() { _css_string_escape "$(template_context_value "$context_name" blurs_dir)" ) render_current_date_text=$(_html_escape "$(current_date_text)") + render_enter_page_html=$( + _html_escape "$(template_context_value "$context_name" enter_page)" + ) render_exif_details_html=$( template_context_value "$context_name" exif_details ) @@ -602,6 +618,7 @@ template() { local render_background_image_css local render_blurs_dir_css local render_current_date_text + local render_enter_page_html local render_exif_details_html local render_height_html local render_html_dir @@ -1153,6 +1170,38 @@ render_album_index_redirect() { redirect_page 'page-1' } +render_album_splash_page() { + local -r photos_dir="$1"; shift + local -r html_dir="$1"; shift + local -r blurs_dir="$1"; shift + local -r backhref="$1"; shift + local photo + + photo=$(randomphoto "$photos_dir" splash) + template 'splash' 'index.html' \ + html_dir "$html_dir" \ + backhref "$backhref" \ + blurs_dir "$blurs_dir" \ + background_image "$photo" \ + photos_dir "$photos_dir" \ + photo "$photo" \ + enter_page 'page-1' +} + +render_album_index() { + local -r photos_dir="$1"; shift + local -r html_dir="$1"; shift + local -r blurs_dir="$1"; shift + local -r backhref="$1"; shift + + if [ "${SPLASH_PAGE:-yes}" = yes ]; then + render_album_splash_page "$photos_dir" "$html_dir" "$blurs_dir" \ + "$backhref" + else + render_album_index_redirect "$html_dir" + fi +} + render_album_pages() { local -r photos_dir="$1"; shift local -r html_dir="$1"; shift @@ -1214,7 +1263,7 @@ render_album_pages() { finish_preview_page "$name" "$html_dir" "$backhref" "$tarball_name" render_view_redirects "$html_dir" - render_album_index_redirect "$html_dir" + render_album_index "$photos_dir" "$html_dir" "$blurs_dir" "$backhref" } randomphoto() { @@ -1331,6 +1380,7 @@ write_generation_metadata() { printf ' "maxpreviews": %s,\n' "$(_json_string "${MAXPREVIEWS:-}")" printf ' "random_seed": %s,\n' "$(_json_string "${RANDOM_SEED:-}")" printf ' "shuffle": %s,\n' "$(_json_bool "${SHUFFLE:-no}")" + printf ' "splash_page": %s,\n' "$(_json_bool "${SPLASH_PAGE:-yes}")" printf ' "original_basepath": %s\n' \ "$(_json_string "${ORIGINAL_BASEPATH:-}")" printf ' }\n' @@ -1405,6 +1455,7 @@ dry_run() { printf 'Max previews per page: %s\n' "$MAXPREVIEWS" printf 'Random seed: %s\n' "${RANDOM_SEED:-}" printf 'Shuffle: %s\n' "${SHUFFLE:-no}" + printf 'Splash page: %s\n' "${SPLASH_PAGE:-yes}" printf 'Image count: %s\n' "$image_count" printf 'Tarball setting: %s\n' "${TARBALL_INCLUDE:-no}" if [ "${TARBALL_INCLUDE:-no}" = yes ]; then @@ -1420,8 +1471,13 @@ dry_run() { printf ' %s/blurs\n' "$DIST_DIR" printf 'Planned generated files:\n' - printf ' %s/index.html (%s album index redirect)\n' \ - "$DIST_DIR" "$html_index_count" + if [ "${SPLASH_PAGE:-yes}" = yes ]; then + printf ' %s/index.html (%s splash page)\n' \ + "$DIST_DIR" "$html_index_count" + else + printf ' %s/index.html (%s album index redirect)\n' \ + "$DIST_DIR" "$html_index_count" + fi printf ' %s/photoalbum.json\n' "$DIST_DIR" printf ' %s/photos/* (%s image files)\n' "$DIST_DIR" "$image_count" printf ' %s/thumbs/* (%s image files)\n' "$DIST_DIR" "$image_count" @@ -1471,6 +1527,7 @@ print_config() { print_shell_assignment MAXPREVIEWS "$MAXPREVIEWS" print_shell_assignment RANDOM_SEED "${RANDOM_SEED:-}" print_shell_assignment SHUFFLE "${SHUFFLE:-no}" + print_shell_assignment SPLASH_PAGE "${SPLASH_PAGE:-yes}" print_shell_assignment TARBALL_INCLUDE "${TARBALL_INCLUDE:-no}" print_shell_assignment TARBALL_SUFFIX "${TARBALL_SUFFIX:-.tar}" print_shell_array_assignment TAR_OPTS "${tar_opts[@]}" @@ -1666,6 +1723,7 @@ apply_config_defaults() { ORIGINAL_BASEPATH="${ORIGINAL_BASEPATH:-}" RANDOM_SEED="${RANDOM_SEED:-}" SHUFFLE="${SHUFFLE:-no}" + SPLASH_PAGE="${SPLASH_PAGE:-yes}" TARBALL_INCLUDE="${TARBALL_INCLUDE:-no}" TARBALL_SUFFIX="${TARBALL_SUFFIX:-.tar}" if ! declare -p TAR_OPTS >/dev/null 2>&1; then @@ -1713,6 +1771,9 @@ apply_cli_overrides() { if [ -n "$cli_shuffle" ]; then SHUFFLE="$cli_shuffle" fi + if [ -n "$cli_splash_page" ]; then + SPLASH_PAGE="$cli_splash_page" + fi if [ -n "$cli_tarball_include" ]; then TARBALL_INCLUDE="$cli_tarball_include" fi @@ -1805,6 +1866,10 @@ validate_template_dir() { config_error "TEMPLATE_DIR $TEMPLATE_DIR must be a readable directory" fi + if [ "${SPLASH_PAGE:-yes}" = yes ]; then + required_templates+=(splash) + fi + for template_name in "${required_templates[@]}"; do if [ ! -r "$TEMPLATE_DIR/$template_name.tmpl" ]; then config_error \ @@ -1844,6 +1909,7 @@ validate_generation_config() { validate_positive_integer_config_var THUMBHEIGHT validate_positive_integer_config_var MAXPREVIEWS validate_yes_no_config_var SHUFFLE + validate_yes_no_config_var SPLASH_PAGE validate_yes_no_config_var TARBALL_INCLUDE if [ ! -d "$INCOMING_DIR" ]; then @@ -1880,6 +1946,7 @@ validate_print_config() { validate_positive_integer_config_var THUMBHEIGHT validate_positive_integer_config_var MAXPREVIEWS validate_yes_no_config_var SHUFFLE + validate_yes_no_config_var SPLASH_PAGE validate_yes_no_config_var TARBALL_INCLUDE resolve_tar_opts tar_opts } @@ -1962,6 +2029,14 @@ parse_cli_arguments() { cli_shuffle='no' has_config_overrides='yes' ;; + --splash) + cli_splash_page='yes' + has_config_overrides='yes' + ;; + --no-splash) + cli_splash_page='no' + has_config_overrides='yes' + ;; --tarball) cli_tarball_include='yes' has_config_overrides='yes' @@ -2035,6 +2110,7 @@ log_configured_action() { log_verbose "Effective incoming directory: ${INCOMING_DIR:-}" log_verbose "Effective output directory: ${DIST_DIR:-}" log_verbose "Effective template directory: ${TEMPLATE_DIR:-}" + log_verbose "Effective splash page setting: ${SPLASH_PAGE:-yes}" log_verbose "Effective tarball setting: ${TARBALL_INCLUDE:-no}" } @@ -2094,6 +2170,7 @@ main() { local cli_maxpreviews='' local cli_random_seed='' local cli_shuffle='' + local cli_splash_page='' local cli_tarball_include='' local cli_template_dir='' local cli_thumbheight='' diff --git a/share/templates/default/splash.tmpl b/share/templates/default/splash.tmpl new file mode 100644 index 0000000..ce3483d --- /dev/null +++ b/share/templates/default/splash.tmpl @@ -0,0 +1,78 @@ +cat <<END +<html> +<head> + <title>${render_title_html}</title> + <style type="text/css"> + body { + background-color: #000000; + color: #ffffff; + background-image: + linear-gradient(rgba(0, 0, 0, 0.35), rgba(0, 0, 0, 0.85)), + url("${render_backhref_css}/${render_blurs_dir_css}/${render_background_image_css}"); + background-size: cover; + background-repeat: no-repeat; + background-position: center center; + font-family: verdana, sans-serif; + margin: 0; + min-height: 100vh; + text-align: center; + } + + a { + color: #ffffff; + } + + main.splash { + align-items: center; + box-sizing: border-box; + display: flex; + flex-direction: column; + justify-content: center; + min-height: 100vh; + padding: 24px; + } + + h1 { + background-color: #000000; + border: 3px solid #ffffff; + box-sizing: border-box; + font-size: 2em; + margin: 0 0 18px; + max-width: 900px; + padding: 8px 12px; + width: 100%; + } + + img.splash-photo { + background-color: #000000; + border: 3px solid #ffffff; + box-sizing: border-box; + max-height: 72vh; + max-width: 95vw; + object-fit: contain; + padding: 5px; + } + + p.enter { + background-color: #000000; + border: 3px solid #ffffff; + font-size: 1.2em; + margin: 18px 0 0; + padding: 8px 14px; + } + </style> +</head> + +<body> + <main class="splash"> + <h1>${render_title_html}</h1> + <a href="${render_enter_page_html}.html"> + <img class="splash-photo" src="${render_backhref_html}/${render_photos_dir_html}/${render_photo_html}" /> + </a> + <p class="enter"> + <a href="${render_enter_page_html}.html">Enter album</a> + </p> + </main> +</body> +</html> +END diff --git a/src/photoalbum.default.conf b/src/photoalbum.default.conf index a4ffb1b..1af7bf2 100644 --- a/src/photoalbum.default.conf +++ b/src/photoalbum.default.conf @@ -9,6 +9,8 @@ HEIGHT=1200 MAXPREVIEWS=40 # Randomly shuffle all previews. # SHUFFLE=yes +# Generate a splash landing page at index.html. +SPLASH_PAGE=yes # Set to any non-empty value for repeatable background, animation, timestamp, # and shuffled preview choices. # RANDOM_SEED=album-build-1 diff --git a/src/photoalbum.sh b/src/photoalbum.sh index facc320..c36e025 100755 --- a/src/photoalbum.sh +++ b/src/photoalbum.sh @@ -31,6 +31,8 @@ usage() { --thumbheight VALUE --maxpreviews N --random-seed VALUE + --splash + --no-splash --shuffle --no-shuffle --tarball @@ -425,6 +427,16 @@ validate_template_context() { redirect) required_vars+=(redirect_page) ;; + splash) + required_vars+=( + backhref + background_image + blurs_dir + enter_page + photo + photos_dir + ) + ;; details) required_vars+=( animation_class @@ -464,6 +476,7 @@ source_template_file() { render_background_image_css="$render_background_image_css" \ render_blurs_dir_css="$render_blurs_dir_css" \ render_current_date_text="$render_current_date_text" \ + render_enter_page_html="$render_enter_page_html" \ render_exif_details_html="$render_exif_details_html" \ render_height_html="$render_height_html" \ render_html_dir_html="$render_html_dir_html" \ @@ -535,6 +548,9 @@ prepare_template_render_vars() { _css_string_escape "$(template_context_value "$context_name" blurs_dir)" ) render_current_date_text=$(_html_escape "$(current_date_text)") + render_enter_page_html=$( + _html_escape "$(template_context_value "$context_name" enter_page)" + ) render_exif_details_html=$( template_context_value "$context_name" exif_details ) @@ -602,6 +618,7 @@ template() { local render_background_image_css local render_blurs_dir_css local render_current_date_text + local render_enter_page_html local render_exif_details_html local render_height_html local render_html_dir @@ -1153,6 +1170,38 @@ render_album_index_redirect() { redirect_page 'page-1' } +render_album_splash_page() { + local -r photos_dir="$1"; shift + local -r html_dir="$1"; shift + local -r blurs_dir="$1"; shift + local -r backhref="$1"; shift + local photo + + photo=$(randomphoto "$photos_dir" splash) + template 'splash' 'index.html' \ + html_dir "$html_dir" \ + backhref "$backhref" \ + blurs_dir "$blurs_dir" \ + background_image "$photo" \ + photos_dir "$photos_dir" \ + photo "$photo" \ + enter_page 'page-1' +} + +render_album_index() { + local -r photos_dir="$1"; shift + local -r html_dir="$1"; shift + local -r blurs_dir="$1"; shift + local -r backhref="$1"; shift + + if [ "${SPLASH_PAGE:-yes}" = yes ]; then + render_album_splash_page "$photos_dir" "$html_dir" "$blurs_dir" \ + "$backhref" + else + render_album_index_redirect "$html_dir" + fi +} + render_album_pages() { local -r photos_dir="$1"; shift local -r html_dir="$1"; shift @@ -1214,7 +1263,7 @@ render_album_pages() { finish_preview_page "$name" "$html_dir" "$backhref" "$tarball_name" render_view_redirects "$html_dir" - render_album_index_redirect "$html_dir" + render_album_index "$photos_dir" "$html_dir" "$blurs_dir" "$backhref" } randomphoto() { @@ -1331,6 +1380,7 @@ write_generation_metadata() { printf ' "maxpreviews": %s,\n' "$(_json_string "${MAXPREVIEWS:-}")" printf ' "random_seed": %s,\n' "$(_json_string "${RANDOM_SEED:-}")" printf ' "shuffle": %s,\n' "$(_json_bool "${SHUFFLE:-no}")" + printf ' "splash_page": %s,\n' "$(_json_bool "${SPLASH_PAGE:-yes}")" printf ' "original_basepath": %s\n' \ "$(_json_string "${ORIGINAL_BASEPATH:-}")" printf ' }\n' @@ -1405,6 +1455,7 @@ dry_run() { printf 'Max previews per page: %s\n' "$MAXPREVIEWS" printf 'Random seed: %s\n' "${RANDOM_SEED:-}" printf 'Shuffle: %s\n' "${SHUFFLE:-no}" + printf 'Splash page: %s\n' "${SPLASH_PAGE:-yes}" printf 'Image count: %s\n' "$image_count" printf 'Tarball setting: %s\n' "${TARBALL_INCLUDE:-no}" if [ "${TARBALL_INCLUDE:-no}" = yes ]; then @@ -1420,8 +1471,13 @@ dry_run() { printf ' %s/blurs\n' "$DIST_DIR" printf 'Planned generated files:\n' - printf ' %s/index.html (%s album index redirect)\n' \ - "$DIST_DIR" "$html_index_count" + if [ "${SPLASH_PAGE:-yes}" = yes ]; then + printf ' %s/index.html (%s splash page)\n' \ + "$DIST_DIR" "$html_index_count" + else + printf ' %s/index.html (%s album index redirect)\n' \ + "$DIST_DIR" "$html_index_count" + fi printf ' %s/photoalbum.json\n' "$DIST_DIR" printf ' %s/photos/* (%s image files)\n' "$DIST_DIR" "$image_count" printf ' %s/thumbs/* (%s image files)\n' "$DIST_DIR" "$image_count" @@ -1471,6 +1527,7 @@ print_config() { print_shell_assignment MAXPREVIEWS "$MAXPREVIEWS" print_shell_assignment RANDOM_SEED "${RANDOM_SEED:-}" print_shell_assignment SHUFFLE "${SHUFFLE:-no}" + print_shell_assignment SPLASH_PAGE "${SPLASH_PAGE:-yes}" print_shell_assignment TARBALL_INCLUDE "${TARBALL_INCLUDE:-no}" print_shell_assignment TARBALL_SUFFIX "${TARBALL_SUFFIX:-.tar}" print_shell_array_assignment TAR_OPTS "${tar_opts[@]}" @@ -1666,6 +1723,7 @@ apply_config_defaults() { ORIGINAL_BASEPATH="${ORIGINAL_BASEPATH:-}" RANDOM_SEED="${RANDOM_SEED:-}" SHUFFLE="${SHUFFLE:-no}" + SPLASH_PAGE="${SPLASH_PAGE:-yes}" TARBALL_INCLUDE="${TARBALL_INCLUDE:-no}" TARBALL_SUFFIX="${TARBALL_SUFFIX:-.tar}" if ! declare -p TAR_OPTS >/dev/null 2>&1; then @@ -1713,6 +1771,9 @@ apply_cli_overrides() { if [ -n "$cli_shuffle" ]; then SHUFFLE="$cli_shuffle" fi + if [ -n "$cli_splash_page" ]; then + SPLASH_PAGE="$cli_splash_page" + fi if [ -n "$cli_tarball_include" ]; then TARBALL_INCLUDE="$cli_tarball_include" fi @@ -1805,6 +1866,10 @@ validate_template_dir() { config_error "TEMPLATE_DIR $TEMPLATE_DIR must be a readable directory" fi + if [ "${SPLASH_PAGE:-yes}" = yes ]; then + required_templates+=(splash) + fi + for template_name in "${required_templates[@]}"; do if [ ! -r "$TEMPLATE_DIR/$template_name.tmpl" ]; then config_error \ @@ -1844,6 +1909,7 @@ validate_generation_config() { validate_positive_integer_config_var THUMBHEIGHT validate_positive_integer_config_var MAXPREVIEWS validate_yes_no_config_var SHUFFLE + validate_yes_no_config_var SPLASH_PAGE validate_yes_no_config_var TARBALL_INCLUDE if [ ! -d "$INCOMING_DIR" ]; then @@ -1880,6 +1946,7 @@ validate_print_config() { validate_positive_integer_config_var THUMBHEIGHT validate_positive_integer_config_var MAXPREVIEWS validate_yes_no_config_var SHUFFLE + validate_yes_no_config_var SPLASH_PAGE validate_yes_no_config_var TARBALL_INCLUDE resolve_tar_opts tar_opts } @@ -1962,6 +2029,14 @@ parse_cli_arguments() { cli_shuffle='no' has_config_overrides='yes' ;; + --splash) + cli_splash_page='yes' + has_config_overrides='yes' + ;; + --no-splash) + cli_splash_page='no' + has_config_overrides='yes' + ;; --tarball) cli_tarball_include='yes' has_config_overrides='yes' @@ -2035,6 +2110,7 @@ log_configured_action() { log_verbose "Effective incoming directory: ${INCOMING_DIR:-}" log_verbose "Effective output directory: ${DIST_DIR:-}" log_verbose "Effective template directory: ${TEMPLATE_DIR:-}" + log_verbose "Effective splash page setting: ${SPLASH_PAGE:-yes}" log_verbose "Effective tarball setting: ${TARBALL_INCLUDE:-no}" } @@ -2094,6 +2170,7 @@ main() { local cli_maxpreviews='' local cli_random_seed='' local cli_shuffle='' + local cli_splash_page='' local cli_tarball_include='' local cli_template_dir='' local cli_thumbheight='' diff --git a/tests/cli.sh b/tests/cli.sh index a554d58..44786f6 100755 --- a/tests/cli.sh +++ b/tests/cli.sh @@ -40,6 +40,9 @@ test::write_preflight_config() { if [ "$omitted_var" != SHUFFLE ]; then printf 'SHUFFLE=no\n' fi + if [ "$omitted_var" != SPLASH_PAGE ]; then + printf 'SPLASH_PAGE=yes\n' + fi if [ "$omitted_var" != TARBALL_INCLUDE ]; then printf 'TARBALL_INCLUDE=no\n' fi @@ -134,6 +137,7 @@ assert metadata["settings"]["height"] == "120" assert metadata["settings"]["thumbheight"] == "30" assert metadata["settings"]["maxpreviews"] == maxpreviews assert metadata["settings"]["shuffle"] is False +assert isinstance(metadata["settings"]["splash_page"], bool) assert "original_basepath" in metadata["settings"] PY } @@ -869,6 +873,7 @@ THUMBHEIGHT=300 MAXPREVIEWS=40 RANDOM_SEED='' SHUFFLE=no +SPLASH_PAGE=yes TARBALL_INCLUDE=yes TARBALL_SUFFIX=.tar TAR_OPTS=( -c ) @@ -1002,6 +1007,7 @@ THUMBHEIGHT=30 MAXPREVIEWS=7 RANDOM_SEED='' SHUFFLE=yes +SPLASH_PAGE=yes TARBALL_INCLUDE=no TARBALL_SUFFIX=.tar TAR_OPTS=( -c ) @@ -1037,6 +1043,7 @@ THUMBHEIGHT=30 MAXPREVIEWS=8 RANDOM_SEED='' SHUFFLE=no +SPLASH_PAGE=yes TARBALL_INCLUDE=no TARBALL_SUFFIX=.tar TAR_OPTS=( -c ) @@ -1082,6 +1089,7 @@ test_print_config_applies_cli_overrides_without_writes() { --maxpreviews 9 \ --random-seed cli-seed \ --shuffle \ + --no-splash \ --tarball ) expected=$(cat <<EOF @@ -1095,6 +1103,7 @@ THUMBHEIGHT=45 MAXPREVIEWS=9 RANDOM_SEED=cli-seed SHUFFLE=yes +SPLASH_PAGE=no TARBALL_INCLUDE=yes TARBALL_SUFFIX=.tar TAR_OPTS=( -c ) @@ -1126,10 +1135,12 @@ test_print_config_applies_negative_cli_overrides() { output=$( cd "$TEST_TMPDIR" - "$TEST_PHOTOALBUM" --print-config --no-shuffle --no-tarball + "$TEST_PHOTOALBUM" \ + --print-config --no-shuffle --no-splash --no-tarball ) test::assert_contains 'SHUFFLE=no' "$output" + test::assert_contains 'SPLASH_PAGE=no' "$output" test::assert_contains 'TARBALL_INCLUDE=no' "$output" test::teardown } @@ -1274,6 +1285,7 @@ test_dry_run_reports_cli_overrides_without_writes() { --maxpreviews 2 \ --random-seed dry-seed \ --shuffle \ + --no-splash \ --tarball ) @@ -1290,6 +1302,7 @@ test_dry_run_reports_cli_overrides_without_writes() { test::assert_contains 'Max previews per page: 2' "$output" test::assert_contains 'Random seed: dry-seed' "$output" test::assert_contains 'Shuffle: yes' "$output" + test::assert_contains 'Splash page: no' "$output" test::assert_contains 'Image count: 6' "$output" test::assert_contains 'Tarball setting: yes' "$output" test::assert_contains 'Tarball name plan: incoming-<timestamp>.tar' \ @@ -1297,7 +1310,9 @@ test_dry_run_reports_cli_overrides_without_writes() { test::assert_contains 'Planned directories:' "$output" test::assert_contains " $dist_dir/photos" "$output" test::assert_contains 'Planned generated files:' "$output" - test::assert_contains " $dist_dir/index.html" "$output" + test::assert_contains \ + " $dist_dir/index.html (1 album index redirect)" \ + "$output" test::assert_contains " $dist_dir/photoalbum.json" "$output" test::assert_contains " $dist_dir/photos/* (6 image files)" "$output" test::assert_contains " $dist_dir/thumbs/* (6 image files)" "$output" @@ -1573,6 +1588,7 @@ test_generate_preflight_rejects_invalid_yes_no_values() { local output local -a bool_vars=( SHUFFLE + SPLASH_PAGE TARBALL_INCLUDE ) @@ -1781,7 +1797,15 @@ test_integration_generates_album_outputs_and_cleans() { test::assert_contains 'Next 2 pictures' "$page_html" test::assert_contains 'No EXIF details available.' "$details_html" test::assert_contains 'href="1-1.html">Image view</a>' "$details_html" - test::assert_contains 'url=page-1.html' "$top_index_html" + test::assert_contains '<title>Integration album</title>' "$top_index_html" + test::assert_contains 'Enter album' "$top_index_html" + test::assert_contains 'href="page-1.html"' "$top_index_html" + test::assert_contains \ + '<img class="splash-photo" src="./photos/' \ + "$top_index_html" + test::assert_not_contains '<script' "$top_index_html" + test::assert_not_contains 'javascript:' "$top_index_html" + test::assert_not_contains "http-equiv='refresh'" "$top_index_html" test::assert_find_count 0 "$TEST_TMPDIR/dist" '*.tar' test::assert_generation_metadata \ "$TEST_TMPDIR/dist/photoalbum.json" \ @@ -1822,6 +1846,82 @@ test_integration_generates_album_outputs_and_cleans() { test::teardown } +test_generate_config_no_splash_keeps_index_redirect() { + local config_file + local fake_bin + local top_index_html + + test::setup + fake_bin="$TEST_TMPDIR/bin" + config_file="$TEST_TMPDIR/photoalbum.conf" + + test::install_fake_imagemagick "$fake_bin" + PATH="$fake_bin:$PATH" \ + test::generate_fixture_images "$TEST_TMPDIR/incoming" + test::write_album_config \ + "$config_file" "$TEST_TMPDIR/incoming" "$TEST_TMPDIR/dist" \ + 'No splash config album' 40 + printf 'SPLASH_PAGE=no\n' >> "$config_file" + + ( + cd "$TEST_TMPDIR" + PATH="$fake_bin:$PATH" "$TEST_PHOTOALBUM" --generate + ) + + top_index_html=$(<"$TEST_TMPDIR/dist/index.html") + test::assert_contains 'url=page-1.html' "$top_index_html" + test::assert_not_contains 'Enter album' "$top_index_html" + test::assert_not_contains '<script' "$top_index_html" + test::assert_not_contains 'javascript:' "$top_index_html" + + python3 - "$TEST_TMPDIR/dist/photoalbum.json" <<'PY' +import json +import pathlib +import sys + +metadata = json.loads(pathlib.Path(sys.argv[1]).read_text()) +assert metadata["settings"]["splash_page"] is False +PY + + test::teardown +} + +test_generate_cli_no_splash_overrides_config() { + local config_file + local fake_bin + local template_dir + local top_index_html + + test::setup + fake_bin="$TEST_TMPDIR/bin" + config_file="$TEST_TMPDIR/photoalbum.conf" + template_dir="$TEST_TMPDIR/templates" + + test::install_fake_imagemagick "$fake_bin" + PATH="$fake_bin:$PATH" \ + test::generate_fixture_images "$TEST_TMPDIR/incoming" + cp -R "$TEST_REPO_ROOT/share/templates/default" "$template_dir" + rm -f "$template_dir/splash.tmpl" + test::write_album_config \ + "$config_file" "$TEST_TMPDIR/incoming" "$TEST_TMPDIR/dist" \ + 'No splash CLI album' 40 + printf 'TEMPLATE_DIR=%q\n' "$template_dir" >> "$config_file" + printf 'SPLASH_PAGE=yes\n' >> "$config_file" + + ( + cd "$TEST_TMPDIR" + PATH="$fake_bin:$PATH" "$TEST_PHOTOALBUM" \ + --generate --no-splash + ) + + top_index_html=$(<"$TEST_TMPDIR/dist/index.html") + test::assert_contains 'url=page-1.html' "$top_index_html" + test::assert_not_contains 'Enter album' "$top_index_html" + test::assert_not_contains '<script' "$top_index_html" + test::assert_not_contains 'javascript:' "$top_index_html" + test::teardown +} + test_generate_replaces_dist_after_success() { local config_file local fake_bin @@ -2084,6 +2184,7 @@ test_generate_escapes_html_values() { local photo_name local title local title_html + local top_index_html local view_html test::setup @@ -2123,14 +2224,18 @@ test_generate_escapes_html_values() { ) page_html=$(<"$TEST_TMPDIR/dist/page-1.html") + top_index_html=$(<"$TEST_TMPDIR/dist/index.html") view_html=$(<"$TEST_TMPDIR/dist/1-1.html") details_html=$(<"$TEST_TMPDIR/dist/1-1-details.html") test::assert_no_html_subdir_output "$TEST_TMPDIR/dist" test::assert_contains "<title>$title_html</title>" "$page_html" + test::assert_contains "<title>$title_html</title>" "$top_index_html" test::assert_contains \ "background-image: url(\"./blurs/$css_photo\");" \ "$page_html" + test::assert_contains "url(\"./blurs/$css_photo\")" "$top_index_html" + test::assert_contains "src=\"./photos/$photo_html\"" "$top_index_html" test::assert_contains "name='$photo_html'" "$page_html" test::assert_contains "src='./thumbs/$photo_html'" "$page_html" test::assert_contains '&"'.tar' "$page_html" @@ -2145,6 +2250,7 @@ test_generate_escapes_html_values() { test::assert_contains "<td>$exif_value_html</td>" "$details_html" test::assert_contains "href=\"1-1.html\">Image view</a>" "$details_html" test::assert_not_contains '<title>A & "quoted" <title>' "$page_html" + test::assert_not_contains "$photo_name" "$top_index_html" test::assert_not_contains "$photo_name" "$view_html" test::assert_not_contains "O'Neil & \"<camera>\"" "$details_html" @@ -2516,6 +2622,12 @@ main() { '--generate creates output structure and --clean removes it' \ test_integration_generates_album_outputs_and_cleans test::run_case \ + '--generate SPLASH_PAGE=no keeps root index redirect' \ + test_generate_config_no_splash_keeps_index_redirect + test::run_case \ + '--generate --no-splash keeps root index redirect' \ + test_generate_cli_no_splash_overrides_config + test::run_case \ '--generate replaces final dist after success' \ test_generate_replaces_dist_after_success test::run_case \ diff --git a/tests/helpers.sh b/tests/helpers.sh index 19f8b21..22bf986 100755 --- a/tests/helpers.sh +++ b/tests/helpers.sh @@ -393,6 +393,7 @@ test::write_album_config() { printf 'INCOMING_DIR=%q\n' "$incoming_dir" printf 'DIST_DIR=%q\n' "$dist_dir" printf 'TEMPLATE_DIR=%q/share/templates/default\n' "$TEST_REPO_ROOT" + printf 'SPLASH_PAGE=yes\n' printf 'TARBALL_INCLUDE=no\n' } > "$config_file" } |
