1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//! <div align=center>
//!   <img src="https://github.com/mitsuhiko/minijinja/raw/main/artwork/logo.png" alt="" width=320>
//!   <p><strong>MiniJinja: a powerful template engine for Rust with minimal dependencies</strong></p>
//! </div>
//!
//! MiniJinja is a simple [Jinja2](https://jinja.palletsprojects.com/) inspired
//! template engine based on [serde](https://serde.rs/). It's light in features
//! and on dependencies but implements a pretty sizable feature set from Jinja2.
//! It attempts to stay largely compatible in Syntax and behavior:
//!
//! ```jinja
//! {% for user in users %}
//!   <li>{{ user.name }}</li>
//! {% endfor %}
//! ```
//!
//! # Why MiniJinja
//!
//! Rust already has quite a selection of template engines and there are in fact
//! already a handful of engines which are inspired by Jinja2 including
//! [Tera](https://crates.io/crates/tera) and
//! [Askama](https://crates.io/crates/askama) but they are very heavy in terms of
//! dependencies and usage. MiniJinja by its name does not try to become a
//! replacement for these, but it wants to be a good default choice if you need a
//! little bit of templating with minimal dependencies.
//!
//! MiniJinja tries to juggle these three goals:
//!
//! 1. aim for a high level of compatibility with Jinja2 templates
//! 2. provide template rendering and expression evaluation functionality
//! 3. achieve above functionality with the lest amount of dependencies possible
//!
//! # Template Usage
//!
//! To use MiniJinja one needs to create an [`Environment`] and populate it with templates.
//! Afterwards templates can be loaded and rendered.  To pass data one can pass any serde
//! serializable value:
//!
//! ```
//! use minijinja::Environment;
//! use minijinja::value::Single;
//!
//! let mut env = Environment::new();
//! env.add_template("hello", "Hello {{ name }}!").unwrap();
//! let tmpl = env.get_template("hello").unwrap();
//! println!("{}", tmpl.render(Single("name", "John")).unwrap());
//! ```
//!
//! ```plain
//! Hello John!
//! ```
//!
//! # Expression Usage
//!
//! MiniJinja — like Jinja2 — allows to be used as expression language.  This can be
//! useful to express logic in configuration files or similar things.  For this
//! purpose the [`Environment::compile_expression`] method can be used.  It returns
//! an expression object that can then be evaluated, returning the result:
//!
//! ```
//! use minijinja::{Environment, value::Single};
//!
//! let env = Environment::new();
//! let expr = env.compile_expression("number < 42").unwrap();
//! let result = expr.eval(Single("number", 23)).unwrap();
//! assert_eq!(result.is_true(), true);
//! ```
//!
//! # Learn more
//!
//! - [`syntax`]: documentation of the template engine syntax.
//! - [`filters`]: for how to write custom filters and list of built-in filters.
//! - [`tests`]: for how to write custom test functions and list of built-in tests.
//! - [`value`]: for information about the runtime value object.
//! - [`Environment`]: the main API entry point.
//! - [`Template`]: the template object API.
//!
//! # Optional Features
//!
//! There are some additional features that can be enabled:
//!
//! - `source`: enables the [`Source`] type which helps with dynamic loading of templates.
//! - `memchr`: enables the `memchr` dependency which provides performance improvements
//!   for the parser.
//! - `v_htmlescape`: enables the `v_htmlescape` dependency which implements a faster HTML
//!   escaping algorithm.
//! - `unstable_machinery`: provides access to the internal machinery of the engine.  This
//!   is a forever unstable API which mainly exists to aid debugging complex issues.
//!
//! Additionally to cut down on size of the engine some default
//! functionality can be removed:
//!
//! - `builtin_filters`: if this feature is removed the default filters are
//!   not implemented.
//! - `builtin_tests`: if this feature is removed the default tests are
//!   not implemented.
//! - `sync`: this feature makes MiniJinja's type `Send` and `Sync`.  If this feature
//!   is disabled sending types across threads is often not possible.  Thread bounds
//!   of things like callbacks however are not changing which means code that uses
//!   MiniJinja still needs to be threadsafe.
#![allow(clippy::cognitive_complexity)]
#![cfg_attr(docsrs, feature(doc_cfg))]
mod key;

mod ast;
mod compiler;
mod environment;
mod error;
mod instructions;
mod lexer;
mod parser;
mod tokens;
mod utils;
mod vm;

pub mod filters;
pub mod syntax;
pub mod tests;
pub mod value;

#[cfg(feature = "source")]
mod source;

pub use self::environment::{Environment, Expression, Template};
pub use self::error::{Error, ErrorKind};
pub use self::utils::{AutoEscape, HtmlEscape};

#[cfg(feature = "source")]
pub use self::source::Source;

/// This module gives access to the low level machinery.
///
/// This module is only provided by the `unstable_machinery` feature and does not
/// have a stable interface.  It mostly exists for internal testing purposes and
/// for debugging.
#[cfg(feature = "unstable_machinery")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable_machinery")))]
pub mod machinery {
    /// The AST nodes.
    pub mod ast {
        pub use crate::ast::*;
    }
    pub use crate::compiler::Compiler;
    pub use crate::instructions::{Instruction, Instructions};
    pub use crate::lexer::tokenize;
    pub use crate::parser::parse;
    pub use crate::tokens::{Span, Token};
    pub use crate::vm::{simple_eval, Vm};
}