diff --git a/tools/prepare_mdbook_zh.py b/tools/prepare_mdbook_zh.py index 031dc15..26def20 100644 --- a/tools/prepare_mdbook_zh.py +++ b/tools/prepare_mdbook_zh.py @@ -11,6 +11,71 @@ OPTION_LINE_RE = re.compile(r"^:(width|label):`[^`]+`\s*$", re.MULTILINE) NUMREF_RE = re.compile(r":numref:`([^`]+)`") EQREF_RE = re.compile(r":eqref:`([^`]+)`") CITE_RE = re.compile(r":cite:`([^`]+)`") +RAW_HTML_FILE_RE = re.compile(r"^\s*:file:\s*([^\s]+)\s*$") +HEAD_TAG_RE = re.compile(r"", re.IGNORECASE) +STYLE_BLOCK_RE = re.compile(r"", re.IGNORECASE | re.DOTALL) +FRONTPAGE_LAYOUT_CSS = """ + +""".strip() def extract_title(markdown: str, fallback: str = "Untitled") -> str: @@ -87,6 +152,58 @@ def normalize_directives(markdown: str) -> str: return "\n".join(collapsed) + "\n" +def resolve_raw_html_file(current_file: Path, filename: str) -> Path: + direct = (current_file.parent / filename).resolve() + if direct.exists(): + return direct + + static_fallback = (current_file.parent / "static" / filename).resolve() + if static_fallback.exists(): + return static_fallback + + raise FileNotFoundError(f"Raw HTML include '{filename}' from '{current_file}' does not exist") + + +def rewrite_frontpage_assets(html: str) -> str: + rewritten = html.replace('./_images/', 'static/image/') + rewritten = rewritten.replace('_images/', 'static/image/') + rewritten = HEAD_TAG_RE.sub("", rewritten) + rewritten = STYLE_BLOCK_RE.sub(_minify_style_block, rewritten) + return rewritten + + +def _minify_style_block(match: re.Match[str]) -> str: + content = match.group(1) + parts = [line.strip() for line in content.splitlines() if line.strip()] + return f"" + + +def wrap_frontpage_html(html: str) -> str: + return "\n".join([FRONTPAGE_LAYOUT_CSS, '
', html.strip(), '
']) + + +def inline_raw_html(block_lines: list[str], current_file: Path) -> str | None: + stripped = [line.strip() for line in block_lines if line.strip()] + if not stripped or stripped[0] != ".. raw:: html": + return None + + filename: str | None = None + for line in stripped[1:]: + match = RAW_HTML_FILE_RE.match(line) + if match: + filename = match.group(1) + break + + if filename is None: + return None + + html_path = resolve_raw_html_file(current_file, filename) + html = rewrite_frontpage_assets(html_path.read_text(encoding="utf-8")).strip() + if Path(filename).name == "frontpage.html": + return wrap_frontpage_html(html) + return html + + def render_toc_list(entries: list[str], current_file: Path, title_cache: dict[Path, str]) -> list[str]: rendered: list[str] = [] for entry in entries: @@ -118,6 +235,14 @@ def rewrite_markdown(markdown: str, current_file: Path, title_cache: dict[Path, output.extend(render_toc_list(entries, current_file, title_cache)) if output and output[-1] != "": output.append("") + elif fence == EVAL_RST_FENCE: + raw_html = inline_raw_html(block_lines, current_file) + if raw_html: + if output and output[-1] != "": + output.append("") + output.extend(raw_html.splitlines()) + if output and output[-1] != "": + output.append("") index += 1 continue