首页 > 解决方案 > 替换和正则表达式异常

问题描述

我想将文本的所有单词包装在<trans>标签中,以便能够处理每个单词。将它们悬停,点击翻译等。

为此,我需要在我的替换函数中有一个例外来忽略 html 标签,如<br>or <span>

这是我的功能:

function wrapWords(str, tmpl) {
  return str.replace(/(?![<br>\<span class="gras">\</span>])[a-zA-ZÀ-ÿ]+/gi, tmpl || "<trans>$&</trans>");
}

此功能适用于俄语字符,但不适用于法语字符。问题是<br>and<span>异常不包括法语字符 b,r,s,p,a... 因为有些单词没有正确包装在我的<trans>标签中。

有谁知道我如何排除一组字符(例如特定标签<br>)而不影响法语中的字母 b 和 r ?

感谢您的任何回答!

标签: javascriptregexreplace

解决方案


正确使用 DOM 会稍微复杂一些,但无需担心极端情况,因为它非常简单。

您想要拆分文本,因此只对文本节点进行操作是有意义的。要查找所有文本节点,我们可以评估一个 XPath,或者我们可以构造一个TreeWalker.

一旦我们知道我们想要在哪些节点上进行操作,我们一次取一个节点并获得全空间和非空间序列。每个都将转换为另一个文本节点,但无空格序列将另外包装在一个<span>. 我们将它们一一附加在原始节点的前面,这将保证正确的顺序,最后我们将删除原始节点,当替换节点都在它们的位置时。

function getTextNodes(node) {
  let walker = document.createTreeWalker(node, NodeFilter.SHOW_TEXT, null, false);
  let textnodes = [];
  let textnode;
  while (textnode = walker.nextNode()) {
    textnodes.push(textnode);
  }
  return textnodes;
}
function wrap(element) {
  getTextNodes(element).forEach(node => {
    node.textContent.replace(/(\S+)|(\s+)/g, (match, word, space) => {
      let textnode = document.createTextNode(match);
      let newnode;
      if (word) {
        newnode = document.createElement('trans');
        newnode.appendChild(textnode);
      } else {
        newnode = textnode;
      }
      node.parentNode.insertBefore(newnode, node);
    });
    node.remove();
  });
}

wrap(document.getElementById('wrapthis'));
trans {
  background-color: pink;
}
Not affected<br/>

<div id="wrapthis">
  This is affected<br>
  <span class="gras">HTML tags are fine</span><br/>
  This as well<br/>
</div>

Not affected<br/>


推荐阅读