use lol_html::{element, RewriteStrSettings}; use serde::Serialize; use crate::{blog::BlogPostMetadata, builder::SiteBuilder, resource::ResourceTemplateData}; #[derive(Debug)] pub enum Extra { Basic(&'static str), HtmlModification(fn(page: String, builder: &SiteBuilder) -> eyre::Result), } impl Extra { /// runs the handler for the extra pub fn handle(&self, page: String, builder: &SiteBuilder) -> eyre::Result { match self { Self::Basic(template) => { let content = builder.reg.render(template, &())?; append_to(&page, &content, "main.page") } Self::HtmlModification(f) => (f)(page, builder), } } } /// Gets the extra for the given value. pub fn get_extra(extra: &str) -> Option { match extra { "index" => Some(Extra::HtmlModification(index)), "click" => Some(Extra::Basic("extras/click")), _ => None, } } fn append_to(page: &str, content: &str, selector: &str) -> eyre::Result { Ok(lol_html::rewrite_str( page, RewriteStrSettings { element_content_handlers: vec![element!(selector, move |el| { el.append(content, lol_html::html_content::ContentType::Html); Ok(()) })], ..Default::default() }, )?) } /// Extra to add a sidebar to the index page with recent blog posts on it. fn index(page: String, builder: &SiteBuilder) -> eyre::Result { #[derive(Debug, Serialize)] struct SidebarTemplateData<'r> { // resources: Vec<&'r ResourceMetadata>, resources: Vec>, } let sidebar = builder.reg.render( "extras/index-injection", &SidebarTemplateData { resources: builder .blog_builder .loaded_metadata .iter() .take(3) .map(|(id, v)| ResourceTemplateData { resource: v, id: id.clone(), extra: (), timestamp: v.timestamp, }) .collect(), }, )?; append_to(&page, &sidebar, "#content") }