@@ -42,6 +42,9 @@ let escapeChar = a => ESC[a] || a;
4242
4343let falsey = v => v == null || v === false ;
4444
45+ let indent = ( s , char ) => String ( s ) . replace ( / ( \n + ) / g, '$1' + ( char || '\t' ) ) ;
46+
47+ let isLargeString = s => ( String ( s ) . length > 40 || String ( s ) . indexOf ( '\n' ) !== - 1 || String ( s ) . indexOf ( '<' ) !== - 1 ) ;
4548
4649/** Render Preact JSX + Components to an HTML string.
4750 * @name render
@@ -51,6 +54,7 @@ let falsey = v => v==null || v===false;
5154 * @param {Object } [options={}] Rendering options
5255 * @param {Boolean } [options.shallow=false] If `true`, renders nested Components as HTML elements (`<Foo a="b" />`).
5356 * @param {Boolean } [options.xml=false] If `true`, uses self-closing tags for elements without children.
57+ * @param {Boolean } [options.pretty=false] If `true`, adds whitespace for readability
5458 */
5559renderToString . render = renderToString ;
5660
@@ -77,6 +81,10 @@ renderToString.shallowRender = (vnode, context) => renderToString(vnode, context
7781export default function renderToString ( vnode , context , opts , inner ) {
7882 let { nodeName, attributes, children } = vnode || EMPTY ;
7983 context = context || { } ;
84+ opts = opts || { } ;
85+
86+ let pretty = opts . pretty ,
87+ indentChar = typeof pretty === 'string' ? pretty : '\t' ;
8088
8189 // #text nodes
8290 if ( ! nodeName ) {
@@ -85,7 +93,7 @@ export default function renderToString(vnode, context, opts, inner) {
8593
8694 // components
8795 if ( typeof nodeName === 'function' ) {
88- if ( opts && opts . shallow && ( inner || ( opts && opts . renderRootComponent === false ) ) ) {
96+ if ( opts . shallow && ( inner || opts . renderRootComponent === false ) ) {
8997 nodeName = getComponentName ( nodeName ) ;
9098 }
9199 else {
@@ -108,7 +116,7 @@ export default function renderToString(vnode, context, opts, inner) {
108116 }
109117 }
110118
111- return renderToString ( rendered , context , opts , ! opts || opts . shallowHighOrder !== false ) ;
119+ return renderToString ( rendered , context , opts , opts . shallowHighOrder !== false ) ;
112120 }
113121 }
114122
@@ -140,25 +148,47 @@ export default function renderToString(vnode, context, opts, inner) {
140148
141149 s += '>' ;
142150
151+ // if (pretty) s += '\n' + indentChar;
152+
143153 if ( html ) {
154+ // if multiline, indent.
155+ if ( pretty && isLargeString ( html ) ) {
156+ html = '\n' + indentChar + indent ( html , indentChar ) ;
157+ }
144158 s += html ;
145159 }
146160 else {
147161 let len = children && children . length ;
148162 if ( len ) {
163+ let pieces = [ ] ,
164+ hasLarge = false ;
149165 for ( let i = 0 ; i < len ; i ++ ) {
150166 let child = children [ i ] ;
151167 if ( ! falsey ( child ) ) {
152- s += renderToString ( child , context , opts , true ) ;
168+ let ret = renderToString ( child , context , opts , true ) ;
169+ // if (pretty && isLargeString(ret)) {
170+ // if (pretty && isLargeString(ret)) {
171+ // ret = '\n' + indentChar + indent(ret);
172+ // }
173+ //s += ret;
174+ if ( ! hasLarge && pretty && isLargeString ( ret ) ) hasLarge = true ;
175+ pieces . push ( ret ) ;
176+ }
177+ }
178+ if ( hasLarge ) {
179+ for ( let i = pieces . length ; i -- ; ) {
180+ pieces [ i ] = '\n' + indentChar + indent ( pieces [ i ] , indentChar ) ;
153181 }
154182 }
183+ s += pieces . join ( '' ) ;
155184 }
156185 else if ( opts && opts . xml ) {
157186 return s . substring ( 0 , s . length - 1 ) + ' />' ;
158187 }
159188 }
160189
161190 if ( VOID_ELEMENTS . indexOf ( nodeName ) === - 1 ) {
191+ if ( pretty && ~ s . indexOf ( '\n' ) ) s += '\n' ;
162192 s += `</${ nodeName } >` ;
163193 }
164194
0 commit comments