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,
load::Loadable,
parser::{parse, CustomHtmlHandler, Parser},
util::slugify,
};
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) -> String {
format!(
r#"<a href="{}">{}</a> [{}]"#,
self.url, self.title, self.date_f
)
}
}
impl Loadable for Post {
fn load(path: &std::path::Path, slug_prefix: &str) -> anyhow::Result<Self> {
let file_name = path
.file_stem()
.context("Could not get file name")?
.to_str()
.context("Could not convert filename into string")?
.to_owned();
let url = slugify(&format!("/{slug_prefix}/{file_name}"));
parse(PostParser::new(url), &fs::read_to_string(path)?)
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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)?;