繁体   English   中英

将 HTML 标签转义为 HTML 实体的最快方法?

[英]Fastest method to escape HTML tags as HTML entities?

我正在编写一个 Chrome 扩展程序,它涉及执行以下许多工作:通过将<>&转换为&lt;来清理可能包含 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 个字符之间的字符串,如果这有所不同的话。

(我的一个想法是不要对大于号进行编码——这样做会有什么真正的危险吗?)

这是您可以执行此操作的一种方法:

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

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

这是一个演示。

您可以尝试传递一个回调函数来执行替换:

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函数进行比较,并使用Dmitrij提出的DOM方法。

你的方式似乎更快...

不过,你为什么需要它?

Martijn 的方法作为原型函数:

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

最快的方法是:

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

这种方法比基于“replace”的方法快两倍,参见http://jsperf.com/htmlencoderegex/35

来源: https : //stackoverflow.com/a/17546215/698168

一个更快/更短的解决方案是:

escaped = new Option(html).innerHTML

这与 JavaScript 的一些奇怪的痕迹有关,其中 Option 元素保留了一个自动执行此类转义的构造函数。

归功于https://github.com/jasonmoo/t.js/blob/master/t.js

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

多合一脚本:

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

 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>

Martijn 的方法作为单个函数处理标记(在 javascript 中使用):

function escapeHTML(html) {
    var fn=function(tag) {
        var charsToReplace = {
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&#34;'
        };
        return charsToReplace[tag] || tag;
    }
    return html.replace(/[&<>"]/g, fn);
}

我不完全确定速度,但如果您正在寻找简单性,我建议使用 lodash/underscore转义函数。

我会将XMLSerializer添加到该堆中。 它在不使用任何对象缓存的情况下提供最快的结果(不在序列化程序上,也不在 Text 节点上)。

function serializeTextNode(text) {
  return new XMLSerializer().serializeToString(document.createTextNode(text));
}

额外的好处是它支持与文本节点不同的序列化属性:

function serializeAttributeValue(value) {
  const attr = document.createAttribute('a');
  attr.value = value;
  return new XMLSerializer().serializeToString(attr);
}

您可以通过检查规范来查看它实际替换的内容,包括 文本节点属性值 完整的文档有更多的节点类型,但概念是一样的。

至于性能,它在不缓存时是最快的。 当您允许缓存时,在带有子 Text 节点的 HTMLElement 上调用innerHTML是最快的。 正则表达式将是最慢的(正如其他评论所证明的那样)。 当然,XMLSerializer 在其他浏览器上可能更快,但在我(有限的)测试中, innerHTML是最快的。


最快单线:

new XMLSerializer().serializeToString(document.createTextNode(text));

最快的缓存:

const cachedElementParent = document.createElement('div');
const cachedChildTextNode = document.createTextNode('');
cachedElementParent.appendChild(cachedChildTextNode);

function serializeTextNode(text) {
  cachedChildTextNode.nodeValue = text;
  return cachedElementParent.innerHTML;
}

https://jsperf.com/htmlentityencode/1

节目有点晚了,但是使用encodeURIComponent()decodeURIComponent() 有什么问题?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM