# Femstache
Femstache is a mustache-like templating library with its own extensions.
## Features
- Template inheritance
- Hindley-Milner static type system with PureScript-like extensible records
- Macros
- Custom escape modes
- Contains meows
## Syntax
Templates are composed of text interspersed with three kinds of control sequences:
- `{{ ... }}`: interpolation
- `{% ... %}`: control
- `{# ... #}`: metadata (only at the top of a document)
There are a few kinds of control structures:
- `{% if COND %} ... {% end %}`
- `{% if let PATTERN = EXPR %} ... {% end %}`
- `{% for item in LIST %} ... {% end %}`
- `{% for item in dict DICT %} ... {% end %}`
- `{% for i in range NUM ... NUM %} ... {% end %}`
There are also variable assignments, these are of the form `{% let VAR = EXPR %}`.
It is also possible to include one template directly into another using `{% include "PATH" %}`.
Template inheritance is also supported, using `{# inherit "PATH_TO_PARENT" #}` and
`{% block BLOCKNAME %}{% end %}`.
Macros are done like this:
```plain
{% macro hello(thingy) %}
hello {{thingy}}!! :3
{% end %}
{% render hello("world") %}
{% render hello("kity") %}
```
## Types
There are several available types:
- boolean values: `bool`
- integer values: `int`
- string values: `string` (these can be raw strings, which are not escaped)
- fragments: `fragment`
- options: `option(a)`
- lists: `list(a)`
- dicts: `dict(a)` (this is from strings to `a`)
- structs: `struct(field1: ty1, field2: ty2, ...)`
- functions: `fun (args...) -> ret`
These are statically inferred and checked.
## Operators
### On all values
- equals: `x == y`
- not equals: `x != y`
### On `bool`
- not: `!x`
- and: `x && y`
- or: `x || y`
### On `int`
- addition: `x + y`
- subtraction: `x - y`
- multiplication: `x * y`
- division: `x / y`
### On `string`
- concatenation: `x ++ y`
### On `dict(a)`
- key access: `d[k]`
### On `struct(...)`
- field access: `st.field`
### On `fun arg -> ret`
- function call: `f(a)`
## Built-in functions
- `raw: string -> string`: string to raw (unescaped) string
- `show_bool: bool -> string`: bool to string
- `show_int: int -> string`: int to string
## Usage
Run `cargo add femstache`.
## Examples
### Template
`index.fem.html`:
```html
{# inherit "./template.fem.html" #}
{% block "title" %}uwu{% end %}
{% block "body" %}
<p>hello :3</p>
{% for kitty in kitties %}
<section>
<p>{{kitty}} needs a new home, adopt them! =^w^=</p>
</section>
{% end %}
{% end %}
```
`template.fem.html`:
```html
<!DOCTYPE html>
<html>
<head>
<title>{% block "title" %}{% end %}</title>
</head>
<body>
{% block "body" %}{% end %}
</body>
</html>
```
### Usage in Rust
```rust
use std::{collections::BTreeMap, path::PathBuf};
use femstache::{Femstache, TemplateSource, EscapeMode, Value};
let mut files = BTreeMap::new();
files.insert(PathBuf::from("hello.fem.html"), "{% for place in places %}hello {{ place }}! :3\n{% end %}".to_owned());
let mut femstache = Femstache::new(TemplateSource::map(files), EscapeMode::Html);
let mut inputs = BTreeMap::new();
inputs.insert("places".to_owned(), Value::List(vec![
Value::string("world"),
Value::string("mom"),
Value::string("puniqt"),
]));
let output = femstache.render("hello.fem.html", inputs).unwrap();
assert_eq!(output, "hello world! :3\nhello mom! :3\nhello puniqt! :3\n");
```