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 +274 -13
- package/package.json +1 -1
- package/runtime/router.js +1 -1
- package/runtime/vader.js +1 -1
- package/vader.js +99 -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,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
|
-
|
|
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
|
-
|
|
426
|
-
|
|
427
|
-
|
|
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
|
-
|
|
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*$/, "")
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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();
|