moonpug
Templates for MoonBit

One page, three ways to write it.

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.

$moon add moonbitstack/moonpug
Read the guide View on GitHub
Edit anything: the engine below is moonpug compiled to JavaScript.

Template

Data

Rendered


        

Preview

3languages, and yours
79filters
39tests
0files, clocks, sockets
4backends

Blocks in any language

Switch language anywhere with {% block lang=pug %}. Blocks nest; force keeps a stretch to its own language.

Escaped unless trusted

Output is escaped by default. |safe and markup values pass through; filters that build markup escape what they wrap.

Compile once

Env keeps compiled templates by name; Template::render takes any ToJson value.

Host objects

Implement Object and a value of yours has attributes, calls, loops and assignments in a template.

Your own language

Register a reader with a name and aliases; the three built in go through the same door.

Refusals with a place

Every error names the template and line, and the column when the source is malformed. Deep recursion is refused, not overflowed.

Delimiters of your own

The strings that make a tag are settings: [[ ]] beside a template that writes { already. Shorthand prefixes too.

Bounded output

Limits caps nesting, range and what one render may write, capture blocks included, so an untrusted template stays finite.

One tree, three readers

Every syntax reads into the same tree; nothing after reading knows whether a line came from braces, indentation or Markdown.

One page, three spellings, one document

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.

html

loading the engine…
renders

pug

renders

md

renders

one 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

one tree

// a Markdown template is two steps:
//   render it, then read what it wrote
{% block lang=md %}
## {{ shelf }}
{% endblock %}
// → <h2>Reading</h2>

BtIns

Filters

abs …

Tests

defined …

Globals

range …