I have my own crate for template rendering. I tried various existing ones but I ended up not liking any of them for one reason or another, so I've made my own.
Some of the features are:
* Fully static. It's compiled into Rust code instead of being dynamic. (I wanted to be able to use normal Rust code in my templates instead of a special template-only language, and I wanted the extra speed.)
* Built-in automatic HTML whitespace minification at compile time.
* Built-in XSS-safe string interpolation. You have to explicitly use the unsafe raw interpolation.
* It can interpolate any Rust value which implements the `Display` trait.
* Doesn't use Jinja's syntax.
* Doesn't have any extra unnecessary dependencies.
* Doesn't use inheritance for template composition, instead it uses simple textual inclusion plus late binding to achieve composition. Since it's hard to explain let me give a simple example. Let's assume I have a skeleton.html which looks like this:
<html>
<head>
<title><~ @paste title ~></title>
</head>
<body>
~~ @paste body
</body>
</html>
And now I have index.html which is the actual template I render, and it looks like this:
~~ @include "skeleton.html"
~~ @snippet title
Index
~~ @end
~~ @snippet body
<h1>Hello world!</h1>
~~ @end
As you can see I first include the skeleton.html, and then I define the "title" and the "body" snippets after the skeleton has already pasted them. Normally this wouldn't work, but since the `@paste` directive is lazy it only gets resolved once the whole template is processed.
This makes it really simple to customize the templates, since you can just add `@paste`s wherever you'd like to have a customization point, and you don't have to think about doing things in the right order since the templating engine will take care of it for you.
(If you forget to define a snippet that was `@paste`d you'll get a compile time error; I also have other directives that allow you to set a default if there was no snippet defined.)
That looks a lot like ructe [0], a templating language that I really love. It compiles templates to functions that you can call from Rust using a build script. The functions parameters are accessible from your templates. You can even import and run arbitrary rust code from your app: