carta_core/template/node.rs
1//! The parsed template tree and its expression nodes.
2
3/// A parsed template: a flat sequence of nodes, with `$if$`/`$for$` holding their bodies inline.
4#[derive(Debug, Clone, PartialEq)]
5pub struct Template {
6 pub(crate) nodes: Vec<Node>,
7}
8
9/// One element of a rendered template.
10#[derive(Debug, Clone, PartialEq)]
11pub(crate) enum Node {
12 /// Verbatim text between directives.
13 Literal(String),
14 /// A variable interpolation, e.g. `$title$` or `$x.y/uppercase$`.
15 Var(Expr),
16 /// `$if(..)$ .. $elseif(..)$ .. $else$ .. $endif$`: ordered guarded branches plus an else body.
17 If {
18 branches: Vec<(Expr, Vec<Node>)>,
19 otherwise: Vec<Node>,
20 },
21 /// `$for(..)$ body $sep$ separator $endfor$`.
22 For {
23 expr: Expr,
24 /// The single bound name when the loop expression is one bare segment, for `$name$` access
25 /// inside the body (`$it$` always works regardless).
26 bind: Option<String>,
27 body: Vec<Node>,
28 sep: Vec<Node>,
29 },
30 /// `$name()$`, or mapped `$xs:name()$` / `$xs:name()[sep]$`.
31 Partial {
32 name: String,
33 map_over: Option<Expr>,
34 sep: Option<String>,
35 },
36}
37
38/// A variable reference: a dotted lookup path plus a chain of pipes applied to the result.
39#[derive(Debug, Clone, PartialEq)]
40pub(crate) struct Expr {
41 pub(crate) path: Vec<String>,
42 pub(crate) pipes: Vec<Pipe>,
43}
44
45/// A single filter applied to a value.
46#[derive(Debug, Clone, PartialEq)]
47pub(crate) enum Pipe {
48 Uppercase,
49 Lowercase,
50 Length,
51 Reverse,
52 First,
53 Last,
54 Rest,
55 AllButLast,
56 Pairs,
57 Alpha,
58 Roman,
59 Chomp,
60 Nowrap,
61 /// Pad a value into a fixed-width block, optionally framed by border strings.
62 Block {
63 align: Align,
64 width: usize,
65 left: String,
66 right: String,
67 },
68}
69
70/// Alignment for the [`Pipe::Block`] padding filters.
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72pub(crate) enum Align {
73 Left,
74 Right,
75 Center,
76}