You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中实现忽略HTML标签的HTML内容搜索高亮功能

Angular HTML文本搜索高亮实现方案

问题背景

我正在Angular中开发HTML文本内特定词汇/短语的搜索高亮功能,目前遇到的核心问题是:待搜索文本包含HTML元素,用innerHTML插入后,搜索class、<span>这类内容时会把HTML标签也显示出来。我需要保留原HTML的格式(比如加粗、斜体),同时搜索时忽略HTML标签(不让标签可见),还要正确插入<mark>标签高亮匹配内容,且不破坏原有HTML结构。

需求示例

  • 搜索输入:Bone
    传入HTML:<p> bla bla <span class="italic">Bone</span>
    预期结果:<p> bla bla <span class="italic"><mark>Bone</mark></span>

  • 搜索输入:bla
    传入HTML:<p> bla bla <span class="italic">Bone</span>
    预期结果:<p> <mark>bla</mark> <mark>bla</mark> <span class="italic">Bone</span>

  • 搜索输入:bla bone
    传入HTML:<p> bla bla <span class="italic">Bone</span>
    预期结果:<p> <mark>bla</mark> <mark>bla</mark> <span class="italic"><mark>Bone</mark></span>

我的解决方案代码

transform(html: string, searchText: string): any {
  if (!searchText) {
    return this.sanitizer.bypassSecurityTrustHtml(html);
  }
  const parser = new DOMParser();
  const doc = parser.parseFromString(html, 'text/html');
  searchText.split(/\s+/).forEach((term) => {
    if (term) {
      this.highlightText(doc.body, term);
    }
  });
  return this.sanitizer.bypassSecurityTrustHtml(doc.body.innerHTML);
}

public highlightText(node: Node, searchText: string): void {
  const escapedText = this.escapeSpecialCharactersFromText(searchText);
  if (node.nodeType === Node.TEXT_NODE) {
    const match = node.textContent.match(escapedText);
    if (match) {
      this.replaceMatchedTextWithMarker(node, escapedText);
    }
  } else if (node.nodeType === Node.ELEMENT_NODE) {
    this.goRecursivelyThroughTheNode(node, searchText);
  }
}

private goRecursivelyThroughTheNode(node: Node, searchText: string) {
  Array.from(node.childNodes).forEach((child) => this.highlightText(child, searchText));
}

private escapeSpecialCharactersFromText(searchText: string) {
  return new RegExp(`(${searchText.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')})`, 'gi');
}

private replaceMatchedTextWithMarker(node: Node, searchRegex: RegExp) {
  const highlightedHtml = node.textContent.replace(searchRegex, '<mark>$1</mark>');
  const span = document.createElement('span');
  span.innerHTML = highlightedHtml;
  node.parentNode.replaceChild(span, node);
}

方案说明

  1. HTML解析与安全处理:用DOMParser解析传入的HTML字符串,避免直接操作字符串破坏标签结构;通过Angular的DomSanitizer处理HTML内容,规避XSS风险。
  2. 节点遍历逻辑:仅针对文本节点做匹配处理,跳过HTML元素节点,确保搜索时完全忽略标签内容。
  3. 正则转义处理:对搜索关键词中的特殊字符进行转义,避免正则表达式语法错误导致的匹配异常。
  4. 文本替换与节点替换:在匹配到的文本节点中插入<mark>标签,通过创建新的<span>节点替换原文本节点,保证原有HTML层级结构不受影响。

内容的提问来源于stack exchange,提问作者yoyo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 02:10:40