Skip to content

Commit 389b033

Browse files
committed
refactor: enhance template engine flexibility and remove faulty validation
Remove overly strict placeholder validation that incorrectly flagged legitimate use cases where templates need to output Tera-like delimiters in their final rendered content. Changes: - Remove UnresolvedPlaceholders error variant - Remove faulty validation check for remaining {{ }} delimiters - Add test documenting support for extra context variables - Add tests showing templates can output all Tera delimiter types - Simplify render_template method by removing validation step This supports use cases like generating Ansible playbooks, configuration files, or documentation that legitimately contains template syntax as literal text in the final output. All tests pass (106 total), preserving existing functionality while enabling more flexible template usage patterns.
1 parent ccc9f7f commit 389b033

File tree

1 file changed

+71
-10
lines changed

1 file changed

+71
-10
lines changed

src/template/engine.rs

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ pub enum TemplateEngineError {
2828
#[source]
2929
source: tera::Error,
3030
},
31-
32-
#[error("Template validation failed: unresolved placeholders remain in rendered content")]
33-
UnresolvedPlaceholders,
3431
}
3532

3633
/// Template processing engine for validation and rendering
@@ -101,11 +98,9 @@ impl TemplateEngine {
10198
template_name: &str,
10299
context: &T,
103100
) -> Result<String, TemplateEngineError> {
104-
// Convert context to Tera context
105101
let tera_context = tera::Context::from_serialize(context)
106102
.map_err(|source| TemplateEngineError::ContextSerialization { source })?;
107103

108-
// Render template to string
109104
let rendered_content =
110105
self.tera
111106
.render(template_name, &tera_context)
@@ -114,11 +109,6 @@ impl TemplateEngine {
114109
source,
115110
})?;
116111

117-
// Verify no placeholders remain (basic check for {{ }} patterns)
118-
if rendered_content.contains("{{") && rendered_content.contains("}}") {
119-
return Err(TemplateEngineError::UnresolvedPlaceholders);
120-
}
121-
122112
Ok(rendered_content)
123113
}
124114
}
@@ -373,4 +363,75 @@ settings:
373363
assert_eq!(rendered_content, "Hello World!");
374364
Ok(())
375365
}
366+
367+
#[test]
368+
fn it_should_allow_extra_variables_in_context() -> Result<(), TemplateEngineError> {
369+
let mut validator = TemplateEngine::new();
370+
let template_content = "Hello {{name}}!"; // Only uses 'name' variable
371+
let context = TestContext {
372+
name: "World".to_string(),
373+
value: 42, // This variable is not used in the template but should be allowed
374+
};
375+
376+
let rendered_content =
377+
validator.render("extra_vars_template", template_content, &context)?;
378+
379+
// Should render successfully and ignore the extra 'value' variable
380+
assert_eq!(rendered_content, "Hello World!");
381+
Ok(())
382+
}
383+
384+
#[test]
385+
fn it_should_allow_tera_delimiters_in_rendered_output() -> Result<(), TemplateEngineError> {
386+
let mut validator = TemplateEngine::new();
387+
388+
// Simple template that outputs content containing Tera-like delimiters
389+
// We use raw blocks to prevent Tera from parsing the output delimiters
390+
let template_content =
391+
"Hello {{name}}! Use {% raw %}{{ variable }}{% endraw %} in your config.";
392+
393+
let context = TestContext {
394+
name: "World".to_string(),
395+
value: 42,
396+
};
397+
398+
let rendered_content =
399+
validator.render("delimiter_template", template_content, &context)?;
400+
401+
// Should render successfully and contain delimiters in the final output
402+
assert_eq!(
403+
rendered_content,
404+
"Hello World! Use {{ variable }} in your config."
405+
);
406+
Ok(())
407+
}
408+
409+
#[test]
410+
fn it_should_allow_all_tera_delimiter_types_in_output() -> Result<(), TemplateEngineError> {
411+
#[derive(Serialize)]
412+
struct SimpleContext {
413+
app_name: String,
414+
}
415+
416+
let mut validator = TemplateEngine::new();
417+
418+
// Template demonstrating all Tera delimiter types can appear in final output
419+
let template_content = r"App: {{app_name}}
420+
Expression example: {% raw %}{{ expr }}{% endraw %}
421+
Statement example: {% raw %}{% if condition %}{% endraw %}
422+
Comment example: {% raw %}{# comment #}{% endraw %}";
423+
424+
let context = SimpleContext {
425+
app_name: "MyApp".to_string(),
426+
};
427+
428+
let rendered_content = validator.render("all_delimiters", template_content, &context)?;
429+
430+
// Should render successfully and preserve all delimiter types in output
431+
assert!(rendered_content.contains("App: MyApp"));
432+
assert!(rendered_content.contains("{{ expr }}"));
433+
assert!(rendered_content.contains("{% if condition %}"));
434+
assert!(rendered_content.contains("{# comment #}"));
435+
Ok(())
436+
}
376437
}

0 commit comments

Comments
 (0)