Skip to content

文本内容高亮

javascript
/**
 * 高亮显示容器中的关键字。
 *
 * @param container - 要搜索和高亮显示关键字的 DOM 容器。
 * @param keyword - 要高亮显示的关键字。
 */
highlight(container: any, keyword: string) {

  // 如果浏览器不支持 CSS Custom Highlight API,直接返回并输出错误信息
  if (!CSS.highlights) {
    console.error('CSS Custom Highlight API is not supported in this browser.');
    return;
  }

  // 清除先前的高亮显示
  // @ts-expect-error: 临时解决缺少 HighlightRegistry 类型的问题。
  CSS.highlights.clear(); // 如果需要清除特定名称的高亮显示,请使用 CSS.highlights.delete('highlightName')

  // 如果关键字为空,则返回
  if (keyword === '') return;

  // 使用 TreeWalker 查找所有文本节点
  const treeWalker = document.createTreeWalker(
    container, NodeFilter.SHOW_TEXT,
    {
      acceptNode: (node) => {
        return node.nodeValue?.toLowerCase().includes(keyword.toLowerCase())
          ? NodeFilter.FILTER_ACCEPT
          : NodeFilter.FILTER_REJECT;
      },
    },
  );

  // 创建 Highlight 对象并注册
  const highlight = new Highlight();
  
  // 遍历所有符合条件的文本节点
  while (treeWalker.nextNode()) {
    const node = treeWalker.currentNode;

    // 跳过特定条件下的节点(例如父节点是 APP-CHAT-MESSAGE 的情况)
    if (node.parentNode?.parentNode?.nextSibling?.nodeName === 'APP-CHAT-MESSAGE') {
      continue;
    }

    let content = node.nodeValue;
    const lowerCaseKeyword = keyword.toLowerCase();
    let startIndex = content?.toLowerCase().indexOf(lowerCaseKeyword);

    // 如果找不到关键字,则继续下一个节点
    if (startIndex === -1 || startIndex === undefined) {
      continue;
    }

    // 循环查找并高亮显示所有匹配的关键字
    while (startIndex !== undefined && startIndex !== -1) {
      const range = new Range();
      range.setStart(node, startIndex);
      range.setEnd(node, startIndex + keyword.length);
      
      // @ts-expect-error: 临时解决缺少 HighlightRegistry 类型的问题。
      highlight.add(range); // 高亮对象添加范围

      content = node.nodeValue;
      startIndex = content?.toLowerCase().indexOf(lowerCaseKeyword, startIndex + keyword.length);
    }
  }

  // 在 HighlightRegistry 中注册高亮实例
  // @ts-expect-error: 临时解决缺少 HighlightRegistry 类型的问题。
  CSS.highlights.set('highlightName', highlight); // 'highlightName' 是自定义的标识符
}