Created: 2014-05-19 14:01
Updated: 2014-05-30 15:41
License: mit


razor.js - reverse {{mustache}} templating

A {{mustache}} is nice, but sometimes you're just itching for a razor...

Introducing razor.js, a reverse {{mustache}} templater. Mustache allows you to turn a view model into a rendered view using a mustache template. Razor.js takes the same template and a rendered view, and returns the view model. This is useful for:

  • screen scraping
  • putting xml in its place

Quick example

var mustache = require('mustache');
var razor = require('./razor');

var template = 'foo{{bar}}baz';
// mustache calls this a view
var model = {
    bar: 'bar'

var rendering = mustache.render(template, model);

// now let's reverse it
var model2 = razor.getModel(template, rendering);

console.log('Did it work?', JSON.stringify(model) === JSON.stringify(model2));

Screen scraping

If you can write a template for it, you can scrape it using razor. If you add contenteditable to your templates, you can create a simple editor for your view models:

var template =
'<ul>' +
    '<li>Your name</li>' +
    '<li contenteditable="true">{{name}}</li>' +
    '<li>Your age</li>' +
    '<li contenteditable="true">{{age}}</li>' +
var model = {
    name: 'Please enter your name here',
    age:  'Please enter your age here'

var form = mustache.render(template, model);
    .on('blur', function() {
        model = razor.getModel(template, this);

Putting xml in its place

You probably used mustache already to create some xml to send to the server, right?... Just because xml is so horrible to work with in Javascript. Razor allows you to use the same templates you use for creating xml to also extract the json data from those xml files:

var xml =
'<message>' +
    '<warning>' +
        'Hello World' +
    '</warning>' +
var template =
'<message>' +
    '<warning>{{warning}}</warning>' +

var model = razor.getModel(template, xml);

This is so simple when compared to other xml tooling, I would like to pose this adage:

XML is just a view on the actual model, just like HTML.


The mustache transform throws away information in some cases. Razor cannot reconstruct this information. For example:

// this works fine
var template = 'foo{{bar}}{{baz}}qux';
var model = {
    bar: 'bar',
    baz: 'baz'
var rendering = mustache.render(template, model);

// this does not
var model2 = razor.getModel(template, rendering);

This example doesn't work, because the mustache rendering doesn't show where the {{bar}} mustache ends and the {{baz}} mustache begins. So razor cannot find the model for this rendering.

Luckily, for most HTML and XML templates, this never happens. Just be mindful of this limitation when using razor.

Cookies help us deliver our services. By using our services, you agree to our use of cookies Learn more