Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ lychee.toml
lychee-report.md
.phpunit.result.cache
code_samples/_inline_php/
/build/
*.egg-info/
97 changes: 3 additions & 94 deletions hooks.py
Original file line number Diff line number Diff line change
@@ -1,96 +1,5 @@
"""
MkDocs hooks for Ibexa developer documentation.
"""MkDocs hooks entry point — delegates to the installable llms_txt package."""

- Keeps the llmstxt plugin's ``sections`` config in sync with the ``nav``
defined in ``mkdocs.yml``.
- Post-processes the Markdown generated by the llmstxt plugin.
from llms_txt.hooks import on_config, on_page_content

All content transformations live in ``llmstxt_preprocess.py``; this module is
only MkDocs event glue.
"""

from __future__ import annotations

import sys
from pathlib import Path, PurePosixPath
from typing import TYPE_CHECKING

_here = Path(__file__).parent
if str(_here) not in sys.path:
sys.path.insert(0, str(_here))

from llmstxt_preprocess import (
absolutize_image_urls,
editions_from_frontmatter,
expand_macros,
inject_page_metadata,
renumber_ordered_lists,
)
from update_llmstxt_config import convert_nav_to_llmstxt_sections

if TYPE_CHECKING:
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.pages import Page


def on_config(config: "MkDocsConfig") -> None:
"""Populate llmstxt sections from nav before the build starts.
The llmstxt plugin reads ``config.sections`` in its ``on_files`` event,
which fires after ``on_config``, so injecting here is the right place.
"""
nav = config.get("nav")
if not nav:
return

llmstxt = config["plugins"].get("llmstxt")
if llmstxt is None:
return

docs_dir = Path(config["docs_dir"])
llmstxt.config.sections = convert_nav_to_llmstxt_sections(nav, docs_dir)


def on_page_content(html: str, *, page: "Page", config: "MkDocsConfig", **kwargs) -> None:
"""Reformat the Markdown content generated by the llmstxt plugin for this page.
Hooks run after plugins for every event, so at this point the llmstxt
plugin has already generated Markdown and stored it in ``_md_pages``.
We reformat here so the plugin writes the corrected content in its own
``on_post_build`` (which also runs before ours, for the same reason).
"""
llmstxt = config["plugins"].get("llmstxt")
if llmstxt is None:
return

src_uri = page.file.src_uri
page_info = llmstxt._md_pages.get(src_uri)
if page_info is None:
return

frontmatter = _read_frontmatter(page, config)
editions = editions_from_frontmatter(frontmatter)
description = expand_macros(str(frontmatter.get("description") or ""), config.get("extra") or {})
if "[[=" in description:
# Unresolved macros must not leak into the output.
description = ""
content = inject_page_metadata(page_info.content, description, editions)
content = renumber_ordered_lists(content)
# Same base URL and page directory the plugin uses for making link hrefs absolute.
page_dir = PurePosixPath(page.file.dest_uri).parent.as_posix()
content = absolutize_image_urls(content, llmstxt._base_url, page_dir)
if content != page_info.content:
llmstxt._md_pages[src_uri] = page_info._replace(content=content)


def _read_frontmatter(page: "Page", config: "MkDocsConfig") -> dict:
"""Read the page's YAML frontmatter from its source file."""
src_path = Path(config["docs_dir"]) / page.file.src_path
try:
from mkdocs.utils import meta as mkdocs_meta
with open(src_path, encoding="utf-8") as f:
raw = f.read()
_, frontmatter = mkdocs_meta.get_data(raw)
return frontmatter
except Exception:
return {}
__all__ = ["on_config", "on_page_content"]
Loading
Loading