Back to Reflex

Markdown

docs/library/typography/markdown.md

0.9.8a15.6 KB
Original Source
python
import reflex as rx

Markdown

The rx.markdown component can be used to render markdown text. It is based on Github Flavored Markdown.

python
rx.vstack(
    rx.markdown("## Hello World!"),
    rx.markdown("### Hello World!"),
    rx.markdown("#### Hello World!"),
    rx.markdown("Support us on [Github](https://github.com/reflex-dev/reflex)."),
    rx.markdown("Use `reflex deploy` to deploy your app with **a single command**."),
)

Math Equations

You can render math equations using LaTeX. For inline equations, surround the equation with $:

python
rx.markdown("Pythagorean theorem: $a^2 + b^2 = c^2$.")
md
# Escaping dollar signs
Because `$` is used as the math delimiter, any pair of `$` characters in the content is interpreted as an inline LaTeX equation — the text between them may disappear or render as a garbled formula. This commonly affects prices and other monetary values, especially in dynamic content such as streamed LLM output. To render literal dollar signs, escape them before passing the text to `rx.markdown`, e.g. `content.replace("$", "\\$")`.

Syntax Highlighting

You can render code blocks with syntax highlighting using the ```{language} syntax:

python
rx.markdown(
    r"""
```python
import reflex as rx
from .pages import index

app = rx.App()
app.add_page(index)
```
"""
)

Tables

You can render tables using the | syntax:

python
rx.markdown(
    """
| Syntax      | Description |
| ----------- | ----------- |
| Header      | Title       |
| Paragraph   | Text        |
"""
)

Plugins

Plugins can be used to extend the functionality of the markdown renderer.

By default Reflex uses the following plugins:

  • remark-gfm for Github Flavored Markdown support (use_gfm).
  • remark-math and rehype-katex for math equation support (use_math, use_katex).
  • rehype-unwrap-images to remove paragraph tags around images (use_unwrap_images).
  • rehype-raw to render raw HTML in markdown (use_raw). NOTE: in a future release this will be disabled by default for security reasons.

These default plugins can be disabled by passing use_[plugin_name]=False to the rx.markdown component. For example, to disable raw HTML rendering, use rx.markdown(..., use_raw=False).

Arbitrary Plugins

You can also add arbitrary remark or rehype plugins using the remark_plugins and rehype_plugins props in conjunction with the rx.markdown.plugin helper.

rx.markdown.plugin takes two arguments:

  1. The npm package name and version of the plugin (e.g. [email protected]).
  2. The named export to use from the plugin (e.g. remarkEmoji).

Remark Plugin Example

For example, to add support for emojis using the remark-emoji plugin:

python
rx.markdown(
    "Hello :smile:! :rocket: :tada:",
    remark_plugins=[
        rx.markdown.plugin("[email protected]", "remarkEmoji"),
    ],
)

Rehype Plugin Example

To make rehype-raw safer for untrusted HTML input we can use rehype-sanitize, which defaults to a safe schema similar to that used by Github.

python
rx.markdown(
    """Here is some **bold** text and a <script>alert("XSS Attack!")</script>.""",
    use_raw=True,
    rehype_plugins=[
        rx.markdown.plugin("[email protected]", "rehypeSanitize"),
    ],
)

Plugin Options

Both remark_plugins and rehype_plugins accept a heterogeneous list of plugin or tuple of (plugin, options) in case the plugin requires some kind of special configuration.

For example, rehype-slug is a simple plugin that adds ID attributes to the headings, but the rehype-autolink-headings plugin accepts options to specify how to render the links to those anchors.

python
rx.markdown(
    """
## Heading 2
### Heading 3
""",
    rehype_plugins=[
        rx.markdown.plugin("[email protected]", "rehypeSlug"),
        (
            rx.markdown.plugin(
                "[email protected]", "rehypeAutolinkHeadings"
            ),
            {
                "behavior": "wrap",
                "properties": {
                    "className": ["heading-link"],
                },
            },
        ),
    ],
)

Component Map

You can specify which components to use for rendering markdown elements using the component_map prop.

Each key in the component_map prop is a markdown element, and the value is a function that takes the text of the element as input and returns a Reflex component.

md
The `pre` and `a` tags are special cases. In addition to the `text`, they also receive a `props` argument containing additional props for the component.
python
component_map = {
    "h1": lambda text: rx.heading(text, as_="h2", size="5", margin_y="1em"),
    "h2": lambda text: rx.heading(text, as_="h2", size="3", margin_y="1em"),
    "h3": lambda text: rx.heading(text, as_="h2", size="1", margin_y="1em"),
    "p": lambda text: rx.text(text, color="green", margin_y="1em"),
    "code": lambda text: rx.code(text, color="purple"),
    "pre": lambda text, **props: rx.code_block(
        text, **props, theme=rx.code_block.themes.dark, margin_y="1em"
    ),
    "a": lambda text, **props: rx.link(
        text, **props, color="blue", _hover={"color": "red"}
    ),
}


def index():
    return rx.box(
        rx.markdown(
            r"""
# Hello World!

## This is a Subheader

### And Another Subheader

Here is some `code`:

```python
import reflex as rx

component = rx.text("Hello World!")
```

And then some more text here,
followed by a link to
[Reflex](https://reflex.dev/).
""",
            component_map=component_map,
        )
    )