| Age | Commit message (Collapse) | Author |
|
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>
|
|
_stats_render_category dispatched on render_kind via a four-arm case
(camera|ranked|ordered|month), a modification magnet inconsistent with
the codebase's other data-driven dispatch (the STATS_RECORD_FUNCTIONS
registry and template.source.sh's prepare_template_render_var__<kind>
declare -F lookup).
Resolve the per-kind renderer by name instead: dispatch to
_stats_render_section__<render_kind> via `declare -F`, guarded so a
missing handler fails loudly (and so set -euo pipefail's errexit does
not trip on declare -F's non-zero "absent" status). Rename the three
section renderers to the _stats_render_section__{ranked,ordered,month}
convention.
Fold the camera kind into ranked: the camera leaderboard differed from
an ordinary ranked section only by the extra 'stats-leaderboard' <ul>
class -- data, not logic -- so it becomes a 'ranked' entry carrying that
class in a new optional 5th spec field (list_class), eliminating the
camera special case. Stats body output is byte-identical before/after
for every render kind (verified via snapshot diff); the existing stats
tests stay green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
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>
|
|
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>
|
|
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>
|
|
Adding an EXIF stats category previously required editing four places: the
reset function, a new _stats_record_*, the body builder, and a new
_stats_render_* section. Introduce a STATS_CATEGORIES registry (the single
source of truth) and make the generic code iterate it instead.
- STATS_CATEGORIES: ordered, pipe-delimited specs
(count_array|prefix|heading|render_kind), declared -gra so it survives a
function-scoped source. The array order IS the overview display order.
- STATS_CATEGORY_BUCKETS: tab-delimited bucket ladders for the 'ordered'
histogram kinds (apertures wide->narrow, etc.).
- STATS_RECORD_FUNCTIONS: the per-photo recorder dispatch list.
Collapsed touch-points:
- reset_photo_exif_stats clears each registry count array via
_stats_category_arrays.
- accumulate_photo_stats dispatches recorders from STATS_RECORD_FUNCTIONS.
- _stats_build_body iterates STATS_CATEGORIES, dispatching each spec through
_stats_render_category (camera/ranked/ordered/month kinds).
- _stats_render_ordered_section reads its ladder from STATS_CATEGORY_BUCKETS;
the camera leaderboard is now ranked + a 'stats-leaderboard' list_class.
Adding a category is now: append one STATS_CATEGORIES entry (plus a
STATS_CATEGORY_BUCKETS row for an ordered ladder) and have a record function
tally into its array. No edits to reset, the body builder, or a per-category
render branch.
Behaviour-preserving: category order, bucket order, headings, counts and
links are unchanged. Verified byte-identical by diffing the stats/ output of
the pre-change binary against the new one over the same fixture album.
Added test_stats_categories_registry_is_single_source_of_truth (registered in
main()) asserting reset, the body builder and the bucket ladders all derive
from the registry; it fails if a category is added in only one place.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
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>
|