// SPDX-FileCopyrightText: 2024 Aravinth Manivannan // // SPDX-License-Identifier: AGPL-3.0-or-later use lazy_static::lazy_static; use rust_embed::RustEmbed; use serde::*; use tera::*; #[allow(unused_imports)] #[cfg(test)] pub use tests::*; pub struct TemplateFile { pub name: &'static str, pub path: &'static str, } impl TemplateFile { pub const fn new(name: &'static str, path: &'static str) -> Self { Self { name, path } } pub fn register(&self, t: &mut Tera) -> std::result::Result<(), tera::Error> { t.add_raw_template(self.name, &Templates::get_template(self).expect(self.name)) } #[cfg(test)] #[allow(dead_code)] pub fn register_from_file(&self, t: &mut Tera) -> std::result::Result<(), tera::Error> { use std::path::Path; t.add_template_file(Path::new("templates/").join(self.path), Some(self.name)) } } pub const PAYLOAD_KEY: &str = "payload"; pub const NAV_SEGMENT: TemplateFile = TemplateFile::new("nav_segment.html", "nav_segment.html"); pub const TAILWIND_CONFIG: TemplateFile = TemplateFile::new("tailwind_config.html", "tailwind_config.html"); lazy_static! { pub static ref TEMPLATES: Tera = { let mut tera = Tera::default(); for t in [NAV_SEGMENT, TAILWIND_CONFIG].iter() { t.register(&mut tera).unwrap(); } tera.autoescape_on(vec![".html", ".sql"]); crate::identity::register_templates(&mut tera); crate::inventory::register_templates(&mut tera); crate::billing::register_templates(&mut tera); crate::ordering::register_templates(&mut tera); tera }; } #[derive(RustEmbed)] #[folder = "templates/"] pub struct Templates; impl Templates { pub fn get_template(t: &TemplateFile) -> Option { match Self::get(t.path) { Some(file) => Some(String::from_utf8_lossy(&file.data).into_owned()), None => None, } } } pub fn context() -> Context { let ctx = Context::new(); // let footer = Footer::new(s); // ctx.insert("footer", &footer); // ctx.insert("page", &PAGES); // ctx.insert("assets", &*ASSETS); ctx } //pub fn auth_ctx(username: Option<&str>, s: &Settings) -> Context { // use routes::GistProfilePathComponent; // let mut profile_link = None; // if let Some(name) = username { // profile_link = Some( // PAGES // .gist // .get_profile_route(GistProfilePathComponent { username: name }), // ); // } // let mut ctx = Context::new(); // let footer = Footer::new(s); // ctx.insert("footer", &footer); // ctx.insert("page", &PAGES); // ctx.insert("assets", &*ASSETS); // ctx.insert("loggedin_user", &profile_link); // ctx //} #[derive(Serialize)] pub struct Footer<'a> { // version: &'a str, admin_email: &'a str, source_code: &'a str, // git_hash: &'a str, // settings: &'a Settings, // demo_user: &'a str, // demo_password: &'a str, } impl<'a> Footer<'a> { pub fn new(admin_email: &'a str, source_code: &'a str) -> Self { Self { // version: VERSION, source_code, admin_email, // git_hash: &GIT_COMMIT_HASH[..8], // demo_user: crate::demo::DEMO_USER, // demo_password: crate::demo::DEMO_PASSWORD, // settings, } } } #[cfg(test)] pub mod tests { use super::*; use derive_builder::*; use derive_more::*; use tracing::info; use std::fs; use std::path::Path; #[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Builder)] pub struct TestWriter { file: String, contents: String, } impl TestWriter { pub fn write(&self) { let p = Path::new(&self.file); if p.exists() { info!("{:?} exists; removing", p.canonicalize().unwrap()); fs::remove_file(&self.file).unwrap(); } let _ = fs::write(&self.file, self.contents.as_bytes()); info!("contents written to file: {:?}", p.canonicalize().unwrap()); } } }