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!(
 | 
					        test_parse!(
 | 
				
			||||||
            "para\n",
 | 
					            "para\n",
 | 
				
			||||||
            (Enter(Leaf(Paragraph)), ""),
 | 
					            (Enter(Leaf(Paragraph)), ""),
 | 
				
			||||||
            (Element(Inline), "para\n"),
 | 
					            (Element(Inline), "para"),
 | 
				
			||||||
            (Exit, ""),
 | 
					            (Exit(Leaf(Paragraph)), ""),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -317,8 +317,8 @@ mod test {
 | 
				
			||||||
            "para0\npara1\n",
 | 
					            "para0\npara1\n",
 | 
				
			||||||
            (Enter(Leaf(Paragraph)), ""),
 | 
					            (Enter(Leaf(Paragraph)), ""),
 | 
				
			||||||
            (Element(Inline), "para0\n"),
 | 
					            (Element(Inline), "para0\n"),
 | 
				
			||||||
            (Element(Inline), "para1\n"),
 | 
					            (Element(Inline), "para1"),
 | 
				
			||||||
            (Exit, ""),
 | 
					            (Exit(Leaf(Paragraph)), ""),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -333,14 +333,14 @@ mod test {
 | 
				
			||||||
                "15\n", //
 | 
					                "15\n", //
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            (Enter(Leaf(Heading { level: 1 })), "#"),
 | 
					            (Enter(Leaf(Heading { level: 1 })), "#"),
 | 
				
			||||||
            (Element(Inline), " 2\n"),
 | 
					            (Element(Inline), "2"),
 | 
				
			||||||
            (Exit, "#"),
 | 
					            (Exit(Leaf(Heading { level: 1 })), "#"),
 | 
				
			||||||
            (Element(Blankline), "\n"),
 | 
					            (Element(Blankline), "\n"),
 | 
				
			||||||
            (Enter(Leaf(Heading { level: 1 })), "#"),
 | 
					            (Enter(Leaf(Heading { level: 1 })), "#"),
 | 
				
			||||||
            (Element(Inline), "   8\n"),
 | 
					            (Element(Inline), "   8\n"),
 | 
				
			||||||
            (Element(Inline), "  12\n"),
 | 
					            (Element(Inline), "  12\n"),
 | 
				
			||||||
            (Element(Inline), "15\n"),
 | 
					            (Element(Inline), "15"),
 | 
				
			||||||
            (Exit, "#"),
 | 
					            (Exit(Leaf(Heading { level: 1 })), "#"),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -356,17 +356,17 @@ mod test {
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            (Enter(Container(Blockquote)), ">"),
 | 
					            (Enter(Container(Blockquote)), ">"),
 | 
				
			||||||
            (Enter(Leaf(Paragraph)), ""),
 | 
					            (Enter(Leaf(Paragraph)), ""),
 | 
				
			||||||
            (Element(Inline), " a\n"),
 | 
					            (Element(Inline), "a"),
 | 
				
			||||||
            (Exit, ""),
 | 
					            (Exit(Leaf(Paragraph)), ""),
 | 
				
			||||||
            (Element(Blankline), "\n"),
 | 
					            (Element(Blankline), ""),
 | 
				
			||||||
            (Enter(Leaf(Heading { level: 2 })), "##"),
 | 
					            (Enter(Leaf(Heading { level: 2 })), "##"),
 | 
				
			||||||
            (Element(Inline), " hl\n"),
 | 
					            (Element(Inline), "hl"),
 | 
				
			||||||
            (Exit, "##"),
 | 
					            (Exit(Leaf(Heading { level: 2 })), "##"),
 | 
				
			||||||
            (Element(Blankline), "\n"),
 | 
					            (Element(Blankline), ""),
 | 
				
			||||||
            (Enter(Leaf(Paragraph)), ""),
 | 
					            (Enter(Leaf(Paragraph)), ""),
 | 
				
			||||||
            (Element(Inline), "  para\n"),
 | 
					            (Element(Inline), "para"),
 | 
				
			||||||
            (Exit, ""),
 | 
					            (Exit(Leaf(Paragraph)), ""),
 | 
				
			||||||
            (Exit, ">"),
 | 
					            (Exit(Container(Blockquote)), ">"),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -379,9 +379,13 @@ mod test {
 | 
				
			||||||
                "```", //
 | 
					                "```", //
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            (Enter(Leaf(CodeBlock { fence_length: 3 })), "```"),
 | 
					            (Enter(Leaf(CodeBlock { fence_length: 3 })), "```"),
 | 
				
			||||||
            (Element(Inline), "\n"),
 | 
					            (Element(Inline), ""),
 | 
				
			||||||
            (Element(Inline), "l0\n"),
 | 
					            (Element(Inline), "l0"),
 | 
				
			||||||
            (Exit, "```"),
 | 
					            (Exit(Leaf(CodeBlock { fence_length: 3 })), "```"),
 | 
				
			||||||
 | 
					            (Element(Blankline), "\n"),
 | 
				
			||||||
 | 
					            (Enter(Leaf(Paragraph)), ""),
 | 
				
			||||||
 | 
					            (Element(Inline), "para"),
 | 
				
			||||||
 | 
					            (Exit(Leaf(Paragraph)), ""),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        test_parse!(
 | 
					        test_parse!(
 | 
				
			||||||
            concat!(
 | 
					            concat!(
 | 
				
			||||||
| 
						 | 
					@ -395,8 +399,8 @@ mod test {
 | 
				
			||||||
            (Element(Inline), "lang\n"),
 | 
					            (Element(Inline), "lang\n"),
 | 
				
			||||||
            (Element(Inline), "l0\n"),
 | 
					            (Element(Inline), "l0\n"),
 | 
				
			||||||
            (Element(Inline), "```\n"),
 | 
					            (Element(Inline), "```\n"),
 | 
				
			||||||
            (Element(Inline), " l1\n"),
 | 
					            (Element(Inline), " l1"),
 | 
				
			||||||
            (Exit, "````"),
 | 
					            (Exit(Leaf(CodeBlock { fence_length: 4 })), "````"),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
use crate::Event;
 | 
					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()
 | 
					    Writer::new(events).write()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@ struct Writer<I> {
 | 
				
			||||||
    events: I,
 | 
					    events: I,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<I: Iterator<Item = Event>> Writer<I> {
 | 
					impl<'s, I: Iterator<Item = Event<'s>>> Writer<I> {
 | 
				
			||||||
    fn new(events: I) -> Self {
 | 
					    fn new(events: I) -> Self {
 | 
				
			||||||
        Self { events }
 | 
					        Self { events }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@ pub enum Atom {
 | 
				
			||||||
    Escape,
 | 
					    Escape,
 | 
				
			||||||
    Nbsp,
 | 
					    Nbsp,
 | 
				
			||||||
    OpenMarker, // ??
 | 
					    OpenMarker, // ??
 | 
				
			||||||
    Ellipses,
 | 
					    Ellipsis,
 | 
				
			||||||
    ImageMarker, // ??
 | 
					    ImageMarker, // ??
 | 
				
			||||||
    EmDash,
 | 
					    EmDash,
 | 
				
			||||||
    EnDash,
 | 
					    EnDash,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										208
									
								
								src/lib.rs
									
										
									
									
									
								
							
							
						
						
									
										208
									
								
								src/lib.rs
									
										
									
									
									
								
							| 
						 | 
					@ -12,11 +12,11 @@ pub struct Block;
 | 
				
			||||||
const EOF: char = '\0';
 | 
					const EOF: char = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, PartialEq, Eq)]
 | 
					#[derive(Debug, PartialEq, Eq)]
 | 
				
			||||||
pub enum Event2<'s> {
 | 
					pub enum Event<'s> {
 | 
				
			||||||
    /// Start of a tag.
 | 
					    /// Start of a tag.
 | 
				
			||||||
    Start(TagKind<'s>, Attributes<'s>),
 | 
					    Start(Tag<'s>, Attributes<'s>),
 | 
				
			||||||
    /// End of a tag.
 | 
					    /// End of a tag.
 | 
				
			||||||
    End(TagKind<'s>),
 | 
					    End(Tag<'s>),
 | 
				
			||||||
    /// A string object, text only.
 | 
					    /// A string object, text only.
 | 
				
			||||||
    Str(&'s str),
 | 
					    Str(&'s str),
 | 
				
			||||||
    /// A verbatim string.
 | 
					    /// 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.
 | 
					    /// A newline that may or may not break a line in the output format.
 | 
				
			||||||
    Softbreak,
 | 
					    Softbreak,
 | 
				
			||||||
    /// A newline that must break a line.
 | 
					    /// 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)]
 | 
					#[derive(Debug, PartialEq, Eq)]
 | 
				
			||||||
pub struct Attributes<'s>(Option<Box<Vec<(&'s str, &'s str)>>>);
 | 
					pub enum Tag<'s> {
 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Debug, PartialEq, Eq)]
 | 
					 | 
				
			||||||
pub enum TagKind<'s> {
 | 
					 | 
				
			||||||
    /// A paragraph.
 | 
					    /// A paragraph.
 | 
				
			||||||
    Paragraph,
 | 
					    Paragraph,
 | 
				
			||||||
    /// A heading.
 | 
					    /// A heading.
 | 
				
			||||||
| 
						 | 
					@ -82,6 +79,24 @@ pub enum TagKind<'s> {
 | 
				
			||||||
    DescriptionItem,
 | 
					    DescriptionItem,
 | 
				
			||||||
    /// A footnote definition.
 | 
					    /// A footnote definition.
 | 
				
			||||||
    Footnote { tag: &'s str },
 | 
					    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)]
 | 
					#[derive(Debug, PartialEq, Eq)]
 | 
				
			||||||
| 
						 | 
					@ -128,22 +143,96 @@ pub enum OrderedListFormat {
 | 
				
			||||||
    ParenParen,
 | 
					    ParenParen,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
impl<'s> Event<'s> {
 | 
					impl<'s> Event<'s> {
 | 
				
			||||||
    fn from_inline(src: &'s str, inline: inline::Event) -> Self {
 | 
					    fn from_inline(src: &'s str, inline: inline::Event) -> Self {
 | 
				
			||||||
        match inline {
 | 
					        let content = inline.span.of(src);
 | 
				
			||||||
            Enter
 | 
					        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)]
 | 
					#[derive(Debug, PartialEq, Eq)]
 | 
				
			||||||
pub enum Event {
 | 
					pub struct Attributes<'s>(Option<Box<Vec<(&'s str, &'s str)>>>);
 | 
				
			||||||
    Start(block::Block),
 | 
					
 | 
				
			||||||
    End,
 | 
					impl<'s> Attributes<'s> {
 | 
				
			||||||
    Inline(inline::Event),
 | 
					    #[must_use]
 | 
				
			||||||
    Blankline,
 | 
					    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> {
 | 
					pub struct Parser<'s> {
 | 
				
			||||||
| 
						 | 
					@ -166,14 +255,14 @@ impl<'s> Parser<'s> {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'s> Iterator for Parser<'s> {
 | 
					impl<'s> Iterator for Parser<'s> {
 | 
				
			||||||
    type Item = Event;
 | 
					    type Item = Event<'s>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
					    fn next(&mut self) -> Option<Self::Item> {
 | 
				
			||||||
        while let Some(parser) = &mut self.parser {
 | 
					        while let Some(parser) = &mut self.parser {
 | 
				
			||||||
            // inside leaf block, with inline content
 | 
					            // inside leaf block, with inline content
 | 
				
			||||||
            if let Some(mut inline) = parser.next() {
 | 
					            if let Some(mut inline) = parser.next() {
 | 
				
			||||||
                inline.span = inline.span.translate(self.inline_start);
 | 
					                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() {
 | 
					            } else if let Some(ev) = self.tree.next() {
 | 
				
			||||||
                match ev.kind {
 | 
					                match ev.kind {
 | 
				
			||||||
                    tree::EventKind::Element(atom) => {
 | 
					                    tree::EventKind::Element(atom) => {
 | 
				
			||||||
| 
						 | 
					@ -181,9 +270,9 @@ impl<'s> Iterator for Parser<'s> {
 | 
				
			||||||
                        parser.parse(ev.span.of(self.src));
 | 
					                        parser.parse(ev.span.of(self.src));
 | 
				
			||||||
                        self.inline_start = ev.span.start();
 | 
					                        self.inline_start = ev.span.start();
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    tree::EventKind::Exit => {
 | 
					                    tree::EventKind::Exit(block) => {
 | 
				
			||||||
                        self.parser = None;
 | 
					                        self.parser = None;
 | 
				
			||||||
                        return Some(Event::End);
 | 
					                        return Some(Event::End(Tag::from_block(self.src, block)));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    tree::EventKind::Enter(..) => unreachable!(),
 | 
					                    tree::EventKind::Enter(..) => unreachable!(),
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -199,29 +288,60 @@ impl<'s> Iterator for Parser<'s> {
 | 
				
			||||||
                if matches!(block, block::Block::Leaf(..)) {
 | 
					                if matches!(block, block::Block::Leaf(..)) {
 | 
				
			||||||
                    self.parser = Some(inline::Parser::new());
 | 
					                    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)]
 | 
					#[cfg(test)]
 | 
				
			||||||
mod test {
 | 
					mod test {
 | 
				
			||||||
 | 
					    use super::Attributes;
 | 
				
			||||||
    use super::Event::*;
 | 
					    use super::Event::*;
 | 
				
			||||||
    use crate::block::Block::*;
 | 
					    use super::Tag::*;
 | 
				
			||||||
    use crate::block::Container::*;
 | 
					 | 
				
			||||||
    use crate::block::Leaf::*;
 | 
					 | 
				
			||||||
    use crate::inline::Atom::*;
 | 
					 | 
				
			||||||
    use crate::inline::EventKind::*;
 | 
					 | 
				
			||||||
    use crate::inline::Node::*;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    macro_rules! test_parse {
 | 
					    macro_rules! test_parse {
 | 
				
			||||||
        ($($st:ident,)? $src:expr $(,$($token:expr),* $(,)?)?) => {
 | 
					        ($($st:ident,)? $src:expr $(,$($token:expr),* $(,)?)?) => {
 | 
				
			||||||
            #[allow(unused)]
 | 
					            #[allow(unused)]
 | 
				
			||||||
            let actual = super::Parser::new($src).collect::<Vec<_>>();
 | 
					            let actual = super::Parser::new($src).collect::<Vec<_>>();
 | 
				
			||||||
            let expected = &[$($($token),*,)?];
 | 
					            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() {
 | 
					    fn para() {
 | 
				
			||||||
        test_parse!(
 | 
					        test_parse!(
 | 
				
			||||||
            "para",
 | 
					            "para",
 | 
				
			||||||
            Start(Leaf(Paragraph)),
 | 
					            Start(Paragraph, Attributes::none()),
 | 
				
			||||||
            Inline(Node(Str).span(0, 4)),
 | 
					            Str("para"),
 | 
				
			||||||
            End
 | 
					            End(Paragraph),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        test_parse!(
 | 
					        test_parse!(
 | 
				
			||||||
            "pa     ra",
 | 
					            "pa     ra",
 | 
				
			||||||
            Start(Leaf(Paragraph)),
 | 
					            Start(Paragraph, Attributes::none()),
 | 
				
			||||||
            Inline(Node(Str).span(0, 9)),
 | 
					            Str("pa     ra"),
 | 
				
			||||||
            End
 | 
					            End(Paragraph),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        test_parse!(
 | 
					        test_parse!(
 | 
				
			||||||
            "para0\n\npara1",
 | 
					            "para0\n\npara1",
 | 
				
			||||||
            Start(Leaf(Paragraph)),
 | 
					            Start(Paragraph, Attributes::none()),
 | 
				
			||||||
            Inline(Node(Str).span(0, 6)),
 | 
					            Str("para0\n"),
 | 
				
			||||||
            End,
 | 
					            End(Paragraph),
 | 
				
			||||||
            Blankline,
 | 
					            Blankline,
 | 
				
			||||||
            Start(Leaf(Paragraph)),
 | 
					            Start(Paragraph, Attributes::none()),
 | 
				
			||||||
            Inline(Node(Str).span(7, 12)),
 | 
					            Str("para1"),
 | 
				
			||||||
            End,
 | 
					            End(Paragraph),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										13
									
								
								src/tree.rs
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								src/tree.rs
									
										
									
									
									
								
							| 
						 | 
					@ -4,7 +4,7 @@ use crate::Span;
 | 
				
			||||||
pub enum EventKind<C, E> {
 | 
					pub enum EventKind<C, E> {
 | 
				
			||||||
    Enter(C),
 | 
					    Enter(C),
 | 
				
			||||||
    Element(E),
 | 
					    Element(E),
 | 
				
			||||||
    Exit,
 | 
					    Exit(C),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq, Eq)]
 | 
					#[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 })
 | 
					            Some(Event { kind, span: n.span })
 | 
				
			||||||
        } else if let Some(block_ni) = self.branch.pop() {
 | 
					        } 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;
 | 
					            self.head = *next;
 | 
				
			||||||
            Some(Event {
 | 
					            Some(Event {
 | 
				
			||||||
                kind: EventKind::Exit,
 | 
					                kind: EventKind::Exit(*cont),
 | 
				
			||||||
                span: *span,
 | 
					                span: *span,
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
| 
						 | 
					@ -192,7 +197,7 @@ impl<C: Copy + std::fmt::Display, E: Copy + std::fmt::Display> std::fmt::Display
 | 
				
			||||||
                    write!(f, "{}{}", indent, container)?;
 | 
					                    write!(f, "{}{}", indent, container)?;
 | 
				
			||||||
                    level += 1;
 | 
					                    level += 1;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                EventKind::Exit => {
 | 
					                EventKind::Exit(_) => {
 | 
				
			||||||
                    level -= 1;
 | 
					                    level -= 1;
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue