vaderjs 1.3.3-7b27417dd2e1 → 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-7b27417dd2e1",
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){switch(super(e),!0){case!e.href:throw new Error("Link href is required");case!e.children:throw new Error("Blank links are not allowed. Please add content to the link :}")}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")?`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
 
@@ -482,49 +438,79 @@ function Compiler(func, file) {
482
438
 
483
439
  let name = component.split("<")[1].split(">")[0].split(" ")[0].replace("/", "");
484
440
  let componentAttributes = component.split("<")[1].split(">")[0].split(" ").join(" ").replace(name, "").trim();
485
- // catchall = "" ={} =[]
486
-
487
-
488
- let props = component.split("<")[1].split(">")[0]
489
-
490
-
491
- const dynamicAttributesRegex = /([a-zA-Z0-9_-]+)\s*=\s*("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|\{(?:[^{}]|(?:\{(?:[^{}]|(?:\{.*.*\})*)*\})*)*\}|(?:\([^)]*\)|()\s*=>\s*(?:\{.*\})?|\{[^}]*\})|\[[^\]]*\])/gs;
441
+ let props = component.includes('/>') ? component.split(`<`)[1].split('/>')[0] : component.split(`<`)[1].split(`>`)[0]
442
+ props = props.replaceAll(/\s+/g, " ").trim()
443
+ props = props.replace(name, '').trim()
444
+ component = component.replace(componentAttributes, '')
445
+ // or spread attributes {...{}, ...{}}
446
+ const dynamicAttributesRegex = /([a-zA-Z0-9_-]+)\s*=\s*("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|\{(?:[^{}]|(?:\{(?:[^{}]|(?:\{(.*.*?)\})*)*\})*)*\}|(?:\([^)]*\)|()\s*=>\s*(?:\{.*.*\})?|\{.*\})|\[[^\]]*\])|\${\{.*\}}/gs;
492
447
 
493
448
  const attributeObject = {};
449
+ let propstring = ''
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" } )
494
462
 
463
+ let spreadContent = spread.match(/\$\{.*\}/gs) ? spread.match(/\$\{.*.*\}/gs)[0] : null
464
+ spreadContent = spread.split('${')[1]
495
465
 
496
- let filteredProps = [];
497
- let isWithinComponent = false;
498
- let componentName = name
499
- let currentProps = []
466
+ spreadContent = spread.replace(/\${/, '')
467
+ spreadContent = spreadContent.replaceAll(/\s+/g, " ").trim()
468
+ spreadContent = spreadContent.replace(')}', ')').replace('}}', '}')
500
469
 
501
- let $_ternaryprops = []
470
+ propstring += spreadContent + ','
471
+ hasSpread = true
472
+
473
+ }
502
474
 
503
475
  let match;
504
- let propstring = ''
476
+
505
477
  // props right now is just a string with all of them on one line and a space between each
506
478
  while ((match = dynamicAttributesRegex.exec(props)) !== null) {
507
479
  let str = match[0].trim().replace(/\s+/g, " ");
508
480
  if (!str.includes('=')) {
509
481
  continue
510
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, " ")
511
497
  str = str.split('=')
512
498
  let key = str[0].trim()
513
- let value = str[1].trim()
514
- if (value.startsWith('"') && !value.endsWith('"') || value.startsWith("'") && !value.endsWith("'")
515
- || value.startsWith('`') && !value.endsWith('`')) {
516
- // wrap in respective quotes
517
- value = value + value[0]
518
- }
499
+ let value = str.slice(1).join('=').trim().match(/\{.*\}/gs) ? str.slice(1).join('=').trim().match(/\{.*\}/gs)[0] : str.slice(1).join('=').trim();
500
+
501
+
519
502
  let isObject = value.startsWith('{{') && value.endsWith('}}')
520
503
  if (isObject) {
521
504
  value = value.split('{{')[1].split('}}')[0].trim()
522
505
  value = `{${value}}`
506
+ propstring += `${key}:${value},`
523
507
  } else {
524
508
  // remove starting { and ending } using regex
525
509
  value = value.replace(/^{/, '').replace(/}$/, '')
510
+ propstring += `${key}:${value},`
526
511
  }
527
- propstring += `${key}:${value},`
512
+ propstring = propstring.replaceAll(/\s+/g, " ").trim()
513
+
528
514
  }
529
515
  component = component.replaceAll(/\s+/g, " ");
530
516
 
@@ -592,7 +578,7 @@ function Compiler(func, file) {
592
578
  let replaceMents = [];
593
579
 
594
580
 
595
- if(imports){
581
+ if (imports) {
596
582
  for (let match of imports) {
597
583
  let path = match.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').trim()
598
584
  switch (true) {
@@ -602,11 +588,11 @@ function Compiler(func, file) {
602
588
  if (!fs.existsSync(process.cwd() + componentFolder)) {
603
589
  throw new Error('Could not find ' + path + ' at ' + match + ' in file ' + file)
604
590
  }
605
-
591
+
606
592
  if (!fs.existsSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'))) {
607
593
  fs.mkdirSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'), { recursive: true })
608
594
  }
609
-
595
+
610
596
  let baseFolder = componentFolder.split('node_modules')[1].split('/')[1]
611
597
  let glp = globSync('**/**/**/**.{jsx,js}', {
612
598
  cwd: process.cwd() + '/node_modules/' + baseFolder + '/',
@@ -617,7 +603,7 @@ function Compiler(func, file) {
617
603
  let text = fs.readFileSync(file, "utf8");
618
604
  if (!file.endsWith('.js') && file.endsWith('.jsx')) {
619
605
  text = Compiler(text, file);
620
-
606
+
621
607
  }
622
608
  let dest = file.split('node_modules')[1]
623
609
  dest = dest.split(baseFolder)[1]
@@ -629,8 +615,8 @@ function Compiler(func, file) {
629
615
  replaceMents.push({ match: oldImportstring, replace: newImport })
630
616
  console.log(`📦 imported Node Package ${baseFolder} `)
631
617
  }
632
-
633
-
618
+
619
+
634
620
  break;
635
621
  default:
636
622
  break;
@@ -655,7 +641,7 @@ function Compiler(func, file) {
655
641
  string = string.replaceAll(/\$\{\/\*.*\*\/\}/gs, "");
656
642
  string = string.replaceAll("<>", "`").replaceAll("</>", "`");
657
643
  string = string.replaceAll(".jsx", ".js");
658
- string = parseComponents(string);
644
+
659
645
 
660
646
  string = string
661
647
  .replaceAll("className", "class")
@@ -907,7 +893,7 @@ async function Build() {
907
893
  page.on('crash', () => {
908
894
  console.error(`Render process crashed for ${route.url}`)
909
895
  });
910
-
896
+
911
897
  await page.goto(`http://localhost:${port}${route.url}`, { waitUntil: 'networkidle2' });
912
898
 
913
899
  page.evaluate(() => {
@@ -952,8 +938,7 @@ async function Build() {
952
938
  })
953
939
  hasRendered = []
954
940
  globalThis.isBuilding = false
955
- globalThis.isProduction ? console.log(`Total Bundle Size: ${Math.round(bundleSize / 1000)}kb`) : null
956
- bundleSize = 0
941
+
957
942
  }
958
943
 
959
944
  if (hasRendered.length === routes.length) {
@@ -969,6 +954,7 @@ async function Build() {
969
954
  }
970
955
  }
971
956
  globalThis.routes = []
957
+ globalThis.paramRoutes = []
972
958
 
973
959
  for await (let file of glb) {
974
960
  // Normalize file paths
@@ -1067,7 +1053,10 @@ async function Build() {
1067
1053
  }
1068
1054
 
1069
1055
 
1070
- 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
+
1071
1060
  globalThis.routes.push({ fileName: fileName, url: obj.url, html: '/' + (isBasePath ? 'index.html' : `${obj.url}/` + 'index.html') })
1072
1061
  }
1073
1062
 
@@ -1088,7 +1077,8 @@ async function Build() {
1088
1077
 
1089
1078
  globalThis.routeDocuments = []
1090
1079
  globalThis.routes.map((route) => {
1091
- let equalparamroute = globalThis.routes.map((e) => {
1080
+ let equalparamroute = globalThis.paramRoutes.map((e) => {
1081
+ console
1092
1082
  if (e.url.includes(':')) {
1093
1083
  let url = e.url.split('/:')[0]
1094
1084
  if (url && route.url === url) {
@@ -1163,11 +1153,14 @@ async function Build() {
1163
1153
  `;
1164
1154
  globalThis.routeDocuments.push({ url: route.url, document: document })
1165
1155
  })
1166
-
1167
- if(globalThis.devMode && !globalThis.oneAndDone){
1156
+
1157
+ if (globalThis.devMode && !globalThis.oneAndDone) {
1168
1158
  ssg(globalThis.routes)
1169
1159
  globalThis.oneAndDone = true
1170
- console.log('Prerendering...')
1160
+ console.log(`In Development Mode, Prerendering ${globalThis.routes.length} pages... Once`)
1161
+ }
1162
+ else if (globalThis.isProduction) {
1163
+ ssg(globalThis.routes)
1171
1164
  }
1172
1165
 
1173
1166
 
@@ -1252,10 +1245,12 @@ async function Build() {
1252
1245
  await writer(process.cwd() + "/dist/" + file, data);
1253
1246
  });
1254
1247
 
1248
+
1255
1249
  }
1256
1250
 
1257
1251
  globalThis.isBuilding = false
1258
1252
 
1253
+ globalThis.isProduction ? console.log(`Total Bundle Size: ${Math.round(bundleSize / 1000)}kb`) : null
1259
1254
  bundleSize = 0;
1260
1255
 
1261
1256
  return true
@@ -1345,7 +1340,7 @@ const s = (port) => {
1345
1340
  return 'application/octet-stream';
1346
1341
  }
1347
1342
  }
1348
-
1343
+
1349
1344
  server.listen(port, () => {
1350
1345
  console.log(`Server is running on port ${port}`);
1351
1346
  globalThis.ws = ws
@@ -1360,7 +1355,7 @@ switch (true) {
1360
1355
 
1361
1356
  globalThis.devMode = true
1362
1357
  globalThis.isProduction = false
1363
-
1358
+
1364
1359
  let p = process.env.PORT || config.port || process.argv.includes('-p') ? process.argv[process.argv.indexOf('-p') + 1] : 3000
1365
1360
  globalThis.oneAndDone = false
1366
1361
  console.log(`
@@ -1392,7 +1387,7 @@ Vader.js v${fs.readFileSync(process.cwd() + '/node_modules/vaderjs/package.json'
1392
1387
  Build()
1393
1388
  }
1394
1389
  }).on('error', (err) => console.log(err))
1395
- })
1390
+ })
1396
1391
  s(p)
1397
1392
 
1398
1393
  globalThis.listen = true;