Skip to content

Commit 0d5ed34

Browse files
committed
Add support for pretty HTML output via a {pretty:true} option /cc @drastick
1 parent e9a9917 commit 0d5ed34

File tree

1 file changed

+33
-3
lines changed

1 file changed

+33
-3
lines changed

src/index.js

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ let escapeChar = a => ESC[a] || a;
4242

4343
let 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
*/
5559
renderToString.render = renderToString;
5660

@@ -77,6 +81,10 @@ renderToString.shallowRender = (vnode, context) => renderToString(vnode, context
7781
export 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

Comments
 (0)