# Cookie Cutter
## Introduction

A feature-rich template engine with context aware escaping and both run time and compile time compilation.

Designed to generate html / js / css documents based on trusted templates but using untrusted user data that are safe to be processed by a browser.

Unlike other template engines cookie cutter does not aim to be minimal or maximally performant instead opting for feature richness and developer experience.

It also does not require templates to be compiled into the application, enabling them to be loaded at run time from a filesystem for example. Compile time inclusion is however also possible and has the benefit of surfacing template errors directly at compile time as native rust compiler errors to catch mistakes as early as possible.

## Minimal "Hello World" example

hello.cctmpl
```cctmpl
template hello() {
    Hello World!
}
```

hello.rs
```rs
use std::collections::{BTreeMap, HashMap};

use cookie_cutter::{
    builtins::{StandardContextWorker, StandardContextualizer, StandardEscaper},
    Templates, Value,
};

fn main() {
    let t: Templates<_> =
        Templates::<StandardEscaper>::new::<StandardContextualizer, StandardContextWorker>(
            [(
                "hello.ccmtmpl",
                include_str!("hello.cctmpl"),
            )],
            HashMap::new(),
        )
        .expect("failed to compile templates");

    assert_eq!(
        t.render("hello", Value::Struct(BTreeMap::new()))
            .expect("failed to render hello template"),
        "Hello World!".to_string()
    );
}
```

Further examples (also showcasing usage in an http server for example) can be found in the [examples](https://github.com/Cookie04DE/cookie_cutter/tree/master/examples) directory.

The [testdata/source\_files](https://github.com/Cookie04DE/cookie_cutter/tree/master/testdata/source_files) directory might also be of interest to you if want to see what the language is capable of.

## Feature Overview
## Type system

The template definition language is statically typed. It's type system allows for text types as well as booleans, integers and floats. Struct and tuple like datatypes build on top of these primitive types and allow for complex data to be represented and used by the templates. The data type can also be omitted and in that case defaults to a specific text type (usually `text`). This is of further importance; for that see [Contextualization](#contextualization).

## Values

Values can be created programmatically (by building up a `Value` enum) or via the `value!` macro allowing for JSON-like value literals.

Cookie cutter also has support for serde to serialize Rust values directly to values for use as template arguments.

## Indentation control

The templating language is indentation aware and automatically strips the longest common whitespace prefix of each line in a template / template literal.

If required this can be manually adjusted using a so called indentation marker which sets the minimum indentation level to a user defined level.

## Template literals (comparable to partials in other template engines)

Template literals allow you to write pieces of text in a specific context (text type) using local variables and pass them to other templates as arguments for example. This can be used to define a common site template which contains all the html boilerplate as well as other common elements like footers and headers and take the actual content of the page as a parameter to be included as the body.

## Comments

Template authors can included comments both in the source files directly (outside of any templates) using familiar C-style comments or inside templates using commands.

## Commands

Static and dynamic content is differentiated by use of commands. Everything outside of commands is literal (static) and everything inside gets computed at render time.

Commands can be expressions (to included dynamic content in templates), variable assignments or just comments.

Commands are started by a variable number of open curly braces to comfortably accommodate static content which commonly requires curly braces and avoids the constant use of escape sequences. The curly count is determined at the start of the template body.

## Escape sequences

Character sequences with a special meaning can be used literally (escaped) by being prefixed with a backslash.

Newlines can be escaped similar to multi line shell commands to write static content across multiple lines without the result having multiple lines as well.

### Variables

The language supports variable which need not be declared but are statically typed (like the rest of the langauge) and need to be assigned before usage.

These store arbitray values and can be reassigned.

### Direct array value inclusion a.k.a. freestanding expressions

Array values can also be directly included in a templates content (given that the two text types are compatible) and the array's values will be included with the correct indentation and newline in the templates body.

### Control flow

The language supports `if` and `each` expressions.

The `if` expression allows values to be selected dynamically, for example to change a login button to logout button if the user is already logged in.

The `each` expression allows you to map over an array and produces a new array. This is commonly used to include a list of things in a templates output. Direct array value inclusion allows you to include this mapped output directly into your templates with the correct indentation and newlines.

### Functions

There are a few builtin functions available to template authors to suit common use cases. These are subject to be extended based on user feedback.

The function call syntax is reminiscent of Haskell and since pipelines of function calls are pretty common (where a function get's called with the result of another function and so on) cookie cutter includes the dollar sign syntax to cut down on parentheses which Haskell users should find familiar.

Custom functions can be written to extend the capabilities of the template engine at render time. These take precendence over the builtin ones and allow you to alter their behaviour if needed.

### Contextualization

The text type is context aware and automatically ensures correct escaping based on the source and destination type. You can safely include a `text` piece into `html` or `js.string.s` (a single quote JS-String) and cookie cutter handles the escaping automatically.

Although web content generation is the primary focus of the project other types of text content can also be supported. For this you can implement your own `Contextualizer` instead of utizilizing the standard one. This provides custom text types and context detecting. You can also opt out of this feature entirely by using the `NoopContextualizer` which only supports the `text` type and does no context analysis.

### Output

Template output can be obtained as a `String` or be directly written to a `fmt::Write` implementor.
