diff --git a/bin/check-site-rot.py b/bin/check-site-rot.py index 0adcef7..cf53eff 100755 --- a/bin/check-site-rot.py +++ b/bin/check-site-rot.py @@ -227,7 +227,14 @@ def resolve(path): homelinks = {m for m in re.findall(r'href="/([a-z0-9-]+)/"', texts[""])} for p in sorted(homelinks - page_set): bad("home: links /%s/ which is not a page" % p) - for p in sorted(page_set - homelinks): + # The home page links a few guides and /guides/, which lists every guide: a page linked from /guides/ counts as linked from home. + reachable = set(homelinks) + if "guides" in page_set: + if "guides" in homelinks: + reachable |= {m for m in re.findall(r'href="/([a-z0-9-]+)/"', texts.get("guides", ""))} + else: + bad("home: does not link /guides/ (the page that lists every guide)") + for p in sorted(page_set - reachable): bad("home: does not link /%s/ (the Guides list or another section should)" % p) for line in problems: diff --git a/bin/test-check-site-rot.sh b/bin/test-check-site-rot.sh index 75cb2bb..8c8fbac 100755 --- a/bin/test-check-site-rot.sh +++ b/bin/test-check-site-rot.sh @@ -83,9 +83,69 @@ import sys p, slug = sys.argv[1:3] s = open(p).read().replace('href="/%s/"' % slug, 'href="/"') open(p, "w").write(s) +# a site with a /guides/ page lists every guide there: take the page off that list too +import os +g = os.path.join(os.path.dirname(p), "guides", "index.html") +if os.path.isfile(g): + gs = open(g).read() + open(g, "w").write(gs.replace('href="/%s/"' % slug, 'href="/"')) EOF expect_fail "a page the home page no longer links" "home: does not link" +# /guides/ lists the guides. Built in the throwaway copy, so these cases run on every site, with or without a real /guides/. +# The home page links /guides/ and not $first; /guides/ links $first. +with_guides() { + fresh + python3 - "$site" "$first" "$second" <<'EOF' +import os, re, sys +site, first, second = sys.argv[1:4] +real = os.path.join(site, "guides") +if os.path.isfile(os.path.join(real, "index.html")): + # a real /guides/ page: keep it, and make sure it lists $first + src = open(os.path.join(real, "index.html")).read() +else: + src = open(os.path.join(site, second, "index.html")).read() + src = re.sub(r".*?", "Guides", src, count=1, flags=re.S) + src = src.replace("/%s/" % second, "/guides/") + os.makedirs(real, exist_ok=True) +if 'href="/%s/"' % first not in src: + src = src.replace("", '

listed guide

' % first, 1) +open(os.path.join(real, "index.html"), "w").write(src) +home = os.path.join(site, "index.html") +h = open(home).read().replace('href="/%s/"' % first, 'href="/"') +if 'href="/guides/"' not in h: + h = h.replace("", '

All guides

', 1) +open(home, "w").write(h) +sm = os.path.join(site, "sitemap.xml") +m = open(sm).read() +if "/guides/" not in m: + open(sm, "w").write(m.replace("", "https://fosterstack.com/guides/", 1)) +ll = os.path.join(site, "llms.txt") +l = open(ll).read() +if "fosterstack.com/guides/)" not in l: + open(ll, "w").write(l.rstrip("\n") + "\n- [Guides](https://fosterstack.com/guides/): all guides\n") +EOF +} + +with_guides; expect_pass "a page linked only from /guides/ counts as linked from home" + +with_guides; python3 - "$site/guides/index.html" "$first" <<'EOF' +import sys +p, slug = sys.argv[1:3] +s = open(p).read() +open(p, "w").write(s.replace('href="/%s/"' % slug, 'href="/"')) +EOF +expect_fail "a page on neither the home page nor /guides/" "home: does not link /$first/" + +with_guides; python3 - "$site/index.html" <<'EOF' +import sys +p = sys.argv[1] +s = open(p).read() +open(p, "w").write(s.replace('href="/guides/"', 'href="/"')) +EOF +expect_fail "a home page that does not link /guides/" "home: does not link /guides/" +expect_fail "a /guides/ page the home page does not link lists nothing for home" "home: does not link /$first/" + fresh; edit "$site/$first/index.html" "REGEX:.*?" "This title is deliberately far too long to be a good page title for a search result" expect_fail "a title over 60 characters" "characters (max 60)"