#!/usr/bin/env python3
"""Check that every image referenced by the docs actually exists.
Broken image links are easy to introduce (moving an assets/ folder, deleting a
file without touching the pages that use it) and hard to notice, because the
published site keeps serving stale copies that were uploaded by earlier builds.
This script catches them at CI time instead.
Only real media references are checked: markdown ````, HTML
`` ``, and ````/````/```` ``src``/``poster``.
Markdown cells of Jupyter notebooks (``.ipynb``, used by the MaixPy3 docs) are
checked too. Fenced and inline code is stripped first, so example commands
like ``convert in.jpg out.jpg`` are not mistaken for links.
Usage:
python3 tools/check_image_links.py # fail on anything not in the baseline
python3 tools/check_image_links.py --list # print every broken link
python3 tools/check_image_links.py --update-baseline
"""
import argparse
import json
import os
import re
import sys
import urllib.parse
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
BASELINE = os.path.join(ROOT, "tools", "known_broken_images.txt")
SCAN_DIRS = ["docs", "news", "pages", "layout"]
SKIP_DIRS = {".git", "out", ".venv", "node_modules", "__pycache__"}
PAGE_EXTS = {".md", ".html", ".ipynb"}
IMG_EXTS = {".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".bmp", ".ico",
".mp4", ".webm", ".mov", ".mp3", ".ogg", ".wav"}
FENCED = re.compile(r"```.*?```|~~~.*?~~~", re.S)
# HTML 注释里的引用不会渲染,不算断链
HTML_COMMENT = re.compile(r"", re.S)
INLINE_CODE = re.compile(r"`[^`\n]*`")
MD_IMG = re.compile(r"!\[[^\]]*\]\(\s*([^)\s>]+)")
HTML_IMG = re.compile(r" ]*?\bsrc\s*=\s*[\"']([^\"']+)", re.I)
MEDIA_TAG = re.compile(r"<(?:video|source|audio)\b[^>]*>", re.I)
MEDIA_ATTR = re.compile(r"(? {ref}")
print("\nFix the path, add the missing image, or remove the reference.")
return 1
return 0
if __name__ == "__main__":
sys.exit(main())