sprae 2.0.0 → 2.1.1

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/sprae.min.js CHANGED
@@ -1 +1 @@
1
- function t(){throw new Error("Cycle detected")}function e(){if(o>1)o--;else{for(var t,e=!1;void 0!==n;){var i=n;for(n=void 0,s++;void 0!==i;){var r=i.o;if(i.o=void 0,i.f&=-3,!(8&i.f)&&h(i))try{i.c()}catch(i){e||(t=i,e=!0)}i=r}}if(s=0,o--,e)throw t}}var r=void 0,n=void 0,o=0,s=0,f=0;function a(t){if(void 0!==r){var e=t.n;if(void 0===e||e.t!==r)return r.s=e={i:0,S:t,p:void 0,n:r.s,t:r,e:void 0,x:void 0,r:e},t.n=e,32&r.f&&t.S(e),e;if(-1===e.i)return e.i=0,void 0!==e.p&&(e.p.n=e.n,void 0!==e.n&&(e.n.p=e.p),e.p=void 0,e.n=r.s,r.s.p=e,r.s=e),e}}function u(t){this.v=t,this.i=0,this.n=void 0,this.t=void 0}function l(t){return new u(t)}function h(t){for(var e=t.s;void 0!==e;e=e.n)if(e.S.i!==e.i||!e.S.h()||e.S.i!==e.i)return!0;return!1}function v(t){for(var e=t.s;void 0!==e;e=e.n){var i=e.S.n;void 0!==i&&(e.r=i),e.S.n=e,e.i=-1}}function c(t){for(var e=t.s,i=void 0;void 0!==e;){var r=e.n;-1===e.i?(e.S.U(e),e.n=void 0):(void 0!==i&&(i.p=e),e.p=void 0,e.n=i,i=e),e.S.n=e.r,void 0!==e.r&&(e.r=void 0),e=r}t.s=i}function d(t){u.call(this,void 0),this.x=t,this.s=void 0,this.g=f-1,this.f=4}function p(t){return new d(t)}function y(t){var i=t.u;if(t.u=void 0,"function"==typeof i){o++;var n=r;r=void 0;try{i()}catch(e){throw t.f&=-2,t.f|=8,b(t),e}finally{r=n,e()}}}function b(t){for(var e=t.s;void 0!==e;e=e.n)e.S.U(e);t.x=void 0,t.s=void 0,y(t)}function m(t){if(r!==this)throw new Error("Out-of-order effect");c(this),r=t,this.f&=-2,8&this.f&&b(this),e()}function g(t){this.x=t,this.u=void 0,this.s=void 0,this.o=void 0,this.f=32}function S(t){var e=new g(t);return e.c(),e.d.bind(e)}u.prototype.h=function(){return!0},u.prototype.S=function(t){this.t!==t&&void 0===t.e&&(t.x=this.t,void 0!==this.t&&(this.t.e=t),this.t=t)},u.prototype.U=function(t){var e=t.e,i=t.x;void 0!==e&&(e.x=i,t.e=void 0),void 0!==i&&(i.e=e,t.x=void 0),t===this.t&&(this.t=i)},u.prototype.subscribe=function(t){var e=this;return S((function(){var i=e.value,r=32&this.f;this.f&=-33;try{t(i)}finally{this.f|=r}}))},u.prototype.valueOf=function(){return this.value},u.prototype.toString=function(){return this.value+""},u.prototype.peek=function(){return this.v},Object.defineProperty(u.prototype,"value",{get:function(){var t=a(this);return void 0!==t&&(t.i=this.i),this.v},set:function(i){if(i!==this.v){s>100&&t(),this.v=i,this.i++,f++,o++;try{for(var r=this.t;void 0!==r;r=r.x)r.t.N()}finally{e()}}}}),(d.prototype=new u).h=function(){if(this.f&=-3,1&this.f)return!1;if(32==(36&this.f))return!0;if(this.f&=-5,this.g===f)return!0;if(this.g=f,this.f|=1,this.i>0&&!h(this))return this.f&=-2,!0;var t=r;try{v(this),r=this;var e=this.x();(16&this.f||this.v!==e||0===this.i)&&(this.v=e,this.f&=-17,this.i++)}catch(t){this.v=t,this.f|=16,this.i++}return r=t,c(this),this.f&=-2,!0},d.prototype.S=function(t){if(void 0===this.t){this.f|=36;for(var e=this.s;void 0!==e;e=e.n)e.S.S(e)}u.prototype.S.call(this,t)},d.prototype.U=function(t){if(u.prototype.U.call(this,t),void 0===this.t){this.f&=-33;for(var e=this.s;void 0!==e;e=e.n)e.S.U(e)}},d.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var t=this.t;void 0!==t;t=t.x)t.t.N()}},d.prototype.peek=function(){if(this.h()||t(),16&this.f)throw this.v;return this.v},Object.defineProperty(d.prototype,"value",{get:function(){1&this.f&&t();var e=a(this);if(this.h(),void 0!==e&&(e.i=this.i),16&this.f)throw this.v;return this.v}}),g.prototype.c=function(){var t=this.S();try{8&this.f||void 0===this.x||(this.u=this.x())}finally{t()}},g.prototype.S=function(){1&this.f&&t(),this.f|=1,this.f&=-9,y(this),v(this),o++;var e=r;return r=this,m.bind(this,e)},g.prototype.N=function(){2&this.f||(this.f|=2,this.o=n,n=this)},g.prototype.d=function(){this.f|=8,1&this.f||b(this)},Symbol.observable||=Symbol("observable");var x=new FinalizationRegistry((t=>t.call?.())),w=t=>t&&t.peek,O=Symbol("signal-struct");function j(t){if(t[O])return t;let e,i;if(!k(t))throw Error("Only array or object states are supported");e={},i={};for(let r in t)i[r]=A(e,r,t[r]);return Object.defineProperty(e,O,{configurable:!1,enumerable:!1,value:!0}),Object.seal(e),e}function A(t,e,i){let r,n=w(i)?i:k(i)?l(j(i)):l((r=(o=i)&&!!(o[Symbol.observable]||o[Symbol.asyncIterator]||o.call&&o.set||o.subscribe||o.then))?void 0:i);var o,s,f,a,u,h,v;return r&&(f=t=>n.value=t,(s=i)&&(v=(s[Symbol.observable]?.()||s).subscribe?.(f,a,undefined),h=v&&(()=>v.unsubscribe?.())||s.set&&s.call?.(u,f)||(s.then?.((t=>{!u&&f(t)}),a)||(async t=>{try{for await(t of s){if(u)return;f(t)}}catch(t){}})())&&(t=>u=1),x.register(s,h))),Object.defineProperty(t,e,{get:()=>n.value,set:w(i)?t=>n.value=t:k(i)?t=>t?Object.assign(n.value,t):n.value=t:t=>n.value=t,enumerable:!0,configurable:!1}),n}function k(t){return t&&t.constructor===Object}var N=new WeakMap;function $(t,e){if(!t.children)return;if(N.has(t))return N.get(t);e||={};const i=j(e),r=t=>{let e,n;if(t.attributes)for(let r=0;r<t.attributes.length;){let o=t.attributes[r];if(":"===o.name[0]){if(e=E[o.name]||E.default,t.removeAttribute(o.name),n=!1===e(t,o.value,i,o.name.slice(1)))break}else r++}if(!n)for(let e of t.children)r(e)};return r(t),N.set(t,i),i}var E={},U=(t,e,i)=>{e.startsWith("on")&&(e=e.toLowerCase()),t[e]!==i&&(t[e]=i),!1===i||null==i?t.removeAttribute(e):"function"!=typeof i&&t.setAttribute(C(e),!0===i?"":"number"==typeof i||"string"==typeof i?i:"class"===e?(Array.isArray(i)?i:Object.entries(i).map((([t,e])=>e?t:""))).filter(Boolean).join(" "):"style"===e?Object.entries(i).map((([t,e])=>`${t}: ${e}`)).join(";"):"")},W=document.createElement("div"),C=t=>{W.dataset[t]="";let e=W.attributes[0].name.slice(5);return delete W.dataset[t],e},B=(t,e,i,r=null)=>{let n,o,s,f=0,a=i.length,u=e.length,{remove:l,same:h,insert:v,replace:c}=B;for(;f<a&&f<u&&h(e[f],i[f]);)f++;for(;f<a&&f<u&&h(i[a-1],e[u-1]);)r=i[(--u,--a)];if(f==u)for(;f<a;)v(r,i[f++],t);else{for(n=e[f];f<a;)s=i[f++],o=n?n.nextSibling:r,h(n,s)?n=o:f<a&&h(i[f],o)?(c(n,s,t),n=o):v(n,s,t);for(;!h(n,r);)o=n.nextSibling,l(n,t),n=o}return i};B.same=(t,e)=>t==e,B.replace=(t,e,i)=>i.replaceChild(e,t),B.insert=(t,e,i)=>i.insertBefore(e,t),B.remove=(t,e)=>e.removeChild(t);var P=B,L={},M={},T={},F=t=>null===t?M:void 0===t?T:"number"==typeof t||t instanceof Number?L[t]||(L[t]=new Number(t)):"string"==typeof t||t instanceof String?L[t]||(L[t]=new String(t)):"boolean"==typeof t||t instanceof Boolean?L[t]||(L[t]=new Boolean(t)):t;E[":with"]=(t,i,r)=>{let n=R(i,"with",r);const s=p((()=>Object.assign({},r,n(r))));let f=$(t,s.value);S(((t=s.value)=>function(t){if(o>0)return t();o++;try{return t()}finally{e()}}((()=>Object.assign(f,t)))))},E[":if"]=(t,e,i)=>{let r=document.createTextNode(""),n=[R(e,":if",i)],o=[t],s=t;for(;(s=t.nextElementSibling)&&s.hasAttribute(":else");)s.removeAttribute(":else"),(e=s.getAttribute(":if"))?(s.removeAttribute(":if"),s.remove(),o.push(s),n.push(R(e,":else :if",i))):(s.remove(),o.push(s),n.push((()=>1)));t.replaceWith(s=r);let f=p((()=>n.findIndex((t=>t(i)))));return S(((t=f.value)=>o[t]!=s&&((s[I]||s).replaceWith(s=o[t]||r),$(s,i)))),!1};var I=Symbol(":each");E[":each"]=(t,e,r)=>{let n=function(t){let e=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,i=t.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!i)return;let r={};r.items=i[2].trim();let n=i[1].replace(/^\s*\(|\)\s*$/g,"").trim(),o=n.match(e);return o?(r.item=n.replace(e,"").trim(),r.index=o[1].trim()):r.item=n,r}(e);if(!n)return q(new Error,e);const o=R(n.items,":each",r),s=t[I]=document.createTextNode("");t.replaceWith(s);const f=p((()=>{let t=o(r);return"number"==typeof t?Array.from({length:t},((t,e)=>e+1)):t})),a=new WeakMap,u=new WeakMap;let l=[];return S(((e=f.value)=>{e||(e=[]);let o=[],h=[];for(let s of e){let e=F(s),f=u.get(e);if(f||(f=t.cloneNode(!0),u.set(e,f)),o.push(f),!a.has(e)){let t=Object.create(r);t[n.item]=s,n.index&&(t[n.index]=i),a.set(e,t)}h.push(a.get(e))}P(s.parentNode,l,o,s),l=o;for(let t=0;t<o.length;t++)$(o[t],h[t])})),!1},E.default=(t,e,i,r)=>{let n=R(e,":"+r,i);S((()=>{return e=n(i),U(t,r,e);var e}))},E[":aria"]=(t,e,i)=>{let r=R(e,":aria",i);S((()=>(e=>{for(let i in e)U(t,"aria"+i[0].toUpperCase()+i.slice(1),null==e[i]?null:e[i]+"")})(r(i))))},E[":data"]=(t,e,i)=>{let r=R(e,":data",i);const n=p((()=>r(i)));S(((e=n.value)=>{for(let i in e)t.dataset[i]=e[i]}))},E[":on"]=(t,e,i)=>{let r,n=R(e,":on",i),o=p((()=>n(i)));S(((e=o.value)=>{for(let e in r)t.removeEventListener(e,r[e]);r=e;for(let e in r)t.addEventListener(e,r[e])}))},E[":"]=(t,e,i)=>{let r=R(e,":",i);S((()=>(e=>{if(e)for(let i in e)U(t,i,e[i])})(r(i))))},E[":text"]=(t,e,i)=>{let r=R(e,":text",i);S((()=>{return e=r(i),void(t.textContent=null==e?"":e);var e}))},E[":value"]=(t,e,i)=>{let r=R(e,":in",i),[n,o]=(t=>["checkbox"===t.type?()=>t.checked:()=>t.value,"text"===t.type||""===t.type?e=>t.value=null==e?"":e:"checkbox"===t.type?e=>(t.value=e?"on":"",U(t,"checked",e)):"select-one"===t.type?e=>([...t.options].map((t=>t.removeAttribute("selected"))),t.value=e,t.selectedOptions[0]?.setAttribute("selected","")):e=>t.value=e])(t);S((()=>{return e=r(i),U(t,"value",e),void o(e);var e}))};var z={};function R(t,e,i){if(z[t])return z[t];let r,n=/^[\n\s]*if.*\(.*\)/.test(t)||/^(let|const)\s/.test(t)?`(() => { ${t} })()`:t;try{r=new Function(["scope"],`let result; with (scope) { result = ${n} }; return result;`)}catch(r){return q(r,t,e,i)}return z[t]=n=>{let o;try{o=r(n)}catch(r){return q(r,t,e,i)}return o}}function q(t,e,i,r){Object.assign(t,{expression:e}),console.warn(`∴sprae: ${t.message}\n\n${i}=${e?`"${e}"\n\n`:""}`,r),setTimeout((()=>{throw t}),0)}var D=$;export{D as default,E as directives};
1
+ function t(){throw new Error("Cycle detected")}function e(){if(n>1)n--;else{for(var t,e=!1;void 0!==r;){var i=r;for(r=void 0,o++;void 0!==i;){var s=i.o;if(i.o=void 0,i.f&=-3,!(8&i.f)&&l(i))try{i.c()}catch(i){e||(t=i,e=!0)}i=s}}if(o=0,n--,e)throw t}}var i=void 0,r=void 0,n=0,o=0,s=0;function a(t){if(void 0!==i){var e=t.n;if(void 0===e||e.t!==i)return i.s=e={i:0,S:t,p:void 0,n:i.s,t:i,e:void 0,x:void 0,r:e},t.n=e,32&i.f&&t.S(e),e;if(-1===e.i)return e.i=0,void 0!==e.p&&(e.p.n=e.n,void 0!==e.n&&(e.n.p=e.p),e.p=void 0,e.n=i.s,i.s.p=e,i.s=e),e}}function f(t){this.v=t,this.i=0,this.n=void 0,this.t=void 0}function u(t){return new f(t)}function l(t){for(var e=t.s;void 0!==e;e=e.n)if(e.S.i!==e.i||!e.S.h()||e.S.i!==e.i)return!0;return!1}function h(t){for(var e=t.s;void 0!==e;e=e.n){var i=e.S.n;void 0!==i&&(e.r=i),e.S.n=e,e.i=-1}}function v(t){for(var e=t.s,i=void 0;void 0!==e;){var r=e.n;-1===e.i?(e.S.U(e),e.n=void 0):(void 0!==i&&(i.p=e),e.p=void 0,e.n=i,i=e),e.S.n=e.r,void 0!==e.r&&(e.r=void 0),e=r}t.s=i}function c(t){f.call(this,void 0),this.x=t,this.s=void 0,this.g=s-1,this.f=4}function d(t){return new c(t)}function p(t){var r=t.u;if(t.u=void 0,"function"==typeof r){n++;var o=i;i=void 0;try{r()}catch(e){throw t.f&=-2,t.f|=8,b(t),e}finally{i=o,e()}}}function b(t){for(var e=t.s;void 0!==e;e=e.n)e.S.U(e);t.x=void 0,t.s=void 0,p(t)}function y(t){if(i!==this)throw new Error("Out-of-order effect");v(this),i=t,this.f&=-2,8&this.f&&b(this),e()}function m(t){this.x=t,this.u=void 0,this.s=void 0,this.o=void 0,this.f=32}function g(t){var e=new m(t);return e.c(),e.d.bind(e)}f.prototype.h=function(){return!0},f.prototype.S=function(t){this.t!==t&&void 0===t.e&&(t.x=this.t,void 0!==this.t&&(this.t.e=t),this.t=t)},f.prototype.U=function(t){var e=t.e,i=t.x;void 0!==e&&(e.x=i,t.e=void 0),void 0!==i&&(i.e=e,t.x=void 0),t===this.t&&(this.t=i)},f.prototype.subscribe=function(t){var e=this;return g((function(){var i=e.value,r=32&this.f;this.f&=-33;try{t(i)}finally{this.f|=r}}))},f.prototype.valueOf=function(){return this.value},f.prototype.toString=function(){return this.value+""},f.prototype.peek=function(){return this.v},Object.defineProperty(f.prototype,"value",{get:function(){var t=a(this);return void 0!==t&&(t.i=this.i),this.v},set:function(i){if(i!==this.v){o>100&&t(),this.v=i,this.i++,s++,n++;try{for(var r=this.t;void 0!==r;r=r.x)r.t.N()}finally{e()}}}}),(c.prototype=new f).h=function(){if(this.f&=-3,1&this.f)return!1;if(32==(36&this.f))return!0;if(this.f&=-5,this.g===s)return!0;if(this.g=s,this.f|=1,this.i>0&&!l(this))return this.f&=-2,!0;var t=i;try{h(this),i=this;var e=this.x();(16&this.f||this.v!==e||0===this.i)&&(this.v=e,this.f&=-17,this.i++)}catch(t){this.v=t,this.f|=16,this.i++}return i=t,v(this),this.f&=-2,!0},c.prototype.S=function(t){if(void 0===this.t){this.f|=36;for(var e=this.s;void 0!==e;e=e.n)e.S.S(e)}f.prototype.S.call(this,t)},c.prototype.U=function(t){if(f.prototype.U.call(this,t),void 0===this.t){this.f&=-33;for(var e=this.s;void 0!==e;e=e.n)e.S.U(e)}},c.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var t=this.t;void 0!==t;t=t.x)t.t.N()}},c.prototype.peek=function(){if(this.h()||t(),16&this.f)throw this.v;return this.v},Object.defineProperty(c.prototype,"value",{get:function(){1&this.f&&t();var e=a(this);if(this.h(),void 0!==e&&(e.i=this.i),16&this.f)throw this.v;return this.v}}),m.prototype.c=function(){var t=this.S();try{8&this.f||void 0===this.x||(this.u=this.x())}finally{t()}},m.prototype.S=function(){1&this.f&&t(),this.f|=1,this.f&=-9,p(this),h(this),n++;var e=i;return i=this,y.bind(this,e)},m.prototype.N=function(){2&this.f||(this.f|=2,this.o=r,r=this)},m.prototype.d=function(){this.f|=8,1&this.f||b(this)},Symbol.observable||=Symbol("observable");var S=new FinalizationRegistry((t=>t.call?.())),x=t=>t&&t.peek,w=Symbol("signal-struct");function A(t){if((e=t)&&e[w])return t;var e;let i,r;if(j(t)){i={},r={};for(let e in t)r[e]=O(i,e,t[e]);return Object.defineProperty(i,w,{configurable:!1,enumerable:!1,value:!0}),Object.seal(i),i}return Array.isArray(t)?t.map((t=>A(t))):t}function O(t,e,i){let r,n=x(i)?i:j(i)||Array.isArray(i)?u(A(i)):u((r=(o=i)&&!!(o[Symbol.observable]||o[Symbol.asyncIterator]||o.call&&o.set||o.subscribe||o.then))?void 0:i);var o,s,a,f,l,h,v;return r&&(a=t=>n.value=t,(s=i)&&(v=(s[Symbol.observable]?.()||s).subscribe?.(a,f,undefined),h=v&&(()=>v.unsubscribe?.())||s.set&&s.call?.(l,a)||(s.then?.((t=>{!l&&a(t)}),f)||(async t=>{try{for await(t of s){if(l)return;a(t)}}catch(t){}})())&&(t=>l=1),S.register(s,h))),Object.defineProperty(t,e,{get:()=>n.value,set:!x(i)&&j(i)?t=>t?Object.assign(n.value,t):n.value=A(t):t=>n.value=A(t),enumerable:!0,configurable:!1}),n}function j(t){return t&&t.constructor===Object}var k=(t,e,i)=>{e.startsWith("on")&&(e=e.toLowerCase()),t[e]!==i&&(t[e]=i),!1===i||null==i?t.removeAttribute(e):"function"!=typeof i&&t.setAttribute($(e),!0===i?"":"number"==typeof i||"string"==typeof i?i:"class"===e?(Array.isArray(i)?i:Object.entries(i).map((([t,e])=>e?t:""))).filter(Boolean).join(" "):"style"===e?Object.entries(i).map((([t,e])=>`${t}: ${e}`)).join(";"):"")},N=document.createElement("div"),$=t=>{N.dataset[t]="";let e=N.attributes[0].name.slice(5);return delete N.dataset[t],e},E=(t,e,i,r=null)=>{let n,o,s,a=0,f=i.length,u=e.length,{remove:l,same:h,insert:v,replace:c}=E;for(;a<f&&a<u&&h(e[a],i[a]);)a++;for(;a<f&&a<u&&h(i[f-1],e[u-1]);)r=i[(--u,--f)];if(a==u)for(;a<f;)v(r,i[a++],t);else{for(n=e[a];a<f;)s=i[a++],o=n?n.nextSibling:r,h(n,s)?n=o:a<f&&h(i[a],o)?(c(n,s,t),n=o):v(n,s,t);for(;!h(n,r);)o=n.nextSibling,l(n,t),n=o}return i};E.same=(t,e)=>t==e,E.replace=(t,e,i)=>i.replaceChild(e,t),E.insert=(t,e,i)=>i.insertBefore(e,t),E.remove=(t,e)=>e.removeChild(t);var U=E,W={},C={},B={},P=(t,e,i,r)=>{let n=I(e,":"+r,i);g((()=>{return e=n(i),k(t,r,e);var e}))},L={},M=Symbol(":each"),T=Symbol(":ref");L[":with"]=(t,i,r)=>{let o=I(i,"with",r);const s=d((()=>Object.assign({},r,o(r))));let a=q(t,s.value);return g(((t=s.value)=>function(t){if(n>0)return t();n++;try{return t()}finally{e()}}((()=>Object.assign(a,t))))),!1},L[":ref"]=(t,e,i)=>t.hasAttribute(":each")?t[T]=e:(q(t,Object.assign(Object.create(i),{[e]:t})),!1),L[":if"]=(t,e,i)=>{let r=document.createTextNode(""),n=[I(e,":if",i)],o=[t],s=t;for(;(s=t.nextElementSibling)&&s.hasAttribute(":else");)s.removeAttribute(":else"),(e=s.getAttribute(":if"))?(s.removeAttribute(":if"),s.remove(),o.push(s),n.push(I(e,":else :if",i))):(s.remove(),o.push(s),n.push((()=>1)));t.replaceWith(s=r);let a=d((()=>n.findIndex((t=>t(i)))));return g(((t=a.value)=>o[t]!=s&&((s[M]||s).replaceWith(s=o[t]||r),q(s,i)))),!1},L[":each"]=(t,e,i)=>{let r=function(t){let e=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,i=t.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!i)return;let r={};r.items=i[2].trim();let n=i[1].replace(/^\s*\(|\)\s*$/g,"").trim(),o=n.match(e);return o?(r.item=n.replace(e,"").trim(),r.index=o[1].trim()):r.item=n,r}(e);if(!r)return z(new Error,e);const n=I(r.items,":each",i),o=t[M]=document.createTextNode("");t.replaceWith(o);const s=d((()=>{let t=n(i);return t?"number"==typeof t?Array.from({length:t},((t,e)=>[e,e+1])):t.constructor===Object?Object.entries(t):Array.isArray(t)?t.map(((t,e)=>[e+1,t])):void z(Error("Bad list value"),r.items,":each",t):[]})),a=new WeakMap,f=new WeakMap;let u=[];return g(((e=s.value)=>{let n=[],l=[];for(let[o,s]of e){let e=null===(h=s)?C:void 0===h?B:"number"==typeof h||h instanceof Number?W[h]||(W[h]=new Number(h)):"string"==typeof h||h instanceof String?W[h]||(W[h]=new String(h)):"boolean"==typeof h||h instanceof Boolean?W[h]||(W[h]=new Boolean(h)):h,u=f.get(e);if(u||(u=t.cloneNode(!0),f.set(e,u)),n.push(u),!a.has(e)){let n=Object.create(i);n[r.item]=s,r.index&&(n[r.index]=o),t[T]&&(n[t[T]]=u),a.set(e,n)}l.push(a.get(e))}var h;U(o.parentNode,u,n,o),u=n;for(let t=0;t<n.length;t++)q(n[t],l[t])})),!1},L[":id"]=(t,e,i)=>{let r=I(e,":id",i);g((()=>{return e=r(i),t.id=e||0===e?e:"";var e}))},L[":"]=(t,e,i)=>{let r=I(e,":",i);g((()=>(e=>{if(e)for(let i in e)k(t,i,e[i])})(r(i))))},L[":text"]=(t,e,i)=>{let r=I(e,":text",i);g((()=>{return e=r(i),void(t.textContent=null==e?"":e);var e}))},L[":value"]=(t,e,i)=>{let r=I(e,":in",i),[n,o]=(t=>["checkbox"===t.type?()=>t.checked:()=>t.value,"text"===t.type||""===t.type?e=>t.value=null==e?"":e:"checkbox"===t.type?e=>(t.value=e?"on":"",k(t,"checked",e)):"select-one"===t.type?e=>([...t.options].map((t=>t.removeAttribute("selected"))),t.value=e,t.selectedOptions[0]?.setAttribute("selected","")):e=>t.value=e])(t);g((()=>{return e=r(i),k(t,"value",e),void o(e);var e}))},L[":on"]=(t,e,i)=>{let r,n=I(e,":on",i),o=d((()=>n(i)));g(((e=o.value)=>{for(let e in r)t.removeEventListener(e,r[e]);r=e;for(let e in r)t.addEventListener(e,r[e])}))},L[":data"]=(t,e,i)=>{let r=I(e,":data",i);const n=d((()=>r(i)));g(((e=n.value)=>{for(let i in e)t.dataset[i]=e[i]}))},L[":aria"]=(t,e,i)=>{let r=I(e,":aria",i);g((()=>(e=>{for(let i in e)k(t,"aria"+i[0].toUpperCase()+i.slice(1),null==e[i]?null:e[i]+"")})(r(i))))};var F={};function I(t,e,i){if(F[t])return F[t];let r,n=/^[\n\s]*if.*\(.*\)/.test(t)||/^(let|const)\s/.test(t)?`(() => { ${t} })()`:t;try{r=new Function(`let result; with (arguments[0]) { result = (${n}) }; return result;`)}catch(r){return z(r,t,e,i)}return F[t]=n=>{let o;try{o=r(n)}catch(r){return z(r,t,e,i)}return o}}function z(t,e,i,r){Object.assign(t,{expression:e}),console.warn(`∴sprae: ${t.message}\n\n${i}=${e?`"${e}"\n\n`:""}`,r),setTimeout((()=>{throw t}),0)}var R=new WeakMap;function q(t,e){if(!t.children)return;if(R.has(t))return R.get(t);e||={};const i=A(e),r=t=>{let e,n;if(t.attributes){for(let r in L)if((n=t.attributes[r])&&(e=L[r],t.removeAttribute(r),!1===e(t,n.value,i)))return;for(let e=0;e<t.attributes.length;){let r=t.attributes[e];if(":"===r.name[0]){if(t.removeAttribute(r.name),!1===P(t,r.value,i,r.name.slice(1)))return}else e++}}for(let e of t.children)r(e)};return r(t),R.set(t,i),i}var D=q;export{D as default};
package/src/core.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import signalStruct from 'signal-struct';
2
+ import defaultDirective, { directives } from './directives.js';
2
3
 
3
4
  // sprae element: apply directives
4
5
  const memo = new WeakMap
@@ -12,27 +13,34 @@ export default function sprae(container, values) {
12
13
 
13
14
  // init directives on element
14
15
  const init = (el) => {
15
- let dir, stop
16
+ let dir, attr
17
+
16
18
  if (el.attributes) {
19
+ // directives must be initialized in order
20
+ for (let name in directives) {
21
+ if (attr = el.attributes[name]) {
22
+ dir = directives[name]
23
+ el.removeAttribute(name)
24
+ if (dir(el, attr.value, state) === false) return
25
+ }
26
+ }
27
+
17
28
  for (let i = 0; i < el.attributes.length;) {
18
29
  let attr = el.attributes[i]
19
30
  if (attr.name[0]===':') {
20
- dir = directives[attr.name] || directives.default
21
31
  el.removeAttribute(attr.name)
22
- if (stop = (dir(el, attr.value, state, attr.name.slice(1))===false)) break
32
+ if (defaultDirective(el, attr.value, state, attr.name.slice(1)) === false) return
23
33
  }
24
34
  else i++
25
35
  }
26
36
  }
27
- if (!stop) for (let child of el.children) init(child)
37
+
38
+ for (let child of el.children) init(child)
28
39
  }
40
+
29
41
  init(container)
30
42
 
31
43
  memo.set(container, state);
32
44
 
33
45
  return state;
34
46
  }
35
-
36
-
37
- // dict of directives
38
- export const directives = {}
package/src/directives.js CHANGED
@@ -1,11 +1,24 @@
1
1
  // directives & parsing
2
- import sprae, { directives } from './core.js'
2
+ import sprae from './core.js'
3
3
  import { prop, input } from 'element-props'
4
- // import { effect, computed, batch } from 'usignal'
4
+ // import { effect, computed, batch } from 'usignal/sync'
5
5
  import { effect, computed, batch } from '@preact/signals-core'
6
6
  import swap from 'swapdom'
7
7
  import p from 'primitive-pool'
8
8
 
9
+
10
+ // any-prop directives
11
+ export default (el, expr, state, name) => {
12
+ let evaluate = parseExpr(expr, ':'+name, state)
13
+ const update = value => prop(el, name, value)
14
+ effect(() => update(evaluate(state)))
15
+ }
16
+
17
+ // reserved directives - order matters!
18
+ export const directives = {}
19
+
20
+ const _each = Symbol(':each'), _ref = Symbol(':ref')
21
+
9
22
  directives[':with'] = (el, expr, rootState) => {
10
23
  let evaluate = parseExpr(expr, 'with', rootState)
11
24
 
@@ -13,7 +26,16 @@ directives[':with'] = (el, expr, rootState) => {
13
26
  // we bind updating
14
27
  const params = computed(() => Object.assign({}, rootState, evaluate(rootState)))
15
28
  let state = sprae(el, params.value)
16
- effect((values=params.value) => batch(()=>Object.assign(state, values)))
29
+ effect((values=params.value) => batch(() => Object.assign(state, values)))
30
+ return false
31
+ }
32
+
33
+ directives[':ref'] = (el, expr, state) => {
34
+ // make sure :ref is initialized after :each
35
+ if (el.hasAttribute(':each')) return el[_ref] = expr;
36
+
37
+ sprae(el, Object.assign(Object.create(state), {[expr]: el}))
38
+ return false
17
39
  }
18
40
 
19
41
  directives[':if'] = (el, expr, state) => {
@@ -38,12 +60,11 @@ directives[':if'] = (el, expr, state) => {
38
60
  el.replaceWith(cur = holder)
39
61
  let idx = computed(() => clauses.findIndex(f => f(state)))
40
62
  // NOTE: it lazily initializes elements on insertion, it's safe to sprae multiple times
41
- effect((i=idx.value) => (els[i] != cur && ((cur[_eachHolder]||cur).replaceWith(cur = els[i] || holder), sprae(cur, state))))
63
+ effect((i=idx.value) => (els[i] != cur && ((cur[_each]||cur).replaceWith(cur = els[i] || holder), sprae(cur, state))))
42
64
 
43
65
  return false
44
66
  }
45
67
 
46
- const _eachHolder = Symbol(':each')
47
68
  directives[':each'] = (tpl, expr, state) => {
48
69
  let each = parseForExpression(expr);
49
70
  if (!each) return exprError(new Error, expr);
@@ -51,14 +72,17 @@ directives[':each'] = (tpl, expr, state) => {
51
72
  const getItems = parseExpr(each.items, ':each', state);
52
73
 
53
74
  // FIXME: make sure no memory leak here
54
- // we need holder to be able :if replace it instead of tpl for combined case
55
- const holder = tpl[_eachHolder] = document.createTextNode('')
75
+ // we need :if to be able to replace holder instead of tpl for :if :each case
76
+ const holder = tpl[_each] = document.createTextNode('')
56
77
  tpl.replaceWith(holder)
57
78
 
58
79
  const items = computed(()=>{
59
80
  let list = getItems(state)
60
- if (typeof list === 'number') return Array.from({length: list}, (_, i)=>i+1)
61
- return list
81
+ if (!list) return []
82
+ if (typeof list === 'number') return Array.from({length: list}, (_, i)=>[i, i+1])
83
+ if (list.constructor === Object) return Object.entries(list)
84
+ if (Array.isArray(list)) return list.map((item,i) => [i+1, item])
85
+ exprError(Error('Bad list value'), each.items, ':each', list)
62
86
  })
63
87
 
64
88
  // stores scope per data item
@@ -67,26 +91,27 @@ directives[':each'] = (tpl, expr, state) => {
67
91
  const itemEls = new WeakMap()
68
92
  let curEls = []
69
93
  effect((list=items.value) => {
70
- if (!list) list = []
71
94
  // collect elements/scopes for items
72
95
  let newEls = [], elScopes = []
73
96
 
74
- for (let item of list) {
75
- let key = p(item)
76
- let el = itemEls.get(key)
97
+ for (let [idx, item] of list) {
98
+ let itemKey = p(item)
99
+ let el = itemEls.get(itemKey)
77
100
  if (!el) {
78
101
  el = tpl.cloneNode(true)
79
- itemEls.set(key, el)
102
+ itemEls.set(itemKey, el)
80
103
  }
81
104
  newEls.push(el)
82
105
 
83
- if (!scopes.has(key)) {
106
+ if (!scopes.has(itemKey)) {
84
107
  let scope = Object.create(state)
85
108
  scope[each.item] = item
86
- if (each.index) scope[each.index] = i;
87
- scopes.set(key, scope)
109
+ if (each.index) scope[each.index] = idx;
110
+ // provide ref, if indicated
111
+ if (tpl[_ref]) scope[tpl[_ref]] = el
112
+ scopes.set(itemKey, scope)
88
113
  }
89
- elScopes.push(scopes.get(key))
114
+ elScopes.push(scopes.get(itemKey))
90
115
  }
91
116
 
92
117
  // swap is really fast & tiny
@@ -126,39 +151,10 @@ function parseForExpression(expression) {
126
151
  return res
127
152
  }
128
153
 
129
-
130
- // common-setter directives
131
- directives['default'] = (el, expr, state, name) => {
132
- let evaluate = parseExpr(expr, ':'+name, state)
133
- const update = value => prop(el, name, value)
134
- effect(() => update(evaluate(state)))
135
- }
136
-
137
- directives[':aria'] = (el, expr, state) => {
138
- let evaluate = parseExpr(expr, ':aria', state)
139
- const update = (value) => {
140
- for (let key in value) prop(el, 'aria'+key[0].toUpperCase()+key.slice(1), value[key] == null ? null : value[key] + '');
141
- }
142
- effect(() => update(evaluate(state)))
143
- }
144
-
145
- directives[':data'] = (el, expr, state) => {
146
- let evaluate = parseExpr(expr, ':data', state)
147
- const value = computed(() => evaluate(state))
148
- effect((v=value.value) => {
149
- for (let key in v) el.dataset[key] = v[key];
150
- })
151
- }
152
-
153
- directives[':on'] = (el, expr, state) => {
154
- let evaluate = parseExpr(expr, ':on', state)
155
- let listeners = computed(() => evaluate(state))
156
- let prevListeners
157
- effect((values=listeners.value) => {
158
- for (let evt in prevListeners) el.removeEventListener(evt, prevListeners[evt]);
159
- prevListeners = values;
160
- for (let evt in prevListeners) el.addEventListener(evt, prevListeners[evt]);
161
- })
154
+ directives[':id'] = (el, expr, state) => {
155
+ let evaluate = parseExpr(expr, ':id', state)
156
+ const update = v => el.id = v || v === 0 ? v : ''
157
+ effect(()=>update(evaluate(state)))
162
158
  }
163
159
 
164
160
  directives[':'] = (el, expr, state) => {
@@ -193,6 +189,34 @@ directives[':value'] = (el, expr, state) => {
193
189
  effect(()=>update(evaluate(state)))
194
190
  }
195
191
 
192
+ directives[':on'] = (el, expr, state) => {
193
+ let evaluate = parseExpr(expr, ':on', state)
194
+ let listeners = computed(() => evaluate(state))
195
+ let prevListeners
196
+ effect((values=listeners.value) => {
197
+ for (let evt in prevListeners) el.removeEventListener(evt, prevListeners[evt]);
198
+ prevListeners = values;
199
+ for (let evt in prevListeners) el.addEventListener(evt, prevListeners[evt]);
200
+ })
201
+ }
202
+
203
+ directives[':data'] = (el, expr, state) => {
204
+ let evaluate = parseExpr(expr, ':data', state)
205
+ const value = computed(() => evaluate(state))
206
+ effect((v=value.value) => {
207
+ for (let key in v) el.dataset[key] = v[key];
208
+ })
209
+ }
210
+
211
+ directives[':aria'] = (el, expr, state) => {
212
+ let evaluate = parseExpr(expr, ':aria', state)
213
+ const update = (value) => {
214
+ for (let key in value) prop(el, 'aria'+key[0].toUpperCase()+key.slice(1), value[key] == null ? null : value[key] + '');
215
+ }
216
+ effect(() => update(evaluate(state)))
217
+ }
218
+
219
+
196
220
  let evaluatorMemo = {}
197
221
 
198
222
  // borrowed from alpine: https://github.com/alpinejs/alpine/blob/main/packages/alpinejs/src/evaluator.js#L61
@@ -214,7 +238,7 @@ function parseExpr(expression, dir, scope) {
214
238
  // guard static-time eval errors
215
239
  let evaluate
216
240
  try {
217
- evaluate = new Function(['scope'], `let result; with (scope) { result = ${rightSideSafeExpression} }; return result;`)
241
+ evaluate = new Function( `let result; with (arguments[0]) { result = (${rightSideSafeExpression}) }; return result;`)
218
242
  } catch ( e ) {
219
243
  return exprError(e, expression, dir, scope)
220
244
  }
package/src/index.js CHANGED
@@ -1,8 +1,6 @@
1
1
  import sprae from './core.js';
2
2
  import './directives.js';
3
-
4
3
  export default sprae;
5
- export * from './core.js';
6
4
 
7
5
  // autoinit
8
6
  // NOTE: abandoning for now, since requires a separate non-module JS entry, until use-case appears
package/test/index.html CHANGED
@@ -19,7 +19,7 @@
19
19
  "preact": "../node_modules/preact/dist/preact.mjs",
20
20
  "preact/hooks": "../node_modules/preact/hooks/dist/hooks.mjs",
21
21
  "@preact/signals-core": "../node_modules/@preact/signals-core/dist/signals-core.mjs",
22
- "usignal": "../node_modules/usignal/esm/sync.js"
22
+ "usignal/sync": "../node_modules/usignal/esm/sync.js"
23
23
  }
24
24
  }
25
25
  </script>
package/test/test.js CHANGED
@@ -1,4 +1,4 @@
1
- // import { signal } from 'usignal'
1
+ // import { signal } from 'usignal/sync'
2
2
  import { signal } from '@preact/signals-core'
3
3
  import test, {is, any, throws} from 'tst'
4
4
  import {tick, time} from 'wait-please'
@@ -63,7 +63,7 @@ test('common: class', async () => {
63
63
  is(el.outerHTML, `<x class="x"></x><y class="y w"></y><z class="b c"></z>`);
64
64
  })
65
65
 
66
- test('spread props: base', async () => {
66
+ test('spraed props: base', async () => {
67
67
  let el = h`<input :id="0" :="{for:1, title:2, help:3, type:4, placeholder: 5, value: 6}" :value="7"/>`
68
68
  let params = sprae(el)
69
69
  is(el.outerHTML, `<input id="0" for="1" title="2" help="3" type="4" placeholder="5" value="7">`)
@@ -171,7 +171,7 @@ test('conditions: reactive values', async () => {
171
171
  })
172
172
 
173
173
 
174
- test('each: base', async () => {
174
+ test('each: array', async () => {
175
175
  // FIXME: in some conspicuous reason jsdom fails to update text nodes somehow
176
176
  let el = h`<p>
177
177
  <span :each="a in b" :text="a"></span>
@@ -189,6 +189,24 @@ test('each: base', async () => {
189
189
  is(el.innerHTML, '')
190
190
  })
191
191
 
192
+ test('each: object', async () => {
193
+ // FIXME: in some conspicuous reason jsdom fails to update text nodes somehow
194
+ let el = h`<p>
195
+ <span :each="x,key in b" :text="[key,x]"></span>
196
+ </p>`
197
+
198
+ const params = sprae(el, { b: null })
199
+
200
+ is(el.innerHTML, '')
201
+ console.log('set 1,2')
202
+ params.b = { x:1, y:2 }
203
+ is(el.innerHTML, '<span>x,1</span><span>y,2</span>')
204
+ params.b = []
205
+ is(el.innerHTML, '')
206
+ params.b = null
207
+ is(el.innerHTML, '')
208
+ })
209
+
192
210
  test('each: loop within loop', async () => {
193
211
  let el = h`<p>
194
212
  <x :each="b in c"><y :each="a in b" :text="a"></y></x>
@@ -197,7 +215,6 @@ test('each: loop within loop', async () => {
197
215
  const params = sprae(el, { c: [[1,2], [3,4]] })
198
216
 
199
217
  is(el.innerHTML, '<x><y>1</y><y>2</y></x><x><y>3</y><y>4</y></x>')
200
- // console.log('set 1,2')
201
218
  params.c = [[5,6], [3,4]]
202
219
  is(el.innerHTML, '<x><y>5</y><y>6</y></x><x><y>3</y><y>4</y></x>')
203
220
  // params.c[1] = [7,8]
@@ -228,6 +245,9 @@ test('each: reactive values', async () => {
228
245
  })
229
246
 
230
247
  test('each: loop with condition', async () => {
248
+ // NOTE: there doesn't seem to be much value in exactly that
249
+ // also it creates confusion with :else directive
250
+ // prohibitin that allows in-order directives init
231
251
  let el = h`<p>
232
252
  <span :each="a in b" :text="a" :if="c"></span>
233
253
  </p>`
@@ -368,7 +388,23 @@ test('with: writes to state', () => {
368
388
  is(a.innerHTML, `<y>3</y>`)
369
389
  })
370
390
 
371
- test('reactives', async () => {
391
+ test('ref: base', () => {
392
+ let a = h`<a :ref="a" :init="log.push(a), null" :text="b"></a>`
393
+ let state = sprae(a, {log:[], b:1})
394
+ is(state.log[0], a)
395
+ is(a.outerHTML, `<a>1</a>`)
396
+ state.b = 2
397
+ is(a.outerHTML, `<a>2</a>`)
398
+ })
399
+
400
+ test('ref with each', () => {
401
+ let a = h`<y><x :ref="x" :each="item in items" :text="log.push(x), item"/></y>`
402
+ let state = sprae(a, {log: [], items: [1,2]})
403
+ is(a.innerHTML, `<x>1</x><x>2</x>`)
404
+ is(state.log, [...a.children])
405
+ })
406
+
407
+ test('reactive values', async () => {
372
408
  let a = new Promise((ok) => setTimeout(() => ok(2), 10))
373
409
 
374
410
  let el = h`<x :text="a">1</x>`
@@ -377,4 +413,10 @@ test('reactives', async () => {
377
413
 
378
414
  await time(20)
379
415
  is(el.outerHTML, `<x>2</x>`)
416
+ })
417
+
418
+ test('scope directives must come first', async () => {
419
+ let a = h`<x :text="y" :with="{y:1}" :ref="x"></x>`
420
+ sprae(a, {})
421
+ is(a.outerHTML, `<x>1</x>`)
380
422
  })
@@ -1,53 +0,0 @@
1
- import sprae, { directive, exprError, parseExpr } from '../core.js'
2
-
3
- directive(':each', (el, expr) => {
4
- let each = parseForExpression(expr);
5
- if (!each) return exprError(new Error, expr);
6
-
7
- const getItems = parseExpr(each.items);
8
-
9
- const holder = new Text
10
- el.replaceWith(holder)
11
-
12
- // FIXME: make sure no memory leak here
13
- // FIXME: there can DOM swapper be used instead
14
- let els = [];
15
- return state => {
16
- els.forEach(el => el.remove()); els = [];
17
- let items = getItems(state);
18
- if (typeof items === 'number') items = Array.from({length: items}, (item, i)=>i+1)
19
- items?.forEach((item,i) => {
20
- const scope = {...state};
21
- scope[each.item] = item;
22
- if (each.index) scope[each.index] = i;
23
- let itemEl = el.cloneNode(true);
24
- els.push(itemEl);
25
- holder.before(itemEl);
26
- sprae(itemEl, scope);
27
- });
28
- }
29
- })
30
-
31
- // This was taken AlpineJS, former VueJS 2.* core. Thanks Alpine & Vue!
32
- function parseForExpression(expression) {
33
- let forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/
34
- let stripParensRE = /^\s*\(|\)\s*$/g
35
- let forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/
36
- let inMatch = expression.match(forAliasRE)
37
-
38
- if (!inMatch) return
39
-
40
- let res = {}
41
- res.items = inMatch[2].trim()
42
- let item = inMatch[1].replace(stripParensRE, '').trim()
43
- let iteratorMatch = item.match(forIteratorRE)
44
-
45
- if (iteratorMatch) {
46
- res.item = item.replace(forIteratorRE, '').trim()
47
- res.index = iteratorMatch[1].trim()
48
- } else {
49
- res.item = item
50
- }
51
-
52
- return res
53
- }