fix: make MkDocs generation filesystem-complete and package-aware
- Add filesystem-based module discovery via `discover_module_paths` - Decouple documentation coverage from Python import behavior - Ensure GriffeLoader receives a full module list instead of a single root - Make MkDocs renderer level-agnostic using global package detection - Emit `index.md` only for true packages, suppress `<package>.md` - Mirror full dotted module hierarchy into nested docs directories - Update CLI, exports, and type stubs to expose discovery helper - Align tests with filesystem-driven module coverage This fixes missing docs for submodules and removes invalid package `.md` files.
This commit is contained in:
@@ -11,43 +11,43 @@ class MkDocsRenderer:
|
||||
name = "mkdocs"
|
||||
|
||||
def generate_sources(self, project: Project, out_dir: Path) -> None:
|
||||
"""
|
||||
Generate Markdown files with mkdocstrings directives.
|
||||
modules = list(project.get_all_modules())
|
||||
paths = {m.path for m in modules}
|
||||
|
||||
Structure rules:
|
||||
- Each top-level package gets a directory
|
||||
- Modules become .md files
|
||||
- Packages (__init__) become index.md
|
||||
"""
|
||||
for module in project.get_all_modules():
|
||||
self._write_module(project, module, out_dir)
|
||||
# Package detection (level-agnostic)
|
||||
packages = {
|
||||
p for p in paths
|
||||
if any(other.startswith(p + ".") for other in paths)
|
||||
}
|
||||
|
||||
for module in modules:
|
||||
self._write_module(module, packages, out_dir)
|
||||
|
||||
# -------------------------
|
||||
# Internal helpers
|
||||
# -------------------------
|
||||
|
||||
def _write_module(self, project: Project, module, out_dir: Path) -> None:
|
||||
def _write_module(self, module, packages: set[str], out_dir: Path) -> None:
|
||||
parts = module.path.split(".")
|
||||
|
||||
# Root package directory
|
||||
pkg_dir = out_dir / parts[0]
|
||||
pkg_dir.mkdir(parents=True, exist_ok=True)
|
||||
if module.path in packages:
|
||||
# package → index.md
|
||||
dir_path = out_dir.joinpath(*parts)
|
||||
dir_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Package (__init__.py) → index.md
|
||||
if module.path == parts[0]:
|
||||
md_path = pkg_dir / "index.md"
|
||||
title = parts[0].replace("_", " ").title()
|
||||
md_path = dir_path / "index.md"
|
||||
title = parts[-1].replace("_", " ").title()
|
||||
else:
|
||||
# Submodule → <name>.md
|
||||
md_path = pkg_dir / f"{parts[-1]}.md"
|
||||
# leaf module → <name>.md
|
||||
dir_path = out_dir.joinpath(*parts[:-1])
|
||||
dir_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
md_path = dir_path / f"{parts[-1]}.md"
|
||||
title = parts[-1].replace("_", " ").title()
|
||||
|
||||
content = self._render_markdown(title, module.path)
|
||||
|
||||
# Idempotent write
|
||||
if md_path.exists():
|
||||
if md_path.read_text(encoding="utf-8") == content:
|
||||
return
|
||||
if md_path.exists() and md_path.read_text(encoding="utf-8") == content:
|
||||
return
|
||||
|
||||
md_path.write_text(content, encoding="utf-8")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user