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.

Hi, I'm Ryan!

Location:
South Jordan, UT
Github:
rpflorence
Twitter:
ryanflorence
Freenode:
rpflo

About Me

I'm a front-end web developer from Salt Lake City, Utah and have been creating websites since the early 90's. I like making awesome user experiences and leaving behind maintainable code. I'm active in the JavaScript community writing plugins, contributing to popular JavaScript libraries, speaking at conferences & meet-ups, and writing about it on the web. I work as the JavaScript guy at Instructure.