Kiwi
Simple yet powerful asynchronous JavaScript template engine based on jQuery Template syntax, usable server-side or client-side.
Install / Use
/learn @coolony/KiwiREADME
Kiwi
What is this?
Kiwi is a cool JavaScript template engine lovingly built from the ground up for Node.js with performance, extensibility, modularity and security in mind. It is compatible with most of jQuery Template syntax, and adds lots of features to it. This means Kiwi is:
- Fast. Insanely fast.
- Completely asynchronous. You have the absolute guarantee that not a single blocking call will be done after Kiwi has been initialized.
- Easily extensible. Three short lines of code are enough to create a new tag.
- Incredibly powerful, even for advanced features. Want dynamic template inheritance? Access individual block contents? Done!
- Easy to set up. One line of code and you can get started on Express 3.x. In most cases, you can even use your existing jQuery or jqTpl templates without modification.
- Robust. Kiwi is carefully tested before any change is pushed to the repository.
- Full-featured. Lots of filters are available, and it can't be easier to add your own if you want.
- Secure. All output is escaped by default.
- Clean. Kiwi won't mess with your prototypes, and won't extend any of the built-in JavaScript objects.
- Good looking. Kiwi is tested with JSHint to ensure code quality.
As an additional feature, you can use Kiwi in client mode, with – almost – all features available, except for the few involving the file system.
Syntax example
<!DOCTYPE html>
<html>
<head>
<title>${title}</title>
</head>
<body>
<p>
{{if name}}
Hello, ${name|capitalize}!
{{else}}
Hello, dear unknown!
{{/if}}
</p>
</body>
</html>
Please note this example template expects name and title variables to always be defined.
Server-side installation
Latest release
npm install kiwi
Development version (may not be suited for production [yet])
npm install https://github.com/coolony/kiwi/tarball/master
Client-side installation
Self-hosted
Just include kiwi.min.js, and you're good to go!
Client-side CDN version
Kiwi is also available as a CDN-hosted version, for free, courtesy of CDNJS / CloudFlare.
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/kiwi/0.2.1/kiwi.min.js"></script>
Client-side dependencies
Please note that client-side usage requires Underscore.js to be included in the page. This requirement will be removed in a future release.
Usage
Loading a template from string
var kiwi = require('kiwi');
var template = '<p>Hello, ${name}!</p>';
new kiwi.Template(template).render({ name: "Kiwi" }, function onRendered(err, rendered) {
console.log('Rendered template is: ' + rendered);
});
Loading a template from disk
var kiwi = require('kiwi');
var template = new kiwi.Template().loadFile('template.kiwi', function onLoaded(err) {
template.render({ name: "Kiwi" }, function onRendered(err, rendered) {
console.log('Rendered template is: ' + rendered);
});
});
In order to make the process of loading and rendering a template easier, Kiwi does expose a handy loadAndRendershortcut:
var kiwi = require('kiwi');
var template = new kiwi.Template().loadAndRender('template.kiwi', { name: "Kiwi" }, function onRendered(err, rendered) {
console.log('Rendered template is: ' + rendered);
});
Accessing variables
Every key of the optional object passed as argument to the Template#render method will be made available for use in your template. You can also access your object with $data.
For example, when passing { name: 'Kiwi'}, you will be able to use the name variable in your template, or $data.name.
Available tags
${}
Basic usage
The ${varOrExpression} tag inserts the value of varOrExpression in the template. This is a shortcut for {{= varOrExpression}}.
// Template
<div>${a}</div>
<div>{{= a}}</div>
// Code
new Template(tpl).render({ a: 'kiwi' }, callback);
// Result
<div>kiwi</div>
<div>kiwi</div>
Filter support
The ${} tag optionally supports filters.
// Template
<div>${a|replace('k', 'w')|capitalize}</div>
// Code
new Template(tpl).render({ a: 'kiwi' }, callback);
// Result
<div>Wiwi</div>
Escaping by default
The ${} tag escapes its output by default.
// Template
<div>${a}</div>
// Code
new Template(tpl).render({ a: '<b>kiwi</b>' }, callback);
// Result
<div><b>kiwi</b></div>
You can optionally insert unescaped data by using the special rawfilter.
// Template
<div>${a|raw}</div>
// Code
new Template(tpl).render({ a: '<b>kiwi</b>' }, callback);
// Result
<div><b>kiwi</b></div>
{{if}}
Basic usage
Used for conditional insertion of content. Renders the content between the opening and closing template tags only if the specified data item field, JavaScript function or expression does not evaluate to false (or to zero, null, type "undefined", or the empty string).
// Template
<div>{{if show}}Foo{{/if}}</div>
<div>{{if !show}}Bar{{/if}}</div>
// Code
new Template(tpl).render({ show:true }, callback);
// Result
<div>Foo</div>
<div></div>
Alternatives
{{else}} can be used in association with the {{if}} tag to provide alternative content based on the values of one or more expressions. The {{else}} tag can be used without a parameter, as in {{if a}}...{{else}}...{{/if}}, or with a parameter, as in {{if a}}...{{else b}}...{{/if}}.
// Template
<div>{{if a === 2}}Moo{{else b === 3}}Foo{{else}}Kiwi{{/if}}</div>
// Code
new Template(tpl).render({ a: 1, b: 2 }, callback);
// Result
<div>Kiwi</div>
{{each}}
Basic usage
Used to iterate over a data array, and render the content between the opening and closing template tags once for each data item.
// Template
<ul>
{{each movies}}
<li>${$index|incr}. ${$value}</li>
{{/each}}
</ul>
// Code
new Template(tpl).render({ movies: [ 'Meet Joe Black', 'City Hunter' ] }, callback);
// Result
<ul>
<li>1. Meet Joe Black</li>
<li>2. City Hunter</li>
</ul>
Index and parameter support
The block of template markup between the opening and closing tags {{each}} and {{/each}} is rendered once for each data item in the data array. Within this block the {{each}} template tag exposes the current index and value as additional template variables $index and $value. These default variable names can be changed by passing in index and value parameters to the {{each}} template tag, as in the following example:
// Template
<ul>
{{each(i, name) movies}}
<li>${i|incr}. ${name}</li>
{{/each}}
</ul>
// Code
new Template(tpl).render({ movies: [ 'Meet Joe Black', 'City Hunter' ] }, callback);
// Result
<ul>
<li>1. Meet Joe Black</li>
<li>2. City Hunter</li>
</ul>
Loop counters
By default, Kiwi sets a number of variables available within the loop:
$each.size: The number of items in the collection$each.counter: The current iteration of the loop (1-indexed)$each.counter0: The current iteration of the loop (0-indexed)$each.revcounter: The number of iterations from the end of the loop (1-indexed)$each.revcounter0: The number of iterations from the end of the loop (0-indexed)$each.first:trueif this is the first time through the loop$each.last:trueif this is the last time through the loop$each.parent: For nested loops, this is the loop "above" the current one$each.parentIndex: For nested loops, this is the current index of the parent loop$each.parentValue: For nested loops, this is the current value of the parent loop
// Template
<ul>
{{each(i, name) movies}}
<li>${$each.counter}. ${name}</li>
{{/each}}
</ul>
// Code
new Template(tpl).render({ movies: [ 'Meet Joe Black', 'City Hunter' ] }, callback);
// Result
<ul>
<li>1. Meet Joe Black</li>
<li>2. City Hunter</li>
</ul>
In order to maintain compatibility with earlier Kiwi releases, _eachLoop is provided as an alias for $each, and $each.parentLoop as an alias for $each.parent. This will be dropped in a future release.
Empty clause
The {{each}} tag can take an optional {{ empty }} clause that will be displayed if the given collection is empty:
// Template
<ul>
{{each(i, name) movies}}
<li>${name}</li>
{{empty}}
<li>No movies found…</li>
{{/each}}
</ul>
// Code
new Template(tpl).render({ movies: [] }, callback);
// Result
<ul>
<li>No movies found…</li>
</ul>
{{as}}
The template markup between the opening and closing tags {{as}} and {{/as}} is not rendered in the document, but instead saved in a variable for later use.
// Template
{{as foo}}Kiwi{{/as}}
<div>${foo}</div>
// Code
new Template(tpl).render({}, callback);
// Result
<div>Kiwi</div>
{{tmpl}}
Used for composition of templates. Renders a nested template from a string within the rendered output of the parent template.
// Template
<div>{{tmpl nested}}</div>
// Code
new Template(tpl).render({ nested: '${a}', a: 'Kiwi' }, callback);
// Result
<div>Kiwi</div>
{{include}}
Used for composition of templates. It renders a nested template within the rendered output of the current template.
Loading nested template from disk
// foo.kiwi
Hello!
// Template
<div>{{include "foo"}}</div>
// Code
new Template(tpl).render({}, callback);
// Result
<div>Hello!</div>
Using directly another Template instance
// Template 1
Hello!
// Template 2
<div>{{include nested}}</div>
// Code
var nested = new Template(tpl1);
new Template(tpl2).render({ nested: nested }, callba

