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