vaderjs 1.3.3-alpha-144 → 1.3.3-alpha-145

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/client/index.js CHANGED
@@ -7,6 +7,47 @@
7
7
  export const strictMount = (key, callback) => {
8
8
 
9
9
  };
10
+
11
+ /**
12
+ * @method $metdata
13
+ * @description This method allows you to set the metadata for the current page
14
+ * @param {string} title
15
+ * @param {string} styles
16
+ * @param {string} description
17
+ * @param {string} keywords
18
+ * @param {string} author
19
+ * @param {string} image
20
+ * @param {string} url
21
+ * @param {string} robot
22
+ * @param {string} manifest
23
+ * @param {Array} tags
24
+ * @returns {Object} - The rendered content.
25
+ *
26
+ */
27
+
28
+ export const $metdata = {
29
+ title:'',
30
+ styles,
31
+ description:'',
32
+ keywords:'',
33
+ author:'',
34
+ image:'',
35
+ url:'',
36
+ robot:'',
37
+ manifest:'',
38
+ tags: []
39
+
40
+ }
41
+
42
+ /**
43
+ * @method $prerender
44
+ * @description This method disables the prerendering of the current page
45
+ */
46
+ export const $prerender = {
47
+
48
+ }
49
+
50
+
10
51
 
11
52
 
12
53
 
@@ -417,28 +458,248 @@ export const useRef = (initialState) => {
417
458
  };
418
459
  };
419
460
 
420
- /**
421
- * @method Link
422
- * @param {string} href
423
- * @param {string} children
424
- * @returns {string} - The rendered content.
425
- * @description This method allows you to create passive links without reloading the page
461
+ /**
462
+ * @class Link
463
+ * @description Link component
464
+ * @extends Component
465
+ * @example
466
+ * <Link href="/some-path" class="custom-link" style="color: blue;">Click me!</Link>
467
+ */
468
+ export class Link extends Component {
469
+ /**
470
+ * @constructor
471
+ * @param {object} props - Component props
472
+ * @param {string} props.href - URL for the link
473
+ * @param {string} props.className - CSS class for the link
474
+ * @param {string} props.title - Title for the link
475
+ * @param {string} props.key - Unique identifier for the link
476
+ * @param {string} props.style - Inline CSS style for the link
477
+ * @param {string} props.children - Content to be displayed inside the link
478
+ */
479
+ constructor(props) {
480
+ super(props);
481
+
482
+ /**
483
+ * @type {object}
484
+ * @property {string} href - URL for the link
485
+ * @property {string} [class] - CSS class for the link
486
+ * @property {string} [style] - Inline CSS style for the link
487
+ * @property {string} [children] - Content to be displayed inside the link
488
+ */
489
+ this.props = props;
490
+
491
+ /**
492
+ * @type {HTMLAnchorElement}
493
+ */
494
+ this.link = document.createElement('a');
495
+
496
+ /**
497
+ * @type {string}
498
+ */
499
+ this.key = props.href + Math.random();
500
+ }
501
+
502
+ /**
503
+ * @function
504
+ * @returns {string} - Rendered HTML for the Link component
505
+ */
506
+ render() {
507
+
508
+ return this.link.outerHTML;
509
+ }
510
+ }
511
+
512
+
513
+
514
+ /**
515
+ * @class Image
516
+ * @description Image component
517
+ * @extends Component
518
+ * @example
519
+ * <Image src="https://via.placeholder.com/150" alt="image" />
426
520
  */
427
- class Link extends Component{
428
- constructor(props){
429
- super(props)
430
- this.props = props
521
+ export class Image extends Component {
522
+ /**
523
+ * @constructor
524
+ * @param {object} props - Component props
525
+ * @param {string} props.src - Image source URL
526
+ * @param {string} props.class - CSS class for the image
527
+ * @param {string} props.style - Inline CSS style for the image
528
+ * @param {number} props.blur - Blur value for the image (optional)
529
+ * @param {number} props.width - Width of the image (optional)
530
+ * @param {number} props.height - Height of the image (optional)
531
+ * @param {boolean} props.optimize - Optimize the image (optional, default: true)
532
+ * @param {boolean} props.loader - Show a placeholder loader (optional, default: true)
533
+ * @param {string} props.alt - Alt text for the image (optional, default: 'image')
534
+ */
535
+ constructor(props) {
536
+ super(props);
537
+
538
+ /**
539
+ * @type {object}
540
+ * @property {string} src - Image source URL
541
+ * @property {string} [class] - CSS class for the image
542
+ * @property {string} [style] - Inline CSS style for the image
543
+ * @property {number} [blur] - Blur value for the image (optional)
544
+ * @property {number} [width] - Width of the image (optional)
545
+ * @property {number} [height] - Height of the image (optional)
546
+ * @property {boolean} [optimize] - Optimize the image (optional, default: true)
547
+ * @property {boolean} [loader] - Show a placeholder loader (optional, default: true)
548
+ * @property {string} [alt] - Alt text for the image (optional, default: 'image')
549
+ * @property {string} [children] - Content to be displayed inside the image
550
+ * @property {string} [key] - Unique identifier for the image
551
+ * @property {string} [onLoad] - Function to be called when the image is loaded
552
+ */
553
+ this.props = {
554
+ src: props.src,
555
+ class: props.class,
556
+ style: props.style,
557
+ blur: props.blur,
558
+ width: props.width,
559
+ height: props.height,
560
+ optimize: props.optimize || true,
561
+ loader: props.loader || true,
562
+ alt: props.alt || 'image',
563
+ };
564
+
565
+ /**
566
+ * @type {string}
567
+ */
568
+ this.key = props.src + Math.random();
569
+
570
+ /**
571
+ * @type {HTMLImageElement}
572
+ * @private
573
+ */
574
+ this.img = document.createElement('img');
575
+
576
+ /**
577
+ * @type {HTMLDivElement}
578
+ * @private
579
+ */
580
+ this.placeholder = document.createElement('div');
581
+ }
582
+
583
+ /**
584
+ * @function
585
+ * @returns {string} - Rendered JSX for the Image component
586
+ */
587
+ render() {
588
+ // adjust width and height to the user's screen size
589
+
590
+
591
+ return this.img.outerHTML;
592
+ }
593
+ }
594
+
595
+ export class Head extends Component {
596
+ /**
597
+ * @constructor
598
+ * @param {object} props - Component props
599
+ * @param {string} props.children - Content to be displayed inside the head
600
+ */
601
+ constructor(props) {
602
+ super(props);
603
+ this.props = {
604
+ children: props.children,
605
+ }
606
+ this.key = 'head';
607
+ this.head = document.createElement('head');
608
+ }
609
+
610
+
611
+
612
+ render() {
613
+ this.head.innerHTML = this.props.children;
614
+ return this.head.outerHTML;
431
615
  }
432
- render(){
433
- return
616
+
617
+ onMount() {
618
+ document.head.innerHTML = this.head.innerHTML;
619
+ document.body.querySelector(`[key="${this.key}"]`).remove();
434
620
  }
435
621
  }
436
622
 
623
+ export class Script extends Component {
624
+ /**
625
+ * @constructor
626
+ * @param {object} props - Component props
627
+ * @param {string} props.children - Content to be displayed inside the script
628
+ */
629
+ constructor(props) {
630
+ super(props);
631
+ this.props = {
632
+ children: props.children,
633
+ }
634
+ this.key = 'script';
635
+ this.script = document.createElement('script');
636
+ }
637
+
638
+
639
+
640
+ render() {
641
+ this.script.innerHTML = this.props.children.split('\n').join(';\n');
642
+ return this.script.outerHTML;
643
+ }
644
+
645
+ onMount() {
646
+ document.head.appendChild(this.script);
647
+ document.body.querySelector(`[key="${this.key}"]`).remove();
648
+ }
649
+
650
+ }
651
+
652
+ /**
653
+ * @class HTML
654
+ * @description HTML component
655
+ * @extends Component
656
+ */
657
+ export class Html extends Component {
658
+ /**
659
+ * @constructor
660
+ * @param {object} props - Component props
661
+ * @param {string} props.children - Content to be displayed inside the HTML
662
+ * @param {string} props.lang - Language for the HTML
663
+ */
664
+ constructor(props) {
665
+ super(props);
666
+ /**
667
+ * @type {object}
668
+ * @property {string} children - Content to be displayed inside the HTML
669
+ * @property {string} lang - Language for the HTML
670
+ * @property {object} attributes - Attributes for the HTML
671
+ */
672
+ this.props = {
673
+ children: props.children,
674
+ lang: props.lang || 'en',
675
+ attributes: props.attributes || {},
676
+ }
677
+ this.key = 'html';
678
+ this.html = document.createElement('html');
679
+ }
680
+
681
+ render() {
682
+ this.html.innerHTML = this.props.children;
683
+ return this.html.outerHTML;
684
+ }
685
+
686
+ onMount() {
687
+ if (window.isServer) {
688
+ document.documentElement.innerHTML = this.html.outerHTML;
689
+ }
690
+ console.log('Document Has Been Mounted')
691
+ }
692
+
693
+ }
437
694
  export default {
438
695
  Component,
439
696
  useRef,
440
697
  useReducer,
441
698
  useState,
442
699
  strictMount,
443
- Link
700
+ Link,
701
+ Image,
702
+ Head,
703
+ Html,
704
+
444
705
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "vaderjs",
3
3
  "description": "A Reactive library aimed to helping you build reactive applications inspired by react.js",
4
4
  "module": "vader.js",
5
- "version": "1.3.3-alpha-144",
5
+ "version": "1.3.3-alpha-145",
6
6
  "bin": {
7
7
  "vader": "./vader.js"
8
8
  },
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,n=`/${t.split("/")[1]}`;this.checkroute(t)||window.devMode||(t="/");let s=(new DOMParser).parseFromString(await fetch(n,{cache:"reload"}).then((e=>e.text())),"text/html").documentElement;document.querySelector("#root").innerHTML=s.querySelector("#root").innerHTML,document.title=s.querySelector("title").innerHTML,document.querySelector('script[id="router"]').remove();let r=document.createElement("script");r.id="router",r.innerHTML=s.querySelector('script[id="router"]').innerHTML,r.setAttribute("type","module"),document.body.appendChild(r)},this.listeners.push(e),1===this.listeners.length?this.handleRoute(window.location.pathname):this.listeners.pop(),t&&t()}extractParams(e,t){const n=e.split("/").filter((e=>""!==e)),s=t.split("/").filter((e=>""!==e)),r={};return n.forEach(((e,t)=>{if(e.startsWith(":")){const n=e.slice(1);r[n]=s[t]}else if(e.startsWith("*")){s.slice(t).forEach(((e,t)=>{r[t]=e}))}})),r}extractQueryParams(e){const t=e.split("?")[1];if(!t)return{};const n={};return t.split("&").forEach((e=>{const[t,s]=e.split("=");n[t]=s})),n}checkroute(e,t){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 n=t.path.split("/").filter((e=>""!==e)),s=e.split("/").filter((e=>""!==e));if(console.log("routeParts",n,"hashParts",s),n.length!==s.length&&!t.path.endsWith("*"))return!1;for(let e=0;e<n.length;e++){const t=n[e],r=s[e];if(!t.startsWith(":")&&!t.startsWith("*")&&t!==r)return!1}return!0}const n=this.extractParams(t.path,e);return Object.keys(n).length>0}))}handleRoute(e){let t=200,n=e,s=this.checkroute(e);if(!s)return!window.location.href.includes("/404")&&routes.find((e=>"/404"===e.url))?(console.error(`Route ${e} was not found`),window.history.pushState({},"","/404"),window.dispatchEvent(new Event("popstate"))):(window.history.pushState({},"","/"),window.dispatchEvent(new Event("popstate"))),void(t=s?200:404);const r=this.extractQueryParams(n),o=s&&s.path?this.extractParams(s.path,e):{};Object.keys(o).forEach((e=>{o[e]=o[e].split("?")?o[e].split("?")[0]:o[e]}));const i={headers:{},params:o,query:r,path:e,fileUrl:window.location.href.split(window.location.origin)[1],url:window.location.href,method:s?s.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":s.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,n,s)=>{function isClass(e){return"function"==typeof e&&/^class\s/.test(Function.prototype.toString.call(e))}try{let s=new Component;if(isClass(e.default)){let t=new e.default;s.state=t.state,s=t}else{if(e.default.toString().includes("this.key"))throw new Error('Using this.key is not supported in functional components use the attribute key="a value" instead');s.key=e.default.toString().split('key="')[1]?e.default.toString().split('key="')[1].split('"')[0]:null;let i={key:s.key,render:()=>e.default.apply(s,[t,n]),request:t,response:n,params:o,queryParams:r,reset:s.reset.bind(s),onMount:s.onMount.bind(s),useState:null,router:{use:s.router.use.bind(s)},bindMount:s.bindMount.bind(s),memoize:s.memoize.bind(s),createComponent:s.createComponent.bind(s),isChild:!1,useState:s.useState.bind(s),parseStyle:s.parseStyle.bind(s),bind:s.bind.bind(s),useRef:s.useRef.bind(s),useReducer:s.useReducer.bind(s),onMount:s.onMount.bind(s),onUnmount:s.onUnmount.bind(s),hydrate:s.hydrate.bind(s)};s.render=i.render,s=i}if(!document.querySelector("#root"))throw new Error("Root element not found, please add an element with id root");s.reset(),s.components={},s.request=t,s.response=n,s.router.use&&!s.isChild?await new Promise((async r=>{if(isClass(e.default))if(isClass(e.default))switch(await s.router.use(t,n),t.pause){case!0:console.log("pausing",t.pause);let e=setInterval((()=>{t.pause?console.log("still pausing",t.pause):(clearInterval(e),r())}),1e3);break;case!1:r()}else r();else switch(await e.default.apply(s,[t,n]),await s.router.use(t,n),t.pause){case!0:let e=setInterval((()=>{t.pause?console.log("still pausing request",t.url):(clearInterval(e),r())}),1e3);break;case!1:r()}})):s.router.use&&s.isChild&&console.warn("Router.use() is not supported in child components");const i=await s.render();document.querySelector("#root").innerHTML!==i&&(document.querySelector("#root").innerHTML=i),s.bindMount(),s.onMount()}catch(e){console.error(e)}},setQuery:e=>{let t="";Object.keys(e).forEach(((n,s)=>{t+=`${0===s?"?":"&"}${n}=${e[n]}`}));let n=window.location.hash.split("?")[0];t=t.replace("/","-").replaceAll("/","-"),window.location.hash=`${n}${t}`},send:e=>{document.querySelector("#root").innerHTML=e},json:e=>{const t=document.querySelector("#root");t.innerHTML="";const n=document.createElement("pre");n.textContent=JSON.stringify(e,null,2),t.appendChild(n)}};middlewares.forEach((e=>{e(i,a)})),s&&s.handler&&s.handler(i,a)}}window.VaderRouter=VaderRouter;export default VaderRouter;
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)},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 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 i(e){return"function"==typeof e&&/^class\s/.test(Function.prototype.toString.call(e))}try{let n=new Component;if(i(e.default)){let t=new e.default;n.state=t.state,n=t}else{if(e.default.toString().includes("this.key"))throw new Error('Using this.key is not supported in functional components use the attribute key="a value" instead');n.key=e.default.toString().split('key="')[1]?e.default.toString().split('key="')[1].split('"')[0]:null;let i={key:n.key,render:()=>e.default.apply(n,[t,r]),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=i.render,n=i}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(i(e.default))if(i(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 a=await n.render();document.querySelector("#root").innerHTML!==a&&(document.querySelector("#root").innerHTML=a),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 n=setInterval((()=>{document.querySelector(`[key="${e}"]`)&&!hasRan.includes(e)&&(clearInterval(n),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,n){function s(e){return"function"==typeof e&&/^class\s/.test(Function.prototype.toString.call(e))}let r=s(e)?new e(t):null;if(!e)throw new Error("Component must be defined");let o=new Component(t);if(s(e))r.props=t,r.children=n,r.props.children=n.join(""),r.parentNode=this,r.request=this.request,r.response=this.response,r.key=t.key||null,o=r;else{e.toString();o.key=e.toString().split('key="')[1]?e.toString().split('key="')[1].split('"')[0]:null;let n={key: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),parentNoe:this};o.render=n.render,o=n}return this.components[t.key]||(this.components[t.key]=o),!this.children.includes(o)&&this.children.push(o),this.components[t.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 n=t.render();return n&&n.split(">,").length>1&&(n=n.replaceAll(">,",">")),`<span key="${e.key}" >${n}</span>`}parseStyle(e){let t="";return Object.keys(e).forEach((n=>{let s=e[n];n=n.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g,"$1-$2").toLowerCase(),t+=`${n}:${s};`})),t}bindMount(){mounts.push(this)}domDifference(e,t){let n=[];for(let s=0;s<e.length;s++){let r=e[s],o=t[s];r&&o&&!r.isEqualNode(o)&&n.push({type:"replace",old:r,new:o.cloneNode(!0)})}return n}updateChangedElements(e){e.forEach((e=>{switch(e.type){case"replace":e.old.parentNode.replaceChild(e.new,e.old);break;case"remove":e.old.remove();break;case"add":e.old.appendChild(e.new.cloneNode(!0))}}))}hydrate(e){if(e){(new DOMParser).parseFromString(this.render(),"text/html").body.querySelector(`[ref="${e}"]`),document.querySelector(`[ref="${e}"]`)}else{let e=this.key?document.querySelector(`[key="${this.key}"]`):null,t=(new DOMParser).parseFromString(this.render(),"text/html").body;if(t=document.createElement("div").appendChild(t),!e&&(e=document.querySelector(`[key="${t.attributes?.key?.value||null}"]`)),!e)return void console.error('Hydration failed, component not found got ensure you have set key="a value" on the component or this.key inside of function or render method body');t.querySelectorAll("*").forEach((e=>{e.hasAttribute("key")&&e.innerHTML!==document.querySelector(`[key="${e.attributes.key.value}"]`).innerHTML&&document.querySelector(`[key="${e.attributes.key.value}"]`).replaceWith(e)}))}}patch(e,t){const n=this.domDifference(e,t);this.updateChangedElements(n)}handleObject(obj){try{obj=JSON.parse(obj)}catch(e){}return eval(obj)}bind(e,t,n,s,...r){n=n+this.key||2022;let o={},i=(s=s.replace(/,,/g,",")).replaceAll(",,",",");for(var u in r){let e=r[u];o[i.split(",")[u]]=e}s=s.replace(",,",",");let a=null;e=e.split("\n").join(";");try{a=new Function(`event, ${s}`,` \n return (async (event, ${s}) => { \n ${e.toString()}\n })(event, ${Object.keys(o).join(",")}) \n `)}catch(e){let{message:t}=e;console.error(`Error in function ${n} ${t}`)}return a=a.bind(this),this.functions.find((e=>e.ref===n))||document.addEventListener(`$dispatch_#id=${n}`,(e=>{let{name:t,event:s}=e.detail;if(t===n){let e=this.functions.find((e=>e.ref===n)).params;Object.keys(e).forEach((t=>{e[t]instanceof CustomEvent&&delete e[t],void 0===e[t]?delete e[t]:e[t]})),a(s,...Object.values(e))}})),window.callFunction=(e,t)=>{document.dispatchEvent(new CustomEvent(`$dispatch_#id=${e}`,{detail:{name:e,params:null,event:t}}))},!this.functions.find((e=>e.ref===n))&&this.functions.push({ref:n,params:o}),t?e:`((event)=>{event.target.ev = event; callFunction('${n}', event.target.ev)})(event)`}useState(e,t){this.state[e]||(this.state[e]=t);let n=()=>this.state[e],s=n();return[s,(t,r)=>{this.state[e]=t,this.hydrate(r),s=n()}]}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,n=null){this.state[e]||(this.state[e]=t);const s=()=>this.state[e];let r=s();return[s(),(t,o)=>{const i=n(r,t)??t;this.state[e]=i,this.hydrate(o),r=s()}]}render(){}checkIFMounted(){new MutationObserver((e=>{e.forEach((e=>{e.target.querySelector(`[key="${this.key}"]`)&&!this.mounted&&(this.onMount(),this.mounted=!0),Array.from(e.removedNodes).find((e=>e.attributes&&e.attributes.key&&e.attributes.key.value===this.key))&&(this.onUnmount(),this.reset())}))})).observe(document.body,{childList:!0,subtree:!0})}onMount(){}onUnmount(){}}export const useState=(e,t)=>{states[e]||(states[e]=t);return[states[e],(t,n)=>{states[e]=t,this.hydrate(n)}]};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")}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 default{Component:Component,useRef:useRef,useReducer:useReducer,useState:useState,strictMount:strictMount,Link:Link};
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 s={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};i.render=s.render,i=s}return this.components[i.key]||(this.components[i.key]=i),!this.children.includes(i)&&this.children.push(i),this.components[i.key]}reset(){Object.keys(this.components).forEach((e=>{this.components[e].onUnmount(),delete this.components[e]})),this.state={},this.children=[]}memoize(e){if(!0==!this.memoizes.includes(e.key))this.memoizes.push(e.key),this.components[e.key]=e;let t=this.components[e.key];t.bindMount(),t.parentNode=this,t.props=e.props,t.request=this.request,t.response=this.response,t.onMount=e.onMount.bind(e),t.onUnmount=e.onUnmount.bind(e);let s=t.render();return s&&s.split(">,").length>1&&(s=s.replaceAll(">,",">")),`<span key="${e.key}" >${s}</span>`}parseStyle(e){let t="";return Object.keys(e).forEach((s=>{let r=e[s];s=s.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g,"$1-$2").toLowerCase(),t+=`${s}:${r};`})),t}bindMount(){mounts.push(this)}domDifference(e,t){let s=[];for(let r=0;r<e.length;r++){let n=e[r],i=t[r];n&&i&&!n.isEqualNode(i)&&s.push({type:"replace",old:n,new:i.cloneNode(!0)})}return s}updateChangedElements(e){e.forEach((e=>{switch(e.type){case"replace":e.old.parentNode.replaceChild(e.new,e.old);break;case"remove":e.old.remove();break;case"add":e.old.appendChild(e.new.cloneNode(!0))}}))}hydrate(e){if(e){(new DOMParser).parseFromString(this.render(),"text/html").body.querySelector(`[ref="${e}"]`),document.querySelector(`[ref="${e}"]`)}else{let e=this.key?document.querySelector(`[key="${this.key}"]`):null,t=(new DOMParser).parseFromString(this.render(),"text/html").body;if(t=document.createElement("div").appendChild(t),!e&&(e=document.querySelector(`[key="${t.attributes?.key?.value||null}"]`)),!e)return void console.error('Hydration failed, component not found got ensure you have set key="a value" on the component or this.key inside of function or render method body');t.querySelectorAll("*").forEach((e=>{e.hasAttribute("key")&&e.innerHTML!==document.querySelector(`[key="${e.attributes.key.value}"]`).innerHTML&&document.querySelector(`[key="${e.attributes.key.value}"]`).replaceWith(e)}))}}patch(e,t){const s=this.domDifference(e,t);this.updateChangedElements(s)}handleObject(obj){try{obj=JSON.parse(obj)}catch(e){}return eval(obj)}bind(e,t,s,r,...n){s=s+this.key||2022;let i={},o=(r=r.replace(/,,/g,",")).replaceAll(",,",",");for(var h in n){let e=n[h];i[o.split(",")[h]]=e}r=r.replace(",,",",");let u=null;e=e.split("\n").join(";");try{u=new Function(`event, ${r}`,` \n return (async (event, ${r}) => { \n ${e.toString()}\n })(event, ${Object.keys(i).join(",")}) \n `)}catch(e){let{message:t}=e;console.error(`Error in function ${s} ${t}`)}return u=u.bind(this),this.functions.find((e=>e.ref===s))||document.addEventListener(`$dispatch_#id=${s}`,(e=>{let{name:t,event:r}=e.detail;if(t===s){let e=this.functions.find((e=>e.ref===s)).params;Object.keys(e).forEach((t=>{e[t]instanceof CustomEvent&&delete e[t],void 0===e[t]?delete e[t]:e[t]})),u(r,...Object.values(e))}})),window.callFunction=(e,t)=>{document.dispatchEvent(new CustomEvent(`$dispatch_#id=${e}`,{detail:{name:e,params:null,event:t}}))},!this.functions.find((e=>e.ref===s))&&this.functions.push({ref:s,params:i}),t?e:`((event)=>{event.target.ev = event; callFunction('${s}', event.target.ev)})(event)`}useState(e,t){this.state[e]||(this.state[e]=t);let s=()=>this.state[e],r=s();return[r,(t,n)=>{this.state[e]=t,this.hydrate(n),r=s()}]}useRef(e=null,t){this.state[e]||(this.state[e]=t);return{bind:e+this.key,current:(()=>document.querySelector(`[ref="${e+this.key}"]`)||t)()}}useReducer(e=null,t,s=null){this.state[e]||(this.state[e]=t);const r=()=>this.state[e];let n=r();return[r(),(t,i)=>{const o=s(n,t)??t;this.state[e]=o,this.hydrate(i),n=r()}]}render(){}checkIFMounted(){new MutationObserver((e=>{e.forEach((e=>{e.target.querySelector(`[key="${this.key}"]`)&&!this.mounted&&(this.onMount(),this.mounted=!0),Array.from(e.removedNodes).find((e=>e.attributes&&e.attributes.key&&e.attributes.key.value===this.key))&&(this.onUnmount(),this.reset())}))})).observe(document.body,{childList:!0,subtree:!0})}onMount(){}onUnmount(){}}export const useState=(e,t)=>{states[e]||(states[e]=t);return[states[e],(t,s)=>{states[e]=t,this.hydrate(s)}]};export const useReducer=(e,t)=>[e,e=>{}];export const useRef=e=>({current:e,bind:""});export class Link extends Component{constructor(e){super(e),this.props=e,this.link=document.createElement("a"),this.key=e.href+Math.random()}render(){return this.link.innerHTML=this.props.children,this.link.setAttribute("id",this.props?.href),this.link.style=this.props?.style,this.link.setAttribute("class",this.props?.class),this.link.setAttribute("onclick",`window.history.pushState({}, '', '${this.props?.href}'); window.dispatchEvent(new Event('popstate'));`),this.link.outerHTML}}export class Image extends Component{constructor(e){super(e),this.props={src:e.src,class:e.class,style:e.style,blur:e.blur,width:e.width,height:e.height,optimize:e.optimize||!0,loader:e.loader||!0,alt:e.alt||"image",ref:e.ref||null},this.key=e.src+Math.random(),this.img=document.createElement("img"),this.placeholder=document.createElement("div")}render(){if(window.isServer)return"";let[e,t]=this.useState("loaded",!1),s=this.useRef("hookref",null),r=this.props.width?this.props.width:window.innerWidth/2,n=this.props.height?this.props.height:window.innerHeight/2;if(!this.props.src)throw new Error("Image src is required");return this.img.setAttribute("src",this.props.src),this.img.setAttribute("class",this.props.class),this.img.setAttribute("style",this.props.style?this.props.style:""),this.img.setAttribute("width",r),this.img.setAttribute("ref",s.bind),this.img.referrerPolicy="no-referrer",this.img.setAttribute("height",n),this.img.setAttribute("loading","lazy"),this.img.setAttribute("alt",this.props.alt),this.props.blur&&this.img.setAttribute("style",`filter: blur(${this.props.blur}px);`),this.props.optimize&&this.img.setAttribute("style",`image-rendering: -webkit-optimize-contrast; object-fit: cover; object-position: center; ${this.props.style?this.props.style:""}`),!this.props.loader||e||window.isServer||(this.placeholder.setAttribute("style",`width: ${r}px; height: ${n}px; background: #eee;`),this.placeholder.setAttribute("class","vader-image-placeholder"),this.placeholder.innerHTML=this.props.loader,window.isServer)?void 0:(this.img.onload=()=>{t(!0,s.bind)},`<span ref="${s.bind}">${e?this.img.outerHTML:this.placeholder.outerHTML}</span>`)}}export class Html extends Component{constructor(e){super(e),this.props={children:e.children,lang:e.lang||"en",attributes:e.attributes||{}},this.key="html",this.html=document.createElement("div")}render(){return window.isServer?(this.html.innerHTML=this.props.children,this.html.setAttribute("lang",this.props.lang?this.props.lang:"en"),this.props.attributes&&Object.keys(this.props.attributes).forEach((e=>{this.html.setAttribute(e,this.props.attributes[e])})),this.html.innerHTML):this.props.children}onMount(){console.log("Document Has Been Mounted")}}export class Head extends Component{constructor(e){super(e),this.props=e,this.key="head",this.head=document.createElement("head")}render(){return""}onMount(){if(!this.state.hasMounted&&window.isServer){document.head.innerHTML=this.props.children+document.head.innerHTML,document.querySelectorAll("script[eager]").forEach((async e=>{if(!e.getAttribute("src"))throw new Error("Eager scripts must be external");e.remove();let t=e.getAttribute("src"),s=document.createElement("script"),r=await fetch(t).then((e=>e.text()));s.innerHTML=r,s.setAttribute("srcid",t),document.querySelector(`[srcid="${t}"]`)||document.head.prepend(s)})),this.state.hasMounted=!0}}}export class Script extends Component{constructor(e){super(e),this.props={children:e.children},this.key="script",this.script=document.createElement("script")}render(){return this.script.innerHTML=this.props.children.split("\n").join(";\n"),this.script.outerHTML}onMount(){document.head.appendChild(this.script),document.body.querySelector(`[key="${this.key}"]`).remove()}}export default{Component:Component,useRef:useRef,useReducer:useReducer,useState:useState,strictMount:strictMount,Link:Link,Image:Image,Head:Head,Script:Script,Html:Html};
package/vader.js CHANGED
@@ -7,7 +7,7 @@ import { WebSocketServer } from 'ws'
7
7
  import { watch } from "fs";
8
8
  import path from 'path'
9
9
  let config = await import('file://' + process.cwd() + '/vader.config.js').then((e) => e.default || e)
10
- console.log(config)
10
+
11
11
 
12
12
  let start = Date.now()
13
13
  let bundleSize = 0;
@@ -99,7 +99,7 @@ function Compiler(func, file) {
99
99
  /\s*([a-zA-Z0-9_-]+)(\s*=\s*("([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'|\{(?:[^{}]|(?:\{(?:[^{}]|(?:\{[^{}]*\})*)*\})*)*\}|(?:\([^)]*\)|\{[^}]*\}|()=>\s*(?:\{[^}]*\})?)|\[[^\]]*\]))?/gs;
100
100
 
101
101
  // only return elements with attribute {()=>{}} or if it also has parameters ex: onclick={(event)=>{console.log(event)}} also get muti line functions
102
- const functionAttributeRegex = /\s*([a-zA-Z0-9_-]+)(\s*=\s*{(.*?)}|\s*=\s*function\s*(.*?))(?=\s*[a-zA-Z0-9_-]+\s*=|\s*>)/gs;
102
+ const functionAttributeRegex = /\s*([a-zA-Z0-9_-]+)(\s*=\s*{((?:[^{}]|(?:\{(?:[^{}]|(?:\{[^{}]*\})*)*\})*)*)})/gs;
103
103
 
104
104
  let attributesList = [];
105
105
 
@@ -143,7 +143,7 @@ function Compiler(func, file) {
143
143
  .split(" ")[0];
144
144
  isJSXComponent = elementTag.match(/^[A-Z]/) ? true : false;
145
145
  }
146
- });
146
+ });
147
147
  // add ; after newlines
148
148
 
149
149
 
@@ -194,15 +194,15 @@ function Compiler(func, file) {
194
194
  // remove comments
195
195
  paramnames = paramnames ? paramnames.map((e) => e.match(/\/\*.*\*\//gs) ? e.replace(e.match(/\/\*.*\*\//gs)[0], "") : e) : null
196
196
  newvalue = newvalue.replaceAll(/\s+/g, " ")
197
-
198
- let bind = isJSXComponent ? `${attributeName}=function(${params}){${newvalue}}.bind(this)` : `${attributeName}="\$\{this.bind("${newvalue.replace(/\s+g/, " ")}", ${isJSXComponent}, "${ref}", "${paramnames ? paramnames.map((e, index) => {
197
+
198
+ let bind = isJSXComponent ? `${attributeName}='function(${params}){${newvalue}}'` : `${attributeName}="\$\{this.bind("${newvalue.replace(/\s+g/, " ")}", ${isJSXComponent}, "${ref}", "${paramnames ? paramnames.map((e, index) => {
199
199
  if (e.length < 1) return ''
200
200
  if (e.length > 0) {
201
201
  index == 0 ? e : ',' + e
202
202
  }
203
203
  return e
204
204
  }) : ''}" ${params ? params.split(',').map((e) => e.trim()).filter(Boolean).map((e) => `,${e}`).join('') : ''})}"`
205
-
205
+
206
206
  string = string.replace(old, bind);
207
207
  }
208
208
  }
@@ -403,40 +403,75 @@ function Compiler(func, file) {
403
403
  string = string.replaceAll('../src', './src')
404
404
 
405
405
  function parseComponents(body, isChild) {
406
- let componentRegex =
407
- /<([A-Z][a-zA-Z0-9_-]+)([^>]*)\/>|<([A-Z][a-zA-Z0-9_-]+)([^>]*)>(.*?)<\/\3>/gs;
406
+ let componentRegex = /<([A-Z][A-Za-z0-9_-]+)([^>]*)>(.*?)<\/\1>|<([A-Z][A-Za-z0-9_-]+)([^]*?)\/>/gs;
408
407
 
409
408
  let componentMatch = body.match(componentRegex);
410
409
  let topComponent = "";
411
410
  componentMatch?.forEach(async (component) => {
411
+
412
412
  let [, element, attributes] = component;
413
+
413
414
 
414
415
  !isChild ? (topComponent = component) : null;
415
- let before = component;
416
- component = component.trim().replace(/\s+/g, " ");
416
+ let before = component;
417
417
 
418
418
  let myChildrens = [];
419
419
 
420
420
  let name = component.split("<")[1].split(">")[0].split(" ")[0].replace("/", "");
421
- let props = component.split(`<${name}`)[1].split(">")[0].trim()
422
-
421
+ // some components will have props that have html inside of them we need to only get the props ex: <Header title={<h1>hello</h1>}></Header> -> title={<h1>hello</h1>} also functions
422
+ let dynamicAttributesRegex = /(\w+)(?:="([^"]*)")?(?:='([^']*)')?(?:=\{([^}]*)\})?(?:=\{(.*?)\})?(?:={([^}]*)})?/gs;
423
+
424
+
425
+ let props = component.match(dynamicAttributesRegex)
426
+
427
+ let filteredProps = [];
428
+ let isWithinComponent = false;
429
+ let componentName = name
430
+
431
+ for (let prop of props) {
432
+ if (prop.includes(componentName)) {
433
+ // If the component is encountered, start collecting props
434
+ isWithinComponent = true;
435
+ filteredProps.push(prop);
436
+ } else if (isWithinComponent && prop.includes('=')) {
437
+ if(prop.startsWith('={')){
438
+ prop = prop.replace('={', ':`')
439
+ prop.replace('} ', '`')
440
+ }
441
+ if(prop.includes('function')){
442
+ // parse 'function' to function
443
+ prop = prop.replace("'", '')
444
+
445
+ if(prop.endsWith("}'")){
446
+ prop = prop.replace("}'", '}')
447
+
448
+ }
449
+
450
+ prop = prop.replace('=function', ':function')
451
+ }
452
+
453
+ filteredProps.push(prop);
454
+
455
+
456
+ }else{
457
+ isWithinComponent = false;
458
+ }
459
+ }
423
460
 
461
+ // get inner content of <Component>inner content</Component>
462
+ let children = new RegExp(`<${name}[^>]*>(.*?)<\/${name}>`, "gs").exec(component) ? new RegExp(`<${name}[^>]*>(.*?)<\/${name}>`, "gs").exec(component)[1] : null;
463
+
464
+ props = filteredProps.join(',')
424
465
  let savedname = name;
425
- let children = props
426
- ? component
427
- .split(`<${name}`)[1]
428
- .split(`${props}`)[1]
429
- .split(`</${name}>`)[0]
430
- .trim()
431
- .replace(">", "")
432
- : component.split(`<${name}`)[1].split(`</${name}>`)[0].trim().replace(">", "");
466
+
467
+
468
+
433
469
  name = name + Math.random().toString(36).substring(2);
434
470
  if (children && children.match(componentRegex)) {
435
471
  children = parseComponents(children, true);
436
472
  childs.push({ parent: name, children: children });
437
473
  } else {
438
-
439
- children = `\`${children}\`,`;
474
+
440
475
  children ? childs.push({ parent: name, children: children }) : null;
441
476
  }
442
477
 
@@ -458,49 +493,24 @@ function Compiler(func, file) {
458
493
 
459
494
 
460
495
 
461
- /**
462
- * @prop {string} props
463
- * @description replace any given possible value in props and parse the string to a valid JSON object
464
- */
465
- props = props
466
- .replaceAll('"', "'")
467
-
468
-
469
- .replaceAll(",,", ',')
470
- .replaceAll("className", "class")
471
- .replaceAll("classname", "class")
472
- .replaceAll("'${", "")
473
- .replaceAll("}'", "")
474
- .split("$:")
475
- .join("")
476
- // replace / with '' at the end of the string
477
- .replace(/\/\s*$/, "")
478
-
479
- .replace(/,\s*$/, "")
496
+
497
+ props = props.replaceAll(`,${savedname}`, '').replaceAll(savedname, '')
498
+ if(props.startsWith(',')){
499
+ props = props.replace(',', '')
500
+ }
501
+ props = props .replaceAll("='", ":'")
502
+ .replaceAll('=`', ':`')
480
503
  .replaceAll('="', ':"')
481
- .replaceAll("='", ":'")
482
- .replaceAll('=`', ':`')
483
- .replaceAll(`={\``, ':`')
484
- .replaceAll('`}', '`')
485
- .replaceAll(",,", ',')
486
- .replaceAll(/=(?=(?:(?:[^"']*["'][^"']*['"])*[^"']*$))/g, ':');
487
-
488
- props = props.replace(/:('[^']*'|"[^"]*")/g, ':$1,');
489
- // ANY VALUE NUMBER BOOLEAN OR STRING
490
- props = props.replace(/=(\d+)/g, ':$1,');
491
- props = props.replaceAll(',,', ',')
492
-
504
+ .replaceAll(`={\``, ':`')
505
+ .replaceAll('`}', '`')
506
+ .replaceAll('={', ":`")
493
507
 
494
508
  /**
495
509
  * @memoize - memoize a component to be remembered on each render and replace the old jsx
496
510
  */
497
511
 
498
- let replace = "";
499
- replace = isChild
500
- ? `this.memoize(this.createComponent(${savedname.replaceAll('/', '')}, ${props}, [${myChildrens.length > 0 ? myChildrens.join(",") : ""
501
- }])),`
502
- : `\${this.memoize(this.createComponent(${savedname.replaceAll('/', '')}, {${props}}, [${myChildrens.length > 0 ? myChildrens.join(",") : ""
503
- }]))}`;
512
+ let replace = "";
513
+ replace = `\${this.memoize(this.createComponent(${savedname}, {${props}}, [\`${myChildrens.join(" ")}\`]))}`;
504
514
 
505
515
  body = body.replace(before, replace);
506
516
  });
@@ -750,6 +760,9 @@ async function Build() {
750
760
  <script>
751
761
  window.routes = JSON.parse('${JSON.stringify(routes)}')
752
762
  </script>
763
+ <script id="isServer">
764
+ window.isServer = true
765
+ </script>
753
766
  <meta charset="UTF-8">
754
767
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
755
768
  <script type="module" id="meta">
@@ -803,30 +816,34 @@ async function Build() {
803
816
  document.head.innerHTML += '<link rel="icon" href="' + metadata.icon + '">'
804
817
  }
805
818
  </script>
819
+ <script type="module" id="router">
820
+ import VaderRouter from '/router.js'
821
+ const router = new VaderRouter('${route.url}', 3000)
822
+ router.get('${route.url}', async (req, res) => {
823
+ let module = await import('/${route.fileName.replace('.jsx', '.js')}')
824
+ if(Object.keys(module).includes('$prerender') && !module.$prerender){
825
+ document.head.setAttribute('prerender', 'false')
826
+ }
827
+ res.render(module, req, res, module.$metadata)
828
+ })
829
+ ${equalparamroute.length > 0 ? equalparamroute.map((e) => {
830
+
831
+
832
+
833
+ return `router.get('${e.url}', async (req, res) => {
834
+ let module = await import('/${e.fileName.replace('.jsx', '.js')}')
835
+ res.render(module, req, res, module.$metadata)
836
+ })\n`
837
+ }) : ''}
838
+ router.listen(3000)
839
+
840
+ </script>
806
841
  </head>
807
842
  <body>
808
843
  <div id="root"></div>
809
844
  </body>
810
845
 
811
- <script type="module" id="router">
812
- import VaderRouter from '/router.js'
813
- const router = new VaderRouter('${route.url}', 3000)
814
- router.get('${route.url}', async (req, res) => {
815
- let module = await import('/${route.fileName.replace('.jsx', '.js')}')
816
- res.render(module, req, res, module.$metadata)
817
- })
818
- ${equalparamroute.length > 0 ? equalparamroute.map((e) => {
819
-
820
-
821
-
822
- return `router.get('${e.url}', async (req, res) => {
823
- let module = await import('/${e.fileName.replace('.jsx', '.js')}')
824
- res.render(module, req, res, module.$metadata)
825
- })\n`
826
- }) : ''}
827
- router.listen(3000)
828
-
829
- </script>
846
+
830
847
  </html>
831
848
  `;
832
849
 
@@ -870,6 +887,10 @@ async function Build() {
870
887
  await page.waitForSelector('#root');
871
888
  await page.evaluate(() => {
872
889
  document.getElementById('meta').remove()
890
+ document.querySelector('#isServer').innerHTML = 'window.isServer = false'
891
+ if(document.head.getAttribute('prerender') === 'false'){
892
+ document.querySelector('#root').innerHTML = ''
893
+ }
873
894
  })
874
895
  const html = await page.content();
875
896
  await page.close();