use crate::elements::*; use htmlescape::encode_minimal; use minify::html::minify; macro_rules! combine_with_lb { ($a:expr, $b:expr) => { if $a.len() > 0 { format!("{}
{}", $a, $b.to_html()) } else { $b.to_html() } }; } pub trait ToHtml { fn to_html(&self) -> String; } impl ToHtml for Inline { fn to_html(&self) -> String { match self { Inline::Text(text) => text.to_html(), Inline::Ruler(ruler) => ruler.to_html(), } } } impl ToHtml for SubText { fn to_html(&self) -> String { match self { SubText::Url(url) => url.to_html(), SubText::Monospace(mono) => mono.to_html(), SubText::Striked(striked) => striked.to_html(), SubText::Plain(plain) => plain.to_html(), SubText::Italic(italic) => italic.to_html(), SubText::Underlined(under) => under.to_html(), SubText::Bold(bold) => bold.to_html(), SubText::Image(img) => img.to_html(), _ => "".to_string(), } } } impl ToHtml for Block { fn to_html(&self) -> String { match self { Block::Paragraph(para) => para.to_html(), Block::List(list) => list.to_html(), Block::Table(table) => table.to_html(), Block::CodeBlock(code) => code.to_html(), Block::Quote(quote) => quote.to_html(), Block::Section(section) => section.to_html(), Block::Import(import) => import.to_html(), } } } impl ToHtml for Document { fn to_html(&self) -> String { let inner = self .elements .iter() .fold("".to_string(), |a, b| format!("{}{}", a, b.to_html())); if self.is_root { let style = minify(std::include_str!("assets/style.css")); format!( "\n
{}
", style, inner ) } else { format!( "
{}
", inner ) } } } impl ToHtml for Import { fn to_html(&self) -> String { let anchor = self.anchor.lock().unwrap(); if let Some(document) = &anchor.document { document.to_html() } else { "".to_string() } } } impl ToHtml for Section { fn to_html(&self) -> String { let inner = self .elements .iter() .fold("".to_string(), |a, b| format!("{}{}", a, b.to_html())); format!("
{}{}
", self.header.to_html(), inner) } } impl ToHtml for Header { fn to_html(&self) -> String { format!("{1}", self.size, self.line.to_html()) } } impl ToHtml for Paragraph { fn to_html(&self) -> String { let inner = self .elements .iter() .fold("".to_string(), |a, b| combine_with_lb!(a, b)); format!("

{}

", inner) } } impl ToHtml for List { fn to_html(&self) -> String { let inner = self .items .iter() .fold("".to_string(), |a, b| format!("{}{}", a, b.to_html())); if self.ordered { format!("
    {}
", inner) } else { format!("", inner) } } } impl ToHtml for ListItem { fn to_html(&self) -> String { let inner = self .children .iter() .fold("".to_string(), |a, b| format!("{}{}", a, b.to_html())); if let Some(first) = self.children.first() { if first.ordered { format!("
  • {}
      {}
  • ", self.text.to_html(), inner) } else { format!("
  • {}
  • ", self.text.to_html(), inner) } } else { format!("
  • {}
  • ", self.text.to_html()) } } } impl ToHtml for Table { fn to_html(&self) -> String { let head = self.header.cells.iter().fold("".to_string(), |a, b| { format!("{}{}", a, b.text.to_html()) }); let body = self .rows .iter() .fold("".to_string(), |a, b| format!("{}{}", a, b.to_html())); format!( "
    {}{}
    ", head, body ) } } impl ToHtml for Row { fn to_html(&self) -> String { let inner = self .cells .iter() .fold("".to_string(), |a, b| format!("{}{}", a, b.to_html())); format!("{}", inner) } } impl ToHtml for Cell { fn to_html(&self) -> String { format!("{}", self.text.to_html()) } } impl ToHtml for CodeBlock { fn to_html(&self) -> String { format!( "
    {}
    ", self.language.clone(), self.code.clone() ) } } impl ToHtml for Quote { fn to_html(&self) -> String { let text = self .text .iter() .fold("".to_string(), |a, b| combine_with_lb!(a, b)); if let Some(meta) = self.metadata.clone() { format!( "
    {}
    {}
    ", text, encode_minimal(meta.data.as_str()) ) } else { format!("
    {}
    ", text) } } } impl ToHtml for Ruler { fn to_html(&self) -> String { "
    ".to_string() } } impl ToHtml for Text { fn to_html(&self) -> String { self.subtext .iter() .fold("".to_string(), |a, b| format!("{}{}", a, b.to_html())) } } impl ToHtml for Image { fn to_html(&self) -> String { if let Some(description) = self.url.description.clone() { minify( format!( "
    \ \ {1}\ \ \
    ", encode_minimal(self.url.url.clone().as_str()), encode_minimal(description.as_str()) ) .as_str(), ) } else { format!("", self.url.url.clone(),) } } } impl ToHtml for BoldText { fn to_html(&self) -> String { format!("{}", self.value.to_html()) } } impl ToHtml for UnderlinedText { fn to_html(&self) -> String { format!("{}", self.value.to_html()) } } impl ToHtml for ItalicText { fn to_html(&self) -> String { format!("{}", self.value.to_html()) } } impl ToHtml for StrikedText { fn to_html(&self) -> String { format!("{}", self.value.to_html()) } } impl ToHtml for MonospaceText { fn to_html(&self) -> String { format!("{}", self.value.to_html()) } } impl ToHtml for Url { fn to_html(&self) -> String { if let Some(description) = self.description.clone() { format!( "{}", self.url.clone(), encode_minimal(description.as_str()) ) } else { format!( "{}", self.url.clone(), encode_minimal(self.url.clone().as_str()) ) } } } impl ToHtml for PlainText { fn to_html(&self) -> String { encode_minimal(self.value.clone().as_str()) } }