const templateCache = new Map(); const ASNT="{{st}}"; const ESNT="{{ste}}"; const TSNT=` `; export interface TemplateResult{ _id:any; templates:TemplateStringsArray, values:any[]; } /** * Create HTM templates and store them in cache * @param {*} templates * @param {...any} values * @returns */ export function html(templates:TemplateStringsArray,...values:unknown[]):TemplateResult{ const t = document.createElement("template"); let s = ""; let n =templates.length; for(let t of templates){ n--; if(t.trim().endsWith("=")){ s+=(t+ASNT); }else{ if(n!==0){ s+=(t+TSNT); }else{ s+=t; } } } t.innerHTML=s;//templates.join(TEXT_SENTINEL); if(!templateCache.has(templates)){ templateCache.set(templates,t); } return { _id:values, templates, values }; } function createStaticIterationList(targetNode:Node){ const result=[]; const itr = document.createNodeIterator(targetNode); //skip the root node itr.nextNode(); let currentNode = itr.nextNode(); while(currentNode){ if(currentNode.nodeType===Node.COMMENT_NODE && currentNode.textContent===ASNT){ //this means it do not have been render even once: fresh node //@ts-ignore if(!currentNode.endCommentNode){ //@ts-ignore currentNode.endCommentNode=currentNode.nextSibling.nextSibling; } //@ts-ignore if(currentNode.isSpecial){ //move till let cn = itr.nextNode(); //@ts-ignore while(cn!==currentNode.endCommentNode){ cn = itr.nextNode(); } } result.push(currentNode); }else if(currentNode.nodeType===Node.ELEMENT_NODE){ //@ts-ignore if(currentNode.stAt){ result.push(currentNode); }else{ //@ts-ignore for(let i=0;i//startCommentNode //array elements //render for the value //endCommentNode old is an array of {_id,templates,values,startCommentNode} old and new array are compared if(old and new id do not match){ if(old do not have an entry): then a new is created and added else : old is completely rendered } */ let k=0; for(let nTR of cv){ let oTR = prevValues[k]; //nTR and oTR are of type : {_id,templates,values,startCommentNode} if(nTR._id!==oTR?._id){ //if id mismatch than needs a render if(!oTR){ //if there is no oldTemplateResult : create new one let d = new DocumentFragment(); render(d,nTR); const ef = createEmptyFragment(); //@ts-ignore replaceInBetweenCommentNode(ef.startCommentNode,d); startCommentNode.parentNode.insertBefore(ef,endCommentNode); //set a reference to this newly created nodes start comment node in nTR //@ts-ignore nTR.startCommentNode=ef.startCommentNode; }else{ //else if oldTemplateResult exist: update its content with new render let d = new DocumentFragment(); render(d,nTR); replaceInBetweenCommentNode(oTR.startCommentNode,d); //set a reference to old start comment node in nTR nTR.startCommentNode=oTR.startCommentNode; } }else{ //copying old start comment node to new list nTR.startCommentNode=oTR.startCommentNode } k++; } //if k is less than the length of previous values //this nodes are no more required and hence will be removed if(k{ const _id = idFunction(item); const templateResult=templateFunction(item,index,_id); templateResult._id=_id; result.push(templateResult); }); return result; } class UnsafeHTML{ constructor(private _value:any){ } public get value() : any{ return this._value; } } // export function unsafeHTML(stringItem:string):TemplateResult{ // const t = document.createElement("template"); // t.innerHTML=stringItem; // if(!templateCache.has(stringItem)){ // templateCache.set(stringItem,t); // } // return { // _id:[], // values:[], // //@ts-ignore // templates:stringItem // } // } export function unsafeHTML(value:any):UnsafeHTML{ return new UnsafeHTML(value); } export const nothing=html``;