Solve one concrete task
Override markdown components
Replace markdown-generated HTML tags with Rust functions and still resolve local assets through the framework.
Replace markdown-generated tags with Rust components
Markdown rendering does not have to be a fixed HTML string step.
Use markdown_component(tag, component) when you want one generated tag to become a Rust function.
That is especially useful for:
custom links
responsive images
code blocks with richer markup
project-specific wrappers around standard tags
Register a component
.markdown_component("img", components::responsive_image)
.markdown_component("a", components::smart_link)
The tag name is the HTML tag produced by markdown, not the original markdown syntax.
Read the generated tag
The component receives ComponentProps.
pub fn smart_link(props: ComponentProps<'_>) -> site_core::Result<Markup> {
let href = props.attr("href").unwrap_or("#");
Ok(html! {
a href=(href) class="smart-link" {
(props.children)
}
})
}
The most useful fields and helpers are:
tagattrschildrenattr(key)
Resolve authored asset references inside the component
If the markdown tag contains a local asset reference, you can resolve it through the same pipeline used by route handlers:
pub fn linked_image(props: ComponentProps<'_>) -> site_core::Result<Markup> {
let src = props.asset_url("src")?.unwrap_or_default();
Ok(html! {
img src=(src) alt=(props.attr("alt").unwrap_or("")) {}
})
}
That keeps relative path handling, output URLs, and asset caching inside the framework instead of re-implementing them in the component.
Request image outputs directly from markdown
Markdown image components can also ask for a concrete output:
let image = props.responsive_image(
"src",
&ResponsiveImageOutput::widths(ImageFormat::Avif, [768, 1200, 1600])
.with_sizes("(min-width: 54rem) 54rem, calc(100vw - 2rem)"),
)?;
Or for one concrete image:
let open_graph = props.image_url(
"src",
&ImageOutput::raster(ImageFormat::Jpeg, 1200, 630)
.rasterize_vector_inputs(),
)?;
The component code still does not need to branch on whether the authored source was SVG, PNG, AVIF, or something else.
Probe authored images when the source matters
When you do need to branch on the authored source, probe it first:
let probe = props.probe_image("src")?;
That gives the component access to the authored format and dimensions without forcing a full image decode.
For a deeper example of the probing workflow, see the blog post
Probe Authored Images Without Decoding Them.