mini_template/
lib.rs

1//#![deny(clippy::undocumented_unsafe_blocks)]
2
3mod error;
4pub mod macros;
5pub mod modifier;
6mod parser;
7mod renderer;
8mod template;
9pub mod value;
10mod variable_container;
11
12#[macro_use]
13extern crate pest_derive;
14#[macro_use]
15extern crate log;
16
17use modifier::Modifier;
18use parser::{parse, ParseError};
19use renderer::RenderContext;
20use std::{collections::HashMap, hash::Hash};
21use template::{Render, Template};
22use variable_container::VariableContainer;
23
24/// A Storage for Templates
25///
26/// A MiniTemplate instance is used to parse, save and render templates.
27#[derive(Default)]
28pub struct MiniTemplate<K: Eq + Hash> {
29    modifier: HashMap<&'static str, &'static Modifier>,
30    template: HashMap<K, Template>,
31}
32
33impl<K: Eq + Hash> MiniTemplate<K> {
34    /// Creates a new instance.
35    /// Use [`MiniTemplate::default`] instead.
36    #[deprecated]
37    pub fn new() -> Self {
38        MiniTemplate {
39            modifier: HashMap::new(),
40            template: HashMap::new(),
41        }
42    }
43
44    /// Adds the following modifiers:
45    ///
46    /// slice, regex, match, replace, replace_regex, upper, lower, repeat, add, sub, mul, div
47    pub fn add_default_modifiers(&mut self) {
48        use modifier::*;
49        self.add_modifier("slice", &slice_modifier);
50        #[cfg(feature = "regex")]
51        {
52            self.add_modifier("regex", &match_modifier);
53            self.add_modifier("match", &match_modifier);
54            self.add_modifier("replace_regex", &replace_regex_modifier);
55        }
56        self.add_modifier("replace", &replace_modifier);
57        self.add_modifier("upper", &upper);
58        self.add_modifier("lower", &lower);
59        self.add_modifier("repeat", &repeat);
60
61        self.add_modifier("add", &add);
62        self.add_modifier("sub", &sub);
63        self.add_modifier("mul", &mul);
64        self.add_modifier("div", &div);
65    }
66
67    /// Register a new modifier
68    ///
69    /// You can implement modifiers by hand. But that will result quite complex setup code.
70    /// Preferably you should take a look at the [`mini_template::modifier::create_modifier`] macro.
71    pub fn add_modifier(&mut self, key: &'static str, modifier: &'static Modifier) {
72        self.modifier.insert(key, modifier);
73    }
74
75    /// Register a new Template for a give key
76    pub fn add_template(&mut self, key: K, tpl: String) -> Result<Option<Template>, ParseError> {
77        let tpl = parse(tpl)?;
78        Ok(self.template.insert(key, tpl))
79    }
80
81    /// Render the template for a given key.
82    /// # Error
83    /// This function will return the following errors:
84    /// * Modifier: An unhandled error occurred inside a modifier
85    /// * UnknownTemplate: There is no template with the given key registered
86    /// * UnknownModifier: The template contains a unknown modifier
87    /// * UnknownVariable: The template contains a unknown variable
88    pub fn render<VC: VariableContainer>(&self, key: &K, data: VC) -> error::Result<String> {
89        let tpl = match self.template.get(key) {
90            Some(t) => t,
91            None => return Err(error::Error::UnknownTemplate),
92        };
93        let mut context = RenderContext::new(&self.modifier, data);
94        let mut buf = String::new();
95        tpl.render(&mut context, &mut buf)?;
96        Ok(buf)
97    }
98}