HTML-кодировка теряется при чтении атрибута из поля ввода
Я использую JavaScript, чтобы извлечь значение из скрытого поля и отобразить его в текстовом поле. Значение в скрытом поле кодируется.
Например,
<input id='hiddenId' type='hidden' value='chalk & cheese' />
втягивается в
<input type='text' value='chalk & cheese' />
через некоторый jQuery, чтобы получить значение из скрытого поля (именно в этот момент я теряю кодировку):
$('#hiddenId').attr('value')
Проблема в том, что когда я читаю chalk & cheese
Из скрытого поля JavaScript, похоже, теряет кодировку. Сбежать "
а также '
Я хочу, чтобы кодировка осталась.
Есть ли библиотека JavaScript или метод jQuery, который будет кодировать строку в HTML?
26 ответов
Я использую эти функции:
function htmlEncode(value){
// Create a in-memory div, set its inner text (which jQuery automatically encodes)
// Then grab the encoded contents back out. The div never exists on the page.
return $('<div/>').text(value).html();
}
function htmlDecode(value){
return $('<div/>').html(value).text();
}
В основном элемент div создается в памяти, но он никогда не добавляется к документу.
На htmlEncode
Функция, которую я установил innerText
элемента, и получить закодированный innerHTML
; на htmlDecode
Функция, которую я установил innerHTML
значение элемента и innerText
получается
Проверьте работающий пример здесь.
Уловка jQuery не кодирует кавычки, а в IE она лишит вас пробелов.
Основываясь на теге escape- шаблона в Django, который, я думаю, уже интенсивно используется / проверен, я сделал эту функцию, которая делает то, что нужно.
Это, возможно, проще (и, возможно, быстрее), чем любой из обходных путей для решения проблемы удаления пробелов, - и он кодирует кавычки, что важно, если вы собираетесь использовать результат, например, в значении атрибута.
function htmlEscape(str) {
return str
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(/</g, '<')
.replace(/>/g, '>');
}
// I needed the opposite function today, so adding here too:
function htmlUnescape(str){
return str
.replace(/"/g, '"')
.replace(/'/g, "'")
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/&/g, '&');
}
Обновление 2013-06-17:
В поисках самого быстрого выхода я нашел эту реализацию replaceAll
метод:
http://dumpsite.com/forum/index.php?topic=4.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 года спустя) Джанго все еще не выполняет ни одну из этих вещей, поэтому я не уверен, насколько они важны:
https://github.com/django/django/blob/1.8b1/django/utils/html.py
Обновление 2016-04-06:
Вы также можете избежать косой черты /
, Это не требуется для правильного кодирования HTML, однако это рекомендуется OWASP в качестве меры безопасности против XSS. (спасибо @JNF за предложение об этом в комментариях)
.replace(/\//g, '/');
Вот не-jQuery-версия, которая значительно быстрее, чем jQuery. .html()
версия и .replace()
версия. Это сохраняет все пробелы, но, как и версия jQuery, не обрабатывает кавычки.
function htmlEncode( html ) {
return document.createElement( 'a' ).appendChild(
document.createTextNode( html ) ).parentNode.innerHTML;
};
Скорость: http://jsperf.com/htmlencoderegex/17
Выход:
Автор сценария:
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> & hello</div>';
document.getElementById( 'same' ).textContent =
'html === htmlDecode( htmlEncode( html ) ): '
+ ( html === htmlDecode( htmlEncode( html ) ) );
HTML:
<input id="hidden" type="hidden" value="chalk & cheese" />
<input id="text" value="" />
<div id="same"></div>
Я знаю, что это старый, но я хотел опубликовать вариант принятого ответа, который будет работать в 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();
}
Подчеркивание обеспечивает _.escape()
а также _.unescape()
методы, которые делают это.
> _.unescape( "chalk & cheese" );
"chalk & cheese"
> _.escape( "chalk & cheese" );
"chalk & cheese"
Для тех, кто предпочитает простой javascript, вот метод, который я успешно использовал:
function escapeHTML (str)
{
var div = document.createElement('div');
var text = document.createTextNode(str);
div.appendChild(text);
return div.innerHTML;
}
Хороший ответ. Обратите внимание, что если значение для кодирования undefined
или же null
с jQuery 1.4.2 вы можете получить такие ошибки, как:
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. Вы можете закодировать каждый символ в вашей строке:
function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}
Или просто нацеливайтесь на главных героев, о которых нужно беспокоиться (&, inebreaks, <,>, "и '), например:
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 &ersand (it has to be first),
* \x0A is newline,
*************/
<textarea id=test rows="9" cols="55"></textarea>
<div id="testing">www.WHAK.com</div>
FWIW, кодировка не теряется. Кодировка используется анализатором разметки (браузером) во время загрузки страницы. Как только источник прочитан и проанализирован, и браузер загрузил DOM в память, кодировка была проанализирована в том, что он представляет. Таким образом, к тому времени, когда ваш JS выполняется для чтения чего-либо в памяти, символ, который он получает, представляет собой то, что представляет кодировка.
Возможно, я работаю строго над семантикой, но я хотел, чтобы вы поняли цель кодирования. Слово "потерял" звучит так, как будто что-то не работает так, как должно.
Прототип имеет встроенный класс String. Так что, если вы используете / планируете использовать Prototype, он делает что-то вроде:
'<div class="article">This is an article</div>'.escapeHTML();
// -> "<div class="article">This is an article</div>"
Вот простое решение JavaScript. Он расширяет объект String методом "HTMLEncode", который можно использовать для объекта без параметра или с параметром.
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("æåøåæå"))
Я сделал суть "метод HTMLEncode для JavaScript".
afaik в javascript нет никаких простых методов HTML Encode/Decode.
Однако, что вы можете сделать, это использовать JS для создания произвольного элемента, установить его внутренний текст, а затем прочитать его с помощью innerHTML.
скажем, с jQuery это должно работать:
var helper = $('chalk & cheese').hide().appendTo('body');
var htmled = helper.html();
helper.remove();
или что-то в этом роде
Моя функция чистого 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;
}
Основано на санитарной обработке angular... (синтаксис модуля 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, '<');
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, '&').
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, '<').
replace(/>/g, '>');
}
export default {encode,decode};
Вот немного, что подражает Server.HTMLEncode
Функция из ASP Microsoft, написанная на чистом 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;
}
Результат не кодирует апострофы, но кодирует другие специальные элементы HTML и любые символы вне диапазона 0x20-0x7e.
У меня была похожая проблема, и я решил ее с помощью функции encodeURIComponent
из JavaScript ( документация)
Например, в вашем случае, если вы используете:
<input id='hiddenId' type='hidden' value='chalk & cheese' />
а также
encodeURIComponent($('#hiddenId').attr('value'))
ты получишь chalk%20%26%20cheese
, Даже места сохранены.
В моем случае мне пришлось закодировать одну обратную косую черту, и этот код работает отлично
encodeURIComponent('name/surname')
и я получил name%2Fsurname
Вам не нужно экранировать / кодировать значения, чтобы перемещать их из одного поля ввода в другое.
<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 не вставляет необработанный HTML или что-либо еще; он просто говорит DOM, чтобы установить value
свойство (или атрибут; не уверен). В любом случае, DOM решает любые проблемы с кодированием для вас. Если вы не делаете что-то странное, как использование document.write
или же eval
HTML-кодирование будет эффективно прозрачным.
Если вы говорите о создании нового текстового поля для хранения результата... это все еще так же просто. Просто передайте статическую часть HTML в jQuery, а затем установите остальные свойства / атрибуты для объекта, который он возвращает вам.
$box = $('<input type="text" name="whatever">').val($('#hiddenId').val());
Если вы хотите использовать jQuery. Я нашел это:
http://www.jquerysdk.com/api/jQuery.htmlspecialchars
(часть плагина jquery.string, предлагаемого jQuery SDK)
Я считаю, что проблема с прототипом заключается в том, что он расширяет базовые объекты в JavaScript и будет несовместим с любым jQuery, который вы, возможно, использовали. Конечно, если вы уже используете Prototype, а не jQuery, это не будет проблемой.
РЕДАКТИРОВАТЬ: Также есть это, который является портом строковых утилит Prototype для jQuery:
Я столкнулся с некоторыми проблемами с обратной косой чертой в строке "Домен \ Пользователь".
Я добавил это к другим побегам от ответа Anentropic
.replace(/\\/g, '\')
Что я нашел здесь: Как избежать обратной косой черты в JavaScript?
var htmlEnDeCode = (function() {
var charToEntityRegex,
entityToCharRegex,
charToEntity,
entityToChar;
function resetCharacterEntities() {
charToEntity = {};
entityToChar = {};
// add the default set
addCharacterEntities({
'&' : '&',
'>' : '>',
'<' : '<',
'"' : '"',
''' : "'"
});
}
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.
HtmlEncodes заданное значение
var htmlEncodeContainer = $('<div />');
function htmlEncode(value) {
if (value) {
return htmlEncodeContainer.text(value).html();
} else {
return '';
}
}
<script>
String.prototype.htmlEncode = function () {
return String(this)
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(/</g, '<')
.replace(/>/g, '>');
}
var aString = '<script>alert("I hack your site")</script>';
console.log(aString.htmlEncode());
</script>
Будет выводить: <script>alert("I hack your site")</script>
.htmlEncode () будет доступен для всех строк после определения.
Некромантинг.
Для этого определенно не требуется jQuery!
Вот порт JavaScript из System.Web.HttpUtility (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("&");
break;
case '>':
output.push(">");
break;
case '<':
output.push("<");
break;
case '"':
output.push(""");
break;
case '\'':
output.push("'");
break;
case '\uff1c':
output.push("<");
break;
case '\uff1e':
output.push(">");
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("");
}
Используя некоторые другие ответы здесь, я сделал версию, которая заменяет все соответствующие символы за один проход, независимо от количества различных закодированных символов (только один вызов replace()
) так будет быстрее для больших строк.
Он не зависит от существования DOM API или других библиотек.
window.encodeHTML = (function() {
function escapeRegex(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
var encodings = {
'&' : '&',
'"' : '"',
'\'' : ''',
'<' : '<',
'>' : '>',
'\\' : '/'
};
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('<>&"\'')
Получить <>&"'
Выбирая что escapeHTML()
делает в prototype.js
Добавление этого скрипта поможет вам избежать HTML:
String.prototype.escapeHTML = function() {
return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')
}
теперь вы можете вызывать метод escapeHTML для строк в вашем скрипте, например:
var escapedString = "<h1>this is HTML</h1>".escapeHTML();
// gives: "<h1>this is HTML</h1>"
Надеюсь, это поможет любому, кто ищет простое решение, без необходимости включать весь prototype.js
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);