Reputation: 171459
Given a string like this:
' \n <div id="a">\n <span class="b">\n<span>Hello</span>\n\n\n</span> <input type="text">\n \n</div>\n '
I'd like to format it like this:
<div id="a">
<span class="b">
<span>Hello</span>
</span>
<input type="text">
</div>
i.e. the result should be: (assume 2 spaces for indentation)
'<div id="a">\n <span class="b">\n <span>\n Hello\n </span>\n </span>\n <input type="text">\n</div>'
What's the most elegant way to achieve this? Is there an established way to do that?
Note:
Upvotes: 23
Views: 25852
Reputation: 193301
Here is a simple recursive function I wrote, which I think might help you to achieve what you are after.
function process(str) {
var div = document.createElement('div');
div.innerHTML = str.trim();
return format(div, 0).innerHTML;
}
function format(node, level) {
var indentBefore = new Array(level++ + 1).join(' '),
indentAfter = new Array(level - 1).join(' '),
textNode;
for (var i = 0; i < node.children.length; i++) {
textNode = document.createTextNode('\n' + indentBefore);
node.insertBefore(textNode, node.children[i]);
format(node.children[i], level);
if (node.lastElementChild == node.children[i]) {
textNode = document.createTextNode('\n' + indentAfter);
node.appendChild(textNode);
}
}
return node;
}
Then you would use it like this:
process(str);
Here is a demo:
var str = '<div id="a"><span class="b"><span>Hello</span></span><input type="text"><p><b>b <i>italic</i></b></p></div>';
function process(str) {
var div = document.createElement('div');
div.innerHTML = str.trim();
return format(div, 0).innerHTML;
}
function format(node, level) {
var indentBefore = new Array(level++ + 1).join(' '),
indentAfter = new Array(level - 1).join(' '),
textNode;
for (var i = 0; i < node.children.length; i++) {
textNode = document.createTextNode('\n' + indentBefore);
node.insertBefore(textNode, node.children[i]);
format(node.children[i], level);
if (node.lastElementChild == node.children[i]) {
textNode = document.createTextNode('\n' + indentAfter);
node.appendChild(textNode);
}
}
return node;
}
document.querySelector('#out').innerText = process(str);
<pre id="out"></pre>
Upvotes: 45
Reputation: 12161
Since there are lots of complains about js-beautify, I'm posting this alternative:
GIT: https://github.com/maxogden/commonjs-html-prettyprinter
DEMO: http://requirebin.com/?gist=45056f6a9b306a14ea3d
CODE:
var htmlmodule = require('html');
var str = ' \n <div id="a">\n <span class="b"><span>Hello</span></span><input type="text">\n \n</div>\n ';
var pretty = htmlmodule.prettyPrint(str);
IF this does not work as you intend to, I recommend parsing the HTML string... for this job you can use this xmldom parseFromString... it's really simple.
Upvotes: 1
Reputation: 4002
The js-beautify tool can work with html, and has an api. It's probably the easiest way to do what you want.
After installing it with node:
var beautify_html = require('js-beautify').html;
result = beautify_html(htmlstring);
To use it in a browser, you need to include all the beautify*.js scripts in this directory and use window.html_beautify
.
Upvotes: 6