正则要求: 没有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要求去除制表符、 等空白字符
* @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: | | \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(/( | | )/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 [] } }
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。