summaryrefslogtreecommitdiff
path: root/src/lib/stats-filter-album.source.sh
AgeCommit message (Collapse)Author
2026-07-18Add DETAILS_PAGE setting to make per-photo details pages optionalPaul Buetow
Album owners can now set DETAILS_PAGE=no (or pass --no-details) to skip generating each photo's *-details.html EXIF summary page and its "Details" navigation redirects, without touching the normal thumbnail overview, per-photo view pages, EXIF tooltips, or STATS_PAGE, which all stay independently controlled. Every "Details" link (on view pages and stats filter mini-album view pages) and every "-details" redirect stub is gated on the setting so no generated page ever links to a file that was not rendered. Wired the new field through CONFIG_SPECS (registry-driven defaults/validation/print-config/CLI override), the --details/--no-details CLI flags, usage() help, the verbose effective-config log, shuriken.json generation metadata, and the dry-run plan. DETAILS_PAGE=yes (the default) keeps prior output byte-for-byte identical. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-06-28or0: encapsulate STATS_* maps behind aggregator accessorsPaul Buetow
The stats reader modules (stats-render.source.sh, stats-filter-album.source.sh) indexed stats-aggregate.source.sh's private STATS_* associative arrays directly, so a key-convention change in the aggregator would silently break both readers. Add a read API owned by stats-aggregate.source.sh (the data owner), mirroring album-render's ALBUM_VIEW_PAGE_BY_PHOTO / album_view_page_for_photo split: stats_total_photos - STATS_TOTALS[photos] denominator stats_filter_pagebase - (prefix,label) -> pagebase, hiding the STATS_FILTER_KEYSEP catkey encoding stats_filter_title - STATS_FILTER_TITLE[pagebase] stats_filter_photos - STATS_FILTER_PHOTOS[pagebase] list stats_filter_count - number of filter mini-albums stats_filter_pagebases - pagebases, LC_ALL=C-sorted (order owned here) stats_category_count/size/max/keys_by_count_desc - per-category count-array reads Route every cross-module STATS_* read through these accessors. The render module's _stats_max_count / _stats_keys_by_count_desc were duplicates of the new stats_category_max / stats_category_keys_by_count_desc, so they are removed. Behavior preserved exactly: missing-key semantics, iteration order (ordered ladders, calendar months, count-desc with LC_ALL=C tie-break, sorted pagebase enqueue) and generated HTML are byte-identical. Header docs updated to describe the accessor boundary. The arrays stay the backing store; only the cross-module READ path is encapsulated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27Fix src/shuriken.sh lib source list missing 5 modulesPaul Buetow
Running `bash src/shuriken.sh --generate ...` directly from a source checkout printed "command not found" for camera_label_from_make_model, photo_exif_values_to and cached_photo_identify_output for every photo, silently emptying EXIF tooltips/details and, with STATS_PAGE=yes, omitting the whole stats/ tree. The hand-maintained source list inside the SHURIKEN_LIB_SOURCES_BEGIN/END marker block had drifted from the authoritative Justfile LIB_SOURCES, missing metadata-label, metadata-cache, stats-aggregate, stats-render and stats-filter-album. `just build` replaces the marker block with LIB_SOURCES when generating bin/shuriken, so the installed binary and the bin-based test suite never noticed; only direct src execution was affected. - Add the 5 missing `source` lines to the marker block in the same order as Justfile LIB_SOURCES, so the two lists now match exactly. - Add tests/cli.sh case test_lib_sources_match_justfile_lib_sources that extracts the marker-block module names and asserts they equal the Justfile LIB_SOURCES (same set and order) to prevent future drift. - shellcheck --check-sourced now follows the 5 newly-sourced libs; suppress the cross-module nameref false positives (SC2178/SC2128/ SC2154) with explained directives and genuinely fix SC2004 (counts_ref[$key] -> [key]) and quote the TITLE default (${TITLE:-}). bin/shuriken changes only by these propagated lib edits; the marker-block source list it generates is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25Fill the album's short final page with a full-row tilePaul Buetow
A short final preview page (e.g. one leftover photo when the photo count isn't a multiple of the page size) can't be aligned to a multiple of 12 cells, so it left an orphaned bottom-right corner. The album's LAST page now widens its leftover final single tile into a "fill" tile spanning the whole row (grid-column: 1 / -1) at any breakpoint, so the bottom edge is flush; object-fit: cover keeps the wider crop undistorted. append_preview_grid takes a fill_last flag: render_full_preview_page sets it only for the page with no "next" link; stats mini-albums pass 'no' so their small galleries are unaffected. build_tile_block gains a 'fill' layout and header.tmpl an a.fill-row rule. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24Unify escape/date helper API; fix current_date_text cachingPaul Buetow
Make the template.source.sh escape/date helper family follow one consistent shape: each escaper now has a nameref <name>_to form (hot path, writes a named variable) plus a thin printf wrapper <name> that delegates to it. The leading "_" now exclusively marks private helpers; the public escape API (called from sibling modules) is unprefixed. - current_date_text now delegates to current_date_text_to so both forms share the SHURIKEN_CURRENT_DATE_TEXT cache; the printf form no longer silently re-execs `date` on every direct call. Output unchanged. - Drop the misleading "_" prefix on the public escape API and update all callers: _html_escape->html_escape, _css_string_escape-> css_string_escape, _json_string->json_string, _json_bool->json_bool, _json_string_escape->json_string_escape. - Add the missing JSON nameref forms: json_string_escape_to, json_string_to, json_bool_to (printf wrappers delegate to them). - Add tests: JSON printf-vs-nameref parity and a current_date_text caching + nameref-parity check. No escaping/encoding or date output changes -- API-shape/perf only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24Encapsulate job pool behind a single handle (job_pool_*)Paul Buetow
Replace the four-parallel-nameref job-pool API (pids/statuses/labels/failed, each needing its own `shellcheck disable=SC2034` at every call site) with a single pool handle: a name prefix whose four backing variables (${pool}_pids/_statuses/_labels/_failed) are derived on demand by the helpers. Bash can't nest indexed arrays in an associative array, so a prefixed-handle with declare -g backing vars is the simplest pure-nameref encoding (no eval). New public API: job_pool_init <pool> job_pool_submit <pool> <label> <cmd...> job_pool_wait <pool> # returns 1 if any job failed Migrate all callers (scalephotos, create_all_photo_derivatives, render_album_pages, render_view_redirects, render_filter_pages) to the handle. queue_preview_page_render_job / queue_album_view_render_job / _album_record_view_photo / _stats_enqueue_filter_album now take one pool arg instead of four names. Drop the dead wrappers and unused parameterization: wait_for_image_job_slot, wait_for_template_render_job_slot and their _jobs variants only ever passed IMAGE_JOBS, so the max_jobs parameter is gone and throttling is fixed at IMAGE_JOBS inside the pool. Also removes wait_for_album_view_render_jobs (now just job_pool_wait). Throttling (max IMAGE_JOBS concurrent), failure detection and failed-job propagation are unchanged; the parallel-throttling and failure-logging tests pass unmodified. SC2034 disable-comments across the touched files drop 29->7. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24Make the generated album mobile friendlyPaul Buetow
Pure CSS/HTML, no JavaScript: - Add a <meta name="viewport"> tag to the two display heads (header.tmpl and splash.tmpl) so phones stop rendering at a zoomed-out desktop width. - Make the overview grid responsive: minmax(min(THUMBHEIGHT, 100%), 1fr) so a column never overflows a narrow screen, plus a max-width:700px media query that shows exactly two square columns on phones (2x2 feature tiles become full-width heroes). aspect-ratio keeps cells square at every width. - Add overflow-x:hidden to body so the slam/glitch entry animations (translateX +/-80vw) cannot make a phone scroll sideways. - Make the menus touch friendly on phones: the navigator/footer/splash links become large rounded buttons (~44px tap targets) and the "|" separators (now wrapped in <span class="nav-sep">) are hidden on mobile while still showing on desktop. - Fix a pre-existing W3C error: the stats filter view-page image was missing an alt attribute (and carried an obsolete border attribute). Verified with headless screenshots at phone width and the W3C Nu HTML checker + CSS validator (zero errors). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22Reuse the album tile grid for stats mini-album galleries (DRY)Paul Buetow
The per-camera and per-filter stats mini-album galleries rendered their own plain img.thumb grid, so they did not get the dynamic tiles. Make them reuse the album's shared grid builder instead. Generalize append_preview_grid (and build_tile_block / build_subdivided_tile / build_preview_thumbnail) to take an href_prefix rather than a page number: the main album passes "<page_num>-" (view pages "<page>-<n>.html") and the stats mini-albums pass "" (view pages bare "<n>.html") -- the only difference between the two grids. The duplicate _stats_filter_thumbnail is removed; _stats_build_filter_thumbs now calls append_preview_grid, and camera.tmpl wraps the result in the same thumbs-grid container. Stats galleries now get the identical 2x2 feature tiles, subdivided sub-thumbnails, entry animations and hover effects as the main overview. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21Fix W3C HTML validation errors in generated pages; release 0.10.10.10.1Paul Buetow
Every shuriken-generated page failed W3C validation. Fixed across the templates and the bash thumbnail builders so all page categories (splash, gallery, photo view, details, stats overview, stats filter mini-albums and redirect stubs) validate cleanly: - Add <!DOCTYPE html>, <html lang="en"> and <meta charset="utf-8"> to the header, splash and redirect templates. - Drop the obsolete type="text/css" on <style> and border='0' on <img>. - Fix invalid CSS "margin: 2 auto" -> "margin: 2px auto". - Add required alt attributes to every <img> (splash, thumbnails, views). - Replace the obsolete name attribute on <a> thumbnail anchors with id (in album-render.source.sh and stats-filter-album.source.sh, where the markup is actually built, plus preview.tmpl for consistency). - Give redirect stubs a <title>; drop trailing slashes on void elements. Updated the affected cli.sh assertions and rebuilt bin/shuriken. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17pn0 decouple stats from album internalsPaul Buetow
Stats reached directly into album-module internals: the private global ALBUM_VIEW_PAGE_BY_PHOTO and the EXIF cache reader cached_photo_identify_output. Introduce a clean boundary, behaviour and generated HTML byte-identical. - Promote the EXIF identify cache primitive (cached_photo_identify_output plus its private helpers photo_cache_signature and print_cached_photo_identify_output) out of album-metadata.source.sh into a new shared src/lib/metadata-cache.source.sh, sourced before both album and stats (right after metadata-label in LIB_SOURCES). It is a low-level metadata primitive used by both consumers, so it no longer belongs to album internals. Signature/behaviour unchanged. - Add album_view_page_for_photo accessor in album-render.source.sh as the documented public API; keep ALBUM_VIEW_PAGE_BY_PHOTO as the album's private backing store. stats-filter-album.source.sh now calls the accessor instead of indexing the global, so a change to album page naming/caching stays contained in the album module. - Add test_album_stats_decoupling_boundary asserting the accessor returns the backing-store value and that the assembled bin/shuriken keeps the cache primitive in the shared module and no longer indexes the global from the stats filter section. Existing stats/album tests unchanged. Verified: 3-image fixture (STATS_PAGE=yes, fixed seed) diff -r of stashed original vs new build is byte-identical across all 47 dist files (only the inherent generated_at timestamp normalized). just test, just shellcheck, just check-generated and git diff --check all pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16cn0 split stats.source.sh into aggregate/render/filter-album modulesPaul Buetow
Pure code move: split the ~1248-line stats.source.sh (SRP+SoC) into three cohesive modules, all functions and STATS_* constants/globals moved verbatim: - stats-aggregate.source.sh: EXIF parsing, bucketing, _stats_tally, reset/collect_photo_exif_stats and the STATS_* maps. - stats-render.source.sh: stats overview page (sections, bars, leaderboard, render_stats_page, _stats_build_body, _stats_filter_link, background pickers). - stats-filter-album.source.sh: per-filter mini-albums (render_filter_pages, gallery/view/thumbnail builders, _stats_enqueue_filter_album). Updated LIB_SOURCES accordingly. No logic change (verified: all 55 functions and top-level globals preserved; full suite, shellcheck, check-generated, diff all pass). The SoC point (HTML built in bash rather than templates) is left for a follow-up (nn0/qn0). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>