mirror of
https://github.com/anotherhadi/awesome-wallpapers.git
synced 2026-10-05 10:18:26 +02:00
Full rewrite
This commit is contained in:
Executable
+62
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
# Validate wallpaper filenames against the naming convention described in README.md:
|
||||
# wallpaper-name_tag1_tag2.png
|
||||
# - name: lowercase letters/digits, words separated by "-"
|
||||
# - tags: lowercase letters, words separated by "-", tags separated by "_"
|
||||
# - only .png and .gif are accepted
|
||||
# - gifs must carry the "animated" tag
|
||||
# - every gif must have a same-named .png counterpart
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
wallpapers_dir="wallpapers"
|
||||
name_re='^[a-z0-9]+(-[a-z0-9]+)*(_[a-z]+(-[a-z]+)*)*$'
|
||||
status=0
|
||||
|
||||
if [[ ! -d "$wallpapers_dir" ]]; then
|
||||
echo "No $wallpapers_dir directory found, skipping."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
shopt -s nullglob
|
||||
for file in "$wallpapers_dir"/*; do
|
||||
[[ -f "$file" ]] || continue
|
||||
filename=$(basename "$file")
|
||||
basename="${filename%.*}"
|
||||
ext="${filename##*.}"
|
||||
|
||||
if [[ "$ext" != "png" && "$ext" != "gif" ]]; then
|
||||
echo "❌ $filename: only .png and .gif files are accepted"
|
||||
status=1
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ ! "$basename" =~ $name_re ]]; then
|
||||
echo "❌ $filename: invalid name/tags, expected wallpaper-name_tag1_tag2 (lowercase, '-' separated words, '_' separated tags)"
|
||||
status=1
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "$ext" == "gif" ]]; then
|
||||
IFS='_' read -r -a parts <<<"$basename"
|
||||
has_animated=0
|
||||
for tag in "${parts[@]:1}"; do
|
||||
[[ "$tag" == "animated" ]] && has_animated=1
|
||||
done
|
||||
if [[ "$has_animated" -eq 0 ]]; then
|
||||
echo "❌ $filename: gif files must include the 'animated' tag"
|
||||
status=1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$wallpapers_dir/$basename.png" ]]; then
|
||||
echo "❌ $filename: missing matching static $basename.png"
|
||||
status=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$status" -eq 0 ]]; then
|
||||
echo "✅ All wallpaper filenames are valid."
|
||||
fi
|
||||
|
||||
exit "$status"
|
||||
Executable
+57
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env bash
|
||||
# Losslessly compress wallpapers before they are committed, so the repo
|
||||
# doesn't grow larger than it needs to. Only files staged in this commit
|
||||
# are touched, to keep the hook fast.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
wallpapers_dir="wallpapers"
|
||||
changed=0
|
||||
|
||||
if [[ ! -d "$wallpapers_dir" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! command -v oxipng >/dev/null 2>&1; then
|
||||
echo "❌ oxipng is required but was not found in PATH"
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v gifsicle >/dev/null 2>&1; then
|
||||
echo "❌ gifsicle is required but was not found in PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mapfile -t staged < <(git diff --cached --name-only --diff-filter=ACM -- "$wallpapers_dir")
|
||||
|
||||
for file in "${staged[@]}"; do
|
||||
[[ -f "$file" ]] || continue
|
||||
ext="${file##*.}"
|
||||
|
||||
before=$(stat -c%s "$file")
|
||||
|
||||
case "$ext" in
|
||||
png)
|
||||
oxipng -o max --strip safe -q "$file" >/dev/null
|
||||
;;
|
||||
gif)
|
||||
gifsicle -O3 --batch "$file"
|
||||
;;
|
||||
*)
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
|
||||
after=$(stat -c%s "$file")
|
||||
if [[ "$after" -ne "$before" ]]; then
|
||||
echo "Compressed $file ($before -> $after bytes)"
|
||||
git add "$file"
|
||||
changed=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$changed" -eq 1 ]]; then
|
||||
echo "Image(s) were compressed and re-staged, please commit again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# Every gif in wallpapers/ must have a same-named static .png counterpart
|
||||
# (see README.md). This hook generates the missing ones from the gif's
|
||||
# first frame and stages them, so a commit adding a gif automatically
|
||||
# gets its png alongside it.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
wallpapers_dir="wallpapers"
|
||||
changed=0
|
||||
|
||||
if [[ ! -d "$wallpapers_dir" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! command -v magick >/dev/null 2>&1; then
|
||||
echo "❌ imagemagick (magick) is required but was not found in PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
shopt -s nullglob
|
||||
for gif in "$wallpapers_dir"/*.gif; do
|
||||
basename="${gif%.gif}"
|
||||
png="$basename.png"
|
||||
|
||||
if [[ -f "$png" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "Generating $png from $(basename "$gif")"
|
||||
if ! magick "${gif}[0]" "$png"; then
|
||||
echo "❌ Failed to generate $png"
|
||||
exit 1
|
||||
fi
|
||||
git add "$png"
|
||||
changed=1
|
||||
done
|
||||
|
||||
if [[ "$changed" -eq 1 ]]; then
|
||||
echo "New static png(s) were generated and staged, please commit again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Executable
+218
@@ -0,0 +1,218 @@
|
||||
#!/usr/bin/env bash
|
||||
# Regenerate WALLPAPERS.md (and its 2/3-column variants, and tags/*.md)
|
||||
# from the contents of wallpapers/.
|
||||
# When a wallpaper has both a static png and an animated gif (same
|
||||
# basename), only one row is emitted, previewed with the gif.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
wallpapers_dir="wallpapers"
|
||||
tags_dir="tags"
|
||||
|
||||
if [[ ! -d "$wallpapers_dir" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Each entry: name<TAB>basename<TAB>preview<TAB>raw_tags(underscore-joined)
|
||||
build_entries() {
|
||||
shopt -s nullglob
|
||||
declare -A seen
|
||||
for file in "$wallpapers_dir"/*.png "$wallpapers_dir"/*.gif; do
|
||||
filename=$(basename "$file")
|
||||
base="${filename%.*}"
|
||||
|
||||
[[ -n "${seen[$base]:-}" ]] && continue
|
||||
seen[$base]=1
|
||||
|
||||
preview="$file"
|
||||
if [[ -f "$wallpapers_dir/$base.gif" ]]; then
|
||||
preview="$wallpapers_dir/$base.gif"
|
||||
fi
|
||||
|
||||
name="${base%%_*}"
|
||||
tags=""
|
||||
if [[ "$base" == *_* ]]; then
|
||||
tags="${base#*_}"
|
||||
fi
|
||||
|
||||
printf '%s\t%s\t%s\t%s\n' "$name" "$base" "$preview" "$tags"
|
||||
done | sort -t $'\t' -k1,1
|
||||
}
|
||||
|
||||
mapfile -t entries < <(build_entries)
|
||||
|
||||
# Collect the sorted, de-duplicated list of tags, and which entries have them.
|
||||
declare -A tag_seen
|
||||
all_tags=()
|
||||
for entry in "${entries[@]}"; do
|
||||
IFS=$'\t' read -r _ _ _ tags_raw <<<"$entry"
|
||||
[[ -z "$tags_raw" ]] && continue
|
||||
IFS='_' read -ra tokens <<<"$tags_raw"
|
||||
for t in "${tokens[@]}"; do
|
||||
if [[ -z "${tag_seen[$t]:-}" ]]; then
|
||||
tag_seen[$t]=1
|
||||
all_tags+=("$t")
|
||||
fi
|
||||
done
|
||||
done
|
||||
mapfile -t sorted_tags < <(printf '%s\n' "${all_tags[@]}" | sort)
|
||||
|
||||
entry_has_tag() {
|
||||
local tags_raw="$1" tag="$2" t
|
||||
IFS='_' read -ra tokens <<<"$tags_raw"
|
||||
for t in "${tokens[@]}"; do
|
||||
[[ "$t" == "$tag" ]] && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# tags_links <raw_tags> <tag-link-prefix>
|
||||
# Turns "foo_bar-baz" into "[foo](<prefix>foo.md), [bar-baz](<prefix>bar-baz.md)"
|
||||
tags_links() {
|
||||
local tags_raw="$1" tag_prefix="$2"
|
||||
[[ -z "$tags_raw" ]] && return
|
||||
local -a tokens
|
||||
IFS='_' read -ra tokens <<<"$tags_raw"
|
||||
local out="" t first=1
|
||||
for t in "${tokens[@]}"; do
|
||||
((first)) || out+=", "
|
||||
first=0
|
||||
out+="[${t}](${tag_prefix}${t}.md)"
|
||||
done
|
||||
printf '%s' "$out"
|
||||
}
|
||||
|
||||
# render_table <cols> <preview-prefix> <tag-link-prefix> <entries...>
|
||||
render_table() {
|
||||
local cols="$1" prefix="$2" tag_prefix="$3"
|
||||
shift 3
|
||||
local -a items=("$@")
|
||||
|
||||
local header="|" sep="|"
|
||||
local i
|
||||
for ((i = 0; i < cols; i++)); do
|
||||
header+=" Preview | Name | Tags |"
|
||||
sep+="---------|------|------|"
|
||||
done
|
||||
echo "$header"
|
||||
echo "$sep"
|
||||
|
||||
local total=${#items[@]}
|
||||
local idx=0
|
||||
while ((idx < total)); do
|
||||
local line="|"
|
||||
local c
|
||||
for ((c = 0; c < cols; c++)); do
|
||||
if ((idx < total)); then
|
||||
local name base preview tags_raw tags_display
|
||||
IFS=$'\t' read -r name base preview tags_raw <<<"${items[idx]}"
|
||||
tags_display="$(tags_links "$tags_raw" "$tag_prefix")"
|
||||
line+="  | ${name} | ${tags_display} |"
|
||||
((idx++))
|
||||
else
|
||||
line+=" | | |"
|
||||
fi
|
||||
done
|
||||
echo "$line"
|
||||
done
|
||||
}
|
||||
|
||||
# render_grid <cols> <preview-prefix> <tag-link-prefix> <entries...>
|
||||
# Like render_table, but each cell stacks the image with its name and
|
||||
# tags underneath instead of using separate Name/Tags columns.
|
||||
render_grid() {
|
||||
local cols="$1" prefix="$2" tag_prefix="$3"
|
||||
shift 3
|
||||
local -a items=("$@")
|
||||
|
||||
local header="|" sep="|"
|
||||
local i
|
||||
for ((i = 0; i < cols; i++)); do
|
||||
header+=" |"
|
||||
sep+=":---:|"
|
||||
done
|
||||
echo "$header"
|
||||
echo "$sep"
|
||||
|
||||
local total=${#items[@]}
|
||||
local idx=0
|
||||
while ((idx < total)); do
|
||||
local line="|"
|
||||
local c
|
||||
for ((c = 0; c < cols; c++)); do
|
||||
if ((idx < total)); then
|
||||
local name base preview tags_raw tags_display cell
|
||||
IFS=$'\t' read -r name base preview tags_raw <<<"${items[idx]}"
|
||||
tags_display="$(tags_links "$tags_raw" "$tag_prefix")"
|
||||
cell="<br>${name}"
|
||||
[[ -n "$tags_display" ]] && cell+="<br>${tags_display}"
|
||||
line+=" ${cell} |"
|
||||
((idx++))
|
||||
else
|
||||
line+=" |"
|
||||
fi
|
||||
done
|
||||
echo "$line"
|
||||
done
|
||||
}
|
||||
|
||||
nav_block() {
|
||||
echo "[1 Column](WALLPAPERS.md) · [2 Columns](WALLPAPERS-2COL.md) · [3 Columns](WALLPAPERS-3COL.md)"
|
||||
}
|
||||
|
||||
tags_block() {
|
||||
local prefix="$1"
|
||||
echo "<details>"
|
||||
echo "<summary>Tags</summary>"
|
||||
echo
|
||||
local t
|
||||
for t in "${sorted_tags[@]}"; do
|
||||
echo "- [${t}](${prefix}${tags_dir}/${t}.md)"
|
||||
done
|
||||
echo
|
||||
echo "</details>"
|
||||
}
|
||||
|
||||
generate_main() {
|
||||
local file="$1" cols="$2"
|
||||
{
|
||||
echo "# Wallpapers"
|
||||
echo
|
||||
nav_block
|
||||
echo
|
||||
tags_block ""
|
||||
echo
|
||||
if ((cols > 1)); then
|
||||
render_grid "$cols" "" "${tags_dir}/" "${entries[@]}"
|
||||
else
|
||||
render_table "$cols" "" "${tags_dir}/" "${entries[@]}"
|
||||
fi
|
||||
} >"$file"
|
||||
git add "$file"
|
||||
}
|
||||
|
||||
generate_main "WALLPAPERS.md" 1
|
||||
generate_main "WALLPAPERS-2COL.md" 2
|
||||
generate_main "WALLPAPERS-3COL.md" 3
|
||||
|
||||
rm -rf "$tags_dir"
|
||||
mkdir -p "$tags_dir"
|
||||
for t in "${sorted_tags[@]}"; do
|
||||
tag_items=()
|
||||
for entry in "${entries[@]}"; do
|
||||
IFS=$'\t' read -r _ _ _ tags_raw <<<"$entry"
|
||||
if entry_has_tag "$tags_raw" "$t"; then
|
||||
tag_items+=("$entry")
|
||||
fi
|
||||
done
|
||||
{
|
||||
echo "# Tag: ${t}"
|
||||
echo
|
||||
echo "[← All wallpapers](../WALLPAPERS.md)"
|
||||
echo
|
||||
render_table 1 "../" "" "${tag_items[@]}"
|
||||
} >"$tags_dir/$t.md"
|
||||
done
|
||||
git add "$tags_dir"
|
||||
|
||||
echo "Generated WALLPAPERS.md, WALLPAPERS-2COL.md, WALLPAPERS-3COL.md and $tags_dir/"
|
||||
@@ -1,65 +0,0 @@
|
||||
name: Check Wallpapers Format
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'app/static/wallpapers/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'app/static/wallpapers/**'
|
||||
|
||||
jobs:
|
||||
check-extensions:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Validate file format and naming conventions
|
||||
run: |
|
||||
# Loop through all wallpaper files
|
||||
cd "./app/static/wallpapers"
|
||||
for file in *; do
|
||||
if [[ -f "$file" ]]; then
|
||||
filename=$file
|
||||
basename=$(echo "$file" | cut -d. -f1)
|
||||
|
||||
# Check if .png, .jpg or .gif
|
||||
if [[ ! $filename =~ \.(png|jpg|gif)$ ]]; then
|
||||
echo "❌ Error: $file is not a PNG, JPG or GIF file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if only lowercase letters, - and _ are used
|
||||
echo "$basename" | grep -qE '^[a-z0-9][a-z0-9_-]*$' || {
|
||||
echo "❌ Error: $file contains invalid characters"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [[ $basename == *-_* ]]; then
|
||||
echo "❌ Error: $file contains a tag with a leading or trailing _"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $basename == *"_static"* ]]; then
|
||||
t=$(echo "$basename" | sed 's/_static/_animated/')
|
||||
if [ ! -f "${t}.gif" ] ; then
|
||||
echo "❌ Error: $file has a static tag but no gif file"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $basename == *"_animated"* ]]; then
|
||||
t=$(echo "$basename" | sed 's/_animated/_static/')
|
||||
if [ ! -f "${t}.png" ] && [ ! -f "${t}.jpg" ]; then
|
||||
echo "❌ Error: $file has a animated tag but no png or jpg file"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $filename == *.gif && $basename != *"_animated"* ]]; then
|
||||
echo "❌ Error: $file is a gif file but doesn't contain _static or _animated"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
@@ -1,49 +0,0 @@
|
||||
name: Create Wallpapers Markdown
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Check Wallpapers Format"]
|
||||
types:
|
||||
- completed
|
||||
permissions:
|
||||
contents: write
|
||||
jobs:
|
||||
generate-md:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }} # Only run if the first workflow was successful
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Create WALLPAPERS.md
|
||||
run: |
|
||||
# Set the output file
|
||||
OUTPUT_FILE="WALLPAPERS.md"
|
||||
|
||||
# Start the markdown file content
|
||||
echo "# Wallpapers" > $OUTPUT_FILE
|
||||
echo "" >> $OUTPUT_FILE
|
||||
|
||||
# Create a table with 2 columns for the wallpapers and their names
|
||||
echo "| Wallpaper | Name |" >> $OUTPUT_FILE
|
||||
echo "|-----------|------|" >> $OUTPUT_FILE
|
||||
|
||||
# Loop through the wallpapers directory
|
||||
for file in app/static/wallpapers/*.{png,jpg,gif}; do
|
||||
if [[ -f "$file" ]]; then
|
||||
# Get the filename without the path
|
||||
FILENAME=$(basename "$file")
|
||||
# Get the name of the wallpaper (without extension)
|
||||
NAME="${FILENAME%.*}"
|
||||
|
||||
# Create the markdown table entry for the wallpaper
|
||||
echo "|  | ${NAME} |" >> $OUTPUT_FILE
|
||||
fi
|
||||
done
|
||||
|
||||
# Commit the changes
|
||||
git config user.name github-actions
|
||||
git config user.email [email protected]
|
||||
git add $OUTPUT_FILE
|
||||
git commit -m "Generate WALLPAPERS.md" && git push
|
||||
exit 0
|
||||
Reference in New Issue
Block a user