JetLeaf’s powerful and lightweight HTML templating engine — built exclusively for the JetLeaf backend framework.
It uses JTL (JetLeaf Template Language), a Mustache-style syntax for writing dynamic HTML with variables, loops, conditionals, and partial includes.
JTL is designed for seamless server-side rendering in Dart using pure HTML templates with logic annotations.
JTL (JetLeaf Template Language) is a markup syntax built into JetLeaf.
It combines expressive logic (e.g., loops, conditionals, includes) with readable HTML, making it ideal for building dynamic views.
JTL templates are typically .html files processed at runtime.
They support rich rendering features without mixing Dart code into HTML.
A powerful, modular, and well-architected template engine for the JetLeaf framework. Built with separation of concerns, clean abstractions, and production-ready robustness.
The refactored JTL template engine follows a layered architecture with clear separation of concerns:
┌─────────────────────────────────────┐
│ Template Engine Factory │
│ (High-level API & Orchestration) │
└──────────────────┬──────────────────┘
│
┌──────────────┼──────────────┐
│ │ │
┌───▼────┐ ┌─────▼──────┐ ┌────▼────────┐
│Template │ │ Renderer │ │ Cache │
│Context │ │ │ │ │
└────┬────┘ └─────┬──────┘ └─────────────┘
│ │
└──────┬──────┘
│
┌───────▼────────┐
│ Code Structure │
│ & Elements │
└────────────────┘
Manages template variables, variable resolution, and expression evaluation.
- TemplateVariableResolver: Resolves variable names to values
- TemplateExpressionEvaluator: Evaluates conditional expressions
- TemplateContext: Central context providing all dynamic data
Represents the parsed structure of templates for introspection and analysis.
- CodeElement: Base abstraction for code fragments
- CodeStructure: Hierarchical representation of template structure
- Statement Types: ConditionalStatement, ForEachStatement, IncludeStatement
Processes templates with context data to produce rendered output.
- TemplateRenderer: Core rendering interface
- DefaultTemplateRenderer: Full-featured implementation
- Handles parsing, variable resolution, expression evaluation, and filtering
Manages reusable filters for value transformation.
- Built-in filters: uppercase, lowercase, capitalize, etc.
- Custom filter registration
- Filter chaining support
High-level API for creating configured engine instances.
- Singleton pattern for consistency
- Global filter management
- Template creation and rendering helpers
Implements performance optimization through caching.
- Optional caching with configurable behavior
- Cache management (clear, size tracking)
- Cache key generation
- 🧠 Logic-aware templates using
{{}}syntax - 🔁 Loops (
{{#each items}} ... {{/each}}) - ❓ Conditionals (
{{#if condition}} ... {{/if}}) - 📦 Includes (
{{> partial}}) - 🧬 Nested Properties (e.g.,
{{user.address.city}}) - ⚡ Runtime caching for speed
- 🛡️ Safe auto-escaping (XSS prevention)
| Feature | Syntax Example |
|---|---|
| Variable | {{user.name}} |
| If block | {{#if isAdmin}}Welcome Admin{{/if}} |
| Each block | {{#each users}}<li>{{this}}</li>{{/each}} |
| Include | {{> header}} |
Create resources/html/user-profile.html:
<h1>Hello, {{user.name}}</h1>
<p>Email: {{user.email}}</p>
{{#if isAdmin}}
<div class="admin-box">You have admin privileges</div>
{{/if}}
<ul>
{{#each user.tags}}
<li>{{this}}</li>
{{/each}}
</ul>
{{> footer}}import 'package:jetleaf/jtl.dart';
void main() async {
final engine = JtlTemplateEngine(baseDirectory: 'resources/html');
final output = await engine.render('user-profile', {
'user': {
'name': 'Alice',
'email': 'alice@example.com',
'tags': ['admin', 'active']
},
'isAdmin': true
});
print(output);
}<p>{{user.profile.contact.phone}}</p>Inside a {{#each}} block:
| Helper | Description |
|---|---|
{{this}} |
Current item |
{{@index}} |
Index of item |
{{@first}} |
True if first in loop |
{{@last}} |
True if last in loop |
JTL supports modular templates via {{> partial}}:
{{> header}} <!-- Loads header.html -->
{{> footer}} <!-- Loads footer.html -->Includes are resolved relative to your base directory.
By default, all variables are escaped to prevent XSS:
| Character | Escaped As |
|---|---|
& |
& |
< |
< |
> |
> |
" |
" |
' |
' |
Support for unescaped HTML (
{{{ rawHtml }}}) is planned.
-
Loads the template from
baseDirectory -
Resolves
{{> includes}} -
Evaluates:
{{#if}},{{#each}}{{@index}},{{this}}, etc.- Variable interpolation like
{{user.name}}
-
Merges final HTML output
Templates are compiled and cached at runtime.
- To disable caching:
TemplateEngine(baseDirectory: 'resources/html', enableCaching: false);- To manually clear:
engine.clearCache();project_root/
├── resources/
│ └── html/
│ ├── user-profile.html
│ ├── header.html
│ ├── footer.html
│ └── error/
│ ├── 404.html
│ ├── 500.html
│ └── home.html
MIT License © JetLeaf Framework Authors