diff --git a/Cargo.lock b/Cargo.lock index 980e42e..166524f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1117,7 +1117,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "snekdown" -version = "0.22.10" +version = "0.23.0" dependencies = [ "asciimath-rs 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index e90c1a8..9bf6e60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snekdown" -version = "0.22.10" +version = "0.23.0" authors = ["trivernis "] edition = "2018" license-file = "LICENSE" diff --git a/src/elements/mod.rs b/src/elements/mod.rs index aa86622..87264ce 100644 --- a/src/elements/mod.rs +++ b/src/elements/mod.rs @@ -184,22 +184,22 @@ pub struct PlainText { #[derive(Clone, Debug)] pub struct BoldText { - pub(crate) value: Box, + pub(crate) value: Vec, } #[derive(Clone, Debug)] pub struct ItalicText { - pub(crate) value: Box, + pub(crate) value: Vec, } #[derive(Clone, Debug)] pub struct UnderlinedText { - pub(crate) value: Box, + pub(crate) value: Vec, } #[derive(Clone, Debug)] pub struct StrikedText { - pub(crate) value: Box, + pub(crate) value: Vec, } #[derive(Clone, Debug)] @@ -209,7 +209,7 @@ pub struct MonospaceText { #[derive(Clone, Debug)] pub struct SuperscriptText { - pub(crate) value: Box, + pub(crate) value: Vec, } #[derive(Clone, Debug)] diff --git a/src/format/html.rs b/src/format/html.rs index 4bde333..88353f3 100644 --- a/src/format/html.rs +++ b/src/format/html.rs @@ -397,31 +397,56 @@ impl ToHtml for Image { impl ToHtml for BoldText { fn to_html(&self) -> String { - format!("{}", self.value.to_html()) + format!( + "{}", + self.value + .iter() + .fold("".to_string(), |a, b| format!("{}{}", a, b.to_html())) + ) } } impl ToHtml for UnderlinedText { fn to_html(&self) -> String { - format!("{}", self.value.to_html()) + format!( + "{}", + self.value + .iter() + .fold("".to_string(), |a, b| format!("{}{}", a, b.to_html())) + ) } } impl ToHtml for ItalicText { fn to_html(&self) -> String { - format!("{}", self.value.to_html()) + format!( + "{}", + self.value + .iter() + .fold("".to_string(), |a, b| format!("{}{}", a, b.to_html())) + ) } } impl ToHtml for StrikedText { fn to_html(&self) -> String { - format!("{}", self.value.to_html()) + format!( + "{}", + self.value + .iter() + .fold("".to_string(), |a, b| format!("{}{}", a, b.to_html())) + ) } } impl ToHtml for SuperscriptText { fn to_html(&self) -> String { - format!("{}", self.value.to_html()) + format!( + "{}", + self.value + .iter() + .fold("".to_string(), |a, b| format!("{}{}", a, b.to_html())) + ) } } diff --git a/src/parser/inline.rs b/src/parser/inline.rs index 34d68f0..6307d38 100644 --- a/src/parser/inline.rs +++ b/src/parser/inline.rs @@ -10,7 +10,7 @@ use std::collections::HashMap; use std::sync::{Arc, RwLock}; pub(crate) trait ParseInline { - fn parse_surrounded(&mut self, surrounding: &char) -> ParseResult; + fn parse_surrounded(&mut self, surrounding: &char) -> ParseResult>; fn parse_inline(&mut self) -> ParseResult; fn parse_image(&mut self) -> ParseResult; fn parse_url(&mut self, short_syntax: bool) -> ParseResult; @@ -36,12 +36,18 @@ pub(crate) trait ParseInline { impl ParseInline for Parser { /// parses Inline surrounded by characters - fn parse_surrounded(&mut self, surrounding: &char) -> ParseResult { + fn parse_surrounded(&mut self, surrounding: &char) -> ParseResult> { let start_index = self.ctm.get_index(); self.ctm.assert_char(surrounding, Some(start_index))?; self.ctm.seek_one()?; - let inline = self.parse_inline()?; - self.ctm.assert_char(surrounding, Some(start_index))?; + let mut inline = vec![self.parse_inline()?]; + while !self.ctm.check_char(surrounding) { + if let Ok(result) = self.parse_inline() { + inline.push(result) + } else { + return Err(self.ctm.rewind_with_error(start_index)); + } + } if !self.ctm.check_eof() { self.ctm.seek_one()?; } @@ -181,24 +187,28 @@ impl ParseInline for Parser { let start_index = self.ctm.get_index(); self.ctm.assert_sequence(&BOLD, Some(start_index))?; self.ctm.seek_one()?; - let inline = self.parse_inline()?; - self.ctm.assert_sequence(&BOLD, Some(start_index))?; + let mut inline = vec![self.parse_inline()?]; + while !self.ctm.check_sequence(&BOLD) { + if let Ok(result) = self.parse_inline() { + inline.push(result); + } else { + return Err(self.ctm.rewind_with_error(start_index)); + } + } self.ctm.seek_one()?; - Ok(BoldText { - value: Box::new(inline), - }) + Ok(BoldText { value: inline }) } fn parse_italic(&mut self) -> ParseResult { Ok(ItalicText { - value: Box::new(self.parse_surrounded(&ITALIC)?), + value: self.parse_surrounded(&ITALIC)?, }) } fn parse_striked(&mut self) -> ParseResult { Ok(StrikedText { - value: Box::new(self.parse_surrounded(&STRIKED)?), + value: self.parse_surrounded(&STRIKED)?, }) } @@ -232,13 +242,13 @@ impl ParseInline for Parser { fn parse_underlined(&mut self) -> ParseResult { Ok(UnderlinedText { - value: Box::new(self.parse_surrounded(&UNDERLINED)?), + value: self.parse_surrounded(&UNDERLINED)?, }) } fn parse_superscript(&mut self) -> ParseResult { Ok(SuperscriptText { - value: Box::new(self.parse_surrounded(&SUPER)?), + value: self.parse_surrounded(&SUPER)?, }) } diff --git a/src/references/templates.rs b/src/references/templates.rs index c0e84ba..4672344 100644 --- a/src/references/templates.rs +++ b/src/references/templates.rs @@ -65,11 +65,36 @@ impl GetTemplateVariables for Inline { match self { Inline::TemplateVar(temp) => vec![Arc::clone(temp)], Inline::Colored(col) => col.value.get_template_variables(), - Inline::Superscript(sup) => sup.value.get_template_variables(), - Inline::Striked(striked) => striked.value.get_template_variables(), - Inline::Underlined(under) => under.value.get_template_variables(), - Inline::Italic(it) => it.value.get_template_variables(), - Inline::Bold(bo) => bo.value.get_template_variables(), + Inline::Superscript(sup) => sup + .value + .iter() + .map(|e| e.get_template_variables()) + .flatten() + .collect(), + Inline::Striked(striked) => striked + .value + .iter() + .map(|e| e.get_template_variables()) + .flatten() + .collect(), + Inline::Underlined(under) => under + .value + .iter() + .map(|e| e.get_template_variables()) + .flatten() + .collect(), + Inline::Italic(it) => it + .value + .iter() + .map(|e| e.get_template_variables()) + .flatten() + .collect(), + Inline::Bold(bo) => bo + .value + .iter() + .map(|e| e.get_template_variables()) + .flatten() + .collect(), _ => Vec::new(), } } @@ -155,30 +180,71 @@ impl FreezeVariables for Inline { col.value = Box::new(Inline::TemplateVar(temp)) } } + Inline::Superscript(sup) => { - if let Some(temp) = sup.value.freeze_variables() { - sup.value = Box::new(Inline::TemplateVar(temp)) - } + sup.value = sup + .value + .iter_mut() + .map(|e| { + if let Some(temp) = e.freeze_variables() { + Inline::TemplateVar(temp) + } else { + e.clone() + } + }) + .collect(); } Inline::Striked(striked) => { - if let Some(temp) = striked.value.freeze_variables() { - striked.value = Box::new(Inline::TemplateVar(temp)) - } + striked.value = striked + .value + .iter_mut() + .map(|e| { + if let Some(temp) = e.freeze_variables() { + Inline::TemplateVar(temp) + } else { + e.clone() + } + }) + .collect(); } Inline::Underlined(under) => { - if let Some(temp) = under.value.freeze_variables() { - under.value = Box::new(Inline::TemplateVar(temp)) - } + under.value = under + .value + .iter_mut() + .map(|e| { + if let Some(temp) = e.freeze_variables() { + Inline::TemplateVar(temp) + } else { + e.clone() + } + }) + .collect(); } Inline::Italic(it) => { - if let Some(temp) = it.value.freeze_variables() { - it.value = Box::new(Inline::TemplateVar(temp)) - } + it.value = it + .value + .iter_mut() + .map(|e| { + if let Some(temp) = e.freeze_variables() { + Inline::TemplateVar(temp) + } else { + e.clone() + } + }) + .collect(); } Inline::Bold(bo) => { - if let Some(temp) = bo.value.freeze_variables() { - bo.value = Box::new(Inline::TemplateVar(temp)) - } + bo.value = bo + .value + .iter_mut() + .map(|e| { + if let Some(temp) = e.freeze_variables() { + Inline::TemplateVar(temp) + } else { + e.clone() + } + }) + .collect(); } _ => {} }