imgstat 2.0.5 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,32 +3,17 @@
3
3
  [![npm version](https://img.shields.io/npm/v/imgstat.svg)](https://www.npmjs.com/package/imgstat)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
- **Give AI context about your images.**
7
- imgstat is a CLI tool that embeds image dimensions directly into filenames, or analyzes remote imagery, to give AI context without needing external parsers.
6
+ give AI context about your images.
8
7
 
9
- ## Installation
8
+ imgstat scans your project and generates image dimension reports your AI coding assistant
9
+ can actually read — without guessing, without vision tokens, without touching your source files.
10
10
 
11
- You can install the package globally:
11
+ ## install
12
12
 
13
13
  ```bash
14
14
  npm install -g imgstat
15
15
  ```
16
16
 
17
- Or run it directly without installing:
18
-
19
- ```bash
20
- npx imgstat
21
- ```
22
-
23
- ## Features
24
-
25
- imgstat handles renaming smoothly and idempotently—it will never re-append dimensions to a file that already has them. When dealing with remote imagery from URLs or scanning your codebase, it securely generates dimension reports without leaving permanent downloads on your machine. For AI integration, the `analyze` mode seamlessly builds an `.agent/rules/image_dimensions.md` file, giving your local language models instant, zero-config context about the images used in your project.
26
-
27
- ## Usage
28
-
29
- Run `imgstat` with no arguments to get an interactive menu. You will be prompted to select the mode you want to use.
30
-
31
- ```bash
32
17
  imgstat
33
18
  ```
34
19
 
package/bin/imgstat CHANGED
@@ -21,6 +21,7 @@ MODE=""
21
21
  TARGET=""
22
22
  DRY_RUN="false"
23
23
  YES_FLAG="false"
24
+ FORMAT=""
24
25
 
25
26
  # Simple parser
26
27
  while [[ $# -gt 0 ]]; do
@@ -50,14 +51,24 @@ while [[ $# -gt 0 ]]; do
50
51
  echo " inspect Print dimensions of local directory images"
51
52
  echo " rename Rename local files (e.g. image-800x600.jpg)"
52
53
  echo " remote Print dimensions of images from a URL"
53
- echo " analyze Scan codebase for URLs, write to .agent/rules/image_dimensions.md"
54
+ echo " analyze Scan codebase for URLs, write dimension report for your IDE"
54
55
  echo ""
55
56
  echo "Options:"
57
+ echo " --format Set output format (e.g. --format json)"
56
58
  echo " --dry-run Show what would happen without making changes"
57
59
  echo " --yes, -y Skip confirmation prompts (for rename)"
58
60
  echo " --help, -h Show this help message"
59
61
  exit 0
60
62
  ;;
63
+ --format)
64
+ shift
65
+ FORMAT="$1"
66
+ if [[ "$FORMAT" != "json" ]]; then
67
+ echo "Error: unsupported format '$FORMAT'. Only 'json' is supported."
68
+ exit 1
69
+ fi
70
+ shift
71
+ ;;
61
72
  -*)
62
73
  echo "Unknown flag: $1"
63
74
  exit 1
@@ -109,6 +120,6 @@ case "$MODE" in
109
120
  ;;
110
121
  analyze)
111
122
  source "$LIB_DIR/analyze.sh"
112
- cmd_analyze "$TARGET"
123
+ cmd_analyze "$TARGET" "1" "$FORMAT"
113
124
  ;;
114
125
  esac
package/lib/analyze.sh CHANGED
@@ -4,6 +4,8 @@ source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/utils.sh"
4
4
 
5
5
  cmd_analyze() {
6
6
  local dir="$1"
7
+ local target_option="${2:-1}"
8
+ local json_format="$3"
7
9
  echo "Analyzing codebase for remote image references in $dir..."
8
10
 
9
11
  # ── Step 1: Extract all http/https URLs from common code files ──────────────
@@ -13,7 +15,7 @@ cmd_analyze() {
13
15
  -type f \( -name "*.html" -o -name "*.jsx" -o -name "*.tsx" -o -name "*.js" -o -name "*.ts" \
14
16
  -o -name "*.vue" -o -name "*.css" -o -name "*.scss" -o -name "*.php" \
15
17
  -o -name "*.py" -o -name "*.rb" -o -name "*.svelte" -o -name "*.astro" \) \
16
- -exec grep -oE "https?://[^\"')[:space:]]+" {} + 2>/dev/null | sort -u)
18
+ -exec grep -hoE "https?://[^\"')[:space:]]+" {} + 2>/dev/null | sort -u)
17
19
 
18
20
  if [[ ${#all_urls[@]} -eq 0 ]]; then
19
21
  echo "No remote URLs found in code files."
@@ -84,22 +86,8 @@ cmd_analyze() {
84
86
  trap 'rm -rf "$TEMP_DIR"' EXIT
85
87
 
86
88
  # Output file setup
87
- local rules_dir="$dir/.agent/rules"
88
- local rules_file="$rules_dir/image_dimensions.md"
89
- mkdir -p "$rules_dir"
90
-
91
- # Write header
92
- cat << 'EOF' > "$rules_file"
93
- # Codebase Remote Images
94
-
95
- > [!NOTE]
96
- > This file is strictly auto-generated by `imgstat`.
97
- > It maps remote image URLs found in the codebase to their exact physical dimensions.
98
- > AI assistants should use this dictionary when asked about layout constraints, native sizes, or aspect ratios of referenced images.
99
-
100
- | Documented URL | Detected Size (W x H) |
101
- |---|---|
102
- EOF
89
+ local TEMP_RESULTS=$(mktemp)
90
+ trap 'rm -rf "$TEMP_DIR" "$TEMP_RESULTS"' EXIT
103
91
 
104
92
  local processed=0
105
93
 
@@ -109,7 +97,9 @@ EOF
109
97
  --user-agent="Mozilla/5.0" \
110
98
  -P "$TEMP_DIR" "$url" 2>/dev/null || true
111
99
 
100
+ shopt -s nullglob
112
101
  local all_files=( "$TEMP_DIR"/* )
102
+ shopt -u nullglob
113
103
  local found_image=""
114
104
 
115
105
  for file in "${all_files[@]}"; do
@@ -128,7 +118,7 @@ EOF
128
118
  if [[ -n "$dim" ]]; then
129
119
  local w="${dim% *}"
130
120
  local h="${dim#* }"
131
- echo "| \`$url\` | **${w}x${h}** |" >> "$rules_file"
121
+ echo "${url}|${w}|${h}" >> "$TEMP_RESULTS"
132
122
  printf " \033[1;32m📐 %s → %sx%s\033[0m\n" "$url" "$w" "$h"
133
123
  processed=$((processed + 1))
134
124
  fi
@@ -140,6 +130,47 @@ EOF
140
130
 
141
131
  echo ""
142
132
  echo "Analysis complete!"
143
- echo "Documented $processed valid image reference(s) into: $rules_file"
133
+
134
+ if [[ $processed -eq 0 ]]; then
135
+ echo "No matching images with dimension info could be parsed."
136
+ return 0
137
+ fi
138
+
139
+ # Depending on Target Option, write file.
140
+ if [[ "$json_format" == "json" ]]; then
141
+ # if it's format json without target, only output json
142
+ if [[ -z "$2" ]]; then
143
+ bash "$(dirname "${BASH_SOURCE[0]}")/format-json.sh" "$dir" "$TEMP_RESULTS" "0"
144
+ return 0
145
+ else
146
+ bash "$(dirname "${BASH_SOURCE[0]}")/format-json.sh" "$dir" "$TEMP_RESULTS" "1"
147
+ fi
148
+ fi
149
+
150
+ case "$target_option" in
151
+ 1)
152
+ bash "$(dirname "${BASH_SOURCE[0]}")/write-agent.sh" "$dir" "$TEMP_RESULTS"
153
+ ;;
154
+ 2)
155
+ bash "$(dirname "${BASH_SOURCE[0]}")/write-cursor.sh" "$dir" "$TEMP_RESULTS"
156
+ ;;
157
+ 3)
158
+ bash "$(dirname "${BASH_SOURCE[0]}")/write-windsurf.sh" "$dir" "$TEMP_RESULTS"
159
+ ;;
160
+ 4)
161
+ bash "$(dirname "${BASH_SOURCE[0]}")/write-claude.sh" "$dir" "$TEMP_RESULTS"
162
+ ;;
163
+ 5)
164
+ bash "$(dirname "${BASH_SOURCE[0]}")/write-agent.sh" "$dir" "$TEMP_RESULTS"
165
+ bash "$(dirname "${BASH_SOURCE[0]}")/write-cursor.sh" "$dir" "$TEMP_RESULTS"
166
+ bash "$(dirname "${BASH_SOURCE[0]}")/write-windsurf.sh" "$dir" "$TEMP_RESULTS"
167
+ bash "$(dirname "${BASH_SOURCE[0]}")/write-claude.sh" "$dir" "$TEMP_RESULTS"
168
+ ;;
169
+ *)
170
+ # default
171
+ bash "$(dirname "${BASH_SOURCE[0]}")/write-agent.sh" "$dir" "$TEMP_RESULTS"
172
+ ;;
173
+ esac
174
+
144
175
  echo "This file can now be read by autonomous coding agents."
145
176
  }
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Inputs
4
+ # $1: Directory path
5
+ # $2: Temp file containing results in format: url|width|height
6
+ # $3: Optional. Target flag meaning we must write to file instead of stdout.
7
+
8
+ DIR="$1"
9
+ RESULTS_FILE="$2"
10
+ HAS_TARGET="$3"
11
+
12
+ JSON_FILE=""
13
+ if [[ "$HAS_TARGET" == "1" ]]; then
14
+ JSON_FILE="$DIR/image_dimensions.json"
15
+ fi
16
+
17
+ NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
18
+
19
+ TEMP_JSON=$(mktemp)
20
+
21
+ echo "{" > "$TEMP_JSON"
22
+ echo " \"generated_at\": \"$NOW\"," >> "$TEMP_JSON"
23
+ echo " \"images\": [" >> "$TEMP_JSON"
24
+
25
+ FIRST_ITEM=true
26
+
27
+ while IFS='|' read -r url w h; do
28
+ if [ "$FIRST_ITEM" = "true" ]; then
29
+ FIRST_ITEM=false
30
+ else
31
+ echo " ," >> "$TEMP_JSON"
32
+ fi
33
+ # We escape the URL safely
34
+ # Assuming url doesn't have quotes for now, but good practice
35
+ SAFE_URL=$(echo -n "$url" | sed 's/"/\\"/g')
36
+ echo -n " { \"path\": \"$SAFE_URL\", \"width\": $w, \"height\": $h }" >> "$TEMP_JSON"
37
+ done < "$RESULTS_FILE"
38
+
39
+ echo "" >> "$TEMP_JSON"
40
+ echo " ]" >> "$TEMP_JSON"
41
+ echo "}" >> "$TEMP_JSON"
42
+
43
+ if [[ -n "$JSON_FILE" ]]; then
44
+ mv "$TEMP_JSON" "$JSON_FILE"
45
+ echo "Wrote JSON dimension report to: $JSON_FILE"
46
+ else
47
+ cat "$TEMP_JSON"
48
+ rm -f "$TEMP_JSON"
49
+ fi
package/lib/ui.sh CHANGED
@@ -74,7 +74,24 @@ cmd_ui() {
74
74
  3)
75
75
  read -e -p "Enter codebase directory to analyze [./]: " dir
76
76
  dir="${dir:-./}"
77
- cmd_analyze "$dir"
77
+ echo ""
78
+ echo "where should the report go?"
79
+ echo ""
80
+ echo " 1. .agent/rules/image_dimensions.md (generic / all tools)"
81
+ echo " 2. .cursor/rules/image_dimensions.mdc (cursor)"
82
+ echo " 3. .windsurfrules (windsurf — appends block)"
83
+ echo " 4. CLAUDE.md (claude code — appends block)"
84
+ echo " 5. all of the above"
85
+ echo ""
86
+ read -e -p "Enter choice [1]: " target_env
87
+ target_env="${target_env:-1}"
88
+
89
+ if [[ ! "$target_env" =~ ^[1-5]$ ]]; then
90
+ echo "Invalid choice. Defaulting to 1."
91
+ target_env=1
92
+ fi
93
+
94
+ cmd_analyze "$dir" "$target_env" ""
78
95
  ;;
79
96
  4)
80
97
  echo "Exiting."
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Inputs
4
+ # $1: Directory path
5
+ # $2: Temp file containing results in format: url|width|height
6
+
7
+ DIR="$1"
8
+ RESULTS_FILE="$2"
9
+
10
+ RULES_DIR="$DIR/.agent/rules"
11
+ RULES_FILE="$RULES_DIR/image_dimensions.md"
12
+
13
+ mkdir -p "$RULES_DIR"
14
+
15
+ cat << 'EOF' > "$RULES_FILE"
16
+ # Codebase Remote Images
17
+
18
+ > [!NOTE]
19
+ > This file is strictly auto-generated by `imgstat`.
20
+ > It maps remote image URLs found in the codebase to their exact physical dimensions.
21
+ > AI assistants should use this dictionary when asked about layout constraints, native sizes, or aspect ratios of referenced images.
22
+
23
+ | Documented URL | Detected Size (W x H) |
24
+ |---|---|
25
+ EOF
26
+
27
+ while IFS='|' read -r url w h; do
28
+ echo "| \`$url\` | **${w}x${h}** |" >> "$RULES_FILE"
29
+ done < "$RESULTS_FILE"
30
+
31
+ echo "Wrote generic rules to: $RULES_FILE"
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Inputs
4
+ # $1: Directory path
5
+ # $2: Temp file containing results in format: url|width|height
6
+
7
+ DIR="$1"
8
+ RESULTS_FILE="$2"
9
+ RULES_FILE="$DIR/CLAUDE.md"
10
+
11
+ TEMP_BLOCK=$(mktemp)
12
+
13
+ cat << 'EOF' > "$TEMP_BLOCK"
14
+ ## image dimensions
15
+
16
+ generated by imgstat. run `npx imgstat` to regenerate.
17
+
18
+ never guess image sizes. use the table below.
19
+
20
+ | file | width | height |
21
+ |------|-------|--------|
22
+ EOF
23
+
24
+ while IFS='|' read -r url w h; do
25
+ echo "| $url | $w | $h |" >> "$TEMP_BLOCK"
26
+ done < "$RESULTS_FILE"
27
+
28
+ # Appending / Replacing logic
29
+ if [[ -f "$RULES_FILE" ]] && grep -q "## image dimensions" "$RULES_FILE"; then
30
+ # Block exists. Let's delete it.
31
+ sed -i.bak '/## image dimensions/,$d' "$RULES_FILE"
32
+ rm -f "${RULES_FILE}.bak"
33
+ fi
34
+
35
+ if [[ -f "$RULES_FILE" ]]; then
36
+ echo "" >> "$RULES_FILE"
37
+ fi
38
+
39
+ cat "$TEMP_BLOCK" >> "$RULES_FILE"
40
+ rm -f "$TEMP_BLOCK"
41
+
42
+ echo "Wrote claude code rules to: $RULES_FILE"
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Inputs
4
+ # $1: Directory path
5
+ # $2: Temp file containing results in format: url|width|height
6
+
7
+ DIR="$1"
8
+ RESULTS_FILE="$2"
9
+
10
+ RULES_DIR="$DIR/.cursor/rules"
11
+ RULES_FILE="$RULES_DIR/image_dimensions.mdc"
12
+
13
+ mkdir -p "$RULES_DIR"
14
+
15
+ cat << 'EOF' > "$RULES_FILE"
16
+ ---
17
+ description: image dimension context for all assets in this project
18
+ alwaysApply: true
19
+ ---
20
+
21
+ when working with images in this project, always refer to this file.
22
+ never guess dimensions. never use vision tokens to infer size.
23
+
24
+ | file | width | height |
25
+ |------|-------|--------|
26
+ EOF
27
+
28
+ while IFS='|' read -r url w h; do
29
+ echo "| $url | $w | $h |" >> "$RULES_FILE"
30
+ done < "$RESULTS_FILE"
31
+
32
+ echo "Wrote cursor rules to: $RULES_FILE"
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Inputs
4
+ # $1: Directory path
5
+ # $2: Temp file containing results in format: url|width|height
6
+
7
+ DIR="$1"
8
+ RESULTS_FILE="$2"
9
+ RULES_FILE="$DIR/.windsurfrules"
10
+
11
+ TEMP_BLOCK=$(mktemp)
12
+
13
+ cat << 'EOF' > "$TEMP_BLOCK"
14
+ # imgstat — image dimensions
15
+ # generated by imgstat. do not edit this block manually.
16
+ # run `npx imgstat` to regenerate.
17
+
18
+ when working with images, never guess dimensions. refer to the table below.
19
+
20
+ | file | width | height |
21
+ |------|-------|--------|
22
+ EOF
23
+
24
+ while IFS='|' read -r url w h; do
25
+ echo "| $url | $w | $h |" >> "$TEMP_BLOCK"
26
+ done < "$RESULTS_FILE"
27
+
28
+ # Appending / Replacing logic
29
+ if [[ -f "$RULES_FILE" ]] && grep -q "# imgstat — image dimensions" "$RULES_FILE"; then
30
+ # Block exists, let's remove it and everything after it (assuming block is at the bottom)
31
+ # Actually, safer to sed replace everything from the start tag until the end of file.
32
+ # But the instructions say "append a clearly delimited block at the bottom".
33
+ # If it exists, replace only that block.
34
+ # Let's assume the block starts at "# imgstat — image dimensions" and continues to EOF.
35
+ sed -i.bak '/# imgstat — image dimensions/,$d' "$RULES_FILE"
36
+ rm -f "${RULES_FILE}.bak"
37
+ fi
38
+
39
+ if [[ -f "$RULES_FILE" ]]; then
40
+ # Ensure there's a newline before appending
41
+ echo "" >> "$RULES_FILE"
42
+ fi
43
+
44
+ cat "$TEMP_BLOCK" >> "$RULES_FILE"
45
+ rm -f "$TEMP_BLOCK"
46
+
47
+ echo "Wrote windsurf rules to: $RULES_FILE"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imgstat",
3
- "version": "2.0.5",
3
+ "version": "3.0.0",
4
4
  "description": "Embeds image dimensions directly into filenames for natural AI context.",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
package/build_deb.sh DELETED
@@ -1,48 +0,0 @@
1
- #!/bin/bash
2
- PACKAGE_NAME="imagestat"
3
- VERSION="1.0"
4
- ARCH="all"
5
- DEB_DIR="${PACKAGE_NAME}_${VERSION}_${ARCH}"
6
-
7
- echo "Building .deb package for $PACKAGE_NAME..."
8
-
9
- # Create directory structure
10
- mkdir -p "$DEB_DIR/usr/local/bin"
11
- mkdir -p "$DEB_DIR/DEBIAN"
12
-
13
- # Determine source file (handle rename)
14
- if [ -f "imagestat" ]; then
15
- cp imagestat "$DEB_DIR/usr/local/bin/$PACKAGE_NAME"
16
- elif [ -f "imgstat.sh" ]; then
17
- cp imgstat.sh "$DEB_DIR/usr/local/bin/$PACKAGE_NAME"
18
- else
19
- echo "Error: Source script not found (looked for 'imagestat' and 'imgstat.sh')."
20
- exit 1
21
- fi
22
-
23
- chmod 755 "$DEB_DIR/usr/local/bin/$PACKAGE_NAME"
24
-
25
- # Create control file
26
- cat > "$DEB_DIR/DEBIAN/control" <<EOF
27
- Package: $PACKAGE_NAME
28
- Version: $VERSION
29
- Section: utils
30
- Priority: optional
31
- Architecture: $ARCH
32
- Allowed-Architectures: all
33
- Maintainer: User <user@example.com>
34
- Depends: imagemagick, wget
35
- Description: Image dimensions scanner and renamer
36
- Recursively scans directories for images and renames them to include their
37
- dimensions (e.g., image-800x600.jpg). Ignores heavy directories like node_modules.
38
- EOF
39
-
40
- # Build package
41
- dpkg-deb --build "$DEB_DIR"
42
-
43
- # Cleanup
44
- mv "${DEB_DIR}.deb" "${PACKAGE_NAME}.deb" 2>/dev/null || true
45
- rm -rf "$DEB_DIR"
46
-
47
- echo "Build complete: ${PACKAGE_NAME}.deb"
48
- echo "Install with: sudo apt install ./$PACKAGE_NAME.deb"
package/imagestat DELETED
@@ -1,124 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Function to display usage
4
- usage() {
5
- echo "Usage: imagestat [-u|--url <url>] [directory]"
6
- echo " -u, --url <url> URL to download images from"
7
- echo " directory Directory to scan (default: current directory)"
8
- exit 1
9
- }
10
-
11
- # Parse arguments
12
- URL=""
13
- TARGET_DIR="."
14
-
15
- while [[ "$#" -gt 0 ]]; do
16
- case $1 in
17
- -u|--url) URL="$2"; shift ;;
18
- -*) echo "Unknown parameter passed: $1"; usage ;;
19
- *) TARGET_DIR="$1" ;;
20
- esac
21
- shift
22
- done
23
-
24
- # Create target directory if it doesn't exist
25
- if [ ! -d "$TARGET_DIR" ]; then
26
- mkdir -p "$TARGET_DIR"
27
- fi
28
-
29
- # Download images if URL is provided
30
- # Download images if URL is provided
31
- if [ -n "$URL" ]; then
32
- echo "Downloading images from $URL to temp folder..."
33
- TEMP_DIR=$(mktemp -d)
34
-
35
- # Download with wget (no extension restriction to catch all images)
36
- # -nd: no directories (flatten)
37
- # -r: recursive (useful if URL is a directory, but works for single file too)
38
- # -l 1: limit recursion depth to 1 just in case (optional, but safer)
39
- # --no-parent: don't go up
40
- wget -nd -H -P "$TEMP_DIR" -e robots=off --user-agent="Mozilla/5.0" "$URL" 2>/dev/null
41
-
42
- echo "Processing downloaded files..."
43
- shopt -s nullglob
44
- for f in "$TEMP_DIR"/*; do
45
- if [ -f "$f" ]; then
46
- # Identify format and dimensions (take first frame for animated gifs etc)
47
- # Use -ping to be faster? identification doesn't need full read usually
48
- ID_OUTPUT=$(identify -format "%m %w %h" "$f[0]" 2>/dev/null)
49
-
50
- if [ -n "$ID_OUTPUT" ]; then
51
- read -r TYPE W H <<< "$ID_OUTPUT"
52
-
53
- # Normalize extension
54
- EXT=$(echo "$TYPE" | tr '[:upper:]' '[:lower:]')
55
- case "$EXT" in
56
- jpeg) EXT="jpg" ;;
57
- esac
58
-
59
- # Get clean basename (remove query params)
60
- BASENAME=$(basename "$f")
61
- CLEAN_NAME=$(echo "$BASENAME" | sed 's/[?=&].*//')
62
- # Remove existing extension if it matches common ones
63
- CLEAN_NAME="${CLEAN_NAME%.*}"
64
-
65
- # Construct new filename
66
- NEW_FILENAME="${CLEAN_NAME}-${W}x${H}.${EXT}"
67
- NEW_PATH="$TARGET_DIR/$NEW_FILENAME"
68
-
69
- # Move to target
70
- mv -n "$f" "$NEW_PATH"
71
- echo "Saved: $NEW_FILENAME ($W x $H)"
72
- fi
73
- fi
74
- done
75
- rm -rf "$TEMP_DIR"
76
- echo "Download processing complete."
77
- fi
78
-
79
- # Export function so xargs can use it
80
- process_image() {
81
- IMG="$1"
82
-
83
- # Get dimensions
84
- DIMENSIONS=$(identify -format "%wx%h" "$IMG" 2>/dev/null)
85
-
86
- if [ -z "$DIMENSIONS" ]; then
87
- echo "Skipping (not an image or identify failed): $IMG"
88
- return
89
- fi
90
-
91
- DIRNAME=$(dirname "$IMG")
92
- BASENAME=$(basename "$IMG")
93
- EXTENSION="${BASENAME##*.}"
94
- FILENAME="${BASENAME%.*}"
95
-
96
- # Normalize filename: lowercase, replace spaces/underscores with hyphens
97
- NEW_FILENAME=$(echo "$FILENAME" | tr '[:upper:]' '[:lower:]' | sed 's/[ _]/-/g' | sed 's/-\{2,\}/-/g')
98
-
99
- # Check if dimensions are already in the filename
100
- if [[ "$NEW_FILENAME" != *"$DIMENSIONS"* ]]; then
101
- NEW_FILENAME="${NEW_FILENAME}-${DIMENSIONS}"
102
- fi
103
-
104
- NEW_BASENAME="${NEW_FILENAME}.${EXTENSION}"
105
- NEW_PATH="$DIRNAME/$NEW_BASENAME"
106
-
107
- if [ "$IMG" != "$NEW_PATH" ]; then
108
- mv "$IMG" "$NEW_PATH"
109
- echo "Renamed: $IMG -> $NEW_PATH"
110
- else
111
- echo "No change: $IMG"
112
- fi
113
- }
114
-
115
- export -f process_image
116
-
117
- # Find and process images
118
- echo "Scanning for images in $TARGET_DIR..."
119
- # Prune standard ignored directories
120
- find "$TARGET_DIR" \
121
- \( -type d -name ".git" -o -name "node_modules" -o -name "dist" -o -name "build" -o -name "vendor" -o -name ".next" -o -name "coverage" \) -prune \
122
- -o -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.gif" -o -iname "*.webp" -o -iname "*.svg" \) -print0 | xargs -0 -P 4 -I {} bash -c 'process_image "$@"' _ {}
123
-
124
- echo "Done."
package/install.sh DELETED
@@ -1,68 +0,0 @@
1
- #!/bin/bash
2
-
3
- APP_NAME="imagestat"
4
- INSTALL_DIR="/usr/local/bin"
5
- TARGET_PATH="$INSTALL_DIR/$APP_NAME"
6
- SOURCE_FILE=""
7
-
8
- # Colors
9
- GREEN='\033[0;32m'
10
- RED='\033[0;31m'
11
- YELLOW='\033[1;33m'
12
- NC='\033[0m' # No Color
13
-
14
- echo -e "${GREEN}Installing $APP_NAME...${NC}"
15
-
16
- # Check sudo
17
- if [ "$EUID" -ne 0 ]; then
18
- echo -e "${YELLOW}Please run as root (sudo) to install globally.${NC}"
19
- echo "Try: sudo ./install.sh"
20
- exit 1
21
- fi
22
-
23
- # Locate source file
24
- if [ -f "imagestat" ]; then
25
- SOURCE_FILE="imagestat"
26
- elif [ -f "imgstat.sh" ]; then
27
- SOURCE_FILE="imgstat.sh"
28
- else
29
- echo "Local script not found. Downloading from GitHub..."
30
- REMOTE_URL="https://raw.githubusercontent.com/isaac0yen/imgstat/main/imagestat"
31
- if command -v curl &> /dev/null; then
32
- curl -fsSL "$REMOTE_URL" -o imagestat
33
- elif command -v wget &> /dev/null; then
34
- wget -q "$REMOTE_URL" -O imagestat
35
- else
36
- echo -e "${RED}Error: Neither curl nor wget found. Cannot download script.${NC}"
37
- exit 1
38
- fi
39
-
40
- if [ ! -f "imagestat" ]; then
41
- echo -e "${RED}Error: Failed to download script.${NC}"
42
- exit 1
43
- fi
44
- SOURCE_FILE="imagestat"
45
- fi
46
-
47
- # Check dependencies
48
- MISSING_DEPS=0
49
- if ! command -v identify &> /dev/null; then
50
- echo -e "${RED}Error: 'identify' (ImageMagick) is not installed.${NC}"
51
- MISSING_DEPS=1
52
- fi
53
- if ! command -v wget &> /dev/null; then
54
- echo -e "${RED}Error: 'wget' is not installed.${NC}"
55
- MISSING_DEPS=1
56
- fi
57
-
58
- if [ $MISSING_DEPS -eq 1 ]; then
59
- echo -e "${YELLOW}Please install missing dependencies first.${NC}"
60
- exit 1
61
- fi
62
-
63
- echo "Installing $SOURCE_FILE to $TARGET_PATH..."
64
- cp "$SOURCE_FILE" "$TARGET_PATH"
65
- chmod +x "$TARGET_PATH"
66
-
67
- echo -e "${GREEN}Success! $APP_NAME has been installed.${NC}"
68
- echo -e "Usage: ${GREEN}$APP_NAME [-u|--url <url>] [directory]${NC}"