summaryrefslogtreecommitdiff
path: root/src/lib/album.source.sh
AgeCommit message (Collapse)Author
2026-06-24Trap-clean refresh_splash temp file; drop fragile errexit $- dancePaul Buetow
refresh_splash mktemp'd $tmp_html was only removed on the explicit failure-return paths, so a signal between mktemp and the final mv leaked a .index.html.XXXXXX file in DIST_DIR that --clean (which only sweeps .shuriken.* staging artifacts) would never reap. Register a cleanup trap right after mktemp, mirroring source_template_file: RETURN covers normal and error returns, INT/TERM/HUP cover signal termination, the handler clears all of these traps (including itself), and the success path clears the trap before the mv so the renamed file is not deleted on return. Also remove the fragile errexit save/restore that string-tested $- to remember whether errexit was on. refresh_splash always runs under the top-level set -euo pipefail, so a localized "set +e; ( set -e; ... ); status=$?; set -e" around each render subshell is sufficient and matches the project's canonical "localized set +e for expected failures" idiom. The bare standalone subshell is required: bash ignores an inner set -e when a compound command sits in an if/&&/|| context, which would let render_album_splash_page run past a failing photo=$(random_splash_photo) and silently produce a broken splash page. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16in0 split album.source.sh into cohesive modulesPaul Buetow
Refactor the ~1442-line album.source.sh ([SRP] violation) into three cohesive modules, leaving album.source.sh a thin coordinator. Pure code move, no behavior change -- whole functions and their doc comments moved verbatim; the assembled bin/shuriken contains the same function set. - image-pipeline.source.sh: ImageMagick derivative generation (create_photo_derivatives, create_all_photo_derivatives) and photo asset prep (prepare_generation_photo_assets). - album-metadata.source.sh: EXIF identify caching, exif tooltip/details helpers, file counts, shuriken.json metadata, EXIF cache clearing and the dry-run plan. - album-render.source.sh: preview/view/details/splash/redirect page rendering, the parallel render-job orchestration and the ALBUM_VIEW_PAGE_BY_PHOTO global. - album.source.sh: thin coordinator (generate, refresh_splash, generate_stats_pages, site-asset/archive/html-clean helpers). Add the three modules to LIB_SOURCES (Justfile) and to the SHURIKEN_LIB_SOURCES markers in src/shuriken.sh, ordered after random and before album.source.sh / stats.source.sh. just build, 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-16vn0 parallelize preview pages and navigation redirectsPaul Buetow
Only per-photo view/detail pages were backgrounded; preview pages (page-*.html) and navigation redirects rendered serially in the main loop, serializing album generation. - render_full_preview_page assembles a complete preview page (header, optional prev link, ordered thumbnails, next/footer) in one call so the per-page appends stay sequential; queue_preview_page_render_job backgrounds each whole page via the shared template render pool, throttled to IMAGE_JOBS. - render_album_pages now materializes the full deterministic page layout up front (album_page_records) and enqueues both view jobs and one preview-page job per page into the same pool; per-photo bookkeeping moved to _album_record_view_photo. - render_view_redirects enqueues one job per view page (render_page_view_redirects) and blocks until all redirects exist, preserving its synchronous contract while parallelizing the work. - Removed obsolete advance_album_preview_page and render_album_page_thumbnail. Parallelism only affects timing: seeded random choices are context-keyed, so output is byte-identical across runs. A failed preview or redirect job flips render_failed and makes generation exit non-zero, matching the view-job failure contract. The IMAGE_JOBS cap still bounds concurrent renders. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15Make the favicon configurable via FAVICON config / --favicon flagPaul Buetow
The generated pages link a favicon.ico that was always the bundled shuriken favicon (copy_site_favicon hard-copied share/shuriken/assets/favicon.ico). Add a FAVICON config variable and a --favicon PATH CLI flag: when set, that file is published as favicon.ico instead of the bundled default; when empty, the bundled favicon is used as before. Plumbed through apply_config_defaults, CLI_OPTION_SPEC + override allowlist, usage, print_config, the action config list and effective-setting log, and validated (a non-empty FAVICON must be a readable file) before generation. shuriken.default.conf and the README document it; a test covers a custom favicon, its appearance in --print-config, and rejection of a missing file. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15Move the stats site into a stats/ subdir to keep the album root smallPaul Buetow
The filter mini-albums put thousands of HTML files directly in the album root. Reorganise so only the main album lives in DIST_DIR and all stats content goes under stats/: stats/index.html - the stats overview (was stats.html) stats/<pagebase>/index.html - each filter gallery (was <pagebase>.html) stats/<pagebase>/<index>.html - each filter view page (was <pagebase>--N.html) Each mini-album is its own directory, so no single directory holds more than one filter's pages. Links updated accordingly: the overview links to <pagebase>/, the gallery thumbnails link to sibling <index>.html, view prev/next/gallery are same-dir, and assets/album-details/back-to-stats resolve via the ../.. backhref. The header Stats link and camera.tmpl back link point at stats/index.html. Mini-albums still reuse the shared photos/thumbs/blurs assets and render in parallel. Tests and the dry-run plan updated for the new layout; README documents the stats/ subdirectory structure. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15Persist the EXIF cache in a volatile ./cache dir parallel to ./distPaul Buetow
The per-photo `identify -verbose` cache lived in $DIST_DIR/.shuriken-cache, which is inside the throwaway staging dir and the published dist: a fresh/cleared dist lost it (forcing a full, slow re-identify of every original) and it got deployed to web servers. Move it to a volatile ./cache/exif directory parallel to ./dist (dirname of DIST_DIR resolves to the working dir in both the staging and direct contexts). Now an unchanged photo skips identify on every regenerate, the cache survives a cleared dist, and it is never deployed. --force clears ./cache/exif once up front (clear_exif_cache) and the run repopulates it, so force still does exactly one identify per photo. Dropped .shuriken-cache from the staging-copy loop. Tests and the audit doc updated for the new cache location. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15Make every stat bucket a clickable filter mini-album, rendered in parallelPaul Buetow
Generalises the per-camera mini-albums to every stats category: clicking any row on the stats page (camera, lens, year, month, aperture, shutter, ISO, focal length, megapixels, aspect, orientation, format, exposure program, metering, white balance, flash) now opens a filter mini-album of just the matching photos, with view pages whose prev/next cycle within the filter. Aggregation: a single _stats_tally now records, for every tallied bucket, the bucket's photo list and a unique filename-safe "pagebase" (camera-canon-eos-r5, iso-400, year-2023, ...) with collision resolution, exposed via STATS_FILTER_* maps. The old camera-only STATS_CAMERA_SLUGS/PHOTOS/SLUG_OWNERS are gone. Render: every bar/leaderboard row is wrapped in a link to its bucket's pagebase via _stats_filter_link. render_filter_pages replaces render_camera_pages and renders ALL filter mini-albums (gallery + per-photo view pages) reusing camera.tmpl/cameraview.tmpl. The galleries/view pages reuse the album's shared photos/thumbs/blurs assets -- only the HTML differs. Parallelism: filter pages render through the shared job pool, throttled to IMAGE_JOBS (the same pool the album view pages use). The album render warms every photo's EXIF cache (via details pages) before the parallel filter render, so the filter jobs only read the cache. Tests updated for the new STATS_FILTER_* structures and extended to assert non-camera filter mini-albums (orientation, ISO) and their stats-page links. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15Stats/camera pages: blurred background, album-like camera thumbs, spacingPaul Buetow
Three refinements to the stats site: - Stats and per-camera pages now get a random blurred background image (same seeded pick the album preview pages use) instead of a plain black page. Adds _stats_random_background + STATS_BLURS_DIR; falls back to black when no photos exist (e.g. isolated unit tests). - Per-camera thumbnails now behave like the main album: they link to each photo's album view page (navigation, details, EXIF tooltip) and carry the same seeded animation class, instead of linking to the raw image. render_album_pages records a photo -> "<page>-<preview>" map (ALBUM_VIEW_PAGE_BY_PHOTO) that the camera pages read; photos with no recorded view page fall back to the image. - Spacing: the camera leaderboard rows get padding + a separator line so the long wrapping camera names are distinguishable, and the stats sections, headings, bar rows, back-link, and camera grid get moderate extra spacing so nothing looks cramped. Tests updated for the new camera-thumbnail markup and extended to assert the stats background and the album view-page links; camera.tmpl comment corrected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15Add EXIF mouse-over tooltip to the normal image viewPaul Buetow
The details view already showed a title="" hover summary (camera, aperture, ISO, shutter, date) on its image; the normal image view did not. Wire the same tooltip into view.tmpl: - render_view_page now computes the EXIF tooltip via photo_exif_tooltip_text (reusing the shared identify cache, so no extra ImageMagick work) and passes it as the exif_tooltip context var. - exif_tooltip is now a required render field for the view template too. - view.tmpl adds the title="" attribute to its <img> when the summary is non-empty, mirroring details.tmpl (no title when there is no EXIF). - Tests: extend the EXIF render test to assert the view image carries the same tooltip, and update the required-context-vars expectation for view. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14rm0 surface stats page in the dry-run planPaul Buetow
Review follow-up: collect_dry_run_plan stored plan["stats_page"] but print_dry_run_plan never rendered it, so --dry-run gave no signal about the STATS_PAGE toggle or the stats/camera pages generate() would write (dead assignment, breaking parity with splash_page). Print a "Stats page: <yes|no>" line and, when enabled, list stats.html and camera-*.html under "Planned generated files" (camera pages are a wildcard since dry-run does not run EXIF aggregation). Add a --dry-run --no-stats test asserting the stats plan is omitted, and extend the existing dry-run test to assert the stats lines when enabled. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14rm0 wire stats feature into generate with STATS_PAGE togglePaul Buetow
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-<slug>.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 <noreply@anthropic.com>
2026-06-14km0 harden parallel job poolPaul Buetow
2026-06-13dm0: split dry-run planning from outputPaul Buetow
2026-06-13jm0: centralize runtime config defaultsPaul Buetow
2026-06-13Refactor generation metadata writing for cm0Paul Buetow
2026-06-12Refactor EXIF tooltip parsing for em0Paul Buetow
2026-06-12Fix remaining errexit masking for bm0Paul Buetow
2026-06-11Rename photoalbum to shurikenPaul Buetow
2026-06-11Copy favicon when refreshing splashPaul Buetow
2026-06-11Add shuriken logo and generated faviconPaul Buetow
2026-06-11Fix detail redirect dry-run countPaul Buetow
2026-06-11Keep detail navigation in detail viewPaul Buetow
2026-06-11Add EXIF tooltip to details viewPaul Buetow
2026-06-11Parallelize template rendering jobsPaul Buetow
2026-06-11Split photoalbum source into lib modulesPaul Buetow