ci: add site pipeline
This commit is contained in:
59
tools/check_site.py
Normal file
59
tools/check_site.py
Normal file
@@ -0,0 +1,59 @@
|
||||
#!/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")
|
||||
Reference in New Issue
Block a user