1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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())
|