Skip to content
panosru edited this page Jul 18, 2012 · 9 revisions

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

{% extends "layout.html" %}
{% block body %}
  <ul>
  {% for user in users %}
    <li><a href="{{ user.url }}">{{ user.username }}</a></li>
  {% endfor %}
  </ul>
{% 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 in JinJS, not in Jinja)
  • Head to http://jinja.pocoo.org/ to read the template designer documentation (the API is fairly different).
  • The expressions are in modified Javascript (just to have not, or, and and other syntactic sugar), which means that there are NO tuples. This has the following implications in the {% for %} tag ;
{% 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, call, let, do. We are still missing trans.

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 :

require("jinjs").registerExtension(".tpl" );

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

var my_transormation_module = require("my_module");
require("jinjs").registerExtension(".ext", function (txt) { 
    return my_transformation_module.transform_text(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.

Filters

So far, they are all implemented, minus pprint, format and all the filters regarding automating escaping (safe, forceescape).

There is a new filter : date, which takes a python style formatting argument as specified in http://docs.python.org/library/datetime.html#strftime-and-strptime-behavior . There's a caveat ; we can't get day or month's locale names since javascript does not provide a way to do so without using another library.

Tests

They will come shortly.