diff --git a/.run/pytest.run.xml b/.run/pytest.run.xml
deleted file mode 100644
index b923b9b..0000000
--- a/.run/pytest.run.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docforge/renderers/mkdocs_renderer.py b/docforge/renderers/mkdocs_renderer.py
index 8edd3d1..7bb49e6 100644
--- a/docforge/renderers/mkdocs_renderer.py
+++ b/docforge/renderers/mkdocs_renderer.py
@@ -1,10 +1,15 @@
"""
-This module implements the MkDocsRenderer, which generates Markdown source files
-compatible with the MkDocs 'material' theme and 'mkdocstrings' extension.
+MkDocsRenderer
+
+Generates Markdown source files compatible with MkDocs Material
+and mkdocstrings, ensuring:
+
+- Root index.md always exists
+- Parent package indexes are created automatically
+- Child modules are linked in parent index files
"""
from pathlib import Path
-
from docforge.models import Project
@@ -16,6 +21,9 @@ class MkDocsRenderer:
name = "mkdocs"
+ # -------------------------
+ # Public API
+ # -------------------------
def generate_sources(self, project: Project, out_dir: Path) -> None:
"""
Produce a set of Markdown files in the output directory based on the
@@ -25,6 +33,9 @@ class MkDocsRenderer:
project: The project models to render.
out_dir: Target directory for documentation files.
"""
+ out_dir.mkdir(parents=True, exist_ok=True)
+ self._ensure_root_index(project, out_dir)
+
modules = list(project.get_all_modules())
paths = {m.path for m in modules}
@@ -53,26 +64,25 @@ class MkDocsRenderer:
parts = module.path.split(".")
if module.path in packages:
- # package → index.md
+ # Package → directory/index.md
dir_path = out_dir.joinpath(*parts)
dir_path.mkdir(parents=True, exist_ok=True)
-
md_path = dir_path / "index.md"
- title = parts[-1].replace("_", " ").title()
+ link_target = f"{parts[-1]}/"
else:
- # leaf module → .md
+ # Leaf module → parent_dir/.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()
+ link_target = f"{parts[-1]}.md"
+ title = parts[-1].replace("_", " ").title()
content = self._render_markdown(title, module.path)
- if md_path.exists() and md_path.read_text(encoding="utf-8") == content:
- return
+ if not md_path.exists() or md_path.read_text(encoding="utf-8") != content:
+ md_path.write_text(content, encoding="utf-8")
- md_path.write_text(content, encoding="utf-8")
+ self._ensure_parent_index(parts, out_dir, link_target, title)
def _render_markdown(self, title: str, module_path: str) -> str:
"""
@@ -89,3 +99,46 @@ class MkDocsRenderer:
f"# {title}\n\n"
f"::: {module_path}\n"
)
+
+ def _ensure_root_index(
+ self,
+ project: Project,
+ out_dir: Path
+ ) -> None:
+ root_index = out_dir / "index.md"
+
+ if not root_index.exists():
+ root_index.write_text(
+ f"# {project.name}\n\n"
+ "## Modules\n\n",
+ encoding="utf-8",
+ )
+
+ def _ensure_parent_index(
+ self,
+ parts: list[str],
+ out_dir: Path,
+ link_target: str,
+ title: str,
+ ) -> None:
+ if len(parts) == 1:
+ parent_index = out_dir / "index.md"
+ link = f"- [{title}]({link_target})\n"
+ else:
+ parent_dir = out_dir.joinpath(*parts[:-1])
+ parent_dir.mkdir(parents=True, exist_ok=True)
+ parent_index = parent_dir / "index.md"
+
+ link = f"- [{title}]({link_target})\n"
+
+ if not parent_index.exists():
+ parent_title = parts[-2].replace("_", " ").title()
+ parent_index.write_text(
+ f"# {parent_title}\n\n",
+ encoding="utf-8",
+ )
+
+ content = parent_index.read_text(encoding="utf-8")
+
+ if link not in content:
+ parent_index.write_text(content + link, encoding="utf-8")
diff --git a/docforge/renderers/mkdocs_renderer.pyi b/docforge/renderers/mkdocs_renderer.pyi
index b3f3f7c..3b13d76 100644
--- a/docforge/renderers/mkdocs_renderer.pyi
+++ b/docforge/renderers/mkdocs_renderer.pyi
@@ -8,10 +8,16 @@ class MkDocsRenderer:
name: str
def generate_sources(self, project: Project, out_dir: Path) -> None: ...
+
def _write_module(
self,
module: Module,
packages: Set[str],
out_dir: Path,
) -> None: ...
+
def _render_markdown(self, title: str, module_path: str) -> str: ...
+
+ def _ensure_root_index(self, project, out_dir) -> None: ...
+
+ def _ensure_parent_index(self, parts, out_dir, link_target, title) -> None: ...
diff --git a/docs/docforge/cli/index.md b/docs/docforge/cli/index.md
index 3b215dd..b5ece30 100644
--- a/docs/docforge/cli/index.md
+++ b/docs/docforge/cli/index.md
@@ -1,3 +1,7 @@
# Cli
::: docforge.cli
+- [Commands](commands.md)
+- [Main](main.md)
+- [Mcp Utils](mcp_utils.md)
+- [Mkdocs Utils](mkdocs_utils.md)
diff --git a/docs/docforge/index.md b/docs/docforge/index.md
index 86fda32..d6800dc 100644
--- a/docs/docforge/index.md
+++ b/docs/docforge/index.md
@@ -1,3 +1,9 @@
# Docforge
::: docforge
+- [Cli](cli/)
+- [Loaders](loaders/)
+- [Models](models/)
+- [Nav](nav/)
+- [Renderers](renderers/)
+- [Servers](servers/)
diff --git a/docs/docforge/loaders/index.md b/docs/docforge/loaders/index.md
index 9dc53f9..2cbb874 100644
--- a/docs/docforge/loaders/index.md
+++ b/docs/docforge/loaders/index.md
@@ -1,3 +1,4 @@
# Loaders
::: docforge.loaders
+- [Griffe Loader](griffe_loader.md)
diff --git a/docs/docforge/models/index.md b/docs/docforge/models/index.md
index 3d02dbd..f16cc48 100644
--- a/docs/docforge/models/index.md
+++ b/docs/docforge/models/index.md
@@ -1,3 +1,6 @@
# Models
::: docforge.models
+- [Module](module.md)
+- [Object](object.md)
+- [Project](project.md)
diff --git a/docs/docforge/nav/index.md b/docs/docforge/nav/index.md
index 95e83b3..b09bf84 100644
--- a/docs/docforge/nav/index.md
+++ b/docs/docforge/nav/index.md
@@ -1,3 +1,6 @@
# Nav
::: docforge.nav
+- [Mkdocs](mkdocs.md)
+- [Resolver](resolver.md)
+- [Spec](spec.md)
diff --git a/docs/docforge/renderers/index.md b/docs/docforge/renderers/index.md
index 53fb5a8..28d61c4 100644
--- a/docs/docforge/renderers/index.md
+++ b/docs/docforge/renderers/index.md
@@ -1,3 +1,6 @@
# Renderers
::: docforge.renderers
+- [Base](base.md)
+- [Mcp Renderer](mcp_renderer.md)
+- [Mkdocs Renderer](mkdocs_renderer.md)
diff --git a/docs/docforge/servers/index.md b/docs/docforge/servers/index.md
index 6297158..22e4b69 100644
--- a/docs/docforge/servers/index.md
+++ b/docs/docforge/servers/index.md
@@ -1,3 +1,4 @@
# Servers
::: docforge.servers
+- [Mcp Server](mcp_server.md)
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..41e79ac
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,5 @@
+# docforge
+
+## Modules
+
+- [Docforge](docforge/)
diff --git a/mkdocs.yml b/mkdocs.yml
index 5b9e7da..72b0e5b 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -1,5 +1,3 @@
-site_name: docforge
-
theme:
name: material
palette:
@@ -33,7 +31,7 @@ plugins:
annotations_path: brief
show_root_heading: true
group_by_category: true
-
+site_name: docforge
nav:
- Home: docforge/index.md
- Loaders: