tera_hot/
lib.rs

1use std::sync::{Arc, RwLock};
2
3#[derive(Clone)]
4pub struct Template {
5    template_dir: String,
6    tera: Arc<RwLock<tera::Tera>>,
7}
8
9impl Template {
10    #[must_use]
11    pub fn new(template_dir: &str) -> Self {
12        let path = format!("{template_dir}/**/*");
13        let tera = match tera::Tera::new(&path) {
14            Ok(tera) => tera,
15            Err(err) => panic!("Parsing error(s): {err}"),
16        };
17
18        Self {
19            tera: Arc::new(RwLock::new(tera)),
20            template_dir: template_dir.to_string(),
21        }
22    }
23
24    pub fn render(&self, template: &str, context: &tera::Context) -> tera::Result<String> {
25        let tera = self.tera.read().unwrap();
26
27        tera.render(template, context)
28    }
29
30    #[cfg(debug_assertions)]
31    pub fn watch(self) {
32        use notify::Watcher;
33
34        let mut watcher = notify::recommended_watcher(move |res| match res {
35            Ok(event) => {
36                log::info!("reloading templates: {event:?}");
37
38                let mut tera = self.tera.write().unwrap();
39
40                match tera.full_reload() {
41                    Ok(_) => log::info!("templates reloaded"),
42                    Err(e) => log::error!("failed to reload templates: {e}"),
43                }
44            }
45            Err(e) => log::warn!("watch error: {e:?}"),
46        })
47        .unwrap();
48
49        log::debug!("watching {} for changes", self.template_dir);
50
51        watcher
52            .watch(
53                &std::path::PathBuf::from(&self.template_dir),
54                notify::RecursiveMode::Recursive,
55            )
56            .unwrap();
57    }
58
59    pub fn register_function<F: tera::Function + 'static>(&mut self, name: &str, function: F) {
60        let mut tera = self.tera.write().unwrap();
61
62        tera.register_function(name, function);
63    }
64
65    pub fn register_filter<F: tera::Filter + 'static>(&mut self, name: &str, filter: F) {
66        let mut tera = self.tera.write().unwrap();
67
68        tera.register_filter(name, filter);
69    }
70
71    pub fn register_tester<T: tera::Test + 'static>(&mut self, name: &str, tester: T) {
72        let mut tera = self.tera.write().unwrap();
73
74        tera.register_tester(name, tester);
75    }
76
77    #[cfg(not(debug_assertions))]
78    pub fn watch(self) {}
79}