#!/usr/bin/env python3 """ fix_page_links.py Run this from the root of a wget-mirrored site (e.g. exhibits-library-jhu-edu/). Problem it fixes: wget's --convert-links + --adjust-extension combo sometimes fails to rewrite links to extensionless pages, even though the actual file was saved locally as page.html. This leaves some internal navigation links pointing at a URL that doesn't exist locally (e.g. href="/exhibits/show/some-exhibit/some-page" instead of href="/exhibits/show/some-exhibit/some-page.html"), causing 404s when browsing the mirror locally. What it does: 1. Walks the whole mirror and indexes every real .html file as a URL path (with the .html stripped), e.g. a file at ./exhibits/show/foo/bar.html becomes "/exhibits/show/foo/bar". 2. Walks every .html file again, and for any href="/exhibits/show/..." link that exactly matches one of those indexed paths (i.e. the link is missing ".html" but a matching page does exist), rewrites it to append ".html". 3. Leaves alone any link that doesn't match a known local page, so it won't touch genuinely out-of-scope or external links. Usage: cd exhibits-library-jhu-edu python3 fix_page_links.py """ import os import re root = "." # Step 1: Build the set of all real local pages (as URL paths, without .html) pages = set() for dirpath, _, files in os.walk(root): for fn in files: if fn.endswith(".html"): full = os.path.relpath(os.path.join(dirpath, fn), root).replace(os.sep, "/") pages.add("/" + full[:-5]) # strip trailing ".html" print(f"Indexed {len(pages)} local pages") # Step 2: Rewrite any href="/exhibits/show/..." link that's missing .html # but matches a page we actually have. link_re = re.compile(r'href="(/exhibits/show/[^"?#]+)"') fixed_count = 0 for dirpath, _, files in os.walk(root): for fn in files: if fn.endswith(".html"): full = os.path.join(dirpath, fn) with open(full, "r", errors="ignore") as f: content = f.read() changed = [False] # mutable container so repl() can update it without `nonlocal` def repl(m, changed=changed): path = m.group(1) if path in pages: changed[0] = True return f'href="{path}.html"' return m.group(0) new_content = link_re.sub(repl, content) if changed[0]: with open(full, "w") as f: f.write(new_content) fixed_count += 1 print(f"Fixed links in {fixed_count} file(s)")