# Cuach, a HTML template system for Rust
Cuach defines a single trait `Render`, usable to produce HTML pages from templates and Rust `struct`s. Cuach compiles on stable Rust and uses procedural macros to produce efficient static code.
Cuach requires a folder called `templates` at the root of a repository (alongside `Cargo.toml`). Then, if that folder contains a file called `index.html`, we can use it like so:
```
#[macro_use]
extern crate cuach;
use cuach::*;
#[template(path="index.html")]
struct A<'a> {
field: &'a str,
other_field: usize
}
fn main() {
println!("{}, (A { field: "blah", other_field: 0 }).render().unwrap())
}
```
The template can be as simple as an empty file, or contain more elaborate things, such as:
```
<html>
<body>
field is equal to <strong>{ self.field }</strong>, and other_field to { self.other_field }.
</body>
</html>
```
## Rules
All the variables and functions of the module where `A` is defined are in scope in the template. There is also an extra variable in scope, `w`, of type `&mut std::fmt::Write`.
For any Rust expression `e`, `{ e }` in the template gets translated to `(e).render_into(w)`.
Moreover, more complex Rust expressions can be used using HTML comments. For instance, the following produces ten HTML paragraphs, with 0, 1, …, 9 as their contents. Anything inside HTML comments is parsed as Rust.
```
<!-- for i in 0..10 { -->
<p>{ i }</p>
<!-- } -->
```
This means in particular that any expression of the form `{ e }` in the template is strictly equivalent to
```
(e).render_into(w)?;
```
## Whitespace and escaping
Any amount of whitespace between tags or comments is ignored if it contains at least one newline character, and is output as is else. One way to force whitespace on an otherwise blank line is to add whitespace between two HTMLcomments, like so:
```
<!-- --> <!-- -->
```
Comments can be used in the templates, but they have to be Rust comments inside HTML comments:
```
<!-- // this is a comment -->
<!-- /* this is
another,
multiline,
comment */ -->
```
The parsing of templates is done using an XML parsing library, [xml-rs](https://crates.io/crates/xml-rs). Therefore, standard XML escaping works and can be used, but it sometimes conflicts with Rust borrows. Cuach handles that situation by replacing, before parsing, all `&` that are not recognised by regular expression `&[a-z]+;` with `&amp;`. After parsing, all instances of `&amp;` are converted back to `&`.
## Including other files
There is nothing special about including other files in Cuach, as Rust provides that ability already, by doing something like `{ include_str!("../templates/included.html") }`. Unfortunately, the parsing libraries used by Cuach (such as `proc-macro2`) do not yet allow Cuach to use filepaths relative to the current file.
## Conflict with JS
The curly braces might sometimes conflict with JS embedded in HTML. The way to deal with this is that Cuach only considers curly braces on the same line: in order to be understood as a Rust expression, the code between `{` and `}` must not contain the character `\n`.
Here is a valid example of JS templated by Cuach, embedded in HTML:
```js
<script>my_function("{self.argument}")</script>
```
And the following is a valid example of passing an object to a function in JS, not transformed by Cuach:
```js
<script>
my_function({
"arg": 0
})
</script>
```