1 | # ECT
|
2 |
|
3 | [Performance focused](http://ectjs.com/#benchmark) JavaScript template engine with embedded CoffeeScript syntax.
|
4 |
|
5 | [Just try demo](http://ectjs.com) to check all features.
|
6 |
|
7 | ## Installation
|
8 |
|
9 | npm install ect
|
10 |
|
11 | ## Features
|
12 |
|
13 | * Excellent performance
|
14 | * Templates caching
|
15 | * Automatic reloading of changed templates
|
16 | * CoffeeScript code in templates
|
17 | * Multi-line expressions support
|
18 | * Tag customization support
|
19 | * Node.JS and client-side support
|
20 | * Powerful but simple syntax
|
21 | * Inheritance, partials, blocks
|
22 | * Compatible with `express`
|
23 | * Backward compatible with `eco`
|
24 | * [Syntax highlighting for Sublime Text 2](https://github.com/TurtlePie/Sublime-ECT) by [TurtlePie](https://github.com/TurtlePie)
|
25 |
|
26 | ## Usage
|
27 |
|
28 | ```js
|
29 | var ECT = require('ect');
|
30 |
|
31 | var renderer = ECT({ root : __dirname + '/views', ext : '.ect' });
|
32 | var html = renderer.render('page', { title: 'Hello, World!' });
|
33 | ```
|
34 |
|
35 | or
|
36 |
|
37 | ```js
|
38 | var ECT = require('ect');
|
39 |
|
40 | var renderer = ECT({ root : __dirname + '/views', ext : '.ect' });
|
41 |
|
42 | renderer.render('page', { title: 'Hello, World!' }, function (error, html) {
|
43 | console.log(error);
|
44 | console.log(html);
|
45 | });
|
46 | ```
|
47 |
|
48 | You may use JavaScript object as root.
|
49 |
|
50 | ```js
|
51 | var ECT = require('ect');
|
52 |
|
53 | var renderer = ECT({ root : {
|
54 | layout: '<html><head><title><%- title %></title></head><body><% content %></body></html>',
|
55 | page: '<% extend "layout" %><p>Page content</p>'
|
56 | }
|
57 | });
|
58 |
|
59 | var html = renderer.render('page', { title: 'Hello, World!' });
|
60 | ```
|
61 |
|
62 | ### With express
|
63 |
|
64 | app.js
|
65 | ```js
|
66 | var express = require('express');
|
67 | var app = express();
|
68 | var ECT = require('ect');
|
69 | var ectRenderer = ECT({ watch: true, root: __dirname + '/views' });
|
70 |
|
71 | app.engine('.ect', ectRenderer.render);
|
72 |
|
73 | app.get('/', function (req, res){
|
74 | res.render('index.ect');
|
75 | });
|
76 |
|
77 | app.listen(3000);
|
78 | console.log('Listening on port 3000');
|
79 | ```
|
80 |
|
81 | views/index.ect
|
82 | ```html
|
83 | <% extend 'layout.ect' %>
|
84 | <div>Hello, World!</div>
|
85 | ```
|
86 |
|
87 | views/layout.ect
|
88 | ```html
|
89 | <html>
|
90 | <body>
|
91 | <% content %>
|
92 | </body>
|
93 | </html>
|
94 | ```
|
95 |
|
96 | ## Syntax
|
97 |
|
98 | ### Unescaped output
|
99 |
|
100 | ```
|
101 | <%- someVar %>
|
102 | ```
|
103 |
|
104 | ### Escaped output
|
105 |
|
106 | ```
|
107 | <%= someVar %>
|
108 | ```
|
109 |
|
110 | ### CoffeeScript code
|
111 |
|
112 | ```
|
113 | <% for article in @articles : %>
|
114 | <% include 'article', article %>
|
115 | <% end %>
|
116 | ```
|
117 |
|
118 | or
|
119 |
|
120 | ```
|
121 | <% if @user?.authenticated : %>
|
122 | <% include 'partials/user' %>
|
123 | <% else : %>
|
124 | <% include 'partials/auth' %>
|
125 | <% end %>
|
126 | ```
|
127 |
|
128 | ### Inheritance
|
129 |
|
130 | ```
|
131 | <% extend 'layout' %>
|
132 | ```
|
133 |
|
134 | Use
|
135 |
|
136 |
|
137 | ```
|
138 | <% content %>
|
139 | ```
|
140 |
|
141 | in parent template to define the insertion point.
|
142 |
|
143 | ### Partials
|
144 |
|
145 | ```
|
146 | <% include 'partial' %>
|
147 | ```
|
148 |
|
149 | You can redefine data context of partial
|
150 |
|
151 | ```
|
152 | <% include 'partial', { customVar: 'Hello, World!' } %>
|
153 | ```
|
154 |
|
155 | ### Blocks
|
156 |
|
157 | ```
|
158 | <% block 'blockName' : %>
|
159 | <p>This is block content</p>
|
160 | <% end %>
|
161 | ```
|
162 |
|
163 | Use
|
164 |
|
165 |
|
166 | ```
|
167 | <% content 'blockName' %>
|
168 | ```
|
169 |
|
170 | in parent template to define the insertion point.
|
171 |
|
172 | Blocks supports more than one level of inheritance and may be redefined.
|
173 |
|
174 | ## Options
|
175 |
|
176 | ### Renderer
|
177 |
|
178 | - `root` — Templates root folder or JavaScript object containing templates
|
179 | - `ext` — Extension of templates, defaulting to `''` (not used for JavaScript objects as root)
|
180 | - `cache` — Compiled functions are cached, defaulting to `true`
|
181 | - `watch` — Automatic reloading of changed templates, defaulting to `false` (useful for debugging with enabled cache, not supported for client-side)
|
182 | - `open` — Open tag, defaulting to `<%`
|
183 | - `close` — Closing tag, defaulting to `%>`
|
184 |
|
185 | ### Compiler middleware
|
186 |
|
187 | - `root` — Base url, defaulting to `/` (should be equal to `root` option on the client side)
|
188 | - `gzip` — Compressing templates with gzip, defaulting to `false`
|
189 |
|
190 | ## Client-side support
|
191 |
|
192 | Download and include [coffee-script.js](https://github.com/jashkenas/coffee-script/blob/master/extras/coffee-script.js) and [ect.min.js](https://github.com/baryshev/ect/tree/master/ect.min.js).
|
193 |
|
194 | ```html
|
195 | <script src="/path/coffee-script.js"></script>
|
196 | <script src="/path/ect.min.js"></script>
|
197 | ```
|
198 |
|
199 | Use it.
|
200 |
|
201 | ```js
|
202 | var renderer = ECT({ root : '/views' });
|
203 | var data = { title : 'Hello, World!' };
|
204 | var html = renderer.render('template.ect', data);
|
205 | ```
|
206 |
|
207 | ### With server side compiler middleware
|
208 |
|
209 | Download and include [ect.min.js](https://github.com/baryshev/ect/tree/master/ect.min.js). You don't need to include CoffeeScript compiler, because templates are served already compiled by server side compiler middleware.
|
210 |
|
211 | ```html
|
212 | <script src="/path/ect.min.js"></script>
|
213 | ```
|
214 |
|
215 | Setup server side compiler middleware.
|
216 |
|
217 | ```js
|
218 | var connect = require('connect');
|
219 | var ECT = require('ect');
|
220 |
|
221 | var renderer = ECT({ root : __dirname + '/views', ext : '.ect' });
|
222 |
|
223 | var app = connect()
|
224 | .use(renderer.compiler({ root: '/views', gzip: true }))
|
225 | .use(function(err, req, res, next) {
|
226 | res.end(err.message);
|
227 | });
|
228 |
|
229 | app.listen(3000);
|
230 | ```
|
231 |
|
232 | Use it.
|
233 |
|
234 | ```js
|
235 | var renderer = ECT({ root : '/views', ext : '.ect' });
|
236 | var data = { title : 'Hello, World!' };
|
237 | var html = renderer.render('template', data);
|
238 | ```
|
239 |
|
240 | Note: root folder must be on the same domain to avoid cross-domain restrictions.
|
241 |
|
242 | ## License
|
243 |
|
244 | (The MIT License)
|
245 |
|
246 | Copyright (c) 2012 Vadim M. Baryshev <vadimbaryshev@gmail.com>
|
247 |
|
248 | Permission is hereby granted, free of charge, to any person obtaining
|
249 | a copy of this software and associated documentation files (the
|
250 | 'Software'), to deal in the Software without restriction, including
|
251 | without limitation the rights to use, copy, modify, merge, publish,
|
252 | distribute, sublicense, and/or sell copies of the Software, and to
|
253 | permit persons to whom the Software is furnished to do so, subject to
|
254 | the following conditions:
|
255 |
|
256 | The above copyright notice and this permission notice shall be
|
257 | included in all copies or substantial portions of the Software.
|
258 |
|
259 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
260 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
261 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
262 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
263 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
264 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
265 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|