Advanced Features Guide¶
Advanced template features for professionals. Miya Engine provides filter blocks, do statements, whitespace control, raw blocks, and autoescape with 100% Jinja2 compatibility.
Working Example: See
examples/features/advanced/for complete examples.
Table of Contents¶
- Filter Blocks
- Do Statements
- Whitespace Control
- Raw Blocks
- Autoescape Control
- Environment Configuration
- Performance & Memory Management
- Practical Examples
Filter Blocks¶
Basic Usage¶
Apply filters to entire blocks of content:
{% filter upper %}
This entire block will be uppercase
Including {{ variable }} variables
{% endfilter %}
Output:
Single Filter¶
{% filter upper %}
hello world
{% endfilter %}
→ HELLO WORLD
{% filter title %}
this is an important announcement
{% endfilter %}
→ This Is An Important Announcement
{% filter trim %}
extra whitespace removed
{% endfilter %}
→ extra whitespace removed
Chained Filters¶
Apply multiple filters in sequence:
{% filter trim|upper|replace("WORLD", "MIYA") %}
hello world
{% endfilter %}
→ HELLO MIYA
{% filter striptags|upper %}
<p>Remove <strong>HTML</strong> tags</p>
{% endfilter %}
→ REMOVE HTML TAGS
Filter Blocks with Logic¶
Filters apply to the entire rendered output:
{% filter upper %}
User list:
{% for user in users %}
- {{ user.name }}
{% endfor %}
{% endfilter %}
Output:
Nested Filter Blocks¶
Filter blocks can be nested:
{% filter upper %}
Outer block
{% filter trim %}
inner block with trim
{% endfilter %}
End outer
{% endfilter %}
Output:
Do Statements¶
Basic Usage¶
Execute expressions without output:
The do statement evaluates an expression but doesn't print the result.
Examples¶
{# Execute without output #}
{% do numbers|sum %}
{# Side effects only #}
{% do data.update({"key": "value"}) %}
{# With filters #}
{% do (100 * 5)|round %}
When to Use¶
{# Trigger computation without displaying result #}
{% set calculation_result = 0 %}
{% do expensive_function(data) %}
{# Execute for side effects #}
{% do logger.log("Template rendered") %}
Note: In pure templates, do has limited use since templates shouldn't have side effects. Most useful when integrating with systems that track template execution.
Whitespace Control¶
The Problem¶
Templates can generate unwanted whitespace:
Output (with extra lines):
The Solution: Minus Sign (-)¶
Use - to strip whitespace:
| Syntax | Description |
|---|---|
{%- |
Strip whitespace before tag |
-%} |
Strip whitespace after tag |
{{- |
Strip whitespace before variable |
-}} |
Strip whitespace after variable |
Left Whitespace Control¶
Remove whitespace before tag:
Output:
Right Whitespace Control¶
Remove whitespace after tag:
Both Sides Control¶
Output:
Practical Examples¶
Clean Comma-Separated List:
Output: Items: item1, item2, item3
Compact Number List:
Output: Values: 1,2,3,4,5
Clean HTML:
<nav>
{%- for link in links %}
<a href="{{ link.url }}">{{ link.title }}</a>
{%- if not loop.last %} | {% endif -%}
{% endfor -%}
</nav>
Output:
Raw Blocks¶
Basic Usage¶
Prevent template processing for documentation or examples:
Output (literal text):
Use Cases¶
1. Documenting Template Syntax:
2. Client-Side Templates:
<script type="text/template" id="user-template">
{% raw %}
<div class="user">
<h3>{{ user.name }}</h3>
<p>{{ user.email }}</p>
</div>
{% endraw %}
</script>
The template inside {% raw %} won't be processed by Miya, allowing it to be used by client-side JavaScript.
3. Code Examples:
<h3>Template Example:</h3>
<pre><code>
{% raw %}
{% if user.active %}
Welcome, {{ user.name }}!
{% endif %}
{% endraw %}
</code></pre>
Autoescape Control¶
What is Autoescaping?¶
Autoescaping automatically escapes HTML special characters to prevent XSS attacks:
{# With autoescape ON (default) #}
{{ "<script>alert('XSS')</script>" }}
→ <script>alert('XSS')</script>
{# With autoescape OFF #}
{{ "<script>alert('XSS')</script>" }}
→ <script>alert('XSS')</script> {# DANGEROUS! #}
Autoescape Blocks¶
Control escaping for specific regions:
{# Turn OFF autoescape #}
{% autoescape false %}
<p>{{ html_content }}</p>
{% endautoescape %}
{# Turn ON autoescape (explicit) #}
{% autoescape true %}
<p>{{ user_input }}</p>
{% endautoescape %}
Safe Filter¶
Mark specific strings as safe:
{# Mark as safe - won't be escaped #}
{{ trusted_html|safe }}
{# Force escaping #}
{{ html_string|escape }}
Practical Examples¶
Rendering Trusted HTML:
{# Article body is pre-sanitized HTML #}
{% autoescape false %}
<div class="article-body">
{{ article.body }}
</div>
{% endautoescape %}
{# Or use safe filter #}
<div class="article-body">
{{ article.body|safe }}
</div>
Protecting User Input:
{# Always escape user-provided content #}
{% autoescape true %}
<div class="comment">
<strong>{{ comment.author }}</strong>
<p>{{ comment.text }}</p>
</div>
{% endautoescape %}
{# Default behavior is autoescape ON #}
<div class="comment">
{{ user_comment }} {# Automatically escaped #}
</div>
Mixed Content:
{# Escape user content, allow trusted HTML #}
<div class="post">
<h2>{{ post.title }}</h2> {# Escaped #}
{% autoescape false %}
{{ post.body|safe }} {# Trusted HTML #}
{% endautoescape %}
<div class="comments">
{% for comment in comments %}
<p>{{ comment.text }}</p> {# Escaped again #}
{% endfor %}
</div>
</div>
Security Best Practices¶
{# SAFE - user input is escaped #}
<p>{{ user.name }}</p>
<p>{{ user.comment }}</p>
{# SAFE - trusted content explicitly marked #}
<div>{{ article.html|safe }}</div>
{# DANGEROUS - disabling autoescape for user input #}
{% autoescape false %}
{{ user_input }} {# XSS VULNERABILITY! #}
{% endautoescape %}
{# NEVER DO THIS #}
{{ user_comment|safe }} {# XSS VULNERABILITY! #}
Rule: Only use |safe or {% autoescape false %} for content you completely control and trust.
Environment Configuration¶
Available Options¶
Configure template behavior at environment creation:
env := miya.NewEnvironment(
miya.WithAutoEscape(true), // Auto-escape HTML (default: true)
miya.WithStrictUndefined(true), // Error on undefined vars (default: false)
miya.WithTrimBlocks(true), // Remove first newline after block (default: false)
miya.WithLstripBlocks(true), // Strip leading spaces before blocks (default: false)
)
AutoEscape¶
// Enable (default)
miya.WithAutoEscape(true) // {{ "<script>" }} → <script>
// Disable (be careful!)
miya.WithAutoEscape(false) // {{ "<script>" }} → <script>
StrictUndefined¶
// Lenient (default) - undefined variables render as empty
miya.WithStrictUndefined(false)
// {{ undefined_var }} → ""
// Strict - undefined variables cause errors
miya.WithStrictUndefined(true)
// {{ undefined_var }} → ERROR: undefined variable
TrimBlocks¶
// Enable - remove first newline after block tags
miya.WithTrimBlocks(true)
// Template:
// {% if true %}
// text
// {% endif %}
//
// Output: "text" (no leading newline)
LstripBlocks¶
// Enable - remove leading whitespace before block tags
miya.WithLstripBlocks(true)
// Template:
// {% if true %}
// text
// {% endif %}
//
// Output: "text" (no leading spaces)
Combining Options¶
// Production configuration
env := miya.NewEnvironment(
miya.WithAutoEscape(true), // Security
miya.WithStrictUndefined(true), // Catch errors early
miya.WithTrimBlocks(true), // Clean output
miya.WithLstripBlocks(true), // Clean output
)
// Development configuration
env := miya.NewEnvironment(
miya.WithAutoEscape(false), // Easier debugging
miya.WithStrictUndefined(false), // Lenient for incomplete data
)
Performance & Memory Management¶
Miya Engine includes several optimizations for high-performance template rendering.
AST Node Pooling¶
The parser uses sync.Pool to reuse frequently allocated AST nodes, reducing garbage collection pressure during template parsing. This is automatic and requires no configuration.
Pooled node types:
- LiteralNode - String, number, and boolean literals
- IdentifierNode - Variable references
- BinaryOpNode - Binary operators (+, -, ==, and, or, etc.)
- FilterNode - Filter applications
- UnaryOpNode - Unary operators (not, -)
- AttributeNode - Attribute access (obj.attr)
- GetItemNode - Index access (obj[key])
- CallNode - Function calls
Template.Release()¶
For high-throughput applications that create many short-lived templates, you can explicitly release pooled AST nodes back to their pools:
// Create and use a template
tmpl, err := env.FromString("Hello {{ name }}!")
if err != nil {
log.Fatal(err)
}
output, err := tmpl.Render(ctx)
if err != nil {
log.Fatal(err)
}
// Optional: release pooled nodes for reuse
tmpl.Release()
When to use Release():
- Processing many unique templates in a loop
- One-time template rendering where the template won't be reused
- Memory-constrained environments
- High-throughput services generating templates dynamically
When NOT to use Release():
- Templates cached in the environment (they're reused)
- Long-lived templates rendered multiple times
- When memory pressure isn't a concern
Evaluator Pooling¶
The environment automatically pools evaluator instances for reuse across render calls. This is handled internally and requires no user action.
// Evaluators are automatically pooled and reused
for i := 0; i < 1000; i++ {
output, _ := tmpl.Render(ctx) // Reuses pooled evaluators
}
Template Caching¶
Templates are cached by name (for file-based templates) or by content hash (for string templates):
// First call: parses and caches the template
tmpl1, _ := env.FromString("Hello {{ name }}!")
// Second call: returns cached template (no parsing)
tmpl2, _ := env.FromString("Hello {{ name }}!")
// tmpl1 and tmpl2 are the same cached instance
Cache Management¶
// Clear all cached templates
env.ClearCache()
// Invalidate a specific template (removes from both regular and inheritance caches)
env.InvalidateTemplate("page.html")
// Check cache size
size := env.GetCacheSize()
Best Practices for Performance¶
// 1. Reuse environments - don't create new ones per request
var env = miya.NewEnvironment(
miya.WithLoader(loader),
miya.WithAutoEscape(true),
)
// 2. Let templates cache - call GetTemplate/FromString once
tmpl, _ := env.GetTemplate("page.html")
for _, data := range items {
ctx := miya.NewContext()
ctx.Set("item", data)
output, _ := tmpl.Render(ctx)
}
// 3. Use Release() only for one-off templates
func processUserTemplate(userTemplate string, data interface{}) string {
tmpl, _ := env.FromString(userTemplate)
defer tmpl.Release() // Release since this is a one-time template
ctx := miya.NewContext()
ctx.Set("data", data)
output, _ := tmpl.Render(ctx)
return output
}
Practical Examples¶
Example 1: Clean HTML Output¶
<nav>
<ul>
{%- for item in nav_items %}
<li><a href="{{ item.url }}">{{ item.title }}</a></li>
{%- endfor %}
</ul>
</nav>
Output (no extra whitespace):
Example 2: Text Transformation Blocks¶
{# Convert entire section to uppercase #}
{% filter upper %}
<h1>Important Announcement</h1>
<p>This message will be in uppercase.</p>
<p>Variable {{ name }} will also be uppercase.</p>
{% endfilter %}
Example 3: Safe Content Rendering¶
<article>
{# Title is escaped #}
<h1>{{ article.title }}</h1>
{# Body is trusted HTML #}
<div class="content">
{{ article.body|safe }}
</div>
{# User comments are escaped #}
<div class="comments">
<h2>Comments</h2>
{% for comment in comments %}
<div class="comment">
<strong>{{ comment.author }}</strong>
<p>{{ comment.text }}</p>
</div>
{% endfor %}
</div>
</article>
Example 4: Template Documentation¶
<h2>Template Syntax Guide</h2>
<h3>Variables:</h3>
<pre>{% raw %}{{ variable }}{% endraw %}</pre>
<h3>Loops:</h3>
<pre>
{% raw %}
{% for item in items %}
{{ item }}
{% endfor %}
{% endraw %}
</pre>
<h3>Conditionals:</h3>
<pre>
{% raw %}
{% if condition %}
content
{% endif %}
{% endraw %}
</pre>
Example 5: Combining Features¶
{# Filter block + whitespace control #}
<div class="notice">
{%- filter upper|trim -%}
This is an important notice
{%- endfilter -%}
</div>
{# Autoescape + filter block #}
{% autoescape false %}
{% filter safe %}
{{ rich_text_content }}
{% endfilter %}
{% endautoescape %}
{# Whitespace control + conditionals #}
<ul>
{%- for item in items %}
{%- if item.visible %}
<li>{{ item.name }}</li>
{%- endif %}
{%- endfor %}
</ul>
Complete Reference¶
Feature Summary¶
| Feature | Syntax | Status | Purpose |
|---|---|---|---|
| Filter Blocks | {% filter name %}...{% endfilter %} |
Full | Apply filters to blocks |
| Chained Filters | {% filter f1\|f2 %}...{% endfilter %} |
Full | Multiple filters |
| Do Statements | {% do expression %} |
Full | Execute without output |
| Whitespace Control | {%-, -%}, {{-, -}} |
Full | Control whitespace |
| Raw Blocks | {% raw %}...{% endraw %} |
Full | Prevent processing |
| Autoescape | {% autoescape bool %}...{% endautoescape %} |
Full | Control HTML escaping |
| Safe Filter | {{ var\|safe }} |
Full | Mark as safe HTML |
| Escape Filter | {{ var\|escape }} |
Full | Force escaping |
Environment Options¶
| Option | Type | Default | Description |
|---|---|---|---|
AutoEscape |
bool | true |
Automatic HTML escaping |
StrictUndefined |
bool | false |
Error on undefined variables |
TrimBlocks |
bool | false |
Remove first newline after blocks |
LstripBlocks |
bool | false |
Strip leading whitespace |
Memory Management Methods¶
| Method | Description |
|---|---|
Template.Release() |
Return pooled AST nodes for reuse (optional) |
Environment.ClearCache() |
Clear all cached templates |
Environment.InvalidateTemplate(name) |
Remove specific template from cache |
Environment.GetCacheSize() |
Get number of cached templates |
Best Practices¶
1. Use Whitespace Control Sparingly¶
{# Good - strategic use #}
Items: {%- for item in items %}{{ item }}{{ ", " if not loop.last }}{% endfor %}
{# Avoid - excessive #}
{%- for item in items -%}
{{- item -}}
{%- endfor -%}
2. Always Escape User Input¶
3. Use Raw for Documentation Only¶
{# Good - documenting syntax #}
<pre>{% raw %}{{ variable }}{% endraw %}</pre>
{# Avoid - for actual content #}
{% raw %}{{ actual_variable_to_render }}{% endraw %}
4. Filter Blocks for Transformation¶
{# Good - transform entire section #}
{% filter upper %}
{% include "announcement.html" %}
{% endfilter %}
{# Avoid - single line (use inline filter) #}
{% filter upper %}{{ text }}{% endfilter %}
{# Better: {{ text|upper }} #}
See Also¶
- Working Example - Complete advanced features demo
- Filters Guide - Available filters for filter blocks
- Control Structures - Template control flow
- Security - HTML escaping and security
Summary¶
All Advanced Features: 100% Jinja2 Compatible
Fully Supported:
- Filter Blocks - Apply filters to entire content blocks
- Chained Filters - Multiple filters on blocks
- Do Statements - Execute without output
- Whitespace Control - Fine-grained whitespace management with -
- Raw Blocks - Prevent template processing
- Autoescape - Control HTML escaping for security
- Environment Configuration - AutoEscape, StrictUndefined, TrimBlocks, LstripBlocks
- Performance Optimizations - AST node pooling, evaluator pooling, template caching
Key Benefits: - Clean, professional output - Security through autoescaping - Documentation-friendly with raw blocks - Powerful block transformations - High performance with minimal memory overhead
All advanced features work identically to Jinja2, providing professional-grade template control.