summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/shuriken100
-rw-r--r--share/templates/default/camera.tmpl2
-rw-r--r--src/lib/album-render.source.sh55
-rw-r--r--src/lib/stats-filter-album.source.sh45
-rwxr-xr-xtests/cli.sh25
5 files changed, 122 insertions, 105 deletions
diff --git a/bin/shuriken b/bin/shuriken
index fb2e4df..ec78a7e 100755
--- a/bin/shuriken
+++ b/bin/shuriken
@@ -2552,8 +2552,10 @@ render_full_preview_page() {
# also groups the page's photos into tiles (some subdivided into smaller
# thumbnails), so the per-page ordering and preview numbering stay here.
local preview_thumbs=''
+ # The main album's view pages are "<page_num>-<preview_num>.html", so the
+ # shared grid builder gets "<page_num>-" as the href prefix.
append_preview_grid preview_thumbs \
- "$thumbs_dir" "$backhref" "$page_num" "$@"
+ "$thumbs_dir" "$backhref" "$page_num-" "$@"
template previewpage "$page_name.html" \
html_dir "$html_dir" \
preview_thumbs "$preview_thumbs"
@@ -2620,19 +2622,22 @@ queue_preview_page_render_job() {
render_job_labels_ref["$!"]="template render job for preview $page_name"
}
-# Build a page's whole thumbnail-grid buffer by walking its photos and grouping
+# Build a whole thumbnail-grid buffer by walking a list of photos and grouping
# them into tiles. Most tiles are a single square thumbnail, but (controlled by
-# THUMB_SUBDIVIDE_PERCENT) some are subdivided into several smaller thumbnails
-# packed into the same square footprint. Each photo keeps its 1-based page
-# position as its preview number (subdivision only groups CONSECUTIVE photos
-# visually, never reorders them), so the view-page links stay correct. Tile
-# blocks are separated by a single newline; the previewpage template adds the
-# trailing newline, matching the old per-thumbnail rendering.
+# THUMB_FEATURE_PERCENT / THUMB_SUBDIVIDE_PERCENT) some become a 2x2 feature tile
+# or are subdivided into several smaller thumbnails. Each photo keeps its 1-based
+# position as its preview number (tiling only groups CONSECUTIVE photos visually,
+# never reorders them), so the view-page links stay correct. The view-page link
+# is "${href_prefix}${preview_num}.html": the main album passes "<page_num>-"; the
+# stats mini-albums pass "" (their view pages are bare "<index>.html"). This is
+# the single shared grid builder for both the main preview pages and the stats
+# mini-album galleries. Tile blocks are separated by a single newline; the
+# template adds the trailing newline.
append_preview_grid() {
local -n buffer_ref="$1"; shift
local -r thumbs_dir="$1"; shift
local -r backhref="$1"; shift
- local -r page_num="$1"; shift
+ local -r href_prefix="$1"; shift
local -a photos=("$@")
local -i i=0
local -i count
@@ -2646,7 +2651,7 @@ append_preview_grid() {
tile_layout_for "$(( ${#photos[@]} - i ))" "${photos[i]}"
)
block=$(build_tile_block \
- "$thumbs_dir" "$backhref" "$page_num" "$layout" "$(( i + 1 ))" \
+ "$thumbs_dir" "$backhref" "$href_prefix" "$layout" "$(( i + 1 ))" \
"${photos[@]:i:count}")
if [ -z "$buffer_ref" ]; then
buffer_ref="$block"
@@ -2714,7 +2719,7 @@ tile_layout_for() {
build_tile_block() {
local -r thumbs_dir="$1"; shift
local -r backhref="$1"; shift
- local -r page_num="$1"; shift
+ local -r href_prefix="$1"; shift
local -r layout="$1"; shift
local -ri start_preview="$1"; shift
local -a photos=("$@")
@@ -2730,13 +2735,13 @@ build_tile_block() {
anchor_class='feature'
fi
build_preview_thumbnail \
- "$thumbs_dir" "$backhref" "$page_num" "$start_preview" \
+ "$thumbs_dir" "$backhref" "$href_prefix" "$start_preview" \
"${photos[0]}" "$animation_class" thumb "$anchor_class"
return
;;
esac
build_subdivided_tile \
- "$thumbs_dir" "$backhref" "$page_num" "$layout" "$start_preview" \
+ "$thumbs_dir" "$backhref" "$href_prefix" "$layout" "$start_preview" \
"${photos[@]}"
}
@@ -2752,7 +2757,7 @@ build_tile_block() {
build_subdivided_tile() {
local -r thumbs_dir="$1"; shift
local -r backhref="$1"; shift
- local -r page_num="$1"; shift
+ local -r href_prefix="$1"; shift
local -r layout="$1"; shift
local -ri start_preview="$1"; shift
local -a photos=("$@")
@@ -2771,7 +2776,7 @@ build_subdivided_tile() {
for (( k = 0; k < ${#photos[@]}; k++ )); do
animation_class=$(random_animation_css_class slow "${photos[k]}")
build_preview_thumbnail \
- "$thumbs_dir" "$backhref" "$page_num" "$(( start_preview + k ))" \
+ "$thumbs_dir" "$backhref" "$href_prefix" "$(( start_preview + k ))" \
"${photos[k]}" "$animation_class" subthumb "${anchor_classes[k]:-}"
printf '\n'
done
@@ -2780,15 +2785,19 @@ build_subdivided_tile() {
# Render the HTML for a single preview thumbnail (HTML-escaping every value the
# way preview.tmpl's context_html fields did). Returned without a trailing
-# newline so callers control separators. img_class defaults to 'thumb' (the full
-# square); subdivided tiles pass 'subthumb'. anchor_class is an optional extra
-# class on the <a> ('wide' marks the full-width strip inside a subdivided tile);
-# when empty the <a> has no class attribute, keeping the single-tile output
-# byte-identical to before.
+# newline so callers control separators. The view-page link is
+# "${href_prefix}${preview_num}.html", so the main album passes "<page_num>-" and
+# the stats mini-albums (whose view pages are bare "<index>.html") pass "" -- the
+# only thing that differs between the two grids, keeping one shared builder.
+# img_class defaults to 'thumb' (the full square); subdivided tiles pass
+# 'subthumb'. anchor_class is an optional extra class on the <a> ('wide' marks the
+# full-width strip inside a subdivided tile, 'feature' a 2x2 hero tile); when empty
+# the <a> has no class attribute, keeping the single-tile output byte-identical to
+# before.
build_preview_thumbnail() {
local -r thumbs_dir="$1"; shift
local -r backhref="$1"; shift
- local -r page_num="$1"; shift
+ local -r href_prefix="$1"; shift
local -r preview_num="$1"; shift
local -r photo_file="$1"; shift
local -r animation_class="$1"; shift
@@ -2808,10 +2817,10 @@ build_preview_thumbnail() {
anchor_class_html=$(_html_escape "$anchor_class")
printf '<a id=%s class=%s href=%s>\n' \
"'$photo_html'" "'$anchor_class_html'" \
- "'$page_num-$preview_num.html'"
+ "'${href_prefix}${preview_num}.html'"
else
printf '<a id=%s href=%s>\n' \
- "'$photo_html'" "'$page_num-$preview_num.html'"
+ "'$photo_html'" "'${href_prefix}${preview_num}.html'"
fi
printf " <img class='%s %s' alt='%s' src='%s/%s/%s'>\n</a>" \
"$img_class" "$anim_html" "$photo_html" "$backhref_html" \
@@ -4595,40 +4604,35 @@ declare -gr STATS_DIR='stats'
# the album root (dist/), used for shared assets and album links.
declare -gr STATS_FILTER_BACKHREF='../..'
-# Emit one thumbnail anchor for a filter gallery: a thumb image (from thumbs/)
-# linking to this filter's view page for that photo (<pagebase>--<index>.html).
-# The photo filename is HTML-escaped; the pagebase and index are filename-safe.
-_stats_filter_thumbnail() {
- local -r backhref_html="$1"; shift
- local -ri index="$1"; shift
- local -r photo="$1"; shift
- local photo_html
- local animation_class
-
- photo_html=$(_html_escape "$photo")
- # Same seeded animation the album thumbnail uses for this photo.
- animation_class=$(random_animation_css_class slow "$photo")
- # The view page sits in the same directory as this gallery, so link to it by
- # bare index; the thumbnail image lives at the album root via backhref.
- printf ' <a id="%s" href="%d.html">' "$photo_html" "$index"
- printf '<img class="thumb %s" alt="%s" src="%s/%s/%s"></a>\n' \
- "$animation_class" "$photo_html" "$backhref_html" "$STATS_THUMBS_DIR" "$photo_html"
-}
-
# Build the full thumbnail grid for one filter from its newline-separated photo
# list, preserving aggregation (encounter) order for deterministic output.
+#
+# This reuses the album's shared grid builder (append_preview_grid), so a filter
+# mini-album gallery gets EXACTLY the same tiles as the main overview: 2x2
+# feature tiles, subdivided tiles with sub-thumbnails, the seeded entry
+# animations and the dramatic hover. The only mini-album-specific detail is the
+# link target -- its view pages are bare "<index>.html" in the same directory --
+# so the href prefix is empty (the main album passes "<page_num>-"). The
+# thumbnail images come from the shared thumbs/ dir, reached via the gallery's
+# backhref (../..). The result is wrapped by camera.tmpl in the same
+# <div class="thumbs-grid"> container the main pages use.
_stats_build_filter_thumbs() {
local -r backhref_html="$1"; shift
local -r photos="$1"; shift
+ local -a photo_list=()
local photo
- local -i index=0
+ local thumbs=''
while IFS= read -r photo; do
- if [ -n "$photo" ]; then
- (( ++index ))
- _stats_filter_thumbnail "$backhref_html" "$index" "$photo"
- fi
+ [ -n "$photo" ] && photo_list+=("$photo")
done <<< "$photos"
+
+ if (( ${#photo_list[@]} == 0 )); then
+ return
+ fi
+ append_preview_grid thumbs \
+ "$STATS_THUMBS_DIR" "$backhref_html" '' "${photo_list[@]}"
+ printf '%s\n' "$thumbs"
}
# Render a filter gallery page (<pagebase>.html): header + camera.tmpl (heading +
diff --git a/share/templates/default/camera.tmpl b/share/templates/default/camera.tmpl
index 3b9d2f6..b1f6363 100644
--- a/share/templates/default/camera.tmpl
+++ b/share/templates/default/camera.tmpl
@@ -21,6 +21,8 @@ cat <<END
</div>
</div>
<div class="camera-thumbs">
+<div class="thumbs-grid">
${render_camera_thumbs_html}
</div>
+</div>
END
diff --git a/src/lib/album-render.source.sh b/src/lib/album-render.source.sh
index d97d05f..6770b86 100644
--- a/src/lib/album-render.source.sh
+++ b/src/lib/album-render.source.sh
@@ -115,8 +115,10 @@ render_full_preview_page() {
# also groups the page's photos into tiles (some subdivided into smaller
# thumbnails), so the per-page ordering and preview numbering stay here.
local preview_thumbs=''
+ # The main album's view pages are "<page_num>-<preview_num>.html", so the
+ # shared grid builder gets "<page_num>-" as the href prefix.
append_preview_grid preview_thumbs \
- "$thumbs_dir" "$backhref" "$page_num" "$@"
+ "$thumbs_dir" "$backhref" "$page_num-" "$@"
template previewpage "$page_name.html" \
html_dir "$html_dir" \
preview_thumbs "$preview_thumbs"
@@ -183,19 +185,22 @@ queue_preview_page_render_job() {
render_job_labels_ref["$!"]="template render job for preview $page_name"
}
-# Build a page's whole thumbnail-grid buffer by walking its photos and grouping
+# Build a whole thumbnail-grid buffer by walking a list of photos and grouping
# them into tiles. Most tiles are a single square thumbnail, but (controlled by
-# THUMB_SUBDIVIDE_PERCENT) some are subdivided into several smaller thumbnails
-# packed into the same square footprint. Each photo keeps its 1-based page
-# position as its preview number (subdivision only groups CONSECUTIVE photos
-# visually, never reorders them), so the view-page links stay correct. Tile
-# blocks are separated by a single newline; the previewpage template adds the
-# trailing newline, matching the old per-thumbnail rendering.
+# THUMB_FEATURE_PERCENT / THUMB_SUBDIVIDE_PERCENT) some become a 2x2 feature tile
+# or are subdivided into several smaller thumbnails. Each photo keeps its 1-based
+# position as its preview number (tiling only groups CONSECUTIVE photos visually,
+# never reorders them), so the view-page links stay correct. The view-page link
+# is "${href_prefix}${preview_num}.html": the main album passes "<page_num>-"; the
+# stats mini-albums pass "" (their view pages are bare "<index>.html"). This is
+# the single shared grid builder for both the main preview pages and the stats
+# mini-album galleries. Tile blocks are separated by a single newline; the
+# template adds the trailing newline.
append_preview_grid() {
local -n buffer_ref="$1"; shift
local -r thumbs_dir="$1"; shift
local -r backhref="$1"; shift
- local -r page_num="$1"; shift
+ local -r href_prefix="$1"; shift
local -a photos=("$@")
local -i i=0
local -i count
@@ -209,7 +214,7 @@ append_preview_grid() {
tile_layout_for "$(( ${#photos[@]} - i ))" "${photos[i]}"
)
block=$(build_tile_block \
- "$thumbs_dir" "$backhref" "$page_num" "$layout" "$(( i + 1 ))" \
+ "$thumbs_dir" "$backhref" "$href_prefix" "$layout" "$(( i + 1 ))" \
"${photos[@]:i:count}")
if [ -z "$buffer_ref" ]; then
buffer_ref="$block"
@@ -277,7 +282,7 @@ tile_layout_for() {
build_tile_block() {
local -r thumbs_dir="$1"; shift
local -r backhref="$1"; shift
- local -r page_num="$1"; shift
+ local -r href_prefix="$1"; shift
local -r layout="$1"; shift
local -ri start_preview="$1"; shift
local -a photos=("$@")
@@ -293,13 +298,13 @@ build_tile_block() {
anchor_class='feature'
fi
build_preview_thumbnail \
- "$thumbs_dir" "$backhref" "$page_num" "$start_preview" \
+ "$thumbs_dir" "$backhref" "$href_prefix" "$start_preview" \
"${photos[0]}" "$animation_class" thumb "$anchor_class"
return
;;
esac
build_subdivided_tile \
- "$thumbs_dir" "$backhref" "$page_num" "$layout" "$start_preview" \
+ "$thumbs_dir" "$backhref" "$href_prefix" "$layout" "$start_preview" \
"${photos[@]}"
}
@@ -315,7 +320,7 @@ build_tile_block() {
build_subdivided_tile() {
local -r thumbs_dir="$1"; shift
local -r backhref="$1"; shift
- local -r page_num="$1"; shift
+ local -r href_prefix="$1"; shift
local -r layout="$1"; shift
local -ri start_preview="$1"; shift
local -a photos=("$@")
@@ -334,7 +339,7 @@ build_subdivided_tile() {
for (( k = 0; k < ${#photos[@]}; k++ )); do
animation_class=$(random_animation_css_class slow "${photos[k]}")
build_preview_thumbnail \
- "$thumbs_dir" "$backhref" "$page_num" "$(( start_preview + k ))" \
+ "$thumbs_dir" "$backhref" "$href_prefix" "$(( start_preview + k ))" \
"${photos[k]}" "$animation_class" subthumb "${anchor_classes[k]:-}"
printf '\n'
done
@@ -343,15 +348,19 @@ build_subdivided_tile() {
# Render the HTML for a single preview thumbnail (HTML-escaping every value the
# way preview.tmpl's context_html fields did). Returned without a trailing
-# newline so callers control separators. img_class defaults to 'thumb' (the full
-# square); subdivided tiles pass 'subthumb'. anchor_class is an optional extra
-# class on the <a> ('wide' marks the full-width strip inside a subdivided tile);
-# when empty the <a> has no class attribute, keeping the single-tile output
-# byte-identical to before.
+# newline so callers control separators. The view-page link is
+# "${href_prefix}${preview_num}.html", so the main album passes "<page_num>-" and
+# the stats mini-albums (whose view pages are bare "<index>.html") pass "" -- the
+# only thing that differs between the two grids, keeping one shared builder.
+# img_class defaults to 'thumb' (the full square); subdivided tiles pass
+# 'subthumb'. anchor_class is an optional extra class on the <a> ('wide' marks the
+# full-width strip inside a subdivided tile, 'feature' a 2x2 hero tile); when empty
+# the <a> has no class attribute, keeping the single-tile output byte-identical to
+# before.
build_preview_thumbnail() {
local -r thumbs_dir="$1"; shift
local -r backhref="$1"; shift
- local -r page_num="$1"; shift
+ local -r href_prefix="$1"; shift
local -r preview_num="$1"; shift
local -r photo_file="$1"; shift
local -r animation_class="$1"; shift
@@ -371,10 +380,10 @@ build_preview_thumbnail() {
anchor_class_html=$(_html_escape "$anchor_class")
printf '<a id=%s class=%s href=%s>\n' \
"'$photo_html'" "'$anchor_class_html'" \
- "'$page_num-$preview_num.html'"
+ "'${href_prefix}${preview_num}.html'"
else
printf '<a id=%s href=%s>\n' \
- "'$photo_html'" "'$page_num-$preview_num.html'"
+ "'$photo_html'" "'${href_prefix}${preview_num}.html'"
fi
printf " <img class='%s %s' alt='%s' src='%s/%s/%s'>\n</a>" \
"$img_class" "$anim_html" "$photo_html" "$backhref_html" \
diff --git a/src/lib/stats-filter-album.source.sh b/src/lib/stats-filter-album.source.sh
index 49eb390..eedb474 100644
--- a/src/lib/stats-filter-album.source.sh
+++ b/src/lib/stats-filter-album.source.sh
@@ -38,40 +38,35 @@ declare -gr STATS_DIR='stats'
# the album root (dist/), used for shared assets and album links.
declare -gr STATS_FILTER_BACKHREF='../..'
-# Emit one thumbnail anchor for a filter gallery: a thumb image (from thumbs/)
-# linking to this filter's view page for that photo (<pagebase>--<index>.html).
-# The photo filename is HTML-escaped; the pagebase and index are filename-safe.
-_stats_filter_thumbnail() {
- local -r backhref_html="$1"; shift
- local -ri index="$1"; shift
- local -r photo="$1"; shift
- local photo_html
- local animation_class
-
- photo_html=$(_html_escape "$photo")
- # Same seeded animation the album thumbnail uses for this photo.
- animation_class=$(random_animation_css_class slow "$photo")
- # The view page sits in the same directory as this gallery, so link to it by
- # bare index; the thumbnail image lives at the album root via backhref.
- printf ' <a id="%s" href="%d.html">' "$photo_html" "$index"
- printf '<img class="thumb %s" alt="%s" src="%s/%s/%s"></a>\n' \
- "$animation_class" "$photo_html" "$backhref_html" "$STATS_THUMBS_DIR" "$photo_html"
-}
-
# Build the full thumbnail grid for one filter from its newline-separated photo
# list, preserving aggregation (encounter) order for deterministic output.
+#
+# This reuses the album's shared grid builder (append_preview_grid), so a filter
+# mini-album gallery gets EXACTLY the same tiles as the main overview: 2x2
+# feature tiles, subdivided tiles with sub-thumbnails, the seeded entry
+# animations and the dramatic hover. The only mini-album-specific detail is the
+# link target -- its view pages are bare "<index>.html" in the same directory --
+# so the href prefix is empty (the main album passes "<page_num>-"). The
+# thumbnail images come from the shared thumbs/ dir, reached via the gallery's
+# backhref (../..). The result is wrapped by camera.tmpl in the same
+# <div class="thumbs-grid"> container the main pages use.
_stats_build_filter_thumbs() {
local -r backhref_html="$1"; shift
local -r photos="$1"; shift
+ local -a photo_list=()
local photo
- local -i index=0
+ local thumbs=''
while IFS= read -r photo; do
- if [ -n "$photo" ]; then
- (( ++index ))
- _stats_filter_thumbnail "$backhref_html" "$index" "$photo"
- fi
+ [ -n "$photo" ] && photo_list+=("$photo")
done <<< "$photos"
+
+ if (( ${#photo_list[@]} == 0 )); then
+ return
+ fi
+ append_preview_grid thumbs \
+ "$STATS_THUMBS_DIR" "$backhref_html" '' "${photo_list[@]}"
+ printf '%s\n' "$thumbs"
}
# Render a filter gallery page (<pagebase>.html): header + camera.tmpl (heading +
diff --git a/tests/cli.sh b/tests/cli.sh
index cc8b925..006937a 100755
--- a/tests/cli.sh
+++ b/tests/cli.sh
@@ -3400,9 +3400,13 @@ test_generate_stats_pages_created_and_nav_linked() {
# The camera gallery is a mini album: thumbnails link to view pages in the
# same dir (<index>.html), and the thumb image points at the album root.
+ # The gallery reuses the main album's shared tile grid (append_preview_grid),
+ # so it is wrapped in the same thumbs-grid container and each photo's anchor
+ # links to its view page regardless of how photos group into tiles.
camera_html=$(<"$TEST_TMPDIR/dist/stats/camera-canon-eos-r5/index.html")
- test::assert_contains 'src="../../thumbs/' "$camera_html"
- test::assert_contains 'href="1.html"' "$camera_html"
+ test::assert_contains '<div class="thumbs-grid">' "$camera_html"
+ test::assert_contains "src='../../thumbs/" "$camera_html"
+ test::assert_contains "href='1.html'" "$camera_html"
# Non-camera stats are clickable mini-albums too: the ISO row links to a
# filter mini-album that exists and is itself a gallery of matching photos.
@@ -3410,7 +3414,7 @@ test_generate_stats_pages_created_and_nav_linked() {
"$(<"$TEST_TMPDIR/dist/stats/index.html")"
test::assert_file_exists "$TEST_TMPDIR/dist/stats/iso-400/index.html"
test::assert_file_exists "$TEST_TMPDIR/dist/stats/iso-400/1.html"
- test::assert_contains 'href="1.html"' \
+ test::assert_contains "href='1.html'" \
"$(<"$TEST_TMPDIR/dist/stats/iso-400/index.html")"
# A per-camera view page exists and its navigation stays within the filter:
@@ -4746,12 +4750,15 @@ BASH
# The Canon EOS 5D gallery lists its two photos as thumbnails linking to
# sibling view pages (<index>.html); the thumb image points at the album
- # root via ../../ .
+ # root via ../../ . The gallery reuses the main album's shared tile grid
+ # (append_preview_grid), so it is wrapped in the same thumbs-grid container
+ # and the per-photo anchors/hrefs/srcs are present regardless of how the
+ # photos are grouped into tiles (single, feature or subdivided).
html=$(cat "$s/camera-canon-eos-5d/index.html")
- test::assert_contains 'href="1.html"' "$html"
- test::assert_contains 'class="thumb ' "$html"
- test::assert_contains 'src="../../thumbs/a.jpg"></a>' "$html"
- test::assert_contains 'href="2.html"' "$html"
+ test::assert_contains '<div class="thumbs-grid">' "$html"
+ test::assert_contains "href='1.html'" "$html"
+ test::assert_contains "src='../../thumbs/a.jpg'>" "$html"
+ test::assert_contains "href='2.html'" "$html"
# Heading shows the (trusted) camera label and a back-to-stats link.
test::assert_contains 'Canon EOS 5D' "$html"
test::assert_contains '<a href="../../stats/index.html">Back to stats</a>' \
@@ -4770,7 +4777,7 @@ BASH
html=$(cat "$s/camera-nikon-co-z6/index.html")
test::assert_contains 'Nikon &amp; Co &lt;Z6&gt;' "$html"
test::assert_not_contains 'Nikon & Co <Z6>' "$html"
- test::assert_contains 'href="1.html"' "$html"
+ test::assert_contains "href='1.html'" "$html"
# Output is deterministic across runs despite parallel rendering.
html=$(cat "$dist_dir/run1/stats/camera-canon-eos-5d/index.html")