超文本标记语言-从输入字段读取属性时丢失编码

我正在使用JavaScript从隐藏字段中提取一个值并将其显示在文本框中。隐藏字段中的值是编码的。

例如,

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

被卷入

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

通过一些jQuery从隐藏字段中获取值(此时我丢失了编码):

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

问题是当我从隐藏字段读取chalk &amp; cheese时,JavaScript似乎失去了编码。我不希望值为chalk & cheese。我希望保留文字amp;

是否有JavaScript库或jQuery方法可以对字符串进行超文本标记语言编码?

654512 次浏览

据我所知,JavaScript中没有任何直接的超文本标记语言Encode/Decode方法。

但是,您可以做的是使用JS创建任意元素,设置其内部文本,然后使用innerHTML读取它。

假设,使用jQuery,这应该可以工作:

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

或者沿着这条线的东西。

原型内置在字符串类中。因此,如果您正在使用/计划使用原型,它会执行以下操作:

'<div class="article">This is an article</div>'.escapeHTML();
// -> "&lt;div class="article"&gt;This is an article&lt;/div&gt;"

编辑:这个答案很久以前就发布了,htmlDecode函数引入了一个XSS漏洞。它已被修改,将临时元素从div更改为textarea,以减少XSS机会。但是现在,我建议您按照其他anwswer中的建议使用DOMParser API。


我使用这些功能:

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();
}

基本上,文本区域元素是在内存中创建的,但它永远不会附加到文档中。

htmlEncode函数上,我设置元素的innerText,并检索编码的innerHTML;在htmlDecode函数上,我设置元素的innerHTML值并检索innerText

查看正在运行的示例这里

FWIW,编码没有丢失。编码在页面加载期间由标记解析器(浏览器)使用。一旦读取和解析源,浏览器将DOM加载到内存中,编码已经被解析成它所代表的内容。因此,当你的JS执行读取内存中的任何内容时,它获得的字符就是编码所代表的。

我在这里可能严格按照语义学来操作,但我想让你理解编码的目的。“丢失”这个词听起来像是某些东西没有正常工作。

我知道这是一个旧的,但我想发布一个公认的答案的变体,它可以在IE中工作而不删除行:

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();
}

好答案。请注意,如果使用jQuery 1.4.2编码的值是undefinednull,您可能会收到以下错误:

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

Uncaught TypeError: Object has no method 'html'

解决方案是修改函数以检查实际值:

function htmlEncode(value){
if (value) {
return jQuery('<div/>').text(value).html();
} else {
return '';
}
}

jQuery技巧不会对引号进行编码,在IE中它会剥离空格。

基于Django中的逃脱模板标签,我想它已经被大量使用/测试过了,我做了这个功能来做需要的事情。

可以说,它比空白剥离问题的任何变通方法都更简单(也可能更快)-并且它对引号进行编码,例如,如果您要在属性值中使用结果,这是必不可少的。

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, '&');
}

2013-06-17更新:
在寻找最快的转义时,我发现了replaceAll方法的这个实现:
http://dumpsite.com/forum/index.php?topic=4.msg29#msg29
(此处也引用:替换字符串中字符的所有实例的最快方法
这里有一些性能结果:
http://jsperf.com/htmlencoderegex/25

它为上面的内置replace链提供了相同的结果字符串。如果有人能解释为什么它更快,我会非常高兴!?

2015-03-04更新:
我刚刚注意到AngularJS使用的正是上面的方法:
https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L435

他们添加了一些改进-他们似乎正在处理模糊的Unicode问题以及将所有非字母数字字符转换为实体。我的印象是,只要您为文档指定了UTF8字符集,后者就没有必要。

我会注意到(4年后)Django仍然没有做这些事情,所以我不确定它们有多重要:
https://github.com/django/django/blob/1.8b1/django/utils/html.py#L44

更新2016-04-06:
您可能还希望转义正斜杠/。这不是正确的超文本标记语言编码所必需的,但是它是由OWASP推荐作为反XSS安全措施。(感谢@JNF在评论中建议这一点)

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

您不应该为了将值从一个输入字段穿梭到另一个输入字段而对值进行转义/编码。

<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不会插入原始超文本标记语言或任何东西;它只是告诉DOM设置value属性(或属性;不确定)。无论哪种方式,DOM都会为您处理任何编码问题。除非您正在做一些奇怪的事情,比如使用document.writeeval,否则超文本标记语言-编码将有效地透明。

如果您正在谈论生成一个新的文本框来保存结果……它仍然很容易。只需将超文本标记语言的静态部分传递给jQuery,然后设置它返回给您的对象的其余属性/属性。

$box = $('<input type="text" name="whatever">').val($('#hiddenId').val());

这是一个非jQuery版本,它比jQuery.html()版本和.replace()版本都快得多。这保留了所有空格,但与jQuery版本一样,不处理引号。

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

速度:http://jsperf.com/htmlencoderegex/17

速度测试

演示:jsFiddle

输出:

输出

脚本:

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 ) ) );

超文本标记语言:

<input id="hidden" type="hidden" value="chalk    &amp; cheese" />
<input id="text" value="" />
<div id="same"></div>

如果你想使用jQuery。我找到了这个:

(jQuery SDK提供的jquery.string插件的一部分)

我认为原型的问题在于它扩展了JavaScript中的基本对象,并且与您可能使用过的任何jQuery不兼容。当然,如果您已经在使用原型而不是jQuery,那就不是问题了。

编辑:还有这个,这是jQuery的原型字符串实用程序的端口:

对于那些喜欢纯JavaScript的人,以下是我成功使用的方法:

function escapeHTML (str)
{
var div = document.createElement('div');
var text = document.createTextNode(str);
div.appendChild(text);
return div.innerHTML;
}
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
};
})();

这是来自ExtJS源代码。

下划线提供了_.escape()_.unescape()方法来执行此操作。

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


> _.escape( "chalk & cheese" );
"chalk &amp; cheese"
<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>

将输出:&lt;script&gt;alert(&quot;I hack your site&quot;)&lt;/script&gt;

. htmlEncode()一旦定义,就可以在所有字符串上访问。

这是一个简单的javascript解决方案。它使用方法“HTMLEncode”扩展String对象,该方法可以在没有参数的对象上使用,也可以使用参数。

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("æåøåæå"))

我做了一个gist"javascript的HTMLEncode方法"

没有JQuery更快。您可以对字符串中的每个字符进行编码:

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

或者只是针对主要角色来担心(&,突破,<;, >, " 和'),比如:

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>

Html对给定值进行编码

  var htmlEncodeContainer = $('<div />');
function htmlEncode(value) {
if (value) {
return htmlEncodeContainer.text(value).html();
} else {
return '';
}
}

基于安格尔消毒…(es6模块语法)

// 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};

我在Domain\User字符串中遇到了一些反斜杠问题。

我把这个加入到Anentropic答案中的其他逃逸中

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

我在这里找到: 如何在JavaScript中转义反斜杠?

我有一个类似的问题,并使用JavaScript中的函数encodeURIComponent留档)解决它

例如,在您的情况下,如果您使用:

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

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

您将获得chalk%20%26%20cheese。甚至保留空格。

在我的例子中,我必须编码一个反斜杠,这个代码完美地工作

encodeURIComponent('name/surname')

我得到了name%2Fsurname

这里有一点模拟微软ASP中的Server.HTMLEncode函数,用纯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;
}

结果不要编码撇号,但编码其他超文本标记语言特殊字符和0x20-0x7e范围之外的任何字符。

选择escapeHTML()在prototype.js做什么

添加此脚本可帮助您转义HTML:

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

现在,您可以在脚本中的字符串上调用逃逸HTML方法,例如:

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

希望它能帮助任何人寻找一个简单的解决方案,而不必包括整个prototype.js

使用这里的一些其他答案,我做了一个版本,它在一次传递中替换了所有相关字符,而不管不同编码字符的数量(只有一次调用replace()),因此对于较大的字符串来说速度会更快。

它不依赖于DOM API或其他库。

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); };
})();

运行一次后,您现在可以调用

encodeHTML('<>&"\'')

获得&lt;&gt;&amp;&quot;&#39;

我的纯JS函数:

/**
* 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超文本标记语言实体编码和解码

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);

巫术。
当然不需要jQuery!
这里有一个来自System. Web. HttpU的JavaScript端口(C#-免责声明:不是很测试):

"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("");
}