standardize packaging, tooling, docs, CI, and licensing
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
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
|
||||
|
||||
__all__ = [
|
||||
"NavSpec",
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -28,8 +27,8 @@ class NavSpec:
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
home: Optional[str],
|
||||
groups: Dict[str, List[str]],
|
||||
home: str | None,
|
||||
groups: dict[str, list[str]],
|
||||
) -> None:
|
||||
"""
|
||||
Initialize a NavSpec instance.
|
||||
@@ -85,7 +84,7 @@ class NavSpec:
|
||||
|
||||
return cls(home=home, groups=groups)
|
||||
|
||||
def all_patterns(self) -> List[str]:
|
||||
def all_patterns(self) -> list[str]:
|
||||
"""
|
||||
Return all path patterns referenced by the specification.
|
||||
|
||||
@@ -93,7 +92,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)
|
||||
|
||||
@@ -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: ...
|
||||
|
||||
Reference in New Issue
Block a user