MiniJinja Documentation
repository·main·Indexed 25 days ago
https://github.com/mitsuhiko/minijinjaA powerful, minimal-dependency template engine based on Jinja2 syntax for Rust, Go, JavaScript, Python, and C environments. Features include support for custom filters, global functions, manual template loaders, and a bundled feature for embedding templates into binaries. It provides advanced capabilities such as async operation support via callbacks, dynamic context for lazy value lookup, and built-in error rendering for debugging.
What's inside MiniJinja
- MiniJinja-Contrib is a utility crate designed for use with MiniJinja. It provides specialized utilities and functionality that are too specific for the MiniJinja core, often including features that are not present in the original Jinja2 specification.
Overview of MiniJinja-Embed
mainMiniJinja-Embed is a utility crate designed for the MiniJinja template engine. It provides two primary workflows:
- Iterative Development: Supports using a loader to load templates from the filesystem during development.
- Production Deployment: Provides utility macros to embed templates directly into your compiled binary, ensuring they are available without external files.
MiniJinja Syntax Overview
mainMiniJinja templates are text files that use expressions and tags to generate content (HTML, XML, CSV, etc.).
- Expressions: Wrapped in
{{ .. }}, these are replaced with values during rendering. - Tags: Wrapped in
{% .. %}, these control the logic of the template (loops, conditionals, inheritance). - Comments: Wrapped in
{# .. #}.
By default, MiniJinja automatically removes one trailing newline from the end of the file during parsing to ensure consistent output.
- Expressions: Wrapped in
List of MiniJinja usage examples
mainThe repository contains numerous examples covering various integration and feature scenarios:
Core Features & Syntax
- hello / minimal: Basic Hello World examples.
- inheritance: Template inheritance usage.
- macros: Using macros and imports.
- line-statements: Line statements and comment syntax.
- recursive-for: Recursive
forloops. - expr: Expression evaluation support.
- debug: Using the built-in
debug()function. - error: Built-in error reporting support.
Context & Data Handling
- dynamic-context / dynamic-objects: Using dynamic objects as template context.
- merge-context: Merging context from multiple values.
- render-value: Passing
ValueasSerializecontext. - none-is-undefined: Configuring
Noneto behave likeundefined. - undefined-tracking: Tracking undefined values in templates.
- value-tracking: Tracking values referenced at runtime.
- deserialize: Deserializing directly from a value.
- load-lazy: Loading data lazily on demand.
- self-referential-context: Using helpers for self-referential contexts.
Loading & Extensions
- custom-loader: Loading templates dynamically at runtime.
- path-loader: Loading templates from disk using the
loaderfeature. - load-resource: Loading files dynamically from disk within templates.
- embedding: Using
minijina-embedto embed templates into the binary. - filters: Writing custom filters and global functions.
- call-block-function: Using the
{% call %}block with custom functions.
Advanced & Integration
- actix-web-demo: Integration with the Actix Web framework.
- function-using-async / object-using-async: Using
tokio::task::block_onwithin functions or objects. - streaming: Using one-shot iterators to stream results.
- syntax-highlighting: Implementing syntax highlighting with
syntect. - build-script: Generating Rust code via MiniJinja in build scripts.
- dsl: Using MiniJinja as a Domain Specific Language (DSL).
Use minijinja-cabi in C applications
mainThe
minijinja-cabicrate provides a C ABI wrapper for MiniJinja, allowing you to use the MiniJinja template engine within C programs. The C header file is located atinclude/minijinja.h.To use it, you typically follow these steps:
- Create a new environment using
mj_env_new(). - Add templates to the environment using
mj_env_add_template(). - Create a context object using
mj_value_new_object()and populate it with data (e.g.,mj_value_set_string_key()). - Render the template using
mj_env_render_template(). - Handle potential errors with
mj_err_print()and free resources usingmj_str_free()andmj_env_free().
#include <minijinja.h> #include <stdio.h> int main() { mj_env *env = mj_env_new(); bool ok = mj_env_add_template(env, "hello", "Hello {{ name }}!"); mj_value ctx = mj_value_new_object(); mj_value_set_string_key(&ctx, "name", mj_value_new_string("C-Lang")); char *rv = mj_env_render_template(env, "hello", ctx); if (!rv) { mj_err_print(); } else { printf("%s\n", rv); mj_str_free(rv); } mj_env_free(env); return 0; }- Create a new environment using
Run C ABI smoke tests
mainTo verify the C ABI implementation, you can run the provided smoke tests using
make.make testEnable Unicode Identifiers and Custom Syntax
mainBy default, MiniJinja does not allow Unicode identifiers or custom delimiters. To achieve parity with Jinja2, you must enable the following features:
- Unicode identifiers: Enable the
unicodefeature. - Custom delimiters: Enable the
custom_syntaxfeature.
- Unicode identifiers: Enable the
Implement template inheritance
mainMiniJinja supports full template inheritance using
extends,block, andsuper().- Use
{% extends "base.html" %}in a child template. - Define blocks with
{% block name %}...{% endblock %}. - Use
{{ super() }}within a block to include the content from the parent block.
- Use
Handle Lazy Iterables in templates
mainIn MiniJinja 2, many operations that previously returned sequences (like
|reverse) now return lazy iterables.Implications:
- You cannot index into these iterables (e.g.,
my_list|reverse[0]will fail). - They are more efficient as they don't allocate a full list immediately.
Workaround: If you need to perform indexing or other sequence-specific operations, force the iterable into a list using the
|listfilter.- You cannot index into these iterables (e.g.,
Debug template errors with built-in error rendering
mainMiniJinja provides built-in error rendering support to improve template debuggability. When a template fails to render, the error output includes:
- A trace of the failure: It shows the specific error message and the file/line number where the error occurred.
- Contextual code snippets: It displays the source code around the error location, using
>to point to the problematic line and^to highlight the specific expression. - Referenced variables: It lists the variables that were in scope at the time of the error, helping you inspect their values.
- Cause chain: If the error was caused by a nested operation (e.g., an error inside an
{% include %}), it shows the underlying cause and the specific context of that sub-template.
$ cargo run template error: could not render include: error in "include.txt" (in hello.txt:8) ---------------------------------- hello.txt ---------------------------------- 5 | {% with foo = 42 %} 6 | {{ range(10) }} 7 | {{ other_seq|join(" ") }} 8 > {% include "include.txt" %} i ^^^^^^^^^^^^^^^^^^^^^ could not render include 9 | {% endwith %} 10 | {% endwith %} 11 | {% endfor %} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Referenced variables: { foo: 42, other_seq: [ 0, 1, 2, 3, 4, ], range: minijinja::functions::builtins::range, } ------------------------------------------------------------------------------- caused by: invalid operation: tried to use + operator on unsupported types number and string (in include.txt:1) --------------------------------- include.txt --------------------------------- 1 > Hello {{ item_squared + bar }}! i ^^^^^^^^^^^^^^^^^^^^ invalid operation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Referenced variables: { bar: "test", item_squared: 4, } -------------------------------------------------------------------------------Implement a manual template loader from the file system
mainYou can implement a custom loader in MiniJinja to fetch templates at runtime from specific locations, such as a local directory. This allows you to decouple template storage from the application logic, enabling the loading of templates from the file system (e.g., a
templatesfolder) during execution.$ cargo run header Hello World! footerRun MiniJinja fuzzers
mainMiniJinja provides two primary fuzzing targets: adding templates to the environment (parse + compile) and rendering templates. Use the following
makecommands to execute them:make fuzz-add-template: Fuzzes the process of adding templates to the environment.make fuzz-render: Fuzzes the template rendering process (includes template input as part of the fuzzing).
$ make fuzz-add-template $ make fuzz-render