Skip to content
This repository
Browse code

Add readme

  • Loading branch information...
commit 01e589e35c73dc346eeb75c20fc44d8906ae7751 1 parent 050d27c
Sam Stephenson authored

Showing 1 changed file with 256 additions and 0 deletions. Show diff stats Hide diff stats

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

0 comments on commit 01e589e

Please sign in to comment.
Something went wrong with that request. Please try again.