Самый быстрый способ избежать тегов HTML в качестве сущностей HTML? - PullRequest
91 голосов
/ 31 марта 2011

Я пишу расширение Chrome, которое включает в себя выполнение лота следующего задания: очистка строк, которые могут содержать теги HTML, путем преобразования <, > и& до &lt;, &gt; и &amp;, соответственно.

(Другими словами, так же, как PHP htmlspecialchars(str, ENT_NOQUOTES) - я не думаю, что есть какая-то реальная необходимость конвертировать двойныесимволы кавычки.)

Это самая быстрая функция, которую я нашел до сих пор:

function safe_tags(str) {
    return str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;') ;
}

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

Может кто-нибудь улучшить это?В основном это строки длиной от 10 до 150 символов, если это имеет значение.

(У меня была одна идея не беспокоиться о кодировании знака «больше» - будет ли с этим какая-то реальная опасность?)

Ответы [ 11 ]

87 голосов
/ 12 февраля 2012

Вот один из способов сделать это:

var escape = document.createElement('textarea');
function escapeHTML(html) {
    escape.textContent = html;
    return escape.innerHTML;
}

function unescapeHTML(html) {
    escape.innerHTML = html;
    return escape.textContent;
}

Вот демоверсия.

72 голосов
/ 31 марта 2011

Вы можете попробовать передать функцию обратного вызова для выполнения замены:

var tagsToReplace = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;'
};

function replaceTag(tag) {
    return tagsToReplace[tag] || tag;
}

function safe_tags_replace(str) {
    return str.replace(/[&<>]/g, replaceTag);
}

Вот тест производительности: http://jsperf.com/encode-html-entities для сравнения с повторным вызовом функции replace и использованиемМетод DOM, предложенный Дмитрием.

Кажется, ваш путь быстрее ...

Зачем он вам нужен?

26 голосов
/ 24 ноября 2012

Метод Мартина как функция-прототип:

String.prototype.escape = function() {
    var tagsToReplace = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;'
    };
    return this.replace(/[&<>]/g, function(tag) {
        return tagsToReplace[tag] || tag;
    });
};

var a = "<abc>";
var b = a.escape(); // "&lt;abc&gt;"
9 голосов
/ 19 июня 2015

Самый быстрый метод:

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

Этот метод примерно в два раза быстрее, чем методы, основанные на «замене», см. http://jsperf.com/htmlencoderegex/35.

Источник: https://stackoverflow.com/a/17546215/698168

8 голосов
/ 31 мая 2015

Исходный код AngularJS также имеет версию внутри angular-sanitize.js .

var SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
    // Match everything outside of normal chars and " (quote character)
    NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;
/**
 * Escapes all potentially dangerous characters, so that the
 * resulting string can be safely inserted into attribute or
 * element text.
 * @param value
 * @returns {string} escaped text
 */
function encodeEntities(value) {
  return value.
    replace(/&/g, '&amp;').
    replace(SURROGATE_PAIR_REGEXP, function(value) {
      var hi = value.charCodeAt(0);
      var low = value.charCodeAt(1);
      return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
    }).
    replace(NON_ALPHANUMERIC_REGEXP, function(value) {
      return '&#' + value.charCodeAt(0) + ';';
    }).
    replace(/</g, '&lt;').
    replace(/>/g, '&gt;');
}
7 голосов
/ 30 июня 2012

Сценарий «все в одном»:

// HTML entities Encode/Decode

function htmlspecialchars(str) {
    var map = {
        "&": "&amp;",
        "<": "&lt;",
        ">": "&gt;",
        "\"": "&quot;",
        "'": "&#39;" // ' -> &apos; for XML only
    };
    return str.replace(/[&<>"']/g, function(m) { return map[m]; });
}
function htmlspecialchars_decode(str) {
    var map = {
        "&amp;": "&",
        "&lt;": "<",
        "&gt;": ">",
        "&quot;": "\"",
        "&#39;": "'"
    };
    return str.replace(/(&amp;|&lt;|&gt;|&quot;|&#39;)/g, function(m) { return map[m]; });
}
function htmlentities(str) {
    var textarea = document.createElement("textarea");
    textarea.innerHTML = str;
    return textarea.innerHTML;
}
function htmlentities_decode(str) {
    var textarea = document.createElement("textarea");
    textarea.innerHTML = str;
    return textarea.value;
}

http://pastebin.com/JGCVs0Ts

3 голосов
/ 09 марта 2019

Еще более быстрое / короткое решение:

escaped = new Option(html).innerHTML

Это связано с каким-то странным пережитком JavaScript, в результате которого элемент Option сохраняет конструктор, который выполняет этот вид экранирования автоматически.

Кредит https://github.com/jasonmoo/t.js/blob/master/t.js

1 голос
/ 26 июля 2015

function encode(r) {
  return r.replace(/[\x26\x0A\x3c\x3e\x22\x27]/g, function(r) {
	return "&#" + r.charCodeAt(0) + ";";
  });
}

test.value=encode('How to encode\nonly html tags &<>\'" nice & fast!');

/*
 \x26 is &ampersand (it has to be first),
 \x0A is newline,
 \x22 is ",
 \x27 is ',
 \x3c is <,
 \x3e is >
*/
<textarea id=test rows=11 cols=55>www.WHAK.com</textarea>
0 голосов
/ 07 ноября 2018

Я не совсем уверен в скорости, но если вы ищете простоту, я бы предложил использовать функцию lodash / underscore escape .

0 голосов
/ 20 марта 2018

Немного опоздал на шоу, но что не так с использованием encodeURIComponent () и decodeURIComponent () ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...