From b7d5c1102c3679b67532f30f2613e4d2d61c59ba Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 14 Jun 2026 23:07:12 +0300 Subject: rm0 wire stats feature into generate with STATS_PAGE toggle Final integration of the stats-site feature: - Add STATS_PAGE config (default yes) mirroring SPLASH_PAGE through every layer: shuriken.default.conf, apply_config_defaults, CLI_OPTION_SPEC (--stats/--no-stats), the CLI_CONFIG_OVERRIDE_TARGETS allowlist (without which the flag was silently ignored), usage text, yes/no validation, print_config, the action config list + effective-setting log, the generation metadata, and the dry-run plan. - generate() now calls a gated generate_stats_pages helper after the album pages (and before archiving, so the stats/camera pages are tarballed): collect_photo_exif_stats + render_stats_page . . + render_camera_pages . . - Emit "stats_page" in shuriken.json next to "splash_page". - Gate the header Stats nav link behind STATS_PAGE via a new render_stats_page_html config_html field, so it is hidden (no 404) when stats are disabled. - Document STATS_PAGE and --stats/--no-stats in the README. - Tests: full --generate produces stats.html + camera-.html + the nav link and stats_page=true; --no-stats suppresses all three and sets stats_page=false; print-config and metadata expectations updated. Co-Authored-By: Claude Opus 4.8 --- src/lib/action.source.sh | 2 ++ src/lib/album.source.sh | 17 +++++++++++++++++ src/lib/bootstrap.source.sh | 2 ++ src/lib/config.print.source.sh | 1 + src/lib/config.source.sh | 1 + src/lib/config.validate.source.sh | 1 + src/lib/template.source.sh | 7 +++++++ 7 files changed, 31 insertions(+) (limited to 'src/lib') diff --git a/src/lib/action.source.sh b/src/lib/action.source.sh index 987fd7a..e2649d7 100644 --- a/src/lib/action.source.sh +++ b/src/lib/action.source.sh @@ -53,6 +53,7 @@ run_action_body_context() { RANDOM_SEED SHUFFLE SPLASH_PAGE + STATS_PAGE TARBALL_INCLUDE TARBALL_SUFFIX TAR_OPTS @@ -158,6 +159,7 @@ log_configured_action() { log_verbose "Effective ImageMagick timeout: ${IMAGEMAGICK_TIMEOUT}s" log_verbose "Effective tar timeout: ${TAR_TIMEOUT}s" log_verbose "Effective splash page setting: $SPLASH_PAGE" + log_verbose "Effective stats page setting: $STATS_PAGE" log_verbose "Effective tarball setting: $TARBALL_INCLUDE" log_verbose "Effective sync delete setting: $SYNC_DELETE" log_verbose "Effective force generation setting: $SHURIKEN_FORCE_GENERATE" diff --git a/src/lib/album.source.sh b/src/lib/album.source.sh index 2036591..c9812a2 100644 --- a/src/lib/album.source.sh +++ b/src/lib/album.source.sh @@ -927,6 +927,7 @@ _collect_generation_metadata() { _GENERATION_METADATA["settings_random_seed"]="$RANDOM_SEED" _GENERATION_METADATA["settings_shuffle"]="$SHUFFLE" _GENERATION_METADATA["settings_splash_page"]="$SPLASH_PAGE" + _GENERATION_METADATA["settings_stats_page"]="$STATS_PAGE" _GENERATION_METADATA["settings_original_basepath"]="$ORIGINAL_BASEPATH" } @@ -985,6 +986,8 @@ _generation_metadata_json() { "$(_json_bool "${_GENERATION_METADATA["settings_shuffle"]}")" printf ' "splash_page": %s,\n' \ "$(_json_bool "${_GENERATION_METADATA["settings_splash_page"]}")" + printf ' "stats_page": %s,\n' \ + "$(_json_bool "${_GENERATION_METADATA["settings_stats_page"]}")" printf ' "original_basepath": %s\n' \ "$(_json_string "${_GENERATION_METADATA["settings_original_basepath"]}")" printf ' }\n' @@ -1040,6 +1043,16 @@ create_generation_archive() { fi } +# Aggregate EXIF stats and render the stats page plus the per-camera pages into +# the dist root (html_dir and backhref are '.', matching render_album_pages). +# Run after the album pages so the per-photo identify cache is already warm. +generate_stats_pages() { + log_verbose 'Stats page enabled; collecting EXIF stats' + collect_photo_exif_stats + render_stats_page . . + render_camera_pages . . +} + generate() { local tarball_name='' @@ -1056,6 +1069,9 @@ generate() { prepare_generation_site_assets clear_rendered_html render_album_pages 'photos' '.' 'thumbs' 'blurs' '.' "$tarball_name" + if [ "$STATS_PAGE" = yes ]; then + generate_stats_pages + fi create_generation_archive "$tarball_name" write_generation_metadata "$tarball_name" } @@ -1158,6 +1174,7 @@ collect_dry_run_plan() { plan_ref["random_seed"]="$RANDOM_SEED" plan_ref["shuffle"]="$SHUFFLE" plan_ref["splash_page"]="$SPLASH_PAGE" + plan_ref["stats_page"]="$STATS_PAGE" plan_ref["image_count"]="$image_count" plan_ref["tarball_include"]="$TARBALL_INCLUDE" plan_ref["tarball_name_plan"]='not planned' diff --git a/src/lib/bootstrap.source.sh b/src/lib/bootstrap.source.sh index 67ba090..a047f5d 100644 --- a/src/lib/bootstrap.source.sh +++ b/src/lib/bootstrap.source.sh @@ -23,6 +23,8 @@ usage() { --random-seed VALUE --splash --no-splash + --stats + --no-stats --shuffle --no-shuffle --tarball diff --git a/src/lib/config.print.source.sh b/src/lib/config.print.source.sh index bad29ef..7b91b60 100644 --- a/src/lib/config.print.source.sh +++ b/src/lib/config.print.source.sh @@ -36,6 +36,7 @@ print_config() { print_shell_assignment RANDOM_SEED "$RANDOM_SEED" print_shell_assignment SHUFFLE "$SHUFFLE" print_shell_assignment SPLASH_PAGE "$SPLASH_PAGE" + print_shell_assignment STATS_PAGE "$STATS_PAGE" print_shell_assignment TARBALL_INCLUDE "$TARBALL_INCLUDE" print_shell_assignment TARBALL_SUFFIX "$TARBALL_SUFFIX" print_shell_assignment TAR_TIMEOUT "$TAR_TIMEOUT" diff --git a/src/lib/config.source.sh b/src/lib/config.source.sh index 348f167..50c331a 100644 --- a/src/lib/config.source.sh +++ b/src/lib/config.source.sh @@ -37,6 +37,7 @@ apply_config_defaults() { RANDOM_SEED="${RANDOM_SEED:-}" SHUFFLE="${SHUFFLE:-no}" SPLASH_PAGE="${SPLASH_PAGE:-yes}" + STATS_PAGE="${STATS_PAGE:-yes}" SYNC_DELETE="${SYNC_DELETE:-yes}" TARBALL_INCLUDE="${TARBALL_INCLUDE:-no}" TARBALL_SUFFIX="${TARBALL_SUFFIX:-.tar}" diff --git a/src/lib/config.validate.source.sh b/src/lib/config.validate.source.sh index b858144..bd2fccf 100644 --- a/src/lib/config.validate.source.sh +++ b/src/lib/config.validate.source.sh @@ -193,6 +193,7 @@ validate_common_config() { validate_positive_integer_config_var TAR_TIMEOUT || return validate_yes_no_config_var SHUFFLE || return validate_yes_no_config_var SPLASH_PAGE || return + validate_yes_no_config_var STATS_PAGE || return validate_yes_no_config_var TARBALL_INCLUDE || return } diff --git a/src/lib/template.source.sh b/src/lib/template.source.sh index 9fd3ad4..8e5b93e 100644 --- a/src/lib/template.source.sh +++ b/src/lib/template.source.sh @@ -167,6 +167,7 @@ declare -ra TEMPLATE_RENDER_FIELD_SPECS=( 'render_redirect_page_html|context_html|redirect_page|redirect_page|redirect' 'render_show_header_bar|context_raw|show_header_bar|show_header_bar|header' 'render_stats_body_html|context_raw|stats_body|stats_body|stats' + 'render_stats_page_html|config_html|STATS_PAGE||' 'render_tarball_include|tarball_include|||' 'render_tarball_name_html|context_html|tarball_name|tarball_name|footer' 'render_thumbheight_html|config_html|THUMBHEIGHT||' @@ -478,6 +479,12 @@ prepare_template_render_vars() { ORIGINAL_BASEPATH) context_value="$ORIGINAL_BASEPATH" ;; + STATS_PAGE) + # Always defaulted by apply_config_defaults; degrade to + # "no" (link hidden) if somehow unset so the header bar + # never references a stats page that was not generated. + context_value="${STATS_PAGE:-no}" + ;; THUMBHEIGHT) # Refresh-only configs do not require generation # sizing fields; render absent values as empty. -- cgit v1.2.3