Coder Social home page Coder Social logo

ejs's Introduction

EJS

Embedded JavaScript templates.

Build Status


NOTE: Version 2 of EJS makes some breaking changes with this version (notably, removal of the filters feature). Work on v2 is happening here: https://github.com/mde/ejs

File issues for EJS v2 here: https://github.com/mde/ejs/issues


Installation

$ npm install ejs

Features

  • Complies with the Express view system
  • Static caching of intermediate JavaScript
  • Unbuffered code for conditionals etc <% code %>
  • Escapes html by default with <%= code %>
  • Unescaped buffering with <%- code %>
  • Supports tag customization
  • Filter support for designer-friendly templates
  • Includes
  • Client-side support
  • Newline slurping with <% code -%> or <% -%> or <%= code -%> or <%- code -%>

Example

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

Try out a live example now

Usage

ejs.compile(str, options);
// => Function

ejs.render(str, options);
// => str

Options

  • cache Compiled functions are cached, requires filename
  • filename Used by cache to key caches
  • scope Function execution context
  • debug Output generated function body
  • compileDebug When false no debug instrumentation is compiled
  • client Returns standalone compiled function
  • open Open tag, defaulting to "<%"
  • close Closing tag, defaulting to "%>"
    •             All others are template-local variables
      

Includes

Includes are relative to the template with the include statement, for example if you have "./views/users.ejs" and "./views/user/show.ejs" you would use <% include user/show %>. The included file(s) are literally included into the template, no IO is performed after compilation, thus local variables are available to these included templates.

<ul>
  <% users.forEach(function(user){ %>
    <% include user/show %>
  <% }) %>
</ul>

Custom delimiters

Custom delimiters can also be applied globally:

var ejs = require('ejs');
ejs.open = '{{';
ejs.close = '}}';

Which would make the following a valid template:

<h1>{{= title }}</h1>

Filters

EJS conditionally supports the concept of "filters". A "filter chain" is a designer friendly api for manipulating data, without writing JavaScript.

Filters can be applied by supplying the : modifier, so for example if we wish to take the array [{ name: 'tj' }, { name: 'mape' }, { name: 'guillermo' }] and output a list of names we can do this simply with filters:

Template:

<p><%=: users | map:'name' | join %></p>

Output:

<p>Tj, Mape, Guillermo</p>

Render call:

ejs.render(str, {
    users: [
      { name: 'tj' },
      { name: 'mape' },
      { name: 'guillermo' }
    ]
});

Or perhaps capitalize the first user's name for display:

<p><%=: users | first | capitalize %></p>

Filter list

Currently these filters are available:

  • first
  • last
  • capitalize
  • downcase
  • upcase
  • sort
  • sort_by:'prop'
  • size
  • length
  • plus:n
  • minus:n
  • times:n
  • divided_by:n
  • join:'val'
  • truncate:n
  • truncate_words:n
  • replace:pattern,substitution
  • prepend:val
  • append:val
  • map:'prop'
  • reverse
  • get:'prop'

Adding filters

To add a filter simply add a method to the .filters object:

ejs.filters.last = function(obj) {
  return obj[obj.length - 1];
};

Layouts

Currently EJS has no notion of blocks, only compile-time includes, however you may still utilize this feature to implement "layouts" by simply including a header and footer like so:

<% include head %>
<h1>Title</h1>
<p>My page</p>
<% include foot %>

client-side support

include ./ejs.js or ./ejs.min.js and require("ejs").compile(str).

License

(The MIT License)

Copyright (c) 2009-2010 TJ Holowaychuk <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

ejs's People

Contributors

1602 avatar der-on avatar domachine avatar forbeslindesay avatar fshost avatar glsh-machine avatar isaacs avatar iwillwen avatar jacksontian avatar jgallen23 avatar jkingyens avatar jonnsl avatar josh avatar jtsay362 avatar mako-taco avatar mde avatar mhemesath avatar seanmonstar avatar slaskis avatar stash avatar tj avatar zerowidth 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

Option to require leading whitespace (space, tab or newline)

Problem

Custom open / close tags like <? and ?> introduce conflicts between other XML processing information tags. These custom tags will attempt to incorrectly parse <?xml ?> or <?something-else ?> as embedded JavaScript.

The same situation also applies to custom tags like <?js and ?> because these could conflict with another special PI like <?jsnode ?> (if that were to exist).

Proposed Solution

Add an option that enforces a white space character immediately after the default open template tag.

The option would mean that the following combinations could be used:

<? if (something) { ?>
   <strong>Yay!</strong>
<? } ?>

<h1><?=page.title?></h1>

<?-page.body?>

Example Usage

var compiled = ejs.compile(tmpl, {
    open                : '<?',
    close               : '?>',
    leadingWhiteSpace   : true
});

Altered EJS Source

function quoteForRegex(str) {
  return str.replace(/([.?*+^$[\]\\(){}-])/g, "\\$1");
}

var parse = exports.parse = function(str, options){
  var options = options || {}
    , open = options.open || exports.open || '<%'
    , close = options.close || exports.close || '%>';

  var buf = [
      "var buf = [];"
    , "\nwith (locals) {"
    , "\n  buf.push('"
  ];

  var lineno = 1;

  var openRegex = new RegExp('^' + quoteForRegex(open) + ( options.leadingWhiteSpace ? '[\\-\\=\\s]' : '[\\-\\=]?' ));

  for (var i = 0, len = str.length; i < len; ++i) {
    var istr = str.substr(i, open.length + 2);
    if (openRegex.test(istr)) {
      var prefix, postfix, line = '__stack.lineno=' + lineno;
      switch (istr[ open.length ]) {
        case '=':
          prefix = "', escape((" + line + ', ';
          postfix = ")), '";
          i += 1 + open.length;
          break;
        case '-':
          prefix = "', (" + line + ', ';
          postfix = "), '";
          i += 1 + open.length;
          break;
        default:
          prefix = "');" + line + ';';
          postfix = "; buf.push('";
          i += open.length;
          break;
      }

      var end = str.indexOf(close, i)
        , js = str.substring(i, end)
        , start = i
        , n = 0;

      while (~(n = js.indexOf("\n", n))) n++, lineno++;
      if (js.substr(0, 1) == ':') js = filtered(js);
      buf.push(prefix, js, postfix);
      i += end - start + close.length - 1;
    }
    else {
      switch (istr[0]) {
        case '\\':
          buf.push("\\\\");
          break;
        case '\'':
          buf.push("\\'");
          break;
        case '\r':
          buf.push(" ");
          break;
        case '\n':
          buf.push("\\n");
          lineno++;
          break;
        default:
          buf.push(istr[0]);
          break;
      }
    }
  }

  buf.push("');\n}\nreturn buf.join('');");
  return buf.join('');
};

escape method of utils breaks rich text editing on second pass

There is code in the escape method to be clever and prevent double-escaping:

.replace(/&(?!\w+;)/g, '&')

Unfortunately, if you're discussing HTML in a rich text editor, you're going to deliberately write things like:

<textarea>...</textarea>

Which need to be double-escaped when you output them again to be edited again. Otherwise the rich text editor sees them as rich markup and not as text talking about rich markup.

Double-escape prevention as a default behavior that can't be overridden is problematic.

I'm going to see what happens if I write a custom alwaysEscape filter and use <%-.

Add custom tag support

OK this is completely a personal preference but I love using <? like PHP over <% like JAVA, its just easier to type. I wonder if ejs could allow for the ability to declare your own "tag" type? or give the option for php style tags.

HTML escape code

[ejs.js : 525]

exports.escape = function(html){
(snip ...)
.replace(/&(?!\w+;)/g, '&')
(snip ...)
};

Why is rgExp "/&(?!\w+;)/g" ?
Is it "/&(?#\w+;)/g" ?
! -> #

Windows line endings with multiline strings causes invalid output with includes

Hello,

I just noticed if I include a javascript file with Windows-style line endings through the include syntax that happens to contain a multiline string such as:
var foo = '
bar';

it's outputted wrong as EJS is translating each instance of \r to a space character in the output generated inside of parse.

I'm not sure what the purpose of the space substitution is so I have no idea as to a proper fix, but I wanted to at least leave a bug report.

feature-request: allow monkey-patching on ejs.parse function

It would be great to use exports.parse inside library instead of parse (local function), because it would allow to monkey-patching on parse function behavior. In my case I only need to add one expression in generated function: arguments.callee.buf = buf;

So I do it via monkey-patch:

var ejs = require('ejs'), old_parse = ejs.parse;
ejs.parse = function () {
    var str = old_parse.apply(this, Array.prototype.slice.call(arguments));
    return str.replace('var buf = [];', 'var buf = []; arguments.callee.buf = buf;');
};

But it is not works at the mo, because in compile function used parse function instead of exports.parse. So, I would happy if I can monkey-patch parse function.

Suggested code:

var compile = exports.compile = function(str, options){
    if (options.debug) sys.puts(exports.parse(str));
    var fn = new Function('locals, filters, escape', exports.parse(str, options));
    return function(locals){
        return fn.call(this, locals, filters, utils.escape);
    }
};

conflicts with colon

Hi there,

I was encountered the issue about the conflicts with ejs filter expression, eg:
one expression with the content:
<%=: varObj | dateformat 'yyyy-MM-dd hh:mm:ss' %>
and the first colon with the tag "<%=:" is the filter tag in ejs, but the customized filter which named as "dateformat" will accept the format string some like the pattern "yyyy-MM-dd hh:mm:ss", and the format pattern string have the colons also as the parameter which will be passed into the filter function, so ejs will give the error stack info as:
"500 SyntaxError: Unexpected token : "

So, it is just a advice that to enable the customized the filter express tag with ejs template file in ejs engine configurations.

Thanks,
-Harrison

Better error reporting for syntax errors

The error reporting that ejs does have is really nice, and makes it easy to track down things like undefined variables and so forth.

However, it is lacking when It comes to reporting syntax errors:

<% if(true) {
        <p>Uh oh... forgot to close the statement!</p>
<% } %>

SyntaxError: Unexpected token <
    at Object.Function (unknown source)
    at Object.compile (/Users/pselden/Documents/express-test/node_modules/ejs/lib/ejs.js:199:12)
    at Function.compile (/Users/pselden/Documents/express-test/node_modules/express/lib/view.js:65:33)

Is there any way to improve upon those types of errors and possibly report the line number where it failed on?

feature request - include/require ability

one feature i miss from jsp/php is the ability to include/require additional files and have them inserted into the current file... not sure what would be a good syntax, but wanted to throw that out there

include is either fundamentally broken or not sufficiently documented

Hi!

I'm using the include keyword in a base template to include whatever template I want to be on the page. It looks like so:

<!doctype html>
<html>
    <head>
        <title>MAWG - <%= pageName %></title>
    <link rel="stylesheet" href="/css/style.css" />
    <% if ( tplHead && tplHead !== '' ) { %>
            <%= tplHead %>
    <% } %>
    </head>
    <body>
        <% if ( tplBody && tplBody !== '' ) { %>
            <% include tplBody %>
    <% } %>
    </body>
</html>

Sadly, because the include keyword assumes that whatever happens after it is a string, not a variable, I get

Error: ENOENT, no such file or directory '/home/marktraceur/projects/mawg/src/templates/tplBody.ejs'

Clearly this is wrong. Inside of the <% %> block, there shouldn't be fudging of the JS syntax. Besides that, there should be a way to include arbitrary templates inside of others.

I would also settle for a way to extend templates, like in the Jinja2 system of Python fame. But that seems like a lot more work.

Cheers!

Doesn't work with require.js

I don't think this works with requirejs on the client-side, because require() is redefined here. Trying to require() it with requirejs returns an undefined.

Broken require('some-view.ejs');

I got this error when trying to require('something.ejs'). As far as I understand this call should return compiled view?

module.js:375
  content = content.replace(/^\#\!.*/, '');
                    ^
TypeError: Object function (locals){
    return fn.call(this, locals, filters, utils.escape);
  } has no method 'replace'
    at Module._compile (module.js:375:21)
    at Object.require.extensions..ejs (/usr/local/lib/node_modules/ejs/lib/ejs.js:336:12)

Issue rendering a javascript template

When trying to render a javascript template that uses ejs for certain reasons I get this error:

deps/express/lib/express/view.js:246
            throw err;
            ^
SyntaxError: Unexpected identifier
    at Object.Function (unknown source)
    at deps/express/support/ejs/lib/ejs.js:89:12
    at Object.render (deps/express/support/ejs/lib/ejs.js:119:14)
    at ServerResponse.render (deps/express/lib/express/view.js:262:26)
    at /Users/seth/projects/buntin/pilot/src/pilot/node/server.js:36:25
    at /Users/seth/projects/buntin/pilot/src/pilot/node/lib/pilot.js:30:13
    at [object Object].<anonymous> (/Users/seth/projects/buntin/pilot/src/pilot/node/deps/node-mongodb-native/lib/mongodb/collection.js:373:35)
    at [object Object].emit (events:32:26)
    at [object Object].<anonymous> (/Users/seth/projects/buntin/pilot/src/pilot/node/deps/node-mongodb-native/lib/mongodb/db.js:77:12)
    at [object Object].emit (events:25:26)

Spec Layouts/Includes/Partials

#35 Is becoming a little unproductive because of all the +1s, if you have an interest and want to watch the discussion then please select watching thread at the bottom. Only comment if you have an opinion about what the API should be, or how it should be implemented.

I want to have a thread to tie down the spec and how we want to implement these features then if @visionmedia agrees with the proposal, I'll write the implementation and submit a pull request.

Syntax

<% extends('layout/path.ejs') %>
<%- include('child-template-path.ejs') %>
<%- include('child-template-path.ejs', {locals:object}) %>

This is easier to parse than a new syntax version, and we can still read these at compile time. We would only allow string literals for path names, and not support the use of copies of extends/include (i.e. <% var e = extends; %><% e('foo.ejs') %> would not be valid and neither would <% extends('foo' + extension) %>)

Functionality

Path resolution

Path names should be relative to the current file path. If no extension is provided, we use the extension of the current file, which we read from options.filename.

It is possible to override the entire resolution of a path to the file contents by providing options.fileLoader. The default implementation of this would look something like:

var path = require('path');
var fs = require('fs');

/**
 * Load the contents of a file
 * 
 * @param {string} source      The source template requesting include/layout
 * @param {string} destination The file path to resolve and load
 * @param {function(exception, string)} callback
 */
function fileLoader(source, destination, callback) {
  fs.readFile(path.resolve(source, destination), 'utf8', callback);
}

We can make this asynchronous because we only call it at compilation time. I think it is worthwhile to support overriding this as it would allow for template rendering on the client and where templates may be stored in a database or somewhere else entirely.

Extends

Extends takes the parent template as an argument, the parent template should get the same locals as the child template. In addition though, it should have access to the content of the client template. There are 2 options for how we do this:

Option 1

Provide the result of rendering the child template as the local contents to the parent template.

Pros:

  • Simple to understand
  • Good match for express pre v3.
  • Simple to implement

Cons:

  • Limited: It's difficult to have the child provide more than one block of content (e.g. providing Main content and sidebar navigation content)

Option 2

Provide a syntax for specifying a block of content, which could then be used in the parent. It could be done such that all content of the child that was not in a block of some sort was then available to the parent template as contents, making this option compatible with Option 1

Proposal

I would propose that we implement Option 1 first, then extend it to support Option 2, maintaining backwards compatibility with the simpler Option 1.

Includes

Includes takes either 1 or 2 arguments. The first argument is the relative path to the child template to include. This is processed by the fileLoader (see Path Resolution above). The second optional argument is the locals to be provided to the include. If the second argument is undefined or not provided, then the locals of the calling template are used instead.

Implementation

TODO

Stringify a Template / Production-ready code

We have a use-case where we'd want ejs templates compiled into a function string, rather than into a function. This would allow us to assign the template result to a namespace and ship a collection of templates without including ejs as a dependency.

In addition, these types of compiled formats shouldn't include line numbers or rethrow functionality.

This would be supported through two attributes on the options object: stringify and production.

I've taken a first crack at implementing these features into a fork:

https://github.com/clintandrewhall/ejs

I'd love your opinion on this, and if this is a good start to this functionality? If it's appropriate, I'll continue working on it as a pull request.

Thanks!

include statement

doing a "npm install" with ejs version 0.7.2 does not provide the latest files.
doing so there is no support in the parser for the "include" statement

the exemple <% include user/show %> won't work

pulling via git works

can you update the npm package so we get same result

thx

data passed to ejs.render not defined, causes error

I have replicated a problem using the example code off the front page of this project. Data passed into ejs.render are throwing an error when referenced in a template.

Code:

var ejs = require('ejs');
var util = require('util');

// var tmpl = "<p><%=: users | map:'name' | join %></p>"
var tmpl = "<ul> <% users.forEach(function(user){ %> <li><%= user.name %></li> <% }) %> </ul>";
util.log(ejs.render(tmpl, {
    users: [
      { name: 'tj' },
      { name: 'mape' },
      { name: 'guillermo' }
    ]
}));

Error:

tippy:gulp davidherron$ node tt.js 

undefined:24
  throw err;
        ^
ReferenceError: ejs:1
 >> 1| <ul> <% users.forEach(function(user){ %> <li><%= user.name %></li> <% }) %> </ul>

users is not defined
    at eval (eval at <anonymous> (/Users/davidherron/node_modules/ejs/lib/ejs.js:198:12))
    at exports.compile (/Users/davidherron/node_modules/ejs/lib/ejs.js:200:15)
    at Object.exports.render (/Users/davidherron/node_modules/ejs/lib/ejs.js:235:13)
    at Object.<anonymous> (/Users/davidherron/boilerplate/gulp/tt.js:6:14)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.runMain (module.js:492:10)
    at process.startup.processNextTick.process._tickCallback (node.js:244:9)

<%=body%>

When I use:
<%=body%>

I get an error saying it can't find the "bod" variable

When I use
<%=body %>

I don't get an error. Not having a space causes the last character in the variable name to be truncated. Implementations such as JSP allow for no space yet correct parsing. Could this get fixed?

Best way to have EJS layout/partials in Express 3?

Trying to get up to speed with Express 3 and one of the biggest changes is removing layouts and partials. This has implications for EJS, since EJS doesn't natively have a layout/partial/block feature (as far as I can tell or figure out).

For straight html we can just use fs.readFile and pass the utf8 string as a local. But, that doesn't work if we want dynamic partials.

How can we achieve layouts/partials using EJS and Express 3?

[documentation] On the client-side, variables must be in the 'locals' option

While trying to use EJS on the client side, I reproduced the example from https://github.com/visionmedia/ejs/blob/master/examples/client.html, but it didn't work. The variables I passed to the render() function weren't passed to the template:

<html>
  <head>
    <script src="../ejs.js"></script>
    <script id="users" type="text/template">
      <% if (names.length) { %>
        <ul>
          <% names.forEach(function(name){ %>
            <li><%= name %></li>
          <% }) %>
        </ul>
      <% } %>
    </script>
    <script>
      onload = function(){
        var users = document.getElementById('users').innerHTML;
        var names = ['loki', 'tobi', 'jane'];
        var html = require('ejs').render(users, { names: names });
        document.body.innerHTML = html;
      }
    </script>
  </head>
  <body>
  </body>
</html>

With this template, the console complained that the names variable wasn't defined when interpreting the template.

After fiddling with the EJS source code, I found out that variables would only be passed to the template if they were under the localsoption, so the line:

        var html = require('ejs').render(users, { names: names });

should be replaced by:

        var html = require('ejs').render(users, { locals: { names: names }});

...for the example to work.

Or did I miss something?

Explain quote issue/workaround in readme

I think the readme should explain that " and ' can't be used in template content and a recommended workaround for each unusable character, such as โ€™.

This will help save a lot of time for first-time users.

fitlers with blocks

I have a block I'm override in layout template:

<% block('title', owner + "'s list" %> which will produce "Bill's list"

I want to use a filter here though that I created called 'possessive' which will add the apostrophe s properly (ie: Wes would become Wes' instead of Wes's)

I can echo it find, but how would I use a filter with a block value?

<%=: owner | possessive %>

Document ejs.renderFile() method

The method renderFile() method is not documented in Readme.md file.

Please advise if this is not the best place to report this kind of issues.

Thanks.

feature-request: provide a clear and update-proof mechanism for adding filters

using ejs 0.4.3 I currently don't know better than to do

require('ejs').filters['my_filter'] = function(){}

This seems quite messy to me, and forces me to rely on the implementation of the filters rather than an api concealing this implementation.

If this way currently exists, it is not documented, and it would be nice if this feature could be better explained in the documentation.

regards,

Extra new lines added

I have a template:

A list of famous people:
<% names.forEach(function (name) { %>
name: <%= name %>
<% } %>

Which generates:

A list of famous people:

name: Alexander

name: Bruce

name: Ceasar

name: David

Could the new lines be removed?

Custom open/close tags not passing to included files

Related to:
expressjs/express#1287

In express:
app.locals.open = '[%';
app.locals.close = '%]';

That seemed to work on the top level view, but included views it doesn't apply to. For example, I have in index.html

[%-include users/login.html %]

in login.html I have some [% %] code blocks, but they are not being recognized.

(note: using ejs as the extension also produces this problem)

feature-request: Rewrite SyntaxException if template compiling fails

It would be notice to be better informed which template snippet failed to be parsed (e.g. missing bracket inside the template). index.js ll130 should be look like

var compile = exports.compile = function(str, options){
if (options.debug) sys.puts(parse(str));

try {  
var fn = new Function('locals, filters, escape', parse(str, options));
}
catch (e) {
if (e instanceof SyntaxError) {
    throw new SyntaxError("Failed to parse script [" + options.filename + "] with content [\n" + str + "\n]: " + e);
}

throw e;
}

return function(locals){
    return fn.call(this, locals, filters, utils.escape);
}

};

Can't check for undefined locals

I can't do typeof someUndefinedLocal == 'undefined' because that will give me an error output saying, "someUndefinedLocal is undefined". Normally, I would be able to do this in JS just fine. If EJS is truely "Embedded JavaScript" then it should at least act like it. For now I have to use typeof this.someUndefinedLocal == 'undefined', but I really wish didn't.

ejs partials views

Hey TJ, I know this isn't an issue but can't find anything answering my question on Google.

With express 3 and EJS, is there away to do layouts and loading of partials similar to jade in EJS.

for example:

extends layout

block content
    include some/other/view

feature request - default filter

Hi, thanks for working on EJS. The following filter has proven useful to me when dealing with possibly undefined keys:

exports.default = function(str, val) {return str || val || '';}

Allows you to use something like this in your template so you don't output 'undefined':

<%=: obj.key | default:'N/A' %>
<%=: obj.key | default %>

Print to buffer within code

I would like to conditionally print something in my template, eg:

<% if (condition) print(formatter.formatCost(cost)) %>

Currently the best way to achieve this appears to be:

<% if (condition) { %><%= print(formatter.formatCost(cost) %><% } %>

As you can see, it's convenient to have something like underscore's print().

Escaping differences between express and client versions.

I'm having troubles reusing my express templates on the client. Specifically, I can't figure out how to render partials in a way that works for both express and the client. I think the major issue is that express auto-escapes everything with <%= and doesn't for <%-. The regular verion just seems to only support <% and doesn't escape anything.

I prefer how express does it, but it would really be beneficial to reuse the server side express templates on the client. Is it possible to make the express EJS implementation work client side or is there a way to render partials that is consistent on both he client and server?

layout not rendered

my code

var express = require('express');
var ejs = require('ejs').__express;
var app = express();

app.engine('html',ejs); 
app.set('views',__dirname + '/views');
app.set('view engine','ejs'); 

app.get('/',function (req,res) {
    res.render('home.html',{title:'Math Wizard'});
});

just rendered 'home.html'...

Thx for answer!

Better Error Catching

I get errors like the following a lot.

ReferenceError: foobar is not defined
at IncomingMessage.anonymous (eval at <anonymous> (/usr/local/lib/node/.npm/ejs/0.3.0/package/lib/ejs/index.js:139:14))
at IncomingMessage.<anonymous> (/usr/local/lib/node/.npm/ejs/0.3.0/package/lib/ejs/index.js:141:19)
at Object.render (/usr/local/lib/node/.npm/ejs/0.3.0/package/lib/ejs/index.js:176:13)
at ServerResponse.render (/usr/local/lib/node/.npm/express/1.0.7/package/lib/express/view.js:334:22)
at ServerResponse.render (/usr/local/lib/node/.npm/express/1.0.7/package/lib/express/view.js:344:10)
at Object.<anonymous> (/home/Holmes/myproject/controllers/home.js:4:6)
at param (/usr/local/lib/node/.npm/connect/0.5.8/package/lib/connect/middleware/router.js:146:21)
at pass (/usr/local/lib/node/.npm/connect/0.5.8/package/lib/connect/middleware/router.js:162:10)
at Object.router [as handle] (/usr/local/lib/node/.npm/connect/0.5.8/package/lib/connect/middleware/router.js:168:6)
at next (/usr/local/lib/node/.npm/connect/0.5.8/package/lib/connect/index.js:218:15)

And this is because somewhere in my template files foobar is not defined. However, I do not know where this error is occurring. I don't even know which template file it is that is referencing foobar! Surely there must be a way to catch these errors and display at least the template file that is causing the error.

Right now ejs/index.js take the blame for these errors because ejs is the file that is executing the template file code. So, my vague idea on a solution would be to wrap the code that executes the template in a try...catch statement, and in the catch, be sure to write out the template filename that's causing there error, along with as much information about there as plausible.

override a variable in layout?

I have a layout.ejs that looks like this:

h1 <%= title %> /h1

I have the page template that gets passed title, however I'm wondering if I can just set the title in the page template instead.

res.render('/page', { title: "My Title" });

Is it possible to just set this title in page.ejs somehow such that it overrides the title or sets the title in layout.ejs?
This way I don't have to continuously pass the title whenever I call res.render(/page).

Feature Request: Add a global toggle to turn include off

It's kind of weird asking for the feature of turning a feature off, I know, but I built up a system to handle includes and template inheritance and the new syntax for includes breaks my include function (or rather, tries to replace it). I was wondering if you could put some kind of toggle such that ejs won't look for the include syntax anymore if set to true.

I'm partial to my system for three main reasons:

  1. I'm trying to keep the templating language purely javascript, with no extra syntax.
  2. Your built in include syntax doesn't allow for variables (all assumed to be string values).
  3. The relative and absolute paths in my system are specified to be within a certain subset of folders, and I don't want the user accessing files from outside of them (which, as far as I can tell, the include syntax would allow).

Cannot get 0.7.3 through npm or git link

Looks like the version number is up to 0.7.3.

On npm it's still on 0.7.1, so no newer version can be fetched.
Using the git link in package.json, the master branch somehow installs 0.7.2, so not sure abut that either

Better client side support.

The current example shows using the script tag to house your ejs templates, which means you have to load all your ejs templates at once. Would be much better if we could lazy load them from the client when needed and cache them.

I wrote a quick piece of code that uses ejs on the client along with jquery to do this:

http://pastie.org/4898961

Would something like this be easy to include in ejs or would you rather we just write it ourselves like I did above?

Thanks,

Brian

feature request - new line suppression

What would be great is to have new-line suppression, like ERB:
<%="test"-%>
and
<% ... %>

The - before the closing tag signals that no new line should be appended.
This is very handy to keep your code + HTML code clean.

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.