(** A deliberately logic-less template engine (spec section 5). A template is DATA, never a program: placeholders, sections, inverted sections and comments, and nothing else. There are no partials, no lambdas, no expression evaluation, no arithmetic, and no filesystem or process access. There is deliberately no "raw" or triple-brace form -- a template cannot opt out of its flavour's escaping. Anything a calendar needs that this cannot express (a month grid's leading blanks, week bucketing) is computed in {!View} and handed in as data. That division is the design, not a workaround. *) (** What a template can be rendered against. *) type value = | Str of string | Bool of bool | List of value list | Obj of (string * value) list type node = | Text of string | Var of string list (** dotted path, e.g. ["name"; "la"] *) | Section of string list * node list | Inverted of string list * node list (** Never raises; a malformed template is an [Error] with a human-readable reason, because the template is user input. *) val parse : string -> (node list, string) result