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().
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.
For code annotations, line numbers, and heading permalinks, inspect the existing
HtmlRendererOptions before writing a hook. Rendering and trust
explains the shared output boundary.