簡體   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