1. ravelsoft
  2. node-jinjs


Clone wiki

node-jinjs / Home


As stated on Jinja's home page, "Jinja Is Beautiful"

{% extends "./layout.html" %}
{% block body %}
  {% for user in users %}
    <li><a href="{{ user.url }}">{{ user.username }}</a></li>
  {% endfor %}
{% endblock %}

JinJS is the native port of Jinja to the world of NodeJS. Just like Jinja, it aims to transform template documents to native javascript code to maximize execution speed.

It is not a 100% exact copy of Jinja however, and is still in early stages.

So far, the principal differences are :

  • You can't have variables with javascript reserved names
  • It is probably much more permissive ; you can assign to compound expressions ({% let foo.bar = something %} is valid)
  • Head to http://jinja.pocoo.org/ to read the template designer documentation (the API is fairly different).
  • The {% for %} tag is very different due to differences between JS and Python ;
{% for value in array %}
    Use {{ loop.index }} or {{ loop.index0 }} for the indexes
{% endfor %}

{% for key, value in object %}
    This will iterate on *ANY* object.
{% endfor %}

The following tags are implemented almost like the real thing : for, if, elseif, extends, block, import, include, macro, let, do. We are still missing call.

The following tags are not in jinja : {% abspath "my/path" %} will return the absolute path on your filesystem of my/path relative to the current file. Useful when generating HTML documents later converted to PDF (like with wkhtmltopdf or princexml).

The following filters are implemented : in, abs, capitalize, default, filesizeformat, first, last, join, length, lower, upper, replace, reverse, round, trim. The others should follow

How To Use

npm install jinjs

With templates as modules

To have node load your templates as if they were modules, you first have to register your module extension :


If you want your file to be transformed prior to being submitted to jinjs, you can pass a callback ;

var pwilang = require("pwilang");
require("jinjs").registerExtension(".pwx", function (txt) { 
    return pwilang.parse(txt); 

You can now write :

var my_template = require("./mytemplate");
var context = { foo: "foo", bar: "bar" };
var result = my_template.render(context);

Use With Browserify

Since JinJS can be used by require-ing the templates, it's dead easy to include them in your client-side projects with the excellent browserify module.

var de = require("jinjs").defaultEnvironment;
var browserifier = require("browserify")();
browserifier.register({ extension: ".tpl", wrapper: function (body, file) {
    return de.getTemplateSourceFromString(body);

Use With Express

JinJS is fully compatible with Express, with a few twists ;

You can have your template-text preprocessed before submitting it to the JinJS machine : use the view options jinjs_pre_compile with a function that takes one string argument and returns its processed version.

This can of course be used per-template or globally as with all the view options in Express.

app.set("view options", { jinjs_pre_compile: function (str) { return parse_pwilang(str); } });

The other fairly important point is that since JinJS provides extend/import/include-ing capabilities, it is very recommanded to forget the whole "layout" option of Express altogether.

This should always be done :

app.set("view options", layout: false);

Also, partial() is fairly useless when one has the {% for %} tag with {% include %}, since the current context is always given to include ;

{# base template of a blog post #}
{% extends "base.jinjs" %}
{{ blog_contents }}
{% for comment in comments %}
    {% include "comment.jinjs" %}
{% endfor %}

The comment file ;

{# the comment.jinjs file #}
{{ comment.user }} said : {{ comment.comment }}.

In short, you are allowed to forget about layout and partial altogether, although you can always use them if so you wish.