mirror of
https://github.com/openmlsys/openmlsys-zh.git
synced 2026-03-21 12:32:04 +08:00
* feat: add v1/v2 versioning and language selector for mdbook - Copy current content to v1/ directory (1st Edition) - Create v2/ directory with new TOC structure (2nd Edition) and placeholder chapters - Add version selector (V1/V2) and language toggle (EN/ZH) in top-right nav bar - Add build scripts: build_mdbook_v1.sh, build_mdbook_v2.sh - Update assemble_docs_publish_tree.py to support v1/v2 deployment layout - Fix mdbook preprocessor to use 'sections' key (v0.4.43 compatibility) - Update .gitignore for new build artifact directories - Deployment layout: / = v2 EN, /cn/ = v2 ZH, /v1/ = v1 EN, /v1/cn/ = v1 ZH Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * build: update CI to build and verify all four books (v1/v2 x EN/ZH) - Clarify step names: "Build v2 (EN + ZH)" and "Build v1 (EN + ZH)" - Add verification step to check all four index.html outputs exist - Deploy workflow assembles: / = v2 EN, /cn/ = v2 ZH, /v1/ = v1 EN, /v1/cn/ = v1 ZH Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: gracefully skip missing TOC entries instead of crashing resolve_toc_target() now returns None for missing files instead of raising FileNotFoundError. This fixes v1 EN build where chapter index files reference TOC entry names that don't match actual filenames. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
136 lines
3.9 KiB
Python
136 lines
3.9 KiB
Python
from __future__ import annotations
|
|
|
|
import argparse
|
|
import shutil
|
|
from pathlib import Path
|
|
|
|
|
|
def remove_path(path: Path) -> None:
|
|
if path.is_symlink() or path.is_file():
|
|
path.unlink()
|
|
return
|
|
if path.is_dir():
|
|
shutil.rmtree(path)
|
|
|
|
|
|
def copy_site(source: Path, destination: Path) -> None:
|
|
source = source.resolve()
|
|
if not source.is_dir():
|
|
raise FileNotFoundError(f"Site source does not exist or is not a directory: {source}")
|
|
|
|
remove_path(destination)
|
|
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
shutil.copytree(source, destination)
|
|
|
|
|
|
def assemble_publish_tree(
|
|
destination_root: Path,
|
|
docs_subdir: str = "docs",
|
|
en_source: Path | None = None,
|
|
zh_source: Path | None = None,
|
|
v1_en_source: Path | None = None,
|
|
v1_zh_source: Path | None = None,
|
|
v2_en_source: Path | None = None,
|
|
v2_zh_source: Path | None = None,
|
|
) -> tuple[Path, Path | None]:
|
|
if en_source is None and zh_source is None and v2_en_source is None:
|
|
raise ValueError("At least one site source must be provided.")
|
|
|
|
destination_root = destination_root.resolve()
|
|
docs_root = (destination_root / docs_subdir).resolve()
|
|
|
|
remove_path(docs_root)
|
|
docs_root.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
# v2 (latest) is deployed at the root — /docs/
|
|
effective_en = v2_en_source or en_source
|
|
if effective_en is not None:
|
|
copy_site(effective_en, docs_root)
|
|
else:
|
|
docs_root.mkdir(parents=True, exist_ok=True)
|
|
|
|
zh_destination: Path | None = None
|
|
effective_zh = v2_zh_source or zh_source
|
|
if effective_zh is not None:
|
|
zh_destination = docs_root / "cn"
|
|
copy_site(effective_zh, zh_destination)
|
|
|
|
# v1 is deployed under /docs/v1/
|
|
if v1_en_source is not None:
|
|
v1_root = docs_root / "v1"
|
|
copy_site(v1_en_source, v1_root)
|
|
if v1_zh_source is not None:
|
|
copy_site(v1_zh_source, v1_root / "cn")
|
|
|
|
return docs_root, zh_destination
|
|
|
|
|
|
def parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(
|
|
description="Assemble the publish tree expected by openmlsys.github.io."
|
|
)
|
|
parser.add_argument(
|
|
"--destination-root",
|
|
type=Path,
|
|
required=True,
|
|
help="Root of the checked-out deployment repository.",
|
|
)
|
|
parser.add_argument(
|
|
"--docs-subdir",
|
|
default="docs",
|
|
help="Subdirectory inside the destination root that hosts the site.",
|
|
)
|
|
parser.add_argument(
|
|
"--en-source",
|
|
type=Path,
|
|
help="Built site to publish at docs/ (legacy, use --v2-en-source instead).",
|
|
)
|
|
parser.add_argument(
|
|
"--zh-source",
|
|
type=Path,
|
|
help="Built site to publish at docs/cn/ (legacy, use --v2-zh-source instead).",
|
|
)
|
|
parser.add_argument(
|
|
"--v1-en-source",
|
|
type=Path,
|
|
help="Built v1 English site to publish at docs/v1/.",
|
|
)
|
|
parser.add_argument(
|
|
"--v1-zh-source",
|
|
type=Path,
|
|
help="Built v1 Chinese site to publish at docs/v1/cn/.",
|
|
)
|
|
parser.add_argument(
|
|
"--v2-en-source",
|
|
type=Path,
|
|
help="Built v2 English site to publish at docs/.",
|
|
)
|
|
parser.add_argument(
|
|
"--v2-zh-source",
|
|
type=Path,
|
|
help="Built v2 Chinese site to publish at docs/cn/.",
|
|
)
|
|
return parser.parse_args()
|
|
|
|
|
|
def main() -> int:
|
|
args = parse_args()
|
|
docs_root, zh_root = assemble_publish_tree(
|
|
destination_root=args.destination_root,
|
|
docs_subdir=args.docs_subdir,
|
|
en_source=args.en_source,
|
|
zh_source=args.zh_source,
|
|
v1_en_source=args.v1_en_source,
|
|
v1_zh_source=args.v1_zh_source,
|
|
v2_en_source=args.v2_en_source,
|
|
v2_zh_source=args.v2_zh_source,
|
|
)
|
|
print(f"Assembled root site at {docs_root}")
|
|
if zh_root is not None:
|
|
print(f"Assembled Chinese site at {zh_root}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|