Template.Tiny

(Sorry if you heard this already :-) )

At $work we do as much “view” type code as we can in JavaScript with the ExtJS framework. I have personally found it to be a great framework to work with, although often it is lacking in the non-UI department. One thing that at first I really liked about Ext was their Template and XTemplate classes. But as time went on I got more and more annoyed with those modules.

I’ve always thought that Template-Toolkit was a really nice templating library to work with. I hate templating html because of all the weird little gotchas having to do with CSS and whatnot, but doing almost all that kind of work in JavaScript I have started missing Template-Toolkit. At some point I heard about Template::Tiny and this past Saturday I thought, “that’s like, 160 LOC…I could probably port that to javascript!”

So I did! It’s not really done yet, but the current code is at github. I need to finish porting the test suite from Perl 5 to JavaScript so that I can ensure correctness (I am certain I screwed up some stuff.)

Alias mentioned in his post that I use XRegExp (600 LOC) to help out with the Regular Expression support in JavaScript for this module. I actually wasn’t going to, since the only thing I needed it for was the /x flag, or to be more clear telling the parser to ignore whitespace, but I want to keep Template.Tiny in sync with the Perl version, and I really don’t want to strip out all the whitespace by hand. If someone takes issue with the dep they can fork away :-)

So once it is fully ported I fully intend to use it entirely from now on instead of the Ext templating. But take note, Ext templates and Template.Tinies (what?) really solve different problems and have different goals. The following is a list of Pros and Cons of each:

🔗 Ext.(X)Template

Pros:

Cons:

Example 1:

var data = { age: 21 };

// XTPL
var tpl = new Ext.XTemplate( "<tpl if="age > 18">Can Vote!</tpl>");
var str = tpl.apply(data);

// TT
var tmp = new Template.Tiny();
var str = tmp.process(
   "[% IF old_enough %]Can Vote![% END %]",
   { old_enough: (age > 18 )}
);

Example 2:

var data = { person: {first_name: 'fREW', last_name: 'Schmidt', title: 'Mr.' }};
// XTPL
var id = new Ext.XTemplate( "<tpl for="person">{title} {first_name} {last_name}</tpl>");
var str = tpl.apply(data);

// TT
var tmp = new Template.Tiny();
var str = tmp.process(
   "[% person.title %] [% person.first_name %] [% person.last_name %]",
   data
);

Example 3:

var data = { werld: 'fail'};

// XTPL
var tpl = new Ext.XTemplate( "Hello {world}");
var str = tpl.apply(data); // error message

// TT
var tmp = new Template.Tiny();
var str = tmp.process(
   "Hello [% world %]",
   data
); // silent failure

Example 4:

var data = { foo: 1 };

// XTPL
var id = new Ext.XTemplate( "{[someComplexRenderer(values.foo)]");
var str = tpl.apply({ foo: 1});

// TT
var tmp = new Template.Tiny();
var str = tmp.process(
   "[% foo %]",
   { foo: someComplexRenderer(data.foo) }
);

Example 5:

var data = { arr: ['foo','bar','baz']};

// XTPL
var tpl = new Ext.XTemplate('<tpl for="arr">({#}. {.})</tpl>');
var str = tpl.apply(data); // "(1. foo)(2. bar)(3. baz)";

// TT
var tmp = new Template.Tiny();
var idx = 0;
var str = tmp.process(
   "[% FOREACH x IN arr %]([% x.i %]. [% x.var %][% END %]",
   { arr: data.arr.map(function(x) { return { i: idx++, var: x } } }
);

Example 6:

var data = { longtext: "this won't fit!"};

// XTPL
var tpl = new Ext.XTemplate('{longtext:ellipsis(5)}');
var str = tpl.apply(data); // "this ...";

// TT
var tmp = new Template.Tiny();
var str = tmp.process(
   "[% longtext %]",
   { longtext: Ext.util.Format( data.longtext, 5) }
);

🔗 Template.Tiny

Pros:

Cons:

Example 7:

var data = { jack_slocum: 1 };

// TT
var tmp = new Template.Tiny();
var str = tmp.process(
   "[% IF jack_slocum %]We don't appreciate else-ifs[% ELSE %] Woot![% END %]",
   data
);

// XTPL
var tpl = new Ext.XTemplate(
   '<tpl if="jack_slocum">We don't appreciate else-ifs</tpl><tpl if="!jack_slocum">Woot!</tpl>'
   );
var str = tpl.apply(data);

I am planning on making a wrapper for TT for our stuff that will allow an anonymous function that will do data transformation like above. But as you can see above XTemplate really has more to offer, it just annoys the heck out of me on a regular basis :-)

Posted Tue, Jan 26, 2010

If you're interested in being notified when new posts are published, you can subscribe here; you'll get an email once a week at the most.