node-t

0.1.0 • Public • Published

Node-T

A fast django-like templating engine for node.js.

Node-T is a templating engine inspired by the django syntax. It has a few extensions and the templates are compiled to native javascript functions which make them really fast. For now it's synchronous, but once a template is read and compiled, it is cached in memory.

Example template code

<html>
<body>
  <h1>Example</h1>
  {% for name in names %}
    <p>
      {{forloop.counter}}
      {# This is a comment #}
      {{name}}{% if name == "Django" %} Reinhardt{% end %}
    </p>
  {% end %}
</body>
</html>

Example node code

var template  = require('node-t');
var tmpl = template.fromFile("/path/to/template.html");
console.log( tmpl.render({names: ["Duke", "Django", "Louis"]}) );

How it works

Node-T reads template files and translates them into javascript functions using the Function constructor. When we later render a template we call the evaled function passing a context object as an argument. This makes the rendering very fast. The template tags are defined as strings of Javascript code - which is a bit ugly, but there are helpers that will make writing tags easier for you.

The slots system will allow you to define your own HTML snippets that will be rendered with a special context.

The API

You have 2 methods for creating a template object:

var template = require('node-slots');
template.fromFile("path/to/template/file.html");
template.fromString("Template string here");

Both of them will give you a template object on which you call the render method passing it a map of context values.

var tmpl = template.fromFile("path/to/template/file.html");
var renderdHtml = tmpl.render({});

Template syntax

You should be familiar with the 1"Django template syntax". Here I'll just sum up the diferences:

  • There are no filters implemented yet
  • Tags like {% for %} and {% if %} are closed with a simple {% end %} tag
  • Not all tags are implemented
  • Some extra tags are implemented
  • Syntax for some tags is a bit different.

Here's a list of currently implemented tags:

Variable tags

Used to print a variable to the template. If the variable is not in the context we don't get an error, rather an empty string. You can use dot notation to access object proerties or array memebers.

<p>First Name: {{users.0.first_name}}</p>

Comment tags

Comment tags are simply ignored. Comments can't span multitple lines.

{# This is a comment #}

Logic tags

extends / block

Check django's template inheritance system for more info. Unlike django, the block tags are terminated with {% end %}, not with {% endblock %}

include

Includes a template in it's place. The template is rendered within the current context. Does not requre closing with {% end %}.

{% include template_path %}
{% include "path/to/template.js" %}

for

You can iterate arrays and objects. Access the current iteration index through 'forloop.index' which is available inside the loop.

{% for x in y %}
  <p>{% forloop.index %}</p>
{% end %}

if

Supports the following expressions. No else tag yet.

{% if x %}{% end %}
{% if !x %}{% end %}
{% if x operator y %}
  Operators: ==, !=, <, <=, >, >=, ===, !==, in
  The 'in' operator checks for presence in arrays too.
{% end %}
{% if x == 'five' %}
  The operands can be also be string or number literals
{% end %}

slot

Slots are parts of a page that where you want highly customized content that depends heavily on dynamic data. They work in pair with widget functions that you can write yourself.

Template code

<div>
  {% slot main %}
</div>
<div>
  {% slot sidebar %}
</div>

Node.js code

context.slots = {
  main: [
    "<h1>This is a paragraph as a normal string.</h1>", // String
    
    { tagname: 'analytics',   // Widget object
      uaCode: 'UA-XXXXX-X' },
  ],
  
  sidebar: [
    "<h3>Navigation</h3>",    // String
    
    { tagname: 'navigation',  // Widget object
      links: [
        '/home',
        '/about',
        '/kittens'
      ]}
  ]
}

context.widgets = {
  analytics: function(context){
    // this inside widget functions is bound to the widget object
    return "<script>..." + this.uaCode + "...</script>";
  },
  navigation: function(context){
    var i, html = "";
    for( i=0; i<this.links; i++ )
      html += "<a href='" + links[i] + "'>" + links[i] + "</a>";
    return html;
  }
}

template.render(context)

Result

<div>
  <h1>This is a paragraph as a normal string.</h1>
  <script>...UA-XXXXX-X...</script>
</div>
<div>
  <h3>Navigation</h3>
  <a href='/home'>/home</a>
  <a href='/about'>/about</a>
  <a href='/kittens'>/kittens</a>
</div>

Readme

Keywords

none

Package Sidebar

Install

npm i node-t

Weekly Downloads

4

Version

0.1.0

License

none

Last publish

Collaborators

  • skid