Templating With Narwhal Server-Side JavaScript and Json-Template
By Ryan Florence, published 2010-06-11
Part of the issue Migrated Articles From Original Site Structure..
Server-side JavaScript is all the rage. Here’s a practical application of JavaScript that I used today. I needed to populate a bunch of html files with some data so I did it with narwhal and json-template. But what’s really cool about templating with json is that many web services are now delivering data with json, so you can take the data exactly how it is and create your templates, server-side and client-side.
Download
Here’s a download of the code in this article if you’d like.
Installing Narwhal and json-template
If you’re on a mac, and have homebrew installed, just do this:
$ brew install narwhal
The end. For everybody else, visit narwhaljs.org because I have no idea.
Now to get json-template installed:
$ tusk install json-template
Directory setup
I’ve got a folder with some files that looks like this:
json-templating/
dictionary.json
playlist.html.jt
render.js
The template playlist.html.jt
For these examples I’m using the code from json-template’s website, with a few adjustments and iterations. Also, I have no idea if it’s common practice to name the templates name.html.jt
but I like it.
<html>
<head><title>{title}</title>
<body>
{# This is a comment and will be removed from the output.}
<h2>Songs in '{playlist-name}'</h2>
<table width="100%">
{.repeated section songs}
<tr>
<td><a href="{url-base|htmltag}{url|htmltag}">Play</a>
<td><i>{title}</i></td>
<td>{artist}</td>
</tr>
{.end}
</table>
</body>
</html>
This looks similar to other templating languages except it doesn’t have a whole lot to it. Instead of recreating stuff like for loops it simply has the “repeated section” idea.
The JSON Dictionary
{
"title": "JSON Templating is cool",
"url-base": "http://example.com/music/",
"playlist-name": "Epic Playlist",
"songs": [
{
"url": "1.mp3",
"artist": "Grayceon",
"title": "Sounds Like Thunder"
},
{
"url": "2.mp3",
"artist": "Thou",
"title": "Their Hooves Carve Craters in the Earth"
}
]
}
The script to make it all happen
var FS = require('file'),
JSON = require('json'),
JT = require('json-template');
// open the template file and the JSON
template = FS.read('playlist.html.jt');
dictionary = JSON.decode(FS.read('dictionary.json'))
// the expand method is all we need
html = JT.expand(template, dictionary);
// write it to a file
FS.write('output.html', html);
Now in the terminal you can just do
$ js render.js
Congratulations, Bro! You’ve now got a file called output.html
that looks like this:
<html>
<head><title>JSON Templating is cool</title>
<body>
<h2>Songs in 'Epic Playlist'</h2>
<table width="100%">
<tr>
<td><a href="http://example.com/music/1.mp3">Play</a>
<td><i>Sounds Like Thunder</i></td>
<td>Grayceon</td>
</tr>
<tr>
<td><a href="http://example.com/music/2.mp3">Play</a>
<td><i>Their Hooves Carve Craters in the Earth</i></td>
<td>Thou</td>
</tr>
</table>
</body>
</html>
The .or declaration
Maybe our dictionary doesn’t have a songs
key. Our last script assumed that it did. This is a common problem when templating, how to handle empty data. Check out this template:
<html>
<head><title>{title}</title>
<body>
{# This is a comment and will be removed from the output.}
{.section songs}
<h2>Songs in '{playlist-name}'</h2>
<table width="100%">
{.repeated section @}
<tr>
<td><a href="{url-base|htmltag}{url|htmltag}">Play</a>
<td><i>{title}</i></td>
<td>{artist}</td>
</tr>
{.end}
</table>
{.or}
<p><em>(No page content matches)</em></p>
{.end}
</body>
</html>
We’ve got a new “section” called songs. If there is a songs
key then it’s going to go ahead and expand that section, if there is not a songs
key then it will move down to the or
and expand that instead. Pretty awesome. Next up, we’ve got the repeated section
inside of songs
where we use an @
to point to each song (since we’re already in a songs
section.)
Note that we’ve got a title
key at the top level (the title of the html page) and a title
key for each song. The song’s title wins when inside of the repeated section. I’m not sure how to access the higher level title
inside of there, maybe you know?
Lastly, note the {url-base|htmltag}
. There are a handful of formatters shipped with json-template: html
, htmltag
, html-attr-value
, str
, raw
, AbsUrl
, plain-url
.
Conclusion
With JSONP and ajax being big parts of our lives, I think it’s awesome to be able to use the same templating language on the server or the client. The declarative design makes json-template ridiculously simple to work with. Give it a shot today.