diff --git a/app/src/confgen/template.py b/app/src/confgen/template.py new file mode 100644 index 0000000..0ad0731 --- /dev/null +++ b/app/src/confgen/template.py @@ -0,0 +1,52 @@ +"""Template engine for confgen using Jinja2.""" + +import re +from typing import Any + + +class TemplateEngine: + """Jinja2-based template engine for configuration rendering.""" + + def __init__(self): + import jinja2 + + self.env = jinja2.Environment( + block_start_string="{%", + block_end_string="%}", + variable_start_string="{{", + variable_end_string="}}", + comment_start_string="{#", + comment_end_string="#}", + trim_blocks=True, + lstrip_blocks=True, + ) + + def render(self, template_content: str, variables: dict[str, Any]) -> str: + """Render a template with the given variables.""" + template = self.env.from_string(template_content) + return template.render(**variables) + + def render_file(self, template_path: str, variables: dict[str, Any]) -> str: + """Render a template file with the given variables.""" + with open(template_path) as f: + template_content = f.read() + return self.render(template_content, variables) + + def extract_variables(self, template_content: str) -> list[str]: + """Extract variable names from a template.""" + pattern = r"\{\{([^}]+)\}\}" + matches = re.findall(pattern, template_content) + variables = [] + for match in matches: + match = match.strip() + if not match.startswith("env.") and not match.startswith("vault."): + variables.append(match.split("|")[0].strip()) + return list(set(variables)) + + def has_conditionals(self, template_content: str) -> bool: + """Check if template contains conditionals.""" + return "{% if" in template_content or "{%- if" in template_content + + def has_loops(self, template_content: str) -> bool: + """Check if template contains loops.""" + return "{% for" in template_content or "{%- for" in template_content