refactor(npf): simplify TryFrom implementation and NPF folding

This commit is contained in:
Gustavo "Guz" L. de Mello
2024-04-25 19:11:07 -03:00
parent 498a9ed57f
commit 3b8b834521
2 changed files with 79 additions and 116 deletions

View File

@@ -1,12 +1,8 @@
use std::{ use std::cell::RefCell;
borrow::{Borrow, BorrowMut},
cell::RefCell,
collections::VecDeque,
};
use comrak::{ use comrak::{
arena_tree::Node, arena_tree::{Children, Node},
nodes::{Ast, AstNode, NodeValue}, nodes::{Ast, NodeValue},
}; };
pub mod attributions; pub mod attributions;
@@ -28,111 +24,87 @@ pub enum NPFConvertError {
InvalidURL { url: String, err: url::ParseError }, InvalidURL { url: String, err: url::ParseError },
} }
fn extract_text(contents: &Vec<BlockValue>) -> String { impl<'a> TryFrom<Children<'a, RefCell<Ast>>> for objects::Post {
contents type Error = NPFConvertError;
.iter() fn try_from(mut nodes: Children<'a, RefCell<Ast>>) -> Result<Self, Self::Error> {
.fold(String::new(), |mut a, c| { nodes.try_fold(Self::new(0), |mut acc, n| {
if let BlockValue::Text(block) = c { acc.content.append(&mut Self::try_from(n)?.content);
a.push_str(&format!(" {}", block.text)); Ok(acc)
}
a
}) })
.trim() }
.to_string()
} }
impl<'a> TryFrom<&'a Node<'a, RefCell<Ast>>> for objects::Post { impl<'a> TryFrom<&'a Node<'a, RefCell<Ast>>> for objects::Post {
type Error = NPFConvertError; type Error = NPFConvertError;
fn try_from(value: &'a Node<'a, RefCell<Ast>>) -> Result<Self, Self::Error> { fn try_from(node: &'a Node<'a, RefCell<Ast>>) -> Result<Self, Self::Error> {
let mut post = Self::new(0); match &node.data.borrow().value {
NodeValue::Document => Self::try_from(node.children()),
let nodes = value.children().into_iter(); NodeValue::Paragraph => {
let r: Result<Vec<_>, NPFConvertError> = nodes let p = Self::try_from(node.children())?.fold_content();
.map(|n| match &n.data.borrow().value { println!("{p:#?}");
NodeValue::Paragraph => { Ok(p)
let mut paragraph_contents = Self::try_from(n)?.content; }
post.content.append(&mut paragraph_contents); NodeValue::Text(t) => {
Ok(()) let mut post = Self::new(0);
} let block_text = BlockText::from(String::from(t.clone()));
NodeValue::Text(t) => { post.content.push(BlockValue::Text(block_text));
let block_text = BlockText::from(String::from(t.clone())); Ok(post)
post.content.push(BlockValue::Text(block_text)); }
Ok(()) NodeValue::Strong => Ok(Self::try_from(node.children())?
} .fold_content()
NodeValue::Strong => { .for_each_content(|c| {
let mut content = Self::try_from(n)? if let BlockValue::Text(ref mut t) = c {
.fold_content() let format = FormatValue::Bold(FormatTypeBold::from(&t.text));
.for_each_content(|c| { t.push_formatting(format);
if let BlockValue::Text(ref mut t) = c { // t.text = String::from(t.text.trim());
let format = FormatValue::Bold(FormatTypeBold::from(&t.text));
t.push_formatting(format);
t.text = String::from(t.text.trim());
}
})
.content;
post.content.append(&mut content);
Ok(())
}
NodeValue::Emph => {
let mut content = Self::try_from(n)?
.fold_content()
.for_each_content(|c| {
if let BlockValue::Text(ref mut t) = c {
let format = FormatValue::Italic(FormatTypeItalic::from(&t.text));
t.push_formatting(format);
t.text = String::from(t.text.trim());
}
})
.content;
post.content.append(&mut content);
// println!("{:#?}", post);
Ok(())
}
NodeValue::Strikethrough => {
let mut content = Self::try_from(n)?
.fold_content()
.for_each_content(|c| {
if let BlockValue::Text(ref mut t) = c {
let format = FormatValue::StrikeThrough(
FormatTypeStrikeThrough::from(&t.text),
);
t.push_formatting(format);
t.text = String::from(t.text.trim());
}
})
.content;
post.content.append(&mut content);
Ok(())
}
NodeValue::Link(link) => match url::Url::parse(&link.url) {
Ok(url) => {
let mut content = Self::try_from(n)?
.fold_content()
.for_each_content(|c| {
if let BlockValue::Text(ref mut t) = c {
let mut format = FormatTypeLink::from(&t.text);
format.url = url.clone();
t.push_formatting(FormatValue::Link(format));
t.text = String::from(t.text.trim());
}
})
.content;
post.content.append(&mut content);
Ok(())
} }
Err(err) => Err(NPFConvertError::InvalidURL { })),
url: link.url.clone(), NodeValue::Emph => Ok(Self::try_from(node.children())?
err, .fold_content()
}), .for_each_content(|c| {
}, if let BlockValue::Text(ref mut t) = c {
_ => Ok(()), let format = FormatValue::Italic(FormatTypeItalic::from(&t.text));
}) t.push_formatting(format);
.collect(); // t.text = String::from(t.text.trim());
if let Err(e) = r { }
Err(e) })),
} else { NodeValue::Strikethrough => Ok(Self::try_from(node.children())?
Ok(post) .fold_content()
.for_each_content(|c| {
if let BlockValue::Text(ref mut t) = c {
let format =
FormatValue::StrikeThrough(FormatTypeStrikeThrough::from(&t.text));
t.push_formatting(format);
// t.text = String::from(t.text.trim());
}
})),
NodeValue::Link(link) => match url::Url::parse(&link.url) {
Ok(url) => Ok(Self::try_from(node.children())?
.fold_content()
.for_each_content(|c| {
if let BlockValue::Text(ref mut t) = c {
let mut format = FormatTypeLink::from(&t.text);
format.url = url.clone();
t.push_formatting(FormatValue::Link(format));
// t.text = String::from(t.text.trim());
}
})),
Err(err) => Err(NPFConvertError::InvalidURL {
url: link.url.clone(),
err,
}),
},
NodeValue::SoftBreak => {
let mut post = Self::new(0);
post.content.push(BlockValue::Text(BlockText::from(" ")));
Ok(post)
}
NodeValue::LineBreak => {
let mut post = Self::new(0);
post.content.push(BlockValue::Text(BlockText::from("\n")));
Ok(post)
}
_ => Ok(Self::new(0)),
} }
} }
} }

View File

@@ -78,12 +78,6 @@ impl Post {
} }
}) })
.flatten() .flatten()
.map(|mut a| {
if let BlockValue::Text(ref mut t) = a {
t.text = String::from(t.text.trim());
}
a
})
.collect::<Vec<_>>(); .collect::<Vec<_>>();
self self
} }
@@ -154,8 +148,6 @@ impl From<u64> for Post {
fn fold_text_block(mut acc: BlockText, c: &mut BlockValue) -> BlockText { fn fold_text_block(mut acc: BlockText, c: &mut BlockValue) -> BlockText {
if let BlockValue::Text(t) = c { if let BlockValue::Text(t) = c {
let text = &t.text.trim();
if let Some(ref mut f) = &mut t.formatting { if let Some(ref mut f) = &mut t.formatting {
let offset = acc.text.chars().count() as u64; let offset = acc.text.chars().count() as u64;
f.iter_mut().for_each(|f| f.offset(offset)); f.iter_mut().for_each(|f| f.offset(offset));
@@ -166,8 +158,7 @@ fn fold_text_block(mut acc: BlockText, c: &mut BlockValue) -> BlockText {
acc.formatting = Some(f.to_vec()); acc.formatting = Some(f.to_vec());
} }
} }
acc.text.push_str(&t.text);
acc.text.push_str(&format!("{} ", text));
} }
acc acc
} }