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 docs/app/rxconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import reflex_xy
from reflex_site_shared.plugins import SharedSiteStylesPlugin
from xy_docs.config import DOCS_CONFIG
from xy_docs.plugins import XYDocsAgentFilesPlugin
from xy_docs.prerender import XyDocsMarkdownPlugin

config = rx.Config(
Expand All @@ -23,6 +24,7 @@
rx.plugins.RadixThemesPlugin(),
rx.plugins.SitemapPlugin(trailing_slash="always"),
XyDocsMarkdownPlugin(docs=DOCS_CONFIG),
XYDocsAgentFilesPlugin(docs=DOCS_CONFIG),
reflex_xy.XYPlugin(),
],
)
83 changes: 83 additions & 0 deletions docs/app/tests/test_agent_files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""Tests for the agent-readable documentation files and page actions."""

from pathlib import Path

import pytest
from reflex_site_shared.docs.content import discover_docs
from rxconfig import config
from xy_docs.breadcrumb import xy_docs_breadcrumb
from xy_docs.config import DOCS_CONFIG
from xy_docs.constants import LLMS_FULL_TXT_PATH, PUBLIC_DOCS_URL
from xy_docs.plugins import (
XYDocsAgentFilesPlugin,
build_llms_full_txt,
build_llms_txt,
markdown_asset_path,
)
from xy_docs.prerender import XyDocsMarkdownPlugin
from xy_docs.sidebar import xy_docs_sidebar


def _headings(content: str, level: int) -> list[str]:
"""Collect headings of one level, ignoring fenced code blocks."""
prefix = "#" * level + " "
headings: list[str] = []
in_fence = False
for line in content.splitlines():
if line.lstrip().startswith(("```", "~~~")):
in_fence = not in_fence
elif not in_fence and line.startswith(prefix):
headings.append(line)
return headings


def test_markdown_asset_paths_match_published_assets() -> None:
"""Every derived Markdown path is actually published for its page."""
published = {
path.as_posix()
for path, _content in XyDocsMarkdownPlugin(docs=DOCS_CONFIG).get_static_assets()
}
for page in discover_docs(DOCS_CONFIG):
asset = markdown_asset_path(page)
assert any(path.endswith(asset) for path in published), page.route


def test_llms_txt_indexes_every_page_under_the_public_url() -> None:
"""The index links llms-full.txt and each page's public Markdown URL."""
content = build_llms_txt(DOCS_CONFIG)
assert f"({PUBLIC_DOCS_URL}{LLMS_FULL_TXT_PATH})" in content
for page in discover_docs(DOCS_CONFIG):
assert f"({PUBLIC_DOCS_URL}/{markdown_asset_path(page)})" in content


def test_llms_full_txt_keeps_section_headers_above_page_content() -> None:
"""The combined file has one H1 and an H2 section per page."""
content = build_llms_full_txt(DOCS_CONFIG)
assert _headings(content, level=1) == ["# XY Documentation"]
section_headers = _headings(content, level=2)
for page in discover_docs(DOCS_CONFIG):
assert f"## {page.title}" in section_headers


def test_agent_files_publish_under_the_frontend_path(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Both agent files land inside the configured frontend path."""
monkeypatch.setattr("xy_docs.plugins.get_config", lambda: config)
assets = XYDocsAgentFilesPlugin(docs=DOCS_CONFIG).get_static_assets()
paths = {path for path, _content in assets}
root = Path("public") / config.frontend_path.strip("/")
assert paths == {root / "llms.txt", root / "llms-full.txt"}


def test_breadcrumb_actions_use_public_and_local_urls() -> None:
"""Page actions point at this site's Markdown, not root-relative paths."""
for page in discover_docs(DOCS_CONFIG):
if page.route.strip("/"):
break
rendered = str(xy_docs_breadcrumb(page, xy_docs_sidebar(page.route)))
asset = markdown_asset_path(page)
public_host_and_path = PUBLIC_DOCS_URL.removeprefix("https://")
assert f"{public_host_and_path}/{asset}" in rendered
assert f"{PUBLIC_DOCS_URL}{LLMS_FULL_TXT_PATH}" in rendered
assert f"{config.frontend_path}/{asset}" in rendered
88 changes: 44 additions & 44 deletions docs/app/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions docs/app/xy_docs/breadcrumb.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@

import reflex as rx
import reflex_components_internal as ui
from reflex_base.config import get_config
from reflex_site_shared.docs import docs_page_actions
from reflex_site_shared.docs.models import DocsPage
from reflex_site_shared.views.sidebar import docs_sidebar_drawer

from xy_docs.constants import LLMS_FULL_TXT_PATH, PUBLIC_DOCS_URL
from xy_docs.plugins import markdown_asset_path

_BREADCRUMB_LABELS = {
"charts": "Chart Gallery",
"gallery": "Chart Gallery",
Expand Down Expand Up @@ -114,6 +119,11 @@ def xy_docs_breadcrumb(page: DocsPage, sidebar: rx.Component) -> rx.Component:
class_name="flex flex-row items-center gap-[5px] overflow-hidden lg:gap-4",
),
rx.box(
docs_page_actions(
markdown_url=f"{PUBLIC_DOCS_URL}/{markdown_asset_path(page)}",
llms_full_txt_url=f"{PUBLIC_DOCS_URL}{LLMS_FULL_TXT_PATH}",
copy_url=f"{get_config().frontend_path}/{markdown_asset_path(page)}",
),
ui.icon(
"ArrowDown01Icon",
size=14,
Expand Down
4 changes: 4 additions & 0 deletions docs/app/xy_docs/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@
PUBLIC_XY_VERSION = os.getenv("XY_DOCS_PUBLIC_VERSION", "0.0.1").strip()
DOCS_CHANNEL = os.getenv("XY_DOCS_CHANNEL", "preview").strip().lower()
SOCIAL_IMAGE_URL = f"{PUBLIC_DOCS_URL}/xy-social-card.png"
LLMS_TXT_PATH = "/llms.txt"
LLMS_FULL_TXT_PATH = "/llms-full.txt"

if DOCS_CHANNEL not in {"preview", "stable"}:
msg = "XY_DOCS_CHANNEL must be either 'preview' or 'stable'"
raise ValueError(msg)

__all__ = [
"DOCS_CHANNEL",
"LLMS_FULL_TXT_PATH",
"LLMS_TXT_PATH",
"PUBLIC_DOCS_URL",
"PUBLIC_XY_VERSION",
"SOCIAL_IMAGE_URL",
Expand Down
Loading
Loading