From cb9573119a9121d79b22d93d341735d30f1f6d22 Mon Sep 17 00:00:00 2001 From: cydia2001 Date: Wed, 11 Mar 2026 01:19:56 +0000 Subject: [PATCH] feat: add homepage language switch links Inject a homepage-only language switch into the mdBook frontpage wrapper so the English homepage links to the Chinese homepage and the Chinese homepage links back to the English homepage. --- tests/test_prepare_mdbook.py | 51 +++++++++++++++++++++++++ tests/test_prepare_mdbook_zh.py | 3 ++ tools/mdbook_preprocessor.py | 4 ++ tools/mdbook_zh_preprocessor.py | 4 ++ tools/prepare_mdbook.py | 67 ++++++++++++++++++++++++++++++--- tools/prepare_mdbook_zh.py | 29 ++++++++++++++ 6 files changed, 153 insertions(+), 5 deletions(-) diff --git a/tests/test_prepare_mdbook.py b/tests/test_prepare_mdbook.py index bfce92e..ffcdf1d 100644 --- a/tests/test_prepare_mdbook.py +++ b/tests/test_prepare_mdbook.py @@ -109,6 +109,57 @@ Reference :cite:`smith2024`. self.assertIn("## References", rewritten) self.assertNotIn("## 参考文献", rewritten) + def test_rewrite_markdown_inlines_frontpage_with_language_switch(self) -> None: + with tempfile.TemporaryDirectory() as tmpdir: + root = Path(tmpdir) + source = root / "en_chapters" + static_dir = source / "static" + static_dir.mkdir(parents=True) + + index = source / "index.md" + index.write_text( + """# Home + +```eval_rst +.. raw:: html + :file: frontpage.html +``` +""", + encoding="utf-8", + ) + (static_dir / "frontpage.html").write_text( + "
frontpage
\n", + encoding="utf-8", + ) + + rewritten = rewrite_markdown( + index.read_text(encoding="utf-8"), + index.resolve(), + {index.resolve(): "Home"}, + frontpage_switch_label="中文", + frontpage_switch_href="cn/", + ) + + self.assertIn('class="openmlsys-frontpage-switch"', rewritten) + self.assertIn('href="cn/"', rewritten) + self.assertIn(">中文", rewritten) + + def test_regular_page_does_not_render_frontpage_switch(self) -> None: + with tempfile.TemporaryDirectory() as tmpdir: + root = Path(tmpdir) + page = root / "chapter.md" + page.write_text("# Chapter\n\nRegular body.\n", encoding="utf-8") + + rewritten = rewrite_markdown( + page.read_text(encoding="utf-8"), + page.resolve(), + {page.resolve(): "Chapter"}, + frontpage_switch_label="中文", + frontpage_switch_href="cn/", + ) + + self.assertNotIn('openmlsys-frontpage-switch', rewritten) + if __name__ == "__main__": unittest.main() diff --git a/tests/test_prepare_mdbook_zh.py b/tests/test_prepare_mdbook_zh.py index 7182438..e6a7e4c 100644 --- a/tests/test_prepare_mdbook_zh.py +++ b/tests/test_prepare_mdbook_zh.py @@ -221,6 +221,9 @@ missing self.assertIn("static/image/logo.png", rewritten) self.assertIn("static/image/jinxuefeng.png", rewritten) self.assertIn("console.log('frontpage')", rewritten) + self.assertIn('class="openmlsys-frontpage-switch"', rewritten) + self.assertIn('href="../"', rewritten) + self.assertIn(">English", rewritten) if __name__ == "__main__": diff --git a/tools/mdbook_preprocessor.py b/tools/mdbook_preprocessor.py index 15c4d15..d02f5bb 100644 --- a/tools/mdbook_preprocessor.py +++ b/tools/mdbook_preprocessor.py @@ -12,6 +12,8 @@ except ModuleNotFoundError: PLACEHOLDER_PREFIX = "[TODO: src = zh_chapters/" BIBLIOGRAPHY_TITLE = "References" +FRONTPAGE_SWITCH_LABEL = "中文" +FRONTPAGE_SWITCH_HREF = "cn/" def iter_chapters(items: list[dict]) -> list[dict]: @@ -47,6 +49,8 @@ def main() -> int: title_cache, bib_db, bibliography_title=BIBLIOGRAPHY_TITLE, + frontpage_switch_label=FRONTPAGE_SWITCH_LABEL, + frontpage_switch_href=FRONTPAGE_SWITCH_HREF, ) json.dump(book, sys.stdout, ensure_ascii=False) diff --git a/tools/mdbook_zh_preprocessor.py b/tools/mdbook_zh_preprocessor.py index e58d8d1..3940cda 100644 --- a/tools/mdbook_zh_preprocessor.py +++ b/tools/mdbook_zh_preprocessor.py @@ -11,6 +11,8 @@ except ModuleNotFoundError: BIBLIOGRAPHY_TITLE = "参考文献" +FRONTPAGE_SWITCH_LABEL = "English" +FRONTPAGE_SWITCH_HREF = "../" def iter_chapters(items: list[dict]) -> list[dict]: @@ -46,6 +48,8 @@ def main() -> int: title_cache, bib_db, bibliography_title=BIBLIOGRAPHY_TITLE, + frontpage_switch_label=FRONTPAGE_SWITCH_LABEL, + frontpage_switch_href=FRONTPAGE_SWITCH_HREF, ) json.dump(book, sys.stdout, ensure_ascii=False) diff --git a/tools/prepare_mdbook.py b/tools/prepare_mdbook.py index 154bcfb..d094bd4 100644 --- a/tools/prepare_mdbook.py +++ b/tools/prepare_mdbook.py @@ -26,6 +26,31 @@ FRONTPAGE_LAYOUT_CSS = """ .openmlsys-frontpage { width: 100%; margin: 0 auto 3rem; + position: relative; +} +.openmlsys-frontpage-switch { + position: absolute; + top: 20px; + right: 20px; + z-index: 2; + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 88px; + padding: 10px 16px; + border-radius: 999px; + border: 1px solid rgba(11, 107, 203, 0.25); + background: rgba(255, 255, 255, 0.92); + color: var(--links, #0b6bcb); + font-size: 14px; + font-weight: 600; + text-decoration: none; + box-shadow: 0 12px 30px rgba(11, 107, 203, 0.12); + backdrop-filter: blur(10px); +} +.openmlsys-frontpage-switch:hover { + background: #fff; + border-color: rgba(11, 107, 203, 0.4); } .openmlsys-frontpage .mdl-grid { display: flex; @@ -79,6 +104,10 @@ FRONTPAGE_LAYOUT_CSS = """ max-width: 960px; } @media (max-width: 1000px) { + .openmlsys-frontpage-switch { + top: 12px; + right: 12px; + } .openmlsys-frontpage .mdl-cell, .openmlsys-frontpage .mdl-cell--1-col, .openmlsys-frontpage .mdl-cell--3-col, @@ -373,11 +402,28 @@ def _minify_style_block(match: re.Match[str]) -> str: return f"" -def wrap_frontpage_html(html: str) -> str: - return "\n".join([FRONTPAGE_LAYOUT_CSS, '
', html.strip(), "
"]) +def render_frontpage_switch(label: str, href: str) -> str: + return f'{label}' -def inline_raw_html(block_lines: list[str], current_file: Path) -> str | None: +def wrap_frontpage_html( + html: str, + frontpage_switch_label: str | None = None, + frontpage_switch_href: str | None = None, +) -> str: + parts = [FRONTPAGE_LAYOUT_CSS, '
'] + if frontpage_switch_label and frontpage_switch_href: + parts.append(render_frontpage_switch(frontpage_switch_label, frontpage_switch_href)) + parts.extend([html.strip(), "
"]) + return "\n".join(parts) + + +def inline_raw_html( + block_lines: list[str], + current_file: Path, + frontpage_switch_label: str | None = None, + frontpage_switch_href: str | None = None, +) -> str | None: stripped = [line.strip() for line in block_lines if line.strip()] if not stripped or stripped[0] != ".. raw:: html": return None @@ -395,7 +441,11 @@ def inline_raw_html(block_lines: list[str], current_file: Path) -> str | 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 wrap_frontpage_html( + html, + frontpage_switch_label=frontpage_switch_label, + frontpage_switch_href=frontpage_switch_href, + ) return html @@ -430,6 +480,8 @@ def rewrite_markdown( title_cache: dict[Path, str], bib_db: dict[str, dict[str, str]] | None = None, bibliography_title: str = DEFAULT_BIBLIOGRAPHY_TITLE, + frontpage_switch_label: str | None = None, + frontpage_switch_href: str | None = None, ) -> str: output: list[str] = [] lines = markdown.splitlines() @@ -455,7 +507,12 @@ def rewrite_markdown( if rendered and output and output[-1] != "": output.append("") elif fence == EVAL_RST_FENCE: - raw_html = inline_raw_html(block_lines, current_file) + raw_html = inline_raw_html( + block_lines, + current_file, + frontpage_switch_label=frontpage_switch_label, + frontpage_switch_href=frontpage_switch_href, + ) if raw_html: if output and output[-1] != "": output.append("") diff --git a/tools/prepare_mdbook_zh.py b/tools/prepare_mdbook_zh.py index a5e17c5..ec8bac9 100644 --- a/tools/prepare_mdbook_zh.py +++ b/tools/prepare_mdbook_zh.py @@ -7,6 +7,7 @@ try: from tools.prepare_mdbook import ( build_title_cache, extract_title, + inline_raw_html, parse_bib, rewrite_markdown, write_summary, @@ -15,12 +16,17 @@ except ModuleNotFoundError: from prepare_mdbook import ( build_title_cache, extract_title, + inline_raw_html, parse_bib, rewrite_markdown, write_summary, ) +FRONTPAGE_SWITCH_LABEL = "English" +FRONTPAGE_SWITCH_HREF = "../" + + def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description="Generate mdBook SUMMARY.md for zh_chapters.") parser.add_argument("--source", type=Path, default=Path("zh_chapters"), help="Source chapter directory") @@ -40,5 +46,28 @@ def main() -> int: return 0 +def rewrite_markdown( + markdown: str, + current_file: Path, + title_cache: dict[Path, str], + bib_db: dict[str, dict[str, str]] | None = None, + bibliography_title: str = "参考文献", +) -> str: + try: + from tools.prepare_mdbook import rewrite_markdown as generic_rewrite_markdown + except ModuleNotFoundError: + from prepare_mdbook import rewrite_markdown as generic_rewrite_markdown + + return generic_rewrite_markdown( + markdown, + current_file, + title_cache, + bib_db=bib_db, + bibliography_title=bibliography_title, + frontpage_switch_label=FRONTPAGE_SWITCH_LABEL, + frontpage_switch_href=FRONTPAGE_SWITCH_HREF, + ) + + if __name__ == "__main__": raise SystemExit(main())