OLD | NEW |
---|---|
(Empty) | |
1 # Handlebar templates | |
2 | |
3 This repository contains utilities around a templating system that I called "Han dlebar". They're a logic-less templating language based on [mustache](http://mus tache.github.com/) (obviously) which is itself based on [ctemplate](http://code. google.com/p/ctemplate) apparently. | |
mkearney1
2013/11/15 02:04:23
Would be nice to have an updated README once dust
not at google - send to devlin
2013/11/15 05:25:55
Agree x100. there's the docs on github.com/kalman/
| |
4 | |
5 The original and reference implementation is written in Java, with a JavaScript (via CoffeeScript) port and a Python port. The tests are cross-platform but cont rolled from Java with junit; this means that all implementations are hopefully u p to date (or else some tests are failing). | |
6 | |
7 The goal of handlebar is to provide the most complete and convenient way to writ e logic-less templates across the whole stack of a web application. Write templa tes once, statically render content on the Java/Python server, then as content i s dynamically added render it using the same templates on the JavaScript client. | |
8 | |
9 ## Overview | |
10 | |
11 A template is text plus "mustache" control characters (thank you mustache for th e cool terminology I have adopted). | |
12 | |
13 A template is rendered by passing it JSON data. I say "JSON" but what I really m ean is JSON-like data; the actual input will vary depending on the language bind ings (Java uses reflection over properties and maps, JavaScript uses objects, Py thon uses dictionaries). | |
14 | |
15 Generally speaking there are two classes of mustaches: "self closing" ones like `{{foo}}` `{{{foo}}}` `{{*foo}}`, and "has children" ones like `{{#foo}}...{{/fo o}}` `{{?foo}}...{{/foo}}` `{{^foo}}...{{/foo}}` where the `...` is arbitrary ot her template data. | |
16 | |
17 In both cases the `foo` represents a path into the JSON structure, so | |
18 | |
19 {{foo.bar.baz}} | |
20 | |
21 is valid for JSON like | |
22 | |
23 {"foo": {"bar": {"baz": 42 }}} | |
24 | |
25 (here it would resolve to `42`). | |
26 | |
27 All libraries also have the behaviour where descending into a section of the JSO N will "push" the sub-JSON onto the top of the "context stack", so given JSON li ke | |
28 | |
29 {"foo": {"bar": {"foo": 42 }}} | |
30 | |
31 the template | |
32 | |
33 {{foo.bar.foo}} {{?foo}}{{bar.foo}} {{?bar}{{foo}}{{/bar}} {{/foo}} | |
34 | |
35 will correctly resolve all references to be `42`. | |
36 | |
37 There is an additional identifier `@` representing the "tip" of that context sta ck, useful when iterating using the `{{#foo}}...{{/foo}}` structure; `{ "list": [1,2,3] }` with `{{#list}} {{@}} {{/list}}` will print ` 1 2 3 `. | |
38 | |
39 Finally, note that the `{{/foo}}` in `{{#foo}}...{{/foo}}` is actually redundant , and that `{{#foo}}...{{/}}` would be sufficient. Depdencing on the situation o ne or the other will tend to be more readable (explicitly using `{{/foo}}` will perform more validation). | |
40 | |
41 ## Structures ("mustaches") | |
42 | |
43 ### `{{foo.bar}}` | |
44 | |
45 Prints out the HTML-escaped value at path `foo.bar`. | |
46 | |
47 ### `{{{foo.bar}}}` | |
48 | |
49 Prints out value at path `foo.bar` (no escaping). | |
50 | |
51 ### `{{*foo.bar}}}` | |
52 | |
53 Prints out the JSON serialization of the object at path `foo.bar` (no escaping; this is designed for JavaScript client bootstrapping). | |
54 | |
55 ### `{{+foo.bar}}` | |
56 | |
57 Inserts the sub-template (aka "partial template") found at path `foo.bar`. Curre ntly, all libraries actually enforce that this is a pre-compiled template (rathe r than a plain string for example) for efficiency. This lets you do something li ke: | |
58 | |
59 template = Handlebar('{{#list}} {{+partial}} {{/}}') | |
60 partial = Handlebar('{{foo}}...') | |
61 json = { | |
62 'list': [ | |
63 { 'foo': 42 }, | |
64 { 'foo': 56 }, | |
65 { 'foo': 10 } | |
66 ] | |
67 } | |
68 print(template.render(json, {'partial': partial}).text) | |
69 > 42... 56... 10... | |
70 | |
71 Very useful for dynamic web apps, and also just very useful. | |
72 | |
73 ### `{{#foo.bar}}...{{/}}` | |
74 | |
75 Runs `...` for each item in an array found at path `foo.bar`, or each key/value pair in an object. | |
76 | |
77 ### `{{?foo.bar}}...{{/}}` | |
78 | |
79 Runs `...` if `foo.bar` resolves to a "value", which is defined based on types. | |
80 | |
81 * `null` is never considered a value. | |
82 * `true` is a valid, `false` isn't. | |
83 * Any number other than `0` is a value. | |
84 * Any non-empty string is a value. | |
85 * Any non-empty array is a value. | |
86 * Any non-empty object is a value. | |
87 | |
88 ### `{{^foo.bar}}...{{/}}` | |
89 | |
90 Runs `...` if `foo.bar` _doesn't_ resolve to a "value". The exact opposite of `{ {?foo.bar}}...{{/}}`. | |
91 | |
92 ### `{{:foo.bar}}{{=case1}}...{{=case2}}___{{/}}` | |
93 | |
94 Ooh a switch statement! Prints `...` if the string found at `foo.bar` is the str ing `"case1"`, `___` if it's `"case2"`, etc. | |
95 | |
96 ## That's all | |
97 | |
98 But at the moment this is currently under heavy weekend development. Which is to say a constant trickle of code as I need it. | |
99 | |
100 Soon: better fault tolerance all round, comments, tidier syntax, less whitespace y output, and moving the Java and JavaScript/CoffeeScript implementations and te sts into this repository! And maybe some kind of online playground at some point . | |
OLD | NEW |