vaderjs 1.3.3-7b27417d42e1 → 1.3.3-7bn27417d42e1

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/README.md CHANGED
@@ -81,7 +81,7 @@ export default function(req, res){
81
81
 
82
82
  return <>
83
83
  <h1>${count}</h1>
84
- <button onClick={(event)=>{setCount(count + 1)}}>
84
+ <button onClick={(event)=>{setCount(++count)}}>
85
85
  </>
86
86
  }
87
87
 
@@ -130,7 +130,7 @@ export function Layout({title, keywords, description, children}){
130
130
 
131
131
  export default function (req, res){
132
132
  return <>
133
- <Layout $={{title:'home', description:'home page', keywords:'vader.js', logo:''}}>
133
+ <Layout ${{title:'home', description:'home page', keywords:'vader.js', logo:''}}>
134
134
  <h1> Hello World</h1>
135
135
  </Layout>
136
136
  </>
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "vaderjs",
3
3
  "description": "A Reactive library aimed to helping you build reactive applications inspired by react.js",
4
4
  "module": "vader.js",
5
- "version": "1.3.3-7b27417d42e1",
5
+ "version": "1.3.3-7bn27417d42e1",
6
6
  "bin": {
7
7
  "vader": "./vader.js"
8
8
  },
package/runtime/vader.js CHANGED
@@ -1 +1 @@
1
- window.Vader={version:"1.3.3"},window.componentRegistry={};let errors={"SyntaxError: Unexpected token '<'":"You forgot to enclose tags in a fragment <></>"},mounts=[],lastRoute=null,hasRan=[];export const strictMount=(e,t)=>{let s=setInterval((()=>{document.querySelector(`[key="${e}"]`)&&!hasRan.includes(e)&&(clearInterval(s),t(),hasRan.push(e))}),120)};export class Component{constructor(e={}){this.$_vaderElement=!0,this.state={},this.key=null,this.components={},this.mounted=!1,this.checkIFMounted(),this.memoizes=[],this.functions=[],this.props={children:"",$:{},...e},this.children=[],this.noKey=!1,this.parentNode={},this.request={headers:{},method:"GET",params:{},path:"",query:{}},this.response={json:e=>{},send:e=>{},redirect:e=>{},render:async e=>{},log:e=>{},setQuery:e=>{}},this.router={use:e=>{}}}createComponent(e,t,s){function isClass(e){return"function"==typeof e&&/^class\s/.test(Function.prototype.toString.call(e))}let r=isClass(e)?new e(t):null;if(!e)throw new Error("Component must be defined");let n=[],i=new Component(t);if(isClass(e))r.props=t||{},r.props.children=s.join("")||[],r.props.children=s.join(""),r.parentNode=this,r.type="class ",r.request=this.request,r.response=this.response,r.key=r.props.key?r.props.key:Math.random(),i=r;else{e.toString();i.key=e.toString().split('key="')[1]?e.toString().split('key="')[1].split('"')[0]:null,t=t?{...t,...n.reduce(((e,t)=>({...e,...t})),{}),children:s.join("")||[]}:{children:s.join("")||[]};let r={key:i.key?i.key:Math.random(),isUnique:!!i.key,render:()=>e.apply(i,[t]),request:this.request,isChild:!0,response:this.response,params:this.request.params,queryParams:this.request.query,reset:i.reset.bind(i),onMount:i.onMount.bind(i),useState:null,router:{use:i.router.use.bind(i)},bindMount:i.bindMount.bind(i),memoize:i.memoize.bind(i),createComponent:i.createComponent.bind(i),isChild:!1,useState:i.useState.bind(i),parseStyle:i.parseStyle.bind(i),bind:i.bind.bind(i),useRef:i.useRef.bind(i),request:this.request,response:this.response,useReducer:i.useReducer.bind(i),hydrate:i.hydrate.bind(i),onUnmount:i.onUnmount.bind(i),type:"function",parentNoe:this,props:{...t,children:s.join("")||[]}};i.render=r.render,i=r,i.props.children=s.join("")||[]}return this.components[i.key]||(this.components[i.key]=i),!this.children.includes(i)&&this.children.push(i),this.components[i.key]}reset(){Object.keys(this.components).forEach((e=>{this.components[e].onUnmount(),delete this.components[e]})),this.state={},this.children=[]}memoize(e){if(!0==!this.memoizes.includes(e.key))this.memoizes.push(e.key),this.components[e.key]=e;let t=this.components[e.key];"class"!==t.type||t.$_vaderElement||console.error(`class ${t.constructor.name} must extend Component`),t.bindMount(),t.parentNode=this,t.props=e.props,t.request=this.request,t.response=this.response,t.onMount=e.onMount.bind(e),t.onUnmount=e.onUnmount.bind(e);let s=t.render();return s&&s.split(">,").length>1&&(s=s.replaceAll(">,",">")),t.nokey||t.noKey?s:`<div key="${t.key}">${s}</div>`}parseStyle(e){let t="";return Object.keys(e).forEach((s=>{let r=e[s];s=s.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g,"$1-$2").toLowerCase(),t+=`${s}:${r};`})),t}bindMount(){mounts.push(this)}domDifference(e,t){let s=[];for(let r=0;r<e.length;r++){let n=e[r],i=t[r];if(n&&i&&n.childNodes.length>0&&i.childNodes.length>0){switch(!0){case n.attributes&&i.attributes&&n.attributes.length!==i.attributes.length:s.push({type:"attributeSwap",old:n,new:i});break;case!n.isEqualNode(i)&&n.nodeName===i.nodeName&&n.textContent!==i.textContent:s.push({type:"replace",old:n,new:i})}let e=this.domDifference(Array.from(n.childNodes),Array.from(i.childNodes));return s.push(...e),s}n.isEqualNode(i)||n.nodeName!==i.nodeName||n.textContent===i.textContent?!n&&i&&s.push({type:"add",old:n,new:i}):s.push({type:"replace",old:n,new:i})}return s}updateChangedElements(e){e.forEach((e=>{if(e)switch(e.type){case"replace":if(e.old.panrntNode&&"BODY"===e.old.parentNode.nodeName)return;e.old.replaceWith(e.new.cloneNode(!0));break;case"remove":e.old.remove();break;case"attributeSwap":let t=Array.from(e.old.attributes),s=Array.from(e.new.attributes);t.forEach((t=>{e.old.removeAttribute(t.name)})),s.forEach((t=>{e.old.setAttribute(t.name,t.value)}));break;case"add":e.old.appendChild(e.new.cloneNode(!0))}}))}hydrate(e){if(e){let t=(new DOMParser).parseFromString(this.render(),"text/html").body.querySelectorAll(`[ref="${e.bind?e.bind:e}"]`),s=document.querySelectorAll(`[ref="${e?e.bind:e}"]`);t.forEach((e=>{let t=Array.from(s).find((t=>t.getAttribute("ref")===e.getAttribute("ref")));if(t){let s=this.domDifference(Array.from(t.childNodes),Array.from(e.childNodes));this.updateChangedElements([s])}}))}else{let e=this.key?document.querySelector(`[key="${this.key}"]`):null;if(e){let t=(new DOMParser).parseFromString(this.render(),"text/html").body.querySelector(`[key="${this.key}"]`),s=e,r=this.domDifference([s],[t]);this.updateChangedElements(r)}}}patch(e,t){const s=this.domDifference(e,t);this.updateChangedElements(s)}handleObject(obj){try{obj=JSON.parse(obj)}catch(e){}return eval(obj)}bind(e,t,s,r,...n){return s+=this.key,window["callFunctions"+this.key]=(e,t)=>{let s=this.functions.find((t=>t.ref===e));s&&s.func(t)},this.functions.find((e=>e.ref===s))||this.functions.push({ref:s,func:e}),t?e:`((event)=>{callFunctions${this.key} ? callFunctions${this.key}('${s}', event) : null})(event)`}setState(e,t){this.state=e,this.hydrate(t)}useState(e,t){this.state.hasOwnProperty(e)||(this.state[e]=t);return[(()=>this.state[e])(),(t,s)=>{this.state[e]=t,this.hydrate(s)}]}useRef(e=null,t){this.state[e]||(this.state[e]=t);return{bind:e+this.key,current:(()=>document.querySelector(`[ref="${e+this.key}"]`)||t)()}}useReducer(e=null,t,s=null){this.state[e]||(this.state[e]=t);const getValue=()=>this.state[e];let r=getValue();return[getValue(),(t,n)=>{const i=s(r,t)??t;this.state[e]=i,this.hydrate(n),r=getValue()}]}render(){}checkIFMounted(){new MutationObserver((e=>{e.forEach((e=>{e.target.querySelector(`[key="${this.key}"]`)&&!this.mounted&&(this.onMount(),this.mounted=!0),Array.from(e.removedNodes).find((e=>e.attributes&&e.attributes.key&&e.attributes.key.value===this.key))&&(this.onUnmount(),this.reset())}))})).observe(document.body,{childList:!0,subtree:!0})}onMount(){}onUnmount(){}}export const useState=(e,t)=>{this.state[e]||(this.state[e]=t);return[states[e],(t,s)=>{states[e]=t,this.hydrate(s)}]};export const useReducer=(e,t)=>[e,e=>{}];export const useRef=e=>({current:e,bind:""});export class Link extends Component{constructor(e){super(e),this.props=e,this.link=document.createElement("a"),this.key=e.href+Math.random(),this.nokey=!0}render(){return this.link.innerHTML=this.props.children,this.link.setAttribute("id",this.props?.href),this.link.style=this.props?.style,this.link.setAttribute("class",this.props?.class||this.props?.className),this.link.setAttribute("onclick",this.props?.href?.includes("https")||this.props?.href?.includes("http")?`window.open('${this.props.href}', ${this.props.action||"_blank"}).focus()`:`window.history.pushState({}, '', '${this.props?.href}'); window.dispatchEvent(new Event('popstate'));`),this.link.outerHTML}}export class Image extends Component{constructor(e){super(e),this.props={src:e.src,class:e.class,style:e.style,blur:e.blur,width:e.width,height:e.height,optimize:e.optimize||!0,loader:e.loader||!0,alt:e.alt||"image",ref:e.ref||null},this.key=e.src+Math.random(),this.img=document.createElement("img"),this.placeholder=document.createElement("div")}render(){if(window.isServer)return"";let[e,t]=this.useState("loaded",!1),s=this.useRef("hookref",null),r=this.props.width?this.props.width:window.innerWidth/2,n=this.props.height?this.props.height:window.innerHeight/2;if(!this.props.src)throw new Error("Image src is required");return this.img.setAttribute("src",this.props.src),this.img.setAttribute("class",this.props.class),this.img.setAttribute("style",this.props.style?this.props.style:""),this.img.setAttribute("width",r),this.img.setAttribute("ref",s.bind),this.img.referrerPolicy="no-referrer",this.img.setAttribute("height",n),this.img.setAttribute("loading","lazy"),this.img.setAttribute("alt",this.props.alt),this.props.blur&&this.img.setAttribute("style",`filter: blur(${this.props.blur}px);`),this.props.optimize&&this.img.setAttribute("style",`image-rendering: -webkit-optimize-contrast; object-fit: cover; object-position: center; ${this.props.style?this.props.style:""}`),!this.props.loader||e||window.isServer||(this.placeholder.setAttribute("style",`width: ${r}px; height: ${n}px; background: #eee;`),this.placeholder.setAttribute("class","vader-image-placeholder"),this.placeholder.innerHTML=this.props.loader,window.isServer)?void 0:(this.img.onload=()=>{t(!0,s.bind)},`<span ref="${s.bind}">${e?this.img.outerHTML:this.placeholder.outerHTML}</span>`)}}export class Html extends Component{constructor(e){super(e),this.props={children:e.children,lang:e.lang||"en",attributes:e.attributes||{}},this.key="html",this.html=document.createElement("div")}render(){return window.isServer?(this.html.innerHTML=this.props.children,this.html.setAttribute("lang",this.props.lang?this.props.lang:"en"),this.props.attributes&&Object.keys(this.props.attributes).forEach((e=>{this.html.setAttribute(e,this.props.attributes[e])})),this.html.innerHTML):this.props.children}onMount(){console.log("Document Has Been Mounted")}}export class Head extends Component{constructor(e){super(e),this.props=e,this.key="head",this.head=document.createElement("head")}render(){return""}onMount(){if(!this.state.hasMounted&&window.isServer){document.head.innerHTML=this.props.children+document.head.innerHTML,document.querySelectorAll("script[eager]").forEach((async e=>{if(!e.getAttribute("src"))throw new Error("Eager scripts must be external");e.remove();let t=e.getAttribute("src"),s=document.createElement("script"),r=null;await fetch(t).then((e=>{if(404===e.status)throw document.documentElement.setAttribute("error",JSON.stringify({error:`File ${t} not found`,status:404})),new Error(`File ${t} not found`);return e.text()})).then((e=>{r=e})).catch((e=>{throw e})),s.innerHTML=r,s.setAttribute("srcid",t),document.querySelector(`[srcid="${t}"]`)||document.head.prepend(s)})),this.state.hasMounted=!0}}}export class Script extends Component{constructor(e){super(e),this.props={children:e.children},this.key="script",this.script=document.createElement("script")}render(){return this.script.innerHTML=this.props.children.split("\n").join(";\n"),this.script.outerHTML}onMount(){document.head.appendChild(this.script),document.body.querySelector(`[key="${this.key}"]`).remove()}}export default{Component:Component,useRef:useRef,useReducer:useReducer,useState:useState,strictMount:strictMount,Link:Link,Image:Image,Head:Head,Script:Script,Html:Html};
1
+ window.Vader={version:"1.3.3"},window.componentRegistry={};let errors={"SyntaxError: Unexpected token '<'":"You forgot to enclose tags in a fragment <></>"},mounts=[],lastRoute=null,hasRan=[];export const strictMount=(e,t)=>{let s=setInterval((()=>{document.querySelector(`[key="${e}"]`)&&!hasRan.includes(e)&&(clearInterval(s),t(),hasRan.push(e))}),120)};export class Component{constructor(e={}){this.$_vaderElement=!0,this.state={},this.key=null,this.components={},this.mounted=!1,this.checkIFMounted(),this.memoizes=[],this.functions=[],this.props={children:"",$:{},...e},this.children=[],this.noKey=!1,this.parentNode={},this.request={headers:{},method:"GET",params:{},path:"",query:{}},this.response={json:e=>{},send:e=>{},redirect:e=>{},render:async e=>{},log:e=>{},setQuery:e=>{}},this.router={use:e=>{}}}createComponent(e,t,s){function r(e){return"function"==typeof e&&/^class\s/.test(Function.prototype.toString.call(e))}let n=r(e)?new e(t):null;if(!e)throw new Error("Component must be defined");let i=[],o=new Component(t);if(r(e))n.props=t||{},n.props.children=s.join("")||[],n.props.children=s.join(""),n.parentNode=this,n.type="class ",n.request=this.request,n.response=this.response,n.key=n.props.key?n.props.key:Math.random(),o=n;else{e.toString();o.key=e.toString().split('key="')[1]?e.toString().split('key="')[1].split('"')[0]:null,t=t?{...t,...i.reduce(((e,t)=>({...e,...t})),{}),children:s.join("")||[]}:{children:s.join("")||[]};let r={key:o.key?o.key:Math.random(),isUnique:!!o.key,render:()=>e.apply(o,[t]),request:this.request,isChild:!0,response:this.response,params:this.request.params,queryParams:this.request.query,reset:o.reset.bind(o),onMount:o.onMount.bind(o),useState:null,router:{use:o.router.use.bind(o)},bindMount:o.bindMount.bind(o),memoize:o.memoize.bind(o),createComponent:o.createComponent.bind(o),isChild:!1,useState:o.useState.bind(o),parseStyle:o.parseStyle.bind(o),bind:o.bind.bind(o),useRef:o.useRef.bind(o),request:this.request,response:this.response,useReducer:o.useReducer.bind(o),hydrate:o.hydrate.bind(o),onUnmount:o.onUnmount.bind(o),type:"function",parentNoe:this,props:{...t,children:s.join("")||[]}};o.render=r.render,o=r,o.props.children=s.join("")||[]}return this.components[o.key]||(this.components[o.key]=o),!this.children.includes(o)&&this.children.push(o),this.components[o.key]}reset(){Object.keys(this.components).forEach((e=>{this.components[e].onUnmount(),delete this.components[e]})),this.state={},this.children=[]}memoize(e){if(!0==!this.memoizes.includes(e.key))this.memoizes.push(e.key),this.components[e.key]=e;let t=this.components[e.key];"class"!==t.type||t.$_vaderElement||console.error(`class ${t.constructor.name} must extend Component`),t.bindMount(),t.parentNode=this,t.props=e.props,t.request=this.request,t.response=this.response,t.onMount=e.onMount.bind(e),t.onUnmount=e.onUnmount.bind(e);let s=t.render();return s&&s.split(">,").length>1&&(s=s.replaceAll(">,",">")),t.nokey||t.noKey?s:`<div key="${t.key}">${s}</div>`}parseStyle(e){let t="";return Object.keys(e).forEach((s=>{let r=e[s];s=s.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g,"$1-$2").toLowerCase(),t+=`${s}:${r};`})),t}bindMount(){mounts.push(this)}domDifference(e,t){let s=[];for(let r=0;r<e.length;r++){let n=e[r],i=t[r];if(n&&i&&n.childNodes.length>0&&i.childNodes.length>0){switch(!0){case n.attributes&&i.attributes&&n.attributes.length!==i.attributes.length:s.push({type:"attributeSwap",old:n,new:i});break;case!n.isEqualNode(i)&&n.nodeName===i.nodeName&&n.textContent!==i.textContent:s.push({type:"replace",old:n,new:i})}let e=this.domDifference(Array.from(n.childNodes),Array.from(i.childNodes));return s.push(...e),s}n.isEqualNode(i)||n.nodeName!==i.nodeName||n.textContent===i.textContent?!n&&i&&s.push({type:"add",old:n,new:i}):s.push({type:"replace",old:n,new:i})}return s}updateChangedElements(e){e.forEach((e=>{if(e)switch(e.type){case"replace":if(e.old.panrntNode&&"BODY"===e.old.parentNode.nodeName)return;e.old.replaceWith(e.new.cloneNode(!0));break;case"remove":e.old.remove();break;case"attributeSwap":let t=Array.from(e.old.attributes),s=Array.from(e.new.attributes);t.forEach((t=>{e.old.removeAttribute(t.name)})),s.forEach((t=>{e.old.setAttribute(t.name,t.value)}));break;case"add":e.old.appendChild(e.new.cloneNode(!0))}}))}hydrate(e){if(e){let t=(new DOMParser).parseFromString(this.render(),"text/html").body.querySelectorAll(`[ref="${e.bind?e.bind:e}"]`),s=document.querySelectorAll(`[ref="${e?e.bind:e}"]`);t.forEach((e=>{let t=Array.from(s).find((t=>t.getAttribute("ref")===e.getAttribute("ref")));if(t){let s=this.domDifference(Array.from(t.childNodes),Array.from(e.childNodes));this.updateChangedElements([s])}}))}else{let e=this.key?document.querySelector(`[key="${this.key}"]`):null;if(e){let t=(new DOMParser).parseFromString(this.render(),"text/html").body.querySelector(`[key="${this.key}"]`),s=e,r=this.domDifference([s],[t]);this.updateChangedElements(r)}}}patch(e,t){const s=this.domDifference(e,t);this.updateChangedElements(s)}handleObject(obj){try{obj=JSON.parse(obj)}catch(e){}return eval(obj)}bind(e,t,s,r,...n){return s+=this.key,window["callFunctions"+this.key]=(e,t)=>{let s=this.functions.find((t=>t.ref===e));s&&s.func(t)},this.functions.find((e=>e.ref===s))||this.functions.push({ref:s,func:e}),t?e:`((event)=>{callFunctions${this.key} ? callFunctions${this.key}('${s}', event) : null})(event)`}setState(e,t){this.state=e,this.hydrate(t)}useState(e,t){this.state.hasOwnProperty(e)||(this.state[e]=t);return[(()=>this.state[e])(),(t,s)=>{this.state[e]=t,this.hydrate(s)}]}useRef(e=null,t){this.state[e]||(this.state[e]=t);return{bind:e+this.key,current:(()=>document.querySelector(`[ref="${e+this.key}"]`)||t)()}}useReducer(e=null,t,s=null){this.state[e]||(this.state[e]=t);const r=()=>this.state[e];let n=r();return[r(),(t,i)=>{const o=s(n,t)??t;this.state[e]=o,this.hydrate(i),n=r()}]}render(){}checkIFMounted(){new MutationObserver((e=>{e.forEach((e=>{e.target.querySelector(`[key="${this.key}"]`)&&!this.mounted&&(this.onMount(),this.mounted=!0),Array.from(e.removedNodes).find((e=>e.attributes&&e.attributes.key&&e.attributes.key.value===this.key))&&(this.onUnmount(),this.reset())}))})).observe(document.body,{childList:!0,subtree:!0})}onMount(){}onUnmount(){}}export const useState=(e,t)=>{this.state[e]||(this.state[e]=t);return[states[e],(t,s)=>{states[e]=t,this.hydrate(s)}]};export const useReducer=(e,t)=>[e,e=>{}];export const useRef=e=>({current:e,bind:""});export class Link extends Component{constructor(e){super(e),this.props=e,this.link=document.createElement("a"),this.key=e.href+Math.random(),this.nokey=!0}render(){return this.link.innerHTML=this.props.children,this.link.setAttribute("id",this.props?.href),this.link.style=this.props?.style,this.link.setAttribute("class",this.props?.class||this.props?.className),this.link.setAttribute("onclick",this.props?.href?.includes("https")||this.props?.href?.includes("http")?`window.open('${this.props.href}', '${this.props.action||"_blank"}').focus()`:`window.history.pushState({}, '', '${this.props?.href}'); window.dispatchEvent(new Event('popstate'));`),this.link.outerHTML}}export class Image extends Component{constructor(e){super(e),this.props={src:e.src,class:e.class,style:e.style,blur:e.blur,width:e.width,height:e.height,optimize:e.optimize||!0,loader:e.loader||!0,alt:e.alt||"image",ref:e.ref||null},this.key=e.src+Math.random(),this.img=document.createElement("img"),this.placeholder=document.createElement("div")}render(){if(window.isServer)return"";let[e,t]=this.useState("loaded",!1),s=this.useRef("hookref",null),r=this.props.width?this.props.width:window.innerWidth/2,n=this.props.height?this.props.height:window.innerHeight/2;if(!this.props.src)throw new Error("Image src is required");return this.img.setAttribute("src",this.props.src),this.img.setAttribute("class",this.props.class),this.img.setAttribute("style",this.props.style?this.props.style:""),this.img.setAttribute("width",r),this.img.setAttribute("ref",s.bind),this.img.referrerPolicy="no-referrer",this.img.setAttribute("height",n),this.img.setAttribute("loading","lazy"),this.img.setAttribute("alt",this.props.alt),this.props.blur&&this.img.setAttribute("style",`filter: blur(${this.props.blur}px);`),this.props.optimize&&this.img.setAttribute("style",`image-rendering: -webkit-optimize-contrast; object-fit: cover; object-position: center; ${this.props.style?this.props.style:""}`),!this.props.loader||e||window.isServer||(this.placeholder.setAttribute("style",`width: ${r}px; height: ${n}px; background: #eee;`),this.placeholder.setAttribute("class","vader-image-placeholder"),this.placeholder.innerHTML=this.props.loader,window.isServer)?void 0:(this.img.onload=()=>{t(!0,s.bind)},`<span ref="${s.bind}">${e?this.img.outerHTML:this.placeholder.outerHTML}</span>`)}}export class Html extends Component{constructor(e){super(e),this.props={children:e.children,lang:e.lang||"en",attributes:e.attributes||{}},this.key="html",this.html=document.createElement("div")}render(){return this.html.setAttribute("lang",this.props.lang?this.props.lang:"en"),window.isServer?(this.html.innerHTML=this.props.children,this.props.attributes&&Object.keys(this.props.attributes).forEach((e=>{this.html.setAttribute(e,this.props.attributes[e])})),this.html.innerHTML):this.props.children}onMount(){console.log("Document Has Been Mounted")}}export class Head extends Component{constructor(e){super(e),this.props=e,this.key="head",this.head=document.createElement("head"),this.eagerScripts=document.querySelectorAll("script[eager]")}render(){if(!window.isServer&&this.props?.updateOnReload){this.props.children=(new DOMParser).parseFromString(this.props.children,"text/html").head;let e=this.props.children.querySelector("title");e&&e.textContent&&(console.log("title",e.textContent),document.querySelector("title").textContent=e.textContent),this.props.children.querySelectorAll("meta").forEach((e=>{let t=e.getAttribute("name"),s=e.getAttribute("content");t&&s&&document.querySelector(`meta[name="${t}"]`).setAttribute("content",s)})),this.props.children.querySelectorAll("link").forEach((e=>{let t=e.getAttribute("rel"),s=e.getAttribute("href");t&&s&&document.querySelector(`link[rel="${t}"]`).setAttribute("href",s)}))}return""}onMount(){if(!this.state.hasMounted&&window.isServer){document.head.innerHTML=this.props.children+document.head.innerHTML,document.querySelectorAll("script[eager]").forEach((async e=>{if(!e.getAttribute("src"))throw new Error("Eager scripts must be external");e.remove();let t=e.getAttribute("src"),s=document.createElement("script"),r=null;await fetch(t).then((e=>{if(404===e.status)throw document.documentElement.setAttribute("error",JSON.stringify({error:`File ${t} not found`,status:404})),new Error(`File ${t} not found`);return e.text()})).then((e=>{r=e})).catch((e=>{throw e})),s.innerHTML=r,s.setAttribute("srcid",t),document.querySelector(`[srcid="${t}"]`)||document.head.prepend(s)})),this.state.hasMounted=!0}}}export class Script extends Component{constructor(e){super(e),this.props={children:e.children},this.key="script",this.script=document.createElement("script")}render(){return this.script.innerHTML=this.props.children.split("\n").join(";\n"),this.script.outerHTML}onMount(){document.head.appendChild(this.script),document.body.querySelector(`[key="${this.key}"]`).remove()}}export default{Component:Component,useRef:useRef,useReducer:useReducer,useState:useState,strictMount:strictMount,Link:Link,Image:Image,Head:Head,Script:Script,Html:Html};
package/vader.js CHANGED
@@ -84,7 +84,7 @@ function Compiler(func, file) {
84
84
  const spreadAttributeRegex = /\s*([a-zA-Z0-9_-]+)\s*(\$\s*=\s*\{\s*\{(?:[^{}]|(?:\{(?:[^{}]|(?:\{[^{}]*\})*)*\})*)*\}\s*\})/gs;
85
85
 
86
86
 
87
-
87
+ string = parseComponents(string);
88
88
 
89
89
  function extractAttributes(code) {
90
90
  // grab $={...} and ={...}
@@ -117,6 +117,30 @@ function Compiler(func, file) {
117
117
  let functionAttributes = [];
118
118
  let spreadFunctions = [];
119
119
  let functionMatch;
120
+
121
+ /**
122
+ * @search - handle attributes for html elements
123
+ * @keywords - attributes, props, html attributes
124
+ */
125
+ let match;
126
+ while ((match = elementRegex.exec(string)) !== null) {
127
+ let [, element, attributes] = match;
128
+
129
+
130
+ let attributesMatch;
131
+ let elementAttributes = {};
132
+
133
+ while ((attributesMatch = attributeRegex.exec(attributes)) !== null) {
134
+ let [, attributeName, attributeValue] = attributesMatch;
135
+
136
+ elementAttributes[attributeName] = attributeValue || null;
137
+ }
138
+
139
+ attributesList.push({ element, attributes: elementAttributes });
140
+ }
141
+
142
+
143
+
120
144
  while ((functionMatch = functionAttributeRegex.exec(code)) !== null) {
121
145
 
122
146
  let [, attributeName, attributeValue] = functionMatch;
@@ -200,8 +224,9 @@ function Compiler(func, file) {
200
224
  newvalue = newvalue.replaceAll(/\n/g, ";\n")
201
225
  // remove () from newvalue
202
226
  newvalue = newvalue.replace(/\(\s*=>/gs, '=>').replace(/\function\s*\([^\)]*\)\s*\{/gs, '{')
227
+ newvalue = newvalue + `\n /**@id=${ref}**/ \n`
203
228
 
204
- let bind = isJSXComponent ? `${attributeName}='function(${params}){${newvalue}}'` : `${attributeName}="\$\{this.bind(function(){${newvalue}}.bind(this), ${isJSXComponent}, "${ref}", "${paramnames ? paramnames.map((e, index) => {
229
+ let bind = !isJSXComponent && `${attributeName}="\$\{this.bind(function(){${newvalue}}.bind(this), ${isJSXComponent}, "${ref}", "${paramnames ? paramnames.map((e, index) => {
205
230
  if (e.length < 1) return ''
206
231
  if (e.length > 0) {
207
232
  index == 0 ? e : ',' + e
@@ -209,83 +234,8 @@ function Compiler(func, file) {
209
234
  return e
210
235
  }) : ''}" ${params ? params.split(',').map((e) => e.trim()).filter(Boolean).map((e) => `,${e}`).join('') : ''})}"`
211
236
 
212
- string = string.replace(old, bind);
213
- }
214
- }
215
-
216
- /**
217
- * @search - handle attributes for html elements
218
- * @keywords - attributes, props, html attributes
219
- */
220
- let match;
221
- while ((match = elementRegex.exec(string)) !== null) {
222
- let [, element, attributes] = match;
223
-
224
-
225
- let attributesMatch;
226
- let elementAttributes = {};
227
-
228
- while ((attributesMatch = attributeRegex.exec(attributes)) !== null) {
229
- let [, attributeName, attributeValue] = attributesMatch;
230
-
231
- elementAttributes[attributeName] = attributeValue || null;
237
+ string = string.replace(old, bind)
232
238
  }
233
-
234
- attributesList.push({ element, attributes: elementAttributes });
235
- }
236
-
237
- let spreadMatch;
238
- while ((spreadMatch = spreadAttributeRegex.exec(code)) !== null) {
239
- let [, element, spread] = spreadMatch;
240
- let isJSXComponent = element.match(/^[A-Z]/) ? true : false;
241
- if (isJSXComponent) {
242
- continue;
243
- }
244
- let old = spread;
245
- spread = spread.trim().replace(/\s+/g, " ");
246
- // re,pve $={ and }
247
- spread = spread.replace(/\s*\$\s*=\s*{\s*{/gs, '')
248
-
249
- // replace trailing }
250
- spread = spread.replace(/}}\s*$/, '').replace(/}\s*}$/, '')
251
- let splitByCommas = spread.split(/,(?![^{}]*})/gs)
252
- // remove empty strings
253
- splitByCommas = splitByCommas.filter((e) => e.split(':')[0].trim().length > 0)
254
- splitByCommas = splitByCommas.map((e, index) => {
255
- let key = e.split(':')[0].trim()
256
- switch (true) {
257
- case e.includes('function') && !e.includes('this.bind') || e && e.includes('=>') && !e.includes('this.bind'):
258
- let value = e.split(':')[1].trim()
259
- let ref = Math.random().toString(36).substring(2).split('').filter((e) => !Number(e)).join('');
260
- value = `this.bind(${value}, false, "${ref}", "")`
261
- e = `${key}="\${${value}}"`
262
- break;
263
- case e.includes('style:'):
264
- let v2 = e.split('style:')[1].trim().replace(/,$/, '')
265
- v2 = v2.replace(/,$/, '')
266
- e = `${key}="\${this.parseStyle(${v2})}"`
267
- break;
268
-
269
- default:
270
- let v = e.split(':')
271
- key = v[0].trim()
272
- // remove key from v
273
- v.shift()
274
- v = v.join(' ')
275
- e = `${key}="\${${v}}"`
276
-
277
- break;
278
- }
279
-
280
-
281
- return e;
282
- });
283
-
284
-
285
- let newSpread = splitByCommas.join(' ').trim().replace(/,$/, '');
286
-
287
- // remove trailing }
288
- string = string.replace(old, newSpread);
289
239
  }
290
240
 
291
241
  return attributesList;
@@ -410,9 +360,15 @@ function Compiler(func, file) {
410
360
  switch (true) {
411
361
  case line.includes("useState") && !line.includes("import"):
412
362
  let varType = line.split("[")[0]
363
+ if (!line.split("=")[0].split(",")[1]) {
364
+ throw new Error('You forgot to value selector (useState) ' + ' at ' + `${file}:${string.split(line)[0].split('\n').length}`)
365
+ }
413
366
  let key = line.split("=")[0].split(",")[0].trim().split('[')[1];
414
367
 
415
- let setKey = line.split("=")[0].trim().split(",")[1].trim().replace("]", "");
368
+ if (!line.split("=")[0].split(",")[1]) {
369
+ throw new Error('You forgot to add a setter (useState) ' + ' at ' + `${file}:${string.split(line)[0].split('\n').length}`)
370
+ }
371
+ let setKey = line.split("=")[0].split(",")[1].trim().replace("]", "");
416
372
  key = key.replace("[", "").replace(",", "");
417
373
  let valuestate = line.split("=")[1].split("useState(")[1];
418
374
 
@@ -481,37 +437,71 @@ function Compiler(func, file) {
481
437
  let myChildrens = [];
482
438
 
483
439
  let name = component.split("<")[1].split(">")[0].split(" ")[0].replace("/", "");
484
- let componentAttributes = component.split("<")[1].split(">")[0].split(" ").join(" ").replace(name, "").trim();
485
- let props = component.includes('/>')? component.split(`<`)[1].split('/>')[0] : component.split(`<`)[1].split(`>`)[1].split(`</${name}`)[0].trim()
440
+ let componentAttributes = component.split("<")[1].split(">")[0].split(" ").join(" ").replace(name, "").trim();
441
+ let props = component.includes('/>') ? component.split(`<`)[1].split('/>')[0] : component.split(`<`)[1].split(`>`)[0]
486
442
  props = props.replaceAll(/\s+/g, " ").trim()
487
443
  props = props.replace(name, '').trim()
488
444
  component = component.replace(componentAttributes, '')
489
- const dynamicAttributesRegex = /([a-zA-Z0-9_-]+)\s*=\s*("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|\{(?:[^{}]|(?:\{(?:[^{}]|(?:\{(.*.*?)\})*)*\})*)*\}|(?:\([^)]*\)|()\s*=>\s*(?:\{.*.*\})?|\{.*\})|\[[^\]]*\])/gs;
445
+ // or spread attributes {...{}, ...{}}
446
+ const dynamicAttributesRegex = /([a-zA-Z0-9_-]+)\s*=\s*("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|\{(?:[^{}]|(?:\{(?:[^{}]|(?:\{(.*.*?)\})*)*\})*)*\}|(?:\([^)]*\)|()\s*=>\s*(?:\{.*.*\})?|\{.*\})|\[[^\]]*\])|\${\{.*\}}/gs;
490
447
 
491
448
  const attributeObject = {};
492
-
449
+ let propstring = ''
493
450
  let $_ternaryprops = []
451
+ let spreadRegex = /\$\{.*\}/gs;
452
+ let spreadMatch;
453
+ let hasSpread = false;
454
+ while ((spreadMatch = spreadRegex.exec(props)) !== null) {
455
+ let spread = spreadMatch[0].trim().replace(/\s+/g, " ");
456
+ if (!spread.includes('...')) {
457
+ continue
458
+ }
459
+ let old = spread;
460
+ spread = spread.trim().replace(/\s+/g, " ");
461
+ //${...( loaded ? { title: "Malik Whitten - Blog" } : { title: "Loading" } )} -> ...( loaded ? { title: "Malik Whitten - Blog" } : { title: "Loading" } )
462
+
463
+ let spreadContent = spread.match(/\$\{.*\}/gs) ? spread.match(/\$\{.*.*\}/gs)[0] : null
464
+ spreadContent = spread.split('${')[1]
465
+
466
+ spreadContent = spread.replace(/\${/, '')
467
+ spreadContent = spreadContent.replaceAll(/\s+/g, " ").trim()
468
+ spreadContent = spreadContent.replace(')}', ')').replace('}}', '}')
469
+
470
+ propstring += spreadContent + ','
471
+ hasSpread = true
472
+
473
+ }
494
474
 
495
475
  let match;
496
- let propstring = ''
476
+
497
477
  // props right now is just a string with all of them on one line and a space between each
498
478
  while ((match = dynamicAttributesRegex.exec(props)) !== null) {
499
479
  let str = match[0].trim().replace(/\s+/g, " ");
500
480
  if (!str.includes('=')) {
501
481
  continue
502
- }
503
-
504
-
505
- str = str.replaceAll(/\s+/g, " ")
482
+ }
483
+
484
+ if (hasSpread) {
485
+
486
+ console.log('\x1b[33m', '🚨 Code confliction detected', '\x1b[0m')
487
+ let line = string.split(match[0])[0].split('\n').length
488
+ try {
489
+ throw new Error('You cannot use spread props and named props\n on the same component at ' + match[0] + ' at ' + `${file}:${line}`)
490
+ } catch (error) {
491
+ console.error(error)
492
+ process.exit(1)
493
+ }
494
+ }
495
+
496
+ str = str.replaceAll(/\s+/g, " ")
506
497
  str = str.split('=')
507
- let key = str[0].trim()
498
+ let key = str[0].trim()
508
499
  let value = str.slice(1).join('=').trim().match(/\{.*\}/gs) ? str.slice(1).join('=').trim().match(/\{.*\}/gs)[0] : str.slice(1).join('=').trim();
509
500
 
510
-
511
-
501
+
512
502
  let isObject = value.startsWith('{{') && value.endsWith('}}')
513
- if (isObject) {
514
- value = value.split('{{')[1].split('}}')[0].trim()
503
+ if (isObject) {
504
+ value = value.split('{{')[1].split('}}')[0].trim()
515
505
  value = `{${value}}`
516
506
  propstring += `${key}:${value},`
517
507
  } else {
@@ -519,7 +509,8 @@ function Compiler(func, file) {
519
509
  value = value.replace(/^{/, '').replace(/}$/, '')
520
510
  propstring += `${key}:${value},`
521
511
  }
522
-
512
+ propstring = propstring.replaceAll(/\s+/g, " ").trim()
513
+
523
514
  }
524
515
  component = component.replaceAll(/\s+/g, " ");
525
516
 
@@ -587,7 +578,7 @@ function Compiler(func, file) {
587
578
  let replaceMents = [];
588
579
 
589
580
 
590
- if(imports){
581
+ if (imports) {
591
582
  for (let match of imports) {
592
583
  let path = match.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').trim()
593
584
  switch (true) {
@@ -597,11 +588,11 @@ function Compiler(func, file) {
597
588
  if (!fs.existsSync(process.cwd() + componentFolder)) {
598
589
  throw new Error('Could not find ' + path + ' at ' + match + ' in file ' + file)
599
590
  }
600
-
591
+
601
592
  if (!fs.existsSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'))) {
602
593
  fs.mkdirSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'), { recursive: true })
603
594
  }
604
-
595
+
605
596
  let baseFolder = componentFolder.split('node_modules')[1].split('/')[1]
606
597
  let glp = globSync('**/**/**/**.{jsx,js}', {
607
598
  cwd: process.cwd() + '/node_modules/' + baseFolder + '/',
@@ -612,7 +603,7 @@ function Compiler(func, file) {
612
603
  let text = fs.readFileSync(file, "utf8");
613
604
  if (!file.endsWith('.js') && file.endsWith('.jsx')) {
614
605
  text = Compiler(text, file);
615
-
606
+
616
607
  }
617
608
  let dest = file.split('node_modules')[1]
618
609
  dest = dest.split(baseFolder)[1]
@@ -624,8 +615,8 @@ function Compiler(func, file) {
624
615
  replaceMents.push({ match: oldImportstring, replace: newImport })
625
616
  console.log(`📦 imported Node Package ${baseFolder} `)
626
617
  }
627
-
628
-
618
+
619
+
629
620
  break;
630
621
  default:
631
622
  break;
@@ -650,7 +641,7 @@ function Compiler(func, file) {
650
641
  string = string.replaceAll(/\$\{\/\*.*\*\/\}/gs, "");
651
642
  string = string.replaceAll("<>", "`").replaceAll("</>", "`");
652
643
  string = string.replaceAll(".jsx", ".js");
653
- string = parseComponents(string);
644
+
654
645
 
655
646
  string = string
656
647
  .replaceAll("className", "class")
@@ -902,7 +893,7 @@ async function Build() {
902
893
  page.on('crash', () => {
903
894
  console.error(`Render process crashed for ${route.url}`)
904
895
  });
905
-
896
+
906
897
  await page.goto(`http://localhost:${port}${route.url}`, { waitUntil: 'networkidle2' });
907
898
 
908
899
  page.evaluate(() => {
@@ -946,8 +937,8 @@ async function Build() {
946
937
  browser.close()
947
938
  })
948
939
  hasRendered = []
949
- globalThis.isBuilding = false
950
-
940
+ globalThis.isBuilding = false
941
+
951
942
  }
952
943
 
953
944
  if (hasRendered.length === routes.length) {
@@ -963,6 +954,7 @@ async function Build() {
963
954
  }
964
955
  }
965
956
  globalThis.routes = []
957
+ globalThis.paramRoutes = []
966
958
 
967
959
  for await (let file of glb) {
968
960
  // Normalize file paths
@@ -1061,7 +1053,10 @@ async function Build() {
1061
1053
  }
1062
1054
 
1063
1055
 
1064
- if (!obj.url.includes(':')) {
1056
+ if (obj.url.includes(':') && !paramRoutes.includes(obj.url)) {
1057
+ globalThis.paramRoutes.push({ fileName: fileName, url: obj.url, html: '/' + (isBasePath ? 'index.html' : `${obj.url}/` + 'index.html') })
1058
+ } else {
1059
+
1065
1060
  globalThis.routes.push({ fileName: fileName, url: obj.url, html: '/' + (isBasePath ? 'index.html' : `${obj.url}/` + 'index.html') })
1066
1061
  }
1067
1062
 
@@ -1082,7 +1077,8 @@ async function Build() {
1082
1077
 
1083
1078
  globalThis.routeDocuments = []
1084
1079
  globalThis.routes.map((route) => {
1085
- let equalparamroute = globalThis.routes.map((e) => {
1080
+ let equalparamroute = globalThis.paramRoutes.map((e) => {
1081
+ console
1086
1082
  if (e.url.includes(':')) {
1087
1083
  let url = e.url.split('/:')[0]
1088
1084
  if (url && route.url === url) {
@@ -1157,13 +1153,13 @@ async function Build() {
1157
1153
  `;
1158
1154
  globalThis.routeDocuments.push({ url: route.url, document: document })
1159
1155
  })
1160
-
1161
- if(globalThis.devMode && !globalThis.oneAndDone){
1156
+
1157
+ if (globalThis.devMode && !globalThis.oneAndDone) {
1162
1158
  ssg(globalThis.routes)
1163
1159
  globalThis.oneAndDone = true
1164
1160
  console.log(`In Development Mode, Prerendering ${globalThis.routes.length} pages... Once`)
1165
- }
1166
- else if(globalThis.isProduction){
1161
+ }
1162
+ else if (globalThis.isProduction) {
1167
1163
  ssg(globalThis.routes)
1168
1164
  }
1169
1165
 
@@ -1248,7 +1244,7 @@ async function Build() {
1248
1244
  let data = await reader(process.cwd() + "/node_modules/vaderjs/runtime/" + file)
1249
1245
  await writer(process.cwd() + "/dist/" + file, data);
1250
1246
  });
1251
-
1247
+
1252
1248
 
1253
1249
  }
1254
1250
 
@@ -1344,7 +1340,7 @@ const s = (port) => {
1344
1340
  return 'application/octet-stream';
1345
1341
  }
1346
1342
  }
1347
-
1343
+
1348
1344
  server.listen(port, () => {
1349
1345
  console.log(`Server is running on port ${port}`);
1350
1346
  globalThis.ws = ws
@@ -1359,7 +1355,7 @@ switch (true) {
1359
1355
 
1360
1356
  globalThis.devMode = true
1361
1357
  globalThis.isProduction = false
1362
-
1358
+
1363
1359
  let p = process.env.PORT || config.port || process.argv.includes('-p') ? process.argv[process.argv.indexOf('-p') + 1] : 3000
1364
1360
  globalThis.oneAndDone = false
1365
1361
  console.log(`
@@ -1391,7 +1387,7 @@ Vader.js v${fs.readFileSync(process.cwd() + '/node_modules/vaderjs/package.json'
1391
1387
  Build()
1392
1388
  }
1393
1389
  }).on('error', (err) => console.log(err))
1394
- })
1390
+ })
1395
1391
  s(p)
1396
1392
 
1397
1393
  globalThis.listen = true;