Unescape HTML entities containing newline in Javascript?

escaping, html, javascript

Solution

The most simple, but probably not the most efficient solution is to have `htmlDecode()` act only on character and entity references:

var s = "foo\n&\nbar";
s = s.replace(/(&[^;]+;)+/g, htmlDecode);

More efficient is using an optimized rewrite of `htmlDecode()` that is only called once per input, acts only on character and entity references, and reuses the DOM element object:

function htmlDecode (input)
{
  var e = document.createElement("span");

  var result = input.replace(/(&[^;]+;)+/g, function (match) {
    e.innerHTML = match;
    return e.firstChild.nodeValue;
  });

  return result;
}

/* returns "foo\n&\nbar" */
htmlDecode("foo\n&\nbar");

Wladimir Palant has pointed out an XSS issue with this function: The value of some (HTML5) event listener attributes, like `onerror`, is executed if you assign HTML with elements that have those attributes specified to the `innerHTML` property. So you should not use this function on arbitrary input containing actual HTML, only on HTML that is already escaped. Otherwise you should adapt the regular expression accordingly, for example use `/(&[^;<>]+;)+/` instead to prevent `&…;` where `…` contains tags from being matched.

For arbitrary HTML, please see his alternative approach, but note that it is not as compatible as this one.

Problem

If you have a string containing HTML entities and want to unescape it, this solution (or variants thereof) is suggested multiple times: ``` function htmlDecode(input){ var e = document.createElement('div'); e.innerHTML = input; return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue; } htmlDecode("&lt;img src='myimage.jpg'&gt;"); // returns "<img src='myimage.jpg'>" ``` (See, for example, this answer: https://stackoverflow.com/a/1912522/1199564) This works fine as long as the string does not contain newline and we are not running on Internet Explorer version pre 10 (tested on version 9 and 8). If the string contains a newline, IE 8 and 9 will replace it with a space character instead of leaving it unchanged (as it is on Chrome, Safari, Firefox and IE 10). ``` htmlDecode("Hello\nWorld"); // returns "Hello World" on IE 8 and 9 ``` Any suggestions for a solution that works with IE before version 10?

Original source

Related problems