forge_tree/generator/
template_engine.rs

1use crate::{Result, ForgeTreeError};
2use handlebars::Handlebars;
3use serde_json::Value;
4use std::collections::HashMap;
5
6pub struct TemplateEngine {
7    handlebars: Handlebars<'static>,
8}
9
10impl TemplateEngine {
11    pub fn new() -> Self {
12        let mut handlebars = Handlebars::new();
13        
14        // Register built-in helpers
15        handlebars.register_helper("uppercase", Box::new(uppercase_helper));
16        handlebars.register_helper("lowercase", Box::new(lowercase_helper));
17        handlebars.register_helper("snake_case", Box::new(snake_case_helper));
18        handlebars.register_helper("pascal_case", Box::new(pascal_case_helper));
19
20        Self { handlebars }
21    }
22
23    pub fn render_template(&self, template: &str, variables: &HashMap<String, String>) -> Result<String> {
24        let json_vars: Value = serde_json::to_value(variables)
25            .map_err(|e| ForgeTreeError::Parse(format!("Failed to serialize variables: {}", e)))?;
26        
27        // Remove the explicit map_err - the #[from] conversion handles it automatically
28        self.handlebars
29            .render_template(template, &json_vars)
30            .map_err(ForgeTreeError::TemplateRender)
31    }
32
33    pub fn register_template(&mut self, name: &str, template: &str) -> Result<()> {
34        // This now uses the TemplateParse variant for registration errors
35        self.handlebars
36            .register_template_string(name, template)
37            .map_err(ForgeTreeError::TemplateParse)
38    }
39}
40
41// Helper functions remain the same...
42fn uppercase_helper(
43    h: &handlebars::Helper,
44    _: &Handlebars,
45    _: &handlebars::Context,
46    _: &mut handlebars::RenderContext,
47    out: &mut dyn handlebars::Output,
48) -> handlebars::HelperResult {
49    let param = h.param(0)
50        .and_then(|v| v.value().as_str())
51        .unwrap_or("");
52    out.write(&param.to_uppercase())?;
53    Ok(())
54}
55
56fn lowercase_helper(
57    h: &handlebars::Helper,
58    _: &Handlebars,
59    _: &handlebars::Context,
60    _: &mut handlebars::RenderContext,
61    out: &mut dyn handlebars::Output,
62) -> handlebars::HelperResult {
63    let param = h.param(0)
64        .and_then(|v| v.value().as_str())
65        .unwrap_or("");
66    out.write(&param.to_lowercase())?;
67    Ok(())
68}
69
70fn snake_case_helper(
71    h: &handlebars::Helper,
72    _: &Handlebars,
73    _: &handlebars::Context,
74    _: &mut handlebars::RenderContext,
75    out: &mut dyn handlebars::Output,
76) -> handlebars::HelperResult {
77    let param = h.param(0)
78        .and_then(|v| v.value().as_str())
79        .unwrap_or("");
80    
81    let snake_case = param
82        .chars()
83        .map(|c| if c.is_uppercase() { format!("_{}", c.to_lowercase()) } else { c.to_string() })
84        .collect::<String>()
85        .trim_start_matches('_')
86        .to_string();
87    
88    out.write(&snake_case)?;
89    Ok(())
90}
91
92fn pascal_case_helper(
93    h: &handlebars::Helper,
94    _: &Handlebars,
95    _: &handlebars::Context,
96    _: &mut handlebars::RenderContext,
97    out: &mut dyn handlebars::Output,
98) -> handlebars::HelperResult {
99    let param = h.param(0)
100        .and_then(|v| v.value().as_str())
101        .unwrap_or("");
102    
103    let pascal_case = param
104        .split(['_', '-', ' '])
105        .map(|word| {
106            let mut chars = word.chars();
107            match chars.next() {
108                None => String::new(),
109                Some(first) => first.to_uppercase().collect::<String>() + &chars.collect::<String>(),
110            }
111        })
112        .collect::<String>();
113    
114    out.write(&pascal_case)?;
115    Ok(())
116}
117
118impl Default for TemplateEngine {
119    fn default() -> Self {
120        Self::new()
121    }
122}