vaderjs 1.3.3-5b5a772ebe58 → 1.3.3-7924566dd811
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 +1 -1
- package/runtime/router.js +1 -1
- package/runtime/vader.js +1 -1
- package/vader.js +189 -209
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
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
|
|
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 isClass(e){return"function"==typeof e&&/^class\s/.test(Function.prototype.toString.call(e))}let r=isClass(e)?new e(t):null;if(!e)throw new Error("Component must be defined");let i=new Component(t);if(isClass(e))r.props=t||{},r.props.children=s.join("")||[],r.props.children=s.join(""),r.parentNode=this,r.request=this.request,r.response=this.response,r.key=r.props.key?r.props.key:Math.random(),i=r;else{e.toString();i.key=e.toString().split('key="')[1]?e.toString().split('key="')[1].split('"')[0]:null;let r=[];Object.keys(t).forEach((e=>{if(e.startsWith("$props")&&(r.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]}))}})),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(">,",">")),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];i&&n&&!i.isEqualNode(n)&&s.push({type:"replace",old:i,new:n.cloneNode(!0)})}return s}updateChangedElements(e){e.forEach((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("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{if(this.key?document.querySelector(`[key="${this.key}"]`):null){let e=(new DOMParser).parseFromString(this.render(),"text/html").body.querySelector(`[key="${this.key}"]`),t=document.querySelector(`[key="${this.key}"]`),s=this.domDifference(t.children,e.children);this.updateChangedElements(s)}}}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)=>{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)`}setState(e,t){this.state=e,this.hydrate(t)}useState(e,t){this.state.hasOwnProperty(e)||(this.state[e]=t);return[(()=>this.state[e])(),(t,s)=>{this.state[e]=t,this.hydrate(s)}]}useRef(e=null,t){this.state[e]||(this.state[e]=t);return{bind:e+this.key,current:(()=>document.querySelector(`[ref="${e+this.key}"]`)||t)()}}useReducer(e=null,t,s=null){this.state[e]||(this.state[e]=t);const getValue=()=>this.state[e];let r=getValue();return[getValue(),(t,i)=>{const n=s(r,t)??t;this.state[e]=n,this.hydrate(i),r=getValue()}]}render(){}checkIFMounted(){new MutationObserver((e=>{e.forEach((e=>{e.target.querySelector(`[key="${this.key}"]`)&&!this.mounted&&(this.onMount(),this.mounted=!0),Array.from(e.removedNodes).find((e=>e.attributes&&e.attributes.key&&e.attributes.key.value===this.key))&&(this.onUnmount(),this.reset())}))})).observe(document.body,{childList:!0,subtree:!0})}onMount(){}onUnmount(){}}export const useState=(e,t)=>{this.state[e]||(this.state[e]=t);return[states[e],(t,s)=>{states[e]=t,this.hydrate(s)}]};export const useReducer=(e,t)=>[e,e=>{}];export const useRef=e=>({current:e,bind:""});export class Link extends Component{constructor(e){super(e),this.props=e,this.link=document.createElement("a"),this.key=e.href+Math.random(),this.nokey=!0}render(){return this.link.innerHTML=this.props.children,this.link.setAttribute("id",this.props?.href),this.link.style=this.props?.style,this.link.setAttribute("class",this.props?.class),this.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){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
|
@@ -22,16 +22,8 @@ let writer = async (file, data) => {
|
|
|
22
22
|
globalThis.isWriting = null
|
|
23
23
|
return { _written: true };
|
|
24
24
|
};
|
|
25
|
-
|
|
26
|
-
let
|
|
27
|
-
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
|
-
|
|
25
|
+
|
|
26
|
+
let bundleSize = 0;
|
|
35
27
|
|
|
36
28
|
if (!fs.existsSync(process.cwd() + '/dist')) {
|
|
37
29
|
fs.mkdirSync(process.cwd() + '/dist')
|
|
@@ -48,44 +40,13 @@ if (typeof process.env.isCloudflare !== "undefined" || !fs.existsSync(process.cw
|
|
|
48
40
|
|
|
49
41
|
|
|
50
42
|
function Compiler(func, file) {
|
|
51
|
-
let string = func;
|
|
52
|
-
// Remove block comments
|
|
53
|
-
|
|
43
|
+
let string = func;
|
|
54
44
|
let returns = []
|
|
55
45
|
let comments = string.match(/\{\s*\/\*.*\*\/\s*}/gs)?.map((comment) => comment.trim());
|
|
56
46
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
)
|
|
61
|
-
?.map((match) => match.trim());
|
|
62
|
-
|
|
63
|
-
let functionNames = [];
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
});
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
89
50
|
|
|
90
51
|
// get all Obj({}) and parse to JSON.stringify
|
|
91
52
|
|
|
@@ -101,6 +62,51 @@ function Compiler(func, file) {
|
|
|
101
62
|
|
|
102
63
|
let childs = [];
|
|
103
64
|
|
|
65
|
+
const spreadAttributeRegex = /\s*([a-zA-Z0-9_-]+)(\s*\$\s*=\s*{{((?:[^{}]|(?:\{(?:[^{}]|(?:\{[^{}]*\})*)*\})*)*)}})/gs;
|
|
66
|
+
let spreadMatch;
|
|
67
|
+
while ((spreadMatch = spreadAttributeRegex.exec(string)) !== null) {
|
|
68
|
+
let [, element, spread] = spreadMatch;
|
|
69
|
+
let isJSXComponent = element.match(/[A-Z]/) ? true : false;
|
|
70
|
+
if (isJSXComponent) {
|
|
71
|
+
continue
|
|
72
|
+
|
|
73
|
+
}
|
|
74
|
+
let old = spread;
|
|
75
|
+
|
|
76
|
+
// turn spread into attributes
|
|
77
|
+
spread = spread.replace(/\s*$\s*=\s*/, "");
|
|
78
|
+
spread = spread.replace(/{{/, "");
|
|
79
|
+
spread = spread.replace(/}}/, "");
|
|
80
|
+
spread = spread.replace(/\$\s*=\s*/, "");
|
|
81
|
+
|
|
82
|
+
// turn : into =
|
|
83
|
+
|
|
84
|
+
// do not split inner Objects ex: {color: 'red', background: {color: 'blue'}} -> {color: 'red', background: {color: 'blue'}}
|
|
85
|
+
let splitByCommas = spread.split(/,(?![^{]*})/g);
|
|
86
|
+
splitByCommas = splitByCommas.map((e) => e.trim())
|
|
87
|
+
splitByCommas = splitByCommas.map((e) => {
|
|
88
|
+
switch (true) {
|
|
89
|
+
case e.includes('function') || e.includes('=>'):
|
|
90
|
+
e = e.replace(/:(.*)/gs, '={$1}')
|
|
91
|
+
break;
|
|
92
|
+
case e.includes('style'):
|
|
93
|
+
e = e.replace(/:(.*)/gs, '="${this.parseStyle($1)}"')
|
|
94
|
+
break;
|
|
95
|
+
case e.includes('[') && e.includes(']'):
|
|
96
|
+
e = e.replace(/:(.*)/gs, '={$1.join(" ")}')
|
|
97
|
+
break;
|
|
98
|
+
default:
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return e.trim()
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
let newSpread = `\t` + splitByCommas.join(' ') + `\t`
|
|
105
|
+
|
|
106
|
+
string = string.replace(old, newSpread);
|
|
107
|
+
|
|
108
|
+
}
|
|
109
|
+
|
|
104
110
|
|
|
105
111
|
|
|
106
112
|
function extractAttributes(code) {
|
|
@@ -112,41 +118,42 @@ function Compiler(func, file) {
|
|
|
112
118
|
const attributeRegex =
|
|
113
119
|
/\s*([a-zA-Z0-9_-]+)(\s*=\s*("([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'|\{(?:[^{}]|(?:\{(?:[^{}]|(?:\{[^{}]*\})*)*\})*)*\}|(?:\([^)]*\)|\{[^}]*\}|()=>\s*(?:\{[^}]*\})?)|\[[^\]]*\]))?/gs;
|
|
114
120
|
|
|
115
|
-
//
|
|
121
|
+
// <div $={{color: 'red'}}></div>
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
// only return elements with attribute {()=>{}} or if it also has parameters ex: onclick={(event)=>{console.log(event)}} also get muti line functions or onClick=()=>{}
|
|
116
126
|
const functionAttributeRegex = /\s*([a-zA-Z0-9_-]+)(\s*=\s*{((?:[^{}]|(?:\{(?:[^{}]|(?:\{[^{}]*\})*)*\})*)*)})/gs;
|
|
117
127
|
|
|
118
128
|
let attributesList = [];
|
|
119
129
|
|
|
120
|
-
|
|
130
|
+
let spreadAttributes = [];
|
|
131
|
+
let spreadMatch;
|
|
132
|
+
/**
|
|
133
|
+
* @search - handle spread for html elements
|
|
134
|
+
* @keywords - spread, spread attributes, spread props, spread html attributes
|
|
135
|
+
*/
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @search - handle function parsing for html elements
|
|
140
|
+
* @keywords - function, function attributes, function props, function html attributes
|
|
141
|
+
*
|
|
142
|
+
*/
|
|
121
143
|
let functionAttributes = [];
|
|
122
144
|
let functionMatch;
|
|
123
145
|
while ((functionMatch = functionAttributeRegex.exec(code)) !== null) {
|
|
124
|
-
let [, attributeName, attributeValue] = functionMatch;
|
|
125
146
|
|
|
147
|
+
let [, attributeName, attributeValue] = functionMatch;
|
|
126
148
|
let attribute = {};
|
|
127
149
|
|
|
128
|
-
if (attributeValue && attributeValue.includes("=>") || attributeValue && attributeValue.includes("function")
|
|
129
|
-
|
|
130
|
-
|
|
150
|
+
if (attributeValue && attributeValue.includes("=>") || attributeValue && attributeValue.includes("function")
|
|
151
|
+
&& !spreadFunctions.includes(attributeValue)
|
|
152
|
+
) {
|
|
153
|
+
|
|
131
154
|
let ref = Math.random().toString(36).substring(2).split('').filter((e) => !Number(e)).join('')
|
|
132
155
|
let old = `${attributeName}${attributeValue}`
|
|
133
|
-
|
|
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
|
-
|
|
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
|
-
});
|
|
156
|
+
|
|
150
157
|
let elementMatch = string.match(/<([a-zA-Z0-9_-]+)([^>]*)>/gs);
|
|
151
158
|
let isJSXComponent = false;
|
|
152
159
|
elementMatch.forEach((element) => {
|
|
@@ -200,8 +207,7 @@ function Compiler(func, file) {
|
|
|
200
207
|
newvalue = newvalue.replace(/}\s*$/, '');
|
|
201
208
|
|
|
202
209
|
|
|
203
|
-
|
|
204
|
-
functionparams.length > 0 ? params = params + ',' + functionparams.map((e) => e.name).join(',') : null
|
|
210
|
+
|
|
205
211
|
|
|
206
212
|
newvalue = newvalue.replaceAll(',,', ',')
|
|
207
213
|
let paramnames = params ? params.split(',').map((e) => e.trim()) : null
|
|
@@ -224,6 +230,10 @@ function Compiler(func, file) {
|
|
|
224
230
|
}
|
|
225
231
|
}
|
|
226
232
|
|
|
233
|
+
/**
|
|
234
|
+
* @search - handle attributes for html elements
|
|
235
|
+
* @keywords - attributes, props, html attributes
|
|
236
|
+
*/
|
|
227
237
|
let match;
|
|
228
238
|
while ((match = elementRegex.exec(code)) !== null) {
|
|
229
239
|
let [, element, attributes] = match;
|
|
@@ -248,8 +258,7 @@ function Compiler(func, file) {
|
|
|
248
258
|
let returns = code.match(/return\s*\<>.*\<\/>|return\s*\(.*\)/gs);
|
|
249
259
|
|
|
250
260
|
return returns || [];
|
|
251
|
-
}
|
|
252
|
-
// throw error if return is not wrapped in <></> or
|
|
261
|
+
}
|
|
253
262
|
if (string.match(/return\s*\<>|return\s*\(.*\)/gs) && !string.match(/return\s*\<>.*\<\/>|return\s*\(.*\)/gs)
|
|
254
263
|
|| string.match(/return\s*\<[a-zA-Z0-9_-]+.*>/gs)
|
|
255
264
|
) {
|
|
@@ -265,6 +274,10 @@ function Compiler(func, file) {
|
|
|
265
274
|
let outerReturn = extractOuterReturn(string);
|
|
266
275
|
let contents = "";
|
|
267
276
|
let updatedContents = "";
|
|
277
|
+
/**
|
|
278
|
+
* @search - handle return [...]
|
|
279
|
+
* @keywords - return, return jsx, return html, return [...]
|
|
280
|
+
*/
|
|
268
281
|
outerReturn.forEach((returnStatement) => {
|
|
269
282
|
|
|
270
283
|
let lines = returnStatement.split("\n");
|
|
@@ -278,13 +291,12 @@ function Compiler(func, file) {
|
|
|
278
291
|
}
|
|
279
292
|
let usesBraces = returnStatement.match(/return\s*\(/gs) ? true : false;
|
|
280
293
|
|
|
281
|
-
|
|
282
|
-
// Remove trailing ']' or trailing )
|
|
294
|
+
|
|
283
295
|
contents = contents.trim().replace(/\]$/, "")
|
|
284
296
|
contents = contents.replace(/\)$/, "");
|
|
285
297
|
usesBraces ? !contents.includes('<>') ? contents = `<>${contents}</>` : null : null
|
|
286
298
|
updatedContents = contents;
|
|
287
|
-
|
|
299
|
+
let attributes = extractAttributes(contents);
|
|
288
300
|
|
|
289
301
|
let newAttributes = [];
|
|
290
302
|
let oldAttributes = [];
|
|
@@ -363,9 +375,7 @@ function Compiler(func, file) {
|
|
|
363
375
|
valuestate = valuestate.match(regex) ? valuestate.match(regex)[0].split("useState(")[1].split(")")[0].trim() : valuestate
|
|
364
376
|
|
|
365
377
|
|
|
366
|
-
let newState = `${varType} [${key}, ${setKey}] = this.useState('${key}', ${valuestate}
|
|
367
|
-
|
|
368
|
-
`;
|
|
378
|
+
let newState = `${varType} [${key}, ${setKey}] = this.useState('${key}', ${valuestate}`;
|
|
369
379
|
string = string.replace(line, newState);
|
|
370
380
|
break;
|
|
371
381
|
case line.includes("useRef") && !line.includes("import"):
|
|
@@ -410,25 +420,24 @@ function Compiler(func, file) {
|
|
|
410
420
|
string = string.replaceAll('../src', './src')
|
|
411
421
|
|
|
412
422
|
function parseComponents(body, isChild) {
|
|
413
|
-
let componentRegex = /<([A-Z][A-Za-z0-9_-]+)([^>]*)
|
|
423
|
+
let componentRegex = /<([A-Z][A-Za-z0-9_-]+)\s*([^>]*)>\s*([\s\S]*?)\s*<\/\1>|<([A-Z][A-Za-z0-9_-]+)([^]*?)\/>/gs;
|
|
414
424
|
|
|
415
425
|
let componentMatch = body.match(componentRegex);
|
|
416
426
|
let topComponent = "";
|
|
417
427
|
componentMatch?.forEach(async (component) => {
|
|
418
428
|
|
|
419
429
|
let [, element, attributes] = component;
|
|
420
|
-
|
|
430
|
+
let before = component;
|
|
431
|
+
component = component.trim().replace(/\s+/g, " ");
|
|
421
432
|
|
|
422
433
|
!isChild ? (topComponent = component) : null;
|
|
423
|
-
|
|
434
|
+
|
|
424
435
|
|
|
425
436
|
let myChildrens = [];
|
|
426
437
|
|
|
427
438
|
let name = component.split("<")[1].split(">")[0].split(" ")[0].replace("/", "");
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
const dynamicAttributesRegex = /(\w+)(?:="([^"]*)")?(?:='([^']*)')?(?:=\{([^}]*)\})?(?:=\{(.*?)\})?(?:={([^}]*)})?(?:{([^}]*)})?|(?:{(?:[^{}]+|\{(?:[^{}]+|\{[^}]*\})*\})*\})|(\.{3}\{(?:[^{}]+|\{(?:[^{}]+|\{[^}]*\})*\})*\})/gs;
|
|
431
|
-
|
|
439
|
+
let componentAttributes = component.split("<")[1].split(">")[0].split(" ").join(" ").replace(name, "").trim();
|
|
440
|
+
const dynamicAttributesRegex = /(\w+)(?:="([^"]*)")?(?:='([^']*)')?(?:=\{([^}]*)\})?(?:=\{(.*?)\})?(?:={([^}]*)})?(?:{([^}]*)})?|(?:{(?:[^{}]+|\{(?:[^{}]+|\{[^}]*\})*\})*\})|(\.{3}\{(?:[^{}]+|\{(?:[^{}]+|\{[^}]*\})*\})*\})|\$=\{(?:[^{}]+|\{(?:[^{}]+|\{[^}]*\})*\})*\}/gs;
|
|
432
441
|
|
|
433
442
|
|
|
434
443
|
|
|
@@ -439,18 +448,31 @@ function Compiler(func, file) {
|
|
|
439
448
|
let filteredProps = [];
|
|
440
449
|
let isWithinComponent = false;
|
|
441
450
|
let componentName = name
|
|
451
|
+
let currentProps = []
|
|
452
|
+
|
|
453
|
+
let $_ternaryprops = []
|
|
442
454
|
|
|
443
455
|
for (let prop of props) {
|
|
444
456
|
|
|
445
457
|
if (prop === componentName) {
|
|
446
|
-
|
|
447
|
-
// If the component is encountered, start collecting props
|
|
458
|
+
|
|
448
459
|
isWithinComponent = true;
|
|
449
460
|
filteredProps.push(prop);
|
|
450
461
|
} else if (isWithinComponent && prop.includes('=')) {
|
|
451
462
|
|
|
452
|
-
if (prop.
|
|
453
|
-
|
|
463
|
+
if (prop.startsWith('$=')) {
|
|
464
|
+
let old = prop
|
|
465
|
+
prop = prop.replace('$=', '$_ternary=')
|
|
466
|
+
|
|
467
|
+
// remove trailing }
|
|
468
|
+
prop = prop.replace(/}\s*$/, '')
|
|
469
|
+
component = component.replace(old, prop)
|
|
470
|
+
componentAttributes = componentAttributes.replace(old, prop)
|
|
471
|
+
|
|
472
|
+
$_ternaryprops.push(prop)
|
|
473
|
+
|
|
474
|
+
}
|
|
475
|
+
else if (prop.includes('${')) {
|
|
454
476
|
|
|
455
477
|
prop = prop.replace('="', ':').replace('}"', '}')
|
|
456
478
|
if (prop.includes('${')) {
|
|
@@ -467,7 +489,7 @@ function Compiler(func, file) {
|
|
|
467
489
|
}
|
|
468
490
|
|
|
469
491
|
}
|
|
470
|
-
if (prop.startsWith('={')) {
|
|
492
|
+
else if (prop.startsWith('={')) {
|
|
471
493
|
prop = prop.replace('={', ':`${')
|
|
472
494
|
prop.replace('} ', '}`')
|
|
473
495
|
}
|
|
@@ -487,72 +509,25 @@ function Compiler(func, file) {
|
|
|
487
509
|
filteredProps.push(prop);
|
|
488
510
|
|
|
489
511
|
|
|
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
512
|
|
|
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
|
-
|
|
537
|
-
} else {
|
|
538
|
-
// Process nested structures within the object
|
|
539
|
-
processedSpreadObject = `{...${spreadObject}}`;
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
const $propsKey = `$props_${Math.random().toString(36).substring(2)}`;
|
|
543
|
-
filteredProps.push(`${$propsKey}:${processedSpreadObject}`);
|
|
544
|
-
}
|
|
545
513
|
}
|
|
546
514
|
|
|
515
|
+
|
|
547
516
|
else {
|
|
548
517
|
isWithinComponent = false;
|
|
549
518
|
}
|
|
550
519
|
}
|
|
520
|
+
component = component.replaceAll(/\s+/g, " ");
|
|
521
|
+
|
|
522
|
+
component = component.replace(componentAttributes, '')
|
|
523
|
+
$_ternaryprops.forEach((prop) => {
|
|
524
|
+
component = component.replace(prop, '')
|
|
525
|
+
})
|
|
551
526
|
|
|
552
|
-
|
|
553
|
-
let children = new RegExp(`<${name}[^>]*>(.*?)<\/${name}>`, "gs").exec(component) ? new RegExp(`<${name}[^>]*>(.*?)<\/${name}>`, "gs").exec(component)[1] : null;
|
|
527
|
+
let children = component.split(`<${name}`)[1].split(`</${name}>`)[0].trim().replace(/\s+/g, " ").trim().replace(/,$/, '').replace('>', '').replace(/\/$/, '').trim()
|
|
554
528
|
|
|
555
|
-
|
|
529
|
+
|
|
530
|
+
props = filteredProps.join(',').replace(/\s+/g, " ").trim().replace(/,$/, '')
|
|
556
531
|
|
|
557
532
|
let savedname = name;
|
|
558
533
|
|
|
@@ -573,12 +548,13 @@ function Compiler(func, file) {
|
|
|
573
548
|
/<([A-Z][A-Za-z0-9_-]+)([^>]*)>(.*?)<\/\1>|<([A-Z][A-Za-z0-9_-]+)([^]*?)\/>/gs
|
|
574
549
|
);
|
|
575
550
|
if (html) {
|
|
576
|
-
html = html.map((h) => h.trim().replace(/\s+/g, " ")).join(" ");
|
|
551
|
+
html = html.map((h) => h.trim().replace(/\s+/g, " ")).join(" ");
|
|
577
552
|
child.children = child.children.replaceAll(html, `${html}`);
|
|
578
553
|
// remove duplicate quotes
|
|
579
554
|
}
|
|
580
555
|
|
|
581
556
|
myChildrens.push(child.children);
|
|
557
|
+
childs = childs.filter((e) => e.parent !== name);
|
|
582
558
|
}
|
|
583
559
|
});
|
|
584
560
|
|
|
@@ -599,8 +575,10 @@ function Compiler(func, file) {
|
|
|
599
575
|
* @memoize - memoize a component to be remembered on each render and replace the old jsx
|
|
600
576
|
*/
|
|
601
577
|
|
|
578
|
+
|
|
602
579
|
let replace = "";
|
|
603
|
-
replace = `\${this.memoize(this.createComponent(${savedname}, {${props}}, [\`${myChildrens.join(
|
|
580
|
+
replace = `\${this.memoize(this.createComponent(${savedname}, {${props}}, [\`${myChildrens.join('')}\`]))}`;
|
|
581
|
+
|
|
604
582
|
|
|
605
583
|
body = body.replace(before, replace);
|
|
606
584
|
});
|
|
@@ -613,55 +591,56 @@ function Compiler(func, file) {
|
|
|
613
591
|
const importRegex = /import\s*([^\s,]+|\{[^}]+\})\s*from\s*(['"])(.*?)\2/g;
|
|
614
592
|
const imports = string.match(importRegex);
|
|
615
593
|
let replaceMents = [];
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
for
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
for (let match of imports) {
|
|
619
597
|
let path = match.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').trim()
|
|
620
598
|
switch (true) {
|
|
621
599
|
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
|
-
|
|
600
|
+
let componentFolder = fs.existsSync(process.cwd() + '/node_modules/' + path) ? process.cwd() + '/node_modules/' + path : process.cwd() + '/node_modules/' + path.split('/')[0]
|
|
601
|
+
componentFolder = componentFolder.split(process.cwd())[1]
|
|
602
|
+
if (!fs.existsSync(process.cwd() + componentFolder)) {
|
|
625
603
|
throw new Error('Could not find ' + path + ' at ' + match + ' in file ' + file)
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
if (!fs.existsSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'))) {
|
|
607
|
+
fs.mkdirSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'), { recursive: true })
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
let baseFolder = componentFolder.split('node_modules')[1].split('/')[1]
|
|
611
|
+
let glp = globSync('**/**/**/**.{jsx,js}', {
|
|
612
|
+
cwd: process.cwd() + '/node_modules/' + baseFolder + '/',
|
|
613
|
+
absolute: true,
|
|
614
|
+
recursive: true
|
|
615
|
+
})
|
|
616
|
+
for (let file of glp) {
|
|
617
|
+
let text = fs.readFileSync(file, "utf8");
|
|
618
|
+
if (!file.endsWith('.js') && file.endsWith('.jsx')) {
|
|
619
|
+
text = Compiler(text, file);
|
|
620
|
+
|
|
630
621
|
}
|
|
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
|
-
|
|
622
|
+
let dest = file.split('node_modules')[1]
|
|
623
|
+
dest = dest.split(baseFolder)[1]
|
|
624
|
+
// write to dist
|
|
625
|
+
writer(process.cwd() + '/dist/src/' + baseFolder + dest, text)
|
|
626
|
+
let importname = match.split('import')[1].split('from')[0].trim()
|
|
627
|
+
let oldImportstring = match.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').trim()
|
|
628
|
+
let newImport = `/src/${baseFolder + dest}`
|
|
629
|
+
newImport = newImport.replaceAll('.jsx', '.js').replaceAll('\\', '/')
|
|
630
|
+
replaceMents.push({ match: oldImportstring, replace: newImport })
|
|
631
|
+
console.log(`📦 imported Node Package ${baseFolder} `)
|
|
632
|
+
}
|
|
633
|
+
|
|
655
634
|
|
|
656
635
|
break;
|
|
657
636
|
default:
|
|
658
637
|
break;
|
|
659
638
|
}
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
for(let replace of replaceMents){
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
for (let replace of replaceMents) {
|
|
663
642
|
string = string.replaceAll(replace.match, replace.replace)
|
|
664
|
-
}
|
|
643
|
+
}
|
|
665
644
|
|
|
666
645
|
string = string.replaceAll(/\$\{[^{]*\.{3}/gs, (match) => {
|
|
667
646
|
if (match.includes('...')) {
|
|
@@ -716,7 +695,7 @@ function Compiler(func, file) {
|
|
|
716
695
|
let asyncimportMatch = line.match(/import\s*\((.*)\)/gs);
|
|
717
696
|
// handle import { Component } from 'vaderjs/runtime/vader.js'
|
|
718
697
|
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
|
-
|
|
698
|
+
|
|
720
699
|
if (asyncimportMatch) {
|
|
721
700
|
asyncimportMatch.forEach(async (match) => {
|
|
722
701
|
let beforeimport = match
|
|
@@ -770,7 +749,7 @@ function Compiler(func, file) {
|
|
|
770
749
|
|
|
771
750
|
let newImport = ''
|
|
772
751
|
let name = match.split('import')[1].split('from')[0].trim()
|
|
773
|
-
|
|
752
|
+
|
|
774
753
|
|
|
775
754
|
switch (true) {
|
|
776
755
|
case path && path.includes('json'):
|
|
@@ -796,9 +775,9 @@ function Compiler(func, file) {
|
|
|
796
775
|
newImport = ``
|
|
797
776
|
break;
|
|
798
777
|
case path && !path.startsWith('./') && !path.includes('/vader.js') && !path.startsWith('src') && !path.startsWith('public') &&
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
778
|
+
path.match(/^[A-Za-z0-9_-]+$/gs) && !path.includes('http') && !path.includes('https'):
|
|
779
|
+
|
|
780
|
+
break;
|
|
802
781
|
default:
|
|
803
782
|
let beforePath = path
|
|
804
783
|
let deep = path.split('/').length - 1
|
|
@@ -856,14 +835,7 @@ async function Build() {
|
|
|
856
835
|
return text;
|
|
857
836
|
};
|
|
858
837
|
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
// Process files in the 'pages' directory
|
|
865
|
-
let appjs = '';
|
|
866
|
-
let hasWritten = []
|
|
838
|
+
|
|
867
839
|
function ssg(routes = []) {
|
|
868
840
|
globalThis.isBuilding = true
|
|
869
841
|
console.log(`Generating html files for ${routes.length} routes`)
|
|
@@ -1019,38 +991,47 @@ async function Build() {
|
|
|
1019
991
|
headless: "new", args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
|
1020
992
|
warning: false,
|
|
1021
993
|
})
|
|
1022
|
-
|
|
994
|
+
|
|
1023
995
|
const browserPID = browser.process().pid
|
|
1024
996
|
try {
|
|
1025
997
|
|
|
1026
998
|
route.url = route.url.replaceAll(/\/:[a-zA-Z0-9_-]+/gs, '')
|
|
1027
999
|
let page = await browser.newPage();
|
|
1028
1000
|
await page.goto(`http://localhost:${port}/`, { waitUntil: 'networkidle2' });
|
|
1001
|
+
await page.on('console', msg => console.log('PAGE LOG:', msg.text()));
|
|
1002
|
+
await page.on('error', err => console.log('PAGE LOG:', err));
|
|
1003
|
+
await page.on('pageerror', err => console.log('PAGE LOG:', err));
|
|
1004
|
+
await page.evaluate(() => {
|
|
1005
|
+
window.onerror = function (msg, url, lineNo, columnNo, error) {
|
|
1006
|
+
console.log(msg, url, lineNo, columnNo, error)
|
|
1007
|
+
}
|
|
1008
|
+
})
|
|
1029
1009
|
await page.waitForSelector('#root', { timeout: 10000 })
|
|
1030
1010
|
await page.evaluate(() => {
|
|
1031
1011
|
document.getElementById('meta').remove()
|
|
1032
1012
|
document.querySelector('#isServer').innerHTML = 'window.isServer = false'
|
|
1033
1013
|
if (document.head.getAttribute('prerender') === 'false') {
|
|
1034
1014
|
document.querySelector('#root').innerHTML = ''
|
|
1015
|
+
console.log(`Disabled prerendering for ${window.location.pathname}`)
|
|
1035
1016
|
}
|
|
1036
|
-
})
|
|
1017
|
+
})
|
|
1037
1018
|
const html = await page.content();
|
|
1038
1019
|
|
|
1039
1020
|
await page.close();
|
|
1040
1021
|
await writer(process.cwd() + '/dist/' + (route.url === '/' ? 'index.html' : `${route.url}/` + 'index.html'), html)
|
|
1041
1022
|
await browser.close();
|
|
1042
1023
|
server.close()
|
|
1043
|
-
|
|
1024
|
+
|
|
1044
1025
|
} catch (error) {
|
|
1045
1026
|
server.close()
|
|
1046
|
-
await browser.close();
|
|
1027
|
+
await browser.close();
|
|
1047
1028
|
}
|
|
1048
1029
|
finally {
|
|
1049
1030
|
await browser.close();
|
|
1050
|
-
server.close()
|
|
1031
|
+
server.close()
|
|
1051
1032
|
}
|
|
1052
1033
|
try {
|
|
1053
|
-
process.kill(browserPID
|
|
1034
|
+
process.kill(browserPID)
|
|
1054
1035
|
} catch (error) {
|
|
1055
1036
|
}
|
|
1056
1037
|
|
|
@@ -1096,7 +1077,6 @@ async function Build() {
|
|
|
1096
1077
|
data = Compiler(data, origin);
|
|
1097
1078
|
|
|
1098
1079
|
|
|
1099
|
-
|
|
1100
1080
|
await writer(process.cwd() + "/dist/" + fileName.replace('.jsx', '.js'), data).then(async () => {
|
|
1101
1081
|
|
|
1102
1082
|
|
|
@@ -1259,7 +1239,7 @@ async function Build() {
|
|
|
1259
1239
|
console.log(`📦 Build completed: Build Size -> ${Math.round(bundleSize / 1000)}kb`)
|
|
1260
1240
|
|
|
1261
1241
|
bundleSize = 0;
|
|
1262
|
-
|
|
1242
|
+
|
|
1263
1243
|
return true
|
|
1264
1244
|
}
|
|
1265
1245
|
const s = () => {
|
|
@@ -1389,7 +1369,7 @@ Vader.js v1.3.3
|
|
|
1389
1369
|
}
|
|
1390
1370
|
}).on('error', (err) => console.log(err))
|
|
1391
1371
|
})
|
|
1392
|
-
let p = process.argv[process.argv.indexOf('--watch') + 1] ||
|
|
1372
|
+
let p = process.argv[process.argv.indexOf('--watch') + 1] || process.env.PORT || 3000
|
|
1393
1373
|
|
|
1394
1374
|
process.env.PORT = p
|
|
1395
1375
|
s()
|