Search code examples
underscore.jsunderscore.js-templating

underscore interpolate settings


I'm trying to use handlebars style templating with underscore in backbone (with require.js). I have the following:

_.templateSettings.interpolate = /\{\{(.+?)\}\}/g;

In my templates I have set up a test:

<div><%= title %> | {{ title }}</div>

I get the following in the browser:

Correct title | {{ title }}

So it looks like the standard underscore template settings are working and the handlebars style ones are getting ignored:

But if I check in the console in chrome I get this (which looks to me like it should be correct)

_.templateSettings
Object {evaluate: /<%([\s\S]+?)%>/g, interpolate: /\{\{(.+?)\}\}/g, escape: /<%-([\s\S]+?)%>/g}

Any ideas why this isn't working correctly?


Solution

  • When I do this:

    _.templateSettings.interpolate = /\{\{(.+?)\}\}/g;
    var t = _.template($('#t').html());
    

    with your template in #t, I get an error:

    SyntaxError: Unexpected token '='

    That nicely confirmed my suspicion that the evaluate regex:

    /<%([\s\S]+?)%>/g
    

    was matching your <%= ... %> in the template. An equals sign matches \S so of course the evaluate regex will find <%= ... %>, strip off the <% and %>, and leave you with a syntax error in the JavaScript that _.template will try to build.

    If you look inside the _.template source you'll see that the regexes are checked in a particular order:

    1. escape
    2. interpolate
    3. evaluate

    So just replacing interpolate will let the <%= ... %> things fall through to be caught (and misinterpreted) by evaluate.

    All you need to do is replace the evaluate regex as well. I'd recommend replacing all three regexes to avoid problems:

    _.templateSettings = {
        evaluate:    /\{\{(.+?)\}\}/g,
        interpolate: /\{\{=(.+?)\}\}/g,
        escape:      /\{\{-(.+?)\}\}/g
    };
    

    Demo: http://jsfiddle.net/ambiguous/SdLsn/