""" This module provides the MkDocsNavEmitter, which converts a ResolvedNav instance into the specific YAML-ready list structure expected by the MkDocs 'nav' configuration. """ from pathlib import Path from typing import List, Dict, Any from docforge.nav.resolver import ResolvedNav class MkDocsNavEmitter: """ Emitter responsible for transforming a ResolvedNav into an MkDocs-compatible navigation structure. """ def emit(self, nav: ResolvedNav) -> List[Dict[str, Any]]: """ Generate a list of navigation entries for mkdocs.yml. Args: nav: The resolved navigation data. Returns: A list of dictionary mappings representing the MkDocs navigation. """ result: List[Dict[str, Any]] = [] # Home entry (semantic path) if nav.home: result.append({"Home": nav.home}) # Group entries for group, paths in nav.groups.items(): entries: List[str] = [] for p in paths: # Convert filesystem path back to docs-relative path rel_path = self._to_relative(p, nav._docs_root) entries.append(rel_path) result.append({group: entries}) return result def _to_relative(self, path: Path, docs_root: Path | None) -> str: """ Convert a filesystem path to a path relative to the documentation root. This handles both absolute and relative filesystem paths, ensuring the output is compatible with MkDocs navigation requirements. Args: path: The path to convert. docs_root: The root directory for documentation. Returns: A string representing the relative POSIX-style path. """ if docs_root and path.is_absolute(): try: path = path.relative_to(docs_root.resolve()) except ValueError: pass elif docs_root: # Handle relative paths (e.g. starting with 'docs/') 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:] # Fallback for other cases return path.as_posix().split("/docs/", 1)[-1]