Rust templating with Handlebars

Overview

handlebars-rust

Handlebars templating language implemented in Rust and for Rust.

Handlebars-rust is the template engine that renders the official Rust website rust-lang.org, its book.

Build Status MIT licensed Docs rustc Donate

Getting Started

Quick Start

extern crate handlebars;
#[macro_use]
extern crate serde_json;

use handlebars::Handlebars;

fn main() -> Result<(), Box<dyn Error>> {
    let mut reg = Handlebars::new();
    // render without register
    println!(
        "{}",
        reg.render_template("Hello {{name}}", &json!({"name": "foo"}))?
    );

    // register template using given name
    reg.register_template_string("tpl_1", "Good afternoon, {{name}}")?;
    println!("{}", reg.render("tpl_1", &json!({"name": "foo"}))?);
    Ok(())
}

Code Example

If you are not familiar with handlebars language syntax, it is recommended to walk through their introduction first.

Examples are provided in source tree to demo usage of various api.

  • quick the very basic example of registry and render apis
  • render how to define custom helpers with function, trait impl or macro, and also how to use custom helpers.
  • render_file similar to render, but render to file instead of string
  • partials template inheritance with handlebars
  • decorator how to use decorator to change data or define custom helper
  • script how to define custom helper with rhai scripting language, just like using javascript for handlebarsjs
  • error simple case for error
  • dev_mode a web server hosts handlebars in dev_mode, you can edit the template and see the change without restarting your server.

Minimum Rust Version Policy

Handlebars will track Rust nightly and stable channel. When dropping support for previous stable versions, I will bump major version and clarify in CHANGELOG.

Rust compatibility table

Handlebars version range Minimum Rust version
~3.0.0 1.32
~2.0.0 1.32
~1.1.0 1.30
~1.0.0 1.23

Document

Rust doc.

Changelog

Changelog is available in the source tree named as CHANGELOG.md.

Contributor Guide

Any contribution to this library is welcomed. To get started into development, I have several Help Wanted issues, with the difficulty level labeled. When running into any problem, feel free to contact me on github.

I'm always looking for maintainers to work together on this library, let me know (via email or anywhere in the issue tracker) if you want to join.

Why (this) Handlebars?

Handlebars is a real-world templating system that you can use to build your application without pain.

Features

Isolation of Rust and HTML

This library doesn't attempt to use some macro magic to allow you to write your template within your rust code. I admit that it's fun to do that but it doesn't fit real-world use cases.

Limited but essential control structures built-in

Only essential control directives if and each are built-in. This prevents you from putting too much application logic into your template.

Extensible helper system

You can write your own helper with Rust! It can be a block helper or inline helper. Put your logic into the helper and don't repeat yourself.

A helper can be as a simple as a Rust function like:

handlebars_helper!(hex: |v: i64| format!("0x{:x}", v));

/// register the helper
handlebars.register_helper("hex", Box::new(hex));

And using it in your template:

{{hex 16}}

By default, handlebars-rust ships additional helpers (compared with original js version) that is useful when working with if.

With script_helper feature flag enabled, you can also create helpers using rhai script, just like JavaScript for handlebars-js. This feature was in early stage. Its API was limited at the moment, and can change in future.

Template inheritance

Every time I look into a templating system, I will investigate its support for template inheritance.

Template include is not sufficient for template reuse. In most cases you will need a skeleton of page as parent (header, footer, etc.), and embed your page into this parent.

You can find a real example of template inheritance in examples/partials.rs and templates used by this file.

Auto-reload in dev mode

By turning on dev_mode, handlebars auto reloads any template and scripts that loaded from files or directory. This can be handy for template development.

WebAssembly compatible

Handlebars 3.0 can be used in WebAssembly projects.

Related Projects

Web frameworks

Adopters

The adopters page lists projects that uses handlebars for part of their functionalities.

Extensions

The extensions page has libraries that provide additional helpers, decorators and outputs to handlebars-rust, and you can use in your own projects.

License

This library (handlebars-rust) is open sourced under the MIT License.

Comments
  • Pest parser

    Pest parser

    Fixes #81

    I decided to use pest to replace current custom parser for maintainability and correctness.

    Tasks:

    • [x] Grammar
    • [x] Rebuild parser with pest Rdp.queue() results
    • [x] Keeping error tracking: report template error with line/column number
    • [x] Keeping template element maps, line/column number for each item
    • [x] Retain leading whitespaces in text
    opened by sunng87 21
  • added a markdown helper

    added a markdown helper

    I know this is probably just the beginning but I think I added a working markdown helper so that if you have a variable x that is a string containing markdown, then you can parse it to html by passing

    {{markdown x}}
    

    in the template..

    I want to improve this by adding some kind of environment, but I couldn't quite figure it out right away (and the use case above is the one that i want to use anyway). As a second commit perhaps something like below could be implemented

    {{#markdown}}
    #wow
    {{> sub_template}}
    {{~markdown}}
    

    edit: also sorry that this changed Cargo.toml so much. I used cargo add pulldown-cmark and it must have mangled the Cargo.toml I will go back and edit by hand

    opened by waynenilsen 18
  • Segfault in Handlebars

    Segfault in Handlebars

    I just experienced a segfault which seems to be originated in the handlebars code.

    As there are ~6000 stack levels, it seems that I ended up crashing into the heap by recursing too deep. The recursion seems to happen in handlebars, as only a few (as in below 10) stack levels are from my code.

    The corrosponding code is here, here is the causing call.

    The templates can be found here, the registration of the templates and the helpers is here. If you have any questions regarding the code, feel free to ask me, I know the codebase is pretty big and maybe confusing for some people.


    To reproduce:

    • Clone the repository, checkout the branch from the PR
    • cargo build --manifest-path bin/core/imag-store/Cargo.toml # takes some time
    • mkdir /tmp/store/
    • ./target/debug/imag-store --rtp /tmp/ --config imagrc.toml create -p test entry -c foo
    • enjoy.

    The last few lines of the stacktrace follow


    #6274 0x00005555556808c2 in core::result::Result<&handlebars::template::Template, handlebars::error::RenderError>::and_then<&handlebars::template::Template,handlebars::error::RenderError,(),closure> (self=Ok = {...}, op=closure = {...})
        at /build/rustc-1.17.0-src/src/libcore/result.rs:601
    #6275 0x00005555555f8b18 in handlebars::registry::Registry::renderw<collections::btree::map::BTreeMap<&str, collections::string::String>> (self=0x7ffff6ab9038, name="DEBUG", data=0x7fffffff5578, writer=&mut Write)
        at /home/m/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.29.0/src/registry.rs:247
    #6276 0x00005555555f8654 in handlebars::registry::Registry::render<collections::btree::map::BTreeMap<&str, collections::string::String>> (self=0x7ffff6ab9038, name="DEBUG", data=0x7fffffff5578)
        at /home/m/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.29.0/src/registry.rs:236
    #6277 0x00005555556f75c4 in libimagrt::logger::{{impl}}::log (self=0x7ffff6ab9000, record=0x7fffffff5a50) at /home/m/archive/development/rust/imag/lib/core/libimagrt/src/logger.rs:149
    #6278 0x0000555555e16a17 in log::__log (level=log::LogLevel::Debug, target="handlebars::render", loc=0x5555562f06a8 <<handlebars::template::TemplateElement as handlebars::render::Renderable>::render::_LOC>, args=Arguments = {...})
        at /home/m/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:903
    #6279 0x0000555555ae6784 in handlebars::render::{{impl}}::render (self=0x7ffff6a35400, registry=0x7ffff6ab9038, rc=0x7fffffff7038) at /home/m/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.29.0/src/render.rs:641
    #6280 0x0000555555ae5e41 in handlebars::render::{{impl}}::render (self=0x7ffff6a37718, registry=0x7ffff6ab9038, rc=0x7fffffff7038) at /home/m/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.29.0/src/render.rs:590
    #6281 0x00005555555f8f6e in handlebars::registry::{{impl}}::renderw::{{closure}}<collections::btree::map::BTreeMap<&str, collections::string::String>> (t=0x7ffff6a37718) at /home/m/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.29.0/src/registry.rs:254
    #6282 0x00005555556808c2 in core::result::Result<&handlebars::template::Template, handlebars::error::RenderError>::and_then<&handlebars::template::Template,handlebars::error::RenderError,(),closure> (self=Ok = {...}, op=closure = {...})
        at /build/rustc-1.17.0-src/src/libcore/result.rs:601
    #6283 0x00005555555f8b18 in handlebars::registry::Registry::renderw<collections::btree::map::BTreeMap<&str, collections::string::String>> (self=0x7ffff6ab9038, name="DEBUG", data=0x7fffffff79d8, writer=&mut Write)
        at /home/m/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.29.0/src/registry.rs:247
    #6284 0x00005555555f8654 in handlebars::registry::Registry::render<collections::btree::map::BTreeMap<&str, collections::string::String>> (self=0x7ffff6ab9038, name="DEBUG", data=0x7fffffff79d8)
        at /home/m/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.29.0/src/registry.rs:236
    #6285 0x00005555556f75c4 in libimagrt::logger::{{impl}}::log (self=0x7ffff6ab9000, record=0x7fffffff7eb0) at /home/m/archive/development/rust/imag/lib/core/libimagrt/src/logger.rs:149
    #6286 0x0000555555e16a17 in log::__log (level=log::LogLevel::Debug, target="handlebars::render", loc=0x5555562f06a8 <<handlebars::template::TemplateElement as handlebars::render::Renderable>::render::_LOC>, args=Arguments = {...})
        at /home/m/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:903
    #6287 0x0000555555ae6784 in handlebars::render::{{impl}}::render (self=0x7ffff6a35400, registry=0x7ffff6ab9038, rc=0x7fffffff9498) at /home/m/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.29.0/src/render.rs:641
    #6288 0x0000555555ae5e41 in handlebars::render::{{impl}}::render (self=0x7ffff6a37718, registry=0x7ffff6ab9038, rc=0x7fffffff9498) at /home/m/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.29.0/src/render.rs:590
    #6289 0x00005555555f8f6e in handlebars::registry::{{impl}}::renderw::{{closure}}<collections::btree::map::BTreeMap<&str, collections::string::String>> (t=0x7ffff6a37718) at /home/m/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.29.0/src/registry.rs:254
    #6290 0x00005555556808c2 in core::result::Result<&handlebars::template::Template, handlebars::error::RenderError>::and_then<&handlebars::template::Template,handlebars::error::RenderError,(),closure> (self=Ok = {...}, op=closure = {...})
        at /build/rustc-1.17.0-src/src/libcore/result.rs:601
    #6291 0x00005555555f8b18 in handlebars::registry::Registry::renderw<collections::btree::map::BTreeMap<&str, collections::string::String>> (self=0x7ffff6ab9038, name="DEBUG", data=0x7fffffff9e38, writer=&mut Write)
        at /home/m/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.29.0/src/registry.rs:247
    ---Type <return> to continue, or q <return> to quit---
    #6292 0x00005555555f8654 in handlebars::registry::Registry::render<collections::btree::map::BTreeMap<&str, collections::string::String>> (self=0x7ffff6ab9038, name="DEBUG", data=0x7fffffff9e38)
        at /home/m/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.29.0/src/registry.rs:236
    #6293 0x00005555556f75c4 in libimagrt::logger::{{impl}}::log (self=0x7ffff6ab9000, record=0x7fffffffa310) at /home/m/archive/development/rust/imag/lib/core/libimagrt/src/logger.rs:149
    
    #6294 0x0000555555e16a17 in log::__log (level=log::LogLevel::Debug, target="libimagrt::runtime", loc=0x5555562e92f0 <libimagrt::runtime::Runtime::_new::_LOC>, args=Arguments = {...}) at /home/m/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.3.8/src/lib.rs:903
    #6295 0x00005555555d4d34 in libimagrt::runtime::Runtime::_new<clap::app::App> (cli_app=App = {...}, matches=ArgMatches = {...}, Python Exception <type 'exceptions.ValueError'> invalid literal for int() with base 0: '0x1 <error: Cannot access memory at address 0x1>': 
    config=...) at <log macros>:7
    #6296 0x00005555555d4319 in libimagrt::runtime::Runtime::new<clap::app::App> (cli_app=App = {...}) at /home/m/archive/development/rust/imag/lib/core/libimagrt/src/runtime.rs:97
    #6297 0x00005555555d360d in libimagrt::setup::generate_runtime_setup<fn(clap::app::App) -> clap::app::App> (name="imag-store", version="0.4.0", about="Direct interface to the store. Use with great care!", builder=0x0)
        at /home/m/archive/development/rust/imag/lib/core/libimagrt/src/setup.rs:39
    #6298 0x00005555555e642c in imag_store::main () at /home/m/archive/development/rust/imag/bin/core/imag-store/src/main.rs:71
    
    opened by matthiasbeyer 14
  • update some debs for minimal-versions

    update some debs for minimal-versions

    This bumps the minimal acceptable versions in Cargo.toml to versions that are compatible with -Z minimal-versions. This is part of the process of seeing how hard this is for crates to use in preparation for getting it stabilized for use in CI, specifically upstreaming the changes required to get criterion working with it. It is easy to use if all of your dependencies support it, but much harder if trying to impose it on them.

    Also cargo defaults to interpreting version requirements as ^. So this switched to the shorter form.

    opened by Eh2406 12
  • Consider using rustc_serialize::json::encode to obtain json

    Consider using rustc_serialize::json::encode to obtain json

    Rather than force every structure to implement the ToJson trait, it might be preferable to allow users to just add a #[derive(RustcEncodable)] on their structs, and handlebars can obtain a JSON value via the rustc_serialize::json::encode function.

    opened by hugoduncan 12
  • handlebars 3.2.0 breaks existing code

    handlebars 3.2.0 breaks existing code

    Presumably because of #346 but haven't confirmed yet.

    This custom helper https://github.com/CleverCloud/amq-protocol/blob/011ed7a80d4448b03ca2db48b50e73c03104b98d/codegen/src/templating.rs#L283-L343 now hits this assertion with 3.2.0 while it works fine with 3.1.0 https://github.com/CleverCloud/amq-protocol/blob/011ed7a80d4448b03ca2db48b50e73c03104b98d/codegen/src/templating.rs#L307

    bug 
    opened by Keruspe 11
  • signle quote not working

    signle quote not working

    Test:

        #[test]
        fn test_template() {
            let mut handlebars = Handlebars::new();
            let data = json!({});
            handlebars.render_template("{{'test'}}", &data).unwrap();
        }
    

    Throw,

    ---- test::test_template stdout ----
    thread 'test::test_template' panicked at 'called `Result::unwrap()` on an `Err` value: RenderError { desc: "Failed to parse template.", template_name: None, line_no: None, column_no: None, cause: Some(TemplateError { reason: InvalidSyntax, template_name: None, line_no: Some(1), column_no: Some(3), segment: Some("   0 | {{'test'}}\n     |---^------\n") }), unimplemented: false }', src/main.rs:155:57
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    
    opened by theowenyoung 10
  • Compile error with the 2.0.3 update

    Compile error with the 2.0.3 update

    Hi! I use the mdbook crate and it stopped compiling today, very likely due to handlebars' update.

    I don't know much about both projects but here's the error:

    Error
    Compiling mdbook v0.3.5
    error[E0277]: `(dyn std::error::Error + 'static)` cannot be sent between threads safely
    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/mdbook-0.3.5/src/lib.rs:123:5
        |
    123 | /     error_chain! {
    124 | |         foreign_links {
    125 | |             Io(std::io::Error) #[doc = "A wrapper around `std::io::Error`"];
    126 | |             HandlebarsRender(handlebars::RenderError) #[doc = "Handlebars rendering failed"];
    ...   |
    156 | |         }
    157 | |     }
        | |_____^ `(dyn std::error::Error + 'static)` cannot be sent between threads safely
        |
        = help: the trait `std::marker::Send` is not implemented for `(dyn std::error::Error + 'static)`
        = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<(dyn std::error::Error + 'static)>`
        = note: required because it appears within the type `std::boxed::Box<(dyn std::error::Error + 'static)>`
        = note: required because it appears within the type `std::option::Option<std::boxed::Box<(dyn std::error::Error + 'static)>>`
        = note: required because it appears within the type `handlebars::error::RenderError`
        = note: required because it appears within the type `errors::ErrorKind`
        = note: required because it appears within the type `errors::Error`
        = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
    

    Since the update was a patch, the issue is more to report the breaking change than anything else.

    Here's the issue in mdbook.

    opened by leudz 10
  • Iterate through JSON Object that has keys with unusual characters

    Iterate through JSON Object that has keys with unusual characters

    Hello! First off, thanks for all the great work!

    I'm trying to render a Handlebars template that needs to iterate through a JSON object with keys that contain dots and spaces. This causes Handlebars to return a RenderError with description Invalid JSON path.

    Minimal Example

    It fails in the same way if I replace "strange key" with "strange.key". I tried this using handlebars-rust version 0.28.3.

    extern crate handlebars;
    #[macro_use]
    extern crate serde_json;
    
    use handlebars::Handlebars;
    
    fn main() {
        Handlebars::new().template_render(
            "{{#each x}} {{@key}} {{this}}, {{/each}}",
            &json!({"x": {"a": 1, "b": 2, "strange key": 3}})
        ).map(|s| println!("{}", s)).unwrap();
    }
    

    Handlebars Code

    I believe this line in src/grammar.rs in today's master branch is relevant:

    path_ident = _{ ['a'..'z']|['A'..'Z']|['0'..'9']|["_"]|["@"]|["$"]|["<"]|[">"]|["-"]}
    

    I'm unfamiliar with Handlebars, but this grammar could be updated to support more general JSON keys, or it could be ignored if referring to the key using this or @key.

    I'd be glad to submit a PR if necessary, but I would appreciate any help.

    opened by roguh 10
  • Partial is rendered twice

    Partial is rendered twice

    Not sure if this is an issue with the library or my syntax. I'm updating a project that I wrote from the legacy partial syntax to the new syntax. I have three (simplified) templates like this:

    <!-- base.hbs -->
    <html>
    <body>
    {{> layout}}
    </body>
    </html>
    
    <!-- blog.hbs -->
    {{#> base}}
    
    {{#*inline "layout"}}
    <div>
    {{#> content}}
    Parent content
    {{> otherHelper}}
    {{/content}}
    </div>
    {{/inline}}
    
    {{/base}}
    
    <!-- blog_post.hbs -->
    {{#> blog}}
    
    {{#*inline "content"}}
    Child content
    {{/inline}}
    
    {{/blog}}
    

    The problem is that the otherHelper helper gets rendered (and output) twice, and I cannot figure out why.

    bug 
    opened by euclio 10
  • Enum handling

    Enum handling

    If I had an enum like:

    pub enum Value {
        Float(f64),
        Bool(bool),
    }
    

    How would I render something like:

    {{#if value == Float(val)}}
        <input type='number' value={{val}} />
    {{/if}}
    
    {{#if value == Bool(val)}}
        <input type='checkbox' checked={{val}} />
    {{/if}}
    
    opened by ghotiphud 10
  • How to use square brackets when calling helper?

    How to use square brackets when calling helper?

    I can't figure out how to use square brackets to refer to a helper. While fuzzing, a template like {{[\0] ''}} failed and said there was no helper named \0 even though it was defined. However, when I used the same template and defined a helper named [\0], it worked.

    Naming the helper \0 works in the Handlebars.js playground but naming it [\0] doesn't, so I'm not sure why the opposite is true for handlebars-rust.

    Question

    What am I doing wrong? I used handlebars.register_helper to register the helper. Is it supposed to be done some other way?

    opened by ysthakur 0
  • Web playground

    Web playground

    We need a web playground to demo and verify template or data. The playground should allow user to provide:

    • a base template
    • several partials with names
    • data as json string
    • helper defined as rhai script

    The data gathered from user input is passed to web assembly module. The the result or error message is given back to user.

    Web playground can be deployed to github pages via github action. We will always use latest master branch to built the wasm module.

    help wanted 
    opened by sunng87 0
  • Improve stability of the benchmark

    Improve stability of the benchmark

    Some benches were not totally stable on my computer (it's really hot these days, maybe I hit the temp freq switch of my cpu in the benches)

    But on some case maybe black boxing and increasing the measurement (now 100 by default) is a start:

    doc of criterion black_box: https://docs.rs/criterion/latest/criterion/fn.black_box.html

    opened by darnuria 2
  • feat: AsyncHelperDef WIP

    feat: AsyncHelperDef WIP

    Fixes #157

    This is an attempt in progress to add async support for handlebars helper. The whole render call stack needs to be async when any of the helper is async.

    TODO Items:

    • [ ] async helper registartion
    • [ ] Registry APIs support for async helpers, like has_helper
    • [ ] async render
    • [ ] test and examples
    opened by sunng87 0
  • Supports `Result` for helper function

    Supports `Result` for helper function

    In production code the helpers may returns error, we could returns the underlying error from helper when render_template.

    Below are some pseudo-code:

    fn query_name_by_id(id: &str) -> Result<String, DBError> {
    	...
    }
    
    let result = hbr.render_template("The name is {{query_name_by_id this}}", &id);
    
    match result {
    	Ok() -> {},
    	Err(e) -> {
    		match e {
    			Handlebars.Error(e) => // render error
    			DBError(e) => // db error from query_name_by_id
    			_ => {}
    		}
    	}
    }
    
    question 
    opened by RoCry 4
Releases(v4.3.0)
  • v4.3.0(May 18, 2022)

    Changes included in 4.3.0 release:

    • [Changed] update MSRV to 1.57 as rhai requires
    • [Fixed] Reimplemented indent support for partial expression {{> partial}}, which is introduced in 4.2.0. The new implementation is aligned with original javascript version, that every text line generated from partial are indented as {{> partial}} does. prevent_indent will turn-off this feature. [#505]
    • [Changed] changed error support library from quick_error to thiserror

    Caution that the partial indent fix will make handlebars 4.3 behaviour different with 4.2 when there is indent with {{> partial}} statement.

    Source code(tar.gz)
    Source code(zip)
  • v4.2.1(Feb 3, 2022)

  • v4.2.0(Jan 6, 2022)

    Added

    • RustEmbed support for loading templates from [#484]

    Fixed

    • Parser support for variables begins with digit [#479]
    • Typo in Debug impl of Handlebars [#485 ]

    Changed

    • Keep indent whitespaces for partial expression {{> partial}} as default in handlebarsjs. A new option prevent_indent is provided on Handlebars to turn off this behaviour. [#486]
    • Update MSRV to 1.51 due to dependency changes
    Source code(tar.gz)
    Source code(zip)
  • v4.1.5(Nov 18, 2021)

  • v4.1.4(Nov 5, 2021)

  • v4.1.3(Sep 13, 2021)

  • v4.1.2(Aug 22, 2021)

    Added

    • Support for generic types in handlebars_helper!.
    • Getter and setter for rhai Engine from registry.

    Fixed

    • Improve doc for dev_mode that it has to be enabled before adding templates.
    Source code(tar.gz)
    Source code(zip)
  • v4.1.1(Jul 31, 2021)

  • v4.1.0(Jul 12, 2021)

    Detailed Changelog

    • [Added] export StringOutput as requested in #442
    • [Changed] strict mode now applies to our helper macro handlebars_helper! and built-in helpers based on it.
    • [Fixed] Line stripping feature for standalone statement introduced in #404 is now aligned with handlebarsjs. #448
    Source code(tar.gz)
    Source code(zip)
  • v4.0.0(May 25, 2021)

    4.0 Highlights

    Development mode

    4.0 brings in dev_mode to Handlebars. By turning on dev_mode, templates loaded from files or directories are auto-reloaded each time. This makes development workflow more fluent.

    Performance improvement

    4.0 provides up to 20% performance boost compared to 3.x.

    Bugfixes

    Several corner cases were fixed in this release. Some has already been backported on to 3.x branch.

    Detailed Changelog

    • [Added] dev_mode for registry: templates and scripts loaded from file are always reloaded when dev mode enabled [#395]
    • [Added] Registry is now Clone [#395]
    • [Added] New built-in helper len [#421]
    • [Changed] Updated rhai to 0.19 and then 0.20 [#391]
    • [Changed] #each helper now renders else block for non-iterable data [#380]
    • [Changed] TemplateError and ScriptError is now a cause of RenderError [#395]
    • [Changed] Empty lines around block helpers are now stripped [#404]
    • [Changed] Breaking RenderContext::get_partial now returns Option<&Template>
    • [Changed] Breaking Capitalize names like HtmlExpression and IoError based on clippy recommendations [#424]
    • [Changed] Breaking Improved return type of call_inner from HelperDef to avoid misleading [#437]
    • [Fixed] reference starts with null, true and false were parsed incorrectly [#382]
    • [Fixed] dir source path separator bug on windows [#389] [#405]
    • [Fixed] stack overflow with nested @partial-block [#401]
    • [Fixed] value access issue when upper block has a base value [#419]
    • [Fixed] escape rules for Json string literal [#423]
    • [Fixed] Breaking zero-arity subexpressions support [#433] Zero-arity subexpression no longer resolved as variable. The behaviour is now aligned with handlebarsjs.
    • [Removed] Breaking option to disable source map is removed [#395]
    • [Removed] Breaking TemplateFileError and TemplateRenderError are removed and merged into TemplateError and RenderError [#395]
    Source code(tar.gz)
    Source code(zip)
  • v3.5.3(Feb 20, 2021)

Owner
Ning Sun
Programmer, at work and at home. Open source enthusiast. Linux user. Favourite languages: Clojure, Rust
Ning Sun
Easily embed and manage assets for your web application to build standalone-executables. Offers filename hashing, templating and more.

reinda: easily embed and manage assets This library helps you manage your assets (external files) and is mostly intended to be used in web application

Lukas Kalbertodt 23 Jul 15, 2022
Yarte stands for Yet Another Rust Template Engine

Should we start to worry? bytes-buf feature can produce SIGILL. avx and sse flags are in almost all cpus of x86 and x86_64 architectures. More details

Juan Aguilar 249 Dec 19, 2022
:pencil: Compile-time HTML templates for Rust

maud Documentation (source) • API reference • Change log Maud is an HTML template engine for Rust. It's implemented as a macro, html!, which compiles

Chris Wong 1.4k Jan 1, 2023
A macro-based html builder for rust

Horrorshow A macro-based html templating library, compatible with stable rust (currently requires rust >= 1.37). Features This crate will degrade grac

Steven Allen 267 Dec 11, 2022
Rust Compiled Templates with static-file handling

Rust Compiled Templates — ructe This is my attempt at writing a HTML template system for Rust. Some inspiration comes from the scala template system u

Rasmus Kaj 337 Jan 8, 2023
A template engine for Rust based on Jinja2/Django

Tera Tera is a template engine inspired by Jinja2 and the Django template language. <title>{% block title %}{% endblock title %}</title> <ul> {% for u

Vincent Prouillet 2.5k Jan 1, 2023
Type-safe, compiled Jinja-like templates for Rust

Askama Askama implements a template rendering engine based on Jinja. It generates Rust code from your templates at compile time based on a user-define

Dirkjan Ochtman 2k Jan 5, 2023
A flexible template engine for Rust

Rustache Rustache is a Rust implementation of the Mustache spec. Documentation The different Mustache tags are documented at the mustache(5) man page.

rustache 208 May 10, 2022
A minimalist Rust WebAssembly project template

MiniWASM - A minimalist Rust WebAssembly project template This is a minimal Rust-powered WebAssembly application template. It was designed to showcase

Emil Loer 160 Jul 26, 2022
A template for a Rust-powered static-page Try Online interface

rust-tio-template A template for a Rust-powered static-page Try Online interface What is included This is an example setup that enables all of the fol

null 2 Dec 13, 2021
MiniJinja is a powerful but minimal dependency template engine for Rust

MiniJinja: a powerful template engine for Rust with minimal dependencies MiniJinja is a powerful but minimal dependency template engine for Rust which

Armin Ronacher 686 Jan 5, 2023
Templates for creating rust projects with a GitHub-managed lifecycle with cargo-generate 🏗️📃

rust-templates Templates for creating rust projects with a GitHub-managed lifecycle with cargo-generate. ??️ ?? What you get: PR build validation usin

Ben Greenier 1 Oct 30, 2021
A "Hello, world!" template of a Rust binary crate for the ESP-IDF framework.

Rust on ESP-IDF "Hello, World" template A "Hello, world!" template of a Rust binary crate for the ESP-IDF framework. This is the crate you get when ru

Ivan Markov 140 Jan 4, 2023
A fast & simple boilerplate generator, built with Rust. 🦀

Boom ?? A fast & simple boilerplate generator, built with Rust. Installing boom This package is not yet downloadable on Brew or other package managers

Tristan Edwards 4 Apr 20, 2022
A template for creating services in Rust using Axum and Prisma.

A template for creating services in Rust using Axum and Prisma. This uses the super cool Prisma Rust Client.

Aaron Leopold 6 Oct 19, 2022
✨ A perfect template for a binary rust project.

Rust Template A project template for Rust, helping to structure your projects blazingly fast ⚡ . Features ?? Code-ready for binary projects. Add amazi

bwtecode 3 Aug 21, 2022
Rust templating with Handlebars

handlebars-rust Handlebars templating language implemented in Rust and for Rust. Handlebars-rust is the template engine that renders the official Rust

Ning Sun 923 Dec 29, 2022
This app reads a csv file and sends an email with a formatted Handlebars file.

Bulkmail This app reads a csv file and sends an email with a formatted Handlebars file. This can be run on Linux for AMD64 and ARMv7. Upstream Links D

Giovanni Bassi 17 Nov 3, 2022
Self-contained template system with Handlebars and inline shell scripts

Handlematters Self-contained template system with Handlebars and inline shell scripts Introduction Handlematters is a template system that combines Ha

Keita Urashima 3 Sep 9, 2022
Handlebars middleware for Iron web framework

handlebars-iron Handlebars middleware for the Iron web framework. This library, together with handlebars, iron and hyper, works on both stable and nig

Ning Sun 118 Jun 28, 2022