HTML-encoding lost when attribute read from input field
Asked Answered
C

26

773

I’m using JavaScript to pull a value out from a hidden field and display it in a textbox. The value in the hidden field is encoded.

For example,

<input id='hiddenId' type='hidden' value='chalk &amp; cheese' />

gets pulled into

<input type='text' value='chalk &amp; cheese' />

via some jQuery to get the value from the hidden field (it’s at this point that I lose the encoding):

$('#hiddenId').attr('value')

The problem is that when I read chalk &amp; cheese from the hidden field, JavaScript seems to lose the encoding. I do not want the value to be chalk & cheese. I want the literal amp; to be retained.

Is there a JavaScript library or a jQuery method that will HTML-encode a string?

Ceja answered 2/8, 2009 at 21:8 Comment(6)
Can you show the Javascript you are using?Apeldoorn
have added how I get value from hidden fieldCeja
debuggable.com/posts/…Ceja
Do NOT use the innerHTML method (the jQuery .html() method uses innerHTML), as on some (I've only tested Chrome) browsers, this won't escape quotes, so if you were to put your value into an attribute value, you would end up with an XSS vulnerability.Semen
in what context is chalk and cheese ever used together 0_oGodparent
@Godparent when comparing two items. example. they are as different as chalk and cheese ;)Undetermined
G
1074

EDIT: This answer was posted a long ago, and the htmlDecode function introduced a XSS vulnerability. It has been modified changing the temporary element from a div to a textarea reducing the XSS chance. But nowadays, I would encourage you to use the DOMParser API as suggested in other anwswer.


I use these functions:

function htmlEncode(value){
  // Create a in-memory element, set its inner text (which is automatically encoded)
  // Then grab the encoded contents back out. The element never exists on the DOM.
  return $('<textarea/>').text(value).html();
}

function htmlDecode(value){
  return $('<textarea/>').html(value).text();
}

Basically a textarea element is created in memory, but it is never appended to the document.

On the htmlEncode function I set the innerText of the element, and retrieve the encoded innerHTML; on the htmlDecode function I set the innerHTML value of the element and the innerText is retrieved.

Check a running example here.

Gaskell answered 2/8, 2009 at 22:3 Comment(2)
This works for most scenarios, but this implementation of htmlDecode will eliminate any extra whitespace. So for some values of "input", input != htmlDecode(htmlEncode(input)). This was a problem for us in some scenarios. For example, if input = "<p>\t Hi \n There </p>", a roundtrip encode/decode will yield "<p> Hi There </p>". Most of the time this is okay, but sometimes it isn't. :)Dc
Depends on the browser, on Firefox it is including the whitespaces, new lines... On IE it strips all.Idea
C
565

The jQuery trick doesn't encode quote marks and in IE it will strip your whitespace.

Based on the escape templatetag in Django, which I guess is heavily used/tested already, I made this function which does what's needed.

It's arguably simpler (and possibly faster) than any of the workarounds for the whitespace-stripping issue - and it encodes quote marks, which is essential if you're going to use the result inside an attribute value for example.

function htmlEscape(str) {
    return str
        .replace(/&/g, '&amp;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');
}

// I needed the opposite function today, so adding here too:
function htmlUnescape(str){
    return str
        .replace(/&quot;/g, '"')
        .replace(/&#39;/g, "'")
        .replace(/&lt;/g, '<')
        .replace(/&gt;/g, '>')
        .replace(/&amp;/g, '&');
}

Update 2013-06-17:
In the search for the fastest escaping I have found this implementation of a replaceAll method:
http://dumpsite.com/forum/index.php?topic=4.msg29#msg29
(also referenced here: Fastest method to replace all instances of a character in a string)
Some performance results here:
http://jsperf.com/htmlencoderegex/25

It gives identical result string to the builtin replace chains above. I'd be very happy if someone could explain why it's faster!?

Update 2015-03-04:
I just noticed that AngularJS are using exactly the method above:
https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L435

They add a couple of refinements - they appear to be handling an obscure Unicode issue as well as converting all non-alphanumeric characters to entities. I was under the impression the latter was not necessary as long as you have an UTF8 charset specified for your document.

I will note that (4 years later) Django still does not do either of these things, so I'm not sure how important they are:
https://github.com/django/django/blob/1.8b1/django/utils/html.py#L44

Update 2016-04-06:
You may also wish to escape forward-slash /. This is not required for correct HTML encoding, however it is recommended by OWASP as an anti-XSS safety measure. (thanks to @JNF for suggesting this in comments)

        .replace(/\//g, '&#x2F;');
Clotho answered 19/8, 2011 at 15:41 Comment(1)
@Ferruccio ...and for reasons why not to use &apos; see: #2084254 blogs.msdn.com/b/kirillosenkov/archive/2010/03/19/… fishbowl.pastiche.org/2003/07/01/the_curse_of_aposClotho
K
83

Here's a non-jQuery version that is considerably faster than both the jQuery .html() version and the .replace() version. This preserves all whitespace, but like the jQuery version, doesn't handle quotes.

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

Speed: http://jsperf.com/htmlencoderegex/17

speed test

Demo: jsFiddle

Output:

output

Script:

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

function htmlDecode( html ) {
    var a = document.createElement( 'a' ); a.innerHTML = html;
    return a.textContent;
};

document.getElementById( 'text' ).value = htmlEncode( document.getElementById( 'hidden' ).value );

//sanity check
var html = '<div>   &amp; hello</div>';
document.getElementById( 'same' ).textContent = 
      'html === htmlDecode( htmlEncode( html ) ): ' 
    + ( html === htmlDecode( htmlEncode( html ) ) );

HTML:

<input id="hidden" type="hidden" value="chalk    &amp; cheese" />
<input id="text" value="" />
<div id="same"></div>
Kalina answered 11/3, 2013 at 20:48 Comment(1)
This begs the question: why isn't it a global function in JS already?!Polydactyl
S
32

I know this is an old one, but I wanted to post a variation of the accepted answer that will work in IE without removing lines:

function multiLineHtmlEncode(value) {
    var lines = value.split(/\r\n|\r|\n/);
    for (var i = 0; i < lines.length; i++) {
        lines[i] = htmlEncode(lines[i]);
    }
    return lines.join('\r\n');
}

function htmlEncode(value) {
    return $('<div/>').text(value).html();
} 
Schnabel answered 26/10, 2010 at 16:32 Comment(0)
S
29

Underscore provides _.escape() and _.unescape() methods that do this.

> _.unescape( "chalk &amp; cheese" );
  "chalk & cheese"

> _.escape( "chalk & cheese" );
  "chalk &amp; cheese"
Selfassurance answered 10/1, 2014 at 15:4 Comment(0)
G
12

Good answer. Note that if the value to encode is undefined or null with jQuery 1.4.2 you might get errors such as:

jQuery("<div/>").text(value).html is not a function

OR

Uncaught TypeError: Object has no method 'html'

The solution is to modify the function to check for an actual value:

function htmlEncode(value){ 
    if (value) {
        return jQuery('<div/>').text(value).html(); 
    } else {
        return '';
    }
}
Groveman answered 2/11, 2010 at 22:40 Comment(1)
jQuery('<div/>').text(value || '').html()Fencing
A
12

For those who prefer plain javascript, here is the method I have used successfully:

function escapeHTML (str)
{
    var div = document.createElement('div');
    var text = document.createTextNode(str);
    div.appendChild(text);
    return div.innerHTML;
}
Archi answered 12/10, 2013 at 21:13 Comment(0)
S
6

FWIW, the encoding is not being lost. The encoding is used by the markup parser (browser) during the page load. Once the source is read and parsed and the browser has the DOM loaded into memory, the encoding has been parsed into what it represents. So by the time your JS is execute to read anything in memory, the char it gets is what the encoding represented.

I may be operating strictly on semantics here, but I wanted you to understand the purpose of encoding. The word "lost" makes it sound like something isn't working like it should.

Sled answered 24/1, 2010 at 12:13 Comment(0)
D
6

Faster without Jquery. You can encode every character in your string:

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}

Or just target the main characters to worry about (&, inebreaks, <, >, " and ') like:

function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}

test.value=encode('Encode HTML entities!\n\n"Safe" escape <script id=\'\'> & useful in <pre> tags!');

testing.innerHTML=test.value;

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<textarea id=test rows="9" cols="55"></textarea>

<div id="testing">www.WHAK.com</div>
Disaffirm answered 26/7, 2015 at 13:49 Comment(0)
A
5

Prototype has it built-in the String class. So if you are using/plan to use Prototype, it does something like:

'<div class="article">This is an article</div>'.escapeHTML();
// -> "&lt;div class="article"&gt;This is an article&lt;/div&gt;"
Apeldoorn answered 2/8, 2009 at 21:17 Comment(2)
After looking at Prototype's solution, this is all it's doing... .replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); Easy enough.Colchester
shouldn't it do something with quote marks too? that's not goodClotho
K
4

Here is a simple javascript solution. It extends String object with a method "HTMLEncode" which can be used on an object without parameter, or with a parameter.

String.prototype.HTMLEncode = function(str) {
  var result = "";
  var str = (arguments.length===1) ? str : this;
  for(var i=0; i<str.length; i++) {
     var chrcode = str.charCodeAt(i);
     result+=(chrcode>128) ? "&#"+chrcode+";" : str.substr(i,1)
   }
   return result;
}
// TEST
console.log("stetaewteaw æø".HTMLEncode());
console.log("stetaewteaw æø".HTMLEncode("æåøåæå"))

I have made a gist "HTMLEncode method for javascript".

Keciakeck answered 10/1, 2015 at 15:26 Comment(0)
C
3

As far as I know there isn't any straight forward HTML Encode/Decode method in javascript.

However, what you can do, is to use JS to create an arbitrary element, set its inner text, then read it using innerHTML.

Let's say, with jQuery, this should work:

var helper = $('chalk & cheese').hide().appendTo('body');
var htmled = helper.html();
helper.remove();

Or something along these lines.

Cycle answered 2/8, 2009 at 21:16 Comment(1)
I find the downvote a little bit amusing, considering this answer is almost identical to the one that has over 870 upvotes, and was posted a little bit after this one.Cycle
G
3

Based on angular's sanitize... (es6 module syntax)

// ref: https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js
const SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
const NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;

const decodeElem = document.createElement('pre');


/**
 * Decodes html encoded text, so that the actual string may
 * be used.
 * @param value
 * @returns {string} decoded text
 */
export function decode(value) {
  if (!value) return '';
  decodeElem.innerHTML = value.replace(/</g, '&lt;');
  return decodeElem.textContent;
}


/**
 * Encodes all potentially dangerous characters, so that the
 * resulting string can be safely inserted into attribute or
 * element text.
 * @param value
 * @returns {string} encoded text
 */
export function encode(value) {
  if (value === null || value === undefined) return '';
  return String(value).
    replace(/&/g, '&amp;').
    replace(SURROGATE_PAIR_REGEXP, value => {
      var hi = value.charCodeAt(0);
      var low = value.charCodeAt(1);
      return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
    }).
    replace(NON_ALPHANUMERIC_REGEXP, value => {
      return '&#' + value.charCodeAt(0) + ';';
    }).
    replace(/</g, '&lt;').
    replace(/>/g, '&gt;');
}

export default {encode,decode};
Gelignite answered 13/7, 2016 at 18:56 Comment(5)
While I do really like this answer and actually I think is a good approach I have a doubt, is the bitwise operator on if (value === null | value === undefined) return ''; a typo or actually a feature? If so, why use that one and not the common || ? Thank you!!Raven
@AlejandroVales I'm pretty sure it was a typo... corrected.Gelignite
Well anyhow keep in mind that the | will lead to 0 or 1, so actually it did work ^^Raven
couldn't you just use == null? undefined is the only thing to have equivalence with null, so two triple-equals aren't necessary anywayHeadstand
that's not true at all. null and 0 are both falsy, yes, so you cant just do !value, but the whole point of == is to make certain things easier. 0 == null is false. undefined == null is true. you can just do value == nullHeadstand
S
3

My pure-JS function:

/**
 * HTML entities encode
 *
 * @param {string} str Input text
 * @return {string} Filtered text
 */
function htmlencode (str){

  var div = document.createElement('div');
  div.appendChild(document.createTextNode(str));
  return div.innerHTML;
}

JavaScript HTML Entities Encode & Decode

Scenarist answered 19/12, 2018 at 11:2 Comment(0)
A
2

You shouldn't have to escape/encode values in order to shuttle them from one input field to another.

<form>
 <input id="button" type="button" value="Click me">
 <input type="hidden" id="hiddenId" name="hiddenId" value="I like cheese">
 <input type="text" id="output" name="output">
</form>
<script>
    $(document).ready(function(e) {
        $('#button').click(function(e) {
            $('#output').val($('#hiddenId').val());
        });
    });
</script>

JS doesn't go inserting raw HTML or anything; it just tells the DOM to set the value property (or attribute; not sure). Either way, the DOM handles any encoding issues for you. Unless you're doing something odd like using document.write or eval, HTML-encoding will be effectively transparent.

If you're talking about generating a new textbox to hold the result...it's still as easy. Just pass the static part of the HTML to jQuery, and then set the rest of the properties/attributes on the object it returns to you.

$box = $('<input type="text" name="whatever">').val($('#hiddenId').val());
Afrikaner answered 25/1, 2013 at 23:50 Comment(0)
B
2

I had a similar problem and solve it using the function encodeURIComponent from JavaScript (documentation)

For example, in your case if you use:

<input id='hiddenId' type='hidden' value='chalk & cheese' />

and

encodeURIComponent($('#hiddenId').attr('value'))

you will get chalk%20%26%20cheese. Even spaces are kept.

In my case, I had to encode one backslash and this code works perfectly

encodeURIComponent('name/surname')

and I got name%2Fsurname

Birdie answered 5/7, 2017 at 23:0 Comment(0)
K
2

Here's a little bit that emulates the Server.HTMLEncode function from Microsoft's ASP, written in pure JavaScript:

function htmlEncode(s) {
  var ntable = {
    "&": "amp",
    "<": "lt",
    ">": "gt",
    "\"": "quot"
  };
  s = s.replace(/[&<>"]/g, function(ch) {
    return "&" + ntable[ch] + ";";
  })
  s = s.replace(/[^ -\x7e]/g, function(ch) {
    return "&#" + ch.charCodeAt(0).toString() + ";";
  });
  return s;
}

The result does not encode apostrophes, but encodes the other HTML specials and any character outside the 0x20-0x7e range.

Kosse answered 20/6, 2018 at 17:40 Comment(0)
B
1

If you want to use jQuery. I found this:

http://www.jquerysdk.com/api/jQuery.htmlspecialchars

(part of jquery.string plugin offered by jQuery SDK)

The problem with Prototype I believe is that it extends base objects in JavaScript and will be incompatible with any jQuery you may have used. Of course, if you are already using Prototype and not jQuery, it won't be a problem.

EDIT: Also there is this, which is a port of Prototype's string utilities for jQuery:

http://stilldesigning.com/dotstring/

Brand answered 25/4, 2013 at 20:27 Comment(0)
H
1
var htmlEnDeCode = (function() {
    var charToEntityRegex,
        entityToCharRegex,
        charToEntity,
        entityToChar;

    function resetCharacterEntities() {
        charToEntity = {};
        entityToChar = {};
        // add the default set
        addCharacterEntities({
            '&amp;'     :   '&',
            '&gt;'      :   '>',
            '&lt;'      :   '<',
            '&quot;'    :   '"',
            '&#39;'     :   "'"
        });
    }

    function addCharacterEntities(newEntities) {
        var charKeys = [],
            entityKeys = [],
            key, echar;
        for (key in newEntities) {
            echar = newEntities[key];
            entityToChar[key] = echar;
            charToEntity[echar] = key;
            charKeys.push(echar);
            entityKeys.push(key);
        }
        charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g');
        entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
    }

    function htmlEncode(value){
        var htmlEncodeReplaceFn = function(match, capture) {
            return charToEntity[capture];
        };

        return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn);
    }

    function htmlDecode(value) {
        var htmlDecodeReplaceFn = function(match, capture) {
            return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10));
        };

        return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn);
    }

    resetCharacterEntities();

    return {
        htmlEncode: htmlEncode,
        htmlDecode: htmlDecode
    };
})();

This is from ExtJS source code.

Hesitant answered 2/1, 2014 at 10:42 Comment(0)
W
1
<script>
String.prototype.htmlEncode = function () {
    return String(this)
        .replace(/&/g, '&amp;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');

}

var aString = '<script>alert("I hack your site")</script>';
console.log(aString.htmlEncode());
</script>

Will output: &lt;script&gt;alert(&quot;I hack your site&quot;)&lt;/script&gt;

.htmlEncode() will be accessible on all strings once defined.

Wesleywesleyan answered 3/7, 2014 at 14:11 Comment(0)
K
1

HtmlEncodes the given value

  var htmlEncodeContainer = $('<div />');
  function htmlEncode(value) {
    if (value) {
      return htmlEncodeContainer.text(value).html();
    } else {
      return '';
    }
  }
Knockwurst answered 20/1, 2016 at 3:4 Comment(0)
K
1

I ran into some issues with backslash in my Domain\User string.

I added this to the other escapes from Anentropic's answer

.replace(/\\/g, '&#92;')

Which I found here: How to escape backslash in JavaScript?

Kyrstin answered 17/8, 2016 at 16:14 Comment(0)
M
0

Picking what escapeHTML() is doing in the prototype.js

Adding this script helps you escapeHTML:

String.prototype.escapeHTML = function() { 
    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
}

now you can call escapeHTML method on strings in your script, like:

var escapedString = "<h1>this is HTML</h1>".escapeHTML();
// gives: "&lt;h1&gt;this is HTML&lt;/h1&gt;"

Hope it helps anyone looking for a simple solution without having to include the entire prototype.js

Marlenemarler answered 22/8, 2018 at 13:20 Comment(0)
H
0

Using some of the other answers here I made a version that replaces all the pertinent characters in one pass irrespective of the number of distinct encoded characters (only one call to replace()) so will be faster for larger strings.

It doesn't rely on the DOM API to exist or on other libraries.

window.encodeHTML = (function() {
    function escapeRegex(s) {
        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
    }
    var encodings = {
        '&'  : '&amp;',
        '"'  : '&quot;',
        '\'' : '&#39;',
        '<'  : '&lt;',
        '>'  : '&gt;',
        '\\' : '&#x2F;'
    };
    function encode(what) { return encodings[what]; };
    var specialChars = new RegExp('[' +
        escapeRegex(Object.keys(encodings).join('')) +
    ']', 'g');

    return function(text) { return text.replace(specialChars, encode); };
})();

Having ran that once, you can now call

encodeHTML('<>&"\'')

To get &lt;&gt;&amp;&quot;&#39;

Headstand answered 16/10, 2018 at 6:37 Comment(0)
M
0

function encodeHTML(str) {
    return document.createElement("a").appendChild( 
        document.createTextNode(str)).parentNode.innerHTML;
};

function decodeHTML(str) {
    var element = document.createElement("a"); 
    element.innerHTML = str;
    return element.textContent;
};
var str = "<"
var enc = encodeHTML(str);
var dec = decodeHTML(enc);
console.log("str: " + str, "\nenc: " + enc, "\ndec: " + dec);
Mercantile answered 16/6, 2019 at 13:47 Comment(0)
F
0

Necromancing.
There's certainly no jQuery required for that !
Here a JavaScript port from System.Web.HttpUtility (C# - disclaimer: not very tested):

"use strict";
function htmlDecode(s) {
    if (s == null)
        return null;
    if (s.length == 0)
        return "";
    if (s.indexOf('&') == -1)
        return s;
    function isDigit(str) {
        return /^\d+$/.test(str);
    }
    function isHexDigit(str) {
        return /[0-9A-Fa-f]{6}/g.test(str);
    }
    function initEntities() {
        var entities = {};
        entities["nbsp"] = '\u00A0';
        entities["iexcl"] = '\u00A1';
        entities["cent"] = '\u00A2';
        entities["pound"] = '\u00A3';
        entities["curren"] = '\u00A4';
        entities["yen"] = '\u00A5';
        entities["brvbar"] = '\u00A6';
        entities["sect"] = '\u00A7';
        entities["uml"] = '\u00A8';
        entities["copy"] = '\u00A9';
        entities["ordf"] = '\u00AA';
        entities["laquo"] = '\u00AB';
        entities["not"] = '\u00AC';
        entities["shy"] = '\u00AD';
        entities["reg"] = '\u00AE';
        entities["macr"] = '\u00AF';
        entities["deg"] = '\u00B0';
        entities["plusmn"] = '\u00B1';
        entities["sup2"] = '\u00B2';
        entities["sup3"] = '\u00B3';
        entities["acute"] = '\u00B4';
        entities["micro"] = '\u00B5';
        entities["para"] = '\u00B6';
        entities["middot"] = '\u00B7';
        entities["cedil"] = '\u00B8';
        entities["sup1"] = '\u00B9';
        entities["ordm"] = '\u00BA';
        entities["raquo"] = '\u00BB';
        entities["frac14"] = '\u00BC';
        entities["frac12"] = '\u00BD';
        entities["frac34"] = '\u00BE';
        entities["iquest"] = '\u00BF';
        entities["Agrave"] = '\u00C0';
        entities["Aacute"] = '\u00C1';
        entities["Acirc"] = '\u00C2';
        entities["Atilde"] = '\u00C3';
        entities["Auml"] = '\u00C4';
        entities["Aring"] = '\u00C5';
        entities["AElig"] = '\u00C6';
        entities["Ccedil"] = '\u00C7';
        entities["Egrave"] = '\u00C8';
        entities["Eacute"] = '\u00C9';
        entities["Ecirc"] = '\u00CA';
        entities["Euml"] = '\u00CB';
        entities["Igrave"] = '\u00CC';
        entities["Iacute"] = '\u00CD';
        entities["Icirc"] = '\u00CE';
        entities["Iuml"] = '\u00CF';
        entities["ETH"] = '\u00D0';
        entities["Ntilde"] = '\u00D1';
        entities["Ograve"] = '\u00D2';
        entities["Oacute"] = '\u00D3';
        entities["Ocirc"] = '\u00D4';
        entities["Otilde"] = '\u00D5';
        entities["Ouml"] = '\u00D6';
        entities["times"] = '\u00D7';
        entities["Oslash"] = '\u00D8';
        entities["Ugrave"] = '\u00D9';
        entities["Uacute"] = '\u00DA';
        entities["Ucirc"] = '\u00DB';
        entities["Uuml"] = '\u00DC';
        entities["Yacute"] = '\u00DD';
        entities["THORN"] = '\u00DE';
        entities["szlig"] = '\u00DF';
        entities["agrave"] = '\u00E0';
        entities["aacute"] = '\u00E1';
        entities["acirc"] = '\u00E2';
        entities["atilde"] = '\u00E3';
        entities["auml"] = '\u00E4';
        entities["aring"] = '\u00E5';
        entities["aelig"] = '\u00E6';
        entities["ccedil"] = '\u00E7';
        entities["egrave"] = '\u00E8';
        entities["eacute"] = '\u00E9';
        entities["ecirc"] = '\u00EA';
        entities["euml"] = '\u00EB';
        entities["igrave"] = '\u00EC';
        entities["iacute"] = '\u00ED';
        entities["icirc"] = '\u00EE';
        entities["iuml"] = '\u00EF';
        entities["eth"] = '\u00F0';
        entities["ntilde"] = '\u00F1';
        entities["ograve"] = '\u00F2';
        entities["oacute"] = '\u00F3';
        entities["ocirc"] = '\u00F4';
        entities["otilde"] = '\u00F5';
        entities["ouml"] = '\u00F6';
        entities["divide"] = '\u00F7';
        entities["oslash"] = '\u00F8';
        entities["ugrave"] = '\u00F9';
        entities["uacute"] = '\u00FA';
        entities["ucirc"] = '\u00FB';
        entities["uuml"] = '\u00FC';
        entities["yacute"] = '\u00FD';
        entities["thorn"] = '\u00FE';
        entities["yuml"] = '\u00FF';
        entities["fnof"] = '\u0192';
        entities["Alpha"] = '\u0391';
        entities["Beta"] = '\u0392';
        entities["Gamma"] = '\u0393';
        entities["Delta"] = '\u0394';
        entities["Epsilon"] = '\u0395';
        entities["Zeta"] = '\u0396';
        entities["Eta"] = '\u0397';
        entities["Theta"] = '\u0398';
        entities["Iota"] = '\u0399';
        entities["Kappa"] = '\u039A';
        entities["Lambda"] = '\u039B';
        entities["Mu"] = '\u039C';
        entities["Nu"] = '\u039D';
        entities["Xi"] = '\u039E';
        entities["Omicron"] = '\u039F';
        entities["Pi"] = '\u03A0';
        entities["Rho"] = '\u03A1';
        entities["Sigma"] = '\u03A3';
        entities["Tau"] = '\u03A4';
        entities["Upsilon"] = '\u03A5';
        entities["Phi"] = '\u03A6';
        entities["Chi"] = '\u03A7';
        entities["Psi"] = '\u03A8';
        entities["Omega"] = '\u03A9';
        entities["alpha"] = '\u03B1';
        entities["beta"] = '\u03B2';
        entities["gamma"] = '\u03B3';
        entities["delta"] = '\u03B4';
        entities["epsilon"] = '\u03B5';
        entities["zeta"] = '\u03B6';
        entities["eta"] = '\u03B7';
        entities["theta"] = '\u03B8';
        entities["iota"] = '\u03B9';
        entities["kappa"] = '\u03BA';
        entities["lambda"] = '\u03BB';
        entities["mu"] = '\u03BC';
        entities["nu"] = '\u03BD';
        entities["xi"] = '\u03BE';
        entities["omicron"] = '\u03BF';
        entities["pi"] = '\u03C0';
        entities["rho"] = '\u03C1';
        entities["sigmaf"] = '\u03C2';
        entities["sigma"] = '\u03C3';
        entities["tau"] = '\u03C4';
        entities["upsilon"] = '\u03C5';
        entities["phi"] = '\u03C6';
        entities["chi"] = '\u03C7';
        entities["psi"] = '\u03C8';
        entities["omega"] = '\u03C9';
        entities["thetasym"] = '\u03D1';
        entities["upsih"] = '\u03D2';
        entities["piv"] = '\u03D6';
        entities["bull"] = '\u2022';
        entities["hellip"] = '\u2026';
        entities["prime"] = '\u2032';
        entities["Prime"] = '\u2033';
        entities["oline"] = '\u203E';
        entities["frasl"] = '\u2044';
        entities["weierp"] = '\u2118';
        entities["image"] = '\u2111';
        entities["real"] = '\u211C';
        entities["trade"] = '\u2122';
        entities["alefsym"] = '\u2135';
        entities["larr"] = '\u2190';
        entities["uarr"] = '\u2191';
        entities["rarr"] = '\u2192';
        entities["darr"] = '\u2193';
        entities["harr"] = '\u2194';
        entities["crarr"] = '\u21B5';
        entities["lArr"] = '\u21D0';
        entities["uArr"] = '\u21D1';
        entities["rArr"] = '\u21D2';
        entities["dArr"] = '\u21D3';
        entities["hArr"] = '\u21D4';
        entities["forall"] = '\u2200';
        entities["part"] = '\u2202';
        entities["exist"] = '\u2203';
        entities["empty"] = '\u2205';
        entities["nabla"] = '\u2207';
        entities["isin"] = '\u2208';
        entities["notin"] = '\u2209';
        entities["ni"] = '\u220B';
        entities["prod"] = '\u220F';
        entities["sum"] = '\u2211';
        entities["minus"] = '\u2212';
        entities["lowast"] = '\u2217';
        entities["radic"] = '\u221A';
        entities["prop"] = '\u221D';
        entities["infin"] = '\u221E';
        entities["ang"] = '\u2220';
        entities["and"] = '\u2227';
        entities["or"] = '\u2228';
        entities["cap"] = '\u2229';
        entities["cup"] = '\u222A';
        entities["int"] = '\u222B';
        entities["there4"] = '\u2234';
        entities["sim"] = '\u223C';
        entities["cong"] = '\u2245';
        entities["asymp"] = '\u2248';
        entities["ne"] = '\u2260';
        entities["equiv"] = '\u2261';
        entities["le"] = '\u2264';
        entities["ge"] = '\u2265';
        entities["sub"] = '\u2282';
        entities["sup"] = '\u2283';
        entities["nsub"] = '\u2284';
        entities["sube"] = '\u2286';
        entities["supe"] = '\u2287';
        entities["oplus"] = '\u2295';
        entities["otimes"] = '\u2297';
        entities["perp"] = '\u22A5';
        entities["sdot"] = '\u22C5';
        entities["lceil"] = '\u2308';
        entities["rceil"] = '\u2309';
        entities["lfloor"] = '\u230A';
        entities["rfloor"] = '\u230B';
        entities["lang"] = '\u2329';
        entities["rang"] = '\u232A';
        entities["loz"] = '\u25CA';
        entities["spades"] = '\u2660';
        entities["clubs"] = '\u2663';
        entities["hearts"] = '\u2665';
        entities["diams"] = '\u2666';
        entities["quot"] = '\u0022';
        entities["amp"] = '\u0026';
        entities["lt"] = '\u003C';
        entities["gt"] = '\u003E';
        entities["OElig"] = '\u0152';
        entities["oelig"] = '\u0153';
        entities["Scaron"] = '\u0160';
        entities["scaron"] = '\u0161';
        entities["Yuml"] = '\u0178';
        entities["circ"] = '\u02C6';
        entities["tilde"] = '\u02DC';
        entities["ensp"] = '\u2002';
        entities["emsp"] = '\u2003';
        entities["thinsp"] = '\u2009';
        entities["zwnj"] = '\u200C';
        entities["zwj"] = '\u200D';
        entities["lrm"] = '\u200E';
        entities["rlm"] = '\u200F';
        entities["ndash"] = '\u2013';
        entities["mdash"] = '\u2014';
        entities["lsquo"] = '\u2018';
        entities["rsquo"] = '\u2019';
        entities["sbquo"] = '\u201A';
        entities["ldquo"] = '\u201C';
        entities["rdquo"] = '\u201D';
        entities["bdquo"] = '\u201E';
        entities["dagger"] = '\u2020';
        entities["Dagger"] = '\u2021';
        entities["permil"] = '\u2030';
        entities["lsaquo"] = '\u2039';
        entities["rsaquo"] = '\u203A';
        entities["euro"] = '\u20AC';
        return entities;
    }
    var Entities = initEntities();
    var rawEntity = [];
    var entity = [];
    var output = [];
    var len = s.length;
    var state = 0;
    var number = 0;
    var is_hex_value = false;
    var have_trailing_digits = false;
    for (var i = 0; i < len; i++) {
        var c = s[i];
        if (state == 0) {
            if (c == '&') {
                entity.push(c);
                rawEntity.push(c);
                state = 1;
            }
            else {
                output.push(c);
            }
            continue;
        }
        if (c == '&') {
            state = 1;
            if (have_trailing_digits) {
                entity.push(number.toString());
                have_trailing_digits = false;
            }
            output.push(entity.join(""));
            entity = [];
            entity.push('&');
            continue;
        }
        if (state == 1) {
            if (c == ';') {
                state = 0;
                output.push(entity.join(""));
                output.push(c);
                entity = [];
            }
            else {
                number = 0;
                is_hex_value = false;
                if (c != '#') {
                    state = 2;
                }
                else {
                    state = 3;
                }
                entity.push(c);
                rawEntity.push(c);
            }
        }
        else if (state == 2) {
            entity.push(c);
            if (c == ';') {
                var key = entity.join("");
                if (key.length > 1 && Entities.hasOwnProperty(key.substr(1, key.length - 2)))
                    key = Entities[key.substr(1, key.length - 2)].toString();
                output.push(key);
                state = 0;
                entity = [];
                rawEntity = [];
            }
        }
        else if (state == 3) {
            if (c == ';') {
                if (number == 0)
                    output.push(rawEntity.join("") + ";");
                else if (number > 65535) {
                    output.push("&#");
                    output.push(number.toString());
                    output.push(";");
                }
                else {
                    output.push(String.fromCharCode(number));
                }
                state = 0;
                entity = [];
                rawEntity = [];
                have_trailing_digits = false;
            }
            else if (is_hex_value && isHexDigit(c)) {
                number = number * 16 + parseInt(c, 16);
                have_trailing_digits = true;
                rawEntity.push(c);
            }
            else if (isDigit(c)) {
                number = number * 10 + (c.charCodeAt(0) - '0'.charCodeAt(0));
                have_trailing_digits = true;
                rawEntity.push(c);
            }
            else if (number == 0 && (c == 'x' || c == 'X')) {
                is_hex_value = true;
                rawEntity.push(c);
            }
            else {
                state = 2;
                if (have_trailing_digits) {
                    entity.push(number.toString());
                    have_trailing_digits = false;
                }
                entity.push(c);
            }
        }
    }
    if (entity.length > 0) {
        output.push(entity.join(""));
    }
    else if (have_trailing_digits) {
        output.push(number.toString());
    }
    return output.join("");
}
function htmlEncode(s) {
    if (s == null)
        return null;
    if (s.length == 0)
        return s;
    var needEncode = false;
    for (var i = 0; i < s.length; i++) {
        var c = s[i];
        if (c == '&' || c == '"' || c == '<' || c == '>' || c.charCodeAt(0) > 159
            || c == '\'') {
            needEncode = true;
            break;
        }
    }
    if (!needEncode)
        return s;
    var output = [];
    var len = s.length;
    for (var i = 0; i < len; i++) {
        var ch = s[i];
        switch (ch) {
            case '&':
                output.push("&amp;");
                break;
            case '>':
                output.push("&gt;");
                break;
            case '<':
                output.push("&lt;");
                break;
            case '"':
                output.push("&quot;");
                break;
            case '\'':
                output.push("&#39;");
                break;
            case '\uff1c':
                output.push("&#65308;");
                break;
            case '\uff1e':
                output.push("&#65310;");
                break;
            default:
                if (ch.charCodeAt(0) > 159 && ch.charCodeAt(0) < 256) {
                    output.push("&#");
                    output.push(ch.charCodeAt(0).toString());
                    output.push(";");
                }
                else
                    output.push(ch);
                break;
        }
    }
    return output.join("");
}
Frontolysis answered 12/10, 2021 at 15:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.