// SPDX-License-Identifier: AGPL-3.0-only use std::sync::LazyLock; use handlebars::*; use reqwest::StatusCode; use crate::CONFIG; static INTERNAL_THEMES: &[(&str, &str)] = &[("plain", include_str!("hbs/plain.hbs"))]; static HANDLEBARS: LazyLock = LazyLock::new(|| { let mut hb = Handlebars::new(); handlebars_helper!(url_encode: |s: String| urlencoding::encode(&s)); hb.register_helper("url-encode", Box::new(url_encode)); for (key, fulltext) in INTERNAL_THEMES { log::info!("Registering internal handlebars theme `{key}`"); hb.register_template_string(key, fulltext).unwrap(); } hb.set_dev_mode(CONFIG.theme_dev); if let Some(themes_dir) = CONFIG.theme_dir.as_ref() { log::info!("Registering handlebars theme dir `{themes_dir}` with extension `{}`.", CONFIG.theme_ext_hbs); hb.register_templates_directory(&CONFIG.theme_ext_hbs, themes_dir.as_ref()).unwrap(); } hb }); pub fn render_theme(name: &str, ctx: &crate::ctx::Ctx) -> Option> { let templ = HANDLEBARS.get_template(name)?; let ctx = Context::wraps(ctx).unwrap(); let render = templ.renders(&HANDLEBARS, &ctx, &mut RenderContext::new(Some(&name.into()))).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR); Some(render) } pub fn touch() { LazyLock::force(&HANDLEBARS); }