Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript: How to correct indentation in HTML string? [closed]

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? Are there any known libraries that do that?

Note:

  • I'm not looking for HTML syntax highlighting, just indentation correction
  • I'm not looking to support the whole HTML spec, correcting basic HTML like the example above would suffice
like image 602
Misha Moroshko Avatar asked Oct 14 '14 12:10

Misha Moroshko


People also ask

Is indentation ignored in HTML?

HTML code does not need to be indented, and all browsers and search engines ignore indentation and extra spacing.

Does HTML follow indentation?

HTML does not care about indentation, it only requires proper nesting.


Video Answer


1 Answers

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>

Demo: http://jsfiddle.net/1gf07wap/

like image 118
dfsq Avatar answered Sep 29 '22 15:09

dfsq