Skip to main content

dotm/
template.rs

1use anyhow::{Context, Result};
2use tera::Tera;
3use toml::map::Map;
4use toml::Value;
5
6/// Render a Tera template string with the given variables.
7pub fn render_template(template_str: &str, vars: &Map<String, Value>) -> Result<String> {
8    let mut tera = Tera::default();
9    tera.add_raw_template("__dotm_template", template_str)
10        .context("failed to parse template")?;
11
12    let context = toml_map_to_tera_context(vars);
13
14    tera.render("__dotm_template", &context)
15        .context("failed to render template")
16}
17
18fn toml_map_to_tera_context(vars: &Map<String, Value>) -> tera::Context {
19    let mut context = tera::Context::new();
20    for (key, value) in vars {
21        context.insert(key, &toml_value_to_json(value));
22    }
23    context
24}
25
26fn toml_value_to_json(value: &Value) -> serde_json::Value {
27    match value {
28        Value::String(s) => serde_json::Value::String(s.clone()),
29        Value::Integer(i) => serde_json::json!(*i),
30        Value::Float(f) => serde_json::json!(*f),
31        Value::Boolean(b) => serde_json::Value::Bool(*b),
32        Value::Datetime(dt) => serde_json::Value::String(dt.to_string()),
33        Value::Array(arr) => serde_json::Value::Array(arr.iter().map(toml_value_to_json).collect()),
34        Value::Table(table) => {
35            let map: serde_json::Map<String, serde_json::Value> =
36                table.iter().map(|(k, v)| (k.clone(), toml_value_to_json(v))).collect();
37            serde_json::Value::Object(map)
38        }
39    }
40}