Menu
Public repository / master
AkurAI-Framework / crates/template/src/ast.rs
Latest change d506ed551fac416b6bd5797287d71abc9af1d250 - OLI-211: ==, != and in comparisons in template {% if %} by Ólafur Búi Ólafsson
//! The template AST: what a parsed template is made of.
/// A dotted lookup path into the context, e.g. `user.name` → `["user","name"]`.
pub type Path = Vec<String>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Node {
/// Literal text, emitted verbatim.
Text(String),
/// `{{ path }}` (HTML-escaped) or `{{{ path }}}` (raw, `escape = false`).
Var { path: Path, escape: bool },
/// `{% if path %} body {% else %} else_body {% endif %}`.
If {
cond: Cond,
body: Vec<Node>,
else_body: Vec<Node>,
},
/// `{% for var in path %} body {% endfor %}` over an array.
For {
var: String,
path: Path,
body: Vec<Node>,
},
/// `{% include "name" %}` — renders another registered template inline.
Include(String),
/// `{{ t "key" }}` or `{{ t "key" name=path … }}` — i18n translation lookup.
///
/// The renderer reads `__messages.<key>` from the root context, replaces
/// `{name}` placeholders by resolving each `(name, path)` arg, then emits
/// the result (HTML-escaped when `escape = true`). If the key is absent
/// the key text itself is emitted.
Translate {
key: String,
/// Named arguments for `{placeholder}` interpolation. Each element is
/// `(placeholder_name, context_path)`.
args: Vec<(String, Path)>,
/// `true` for `{{ t … }}`, `false` for `{{{ t … }}}`.
escape: bool,
},
}
/// One side of a comparison: a context path or a literal.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Operand {
Path(Path),
Str(String),
Int(i64),
}
/// An `{% if %}` condition.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Cond {
/// `{% if path %}` — truthiness.
Truthy(Path),
/// `a == b`
Eq(Operand, Operand),
/// `a != b`
Ne(Operand, Operand),
/// `needle in haystack` — array membership or substring.
In(Operand, Operand),
}