Categories
Web
  • Github CLI
  • SSH
  • HTTPS
Clone Repo

MUSTACHE-ZIG

{{mustache}} templates for Zig.

made with Zig Matrix Build codecov license mit

! Under development !

Read more on Zig News

Features

Comments {{! Mustache is awesome }}.

✓ Custom delimiters {{=[ ]=}}.

Interpolation of common types, such as strings, enums, bools, optionals, pointers, integers, floats and JSON objects into {{variables}.

Unescaped interpolation with {{{tripple-mustache}}} or {{&ampersant}}.

✓ Rendering sections {{#foo}} ... {{/foo}}.

Section iterator over slices, arrays and tuples {{slice}} ... {{/slice}}.

✓ Rendering inverted sections {{^foo}} ... {{/foo}}.

Lambdas expansion.

✓ Rendering partials {{>file.html}}.

☐ Rendering parents and blocks {{<file.html}} and {{$block}}.

Full spec compliant

✓ All implemented features passes the tests from mustache spec.

Examples

Render from strings, files and pre-loaded templates. See the source code for more details.

Runtime parser


const std = @import("std");
const mustache = @import("mustache");

pub fn main() !void {
    const template =
        \\Hello {{name}} from Zig
        \\Supported features:
        \\{{#features}}
        \\  - {{name}}
        \\{{/features}}
    ;

    const data = .{
        .name = "friends",
        .features = .{
            .{ .name = "interpolation" },
            .{ .name = "sections" },
            .{ .name = "delimiters" },
            .{ .name = "partials" },
        },
    };

    const allocator = std.testing.allocator;
    const result = try mustache.allocRenderText(allocator, template, data);
    defer allocator.free(result);

    try std.testing.expectEqualStrings(
        \\Hello friends from Zig
        \\Supported features:
        \\  - interpolation
        \\  - sections
        \\  - delimiters
        \\  - partials
        \\
    , result);
}

Comptime parser


const std = @import("std");
const mustache = @import("mustache");

pub fn main() !void {
    const template_text = "It's a comptime loaded template, with a {{value}}";
    const comptime_template = comptime mustache.parseComptime(template_text, .{}, .{});
    
    const Data = struct { value: []const u8 };
    const data: Data = .{
        .value = "runtime value"
    };

    const allocator = std.testing.allocator;
    const result = try mustache.allocRender(comptime_template, data);
    defer allocator.free(result);

    try std.testing.expectEqualStrings(
        "It's a comptime loaded template, with a runtime value", 
        result,
    );
}

JSON support


const std = @import("std");
const mustache = @import("mustache");

pub fn main() !void {
    const allocator = std.testing.allocator;

    // Parsing an arbitrary (dynamic) json string:
    const json_source =
        \\{
        \\   "name": "friends"
        \\}
    ;    
    var json = try std.json.parseFromSlice(
        std.json.Value,
        allocator,
        json_source,
        .{},
    );
    defer json.deinit();

    const template = "Hello {{name}} from Zig";
    const result = try mustache.allocRenderText(allocator, template, json);
    defer allocator.free(result);

    try std.testing.expectEqualStrings("Hello friends from Zig" , result);
}

FFI Interface

Mustache-zig exports a FFI interface to be consumed by other languages

For more details:

Customizable use

There is no “one size fits all”, but the mustache-zig API is intended to provide great flexibility to cover many use cases.

Benchmarks.

There are some benchmark tests inspired by the excellent Ramhorns’s benchmarks, comparing the performance of most popular Rust template engines.

  1. Rendering to a new allocated string 1 million times

    Total timens/iterMB/s
    Ramhorns 0.14.00,040s40 ns2425 MB/s
    Askama 0.90,136s136 ns713 MB/s
    Tera 1.2.00,308s308 ns314 MB/s
    Mustache 0.90,363s363 ns267 MB/s
    Handlebars 3.1.0-beta.21,833s1,833 ns52 MB/s
  2. Parsing a template 1 million times

    Total timens/iterMB/s
    Ramhorns 0.14.00,317s317 ns492 MB/s
    Mustache 0.95,863s5,863 ns26 MB/s
    Handlebars 3.1.0-beta.211,797s11,797 ns13 MB/s

*All benchmarks were executed using cargo bench on a Intel i7-1185G7 @ 3.00GHz, Linux kernel 5.17

For comparision with mustache-zig, refer to “Rendering to a new allocated string 1 million times” and “Parsing a template 1 million times” sections bellow.

Mustache vs Zig’s fmt

The same benchmark was implemented in Zig for both mustache-zig and Zig’s std.fmt.

We can assume that Zig’s std.fmt is the fastest possible way to render a simple string using Zig. This benchmark shows how much slower a mustache template is rendered when compared with the same template rendered by Zig’s std.fmt.

  1. Rendering to a pre-allocated buffer 1 million times

    Total timens/iterMB/sPenality
    Zig fmt0.042s42 ns2596 MB/s
    mustache-zig0.094s94 ns1149 MB/s2.260x slower
  2. Rendering to a new allocated string 1 million times

    Total timens/iterMB/sPenality
    Zig fmt0.058s58 ns1869 MB/s
    mustache-zig0.167s167 ns645 MB/s2.897x slower
  3. Rendering to a local file 1 million times

    Total timens/iterMB/sPenality
    Zig fmt0.079s79 ns1367 MB/s
    mustache-zig0.125s125 ns862 MB/s1.586x slower
  4. Parsing a template 1 million times

    Total timens/iterMB/s
    mustache-zig1.380s1,380 ns182 MB/s

*All benchmarks were compiled as ReleaseSafe, and executed on a Intel i7-1185G7 @ 3.00GHz, Linux kernel 5.17

Memory benchmarks

Mustache templates are well known for HTML templating, but it’s useful to render any kind of dynamic document, and potentially load templates from untrusted or user-defined sources.

So, it’s also important to be able to deal with multi-megabyte inputs without eating all your RAM.


    // 32KB should be enough memory for this job
    // 16KB if we don't need to support lambdas 😅
    var plenty_of_memory = std.heap.GeneralPurposeAllocator(.{ .enable_memory_limit = true }){
        .requested_memory_limit = 32 * 1024,
    };
    defer _ = plenty_of_memory.deinit();

    try mustache.renderFile(plenty_of_memory.allocator(), "10MB_file.mustache", ctx, out_writer);

Licensing

  • MIT

  • Mustache is Copyright (C) 2009 Chris Wanstrath Original CTemplate by Google

About
Logic-less templates for Zig
Owner
batiati (User)
Last Commit
2025-03-05
Latest Release
Latest Release Date
Created
2022-02-15