Newer
Older
use orgize::elements::Keyword;
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
use orgize::elements::Timestamp;
use orgize::{
export::{DefaultHtmlHandler, HtmlHandler},
Element, Org,
};
use std::io::Write;
use syntect::{
highlighting::{Theme, ThemeSet},
html::highlighted_html_for_string,
parsing::SyntaxSet,
};
use time::macros::format_description;
use time::Date;
pub trait Parser<T> {
fn start(&mut self, _: &Element) -> anyhow::Result<()>;
fn end(&mut self, _: &Element) -> anyhow::Result<()>;
fn render(self) -> anyhow::Result<T>;
}
pub fn parse<T, P: Parser<T>>(mut p: P, org: &str) -> anyhow::Result<T> {
for e in Org::parse(org).iter() {
match e {
orgize::Event::Start(ele) => p.start(ele)?,
orgize::Event::End(ele) => p.end(ele)?,
}
}
p.render()
}
pub struct CustomHtmlHandler {
fallback: DefaultHtmlHandler,
ps: SyntaxSet,
theme: Theme,
}
impl CustomHtmlHandler {
pub fn new() -> anyhow::Result<Self> {
let mut ps = SyntaxSet::load_defaults_newlines().into_builder();
ps.add_from_folder("assets/syntaxes", true)?;
let ps = ps.build();
theme: ts
.themes
.remove("base16-eighties.dark")
.expect("Could not load theme"),
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
}
}
impl HtmlHandler<Error> for CustomHtmlHandler {
fn start<W: Write>(&mut self, mut w: W, element: &Element) -> Result<(), Error> {
match element {
Element::SourceBlock(block) => {
let syntax = self
.ps
.find_syntax_by_token(&block.language)
.with_context(|| format!("Unknown language {}", block.language))?;
let html =
highlighted_html_for_string(&block.contents, &self.ps, syntax, &self.theme)?;
write!(w, "{html}")?;
}
Element::SpecialBlock(block) => match block.name.as_ref() {
"JUSTIFYRIGHT" => {
write!(w, r#"<div class="justify-right">"#)?;
}
_ => bail!("Unrecognized special block name {}", block.name),
},
Element::Timestamp(Timestamp::Active { start, .. }) => {
let date = Date::from_calendar_date(
start.year.into(),
start.month.try_into()?,
start.day,
)?;
date.format_into(
&mut w,
format_description!("[day] [month repr:short] [year]"),
)?;
}
Element::Link(Link { path, desc }) if desc.is_none() => {
write!(w, r#"<a href="/img/{path}"><img src="/thumb/{path}">"#)?;
}
Element::Keyword(Keyword { key, value, .. }) if key == "VIDEO" => {
write!(
w,
r#"<video controls="controls"><source src="{value}"></video>"#
)?;
}
// fallback to default handler
_ => self.fallback.start(w, element)?,
}
Ok(())
}
fn end<W: Write>(&mut self, mut w: W, element: &Element) -> Result<(), Error> {
match element {
Element::SpecialBlock(block) => match block.name.as_ref() {
"JUSTIFYRIGHT" => {
write!(w, "</div>")?;
}
_ => bail!("Unrecognized special block name {}", block.name),
},
Element::Link(Link { desc, .. }) if desc.is_none() => {
write!(w, r#"</img></a>"#)?;
}