aboutsummaryrefslogtreecommitdiffstats
path: root/tools/image_budget.py
diff options
context:
space:
mode:
authorsillylaird <sillyfanboy@gmail.com>2026-09-03 00:33:59 +0000
committersillylaird <sillyfanboy@gmail.com>2026-09-03 00:33:59 +0000
commit898b52edcb47bcb3e9d6106e74ca73e74ea01e70 (patch)
tree85c6ee5ad58b860144551184d4cf86b560c62b91 /tools/image_budget.py
downloadwww-898b52edcb47bcb3e9d6106e74ca73e74ea01e70.tar.gz
www-898b52edcb47bcb3e9d6106e74ca73e74ea01e70.zip
import live www.sillylaird.ca webrootHEADmain
Diffstat (limited to '')
-rwxr-xr-xtools/image_budget.py72
1 files changed, 72 insertions, 0 deletions
diff --git a/tools/image_budget.py b/tools/image_budget.py
new file mode 100755
index 0000000..f8fc822
--- /dev/null
+++ b/tools/image_budget.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+"""Image size budget check.
+
+Flags images that exceed a per-file byte budget so heavy assets don't creep
+back in after an optimization pass. Offline and fast — safe for the default
+audit run.
+
+Budgets (override on the CLI):
+ raster (png/jpg/jpeg/webp) : 250 KB
+ gif : 600 KB (animations are bigger)
+
+Usage:
+ python tools/image_budget.py [--max-kb 250] [--gif-max-kb 600]
+"""
+
+from __future__ import annotations
+
+import argparse
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parents[1]
+# Include section asset dirs that hold page-local images (not only /assets/img).
+SCAN_DIRS = (
+ "assets/img",
+ "images",
+ "startpage",
+ "computers",
+ "gaming",
+ "vblog",
+ "mstartpage",
+)
+RASTER = {".png", ".jpg", ".jpeg", ".webp"}
+
+
+def main() -> int:
+ ap = argparse.ArgumentParser(description="Image size budget check")
+ ap.add_argument("--max-kb", type=int, default=250)
+ ap.add_argument("--gif-max-kb", type=int, default=600)
+ args = ap.parse_args()
+
+ over: list[tuple[int, str, int]] = [] # (size, path, budget)
+ for d in SCAN_DIRS:
+ base = ROOT / d
+ if not base.is_dir():
+ continue
+ for f in base.rglob("*"):
+ if not f.is_file():
+ continue
+ ext = f.suffix.lower()
+ if ext == ".gif":
+ budget = args.gif_max_kb * 1024
+ elif ext in RASTER:
+ budget = args.max_kb * 1024
+ else:
+ continue
+ sz = f.stat().st_size
+ if sz > budget:
+ over.append((sz, f.relative_to(ROOT).as_posix(), budget))
+
+ if over:
+ print("Images over budget:")
+ for sz, path, budget in sorted(over, reverse=True):
+ print(f"- {path}: {sz/1024:.0f} KB (budget {budget//1024} KB)")
+ print("\nTip: run ./tools/optimize_images.sh")
+ return 1
+
+ print("OK: all images within budget")
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())