6
6
assign ,
7
7
getChildren
8
8
} from './util' ;
9
- import { options , Fragment , createElement } from 'preact' ;
9
+ import { options } 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,40 @@ function _renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
56
60
return '' ;
57
61
}
58
62
63
+ // #text nodes
64
+ if ( typeof vnode !== 'object' ) {
65
+ return encodeEntities ( vnode ) ;
66
+ }
67
+
68
+ let pretty = opts . pretty ,
69
+ indentChar = pretty && typeof pretty === 'string' ? pretty : '\t' ;
70
+
59
71
// wrap array nodes in Fragment
60
72
if ( Array . isArray ( vnode ) ) {
61
- vnode = createElement ( Fragment , null , vnode ) ;
73
+ let rendered = '' ;
74
+ for ( let i = 0 ; i < vnode . length ; i ++ ) {
75
+ if ( pretty && i > 0 ) rendered += '\n' ;
76
+ rendered += _renderToString (
77
+ vnode [ i ] ,
78
+ context ,
79
+ opts ,
80
+ inner ,
81
+ isSvgMode ,
82
+ selectValue
83
+ ) ;
84
+ }
85
+ return rendered ;
62
86
}
63
87
64
88
let nodeName = vnode . type ,
65
89
props = vnode . props ,
66
90
isComponent = false ;
67
- context = context || { } ;
68
- opts = opts || { } ;
69
-
70
- let pretty = opts . pretty ,
71
- indentChar = pretty && typeof pretty === 'string' ? pretty : '\t' ;
72
-
73
- // #text nodes
74
- if ( typeof vnode !== 'object' && ! nodeName ) {
75
- return encodeEntities ( vnode ) ;
76
- }
77
91
78
92
// components
79
93
if ( typeof nodeName === 'function' ) {
80
94
isComponent = true ;
81
95
if ( opts . shallow && ( inner || opts . renderRootComponent === false ) ) {
82
96
nodeName = getComponentName ( nodeName ) ;
83
- } else if ( nodeName === Fragment ) {
84
- let rendered = '' ;
85
- let children = [ ] ;
86
- 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 ;
101
97
} else {
102
98
let rendered ;
103
99
@@ -197,7 +193,7 @@ function _renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
197
193
}
198
194
199
195
// render JSX to HTML
200
- let s = '' ,
196
+ let s = '<' + nodeName ,
201
197
propChildren ,
202
198
html ;
203
199
@@ -215,7 +211,7 @@ function _renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
215
211
continue ;
216
212
}
217
213
218
- if ( name . match ( / [ \s \n \\ / = ' " \0 < > ] / ) ) continue ;
214
+ if ( UNSAFE_NAME . test ( name ) ) continue ;
219
215
220
216
if (
221
217
! ( opts && opts . allAttributes ) &&
@@ -287,18 +283,19 @@ function _renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
287
283
288
284
// account for >1 multiline attribute
289
285
if ( pretty ) {
290
- let sub = s . replace ( / ^ \n \s * / , ' ' ) ;
286
+ let sub = s . replace ( / \n \s * / , ' ' ) ;
291
287
if ( sub !== s && ! ~ sub . indexOf ( '\n' ) ) s = sub ;
292
288
else if ( pretty && ~ s . indexOf ( '\n' ) ) s += '\n' ;
293
289
}
294
290
295
- s = `<${ nodeName } ${ s } >` ;
296
- if ( UNSAFE_NAME . test ( String ( nodeName ) ) )
291
+ s += '>' ;
292
+
293
+ if ( UNSAFE_NAME . test ( nodeName ) )
297
294
throw new Error ( `${ nodeName } is not a valid HTML tag name in ${ s } ` ) ;
298
295
299
296
let isVoid =
300
- VOID_ELEMENTS . test ( String ( nodeName ) ) ||
301
- ( opts . voidElements && opts . voidElements . test ( String ( nodeName ) ) ) ;
297
+ VOID_ELEMENTS . test ( nodeName ) ||
298
+ ( opts . voidElements && opts . voidElements . test ( nodeName ) ) ;
302
299
let pieces = [ ] ;
303
300
304
301
let children ;
0 commit comments