Skip to content

Commit

Permalink
Node should start from delimiter (#39)
Browse files Browse the repository at this point in the history
A node should start from the delimiter.
  • Loading branch information
Lurk authored Nov 2, 2023
1 parent accffe2 commit 6d557fe
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 37 deletions.
7 changes: 6 additions & 1 deletion src/nodes/accordion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl Display for Accordion {

impl Node for Accordion {
fn len(&self) -> usize {
let delimiter_len = if self.nodes.is_empty() {
let delimiter_len = if self.is_empty() {
0
} else {
self.nodes.len() - 1
Expand All @@ -100,6 +100,10 @@ impl Branch<AccordionNodes> for Accordion {
fn get_outer_token_length(&self) -> usize {
8
}

fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
}

impl Deserializer for Accordion {
Expand Down Expand Up @@ -190,5 +194,6 @@ mod test {
fn empty_accordion() {
let accordion = Accordion::default();
assert_eq!(accordion.len(), 8);
assert_eq!(accordion.is_empty(), true);
}
}
12 changes: 10 additions & 2 deletions src/nodes/accordion_tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl Display for AccordionTab {

impl Node for AccordionTab {
fn len(&self) -> usize {
let delimeter_len = if self.nodes.is_empty() {
let delimeter_len = if self.is_empty() {
0
} else {
(self.nodes.len() - 1) * 2
Expand Down Expand Up @@ -186,6 +186,10 @@ impl Branch<AccordionTabNodes> for AccordionTab {
fn get_outer_token_length(&self) -> usize {
6 + self.header.as_ref().map_or(0, |header| header.len() + 3)
}

fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
}

impl Deserializer for AccordionTab {
Expand Down Expand Up @@ -214,7 +218,10 @@ mod cfg {
list::ListTypes::*, list_item::ListItem, list_item_content::ListItemContent,
paragraph::Paragraph, text::Text,
},
toolkit::{deserializer::Deserializer, node::Node},
toolkit::{
deserializer::{Branch, Deserializer},
node::Node,
},
};

#[test]
Expand Down Expand Up @@ -350,5 +357,6 @@ t**b**
fn empty_tab() {
let tab = AccordionTab::new::<&str>(None, vec![]);
assert_eq!(tab.len(), 6);
assert_eq!(tab.is_empty(), true);
}
}
5 changes: 5 additions & 0 deletions src/nodes/bold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ impl Branch<BoldNodes> for Bold {
fn get_outer_token_length(&self) -> usize {
4
}

fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
}

impl Display for Bold {
Expand Down Expand Up @@ -188,5 +192,6 @@ mod tests {
fn empty_bold() {
let b = Bold::new(vec![]);
assert_eq!(b.len(), 4);
assert_eq!(b.is_empty(), true);
}
}
12 changes: 10 additions & 2 deletions src/nodes/highlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl Display for Highlight {

impl Node for Highlight {
fn len(&self) -> usize {
let delimiter_length = if self.nodes.is_empty() {
let delimiter_length = if self.is_empty() {
0
} else {
(self.nodes.len() - 1) * 2
Expand Down Expand Up @@ -114,6 +114,10 @@ impl Branch<HighlightNodes> for Highlight {
8 + self.header.as_ref().map_or(0, |header| header.len() + 4)
+ self.icon.as_ref().map_or(0, |icon| icon.len() + 3)
}

fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
}

impl Deserializer for Highlight {
Expand All @@ -138,7 +142,10 @@ impl Deserializer for Highlight {
mod tests {
use crate::{
nodes::{highlight::Highlight, paragraph::Paragraph, text::Text},
toolkit::{deserializer::Deserializer, node::Node},
toolkit::{
deserializer::{Branch, Deserializer},
node::Node,
},
};
use pretty_assertions::assert_eq;

Expand Down Expand Up @@ -228,5 +235,6 @@ mod tests {
fn empty_highlight() {
let highlight = Highlight::new::<String, String>(None, None, vec![]);
assert_eq!(highlight.len(), 8);
assert_eq!(highlight.is_empty(), true);
}
}
12 changes: 10 additions & 2 deletions src/nodes/image_gallery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ impl Display for ImageGallery {

impl Node for ImageGallery {
fn len(&self) -> usize {
let delimiter_len = if self.nodes.is_empty() {
let delimiter_len = if self.is_empty() {
0
} else {
self.nodes.len() - 1
Expand Down Expand Up @@ -111,14 +111,21 @@ impl Branch<ImageGalleryNodes> for ImageGallery {
fn get_outer_token_length(&self) -> usize {
8
}

fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
}

#[cfg(test)]
mod tests {
use super::ImageGallery;
use crate::{
nodes::image::Image,
toolkit::{deserializer::Deserializer, node::Node},
toolkit::{
deserializer::{Branch, Deserializer},
node::Node,
},
};
use pretty_assertions::assert_eq;

Expand Down Expand Up @@ -176,5 +183,6 @@ mod tests {
fn empty_gallery() {
let gal = ImageGallery::new(vec![]);
assert_eq!(gal.len(), 8);
assert_eq!(gal.is_empty(), true);
}
}
6 changes: 5 additions & 1 deletion src/nodes/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl Display for List {

impl Node for List {
fn len(&self) -> usize {
let add = if self.nodes.is_empty() {
let add = if self.is_empty() {
0
} else {
self.nodes.len() - 1
Expand Down Expand Up @@ -154,6 +154,10 @@ impl Branch<ListNodes> for List {
fn get_outer_token_length(&self) -> usize {
0
}

fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
}

#[cfg(test)]
Expand Down
10 changes: 9 additions & 1 deletion src/nodes/list_item_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ impl Branch<ListItemContentNodes> for ListItemContent {
fn get_outer_token_length(&self) -> usize {
0
}

fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
}

impl Deserializer for ListItemContent {
Expand All @@ -166,7 +170,10 @@ mod test {
anchor::Anchor, bold::Bold, inline_code::InlineCode, italic::Italic,
strikethrough::Strikethrough, text::Text,
},
toolkit::{deserializer::Deserializer, node::Node},
toolkit::{
deserializer::{Branch, Deserializer},
node::Node,
},
};
use pretty_assertions::assert_eq;

Expand Down Expand Up @@ -246,5 +253,6 @@ mod test {
fn empty_list_item_content() {
let list_item_content = ListItemContent::default();
assert_eq!(list_item_content.len(), 0);
assert_eq!(list_item_content.is_empty(), true);
}
}
5 changes: 5 additions & 0 deletions src/nodes/paragraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ impl Branch<ParagraphNodes> for Paragraph {
fn get_outer_token_length(&self) -> usize {
0
}

fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
}
impl Default for Paragraph {
fn default() -> Self {
Expand Down Expand Up @@ -227,5 +231,6 @@ mod tests {
#[test]
fn len() {
assert_eq!(Paragraph::default().len(), 0);
assert_eq!(Paragraph::default().is_empty(), true);
}
}
18 changes: 17 additions & 1 deletion src/nodes/yamd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ impl Branch<YamdNodes> for Yamd {
fn get_outer_token_length(&self) -> usize {
0
}

fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
}

impl Deserializer for Yamd {
Expand Down Expand Up @@ -192,7 +196,7 @@ impl Display for Yamd {

impl Node for Yamd {
fn len(&self) -> usize {
let delimeter_len = if self.nodes.is_empty() {
let delimeter_len = if self.is_empty() {
0
} else {
(self.nodes.len() - 1) * 2
Expand Down Expand Up @@ -499,5 +503,17 @@ end"#;
fn empty_yamd() {
let yamd = Yamd::new(None, vec![]);
assert_eq!(yamd.len(), 0);
assert_eq!(yamd.is_empty(), true);
}

#[test]
fn node_should_start_from_delimiter() {
let input = "text - text";
let expected = Yamd::new(
None,
vec![Paragraph::new(vec![Text::new("text - text").into()]).into()],
);
let actual = Yamd::deserialize(input).unwrap();
assert_eq!(expected, actual);
}
}
59 changes: 32 additions & 27 deletions src/toolkit/deserializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,38 @@ where
fn get_maybe_nodes() -> Vec<MaybeNode<BranchNodes>>;
fn get_fallback_node() -> Option<DefinitelyNode<BranchNodes>>;
fn get_outer_token_length(&self) -> usize;
fn is_empty(&self) -> bool;
fn parse_branch(input: &str, delimeter: &str, mut branch: Self) -> Option<Self>
where
Self: Sized + Deserializer + Node,
{
let mut current_position = 0;
let mut next_position = 0;
let mut fallback_position = 0;
let maybe_nodes = Self::get_maybe_nodes();
while current_position < input.len() {
let slice = &input[current_position..];
let char_len = slice.chars().next().unwrap().len_utf8();
current_position += char_len;
for parser in &maybe_nodes {
if let Some(node) = parser(slice, branch.context()) {
while fallback_position != current_position - char_len {
fallback_position = branch.fallback(
&input[fallback_position..current_position - char_len],
delimeter,
);
next_position += slice.chars().next().unwrap().len_utf8();
if delimeter.is_empty() || slice.starts_with(delimeter) || current_position == 0 {
let slice = if current_position == 0 {
slice
} else {
&slice[delimeter.len()..]
};
for parser in &maybe_nodes {
if let Some(node) = parser(slice, branch.context()) {
while fallback_position != current_position {
fallback_position = branch
.fallback(&input[fallback_position..current_position], delimeter);
}
branch.push(node);
next_position = branch.len() - branch.get_outer_token_length();
fallback_position = next_position;
break;
}
branch.push(node);
current_position = branch.len() - branch.get_outer_token_length();
fallback_position = current_position;
if !delimeter.is_empty() && input[current_position..].starts_with(delimeter) {
current_position += delimeter.len();
fallback_position = current_position;
}

break;
}
}
current_position = next_position;
}
while fallback_position < input.len() {
if Self::get_fallback_node().is_none() {
Expand All @@ -55,16 +57,19 @@ where
where
Self: Node,
{
let node = Self::get_fallback_node()
.map(|f| f(slice))
.expect("Fallback node should always be available");
let node_len = node.len();
self.push(node);
let mut fallback_position = self.len() - self.get_outer_token_length();
if !delimeter.is_empty() && slice[node_len..].starts_with(delimeter) {
fallback_position += delimeter.len();
let slice = if self.is_empty() {
slice
} else {
&slice[delimeter.len()..]
};
if !slice.is_empty() {
self.push(
Self::get_fallback_node()
.map(|f| f(slice))
.expect("Fallback node should always be available"),
);
}
fallback_position
self.len() - self.get_outer_token_length()
}
}

Expand Down

0 comments on commit 6d557fe

Please sign in to comment.