66 assign ,
77 getChildren
88} from './util' ;
9- import { options , Fragment , createElement } from 'preact' ;
9+ import { options , Fragment } from 'preact' ;
10+
11+ /** @typedef {import('preact').VNode } VNode */
1012
1113const SHALLOW = { shallow : true } ;
1214
@@ -28,7 +30,7 @@ const noop = () => {};
2830 * @param {Boolean } [options.shallow=false] If `true`, renders nested Components as HTML elements (`<Foo a="b" />`).
2931 * @param {Boolean } [options.xml=false] If `true`, uses self-closing tags for elements without children.
3032 * @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)
3234 */
3335renderToString . render = renderToString ;
3436
@@ -43,6 +45,8 @@ let shallowRender = (vnode, context) => renderToString(vnode, context, SHALLOW);
4345
4446const EMPTY_ARR = [ ] ;
4547function renderToString ( vnode , context , opts ) {
48+ context = context || { } ;
49+ opts = opts || { } ;
4650 const res = _renderToString ( vnode , context , opts ) ;
4751 // options._commit, we don't schedule any effects in this library right now,
4852 // so we can pass an empty queue to this hook.
@@ -56,48 +60,50 @@ function _renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
5660 return '' ;
5761 }
5862
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 ) ;
6266 }
6367
64- let nodeName = vnode . type ,
65- props = vnode . props ,
66- isComponent = false ;
67- context = context || { } ;
68- opts = opts || { } ;
69-
7068 let pretty = opts . pretty ,
7169 indentChar = pretty && typeof pretty === 'string' ? pretty : '\t' ;
7270
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 ;
7685 }
7786
87+ let nodeName = vnode . type ,
88+ props = vnode . props ,
89+ isComponent = false ;
90+
7891 // components
7992 if ( typeof nodeName === 'function' ) {
8093 isComponent = true ;
8194 if ( opts . shallow && ( inner || opts . renderRootComponent === false ) ) {
8295 nodeName = getComponentName ( nodeName ) ;
8396 } else if ( nodeName === Fragment ) {
84- let rendered = '' ;
85- let children = [ ] ;
97+ const children = [ ] ;
8698 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+ ) ;
101107 } else {
102108 let rendered ;
103109
@@ -197,7 +203,7 @@ function _renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
197203 }
198204
199205 // render JSX to HTML
200- let s = '' ,
206+ let s = '<' + nodeName ,
201207 propChildren ,
202208 html ;
203209
@@ -215,7 +221,7 @@ function _renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
215221 continue ;
216222 }
217223
218- if ( name . match ( / [ \s \n \\ / = ' " \0 < > ] / ) ) continue ;
224+ if ( UNSAFE_NAME . test ( name ) ) continue ;
219225
220226 if (
221227 ! ( opts && opts . allAttributes ) &&
@@ -287,18 +293,19 @@ function _renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
287293
288294 // account for >1 multiline attribute
289295 if ( pretty ) {
290- let sub = s . replace ( / ^ \n \s * / , ' ' ) ;
296+ let sub = s . replace ( / \n \s * / , ' ' ) ;
291297 if ( sub !== s && ! ~ sub . indexOf ( '\n' ) ) s = sub ;
292298 else if ( pretty && ~ s . indexOf ( '\n' ) ) s += '\n' ;
293299 }
294300
295- s = `<${ nodeName } ${ s } >` ;
296- if ( UNSAFE_NAME . test ( String ( nodeName ) ) )
301+ s += '>' ;
302+
303+ if ( UNSAFE_NAME . test ( nodeName ) )
297304 throw new Error ( `${ nodeName } is not a valid HTML tag name in ${ s } ` ) ;
298305
299306 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 ) ) ;
302309 let pieces = [ ] ;
303310
304311 let children ;
0 commit comments