vaderjs 1.4.2-jpiml56 → 1.4.2-kml56
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 +4 -14
- package/binaries/Kalix/index.js +12 -20
- package/binaries/compiler/main.js +20 -99
- package/binaries/vader.js +0 -0
- package/binaries/watcher/hmr.js +0 -5
- package/client/runtime/index.js +417 -1
- package/client/runtime/router.js +235 -1
- package/config/index.ts +1 -20
- package/package.json +3 -2
- package/plugins/cloudflare/functions/index.js +0 -4
- package/plugins/cloudflare/toCopy/@server/Kalix/index.js +14 -62
- package/plugins/cloudflare/toCopy/src/client.js +432 -1
- package/plugins/cloudflare/toCopy/src/router.js +235 -1
- package/plugins/ssg/index.js +21 -94
- package/router/index.ts +10 -37
- package/server/index.js +2 -16
- package/plugins/tailwindcss/index.ts +0 -93
- /package/{vader_dev.js → vader.js} +0 -0
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vaderjs",
|
|
3
3
|
"description": "A reactive framework for building fast and scalable web applications",
|
|
4
|
-
"version": "1.4.2-
|
|
4
|
+
"version": "1.4.2-kml56",
|
|
5
|
+
"main": "vader.js",
|
|
5
6
|
"author": {
|
|
6
7
|
"name": "Malikwhitten67",
|
|
7
8
|
"email": "malikwhitterb@gmail.com"
|
|
@@ -13,7 +14,7 @@
|
|
|
13
14
|
},
|
|
14
15
|
"type": "module",
|
|
15
16
|
"bin":{
|
|
16
|
-
"vader":"./
|
|
17
|
+
"vader":"./vader.js"
|
|
17
18
|
},
|
|
18
19
|
"dependencies": {
|
|
19
20
|
"ws": "latest"
|
|
@@ -8,10 +8,6 @@ const glob = new Glob("/**/*.{ts,tsx,js,jsx}", {
|
|
|
8
8
|
*/
|
|
9
9
|
async function generate(){
|
|
10
10
|
let config = await import(process.cwd() + '/vader.config.js').then((config) => { return config.default })
|
|
11
|
-
if(!config?.env || !config?.env.SSR){
|
|
12
|
-
console.error('\x1b[31m[CloudFlare Functions] \x1b[0m - Please add an SSR environment variable to your vader.config.js file')
|
|
13
|
-
return
|
|
14
|
-
}
|
|
15
11
|
let start = Date.now()
|
|
16
12
|
for(var i of glob.scanSync({cwd: process.cwd() + '/routes', absolute: true})){
|
|
17
13
|
let data = await Bun.file(i).text()
|
|
@@ -10,40 +10,10 @@ export class DOMParser {
|
|
|
10
10
|
*/
|
|
11
11
|
parseFromString(html) {
|
|
12
12
|
let doc = new Document();
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"jsxDEV": "Element",
|
|
18
|
-
"jsx": "Element"
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
let el = t.transformSync(`
|
|
23
|
-
|
|
24
|
-
const html = ${html}
|
|
25
|
-
function Doc() {
|
|
26
|
-
return (
|
|
27
|
-
<html>
|
|
28
|
-
<body>${html}</body>
|
|
29
|
-
</html>
|
|
30
|
-
)
|
|
31
|
-
}
|
|
32
|
-
return Doc()
|
|
33
|
-
` )
|
|
34
|
-
el = el.replaceAll(`jsxDEV`, `Element`)
|
|
35
|
-
let evaluated = eval(`(function(){${el}})()`)
|
|
36
|
-
evaluated.children.forEach((child) => {
|
|
37
|
-
child.outerHTML = child.toString()
|
|
38
|
-
})
|
|
39
|
-
doc.tree = evaluated.children
|
|
40
|
-
doc.body = evaluated.children[0]
|
|
41
|
-
doc.body.outerHTML = evaluated.children[0].toString()
|
|
42
|
-
doc.body.firstChild = evaluated.children[0].children[0]
|
|
43
|
-
doc.documentElement = evaluated
|
|
44
|
-
doc.documentElement.outerHTML = evaluated.children[0].toString()
|
|
45
|
-
this.tree = evaluated.children
|
|
46
|
-
return doc
|
|
13
|
+
return {
|
|
14
|
+
error: "Not implemented",
|
|
15
|
+
}
|
|
16
|
+
|
|
47
17
|
}
|
|
48
18
|
/**
|
|
49
19
|
* @description - Returns a string containing the HTML serialization of the element's descendants.
|
|
@@ -67,7 +37,7 @@ export class HTMLTextNode {
|
|
|
67
37
|
}
|
|
68
38
|
|
|
69
39
|
insertBefore(node) {
|
|
70
|
-
this.nodeValue = `${node.
|
|
40
|
+
this.nodeValue = `${node.toString()}${this.nodeValue}`;
|
|
71
41
|
return this;
|
|
72
42
|
}
|
|
73
43
|
}
|
|
@@ -111,7 +81,7 @@ export class HTMLElement {
|
|
|
111
81
|
if (key !== 'style' && key !== 'ref' && !key.startsWith('on')) {
|
|
112
82
|
props += `${key}="${this.props[key]}" `
|
|
113
83
|
}
|
|
114
|
-
}
|
|
84
|
+
}
|
|
115
85
|
let children = this.children
|
|
116
86
|
.map((child) => {
|
|
117
87
|
return child.toString();
|
|
@@ -153,9 +123,7 @@ export class HTMLElement {
|
|
|
153
123
|
}
|
|
154
124
|
})
|
|
155
125
|
.join("");
|
|
156
|
-
return string;
|
|
157
|
-
|
|
158
|
-
|
|
126
|
+
return string;
|
|
159
127
|
default:
|
|
160
128
|
break;
|
|
161
129
|
}
|
|
@@ -182,8 +150,8 @@ export class HTMLElement {
|
|
|
182
150
|
* @returns {HTMLElement}
|
|
183
151
|
*/
|
|
184
152
|
setContent(content) {
|
|
185
|
-
let textNode = new
|
|
186
|
-
this.children = [textNode];
|
|
153
|
+
let textNode = new HTMLTextNode(content);
|
|
154
|
+
this.children = [textNode];
|
|
187
155
|
this.outerHTML = this.toString("outerHTML");
|
|
188
156
|
this.innerHTML = this.toString("innerHTML");
|
|
189
157
|
return this;
|
|
@@ -351,7 +319,7 @@ export class HTMLElement {
|
|
|
351
319
|
this.textContent = this.toString("innerText");
|
|
352
320
|
this.children.forEach((c) => {
|
|
353
321
|
if (c.children) {
|
|
354
|
-
child = c.children.find((child) => {
|
|
322
|
+
child = c.children.find((child) => {
|
|
355
323
|
child.outerHTML = child.toString("outerHTML");
|
|
356
324
|
child.innerHTML = child.toString("innerHTML");
|
|
357
325
|
return child.tagName === selector;
|
|
@@ -439,9 +407,6 @@ export class Document {
|
|
|
439
407
|
* @returns {HTMLElement}
|
|
440
408
|
*/
|
|
441
409
|
createElement(nodeData) {
|
|
442
|
-
if(!nodeData){
|
|
443
|
-
return new HTMLElement("div", {}, [])
|
|
444
|
-
}
|
|
445
410
|
if (typeof nodeData === 'string') {
|
|
446
411
|
return new HTMLElement(nodeData, {}, [])
|
|
447
412
|
}
|
|
@@ -561,17 +526,7 @@ function handleStyles(styles, nodeEl) {
|
|
|
561
526
|
*/
|
|
562
527
|
export function Element(tag, props = {}, ...children) {
|
|
563
528
|
if(typeof tag === 'function'){
|
|
564
|
-
let
|
|
565
|
-
if (child.tagName === "TEXT_ELEMENT") {
|
|
566
|
-
return new HTMLTextNode(child);
|
|
567
|
-
}
|
|
568
|
-
if (child instanceof HTMLElement) {
|
|
569
|
-
return child;
|
|
570
|
-
}
|
|
571
|
-
return new HTMLElement(child.tagName, child.props, child.children);
|
|
572
|
-
})
|
|
573
|
-
childObj = childObj[0]
|
|
574
|
-
let el = tag({...props, children: childObj})
|
|
529
|
+
let el = tag(props, children)
|
|
575
530
|
return el
|
|
576
531
|
}
|
|
577
532
|
if(props === null){
|
|
@@ -637,12 +592,9 @@ export function Element(tag, props = {}, ...children) {
|
|
|
637
592
|
|
|
638
593
|
node.children = children
|
|
639
594
|
delete props.children
|
|
640
|
-
}
|
|
595
|
+
}
|
|
596
|
+
|
|
641
597
|
for (var i = 0; i < children.length; i++) {
|
|
642
|
-
if(typeof children[i] === 'undefined'){
|
|
643
|
-
delete children[i]
|
|
644
|
-
continue;
|
|
645
|
-
}
|
|
646
598
|
if (typeof children[i] === "string" || typeof children[i] === "number") {
|
|
647
599
|
children[i] = {
|
|
648
600
|
tagName: "TEXT_ELEMENT",
|
|
@@ -655,7 +607,7 @@ export function Element(tag, props = {}, ...children) {
|
|
|
655
607
|
} else {
|
|
656
608
|
if (children[i]) {
|
|
657
609
|
children[i].parentNode = { tagName: tag, props: props, children: children };
|
|
658
|
-
}
|
|
610
|
+
}
|
|
659
611
|
|
|
660
612
|
children[i] = new HTMLElement(children[i].tagName, children[i].props, children[i].children)
|
|
661
613
|
}
|
|
@@ -1 +1,432 @@
|
|
|
1
|
-
window.vader
|
|
1
|
+
window.vader = {
|
|
2
|
+
version: '1.0.0'
|
|
3
|
+
}
|
|
4
|
+
globalThis.isServer = false
|
|
5
|
+
window.hasRan = []
|
|
6
|
+
globalThis.memoizedFunctions = []
|
|
7
|
+
const memoizedRefs = []
|
|
8
|
+
/**
|
|
9
|
+
* @description This function is used to calculate the difference between two nodes - and return the elements in which the difference is found
|
|
10
|
+
* @param {HTMLElement} oldNode
|
|
11
|
+
* @param {HTMLElement} newNode
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
14
|
+
function calculateDiff(oldNode, newNode){
|
|
15
|
+
if(oldNode === undefined || newNode === undefined){
|
|
16
|
+
return []
|
|
17
|
+
}
|
|
18
|
+
let diff = []
|
|
19
|
+
if(oldNode?.children.length > 0){
|
|
20
|
+
for(var i = 0; i < oldNode.children.length; i++){
|
|
21
|
+
diff.push(...calculateDiff(oldNode.children[i], newNode.children[i]))
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
return diff
|
|
25
|
+
}
|
|
26
|
+
if(!oldNode?._isRoot){
|
|
27
|
+
if(oldNode.nodeType === 3 && oldNode.nodeValue !== newNode.nodeValue){
|
|
28
|
+
diff.push({type: 'REPLACE', oldNode, newNode})
|
|
29
|
+
}
|
|
30
|
+
else if(oldNode.nodeType === 1 && oldNode.innerHTML !== newNode.innerHTML
|
|
31
|
+
){
|
|
32
|
+
diff.push({type: 'REPLACE', oldNode, newNode})
|
|
33
|
+
}
|
|
34
|
+
else if(oldNode.nodeType === 1 && oldNode.tagName === newNode.tagName){
|
|
35
|
+
for(var i = 0; i < oldNode.attributes.length; i++){
|
|
36
|
+
if(oldNode.attributes[i].value !== newNode.attributes[i].value){
|
|
37
|
+
diff.push({type: 'PROPS', oldNode, newNode})
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
return diff
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @description This function is used to generate functonal components
|
|
50
|
+
* @param {Function} tag
|
|
51
|
+
* @param {Object} props
|
|
52
|
+
* @param {...any} children
|
|
53
|
+
* @returns {Object} - The first child of the functional component
|
|
54
|
+
*/
|
|
55
|
+
function generateJSX(tag, props, ...children){
|
|
56
|
+
let node = {
|
|
57
|
+
state: {},
|
|
58
|
+
mainFunction: tag,
|
|
59
|
+
_key: tag.name || Math.random().toString(36).substring(7),
|
|
60
|
+
$$typeof: 'JSX_CHILD',
|
|
61
|
+
firstChild:null,
|
|
62
|
+
children: children,
|
|
63
|
+
_name: tag.name,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
node.firstChild = tag()
|
|
67
|
+
node.firstChild.htmlNode._key = node._key
|
|
68
|
+
node.firstChild.htmlRoot = node
|
|
69
|
+
node.firstChild.htmlNode._isRoot = true
|
|
70
|
+
node.firstChild.props = props || {}
|
|
71
|
+
node.firstChild._isRoot = true
|
|
72
|
+
node.firstChild._key = node._key
|
|
73
|
+
node.firstChild.props['key'] = node._key
|
|
74
|
+
return node.firstChild
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
function handleStyles(styles, nodeEl) {
|
|
79
|
+
|
|
80
|
+
for (let key in styles) {
|
|
81
|
+
if(typeof styles[key] === 'object'){
|
|
82
|
+
handleStyles(styles[key], nodeEl)
|
|
83
|
+
}
|
|
84
|
+
nodeEl.style[key] = styles[key];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
let hasBeenCalled = []
|
|
91
|
+
/**
|
|
92
|
+
* @description Create a virtual DOM element
|
|
93
|
+
* @param {string | Function} tag
|
|
94
|
+
* @param {Object} props
|
|
95
|
+
* @param {...any} children
|
|
96
|
+
* @returns {Object} - The virtual DOM element
|
|
97
|
+
*/
|
|
98
|
+
function Element(tag, props, ...children){
|
|
99
|
+
!props ? props = {} : null
|
|
100
|
+
if(!props?.['$$key']){
|
|
101
|
+
props['$$key'] = tag.name || Math.random().toString(36).substring(7)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if(typeof tag === 'function'){
|
|
105
|
+
return generateJSX(tag, props, children)
|
|
106
|
+
}
|
|
107
|
+
let node = {
|
|
108
|
+
tag: tag,
|
|
109
|
+
props: props,
|
|
110
|
+
children: children,
|
|
111
|
+
_key: props['$$key'],
|
|
112
|
+
events: [],
|
|
113
|
+
staticEl: document.createElement(tag),
|
|
114
|
+
parentNode: null
|
|
115
|
+
}
|
|
116
|
+
for(var i = 0; i < children.length; i++){
|
|
117
|
+
if(typeof children[i] === 'string' || typeof children[i] === 'number'){
|
|
118
|
+
children[i] = {
|
|
119
|
+
tag: 'TEXT_ELEMENT',
|
|
120
|
+
props: {nodeValue: children[i]},
|
|
121
|
+
_key: props['$$key'],
|
|
122
|
+
parentNode: {tag: tag, props: props, children: children, _key: props['$$key']},
|
|
123
|
+
children: []
|
|
124
|
+
}
|
|
125
|
+
}else{
|
|
126
|
+
if(children[i]){
|
|
127
|
+
children[i].parentNode = {tag: tag, props: props, children: children}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
let nodeEl = node.tag === 'TEXT_ELEMENT' ? document.createTextNode('') : document.createElement(node.tag)
|
|
132
|
+
node.staticEl = nodeEl
|
|
133
|
+
|
|
134
|
+
for(var key in props){
|
|
135
|
+
if(key.toLowerCase().startsWith('on')){
|
|
136
|
+
nodeEl.addEventListener(key.substring(2).toLowerCase(), props[key])
|
|
137
|
+
node.events.push({type: key.substring(2).toLowerCase(), listener: props[key]})
|
|
138
|
+
continue
|
|
139
|
+
}
|
|
140
|
+
if(key === '$$key' && !nodeEl._key && nodeEl.nodeType === 1
|
|
141
|
+
){
|
|
142
|
+
Object.defineProperty(nodeEl, '_key', {
|
|
143
|
+
value: props[key],
|
|
144
|
+
writable: true
|
|
145
|
+
})
|
|
146
|
+
continue
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if(nodeEl && nodeEl.nodeType === 1){
|
|
150
|
+
nodeEl.setAttribute(key, props[key])
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
}
|
|
154
|
+
if(props.style){
|
|
155
|
+
handleStyles(props.style, nodeEl)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if(props.id){
|
|
159
|
+
nodeEl.id = props.id
|
|
160
|
+
}
|
|
161
|
+
if(props.ref){
|
|
162
|
+
switch(true){
|
|
163
|
+
case Array.isArray(props.ref.current):
|
|
164
|
+
if(!props.ref.current.find((el) => el === nodeEl)){
|
|
165
|
+
props.ref.current.push(nodeEl)
|
|
166
|
+
}
|
|
167
|
+
break;
|
|
168
|
+
case props.ref.current === HTMLElement:
|
|
169
|
+
props.ref.current = nodeEl
|
|
170
|
+
break;
|
|
171
|
+
case props.ref.current === null:
|
|
172
|
+
props.ref.current = nodeEl
|
|
173
|
+
break;
|
|
174
|
+
case typeof props.ref === 'function' && !window.hasRan.includes(props.ref):
|
|
175
|
+
window.hasRan.push(props.ref)
|
|
176
|
+
props.ref(nodeEl)
|
|
177
|
+
setTimeout(() => {
|
|
178
|
+
window.hasRan.filter((el) => el !== props.ref)
|
|
179
|
+
}, 0)
|
|
180
|
+
break;
|
|
181
|
+
default:
|
|
182
|
+
props.ref.current = nodeEl
|
|
183
|
+
break;
|
|
184
|
+
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
node['htmlNode'] = nodeEl
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
if(nodeEl.nodeType === 1){
|
|
191
|
+
for(var i = 0; i < children.length; i++){
|
|
192
|
+
if(children[i]){
|
|
193
|
+
if(children[i].tag === 'TEXT_ELEMENT'){
|
|
194
|
+
nodeEl.appendChild(document.createTextNode(children[i].props.nodeValue))
|
|
195
|
+
}
|
|
196
|
+
nodeEl.appendChild(Element(children[i].tag, children[i].props, ...children[i].children).htmlNode)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return node;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
function handleDiff(diff){
|
|
207
|
+
for(var i = 0; i < diff.length; i++){
|
|
208
|
+
switch(true){
|
|
209
|
+
case diff[i].type === 'REPLACE' && !diff[i].oldNode._isRoot:
|
|
210
|
+
let parent = diff[i].oldNode.parentNode
|
|
211
|
+
diff[i].oldNode.parentNode.replaceChild(diff[i].newNode, diff[i].oldNode)
|
|
212
|
+
break;
|
|
213
|
+
case diff[i].type === 'PROPS':
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
}
|
|
219
|
+
let states = {}
|
|
220
|
+
export const useState = (name, initialValue) => {}
|
|
221
|
+
export function useRef(name, initialValue){
|
|
222
|
+
let ref = initialValue
|
|
223
|
+
if(!memoizedRefs.find((el) => el.name === name)){
|
|
224
|
+
memoizedRefs.push({name, ref})
|
|
225
|
+
}
|
|
226
|
+
let getRef = () => memoizedRefs.find((el) => el.name === name).ref
|
|
227
|
+
let setRef = (newValue) => {
|
|
228
|
+
memoizedRefs.find((el) => el.name === name).ref = newValue
|
|
229
|
+
}
|
|
230
|
+
return {
|
|
231
|
+
current: getRef(),
|
|
232
|
+
name,
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
export function Mounted(fn, node){
|
|
236
|
+
let el = Array.from(document.querySelectorAll('*')).find((el) => el._key === memoizedFunctions.find((el) => el.mainFunction === node)._key)
|
|
237
|
+
if(el && !hasBeenCalled.find((el) => el === node)){
|
|
238
|
+
fn()
|
|
239
|
+
hasBeenCalled.push(node)
|
|
240
|
+
}
|
|
241
|
+
else{
|
|
242
|
+
setTimeout(() => {
|
|
243
|
+
Mounted(fn, node)
|
|
244
|
+
}, 0)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
let effects = [];
|
|
250
|
+
|
|
251
|
+
export function useEffect(fn, deps){
|
|
252
|
+
if(!effects.find((el) => el.fn.toString() === fn.toString())){
|
|
253
|
+
effects.push({fn, deps})
|
|
254
|
+
}
|
|
255
|
+
else{
|
|
256
|
+
let effect = effects.find((el) => el.fn.toString() === fn.toString())
|
|
257
|
+
if(effect.deps.toString() !== deps.toString()){
|
|
258
|
+
effect.deps = deps
|
|
259
|
+
effect.fn()
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return () => {
|
|
263
|
+
effects = effects.filter((el) => el.fn !== fn)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
}
|
|
267
|
+
export function useReducer(name, reducer, vnode, initialState){
|
|
268
|
+
let [state, setState] = useState(name, vnode, initialState)
|
|
269
|
+
let dispatch = (action) => {
|
|
270
|
+
let newState = reducer(state, action)
|
|
271
|
+
setState(newState)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return [state, dispatch]
|
|
275
|
+
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
class Component {
|
|
279
|
+
constructor(props){
|
|
280
|
+
this.props = props
|
|
281
|
+
this._key = props['$$key'] || Math.random().toString(36).substring(7)
|
|
282
|
+
this.state = {}
|
|
283
|
+
this.htmlNode = null
|
|
284
|
+
this.firstChild = null
|
|
285
|
+
this.Element = Element
|
|
286
|
+
this.effects = []
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
setState(newState){
|
|
291
|
+
this.state = newState
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
handleDiff(diff){
|
|
295
|
+
for(var i = 0; i < diff.length; i++){
|
|
296
|
+
switch(true){
|
|
297
|
+
case diff[i].type === 'REPLACE' && !diff[i].oldNode._isRoot:
|
|
298
|
+
let parent = diff[i].oldNode.parentNode
|
|
299
|
+
diff[i].oldNode.parentNode.replaceChild(diff[i].newNode, diff[i].oldNode)
|
|
300
|
+
break;
|
|
301
|
+
case diff[i].type === 'PROPS':
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
calculateDiff(oldNode, newNode){
|
|
307
|
+
if(oldNode === undefined || newNode === undefined){
|
|
308
|
+
return []
|
|
309
|
+
}
|
|
310
|
+
let diff = []
|
|
311
|
+
if(oldNode?.children.length > 0){
|
|
312
|
+
for(var i = 0; i < oldNode.children.length; i++){
|
|
313
|
+
diff.push(...this.calculateDiff(oldNode.children[i], newNode.children[i]))
|
|
314
|
+
|
|
315
|
+
}
|
|
316
|
+
return diff
|
|
317
|
+
}
|
|
318
|
+
if(!oldNode?._isRoot){
|
|
319
|
+
if(oldNode.nodeType === 3 && oldNode.nodeValue !== newNode.nodeValue){
|
|
320
|
+
diff.push({type: 'REPLACE', oldNode, newNode})
|
|
321
|
+
}
|
|
322
|
+
else if(oldNode.nodeType === 1 && oldNode.innerHTML !== newNode.innerHTML
|
|
323
|
+
){
|
|
324
|
+
diff.push({type: 'REPLACE', oldNode, newNode})
|
|
325
|
+
}
|
|
326
|
+
else if(oldNode.nodeType === 1 && oldNode.tagName === newNode.tagName){
|
|
327
|
+
for(var i = 0; i < oldNode.attributes.length; i++){
|
|
328
|
+
if(oldNode.attributes[i].value !== newNode.attributes[i].value){
|
|
329
|
+
diff.push({type: 'PROPS', oldNode, newNode})
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
return diff
|
|
338
|
+
}
|
|
339
|
+
useEffect(fn, deps){
|
|
340
|
+
if(!this.effects.find((el) => el.fn.toString() === fn.toString())){
|
|
341
|
+
this.effects.push({fn, deps})
|
|
342
|
+
}
|
|
343
|
+
else{
|
|
344
|
+
let effect = this.effects.find((el) => el.fn.toString() === fn.toString())
|
|
345
|
+
if(effect.deps.toString() !== deps.toString()){
|
|
346
|
+
effect.deps = deps
|
|
347
|
+
effect.fn()
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return () => {
|
|
351
|
+
this.effects = this.effects.filter((el) => el.fn !== fn)
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
useState(name, initialValue){
|
|
355
|
+
if(!this.state[name]){
|
|
356
|
+
this.state[name] = initialValue
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
let getState = () => this.state[name]
|
|
360
|
+
let setState = (newValue) => {
|
|
361
|
+
let dEl = this.firstChild.htmlNode
|
|
362
|
+
if(dEl.tagName === 'HTML'){
|
|
363
|
+
let firstChild = dEl.querySelector('body').firstChild
|
|
364
|
+
dEl = firstChild
|
|
365
|
+
}
|
|
366
|
+
this.state[name] = newValue
|
|
367
|
+
let el = Array.from(document.querySelectorAll('*')).find((el) =>{
|
|
368
|
+
return el._key === dEl._key
|
|
369
|
+
})
|
|
370
|
+
let diff = calculateDiff(el, this.render().htmlNode.tagName === 'HTML' ? this.render().htmlNode.querySelector('body').firstChild : this.render().htmlNode)
|
|
371
|
+
handleDiff(diff)
|
|
372
|
+
|
|
373
|
+
}
|
|
374
|
+
return [getState, setState]
|
|
375
|
+
|
|
376
|
+
}
|
|
377
|
+
useReducer(name, reducer, initialState){
|
|
378
|
+
let [state, setState] = this.useState(name, initialState)
|
|
379
|
+
let dispatch = (action) => {
|
|
380
|
+
let newState = reducer(state(), action)
|
|
381
|
+
setState(newState)
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
return [state, dispatch]
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
render(){
|
|
388
|
+
return null
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export async function render(vnode, container, ...passProps){
|
|
394
|
+
|
|
395
|
+
if(!vnode){
|
|
396
|
+
throw new Error('No vnode was provided')
|
|
397
|
+
}
|
|
398
|
+
// create an object for the node then bind to firstChild
|
|
399
|
+
let comp = new Component({$$key: vnode.name || Math.random().toString(36).substring(7)})
|
|
400
|
+
vnode = vnode.bind(comp)
|
|
401
|
+
comp.render = () => {
|
|
402
|
+
return vnode(...passProps)
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
comp.firstChild = comp.render()
|
|
406
|
+
|
|
407
|
+
if(comp.firstChild.htmlNode.tagName === 'HTML'){
|
|
408
|
+
let hasHead = comp.firstChild.htmlNode.querySelector('head') ? true : false
|
|
409
|
+
let hasBody = comp.firstChild.htmlNode.querySelector('body') ? true : false
|
|
410
|
+
|
|
411
|
+
if(hasHead){
|
|
412
|
+
document.head.innerHTML = comp.firstChild.htmlNode.querySelector('head').innerHTML
|
|
413
|
+
comp.firstChild.children = comp.firstChild.children.filter((el) =>{
|
|
414
|
+
return el.htmlNode.tagName !== 'HEAD'
|
|
415
|
+
})
|
|
416
|
+
}
|
|
417
|
+
if(hasBody){
|
|
418
|
+
comp.firstChild.children = comp.firstChild.children.filter((el) =>{
|
|
419
|
+
if(el.htmlNode.tagName == 'BODY'){
|
|
420
|
+
comp.firstChild = el.children[0]
|
|
421
|
+
}
|
|
422
|
+
})
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
container.innerHTML = ''
|
|
426
|
+
|
|
427
|
+
container.appendChild(comp.firstChild.htmlNode)
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
export default Element
|