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: 0 additions & 2 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,3 @@ jobs:
fetch-tags: true
fetch-depth: 0
- run: uv run pre-commit run --all-files --show-diff-on-failure
- name: Run docs app pre-commit
run: uv run pre-commit run --all-files --show-diff-on-failure --config docs/app/.pre-commit-config.yaml
4 changes: 3 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ repos:
- args:
- reflex
- tests
- docs/app
- packages
id: ruff-format
- args:
- --fix
- --exit-non-zero-on-fix
exclude: ^(integration/benchmarks/|docs/app/)
exclude: ^integration/benchmarks/
id: ruff-check
repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.6
Expand Down
12 changes: 0 additions & 12 deletions docs/app/.pre-commit-config.yaml

This file was deleted.

4 changes: 2 additions & 2 deletions docs/app/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ reflex_docs/ # Main application code
components/ # Reusable UI components
views/ # Shared view components (navbar, footer, cta)
templates/ # Page templates (docpage, mainpage)
docs/ # Markdown documentation (flexdown)
docs/ # Markdown documentation (reflex_docgen)
tests/ # Pytest + Playwright tests
```

Expand Down Expand Up @@ -52,5 +52,5 @@ tests/ # Pytest + Playwright tests

## Key conventions

- Docs: flexdown in `docs/`
- Docs: reflex_docgen in `docs/`
- Before committing: `uv run reflex compile` and `uv run pre-commit run --all-files`
2 changes: 0 additions & 2 deletions docs/app/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ requires-python = ">=3.10"
dependencies = [
"email-validator",
"fastapi",
"flexdown",
"googletrans-py",
"mistletoe",
"openai",
"orjson",
"pandas",
Expand Down
3 changes: 1 addition & 2 deletions docs/app/reflex_docs/components/button.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from typing import Callable, Literal

from reflex_ui_shared.components.icons import get_icon

import reflex as rx
from reflex_ui_shared.components.icons import get_icon

LiteralButtonVariant = Literal[
"primary", "success", "destructive", "secondary", "muted"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import reflex as rx
import reflex_ui as ui
from reflex.style import toggle_color_mode
from reflex_ui_shared.components.icons import get_icon
from reflex_ui_shared.components.marketing_button import button
from reflex_ui_shared.constants import DISCORD_URL, GITHUB_URL, TWITTER_URL
from reflex_ui_shared.views.hosting_banner import HostingBannerState

import reflex as rx
from reflex.style import toggle_color_mode

_DRAWER_LINKS_DOCS = "/docs"
_DRAWER_LINKS_TEMPLATES = "/templates"
_DRAWER_LINKS_BLOG = "/blog"
Expand Down
73 changes: 48 additions & 25 deletions docs/app/reflex_docs/docgen_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import types
from pathlib import Path

import reflex as rx
from reflex_base.constants.colors import ColorType
from reflex_docgen.markdown import (
Block,
Expand Down Expand Up @@ -52,15 +53,14 @@
)
from reflex_ui_shared.constants import REFLEX_ASSETS_CDN

import reflex as rx

# ---------------------------------------------------------------------------
# Exec environment — mirrors flexdown's module-based exec mechanism
# Exec environment — mirrors reflex_docgen's module-based exec mechanism
# ---------------------------------------------------------------------------

# One in-memory module per file — all exec blocks within a doc accumulate
# into the same namespace, so later definitions shadow earlier ones cleanly.
_file_modules: dict[str, types.ModuleType] = {}
_executed_blocks: set[tuple[str, str]] = set()

# Register the parent package so pickle can resolve child modules.
_PARENT_PKG = "_docgen_exec"
Expand All @@ -83,8 +83,16 @@ def _exec_code(content: str, env: dict, filename: str) -> None:
"""Execute a ``python exec`` code block via an in-memory module.

All exec blocks within the same file share one module so that State
subclass redefinitions shadow correctly.
subclass redefinitions shadow correctly. When the same block is
encountered a second time (e.g. the frontend is evaluated twice —
once for compilation and once on the backend), skip re-execution and
just populate *env* from the cached module namespace.
"""
key = (filename, content)
if key in _executed_blocks:
env.update(_file_modules[filename].__dict__)
return

if filename not in _file_modules:
mod_name = _make_module_name(filename)
module = types.ModuleType(mod_name)
Expand All @@ -99,6 +107,7 @@ def _exec_code(content: str, env: dict, filename: str) -> None:
exec(compile(content, filename or "<docgen-exec>", "exec"), module.__dict__)

env.update(module.__dict__)
_executed_blocks.add(key)


# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -165,7 +174,7 @@ def _spans_to_plaintext(spans: tuple[Span, ...]) -> str:
class ReflexDocTransformer(DocumentTransformer[rx.Component]):
"""Transforms a reflex_docgen Document into Reflex components.

Mirrors the rendering that the flexdown pipeline produces, so docs from
Mirrors the rendering that the reflex_docgen pipeline produces, so docs from
the parent docs directory look identical to the locally-authored ones.
"""

Expand Down Expand Up @@ -503,27 +512,34 @@ def title_comp() -> rx.Component:
),
]

if children:
# Has body content — render as collapsible accordion.
if title_spans:
trigger.append(title_comp())
body = rx.accordion.content(
self._render_children(children),
padding="0px",
margin_top="16px",
)
else:
trigger.append(
rx.box(
self._render_children(children),
class_name="font-[475] !text-secondary-11",
),
)
body = rx.fragment()
if children and title_spans:
# Has heading + body — render as collapsible accordion.
trigger.append(title_comp())
body = rx.accordion.content(
self._render_children(children),
padding="0px",
margin_top="16px",
)
return collapsible_box(trigger, body, color)

# Title only, no body — simple box.
trigger.append(title_comp())
# Title only, or text-only (no heading) — simple non-collapsible box.
if title_spans:
trigger.append(title_comp())
elif children:
# Render inline spans directly — avoid text_block's mb-4 margin.
spans: list[rx.Component | str] = []
for child in children:
if isinstance(child, TextBlock):
spans.extend(_render_spans(child.children))
else:
spans.append(self.transform_block(child))
trigger.append(
rx.box(
*spans,
class_name="font-[475]",
color=f"{rx.color(color, 11)}",
),
)
return rx.vstack(
rx.hstack(
*trigger,
Expand Down Expand Up @@ -694,6 +710,13 @@ def render_docgen_document(


def get_docgen_toc(filepath: str | Path) -> list[tuple[int, str]]:
"""Extract TOC headings as (level, text) tuples — same format as flexdown's get_toc."""
"""Extract TOC headings as (level, text) tuples — same format as reflex_docgen's get_toc."""
doc = _parse_doc(filepath)
return [(h.level, _spans_to_plaintext(h.children)) for h in doc.headings]


def render_markdown(text: str) -> rx.Component:
"""Render a plain markdown text string into Reflex components."""
doc = parse_document(text)
transformer = ReflexDocTransformer()
return transformer.transform(doc)
Loading
Loading