oct
Loading...
Searching...
No Matches
oct.docs.front_page Namespace Reference

Classes

class  FrontPageError

Functions

Path resolve_template_path (Path ws_root)
dict[str, Any] build_render_context (Workspace workspace)
Path|None copy_assets (Path ws_root, Path site_root)
Path render_front_page (Path ws_root, Path site_root, Workspace workspace)

Variables

Path _BUNDLED_TEMPLATE_DIR = Path(__file__).resolve().parents[1] / "templates" / "docs_hub"
Path _WORKSPACE_TEMPLATE_REL = Path("docs") / "_hub" / "index.html.j2"
Path _WORKSPACE_ASSETS_REL = Path("assets")
Path _BUNDLED_ASSETS_DIR = _BUNDLED_TEMPLATE_DIR / "_assets"

Detailed Description

Purpose
-------
Render the workspace-mode docs hub front page. Resolves the template
override at ``<workspace>/docs/_hub/index.html.j2`` and falls back to
the bundled neutral default at ``oct/templates/docs_hub/index.html.j2``.
Substitutes a manifest-driven ``subprojects`` context into the Jinja
template and writes the result to ``<site_root>/index.html``. Also
copies ``<workspace>/assets/`` (if present) into ``<site_root>/_assets/``,
falling back to the bundled defaults bundled under
``oct/templates/docs_hub/_assets/``.

Responsibilities
----------------
- Resolve the active template via :func:`resolve_template_path`,
  preferring the workspace override.
- Build the Jinja render context from the loaded
  :class:`oct.core.workspace.Workspace`.
- Render the template and write ``index.html`` to the site root.
- Copy assets from the workspace (or bundled defaults) into the
  site's ``_assets/`` directory.

Diagnostics
-----------
Domain: OCT-DOCS
Levels:
    L2 - render entry / exit
    L3 - template resolution decision, asset directory selection
    L4 - per-asset copy

Contracts
---------
- Render is pure: same inputs produce the same HTML output (modulo the
  ``generated_at`` ISO timestamp).
- Asset copy uses :func:`shutil.copytree` with ``dirs_exist_ok=True`` -
  no symlinks (Windows safety).
- The renderer never reads or executes user code; the Jinja environment
  has autoescape enabled for HTML safety.

Dependencies
------------
- jinja2 (lazy; Environment, FileSystemLoader, select_autoescape - renders the template, already in via Sphinx)
- oct.core.workspace (Workspace dataclass)
- oct.core.diagnostics (_dbg structured logger)
- oct.docs.doxyfile_init (lazy; has_doxyfile - whether a subproject gets a Doxygen card)
- oct.docs.typedoc (lazy; has_typedoc - whether a subproject gets a TypeDoc card)

Function Documentation

◆ build_render_context()

dict[str, Any] oct.docs.front_page.build_render_context ( Workspace workspace)
Build the Jinja context dict for the front page.

The shape is intentionally narrow so override templates can rely on
a stable contract:

- ``workspace_name`` -- string, from the manifest
- ``option_c_href`` -- string, relative URL to the Option C tier
- ``subprojects`` -- list of dicts ``{"name", "sphinx_href",
  "doxygen_href", "typedoc_href"}``; ``doxygen_href`` is ``None`` for
  a subproject that declares no Doxyfile or whose manifest entry sets
  ``html_docs: {"doxygen": false}``, and ``typedoc_href`` is ``None``
  for one with no ``typedoc.json``; the template shows no card for a
  ``None`` href, and a row left with only its Sphinx card is laid out
  at full width
- ``generated_at`` -- ISO-8601 timestamp (seconds precision)

Only subprojects the manifest declares as carded appear in
``subprojects``: an entry with ``html_docs: false`` has no output to
link to, and one with ``html_docs: {"hub": false}`` is built and
reachable by URL but deliberately kept off the index. The template
therefore does not need to know the manifest schema - it renders
every entry it is given.

The Doxygen card follows the same declaration the build fan-out uses,
a Doxyfile at :data:`oct.docs.doxyfile_init.DOXYFILE_REL`. Before
2026-09-27 every card linked to ``<name>/doxygen/html/index.html``
unconditionally, which put five dead links on the front page - one per
subproject that never had a Doxyfile. Since 2026-09-28 the card also
follows the manifest switch ``html_docs: {"doxygen": false}``, because
the fan-out then neither builds nor aggregates that subproject's
Doxygen and a card would point at a withdrawn tree.

Definition at line 111 of file front_page.py.

Here is the caller graph for this function:

◆ copy_assets()

Path | None oct.docs.front_page.copy_assets ( Path ws_root,
Path site_root )
Copy workspace assets (or bundled fallbacks) into ``site_root/_assets``.

Returns the resolved source directory used, or ``None`` when no
assets directory was found and nothing was copied.

Definition at line 173 of file front_page.py.

Here is the caller graph for this function:

◆ render_front_page()

Path oct.docs.front_page.render_front_page ( Path ws_root,
Path site_root,
Workspace workspace )
Render the front page and write it to ``site_root/index.html``.

Parameters
----------
ws_root:
    Workspace root path. Used to find the override template and
    the workspace ``assets/`` directory.
site_root:
    Aggregation directory (``<ws_root>/_site/`` in normal use).
    Created if it does not exist.
workspace:
    Loaded :class:`Workspace` providing the manifest data the
    template loops over.

Returns
-------
Path
    The absolute path to the written ``index.html``.

Definition at line 197 of file front_page.py.

Here is the call graph for this function:

◆ resolve_template_path()

Path oct.docs.front_page.resolve_template_path ( Path ws_root)
Return the active front-page template path.

Resolution order:
1. ``<ws_root>/docs/_hub/index.html.j2`` (workspace override)
2. ``oct/templates/docs_hub/index.html.j2`` (bundled default)

Raises
------
FrontPageError
    When neither template exists. Should be impossible in normal
    installs because the bundled default ships with the package.

Definition at line 83 of file front_page.py.

Here is the caller graph for this function:

Variable Documentation

◆ _BUNDLED_ASSETS_DIR

Path oct.docs.front_page._BUNDLED_ASSETS_DIR = _BUNDLED_TEMPLATE_DIR / "_assets"
protected

Definition at line 76 of file front_page.py.

◆ _BUNDLED_TEMPLATE_DIR

Path oct.docs.front_page._BUNDLED_TEMPLATE_DIR = Path(__file__).resolve().parents[1] / "templates" / "docs_hub"
protected

Definition at line 65 of file front_page.py.

◆ _WORKSPACE_ASSETS_REL

Path oct.docs.front_page._WORKSPACE_ASSETS_REL = Path("assets")
protected

Definition at line 72 of file front_page.py.

◆ _WORKSPACE_TEMPLATE_REL

Path oct.docs.front_page._WORKSPACE_TEMPLATE_REL = Path("docs") / "_hub" / "index.html.j2"
protected

Definition at line 68 of file front_page.py.