This commit is contained in:
Noah Hellman 2022-12-07 19:32:42 +01:00
parent c53988cc47
commit a994228bb5
2 changed files with 55 additions and 32 deletions

View file

@ -68,7 +68,13 @@ impl<'s, I: Iterator<Item = Event<'s>>, W: std::fmt::Write> Writer<I, W> {
Container::Footnote { .. } => todo!(), Container::Footnote { .. } => todo!(),
Container::Table => self.out.write_str("<table>")?, Container::Table => self.out.write_str("<table>")?,
Container::TableRow => self.out.write_str("<tr>")?, Container::TableRow => self.out.write_str("<tr>")?,
Container::Div => self.out.write_str("<div>")?, Container::Div { class } => {
if let Some(c) = class {
write!(self.out, r#"<div class="{}">"#, c)?;
} else {
self.out.write_str("<div>")?;
}
}
Container::Span => self.out.write_str("<span>")?, Container::Span => self.out.write_str("<span>")?,
Container::Paragraph => self.out.write_str("<p>")?, Container::Paragraph => self.out.write_str("<p>")?,
Container::Heading { level } => write!(self.out, "<h{}>", level)?, Container::Heading { level } => write!(self.out, "<h{}>", level)?,
@ -108,7 +114,7 @@ impl<'s, I: Iterator<Item = Event<'s>>, W: std::fmt::Write> Writer<I, W> {
Container::Footnote { .. } => todo!(), Container::Footnote { .. } => todo!(),
Container::Table => self.out.write_str("</table>")?, Container::Table => self.out.write_str("</table>")?,
Container::TableRow => self.out.write_str("</tr>")?, Container::TableRow => self.out.write_str("</tr>")?,
Container::Div => self.out.write_str("</div>")?, Container::Div { .. } => self.out.write_str("</div>")?,
Container::Paragraph => self.out.write_str("</p>")?, Container::Paragraph => self.out.write_str("</p>")?,
Container::Heading { level } => write!(self.out, "</h{}>", level)?, Container::Heading { level } => write!(self.out, "</h{}>", level)?,
Container::TableCell => self.out.write_str("</td>")?, Container::TableCell => self.out.write_str("</td>")?,

View file

@ -47,7 +47,7 @@ pub enum Container<'s> {
/// A row element of a table. /// A row element of a table.
TableRow, TableRow,
/// A block-level divider element. /// A block-level divider element.
Div, Div { class: Option<&'s str> },
/// A paragraph. /// A paragraph.
Paragraph, Paragraph,
/// A heading. /// A heading.
@ -98,7 +98,7 @@ impl<'s> Container<'s> {
| Self::Footnote { .. } | Self::Footnote { .. }
| Self::Table | Self::Table
| Self::TableRow | Self::TableRow
| Self::Div | Self::Div { .. }
| Self::Paragraph | Self::Paragraph
| Self::Heading { .. } | Self::Heading { .. }
| Self::DescriptionTerm | Self::DescriptionTerm
@ -131,7 +131,7 @@ impl<'s> Container<'s> {
| Self::Footnote { .. } | Self::Footnote { .. }
| Self::Table | Self::Table
| Self::TableRow | Self::TableRow
| Self::Div => true, | Self::Div { .. } => true,
Self::Paragraph Self::Paragraph
| Self::Heading { .. } | Self::Heading { .. }
| Self::TableCell | Self::TableCell
@ -204,8 +204,6 @@ pub enum Atom {
EmDash, EmDash,
/// A thematic break, typically a horizontal rule. /// A thematic break, typically a horizontal rule.
ThematicBreak, ThematicBreak,
/// A blank line.
Blankline,
/// A space that may not break a line. /// A space that may not break a line.
NonBreakingSpace, NonBreakingSpace,
/// 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.
@ -214,6 +212,8 @@ pub enum Atom {
Hardbreak, Hardbreak,
/// An escape character, not visible in output. /// An escape character, not visible in output.
Escape, Escape,
/// A blank line, not visible in output.
Blankline,
} }
impl<'s> Event<'s> { impl<'s> Event<'s> {
@ -278,7 +278,7 @@ impl<'s> Container<'s> {
}, },
block::Block::Container(c) => match c { block::Block::Container(c) => match c {
block::Container::Blockquote => Self::Blockquote, block::Container::Blockquote => Self::Blockquote,
block::Container::Div { .. } => Self::Div, block::Container::Div { .. } => Self::Div { class: None },
block::Container::Footnote { .. } => Self::Footnote { tag: todo!() }, block::Container::Footnote { .. } => Self::Footnote { tag: todo!() },
_ => todo!(), _ => todo!(),
}, },
@ -297,13 +297,16 @@ impl<'s> Attributes<'s> {
Self(None) Self(None)
} }
pub fn take(&mut self) -> Self {
Self(self.0.take())
}
#[must_use] #[must_use]
pub fn valid(src: &str) -> bool { pub fn valid(src: &str) -> bool {
todo!() todo!()
} }
#[must_use] pub fn parse(&mut self, src: &'s str) {
pub fn parse(src: &'s str) -> Self {
todo!() todo!()
} }
} }
@ -313,6 +316,7 @@ pub struct Parser<'s> {
tree: block::Tree, tree: block::Tree,
parser: Option<inline::Parser<'s>>, parser: Option<inline::Parser<'s>>,
inline_start: usize, inline_start: usize,
attributes: Attributes<'s>,
} }
impl<'s> Parser<'s> { impl<'s> Parser<'s> {
@ -323,6 +327,7 @@ impl<'s> Parser<'s> {
tree: block::parse(src), tree: block::parse(src),
parser: None, parser: None,
inline_start: 0, inline_start: 0,
attributes: Attributes::none(),
} }
} }
} }
@ -351,29 +356,42 @@ impl<'s> Iterator for Parser<'s> {
} }
} }
self.tree.next().map(|ev| match ev.kind { for ev in &mut self.tree {
tree::EventKind::Element(atom) => { let content = ev.span.of(self.src);
assert_eq!(atom, block::Atom::Blankline); let event = match ev.kind {
Event::Atom(Atom::Blankline) tree::EventKind::Element(atom) => match atom {
block::Atom::Inline => panic!("inline outside leaf block"),
block::Atom::Blankline => Event::Atom(Atom::Blankline),
block::Atom::Attributes => {
self.attributes.parse(content);
continue;
} }
},
tree::EventKind::Enter(block) => { tree::EventKind::Enter(block) => {
if matches!(block, block::Block::Leaf(l)) { if matches!(block, block::Block::Leaf(_)) {
self.parser = Some(inline::Parser::new()); self.parser = Some(inline::Parser::new());
self.inline_start = ev.span.end();
} }
match block { let container = match block {
block::Block::Leaf(block::Leaf::Paragraph) => self.inline_start = ev.span.end(),
block::Block::Leaf(block::Leaf::CodeBlock { .. }) => { block::Block::Leaf(block::Leaf::CodeBlock { .. }) => {
let lang = self.tree.next().unwrap(); self.inline_start += 1; // skip newline
self.inline_start = lang.span.end(); Container::CodeBlock {
let lang = (!lang.span.is_empty()).then(|| lang.span.of(self.src).trim()); lang: (!ev.span.is_empty()).then(|| ev.span.of(self.src)),
return Event::Start(Container::CodeBlock { lang }, Attributes::none());
} }
_ => {}
} }
Event::Start(Container::from_block(self.src, block), Attributes::none()) block::Block::Container(block::Container::Div { .. }) => Container::Div {
class: (!ev.span.is_empty()).then(|| ev.span.of(self.src)),
},
b => Container::from_block(self.src, b),
};
Event::Start(container, self.attributes.take())
} }
tree::EventKind::Exit(block) => Event::End(Container::from_block(self.src, block)), tree::EventKind::Exit(block) => Event::End(Container::from_block(self.src, block)),
}) };
return Some(event);
}
None
} }
} }
@ -447,7 +465,6 @@ mod test {
Start(Paragraph, Attributes::none()), Start(Paragraph, Attributes::none()),
Str("para0"), Str("para0"),
End(Paragraph), End(Paragraph),
Atom(Blankline),
Start(Paragraph, Attributes::none()), Start(Paragraph, Attributes::none()),
Str("para1"), Str("para1"),
End(Paragraph), End(Paragraph),