UNPKG

templz

Version:

Mustache-inspired template engine working with strings and elements

25 lines (24 loc) 12.2 kB
(function(w,q){"function"===typeof define&&define.amd?define([],q):"object"===typeof exports?module.exports=q():w.Templz=q()})(this,function(){function w(){}function q(f){return"string"===typeof f?n(f).split(/\s+/,2):y(f)&&f}function E(f,h){if(f.length){var d;d=[];for(var e=[],g=0,k;g<f.length;)if(k=f[g++],"#"===k.type||"^"===k.type)d.push(k.value);else if("/"===k.type)if(d.length){if(d.pop()!==k.value)throw Error('Unclosed section "'+openSection[1]+'"');}else e.push(k.value);d=[e,d];for(g=0;g<d[0].length;g++){e= h.pop();if(!e)throw Error('Unopened section "'+d[0][g]+'"');if(e!==d[0][g])throw Error('Unclosed section "'+e+'"');}d[1].length&&h.push.apply(h,d[1])}return f}function B(f){for(var h=[],d=h,e=[],g,k=0;k<f.length;)g=f[k++],"#"!==g.type&&"^"!==g.type||g.children?"/"===g.type?(e.pop(),d=e.length?e[e.length-1].children:h):d.push(g):(d.push(g),e.push(g),g.children=d=[]);return h}function H(f,h){for(var d=f.attributes,e,g=null,k=0;k<d.length;k++)(e=d[k].value)&&0<=e.indexOf(h[0])&&(e=F(e,h),!e.length|| 1===e.length&&"text"===e[0].type||(e=B(E(e,[])),g||(g={}),g[d[k].name]=e));return g}function C(f,h,d,e){function g(){if(0<=m.indexOf(d[0]))for(var a=E(F(m,d),G),c=0,e;c<a.length;)e=a[c++],"text"===e.type?t.appendChild(f.newText(e.value)):(k(),l.push(e));else t.appendChild(f.newText(m));m=""}function k(){var a=t.childNodes.length;a&&(l.push({type:I.FRAGMENT_TEMPLATE,value:1===a?t.firstChild:t}),t=f.newFrag())}for(var l=[],c,b,a,m="",t=f.newFrag(),r,G=[],J=0;J<h.length;)if(a=h[J++],3===a.nodeType)m+= a.nodeValue;else if(1===a.nodeType){m&&g();c=null;if(b=a.getAttribute(e+"prefix"))e=b;if(b=a.getAttribute(e+"tags"))d=q(b);(b=a.getAttribute(e+"name"))?(c={type:"name",value:n(b)},c.node=a.cloneNode(!1),c.node.removeAttribute(e+"name")):(b=a.getAttribute(e+"content"))?(c={type:"&",value:n(b)},c.node=a.cloneNode(!1),c.node.removeAttribute(e+"content")):(b=a.getAttribute(e+"section"))?(c={type:"#",value:n(b)},r=a.cloneNode(!0),r.removeAttribute(e+"section"),c.children=C(f,[r],d,e)):(b=a.getAttribute(e+ "empty"))?(c={type:"^",value:n(b)},r=a.cloneNode(!0),r.removeAttribute(e+"empty"),c.children=C(f,[r],d,e)):(b=a.getAttribute(e+"partial"))?(c={type:">",value:n(b)},c.node=a.cloneNode(!1),c.node.removeAttribute(e+"partial")):(r=H(a,d),b=a.childNodes.length?C(f,a.childNodes,d,e):[],r||b.length&&(1!==b.length||"fragment"!==b[0].type)?(c={type:"node"},c.attributes=r,1<b.length||1===b.length&&"fragment"!==b[0].type?(c.children=B(b),c.node=a.cloneNode(!1)):c.node=a.cloneNode(!0)):(r=a.cloneNode(!1),b.length&& r.appendChild(b[0].value),t.appendChild(r)));c&&(!c.node||"attributes"in c||(c.attributes=H(a,d)),k(),l.push(c))}else m&&g(),t.appendChild(a);m&&g();if(G.length)throw Error('Unclosed section: "'+G.pop()+'"');k();return l}function F(f,h){function d(){if(!c||-1!=="text # ^ /".indexOf(c.type)){if(c&&"text"===c.type){var a=c.value.lastIndexOf("\n")+1;if(a&&/\S/.test(c.value.slice(a))||!a&&(1<e.length||/\S/.test(c.value)))return}var b=m+g[1],d=f.indexOf("\n",b)+1;if(d&&!/\S/.test(f.slice(b,d))||!d&&!/\S/.test(f.slice(b)))a? c.value=c.value.slice(0,a):c&&"text"===c.type&&(e.length=c=0),m=d?d-g[1]:t}}if(!f)return[];for(var e=[],g=[h[0].length,h[1].length],k,l,c,b=[],a=0,m=0,t=f.length;a<t;){a=f.indexOf(h[0],a);if(-1===a){c&&"text"===c.type?c.value+=f.substring(m):e.push({type:"text",value:f.substring(m)});break}a>m&&(c&&"text"===c.type?c.value+=f.substring(m,a):e.push(c={type:"text",value:f.substring(m,a)}));m=f.indexOf(h[1],a+=g[0]);if(-1===m)throw Error("Unclosed tag: "+h[0]+f.substr(a,6)+"...");k=n(f.substring(a,m)); switch(k.charAt(0)){case "#":case "^":l=n(k.substring(1));b.push(l);d();e.push(c={type:k.charAt(0),value:l});c.index=m+g[1];break;case "/":l=n(k.substring(1));if(b.length&&(k=b.pop())!==l)throw Error('Unclosed section "'+k+'"');d();e.push(c={type:"/",value:l});c.index=a-g[0];break;case "{":if("}"===k.charAt(k.length-1))k=k.slice(0,-1);else if("}"!==f.charAt(m++)||f.substr(m,g[1])!==h[1])throw Error("Unclosed tag at "+a);case "&":l=n(k.substring(1));e.push(c={type:"&",value:l});break;case ">":l=n(k.substring(1)); l={type:">",value:l,indent:""};c&&"text"===c.type&&((k=c.value.lastIndexOf("\n")+1)&&!/\S/.test(k=c.value.slice(k))?l.indent=k:1!==e.length||/\S/.test(c.value)||(l.indent=c.value));d();e.push(c=l);break;case "!":d();break;case "=":if("="===k.charAt(k.length-1))k=k.slice(0,-1);else if("="!==f.charAt(m++)||f.substr(m,g[1])!==h[1])throw Error("Unclosed tag at "+a);d();h=q(k.substring(1));m+=g[1]-h[1].length;g=[h[0].length,h[1].length];break;default:e.push(c={type:"name",value:k})}a=m+=g[1]}return e} function u(f,h){for(var d=h.split("."),e=f.length,g,k;e--;){k=f[e];for(g=0;g<d.length&&k;g++)if(k[d[g]])k=k[d[g]];else break;if(g===d.length)return k}}function z(f,h,d,e,g){for(var k=0,l,c="",b,a;k<h.length;)switch(b=h[k++],b.type){case "text":c+=b.value;break;case "name":case "&":if(a="."===b.value?d[d.length-1]:u(d,b.value))"function"===typeof a&&(a=a(b.value)),c+="&"===b.type?a:L(a);break;case "#":if(a=u(d,b.value))if(y(a))for(l=0;l<a.length;l++)a[l]&&(c+=z(f,b.children,d.concat([a[l]]),e,g)); else"function"===typeof a&&(a=a(b.value)),a&&(c+=z(f,b.children,d.concat([a]),e,g));break;case "^":a=u(d,b.value);if(!a||y(a)&&!a.length)c+=z(f,b.children,d,e,g);break;case ">":if(!g||"object"!==typeof g||!g[b.value])break;a=g[b.value];if("string"===typeof a||"object"===typeof a&&"nodeType"in a)a=f.compile(a);a instanceof w&&(a=a.render(d[d.length-1],g))&&("string"===typeof a&&b.indent&&(a=b.indent+a.replace(/\n/g,"\n"+b.indent)),c+="string"===typeof a?a:f.serializeFragment(a))}return c}function A(f, h,d,e){function g(a,b,d){var g=a.node.cloneNode(null===b);a=a.attributes;var h;null!==b&&("object"===typeof b&&"nodeType"in b?g.appendChild(b):g.innerHTML=b);for(h in a)g.setAttribute(h,z(f,a[h],d,"",e));c.appendChild(g)}for(var k=0,l,c=f.newFrag(),b,a;k<h.length;)switch(b=h[k++],b.type){case "text":c.appendChild(f.newText(b.value));break;case "fragment":c.appendChild(b.value.cloneNode(!0));break;case "node":g(b,b.children?A(f,b.children,d,e):null,d);break;case "name":case "&":if(a="."===b.value? d[d.length-1]:u(d,b.value))"function"===typeof a&&(a=a(b.value)),b.node?g(b,"&"===b.type?a:f.newText(a),d):c.appendChild("&"===b.type?f.getFrag(a):f.newText(a));break;case "#":if(a=u(d,b.value))if(y(a))for(l=0;l<a.length;l++)a[l]&&c.appendChild(A(f,b.children,d.concat([a[l]]),e));else"function"===typeof a&&(a=a(b.value)),a&&c.appendChild(A(f,b.children,d.concat([a]),e));break;case "^":a=u(d,b.value);(!a||y(a)&&!a.length)&&c.appendChild(A(f,b.children,d,e));break;case ">":if(!e||"object"!==typeof e|| !e[b.value])break;a=e[b.value];if("string"===typeof a||"object"===typeof a&&"nodeType"in a)a=f.compile(a);a instanceof w&&(a=a.render(d[d.length-1],e))&&("string"===typeof a&&b.indent&&(a=b.indent+a.replace(/\n/g,"\n"+b.indent)),g(b,"string"===typeof a?f.newText(a):a,d))}return c}function D(f,h){function d(a,c,b){this.source=c;this.tokens=B(E(F(c,b),[]))}function e(a,c,b,e){this.source=c;this.tokens=B(C(a,c,b,e))}h||(h=f&&"undefined"!==typeof f.document?f.document:null);d.prototype=new w;d.prototype.render= function(a,b){return z(c,this.tokens,[a],"",b)};e.prototype=new w;e.prototype.render=function(a,b){return A(c,this.tokens,[a],b)};d.prototype.type=this.STRING_TEMPLATE;e.prototype.type=this.FRAGMENT_TEMPLATE;var g=this,k=h&&h.createDocumentFragment&&h.createDocumentFragment().nodeType,l=!!f&&"undefined"!==typeof f.HTMLTemplateElement,c={isNode:f&&f.Node?function(a){return!!a&&a instanceof f.Node}:function(a){return a&&"object"===typeof a&&"number"===typeof a.nodeType&&"string"===typeof a.nodeName}, isFragment:9===k?function(a){return 9===a.nodeType&&"#document-fragment"===a.nodeName}:function(a){return 11===a.nodeType},newFrag:k&&(K?h.createDocumentFragment.bind(h):function(){return h.createDocumentFragment()}),newText:h&&(K?h.createTextNode.bind(h):function(a){return h.createTextNode(a)}),getFrag:h&&(l?function(a){return function(c){a.innerHTML=c;c=a.content.cloneNode(!0);a.innerHTML="";return c}}(h.createElement("template")):function(){var a={td:"tr",th:"tr",tr:"tbody",thead:"table",tbody:"table", tfoot:"table",option:"select",optgroup:"select"};return function(b){var e=c.newFrag(),d=(b+"").match(/<(t[hdr]|thead|tbody|tfoot|option|optgroup)\b/i),d=h.createElement(d&&a[d[1].toLowerCase()]||"div");for(d.innerHTML=b;d.firstChild;)e.appendChild(d.firstChild);return e}}()),serializeFragment:h&&("outerHTML"in h.documentElement?function(a){var c=0;a=a.childNodes;for(var b="",d;c<a.length;)switch(d=a[c++],d.nodeType){case 1:b+=d.outerHTML;break;case 3:b+=d.nodeValue;break;case 8:b+="\x3c!--"+d.nodeValue+ "--\x3e"}return b}:function(a){return function(c){a.innerHTML="";a.appendChild(c.cloneNode(!0));return a.innerHTML}}(h.createElement("div")))},b={string:d,fragment:e};this.serialize=c.serializeFragment;this.createFragment=c.getFrag;this.compile=c.compile=function(a,d,e){null==d&&(d=g.tags);null==e&&(e=g.prefix);var f,h;if("string"===typeof a)f=a,h=g.STRING_TEMPLATE;else if(3===a.nodeType)f=[a],h=g.FRAGMENT_TEMPLATE;else if(1===a.nodeType||c.isFragment(a))f="TEMPLATE"===a.nodeName&&l&&a instanceof HTMLTemplateElement?a.content.childNodes:a.childNodes,h=g.FRAGMENT_TEMPLATE;if(!f)throw new TypeError("Invalid template");return new b[h](c,f,q(d),e)};if(Object.observe){w.prototype.bindToData=function(c,b){return new a(this,c,b)};this.bindElementToData=function(a,b,d,e,f){if(!c.isNode(a))throw new TypeError("Invalid node");b=this.compile(a,d,e).bindToData(b,f);a.innerHTML="";b.appendTo(a);return b};var a=function(a,b,d){function e(a,b){Object.observe(a,f,["add","update","delete"]);p.push(a);x.push(b); b=b.concat([a]);for(var c in a){var d=a[c];d&&"object"===typeof d&&e(d,b)}}function f(a){q=!0;if(n){var b=0,c,d;for(l();b<a.length;b++){c=a[b].type;if(("delete"===c||"update"===c)&&(d=a[b].oldValue)&&"object"===typeof d&&0<=p.indexOf(d)){for(var g=[],h=[],k=0;k<p.length;k++)d!==p[k]&&-1===x[k].indexOf(d)?(g.push(p[k]),h.push(x[k])):Object.unobserve(p[k],f);p.splice.apply(p,[0,p.length].concat(g));x=h}("add"===c||"update"===c)&&(d=a[b].object[a[b].name])&&"object"===typeof d&&-1===p.indexOf(d)&&(c= p.indexOf(a[b].object),e(d,x[c]||[]))}}}function k(e,f){var l;q&&(u=a.render(b,d),q=!1);l=a.type===g.STRING_TEMPLATE?c.newText(u):u;3===l.nodeType?v=[l]:l.childNodes.length?v=[].slice.call(l.childNodes):(l=h.createComment("Templz empty result"),v=[l]);e.insertBefore(l,f)}function l(){var a=v.slice(),b=v[0].parentNode,c=0;for(k(b,v[0]);c<a.length;)b.removeChild(a[c++])}if(!(a instanceof w))throw new TypeError("Invalid template");var n=!1,q,u,v=[],p=[],x=[];this.insertBefore=function(a){if(!c.isNode(a))throw new TypeError("Invalid node"); var b,d=a.parentNode;if(!d)throw new ReferenceError("Cannot insert before a detached node");if(n)for(b=0;b<v.length;b++)d.insertBefore(v[b],a);else k(d,a),n=!0};this.appendTo=function(a){if(!c.isNode(a))throw new TypeError("Invalid node");if(n)for(var b=0;b<v.length;b++)a.appendChild(v[b]);else k(a,null),n=!0};this.getTemplate=function(){return a};this.bind=function(a,c){if("object"!==typeof a)throw new TypeError("Data must be an object");"object"===typeof c&&(d=c);a!==p[0]&&(p.length&&unobserveAll(), q=!0,b=a,e(a,[]),n&&l())};this.unbind=function(){for(var a=0;a<p.length;)Object.unobserve(p[a++],f);p.length=x.length=0};this.bind(b)};a.prototype.constructor=function(){throw new TypeError("Illegal constructor");}}}w.prototype={constructor:function(){throw new TypeError("Illegal constructor");}};var K="bind"in function(){},n="".trim?function(f){return f.trim()}:function(f){return function(h){return h.replace(f,"")}}(/^\s+|\s+$/g),y=Array.isArray||function(f){return function(h){return"[object Array]"=== f.call(h)}}(Object.prototype.toString),L=function(f,h){return function(d){return(d+"").replace(h,function(d){return f[d]})}}({"&":"&#38;","<":"&#60;",">":"&#62;",'"':"&#34;","'":"&#39;","/":"&#47;"},/[&<>"'\/]/g);D.prototype={constructor:D,Context:D,version:"0.2.0",STRING_TEMPLATE:"string",FRAGMENT_TEMPLATE:"fragment",tags:["{{","}}"],prefix:"tpz-"};var I=new D(this||("undefined"!==typeof window?window:"undefined"!==typeof global?global:null));return I});