Skip to main content

socketry_markdown/
renderer.rs

1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4//! Traits for rendering Markdown AST nodes.
5mod html;
6mod markdown;
7
8pub use html::HTMLRenderer;
9pub use markdown::MarkdownRenderer;
10
11use crate::mdast::Node;
12use alloc::string::String;
13
14/// A renderer for an AST node tree.
15///
16/// Implement [`render_node`][Self::render_node] to decide how each node is
17/// emitted. Call [`render_children`][Self::render_children] for transparent
18/// containers or when a node's children should be rendered recursively.
19/// Renderers choose their output format and escaping rules.
20///
21/// This is separate from [`crate::to_html`], which parses Markdown source and
22/// renders the parser's events with the built-in HTML compiler.
23///
24/// # Example
25///
26/// ```ignore
27/// use socketry_markdown::{mdast::Node, renderer::Renderer};
28///
29/// struct PlainText;
30///
31/// impl Renderer for PlainText {
32///     fn render_node(&mut self, node: &Node) -> String {
33///         match node {
34///             Node::Text(text) => text.value.clone(),
35///             Node::InlineCode(code) => code.value.clone(),
36///             Node::Code(code) => code.value.clone(),
37///             Node::Break(_) => "\n".into(),
38///             Node::Image(image) => image.alt.clone(),
39///             Node::ImageReference(image) => image.alt.clone(),
40///             Node::Definition(_) | Node::FootnoteReference(_) | Node::ThematicBreak(_) => {
41///                 String::new()
42///             }
43///             _ => self.render_children(node),
44///         }
45///     }
46/// }
47///
48/// let node = Node::Fragment(socketry_markdown::mdast::Fragment {
49///     children: vec![Node::Text(socketry_markdown::mdast::Text {
50///         value: "hello".into(),
51///         position: None,
52///     })],
53/// });
54/// let mut renderer = PlainText;
55/// let plain_text = node.render_with(&mut renderer);
56/// ```
57pub trait Renderer {
58    /// Render one AST node into this renderer's output.
59    fn render_node(&mut self, node: &Node) -> String;
60
61    /// Render a node and its descendants.
62    fn render(&mut self, node: &Node) -> String {
63        self.render_node(node)
64    }
65
66    /// Render the direct children of a parent node in order.
67    fn render_children(&mut self, node: &Node) -> String {
68        let mut output = String::new();
69
70        if let Some(children) = node.children() {
71            for child in children {
72                output.push_str(&self.render(child));
73            }
74        }
75
76        output
77    }
78}