diff options
| author | Paul Buetow <paul@buetow.org> | 2026-06-11 10:43:19 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-06-11 10:43:19 +0300 |
| commit | 1e7b394e56085a9cc33b8b8b64b094d5223e8853 (patch) | |
| tree | d716db2d332904bb66f34572ec066d19170cd9cc | |
| parent | cbd3cf2be4ce50092ec4eb3f4b28d77c0aa044e4 (diff) | |
Add shuriken logo and generated favicon
| -rw-r--r-- | Justfile | 2 | ||||
| -rw-r--r-- | README.md | 12 | ||||
| -rw-r--r-- | assets/docs/shuriken-logo.jpg | bin | 0 -> 50976 bytes | |||
| -rw-r--r-- | assets/docs/shuriken-logo.svg | 18 | ||||
| -rw-r--r-- | assets/site/favicon.ico | bin | 0 -> 123870 bytes | |||
| -rwxr-xr-x | bin/photoalbum | 43 | ||||
| -rw-r--r-- | share/templates/default/header.tmpl | 1 | ||||
| -rw-r--r-- | share/templates/default/redirect.tmpl | 1 | ||||
| -rw-r--r-- | share/templates/default/splash.tmpl | 1 | ||||
| -rw-r--r-- | src/lib/album.source.sh | 22 | ||||
| -rw-r--r-- | src/lib/bootstrap.source.sh | 18 | ||||
| -rwxr-xr-x | src/photoalbum.sh | 3 | ||||
| -rwxr-xr-x | tests/cli.sh | 12 |
13 files changed, 129 insertions, 4 deletions
@@ -140,6 +140,8 @@ install: check-generated build install -d "{{DESTDIR}}{{DATADIR}}/{{NAME}}" rm -rf "{{DESTDIR}}{{DATADIR}}/{{NAME}}/templates" cp -R ./share/templates "{{DESTDIR}}{{DATADIR}}/{{NAME}}/" + rm -rf "{{DESTDIR}}{{DATADIR}}/{{NAME}}/assets" + cp -R ./assets/site "{{DESTDIR}}{{DATADIR}}/{{NAME}}/assets" install -d "{{DESTDIR}}{{SYSCONFDIR}}" install -m 0644 \ ./src/photoalbum.default.conf \ @@ -1,5 +1,7 @@ # photoalbum + + photoalbum is a minimal Bash script for Unix like operating systems (such as Linux) to generate static web photo albums. The resulting static photo album is pure HTML+CSS (without any JavaScript!). @@ -20,10 +22,10 @@ changing either file, and use `just check-generated` to verify that the tracked script has not drifted. `just test` and `just install` run that drift check before rebuilding so stale committed output is not hidden. -`just install` installs `photoalbum` to `/usr/bin`, templates to -`/usr/share/photoalbum/templates`, and the default config to -`/etc/default/photoalbum`. Override paths with `DESTDIR`, `PREFIX`, `BINDIR`, -`DATADIR`, or `SYSCONFDIR` when packaging or staging an install: +`just install` installs `photoalbum` to `/usr/bin`, templates and static assets +to `/usr/share/photoalbum`, and the default config to `/etc/default/photoalbum`. +Override paths with `DESTDIR`, `PREFIX`, `BINDIR`, `DATADIR`, or `SYSCONFDIR` +when packaging or staging an install: ``` DESTDIR="$PWD/pkg" PREFIX=/usr just install @@ -106,6 +108,8 @@ Successful generation writes `photoalbum.json` into the output directory. This metadata records the generator version and timestamp, config source, template directory, supported source image and generated file counts, tarball status, and effective settings useful for debugging a published album. +Generation also writes `favicon.ico` into the output directory and the default +templates link to it. Normal generation preserves reusable generated artifacts from the previous `DIST_DIR` while still rerendering HTML, random splash/background choices, diff --git a/assets/docs/shuriken-logo.jpg b/assets/docs/shuriken-logo.jpg Binary files differnew file mode 100644 index 0000000..fc7216c --- /dev/null +++ b/assets/docs/shuriken-logo.jpg diff --git a/assets/docs/shuriken-logo.svg b/assets/docs/shuriken-logo.svg new file mode 100644 index 0000000..58ed8ab --- /dev/null +++ b/assets/docs/shuriken-logo.svg @@ -0,0 +1,18 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" role="img" aria-labelledby="title desc"> + <title id="title">Shuriken logo</title> + <desc id="desc">A four-point shuriken mark with a red center ring.</desc> + <rect width="256" height="256" rx="36" fill="#f4f0e8"/> + <circle cx="128" cy="128" r="108" fill="#18212b"/> + <path + d="M128 18 153 94 231 65 190 128 231 191 153 162 128 238 103 162 25 191 66 128 25 65 103 94Z" + fill="#dce5eb" + stroke="#0b1118" + stroke-linejoin="round" + stroke-width="10"/> + <path + d="M128 43 146 101 204 82 171 128 204 174 146 155 128 213 110 155 52 174 85 128 52 82 110 101Z" + fill="#7f8e99"/> + <circle cx="128" cy="128" r="39" fill="#18212b"/> + <circle cx="128" cy="128" r="24" fill="none" stroke="#c7432b" stroke-width="10"/> + <circle cx="128" cy="128" r="8" fill="#f4f0e8"/> +</svg> diff --git a/assets/site/favicon.ico b/assets/site/favicon.ico Binary files differnew file mode 100644 index 0000000..754a880 --- /dev/null +++ b/assets/site/favicon.ico diff --git a/bin/photoalbum b/bin/photoalbum index 33f369a..065793f 100755 --- a/bin/photoalbum +++ b/bin/photoalbum @@ -7,8 +7,11 @@ set -euo pipefail declare -r VERSION='0.7.0' declare -r DEFAULTRC="${PHOTOALBUM_DEFAULT_RC:-/etc/default/photoalbum}" declare -r PACKAGED_TEMPLATE_DIR='/usr/share/photoalbum/templates/default' +declare -r PACKAGED_ASSET_DIR='/usr/share/photoalbum/assets' DEFAULT_TEMPLATE_DIR="${PHOTOALBUM_DEFAULT_TEMPLATE_DIR:-$PACKAGED_TEMPLATE_DIR}" declare -r DEFAULT_TEMPLATE_DIR +DEFAULT_ASSET_DIR="${PHOTOALBUM_DEFAULT_ASSET_DIR:-$PACKAGED_ASSET_DIR}" +declare -r DEFAULT_ASSET_DIR PHOTOALBUM_OUTPUT_MODE="${PHOTOALBUM_OUTPUT_MODE:-normal}" PHOTOALBUM_ACTIVE_GENERATION_PID='' PHOTOALBUM_FORCE_GENERATE="${PHOTOALBUM_FORCE_GENERATE:-no}" @@ -221,6 +224,24 @@ resolve_default_template_dir() { printf '%s\n' "$DEFAULT_TEMPLATE_DIR" } +resolve_default_asset_dir() { + local source_root + + if [ -d "$DEFAULT_ASSET_DIR" ]; then + printf '%s\n' "$DEFAULT_ASSET_DIR" + return + fi + + source_root=$(resolve_source_root) + + if [ -n "$source_root" ]; then + printf '%s\n' "$source_root/assets/site" + return + fi + + printf '%s\n' "$DEFAULT_ASSET_DIR" +} + template_dir_uses_default() { if [ -z "${TEMPLATE_DIR+x}" ] || [ -z "$TEMPLATE_DIR" ]; then return 1 @@ -2188,6 +2209,26 @@ prepare_generation_photo_assets() { create_all_photo_derivatives 'photos' 'thumbs' 'blurs' } +copy_site_favicon() { + local asset_dir + local favicon_src + + asset_dir=$(resolve_default_asset_dir) + favicon_src="$asset_dir/favicon.ico" + + if [ ! -r "$favicon_src" ]; then + config_error "favicon file $favicon_src must be readable" + return 1 + fi + + log_verbose "Copying favicon to $(_display_path "$DIST_DIR/favicon.ico")" + cp "$favicon_src" "$DIST_DIR/favicon.ico" +} + +prepare_generation_site_assets() { + copy_site_favicon +} + clear_rendered_html() { find "$DIST_DIR" -type f -name '*.html' -delete } @@ -2213,6 +2254,7 @@ generate() { fi prepare_generation_photo_assets + prepare_generation_site_assets clear_rendered_html render_album_pages 'photos' '.' 'thumbs' 'blurs' '.' "$tarball_name" create_generation_archive "$tarball_name" @@ -2286,6 +2328,7 @@ dry_run() { printf ' %s/index.html (%s album index redirect)\n' \ "$DIST_DIR" "$html_index_count" fi + printf ' %s/favicon.ico\n' "$DIST_DIR" printf ' %s/photoalbum.json\n' "$DIST_DIR" printf ' %s/photos/* (%s image files)\n' "$DIST_DIR" "$image_count" printf ' %s/thumbs/* (%s image files)\n' "$DIST_DIR" "$image_count" diff --git a/share/templates/default/header.tmpl b/share/templates/default/header.tmpl index 7f30a77..953109a 100644 --- a/share/templates/default/header.tmpl +++ b/share/templates/default/header.tmpl @@ -2,6 +2,7 @@ cat <<END <html> <head> <title>${render_title_html}</title> + <link rel="icon" href="${render_backhref_html}/favicon.ico" type="image/x-icon"> <style type="text/css"> body { background-color: #000000; diff --git a/share/templates/default/redirect.tmpl b/share/templates/default/redirect.tmpl index 866aa38..b7119aa 100644 --- a/share/templates/default/redirect.tmpl +++ b/share/templates/default/redirect.tmpl @@ -1,6 +1,7 @@ cat <<END <html> <head> + <link rel="icon" href="./favicon.ico" type="image/x-icon"> <meta http-equiv='refresh' content='0; url=${render_redirect_page_html}.html'> </head> <body> diff --git a/share/templates/default/splash.tmpl b/share/templates/default/splash.tmpl index ce3483d..5363978 100644 --- a/share/templates/default/splash.tmpl +++ b/share/templates/default/splash.tmpl @@ -2,6 +2,7 @@ cat <<END <html> <head> <title>${render_title_html}</title> + <link rel="icon" href="${render_backhref_html}/favicon.ico" type="image/x-icon"> <style type="text/css"> body { background-color: #000000; diff --git a/src/lib/album.source.sh b/src/lib/album.source.sh index 760201a..0f67396 100644 --- a/src/lib/album.source.sh +++ b/src/lib/album.source.sh @@ -890,6 +890,26 @@ prepare_generation_photo_assets() { create_all_photo_derivatives 'photos' 'thumbs' 'blurs' } +copy_site_favicon() { + local asset_dir + local favicon_src + + asset_dir=$(resolve_default_asset_dir) + favicon_src="$asset_dir/favicon.ico" + + if [ ! -r "$favicon_src" ]; then + config_error "favicon file $favicon_src must be readable" + return 1 + fi + + log_verbose "Copying favicon to $(_display_path "$DIST_DIR/favicon.ico")" + cp "$favicon_src" "$DIST_DIR/favicon.ico" +} + +prepare_generation_site_assets() { + copy_site_favicon +} + clear_rendered_html() { find "$DIST_DIR" -type f -name '*.html' -delete } @@ -915,6 +935,7 @@ generate() { fi prepare_generation_photo_assets + prepare_generation_site_assets clear_rendered_html render_album_pages 'photos' '.' 'thumbs' 'blurs' '.' "$tarball_name" create_generation_archive "$tarball_name" @@ -988,6 +1009,7 @@ dry_run() { printf ' %s/index.html (%s album index redirect)\n' \ "$DIST_DIR" "$html_index_count" fi + printf ' %s/favicon.ico\n' "$DIST_DIR" printf ' %s/photoalbum.json\n' "$DIST_DIR" printf ' %s/photos/* (%s image files)\n' "$DIST_DIR" "$image_count" printf ' %s/thumbs/* (%s image files)\n' "$DIST_DIR" "$image_count" diff --git a/src/lib/bootstrap.source.sh b/src/lib/bootstrap.source.sh index bb309f9..3e514fc 100644 --- a/src/lib/bootstrap.source.sh +++ b/src/lib/bootstrap.source.sh @@ -109,6 +109,24 @@ resolve_default_template_dir() { printf '%s\n' "$DEFAULT_TEMPLATE_DIR" } +resolve_default_asset_dir() { + local source_root + + if [ -d "$DEFAULT_ASSET_DIR" ]; then + printf '%s\n' "$DEFAULT_ASSET_DIR" + return + fi + + source_root=$(resolve_source_root) + + if [ -n "$source_root" ]; then + printf '%s\n' "$source_root/assets/site" + return + fi + + printf '%s\n' "$DEFAULT_ASSET_DIR" +} + template_dir_uses_default() { if [ -z "${TEMPLATE_DIR+x}" ] || [ -z "$TEMPLATE_DIR" ]; then return 1 diff --git a/src/photoalbum.sh b/src/photoalbum.sh index 45ace17..b0d3cee 100755 --- a/src/photoalbum.sh +++ b/src/photoalbum.sh @@ -7,8 +7,11 @@ set -euo pipefail declare -r VERSION='PHOTOALBUMVERSION' declare -r DEFAULTRC="${PHOTOALBUM_DEFAULT_RC:-/etc/default/photoalbum}" declare -r PACKAGED_TEMPLATE_DIR='/usr/share/photoalbum/templates/default' +declare -r PACKAGED_ASSET_DIR='/usr/share/photoalbum/assets' DEFAULT_TEMPLATE_DIR="${PHOTOALBUM_DEFAULT_TEMPLATE_DIR:-$PACKAGED_TEMPLATE_DIR}" declare -r DEFAULT_TEMPLATE_DIR +DEFAULT_ASSET_DIR="${PHOTOALBUM_DEFAULT_ASSET_DIR:-$PACKAGED_ASSET_DIR}" +declare -r DEFAULT_ASSET_DIR PHOTOALBUM_OUTPUT_MODE="${PHOTOALBUM_OUTPUT_MODE:-normal}" PHOTOALBUM_ACTIVE_GENERATION_PID='' PHOTOALBUM_FORCE_GENERATE="${PHOTOALBUM_FORCE_GENERATE:-no}" diff --git a/tests/cli.sh b/tests/cli.sh index 53acecf..2a71dba 100755 --- a/tests/cli.sh +++ b/tests/cli.sh @@ -239,6 +239,7 @@ test_just_install_and_deinstall_with_destdir() { test::assert_file_exists "$stage_dir/etc/default/photoalbum" test::assert_file_exists \ "$stage_dir/usr/share/photoalbum/templates/default/view.tmpl" + test::assert_file_exists "$stage_dir/usr/share/photoalbum/assets/favicon.ico" ( cd "$TEST_REPO_ROOT" @@ -1657,6 +1658,7 @@ test_dry_run_reports_cli_overrides_without_writes() { test::assert_contains \ " $dist_dir/index.html (1 album index redirect)" \ "$output" + test::assert_contains " $dist_dir/favicon.ico" "$output" test::assert_contains " $dist_dir/photoalbum.json" "$output" test::assert_contains " $dist_dir/photos/* (6 image files)" "$output" test::assert_contains " $dist_dir/thumbs/* (6 image files)" "$output" @@ -2131,6 +2133,7 @@ test_integration_generates_album_outputs_and_cleans() { test::assert_file_exists "$TEST_TMPDIR/dist/3-2.html" test::assert_file_exists "$TEST_TMPDIR/dist/3-2-details.html" test::assert_file_exists "$TEST_TMPDIR/dist/index.html" + test::assert_file_exists "$TEST_TMPDIR/dist/favicon.ico" test::assert_file_exists "$TEST_TMPDIR/dist/photoalbum.json" test::assert_no_html_subdir_output "$TEST_TMPDIR/dist" @@ -2161,6 +2164,12 @@ test_integration_generates_album_outputs_and_cleans() { test::assert_not_contains 'class="details-photo-link" href="1-2.html"' \ "$details_html" test::assert_contains '<title>Integration album</title>' "$top_index_html" + test::assert_contains \ + '<link rel="icon" href="./favicon.ico" type="image/x-icon">' \ + "$top_index_html" + test::assert_contains \ + '<link rel="icon" href="./favicon.ico" type="image/x-icon">' \ + "$page_html" test::assert_contains 'Enter album' "$top_index_html" test::assert_contains 'href="page-1.html"' "$top_index_html" test::assert_contains \ @@ -2335,6 +2344,9 @@ test_generate_config_no_splash_keeps_index_redirect() { top_index_html=$(<"$TEST_TMPDIR/dist/index.html") test::assert_contains 'url=page-1.html' "$top_index_html" + test::assert_contains \ + '<link rel="icon" href="./favicon.ico" type="image/x-icon">' \ + "$top_index_html" test::assert_not_contains 'Enter album' "$top_index_html" test::assert_not_contains '<script' "$top_index_html" test::assert_not_contains 'javascript:' "$top_index_html" |
