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,
}
impl Post {
pub fn html(&self) -> anyhow::Result<String> {
let title = &self.title;
let content = &self.content;
Ok(format!(
r#"<div class="header-container"><h1>{title}</h1><div class="header-date">{date}</div></div>{content}"#
))
}
pub fn link(&self) -> anyhow::Result<String> {
let link = format!(
r#"<tr><td><a href="{}">{}</a></td><td>[{}]</td></tr>"#,
self.url,
self.title,
self.date_f()?
);
Ok(link)
}
fn date_f(&self) -> anyhow::Result<String> {
let date_f = self
.date
.format(format_description!("[day] [month repr:short] [year]"))?;
Ok(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)?)
impl Ord for Post {
fn cmp(&self, other: &Self) -> Ordering {
self.date.cmp(&other.date)
}
}
impl PartialOrd for Post {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for Post {
fn eq(&self, other: &Self) -> bool {
self.date == other.date
}
}
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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 content = String::from_utf8(self.content)?;