From 3b8b834521f617a6b71fadd5a9df1ca67a6c9afa Mon Sep 17 00:00:00 2001 From: "Gustavo \"Guz\" L. de Mello" Date: Thu, 25 Apr 2024 19:11:07 -0300 Subject: [PATCH] refactor(npf): simplify TryFrom implementation and NPF folding --- src/convert/npf.rs | 184 ++++++++++++++------------------ src/convert/npf/objects_post.rs | 11 +- 2 files changed, 79 insertions(+), 116 deletions(-) diff --git a/src/convert/npf.rs b/src/convert/npf.rs index 5c82f39..4f20534 100644 --- a/src/convert/npf.rs +++ b/src/convert/npf.rs @@ -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) -> 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>> for objects::Post { + type Error = NPFConvertError; + fn try_from(mut nodes: Children<'a, RefCell>) -> Result { + 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>> for objects::Post { type Error = NPFConvertError; - fn try_from(value: &'a Node<'a, RefCell>) -> Result { - let mut post = Self::new(0); - - let nodes = value.children().into_iter(); - let r: Result, 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>) -> Result { + 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)), } } } diff --git a/src/convert/npf/objects_post.rs b/src/convert/npf/objects_post.rs index e4393ad..1742dbc 100644 --- a/src/convert/npf/objects_post.rs +++ b/src/convert/npf/objects_post.rs @@ -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::>(); self } @@ -154,8 +148,6 @@ impl From 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 }