-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
244 lines (184 loc) · 8.09 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
<!DOCTYPE html>
<html lang=en>
<head>
<meta charset=utf8>
<title>Handpipe.js - Generator based handlebars style streaming templates</title>
<link href="style.css" rel=stylesheet>
<link href="http://fonts.googleapis.com/css?family=Raleway:400,100,300,500,600,700,800" rel=stylesheet>
<link href="lib/highlight/styles/github.css" rel=stylesheet>
</head>
<body>
<div id=wrapper>
<header>
<h1>Handpipe.js</h1>
<p>Generator based handlebars style streaming templates.</p>
</header>
<main>
<p class=lead>Handpipe.js is a new & different take on handlebars templates. It uses <strong>ES6 generators</strong> to retrieve data asynchronously & <strong>Node's stream</strong> abstraction to compile & process templates memory & time efficiently.</p>
<form id="download" action="https://raw.githubusercontent.com/handpipe/handpipe.js/master/dist/handpipe.js">
<button type="submit">Download <strong>v0.11.0</strong></button>
<br>
<small><a href="https://raw.githubusercontent.com/handpipe/handpipe.js/master/dist/handpipe.min.js">Download minified version</a></small>
</form>
<h2 id=getting-started>Getting started</h2>
<h3 id=example-1>Example 1</h3>
<p>Given a template in the DOM:</p>
<pre><code class=handlebars>
<!doctype html>
<div id="output"></div>
<script id="template" type="text/x-handpipe-template">
<div>
<h1>{{title}}</h1>
<p>{{desc}}</p>
</div>
</script>
<script src="bundle.js"></script>
</code></pre>
<p>Read, process and pipe to DOM element with ID "output":</p>
<pre><code class=javascript>
// main.js
var innerhtml = require("innerhtml")
, hp = require("handpipe")
, template = document.getElementById("template")
, output = document.getElementById("output")
var compiler = hp({
title: function (next, cb) {
// Some async operation to get data for "title"
setTimeout(function () { cb(null, "foobar") }, 1000)
},
desc: "Lorem ipsum dolor sit"
})
innerhtml.createReadStream(template)
.pipe(compiler)
.pipe(innerhtml.createWriteStream(output))
</code></pre>
<p><a href="http://browserify.org/">Browserify</a> this file to use in the browser:</p>
<pre><code>
npm install -g browserify
npm install innerhtml handpipe
browserify main.js > bundle.js
</code></pre>
<h3 id=example-2>Example 2</h3>
<p>Given template.html:</p>
<pre><code class=handlebars>
<!doctype html>
<div>
<h1>{{title}}</h1>
<p>{{desc}}</p>
</div>
</code></pre>
<p>Read, process and pipe to output.html:</p>
<pre><code class=javascript>
var fs = require("fs")
, hp = require("handpipe")
var compiler = hp({
title: function (next, cb) {
// Some async operation to get data for "title"
setTimeout(function () { cb(null, "foobar") }, 1000)
},
desc: "Lorem ipsum dolor sit"
})
fs.createReadStream("template.html")
.pipe(compiler)
.pipe(fs.createWriteStream("output.html"))
</code></pre>
<p>To use this file:</p>
<ol>
<li>Install node >= 0.11
<li>Start node using <code>--harmony</code> flag.
</ol>
<h2 id=api>API</h2>
<h3 id=handpipe>handpipe([ data ])</h3>
<p>Create a transform stream to compile a template and apply a data context to it. Pipe Handlebars in, and HTML/Markdown/whatever out. Shortcut for <code>handpipe.compile().pipe(handpipe.apply([ data ]))</code></p>
<h4 id=handpipe-data>data</h4>
<p>The <code>data</code> object gets values for the template. Properties that require async processing are functions with the signature <code>function (next, cb) {}</code>.</p>
<p><code>next</code> is an object that has a <code>key</code> property. This is the name of the variable / function your code should invoke to retrieve the value. In loops, the next object will also contain an <code>index</code> and an <code>iterable</code> property.</p>
<p>Invoke <code>cb</code> when the value has been retrieved. Pass the value as the second argument (error as the first if one occurred).</p>
<h3 id=handpipe-compile>handpipe.compile()</h3>
<p>Create a new handpipe compiler. The compiler is a transform stream you can pipe templates into and compiled template JS out from.</p>
<h3 id=handpipe-apply>handpipe.apply([ data ])</h3>
<p>Applies the <a href="#handpipe-data"><code>data</code></a> to the compiled template. Returns a transform stream that you can pipe compiled template JS into and HTML/Markdown/whatever out from. </p>
<h2 id=template-syntax>Template syntax</h2>
<p>Template syntax is a subset of handlebars.</p>
<h3 id=variable-output>Variable output</h3>
<p>Output variables using double curly braces:</p>
<pre><code class=handlebars> {{varname}}</code></pre>
<p>handpipe supports simple paths so you can output content below the current context:</p>
<pre><code class=handlebars> {{foo.bar}} or {{foo/bar}}</code></pre>
<p>Nested paths can also include <code>../</code> segments, which evaluate their paths against a parent context.</p>
<pre><code class=handlebars>
<h1>Comments</h1>
<div id="comments">
{{#each comments}}
<h2><a href="/posts/{{../permalink}}#{{id}}">{{title}}</a></h2>
<div>{{body}}</div>
{{/each}}
</div>
</code></pre>
<h3 id=loops>Loops</h3>
<p>Use the <code>each</code> block helper to iterate over arrays:</p>
<pre><code class=handlebars>
<ul>
{{#each sprockets}}
<li>{{name}} ({{teeth}})</li>
{{/each}}
</ul>
</code></pre>
<p>You might populate this template with the following JS:</p>
<pre><code class=javascript>
hp({
sprockets: function (next, cb) {
db.sprockets.find({}).toArray(cb)
}
})
</code></pre>
<p>If sprocket objects <strong>do not</strong> have "name" and/or "teeth" properties then the <code>data</code> object passed to handpipe will be queried so that a value can be provided. <code>next.key</code> will be "name" or "teeth" (depending on which property is currently being evaluated), <code>next.context</code> will be the current sprocket object.</p>
<h3 id=conditionals>Conditionals</h3>
<p>Use the <code>if</code> block helper to create conditionally rendered template blocks:</p>
<pre><code class=handlebars>
{{#if title}}
<h1>{{title}}</h1>
{{/if}}
</code></pre>
<p>With optional alternative:</p>
<pre><code class=handlebars>
{{#if title}}
<h1>{{title}}</h1>
{{else}}
<h1>Unnamed</h1>
{{/if}}
</code></pre>
<h3 id=html-escaping>HTML escaping</h3>
<p>handpipe HTML-escapes values returned by a <code>{{expression}}</code>. If you don't want handpipe to escape a value, use the "triple-stash", <code>{{{</code>.</p>
<pre><code class=handlebars>
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{{body}}}
</div>
</div>
</code></pre>
<h3 id=comments>Comments</h3>
<p>Use <code>{{! comment }}</code> or <code>{{!-- comment --}}</code> to create comments that don't appear in output HTML. Any comments that must contain <code>{{</code> or <code>}}</code> should use the <code>{{!-- --}}</code> syntax.</p>
<h3 id=context-re-binding>Context re-binding</h3>
<p>Use the <code>with</code> block helper to alter the context for a template block:</p>
<pre><code class=handlebars>
<div class="entry">
<h1>{{title}}</h1>
{{#with author}}
<h2>By {{firstName}} {{lastName}}</h2>
{{/with}}
</div>
</code></pre>
</main>
<footer>
<div>
<a id="github" href="http://github.com/handpipe"><img src="img/GitHub-Mark-32px.png"></a>
<small>Mustache designed by Gabriela Ruiz from the Noun Project</small>
</div>
</footer>
</div><!--/#wrapper-->
<script src="lib/highlight/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>