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,112 +24,88 @@ 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();
let r: Result<Vec<_>, NPFConvertError> = nodes
.map(|n| match &n.data.borrow().value {
NodeValue::Paragraph => { NodeValue::Paragraph => {
let mut paragraph_contents = Self::try_from(n)?.content; let p = Self::try_from(node.children())?.fold_content();
post.content.append(&mut paragraph_contents); println!("{p:#?}");
Ok(()) Ok(p)
} }
NodeValue::Text(t) => { NodeValue::Text(t) => {
let mut post = Self::new(0);
let block_text = BlockText::from(String::from(t.clone())); let block_text = BlockText::from(String::from(t.clone()));
post.content.push(BlockValue::Text(block_text)); post.content.push(BlockValue::Text(block_text));
Ok(()) Ok(post)
} }
NodeValue::Strong => { NodeValue::Strong => Ok(Self::try_from(node.children())?
let mut content = Self::try_from(n)?
.fold_content() .fold_content()
.for_each_content(|c| { .for_each_content(|c| {
if let BlockValue::Text(ref mut t) = c { if let BlockValue::Text(ref mut t) = c {
let format = FormatValue::Bold(FormatTypeBold::from(&t.text)); let format = FormatValue::Bold(FormatTypeBold::from(&t.text));
t.push_formatting(format); t.push_formatting(format);
t.text = String::from(t.text.trim()); // t.text = String::from(t.text.trim());
} }
}) })),
.content; NodeValue::Emph => Ok(Self::try_from(node.children())?
post.content.append(&mut content);
Ok(())
}
NodeValue::Emph => {
let mut content = Self::try_from(n)?
.fold_content() .fold_content()
.for_each_content(|c| { .for_each_content(|c| {
if let BlockValue::Text(ref mut t) = c { if let BlockValue::Text(ref mut t) = c {
let format = FormatValue::Italic(FormatTypeItalic::from(&t.text)); let format = FormatValue::Italic(FormatTypeItalic::from(&t.text));
t.push_formatting(format); t.push_formatting(format);
t.text = String::from(t.text.trim()); // t.text = String::from(t.text.trim());
} }
}) })),
.content; NodeValue::Strikethrough => Ok(Self::try_from(node.children())?
post.content.append(&mut content);
// println!("{:#?}", post);
Ok(())
}
NodeValue::Strikethrough => {
let mut content = Self::try_from(n)?
.fold_content() .fold_content()
.for_each_content(|c| { .for_each_content(|c| {
if let BlockValue::Text(ref mut t) = c { if let BlockValue::Text(ref mut t) = c {
let format = FormatValue::StrikeThrough( let format =
FormatTypeStrikeThrough::from(&t.text), FormatValue::StrikeThrough(FormatTypeStrikeThrough::from(&t.text));
);
t.push_formatting(format); t.push_formatting(format);
t.text = String::from(t.text.trim()); // t.text = String::from(t.text.trim());
}
})
.content;
post.content.append(&mut content);
Ok(())
} }
})),
NodeValue::Link(link) => match url::Url::parse(&link.url) { NodeValue::Link(link) => match url::Url::parse(&link.url) {
Ok(url) => { Ok(url) => Ok(Self::try_from(node.children())?
let mut content = Self::try_from(n)?
.fold_content() .fold_content()
.for_each_content(|c| { .for_each_content(|c| {
if let BlockValue::Text(ref mut t) = c { if let BlockValue::Text(ref mut t) = c {
let mut format = FormatTypeLink::from(&t.text); let mut format = FormatTypeLink::from(&t.text);
format.url = url.clone(); format.url = url.clone();
t.push_formatting(FormatValue::Link(format)); t.push_formatting(FormatValue::Link(format));
t.text = String::from(t.text.trim()); // t.text = String::from(t.text.trim());
}
})
.content;
post.content.append(&mut content);
Ok(())
} }
})),
Err(err) => Err(NPFConvertError::InvalidURL { Err(err) => Err(NPFConvertError::InvalidURL {
url: link.url.clone(), url: link.url.clone(),
err, err,
}), }),
}, },
_ => Ok(()), NodeValue::SoftBreak => {
}) let mut post = Self::new(0);
.collect(); post.content.push(BlockValue::Text(BlockText::from(" ")));
if let Err(e) = r {
Err(e)
} else {
Ok(post) 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
} }