Skip to main content

Node

Struct Node 

Source
pub struct Node {
    pub children: Vec<Node>,
    pub srcmap: Option<SourcePos>,
    pub ext: NodeExtSet,
    pub attrs: Vec<(&'static str, String)>,
    pub node_type: TypeKey,
    pub node_value: Box<dyn NodeValue>,
}
Expand description

Single node in the CommonMark AST.

Fields§

§children: Vec<Node>

Array of child nodes.

§srcmap: Option<SourcePos>

Source mapping info.

§ext: NodeExtSet

Custom data specific to this token.

§attrs: Vec<(&'static str, String)>

Additional attributes to be added to resulting html.

§node_type: TypeKey

Type name, used for debugging.

§node_value: Box<dyn NodeValue>

Storage for arbitrary token-specific data.

Implementations§

Source§

impl Node

Source

pub fn new<T: NodeValue>(value: T) -> Self

Create a new Node with a custom value.

Examples found in repository?
examples/ferris/inline_rule.rs (line 52)
46    fn run(state: &mut InlineState) -> Option<(Node, usize)> {
47        let input = &state.src[state.pos..state.pos_max]; // look for stuff at state.pos
48        if !input.starts_with(CRAB_CLAW) { return None; } // return None if it's not found
49
50        // return new node and length of this structure
51        Some((
52            Node::new(InlineFerris),
53            CRAB_CLAW.len(),
54        ))
55    }
More examples
Hide additional examples
examples/ferris/core_rule.rs (line 57)
45    fn run(root: &mut Node, _: &MarkdownIt) {
46        let mut counter = 0;
47
48        // walk through AST recursively and count the number of two
49        // custom nodes added by other two rules
50        root.walk(|node, _| {
51            if node.is::<InlineFerris>() || node.is::<BlockFerris>() {
52                counter += 1;
53            }
54        });
55
56        // append a counter to the root as a custom node
57        root.children.push(Node::new(FerrisCounter(counter)))
58    }
examples/ferris/block_rule.rs (line 63)
48    fn run(state: &mut BlockState) -> Option<(Node, usize)> {
49        // get contents of a line number `state.line` and check it
50        let line = state.get_line(state.line).trim();
51        if !line.starts_with(CRAB_CLAW) { return None; }
52        if !line.ends_with(CRAB_CLAW)   { return None; }
53
54        // require any number of `-` in between, but no less than 4
55        if line.len() < CRAB_CLAW.len() * 2 + 4 { return None; }
56
57        // and make sure no other characters are present there
58        let dashes = &line[CRAB_CLAW.len()..line.len()-CRAB_CLAW.len()];
59        if dashes.chars().any(|c| c != '-') { return None; }
60
61        // return new node and number of lines it occupies
62        Some((
63            Node::new(BlockFerris),
64            1,
65        ))
66    }
Source

pub fn name(&self) -> &'static str

Return std::any::type_name() of node value.

Source

pub fn is<T: NodeValue>(&self) -> bool

Check that this node value is of given type.

Examples found in repository?
examples/ferris/core_rule.rs (line 51)
45    fn run(root: &mut Node, _: &MarkdownIt) {
46        let mut counter = 0;
47
48        // walk through AST recursively and count the number of two
49        // custom nodes added by other two rules
50        root.walk(|node, _| {
51            if node.is::<InlineFerris>() || node.is::<BlockFerris>() {
52                counter += 1;
53            }
54        });
55
56        // append a counter to the root as a custom node
57        root.children.push(Node::new(FerrisCounter(counter)))
58    }
Source

pub fn cast<T: NodeValue>(&self) -> Option<&T>

Downcast node value to specific type.

Source

pub fn cast_mut<T: NodeValue>(&mut self) -> Option<&mut T>

Downcast node value to specific type.

Source

pub fn render(&self) -> String

Render this node to HTML.

Examples found in repository?
examples/ferris/main.rs (line 22)
6fn main() {
7    // create markdown parser
8    let md = &mut markdown_it::MarkdownIt::new();
9
10    // add commonmark syntax, you almost always want to do that
11    markdown_it::plugins::cmark::add(md);
12
13    // add custom three rules described above
14    inline_rule::add(md);
15    block_rule::add(md);
16    core_rule::add(md);
17
18    // and now you can use it
19    let html = md.parse(r#"
20(\/) hello world (\/)
21(\/)-------------(\/)
22    "#).render();
23
24    print!("{html}");
25
26    assert_eq!(html.trim(), r#"
27<p><span class="ferris-inline">🦀</span> hello world <span class="ferris-inline">🦀</span></p>
28<div class="ferris-block"><img src="https://upload.wikimedia.org/wikipedia/commons/0/0f/Original_Ferris.svg"></div>
29<footer class="ferris-counter">There are 3 crabs lurking in this document.</footer>
30    "#.trim());
31}
More examples
Hide additional examples
examples/syntect/main.rs (line 88)
1fn main() {
2    #[cfg(not(feature = "syntect"))]
3    {
4        eprintln!("Run this example with the `syntect` feature enabled.");
5        eprintln!("such as: cargo run --example syntect --features syntect");
6        return;
7    }
8
9    let mut md_inline = markdown_it::MarkdownIt::new();
10    markdown_it::plugins::cmark::add(&mut md_inline);
11    markdown_it::plugins::extra::syntect::add(&mut md_inline);
12
13    let mut md_classed = markdown_it::MarkdownIt::new();
14    markdown_it::plugins::cmark::add(&mut md_classed);
15    markdown_it::plugins::extra::syntect::add(&mut md_classed);
16    markdown_it::plugins::extra::syntect::set_to_classed(&mut md_classed);
17
18    let input_inline = r#"
19parse with inline mode:
20
21```rust {2}
22fn main() {
23    println!("Ciallo world!");
24}
25```
26"#;
27    let input_classed = r#"
28parse with classed mode:
29
30```rust {2}
31fn main() {
32    println!("Ciallo world!");
33}
34```
35"#;
36
37    let highlighted_line_css = r#"
38.syntect-line-highlighted {
39    background-color: #fffbdd;
40    border-left: 4px solid #f9c513;
41    padding-left: 12px;
42}
43"#;
44
45    let html = format!(
46        r#"<!DOCTYPE html>
47<html>
48<head>
49  <meta charset="utf-8">
50  <title>Code highlight example</title>
51  <style>
52  body {{
53    font-family: sans-serif;
54    max-width: 800px;
55    margin: 40px auto;
56    padding: 20px;
57  }}
58  h2 {{
59    margin-top: 40px;
60  }}
61  pre {{
62    background-color: #f6f8fa;
63    padding: 16px 0;
64    border-radius: 6px;
65    font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
66    font-size: 14px;
67    line-height: 1.5;
68    overflow: auto;
69  }}
70  .syntect-line {{
71    display: block;
72    padding: 0 16px;
73  }}
74  {}
75  {}
76  </style>
77</head>
78<body>
79  <h2>Inline Mode</h2>
80  {}
81  <h2>Classed Mode</h2>
82  {}
83</body>
84</html>
85"#,
86        markdown_it::plugins::extra::syntect::theme_css(&md_classed).unwrap_or_default(),
87        highlighted_line_css,
88        md_inline.parse(input_inline).render(),
89        md_classed.parse(input_classed).render(),
90    );
91
92    let path = "examples/syntect/demo.html";
93    std::fs::write(path, html).expect("write file failed");
94    println!("success write to '{}'", path);
95}
Source

pub fn xrender(&self) -> String

Render this node to XHTML, it adds slash to self-closing tags like this: <img />.

This mode exists for compatibility with CommonMark tests.

Source

pub fn replace<T: NodeValue>(&mut self, value: T)

Replace custom value with another value (this is roughly equivalent to replacing the entire node and copying children and sourcemaps).

Source

pub fn walk<'a>(&'a self, f: impl FnMut(&'a Node, u32))

Execute function f recursively on every member of AST tree (using preorder deep-first search).

Examples found in repository?
examples/ferris/core_rule.rs (lines 50-54)
45    fn run(root: &mut Node, _: &MarkdownIt) {
46        let mut counter = 0;
47
48        // walk through AST recursively and count the number of two
49        // custom nodes added by other two rules
50        root.walk(|node, _| {
51            if node.is::<InlineFerris>() || node.is::<BlockFerris>() {
52                counter += 1;
53            }
54        });
55
56        // append a counter to the root as a custom node
57        root.children.push(Node::new(FerrisCounter(counter)))
58    }
Source

pub fn walk_mut(&mut self, f: impl FnMut(&mut Node, u32))

Execute function f recursively on every member of AST tree (using preorder deep-first search).

Source

pub fn walk_post(&self, f: impl FnMut(&Node, u32))

Execute function f recursively on every member of AST tree (using postorder deep-first search).

Source

pub fn walk_post_mut(&mut self, f: impl FnMut(&mut Node, u32))

Execute function f recursively on every member of AST tree (using postorder deep-first search).

Source

pub fn collect_text(&self) -> String

Walk recursively through child nodes and collect all text nodes into a single string.

Trait Implementations§

Source§

impl Debug for Node

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Node

Source§

fn default() -> Self

Create empty Node. Empty node should only be used as placeholder for functions like std::mem::take, and it cannot be rendered.

Source§

impl Drop for Node

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl Freeze for Node

§

impl !RefUnwindSafe for Node

§

impl !Send for Node

§

impl !Sync for Node

§

impl Unpin for Node

§

impl UnsafeUnpin for Node

§

impl !UnwindSafe for Node

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.