Skip to content
Ferromark

Ferromark / Rust

Customize Code Blocks in Rust

Use HtmlRenderHooks to replace output for selected AST nodes. The normal render() path does not dispatch hooks; opt in with render_with_hooks().

For syntax highlighting, enable Ferromark's optional ferriki Cargo feature and use FerrikiHighlightHooks with an initialized Ferriki highlighter. Ferromark keeps the code-block wrappers, line numbers, and annotations. The optional ferriki-remote feature enables release-pinned CDN assets. Build the highlighter and preload required languages/themes before rendering. See the native highlighting guide for the adapter contract.

use ferromark::{Allocator, HtmlRenderContext, HtmlRenderControl, HtmlRenderHooks,
    HtmlRenderer, Parser};
use ferromark::ast::Node;

struct CodeRenderer;
impl HtmlRenderHooks for CodeRenderer {
    fn render_node(&mut self, node: &Node<'_>, cx: &mut HtmlRenderContext<'_>)
        -> HtmlRenderControl {
        if let Node::CodeBlock(block) = node {
            cx.write("<pre class=\"source\"><code>");
            cx.write_escaped(&block.value);
            cx.write("</code></pre>\n");
            HtmlRenderControl::Handled
        } else {
            HtmlRenderControl::Default
        }
    }
}
let source = "```rust\nfn main() {}\n```";
let allocator = Allocator::for_source_len(source.len());
let document = Parser::new(&allocator, source).parse().unwrap();
let html = HtmlRenderer::new().render_with_hooks(&document, &mut CodeRenderer);
assert!(html.contains("class=\"source\""));

Return Default to use built-in output; return Handled after writing the entire replacement. The hook sees fenced and indented code blocks. A highlighter adapter can inspect the code, language, and metadata, then write its HTML here.

cx.write() inserts raw HTML, even when sanitization is enabled. Escape source text with write_escaped, attributes with write_attribute_escaped, and URL attributes with write_url_escaped. Validate URL schemes when supplying custom URLs. Only insert highlighter output you trust. Theme colors from custom hooks are escaped for HTML attributes, but their CSS values are not validated.

For code annotations, line numbers, and heading permalinks, inspect the existing HtmlRendererOptions before writing a hook. Rendering and trust explains the shared output boundary.

Compose highlighting and diagrams

Use HtmlRenderHooks::render_code_block for whole-block replacements and highlight_code_block for highlighted line fragments. A tuple composes hooks; all whole-block replacements run before highlighting. The code-only render_with_code_hooks entry point preserves normal inline rendering.

The optional ferrigura feature implements these HTML and JSX contracts with FerriguraHooks, just as the ferriki feature does with FerrikiHighlightHooks. The highlighting and diagrams guide explains the available builds and links to the Rust adapter example.