uhtml
Version:
A minimalistic library to create fast and reactive Web pages
2 lines (1 loc) • 5.94 kB
JavaScript
const{isArray:e}=Array,{assign:t,freeze:n,keys:s}=Object,r=42,c=new Set(["plaintext","script","style","textarea","title","xmp"]),o=new Set(["area","base","br","col","embed","hr","img","input","keygen","link","menuitem","meta","param","source","track","wbr"]),i=n({}),a=n([]),l=(e,t)=>(e.children===a&&(e.children=[]),e.children.push(t),t.parent=e,t),p=(e,t,n)=>{e.props===i&&(e.props={}),e.props[t]=n},h=(e,t,n)=>{e!==t&&n.push(e)},u=(e,t)=>{e.children=t.map(m,e)},d=(n,s,r)=>{switch(s.length){case r:u(n,s[r-1]);case r-1:{const c=s[r-2];e(c)?u(n,c):n.props=t({},c)}}return n};function m(e){const t=f(e);return t.parent=this,t}const f=e=>{switch(e[0]){case 8:return new w(e[1]);case 10:return new x(e[1]);case 3:return new $(e[1]);case r:return d(new y,e,3);case 1:return d(new S(e[1],!!e[2]),e,5);case 11:{const t=new b;return 1<e.length&&(t.children=e[1].map(m,t)),t}}};class g{constructor(e){this.type=e,this.parent=null}toJSON(){return[this.type,this.data]}}class w extends g{constructor(e){super(8),this.data=e}toString(){return`\x3c!--${this.data}--\x3e`}}class x extends g{constructor(e){super(10),this.data=e}toString(){return`<!${this.data}>`}}class $ extends g{constructor(e){super(3),this.data=e}toString(){return this.data}}class y extends g{constructor(){super(r),this.name="template",this.props=i,this.children=a}toJSON(){const e=[r];return h(this.props,i,e),h(this.children,a,e),e}toString(){let e="";for(const t in this.props){const n=this.props[t];null!=n&&("boolean"==typeof n?n&&(e+=` ${t}`):e+=` ${t}="${n}"`)}return`<template${e}>${this.children.join("")}</template>`}}class S extends g{constructor(e,t=!1){super(1),this.name=e,this.xml=t,this.props=i,this.children=a}toJSON(){const e=[1,this.name,+this.xml];return h(this.props,i,e),h(this.children,a,e),e}toString(){const{xml:e,name:t,props:n,children:s}=this,{length:r}=s;let i=`<${t}`;for(const t in n){const s=n[t];null!=s&&("boolean"==typeof s?s&&(i+=e?` ${t}=""`:` ${t}`):i+=` ${t}="${s}"`)}if(r){i+=">";for(let n=!e&&c.has(t),o=0;o<r;o++)i+=n?s[o].data:s[o];i+=`</${t}>`}else i+=e?" />":o.has(t)?">":`></${t}>`;return i}}class b extends g{constructor(){super(11),this.name="#fragment",this.children=a}toJSON(){const e=[11];return h(this.children,a,e),e}toString(){return this.children.join("")}}const O="\0",k=`"${O}"`,j=`'${O}'`,v=/\x00|<[^><\s]+/g,C=/([^\s/>=]+)(?:=(\x00|(?:(['"])[\s\S]*?\3)))?/g,J=(e,t,n,s,r)=>[t,n,s],N=e=>{const t=[];for(;e.parent;){switch(e.type){case r:case 1:"template"===e.name&&t.push(-1)}t.push(e.parent.children.indexOf(e)),e=e.parent}return t},A=(e,t)=>{do{e=e.parent}while(t.has(e));return e};const T=(e,t)=>t<0?e:e.children[t];var W=(e,t)=>t.reduceRight(T,e);const D=e=>(e.props===i&&(e.props={}),e.props),E=(e,t,n)=>{null==n?delete e[t]:e[t]=n},F=(e,t)=>{const n=D(e);for(const e in t){const s="role"===e?e:`aria-${e}`,r=t[e];E(n,s,r)}0===s(n).length&&(e.props=n)},z=e=>(t,n)=>{const r=D(t);E(r,e,n),0===s(r).length&&(t.props=r)},L=(t,n)=>{const{children:s}=t.parent,r=s.indexOf(t);if(e(n)){const e=new b;e.children=n,n=e}else n instanceof g||(n=new $(null==n?"":n));s[r]=n},M=(e,t)=>[e,t],R=(e,t)=>{const n=D(e);for(const e in t){const s=`data-${e}`,r=t[e];E(n,s,r)}0===s(n).length&&(e.props=n)},q=e=>(t,n)=>{const r=D(t);E(r,e,n),0===s(r).length&&(t.props=r)},B=(e,t)=>{e.children=null==t?a:[new $(t)]},G=e=>(t,n)=>{const r=D(t);n?r[e]=!!n:(delete r[e],0===s(r).length&&(t.props=r))},H=(({Comment:e=w,DocumentType:t=x,Text:n=$,Fragment:s=b,Element:i=S,Component:h=y,update:u=J})=>(d,m,f)=>{const g=d.join(O).trim(),w=new Set,x=[];let $=new s,y=0,S=0,b=0,J=a;for(const s of g.matchAll(v)){if(0<S){S--;continue}const d=s[0],v=s.index;if(y<v&&l($,new n(g.slice(y,v))),d===O){"table"===$.name&&($=l($,new i("tbody",f)),w.add($));const t=l($,new e("◦"));x.push(u(t,8,N(t),"",m[b++])),y=v+1}else if(d.startsWith("<!")){const n=g.indexOf(">",v+2);if("--\x3e"===g.slice(n-2,n+1)){const t=g.slice(v+4,n-2);"!"===t[0]&&l($,new e(t.slice(1).replace(/!$/,"")))}else l($,new t(g.slice(v+2,n)));y=n+1}else if(d.startsWith("</")){const e=g.indexOf(">",v+2);f&&"svg"===$.name&&(f=!1),$=A($,w),y=e+1}else{const e=v+d.length,t=g.indexOf(">",e),s=d.slice(1);let T=s;if(s===O?(T="template",$=l($,new h),J=N($).slice(1),x.push(u($,r,J,"",m[b++]))):(f||(T=T.toLowerCase(),"table"!==$.name||"tr"!==T&&"td"!==T||($=l($,new i("tbody",f)),w.add($)),"tbody"===$.name&&"td"===T&&($=l($,new i("tr",f)),w.add($))),$=l($,new i(T,!!f&&"svg"!==T)),J=a),e<t){let n=!1;for(const[s,r,c]of g.slice(e,t).matchAll(C))if(c===O||c===k||c===j||(n=r.endsWith(O))){const e=J===a?J=N($):J;x.push(u($,2,e,n?r.slice(0,-1):r,m[b++])),n=!1,S++}else p($,r,!c||c.slice(1,-1));J=a}y=t+1;const W=0<t&&"/"===g[t-1];if(f)W&&($=$.parent);else if(W||o.has(T))$=W?A($,w):$.parent;else if("svg"===T)f=!0;else if(c.has(T)){const e=g.indexOf(`</${s}>`,y),t=g.slice(y,e);t.trim()===O?(S++,x.push(u($,3,N($),"",m[b++]))):l($,new n(t)),$=$.parent,y=e+s.length+3,S++;continue}}}return y<g.length&&l($,new n(g.slice(y))),[$,x]})({Comment:w,DocumentType:x,Text:$,Fragment:b,Element:S,Component:y,update:(e,t,n,s)=>{switch(t){case r:return[n,M,3];case 8:return[n,L,2];case 2:switch(s.at(0)){case"@":return[n,(c=Symbol(s),(e,t)=>{const n=D(e);null==t?delete n[c]:n[c]=t}),7];case"?":return[n,G(s.slice(1)),10];case".":return"..."===s?[n,(e.type,(e,t)=>{}),6]:[n,q(s.slice(1)),5];case"a":if("aria"===s)return[n,F,0];case"d":if("data"===s)return[n,R,4];case"k":if("key"===s)return[n,Object,8];default:return[n,z(s),1]}case 3:return[n,B,9]}var c}}),{parse:I,stringify:K}=JSON,P=e=>{const n=new WeakMap;return(s,...r)=>{const[c,o]=n.get(s)||((t,s)=>{const r=H(t,s,e);return r[0]=I(K(r[0])),n.set(t,r),r})(s,r),i=f(c),a=r.length;if(a===o.length){const e=[];for(let t,n,s=0;s<a;s++){const[c,a,l]=o[s],p=r[s];n!==c&&(t=W(i,c),n=c),8!==l&&(3===l?e.push(a(t,p)):a(t,p))}for(const[n,s]of e){const e=t({children:n.children},n.props);L(n,s(e))}}return i}},Q=P(!1),U=P(!0);export{Q as html,U as svg};