1 | Embedded JavaScript templates<br/>
|
2 | [![Build Status](https://img.shields.io/travis/mde/ejs/master.svg?style=flat)](https://travis-ci.org/mde/ejs)
|
3 | [![Developing Dependencies](https://img.shields.io/david/dev/mde/ejs.svg?style=flat)](https://david-dm.org/mde/ejs?type=dev)
|
4 | [![Known Vulnerabilities](https://snyk.io/test/npm/ejs/badge.svg?style=flat)](https://snyk.io/test/npm/ejs)
|
5 | =============================
|
6 |
|
7 | ## Installation
|
8 |
|
9 | ```bash
|
10 | $ npm install ejs
|
11 | ```
|
12 |
|
13 | ## Features
|
14 |
|
15 | * Control flow with `<% %>`
|
16 | * Escaped output with `<%= %>` (escape function configurable)
|
17 | * Unescaped raw output with `<%- %>`
|
18 | * Newline-trim mode ('newline slurping') with `-%>` ending tag
|
19 | * Whitespace-trim mode (slurp all whitespace) for control flow with `<%_ _%>`
|
20 | * Custom delimiters (e.g. `[? ?]` instead of `<% %>`)
|
21 | * Includes
|
22 | * Client-side support
|
23 | * Static caching of intermediate JavaScript
|
24 | * Static caching of templates
|
25 | * Complies with the [Express](http://expressjs.com) view system
|
26 |
|
27 | ## Example
|
28 |
|
29 | ```ejs
|
30 | <% if (user) { %>
|
31 | <h2><%= user.name %></h2>
|
32 | <% } %>
|
33 | ```
|
34 |
|
35 | Try EJS online at: https://ionicabizau.github.io/ejs-playground/.
|
36 |
|
37 | ## Usage
|
38 |
|
39 | ```javascript
|
40 | let template = ejs.compile(str, options);
|
41 | template(data);
|
42 | // => Rendered HTML string
|
43 |
|
44 | ejs.render(str, data, options);
|
45 | // => Rendered HTML string
|
46 |
|
47 | ejs.renderFile(filename, data, options, function(err, str){
|
48 | // str => Rendered HTML string
|
49 | });
|
50 | ```
|
51 |
|
52 | It is also possible to use `ejs.render(dataAndOptions);` where you pass
|
53 | everything in a single object. In that case, you'll end up with local variables
|
54 | for all the passed options. However, be aware that your code could break if we
|
55 | add an option with the same name as one of your data object's properties.
|
56 | Therefore, we do not recommend using this shortcut.
|
57 |
|
58 | ## Options
|
59 |
|
60 | - `cache` Compiled functions are cached, requires `filename`
|
61 | - `filename` The name of the file being rendered. Not required if you
|
62 | are using `renderFile()`. Used by `cache` to key caches, and for includes.
|
63 | - `root` Set project root for includes with an absolute path (/file.ejs).
|
64 | Can be array to try to resolve include from multiple directories.
|
65 | - `views` An array of paths that EJS can look in to attempt to resolve
|
66 | includes with relative paths.
|
67 | - `context` Function execution context
|
68 | - `compileDebug` When `false` no debug instrumentation is compiled
|
69 | - `client` When `true`, compiles a function that can be rendered
|
70 | in the browser without needing to load the EJS Runtime
|
71 | ([ejs.min.js](https://github.com/mde/ejs/releases/latest)).
|
72 | - `delimiter` Character to use for inner delimiter, by default '%'
|
73 | - `openDelimiter` Character to use for opening delimiter, by default '<'
|
74 | - `closeDelimiter` Character to use for closing delimiter, by default '>'
|
75 | - `debug` Output generated function body
|
76 | - `strict` When set to `true`, generated function is in strict mode
|
77 | - `_with` Whether or not to use `with() {}` constructs. If `false`
|
78 | then the locals will be stored in the `locals` object. Set to `false` in strict mode.
|
79 | - `destructuredLocals` An array of local variables that are always destructured from
|
80 | the locals object, available even in strict mode.
|
81 | - `localsName` Name to use for the object storing local variables when not using
|
82 | `with` Defaults to `locals`
|
83 | - `rmWhitespace` Remove all safe-to-remove whitespace, including leading
|
84 | and trailing whitespace. It also enables a safer version of `-%>` line
|
85 | slurping for all scriptlet tags (it does not strip new lines of tags in
|
86 | the middle of a line).
|
87 | - `escape` The escaping function used with `<%=` construct. It is
|
88 | used in rendering and is `.toString()`ed in the generation of client functions.
|
89 | (By default escapes XML).
|
90 | - `outputFunctionName` Set to a string (e.g., 'echo' or 'print') for a function to print
|
91 | output inside scriptlet tags.
|
92 | - `async` When `true`, EJS will use an async function for rendering. (Depends
|
93 | on async/await support in the JS runtime.
|
94 | - `beautify` Make sure to set this to 'false' in order to skip UglifyJS parsing,
|
95 | when using ES6 features (`const`, etc) as UglifyJS doesn't understand them.
|
96 |
|
97 | This project uses [JSDoc](http://usejsdoc.org/). For the full public API
|
98 | documentation, clone the repository and run `npm run doc`. This will run JSDoc
|
99 | with the proper options and output the documentation to `out/`. If you want
|
100 | the both the public & private API docs, run `npm run devdoc` instead.
|
101 |
|
102 | ## Tags
|
103 |
|
104 | - `<%` 'Scriptlet' tag, for control-flow, no output
|
105 | - `<%_` 'Whitespace Slurping' Scriptlet tag, strips all whitespace before it
|
106 | - `<%=` Outputs the value into the template (escaped)
|
107 | - `<%-` Outputs the unescaped value into the template
|
108 | - `<%#` Comment tag, no execution, no output
|
109 | - `<%%` Outputs a literal '<%'
|
110 | - `%%>` Outputs a literal '%>'
|
111 | - `%>` Plain ending tag
|
112 | - `-%>` Trim-mode ('newline slurp') tag, trims following newline
|
113 | - `_%>` 'Whitespace Slurping' ending tag, removes all whitespace after it
|
114 |
|
115 | For the full syntax documentation, please see [docs/syntax.md](https://github.com/mde/ejs/blob/master/docs/syntax.md).
|
116 |
|
117 | ## Includes
|
118 |
|
119 | Includes either have to be an absolute path, or, if not, are assumed as
|
120 | relative to the template with the `include` call. For example if you are
|
121 | including `./views/user/show.ejs` from `./views/users.ejs` you would
|
122 | use `<%- include('user/show') %>`.
|
123 |
|
124 | You must specify the `filename` option for the template with the `include`
|
125 | call unless you are using `renderFile()`.
|
126 |
|
127 | You'll likely want to use the raw output tag (`<%-`) with your include to avoid
|
128 | double-escaping the HTML output.
|
129 |
|
130 | ```ejs
|
131 | <ul>
|
132 | <% users.forEach(function(user){ %>
|
133 | <%- include('user/show', {user: user}) %>
|
134 | <% }); %>
|
135 | </ul>
|
136 | ```
|
137 |
|
138 | Includes are inserted at runtime, so you can use variables for the path in the
|
139 | `include` call (for example `<%- include(somePath) %>`). Variables in your
|
140 | top-level data object are available to all your includes, but local variables
|
141 | need to be passed down.
|
142 |
|
143 | NOTE: Include preprocessor directives (`<% include user/show %>`) are
|
144 | not supported in v3.0+.
|
145 |
|
146 | ## Custom delimiters
|
147 |
|
148 | Custom delimiters can be applied on a per-template basis, or globally:
|
149 |
|
150 | ```javascript
|
151 | let ejs = require('ejs'),
|
152 | users = ['geddy', 'neil', 'alex'];
|
153 |
|
154 | // Just one template
|
155 | ejs.render('<p>[?= users.join(" | "); ?]</p>', {users: users}, {delimiter: '?', openDelimiter: '[', closeDelimiter: ']'});
|
156 | // => '<p>geddy | neil | alex</p>'
|
157 |
|
158 | // Or globally
|
159 | ejs.delimiter = '?';
|
160 | ejs.openDelimiter = '[';
|
161 | ejs.closeDelimiter = ']';
|
162 | ejs.render('<p>[?= users.join(" | "); ?]</p>', {users: users});
|
163 | // => '<p>geddy | neil | alex</p>'
|
164 | ```
|
165 |
|
166 | ## Caching
|
167 |
|
168 | EJS ships with a basic in-process cache for caching the intermediate JavaScript
|
169 | functions used to render templates. It's easy to plug in LRU caching using
|
170 | Node's `lru-cache` library:
|
171 |
|
172 | ```javascript
|
173 | let ejs = require('ejs'),
|
174 | LRU = require('lru-cache');
|
175 | ejs.cache = LRU(100); // LRU cache with 100-item limit
|
176 | ```
|
177 |
|
178 | If you want to clear the EJS cache, call `ejs.clearCache`. If you're using the
|
179 | LRU cache and need a different limit, simple reset `ejs.cache` to a new instance
|
180 | of the LRU.
|
181 |
|
182 | ## Custom file loader
|
183 |
|
184 | The default file loader is `fs.readFileSync`, if you want to customize it, you can set ejs.fileLoader.
|
185 |
|
186 | ```javascript
|
187 | let ejs = require('ejs');
|
188 | let myFileLoad = function (filePath) {
|
189 | return 'myFileLoad: ' + fs.readFileSync(filePath);
|
190 | };
|
191 |
|
192 | ejs.fileLoader = myFileLoad;
|
193 | ```
|
194 |
|
195 | With this feature, you can preprocess the template before reading it.
|
196 |
|
197 | ## Layouts
|
198 |
|
199 | EJS does not specifically support blocks, but layouts can be implemented by
|
200 | including headers and footers, like so:
|
201 |
|
202 |
|
203 | ```ejs
|
204 | <%- include('header') -%>
|
205 | <h1>
|
206 | Title
|
207 | </h1>
|
208 | <p>
|
209 | My page
|
210 | </p>
|
211 | <%- include('footer') -%>
|
212 | ```
|
213 |
|
214 | ## Client-side support
|
215 |
|
216 | Go to the [Latest Release](https://github.com/mde/ejs/releases/latest), download
|
217 | `./ejs.js` or `./ejs.min.js`. Alternately, you can compile it yourself by cloning
|
218 | the repository and running `jake build` (or `$(npm bin)/jake build` if jake is
|
219 | not installed globally).
|
220 |
|
221 | Include one of these files on your page, and `ejs` should be available globally.
|
222 |
|
223 | ### Example
|
224 |
|
225 | ```html
|
226 | <div id="output"></div>
|
227 | <script src="ejs.min.js"></script>
|
228 | <script>
|
229 | let people = ['geddy', 'neil', 'alex'],
|
230 | html = ejs.render('<%= people.join(", "); %>', {people: people});
|
231 | // With jQuery:
|
232 | $('#output').html(html);
|
233 | // Vanilla JS:
|
234 | document.getElementById('output').innerHTML = html;
|
235 | </script>
|
236 | ```
|
237 |
|
238 | ### Caveats
|
239 |
|
240 | Most of EJS will work as expected; however, there are a few things to note:
|
241 |
|
242 | 1. Obviously, since you do not have access to the filesystem, `ejs.renderFile()` won't work.
|
243 | 2. For the same reason, `include`s do not work unless you use an `include callback`. Here is an example:
|
244 | ```javascript
|
245 | let str = "Hello <%= include('file', {person: 'John'}); %>",
|
246 | fn = ejs.compile(str, {client: true});
|
247 |
|
248 | fn(data, null, function(path, d){ // include callback
|
249 | // path -> 'file'
|
250 | // d -> {person: 'John'}
|
251 | // Put your code here
|
252 | // Return the contents of file as a string
|
253 | }); // returns rendered string
|
254 | ```
|
255 |
|
256 | See the [examples folder](https://github.com/mde/ejs/tree/master/examples) for more details.
|
257 |
|
258 | ### IDE Integration with Syntax Highlighting
|
259 |
|
260 | VSCode:Javascript EJS by *DigitalBrainstem*
|
261 |
|
262 | ## Related projects
|
263 |
|
264 | There are a number of implementations of EJS:
|
265 |
|
266 | * TJ's implementation, the v1 of this library: https://github.com/tj/ejs
|
267 | * EJS Embedded JavaScript Framework on Google Code: https://code.google.com/p/embeddedjavascript/
|
268 | * Sam Stephenson's Ruby implementation: https://rubygems.org/gems/ejs
|
269 | * Erubis, an ERB implementation which also runs JavaScript: http://www.kuwata-lab.com/erubis/users-guide.04.html#lang-javascript
|
270 | * DigitalBrainstem EJS Language support: https://github.com/Digitalbrainstem/ejs-grammar
|
271 |
|
272 | ## License
|
273 |
|
274 | Licensed under the Apache License, Version 2.0
|
275 | (<http://www.apache.org/licenses/LICENSE-2.0>)
|
276 |
|
277 | - - -
|
278 | EJS Embedded JavaScript templates copyright 2112
|
279 | mde@fleegix.org.
|
280 |
|
\ | No newline at end of file |