Giter VIP home page Giter VIP logo

ejs's Introduction

Embedded JavaScript templates
Known Vulnerabilities

Security

Security professionals, before reporting any security issues, please reference the SECURITY.md in this project, in particular, the following: "EJS is effectively a JavaScript runtime. Its entire job is to execute JavaScript. If you run the EJS render method without checking the inputs yourself, you are responsible for the results."

In short, DO NOT submit 'vulnerabilities' that include this snippet of code:

app.get('/', (req, res) => {
  res.render('index', req.query);
});

Installation

$ npm install ejs

Features

  • Control flow with <% %>
  • Escaped output with <%= %> (escape function configurable)
  • Unescaped raw output with <%- %>
  • Newline-trim mode ('newline slurping') with -%> ending tag
  • Whitespace-trim mode (slurp all whitespace) for control flow with <%_ _%>
  • Custom delimiters (e.g. [? ?] instead of <% %>)
  • Includes
  • Client-side support
  • Static caching of intermediate JavaScript
  • Static caching of templates
  • Complies with the Express view system

Example

<% if (user) { %>
  <h2><%= user.name %></h2>
<% } %>

Try EJS online at: https://ionicabizau.github.io/ejs-playground/.

Basic usage

let template = ejs.compile(str, options);
template(data);
// => Rendered HTML string

ejs.render(str, data, options);
// => Rendered HTML string

ejs.renderFile(filename, data, options, function(err, str){
    // str => Rendered HTML string
});

It is also possible to use ejs.render(dataAndOptions); where you pass everything in a single object. In that case, you'll end up with local variables for all the passed options. However, be aware that your code could break if we add an option with the same name as one of your data object's properties. Therefore, we do not recommend using this shortcut.

Important

You 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.

Options

  • cache Compiled functions are cached, requires filename
  • filename The name of the file being rendered. Not required if you are using renderFile(). Used by cache to key caches, and for includes.
  • root Set template root(s) for includes with an absolute path (e.g, /file.ejs). Can be array to try to resolve include from multiple directories.
  • views An array of paths to use when resolving includes with relative paths.
  • context Function execution context
  • compileDebug When false no debug instrumentation is compiled
  • client When true, compiles a function that can be rendered in the browser without needing to load the EJS Runtime (ejs.min.js).
  • delimiter Character to use for inner delimiter, by default '%'
  • openDelimiter Character to use for opening delimiter, by default '<'
  • closeDelimiter Character to use for closing delimiter, by default '>'
  • debug Outputs generated function body
  • strict When set to true, generated function is in strict mode
  • _with Whether or not to use with() {} constructs. If false then the locals will be stored in the locals object. Set to false in strict mode.
  • destructuredLocals An array of local variables that are always destructured from the locals object, available even in strict mode.
  • localsName Name to use for the object storing local variables when not using with Defaults to locals
  • rmWhitespace Remove all safe-to-remove whitespace, including leading and trailing whitespace. It also enables a safer version of -%> line slurping for all scriptlet tags (it does not strip new lines of tags in the middle of a line).
  • escape The escaping function used with <%= construct. It is used in rendering and is .toString()ed in the generation of client functions. (By default escapes XML).
  • outputFunctionName Set to a string (e.g., 'echo' or 'print') for a function to print output inside scriptlet tags.
  • async When true, EJS will use an async function for rendering. (Depends on async/await support in the JS runtime.
  • includer Custom function to handle EJS includes, receives (originalPath, parsedPath) parameters, where originalPath is the path in include as-is and parsedPath is the previously resolved path. Should return an object { filename, template }, you may return only one of the properties, where filename is the final parsed path and template is the included content.

This project uses JSDoc. For the full public API documentation, clone the repository and run jake doc. This will run JSDoc with the proper options and output the documentation to out/. If you want the both the public & private API docs, run jake devdoc instead.

Tags

  • <% 'Scriptlet' tag, for control-flow, no output
  • <%_ 'Whitespace Slurping' Scriptlet tag, strips all whitespace before it
  • <%= Outputs the value into the template (escaped)
  • <%- Outputs the unescaped value into the template
  • <%# Comment tag, no execution, no output
  • <%% Outputs a literal '<%'
  • %%> Outputs a literal '%>'
  • %> Plain ending tag
  • -%> Trim-mode ('newline slurp') tag, trims following newline
  • _%> 'Whitespace Slurping' ending tag, removes all whitespace after it

For the full syntax documentation, please see docs/syntax.md.

Includes

Includes either have to be an absolute path, or, if not, are assumed as relative to the template with the include call. For example if you are including ./views/user/show.ejs from ./views/users.ejs you would use <%- include('user/show') %>.

You must specify the filename option for the template with the include call unless you are using renderFile().

You'll likely want to use the raw output tag (<%-) with your include to avoid double-escaping the HTML output.

<ul>
  <% users.forEach(function(user){ %>
    <%- include('user/show', {user: user}) %>
  <% }); %>
</ul>

Includes are inserted at runtime, so you can use variables for the path in the include call (for example <%- include(somePath) %>). Variables in your top-level data object are available to all your includes, but local variables need to be passed down.

NOTE: Include preprocessor directives (<% include user/show %>) are not supported in v3.0+.

Custom delimiters

Custom delimiters can be applied on a per-template basis, or globally:

let ejs = require('ejs'),
    users = ['geddy', 'neil', 'alex'];

// Just one template
ejs.render('<p>[?= users.join(" | "); ?]</p>', {users: users}, {delimiter: '?', openDelimiter: '[', closeDelimiter: ']'});
// => '<p>geddy | neil | alex</p>'

// Or globally
ejs.delimiter = '?';
ejs.openDelimiter = '[';
ejs.closeDelimiter = ']';
ejs.render('<p>[?= users.join(" | "); ?]</p>', {users: users});
// => '<p>geddy | neil | alex</p>'

Caching

EJS ships with a basic in-process cache for caching the intermediate JavaScript functions used to render templates. It's easy to plug in LRU caching using Node's lru-cache library:

let ejs = require('ejs'),
    LRU = require('lru-cache');
ejs.cache = LRU(100); // LRU cache with 100-item limit

If you want to clear the EJS cache, call ejs.clearCache. If you're using the LRU cache and need a different limit, simple reset ejs.cache to a new instance of the LRU.

Custom file loader

The default file loader is fs.readFileSync, if you want to customize it, you can set ejs.fileLoader.

let ejs = require('ejs');
let myFileLoad = function (filePath) {
  return 'myFileLoad: ' + fs.readFileSync(filePath);
};

ejs.fileLoader = myFileLoad;

With this feature, you can preprocess the template before reading it.

Layouts

EJS does not specifically support blocks, but layouts can be implemented by including headers and footers, like so:

<%- include('header') -%>
<h1>
  Title
</h1>
<p>
  My page
</p>
<%- include('footer') -%>

Client-side support

Go to the Latest Release, download ./ejs.js or ./ejs.min.js. Alternately, you can compile it yourself by cloning the repository and running jake build (or $(npm bin)/jake build if jake is not installed globally).

Include one of these files on your page, and ejs should be available globally.

Example

<div id="output"></div>
<script src="ejs.min.js"></script>
<script>
  let people = ['geddy', 'neil', 'alex'],
      html = ejs.render('<%= people.join(", "); %>', {people: people});
  // With jQuery:
  $('#output').html(html);
  // Vanilla JS:
  document.getElementById('output').innerHTML = html;
</script>

Caveats

Most of EJS will work as expected; however, there are a few things to note:

  1. Obviously, since you do not have access to the filesystem, ejs.renderFile() won't work.
  2. For the same reason, includes do not work unless you use an include callback. Here is an example:
let str = "Hello <%= include('file', {person: 'John'}); %>",
    fn = ejs.compile(str, {client: true});

fn(data, null, function(path, d){ // include callback
  // path -> 'file'
  // d -> {person: 'John'}
  // Put your code here
  // Return the contents of file as a string
}); // returns rendered string

See the examples folder for more details.

CLI

EJS ships with a full-featured CLI. Options are similar to those used in JavaScript code:

  • -o / --output-file FILE Write the rendered output to FILE rather than stdout.
  • -f / --data-file FILE Must be JSON-formatted. Use parsed input from FILE as data for rendering.
  • -i / --data-input STRING Must be JSON-formatted and URI-encoded. Use parsed input from STRING as data for rendering.
  • -m / --delimiter CHARACTER Use CHARACTER with angle brackets for open/close (defaults to %).
  • -p / --open-delimiter CHARACTER Use CHARACTER instead of left angle bracket to open.
  • -c / --close-delimiter CHARACTER Use CHARACTER instead of right angle bracket to close.
  • -s / --strict When set to true, generated function is in strict mode
  • -n / --no-with Use 'locals' object for vars rather than using with (implies --strict).
  • -l / --locals-name Name to use for the object storing local variables when not using with.
  • -w / --rm-whitespace Remove all safe-to-remove whitespace, including leading and trailing whitespace.
  • -d / --debug Outputs generated function body
  • -h / --help Display this help message.
  • -V/v / --version Display the EJS version.

Here are some examples of usage:

$ ejs -p [ -c ] ./template_file.ejs -o ./output.html
$ ejs ./test/fixtures/user.ejs name=Lerxst
$ ejs -n -l _ ./some_template.ejs -f ./data_file.json

Data input

There is a variety of ways to pass the CLI data for rendering.

Stdin:

$ ./test/fixtures/user_data.json | ejs ./test/fixtures/user.ejs
$ ejs ./test/fixtures/user.ejs < test/fixtures/user_data.json

A data file:

$ ejs ./test/fixtures/user.ejs -f ./user_data.json

A command-line option (must be URI-encoded):

./bin/cli.js -i %7B%22name%22%3A%20%22foo%22%7D ./test/fixtures/user.ejs

Or, passing values directly at the end of the invocation:

./bin/cli.js -m $ ./test/fixtures/user.ejs name=foo

Output

The CLI by default send output to stdout, but you can use the -o or --output-file flag to specify a target file to send the output to.

IDE Integration with Syntax Highlighting

VSCode:Javascript EJS by DigitalBrainstem

Related projects

There are a number of implementations of EJS:

License

Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)


EJS Embedded JavaScript templates copyright 2112 [email protected].

ejs's People

Contributors

akhoury avatar bloodyknuckles avatar dependabot[bot] avatar der-on avatar dgofman avatar exe-boss avatar gabrielmancini avatar jbielick avatar kengoldfarb avatar kieran avatar kurokikaze avatar larzconwell avatar leomp12 avatar mde avatar miguelmadero avatar mikedevita avatar mjgs avatar molda avatar na-sa-do avatar nwoltman avatar pekpon avatar phanect avatar robertkowalski avatar ryanzim avatar scasei avatar techwraith avatar timothygu avatar trott avatar troyastorino avatar vwkd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ejs's Issues

Next release: EJS 2.0.9/2.1.0

This issue is basically a question of the version and contents that will be in the next release. In our changelog, I have separated out two commits that might be better if we put it in another minor release (i.e. 2.1.0). So the question now is, should we just release a 2.1.0 with all changes since 2.0.8, or a 2.0.9 with bugfixes then 2.1.0?

would you give a full example to show how to use include with expressjs?

I write the code like this
res.render('admin/user', { title: 'AB', description: "AB", categories: [{},{}],user:{},cur:"user"},{filename:'admin/user'});

and html file as ejs like this
.
.
.
<% include sidebar.html %>
.
.
but it do not work.

also remove the {filename:'admin/user'} it still do not work.

How to replace filter functionnality

Hello,

Due to release upgrade my code don't work anymore due to this piece of code:
ejs.filters.toLocaleDateString = function(d) {...}

I wonder how to replace the filters fonctionnality that was in V1 ?
Have a guide line for doing that ?

Thank's in advance,

Jean-Marc

Document release process

There is a Jake task for performing a release jake publish (using a Jake builtin) that automatically bumps the version number, etc. This should be documented somewhere so people don't make manual changes to the version in package.json file, etc.

Allow Completely Custom Delimiters

When we upgraded to latest EJS, we lost the ability to do tempting the way we'd set up previously with:

ejs.open = '{{';
ejs.close = '}}';

Is this planning on being supported eventually? Would you consider a PR for this or is there a technical reason that delimiters now work only inside < and > tags?

Remove template caching

This whole file caching thing is lame. We already cache the compiled functions. Why cache the file content?

No dedicated documentation

I am sure this is on someone's TODO list but just adding a bug to track it. By dedicated documentation, I mean a website with all the API methods, options, etc., like Jade's.

Add support for compile-time `with()`

One of the major bottlenecks in the execution of template functions is the use of with () {} construct, which is not even supported in JavaScript strict mode. To work around this, some (most of my performance-critical) projects use the _with option to disable the use of with () {} in template scripts and use locals.variable instead of variable in EJS files.

Recently, it has come to my attention that there is a module with that scans the source for undeclared variables and adds a shim for it, all at compile-time. This has two major effects and one side effect:

  1. compile speed is a lot slower
  2. runtime speed is a lot faster
  3. undeclared variables are not recognized as errors but instead resolve to undefined, which then resolve to the empty string

Compilation benchmark:

ejs v2 old x 28,709 ops/sec ยฑ0.09% (101 runs sampled)
ejs v2 new x 1,343 ops/sec ยฑ1.83% (96 runs sampled)

(21 x slower)

Template benchmark:

ejs v2 old x 160,036 ops/sec ยฑ1.11% (100 runs sampled)
ejs v2 old !_with x 680,884 ops/sec ยฑ0.43% (98 runs sampled)
ejs v2 new x 631,878 ops/sec ยฑ0.40% (102 runs sampled)
ejs v2 new !_with x 675,687 ops/sec ยฑ0.46% (100 runs sampled)

(395% old, 94% !_with)

I am certainly against enable this by default, as the performance regression caused by it is way too big. But do people think it's worth adding an option for? Also how about implicitly enabling this option when caching is enabled?

Note that the with module uses acorn, which might be undesirable for users using the browser to render EJS, but I can easily use a conditional to filter that out when browserifying.

using "include" keyword un-delimited causes odd error

okay, this is a weird issue so bare with me. i'm attempting to use EJS to output jade templates. when trying to do so, i uncovered a very peculiar bug that has something to do with how EJS includes are being interpreted.

i've created an example to demonstrate the weirdness - http://runnable.com/VSwsiwZIeMpRgeDw

the basic info

trying to render template that includes the words include un-delimited with <% %> or any EJS template tags causes an error UNLESS there is other content on the preceding line.

some details

it looks like including the include keyword triggers EJS to evaluate it like it's a regular <% include %> even when it's not within the template tags. this issue goes away if you put some content on the preceding line. this indicates to me that there is something wrong with how you are scanning for includes but i truly don't know enough about the internals of EJS to diagnose it.

Please let me know if I can clarify anything beyond the example link i've provided - http://runnable.com/VSwsiwZIeMpRgeDw

Issue parsing '//' string literal

This line does not parse correctly with this library, instead it throws the error "Unexpected identifier":

<% var root = location.protocol + '//' + location.host %>

Current workaround is to replace the '//' string constant with an escaped '//' (or '/' + '/' also works). I suspect that the global double-slash search-and-replace comment stripping at ejs.js#L471 is not considering this edge case properly.

ejs with v0.11.14 Error: Identifier 'rethrow' has already been declared

$ node --version 
$ v0.11.14

some.js

var ejs = require('ejs'); 
$ node --harmony some.js

Error

SyntaxError: Identifier 'rethrow' has already been declared
    at exports.runInThisContext (vm.js:73:16)
    at Module._compile (module.js:443:25)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (/Users/mdemo/work/code/lark-views/ejs.js:9:11)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)

Breaking changes.

Etherpad packages JSON has it's requirement as >1.0.0.. By releasing 2+ you broke things.

That's fine, but what you didn't do was given us time to get deprecated notices sorted.. Afaik you didn't even provide a version w/ notices saying methods would be deprecated..

Please re-release a new version that has support for V1 and maybe give us a few months to change our packages to reflect the v2 api..

The way you did this is kinda shitty just FYI ;\

ether/etherpad-lite#2437 (comment)

Layout support

I've started to implement layout support for ejs and before I go too far down the rabbit hole I thought it would be worthwhile to get some feedback.

In my fork of the repo I have started to add some test file for the possible layout syntax. The idea behind the syntax is based off of Laravel's templating engine.

I have put together a few example use cases that will need to be tested against.

Layout files

Use cases

What do you think?

Error: Unknown encoding in Node.js 0.8

I tried to update the Express test suite to use ejs 2.2.4, but there were suddenly a lot of failures with Error: Unknown encoding

Partial stack trace:

Error: Unknown encoding
    at Buffer.toString (buffer.js:440:13)
    at Object.fs.readFileSync (fs.js:241:33)
    at handleCache (/home/travis/build/strongloop/express/node_modules/ejs/lib/ejs.js:75:19)
    at View.exports.renderFile [as engine] (/home/travis/build/strongloop/express/node_modules/ejs/lib/ejs.js:195:14)
    at View.render (/home/travis/build/strongloop/express/lib/view.js:9:2917)

Looks like it's coming from https://github.com/mde/ejs/blob/v2.2.4/lib/ejs.js#L75 , which is not using fs.readFileSync correctly (at least in Node.js 0.8).

Did ejs drop Node.js 0.8 compatibility suddenly without a major version bump? It looks like there was a note in the 2.1.1.

Let me know if you're going to support Node.js 0.8. If not, I'll look for another templating engine.

Add an option to ignore all unneeded whitespace

Benchmarking shows that sometimes too many

__output += "        \n";

will have a very negative effect on performance. It is also one of the major reasons why doT is much faster than EJS, even though theoretically EJS is simpler.

New line slurping does get rid of the new line, but then you still have

__output += "        ";

Cannot include files from root directory

I have an ejs file that i'm rendering through express say hello.ejs. The views folder structure is views/site/test/hello.ejs

I have the following snippet inside the hello.ejs file

<%- include('/partials/site/templates/navbar.html'); %>

Currently this doesn't work. I can't include files from the views directory.

The current work around i see is going to the parent directory and giving the path

<%- include('../../../partials/course/templates/navbar.html'); %>

It'd be useful to allow include from root dir.

TypeError: fs.readFileSync is not a function

I'm trying to run EJS strictly in a browser, no Node.js. Here's my code:

ejs.renderFile('/wishabi/tag/templates/tag_pane', {
  item: feature.item,
  displayTypes: this.mapData.displayTypes,
  qcMode: $j('#qc_mode').is(':checked')
}, {client: true}, function(template) {
  $('#tag-body').html(template);
});

When I run this, the result is "TypeError: fs.readFileSync is not a function". Looking at ejs.js in the latest release, I see no definition of this function anywhere, although it's called multiple times from the code. Is something broken?

Inconsistent behavior on undefined object property reference

Minimal test:

require('ejs').render('<%- data.test %>', {data:{}})

In ejs <=1.0.0, this returns '' (empty string).
In ejs 2.x, this returns 'undefined'.

This breaks some existing templates, so unless there's an intentional reason to make this breaking change (and it's clearly documented), I would like to see consistency with the <=1.0.0 behavior.

Support for blocks

Is it possible to have any support for blocks?

ejs-locals provides a block function, but it's not nice, because it takes a string as block content, I'd rather use EJS/HTML in a block, not have to write it as string...

Something like this:
tj/ejs#142

I'm looking for a feature similar to content_for in Ruby.

Client mode virtually unusable in real world

There are two big design mistakes (IMO) in the implementation of the client mode:

  1. .compile() returns a function, not a string
    • I cannot think of any occasion that returning a client function in function form would ever be helpful. All tests for client mode uses a .toString().
    • Jade returns a string.
  2. The current API does not allow changing the function name of the output function, making it impossible to have more than one functions in a webpage without manual var thisIsTheNameIWant = eval(str)
    • This is extremely awkward for users who want to embed their function string in a HTML data- attribute.
    • Jade fixes this making options.name represent the name of the function.
    • Currently the output function is called anonymous(), which is plain stupid (Jade uses template()).

Both of these points cannot be done without breaking backward compat.

Make `resolveInclude()` overridable

Migrated from tj/ejs#170, opened by @dresende.

If this function could be exported (to be replaced), I (and others) could overwrite it to be able to dynamically accept other include paths and possibly other crazy stuff. I had to do this and to achieve it I had to replace exports.parse (without changing it) to then be able to create my own resolveInclude.

This is just a tiny cool feature, not that I can't live without it..

Outputing plain `<%%` doesn't work

This works:

require('./lib/ejs').render('<%% %>')
// => '<% %>'

This doesn't:

require('./lib/ejs').render('<%% ')
// => Error: Could not find matching close tag for "<%%".
// =>     at /home/timothy_gu/ejs/lib/ejs.js:364:19
// =>     at Array.forEach (native)
// =>     at generateSource (/home/timothy_gu/ejs/lib/ejs.js:352:15)
// =>     at compile (/home/timothy_gu/ejs/lib/ejs.js:281:12)
// =>     at Object.exports.compile (/home/timothy_gu/ejs/lib/ejs.js:133:16)
// =>     at Object.exports.render (/home/timothy_gu/ejs/lib/ejs.js:177:18)

Make renderFile pseudo-async

Right now the callback passed to renderFile is called synchronously, which might be surprising to the users.

Wrapping the calls to the callback in process.nextTick() should be enough.

options found in locals object. The option(s) is copied to the option object. This behavior is deprecated and will be removed in EJS 3

Why locals is deprecated, any workaround in the future?

function cpOptsInData(data, opts) {
  _OPTS.forEach(function (p) {
    if (typeof data[p] != 'undefined') {
      if (!optInDataWarned) {
        console.warn('options found in locals object. The option(s) is '
                   + 'copied to the option object. This behavior is '
                   + 'deprecated and will be removed in EJS 3');
        optInDataWarned = true;
      }
      opts[p] = data[p];
    }
  });
}

Multi line comments break rendering

There doesn't seem to be any way of commenting out certain pieces of code spanning multiple lines. For instance this code throws an error Could not find matching close tag for "<%".:

<% /*if (true) { %>
    <p>hello</p>
<% }*/ %>

..as does this one:

<% /*
    <% if (true) { %>
        <p>hello</p>
    <% } %>
*/ %>

..and even this breaks:

<%# /*
    <% if (true) { %>
        <p>hello</p>
    <% } %>
*/ %>

Not being able to use block comments is very inconvenient. Sometimes it's useful to experiment with a few versions of code without completely deleting it or having to move it outside of the file.

A simple way of fixing this would be adding support for standard block comments - e.g. when a <% /* tag is found, EJS would search for a matching */ %> or perhaps adding a multi-line comment tag `<%## ... #%>'.

Track dependencies

It would be really useful if ejs offered a way to get a list of the dependencies for a file when compiling it. This would enable recompiling only when some files have changed. Ideally this would work roughly the same as jade's support for this feature.

Include in client side?

I might be misunderstanding this, but question about #68 - if I can't render a file on the client side, does that mean that I can't include another template this way - i.e. I can't replicate partials?

E.g. this:

<%= include('my_file', {foo: 'bar'}) %>

is simply not usable client-side? Is there some way to specify a second inline template perhaps?

Smaller client functions

I intend to precompile some simple templates to a javascript source file for browser.(https://github.com/teambition/gulp-ejs-template)

I test file ./test/fixtures/messed.ejs:

<ul><%users.forEach(function(user){%><li><%=user.name%></li><%})%></ul>

use {client:true, compileDebug:false}, get a result, it is too fat. Any chance I pull request to improve it (remove include, move escape and rethrow out of function)?

function template(locals, escape, include, rethrow) {
  escape = escape || function(markup) {
    // Handle stupid JS `undefined` and `null`
    // Yes, we want double-equal here to catch both
    // jshint eqnull: true
    if (markup == null) {
      return '';
    }
    return String(markup)
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/'/g, '&#39;')
      .replace(/"/g, '&quot;');
  };
  rethrow = rethrow || function rethrow(err, str, filename, lineno) {
    var lines = str.split('\n'),
      start = Math.max(lineno - 3, 0),
      end = Math.min(lines.length, lineno + 3);

    // Error context
    var context = lines.slice(start, end).map(function(line, i) {
      var curr = i + start + 1;
      return (curr == lineno ? ' >> ' : '    ') + curr + '| ' + line;
    }).join('\n');

    // Alter exception message
    err.path = filename;
    err.message = (filename || 'ejs') + ':' + lineno + '\n' + context + '\n\n' + err.message;

    throw err;
  };
  var __output = "";
  with(locals || {}) {;
    __output += "<ul>";;
    users.forEach(function(user) {;
      __output += "<li>";;
      __output += escape(user.name);
      __output += "</li>";;
    });
    __output += "</ul>";
  };
  return __output.trim();
}

Support for full file paths in includes?

Is there anyway to pass a full path instead of a relative one to an Include?

We have the code split into different components. Since Express now supports multiple views folders there is no problem there, but when we want to include an ejs from another component (such as common header for a page) we have to things like <% include ../../../../../components/header.ejs%> which looks horrible.

I've created a function to get all the views, extract the full path and transform something like
<%- include(getView('components/header.ejs')); %> into <%- include ('/projectpath/common/components/header.ejs');%>

However since full paths are not supported this obviously doesn't work. Is there a workaround for it? Is this going to be supported at some point in the future?

Crash on missing file

The following code tries to render a file that does not exist:

ejs.renderFile(__dirname + '/app/index.html.ejs')

...but you can't discern that from the resulting error message:

./node_modules/ejs/lib/ejs.js:213
      var tmpl = data.toString().trim();
                      ^
TypeError: Cannot call method 'toString' of undefined
    at ./node_modules/ejs/lib/ejs.js:213:23
    at fs.js:207:20
    at Object.oncomplete (fs.js:107:15)

The problem lies in this library's code using data before it checks for err:

    read(path, function (err, data) {
      var tmpl = data.toString().trim();
      if (err) {
        return cb(err);
      }
      if (opts.cache) {
        templateCache[path] = tmpl;
      }
      handleTemplate(tmpl);
    });

Remove v2 branch?

ejs v2 has already been published to npm, and the v2 branch has already been fully merged into master. Therefore I think it should be removed now.

New async renderFile causes subtle bugs in other libraries

The change introduced in #53 causes havoc with all libraries which monitor whether res.end was called (by proxying it).

For example, express-session monitors res.end calls in order to commit the session.

Also, CompoundJS will only continue routing if a controller called res.end.

The latter caused a problem in my applications, because I had several routes and a "catch-all" route for 404 errors at the end. What happened now was that for every request, the correct controller rendered its view by calling "renderFile" and then "next", but then, because renderFile is now async, CompoundJS didn't detect a res.end call and resumes routing. It now triggers my 404 route. The 404 route also renders a view. Then the first view is actually sent, then the second one - now crashing with "headers already sent".

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.