preact-render-to-string 6.5.7 → 6.5.9
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/dist/commonjs.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.module.js +1 -1
- package/dist/index.module.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/jsx/commonjs.js +1 -1
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +1 -1
- package/dist/jsx/index.module.js +1 -1
- package/dist/jsx/index.module.js.map +1 -1
- package/dist/jsx/index.umd.js +1 -1
- package/dist/jsx/index.umd.js.map +1 -1
- package/dist/stream/index.js +1 -1
- package/dist/stream/index.js.map +1 -1
- package/dist/stream/index.mjs +1 -1
- package/dist/stream/index.module.js +1 -1
- package/dist/stream/index.module.js.map +1 -1
- package/dist/stream/index.umd.js +1 -1
- package/dist/stream/index.umd.js.map +1 -1
- package/dist/stream/node/index.js +90 -75
- package/dist/stream/node/index.js.map +1 -1
- package/dist/stream/node/index.mjs +90 -75
- package/dist/stream/node/index.module.js +90 -75
- package/dist/stream/node/index.module.js.map +1 -1
- package/dist/stream/node/index.umd.js +90 -75
- package/dist/stream/node/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/index.js +94 -82
- package/src/lib/util.js +5 -5
|
@@ -4,7 +4,7 @@ import { options, h, Fragment } from 'preact';
|
|
|
4
4
|
const UNSAFE_NAME = /[\s\n\\/='"\0<>]/;
|
|
5
5
|
const NAMESPACE_REPLACE_REGEX = /^(xlink|xmlns|xml)([A-Z])/;
|
|
6
6
|
const HTML_LOWER_CASE = /^accessK|^auto[A-Z]|^cell|^ch|^col|cont|cross|dateT|encT|form[A-Z]|frame|hrefL|inputM|maxL|minL|noV|playsI|popoverT|readO|rowS|spellC|src[A-Z]|tabI|useM|item[A-Z]/;
|
|
7
|
-
const SVG_CAMEL_CASE = /^ac|^ali|arabic|basel|cap|clipPath$|clipRule$|color|dominant|enable|fill|flood|font|glyph[^R]|horiz|image|letter|lighting|marker[^WUH]|overline|panose|pointe|paint|rendering|shape|stop|strikethrough|stroke|text[^L]|transform|underline|unicode|units|^v[^i]|^w|^xH/; // DOM properties that should NOT have "px" added when numeric
|
|
7
|
+
const SVG_CAMEL_CASE = /^ac|^ali|arabic|basel|cap|clipPath$|clipRule$|color|dominant|enable|fill|flood|font|glyph[^R]|horiz|image|letter|lighting|marker[^WUH]|overline|panose|pointe|paint|rendering|shape|stop|strikethrough|stroke|spel|text[^L]|transform|underline|unicode|units|^v[^i]|^w|^xH/; // DOM properties that should NOT have "px" added when numeric
|
|
8
8
|
|
|
9
9
|
const ENCODED_ENTITIES = /["&<]/;
|
|
10
10
|
/** @param {string} str */
|
|
@@ -36,13 +36,13 @@ function encodeEntities(str) {
|
|
|
36
36
|
} // Append skipped/buffered characters and the encoded entity:
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
if (i !== last) out
|
|
40
|
-
out
|
|
39
|
+
if (i !== last) out = out + str.slice(last, i);
|
|
40
|
+
out = out + ch; // Start the next seek/buffer after the entity's offset:
|
|
41
41
|
|
|
42
42
|
last = i + 1;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
if (i !== last) out
|
|
45
|
+
if (i !== last) out = out + str.slice(last, i);
|
|
46
46
|
return out;
|
|
47
47
|
}
|
|
48
48
|
const JS_TO_CSS = {};
|
|
@@ -70,6 +70,24 @@ function styleObjToCss(s) {
|
|
|
70
70
|
|
|
71
71
|
return str || undefined;
|
|
72
72
|
}
|
|
73
|
+
|
|
74
|
+
function markAsDirty() {
|
|
75
|
+
this.__d = true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function createComponent(vnode, context) {
|
|
79
|
+
return {
|
|
80
|
+
__v: vnode,
|
|
81
|
+
context,
|
|
82
|
+
props: vnode.props,
|
|
83
|
+
// silently drop state updates
|
|
84
|
+
setState: markAsDirty,
|
|
85
|
+
forceUpdate: markAsDirty,
|
|
86
|
+
__d: true,
|
|
87
|
+
// hooks
|
|
88
|
+
__h: new Array(0)
|
|
89
|
+
};
|
|
90
|
+
} // Necessary for createContext api. Setting this property will pass
|
|
73
91
|
/**
|
|
74
92
|
* @template T
|
|
75
93
|
*/
|
|
@@ -104,9 +122,11 @@ const DIRTY = '__d';
|
|
|
104
122
|
const NEXT_STATE = '__s';
|
|
105
123
|
const CHILD_DID_SUSPEND = '__c';
|
|
106
124
|
|
|
125
|
+
const EMPTY_OBJ = {};
|
|
107
126
|
const EMPTY_ARR = [];
|
|
108
127
|
const isArray = Array.isArray;
|
|
109
|
-
const assign = Object.assign;
|
|
128
|
+
const assign = Object.assign;
|
|
129
|
+
const EMPTY_STR = ''; // Global state for the current render pass
|
|
110
130
|
|
|
111
131
|
let beforeDiff, afterDiff, renderHook, ummountHook;
|
|
112
132
|
/**
|
|
@@ -136,8 +156,8 @@ function renderToString(vnode, context, _rendererState) {
|
|
|
136
156
|
try {
|
|
137
157
|
const rendered = _renderToString(vnode, context || EMPTY_OBJ, false, undefined, parent, false, _rendererState);
|
|
138
158
|
|
|
139
|
-
if (
|
|
140
|
-
return rendered.join(
|
|
159
|
+
if (isArray(rendered)) {
|
|
160
|
+
return rendered.join(EMPTY_STR);
|
|
141
161
|
}
|
|
142
162
|
|
|
143
163
|
return rendered;
|
|
@@ -155,12 +175,6 @@ function renderToString(vnode, context, _rendererState) {
|
|
|
155
175
|
EMPTY_ARR.length = 0;
|
|
156
176
|
}
|
|
157
177
|
}
|
|
158
|
-
|
|
159
|
-
function markAsDirty() {
|
|
160
|
-
this.__d = true;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const EMPTY_OBJ = {};
|
|
164
178
|
/**
|
|
165
179
|
* @param {VNode} vnode
|
|
166
180
|
* @param {Record<string, unknown>} context
|
|
@@ -222,36 +236,40 @@ function renderClassComponent(vnode, context) {
|
|
|
222
236
|
|
|
223
237
|
function _renderToString(vnode, context, isSvgMode, selectValue, parent, asyncMode, renderer) {
|
|
224
238
|
// Ignore non-rendered VNodes/values
|
|
225
|
-
if (vnode == null || vnode === true || vnode === false || vnode ===
|
|
226
|
-
return
|
|
227
|
-
}
|
|
239
|
+
if (vnode == null || vnode === true || vnode === false || vnode === EMPTY_STR) {
|
|
240
|
+
return EMPTY_STR;
|
|
241
|
+
}
|
|
228
242
|
|
|
243
|
+
let vnodeType = typeof vnode; // Text VNodes: escape as HTML
|
|
229
244
|
|
|
230
|
-
if (
|
|
231
|
-
if (
|
|
232
|
-
return encodeEntities(vnode +
|
|
245
|
+
if (vnodeType != 'object') {
|
|
246
|
+
if (vnodeType == 'function') return EMPTY_STR;
|
|
247
|
+
return vnodeType == 'string' ? encodeEntities(vnode) : vnode + EMPTY_STR;
|
|
233
248
|
} // Recurse into children / Arrays
|
|
234
249
|
|
|
235
250
|
|
|
236
251
|
if (isArray(vnode)) {
|
|
237
|
-
let rendered =
|
|
252
|
+
let rendered = EMPTY_STR,
|
|
238
253
|
renderArray;
|
|
239
254
|
parent[CHILDREN] = vnode;
|
|
240
255
|
|
|
241
256
|
for (let i = 0; i < vnode.length; i++) {
|
|
242
257
|
let child = vnode[i];
|
|
243
|
-
if (child == null || typeof child
|
|
258
|
+
if (child == null || typeof child == 'boolean') continue;
|
|
244
259
|
|
|
245
260
|
const childRender = _renderToString(child, context, isSvgMode, selectValue, parent, asyncMode, renderer);
|
|
246
261
|
|
|
247
|
-
if (typeof childRender
|
|
248
|
-
rendered
|
|
262
|
+
if (typeof childRender == 'string') {
|
|
263
|
+
rendered = rendered + childRender;
|
|
249
264
|
} else {
|
|
250
|
-
|
|
265
|
+
if (!renderArray) {
|
|
266
|
+
renderArray = [];
|
|
267
|
+
}
|
|
268
|
+
|
|
251
269
|
if (rendered) renderArray.push(rendered);
|
|
252
|
-
rendered =
|
|
270
|
+
rendered = EMPTY_STR;
|
|
253
271
|
|
|
254
|
-
if (
|
|
272
|
+
if (isArray(childRender)) {
|
|
255
273
|
renderArray.push(...childRender);
|
|
256
274
|
} else {
|
|
257
275
|
renderArray.push(childRender);
|
|
@@ -268,43 +286,44 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent, asyncMo
|
|
|
268
286
|
} // VNodes have {constructor:undefined} to prevent JSON injection:
|
|
269
287
|
|
|
270
288
|
|
|
271
|
-
if (vnode.constructor !== undefined) return
|
|
289
|
+
if (vnode.constructor !== undefined) return EMPTY_STR;
|
|
272
290
|
vnode[PARENT] = parent;
|
|
273
291
|
if (beforeDiff) beforeDiff(vnode);
|
|
274
292
|
let type = vnode.type,
|
|
275
|
-
props = vnode.props
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
293
|
+
props = vnode.props; // Invoke rendering on Components
|
|
294
|
+
|
|
295
|
+
if (typeof type == 'function') {
|
|
296
|
+
let cctx = context,
|
|
297
|
+
contextType,
|
|
298
|
+
rendered,
|
|
299
|
+
component;
|
|
280
300
|
|
|
281
|
-
if (typeof type === 'function') {
|
|
282
301
|
if (type === Fragment) {
|
|
283
302
|
// Serialized precompiled JSX.
|
|
284
|
-
if (props
|
|
285
|
-
let out =
|
|
303
|
+
if ('tpl' in props) {
|
|
304
|
+
let out = EMPTY_STR;
|
|
286
305
|
|
|
287
306
|
for (let i = 0; i < props.tpl.length; i++) {
|
|
288
|
-
out
|
|
307
|
+
out = out + props.tpl[i];
|
|
289
308
|
|
|
290
309
|
if (props.exprs && i < props.exprs.length) {
|
|
291
310
|
const value = props.exprs[i];
|
|
292
311
|
if (value == null) continue; // Check if we're dealing with a vnode or an array of nodes
|
|
293
312
|
|
|
294
|
-
if (typeof value
|
|
295
|
-
out
|
|
313
|
+
if (typeof value == 'object' && (value.constructor === undefined || isArray(value))) {
|
|
314
|
+
out = out + _renderToString(value, context, isSvgMode, selectValue, vnode, asyncMode, renderer);
|
|
296
315
|
} else {
|
|
297
316
|
// Values are pre-escaped by the JSX transform
|
|
298
|
-
out
|
|
317
|
+
out = out + value;
|
|
299
318
|
}
|
|
300
319
|
}
|
|
301
320
|
}
|
|
302
321
|
|
|
303
322
|
return out;
|
|
304
|
-
} else if (props
|
|
323
|
+
} else if ('UNSTABLE_comment' in props) {
|
|
305
324
|
// Fragments are the least used components of core that's why
|
|
306
325
|
// branching here for comments has the least effect on perf.
|
|
307
|
-
return '<!--' + encodeEntities(props.UNSTABLE_comment
|
|
326
|
+
return '<!--' + encodeEntities(props.UNSTABLE_comment) + '-->';
|
|
308
327
|
}
|
|
309
328
|
|
|
310
329
|
rendered = props.children;
|
|
@@ -316,24 +335,17 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent, asyncMo
|
|
|
316
335
|
cctx = provider ? provider.props.value : contextType.__;
|
|
317
336
|
}
|
|
318
337
|
|
|
319
|
-
|
|
338
|
+
let isClassComponent = type.prototype && typeof type.prototype.render == 'function';
|
|
339
|
+
|
|
340
|
+
if (isClassComponent) {
|
|
320
341
|
rendered =
|
|
321
342
|
/**#__NOINLINE__**/
|
|
322
343
|
renderClassComponent(vnode, cctx);
|
|
323
344
|
component = vnode[COMPONENT];
|
|
324
345
|
} else {
|
|
325
|
-
component =
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
context: cctx,
|
|
329
|
-
// silently drop state updates
|
|
330
|
-
setState: markAsDirty,
|
|
331
|
-
forceUpdate: markAsDirty,
|
|
332
|
-
__d: true,
|
|
333
|
-
// hooks
|
|
334
|
-
__h: []
|
|
335
|
-
};
|
|
336
|
-
vnode[COMPONENT] = component; // If a hook invokes setState() to invalidate the component during rendering,
|
|
346
|
+
vnode[COMPONENT] = component =
|
|
347
|
+
/**#__NOINLINE__**/
|
|
348
|
+
createComponent(vnode, cctx); // If a hook invokes setState() to invalidate the component during rendering,
|
|
337
349
|
// re-render it up to 25 times to allow "settling" of memoized states.
|
|
338
350
|
// Note:
|
|
339
351
|
// This will need to be updated for Preact 11 to use internal.flags rather than component._dirty:
|
|
@@ -354,23 +366,21 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent, asyncMo
|
|
|
354
366
|
context = assign({}, context, component.getChildContext());
|
|
355
367
|
}
|
|
356
368
|
|
|
357
|
-
if ((type.getDerivedStateFromError || component.componentDidCatch)
|
|
358
|
-
|
|
369
|
+
if (isClassComponent && options.errorBoundaries && (type.getDerivedStateFromError || component.componentDidCatch)) {
|
|
370
|
+
// When a component returns a Fragment node we flatten it in core, so we
|
|
359
371
|
// need to mirror that logic here too
|
|
360
|
-
|
|
361
|
-
let isTopLevelFragment = rendered != null && rendered.type === Fragment && rendered.key == null;
|
|
372
|
+
let isTopLevelFragment = rendered != null && rendered.type === Fragment && rendered.key == null && rendered.props.tpl == null;
|
|
362
373
|
rendered = isTopLevelFragment ? rendered.props.children : rendered;
|
|
363
374
|
|
|
364
375
|
try {
|
|
365
|
-
|
|
366
|
-
return str;
|
|
376
|
+
return _renderToString(rendered, context, isSvgMode, selectValue, vnode, asyncMode, renderer);
|
|
367
377
|
} catch (err) {
|
|
368
378
|
if (type.getDerivedStateFromError) {
|
|
369
379
|
component[NEXT_STATE] = type.getDerivedStateFromError(err);
|
|
370
380
|
}
|
|
371
381
|
|
|
372
382
|
if (component.componentDidCatch) {
|
|
373
|
-
component.componentDidCatch(err,
|
|
383
|
+
component.componentDidCatch(err, EMPTY_OBJ);
|
|
374
384
|
}
|
|
375
385
|
|
|
376
386
|
if (component[DIRTY]) {
|
|
@@ -381,12 +391,12 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent, asyncMo
|
|
|
381
391
|
context = assign({}, context, component.getChildContext());
|
|
382
392
|
}
|
|
383
393
|
|
|
384
|
-
let isTopLevelFragment = rendered != null && rendered.type === Fragment && rendered.key == null;
|
|
394
|
+
let isTopLevelFragment = rendered != null && rendered.type === Fragment && rendered.key == null && rendered.props.tpl == null;
|
|
385
395
|
rendered = isTopLevelFragment ? rendered.props.children : rendered;
|
|
386
|
-
|
|
396
|
+
return _renderToString(rendered, context, isSvgMode, selectValue, vnode, asyncMode, renderer);
|
|
387
397
|
}
|
|
388
398
|
|
|
389
|
-
return
|
|
399
|
+
return EMPTY_STR;
|
|
390
400
|
} finally {
|
|
391
401
|
if (afterDiff) afterDiff(vnode);
|
|
392
402
|
vnode[PARENT] = null;
|
|
@@ -415,32 +425,33 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent, asyncMo
|
|
|
415
425
|
if (res !== undefined) return res;
|
|
416
426
|
let errorHook = options[CATCH_ERROR];
|
|
417
427
|
if (errorHook) errorHook(error, vnode);
|
|
418
|
-
return
|
|
428
|
+
return EMPTY_STR;
|
|
419
429
|
}
|
|
420
430
|
|
|
421
431
|
if (!asyncMode) throw error;
|
|
422
|
-
if (!error || typeof error.then
|
|
432
|
+
if (!error || typeof error.then != 'function') throw error;
|
|
423
433
|
|
|
424
434
|
const renderNestedChildren = () => {
|
|
425
435
|
try {
|
|
426
436
|
return _renderToString(rendered, context, isSvgMode, selectValue, vnode, asyncMode, renderer);
|
|
427
437
|
} catch (e) {
|
|
428
|
-
if (!e || typeof e.then
|
|
429
|
-
return e.then(() => _renderToString(rendered, context, isSvgMode, selectValue, vnode, asyncMode, renderer),
|
|
438
|
+
if (!e || typeof e.then != 'function') throw e;
|
|
439
|
+
return e.then(() => _renderToString(rendered, context, isSvgMode, selectValue, vnode, asyncMode, renderer), renderNestedChildren);
|
|
430
440
|
}
|
|
431
441
|
};
|
|
432
442
|
|
|
433
|
-
return error.then(
|
|
443
|
+
return error.then(renderNestedChildren);
|
|
434
444
|
}
|
|
435
445
|
} // Serialize Element VNodes to HTML
|
|
436
446
|
|
|
437
447
|
|
|
438
448
|
let s = '<' + type,
|
|
439
|
-
html =
|
|
449
|
+
html = EMPTY_STR,
|
|
440
450
|
children;
|
|
441
451
|
|
|
442
452
|
for (let name in props) {
|
|
443
453
|
let v = props[name];
|
|
454
|
+
if (typeof v == 'function') continue;
|
|
444
455
|
|
|
445
456
|
switch (name) {
|
|
446
457
|
case 'children':
|
|
@@ -531,23 +542,27 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent, asyncMo
|
|
|
531
542
|
// serialize boolean aria-xyz or draggable attribute values as strings
|
|
532
543
|
// `draggable` is an enumerated attribute and not Boolean. A value of `true` or `false` is mandatory
|
|
533
544
|
// https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/draggable
|
|
534
|
-
v
|
|
545
|
+
v = v + EMPTY_STR;
|
|
535
546
|
} else if (isSvgMode) {
|
|
536
547
|
if (SVG_CAMEL_CASE.test(name)) {
|
|
537
548
|
name = name === 'panose1' ? 'panose-1' : name.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
538
549
|
}
|
|
539
550
|
} else if (HTML_LOWER_CASE.test(name)) {
|
|
540
551
|
name = name.toLowerCase();
|
|
552
|
+
|
|
553
|
+
if (name === 'spellcheck') {
|
|
554
|
+
v = '' + v;
|
|
555
|
+
}
|
|
541
556
|
}
|
|
542
557
|
}
|
|
543
558
|
} // write this attribute to the buffer
|
|
544
559
|
|
|
545
560
|
|
|
546
|
-
if (v != null && v !== false
|
|
547
|
-
if (v === true || v ===
|
|
561
|
+
if (v != null && v !== false) {
|
|
562
|
+
if (v === true || v === EMPTY_STR) {
|
|
548
563
|
s = s + ' ' + name;
|
|
549
564
|
} else {
|
|
550
|
-
s = s + ' ' + name + '="' +
|
|
565
|
+
s = s + ' ' + name + '="' + (typeof v == 'string' ? encodeEntities(v) : v + EMPTY_STR) + '"';
|
|
551
566
|
}
|
|
552
567
|
}
|
|
553
568
|
}
|
|
@@ -578,7 +593,7 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent, asyncMo
|
|
|
578
593
|
|
|
579
594
|
const endTag = '</' + type + '>';
|
|
580
595
|
const startTag = s + '>';
|
|
581
|
-
if (
|
|
596
|
+
if (isArray(html)) return [startTag, ...html, endTag];else if (typeof html != 'string') return [startTag, html, endTag];
|
|
582
597
|
return startTag + html + endTag;
|
|
583
598
|
}
|
|
584
599
|
|