Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 0 additions & 7 deletions docs/app/reflex.lock/bun.lock

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

1 change: 0 additions & 1 deletion docs/app/reflex.lock/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "19.2.6",
"react-dropzone": "15.0.0",
"react-fast-marquee": "1.6.5",
"react-helmet": "6.1.0",
"react-leaflet": "5.0.0",
Expand Down
30 changes: 30 additions & 0 deletions packages/reflex-docgen/src/reflex_docgen/markdown/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
"""Markdown parsing and types for Reflex documentation."""

from __future__ import annotations

from typing import TYPE_CHECKING

from reflex_docgen.markdown import transformer as transformer
from reflex_docgen.markdown._parser import parse_document as parse_document
from reflex_docgen.markdown._types import Block as Block
Expand Down Expand Up @@ -27,6 +31,11 @@
from reflex_docgen.markdown._types import TextSpan as TextSpan
from reflex_docgen.markdown._types import ThematicBreakBlock as ThematicBreakBlock

if TYPE_CHECKING:
from reflex_docgen.markdown.transformer import (
ReflexComponentTransformer as ReflexComponentTransformer,
)

__all__ = [
"Block",
"BoldSpan",
Expand All @@ -44,6 +53,7 @@
"ListBlock",
"ListItem",
"QuoteBlock",
"ReflexComponentTransformer",
"Span",
"StrikethroughSpan",
"TableBlock",
Expand All @@ -55,3 +65,23 @@
"parse_document",
"transformer",
]


def __getattr__(name: str) -> object:
"""Lazily re-export the reflex-dependent transformer on first access.

Args:
name: The attribute being accessed.

Returns:
The resolved attribute.

Raises:
AttributeError: If the attribute does not exist.
"""
if name == "ReflexComponentTransformer":
from reflex_docgen.markdown.transformer import ReflexComponentTransformer

return ReflexComponentTransformer
msg = f"module {__name__!r} has no attribute {name!r}"
raise AttributeError(msg)
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def _extract_frontmatter(source: str) -> tuple[FrontMatter | None, str]:
only_low_level=only_low_level,
title=title,
component_previews=tuple(previews),
metadata=data,
),
source[m.end() :],
)
Expand Down Expand Up @@ -254,6 +255,7 @@ def _convert_block(token: BlockToken) -> Block | None:
name=flags[0],
args=flags[1:],
children=_parse_blocks(content),
content=content,
)

return CodeBlock(language=language, flags=flags, content=content)
Expand Down
17 changes: 16 additions & 1 deletion packages/reflex-docgen/src/reflex_docgen/markdown/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

from __future__ import annotations

from dataclasses import dataclass
from collections.abc import Mapping
from dataclasses import dataclass, field

# ---------------------------------------------------------------------------
# Span types — inline content without exposing mistletoe
Expand Down Expand Up @@ -141,12 +142,16 @@ class FrontMatter:
only_low_level: Whether to show only low-level component variants.
title: An optional page title.
component_previews: Preview lambdas keyed by component class name.
metadata: The full raw frontmatter mapping, including the keys modeled
by the fields above plus any arbitrary keys a site defines (e.g.
``author``, ``tags``, ``order``).
"""

components: tuple[str, ...]
only_low_level: bool
title: str | None
component_previews: tuple[ComponentPreview, ...]
metadata: Mapping[str, object] = field(default_factory=dict)
Comment thread
carlosabadia marked this conversation as resolved.
Outdated


@dataclass(frozen=True, slots=True, kw_only=True)
Expand Down Expand Up @@ -174,11 +179,16 @@ class DirectiveBlock:
name: The directive name (e.g. "alert", "video", "definition", "section").
args: Additional arguments after the name (e.g. ("info",) or ("https://...",)).
children: The parsed block-level content inside the directive.
content: The raw (unparsed) inner text. Directives whose body is
line-oriented rather than markdown (e.g. a ``quote`` block's
``- name:``/``- role:`` lines) should read this instead of
``children`` to avoid CommonMark reflowing the lines.
"""

name: str
args: tuple[str, ...]
children: tuple[Block, ...]
content: str = ""


@dataclass(frozen=True, slots=True, kw_only=True)
Expand Down Expand Up @@ -310,6 +320,11 @@ class Document:
frontmatter: FrontMatter | None
blocks: tuple[Block, ...]

@property
def metadata(self) -> Mapping[str, object]:
"""Return the raw frontmatter mapping, or an empty mapping if absent."""
return self.frontmatter.metadata if self.frontmatter is not None else {}

@property
def headings(self) -> tuple[HeadingBlock, ...]:
"""Return all headings in the document."""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,49 @@
"""Document transformers for converting parsed markdown into other formats."""

from __future__ import annotations

from typing import TYPE_CHECKING

from reflex_docgen.markdown.transformer._base import (
DocumentTransformer as DocumentTransformer,
)
from reflex_docgen.markdown.transformer._markdown import (
MarkdownTransformer as MarkdownTransformer,
)

if TYPE_CHECKING:
from reflex_docgen.markdown.transformer._reflex import (
ReflexComponentTransformer as ReflexComponentTransformer,
)

__all__ = [
"DocumentTransformer",
"MarkdownTransformer",
"ReflexComponentTransformer",
]


def __getattr__(name: str) -> object:
"""Lazily import the reflex-dependent transformer on first access.

Keeps ``import reflex_docgen.markdown`` (and the markdown-string
transformer) free of a hard ``reflex`` import until the component
transformer is actually used.

Args:
name: The attribute being accessed.

Returns:
The resolved attribute.

Raises:
AttributeError: If the attribute does not exist.
"""
if name == "ReflexComponentTransformer":
from reflex_docgen.markdown.transformer._reflex import (
ReflexComponentTransformer,
)

return ReflexComponentTransformer
msg = f"module {__name__!r} has no attribute {name!r}"
raise AttributeError(msg)
Comment thread
carlosabadia marked this conversation as resolved.
Outdated
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,24 @@ def line_break(self, span: LineBreakSpan) -> str:
def frontmatter(self, block: FrontMatter) -> str:
import yaml

data: dict[str, object] = {}
if block.components:
data["components"] = list(block.components)
if block.only_low_level:
data["only_low_level"] = [True]
if block.title is not None:
data["title"] = block.title
for preview in block.component_previews:
data[preview.name] = preview.source
if block.metadata:
# The raw mapping is the faithful source of truth for a parsed
# document: render it verbatim so a parse -> render round-trip
# preserves key order, falsy values (e.g. ``only_low_level: false``),
# and preview source text exactly.
data: dict[str, object] = dict(block.metadata)
else:
# Programmatically constructed frontmatter carries no raw mapping;
# rebuild one from the typed fields and previews.
data = {}
if block.components:
data["components"] = list(block.components)
if block.only_low_level:
data["only_low_level"] = [True]
if block.title is not None:
data["title"] = block.title
for preview in block.component_previews:
data[preview.name] = preview.source
return f"---\n{yaml.dump(data, default_flow_style=False, sort_keys=False).rstrip()}\n---"

def code_block(self, block: CodeBlock) -> str:
Expand Down
Loading
Loading