vaderjs 1.3.3-8924566yt812 → 1.3.3-9bn28b17d42e1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/client/index.js +221 -222
- package/package.json +4 -2
- package/runtime/router.js +1 -1
- package/runtime/vader.js +1 -1
- package/vader.js +571 -448
package/vader.js
CHANGED
|
@@ -1,11 +1,40 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import fs from "fs";
|
|
2
|
+
import fs, { fstatSync } from "fs";
|
|
3
3
|
import { glob, globSync, globStream, globStreamSync, Glob, } from 'glob'
|
|
4
4
|
import puppeteer from 'puppeteer';
|
|
5
5
|
import http from 'http'
|
|
6
|
+
import { SourceMapGenerator } from 'source-map'
|
|
7
|
+
|
|
6
8
|
import { WebSocketServer } from 'ws'
|
|
9
|
+
import prettier from 'prettier'
|
|
7
10
|
import { watch } from "fs";
|
|
8
11
|
import path from 'path'
|
|
12
|
+
|
|
13
|
+
globalThis.compiledFiles = []
|
|
14
|
+
|
|
15
|
+
const sourceMapGen = (data, code) => {
|
|
16
|
+
let { origin, fileName } = data
|
|
17
|
+
const sourceMap = new SourceMapGenerator({ file: '/src/' + fileName.replace('.jsx', '.js') });
|
|
18
|
+
|
|
19
|
+
const lines = fs.readFileSync(origin, "utf8").split("\n");
|
|
20
|
+
let line = 1;
|
|
21
|
+
let column = 0;
|
|
22
|
+
for (const l of lines) {
|
|
23
|
+
sourceMap.addMapping({
|
|
24
|
+
source: origin,
|
|
25
|
+
sourceRoot: '/src',
|
|
26
|
+
original: { line: line, column: 0 },
|
|
27
|
+
generated: { line: line, column: 0 },
|
|
28
|
+
});
|
|
29
|
+
line++;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
sourceMap.setSourceContent(origin, fs.readFileSync(origin, "utf8"));
|
|
33
|
+
|
|
34
|
+
code = code + `\n//# sourceMappingURL=./src/maps/${fileName.replace('.jsx', '.js')}.map \n //#sourceURL=/src/maps/${fileName.replace('.jsx', '.js')}.map`
|
|
35
|
+
return { code, sourceMap };
|
|
36
|
+
}
|
|
37
|
+
|
|
9
38
|
let config = await import('file://' + process.cwd() + '/vader.config.js').then((e) => e.default || e)
|
|
10
39
|
let writer = async (file, data) => {
|
|
11
40
|
globalThis.isWriting = file
|
|
@@ -22,8 +51,8 @@ let writer = async (file, data) => {
|
|
|
22
51
|
globalThis.isWriting = null
|
|
23
52
|
return { _written: true };
|
|
24
53
|
};
|
|
25
|
-
|
|
26
|
-
let bundleSize = 0;
|
|
54
|
+
|
|
55
|
+
let bundleSize = 0;
|
|
27
56
|
|
|
28
57
|
if (!fs.existsSync(process.cwd() + '/dist')) {
|
|
29
58
|
fs.mkdirSync(process.cwd() + '/dist')
|
|
@@ -33,91 +62,47 @@ if (!fs.existsSync(process.cwd() + '/dist')) {
|
|
|
33
62
|
|
|
34
63
|
|
|
35
64
|
if (typeof process.env.isCloudflare !== "undefined" || !fs.existsSync(process.cwd() + '/dist/index.html')) {
|
|
36
|
-
|
|
37
|
-
fs.writeFileSync(process.cwd() + "/dist/index.html", htmlFile)
|
|
65
|
+
fs.writeFileSync(process.cwd() + "/dist/index.html", '')
|
|
38
66
|
}
|
|
39
67
|
|
|
40
68
|
|
|
41
69
|
|
|
42
70
|
function Compiler(func, file) {
|
|
43
|
-
let string = func;
|
|
71
|
+
let string = func;
|
|
44
72
|
let returns = []
|
|
45
73
|
let comments = string.match(/\{\s*\/\*.*\*\/\s*}/gs)?.map((comment) => comment.trim());
|
|
46
74
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
75
|
|
|
52
|
-
let childs = [];
|
|
53
76
|
|
|
54
|
-
const spreadAttributeRegex = /\s*([a-zA-Z0-9_-]+)(\s*\$\s*=\s*{{((?:[^{}]|(?:\{(?:[^{}]|(?:\{[^{}]*\})*)*\})*)*)}})/gs;
|
|
55
|
-
let spreadMatch;
|
|
56
|
-
while ((spreadMatch = spreadAttributeRegex.exec(string)) !== null) {
|
|
57
|
-
let [, element, spread] = spreadMatch;
|
|
58
|
-
let isJSXComponent = element.match(/[A-Z]/) ? true : false;
|
|
59
|
-
if (isJSXComponent) {
|
|
60
|
-
continue
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
let old = spread;
|
|
64
|
-
|
|
65
|
-
// turn spread into attributes
|
|
66
|
-
spread = spread.replace(/\s*$\s*=\s*/, "");
|
|
67
|
-
spread = spread.replace(/{{/, "");
|
|
68
|
-
spread = spread.replace(/}}/, "");
|
|
69
|
-
spread = spread.replace(/\$\s*=\s*/, "");
|
|
70
|
-
|
|
71
|
-
// turn : into =
|
|
72
77
|
|
|
73
|
-
// do not split inner Objects ex: {color: 'red', background: {color: 'blue'}} -> {color: 'red', background: {color: 'blue'}}
|
|
74
|
-
let splitByCommas = spread.split(/,(?![^{]*})/g);
|
|
75
|
-
splitByCommas = splitByCommas.map((e) => e.trim())
|
|
76
|
-
splitByCommas = splitByCommas.map((e) => {
|
|
77
|
-
switch (true) {
|
|
78
|
-
case e.includes('function') || e.includes('=>'):
|
|
79
|
-
e = e.replace(/:(.*)/gs, '={$1}')
|
|
80
|
-
break;
|
|
81
|
-
case e.includes('style'):
|
|
82
|
-
e = e.replace(/:(.*)/gs, '="${this.parseStyle($1)}"')
|
|
83
|
-
break;
|
|
84
|
-
case e.includes('[') && e.includes(']'):
|
|
85
|
-
e = e.replace(/:(.*)/gs, '={$1.join(" ")}')
|
|
86
|
-
break;
|
|
87
|
-
default:
|
|
88
|
-
e = e.replace(/:(.*)/gs, '=$1')
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
78
|
|
|
92
|
-
return e.trim()
|
|
93
|
-
})
|
|
94
79
|
|
|
95
|
-
|
|
80
|
+
let childs = [];
|
|
96
81
|
|
|
97
|
-
string = string.replace(old, newSpread);
|
|
98
82
|
|
|
99
|
-
|
|
83
|
+
// or : value boolean variable etc
|
|
84
|
+
const spreadAttributeRegex = /\s*([a-zA-Z0-9_-]+)\s*(\$\s*=\s*\{\s*\{(?:[^{}]|(?:\{(?:[^{}]|(?:\{[^{}]*\})*)*\})*)*\}\s*\})/gs;
|
|
100
85
|
|
|
101
86
|
|
|
87
|
+
string = parseComponents(string);
|
|
102
88
|
|
|
103
89
|
function extractAttributes(code) {
|
|
104
|
-
//
|
|
90
|
+
// grab $={...} and ={...}
|
|
105
91
|
const elementRegex = /<([a-zA-Z0-9_-]+)([^>]*)>/gs;
|
|
106
92
|
|
|
107
93
|
// Match attributes in an opening tag, including those with ={}
|
|
108
94
|
// Match attributes in an opening tag, including those with ={...}
|
|
109
95
|
const attributeRegex =
|
|
110
|
-
/\s*([a-zA-Z0-9_-]+)(\s*=\s*("([^"\\]*(
|
|
96
|
+
/\s*([a-zA-Z0-9_-]+)(\s*=\s*("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|\{(?:[^{}]|(?:\{(?:[^{}]|(?:\{[^{}]*\})*)*\})*)*\}|(?:\([^)]*\)|\{[^}]*\}|()=>\s*(?:\{[^}]*\})?)|\[[^\]]*\]))?/gs;
|
|
111
97
|
|
|
112
|
-
|
|
113
98
|
|
|
114
|
-
|
|
115
|
-
const functionAttributeRegex = /\s*([a-zA-Z0-9_-]+)
|
|
99
|
+
|
|
100
|
+
const functionAttributeRegex = /\s*([a-zA-Z0-9_-]+)\s*(=\s*{((?:[^{}]|(?:\{(?:[^{}]|(?:\{[^{}]*\})*)*\})*)*)})/gs;
|
|
116
101
|
|
|
117
102
|
let attributesList = [];
|
|
118
103
|
|
|
119
104
|
let spreadAttributes = [];
|
|
120
|
-
|
|
105
|
+
|
|
121
106
|
/**
|
|
122
107
|
* @search - handle spread for html elements
|
|
123
108
|
* @keywords - spread, spread attributes, spread props, spread html attributes
|
|
@@ -130,19 +115,46 @@ function Compiler(func, file) {
|
|
|
130
115
|
*
|
|
131
116
|
*/
|
|
132
117
|
let functionAttributes = [];
|
|
118
|
+
let spreadFunctions = [];
|
|
133
119
|
let functionMatch;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @search - handle attributes for html elements
|
|
123
|
+
* @keywords - attributes, props, html attributes
|
|
124
|
+
*/
|
|
125
|
+
let match;
|
|
126
|
+
while ((match = elementRegex.exec(string)) !== null) {
|
|
127
|
+
let [, element, attributes] = match;
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
let attributesMatch;
|
|
131
|
+
let elementAttributes = {};
|
|
132
|
+
|
|
133
|
+
while ((attributesMatch = attributeRegex.exec(attributes)) !== null) {
|
|
134
|
+
let [, attributeName, attributeValue] = attributesMatch;
|
|
135
|
+
|
|
136
|
+
elementAttributes[attributeName] = attributeValue || null;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
attributesList.push({ element, attributes: elementAttributes });
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
134
144
|
while ((functionMatch = functionAttributeRegex.exec(code)) !== null) {
|
|
135
145
|
|
|
136
146
|
let [, attributeName, attributeValue] = functionMatch;
|
|
137
147
|
let attribute = {};
|
|
138
148
|
|
|
139
|
-
if (attributeValue && attributeValue.includes("=>")
|
|
149
|
+
if (attributeValue && attributeValue.includes("=>")
|
|
150
|
+
&& !attributeValue.includes("this.bind")
|
|
151
|
+
|| attributeValue && attributeValue.includes("function")
|
|
140
152
|
&& !spreadFunctions.includes(attributeValue)
|
|
141
153
|
) {
|
|
142
|
-
|
|
154
|
+
|
|
143
155
|
let ref = Math.random().toString(36).substring(2).split('').filter((e) => !Number(e)).join('')
|
|
144
156
|
let old = `${attributeName}${attributeValue}`
|
|
145
|
-
|
|
157
|
+
|
|
146
158
|
let elementMatch = string.match(/<([a-zA-Z0-9_-]+)([^>]*)>/gs);
|
|
147
159
|
let isJSXComponent = false;
|
|
148
160
|
elementMatch.forEach((element) => {
|
|
@@ -155,11 +167,15 @@ function Compiler(func, file) {
|
|
|
155
167
|
isJSXComponent = elementTag.match(/^[A-Z]/) ? true : false;
|
|
156
168
|
}
|
|
157
169
|
});
|
|
170
|
+
if (isJSXComponent) {
|
|
171
|
+
continue
|
|
172
|
+
}
|
|
158
173
|
// add ; after newlines
|
|
159
174
|
|
|
160
175
|
|
|
161
176
|
let newvalue = attributeValue.includes('=>') ? attributeValue.split("=>").slice(1).join("=>").trim() : attributeValue.split("function").slice(1).join("function").trim()
|
|
162
177
|
|
|
178
|
+
// add ; after newlines
|
|
163
179
|
|
|
164
180
|
|
|
165
181
|
newvalue = newvalue.trim();
|
|
@@ -196,7 +212,7 @@ function Compiler(func, file) {
|
|
|
196
212
|
newvalue = newvalue.replace(/}\s*$/, '');
|
|
197
213
|
|
|
198
214
|
|
|
199
|
-
|
|
215
|
+
|
|
200
216
|
|
|
201
217
|
newvalue = newvalue.replaceAll(',,', ',')
|
|
202
218
|
let paramnames = params ? params.split(',').map((e) => e.trim()) : null
|
|
@@ -206,8 +222,11 @@ function Compiler(func, file) {
|
|
|
206
222
|
|
|
207
223
|
// add ; after newlines
|
|
208
224
|
newvalue = newvalue.replaceAll(/\n/g, ";\n")
|
|
225
|
+
// remove () from newvalue
|
|
226
|
+
newvalue = newvalue.replace(/\(\s*=>/gs, '=>').replace(/\function\s*\([^\)]*\)\s*\{/gs, '{')
|
|
227
|
+
newvalue = newvalue + `\n /**@id=${ref}**/ \n`
|
|
209
228
|
|
|
210
|
-
let bind = isJSXComponent
|
|
229
|
+
let bind = !isJSXComponent && `${attributeName}="\$\{this.bind(function(){${newvalue}}.bind(this), ${isJSXComponent}, "${ref}", "${paramnames ? paramnames.map((e, index) => {
|
|
211
230
|
if (e.length < 1) return ''
|
|
212
231
|
if (e.length > 0) {
|
|
213
232
|
index == 0 ? e : ',' + e
|
|
@@ -215,30 +234,10 @@ function Compiler(func, file) {
|
|
|
215
234
|
return e
|
|
216
235
|
}) : ''}" ${params ? params.split(',').map((e) => e.trim()).filter(Boolean).map((e) => `,${e}`).join('') : ''})}"`
|
|
217
236
|
|
|
218
|
-
string = string.replace(old, bind)
|
|
237
|
+
string = string.replace(old, bind)
|
|
219
238
|
}
|
|
220
239
|
}
|
|
221
240
|
|
|
222
|
-
/**
|
|
223
|
-
* @search - handle attributes for html elements
|
|
224
|
-
* @keywords - attributes, props, html attributes
|
|
225
|
-
*/
|
|
226
|
-
let match;
|
|
227
|
-
while ((match = elementRegex.exec(code)) !== null) {
|
|
228
|
-
let [, element, attributes] = match;
|
|
229
|
-
|
|
230
|
-
let attributesMatch;
|
|
231
|
-
let elementAttributes = {};
|
|
232
|
-
|
|
233
|
-
while ((attributesMatch = attributeRegex.exec(attributes)) !== null) {
|
|
234
|
-
let [, attributeName, attributeValue] = attributesMatch;
|
|
235
|
-
|
|
236
|
-
elementAttributes[attributeName] = attributeValue || null;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
attributesList.push({ element, attributes: elementAttributes });
|
|
240
|
-
}
|
|
241
|
-
|
|
242
241
|
return attributesList;
|
|
243
242
|
}
|
|
244
243
|
|
|
@@ -247,7 +246,7 @@ function Compiler(func, file) {
|
|
|
247
246
|
let returns = code.match(/return\s*\<>.*\<\/>|return\s*\(.*\)/gs);
|
|
248
247
|
|
|
249
248
|
return returns || [];
|
|
250
|
-
}
|
|
249
|
+
}
|
|
251
250
|
if (string.match(/return\s*\<>|return\s*\(.*\)/gs) && !string.match(/return\s*\<>.*\<\/>|return\s*\(.*\)/gs)
|
|
252
251
|
|| string.match(/return\s*\<[a-zA-Z0-9_-]+.*>/gs)
|
|
253
252
|
) {
|
|
@@ -280,17 +279,22 @@ function Compiler(func, file) {
|
|
|
280
279
|
}
|
|
281
280
|
let usesBraces = returnStatement.match(/return\s*\(/gs) ? true : false;
|
|
282
281
|
|
|
283
|
-
|
|
282
|
+
let attributes = extractAttributes(string);
|
|
284
283
|
contents = contents.trim().replace(/\]$/, "")
|
|
285
284
|
contents = contents.replace(/\)$/, "");
|
|
286
285
|
usesBraces ? !contents.includes('<>') ? contents = `<>${contents}</>` : null : null
|
|
287
286
|
updatedContents = contents;
|
|
288
|
-
|
|
287
|
+
|
|
289
288
|
|
|
290
289
|
let newAttributes = [];
|
|
291
290
|
let oldAttributes = [];
|
|
292
291
|
attributes.forEach((attribute) => {
|
|
293
292
|
const { element, attributes } = attribute;
|
|
293
|
+
// make sure it isnt a jsx component
|
|
294
|
+
let isJSXComponent = element.match(/[A-Z]/) ? true : false;
|
|
295
|
+
if (isJSXComponent) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
294
298
|
if (Object.keys(attributes).length === 0) return;
|
|
295
299
|
|
|
296
300
|
|
|
@@ -300,7 +304,9 @@ function Compiler(func, file) {
|
|
|
300
304
|
let value = attributes[key];
|
|
301
305
|
let oldvalue = value;
|
|
302
306
|
if (value && !value.new) {
|
|
307
|
+
|
|
303
308
|
if (value && value.includes("={")) {
|
|
309
|
+
|
|
304
310
|
value = value.replace("=", "");
|
|
305
311
|
value == "undefined" ? (value = '"') : (value = value);
|
|
306
312
|
|
|
@@ -354,9 +360,15 @@ function Compiler(func, file) {
|
|
|
354
360
|
switch (true) {
|
|
355
361
|
case line.includes("useState") && !line.includes("import"):
|
|
356
362
|
let varType = line.split("[")[0]
|
|
363
|
+
if (!line.split("=")[0].split(",")[1]) {
|
|
364
|
+
throw new Error('You forgot to value selector (useState) ' + ' at ' + `${file}:${string.split(line)[0].split('\n').length}`)
|
|
365
|
+
}
|
|
357
366
|
let key = line.split("=")[0].split(",")[0].trim().split('[')[1];
|
|
358
367
|
|
|
359
|
-
|
|
368
|
+
if (!line.split("=")[0].split(",")[1]) {
|
|
369
|
+
throw new Error('You forgot to add a setter (useState) ' + ' at ' + `${file}:${string.split(line)[0].split('\n').length}`)
|
|
370
|
+
}
|
|
371
|
+
let setKey = line.split("=")[0].split(",")[1].trim().replace("]", "");
|
|
360
372
|
key = key.replace("[", "").replace(",", "");
|
|
361
373
|
let valuestate = line.split("=")[1].split("useState(")[1];
|
|
362
374
|
|
|
@@ -425,86 +437,80 @@ function Compiler(func, file) {
|
|
|
425
437
|
let myChildrens = [];
|
|
426
438
|
|
|
427
439
|
let name = component.split("<")[1].split(">")[0].split(" ")[0].replace("/", "");
|
|
428
|
-
let componentAttributes = component.split("<")[1].split(">")[0].split(" ").join(" ").replace(name, "").trim();
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
let props = component.match(dynamicAttributesRegex)
|
|
436
|
-
|
|
437
|
-
let filteredProps = [];
|
|
438
|
-
let isWithinComponent = false;
|
|
439
|
-
let componentName = name
|
|
440
|
-
let currentProps = []
|
|
440
|
+
let componentAttributes = component.split("<")[1].split(">")[0].split(" ").join(" ").replace(name, "").trim();
|
|
441
|
+
let props = component.includes('/>') ? component.split(`<`)[1].split('/>')[0] : component.split(`<`)[1].split(`>`)[0]
|
|
442
|
+
props = props.replaceAll(/\s+/g, " ").trim()
|
|
443
|
+
props = props.replace(name, '').trim()
|
|
444
|
+
component = component.replace(componentAttributes, '')
|
|
445
|
+
// or spread attributes {...{}, ...{}}
|
|
446
|
+
const dynamicAttributesRegex = /([a-zA-Z0-9_-]+)\s*=\s*("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|\{(?:[^{}]|(?:\{(?:[^{}]|(?:\{(.*.*?)\})*)*\})*)*\}|(?:\([^)]*\)|()\s*=>\s*(?:\{.*.*\})?|\{.*\})|\[[^\]]*\])|\${\{.*\}}/gs;
|
|
441
447
|
|
|
448
|
+
const attributeObject = {};
|
|
449
|
+
let propstring = ''
|
|
442
450
|
let $_ternaryprops = []
|
|
451
|
+
let spreadRegex = /\$\{.*\}/gs;
|
|
452
|
+
let spreadMatch;
|
|
453
|
+
let hasSpread = false;
|
|
454
|
+
while ((spreadMatch = spreadRegex.exec(props)) !== null) {
|
|
455
|
+
let spread = spreadMatch[0].trim().replace(/\s+/g, " ");
|
|
456
|
+
if (!spread.includes('...')) {
|
|
457
|
+
continue
|
|
458
|
+
}
|
|
459
|
+
let old = spread;
|
|
460
|
+
spread = spread.trim().replace(/\s+/g, " ");
|
|
461
|
+
//${...( loaded ? { title: "Malik Whitten - Blog" } : { title: "Loading" } )} -> ...( loaded ? { title: "Malik Whitten - Blog" } : { title: "Loading" } )
|
|
443
462
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
if (prop === componentName) {
|
|
447
|
-
|
|
448
|
-
isWithinComponent = true;
|
|
449
|
-
filteredProps.push(prop);
|
|
450
|
-
} else if (isWithinComponent && prop.includes('=')) {
|
|
451
|
-
|
|
452
|
-
if (prop.startsWith('$=')) {
|
|
453
|
-
let old = prop
|
|
454
|
-
prop = prop.replace('$=', '$_ternary=')
|
|
455
|
-
|
|
456
|
-
// remove trailing }
|
|
457
|
-
prop = prop.replace(/}\s*$/, '')
|
|
458
|
-
component = component.replace(old, prop)
|
|
459
|
-
componentAttributes = componentAttributes.replace(old, prop)
|
|
460
|
-
|
|
461
|
-
$_ternaryprops.push(prop)
|
|
463
|
+
let spreadContent = spread.match(/\$\{.*\}/gs) ? spread.match(/\$\{.*.*\}/gs)[0] : null
|
|
464
|
+
spreadContent = spread.split('${')[1]
|
|
462
465
|
|
|
463
|
-
|
|
464
|
-
|
|
466
|
+
spreadContent = spread.replace(/\${/, '')
|
|
467
|
+
spreadContent = spreadContent.replaceAll(/\s+/g, " ").trim()
|
|
468
|
+
spreadContent = spreadContent.replace(')}', ')').replace('}}', '}')
|
|
465
469
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
prop = prop.replace('="', ':')
|
|
469
|
-
prop = prop.replace('${', '')
|
|
470
|
-
prop = prop.replace('}', '')
|
|
470
|
+
propstring += spreadContent + ','
|
|
471
|
+
hasSpread = true
|
|
471
472
|
|
|
472
|
-
|
|
473
|
-
if (prop.includes('="${{')) {
|
|
474
|
-
prop = prop.replace('${{', '{')
|
|
475
|
-
prop = prop.replace('}}', '}')
|
|
476
|
-
prop = prop.replace('="', ':')
|
|
477
|
-
prop = prop.replace('}"', '}')
|
|
478
|
-
}
|
|
473
|
+
}
|
|
479
474
|
|
|
480
|
-
|
|
481
|
-
else if (prop.startsWith('={')) {
|
|
482
|
-
prop = prop.replace('={', ':`${')
|
|
483
|
-
prop.replace('} ', '}`')
|
|
484
|
-
}
|
|
475
|
+
let match;
|
|
485
476
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
477
|
+
// props right now is just a string with all of them on one line and a space between each
|
|
478
|
+
while ((match = dynamicAttributesRegex.exec(props)) !== null) {
|
|
479
|
+
let str = match[0].trim().replace(/\s+/g, " ");
|
|
480
|
+
if (!str.includes('=')) {
|
|
481
|
+
continue
|
|
482
|
+
}
|
|
489
483
|
|
|
490
|
-
|
|
491
|
-
prop = prop.replace("}'", '}')
|
|
484
|
+
if (hasSpread) {
|
|
492
485
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
486
|
+
console.log('\x1b[33m', '🚨 Code confliction detected', '\x1b[0m')
|
|
487
|
+
let line = string.split(match[0])[0].split('\n').length
|
|
488
|
+
try {
|
|
489
|
+
throw new Error('You cannot use spread props and named props\n on the same component at ' + match[0] + ' at ' + `${file}:${line}`)
|
|
490
|
+
} catch (error) {
|
|
491
|
+
console.error(error)
|
|
492
|
+
process.exit(1)
|
|
496
493
|
}
|
|
494
|
+
}
|
|
497
495
|
|
|
498
|
-
|
|
499
|
-
|
|
496
|
+
str = str.replaceAll(/\s+/g, " ")
|
|
497
|
+
str = str.split('=')
|
|
498
|
+
let key = str[0].trim()
|
|
499
|
+
let value = str.slice(1).join('=').trim().match(/\{.*\}/gs) ? str.slice(1).join('=').trim().match(/\{.*\}/gs)[0] : str.slice(1).join('=').trim();
|
|
500
500
|
|
|
501
501
|
|
|
502
|
+
let isObject = value.startsWith('{{') && value.endsWith('}}')
|
|
503
|
+
if (isObject) {
|
|
504
|
+
value = value.split('{{')[1].split('}}')[0].trim()
|
|
505
|
+
value = `{${value}}`
|
|
506
|
+
propstring += `${key}:${value},`
|
|
507
|
+
} else {
|
|
508
|
+
// remove starting { and ending } using regex
|
|
509
|
+
value = value.replace(/^{/, '').replace(/}$/, '')
|
|
510
|
+
propstring += `${key}:${value},`
|
|
502
511
|
}
|
|
512
|
+
propstring = propstring.replaceAll(/\s+/g, " ").trim()
|
|
503
513
|
|
|
504
|
-
|
|
505
|
-
else {
|
|
506
|
-
isWithinComponent = false;
|
|
507
|
-
}
|
|
508
514
|
}
|
|
509
515
|
component = component.replaceAll(/\s+/g, " ");
|
|
510
516
|
|
|
@@ -513,10 +519,9 @@ function Compiler(func, file) {
|
|
|
513
519
|
component = component.replace(prop, '')
|
|
514
520
|
})
|
|
515
521
|
|
|
516
|
-
let children =
|
|
522
|
+
let children = new RegExp(`<${name}[^>]*>([^]*)<\/${name}>`, 'gs').exec(component)?.[1] || null;
|
|
517
523
|
|
|
518
524
|
|
|
519
|
-
props = filteredProps.join(',').replace(/\s+/g, " ").trim().replace(/,$/, '')
|
|
520
525
|
|
|
521
526
|
let savedname = name;
|
|
522
527
|
|
|
@@ -549,24 +554,15 @@ function Compiler(func, file) {
|
|
|
549
554
|
|
|
550
555
|
|
|
551
556
|
|
|
552
|
-
|
|
553
|
-
props = props.replaceAll(`,${savedname}`, '').replaceAll(savedname, '')
|
|
554
|
-
if (props.startsWith(',')) {
|
|
555
|
-
props = props.replace(',', '')
|
|
556
|
-
}
|
|
557
|
-
props = props.replaceAll("='", ":'")
|
|
558
|
-
.replaceAll('=`', ':`')
|
|
559
|
-
.replaceAll('="', ':"')
|
|
560
|
-
.replaceAll('={', ':')
|
|
557
|
+
propstring = propstring.replace(/,$/, '')
|
|
561
558
|
|
|
562
559
|
|
|
563
560
|
/**
|
|
564
561
|
* @memoize - memoize a component to be remembered on each render and replace the old jsx
|
|
565
562
|
*/
|
|
566
563
|
|
|
567
|
-
|
|
568
564
|
let replace = "";
|
|
569
|
-
replace = `\${this.memoize(this.createComponent(${savedname}, {${
|
|
565
|
+
replace = `\${this.memoize(this.createComponent(${savedname}, {${propstring}}, [\`${myChildrens.join('')}\`]))}`;
|
|
570
566
|
|
|
571
567
|
|
|
572
568
|
body = body.replace(before, replace);
|
|
@@ -582,48 +578,49 @@ function Compiler(func, file) {
|
|
|
582
578
|
let replaceMents = [];
|
|
583
579
|
|
|
584
580
|
|
|
585
|
-
|
|
586
|
-
let
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
581
|
+
if (imports) {
|
|
582
|
+
for (let match of imports) {
|
|
583
|
+
let path = match.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').trim()
|
|
584
|
+
switch (true) {
|
|
585
|
+
case path && !path.includes('./') && !path.includes('/vader.js') && !path.includes('/vaderjs/client') && !path.startsWith('src') && !path.startsWith('public') && !path.includes('http') && !path.includes('https'):
|
|
586
|
+
let componentFolder = fs.existsSync(process.cwd() + '/node_modules/' + path) ? process.cwd() + '/node_modules/' + path : process.cwd() + '/node_modules/' + path.split('/')[0]
|
|
587
|
+
componentFolder = componentFolder.split(process.cwd())[1]
|
|
588
|
+
if (!fs.existsSync(process.cwd() + componentFolder)) {
|
|
589
|
+
throw new Error('Could not find ' + path + ' at ' + match + ' in file ' + file)
|
|
590
|
+
}
|
|
594
591
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
592
|
+
if (!fs.existsSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'))) {
|
|
593
|
+
fs.mkdirSync(process.cwd() + '/dist/src/' + componentFolder.split('/').slice(2).join('/'), { recursive: true })
|
|
594
|
+
}
|
|
598
595
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
596
|
+
let baseFolder = componentFolder.split('node_modules')[1].split('/')[1]
|
|
597
|
+
let glp = globSync('**/**/**/**.{jsx,js}', {
|
|
598
|
+
cwd: process.cwd() + '/node_modules/' + baseFolder + '/',
|
|
599
|
+
absolute: true,
|
|
600
|
+
recursive: true
|
|
601
|
+
})
|
|
602
|
+
for (let file of glp) {
|
|
603
|
+
let text = fs.readFileSync(file, "utf8");
|
|
604
|
+
if (!file.endsWith('.js') && file.endsWith('.jsx')) {
|
|
605
|
+
text = Compiler(text, file);
|
|
609
606
|
|
|
607
|
+
}
|
|
608
|
+
let dest = file.split('node_modules')[1]
|
|
609
|
+
dest = dest.split(baseFolder)[1]
|
|
610
|
+
writer(process.cwd() + '/dist/src/' + baseFolder + dest, text)
|
|
611
|
+
let importname = match.split('import')[1].split('from')[0].trim()
|
|
612
|
+
let oldImportstring = match.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').trim()
|
|
613
|
+
let newImport = `/src/${baseFolder + dest}`
|
|
614
|
+
newImport = newImport.replaceAll('.jsx', '.js').replaceAll('\\', '/')
|
|
615
|
+
replaceMents.push({ match: oldImportstring, replace: newImport })
|
|
616
|
+
console.log(`📦 imported Node Package ${baseFolder} `)
|
|
610
617
|
}
|
|
611
|
-
let dest = file.split('node_modules')[1]
|
|
612
|
-
dest = dest.split(baseFolder)[1]
|
|
613
|
-
// write to dist
|
|
614
|
-
writer(process.cwd() + '/dist/src/' + baseFolder + dest, text)
|
|
615
|
-
let importname = match.split('import')[1].split('from')[0].trim()
|
|
616
|
-
let oldImportstring = match.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').trim()
|
|
617
|
-
let newImport = `/src/${baseFolder + dest}`
|
|
618
|
-
newImport = newImport.replaceAll('.jsx', '.js').replaceAll('\\', '/')
|
|
619
|
-
replaceMents.push({ match: oldImportstring, replace: newImport })
|
|
620
|
-
console.log(`📦 imported Node Package ${baseFolder} `)
|
|
621
|
-
}
|
|
622
618
|
|
|
623
619
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
620
|
+
break;
|
|
621
|
+
default:
|
|
622
|
+
break;
|
|
623
|
+
}
|
|
627
624
|
}
|
|
628
625
|
}
|
|
629
626
|
|
|
@@ -644,7 +641,7 @@ function Compiler(func, file) {
|
|
|
644
641
|
string = string.replaceAll(/\$\{\/\*.*\*\/\}/gs, "");
|
|
645
642
|
string = string.replaceAll("<>", "`").replaceAll("</>", "`");
|
|
646
643
|
string = string.replaceAll(".jsx", ".js");
|
|
647
|
-
|
|
644
|
+
|
|
648
645
|
|
|
649
646
|
string = string
|
|
650
647
|
.replaceAll("className", "class")
|
|
@@ -810,236 +807,165 @@ function Compiler(func, file) {
|
|
|
810
807
|
|
|
811
808
|
globalThis.isBuilding = false
|
|
812
809
|
globalThis.isWriting = null
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
absolute: true,
|
|
817
|
-
recursive: true
|
|
818
|
-
});
|
|
810
|
+
|
|
811
|
+
let hasRendered = []
|
|
812
|
+
|
|
819
813
|
async function Build() {
|
|
814
|
+
const glb = await glob("**/**/**/**.{jsx,js}", {
|
|
815
|
+
ignore: ["node_modules/**/*", "dist/**/*"],
|
|
816
|
+
cwd: process.cwd() + '/pages/',
|
|
817
|
+
absolute: true,
|
|
818
|
+
recursive: true
|
|
819
|
+
});
|
|
820
|
+
|
|
820
821
|
globalThis.isBuilding = true
|
|
821
|
-
console.log('
|
|
822
|
+
console.log(globalThis.isProduction ? 'Creating Optimized Production Build\n' : '')
|
|
823
|
+
let str = `Page \t\t\t\t Size\n`
|
|
824
|
+
globalThis.isProduction ? console.log('\x1b[32m%s\x1b[0m', str) : null
|
|
822
825
|
let reader = async (file) => {
|
|
823
826
|
let text = await fs.readFileSync(file, "utf8");
|
|
824
827
|
return text;
|
|
825
828
|
};
|
|
826
829
|
|
|
827
|
-
|
|
830
|
+
|
|
831
|
+
|
|
828
832
|
function ssg(routes = []) {
|
|
829
833
|
globalThis.isBuilding = true
|
|
830
|
-
|
|
834
|
+
let server = http.createServer((req, res) => {
|
|
835
|
+
let route = routes.find((e) => e.url === req.url)
|
|
836
|
+
if (route) {
|
|
837
|
+
let document = globalThis.routeDocuments.find((e) => e.url === req.url)
|
|
838
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
839
|
+
res.end(document.document);
|
|
840
|
+
} else {
|
|
841
|
+
const filePath = process.cwd() + '/dist/' + req.url
|
|
842
|
+
|
|
843
|
+
fs.readFile(filePath, (err, data) => {
|
|
844
|
+
if (err) {
|
|
845
|
+
res.writeHead(404, { 'Content-Type': filePath.includes('js') ? 'text/javascript' : 'text/html' });
|
|
846
|
+
res.end('File not found');
|
|
847
|
+
} else {
|
|
848
|
+
res.writeHead(200, { 'Content-Type': filePath.includes('js') ? 'text/javascript' : 'text/html' });
|
|
849
|
+
res.end(data);
|
|
850
|
+
}
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
let port = 12000
|
|
856
|
+
server.on('error', (err) => {
|
|
857
|
+
if (err.code === 'EADDRINUSE') {
|
|
858
|
+
setTimeout(() => {
|
|
859
|
+
server.close();
|
|
860
|
+
server.listen(++port);
|
|
861
|
+
}, 1000);
|
|
862
|
+
}
|
|
863
|
+
})
|
|
864
|
+
|
|
865
|
+
const browser = puppeteer.launch({
|
|
866
|
+
headless: "new", args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
|
867
|
+
warning: false,
|
|
868
|
+
})
|
|
869
|
+
server.listen(port);
|
|
870
|
+
|
|
831
871
|
routes.forEach(async (route) => {
|
|
832
872
|
if (route.url.includes(':')) {
|
|
833
|
-
console.log('Route ' + route.url + ' is a dynamic route and will not be generated')
|
|
834
873
|
return
|
|
835
874
|
}
|
|
836
|
-
|
|
837
|
-
if (e.url.includes(':')) {
|
|
838
|
-
let url = e.url.split('/:')[0]
|
|
839
|
-
if (url && route.url === url) {
|
|
840
|
-
return e
|
|
841
|
-
} else {
|
|
842
|
-
return null
|
|
843
|
-
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
return null
|
|
847
|
-
}).filter(Boolean)
|
|
848
|
-
let document = `
|
|
849
|
-
<!DOCTYPE html>
|
|
850
|
-
<html lang="en">
|
|
851
|
-
<head>
|
|
852
|
-
<script>
|
|
853
|
-
window.routes = JSON.parse('${JSON.stringify(routes)}')
|
|
854
|
-
</script>
|
|
855
|
-
<script id="isServer">
|
|
856
|
-
window.isServer = true
|
|
857
|
-
</script>
|
|
858
|
-
<meta charset="UTF-8">
|
|
859
|
-
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
860
|
-
<script type="module" id="meta">
|
|
861
|
-
window.history.pushState({}, '', '${route.url}')
|
|
862
|
-
window.module = await import('/${route.fileName.replace('.jsx', '.js')}')
|
|
863
|
-
let metadata = await module.$metadata
|
|
864
|
-
if(metadata && metadata.title){
|
|
865
|
-
document.head.innerHTML += '<title>' + metadata.title + '</title>'
|
|
866
|
-
}
|
|
867
|
-
if(metadata && metadata.description){
|
|
868
|
-
document.head.innerHTML += '<meta name="description" content="' + metadata.description + '">'
|
|
869
|
-
}
|
|
870
|
-
if(metadata && metadata.keywords){
|
|
871
|
-
document.head.innerHTML += '<meta name="keywords" content="' + metadata.keywords + '">'
|
|
872
|
-
}
|
|
873
|
-
if(metadata && metadata.author){
|
|
874
|
-
document.head.innerHTML += '<meta name="author" content="' + metadata.author + '">'
|
|
875
|
-
}
|
|
876
|
-
if(metadata && metadata.image){
|
|
877
|
-
let image = metadata.image.file
|
|
878
|
-
let type = metadata.image.type
|
|
879
|
-
|
|
880
|
-
document.head.innerHTML += '<meta property="og:image" content="' + image + '">'
|
|
881
|
-
document.head.innerHTML += '<meta property="og:image:type" content="' + type + '">'
|
|
882
|
-
}
|
|
883
|
-
if(metadata && metadata.url){
|
|
884
|
-
document.head.innerHTML += '<meta property="og:url" content="' + metadata.url + '">'
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
if(metadata && metadata.robot){
|
|
888
|
-
document.head.innerHTML += '<meta name="robots" content="' + metadata.robot + '">'
|
|
889
|
-
}
|
|
890
|
-
if(metadata && metadata.manifest){
|
|
891
|
-
document.head.innerHTML += '<link rel="manifest" href="' + metadata.manifest + '">'
|
|
892
|
-
}
|
|
893
|
-
if(metadata && metadata.tags){
|
|
894
|
-
metadata.tags.forEach(tag => {
|
|
895
|
-
document.head.innerHTML += tag
|
|
896
|
-
})
|
|
897
|
-
}
|
|
875
|
+
globalThis.listen = true;
|
|
898
876
|
|
|
899
|
-
|
|
900
|
-
metadata.styles.forEach(style => {
|
|
901
|
-
style = style.replaceAll('./', '/')
|
|
902
|
-
style = style.replaceAll('../', '/')
|
|
903
|
-
style = style.replace("'", '')
|
|
904
|
-
document.head.innerHTML += '<link rel="stylesheet" href="' + style + '">'
|
|
905
|
-
})
|
|
906
|
-
}
|
|
907
|
-
if(metadata && metadata.icon){
|
|
908
|
-
document.head.innerHTML += '<link rel="icon" href="' + metadata.icon + '">'
|
|
909
|
-
}
|
|
910
|
-
</script>
|
|
911
|
-
<script type="module" id="router">
|
|
912
|
-
import VaderRouter from '/router.js'
|
|
913
|
-
const router = new VaderRouter('${route.url}', 3000)
|
|
914
|
-
router.get('${route.url}', async (req, res) => {
|
|
915
|
-
let module = await import('/${route.fileName.replace('.jsx', '.js')}')
|
|
916
|
-
if(Object.keys(module).includes('$prerender') && !module.$prerender){
|
|
917
|
-
document.head.setAttribute('prerender', 'false')
|
|
918
|
-
}
|
|
919
|
-
res.render(module, req, res, module.$metadata)
|
|
920
|
-
})
|
|
921
|
-
${equalparamroute.length > 0 ? equalparamroute.map((e) => {
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
return `router.get('${e.url}', async (req, res) => {
|
|
926
|
-
let module = await import('/${e.fileName.replace('.jsx', '.js')}')
|
|
927
|
-
res.render(module, req, res, module.$metadata)
|
|
928
|
-
})\n`
|
|
929
|
-
}) : ''}
|
|
930
|
-
router.listen(3000)
|
|
931
|
-
|
|
932
|
-
</script>
|
|
933
|
-
</head>
|
|
934
|
-
<body>
|
|
935
|
-
<div id="root"></div>
|
|
936
|
-
</body>
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
</html>
|
|
940
|
-
`;
|
|
877
|
+
try {
|
|
941
878
|
|
|
942
|
-
|
|
943
|
-
|
|
879
|
+
route.url = route.url.replaceAll(/\/:[a-zA-Z0-9_-]+/gs, '')
|
|
880
|
+
let page = (await browser).newPage()
|
|
881
|
+
page.then(async (page) => {
|
|
882
|
+
page.on('error', (err) => {
|
|
883
|
+
console.error('JS ERROR:', JSON.parse(err));
|
|
884
|
+
});
|
|
885
|
+
try {
|
|
886
|
+
page.on('pageerror', async err => {
|
|
887
|
+
let errorObj = JSON.parse(await page.evaluate(() => document.documentElement.getAttribute('error')) || '{}')
|
|
888
|
+
console.log('\x1b[31m%s\x1b[0m', 'Compiler Error:', errorObj)
|
|
889
|
+
|
|
890
|
+
console.log('\x1b[31m%s\x1b[0m', 'Error:', err)
|
|
891
|
+
});
|
|
892
|
+
} catch (error) {
|
|
893
|
+
page.close()
|
|
894
|
+
}
|
|
895
|
+
page.on('crash', () => {
|
|
896
|
+
console.error(`Render process crashed for ${route.url}`)
|
|
897
|
+
});
|
|
944
898
|
|
|
945
|
-
|
|
899
|
+
await page.goto(`http://localhost:${port}${route.url}`, { waitUntil: 'networkidle2' });
|
|
946
900
|
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
fs.readFile(filePath, (err, data) => {
|
|
955
|
-
if (err) {
|
|
956
|
-
res.writeHead(404, { 'Content-Type': filePath.includes('js') ? 'text/javascript' : 'text/html' });
|
|
957
|
-
res.end('File not found');
|
|
958
|
-
} else {
|
|
959
|
-
res.writeHead(200, { 'Content-Type': filePath.includes('js') ? 'text/javascript' : 'text/html' });
|
|
960
|
-
res.end(data);
|
|
901
|
+
page.evaluate(() => {
|
|
902
|
+
document.querySelector('#meta').remove()
|
|
903
|
+
document.querySelector('#isServer').innerHTML = 'window.isServer = false'
|
|
904
|
+
if (document.head.getAttribute('prerender') === 'false') {
|
|
905
|
+
document.querySelector('#root').innerHTML = ''
|
|
906
|
+
console.log(`Disabled prerendering for ${window.location.pathname}`)
|
|
961
907
|
}
|
|
962
|
-
})
|
|
963
|
-
|
|
964
|
-
});
|
|
908
|
+
})
|
|
909
|
+
let html = await page.content();
|
|
965
910
|
|
|
966
|
-
|
|
967
|
-
server.on('error', (err) => {
|
|
968
|
-
if (err.code === 'EADDRINUSE') {
|
|
969
|
-
console.log(`Port ${port} is in use, trying another port...`);
|
|
970
|
-
setTimeout(() => {
|
|
971
|
-
server.close();
|
|
972
|
-
server.listen(++port);
|
|
973
|
-
}, 1000);
|
|
974
|
-
}
|
|
975
|
-
})
|
|
911
|
+
html = await prettier.format(html, { parser: "html" })
|
|
976
912
|
|
|
977
|
-
|
|
913
|
+
writer(process.cwd() + '/dist/' + (route.url === '/' ? 'index.html' : `${route.url}/` + 'index.html'), html)
|
|
978
914
|
|
|
979
|
-
|
|
980
|
-
headless: "new", args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
|
981
|
-
warning: false,
|
|
982
|
-
})
|
|
983
|
-
|
|
984
|
-
const browserPID = browser.process().pid
|
|
985
|
-
try {
|
|
915
|
+
console.log(`\x1b[32m%s\x1b[0m`, `Prerendered ${route.url}...`)
|
|
986
916
|
|
|
987
|
-
|
|
988
|
-
let page = await browser.newPage();
|
|
989
|
-
await page.goto(`http://localhost:${port}/`, { waitUntil: 'networkidle2' });
|
|
990
|
-
await page.on('console', msg => console.log('PAGE LOG:', msg.text()));
|
|
991
|
-
await page.on('error', err => console.log('PAGE LOG:', err));
|
|
992
|
-
await page.on('pageerror', err => console.log('PAGE LOG:', err));
|
|
993
|
-
await page.evaluate(() => {
|
|
994
|
-
window.onerror = function (msg, url, lineNo, columnNo, error) {
|
|
995
|
-
console.log(msg, url, lineNo, columnNo, error)
|
|
996
|
-
}
|
|
917
|
+
hasRendered.push(route.url)
|
|
997
918
|
})
|
|
998
|
-
await page.waitForSelector('#root', { timeout: 10000 })
|
|
999
|
-
await page.evaluate(() => {
|
|
1000
|
-
document.getElementById('meta').remove()
|
|
1001
|
-
document.querySelector('#isServer').innerHTML = 'window.isServer = false'
|
|
1002
|
-
if (document.head.getAttribute('prerender') === 'false') {
|
|
1003
|
-
document.querySelector('#root').innerHTML = ''
|
|
1004
|
-
console.log(`Disabled prerendering for ${window.location.pathname}`)
|
|
1005
|
-
}
|
|
1006
|
-
})
|
|
1007
|
-
const html = await page.content();
|
|
1008
919
|
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
await browser.close();
|
|
1012
|
-
server.close()
|
|
920
|
+
|
|
921
|
+
|
|
1013
922
|
|
|
1014
923
|
} catch (error) {
|
|
1015
|
-
|
|
1016
|
-
|
|
924
|
+
console.log('\x1b[31m%s\x1b[0m', 'Error:', error)
|
|
925
|
+
|
|
1017
926
|
}
|
|
1018
927
|
finally {
|
|
1019
|
-
await browser.close();
|
|
1020
|
-
server.close()
|
|
1021
|
-
}
|
|
1022
|
-
try {
|
|
1023
|
-
process.kill(browserPID)
|
|
1024
|
-
} catch (error) {
|
|
1025
928
|
}
|
|
929
|
+
})
|
|
930
|
+
|
|
1026
931
|
|
|
1027
932
|
|
|
1028
|
-
})
|
|
1029
933
|
|
|
1030
|
-
|
|
934
|
+
|
|
935
|
+
function kill() {
|
|
936
|
+
console.log(`\x1b[32m%s\x1b[0m`, `\nPrerendered ${routes.length} pages...\n`)
|
|
937
|
+
server.close()
|
|
938
|
+
browser.then((browser) => {
|
|
939
|
+
browser.close()
|
|
940
|
+
})
|
|
941
|
+
hasRendered = []
|
|
1031
942
|
globalThis.isBuilding = false
|
|
1032
|
-
clearTimeout(timeout)
|
|
1033
|
-
}, 1000)
|
|
1034
|
-
console.log(`Generated ${routes.length} html files for ${routes.length} routes`)
|
|
1035
|
-
}
|
|
1036
943
|
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
if (hasRendered.length === routes.length) {
|
|
947
|
+
kill()
|
|
948
|
+
} else {
|
|
949
|
+
console.log(`\x1b[32m%s\x1b[0m`, `Prerendering ${routes.length} pages...\n`)
|
|
950
|
+
let interval = setInterval(() => {
|
|
951
|
+
if (hasRendered.length === routes.length) {
|
|
952
|
+
kill()
|
|
953
|
+
clearInterval(interval)
|
|
954
|
+
}
|
|
955
|
+
}, 1000);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
1037
958
|
globalThis.routes = []
|
|
959
|
+
globalThis.paramRoutes = []
|
|
1038
960
|
|
|
1039
961
|
for await (let file of glb) {
|
|
1040
962
|
// Normalize file paths
|
|
1041
963
|
let origin = file.replace(/\\/g, '/');
|
|
1042
964
|
let fileName = origin.split('/pages/')[1].split('.jsx')[0].replace('.jsx', '') + '.jsx';
|
|
965
|
+
if (file.endsWith('.js')) {
|
|
966
|
+
console.warn('\x1b[33m%s\x1b[0m', `Warning: js files in the pages directory are not supported. Skipping ${file}`)
|
|
967
|
+
continue
|
|
968
|
+
}
|
|
1043
969
|
let isBasePath = fileName === 'index.jsx';
|
|
1044
970
|
let isParamRoute = fileName.includes('[') && fileName.includes(']') ? true : false
|
|
1045
971
|
|
|
@@ -1063,17 +989,15 @@ async function Build() {
|
|
|
1063
989
|
|
|
1064
990
|
|
|
1065
991
|
let data = await fs.readFileSync(origin, "utf8");
|
|
1066
|
-
console.log(`Compiling ${fileName}...`)
|
|
1067
|
-
data = Compiler(data, origin);
|
|
1068
|
-
|
|
1069
992
|
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
}
|
|
993
|
+
// gen sourcemap if not production
|
|
994
|
+
let size = fs.statSync(origin).size;
|
|
995
|
+
if (!globalThis.isProduction) {
|
|
996
|
+
let { sourceMap } = sourceMapGen({ origin: origin, fileName: fileName }, await Compiler(data, origin))
|
|
997
|
+
data = data + `\n//# sourceMappingURL=/src/maps/${fileName.replace('.jsx', '.js.map')}\n //#sourceURL=${origin}`
|
|
998
|
+
await writer(process.cwd() + "/dist/src/maps/" + fileName.replace('.jsx', '.js.map'), JSON.stringify(sourceMap, null, 2))
|
|
999
|
+
}
|
|
1000
|
+
await writer(process.cwd() + "/dist/" + fileName.replace('.jsx', '.js'), await Compiler(data, origin))
|
|
1077
1001
|
|
|
1078
1002
|
// configure routing for each page
|
|
1079
1003
|
|
|
@@ -1135,13 +1059,148 @@ async function Build() {
|
|
|
1135
1059
|
}
|
|
1136
1060
|
|
|
1137
1061
|
|
|
1138
|
-
|
|
1062
|
+
if (obj.url.includes(':') && !paramRoutes.includes(obj.url)) {
|
|
1063
|
+
globalThis.paramRoutes.push({ fileName: fileName, url: obj.url, html: '/' + (isBasePath ? 'index.html' : `${obj.url}/` + 'index.html') })
|
|
1064
|
+
} else {
|
|
1139
1065
|
|
|
1066
|
+
globalThis.routes.push({ fileName: fileName, url: obj.url, html: '/' + (isBasePath ? 'index.html' : `${obj.url}/` + 'index.html') })
|
|
1067
|
+
}
|
|
1140
1068
|
|
|
1069
|
+
// check if route has a index.html file
|
|
1141
1070
|
|
|
1071
|
+
if (!fs.existsSync(process.cwd() + '/dist/' + (isBasePath ? 'index.html' : `${obj.url}/` + 'index.html'))
|
|
1072
|
+
&& !obj.url.includes(':') && !globalThis.isProduction
|
|
1073
|
+
) {
|
|
1074
|
+
let document = `<!DOCTYPE html>
|
|
1075
|
+
<html lang="en">
|
|
1076
|
+
<head>
|
|
1077
|
+
<meta charset="UTF-8">
|
|
1078
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1079
|
+
<title>${obj.url}</title>
|
|
1080
|
+
<script>
|
|
1081
|
+
window.routes = JSON.parse('${JSON.stringify(globalThis.routes)}')
|
|
1082
|
+
</script>
|
|
1083
|
+
<script type="module">
|
|
1084
|
+
import VaderRouter from '/router.js'
|
|
1085
|
+
const router = new VaderRouter('${obj.url}')
|
|
1086
|
+
router.get('${obj.url}', async (req, res) => {
|
|
1087
|
+
let module = await import('${obj.url === '/' ? 'index.js' : obj.url}/index.js')
|
|
1088
|
+
if(Object.keys(module).includes('$prerender') && !module.$prerender){
|
|
1089
|
+
document.head.setAttribute('prerender', 'false')
|
|
1090
|
+
}
|
|
1091
|
+
res.render(module, req, res, module.$metadata)
|
|
1092
|
+
})
|
|
1093
|
+
router.listen(3000)
|
|
1094
|
+
</script>
|
|
1095
|
+
</head>
|
|
1096
|
+
<body>
|
|
1097
|
+
<div id="root"></div>
|
|
1098
|
+
</body>
|
|
1099
|
+
</html>`
|
|
1100
|
+
writer(process.cwd() + '/dist/' + (isBasePath ? 'index.html' : `${obj.url}/` + 'index.html'), document)
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
let stats = {
|
|
1104
|
+
route: obj.url.padEnd(30),
|
|
1105
|
+
size: Math.round(size / 1000) + 'kb',
|
|
1106
|
+
letParentFolder: obj.url.split('/').slice(0, -1).join('/'),
|
|
1107
|
+
isChildRoute: obj.url.split('/').slice(0, -1).join('/').includes(':') ? true : false,
|
|
1108
|
+
parentRoute: obj.url.split('/').slice(0, -1).join('/').split(':')[0],
|
|
1109
|
+
|
|
1110
|
+
}
|
|
1111
|
+
stats.isChildRoute ? stats.route = `? ${obj.url}` : null
|
|
1112
|
+
let string = `${isBasePath ? '+' : '+'} ${stats.route.padEnd(30)} ${stats.size}`
|
|
1113
|
+
|
|
1114
|
+
globalThis.isProduction ? console.log(string) : null
|
|
1142
1115
|
}
|
|
1143
1116
|
|
|
1144
|
-
|
|
1117
|
+
globalThis.routeDocuments = []
|
|
1118
|
+
globalThis.routes.map((route) => {
|
|
1119
|
+
let equalparamroute = globalThis.paramRoutes.map((e) => {
|
|
1120
|
+
console
|
|
1121
|
+
if (e.url.includes(':')) {
|
|
1122
|
+
let url = e.url.split('/:')[0]
|
|
1123
|
+
if (url && route.url === url) {
|
|
1124
|
+
return e
|
|
1125
|
+
} else {
|
|
1126
|
+
return null
|
|
1127
|
+
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
return null
|
|
1131
|
+
}).filter(Boolean)
|
|
1132
|
+
let document = `
|
|
1133
|
+
<!DOCTYPE html>
|
|
1134
|
+
<html lang="en">
|
|
1135
|
+
<head>
|
|
1136
|
+
<script>
|
|
1137
|
+
window.routes = JSON.parse('${JSON.stringify(globalThis.routes)}')
|
|
1138
|
+
</script>
|
|
1139
|
+
<script type="module" id="meta">
|
|
1140
|
+
window.history.pushState({}, '', '${route.url}')
|
|
1141
|
+
|
|
1142
|
+
</script>
|
|
1143
|
+
<script id="isServer">
|
|
1144
|
+
window.isServer = true
|
|
1145
|
+
</script>
|
|
1146
|
+
<meta charset="UTF-8">
|
|
1147
|
+
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
1148
|
+
|
|
1149
|
+
<script type="module" id="router">
|
|
1150
|
+
import VaderRouter from '/router.js'
|
|
1151
|
+
const router = new VaderRouter('${route.url}')
|
|
1152
|
+
router.get('${route.url}', async (req, res) => {
|
|
1153
|
+
try{
|
|
1154
|
+
let module = await import('/${route.fileName.replace('.jsx', '.js')}')
|
|
1155
|
+
if(Object.keys(module).includes('$prerender') && !module.$prerender){
|
|
1156
|
+
document.head.setAttribute('prerender', 'false')
|
|
1157
|
+
}
|
|
1158
|
+
res.render(module, req, res, module.$metadata)
|
|
1159
|
+
}
|
|
1160
|
+
catch(error){
|
|
1161
|
+
let errorMessage = {
|
|
1162
|
+
message: error.message,
|
|
1163
|
+
name: error.name,
|
|
1164
|
+
stack: error.stack,
|
|
1165
|
+
path: window.location.pathname
|
|
1166
|
+
};
|
|
1167
|
+
|
|
1168
|
+
|
|
1169
|
+
document.documentElement.setAttribute('error', JSON.stringify(errorMessage));
|
|
1170
|
+
throw new Error(error)
|
|
1171
|
+
}
|
|
1172
|
+
})
|
|
1173
|
+
${equalparamroute.length > 0 ? equalparamroute.map((e) => {
|
|
1174
|
+
|
|
1175
|
+
|
|
1176
|
+
|
|
1177
|
+
return `router.get('${e.url}', async (req, res) => {
|
|
1178
|
+
let module = await import('/${e.fileName.replace('.jsx', '.js')}')
|
|
1179
|
+
res.render(module, req, res, module.$metadata)
|
|
1180
|
+
})\n`
|
|
1181
|
+
}) : ''}
|
|
1182
|
+
router.listen(3000)
|
|
1183
|
+
|
|
1184
|
+
</script>
|
|
1185
|
+
</head>
|
|
1186
|
+
<body>
|
|
1187
|
+
<div id="root"></div>
|
|
1188
|
+
</body>
|
|
1189
|
+
|
|
1190
|
+
|
|
1191
|
+
</html>
|
|
1192
|
+
`;
|
|
1193
|
+
globalThis.routeDocuments.push({ url: route.url, document: document })
|
|
1194
|
+
})
|
|
1195
|
+
|
|
1196
|
+
if (globalThis.devMode && !globalThis.oneAndDone) {
|
|
1197
|
+
ssg(globalThis.routes)
|
|
1198
|
+
globalThis.oneAndDone = true
|
|
1199
|
+
console.log(`In Development Mode, Prerendering ${globalThis.routes.length} pages... Once`)
|
|
1200
|
+
}
|
|
1201
|
+
else if (globalThis.isProduction) {
|
|
1202
|
+
ssg(globalThis.routes)
|
|
1203
|
+
}
|
|
1145
1204
|
|
|
1146
1205
|
|
|
1147
1206
|
const scannedSourceFiles = await glob("**/**.{jsx,js,json}", {
|
|
@@ -1169,23 +1228,25 @@ async function Build() {
|
|
|
1169
1228
|
scannedSourceFiles.forEach(async (file) => {
|
|
1170
1229
|
file = file.replace(/\\/g, '/');
|
|
1171
1230
|
let name = file.split('/src/')[1]
|
|
1172
|
-
//parse jsx
|
|
1173
1231
|
|
|
1174
1232
|
let data = await reader(process.cwd() + "/src/" + name)
|
|
1175
1233
|
if (name.includes('.jsx')) {
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
}
|
|
1234
|
+
let origin = process.cwd() + "/src/" + name
|
|
1235
|
+
if (!globalThis.isProduction) {
|
|
1236
|
+
let { sourceMap } = sourceMapGen({ origin: origin, fileName: name }, await Compiler(data, origin))
|
|
1237
|
+
data = data + `\n//# sourceMappingURL=/src/maps/${name.replace('.jsx', '.js.map')}\n //#sourceURL=${origin}`
|
|
1238
|
+
await writer(process.cwd() + "/dist/src/maps/" + name.replace('.jsx', '.js.map'), JSON.stringify(sourceMap, null, 2))
|
|
1239
|
+
}
|
|
1240
|
+
await writer(process.cwd() + "/dist/src/" + name.split('.jsx').join('.js'), await Compiler(data, origin))
|
|
1182
1241
|
return
|
|
1183
1242
|
}
|
|
1184
|
-
|
|
1243
|
+
if (!name.includes('.map')) {
|
|
1244
|
+
bundleSize += fs.statSync(process.cwd() + "/src/" + name).size;
|
|
1245
|
+
}
|
|
1185
1246
|
await writer(process.cwd() + "/dist/src/" + name, data);
|
|
1186
1247
|
})
|
|
1187
1248
|
|
|
1188
|
-
const scannedPublicFiles = await glob("
|
|
1249
|
+
const scannedPublicFiles = await glob("**/**/**.{css,js,html,mjs,cjs,png,jpg,jpeg,gif,svg,mp4,webm,ogg}", {
|
|
1189
1250
|
ignore: ["node_modules/**/*", "dist/**/*"],
|
|
1190
1251
|
cwd: process.cwd() + '/public/',
|
|
1191
1252
|
absolute: true,
|
|
@@ -1193,7 +1254,7 @@ async function Build() {
|
|
|
1193
1254
|
scannedPublicFiles.forEach(async (file) => {
|
|
1194
1255
|
file = file.replace(/\\/g, '/');
|
|
1195
1256
|
file = file.split('/public/')[1]
|
|
1196
|
-
let data =
|
|
1257
|
+
let data = fs.readFileSync(process.cwd() + "/public/" + file);
|
|
1197
1258
|
bundleSize += fs.statSync(process.cwd() + "/public/" + file).size;
|
|
1198
1259
|
await writer(process.cwd() + "/dist/public/" + file, data);
|
|
1199
1260
|
})
|
|
@@ -1223,26 +1284,78 @@ async function Build() {
|
|
|
1223
1284
|
await writer(process.cwd() + "/dist/" + file, data);
|
|
1224
1285
|
});
|
|
1225
1286
|
|
|
1287
|
+
|
|
1226
1288
|
}
|
|
1227
1289
|
|
|
1228
1290
|
globalThis.isBuilding = false
|
|
1229
|
-
console.log(`📦 Build completed: Build Size -> ${Math.round(bundleSize / 1000)}kb`)
|
|
1230
1291
|
|
|
1292
|
+
globalThis.isProduction ? console.log(`Total Bundle Size: ${Math.round(bundleSize / 1000)}kb`) : null
|
|
1231
1293
|
bundleSize = 0;
|
|
1294
|
+
if (!globalThis.isBuilding && !globalThis.isProduction) {
|
|
1295
|
+
let folders = fs.readdirSync(process.cwd() + '/dist/', { withFileTypes: true })
|
|
1296
|
+
let mapfolders = fs.readdirSync(process.cwd() + '/dist/src/maps/', { withFileTypes: true }) || []
|
|
1297
|
+
console.log(`Cleaning up dist folder...`)
|
|
1298
|
+
folders.forEach((folder) => {
|
|
1299
|
+
// exclude files
|
|
1300
|
+
if (folder.name.includes('src') || folder.name.includes('public') || folder.name.includes('pages')
|
|
1301
|
+
|| !folder.isDirectory()
|
|
1302
|
+
) {
|
|
1303
|
+
return
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
let existsInPages = fs.existsSync(process.cwd() + '/pages/' + folder.name)
|
|
1232
1307
|
|
|
1308
|
+
if (existsInPages) {
|
|
1309
|
+
return
|
|
1310
|
+
}
|
|
1311
|
+
fs.rm(process.cwd() + '/dist/' + folder.name, { recursive: true }, (err) => {
|
|
1312
|
+
if (err) {
|
|
1313
|
+
throw err
|
|
1314
|
+
}
|
|
1315
|
+
})
|
|
1316
|
+
})
|
|
1317
|
+
mapfolders.forEach((folder) => {
|
|
1318
|
+
|
|
1319
|
+
let existsInPages = fs.existsSync(process.cwd() + '/pages/' + folder.name)
|
|
1320
|
+
let existsInSrc = fs.existsSync(process.cwd() + '/src/' + folder.name)
|
|
1321
|
+
if (existsInPages || existsInSrc) {
|
|
1322
|
+
return
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
let name = folder.name.includes('.js.map') ? folder.name.split('.js.map').join('.js') : folder.name
|
|
1326
|
+
if (fs.existsSync(process.cwd() + '/dist/src/maps/' + name)) {
|
|
1327
|
+
fs.rm(process.cwd() + '/dist/src/maps/' + name, { recursive: true }, (err) => {
|
|
1328
|
+
if (err) {
|
|
1329
|
+
throw err
|
|
1330
|
+
}
|
|
1331
|
+
})
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
|
|
1335
|
+
|
|
1336
|
+
})
|
|
1337
|
+
}
|
|
1233
1338
|
return true
|
|
1234
1339
|
}
|
|
1235
|
-
const s = () => {
|
|
1340
|
+
const s = (port) => {
|
|
1236
1341
|
|
|
1237
1342
|
const server = http.createServer((req, res) => {
|
|
1238
1343
|
|
|
1239
|
-
const validExtensions = ['.js', '.css', '.mjs', '.cjs', '.html', '.json', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.mp4', '.webm', '.ogg']
|
|
1344
|
+
const validExtensions = ['.js', '.css', '.mjs', '.cjs', '.html', '.json', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.mp4', '.webm', '.ogg', '.map']
|
|
1240
1345
|
|
|
1241
1346
|
if (!validExtensions.some(ext => req.url.endsWith(ext))) {
|
|
1242
|
-
req.url = req.url
|
|
1347
|
+
req.url = req.url + '/'
|
|
1348
|
+
let baseRoute = '/' + req.url.split('/')[1]
|
|
1349
|
+
let paramRoute = globalThis.paramRoutes.find((e) => {
|
|
1350
|
+
let base = e.url.split('/:')[0]
|
|
1351
|
+
return base === baseRoute
|
|
1352
|
+
})
|
|
1353
|
+
if (paramRoute) {
|
|
1354
|
+
req.url = baseRoute
|
|
1355
|
+
}
|
|
1243
1356
|
req.url = path.join(process.cwd(), 'dist', req.url, 'index.html');
|
|
1244
1357
|
} else {
|
|
1245
|
-
req.url = path.join(process.cwd(), 'dist', req.url);
|
|
1358
|
+
req.url = path.join(process.cwd(), 'dist/', req.url);
|
|
1246
1359
|
}
|
|
1247
1360
|
|
|
1248
1361
|
const filePath = req.url
|
|
@@ -1259,6 +1372,7 @@ const s = () => {
|
|
|
1259
1372
|
let ws = new WebSocket('ws://localhost:${process.env.PORT || 3000}')
|
|
1260
1373
|
ws.onmessage = (e) => {
|
|
1261
1374
|
if(e.data === 'reload'){
|
|
1375
|
+
console.log('Reloading...')
|
|
1262
1376
|
window.location.reload()
|
|
1263
1377
|
}
|
|
1264
1378
|
}
|
|
@@ -1280,7 +1394,7 @@ const s = () => {
|
|
|
1280
1394
|
|
|
1281
1395
|
|
|
1282
1396
|
function getContentType(filePath) {
|
|
1283
|
-
let ext = ['.js', '.css', '.mjs', '.cjs', '.html', '.json', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.mp4', '.webm', '.ogg'].includes(path.extname(filePath)) ? path.extname(filePath) : '.html'
|
|
1397
|
+
let ext = ['.js', '.css', '.mjs', '.cjs', '.html', '.json', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.mp4', '.webm', '.ogg', '.map'].includes(path.extname(filePath)) ? path.extname(filePath) : '.html'
|
|
1284
1398
|
switch (ext) {
|
|
1285
1399
|
case '.js':
|
|
1286
1400
|
return 'text/javascript';
|
|
@@ -1292,6 +1406,8 @@ const s = () => {
|
|
|
1292
1406
|
return 'text/javascript';
|
|
1293
1407
|
case '.html':
|
|
1294
1408
|
return 'text/html';
|
|
1409
|
+
case '.map':
|
|
1410
|
+
return 'application/json';
|
|
1295
1411
|
case '.json':
|
|
1296
1412
|
return 'application/json';
|
|
1297
1413
|
case '.png':
|
|
@@ -1315,34 +1431,29 @@ const s = () => {
|
|
|
1315
1431
|
}
|
|
1316
1432
|
}
|
|
1317
1433
|
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1434
|
+
server.listen(port, () => {
|
|
1435
|
+
console.log(`Server is running on port ${port}`);
|
|
1436
|
+
globalThis.ws = ws
|
|
1321
1437
|
});
|
|
1322
|
-
let i =
|
|
1323
|
-
setInterval(() => {
|
|
1324
|
-
if (globalThis.isBuilding && globalThis.devMode) {
|
|
1325
1438
|
|
|
1326
|
-
ws.clients.forEach((client) => {
|
|
1327
|
-
client.send('reload')
|
|
1328
|
-
})
|
|
1329
|
-
} else {
|
|
1330
|
-
clearInterval(i)
|
|
1331
|
-
}
|
|
1332
|
-
}, 120)
|
|
1333
1439
|
|
|
1334
1440
|
}
|
|
1335
1441
|
|
|
1336
1442
|
|
|
1337
1443
|
switch (true) {
|
|
1338
|
-
case process.argv.includes('
|
|
1444
|
+
case process.argv.includes('dev') && !process.argv.includes('build') && !process.argv.includes('start'):
|
|
1339
1445
|
|
|
1340
1446
|
globalThis.devMode = true
|
|
1447
|
+
globalThis.isProduction = false
|
|
1448
|
+
|
|
1449
|
+
let p = process.env.PORT || config.port || process.argv.includes('-p') ? process.argv[process.argv.indexOf('-p') + 1] : 3000
|
|
1450
|
+
globalThis.oneAndDone = false
|
|
1341
1451
|
console.log(`
|
|
1342
|
-
Vader.js
|
|
1452
|
+
Vader.js v${fs.readFileSync(process.cwd() + '/node_modules/vaderjs/package.json', 'utf8').split('"version": "')[1].split('"')[0]}
|
|
1343
1453
|
- Watching for changes in ./pages
|
|
1344
1454
|
- Watching for changes in ./src
|
|
1345
1455
|
- Watching for changes in ./public
|
|
1456
|
+
- Serving on port ${p}
|
|
1346
1457
|
`)
|
|
1347
1458
|
!globalThis.isBuilding ? Build() : null
|
|
1348
1459
|
|
|
@@ -1354,51 +1465,63 @@ Vader.js v1.3.3
|
|
|
1354
1465
|
if (event == 'change'
|
|
1355
1466
|
&& !globalThis.isBuilding
|
|
1356
1467
|
) {
|
|
1468
|
+
if (globalThis.ws && !globalThis.isWriting) {
|
|
1469
|
+
globalThis.ws.clients.forEach((client) => {
|
|
1470
|
+
console.log('Reloading...')
|
|
1471
|
+
client.send('reload')
|
|
1472
|
+
})
|
|
1473
|
+
}
|
|
1357
1474
|
|
|
1475
|
+
console.log('\nRebuilding...')
|
|
1476
|
+
globalThis.isBuilding = true
|
|
1358
1477
|
Build()
|
|
1359
1478
|
}
|
|
1360
1479
|
}).on('error', (err) => console.log(err))
|
|
1361
1480
|
})
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
process.env.PORT = p
|
|
1365
|
-
s()
|
|
1481
|
+
s(p)
|
|
1366
1482
|
|
|
1367
1483
|
globalThis.listen = true;
|
|
1368
1484
|
|
|
1369
1485
|
break;
|
|
1370
|
-
case process.argv.includes('
|
|
1486
|
+
case process.argv.includes('build') && !process.argv.includes('dev') && !process.argv.includes('start'):
|
|
1371
1487
|
globalThis.devMode = false
|
|
1488
|
+
globalThis.isProduction = true
|
|
1489
|
+
globalThis.routeStates = []
|
|
1372
1490
|
console.log(`
|
|
1373
1491
|
Vader.js v1.3.3
|
|
1374
1492
|
Building to ./dist
|
|
1375
1493
|
`)
|
|
1494
|
+
if (fs.existsSync(process.cwd() + '/dist/src/maps')) {
|
|
1495
|
+
fs.rmSync(process.cwd() + '/dist/src/maps', { recursive: true })
|
|
1496
|
+
}
|
|
1376
1497
|
Build()
|
|
1377
1498
|
|
|
1378
1499
|
break;
|
|
1379
|
-
case process.argv.includes('
|
|
1380
|
-
let port = process.argv[process.argv.indexOf('
|
|
1381
|
-
|
|
1500
|
+
case process.argv.includes('start') && !process.argv.includes('dev') && !process.argv.includes('build'):
|
|
1501
|
+
let port = process.env.PORT || config.port || process.argv.includes('-p') ? process.argv[process.argv.indexOf('-p') + 1] : 3000
|
|
1502
|
+
console.log(port)
|
|
1382
1503
|
globalThis.devMode = false
|
|
1383
1504
|
console.log(`
|
|
1384
1505
|
Vader.js v1.3.3
|
|
1385
1506
|
Serving ./dist on port ${port}
|
|
1386
1507
|
url: http://localhost:${port}
|
|
1387
1508
|
`)
|
|
1388
|
-
s()
|
|
1509
|
+
s(port)
|
|
1389
1510
|
break;
|
|
1390
1511
|
default:
|
|
1391
|
-
|
|
1512
|
+
// add color
|
|
1513
|
+
console.log(`
|
|
1392
1514
|
Vader.js is a reactive framework for building interactive applications for the web built ontop of bun.js!
|
|
1393
1515
|
|
|
1394
1516
|
Usage: vader <command>
|
|
1395
1517
|
|
|
1396
1518
|
Commands:
|
|
1397
|
-
|
|
1519
|
+
|
|
1520
|
+
vaderjs dev -p <number> Start the development server
|
|
1398
1521
|
|
|
1399
|
-
|
|
1522
|
+
vaderjs build Build the project to ./dist
|
|
1400
1523
|
|
|
1401
|
-
|
|
1524
|
+
vaderjs start -p <number> Production Mode (default 3000 or process.env.PORT)
|
|
1402
1525
|
|
|
1403
1526
|
Learn more about vader: https://vader-js.pages.dev/
|
|
1404
1527
|
|