Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 249 lines (179 sloc) 8.38 kb
01e589e @sstephenson Add readme
authored
1 Eco: Embedded CoffeeScript templates
2 ====================================
3
4 Eco lets you embed [CoffeeScript](http://coffeescript.org/) logic in
5 your markup. It's like EJS and ERB, but with CoffeeScript inside the
6 `<% ... %>`. Use it from [Node.js](http://nodejs.org/) to render your
a353639 @sstephenson Describe the command-line utility
authored
7 application's views on the server side, or compile your templates
8 to JavaScript with the `eco` command-line utility and use them to
9 dynamically render views in the browser.
01e589e @sstephenson Add readme
authored
10
6355c8b @sstephenson Style
authored
11 Here's how an Eco template looks:
01e589e @sstephenson Add readme
authored
12
13 <% if @projects.length: %>
14 <% for project in @projects: %>
15 <a href="<%= project.url %>"><%= project.name %></a>
16 <p><%= project.description %></p>
17 <% end %>
18 <% else: %>
19 No projects
20 <% end %>
21
11a467e @sstephenson Extract documentation into doc/ and generate README.md programmatically
authored
22 # Usage
01e589e @sstephenson Add readme
authored
23
24 Use `eco.render()` to render your templates. The first argument is the
25 template source as a string. The second argument is the context object
26 which contains your view state and any helper methods you want to call.
27
28 eco = require "eco"
29 fs = require "fs"
30
31 template = fs.readFileSync __dirname + "/views/projects.html.eco", "utf-8"
32 console.log eco.render template, projects: [
33 { name: "Mobile app", url: "/projects/1", description: "Iteration 1" },
34 { name: "Home page redesign", url: "/projects/2" }
35 ]
36
37 Eco is fully synchronous. If your template needs to access data from
38 asynchronous operations, perform those first before calling `render`.
39
6355c8b @sstephenson Style
authored
40 ## Language reference
41
42 Eco's syntax is simple:
01e589e @sstephenson Add readme
authored
43
44 * `<% expression %>`: Evaluate a CoffeeScript expression without
45 printing its return value.
46 * `<%= expression %>`: Evaluate a CoffeeScript expression, escape its
47 return value, and print it.
48 * `<%- expression %>`: Evaluate a CoffeeScript expression and print
49 its return value without escaping it.
50 * `<%= @property %>`: Print the escaped value of the property
51 `property` from the context object passed to `render`.
52 * `<%= @helper() %>`: Call the helper method `helper` from the context
53 object passed to `render`, then print its escaped return value.
6a92073 @sstephenson Document tag escaping and blocks in the syntax synopsis
authored
54 * `<% @helper -> %>...<% end %>`: Call the helper method `helper` with
55 a function as its first argument. When invoked, the function will
56 capture and return the content `...` inside the tag.
57 * `<%%` and `%%>` will result in a literal `<%` and `%>` in the
58 rendered template, respectively.
01e589e @sstephenson Add readme
authored
59
11a467e @sstephenson Extract documentation into doc/ and generate README.md programmatically
authored
60 ## A note about whitespace
01e589e @sstephenson Add readme
authored
61
ff8cb94 @sstephenson Add "therefore" to clarify causal role of whitespace insensitivity in…
authored
62 CoffeeScript is whitespace-sensitive, but your templates
63 aren't. Therefore, Eco code tags that begin an indented CoffeeScript
64 block must be suffixed with a colon. To indicate the end of an
65 indented block, use the special tag `<% end %>`. For example:
01e589e @sstephenson Add readme
authored
66
67 <% if @project.isOnHold(): %>
68 On Hold
69 <% end %>
70
71 You don't need to write the `if` and `end` tags on separate lines:
72
73 <% if @project.isOnHold(): %> On Hold <% end %>
74
75 And you can use the single-line postfix form of `if` as you'd expect:
76
77 <%= "On Hold" if @project.isOnHold() %>
78
79 Certain forms in CoffeeScript, such as `else`, must be unindented
80 first. Eco handles that for you automatically:
81
82 <% if @project.isOnHold(): %>
83 On Hold
84 <% else if @project.isArchived(): %>
85 Archived
86 <% end %>
87
11a467e @sstephenson Extract documentation into doc/ and generate README.md programmatically
authored
88 ## The context object
01e589e @sstephenson Add readme
authored
89
90 The context object you pass to `eco.render()` becomes the value of
91 `this` inside your template. You can use CoffeeScript's `@` sigil to
92 easily access properties and call helper methods on the context
93 object.
94
95 eco.render "<p><%= @description %></p>",
96 description: "HTML 5 mobile app"
97
11a467e @sstephenson Extract documentation into doc/ and generate README.md programmatically
authored
98 ## Helpers
01e589e @sstephenson Add readme
authored
99
100 Helper methods on your context object can access other properties on
101 the context object in the same way they're accessed in the template:
102 through `this`, or with the `@` sigil.
103
104 translations = require "translations"
105
106 eco.render "<span><%= @translate 'common.welcomeText' %></span>",
107 language: "en"
108 translate: (key) ->
109 translations[@language][key]
110
11a467e @sstephenson Extract documentation into doc/ and generate README.md programmatically
authored
111 ## Escaping and unescaping
01e589e @sstephenson Add readme
authored
112
113 When you print an expression in a template with `<%= ... %>`, its
114 value is HTML-escaped. For example,
115
116 eco.render "<%= @description %>",
117 description: "<strong>HTML 5</strong> mobile app"
118
119 would render:
120
121 &lt;strong&gt;HTML 5&lt;/strong&gt; mobile app
122
123 You can use the `<%- ... %>` tag to print the value of an expression
124 without escaping it. So this code:
125
126 eco.render "<%- @description %>",
127 description: "<strong>HTML 5</strong> mobile app"
128
129 would produce:
130
131 <strong>HTML 5</strong> mobile app
132
133 It is sometimes useful to generate markup in helper methods. The
134 special `safe` method on the context object tells Eco that the string
135 can be printed in `<%= ... %>` tags without being escaped. You can use
136 this in conjunction with the context object's `escape` method to
137 selectively sanitize parts of the string. For example,
138
aed6b85 @sstephenson Fix linkTo example in the readme
authored
139 eco.render "<%= @linkTo @project %>",
01e589e @sstephenson Add readme
authored
140 project: { id: 4, name: "Crate & Barrel" }
141 linkTo: (project) ->
142 url = "/projects/#{project.id}"
143 name = @escape project.name
144 @safe "<a href='#{url}'>#{name}</a>"
145
146 would render:
147
148 <a href='/projects/4'>Crate &amp; Barrel</a>
149
11a467e @sstephenson Extract documentation into doc/ and generate README.md programmatically
authored
150 ## Custom escape helpers
01e589e @sstephenson Add readme
authored
151
152 By default, Eco's `escape` method takes a string and returns an
153 HTML-escaped string. You can override this behavior to escape for
154 formats other than HTML, or to bypass escaping entirely. For example,
155
156 eco.render "From: <%= @address %>",
157 address: "Sam Stephenson <sstephenson@gmail.com>"
aed6b85 @sstephenson Fix linkTo example in the readme
authored
158 escape: (string) -> string
01e589e @sstephenson Add readme
authored
159
160 would return:
161
162 From: Sam Stephenson <sstephenson@gmail.com>
163
11a467e @sstephenson Extract documentation into doc/ and generate README.md programmatically
authored
164 ## Blocks and capturing
01e589e @sstephenson Add readme
authored
165
166 You can capture blocks of a template by wrapping them in a function
167 definition. For example, rendering this template:
168
169 <% div = (contents) => %>
170 <div><%- contents %></div>
171 <% end %>
172 <%= div "Hello" %>
173
174 would produce:
175
176 <div>Hello</div>
177
178 Captured blocks can be passed to helper methods too. In this example,
179 the capture body is passed to the `formFor` helper as its last
180 argument. Then the `formFor` helper calls this argument to produce a
181 value.
182
183 template = """
184 <%= @formFor @project, (form) => %>
185 <label>Name:</label>
186 <%= form.textField "name" %>
187 <% end %>
188 """
189
190 eco.render template,
191 project: { id: 1, name: "Mobile app" }
e43e9f7 @zungaphobia Change reserved keyword 'yield' to 'yield_to' in README
zungaphobia authored
192 formFor: (project, yield_to) ->
01e589e @sstephenson Add readme
authored
193 form =
194 textField: (attribute) =>
195 name = @escape attribute
196 value = @escape @project[attribute]
197 @safe "<input type='text' name='#{name}' value='#{value}'>"
198
199 url = "/projects/#{@project.id}"
e43e9f7 @zungaphobia Change reserved keyword 'yield' to 'yield_to' in README
zungaphobia authored
200 body = yield_to form
01e589e @sstephenson Add readme
authored
201 @safe "<form action='#{url}' method='post'>#{body}</form>"
202
203 Note: In general, you should use CoffeeScript's fat arrow (`=>`) to
204 define capturing functions, so that you have access to the context
205 object inside the captured block. Treat the plain arrow (`->`) as an
206 optimization, for when you are certain the capture body will not need
207 to reference properties or helper methods on the context object.
208
209
11a467e @sstephenson Extract documentation into doc/ and generate README.md programmatically
authored
210 # Contributing
01e589e @sstephenson Add readme
authored
211
212 You can check out the Eco source code from GitHub:
213
214 $ git clone http://github.com/sstephenson/eco.git
215
216 To run Eco's test suite, install
217 [nodeunit](http://github.com/caolan/nodeunit) and run `cake test`.
218
219 Report bugs on the [GitHub issue tracker](http://github.com/sstephenson/eco/issues).
220
11a467e @sstephenson Extract documentation into doc/ and generate README.md programmatically
authored
221 # License (MIT)
01e589e @sstephenson Add readme
authored
222
223 Copyright (c) 2010 Sam Stephenson <sstephenson@gmail.com>
224
225 Permission is hereby granted, free of charge, to any person obtaining
226 a copy of this software and associated documentation files (the
227 "Software"), to deal in the Software without restriction, including
228 without limitation the rights to use, copy, modify, merge, publish,
229 distribute, sublicense, and/or sell copies of the Software, and to
230 permit persons to whom the Software is furnished to do so, subject to
231 the following conditions:
232
233 The above copyright notice and this permission notice shall be
234 included in all copies or substantial portions of the Software.
235
236 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
237 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
238 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
239 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
240 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
241 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
242 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
243
11a467e @sstephenson Extract documentation into doc/ and generate README.md programmatically
authored
244 # Special thanks
01e589e @sstephenson Add readme
authored
245
246 * Jeremy Ashkenas <jashkenas@gmail.com>
247 * Josh Peek <josh@joshpeek.com>
11a467e @sstephenson Extract documentation into doc/ and generate README.md programmatically
authored
248
Something went wrong with that request. Please try again.