diff --git a/mkdocs.yml b/mkdocs.yml index fdda977..e04cfd3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -87,6 +87,11 @@ plugins: # Built-in, offline search — the index is a JSON file in the build output. - search +hooks: + # Rewrites directory-style links (e.g. [incidents/](incidents/)) to the + # landing pages the build generates for them. Publishing-layer logic only. + - publishing/hooks.py + markdown_extensions: - admonition - attr_list diff --git a/publishing/build.sh b/publishing/build.sh index d577b66..1c91831 100755 --- a/publishing/build.sh +++ b/publishing/build.sh @@ -34,6 +34,7 @@ tar cf - \ --exclude='.site-build' \ --exclude='.venv-docs' \ --exclude='*.sh' \ + --exclude='*.py' \ --exclude='publishing/webhook-receiver.py' \ --exclude='publishing/webhook-receiver.service' \ --exclude='mkdocs.yml' \ diff --git a/publishing/hooks.py b/publishing/hooks.py new file mode 100644 index 0000000..b453b6f --- /dev/null +++ b/publishing/hooks.py @@ -0,0 +1,38 @@ +"""MkDocs hook: make directory-style links work on a static site. + +The documents sometimes link to a directory the way Gitea renders it, e.g. +infrastructure.md contains [`incidents/`](incidents/). On a static site with +directory URLs, that href resolves relative to the *page* (giving +/infrastructure/incidents/ and a 404). This hook rewrites such links to the +generated landing page for that directory (build.sh creates +/index.md for documented directories that lack one). It never edits the +documents themselves. +""" + +import posixpath +import re + +from mkdocs.utils import get_relative_url + +_HREF = re.compile(r'(href=)("([^"]+)/")') + + +def on_page_content(html, page, config, files): + index_urls = {} + for f in files: + src = f.src_path + if src.endswith("/index.md"): + index_urls[posixpath.dirname(src)] = f.url + + page_dir = posixpath.dirname(page.file.src_path) + + def fix(match): + href = match.group(3) + if href.startswith(("http://", "https://", "/", "#")): + return match.group(0) + target = posixpath.normpath(posixpath.join(page_dir, href)) + if target in (".", "..") or target not in index_urls: + return match.group(0) + return f'{match.group(1)}"{get_relative_url(index_urls[target], page.file.url)}"' + + return _HREF.sub(fix, html)