diff --git a/Cargo.lock b/Cargo.lock index 7e7de78..2445e43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -358,7 +358,7 @@ dependencies = [ [[package]] name = "snekdown" -version = "0.5.4" +version = "0.5.5" dependencies = [ "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 7e9632d..74ead05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snekdown" -version = "0.5.4" +version = "0.5.5" authors = ["trivernis "] edition = "2018" license-file = "LICENSE" diff --git a/perf.data b/perf.data new file mode 100644 index 0000000..c924911 Binary files /dev/null and b/perf.data differ diff --git a/src/format/html.rs b/src/format/html.rs index 93b65d5..9faff09 100644 --- a/src/format/html.rs +++ b/src/format/html.rs @@ -25,33 +25,33 @@ impl ToHtml for Element { match self { Element::Block(block) => block.to_html(), Element::Inline(inline) => inline.to_html(), - Element::SubText(sub) => sub.to_html(), + Element::Line(line) => line.to_html(), } } } -impl ToHtml for Inline { +impl ToHtml for Line { fn to_html(&self) -> String { match self { - Inline::Text(text) => text.to_html(), - Inline::Ruler(ruler) => ruler.to_html(), - Inline::Anchor(anchor) => anchor.to_html(), + Line::Text(text) => text.to_html(), + Line::Ruler(ruler) => ruler.to_html(), + Line::Anchor(anchor) => anchor.to_html(), } } } -impl ToHtml for SubText { +impl ToHtml for Inline { fn to_html(&self) -> String { match self { - SubText::Url(url) => url.to_html(), - SubText::Monospace(mono) => mono.to_html(), - SubText::Striked(striked) => striked.to_html(), - SubText::Plain(plain) => plain.to_html(), - SubText::Italic(italic) => italic.to_html(), - SubText::Underlined(under) => under.to_html(), - SubText::Bold(bold) => bold.to_html(), - SubText::Image(img) => img.to_html(), - SubText::Placeholder(placeholder) => placeholder.lock().unwrap().to_html(), + Inline::Url(url) => url.to_html(), + Inline::Monospace(mono) => mono.to_html(), + Inline::Striked(striked) => striked.to_html(), + Inline::Plain(plain) => plain.to_html(), + Inline::Italic(italic) => italic.to_html(), + Inline::Underlined(under) => under.to_html(), + Inline::Bold(bold) => bold.to_html(), + Inline::Image(img) => img.to_html(), + Inline::Placeholder(placeholder) => placeholder.lock().unwrap().to_html(), } } } @@ -277,7 +277,7 @@ impl ToHtml for Ruler { } } -impl ToHtml for Text { +impl ToHtml for TextLine { fn to_html(&self) -> String { self.subtext .iter() diff --git a/src/parsing/charstate.rs b/src/parsing/charstate.rs index adcd49e..82e1212 100644 --- a/src/parsing/charstate.rs +++ b/src/parsing/charstate.rs @@ -281,6 +281,7 @@ impl CharStateMachine for Parser { } } + /// seeks until it encounters a linebreak character fn seek_until_linebreak(&mut self) { if self.check_special(&LB) { self.skip_char(); diff --git a/src/parsing/elements.rs b/src/parsing/elements.rs index 0581815..dd729ef 100644 --- a/src/parsing/elements.rs +++ b/src/parsing/elements.rs @@ -36,8 +36,8 @@ pub enum MetadataValue { #[derive(Clone, Debug)] pub enum Element { Block(Box), + Line(Box), Inline(Box), - SubText(Box), } #[derive(Clone, Debug)] @@ -53,8 +53,8 @@ pub enum Block { } #[derive(Clone, Debug)] -pub enum Inline { - Text(Text), +pub enum Line { + Text(TextLine), Ruler(Ruler), Anchor(Anchor), } @@ -77,13 +77,13 @@ pub struct Section { #[derive(Clone, Debug)] pub struct Header { pub(crate) size: u8, - pub(crate) line: Inline, + pub(crate) line: Line, pub(crate) anchor: String, } #[derive(Clone, Debug)] pub struct Paragraph { - pub(crate) elements: Vec, + pub(crate) elements: Vec, } #[derive(Clone, Debug)] @@ -94,7 +94,7 @@ pub struct List { #[derive(Clone, Debug)] pub struct ListItem { - pub(crate) text: Inline, + pub(crate) text: Line, pub(crate) level: u16, pub(crate) ordered: bool, pub(crate) children: Vec, @@ -113,7 +113,7 @@ pub struct Row { #[derive(Clone, Debug)] pub struct Cell { - pub(crate) text: Inline, + pub(crate) text: Line, } #[derive(Clone, Debug)] @@ -125,7 +125,7 @@ pub struct CodeBlock { #[derive(Clone, Debug)] pub struct Quote { pub(crate) metadata: Option, - pub(crate) text: Vec, + pub(crate) text: Vec, } #[derive(Clone, Debug)] @@ -148,12 +148,12 @@ pub struct InlineMetadata { pub struct Ruler {} #[derive(Clone, Debug)] -pub struct Text { - pub subtext: Vec, +pub struct TextLine { + pub subtext: Vec, } #[derive(Clone, Debug)] -pub enum SubText { +pub enum Inline { Plain(PlainText), Bold(BoldText), Italic(ItalicText), @@ -172,22 +172,22 @@ pub struct PlainText { #[derive(Clone, Debug)] pub struct BoldText { - pub(crate) value: Box, + pub(crate) value: Box, } #[derive(Clone, Debug)] pub struct ItalicText { - pub(crate) value: Box, + pub(crate) value: Box, } #[derive(Clone, Debug)] pub struct UnderlinedText { - pub(crate) value: Box, + pub(crate) value: Box, } #[derive(Clone, Debug)] pub struct StrikedText { - pub(crate) value: Box, + pub(crate) value: Box, } #[derive(Clone, Debug)] @@ -215,7 +215,7 @@ pub struct Placeholder { #[derive(Clone, Debug)] pub struct Anchor { - pub(crate) description: Box, + pub(crate) description: Box, pub(crate) reference: String, } @@ -266,7 +266,7 @@ impl Document { self.elements.iter().for_each(|e| match e { Block::Section(sec) => { if !sec.get_hide_in_toc() { - let mut item = ListItem::new(Inline::Anchor(sec.header.get_anchor()), 1, true); + let mut item = ListItem::new(Line::Anchor(sec.header.get_anchor()), 1, true); item.children.append(&mut sec.get_toc_list().items); list.add_item(item); } @@ -322,7 +322,7 @@ impl Section { self.elements.iter().for_each(|e| { if let Block::Section(sec) = e { if !sec.get_hide_in_toc() { - let mut item = ListItem::new(Inline::Anchor(sec.header.get_anchor()), 1, true); + let mut item = ListItem::new(Line::Anchor(sec.header.get_anchor()), 1, true); item.children.append(&mut sec.get_toc_list().items); list.add_item(item); } @@ -342,7 +342,7 @@ impl Section { } impl Header { - pub fn new(content: Inline, anchor: String) -> Self { + pub fn new(content: Line, anchor: String) -> Self { Self { size: 0, anchor, @@ -365,7 +365,7 @@ impl Paragraph { } } - pub fn add_element(&mut self, element: Inline) { + pub fn add_element(&mut self, element: Line) { self.elements.push(element) } } @@ -384,7 +384,7 @@ impl List { } impl ListItem { - pub fn new(text: Inline, level: u16, ordered: bool) -> Self { + pub fn new(text: Line, level: u16, ordered: bool) -> Self { Self { text, level, @@ -398,14 +398,14 @@ impl ListItem { } } -impl Text { +impl TextLine { pub fn new() -> Self { Self { subtext: Vec::new(), } } - pub fn add_subtext(&mut self, subtext: SubText) { + pub fn add_subtext(&mut self, subtext: Inline) { self.subtext.push(subtext) } } @@ -447,7 +447,7 @@ impl Quote { } } - pub fn add_text(&mut self, text: Text) { + pub fn add_text(&mut self, text: TextLine) { self.text.push(text) } } diff --git a/src/parsing/mod.rs b/src/parsing/mod.rs index c4bd97e..e9d6906 100644 --- a/src/parsing/mod.rs +++ b/src/parsing/mod.rs @@ -2,4 +2,5 @@ pub mod charstate; pub mod elements; pub mod parser; pub mod placeholders; +pub mod subtext; pub mod tokens; diff --git a/src/parsing/parser.rs b/src/parsing/parser.rs index 44d4b48..ac5b896 100644 --- a/src/parsing/parser.rs +++ b/src/parsing/parser.rs @@ -2,6 +2,7 @@ use super::elements::*; use super::tokens::*; use crate::parsing::charstate::CharStateMachine; use crate::parsing::placeholders::ProcessPlaceholders; +use crate::parsing::subtext::ParseInline; use crossbeam_utils::sync::WaitGroup; use std::collections::HashMap; use std::error::Error; @@ -100,7 +101,7 @@ pub struct Parser { paths: Arc>>, wg: WaitGroup, is_child: bool, - subtext_break_at: Vec, + pub(crate) inline_break_at: Vec, document: Document, } @@ -147,7 +148,7 @@ impl Parser { paths, wg: WaitGroup::new(), is_child, - subtext_break_at: Vec::new(), + inline_break_at: Vec::new(), document: Document::new(!is_child), } } @@ -352,7 +353,7 @@ impl Parser { /// parses the header of a section fn parse_header(&mut self) -> Result { let start_index = self.index; - let line = self.parse_inline()?; + let line = self.parse_line()?; let mut anchor = String::new(); self.text[start_index..self.index] .iter() @@ -399,7 +400,7 @@ impl Parser { && self.next_char() != None && (self.check_seek_inline_whitespace() || self.check_special(&LB)) { - if let Ok(text) = self.parse_text() { + if let Ok(text) = self.parse_text_line() { if text.subtext.len() > 0 { quote.add_text(text); } @@ -415,7 +416,7 @@ impl Parser { } /// Parses metadata - fn parse_inline_metadata(&mut self) -> Result { + pub(crate) fn parse_inline_metadata(&mut self) -> Result { let start_index = self.index; self.assert_special(&META_OPEN, start_index)?; self.skip_char(); @@ -523,7 +524,7 @@ impl Parser { fn parse_paragraph(&mut self) -> Result { self.seek_whitespace(); let mut paragraph = Paragraph::new(); - while let Ok(token) = self.parse_inline() { + while let Ok(token) = self.parse_line() { paragraph.add_element(token); let start_index = self.index; if self.check_special_sequence_group(&BLOCK_SPECIAL_CHARS) { @@ -623,7 +624,7 @@ impl Parser { return Err(self.revert_with_error(start_index)); } - let item = ListItem::new(self.parse_inline()?, level as u16, ordered); + let item = ListItem::new(self.parse_line()?, level as u16, ordered); Ok(item) } @@ -663,11 +664,11 @@ impl Parser { self.seek_inline_whitespace(); self.assert_special(&PIPE, start_index)?; self.skip_char(); - self.subtext_break_at.push(PIPE); + self.inline_break_at.push(PIPE); self.seek_inline_whitespace(); let mut row = Row::new(); - while let Ok(element) = self.parse_inline() { + while let Ok(element) = self.parse_line() { row.add_cell(Cell { text: element }); if self.check_special(&PIPE) { if self.next_char() == None { @@ -679,7 +680,7 @@ impl Parser { } self.seek_inline_whitespace(); } - self.subtext_break_at.clear(); + self.inline_break_at.clear(); if row.cells.len() > 0 { Ok(row) @@ -689,21 +690,21 @@ impl Parser { } /// parses inline definitions - fn parse_inline(&mut self) -> Result { + fn parse_line(&mut self) -> Result { if self.index > self.text.len() { Err(ParseError::new(self.index)) } else { if let Ok(ruler) = self.parse_ruler() { - return Ok(Inline::Ruler(ruler)); - } else if let Ok(text) = self.parse_text() { - return Ok(Inline::Text(text)); + return Ok(Line::Ruler(ruler)); + } else if let Ok(text) = self.parse_text_line() { + return Ok(Line::Text(text)); } return Err(ParseError::new(self.index)); } } /// parses a placeholder element - fn parse_placeholder(&mut self) -> Result>, ParseError> { + pub(crate) fn parse_placeholder(&mut self) -> Result>, ParseError> { let start_index = self.index; self.assert_special_sequence(&SQ_PHOLDER_START, self.index)?; self.skip_char(); @@ -731,9 +732,9 @@ impl Parser { } /// Parses a line of text - fn parse_text(&mut self) -> Result { - let mut text = Text::new(); - while let Ok(subtext) = self.parse_subtext() { + fn parse_text_line(&mut self) -> Result { + let mut text = TextLine::new(); + while let Ok(subtext) = self.parse_inline() { text.add_subtext(subtext); let current_index = self.index; if self.next_char() == None { @@ -748,158 +749,4 @@ impl Parser { Ok(text) } - - /// parses subtext, the formatting parts of a line (Text) - fn parse_subtext(&mut self) -> Result { - if self.check_linebreak() { - return Err(ParseError::new(self.index)); - } - if let Ok(image) = self.parse_image() { - return Ok(SubText::Image(image)); - } - if let Ok(url) = self.parse_url(false) { - return Ok(SubText::Url(url)); - } - if let Ok(pholder) = self.parse_placeholder() { - return Ok(SubText::Placeholder(pholder)); - } - match self.current_char { - ASTERISK if !self.check_escaped() => { - parse_option!(self.next_char(), self.index); - - if self.check_special(&ASTERISK) { - parse_option!(self.next_char(), self.index); - let subtext = self.parse_subtext()?; - if self.check_special(&ASTERISK) { - self.skip_char(); - if self.check_special(&ASTERISK) { - self.skip_char(); - } - } - Ok(SubText::Bold(BoldText { - value: Box::new(subtext), - })) - } else { - let subtext = self.parse_subtext()?; - if self.check_special(&ASTERISK) { - self.skip_char(); - } - Ok(SubText::Italic(ItalicText { - value: Box::new(subtext), - })) - } - } - UNDERSCR if !self.check_escaped() => { - parse_option!(self.next_char(), self.index); - let subtext = self.parse_subtext()?; - parse_option!(self.next_char(), self.index); - Ok(SubText::Underlined(UnderlinedText { - value: Box::new(subtext), - })) - } - TILDE if !self.check_escaped() => { - parse_option!(self.next_char(), self.index); - let subtext = self.parse_subtext()?; - if self.check_special(&TILDE) { - parse_option!(self.next_char(), self.index); - } - Ok(SubText::Striked(StrikedText { - value: Box::new(subtext), - })) - } - BACKTICK if !self.check_escaped() => { - parse_option!(self.next_char(), self.index); - let content = self.get_string_until(&[BACKTICK, LB], &[])?; - if self.check_special(&BACKTICK) { - parse_option!(self.next_char(), self.index) - } - Ok(SubText::Monospace(MonospaceText { value: content })) - } - PIPE if !self.check_escaped() => Err(ParseError::new(self.index)), // handling of table cells - _ => Ok(SubText::Plain(self.parse_plain_text()?)), - } - } - - /// parses an image url - fn parse_image(&mut self) -> Result { - let start_index = self.index; - self.seek_inline_whitespace(); - self.assert_special(&IMG_START, start_index)?; - self.skip_char(); - - if let Ok(url) = self.parse_url(true) { - let metadata = if let Ok(meta) = self.parse_inline_metadata() { - Some(meta) - } else { - None - }; - Ok(Image { url, metadata }) - } else { - Err(self.revert_with_error(start_index)) - } - } - - // parses an url - fn parse_url(&mut self, short_syntax: bool) -> Result { - let start_index = self.index; - self.seek_inline_whitespace(); - - let mut description = String::new(); - if self.check_special(&DESC_OPEN) { - self.skip_char(); - description = if let Ok(desc) = self.get_string_until(&[DESC_CLOSE], &[LB]) { - desc - } else { - return Err(self.revert_with_error(start_index)); - }; - } else if !short_syntax { - return Err(self.revert_with_error(start_index)); - } - self.skip_char(); - self.assert_special(&URL_OPEN, start_index)?; - self.skip_char(); - self.seek_inline_whitespace(); - - let url = if let Ok(url_str) = self.get_string_until(&[URL_CLOSE], &[LB]) { - url_str - } else { - return Err(self.revert_with_error(start_index)); - }; - self.skip_char(); - - if description.is_empty() { - Ok(Url::new(None, url)) - } else { - Ok(Url::new(Some(description), url)) - } - } - - /// parses plain text as a string until it encounters an unescaped special inline char - fn parse_plain_text(&mut self) -> Result { - let mut current_char = self.current_char; - let mut characters = String::new(); - let mut count = 0; - loop { - if self.check_special_group(&INLINE_SPECIAL_CHARS) - || (count > 0 && self.check_special_group(&INLINE_SPECIAL_CHARS_SECOND)) - || (count > 0 && self.check_special_group(&self.subtext_break_at)) - { - break; - } else if !self.check_special(&SPECIAL_ESCAPE) { - characters.push(current_char) - } - if let Some(character) = self.next_char() { - current_char = character; - } else { - break; - } - count += 1; - } - - if characters.len() > 0 { - Ok(PlainText { value: characters }) - } else { - Err(ParseError::new(self.index)) - } - } } diff --git a/src/parsing/placeholders.rs b/src/parsing/placeholders.rs index 7345e26..923a833 100644 --- a/src/parsing/placeholders.rs +++ b/src/parsing/placeholders.rs @@ -8,15 +8,15 @@ macro_rules! block { } #[allow(unused)] -macro_rules! inline { +macro_rules! line { ($inner:expr) => { - Element::Inline(Box::new($inner)) + Element::Line(Box::new($inner)) }; } -macro_rules! subtext { +macro_rules! inline { ($inner:expr) => { - Element::SubText(Box::new($inner)) + Element::Inline(Box::new($inner)) }; } @@ -36,13 +36,13 @@ impl ProcessPlaceholders for Document { let mut pholder = p.lock().unwrap(); match pholder.name.to_ascii_lowercase().as_str() { P_TOC => pholder.set_value(block!(Block::List(self.create_toc()))), - P_DATE => pholder.set_value(subtext!(SubText::Plain(PlainText { + P_DATE => pholder.set_value(inline!(Inline::Plain(PlainText { value: get_date_string() }))), - P_TIME => pholder.set_value(subtext!(SubText::Plain(PlainText { + P_TIME => pholder.set_value(inline!(Inline::Plain(PlainText { value: get_time_string() }))), - P_DATETIME => pholder.set_value(subtext!(SubText::Plain(PlainText { + P_DATETIME => pholder.set_value(inline!(Inline::Plain(PlainText { value: format!("{} {}", get_date_string(), get_time_string()) }))), _ => {} diff --git a/src/parsing/subtext.rs b/src/parsing/subtext.rs new file mode 100644 index 0000000..7b5cd8e --- /dev/null +++ b/src/parsing/subtext.rs @@ -0,0 +1,178 @@ +use super::charstate::CharStateMachine; +use super::elements::*; +use super::parser::ParseError; +use super::tokens::*; +use crate::Parser; + +pub(crate) trait ParseInline { + fn parse_inline(&mut self) -> Result; + fn parse_image(&mut self) -> Result; + fn parse_url(&mut self, short_syntax: bool) -> Result; + fn parse_bold(&mut self) -> Result; + fn parse_italic(&mut self) -> Result; + fn parse_striked(&mut self) -> Result; + fn parse_monospace(&mut self) -> Result; + fn parse_underlined(&mut self) -> Result; + fn parse_plain(&mut self) -> Result; + fn parse_surrounded(&mut self, surrounding: &char) -> Result; +} + +impl ParseInline for Parser { + /// parses Inline, the formatting parts of a line (Text) + fn parse_inline(&mut self) -> Result { + if self.check_special(&PIPE) || self.check_linebreak() { + Err(ParseError::new(self.index)) + } else if let Ok(image) = self.parse_image() { + Ok(Inline::Image(image)) + } else if let Ok(url) = self.parse_url(false) { + Ok(Inline::Url(url)) + } else if let Ok(pholder) = self.parse_placeholder() { + Ok(Inline::Placeholder(pholder)) + } else if let Ok(bold) = self.parse_bold() { + Ok(Inline::Bold(bold)) + } else if let Ok(italic) = self.parse_italic() { + Ok(Inline::Italic(italic)) + } else if let Ok(under) = self.parse_underlined() { + Ok(Inline::Underlined(under)) + } else if let Ok(mono) = self.parse_monospace() { + Ok(Inline::Monospace(mono)) + } else if let Ok(striked) = self.parse_striked() { + Ok(Inline::Striked(striked)) + } else { + Ok(Inline::Plain(self.parse_plain()?)) + } + } + + /// parses an image url + fn parse_image(&mut self) -> Result { + let start_index = self.index; + self.seek_inline_whitespace(); + self.assert_special(&IMG_START, start_index)?; + self.skip_char(); + + if let Ok(url) = self.parse_url(true) { + let metadata = if let Ok(meta) = self.parse_inline_metadata() { + Some(meta) + } else { + None + }; + Ok(Image { url, metadata }) + } else { + Err(self.revert_with_error(start_index)) + } + } + + // parses an url + fn parse_url(&mut self, short_syntax: bool) -> Result { + let start_index = self.index; + self.seek_inline_whitespace(); + + let mut description = String::new(); + if self.check_special(&DESC_OPEN) { + self.skip_char(); + description = if let Ok(desc) = self.get_string_until(&[DESC_CLOSE], &[LB]) { + desc + } else { + return Err(self.revert_with_error(start_index)); + }; + } else if !short_syntax { + return Err(self.revert_with_error(start_index)); + } + self.skip_char(); + self.assert_special(&URL_OPEN, start_index)?; + self.skip_char(); + self.seek_inline_whitespace(); + + let url = if let Ok(url_str) = self.get_string_until(&[URL_CLOSE], &[LB]) { + url_str + } else { + return Err(self.revert_with_error(start_index)); + }; + self.skip_char(); + + if description.is_empty() { + Ok(Url::new(None, url)) + } else { + Ok(Url::new(Some(description), url)) + } + } + + /// parses bold text with must start with two asterisks + fn parse_bold(&mut self) -> Result { + let start_index = self.index; + self.assert_special_sequence(&BOLD, start_index)?; + self.skip_char(); + let inline = self.parse_inline()?; + self.assert_special_sequence(&BOLD, start_index)?; + self.skip_char(); + + Ok(BoldText { + value: Box::new(inline), + }) + } + + fn parse_italic(&mut self) -> Result { + Ok(ItalicText { + value: Box::new(self.parse_surrounded(&ITALIC)?), + }) + } + + fn parse_striked(&mut self) -> Result { + Ok(StrikedText { + value: Box::new(self.parse_surrounded(&STRIKED)?), + }) + } + + /// parses monospace text (inline-code) that isn't allowed to contain special characters + fn parse_monospace(&mut self) -> Result { + let start_index = self.index; + self.assert_special(&BACKTICK, start_index)?; + self.skip_char(); + let content = self.get_string_until(&[BACKTICK, LB], &[])?; + self.assert_special(&BACKTICK, start_index)?; + self.skip_char(); + + Ok(MonospaceText { value: content }) + } + + fn parse_underlined(&mut self) -> Result { + Ok(UnderlinedText { + value: Box::new(self.parse_surrounded(&UNDERLINED)?), + }) + } + + /// parses plain text as a string until it encounters an unescaped special inline char + fn parse_plain(&mut self) -> Result { + if self.check_linebreak() { + return Err(ParseError::new(self.index)); + } + let mut characters = String::new(); + characters.push(self.current_char); + while let Some(ch) = self.next_char() { + if self.check_special_group(&INLINE_SPECIAL_CHARS) + || self.check_special_group(&self.inline_break_at) + { + break; + } + characters.push(ch) + } + + if characters.len() > 0 { + Ok(PlainText { value: characters }) + } else { + Err(ParseError::new(self.index)) + } + } + + /// parses Inline surrounded by characters + fn parse_surrounded(&mut self, surrounding: &char) -> Result { + let start_index = self.index; + self.assert_special(surrounding, start_index)?; + self.skip_char(); + let inline = self.parse_inline()?; + self.assert_special(surrounding, start_index)?; + self.skip_char(); + + Ok(inline) + } +} diff --git a/src/parsing/tokens.rs b/src/parsing/tokens.rs index 8df9769..c0ef6d1 100644 --- a/src/parsing/tokens.rs +++ b/src/parsing/tokens.rs @@ -42,6 +42,12 @@ pub(crate) const IMPORT_CLOSE: char = L_BRACKET; pub(crate) const PHOLDER_OPEN: char = R_BRACKET; pub(crate) const PHOLDER_CLOSE: char = L_BRACKET; +pub(crate) const ITALIC: char = ASTERISK; +pub(crate) const MONOSPACE: char = BACKTICK; +pub(crate) const STRIKED: char = TILDE; +pub(crate) const UNDERLINED: char = UNDERSCR; +pub(crate) const BOLD: [char; 2] = [ASTERISK, ASTERISK]; + // groups pub(crate) const QUOTES: [char; 2] = [SINGLE_QUOTE, DOUBLE_QUOTE]; @@ -57,8 +63,9 @@ pub(crate) const BLOCK_SPECIAL_CHARS: [&[char]; 8] = [ &[IMPORT_START, IMPORT_OPEN], ]; -pub(crate) const INLINE_SPECIAL_CHARS: [char; 5] = [LB, ASTERISK, UNDERSCR, TILDE, BACKTICK]; -pub(crate) const INLINE_SPECIAL_CHARS_SECOND: [char; 3] = [DESC_OPEN, IMG_START, URL_OPEN]; +pub(crate) const INLINE_SPECIAL_CHARS: [char; 8] = [ + BACKTICK, TILDE, UNDERSCR, ASTERISK, DESC_OPEN, IMG_START, URL_OPEN, LB, +]; pub(crate) const LIST_SPECIAL_CHARS: [char; 14] = [ MINUS, PLUS, ASTERISK, O, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',