New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@modulor-js/html

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@modulor-js/html - npm Package Compare versions

Comparing version 1.1.3 to 1.2.0

2

build/html.js

@@ -1,1 +0,1 @@

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(e.MHTML={})}(this,function(e){"use strict";function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:document.createTextNode(""),t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:document.createTextNode("");return this.childNodes=[],this.firstChild=null,this.lastChild=null,this.startNode=e,this.stopNode=t,e&&t?e.parentNode!==t.parentNode?this:(this.update(),this):this}t.prototype.appendChild=function(e){this.stopNode.parentNode.insertBefore(e,this.stopNode),this.update()},t.prototype.removeChild=function(e){this.stopNode.parentNode.removeChild(e),this.update()},t.prototype.replaceChild=function(e,t){t.parentNode.replaceChild(e,t),this.update()},t.prototype.extractContents=function(){var e=document.createDocumentFragment();return e.appendChild(this.startNode),this.childNodes.reduce(function(e,t){return e.appendChild(t),e},e),e.appendChild(this.stopNode),e},t.prototype.update=function(){this.childNodes=[];for(var e=this.startNode.nextSibling;e&&e!==this.stopNode;e=e.nextSibling)this.childNodes.push(e);this.firstChild=this.childNodes[0],this.lastChild=this.childNodes[this.childNodes.length-1]};var n=1,r=3,o=8,i=document.body.namespaceURI,u="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function a(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function c(e,t){return e.nodeType===t.nodeType&&(e.tagName&&t.tagName&&e.tagName.toLowerCase()===t.tagName.toLowerCase())}function d(e){return void 0!==e}function s(e){return!!e&&("object"===(void 0===e?"undefined":u(e))||f(e))&&f(e.then)}function f(e){return"function"==typeof e}function l(e){return(void 0===e?"undefined":u(e))===u(!0)}function h(e){return e.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g,"\\$&")}var p=function(){return function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var n=[],r=!0,o=!1,i=void 0;try{for(var u,a=e[Symbol.iterator]();!(r=(u=a.next()).done)&&(n.push(u.value),!t||n.length!==t);r=!0);}catch(e){o=!0,i=e}finally{try{!r&&a.return&&a.return()}finally{if(o)throw i}}return n}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();var m={},v=new Map,y=new Map,g=new DOMParser,C="{modulor_html_chunk_"+ +new Date+":",N="}",b="modulor_sanitize_node_"+ +new Date+":",x=new RegExp("<([ /])?("+["table","tr","td","style"].join("|")+")([ ][^]>)?","igm"),w=/<([^\s]+)([ ].+)?\/([ ]+)?>/gim,T=new RegExp(O(),"ig"),j=new RegExp(O(!0),"ig"),A=new RegExp("^"+O(!0)+"$");function E(e){return f(e)?"function":e instanceof Array?"array":e instanceof Node?"element":s(e)?"promise":d(e)?"text":"undefined"}function D(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];return e.replace(j,function(e,n,r){var o=t[r];return d(o)?o:""})}function R(e,t,n){var r=t.name,o=t.value;if(s(o))o.then(function(t){return R(e,{name:r,value:t},n)});else if("style"!==r)if(f(r))r(e,o);else{if(!(n&&""===o)&&r in e)try{return void(e[r]=o)}catch(e){}e.setAttribute(r,o)}else!function(e){return e&&"object"===(void 0===e?"undefined":u(e))&&e.constructor===Object}(o)?e.setAttribute(r,o):Object.assign(e.style,o)}function S(e,t){if(d(e)&&""!==e){var n=E(e);return"promise"===n?e.then(function(e){return S(e,t)}):("array"===n?e:(""+e).split(" ")).forEach(function(e){return t(e)})}}function k(e){var t={nodeType:e.nodeType,namespaceURI:e.namespaceURI,textContent:e.textContent,attributes:[],childNodes:[]};e.tagName&&(t.tagName=e.tagName.toLowerCase().replace(b,"").toUpperCase());for(var n=e.attributes||[],i=function(r){var o=n[r],i=o.name,u=o.value,a=i.match(T),c=u.match(T),d=i.match(A),s=u.match(A);if("class"===i){var f=u.split(" ").reduce(function(e,t){return e[t.match(T)?0:1].push(t),e},[[],[]]),h=p(f,2),m=h[0],v=h[1];return t.attributes.push({name:i,value:v.join(" ")}),m.length&&t.attributes.push(function(e,t){return function(t,n){m.forEach(function(r){var o=r.match(A),i=o?t[o[2]]:D(r,t),u=o?n[o[2]]:D(r,n);u!==i&&(u&&S(u,function(t){return e.classList.remove(t)}),i&&S(i,function(t){return e.classList.add(t)}))})}}),"continue"}a||c?t.attributes.push(function(t){return function(n,r){var o=d?n[d[2]]:D(i,n),a=d?r[d[2]]:D(i,r),c=s?n[s[2]]:D(u,n),f=s?r[s[2]]:D(u,r);if((o!==a||c!==f)&&(o!==a&&t.removeAttribute(a),o))return R(t,{name:o,value:c},l(e[o])),function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}({},o,c)}}):t.attributes.push({name:i,value:u,isBoolean:l(e[i])})},u=0;u<n.length;u++)i(u);for(var a=e.childNodes||[],c=function(e){var n=a[e];return n.nodeType===r?(n.textContent.split(T).filter(function(e){return!!e}).forEach(function(e){var n=e.match(A);if(n){var o=n[2];t.childNodes.push(function(e){return function(t){return $(t[o],e)}})}else t.childNodes.push({nodeType:r,textContent:e})}),"continue"):n.nodeType===o?(n.textContent.match(T)?t.childNodes.push(function(e){var t=document.createComment(""),r=n.textContent;return e.appendChild(t),function(e){t.textContent=D(r,e)}}):t.childNodes.push({nodeType:o,textContent:n.textContent}),"continue"):void t.childNodes.push(k(n))},d=0;d<a.length;d++)c(d);return t}function F(e){var t,n=(t=e,Array.isArray(t)?t:Array.from(t)),r=n[0];return n.slice(1).reduce(function(e,t,n){var r=""+C+n+N;return e.concat(r).concat(t)},r)}function O(e){var t=(e?"(":"")+"\\d+"+(e?")":"");return"("+h(C)+t+h(N)+")"}function $(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:document.createDocumentFragment(),n=v.get(t)||{},r=E(e),o=n.lastChunk,i=n.lastRenderedChunkType,u=n.update;if(o===e)return t;if("promise"===r)return _.promise(t,e),t;if(i!==r)a(t);else if(u){var c=u(e);return f(c)&&(n.update=c),n.lastChunk=e,t}return v.set(t,{update:_[r](t,e),lastRenderedChunkType:r,lastChunk:e}),t}var _={array:function e(t,n){var r=L({childNodes:[].concat(n).map(function(e,t){return function(e){return function(n){return $(n[t],e)}}})},t,{useDocFragment:!0}),o=p(r,2),i=o[0],u=o[1];return i(n),u(),function(r){if(r.length!==n.length)return e(t,r);i(r)}},undefined:a,text:function(e,t){var n=document.createTextNode(t);return e.appendChild(n),function(e){return n.textContent=e}},element:function(e,t){return e.appendChild(t),function(t){e.childNodes.length>1&&e.childNodes.slice(1).forEach(function(t){return e.removeChild(t)}),e.replaceChild(t,e.childNodes[0])}},promise:function(e,t){t.then(function(t){e.update(),$(t,e)})},function:function(e,t){var n=t(e);return function(t){n=t(e,n)}}};function I(e,t){for(var n=t.attributes,r=e.attributes,o=0;o<r.length;o++)e.removeAttribute(r[o].name);for(var i=[],u={},a=0;a<n.length;a++){var c=n[a];if(f(c))i.push(c(e));else{var d=c.name,s=c.value,l=c.isBoolean;R(e,{name:d,value:s},l),u[d]=s}}if("props"in e){if(i.length)return[function(t,n){var r=i.reduce(function(e,r){return Object.assign(e,r(t,n))},{});Object.keys(r).length&&(e.props=Object.assign(u,r))}];e.props=u}return i}function L(e,u){for(var a,d,s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},l=[],h=s.useDocFragment?document.createDocumentFragment():u,p=e.childNodes,m=function(e){return e?function(t){return u.replaceChild(t,e)}:function(e){return h.appendChild(e)}},v=0,g=0;;v++){var C=p[v],N=u.childNodes[v+g];if(!C&&!N)break;if(C)if(N&&c(C,N))d=N,(r===(a=C).nodeType!==a.nodeType||a.textContent!==d.textContent)&&c(C,N)&&(l=l.concat(L(C,N)[0]).concat(I(N,C)));else{var b=m(N);if(f(C)){var x=y.get(N);if(!x){var w=(x=new t).startNode;b(x.extractContents()),y.set(w,x)}var T=C(x);T&&l.push(T),x.update(),g+=x.childNodes.length+1;continue}switch(C.nodeType){case r:b(document.createTextNode(C.textContent));break;case o:b(document.createComment(C.textContent));break;case n:var j=C.namespaceURI,A=C.tagName.toLowerCase(),E=j===i?document.createElement(A):document.createElementNS(j,A);l=l.concat(L(C,E)[0]).concat(I(E,C)),b(E)}}else u.removeChild(N),v--}var D=[];return[function e(t){return l.forEach(function(e){return e(t,D)}),D=t,e},function(){return s.useDocFragment?u.appendChild(h):void 0}]}e.NodesRange=t,e.emptyNode=a,e.render=$,e.morph=L,e.html=function(){for(var e=arguments.length,t=Array(e>1?e-1:0),n=1;n<e;n++)t[n-1]=arguments[n];var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];if(!r.length)return this;var o,i=function(e){for(var t=5381,n=e.length;n;)t=33*t^e.charCodeAt(--n);return t>>>0}(r.join(C+N)),u=m[i],a=void 0;if(d(u))a=u;else{var c=F(r);o=function(e){return e.replace(x,"<$1"+b+"$2")}(c.replace(w,"<$1$2></$1>")),a=k(g.parseFromString(o,"text/html").body),m[i]=a}return function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:document.createDocumentFragment(),n=arguments[1];if(n&&n.templateId===i)return n(t);var r=L(a,e,{useDocFragment:!0}),o=p(r,2),u=o[0],c=o[1];return u(t),c(),u.templateId=i,u}},e.stopNode=function(){},Object.defineProperty(e,"__esModule",{value:!0})});
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(e.MHTML={})}(this,function(e){"use strict";function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:document.createTextNode(""),t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:document.createTextNode("");return this.childNodes=[],this.firstChild=null,this.lastChild=null,this.startNode=e,this.stopNode=t,e&&t?e.parentNode!==t.parentNode?this:(this.update(),this):this}t.prototype.appendChild=function(e){this.stopNode.parentNode.insertBefore(e,this.stopNode),this.update()},t.prototype.removeChild=function(e){this.stopNode.parentNode.removeChild(e),this.update()},t.prototype.replaceChild=function(e,t){t.parentNode.replaceChild(e,t),this.update()},t.prototype.extractContents=function(){var e=document.createDocumentFragment();return e.appendChild(this.startNode),this.childNodes.reduce(function(e,t){return e.appendChild(t),e},e),e.appendChild(this.stopNode),e},t.prototype.update=function(){this.childNodes=[];for(var e=this.startNode.nextSibling;e&&e!==this.stopNode;e=e.nextSibling)this.childNodes.push(e);this.firstChild=this.childNodes[0],this.lastChild=this.childNodes[this.childNodes.length-1]};var n,r=1,o=3,i=8,u=document.body.namespaceURI,a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function c(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function s(e,t){return e.nodeType===t.nodeType&&(e.tagName&&t.tagName&&e.tagName.toLowerCase()===t.tagName.toLowerCase())}function d(e){return void 0!==e}function l(e){return!!e&&("object"===(void 0===e?"undefined":a(e))||f(e))&&f(e.then)}function f(e){return"function"==typeof e}function p(e){return(void 0===e?"undefined":a(e))===a(!0)}function h(e){return e.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g,"\\$&")}function m(){}var v=function(){return function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var n=[],r=!0,o=!1,i=void 0;try{for(var u,a=e[Symbol.iterator]();!(r=(u=a.next()).done)&&(n.push(u.value),!t||n.length!==t);r=!0);}catch(e){o=!0,i=e}finally{try{!r&&a.return&&a.return()}finally{if(o)throw i}}return n}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();function g(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var y,N={},C=new Map,b=new Map,x=new DOMParser,w="{modulor_html_chunk_"+ +new Date+":",j="}",T="modulor_sanitize_node_"+ +new Date+":",k=new RegExp("<([ /])?("+["table","tr","td","style"].join("|")+")([ ][^]>)?","igm"),A="modulor-dynamic-tag-"+ +new Date,D="modulor-chunk-"+ +new Date,R=(y="("+h(w)+"([^ >]+)"+h(j)+")",new RegExp("(<([ /])?)(([^ >]+)?("+y+")([a-zA-Z0-9-_]+)?)(([ ][^])?>)?","igm")),E=/<([^\s]+)([ ].+)?\/([ ]+)?>/gim,O=new RegExp(G(),"ig"),F=new RegExp(G(!0),"ig"),S=new RegExp("^"+G(!0)+"$"),L="preventChildRendering",_="function",$="array",I="element",M="promise",U="undefined",B="text";function P(e){return f(e)?_:e instanceof Array?$:e instanceof Node?I:l(e)?M:d(e)?B:U}function z(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];return e.replace(F,function(e,n,r){var o=t[r];return d(o)?o:""})}function H(e,t,n){var r=t.name,o=t.value;if(l(o))o.then(function(t){return H(e,{name:r,value:t},n)});else if("style"!==r)if(f(r))r(e,o);else{if(!(n&&""===o)&&r in e)try{return void(e[r]=o)}catch(e){}e.setAttribute(r,o)}else!function(e){return e&&"object"===(void 0===e?"undefined":a(e))&&e.constructor===Object}(o)?e.setAttribute(r,o):Object.assign(e.style,o)}function V(e,t){if(d(e)&&""!==e){var n=P(e);return n===M?e.then(function(e){return V(e,t)}):(n===$?e:(""+e).split(" ")).forEach(function(e){return t(e)})}}function Z(e){for(var t={nodeType:e.nodeType,namespaceURI:e.namespaceURI,textContent:e.textContent,attributes:[],childNodes:[]},n=t.attributes,r=t.childNodes,u=e.attributes||[],a=function(t){var r=u[t],o=r.name,i=r.value;if(o===D)return"continue";var a=o.match(O),c=i.match(O),s=o.match(S),d=i.match(S);if("class"===o){var l=i.split(" ").reduce(function(e,t){return e[t.match(O)?0:1].push(t),e},[[],[]]),f=v(l,2),h=f[0],m=f[1];return n.push({name:o,value:m.join(" ")}),h.length&&n.push(function(e){return function(t,n){var r=h.reduce(function(r,o){var i=o.match(S),u=i?t[i[2]]:z(o,t),a=i?n[i[2]]:z(o,n);return a!==u?(a&&V(a,function(t){return e.classList.remove(t)}),u&&V(u,function(t){return e.classList.add(t)}),!0):r},!1);return[{key:"className",value:e.className},r]}}),"continue"}a||c?n.push(function(t){return function(n,r){var u=s?n[s[2]]:z(o,n),a=s?r[s[2]]:z(o,r),c=d?n[d[2]]:z(i,n),l=d?r[d[2]]:z(i,r),f={key:u,value:c};return u===a&&c===l?[f,!1]:(u!==a&&t.removeAttribute(a),u?(f[u]=c,H(t,{name:u,value:c},p(e[u])),[f,!0]):[f,!0])}}):n.push({name:o,value:i,isBoolean:p(e[o])})},c=0;c<u.length;c++)a(c);for(var s=e.childNodes||[],d=function(e){var t=s[e];return t.nodeType===o?(t.textContent.split(O).filter(function(e){return!!e}).forEach(function(e){var t=e.match(S);if(t){var n=t[2];r.push(function(e){return function(t){return J(t[n],e)}})}else r.push({nodeType:o,textContent:e})}),"continue"):t.nodeType===i?(t.textContent.match(O)?r.push(function(e){var n=document.createComment(""),r=t.textContent;return e.appendChild(n),function(e){n.textContent=z(r,e)}}):r.push({nodeType:i,textContent:t.textContent}),"continue"):void r.push(Z(t))},l=0;l<s.length;l++)d(l);var f=e.tagName;if(f===A.toUpperCase()){var h=e.attributes[D].value,y=h.match(S);return function(e){var n=void 0;return function(r,o){var i=y?r[y[2]]:z(h,r),u=y?o[y[2]]:z(h,o);if(n&&i===u)return n(r);var a,c,s,d=P(i),l={childNodes:[Object.assign({},t,{tagName:i})]};if(d===_){var f=W(l,{appendChild:m,replaceChild:m,childNodes:[(a={props:function(t){return J(i(t),e)}},c={},s=Object.assign(g({props:m,tagName:null,setAttribute:function(e,t){"class"===e&&(c=t.split(" ").reduce(function(e,t){return Object.assign(e,g({},t,!0))},{}))},removeAttribute:m,classList:{add:function(e){c[e]=!0,s.className=Object.keys(c).join(" ").trim()},remove:function(e){delete c[e],s.className=Object.keys(c).join(" ").trim()}},className:"",attributes:[],childNodes:[],appendChild:m,isVirtual:!0},L,!0),a),s)]}),p=v(f,1);return(n=p[0])(r)}var N=W(l,e,{useDocFragment:!0}),C=v(N,2),b=C[0],x=C[1];b(r),x(),n=b}}}return f&&(t.tagName=e.tagName.toLowerCase().replace(T,"").toUpperCase()),t}function q(e){var t,n=(t=e,Array.isArray(t)?t:Array.from(t)),r=n[0];return n.slice(1).reduce(function(e,t,n){var r=""+w+n+j;return e.concat(r).concat(t)},r)}function G(e){var t=(e?"(":"")+"\\d+"+(e?")":"");return"("+h(w)+t+h(j)+")"}function J(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:document.createDocumentFragment(),n=C.get(t)||{},r=P(e),o=n.lastChunk,i=n.lastRenderedChunkType,u=n.update;if(o===e)return t;if(r===M)return K[M](t,e),t;if(i!==r)c(t);else if(u){var a=u(e);return f(a)&&(n.update=a),n.lastChunk=e,t}return C.set(t,{update:K[r](t,e),lastRenderedChunkType:r,lastChunk:e}),t}var K=(g(n={},$,function e(t,n){var r=W({childNodes:[].concat(n).map(function(e,t){return function(e){return function(n){return J(n[t],e)}}})},t,{useDocFragment:!0}),o=v(r,2),i=o[0],u=o[1];return i(n),u(),function(r){if(r.length!==n.length)return e(t,r);i(r)}}),g(n,U,c),g(n,B,function(e,t){var n=document.createTextNode(t);return e.appendChild(n),function(e){return n.textContent=e}}),g(n,I,function(e,t){return e.appendChild(t),function(t){e.childNodes.length>1&&e.childNodes.slice(1).forEach(function(t){return e.removeChild(t)}),e.replaceChild(t,e.childNodes[0])}}),g(n,M,function(e,t){t.then(function(t){e.update(),J(t,e)})}),g(n,_,function(e,t){var n=t(e);return function(t){n=t(e,n)}}),n);function Q(e,t,n){for(var r=t.attributes,o=e.attributes,i=0;i<o.length;i++)e.removeAttribute(o[i].name);for(var u=[],a={},c=0;c<r.length;c++){var s=r[c];if(f(s))u.push(s(e));else{var d=s.name,l=s.value,p=s.isBoolean;H(e,{name:d,value:l},p),a["class"===d?"className":d]=l}}if(e[L]&&u.push(function(e,n){return[{key:"children",value:function(n,r){if(r)return r(e),r;var o=W(t,n,{useDocFragment:!0}),i=v(o,2),u=i[0],a=i[1];return u(e),a(),u}},!0]}),"props"in e){var h=f(e.props)?e.props:function(t,n){return n&&(e.props=t)};if(u.length)return[function(e,t){var n=u.reduce(function(n,r){var o=v(n,2),i=o[0],u=o[1],a=r(e,t),c=v(a,2),s=c[0],d=s.key,l=s.value,f=c[1],p="string"==typeof d||"number"==typeof d?g({},d,l):{};return[Object.assign({},i,p),u||f]},[a,!1]),r=v(n,2),o=r[0],i=r[1];h(o,i)}];h(a,!0)}return u}function W(e,n){var a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(n[L])return[m,[]];for(var c,d,l=[],p=a.useDocFragment?document.createDocumentFragment():n,h=e.childNodes,v=function(e){return e?function(t){return n.replaceChild(t,e)}:function(e){return p.appendChild(e)}},g=0,y=0;;g++){var N=h[g],C=n.childNodes[g+y];if(!N&&!C)break;if(N)if(C&&s(N,C))d=C,(o===(c=N).nodeType!==c.nodeType||c.textContent!==d.textContent)&&s(N,C)&&(l=l.concat(W(N,C)[0]).concat(Q(C,N)));else{var x=v(C);if(f(N)){var w=b.get(C);if(!w){var j=(w=new t).startNode;x(w.extractContents()),b.set(j,w)}var T=N(w);T&&l.push(T),w.update(),y+=w.childNodes.length+1;continue}switch(N.nodeType){case o:x(document.createTextNode(N.textContent));break;case i:x(document.createComment(N.textContent));break;case r:var k=N.namespaceURI,A=N.tagName,D=void 0;D=C&&C[L]?C:k===u?document.createElement(A.toLowerCase()):document.createElementNS(k,A.toLowerCase()),l=l.concat(W(N,D)[0]).concat(Q(D,N)),x(D)}}else n.removeChild(C),g--}var R=[];return[function e(t){return l.forEach(function(e){return e(t,R)}),R=t,e},function(){return a.useDocFragment?n.appendChild(p):void 0}]}e.NodesRange=t,e.emptyNode=c,e.render=J,e.morph=W,e.html=function(){for(var e=arguments.length,t=Array(e>1?e-1:0),n=1;n<e;n++)t[n-1]=arguments[n];var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];if(!r.length)return this;var o,i=function(e){for(var t=5381,n=e.length;n;)t=33*t^e.charCodeAt(--n);return t>>>0}(r.join(w+j)),u=N[i],a=void 0;if(d(u))a=u;else{var c=q(r);o=function(e){return e.replace(k,"<$1"+T+"$2")}(function(e){return e.replace(E,"<$1$2></$1>")}(c.replace(R,function(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];t[0];var r=t[1],o=t[2],i=t[3],u=(t[4],t[5],t[6],t[7],t[8],t[9]);return o?"</"+A+">":""+r+A+" "+D+'="'+i+'"'+(u||"")}))),a=Z(x.parseFromString(o,"text/html").body),N[i]=a}return function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:document.createDocumentFragment(),n=arguments[1];if(n&&n.templateId===i)return n(t);var r=W(a,e,{useDocFragment:!0}),o=v(r,2),u=o[0],c=o[1];return u(t),c(),u.templateId=i,u}},e.stopNode=function(){},Object.defineProperty(e,"__esModule",{value:!0})});
{
"name": "@modulor-js/html",
"version": "1.1.3",
"version": "1.2.0",
"description": "Template engine based on tagged template literals",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -54,3 +54,3 @@ # modulor-html [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Missing%20template%20engine%20for%20Web%20Components&url=https://github.com/modulor-js/modulor-html&hashtags=webcomponents,template-engine,js)

- Small size (**3.3kb** minigzipped)
- Small size (**4kb** minigzipped)

@@ -57,0 +57,0 @@ - High performance

@@ -55,1 +55,3 @@ import { TEXT_NODE } from './constants';

};
export function noop(){}
import { NodesRange } from './range';
import {
emptyNode, same, hash, regExpEscape,
emptyNode, same, hash, regExpEscape, noop,
isSameTextNode, isDefined, isPromise, isFunction, isObject, isBoolean

@@ -25,2 +25,6 @@ } from './helpers';

let specialTagName = `modulor-dynamic-tag-${+new Date()}`;
let specialAttributeName = `modulor-chunk-${+new Date()}`;
let dynamicTagsRegex = getDynamicTagsRegex();
const selfClosingRegex = /<([^\s]+)([ ].+)?\/([ ]+)?>/igm;

@@ -32,16 +36,24 @@

let preventChildRenderingProp = 'preventChildRendering';
const CHUNK_TYPE_FUNCTION = 'function';
const CHUNK_TYPE_ARRAY = 'array';
const CHUNK_TYPE_ELEMENT = 'element';
const CHUNK_TYPE_PROMISE = 'promise';
const CHUNK_TYPE_UNDEFINED = 'undefined';
const CHUNK_TYPE_TEXT = 'text';
function getChunkType(chunk){
if(isFunction(chunk)){
return 'function';
return CHUNK_TYPE_FUNCTION;
} else if(chunk instanceof Array){
return 'array';
return CHUNK_TYPE_ARRAY;
} else if(chunk instanceof Node){
return 'element';
return CHUNK_TYPE_ELEMENT;
} else if(isPromise(chunk)){
return 'promise';
return CHUNK_TYPE_PROMISE;
} else if(!isDefined(chunk)){
return 'undefined';
return CHUNK_TYPE_UNDEFINED;
}
return 'text';
return CHUNK_TYPE_TEXT;
}

@@ -90,9 +102,43 @@

const chunkType = getChunkType(value);
if(chunkType === 'promise'){
if(chunkType === CHUNK_TYPE_PROMISE){
return value.then((newValue) => applyClassFn(newValue, fn));
}
let classesArray = chunkType === 'array' ? value : ('' + value).split(' ');
let classesArray = chunkType === CHUNK_TYPE_ARRAY ? value : ('' + value).split(' ');
return classesArray.forEach((className) => fn(className));
}
function createVirtualElement(extend){
let classes = {};
const element = Object.assign({
props: noop,
tagName: null,
setAttribute: (name, value) => {
if(name === 'class'){
classes = value.split(' ').reduce((acc, className) => Object.assign(acc, {
[className]: true
}), {});
}
},
removeAttribute: noop,
classList: {
add: (value) => {
classes[value] = true;
element.className = Object.keys(classes).join(' ').trim();
},
remove: (value) => {
delete classes[value];
element.className = Object.keys(classes).join(' ').trim();
}
},
className: '',
attributes: [],
childNodes: [],
appendChild: noop,
isVirtual: true,
[preventChildRenderingProp]: true
}, extend);
return element;
};
function processNode($container){

@@ -107,5 +153,3 @@ const nodeCopy = {

if($container.tagName){
nodeCopy.tagName = $container.tagName.toLowerCase().replace(sanitizeNodePrefix, '').toUpperCase();
}
const { attributes, childNodes } = nodeCopy;

@@ -115,2 +159,5 @@ const childAttributes = $container.attributes || [];

const { name, value } = childAttributes[j];
if(name === specialAttributeName){
continue;
}

@@ -128,6 +175,6 @@ const nameIsDynamic = name.match(findChunksRegex);

}, [[], []]);
nodeCopy.attributes.push({ name, value: initial.join(' ') });
dynamic.length && nodeCopy.attributes.push((target, cbk) => {
attributes.push({ name, value: initial.join(' ') });
dynamic.length && attributes.push((target) => {
return (values, prevValues) => {
dynamic.forEach((className) => {
const updated = dynamic.reduce((acc, className) => {
const matchClass = className.match(matchChunkRegex);

@@ -139,4 +186,7 @@ const newValue = matchClass ? values[matchClass[2]] : replaceTokens(className, values);

newValue && applyClassFn(newValue, (className) => target.classList.add(className));
return true;
}
});
return acc;
}, false);
return [{ key: 'className', value: target.className }, updated];
};

@@ -148,4 +198,4 @@ });

if(nameIsDynamic || valueIsDynamic){
nodeCopy.attributes.push((target) => {
return (values, prevValues) => {
attributes.push((target) => {
return function update(values, prevValues){
const preparedName = matchName ? values[matchName[2]] : replaceTokens(name, values);

@@ -157,4 +207,5 @@ const preparedPrevName = matchName ? prevValues[matchName[2]] : replaceTokens(name, prevValues);

const prop = { key: preparedName, value: preparedValue };
if(preparedName === preparedPrevName && preparedValue === preparedPrevValue){
return;
return [prop, false];
}

@@ -167,8 +218,8 @@

if(!preparedName){
return;
return [prop, true];
}
prop[preparedName] = preparedValue;
applyAttribute(target, { name: preparedName, value: preparedValue }, isBoolean($container[preparedName]));
return { [preparedName]: preparedValue };
return [prop, true];
};

@@ -178,9 +229,9 @@

} else {
nodeCopy.attributes.push({ name, value, isBoolean: isBoolean($container[name]) });
attributes.push({ name, value, isBoolean: isBoolean($container[name]) });
}
}
const childNodes = $container.childNodes || [];
for(let i = 0; i < childNodes.length; i++){
const $childNode = childNodes[i];
const containerChildNodes = $container.childNodes || [];
for(let i = 0; i < containerChildNodes.length; i++){
const $childNode = containerChildNodes[i];
if($childNode.nodeType === TEXT_NODE){

@@ -192,7 +243,7 @@ const chunks = $childNode.textContent.split(findChunksRegex);

const matchIndex = match[2];
nodeCopy.childNodes.push((range) => {
childNodes.push((range) => {
return (values) => render(values[matchIndex], range);
});
} else {
nodeCopy.childNodes.push({
childNodes.push({
nodeType: TEXT_NODE,

@@ -207,3 +258,3 @@ textContent: chunk,

if($childNode.textContent.match(findChunksRegex)){
nodeCopy.childNodes.push((range) => {
childNodes.push((range) => {
const $element = document.createComment('');

@@ -217,3 +268,3 @@ const content = $childNode.textContent;

} else {
nodeCopy.childNodes.push({
childNodes.push({
nodeType: COMMENT_NODE,

@@ -225,5 +276,50 @@ textContent: $childNode.textContent,

}
nodeCopy.childNodes.push(processNode($childNode));
childNodes.push(processNode($childNode));
}
const tagName = $container.tagName;
if(tagName === specialTagName.toUpperCase()){
const chunkName = $container.attributes[specialAttributeName].value;
const matchChunk = chunkName.match(matchChunkRegex);
return (range) => {
let update;
return (values, prevValues) => {
const newValue = matchChunk ? values[matchChunk[2]] : replaceTokens(chunkName, values);
const oldValue = matchChunk ? prevValues[matchChunk[2]] : replaceTokens(chunkName, prevValues);
if(update && newValue === oldValue){
return update(values);
}
const chunkType = getChunkType(newValue);
const container = {
childNodes: [Object.assign({}, nodeCopy, {
tagName: newValue
})]
};
if(chunkType === CHUNK_TYPE_FUNCTION){
const target = {
appendChild: noop,
replaceChild: noop,
childNodes: [createVirtualElement({
props: (value) => render(newValue(value), range)
})]
};
[update] = morph(container, target);
return update(values);
}
const [newUpdate, initialRender] = morph(container, range, { useDocFragment: true });
newUpdate(values);
initialRender();
update = newUpdate;
};
};
} else if(tagName){
nodeCopy.tagName = $container.tagName.toLowerCase().replace(sanitizeNodePrefix, '').toUpperCase();
}
return nodeCopy;

@@ -252,2 +348,16 @@ }

function getDynamicTagsRegex(groupMatches = false){
const tokenRegEx = `(${regExpEscape(PREFIX)}([^ >]+)${regExpEscape(POSTFIX)})`;
return new RegExp(`(<([ /])?)(([^ >]+)?(${tokenRegEx})([a-zA-Z0-9-_]+)?)(([ ][^])?>)?`, 'igm');
}
function replaceDynamicTags(str){
return str.replace(dynamicTagsRegex, (...args) => {
const [_, opening, isClosing, chunkName, __, ___, suffix, ____, _____, closing] = args;
return isClosing
? `</${specialTagName}>`
: `${opening}${specialTagName} ${specialAttributeName}="${chunkName}"${closing || ''}`
});
};
function openSelfClosingTags(str){

@@ -264,4 +374,4 @@ return str.replace(selfClosingRegex, '<$1$2></$1>');

}
if(chunkType === 'promise'){
chunkProcessingFunctions['promise'](range, value);
if(chunkType === CHUNK_TYPE_PROMISE){
chunkProcessingFunctions[CHUNK_TYPE_PROMISE](range, value);
return range;

@@ -286,3 +396,3 @@ }

const chunkProcessingFunctions = {
'array': function processArrayChunk(range, value){
[CHUNK_TYPE_ARRAY]: function processArrayChunk(range, value){
const preprocessedChunksContainer = {

@@ -303,4 +413,4 @@ childNodes: [].concat(value).map((chunk, index) => {

},
'undefined': emptyNode,
'text': (range, value) => {
[CHUNK_TYPE_UNDEFINED]: emptyNode,
[CHUNK_TYPE_TEXT]: (range, value) => {
const textNode = document.createTextNode(value);

@@ -310,3 +420,3 @@ range.appendChild(textNode);

},
'element': (range, value) => {
[CHUNK_TYPE_ELEMENT]: (range, value) => {
range.appendChild(value);

@@ -320,3 +430,3 @@ return (value) => {

},
'promise': (range, value) => {
[CHUNK_TYPE_PROMISE]: (range, value) => {
value.then((response) => {

@@ -327,3 +437,3 @@ range.update();

},
'function': (range, value) => {
[CHUNK_TYPE_FUNCTION]: (range, value) => {
let result = value(range);

@@ -336,3 +446,3 @@ return (value) => {

function copyAttributes(target, source){
function copyAttributes(target, source, interceptChildrenRendering){
const sourceAttributes = source.attributes;

@@ -360,15 +470,36 @@ const targetAttributes = target.attributes;

applyAttribute(target, { name, value }, isBoolean);
props[name] = value;
props[name === 'class' ? 'className' : name] = value;
}
if(target[preventChildRenderingProp]){
updates.push((values, prevValues) => {
const children = (range, update) => {
if(update){
update(values);
return update;
}
const [newUpdate, initialRender] = morph(source, range, { useDocFragment: true });
newUpdate(values);
initialRender();
return newUpdate;
};
return [{ key: 'children', value: children }, true];
});
}
if('props' in target){
const setProps = isFunction(target.props)
? target.props
: (props, updated) => updated && (target.props = props);
if(updates.length){
return [(values, prevValues) => {
const dynamicProps = updates.reduce((acc, u) => Object.assign(acc, u(values, prevValues)), {});
if(Object.keys(dynamicProps).length){
target.props = Object.assign(props, dynamicProps);
}
const [newProps, updated] = updates.reduce(([props, accUpdated], u) => {
const [{ key, value }, updated] = u(values, prevValues);
const prop = (typeof key === 'string' || typeof key === 'number') ? { [key]: value } : {};
return [Object.assign({}, props, prop), accUpdated || updated];
}, [props, false]);
setProps(newProps, updated);
}];
}
target.props = props;
setProps(props, true);
}

@@ -381,2 +512,6 @@ return updates;

if($target[preventChildRenderingProp]){
return [noop, []];
}
let updates = [];

@@ -447,9 +582,16 @@

const namespaceURI = $sourceElement.namespaceURI;
const tagName = $sourceElement.tagName.toLowerCase();
const newChild = namespaceURI === DEFAULT_NAMESPACE_URI
? document.createElement(tagName)
: document.createElementNS(namespaceURI, tagName);
const tagName = $sourceElement.tagName;
updates = updates
.concat(morph($sourceElement, newChild)[0])
let newChild;
let morphUpdates = [];
if($targetElement && $targetElement[preventChildRenderingProp]){
newChild = $targetElement;
} else {
newChild = namespaceURI === DEFAULT_NAMESPACE_URI
? document.createElement(tagName.toLowerCase())
: document.createElementNS(namespaceURI, tagName.toLowerCase());
}
updates = updates.concat(morph($sourceElement, newChild)[0])
.concat(copyAttributes(newChild, $sourceElement));

@@ -506,3 +648,3 @@

const template = prepareLiterals(chunks);
container = generateContainer(sanitize(openSelfClosingTags(template)));
container = generateContainer(sanitize(openSelfClosingTags(replaceDynamicTags(template))));
templatesCache[templateId] = container;

@@ -540,6 +682,8 @@ } else {

replaceTokens, processNode, generateContainer,
sanitize, copyAttributes, prepareLiterals, openSelfClosingTags,
sanitize, copyAttributes, prepareLiterals, openSelfClosingTags, replaceDynamicTags,
setPrefix: (value) => PREFIX = value,
setPostfix: (value) => POSTFIX = value,
setSanitizeNodePrefix: (value) => sanitizeNodePrefix = value,
setSpecialTagName: (value) => specialTagName = value,
setSpecialAttributeName: (value) => specialAttributeName = value,
updateChunkRegexes: () => {

@@ -549,2 +693,3 @@ findChunksRegex = new RegExp(getTokenRegExp(), 'ig');

matchChunkRegex = new RegExp(`^${getTokenRegExp(true)}$`);
dynamicTagsRegex = getDynamicTagsRegex();
}

@@ -551,0 +696,0 @@ });

@@ -1,2 +0,2 @@

import { html, render, r, stopNode, Template, containersMap } from '../src/html';
import { html, render, r, stopNode, Template, containersMap } from '@modulor-js/html';

@@ -8,19 +8,33 @@

//const container = document.createElement('div');
////const container2 = document.createElement('div');
const container = document.createElement('div');
//const container2 = document.createElement('div');
const comp = (props) => {
//console.log(props);
//return children;
return html`
<div test="myel">
${props.foo}
${props.foo ? props.children : void 0}
</div>
`;
};
//const tpl = (scope) => html`
//${scope.a.map((item, index) => html`
//<span class="foo foo-${index} bar-${item}">${item}</span>
//`)}
const tpl = (scope) => html`
<${comp} foo="${scope.a[0]}">
<div>${scope.a[1]}</div>
</${comp}>
`;
//const tpl2 = (scope) => html`
//<span bla="${scope.a}">${scope.b}</div>
//`;
////const tpl2 = (scope) => html`
////<span bla="${scope.a}">${scope.b}</div>
////`;
//const rr = tpl2({ a: 1});
////const rr = tpl2({ a: 1});
//render(tpl({ a: [1,2,3] }), container);
render(tpl({ a: [1,6,3] }), container);
render(tpl({ a: [2,6,3] }), container);
render(tpl({ a: [0,7,3] }), container);
//console.log(container.innerHTML);
render(tpl({ a: [1,8,3] }), container);
//console.log(container.innerHTML);
//render(tpl({ a: [3,4,5] }), container);

@@ -27,0 +41,0 @@ //console.log(container.innerHTML);

@@ -622,1 +622,624 @@ import 'web-components-polyfill';

});
describe('dynamic tags', () => {
describe('string value', () => {
it('renders tag with dynamic name', () => {
const $container = document.createElement('div');
const tpl = (scope) => html`
<x-${scope[0]}/>
<x-${scope[1]}></x-${scope[1]}>
<${scope[2]}-y-${scope[0]}/>
<${scope[1]}/>
`;
const values1 = ['foo', 'bar', 'baz'];
render(tpl(values1), $container);
expect($container.innerHTML).toBe(`<x-${values1[0]}></x-${values1[0]}>
<x-${values1[1]}></x-${values1[1]}>
<${values1[2]}-y-${values1[0]}></${values1[2]}-y-${values1[0]}>
<${values1[1]}></${values1[1]}>
`);
const values2 = ['quux', 'bla', 'test'];
render(tpl(values2), $container);
expect($container.innerHTML).toBe(`<x-${values2[0]}></x-${values2[0]}>
<x-${values2[1]}></x-${values2[1]}>
<${values2[2]}-y-${values2[0]}></${values2[2]}-y-${values2[0]}>
<${values2[1]}></${values2[1]}>
`);
const values3 = [1, 'bar', 'baz'];
render(tpl(values3), $container);
expect($container.innerHTML).toBe(`<x-${values3[0]}></x-${values3[0]}>
<x-${values3[1]}></x-${values3[1]}>
<${values3[2]}-y-${values3[0]}></${values3[2]}-y-${values3[0]}>
<${values3[1]}></${values3[1]}>
`);
});
it('handles attributes in dynamic tags', () => {
const $container = document.createElement('div');
const tpl = ({ tagName, values }) => html`
<span></span>
<x-${tagName} foo="${values[0]}" bar-${values[1]}="${values[2]}" class="quux ${values[3]}"/>
`;
const values1 = { tagName: 'div', values: ['foo', 1, 'bar', 'baz'] };
render(tpl(values1), $container);
expect($container.innerHTML).toBe(`<span></span>
<x-${values1.tagName} class="quux ${values1.values[3]}" foo="${values1.values[0]}" bar-${values1.values[1]}="${values1.values[2]}"></x-${values1.tagName}>
`);
const values2 = { tagName: 'span', values: ['foo', 1, 'bar', 'baz'] };
render(tpl(values2), $container);
expect($container.innerHTML).toBe(`<span></span>
<x-${values2.tagName} class="quux ${values2.values[3]}" foo="${values2.values[0]}" bar-${values2.values[1]}="${values2.values[2]}"></x-${values2.tagName}>
`);
const values3 = { tagName: 'span', values: ['quux', 'test', 3, 'baz'] };
render(tpl(values3), $container);
expect($container.innerHTML).toBe(`<span></span>
<x-${values3.tagName} class="quux ${values3.values[3]}" foo="${values3.values[0]}" bar-${values3.values[1]}="${values3.values[2]}"></x-${values3.tagName}>
`);
});
it('renders child content correctly', () => {
const $container = document.createElement('div');
const tpl = ({ tagName, value, list }) => html`
<x-${tagName}>
${list ? list.map((val) => html`
<span>${val}</span>
`) : void 0}
<div>${value}</div>
</x-${tagName}>
`;
const values1 = { tagName: 'foo', value: 'bar' };
render(tpl(values1), $container);
expect($container.innerHTML).toBe(`<x-${values1.tagName}>
<div>${values1.value}</div>
</x-${values1.tagName}>
`);
const values2 = { tagName: 'foo', value: 'baz', list: ['xxx', 'yyy'] };
render(tpl(values2), $container);
expect($container.innerHTML).toBe(`<x-${values2.tagName}>
<span>${values2.list[0]}</span>
<span>${values2.list[1]}</span>
<div>${values2.value}</div>
</x-${values2.tagName}>
`);
const values3 = { tagName: 'bar', value: 'baz', list: ['xxx', 'yyy'] };
render(tpl(values3), $container);
expect($container.innerHTML).toBe(`<x-${values3.tagName}>
<span>${values3.list[0]}</span>
<span>${values3.list[1]}</span>
<div>${values3.value}</div>
</x-${values3.tagName}>
`);
const values4 = { tagName: 'bar', value: 'baz' };
render(tpl(values4), $container);
expect($container.innerHTML).toBe(`<x-${values4.tagName}>
<div>${values4.value}</div>
</x-${values4.tagName}>
`);
});
it('renders child content only on demand', () => {
const $container = document.createElement('div');
const fn1 = jest.fn();
const fn2 = jest.fn();
const fn3 = jest.fn();
const fn4 = jest.fn();
const tpl = ({ tagName, tagName2 }) => html`
<x-${tagName} ${fn3}>
${fn1}
</x-${tagName}>
<${tagName2} ${fn4}>
${fn2}
</${tagName2}>
`;
const values1 = { tagName: 'foo', tagName2: 'div' };
render(tpl(values1), $container);
expect($container.innerHTML).toBe(`<x-${values1.tagName}>
</x-${values1.tagName}>
<${values1.tagName2}>
</${values1.tagName2}>
`);
expect(fn1).toHaveBeenCalledTimes(1);
expect(fn2).toHaveBeenCalledTimes(1);
expect(fn3).toHaveBeenCalledTimes(1);
expect(fn4).toHaveBeenCalledTimes(1);
const values2 = { tagName: 'foo', tagName2: 'span' };
render(tpl(values2), $container);
expect($container.innerHTML).toBe(`<x-${values2.tagName}>
</x-${values2.tagName}>
<${values2.tagName2}>
</${values2.tagName2}>
`);
expect(fn1).toHaveBeenCalledTimes(1);
expect(fn2).toHaveBeenCalledTimes(2);
expect(fn3).toHaveBeenCalledTimes(1);
expect(fn4).toHaveBeenCalledTimes(2);
const values3 = { tagName: 'foo', tagName2: 'div' };
render(tpl(values3), $container);
expect($container.innerHTML).toBe(`<x-${values3.tagName}>
</x-${values3.tagName}>
<${values3.tagName2}>
</${values3.tagName2}>
`);
expect(fn1).toHaveBeenCalledTimes(1);
expect(fn2).toHaveBeenCalledTimes(3);
expect(fn3).toHaveBeenCalledTimes(1);
expect(fn4).toHaveBeenCalledTimes(3);
});
});
describe('function value', () => {
describe('props handling', () => {
const $container = document.createElement('div');
const Component = jest.fn();
it('handles simple attributes', () => {
const tpl = (values) => html`
<${Component} foo="xxx" ${values[0]}="yyy" ${values[1]}="${values[2]}"/>
`;
const values = ['zzz', 'aaa', true];
render(tpl(values), $container);
expect(Component).toHaveBeenCalledWith({
foo: 'xxx',
[values[0]]: 'yyy',
[values[1]]: values[2],
children: expect.any(Function)
});
//maybe incorrect behaviour below. maybe should not be called
Component.mockReset();
render(tpl(values), $container);
expect(Component).toHaveBeenCalledWith({
foo: 'xxx',
[values[0]]: 'yyy',
[values[1]]: values[2],
children: expect.any(Function)
});
Component.mockReset();
render(tpl(values), $container);
expect(Component).toHaveBeenCalledWith({
foo: 'xxx',
[values[0]]: 'yyy',
[values[1]]: values[2],
children: expect.any(Function)
});
Component.mockReset();
const values2 = ['bbb', 'ccc', { a: [] }];
render(tpl(values2), $container);
expect(Component).toHaveBeenCalledWith({
foo: 'xxx',
[values2[0]]: 'yyy',
[values2[1]]: values2[2],
children: expect.any(Function)
});
Component.mockReset();
const values3 = ['bbb', 'ccc'];
render(tpl(values3), $container);
expect(Component).toHaveBeenCalledWith({
foo: 'xxx',
[values3[0]]: 'yyy',
children: expect.any(Function)
});
Component.mockReset();
const values4 = ['bbb', void 0, [1]];
render(tpl(values4), $container);
expect(Component).toHaveBeenCalledWith({
foo: 'xxx',
[values4[0]]: 'yyy',
children: expect.any(Function)
});
});
it('passes only attributes where name is string or number', () => {
const tpl = (values) => html`
<${Component} ${values[0]}="yyy" ${values[1]}="${values[2]}"/>
`;
const values = ['zzz', 'aaa', true];
render(tpl(values), $container);
expect(Component).toHaveBeenCalledWith({
[values[0]]: 'yyy',
[values[1]]: values[2],
children: expect.any(Function)
});
Component.mockReset();
const values2 = [() => {}, true, true];
render(tpl(values2), $container);
expect(Component).toHaveBeenCalledWith({
children: expect.any(Function)
});
Component.mockReset();
const values3 = [null, {}, true];
render(tpl(values3), $container);
expect(Component).toHaveBeenCalledWith({
children: expect.any(Function)
});
});
it('handles simple classes', () => {
const tpl = (values) => html`
<${Component} class="foo ${values[0]} ${values[1]}"/>
`;
const values = ['zzz'];
render(tpl(values), $container);
expect(Component).toHaveBeenCalledWith({
className: `foo ${values[0]}`,
children: expect.any(Function)
});
Component.mockReset();
const values2 = [];
render(tpl(values2), $container);
expect(Component).toHaveBeenCalledWith({
className: `foo`,
children: expect.any(Function)
});
Component.mockReset();
const values3 = ['bla', 'bar'];
render(tpl(values3), $container);
expect(Component).toHaveBeenCalledWith({
className: `foo ${values3[0]} ${values3[1]}`,
children: expect.any(Function)
});
});
it('handles complex classes', () => {
const Component = jest.fn();
const tpl = (values) => html`
<${Component} class="${values[0] ? values[1] : void 0} ${values[2]} ${values[3]}"/>
`;
const values = [true, 'zzz', ['yyy', 'aaa'], null];
render(tpl(values), $container);
expect(Component).toHaveBeenCalledWith({
className: `${values[1]} ${values[2].join(' ')}`,
children: expect.any(Function)
});
Component.mockReset();
const values2 = [false, 'zzz', 'yyy', false];
render(tpl(values2), $container);
expect(Component).toHaveBeenCalledWith({
className: `${values2[2]}`,
children: expect.any(Function)
});
Component.mockReset();
const values3 = [true, ['bbb'], ['yyy xxx', 'zzz']];
render(tpl(values3), $container);
expect(Component).toHaveBeenCalledWith({
className: `${values3[1].join(' ')} ${values3[2].join(' ')}`,
children: expect.any(Function)
});
});
});
describe('child content rendering', () => {
it('handles ternary operator', () => {
const $container = document.createElement('div');
const Component = ({ children, show }) => html`
<span id="bar">${show}</span>
<div class="component-wrapper">
${show ? children : void 0}
</div>
`;
const tpl = ({ show, values }) => html`
<${Component} show=${show}>
<div id="foo"></div>
<span test="${values[0]}">${values[1]}</span>
</${Component}>
`;
const values1 = { show: true, values: ['foo', 'bar'] };
render(tpl(values1), $container);
expect($container.innerHTML).toBe(`<span id="bar">${values1.show}</span>
<div class="component-wrapper">
<div id="foo"></div>
<span test="${values1.values[0]}">${values1.values[1]}</span>
</div>
`);
const values2 = { show: false, values: ['foo', 'bar'] };
render(tpl(values2), $container);
expect($container.innerHTML).toBe(`<span id="bar">${values2.show}</span>
<div class="component-wrapper">
</div>
`);
const values3 = { show: true, values: ['baz', 'quux'] };
render(tpl(values3), $container);
expect($container.innerHTML).toBe(`<span id="bar">${values3.show}</span>
<div class="component-wrapper">
<div id="foo"></div>
<span test="${values3.values[0]}">${values3.values[1]}</span>
</div>
`);
const values4 = { show: true, values: ['baz', 'zzz'] };
render(tpl(values4), $container);
expect($container.innerHTML).toBe(`<span id="bar">${values4.show}</span>
<div class="component-wrapper">
<div id="foo"></div>
<span test="${values4.values[0]}">${values4.values[1]}</span>
</div>
`);
});
it('handles arrays in child content', () => {
const $container = document.createElement('div');
const Component = ({ children }) => html`${children}`;
const tpl = ({ values }) => html`
<${Component}>
${values.map((value) => html`
<span>${value}</span>
`)}
</${Component}>
`;
const values1 = { values: ['foo', 'bar'] };
render(tpl(values1), $container);
expect($container.innerHTML).toBe(`
<span>${values1.values[0]}</span>
<span>${values1.values[1]}</span>
`);
const values2 = { values: ['quux', 'zzz'] };
render(tpl(values2), $container);
expect($container.innerHTML).toBe(`
<span>${values2.values[0]}</span>
<span>${values2.values[1]}</span>
`);
const values3 = { values: ['quux', 'zzz', 'yyy'] };
render(tpl(values3), $container);
expect($container.innerHTML).toBe(`
<span>${values3.values[0]}</span>
<span>${values3.values[1]}</span>
<span>${values3.values[2]}</span>
`);
const values4 = { values: ['quux', 'yyy'] };
render(tpl(values4), $container);
expect($container.innerHTML).toBe(`
<span>${values4.values[0]}</span>
<span>${values4.values[1]}</span>
`);
});
it('handles nested components', () => {
const $container = document.createElement('div');
const ComponentA = ({ children, foo }) => html`
<div id="component-a" foo=${foo}>
${children}
</div>
`;
const ComponentB = ({ value }) => html`
<span id="component-b">
<${ComponentA} foo=${value + '-bla'}>
<p>${value}</p>
</${ComponentA}>
</span>
`;
const tpl = ({ values }) => html`
<${ComponentB} value=${values[0]}/>
`;
const values1 = { values: ['foo'] };
render(tpl(values1), $container);
expect($container.innerHTML).toBe(`<span id="component-b">
<div id="component-a" foo="${values1.values[0]}-bla">
<p>${values1.values[0]}</p>
</div>
</span>
`);
const values2 = { values: ['bar'] };
render(tpl(values2), $container);
expect($container.innerHTML).toBe(`<span id="component-b">
<div id="component-a" foo="${values2.values[0]}-bla">
<p>${values2.values[0]}</p>
</div>
</span>
`);
});
});
});
it('handles mixed content', () => {
const $container = document.createElement('div');
const Component = ({ children }) => html`
<div id="component">
${children}
</div>
`;
const tpl = ({ tag, childContent }) => html`
<${tag}>
<span>${childContent}</span>
</${tag}>
`;
const values1 = { tag: 'x-foo', childContent: 'test' };
render(tpl(values1), $container);
expect($container.innerHTML).toBe(`<${values1.tag}>
<span>${values1.childContent}</span>
</${values1.tag}>
`);
const values2 = { tag: Component, childContent: 'foo' };
render(tpl(values2), $container);
expect($container.innerHTML).toBe(`<div id="component">
<span>${values2.childContent}</span>
</div>
`);
const values3 = { tag: 'x-foo', childContent: 'foo' };
render(tpl(values3), $container);
expect($container.innerHTML).toBe(`<${values3.tag}>
<span>${values3.childContent}</span>
</${values3.tag}>
`);
const values4 = { tag: 'x-bar', childContent: 'foo' };
render(tpl(values4), $container);
expect($container.innerHTML).toBe(`<${values4.tag}>
<span>${values4.childContent}</span>
</${values4.tag}>
`);
});
});
import {
html, prepareLiterals, replaceTokens, sanitize, openSelfClosingTags, setPrefix, setPostfix, setSanitizeNodePrefix, updateChunkRegexes
html, prepareLiterals, replaceTokens, sanitize, openSelfClosingTags, replaceDynamicTags,
setPrefix, setPostfix, setSanitizeNodePrefix, updateChunkRegexes, setSpecialTagName, setSpecialAttributeName
} from '../../src/html';

@@ -8,2 +9,4 @@

setSanitizeNodePrefix('sanitize:');
setSpecialTagName('modulor-dynamic-tag');
setSpecialAttributeName('modulor-chunk');
updateChunkRegexes();

@@ -42,2 +45,6 @@

expectedReplacedTokens: 'foo 1 bar 2 baz',
},
{
parsedString: prepareLiterals`<${'div'}><${'span'}></${'span'}></${'div'}>`,
expectedPreparedLiterals: '<{modulor_html_chunk:0}><{modulor_html_chunk:1}></{modulor_html_chunk:2}></{modulor_html_chunk:3}>',
}

@@ -180,1 +187,109 @@ ];

describe('replaceDynamicTags', () => {
const testSets = [
{
input: '<{modulor_html_chunk:0}></{modulor_html_chunk:1}>',
expectation: '<modulor-dynamic-tag modulor-chunk="{modulor_html_chunk:0}"></modulor-dynamic-tag>'
},
{
input: '<{modulor_html_chunk:0}/>',
expectation: '<modulor-dynamic-tag modulor-chunk="{modulor_html_chunk:0}"/>'
},
{
input: '<{modulor_html_chunk:0} foo="bar"/>',
expectation: '<modulor-dynamic-tag modulor-chunk="{modulor_html_chunk:0}" foo="bar"/>'
},
{
input: '<x-{modulor_html_chunk:1}></x-{modulor_html_chunk:2}>',
expectation: '<modulor-dynamic-tag modulor-chunk="x-{modulor_html_chunk:1}"></modulor-dynamic-tag>'
},
{
input: '<{modulor_html_chunk:1}-test foo="bar"></{modulor_html_chunk:2}>',
expectation: '<modulor-dynamic-tag modulor-chunk="{modulor_html_chunk:1}-test" foo="bar"></modulor-dynamic-tag>'
},
{
input: '<x-{modulor_html_chunk:1}-test foo="bar"></x-{modulor_html_chunk:2}>',
expectation: '<modulor-dynamic-tag modulor-chunk="x-{modulor_html_chunk:1}-test" foo="bar"></modulor-dynamic-tag>'
},
{
input: '<x-{modulor_html_chunk:1}-test-{modulor_html_chunk:2} foo="bar"></x-{modulor_html_chunk:3}>',
expectation: '<modulor-dynamic-tag modulor-chunk="x-{modulor_html_chunk:1}-test-{modulor_html_chunk:2}" foo="bar"></modulor-dynamic-tag>'
},
{
input: `
<{modulor_html_chunk:0}>
<{modulor_html_chunk:1}>
</{modulor_html_chunk:2}>
</{modulor_html_chunk:3}>
`,
expectation: `
<modulor-dynamic-tag modulor-chunk="{modulor_html_chunk:0}">
<modulor-dynamic-tag modulor-chunk="{modulor_html_chunk:1}">
</modulor-dynamic-tag>
</modulor-dynamic-tag>
`
},
{
input: `
<{modulor_html_chunk:0} foo="{modulor_html_chunk:1}" {modulor_html_chunk:1}="{modulor_html_chunk:2}">
<{modulor_html_chunk:3}
bla="test">
</{modulor_html_chunk:4}>
</{modulor_html_chunk:5}>
`,
expectation: `
<modulor-dynamic-tag modulor-chunk="{modulor_html_chunk:0}" foo="{modulor_html_chunk:1}" {modulor_html_chunk:1}="{modulor_html_chunk:2}">
<modulor-dynamic-tag modulor-chunk="{modulor_html_chunk:3}"
bla="test">
</modulor-dynamic-tag>
</modulor-dynamic-tag>
`
},
{
input: `
<x-{modulor_html_chunk:0}-y foo="{modulor_html_chunk:1}" {modulor_html_chunk:1}="{modulor_html_chunk:2}">
<{modulor_html_chunk:3}-foo
bla="test">
</{modulor_html_chunk:4}>
</x-{modulor_html_chunk:5}-y>
`,
expectation: `
<modulor-dynamic-tag modulor-chunk="x-{modulor_html_chunk:0}-y" foo="{modulor_html_chunk:1}" {modulor_html_chunk:1}="{modulor_html_chunk:2}">
<modulor-dynamic-tag modulor-chunk="{modulor_html_chunk:3}-foo"
bla="test">
</modulor-dynamic-tag>
</modulor-dynamic-tag>
`
},
{
input: `
<{modulor_html_chunk:0}>
{modulor_html_chunk:1}
<{modulor_html_chunk:2}>
{modulor_html_chunk:3}
</{modulor_html_chunk:4}>
{modulor_html_chunk:5}
</{modulor_html_chunk:6}>
{modulor_html_chunk:7}
`,
expectation: `
<modulor-dynamic-tag modulor-chunk="{modulor_html_chunk:0}">
{modulor_html_chunk:1}
<modulor-dynamic-tag modulor-chunk="{modulor_html_chunk:2}">
{modulor_html_chunk:3}
</modulor-dynamic-tag>
{modulor_html_chunk:5}
</modulor-dynamic-tag>
{modulor_html_chunk:7}
`
},
]
testSets.forEach((testSet, index) => {
it(`set #${index}`, () => {
expect(replaceDynamicTags(testSet.input)).toBe(testSet.expectation);
});
})
});

@@ -330,3 +330,3 @@ import 'document-register-element';

const tplF = (scope) => html`
<my-test-component-f attr="123" value="${scope.value}" foo="${scope.foo}"></my-test-component-f>
<my-test-component-f attr="123" value="${scope.value}" foo="${scope.foo}" ${scope.value2}="val"></my-test-component-f>
`;

@@ -352,2 +352,3 @@

value: 'baz',
value2: 'dynamicProp',
foo: 'bar'

@@ -360,2 +361,3 @@ }), container);

value: 'baz',
dynamicProp: 'val',
foo: 'bar'

@@ -371,3 +373,7 @@ });

expect(propsSetterSpy).not.toHaveBeenCalled();
expect(propsSetterSpy).toHaveBeenCalledWith({
attr: '123',
value: 'baz',
foo: 'bar'
});

@@ -389,2 +395,162 @@ propsSetterSpy.mockReset();

it('calls props if it is a function on every render', () => {
const propsSetterSpy = jest.fn();
customElements.define('my-test-component-g', class extends HTMLElement {
props(...args){
propsSetterSpy(...args);
}
});
const tplF = (scope) => html`
<my-test-component-g attr="123" value="${scope.value}" foo="${scope.foo}" ${scope.value2}="val" />
`;
const container = document.createElement('div');
render(tplF({
value: 'bla',
foo: 'bar'
}), container);
expect(propsSetterSpy).toHaveBeenCalledTimes(1);
expect(propsSetterSpy).toHaveBeenCalledWith({
attr: '123',
value: 'bla',
foo: 'bar'
}, true);
render(tplF({
value: 'bla',
foo: 'bar'
}), container);
expect(propsSetterSpy).toHaveBeenCalledTimes(2);
expect(propsSetterSpy).toHaveBeenCalledWith({
attr: '123',
value: 'bla',
foo: 'bar'
}, false);
render(tplF({
value: 'baz',
value2: 'dynamicProp',
foo: 'bar'
}), container);
expect(propsSetterSpy).toHaveBeenCalledTimes(3);
expect(propsSetterSpy).toHaveBeenCalledWith({
attr: '123',
value: 'baz',
dynamicProp: 'val',
foo: 'bar'
}, true);
render(tplF({
value: 'baz',
foo: 'bar'
}), container);
expect(propsSetterSpy).toHaveBeenCalledTimes(4);
expect(propsSetterSpy).toHaveBeenCalledWith({
attr: '123',
value: 'baz',
foo: 'bar'
}, true);
render(tplF({
value: 'baz',
foo: 'quux'
}), container);
expect(propsSetterSpy).toHaveBeenCalledTimes(5);
expect(propsSetterSpy).toHaveBeenCalledWith({
attr: '123',
value: 'baz',
foo: 'quux'
}, true);
});
it('intercepts children rendering correctly', () => {
const propsSetterSpyIntercept = jest.fn();
const propsSetterSpy = jest.fn();
const $renderContainer = document.createElement('div');
const renderContainer = ({ children }) => {
render(children, $renderContainer);
};
customElements.define('my-test-component-h', class extends HTMLElement {
props(props, updated){
propsSetterSpyIntercept(props);
renderContainer(props);
}
get preventChildRendering(){
return true;
}
});
customElements.define('my-test-component-i', class extends HTMLElement {
props(props, updated){
propsSetterSpy(props);
}
});
const tplF = (scope) => html`
<my-test-component-h foo="${scope.foo}">
<span class="test">${scope.bar}</span>
</my-test-component-h>
<my-test-component-i foo="${scope.foo}">
<span class="test"></span>
</my-test-component-i>
`;
const container = document.createElement('div');
render(tplF({ foo: 'bar', bar: 'baz' }), container);
expect(propsSetterSpyIntercept).toHaveBeenCalledWith({
foo: 'bar',
children: expect.any(Function)
});
expect(propsSetterSpy).toHaveBeenCalledWith({
foo: 'bar'
});
expect(container.querySelector('my-test-component-h .test')).toBe(null);
expect($renderContainer.innerHTML).toEqual(`
<span class="test">baz</span>
`);
expect(container.querySelector('my-test-component-i .test')).not.toBe(null);
propsSetterSpyIntercept.mockReset();
propsSetterSpy.mockReset();
render(tplF({ foo: 'bla', bar: 'quux' }), container);
expect(propsSetterSpyIntercept).toHaveBeenCalledWith({
foo: 'bla',
children: expect.any(Function)
});
expect(propsSetterSpy).toHaveBeenCalledWith({
foo: 'bla'
});
expect(container.querySelector('my-test-component-h .test')).toBe(null);
expect($renderContainer.innerHTML).toEqual(`
<span class="test">quux</span>
`);
expect(container.querySelector('my-test-component-i .test')).not.toBe(null);
});
});

@@ -391,0 +557,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc