refactor: improve Post's api for the conversion

This commit is contained in:
Gustavo "Guz" L. de Mello
2024-04-24 20:27:06 -03:00
parent b57435c728
commit 41cb734457
3 changed files with 98 additions and 60 deletions

View File

@@ -1,6 +1,7 @@
use std::{
borrow::{Borrow, BorrowMut},
cell::RefCell,
collections::VecDeque,
};
use comrak::{
@@ -15,9 +16,12 @@ pub mod objects;
pub mod text_formatting;
mod objects_post;
use content_blocks::{BlockText, BlockValue};
use text_formatting::{FormatTypeBold, FormatTypeItalic, FormatValue};
use self::content_blocks::BlockImage;
#[derive(Debug)]
pub enum NPFConvertError {
TODO,
@@ -55,72 +59,41 @@ impl<'a> TryFrom<&'a Node<'a, RefCell<Ast>>> for objects::Post {
Ok(())
}
NodeValue::Strong => {
let mut content = Self::try_from(n)?.content;
let mut res = content.iter_mut().fold(
BlockText::new(&String::new()),
|mut acc, c| match c {
BlockValue::Text(t) => {
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);
});
if let Some(ref mut af) = acc.formatting {
af.append(f);
} else {
acc.formatting = Some(f.to_vec());
}
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));
if let Some(ref mut f) = t.formatting {
f.push(format);
} else {
t.formatting = Some(vec![format]);
}
acc.text.push_str(&format!("{} ", text));
acc
t.text = String::from(t.text.trim());
}
_ => acc,
},
);
res.text = res.text.trim().to_string();
let format = FormatValue::Bold(FormatTypeBold::from(&res.text));
if let Some(ref mut f) = res.formatting {
f.push(format);
} else {
res.formatting = Some(vec![format]);
}
post.content.push(BlockValue::Text(res));
})
.content;
post.content.append(&mut content);
Ok(())
}
NodeValue::Emph => {
let mut content = Self::try_from(n)?.content;
let mut res = content.iter_mut().fold(
BlockText::new(&String::new()),
|mut acc, c| match c {
BlockValue::Text(t) => {
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);
});
if let Some(ref mut af) = acc.formatting {
af.append(f);
} else {
acc.formatting = Some(f.to_vec());
}
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));
if let Some(ref mut f) = t.formatting {
f.push(format);
} else {
t.formatting = Some(vec![format]);
}
acc.text.push_str(&format!("{} ", text));
acc
t.text = String::from(t.text.trim());
}
_ => acc,
},
);
res.text = res.text.trim().to_string();
let format = FormatValue::Italic(FormatTypeItalic::from(&res.text));
if let Some(ref mut f) = res.formatting {
f.push(format);
} else {
res.formatting = Some(vec![format]);
}
// println!("italic {:#?}", res);
post.content.push(BlockValue::Text(res));
})
.content;
post.content.append(&mut content);
// println!("{:#?}", post);
Ok(())
}
_ => Ok(()),
@@ -129,7 +102,7 @@ impl<'a> TryFrom<&'a Node<'a, RefCell<Ast>>> for objects::Post {
if let Err(e) = r {
Err(e)
} else {
// println!("{:#?}", post);
println!("{:#?}", post);
Ok(post)
}
}

View File

@@ -13,6 +13,17 @@ pub enum BlockValue {
Audio(BlockAudio),
Video(BlockVideo),
}
impl BlockValue {
pub fn get_type(&self) -> String {
String::from(match &self {
BlockValue::Text(_) => "text",
BlockValue::Image(_) => "image",
BlockValue::Link(_) => "link",
BlockValue::Audio(_) => "audio",
BlockValue::Video(_) => "video",
})
}
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(rename_all = "snake_case")]

View File

@@ -1,4 +1,8 @@
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use super::content_blocks::{BlockText, BlockValue};
#[serde_with::skip_serializing_none]
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct Post {
@@ -56,6 +60,37 @@ impl Post {
false
}
}
pub fn fold_content(mut self) -> Self {
// TODO: Some form of folding also the layout of the npf
let groups = self.content.iter_mut().group_by(|c| c.get_type() == "text");
self.content = groups
.into_iter()
.map(|a| {
if a.0 == true {
vec![BlockValue::Text(
a.1.fold(BlockText::new(&String::new()), fold_text_block),
)]
} else {
a.1.map(|c| c.to_owned()).collect::<Vec<_>>()
}
})
.flatten()
.map(|mut a| {
if let BlockValue::Text(ref mut t) = a {
t.text = String::from(t.text.trim());
}
a
})
.collect::<Vec<_>>();
self
}
pub fn for_each_content<F>(mut self, f: F) -> Self
where
F: Fn(&mut BlockValue),
{
self.content.iter_mut().for_each(f);
self
}
fn default() -> Self {
Self {
object_type: String::from("post"),
@@ -114,3 +149,22 @@ 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));
if let Some(ref mut af) = acc.formatting {
af.append(f);
} else {
acc.formatting = Some(f.to_vec());
}
}
acc.text.push_str(&format!("{} ", text));
}
acc
}