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 itsWriteimplementation.node: the&Nodebeing formatted, when theNodeValue’s contents aren’t enough.entering:truewhen the node is being first descended into,falsewhen 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",
&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);