vaderjs 1.3.3-alpha-19 → 1.3.3-alpha-20
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 +24 -8
- package/client/index.js +231 -62
- package/package.json +1 -1
- package/runtime/vader.js +230 -49
- package/vader.js +54 -32
package/README.md
CHANGED
|
@@ -94,9 +94,10 @@ return {default:Home}
|
|
|
94
94
|
|
|
95
95
|
|
|
96
96
|
### State Management
|
|
97
|
+
Vaderjs uses partial hydration which is much better than react vdom, simply pass the ref key to state and only that element will update - no vdom required!!
|
|
97
98
|
|
|
98
99
|
```jsx
|
|
99
|
-
let {Component, useState} = await import('vaderjs/client')
|
|
100
|
+
let {Component, useState, useRef} = await import('vaderjs/client')
|
|
100
101
|
|
|
101
102
|
class MyApp extends Component{
|
|
102
103
|
contructor(){
|
|
@@ -106,12 +107,16 @@ class MyApp extends Component{
|
|
|
106
107
|
|
|
107
108
|
render(){
|
|
108
109
|
let [count, setCount] = useState(0)
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
110
|
+
let ref = useRef('')
|
|
111
|
+
|
|
112
112
|
return <>
|
|
113
|
-
<p>Count is ${count}</p>
|
|
114
|
-
|
|
113
|
+
<p ref={ref.bind}>Count is ${count}</p>
|
|
114
|
+
${/**
|
|
115
|
+
pass anything used from the toplevel render to the lowerlevel function params to be able to invoke!
|
|
116
|
+
**/}
|
|
117
|
+
<button onclick={(setCount, count, ref)=>{
|
|
118
|
+
setCount(count + 1, ref.bind)
|
|
119
|
+
}}>Increment</button>
|
|
115
120
|
</>
|
|
116
121
|
|
|
117
122
|
}
|
|
@@ -124,6 +129,7 @@ return {default:MyApp}
|
|
|
124
129
|
### Function Binding
|
|
125
130
|
|
|
126
131
|
Vaderjs allows you to bind functions directly to html elements just like react
|
|
132
|
+
there are two ways - top level invokes like below
|
|
127
133
|
|
|
128
134
|
```javascript
|
|
129
135
|
// vader uses params[0] as the event target object and other parameters resolve after
|
|
@@ -141,8 +147,18 @@ return <>
|
|
|
141
147
|
</>
|
|
142
148
|
```
|
|
143
149
|
|
|
144
|
-
|
|
145
|
-
|
|
150
|
+
and lower level invokes - these operate the same just allow you to pass items from top level to lower level: ex - I have a variable named car and i want the button to log it i can pass it as a parameter to allow it to be added to the buttons function scope
|
|
151
|
+
|
|
152
|
+
```jsx
|
|
153
|
+
let car = {
|
|
154
|
+
model: 'tesla',
|
|
155
|
+
price: 'toomiuch'
|
|
156
|
+
}
|
|
157
|
+
return <>
|
|
158
|
+
<button onclick={(car)=>{
|
|
159
|
+
console.log(car.model)
|
|
160
|
+
}}>Log</button>
|
|
161
|
+
```
|
|
146
162
|
|
|
147
163
|
|
|
148
164
|
|
package/client/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
window.params = {};
|
|
3
3
|
window.Vader = {
|
|
4
|
-
version: "1.3.
|
|
4
|
+
version: "1.3.3",
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
let errors = {
|
|
@@ -43,16 +43,13 @@ let hasran = [];
|
|
|
43
43
|
let states = {};
|
|
44
44
|
let mounts = [];
|
|
45
45
|
export const strictMount = (key, callback) => {
|
|
46
|
-
|
|
47
|
-
if(
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
let timer = setInterval(() => {
|
|
47
|
+
if (document.querySelector('[key="' + key + '"]')) {
|
|
48
|
+
console.log('mounted')
|
|
49
|
+
clearInterval(timer);
|
|
50
50
|
callback();
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
hasran.push(callback.toString());
|
|
54
|
-
}
|
|
55
|
-
},0);
|
|
51
|
+
}
|
|
52
|
+
}, 120);
|
|
56
53
|
};
|
|
57
54
|
|
|
58
55
|
window.delegate = (event) => {
|
|
@@ -167,9 +164,93 @@ export class Component {
|
|
|
167
164
|
window.listeners = [];
|
|
168
165
|
this.functionMap = new Map();
|
|
169
166
|
this.freeMemoryFromFunctions();
|
|
167
|
+
this.checkIFMounted();
|
|
170
168
|
this.memoizes = []
|
|
169
|
+
|
|
170
|
+
this.vdom = []
|
|
171
|
+
|
|
171
172
|
this.children = []
|
|
173
|
+
let dom = new DOMParser().parseFromString(this.render(), 'text/html').body.firstChild;
|
|
174
|
+
dom.querySelectorAll('*').forEach((el) => {
|
|
175
|
+
let obj = {
|
|
176
|
+
el: el,
|
|
177
|
+
tag: el.tagName,
|
|
178
|
+
html: el.innerHTML,
|
|
179
|
+
content: el.textContent,
|
|
180
|
+
value: el.value,
|
|
181
|
+
attributes: el.attributes,
|
|
182
|
+
children: el.childNodes,
|
|
183
|
+
}
|
|
184
|
+
this.vdom.push(obj)
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Parent of the current component.
|
|
189
|
+
* @type {Component}
|
|
190
|
+
*/
|
|
191
|
+
this.parentNode = {}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Request object.
|
|
195
|
+
*/
|
|
196
|
+
this.request = {
|
|
197
|
+
/**
|
|
198
|
+
* @type {string}
|
|
199
|
+
* @description The headers for the current route
|
|
200
|
+
*/
|
|
201
|
+
headers:{},
|
|
202
|
+
/**
|
|
203
|
+
* @type {string}
|
|
204
|
+
* @description The method for the current route
|
|
205
|
+
*/
|
|
206
|
+
method: "GET",
|
|
207
|
+
/**
|
|
208
|
+
* @type {string}
|
|
209
|
+
* @description params for the given route /:id/:name etc
|
|
210
|
+
*/
|
|
211
|
+
params: {},
|
|
212
|
+
/**
|
|
213
|
+
* @type {string}
|
|
214
|
+
* @description path: current route path
|
|
215
|
+
*/
|
|
216
|
+
path: "",
|
|
217
|
+
/**
|
|
218
|
+
* @type {string}
|
|
219
|
+
* @description query: query object for the current route ?name=hello -> {name: 'hello'}
|
|
220
|
+
*/
|
|
221
|
+
query: {},
|
|
222
|
+
},
|
|
223
|
+
/**
|
|
224
|
+
* @type {string}
|
|
225
|
+
* @description The response object for the current route
|
|
226
|
+
*/
|
|
227
|
+
this.response = {
|
|
228
|
+
/**
|
|
229
|
+
* @method json
|
|
230
|
+
* @description This method allows you to send json data to the client
|
|
231
|
+
* @param {*} data
|
|
232
|
+
*/
|
|
233
|
+
json: (data) => {},
|
|
234
|
+
/**
|
|
235
|
+
* @method send
|
|
236
|
+
* @description This method allows you to send text data to the client
|
|
237
|
+
* @param {*} data
|
|
238
|
+
*/
|
|
239
|
+
send: (data) => {},
|
|
240
|
+
/**
|
|
241
|
+
* @method redirect
|
|
242
|
+
* @description This method allows you to redirect the client to a new route
|
|
243
|
+
* @param {*} path
|
|
244
|
+
*/
|
|
245
|
+
redirect: (path) => {},
|
|
246
|
+
/**
|
|
247
|
+
* @method render
|
|
248
|
+
* @description render a new component to the client
|
|
249
|
+
* @param {*} Component
|
|
250
|
+
*/
|
|
251
|
+
render: async (Component) => {},
|
|
172
252
|
}
|
|
253
|
+
}
|
|
173
254
|
|
|
174
255
|
createComponent(/**@type {Component}**/component, props, children) {
|
|
175
256
|
|
|
@@ -179,26 +260,16 @@ export class Component {
|
|
|
179
260
|
if(!props.key){
|
|
180
261
|
throw new Error('new components must have a key')
|
|
181
262
|
}
|
|
182
|
-
let comp = new component();
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (newFunc) {
|
|
187
|
-
newFunc = newFunc[0].replace(/this.bind\((.*)\)/gs, "$1");
|
|
188
|
-
newFunc = newFunc.split('`')[1]
|
|
189
|
-
props[key] = this.bind(newFunc, { jsx: true, params: props[key], ref: props.ref });
|
|
190
|
-
return
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
props[key] = props[key].toString().replace('"', '').replace("'", '').replace('${', '').replace('}', '')
|
|
196
|
-
});
|
|
263
|
+
let comp = new component(props);
|
|
264
|
+
if(this.components[props.key]){
|
|
265
|
+
return this.components[props.key]
|
|
266
|
+
}
|
|
197
267
|
comp['props'] = props;
|
|
198
268
|
comp.children = children;
|
|
199
269
|
comp.props.children = children.join('')
|
|
200
270
|
comp.parentNode = this;
|
|
201
271
|
comp.key = props.key || null;
|
|
272
|
+
|
|
202
273
|
this.components[props.key] = comp
|
|
203
274
|
this.children.push(comp)
|
|
204
275
|
return this.components[props.key]
|
|
@@ -215,6 +286,7 @@ export class Component {
|
|
|
215
286
|
}
|
|
216
287
|
|
|
217
288
|
let comp = this.components[component.key];
|
|
289
|
+
|
|
218
290
|
let h = comp.render()
|
|
219
291
|
|
|
220
292
|
if(h && h.split('>,').length > 1){
|
|
@@ -240,28 +312,75 @@ export class Component {
|
|
|
240
312
|
* Hydrates the component by updating the HTML content if it has changed.
|
|
241
313
|
* @private
|
|
242
314
|
*/
|
|
243
|
-
hydrate() {
|
|
244
|
-
if (this.key) {
|
|
245
|
-
|
|
246
|
-
const el = document.querySelector(`[key="${this.key}"]`);
|
|
247
315
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
316
|
+
domDifference(oldDom, newDom) {
|
|
317
|
+
let diff = [];
|
|
318
|
+
|
|
319
|
+
for (let i = 0; i < oldDom.length; i++) {
|
|
320
|
+
let oldEl = oldDom[i];
|
|
321
|
+
let newEl = newDom[i];
|
|
322
|
+
|
|
323
|
+
if (oldEl && newEl && !oldEl.isEqualNode(newEl)) {
|
|
324
|
+
diff.push({
|
|
325
|
+
type: 'replace',
|
|
326
|
+
old: oldEl,
|
|
327
|
+
new: newEl.cloneNode(true),
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return diff;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
updateChangedElements(diff) {
|
|
336
|
+
diff.forEach((change) => {
|
|
337
|
+
switch (change.type) {
|
|
338
|
+
case 'replace':
|
|
339
|
+
change.old.parentNode.replaceChild(change.new, change.old);
|
|
340
|
+
break;
|
|
341
|
+
case 'remove':
|
|
342
|
+
change.old.remove();
|
|
343
|
+
break;
|
|
344
|
+
case 'add':
|
|
345
|
+
change.old.appendChild(change.new.cloneNode(true));
|
|
346
|
+
break;
|
|
347
|
+
default:
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
hydrate(hook) {
|
|
354
|
+
if (this.key) {
|
|
355
|
+
if (hook) {
|
|
356
|
+
let newDom = new DOMParser().parseFromString(this.render(), 'text/html').body.firstChild;
|
|
357
|
+
|
|
358
|
+
let oldElements = document.body.querySelectorAll(`[ref="${hook}"]`);
|
|
359
|
+
let newElements = newDom.querySelectorAll(`[ref="${hook}"]`);
|
|
360
|
+
let diff = this.domDifference(oldElements, newElements);
|
|
361
|
+
this.updateChangedElements(diff);
|
|
362
|
+
} else {
|
|
363
|
+
const targetElement = document.querySelector(`[key="${this.key}"]`);
|
|
364
|
+
if (targetElement) {
|
|
365
|
+
targetElement.innerHTML = this.render();
|
|
366
|
+
} else {
|
|
367
|
+
console.error('Target element not found.');
|
|
261
368
|
}
|
|
262
369
|
}
|
|
263
370
|
}
|
|
264
371
|
}
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
patch(oldElements, newElements) {
|
|
376
|
+
const diff = this.domDifference(oldElements, newElements);
|
|
377
|
+
|
|
378
|
+
this.updateChangedElements(diff);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
|
|
265
384
|
|
|
266
385
|
/**
|
|
267
386
|
* Handles an object by parsing it as JSON and evaluating it.
|
|
@@ -279,7 +398,7 @@ export class Component {
|
|
|
279
398
|
}
|
|
280
399
|
|
|
281
400
|
/**
|
|
282
|
-
* Frees memory from functions that have not been used for a certain period of time.
|
|
401
|
+
* Frees memory from functions that have not been used for a certain period of time.c
|
|
283
402
|
* @private
|
|
284
403
|
*/
|
|
285
404
|
freeMemoryFromFunctions() {
|
|
@@ -299,23 +418,47 @@ export class Component {
|
|
|
299
418
|
* @param {string} ref - The reference.
|
|
300
419
|
* @returns {string} - A valid inline JS function call.
|
|
301
420
|
*/
|
|
302
|
-
bind(funcData,
|
|
421
|
+
bind(funcData,jsx,ref, paramNames, ...params) {
|
|
422
|
+
|
|
303
423
|
|
|
304
424
|
const name = `func_${crypto ? crypto.getRandomValues(new Uint32Array(1))[0] : Math.random()}`;
|
|
305
425
|
|
|
306
|
-
var dynamicFunction = (params) => {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
426
|
+
var dynamicFunction = async (...params) => {
|
|
427
|
+
|
|
428
|
+
// Replace double commas with a single comma
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
// Turn params into a destructured object
|
|
432
|
+
let paramObject = {};
|
|
433
|
+
params = params[0]
|
|
434
|
+
|
|
435
|
+
paramNames = paramNames.replace(/,,/g, ',');
|
|
436
|
+
let newparamnames = paramNames.replaceAll(',,', ',')
|
|
437
|
+
// Remove trailing commas
|
|
438
|
+
paramNames.endsWith(',') ? paramNames = paramNames.slice(0, -1) : null;
|
|
439
|
+
console.log(paramNames)
|
|
440
|
+
|
|
441
|
+
params.forEach((param, index) => {
|
|
442
|
+
paramObject[newparamnames.split(',')[index]] = param;
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
paramNames = paramNames.replace(',,', ',');
|
|
446
|
+
let func = new Function(`${paramNames}`, `
|
|
447
|
+
return (async (${paramNames}) => {
|
|
448
|
+
${funcData}
|
|
449
|
+
})(${Object.keys(paramObject).join(',')})
|
|
450
|
+
`);
|
|
451
|
+
|
|
452
|
+
// Bind and execute the function with the provided parameters
|
|
453
|
+
await func.bind(this)(...Object.values(paramObject));
|
|
312
454
|
};
|
|
455
|
+
|
|
313
456
|
|
|
314
457
|
dynamicFunction = dynamicFunction.bind(this);
|
|
315
458
|
if (!this.functionMap.has(name)) {
|
|
316
459
|
document.addEventListener(`call_${name}`, (e) => {
|
|
317
460
|
|
|
318
|
-
dynamicFunction();
|
|
461
|
+
dynamicFunction(params);
|
|
319
462
|
this.functionMap.set(e.detail.name, {
|
|
320
463
|
lastUsed: Date.now(),
|
|
321
464
|
});
|
|
@@ -335,15 +478,17 @@ export class Component {
|
|
|
335
478
|
};
|
|
336
479
|
|
|
337
480
|
// Return a valid inline js function call
|
|
338
|
-
return
|
|
481
|
+
return jsx ? dynamicFunction : `
|
|
339
482
|
((event) => {
|
|
340
|
-
event.target.setAttribute('data-ref', '${
|
|
483
|
+
event.target.setAttribute('data-ref', '${ref}');
|
|
341
484
|
let reference = event.target.getAttribute('data-ref');
|
|
342
485
|
event.target.eventData = event;
|
|
486
|
+
|
|
343
487
|
let domquery = queryRef(reference);
|
|
344
|
-
|
|
345
|
-
domquery.eventData
|
|
346
|
-
|
|
488
|
+
|
|
489
|
+
domquery.eventData = event;
|
|
490
|
+
domquery.eventData.target = domquery;
|
|
491
|
+
call('${name}', {event:domquery.eventData}, '${paramNames}')
|
|
347
492
|
})(event)
|
|
348
493
|
`;
|
|
349
494
|
}
|
|
@@ -412,11 +557,14 @@ export class Component {
|
|
|
412
557
|
if (!this.state[key]) {
|
|
413
558
|
this.state[key] = initialState;
|
|
414
559
|
}
|
|
415
|
-
|
|
416
|
-
const
|
|
560
|
+
let updatedValue = () => this.state[key];
|
|
561
|
+
const getValue = updatedValue()
|
|
562
|
+
const set = (newValue, hook) => {
|
|
417
563
|
this.state[key] = newValue;
|
|
418
|
-
this.hydrate();
|
|
564
|
+
this.hydrate(hook);
|
|
419
565
|
};
|
|
566
|
+
this[`set${key}`] = set;
|
|
567
|
+
this[`get${key}`] = getValue;
|
|
420
568
|
return [getValue, set];
|
|
421
569
|
}
|
|
422
570
|
|
|
@@ -429,9 +577,11 @@ export class Component {
|
|
|
429
577
|
this.state[key] = newValue;
|
|
430
578
|
this.hydrate();
|
|
431
579
|
};
|
|
580
|
+
|
|
581
|
+
|
|
432
582
|
return {
|
|
433
|
-
bind: key,
|
|
434
|
-
current:
|
|
583
|
+
bind: key + this.key,
|
|
584
|
+
current: document.querySelector(`[ref="${key + this.key}"]`) || initialState
|
|
435
585
|
}
|
|
436
586
|
}
|
|
437
587
|
|
|
@@ -455,7 +605,7 @@ export class Component {
|
|
|
455
605
|
* @private
|
|
456
606
|
*/
|
|
457
607
|
checkIFMounted() {
|
|
458
|
-
if (this.mounted) return;
|
|
608
|
+
if (this.mounted || !this.key) return;
|
|
459
609
|
let timer = setInterval(() => {
|
|
460
610
|
if (document.querySelector('[key="' + this.key + '"]')) {
|
|
461
611
|
clearInterval(timer);
|
|
@@ -533,6 +683,7 @@ window.require = require;
|
|
|
533
683
|
* @description Allows you to use state to dynamically update your component
|
|
534
684
|
*/
|
|
535
685
|
export const useState = (initialState) => {
|
|
686
|
+
let key = ''
|
|
536
687
|
let value = initialState;
|
|
537
688
|
if (key && !states[key]) {
|
|
538
689
|
this.states[key] = initialState;
|
|
@@ -540,6 +691,16 @@ export const useState = (initialState) => {
|
|
|
540
691
|
return [value, (newValue) => {}];
|
|
541
692
|
};
|
|
542
693
|
|
|
694
|
+
/**
|
|
695
|
+
* @method useReducer
|
|
696
|
+
* @param {*} initialState
|
|
697
|
+
* @param {*} reducer
|
|
698
|
+
* @returns {Array} [value, set]
|
|
699
|
+
*/
|
|
700
|
+
export const useReducer = (/**@type {*}**/initialState, /**@type {function}**/reducer) => {
|
|
701
|
+
return [initialState, (newValue) => {}];
|
|
702
|
+
};
|
|
703
|
+
|
|
543
704
|
const constants = {};
|
|
544
705
|
let constantCounter = 0;
|
|
545
706
|
|
|
@@ -551,12 +712,20 @@ export const constant = (value) => {
|
|
|
551
712
|
return constants[key];
|
|
552
713
|
};
|
|
553
714
|
|
|
715
|
+
export const useRef = (initialState) => {
|
|
716
|
+
return {
|
|
717
|
+
current: initialState,
|
|
718
|
+
bind: '',
|
|
719
|
+
};
|
|
720
|
+
};
|
|
554
721
|
export default {
|
|
555
722
|
Component,
|
|
556
723
|
require,
|
|
557
724
|
invoke,
|
|
558
725
|
mem,
|
|
559
726
|
constant,
|
|
727
|
+
useRef,
|
|
728
|
+
useReducer,
|
|
560
729
|
useState,
|
|
561
730
|
strictMount,
|
|
562
731
|
stylis,
|
package/package.json
CHANGED
package/runtime/vader.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
window.params = {};
|
|
3
3
|
window.Vader = {
|
|
4
|
-
version: "1.3.
|
|
4
|
+
version: "1.3.3",
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
let errors = {
|
|
@@ -43,16 +43,13 @@ let hasran = [];
|
|
|
43
43
|
let states = {};
|
|
44
44
|
let mounts = [];
|
|
45
45
|
export const strictMount = (key, callback) => {
|
|
46
|
-
|
|
47
|
-
if(
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
let timer = setInterval(() => {
|
|
47
|
+
if (document.querySelector('[key="' + key + '"]')) {
|
|
48
|
+
console.log('mounted')
|
|
49
|
+
clearInterval(timer);
|
|
50
50
|
callback();
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
hasran.push(callback.toString());
|
|
54
|
-
}
|
|
55
|
-
},0);
|
|
51
|
+
}
|
|
52
|
+
}, 120);
|
|
56
53
|
};
|
|
57
54
|
|
|
58
55
|
window.delegate = (event) => {
|
|
@@ -167,9 +164,93 @@ export class Component {
|
|
|
167
164
|
window.listeners = [];
|
|
168
165
|
this.functionMap = new Map();
|
|
169
166
|
this.freeMemoryFromFunctions();
|
|
167
|
+
this.checkIFMounted();
|
|
170
168
|
this.memoizes = []
|
|
169
|
+
|
|
170
|
+
this.vdom = []
|
|
171
|
+
|
|
171
172
|
this.children = []
|
|
173
|
+
let dom = new DOMParser().parseFromString(this.render(), 'text/html').body.firstChild;
|
|
174
|
+
dom.querySelectorAll('*').forEach((el) => {
|
|
175
|
+
let obj = {
|
|
176
|
+
el: el,
|
|
177
|
+
tag: el.tagName,
|
|
178
|
+
html: el.innerHTML,
|
|
179
|
+
content: el.textContent,
|
|
180
|
+
value: el.value,
|
|
181
|
+
attributes: el.attributes,
|
|
182
|
+
children: el.childNodes,
|
|
183
|
+
}
|
|
184
|
+
this.vdom.push(obj)
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Parent of the current component.
|
|
189
|
+
* @type {Component}
|
|
190
|
+
*/
|
|
191
|
+
this.parentNode = {}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Request object.
|
|
195
|
+
*/
|
|
196
|
+
this.request = {
|
|
197
|
+
/**
|
|
198
|
+
* @type {string}
|
|
199
|
+
* @description The headers for the current route
|
|
200
|
+
*/
|
|
201
|
+
headers:{},
|
|
202
|
+
/**
|
|
203
|
+
* @type {string}
|
|
204
|
+
* @description The method for the current route
|
|
205
|
+
*/
|
|
206
|
+
method: "GET",
|
|
207
|
+
/**
|
|
208
|
+
* @type {string}
|
|
209
|
+
* @description params for the given route /:id/:name etc
|
|
210
|
+
*/
|
|
211
|
+
params: {},
|
|
212
|
+
/**
|
|
213
|
+
* @type {string}
|
|
214
|
+
* @description path: current route path
|
|
215
|
+
*/
|
|
216
|
+
path: "",
|
|
217
|
+
/**
|
|
218
|
+
* @type {string}
|
|
219
|
+
* @description query: query object for the current route ?name=hello -> {name: 'hello'}
|
|
220
|
+
*/
|
|
221
|
+
query: {},
|
|
222
|
+
},
|
|
223
|
+
/**
|
|
224
|
+
* @type {string}
|
|
225
|
+
* @description The response object for the current route
|
|
226
|
+
*/
|
|
227
|
+
this.response = {
|
|
228
|
+
/**
|
|
229
|
+
* @method json
|
|
230
|
+
* @description This method allows you to send json data to the client
|
|
231
|
+
* @param {*} data
|
|
232
|
+
*/
|
|
233
|
+
json: (data) => {},
|
|
234
|
+
/**
|
|
235
|
+
* @method send
|
|
236
|
+
* @description This method allows you to send text data to the client
|
|
237
|
+
* @param {*} data
|
|
238
|
+
*/
|
|
239
|
+
send: (data) => {},
|
|
240
|
+
/**
|
|
241
|
+
* @method redirect
|
|
242
|
+
* @description This method allows you to redirect the client to a new route
|
|
243
|
+
* @param {*} path
|
|
244
|
+
*/
|
|
245
|
+
redirect: (path) => {},
|
|
246
|
+
/**
|
|
247
|
+
* @method render
|
|
248
|
+
* @description render a new component to the client
|
|
249
|
+
* @param {*} Component
|
|
250
|
+
*/
|
|
251
|
+
render: async (Component) => {},
|
|
172
252
|
}
|
|
253
|
+
}
|
|
173
254
|
|
|
174
255
|
createComponent(/**@type {Component}**/component, props, children) {
|
|
175
256
|
|
|
@@ -179,13 +260,16 @@ export class Component {
|
|
|
179
260
|
if(!props.key){
|
|
180
261
|
throw new Error('new components must have a key')
|
|
181
262
|
}
|
|
182
|
-
let comp = new component();
|
|
183
|
-
|
|
263
|
+
let comp = new component(props);
|
|
264
|
+
if(this.components[props.key]){
|
|
265
|
+
return this.components[props.key]
|
|
266
|
+
}
|
|
184
267
|
comp['props'] = props;
|
|
185
268
|
comp.children = children;
|
|
186
269
|
comp.props.children = children.join('')
|
|
187
270
|
comp.parentNode = this;
|
|
188
271
|
comp.key = props.key || null;
|
|
272
|
+
|
|
189
273
|
this.components[props.key] = comp
|
|
190
274
|
this.children.push(comp)
|
|
191
275
|
return this.components[props.key]
|
|
@@ -202,6 +286,7 @@ export class Component {
|
|
|
202
286
|
}
|
|
203
287
|
|
|
204
288
|
let comp = this.components[component.key];
|
|
289
|
+
|
|
205
290
|
let h = comp.render()
|
|
206
291
|
|
|
207
292
|
if(h && h.split('>,').length > 1){
|
|
@@ -227,28 +312,75 @@ export class Component {
|
|
|
227
312
|
* Hydrates the component by updating the HTML content if it has changed.
|
|
228
313
|
* @private
|
|
229
314
|
*/
|
|
230
|
-
hydrate() {
|
|
231
|
-
if (this.key) {
|
|
232
|
-
|
|
233
|
-
const el = document.querySelector(`[key="${this.key}"]`);
|
|
234
315
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
316
|
+
domDifference(oldDom, newDom) {
|
|
317
|
+
let diff = [];
|
|
318
|
+
|
|
319
|
+
for (let i = 0; i < oldDom.length; i++) {
|
|
320
|
+
let oldEl = oldDom[i];
|
|
321
|
+
let newEl = newDom[i];
|
|
322
|
+
|
|
323
|
+
if (oldEl && newEl && !oldEl.isEqualNode(newEl)) {
|
|
324
|
+
diff.push({
|
|
325
|
+
type: 'replace',
|
|
326
|
+
old: oldEl,
|
|
327
|
+
new: newEl.cloneNode(true),
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return diff;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
updateChangedElements(diff) {
|
|
336
|
+
diff.forEach((change) => {
|
|
337
|
+
switch (change.type) {
|
|
338
|
+
case 'replace':
|
|
339
|
+
change.old.parentNode.replaceChild(change.new, change.old);
|
|
340
|
+
break;
|
|
341
|
+
case 'remove':
|
|
342
|
+
change.old.remove();
|
|
343
|
+
break;
|
|
344
|
+
case 'add':
|
|
345
|
+
change.old.appendChild(change.new.cloneNode(true));
|
|
346
|
+
break;
|
|
347
|
+
default:
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
hydrate(hook) {
|
|
354
|
+
if (this.key) {
|
|
355
|
+
if (hook) {
|
|
356
|
+
let newDom = new DOMParser().parseFromString(this.render(), 'text/html').body.firstChild;
|
|
357
|
+
|
|
358
|
+
let oldElements = document.body.querySelectorAll(`[ref="${hook}"]`);
|
|
359
|
+
let newElements = newDom.querySelectorAll(`[ref="${hook}"]`);
|
|
360
|
+
let diff = this.domDifference(oldElements, newElements);
|
|
361
|
+
this.updateChangedElements(diff);
|
|
362
|
+
} else {
|
|
363
|
+
const targetElement = document.querySelector(`[key="${this.key}"]`);
|
|
364
|
+
if (targetElement) {
|
|
365
|
+
targetElement.innerHTML = this.render();
|
|
366
|
+
} else {
|
|
367
|
+
console.error('Target element not found.');
|
|
248
368
|
}
|
|
249
369
|
}
|
|
250
370
|
}
|
|
251
371
|
}
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
patch(oldElements, newElements) {
|
|
376
|
+
const diff = this.domDifference(oldElements, newElements);
|
|
377
|
+
|
|
378
|
+
this.updateChangedElements(diff);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
|
|
252
384
|
|
|
253
385
|
/**
|
|
254
386
|
* Handles an object by parsing it as JSON and evaluating it.
|
|
@@ -266,7 +398,7 @@ export class Component {
|
|
|
266
398
|
}
|
|
267
399
|
|
|
268
400
|
/**
|
|
269
|
-
* Frees memory from functions that have not been used for a certain period of time.
|
|
401
|
+
* Frees memory from functions that have not been used for a certain period of time.c
|
|
270
402
|
* @private
|
|
271
403
|
*/
|
|
272
404
|
freeMemoryFromFunctions() {
|
|
@@ -286,24 +418,47 @@ export class Component {
|
|
|
286
418
|
* @param {string} ref - The reference.
|
|
287
419
|
* @returns {string} - A valid inline JS function call.
|
|
288
420
|
*/
|
|
289
|
-
bind(funcData,jsx,ref, params) {
|
|
421
|
+
bind(funcData,jsx,ref, paramNames, ...params) {
|
|
422
|
+
|
|
290
423
|
|
|
291
|
-
console.log(jsx)
|
|
292
424
|
const name = `func_${crypto ? crypto.getRandomValues(new Uint32Array(1))[0] : Math.random()}`;
|
|
293
425
|
|
|
294
|
-
var dynamicFunction = (params) => {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
426
|
+
var dynamicFunction = async (...params) => {
|
|
427
|
+
|
|
428
|
+
// Replace double commas with a single comma
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
// Turn params into a destructured object
|
|
432
|
+
let paramObject = {};
|
|
433
|
+
params = params[0]
|
|
434
|
+
|
|
435
|
+
paramNames = paramNames.replace(/,,/g, ',');
|
|
436
|
+
let newparamnames = paramNames.replaceAll(',,', ',')
|
|
437
|
+
// Remove trailing commas
|
|
438
|
+
paramNames.endsWith(',') ? paramNames = paramNames.slice(0, -1) : null;
|
|
439
|
+
console.log(paramNames)
|
|
440
|
+
|
|
441
|
+
params.forEach((param, index) => {
|
|
442
|
+
paramObject[newparamnames.split(',')[index]] = param;
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
paramNames = paramNames.replace(',,', ',');
|
|
446
|
+
let func = new Function(`${paramNames}`, `
|
|
447
|
+
return (async (${paramNames}) => {
|
|
448
|
+
${funcData}
|
|
449
|
+
})(${Object.keys(paramObject).join(',')})
|
|
450
|
+
`);
|
|
451
|
+
|
|
452
|
+
// Bind and execute the function with the provided parameters
|
|
453
|
+
await func.bind(this)(...Object.values(paramObject));
|
|
300
454
|
};
|
|
455
|
+
|
|
301
456
|
|
|
302
457
|
dynamicFunction = dynamicFunction.bind(this);
|
|
303
458
|
if (!this.functionMap.has(name)) {
|
|
304
459
|
document.addEventListener(`call_${name}`, (e) => {
|
|
305
460
|
|
|
306
|
-
dynamicFunction();
|
|
461
|
+
dynamicFunction(params);
|
|
307
462
|
this.functionMap.set(e.detail.name, {
|
|
308
463
|
lastUsed: Date.now(),
|
|
309
464
|
});
|
|
@@ -325,13 +480,15 @@ export class Component {
|
|
|
325
480
|
// Return a valid inline js function call
|
|
326
481
|
return jsx ? dynamicFunction : `
|
|
327
482
|
((event) => {
|
|
328
|
-
event.target.setAttribute('data-ref', '${ref}
|
|
483
|
+
event.target.setAttribute('data-ref', '${ref}');
|
|
329
484
|
let reference = event.target.getAttribute('data-ref');
|
|
330
485
|
event.target.eventData = event;
|
|
486
|
+
|
|
331
487
|
let domquery = queryRef(reference);
|
|
332
|
-
|
|
333
|
-
domquery.eventData
|
|
334
|
-
|
|
488
|
+
|
|
489
|
+
domquery.eventData = event;
|
|
490
|
+
domquery.eventData.target = domquery;
|
|
491
|
+
call('${name}', {event:domquery.eventData}, '${paramNames}')
|
|
335
492
|
})(event)
|
|
336
493
|
`;
|
|
337
494
|
}
|
|
@@ -400,11 +557,14 @@ export class Component {
|
|
|
400
557
|
if (!this.state[key]) {
|
|
401
558
|
this.state[key] = initialState;
|
|
402
559
|
}
|
|
403
|
-
|
|
404
|
-
const
|
|
560
|
+
let updatedValue = () => this.state[key];
|
|
561
|
+
const getValue = updatedValue()
|
|
562
|
+
const set = (newValue, hook) => {
|
|
405
563
|
this.state[key] = newValue;
|
|
406
|
-
this.hydrate();
|
|
564
|
+
this.hydrate(hook);
|
|
407
565
|
};
|
|
566
|
+
this[`set${key}`] = set;
|
|
567
|
+
this[`get${key}`] = getValue;
|
|
408
568
|
return [getValue, set];
|
|
409
569
|
}
|
|
410
570
|
|
|
@@ -417,9 +577,11 @@ export class Component {
|
|
|
417
577
|
this.state[key] = newValue;
|
|
418
578
|
this.hydrate();
|
|
419
579
|
};
|
|
580
|
+
|
|
581
|
+
|
|
420
582
|
return {
|
|
421
|
-
bind: key,
|
|
422
|
-
current:
|
|
583
|
+
bind: key + this.key,
|
|
584
|
+
current: document.querySelector(`[ref="${key + this.key}"]`) || initialState
|
|
423
585
|
}
|
|
424
586
|
}
|
|
425
587
|
|
|
@@ -443,7 +605,7 @@ export class Component {
|
|
|
443
605
|
* @private
|
|
444
606
|
*/
|
|
445
607
|
checkIFMounted() {
|
|
446
|
-
if (this.mounted) return;
|
|
608
|
+
if (this.mounted || !this.key) return;
|
|
447
609
|
let timer = setInterval(() => {
|
|
448
610
|
if (document.querySelector('[key="' + this.key + '"]')) {
|
|
449
611
|
clearInterval(timer);
|
|
@@ -521,6 +683,7 @@ window.require = require;
|
|
|
521
683
|
* @description Allows you to use state to dynamically update your component
|
|
522
684
|
*/
|
|
523
685
|
export const useState = (initialState) => {
|
|
686
|
+
let key = ''
|
|
524
687
|
let value = initialState;
|
|
525
688
|
if (key && !states[key]) {
|
|
526
689
|
this.states[key] = initialState;
|
|
@@ -528,6 +691,16 @@ export const useState = (initialState) => {
|
|
|
528
691
|
return [value, (newValue) => {}];
|
|
529
692
|
};
|
|
530
693
|
|
|
694
|
+
/**
|
|
695
|
+
* @method useReducer
|
|
696
|
+
* @param {*} initialState
|
|
697
|
+
* @param {*} reducer
|
|
698
|
+
* @returns {Array} [value, set]
|
|
699
|
+
*/
|
|
700
|
+
export const useReducer = (/**@type {*}**/initialState, /**@type {function}**/reducer) => {
|
|
701
|
+
return [initialState, (newValue) => {}];
|
|
702
|
+
};
|
|
703
|
+
|
|
531
704
|
const constants = {};
|
|
532
705
|
let constantCounter = 0;
|
|
533
706
|
|
|
@@ -539,12 +712,20 @@ export const constant = (value) => {
|
|
|
539
712
|
return constants[key];
|
|
540
713
|
};
|
|
541
714
|
|
|
715
|
+
export const useRef = (initialState) => {
|
|
716
|
+
return {
|
|
717
|
+
current: initialState,
|
|
718
|
+
bind: '',
|
|
719
|
+
};
|
|
720
|
+
};
|
|
542
721
|
export default {
|
|
543
722
|
Component,
|
|
544
723
|
require,
|
|
545
724
|
invoke,
|
|
546
725
|
mem,
|
|
547
726
|
constant,
|
|
727
|
+
useRef,
|
|
728
|
+
useReducer,
|
|
548
729
|
useState,
|
|
549
730
|
strictMount,
|
|
550
731
|
stylis,
|
package/vader.js
CHANGED
|
@@ -39,8 +39,7 @@ function Compiler(func) {
|
|
|
39
39
|
)
|
|
40
40
|
) {
|
|
41
41
|
return;
|
|
42
|
-
}
|
|
43
|
-
let code = string;
|
|
42
|
+
}
|
|
44
43
|
|
|
45
44
|
let name = func.split(" ")[1].split("(")[0].trim();
|
|
46
45
|
|
|
@@ -159,7 +158,7 @@ function Compiler(func) {
|
|
|
159
158
|
let params = hasParams
|
|
160
159
|
? line.split("(")[1].split(")")[0].trim()
|
|
161
160
|
: null;
|
|
162
|
-
|
|
161
|
+
|
|
163
162
|
if (
|
|
164
163
|
functionparams.length > 0 &&
|
|
165
164
|
functionparams.find((p) => p.name == name)
|
|
@@ -188,7 +187,7 @@ function Compiler(func) {
|
|
|
188
187
|
newvalue = newvalue.replace(
|
|
189
188
|
hasParams ? `${name}(${params})` : name,
|
|
190
189
|
`this.callFunction(\${${replacement}}, ${isJSXComponent ? true : false
|
|
191
|
-
}, event
|
|
190
|
+
}, event, \${JSON.stringify(${params || null})})`
|
|
192
191
|
);
|
|
193
192
|
}
|
|
194
193
|
}
|
|
@@ -215,14 +214,19 @@ function Compiler(func) {
|
|
|
215
214
|
|
|
216
215
|
|
|
217
216
|
let otherdata = {};
|
|
217
|
+
|
|
218
218
|
params ? (otherdata["params"] = params) : null;
|
|
219
219
|
otherdata["jsx"] = isJSXComponent;
|
|
220
220
|
otherdata["ref"] = ref;
|
|
221
221
|
|
|
222
222
|
newvalue = newvalue.split('\n').map(line => line.trim() ? line.trim() + ';' : line).join('\n');
|
|
223
223
|
|
|
224
|
+
// turn params into param1, param2, param3
|
|
224
225
|
|
|
225
|
-
|
|
226
|
+
|
|
227
|
+
let paramString = params ? params.split(' ').map(param => param + ',').join('') : "";
|
|
228
|
+
|
|
229
|
+
let newatribute = `${attributeName}="\${this.bind(\`${newvalue}\`, ${isJSXComponent ? true : false}, '${ref}', "${paramString}", ${params || null})}"`
|
|
226
230
|
|
|
227
231
|
|
|
228
232
|
attribute[attributeName] = {
|
|
@@ -258,7 +262,10 @@ function Compiler(func) {
|
|
|
258
262
|
otherdata["ref"] = ref;
|
|
259
263
|
// since js is all in one line split it
|
|
260
264
|
newvalue = newvalue.split('\n').map(line => line.trim() ? line.trim() + ';' : line).join('\n');
|
|
261
|
-
|
|
265
|
+
// param1, param2, param3
|
|
266
|
+
let length = params ? params.split(' ').length : 0;
|
|
267
|
+
let paramString = params ? params.split(' ').map(param => param + ',').join('') : "";
|
|
268
|
+
let newattribute = `${attributeName}="\${this.bind(\`${newvalue}\`, ${isJSXComponent ? true : false}, '${ref}', "${paramString}", ${params || null})}"`
|
|
262
269
|
newattribute = newattribute.replace(/\s+/g, " ")
|
|
263
270
|
string = string.replace(old, newattribute);
|
|
264
271
|
}
|
|
@@ -295,6 +302,7 @@ function Compiler(func) {
|
|
|
295
302
|
let contents = "";
|
|
296
303
|
let updatedContents = "";
|
|
297
304
|
outerReturn.forEach((returnStatement) => {
|
|
305
|
+
|
|
298
306
|
let lines = returnStatement.split("\n");
|
|
299
307
|
|
|
300
308
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -303,7 +311,7 @@ function Compiler(func) {
|
|
|
303
311
|
continue;
|
|
304
312
|
}
|
|
305
313
|
contents += line + "\n";
|
|
306
|
-
}
|
|
314
|
+
}
|
|
307
315
|
|
|
308
316
|
// Remove trailing ']'
|
|
309
317
|
contents = contents.trim().replace(/\]$/, "");
|
|
@@ -321,19 +329,19 @@ function Compiler(func) {
|
|
|
321
329
|
|
|
322
330
|
let value = attributes[key];
|
|
323
331
|
let oldvalue = value;
|
|
324
|
-
if (value && !value.new) {
|
|
325
|
-
if (value && value.includes("{")) {
|
|
332
|
+
if (value && !value.new) {
|
|
333
|
+
if (value && value.includes("={")) {
|
|
326
334
|
value = value.replace("=", "");
|
|
327
335
|
value == "undefined" ? (value = '"') : (value = value);
|
|
328
336
|
key == 'style' ? value = `{this.parseStyle({${value.split('{{')[1].split('}}')[0]}})}` : null
|
|
329
337
|
|
|
330
338
|
|
|
331
339
|
value = `="\$${value}",`;
|
|
332
|
-
string = string.
|
|
340
|
+
string = string.replace(oldvalue, value);
|
|
333
341
|
|
|
334
|
-
} else if (value && value.includes("`")) {
|
|
342
|
+
} else if (value && value.includes("={`")) {
|
|
335
343
|
value = value.replace("=", "");
|
|
336
|
-
|
|
344
|
+
|
|
337
345
|
value = `"\$${value}",`;
|
|
338
346
|
string = string.replace(oldvalue, value);
|
|
339
347
|
|
|
@@ -405,16 +413,15 @@ function Compiler(func) {
|
|
|
405
413
|
let setKey = line.split("=")[0].split(",")[1].trim().replace("]", "");
|
|
406
414
|
|
|
407
415
|
key = key.replace("[", "").replace(",", "");
|
|
408
|
-
let value = line
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
this.${key} = ${key}
|
|
416
|
-
this.${setKey} = ${setKey}
|
|
416
|
+
let value = line.split("=")[1].split("useState(")[1]
|
|
417
|
+
let regex = /useState\((.*)\)/gs
|
|
418
|
+
value = value.match(regex) ? value.match(regex)[0].split("useState(")[1].split(")")[0].trim() : value
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
let newState = `${type} [${key}, ${setKey}] = this.useState('${key}', ${value}
|
|
422
|
+
|
|
417
423
|
`;
|
|
424
|
+
|
|
418
425
|
|
|
419
426
|
// get setkey calls and replace with this.setKey
|
|
420
427
|
string.split("\n").forEach((line) => {
|
|
@@ -429,18 +436,28 @@ function Compiler(func) {
|
|
|
429
436
|
}
|
|
430
437
|
});
|
|
431
438
|
string = string.replace(line, newState);
|
|
432
|
-
} else if (line.includes("useRef")) {
|
|
439
|
+
} else if (line.includes("useRef") && !line.includes("import")) {
|
|
433
440
|
line = line.trim();
|
|
434
441
|
// let ref = useRef(null)
|
|
435
442
|
let type = line.split(" ")[0];
|
|
436
443
|
let key = line.split("=")[0].split(" ")[1].trim();
|
|
437
|
-
let value = line
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
+
let value = line.split("=")[1].split("useRef(")[1]
|
|
445
|
+
|
|
446
|
+
let regex = /useState\((.*)\)/gs
|
|
447
|
+
value = value.match(regex) ? value.match(regex)[0].split("useRef(")[1].split(")")[0].trim() : value
|
|
448
|
+
let newState = `${type} ${key} = this.useRef('${key}', ${value}`;
|
|
449
|
+
|
|
450
|
+
string = string.replace(line, newState);
|
|
451
|
+
}else if (line.includes("useReducer") && !line.includes("import")){
|
|
452
|
+
line = line.trim();
|
|
453
|
+
// let ref = useRef(null)
|
|
454
|
+
let type = line.split(" ")[0];
|
|
455
|
+
let key = line.split("=")[0].split(" ")[1].trim();
|
|
456
|
+
let value = line.split("=")[1].split("useReducer(")[1]
|
|
457
|
+
|
|
458
|
+
let regex = /useReducer\((.*)\)/gs
|
|
459
|
+
value = value.match(regex) ? value.match(regex)[0].split("useReducer(")[1].split(")")[0].trim() : value
|
|
460
|
+
let newState = `${type} ${key} = this.useReducer('${key}', ${value}`;
|
|
444
461
|
|
|
445
462
|
string = string.replace(line, newState);
|
|
446
463
|
}
|
|
@@ -475,6 +492,12 @@ function Compiler(func) {
|
|
|
475
492
|
return array;
|
|
476
493
|
};
|
|
477
494
|
|
|
495
|
+
// replaceall comments ${/* */} with ''
|
|
496
|
+
string = string.replaceAll(/\$\{\/\*.*\*\/\}/gs, "");
|
|
497
|
+
|
|
498
|
+
string = string.replaceAll('../src', './src')
|
|
499
|
+
|
|
500
|
+
|
|
478
501
|
// capture <Component />, <Component></Component>, and <Component>content</Component>
|
|
479
502
|
|
|
480
503
|
// Example usage
|
|
@@ -495,7 +518,7 @@ function Compiler(func) {
|
|
|
495
518
|
|
|
496
519
|
let name = component.split("<")[1].split(">")[0].split(" ")[0].replace("/", "");
|
|
497
520
|
let props = component.split(`<${name}`)[1].split(">")[0].trim()
|
|
498
|
-
|
|
521
|
+
|
|
499
522
|
|
|
500
523
|
let savedname = name;
|
|
501
524
|
let children = props
|
|
@@ -551,6 +574,7 @@ function Compiler(func) {
|
|
|
551
574
|
// remove trailing ,
|
|
552
575
|
.replace(/,\s*$/, "")
|
|
553
576
|
props = props.replace(/:('[^']*'|"[^"]*")/g, ':$1,');
|
|
577
|
+
props = props.replaceAll(',,', ',')
|
|
554
578
|
|
|
555
579
|
|
|
556
580
|
|
|
@@ -724,9 +748,7 @@ async function Build() {
|
|
|
724
748
|
});
|
|
725
749
|
|
|
726
750
|
}
|
|
727
|
-
|
|
728
751
|
|
|
729
|
-
console.log(`Compilation completed`)
|
|
730
752
|
globalThis.isBuilding = false
|
|
731
753
|
}
|
|
732
754
|
import { watch } from "fs";
|