jtdal
Version:
Small template engine based on Zope TAL, using data attributes
1 lines • 7.33 kB
JavaScript
;export default class t{static t=["condition","repeat","content","replace","attributes","omittag"];static i="(?:[\\w\\-\\/]*[\\w](?:[\\s]*\\|[\\s]*[\\w\\-\\/]*[\\w])*)";static l="STRING:(?:[^;](?:(?!<=;);)?)+";static o="MACRO:[a-zA-Z0-9-]+";static u="(?:(?:!)?[\\w\\-\\/]*[\\w](?:[\\s]*\\|[\\s]*[\\w\\-\\/]*[\\w])*)";static p="(?:"+t.l+"|(?:"+t.u+")(?:[\\s]*\\|[\\s]*"+t.l+")?)";static h="(?:"+t.o+"|"+t.l+"|"+t.u+"(?:[\\s]*\\|[\\s]*"+t.l+")?)";static S=new RegExp("<((?:\\w+:)?\\w+)(\\s+[^<>]+?)??\\s+\\bdata-tdal-(?:"+t.t.join("|")+")\\b=(['\"])(.*?)\\3(\\s+[^<>]+?)??\\s*(/)?>","i");static m=/\s((?:[\w-]+:)?[\w-]+)=(?:(['"])(.*?)\2|([^>\s'"]+))/gi;static A=new RegExp("(?:{("+t.i+")}|{\\?("+t.u+")}(.*?){\\/\\2})");static _=new RegExp("^[\\s]*("+t.p+")[\\s]*$");static R=new RegExp("^[\\s]*([\\w\\-]+?)[\\s]+("+t.i+")[\\s]*$");static N=new RegExp("^[\\s]*(?:(structure)[\\s]+)?("+t.h+")[\\s]*$");static P=new RegExp("[\\s]*(?:(?:([\\w\\-]+)(\\??)[\\s]+("+t.p+")[\\s]*)(?:;;[\\s]*|$))","g");static O=/\s*(data-tdal-[\w-]+)=(?:(['"])(.*?)\2|([^>\s'"]+))/gi;static k=["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"];v={};static T(e,r={}){let s,a='""';for(;null!=(s=t.A.exec(e));)if(0<s.index&&(a+="+"+JSON.stringify(String(e.substring(0,s.index)))),e=e.substring(s.index+s[0].length),s[1])a+="+(a("+t.$(s[1],!1,r)+')&&("string"===typeof t[t[0]]||("number"===typeof t[t[0]]&&!isNaN(t[t[0]])))?t[t[0]]:"")';else if(s[2]){const e=t.$(s[2],!0,r);"true"===e?a+="+"+this.T(s[3],r):"false"!==e&&(a+="+(true==="+e+'?""+'+this.T(s[3],r)+':"")')}return 0<e.length&&(a+="+"+JSON.stringify(String(e))),a}static $(t,e=!1,r={}){let s="";if(t)t:{const a=t.split("|"),i=a.length;for(let t=0;t<i;++t){0!=t&&(s+="||");let i=a[t].replace(/^\s+/,"");if(i.startsWith("STRING:")){s+="("+this.T(i.substring(7))+")";break t}if(i.startsWith("MACRO:")){void 0!==r[i.substring(6)]?s+='("function"===typeof m["'+i.substring(6)+'"]?m["'+i.substring(6)+'"]():false)':s+="false";break t}{i=i.replace(/\s+$/,"");const t="!"===i[0],r=e||t,a=(t?i.substring(1):i).split("/");if(0<a.length&&0<a[0].length)switch(a[0]){case"FALSE":s+=t?"true":"false";break t;case"TRUE":s+=t?"false":"true";break t;case"REPEAT":3==a.length&&(s+=(r?(t?"!":"")+"b(":"")+'c(r,"'+a.join("/")+'")'+(r?")":""));break;case"GLOBAL":1<a.length&&0<a[1].length&&(s+=(r?(t?"!":"")+"b(":"")+'c(d,"'+a.slice(1).join("/")+'")'+(r?")":""));break;default:s+=r?(t?"!(":"")+'(a(c(r,"'+a.join("/")+'"))&&b(t[t[0]]))||(a(c(d,"'+a.join("/")+'"))&&b(t[t[0]]))'+(t?")":""):'((a(c(r,"'+a.join("/")+'"))||a(c(d,"'+a.join("/")+'")))?t[t[0]]:false)'}}}}else s="false";return s}j(e){let r,s="";const a="data-tdal-";for(;null!==(r=t.S.exec(e));){0<r.index&&(s+="+"+JSON.stringify(String(e.substring(0,r.index)))),e=e.substring(r.index+r[0].length);let i=!!r[6]||t.k.includes(r[1].toLowerCase());const n=["",r[0],"","","","","",""],l={},o=r[0].matchAll(t.m);for(const t of o)l[t[1]]=t;if(n[1]=n[1].replaceAll(t.O,""),!i){const t=new RegExp("<(\\/)?"+r[1]+"[^<>]*(?<!\\/)>","gi");let s,a=[],l=1;for(;void 0===a[0]&&null!==(s=t.exec(e));)s[1]?l--:l++,0==l&&(a=[s.index,s[0].length]);void 0===a[0]?i=!0:(n[4]+=this.j(e.substring(0,a[0])),n[6]+=e.substring(a[0],a[0]+a[1]),e=e.substring(a[0]+a[1]))}t:{let e,r,s=a+t.t[0];if(l[s]&&t._.exec(l[s][3])){if(r=t.$(l[s][3],!0,this.v),"false"===r)break t;"true"!==r&&(n[0]+="+(true==="+r+'?""',n[7]=':"")'+n[7])}if(s=a+t.t[1],l[s]&&(e=t.R.exec(l[s][3]))){if(r=t.$(e[2],!1,this.v),"false"==r||'""'==r||"true"==r)break t;n[0]+="+(",n[0]+="((",n[0]+="a("+r+")&&",n[0]+="(!Array.isArray(t[t[0]])||(t[t[0]]=Object.assign({},t[t[0]])))&&",n[0]+='("object"===typeof t[t[0]]&&null!==t[t[0]]&&Object.keys(t[t[0]]).length)',n[0]+=")?((t[++t[0]]=1)&&t[0]++):((t[0]+=2)&&false))",n[0]+="?",n[0]+="Object.keys(t[t[0]-2]).reduce((o,e)=>{",n[0]+='r["'+e[1]+'"]=t[t[0]-2][e];',n[0]+="const n=t[t[0]-1]++,l=Object.keys(t[t[0]-2]).length;",n[0]+='r["REPEAT"]["'+e[1]+'"]={index:e,number:n,length:l,even:0==(n%2),odd:1==(n%2),first:1==n,last:l==n};',n[0]+="return o",n[7]=';},""):"")+((t[0]-=2)&&(delete r["REPEAT"]["'+e[1]+'"])&&delete(r["'+e[1]+'"])?"":"")'+n[7]}if(s=a+t.t[2],l[s]&&(e=t.N.exec(l[s][3]))){if(r=t.$(e[2],!1,this.v),"false"==r)n[4]="";else if("true"!=r){let t=["",""];"structure"!=e[1]&&(t[0]="String(",t[1]=').replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """)'),n[3]+="+(a("+r+')&&("string"===typeof t[t[0]]||("number"===typeof t[t[0]]&&!isNaN(t[t[0]])))?'+t[0]+"t[t[0]]"+t[1]+':(true!==t[t[0]]?"":""',n[5]+="))"}}else if(s=a+t.t[3],l[s]&&(e=t.N.exec(l[s][3])))if(r=t.$(e[2],!1,this.v),"false"==r)n[1]="",n[4]="",n[6]="";else if("true"!=r){let t=["",""];"structure"!=e[1]&&(t[0]="String(",t[1]=').replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """)'),n[0]+="+(a("+r+')&&("string"===typeof t[t[0]]||("number"===typeof t[t[0]]&&!isNaN(t[t[0]])))?'+t[0]+"t[t[0]]"+t[1]+':(true!==t[t[0]]?"":""',n[7]="))"+n[7]}if(s=a+t.t[4],l[s]){const a=l[s][3].matchAll(t.P);for(e of a){const s="?"===e[2];r=t.$(e[3],s,this.v),"false"===r?void 0!==l[e[1]]&&(n[1]=n[1].replace(new RegExp("\\s*\\b"+e[1]+"\\b(?:=(['\"]).*?\\1)?(?=\\s|\\/?>)"),"")):"true"!==r&&(n[2]+=s?`+(${r}?" ${e[1]}":""`:`+(a(${r})&&( "string" === typeof t[t[0]] || ( "number" === typeof t[t[0]] && !isNaN(t[t[0]])))?" ${e[1]}=\\""+t[t[0]]+"\\"":( true !== t[t[0]]?"":"${e[1]}"`,void 0!==l[e[1]]&&(n[1]=n[1].replace(new RegExp("\\s*\\b"+e[1]+"\\b(?:=(['\"]).*?\\1)?(?=\\s|\\/?>)"),""),n[2]+=void 0!==l[e[1]][3]&&""!=l[e[1]][3]?'+"="+'+JSON.stringify(String(l[e[1]][2]+l[e[1]][3]+l[e[1]][2])):""),n[2]+=")",s||(n[2]+=")"))}}s=a+t.t[5],l[s]&&t._.exec(l[s][3])&&(r=t.$(l[s][3],!0,this.v),"true"==r?(n[1]="",n[6]=""):"false"!=r&&(n[0]+="+("+r+'?"":""',n[3]=")"+n[3],n[5]+="+("+r+'?"":""',n[7]=")"+n[7]))}n[1]=n[1].replace(/\s*\/?>$/,""),!i||""==n[4]&&""==n[3]&&""==n[5]||(n[6]="</"+r[1]+">",i=!1),s+=n[0]+"+"+JSON.stringify(String(n[1]))+n[2]+(""!=n[1]?'+"'+(i?"/":"")+'>"':"")+n[3]+n[4]+n[5]+"+"+JSON.stringify(String(n[6]))+n[7]}return s+="+"+JSON.stringify(String(e)),s}MacroAdd(t,e,r=!0,s=!0){let a=!1;return t.match(/^[a-zA-Z0-9-]*$/)&&(a=!0,this.v[t]='""'+this.j(s?e.replace(/<!--.*?-->/gs,""):e),r&&(this.v[t]="("+this.v[t]+").trim()")),a}constructor(t=[],e=!0,r=!0){const s=t.length;for(let a=0;a<s;a++)this.MacroAdd(t[a][0],t[a][1],e,r)}C(t,e=!0,r=!0){const s=["",""];let a=this.j(r?t.replace(/<!--.*?-->/gs,""):t),i='const r={"REPEAT":{}}';i+=",t=[1]",i+=",m={"+Object.keys(this.v).map((t=>'"'+t+'":()=>'+this.v[t])).join(",")+"}",i+=",a=(e)=>{",i+="t[t[0]]=e;",i+="return false!==t[t[0]]",i+="}",i+=",c=(a,b)=>{",i+='let z=!1,y=b.split("/"),x,w;',i+="if(0<y.length&&0<y[0].length)",i+="for(z=a,x=0;x<y.length&&1!==z;x++)",i+='z="object"===typeof z&&null!==z&&void 0!==(w="function"===typeof z[y[x]]?z[y[x]](d,r):z[y[x]])&&w;',i+="return z",i+="}",i+=",b=(v)=>{",i+='return v&&("object"===typeof v?0<Object.keys(v).length:(Array.isArray(v)?0<v.length:true))',i+="}",i+=";",e&&(s[0]="(",s[1]=").trim()"),i+="return "+s[0]+'""'+a+s[1],a="";do{a=i,i=i.replace(/(?<!\\)"\+"/g,"").replace('(true!==t[t[0]]?"":"")','""')}while(a!=i);return i}CompileToFunction(t,e=!0,r=!0){return new Function("d",this.C(t,e,r))}CompileToString(t,e=!0,r=!0){return"function(d){"+this.C(t,e,r)+"}"}}