vaderjs 1.3.3-7775642-hotfix → 1.3.3-7b27417d42e1

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/vader.js CHANGED
@@ -143,6 +143,9 @@ function Compiler(func, file) {
143
143
  isJSXComponent = elementTag.match(/^[A-Z]/) ? true : false;
144
144
  }
145
145
  });
146
+ if (isJSXComponent) {
147
+ continue
148
+ }
146
149
  // add ; after newlines
147
150
 
148
151
 
@@ -239,34 +242,34 @@ function Compiler(func, file) {
239
242
  continue;
240
243
  }
241
244
  let old = spread;
242
- spread = spread.trim().replace(/\s+/g, " ");
245
+ spread = spread.trim().replace(/\s+/g, " ");
243
246
  // re,pve $={ and }
244
247
  spread = spread.replace(/\s*\$\s*=\s*{\s*{/gs, '')
245
-
248
+
246
249
  // replace trailing }
247
- spread = spread.replace(/}}\s*$/, '').replace(/}\s*}$/, '')
248
- let splitByCommas = spread.split(/,(?![^{}]*})/gs)
250
+ spread = spread.replace(/}}\s*$/, '').replace(/}\s*}$/, '')
251
+ let splitByCommas = spread.split(/,(?![^{}]*})/gs)
249
252
  // remove empty strings
250
253
  splitByCommas = splitByCommas.filter((e) => e.split(':')[0].trim().length > 0)
251
- splitByCommas = splitByCommas.map((e, index) => {
254
+ splitByCommas = splitByCommas.map((e, index) => {
252
255
  let key = e.split(':')[0].trim()
253
256
  switch (true) {
254
257
  case e.includes('function') && !e.includes('this.bind') || e && e.includes('=>') && !e.includes('this.bind'):
255
258
  let value = e.split(':')[1].trim()
256
- let ref = Math.random().toString(36).substring(2).split('').filter((e) => !Number(e)).join('');
259
+ let ref = Math.random().toString(36).substring(2).split('').filter((e) => !Number(e)).join('');
257
260
  value = `this.bind(${value}, false, "${ref}", "")`
258
261
  e = `${key}="\${${value}}"`
259
262
  break;
260
- case e.includes('style:'):
261
- let v2 = e.split('style:')[1].trim().replace(/,$/, '')
262
- v2 = v2.replace(/,$/, '')
263
+ case e.includes('style:'):
264
+ let v2 = e.split('style:')[1].trim().replace(/,$/, '')
265
+ v2 = v2.replace(/,$/, '')
263
266
  e = `${key}="\${this.parseStyle(${v2})}"`
264
- break;
265
-
266
- default:
267
- let v = e.split(':')
267
+ break;
268
+
269
+ default:
270
+ let v = e.split(':')
268
271
  key = v[0].trim()
269
- // remove key from v
272
+ // remove key from v
270
273
  v.shift()
271
274
  v = v.join(' ')
272
275
  e = `${key}="\${${v}}"`
@@ -277,7 +280,7 @@ function Compiler(func, file) {
277
280
 
278
281
  return e;
279
282
  });
280
-
283
+
281
284
 
282
285
  let newSpread = splitByCommas.join(' ').trim().replace(/,$/, '');
283
286
 
@@ -348,7 +351,7 @@ function Compiler(func, file) {
348
351
  newAttributes.push(attribute);
349
352
  for (let key in attributes) {
350
353
 
351
- let value = attributes[key];
354
+ let value = attributes[key];
352
355
  let oldvalue = value;
353
356
  if (value && !value.new) {
354
357
 
@@ -478,92 +481,45 @@ function Compiler(func, file) {
478
481
  let myChildrens = [];
479
482
 
480
483
  let name = component.split("<")[1].split(">")[0].split(" ")[0].replace("/", "");
481
- let componentAttributes = component.split("<")[1].split(">")[0].split(" ").join(" ").replace(name, "").trim();
482
- const dynamicAttributesRegex = /(\w+)(?:="([^"]*?)"|='([^']*?)'|(?:=\{([^}]*?)\})?|(?:=\{(.*?)*\})?|(?:={([^}]*?)})?|(?:{([^}]*?)})?|(?:}))?|\$=\s*\{\s*\{\s*([^]*?)\s*\}\s*\}/gs;
483
-
484
-
485
-
486
- let props = component.match(dynamicAttributesRegex)
487
-
488
- let filteredProps = [];
489
- let isWithinComponent = false;
490
- let componentName = name
491
- let currentProps = []
484
+ let componentAttributes = component.split("<")[1].split(">")[0].split(" ").join(" ").replace(name, "").trim();
485
+ let props = component.includes('/>')? component.split(`<`)[1].split('/>')[0] : component.split(`<`)[1].split(`>`)[1].split(`</${name}`)[0].trim()
486
+ props = props.replaceAll(/\s+/g, " ").trim()
487
+ props = props.replace(name, '').trim()
488
+ component = component.replace(componentAttributes, '')
489
+ const dynamicAttributesRegex = /([a-zA-Z0-9_-]+)\s*=\s*("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|\{(?:[^{}]|(?:\{(?:[^{}]|(?:\{(.*.*?)\})*)*\})*)*\}|(?:\([^)]*\)|()\s*=>\s*(?:\{.*.*\})?|\{.*\})|\[[^\]]*\])/gs;
492
490
 
491
+ const attributeObject = {};
492
+
493
493
  let $_ternaryprops = []
494
494
 
495
- for (let prop of props) {
496
-
497
- if (prop === componentName) {
498
-
499
- isWithinComponent = true;
500
- filteredProps.push(prop);
501
- } else if (isWithinComponent && prop.includes('=')) {
502
-
503
- if (prop.startsWith('$=')) {
504
- let old = prop
505
- let match = prop.replace(/\$\s*=\s*\{\s*\{\s*([^]*?)\s*\}\s*\}/gs, '$1')
506
- match = match.replace('$:', '$_ternary:')
507
- component = component.replace(old, '')
508
- componentAttributes = componentAttributes.replace(old, match)
509
-
510
- $_ternaryprops.push(prop)
511
-
512
- }
513
- else if (prop.includes('${')) {
514
-
515
-
516
- prop = prop.replace('="', ':')
517
- if (prop.includes('${')) {
518
- prop = prop.replace('="', ':')
519
- prop = prop.replace('${', '')
520
- }
521
- if (prop.includes('="${{')) {
522
- prop = prop.replace('${{', '{')
523
- prop = prop.replace('}}', '}')
524
- prop = prop.replace('="', ':')
525
- prop = prop.replace('}"', '}')
526
- }
527
-
528
- }
529
- if (prop.includes('={')) {
530
- let value = prop.split('={')
531
- let isObj = value[1].match(/^{.*}$/gs) ? true : false
532
- if (!isObj) {
533
- // remove trailing }
534
- value[1] = value[1].replace(/}\s*$/, '')
535
- }
536
-
537
- if (value[0] == 'style' && isObj) {
538
- value[1] = `this.parseStyle(${value[1]})`
539
- }
540
- prop = `${value[0]}:${value[1]}`
541
- }
542
-
543
- if (prop.includes('function') || prop.includes('=>')) {
544
- // parse 'function' to function
545
- prop = prop.replace("'", '')
546
-
547
- if (prop.endsWith("}'")) {
548
- prop = prop.replace("}'", '}')
549
-
550
- }
551
-
552
- prop = prop.replace('=function', ':function')
553
- }
554
-
555
- filteredProps.push(prop);
556
-
557
-
558
-
559
- } else if (isWithinComponent && prop.includes('}')) {
560
-
561
- }
562
-
495
+ let match;
496
+ let propstring = ''
497
+ // props right now is just a string with all of them on one line and a space between each
498
+ while ((match = dynamicAttributesRegex.exec(props)) !== null) {
499
+ let str = match[0].trim().replace(/\s+/g, " ");
500
+ if (!str.includes('=')) {
501
+ continue
502
+ }
503
+
504
+
505
+ str = str.replaceAll(/\s+/g, " ")
506
+ str = str.split('=')
507
+ let key = str[0].trim()
508
+ let value = str.slice(1).join('=').trim().match(/\{.*\}/gs) ? str.slice(1).join('=').trim().match(/\{.*\}/gs)[0] : str.slice(1).join('=').trim();
563
509
 
564
- else {
565
- isWithinComponent = false;
510
+
511
+
512
+ let isObject = value.startsWith('{{') && value.endsWith('}}')
513
+ if (isObject) {
514
+ value = value.split('{{')[1].split('}}')[0].trim()
515
+ value = `{${value}}`
516
+ propstring += `${key}:${value},`
517
+ } else {
518
+ // remove starting { and ending } using regex
519
+ value = value.replace(/^{/, '').replace(/}$/, '')
520
+ propstring += `${key}:${value},`
566
521
  }
522
+
567
523
  }
568
524
  component = component.replaceAll(/\s+/g, " ");
569
525
 
@@ -574,7 +530,7 @@ function Compiler(func, file) {
574
530
 
575
531
  let children = new RegExp(`<${name}[^>]*>([^]*)<\/${name}>`, 'gs').exec(component)?.[1] || null;
576
532
 
577
- props = filteredProps.join(',').replace(/\s+/g, " ").trim().replace(/,$/, '')
533
+
578
534
 
579
535
  let savedname = name;
580
536
 
@@ -607,24 +563,15 @@ function Compiler(func, file) {
607
563
 
608
564
 
609
565
 
610
-
611
- props = props.replaceAll(`,${savedname}`, '').replaceAll(savedname, '')
612
- if (props.startsWith(',')) {
613
- props = props.replace(',', '')
614
- }
615
- props = props.replaceAll("='", ":'")
616
- .replaceAll('=`', ':`')
617
- .replaceAll('="', ':"')
618
- .replaceAll('={', ':')
566
+ propstring = propstring.replace(/,$/, '')
619
567
 
620
568
 
621
569
  /**
622
570
  * @memoize - memoize a component to be remembered on each render and replace the old jsx
623
571
  */
624
572
 
625
-
626
573
  let replace = "";
627
- replace = `\${this.memoize(this.createComponent(${savedname}, {${props}}, [\`${myChildrens.join('')}\`]))}`;
574
+ replace = `\${this.memoize(this.createComponent(${savedname}, {${propstring}}, [\`${myChildrens.join('')}\`]))}`;
628
575
 
629
576
 
630
577
  body = body.replace(before, replace);
@@ -640,47 +587,49 @@ function Compiler(func, file) {
640
587
  let replaceMents = [];
641
588
 
642
589
 
643
- for (let match of imports) {
644
- let path = match.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').trim()
645
- switch (true) {
646
- case path && !path.includes('./') && !path.includes('/vader.js') && !path.includes('/vaderjs/client') && !path.startsWith('src') && !path.startsWith('public') && !path.includes('http') && !path.includes('https'):
647
- let componentFolder = fs.existsSync(process.cwd() + '/node_modules/' + path) ? process.cwd() + '/node_modules/' + path : process.cwd() + '/node_modules/' + path.split('/')[0]
648
- componentFolder = componentFolder.split(process.cwd())[1]
649
- if (!fs.existsSync(process.cwd() + componentFolder)) {
650
- throw new Error('Could not find ' + path + ' at ' + match + ' in file ' + file)
651
- }
652
-
653
- if (!fs.existsSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'))) {
654
- fs.mkdirSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'), { recursive: true })
655
- }
656
-
657
- let baseFolder = componentFolder.split('node_modules')[1].split('/')[1]
658
- let glp = globSync('**/**/**/**.{jsx,js}', {
659
- cwd: process.cwd() + '/node_modules/' + baseFolder + '/',
660
- absolute: true,
661
- recursive: true
662
- })
663
- for (let file of glp) {
664
- let text = fs.readFileSync(file, "utf8");
665
- if (!file.endsWith('.js') && file.endsWith('.jsx')) {
666
- text = Compiler(text, file);
667
-
590
+ if(imports){
591
+ for (let match of imports) {
592
+ let path = match.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').trim()
593
+ switch (true) {
594
+ case path && !path.includes('./') && !path.includes('/vader.js') && !path.includes('/vaderjs/client') && !path.startsWith('src') && !path.startsWith('public') && !path.includes('http') && !path.includes('https'):
595
+ let componentFolder = fs.existsSync(process.cwd() + '/node_modules/' + path) ? process.cwd() + '/node_modules/' + path : process.cwd() + '/node_modules/' + path.split('/')[0]
596
+ componentFolder = componentFolder.split(process.cwd())[1]
597
+ if (!fs.existsSync(process.cwd() + componentFolder)) {
598
+ throw new Error('Could not find ' + path + ' at ' + match + ' in file ' + file)
668
599
  }
669
- let dest = file.split('node_modules')[1]
670
- dest = dest.split(baseFolder)[1]
671
- writer(process.cwd() + '/dist/src/' + baseFolder + dest, text)
672
- let importname = match.split('import')[1].split('from')[0].trim()
673
- let oldImportstring = match.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').trim()
674
- let newImport = `/src/${baseFolder + dest}`
675
- newImport = newImport.replaceAll('.jsx', '.js').replaceAll('\\', '/')
676
- replaceMents.push({ match: oldImportstring, replace: newImport })
677
- console.log(`📦 imported Node Package ${baseFolder} `)
678
- }
679
-
680
-
681
- break;
682
- default:
683
- break;
600
+
601
+ if (!fs.existsSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'))) {
602
+ fs.mkdirSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'), { recursive: true })
603
+ }
604
+
605
+ let baseFolder = componentFolder.split('node_modules')[1].split('/')[1]
606
+ let glp = globSync('**/**/**/**.{jsx,js}', {
607
+ cwd: process.cwd() + '/node_modules/' + baseFolder + '/',
608
+ absolute: true,
609
+ recursive: true
610
+ })
611
+ for (let file of glp) {
612
+ let text = fs.readFileSync(file, "utf8");
613
+ if (!file.endsWith('.js') && file.endsWith('.jsx')) {
614
+ text = Compiler(text, file);
615
+
616
+ }
617
+ let dest = file.split('node_modules')[1]
618
+ dest = dest.split(baseFolder)[1]
619
+ writer(process.cwd() + '/dist/src/' + baseFolder + dest, text)
620
+ let importname = match.split('import')[1].split('from')[0].trim()
621
+ let oldImportstring = match.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').trim()
622
+ let newImport = `/src/${baseFolder + dest}`
623
+ newImport = newImport.replaceAll('.jsx', '.js').replaceAll('\\', '/')
624
+ replaceMents.push({ match: oldImportstring, replace: newImport })
625
+ console.log(`📦 imported Node Package ${baseFolder} `)
626
+ }
627
+
628
+
629
+ break;
630
+ default:
631
+ break;
632
+ }
684
633
  }
685
634
  }
686
635
 
@@ -873,6 +822,8 @@ const glb = await glob("**/**/**/**.{jsx,js}", {
873
822
  absolute: true,
874
823
  recursive: true
875
824
  });
825
+ let hasRendered = []
826
+
876
827
  async function Build() {
877
828
  globalThis.isBuilding = true
878
829
  console.log(globalThis.isProduction ? 'Creating Optimized Production Build\n' : '')
@@ -887,191 +838,130 @@ async function Build() {
887
838
 
888
839
  function ssg(routes = []) {
889
840
  globalThis.isBuilding = true
890
- routes.forEach(async (route) => {
891
- if (route.url.includes(':')) {
892
- return
893
- }
894
- let equalparamroute = routes.map((e) => {
895
- if (e.url.includes(':')) {
896
- let url = e.url.split('/:')[0]
897
- if (url && route.url === url) {
898
- return e
899
- } else {
900
- return null
841
+ let server = http.createServer((req, res) => {
842
+ let route = routes.find((e) => e.url === req.url)
843
+ if (route) {
844
+ let document = globalThis.routeDocuments.find((e) => e.url === req.url)
845
+ res.writeHead(200, { 'Content-Type': 'text/html' });
846
+ res.end(document.document);
847
+ } else {
848
+ const filePath = process.cwd() + '/dist/' + req.url
901
849
 
850
+ fs.readFile(filePath, (err, data) => {
851
+ if (err) {
852
+ res.writeHead(404, { 'Content-Type': filePath.includes('js') ? 'text/javascript' : 'text/html' });
853
+ res.end('File not found');
854
+ } else {
855
+ res.writeHead(200, { 'Content-Type': filePath.includes('js') ? 'text/javascript' : 'text/html' });
856
+ res.end(data);
902
857
  }
903
- }
904
- return null
905
- }).filter(Boolean)
906
- let document = `
907
- <!DOCTYPE html>
908
- <html lang="en">
909
- <head>
910
- <script>
911
- window.routes = JSON.parse('${JSON.stringify(routes)}')
912
-
913
-
914
- </script>
915
- <script id="isServer">
916
- window.isServer = true
917
- </script>
918
- <meta charset="UTF-8">
919
- <meta name="viewport" content="width=device-width,initial-scale=1.0">
920
- <script type="module" id="meta">
921
- window.history.pushState({}, '', '${route.url}')
922
-
923
- </script>
924
- <script type="module" id="router">
925
- import VaderRouter from '/router.js'
926
- const router = new VaderRouter('${route.url}', 3000)
927
- router.get('${route.url}', async (req, res) => {
928
- try{
929
- let module = await import('/${route.fileName.replace('.jsx', '.js')}')
930
- if(Object.keys(module).includes('$prerender') && !module.$prerender){
931
- document.head.setAttribute('prerender', 'false')
932
- }
933
- res.render(module, req, res, module.$metadata)
934
- }
935
- catch(error){
936
- let errorMessage = {
937
- message: error.message,
938
- name: error.name,
939
- stack: error.stack,
940
- path: window.location.pathname
941
- };
942
-
943
-
944
- document.documentElement.setAttribute('error', JSON.stringify(errorMessage));
945
- throw new Error(error)
946
- }
947
- })
948
- ${equalparamroute.length > 0 ? equalparamroute.map((e) => {
949
-
950
-
951
-
952
- return `router.get('${e.url}', async (req, res) => {
953
- let module = await import('/${e.fileName.replace('.jsx', '.js')}')
954
- res.render(module, req, res, module.$metadata)
955
- })\n`
956
- }) : ''}
957
- router.listen(3000)
958
-
959
- </script>
960
- </head>
961
- <body>
962
- <div id="root"></div>
963
- </body>
964
-
965
-
966
- </html>
967
- `;
968
-
969
- // generate random but common ports
970
- let port = Math.floor(Math.random() * (65535 - 49152 + 1) + 49152)
971
-
972
- const server = http.createServer((req, res) => {
858
+ });
859
+ }
860
+ });
973
861
 
974
- if (req.url === '/') {
975
- res.writeHead(200, { 'Content-Type': 'text/html' });
976
- res.end(document);
977
- } else {
978
- // Serve static files (adjust the file paths based on your project structure)
979
- const filePath = process.cwd() + '/dist/' + req.url
980
-
981
- fs.readFile(filePath, (err, data) => {
982
- if (err) {
983
- res.writeHead(404, { 'Content-Type': filePath.includes('js') ? 'text/javascript' : 'text/html' });
984
- res.end('File not found');
985
- } else {
986
- res.writeHead(200, { 'Content-Type': filePath.includes('js') ? 'text/javascript' : 'text/html' });
987
- res.end(data);
988
- }
989
- });
990
- }
991
- });
862
+ let port = 12000
863
+ server.on('error', (err) => {
864
+ if (err.code === 'EADDRINUSE') {
865
+ setTimeout(() => {
866
+ server.close();
867
+ server.listen(++port);
868
+ }, 1000);
869
+ }
870
+ })
992
871
 
993
- server.listen(port)
994
- server.on('error', (err) => {
995
- if (err.code === 'EADDRINUSE') {
996
- console.log(`Port ${port} is in use, trying another port...`);
997
- setTimeout(() => {
998
- server.close();
999
- server.listen(++port);
1000
- }, 1000);
1001
- }
1002
- })
872
+ const browser = puppeteer.launch({
873
+ headless: "new", args: ['--no-sandbox', '--disable-setuid-sandbox'],
874
+ warning: false,
875
+ })
876
+ server.listen(port);
1003
877
 
878
+ routes.forEach(async (route) => {
879
+ if (route.url.includes(':')) {
880
+ return
881
+ }
1004
882
  globalThis.listen = true;
1005
883
 
1006
- const browser = await puppeteer.launch({
1007
- headless: "new", args: ['--no-sandbox', '--disable-setuid-sandbox'],
1008
- warning: false,
1009
- })
1010
884
  try {
1011
885
 
1012
886
  route.url = route.url.replaceAll(/\/:[a-zA-Z0-9_-]+/gs, '')
1013
- let page = await browser.newPage();
1014
- // Handle browser errors
1015
- page.on('error', (err) => {
1016
- console.error('BROWSER ERROR:', JSON.parse(err));
1017
- });
1018
-
1019
- try {
1020
- page.on('pageerror', async err => {
1021
- let errorObj = JSON.parse(await page.evaluate(() => document.documentElement.getAttribute('error')) || '{}')
1022
- console.log('\x1b[31m%s\x1b[0m', 'Compiler Error:', errorObj)
1023
-
887
+ let page = (await browser).newPage()
888
+ page.then(async (page) => {
889
+ page.on('error', (err) => {
890
+ console.error('JS ERROR:', JSON.parse(err));
1024
891
  });
1025
- } catch (error) {
1026
- browser.close()
1027
- }
1028
- // Handle page crashes
1029
- page.on('crash', () => {
1030
- console.error('PAGE CRASHED');
1031
- });
1032
- page.on('requestfailed', request => {
1033
- console.error('REQUEST FAILED:', request.url(), request.failure().errorText);
1034
- });
1035
- await page.goto(`http://localhost:${port}/`, { waitUntil: 'networkidle2' });
1036
-
1037
-
1038
-
892
+ try {
893
+ page.on('pageerror', async err => {
894
+ let errorObj = JSON.parse(await page.evaluate(() => document.documentElement.getAttribute('error')) || '{}')
895
+ console.log('\x1b[31m%s\x1b[0m', 'Compiler Error:', errorObj)
896
+
897
+ console.log('\x1b[31m%s\x1b[0m', 'Error:', err)
898
+ });
899
+ } catch (error) {
900
+ page.close()
901
+ }
902
+ page.on('crash', () => {
903
+ console.error(`Render process crashed for ${route.url}`)
904
+ });
905
+
906
+ await page.goto(`http://localhost:${port}${route.url}`, { waitUntil: 'networkidle2' });
907
+
908
+ page.evaluate(() => {
909
+ document.querySelector('#meta').remove()
910
+ document.querySelector('#isServer').innerHTML = 'window.isServer = false'
911
+ if (document.head.getAttribute('prerender') === 'false') {
912
+ document.querySelector('#root').innerHTML = ''
913
+ console.log(`Disabled prerendering for ${window.location.pathname}`)
914
+ }
915
+ })
916
+ let html = await page.content();
1039
917
 
918
+ html = await prettier.format(html, { parser: "html" })
1040
919
 
920
+ writer(process.cwd() + '/dist/' + (route.url === '/' ? 'index.html' : `${route.url}/` + 'index.html'), html)
1041
921
 
922
+ console.log(`\x1b[32m%s\x1b[0m`, `Prerendered ${route.url}...`)
1042
923
 
1043
- await page.evaluate(() => {
1044
- document.getElementById('meta').remove()
1045
- document.querySelector('#isServer').innerHTML = 'window.isServer = false'
1046
- if (document.head.getAttribute('prerender') === 'false') {
1047
- document.querySelector('#root').innerHTML = ''
1048
- console.log(`Disabled prerendering for ${window.location.pathname}`)
1049
- }
924
+ hasRendered.push(route.url)
1050
925
  })
1051
- let html = await page.content();
1052
-
1053
- html = await prettier.format(html, { parser: "html" })
1054
926
 
1055
927
 
1056
- await writer(process.cwd() + '/dist/' + (route.url === '/' ? 'index.html' : `${route.url}/` + 'index.html'), html)
1057
928
 
1058
929
 
1059
930
  } catch (error) {
1060
- console.log(error)
1061
- }
931
+ console.log('\x1b[31m%s\x1b[0m', 'Error:', error)
1062
932
 
933
+ }
1063
934
  finally {
1064
- browser.close()
1065
- server.close()
1066
935
  }
1067
936
  })
1068
937
 
1069
- let timeout = setTimeout(() => {
1070
- globalThis.isBuilding = false
1071
- clearTimeout(timeout)
1072
- }, 1000)
1073
- }
1074
938
 
939
+
940
+
941
+
942
+ function kill() {
943
+ console.log(`\x1b[32m%s\x1b[0m`, `\nPrerendered ${routes.length} pages...\n`)
944
+ server.close()
945
+ browser.then((browser) => {
946
+ browser.close()
947
+ })
948
+ hasRendered = []
949
+ globalThis.isBuilding = false
950
+
951
+ }
952
+
953
+ if (hasRendered.length === routes.length) {
954
+ kill()
955
+ } else {
956
+ console.log(`\x1b[32m%s\x1b[0m`, `Prerendering ${routes.length} pages...\n`)
957
+ let interval = setInterval(() => {
958
+ if (hasRendered.length === routes.length) {
959
+ kill()
960
+ clearInterval(interval)
961
+ }
962
+ }, 1000);
963
+ }
964
+ }
1075
965
  globalThis.routes = []
1076
966
 
1077
967
  for await (let file of glb) {
@@ -1171,7 +1061,9 @@ async function Build() {
1171
1061
  }
1172
1062
 
1173
1063
 
1174
- globalThis.routes.push({ fileName: fileName, url: obj.url, html: '/' + (isBasePath ? 'index.html' : `${obj.url}/` + 'index.html') })
1064
+ if (!obj.url.includes(':')) {
1065
+ globalThis.routes.push({ fileName: fileName, url: obj.url, html: '/' + (isBasePath ? 'index.html' : `${obj.url}/` + 'index.html') })
1066
+ }
1175
1067
 
1176
1068
 
1177
1069
  let stats = {
@@ -1188,7 +1080,92 @@ async function Build() {
1188
1080
  globalThis.isProduction ? console.log(string) : null
1189
1081
  }
1190
1082
 
1191
- ssg(globalThis.routes)
1083
+ globalThis.routeDocuments = []
1084
+ globalThis.routes.map((route) => {
1085
+ let equalparamroute = globalThis.routes.map((e) => {
1086
+ if (e.url.includes(':')) {
1087
+ let url = e.url.split('/:')[0]
1088
+ if (url && route.url === url) {
1089
+ return e
1090
+ } else {
1091
+ return null
1092
+
1093
+ }
1094
+ }
1095
+ return null
1096
+ }).filter(Boolean)
1097
+ let document = `
1098
+ <!DOCTYPE html>
1099
+ <html lang="en">
1100
+ <head>
1101
+ <script>
1102
+ window.routes = JSON.parse('${JSON.stringify(globalThis.routes)}')
1103
+ </script>
1104
+ <script type="module" id="meta">
1105
+ window.history.pushState({}, '', '${route.url}')
1106
+
1107
+ </script>
1108
+ <script id="isServer">
1109
+ window.isServer = true
1110
+ </script>
1111
+ <meta charset="UTF-8">
1112
+ <meta name="viewport" content="width=device-width,initial-scale=1.0">
1113
+
1114
+ <script type="module" id="router">
1115
+ import VaderRouter from '/router.js'
1116
+ const router = new VaderRouter('${route.url}')
1117
+ router.get('${route.url}', async (req, res) => {
1118
+ try{
1119
+ let module = await import('/${route.fileName.replace('.jsx', '.js')}')
1120
+ if(Object.keys(module).includes('$prerender') && !module.$prerender){
1121
+ document.head.setAttribute('prerender', 'false')
1122
+ }
1123
+ res.render(module, req, res, module.$metadata)
1124
+ }
1125
+ catch(error){
1126
+ let errorMessage = {
1127
+ message: error.message,
1128
+ name: error.name,
1129
+ stack: error.stack,
1130
+ path: window.location.pathname
1131
+ };
1132
+
1133
+
1134
+ document.documentElement.setAttribute('error', JSON.stringify(errorMessage));
1135
+ throw new Error(error)
1136
+ }
1137
+ })
1138
+ ${equalparamroute.length > 0 ? equalparamroute.map((e) => {
1139
+
1140
+
1141
+
1142
+ return `router.get('${e.url}', async (req, res) => {
1143
+ let module = await import('/${e.fileName.replace('.jsx', '.js')}')
1144
+ res.render(module, req, res, module.$metadata)
1145
+ })\n`
1146
+ }) : ''}
1147
+ router.listen(3000)
1148
+
1149
+ </script>
1150
+ </head>
1151
+ <body>
1152
+ <div id="root"></div>
1153
+ </body>
1154
+
1155
+
1156
+ </html>
1157
+ `;
1158
+ globalThis.routeDocuments.push({ url: route.url, document: document })
1159
+ })
1160
+
1161
+ if(globalThis.devMode && !globalThis.oneAndDone){
1162
+ ssg(globalThis.routes)
1163
+ globalThis.oneAndDone = true
1164
+ console.log(`In Development Mode, Prerendering ${globalThis.routes.length} pages... Once`)
1165
+ }
1166
+ else if(globalThis.isProduction){
1167
+ ssg(globalThis.routes)
1168
+ }
1192
1169
 
1193
1170
 
1194
1171
  const scannedSourceFiles = await glob("**/**.{jsx,js,json}", {
@@ -1216,11 +1193,10 @@ async function Build() {
1216
1193
  scannedSourceFiles.forEach(async (file) => {
1217
1194
  file = file.replace(/\\/g, '/');
1218
1195
  let name = file.split('/src/')[1]
1219
- //parse jsx
1220
1196
 
1221
1197
  let data = await reader(process.cwd() + "/src/" + name)
1222
1198
  if (name.includes('.jsx')) {
1223
- let origin = process.cwd() + "/src/" + name
1199
+ let origin = process.cwd() + "/src/" + name
1224
1200
  if (!globalThis.isProduction) {
1225
1201
  let { sourceMap } = sourceMapGen({ origin: origin, fileName: name }, await Compiler(data, origin))
1226
1202
  data = data + `\n//# sourceMappingURL=/src/maps/${name.replace('.jsx', '.js.map')}\n //#sourceURL=${origin}`
@@ -1229,11 +1205,13 @@ async function Build() {
1229
1205
  await writer(process.cwd() + "/dist/src/" + name.split('.jsx').join('.js'), await Compiler(data, origin))
1230
1206
  return
1231
1207
  }
1232
- bundleSize += fs.statSync(process.cwd() + "/src/" + name).size;
1208
+ if (!name.includes('.map')) {
1209
+ bundleSize += fs.statSync(process.cwd() + "/src/" + name).size;
1210
+ }
1233
1211
  await writer(process.cwd() + "/dist/src/" + name, data);
1234
1212
  })
1235
1213
 
1236
- const scannedPublicFiles = await glob("**/**.{css,js,html,mjs,cjs}", {
1214
+ const scannedPublicFiles = await glob("**/**/**.{css,js,html,mjs,cjs,png,jpg,jpeg,gif,svg,mp4,webm,ogg}", {
1237
1215
  ignore: ["node_modules/**/*", "dist/**/*"],
1238
1216
  cwd: process.cwd() + '/public/',
1239
1217
  absolute: true,
@@ -1241,7 +1219,7 @@ async function Build() {
1241
1219
  scannedPublicFiles.forEach(async (file) => {
1242
1220
  file = file.replace(/\\/g, '/');
1243
1221
  file = file.split('/public/')[1]
1244
- let data = await reader(process.cwd() + "/public/" + file)
1222
+ let data = fs.readFileSync(process.cwd() + "/public/" + file);
1245
1223
  bundleSize += fs.statSync(process.cwd() + "/public/" + file).size;
1246
1224
  await writer(process.cwd() + "/dist/public/" + file, data);
1247
1225
  })
@@ -1270,17 +1248,18 @@ async function Build() {
1270
1248
  let data = await reader(process.cwd() + "/node_modules/vaderjs/runtime/" + file)
1271
1249
  await writer(process.cwd() + "/dist/" + file, data);
1272
1250
  });
1251
+
1273
1252
 
1274
1253
  }
1275
1254
 
1276
1255
  globalThis.isBuilding = false
1277
- globalThis.isProduction ? console.log(`\nTotal bundle size: ${Math.round(bundleSize / 1000)}kb`) : null
1278
1256
 
1257
+ globalThis.isProduction ? console.log(`Total Bundle Size: ${Math.round(bundleSize / 1000)}kb`) : null
1279
1258
  bundleSize = 0;
1280
1259
 
1281
1260
  return true
1282
1261
  }
1283
- const s = () => {
1262
+ const s = (port) => {
1284
1263
 
1285
1264
  const server = http.createServer((req, res) => {
1286
1265
 
@@ -1365,10 +1344,9 @@ const s = () => {
1365
1344
  return 'application/octet-stream';
1366
1345
  }
1367
1346
  }
1368
-
1369
- const PORT = process.env.PORT || 3000;
1370
- server.listen(PORT, () => {
1371
- console.log(`Server is running on port ${PORT}`);
1347
+
1348
+ server.listen(port, () => {
1349
+ console.log(`Server is running on port ${port}`);
1372
1350
  globalThis.ws = ws
1373
1351
  });
1374
1352
 
@@ -1381,11 +1359,15 @@ switch (true) {
1381
1359
 
1382
1360
  globalThis.devMode = true
1383
1361
  globalThis.isProduction = false
1362
+
1363
+ let p = process.env.PORT || config.port || process.argv.includes('-p') ? process.argv[process.argv.indexOf('-p') + 1] : 3000
1364
+ globalThis.oneAndDone = false
1384
1365
  console.log(`
1385
- Vader.js v1.3.3
1366
+ Vader.js v${fs.readFileSync(process.cwd() + '/node_modules/vaderjs/package.json', 'utf8').split('"version": "')[1].split('"')[0]}
1386
1367
  - Watching for changes in ./pages
1387
1368
  - Watching for changes in ./src
1388
1369
  - Watching for changes in ./public
1370
+ - Serving on port ${p}
1389
1371
  `)
1390
1372
  !globalThis.isBuilding ? Build() : null
1391
1373
 
@@ -1404,15 +1386,13 @@ Vader.js v1.3.3
1404
1386
  })
1405
1387
  }
1406
1388
 
1389
+ console.log('\nRebuilding...')
1407
1390
  globalThis.isBuilding = true
1408
1391
  Build()
1409
1392
  }
1410
1393
  }).on('error', (err) => console.log(err))
1411
- })
1412
- let p = process.argv[process.argv.indexOf('dev') + 1] || 3000
1413
-
1414
- process.env.PORT = p
1415
- s()
1394
+ })
1395
+ s(p)
1416
1396
 
1417
1397
  globalThis.listen = true;
1418
1398
 
@@ -1432,30 +1412,30 @@ Building to ./dist
1432
1412
 
1433
1413
  break;
1434
1414
  case process.argv.includes('start') && !process.argv.includes('dev') && !process.argv.includes('build'):
1435
- let port = process.argv[process.argv.indexOf('--serve') + 1] || 3000
1436
- process.env.PORT = port
1415
+ let port = process.env.PORT || config.port || process.argv.includes('-p') ? process.argv[process.argv.indexOf('-p') + 1] : 3000
1416
+ console.log(port)
1437
1417
  globalThis.devMode = false
1438
1418
  console.log(`
1439
1419
  Vader.js v1.3.3
1440
1420
  Serving ./dist on port ${port}
1441
1421
  url: http://localhost:${port}
1442
1422
  `)
1443
- s()
1423
+ s(port)
1444
1424
  break;
1445
1425
  default:
1446
1426
  // add color
1447
1427
  console.log(`
1448
- Vader.js is a reactive framework for building interactive applications for the web!
1428
+ Vader.js is a reactive framework for building interactive applications for the web built ontop of bun.js!
1449
1429
 
1450
1430
  Usage: vader <command>
1451
1431
 
1452
1432
  Commands:
1453
1433
 
1454
- vaderjs dev Start the development server
1434
+ vaderjs dev -p <number> Start the development server
1455
1435
 
1456
1436
  vaderjs build Build the project to ./dist
1457
1437
 
1458
- vaderjs start <port> Production Mode (default 3000 or process.env.PORT)
1438
+ vaderjs start -p <number> Production Mode (default 3000 or process.env.PORT)
1459
1439
 
1460
1440
  Learn more about vader: https://vader-js.pages.dev/
1461
1441
 
@@ -1463,4 +1443,3 @@ Learn more about vader: https://vader-js.pages.dev/
1463
1443
  break;
1464
1444
 
1465
1445
  }
1466
-