vaderjs 1.3.3-alpha-151 → 1.3.3-alpha-152

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.
Files changed (3) hide show
  1. package/package.json +1 -1
  2. package/runtime/vader.js +1 -1
  3. package/vader.js +235 -255
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-alpha-151",
5
+ "version": "1.3.3-alpha-152",
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=[],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(){this.state={},this.key=null,this.components={},this.mounted=!1,this.checkIFMounted(),this.memoizes=[],this.functions=[],this.children=[],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=new Component(t);if(r(e))n.props=t||{},n.props.children=s.join("")||[],n.props.children=s.join(""),n.parentNode=this,n.request=this.request,n.response=this.response,n.key=n.props.key?n.props.key:Math.random(),i=n;else{e.toString();i.key=e.toString().split('key="')[1]?e.toString().split('key="')[1].split('"')[0]:null;let r=[];Object.keys(t).forEach((e=>{e.startsWith("$props")&&(r.push(t[e]),delete t[e])})),t=t?{...t,...r.reduce(((e,t)=>({...e,...t})),{}),children:s.join("")||[]}:{children:s.join("")||[]};let n={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),parentNoe:this,props:{...t,children:s.join("")||[]}};i.render=n.render,i=n,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];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(">,",">")),`<span key="${e.key}" >${s}</span>`}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];n&&i&&!n.isEqualNode(i)&&s.push({type:"replace",old:n,new:i.cloneNode(!0)})}return s}updateChangedElements(e){e.forEach((e=>{switch(e.type){case"replace":e.old.parentNode.replaceChild(e.new,e.old);break;case"remove":e.old.remove();break;case"add":e.old.appendChild(e.new.cloneNode(!0))}}))}hydrate(e){if(e){(new DOMParser).parseFromString(this.render(),"text/html").body.querySelector(`[ref="${e}"]`),document.querySelector(`[ref="${e}"]`)}else{let e=this.key?document.querySelector(`[key="${this.key}"]`):null,t=(new DOMParser).parseFromString(this.render(),"text/html").body;if(t=document.createElement("div").appendChild(t),!e&&(e=document.querySelector(`[key="${t.attributes?.key?.value||null}"]`)),!e)return void console.error('Hydration failed, component not found got ensure you have set key="a value" on the component or this.key inside of function or render method body');t.querySelectorAll("*").forEach((e=>{e.hasAttribute("key")&&e.innerHTML!==document.querySelector(`[key="${e.attributes.key.value}"]`).innerHTML&&document.querySelector(`[key="${e.attributes.key.value}"]`).replaceWith(e)}))}}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){s=s+this.key||2022;let i={},o=(r=r.replace(/,,/g,",")).replaceAll(",,",",");for(var h in n){let e=n[h];i[o.split(",")[h]]=e}r=r.replace(",,",",");return this.functions.find((e=>e.ref===s))||document.addEventListener(`$dispatch_#id=${s}`,(t=>{let{name:r,event:n}=t.detail;if(r===s){let t=this.functions.find((e=>e.ref===s)).params;Object.keys(t).forEach((e=>{t[e]instanceof CustomEvent&&delete t[e],void 0===t[e]?delete t[e]:t[e]}));let r=n;console.log(r),e(n.detail.event)}})),window.callFunction=(e,t)=>{document.dispatchEvent(new CustomEvent(`$dispatch_#id=${e}`,{detail:{name:e,params:null,event:t}}))},!this.functions.find((e=>e.ref===s))&&this.functions.push({ref:s,params:i}),t?e:`((event)=>{event.target.ev = event; callFunction('${s}', event.target.ev)})(event)`}useState(e,t){this.state[e]||(this.state[e]=t);let s=()=>this.state[e],r=s();return[r,(t,n)=>{console.log(t),this.state[e]=t,r=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)=>{states[e]||(states[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()}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.link.setAttribute("onclick",`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=await fetch(t).then((e=>e.text()));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=[],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(){this.state={},this.key=null,this.components={},this.mounted=!1,this.checkIFMounted(),this.memoizes=[],this.functions=[],this.children=[],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=new Component(t);if(r(e))n.props=t||{},n.props.children=s.join("")||[],n.props.children=s.join(""),n.parentNode=this,n.request=this.request,n.response=this.response,n.key=n.props.key?n.props.key:Math.random(),i=n;else{e.toString();i.key=e.toString().split('key="')[1]?e.toString().split('key="')[1].split('"')[0]:null;let r=[];Object.keys(t).forEach((e=>{e.startsWith("$props")&&(r.push(t[e]),delete t[e])})),t=t?{...t,...r.reduce(((e,t)=>({...e,...t})),{}),children:s.join("")||[]}:{children:s.join("")||[]};let n={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),parentNoe:this,props:{...t,children:s.join("")||[]}};i.render=n.render,i=n,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];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(">,",">")),`<span key="${e.key}" >${s}</span>`}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];n&&i&&!n.isEqualNode(i)&&s.push({type:"replace",old:n,new:i.cloneNode(!0)})}return s}updateChangedElements(e){e.forEach((e=>{switch(e.type){case"replace":e.old.parentNode.replaceChild(e.new,e.old);break;case"remove":e.old.remove();break;case"add":e.old.appendChild(e.new.cloneNode(!0))}}))}hydrate(e){if(e){console.log("hydrating");let t=(new DOMParser).parseFromString(this.render(),"text/html").body.querySelector(`[ref="${e}"]`);document.querySelector(`[ref="${e}"]`);document.querySelector(`[ref="${e}"]`).replaceWith(t)}else{let e=this.key?document.querySelector(`[key="${this.key}"]`):null;e&&(e.innerHTML=this.render())}}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)=>{console.log("called");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)`}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()}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.link.setAttribute("onclick",`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=await fetch(t).then((e=>e.text()));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
@@ -4,10 +4,10 @@ import { glob, globSync, globStream, globStreamSync, Glob, } from 'glob'
4
4
  import puppeteer from 'puppeteer';
5
5
  import http from 'http'
6
6
  import { WebSocketServer } from 'ws'
7
- import { watch } from "fs";
7
+ import { watch } from "fs";
8
8
  import path from 'path'
9
- let config = await import('file://' + process.cwd() + '/vader.config.js').then((e) => e.default || e)
10
-
9
+ let config = await import('file://' + process.cwd() + '/vader.config.js').then((e) => e.default || e)
10
+
11
11
 
12
12
  let start = Date.now()
13
13
  let bundleSize = 0;
@@ -31,7 +31,7 @@ if (typeof process.env.isCloudflare !== "undefined" || !fs.existsSync(process.cw
31
31
  fs.writeFileSync(process.cwd() + "/dist/index.html", htmlFile)
32
32
  }
33
33
 
34
-
34
+
35
35
 
36
36
  function Compiler(func, file) {
37
37
  let string = func;
@@ -108,6 +108,7 @@ function Compiler(func, file) {
108
108
  let functionMatch;
109
109
  while ((functionMatch = functionAttributeRegex.exec(code)) !== null) {
110
110
  let [, attributeName, attributeValue] = functionMatch;
111
+
111
112
  let attribute = {};
112
113
 
113
114
  if (attributeValue && attributeValue.includes("=>") || attributeValue && attributeValue.includes("function")) {
@@ -143,7 +144,7 @@ function Compiler(func, file) {
143
144
  .split(" ")[0];
144
145
  isJSXComponent = elementTag.match(/^[A-Z]/) ? true : false;
145
146
  }
146
- });
147
+ });
147
148
  // add ; after newlines
148
149
 
149
150
 
@@ -193,10 +194,10 @@ function Compiler(func, file) {
193
194
  paramnames = paramnames ? paramnames.filter((e) => e.length > 0) : null
194
195
  // remove comments
195
196
  paramnames = paramnames ? paramnames.map((e) => e.match(/\/\*.*\*\//gs) ? e.replace(e.match(/\/\*.*\*\//gs)[0], "") : e) : null
196
-
197
+
197
198
  // add ; after newlines
198
199
  newvalue = newvalue.replaceAll(/\n/g, ";\n")
199
-
200
+
200
201
  let bind = isJSXComponent ? `${attributeName}='function(${params}){${newvalue}}'` : `${attributeName}="\$\{this.bind(function(){${newvalue}}.bind(this), ${isJSXComponent}, "${ref}", "${paramnames ? paramnames.map((e, index) => {
201
202
  if (e.length < 1) return ''
202
203
  if (e.length > 0) {
@@ -204,7 +205,7 @@ function Compiler(func, file) {
204
205
  }
205
206
  return e
206
207
  }) : ''}" ${params ? params.split(',').map((e) => e.trim()).filter(Boolean).map((e) => `,${e}`).join('') : ''})}"`
207
-
208
+
208
209
  string = string.replace(old, bind);
209
210
  }
210
211
  }
@@ -230,15 +231,21 @@ function Compiler(func, file) {
230
231
 
231
232
  function extractOuterReturn(code) {
232
233
  // match return [...]
233
- let returns = code.match(/return\s*\<>.*\<\/>/gs)
234
+ let returns = code.match(/return\s*\<>.*\<\/>|return\s*\(.*\)/gs);
234
235
 
235
236
  return returns || [];
236
237
  }
237
- // throw error if return is not wrapped in <></> if return is found and not wrapped in <></> or <div></div> and not <><div></div></>
238
- if (string.match(/return\s*\<>/gs) && !string.match(/return\s*\<>.*\<\/>/gs)
238
+ // throw error if return is not wrapped in <></> or
239
+ if (string.match(/return\s*\<>|return\s*\(.*\)/gs) && !string.match(/return\s*\<>.*\<\/>|return\s*\(.*\)/gs)
239
240
  || string.match(/return\s*\<[a-zA-Z0-9_-]+.*>/gs)
240
241
  ) {
241
- throw new SyntaxError("You forgot to enclose jsx in a fragment <></> at line " + string.split(/return\s*\<[a-zA-Z0-9_-]+.*>/gs)[0].split('\n').length + ' in file ' + file)
242
+
243
+ try {
244
+ throw new SyntaxError("You forgot to enclose jsx in a fragment return <> jsx html </> or return (<> jsx html </>) at line " + string.split(/return\s*\<[a-zA-Z0-9_-]+.*>/gs)[0].split('\n').length + ' in file ' + file)
245
+ } catch (error) {
246
+ console.error(error)
247
+ process.exit(1)
248
+ }
242
249
  }
243
250
 
244
251
  let outerReturn = extractOuterReturn(string);
@@ -250,16 +257,20 @@ function Compiler(func, file) {
250
257
 
251
258
  for (let i = 0; i < lines.length; i++) {
252
259
  let line = lines[i];
253
- if (line.match(/return\s*\<>/gs)) {
260
+ if (line.match(/return\s*\<>|return\s*\(/gs)) {
254
261
  continue;
255
262
  }
256
263
  contents += line + "\n";
257
264
  }
265
+ let usesBraces = returnStatement.match(/return\s*\(/gs) ? true : false;
258
266
 
259
- // Remove trailing ']'
260
- contents = contents.trim().replace(/\]$/, "");
261
- updatedContents = contents;
262
267
  let attributes = extractAttributes(contents);
268
+ // Remove trailing ']' or trailing )
269
+ contents = contents.trim().replace(/\]$/, "")
270
+ contents = contents.replace(/\)$/, "");
271
+ usesBraces ? !contents.includes('<>') ? contents = `<>${contents}</>` : null : null
272
+ updatedContents = contents;
273
+
263
274
 
264
275
  let newAttributes = [];
265
276
  let oldAttributes = [];
@@ -283,6 +294,7 @@ function Compiler(func, file) {
283
294
  ? value = `{this.parseStyle({${value.split('{{')[1].split('}}')[0]}})}` : null
284
295
 
285
296
 
297
+
286
298
  value = `="\$${value}",`;
287
299
  string = string.replace(oldvalue, value);
288
300
 
@@ -294,34 +306,13 @@ function Compiler(func, file) {
294
306
 
295
307
  }
296
308
  } else if (value && value.new) {
297
- string = string.replace(value.old, value.new);
309
+ string = string.replace(oldvalue, value.new);
298
310
  }
299
311
  }
300
312
  });
301
313
  });
302
314
 
303
- let retursnString = [];
304
- let outerReturnString = extractOuterReturn(string);
305
-
306
- outerReturnString.forEach((returnStatement) => {
307
- let lines = returnStatement.split("\n");
308
- let code = "";
309
- for (let i = 0; i < lines.length; i++) {
310
- let line = lines[i];
311
-
312
- code += line + "\n";
313
- }
314
-
315
- code = code.trim().replace(/\<\/\>$/, "");
316
- retursnString.push(code);
317
- });
318
-
319
- retursnString.forEach((returnStatement, index) => {
320
- let old = outerReturnString[index];
321
315
 
322
- let newReturn = `${returnStatement}</>`;
323
- string = string.replace(old, newReturn);
324
- });
325
316
 
326
317
  if (comments) {
327
318
  comments.forEach((comment) => {
@@ -410,149 +401,154 @@ function Compiler(func, file) {
410
401
  let componentMatch = body.match(componentRegex);
411
402
  let topComponent = "";
412
403
  componentMatch?.forEach(async (component) => {
413
-
404
+
414
405
  let [, element, attributes] = component;
415
-
406
+
416
407
 
417
408
  !isChild ? (topComponent = component) : null;
418
- let before = component;
409
+ let before = component;
419
410
 
420
411
  let myChildrens = [];
421
412
 
422
413
  let name = component.split("<")[1].split(">")[0].split(" ")[0].replace("/", "");
423
414
  // some components will have props that have html inside of them we need to only get the props ex: <Header title={<h1>hello</h1>}></Header> -> title={<h1>hello</h1>} // also spread props ex: <Header {...props}></Header> -> {...props} or {...props, title: 'hello'} or {...props, color:{color: 'red'}}
424
415
  // grab ...( spread props )
425
- const dynamicAttributesRegex = /(\w+)(?:="([^"]*)")?(?:='([^']*)')?(?:=\{([^}]*)\})?(?:=\{(.*?)\})?(?:={([^}]*)})?(?:{([^}]*)})?|(\{(?:[^{}]+|\{(?:[^{}]+|\{[^}]*\})*\})*\})/gs;
416
+ const dynamicAttributesRegex = /(\w+)(?:="([^"]*)")?(?:='([^']*)')?(?:=\{([^}]*)\})?(?:=\{(.*?)\})?(?:={([^}]*)})?(?:{([^}]*)})?|(?:{(?:[^{}]+|\{(?:[^{}]+|\{[^}]*\})*\})*\})|(\.{3}\{(?:[^{}]+|\{(?:[^{}]+|\{[^}]*\})*\})*\})/gs;
417
+
418
+
426
419
 
427
420
 
428
421
 
429
422
 
430
-
431
423
  let props = component.match(dynamicAttributesRegex)
432
-
433
- let filteredProps = [];
434
- let isWithinComponent = false;
435
- let componentName = name
436
-
437
- for (let prop of props) {
438
-
439
- if (prop.includes(componentName)) {
440
- // If the component is encountered, start collecting props
441
- isWithinComponent = true;
442
- filteredProps.push(prop);
443
- } else if (isWithinComponent && prop.includes('=')) {
444
-
445
- if(prop.includes('${')){
446
- // if it has an object inside of it then we should just do soemting:object else we should do something: `${object}`
447
-
448
- prop = prop.replace('="', ':').replace('}"', '}')
449
- if(prop.includes('${')){
450
- prop = prop.replace('="',':')
451
- prop = prop.replace('${', '')
452
- prop = prop.replace('}', '')
453
-
454
- }
455
- if(prop.includes('="${{')){
456
- prop = prop.replace('${{', '{')
457
- prop = prop.replace('}}', '}')
458
- prop = prop.replace('="', ':')
459
- prop = prop.replace('}"', '}')
460
- }
461
-
462
- }
463
- if(prop.startsWith('={')){
464
- prop = prop.replace('={', ':`${')
465
- prop.replace('} ', '}`')
466
- }
467
-
468
- if(prop.includes('function')){
469
- // parse 'function' to function
470
- prop = prop.replace("'", '')
471
-
472
- if(prop.endsWith("}'")){
473
- prop = prop.replace("}'", '}')
474
- console
475
-
424
+
425
+ let filteredProps = [];
426
+ let isWithinComponent = false;
427
+ let componentName = name
428
+
429
+ for (let prop of props) {
430
+
431
+ if (prop.includes(componentName)) {
432
+ // If the component is encountered, start collecting props
433
+ isWithinComponent = true;
434
+ filteredProps.push(prop);
435
+ } else if (isWithinComponent && prop.includes('=')) {
436
+
437
+ if (prop.includes('${')) {
438
+ // if it has an object inside of it then we should just do soemting:object else we should do something: `${object}`
439
+
440
+ prop = prop.replace('="', ':').replace('}"', '}')
441
+ if (prop.includes('${')) {
442
+ prop = prop.replace('="', ':')
443
+ prop = prop.replace('${', '')
444
+ prop = prop.replace('}', '')
445
+
446
+ }
447
+ if (prop.includes('="${{')) {
448
+ prop = prop.replace('${{', '{')
449
+ prop = prop.replace('}}', '}')
450
+ prop = prop.replace('="', ':')
451
+ prop = prop.replace('}"', '}')
452
+ }
453
+
454
+ }
455
+ if (prop.startsWith('={')) {
456
+ prop = prop.replace('={', ':`${')
457
+ prop.replace('} ', '}`')
458
+ }
459
+
460
+ if (prop.includes('function')) {
461
+ // parse 'function' to function
462
+ prop = prop.replace("'", '')
463
+
464
+ if (prop.endsWith("}'")) {
465
+ prop = prop.replace("}'", '}')
466
+
467
+ }
468
+
469
+ prop = prop.replace('=function', ':function')
470
+ }
471
+
472
+ filteredProps.push(prop);
473
+
474
+
476
475
  }
477
-
478
- prop = prop.replace('=function', ':function')
479
- }
476
+ else if (isWithinComponent && prop.includes('...')) {
477
+
478
+
479
+
480
+ // Check if spread props are within curly braces
481
+ if (prop.startsWith('{') && prop.endsWith('}')) {
482
+ const spreadObject = prop
483
+ const hasOtherObjects = spreadObject.split(',').filter((e) => e.includes(':')).length > 0;
484
+
485
+ const isValidSpread = spreadObject.includes('...');
486
+
487
+ let processedSpreadObject = '';
488
+ if (isValidSpread) {
489
+ // Split the spreadObject by commas and process each part individually
490
+ const parts = spreadObject.split(',').map((part) => {
491
+ if (part.trim().startsWith('{') && part.trim().endsWith('}')) {
492
+ const nestedParts = part
493
+ .trim()
494
+ .slice(1, -1) // Remove outer {}
495
+ .split(',')
496
+ .map((nestedPart) => {
497
+ return nestedPart.includes('...') ? nestedPart.trim().replace(/\.\.\./, '') : `...${nestedPart.trim()}`;
498
+ });
499
+ return `{${nestedParts.join(',')}}`;
500
+ } else {
501
+ return part.includes('...') ? part.trim() : part.trim().startsWith('{') ? `...${part.trim()}` : `${part.trim()}`;
502
+ }
503
+ });
504
+ if (!parts.join(',').includes('{(')) {
480
505
 
481
- filteredProps.push(prop);
482
-
483
-
484
- }
485
- else if (isWithinComponent && prop.includes('...')) {
486
-
487
-
488
-
489
- // Check if spread props are within curly braces
490
- if (prop.startsWith('{') && prop.endsWith('}')) {
491
- const spreadObject = prop
492
- const hasOtherObjects = spreadObject.split(',').filter((e) => e.includes(':')).length > 0;
493
-
494
- const isValidSpread = spreadObject.includes('...');
495
-
496
- let processedSpreadObject = '';
497
- if (isValidSpread) {
498
- // Split the spreadObject by commas and process each part individually
499
- const parts = spreadObject.split(',').map((part) => {
500
- if (part.trim().startsWith('{') && part.trim().endsWith('}')) {
501
- // Handle nested spreads within the object
502
- const nestedParts = part
503
- .trim()
504
- .slice(1, -1) // Remove outer {}
505
- .split(',')
506
- .map((nestedPart) => {
507
- return nestedPart.includes('...') ? nestedPart.trim().replace(/\.\.\./, '') : `...${nestedPart.trim()}`;
508
- });
509
- return `{${nestedParts.join(',')}}`;
510
- } else {
511
- return part.includes('...') ? part.trim() : part.trim().startsWith('{') ? `...${part.trim()}` : `${part.trim()}`;
506
+ processedSpreadObject = `${parts.join(',')}`
507
+
508
+ } else {
509
+ let prop = parts.join(',')
510
+ prop = prop.replaceAll('{(', '(')
511
+ prop = prop.replaceAll(')}', ')')
512
+ processedSpreadObject = prop
513
+ }
514
+ if (prop.includes('{{')) {
515
+ let prop = parts.join(',')
516
+ prop = prop.replaceAll('{{', '{')
517
+ prop = prop.replaceAll('}}', '}')
518
+ processedSpreadObject = prop
519
+ }
520
+
521
+
522
+ } else {
523
+ // Process nested structures within the object
524
+ processedSpreadObject = `{...${spreadObject}}`;
512
525
  }
513
- });
514
- if(!parts.join(',').includes('{(')){
515
-
516
- processedSpreadObject = `${parts.join(',')}`
517
-
518
- }else{
519
- let prop = parts.join(',')
520
- prop = prop.replaceAll('{(', '(')
521
- prop = prop.replaceAll(')}', ')')
522
- processedSpreadObject = prop
526
+
527
+ const $propsKey = `$props_${Math.random().toString(36).substring(2)}`;
528
+ filteredProps.push(`${$propsKey}:${processedSpreadObject}`);
523
529
  }
524
-
525
-
526
- } else {
527
- // Process nested structures within the object
528
- processedSpreadObject = `{...${spreadObject}}`;
529
- }
530
-
531
- const $propsKey = `$props_${Math.random().toString(36).substring(2)}`;
532
- filteredProps.push(`${$propsKey}:${processedSpreadObject}`);
533
- }
534
- }
535
-
536
- else{
537
- isWithinComponent = false;
538
- }
539
- }
530
+ }
531
+
532
+ else {
533
+ isWithinComponent = false;
534
+ }
535
+ }
540
536
 
541
537
  // get inner content of <Component>inner content</Component>
542
538
  let children = new RegExp(`<${name}[^>]*>(.*?)<\/${name}>`, "gs").exec(component) ? new RegExp(`<${name}[^>]*>(.*?)<\/${name}>`, "gs").exec(component)[1] : null;
543
-
539
+
544
540
  props = filteredProps.join(',')
545
-
541
+
546
542
  let savedname = name;
547
-
548
-
543
+
544
+
549
545
 
550
546
  name = name + Math.random().toString(36).substring(2);
551
547
  if (children && children.match(componentRegex)) {
552
548
  children = parseComponents(children, true);
553
549
  childs.push({ parent: name, children: children });
554
550
  } else {
555
-
551
+
556
552
  children ? childs.push({ parent: name, children: children }) : null;
557
553
  }
558
554
 
@@ -574,24 +570,22 @@ function Compiler(func, file) {
574
570
 
575
571
 
576
572
 
577
-
578
- props = props.replaceAll(`,${savedname}`, '').replaceAll(savedname, '')
579
- if(props.startsWith(',')){
580
- props = props.replace(',', '')
581
- }
582
- props = props .replaceAll("='", ":'")
583
- .replaceAll('=`', ':`')
573
+
574
+ props = props.replaceAll(`,${savedname}`, '').replaceAll(savedname, '')
575
+ if (props.startsWith(',')) {
576
+ props = props.replace(',', '')
577
+ }
578
+ props = props.replaceAll("='", ":'")
579
+ .replaceAll('=`', ':`')
584
580
  .replaceAll('="', ':"')
585
- .replaceAll(`={\``, ':`')
586
- .replaceAll('`}', '`')
587
- .replaceAll('={', ":`")
588
-
581
+ .replaceAll('={', ':')
582
+
589
583
 
590
584
  /**
591
585
  * @memoize - memoize a component to be remembered on each render and replace the old jsx
592
586
  */
593
587
 
594
- let replace = "";
588
+ let replace = "";
595
589
  replace = `\${this.memoize(this.createComponent(${savedname}, {${props}}, [\`${myChildrens.join(" ")}\`]))}`;
596
590
 
597
591
  body = body.replace(before, replace);
@@ -781,6 +775,12 @@ function Compiler(func, file) {
781
775
 
782
776
  globalThis.isBuilding = false
783
777
  globalThis.isWriting = null
778
+ const glb = await glob("**/**/**/**.{jsx,js}", {
779
+ ignore: ["node_modules/**/*", "dist/**/*"],
780
+ cwd: process.cwd() + '/pages/',
781
+ absolute: true,
782
+ recursive: true
783
+ });
784
784
  async function Build() {
785
785
  globalThis.isBuilding = true
786
786
  console.log('Compiling......')
@@ -806,12 +806,7 @@ async function Build() {
806
806
  };
807
807
 
808
808
 
809
- const glb = await glob("**/**/**/**.{jsx,js}", {
810
- ignore: ["node_modules/**/*", "dist/**/*"],
811
- cwd: process.cwd() + '/pages/',
812
- absolute: true,
813
- recursive: true
814
- });
809
+
815
810
 
816
811
  // Process files in the 'pages' directory
817
812
  let appjs = '';
@@ -823,10 +818,10 @@ async function Build() {
823
818
  if (route.url.includes(':')) {
824
819
  console.log('Route ' + route.url + ' is a dynamic route and will not be generated')
825
820
  return
826
- }
827
- let equalparamroute = routes.map((e) => {
821
+ }
822
+ let equalparamroute = routes.map((e) => {
828
823
  if (e.url.includes(':')) {
829
- let url = e.url.split('/:')[0]
824
+ let url = e.url.split('/:')[0]
830
825
  if (url && route.url === url) {
831
826
  return e
832
827
  } else {
@@ -910,14 +905,14 @@ async function Build() {
910
905
  res.render(module, req, res, module.$metadata)
911
906
  })
912
907
  ${equalparamroute.length > 0 ? equalparamroute.map((e) => {
913
-
914
-
915
-
916
- return `router.get('${e.url}', async (req, res) => {
908
+
909
+
910
+
911
+ return `router.get('${e.url}', async (req, res) => {
917
912
  let module = await import('/${e.fileName.replace('.jsx', '.js')}')
918
913
  res.render(module, req, res, module.$metadata)
919
914
  })\n`
920
- }) : ''}
915
+ }) : ''}
921
916
  router.listen(3000)
922
917
 
923
918
  </script>
@@ -934,8 +929,8 @@ async function Build() {
934
929
  let port = Math.floor(Math.random() * (65535 - 49152 + 1) + 49152)
935
930
 
936
931
  const server = http.createServer((req, res) => {
937
-
938
- if (req.url === '/') {
932
+
933
+ if (req.url === '/') {
939
934
  res.writeHead(200, { 'Content-Type': 'text/html' });
940
935
  res.end(document);
941
936
  } else {
@@ -967,26 +962,26 @@ async function Build() {
967
962
 
968
963
  globalThis.listen = true;
969
964
 
970
- const browser = await puppeteer.launch({
971
- headless: "new", args: ['--no-sandbox', '--disable-setuid-sandbox'],
965
+ const browser = await puppeteer.launch({
966
+ headless: "new", args: ['--no-sandbox', '--disable-setuid-sandbox'],
972
967
  warning: false,
973
968
  })
974
969
 
975
970
  try {
976
-
971
+
977
972
  route.url = route.url.replaceAll(/\/:[a-zA-Z0-9_-]+/gs, '')
978
973
  let page = await browser.newPage();
979
- await page.goto(`http://localhost:${port}/` , { waitUntil: 'networkidle2' });
974
+ await page.goto(`http://localhost:${port}/`, { waitUntil: 'networkidle2' });
980
975
  await page.waitForSelector('#root');
981
976
  await page.evaluate(() => {
982
977
  document.getElementById('meta').remove()
983
978
  document.querySelector('#isServer').innerHTML = 'window.isServer = false'
984
- if(document.head.getAttribute('prerender') === 'false'){
979
+ if (document.head.getAttribute('prerender') === 'false') {
985
980
  document.querySelector('#root').innerHTML = ''
986
981
  }
987
982
  })
988
983
  const html = await page.content();
989
-
984
+
990
985
  await page.close();
991
986
  await writer(process.cwd() + '/dist/' + (route.url === '/' ? 'index.html' : `${route.url}/` + 'index.html'), html)
992
987
  await browser.close();
@@ -994,11 +989,11 @@ async function Build() {
994
989
  console.log(error)
995
990
  await browser.close();
996
991
  }
997
- finally{
992
+ finally {
998
993
  await browser.close();
999
994
  server.close()
1000
995
  }
1001
-
996
+
1002
997
 
1003
998
  })
1004
999
 
@@ -1006,6 +1001,7 @@ async function Build() {
1006
1001
  globalThis.isBuilding = false
1007
1002
  clearTimeout(timeout)
1008
1003
  }, 1000)
1004
+ console.log(`Generated ${routes.length} html files for ${routes.length} routes`)
1009
1005
  }
1010
1006
 
1011
1007
  globalThis.routes = []
@@ -1043,75 +1039,72 @@ async function Build() {
1043
1039
 
1044
1040
  await writer(process.cwd() + "/dist/" + fileName.replace('.jsx', '.js'), data).then(async () => {
1045
1041
 
1046
- let { minify } = await import('terser')
1047
-
1048
- try {
1049
- let minified = await minify(data, {
1050
- toplevel: true,
1051
- ecma: 2016,
1052
- enclose: false,
1053
- module: true,
1054
- compress: true,
1055
- keep_fnames: true,
1056
1042
 
1057
- })
1058
1043
 
1059
- minified.code += `\n\n window.params = ${JSON.stringify(obj.url.split('/').filter((e) => e.includes(':')).map((e) => e.split(':')[1]))}`
1044
+ await writer(process.cwd() + "/dist/" + fileName.replace('.jsx', '.js'), data)
1060
1045
 
1061
- await writer(process.cwd() + "/dist/" + fileName.replace('.jsx', '.js'), minified.code)
1062
- } catch (error) {
1063
- console.log(error)
1064
- }
1065
1046
  })
1066
1047
 
1048
+ // configure routing for each page
1067
1049
 
1068
1050
  obj.compiledPath = process.cwd() + "/dist/pages/" + fileName.replace('.jsx', '.js')
1069
- let providerRedirects = {cloudflare: '_redirects', vercel: 'vercel.json', netlify:'_redirects'}
1070
- switch(true){
1051
+ let providerRedirects = { cloudflare: '_redirects', vercel: 'vercel.json', netlify: '_redirects' }
1052
+ switch (true) {
1071
1053
  case config && config.host && !config.host['_redirect']:
1072
1054
  let host = config.host.provider
1073
-
1074
- let provider = providerRedirects[host]
1075
- if(provider){
1076
-
1077
- let redirectFile = fs.existsSync(process.cwd() + '/dist/' + provider) ? fs.readFileSync(process.cwd() + '/dist/' + provider, 'utf8') : ''
1078
- let type = provider === '_redirects' ? 'text/plain' : 'application/json'
1079
-
1080
- let root = obj.url.includes(':') ? obj.url.split(':')[0] : obj.url
1081
- switch(true){
1055
+
1056
+ let provider = providerRedirects[host]
1057
+ if (provider) {
1058
+
1059
+ let redirectFile = null
1060
+ switch (true) {
1061
+ case provider === '_redirects':
1062
+ redirectFile = fs.existsSync(process.cwd() + '/dist/' + provider) ? fs.readFileSync(process.cwd() + '/dist/' + provider, 'utf8') : ''
1063
+ break;
1064
+ case provider === 'vercel.json':
1065
+ redirectFile = fs.existsSync(process.cwd() + '/' + provider) ? fs.readFileSync(process.cwd() + '/' + provider, 'utf8') : ''
1066
+ break;
1067
+ default:
1068
+ break;
1069
+ }
1070
+ let type = provider === '_redirects' ? 'text/plain' : 'application/json'
1071
+
1072
+ let root = obj.url.includes(':') ? obj.url.split('/:')[0] : obj.url
1073
+ switch (true) {
1082
1074
  case root === '/':
1083
1075
  break;
1084
1076
  case type === 'text/plain' && !redirectFile.includes(obj.url) && obj.url.includes(':'):
1085
1077
  let page = obj.pathname.split('/pages/')[1].replace('.jsx', '.js')
1086
1078
  redirectFile += `\n/${page} /${page} 200\n${obj.url} ${root} 200\n`
1087
1079
  !redirectFile.includes('/404') ? redirectFile += `\n/404 /404 404` : null
1088
- fs.writeFileSync(process.cwd() + '/dist/' + provider, redirectFile)
1080
+ fs.writeFileSync(process.cwd() + '/dist/' + provider, redirectFile)
1089
1081
  console.log(`Added ${obj.url} ${obj.url} 200 to ${provider}`)
1090
1082
  break;
1091
- case type === 'application/json' && !redirectFile.includes(root):
1092
- let json = JSON.parse(redirectFile) || {}
1083
+ case type === 'application/json' && !redirectFile?.includes(`${obj.url}`):
1084
+ let json = redirectFile ? JSON.parse(redirectFile) : {}
1093
1085
  let isVercel = provider === 'vercel.json' ? true : false
1094
- if(isVercel){
1086
+ if (isVercel) {
1095
1087
  json['rewrites'] = json['rewrites'] || []
1096
- json['rewrites'].push({ "source": `${root}/*`, "destination": `/${root}` })
1088
+ json['rewrites'].push({ "source": obj.url, "destination": `${root}/index.html` })
1089
+ fs.writeFileSync(process.cwd() + '/' + provider, JSON.stringify(json, null, 2))
1090
+ console.log(`Added ${obj.url} ${root}/index.html to ${provider}`)
1097
1091
  }
1098
- fs.writeFileSync(process.cwd() + '/dist/' + provider, JSON.stringify(json))
1099
- console.log(`Added ${root}/* ${root} 200 to ${provider}`)
1092
+
1100
1093
  }
1101
1094
  }
1102
1095
  break;
1103
1096
  case config && config.host && config.host['_redirect']:
1104
- let file = config.host['_redirect']
1097
+ let file = config.host['_redirect']
1105
1098
  file = file.split('./').join('')
1106
- let redirectFile = fs.existsSync(process.cwd() + '/' + file) ? fs.readFileSync(process.cwd() + '/' + file, 'utf8') : ''
1099
+ let redirectFile = fs.existsSync(process.cwd() + '/' + file) ? fs.readFileSync(process.cwd() + '/' + file, 'utf8') : ''
1107
1100
  fs.writeFileSync(process.cwd() + '/dist/' + file, redirectFile)
1108
1101
  console.log(`Using ${file} for redirects`)
1109
1102
  default:
1110
1103
  break;
1111
1104
 
1112
1105
  }
1113
-
1114
-
1106
+
1107
+
1115
1108
  globalThis.routes.push({ fileName: fileName, url: obj.url, html: '/' + (isBasePath ? 'index.html' : `${obj.url}/` + 'index.html') })
1116
1109
 
1117
1110
 
@@ -1153,18 +1146,7 @@ async function Build() {
1153
1146
  data = Compiler(data, process.cwd() + "/src/" + name);
1154
1147
 
1155
1148
  await writer(process.cwd() + "/dist/src/" + name.split('.jsx').join('.js'), data).then(async () => {
1156
- let { minify } = await import('terser')
1157
- try {
1158
- let minified = await minify(data, {
1159
- ecma: " 2016",
1160
- module: true,
1161
- compress: true,
1162
- keep_fnames: true,
1163
- })
1164
- await writer(process.cwd() + "/dist/src/" + name.replace('.jsx', '.js'), minified.code)
1165
- } catch (error) {
1166
- console.log(error)
1167
- }
1149
+ await writer(process.cwd() + "/dist/src/" + name.replace('.jsx', '.js'), data)
1168
1150
 
1169
1151
  })
1170
1152
  return
@@ -1236,18 +1218,17 @@ const s = () => {
1236
1218
 
1237
1219
  fs.readFile(filePath, (err, data) => {
1238
1220
  if (err) {
1239
- console.log(err)
1240
1221
  res.writeHead(404, { 'Content-Type': 'text/html' });
1241
1222
  res.end(fs.existsSync(process.cwd() + '/dist/404') ? fs.readFileSync(process.cwd() + '/dist/404/index.html') : '404');
1242
1223
  } else {
1243
- const contentType = getContentType(filePath);
1224
+ const contentType = getContentType(filePath);
1244
1225
  switch (true) {
1245
1226
  case contentType === 'text/html' && globalThis.devMode:
1246
1227
  data = data.toString() + `<script type="module">
1247
- let ws = new WebSocket('ws://localhost:3000')
1228
+ let ws = new WebSocket('ws://localhost:${process.env.PORT || 3000}')
1248
1229
  ws.onmessage = (e) => {
1249
1230
  if(e.data === 'reload'){
1250
- window.rehydrate()
1231
+ window.location.reload()
1251
1232
  }
1252
1233
  }
1253
1234
  </script>
@@ -1262,13 +1243,13 @@ const s = () => {
1262
1243
 
1263
1244
  const ws = new WebSocketServer({ server });
1264
1245
  ws.on('connection', (socket) => {
1265
- console.log('Client connected');
1266
- socket.on('close', () => console.log('Client disconnected'));
1246
+ console.log('WebSocket Hydration Client connected');
1247
+ socket.on('close', () => console.log('WebSocket Hydration Client disconnected'));
1267
1248
  });
1268
1249
 
1269
1250
 
1270
1251
  function getContentType(filePath) {
1271
- let ext = ['.js', '.css', '.mjs', '.cjs', '.html', '.json', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.mp4', '.webm', '.ogg'].includes(path.extname(filePath)) ? path.extname(filePath) : '.html'
1252
+ let ext = ['.js', '.css', '.mjs', '.cjs', '.html', '.json', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.mp4', '.webm', '.ogg'].includes(path.extname(filePath)) ? path.extname(filePath) : '.html'
1272
1253
  switch (ext) {
1273
1254
  case '.js':
1274
1255
  return 'text/javascript';
@@ -1310,21 +1291,20 @@ const s = () => {
1310
1291
  let i =
1311
1292
  setInterval(() => {
1312
1293
  if (globalThis.isBuilding && globalThis.devMode) {
1313
- // reload page
1314
- console.log(globalThis.isBuilding)
1315
- console.log('Reloading page...')
1294
+
1316
1295
  ws.clients.forEach((client) => {
1317
1296
  client.send('reload')
1318
- console.log('Reloaded page')
1319
1297
  })
1320
- }
1298
+ } else {
1299
+ clearInterval(i)
1300
+ }
1321
1301
  }, 120)
1322
1302
 
1323
1303
  }
1324
1304
 
1325
1305
 
1326
1306
  switch (true) {
1327
- case process.argv.includes('--watch'):
1307
+ case process.argv.includes('--watch') && !process.argv.includes('--build') && !process.argv.includes('--serve'):
1328
1308
 
1329
1309
  globalThis.devMode = true
1330
1310
  console.log(`
@@ -1354,7 +1334,7 @@ Vader.js v1.3.3
1354
1334
  globalThis.listen = true;
1355
1335
 
1356
1336
  break;
1357
- case process.argv.includes('--build'):
1337
+ case process.argv.includes('--build') && !process.argv.includes('--watch') && !process.argv.includes('--serve'):
1358
1338
  globalThis.devMode = false
1359
1339
  console.log(`
1360
1340
  Vader.js v1.3.3
@@ -1363,7 +1343,7 @@ Building to ./dist
1363
1343
  Build()
1364
1344
 
1365
1345
  break;
1366
- case process.argv.includes('--serve'):
1346
+ case process.argv.includes('--serve') && !process.argv.includes('--watch') && !process.argv.includes('--build'):
1367
1347
  let port = process.argv[process.argv.indexOf('--serve') + 1] || 3000
1368
1348
  process.env.PORT = port
1369
1349
  globalThis.devMode = false
@@ -1381,9 +1361,9 @@ Vader.js is a reactive framework for building interactive applications for the w
1381
1361
  Usage: vader <command>
1382
1362
 
1383
1363
  Commands:
1384
- --watch Watch the pages folder for changes and recompile
1364
+ --watch Watch the pages folder for changes with hot reloading
1385
1365
 
1386
- --build Build the project
1366
+ --build Build the project to ./dist
1387
1367
 
1388
1368
  --serve Serve the project on a port (default 3000)
1389
1369