A Tera 2.0-style template engine for MoonBit — VM-architected, ported from Keats/tera.
moon_tera brings a mature, Jinja2/Tera-flavored template engine to the MoonBit ecosystem. It targets static site generation (SSG), web/server-side rendering, and config / LLM-prompt templating.
It is a from-scratch port of Tera 2.0’s architecture, adapted to MoonBit’s type
system: no serde; a native Value data model with @json interop.
✨ Features
Expressions{{ ... }} with a Pratt parser: literals, variables, member
access (a.b), arithmetic (+ - * / %), comparisons (== != < > <= >=),
logic (and / or / not), is tests, and | filters (chainable)
Control flow{% if/elif/else %}, {% for x in xs %}, {% set %} (planned)
26+ filters: upper lower trim length default first last abs reverse nth int round keys values json_encode escape_html capitalize concat unique slice replace split join sort title striptags
13 is tests: odd even defined undefined string number integer float bool array object empty iterable
Bytecode VM architecture (Parser → Compiler → Interpreter); the compile/run
path is wired up, M1.5 renders via an AST-walk interpreter
Autoescape foundation (escape_html / e); whitespace control; comments {# #}
🔨 Build & Test
moon check # type-check
moon build # build (default target: wasm-gc)
moon test # run all tests (40+)
moon test --target all # all backends (wasm-gc / js / native)
📦 Quick example
let tera = Tera::new()
tera.add_template("base", "<h1>{% block title %}Blog{% endblock %}</h1>")
tera.add_template("post", "{% extends \"base\" %}{% block title %}{{ title | upper }}{% endblock %}")
let ctx = object_value([("title", str_value("hello"))])
tera.render("post", ctx) // => "<h1>HELLO</h1>"
moon_tera
moon_terabrings a mature, Jinja2/Tera-flavored template engine to the MoonBit ecosystem. It targets static site generation (SSG), web/server-side rendering, and config / LLM-prompt templating.It is a from-scratch port of Tera 2.0’s architecture, adapted to MoonBit’s type system: no
serde; a nativeValuedata model with@jsoninterop.✨ Features
{{ ... }}with a Pratt parser: literals, variables, member access (a.b), arithmetic (+ - * / %), comparisons (== != < > <= >=), logic (and / or / not),istests, and|filters (chainable){% if/elif/else %},{% for x in xs %},{% set %}(planned){% extends "base" %}/{% block name %}— child blocks override ancestors{% include "partial" %}upper lower trim length default first last abs reverse nth int round keys values json_encode escape_html capitalize concat unique slice replace split join sort title striptagsistests:odd even defined undefined string number integer float bool array object empty iterableescape_html/e); whitespace control; comments{# #}🔨 Build & Test
📦 Quick example
🧭 Architecture
value.mbtValuedata model + truthinesslexer.mbt/token.mbt{{ }}/{% %}/{# #})expr.mbtparser.mbtvm.mbtfilters.mbt/is_tests.mbttera.mbt🆚 Differentiation vs
moonjinjaistests📄 License
MIT. Derivative port of Keats/tera (MIT); see LICENSE and NOTICE. Original copyright preserved.
🚧 Status
Built for the 2026 CCF × MoonBit open-source ecosystem contest. Roadmap: M0 scaffold ✓ · M1 render pipeline ✓ · M2 filters/tests ✓ (ongoing) · M3 inheritance/include ✓ · M4 SSG demo + polish (ongoing).