正則要求: 沒有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 [] } }