Skip to content
Snippets Groups Projects
Select Git revision
  • 4d72355da0670d12c599e7b78f08f3a1ae80ab06
  • master default protected
2 results

.env

Blame
  • parser.rs 3.74 KiB
    use anyhow::bail;
    use anyhow::Context;
    use anyhow::Error;
    use orgize::elements::Keyword;
    use orgize::elements::Link;
    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 Default for CustomHtmlHandler {
        fn default() -> Self {
            let mut ts = ThemeSet::load_defaults();
    
            Self {
                fallback: Default::default(),
                ps: SyntaxSet::load_defaults_newlines(),
                theme: ts
                    .themes
                    .remove("base16-eighties.dark")
                    .expect("Could not load theme"),
            }
        }
    }
    
    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>"#)?;
                }
                // fallback to default handler
                _ => self.fallback.end(w, element)?,
            }
    
            Ok(())
        }
    }