MiniJinja Documentation

repository·main·Indexed 25 days ago

https://github.com/mitsuhiko/minijinja

A 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.

Tokens
35.6K
Snippets
118
Records
240
Agent score
83%

What's inside MiniJinja

  1. Overview of MiniJinja-Embed

    main

    MiniJinja-Embed is a utility crate designed for the MiniJinja template engine. It provides two primary workflows:

    1. Iterative Development: Supports using a loader to load templates from the filesystem during development.
    2. Production Deployment: Provides utility macros to embed templates directly into your compiled binary, ensuring they are available without external files.
  2. MiniJinja Syntax Overview

    main

    MiniJinja 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.

  3. List of MiniJinja usage examples

    main

    The 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 for loops.
    • 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 Value as Serialize context.
    • none-is-undefined: Configuring None to behave like undefined.
    • 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 loader feature.
    • load-resource: Loading files dynamically from disk within templates.
    • embedding: Using minijina-embed to 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_on within 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).
  4. Use minijinja-cabi in C applications

    main

    The minijinja-cabi crate provides a C ABI wrapper for MiniJinja, allowing you to use the MiniJinja template engine within C programs. The C header file is located at include/minijinja.h.

    To use it, you typically follow these steps:

    1. Create a new environment using mj_env_new().
    2. Add templates to the environment using mj_env_add_template().
    3. Create a context object using mj_value_new_object() and populate it with data (e.g., mj_value_set_string_key()).
    4. Render the template using mj_env_render_template().
    5. Handle potential errors with mj_err_print() and free resources using mj_str_free() and mj_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;
    }
  5. Enable Unicode Identifiers and Custom Syntax

    main

    By 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 unicode feature.
    • Custom delimiters: Enable the custom_syntax feature.
  6. Implement template inheritance

    main

    MiniJinja supports full template inheritance using extends, block, and super().

    • 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.
  7. Handle Lazy Iterables in templates

    main

    In 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 |list filter.

  8. Debug template errors with built-in error rendering

    main

    MiniJinja provides built-in error rendering support to improve template debuggability. When a template fails to render, the error output includes:

    1. A trace of the failure: It shows the specific error message and the file/line number where the error occurred.
    2. 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.
    3. Referenced variables: It lists the variables that were in scope at the time of the error, helping you inspect their values.
    4. 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,
    }
    -------------------------------------------------------------------------------
  9. Implement a manual template loader from the file system

    main

    You 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 templates folder) during execution.

    $ cargo run
    header
    Hello World!
    footer
  10. Run MiniJinja fuzzers

    main

    MiniJinja provides two primary fuzzing targets: adding templates to the environment (parse + compile) and rendering templates. Use the following make commands 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