doc preprocessor: support indent directives

Janky Python makes the world go around. In repentance I removed some
jank from it.

Change-Id: Id91e1fd40cb73049cb64deab6f81a7193132fa82
This commit is contained in:
Jade Lovelace
2025-03-25 17:06:53 -07:00
parent 41e10862cb
commit 989498407b
+39 -5
View File
@@ -1,9 +1,21 @@
#!/usr/bin/env python3
"""
Preprocesses mdbook markdown, primarily for include directives.
The include directive format is as follows:
{{#include foo/bar/baz.md}}
The content of includes will be indented as much as the directive itself.
Including a generated file (from building Lix; generally for the 'new' CLI):
{{#include @generated@/foo/bar/baz.md}}
"""
from pathlib import Path
import json
import os, os.path
import sys
import textwrap
name = 'substitute.py'
@@ -11,6 +23,12 @@ def log(*args, **kwargs):
kwargs['file'] = sys.stderr
return print(f'{name}:', *args, **kwargs)
def remove_prefix_if_present(s: str, prefix: str) -> str | None:
if s.startswith(prefix):
return s.removeprefix(prefix)
else:
return None
def do_include(content: str, relative_md_path: Path, source_root: Path, search_path: Path):
assert not relative_md_path.is_absolute(), f'{relative_md_path=} from mdbook should be relative'
@@ -20,16 +38,32 @@ def do_include(content: str, relative_md_path: Path, source_root: Path, search_p
lines = []
for l in content.splitlines(keepends=True):
if l.strip().startswith("{{#include "):
requested = l.strip()[11:][:-2]
if requested.startswith("@generated@/"):
included = search_path / Path(requested[12:])
if remain := remove_prefix_if_present(l.strip(), "{{#include"):
requested = remain[1:-2]
# We indent bodies of indent directives by the indent of the
# directive itself.
num_leading_indent = len(l) - len(l.lstrip())
if subpath := remove_prefix_if_present(requested, "@generated@/"):
included = search_path / Path(subpath)
requested = included.relative_to(search_path)
else:
included = source_root / relative_md_path.parent / requested
requested = included.resolve().relative_to(source_root)
assert included.exists(), f"{requested} not found at {included}"
lines.append(do_include(included.read_text(), requested, source_root, search_path) + "\n")
lines.append(
textwrap.indent(
do_include(
included.read_text(),
requested,
source_root,
search_path,
),
" " * num_leading_indent
)
+ "\n"
)
else:
lines.append(l)
return "".join(lines)