use crate::engine::TemplateEngine;
use crate::tera_engine::TeraEngine;
use doido_core::Result;
use std::sync::{Arc, OnceLock};
static ENGINE: OnceLock<Arc<dyn TemplateEngine>> = OnceLock::new();
pub fn set_engine(engine: Arc<dyn TemplateEngine>) {
let _ = ENGINE.set(engine);
}
pub fn init(templates_dir: &str) -> Result<()> {
if ENGINE.get().is_some() {
return Ok(());
}
let engine = TeraEngine::new(templates_dir)?;
set_engine(Arc::new(engine));
Ok(())
}
pub fn try_engine() -> Option<Arc<dyn TemplateEngine>> {
ENGINE.get().cloned()
}
pub fn render(template: &str, context: &serde_json::Value) -> Result<String> {
let engine = ENGINE.get().ok_or_else(|| {
doido_core::anyhow::anyhow!(
"view engine not initialised; call doido_view::init(\"app/views\") at boot"
)
})?;
engine.render(template, context)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::engine::TemplateEngine;
struct StubEngine;
impl TemplateEngine for StubEngine {
fn render(&self, template: &str, _ctx: &serde_json::Value) -> Result<String> {
Ok(format!("stub:{template}"))
}
fn reload(&self) -> Result<()> {
Ok(())
}
}
#[test]
fn set_then_render_uses_installed_engine() {
set_engine(Arc::new(StubEngine));
assert_eq!(
render("posts/index", &serde_json::json!({})).unwrap(),
"stub:posts/index"
);
}
}