Jinja2C++ Documentation

repository·master·Indexed 20 days ago

https://github.com/jinja2cpp/jinja2cpp

A C++ implementation of the Jinja2 Python template engine used for dynamic HTML and source code generation. It supports a wide range of Jinja2 features including expressions, filters, testers, control statements, and template logic. The library provides tools for AST traversal via StatementVisitor, JSON serialization using Boost.JSON or RapidJSON, and generic adapter interfaces for mapping custom C++ data types to template values.

Tokens
9.2K
Snippets
27
Records
36
Agent score
69%

What's inside Jinja2C++

  1. Quickstart: Render a template with Jinja2C++

    master

    To use Jinja2C++ in your code, you follow a three-step process: declare a jinja2::Template object, load your template string or file, and then render it using RenderAsString.

    #include <jinja2cpp/template.h>
    #include <iostream>
    
    int main() {
        // 1. Declare the template object
        jinja2::Template tpl;
    
        // 2. Populate it with a template
        tpl.Load("{{ 'Hello World' }}!!!");
    
        // 3. Render the template
        std::cout << tpl.RenderAsString({}).value() << std::endl;
        return 0;
    }
  2. Use Jinja2C++ with conan.io

    master

    Jinja2C++ is available as a Conan package. You can integrate it into your project by adding jinja2cpp/1.1.0 (or the desired version) to your conanfile.txt or conanfile.py. Below is an example of using conan-cmake integration in a CMakeLists.txt file.

    cmake_minimum_required(VERSION 3.24)
    project(Jinja2CppSampleConan CXX)
    
    list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
    list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})
    
    add_definitions("-std=c++14")
    
    if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
      file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/0.18.1/conan.cmake"
                    "${CMAKE_BINARY_DIR}/conan.cmake"
                    TLS_VERIFY ON)
    endif()
    include(${CMAKE_BINARY_DIR}/conan.cmake)
    
    conan_cmake_autodetect(settings)
    conan_cmake_run(REQUIRES
                        jinja2cpp/1.1.0
                        gtest/1.14.0
                    BASIC_SETUP
                    ${CONAN_SETTINGS}
                    OPTIONS
                        jinja2cpp/*:shared=False
                        gtest/*:shared=False
                    BUILD missing)
    
    set (TARGET_NAME jinja2cpp_build_test)
    add_executable (${TARGET_NAME} main.cpp)
    target_link_libraries (${TARGET_NAME} ${CONAN_LIBS})
    set_target_properties (${TARGET_NAME} PROPERTIES
                CXX_STANDARD 14
                CXX_STANDARD_REQUIRED ON)
  3. Install Jinja2C++ via CMake

    master

    You can build and install Jinja2C++ from source using CMake. By default, the build uses internally-shipped dependencies (like Boost).

    # Clone the repository
    git clone https://github.com/flexferrum/Jinja2Cpp.git
    cd Jinja2Cpp
    
    # Create build directory
    mkdir build
    cd build
    
    # Run CMake and build
    cmake .. -DCMAKE_INSTALL_PREFIX=<path to install folder>
    cmake --build . --target all
    
    # Install library
    cmake --build . --target install
  4. Implement custom data type adapters using generic adapter interfaces

    master

    To map custom C++ data types to Jinja2 template values, you can implement interfaces that follow the patterns established by the IndexedListItemAccessorImpl, IndexedListAccessorImpl, and MapAccessorImpl templates. These adapters allow the Jinja2 engine to interact with your native C++ collections (like lists or maps) as if they were native Jinja2 types.

    Key Adapter Patterns

    1. Indexed Item Access (Single Element Access)

    For types that allow accessing an element by an index (e.g., a single object that behaves like a container), implement the logic required by IndexedListItemAccessorImpl. You must provide:

    • GetItem(idx): Returns the item at the specified index.
    • ItemsCountImpl(): Returns the total number of items.
    • GetIndexer(): Returns a pointer to the indexer (usually this).

    2. Indexed List Access (Collection Access)

    For types representing a collection of items, implement IndexedListAccessorImpl. This provides both index-based access and iteration capabilities. You must provide:

    • GetItem(idx): Returns the item at the specified index.
    • ItemsCountImpl(): Returns the total number of items.
    • CreateListAccessorEnumerator(): Returns an enumerator for iterating over the collection.

    3. Map Access (Key-Value Access)

    For types representing key-value pairs (like a dictionary or map), implement MapAccessorImpl. You must provide:

    • GetItem(name): Returns the value associated with the string key name.

    Enumerator Lifecycle

    When implementing iterators for these collections, the engine uses an Enumerator pattern. The enumerator supports:

    • MoveNext(): Advances the iterator to the next item.
    • GetCurrent(): Returns the current value in the iteration.
    • Reset(): Resets the iterator to the beginning.
    • Clone() / Move(): Allows for duplicating or transferring the state of the iterator.
  5. How TemplateImpl handles errors

    master

    Errors in jinja2cpp are encapsulated in ErrorInfoTpl<CharT>.

    When calling Load or Render, the library returns these error objects instead of throwing exceptions in most cases (using boost::optional or nonstd::expected). If a rendering error occurs, the ErrorInfoTpl contains:

    • code: An ErrorCode indicating the type of failure (e.g., TemplateNotParsed, MetadataParseError, UnexpectedException).
    • srcLoc: The location in the template (file name, line, and column) where the error occurred.
    • locationDescr: A description of the error location.
    • extraParams: Additional context or values related to the error.
  6. Configure Jinja2C++ build flags

    master

    You can customize the build process using several CMake command-line options via -D:

    • JINJA2CPP_BUILD_TESTS: (default TRUE) Determines whether to build the library's tests.
    • JINJA2CPP_STRICT_WARNINGS: (default TRUE) Enables strict compile-warnings (e.g., -Wall -Werror).
    • JINJA2CPP_MSVC_RUNTIME_TYPE: (default /MD) Sets the MSVC runtime type to link with.
    • JINJA2CPP_DEPS_MODE: Controls how dependencies are handled. Possible values:
      • internal: Uses dependencies (including boost) shipped as subprojects. No external provision required.
      • external-boost: Uses boost as an externally-provided dependency; all other dependencies are taken from subprojects.
      • external: All dependencies must be provided externally via standard CMake variables (e.g., CMAKE_PREFIX_PATH).
      • conan-build: Special mode for building via a Conan recipe.
  7. Supported Jinja2 features in Jinja2C++

    master

    Jinja2C++ provides support for a wide range of Jinja2 specification features, including:

    • Expressions: Simple, filtered, and conditional expressions.
    • Filters: sort, default, first, last, length, max, min, reverse, unique, sum, attr, map, reject, rejectattr, select, selectattr, pprint, dictsort, abs, float, int, list, round, random, trim, title, upper, wordcount, replace, truncate, groupby, urlencode, capitalize, escape, tojson, striptags, center, xmlattr.
    • Testers: eq, defined, ge, gt, iterable, le, lt, mapping, ne, number, sequence, string, undefined, in, even, odd, lower, upper.
    • Functions: range, loop.cycle.
    • Control Statements: if (with elif/else), for (with else/if parts), set (line and block), filter, do (extension), with.
    • Template Logic: include, import/from, extends/block, macro/call, recursive loops, space control, and raw/endraw blocks.
  8. Implement IRendererCallback for custom rendering logic

    master

    The IRendererCallback is an interface used by RenderContext to interact with the rendering engine. Users must implement this interface to provide functionality for string conversion, stream management, template loading, and error handling.

    Required Methods:

    • GetAsTargetString(const InternalValue& val): Converts an InternalValue into the target string format.
    • GetStreamOnString(TargetString& str): Provides an output stream for writing to a string.
    • LoadTemplate(const std::string& fileName): Loads a template from a file path. Returns a variant containing either an error or a shared pointer to a TemplateImpl (supporting both char and wchar_t).
    • LoadTemplate(const InternalValue& fileName): Overload for loading templates using an InternalValue as the filename.
    • ThrowRuntimeError(ErrorCode code, ValuesList extraParams): Handles runtime errors during template execution.
  9. Use IRendererBase to render template output

    master

    The IRendererBase interface is the primary abstraction for objects capable of generating template output. To perform rendering, call the Render method, passing an OutStream (the destination for the output) and a RenderContext (the object containing the variables and state used during evaluation).

    // Assuming instances of OutStream, RenderContext, and a concrete IRendererBase implementation
    void ExecuteRender(jinja2::IRendererBase& renderer, jinja2::OutStream& os, jinja2::RenderContext& context) {
        renderer.Render(os, context);
    }
  10. Configure the Tester filter

    master

    The Tester filter is used to validate values against specific conditions or types.

    class Tester : public FilterBase
    {
    public:
        enum Mode
        {
            RejectMode,
            RejectAttrMode,
            SelectMode,
            SelectAttrMode,
        };
        Tester(FilterParams params, Mode mode);
        InternalValue Filter(const InternalValue& baseVal, RenderContext& context) override;
        // ...
    };
  11. Include and Import templates

    master

    To reuse code across templates, use IncludeStatement or ImportStatement:

    • IncludeStatement: Renders another template within the current context. Options include ignoreMissing (to prevent errors if the file is not found) and withContext (to determine if the current scope is shared).
    • ImportStatement: Imports specific names or a whole namespace from another template. Use AddNameToImport to map specific names to aliases and SetNamespace to define the import namespace.
  12. Assign values using SetStatement variants

    master

    Jinja2cpp provides several ways to assign values to variables using the SetStatement hierarchy:

    • SetLineStatement: Assigns the result of an expression to one or more fields.
    • SetBlockStatement: Assigns the result of rendering a block of content to one or more fields.
    • SetRawBlockStatement: A specialized SetBlockStatement that renders the block without processing it (raw).
    • SetFilteredBlockStatement: Assigns the result of a block to fields after applying an ExpressionFilter.