femstache 0.1.13

Embrace the feminine mustache to unlock your templating dreams! Or something, I don't know. :3
Documentation
# 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");
```