#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Block {
Heading {
level: u8,
text: String,
},
Paragraph(String),
List {
marker: ListMarker,
items: Vec<String>,
},
Code(String),
Table(Vec<Vec<String>>),
Image {
alt: String,
index: Option<usize>,
},
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ListMarker {
Bullet,
Ordered,
Labelled(Vec<String>),
}
impl Block {
#[must_use]
pub fn text(&self) -> String {
match self {
Self::Paragraph(text) => {
lead_in(text).map_or_else(|| text.clone(), |(lead, rest)| format!("{lead}{rest}"))
}
Self::Heading { text, .. } | Self::Code(text) => text.clone(),
Self::List { items, .. } => items.join("\n"),
Self::Table(rows) => rows
.iter()
.map(|row| row.join("\t"))
.collect::<Vec<_>>()
.join("\n"),
Self::Image { alt, .. } => alt.clone(),
}
}
}
#[must_use]
pub fn lead_in(text: &str) -> Option<(&str, &str)> {
let (lead, rest) = text.strip_prefix("**")?.split_once("**")?;
(!lead.is_empty()).then_some((lead, rest))
}
#[cfg(test)]
mod tests {
use super::{Block, lead_in};
#[test]
fn a_lead_in_is_taken_apart_and_words_come_without_the_marks() {
assert_eq!(
lead_in("**Redaction** - Lets you"),
Some(("Redaction", " - Lets you"))
);
assert_eq!(lead_in("Redaction - Lets you"), None);
assert_eq!(lead_in("****"), None);
assert_eq!(
Block::Paragraph("**Redaction** - Lets you".into()).text(),
"Redaction - Lets you"
);
}
}