From dc92d4a79d1063aafff56bc95594bc46aac3d717 Mon Sep 17 00:00:00 2001 From: Forgejo Actions Date: Sun, 19 Apr 2026 16:40:05 -0700 Subject: [PATCH] [docs] clean up latex leaking into docs site --- make_docs.sh | 10 +++- meanas/fdtd/energy.py | 1 + mkdocs.yml | 2 +- scripts/prepare_docs_sources.py | 93 +++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 scripts/prepare_docs_sources.py diff --git a/make_docs.sh b/make_docs.sh index 67a2a02..6bda9d9 100755 --- a/make_docs.sh +++ b/make_docs.sh @@ -5,7 +5,15 @@ set -Eeuo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$ROOT" -mkdocs build --clean +DOCS_TMP="$(mktemp -d)" +cleanup() { + rm -rf "$DOCS_TMP" +} +trap cleanup EXIT + +python3 "$ROOT/scripts/prepare_docs_sources.py" "$ROOT/meanas" "$DOCS_TMP" + +MKDOCSTRINGS_PYTHON_PATH="$DOCS_TMP" mkdocs build --clean PRINT_PAGE='site/print_page/index.html' if [[ -f "$PRINT_PAGE" ]] && command -v htmlark >/dev/null 2>&1; then diff --git a/meanas/fdtd/energy.py b/meanas/fdtd/energy.py index 6df30dc..57387aa 100644 --- a/meanas/fdtd/energy.py +++ b/meanas/fdtd/energy.py @@ -57,6 +57,7 @@ def poynting( (see `meanas.tests.test_fdtd.test_poynting_planes`) The full relationship is + $$ \begin{aligned} (U_{l+\frac{1}{2}} - U_l) / \Delta_t diff --git a/mkdocs.yml b/mkdocs.yml index 837284c..a0dcd2c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -34,7 +34,7 @@ plugins: handlers: python: paths: - - . + - !ENV [MKDOCSTRINGS_PYTHON_PATH, "."] options: show_root_heading: true show_root_toc_entry: false diff --git a/scripts/prepare_docs_sources.py b/scripts/prepare_docs_sources.py new file mode 100644 index 0000000..7e9bcc5 --- /dev/null +++ b/scripts/prepare_docs_sources.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +"""Prepare a temporary source tree for docs generation. + +The live source keeps readable display-math blocks written as standalone +`$$ ... $$` docstring sections. MkDocs + mkdocstrings does not consistently +preserve those blocks as MathJax input when they appear inside API docstrings, +so the docs build rewrites them in a temporary copy into explicit +`
...
` containers. +""" + +from __future__ import annotations + +from pathlib import Path +import shutil +import sys + + +def _rewrite_display_math(text: str) -> str: + lines = text.splitlines(keepends=True) + output: list[str] = [] + in_block = False + block_indent = "" + + for line in lines: + stripped = line.strip() + indent = line[: len(line) - len(line.lstrip())] + + if not in_block: + if stripped == "$$": + block_indent = indent + output.append(f'{block_indent}
\\[\n') + in_block = True + continue + + if stripped.startswith("$$") and stripped.endswith("$$") and stripped != "$$": + body = stripped[2:-2].strip() + output.append(f'{indent}
\\[ {body} \\]
\n') + continue + + if stripped.startswith("$$"): + block_indent = indent + body = stripped[2:].strip() + output.append(f'{block_indent}
\\[\n') + if body: + output.append(f"{block_indent}{body}\n") + in_block = True + continue + + output.append(line) + continue + + if stripped == "$$": + output.append(f"{block_indent}\\]
\n") + in_block = False + block_indent = "" + continue + + if stripped.endswith("$$"): + body = stripped[:-2].rstrip() + if body: + output.append(f"{block_indent}{body}\n") + output.append(f"{block_indent}\\]
\n") + in_block = False + block_indent = "" + continue + + output.append(line) + + if in_block: + raise ValueError("unterminated display-math block") + + return "".join(output) + + +def main() -> int: + if len(sys.argv) != 3: + print("usage: prepare_docs_sources.py ", file=sys.stderr) + return 2 + + src_dir = Path(sys.argv[1]).resolve() + dst_root = Path(sys.argv[2]).resolve() + dst_pkg = dst_root / src_dir.name + + shutil.copytree(src_dir, dst_pkg) + + for path in dst_pkg.rglob("*.py"): + path.write_text(_rewrite_display_math(path.read_text())) + + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())