Files
rezayaghobi.ir/tools/check_site.py
rezayaghobi-dev 12e72d0418
All checks were successful
site / test (push) Successful in 26s
site / build (push) Successful in 11s
ci: add site pipeline
2026-10-20 17:57:04 +03:30

60 lines
1.9 KiB
Python

#!/usr/bin/env python3
import re
import sys
from html.parser import HTMLParser
from pathlib import Path
from urllib.parse import urlparse
ROOT = Path(__file__).resolve().parent.parent
INDEX = ROOT / "index.html"
SKIP = ("#", "mailto:", "tel:", "data:", "javascript:")
FETCH_RELS = {"stylesheet", "icon", "preload", "modulepreload", "manifest", "apple-touch-icon"}
errors = []
def check(ref, base, where, fetched):
if not ref or ref.startswith(SKIP):
return
if ref.startswith(("http://", "https://", "//")):
if fetched:
errors.append(f"{where}: external request {ref}")
return
path = urlparse(ref).path
target = ROOT / path.lstrip("/") if path.startswith("/") else base.parent / path
if not target.exists():
errors.append(f"{where}: missing file {ref}")
class Page(HTMLParser):
def handle_starttag(self, tag, attrs):
a = dict(attrs)
refs = []
if tag in ("script", "img", "source", "iframe", "video", "audio"):
refs.append(a.get("src"))
for part in (a.get("srcset") or "").split(","):
if part.strip():
refs.append(part.split()[0])
elif tag == "link" and FETCH_RELS & set((a.get("rel") or "").split()):
refs.append(a.get("href"))
for ref in refs:
check(ref, INDEX, "index.html", True)
if tag == "a":
check(a.get("href"), INDEX, "index.html", False)
for name in ("index.html", "favicon.svg", "robots.txt"):
if not (ROOT / name).is_file():
errors.append(f"missing required file: {name}")
if INDEX.is_file():
Page().feed(INDEX.read_text(encoding="utf-8"))
for css in ROOT.glob("assets/*.css"):
for ref in re.findall(r"url\(\s*['\"]?([^'\")]+)", css.read_text(encoding="utf-8")):
check(ref, css, str(css.relative_to(ROOT)), True)
if errors:
print("\n".join(errors))
sys.exit(1)
print("site check passed")