Created
September 16, 2010 11:52
-
-
Save aron/582305 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* A lightweight templating system. | |
* | |
* Based on Tim (http://github.com/premasagar/tim) and Mustache | |
* (http://github.com/janl/mustache.js). | |
* | |
* Template supports simple value replacement as well as block | |
* functions, iterators and conditionals | |
* | |
* Template strings can contain either plain tokens `{{token}}` | |
* which are replaced with their equivilent value in the data | |
* object or blocks `{%block%}` which can wrap a portion of your | |
* template. | |
* | |
* Whitespace in tokens is ignored. Blocks must be closed using | |
* either "end" or a slash "/" followed by the block name. eg. | |
* `{% myblock %}Content{% /myblock %}` | |
* or | |
* `{% myblock %}Content{% end myblock %}` | |
* | |
* Arguments | |
* | |
* string - A template String to convert. | |
* data - A data Object containing key/value pairs to supplant. | |
* | |
* Simple Examples | |
* | |
* template('{{name}}', {name: 'Aron'}); | |
* //=> "Aron" | |
* | |
* template('{{user.age}}', {name: 'Aron', age: 25}); | |
* //=> 25 | |
* | |
* Iterator Examples | |
* | |
* All values in array will be passed into a new template call with one | |
* key, `item`, this will equal the current array item. If a block is | |
* used its contents will be used as the template string. | |
* | |
* template('a {{item}}, ', {animals: ['cat', 'dog', 'mouse']}); | |
* //=> "a cat, a dog, a mouse, " | |
* | |
* template('<ul>{% animals %}<li>{{item.name}}</li>{% end animals %}</ul>', { | |
* animals: [{name: 'cat'}, {name: 'dog'}, {name: 'mouse'}] | |
* }); | |
* //=> "<ul><li>cat</li><li>dog</li><li>mouse</li></ul>" | |
* | |
* Boolean Example | |
* | |
* If true a boolean block will display its contents. | |
* | |
* template('{%is_admin?%}<a href="Edit">Edit {{type}}</a>{%end is_admin?%}', { | |
* 'is_admin?': true, type: 'User' | |
* }); | |
* //=> <a href="Edit">Edit User</a> | |
* | |
* Callback Example | |
* | |
* Functions receive the block contents as a parameter and can | |
* return any string value. The callbacks context (this) is bound | |
* to the data object passed in to the template. | |
* | |
* template('{%callback%}<p>Some template string</p>{%end callback%}', { | |
* callback: function (tmpl) { | |
* // this === data | |
* // tmpl === "<p>Some template string</p>" | |
* return 'Whatever'; | |
* } | |
* }); | |
* //=> "Whatever" | |
* | |
* Returns supplanted template String. | |
*/ | |
(function (namespace, context) { | |
var keypath = '\\s*([a-z0-9_$][.a-z0-9_$?]*)\\s*', | |
token_regex = new RegExp('{{' + keypath + '}}', 'gi'), | |
block_regex = new RegExp('{%' + keypath + '%}([\\s\\S]*){%\\s*(?:end|\\/)\\s*\\1\\s*%}', 'gi'), | |
isArray; | |
isArray = Array.isArray || function (o) { | |
return Object.prototype.toString.call(o) === '[object Array]'; | |
}; | |
context[namespace] = function template(string, data) { | |
function getValueForToken(match, token, contents) { | |
var path = token.split('.'), | |
length = path.length, | |
lookup = data || {}, | |
i = 0; | |
contents = contents || ''; | |
for (; i < length; i+=1) { | |
lookup = lookup[path[i]]; | |
if (i === length - 1){ | |
switch (typeof lookup) { | |
case 'string': | |
case 'number': | |
return lookup; | |
case 'boolean': | |
return lookup ? contents : ''; | |
case 'function': | |
return lookup.call(data, contents); | |
case 'object': | |
if (isArray(lookup)) { | |
return (function iterateDataArray() { | |
var items = [], | |
length = lookup.length, | |
i = 0; | |
for (; i < length; i+=1) { | |
items.push(template(contents || '{{item}}', {item:lookup[i]})); | |
} | |
return items.join(''); | |
})(); | |
} | |
} | |
} | |
} | |
return match; | |
} | |
return string.replace(block_regex, getValueForToken).replace(token_regex, getValueForToken); | |
}; | |
})('template', this); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(m,n){var g="\\s*([a-z0-9_$][.a-z0-9_$?]*)\\s*",o=new RegExp("{{"+g+"}}","gi"),p=new RegExp("{%"+g+"%}([\\s\\S]*){%\\s*(?:end|\\/)\\s*\\1\\s*%}","gi"),h;h=Array.isArray||function(e){return Object.prototype.toString.call(e)==="[object Array]"};n[m]=function e(q,i){function j(r,c,b){c=c.split(".");var k=c.length,a=i||{},d=0;for(b=b||"";d<k;d+=1){a=a[c[d]];if(d===k-1)switch(typeof a){case "string":case "number":return a;case "boolean":return a?b:"";case "function":return a.call(i,b);case "object":if(h(a))return function t(){for(var l= | |
[],s=a.length,f=0;f<s;f+=1)l.push(e(b||"{{item}}",{item:a[f]}));return l.join("")}()}}return r}return q.replace(p,j).replace(o,j)}})("template",this); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var data = { | |
name: 'Aron', | |
age: 25, | |
bio: 'A web developer living in Brighton, UK', | |
items: ['shoe', 'hat', 'coat', 'watch', 'umbrella'], | |
'is_admin?': false, | |
comments: function (tmpl) { | |
// Do something complicated. | |
return 'No Comment'; | |
} | |
}; | |
console.log(template( | |
'<p>{{name}} is {{age}} and a {{bio}}. He has the following possessions:</p>\n' + | |
'<ul>' + | |
'{% items %}\n <li>a {{item}}</li>{% enditems %}\n' + | |
'</ul>\n' + | |
'{% is_admin? %}\n<a href="login>Login</a>"{% endis_admin? %}' + | |
'<p>{{comments}}</p>', | |
data | |
)); | |
/* Outputs: | |
<p>Aron is 25 and a A web developer living in Brighton, UK. He has the following possessions:</p> | |
<ul> | |
<li>a shoe</li> | |
<li>a hat</li> | |
<li>a coat</li> | |
<li>a watch</li> | |
<li>a umbrella</li> | |
</ul> | |
<p>No Comment</p> | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment