|
(function(exports){ |
|
/*jshint expr:true*/ |
|
"use strict"; |
|
var tplType = 'text/tpl' |
|
, tplStrings = {} |
|
, registeredFilters = {} |
|
, escapedchars={ "&": "&" ,"<": "<" ,">": ">" ,'"': """ ,"'": "'" ,"`": "`" } |
|
, G = (typeof global !== 'undefined') ? global : (new Function('return this;'))() |
|
; |
|
function escaped(str){ |
|
return str.replace(/[<>"'`]|&(?!amp;)/g,function(m){ return escapedchars[m];}); |
|
} |
|
function registerString(tplName,tplStr){ |
|
tplStrings[tplName] = tplStr.replace(/^\s+|\s+$/g,''); |
|
} |
|
function registerScriptTag(scriptTag,name){ |
|
registerString(name || scriptTag.getAttribute('rel'),scriptTag.innerHTML); |
|
scriptTag.parentNode.removeChild(scriptTag); |
|
} |
|
function registerFilter(filterName,filterMethod){ |
|
registeredFilters[filterName] = filterMethod || G[filterName]; |
|
} |
|
function preload(){ |
|
var tplScripts,i; |
|
if( document.querySelectorAll ){ |
|
tplScripts = document.querySelectorAll('script[type="'+tplType+'"][rel]'); |
|
}else{ |
|
var tmp = document.getElementsByTagName('script'); |
|
for( i=tmp.length,tplScripts=[]; i--;){ |
|
tmp[i].getAttribute('type') === tplType && tmp[i].getAttribute('rel') && tplScripts.push(tmp[i]); |
|
} |
|
} |
|
for( i = tplScripts.length;i--;){ |
|
registerScriptTag(tplScripts[i]); |
|
} |
|
} |
|
|
|
function getDataKey(datas,key,context){ |
|
if( ~key.indexOf('|') ){ |
|
var filters=key.split('|'), data,i,l; |
|
key = filters.shift(); |
|
data = getDataKey(datas,key,context); |
|
for(i=0,l=filters.length;i<l;i++){ |
|
if( ! registeredFilters[filters[i]] ){ |
|
registerFilter(filters[i]); |
|
} |
|
data = registeredFilters[filters[i]](data); |
|
} |
|
return data; |
|
} |
|
if(key.match(/^\//)){ |
|
key=key.substr(1); |
|
context=''; |
|
} |
|
while(key.match(/^..\//)){ |
|
context = (~context.indexOf('.'))?'':context.replace(/\.[^\.]*$/,''); |
|
key = key.replace(/^..\//,''); |
|
} |
|
|
|
key =key.replace(/^\.+/,''); |
|
key = ((context||'')+(context && key?'.':'')+key).split('.'); |
|
var res = datas; |
|
for(var i=0,l=key.length;i<l;i++){ |
|
if(! (key[i] in res) ){ return null;} |
|
res=res[key[i]]; |
|
} |
|
return res; |
|
} |
|
function render(str,datas,context){ |
|
context || (context=''); |
|
return str |
|
.replace(/\{\{\s*#([^\{\s]+?)\}\}([\s\S]*?)\{\{\/\1\}\}/g,function(m,param,str){ // each elements #param ending /param |
|
var res = [],data = getDataKey(datas,param,context),nContext = (context?context+'.':'')+param; |
|
if(! data ){ return '';} |
|
for( var i in data ){ |
|
data.hasOwnProperty(i) && res.push(render(str,datas,nContext+'.'+i)); |
|
} |
|
return res.join(''); |
|
}) |
|
.replace(/\{\{([^\{\s]+?)(!)?\?\s*\}\}([\s\S]*?)\{\{\?\1\}\}/g,function(m,param,not,str){ // if => param? if not => param!? both ending with ?param |
|
var data = getDataKey(datas,param,context); |
|
var paramTrue = (!data)? false : (data instanceof Array ? data.length : true); |
|
not && (paramTrue = !paramTrue); |
|
return paramTrue ? render(str,datas,context) : ''; |
|
}) |
|
.replace(/\{\{\{([^\{\s]*?)\}\}\}/g,function(m,id){ // triple stash for escaped replacement |
|
return escaped(getDataKey(datas,id,context)); |
|
}) |
|
.replace(/\{\{([^\{\s]*?)\}\}/g,function(m,id){ return getDataKey(datas,id,context);}) // double stash for normal replacement |
|
; |
|
} |
|
function tpl(name,datas){ |
|
if( tplStrings[name] === undefined){ |
|
preload(); |
|
if( tplStrings[name] === undefined){ |
|
return false; |
|
} |
|
} |
|
return render(tplStrings[name],datas); |
|
} |
|
tpl.registerScriptTag = registerScriptTag; |
|
tpl.registerString = registerString; |
|
tpl.registerFilter = function(name,filter){registerFilter(name,filter); return this;}; |
|
tpl.preload= preload; |
|
tpl.renderString=render; |
|
exports.tpl = tpl; |
|
})((typeof exports === 'object') ? exports : this); |
Moved to its own repository: https://github.com/malko/stpl