module

TemplatePreprocessor

Preprocesses Crinja templates at load time to cut per-page render cost:

  • Includes are inlined into the template source (recursively, with cycle detection): every {% include %} costs a context creation and template resolution on every render.
  • Subtrees that only reference build-constant site variables are evaluated once against the constants and replaced by fixed text ("folding"). Constants are per language (site title, nav items, ...), so folded templates are cached per {env, template, lang} plus a hash of the inlined source, so a template edit (e.g. in auto mode) re-folds instead of serving a stale cached template.

Folding is deliberately conservative: only if-tags, for-tags whose collection and body are constant, print statements and fixed text fold; expressions are limited to literals, constant lookups, member and index access, operators and a whitelist of pure filters; and any evaluation error leaves the subtree dynamic. A Template is bound to the env that parsed it, so folded templates are cached per environment as well (the env pool is bounded by cpu_count).

Constants

FOLDABLE_TAGS = Set {"if", "for", "raw"}

Tags whose rendering has no side effects on the context.

PURE_FILTERS = Set {"upper", "lower", "title", "capitalize", "trim", "length", "count", "join", "first", "last", "default", "safe", "escape", "e", "int", "float", "string", "list", "abs", "round", "reverse", "sort", "unique", "min", "max", "sum"}

Filters that are safe to evaluate at load time. Anything not listed (in particular functions like shell) keeps its subtree dynamic.

TAG_KEYWORDS = Set {"and", "or", "not", "in", "is", "if", "else", "div", "mod", "by", "loop", "defined", "none", "true", "false", "length", "count", "upper", "lower", "title", "capitalize", "trim", "first", "last", "default"}

Keywords (and words like filter names) that may legally appear in a foldable tag's arguments without naming a runtime variable

Class methods

get_template(env : Crinja, name : String, lang : String, constants : Hash(String, Crinja::Value)) : Crinja::Template

The folded template for name in lang, loading the source through the loader of env. The returned Template belongs to env: render it via render_with, not Template#render.

Source
render_with(env : Crinja, template : Crinja::Template, bindings) : String

Render a (possibly folded) template with the CURRENT fiber's environment. Template#render would use the env that parsed the template, which for pooled environments is another fiber's env.

Source