vaderjs 1.3.3-7u27417d42e1 → 1.3.3-7y27417d42e1

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-7u27417d42e1",
5
+ "version": "1.3.3-7y27417d42e1",
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
@@ -117,7 +117,7 @@ function Compiler(func, file) {
117
117
  let functionAttributes = [];
118
118
  let spreadFunctions = [];
119
119
  let functionMatch;
120
-
120
+
121
121
  /**
122
122
  * @search - handle attributes for html elements
123
123
  * @keywords - attributes, props, html attributes
@@ -139,59 +139,7 @@ function Compiler(func, file) {
139
139
  attributesList.push({ element, attributes: elementAttributes });
140
140
  }
141
141
 
142
- let spreadMatch;
143
- while ((spreadMatch = spreadAttributeRegex.exec(code)) !== null) {
144
- let [, element, spread] = spreadMatch;
145
- let isJSXComponent = element.match(/^[A-Z]/) ? true : false;
146
- if (isJSXComponent) {
147
- continue;
148
- }
149
- let old = spread;
150
- spread = spread.trim().replace(/\s+/g, " ");
151
- // re,pve $={ and }
152
- spread = spread.replace(/\s*\$\s*=\s*{\s*{/gs, '')
153
-
154
- // replace trailing }
155
- spread = spread.replace(/}}\s*$/, '').replace(/}\s*}$/, '')
156
- let splitByCommas = spread.split(/,(?![^{}]*})/gs)
157
- // remove empty strings
158
- splitByCommas = splitByCommas.filter((e) => e.split(':')[0].trim().length > 0)
159
- splitByCommas = splitByCommas.map((e, index) => {
160
- let key = e.split(':')[0].trim()
161
- switch (true) {
162
- case e.includes('function') && !e.includes('this.bind') || e && e.includes('=>') && !e.includes('this.bind'):
163
- let value = e.split(':')[1].trim()
164
- let ref = Math.random().toString(36).substring(2).split('').filter((e) => !Number(e)).join('');
165
- value = `this.bind(${value}, false, "${ref}", "")`
166
- e = `${key}="\${${value}}"`
167
- break;
168
- case e.includes('style:'):
169
- let v2 = e.split('style:')[1].trim().replace(/,$/, '')
170
- v2 = v2.replace(/,$/, '')
171
- e = `${key}="\${this.parseStyle(${v2})}"`
172
- break;
173
-
174
- default:
175
- let v = e.split(':')
176
- key = v[0].trim()
177
- // remove key from v
178
- v.shift()
179
- v = v.join(' ')
180
- e = `${key}="\${${v}}"`
181
-
182
- break;
183
- }
184
-
185
-
186
- return e;
187
- });
188
-
189
142
 
190
- let newSpread = splitByCommas.join(' ').trim().replace(/,$/, '');
191
-
192
- // remove trailing }
193
- string = string.replace(old, newSpread);
194
- }
195
143
 
196
144
  while ((functionMatch = functionAttributeRegex.exec(code)) !== null) {
197
145
 
@@ -216,17 +164,17 @@ function Compiler(func, file) {
216
164
  .split("<")[1]
217
165
  .split(">")[0]
218
166
  .split(" ")[0];
219
- isJSXComponent = elementTag.match(/^[A-Z]/) ? true : false;
167
+ isJSXComponent = elementTag.match(/^[A-Z]/) ? true : false;
220
168
  }
221
169
  });
222
- if (isJSXComponent) {
170
+ if (isJSXComponent) {
223
171
  continue
224
172
  }
225
173
  // add ; after newlines
226
174
 
227
175
 
228
176
  let newvalue = attributeValue.includes('=>') ? attributeValue.split("=>").slice(1).join("=>").trim() : attributeValue.split("function").slice(1).join("function").trim()
229
-
177
+
230
178
  // add ; after newlines
231
179
 
232
180
 
@@ -278,14 +226,14 @@ function Compiler(func, file) {
278
226
  newvalue = newvalue.replace(/\(\s*=>/gs, '=>').replace(/\function\s*\([^\)]*\)\s*\{/gs, '{')
279
227
  newvalue = newvalue + `\n /**@id=${ref}**/ \n`
280
228
 
281
- let bind = !isJSXComponent && `${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) => {
282
230
  if (e.length < 1) return ''
283
231
  if (e.length > 0) {
284
232
  index == 0 ? e : ',' + e
285
233
  }
286
234
  return e
287
235
  }) : ''}" ${params ? params.split(',').map((e) => e.trim()).filter(Boolean).map((e) => `,${e}`).join('') : ''})}"`
288
-
236
+
289
237
  string = string.replace(old, bind)
290
238
  }
291
239
  }
@@ -412,9 +360,15 @@ function Compiler(func, file) {
412
360
  switch (true) {
413
361
  case line.includes("useState") && !line.includes("import"):
414
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
+ }
415
366
  let key = line.split("=")[0].split(",")[0].trim().split('[')[1];
416
367
 
417
- 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("]", "");
418
372
  key = key.replace("[", "").replace(",", "");
419
373
  let valuestate = line.split("=")[1].split("useState(")[1];
420
374
 
@@ -483,37 +437,73 @@ function Compiler(func, file) {
483
437
  let myChildrens = [];
484
438
 
485
439
  let name = component.split("<")[1].split(">")[0].split(" ")[0].replace("/", "");
486
- let componentAttributes = component.split("<")[1].split(">")[0].split(" ").join(" ").replace(name, "").trim();
487
- let props = component.includes('/>')? component.split(`<`)[1].split('/>')[0] : component.split(`<`)[1].split(`>`)[0]
488
- props = props.replaceAll(/\s+/g, " ").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]
442
+ props = props.replaceAll(/\s+/g, " ").trim()
489
443
  props = props.replace(name, '').trim()
490
444
  component = component.replace(componentAttributes, '')
491
- 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;
492
447
 
493
448
  const attributeObject = {};
494
-
449
+ let propstring = ''
495
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
+ // get last most } and remove it
472
+ propstring = propstring.slice(0, -1)
473
+ hasSpread = true
474
+
475
+ }
496
476
 
497
477
  let match;
498
- let propstring = ''
478
+
499
479
  // props right now is just a string with all of them on one line and a space between each
500
480
  while ((match = dynamicAttributesRegex.exec(props)) !== null) {
501
481
  let str = match[0].trim().replace(/\s+/g, " ");
502
482
  if (!str.includes('=')) {
503
483
  continue
504
- }
505
-
506
-
507
- str = str.replaceAll(/\s+/g, " ")
484
+ }
485
+
486
+ if (hasSpread) {
487
+
488
+ console.log('\x1b[33m', '🚨 Code confliction detected', '\x1b[0m')
489
+ let line = string.split(match[0])[0].split('\n').length
490
+ try {
491
+ throw new Error('You cannot use spread props and named props\n on the same component at ' + match[0] + ' at ' + `${file}:${line}`)
492
+ } catch (error) {
493
+ console.error(error)
494
+ process.exit(1)
495
+ }
496
+ }
497
+
498
+ str = str.replaceAll(/\s+/g, " ")
508
499
  str = str.split('=')
509
- let key = str[0].trim()
500
+ let key = str[0].trim()
510
501
  let value = str.slice(1).join('=').trim().match(/\{.*\}/gs) ? str.slice(1).join('=').trim().match(/\{.*\}/gs)[0] : str.slice(1).join('=').trim();
511
-
512
-
513
-
502
+
503
+
514
504
  let isObject = value.startsWith('{{') && value.endsWith('}}')
515
- if (isObject) {
516
- value = value.split('{{')[1].split('}}')[0].trim()
505
+ if (isObject) {
506
+ value = value.split('{{')[1].split('}}')[0].trim()
517
507
  value = `{${value}}`
518
508
  propstring += `${key}:${value},`
519
509
  } else {
@@ -522,8 +512,8 @@ function Compiler(func, file) {
522
512
  propstring += `${key}:${value},`
523
513
  }
524
514
  propstring = propstring.replaceAll(/\s+/g, " ").trim()
525
-
526
- }
515
+
516
+ }
527
517
  component = component.replaceAll(/\s+/g, " ");
528
518
 
529
519
  component = component.replace(componentAttributes, '')
@@ -590,7 +580,7 @@ function Compiler(func, file) {
590
580
  let replaceMents = [];
591
581
 
592
582
 
593
- if(imports){
583
+ if (imports) {
594
584
  for (let match of imports) {
595
585
  let path = match.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').trim()
596
586
  switch (true) {
@@ -600,11 +590,11 @@ function Compiler(func, file) {
600
590
  if (!fs.existsSync(process.cwd() + componentFolder)) {
601
591
  throw new Error('Could not find ' + path + ' at ' + match + ' in file ' + file)
602
592
  }
603
-
593
+
604
594
  if (!fs.existsSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'))) {
605
595
  fs.mkdirSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'), { recursive: true })
606
596
  }
607
-
597
+
608
598
  let baseFolder = componentFolder.split('node_modules')[1].split('/')[1]
609
599
  let glp = globSync('**/**/**/**.{jsx,js}', {
610
600
  cwd: process.cwd() + '/node_modules/' + baseFolder + '/',
@@ -615,7 +605,7 @@ function Compiler(func, file) {
615
605
  let text = fs.readFileSync(file, "utf8");
616
606
  if (!file.endsWith('.js') && file.endsWith('.jsx')) {
617
607
  text = Compiler(text, file);
618
-
608
+
619
609
  }
620
610
  let dest = file.split('node_modules')[1]
621
611
  dest = dest.split(baseFolder)[1]
@@ -627,8 +617,8 @@ function Compiler(func, file) {
627
617
  replaceMents.push({ match: oldImportstring, replace: newImport })
628
618
  console.log(`📦 imported Node Package ${baseFolder} `)
629
619
  }
630
-
631
-
620
+
621
+
632
622
  break;
633
623
  default:
634
624
  break;
@@ -653,7 +643,7 @@ function Compiler(func, file) {
653
643
  string = string.replaceAll(/\$\{\/\*.*\*\/\}/gs, "");
654
644
  string = string.replaceAll("<>", "`").replaceAll("</>", "`");
655
645
  string = string.replaceAll(".jsx", ".js");
656
-
646
+
657
647
 
658
648
  string = string
659
649
  .replaceAll("className", "class")
@@ -905,7 +895,7 @@ async function Build() {
905
895
  page.on('crash', () => {
906
896
  console.error(`Render process crashed for ${route.url}`)
907
897
  });
908
-
898
+
909
899
  await page.goto(`http://localhost:${port}${route.url}`, { waitUntil: 'networkidle2' });
910
900
 
911
901
  page.evaluate(() => {
@@ -949,8 +939,8 @@ async function Build() {
949
939
  browser.close()
950
940
  })
951
941
  hasRendered = []
952
- globalThis.isBuilding = false
953
-
942
+ globalThis.isBuilding = false
943
+
954
944
  }
955
945
 
956
946
  if (hasRendered.length === routes.length) {
@@ -966,6 +956,7 @@ async function Build() {
966
956
  }
967
957
  }
968
958
  globalThis.routes = []
959
+ globalThis.paramRoutes = []
969
960
 
970
961
  for await (let file of glb) {
971
962
  // Normalize file paths
@@ -1064,7 +1055,10 @@ async function Build() {
1064
1055
  }
1065
1056
 
1066
1057
 
1067
- if (!obj.url.includes(':')) {
1058
+ if (obj.url.includes(':') && !paramRoutes.includes(obj.url)) {
1059
+ globalThis.paramRoutes.push({ fileName: fileName, url: obj.url, html: '/' + (isBasePath ? 'index.html' : `${obj.url}/` + 'index.html') })
1060
+ } else {
1061
+
1068
1062
  globalThis.routes.push({ fileName: fileName, url: obj.url, html: '/' + (isBasePath ? 'index.html' : `${obj.url}/` + 'index.html') })
1069
1063
  }
1070
1064
 
@@ -1085,7 +1079,8 @@ async function Build() {
1085
1079
 
1086
1080
  globalThis.routeDocuments = []
1087
1081
  globalThis.routes.map((route) => {
1088
- let equalparamroute = globalThis.routes.map((e) => {
1082
+ let equalparamroute = globalThis.paramRoutes.map((e) => {
1083
+ console
1089
1084
  if (e.url.includes(':')) {
1090
1085
  let url = e.url.split('/:')[0]
1091
1086
  if (url && route.url === url) {
@@ -1160,13 +1155,13 @@ async function Build() {
1160
1155
  `;
1161
1156
  globalThis.routeDocuments.push({ url: route.url, document: document })
1162
1157
  })
1163
-
1164
- if(globalThis.devMode && !globalThis.oneAndDone){
1158
+
1159
+ if (globalThis.devMode && !globalThis.oneAndDone) {
1165
1160
  ssg(globalThis.routes)
1166
1161
  globalThis.oneAndDone = true
1167
1162
  console.log(`In Development Mode, Prerendering ${globalThis.routes.length} pages... Once`)
1168
- }
1169
- else if(globalThis.isProduction){
1163
+ }
1164
+ else if (globalThis.isProduction) {
1170
1165
  ssg(globalThis.routes)
1171
1166
  }
1172
1167
 
@@ -1251,7 +1246,7 @@ async function Build() {
1251
1246
  let data = await reader(process.cwd() + "/node_modules/vaderjs/runtime/" + file)
1252
1247
  await writer(process.cwd() + "/dist/" + file, data);
1253
1248
  });
1254
-
1249
+
1255
1250
 
1256
1251
  }
1257
1252
 
@@ -1347,7 +1342,7 @@ const s = (port) => {
1347
1342
  return 'application/octet-stream';
1348
1343
  }
1349
1344
  }
1350
-
1345
+
1351
1346
  server.listen(port, () => {
1352
1347
  console.log(`Server is running on port ${port}`);
1353
1348
  globalThis.ws = ws
@@ -1362,7 +1357,7 @@ switch (true) {
1362
1357
 
1363
1358
  globalThis.devMode = true
1364
1359
  globalThis.isProduction = false
1365
-
1360
+
1366
1361
  let p = process.env.PORT || config.port || process.argv.includes('-p') ? process.argv[process.argv.indexOf('-p') + 1] : 3000
1367
1362
  globalThis.oneAndDone = false
1368
1363
  console.log(`
@@ -1394,7 +1389,7 @@ Vader.js v${fs.readFileSync(process.cwd() + '/node_modules/vaderjs/package.json'
1394
1389
  Build()
1395
1390
  }
1396
1391
  }).on('error', (err) => console.log(err))
1397
- })
1392
+ })
1398
1393
  s(p)
1399
1394
 
1400
1395
  globalThis.listen = true;