Skip to main content

rustbasic_core/template/
mod.rs

1pub mod lexer;
2pub mod parser;
3pub mod evaluator;
4
5use lexer::Lexer;
6use parser::Parser;
7use evaluator::{Evaluator, FilterFn};
8use serde_json::Value;
9use std::collections::HashMap;
10use std::sync::Arc;
11
12pub struct TemplateEngine {
13    filters: HashMap<String, FilterFn>,
14}
15
16impl Default for TemplateEngine {
17    fn default() -> Self {
18        Self::new()
19    }
20}
21
22impl TemplateEngine {
23    pub fn new() -> Self {
24        let mut filters = HashMap::new();
25
26        // Register default filters
27        filters.insert(
28            "safe".to_string(),
29            Arc::new(|val: &Value, _args: &[Value]| val.clone()) as FilterFn,
30        );
31        filters.insert(
32            "tojson".to_string(),
33            Arc::new(|val: &Value, _args: &[Value]| {
34                // Return raw string to be rendered directly
35                let s = serde_json::to_string(val).unwrap_or_default();
36                Value::String(s)
37            }) as FilterFn,
38        );
39
40        Self { filters }
41    }
42
43    pub fn add_filter<F>(&mut self, name: &str, filter: F)
44    where
45        F: Fn(&Value, &[Value]) -> Value + Send + Sync + 'static,
46    {
47        self.filters.insert(name.to_string(), Arc::new(filter));
48    }
49
50    pub fn render(&self, template_str: &str, context: &Value) -> Result<String, String> {
51        let mut lexer = Lexer::new(template_str);
52        let tokens = lexer.tokenize()?;
53        let mut parser = Parser::new(tokens);
54        let nodes = parser.parse()?;
55        let evaluator = Evaluator::new(self.filters.clone());
56        evaluator.render_nodes(&nodes, context)
57    }
58}