diff --git a/docforge/cli/commands.py b/docforge/cli/commands.py index e940c66..1bf8491 100644 --- a/docforge/cli/commands.py +++ b/docforge/cli/commands.py @@ -39,7 +39,7 @@ def cli() -> None: @click.option( "--docs-dir", type=click.Path(path_type=Path), - default=Path("docs"), + default=Path("docs/lib"), help="Directory for MD sources", ) @click.option( @@ -61,7 +61,7 @@ def cli() -> None: @click.option( "--out-dir", type=click.Path(path_type=Path), - default=Path("mcp_docs"), + default=Path("docs/mcp"), help="MCP output directory", ) def build( @@ -144,6 +144,7 @@ def build( docs_dir, project_name, module_is_source, + readme_dir=mkdocs_yml.parent, ) click.echo(f"Generating MkDocs config {mkdocs_yml}...") @@ -177,7 +178,7 @@ def build( @click.option( "--out-dir", type=click.Path(path_type=Path), - default=Path("mcp_docs"), + default=Path("docs/mcp"), help="MCP root directory", ) def serve( diff --git a/docforge/cli/mcp_utils.py b/docforge/cli/mcp_utils.py index 09e3b2c..a47cef5 100644 --- a/docforge/cli/mcp_utils.py +++ b/docforge/cli/mcp_utils.py @@ -63,7 +63,7 @@ def serve(module: str, mcp_root: Path) -> None: If the MCP documentation bundle is missing required files or directories. """ if not mcp_root.exists(): - raise click.ClickException(f"mcp_docs directory not found: {mcp_root}") + raise click.ClickException(f"MCP docs directory not found: {mcp_root}") required = [ mcp_root / "index.json", diff --git a/docforge/cli/mkdocs_utils.py b/docforge/cli/mkdocs_utils.py index 289d524..5ab4d4d 100644 --- a/docforge/cli/mkdocs_utils.py +++ b/docforge/cli/mkdocs_utils.py @@ -4,6 +4,7 @@ Utilities for working with MkDocs in the doc-forge CLI. """ +import os from importlib import resources from pathlib import Path @@ -20,6 +21,7 @@ def generate_sources( docs_dir: Path, project_name: str | None = None, module_is_source: bool | None = None, + readme_dir: Path | None = None, ) -> None: """ Generate MkDocs Markdown sources for a Python module. @@ -42,6 +44,10 @@ def generate_sources( module_is_source (Optional[bool]): If True, treat the specified module directory as the project root rather than a nested module. + + readme_dir (Optional[Path]): + Directory where the generated README.md should be written. If not + provided, defaults to the parent of ``docs_dir``. """ loader = GriffeLoader() discovered_paths = discover_module_paths(module) @@ -58,6 +64,7 @@ def generate_sources( project, docs_dir, module_is_source, + readme_dir, ) @@ -117,6 +124,7 @@ def generate_config( data = yaml.safe_load(text) data["site_name"] = site_name + data["docs_dir"] = Path(os.path.relpath(docs_dir, out.parent)).as_posix() data["nav"] = nav_block out.write_text(yaml.safe_dump(data, sort_keys=False), encoding="utf-8") diff --git a/docforge/renderers/mkdocs_renderer.py b/docforge/renderers/mkdocs_renderer.py index 5b7df4f..aaea47c 100644 --- a/docforge/renderers/mkdocs_renderer.py +++ b/docforge/renderers/mkdocs_renderer.py @@ -82,6 +82,7 @@ class MkDocsRenderer: project: Project, docs_dir: Path, module_is_source: bool | None = None, + readme_dir: Path | None = None, ) -> None: """ Generate a `README.md` file from the root module docstring. @@ -99,15 +100,20 @@ class MkDocsRenderer: docs_dir (Path): Directory containing generated documentation sources. - module_is_source (bool, optional): + module_is_source (Optional[bool]): Whether the module is treated as the project source root. + + readme_dir (Optional[Path]): + Directory where the generated README.md should be written. + Defaults to the parent of `docs_dir`. """ if not module_is_source: # Future: support README generation per module return - readme_path = docs_dir.parent / "README.md" + readme_root = readme_dir if readme_dir is not None else docs_dir.parent + readme_path = readme_root / "README.md" root_module = None for module in project.get_all_modules(): diff --git a/tests/cli/test_build_mcp.py b/tests/cli/test_build_mcp.py index 8cb1bb2..88ff93e 100644 --- a/tests/cli/test_build_mcp.py +++ b/tests/cli/test_build_mcp.py @@ -11,7 +11,7 @@ def test_mcp_build(cli_runner): (pkg / "__init__.py").write_text("") (pkg / "mod.py").write_text("def f(): ...\n") - out_dir = cwd / "mcp_docs" + out_dir = cwd / "docs" / "mcp" result = cli_runner.invoke( cli, @@ -20,8 +20,6 @@ def test_mcp_build(cli_runner): "--mcp", "--module", "testpkg", - "--out-dir", - str(out_dir), ], ) diff --git a/tests/cli/test_build_mkdocs.py b/tests/cli/test_build_mkdocs.py index 7987ed4..b44da95 100644 --- a/tests/cli/test_build_mkdocs.py +++ b/tests/cli/test_build_mkdocs.py @@ -33,8 +33,6 @@ def test_mkdocs_build_full_flow( "testpkg", "--site-name", "Test Site", - "--docs-dir", - "docs", "--mkdocs-yml", "mkdocs.yml", ], @@ -43,7 +41,8 @@ def test_mkdocs_build_full_flow( assert result.exit_code == 0 assert mock_mkdocs_build() is True assert (cwd / "mkdocs.yml").exists() - assert (cwd / "docs" / "testpkg" / "mod.md").exists() + assert (cwd / "docs" / "lib" / "testpkg" / "mod.md").exists() + assert "docs_dir: docs/lib" in (cwd / "mkdocs.yml").read_text() def test_mkdocs_build_missing_module_fails(cli_runner): @@ -81,8 +80,6 @@ def test_mkdocs_build_without_site_name_uses_module_as_default_full_flow( "--mkdocs", "--module", "testpkg", - "--docs-dir", - "docs", "--mkdocs-yml", "mkdocs.yml", ], @@ -99,5 +96,5 @@ def test_mkdocs_build_without_site_name_uses_module_as_default_full_flow( content = mkdocs_yml.read_text() assert "site_name: testpkg" in content - # Docs must be generated - assert (cwd / "docs" / "testpkg" / "mod.md").exists() + # Docs must be generated under the nested docs/lib dir + assert (cwd / "docs" / "lib" / "testpkg" / "mod.md").exists()