6
6
assign ,
7
7
getChildren
8
8
} from './util' ;
9
- import { options , Fragment , createElement } from 'preact' ;
9
+ import { options , Fragment } from 'preact' ;
10
+
11
+ /** @typedef {import('preact').VNode } VNode */
10
12
11
13
const SHALLOW = { shallow : true } ;
12
14
@@ -28,7 +30,7 @@ const noop = () => {};
28
30
* @param {Boolean } [options.shallow=false] If `true`, renders nested Components as HTML elements (`<Foo a="b" />`).
29
31
* @param {Boolean } [options.xml=false] If `true`, uses self-closing tags for elements without children.
30
32
* @param {Boolean } [options.pretty=false] If `true`, adds whitespace for readability
31
- * @param {RegEx |undefined } [options.voidElements] RegeEx that matches elements that are considered void (self-closing)
33
+ * @param {RegExp |undefined } [options.voidElements] RegeEx that matches elements that are considered void (self-closing)
32
34
*/
33
35
renderToString . render = renderToString ;
34
36
@@ -43,6 +45,8 @@ let shallowRender = (vnode, context) => renderToString(vnode, context, SHALLOW);
43
45
44
46
const EMPTY_ARR = [ ] ;
45
47
function renderToString ( vnode , context , opts ) {
48
+ context = context || { } ;
49
+ opts = opts || { } ;
46
50
const res = _renderToString ( vnode , context , opts ) ;
47
51
// options._commit, we don't schedule any effects in this library right now,
48
52
// so we can pass an empty queue to this hook.
@@ -56,48 +60,50 @@ function _renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
56
60
return '' ;
57
61
}
58
62
59
- // wrap array nodes in Fragment
60
- if ( Array . isArray ( vnode ) ) {
61
- vnode = createElement ( Fragment , null , vnode ) ;
63
+ // #text nodes
64
+ if ( typeof vnode !== 'object' ) {
65
+ return encodeEntities ( vnode ) ;
62
66
}
63
67
64
- let nodeName = vnode . type ,
65
- props = vnode . props ,
66
- isComponent = false ;
67
- context = context || { } ;
68
- opts = opts || { } ;
69
-
70
68
let pretty = opts . pretty ,
71
69
indentChar = pretty && typeof pretty === 'string' ? pretty : '\t' ;
72
70
73
- // #text nodes
74
- if ( typeof vnode !== 'object' && ! nodeName ) {
75
- return encodeEntities ( vnode ) ;
71
+ if ( Array . isArray ( vnode ) ) {
72
+ let rendered = '' ;
73
+ for ( let i = 0 ; i < vnode . length ; i ++ ) {
74
+ if ( pretty && i > 0 ) rendered += '\n' ;
75
+ rendered += _renderToString (
76
+ vnode [ i ] ,
77
+ context ,
78
+ opts ,
79
+ inner ,
80
+ isSvgMode ,
81
+ selectValue
82
+ ) ;
83
+ }
84
+ return rendered ;
76
85
}
77
86
87
+ let nodeName = vnode . type ,
88
+ props = vnode . props ,
89
+ isComponent = false ;
90
+
78
91
// components
79
92
if ( typeof nodeName === 'function' ) {
80
93
isComponent = true ;
81
94
if ( opts . shallow && ( inner || opts . renderRootComponent === false ) ) {
82
95
nodeName = getComponentName ( nodeName ) ;
83
96
} else if ( nodeName === Fragment ) {
84
- let rendered = '' ;
85
- let children = [ ] ;
97
+ const children = [ ] ;
86
98
getChildren ( children , vnode . props . children ) ;
87
-
88
- for ( let i = 0 ; i < children . length ; i ++ ) {
89
- rendered +=
90
- ( i > 0 && pretty ? '\n' : '' ) +
91
- _renderToString (
92
- children [ i ] ,
93
- context ,
94
- opts ,
95
- opts . shallowHighOrder !== false ,
96
- isSvgMode ,
97
- selectValue
98
- ) ;
99
- }
100
- return rendered ;
99
+ return _renderToString (
100
+ children ,
101
+ context ,
102
+ opts ,
103
+ opts . shallowHighOrder !== false ,
104
+ isSvgMode ,
105
+ selectValue
106
+ ) ;
101
107
} else {
102
108
let rendered ;
103
109
@@ -197,7 +203,7 @@ function _renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
197
203
}
198
204
199
205
// render JSX to HTML
200
- let s = '' ,
206
+ let s = '<' + nodeName ,
201
207
propChildren ,
202
208
html ;
203
209
@@ -215,7 +221,7 @@ function _renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
215
221
continue ;
216
222
}
217
223
218
- if ( name . match ( / [ \s \n \\ / = ' " \0 < > ] / ) ) continue ;
224
+ if ( UNSAFE_NAME . test ( name ) ) continue ;
219
225
220
226
if (
221
227
! ( opts && opts . allAttributes ) &&
@@ -287,18 +293,19 @@ function _renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
287
293
288
294
// account for >1 multiline attribute
289
295
if ( pretty ) {
290
- let sub = s . replace ( / ^ \n \s * / , ' ' ) ;
296
+ let sub = s . replace ( / \n \s * / , ' ' ) ;
291
297
if ( sub !== s && ! ~ sub . indexOf ( '\n' ) ) s = sub ;
292
298
else if ( pretty && ~ s . indexOf ( '\n' ) ) s += '\n' ;
293
299
}
294
300
295
- s = `<${ nodeName } ${ s } >` ;
296
- if ( UNSAFE_NAME . test ( String ( nodeName ) ) )
301
+ s += '>' ;
302
+
303
+ if ( UNSAFE_NAME . test ( nodeName ) )
297
304
throw new Error ( `${ nodeName } is not a valid HTML tag name in ${ s } ` ) ;
298
305
299
306
let isVoid =
300
- VOID_ELEMENTS . test ( String ( nodeName ) ) ||
301
- ( opts . voidElements && opts . voidElements . test ( String ( nodeName ) ) ) ;
307
+ VOID_ELEMENTS . test ( nodeName ) ||
308
+ ( opts . voidElements && opts . voidElements . test ( nodeName ) ) ;
302
309
let pieces = [ ] ;
303
310
304
311
let children ;
0 commit comments