pmeunier/cuach

cuach

Latest patch on March 12, 2019
cuachInitial patchon March 12, 2019
cuach-deriveInitial patchon March 12, 2019
Cargo.tomlFixing a bug in generated codeon March 12, 2019
README.mdTypos in the READMEon March 12, 2019
README.md

Cuach, a HTML template system for Rust

Cuach defines a single trait Render, usable to produce HTML pages from templates and Rust structs. 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. 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.