| Age | Commit message (Collapse) | Author |
|
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>
|
|
Pure, behavior-preserving refactor: extract _-prefixed helpers from six
functions that exceeded the project's 50-line threshold, leaving each
original as a thin orchestrator. Generated HTML, dry-run output,
shuriken.json, EXIF cache behavior and the flush-grid layout are all
byte-identical (full test suite green).
Refactored:
- _generation_metadata_json -> _generation_metadata_json_head +
_generation_metadata_json_settings
- print_dry_run_plan -> _print_dry_run_settings + _print_dry_run_files
- _photo_exif_tooltip_text_from_values -> _collect_exif_tooltip_parts +
_emit_exif_tooltip_parts
- cached_photo_identify_output -> _rebuild_photo_identify_cache
- render_album_pages -> _render_album_page (one page record)
- append_preview_grid -> _roll_and_align_page_tiles + _emit_page_tiles
(uniquely-named namerefs to avoid circular-nameref)
Left intact (delicate errexit/trap management that must stay in one
function scope, where a split would change semantics):
source_template_file, refresh_splash, generate_staged,
replace_dist_with_staging.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
collect_dry_run_page_plan re-derived page_count via the ceil formula and
redirect_count via a magic "*4+2", duplicating logic owned by
album_page_records (pagination) and render_page_view_redirects (redirect
files). The preview could silently drift from a real --generate.
Single source of truth:
- album_page_count_for_image_count (album-photo-select.source.sh) owns the
MAXPREVIEWS-per-page grouping count that album_page_records realises.
- ALBUM_REDIRECTS_PER_PAGE=4 / ALBUM_REDIRECTS_LAST_PAGE_EXTRA=2 +
album_redirect_count_for_page_count (album-render.source.sh) own the
per-page (4) plus last-page-extra (2) redirect tally that
render_page_view_redirects actually emits.
dry-run now predicts both counts through these helpers (no dist files
touched, side-effect free). Confirmed the real redirect count is
page_count*4+2, so output is byte-identical: partial-final-page (3 preview
pages / 14 navigation redirects) and empty album (0 / 0) unchanged.
Regenerated bin/shuriken; just test/shellcheck/check-generated all pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
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>
|
|
Collapse the duplicated "find photos, error on empty, random_index by
ctx, return one" pattern into a single photo-list.source.sh exposing
list_photos <dir> and pick_random_photo <dir> <ctx>. Consumers in
album-photo-select, album-render, image-pipeline and stats-render now
call the shared helpers; _stats_load_background_photos keeps its caching
via a cached list_photos call rather than re-listing per filter page.
Per-call-site random_index ctx strings are preserved, so selection
semantics are unchanged. Sourced before its consumers in LIB_SOURCES
(Justfile + src/shuriken.sh); bin/shuriken regenerated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
album-render.source.sh bundled four concerns that change for unrelated
reasons. Extract three focused siblings, leaving album-render as the page
orchestrator:
- album-tile-layout.source.sh tile_layout_for, build_tile_block,
build_subdivided_tile
- album-thumbnail-html.source.sh build_preview_thumbnail,
append_preview_grid
- album-photo-select.source.sh album_photo_files, album_page_records,
splash_photo_files, random_splash_photo,
randomphoto
album-render.source.sh keeps page assembly, the per-photo view/details
pages, navigation redirects, index/splash, and the job_pool_* plumbing.
Every function moved whole with no body/signature change. The
album_view_page_for_photo accessor and its private ALBUM_VIEW_PAGE_BY_PHOTO
map stay in album-render so the stats mini-album boundary is unchanged.
LIB_SOURCES (Justfile + src/shuriken.sh) sources the three new modules
before album-render. Regenerated bin/shuriken.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
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>
|
|
Each tile rolled for a feature independently, so a page (or stats
gallery) could fill up with large 2x2 hero tiles. append_preview_grid
now counts the features it has placed and stops offering the "feature"
layout to tile_layout_for once two have been used, so any single grid
gets at most two feature tiles; later tiles fall back to subdivided or
single. The cap is per append_preview_grid call, so it applies to both
the main preview pages and the stats mini-album galleries.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
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>
|
|
Allow a single photo to be blown up into a large "feature" tile that
spans a 2x2 block of the album overview, controlled by a new
THUMB_FEATURE_PERCENT (0-100, default 10; 0 disables). Each tile rolls
for a feature first, then for a subdivision, otherwise stays a normal
square.
To pack mixed-size tiles (normal 1x1, subdivided 1x1, feature 2x2)
without gaps, the overview is now a real CSS grid with
grid-auto-flow: dense, so smaller tiles backfill the holes a 2x2 feature
would leave. Tile spacing moved from per-image padding to the grid gap.
Feature tiles reuse the img.thumb class and its dramatic hover.
THUMB_FEATURE_PERCENT is wired through the same layers as
THUMB_SUBDIVIDE_PERCENT: config defaults, 0..100 validation,
--print-config, the --feature CLI flag, the usage text, and the
shuriken.json / --dry-run metadata, with docs and tests updated.
Generated HTML and CSS pass the W3C Nu HTML checker and CSS validator.
Setting both percentages to 0 reproduces the previous all-1x1 grid.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Make the album preview grid livelier: with a configurable probability
(THUMB_SUBDIVIDE_PERCENT, default 30%) a square thumbnail tile is
subdivided into several smaller thumbnails packed into the same square
footprint, chosen at random from:
- quad: 2x2 squares (4 photos)
- two-wide: two stacked full-width strips (2 photos)
- squares+wide: two squares plus one full-width strip, strip on the
top or the bottom (3 photos)
Each sub-thumbnail stays its own clickable photo with its own view page;
subdivision only groups consecutive photos visually, so preview
numbering and the view/details/redirect pages are unchanged. No new
images are generated (CSS object-fit crops the existing aspect-correct
thumbs into squares or wide strips). Sub-thumbnails get the same random
entry animation and the same dramatic hover (flip/scale/rotate/filter)
as full thumbs. The layout choice reuses the seeded random_index, so
builds stay reproducible under RANDOM_SEED. THUMB_SUBDIVIDE_PERCENT=0
reproduces the previous output byte-for-byte.
The new option is wired through the config defaults, validation
(0..100), --print-config, the --subdivide CLI flag, the usage text, and
the shuriken.json / --dry-run metadata, with docs and tests updated.
Generated HTML and CSS pass the W3C Nu HTML checker and CSS validator.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
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>
|
|
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>
|
|
Each thumbnail on a preview page (page-N.html) used to be rendered by its
own "template preview" call, paying the full source_template_file cost --
an "env -i bash" invocation -- per thumbnail. With MAXPREVIEWS thumbnails
per page that was N template renders per page just for the grid.
render_full_preview_page now builds the markup for ALL of a page's
thumbnails in bash (build_preview_thumbnail / append_preview_thumbnail)
and emits the whole grid in ONE render via a new previewpage.tmpl that
takes the pre-built HTML through a context_raw "preview_thumbs" field --
the same pattern the stats filter galleries (camera.tmpl) already use.
Per-thumbnail markup is byte-identical to the old preview.tmpl output:
same <a name=... href=...><img class='thumb <anim>' .../></a> structure,
order, HTML escaping and seeded "slow" animation class. Header and footer
stay as their own template calls, so a page now costs ~1 previewpage
render + header/footer instead of N + chrome.
The parallel job-pool integration and failure contract are unchanged:
each preview page is still one background render job. Added the
render_preview_thumbs_html field spec (hn0 dispatch pattern, context_raw
kind), registered previewpage in the validate_template_dir required
templates and in the required-context-vars test expectations, and pointed
the four generation template-failure tests at previewpage.tmpl (generation
no longer renders preview.tmpl). The standalone "template preview" engine
unit tests keep exercising preview.tmpl, which still ships.
Verified byte-identical output: generated the fixture album (including a
spaces/special-char filename) twice with RANDOM_SEED=42 using the parent
commit's bin/shuriken vs the new bin; every .html file is identical.
just test, just shellcheck, just check-generated and git diff --check all
pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
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>
|