regex JS bug:高亮单词,不敏感

voase2hg  于 2023-06-25  发布在  其他
关注(0)|答案(1)|浏览(99)

它很容易突出显示的话,框架自由,不区分大小写,即使在html标记的代码。
可以帮助改进纯JavaScript代码吗?
工作,几乎完美。

(document.body).realcar("word high");

Bug仅在以下情况下发生:用户搜索连续的单词。
第二个单词被替换为句子中的其他单词,该单词位于“”(文本片段的最后一个空格)之后。因为它不替换为搜索到的第二个单词。
完美地工作来搜索:“light nos”,在这种情况下:Highlight <strong>nossa!</strong>
窃听功能:

HTMLElement.prototype.realcar = function(word) { var el = this;
const wordss = word.trim().sanitiza().split(" ").filter(word1 => word1.length > 2);
  const expr = new RegExp(wordss.join('|'), 'ig'); 
  let expr00 = expr; 
  const RegExpUNICO=wordss; 
  const nodes = Array.from(el.childNodes); 

  for (let i = 0; i < nodes.length; i++) {
    const node = nodes[i];

    if (node.nodeType === 3) {
      const nodeValue = node.nodeValue;  let matches = [];
      while ((match = expr.exec((nodeValue).sanitiza())) !== null) {
        //console.log("++"+match); 
        matches.push(match[0]);
      const palavrar = nodeValue.substring(match.index, match.index+match[0].length);
    RegExpUNICO.push(palavrar); 
        }
      expr00 = RegExpUNICO.join('|');
      let expr0 = new RegExp(expr00, 'ig');
      console.log("**"+expr00);
       
      
      
      if (matches) {
        const parts = nodeValue.split(expr0);

        for (let n = 0; n < parts.length; n++) {
          if (n) {
            const xx = document.createElement("hightx");
            xx.style.border = '1px solid blue';
            xx.style.backgroundColor = '#ffea80'; 
            const startIndex = nodeValue.indexOf(parts[n - 1]) + parts[n - 1].length;
            const palavra = node.nodeValue.substr(startIndex, matches[n - 1].length);
            xx.appendChild(document.createTextNode(palavra));
            el.insertBefore(xx, node);
          }

          if (parts[n]) {
            el.insertBefore(document.createTextNode(parts[n]), node);
          }
        }

        el.removeChild(node);
      }
    } else {
      node.realcar(word);
    }
  } 
}

在这里尝试代码:https://jsbin.com/vegihit/edit?js,console,output请帮助调试和修复它!

csga3l58

csga3l581#

主要问题在这一行:

const startIndex = nodeValue.indexOf(parts[n - 1]) + parts[n - 1].length;

这假设parts[n - 1]nodeValue中只出现一次,但不能保证。例如,parts[n - 1]可能是一个空格,并且在字符串的前面出现过,然后会选择错误的单词。
另一个问题较少的问题是if (matches)将始终为true,因为即使是空数组也是真实值。应该是if (matches.length)
为了解决第一个问题,有几种可能的解决方案:你的目标是知道下一个相邻的减法是从nodeValue中提取的。您可以通过在nodeValue.split(expr0)的输出中包含分隔符来实现这一点。你可以通过在正则表达式中添加一个 capture group 来实现。这意味着循环将同时迭代不匹配的子字符串和匹配的子字符串--覆盖整个字符串,没有遗漏。
以下是相关代码的更正:

if (matches.length) { // Must test the .length
    // Move the creation of `expr0` here :
    // Create a capture group by adding parentheses: 
    const expr00 = "(" + RegExpUNICO.join('|') + ")";
    const expr0 = new RegExp(expr00, 'ig');
    const parts = nodeValue.split(expr0);
    
    for (let n = 0; n < parts.length; n++) {
        const textNode = document.createTextNode(parts[n]);
        if (n % 2) { // A matched term; always at odd index because of capture group
            const xx = document.createElement("hightx");
            xx.style.border = '1px solid blue';
            xx.style.backgroundColor = '#ffea80'; 
            // No more need to determine an index or length: we have the exact substring
            xx.appendChild(textNode);
            el.insertBefore(xx, node);
        } else if (parts[n]) { // A (nonempty) substring that is not part of a match
            el.insertBefore(textNode, node);
        }
    }
    el.removeChild(node);
}

相关问题