vaderjs 1.3.3-alpha-144 → 1.3.3-alpha-146
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 +274 -13
- package/package.json +1 -1
- package/runtime/router.js +1 -1
- package/runtime/vader.js +1 -1
- package/vader.js +104 -78
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
|
-
* @
|
|
422
|
-
* @
|
|
423
|
-
* @
|
|
424
|
-
* @
|
|
425
|
-
*
|
|
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
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
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
|
-
|
|
433
|
-
|
|
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
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,
|
|
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
|
-
|
|
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*{(
|
|
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}}
|
|
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,80 @@ 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
|
-
|
|
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.includes('${')){
|
|
438
|
+
prop = prop.replace('${', '`')
|
|
439
|
+
prop = prop.replace('}', '`')
|
|
440
|
+
console.log(prop)
|
|
441
|
+
}
|
|
442
|
+
if(prop.startsWith('={')){
|
|
443
|
+
prop = prop.replace('={', ':`')
|
|
444
|
+
prop.replace('} ', '`')
|
|
445
|
+
}
|
|
446
|
+
if(prop.includes('function')){
|
|
447
|
+
// parse 'function' to function
|
|
448
|
+
prop = prop.replace("'", '')
|
|
449
|
+
|
|
450
|
+
if(prop.endsWith("}'")){
|
|
451
|
+
prop = prop.replace("}'", '}')
|
|
452
|
+
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
prop = prop.replace('=function', ':function')
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
filteredProps.push(prop);
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
}else{
|
|
462
|
+
isWithinComponent = false;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
423
465
|
|
|
466
|
+
// get inner content of <Component>inner content</Component>
|
|
467
|
+
let children = new RegExp(`<${name}[^>]*>(.*?)<\/${name}>`, "gs").exec(component) ? new RegExp(`<${name}[^>]*>(.*?)<\/${name}>`, "gs").exec(component)[1] : null;
|
|
468
|
+
|
|
469
|
+
props = filteredProps.join(',')
|
|
424
470
|
let savedname = name;
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
.split(`${props}`)[1]
|
|
429
|
-
.split(`</${name}>`)[0]
|
|
430
|
-
.trim()
|
|
431
|
-
.replace(">", "")
|
|
432
|
-
: component.split(`<${name}`)[1].split(`</${name}>`)[0].trim().replace(">", "");
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
|
|
433
474
|
name = name + Math.random().toString(36).substring(2);
|
|
434
475
|
if (children && children.match(componentRegex)) {
|
|
435
476
|
children = parseComponents(children, true);
|
|
436
477
|
childs.push({ parent: name, children: children });
|
|
437
478
|
} else {
|
|
438
|
-
|
|
439
|
-
children = `\`${children}\`,`;
|
|
479
|
+
|
|
440
480
|
children ? childs.push({ parent: name, children: children }) : null;
|
|
441
481
|
}
|
|
442
482
|
|
|
@@ -458,49 +498,24 @@ function Compiler(func, file) {
|
|
|
458
498
|
|
|
459
499
|
|
|
460
500
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
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*$/, "")
|
|
501
|
+
|
|
502
|
+
props = props.replaceAll(`,${savedname}`, '').replaceAll(savedname, '')
|
|
503
|
+
if(props.startsWith(',')){
|
|
504
|
+
props = props.replace(',', '')
|
|
505
|
+
}
|
|
506
|
+
props = props .replaceAll("='", ":'")
|
|
507
|
+
.replaceAll('=`', ':`')
|
|
480
508
|
.replaceAll('="', ':"')
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
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
|
-
|
|
509
|
+
.replaceAll(`={\``, ':`')
|
|
510
|
+
.replaceAll('`}', '`')
|
|
511
|
+
.replaceAll('={', ":`")
|
|
493
512
|
|
|
494
513
|
/**
|
|
495
514
|
* @memoize - memoize a component to be remembered on each render and replace the old jsx
|
|
496
515
|
*/
|
|
497
516
|
|
|
498
|
-
let replace = "";
|
|
499
|
-
replace =
|
|
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
|
-
}]))}`;
|
|
517
|
+
let replace = "";
|
|
518
|
+
replace = `\${this.memoize(this.createComponent(${savedname}, {${props}}, [\`${myChildrens.join(" ")}\`]))}`;
|
|
504
519
|
|
|
505
520
|
body = body.replace(before, replace);
|
|
506
521
|
});
|
|
@@ -750,6 +765,9 @@ async function Build() {
|
|
|
750
765
|
<script>
|
|
751
766
|
window.routes = JSON.parse('${JSON.stringify(routes)}')
|
|
752
767
|
</script>
|
|
768
|
+
<script id="isServer">
|
|
769
|
+
window.isServer = true
|
|
770
|
+
</script>
|
|
753
771
|
<meta charset="UTF-8">
|
|
754
772
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
755
773
|
<script type="module" id="meta">
|
|
@@ -803,30 +821,34 @@ async function Build() {
|
|
|
803
821
|
document.head.innerHTML += '<link rel="icon" href="' + metadata.icon + '">'
|
|
804
822
|
}
|
|
805
823
|
</script>
|
|
824
|
+
<script type="module" id="router">
|
|
825
|
+
import VaderRouter from '/router.js'
|
|
826
|
+
const router = new VaderRouter('${route.url}', 3000)
|
|
827
|
+
router.get('${route.url}', async (req, res) => {
|
|
828
|
+
let module = await import('/${route.fileName.replace('.jsx', '.js')}')
|
|
829
|
+
if(Object.keys(module).includes('$prerender') && !module.$prerender){
|
|
830
|
+
document.head.setAttribute('prerender', 'false')
|
|
831
|
+
}
|
|
832
|
+
res.render(module, req, res, module.$metadata)
|
|
833
|
+
})
|
|
834
|
+
${equalparamroute.length > 0 ? equalparamroute.map((e) => {
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
return `router.get('${e.url}', async (req, res) => {
|
|
839
|
+
let module = await import('/${e.fileName.replace('.jsx', '.js')}')
|
|
840
|
+
res.render(module, req, res, module.$metadata)
|
|
841
|
+
})\n`
|
|
842
|
+
}) : ''}
|
|
843
|
+
router.listen(3000)
|
|
844
|
+
|
|
845
|
+
</script>
|
|
806
846
|
</head>
|
|
807
847
|
<body>
|
|
808
848
|
<div id="root"></div>
|
|
809
849
|
</body>
|
|
810
850
|
|
|
811
|
-
|
|
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>
|
|
851
|
+
|
|
830
852
|
</html>
|
|
831
853
|
`;
|
|
832
854
|
|
|
@@ -870,6 +892,10 @@ async function Build() {
|
|
|
870
892
|
await page.waitForSelector('#root');
|
|
871
893
|
await page.evaluate(() => {
|
|
872
894
|
document.getElementById('meta').remove()
|
|
895
|
+
document.querySelector('#isServer').innerHTML = 'window.isServer = false'
|
|
896
|
+
if(document.head.getAttribute('prerender') === 'false'){
|
|
897
|
+
document.querySelector('#root').innerHTML = ''
|
|
898
|
+
}
|
|
873
899
|
})
|
|
874
900
|
const html = await page.content();
|
|
875
901
|
await page.close();
|