The Engine interface allows you to implement custom template rendering engines for Ason. This enables support for template syntax beyond the default Pongo2/Jinja2.
type Engine interface {
// Render renders a template string with the given context variables
Render(template string, context map[string]interface{}) (string, error)
// RenderFile renders a template from a file path
RenderFile(filePath string, context map[string]interface{}) (string, error)
}Renders a template provided as a string.
Parameters:
template: The template content as a stringcontext: Variables available for substitution in the template
Returns:
- The rendered output string
- An error if rendering fails (syntax error, missing variable, etc.)
Contract:
- Must be thread-safe for concurrent use
- Should respect context cancellation if applicable
- Should not modify the input template or context
Renders a template stored in a file.
Parameters:
filePath: Path to the template filecontext: Variables available for substitution in the template
Returns:
- The rendered output string
- An error if the file cannot be read or rendering fails
Contract:
- Must handle file I/O errors (permission denied, not found, etc.)
- Must be thread-safe for concurrent use
- Should respect context cancellation if applicable
Your Engine implementation MUST be thread-safe. The Generator can and will use a single Engine instance across multiple concurrent goroutines without additional synchronization.
Recommendations:
- Use only thread-safe operations in your implementation
- Avoid shared mutable state
- Use
sync.Mutexorsync.RWMutexif state must be shared - Pre-compile templates during initialization when possible
While the Engine interface doesn't explicitly take a context.Context parameter, your implementation should be mindful that it may be called within a cancellation context. If your engine performs long-running operations (like processing very large templates), consider checking for cancellation.
Your Engine should return descriptive errors that include:
- What operation failed (render, compile, etc.)
- Why it failed (syntax error, missing variable, etc.)
- Original error if available for debugging
Example error patterns:
fmt.Errorf("failed to render template: %w", underlyingError)
fmt.Errorf("undefined variable: %s", variableName)
fmt.Errorf("syntax error at line %d: %s", lineNum, message)See examples/custom_engine.go for a complete working example of a custom Engine implementation.
The default engine uses Pongo2, which provides Jinja2-like template syntax:
- Variable substitution:
{{ variable_name }} - Filters:
{{ value | upper }} - Conditionals:
{% if condition %} ... {% endif %} - Loops:
{% for item in list %} ... {% endfor %}
To use the default engine:
engine := pkg.NewDefaultEngine()
gen, err := pkg.NewGenerator(engine)- Pre-compilation: If your engine supports it, compile templates during initialization rather than on each render
- Caching: Consider caching compiled templates if rendering the same template multiple times
- Memory: Be mindful of memory usage, especially for large templates
- Concurrency: Ensure your implementation scales well with concurrent usage
When testing a custom Engine:
- Verify thread-safety with concurrent renders
- Test error handling for invalid templates
- Benchmark performance on typical templates
- Verify output correctness with various input types
- Test with the Generator's concurrency helpers
Example test pattern:
func TestCustomEngine(t *testing.T) {
engine := NewCustomEngine()
gen, _ := pkg.NewGenerator(engine)
// Test successful render
err := gen.Generate(ctx, templatePath, vars, outputPath)
require.NoError(t, err)
}If you're coming from a different template engine:
- Mustache → Implement a MustacheEngine wrapping a Go Mustache library
- Handlebars → Implement a HandlebarEngine wrapping a Go Handlebars library
- HTML Templates → Implement an HTMLEngine wrapping Go's html/template
- Go Templates → Implement a GoTemplateEngine wrapping Go's text/template
- Custom Format → Implement your own parsing and rendering logic
See docs/examples/custom_engine_guide.md for detailed implementation guidelines.