diff --git a/dist/sigpro.esm.js b/dist/sigpro.esm.js index b9b6cad..a228be7 100644 --- a/dist/sigpro.esm.js +++ b/dist/sigpro.esm.js @@ -15,10 +15,6 @@ var MOUNTED_NODES = new WeakMap; var SVG_NS = "http://www.w3.org/2000/svg"; var XLINK_NS = "http://www.w3.org/1999/xlink"; var SVG_TAGS = new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(",")); -var attrFilter = null; -var filterXSS = (fn) => { - attrFilter = fn; -}; var dispose = (eff) => { if (!eff || eff._disposed) return; @@ -247,6 +243,21 @@ var cleanupNode = (node) => { if (node.childNodes) node.childNodes.forEach((n) => cleanupNode(n)); }; +var DANGEROUS_PROTOCOL = /^\s*(javascript|data|vbscript):/i; +var DANGEROUS_URI_ATTRS = new Set(["src", "href", "formaction", "action", "background", "code", "archive"]); +var isDangerousAttr = (key) => DANGEROUS_URI_ATTRS.has(key) || key.startsWith("on"); +var validateAttr = (key, val) => { + if (val == null || val === false) + return null; + if (isDangerousAttr(key)) { + const sVal = String(val); + if (DANGEROUS_PROTOCOL.test(sVal)) { + console.warn(`[SigPro] Bloqueado protocolo peligroso en ${key}`); + return "#"; + } + } + return val; +}; var h = (tag, props = {}, children = []) => { if (props instanceof Node || isArr(props) || !isObj(props)) { children = props; @@ -285,38 +296,38 @@ var h = (tag, props = {}, children = []) => { isFunc(v) ? v(el) : v.current = el; continue; } - let val = attrFilter ? attrFilter(k, v) : v; if (isSVG && k.startsWith("xlink:")) { - val == null ? el.removeAttributeNS(XLINK_NS, k.slice(6)) : el.setAttributeNS(XLINK_NS, k.slice(6), val); + const cleanVal = validateAttr(k.slice(6), v); + cleanVal == null ? el.removeAttributeNS(XLINK_NS, k.slice(6)) : el.setAttributeNS(XLINK_NS, k.slice(6), cleanVal); continue; } if (k.startsWith("on")) { const ev = k.slice(2).toLowerCase(); - el.addEventListener(ev, val); - const off = () => el.removeEventListener(ev, val); + el.addEventListener(ev, v); + const off = () => el.removeEventListener(ev, v); el._cleanups.add(off); onUnmount(off); - } else if (isFunc(val)) { + } else if (isFunc(v)) { const effect = createEffect(() => { - const raw = val(); - const safeVal = attrFilter ? attrFilter(k, raw) : raw; + const val = validateAttr(k, v()); if (k === "class") - el.className = safeVal || ""; - else if (safeVal == null) + el.className = val || ""; + else if (val == null) el.removeAttribute(k); else if (k in el && !isSVG) - el[k] = safeVal; + el[k] = val; else - el.setAttribute(k, safeVal === true ? "" : safeVal); + el.setAttribute(k, val === true ? "" : val); }); effect(); el._cleanups.add(() => dispose(effect)); onUnmount(() => dispose(effect)); if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) && (k === "value" || k === "checked")) { const evType = k === "checked" ? "change" : "input"; - el.addEventListener(evType, (ev) => val(ev.target[k])); + el.addEventListener(evType, (ev) => v(ev.target[k])); } } else { + const val = validateAttr(k, v); if (val != null) { if (k in el && !isSVG) el[k] = val; @@ -498,13 +509,23 @@ var mount = (comp, target) => { MOUNTED_NODES.set(t, inst); return inst; }; +var sigpro = () => { + if (typeof window === "undefined") + return; + Object.assign(window, { $, $$, watch, h, when, each, router, mount, batch }); + "a abbr article aside ... video".split(" ").forEach((tag) => { + window[tag] = (props, children) => h(tag, props, children); + }); +}; +if (typeof import.meta === "undefined" && typeof window !== "undefined") + sigpro(); export { when, watch, + sigpro, router, mount, h, - filterXSS, each, batch, $$, diff --git a/dist/sigpro.esm.min.js b/dist/sigpro.esm.min.js index 8f6235c..34aa4ae 100644 --- a/dist/sigpro.esm.min.js +++ b/dist/sigpro.esm.min.js @@ -1 +1 @@ -var m=(e)=>typeof e==="function",j=(e)=>e&&typeof e==="object",N=Array.isArray,E=typeof document<"u"?document:null,V=(e)=>e?._isRuntime?e.container:e instanceof Node?e:E.createTextNode(e==null?"":String(e)),d=null,_=null,b=!1,C=0,R=new Set,I=new WeakMap,O=Symbol("iter"),L=new WeakMap,K="http://www.w3.org/2000/svg",P="http://www.w3.org/1999/xlink",W=new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(",")),v=null,q=(e)=>{v=e},S=(e)=>{if(!e||e._disposed)return;e._disposed=!0;let r=[e];while(r.length){let n=r.pop();if(n._cleanups)n._cleanups.forEach((o)=>o()),n._cleanups.clear();if(n._children)n._children.forEach((o)=>r.push(o)),n._children.clear();if(n._deps)n._deps.forEach((o)=>o.delete(n)),n._deps.clear()}},g=(e)=>{if(_)(_._cleanups||=new Set).add(e)},D=(e)=>{let r=d;d=null;try{return e()}finally{d=r}},x=(e,r=!1)=>{let n=()=>{if(n._disposed)return;if(n._deps)n._deps.forEach((c)=>c.delete(n));if(n._cleanups)n._cleanups.forEach((c)=>c()),n._cleanups.clear();let o=d,s=_;d=_=n;try{return n._result=e()}catch(c){console.error("[SigPro]",c)}finally{d=o,_=s}};if(n._deps=n._cleanups=n._children=null,n._disposed=!1,n._isComputed=r,n._depth=d?d._depth+1:0,n._mounts=[],n._parent=_,_)(_._children||=new Set).add(n);return n},$=()=>{if(b)return;b=!0;let e=Array.from(R).sort((r,n)=>r._depth-n._depth);R.clear();for(let r of e)if(!r._disposed)r();b=!1},z=(e)=>{C++;try{return e()}finally{if(C--,C===0&&R.size>0&&!b)$()}},w=(e,r=!1)=>{if(!r&&d&&!d._disposed)e.add(d),(d._deps||=new Set).add(e);else if(r&&e.size>0){let n=!1;for(let o of e){if(o===d||o._disposed)continue;if(o._isComputed){if(o._dirty=!0,o._subs)w(o._subs,!0)}else R.add(o),n=!0}if(n&&!b&&C===0)queueMicrotask($)}},U=(e,r=null)=>{let n=new Set;if(m(e)){let o,s=()=>{if(s._dirty){let c=d;d=s;try{let t=e();if(!Object.is(o,t))o=t,w(n,!0)}finally{d=c}s._dirty=!1}return w(n),o};return s._isComputed=!0,s._subs=n,s._dirty=!0,s._deps=null,s._disposed=!1,s}if(r)try{e=JSON.parse(localStorage.getItem(r))??e}catch(o){}return(...o)=>{if(o.length){let s=m(o[0])?o[0](e):o[0];if(!Object.is(e,s)){if(e=s,r)localStorage.setItem(r,JSON.stringify(e));w(n,!0)}}return w(n),e}},X=(e)=>{if(!j(e))return e;let r=I.get(e);if(r)return r;let n=new Map,o=(c)=>{let t=n.get(c);if(!t)n.set(c,t=new Set);return t},s=new Proxy(e,{get(c,t,i){if(typeof t!=="symbol")w(o(t));return X(Reflect.get(c,t,i))},set(c,t,i,l){let u=Reflect.has(c,t),a=Reflect.get(c,t,l),f=Reflect.set(c,t,i,l);if(f&&!Object.is(a,i)){if(w(o(t),!0),!u)w(o(O),!0)}return f},deleteProperty(c,t){let i=Reflect.deleteProperty(c,t);if(i)w(o(t),!0),w(o(O),!0);return i},ownKeys(c){return w(o(O)),Reflect.ownKeys(c)}});return I.set(e,s),s},k=(e,r)=>{if(r===void 0){let o=x(e);return o(),()=>S(o)}let n=x(()=>{let o=Array.isArray(e)?e.map((s)=>s()):e();D(()=>r(o))});return n(),()=>S(n)},B=(e)=>{if(!e)return;if(e._cleanups)e._cleanups.forEach((r)=>r()),e._cleanups.clear();if(e._ownerEffect)S(e._ownerEffect);if(e.childNodes)e.childNodes.forEach((r)=>B(r))},M=(e,r={},n=[])=>{if(r instanceof Node||N(r)||!j(r))n=r,r={};if(m(e)){let t=x(()=>{let a=e(r,{children:n,emit:(f,...h)=>r[`on${f[0].toUpperCase()}${f.slice(1)}`]?.(...h)});return t._result=a,a});t();let i=t._result;if(i==null)return null;let l=i instanceof Node||N(i)&&i.every((a)=>a instanceof Node)?i:E.createTextNode(String(i)),u=(a)=>{if(j(a)&&!a._isRuntime)a._mounts=t._mounts||[],a._cleanups=t._cleanups||new Set,a._ownerEffect=t};return N(l)?l.forEach(u):u(l),l}let o=W.has(e),s=o?E.createElementNS(K,e):E.createElement(e);s._cleanups=new Set;for(let t of Object.keys(r)){let i=r[t];if(t==="ref"){m(i)?i(s):i.current=s;continue}let l=v?v(t,i):i;if(o&&t.startsWith("xlink:")){l==null?s.removeAttributeNS(P,t.slice(6)):s.setAttributeNS(P,t.slice(6),l);continue}if(t.startsWith("on")){let u=t.slice(2).toLowerCase();s.addEventListener(u,l);let a=()=>s.removeEventListener(u,l);s._cleanups.add(a),g(a)}else if(m(l)){let u=x(()=>{let a=l(),f=v?v(t,a):a;if(t==="class")s.className=f||"";else if(f==null)s.removeAttribute(t);else if(t in s&&!o)s[t]=f;else s.setAttribute(t,f===!0?"":f)});if(u(),s._cleanups.add(()=>S(u)),g(()=>S(u)),/^(INPUT|TEXTAREA|SELECT)$/.test(s.tagName)&&(t==="value"||t==="checked")){let a=t==="checked"?"change":"input";s.addEventListener(a,(f)=>l(f.target[t]))}}else if(l!=null)if(t in s&&!o)s[t]=l;else s.setAttribute(t,l===!0?"":l)}let c=(t)=>{if(N(t))return t.forEach(c);if(m(t)){let i=E.createTextNode("");s.appendChild(i);let l=[],u=x(()=>{let a=t(),f=(N(a)?a:[a]).map(V);l.forEach((p)=>{if(p._isRuntime)p.destroy();else B(p);if(p.parentNode)p.remove()});let h=i;for(let p=f.length-1;p>=0;p--){let y=f[p];if(y.parentNode!==h.parentNode)h.parentNode?.insertBefore(y,h);if(y._mounts)y._mounts.forEach((G)=>G());h=y}l=f});u(),s._cleanups.add(()=>S(u)),g(()=>S(u))}else{let i=V(t);if(s.appendChild(i),i._mounts)i._mounts.forEach((l)=>l())}};return c(n),s},T=(e)=>{let r=new Set,n=_,o=d,s=E.createElement("div");s.style.display="contents",s.setAttribute("role","presentation"),_={_cleanups:r},d=null;let c=(t)=>{if(!t)return;if(t._isRuntime)r.add(t.destroy),s.appendChild(t.container);else if(N(t))t.forEach(c);else s.appendChild(t instanceof Node?t:E.createTextNode(String(t==null?"":t)))};try{c(e({onCleanup:(t)=>r.add(t)}))}finally{_=n,d=o}return{_isRuntime:!0,container:s,destroy:()=>{r.forEach((t)=>t()),B(s),s.remove()}}},F=(e,r,n=null)=>{let o=E.createTextNode(""),s=M("div",{style:"display:contents"},[o]),c=null;return k(()=>!!(m(e)?e():e),(t)=>{if(c)c.destroy(),c=null;let i=t?r:n;if(i)c=T(()=>m(i)?i():i),s.insertBefore(c.container,o)}),g(()=>c?.destroy()),s},J=(e,r,n)=>{let o=E.createTextNode(""),s=M("div",{style:"display:contents"},[o]),c=new Map;return k(()=>(m(e)?e():e)||[],(t)=>{let i=new Map,l=[],u=t||[];for(let f=0;fr(h,f));else c.delete(p);i.set(p,y),l.push(y)}c.forEach((f)=>f.destroy());let a=o;for(let f=l.length-1;f>=0;f--){let p=l[f].container;if(p.nextSibling!==a)s.insertBefore(p,a);a=p}c=i}),s},A=(e)=>{let r=()=>window.location.hash.slice(1)||"/",n=U(r()),o=()=>n(r());window.addEventListener("hashchange",o),g(()=>window.removeEventListener("hashchange",o));let s=M("div",{class:"router-hook"}),c=null;return k([n],()=>{let t=n(),i=e.find((l)=>{let u=l.path.split("/").filter(Boolean),a=t.split("/").filter(Boolean);return u.length===a.length&&u.every((f,h)=>f[0]===":"||f===a[h])})||e.find((l)=>l.path==="*");if(i){c?.destroy();let l={};i.path.split("/").filter(Boolean).forEach((u,a)=>{if(u[0]===":")l[u.slice(1)]=t.split("/").filter(Boolean)[a]}),A.params(l),c=T(()=>m(i.component)?i.component(l):i.component),s.replaceChildren(c.container)}}),s};A.params=U({});A.to=(e)=>window.location.hash=e.replace(/^#?\/?/,"#/");A.back=()=>window.history.back();A.path=()=>window.location.hash.replace(/^#/,"")||"/";var Q=(e,r)=>{let n=typeof r==="string"?E.querySelector(r):r;if(!n)return;if(L.has(n))L.get(n).destroy();let o=T(m(e)?e:()=>e);return n.replaceChildren(o.container),L.set(n,o),o};export{F as when,k as watch,A as router,Q as mount,M as h,q as filterXSS,J as each,z as batch,X as $$,U as $}; +var m=(e)=>typeof e==="function",P=(e)=>e&&typeof e==="object",N=Array.isArray,E=typeof document<"u"?document:null,I=(e)=>e?._isRuntime?e.container:e instanceof Node?e:E.createTextNode(e==null?"":String(e)),d=null,_=null,g=!1,R=0,O=new Set,M=new WeakMap,j=Symbol("iter"),L=new WeakMap,W="http://www.w3.org/2000/svg",$="http://www.w3.org/1999/xlink",K=new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(",")),S=(e)=>{if(!e||e._disposed)return;e._disposed=!0;let s=[e];while(s.length){let n=s.pop();if(n._cleanups)n._cleanups.forEach((r)=>r()),n._cleanups.clear();if(n._children)n._children.forEach((r)=>s.push(r)),n._children.clear();if(n._deps)n._deps.forEach((r)=>r.delete(n)),n._deps.clear()}},b=(e)=>{if(_)(_._cleanups||=new Set).add(e)},q=(e)=>{let s=d;d=null;try{return e()}finally{d=s}},x=(e,s=!1)=>{let n=()=>{if(n._disposed)return;if(n._deps)n._deps.forEach((i)=>i.delete(n));if(n._cleanups)n._cleanups.forEach((i)=>i()),n._cleanups.clear();let r=d,o=_;d=_=n;try{return n._result=e()}catch(i){console.error("[SigPro]",i)}finally{d=r,_=o}};if(n._deps=n._cleanups=n._children=null,n._disposed=!1,n._isComputed=s,n._depth=d?d._depth+1:0,n._mounts=[],n._parent=_,_)(_._children||=new Set).add(n);return n},k=()=>{if(g)return;g=!0;let e=Array.from(O).sort((s,n)=>s._depth-n._depth);O.clear();for(let s of e)if(!s._disposed)s();g=!1},z=(e)=>{R++;try{return e()}finally{if(R--,R===0&&O.size>0&&!g)k()}},w=(e,s=!1)=>{if(!s&&d&&!d._disposed)e.add(d),(d._deps||=new Set).add(e);else if(s&&e.size>0){let n=!1;for(let r of e){if(r===d||r._disposed)continue;if(r._isComputed){if(r._dirty=!0,r._subs)w(r._subs,!0)}else O.add(r),n=!0}if(n&&!g&&R===0)queueMicrotask(k)}},U=(e,s=null)=>{let n=new Set;if(m(e)){let r,o=()=>{if(o._dirty){let i=d;d=o;try{let t=e();if(!Object.is(r,t))r=t,w(n,!0)}finally{d=i}o._dirty=!1}return w(n),r};return o._isComputed=!0,o._subs=n,o._dirty=!0,o._deps=null,o._disposed=!1,o}if(s)try{e=JSON.parse(localStorage.getItem(s))??e}catch(r){}return(...r)=>{if(r.length){let o=m(r[0])?r[0](e):r[0];if(!Object.is(e,o)){if(e=o,s)localStorage.setItem(s,JSON.stringify(e));w(n,!0)}}return w(n),e}},D=(e)=>{if(!P(e))return e;let s=M.get(e);if(s)return s;let n=new Map,r=(i)=>{let t=n.get(i);if(!t)n.set(i,t=new Set);return t},o=new Proxy(e,{get(i,t,c){if(typeof t!=="symbol")w(r(t));return D(Reflect.get(i,t,c))},set(i,t,c,l){let a=Reflect.has(i,t),f=Reflect.get(i,t,l),u=Reflect.set(i,t,c,l);if(u&&!Object.is(f,c)){if(w(r(t),!0),!a)w(r(j),!0)}return u},deleteProperty(i,t){let c=Reflect.deleteProperty(i,t);if(c)w(r(t),!0),w(r(j),!0);return c},ownKeys(i){return w(r(j)),Reflect.ownKeys(i)}});return M.set(e,o),o},T=(e,s)=>{if(s===void 0){let r=x(e);return r(),()=>S(r)}let n=x(()=>{let r=Array.isArray(e)?e.map((o)=>o()):e();q(()=>s(r))});return n(),()=>S(n)},V=(e)=>{if(!e)return;if(e._cleanups)e._cleanups.forEach((s)=>s()),e._cleanups.clear();if(e._ownerEffect)S(e._ownerEffect);if(e.childNodes)e.childNodes.forEach((s)=>V(s))},J=/^\s*(javascript|data|vbscript):/i,Q=new Set(["src","href","formaction","action","background","code","archive"]),X=(e)=>Q.has(e)||e.startsWith("on"),B=(e,s)=>{if(s==null||s===!1)return null;if(X(e)){let n=String(s);if(J.test(n))return console.warn(`[SigPro] Bloqueado protocolo peligroso en ${e}`),"#"}return s},A=(e,s={},n=[])=>{if(s instanceof Node||N(s)||!P(s))n=s,s={};if(m(e)){let t=x(()=>{let f=e(s,{children:n,emit:(u,...h)=>s[`on${u[0].toUpperCase()}${u.slice(1)}`]?.(...h)});return t._result=f,f});t();let c=t._result;if(c==null)return null;let l=c instanceof Node||N(c)&&c.every((f)=>f instanceof Node)?c:E.createTextNode(String(c)),a=(f)=>{if(P(f)&&!f._isRuntime)f._mounts=t._mounts||[],f._cleanups=t._cleanups||new Set,f._ownerEffect=t};return N(l)?l.forEach(a):a(l),l}let r=K.has(e),o=r?E.createElementNS(W,e):E.createElement(e);o._cleanups=new Set;for(let t of Object.keys(s)){let c=s[t];if(t==="ref"){m(c)?c(o):c.current=o;continue}if(r&&t.startsWith("xlink:")){let l=B(t.slice(6),c);l==null?o.removeAttributeNS($,t.slice(6)):o.setAttributeNS($,t.slice(6),l);continue}if(t.startsWith("on")){let l=t.slice(2).toLowerCase();o.addEventListener(l,c);let a=()=>o.removeEventListener(l,c);o._cleanups.add(a),b(a)}else if(m(c)){let l=x(()=>{let a=B(t,c());if(t==="class")o.className=a||"";else if(a==null)o.removeAttribute(t);else if(t in o&&!r)o[t]=a;else o.setAttribute(t,a===!0?"":a)});if(l(),o._cleanups.add(()=>S(l)),b(()=>S(l)),/^(INPUT|TEXTAREA|SELECT)$/.test(o.tagName)&&(t==="value"||t==="checked")){let a=t==="checked"?"change":"input";o.addEventListener(a,(f)=>c(f.target[t]))}}else{let l=B(t,c);if(l!=null)if(t in o&&!r)o[t]=l;else o.setAttribute(t,l===!0?"":l)}}let i=(t)=>{if(N(t))return t.forEach(i);if(m(t)){let c=E.createTextNode("");o.appendChild(c);let l=[],a=x(()=>{let f=t(),u=(N(f)?f:[f]).map(I);l.forEach((p)=>{if(p._isRuntime)p.destroy();else V(p);if(p.parentNode)p.remove()});let h=c;for(let p=u.length-1;p>=0;p--){let y=u[p];if(y.parentNode!==h.parentNode)h.parentNode?.insertBefore(y,h);if(y._mounts)y._mounts.forEach((G)=>G());h=y}l=u});a(),o._cleanups.add(()=>S(a)),b(()=>S(a))}else{let c=I(t);if(o.appendChild(c),c._mounts)c._mounts.forEach((l)=>l())}};return i(n),o},C=(e)=>{let s=new Set,n=_,r=d,o=E.createElement("div");o.style.display="contents",o.setAttribute("role","presentation"),_={_cleanups:s},d=null;let i=(t)=>{if(!t)return;if(t._isRuntime)s.add(t.destroy),o.appendChild(t.container);else if(N(t))t.forEach(i);else o.appendChild(t instanceof Node?t:E.createTextNode(String(t==null?"":t)))};try{i(e({onCleanup:(t)=>s.add(t)}))}finally{_=n,d=r}return{_isRuntime:!0,container:o,destroy:()=>{s.forEach((t)=>t()),V(o),o.remove()}}},F=(e,s,n=null)=>{let r=E.createTextNode(""),o=A("div",{style:"display:contents"},[r]),i=null;return T(()=>!!(m(e)?e():e),(t)=>{if(i)i.destroy(),i=null;let c=t?s:n;if(c)i=C(()=>m(c)?c():c),o.insertBefore(i.container,r)}),b(()=>i?.destroy()),o},H=(e,s,n)=>{let r=E.createTextNode(""),o=A("div",{style:"display:contents"},[r]),i=new Map;return T(()=>(m(e)?e():e)||[],(t)=>{let c=new Map,l=[],a=t||[];for(let u=0;us(h,u));else i.delete(p);c.set(p,y),l.push(y)}i.forEach((u)=>u.destroy());let f=r;for(let u=l.length-1;u>=0;u--){let p=l[u].container;if(p.nextSibling!==f)o.insertBefore(p,f);f=p}i=c}),o},v=(e)=>{let s=()=>window.location.hash.slice(1)||"/",n=U(s()),r=()=>n(s());window.addEventListener("hashchange",r),b(()=>window.removeEventListener("hashchange",r));let o=A("div",{class:"router-hook"}),i=null;return T([n],()=>{let t=n(),c=e.find((l)=>{let a=l.path.split("/").filter(Boolean),f=t.split("/").filter(Boolean);return a.length===f.length&&a.every((u,h)=>u[0]===":"||u===f[h])})||e.find((l)=>l.path==="*");if(c){i?.destroy();let l={};c.path.split("/").filter(Boolean).forEach((a,f)=>{if(a[0]===":")l[a.slice(1)]=t.split("/").filter(Boolean)[f]}),v.params(l),i=C(()=>m(c.component)?c.component(l):c.component),o.replaceChildren(i.container)}}),o};v.params=U({});v.to=(e)=>window.location.hash=e.replace(/^#?\/?/,"#/");v.back=()=>window.history.back();v.path=()=>window.location.hash.replace(/^#/,"")||"/";var Y=(e,s)=>{let n=typeof s==="string"?E.querySelector(s):s;if(!n)return;if(L.has(n))L.get(n).destroy();let r=C(m(e)?e:()=>e);return n.replaceChildren(r.container),L.set(n,r),r},Z=()=>{if(typeof window>"u")return;Object.assign(window,{$:U,$$:D,watch:T,h:A,when:F,each:H,router:v,mount:Y,batch:z}),"a abbr article aside ... video".split(" ").forEach((e)=>{window[e]=(s,n)=>A(e,s,n)})};if(typeof import.meta>"u"&&typeof window<"u")Z();export{F as when,T as watch,Z as sigpro,v as router,Y as mount,A as h,H as each,z as batch,D as $$,U as $}; diff --git a/dist/sigpro.js b/dist/sigpro.js index bf76c8b..7db958c 100644 --- a/dist/sigpro.js +++ b/dist/sigpro.js @@ -37,15 +37,15 @@ }); }; - // sigpro-full.js - var exports_sigpro_full = {}; - __export(exports_sigpro_full, { + // index.js + var exports_sigpro = {}; + __export(exports_sigpro, { when: () => when, watch: () => watch, + sigpro: () => sigpro, router: () => router, mount: () => mount, h: () => h, - filterXSS: () => filterXSS, each: () => each, batch: () => batch, $$: () => $$, @@ -69,10 +69,6 @@ var SVG_NS = "http://www.w3.org/2000/svg"; var XLINK_NS = "http://www.w3.org/1999/xlink"; var SVG_TAGS = new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(",")); - var attrFilter = null; - var filterXSS = (fn) => { - attrFilter = fn; - }; var dispose = (eff) => { if (!eff || eff._disposed) return; @@ -301,6 +297,21 @@ if (node.childNodes) node.childNodes.forEach((n) => cleanupNode(n)); }; + var DANGEROUS_PROTOCOL = /^\s*(javascript|data|vbscript):/i; + var DANGEROUS_URI_ATTRS = new Set(["src", "href", "formaction", "action", "background", "code", "archive"]); + var isDangerousAttr = (key) => DANGEROUS_URI_ATTRS.has(key) || key.startsWith("on"); + var validateAttr = (key, val) => { + if (val == null || val === false) + return null; + if (isDangerousAttr(key)) { + const sVal = String(val); + if (DANGEROUS_PROTOCOL.test(sVal)) { + console.warn(`[SigPro] Bloqueado protocolo peligroso en ${key}`); + return "#"; + } + } + return val; + }; var h = (tag, props = {}, children = []) => { if (props instanceof Node || isArr(props) || !isObj(props)) { children = props; @@ -339,38 +350,38 @@ isFunc(v) ? v(el) : v.current = el; continue; } - let val = attrFilter ? attrFilter(k, v) : v; if (isSVG && k.startsWith("xlink:")) { - val == null ? el.removeAttributeNS(XLINK_NS, k.slice(6)) : el.setAttributeNS(XLINK_NS, k.slice(6), val); + const cleanVal = validateAttr(k.slice(6), v); + cleanVal == null ? el.removeAttributeNS(XLINK_NS, k.slice(6)) : el.setAttributeNS(XLINK_NS, k.slice(6), cleanVal); continue; } if (k.startsWith("on")) { const ev = k.slice(2).toLowerCase(); - el.addEventListener(ev, val); - const off = () => el.removeEventListener(ev, val); + el.addEventListener(ev, v); + const off = () => el.removeEventListener(ev, v); el._cleanups.add(off); onUnmount(off); - } else if (isFunc(val)) { + } else if (isFunc(v)) { const effect = createEffect(() => { - const raw = val(); - const safeVal = attrFilter ? attrFilter(k, raw) : raw; + const val = validateAttr(k, v()); if (k === "class") - el.className = safeVal || ""; - else if (safeVal == null) + el.className = val || ""; + else if (val == null) el.removeAttribute(k); else if (k in el && !isSVG) - el[k] = safeVal; + el[k] = val; else - el.setAttribute(k, safeVal === true ? "" : safeVal); + el.setAttribute(k, val === true ? "" : val); }); effect(); el._cleanups.add(() => dispose(effect)); onUnmount(() => dispose(effect)); if (/^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) && (k === "value" || k === "checked")) { const evType = k === "checked" ? "change" : "input"; - el.addEventListener(evType, (ev) => val(ev.target[k])); + el.addEventListener(evType, (ev) => v(ev.target[k])); } } else { + const val = validateAttr(k, v); if (val != null) { if (k in el && !isSVG) el[k] = val; @@ -552,38 +563,14 @@ MOUNTED_NODES.set(t, inst); return inst; }; - // sigpro/tags.js - if (typeof window !== "undefined") { - "a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video".split(" ").forEach((tag) => { - window[tag] = (...args) => h(tag, ...args); + var sigpro = () => { + if (typeof window === "undefined") + return; + Object.assign(window, { $, $$, watch, h, when, each, router, mount, batch }); + "a abbr article aside ... video".split(" ").forEach((tag) => { + window[tag] = (props, children) => h(tag, props, children); }); - console.log("SigPro tags ready"); - } - - // sigpro/xss.js - var DANGEROUS_PROTOCOL = /^\s*(javascript|data|vbscript):/i; - var DANGEROUS_URI_ATTRS = new Set(["src", "href", "formaction", "action", "background", "code", "archive"]); - var isDangerousAttr = (key) => DANGEROUS_URI_ATTRS.has(key) || key.startsWith("on"); - var validateAttr = (key, val) => { - if (val == null || val === false) - return null; - if (isDangerousAttr(key)) { - const sVal = String(val); - if (DANGEROUS_PROTOCOL.test(sVal)) { - console.warn(`[SigPro XSS] Locked ${key}`); - return "#"; - } - } - return val; }; - filterXSS(validateAttr); - - // sigpro-full.js - if (typeof window !== "undefined") { - const props = {}; - for (const fn of [["$", $], ["$$", $$], ["watch", watch], ["h", h], ["when", when], ["each", each], ["router", router], ["mount", mount], ["batch", batch]]) { - props[fn[0]] = { value: fn[1], writable: false, configurable: false, enumerable: true }; - } - Object.defineProperties(window, props); - } + if (typeof import.meta === "undefined" && typeof window !== "undefined") + sigpro(); })(); diff --git a/dist/sigpro.min.js b/dist/sigpro.min.js index 53ba08e..fe94c2b 100644 --- a/dist/sigpro.min.js +++ b/dist/sigpro.min.js @@ -1 +1 @@ -(()=>{var{defineProperty:j,getOwnPropertyNames:Q,getOwnPropertyDescriptor:H}=Object,Y=Object.prototype.hasOwnProperty;function Z(e){return this[e]}var ee=(e)=>{var t=(X??=new WeakMap).get(e),n;if(t)return t;if(t=j({},"__esModule",{value:!0}),e&&typeof e==="object"||typeof e==="function"){for(var s of Q(e))if(!Y.call(t,s))j(t,s,{get:Z.bind(e,s),enumerable:!(n=H(e,s))||n.enumerable})}return X.set(e,t),t},X;var te=(e)=>e;function ne(e,t){this[e]=te.bind(null,t)}var oe=(e,t)=>{for(var n in t)j(e,n,{get:t[n],enumerable:!0,configurable:!0,set:ne.bind(t,n)})};var ue={};oe(ue,{when:()=>D,watch:()=>x,router:()=>N,mount:()=>W,h:()=>E,filterXSS:()=>B,each:()=>G,batch:()=>I,$$:()=>L,$:()=>T});var m=(e)=>typeof e==="function",k=(e)=>e&&typeof e==="object",v=Array.isArray,S=typeof document<"u"?document:null,K=(e)=>e?._isRuntime?e.container:e instanceof Node?e:S.createTextNode(e==null?"":String(e)),d=null,_=null,R=!1,C=0,$=new Set,q=new WeakMap,U=Symbol("iter"),V=new WeakMap,se="http://www.w3.org/2000/svg",z="http://www.w3.org/1999/xlink",re=new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(",")),A=null,B=(e)=>{A=e},b=(e)=>{if(!e||e._disposed)return;e._disposed=!0;let t=[e];while(t.length){let n=t.pop();if(n._cleanups)n._cleanups.forEach((s)=>s()),n._cleanups.clear();if(n._children)n._children.forEach((s)=>t.push(s)),n._children.clear();if(n._deps)n._deps.forEach((s)=>s.delete(n)),n._deps.clear()}},g=(e)=>{if(_)(_._cleanups||=new Set).add(e)},ce=(e)=>{let t=d;d=null;try{return e()}finally{d=t}},O=(e,t=!1)=>{let n=()=>{if(n._disposed)return;if(n._deps)n._deps.forEach((c)=>c.delete(n));if(n._cleanups)n._cleanups.forEach((c)=>c()),n._cleanups.clear();let s=d,r=_;d=_=n;try{return n._result=e()}catch(c){console.error("[SigPro]",c)}finally{d=s,_=r}};if(n._deps=n._cleanups=n._children=null,n._disposed=!1,n._isComputed=t,n._depth=d?d._depth+1:0,n._mounts=[],n._parent=_,_)(_._children||=new Set).add(n);return n},F=()=>{if(R)return;R=!0;let e=Array.from($).sort((t,n)=>t._depth-n._depth);$.clear();for(let t of e)if(!t._disposed)t();R=!1},I=(e)=>{C++;try{return e()}finally{if(C--,C===0&&$.size>0&&!R)F()}},w=(e,t=!1)=>{if(!t&&d&&!d._disposed)e.add(d),(d._deps||=new Set).add(e);else if(t&&e.size>0){let n=!1;for(let s of e){if(s===d||s._disposed)continue;if(s._isComputed){if(s._dirty=!0,s._subs)w(s._subs,!0)}else $.add(s),n=!0}if(n&&!R&&C===0)queueMicrotask(F)}},T=(e,t=null)=>{let n=new Set;if(m(e)){let s,r=()=>{if(r._dirty){let c=d;d=r;try{let o=e();if(!Object.is(s,o))s=o,w(n,!0)}finally{d=c}r._dirty=!1}return w(n),s};return r._isComputed=!0,r._subs=n,r._dirty=!0,r._deps=null,r._disposed=!1,r}if(t)try{e=JSON.parse(localStorage.getItem(t))??e}catch(s){}return(...s)=>{if(s.length){let r=m(s[0])?s[0](e):s[0];if(!Object.is(e,r)){if(e=r,t)localStorage.setItem(t,JSON.stringify(e));w(n,!0)}}return w(n),e}},L=(e)=>{if(!k(e))return e;let t=q.get(e);if(t)return t;let n=new Map,s=(c)=>{let o=n.get(c);if(!o)n.set(c,o=new Set);return o},r=new Proxy(e,{get(c,o,i){if(typeof o!=="symbol")w(s(o));return L(Reflect.get(c,o,i))},set(c,o,i,l){let u=Reflect.has(c,o),a=Reflect.get(c,o,l),f=Reflect.set(c,o,i,l);if(f&&!Object.is(a,i)){if(w(s(o),!0),!u)w(s(U),!0)}return f},deleteProperty(c,o){let i=Reflect.deleteProperty(c,o);if(i)w(s(o),!0),w(s(U),!0);return i},ownKeys(c){return w(s(U)),Reflect.ownKeys(c)}});return q.set(e,r),r},x=(e,t)=>{if(t===void 0){let s=O(e);return s(),()=>b(s)}let n=O(()=>{let s=Array.isArray(e)?e.map((r)=>r()):e();ce(()=>t(s))});return n(),()=>b(n)},M=(e)=>{if(!e)return;if(e._cleanups)e._cleanups.forEach((t)=>t()),e._cleanups.clear();if(e._ownerEffect)b(e._ownerEffect);if(e.childNodes)e.childNodes.forEach((t)=>M(t))},E=(e,t={},n=[])=>{if(t instanceof Node||v(t)||!k(t))n=t,t={};if(m(e)){let o=O(()=>{let a=e(t,{children:n,emit:(f,...h)=>t[`on${f[0].toUpperCase()}${f.slice(1)}`]?.(...h)});return o._result=a,a});o();let i=o._result;if(i==null)return null;let l=i instanceof Node||v(i)&&i.every((a)=>a instanceof Node)?i:S.createTextNode(String(i)),u=(a)=>{if(k(a)&&!a._isRuntime)a._mounts=o._mounts||[],a._cleanups=o._cleanups||new Set,a._ownerEffect=o};return v(l)?l.forEach(u):u(l),l}let s=re.has(e),r=s?S.createElementNS(se,e):S.createElement(e);r._cleanups=new Set;for(let o of Object.keys(t)){let i=t[o];if(o==="ref"){m(i)?i(r):i.current=r;continue}let l=A?A(o,i):i;if(s&&o.startsWith("xlink:")){l==null?r.removeAttributeNS(z,o.slice(6)):r.setAttributeNS(z,o.slice(6),l);continue}if(o.startsWith("on")){let u=o.slice(2).toLowerCase();r.addEventListener(u,l);let a=()=>r.removeEventListener(u,l);r._cleanups.add(a),g(a)}else if(m(l)){let u=O(()=>{let a=l(),f=A?A(o,a):a;if(o==="class")r.className=f||"";else if(f==null)r.removeAttribute(o);else if(o in r&&!s)r[o]=f;else r.setAttribute(o,f===!0?"":f)});if(u(),r._cleanups.add(()=>b(u)),g(()=>b(u)),/^(INPUT|TEXTAREA|SELECT)$/.test(r.tagName)&&(o==="value"||o==="checked")){let a=o==="checked"?"change":"input";r.addEventListener(a,(f)=>l(f.target[o]))}}else if(l!=null)if(o in r&&!s)r[o]=l;else r.setAttribute(o,l===!0?"":l)}let c=(o)=>{if(v(o))return o.forEach(c);if(m(o)){let i=S.createTextNode("");r.appendChild(i);let l=[],u=O(()=>{let a=o(),f=(v(a)?a:[a]).map(K);l.forEach((p)=>{if(p._isRuntime)p.destroy();else M(p);if(p.parentNode)p.remove()});let h=i;for(let p=f.length-1;p>=0;p--){let y=f[p];if(y.parentNode!==h.parentNode)h.parentNode?.insertBefore(y,h);if(y._mounts)y._mounts.forEach((J)=>J());h=y}l=f});u(),r._cleanups.add(()=>b(u)),g(()=>b(u))}else{let i=K(o);if(r.appendChild(i),i._mounts)i._mounts.forEach((l)=>l())}};return c(n),r},P=(e)=>{let t=new Set,n=_,s=d,r=S.createElement("div");r.style.display="contents",r.setAttribute("role","presentation"),_={_cleanups:t},d=null;let c=(o)=>{if(!o)return;if(o._isRuntime)t.add(o.destroy),r.appendChild(o.container);else if(v(o))o.forEach(c);else r.appendChild(o instanceof Node?o:S.createTextNode(String(o==null?"":o)))};try{c(e({onCleanup:(o)=>t.add(o)}))}finally{_=n,d=s}return{_isRuntime:!0,container:r,destroy:()=>{t.forEach((o)=>o()),M(r),r.remove()}}},D=(e,t,n=null)=>{let s=S.createTextNode(""),r=E("div",{style:"display:contents"},[s]),c=null;return x(()=>!!(m(e)?e():e),(o)=>{if(c)c.destroy(),c=null;let i=o?t:n;if(i)c=P(()=>m(i)?i():i),r.insertBefore(c.container,s)}),g(()=>c?.destroy()),r},G=(e,t,n)=>{let s=S.createTextNode(""),r=E("div",{style:"display:contents"},[s]),c=new Map;return x(()=>(m(e)?e():e)||[],(o)=>{let i=new Map,l=[],u=o||[];for(let f=0;ft(h,f));else c.delete(p);i.set(p,y),l.push(y)}c.forEach((f)=>f.destroy());let a=s;for(let f=l.length-1;f>=0;f--){let p=l[f].container;if(p.nextSibling!==a)r.insertBefore(p,a);a=p}c=i}),r},N=(e)=>{let t=()=>window.location.hash.slice(1)||"/",n=T(t()),s=()=>n(t());window.addEventListener("hashchange",s),g(()=>window.removeEventListener("hashchange",s));let r=E("div",{class:"router-hook"}),c=null;return x([n],()=>{let o=n(),i=e.find((l)=>{let u=l.path.split("/").filter(Boolean),a=o.split("/").filter(Boolean);return u.length===a.length&&u.every((f,h)=>f[0]===":"||f===a[h])})||e.find((l)=>l.path==="*");if(i){c?.destroy();let l={};i.path.split("/").filter(Boolean).forEach((u,a)=>{if(u[0]===":")l[u.slice(1)]=o.split("/").filter(Boolean)[a]}),N.params(l),c=P(()=>m(i.component)?i.component(l):i.component),r.replaceChildren(c.container)}}),r};N.params=T({});N.to=(e)=>window.location.hash=e.replace(/^#?\/?/,"#/");N.back=()=>window.history.back();N.path=()=>window.location.hash.replace(/^#/,"")||"/";var W=(e,t)=>{let n=typeof t==="string"?S.querySelector(t):t;if(!n)return;if(V.has(n))V.get(n).destroy();let s=P(m(e)?e:()=>e);return n.replaceChildren(s.container),V.set(n,s),s};if(typeof window<"u")"a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video".split(" ").forEach((e)=>{window[e]=(...t)=>E(e,...t)}),console.log("SigPro tags ready");var ie=/^\s*(javascript|data|vbscript):/i,le=new Set(["src","href","formaction","action","background","code","archive"]),ae=(e)=>le.has(e)||e.startsWith("on"),fe=(e,t)=>{if(t==null||t===!1)return null;if(ae(e)){let n=String(t);if(ie.test(n))return console.warn(`[SigPro XSS] Locked ${e}`),"#"}return t};B(fe);if(typeof window<"u"){let e={};for(let t of[["$",T],["$$",L],["watch",x],["h",E],["when",D],["each",G],["router",N],["mount",W],["batch",I]])e[t[0]]={value:t[1],writable:!1,configurable:!1,enumerable:!0};Object.defineProperties(window,e)}})(); +(()=>{var{defineProperty:L,getOwnPropertyNames:F,getOwnPropertyDescriptor:H}=Object,Y=Object.prototype.hasOwnProperty;function Z(e){return this[e]}var ee=(e)=>{var n=($??=new WeakMap).get(e),t;if(n)return n;if(n=L({},"__esModule",{value:!0}),e&&typeof e==="object"||typeof e==="function"){for(var o of F(e))if(!Y.call(n,o))L(n,o,{get:Z.bind(e,o),enumerable:!(t=H(e,o))||t.enumerable})}return $.set(e,n),n},$;var te=(e)=>e;function ne(e,n){this[e]=te.bind(null,n)}var se=(e,n)=>{for(var t in n)L(e,t,{get:n[t],enumerable:!0,configurable:!0,set:ne.bind(n,t)})};var fe={};se(fe,{when:()=>q,watch:()=>R,sigpro:()=>Q,router:()=>N,mount:()=>J,h:()=>g,each:()=>z,batch:()=>K,$$:()=>I,$:()=>C});var m=(e)=>typeof e==="function",V=(e)=>e&&typeof e==="object",v=Array.isArray,E=typeof document<"u"?document:null,k=(e)=>e?._isRuntime?e.container:e instanceof Node?e:E.createTextNode(e==null?"":String(e)),d=null,_=null,b=!1,O=0,T=new Set,D=new WeakMap,B=Symbol("iter"),P=new WeakMap,oe="http://www.w3.org/2000/svg",G="http://www.w3.org/1999/xlink",re=new Set("svg,path,circle,rect,line,polyline,polygon,g,defs,text,textPath,tspan,use,symbol,image,marker,ellipse".split(",")),S=(e)=>{if(!e||e._disposed)return;e._disposed=!0;let n=[e];while(n.length){let t=n.pop();if(t._cleanups)t._cleanups.forEach((o)=>o()),t._cleanups.clear();if(t._children)t._children.forEach((o)=>n.push(o)),t._children.clear();if(t._deps)t._deps.forEach((o)=>o.delete(t)),t._deps.clear()}},x=(e)=>{if(_)(_._cleanups||=new Set).add(e)},ce=(e)=>{let n=d;d=null;try{return e()}finally{d=n}},A=(e,n=!1)=>{let t=()=>{if(t._disposed)return;if(t._deps)t._deps.forEach((i)=>i.delete(t));if(t._cleanups)t._cleanups.forEach((i)=>i()),t._cleanups.clear();let o=d,r=_;d=_=t;try{return t._result=e()}catch(i){console.error("[SigPro]",i)}finally{d=o,_=r}};if(t._deps=t._cleanups=t._children=null,t._disposed=!1,t._isComputed=n,t._depth=d?d._depth+1:0,t._mounts=[],t._parent=_,_)(_._children||=new Set).add(t);return t},W=()=>{if(b)return;b=!0;let e=Array.from(T).sort((n,t)=>n._depth-t._depth);T.clear();for(let n of e)if(!n._disposed)n();b=!1},K=(e)=>{O++;try{return e()}finally{if(O--,O===0&&T.size>0&&!b)W()}},w=(e,n=!1)=>{if(!n&&d&&!d._disposed)e.add(d),(d._deps||=new Set).add(e);else if(n&&e.size>0){let t=!1;for(let o of e){if(o===d||o._disposed)continue;if(o._isComputed){if(o._dirty=!0,o._subs)w(o._subs,!0)}else T.add(o),t=!0}if(t&&!b&&O===0)queueMicrotask(W)}},C=(e,n=null)=>{let t=new Set;if(m(e)){let o,r=()=>{if(r._dirty){let i=d;d=r;try{let s=e();if(!Object.is(o,s))o=s,w(t,!0)}finally{d=i}r._dirty=!1}return w(t),o};return r._isComputed=!0,r._subs=t,r._dirty=!0,r._deps=null,r._disposed=!1,r}if(n)try{e=JSON.parse(localStorage.getItem(n))??e}catch(o){}return(...o)=>{if(o.length){let r=m(o[0])?o[0](e):o[0];if(!Object.is(e,r)){if(e=r,n)localStorage.setItem(n,JSON.stringify(e));w(t,!0)}}return w(t),e}},I=(e)=>{if(!V(e))return e;let n=D.get(e);if(n)return n;let t=new Map,o=(i)=>{let s=t.get(i);if(!s)t.set(i,s=new Set);return s},r=new Proxy(e,{get(i,s,c){if(typeof s!=="symbol")w(o(s));return I(Reflect.get(i,s,c))},set(i,s,c,l){let a=Reflect.has(i,s),f=Reflect.get(i,s,l),u=Reflect.set(i,s,c,l);if(u&&!Object.is(f,c)){if(w(o(s),!0),!a)w(o(B),!0)}return u},deleteProperty(i,s){let c=Reflect.deleteProperty(i,s);if(c)w(o(s),!0),w(o(B),!0);return c},ownKeys(i){return w(o(B)),Reflect.ownKeys(i)}});return D.set(e,r),r},R=(e,n)=>{if(n===void 0){let o=A(e);return o(),()=>S(o)}let t=A(()=>{let o=Array.isArray(e)?e.map((r)=>r()):e();ce(()=>n(o))});return t(),()=>S(t)},M=(e)=>{if(!e)return;if(e._cleanups)e._cleanups.forEach((n)=>n()),e._cleanups.clear();if(e._ownerEffect)S(e._ownerEffect);if(e.childNodes)e.childNodes.forEach((n)=>M(n))},ie=/^\s*(javascript|data|vbscript):/i,le=new Set(["src","href","formaction","action","background","code","archive"]),ae=(e)=>le.has(e)||e.startsWith("on"),U=(e,n)=>{if(n==null||n===!1)return null;if(ae(e)){let t=String(n);if(ie.test(t))return console.warn(`[SigPro] Bloqueado protocolo peligroso en ${e}`),"#"}return n},g=(e,n={},t=[])=>{if(n instanceof Node||v(n)||!V(n))t=n,n={};if(m(e)){let s=A(()=>{let f=e(n,{children:t,emit:(u,...h)=>n[`on${u[0].toUpperCase()}${u.slice(1)}`]?.(...h)});return s._result=f,f});s();let c=s._result;if(c==null)return null;let l=c instanceof Node||v(c)&&c.every((f)=>f instanceof Node)?c:E.createTextNode(String(c)),a=(f)=>{if(V(f)&&!f._isRuntime)f._mounts=s._mounts||[],f._cleanups=s._cleanups||new Set,f._ownerEffect=s};return v(l)?l.forEach(a):a(l),l}let o=re.has(e),r=o?E.createElementNS(oe,e):E.createElement(e);r._cleanups=new Set;for(let s of Object.keys(n)){let c=n[s];if(s==="ref"){m(c)?c(r):c.current=r;continue}if(o&&s.startsWith("xlink:")){let l=U(s.slice(6),c);l==null?r.removeAttributeNS(G,s.slice(6)):r.setAttributeNS(G,s.slice(6),l);continue}if(s.startsWith("on")){let l=s.slice(2).toLowerCase();r.addEventListener(l,c);let a=()=>r.removeEventListener(l,c);r._cleanups.add(a),x(a)}else if(m(c)){let l=A(()=>{let a=U(s,c());if(s==="class")r.className=a||"";else if(a==null)r.removeAttribute(s);else if(s in r&&!o)r[s]=a;else r.setAttribute(s,a===!0?"":a)});if(l(),r._cleanups.add(()=>S(l)),x(()=>S(l)),/^(INPUT|TEXTAREA|SELECT)$/.test(r.tagName)&&(s==="value"||s==="checked")){let a=s==="checked"?"change":"input";r.addEventListener(a,(f)=>c(f.target[s]))}}else{let l=U(s,c);if(l!=null)if(s in r&&!o)r[s]=l;else r.setAttribute(s,l===!0?"":l)}}let i=(s)=>{if(v(s))return s.forEach(i);if(m(s)){let c=E.createTextNode("");r.appendChild(c);let l=[],a=A(()=>{let f=s(),u=(v(f)?f:[f]).map(k);l.forEach((p)=>{if(p._isRuntime)p.destroy();else M(p);if(p.parentNode)p.remove()});let h=c;for(let p=u.length-1;p>=0;p--){let y=u[p];if(y.parentNode!==h.parentNode)h.parentNode?.insertBefore(y,h);if(y._mounts)y._mounts.forEach((X)=>X());h=y}l=u});a(),r._cleanups.add(()=>S(a)),x(()=>S(a))}else{let c=k(s);if(r.appendChild(c),c._mounts)c._mounts.forEach((l)=>l())}};return i(t),r},j=(e)=>{let n=new Set,t=_,o=d,r=E.createElement("div");r.style.display="contents",r.setAttribute("role","presentation"),_={_cleanups:n},d=null;let i=(s)=>{if(!s)return;if(s._isRuntime)n.add(s.destroy),r.appendChild(s.container);else if(v(s))s.forEach(i);else r.appendChild(s instanceof Node?s:E.createTextNode(String(s==null?"":s)))};try{i(e({onCleanup:(s)=>n.add(s)}))}finally{_=t,d=o}return{_isRuntime:!0,container:r,destroy:()=>{n.forEach((s)=>s()),M(r),r.remove()}}},q=(e,n,t=null)=>{let o=E.createTextNode(""),r=g("div",{style:"display:contents"},[o]),i=null;return R(()=>!!(m(e)?e():e),(s)=>{if(i)i.destroy(),i=null;let c=s?n:t;if(c)i=j(()=>m(c)?c():c),r.insertBefore(i.container,o)}),x(()=>i?.destroy()),r},z=(e,n,t)=>{let o=E.createTextNode(""),r=g("div",{style:"display:contents"},[o]),i=new Map;return R(()=>(m(e)?e():e)||[],(s)=>{let c=new Map,l=[],a=s||[];for(let u=0;un(h,u));else i.delete(p);c.set(p,y),l.push(y)}i.forEach((u)=>u.destroy());let f=o;for(let u=l.length-1;u>=0;u--){let p=l[u].container;if(p.nextSibling!==f)r.insertBefore(p,f);f=p}i=c}),r},N=(e)=>{let n=()=>window.location.hash.slice(1)||"/",t=C(n()),o=()=>t(n());window.addEventListener("hashchange",o),x(()=>window.removeEventListener("hashchange",o));let r=g("div",{class:"router-hook"}),i=null;return R([t],()=>{let s=t(),c=e.find((l)=>{let a=l.path.split("/").filter(Boolean),f=s.split("/").filter(Boolean);return a.length===f.length&&a.every((u,h)=>u[0]===":"||u===f[h])})||e.find((l)=>l.path==="*");if(c){i?.destroy();let l={};c.path.split("/").filter(Boolean).forEach((a,f)=>{if(a[0]===":")l[a.slice(1)]=s.split("/").filter(Boolean)[f]}),N.params(l),i=j(()=>m(c.component)?c.component(l):c.component),r.replaceChildren(i.container)}}),r};N.params=C({});N.to=(e)=>window.location.hash=e.replace(/^#?\/?/,"#/");N.back=()=>window.history.back();N.path=()=>window.location.hash.replace(/^#/,"")||"/";var J=(e,n)=>{let t=typeof n==="string"?E.querySelector(n):n;if(!t)return;if(P.has(t))P.get(t).destroy();let o=j(m(e)?e:()=>e);return t.replaceChildren(o.container),P.set(t,o),o},Q=()=>{if(typeof window>"u")return;Object.assign(window,{$:C,$$:I,watch:R,h:g,when:q,each:z,router:N,mount:J,batch:K}),"a abbr article aside ... video".split(" ").forEach((e)=>{window[e]=(n,t)=>g(e,n,t)})};if(typeof import.meta>"u"&&typeof window<"u")Q();})(); diff --git a/docs/api/global.md b/docs/api/global.md index 23e4549..3aedad2 100644 --- a/docs/api/global.md +++ b/docs/api/global.md @@ -111,8 +111,9 @@ export const filteredTodos = $(() => { ```javascript // components/TodoApp.js +import { sigpro } from 'sigpro'; import { todos, filter, addTodo, toggleTodo, filteredTodos } from "../store/todos.js"; -import "sigpro/tags" // tags helpers available in global +sigpro(); // tags helpers available in global also core functions const TodoApp = () => div({ class: "todo-app" }, [ diff --git a/docs/api/h.md b/docs/api/h.md index 812dbe0..2c48aeb 100644 --- a/docs/api/h.md +++ b/docs/api/h.md @@ -138,7 +138,8 @@ h('svg', { width: 100, height: 100 }, [ ## Complete Example ```javascript -import { $, h, mount } from 'sigpro'; +import { sigpro } from 'sigpro'; +sigpro(); // tags helpers available in global also core functions const dynamicTag = $('h1'); diff --git a/docs/api/mount.md b/docs/api/mount.md index c5572a0..77acb01 100644 --- a/docs/api/mount.md +++ b/docs/api/mount.md @@ -119,8 +119,8 @@ When `destroy()` is called (or when a new mount replaces an old one), everything ## Complete Example ```javascript -import { $, mount, div, h1, button } from 'sigpro'; -import "sigpro/tags" // tags helpers available in global +import { sigpro } from 'sigpro'; +sigpro(); // tags helpers available in global also core functions const App = () => { const count = $(0); diff --git a/docs/api/quick.md b/docs/api/quick.md index cd382c8..89e59cf 100644 --- a/docs/api/quick.md +++ b/docs/api/quick.md @@ -1,18 +1,5 @@ # SigPro – Complete API Reference -SigPro is a **Real‑DOM first** reactive micro‑framework. No virtual DOM, no diffing overhead – it updates the DOM directly with surgical precision. Built‑in automatic cleanup prevents memory leaks, and the API is designed to be both tiny and powerful. - -```javascript -import { $, $$, watch, h, when, each, router, mount, batch } from 'sigpro' -// Optional side‑effects (activate global helpers & security): -import 'sigpro/tags' // → window.div, window.span, etc. -import 'sigpro/xss' // → attribute sanitisation -``` - -In a classic IIFE script (` ``` ---- - -## 9. Important Notes - -- **Naming:** All tag helpers are **lowercase**. -- **Global availability:** - - **IIFE script** – automatically on `window`. - - **ESM module** – not global by default; use `import 'sigpro/tags'` to activate them. -- **Custom components:** Use **PascalCase** for your own component functions (e.g., `UserCard`) to visually distinguish them from built‑in tags. - ---- - -## 10. Summary - -| Feature | Description | -| :--- | :--- | -| **Tag helpers** | Lowercase functions for every HTML element (e.g., `div()`, `button()`). | -| **Activation** | IIFE: automatic. ESM: `import 'sigpro/tags'`. | -| **Reactive attributes** | Pass a function to any attribute to keep it synced. | -| **Two‑way binding** | Assign a signal directly to `value` or `checked` on form elements. | -| **Dynamic children** | Pass a function as a child for live updating content. | -| **Auto‑cleanup** | All effects, events, and children are disposed when the element is removed. | -| **Security** | Optional XSS shield: `import 'sigpro/xss'`. | diff --git a/docs/install.md b/docs/install.md index 418f70b..0d4aa45 100644 --- a/docs/install.md +++ b/docs/install.md @@ -48,16 +48,13 @@ bun add sigpro ```html ``` @@ -68,7 +65,7 @@ bun add sigpro ```html - +