Current section
Files
Jump to
Current section
Files
README.md
# Jennie 🩸
Logic-less templates inspired by Moustache.
Anthrodontics is the mobile operating system for dentists. Templates are the
best and most predictable form of automation. We need something that it is
simple for users to understand, from beginners to experts. Curly brackets sit
nicely in that spectrum - so there's currently Handlebars on the extreme end
and Moustache on the other side. Jennie is a compromise that tries to achieve
the best of both worlds
## Installation
Add `jennie` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:jennie, "~> 0.9"}
]
end
```
## Usage
```elixir
Jennie.render("Hello {{name}}!", %{"name" => "World"})
# Hello World!
```
## Syntax
Jennie speaks the familiar Moustache tags:
| Tag | Meaning |
| --- | --- |
| `{{name}}` | Variable, HTML-escaped |
| `{{{name}}}` / `{{& name}}` | Variable, raw (not escaped) |
| `{{a.b.c}}` | Dotted name lookup |
| `{{.}}` | Implicit iterator (the current context) |
| `{{#name}}…{{/name}}` | Section — rendered when truthy, iterated over lists |
| `{{^name}}…{{/name}}` | Inverted section — rendered when falsey/empty |
| `{{! comment }}` | Comment (ignored) |
| `{{> partial}}` | Partial |
On top of these, Jennie adds two conveniences.
### List formatters
A variable tag may name a formatter after a pipe. When the value is a list, the
items are rendered (each escaped individually) and joined:
```elixir
Jennie.render("{{list | and}}", %{"list" => ["mesial", "occlusal", "distal"]})
# "mesial, occlusal, and distal"
Jennie.render("{{steps | ol}}", %{"steps" => ["Etch", "Bond"]})
# "1. Etch\n2. Bond"
```
Available formatters:
| Formatter | Result |
| --- | --- |
| `ol` | Numbered lines (`1. …`, `2. …`) |
| `and` | Oxford-comma list joined with "and" |
| `or` | Oxford-comma list joined with "or" |
| `join` | Plain join with `", "` |
| `join "sep"` | Plain join with a custom double-quoted separator |
Only the list items are escaped — the separators and conjunctions are emitted
raw. Use `{{{list | and}}}` or `{{& list | and}}` to skip escaping the items
too. A non-list value renders as if no formatter were present, and formatters
are only allowed on variable tags (not on `{{#…}}` / `{{^…}}` sections).
### Collapsible lines
A line whose non-whitespace content is entirely enclosed in sections that open
and close on that same line is dropped — trailing newline and leading
indentation included — when those sections render blank, instead of leaving an
empty line behind:
```elixir
Jennie.render("{{#opt}}Step A.{{/opt}}\nStep B.", %{"opt" => false})
# "Step B."
```
Any literal (non-whitespace) text outside the sections keeps the line. This is
enabled by default; pass `collapse_empty_lines: false` to turn it off.
## Options
`Jennie.render/3` and `Jennie.compile/2` accept:
| Option | Default | Meaning |
| --- | --- | --- |
| `:escape` | HTML escaper | A `(binary -> iodata)` escaper |
| `:partials` | `%{}` | Map of partial name to template source |
| `:raise_on_missing_partial` | `false` | Raise instead of rendering `""` |
| `:engine` | `Jennie.Engine` | Output engine module |
| `:ignore_nil` | `false` | Leave tags whose keys are absent in place |
| `:collapse_empty_lines` | `true` | Drop lines whose same-line sections all render blank |
You can run `mix test` to see the full code coverage.