nuaavee
nuaavee

Reputation: 1356

Convert HTML Character Entities back to regular text using javascript

the questions says it all :)

eg. we have >, we need > using only javascript

Update: It seems jquery is the easy way out. But, it would be nice to have a lightweight solution. More like a function which is capable to do this by itself.

Upvotes: 20

Views: 34721

Answers (7)

j.j.
j.j.

Reputation: 2100

This answer isn't really new, but concise without needless cruft.
You can create any element like <p> or <b> or <span> or <foo> or <whatever>.
Unsuitable for untrusted user input.

function entity(x) {
    const foo = document.createElement("foo");
    foo.innerHTML = x;
    return foo.textContent;
}

console.log( entity("&hearts; &nbsp; &clubs;") );  // returns ♥   ♣

alert( entity("&hearts; &nbsp; &clubs;") );

Upvotes: 0

arashka
arashka

Reputation: 1325

Use Dentity! I found none of the answers above satisfying, so I cherry picked some stuff from here (specially answer by @Gumbo and then also used the tests from the "he" project), fixed their problems and added the complete W3C entity definitions, and some more functionality. I also made it as small as possible, which is now 31KB minified and 14KB when gzipped. You can download it from https://github.com/arashkazemi/dentity

It includes both the decoder and encoder functions and it works both in browser and in node environment. I hope it solves the problem efficiently!

Upvotes: 0

Nux
Nux

Reputation: 10002

Here is a "class" for decoding whole HTML document.

HTMLDecoder = {
    tempElement: document.createElement('span'),
    decode: function(html) {
        var _self = this;
        html.replace(/&(#(?:x[0-9a-f]+|\d+)|[a-z]+);/gi,
            function(str) {
                _self.tempElement.innerHTML= str;
                str = _self.tempElement.textContent || _self.tempElement.innerText;
                return str;
            }
        );
    }
}

Note that I used Gumbo's regexp for catching entities but for fully valid HTML documents (or XHTML) you could simpy use /&[^;]+;/g.

Upvotes: 4

CICDC
CICDC

Reputation: 167

I know there are libraries out there, but here are a couple of solutions for browsers. These work well when placing html entity data strings into human editable areas where you want the characters to be shown, such as textarea's or input[type=text].

I add this answer as I have to support older versions of IE and I feel that it wraps up a few days worth of research and testing. I hope somebody finds this useful.

First this is for more modern browsers using jQuery, Please note that this should NOT be used if you have to support versions of IE before 10 (7, 8, or 9) as it will strip out the newlines leaving you with just one long line of text.

if (!String.prototype.HTMLDecode) {
    String.prototype.HTMLDecode = function () {
            var str = this.toString(),
            $decoderEl = $('<textarea />');

        str = $decoderEl.html(str)
            .text()
            .replace(/<br((\/)|( \/))?>/gi, "\r\n");

        $decoderEl.remove();

        return str;
    };
}

This next one is based on kennebec's work above, with some differences which are mostly for the sake of older IE versions. This does not require jQuery, but does still require a browser.

if (!String.prototype.HTMLDecode) {
    String.prototype.HTMLDecode = function () {
        var str = this.toString(),
            //Create an element for decoding            
            decoderEl = document.createElement('p');

        //Bail if empty, otherwise IE7 will return undefined when 
        //OR-ing the 2 empty strings from innerText and textContent
        if (str.length == 0) {
            return str;
        }

        //convert newlines to <br's> to save them
        str = str.replace(/((\r\n)|(\r)|(\n))/gi, " <br/>");            

        decoderEl.innerHTML = str;
        /*
        We use innerText first as IE strips newlines out with textContent.
        There is said to be a performance hit for this, but sometimes
        correctness of data (keeping newlines) must take precedence.
        */
        str = decoderEl.innerText || decoderEl.textContent;

        //clean up the decoding element
        decoderEl = null;

        //replace back in the newlines
        return str.replace(/<br((\/)|( \/))?>/gi, "\r\n");
    };
}

/* 
Usage: 
    var str = "&gt;";
    return str.HTMLDecode();

returned value: 
    (String) >    
*/

Upvotes: 3

kennebec
kennebec

Reputation: 104780

function decodeEntities(s){
    var str, temp= document.createElement('p');
    temp.innerHTML= s;
    str= temp.textContent || temp.innerText;
    temp=null;
    return str;
}

alert(decodeEntities('&lt;'))

/*  returned value: (String)
<
*/

Upvotes: 22

Gumbo
Gumbo

Reputation: 655239

You could do something like this:

String.prototype.decodeHTML = function() {
    var map = {"gt":">" /* , … */};
    return this.replace(/&(#(?:x[0-9a-f]+|\d+)|[a-z]+);?/gi, function($0, $1) {
        if ($1[0] === "#") {
            return String.fromCharCode($1[1].toLowerCase() === "x" ? parseInt($1.substr(2), 16)  : parseInt($1.substr(1), 10));
        } else {
            return map.hasOwnProperty($1) ? map[$1] : $0;
        }
    });
};

Upvotes: 33

Oded
Oded

Reputation: 499002

There is nothing built in, but there are many libraries that have been written to do this.

Here is one.

And here one that is a jQuery plugin.

Upvotes: 1

Related Questions