FED

©FrontEndDev.org
2015 - 2024
web@2.22.0 api@2.20.0

一行代码实现 unescape html

实体符

在 HTML 中,某些字符是预留的。在 HTML 中不能使用小于号(<)和大于号(>),这是因为浏览器会误认为它们是标签。如果希望正确地显示预留字符,我们必须在 HTML 源代码中使用字符实体(character entities)。如需显示小于号,我们必须这样写:&lt;&#60;或者&#x3c;;

不同的表现格式是根据原始字符的 ascii 码来进行关联的。其中,<符号对应的十进制 ascii 为 60,对应的十六进制为 3c。

因此,对实体符的解码,需要匹配符合格式的&#来进行解码。

解码

根据格式得出正则:

/&#(x)?([\w\d]{0,5});/ig

然后进行字符串替换

/**
 * 解码 html 实体符
 * @param str {String} html 实体符
 * @returns {String}
 */
var unescapeHTML = function (str) {
    return str.replace(/&#(x)?([\w\d]{0,5});/ig, function (full, hex, code) {
        return String.fromCharCode(parseInt(code, hex ? 16 : 10));
    });
};

此时,一些如&lt;这样的字符是无法正常替换的,需要建立一个 map 表来进行处理。


/**
 * 解码 html 实体符 map
 * @type {Object}
 */
var unescapeHTMLMap = {
    '&': /&amp;/g,
    '<': /&lt;/g,
    '>': /&gt;/g,
    '"': /&quot;/g,
    '\'': /&apos;/g,
    '/': /&#x2f;/g
};
/**
 * 解码 html 实体符
 * @param str {String} html 实体符
 * @returns {String}
 */
var unescapeHTML = function (str) {
    str = str.replace(/&#(x)?([\w\d]{0,5});/ig, function (full, hex, code) {
        return String.fromCharCode(parseInt(code, hex ? 16 : 10));
    });

    for (var src in unescapeHTMLMap) {
        str = str.replace(unescapeHTMLMap[src], src);
    }

    return str;
};

至此,一个完整的解码 html 实体符的功能就完成了。

真·一行

利用 innerHTML 和 textContent 来实现。

/**
 * 解码 html 实体符
 * @param str {String} html 实体符
 * @returns {String}
 */
var unescapeHTML = (function (str) {
    var $p = document.createElement('p');

    $p.style.display = 'none';
	document.body.appendChild($p);

    return function (str) {
        $p.innerHTML = str;

        return $p.textContent || $p.innerText;
    };
}());

如果原始字符串有 html 标签,则会被过滤。 如

unescapeHTML('<&lt;&#60;&#x3c;')
// => "<<<<"
unescapeHTML('<&lt;&#60;&#x3c;<a></a>')
// => "<<<<"

原始的<a>标签被过滤掉了。

既然 html 标签会被过滤,那么我们可以在开始的时候进行一次 escape 转换即可:

/**
 * 解码 html 实体符
 * @param str {String} html 实体符
 * @returns {String}
 */
var unescapeHTML = (function (str) {
    var p = document.createElement('p');

    return function (str) {
        // 处理掉 < 符号,防止 html 标签(如:<a>)被过滤
        p.innerHTML = (str + '').replace(/</g, '&lt;');

        return p.textContent || p.innerText || '';
    };
}());