为什么RegEx输出转义文本而不是HTML

Why does RegEx output escaped text instead of HTML

本文关键字:HTML 文本 RegEx 输出 转义 为什么      更新时间:2023-09-26

我正在编写一个Chrome扩展,它在与某个正则表达式匹配的每个字符串周围添加一个<span> ... </span>。RegEx匹配非常有效,但我似乎找不到在文本周围正确添加span标记的方法。

到目前为止,我的代码是:

// main.js
var regex_pattern = new RegEx('(apple)', 'g'); // Let's pretend I want to match every instance of 'apple'
var textNodes = getTextNodes(); // A function that returns a list of every text node from the DOM
for (var i = 0; i < textNodes.length; i++) {
    if (textNodes[i].nodeValue.match(regex_pattern)) {
        textNodes[i].nodeValue = textNodes[i].nodeValue.replace(regex_pattern, "<span class='highlight'>$&</span>");
    }
}

这将正确识别RegEx模式(在本例中为"apple")的每个匹配项,并输出<span class="highlight">apple</span>。唯一的问题是,Chrome不将其视为HTML,而是将其视为由文本处理——因此,与其看到根据highlight类设计的世界"苹果",不如看到文字输出:<span class="highlight">apple<span>

为什么会发生这种情况,以及如何修复它以便正确应用样式?意识到这不太理想,我尝试使用insertBefore()方法将匹配的文本包装在一个跨度中,但这没有任何作用,它会出错或无法添加span节点,这取决于我如何调整代码。感谢您提供的任何见解!

不能使用nodeValue将文本节点替换为任意HTML。

您必须手动操作:

function replaceNodeWithHTML(node, html) {
  var parent = node.parentNode;
  if(!parent) return;
  var next = node.nextSibling;
  var parser = document.createElement('div');
  parser.innerHTML = html;
  while(parser.firstChild)
    parent.insertBefore(parser.firstChild, next);
  parent.removeChild(node);
}
var regex_pattern = /(apple)/g;
var textNodes = [document.querySelector('div').firstChild];
for (var i = 0; i < textNodes.length; i++)
  if (textNodes[i].nodeValue.match(regex_pattern))
    replaceNodeWithHTML(
      textNodes[i], 
      textNodes[i].nodeValue.replace(regex_pattern, "<span class='highlight'>$&</span>")
    );
.highlight {
  background: yellow;
}
<div>I have an (apple). You have an (apple) too.</div>

如果节点有insertAdjacentHTML方法,但只有元素有,则会更容易。

在元素上设置.innerHTML。设置textNode.nodeValue值直接设置文本。