html
loading the engine…
Text with braces, indented markup, or Markdown, over one expression language. All three write HTML5: a Markdown template is rendered to Markdown and then read as Markdown. A template compiles once and renders as often as you like; it touches no file, clock or socket unless you hand it a function that does.
Switch language anywhere with {% block lang=pug %}. Blocks nest; force keeps a stretch to its own language.
Output is escaped by default. |safe and markup values pass through; filters that build markup escape what they wrap.
Env keeps compiled templates by name; Template::render takes any ToJson value.
Implement Object and a value of yours has attributes, calls, loops and assignments in a template.
Register a reader with a name and aliases; the three built in go through the same door.
Every error names the template and line, and the column when the source is malformed. Deep recursion is refused, not overflowed.
The strings that make a tag are settings: [[ ]] beside a template that writes { already. Shorthand prefixes too.
Limits caps nesting, range and what one render may write, capture blocks included, so an untrusted template stays finite.
Every syntax reads into the same tree; nothing after reading knows whether a line came from braces, indentation or Markdown.
The same shelf written three ways. The source on each pane is the template; below it is what this page's own copy of the engine renders it to — nothing here is typed in by hand.
loading the engine…
let env = @moonpug.Env::new(load=read) env.template("shelf.pug").render(shelf) env.template("shelf.md").render(shelf) // both write the same page
// a Markdown template is two steps: // render it, then read what it wrote {% block lang=md %} ## {{ shelf }} {% endblock %} // → <h2>Reading</h2>
abs …defined …range …