Как декодировать HTML-сущности с помощью jQuery?

308

Как использовать jQuery для декодирования HTML-объектов в строке?

Теги:

17 ответов

387
Лучший ответ

Примечание по безопасности:, используя этот ответ (сохраненный в его первоначальной форме ниже), может ввести lucascaro answer для объяснения уязвимостей в этом ответе и используйте подход либо из этого ответа, либо из Отметьте ответ Amery.

Собственно, попробуйте

var decoded = $("<div/>").html(encodedStr).text();
  • 170
    Не делайте этого с ненадежными данными. Многие браузеры загружают изображения и запускают связанные события, даже если узел не подключен к DOM. Попробуйте запустить $("<div/>").html('<img src="http://www.google.com/images/logos/ps_logo2.png" onload=alert(1337)>') . В Firefox или Safari выдает предупреждение.
  • 0
    @ Майк, так что ты порекомендовал вместо этого? ваш ответ .replace () не годится, если вы не знаете, что заменяете ...
Показать ещё 3 комментария
147

Без jQuery:

function decodeEntities(encodedString) {
    var textArea = document.createElement('textarea');
    textArea.innerHTML = encodedString;
    return textArea.value;
}

console.log(decodeEntities('1 &amp; 2')); // '1 & 2'

Это работает аналогично принятому ответу, но безопасно использовать с ненадежным вводом пользователя.


Проблемы безопасности при сходных подходах

Как отмеченный Майком Самуэлем, выполнение этого с <div> вместо <textarea> с ненадежным пользовательским вводом является уязвимостью XSS, даже если <div> никогда не добавляется в DOM:

function decodeEntities(encodedString) {
    var div = document.createElement('div');
    div.innerHTML = encodedString;
    return div.textContent;
}

// Shows an alert
decodeEntities('<img src="nonexistent_image" onerror="alert(1337)">')

Однако эта атака невозможна против <textarea>, потому что нет элементов HTML, которые разрешены для содержимого <textarea>. Следовательно, любые HTML-теги, все еще присутствующие в "закодированной" строке, будут автоматически закодированы сущностью в браузере.

function decodeEntities(encodedString) {
    var textArea = document.createElement('textarea');
    textArea.innerHTML = encodedString;
    return textArea.value;
}

// Safe, and returns the correct answer
console.log(decodeEntities('<img src="nonexistent_image" onerror="alert(1337)">'))

Выполнение этого с помощью jQuery .html() и .val() вместо использования .innerHTML и .value также небезопасен * для некоторых версий jQuery, даже при использовании textarea. Это связано с тем, что более старые версии jQuery преднамеренно и явно оценивают сценарии, содержащиеся в строке, переданной в .html(). Следовательно, такой код показывает предупреждение в jQuery 1.8:

// Shows alert
$('<textarea>').html('<script>alert(1337)</script>').text()

* Благодаря Эру Пенкман за эту уязвимость.

  • 5
    Может быть хорошей идеей уничтожить текстовую область после извлечения ее значения: decodedString = textArea.value; textArea.remove(); return decodedString;
  • 2
    Или только, если версия javascript действительно поддерживает remove (): if ('remove' in Element.prototype) textArea.remove();
Показать ещё 3 комментария
77

Как сказал Майк Самуэль, не используйте jQuery.html(). text() для декодирования html-объектов, поскольку это небезопасно.

Вместо этого используйте средство визуализации шаблонов, например Mustache.js или decodeEntities от Комментарий @VyvIT.

Underscore.js библиотека утилитных лент поставляется с методами escape и unescape, но они небезопасны для ввода пользователем:

_. escape (string)

_. unescape (строка)

  • 2
    Это на самом деле заслуживает гораздо больше голосов! Определенно мое предпочтительное решение. К настоящему времени они включили unescape в документы.
  • 0
    Спасибо, я обновил свой ответ с прямой ссылкой на новые документы.
Показать ещё 7 комментариев
27

Вопрос ограничивается "с помощью jQuery", но может помочь некоторым узнать, что код jQuery, приведенный в лучшем ответе, здесь ниже: это работает с jQuery или без него:

function decodeEntities(input) {
  var y = document.createElement('textarea');
  y.innerHTML = input;
  return y.value;
}
27

Я думаю, вы смешиваете текст и методы HTML. Посмотрите на этот пример, если вы используете внутренний HTML-код элемента как текст, вы получите декодированные HTML-теги (вторая кнопка). Но если вы используете их как HTML, вы получите представление в формате HTML (первая кнопка).

<div id="myDiv">
    here is a <b>HTML</b> content.
</div>
<br />
<input value="Write as HTML" type="button" onclick="javascript:$('#resultDiv').html($('#myDiv').html());" />
&nbsp;&nbsp;
<input value="Write as Text" type="button" onclick="javascript:$('#resultDiv').text($('#myDiv').html());" />
<br /><br />
<div id="resultDiv">
    Results here !
</div>

Первая кнопка пишет: здесь HTML.

Вторая кнопка пишет: - это контент <B> HTML </B> .

Кстати, вы можете увидеть плагин, который я нашел в плагин jQuery - HTML-декодирование и кодирование, который кодирует и декодирует строки HTML.

15

Вы можете использовать библиотеку he, доступную из https://github.com/mathiasbynens/he

Пример:

console.log(he.decode("J&#246;rg &amp J&#xFC;rgen rocked to &amp; fro "));
// Logs "Jörg & Jürgen rocked to & fro"

I бросил вызов автору библиотеки по вопросу о том, есть ли какая-либо причина использовать эту библиотеку в клиентском коде в пользу <textarea> хак, предоставленный в других ответах здесь и в другом месте. Он дал несколько возможных оправданий:

  • Если вы используете node.js serverside, использование библиотеки для кодирования/декодирования HTML дает вам единственное решение, которое работает как на стороне клиента, так и на серверах.

  • В некоторых алгоритмах декодирования сущностей браузеров есть ошибки или отсутствует поддержка некоторых названных ссылок на символы. Например, Internet Explorer будет как декодировать, так и рендерить неразрывные пробелы (&nbsp;) правильно, но сообщать о них как обычные пробелы вместо неразрывных через свойство DOM element innerText, нарушая <textarea> hack (хотя и только второстепенным образом). Кроме того, IE 8 и 9 просто не поддерживают любую новую ссылку на именованные символы, добавленную в HTML 5. Автор он также проводит тестирование поддержки ссылок на именованные символы на http://mathias.html5.org/tests/html/named-character-references/. В IE 8 он сообщает более тысячи ошибок.

    Если вы хотите изолировать от ошибок браузера, связанных с расшифровкой сущностей и/или иметь возможность обрабатывать полный диапазон имен символов, вы не можете уйти с помощью <textarea> hack; вам понадобится библиотека, подобная ему.

  • Он просто чертовски хорошо чувствует, что делает вещи таким образом, менее хаки.

  • 2
    +1 jQuery не решение для всего. Используйте правильный инструмент для работы.
9

закодировать:

$("<textarea/>").html('<a>').html();      // return '&lt;a&gt'

расшифровывает:

$("<textarea/>").html('&lt;a&gt').val()   // return '<a>'
  • 3
    уже есть ответ, который работает, и он почти идентичен этому. Нам не нужны повторяющиеся ответы
  • 3
    Это правильный ответ. В ответе Тома используется элемент DIV, что делает этот ответ уязвимым для XSS.
Показать ещё 1 комментарий
4

Использование

myString = myString.replace( /\&amp;/g, '&' );

Это проще всего сделать на стороне сервера, потому что, по-видимому, у JavaScript нет встроенной библиотеки для обработки сущностей, и я не нашел ничего в верхней части результатов поиска для различных фреймворков, расширяющих JavaScript.

Найдите "JavaScript-объекты HTML", и вы можете найти несколько библиотек для этой цели, но они, вероятно, будут построены вокруг вышеуказанной логики - замените сущность на сущность.

1

Вы должны создать пользовательскую функцию для html-объектов:

function htmlEntities(str) {
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g,'&gt;').replace(/"/g, '&quot;');
}
  • 0
    Почему ты голосуешь?
  • 0
    Понятия не имею, мне это так помогло +1 л-)
Показать ещё 2 комментария
0

Вот еще одна проблема: Исключенная строка не выглядит читаемой при назначении входного значения

var string = _.escape("<img src=fake onerror=alert('boo!')>");
$('input').val(string);

Exapmle: https://jsfiddle.net/kjpdwmqa/3/

0

Расширить класс String:

String::decode = ->
  $('<textarea />').html(this).text()

и использовать как метод:

"&lt;img src='myimage.jpg'&gt;".decode()
0

Для пользователей ExtJS, если у вас уже есть закодированная строка, например, когда возвращаемое значение библиотечной функции является содержимым innerHTML, рассмотрите эту функцию ExtJS:

Ext.util.Format.htmlDecode(innerHtmlContent)
0

Предположим, что у вас есть строка ниже.

Наши каюты Deluxe - теплые, уютные и удобный

var str = $("p").text(); // get the text from <p> tag
$('p').html(str).text();  // Now,decode html entities in your variable i.e 

str и назначьте тег

.

что он.

0

Мне просто нужно было иметь HTML-объект charater (& dArr;) в качестве значения для кнопки HTML. Код HTML хорошо выглядит с самого начала в браузере:

<input type="button" value="Embed & Share  &dArr;" id="share_button" />

Теперь я добавляю переключатель, который также должен отображать charater. Это мое решение

$("#share_button").toggle(
    function(){
        $("#share").slideDown();
        $(this).attr("value", "Embed & Share " + $("<div>").html("&uArr;").text());
    }

Отображается & dArr; снова в кнопке. Надеюсь, это может помочь кому-то.

  • 0
    Проще было бы использовать escape-последовательность Unicode (например, "Embed & Share \u21d1" ) или, что еще лучше, просто "Embed & Share ⇑" если вы можете обслуживать свой сценарий в UTF-8 (или UTF-16, или любая другая кодировка, которая поддерживает символ)). Использование элемента DOM для синтаксического анализа HTML-сущности просто для того, чтобы вставить произвольный символ Юникода в строку JavaScript, - это хитрый и творческий подход, который мог бы гордить Рубе Голдберга, но не является хорошей практикой; экранирование Юникода на языке специально для обработки этого варианта использования.
-3

Я думаю, что это полная противоположность выбранному решению.

var decoded = $("<div/>").text(encodedStr).html();
  • 1
    Извините, это кодирует это дальше!
-3

Самый простой способ - установить селектор классов для своих элементов, а затем использовать следующий код:

$(function(){
    $('.classSelector').each(function(a, b){
        $(b).html($(b).text());
    });
});

Больше не нужно!

У меня была эта проблема, и я нашел это ясное решение, и он отлично работает.

-3

Чтобы декодировать HTML-объекты с помощью jQuery, просто используйте эту функцию:

function html_entity_decode(txt){
    var randomID = Math.floor((Math.random()*100000)+1);
    $('body').append('<div id="random'+randomID+'"></div>');
    $('#random'+randomID).html(txt);
    var entity_decoded = $('#random'+randomID).html();
    $('#random'+randomID).remove();
    return entity_decoded;
}

Как использовать:

JavaScript:

var txtEncoded = "&aacute; &eacute; &iacute; &oacute; &uacute;";
$('#some-id').val(html_entity_decode(txtEncoded));

HTML:

<input id="some-id" type="text" />

Ещё вопросы

Сообщество Overcoder
Наверх
Меню