Newer
Older
use anyhow::{bail, Context};
use orgize::{elements::Keyword, export::HtmlHandler, Element};
use time::{macros::format_description, Date};
use crate::{
date::parse_org_date,
parser::{CustomHtmlHandler, Parser},
};
pub struct Post {
pub title: String,
pub date_f: String,
pub content: String,
}
impl Post {
pub fn html(&self) -> anyhow::Result<String> {
let title = &self.title;
let content = &self.content;
let date = &self.date_f;
Ok(format!(
r#"<div class="header-container"><h1>{title}</h1><div class="header-date">{date}</div></div>{content}"#
))
}
pub fn link(&self, slug: &str) -> String {
format!(r#"<a href="{slug}">{}</a> [{}]"#, self.title, self.date_f)
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
}
}
pub struct PostParser {
title: Option<String>,
date: Option<Date>,
content: Vec<u8>,
handler: CustomHtmlHandler,
}
impl Default for PostParser {
fn default() -> Self {
Self {
title: None,
date: None,
content: vec![],
handler: CustomHtmlHandler::default(),
}
}
}
impl Parser<Post> for PostParser {
fn start(&mut self, e: &Element) -> anyhow::Result<()> {
match e {
Element::Keyword(Keyword { key, value, .. }) if key == "TITLE" => {
if self.title.is_some() {
bail!("Post has more than one title");
}
self.title = Some(value.to_string());
}
Element::Keyword(Keyword { key, value, .. }) if key == "DATE" => {
if self.date.is_some() {
bail!("Post has more than one date");
}
self.date = Some(parse_org_date(value)?);
}
_ => {
self.handler.start(&mut self.content, e)?;
}
}
Ok(())
}
fn end(&mut self, e: &Element) -> anyhow::Result<()> {
self.handler.end(&mut self.content, e)?;
Ok(())
}
fn render(self) -> anyhow::Result<Post> {
let title = self.title.context("Could not find post title")?;
let date = self.date.context("Could not find post date")?;
let date_f = date.format(format_description!("[day] [month repr:short] [year]"))?;
let content = String::from_utf8(self.content)?;
Ok(Post {
title,
date_f,
content,
})
}
}