create_formatter

Macro create_formatter 

Source
macro_rules! create_formatter {
    ($name:ident, { $( $pat:pat => | $( $capture:ident ),* | $case:tt ),* $(,)? }) => { ... };
    ($name:ident<$type:ty>, { $( $pat:pat => | $( $capture:ident ),* | $case:tt ),* $(,)? }) => { ... };
    (@inner $name:ident<$type:ty $(, $user_type:ty)?>, { $( $pat:pat => | $( $capture:ident ),* | $case:tt ),* $(,)? }) => { ... };
}
Expand description

Create a formatter with specialised rules for certain node types.

Give the name of the newly created struct, and then a list of NodeValue match cases within curly braces. The left-hand side are regular patterns and can include captures. The right-hand side starts with a mandatory list of contextual captures, similar to lambdas. The following contextual captures are available:

  • context: the &mut Context, giving access to rendering options, plugins, and output appending via its Write implementation.
  • node: the &Node being formatted, when the NodeValue’s contents aren’t enough.
  • entering: true when the node is being first descended into, false when being exited.

By default, an overridden formatter will return ChildRendering::HTML, causing children of the node to be rendered as HTML as usual. You can return one of these enum values (wrapped in Ok) from within your override to change this behaviour, in some or all cases. These values are only noted when entering a node.

If you supply a type parameter after the name of your formatter, it will be taken as an additional argument on the generated format_document method, is available on the Context as the user property, and becomes the return value of format_document.

create_formatter!(CustomFormatter<usize>, {
    NodeValue::Emph => |context, entering| {
        context.user += 1;
        if entering {
            context.write_str("<i>")?;
        } else {
            context.write_str("</i>")?;
        }
    },
    NodeValue::Strong => |context, entering| {
        context.user += 1;
        context.write_str(if entering { "<b>" } else { "</b>" })?;
    },
    NodeValue::Image(ref nl) => |context, node, entering| {
        assert!(node.data().sourcepos == (3, 1, 3, 18).into());
        if entering {
            context.write_str(&nl.url.to_uppercase())?;
            return Ok(ChildRendering::Skip);
        }
    },
});

let options = Options::default();
let arena = Arena::new();
let doc = parse_document(
    &arena,
    "_Hello_, **world**.\n\n![title](/img.png)",
    &options,
);

let mut result: String = String::new();
let converted_count = CustomFormatter::format_document(doc, &options, &mut result, 0).unwrap();

assert_eq!(
    result,
    "<p><i>Hello</i>, <b>world</b>.</p>\n<p>/IMG.PNG</p>\n"
);

assert_eq!(converted_count, 4);