use derive_more::Constructor; use serde::Serialize; use serde_json::value::Value; use std::{collections::HashMap, fmt::Debug}; use tera::{Context, Tera}; #[derive(Constructor, Debug, Serialize)] pub struct BlogPost { pub title: String, pub human_date: String, pub sort_date: i64, // Sort date = unix timestamp pub last_updated: i64, pub content: String, pub output_file_name: String, } pub fn generate(blog_posts: Vec, template_dir: &String) -> String { let mut tera = Tera::new(&format!("{}/*", template_dir)).unwrap(); tera.autoescape_on(vec![]); tera.register_filter("truncate", truncate); tera.register_filter("get_unformatted_content", get_unformatted_text); tera.register_filter("remove_headers", remove_headers); let mut context = Context::new(); context.insert("blog_posts", &blog_posts); tera.render("index.html", &context).unwrap() } fn get_unformatted_text(html: &Value, _: &HashMap) -> Result { let frag = scraper::Html::parse_fragment(&html.as_str().unwrap()); let mut unformatted_text = String::new(); for node in frag.tree { if let scraper::node::Node::Text(text) = node { unformatted_text.push_str(&text); } } Ok(Value::String(unformatted_text)) } fn remove_headers(html: &Value, _: &HashMap ) -> Result { let frag = scraper::Html::parse_fragment(html.as_str().unwrap()); let mut mut_frag = frag.clone(); let headers = vec!["h1","h2","h3","h4","h5","h6"]; for node in frag.tree.nodes() { if let scraper::Node::Element(element) = node.value() { if headers.contains(&element.name.local.to_string().as_str()) { mut_frag.tree.get_mut(node.id()).unwrap().detach(); } } } Ok(Value::String(mut_frag.html())) } fn truncate(value: &Value, args: &HashMap) -> Result { let mut value = value.as_str().unwrap().to_string(); let new_len: usize = args.get("len").unwrap().as_str().unwrap().parse().unwrap(); value.truncate(new_len); Ok(Value::String(value.to_string())) } #[cfg(test)] mod tests { use crate::index::*; #[test] fn truncate_shortens() { let mut args: HashMap = HashMap::new(); args.insert("len".to_string(), Value::String("4".to_string())); let truncated_string = truncate(&Value::String("Meow Nya".to_string()), &args).unwrap(); assert_eq!(truncated_string.as_str().unwrap(), "Meow"); } }