README.md
1Embedded JavaScript templates<br/>
2[](https://travis-ci.org/mde/ejs)
3[](https://david-dm.org/mde/ejs?type=dev)
4[](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
35Try EJS online at: https://ionicabizau.github.io/ejs-playground/.
36
37## Basic usage
38
39```javascript
40let template = ejs.compile(str, options);
41template(data);
42// => Rendered HTML string
43
44ejs.render(str, data, options);
45// => Rendered HTML string
46
47ejs.renderFile(filename, data, options, function(err, str){
48 // str => Rendered HTML string
49});
50```
51
52It is also possible to use `ejs.render(dataAndOptions);` where you pass
53everything in a single object. In that case, you'll end up with local variables
54for all the passed options. However, be aware that your code could break if we
55add an option with the same name as one of your data object's properties.
56Therefore, we do not recommend using this shortcut.
57
58### Important
59You should never give end-users unfettered access to the EJS render method, If you do so you are using EJS in an inherently un-secure way.
60
61### Options
62
63 - `cache` Compiled functions are cached, requires `filename`
64 - `filename` The name of the file being rendered. Not required if you
65 are using `renderFile()`. Used by `cache` to key caches, and for includes.
66 - `root` Set template root(s) for includes with an absolute path (e.g, /file.ejs).
67 Can be array to try to resolve include from multiple directories.
68 - `views` An array of paths to use when resolving includes with relative paths.
69 - `context` Function execution context
70 - `compileDebug` When `false` no debug instrumentation is compiled
71 - `client` When `true`, compiles a function that can be rendered
72 in the browser without needing to load the EJS Runtime
73 ([ejs.min.js](https://github.com/mde/ejs/releases/latest)).
74 - `delimiter` Character to use for inner delimiter, by default '%'
75 - `openDelimiter` Character to use for opening delimiter, by default '<'
76 - `closeDelimiter` Character to use for closing delimiter, by default '>'
77 - `debug` Outputs generated function body
78 - `strict` When set to `true`, generated function is in strict mode
79 - `_with` Whether or not to use `with() {}` constructs. If `false`
80 then the locals will be stored in the `locals` object. Set to `false` in strict mode.
81 - `destructuredLocals` An array of local variables that are always destructured from
82 the locals object, available even in strict mode.
83 - `localsName` Name to use for the object storing local variables when not using
84 `with` Defaults to `locals`
85 - `rmWhitespace` Remove all safe-to-remove whitespace, including leading
86 and trailing whitespace. It also enables a safer version of `-%>` line
87 slurping for all scriptlet tags (it does not strip new lines of tags in
88 the middle of a line).
89 - `escape` The escaping function used with `<%=` construct. It is
90 used in rendering and is `.toString()`ed in the generation of client functions.
91 (By default escapes XML).
92 - `outputFunctionName` Set to a string (e.g., 'echo' or 'print') for a function to print
93 output inside scriptlet tags.
94 - `async` When `true`, EJS will use an async function for rendering. (Depends
95 on async/await support in the JS runtime.
96 - `includer` Custom function to handle EJS includes, receives `(originalPath, parsedPath)`
97 parameters, where `originalPath` is the path in include as-is and `parsedPath` is the
98 previously resolved path. Should return an object `{ filename, template }`,
99 you may return only one of the properties, where `filename` is the final parsed path and `template`
100 is the included content.
101
102This project uses [JSDoc](http://usejsdoc.org/). For the full public API
103documentation, clone the repository and run `jake doc`. This will run JSDoc
104with the proper options and output the documentation to `out/`. If you want
105the both the public & private API docs, run `jake devdoc` instead.
106
107### Tags
108
109 - `<%` 'Scriptlet' tag, for control-flow, no output
110 - `<%_` 'Whitespace Slurping' Scriptlet tag, strips all whitespace before it
111 - `<%=` Outputs the value into the template (escaped)
112 - `<%-` Outputs the unescaped value into the template
113 - `<%#` Comment tag, no execution, no output
114 - `<%%` Outputs a literal '<%'
115 - `%%>` Outputs a literal '%>'
116 - `%>` Plain ending tag
117 - `-%>` Trim-mode ('newline slurp') tag, trims following newline
118 - `_%>` 'Whitespace Slurping' ending tag, removes all whitespace after it
119
120For the full syntax documentation, please see [docs/syntax.md](https://github.com/mde/ejs/blob/master/docs/syntax.md).
121
122### Includes
123
124Includes either have to be an absolute path, or, if not, are assumed as
125relative to the template with the `include` call. For example if you are
126including `./views/user/show.ejs` from `./views/users.ejs` you would
127use `<%- include('user/show') %>`.
128
129You must specify the `filename` option for the template with the `include`
130call unless you are using `renderFile()`.
131
132You'll likely want to use the raw output tag (`<%-`) with your include to avoid
133double-escaping the HTML output.
134
135```ejs
136<ul>
137 <% users.forEach(function(user){ %>
138 <%- include('user/show', {user: user}) %>
139 <% }); %>
140</ul>
141```
142
143Includes are inserted at runtime, so you can use variables for the path in the
144`include` call (for example `<%- include(somePath) %>`). Variables in your
145top-level data object are available to all your includes, but local variables
146need to be passed down.
147
148NOTE: Include preprocessor directives (`<% include user/show %>`) are
149not supported in v3.0+.
150
151## Custom delimiters
152
153Custom delimiters can be applied on a per-template basis, or globally:
154
155```javascript
156let ejs = require('ejs'),
157 users = ['geddy', 'neil', 'alex'];
158
159// Just one template
160ejs.render('<p>[?= users.join(" | "); ?]</p>', {users: users}, {delimiter: '?', openDelimiter: '[', closeDelimiter: ']'});
161// => '<p>geddy | neil | alex</p>'
162
163// Or globally
164ejs.delimiter = '?';
165ejs.openDelimiter = '[';
166ejs.closeDelimiter = ']';
167ejs.render('<p>[?= users.join(" | "); ?]</p>', {users: users});
168// => '<p>geddy | neil | alex</p>'
169```
170
171### Caching
172
173EJS ships with a basic in-process cache for caching the intermediate JavaScript
174functions used to render templates. It's easy to plug in LRU caching using
175Node's `lru-cache` library:
176
177```javascript
178let ejs = require('ejs'),
179 LRU = require('lru-cache');
180ejs.cache = LRU(100); // LRU cache with 100-item limit
181```
182
183If you want to clear the EJS cache, call `ejs.clearCache`. If you're using the
184LRU cache and need a different limit, simple reset `ejs.cache` to a new instance
185of the LRU.
186
187### Custom file loader
188
189The default file loader is `fs.readFileSync`, if you want to customize it, you can set ejs.fileLoader.
190
191```javascript
192let ejs = require('ejs');
193let myFileLoad = function (filePath) {
194 return 'myFileLoad: ' + fs.readFileSync(filePath);
195};
196
197ejs.fileLoader = myFileLoad;
198```
199
200With this feature, you can preprocess the template before reading it.
201
202### Layouts
203
204EJS does not specifically support blocks, but layouts can be implemented by
205including headers and footers, like so:
206
207
208```ejs
209<%- include('header') -%>
210<h1>
211 Title
212</h1>
213<p>
214 My page
215</p>
216<%- include('footer') -%>
217```
218
219## Client-side support
220
221Go to the [Latest Release](https://github.com/mde/ejs/releases/latest), download
222`./ejs.js` or `./ejs.min.js`. Alternately, you can compile it yourself by cloning
223the repository and running `jake build` (or `$(npm bin)/jake build` if jake is
224not installed globally).
225
226Include one of these files on your page, and `ejs` should be available globally.
227
228### Example
229
230```html
231<div id="output"></div>
232<script src="ejs.min.js"></script>
233<script>
234 let people = ['geddy', 'neil', 'alex'],
235 html = ejs.render('<%= people.join(", "); %>', {people: people});
236 // With jQuery:
237 $('#output').html(html);
238 // Vanilla JS:
239 document.getElementById('output').innerHTML = html;
240</script>
241```
242
243### Caveats
244
245Most of EJS will work as expected; however, there are a few things to note:
246
2471. Obviously, since you do not have access to the filesystem, `ejs.renderFile()` won't work.
2482. For the same reason, `include`s do not work unless you use an `include callback`. Here is an example:
249 ```javascript
250 let str = "Hello <%= include('file', {person: 'John'}); %>",
251 fn = ejs.compile(str, {client: true});
252
253 fn(data, null, function(path, d){ // include callback
254 // path -> 'file'
255 // d -> {person: 'John'}
256 // Put your code here
257 // Return the contents of file as a string
258 }); // returns rendered string
259 ```
260
261See the [examples folder](https://github.com/mde/ejs/tree/master/examples) for more details.
262
263## CLI
264
265EJS ships with a full-featured CLI. Options are similar to those used in JavaScript code:
266
267 - `-o / --output-file FILE` Write the rendered output to FILE rather than stdout.
268 - `-f / --data-file FILE` Must be JSON-formatted. Use parsed input from FILE as data for rendering.
269 - `-i / --data-input STRING` Must be JSON-formatted and URI-encoded. Use parsed input from STRING as data for rendering.
270 - `-m / --delimiter CHARACTER` Use CHARACTER with angle brackets for open/close (defaults to %).
271 - `-p / --open-delimiter CHARACTER` Use CHARACTER instead of left angle bracket to open.
272 - `-c / --close-delimiter CHARACTER` Use CHARACTER instead of right angle bracket to close.
273 - `-s / --strict` When set to `true`, generated function is in strict mode
274 - `-n / --no-with` Use 'locals' object for vars rather than using `with` (implies --strict).
275 - `-l / --locals-name` Name to use for the object storing local variables when not using `with`.
276 - `-w / --rm-whitespace` Remove all safe-to-remove whitespace, including leading and trailing whitespace.
277 - `-d / --debug` Outputs generated function body
278 - `-h / --help` Display this help message.
279 - `-V/v / --version` Display the EJS version.
280
281Here are some examples of usage:
282
283```shell
284$ ejs -p [ -c ] ./template_file.ejs -o ./output.html
285$ ejs ./test/fixtures/user.ejs name=Lerxst
286$ ejs -n -l _ ./some_template.ejs -f ./data_file.json
287```
288
289### Data input
290
291There is a variety of ways to pass the CLI data for rendering.
292
293Stdin:
294
295```shell
296$ ./test/fixtures/user_data.json | ejs ./test/fixtures/user.ejs
297$ ejs ./test/fixtures/user.ejs < test/fixtures/user_data.json
298```
299
300A data file:
301
302```shell
303$ ejs ./test/fixtures/user.ejs -f ./user_data.json
304```
305
306A command-line option (must be URI-encoded):
307
308```shell
309./bin/cli.js -i %7B%22name%22%3A%20%22foo%22%7D ./test/fixtures/user.ejs
310```
311
312Or, passing values directly at the end of the invocation:
313
314```shell
315./bin/cli.js -m $ ./test/fixtures/user.ejs name=foo
316```
317
318### Output
319
320The CLI by default send output to stdout, but you can use the `-o` or `--output-file`
321flag to specify a target file to send the output to.
322
323## IDE Integration with Syntax Highlighting
324
325VSCode:Javascript EJS by *DigitalBrainstem*
326
327## Related projects
328
329There are a number of implementations of EJS:
330
331 * TJ's implementation, the v1 of this library: https://github.com/tj/ejs
332 * EJS Embedded JavaScript Framework on Google Code: https://code.google.com/p/embeddedjavascript/
333 * Sam Stephenson's Ruby implementation: https://rubygems.org/gems/ejs
334 * Erubis, an ERB implementation which also runs JavaScript: http://www.kuwata-lab.com/erubis/users-guide.04.html#lang-javascript
335 * DigitalBrainstem EJS Language support: https://github.com/Digitalbrainstem/ejs-grammar
336
337## License
338
339Licensed under the Apache License, Version 2.0
340(<http://www.apache.org/licenses/LICENSE-2.0>)
341
342- - -
343EJS Embedded JavaScript templates copyright 2112
344mde@fleegix.org.
345