wip
This commit is contained in:
		
					parent
					
						
							
								2a2851178a
							
						
					
				
			
			
				commit
				
					
						e84e7dd50b
					
				
			
		
					 5 changed files with 202 additions and 73 deletions
				
			
		
							
								
								
									
										48
									
								
								src/block.rs
									
										
									
									
									
								
							
							
						
						
									
										48
									
								
								src/block.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -306,8 +306,8 @@ mod test {
 | 
			
		|||
        test_parse!(
 | 
			
		||||
            "para\n",
 | 
			
		||||
            (Enter(Leaf(Paragraph)), ""),
 | 
			
		||||
            (Element(Inline), "para\n"),
 | 
			
		||||
            (Exit, ""),
 | 
			
		||||
            (Element(Inline), "para"),
 | 
			
		||||
            (Exit(Leaf(Paragraph)), ""),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -317,8 +317,8 @@ mod test {
 | 
			
		|||
            "para0\npara1\n",
 | 
			
		||||
            (Enter(Leaf(Paragraph)), ""),
 | 
			
		||||
            (Element(Inline), "para0\n"),
 | 
			
		||||
            (Element(Inline), "para1\n"),
 | 
			
		||||
            (Exit, ""),
 | 
			
		||||
            (Element(Inline), "para1"),
 | 
			
		||||
            (Exit(Leaf(Paragraph)), ""),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -333,14 +333,14 @@ mod test {
 | 
			
		|||
                "15\n", //
 | 
			
		||||
            ),
 | 
			
		||||
            (Enter(Leaf(Heading { level: 1 })), "#"),
 | 
			
		||||
            (Element(Inline), " 2\n"),
 | 
			
		||||
            (Exit, "#"),
 | 
			
		||||
            (Element(Inline), "2"),
 | 
			
		||||
            (Exit(Leaf(Heading { level: 1 })), "#"),
 | 
			
		||||
            (Element(Blankline), "\n"),
 | 
			
		||||
            (Enter(Leaf(Heading { level: 1 })), "#"),
 | 
			
		||||
            (Element(Inline), "   8\n"),
 | 
			
		||||
            (Element(Inline), "  12\n"),
 | 
			
		||||
            (Element(Inline), "15\n"),
 | 
			
		||||
            (Exit, "#"),
 | 
			
		||||
            (Element(Inline), "15"),
 | 
			
		||||
            (Exit(Leaf(Heading { level: 1 })), "#"),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -356,17 +356,17 @@ mod test {
 | 
			
		|||
            ),
 | 
			
		||||
            (Enter(Container(Blockquote)), ">"),
 | 
			
		||||
            (Enter(Leaf(Paragraph)), ""),
 | 
			
		||||
            (Element(Inline), " a\n"),
 | 
			
		||||
            (Exit, ""),
 | 
			
		||||
            (Element(Blankline), "\n"),
 | 
			
		||||
            (Element(Inline), "a"),
 | 
			
		||||
            (Exit(Leaf(Paragraph)), ""),
 | 
			
		||||
            (Element(Blankline), ""),
 | 
			
		||||
            (Enter(Leaf(Heading { level: 2 })), "##"),
 | 
			
		||||
            (Element(Inline), " hl\n"),
 | 
			
		||||
            (Exit, "##"),
 | 
			
		||||
            (Element(Blankline), "\n"),
 | 
			
		||||
            (Element(Inline), "hl"),
 | 
			
		||||
            (Exit(Leaf(Heading { level: 2 })), "##"),
 | 
			
		||||
            (Element(Blankline), ""),
 | 
			
		||||
            (Enter(Leaf(Paragraph)), ""),
 | 
			
		||||
            (Element(Inline), "  para\n"),
 | 
			
		||||
            (Exit, ""),
 | 
			
		||||
            (Exit, ">"),
 | 
			
		||||
            (Element(Inline), "para"),
 | 
			
		||||
            (Exit(Leaf(Paragraph)), ""),
 | 
			
		||||
            (Exit(Container(Blockquote)), ">"),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -379,9 +379,13 @@ mod test {
 | 
			
		|||
                "```", //
 | 
			
		||||
            ),
 | 
			
		||||
            (Enter(Leaf(CodeBlock { fence_length: 3 })), "```"),
 | 
			
		||||
            (Element(Inline), "\n"),
 | 
			
		||||
            (Element(Inline), "l0\n"),
 | 
			
		||||
            (Exit, "```"),
 | 
			
		||||
            (Element(Inline), ""),
 | 
			
		||||
            (Element(Inline), "l0"),
 | 
			
		||||
            (Exit(Leaf(CodeBlock { fence_length: 3 })), "```"),
 | 
			
		||||
            (Element(Blankline), "\n"),
 | 
			
		||||
            (Enter(Leaf(Paragraph)), ""),
 | 
			
		||||
            (Element(Inline), "para"),
 | 
			
		||||
            (Exit(Leaf(Paragraph)), ""),
 | 
			
		||||
        );
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            concat!(
 | 
			
		||||
| 
						 | 
				
			
			@ -395,8 +399,8 @@ mod test {
 | 
			
		|||
            (Element(Inline), "lang\n"),
 | 
			
		||||
            (Element(Inline), "l0\n"),
 | 
			
		||||
            (Element(Inline), "```\n"),
 | 
			
		||||
            (Element(Inline), " l1\n"),
 | 
			
		||||
            (Exit, "````"),
 | 
			
		||||
            (Element(Inline), " l1"),
 | 
			
		||||
            (Exit(Leaf(CodeBlock { fence_length: 4 })), "````"),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
use crate::Event;
 | 
			
		||||
 | 
			
		||||
pub fn push_html<'s, I: Iterator<Item = Event>>(s: &mut String, events: I) {
 | 
			
		||||
pub fn push_html<'s, I: Iterator<Item = Event<'s>>>(s: &mut String, events: I) {
 | 
			
		||||
    Writer::new(events).write()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ struct Writer<I> {
 | 
			
		|||
    events: I,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<I: Iterator<Item = Event>> Writer<I> {
 | 
			
		||||
impl<'s, I: Iterator<Item = Event<'s>>> Writer<I> {
 | 
			
		||||
    fn new(events: I) -> Self {
 | 
			
		||||
        Self { events }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ pub enum Atom {
 | 
			
		|||
    Escape,
 | 
			
		||||
    Nbsp,
 | 
			
		||||
    OpenMarker, // ??
 | 
			
		||||
    Ellipses,
 | 
			
		||||
    Ellipsis,
 | 
			
		||||
    ImageMarker, // ??
 | 
			
		||||
    EmDash,
 | 
			
		||||
    EnDash,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										208
									
								
								src/lib.rs
									
										
									
									
									
								
							
							
						
						
									
										208
									
								
								src/lib.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -12,11 +12,11 @@ pub struct Block;
 | 
			
		|||
const EOF: char = '\0';
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, PartialEq, Eq)]
 | 
			
		||||
pub enum Event2<'s> {
 | 
			
		||||
pub enum Event<'s> {
 | 
			
		||||
    /// Start of a tag.
 | 
			
		||||
    Start(TagKind<'s>, Attributes<'s>),
 | 
			
		||||
    Start(Tag<'s>, Attributes<'s>),
 | 
			
		||||
    /// End of a tag.
 | 
			
		||||
    End(TagKind<'s>),
 | 
			
		||||
    End(Tag<'s>),
 | 
			
		||||
    /// A string object, text only.
 | 
			
		||||
    Str(&'s str),
 | 
			
		||||
    /// A verbatim string.
 | 
			
		||||
| 
						 | 
				
			
			@ -38,16 +38,13 @@ pub enum Event2<'s> {
 | 
			
		|||
    /// A newline that may or may not break a line in the output format.
 | 
			
		||||
    Softbreak,
 | 
			
		||||
    /// A newline that must break a line.
 | 
			
		||||
    HardBreak,
 | 
			
		||||
    Hardbreak,
 | 
			
		||||
    /// An escape character, not visible in output.
 | 
			
		||||
    Escape,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Attributes are rare, better to pay 8 bytes always and sometimes an extra allocation instead of
 | 
			
		||||
// always 24 bytes.
 | 
			
		||||
#[derive(Debug, PartialEq, Eq)]
 | 
			
		||||
pub struct Attributes<'s>(Option<Box<Vec<(&'s str, &'s str)>>>);
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, PartialEq, Eq)]
 | 
			
		||||
pub enum TagKind<'s> {
 | 
			
		||||
pub enum Tag<'s> {
 | 
			
		||||
    /// A paragraph.
 | 
			
		||||
    Paragraph,
 | 
			
		||||
    /// A heading.
 | 
			
		||||
| 
						 | 
				
			
			@ -82,6 +79,24 @@ pub enum TagKind<'s> {
 | 
			
		|||
    DescriptionItem,
 | 
			
		||||
    /// A footnote definition.
 | 
			
		||||
    Footnote { tag: &'s str },
 | 
			
		||||
    /// A subscripted element.
 | 
			
		||||
    Subscript,
 | 
			
		||||
    /// A superscripted element.
 | 
			
		||||
    Superscript,
 | 
			
		||||
    /// An inserted element.
 | 
			
		||||
    Insert,
 | 
			
		||||
    /// A deleted element.
 | 
			
		||||
    Delete,
 | 
			
		||||
    /// An element emphasized with a bold typeface.
 | 
			
		||||
    Strong,
 | 
			
		||||
    /// An emphasized element.
 | 
			
		||||
    Emphasis,
 | 
			
		||||
    /// A highlighted inline element.
 | 
			
		||||
    Mark,
 | 
			
		||||
    /// An quoted element, using single quotes.
 | 
			
		||||
    SingleQuoted,
 | 
			
		||||
    /// A quoted inline element, using double quotes.
 | 
			
		||||
    DoubleQuoted,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, PartialEq, Eq)]
 | 
			
		||||
| 
						 | 
				
			
			@ -128,22 +143,96 @@ pub enum OrderedListFormat {
 | 
			
		|||
    ParenParen,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
impl<'s> Event<'s> {
 | 
			
		||||
    fn from_inline(src: &'s str, inline: inline::Event) -> Self {
 | 
			
		||||
        match inline {
 | 
			
		||||
            Enter
 | 
			
		||||
        let content = inline.span.of(src);
 | 
			
		||||
        match inline.kind {
 | 
			
		||||
            inline::EventKind::Enter(c) | inline::EventKind::Exit(c) => {
 | 
			
		||||
                let t = match c {
 | 
			
		||||
                    inline::Container::Span => Tag::Span,
 | 
			
		||||
                    inline::Container::Subscript => Tag::Subscript,
 | 
			
		||||
                    inline::Container::Superscript => Tag::Superscript,
 | 
			
		||||
                    inline::Container::Insert => Tag::Insert,
 | 
			
		||||
                    inline::Container::Delete => Tag::Delete,
 | 
			
		||||
                    inline::Container::Emphasis => Tag::Emphasis,
 | 
			
		||||
                    inline::Container::Strong => Tag::Strong,
 | 
			
		||||
                    inline::Container::Mark => Tag::Mark,
 | 
			
		||||
                    inline::Container::SingleQuoted => Tag::SingleQuoted,
 | 
			
		||||
                    inline::Container::DoubleQuoted => Tag::DoubleQuoted,
 | 
			
		||||
                    _ => todo!(),
 | 
			
		||||
                };
 | 
			
		||||
                if matches!(inline.kind, inline::EventKind::Enter(_)) {
 | 
			
		||||
                    Self::Start(t, Attributes::none())
 | 
			
		||||
                } else {
 | 
			
		||||
                    Self::End(t)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            inline::EventKind::Atom(a) => match a {
 | 
			
		||||
                inline::Atom::Ellipsis => Self::Ellipsis,
 | 
			
		||||
                inline::Atom::EnDash => Self::EnDash,
 | 
			
		||||
                inline::Atom::EmDash => Self::EmDash,
 | 
			
		||||
                inline::Atom::Nbsp => Self::NonBreakingSpace,
 | 
			
		||||
                inline::Atom::Softbreak => Self::Softbreak,
 | 
			
		||||
                inline::Atom::Hardbreak => Self::Hardbreak,
 | 
			
		||||
                inline::Atom::Escape => Self::Escape,
 | 
			
		||||
                _ => todo!(),
 | 
			
		||||
            },
 | 
			
		||||
            inline::EventKind::Node(n) => match n {
 | 
			
		||||
                inline::Node::Str => Self::Str(content),
 | 
			
		||||
                inline::Node::Verbatim => Self::Verbatim(content),
 | 
			
		||||
                inline::Node::InlineMath => Self::Math {
 | 
			
		||||
                    content,
 | 
			
		||||
                    display: false,
 | 
			
		||||
                },
 | 
			
		||||
                inline::Node::DisplayMath => Self::Math {
 | 
			
		||||
                    content,
 | 
			
		||||
                    display: true,
 | 
			
		||||
                },
 | 
			
		||||
                _ => todo!(),
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
impl<'s> Tag<'s> {
 | 
			
		||||
    fn from_block(src: &'s str, block: block::Block) -> Self {
 | 
			
		||||
        match block {
 | 
			
		||||
            block::Block::Leaf(l) => match l {
 | 
			
		||||
                block::Leaf::Paragraph => Self::Paragraph,
 | 
			
		||||
                block::Leaf::Heading { level } => Self::Heading { level },
 | 
			
		||||
                block::Leaf::CodeBlock { .. } => Self::CodeBlock { language: None },
 | 
			
		||||
                _ => todo!(),
 | 
			
		||||
            },
 | 
			
		||||
            block::Block::Container(c) => match c {
 | 
			
		||||
                block::Container::Blockquote => Self::Blockquote,
 | 
			
		||||
                block::Container::Div { .. } => Self::Div,
 | 
			
		||||
                block::Container::Footnote { .. } => Self::Footnote { tag: todo!() },
 | 
			
		||||
                _ => todo!(),
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Attributes are rare, better to pay 8 bytes always and sometimes an extra allocation instead of
 | 
			
		||||
// always 24 bytes.
 | 
			
		||||
#[derive(Debug, PartialEq, Eq)]
 | 
			
		||||
pub enum Event {
 | 
			
		||||
    Start(block::Block),
 | 
			
		||||
    End,
 | 
			
		||||
    Inline(inline::Event),
 | 
			
		||||
    Blankline,
 | 
			
		||||
pub struct Attributes<'s>(Option<Box<Vec<(&'s str, &'s str)>>>);
 | 
			
		||||
 | 
			
		||||
impl<'s> Attributes<'s> {
 | 
			
		||||
    #[must_use]
 | 
			
		||||
    pub fn none() -> Self {
 | 
			
		||||
        Self(None)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[must_use]
 | 
			
		||||
    pub fn valid(src: &str) -> bool {
 | 
			
		||||
        todo!()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[must_use]
 | 
			
		||||
    pub fn parse(src: &'s str) -> Self {
 | 
			
		||||
        todo!()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Parser<'s> {
 | 
			
		||||
| 
						 | 
				
			
			@ -166,14 +255,14 @@ impl<'s> Parser<'s> {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
impl<'s> Iterator for Parser<'s> {
 | 
			
		||||
    type Item = Event;
 | 
			
		||||
    type Item = Event<'s>;
 | 
			
		||||
 | 
			
		||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
        while let Some(parser) = &mut self.parser {
 | 
			
		||||
            // inside leaf block, with inline content
 | 
			
		||||
            if let Some(mut inline) = parser.next() {
 | 
			
		||||
                inline.span = inline.span.translate(self.inline_start);
 | 
			
		||||
                return Some(Event::Inline(inline));
 | 
			
		||||
                return Some(Event::from_inline(self.src, inline));
 | 
			
		||||
            } else if let Some(ev) = self.tree.next() {
 | 
			
		||||
                match ev.kind {
 | 
			
		||||
                    tree::EventKind::Element(atom) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -181,9 +270,9 @@ impl<'s> Iterator for Parser<'s> {
 | 
			
		|||
                        parser.parse(ev.span.of(self.src));
 | 
			
		||||
                        self.inline_start = ev.span.start();
 | 
			
		||||
                    }
 | 
			
		||||
                    tree::EventKind::Exit => {
 | 
			
		||||
                    tree::EventKind::Exit(block) => {
 | 
			
		||||
                        self.parser = None;
 | 
			
		||||
                        return Some(Event::End);
 | 
			
		||||
                        return Some(Event::End(Tag::from_block(self.src, block)));
 | 
			
		||||
                    }
 | 
			
		||||
                    tree::EventKind::Enter(..) => unreachable!(),
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -199,29 +288,60 @@ impl<'s> Iterator for Parser<'s> {
 | 
			
		|||
                if matches!(block, block::Block::Leaf(..)) {
 | 
			
		||||
                    self.parser = Some(inline::Parser::new());
 | 
			
		||||
                }
 | 
			
		||||
                Event::Start(block)
 | 
			
		||||
                Event::Start(Tag::from_block(self.src, block), Attributes::none())
 | 
			
		||||
            }
 | 
			
		||||
            tree::EventKind::Exit => Event::End,
 | 
			
		||||
            tree::EventKind::Exit(block) => Event::End(Tag::from_block(self.src, block)),
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod test {
 | 
			
		||||
    use super::Attributes;
 | 
			
		||||
    use super::Event::*;
 | 
			
		||||
    use crate::block::Block::*;
 | 
			
		||||
    use crate::block::Container::*;
 | 
			
		||||
    use crate::block::Leaf::*;
 | 
			
		||||
    use crate::inline::Atom::*;
 | 
			
		||||
    use crate::inline::EventKind::*;
 | 
			
		||||
    use crate::inline::Node::*;
 | 
			
		||||
    use super::Tag::*;
 | 
			
		||||
 | 
			
		||||
    macro_rules! test_parse {
 | 
			
		||||
        ($($st:ident,)? $src:expr $(,$($token:expr),* $(,)?)?) => {
 | 
			
		||||
            #[allow(unused)]
 | 
			
		||||
            let actual = super::Parser::new($src).collect::<Vec<_>>();
 | 
			
		||||
            let expected = &[$($($token),*,)?];
 | 
			
		||||
            assert_eq!(actual, expected, "\n\n{}\n\n", $src);
 | 
			
		||||
            assert_eq!(
 | 
			
		||||
                actual,
 | 
			
		||||
                expected,
 | 
			
		||||
                concat!(
 | 
			
		||||
                    "\n",
 | 
			
		||||
                    "\x1b[0;1m====================== INPUT =========================\x1b[0m\n",
 | 
			
		||||
                    "\x1b[2m{}",
 | 
			
		||||
                    "\x1b[0;1m================ ACTUAL vs EXPECTED ==================\x1b[0m\n",
 | 
			
		||||
                    "{}",
 | 
			
		||||
                    "\x1b[0;1m======================================================\x1b[0m\n",
 | 
			
		||||
                ),
 | 
			
		||||
                $src,
 | 
			
		||||
                {
 | 
			
		||||
                    let a = actual.iter().map(|n| format!("{:?}", n)).collect::<Vec<_>>();
 | 
			
		||||
                    let b = expected.iter().map(|n| format!("{:?}", n)).collect::<Vec<_>>();
 | 
			
		||||
                    let max = a.len().max(b.len());
 | 
			
		||||
                    let a_width = a.iter().map(|a| a.len()).max().unwrap_or(0);
 | 
			
		||||
                    a.iter()
 | 
			
		||||
                        .map(AsRef::as_ref)
 | 
			
		||||
                        .chain(std::iter::repeat(""))
 | 
			
		||||
                        .zip(b.iter().map(AsRef::as_ref).chain(std::iter::repeat("")))
 | 
			
		||||
                        .take(max)
 | 
			
		||||
                        .map(|(a, b)|
 | 
			
		||||
                            format!(
 | 
			
		||||
                                "\x1b[{}m{:a_width$}\x1b[0m    {}=    \x1b[{}m{}\x1b[0m\n",
 | 
			
		||||
                                if a == b { "2" } else { "31" },
 | 
			
		||||
                                a,
 | 
			
		||||
                                if a == b { '=' } else { '!' },
 | 
			
		||||
                                if a == b { "2" } else { "32" },
 | 
			
		||||
                                b,
 | 
			
		||||
                                a_width = a_width,
 | 
			
		||||
                            )
 | 
			
		||||
                        )
 | 
			
		||||
                        .collect::<String>()
 | 
			
		||||
                },
 | 
			
		||||
            );
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -229,25 +349,25 @@ mod test {
 | 
			
		|||
    fn para() {
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "para",
 | 
			
		||||
            Start(Leaf(Paragraph)),
 | 
			
		||||
            Inline(Node(Str).span(0, 4)),
 | 
			
		||||
            End
 | 
			
		||||
            Start(Paragraph, Attributes::none()),
 | 
			
		||||
            Str("para"),
 | 
			
		||||
            End(Paragraph),
 | 
			
		||||
        );
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "pa     ra",
 | 
			
		||||
            Start(Leaf(Paragraph)),
 | 
			
		||||
            Inline(Node(Str).span(0, 9)),
 | 
			
		||||
            End
 | 
			
		||||
            Start(Paragraph, Attributes::none()),
 | 
			
		||||
            Str("pa     ra"),
 | 
			
		||||
            End(Paragraph),
 | 
			
		||||
        );
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "para0\n\npara1",
 | 
			
		||||
            Start(Leaf(Paragraph)),
 | 
			
		||||
            Inline(Node(Str).span(0, 6)),
 | 
			
		||||
            End,
 | 
			
		||||
            Start(Paragraph, Attributes::none()),
 | 
			
		||||
            Str("para0\n"),
 | 
			
		||||
            End(Paragraph),
 | 
			
		||||
            Blankline,
 | 
			
		||||
            Start(Leaf(Paragraph)),
 | 
			
		||||
            Inline(Node(Str).span(7, 12)),
 | 
			
		||||
            End,
 | 
			
		||||
            Start(Paragraph, Attributes::none()),
 | 
			
		||||
            Str("para1"),
 | 
			
		||||
            End(Paragraph),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								src/tree.rs
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								src/tree.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -4,7 +4,7 @@ use crate::Span;
 | 
			
		|||
pub enum EventKind<C, E> {
 | 
			
		||||
    Enter(C),
 | 
			
		||||
    Element(E),
 | 
			
		||||
    Exit,
 | 
			
		||||
    Exit(C),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq, Eq)]
 | 
			
		||||
| 
						 | 
				
			
			@ -53,10 +53,15 @@ impl<C: Copy, E: Copy> Iterator for Tree<C, E> {
 | 
			
		|||
            };
 | 
			
		||||
            Some(Event { kind, span: n.span })
 | 
			
		||||
        } else if let Some(block_ni) = self.branch.pop() {
 | 
			
		||||
            let Node { next, span, .. } = &self.nodes[block_ni.index()];
 | 
			
		||||
            let Node { next, kind, span } = &self.nodes[block_ni.index()];
 | 
			
		||||
            let cont = if let NodeKind::Container(c, _) = kind {
 | 
			
		||||
                c
 | 
			
		||||
            } else {
 | 
			
		||||
                panic!();
 | 
			
		||||
            };
 | 
			
		||||
            self.head = *next;
 | 
			
		||||
            Some(Event {
 | 
			
		||||
                kind: EventKind::Exit,
 | 
			
		||||
                kind: EventKind::Exit(*cont),
 | 
			
		||||
                span: *span,
 | 
			
		||||
            })
 | 
			
		||||
        } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -192,7 +197,7 @@ impl<C: Copy + std::fmt::Display, E: Copy + std::fmt::Display> std::fmt::Display
 | 
			
		|||
                    write!(f, "{}{}", indent, container)?;
 | 
			
		||||
                    level += 1;
 | 
			
		||||
                }
 | 
			
		||||
                EventKind::Exit => {
 | 
			
		||||
                EventKind::Exit(_) => {
 | 
			
		||||
                    level -= 1;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue