@b9g/crank 0.5.6 → 0.6.0
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 +225 -22
- package/crank.cjs +2009 -1981
- package/crank.cjs.map +1 -1
- package/crank.d.ts +489 -486
- package/crank.js +2009 -1981
- package/crank.js.map +1 -1
- package/dom.cjs +296 -289
- package/dom.cjs.map +1 -1
- package/dom.d.ts +14 -14
- package/dom.js +296 -289
- package/dom.js.map +1 -1
- package/html.cjs +149 -136
- package/html.cjs.map +1 -1
- package/html.d.ts +17 -17
- package/html.js +149 -136
- package/html.js.map +1 -1
- package/jsx-runtime.cjs +13 -8
- package/jsx-runtime.cjs.map +1 -1
- package/jsx-runtime.d.ts +6 -5
- package/jsx-runtime.js +13 -9
- package/jsx-runtime.js.map +1 -1
- package/jsx-tag.cjs +421 -421
- package/jsx-tag.cjs.map +1 -1
- package/jsx-tag.d.ts +2 -2
- package/jsx-tag.js +421 -421
- package/jsx-tag.js.map +1 -1
- package/package.json +16 -16
- package/standalone.d.ts +2 -2
- package/umd.d.ts +3 -3
- package/umd.js +2451 -2403
- package/umd.js.map +1 -1
package/dom.js
CHANGED
|
@@ -1,295 +1,302 @@
|
|
|
1
1
|
/// <reference types="dom.d.ts" />
|
|
2
2
|
import { Portal, Renderer } from './crank.js';
|
|
3
3
|
|
|
4
|
-
const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
5
|
-
const impl = {
|
|
6
|
-
scope(xmlns, tag, props) {
|
|
7
|
-
switch (tag) {
|
|
8
|
-
case Portal:
|
|
9
|
-
xmlns = undefined;
|
|
10
|
-
break;
|
|
11
|
-
case "svg":
|
|
12
|
-
xmlns = SVG_NAMESPACE;
|
|
13
|
-
break;
|
|
14
|
-
}
|
|
15
|
-
return props.xmlns || xmlns;
|
|
16
|
-
},
|
|
17
|
-
create(tag, _props, xmlns) {
|
|
18
|
-
if (typeof tag !== "string") {
|
|
19
|
-
throw new Error(`Unknown tag: ${tag.toString()}`);
|
|
20
|
-
}
|
|
21
|
-
else if (tag.toLowerCase() === "svg") {
|
|
22
|
-
xmlns = SVG_NAMESPACE;
|
|
23
|
-
}
|
|
24
|
-
return xmlns
|
|
25
|
-
? document.createElementNS(xmlns, tag)
|
|
26
|
-
: document.createElement(tag);
|
|
27
|
-
},
|
|
28
|
-
hydrate(tag, node, props) {
|
|
29
|
-
if (typeof tag !== "string" && tag !== Portal) {
|
|
30
|
-
throw new Error(`Unknown tag: ${tag.toString()}`);
|
|
31
|
-
}
|
|
32
|
-
if (typeof tag === "string" &&
|
|
33
|
-
tag.toUpperCase() !== node.tagName) {
|
|
34
|
-
// TODO: consider pros and cons of hydration warnings
|
|
35
|
-
//console.error(`Expected <${tag}> while hydrating but found:`, node);
|
|
36
|
-
return undefined;
|
|
37
|
-
}
|
|
38
|
-
const children = [];
|
|
39
|
-
for (let i = 0; i < node.childNodes.length; i++) {
|
|
40
|
-
const child = node.childNodes[i];
|
|
41
|
-
if (child.nodeType === Node.TEXT_NODE) {
|
|
42
|
-
children.push(child.data);
|
|
43
|
-
}
|
|
44
|
-
else if (child.nodeType === Node.ELEMENT_NODE) {
|
|
45
|
-
children.push(child);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
// TODO: extract props from nodes
|
|
49
|
-
return { props, children };
|
|
50
|
-
},
|
|
51
|
-
patch(_tag,
|
|
52
|
-
// TODO: Why does this assignment work?
|
|
53
|
-
node, name,
|
|
54
|
-
// TODO: Stricter typings?
|
|
55
|
-
value, oldValue, xmlns) {
|
|
56
|
-
const isSVG = xmlns === SVG_NAMESPACE;
|
|
57
|
-
switch (name) {
|
|
58
|
-
case "style": {
|
|
59
|
-
const style = node.style;
|
|
60
|
-
if (style == null) {
|
|
61
|
-
node.setAttribute("style", value);
|
|
62
|
-
}
|
|
63
|
-
else if (value == null || value === false) {
|
|
64
|
-
node.removeAttribute("style");
|
|
65
|
-
}
|
|
66
|
-
else if (value === true) {
|
|
67
|
-
node.setAttribute("style", "");
|
|
68
|
-
}
|
|
69
|
-
else if (typeof value === "string") {
|
|
70
|
-
if (style.cssText !== value) {
|
|
71
|
-
style.cssText = value;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
if (typeof oldValue === "string") {
|
|
76
|
-
style.cssText = "";
|
|
77
|
-
}
|
|
78
|
-
for (const styleName in { ...oldValue, ...value }) {
|
|
79
|
-
const styleValue = value && value[styleName];
|
|
80
|
-
if (styleValue == null) {
|
|
81
|
-
style.removeProperty(styleName);
|
|
82
|
-
}
|
|
83
|
-
else if (style.getPropertyValue(styleName) !== styleValue) {
|
|
84
|
-
style.setProperty(styleName, styleValue);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
case "class":
|
|
91
|
-
case "className":
|
|
92
|
-
if (value === true) {
|
|
93
|
-
node.setAttribute("class", "");
|
|
94
|
-
}
|
|
95
|
-
else if (value == null) {
|
|
96
|
-
node.removeAttribute("class");
|
|
97
|
-
}
|
|
98
|
-
else if (!isSVG) {
|
|
99
|
-
if (node.className !== value) {
|
|
100
|
-
node["className"] = value;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
else if (node.getAttribute("class") !== value) {
|
|
104
|
-
node.setAttribute("class", value);
|
|
105
|
-
}
|
|
106
|
-
break;
|
|
107
|
-
case "innerHTML":
|
|
108
|
-
if (value !== oldValue) {
|
|
109
|
-
node.innerHTML = value;
|
|
110
|
-
}
|
|
111
|
-
break;
|
|
112
|
-
default: {
|
|
113
|
-
if (name
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
if (
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
4
|
+
const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
5
|
+
const impl = {
|
|
6
|
+
scope(xmlns, tag, props) {
|
|
7
|
+
switch (tag) {
|
|
8
|
+
case Portal:
|
|
9
|
+
xmlns = undefined;
|
|
10
|
+
break;
|
|
11
|
+
case "svg":
|
|
12
|
+
xmlns = SVG_NAMESPACE;
|
|
13
|
+
break;
|
|
14
|
+
}
|
|
15
|
+
return props.xmlns || xmlns;
|
|
16
|
+
},
|
|
17
|
+
create(tag, _props, xmlns) {
|
|
18
|
+
if (typeof tag !== "string") {
|
|
19
|
+
throw new Error(`Unknown tag: ${tag.toString()}`);
|
|
20
|
+
}
|
|
21
|
+
else if (tag.toLowerCase() === "svg") {
|
|
22
|
+
xmlns = SVG_NAMESPACE;
|
|
23
|
+
}
|
|
24
|
+
return xmlns
|
|
25
|
+
? document.createElementNS(xmlns, tag)
|
|
26
|
+
: document.createElement(tag);
|
|
27
|
+
},
|
|
28
|
+
hydrate(tag, node, props) {
|
|
29
|
+
if (typeof tag !== "string" && tag !== Portal) {
|
|
30
|
+
throw new Error(`Unknown tag: ${tag.toString()}`);
|
|
31
|
+
}
|
|
32
|
+
if (typeof tag === "string" &&
|
|
33
|
+
tag.toUpperCase() !== node.tagName) {
|
|
34
|
+
// TODO: consider pros and cons of hydration warnings
|
|
35
|
+
//console.error(`Expected <${tag}> while hydrating but found:`, node);
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
const children = [];
|
|
39
|
+
for (let i = 0; i < node.childNodes.length; i++) {
|
|
40
|
+
const child = node.childNodes[i];
|
|
41
|
+
if (child.nodeType === Node.TEXT_NODE) {
|
|
42
|
+
children.push(child.data);
|
|
43
|
+
}
|
|
44
|
+
else if (child.nodeType === Node.ELEMENT_NODE) {
|
|
45
|
+
children.push(child);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// TODO: extract props from nodes
|
|
49
|
+
return { props, children };
|
|
50
|
+
},
|
|
51
|
+
patch(_tag,
|
|
52
|
+
// TODO: Why does this assignment work?
|
|
53
|
+
node, name,
|
|
54
|
+
// TODO: Stricter typings?
|
|
55
|
+
value, oldValue, xmlns) {
|
|
56
|
+
const isSVG = xmlns === SVG_NAMESPACE;
|
|
57
|
+
switch (name) {
|
|
58
|
+
case "style": {
|
|
59
|
+
const style = node.style;
|
|
60
|
+
if (style == null) {
|
|
61
|
+
node.setAttribute("style", value);
|
|
62
|
+
}
|
|
63
|
+
else if (value == null || value === false) {
|
|
64
|
+
node.removeAttribute("style");
|
|
65
|
+
}
|
|
66
|
+
else if (value === true) {
|
|
67
|
+
node.setAttribute("style", "");
|
|
68
|
+
}
|
|
69
|
+
else if (typeof value === "string") {
|
|
70
|
+
if (style.cssText !== value) {
|
|
71
|
+
style.cssText = value;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
if (typeof oldValue === "string") {
|
|
76
|
+
style.cssText = "";
|
|
77
|
+
}
|
|
78
|
+
for (const styleName in { ...oldValue, ...value }) {
|
|
79
|
+
const styleValue = value && value[styleName];
|
|
80
|
+
if (styleValue == null) {
|
|
81
|
+
style.removeProperty(styleName);
|
|
82
|
+
}
|
|
83
|
+
else if (style.getPropertyValue(styleName) !== styleValue) {
|
|
84
|
+
style.setProperty(styleName, styleValue);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case "class":
|
|
91
|
+
case "className":
|
|
92
|
+
if (value === true) {
|
|
93
|
+
node.setAttribute("class", "");
|
|
94
|
+
}
|
|
95
|
+
else if (value == null) {
|
|
96
|
+
node.removeAttribute("class");
|
|
97
|
+
}
|
|
98
|
+
else if (!isSVG) {
|
|
99
|
+
if (node.className !== value) {
|
|
100
|
+
node["className"] = value;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else if (node.getAttribute("class") !== value) {
|
|
104
|
+
node.setAttribute("class", value);
|
|
105
|
+
}
|
|
106
|
+
break;
|
|
107
|
+
case "innerHTML":
|
|
108
|
+
if (value !== oldValue) {
|
|
109
|
+
node.innerHTML = value;
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
|
+
default: {
|
|
113
|
+
if (name[0] === "o" &&
|
|
114
|
+
name[1] === "n" &&
|
|
115
|
+
name[2] === name[2].toUpperCase() &&
|
|
116
|
+
typeof value === "function") {
|
|
117
|
+
// Support React-style event names (onClick, onChange, etc.)
|
|
118
|
+
name = name.toLowerCase();
|
|
119
|
+
}
|
|
120
|
+
if (name in node &&
|
|
121
|
+
// boolean properties will coerce strings, but sometimes they map to
|
|
122
|
+
// enumerated attributes, where truthy strings ("false", "no") map to
|
|
123
|
+
// falsy properties, so we use attributes in this case.
|
|
124
|
+
!(typeof value === "string" &&
|
|
125
|
+
typeof node[name] === "boolean")) {
|
|
126
|
+
// walk up the object's prototype chain to find the owner of the
|
|
127
|
+
// named property
|
|
128
|
+
let obj = node;
|
|
129
|
+
do {
|
|
130
|
+
if (Object.prototype.hasOwnProperty.call(obj, name)) {
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
} while ((obj = Object.getPrototypeOf(obj)));
|
|
134
|
+
// get the descriptor for the named property and check whether it
|
|
135
|
+
// implies that the property is writable
|
|
136
|
+
const descriptor = Object.getOwnPropertyDescriptor(obj, name);
|
|
137
|
+
if (descriptor != null &&
|
|
138
|
+
(descriptor.writable === true || descriptor.set !== undefined)) {
|
|
139
|
+
if (node[name] !== value || oldValue === undefined) {
|
|
140
|
+
node[name] = value;
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
// if the property wasn't writable, fall through to the code below
|
|
145
|
+
// which uses setAttribute() instead of assigning directly.
|
|
146
|
+
}
|
|
147
|
+
if (value === true) {
|
|
148
|
+
value = "";
|
|
149
|
+
}
|
|
150
|
+
else if (value == null || value === false) {
|
|
151
|
+
node.removeAttribute(name);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (node.getAttribute(name) !== value) {
|
|
155
|
+
node.setAttribute(name, value);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
arrange(tag, node, props, children, _oldProps, oldChildren) {
|
|
161
|
+
if (tag === Portal && (node == null || typeof node.nodeType !== "number")) {
|
|
162
|
+
throw new TypeError(`Portal root is not a node. Received: ${JSON.stringify(node && node.toString())}`);
|
|
163
|
+
}
|
|
164
|
+
if (!("innerHTML" in props) &&
|
|
165
|
+
// We don’t want to update elements without explicit children (<div/>),
|
|
166
|
+
// because these elements sometimes have child nodes added via raw
|
|
167
|
+
// DOM manipulations.
|
|
168
|
+
// However, if an element has previously rendered children, we clear the
|
|
169
|
+
// them because it would be surprising not to clear Crank managed
|
|
170
|
+
// children, even if the new element does not have explicit children.
|
|
171
|
+
("children" in props || (oldChildren && oldChildren.length))) {
|
|
172
|
+
if (children.length === 0) {
|
|
173
|
+
node.textContent = "";
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
let oldChild = node.firstChild;
|
|
177
|
+
let i = 0;
|
|
178
|
+
while (oldChild !== null && i < children.length) {
|
|
179
|
+
const newChild = children[i];
|
|
180
|
+
if (oldChild === newChild) {
|
|
181
|
+
oldChild = oldChild.nextSibling;
|
|
182
|
+
i++;
|
|
183
|
+
}
|
|
184
|
+
else if (typeof newChild === "string") {
|
|
185
|
+
if (oldChild.nodeType === Node.TEXT_NODE) {
|
|
186
|
+
if (oldChild.data !== newChild) {
|
|
187
|
+
oldChild.data = newChild;
|
|
188
|
+
}
|
|
189
|
+
oldChild = oldChild.nextSibling;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
node.insertBefore(document.createTextNode(newChild), oldChild);
|
|
193
|
+
}
|
|
194
|
+
i++;
|
|
195
|
+
}
|
|
196
|
+
else if (oldChild.nodeType === Node.TEXT_NODE) {
|
|
197
|
+
const nextSibling = oldChild.nextSibling;
|
|
198
|
+
node.removeChild(oldChild);
|
|
199
|
+
oldChild = nextSibling;
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
node.insertBefore(newChild, oldChild);
|
|
203
|
+
i++;
|
|
204
|
+
// TODO: This is an optimization but we need to think a little more about other cases like prepending.
|
|
205
|
+
if (oldChild !== children[i]) {
|
|
206
|
+
const nextSibling = oldChild.nextSibling;
|
|
207
|
+
node.removeChild(oldChild);
|
|
208
|
+
oldChild = nextSibling;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// remove excess DOM nodes
|
|
213
|
+
while (oldChild !== null) {
|
|
214
|
+
const nextSibling = oldChild.nextSibling;
|
|
215
|
+
node.removeChild(oldChild);
|
|
216
|
+
oldChild = nextSibling;
|
|
217
|
+
}
|
|
218
|
+
// append excess children
|
|
219
|
+
for (; i < children.length; i++) {
|
|
220
|
+
const newChild = children[i];
|
|
221
|
+
node.appendChild(typeof newChild === "string"
|
|
222
|
+
? document.createTextNode(newChild)
|
|
223
|
+
: newChild);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
text(text, _scope, hydrationData) {
|
|
229
|
+
if (hydrationData != null) {
|
|
230
|
+
let value = hydrationData.children.shift();
|
|
231
|
+
if (typeof value !== "string" || !value.startsWith(text)) ;
|
|
232
|
+
else if (text.length < value.length) {
|
|
233
|
+
value = value.slice(text.length);
|
|
234
|
+
hydrationData.children.unshift(value);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return text;
|
|
238
|
+
},
|
|
239
|
+
raw(value, xmlns, hydrationData) {
|
|
240
|
+
let result;
|
|
241
|
+
if (typeof value === "string") {
|
|
242
|
+
const el = xmlns == null
|
|
243
|
+
? document.createElement("div")
|
|
244
|
+
: document.createElementNS(xmlns, "svg");
|
|
245
|
+
el.innerHTML = value;
|
|
246
|
+
if (el.childNodes.length === 0) {
|
|
247
|
+
result = undefined;
|
|
248
|
+
}
|
|
249
|
+
else if (el.childNodes.length === 1) {
|
|
250
|
+
result = el.childNodes[0];
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
result = Array.from(el.childNodes);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
result = value;
|
|
258
|
+
}
|
|
259
|
+
if (hydrationData != null) {
|
|
260
|
+
// TODO: maybe we should warn on incorrect values
|
|
261
|
+
if (Array.isArray(result)) {
|
|
262
|
+
for (let i = 0; i < result.length; i++) {
|
|
263
|
+
const node = result[i];
|
|
264
|
+
if (typeof node !== "string" &&
|
|
265
|
+
(node.nodeType === Node.ELEMENT_NODE ||
|
|
266
|
+
node.nodeType === Node.TEXT_NODE)) {
|
|
267
|
+
hydrationData.children.shift();
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
else if (result != null && typeof result !== "string") {
|
|
272
|
+
if (result.nodeType === Node.ELEMENT_NODE ||
|
|
273
|
+
result.nodeType === Node.TEXT_NODE) {
|
|
274
|
+
hydrationData.children.shift();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return result;
|
|
279
|
+
},
|
|
280
|
+
};
|
|
281
|
+
class DOMRenderer extends Renderer {
|
|
282
|
+
constructor() {
|
|
283
|
+
super(impl);
|
|
284
|
+
}
|
|
285
|
+
render(children, root, ctx) {
|
|
286
|
+
validateRoot(root);
|
|
287
|
+
return super.render(children, root, ctx);
|
|
288
|
+
}
|
|
289
|
+
hydrate(children, root, ctx) {
|
|
290
|
+
validateRoot(root);
|
|
291
|
+
return super.hydrate(children, root, ctx);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function validateRoot(root) {
|
|
295
|
+
if (root === null ||
|
|
296
|
+
(typeof root === "object" && typeof root.nodeType !== "number")) {
|
|
297
|
+
throw new TypeError(`Render root is not a node. Received: ${JSON.stringify(root && root.toString())}`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
293
300
|
const renderer = new DOMRenderer();
|
|
294
301
|
|
|
295
302
|
export { DOMRenderer, impl, renderer };
|