9 releases (4 breaking)

new 0.5.0 Dec 20, 2024
0.4.1 Dec 19, 2024
0.3.0 Dec 19, 2024
0.2.2 Dec 18, 2024
0.1.2 Dec 17, 2024

#85 in Template engine

Download history 332/week @ 2024-12-13

332 downloads per month

MIT/Apache

120KB
3K SLoC

moostache is a Mustache template engine.

It supports the following Mustache features: escaped variables, unescaped variables, dotted names, implicit iterators, sections, inverted sections, comments, and partials.

It does not support these Mustache features: lambdas, dynamic names, blocks, parents, or set delimiters.

Guide

To render templates you must create a type that implements the TemplateLoader trait and call one of its render functions. Moostache provides two implementations: HashMapLoader and FileLoader.

HashMapLoader

You can create a HashMapLoader from a hashmap:

use moostache::HashMapLoader;
use maplit::hashmap;

let loader = HashMapLoader::try_from(hashmap! {
    "greet" => "hello {{name}}!",
})?;

Or from a LoaderConfig:

use moostache::{HashMapLoader, LoaderConfig};

// this will eagerly load all .html files in the
// templates directory and its sub-directories
// into memory and compile them into moostache
// templates, up to cache_size
let loader = HashMapLoader::try_from(LoaderConfig {
    templates_directory: "./templates",
    templates_extension: "html",
    cache_size: 200,
})?;

Then you can render any template by name, passing it a type which impls Serialize:

use moostache::TemplateLoader;
use serde_derive::Serialize;

#[derive(Serialize)]
struct Person<'a> {
    name: &'a str,
}

let john = Person {
    name: "John",
};

let rendered = loader.render_serializable_to_string("greet", &john);
assert_eq!(rendered, "hello John!")

Or by passing it a serde_json::Value:

use moostache::TemplateLoader;
use serde_json::json;

let john = json!({
    "name": "John",
});

let rendered = loader.render_to_string("greet", &john);
assert_eq!(rendered, "hello John!")

FileLoader

You can create a FileLoader from a LoaderConfig:

use moostache::{FileLoader, LoaderConfig};

// this loader will lazily read .html files from
// the templates directory and its sub-directories
// and compile them to moostache templates during
// renders, and it will cache up to cache_size
// compiled templates in an internal LRU cache
let loader = FileLoader::try_from(LoaderConfig {
    templates_directory: "./templates",
    templates_extension: "html",
    cache_size: 200,
})?;

Then, as explained above, you can render any template by name, passing it a type which impls Serialize or a serde_json::Value.

HashMapLoader vs FileLoader

HashMapLoader is a little bit faster during initial renders because it requires you to preload all templates that may be used during the render into memory. You may prefer to use the HashMapLoader if all of your templates can fit into memory.

FileLoader is more memory-efficient, since it lazily fetches templates during renders, and then caches a certain amount of them in an LRU cache for follow-up renders. You may prefer to use the FileLoader if not all of your templates can fit into memory.

Regardless, both impl the TemplateLoader trait so they each support the insert and remove methods to insert and remove templates in-between renders for additional flexibility.

Dependencies

~2.2–9MB
~83K SLoC