6 Commits

Author SHA1 Message Date
8c6c46caf2 feat: add wiki build kind with file-structure-derived navigation
- add build_wiki_nav deriving MkDocs nav from docs/wiki file structure
  (index.md -> Home, numeric prefixes stripped and title-cased, nested
  dirs become groups, natural ordering)
- add --wiki / --wiki-dir to build; wiki-only builds need no --module
- merge wiki nav before generated lib/api nav; wiki Home replaces the
  nav spec Home entry
- add mkdocs.wiki.yml template fragment and nav/cli tests
- dogfood doc-forge's own docs/wiki and regenerate site output
2026-09-11 23:38:23 +05:30
bacf17b930 feat: add --api OpenAPI build mode with docs/api scheme and lib-prefixed nav 2026-09-11 05:37:56 +05:30
17e8628197 docs: nest generated docs under docs/lib and docs/mcp 2026-09-10 21:15:11 +05:30
a1c5f046d4 docs: output generated sources under docs/lib and docs/mcp 2026-09-10 21:11:30 +05:30
d4b79cf95a ignore coverage.xml test artifact 2026-09-10 20:21:23 +05:30
0129268cd3 standardize packaging, tooling, docs, CI, and licensing 2026-09-10 18:49:04 +05:30
155 changed files with 4091 additions and 2244 deletions

View File

@@ -32,6 +32,26 @@ steps:
echo "🆕 New version detected: $PACKAGE_NAME==$VERSION"
fi
- name: quality-gate
image: python:3.13-slim
environment:
PIP_REPO_URL:
from_secret: PIP_REPO_URL
PIP_USERNAME:
from_secret: PIP_USERNAME
PIP_PASSWORD:
from_secret: PIP_PASSWORD
commands:
- pip install --upgrade pip build
- |
AUTH_URL="https://${PIP_USERNAME}:${PIP_PASSWORD}@$(echo "${PIP_REPO_URL#*://}" | sed 's:/*$::')/simple"
pip install --index-url "$AUTH_URL" --extra-index-url https://pypi.org/simple/ -U ".[dev]"
- echo "🛡️ Running quality gate..."
- python -m black --check .
- python -m ruff check .
- python -m mypy
- python -m pytest
- name: build-package
image: python:3.13-slim
commands:
@@ -126,4 +146,4 @@ steps:
trigger:
event:
- custom
- custom

5
.gitignore vendored
View File

@@ -87,3 +87,8 @@ Thumbs.db
# =========================
.env
.env.*
# =========================
# Testing artifacts
# =========================
coverage.xml

21
CHANGELOG.md Normal file
View File

@@ -0,0 +1,21 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- `py.typed` marker for PEP 561 type information.
- `.drone.yml` CI with a quality-gate step (black, ruff, mypy, pytest).
- MIT `LICENSE`.
### Changed
- Standardized `pyproject.toml` (canonical packaging, lint tool config, extras).
- Pinned the `mcp` extra to `mcp>=1.0.0,<2.0.0` to restore compatibility with
the current MCP server API used by doc-forge.
### Fixed
- Stub fixes for typed API surfaces.

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Aetoskia Platform
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,26 +1,30 @@
home: index.md
home: lib/index.md
groups:
Loaders:
- loaders/index.md
- loaders/griffe_loader.md
- lib/loaders/index.md
- lib/loaders/griffe_loader.md
Models:
- models/index.md
- models/module.md
- models/object.md
- models/project.md
- lib/models/index.md
- lib/models/module.md
- lib/models/object.md
- lib/models/project.md
Navigation:
- nav/index.md
- nav/spec.md
- nav/resolver.md
- nav/mkdocs.md
- lib/nav/index.md
- lib/nav/spec.md
- lib/nav/resolver.md
- lib/nav/mkdocs.md
Renderers:
- renderers/index.md
- renderers/base.md
- renderers/mkdocs_renderer.md
- renderers/mcp_renderer.md
- lib/renderers/index.md
- lib/renderers/base.md
- lib/renderers/mkdocs_renderer.md
- lib/renderers/mcp_renderer.md
CLI:
- cli/index.md
- cli/main.md
- cli/commands.md
- cli/mcp_utils.md
- cli/mkdocs_utils.md
- lib/cli/index.md
- lib/cli/main.md
- lib/cli/commands.md
- lib/cli/api_utils.md
- lib/cli/mcp_utils.md
- lib/cli/mkdocs_utils.md
icon:
logo: material/file-document-multiple
repo: fontawesome/brands/github

View File

@@ -1,7 +1,7 @@
from .loaders import GriffeLoader, discover_module_paths
from .renderers import MkDocsRenderer, MCPRenderer
from .cli import main
from . import models
from .cli import main
from .loaders import GriffeLoader, discover_module_paths
from .renderers import MCPRenderer, MkDocsRenderer
__all__ = [
"GriffeLoader",

View File

@@ -37,6 +37,4 @@ Example:
from .main import main
__all__ = [
"main"
]
__all__ = ["main"]

View File

@@ -1,5 +1,3 @@
from .main import main
__all__ = [
"main"
]
__all__ = ["main"]

114
docforge/cli/api_utils.py Normal file
View File

@@ -0,0 +1,114 @@
"""
# Summary
Utilities for building API documentation from an OpenAPI specification.
"""
import json
from dataclasses import dataclass
from pathlib import Path
import click
SWAGGER_SPEC_FILENAME = "openapi.json"
@dataclass
class OpenAPIMetadata:
"""
Metadata derived from the ``info`` block of an OpenAPI specification.
Attributes:
site_name: Spec title, used as the MkDocs site name.
site_description: Spec description, used as the site description.
site_author: Contact name (fallback: contact email), used as the
site author.
"""
site_name: str
site_description: str | None
site_author: str | None
def load_openapi_spec(spec_path: Path) -> dict:
"""
Load and validate an OpenAPI specification from a JSON file.
Args:
spec_path: Path to the OpenAPI JSON specification file.
Returns:
dict:
The parsed OpenAPI specification.
Raises:
click.ClickException:
If the file cannot be read or the ``info`` block is invalid.
"""
if not spec_path.exists():
raise click.ClickException(f"OpenAPI spec not found: {spec_path}")
try:
data = json.loads(spec_path.read_text(encoding="utf-8"))
except (json.JSONDecodeError, OSError) as exc:
raise click.ClickException(f"Unable to read OpenAPI spec: {exc}") from exc
if not isinstance(data, dict):
raise click.ClickException("OpenAPI spec must be a JSON mapping")
info = data.get("info")
if not isinstance(info, dict) or not isinstance(info.get("title"), str):
raise click.ClickException("OpenAPI spec missing 'info.title'")
return data
def derive_metadata(spec: dict) -> OpenAPIMetadata:
"""
Derive MkDocs site metadata from an OpenAPI spec ``info`` block.
Args:
spec: Parsed OpenAPI specification.
Returns:
OpenAPIMetadata:
Site name, description, and author derived from the spec.
"""
info = spec["info"]
contact = info.get("contact")
if isinstance(contact, dict):
author = contact.get("name") or contact.get("email")
else:
author = None
return OpenAPIMetadata(
site_name=info.get("title", ""),
site_description=info.get("description"),
site_author=author,
)
def generate_api_sources(spec: dict, docs_dir: Path) -> None:
"""
Generate swagger-enabled Markdown sources and the spec copy.
The specification is written as ``openapi.json`` inside ``docs_dir`` and
an ``index.md`` embedding the swagger UI is generated alongside it.
Args:
spec: Parsed OpenAPI specification.
docs_dir: Directory (for example ``docs/api``) where the swagger
sources are written.
"""
docs_dir.mkdir(parents=True, exist_ok=True)
spec_path = docs_dir / SWAGGER_SPEC_FILENAME
spec_json = json.dumps(spec, indent=2)
if not spec_path.exists() or spec_path.read_text(encoding="utf-8") != spec_json:
spec_path.write_text(spec_json, encoding="utf-8")
index_path = docs_dir / "index.md"
content = "# API Reference\n\n" f'<swagger-ui src="{SWAGGER_SPEC_FILENAME}"/>\n'
if not index_path.exists() or index_path.read_text(encoding="utf-8") != content:
index_path.write_text(content, encoding="utf-8")

View File

@@ -0,0 +1,13 @@
from dataclasses import dataclass
from pathlib import Path
from typing import Any
@dataclass
class OpenAPIMetadata:
site_name: str
site_description: str | None
site_author: str | None
def load_openapi_spec(spec_path: Path) -> dict[Any, Any]: ...
def derive_metadata(spec: dict[Any, Any]) -> OpenAPIMetadata: ...
def generate_api_sources(spec: dict[Any, Any], docs_dir: Path) -> None: ...

View File

@@ -6,12 +6,12 @@ Command definitions for the doc-forge CLI.
Provides the CLI structure using Click, including build, serve, and tree commands.
"""
import click
from pathlib import Path
from typing import Sequence, Optional
import click
from docforge.cli import api_utils, mcp_utils, mkdocs_utils
from docforge.loaders import GriffeLoader
from docforge.cli import mkdocs_utils
from docforge.cli import mcp_utils
@click.group()
@@ -28,26 +28,71 @@ def cli() -> None:
@cli.command()
@click.option("--mcp", is_flag=True, help="Build MCP resources")
@click.option("--mkdocs", is_flag=True, help="Build MkDocs site")
@click.option("--module-is-source", is_flag=True, help="Module is source folder and to be treated as root folder")
@click.option("--api", is_flag=True, help="Build API docs from an OpenAPI spec")
@click.option(
"--wiki", is_flag=True, help="Include a hand-written wiki in the MkDocs site"
)
@click.option(
"--module-is-source",
is_flag=True,
help="Module is source folder and to be treated as root folder",
)
@click.option("--module", help="Python module to document")
@click.option(
"--openapi-spec",
type=click.Path(path_type=Path),
help="Path to the OpenAPI JSON specification",
)
@click.option("--project-name", help="Project name override")
@click.option("--site-name", help="MkDocs site name")
@click.option("--docs-dir", type=click.Path(path_type=Path), default=Path("docs"), help="Directory for MD sources")
@click.option("--nav", "nav_file", type=click.Path(path_type=Path), default=Path("docforge.nav.yml"),
help="Nav spec path")
@click.option("--template", type=click.Path(path_type=Path), help="MkDocs template path")
@click.option("--mkdocs-yml", type=click.Path(path_type=Path), default=Path("mkdocs.yml"), help="Output config path")
@click.option("--out-dir", type=click.Path(path_type=Path), default=Path("mcp_docs"), help="MCP output directory")
@click.option(
"--docs-dir",
type=click.Path(path_type=Path),
default=Path("docs"),
help="MkDocs documentation root",
)
@click.option(
"--wiki-dir",
type=click.Path(path_type=Path),
default=Path("docs/wiki"),
help="Hand-written wiki directory included in the MkDocs site",
)
@click.option(
"--nav",
"nav_file",
type=click.Path(path_type=Path),
default=Path("docforge.nav.yml"),
help="Nav spec path",
)
@click.option(
"--template", type=click.Path(path_type=Path), help="MkDocs template path"
)
@click.option(
"--mkdocs-yml",
type=click.Path(path_type=Path),
default=Path("mkdocs.yml"),
help="Output config path",
)
@click.option(
"--out-dir",
type=click.Path(path_type=Path),
default=Path("docs/mcp"),
help="MCP output directory",
)
def build(
mcp: bool,
mkdocs: bool,
api: bool,
wiki: bool,
module_is_source: bool,
module: Optional[str],
project_name: Optional[str],
site_name: Optional[str],
module: str | None,
openapi_spec: Path | None,
project_name: str | None,
site_name: str | None,
docs_dir: Path,
wiki_dir: Path,
nav_file: Path,
template: Optional[Path],
template: Path | None,
mkdocs_yml: Path,
out_dir: Path,
) -> None:
@@ -55,14 +100,14 @@ def build(
Build documentation artifacts.
This command performs the full documentation build pipeline:
1. Introspects the Python project using Griffe
2. Generates renderer-specific documentation sources
3. Optionally builds the final documentation output
style of the selected platform, generates renderer-specific
documentation sources, and optionally builds the final output.
Depending on the selected options, the build can target:
- MkDocs static documentation sites
- MkDocs static documentation sites for library reference docs
- Swagger-enabled API docs generated from an OpenAPI spec
- Hand-written wiki pages included in the MkDocs site
- MCP structured documentation resources
Args:
@@ -70,7 +115,13 @@ def build(
Enable MCP documentation generation.
mkdocs (bool):
Enable MkDocs documentation generation.
Enable MkDocs library documentation generation.
api (bool):
Enable API documentation generation from an OpenAPI spec.
wiki (bool):
Include a hand-written wiki directory in the MkDocs site.
module_is_source (bool):
Treat the specified module directory as the project root.
@@ -78,6 +129,9 @@ def build(
module (Optional[str]):
Python module import path to document.
openapi_spec (Optional[Path]):
Path to the OpenAPI JSON specification used for API docs.
project_name (Optional[str]):
Optional override for the project name.
@@ -85,7 +139,10 @@ def build(
Display name for the MkDocs site.
docs_dir (Path):
Directory where Markdown documentation sources will be generated.
Shared documentation root used as the MkDocs ``docs_dir``.
wiki_dir (Path):
Directory containing hand-written wiki markdown files.
nav_file (Path):
Path to the navigation specification file.
@@ -103,25 +160,76 @@ def build(
click.UsageError:
If required options are missing or conflicting.
"""
if not mcp and not mkdocs:
raise click.UsageError("Must specify either --mcp or --mkdocs")
if not mcp and not mkdocs and not api and not wiki:
raise click.UsageError("Must specify either --mcp, --mkdocs, --wiki, or --api")
if mkdocs:
if not module:
raise click.UsageError("--module is required for MkDocs build")
if not site_name:
site_name = module
if api:
if not openapi_spec:
raise click.UsageError("--openapi-spec is required for API build")
if site_name and not mkdocs and not wiki:
raise click.UsageError(
"--site-name cannot be overridden for API build; "
"the OpenAPI spec provides the site name"
)
click.echo(f"Generating MkDocs sources in {docs_dir}...")
mkdocs_utils.generate_sources(
module,
docs_dir,
project_name,
module_is_source,
if (mkdocs or mcp) and not module:
raise click.UsageError(
"--module is required for MkDocs build"
if mkdocs
else "--module is required for MCP build"
)
spec: dict | None = None
if api:
spec = api_utils.load_openapi_spec(openapi_spec)
if mkdocs:
lib_dir = docs_dir / "lib"
click.echo(f"Generating MkDocs sources in {lib_dir}...")
mkdocs_utils.generate_sources(
module,
lib_dir,
project_name,
module_is_source,
readme_dir=mkdocs_yml.parent,
)
if api:
api_dir = docs_dir / "api"
click.echo(f"Generating API sources in {api_dir}...")
api_utils.generate_api_sources(spec, api_dir)
if mkdocs or api or wiki:
modes: list[str] = []
if mkdocs:
modes.append("lib")
if api:
modes.append("api")
if wiki:
modes.append("wiki")
site_description: str | None = None
site_author: str | None = None
effective_site_name = site_name or module or Path.cwd().name
if api:
metadata = api_utils.derive_metadata(spec)
effective_site_name = metadata.site_name
site_description = metadata.site_description
site_author = metadata.site_author
click.echo(f"Generating MkDocs config {mkdocs_yml}...")
mkdocs_utils.generate_config(docs_dir, nav_file, template, mkdocs_yml, site_name)
mkdocs_utils.generate_config(
docs_dir,
nav_file,
template,
mkdocs_yml,
effective_site_name,
modes=modes,
site_description=site_description,
site_author=site_author,
wiki_dir=wiki_dir if wiki else None,
)
click.echo("Running MkDocs build...")
mkdocs_utils.build(mkdocs_yml)
@@ -140,12 +248,22 @@ def build(
@click.option("--mcp", is_flag=True, help="Serve MCP documentation")
@click.option("--mkdocs", is_flag=True, help="Serve MkDocs site")
@click.option("--module", help="Python module to serve")
@click.option("--mkdocs-yml", type=click.Path(path_type=Path), default=Path("mkdocs.yml"), help="MkDocs config path")
@click.option("--out-dir", type=click.Path(path_type=Path), default=Path("mcp_docs"), help="MCP root directory")
@click.option(
"--mkdocs-yml",
type=click.Path(path_type=Path),
default=Path("mkdocs.yml"),
help="MkDocs config path",
)
@click.option(
"--out-dir",
type=click.Path(path_type=Path),
default=Path("docs/mcp"),
help="MCP root directory",
)
def serve(
mcp: bool,
mkdocs: bool,
module: Optional[str],
module: str | None,
mkdocs_yml: Path,
out_dir: Path,
) -> None:
@@ -202,7 +320,7 @@ def serve(
)
def tree(
module: str,
project_name: Optional[str],
project_name: str | None,
) -> None:
"""
Display the documentation object tree for a module.

View File

@@ -1,34 +1,36 @@
from click.core import Group
from pathlib import Path
from typing import Sequence, Optional, Any
from typing import Any
from click.core import Group
cli: Group
def build(
mcp: bool,
mkdocs: bool,
api: bool,
wiki: bool,
module_is_source: bool,
module: Optional[str],
project_name: Optional[str],
site_name: Optional[str],
module: str | None,
openapi_spec: Path | None,
project_name: str | None,
site_name: str | None,
docs_dir: Path,
wiki_dir: Path,
nav_file: Path,
template: Optional[Path],
template: Path | None,
mkdocs_yml: Path,
out_dir: Path,
) -> None: ...
def serve(
mcp: bool,
mkdocs: bool,
module: Optional[str],
module: str | None,
mkdocs_yml: Path,
out_dir: Path,
) -> None: ...
def tree(
module: str,
project_name: Optional[str],
project_name: str | None,
) -> None: ...
def _print_object(obj: Any, indent: str) -> None: ...

View File

@@ -22,4 +22,4 @@ def main() -> None:
if __name__ == "__main__":
main()
main()

View File

@@ -5,7 +5,9 @@ Utilities for working with MCP in the doc-forge CLI.
"""
from pathlib import Path
import click
from docforge.loaders import GriffeLoader, discover_module_paths
from docforge.renderers import MCPRenderer
from docforge.servers import MCPServer
@@ -61,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",

View File

@@ -1,4 +1,6 @@
from pathlib import Path
def generate_resources(module: str, project_name: str | None, out_dir: Path) -> None: ...
def generate_resources(
module: str, project_name: str | None, out_dir: Path
) -> None: ...
def serve(module: str, mcp_root: Path) -> None: ...

View File

@@ -4,13 +4,22 @@
Utilities for working with MkDocs in the doc-forge CLI.
"""
from pathlib import Path
import os
from collections.abc import Iterable
from importlib import resources
from pathlib import Path
import click
import yaml
from docforge.loaders import GriffeLoader, discover_module_paths
from docforge.nav import (
MkDocsNavEmitter,
build_wiki_nav,
load_nav_spec,
resolve_nav,
)
from docforge.renderers import MkDocsRenderer
from docforge.nav import load_nav_spec, resolve_nav, MkDocsNavEmitter
def generate_sources(
@@ -18,6 +27,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.
@@ -40,6 +50,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)
@@ -56,6 +70,7 @@ def generate_sources(
project,
docs_dir,
module_is_source,
readme_dir,
)
@@ -65,24 +80,35 @@ def generate_config(
template: Path | None,
out: Path,
site_name: str,
modes: Iterable[str] | None = None,
site_description: str | None = None,
site_author: str | None = None,
wiki_dir: Path | None = None,
) -> None:
"""
Generate an `mkdocs.yml` configuration file.
The configuration is created by combining a template configuration
with a navigation structure derived from the docforge navigation
specification.
specification (and, when a wiki directory is provided, from the wiki
file structure).
The ``docs_dir`` is always written relative to the MkDocs root and is
expected to be the shared documentation parent (for example ``docs``),
with generated sources nested under ``lib/`` or ``api/`` subdirectories
and hand-written wiki content under a ``wiki/`` subdirectory.
Args:
docs_dir (Path):
Directory containing generated documentation Markdown files.
Shared documentation root used as the MkDocs ``docs_dir``.
nav_file (Path):
Path to the `docforge.nav.yml` navigation specification.
template (Optional[Path]):
Optional path to a custom MkDocs configuration template. If not
provided, a built-in template will be used.
Optional path to a fully custom MkDocs configuration template.
If not provided, built-in templates are merged; the provided
template replaces the built-in templates entirely.
out (Path):
Destination path where the generated `mkdocs.yml` file will be written.
@@ -90,34 +116,184 @@ def generate_config(
site_name (str):
Display name for the generated documentation site.
modes (Optional[Iterable[str]]):
Documentation modes to enable. Each mode contributes its own
built-in template fragment (for example ``lib``, ``api``, or
``wiki``), merged on top of the shared ``mkdocs.common.yml``
template.
site_description (Optional[str]):
Optional site description written into the configuration.
site_author (Optional[str]):
Optional site author written into the configuration.
wiki_dir (Optional[Path]):
Optional path to a hand-written wiki directory (for example
``docs/wiki``). When provided, the site navigation is derived
from the wiki file structure and placed before the navigation
groups defined in ``nav_file``.
Raises:
click.FileError:
If the navigation specification or template file cannot be found.
If the navigation specification, template, or wiki directory
cannot be found.
"""
if not nav_file.exists():
if not nav_file.exists() and wiki_dir is None:
raise click.FileError(str(nav_file), hint="Nav spec not found")
spec = load_nav_spec(nav_file)
resolved = resolve_nav(spec, docs_dir)
nav_block = MkDocsNavEmitter().emit(resolved)
nav_block: list[dict] = []
if nav_file.exists():
spec = load_nav_spec(nav_file)
resolved = resolve_nav(spec, docs_dir)
nav_block = MkDocsNavEmitter().emit(resolved)
else:
spec = None
# Load template
if wiki_dir is not None:
if not wiki_dir.exists():
raise click.FileError(str(wiki_dir), hint="Wiki dir not found")
wiki_nav = build_wiki_nav(wiki_dir)
if wiki_nav:
nav_block = wiki_nav + [entry for entry in nav_block if "Home" not in entry]
data = _load_template(template, modes)
data["site_name"] = site_name
if site_description:
data["site_description"] = site_description
if site_author:
data["site_author"] = site_author
data["docs_dir"] = Path(os.path.relpath(docs_dir, out.parent)).as_posix()
data["nav"] = nav_block
if spec is not None and spec.icon:
theme = data.setdefault("theme", {})
if not isinstance(theme, dict):
theme = {}
theme["icon"] = spec.icon
data["theme"] = theme
out.write_text(yaml.safe_dump(data, sort_keys=False), encoding="utf-8")
def _load_template(
template: Path | None,
modes: Iterable[str] | None,
) -> dict:
"""
Load the MkDocs configuration template.
When a custom template path is provided, it is used as-is. Otherwise the
shared ``mkdocs.common.yml`` template is deep-merged with the fragments
contributed by each enabled mode (``lib`` or ``api``).
Args:
template (Optional[Path]):
Optional fully custom template that replaces the built-ins.
modes (Optional[Iterable[str]]):
Documentation modes whose template fragments should be merged.
Returns:
dict:
Merged MkDocs configuration mapping.
Raises:
click.FileError:
If a referenced template file cannot be found.
"""
if template is not None:
if not template.exists():
raise click.FileError(str(template), hint="Template not found")
data = yaml.safe_load(template.read_text(encoding="utf-8"))
else:
return yaml.safe_load(template.read_text(encoding="utf-8"))
data: dict = {}
active_modes = list(modes) if modes else ["lib"]
parts = ["common", *active_modes]
seen: set[str] = set()
for part_name in parts:
if part_name in seen:
continue
seen.add(part_name)
text = (
resources.files("docforge.templates")
.joinpath("mkdocs.sample.yml")
.joinpath(f"mkdocs.{part_name}.yml")
.read_text(encoding="utf-8")
)
data = yaml.safe_load(text)
part: dict = yaml.safe_load(text)
data = _deep_merge(data, part)
data["site_name"] = site_name
data["nav"] = nav_block
return data
out.write_text(yaml.safe_dump(data, sort_keys=False), encoding="utf-8")
def _item_name(item: object) -> str:
"""
Return the identifying name of a list entry.
String entries identify as themselves; mapping entries identify by their
first key. This is used to deduplicate plugin and extension lists.
Args:
item: List entry, either a string or a single-key mapping.
Returns:
str:
The identifying name of the entry.
"""
if isinstance(item, dict):
return next(iter(item.keys()), "")
return str(item)
def _merge_list(base: list, added: list) -> list:
"""
Merge two lists, preserving order and dropping duplicates by name.
Args:
base: Existing list entries.
added: Entries to append when not already present.
Returns:
list:
Merged list with duplicates removed.
"""
result = list(base)
names = {_item_name(item) for item in result}
for item in added:
name = _item_name(item)
if name not in names:
result.append(item)
names.add(name)
return result
def _deep_merge(base: dict, part: dict) -> dict:
"""
Deep merge a template fragment into a base configuration.
Mappings are merged recursively, while lists are combined by
deduplicating entries by their identifying name. Non-container values in
the fragment override the base.
Args:
base: Configuration being built up.
part: Template fragment to merge into the base.
Returns:
dict:
The merged configuration.
"""
for key, value in part.items():
if isinstance(value, dict) and isinstance(base.get(key), dict):
base[key] = _deep_merge(base[key], value)
elif isinstance(value, list) and isinstance(base.get(key), list):
base[key] = _merge_list(base[key], value)
else:
base[key] = value
return base
def build(mkdocs_yml: Path) -> None:
@@ -138,8 +314,8 @@ def build(mkdocs_yml: Path) -> None:
if not mkdocs_yml.exists():
raise click.ClickException(f"mkdocs.yml not found: {mkdocs_yml}")
from mkdocs.config import load_config
from mkdocs.commands.build import build as mkdocs_build
from mkdocs.config import load_config
mkdocs_build(load_config(str(mkdocs_yml)))
@@ -163,4 +339,5 @@ def serve(mkdocs_yml: Path) -> None:
raise click.ClickException(f"mkdocs.yml not found: {mkdocs_yml}")
from mkdocs.commands.serve import serve as mkdocs_serve
mkdocs_serve(config_file=str(mkdocs_yml))

View File

@@ -1,3 +1,4 @@
from collections.abc import Iterable
from pathlib import Path
def generate_sources(
@@ -5,7 +6,18 @@ def generate_sources(
docs_dir: Path,
project_name: str | None = None,
module_is_source: bool | None = None,
readme_dir: Path | None = None,
) -> None: ...
def generate_config(
docs_dir: Path,
nav_file: Path,
template: Path | None,
out: Path,
site_name: str,
modes: Iterable[str] | None = None,
site_description: str | None = None,
site_author: str | None = None,
wiki_dir: Path | None = None,
) -> None: ...
def generate_config(docs_dir: Path, nav_file: Path, template: Path | None, out: Path, site_name: str) -> None: ...
def build(mkdocs_yml: Path) -> None: ...
def serve(mkdocs_yml: Path) -> None: ...

View File

@@ -10,17 +10,18 @@ into doc-forge documentation models.
import logging
from pathlib import Path
from typing import List, Optional
from griffe import (
GriffeLoader as _GriffeLoader,
ModulesCollection,
LinesCollection,
Object,
AliasResolutionError,
LinesCollection,
ModulesCollection,
Object,
)
from griffe import (
GriffeLoader as _GriffeLoader,
)
from docforge.models import Module, Project, DocObject
from docforge.models import DocObject, Module, Project
logger = logging.getLogger(__name__)
@@ -28,7 +29,7 @@ logger = logging.getLogger(__name__)
def discover_module_paths(
module_name: str,
project_root: Path | None = None,
) -> List[str]:
) -> list[str]:
"""
Discover Python modules within a package directory.
@@ -65,7 +66,7 @@ def discover_module_paths(
if not pkg_dir.exists():
raise FileNotFoundError(f"Package not found: {pkg_dir}")
module_paths: List[str] = []
module_paths: list[str] = []
for path in pkg_dir.rglob("*.py"):
if path.name == "__init__.py":
@@ -102,10 +103,10 @@ class GriffeLoader:
)
def load_project(
self,
module_paths: List[str],
project_name: Optional[str] = None,
skip_import_errors: bool = None,
self,
module_paths: list[str],
project_name: str | None = None,
skip_import_errors: bool = None,
) -> Project:
"""
Load multiple modules and assemble them into a Project model.
@@ -250,7 +251,7 @@ class GriffeLoader:
# Safe extractors
# -------------------------
def _safe_docstring(self, obj: Object) -> Optional[str]:
def _safe_docstring(self, obj: Object) -> str | None:
"""
Safely extract a docstring from a Griffe object.
@@ -267,7 +268,7 @@ class GriffeLoader:
except AliasResolutionError:
return None
def _safe_signature(self, obj: Object) -> Optional[str]:
def _safe_signature(self, obj: Object) -> str | None:
"""
Safely extract the signature of a Griffe object.

View File

@@ -1,15 +1,11 @@
from typing import List, Optional
from pathlib import Path
from docforge.models import Module, Project
def discover_module_paths(
module_name: str,
project_root: Path | None = None,
) -> List[str]:
...
) -> list[str]: ...
class GriffeLoader:
"""Griffe-based introspection loaders.
@@ -18,11 +14,10 @@ class GriffeLoader:
"""
def __init__(self) -> None: ...
def load_project(
self,
module_paths: List[str],
project_name: Optional[str] = ...,
module_paths: list[str],
project_name: str | None = ...,
skip_import_errors: bool = ...,
) -> Project:
"""Load a documentation project from Python modules."""

View File

@@ -1,6 +1,6 @@
from .project import Project
from .module import Module
from .object import DocObject
from .project import Project
__all__ = [
"Project",

View File

@@ -9,7 +9,7 @@ model. A `Module` acts as a container for top-level documented objects
introspection.
"""
from typing import Dict, Iterable, Optional
from collections.abc import Iterable
from docforge.models.object import DocObject
@@ -36,7 +36,7 @@ class Module:
def __init__(
self,
path: str,
docstring: Optional[str] = None,
docstring: str | None = None,
) -> None:
"""
Initialize a Module instance.
@@ -50,7 +50,7 @@ class Module:
"""
self.path = path
self.docstring = docstring
self.members: Dict[str, DocObject] = {}
self.members: dict[str, DocObject] = {}
def add_object(self, obj: DocObject) -> None:
"""

View File

@@ -1,23 +1,19 @@
from typing import Dict, Iterable, Optional
from collections.abc import Iterable
from docforge.models.object import DocObject
class Module:
"""Represents a documented Python module."""
path: str
docstring: Optional[str]
members: Dict[str, DocObject]
docstring: str | None
members: dict[str, DocObject]
def __init__(
self,
path: str,
docstring: Optional[str] = ...,
docstring: str | None = ...,
) -> None: ...
def add_object(self, obj: DocObject) -> None: ...
def get_object(self, name: str) -> DocObject: ...
def get_all_objects(self) -> Iterable[DocObject]: ...

View File

@@ -9,7 +9,7 @@ entity such as a class, function, method, or attribute, and may contain nested
members that form a hierarchical documentation structure.
"""
from typing import Dict, Iterable, Optional
from collections.abc import Iterable
class DocObject:
@@ -45,8 +45,8 @@ class DocObject:
name: str,
kind: str,
path: str,
signature: Optional[str] = None,
docstring: Optional[str] = None,
signature: str | None = None,
docstring: str | None = None,
) -> None:
"""
Initialize a DocObject instance.
@@ -72,7 +72,7 @@ class DocObject:
self.path = path
self.signature = signature
self.docstring = docstring
self.members: Dict[str, "DocObject"] = {}
self.members: dict[str, DocObject] = {}
def add_member(self, obj: "DocObject") -> None:
"""

View File

@@ -1,5 +1,4 @@
from typing import Dict, Iterable, Optional
from collections.abc import Iterable
class DocObject:
"""Represents a documented Python object."""
@@ -7,21 +6,18 @@ class DocObject:
name: str
kind: str
path: str
signature: Optional[str]
docstring: Optional[str]
members: Dict[str, "DocObject"]
signature: str | None
docstring: str | None
members: dict[str, DocObject]
def __init__(
self,
name: str,
kind: str,
path: str,
signature: Optional[str] = ...,
docstring: Optional[str] = ...,
signature: str | None = ...,
docstring: str | None = ...,
) -> None: ...
def add_member(self, obj: "DocObject") -> None: ...
def get_member(self, name: str) -> "DocObject": ...
def get_all_members(self) -> Iterable["DocObject"]: ...
def add_member(self, obj: DocObject) -> None: ...
def get_member(self, name: str) -> DocObject: ...
def get_all_members(self) -> Iterable[DocObject]: ...

View File

@@ -8,7 +8,7 @@ doc-forge to represent a documented codebase. A `Project` aggregates multiple
modules and provides access to them through a unified interface.
"""
from typing import Dict, Iterable
from collections.abc import Iterable
from docforge.models.module import Module
@@ -37,7 +37,7 @@ class Project:
Name used to identify the documentation project.
"""
self.name = name
self.modules: Dict[str, Module] = {}
self.modules: dict[str, Module] = {}
def add_module(self, module: Module) -> None:
"""
@@ -85,4 +85,4 @@ class Project:
list[str]:
A list containing the dotted paths of all modules in the project.
"""
return list(self.modules.keys())
return list(self.modules.keys())

View File

@@ -1,20 +1,15 @@
from typing import Dict, Iterable
from collections.abc import Iterable
from docforge.models.module import Module
class Project:
"""Represents a documentation project."""
name: str
modules: Dict[str, Module]
modules: dict[str, Module]
def __init__(self, name: str) -> None: ...
def add_module(self, module: Module) -> None: ...
def get_module(self, path: str) -> Module: ...
def get_all_modules(self) -> Iterable[Module]: ...
def get_module_list(self) -> list[str]: ...

View File

@@ -26,11 +26,13 @@ independent of module hierarchy.
from .spec import NavSpec, load_nav_spec
from .resolver import ResolvedNav, resolve_nav
from .mkdocs import MkDocsNavEmitter
from .wiki import build_wiki_nav
__all__ = [
"NavSpec",
"ResolvedNav",
"MkDocsNavEmitter",
"build_wiki_nav",
"resolve_nav",
"load_nav_spec",
]

View File

@@ -1,11 +1,13 @@
from .spec import NavSpec, load_nav_spec
from .resolver import ResolvedNav, resolve_nav
from .mkdocs import MkDocsNavEmitter
from .resolver import ResolvedNav, resolve_nav
from .spec import NavSpec, load_nav_spec
from .wiki import build_wiki_nav
__all__ = [
"NavSpec",
"ResolvedNav",
"MkDocsNavEmitter",
"build_wiki_nav",
"resolve_nav",
"load_nav_spec",
]

View File

@@ -7,7 +7,7 @@ MkDocs ``nav`` configuration.
"""
from pathlib import Path
from typing import List, Dict, Any
from typing import Any
from docforge.nav.resolver import ResolvedNav
@@ -20,7 +20,7 @@ class MkDocsNavEmitter:
list structure expected by the MkDocs ``nav`` configuration field.
"""
def emit(self, nav: ResolvedNav) -> List[Dict[str, Any]]:
def emit(self, nav: ResolvedNav) -> list[dict[str, Any]]:
"""
Generate a navigation structure for ``mkdocs.yml``.
@@ -33,7 +33,7 @@ class MkDocsNavEmitter:
Each dictionary maps a navigation label to a page or a list of
pages.
"""
result: List[Dict[str, Any]] = []
result: list[dict[str, Any]] = []
# Home entry (semantic path)
if nav.home:
@@ -41,7 +41,7 @@ class MkDocsNavEmitter:
# Group entries
for group, paths in nav.groups.items():
entries: List[str] = []
entries: list[str] = []
for p in paths:
# Convert filesystem path back to docs-relative path
rel_path = self._to_relative(p, nav._docs_root)
@@ -75,7 +75,7 @@ class MkDocsNavEmitter:
path_str = path.as_posix()
docs_root_str = docs_root.as_posix()
if path_str.startswith(docs_root_str + "/"):
return path_str[len(docs_root_str) + 1:]
return path_str[len(docs_root_str) + 1 :]
# Fallback for other cases
return path.as_posix().split("/docs/", 1)[-1]

View File

@@ -1,15 +1,14 @@
from typing import Dict, List, Any
from pathlib import Path
from typing import Any
from docforge.nav.resolver import ResolvedNav
class MkDocsNavEmitter:
"""
Converts a ResolvedNav into MkDocs-compatible `nav` data.
"""
def emit(self, nav: ResolvedNav) -> List[Dict[str, Any]]:
def emit(self, nav: ResolvedNav) -> list[dict[str, Any]]:
"""
Emit a structure suitable for insertion into mkdocs.yml.

View File

@@ -5,10 +5,9 @@ This module resolves a ``NavSpec`` against the filesystem by expanding glob
patterns and validating that referenced documentation files exist.
"""
from pathlib import Path
from typing import Dict, Iterable, List
import glob
from collections.abc import Iterable
from pathlib import Path
from docforge.nav.spec import NavSpec
@@ -29,7 +28,7 @@ class ResolvedNav:
def __init__(
self,
home: str | None,
groups: Dict[str, List[Path]],
groups: dict[str, list[Path]],
docs_root: Path | None = None,
) -> None:
"""
@@ -61,8 +60,7 @@ class ResolvedNav:
yield self._docs_root / self.home
for paths in self.groups.values():
for p in paths:
yield p
yield from paths
def resolve_nav(
@@ -89,7 +87,7 @@ def resolve_nav(
if not docs_root.exists():
raise FileNotFoundError(docs_root)
def resolve_pattern(pattern: str) -> List[Path]:
def resolve_pattern(pattern: str) -> list[Path]:
"""
Resolve a glob pattern relative to the documentation root.
@@ -103,9 +101,7 @@ def resolve_nav(
FileNotFoundError: If the pattern does not match any files.
"""
full = docs_root / pattern
matches = sorted(
Path(p) for p in glob.glob(str(full), recursive=True)
)
matches = sorted(Path(p) for p in glob.glob(str(full), recursive=True))
if not matches:
raise FileNotFoundError(pattern)
@@ -121,10 +117,10 @@ def resolve_nav(
home = spec.home
# Resolve navigation groups
resolved_groups: Dict[str, List[Path]] = {}
resolved_groups: dict[str, list[Path]] = {}
for group, patterns in spec.groups.items():
files: List[Path] = []
files: list[Path] = []
for pattern in patterns:
files.extend(resolve_pattern(pattern))
resolved_groups[group] = files

View File

@@ -1,9 +1,8 @@
from collections.abc import Iterable
from pathlib import Path
from typing import Dict, List, Iterable, Optional
from docforge.nav.spec import NavSpec
class ResolvedNav:
"""
Fully-resolved navigation tree.
@@ -13,17 +12,16 @@ class ResolvedNav:
- Order is preserved
"""
home: Optional[str]
groups: Dict[str, List[Path]]
_docs_root: Optional[Path]
home: str | None
groups: dict[str, list[Path]]
_docs_root: Path | None
def __init__(
self,
home: str | None,
groups: Dict[str, List[Path]],
groups: dict[str, list[Path]],
docs_root: Path | None = ...,
) -> None: ...
def all_files(self) -> Iterable[Path]:
"""
Return all resolved documentation files in nav order.
@@ -33,7 +31,6 @@ class ResolvedNav:
"""
...
def resolve_nav(
spec: NavSpec,
docs_root: Path,

View File

@@ -7,7 +7,6 @@ structure defined by the user in the doc-forge navigation specification
"""
from pathlib import Path
from typing import Dict, List, Optional
import yaml
@@ -24,12 +23,16 @@ class NavSpec:
``index.md``).
groups: Mapping of navigation group titles to lists of file patterns
or glob expressions.
icon: Optional mapping of theme icon entries (for example
``{"logo": "material/code-tags"}``) injected into the MkDocs
theme as ``theme.icon``.
"""
def __init__(
self,
home: Optional[str],
groups: Dict[str, List[str]],
home: str | None,
groups: dict[str, list[str]],
icon: dict[str, str] | None = None,
) -> None:
"""
Initialize a NavSpec instance.
@@ -38,9 +41,12 @@ class NavSpec:
home: Relative path to the home document.
groups: Mapping of group names to lists of path patterns
(glob expressions).
icon: Optional mapping of theme icon entries applied to the
generated MkDocs configuration.
"""
self.home = home
self.groups = groups
self.icon = icon
@classmethod
def load(cls, path: Path) -> "NavSpec":
@@ -68,6 +74,7 @@ class NavSpec:
home = data.get("home")
groups = data.get("groups", {})
icon = data.get("icon")
if home is not None and not isinstance(home, str):
raise ValueError("home must be a string")
@@ -83,9 +90,17 @@ class NavSpec:
):
raise ValueError(f"group '{key}' must be a list of strings")
return cls(home=home, groups=groups)
if icon is not None and (
not isinstance(icon, dict)
or not all(
isinstance(k, str) and isinstance(v, str) for k, v in icon.items()
)
):
raise ValueError("icon must be a mapping of strings")
def all_patterns(self) -> List[str]:
return cls(home=home, groups=groups, icon=icon)
def all_patterns(self) -> list[str]:
"""
Return all path patterns referenced by the specification.
@@ -93,7 +108,7 @@ class NavSpec:
A list containing the home document (if defined) and all
group pattern entries.
"""
patterns: List[str] = []
patterns: list[str] = []
if self.home:
patterns.append(self.home)
@@ -132,4 +147,5 @@ def load_nav_spec(path: Path) -> NavSpec:
return NavSpec(
home=data.get("home"),
groups=data.get("groups", {}),
icon=data.get("icon"),
)

View File

@@ -1,6 +1,4 @@
from pathlib import Path
from typing import Dict, List, Optional
class NavSpec:
"""
@@ -10,18 +8,16 @@ class NavSpec:
of filesystem structure or MkDocs specifics.
"""
home: Optional[str]
groups: Dict[str, List[str]]
home: str | None
groups: dict[str, list[str]]
def __init__(
self,
home: Optional[str],
groups: Dict[str, List[str]],
) -> None:
...
home: str | None,
groups: dict[str, list[str]],
) -> None: ...
@classmethod
def load(cls, path: Path) -> "NavSpec":
def load(cls, path: Path) -> NavSpec:
"""
Load and validate a nav specification from YAML.
@@ -31,12 +27,11 @@ class NavSpec:
"""
...
def all_patterns(self) -> List[str]:
def all_patterns(self) -> list[str]:
"""
Return all path patterns referenced by the spec
(including home and group entries).
"""
...
def load_nav_spec(path: Path) -> NavSpec: ...

161
docforge/nav/wiki.py Normal file
View File

@@ -0,0 +1,161 @@
"""
# Summary
Wiki navigation derivation.
This module provides ``build_wiki_nav``, which derives an MkDocs-ready
navigation block from the file structure of a hand-written wiki directory
(typically ``docs/wiki``). wiki content is authored by hand and is never
modified by doc-forge; only the navigation layout is inferred.
# Notes
- ``index.md`` at the wiki root becomes the ``Home`` entry.
- Page labels are derived from filenames: numeric order prefixes such as
``01_`` or ``02-`` are stripped, separators are replaced with spaces, and
names are title-cased (``01_overview.md`` becomes ``Overview``).
- Subdirectories become nested navigation groups. A nested ``index.md`` is
rendered as the section root placed first inside the group.
- Only ``.md`` files are considered; hidden entries are ignored.
"""
import re
from pathlib import Path
from typing import Any
def build_wiki_nav(wiki_dir: Path) -> list[dict[str, Any]]:
"""
Derive an MkDocs navigation block from a wiki directory.
Returned paths are relative to the parent of ``wiki_dir`` and carry the
wiki directory name as their leading component (for example
``wiki/01_overview.md`` when the wiki lives at ``docs/wiki``). This makes
the result directly usable in an MkDocs ``nav`` block with
- ``index.md`` at the wiki root becomes the ``Home`` entry.
- Page labels are derived from filenames: numeric order prefixes such as
``01_`` or ``02-`` are stripped, separators are replaced with spaces, and
names are title-cased (``01_overview.md`` becomes ``Overview``).
- Subdirectories become nested navigation groups. A nested ``index.md`` is
rendered as the section root placed first inside the group.
- Only ``.md`` files are considered; hidden entries are ignored.
Args:
wiki_dir (Path):
Path to the hand-written wiki directory, for example ``docs/wiki``.
Returns:
List[Dict[str, Any]]:
Navigation entries compatible with the MkDocs ``nav`` configuration.
The list is empty if the wiki contains no Markdown files.
Raises:
FileNotFoundError:
If the wiki directory does not exist.
"""
if not wiki_dir.exists():
raise FileNotFoundError(wiki_dir)
root = wiki_dir.parent
def rel(path: Path) -> str:
try:
return path.relative_to(root).as_posix()
except ValueError:
return path.as_posix()
nav: list[dict[str, Any]] = []
if (wiki_dir / "index.md").exists():
nav.append({"Home": rel(wiki_dir / "index.md")})
nav.extend(_render_entries(wiki_dir, rel))
return nav
def _render_entries(base_dir: Path, rel) -> list[dict[str, Any]]:
"""
Render navigation entries for the children of a wiki directory.
Markdown pages become labeled entries, subdirectories containing
Markdown become nested groups, and a nested ``index.md`` is emitted
first as the section root.
Args:
base_dir (Path):
Directory whose children are rendered.
rel:
Callable converting a wiki file path into a docs-relative path.
Returns:
List[Dict[str, Any]]:
Navigation entries for ``base_dir`` in natural sort order.
"""
children = sorted(
(child for child in base_dir.iterdir() if not child.name.startswith(".")),
key=lambda child: _natural_key(child.name),
)
entries: list[dict[str, Any]] = []
for child in children:
if child.is_dir():
if not any(child.rglob("*.md")):
continue
group: list[dict[str, Any]] = []
nested_index = child / "index.md"
if nested_index.exists():
group.append({_prettify(child.name): rel(nested_index)})
group.extend(_render_entries(child, rel))
entries.append({_prettify(child.name): group})
elif child.suffix == ".md":
if child.name == "index.md":
continue
entries.append({_prettify(child.stem): rel(child)})
return entries
def _prettify(name: str) -> str:
"""
Convert a filename or directory name into a navigation label.
Numeric order prefixes (``01_``, ``02-``, ``03.``) are stripped,
separators are replaced with spaces, and the result is title-cased.
Args:
name (str):
Filename stem or directory name to prettify.
Returns:
str:
Title-cased navigation label.
"""
name = re.sub(r"^\d+[_\-. ]?", "", name)
name = re.sub(r"[_-]+", " ", name).strip()
return name.title()
def _natural_key(name: str) -> list[object]:
"""
Build a natural sort key from a filename.
The key splits ``name`` into alternating non-digit and digit parts so
that numeric prefixes sort numerically (``02`` before ``10``).
Args:
name (str):
Filename or directory name to key.
Returns:
List[object]:
Mixed list of lowercased strings and integers used for sorting.
"""
return [
int(part) if part.isdigit() else part.lower()
for part in re.split(r"(\d+)", name)
]

15
docforge/nav/wiki.pyi Normal file
View File

@@ -0,0 +1,15 @@
from pathlib import Path
from typing import Any
def build_wiki_nav(wiki_dir: Path) -> list[dict[str, Any]]:
"""
Derive an MkDocs navigation block from a wiki directory.
Returns:
Wiki navigation entries compatible with the MkDocs
`nav` configuration.
Raises:
FileNotFoundError: if the wiki directory does not exist
"""
...

0
docforge/py.typed Normal file
View File

View File

@@ -1,5 +1,5 @@
from .mkdocs_renderer import MkDocsRenderer
from .mcp_renderer import MCPRenderer
from .mkdocs_renderer import MkDocsRenderer
__all__ = [
"MkDocsRenderer",

View File

@@ -3,7 +3,6 @@ from typing import Protocol
from docforge.models import Project
class RendererConfig:
"""Renderer configuration container."""
@@ -12,7 +11,6 @@ class RendererConfig:
def __init__(self, out_dir: Path, project: Project) -> None: ...
class DocRenderer(Protocol):
"""Renderer interface."""

View File

@@ -9,9 +9,8 @@ resources compatible with the Model Context Protocol (MCP).
import json
from pathlib import Path
from typing import Dict, List
from docforge.models import Project, Module, DocObject
from docforge.models import DocObject, Module, Project
class MCPRenderer:
@@ -42,15 +41,17 @@ class MCPRenderer:
modules_dir = out_dir / "modules"
modules_dir.mkdir(parents=True, exist_ok=True)
nav: List[Dict[str, str]] = []
nav: list[dict[str, str]] = []
for module in project.get_all_modules():
self._write_module(module, modules_dir)
nav.append({
"module": module.path,
"resource": f"doc://modules/{module.path}",
})
nav.append(
{
"module": module.path,
"resource": f"doc://modules/{module.path}",
}
)
# Write nav.json
(out_dir / "nav.json").write_text(
@@ -91,7 +92,7 @@ class MCPRenderer:
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text(self._json(payload), encoding="utf-8")
def _render_module(self, module: Module) -> Dict:
def _render_module(self, module: Module) -> dict:
"""
Convert a Module model into MCP-compatible structured data.
@@ -103,7 +104,7 @@ class MCPRenderer:
Dict:
Dictionary representing the module and its documented objects.
"""
data: Dict = {
data: dict = {
"path": module.path,
"docstring": module.docstring,
"objects": {},
@@ -114,7 +115,7 @@ class MCPRenderer:
return data
def _render_object(self, obj: DocObject) -> Dict:
def _render_object(self, obj: DocObject) -> dict:
"""
Recursively convert a DocObject into structured MCP data.
@@ -126,7 +127,7 @@ class MCPRenderer:
Dict:
Dictionary describing the object and any nested members.
"""
data: Dict = {
data: dict = {
"name": obj.name,
"kind": obj.kind,
"path": obj.path,
@@ -137,14 +138,13 @@ class MCPRenderer:
members = list(obj.get_all_members())
if members:
data["members"] = {
member.name: self._render_object(member)
for member in members
member.name: self._render_object(member) for member in members
}
return data
@staticmethod
def _json(data: Dict) -> str:
def _json(data: dict) -> str:
"""
Serialize data to formatted JSON.

View File

@@ -1,8 +1,7 @@
from pathlib import Path
from typing import Dict, List
from docforge.models import Project, Module, DocObject
from typing import Any
from docforge.models import DocObject, Module, Project
class MCPRenderer:
"""Renderer that emits MCP-native JSON resources from docforge models."""
@@ -15,12 +14,12 @@ class MCPRenderer:
def _write_module(self, module: Module, modules_dir: Path) -> None:
"""Serialize a module into an MCP JSON resource."""
def _render_module(self, module: Module) -> Dict:
def _render_module(self, module: Module) -> dict[str, Any]:
"""Render a Module into MCP-friendly structured data."""
def _render_object(self, obj: DocObject) -> Dict:
def _render_object(self, obj: DocObject) -> dict[str, Any]:
"""Recursively render a DocObject into structured MCP data."""
@staticmethod
def _json(data: Dict) -> str:
def _json(data: dict[str, Any]) -> str:
"""Serialize structured data to formatted JSON."""

View File

@@ -16,7 +16,8 @@ The renderer ensures a consistent documentation structure by:
"""
from pathlib import Path
from docforge.models import Project, Module
from docforge.models import Module, Project
class MkDocsRenderer:
@@ -65,8 +66,7 @@ class MkDocsRenderer:
# Detect packages (modules with children)
packages = {
p for p in paths
if any(other.startswith(p + ".") for other in paths)
p for p in paths if any(other.startswith(p + ".") for other in paths)
}
for module in modules:
@@ -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():
@@ -127,12 +133,12 @@ class MkDocsRenderer:
str(root_module.docstring),
)
content = (
f"# {project.name}\n\n"
f"{doc.strip()}\n"
)
content = f"# {project.name}\n\n" f"{doc.strip()}\n"
if not readme_path.exists() or readme_path.read_text(encoding="utf-8") != content:
if (
not readme_path.exists()
or readme_path.read_text(encoding="utf-8") != content
):
readme_path.write_text(
content,
encoding="utf-8",
@@ -231,10 +237,7 @@ class MkDocsRenderer:
str:
Markdown source containing a mkdocstrings directive.
"""
return (
f"# {title}\n\n"
f"::: {module_path}\n"
)
return f"# {title}\n\n" f"::: {module_path}\n"
def _ensure_root_index(
self,
@@ -255,8 +258,7 @@ class MkDocsRenderer:
if not root_index.exists():
root_index.write_text(
f"# {project.name}\n\n"
"## Modules\n\n",
f"# {project.name}\n\n" "## Modules\n\n",
encoding="utf-8",
)

View File

@@ -1,6 +1,6 @@
from pathlib import Path
from docforge.models import Project, Module
from docforge.models import Module, Project
class MkDocsRenderer:
name: str
@@ -11,14 +11,12 @@ class MkDocsRenderer:
out_dir: Path,
module_is_source: bool | None = None,
) -> None: ...
def generate_readme(
self,
project: Project,
docs_dir: Path,
module_is_source: bool | None = None,
) -> None:
) -> None: ...
def _write_module(
self,
module: Module,
@@ -26,9 +24,8 @@ class MkDocsRenderer:
out_dir: Path,
module_is_source: bool | None = None,
) -> 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: ...
def _ensure_root_index(self, project: Project, out_dir: Path) -> None: ...
def _ensure_parent_index(
self, parts: list[str], out_dir: Path, link_target: str, title: str
) -> None: ...

View File

@@ -96,9 +96,7 @@ class MCPServer:
@self.app.resource("docs://modules/{module}")
def module(module: str):
return self._read_json(
self.mcp_root / "modules" / f"{module}.json"
)
return self._read_json(self.mcp_root / "modules" / f"{module}.json")
# ------------------------------------------------------------------
# MCP tools

View File

@@ -1,9 +1,8 @@
from pathlib import Path
from typing import Literal, Any
from typing import Any, Literal
from mcp.server.fastmcp import FastMCP
class MCPServer:
"""MCP server for serving documentation."""
@@ -11,12 +10,8 @@ class MCPServer:
app: FastMCP
def __init__(self, mcp_root: Path, name: str) -> None: ...
def _read_json(self, path: Path) -> Any: ...
def _register_resources(self) -> None: ...
def _register_tools(self) -> None: ...
def run(self, transport: Literal["stdio", "sse", "streamable-http"] = ...) -> None:
"""Start the MCP server."""

View File

@@ -0,0 +1,16 @@
theme:
features:
- toc.integrate
- header.autohide
- announce.dismiss
- footer.social
- content.code.select
- content.code.line_numbers
- content.tooltips
plugins:
- search
- swagger-ui-tag
- neoteroi.mkdocsoad:
use_pymdownx: true

View File

@@ -29,26 +29,6 @@ theme:
- search.share
- search.suggest
plugins:
- search
- mkdocstrings:
handlers:
python:
paths: ["."]
options:
docstring_style: google
show_source: false
show_signature_annotations: true
separate_signature: true
merge_init_into_class: true
inherited_members: true
annotations_path: brief
show_root_heading: true
group_by_category: true
show_category_heading: true
show_object_full_path: false
show_symbol_type_heading: true
markdown_extensions:
- pymdownx.superfences
- pymdownx.inlinehilite
@@ -57,7 +37,6 @@ markdown_extensions:
- admonition
- pymdownx.details
- pymdownx.superfences
- pymdownx.highlight:
linenums: true
anchor_linenums: true
@@ -76,3 +55,6 @@ markdown_extensions:
- pymdownx.caret
- pymdownx.tilde
- pymdownx.mark
extra_css:
- https://unpkg.com/dracula-prism/dist/css/dracula-prism.css

View File

@@ -0,0 +1,19 @@
plugins:
- search
- mkdocstrings:
handlers:
python:
paths: ["."]
options:
docstring_style: google
show_source: false
show_signature_annotations: true
separate_signature: true
merge_init_into_class: true
inherited_members: true
annotations_path: brief
show_root_heading: true
group_by_category: true
show_category_heading: true
show_object_full_path: false
show_symbol_type_heading: true

View File

@@ -0,0 +1,2 @@
plugins:
- search

View File

@@ -0,0 +1,3 @@
# Api Utils
::: docforge.cli.api_utils

View File

@@ -0,0 +1,3 @@
# Api Utils
::: docforge.cli.api_utils

View File

@@ -0,0 +1,3 @@
# Commands
::: docforge.cli.commands

View File

@@ -0,0 +1,8 @@
# Cli
::: docforge.cli
- [Api Utils](api_utils.md)
- [Commands](commands.md)
- [Main](main.md)
- [Mcp Utils](mcp_utils.md)
- [Mkdocs Utils](mkdocs_utils.md)

View File

@@ -0,0 +1,3 @@
# Main
::: docforge.cli.main

View File

@@ -0,0 +1,3 @@
# Mcp Utils
::: docforge.cli.mcp_utils

View File

@@ -0,0 +1,3 @@
# Mkdocs Utils
::: docforge.cli.mkdocs_utils

View File

@@ -0,0 +1,9 @@
# Docforge
::: docforge
- [Cli](cli/)
- [Loaders](loaders/)
- [Models](models/)
- [Nav](nav/)
- [Renderers](renderers/)
- [Servers](servers/)

View File

@@ -0,0 +1,4 @@
# Loaders
::: docforge.loaders
- [Griffe Loader](griffe_loader.md)

View File

@@ -0,0 +1,6 @@
# Models
::: docforge.models
- [Module](module.md)
- [Object](object.md)
- [Project](project.md)

View File

@@ -0,0 +1,7 @@
# Nav
::: docforge.nav
- [Mkdocs](mkdocs.md)
- [Resolver](resolver.md)
- [Spec](spec.md)
- [Wiki](wiki.md)

View File

@@ -0,0 +1,3 @@
# Wiki
::: docforge.nav.wiki

View File

@@ -0,0 +1,6 @@
# Renderers
::: docforge.renderers
- [Base](base.md)
- [Mcp Renderer](mcp_renderer.md)
- [Mkdocs Renderer](mkdocs_renderer.md)

View File

@@ -0,0 +1,4 @@
# Servers
::: docforge.servers
- [Mcp Server](mcp_server.md)

View File

@@ -1,3 +1,4 @@
# docforge
::: docforge
- [Docforge](docforge/)

View File

@@ -0,0 +1,3 @@
# Griffe Loader
::: docforge.loaders.griffe_loader

View File

@@ -0,0 +1,3 @@
# Module
::: docforge.models.module

View File

@@ -0,0 +1,3 @@
# Object
::: docforge.models.object

View File

@@ -0,0 +1,3 @@
# Project
::: docforge.models.project

3
docs/lib/nav/mkdocs.md Normal file
View File

@@ -0,0 +1,3 @@
# Mkdocs
::: docforge.nav.mkdocs

3
docs/lib/nav/resolver.md Normal file
View File

@@ -0,0 +1,3 @@
# Resolver
::: docforge.nav.resolver

3
docs/lib/nav/spec.md Normal file
View File

@@ -0,0 +1,3 @@
# Spec
::: docforge.nav.spec

View File

@@ -0,0 +1,3 @@
# Base
::: docforge.renderers.base

View File

@@ -0,0 +1,3 @@
# Mcp Renderer
::: docforge.renderers.mcp_renderer

View File

@@ -0,0 +1,3 @@
# Mkdocs Renderer
::: docforge.renderers.mkdocs_renderer

View File

@@ -0,0 +1,3 @@
# Mcp Server
::: docforge.servers.mcp_server

View File

@@ -1,6 +1,6 @@
{
"project": "docforge",
"type": "docforge-model",
"modules_count": 22,
"modules_count": 23,
"source": "docforge"
}

View File

@@ -0,0 +1,102 @@
{
"module": "docforge.cli.api_utils",
"content": {
"path": "docforge.cli.api_utils",
"docstring": "# Summary\n\nUtilities for building API documentation from an OpenAPI specification.",
"objects": {
"json": {
"name": "json",
"kind": "alias",
"path": "docforge.cli.api_utils.json",
"signature": "<bound method Alias.signature of Alias('json', 'json')>",
"docstring": null
},
"dataclass": {
"name": "dataclass",
"kind": "alias",
"path": "docforge.cli.api_utils.dataclass",
"signature": "<bound method Alias.signature of Alias('dataclass', 'dataclasses.dataclass')>",
"docstring": null
},
"Path": {
"name": "Path",
"kind": "alias",
"path": "docforge.cli.api_utils.Path",
"signature": "<bound method Alias.signature of Alias('Path', 'pathlib.Path')>",
"docstring": null
},
"click": {
"name": "click",
"kind": "alias",
"path": "docforge.cli.api_utils.click",
"signature": "<bound method Alias.signature of Alias('click', 'click')>",
"docstring": null
},
"SWAGGER_SPEC_FILENAME": {
"name": "SWAGGER_SPEC_FILENAME",
"kind": "attribute",
"path": "docforge.cli.api_utils.SWAGGER_SPEC_FILENAME",
"signature": null,
"docstring": null
},
"OpenAPIMetadata": {
"name": "OpenAPIMetadata",
"kind": "class",
"path": "docforge.cli.api_utils.OpenAPIMetadata",
"signature": "<bound method Class.signature of Class('OpenAPIMetadata', 16, 30)>",
"docstring": "Metadata derived from the ``info`` block of an OpenAPI specification.\n\nAttributes:\n site_name: Spec title, used as the MkDocs site name.\n site_description: Spec description, used as the site description.\n site_author: Contact name (fallback: contact email), used as the\n site author.",
"members": {
"site_name": {
"name": "site_name",
"kind": "attribute",
"path": "docforge.cli.api_utils.OpenAPIMetadata.site_name",
"signature": null,
"docstring": null
},
"site_description": {
"name": "site_description",
"kind": "attribute",
"path": "docforge.cli.api_utils.OpenAPIMetadata.site_description",
"signature": null,
"docstring": null
},
"site_author": {
"name": "site_author",
"kind": "attribute",
"path": "docforge.cli.api_utils.OpenAPIMetadata.site_author",
"signature": null,
"docstring": null
}
}
},
"load_openapi_spec": {
"name": "load_openapi_spec",
"kind": "function",
"path": "docforge.cli.api_utils.load_openapi_spec",
"signature": "<bound method Function.signature of Function('load_openapi_spec', 33, 63)>",
"docstring": "Load and validate an OpenAPI specification from a JSON file.\n\nArgs:\n spec_path: Path to the OpenAPI JSON specification file.\n\nReturns:\n dict:\n The parsed OpenAPI specification.\n\nRaises:\n click.ClickException:\n If the file cannot be read or the ``info`` block is invalid."
},
"derive_metadata": {
"name": "derive_metadata",
"kind": "function",
"path": "docforge.cli.api_utils.derive_metadata",
"signature": "<bound method Function.signature of Function('derive_metadata', 66, 89)>",
"docstring": "Derive MkDocs site metadata from an OpenAPI spec ``info`` block.\n\nArgs:\n spec: Parsed OpenAPI specification.\n\nReturns:\n OpenAPIMetadata:\n Site name, description, and author derived from the spec."
},
"generate_api_sources": {
"name": "generate_api_sources",
"kind": "function",
"path": "docforge.cli.api_utils.generate_api_sources",
"signature": "<bound method Function.signature of Function('generate_api_sources', 92, 114)>",
"docstring": "Generate swagger-enabled Markdown sources and the spec copy.\n\nThe specification is written as ``openapi.json`` inside ``docs_dir`` and\nan ``index.md`` embedding the swagger UI is generated alongside it.\n\nArgs:\n spec: Parsed OpenAPI specification.\n docs_dir: Directory (for example ``docs/api``) where the swagger\n sources are written."
},
"Any": {
"name": "Any",
"kind": "alias",
"path": "docforge.cli.api_utils.Any",
"signature": "<bound method Alias.signature of Alias('Any', 'typing.Any')>",
"docstring": null
}
}
}
}

View File

@@ -4,13 +4,6 @@
"path": "docforge.cli.commands",
"docstring": "# Summary\n\nCommand definitions for the doc-forge CLI.\n\nProvides the CLI structure using Click, including build, serve, and tree commands.",
"objects": {
"click": {
"name": "click",
"kind": "alias",
"path": "docforge.cli.commands.click",
"signature": "<bound method Alias.signature of Alias('click', 'click')>",
"docstring": null
},
"Path": {
"name": "Path",
"kind": "alias",
@@ -18,195 +11,112 @@
"signature": "<bound method Alias.signature of Alias('Path', 'pathlib.Path')>",
"docstring": null
},
"Sequence": {
"name": "Sequence",
"click": {
"name": "click",
"kind": "alias",
"path": "docforge.cli.commands.Sequence",
"signature": "<bound method Alias.signature of Alias('Sequence', 'typing.Sequence')>",
"path": "docforge.cli.commands.click",
"signature": "<bound method Alias.signature of Alias('click', 'click')>",
"docstring": null
},
"Optional": {
"name": "Optional",
"kind": "alias",
"path": "docforge.cli.commands.Optional",
"signature": "<bound method Alias.signature of Alias('Optional', 'typing.Optional')>",
"docstring": null
},
"GriffeLoader": {
"name": "GriffeLoader",
"kind": "class",
"path": "docforge.cli.commands.GriffeLoader",
"signature": "<bound method Alias.signature of Alias('GriffeLoader', 'docforge.loaders.GriffeLoader')>",
"docstring": "Load Python modules using Griffe and convert them into doc-forge models.\n\nThis loader uses the Griffe introspection engine to analyze Python source\ncode and transform the extracted information into `Project`, `Module`,\nand `DocObject` instances used by doc-forge.",
"members": {
"load_project": {
"name": "load_project",
"kind": "function",
"path": "docforge.cli.commands.GriffeLoader.load_project",
"signature": "<bound method Alias.signature of Alias('load_project', 'docforge.loaders.griffe_loader.GriffeLoader.load_project')>",
"docstring": "Load multiple modules and assemble them into a Project model.\n\nEach module path is introspected and converted into a `Module`\ninstance. All modules are then aggregated into a single `Project`\nobject.\n\nArgs:\n module_paths (List[str]):\n List of dotted module import paths to load.\n\n project_name (str, optional):\n Optional override for the project name. Defaults to the top-level\n name of the first module.\n\n skip_import_errors (bool, optional):\n If True, modules that fail to load will be skipped instead of raising an error.\n\nReturns:\n Project:\n A populated `Project` instance containing the loaded modules.\n\nRaises:\n ValueError:\n If no module paths are provided.\n\n ImportError:\n If a module fails to load and `skip_import_errors` is False."
},
"load_module": {
"name": "load_module",
"kind": "function",
"path": "docforge.cli.commands.GriffeLoader.load_module",
"signature": "<bound method Alias.signature of Alias('load_module', 'docforge.loaders.griffe_loader.GriffeLoader.load_module')>",
"docstring": "Load and convert a single Python module.\n\nThe module is introspected using Griffe and then transformed into\na doc-forge `Module` model.\n\nArgs:\n path (str):\n Dotted import path of the module.\n\nReturns:\n Module:\n A populated `Module` instance."
}
}
},
"mkdocs_utils": {
"name": "mkdocs_utils",
"api_utils": {
"name": "api_utils",
"kind": "module",
"path": "docforge.cli.commands.mkdocs_utils",
"signature": "<bound method Alias.signature of Alias('mkdocs_utils', 'docforge.cli.mkdocs_utils')>",
"docstring": "# Summary\n\nUtilities for working with MkDocs in the doc-forge CLI.",
"path": "docforge.cli.commands.api_utils",
"signature": "<bound method Alias.signature of Alias('api_utils', 'docforge.cli.api_utils')>",
"docstring": "# Summary\n\nUtilities for building API documentation from an OpenAPI specification.",
"members": {
"json": {
"name": "json",
"kind": "alias",
"path": "docforge.cli.commands.api_utils.json",
"signature": "<bound method Alias.signature of Alias('json', 'docforge.cli.api_utils.json')>",
"docstring": null
},
"dataclass": {
"name": "dataclass",
"kind": "alias",
"path": "docforge.cli.commands.api_utils.dataclass",
"signature": "<bound method Alias.signature of Alias('dataclass', 'docforge.cli.api_utils.dataclass')>",
"docstring": null
},
"Path": {
"name": "Path",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.Path",
"signature": "<bound method Alias.signature of Alias('Path', 'docforge.cli.mkdocs_utils.Path')>",
"docstring": null
},
"resources": {
"name": "resources",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.resources",
"signature": "<bound method Alias.signature of Alias('resources', 'docforge.cli.mkdocs_utils.resources')>",
"path": "docforge.cli.commands.api_utils.Path",
"signature": "<bound method Alias.signature of Alias('Path', 'docforge.cli.api_utils.Path')>",
"docstring": null
},
"click": {
"name": "click",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.click",
"signature": "<bound method Alias.signature of Alias('click', 'docforge.cli.mkdocs_utils.click')>",
"path": "docforge.cli.commands.api_utils.click",
"signature": "<bound method Alias.signature of Alias('click', 'docforge.cli.api_utils.click')>",
"docstring": null
},
"yaml": {
"name": "yaml",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.yaml",
"signature": "<bound method Alias.signature of Alias('yaml', 'docforge.cli.mkdocs_utils.yaml')>",
"SWAGGER_SPEC_FILENAME": {
"name": "SWAGGER_SPEC_FILENAME",
"kind": "attribute",
"path": "docforge.cli.commands.api_utils.SWAGGER_SPEC_FILENAME",
"signature": "<bound method Alias.signature of Alias('SWAGGER_SPEC_FILENAME', 'docforge.cli.api_utils.SWAGGER_SPEC_FILENAME')>",
"docstring": null
},
"GriffeLoader": {
"name": "GriffeLoader",
"OpenAPIMetadata": {
"name": "OpenAPIMetadata",
"kind": "class",
"path": "docforge.cli.commands.mkdocs_utils.GriffeLoader",
"signature": "<bound method Alias.signature of Alias('GriffeLoader', 'docforge.cli.mkdocs_utils.GriffeLoader')>",
"docstring": "Load Python modules using Griffe and convert them into doc-forge models.\n\nThis loader uses the Griffe introspection engine to analyze Python source\ncode and transform the extracted information into `Project`, `Module`,\nand `DocObject` instances used by doc-forge.",
"path": "docforge.cli.commands.api_utils.OpenAPIMetadata",
"signature": "<bound method Alias.signature of Alias('OpenAPIMetadata', 'docforge.cli.api_utils.OpenAPIMetadata')>",
"docstring": "Metadata derived from the ``info`` block of an OpenAPI specification.\n\nAttributes:\n site_name: Spec title, used as the MkDocs site name.\n site_description: Spec description, used as the site description.\n site_author: Contact name (fallback: contact email), used as the\n site author.",
"members": {
"load_project": {
"name": "load_project",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.GriffeLoader.load_project",
"signature": "<bound method Alias.signature of Alias('load_project', 'docforge.loaders.griffe_loader.GriffeLoader.load_project')>",
"docstring": "Load multiple modules and assemble them into a Project model.\n\nEach module path is introspected and converted into a `Module`\ninstance. All modules are then aggregated into a single `Project`\nobject.\n\nArgs:\n module_paths (List[str]):\n List of dotted module import paths to load.\n\n project_name (str, optional):\n Optional override for the project name. Defaults to the top-level\n name of the first module.\n\n skip_import_errors (bool, optional):\n If True, modules that fail to load will be skipped instead of raising an error.\n\nReturns:\n Project:\n A populated `Project` instance containing the loaded modules.\n\nRaises:\n ValueError:\n If no module paths are provided.\n\n ImportError:\n If a module fails to load and `skip_import_errors` is False."
},
"load_module": {
"name": "load_module",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.GriffeLoader.load_module",
"signature": "<bound method Alias.signature of Alias('load_module', 'docforge.loaders.griffe_loader.GriffeLoader.load_module')>",
"docstring": "Load and convert a single Python module.\n\nThe module is introspected using Griffe and then transformed into\na doc-forge `Module` model.\n\nArgs:\n path (str):\n Dotted import path of the module.\n\nReturns:\n Module:\n A populated `Module` instance."
}
}
},
"discover_module_paths": {
"name": "discover_module_paths",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.discover_module_paths",
"signature": "<bound method Alias.signature of Alias('discover_module_paths', 'docforge.cli.mkdocs_utils.discover_module_paths')>",
"docstring": "Discover Python modules within a package directory.\n\nThe function scans the filesystem for `.py` files inside the specified\npackage and converts them into dotted module import paths.\n\nDiscovery rules:\n\n- Directories containing `__init__.py` are treated as packages.\n- Each `.py` file is treated as a module.\n- Results are returned as dotted import paths.\n\nArgs:\n module_name (str):\n Top-level package name to discover modules from.\n\n project_root (Path, optional):\n Root directory used to resolve module paths. If not provided, the\n current working directory is used.\n\nReturns:\n List[str]:\n A sorted list of unique dotted module import paths.\n\nRaises:\n FileNotFoundError:\n If the specified package directory does not exist."
},
"MkDocsRenderer": {
"name": "MkDocsRenderer",
"kind": "class",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer",
"signature": "<bound method Alias.signature of Alias('MkDocsRenderer', 'docforge.cli.mkdocs_utils.MkDocsRenderer')>",
"docstring": "Renderer that produces Markdown documentation for MkDocs.\n\nGenerated pages use mkdocstrings directives to reference Python modules,\nallowing MkDocs to render API documentation dynamically.",
"members": {
"name": {
"name": "name",
"site_name": {
"name": "site_name",
"kind": "attribute",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.name",
"signature": "<bound method Alias.signature of Alias('name', 'docforge.renderers.mkdocs_renderer.MkDocsRenderer.name')>",
"path": "docforge.cli.commands.api_utils.OpenAPIMetadata.site_name",
"signature": "<bound method Alias.signature of Alias('site_name', 'docforge.cli.api_utils.OpenAPIMetadata.site_name')>",
"docstring": null
},
"generate_sources": {
"name": "generate_sources",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.generate_sources",
"signature": "<bound method Alias.signature of Alias('generate_sources', 'docforge.renderers.mkdocs_renderer.MkDocsRenderer.generate_sources')>",
"docstring": "Generate Markdown documentation files for a project.\n\nThis method renders a documentation structure from the provided\nproject model and writes the resulting Markdown files to the\nspecified output directory.\n\nArgs:\n project (Project):\n Project model containing modules to document.\n\n out_dir (Path):\n Directory where generated Markdown files will be written.\n\n module_is_source (bool, optional):\n If True, treat the specified module as the documentation root\n rather than nesting it inside a folder."
"site_description": {
"name": "site_description",
"kind": "attribute",
"path": "docforge.cli.commands.api_utils.OpenAPIMetadata.site_description",
"signature": "<bound method Alias.signature of Alias('site_description', 'docforge.cli.api_utils.OpenAPIMetadata.site_description')>",
"docstring": null
},
"generate_readme": {
"name": "generate_readme",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.generate_readme",
"signature": "<bound method Alias.signature of Alias('generate_readme', 'docforge.renderers.mkdocs_renderer.MkDocsRenderer.generate_readme')>",
"docstring": "Generate a `README.md` file from the root module docstring.\n\nBehavior:\n\n- If `module_is_source` is True, `README.md` is written to the project\n root directory.\n- If False, README generation is currently not implemented.\n\nArgs:\n project (Project):\n Project model containing documentation metadata.\n\n docs_dir (Path):\n Directory containing generated documentation sources.\n\n module_is_source (bool, optional):\n Whether the module is treated as the project source root."
"site_author": {
"name": "site_author",
"kind": "attribute",
"path": "docforge.cli.commands.api_utils.OpenAPIMetadata.site_author",
"signature": "<bound method Alias.signature of Alias('site_author', 'docforge.cli.api_utils.OpenAPIMetadata.site_author')>",
"docstring": null
}
}
},
"load_nav_spec": {
"name": "load_nav_spec",
"load_openapi_spec": {
"name": "load_openapi_spec",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.load_nav_spec",
"signature": "<bound method Alias.signature of Alias('load_nav_spec', 'docforge.cli.mkdocs_utils.load_nav_spec')>",
"docstring": "Load a navigation specification file.\n\nThis helper function reads a YAML navigation file and constructs a\ncorresponding ``NavSpec`` instance.\n\nArgs:\n path: Path to the navigation specification file.\n\nReturns:\n A ``NavSpec`` instance representing the parsed specification.\n\nRaises:\n FileNotFoundError: If the specification file does not exist.\n ValueError: If the YAML structure is invalid."
"path": "docforge.cli.commands.api_utils.load_openapi_spec",
"signature": "<bound method Alias.signature of Alias('load_openapi_spec', 'docforge.cli.api_utils.load_openapi_spec')>",
"docstring": "Load and validate an OpenAPI specification from a JSON file.\n\nArgs:\n spec_path: Path to the OpenAPI JSON specification file.\n\nReturns:\n dict:\n The parsed OpenAPI specification.\n\nRaises:\n click.ClickException:\n If the file cannot be read or the ``info`` block is invalid."
},
"resolve_nav": {
"name": "resolve_nav",
"derive_metadata": {
"name": "derive_metadata",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.resolve_nav",
"signature": "<bound method Alias.signature of Alias('resolve_nav', 'docforge.cli.mkdocs_utils.resolve_nav')>",
"docstring": "Resolve a navigation specification against the filesystem.\n\nThe function expands glob patterns defined in a ``NavSpec`` and verifies\nthat referenced documentation files exist within the documentation root.\n\nArgs:\n spec: Navigation specification describing documentation layout.\n docs_root: Root directory containing documentation Markdown files.\n\nReturns:\n A ``ResolvedNav`` instance containing validated navigation paths.\n\nRaises:\n FileNotFoundError: If the documentation root does not exist or a\n navigation pattern does not match any files."
"path": "docforge.cli.commands.api_utils.derive_metadata",
"signature": "<bound method Alias.signature of Alias('derive_metadata', 'docforge.cli.api_utils.derive_metadata')>",
"docstring": "Derive MkDocs site metadata from an OpenAPI spec ``info`` block.\n\nArgs:\n spec: Parsed OpenAPI specification.\n\nReturns:\n OpenAPIMetadata:\n Site name, description, and author derived from the spec."
},
"MkDocsNavEmitter": {
"name": "MkDocsNavEmitter",
"kind": "class",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsNavEmitter",
"signature": "<bound method Alias.signature of Alias('MkDocsNavEmitter', 'docforge.cli.mkdocs_utils.MkDocsNavEmitter')>",
"docstring": "Emit MkDocs navigation structures from resolved navigation data.\n\nThe emitter transforms a ``ResolvedNav`` object into the YAML-compatible\nlist structure expected by the MkDocs ``nav`` configuration field.",
"members": {
"emit": {
"name": "emit",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsNavEmitter.emit",
"signature": "<bound method Alias.signature of Alias('emit', 'docforge.nav.mkdocs.MkDocsNavEmitter.emit')>",
"docstring": "Generate a navigation structure for ``mkdocs.yml``.\n\nArgs:\n nav: Resolved navigation data describing documentation groups\n and their associated Markdown files.\n\nReturns:\n A list of dictionaries representing the MkDocs navigation layout.\n Each dictionary maps a navigation label to a page or a list of\n pages."
}
}
},
"generate_sources": {
"name": "generate_sources",
"generate_api_sources": {
"name": "generate_api_sources",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.generate_sources",
"signature": "<bound method Alias.signature of Alias('generate_sources', 'docforge.cli.mkdocs_utils.generate_sources')>",
"docstring": "Generate MkDocs Markdown sources for a Python module.\n\nThis function introspects the specified module, builds the internal\ndocumentation model, and renders Markdown documentation files for\nuse with MkDocs.\n\nArgs:\n module (str):\n Python module import path used as the entry point for\n documentation generation.\n\n docs_dir (Path):\n Directory where the generated Markdown files will be written.\n\n project_name (Optional[str]):\n Optional override for the project name used in documentation metadata.\n\n module_is_source (Optional[bool]):\n If True, treat the specified module directory as the project root\n rather than a nested module."
"path": "docforge.cli.commands.api_utils.generate_api_sources",
"signature": "<bound method Alias.signature of Alias('generate_api_sources', 'docforge.cli.api_utils.generate_api_sources')>",
"docstring": "Generate swagger-enabled Markdown sources and the spec copy.\n\nThe specification is written as ``openapi.json`` inside ``docs_dir`` and\nan ``index.md`` embedding the swagger UI is generated alongside it.\n\nArgs:\n spec: Parsed OpenAPI specification.\n docs_dir: Directory (for example ``docs/api``) where the swagger\n sources are written."
},
"generate_config": {
"name": "generate_config",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.generate_config",
"signature": "<bound method Alias.signature of Alias('generate_config', 'docforge.cli.mkdocs_utils.generate_config')>",
"docstring": "Generate an `mkdocs.yml` configuration file.\n\nThe configuration is created by combining a template configuration\nwith a navigation structure derived from the docforge navigation\nspecification.\n\nArgs:\n docs_dir (Path):\n Directory containing generated documentation Markdown files.\n\n nav_file (Path):\n Path to the `docforge.nav.yml` navigation specification.\n\n template (Optional[Path]):\n Optional path to a custom MkDocs configuration template. If not\n provided, a built-in template will be used.\n\n out (Path):\n Destination path where the generated `mkdocs.yml` file will be written.\n\n site_name (str):\n Display name for the generated documentation site.\n\nRaises:\n click.FileError:\n If the navigation specification or template file cannot be found."
},
"build": {
"name": "build",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.build",
"signature": "<bound method Alias.signature of Alias('build', 'docforge.cli.mkdocs_utils.build')>",
"docstring": "Build the MkDocs documentation site.\n\nThis function loads the MkDocs configuration and runs the MkDocs\nbuild command to generate the final static documentation site.\n\nArgs:\n mkdocs_yml (Path):\n Path to the `mkdocs.yml` configuration file.\n\nRaises:\n click.ClickException:\n If the configuration file does not exist."
},
"serve": {
"name": "serve",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.serve",
"signature": "<bound method Alias.signature of Alias('serve', 'docforge.cli.mkdocs_utils.serve')>",
"docstring": "Start an MkDocs development server with live reload.\n\nThe server watches documentation files and automatically reloads\nthe site when changes are detected.\n\nArgs:\n mkdocs_yml (Path):\n Path to the `mkdocs.yml` configuration file.\n\nRaises:\n click.ClickException:\n If the configuration file does not exist."
"Any": {
"name": "Any",
"kind": "alias",
"path": "docforge.cli.commands.api_utils.Any",
"signature": "<bound method Alias.signature of Alias('Any', 'docforge.cli.api_utils.Any')>",
"docstring": null
}
}
},
@@ -330,6 +240,198 @@
}
}
},
"mkdocs_utils": {
"name": "mkdocs_utils",
"kind": "module",
"path": "docforge.cli.commands.mkdocs_utils",
"signature": "<bound method Alias.signature of Alias('mkdocs_utils', 'docforge.cli.mkdocs_utils')>",
"docstring": "# Summary\n\nUtilities for working with MkDocs in the doc-forge CLI.",
"members": {
"os": {
"name": "os",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.os",
"signature": "<bound method Alias.signature of Alias('os', 'docforge.cli.mkdocs_utils.os')>",
"docstring": null
},
"Iterable": {
"name": "Iterable",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.Iterable",
"signature": "<bound method Alias.signature of Alias('Iterable', 'docforge.cli.mkdocs_utils.Iterable')>",
"docstring": null
},
"resources": {
"name": "resources",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.resources",
"signature": "<bound method Alias.signature of Alias('resources', 'docforge.cli.mkdocs_utils.resources')>",
"docstring": null
},
"Path": {
"name": "Path",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.Path",
"signature": "<bound method Alias.signature of Alias('Path', 'docforge.cli.mkdocs_utils.Path')>",
"docstring": null
},
"click": {
"name": "click",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.click",
"signature": "<bound method Alias.signature of Alias('click', 'docforge.cli.mkdocs_utils.click')>",
"docstring": null
},
"yaml": {
"name": "yaml",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.yaml",
"signature": "<bound method Alias.signature of Alias('yaml', 'docforge.cli.mkdocs_utils.yaml')>",
"docstring": null
},
"GriffeLoader": {
"name": "GriffeLoader",
"kind": "class",
"path": "docforge.cli.commands.mkdocs_utils.GriffeLoader",
"signature": "<bound method Alias.signature of Alias('GriffeLoader', 'docforge.cli.mkdocs_utils.GriffeLoader')>",
"docstring": "Load Python modules using Griffe and convert them into doc-forge models.\n\nThis loader uses the Griffe introspection engine to analyze Python source\ncode and transform the extracted information into `Project`, `Module`,\nand `DocObject` instances used by doc-forge.",
"members": {
"load_project": {
"name": "load_project",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.GriffeLoader.load_project",
"signature": "<bound method Alias.signature of Alias('load_project', 'docforge.loaders.griffe_loader.GriffeLoader.load_project')>",
"docstring": "Load multiple modules and assemble them into a Project model.\n\nEach module path is introspected and converted into a `Module`\ninstance. All modules are then aggregated into a single `Project`\nobject.\n\nArgs:\n module_paths (List[str]):\n List of dotted module import paths to load.\n\n project_name (str, optional):\n Optional override for the project name. Defaults to the top-level\n name of the first module.\n\n skip_import_errors (bool, optional):\n If True, modules that fail to load will be skipped instead of raising an error.\n\nReturns:\n Project:\n A populated `Project` instance containing the loaded modules.\n\nRaises:\n ValueError:\n If no module paths are provided.\n\n ImportError:\n If a module fails to load and `skip_import_errors` is False."
},
"load_module": {
"name": "load_module",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.GriffeLoader.load_module",
"signature": "<bound method Alias.signature of Alias('load_module', 'docforge.loaders.griffe_loader.GriffeLoader.load_module')>",
"docstring": "Load and convert a single Python module.\n\nThe module is introspected using Griffe and then transformed into\na doc-forge `Module` model.\n\nArgs:\n path (str):\n Dotted import path of the module.\n\nReturns:\n Module:\n A populated `Module` instance."
}
}
},
"discover_module_paths": {
"name": "discover_module_paths",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.discover_module_paths",
"signature": "<bound method Alias.signature of Alias('discover_module_paths', 'docforge.cli.mkdocs_utils.discover_module_paths')>",
"docstring": "Discover Python modules within a package directory.\n\nThe function scans the filesystem for `.py` files inside the specified\npackage and converts them into dotted module import paths.\n\nDiscovery rules:\n\n- Directories containing `__init__.py` are treated as packages.\n- Each `.py` file is treated as a module.\n- Results are returned as dotted import paths.\n\nArgs:\n module_name (str):\n Top-level package name to discover modules from.\n\n project_root (Path, optional):\n Root directory used to resolve module paths. If not provided, the\n current working directory is used.\n\nReturns:\n List[str]:\n A sorted list of unique dotted module import paths.\n\nRaises:\n FileNotFoundError:\n If the specified package directory does not exist."
},
"MkDocsNavEmitter": {
"name": "MkDocsNavEmitter",
"kind": "class",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsNavEmitter",
"signature": "<bound method Alias.signature of Alias('MkDocsNavEmitter', 'docforge.cli.mkdocs_utils.MkDocsNavEmitter')>",
"docstring": "Emit MkDocs navigation structures from resolved navigation data.\n\nThe emitter transforms a ``ResolvedNav`` object into the YAML-compatible\nlist structure expected by the MkDocs ``nav`` configuration field.",
"members": {
"emit": {
"name": "emit",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsNavEmitter.emit",
"signature": "<bound method Alias.signature of Alias('emit', 'docforge.nav.mkdocs.MkDocsNavEmitter.emit')>",
"docstring": "Generate a navigation structure for ``mkdocs.yml``.\n\nArgs:\n nav: Resolved navigation data describing documentation groups\n and their associated Markdown files.\n\nReturns:\n A list of dictionaries representing the MkDocs navigation layout.\n Each dictionary maps a navigation label to a page or a list of\n pages."
}
}
},
"load_nav_spec": {
"name": "load_nav_spec",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.load_nav_spec",
"signature": "<bound method Alias.signature of Alias('load_nav_spec', 'docforge.cli.mkdocs_utils.load_nav_spec')>",
"docstring": "Load a navigation specification file.\n\nThis helper function reads a YAML navigation file and constructs a\ncorresponding ``NavSpec`` instance.\n\nArgs:\n path: Path to the navigation specification file.\n\nReturns:\n A ``NavSpec`` instance representing the parsed specification.\n\nRaises:\n FileNotFoundError: If the specification file does not exist.\n ValueError: If the YAML structure is invalid."
},
"resolve_nav": {
"name": "resolve_nav",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.resolve_nav",
"signature": "<bound method Alias.signature of Alias('resolve_nav', 'docforge.cli.mkdocs_utils.resolve_nav')>",
"docstring": "Resolve a navigation specification against the filesystem.\n\nThe function expands glob patterns defined in a ``NavSpec`` and verifies\nthat referenced documentation files exist within the documentation root.\n\nArgs:\n spec: Navigation specification describing documentation layout.\n docs_root: Root directory containing documentation Markdown files.\n\nReturns:\n A ``ResolvedNav`` instance containing validated navigation paths.\n\nRaises:\n FileNotFoundError: If the documentation root does not exist or a\n navigation pattern does not match any files."
},
"MkDocsRenderer": {
"name": "MkDocsRenderer",
"kind": "class",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer",
"signature": "<bound method Alias.signature of Alias('MkDocsRenderer', 'docforge.cli.mkdocs_utils.MkDocsRenderer')>",
"docstring": "Renderer that produces Markdown documentation for MkDocs.\n\nGenerated pages use mkdocstrings directives to reference Python modules,\nallowing MkDocs to render API documentation dynamically.",
"members": {
"name": {
"name": "name",
"kind": "attribute",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.name",
"signature": "<bound method Alias.signature of Alias('name', 'docforge.renderers.mkdocs_renderer.MkDocsRenderer.name')>",
"docstring": null
},
"generate_sources": {
"name": "generate_sources",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.generate_sources",
"signature": "<bound method Alias.signature of Alias('generate_sources', 'docforge.renderers.mkdocs_renderer.MkDocsRenderer.generate_sources')>",
"docstring": "Generate Markdown documentation files for a project.\n\nThis method renders a documentation structure from the provided\nproject model and writes the resulting Markdown files to the\nspecified output directory.\n\nArgs:\n project (Project):\n Project model containing modules to document.\n\n out_dir (Path):\n Directory where generated Markdown files will be written.\n\n module_is_source (bool, optional):\n If True, treat the specified module as the documentation root\n rather than nesting it inside a folder."
},
"generate_readme": {
"name": "generate_readme",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.generate_readme",
"signature": "<bound method Alias.signature of Alias('generate_readme', 'docforge.renderers.mkdocs_renderer.MkDocsRenderer.generate_readme')>",
"docstring": "Generate a `README.md` file from the root module docstring.\n\nBehavior:\n\n- If `module_is_source` is True, `README.md` is written to the project\n root directory.\n- If False, README generation is currently not implemented.\n\nArgs:\n project (Project):\n Project model containing documentation metadata.\n\n docs_dir (Path):\n Directory containing generated documentation sources.\n\n module_is_source (Optional[bool]):\n Whether the module is treated as the project source root.\n\n readme_dir (Optional[Path]):\n Directory where the generated README.md should be written.\n Defaults to the parent of `docs_dir`."
}
}
},
"generate_sources": {
"name": "generate_sources",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.generate_sources",
"signature": "<bound method Alias.signature of Alias('generate_sources', 'docforge.cli.mkdocs_utils.generate_sources')>",
"docstring": "Generate MkDocs Markdown sources for a Python module.\n\nThis function introspects the specified module, builds the internal\ndocumentation model, and renders Markdown documentation files for\nuse with MkDocs.\n\nArgs:\n module (str):\n Python module import path used as the entry point for\n documentation generation.\n\n docs_dir (Path):\n Directory where the generated Markdown files will be written.\n\n project_name (Optional[str]):\n Optional override for the project name used in documentation metadata.\n\n module_is_source (Optional[bool]):\n If True, treat the specified module directory as the project root\n rather than a nested module.\n\n readme_dir (Optional[Path]):\n Directory where the generated README.md should be written. If not\n provided, defaults to the parent of ``docs_dir``."
},
"generate_config": {
"name": "generate_config",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.generate_config",
"signature": "<bound method Alias.signature of Alias('generate_config', 'docforge.cli.mkdocs_utils.generate_config')>",
"docstring": "Generate an `mkdocs.yml` configuration file.\n\nThe configuration is created by combining a template configuration\nwith a navigation structure derived from the docforge navigation\nspecification.\n\nThe ``docs_dir`` is always written relative to the MkDocs root and is\nexpected to be the shared documentation parent (for example ``docs``),\nwith generated sources nested under ``lib/`` or ``api/`` subdirectories.\n\nArgs:\n docs_dir (Path):\n Shared documentation root used as the MkDocs ``docs_dir``.\n\n nav_file (Path):\n Path to the `docforge.nav.yml` navigation specification.\n\n template (Optional[Path]):\n Optional path to a fully custom MkDocs configuration template.\n If not provided, built-in templates are merged; the provided\n template replaces the built-in templates entirely.\n\n out (Path):\n Destination path where the generated `mkdocs.yml` file will be written.\n\n site_name (str):\n Display name for the generated documentation site.\n\n modes (Optional[Iterable[str]]):\n Documentation modes to enable. Each mode contributes its own\n built-in template fragment (for example ``lib`` or ``api``),\n merged on top of the shared ``mkdocs.common.yml`` template.\n\n site_description (Optional[str]):\n Optional site description written into the configuration.\n\n site_author (Optional[str]):\n Optional site author written into the configuration.\n\nRaises:\n click.FileError:\n If the navigation specification or template file cannot be found."
},
"build": {
"name": "build",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.build",
"signature": "<bound method Alias.signature of Alias('build', 'docforge.cli.mkdocs_utils.build')>",
"docstring": "Build the MkDocs documentation site.\n\nThis function loads the MkDocs configuration and runs the MkDocs\nbuild command to generate the final static documentation site.\n\nArgs:\n mkdocs_yml (Path):\n Path to the `mkdocs.yml` configuration file.\n\nRaises:\n click.ClickException:\n If the configuration file does not exist."
},
"serve": {
"name": "serve",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.serve",
"signature": "<bound method Alias.signature of Alias('serve', 'docforge.cli.mkdocs_utils.serve')>",
"docstring": "Start an MkDocs development server with live reload.\n\nThe server watches documentation files and automatically reloads\nthe site when changes are detected.\n\nArgs:\n mkdocs_yml (Path):\n Path to the `mkdocs.yml` configuration file.\n\nRaises:\n click.ClickException:\n If the configuration file does not exist."
}
}
},
"GriffeLoader": {
"name": "GriffeLoader",
"kind": "class",
"path": "docforge.cli.commands.GriffeLoader",
"signature": "<bound method Alias.signature of Alias('GriffeLoader', 'docforge.loaders.GriffeLoader')>",
"docstring": "Load Python modules using Griffe and convert them into doc-forge models.\n\nThis loader uses the Griffe introspection engine to analyze Python source\ncode and transform the extracted information into `Project`, `Module`,\nand `DocObject` instances used by doc-forge.",
"members": {
"load_project": {
"name": "load_project",
"kind": "function",
"path": "docforge.cli.commands.GriffeLoader.load_project",
"signature": "<bound method Alias.signature of Alias('load_project', 'docforge.loaders.griffe_loader.GriffeLoader.load_project')>",
"docstring": "Load multiple modules and assemble them into a Project model.\n\nEach module path is introspected and converted into a `Module`\ninstance. All modules are then aggregated into a single `Project`\nobject.\n\nArgs:\n module_paths (List[str]):\n List of dotted module import paths to load.\n\n project_name (str, optional):\n Optional override for the project name. Defaults to the top-level\n name of the first module.\n\n skip_import_errors (bool, optional):\n If True, modules that fail to load will be skipped instead of raising an error.\n\nReturns:\n Project:\n A populated `Project` instance containing the loaded modules.\n\nRaises:\n ValueError:\n If no module paths are provided.\n\n ImportError:\n If a module fails to load and `skip_import_errors` is False."
},
"load_module": {
"name": "load_module",
"kind": "function",
"path": "docforge.cli.commands.GriffeLoader.load_module",
"signature": "<bound method Alias.signature of Alias('load_module', 'docforge.loaders.griffe_loader.GriffeLoader.load_module')>",
"docstring": "Load and convert a single Python module.\n\nThe module is introspected using Griffe and then transformed into\na doc-forge `Module` model.\n\nArgs:\n path (str):\n Dotted import path of the module.\n\nReturns:\n Module:\n A populated `Module` instance."
}
}
},
"cli": {
"name": "cli",
"kind": "attribute",
@@ -341,36 +443,36 @@
"name": "build",
"kind": "function",
"path": "docforge.cli.commands.build",
"signature": "<bound method Function.signature of Function('build', 28, 136)>",
"docstring": "Build documentation artifacts.\n\nThis command performs the full documentation build pipeline:\n\n1. Introspects the Python project using Griffe\n2. Generates renderer-specific documentation sources\n3. Optionally builds the final documentation output\n\nDepending on the selected options, the build can target:\n\n- MkDocs static documentation sites\n- MCP structured documentation resources\n\nArgs:\n mcp (bool):\n Enable MCP documentation generation.\n\n mkdocs (bool):\n Enable MkDocs documentation generation.\n\n module_is_source (bool):\n Treat the specified module directory as the project root.\n\n module (Optional[str]):\n Python module import path to document.\n\n project_name (Optional[str]):\n Optional override for the project name.\n\n site_name (Optional[str]):\n Display name for the MkDocs site.\n\n docs_dir (Path):\n Directory where Markdown documentation sources will be generated.\n\n nav_file (Path):\n Path to the navigation specification file.\n\n template (Optional[Path]):\n Optional custom MkDocs configuration template.\n\n mkdocs_yml (Path):\n Output path for the generated MkDocs configuration.\n\n out_dir (Path):\n Output directory for generated MCP resources.\n\nRaises:\n click.UsageError:\n If required options are missing or conflicting."
"signature": "<bound method Function.signature of Function('build', 28, 223)>",
"docstring": "Build documentation artifacts.\n\nThis command performs the full documentation build pipeline:\nstyle of the selected platform, generates renderer-specific\ndocumentation sources, and optionally builds the final output.\n\nDepending on the selected options, the build can target:\n\n- MkDocs static documentation sites for library reference docs\n- Swagger-enabled API docs generated from an OpenAPI spec\n- MCP structured documentation resources\n\nArgs:\n mcp (bool):\n Enable MCP documentation generation.\n\n mkdocs (bool):\n Enable MkDocs library documentation generation.\n\n api (bool):\n Enable API documentation generation from an OpenAPI spec.\n\n module_is_source (bool):\n Treat the specified module directory as the project root.\n\n module (Optional[str]):\n Python module import path to document.\n\n openapi_spec (Optional[Path]):\n Path to the OpenAPI JSON specification used for API docs.\n\n project_name (Optional[str]):\n Optional override for the project name.\n\n site_name (Optional[str]):\n Display name for the MkDocs site.\n\n docs_dir (Path):\n Shared documentation root used as the MkDocs ``docs_dir``.\n\n nav_file (Path):\n Path to the navigation specification file.\n\n template (Optional[Path]):\n Optional custom MkDocs configuration template.\n\n mkdocs_yml (Path):\n Output path for the generated MkDocs configuration.\n\n out_dir (Path):\n Output directory for generated MCP resources.\n\nRaises:\n click.UsageError:\n If required options are missing or conflicting."
},
"serve": {
"name": "serve",
"kind": "function",
"path": "docforge.cli.commands.serve",
"signature": "<bound method Function.signature of Function('serve', 139, 190)>",
"signature": "<bound method Function.signature of Function('serve', 226, 287)>",
"docstring": "Serve generated documentation locally.\n\nDepending on the selected mode, this command starts either:\n\n- A MkDocs development server for browsing documentation\n- An MCP server exposing structured documentation resources\n\nArgs:\n mcp (bool):\n Serve documentation using the MCP server.\n\n mkdocs (bool):\n Serve the MkDocs development site.\n\n module (Optional[str]):\n Python module import path to serve via MCP.\n\n mkdocs_yml (Path):\n Path to the MkDocs configuration file.\n\n out_dir (Path):\n Root directory containing MCP documentation resources.\n\nRaises:\n click.UsageError:\n If invalid or conflicting options are provided."
},
"tree": {
"name": "tree",
"kind": "function",
"path": "docforge.cli.commands.tree",
"signature": "<bound method Function.signature of Function('tree', 193, 229)>",
"signature": "<bound method Function.signature of Function('tree', 290, 326)>",
"docstring": "Display the documentation object tree for a module.\n\nThis command introspects the specified module and prints a\nhierarchical representation of the discovered documentation\nobjects, including modules, classes, functions, and members.\n\nArgs:\n module (str):\n Python module import path to introspect.\n\n project_name (Optional[str]):\n Optional name to display as the project root."
},
"Group": {
"name": "Group",
"kind": "alias",
"path": "docforge.cli.commands.Group",
"signature": "<bound method Alias.signature of Alias('Group', 'click.core.Group')>",
"docstring": null
},
"Any": {
"name": "Any",
"kind": "alias",
"path": "docforge.cli.commands.Any",
"signature": "<bound method Alias.signature of Alias('Any', 'typing.Any')>",
"docstring": null
},
"Group": {
"name": "Group",
"kind": "alias",
"path": "docforge.cli.commands.Group",
"signature": "<bound method Alias.signature of Alias('Group', 'click.core.Group')>",
"docstring": null
}
}
}

View File

@@ -27,6 +27,108 @@
}
}
},
"api_utils": {
"name": "api_utils",
"kind": "module",
"path": "docforge.cli.api_utils",
"signature": null,
"docstring": "# Summary\n\nUtilities for building API documentation from an OpenAPI specification.",
"members": {
"json": {
"name": "json",
"kind": "alias",
"path": "docforge.cli.api_utils.json",
"signature": "<bound method Alias.signature of Alias('json', 'json')>",
"docstring": null
},
"dataclass": {
"name": "dataclass",
"kind": "alias",
"path": "docforge.cli.api_utils.dataclass",
"signature": "<bound method Alias.signature of Alias('dataclass', 'dataclasses.dataclass')>",
"docstring": null
},
"Path": {
"name": "Path",
"kind": "alias",
"path": "docforge.cli.api_utils.Path",
"signature": "<bound method Alias.signature of Alias('Path', 'pathlib.Path')>",
"docstring": null
},
"click": {
"name": "click",
"kind": "alias",
"path": "docforge.cli.api_utils.click",
"signature": "<bound method Alias.signature of Alias('click', 'click')>",
"docstring": null
},
"SWAGGER_SPEC_FILENAME": {
"name": "SWAGGER_SPEC_FILENAME",
"kind": "attribute",
"path": "docforge.cli.api_utils.SWAGGER_SPEC_FILENAME",
"signature": null,
"docstring": null
},
"OpenAPIMetadata": {
"name": "OpenAPIMetadata",
"kind": "class",
"path": "docforge.cli.api_utils.OpenAPIMetadata",
"signature": "<bound method Class.signature of Class('OpenAPIMetadata', 16, 30)>",
"docstring": "Metadata derived from the ``info`` block of an OpenAPI specification.\n\nAttributes:\n site_name: Spec title, used as the MkDocs site name.\n site_description: Spec description, used as the site description.\n site_author: Contact name (fallback: contact email), used as the\n site author.",
"members": {
"site_name": {
"name": "site_name",
"kind": "attribute",
"path": "docforge.cli.api_utils.OpenAPIMetadata.site_name",
"signature": null,
"docstring": null
},
"site_description": {
"name": "site_description",
"kind": "attribute",
"path": "docforge.cli.api_utils.OpenAPIMetadata.site_description",
"signature": null,
"docstring": null
},
"site_author": {
"name": "site_author",
"kind": "attribute",
"path": "docforge.cli.api_utils.OpenAPIMetadata.site_author",
"signature": null,
"docstring": null
}
}
},
"load_openapi_spec": {
"name": "load_openapi_spec",
"kind": "function",
"path": "docforge.cli.api_utils.load_openapi_spec",
"signature": "<bound method Function.signature of Function('load_openapi_spec', 33, 63)>",
"docstring": "Load and validate an OpenAPI specification from a JSON file.\n\nArgs:\n spec_path: Path to the OpenAPI JSON specification file.\n\nReturns:\n dict:\n The parsed OpenAPI specification.\n\nRaises:\n click.ClickException:\n If the file cannot be read or the ``info`` block is invalid."
},
"derive_metadata": {
"name": "derive_metadata",
"kind": "function",
"path": "docforge.cli.api_utils.derive_metadata",
"signature": "<bound method Function.signature of Function('derive_metadata', 66, 89)>",
"docstring": "Derive MkDocs site metadata from an OpenAPI spec ``info`` block.\n\nArgs:\n spec: Parsed OpenAPI specification.\n\nReturns:\n OpenAPIMetadata:\n Site name, description, and author derived from the spec."
},
"generate_api_sources": {
"name": "generate_api_sources",
"kind": "function",
"path": "docforge.cli.api_utils.generate_api_sources",
"signature": "<bound method Function.signature of Function('generate_api_sources', 92, 114)>",
"docstring": "Generate swagger-enabled Markdown sources and the spec copy.\n\nThe specification is written as ``openapi.json`` inside ``docs_dir`` and\nan ``index.md`` embedding the swagger UI is generated alongside it.\n\nArgs:\n spec: Parsed OpenAPI specification.\n docs_dir: Directory (for example ``docs/api``) where the swagger\n sources are written."
},
"Any": {
"name": "Any",
"kind": "alias",
"path": "docforge.cli.api_utils.Any",
"signature": "<bound method Alias.signature of Alias('Any', 'typing.Any')>",
"docstring": null
}
}
},
"commands": {
"name": "commands",
"kind": "module",
@@ -34,13 +136,6 @@
"signature": null,
"docstring": "# Summary\n\nCommand definitions for the doc-forge CLI.\n\nProvides the CLI structure using Click, including build, serve, and tree commands.",
"members": {
"click": {
"name": "click",
"kind": "alias",
"path": "docforge.cli.commands.click",
"signature": "<bound method Alias.signature of Alias('click', 'click')>",
"docstring": null
},
"Path": {
"name": "Path",
"kind": "alias",
@@ -48,195 +143,112 @@
"signature": "<bound method Alias.signature of Alias('Path', 'pathlib.Path')>",
"docstring": null
},
"Sequence": {
"name": "Sequence",
"click": {
"name": "click",
"kind": "alias",
"path": "docforge.cli.commands.Sequence",
"signature": "<bound method Alias.signature of Alias('Sequence', 'typing.Sequence')>",
"path": "docforge.cli.commands.click",
"signature": "<bound method Alias.signature of Alias('click', 'click')>",
"docstring": null
},
"Optional": {
"name": "Optional",
"kind": "alias",
"path": "docforge.cli.commands.Optional",
"signature": "<bound method Alias.signature of Alias('Optional', 'typing.Optional')>",
"docstring": null
},
"GriffeLoader": {
"name": "GriffeLoader",
"kind": "class",
"path": "docforge.cli.commands.GriffeLoader",
"signature": "<bound method Alias.signature of Alias('GriffeLoader', 'docforge.loaders.GriffeLoader')>",
"docstring": "Load Python modules using Griffe and convert them into doc-forge models.\n\nThis loader uses the Griffe introspection engine to analyze Python source\ncode and transform the extracted information into `Project`, `Module`,\nand `DocObject` instances used by doc-forge.",
"members": {
"load_project": {
"name": "load_project",
"kind": "function",
"path": "docforge.cli.commands.GriffeLoader.load_project",
"signature": "<bound method Alias.signature of Alias('load_project', 'docforge.loaders.griffe_loader.GriffeLoader.load_project')>",
"docstring": "Load multiple modules and assemble them into a Project model.\n\nEach module path is introspected and converted into a `Module`\ninstance. All modules are then aggregated into a single `Project`\nobject.\n\nArgs:\n module_paths (List[str]):\n List of dotted module import paths to load.\n\n project_name (str, optional):\n Optional override for the project name. Defaults to the top-level\n name of the first module.\n\n skip_import_errors (bool, optional):\n If True, modules that fail to load will be skipped instead of raising an error.\n\nReturns:\n Project:\n A populated `Project` instance containing the loaded modules.\n\nRaises:\n ValueError:\n If no module paths are provided.\n\n ImportError:\n If a module fails to load and `skip_import_errors` is False."
},
"load_module": {
"name": "load_module",
"kind": "function",
"path": "docforge.cli.commands.GriffeLoader.load_module",
"signature": "<bound method Alias.signature of Alias('load_module', 'docforge.loaders.griffe_loader.GriffeLoader.load_module')>",
"docstring": "Load and convert a single Python module.\n\nThe module is introspected using Griffe and then transformed into\na doc-forge `Module` model.\n\nArgs:\n path (str):\n Dotted import path of the module.\n\nReturns:\n Module:\n A populated `Module` instance."
}
}
},
"mkdocs_utils": {
"name": "mkdocs_utils",
"api_utils": {
"name": "api_utils",
"kind": "module",
"path": "docforge.cli.commands.mkdocs_utils",
"signature": "<bound method Alias.signature of Alias('mkdocs_utils', 'docforge.cli.mkdocs_utils')>",
"docstring": "# Summary\n\nUtilities for working with MkDocs in the doc-forge CLI.",
"path": "docforge.cli.commands.api_utils",
"signature": "<bound method Alias.signature of Alias('api_utils', 'docforge.cli.api_utils')>",
"docstring": "# Summary\n\nUtilities for building API documentation from an OpenAPI specification.",
"members": {
"json": {
"name": "json",
"kind": "alias",
"path": "docforge.cli.commands.api_utils.json",
"signature": "<bound method Alias.signature of Alias('json', 'docforge.cli.api_utils.json')>",
"docstring": null
},
"dataclass": {
"name": "dataclass",
"kind": "alias",
"path": "docforge.cli.commands.api_utils.dataclass",
"signature": "<bound method Alias.signature of Alias('dataclass', 'docforge.cli.api_utils.dataclass')>",
"docstring": null
},
"Path": {
"name": "Path",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.Path",
"signature": "<bound method Alias.signature of Alias('Path', 'docforge.cli.mkdocs_utils.Path')>",
"docstring": null
},
"resources": {
"name": "resources",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.resources",
"signature": "<bound method Alias.signature of Alias('resources', 'docforge.cli.mkdocs_utils.resources')>",
"path": "docforge.cli.commands.api_utils.Path",
"signature": "<bound method Alias.signature of Alias('Path', 'docforge.cli.api_utils.Path')>",
"docstring": null
},
"click": {
"name": "click",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.click",
"signature": "<bound method Alias.signature of Alias('click', 'docforge.cli.mkdocs_utils.click')>",
"path": "docforge.cli.commands.api_utils.click",
"signature": "<bound method Alias.signature of Alias('click', 'docforge.cli.api_utils.click')>",
"docstring": null
},
"yaml": {
"name": "yaml",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.yaml",
"signature": "<bound method Alias.signature of Alias('yaml', 'docforge.cli.mkdocs_utils.yaml')>",
"SWAGGER_SPEC_FILENAME": {
"name": "SWAGGER_SPEC_FILENAME",
"kind": "attribute",
"path": "docforge.cli.commands.api_utils.SWAGGER_SPEC_FILENAME",
"signature": "<bound method Alias.signature of Alias('SWAGGER_SPEC_FILENAME', 'docforge.cli.api_utils.SWAGGER_SPEC_FILENAME')>",
"docstring": null
},
"GriffeLoader": {
"name": "GriffeLoader",
"OpenAPIMetadata": {
"name": "OpenAPIMetadata",
"kind": "class",
"path": "docforge.cli.commands.mkdocs_utils.GriffeLoader",
"signature": "<bound method Alias.signature of Alias('GriffeLoader', 'docforge.cli.mkdocs_utils.GriffeLoader')>",
"docstring": "Load Python modules using Griffe and convert them into doc-forge models.\n\nThis loader uses the Griffe introspection engine to analyze Python source\ncode and transform the extracted information into `Project`, `Module`,\nand `DocObject` instances used by doc-forge.",
"path": "docforge.cli.commands.api_utils.OpenAPIMetadata",
"signature": "<bound method Alias.signature of Alias('OpenAPIMetadata', 'docforge.cli.api_utils.OpenAPIMetadata')>",
"docstring": "Metadata derived from the ``info`` block of an OpenAPI specification.\n\nAttributes:\n site_name: Spec title, used as the MkDocs site name.\n site_description: Spec description, used as the site description.\n site_author: Contact name (fallback: contact email), used as the\n site author.",
"members": {
"load_project": {
"name": "load_project",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.GriffeLoader.load_project",
"signature": "<bound method Alias.signature of Alias('load_project', 'docforge.loaders.griffe_loader.GriffeLoader.load_project')>",
"docstring": "Load multiple modules and assemble them into a Project model.\n\nEach module path is introspected and converted into a `Module`\ninstance. All modules are then aggregated into a single `Project`\nobject.\n\nArgs:\n module_paths (List[str]):\n List of dotted module import paths to load.\n\n project_name (str, optional):\n Optional override for the project name. Defaults to the top-level\n name of the first module.\n\n skip_import_errors (bool, optional):\n If True, modules that fail to load will be skipped instead of raising an error.\n\nReturns:\n Project:\n A populated `Project` instance containing the loaded modules.\n\nRaises:\n ValueError:\n If no module paths are provided.\n\n ImportError:\n If a module fails to load and `skip_import_errors` is False."
},
"load_module": {
"name": "load_module",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.GriffeLoader.load_module",
"signature": "<bound method Alias.signature of Alias('load_module', 'docforge.loaders.griffe_loader.GriffeLoader.load_module')>",
"docstring": "Load and convert a single Python module.\n\nThe module is introspected using Griffe and then transformed into\na doc-forge `Module` model.\n\nArgs:\n path (str):\n Dotted import path of the module.\n\nReturns:\n Module:\n A populated `Module` instance."
}
}
},
"discover_module_paths": {
"name": "discover_module_paths",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.discover_module_paths",
"signature": "<bound method Alias.signature of Alias('discover_module_paths', 'docforge.cli.mkdocs_utils.discover_module_paths')>",
"docstring": "Discover Python modules within a package directory.\n\nThe function scans the filesystem for `.py` files inside the specified\npackage and converts them into dotted module import paths.\n\nDiscovery rules:\n\n- Directories containing `__init__.py` are treated as packages.\n- Each `.py` file is treated as a module.\n- Results are returned as dotted import paths.\n\nArgs:\n module_name (str):\n Top-level package name to discover modules from.\n\n project_root (Path, optional):\n Root directory used to resolve module paths. If not provided, the\n current working directory is used.\n\nReturns:\n List[str]:\n A sorted list of unique dotted module import paths.\n\nRaises:\n FileNotFoundError:\n If the specified package directory does not exist."
},
"MkDocsRenderer": {
"name": "MkDocsRenderer",
"kind": "class",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer",
"signature": "<bound method Alias.signature of Alias('MkDocsRenderer', 'docforge.cli.mkdocs_utils.MkDocsRenderer')>",
"docstring": "Renderer that produces Markdown documentation for MkDocs.\n\nGenerated pages use mkdocstrings directives to reference Python modules,\nallowing MkDocs to render API documentation dynamically.",
"members": {
"name": {
"name": "name",
"site_name": {
"name": "site_name",
"kind": "attribute",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.name",
"signature": "<bound method Alias.signature of Alias('name', 'docforge.renderers.mkdocs_renderer.MkDocsRenderer.name')>",
"path": "docforge.cli.commands.api_utils.OpenAPIMetadata.site_name",
"signature": "<bound method Alias.signature of Alias('site_name', 'docforge.cli.api_utils.OpenAPIMetadata.site_name')>",
"docstring": null
},
"generate_sources": {
"name": "generate_sources",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.generate_sources",
"signature": "<bound method Alias.signature of Alias('generate_sources', 'docforge.renderers.mkdocs_renderer.MkDocsRenderer.generate_sources')>",
"docstring": "Generate Markdown documentation files for a project.\n\nThis method renders a documentation structure from the provided\nproject model and writes the resulting Markdown files to the\nspecified output directory.\n\nArgs:\n project (Project):\n Project model containing modules to document.\n\n out_dir (Path):\n Directory where generated Markdown files will be written.\n\n module_is_source (bool, optional):\n If True, treat the specified module as the documentation root\n rather than nesting it inside a folder."
"site_description": {
"name": "site_description",
"kind": "attribute",
"path": "docforge.cli.commands.api_utils.OpenAPIMetadata.site_description",
"signature": "<bound method Alias.signature of Alias('site_description', 'docforge.cli.api_utils.OpenAPIMetadata.site_description')>",
"docstring": null
},
"generate_readme": {
"name": "generate_readme",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.generate_readme",
"signature": "<bound method Alias.signature of Alias('generate_readme', 'docforge.renderers.mkdocs_renderer.MkDocsRenderer.generate_readme')>",
"docstring": "Generate a `README.md` file from the root module docstring.\n\nBehavior:\n\n- If `module_is_source` is True, `README.md` is written to the project\n root directory.\n- If False, README generation is currently not implemented.\n\nArgs:\n project (Project):\n Project model containing documentation metadata.\n\n docs_dir (Path):\n Directory containing generated documentation sources.\n\n module_is_source (bool, optional):\n Whether the module is treated as the project source root."
"site_author": {
"name": "site_author",
"kind": "attribute",
"path": "docforge.cli.commands.api_utils.OpenAPIMetadata.site_author",
"signature": "<bound method Alias.signature of Alias('site_author', 'docforge.cli.api_utils.OpenAPIMetadata.site_author')>",
"docstring": null
}
}
},
"load_nav_spec": {
"name": "load_nav_spec",
"load_openapi_spec": {
"name": "load_openapi_spec",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.load_nav_spec",
"signature": "<bound method Alias.signature of Alias('load_nav_spec', 'docforge.cli.mkdocs_utils.load_nav_spec')>",
"docstring": "Load a navigation specification file.\n\nThis helper function reads a YAML navigation file and constructs a\ncorresponding ``NavSpec`` instance.\n\nArgs:\n path: Path to the navigation specification file.\n\nReturns:\n A ``NavSpec`` instance representing the parsed specification.\n\nRaises:\n FileNotFoundError: If the specification file does not exist.\n ValueError: If the YAML structure is invalid."
"path": "docforge.cli.commands.api_utils.load_openapi_spec",
"signature": "<bound method Alias.signature of Alias('load_openapi_spec', 'docforge.cli.api_utils.load_openapi_spec')>",
"docstring": "Load and validate an OpenAPI specification from a JSON file.\n\nArgs:\n spec_path: Path to the OpenAPI JSON specification file.\n\nReturns:\n dict:\n The parsed OpenAPI specification.\n\nRaises:\n click.ClickException:\n If the file cannot be read or the ``info`` block is invalid."
},
"resolve_nav": {
"name": "resolve_nav",
"derive_metadata": {
"name": "derive_metadata",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.resolve_nav",
"signature": "<bound method Alias.signature of Alias('resolve_nav', 'docforge.cli.mkdocs_utils.resolve_nav')>",
"docstring": "Resolve a navigation specification against the filesystem.\n\nThe function expands glob patterns defined in a ``NavSpec`` and verifies\nthat referenced documentation files exist within the documentation root.\n\nArgs:\n spec: Navigation specification describing documentation layout.\n docs_root: Root directory containing documentation Markdown files.\n\nReturns:\n A ``ResolvedNav`` instance containing validated navigation paths.\n\nRaises:\n FileNotFoundError: If the documentation root does not exist or a\n navigation pattern does not match any files."
"path": "docforge.cli.commands.api_utils.derive_metadata",
"signature": "<bound method Alias.signature of Alias('derive_metadata', 'docforge.cli.api_utils.derive_metadata')>",
"docstring": "Derive MkDocs site metadata from an OpenAPI spec ``info`` block.\n\nArgs:\n spec: Parsed OpenAPI specification.\n\nReturns:\n OpenAPIMetadata:\n Site name, description, and author derived from the spec."
},
"MkDocsNavEmitter": {
"name": "MkDocsNavEmitter",
"kind": "class",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsNavEmitter",
"signature": "<bound method Alias.signature of Alias('MkDocsNavEmitter', 'docforge.cli.mkdocs_utils.MkDocsNavEmitter')>",
"docstring": "Emit MkDocs navigation structures from resolved navigation data.\n\nThe emitter transforms a ``ResolvedNav`` object into the YAML-compatible\nlist structure expected by the MkDocs ``nav`` configuration field.",
"members": {
"emit": {
"name": "emit",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsNavEmitter.emit",
"signature": "<bound method Alias.signature of Alias('emit', 'docforge.nav.mkdocs.MkDocsNavEmitter.emit')>",
"docstring": "Generate a navigation structure for ``mkdocs.yml``.\n\nArgs:\n nav: Resolved navigation data describing documentation groups\n and their associated Markdown files.\n\nReturns:\n A list of dictionaries representing the MkDocs navigation layout.\n Each dictionary maps a navigation label to a page or a list of\n pages."
}
}
},
"generate_sources": {
"name": "generate_sources",
"generate_api_sources": {
"name": "generate_api_sources",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.generate_sources",
"signature": "<bound method Alias.signature of Alias('generate_sources', 'docforge.cli.mkdocs_utils.generate_sources')>",
"docstring": "Generate MkDocs Markdown sources for a Python module.\n\nThis function introspects the specified module, builds the internal\ndocumentation model, and renders Markdown documentation files for\nuse with MkDocs.\n\nArgs:\n module (str):\n Python module import path used as the entry point for\n documentation generation.\n\n docs_dir (Path):\n Directory where the generated Markdown files will be written.\n\n project_name (Optional[str]):\n Optional override for the project name used in documentation metadata.\n\n module_is_source (Optional[bool]):\n If True, treat the specified module directory as the project root\n rather than a nested module."
"path": "docforge.cli.commands.api_utils.generate_api_sources",
"signature": "<bound method Alias.signature of Alias('generate_api_sources', 'docforge.cli.api_utils.generate_api_sources')>",
"docstring": "Generate swagger-enabled Markdown sources and the spec copy.\n\nThe specification is written as ``openapi.json`` inside ``docs_dir`` and\nan ``index.md`` embedding the swagger UI is generated alongside it.\n\nArgs:\n spec: Parsed OpenAPI specification.\n docs_dir: Directory (for example ``docs/api``) where the swagger\n sources are written."
},
"generate_config": {
"name": "generate_config",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.generate_config",
"signature": "<bound method Alias.signature of Alias('generate_config', 'docforge.cli.mkdocs_utils.generate_config')>",
"docstring": "Generate an `mkdocs.yml` configuration file.\n\nThe configuration is created by combining a template configuration\nwith a navigation structure derived from the docforge navigation\nspecification.\n\nArgs:\n docs_dir (Path):\n Directory containing generated documentation Markdown files.\n\n nav_file (Path):\n Path to the `docforge.nav.yml` navigation specification.\n\n template (Optional[Path]):\n Optional path to a custom MkDocs configuration template. If not\n provided, a built-in template will be used.\n\n out (Path):\n Destination path where the generated `mkdocs.yml` file will be written.\n\n site_name (str):\n Display name for the generated documentation site.\n\nRaises:\n click.FileError:\n If the navigation specification or template file cannot be found."
},
"build": {
"name": "build",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.build",
"signature": "<bound method Alias.signature of Alias('build', 'docforge.cli.mkdocs_utils.build')>",
"docstring": "Build the MkDocs documentation site.\n\nThis function loads the MkDocs configuration and runs the MkDocs\nbuild command to generate the final static documentation site.\n\nArgs:\n mkdocs_yml (Path):\n Path to the `mkdocs.yml` configuration file.\n\nRaises:\n click.ClickException:\n If the configuration file does not exist."
},
"serve": {
"name": "serve",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.serve",
"signature": "<bound method Alias.signature of Alias('serve', 'docforge.cli.mkdocs_utils.serve')>",
"docstring": "Start an MkDocs development server with live reload.\n\nThe server watches documentation files and automatically reloads\nthe site when changes are detected.\n\nArgs:\n mkdocs_yml (Path):\n Path to the `mkdocs.yml` configuration file.\n\nRaises:\n click.ClickException:\n If the configuration file does not exist."
"Any": {
"name": "Any",
"kind": "alias",
"path": "docforge.cli.commands.api_utils.Any",
"signature": "<bound method Alias.signature of Alias('Any', 'docforge.cli.api_utils.Any')>",
"docstring": null
}
}
},
@@ -360,6 +372,198 @@
}
}
},
"mkdocs_utils": {
"name": "mkdocs_utils",
"kind": "module",
"path": "docforge.cli.commands.mkdocs_utils",
"signature": "<bound method Alias.signature of Alias('mkdocs_utils', 'docforge.cli.mkdocs_utils')>",
"docstring": "# Summary\n\nUtilities for working with MkDocs in the doc-forge CLI.",
"members": {
"os": {
"name": "os",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.os",
"signature": "<bound method Alias.signature of Alias('os', 'docforge.cli.mkdocs_utils.os')>",
"docstring": null
},
"Iterable": {
"name": "Iterable",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.Iterable",
"signature": "<bound method Alias.signature of Alias('Iterable', 'docforge.cli.mkdocs_utils.Iterable')>",
"docstring": null
},
"resources": {
"name": "resources",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.resources",
"signature": "<bound method Alias.signature of Alias('resources', 'docforge.cli.mkdocs_utils.resources')>",
"docstring": null
},
"Path": {
"name": "Path",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.Path",
"signature": "<bound method Alias.signature of Alias('Path', 'docforge.cli.mkdocs_utils.Path')>",
"docstring": null
},
"click": {
"name": "click",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.click",
"signature": "<bound method Alias.signature of Alias('click', 'docforge.cli.mkdocs_utils.click')>",
"docstring": null
},
"yaml": {
"name": "yaml",
"kind": "alias",
"path": "docforge.cli.commands.mkdocs_utils.yaml",
"signature": "<bound method Alias.signature of Alias('yaml', 'docforge.cli.mkdocs_utils.yaml')>",
"docstring": null
},
"GriffeLoader": {
"name": "GriffeLoader",
"kind": "class",
"path": "docforge.cli.commands.mkdocs_utils.GriffeLoader",
"signature": "<bound method Alias.signature of Alias('GriffeLoader', 'docforge.cli.mkdocs_utils.GriffeLoader')>",
"docstring": "Load Python modules using Griffe and convert them into doc-forge models.\n\nThis loader uses the Griffe introspection engine to analyze Python source\ncode and transform the extracted information into `Project`, `Module`,\nand `DocObject` instances used by doc-forge.",
"members": {
"load_project": {
"name": "load_project",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.GriffeLoader.load_project",
"signature": "<bound method Alias.signature of Alias('load_project', 'docforge.loaders.griffe_loader.GriffeLoader.load_project')>",
"docstring": "Load multiple modules and assemble them into a Project model.\n\nEach module path is introspected and converted into a `Module`\ninstance. All modules are then aggregated into a single `Project`\nobject.\n\nArgs:\n module_paths (List[str]):\n List of dotted module import paths to load.\n\n project_name (str, optional):\n Optional override for the project name. Defaults to the top-level\n name of the first module.\n\n skip_import_errors (bool, optional):\n If True, modules that fail to load will be skipped instead of raising an error.\n\nReturns:\n Project:\n A populated `Project` instance containing the loaded modules.\n\nRaises:\n ValueError:\n If no module paths are provided.\n\n ImportError:\n If a module fails to load and `skip_import_errors` is False."
},
"load_module": {
"name": "load_module",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.GriffeLoader.load_module",
"signature": "<bound method Alias.signature of Alias('load_module', 'docforge.loaders.griffe_loader.GriffeLoader.load_module')>",
"docstring": "Load and convert a single Python module.\n\nThe module is introspected using Griffe and then transformed into\na doc-forge `Module` model.\n\nArgs:\n path (str):\n Dotted import path of the module.\n\nReturns:\n Module:\n A populated `Module` instance."
}
}
},
"discover_module_paths": {
"name": "discover_module_paths",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.discover_module_paths",
"signature": "<bound method Alias.signature of Alias('discover_module_paths', 'docforge.cli.mkdocs_utils.discover_module_paths')>",
"docstring": "Discover Python modules within a package directory.\n\nThe function scans the filesystem for `.py` files inside the specified\npackage and converts them into dotted module import paths.\n\nDiscovery rules:\n\n- Directories containing `__init__.py` are treated as packages.\n- Each `.py` file is treated as a module.\n- Results are returned as dotted import paths.\n\nArgs:\n module_name (str):\n Top-level package name to discover modules from.\n\n project_root (Path, optional):\n Root directory used to resolve module paths. If not provided, the\n current working directory is used.\n\nReturns:\n List[str]:\n A sorted list of unique dotted module import paths.\n\nRaises:\n FileNotFoundError:\n If the specified package directory does not exist."
},
"MkDocsNavEmitter": {
"name": "MkDocsNavEmitter",
"kind": "class",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsNavEmitter",
"signature": "<bound method Alias.signature of Alias('MkDocsNavEmitter', 'docforge.cli.mkdocs_utils.MkDocsNavEmitter')>",
"docstring": "Emit MkDocs navigation structures from resolved navigation data.\n\nThe emitter transforms a ``ResolvedNav`` object into the YAML-compatible\nlist structure expected by the MkDocs ``nav`` configuration field.",
"members": {
"emit": {
"name": "emit",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsNavEmitter.emit",
"signature": "<bound method Alias.signature of Alias('emit', 'docforge.nav.mkdocs.MkDocsNavEmitter.emit')>",
"docstring": "Generate a navigation structure for ``mkdocs.yml``.\n\nArgs:\n nav: Resolved navigation data describing documentation groups\n and their associated Markdown files.\n\nReturns:\n A list of dictionaries representing the MkDocs navigation layout.\n Each dictionary maps a navigation label to a page or a list of\n pages."
}
}
},
"load_nav_spec": {
"name": "load_nav_spec",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.load_nav_spec",
"signature": "<bound method Alias.signature of Alias('load_nav_spec', 'docforge.cli.mkdocs_utils.load_nav_spec')>",
"docstring": "Load a navigation specification file.\n\nThis helper function reads a YAML navigation file and constructs a\ncorresponding ``NavSpec`` instance.\n\nArgs:\n path: Path to the navigation specification file.\n\nReturns:\n A ``NavSpec`` instance representing the parsed specification.\n\nRaises:\n FileNotFoundError: If the specification file does not exist.\n ValueError: If the YAML structure is invalid."
},
"resolve_nav": {
"name": "resolve_nav",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.resolve_nav",
"signature": "<bound method Alias.signature of Alias('resolve_nav', 'docforge.cli.mkdocs_utils.resolve_nav')>",
"docstring": "Resolve a navigation specification against the filesystem.\n\nThe function expands glob patterns defined in a ``NavSpec`` and verifies\nthat referenced documentation files exist within the documentation root.\n\nArgs:\n spec: Navigation specification describing documentation layout.\n docs_root: Root directory containing documentation Markdown files.\n\nReturns:\n A ``ResolvedNav`` instance containing validated navigation paths.\n\nRaises:\n FileNotFoundError: If the documentation root does not exist or a\n navigation pattern does not match any files."
},
"MkDocsRenderer": {
"name": "MkDocsRenderer",
"kind": "class",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer",
"signature": "<bound method Alias.signature of Alias('MkDocsRenderer', 'docforge.cli.mkdocs_utils.MkDocsRenderer')>",
"docstring": "Renderer that produces Markdown documentation for MkDocs.\n\nGenerated pages use mkdocstrings directives to reference Python modules,\nallowing MkDocs to render API documentation dynamically.",
"members": {
"name": {
"name": "name",
"kind": "attribute",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.name",
"signature": "<bound method Alias.signature of Alias('name', 'docforge.renderers.mkdocs_renderer.MkDocsRenderer.name')>",
"docstring": null
},
"generate_sources": {
"name": "generate_sources",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.generate_sources",
"signature": "<bound method Alias.signature of Alias('generate_sources', 'docforge.renderers.mkdocs_renderer.MkDocsRenderer.generate_sources')>",
"docstring": "Generate Markdown documentation files for a project.\n\nThis method renders a documentation structure from the provided\nproject model and writes the resulting Markdown files to the\nspecified output directory.\n\nArgs:\n project (Project):\n Project model containing modules to document.\n\n out_dir (Path):\n Directory where generated Markdown files will be written.\n\n module_is_source (bool, optional):\n If True, treat the specified module as the documentation root\n rather than nesting it inside a folder."
},
"generate_readme": {
"name": "generate_readme",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.generate_readme",
"signature": "<bound method Alias.signature of Alias('generate_readme', 'docforge.renderers.mkdocs_renderer.MkDocsRenderer.generate_readme')>",
"docstring": "Generate a `README.md` file from the root module docstring.\n\nBehavior:\n\n- If `module_is_source` is True, `README.md` is written to the project\n root directory.\n- If False, README generation is currently not implemented.\n\nArgs:\n project (Project):\n Project model containing documentation metadata.\n\n docs_dir (Path):\n Directory containing generated documentation sources.\n\n module_is_source (Optional[bool]):\n Whether the module is treated as the project source root.\n\n readme_dir (Optional[Path]):\n Directory where the generated README.md should be written.\n Defaults to the parent of `docs_dir`."
}
}
},
"generate_sources": {
"name": "generate_sources",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.generate_sources",
"signature": "<bound method Alias.signature of Alias('generate_sources', 'docforge.cli.mkdocs_utils.generate_sources')>",
"docstring": "Generate MkDocs Markdown sources for a Python module.\n\nThis function introspects the specified module, builds the internal\ndocumentation model, and renders Markdown documentation files for\nuse with MkDocs.\n\nArgs:\n module (str):\n Python module import path used as the entry point for\n documentation generation.\n\n docs_dir (Path):\n Directory where the generated Markdown files will be written.\n\n project_name (Optional[str]):\n Optional override for the project name used in documentation metadata.\n\n module_is_source (Optional[bool]):\n If True, treat the specified module directory as the project root\n rather than a nested module.\n\n readme_dir (Optional[Path]):\n Directory where the generated README.md should be written. If not\n provided, defaults to the parent of ``docs_dir``."
},
"generate_config": {
"name": "generate_config",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.generate_config",
"signature": "<bound method Alias.signature of Alias('generate_config', 'docforge.cli.mkdocs_utils.generate_config')>",
"docstring": "Generate an `mkdocs.yml` configuration file.\n\nThe configuration is created by combining a template configuration\nwith a navigation structure derived from the docforge navigation\nspecification.\n\nThe ``docs_dir`` is always written relative to the MkDocs root and is\nexpected to be the shared documentation parent (for example ``docs``),\nwith generated sources nested under ``lib/`` or ``api/`` subdirectories.\n\nArgs:\n docs_dir (Path):\n Shared documentation root used as the MkDocs ``docs_dir``.\n\n nav_file (Path):\n Path to the `docforge.nav.yml` navigation specification.\n\n template (Optional[Path]):\n Optional path to a fully custom MkDocs configuration template.\n If not provided, built-in templates are merged; the provided\n template replaces the built-in templates entirely.\n\n out (Path):\n Destination path where the generated `mkdocs.yml` file will be written.\n\n site_name (str):\n Display name for the generated documentation site.\n\n modes (Optional[Iterable[str]]):\n Documentation modes to enable. Each mode contributes its own\n built-in template fragment (for example ``lib`` or ``api``),\n merged on top of the shared ``mkdocs.common.yml`` template.\n\n site_description (Optional[str]):\n Optional site description written into the configuration.\n\n site_author (Optional[str]):\n Optional site author written into the configuration.\n\nRaises:\n click.FileError:\n If the navigation specification or template file cannot be found."
},
"build": {
"name": "build",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.build",
"signature": "<bound method Alias.signature of Alias('build', 'docforge.cli.mkdocs_utils.build')>",
"docstring": "Build the MkDocs documentation site.\n\nThis function loads the MkDocs configuration and runs the MkDocs\nbuild command to generate the final static documentation site.\n\nArgs:\n mkdocs_yml (Path):\n Path to the `mkdocs.yml` configuration file.\n\nRaises:\n click.ClickException:\n If the configuration file does not exist."
},
"serve": {
"name": "serve",
"kind": "function",
"path": "docforge.cli.commands.mkdocs_utils.serve",
"signature": "<bound method Alias.signature of Alias('serve', 'docforge.cli.mkdocs_utils.serve')>",
"docstring": "Start an MkDocs development server with live reload.\n\nThe server watches documentation files and automatically reloads\nthe site when changes are detected.\n\nArgs:\n mkdocs_yml (Path):\n Path to the `mkdocs.yml` configuration file.\n\nRaises:\n click.ClickException:\n If the configuration file does not exist."
}
}
},
"GriffeLoader": {
"name": "GriffeLoader",
"kind": "class",
"path": "docforge.cli.commands.GriffeLoader",
"signature": "<bound method Alias.signature of Alias('GriffeLoader', 'docforge.loaders.GriffeLoader')>",
"docstring": "Load Python modules using Griffe and convert them into doc-forge models.\n\nThis loader uses the Griffe introspection engine to analyze Python source\ncode and transform the extracted information into `Project`, `Module`,\nand `DocObject` instances used by doc-forge.",
"members": {
"load_project": {
"name": "load_project",
"kind": "function",
"path": "docforge.cli.commands.GriffeLoader.load_project",
"signature": "<bound method Alias.signature of Alias('load_project', 'docforge.loaders.griffe_loader.GriffeLoader.load_project')>",
"docstring": "Load multiple modules and assemble them into a Project model.\n\nEach module path is introspected and converted into a `Module`\ninstance. All modules are then aggregated into a single `Project`\nobject.\n\nArgs:\n module_paths (List[str]):\n List of dotted module import paths to load.\n\n project_name (str, optional):\n Optional override for the project name. Defaults to the top-level\n name of the first module.\n\n skip_import_errors (bool, optional):\n If True, modules that fail to load will be skipped instead of raising an error.\n\nReturns:\n Project:\n A populated `Project` instance containing the loaded modules.\n\nRaises:\n ValueError:\n If no module paths are provided.\n\n ImportError:\n If a module fails to load and `skip_import_errors` is False."
},
"load_module": {
"name": "load_module",
"kind": "function",
"path": "docforge.cli.commands.GriffeLoader.load_module",
"signature": "<bound method Alias.signature of Alias('load_module', 'docforge.loaders.griffe_loader.GriffeLoader.load_module')>",
"docstring": "Load and convert a single Python module.\n\nThe module is introspected using Griffe and then transformed into\na doc-forge `Module` model.\n\nArgs:\n path (str):\n Dotted import path of the module.\n\nReturns:\n Module:\n A populated `Module` instance."
}
}
},
"cli": {
"name": "cli",
"kind": "attribute",
@@ -371,36 +575,36 @@
"name": "build",
"kind": "function",
"path": "docforge.cli.commands.build",
"signature": "<bound method Function.signature of Function('build', 28, 136)>",
"docstring": "Build documentation artifacts.\n\nThis command performs the full documentation build pipeline:\n\n1. Introspects the Python project using Griffe\n2. Generates renderer-specific documentation sources\n3. Optionally builds the final documentation output\n\nDepending on the selected options, the build can target:\n\n- MkDocs static documentation sites\n- MCP structured documentation resources\n\nArgs:\n mcp (bool):\n Enable MCP documentation generation.\n\n mkdocs (bool):\n Enable MkDocs documentation generation.\n\n module_is_source (bool):\n Treat the specified module directory as the project root.\n\n module (Optional[str]):\n Python module import path to document.\n\n project_name (Optional[str]):\n Optional override for the project name.\n\n site_name (Optional[str]):\n Display name for the MkDocs site.\n\n docs_dir (Path):\n Directory where Markdown documentation sources will be generated.\n\n nav_file (Path):\n Path to the navigation specification file.\n\n template (Optional[Path]):\n Optional custom MkDocs configuration template.\n\n mkdocs_yml (Path):\n Output path for the generated MkDocs configuration.\n\n out_dir (Path):\n Output directory for generated MCP resources.\n\nRaises:\n click.UsageError:\n If required options are missing or conflicting."
"signature": "<bound method Function.signature of Function('build', 28, 223)>",
"docstring": "Build documentation artifacts.\n\nThis command performs the full documentation build pipeline:\nstyle of the selected platform, generates renderer-specific\ndocumentation sources, and optionally builds the final output.\n\nDepending on the selected options, the build can target:\n\n- MkDocs static documentation sites for library reference docs\n- Swagger-enabled API docs generated from an OpenAPI spec\n- MCP structured documentation resources\n\nArgs:\n mcp (bool):\n Enable MCP documentation generation.\n\n mkdocs (bool):\n Enable MkDocs library documentation generation.\n\n api (bool):\n Enable API documentation generation from an OpenAPI spec.\n\n module_is_source (bool):\n Treat the specified module directory as the project root.\n\n module (Optional[str]):\n Python module import path to document.\n\n openapi_spec (Optional[Path]):\n Path to the OpenAPI JSON specification used for API docs.\n\n project_name (Optional[str]):\n Optional override for the project name.\n\n site_name (Optional[str]):\n Display name for the MkDocs site.\n\n docs_dir (Path):\n Shared documentation root used as the MkDocs ``docs_dir``.\n\n nav_file (Path):\n Path to the navigation specification file.\n\n template (Optional[Path]):\n Optional custom MkDocs configuration template.\n\n mkdocs_yml (Path):\n Output path for the generated MkDocs configuration.\n\n out_dir (Path):\n Output directory for generated MCP resources.\n\nRaises:\n click.UsageError:\n If required options are missing or conflicting."
},
"serve": {
"name": "serve",
"kind": "function",
"path": "docforge.cli.commands.serve",
"signature": "<bound method Function.signature of Function('serve', 139, 190)>",
"signature": "<bound method Function.signature of Function('serve', 226, 287)>",
"docstring": "Serve generated documentation locally.\n\nDepending on the selected mode, this command starts either:\n\n- A MkDocs development server for browsing documentation\n- An MCP server exposing structured documentation resources\n\nArgs:\n mcp (bool):\n Serve documentation using the MCP server.\n\n mkdocs (bool):\n Serve the MkDocs development site.\n\n module (Optional[str]):\n Python module import path to serve via MCP.\n\n mkdocs_yml (Path):\n Path to the MkDocs configuration file.\n\n out_dir (Path):\n Root directory containing MCP documentation resources.\n\nRaises:\n click.UsageError:\n If invalid or conflicting options are provided."
},
"tree": {
"name": "tree",
"kind": "function",
"path": "docforge.cli.commands.tree",
"signature": "<bound method Function.signature of Function('tree', 193, 229)>",
"signature": "<bound method Function.signature of Function('tree', 290, 326)>",
"docstring": "Display the documentation object tree for a module.\n\nThis command introspects the specified module and prints a\nhierarchical representation of the discovered documentation\nobjects, including modules, classes, functions, and members.\n\nArgs:\n module (str):\n Python module import path to introspect.\n\n project_name (Optional[str]):\n Optional name to display as the project root."
},
"Group": {
"name": "Group",
"kind": "alias",
"path": "docforge.cli.commands.Group",
"signature": "<bound method Alias.signature of Alias('Group', 'click.core.Group')>",
"docstring": null
},
"Any": {
"name": "Any",
"kind": "alias",
"path": "docforge.cli.commands.Any",
"signature": "<bound method Alias.signature of Alias('Any', 'typing.Any')>",
"docstring": null
},
"Group": {
"name": "Group",
"kind": "alias",
"path": "docforge.cli.commands.Group",
"signature": "<bound method Alias.signature of Alias('Group', 'click.core.Group')>",
"docstring": null
}
}
},
@@ -512,14 +716,14 @@
"name": "generate_resources",
"kind": "function",
"path": "docforge.cli.mcp_utils.generate_resources",
"signature": "<bound method Function.signature of Function('generate_resources', 14, 40)>",
"signature": "<bound method Function.signature of Function('generate_resources', 16, 42)>",
"docstring": "Generate MCP documentation resources from a Python module.\n\nThe function performs project introspection, builds the internal\ndocumentation model, and renders MCP-compatible JSON resources\nto the specified output directory.\n\nArgs:\n module (str):\n Python module import path used as the entry point for\n documentation generation.\n\n project_name (Optional[str]):\n Optional override for the project name used in generated\n documentation metadata.\n\n out_dir (Path):\n Directory where MCP resources (index.json, nav.json, and module data)\n will be written."
},
"serve": {
"name": "serve",
"kind": "function",
"path": "docforge.cli.mcp_utils.serve",
"signature": "<bound method Function.signature of Function('serve', 43, 80)>",
"signature": "<bound method Function.signature of Function('serve', 45, 82)>",
"docstring": "Start an MCP server for a pre-generated documentation bundle.\n\nThe server exposes documentation resources such as project metadata,\nnavigation structure, and module documentation through MCP endpoints.\n\nArgs:\n module (str):\n Python module import path used to identify the served\n documentation instance.\n\n mcp_root (Path):\n Path to the directory containing the MCP documentation\n bundle (index.json, nav.json, and modules/).\n\nRaises:\n click.ClickException:\n If the MCP documentation bundle is missing required files or directories."
}
}
@@ -531,11 +735,18 @@
"signature": null,
"docstring": "# Summary\n\nUtilities for working with MkDocs in the doc-forge CLI.",
"members": {
"Path": {
"name": "Path",
"os": {
"name": "os",
"kind": "alias",
"path": "docforge.cli.mkdocs_utils.Path",
"signature": "<bound method Alias.signature of Alias('Path', 'pathlib.Path')>",
"path": "docforge.cli.mkdocs_utils.os",
"signature": "<bound method Alias.signature of Alias('os', 'os')>",
"docstring": null
},
"Iterable": {
"name": "Iterable",
"kind": "alias",
"path": "docforge.cli.mkdocs_utils.Iterable",
"signature": "<bound method Alias.signature of Alias('Iterable', 'collections.abc.Iterable')>",
"docstring": null
},
"resources": {
@@ -545,6 +756,13 @@
"signature": "<bound method Alias.signature of Alias('resources', 'importlib.resources')>",
"docstring": null
},
"Path": {
"name": "Path",
"kind": "alias",
"path": "docforge.cli.mkdocs_utils.Path",
"signature": "<bound method Alias.signature of Alias('Path', 'pathlib.Path')>",
"docstring": null
},
"click": {
"name": "click",
"kind": "alias",
@@ -589,6 +807,36 @@
"signature": "<bound method Alias.signature of Alias('discover_module_paths', 'docforge.loaders.discover_module_paths')>",
"docstring": "Discover Python modules within a package directory.\n\nThe function scans the filesystem for `.py` files inside the specified\npackage and converts them into dotted module import paths.\n\nDiscovery rules:\n\n- Directories containing `__init__.py` are treated as packages.\n- Each `.py` file is treated as a module.\n- Results are returned as dotted import paths.\n\nArgs:\n module_name (str):\n Top-level package name to discover modules from.\n\n project_root (Path, optional):\n Root directory used to resolve module paths. If not provided, the\n current working directory is used.\n\nReturns:\n List[str]:\n A sorted list of unique dotted module import paths.\n\nRaises:\n FileNotFoundError:\n If the specified package directory does not exist."
},
"MkDocsNavEmitter": {
"name": "MkDocsNavEmitter",
"kind": "class",
"path": "docforge.cli.mkdocs_utils.MkDocsNavEmitter",
"signature": "<bound method Alias.signature of Alias('MkDocsNavEmitter', 'docforge.nav.MkDocsNavEmitter')>",
"docstring": "Emit MkDocs navigation structures from resolved navigation data.\n\nThe emitter transforms a ``ResolvedNav`` object into the YAML-compatible\nlist structure expected by the MkDocs ``nav`` configuration field.",
"members": {
"emit": {
"name": "emit",
"kind": "function",
"path": "docforge.cli.mkdocs_utils.MkDocsNavEmitter.emit",
"signature": "<bound method Alias.signature of Alias('emit', 'docforge.nav.mkdocs.MkDocsNavEmitter.emit')>",
"docstring": "Generate a navigation structure for ``mkdocs.yml``.\n\nArgs:\n nav: Resolved navigation data describing documentation groups\n and their associated Markdown files.\n\nReturns:\n A list of dictionaries representing the MkDocs navigation layout.\n Each dictionary maps a navigation label to a page or a list of\n pages."
}
}
},
"load_nav_spec": {
"name": "load_nav_spec",
"kind": "function",
"path": "docforge.cli.mkdocs_utils.load_nav_spec",
"signature": "<bound method Alias.signature of Alias('load_nav_spec', 'docforge.nav.load_nav_spec')>",
"docstring": "Load a navigation specification file.\n\nThis helper function reads a YAML navigation file and constructs a\ncorresponding ``NavSpec`` instance.\n\nArgs:\n path: Path to the navigation specification file.\n\nReturns:\n A ``NavSpec`` instance representing the parsed specification.\n\nRaises:\n FileNotFoundError: If the specification file does not exist.\n ValueError: If the YAML structure is invalid."
},
"resolve_nav": {
"name": "resolve_nav",
"kind": "function",
"path": "docforge.cli.mkdocs_utils.resolve_nav",
"signature": "<bound method Alias.signature of Alias('resolve_nav', 'docforge.nav.resolve_nav')>",
"docstring": "Resolve a navigation specification against the filesystem.\n\nThe function expands glob patterns defined in a ``NavSpec`` and verifies\nthat referenced documentation files exist within the documentation root.\n\nArgs:\n spec: Navigation specification describing documentation layout.\n docs_root: Root directory containing documentation Markdown files.\n\nReturns:\n A ``ResolvedNav`` instance containing validated navigation paths.\n\nRaises:\n FileNotFoundError: If the documentation root does not exist or a\n navigation pattern does not match any files."
},
"MkDocsRenderer": {
"name": "MkDocsRenderer",
"kind": "class",
@@ -615,37 +863,7 @@
"kind": "function",
"path": "docforge.cli.mkdocs_utils.MkDocsRenderer.generate_readme",
"signature": "<bound method Alias.signature of Alias('generate_readme', 'docforge.renderers.mkdocs_renderer.MkDocsRenderer.generate_readme')>",
"docstring": "Generate a `README.md` file from the root module docstring.\n\nBehavior:\n\n- If `module_is_source` is True, `README.md` is written to the project\n root directory.\n- If False, README generation is currently not implemented.\n\nArgs:\n project (Project):\n Project model containing documentation metadata.\n\n docs_dir (Path):\n Directory containing generated documentation sources.\n\n module_is_source (bool, optional):\n Whether the module is treated as the project source root."
}
}
},
"load_nav_spec": {
"name": "load_nav_spec",
"kind": "function",
"path": "docforge.cli.mkdocs_utils.load_nav_spec",
"signature": "<bound method Alias.signature of Alias('load_nav_spec', 'docforge.nav.load_nav_spec')>",
"docstring": "Load a navigation specification file.\n\nThis helper function reads a YAML navigation file and constructs a\ncorresponding ``NavSpec`` instance.\n\nArgs:\n path: Path to the navigation specification file.\n\nReturns:\n A ``NavSpec`` instance representing the parsed specification.\n\nRaises:\n FileNotFoundError: If the specification file does not exist.\n ValueError: If the YAML structure is invalid."
},
"resolve_nav": {
"name": "resolve_nav",
"kind": "function",
"path": "docforge.cli.mkdocs_utils.resolve_nav",
"signature": "<bound method Alias.signature of Alias('resolve_nav', 'docforge.nav.resolve_nav')>",
"docstring": "Resolve a navigation specification against the filesystem.\n\nThe function expands glob patterns defined in a ``NavSpec`` and verifies\nthat referenced documentation files exist within the documentation root.\n\nArgs:\n spec: Navigation specification describing documentation layout.\n docs_root: Root directory containing documentation Markdown files.\n\nReturns:\n A ``ResolvedNav`` instance containing validated navigation paths.\n\nRaises:\n FileNotFoundError: If the documentation root does not exist or a\n navigation pattern does not match any files."
},
"MkDocsNavEmitter": {
"name": "MkDocsNavEmitter",
"kind": "class",
"path": "docforge.cli.mkdocs_utils.MkDocsNavEmitter",
"signature": "<bound method Alias.signature of Alias('MkDocsNavEmitter', 'docforge.nav.MkDocsNavEmitter')>",
"docstring": "Emit MkDocs navigation structures from resolved navigation data.\n\nThe emitter transforms a ``ResolvedNav`` object into the YAML-compatible\nlist structure expected by the MkDocs ``nav`` configuration field.",
"members": {
"emit": {
"name": "emit",
"kind": "function",
"path": "docforge.cli.mkdocs_utils.MkDocsNavEmitter.emit",
"signature": "<bound method Alias.signature of Alias('emit', 'docforge.nav.mkdocs.MkDocsNavEmitter.emit')>",
"docstring": "Generate a navigation structure for ``mkdocs.yml``.\n\nArgs:\n nav: Resolved navigation data describing documentation groups\n and their associated Markdown files.\n\nReturns:\n A list of dictionaries representing the MkDocs navigation layout.\n Each dictionary maps a navigation label to a page or a list of\n pages."
"docstring": "Generate a `README.md` file from the root module docstring.\n\nBehavior:\n\n- If `module_is_source` is True, `README.md` is written to the project\n root directory.\n- If False, README generation is currently not implemented.\n\nArgs:\n project (Project):\n Project model containing documentation metadata.\n\n docs_dir (Path):\n Directory containing generated documentation sources.\n\n module_is_source (Optional[bool]):\n Whether the module is treated as the project source root.\n\n readme_dir (Optional[Path]):\n Directory where the generated README.md should be written.\n Defaults to the parent of `docs_dir`."
}
}
},
@@ -653,28 +871,28 @@
"name": "generate_sources",
"kind": "function",
"path": "docforge.cli.mkdocs_utils.generate_sources",
"signature": "<bound method Function.signature of Function('generate_sources', 16, 59)>",
"docstring": "Generate MkDocs Markdown sources for a Python module.\n\nThis function introspects the specified module, builds the internal\ndocumentation model, and renders Markdown documentation files for\nuse with MkDocs.\n\nArgs:\n module (str):\n Python module import path used as the entry point for\n documentation generation.\n\n docs_dir (Path):\n Directory where the generated Markdown files will be written.\n\n project_name (Optional[str]):\n Optional override for the project name used in documentation metadata.\n\n module_is_source (Optional[bool]):\n If True, treat the specified module directory as the project root\n rather than a nested module."
"signature": "<bound method Function.signature of Function('generate_sources', 20, 69)>",
"docstring": "Generate MkDocs Markdown sources for a Python module.\n\nThis function introspects the specified module, builds the internal\ndocumentation model, and renders Markdown documentation files for\nuse with MkDocs.\n\nArgs:\n module (str):\n Python module import path used as the entry point for\n documentation generation.\n\n docs_dir (Path):\n Directory where the generated Markdown files will be written.\n\n project_name (Optional[str]):\n Optional override for the project name used in documentation metadata.\n\n module_is_source (Optional[bool]):\n If True, treat the specified module directory as the project root\n rather than a nested module.\n\n readme_dir (Optional[Path]):\n Directory where the generated README.md should be written. If not\n provided, defaults to the parent of ``docs_dir``."
},
"generate_config": {
"name": "generate_config",
"kind": "function",
"path": "docforge.cli.mkdocs_utils.generate_config",
"signature": "<bound method Function.signature of Function('generate_config', 62, 120)>",
"docstring": "Generate an `mkdocs.yml` configuration file.\n\nThe configuration is created by combining a template configuration\nwith a navigation structure derived from the docforge navigation\nspecification.\n\nArgs:\n docs_dir (Path):\n Directory containing generated documentation Markdown files.\n\n nav_file (Path):\n Path to the `docforge.nav.yml` navigation specification.\n\n template (Optional[Path]):\n Optional path to a custom MkDocs configuration template. If not\n provided, a built-in template will be used.\n\n out (Path):\n Destination path where the generated `mkdocs.yml` file will be written.\n\n site_name (str):\n Display name for the generated documentation site.\n\nRaises:\n click.FileError:\n If the navigation specification or template file cannot be found."
"signature": "<bound method Function.signature of Function('generate_config', 72, 150)>",
"docstring": "Generate an `mkdocs.yml` configuration file.\n\nThe configuration is created by combining a template configuration\nwith a navigation structure derived from the docforge navigation\nspecification.\n\nThe ``docs_dir`` is always written relative to the MkDocs root and is\nexpected to be the shared documentation parent (for example ``docs``),\nwith generated sources nested under ``lib/`` or ``api/`` subdirectories.\n\nArgs:\n docs_dir (Path):\n Shared documentation root used as the MkDocs ``docs_dir``.\n\n nav_file (Path):\n Path to the `docforge.nav.yml` navigation specification.\n\n template (Optional[Path]):\n Optional path to a fully custom MkDocs configuration template.\n If not provided, built-in templates are merged; the provided\n template replaces the built-in templates entirely.\n\n out (Path):\n Destination path where the generated `mkdocs.yml` file will be written.\n\n site_name (str):\n Display name for the generated documentation site.\n\n modes (Optional[Iterable[str]]):\n Documentation modes to enable. Each mode contributes its own\n built-in template fragment (for example ``lib`` or ``api``),\n merged on top of the shared ``mkdocs.common.yml`` template.\n\n site_description (Optional[str]):\n Optional site description written into the configuration.\n\n site_author (Optional[str]):\n Optional site author written into the configuration.\n\nRaises:\n click.FileError:\n If the navigation specification or template file cannot be found."
},
"build": {
"name": "build",
"kind": "function",
"path": "docforge.cli.mkdocs_utils.build",
"signature": "<bound method Function.signature of Function('build', 123, 144)>",
"signature": "<bound method Function.signature of Function('build', 272, 293)>",
"docstring": "Build the MkDocs documentation site.\n\nThis function loads the MkDocs configuration and runs the MkDocs\nbuild command to generate the final static documentation site.\n\nArgs:\n mkdocs_yml (Path):\n Path to the `mkdocs.yml` configuration file.\n\nRaises:\n click.ClickException:\n If the configuration file does not exist."
},
"serve": {
"name": "serve",
"kind": "function",
"path": "docforge.cli.mkdocs_utils.serve",
"signature": "<bound method Function.signature of Function('serve', 147, 166)>",
"signature": "<bound method Function.signature of Function('serve', 296, 316)>",
"docstring": "Start an MkDocs development server with live reload.\n\nThe server watches documentation files and automatically reloads\nthe site when changes are detected.\n\nArgs:\n mkdocs_yml (Path):\n Path to the `mkdocs.yml` configuration file.\n\nRaises:\n click.ClickException:\n If the configuration file does not exist."
}
}

Some files were not shown because too many files have changed in this diff Show More