]>
Commit | Line | Data |
---|---|---|
8bb4bdeb XL |
1 | handlebars-rust |
2 | =============== | |
3 | ||
4 | Rust templating with [Handlebars templating language](https://handlebarsjs.com). | |
5 | ||
6 | [![Build Status](https://travis-ci.org/sunng87/handlebars-rust.svg?branch=master)](https://travis-ci.org/sunng87/handlebars-rust) | |
7 | [![](http://meritbadge.herokuapp.com/handlebars)](https://crates.io/crates/handlebars) | |
8 | [![](https://img.shields.io/crates/d/handlebars.svg)](https://crates.io/crates/handlebars) | |
9 | [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) | |
83c7162d | 10 | [![Docs](https://docs.rs/handlebars/badge.svg)](https://docs.rs/crate/handlebars/) |
8bb4bdeb XL |
11 | |
12 | ## Getting Started | |
13 | ||
ea8adc8c XL |
14 | ### Quick Start |
15 | ||
16 | ```rust | |
17 | extern crate handlebars; | |
18 | #[macro_use] | |
19 | extern crate serde_json; | |
20 | ||
21 | use handlebars::Handlebars; | |
22 | ||
23 | fn main() { | |
24 | let mut reg = Handlebars::new(); | |
25 | // render without register | |
26 | println!( | |
27 | "{}", | |
83c7162d | 28 | reg.render_template("Hello {{name}}", &json!({"name": "foo"})) |
ea8adc8c XL |
29 | .unwrap() |
30 | ); | |
31 | ||
32 | // register template using given name | |
33 | reg.register_template_string("tpl_1", "Good afternoon, {{name}}") | |
34 | .unwrap(); | |
35 | println!("{}", reg.render("tpl_1", &json!({"name": "foo"})).unwrap()); | |
36 | } | |
37 | ``` | |
38 | ||
39 | Note that I use `unwrap` here which is not recommended in your real code. | |
40 | ||
41 | ### Code Example | |
42 | ||
8bb4bdeb XL |
43 | If you are not familiar with [handlebars language |
44 | syntax](https://handlebarsjs.com), it is recommended to walk through | |
45 | their introduction first. | |
46 | ||
47 | Check `render` example in the source tree. The example shows you how | |
48 | to: | |
49 | ||
50 | * Create a `Handlebars` registry and register the template from files; | |
51 | * Create a custom Helper with closure or struct implementing | |
52 | `HelperDef`, and register it; | |
53 | * Define and prepare some data; | |
54 | * Render it; | |
55 | ||
56 | Run `cargo run --example render` to see results. | |
57 | (or `RUST_LOG=handlebars=info cargo run --example render` for logging | |
58 | output). | |
59 | ||
60 | Checkout `examples/` for more concrete demos of current API. | |
61 | ||
041b39d2 XL |
62 | From 0.26, [Serde](https://serde.rs/) JSON is the default type system |
63 | for this library. The data you pass to handlebars template must | |
64 | implements the `Serialize` trait. Note that we don't actually | |
65 | serialize data to JSON string, we just use the JSON type: number, | |
66 | boolean and etc. | |
67 | ||
68 | Rustc_serialize is now officially deprecated. If your application is | |
69 | still using it, you need to use handlebars-rust `0.25.*`. | |
8bb4bdeb XL |
70 | |
71 | ## Documents | |
72 | ||
73 | [Rust | |
74 | doc](http://sunng87.github.io/handlebars-rust/handlebars/index.html). | |
75 | ||
76 | ## Changelog | |
77 | ||
78 | Change log is available in the source tree named as `CHANGELOG.md`. | |
79 | ||
80 | ## Why (this) Handlebars? | |
81 | ||
82 | Handlebars is a real-world templating system that you can use to build | |
83 | your application without pain. | |
84 | ||
85 | ### Features | |
86 | ||
87 | #### Isolation of Rust and HTML | |
88 | ||
89 | This library doesn't attempt to use some macro magic to allow you to | |
90 | write your template within your rust code. I admit that it's fun to do | |
91 | that but it doesn't fit real-world use case. | |
92 | ||
93 | #### Limited but essential control structure built-in | |
94 | ||
95 | Only essential control directive `if` and `each` were built-in. This | |
96 | prevents you to put too much application logic into your template. | |
97 | ||
98 | #### Extensible helper system | |
99 | ||
100 | You can write your own helper with Rust! It can be a block helper or | |
101 | inline helper. Put you logic into the helper and don't repeat | |
102 | yourself. | |
103 | ||
104 | A helper can be as a simple as a Rust function like: | |
105 | ||
106 | ```rust | |
107 | fn hex_helper (h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { | |
108 | // just for example, add error check for unwrap | |
109 | let param = h.param(0).unwrap().value(); | |
110 | let rendered = format!("0x{:x}", param.as_u64().unwrap()); | |
111 | try!(rc.writer.write(rendered.into_bytes().as_ref())); | |
112 | Ok(()) | |
113 | } | |
114 | ||
115 | /// register the helper | |
116 | handlebars.register_helper("hex", Box::new(hex_helper)); | |
117 | ``` | |
118 | ||
119 | And using it in your template: | |
120 | ||
121 | ```handlebars | |
122 | {{hex my_value}} | |
123 | ``` | |
124 | ||
125 | #### Template inheritance | |
126 | ||
127 | Every time I look into a templating system, I will investigate its | |
128 | support for [template | |
129 | inheritance](https://docs.djangoproject.com/en/1.9/ref/templates/language/#template-inheritance). | |
130 | ||
131 | Template include is not sufficient for template reuse. In most case | |
132 | you will need a skeleton of page as parent (header, footer, etc.), and | |
133 | embed you page into this parent. | |
134 | ||
135 | You can find a real example for template inheritance in | |
136 | `examples/partials.rs`, and templates used by this file. | |
137 | ||
8bb4bdeb XL |
138 | #### WebAssembly compatible |
139 | ||
140 | You can use this handlebars implementation in your rust project that | |
141 | compiles to WebAssembly. Checkout my fork of | |
142 | [todomvc](https://github.com/sunng87/rust-todomvc) demo. | |
143 | ||
83c7162d XL |
144 | #### Strict mode |
145 | ||
146 | Handlebars, the language designed to work with JavaScript, has no | |
147 | strict restriction on accessing non-existed fields or index. It | |
148 | generates empty string for such case. However, in Rust we want a | |
149 | little bit strict sometime. | |
150 | ||
151 | By enabling `strcit_mode` on handlebars: | |
152 | ||
153 | ```rust | |
154 | handlebars.set_strict_mode(true); | |
155 | ``` | |
156 | ||
157 | You will get a `RenderError` when accessing fields that not exists. | |
158 | ||
8bb4bdeb XL |
159 | ### Limitations |
160 | ||
161 | * This implementation is **not fully compatible** with the original | |
162 | javascript version. Specifically, mustache list iteration and null | |
163 | check doesn't work. But you can use `#each` and `#if` for same | |
164 | behavior. | |
ea8adc8c XL |
165 | * You will need to make your data `Serializable` on serde. We don't |
166 | actually serialize data into JSON string or similar. However, we use | |
167 | JSON data type system in template render process. | |
8bb4bdeb XL |
168 | |
169 | ### Handlebars-js features supported in Handlebars-rust | |
170 | ||
171 | * Expression / Block Helpers | |
172 | * Built-in helpers | |
173 | * each | |
174 | * if | |
175 | * with | |
176 | * lookup | |
177 | * log | |
178 | * Custom helper | |
179 | * Parameter and hashes for helper, block params | |
180 | * Partials, include, template inheritance | |
181 | * Omitting whitespace with `~` | |
182 | * Subexpression `{{(foo bar)}}` | |
183 | * Json expression `a.b.[0]` and `a.b.[c]` | |
184 | * RawHelper syntax `{{{{raw-helper}}}}...{{{{/raw-helper}}}}` | |
185 | * Decorator, implemented in Rust way | |
186 | ||
187 | ### JavaScript implementation features we don't have | |
188 | ||
189 | * Mustache block (use `if`/`each` instead) | |
190 | * Chained else | |
191 | ||
192 | Feel free to report an issue if you find something broken. We aren't | |
193 | going to implement all features of handlebars-js, but we should have a | |
194 | workaround for cases we don't support. | |
195 | ||
196 | ## Handlebars for Web Frameworks | |
197 | ||
198 | * Iron: [handlebars-iron](https://github.com/sunng87/handlebars-iron) | |
199 | * Rocket: [rocket/contrib](https://api.rocket.rs/rocket_contrib/struct.Template.html) | |
200 | ||
201 | ## Using handlebars-rust? | |
202 | ||
203 | Add your project to our | |
204 | [adopters](https://github.com/sunng87/handlebars-rust/wiki/adopters). | |
205 | ||
206 | ## License | |
207 | ||
208 | This library (handlebars-rust) is open sourced under MIT License. | |
209 | ||
210 | ## Contact | |
211 | ||
83c7162d | 212 | [Ning Sun](https://github.com/sunng87) (sunng@protonmail.com) |