@ryupold/vode 1.8.4 → 1.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +13 -0
- package/.github/workflows/tests.yml +17 -0
- package/dist/vode.cjs.min.js +2 -2
- package/dist/vode.es5.min.js +4 -4
- package/dist/vode.js +28 -8
- package/dist/vode.min.js +1 -1
- package/dist/vode.min.mjs +1 -1
- package/dist/vode.mjs +28 -8
- package/package.json +4 -3
- package/src/merge-style.ts +4 -1
- package/src/vode.ts +27 -8
- package/test/helper.ts +168 -0
- package/test/index.ts +80 -0
- package/test/mocks.ts +111 -0
- package/test/tests-app.ts +226 -0
- package/test/tests-children.ts +69 -0
- package/test/tests-createPatch.ts +28 -0
- package/test/tests-createState.ts +43 -0
- package/test/tests-defuse.ts +74 -0
- package/test/tests-hydrate.ts +68 -0
- package/test/tests-memo.ts +119 -0
- package/test/tests-mergeClass.ts +63 -0
- package/test/tests-mergeProps.ts +43 -0
- package/test/tests-mergeStyle.ts +39 -0
- package/test/tests-props.ts +34 -0
- package/test/tests-state-context.ts +106 -0
- package/test/tests-tag.ts +33 -0
- package/test/tests-vode.ts +27 -0
- package/tsconfig.test.json +18 -0
package/dist/vode.min.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var P={currentViewTransition:void 0,requestAnimationFrame:window.requestAnimationFrame?window.requestAnimationFrame.bind(window):(e=>e()),startViewTransition:document.startViewTransition?document.startViewTransition.bind(document):null};function q(e,n,...s){if(!e)throw new Error("first argument to vode() must be a tag name or a vode");return Array.isArray(e)?e:n?[e,n,...s]:[e,...s]}function w(e,n,s,...a){if(!e?.parentElement)throw new Error("first argument to app() must be a valid HTMLElement inside the <html></html> document");if(!n||typeof n!="object")throw new Error("second argument to app() must be a state object");if(typeof s!="function")throw new Error("third argument to app() must be a function that returns a vode");let t={};t.syncRenderer=P.requestAnimationFrame,t.asyncRenderer=P.startViewTransition,t.qSync=null,t.qAsync=null,t.stats={lastSyncRenderTime:0,lastAsyncRenderTime:0,syncRenderCount:0,asyncRenderCount:0,liveEffectCount:0,patchCount:0,syncRenderPatchCount:0,asyncRenderPatchCount:0};let o=n;"patch"in n&&typeof n.patch=="function"&&Array.isArray(n.patch.initialPatches)&&(a=[...n.patch.initialPatches,...a]),Object.defineProperty(n,"patch",{enumerable:!1,configurable:!0,writable:!1,value:async(l,y)=>{if(!(!l||typeof l!="function"&&typeof l!="object"))if(t.stats.patchCount++,l?.next){let S=l;t.stats.liveEffectCount++;try{let u=await S.next();for(;u.done===!1;){t.stats.liveEffectCount++;try{o.patch(u.value,y),u=await S.next()}finally{t.stats.liveEffectCount--}}o.patch(u.value,y)}finally{t.stats.liveEffectCount--}}else if(l.then){t.stats.liveEffectCount++;try{let S=await l;o.patch(S,y)}finally{t.stats.liveEffectCount--}}else if(Array.isArray(l))if(l.length>0)for(let S of l)o.patch(S,!document.hidden&&!!t.asyncRenderer);else{t.qSync=E(t.qSync||{},t.qAsync,!1),t.qAsync=null;try{P.currentViewTransition?.skipTransition()}catch{}t.stats.syncRenderPatchCount++,t.renderSync()}else typeof l=="function"?o.patch(l(t.state),y):y?(t.stats.asyncRenderPatchCount++,t.qAsync=E(t.qAsync||{},l,!1),await t.renderAsync()):(t.stats.syncRenderPatchCount++,t.qSync=E(t.qSync||{},l,!1),t.renderSync())}});function r(l){let y=Date.now(),S=s(t.state);t.vode=C(t.state,e.parentElement,0,0,t.vode,S),e.tagName.toUpperCase()!==S[0].toUpperCase()&&(e=t.vode.node,e._vode=t),l||(t.stats.lastSyncRenderTime=Date.now()-y,t.stats.syncRenderCount++,t.isRendering=!1,t.qSync&&t.renderSync())}let p=r.bind(null,!1),i=r.bind(null,!0);Object.defineProperty(t,"renderSync",{enumerable:!1,configurable:!0,writable:!1,value:()=>{t.isRendering||!t.qSync||(t.isRendering=!0,t.state=E(t.state,t.qSync,!0),t.qSync=null,t.syncRenderer(p))}}),Object.defineProperty(t,"renderAsync",{enumerable:!1,configurable:!0,writable:!1,value:async()=>{if(t.isAnimating||!t.qAsync||(await P.currentViewTransition?.updateCallbackDone,t.isAnimating||!t.qAsync||document.hidden))return;t.isAnimating=!0;let l=Date.now();try{t.state=E(t.state,t.qAsync,!0),t.qAsync=null,P.currentViewTransition=t.asyncRenderer(i),await P.currentViewTransition?.updateCallbackDone}finally{t.stats.lastAsyncRenderTime=Date.now()-l,t.stats.asyncRenderCount++,t.isAnimating=!1}t.qAsync&&t.renderAsync()}}),t.state=o;let c=e;c._vode=t;let d=Array.from(e.parentElement.children).indexOf(e);t.vode=C(n,e.parentElement,d,d,D(e,!0),s(n));for(let l of a)o.patch(l);return l=>o.patch(l)}function F(e){if(e?._vode){let s=function(t){if(!t?.node)return;let o=A(t);if(o){for(let r in o)r[0]==="o"&&r[1]==="n"&&(t.node[r]=null);t.node.catch=null}if(t.node._vode)F(t.node);else{let r=N(t);if(r)for(let p of r)s(p)}};var n=s;let a=e._vode;delete e._vode,Object.defineProperty(a.state,"patch",{value:void 0}),Object.defineProperty(a,"renderSync",{value:()=>{}}),Object.defineProperty(a,"renderAsync",{value:()=>{}}),s(a.vode)}else for(let s of e.children)F(s)}function D(e,n){if(e?.nodeType===Node.TEXT_NODE)return e.nodeValue?.trim()!==""?n?e:e.nodeValue:void 0;if(e.nodeType===Node.COMMENT_NODE)return;if(e.nodeType===Node.ELEMENT_NODE){let a=[e.tagName.toLowerCase()];if(n&&(a.node=e),e?.hasAttributes()){let t={},o=e.attributes;for(let r of o)t[r.name]=r.value;a.push(t)}if(e.hasChildNodes()){let t=[];for(let o of e.childNodes){let r=o&&D(o,n);r?a.push(r):o&&n&&t.push(o)}for(let o of t)o.remove()}return a}else return}function X(e,n){if(!e||!Array.isArray(e))throw new Error("first argument to memo() must be an array of values to compare");if(typeof n!="function")throw new Error("second argument to memo() must be a function that returns a vode or props object");return n.__memo=e,n}function Y(e){if(!e||typeof e!="object")throw new Error("createState() must be called with a state object");return"patch"in e||Object.defineProperty(e,"patch",{enumerable:!1,configurable:!0,writable:!1,value:n=>{let s=e;Array.isArray(s.patch.initialPatches)||(s.patch.initialPatches=[]),s.patch.initialPatches.push(n)}}),e}function W(e){return e}function $(e){return e?Array.isArray(e)?e[0]:typeof e=="string"||e.nodeType===Node.TEXT_NODE?"#text":void 0:void 0}function A(e){if(Array.isArray(e)&&e.length>1&&e[1]&&!Array.isArray(e[1])&&typeof e[1]=="object"&&e[1].nodeType!==Node.TEXT_NODE)return e[1]}function N(e){let n=v(e);return n>0?e.slice(n):null}function J(e){let n=v(e);return n<0?0:e.length-n}function Q(e,n){let s=v(e);if(s>0)return e[n+s]}function v(e){return A(e)?e.length>2?2:-1:Array.isArray(e)&&e.length>1?1:-1}function E(e,n,s){if(!n)return e;for(let a in n){let t=n[a];if(t&&typeof t=="object"){let o=e[a];o?Array.isArray(t)?e[a]=[...t]:t instanceof Date&&o!==t?e[a]=new Date(t):Array.isArray(o)?e[a]=E({},t,s):typeof o=="object"?E(e[a],t,s):e[a]=E({},t,s):Array.isArray(t)?e[a]=[...t]:t instanceof Date?e[a]=new Date(t):e[a]=E({},t,s)}else t===void 0&&s?delete e[a]:e[a]=t}return e}function C(e,n,s,a,t,o,r){try{o=R(e,o,t);let p=!o||typeof o=="number"||typeof o=="boolean";if(o===t||!t&&p)return t;let i=t?.nodeType===Node.TEXT_NODE,c=i?t:t?.node;if(p){c?.onUnmount&&e.patch(c.onUnmount(c)),c?.remove();return}let d=!p&&_(o),l=!p&&K(o),y=!!o&&typeof o!="string"&&!!(o?.node||o?.nodeType===Node.TEXT_NODE);if(!d&&!l&&!y&&!t)throw new Error("Invalid vode: "+typeof o+" "+JSON.stringify(o));if(y&&d?o=o.wholeText:y&&l&&(o=[...o]),i&&d)return c.nodeValue!==o&&(c.nodeValue=o),t;if(d&&(!c||!i)){let S=document.createTextNode(o);if(c)c.onUnmount&&e.patch(c.onUnmount(c)),c.replaceWith(S);else{let u=!1;for(let f=a;f<n.childNodes.length;f++){let x=n.childNodes[f];if(x){x.before(S,x),u=!0;break}}u||n.appendChild(S)}return S}if(l&&(!c||i||t[0]!==o[0])){let S=o;1 in S&&(S[1]=R(e,S[1],void 0));let u=A(o);u?.xmlns!==void 0&&(r=u.xmlns);let f=r?document.createElementNS(r,o[0]):document.createElement(o[0]);if(o.node=f,O(e,f,void 0,u,r??null),u&&"catch"in u&&(o.node.catch=null,o.node.removeAttribute("catch")),c)c.onUnmount&&e.patch(c.onUnmount(c)),c.replaceWith(f);else{let h=!1;for(let g=a;g<n.childNodes.length;g++){let T=n.childNodes[g];if(T){T.before(f,T),h=!0;break}}h||n.appendChild(f)}let x=N(o);if(x){let h=u?2:1,g=0;for(let T=0;T<x.length;T++){let m=x[T],b=C(e,f,T,g,void 0,m,r??null);o[T+h]=b,b&&g++}}return f.onMount&&e.patch(f.onMount(f)),o}if(!i&&l&&t[0]===o[0]){o.node=c;let S=o,u=t,f=A(o),x=A(t);if(f?.xmlns!==void 0&&(r=f.xmlns),S[1]?.__memo){let T=S[1];S[1]=R(e,S[1],u[1]),T!==S[1]&&O(e,c,x,f,r)}else O(e,c,x,f,r);f?.catch&&x?.catch!==f.catch&&(o.node.catch=null,o.node.removeAttribute("catch"));let h=N(o),g=N(t);if(h){let T=f?2:1,m=0;for(let b=0;b<h.length;b++){let k=h[b],B=g&&g[b],I=C(e,c,b,m,B,k,r);o[b+T]=I,I&&m++}}if(g){let T=h?h.length:0;for(let m=g.length-1;m>=T;m--)C(e,c,m,m,g[m],void 0,r)}return o}}catch(p){let i=A(o)?.catch;if(i){let c=typeof i=="function"?i(e,p):i;return C(e,n,s,a,D(o?.node||t?.node,!0),c,r)}else throw p}}function K(e){return Array.isArray(e)&&e.length>0&&typeof e[0]=="string"}function _(e){return typeof e=="string"||e?.nodeType===Node.TEXT_NODE}function R(e,n,s){if(typeof n!="function")return n;let a=n?.__memo,t=s?.__memo;if(Array.isArray(a)&&Array.isArray(t)&&a.length===t.length){let r=!0;for(let p=0;p<a.length;p++)if(a[p]!==t[p]){r=!1;break}if(r)return s}let o=V(n,e);return typeof o=="object"&&(o.__memo=n?.__memo),o}function V(e,n){return typeof e=="function"?V(e(n),n):e}function O(e,n,s,a,t){if(!a&&!s)return;let o=t!==void 0;if(s)for(let r in s){let p=s[r],i=a?.[r];p!==i&&(a?a[r]=M(e,n,r,p,i,o):M(e,n,r,p,void 0,o))}if(a&&s){for(let r in a)if(!(r in s)){let p=a[r];a[r]=M(e,n,r,void 0,p,o)}}else if(a)for(let r in a){let p=a[r];a[r]=M(e,n,r,void 0,p,o)}}function M(e,n,s,a,t,o){if(s==="style")if(!t)n.style.cssText="";else if(typeof t=="string")a!==t&&(n.style.cssText=t);else if(a&&typeof a=="object"){for(let r in a)t[r]||(n.style[r]=null);for(let r in t){let p=a[r],i=t[r];p!==i&&(n.style[r]=i)}}else for(let r in t)n.style[r]=t[r];else if(s==="class")t?n.setAttribute("class",j(t)):n.removeAttribute("class");else if(s[0]==="o"&&s[1]==="n")if(t){let r=null;if(typeof t=="function"){let p=t;r=i=>e.patch(p(e,i))}else typeof t=="object"&&(r=()=>e.patch(t));n[s]=r}else n[s]=null;else o||(n[s]=t),t==null||t===!1?n.removeAttribute(s):n.setAttribute(s,t);return t}function j(e){return typeof e=="string"?e:Array.isArray(e)?e.map(j).join(" "):typeof e=="object"?Object.keys(e).filter(n=>e[n]).join(" "):""}var Z="a",tt="abbr",et="address",nt="area",ot="article",at="aside",st="audio",rt="b",ct="base",it="bdi",lt="bdo",pt="blockquote",St="body",ft="br",dt="button",ut="canvas",Tt="caption",yt="cite",gt="code",xt="col",ht="colgroup",mt="data",bt="datalist",Et="dd",Pt="del",At="details",Ct="dfn",Mt="dialog",Nt="div",Rt="dl",Ot="dt",Dt="em",vt="embed",Lt="fieldset",It="figcaption",Ft="figure",Vt="footer",jt="form",Ht="h1",Ut="h2",Gt="h3",kt="h4",Bt="h5",Kt="h6",_t="head",qt="header",wt="hgroup",Xt="hr",Yt="html",Wt="i",$t="iframe",Jt="img",Qt="input",zt="ins",Zt="kbd",te="label",ee="legend",ne="li",oe="link",ae="main",se="map",re="mark",ce="menu",ie="meta",le="meter",pe="nav",Se="noscript",fe="object",de="ol",ue="optgroup",Te="option",ye="output",ge="p",xe="picture",he="pre",me="progress",be="q",Ee="rp",Pe="rt",Ae="ruby",Ce="s",Me="samp",Ne="script",Re="search",Oe="section",De="select",ve="slot",Le="small",Ie="source",Fe="span",Ve="strong",je="style",He="sub",Ue="summary",Ge="sup",ke="table",Be="tbody",Ke="td",_e="template",qe="textarea",we="tfoot",Xe="th",Ye="thead",We="time",$e="title",Je="tr",Qe="track",ze="u",Ze="ul",tn="var",en="video",nn="wbr",on="animate",an="animateMotion",sn="animateTransform",rn="circle",cn="clipPath",ln="defs",pn="desc",Sn="ellipse",fn="feBlend",dn="feColorMatrix",un="feComponentTransfer",Tn="feComposite",yn="feConvolveMatrix",gn="feDiffuseLighting",xn="feDisplacementMap",hn="feDistantLight",mn="feDropShadow",bn="feFlood",En="feFuncA",Pn="feFuncB",An="feFuncG",Cn="feFuncR",Mn="feGaussianBlur",Nn="feImage",Rn="feMerge",On="feMergeNode",Dn="feMorphology",vn="feOffset",Ln="fePointLight",In="feSpecularLighting",Fn="feSpotLight",Vn="feTile",jn="feTurbulence",Hn="filter",Un="foreignObject",Gn="g",kn="image",Bn="line",Kn="linearGradient",_n="marker",qn="mask",wn="metadata",Xn="mpath",Yn="path",Wn="pattern",$n="polygon",Jn="polyline",Qn="radialGradient",zn="rect",Zn="set",to="stop",eo="svg",no="switch",oo="symbol",ao="text",so="textPath",ro="tspan",co="use",io="view",lo="annotation",po="annotation-xml",So="maction",fo="math",uo="merror",To="mfrac",yo="mi",go="mmultiscripts",xo="mn",ho="mo",mo="mover",bo="mpadded",Eo="mphantom",Po="mprescripts",Ao="mroot",Co="mrow",Mo="ms",No="mspace",Ro="msqrt",Oo="mstyle",Do="msub",vo="msubsup",Lo="msup",Io="mtable",Fo="mtd",Vo="mtext",jo="mtr",Ho="munder",Uo="munderover",Go="semantics";function H(...e){if(!e||e.length===0)return null;if(e.length===1)return e[0];let n=e[0];for(let s=1;s<e.length;s++){let a=n,t=e[s];if(!a)n=t;else if(t)if(typeof a=="string"&&typeof t=="string"){let o=a.split(" "),r=t.split(" "),p=new Set([...o,...r]);n=Array.from(p).join(" ").trim()}else if(typeof a=="string"&&Array.isArray(t)){let o=new Set([...t,...a.split(" ")]);n=Array.from(o).join(" ").trim()}else if(Array.isArray(a)&&typeof t=="string"){let o=new Set([...a,...t.split(" ")]);n=Array.from(o).join(" ").trim()}else if(Array.isArray(a)&&Array.isArray(t)){let o=new Set([...a,...t]);n=Array.from(o).join(" ").trim()}else if(typeof a=="string"&&typeof t=="object")n={[a]:!0,...t};else if(typeof a=="object"&&typeof t=="string")n={...a,[t]:!0};else if(typeof a=="object"&&typeof t=="object")n={...a,...t};else if(typeof a=="object"&&Array.isArray(t)){let o={...a};for(let r of t)o[r]=!0;n=o}else if(Array.isArray(a)&&typeof t=="object"){let o={};for(let r of a)o[r]=!0;for(let r of Object.keys(t))o[r]=t[r];n=o}else throw new Error(`cannot merge classes of ${a} (${typeof a}) and ${t} (${typeof t})`);else continue}return n}var U=document.createElement("div");function G(...e){try{let n=U.style;for(let s of e)if(typeof s=="object"&&s!==null)for(let a in s)n[a]=s[a];else typeof s=="string"&&(n.cssText+=";"+s);return n.cssText}finally{U.style.cssText=""}}function wo(...e){if(e.length===0)return;if(e.length===1)return e[0]||void 0;let n;for(let s of e)if(!(typeof s!="object"||s===null)){n||(n={});for(let a in s)a==="style"?n.style=G(n.style,s.style):a==="class"?n.class=H(n.class,s.class):n[a]=s[a]}return n}function Yo(e){return new L(e,[])}var L=class e{constructor(n,s){this.state=n;this.keys=s;function a(i,c){if(s.length>1){let d=0,l=c[s[d]];for((typeof l!="object"||l===null)&&(c[s[d]]=l={}),d=1;d<s.length-1;d++){let y=l;l=l[s[d]],(typeof l!="object"||l===null)&&(y[s[d]]=l={})}l[s[d]]=i}else s.length===1?typeof c[s[0]]=="object"&&typeof i=="object"?Object.assign(c[s[0]],i):c[s[0]]=i:Object.assign(c,i)}function t(i){let c={};return a(i,c),c}function o(){if(s.length===0)return n;let i=n?n[s[0]]:void 0;for(let c=1;c<s.length&&i;c++)i=i[s[c]];return i}function r(i){a(i,n)}function p(i,c){c?n.patch([t(i)]):n.patch(t(i))}return new Proxy(this,{get:(i,c,d)=>{if(c==="state")return n;if(c==="get")return o;if(c==="put")return r;if(c==="patch")return p;let l=[...i.keys,String(c)];return new e(i.state,l)}})}state;keys;get(){}put(n){}patch(n){}};export{Z as A,tt as ABBR,et as ADDRESS,on as ANIMATE,an as ANIMATEMOTION,sn as ANIMATETRANSFORM,lo as ANNOTATION,po as ANNOTATION_XML,nt as AREA,ot as ARTICLE,at as ASIDE,st as AUDIO,rt as B,ct as BASE,it as BDI,lt as BDO,pt as BLOCKQUOTE,St as BODY,ft as BR,dt as BUTTON,ut as CANVAS,Tt as CAPTION,rn as CIRCLE,yt as CITE,cn as CLIPPATH,gt as CODE,xt as COL,ht as COLGROUP,mt as DATA,bt as DATALIST,Et as DD,ln as DEFS,Pt as DEL,pn as DESC,At as DETAILS,Ct as DFN,Mt as DIALOG,Nt as DIV,Rt as DL,Ot as DT,Sn as ELLIPSE,Dt as EM,vt as EMBED,fn as FEBLEND,dn as FECOLORMATRIX,un as FECOMPONENTTRANSFER,Tn as FECOMPOSITE,yn as FECONVOLVEMATRIX,gn as FEDIFFUSELIGHTING,xn as FEDISPLACEMENTMAP,hn as FEDISTANTLIGHT,mn as FEDROPSHADOW,bn as FEFLOOD,En as FEFUNCA,Pn as FEFUNCB,An as FEFUNCG,Cn as FEFUNCR,Mn as FEGAUSSIANBLUR,Nn as FEIMAGE,Rn as FEMERGE,On as FEMERGENODE,Dn as FEMORPHOLOGY,vn as FEOFFSET,Ln as FEPOINTLIGHT,In as FESPECULARLIGHTING,Fn as FESPOTLIGHT,Vn as FETILE,jn as FETURBULENCE,Lt as FIELDSET,It as FIGCAPTION,Ft as FIGURE,Hn as FILTER,Vt as FOOTER,Un as FOREIGNOBJECT,jt as FORM,Gn as G,Ht as H1,Ut as H2,Gt as H3,kt as H4,Bt as H5,Kt as H6,_t as HEAD,qt as HEADER,wt as HGROUP,Xt as HR,Yt as HTML,Wt as I,$t as IFRAME,kn as IMAGE,Jt as IMG,Qt as INPUT,zt as INS,Zt as KBD,te as LABEL,ee as LEGEND,ne as LI,Bn as LINE,Kn as LINEARGRADIENT,oe as LINK,So as MACTION,ae as MAIN,se as MAP,re as MARK,_n as MARKER,qn as MASK,fo as MATH,ce as MENU,uo as MERROR,ie as META,wn as METADATA,le as METER,To as MFRAC,yo as MI,go as MMULTISCRIPTS,xo as MN,ho as MO,mo as MOVER,bo as MPADDED,Xn as MPATH,Eo as MPHANTOM,Po as MPRESCRIPTS,Ao as MROOT,Co as MROW,Mo as MS,No as MSPACE,Ro as MSQRT,Oo as MSTYLE,Do as MSUB,vo as MSUBSUP,Lo as MSUP,Io as MTABLE,Fo as MTD,Vo as MTEXT,jo as MTR,Ho as MUNDER,Uo as MUNDEROVER,pe as NAV,Se as NOSCRIPT,fe as OBJECT,de as OL,ue as OPTGROUP,Te as OPTION,ye as OUTPUT,ge as P,Yn as PATH,Wn as PATTERN,xe as PICTURE,$n as POLYGON,Jn as POLYLINE,he as PRE,me as PROGRESS,be as Q,Qn as RADIALGRADIENT,zn as RECT,Ee as RP,Pe as RT,Ae as RUBY,Ce as S,Me as SAMP,Ne as SCRIPT,Re as SEARCH,Oe as SECTION,De as SELECT,Go as SEMANTICS,Zn as SET,ve as SLOT,Le as SMALL,Ie as SOURCE,Fe as SPAN,to as STOP,Ve as STRONG,je as STYLE,He as SUB,Ue as SUMMARY,Ge as SUP,eo as SVG,no as SWITCH,oo as SYMBOL,ke as TABLE,Be as TBODY,Ke as TD,_e as TEMPLATE,ao as TEXT,qe as TEXTAREA,so as TEXTPATH,we as TFOOT,Xe as TH,Ye as THEAD,We as TIME,$e as TITLE,Je as TR,Qe as TRACK,ro as TSPAN,ze as U,Ze as UL,co as USE,tn as VAR,en as VIDEO,io as VIEW,nn as WBR,w as app,Q as child,J as childCount,N as children,v as childrenStart,Yo as context,W as createPatch,Y as createState,F as defuse,P as globals,D as hydrate,X as memo,H as mergeClass,wo as mergeProps,G as mergeStyle,A as props,$ as tag,q as vode};
|
|
1
|
+
var P={currentViewTransition:void 0,requestAnimationFrame:typeof window<"u"&&typeof window.requestAnimationFrame=="function"?window.requestAnimationFrame.bind(window):(e=>e()),startViewTransition:typeof document<"u"&&typeof document.startViewTransition=="function"?document.startViewTransition.bind(document):null};function q(e,n,...s){if(!e)throw new Error("first argument to vode() must be a tag name or a vode");return Array.isArray(e)?e:typeof n=="object"?[e,n,...s]:[e,...s]}function w(e,n,s,...a){if(!e?.parentElement)throw new Error("first argument to app() must be a valid HTMLElement inside the <html></html> document");if(!n||typeof n!="object")throw new Error("second argument to app() must be a state object");if(typeof s!="function")throw new Error("third argument to app() must be a function that returns a vode");let t={};t.syncRenderer=P.requestAnimationFrame,t.asyncRenderer=P.startViewTransition,t.qSync=null,t.qAsync=null,t.stats={lastSyncRenderTime:0,lastAsyncRenderTime:0,syncRenderCount:0,asyncRenderCount:0,liveEffectCount:0,patchCount:0,syncRenderPatchCount:0,asyncRenderPatchCount:0};let o=n;"patch"in n&&typeof n.patch=="function"&&Array.isArray(n.patch.initialPatches)&&(a=[...n.patch.initialPatches,...a]),Object.defineProperty(n,"patch",{enumerable:!1,configurable:!0,writable:!1,value:async(l,y)=>{if(!(!l||typeof l!="function"&&typeof l!="object"))if(t.stats.patchCount++,l?.next){let f=l;t.stats.liveEffectCount++;try{let u=await f.next();for(;u.done===!1;){t.stats.liveEffectCount++;try{o.patch(u.value,y),u=await f.next()}finally{t.stats.liveEffectCount--}}o.patch(u.value,y)}finally{t.stats.liveEffectCount--}}else if(l.then){t.stats.liveEffectCount++;try{let f=await l;o.patch(f,y)}finally{t.stats.liveEffectCount--}}else if(Array.isArray(l))if(l.length>0)for(let f of l)o.patch(f,!document.hidden&&!!t.asyncRenderer);else{t.qSync=E(t.qSync||{},t.qAsync,!1),t.qAsync=null;try{P.currentViewTransition?.skipTransition()}catch{}t.stats.syncRenderPatchCount++,t.renderSync()}else typeof l=="function"?o.patch(l(t.state),y):y?(t.stats.asyncRenderPatchCount++,t.qAsync=E(t.qAsync||{},l,!1),await t.renderAsync()):(t.stats.syncRenderPatchCount++,t.qSync=E(t.qSync||{},l,!1),t.renderSync())}});function r(l){let y=Date.now(),f=s(t.state);t.vode=C(t.state,e.parentElement,0,0,t.vode,f),e.tagName.toUpperCase()!==f[0].toUpperCase()&&(e=t.vode.node,e._vode=t),l||(t.stats.lastSyncRenderTime=Date.now()-y,t.stats.syncRenderCount++,t.isRendering=!1,t.qSync&&t.renderSync())}let p=r.bind(null,!1),i=r.bind(null,!0);Object.defineProperty(t,"renderSync",{enumerable:!1,configurable:!0,writable:!1,value:()=>{t.isRendering||!t.qSync||(t.isRendering=!0,t.state=E(t.state,t.qSync,!0),t.qSync=null,t.syncRenderer(p))}}),Object.defineProperty(t,"renderAsync",{enumerable:!1,configurable:!0,writable:!1,value:async()=>{if(t.isAnimating||!t.qAsync||(await P.currentViewTransition?.updateCallbackDone,t.isAnimating||!t.qAsync||document.hidden))return;t.isAnimating=!0;let l=Date.now();try{t.state=E(t.state,t.qAsync,!0),t.qAsync=null,P.currentViewTransition=t.asyncRenderer(i),await P.currentViewTransition?.updateCallbackDone}finally{t.stats.lastAsyncRenderTime=Date.now()-l,t.stats.asyncRenderCount++,t.isAnimating=!1}t.qAsync&&t.renderAsync()}}),t.state=o;let c=e;c._vode=t;let S=Array.from(e.parentElement.children).indexOf(e);t.vode=C(n,e.parentElement,S,S,v(e,!0),s(n));for(let l of a)o.patch(l);return l=>o.patch(l)}function V(e){if(e?._vode){let s=function(t){if(!t?.node)return;let o=A(t);if(o){for(let r in o)r[0]==="o"&&r[1]==="n"&&(t.node[r]=null);t.node.catch=null}if(t.node._vode)V(t.node);else{let r=N(t);if(r)for(let p of r)s(p)}};var n=s;let a=e._vode;delete e._vode,Object.defineProperty(a.state,"patch",{value:void 0}),Object.defineProperty(a,"renderSync",{value:()=>{}}),Object.defineProperty(a,"renderAsync",{value:()=>{}}),s(a.vode)}else for(let s of e.children)V(s)}function v(e,n){if(e?.nodeType===Node.TEXT_NODE)return e.nodeValue?.trim()!==""?n?e:e.nodeValue:void 0;if(e.nodeType===Node.ELEMENT_NODE){let a=[e.tagName.toLowerCase()];if(n&&(a.node=e),e?.hasAttributes()){let t={},o=e.attributes;for(let r of o)t[r.name]=r.value;a.push(t)}if(e.hasChildNodes()){let t=[];for(let o of e.childNodes){let r=o&&v(o,n);r?a.push(r):o&&n&&t.push(o)}for(let o of t)o.remove()}return a}else return}function X(e,n){if(!e||!Array.isArray(e))throw new Error("first argument to memo() must be an array of values to compare");if(typeof n!="function")throw new Error("second argument to memo() must be a function that returns a vode or props object");return n.__memo=e,n}function Y(e){if(!e||typeof e!="object")throw new Error("createState() must be called with a state object");return"patch"in e||Object.defineProperty(e,"patch",{enumerable:!1,configurable:!0,writable:!1,value:n=>{let s=e;Array.isArray(s.patch.initialPatches)||(s.patch.initialPatches=[]),s.patch.initialPatches.push(n)}}),e}function W(e){return e}function $(e){return e?Array.isArray(e)?e[0]:typeof e=="string"||e.nodeType===Node.TEXT_NODE?"#text":void 0:void 0}function A(e){if(Array.isArray(e)&&e.length>1&&e[1]&&!Array.isArray(e[1])&&typeof e[1]=="object"&&e[1].nodeType!==Node.TEXT_NODE)return e[1]}function N(e){let n=L(e);return n>0?e.slice(n):null}function J(e){let n=L(e);return n<0?0:e.length-n}function Q(e,n){let s=L(e);if(s>0)return e[n+s]}function L(e){return A(e)?e.length>2?2:-1:Array.isArray(e)&&e.length>1?1:-1}function E(e,n,s){if(!n)return e;for(let a in n){let t=n[a];if(t&&typeof t=="object"){let o=e[a];o?Array.isArray(t)?e[a]=[...t]:t instanceof Date&&o!==t?e[a]=new Date(t):Array.isArray(o)?e[a]=E({},t,s):typeof o=="object"?E(e[a],t,s):e[a]=E({},t,s):Array.isArray(t)?e[a]=[...t]:t instanceof Date?e[a]=new Date(t):e[a]=E({},t,s)}else t===void 0&&s?delete e[a]:e[a]=t}return e}function C(e,n,s,a,t,o,r){try{o=O(e,o,t);let p=!o||typeof o=="number"||typeof o=="boolean";if(o===t||!t&&p)return t;let i=t?.nodeType===Node.TEXT_NODE,c=i?t:t?.node;if(p){c?.onUnmount&&e.patch(c.onUnmount(c)),c?.remove();return}let S=!p&&K(o),l=!p&&B(o),y=!!o&&typeof o!="string"&&!!(o?.node||o?.nodeType===Node.TEXT_NODE);if(!S&&!l&&!y&&!t)throw new Error("Invalid vode: "+typeof o+" "+JSON.stringify(o));if(y&&S?o=o.wholeText:y&&l&&(o=[...o]),i&&S)return c.nodeValue!==o&&(c.nodeValue=o),t;if(S&&(!c||!i)){let f=document.createTextNode(o);if(c)c.onUnmount&&e.patch(c.onUnmount(c)),c.replaceWith(f);else{let u=!1;for(let d=a;d<n.childNodes.length;d++){let x=n.childNodes[d];if(x){x.before(f,x),u=!0;break}}u||n.appendChild(f)}return f}if(l&&(!c||i||t[0]!==o[0])){let f=o;1 in f&&(f[1]=O(e,f[1],void 0));let u=A(o);u?.xmlns!==void 0&&(r=u.xmlns);let d=r?document.createElementNS(r,o[0]):document.createElement(o[0]);if(o.node=d,D(e,d,void 0,u,r??null),u&&"catch"in u&&(o.node.catch=null,o.node.removeAttribute("catch")),c)c.onUnmount&&e.patch(c.onUnmount(c)),c.replaceWith(d);else{let h=!1;for(let g=a;g<n.childNodes.length;g++){let T=n.childNodes[g];if(T){T.before(d,T),h=!0;break}}h||n.appendChild(d)}let x=N(o);if(x){let h=u?2:1,g=0;for(let T=0;T<x.length;T++){let m=x[T],b=C(e,d,T,g,void 0,m,r??null);o[T+h]=b,b&&g++}}return d.onMount&&e.patch(d.onMount(d)),o}if(!i&&l&&t[0]===o[0]){o.node=c;let f=o,u=t,d=A(o),x=A(t);if(d?.xmlns!==void 0&&(r=d.xmlns),f[1]?.__memo){let T=f[1];f[1]=O(e,f[1],u[1]),T!==f[1]&&D(e,c,x,d,r)}else D(e,c,x,d,r);d?.catch&&x?.catch!==d.catch&&(o.node.catch=null,o.node.removeAttribute("catch"));let h=N(o),g=N(t);if(h){let T=d?2:1,m=0;for(let b=0;b<h.length;b++){let k=h[b],_=g&&g[b],F=C(e,c,b,m,_,k,r);o[b+T]=F,F&&m++}}if(g){let T=h?h.length:0;for(let m=g.length-1;m>=T;m--)C(e,c,m,m,g[m],void 0,r)}return o}}catch(p){let i=A(o)?.catch;if(i){let c=typeof i=="function"?i(e,p):i;return C(e,n,s,a,v(o?.node||t?.node,!0),c,r)}else throw p}}function B(e){return Array.isArray(e)&&e.length>0&&typeof e[0]=="string"}function K(e){return typeof e=="string"||e?.nodeType===Node.TEXT_NODE}function O(e,n,s){if(typeof n!="function")return n;let a=n?.__memo,t=s?.__memo;if(Array.isArray(a)&&Array.isArray(t)&&a.length===t.length){let p=!0;for(let i=0;i<a.length;i++)if(a[i]!==t[i]){p=!1;break}if(p)return s}let o=n(e);if(typeof o=="function"&&o?.__memo){let p=o.__memo;if(Array.isArray(p)&&Array.isArray(t)&&p.length===t.length){let c=!0;for(let S=0;S<p.length;S++)if(p[S]!==t[S]){c=!1;break}if(c)return s}let i=o(e);return typeof i=="object"&&(i.__memo=p),i}let r=typeof o=="function"?j(o,e):o;return typeof r=="object"&&(r.__memo=o?.__memo||n?.__memo),r}function j(e,n){return typeof e=="function"?j(e(n),n):e}function D(e,n,s,a,t){if(!a&&!s)return;let o=t!==void 0;if(s)for(let r in s){let p=s[r],i=a?.[r];p!==i&&(a?a[r]=M(e,n,r,p,i,o):M(e,n,r,p,void 0,o))}if(a&&s){for(let r in a)if(!(r in s)){let p=a[r];a[r]=M(e,n,r,void 0,p,o)}}else if(a)for(let r in a){let p=a[r];a[r]=M(e,n,r,void 0,p,o)}}function M(e,n,s,a,t,o){if(s==="style")if(!t)n.style.cssText="";else if(typeof t=="string")a!==t&&(n.style.cssText=t);else if(a&&typeof a=="object"){for(let r in a)t[r]||(n.style[r]=null);for(let r in t){let p=a[r],i=t[r];p!==i&&(n.style[r]=i)}}else for(let r in t)n.style[r]=t[r];else if(s==="class")t?n.setAttribute("class",H(t)):n.removeAttribute("class");else if(s[0]==="o"&&s[1]==="n")if(t){let r=null;if(typeof t=="function"){let p=t;r=i=>e.patch(p(e,i))}else typeof t=="object"&&(r=()=>e.patch(t));n[s]=r}else n[s]=null;else o||(n[s]=t),t==null||t===!1?n.removeAttribute(s):n.setAttribute(s,t);return t}function H(e){return typeof e=="string"?e:Array.isArray(e)?e.map(H).join(" "):typeof e=="object"?Object.keys(e).filter(n=>e[n]).join(" "):""}var Z="a",tt="abbr",et="address",nt="area",ot="article",at="aside",st="audio",rt="b",ct="base",it="bdi",lt="bdo",pt="blockquote",ft="body",St="br",dt="button",ut="canvas",Tt="caption",yt="cite",gt="code",xt="col",ht="colgroup",mt="data",bt="datalist",Et="dd",Pt="del",At="details",Ct="dfn",Mt="dialog",Nt="div",Rt="dl",Ot="dt",Dt="em",vt="embed",Lt="fieldset",It="figcaption",Ft="figure",Vt="footer",jt="form",Ht="h1",Ut="h2",Gt="h3",kt="h4",_t="h5",Bt="h6",Kt="head",qt="header",wt="hgroup",Xt="hr",Yt="html",Wt="i",$t="iframe",Jt="img",Qt="input",zt="ins",Zt="kbd",te="label",ee="legend",ne="li",oe="link",ae="main",se="map",re="mark",ce="menu",ie="meta",le="meter",pe="nav",fe="noscript",Se="object",de="ol",ue="optgroup",Te="option",ye="output",ge="p",xe="picture",he="pre",me="progress",be="q",Ee="rp",Pe="rt",Ae="ruby",Ce="s",Me="samp",Ne="script",Re="search",Oe="section",De="select",ve="slot",Le="small",Ie="source",Fe="span",Ve="strong",je="style",He="sub",Ue="summary",Ge="sup",ke="table",_e="tbody",Be="td",Ke="template",qe="textarea",we="tfoot",Xe="th",Ye="thead",We="time",$e="title",Je="tr",Qe="track",ze="u",Ze="ul",tn="var",en="video",nn="wbr",on="animate",an="animateMotion",sn="animateTransform",rn="circle",cn="clipPath",ln="defs",pn="desc",fn="ellipse",Sn="feBlend",dn="feColorMatrix",un="feComponentTransfer",Tn="feComposite",yn="feConvolveMatrix",gn="feDiffuseLighting",xn="feDisplacementMap",hn="feDistantLight",mn="feDropShadow",bn="feFlood",En="feFuncA",Pn="feFuncB",An="feFuncG",Cn="feFuncR",Mn="feGaussianBlur",Nn="feImage",Rn="feMerge",On="feMergeNode",Dn="feMorphology",vn="feOffset",Ln="fePointLight",In="feSpecularLighting",Fn="feSpotLight",Vn="feTile",jn="feTurbulence",Hn="filter",Un="foreignObject",Gn="g",kn="image",_n="line",Bn="linearGradient",Kn="marker",qn="mask",wn="metadata",Xn="mpath",Yn="path",Wn="pattern",$n="polygon",Jn="polyline",Qn="radialGradient",zn="rect",Zn="set",to="stop",eo="svg",no="switch",oo="symbol",ao="text",so="textPath",ro="tspan",co="use",io="view",lo="annotation",po="annotation-xml",fo="maction",So="math",uo="merror",To="mfrac",yo="mi",go="mmultiscripts",xo="mn",ho="mo",mo="mover",bo="mpadded",Eo="mphantom",Po="mprescripts",Ao="mroot",Co="mrow",Mo="ms",No="mspace",Ro="msqrt",Oo="mstyle",Do="msub",vo="msubsup",Lo="msup",Io="mtable",Fo="mtd",Vo="mtext",jo="mtr",Ho="munder",Uo="munderover",Go="semantics";function U(...e){if(!e||e.length===0)return null;if(e.length===1)return e[0];let n=e[0];for(let s=1;s<e.length;s++){let a=n,t=e[s];if(!a)n=t;else if(t)if(typeof a=="string"&&typeof t=="string"){let o=a.split(" "),r=t.split(" "),p=new Set([...o,...r]);n=Array.from(p).join(" ").trim()}else if(typeof a=="string"&&Array.isArray(t)){let o=new Set([...t,...a.split(" ")]);n=Array.from(o).join(" ").trim()}else if(Array.isArray(a)&&typeof t=="string"){let o=new Set([...a,...t.split(" ")]);n=Array.from(o).join(" ").trim()}else if(Array.isArray(a)&&Array.isArray(t)){let o=new Set([...a,...t]);n=Array.from(o).join(" ").trim()}else if(typeof a=="string"&&typeof t=="object")n={[a]:!0,...t};else if(typeof a=="object"&&typeof t=="string")n={...a,[t]:!0};else if(typeof a=="object"&&typeof t=="object")n={...a,...t};else if(typeof a=="object"&&Array.isArray(t)){let o={...a};for(let r of t)o[r]=!0;n=o}else if(Array.isArray(a)&&typeof t=="object"){let o={};for(let r of a)o[r]=!0;for(let r of Object.keys(t))o[r]=t[r];n=o}else throw new Error(`cannot merge classes of ${a} (${typeof a}) and ${t} (${typeof t})`);else continue}return n}var R;function G(...e){R||(R=document.createElement("div"));try{let n=R.style;for(let s of e)if(typeof s=="object"&&s!==null)for(let a in s)n[a]=s[a];else typeof s=="string"&&(n.cssText+=";"+s);return n.cssText}finally{R.style.cssText=""}}function wo(...e){if(e.length===0)return;if(e.length===1)return e[0]||void 0;let n;for(let s of e)if(!(typeof s!="object"||s===null)){n||(n={});for(let a in s)a==="style"?n.style=G(n.style,s.style):a==="class"?n.class=U(n.class,s.class):n[a]=s[a]}return n}function Yo(e){return new I(e,[])}var I=class e{constructor(n,s){this.state=n;this.keys=s;function a(i,c){if(s.length>1){let S=0,l=c[s[S]];for((typeof l!="object"||l===null)&&(c[s[S]]=l={}),S=1;S<s.length-1;S++){let y=l;l=l[s[S]],(typeof l!="object"||l===null)&&(y[s[S]]=l={})}l[s[S]]=i}else s.length===1?typeof c[s[0]]=="object"&&typeof i=="object"?Object.assign(c[s[0]],i):c[s[0]]=i:Object.assign(c,i)}function t(i){let c={};return a(i,c),c}function o(){if(s.length===0)return n;let i=n?n[s[0]]:void 0;for(let c=1;c<s.length&&i;c++)i=i[s[c]];return i}function r(i){a(i,n)}function p(i,c){c?n.patch([t(i)]):n.patch(t(i))}return new Proxy(this,{get:(i,c,S)=>{if(c==="state")return n;if(c==="get")return o;if(c==="put")return r;if(c==="patch")return p;let l=[...i.keys,String(c)];return new e(i.state,l)}})}state;keys;get(){}put(n){}patch(n){}};export{Z as A,tt as ABBR,et as ADDRESS,on as ANIMATE,an as ANIMATEMOTION,sn as ANIMATETRANSFORM,lo as ANNOTATION,po as ANNOTATION_XML,nt as AREA,ot as ARTICLE,at as ASIDE,st as AUDIO,rt as B,ct as BASE,it as BDI,lt as BDO,pt as BLOCKQUOTE,ft as BODY,St as BR,dt as BUTTON,ut as CANVAS,Tt as CAPTION,rn as CIRCLE,yt as CITE,cn as CLIPPATH,gt as CODE,xt as COL,ht as COLGROUP,mt as DATA,bt as DATALIST,Et as DD,ln as DEFS,Pt as DEL,pn as DESC,At as DETAILS,Ct as DFN,Mt as DIALOG,Nt as DIV,Rt as DL,Ot as DT,fn as ELLIPSE,Dt as EM,vt as EMBED,Sn as FEBLEND,dn as FECOLORMATRIX,un as FECOMPONENTTRANSFER,Tn as FECOMPOSITE,yn as FECONVOLVEMATRIX,gn as FEDIFFUSELIGHTING,xn as FEDISPLACEMENTMAP,hn as FEDISTANTLIGHT,mn as FEDROPSHADOW,bn as FEFLOOD,En as FEFUNCA,Pn as FEFUNCB,An as FEFUNCG,Cn as FEFUNCR,Mn as FEGAUSSIANBLUR,Nn as FEIMAGE,Rn as FEMERGE,On as FEMERGENODE,Dn as FEMORPHOLOGY,vn as FEOFFSET,Ln as FEPOINTLIGHT,In as FESPECULARLIGHTING,Fn as FESPOTLIGHT,Vn as FETILE,jn as FETURBULENCE,Lt as FIELDSET,It as FIGCAPTION,Ft as FIGURE,Hn as FILTER,Vt as FOOTER,Un as FOREIGNOBJECT,jt as FORM,Gn as G,Ht as H1,Ut as H2,Gt as H3,kt as H4,_t as H5,Bt as H6,Kt as HEAD,qt as HEADER,wt as HGROUP,Xt as HR,Yt as HTML,Wt as I,$t as IFRAME,kn as IMAGE,Jt as IMG,Qt as INPUT,zt as INS,Zt as KBD,te as LABEL,ee as LEGEND,ne as LI,_n as LINE,Bn as LINEARGRADIENT,oe as LINK,fo as MACTION,ae as MAIN,se as MAP,re as MARK,Kn as MARKER,qn as MASK,So as MATH,ce as MENU,uo as MERROR,ie as META,wn as METADATA,le as METER,To as MFRAC,yo as MI,go as MMULTISCRIPTS,xo as MN,ho as MO,mo as MOVER,bo as MPADDED,Xn as MPATH,Eo as MPHANTOM,Po as MPRESCRIPTS,Ao as MROOT,Co as MROW,Mo as MS,No as MSPACE,Ro as MSQRT,Oo as MSTYLE,Do as MSUB,vo as MSUBSUP,Lo as MSUP,Io as MTABLE,Fo as MTD,Vo as MTEXT,jo as MTR,Ho as MUNDER,Uo as MUNDEROVER,pe as NAV,fe as NOSCRIPT,Se as OBJECT,de as OL,ue as OPTGROUP,Te as OPTION,ye as OUTPUT,ge as P,Yn as PATH,Wn as PATTERN,xe as PICTURE,$n as POLYGON,Jn as POLYLINE,he as PRE,me as PROGRESS,be as Q,Qn as RADIALGRADIENT,zn as RECT,Ee as RP,Pe as RT,Ae as RUBY,Ce as S,Me as SAMP,Ne as SCRIPT,Re as SEARCH,Oe as SECTION,De as SELECT,Go as SEMANTICS,Zn as SET,ve as SLOT,Le as SMALL,Ie as SOURCE,Fe as SPAN,to as STOP,Ve as STRONG,je as STYLE,He as SUB,Ue as SUMMARY,Ge as SUP,eo as SVG,no as SWITCH,oo as SYMBOL,ke as TABLE,_e as TBODY,Be as TD,Ke as TEMPLATE,ao as TEXT,qe as TEXTAREA,so as TEXTPATH,we as TFOOT,Xe as TH,Ye as THEAD,We as TIME,$e as TITLE,Je as TR,Qe as TRACK,ro as TSPAN,ze as U,Ze as UL,co as USE,tn as VAR,en as VIDEO,io as VIEW,nn as WBR,w as app,Q as child,J as childCount,N as children,L as childrenStart,Yo as context,W as createPatch,Y as createState,V as defuse,P as globals,v as hydrate,X as memo,U as mergeClass,wo as mergeProps,G as mergeStyle,A as props,$ as tag,q as vode};
|
package/dist/vode.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// src/vode.ts
|
|
2
2
|
var globals = {
|
|
3
3
|
currentViewTransition: void 0,
|
|
4
|
-
requestAnimationFrame:
|
|
5
|
-
startViewTransition:
|
|
4
|
+
requestAnimationFrame: typeof window !== "undefined" && typeof window.requestAnimationFrame === "function" ? window.requestAnimationFrame.bind(window) : ((cb) => cb()),
|
|
5
|
+
startViewTransition: typeof document !== "undefined" && typeof document.startViewTransition === "function" ? document.startViewTransition.bind(document) : null
|
|
6
6
|
};
|
|
7
7
|
function vode(tag2, props2, ...children2) {
|
|
8
8
|
if (!tag2) throw new Error("first argument to vode() must be a tag name or a vode");
|
|
9
9
|
if (Array.isArray(tag2)) return tag2;
|
|
10
|
-
else if (props2) return [tag2, props2, ...children2];
|
|
10
|
+
else if (typeof props2 === "object") return [tag2, props2, ...children2];
|
|
11
11
|
else return [tag2, ...children2];
|
|
12
12
|
}
|
|
13
13
|
function app(container, state, dom, ...initialPatches) {
|
|
@@ -200,8 +200,6 @@ function hydrate(element, prepareForRender) {
|
|
|
200
200
|
if (element.nodeValue?.trim() !== "")
|
|
201
201
|
return prepareForRender ? element : element.nodeValue;
|
|
202
202
|
return void 0;
|
|
203
|
-
} else if (element.nodeType === Node.COMMENT_NODE) {
|
|
204
|
-
return void 0;
|
|
205
203
|
} else if (element.nodeType === Node.ELEMENT_NODE) {
|
|
206
204
|
const tag2 = element.tagName.toLowerCase();
|
|
207
205
|
const root = [tag2];
|
|
@@ -496,9 +494,28 @@ function remember(state, present, past) {
|
|
|
496
494
|
}
|
|
497
495
|
if (same) return past;
|
|
498
496
|
}
|
|
499
|
-
const
|
|
497
|
+
const result = present(state);
|
|
498
|
+
if (typeof result === "function" && result?.__memo) {
|
|
499
|
+
const resultMemo = result.__memo;
|
|
500
|
+
if (Array.isArray(resultMemo) && Array.isArray(pastMemo) && resultMemo.length === pastMemo.length) {
|
|
501
|
+
let same = true;
|
|
502
|
+
for (let i = 0; i < resultMemo.length; i++) {
|
|
503
|
+
if (resultMemo[i] !== pastMemo[i]) {
|
|
504
|
+
same = false;
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
if (same) return past;
|
|
509
|
+
}
|
|
510
|
+
const innerRender = result(state);
|
|
511
|
+
if (typeof innerRender === "object") {
|
|
512
|
+
innerRender.__memo = resultMemo;
|
|
513
|
+
}
|
|
514
|
+
return innerRender;
|
|
515
|
+
}
|
|
516
|
+
const newRender = typeof result === "function" ? unwrap(result, state) : result;
|
|
500
517
|
if (typeof newRender === "object") {
|
|
501
|
-
newRender.__memo = present?.__memo;
|
|
518
|
+
newRender.__memo = result?.__memo || present?.__memo;
|
|
502
519
|
}
|
|
503
520
|
return newRender;
|
|
504
521
|
}
|
|
@@ -857,8 +874,11 @@ function mergeClass(...classes) {
|
|
|
857
874
|
}
|
|
858
875
|
|
|
859
876
|
// src/merge-style.ts
|
|
860
|
-
var tempDivForStyling
|
|
877
|
+
var tempDivForStyling;
|
|
861
878
|
function mergeStyle(...props2) {
|
|
879
|
+
if (!tempDivForStyling) {
|
|
880
|
+
tempDivForStyling = document.createElement("div");
|
|
881
|
+
}
|
|
862
882
|
try {
|
|
863
883
|
const merged = tempDivForStyling.style;
|
|
864
884
|
for (const style of props2) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ryupold/vode",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.5",
|
|
4
4
|
"description": "a minimalist web framework",
|
|
5
5
|
"author": "Michael Scherbakow (ryupold)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -46,12 +46,13 @@
|
|
|
46
46
|
"release": "npm run build && npm run build-min && npm run build-classic && npm run build-classic-min && npm run babel && npm run babel-classic && npm run types",
|
|
47
47
|
"publish": "npm publish --access public",
|
|
48
48
|
"clean": "tsc -b --clean && rm dist/*",
|
|
49
|
-
"watch": "tsc -b -w"
|
|
49
|
+
"watch": "tsc -b -w",
|
|
50
|
+
"test": "tsc -p tsconfig.test.json && esbuild test/index.ts --bundle --outfile=test/bundle.js --platform=node && node test/bundle.js"
|
|
50
51
|
},
|
|
51
52
|
"devDependencies": {
|
|
52
53
|
"@babel/cli": "7.28.6",
|
|
53
54
|
"@babel/core": "7.29.0",
|
|
54
|
-
"@babel/preset-env": "7.29.
|
|
55
|
+
"@babel/preset-env": "7.29.5",
|
|
55
56
|
"babel-preset-minify": "0.5.2",
|
|
56
57
|
"dts-bundle-generator": "9.5.1",
|
|
57
58
|
"esbuild": "0.28.0",
|
package/src/merge-style.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { StyleProp } from "./vode";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
let tempDivForStyling: HTMLElement | undefined;
|
|
4
4
|
|
|
5
5
|
/** merge `StyleProps`s regardless of type
|
|
6
6
|
* @returns {string} merged StyleProp */
|
|
7
7
|
export function mergeStyle(...props: StyleProp[]): StyleProp {
|
|
8
|
+
if (!tempDivForStyling) {
|
|
9
|
+
tempDivForStyling = document.createElement('div');
|
|
10
|
+
}
|
|
8
11
|
try{
|
|
9
12
|
const merged = tempDivForStyling.style;
|
|
10
13
|
for (const style of props) {
|
package/src/vode.ts
CHANGED
|
@@ -78,8 +78,8 @@ export type PatchableState<S = object> = S & Patchable<S>;
|
|
|
78
78
|
|
|
79
79
|
export const globals = {
|
|
80
80
|
currentViewTransition: <ViewTransition | null | undefined>undefined,
|
|
81
|
-
requestAnimationFrame:
|
|
82
|
-
startViewTransition:
|
|
81
|
+
requestAnimationFrame: typeof window !== "undefined" && typeof window.requestAnimationFrame === "function" ? window.requestAnimationFrame.bind(window) : ((cb: () => void) => cb()),
|
|
82
|
+
startViewTransition: typeof document !== "undefined" && typeof document.startViewTransition === "function" ? document.startViewTransition.bind(document) : null,
|
|
83
83
|
};
|
|
84
84
|
|
|
85
85
|
export interface ContainerNode<S = PatchableState> extends HTMLElement {
|
|
@@ -122,7 +122,7 @@ export function vode<S = PatchableState>(tag: Tag | Vode<S>, props?: Props<S> |
|
|
|
122
122
|
if (!tag) throw new Error("first argument to vode() must be a tag name or a vode");
|
|
123
123
|
|
|
124
124
|
if (Array.isArray(tag)) return tag;
|
|
125
|
-
else if (props) return [tag, props as Props<S>, ...children];
|
|
125
|
+
else if (typeof props === "object") return [tag, props as Props<S>, ...children];
|
|
126
126
|
else return [tag, ...children];
|
|
127
127
|
}
|
|
128
128
|
|
|
@@ -349,9 +349,6 @@ export function hydrate<S = PatchableState>(element: Element | Text, prepareForR
|
|
|
349
349
|
return prepareForRender ? element as Text : (element as Text).nodeValue!;
|
|
350
350
|
return undefined; //ignore (mostly html whitespace)
|
|
351
351
|
}
|
|
352
|
-
else if (element.nodeType === Node.COMMENT_NODE) {
|
|
353
|
-
return undefined; //ignore (not interesting)
|
|
354
|
-
}
|
|
355
352
|
else if (element.nodeType === Node.ELEMENT_NODE) {
|
|
356
353
|
const tag: Tag = (<Element>element).tagName.toLowerCase();
|
|
357
354
|
const root: Vode<S> = [tag];
|
|
@@ -730,9 +727,31 @@ function remember<S>(state: S, present: any, past: any): ChildVode<S> | Attached
|
|
|
730
727
|
}
|
|
731
728
|
if (same) return past;
|
|
732
729
|
}
|
|
733
|
-
|
|
730
|
+
|
|
731
|
+
const result = present(state);
|
|
732
|
+
|
|
733
|
+
if (typeof result === "function" && result?.__memo) {
|
|
734
|
+
const resultMemo = result.__memo;
|
|
735
|
+
if (Array.isArray(resultMemo) && Array.isArray(pastMemo) && resultMemo.length === pastMemo.length) {
|
|
736
|
+
let same = true;
|
|
737
|
+
for (let i = 0; i < resultMemo.length; i++) {
|
|
738
|
+
if (resultMemo[i] !== pastMemo[i]) {
|
|
739
|
+
same = false;
|
|
740
|
+
break;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
if (same) return past;
|
|
744
|
+
}
|
|
745
|
+
const innerRender = result(state);
|
|
746
|
+
if (typeof innerRender === "object") {
|
|
747
|
+
innerRender.__memo = resultMemo;
|
|
748
|
+
}
|
|
749
|
+
return innerRender;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
const newRender = typeof result === "function" ? unwrap(result, state) : result;
|
|
734
753
|
if (typeof newRender === "object") {
|
|
735
|
-
(<any>newRender).__memo = present?.__memo;
|
|
754
|
+
(<any>newRender).__memo = result?.__memo || present?.__memo;
|
|
736
755
|
}
|
|
737
756
|
return newRender;
|
|
738
757
|
}
|
package/test/helper.ts
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { children, ChildVode, PatchableState, tag, Vode } from "../src/vode";
|
|
2
|
+
import { MockElement, MockText } from "./mocks";
|
|
3
|
+
|
|
4
|
+
export class Expectation {
|
|
5
|
+
constructor(public readonly what: any) { }
|
|
6
|
+
|
|
7
|
+
toBeA(type: "undefined" | "object" | "function" | "bigint" | "boolean" | "number" | "string" | "symbol") {
|
|
8
|
+
if (typeof this.what !== type) {
|
|
9
|
+
throw new ExpectationError(this, `expected \n\ntypeof ${this.what}\n\nto be \n\n${type}`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
toEqual(other: any) {
|
|
14
|
+
function deepCompare(a: any, b: any, path: string[]): string[] | null {
|
|
15
|
+
if (typeof a !== typeof b) {
|
|
16
|
+
if (path.length === 0) path.push(``);
|
|
17
|
+
path[path.length - 1] += ` (type: ${typeof a} != ${typeof b})`;
|
|
18
|
+
return path;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (typeof a !== "object" || a === null) {
|
|
22
|
+
if (path.length === 0) path.push(``);
|
|
23
|
+
path[path.length - 1] += ` (value: ${a} != ${b})`;
|
|
24
|
+
return a !== b ? path : null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
for (const prop of Object.entries(a)) {
|
|
28
|
+
const [k, v] = prop;
|
|
29
|
+
const result = deepCompare(v, b[k], [...path, k]);
|
|
30
|
+
if (result) {
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
for (const prop of Object.entries(b)) {
|
|
36
|
+
const [k, v] = prop;
|
|
37
|
+
const result = deepCompare(a[k], v, [...path, k]);
|
|
38
|
+
if (result) {
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (typeof this.what === "object" && typeof other === "object" && this.what !== null && other !== null) {
|
|
47
|
+
const unequal = deepCompare(this.what, other, []);
|
|
48
|
+
if (unequal) {
|
|
49
|
+
throw new ExpectationError(this, `expected \n\n${JSON.stringify(this.what, null, 2)}\n\n to equal \n\n${JSON.stringify(other, null, 2)}\n\nThey differ in: ${unequal.join(".")}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
if (this.what !== other) {
|
|
54
|
+
throw new ExpectationError(this, `expected (${typeof this.what})\n\n${this.what}\n\nto equal (${typeof other})\n\n${other}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
toSucceed<Result>(...args: any): Result {
|
|
60
|
+
if (typeof this.what !== "function") {
|
|
61
|
+
throw new ExpectationError(this, `expected a function\n\nbut it is a ${typeof this.what}`);
|
|
62
|
+
}
|
|
63
|
+
return this.what(...args);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
toFail(...args: any): Error {
|
|
67
|
+
if (typeof this.what !== "function") {
|
|
68
|
+
throw new ExpectationError(this, `expected a function\n\nbut it is a ${typeof this.what}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let r: any;
|
|
72
|
+
try {
|
|
73
|
+
r = this.what(...args);
|
|
74
|
+
} catch (err: any) {
|
|
75
|
+
return err;
|
|
76
|
+
}
|
|
77
|
+
throw new ExpectationError(this, `expected function to fail\n\nbut it succeeded with a result of type ${typeof r}\n\n${r}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
toMatch(v: ChildVode, state?: PatchableState) {
|
|
81
|
+
if (this.what instanceof MockElement || this.what instanceof MockText || typeof this.what === "string" || Array.isArray(this.what) || typeof this.what === "function") {
|
|
82
|
+
const that = this;
|
|
83
|
+
function deepCompare(e: MockElement | MockText | ChildVode, cv: ChildVode, path: string[]): string[] | null {
|
|
84
|
+
|
|
85
|
+
// unwrap component
|
|
86
|
+
while (typeof cv === "function") {
|
|
87
|
+
if (!state) {
|
|
88
|
+
throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na Component\n\nbut got no state passed in [toMatch]`);
|
|
89
|
+
}
|
|
90
|
+
cv = cv(state);
|
|
91
|
+
}
|
|
92
|
+
while (typeof e === "function") {
|
|
93
|
+
if (!state) {
|
|
94
|
+
throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na Component\n\nbut got no state passed in [toMatch]`);
|
|
95
|
+
}
|
|
96
|
+
e = e(state);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (typeof cv === "string" && e instanceof MockText) {
|
|
100
|
+
if (cv !== e.wholeText) {
|
|
101
|
+
throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na text node with\n${cv}\n\nbut text was\n${e.wholeText}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else if (typeof cv === "string" && typeof e === "string") {
|
|
105
|
+
if (cv !== e) {
|
|
106
|
+
throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na text node with\n${cv}\n\nbut text was\n${e}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
else if (Array.isArray(cv) && e instanceof MockElement) {
|
|
111
|
+
if (tag(cv)?.toLocaleUpperCase() !== e.tagName.toUpperCase()) {
|
|
112
|
+
throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\nan element <${tag(cv)}>\n\nbut got <${e.tagName}>`);
|
|
113
|
+
}
|
|
114
|
+
const kids = children(cv) || [];
|
|
115
|
+
for (let i = 0; i < kids.length; i++) {
|
|
116
|
+
deepCompare(e.children[i], kids[i], [...path, `${tag(kids[i] as Vode) || "#text"}`]);
|
|
117
|
+
}
|
|
118
|
+
if (kids.length !== e.children.length) {
|
|
119
|
+
throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\n${kids.length} children\n\nbut <${e.tagName}> has ${e.children.length} children`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else if (Array.isArray(cv) && Array.isArray(e)) {
|
|
123
|
+
if (tag(cv)?.toLocaleUpperCase() !== tag(e)?.toUpperCase()) {
|
|
124
|
+
throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\nan element [${tag(cv)}]\n\nbut got [${tag(e)}]`);
|
|
125
|
+
}
|
|
126
|
+
const kids = children(cv) || [];
|
|
127
|
+
const otherKids = children(e) || [];
|
|
128
|
+
for (let i = 0; i < kids.length; i++) {
|
|
129
|
+
deepCompare(otherKids[i], kids[i], [...path, `${tag(kids[i] as Vode) || "#text"}`]);
|
|
130
|
+
}
|
|
131
|
+
if (kids.length !== otherKids.length) {
|
|
132
|
+
throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\n${kids.length} children\n\nbut [${tag(e)}] has ${otherKids.length} children`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
else if (typeof cv === "string" && e instanceof MockElement) {
|
|
137
|
+
throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na text node\n\nbut got <${e.tagName}>`);
|
|
138
|
+
}
|
|
139
|
+
else if (typeof cv === "string" && Array.isArray(e)) {
|
|
140
|
+
throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na text node\n\nbut got [${tag(e)}]`);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
else if (Array.isArray(cv) && e instanceof MockText) {
|
|
144
|
+
throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\nan element <${tag(cv)}>\n\nbut got #text (${e.wholeText})`);
|
|
145
|
+
}
|
|
146
|
+
else if (Array.isArray(cv) && typeof e === "string") {
|
|
147
|
+
throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\nan element <${tag(cv)}>\n\nbut got #text (${e})`);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
deepCompare(this.what, v, [tag(v as Vode) || "#text"]);
|
|
154
|
+
} else {
|
|
155
|
+
throw new ExpectationError(this, `expected an element or text node\n\nbut it is a ${typeof this.what}\n${this.what}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export class ExpectationError extends Error {
|
|
161
|
+
constructor(public readonly expectation: Expectation, message?: string) {
|
|
162
|
+
super(message)
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function expect(what: any) {
|
|
167
|
+
return new Expectation(what);
|
|
168
|
+
}
|
package/test/index.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { resetMocks } from "./mocks";
|
|
2
|
+
import { ExpectationError } from "./helper";
|
|
3
|
+
|
|
4
|
+
//=== REGISTERED TESTS =========================================
|
|
5
|
+
import vodeTests from "./tests-vode";
|
|
6
|
+
import appTests from "./tests-app";
|
|
7
|
+
import defuseTests from "./tests-defuse";
|
|
8
|
+
import hydrateTests from "./tests-hydrate";
|
|
9
|
+
import memoTests from "./tests-memo";
|
|
10
|
+
import createStateTests from "./tests-createState";
|
|
11
|
+
import createPatchTests from "./tests-createPatch";
|
|
12
|
+
import tagTests from "./tests-tag";
|
|
13
|
+
import childrenTests from "./tests-children";
|
|
14
|
+
import propsTests from "./tests-props";
|
|
15
|
+
import mergeClassTests from "./tests-mergeClass";
|
|
16
|
+
import mergeStyleTests from "./tests-mergeStyle";
|
|
17
|
+
import mergePropsTests from "./tests-mergeProps";
|
|
18
|
+
import stateContextTests from "./tests-state-context";
|
|
19
|
+
|
|
20
|
+
const tests = {
|
|
21
|
+
...vodeTests,
|
|
22
|
+
...appTests,
|
|
23
|
+
...defuseTests,
|
|
24
|
+
...hydrateTests,
|
|
25
|
+
...memoTests,
|
|
26
|
+
|
|
27
|
+
...createStateTests,
|
|
28
|
+
...createPatchTests,
|
|
29
|
+
|
|
30
|
+
...tagTests,
|
|
31
|
+
...propsTests,
|
|
32
|
+
...childrenTests,
|
|
33
|
+
|
|
34
|
+
...mergeClassTests,
|
|
35
|
+
...mergeStyleTests,
|
|
36
|
+
...mergePropsTests,
|
|
37
|
+
|
|
38
|
+
...stateContextTests,
|
|
39
|
+
};
|
|
40
|
+
//===================================================
|
|
41
|
+
|
|
42
|
+
const count = {
|
|
43
|
+
total: 0,
|
|
44
|
+
passed: 0,
|
|
45
|
+
failed: <string[]>[],
|
|
46
|
+
}
|
|
47
|
+
const line = "----------------------------------";
|
|
48
|
+
|
|
49
|
+
for (const test of Object.entries(tests)) {
|
|
50
|
+
count.total++;
|
|
51
|
+
resetMocks();
|
|
52
|
+
try {
|
|
53
|
+
test[1]()
|
|
54
|
+
count.passed++;
|
|
55
|
+
console.log(`#${count.total} ${test[0]}\n-> 🟢 passed\n${line}`);
|
|
56
|
+
} catch (err: any) {
|
|
57
|
+
console.error(`#${count.total} ${test[0]}\n-> 🔴 failed`);
|
|
58
|
+
if (err instanceof ExpectationError) {
|
|
59
|
+
count.failed.push(`#${count.total} ${test[0]}\n-> 🔴 failed:\n${err.message}\n${line}`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
count.failed.push(`#${count.total} ${test[0]}\n-> 🔴 failed:\n${err.message}\n${err.stack}\n${line}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
console.log(`
|
|
68
|
+
total: ${count.total}
|
|
69
|
+
passed: ${count.passed}
|
|
70
|
+
failed: ${count.failed.length}
|
|
71
|
+
`);
|
|
72
|
+
|
|
73
|
+
if (count.passed === count.total) {
|
|
74
|
+
console.log("\n\nall tests passed\n");
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
console.error(`${line.replaceAll("-", "=")}\nError summary:\n\n${count.failed.join(`\n${line}\n`)}`);
|
|
78
|
+
|
|
79
|
+
throw "\n\nsome tests failed (see output)\n";
|
|
80
|
+
}
|
package/test/mocks.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
const NodeConstants = {
|
|
2
|
+
ELEMENT_NODE: 1,
|
|
3
|
+
ATTRIBUTE_NODE: 2,
|
|
4
|
+
TEXT_NODE: 3,
|
|
5
|
+
CDATA_SECTION_NODE: 4,
|
|
6
|
+
ENTITY_REFERENCE_NODE: 5,
|
|
7
|
+
ENTITY_NODE: 6,
|
|
8
|
+
PROCESSING_INSTRUCTION_NODE: 7,
|
|
9
|
+
COMMENT_NODE: 8,
|
|
10
|
+
DOCUMENT_NODE: 9,
|
|
11
|
+
DOCUMENT_TYPE_NODE: 10,
|
|
12
|
+
DOCUMENT_FRAGMENT_NODE: 11,
|
|
13
|
+
NOTATION_NODE: 12,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export class MockElement {
|
|
17
|
+
nodeType = NodeConstants.ELEMENT_NODE;
|
|
18
|
+
childNodes: (MockElement | MockText)[] = [];
|
|
19
|
+
children: (MockElement | MockText)[] = [];
|
|
20
|
+
parentElement: MockElement | null = null;
|
|
21
|
+
get attributes() {
|
|
22
|
+
return Object.entries(this._attrs).map(([name, value]) => ({ name, value }));
|
|
23
|
+
}
|
|
24
|
+
style: { cssText: string } = { cssText: "" };
|
|
25
|
+
tagName = "UNKNOWN";
|
|
26
|
+
private _attrs: Record<string, string> = {};
|
|
27
|
+
|
|
28
|
+
constructor(public tag?: string) {
|
|
29
|
+
if (tag) this.tagName = tag.toUpperCase();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get firstChild() { return this.childNodes[0] ?? null; }
|
|
33
|
+
get lastChild() { return this.childNodes[this.childNodes.length - 1] ?? null; }
|
|
34
|
+
get nextSibling() { return null; }
|
|
35
|
+
|
|
36
|
+
hasAttributes() { return Object.keys(this._attrs).length > 0; }
|
|
37
|
+
hasChildNodes() { return this.childNodes.length > 0; }
|
|
38
|
+
setAttribute(name: string, value: string) { this._attrs[name] = value; }
|
|
39
|
+
removeAttribute(name: string) { delete this._attrs[name]; }
|
|
40
|
+
appendChild(child: MockElement | MockText) {
|
|
41
|
+
this.childNodes.push(child); this.children.push(child); if (child.parentElement !== undefined) child.parentElement = this; return child;
|
|
42
|
+
}
|
|
43
|
+
remove() {
|
|
44
|
+
if (this.parentElement) { const i = this.parentElement.childNodes.indexOf(this); if (i >= 0) this.parentElement.childNodes.splice(i, 1); }
|
|
45
|
+
}
|
|
46
|
+
replaceWith(...nodes: (MockElement | MockText)[]) {
|
|
47
|
+
const parent = this.parentElement;
|
|
48
|
+
if (parent) {
|
|
49
|
+
const i = parent.childNodes.indexOf(this);
|
|
50
|
+
if (i >= 0) { parent.childNodes.splice(i, 1, ...nodes); }
|
|
51
|
+
for (const n of nodes) n.parentElement = parent;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
before(...nodes: (MockElement | MockText)[]) {
|
|
55
|
+
const parent = this.parentElement;
|
|
56
|
+
if (parent) {
|
|
57
|
+
const i = parent.childNodes.indexOf(this);
|
|
58
|
+
if (i >= 0) { parent.childNodes.splice(i, 0, ...nodes); }
|
|
59
|
+
for (const n of nodes) n.parentElement = parent;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
get [Symbol.iterator]() { return Array.prototype[Symbol.iterator].bind(this.children); }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export class MockText {
|
|
66
|
+
nodeType = NodeConstants.TEXT_NODE;
|
|
67
|
+
parentElement: MockElement | null = null;
|
|
68
|
+
constructor(public nodeValue: string) { }
|
|
69
|
+
get wholeText() { return this.nodeValue; }
|
|
70
|
+
remove() { if (this.parentElement) { const i = this.parentElement.childNodes.indexOf(this); if (i >= 0) this.parentElement.childNodes.splice(i, 1); } }
|
|
71
|
+
replaceWith(...nodes: (MockElement | MockText)[]) {
|
|
72
|
+
const parent = this.parentElement;
|
|
73
|
+
if (parent) {
|
|
74
|
+
const i = parent.childNodes.indexOf(this);
|
|
75
|
+
if (i >= 0) { parent.childNodes.splice(i, 1, ...nodes); }
|
|
76
|
+
for (const n of nodes) n.parentElement = parent;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
before(...nodes: (MockElement | MockText)[]) {
|
|
80
|
+
const parent = this.parentElement;
|
|
81
|
+
if (parent) {
|
|
82
|
+
const i = parent.childNodes.indexOf(this);
|
|
83
|
+
if (i >= 0) { parent.childNodes.splice(i, 0, ...nodes); }
|
|
84
|
+
for (const n of nodes) n.parentElement = parent;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function resetMocks() {
|
|
90
|
+
const mockDoc: any = {
|
|
91
|
+
createElement: (tag: string) => new MockElement(tag),
|
|
92
|
+
createTextNode: (text: string) => new MockText(text),
|
|
93
|
+
createElementNS: (ns: string, tag: string) => new MockElement(tag),
|
|
94
|
+
hidden: false,
|
|
95
|
+
};
|
|
96
|
+
const mockWin: any = {
|
|
97
|
+
requestAnimationFrame: (cb: any) => cb(Date.now()),
|
|
98
|
+
startViewTransition: (callbackOptions: any) => {
|
|
99
|
+
return {
|
|
100
|
+
finished: Promise.resolve(),
|
|
101
|
+
ready: Promise.resolve(),
|
|
102
|
+
updateCallbackDone: Promise.resolve(),
|
|
103
|
+
skipTransition() { },
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
globalThis.document ??= mockDoc as Document;
|
|
109
|
+
globalThis.window ??= mockWin as (Window & typeof globalThis);
|
|
110
|
+
globalThis.Node ??= NodeConstants as any;
|
|
111
|
+
}
|