use std::fmt::Display;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use super::ListItem;
#[derive(Debug, PartialEq, Clone, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ListTypes {
Unordered,
Ordered,
}
impl Display for ListTypes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ListTypes::Unordered => write!(f, "-"),
ListTypes::Ordered => write!(f, "+"),
}
}
}
#[derive(Debug, PartialEq, Clone, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct List {
pub list_type: ListTypes,
pub level: usize,
pub body: Vec<ListItem>,
}
impl List {
pub fn new(list_type: ListTypes, level: usize, body: Vec<ListItem>) -> Self {
Self {
list_type,
level,
body,
}
}
}
impl Display for List {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let (pat, rep) = match self.list_type {
ListTypes::Unordered => ("\n- ", "\n\\- "),
ListTypes::Ordered => ("\n+ ", "\n\\+ "),
};
write!(
f,
"{}",
self.body
.iter()
.map(|list_item| format!(
"{}{} {}",
" ".repeat(self.level),
self.list_type,
list_item.to_string().replace(pat, rep)
))
.collect::<Vec<_>>()
.join("\n")
)
}
}
#[cfg(test)]
mod tests {
use crate::nodes::{ListItem, ListTypes};
#[test]
fn list() {
let list = super::List::new(
ListTypes::Unordered,
0,
vec![
ListItem::new(vec!["test".to_string().into()], None),
ListItem::new(vec!["test".to_string().into()], None),
],
);
assert_eq!(list.to_string(), "- test\n- test");
}
#[test]
fn ordered() {
assert_eq!(ListTypes::Ordered.to_string(), "+");
}
#[test]
fn unordered() {
assert_eq!(ListTypes::Unordered.to_string(), "-");
}
#[test]
fn nested_list() {
let list = super::List::new(
ListTypes::Unordered,
0,
vec![ListItem::new(
vec!["test".to_string().into()],
Some(super::List::new(
ListTypes::Ordered,
1,
vec![ListItem::new(vec!["test".to_string().into()], None)],
)),
)],
);
assert_eq!(list.to_string(), "- test\n + test");
}
}