vaderjs 1.3.3-5b5a772ebe58 → 1.3.3-612-hotfix
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 +9 -5
- package/package.json +4 -2
- package/runtime/router.js +1 -1
- package/runtime/vader.js +1 -1
- package/vader.js +376 -341
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
[](https://github.com/Postr-Inc/Vader.js/blob/main/LICENSE) [](https://www.npmjs.com/package/vaderjs)
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
> Do not use any alpha versions as these where changed multiple times any version under latest is considered lts and are deemed to be stable
|
|
18
18
|
## Get Started
|
|
19
19
|
|
|
20
20
|
2. Install vaderjs
|
|
@@ -81,7 +81,7 @@ export default function(req, res){
|
|
|
81
81
|
|
|
82
82
|
return <>
|
|
83
83
|
<h1>${count}</h1>
|
|
84
|
-
<button onClick={(
|
|
84
|
+
<button onClick={(event)=>{setCount(count + 1)}}>
|
|
85
85
|
</>
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -126,9 +126,11 @@ export function Layout({title, keywords, description, children}){
|
|
|
126
126
|
|
|
127
127
|
// pages/index.jsx
|
|
128
128
|
|
|
129
|
+
//$= is a ternary operator used for spread like nesting
|
|
130
|
+
|
|
129
131
|
export default function (req, res){
|
|
130
132
|
return <>
|
|
131
|
-
<Layout {
|
|
133
|
+
<Layout $={{title:'home', description:'home page', keywords:'vader.js', logo:''}}>
|
|
132
134
|
<h1> Hello World</h1>
|
|
133
135
|
</Layout>
|
|
134
136
|
</>
|
|
@@ -173,6 +175,8 @@ export default class MyApp extends Component{
|
|
|
173
175
|
contructor(){
|
|
174
176
|
super()
|
|
175
177
|
this.key = 'static key for state changes'
|
|
178
|
+
// or
|
|
179
|
+
this.nokey // disable element generation
|
|
176
180
|
}
|
|
177
181
|
|
|
178
182
|
render(){
|
|
@@ -215,7 +219,7 @@ return <>
|
|
|
215
219
|
</>
|
|
216
220
|
```
|
|
217
221
|
|
|
218
|
-
|
|
222
|
+
Low level invokes are considered top level and can access - any value above the scope !!
|
|
219
223
|
|
|
220
224
|
```jsx
|
|
221
225
|
let car = {
|
|
@@ -223,7 +227,7 @@ let car = {
|
|
|
223
227
|
price: 'toomiuch'
|
|
224
228
|
}
|
|
225
229
|
return <>
|
|
226
|
-
<button onclick={(
|
|
230
|
+
<button onclick={(event)=>{
|
|
227
231
|
console.log(car.model)
|
|
228
232
|
}}>Log</button>
|
|
229
233
|
```
|
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-
|
|
5
|
+
"version": "1.3.3-612-hotfix",
|
|
6
6
|
"bin": {
|
|
7
7
|
"vader": "./vader.js"
|
|
8
8
|
},
|
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"glob": "latest",
|
|
31
31
|
"puppeteer":"latest",
|
|
32
|
-
"dotenv":"latest"
|
|
32
|
+
"dotenv":"latest",
|
|
33
|
+
"prettier": "latest",
|
|
34
|
+
"source-map": "latest"
|
|
33
35
|
|
|
34
36
|
}
|
|
35
37
|
}
|
package/runtime/router.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Component}from"./vader.js";let middlewares=[];class VaderRouter{constructor(e,t){this.routes=[],this.middlewares=[],this.errorMiddlewares=[],this.listeners=[],this.basePath=e}get(e,t){this.routes.push({path:e,handler:t,method:"get"})}use(e){this.middlewares.push(e)}listen(e,t){e||(e=Math.random().toString(36).substring(7)),window.onpopstate=async e=>{let t=window.location.pathname,r=`/${t.split("/")[1]}`;console.log("route",t),this.checkroute(t)||window.devMode||(t="/404");let n=(new DOMParser).parseFromString(await fetch(r,{cache:"reload"}).then((e=>e.text())),"text/html").documentElement;document.querySelector("#root").innerHTML=n.querySelector("#root").innerHTML,document.title=n.querySelector("title")?n.querySelector("title").innerHTML:document.title,document.querySelector('script[id="router"]').remove();let o=document.createElement("script");o.id="router",o.innerHTML=n.querySelector('script[id="router"]').innerHTML,o.setAttribute("type","module"),document.body.appendChild(o)},window.rehydrate=async()=>{window.location.reload()},this.listeners.push(e),1===this.listeners.length?this.handleRoute(window.location.pathname):this.listeners.pop(),t&&t()}extractParams(e,t){const r=e.split("/").filter((e=>""!==e)),n=t.split("/").filter((e=>""!==e)),o={};return r.forEach(((e,t)=>{if(e.startsWith(":")){const r=e.slice(1);o[r]=n[t]}else if(e.startsWith("*")){n.slice(t).forEach(((e,t)=>{o[t]=e}))}})),o}extractQueryParams(e){const t=e.split("?")[1];if(!t)return{};const r={};return t.split("&").forEach((e=>{const[t,n]=e.split("=");r[t]=n})),r}checkroute(e){return e=e.endsWith("/")?e.slice(0,-1):e,this.routes.find((t=>{if(t.path===e)return!0;if(""===e&&"/"===t.path)return!0;if(e.includes("?")&&(e=e.split("?")[0]),t.path.includes("*")||t.path.includes(":")){const r=t.path.split("/").filter((e=>""!==e)),n=e.split("/").filter((e=>""!==e));if(r.length!==n.length&&!t.path.endsWith("*"))return!1;for(let e=0;e<r.length;e++){const t=r[e],o=n[e];if(!t.startsWith(":")&&!t.startsWith("*")&&t!==o)return!1}return!0}const r=this.extractParams(t.path,e);return Object.keys(r).length>0}))}handleRoute(e){let t=200,r=e,n=this.checkroute(e);n||(n=window.routes.find((e=>!e.url.includes("/404")||this.error||window.devMode?!(this.error||!e.url.includes("/404"))||void 0:(window.history.pushState({},"","/404"),window.dispatchEvent(new Event("popstate")),this.error=!0,!1))),t=n?200:404);const o=this.extractQueryParams(r),s=n&&n.path?this.extractParams(n.path,r):{};Object.keys(s).forEach((e=>{s[e]=s[e].split("?")?s[e].split("?")[0]:s[e]}));const i={headers:{},params:s,query:o,path:e,fileUrl:window.location.href.split(window.location.origin)[1],url:window.location.href,method:n?n.method:"get",pause:!1,timestamp:Date.now()};window.$CURRENT_URL=i.path,window.$FULL_URL=window.location.href.replace("#","");const a={status:t,log:e=>{void 0===e?console.log(`${i.path} ${i.method} ${a.status} ${i.timestamp}`):console.table({"Request Path":i.path,"Request Method":n.method,"Response Status":a.status,"Request Timestamp":i.timestamp})},refresh:()=>{this.handleRoute(window.location.pathname)},redirect:e=>{!e.startsWith("/")&&(e=`/${e}`),window.history.pushState({},"",e),window.dispatchEvent(new Event("popstate"))},render:async(e,t,r,n)=>{function
|
|
1
|
+
import{Component}from"./vader.js";let middlewares=[];class VaderRouter{constructor(e,t){this.routes=[],this.middlewares=[],this.errorMiddlewares=[],this.listeners=[],this.basePath=e}get(e,t){this.routes.push({path:e,handler:t,method:"get"})}use(e){this.middlewares.push(e)}listen(e,t){e||(e=Math.random().toString(36).substring(7)),window.onpopstate=async e=>{let t=window.location.pathname,r=`/${t.split("/")[1]}`;console.log("route",t),this.checkroute(t)||window.devMode||(t="/404");let n=(new DOMParser).parseFromString(await fetch(r,{cache:"reload"}).then((e=>e.text())),"text/html").documentElement;document.querySelector("#root").innerHTML=n.querySelector("#root").innerHTML,document.title=n.querySelector("title")?n.querySelector("title").innerHTML:document.title,document.querySelector('script[id="router"]').remove();let o=document.createElement("script");o.id="router",o.innerHTML=n.querySelector('script[id="router"]').innerHTML,o.setAttribute("type","module"),document.body.appendChild(o)},window.rehydrate=async()=>{window.location.reload()},this.listeners.push(e),1===this.listeners.length?this.handleRoute(window.location.pathname):this.listeners.pop(),t&&t()}extractParams(e,t){const r=e.split("/").filter((e=>""!==e)),n=t.split("/").filter((e=>""!==e)),o={};return r.forEach(((e,t)=>{if(e.startsWith(":")){const r=e.slice(1);o[r]=n[t]}else if(e.startsWith("*")){n.slice(t).forEach(((e,t)=>{o[t]=e}))}})),o}extractQueryParams(e){const t=e.split("?")[1];if(!t)return{};const r={};return t.split("&").forEach((e=>{const[t,n]=e.split("=");r[t]=n})),r}checkroute(e){return e=e.endsWith("/")?e.slice(0,-1):e,this.routes.find((t=>{if(t.path===e)return!0;if(""===e&&"/"===t.path)return!0;if(e.includes("?")&&(e=e.split("?")[0]),t.path.includes("*")||t.path.includes(":")){const r=t.path.split("/").filter((e=>""!==e)),n=e.split("/").filter((e=>""!==e));if(r.length!==n.length&&!t.path.endsWith("*"))return!1;for(let e=0;e<r.length;e++){const t=r[e],o=n[e];if(!t.startsWith(":")&&!t.startsWith("*")&&t!==o)return!1}return!0}const r=this.extractParams(t.path,e);return Object.keys(r).length>0}))}handleRoute(e){let t=200,r=e,n=this.checkroute(e);n||(n=window.routes.find((e=>!e.url.includes("/404")||this.error||window.devMode?!(this.error||!e.url.includes("/404"))||void 0:(window.history.pushState({},"","/404"),window.dispatchEvent(new Event("popstate")),this.error=!0,!1))),t=n?200:404);const o=this.extractQueryParams(r),s=n&&n.path?this.extractParams(n.path,r):{};Object.keys(s).forEach((e=>{s[e]=s[e].split("?")?s[e].split("?")[0]:s[e]}));const i={headers:{},params:s,query:o,path:e,fileUrl:window.location.href.split(window.location.origin)[1],url:window.location.href,method:n?n.method:"get",pause:!1,timestamp:Date.now()};window.$CURRENT_URL=i.path,window.$FULL_URL=window.location.href.replace("#","");const a={status:t,log:e=>{void 0===e?console.log(`${i.path} ${i.method} ${a.status} ${i.timestamp}`):console.table({"Request Path":i.path,"Request Method":n.method,"Response Status":a.status,"Request Timestamp":i.timestamp})},refresh:()=>{this.handleRoute(window.location.pathname)},redirect:e=>{!e.startsWith("/")&&(e=`/${e}`),window.history.pushState({},"",e),window.dispatchEvent(new Event("popstate"))},render:async(e,t,r,n)=>{function isClass(e){return"function"==typeof e&&/^class\s/.test(Function.prototype.toString.call(e))}try{let n=new Component;if(isClass(e.default)){let t=new e.default;n.state=t.state,n=t}else{e.default.toString();n.key=e.default.toString().split('key="')[1]?e.default.toString().split('key="')[1].split('"')[0]:null;let i=e.default.toString().split("this.key")[1]?e.default.toString().split("this.key")[1].split("=")[1].split(";")[0].trim().replaceAll('"',""):null;i&&(n.key=i),console.log("key",n.key);let a={key:n.key,render:()=>{let o=document.createElement("div");return n.key&&o.setAttribute("key",n.key),o.innerHTML=e.default.apply(n,[t,r]),o.outerHTML},request:t,response:r,params:s,queryParams:o,reset:n.reset.bind(n),onMount:n.onMount.bind(n),useState:null,router:{use:n.router.use.bind(n)},bindMount:n.bindMount.bind(n),memoize:n.memoize.bind(n),createComponent:n.createComponent.bind(n),isChild:!1,useState:n.useState.bind(n),parseStyle:n.parseStyle.bind(n),bind:n.bind.bind(n),useRef:n.useRef.bind(n),useReducer:n.useReducer.bind(n),onMount:n.onMount.bind(n),onUnmount:n.onUnmount.bind(n),hydrate:n.hydrate.bind(n)};n.render=a.render,n=a}if(!document.querySelector("#root"))throw new Error("Root element not found, please add an element with id root");n.reset(),n.components={},n.request=t,n.response=r,n.router.use&&!n.isChild?await new Promise((async o=>{if(isClass(e.default))if(isClass(e.default))switch(await n.router.use(t,r),t.pause){case!0:console.log("pausing",t.pause);let e=setInterval((()=>{t.pause?console.log("still pausing",t.pause):(clearInterval(e),o())}),1e3);break;case!1:o()}else o();else switch(await e.default.apply(n,[t,r]),await n.router.use(t,r),t.pause){case!0:let e=setInterval((()=>{t.pause?console.log("still pausing request",t.url):(clearInterval(e),o())}),1e3);break;case!1:o()}})):n.router.use&&n.isChild&&console.warn("Router.use() is not supported in child components");const i=await n.render();document.querySelector("#root").innerHTML!==i&&(document.querySelector("#root").innerHTML=i),n.bindMount(),n.onMount()}catch(e){console.error(e)}},setQuery:e=>{let t="";Object.keys(e).forEach(((r,n)=>{t+=`${0===n?"?":"&"}${r}=${e[r]}`}));let r=window.location.hash.split("?")[0];t=t.replace("/","-").replaceAll("/","-"),window.location.hash=`${r}${t}`},send:e=>{document.querySelector("#root").innerHTML=e},json:e=>{const t=document.querySelector("#root");t.innerHTML="";const r=document.createElement("pre");r.textContent=JSON.stringify(e,null,2),t.appendChild(r)}};middlewares.forEach((e=>{e(i,a)})),n&&n.handler(i,a)}}window.VaderRouter=VaderRouter;export default VaderRouter;
|
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){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};
|
|
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.$_vaderElement=!0,this.state={},this.key=null,this.components={},this.mounted=!1,this.checkIFMounted(),this.memoizes=[],this.functions=[],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 i=r(e)?new e(t):null;if(!e)throw new Error("Component must be defined");let n=[];Object.keys(t).forEach((e=>{if(e.startsWith("$props")&&(n.push(t[e]),delete t[e]),e.startsWith("$_ternary")){let s=t[e];delete t[e],Object.keys(s).forEach((e=>{t[e]=s[e]}))}}));let o=new Component(t);if(r(e))i.props=t||{},i.props.children=s.join("")||[],i.props.children=s.join(""),i.parentNode=this,i.type="class ",i.request=this.request,i.response=this.response,i.key=i.props.key?i.props.key:Math.random(),o=i;else{e.toString();o.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: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 i=e[r],n=t[r];if(i&&n&&i.childNodes.length>0&&n.childNodes.length>0){console.log("equal");let e=this.domDifference(Array.from(i.childNodes),Array.from(n.childNodes));s.push(...e)}i&&n&&0===i.childNodes.length&&0===n.childNodes.length?i.isEqualNode(n)||s.push({type:"replace",old:i,new:n}):i&&n&&Array.from(i.attributes).length!==Array.from(n.attributes).length&&s.push({type:"replace",old:i,new:n})}return s}updateChangedElements(e){e.forEach((e=>{if(e)switch(e.type){case"replace":e.old.replaceWith(e.new);break;case"remove":e.old.remove();break;case"add":e.old.appendChild(e.new.cloneNode(!0))}}))}hydrate(e){if(e){console.log(e.bind);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))[0];this.updateChangedElements([s])}}))}else{let e=this.key?document.querySelector(`[key="${this.key}"]`):null;if(console.log(e),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,...i){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 i=r();return[r(),(t,n)=>{const o=s(i,t)??t;this.state[e]=o,this.hydrate(n),i=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",`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,i=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",i),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: ${i}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){console.log(this.props.children),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
|
@@ -1,11 +1,40 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import { glob, globSync, globStream, globStreamSync, Glob, } from 'glob'
|
|
4
|
-
import puppeteer from 'puppeteer';
|
|
4
|
+
import puppeteer from 'puppeteer';
|
|
5
5
|
import http from 'http'
|
|
6
|
+
import { SourceMapGenerator } from 'source-map'
|
|
7
|
+
|
|
6
8
|
import { WebSocketServer } from 'ws'
|
|
9
|
+
import prettier from 'prettier'
|
|
7
10
|
import { watch } from "fs";
|
|
8
11
|
import path from 'path'
|
|
12
|
+
|
|
13
|
+
globalThis.compiledFiles = []
|
|
14
|
+
|
|
15
|
+
const sourceMapGen = (data, code) => {
|
|
16
|
+
let { origin, fileName } = data
|
|
17
|
+
const sourceMap = new SourceMapGenerator({ file: '/src/' + fileName.replace('.jsx', '.js') });
|
|
18
|
+
|
|
19
|
+
const lines = fs.readFileSync(origin, "utf8").split("\n");
|
|
20
|
+
let line = 1;
|
|
21
|
+
let column = 0;
|
|
22
|
+
for (const l of lines) {
|
|
23
|
+
sourceMap.addMapping({
|
|
24
|
+
source: origin,
|
|
25
|
+
sourceRoot: '/src',
|
|
26
|
+
original: { line: line, column: 0 },
|
|
27
|
+
generated: { line: line, column: 0 },
|
|
28
|
+
});
|
|
29
|
+
line++;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
sourceMap.setSourceContent(origin, fs.readFileSync(origin, "utf8"));
|
|
33
|
+
|
|
34
|
+
code = code + `\n//# sourceMappingURL=./src/maps/${fileName.replace('.jsx', '.js')}.map \n //#sourceURL=/src/maps/${fileName.replace('.jsx', '.js')}.map`
|
|
35
|
+
return { code, sourceMap };
|
|
36
|
+
}
|
|
37
|
+
|
|
9
38
|
let config = await import('file://' + process.cwd() + '/vader.config.js').then((e) => e.default || e)
|
|
10
39
|
let writer = async (file, data) => {
|
|
11
40
|
globalThis.isWriting = file
|
|
@@ -23,15 +52,7 @@ let writer = async (file, data) => {
|
|
|
23
52
|
return { _written: true };
|
|
24
53
|
};
|
|
25
54
|
|
|
26
|
-
let start = Date.now()
|
|
27
55
|
let bundleSize = 0;
|
|
28
|
-
let errorCodes = {
|
|
29
|
-
"SyntaxError: Unexpected token '<'": "You forgot to enclose tags in a fragment <></>",
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* define directories
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
56
|
|
|
36
57
|
if (!fs.existsSync(process.cwd() + '/dist')) {
|
|
37
58
|
fs.mkdirSync(process.cwd() + '/dist')
|
|
@@ -41,112 +62,74 @@ if (!fs.existsSync(process.cwd() + '/dist')) {
|
|
|
41
62
|
|
|
42
63
|
|
|
43
64
|
if (typeof process.env.isCloudflare !== "undefined" || !fs.existsSync(process.cwd() + '/dist/index.html')) {
|
|
44
|
-
|
|
45
|
-
fs.writeFileSync(process.cwd() + "/dist/index.html", htmlFile)
|
|
65
|
+
fs.writeFileSync(process.cwd() + "/dist/index.html", '')
|
|
46
66
|
}
|
|
47
67
|
|
|
48
68
|
|
|
49
69
|
|
|
50
70
|
function Compiler(func, file) {
|
|
51
71
|
let string = func;
|
|
52
|
-
// Remove block comments
|
|
53
|
-
|
|
54
72
|
let returns = []
|
|
55
73
|
let comments = string.match(/\{\s*\/\*.*\*\/\s*}/gs)?.map((comment) => comment.trim());
|
|
56
74
|
|
|
57
|
-
let savedfuncnames = [];
|
|
58
|
-
let functions = string.match(
|
|
59
|
-
/(?:const|let)\s*([a-zA-Z0-9_-]+)\s*=\s*function\s*\(([^)]*)\)|function\s*([a-zA-Z0-9_-]+)\s*\(([^)]*)\)/gs
|
|
60
|
-
)
|
|
61
|
-
?.map((match) => match.trim());
|
|
62
75
|
|
|
63
|
-
let functionNames = [];
|
|
64
76
|
|
|
65
77
|
|
|
66
|
-
functions && functions.forEach((func) => {
|
|
67
|
-
if (
|
|
68
|
-
!func.match(
|
|
69
|
-
/(?:const|let)\s*([a-zA-Z0-9_-]+)\s*=\s*function\s*\(([^)]*)\)|function\s*([a-zA-Z0-9_-]+)\s*\(([^)]*)\)/gs
|
|
70
|
-
)
|
|
71
|
-
) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
let name = func.split(" ")[1].split("(")[0].trim();
|
|
76
|
-
|
|
77
|
-
let lines = string.match(/return\s*\<>.*\<\/>/gs);
|
|
78
|
-
|
|
79
|
-
if (lines) {
|
|
80
|
-
for (let i = 0; i < lines.length; i++) {
|
|
81
|
-
let line = lines[i];
|
|
82
|
-
|
|
83
|
-
if (!functionNames.includes(name)) {
|
|
84
|
-
functionNames.push(name);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
78
|
|
|
90
|
-
// get all Obj({}) and parse to JSON.stringify
|
|
91
79
|
|
|
92
|
-
let
|
|
93
|
-
|
|
94
|
-
objects && objects.forEach((obj) => {
|
|
95
|
-
let key = obj.split("Obj")[1].split("(")[1].split(")")[0].trim();
|
|
96
|
-
let newobj = obj.replaceAll(`Obj(${key})`, `${key}`);
|
|
97
|
-
// let newobj = obj.replaceAll(`Obj(${key})`, `JSON.parse('${key}')`)
|
|
98
|
-
string = string.replaceAll(obj, `this.handleObject('${newobj}')`);
|
|
99
|
-
});
|
|
80
|
+
let childs = [];
|
|
100
81
|
|
|
101
82
|
|
|
102
|
-
|
|
83
|
+
const spreadAttributeRegex = /\s*([a-zA-Z0-9_-]+)\s*(\$\s*=\s*\{\s*\{[^]*?\}\s*\})/gs;
|
|
84
|
+
|
|
103
85
|
|
|
104
86
|
|
|
105
87
|
|
|
106
88
|
function extractAttributes(code) {
|
|
107
|
-
//
|
|
108
|
-
const elementRegex =
|
|
89
|
+
// grab $={...} and ={...}
|
|
90
|
+
const elementRegex = /<([a-zA-Z0-9_-]+)([^>]*)>/gs;
|
|
109
91
|
|
|
110
92
|
// Match attributes in an opening tag, including those with ={}
|
|
111
93
|
// Match attributes in an opening tag, including those with ={...}
|
|
112
94
|
const attributeRegex =
|
|
113
|
-
|
|
95
|
+
/\s*([a-zA-Z0-9_-]+)(\s*=\s*("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|\{(?:[^{}]|(?:\{(?:[^{}]|(?:\{[^{}]*\})*)*\})*)*\}|(?:\([^)]*\)|\{[^}]*\}|()=>\s*(?:\{[^}]*\})?)|\[[^\]]*\]))?/gs;
|
|
96
|
+
|
|
97
|
+
|
|
114
98
|
|
|
115
|
-
|
|
116
|
-
const functionAttributeRegex = /\s*([a-zA-Z0-9_-]+)(\s*=\s*{((?:[^{}]|(?:\{(?:[^{}]|(?:\{[^{}]*\})*)*\})*)*)})/gs;
|
|
99
|
+
const functionAttributeRegex = /\s*([a-zA-Z0-9_-]+)\s*(=\s*{((?:[^{}]|(?:\{(?:[^{}]|(?:\{[^{}]*\})*)*\})*)*)})/gs;
|
|
117
100
|
|
|
118
101
|
let attributesList = [];
|
|
119
102
|
|
|
120
|
-
|
|
103
|
+
let spreadAttributes = [];
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @search - handle spread for html elements
|
|
107
|
+
* @keywords - spread, spread attributes, spread props, spread html attributes
|
|
108
|
+
*/
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @search - handle function parsing for html elements
|
|
113
|
+
* @keywords - function, function attributes, function props, function html attributes
|
|
114
|
+
*
|
|
115
|
+
*/
|
|
121
116
|
let functionAttributes = [];
|
|
117
|
+
let spreadFunctions = [];
|
|
122
118
|
let functionMatch;
|
|
123
119
|
while ((functionMatch = functionAttributeRegex.exec(code)) !== null) {
|
|
124
|
-
let [, attributeName, attributeValue] = functionMatch;
|
|
125
120
|
|
|
121
|
+
let [, attributeName, attributeValue] = functionMatch;
|
|
126
122
|
let attribute = {};
|
|
127
123
|
|
|
128
|
-
if (attributeValue && attributeValue.includes("=>")
|
|
129
|
-
|
|
130
|
-
|
|
124
|
+
if (attributeValue && attributeValue.includes("=>")
|
|
125
|
+
&& !attributeValue.includes("this.bind")
|
|
126
|
+
|| attributeValue && attributeValue.includes("function")
|
|
127
|
+
&& !spreadFunctions.includes(attributeValue)
|
|
128
|
+
) {
|
|
129
|
+
|
|
131
130
|
let ref = Math.random().toString(36).substring(2).split('').filter((e) => !Number(e)).join('')
|
|
132
131
|
let old = `${attributeName}${attributeValue}`
|
|
133
|
-
functionNames.forEach((name) => {
|
|
134
|
-
string.split("\n").forEach((line) => {
|
|
135
|
-
if (line.includes(name) && line.includes("function")) {
|
|
136
|
-
line = line.trim();
|
|
137
|
-
line = line.replace(/\s+/g, " ");
|
|
138
132
|
|
|
139
|
-
let ps = line.split("(").slice(1).join("(").split(")")[0].trim();
|
|
140
|
-
|
|
141
|
-
// remove comments
|
|
142
|
-
ps = ps.match(/\/\*.*\*\//gs)
|
|
143
|
-
? ps.replace(ps.match(/\/\*.*\*\//gs)[0], "")
|
|
144
|
-
: ps;
|
|
145
|
-
functionparams.push({ ref: ref, name: name, params: ps });
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
133
|
let elementMatch = string.match(/<([a-zA-Z0-9_-]+)([^>]*)>/gs);
|
|
151
134
|
let isJSXComponent = false;
|
|
152
135
|
elementMatch.forEach((element) => {
|
|
@@ -164,6 +147,7 @@ function Compiler(func, file) {
|
|
|
164
147
|
|
|
165
148
|
let newvalue = attributeValue.includes('=>') ? attributeValue.split("=>").slice(1).join("=>").trim() : attributeValue.split("function").slice(1).join("function").trim()
|
|
166
149
|
|
|
150
|
+
// add ; after newlines
|
|
167
151
|
|
|
168
152
|
|
|
169
153
|
newvalue = newvalue.trim();
|
|
@@ -201,7 +185,6 @@ function Compiler(func, file) {
|
|
|
201
185
|
|
|
202
186
|
|
|
203
187
|
|
|
204
|
-
functionparams.length > 0 ? params = params + ',' + functionparams.map((e) => e.name).join(',') : null
|
|
205
188
|
|
|
206
189
|
newvalue = newvalue.replaceAll(',,', ',')
|
|
207
190
|
let paramnames = params ? params.split(',').map((e) => e.trim()) : null
|
|
@@ -211,6 +194,8 @@ function Compiler(func, file) {
|
|
|
211
194
|
|
|
212
195
|
// add ; after newlines
|
|
213
196
|
newvalue = newvalue.replaceAll(/\n/g, ";\n")
|
|
197
|
+
// remove () from newvalue
|
|
198
|
+
newvalue = newvalue.replace(/\(\s*=>/gs, '=>').replace(/\function\s*\([^\)]*\)\s*\{/gs, '{')
|
|
214
199
|
|
|
215
200
|
let bind = isJSXComponent ? `${attributeName}='function(${params}){${newvalue}}'` : `${attributeName}="\$\{this.bind(function(){${newvalue}}.bind(this), ${isJSXComponent}, "${ref}", "${paramnames ? paramnames.map((e, index) => {
|
|
216
201
|
if (e.length < 1) return ''
|
|
@@ -224,10 +209,15 @@ function Compiler(func, file) {
|
|
|
224
209
|
}
|
|
225
210
|
}
|
|
226
211
|
|
|
212
|
+
/**
|
|
213
|
+
* @search - handle attributes for html elements
|
|
214
|
+
* @keywords - attributes, props, html attributes
|
|
215
|
+
*/
|
|
227
216
|
let match;
|
|
228
217
|
while ((match = elementRegex.exec(code)) !== null) {
|
|
229
218
|
let [, element, attributes] = match;
|
|
230
219
|
|
|
220
|
+
|
|
231
221
|
let attributesMatch;
|
|
232
222
|
let elementAttributes = {};
|
|
233
223
|
|
|
@@ -239,6 +229,81 @@ function Compiler(func, file) {
|
|
|
239
229
|
|
|
240
230
|
attributesList.push({ element, attributes: elementAttributes });
|
|
241
231
|
}
|
|
232
|
+
|
|
233
|
+
let spreadMatch;
|
|
234
|
+
while ((spreadMatch = spreadAttributeRegex.exec(string)) !== null) {
|
|
235
|
+
let [, element, spread] = spreadMatch;
|
|
236
|
+
|
|
237
|
+
let isJSXComponent = element.match(/[A-Z]/) ? true : false;
|
|
238
|
+
if (isJSXComponent) {
|
|
239
|
+
continue
|
|
240
|
+
|
|
241
|
+
}
|
|
242
|
+
let old = spread;
|
|
243
|
+
// turn spread into attributes
|
|
244
|
+
spread = spread.replace(/\s*$\s*=\s*/, "");
|
|
245
|
+
spread = spread.replace(/\$\s*=\s*/, "");
|
|
246
|
+
spread = spread.replace('{{', '')
|
|
247
|
+
spread = spread.replace(/,$/, '');
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
let splitByCommas = spread.split(/,(?![^{}]*})/gs).map((e) => {
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
switch (true) {
|
|
256
|
+
case e.includes('function') || e.includes('=>'):
|
|
257
|
+
e = e.replace(/\,\s*$/, '');
|
|
258
|
+
// replace commas
|
|
259
|
+
e = e.replace(/,\s*/gs, ',');
|
|
260
|
+
// remove space between (.*) =>
|
|
261
|
+
e = e.replace(/\(\s*=>/gs, '=>');
|
|
262
|
+
e = e.replace(/\s*=>\s*\{/gs, '=>{');
|
|
263
|
+
|
|
264
|
+
// add ; after newlines
|
|
265
|
+
e = e.replace(/\s*(\w+)\s*=>\s*\{/gs, '$1=>{');
|
|
266
|
+
// turn (e) => {e} into function(e){e}
|
|
267
|
+
e = e.replace(/\(([^)]*)\)\s*=>\s*\{/gs, 'function($1){\n');
|
|
268
|
+
e = e.replace(/;/g, ';\n ');
|
|
269
|
+
e = e.replace(/,\s*}\s*$/gs, '}');
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
e = e.replace(/:(.*)/gs, '="\${this.bind($1, ' + false + ', "' + Math.random().toString(36).substring(2).split('').filter((e) => !Number(e)).join('') + '", "")}"');
|
|
274
|
+
|
|
275
|
+
break;
|
|
276
|
+
case e.includes('style'):
|
|
277
|
+
e = e.replace(/,\s*$/gs, '');
|
|
278
|
+
e = e.replace(/}\s*$/gs, '');
|
|
279
|
+
e = e.replaceAll(/{\s*$/gs, '');
|
|
280
|
+
e = e.replaceAll(/}\s*$/gs, '');
|
|
281
|
+
e = e.replace(/style:(.*)/gs, 'style="\${this.parseStyle($1)}"');
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
break;
|
|
285
|
+
case e.includes('[') && e.includes(']'):
|
|
286
|
+
e = e.replace(/:(.*)/gs, '={$1.join(" ")}');
|
|
287
|
+
break;
|
|
288
|
+
default:
|
|
289
|
+
e = e.replace(/:(.*)/gs, '="${$1}"');
|
|
290
|
+
e = e.replace(/,\s*$/gs, '');
|
|
291
|
+
e = e.replace(/}\s*$/gs, '');
|
|
292
|
+
e = e.replaceAll(/{\s*$/gs, '');
|
|
293
|
+
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return e.trim();
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
let newSpread = splitByCommas.join(' ').trim().replace(/,$/, '');
|
|
301
|
+
|
|
302
|
+
// remove trailing }
|
|
303
|
+
newSpread = newSpread.replace(/}\s*$/, '')
|
|
304
|
+
newSpread = newSpread.trim().replace(/{\s*$/gs, '')
|
|
305
|
+
string = string.replace(old, newSpread);
|
|
306
|
+
}
|
|
242
307
|
|
|
243
308
|
return attributesList;
|
|
244
309
|
}
|
|
@@ -249,7 +314,6 @@ function Compiler(func, file) {
|
|
|
249
314
|
|
|
250
315
|
return returns || [];
|
|
251
316
|
}
|
|
252
|
-
// throw error if return is not wrapped in <></> or
|
|
253
317
|
if (string.match(/return\s*\<>|return\s*\(.*\)/gs) && !string.match(/return\s*\<>.*\<\/>|return\s*\(.*\)/gs)
|
|
254
318
|
|| string.match(/return\s*\<[a-zA-Z0-9_-]+.*>/gs)
|
|
255
319
|
) {
|
|
@@ -265,6 +329,10 @@ function Compiler(func, file) {
|
|
|
265
329
|
let outerReturn = extractOuterReturn(string);
|
|
266
330
|
let contents = "";
|
|
267
331
|
let updatedContents = "";
|
|
332
|
+
/**
|
|
333
|
+
* @search - handle return [...]
|
|
334
|
+
* @keywords - return, return jsx, return html, return [...]
|
|
335
|
+
*/
|
|
268
336
|
outerReturn.forEach((returnStatement) => {
|
|
269
337
|
|
|
270
338
|
let lines = returnStatement.split("\n");
|
|
@@ -279,34 +347,40 @@ function Compiler(func, file) {
|
|
|
279
347
|
let usesBraces = returnStatement.match(/return\s*\(/gs) ? true : false;
|
|
280
348
|
|
|
281
349
|
let attributes = extractAttributes(contents);
|
|
282
|
-
// Remove trailing ']' or trailing )
|
|
283
350
|
contents = contents.trim().replace(/\]$/, "")
|
|
284
351
|
contents = contents.replace(/\)$/, "");
|
|
285
352
|
usesBraces ? !contents.includes('<>') ? contents = `<>${contents}</>` : null : null
|
|
286
353
|
updatedContents = contents;
|
|
287
|
-
|
|
354
|
+
|
|
288
355
|
|
|
289
356
|
let newAttributes = [];
|
|
290
357
|
let oldAttributes = [];
|
|
291
358
|
attributes.forEach((attribute) => {
|
|
292
359
|
const { element, attributes } = attribute;
|
|
360
|
+
// make sure it isnt a jsx component
|
|
361
|
+
let isJSXComponent = element.match(/[A-Z]/) ? true : false;
|
|
362
|
+
if (isJSXComponent) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
293
365
|
if (Object.keys(attributes).length === 0) return;
|
|
294
366
|
|
|
295
367
|
|
|
296
368
|
newAttributes.push(attribute);
|
|
297
369
|
for (let key in attributes) {
|
|
298
370
|
|
|
299
|
-
let value = attributes[key];
|
|
371
|
+
let value = attributes[key];
|
|
300
372
|
let oldvalue = value;
|
|
301
373
|
if (value && !value.new) {
|
|
374
|
+
|
|
302
375
|
if (value && value.includes("={")) {
|
|
376
|
+
|
|
303
377
|
value = value.replace("=", "");
|
|
304
378
|
value == "undefined" ? (value = '"') : (value = value);
|
|
305
379
|
|
|
306
380
|
key == 'style'
|
|
307
381
|
&& value.includes("{{")
|
|
308
382
|
? value = `{this.parseStyle({${value.split('{{')[1].split('}}')[0]}})}` : null
|
|
309
|
-
|
|
383
|
+
|
|
310
384
|
|
|
311
385
|
|
|
312
386
|
value = `="\$${value}",`;
|
|
@@ -363,9 +437,7 @@ function Compiler(func, file) {
|
|
|
363
437
|
valuestate = valuestate.match(regex) ? valuestate.match(regex)[0].split("useState(")[1].split(")")[0].trim() : valuestate
|
|
364
438
|
|
|
365
439
|
|
|
366
|
-
let newState = `${varType} [${key}, ${setKey}] = this.useState('${key}', ${valuestate}
|
|
367
|
-
|
|
368
|
-
`;
|
|
440
|
+
let newState = `${varType} [${key}, ${setKey}] = this.useState('${key}', ${valuestate}`;
|
|
369
441
|
string = string.replace(line, newState);
|
|
370
442
|
break;
|
|
371
443
|
case line.includes("useRef") && !line.includes("import"):
|
|
@@ -410,54 +482,61 @@ function Compiler(func, file) {
|
|
|
410
482
|
string = string.replaceAll('../src', './src')
|
|
411
483
|
|
|
412
484
|
function parseComponents(body, isChild) {
|
|
413
|
-
let componentRegex = /<([A-Z][A-Za-z0-9_-]+)([^>]*)
|
|
485
|
+
let componentRegex = /<([A-Z][A-Za-z0-9_-]+)\s*([^>]*)>\s*([\s\S]*?)\s*<\/\1>|<([A-Z][A-Za-z0-9_-]+)([^]*?)\/>/gs;
|
|
414
486
|
|
|
415
487
|
let componentMatch = body.match(componentRegex);
|
|
416
488
|
let topComponent = "";
|
|
417
489
|
componentMatch?.forEach(async (component) => {
|
|
418
490
|
|
|
419
491
|
let [, element, attributes] = component;
|
|
420
|
-
|
|
492
|
+
let before = component;
|
|
493
|
+
component = component.trim().replace(/\s+/g, " ");
|
|
421
494
|
|
|
422
495
|
!isChild ? (topComponent = component) : null;
|
|
423
|
-
|
|
496
|
+
|
|
424
497
|
|
|
425
498
|
let myChildrens = [];
|
|
426
499
|
|
|
427
500
|
let name = component.split("<")[1].split(">")[0].split(" ")[0].replace("/", "");
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
const dynamicAttributesRegex = /(\w+)(?:="([^"]*)")?(?:='([^']*)')?(?:=\{([^}]*)\})?(?:=\{(.*?)\})?(?:={([^}]*)})?(?:{([^}]*)})?|(?:{(?:[^{}]+|\{(?:[^{}]+|\{[^}]*\})*\})*\})|(\.{3}\{(?:[^{}]+|\{(?:[^{}]+|\{[^}]*\})*\})*\})/gs;
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
501
|
+
let componentAttributes = component.split("<")[1].split(">")[0].split(" ").join(" ").replace(name, "").trim();
|
|
502
|
+
const dynamicAttributesRegex = /(\w+)(?:="([^"]*?)"|='([^']*?)'|(?:=\{([^}]*?)\})?|(?:=\{(.*?)*\})?|(?:={([^}]*?)})?|(?:{([^}]*?)})?|(?:}))?|\$=\s*\{\s*\{\s*([^]*?)\s*\}\s*\}/gs;
|
|
434
503
|
|
|
435
504
|
|
|
436
505
|
|
|
437
506
|
let props = component.match(dynamicAttributesRegex)
|
|
438
|
-
|
|
507
|
+
|
|
439
508
|
let filteredProps = [];
|
|
440
509
|
let isWithinComponent = false;
|
|
441
510
|
let componentName = name
|
|
511
|
+
let currentProps = []
|
|
512
|
+
|
|
513
|
+
let $_ternaryprops = []
|
|
442
514
|
|
|
443
515
|
for (let prop of props) {
|
|
444
516
|
|
|
445
517
|
if (prop === componentName) {
|
|
446
518
|
|
|
447
|
-
// If the component is encountered, start collecting props
|
|
448
519
|
isWithinComponent = true;
|
|
449
520
|
filteredProps.push(prop);
|
|
450
521
|
} else if (isWithinComponent && prop.includes('=')) {
|
|
522
|
+
|
|
523
|
+
if (prop.startsWith('$=')) {
|
|
524
|
+
let old = prop
|
|
525
|
+
prop = prop.replace(/\$\s*=\s*\{\s*\{/, '').replace(/\}\s*\}/, '')
|
|
526
|
+
|
|
527
|
+
component = component.replace(old, prop)
|
|
528
|
+
componentAttributes = componentAttributes.replace(old, prop)
|
|
451
529
|
|
|
452
|
-
|
|
453
|
-
// if it has an object inside of it then we should just do soemting:object else we should do something: `${object}`
|
|
530
|
+
$_ternaryprops.push(prop)
|
|
454
531
|
|
|
455
|
-
|
|
456
|
-
|
|
532
|
+
}
|
|
533
|
+
else if (prop.includes('${')) {
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
prop = prop.replace('="', ':')
|
|
537
|
+
if (prop.includes('${')) {
|
|
457
538
|
prop = prop.replace('="', ':')
|
|
458
|
-
prop = prop.replace('${', '')
|
|
459
|
-
prop = prop.replace('}', '')
|
|
460
|
-
|
|
539
|
+
prop = prop.replace('${', '')
|
|
461
540
|
}
|
|
462
541
|
if (prop.includes('="${{')) {
|
|
463
542
|
prop = prop.replace('${{', '{')
|
|
@@ -467,12 +546,21 @@ function Compiler(func, file) {
|
|
|
467
546
|
}
|
|
468
547
|
|
|
469
548
|
}
|
|
470
|
-
if (prop.
|
|
471
|
-
|
|
472
|
-
|
|
549
|
+
if (prop.includes('={')) {
|
|
550
|
+
let value = prop.split('={')
|
|
551
|
+
let isObj = value[1].match(/^{.*}$/gs) ? true : false
|
|
552
|
+
if (!isObj) {
|
|
553
|
+
// remove trailing }
|
|
554
|
+
value[1] = value[1].replace(/}\s*$/, '')
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
if(value[0] == 'style' && isObj){
|
|
558
|
+
value[1] = `this.parseStyle(${value[1]})`
|
|
559
|
+
}
|
|
560
|
+
prop = `${value[0]}:${value[1]}`
|
|
473
561
|
}
|
|
474
562
|
|
|
475
|
-
if (prop.includes('function'))
|
|
563
|
+
if (prop.includes('function') || prop.includes('=>')){
|
|
476
564
|
// parse 'function' to function
|
|
477
565
|
prop = prop.replace("'", '')
|
|
478
566
|
|
|
@@ -481,82 +569,36 @@ function Compiler(func, file) {
|
|
|
481
569
|
|
|
482
570
|
}
|
|
483
571
|
|
|
484
|
-
prop = prop.replace('=function', ':function')
|
|
572
|
+
prop = prop.replace('=function', ':function')
|
|
485
573
|
}
|
|
486
|
-
|
|
574
|
+
|
|
487
575
|
filteredProps.push(prop);
|
|
488
576
|
|
|
489
577
|
|
|
490
|
-
}
|
|
491
|
-
else if (isWithinComponent && prop.includes('...')) {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
// Check if spread props are within curly braces
|
|
496
|
-
if (prop.startsWith('{') && prop.endsWith('}')) {
|
|
497
|
-
const spreadObject = prop
|
|
498
|
-
const hasOtherObjects = spreadObject.split(',').filter((e) => e.includes(':')).length > 0;
|
|
499
|
-
|
|
500
|
-
const isValidSpread = spreadObject.includes('...');
|
|
501
|
-
|
|
502
|
-
let processedSpreadObject = '';
|
|
503
|
-
if (isValidSpread) {
|
|
504
|
-
// Split the spreadObject by commas and process each part individually
|
|
505
|
-
const parts = spreadObject.split(',').map((part) => {
|
|
506
|
-
if (part.trim().startsWith('{') && part.trim().endsWith('}')) {
|
|
507
|
-
const nestedParts = part
|
|
508
|
-
.trim()
|
|
509
|
-
.slice(1, -1) // Remove outer {}
|
|
510
|
-
.split(',')
|
|
511
|
-
.map((nestedPart) => {
|
|
512
|
-
return nestedPart.includes('...') ? nestedPart.trim().replace(/\.\.\./, '') : `...${nestedPart.trim()}`;
|
|
513
|
-
});
|
|
514
|
-
return `{${nestedParts.join(',')}}`;
|
|
515
|
-
} else {
|
|
516
|
-
return part.includes('...') ? part.trim() : part.trim().startsWith('{') ? `...${part.trim()}` : `${part.trim()}`;
|
|
517
|
-
}
|
|
518
|
-
});
|
|
519
|
-
if (!parts.join(',').includes('{(')) {
|
|
520
|
-
|
|
521
|
-
processedSpreadObject = `${parts.join(',')}`
|
|
522
|
-
|
|
523
|
-
} else {
|
|
524
|
-
let prop = parts.join(',')
|
|
525
|
-
prop = prop.replaceAll('{(', '(')
|
|
526
|
-
prop = prop.replaceAll(')}', ')')
|
|
527
|
-
processedSpreadObject = prop
|
|
528
|
-
}
|
|
529
|
-
if (prop.includes('{{')) {
|
|
530
|
-
let prop = parts.join(',')
|
|
531
|
-
prop = prop.replaceAll('{{', '{')
|
|
532
|
-
prop = prop.replaceAll('}}', '}')
|
|
533
|
-
processedSpreadObject = prop
|
|
534
|
-
}
|
|
535
|
-
|
|
536
578
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
processedSpreadObject = `{...${spreadObject}}`;
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
const $propsKey = `$props_${Math.random().toString(36).substring(2)}`;
|
|
543
|
-
filteredProps.push(`${$propsKey}:${processedSpreadObject}`);
|
|
544
|
-
}
|
|
579
|
+
}else if (isWithinComponent && prop.includes('}')) {
|
|
580
|
+
|
|
545
581
|
}
|
|
546
582
|
|
|
583
|
+
|
|
547
584
|
else {
|
|
548
585
|
isWithinComponent = false;
|
|
549
586
|
}
|
|
550
587
|
}
|
|
588
|
+
component = component.replaceAll(/\s+/g, " ");
|
|
551
589
|
|
|
552
|
-
|
|
553
|
-
|
|
590
|
+
component = component.replace(componentAttributes, '')
|
|
591
|
+
$_ternaryprops.forEach((prop) => {
|
|
592
|
+
component = component.replace(prop, '')
|
|
593
|
+
})
|
|
554
594
|
|
|
555
|
-
|
|
595
|
+
let children = new RegExp(`<${name}[^>]*>([^]*)<\/${name}>`, 'gs').exec(component)?.[1] || null;
|
|
556
596
|
|
|
557
|
-
|
|
597
|
+
props = filteredProps.join(',').replace(/\s+/g, " ").trim().replace(/,$/, '')
|
|
558
598
|
|
|
599
|
+
let savedname = name;
|
|
559
600
|
|
|
601
|
+
|
|
560
602
|
|
|
561
603
|
name = name + Math.random().toString(36).substring(2);
|
|
562
604
|
if (children && children.match(componentRegex)) {
|
|
@@ -573,12 +615,13 @@ function Compiler(func, file) {
|
|
|
573
615
|
/<([A-Z][A-Za-z0-9_-]+)([^>]*)>(.*?)<\/\1>|<([A-Z][A-Za-z0-9_-]+)([^]*?)\/>/gs
|
|
574
616
|
);
|
|
575
617
|
if (html) {
|
|
576
|
-
html = html.map((h) => h.trim().replace(/\s+/g, " ")).join(" ");
|
|
618
|
+
html = html.map((h) => h.trim().replace(/\s+/g, " ")).join(" ");
|
|
577
619
|
child.children = child.children.replaceAll(html, `${html}`);
|
|
578
620
|
// remove duplicate quotes
|
|
579
621
|
}
|
|
580
622
|
|
|
581
623
|
myChildrens.push(child.children);
|
|
624
|
+
childs = childs.filter((e) => e.parent !== name);
|
|
582
625
|
}
|
|
583
626
|
});
|
|
584
627
|
|
|
@@ -599,8 +642,10 @@ function Compiler(func, file) {
|
|
|
599
642
|
* @memoize - memoize a component to be remembered on each render and replace the old jsx
|
|
600
643
|
*/
|
|
601
644
|
|
|
645
|
+
|
|
602
646
|
let replace = "";
|
|
603
|
-
replace = `\${this.memoize(this.createComponent(${savedname}, {${props}}, [\`${myChildrens.join(
|
|
647
|
+
replace = `\${this.memoize(this.createComponent(${savedname}, {${props}}, [\`${myChildrens.join('')}\`]))}`;
|
|
648
|
+
|
|
604
649
|
|
|
605
650
|
body = body.replace(before, replace);
|
|
606
651
|
});
|
|
@@ -613,55 +658,55 @@ function Compiler(func, file) {
|
|
|
613
658
|
const importRegex = /import\s*([^\s,]+|\{[^}]+\})\s*from\s*(['"])(.*?)\2/g;
|
|
614
659
|
const imports = string.match(importRegex);
|
|
615
660
|
let replaceMents = [];
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
for
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
for (let match of imports) {
|
|
619
664
|
let path = match.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').trim()
|
|
620
665
|
switch (true) {
|
|
621
666
|
case path && !path.includes('./') && !path.includes('/vader.js') && !path.includes('/vaderjs/client') && !path.startsWith('src') && !path.startsWith('public') && !path.includes('http') && !path.includes('https'):
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
667
|
+
let componentFolder = fs.existsSync(process.cwd() + '/node_modules/' + path) ? process.cwd() + '/node_modules/' + path : process.cwd() + '/node_modules/' + path.split('/')[0]
|
|
668
|
+
componentFolder = componentFolder.split(process.cwd())[1]
|
|
669
|
+
if (!fs.existsSync(process.cwd() + componentFolder)) {
|
|
625
670
|
throw new Error('Could not find ' + path + ' at ' + match + ' in file ' + file)
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
if (!fs.existsSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'))) {
|
|
674
|
+
fs.mkdirSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'), { recursive: true })
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
let baseFolder = componentFolder.split('node_modules')[1].split('/')[1]
|
|
678
|
+
let glp = globSync('**/**/**/**.{jsx,js}', {
|
|
679
|
+
cwd: process.cwd() + '/node_modules/' + baseFolder + '/',
|
|
680
|
+
absolute: true,
|
|
681
|
+
recursive: true
|
|
682
|
+
})
|
|
683
|
+
for (let file of glp) {
|
|
684
|
+
let text = fs.readFileSync(file, "utf8");
|
|
685
|
+
if (!file.endsWith('.js') && file.endsWith('.jsx')) {
|
|
686
|
+
text = Compiler(text, file);
|
|
687
|
+
|
|
630
688
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
}
|
|
643
|
-
let dest = file.split('node_modules')[1]
|
|
644
|
-
dest = dest.split(baseFolder)[1]
|
|
645
|
-
// write to dist
|
|
646
|
-
writer(process.cwd() + '/dist/src/' + baseFolder + dest, text)
|
|
647
|
-
let importname = match.split('import')[1].split('from')[0].trim()
|
|
648
|
-
let oldImportstring = match.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').trim()
|
|
649
|
-
let newImport = `/src/${baseFolder + dest}`
|
|
650
|
-
newImport = newImport.replaceAll('.jsx', '.js').replaceAll('\\', '/')
|
|
651
|
-
replaceMents.push({ match: oldImportstring, replace: newImport })
|
|
652
|
-
console.log(`📦 imported Node Package ${baseFolder} `)
|
|
653
|
-
}
|
|
654
|
-
|
|
689
|
+
let dest = file.split('node_modules')[1]
|
|
690
|
+
dest = dest.split(baseFolder)[1]
|
|
691
|
+
writer(process.cwd() + '/dist/src/' + baseFolder + dest, text)
|
|
692
|
+
let importname = match.split('import')[1].split('from')[0].trim()
|
|
693
|
+
let oldImportstring = match.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').trim()
|
|
694
|
+
let newImport = `/src/${baseFolder + dest}`
|
|
695
|
+
newImport = newImport.replaceAll('.jsx', '.js').replaceAll('\\', '/')
|
|
696
|
+
replaceMents.push({ match: oldImportstring, replace: newImport })
|
|
697
|
+
console.log(`📦 imported Node Package ${baseFolder} `)
|
|
698
|
+
}
|
|
699
|
+
|
|
655
700
|
|
|
656
701
|
break;
|
|
657
702
|
default:
|
|
658
703
|
break;
|
|
659
704
|
}
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
for(let replace of replaceMents){
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
for (let replace of replaceMents) {
|
|
663
708
|
string = string.replaceAll(replace.match, replace.replace)
|
|
664
|
-
}
|
|
709
|
+
}
|
|
665
710
|
|
|
666
711
|
string = string.replaceAll(/\$\{[^{]*\.{3}/gs, (match) => {
|
|
667
712
|
if (match.includes('...')) {
|
|
@@ -716,7 +761,7 @@ function Compiler(func, file) {
|
|
|
716
761
|
let asyncimportMatch = line.match(/import\s*\((.*)\)/gs);
|
|
717
762
|
// handle import { Component } from 'vaderjs/runtime/vader.js'
|
|
718
763
|
let regularimportMatch = line.match(/import\s*([A-Za-z0-9_-]+)\s*from\s*([A-Za-z0-9_-]+)|import\s*([A-Za-z0-9_-]+)\s*from\s*(".*")|import\s*([A-Za-z0-9_-]+)\s*from\s*('.*')|import\s*([A-Za-z0-9_-]+)\s*from\s*(\{.*\})/gs);
|
|
719
|
-
|
|
764
|
+
|
|
720
765
|
if (asyncimportMatch) {
|
|
721
766
|
asyncimportMatch.forEach(async (match) => {
|
|
722
767
|
let beforeimport = match
|
|
@@ -770,7 +815,7 @@ function Compiler(func, file) {
|
|
|
770
815
|
|
|
771
816
|
let newImport = ''
|
|
772
817
|
let name = match.split('import')[1].split('from')[0].trim()
|
|
773
|
-
|
|
818
|
+
|
|
774
819
|
|
|
775
820
|
switch (true) {
|
|
776
821
|
case path && path.includes('json'):
|
|
@@ -796,9 +841,9 @@ function Compiler(func, file) {
|
|
|
796
841
|
newImport = ``
|
|
797
842
|
break;
|
|
798
843
|
case path && !path.startsWith('./') && !path.includes('/vader.js') && !path.startsWith('src') && !path.startsWith('public') &&
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
844
|
+
path.match(/^[A-Za-z0-9_-]+$/gs) && !path.includes('http') && !path.includes('https'):
|
|
845
|
+
|
|
846
|
+
break;
|
|
802
847
|
default:
|
|
803
848
|
let beforePath = path
|
|
804
849
|
let deep = path.split('/').length - 1
|
|
@@ -850,26 +895,20 @@ const glb = await glob("**/**/**/**.{jsx,js}", {
|
|
|
850
895
|
});
|
|
851
896
|
async function Build() {
|
|
852
897
|
globalThis.isBuilding = true
|
|
853
|
-
console.log('
|
|
898
|
+
console.log(globalThis.isProduction ? 'Creating Optimized Production Build\n' : '')
|
|
899
|
+
let str = `Page \t\t\t\t Size\n`
|
|
900
|
+
globalThis.isProduction ? console.log('\x1b[32m%s\x1b[0m', str) : null
|
|
854
901
|
let reader = async (file) => {
|
|
855
902
|
let text = await fs.readFileSync(file, "utf8");
|
|
856
903
|
return text;
|
|
857
904
|
};
|
|
858
905
|
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
906
|
|
|
863
|
-
|
|
864
|
-
// Process files in the 'pages' directory
|
|
865
|
-
let appjs = '';
|
|
866
|
-
let hasWritten = []
|
|
907
|
+
|
|
867
908
|
function ssg(routes = []) {
|
|
868
|
-
globalThis.isBuilding = true
|
|
869
|
-
console.log(`Generating html files for ${routes.length} routes`)
|
|
909
|
+
globalThis.isBuilding = true
|
|
870
910
|
routes.forEach(async (route) => {
|
|
871
|
-
if (route.url.includes(':')) {
|
|
872
|
-
console.log('Route ' + route.url + ' is a dynamic route and will not be generated')
|
|
911
|
+
if (route.url.includes(':')) {
|
|
873
912
|
return
|
|
874
913
|
}
|
|
875
914
|
let equalparamroute = routes.map((e) => {
|
|
@@ -897,65 +936,24 @@ async function Build() {
|
|
|
897
936
|
<meta charset="UTF-8">
|
|
898
937
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
899
938
|
<script type="module" id="meta">
|
|
900
|
-
window.history.pushState({}, '', '${route.url}')
|
|
901
|
-
window.module = await import('/${route.fileName.replace('.jsx', '.js')}')
|
|
902
|
-
let metadata = await module.$metadata
|
|
903
|
-
if(metadata && metadata.title){
|
|
904
|
-
document.head.innerHTML += '<title>' + metadata.title + '</title>'
|
|
905
|
-
}
|
|
906
|
-
if(metadata && metadata.description){
|
|
907
|
-
document.head.innerHTML += '<meta name="description" content="' + metadata.description + '">'
|
|
908
|
-
}
|
|
909
|
-
if(metadata && metadata.keywords){
|
|
910
|
-
document.head.innerHTML += '<meta name="keywords" content="' + metadata.keywords + '">'
|
|
911
|
-
}
|
|
912
|
-
if(metadata && metadata.author){
|
|
913
|
-
document.head.innerHTML += '<meta name="author" content="' + metadata.author + '">'
|
|
914
|
-
}
|
|
915
|
-
if(metadata && metadata.image){
|
|
916
|
-
let image = metadata.image.file
|
|
917
|
-
let type = metadata.image.type
|
|
918
|
-
|
|
919
|
-
document.head.innerHTML += '<meta property="og:image" content="' + image + '">'
|
|
920
|
-
document.head.innerHTML += '<meta property="og:image:type" content="' + type + '">'
|
|
921
|
-
}
|
|
922
|
-
if(metadata && metadata.url){
|
|
923
|
-
document.head.innerHTML += '<meta property="og:url" content="' + metadata.url + '">'
|
|
924
|
-
}
|
|
939
|
+
window.history.pushState({}, '', '${route.url}')
|
|
925
940
|
|
|
926
|
-
if(metadata && metadata.robot){
|
|
927
|
-
document.head.innerHTML += '<meta name="robots" content="' + metadata.robot + '">'
|
|
928
|
-
}
|
|
929
|
-
if(metadata && metadata.manifest){
|
|
930
|
-
document.head.innerHTML += '<link rel="manifest" href="' + metadata.manifest + '">'
|
|
931
|
-
}
|
|
932
|
-
if(metadata && metadata.tags){
|
|
933
|
-
metadata.tags.forEach(tag => {
|
|
934
|
-
document.head.innerHTML += tag
|
|
935
|
-
})
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
if(metadata && metadata.styles){
|
|
939
|
-
metadata.styles.forEach(style => {
|
|
940
|
-
style = style.replaceAll('./', '/')
|
|
941
|
-
style = style.replaceAll('../', '/')
|
|
942
|
-
style = style.replace("'", '')
|
|
943
|
-
document.head.innerHTML += '<link rel="stylesheet" href="' + style + '">'
|
|
944
|
-
})
|
|
945
|
-
}
|
|
946
|
-
if(metadata && metadata.icon){
|
|
947
|
-
document.head.innerHTML += '<link rel="icon" href="' + metadata.icon + '">'
|
|
948
|
-
}
|
|
949
941
|
</script>
|
|
950
942
|
<script type="module" id="router">
|
|
951
943
|
import VaderRouter from '/router.js'
|
|
952
944
|
const router = new VaderRouter('${route.url}', 3000)
|
|
953
945
|
router.get('${route.url}', async (req, res) => {
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
946
|
+
try{
|
|
947
|
+
let module = await import('/${route.fileName.replace('.jsx', '.js')}')
|
|
948
|
+
if(Object.keys(module).includes('$prerender') && !module.$prerender){
|
|
949
|
+
document.head.setAttribute('prerender', 'false')
|
|
950
|
+
}
|
|
951
|
+
res.render(module, req, res, module.$metadata)
|
|
952
|
+
}
|
|
953
|
+
catch(error){
|
|
954
|
+
document.documentElement.setAttribute('error', JSON.stringify({stack: error.stack, message: error.message, at: '${route.fileName}', line: error.lineNumber}))
|
|
955
|
+
throw new Error({stack: error.stack, message: error.message})
|
|
957
956
|
}
|
|
958
|
-
res.render(module, req, res, module.$metadata)
|
|
959
957
|
})
|
|
960
958
|
${equalparamroute.length > 0 ? equalparamroute.map((e) => {
|
|
961
959
|
|
|
@@ -1016,52 +1014,76 @@ async function Build() {
|
|
|
1016
1014
|
globalThis.listen = true;
|
|
1017
1015
|
|
|
1018
1016
|
const browser = await puppeteer.launch({
|
|
1019
|
-
headless:
|
|
1017
|
+
headless: "new", args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
|
1020
1018
|
warning: false,
|
|
1021
|
-
})
|
|
1022
|
-
|
|
1023
|
-
const browserPID = browser.process().pid
|
|
1019
|
+
})
|
|
1024
1020
|
try {
|
|
1025
1021
|
|
|
1026
1022
|
route.url = route.url.replaceAll(/\/:[a-zA-Z0-9_-]+/gs, '')
|
|
1027
1023
|
let page = await browser.newPage();
|
|
1028
|
-
|
|
1029
|
-
|
|
1024
|
+
// Handle browser errors
|
|
1025
|
+
page.on('error', (err) => {
|
|
1026
|
+
console.error('BROWSER ERROR:', err);
|
|
1027
|
+
});
|
|
1028
|
+
await page.evaluate(() => {
|
|
1029
|
+
window.onerror = function (msg, url, lineNo, columnNo, error) {
|
|
1030
|
+
console.log(msg, url, lineNo, columnNo, error)
|
|
1031
|
+
}
|
|
1032
|
+
})
|
|
1033
|
+
try {
|
|
1034
|
+
page.on('pageerror', async err => {
|
|
1035
|
+
let errorObj = await page.evaluate(() => document.documentElement.getAttribute('error'))
|
|
1036
|
+
console.log('\x1b[31m%s\x1b[0m', 'PAGE ERROR:', errorObj);
|
|
1037
|
+
|
|
1038
|
+
});
|
|
1039
|
+
} catch (error) {
|
|
1040
|
+
browser.close()
|
|
1041
|
+
}
|
|
1042
|
+
// Handle page crashes
|
|
1043
|
+
page.on('crash', () => {
|
|
1044
|
+
console.error('PAGE CRASHED');
|
|
1045
|
+
});
|
|
1046
|
+
page.on('requestfailed', request => {
|
|
1047
|
+
console.error('REQUEST FAILED:', request.url(), request.failure().errorText);
|
|
1048
|
+
});
|
|
1049
|
+
await page.goto(`http://localhost:${port}/`, { waitUntil: 'networkidle2' });
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
|
|
1053
|
+
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
|
|
1030
1057
|
await page.evaluate(() => {
|
|
1031
1058
|
document.getElementById('meta').remove()
|
|
1032
1059
|
document.querySelector('#isServer').innerHTML = 'window.isServer = false'
|
|
1033
1060
|
if (document.head.getAttribute('prerender') === 'false') {
|
|
1034
1061
|
document.querySelector('#root').innerHTML = ''
|
|
1062
|
+
console.log(`Disabled prerendering for ${window.location.pathname}`)
|
|
1035
1063
|
}
|
|
1036
|
-
})
|
|
1037
|
-
|
|
1064
|
+
})
|
|
1065
|
+
let html = await page.content();
|
|
1038
1066
|
|
|
1039
|
-
await
|
|
1067
|
+
html = await prettier.format(html, { parser: "html" })
|
|
1068
|
+
|
|
1069
|
+
|
|
1040
1070
|
await writer(process.cwd() + '/dist/' + (route.url === '/' ? 'index.html' : `${route.url}/` + 'index.html'), html)
|
|
1041
|
-
await browser.close();
|
|
1042
|
-
server.close()
|
|
1043
1071
|
|
|
1072
|
+
|
|
1044
1073
|
} catch (error) {
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1074
|
+
console.log(error)
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1048
1077
|
finally {
|
|
1049
|
-
|
|
1078
|
+
browser.close()
|
|
1050
1079
|
server.close()
|
|
1051
1080
|
}
|
|
1052
|
-
try {
|
|
1053
|
-
process.kill(browserPID )
|
|
1054
|
-
} catch (error) {
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
1081
|
})
|
|
1059
1082
|
|
|
1060
1083
|
let timeout = setTimeout(() => {
|
|
1061
1084
|
globalThis.isBuilding = false
|
|
1062
1085
|
clearTimeout(timeout)
|
|
1063
|
-
}, 1000)
|
|
1064
|
-
console.log(`Generated ${routes.length} html files for ${routes.length} routes`)
|
|
1086
|
+
}, 1000)
|
|
1065
1087
|
}
|
|
1066
1088
|
|
|
1067
1089
|
globalThis.routes = []
|
|
@@ -1093,17 +1115,14 @@ async function Build() {
|
|
|
1093
1115
|
|
|
1094
1116
|
|
|
1095
1117
|
let data = await fs.readFileSync(origin, "utf8");
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
await writer(process.cwd() + "/dist/" + fileName.replace('.jsx', '.js'), data)
|
|
1105
|
-
|
|
1106
|
-
})
|
|
1118
|
+
|
|
1119
|
+
// gen sourcemap if not production
|
|
1120
|
+
let size = fs.statSync(origin).size;
|
|
1121
|
+
if(!globalThis.isProduction){
|
|
1122
|
+
let { sourceMap } = sourceMapGen({origin:origin, fileName:fileName}, await Compiler(data, origin))
|
|
1123
|
+
await writer(process.cwd() + "/dist/src/maps/" + fileName.replace('.jsx', '.js.map'), JSON.stringify(sourceMap, null, 2))
|
|
1124
|
+
}
|
|
1125
|
+
await writer(process.cwd() + "/dist/" + fileName.replace('.jsx', '.js'), await Compiler(data, origin))
|
|
1107
1126
|
|
|
1108
1127
|
// configure routing for each page
|
|
1109
1128
|
|
|
@@ -1167,8 +1186,18 @@ async function Build() {
|
|
|
1167
1186
|
|
|
1168
1187
|
globalThis.routes.push({ fileName: fileName, url: obj.url, html: '/' + (isBasePath ? 'index.html' : `${obj.url}/` + 'index.html') })
|
|
1169
1188
|
|
|
1170
|
-
|
|
1171
|
-
|
|
1189
|
+
|
|
1190
|
+
let stats = {route: obj.url.padEnd(30),
|
|
1191
|
+
size: Math.round(size / 1000) + 'kb',
|
|
1192
|
+
letParentFolder: obj.url.split('/').slice(0, -1).join('/'),
|
|
1193
|
+
isChildRoute: obj.url.split('/').slice(0, -1).join('/').includes(':') ? true : false,
|
|
1194
|
+
parentRoute: obj.url.split('/').slice(0, -1).join('/').split(':')[0],
|
|
1195
|
+
|
|
1196
|
+
}
|
|
1197
|
+
stats.isChildRoute ? stats.route = `? ${obj.url}` : null
|
|
1198
|
+
let string = `${isBasePath ? '+' : '+'} ${stats.route.padEnd(30)} ${stats.size}`
|
|
1199
|
+
|
|
1200
|
+
globalThis.isProduction ? console.log(string) : null
|
|
1172
1201
|
}
|
|
1173
1202
|
|
|
1174
1203
|
ssg(globalThis.routes)
|
|
@@ -1205,10 +1234,7 @@ async function Build() {
|
|
|
1205
1234
|
if (name.includes('.jsx')) {
|
|
1206
1235
|
data = Compiler(data, process.cwd() + "/src/" + name);
|
|
1207
1236
|
|
|
1208
|
-
await writer(process.cwd() + "/dist/src/" + name.split('.jsx').join('.js'), data)
|
|
1209
|
-
await writer(process.cwd() + "/dist/src/" + name.replace('.jsx', '.js'), data)
|
|
1210
|
-
|
|
1211
|
-
})
|
|
1237
|
+
await writer(process.cwd() + "/dist/src/" + name.split('.jsx').join('.js'), data)
|
|
1212
1238
|
return
|
|
1213
1239
|
}
|
|
1214
1240
|
bundleSize += fs.statSync(process.cwd() + "/src/" + name).size;
|
|
@@ -1256,17 +1282,17 @@ async function Build() {
|
|
|
1256
1282
|
}
|
|
1257
1283
|
|
|
1258
1284
|
globalThis.isBuilding = false
|
|
1259
|
-
console.log(
|
|
1285
|
+
console.log(`\nTotal bundle size: ${Math.round(bundleSize / 1000)}kb`)
|
|
1260
1286
|
|
|
1261
1287
|
bundleSize = 0;
|
|
1262
|
-
|
|
1288
|
+
|
|
1263
1289
|
return true
|
|
1264
1290
|
}
|
|
1265
1291
|
const s = () => {
|
|
1266
1292
|
|
|
1267
1293
|
const server = http.createServer((req, res) => {
|
|
1268
1294
|
|
|
1269
|
-
const validExtensions = ['.js', '.css', '.mjs', '.cjs', '.html', '.json', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.mp4', '.webm', '.ogg']
|
|
1295
|
+
const validExtensions = ['.js', '.css', '.mjs', '.cjs', '.html', '.json', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.mp4', '.webm', '.ogg', '.map']
|
|
1270
1296
|
|
|
1271
1297
|
if (!validExtensions.some(ext => req.url.endsWith(ext))) {
|
|
1272
1298
|
req.url = req.url !== '/' ? req.url.split('/')[1] : req.url;
|
|
@@ -1289,6 +1315,7 @@ const s = () => {
|
|
|
1289
1315
|
let ws = new WebSocket('ws://localhost:${process.env.PORT || 3000}')
|
|
1290
1316
|
ws.onmessage = (e) => {
|
|
1291
1317
|
if(e.data === 'reload'){
|
|
1318
|
+
console.log('Reloading...')
|
|
1292
1319
|
window.location.reload()
|
|
1293
1320
|
}
|
|
1294
1321
|
}
|
|
@@ -1310,7 +1337,7 @@ const s = () => {
|
|
|
1310
1337
|
|
|
1311
1338
|
|
|
1312
1339
|
function getContentType(filePath) {
|
|
1313
|
-
let ext = ['.js', '.css', '.mjs', '.cjs', '.html', '.json', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.mp4', '.webm', '.ogg'].includes(path.extname(filePath)) ? path.extname(filePath) : '.html'
|
|
1340
|
+
let ext = ['.js', '.css', '.mjs', '.cjs', '.html', '.json', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.mp4', '.webm', '.ogg', '.map'].includes(path.extname(filePath)) ? path.extname(filePath) : '.html'
|
|
1314
1341
|
switch (ext) {
|
|
1315
1342
|
case '.js':
|
|
1316
1343
|
return 'text/javascript';
|
|
@@ -1322,6 +1349,8 @@ const s = () => {
|
|
|
1322
1349
|
return 'text/javascript';
|
|
1323
1350
|
case '.html':
|
|
1324
1351
|
return 'text/html';
|
|
1352
|
+
case '.map':
|
|
1353
|
+
return 'application/json';
|
|
1325
1354
|
case '.json':
|
|
1326
1355
|
return 'application/json';
|
|
1327
1356
|
case '.png':
|
|
@@ -1348,26 +1377,18 @@ const s = () => {
|
|
|
1348
1377
|
const PORT = process.env.PORT || 3000;
|
|
1349
1378
|
server.listen(PORT, () => {
|
|
1350
1379
|
console.log(`Server is running on port ${PORT}`);
|
|
1380
|
+
globalThis.ws = ws
|
|
1351
1381
|
});
|
|
1352
|
-
|
|
1353
|
-
setInterval(() => {
|
|
1354
|
-
if (globalThis.isBuilding && globalThis.devMode) {
|
|
1355
|
-
|
|
1356
|
-
ws.clients.forEach((client) => {
|
|
1357
|
-
client.send('reload')
|
|
1358
|
-
})
|
|
1359
|
-
} else {
|
|
1360
|
-
clearInterval(i)
|
|
1361
|
-
}
|
|
1362
|
-
}, 120)
|
|
1382
|
+
|
|
1363
1383
|
|
|
1364
1384
|
}
|
|
1365
1385
|
|
|
1366
1386
|
|
|
1367
1387
|
switch (true) {
|
|
1368
|
-
case process.argv.includes('
|
|
1388
|
+
case process.argv.includes('dev') && !process.argv.includes('build') && !process.argv.includes('start'):
|
|
1369
1389
|
|
|
1370
1390
|
globalThis.devMode = true
|
|
1391
|
+
globalThis.isProduction = false
|
|
1371
1392
|
console.log(`
|
|
1372
1393
|
Vader.js v1.3.3
|
|
1373
1394
|
- Watching for changes in ./pages
|
|
@@ -1384,12 +1405,19 @@ Vader.js v1.3.3
|
|
|
1384
1405
|
if (event == 'change'
|
|
1385
1406
|
&& !globalThis.isBuilding
|
|
1386
1407
|
) {
|
|
1408
|
+
if(globalThis.ws && !globalThis.isWriting){
|
|
1409
|
+
globalThis.ws.clients.forEach((client) => {
|
|
1410
|
+
console.log('Reloading...')
|
|
1411
|
+
client.send('reload')
|
|
1412
|
+
})
|
|
1413
|
+
}
|
|
1387
1414
|
|
|
1415
|
+
globalThis.isBuilding = true
|
|
1388
1416
|
Build()
|
|
1389
1417
|
}
|
|
1390
1418
|
}).on('error', (err) => console.log(err))
|
|
1391
1419
|
})
|
|
1392
|
-
let p = process.argv[process.argv.indexOf('
|
|
1420
|
+
let p = process.argv[process.argv.indexOf('dev') + 1] || 3000
|
|
1393
1421
|
|
|
1394
1422
|
process.env.PORT = p
|
|
1395
1423
|
s()
|
|
@@ -1397,16 +1425,21 @@ Vader.js v1.3.3
|
|
|
1397
1425
|
globalThis.listen = true;
|
|
1398
1426
|
|
|
1399
1427
|
break;
|
|
1400
|
-
case process.argv.includes('
|
|
1428
|
+
case process.argv.includes('build') && !process.argv.includes('dev') && !process.argv.includes('start'):
|
|
1401
1429
|
globalThis.devMode = false
|
|
1430
|
+
globalThis.isProduction = true
|
|
1431
|
+
globalThis.routeStates = []
|
|
1402
1432
|
console.log(`
|
|
1403
1433
|
Vader.js v1.3.3
|
|
1404
1434
|
Building to ./dist
|
|
1405
1435
|
`)
|
|
1436
|
+
if(fs.existsSync(process.cwd() + '/dist/src/maps')){
|
|
1437
|
+
fs.rmSync(process.cwd() + '/dist/src/maps', { recursive: true })
|
|
1438
|
+
}
|
|
1406
1439
|
Build()
|
|
1407
1440
|
|
|
1408
1441
|
break;
|
|
1409
|
-
case process.argv.includes('
|
|
1442
|
+
case process.argv.includes('start') && !process.argv.includes('dev') && !process.argv.includes('build'):
|
|
1410
1443
|
let port = process.argv[process.argv.indexOf('--serve') + 1] || 3000
|
|
1411
1444
|
process.env.PORT = port
|
|
1412
1445
|
globalThis.devMode = false
|
|
@@ -1418,17 +1451,19 @@ url: http://localhost:${port}
|
|
|
1418
1451
|
s()
|
|
1419
1452
|
break;
|
|
1420
1453
|
default:
|
|
1421
|
-
|
|
1454
|
+
// add color
|
|
1455
|
+
console.log(`
|
|
1422
1456
|
Vader.js is a reactive framework for building interactive applications for the web built ontop of bun.js!
|
|
1423
1457
|
|
|
1424
1458
|
Usage: vader <command>
|
|
1425
1459
|
|
|
1426
1460
|
Commands:
|
|
1427
|
-
|
|
1461
|
+
|
|
1462
|
+
vaderjs dev Start the development server
|
|
1428
1463
|
|
|
1429
|
-
|
|
1464
|
+
vaderjs build Build the project to ./dist
|
|
1430
1465
|
|
|
1431
|
-
|
|
1466
|
+
vaderjs start <port> Production Mode (default 3000 or process.env.PORT)
|
|
1432
1467
|
|
|
1433
1468
|
Learn more about vader: https://vader-js.pages.dev/
|
|
1434
1469
|
|