Skip to content

Renderer Classes

Dinja provides two renderer classes: Renderer for synchronous code and AsyncRenderer for asynchronous code.

Renderer (Sync)

The synchronous HTTP client for the Dinja MDX rendering service.

Constructor

Renderer(
    base_url: str = "http://localhost:8080",
    timeout: float = 30.0
)

Parameters

  • base_url (str, default: "http://localhost:8080") – URL of the Dinja service
  • timeout (float, default: 30.0) – Request timeout in seconds

AsyncRenderer (Async)

The asynchronous HTTP client for the Dinja MDX rendering service.

Installation

Requires an async HTTP library:

pip install dinja[httpx]    # recommended
pip install dinja[aiohttp]  # alternative

Constructor

AsyncRenderer(
    base_url: str = "http://localhost:8080",
    timeout: float = 30.0,
    backend: Literal["httpx", "aiohttp"] | None = None
)

Parameters

  • base_url (str, default: "http://localhost:8080") – URL of the Dinja service
  • timeout (float, default: 30.0) – Request timeout in seconds
  • backend ("httpx" | "aiohttp" | None, default: None) – HTTP backend to use. If None, auto-detects available library.

Context Manager

AsyncRenderer supports async context manager for automatic cleanup:

async with AsyncRenderer("http://localhost:8080") as renderer:
    result = await renderer.html(views={...})
# Connection automatically closed

Or manually:

renderer = AsyncRenderer("http://localhost:8080")
try:
    result = await renderer.html(views={...})
finally:
    await renderer.close()

Methods

Both Renderer and AsyncRenderer share the same methods. For async, just add await.

html()

Renders MDX content to HTML.

# Sync
def html(
    self,
    views: dict[str, str],
    components: dict[str, Component] | dict[str, str] | None = None,
    minify: bool = True,
    utils: str | None = None,
    directives: list[str] | None = None,
) -> Result

# Async
async def html(...) -> Result

javascript()

Renders MDX content to JavaScript.

# Sync
def javascript(
    self,
    views: dict[str, str],
    components: dict[str, Component] | dict[str, str] | None = None,
    minify: bool = True,
    utils: str | None = None,
    directives: list[str] | None = None,
) -> Result

# Async
async def javascript(...) -> Result

schema()

Extracts custom component names — and, if directives is set, directive attributes — from MDX content.

# Sync
def schema(
    self,
    views: dict[str, str],
    components: dict[str, Component] | dict[str, str] | None = None,
    minify: bool = True,
    utils: str | None = None,
    directives: list[str] | None = None,
) -> Result

# Async
async def schema(...) -> Result

directives is a list of attribute-name prefixes (e.g. ["v-", "x-"]). Every attribute in the rendered tree that starts with one of the prefixes is reported in the schema output:

result = renderer.schema(
    views={
        "menu.mdx": '<div v-on:click="toggle" v-show="open" x-data="{ open: false }">Menu</div>'
    },
    directives=["v-", "x-"],
)
print(result.get_output("menu.mdx"))
{
  "components": [],
  "directives": {
    "keys": ["v-on:click", "v-show", "x-data"],
    "patterns": ["v-*", "v-on:*", "x-*"],
    "values": ["open", "toggle", "{ open: false }"]
  }
}
  • keys — exact attribute names that matched a prefix
  • patterns — wildcard summaries (v-on:* for namespaced attributes, v-* otherwise)
  • values — unique attribute values

The directives parameter is accepted by all render methods but only affects schema output.

json()

Renders MDX content to JSON tree representation.

# Sync
def json(
    self,
    views: dict[str, str],
    components: dict[str, Component] | dict[str, str] | None = None,
    minify: bool = True,
    utils: str | None = None,
    directives: list[str] | None = None,
) -> Result

# Async
async def json(...) -> Result

render()

Generic render method with configurable output format.

# Sync
def render(
    self,
    output: Output,  # "html" | "javascript" | "schema" | "json"
    views: dict[str, str],
    components: dict[str, Component] | dict[str, str] | None = None,
    minify: bool = True,
    utils: str | None = None,
    directives: list[str] | None = None,
) -> Result

# Async
async def render(...) -> Result

health()

Checks if the Dinja service is running.

# Sync
def health(self) -> bool

# Async
async def health(self) -> bool

close() (Async only)

Closes the HTTP client connection.

async def close(self) -> None

Parameters

All render methods accept the same parameters:

  • views (dict[str, str]) – Map of file names to MDX content strings
  • components (dict[str, Component] | dict[str, str] | None) – Optional custom components
  • minify (bool, default: True) – Whether to minify output
  • utils (str | None) – Optional JavaScript utilities available to all components
  • directives (list[str] | None) – Optional directive prefixes

Return Type

All render methods return a Result object:

@dataclass
class Result:
    total: int                      # Total files processed
    succeeded: int                  # Number of successful renders
    failed: int                     # Number of failed renders
    files: dict[str, FileResult]    # Individual file results
    errors: list[dict[str, str]]    # Error list

Result Methods

result.is_all_success()           # True if all files succeeded
result.get_output("page.mdx")     # Get output for a file
result.get_metadata("page.mdx")   # Get metadata for a file

Examples

Basic Sync Usage

from dinja import Renderer

renderer = Renderer("http://localhost:8080")

result = renderer.html(views={"page.mdx": "# Hello World"})

if result.is_all_success():
    print(result.get_output("page.mdx"))

Basic Async Usage

import asyncio
from dinja import AsyncRenderer

async def main():
    async with AsyncRenderer("http://localhost:8080") as renderer:
        result = await renderer.html(views={"page.mdx": "# Hello World"})
        if result.is_all_success():
            print(result.get_output("page.mdx"))

asyncio.run(main())

With Components

from dinja import Renderer

renderer = Renderer("http://localhost:8080")

result = renderer.html(
    views={"page.mdx": "# Hello\n\n<Button>Click</Button>"},
    components={
        "Button": "export default function Component(props) { return <button>{props.children}</button>; }"
    },
)

Custom Timeout

# Longer timeout for large batches
renderer = Renderer(
    base_url="http://localhost:8080",
    timeout=60.0
)

Specifying Async Backend

# Use httpx explicitly
renderer = AsyncRenderer(
    base_url="http://localhost:8080",
    backend="httpx"
)

# Use aiohttp explicitly
renderer = AsyncRenderer(
    base_url="http://localhost:8080",
    backend="aiohttp"
)

Multiple Renders

# Sync
renderer = Renderer("http://localhost:8080")
result1 = renderer.html(views={"page1.mdx": "# Page 1"})
result2 = renderer.schema(views={"page2.mdx": "# Page 2"})

# Async
async with AsyncRenderer("http://localhost:8080") as renderer:
    result1 = await renderer.html(views={"page1.mdx": "# Page 1"})
    result2 = await renderer.schema(views={"page2.mdx": "# Page 2"})

Best Practices

  1. Reuse Renderer Instances – Create one instance and reuse it for multiple renders
  2. Use Context Manager for Async – Always use async with to ensure proper cleanup
  3. Check Health First – Use health() to verify the service is running
  4. Handle Results – Always check result.is_all_success() before accessing output
  5. Use Components Dict – Simple dict[str, str] format is auto-converted to dict[str, Component]