fix: toc slug

the3ash committed Jul 12, 2025 at 00:16 UTC 0bba6d977c197f316bcdea0c6beb5118106e5b71
1 file changed +35 -1
src/plugins/remark-toc.mjs
+35 -1
@@ -4,6 +4,7 @@ export default function remarkTOC() {
4 return function (tree, file) {
5 const headings = []
6 let headingIndex = 0
7 + const usedSlugs = new Set()
8
9 // Extract headings from AST
10 visit(tree, 'heading', (node) => {
@@ -21,7 +22,9 @@ export default function remarkTOC() {
22 const text = extractTextContent(node)
23 if (!text) return
24
24 - const id = `heading-${headingIndex}`
25 + // Generate unique slug from text
26 + const slug = generateUniqueSlug(text, usedSlugs)
27 + const id = slug
28
29 if (!node.data) node.data = {}
30 if (!node.data.hProperties) node.data.hProperties = {}
@@ -53,3 +56,34 @@ function extractTextContent(node) {
56
57 return text.trim()
58 }
59 +
60 +// Generate a slug from text
61 +function generateSlug(text) {
62 + return (
63 + text
64 + .toLowerCase()
65 + // Keep Chinese characters, English letters, numbers, spaces and hyphens
66 + .replace(/[^\u4e00-\u9fa5a-z0-9\s-]/g, '')
67 + // Replace spaces with hyphens
68 + .replace(/\s+/g, '-')
69 + // Replace multiple hyphens with single hyphen
70 + .replace(/-+/g, '-')
71 + // Remove leading and trailing hyphens
72 + .replace(/^-|-$/g, '')
73 + )
74 +}
75 +
76 +// Generate a unique slug from text
77 +function generateUniqueSlug(text, usedSlugs) {
78 + let slug = generateSlug(text)
79 + let counter = 1
80 + let uniqueSlug = slug
81 +
82 + while (usedSlugs.has(uniqueSlug)) {
83 + uniqueSlug = `${slug}-${counter}`
84 + counter++
85 + }
86 +
87 + usedSlugs.add(uniqueSlug)
88 + return uniqueSlug
89 +}