正则要求: 没有id属性的h1/2标签,支持过滤嵌套标签生成string作为锚点id

  • <h[12]: 匹配 <h1> 或 <h2> 标签的开始。
  • (?![^>]*\bid=): 使用负向前瞻,确保标签中没有 id 属性。
  • [^>]*: 匹配 <h1> 或 <h2> 标签中的其他属性(如果有的话)。
  • ([\s\S]*?): 捕获标签内部的所有字符,包括空格和换行符。
  • .*? 是非贪婪模式,表示尽可能少地匹配字符,直到遇到关闭标签。这是嵌套标签过滤的关键
  • </h[12]>: 匹配标签的闭合部分,确保 <h1> 或 <h2> 标签完整闭合。
  • g: 全局匹配,用于匹配所有符合条件的标签。
  • s: 处理标签内容跨行的情况。
const reg = /(<h[12](?![^>]*\bid=)[^>]*)>(([\s\S]*?)<\/h[12]>)/gsi;

/**
 * @description 过滤html字符串中h1、h2标签作为锚点
 * @description 锚点id要求去除制表符、&nbsp;等空白字符
 * @param {String} htmlStr html字符串
 * @return {String} 加了锚点的str html字符串
 */
function filterHtmlToAnchor(htmlStr = "") {
  return htmlStr.replace(reg, (match, p1, p2, p3) => {
    // console.log(match)
    // console.log('p1 = ', p1)
    // console.log('p2 = ', p2)
    // console.log('p3 = ', p3)
    if (p1 && p3) {
      // NOTE: /<[^>]*>/g 嵌套标签支持
      // NOTE: &nbsp;|&emsp;|&ensp;\u200B\u200C 空格、换行符过滤
      const title =
        p3
          .replace(/<[^>]*>/g, "")
          .replace(/[\u200B\u200C\u200D\u00A0\u1680\u2002\u2003\u2004\u2005\u2008\u2009\u200A\u205F\u3000\u202F\t\n\r\f\v\xA0]/g, "")
          .replace(/(&nbsp;|&emsp;|&ensp;)/g, "")
          .trim() || "";
      const id = title.replaceAll(" ", "-");
      return `${p1} id="${id}">${p2}`;
    }
    return match;
  });
}

正则要求: 过滤拥有id属性的h1/2标签,支持嵌套标签

  • 正则实现和上面差不多,唯一区别捕获组不同,因为要拿到标签id和标签内容,作为锚点的href和content
  • \bid="([^"]*)" 匹配并捕获id
  • [^>]* 匹配标签其他属性,这个要注意下,id前后都有

    const reg = /<h[12][^>]*\bid="([^"]*)"[^>]*>([\s\S]*?)<\/h[12]>/gis;
    
    /**
     * @description 过滤html字符串中有锚点的h1、h2标签
     * @param {String} htmlStr html字符串
     * @return {Anchor[]} 锚点列表[]
     */
    function filterHtmlToAnchor(htmlStr: string = ''): Anchor[] {
    try {
      return [...htmlStr.matchAll(reg)].map(item => {
        const [_, id, content] = item || [];
        if (id && content) {
          return {
            href: `#${id}`,
            title: (id || '').replace('-', ''),
          }
        }
        return false;
      }).filter(Boolean) as Anchor[];
    } catch (error) {
      return []
    }
    }

肥皂泡
382 声望6 粉丝

码农