diff --git a/src/fmt_md.rs b/src/fmt_md.rs index 8e49f7e..35c5f89 100644 --- a/src/fmt_md.rs +++ b/src/fmt_md.rs @@ -163,9 +163,6 @@ impl<'a> MdWriterState<'a> { MdElemRef::ListItem(ListItemRef(idx, item)) => { self.write_list_item(out, &idx, item); } - MdElemRef::Inline(inline) => { - self.write_inline_element(out, inline); - } MdElemRef::NonSelectable(node) => match node { NonSelectable::ThematicBreak => { out.with_block(Block::Plain, |out| out.write_str("***")); @@ -177,6 +174,9 @@ impl<'a> MdWriterState<'a> { NonSelectable::BlockQuote(block) => self.write_block_quote(out, block), NonSelectable::List(list) => self.write_list(out, list), NonSelectable::Table(table) => self.write_table(out, table), + NonSelectable::Inline(inline) => { + self.write_inline_element(out, inline); + } }, } } @@ -395,17 +395,17 @@ impl<'a> MdWriterState<'a> { W: SimpleWrite, { match elem { - Inline::Span { variant, children } => { + Inline::Formatting(Formatting { variant, children }) => { let surround = match variant { - SpanVariant::Delete => "~~", - SpanVariant::Emphasis => "_", - SpanVariant::Strong => "**", + FormattingVariant::Delete => "~~", + FormattingVariant::Emphasis => "_", + FormattingVariant::Strong => "**", }; out.write_str(surround); self.write_line(out, children); out.write_str(surround); } - Inline::Text { variant, value } => { + Inline::Text(Text { variant, value }) => { let surround = match variant { TextVariant::Plain => "", TextVariant::Code => "`", @@ -416,12 +416,12 @@ impl<'a> MdWriterState<'a> { out.write_str(value); out.write_str(surround); } - Inline::Link { text, link_definition } => { + Inline::Link(Link { text, link_definition }) => { self.write_link_inline(out, ReifiedLabel::Inline(text), link_definition, |me, out| { me.write_line(out, text) }); } - Inline::Image { alt, link } => { + Inline::Image(Image { alt, link }) => { out.write_char('!'); self.write_link_inline(out, ReifiedLabel::Identifier(alt), link, |_, out| out.write_str(alt)); } @@ -614,34 +614,34 @@ pub mod tests { Section(_), ListItem(..), - Inline(Inline::Span{variant: SpanVariant::Delete, ..}), - Inline(Inline::Span{variant: SpanVariant::Emphasis, ..}), - Inline(Inline::Span{variant: SpanVariant::Strong, ..}), - - Inline(Inline::Text{variant: TextVariant::Plain, ..}), - Inline(Inline::Text{variant: TextVariant::Code, ..}), - Inline(Inline::Text{variant: TextVariant::Math, ..}), - Inline(Inline::Text{variant: TextVariant::Html, ..}), - - Inline(Inline::Link{link_definition: LinkDefinition{title: None, reference: LinkReference::Inline, ..}, ..}), - Inline(Inline::Link{link_definition: LinkDefinition{title: None, reference: LinkReference::Full(_), ..}, ..}), - Inline(Inline::Link{link_definition: LinkDefinition{title: None, reference: LinkReference::Collapsed, ..}, ..}), - Inline(Inline::Link{link_definition: LinkDefinition{title: None, reference: LinkReference::Shortcut, ..}, ..}), - Inline(Inline::Link{link_definition: LinkDefinition{title: Some(_), reference: LinkReference::Inline, ..}, ..}), - Inline(Inline::Link{link_definition: LinkDefinition{title: Some(_), reference: LinkReference::Full(_), ..}, ..}), - Inline(Inline::Link{link_definition: LinkDefinition{title: Some(_), reference: LinkReference::Collapsed, ..}, ..}), - Inline(Inline::Link{link_definition: LinkDefinition{title: Some(_), reference: LinkReference::Shortcut, ..}, ..}), - - Inline(Inline::Image{link: LinkDefinition{title: None, reference: LinkReference::Inline, ..}, ..}), - Inline(Inline::Image{link: LinkDefinition{title: None, reference: LinkReference::Full(_), ..}, ..}), - Inline(Inline::Image{link: LinkDefinition{title: None, reference: LinkReference::Collapsed, ..}, ..}), - Inline(Inline::Image{link: LinkDefinition{title: None, reference: LinkReference::Shortcut, ..}, ..}), - Inline(Inline::Image{link: LinkDefinition{title: Some(_), reference: LinkReference::Inline, ..}, ..}), - Inline(Inline::Image{link: LinkDefinition{title: Some(_), reference: LinkReference::Full(_), ..}, ..}), - Inline(Inline::Image{link: LinkDefinition{title: Some(_), reference: LinkReference::Collapsed, ..}, ..}), - Inline(Inline::Image{link: LinkDefinition{title: Some(_), reference: LinkReference::Shortcut, ..}, ..}), - - Inline(Inline::Footnote{..}), + NonSelectable(NonSelectable::Inline(Inline::Formatting(Formatting{variant: FormattingVariant::Delete, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Formatting(Formatting{variant: FormattingVariant::Emphasis, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Formatting(Formatting{variant: FormattingVariant::Strong, ..}))), + + NonSelectable(NonSelectable::Inline(Inline::Text(Text{variant: TextVariant::Plain, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Text(Text{variant: TextVariant::Code, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Text(Text{variant: TextVariant::Math, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Text(Text{variant: TextVariant::Html, ..}))), + + NonSelectable(NonSelectable::Inline(Inline::Link(Link{link_definition: LinkDefinition{title: None, reference: LinkReference::Inline, ..}, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Link(Link{link_definition: LinkDefinition{title: None, reference: LinkReference::Full(_), ..}, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Link(Link{link_definition: LinkDefinition{title: None, reference: LinkReference::Collapsed, ..}, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Link(Link{link_definition: LinkDefinition{title: None, reference: LinkReference::Shortcut, ..}, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Link(Link{link_definition: LinkDefinition{title: Some(_), reference: LinkReference::Inline, ..}, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Link(Link{link_definition: LinkDefinition{title: Some(_), reference: LinkReference::Full(_), ..}, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Link(Link{link_definition: LinkDefinition{title: Some(_), reference: LinkReference::Collapsed, ..}, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Link(Link{link_definition: LinkDefinition{title: Some(_), reference: LinkReference::Shortcut, ..}, ..}))), + + NonSelectable(NonSelectable::Inline(Inline::Image(Image{link: LinkDefinition{title: None, reference: LinkReference::Inline, ..}, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Image(Image{link: LinkDefinition{title: None, reference: LinkReference::Full(_), ..}, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Image(Image{link: LinkDefinition{title: None, reference: LinkReference::Collapsed, ..}, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Image(Image{link: LinkDefinition{title: None, reference: LinkReference::Shortcut, ..}, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Image(Image{link: LinkDefinition{title: Some(_), reference: LinkReference::Inline, ..}, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Image(Image{link: LinkDefinition{title: Some(_), reference: LinkReference::Full(_), ..}, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Image(Image{link: LinkDefinition{title: Some(_), reference: LinkReference::Collapsed, ..}, ..}))), + NonSelectable(NonSelectable::Inline(Inline::Image(Image{link: LinkDefinition{title: Some(_), reference: LinkReference::Shortcut, ..}, ..}))), + + NonSelectable(NonSelectable::Inline(Inline::Footnote{..})), NonSelectable(NonSelectable::ThematicBreak), NonSelectable(NonSelectable::CodeBlock(CodeBlock{variant: CodeVariant::Code(None), ..})), @@ -1313,10 +1313,10 @@ pub mod tests { #[test] fn text() { check_render( - vec![MdElem::Inline(Inline::Text { + vec![MdElem::Inline(Inline::Text(Text { variant: TextVariant::Plain, value: "hello world".to_string(), - })], + }))], indoc! {"hello world"}, ); } @@ -1324,10 +1324,10 @@ pub mod tests { #[test] fn code() { check_render( - vec![MdElem::Inline(Inline::Text { + vec![MdElem::Inline(Inline::Text(Text { variant: TextVariant::Code, value: "hello world".to_string(), - })], + }))], indoc! {"`hello world`"}, ); } @@ -1335,10 +1335,10 @@ pub mod tests { #[test] fn math() { check_render( - vec![MdElem::Inline(Inline::Text { + vec![MdElem::Inline(Inline::Text(Text { variant: TextVariant::Math, value: "hello world".to_string(), - })], + }))], indoc! {"$hello world$"}, ); } @@ -1346,10 +1346,10 @@ pub mod tests { #[test] fn html() { check_render( - vec![MdElem::Inline(Inline::Text { + vec![MdElem::Inline(Inline::Text(Text { variant: TextVariant::Html, value: "".to_string(), - })], + }))], indoc! {""}, ); } @@ -1494,14 +1494,14 @@ pub mod tests { fn check_link(link: LinkDefinition, expect: &str) { let nodes = vec![ - MdElem::Inline(Inline::Link { + MdElem::Inline(Inline::Link(Link { text: vec![ mdq_inline!("hello "), mdq_inline!(span Emphasis [mdq_inline!("world")]), mdq_inline!("!"), ], link_definition: link, - }), + })), m_node!(MdElem::Block::LeafBlock::ThematicBreak), ]; check_render(nodes, expect); @@ -1647,10 +1647,10 @@ pub mod tests { fn check_image(link: LinkDefinition, expect: &str) { let nodes = vec![ - MdElem::Inline(Inline::Image { + MdElem::Inline(Inline::Image(Image { alt: "hello _world_!".to_string(), link, - }), + })), m_node!(MdElem::Block::LeafBlock::ThematicBreak), ]; check_render(nodes, expect); @@ -1711,14 +1711,14 @@ pub mod tests { md_elems![Block::LeafBlock::Paragraph { body: vec![ mdq_inline!("Hello, "), - Inline::Link { + m_node!(Inline::Link { text: vec![mdq_inline!("world"),], link_definition: LinkDefinition { url: "https://example.com".to_string(), title: None, reference: LinkReference::Full("1".to_string()), } - }, + }), mdq_inline!("! This is interesting"), Inline::Footnote(Footnote { label: "a".to_string(), @@ -1843,22 +1843,22 @@ pub mod tests { label: "c".to_string(), text: md_elems!["footnote 2"] }), - Inline::Link { + m_node!(Inline::Link { text: vec![mdq_inline!("b-text")], link_definition: LinkDefinition { url: "https://example.com/b".to_string(), title: None, reference: LinkReference::Full("b".to_string()), }, - }, - Inline::Link { + }), + m_node!(Inline::Link { text: vec![mdq_inline!("a-text")], link_definition: LinkDefinition { url: "https://example.com/a".to_string(), title: None, reference: LinkReference::Full("a".to_string()), }, - }, + }), ] }], indoc! {r#" @@ -1878,14 +1878,14 @@ pub mod tests { title: vec![mdq_inline!("First section")], body: md_elems![Block::LeafBlock::Paragraph { body: vec![ - Inline::Link { + m_node!(Inline::Link { text: vec![mdq_inline!("link description")], link_definition: LinkDefinition { url: "https://exampl.com".to_string(), title: None, reference: LinkReference::Full("1".to_string()), }, - }, + }), mdq_inline!(" and then a thought"), Inline::Footnote(Footnote { label: "a".to_string(), diff --git a/src/fmt_str.rs b/src/fmt_str.rs index 389ea33..4eab22a 100644 --- a/src/fmt_str.rs +++ b/src/fmt_str.rs @@ -1,4 +1,4 @@ -use crate::tree::{Inline, TextVariant}; +use crate::tree::{Formatting, Image, Inline, Link, Text, TextVariant}; use std::borrow::Borrow; pub fn inlines_to_plain_string>(inlines: &[N]) -> String { @@ -15,14 +15,14 @@ fn build_inlines>(out: &mut String, inlines: &[N]) { fn build_inline(out: &mut String, elem: &Inline) { match elem { - Inline::Span { children, .. } => build_inlines(out, children), - Inline::Text { variant, value, .. } => { + Inline::Formatting(Formatting { children, .. }) => build_inlines(out, children), + Inline::Text(Text { variant, value, .. }) => { if !matches!(variant, TextVariant::Html) { out.push_str(value) } } - Inline::Link { text, .. } => build_inlines(out, text), - Inline::Image { alt, .. } => out.push_str(alt), + Inline::Link(Link { text, .. }) => build_inlines(out, text), + Inline::Image(Image { alt, .. }) => out.push_str(alt), Inline::Footnote(footnote) => { out.push_str("[^"); out.push_str(&footnote.label); @@ -36,18 +36,18 @@ mod tests { use super::*; use indoc::indoc; - use crate::tree::{Block, Inline, LeafBlock, MdElem, ReadOptions, SpanVariant, TextVariant}; + use crate::tree::{Block, FormattingVariant, Inline, LeafBlock, MdElem, ReadOptions, TextVariant}; use crate::unwrap; use markdown::ParseOptions; crate::variants_checker!(VARIANTS_CHECKER = Inline { - Span { variant: SpanVariant::Delete, .. }, - Span { variant: SpanVariant::Emphasis, .. }, - Span { variant: SpanVariant::Strong, .. }, - Text { variant: TextVariant::Plain, .. }, - Text { variant: TextVariant::Code, .. }, - Text { variant: TextVariant::Math, .. }, - Text { variant: TextVariant::Html, .. }, + Formatting(Formatting{ variant: FormattingVariant::Delete, .. }), + Formatting(Formatting{ variant: FormattingVariant::Emphasis, .. }), + Formatting(Formatting{ variant: FormattingVariant::Strong, .. }), + Text(Text { variant: TextVariant::Plain, .. }), + Text(Text { variant: TextVariant::Code, .. }), + Text(Text { variant: TextVariant::Math, .. }), + Text(Text { variant: TextVariant::Html, .. }), Link { .. }, Image { .. }, Footnote(_), diff --git a/src/select/selector.rs b/src/select/selector.rs index 8cb500c..4ebe489 100644 --- a/src/select/selector.rs +++ b/src/select/selector.rs @@ -3,9 +3,8 @@ use crate::select::base::Selector; use crate::select::interface::{ParseError, ParseErrorReason, ParseResult, SelectResult}; use crate::select::list_item::{ListItemSelector, ListItemType}; use crate::select::section::SectionSelector; -use crate::tree::Inline; +use crate::tree::{Formatting, Image, Inline, Link, Text}; use crate::tree_ref::{ListItemRef, MdElemRef, NonSelectable}; -use crate::wrap_mdq_refs; #[derive(Debug, PartialEq)] pub enum MdqRefSelector { @@ -91,17 +90,8 @@ impl MdqRefSelector { match node { MdElemRef::Section(s) => MdElemRef::wrap_vec(&s.body), MdElemRef::ListItem(ListItemRef(_, item)) => MdElemRef::wrap_vec(&item.item), - MdElemRef::Inline(inline) => match inline { - Inline::Span { children, .. } => children.iter().map(|child| MdElemRef::Inline(child)).collect(), - Inline::Footnote(footnote) => MdElemRef::wrap_vec(&footnote.text), - Inline::Link { .. } => { - // TODO need to return an MdqNodeRef::Link - Vec::new() - } - Inline::Text { .. } | Inline::Image { .. } => Vec::new(), - }, MdElemRef::NonSelectable(elem) => match elem { - NonSelectable::Paragraph(p) => wrap_mdq_refs!(Inline: &p.body), + NonSelectable::Paragraph(p) => p.body.iter().map(|child| child.into()).collect(), NonSelectable::BlockQuote(b) => MdElemRef::wrap_vec(&b.body), NonSelectable::List(list) => { let mut idx = list.starting_index; @@ -120,13 +110,24 @@ impl MdqRefSelector { for row in &table.rows { for col in row { for cell in col { - result.push(MdElemRef::Inline(cell)); + result.push(MdElemRef::NonSelectable(NonSelectable::Inline(cell))); } } } result } NonSelectable::ThematicBreak | NonSelectable::CodeBlock(_) => Vec::new(), + NonSelectable::Inline(inline) => match inline { + Inline::Formatting(Formatting { children, .. }) => { + children.iter().map(|child| child.into()).collect() + } + Inline::Footnote(footnote) => MdElemRef::wrap_vec(&footnote.text), + Inline::Link(Link { .. }) => { + // TODO need to return an MdqNodeRef::Link + Vec::new() + } + Inline::Text(Text { .. }) | Inline::Image(Image { .. }) => Vec::new(), + }, }, } } diff --git a/src/tree.rs b/src/tree.rs index 5ff5924..1bc296d 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -122,23 +122,35 @@ pub enum CodeVariant { #[derive(Debug, PartialEq, Eq, Hash)] pub enum Inline { - Span { - variant: SpanVariant, - children: Vec, - }, - Text { - variant: TextVariant, - value: String, - }, - Link { - text: Vec, - link_definition: LinkDefinition, - }, - Image { - alt: String, - link: LinkDefinition, - }, Footnote(Footnote), + Formatting(Formatting), + Image(Image), + Link(Link), + Text(Text), +} + +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct Formatting { + pub variant: FormattingVariant, + pub children: Vec, +} + +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct Text { + pub variant: TextVariant, + pub value: String, +} + +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct Link { + pub text: Vec, + pub link_definition: LinkDefinition, +} + +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct Image { + pub alt: String, + pub link: LinkDefinition, } #[derive(Debug)] @@ -180,7 +192,7 @@ pub struct ListItem { } #[derive(Debug, PartialEq, Eq, Hash)] -pub enum SpanVariant { +pub enum FormattingVariant { Delete, Emphasis, Strong, @@ -285,50 +297,50 @@ impl MdElem { items: li_nodes, }) } - mdast::Node::Break(_) => MdElem::Inline(Inline::Text { + mdast::Node::Break(_) => MdElem::Inline(Inline::Text(Text { variant: TextVariant::Plain, value: "\n".to_string(), - }), - mdast::Node::InlineCode(node) => MdElem::Inline(Inline::Text { + })), + mdast::Node::InlineCode(node) => MdElem::Inline(Inline::Text(Text { variant: TextVariant::Code, value: node.value, - }), - mdast::Node::InlineMath(node) => MdElem::Inline(Inline::Text { + })), + mdast::Node::InlineMath(node) => MdElem::Inline(Inline::Text(Text { variant: TextVariant::Math, value: node.value, - }), - mdast::Node::Delete(node) => MdElem::Inline(Inline::Span { - variant: SpanVariant::Delete, + })), + mdast::Node::Delete(node) => MdElem::Inline(Inline::Formatting(Formatting { + variant: FormattingVariant::Delete, children: MdElem::inlines(node.children, lookups)?, - }), - mdast::Node::Emphasis(node) => MdElem::Inline(Inline::Span { - variant: SpanVariant::Emphasis, + })), + mdast::Node::Emphasis(node) => MdElem::Inline(Inline::Formatting(Formatting { + variant: FormattingVariant::Emphasis, children: MdElem::inlines(node.children, lookups)?, - }), - mdast::Node::Image(node) => MdElem::Inline(Inline::Image { + })), + mdast::Node::Image(node) => MdElem::Inline(Inline::Image(Image { alt: node.alt, link: LinkDefinition { url: node.url, title: node.title, reference: LinkReference::Inline, }, - }), - mdast::Node::ImageReference(node) => MdElem::Inline(Inline::Image { + })), + mdast::Node::ImageReference(node) => MdElem::Inline(Inline::Image(Image { alt: node.alt, link: lookups.resolve_link(node.identifier, node.label, node.reference_kind)?, - }), - mdast::Node::Link(node) => MdElem::Inline(Inline::Link { + })), + mdast::Node::Link(node) => MdElem::Inline(Inline::Link(Link { text: MdElem::inlines(node.children, lookups)?, link_definition: LinkDefinition { url: node.url, title: node.title, reference: LinkReference::Inline, }, - }), - mdast::Node::LinkReference(node) => MdElem::Inline(Inline::Link { + })), + mdast::Node::LinkReference(node) => MdElem::Inline(Inline::Link(Link { text: MdElem::inlines(node.children, lookups)?, link_definition: lookups.resolve_link(node.identifier, node.label, node.reference_kind)?, - }), + })), mdast::Node::FootnoteReference(node) => { let definition = lookups.resolve_footnote(&node.identifier, &node.label)?; MdElem::Inline(Inline::Footnote(Footnote { @@ -336,14 +348,14 @@ impl MdElem { text: MdElem::all(definition.children.clone(), lookups)?, })) } - mdast::Node::Strong(node) => MdElem::Inline(Inline::Span { - variant: SpanVariant::Strong, + mdast::Node::Strong(node) => MdElem::Inline(Inline::Formatting(Formatting { + variant: FormattingVariant::Strong, children: MdElem::inlines(node.children, lookups)?, - }), - mdast::Node::Text(node) => MdElem::Inline(Inline::Text { + })), + mdast::Node::Text(node) => MdElem::Inline(Inline::Text(Text { variant: TextVariant::Plain, value: node.value, - }), + })), mdast::Node::Code(node) => { let mdast::Code { value, lang, meta, .. } = node; m_node!(MdElem::Block::LeafBlock::CodeBlock { @@ -410,10 +422,10 @@ impl MdElem { variant: CodeVariant::Yaml, value: node.value, }), - mdast::Node::Html(node) => MdElem::Inline(Inline::Text { + mdast::Node::Html(node) => MdElem::Inline(Inline::Text(Text { variant: TextVariant::Html, value: node.value, - }), + })), mdx_nodes! {} => { // If you implement this, make sure to remove the mdx_nodes macro. That means you'll also need to @@ -536,14 +548,14 @@ impl MdElem { // If both this and the previous were plain text, then just combine the texts. This can happen if there was // a Node::Break between them. if let ( - Some(Inline::Text { + Some(Inline::Text(Text { variant: TextVariant::Plain, value: prev_text, - }), - Inline::Text { + })), + Inline::Text(Text { variant: TextVariant::Plain, value: new_text, - }, + }), ) = (result.last_mut(), &inline) { prev_text.push_str(new_text) @@ -891,17 +903,17 @@ mod tests { check!(&root.children[0], Node::Paragraph(p), lookups => m_node!(MdElem::Block::LeafBlock::Paragraph{body}) = { assert_eq!(p.children.len(), 3); check!(&p.children[0], Node::Text(_), lookups => MdElem::Inline(text) = { - assert_eq!(text, Inline::Text {variant: TextVariant::Plain, value: "hello ".to_string()}); + assert_eq!(text, Inline::Text(Text{variant: TextVariant::Plain, value: "hello ".to_string()})); }); check!(&p.children[1], Node::Break(_), lookups => MdElem::Inline(text) = { - assert_eq!(text, Inline::Text {variant: TextVariant::Plain, value: "\n".to_string()}); + assert_eq!(text, Inline::Text (Text{variant: TextVariant::Plain, value: "\n".to_string()})); }); check!(&p.children[2], Node::Text(_), lookups => MdElem::Inline(text) = { - assert_eq!(text, Inline::Text {variant: TextVariant::Plain, value: "world".to_string()}); + assert_eq!(text, Inline::Text (Text{variant: TextVariant::Plain, value: "world".to_string()})); }); assert_eq!(body, vec![ // note: just a single child, which has a two-line string - Inline::Text {variant: TextVariant::Plain, value: "hello \nworld".to_string()}, + Inline::Text (Text{variant: TextVariant::Plain, value: "hello \nworld".to_string()}), ]) }); } @@ -912,7 +924,7 @@ mod tests { unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::InlineCode(_), lookups => MdElem::Inline(inline) = { - assert_eq!(inline, Inline::Text { variant: TextVariant::Code, value: "foo".to_string() }); + assert_eq!(inline, Inline::Text (Text{ variant: TextVariant::Code, value: "foo".to_string() })); }); } @@ -924,7 +936,7 @@ mod tests { unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::InlineMath(_), lookups => MdElem::Inline(inline) = { - assert_eq!(inline, Inline::Text { variant: TextVariant::Math, value: r#" 0 \ne 1 "#.to_string() }); + assert_eq!(inline, Inline::Text (Text{ variant: TextVariant::Math, value: r#" 0 \ne 1 "#.to_string() })); }); } @@ -934,12 +946,12 @@ mod tests { unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::Delete(_), lookups => MdElem::Inline(inline) = { - assert_eq!(inline, Inline::Span { - variant: SpanVariant::Delete, + assert_eq!(inline, Inline::Formatting(Formatting{ + variant: FormattingVariant::Delete, children: vec![ - Inline::Text { variant: TextVariant::Plain, value: "86 me".to_string()}, + Inline::Text (Text{ variant: TextVariant::Plain, value: "86 me".to_string()}), ] - }); + })); }); } @@ -949,12 +961,12 @@ mod tests { unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::Emphasis(_), lookups => MdElem::Inline(inline) = { - assert_eq!(inline, Inline::Span { - variant: SpanVariant::Emphasis, + assert_eq!(inline, Inline::Formatting(Formatting{ + variant: FormattingVariant::Emphasis, children: vec![ - Inline::Text { variant: TextVariant::Plain, value: "86 me".to_string()}, + Inline::Text (Text{ variant: TextVariant::Plain, value: "86 me".to_string()}), ] - }); + })); }); } @@ -964,12 +976,12 @@ mod tests { unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::Strong(_), lookups => MdElem::Inline(inline) = { - assert_eq!(inline, Inline::Span { - variant: SpanVariant::Strong, + assert_eq!(inline, Inline::Formatting(Formatting{ + variant: FormattingVariant::Strong, children: vec![ - Inline::Text { variant: TextVariant::Plain, value: "strongman".to_string()}, + Inline::Text (Text{ variant: TextVariant::Plain, value: "strongman".to_string()}), ] - }); + })); }); } @@ -979,10 +991,10 @@ mod tests { let (root, lookups) = parse(""); check!(&root.children[0], Node::Html(_), lookups => MdElem::Inline(inline) = { - assert_eq!(inline, Inline::Text { + assert_eq!(inline, Inline::Text (Text{ variant: TextVariant::Html, value: "".to_string(), - }); + })); }); } { @@ -994,13 +1006,13 @@ mod tests { assert_eq!(body.len(), 4); assert_eq!(body, vec![ mdq_inline!("In "), - Inline::Text { + Inline::Text (Text{ variant: TextVariant::Html, - value: "".to_string()}, + value: "".to_string()}), mdq_inline!("a paragraph."), - Inline::Text { + Inline::Text (Text{ variant: TextVariant::Html, - value: "".to_string()}, + value: "".to_string()}), ]) }); } @@ -1014,13 +1026,13 @@ mod tests { assert_eq!(body.len(), 4); assert_eq!(body, vec![ mdq_inline!("In "), - Inline::Text { + Inline::Text (Text{ variant: TextVariant::Html, - value: "".to_string()}, + value: "".to_string()}), mdq_inline!("a paragraph."), - Inline::Text { + Inline::Text (Text{ variant: TextVariant::Html, - value: "".to_string()}, + value: "".to_string()}), ]) }); } @@ -1032,56 +1044,56 @@ mod tests { let (root, lookups) = parse("![]()"); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::Image(_), lookups => MdElem::Inline(img) = { - assert_eq!(img, Inline::Image { + assert_eq!(img, Inline::Image(Image { alt: "".to_string(), link: LinkDefinition{ url: "".to_string(), title: None, reference: LinkReference::Inline, }, - }) + })) }); } { let (root, lookups) = parse("![](https://example.com/foo.png)"); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::Image(_), lookups => MdElem::Inline(img) = { - assert_eq!(img, Inline::Image { + assert_eq!(img, Inline::Image(Image { alt: "".to_string(), link: LinkDefinition{ url: "https://example.com/foo.png".to_string(), title: None, reference: LinkReference::Inline, }, - }) + })) }); } { let (root, lookups) = parse("![alt text]()"); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::Image(_), lookups => MdElem::Inline(img) = { - assert_eq!(img, Inline::Image { + assert_eq!(img, Inline::Image(Image { alt: "alt text".to_string(), link: LinkDefinition{ url: "".to_string(), title: None, reference: LinkReference::Inline, }, - }) + })) }); } { let (root, lookups) = parse(r#"![](https://example.com/foo.png "my tooltip")"#); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::Image(_), lookups => MdElem::Inline(img) = { - assert_eq!(img, Inline::Image { + assert_eq!(img, Inline::Image(Image { alt: "".to_string(), link: LinkDefinition{ url: "https://example.com/foo.png".to_string(), title: Some("my tooltip".to_string()), reference: LinkReference::Inline, }, - }) + })) }); } { @@ -1101,20 +1113,20 @@ mod tests { assert_eq!(root.children.len(), 1); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::Link(_), lookups => MdElem::Inline(link) = { - assert_eq!(link, Inline::Link { + assert_eq!(link, Inline::Link(Link { text: vec![ mdq_inline!("hello "), - Inline::Span { - variant: SpanVariant::Emphasis, + Inline::Formatting(Formatting{ + variant: FormattingVariant::Emphasis, children: vec![mdq_inline!("world")], - } + }) ], link_definition: LinkDefinition{ url: "https://example.com".to_string(), title: None, reference: LinkReference::Inline, }, - }) + })) }); } { @@ -1123,20 +1135,20 @@ mod tests { assert_eq!(root.children.len(), 1); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::Link(_), lookups => MdElem::Inline(link) = { - assert_eq!(link, Inline::Link { + assert_eq!(link, Inline::Link(Link { text: vec![ mdq_inline!("hello "), - Inline::Span { - variant: SpanVariant::Emphasis, + Inline::Formatting(Formatting { + variant: FormattingVariant::Emphasis, children: vec![mdq_inline!("world")], - } + }) ], link_definition: LinkDefinition{ url: "https://example.com".to_string(), title: Some("the title".to_string()), reference: LinkReference::Inline, }, - }) + })) }); } { @@ -1152,20 +1164,20 @@ mod tests { assert_eq!(root.children.len(), 2); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::LinkReference(_), lookups => MdElem::Inline(link) = { - assert_eq!(link, Inline::Link { + assert_eq!(link, Inline::Link(Link { text: vec![ mdq_inline!("hello "), - Inline::Span { - variant: SpanVariant::Emphasis, + Inline::Formatting(Formatting{ + variant: FormattingVariant::Emphasis, children: vec![mdq_inline!("world")], - }, + }), ], link_definition: LinkDefinition{ url: "https://example.com".to_string(), title: None, reference: LinkReference::Full("1".to_string()), }, - }) + })) }); check!(no_node: &root.children[1], Node::Definition(_), lookups); } @@ -1182,20 +1194,20 @@ mod tests { assert_eq!(root.children.len(), 2); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::LinkReference(_), lookups => MdElem::Inline(link) = { - assert_eq!(link, Inline::Link { + assert_eq!(link, Inline::Link(Link { text: vec![ mdq_inline!("hello "), - Inline::Span { - variant: SpanVariant::Emphasis, + Inline::Formatting(Formatting{ + variant: FormattingVariant::Emphasis, children: vec![mdq_inline!("world")], - }, + }), ], link_definition: LinkDefinition{ url: "https://example.com".to_string(), title: Some("my title".to_string()), reference: LinkReference::Collapsed, }, - }) + })) }); check!(no_node: &root.children[1], Node::Definition(_), lookups); } @@ -1212,20 +1224,20 @@ mod tests { assert_eq!(root.children.len(), 2); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::LinkReference(_), lookups => MdElem::Inline(link) = { - assert_eq!(link, Inline::Link { + assert_eq!(link, Inline::Link(Link { text: vec![ mdq_inline!("hello "), - Inline::Span { - variant: SpanVariant::Emphasis, + Inline::Formatting(Formatting{ + variant: FormattingVariant::Emphasis, children: vec![mdq_inline!("world")], - }, + }), ], link_definition: LinkDefinition{ url: "https://example.com".to_string(), title: None, reference: LinkReference::Shortcut, }, - }) + })) }); check!(no_node: &root.children[1], Node::Definition(_), lookups); } @@ -1237,7 +1249,7 @@ mod tests { let (root, lookups) = parse(""); unwrap!(&root.children[0], Node::Paragraph(p)); assert_eq!(p.children.len(), 1); - check!(&p.children[0], Node::Link(_), lookups => MdElem::Inline(Inline::Link{text, link_definition}) = { + check!(&p.children[0], Node::Link(_), lookups => m_node!(MdElem::Inline::Link{text, link_definition}) = { assert_eq!(text, vec![mdq_inline!("https://example.com")]); assert_eq!(link_definition, LinkDefinition{ url: "https://example.com".to_string(), @@ -1249,7 +1261,7 @@ mod tests { let (root, lookups) = parse(""); unwrap!(&root.children[0], Node::Paragraph(p)); assert_eq!(p.children.len(), 1); - check!(&p.children[0], Node::Link(_), lookups => MdElem::Inline(Inline::Link{text, link_definition}) = { + check!(&p.children[0], Node::Link(_), lookups => m_node!(MdElem::Inline::Link{text, link_definition}) = { assert_eq!(text, vec![mdq_inline!("mailto:md@example.com")]); assert_eq!(link_definition, LinkDefinition{ url: "mailto:md@example.com".to_string(), @@ -1262,7 +1274,7 @@ mod tests { let (root, lookups) = parse_with(&ParseOptions::default(), "https://example.com"); unwrap!(&root.children[0], Node::Paragraph(p)); assert_eq!(p.children.len(), 1); - check!(&p.children[0], Node::Text(_), lookups => MdElem::Inline(Inline::Text{variant: TextVariant::Plain, value}) = { + check!(&p.children[0], Node::Text(_), lookups => MdElem::Inline(Inline::Text(Text{variant: TextVariant::Plain, value})) = { assert_eq!(value, "https://example.com".to_string()); }); } @@ -1271,7 +1283,7 @@ mod tests { let (root, lookups) = parse_with(&ParseOptions::gfm(), "https://example.com"); unwrap!(&root.children[0], Node::Paragraph(p)); assert_eq!(p.children.len(), 1); - check!(&p.children[0], Node::Link(_), lookups => MdElem::Inline(Inline::Link{text, link_definition}) = { + check!(&p.children[0], Node::Link(_), lookups => m_node!(MdElem::Inline::Link{text, link_definition}) = { assert_eq!(text, vec![mdq_inline!("https://example.com")]); assert_eq!(link_definition, LinkDefinition{ url: "https://example.com".to_string(), @@ -1291,14 +1303,14 @@ mod tests { [1]: https://example.com/image.png"#}); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::ImageReference(_), lookups => MdElem::Inline(img) = { - assert_eq!(img, Inline::Image { + assert_eq!(img, Inline::Image(Image { alt: "".to_string(), link: LinkDefinition { url: "https://example.com/image.png".to_string(), title: None, reference: LinkReference::Full("1".to_string()), } - }) + })) }); check!(no_node: &root.children[1], Node::Definition(_), lookups); } @@ -1309,14 +1321,14 @@ mod tests { [1]: https://example.com/image.png "my title""#}); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::ImageReference(_), lookups => MdElem::Inline(img) = { - assert_eq!(img, Inline::Image { + assert_eq!(img, Inline::Image(Image { alt: "".to_string(), link: LinkDefinition { url: "https://example.com/image.png".to_string(), title: Some("my title".to_string()), reference: LinkReference::Full("1".to_string()), } - }) + })) }); check!(no_node: &root.children[1], Node::Definition(_), lookups); } @@ -1330,14 +1342,14 @@ mod tests { ); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::ImageReference(_), lookups => MdElem::Inline(img) = { - assert_eq!(img, Inline::Image { + assert_eq!(img, Inline::Image(Image { alt: "my alt".to_string(), link: LinkDefinition { url: "https://example.com/image.png".to_string(), title: Some("my title".to_string()), reference: LinkReference::Collapsed, } - }) + })) }); check!(no_node: &root.children[1], Node::Definition(_), lookups); } @@ -1351,14 +1363,14 @@ mod tests { ); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::ImageReference(_), lookups => MdElem::Inline(img) = { - assert_eq!(img, Inline::Image { + assert_eq!(img, Inline::Image(Image { alt: "my alt".to_string(), link: LinkDefinition { url: "https://example.com/image.png".to_string(), title: None, reference: LinkReference::Shortcut, } - }) + })) }); check!(no_node: &root.children[1], Node::Definition(_), lookups); } @@ -1374,14 +1386,14 @@ mod tests { [1]: https://example.com/image.png"#}); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::LinkReference(_), lookups => MdElem::Inline(link) = { - assert_eq!(link, Inline::Link { + assert_eq!(link, Inline::Link(Link { text: vec![], link_definition: LinkDefinition { url: "https://example.com/image.png".to_string(), title: None, reference: LinkReference::Full("1".to_string()), } - }) + })) }); check!(no_node: &root.children[1], Node::Definition(_), lookups); } @@ -1392,14 +1404,14 @@ mod tests { [1]: https://example.com/image.png "my title""#}); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::LinkReference(_), lookups => MdElem::Inline(link) = { - assert_eq!(link, Inline::Link { + assert_eq!(link, Inline::Link(Link { text: vec![], link_definition: LinkDefinition { url: "https://example.com/image.png".to_string(), title: Some("my title".to_string()), reference: LinkReference::Full("1".to_string()), } - }) + })) }); check!(no_node: &root.children[1], Node::Definition(_), lookups); } @@ -1413,15 +1425,15 @@ mod tests { ); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::LinkReference(_), lookups => MdElem::Inline(link) = { - assert_eq!(link, Inline::Link { + assert_eq!(link, Inline::Link(Link { text: vec![ - Inline::Span{ - variant: SpanVariant::Emphasis, + Inline::Formatting(Formatting{ + variant: FormattingVariant::Emphasis, children: vec![ - Inline::Text {variant: TextVariant::Plain,value: "my".to_string()} + Inline::Text (Text{variant: TextVariant::Plain,value: "my".to_string()}) ], - }, - Inline::Text {variant: TextVariant::Plain,value: " text".to_string()} + }), + Inline::Text (Text{variant: TextVariant::Plain,value: " text".to_string()}) ], link_definition: LinkDefinition { @@ -1429,7 +1441,7 @@ mod tests { title: Some("my title".to_string()), reference: LinkReference::Collapsed, } - }) + })) }); check!(no_node: &root.children[1], Node::Definition(_), lookups); } @@ -1443,16 +1455,16 @@ mod tests { ); unwrap!(&root.children[0], Node::Paragraph(p)); check!(&p.children[0], Node::LinkReference(_), lookups => MdElem::Inline(link) = { - assert_eq!(link, Inline::Link { + assert_eq!(link, Inline::Link(Link { text: vec![ - Inline::Text {variant: TextVariant::Plain,value: "my text".to_string()}, + Inline::Text (Text{variant: TextVariant::Plain,value: "my text".to_string()}), ], link_definition: LinkDefinition { url: "https://example.com/image.png".to_string(), title: None, reference: LinkReference::Shortcut, } - }) + })) }); check!(no_node: &root.children[1], Node::Definition(_), lookups); } @@ -1599,13 +1611,13 @@ mod tests { let (header_depth, header_title) = check!(&root.children[0], Node::Heading(_), lookups => m_node!(MdElem::Block::Container::Section{depth, title, body}) = { assert_eq!(depth, 2); assert_eq!(title, vec![ - Inline::Text { variant: TextVariant::Plain, value: "Header with ".to_string()}, - Inline::Span { - variant: SpanVariant::Emphasis, + Inline::Text (Text{ variant: TextVariant::Plain, value: "Header with ".to_string()}), + Inline::Formatting (Formatting{ + variant: FormattingVariant::Emphasis, children: vec![ - Inline::Text { variant: TextVariant::Plain, value: "emphasis".to_string()}, + Inline::Text (Text{ variant: TextVariant::Plain, value: "emphasis".to_string()}), ] - } + }) ]); assert_eq!(body, vec![ // This code path doesn't do recursion; that's done in all_from_iter, which happens at the root diff --git a/src/tree_ref.rs b/src/tree_ref.rs index 5bb883b..0d5484d 100644 --- a/src/tree_ref.rs +++ b/src/tree_ref.rs @@ -8,7 +8,6 @@ use crate::tree::{ pub enum MdElemRef<'a> { Section(&'a Section), ListItem(ListItemRef<'a>), - Inline(&'a Inline), NonSelectable(NonSelectable<'a>), } @@ -21,11 +20,21 @@ pub enum NonSelectable<'a> { BlockQuote(&'a BlockQuote), List(&'a List), Table(&'a Table), + Inline(&'a Inline), } #[derive(Debug, Clone, Copy)] pub struct ListItemRef<'a>(pub Option, pub &'a ListItem); +/// We implement this one specifically because it's non-trivial: some Inlines are selectable, and some aren't. +impl<'a> From<&'a Inline> for MdElemRef<'a> { + fn from(value: &'a Inline) -> Self { + // TODO actually make this be non-trivial, as the doc says it will be. :-) Specifically, make Link and Image + // selectable. + MdElemRef::NonSelectable(NonSelectable::Inline(value)) + } +} + impl<'a> From<&'a MdElem> for MdElemRef<'a> { fn from(value: &'a MdElem) -> Self { match value { @@ -42,7 +51,7 @@ impl<'a> From<&'a MdElem> for MdElemRef<'a> { Container::Section(section) => Self::Section(section), }, }, - MdElem::Inline(v) => Self::Inline(v), + MdElem::Inline(v) => v.into(), } } } diff --git a/src/tree_test_utils.rs b/src/tree_test_utils.rs index 5a12121..4e7e0dd 100644 --- a/src/tree_test_utils.rs +++ b/src/tree_test_utils.rs @@ -1,6 +1,5 @@ #[cfg(test)] mod test_utils { - #[macro_export] macro_rules! md_elem { ( $($node_names:ident)::* {$($attr:ident: $val:expr),*}) => { @@ -24,16 +23,16 @@ mod test_utils { #[macro_export] macro_rules! mdq_inline { (span $which:ident [$($contents:expr),*$(,)?]) => { - crate::tree::Inline::Span { - variant: crate::tree::SpanVariant::$which, + crate::tree::Inline::Formatting(Formatting { + variant: crate::tree::FormattingVariant::$which, children: vec![$($contents),*], - } + }) }; ($text:literal) => { - crate::tree::Inline::Text { + crate::tree::Inline::Text(Text { variant: crate::tree::TextVariant::Plain, value: $text.to_string(), - } + }) }; } }