forked from
quillmatiq.com/augment
Fork of Chiri for Astro for my blog
1import { visit } from 'unist-util-visit'
2
3export 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) => {
11 const level = node.depth
12
13 // Only process h1, h2, h3
14 if (level > 3) return
15
16 // Skip the first h1
17 if (level === 1 && headingIndex === 0) {
18 headingIndex++
19 return
20 }
21
22 const text = extractTextContent(node)
23 if (!text) return
24
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 = {}
31 node.data.hProperties.id = id
32
33 headings.push({
34 level,
35 text,
36 id,
37 index: headingIndex
38 })
39
40 headingIndex++
41 })
42
43 // Store TOC data in file.data.astro.frontmatter
44 if (!file.data.astro) file.data.astro = {}
45 if (!file.data.astro.frontmatter) file.data.astro.frontmatter = {}
46 file.data.astro.frontmatter.toc = headings
47 }
48}
49
50function extractTextContent(node) {
51 let text = ''
52
53 visit(node, 'text', (textNode) => {
54 text += textNode.value
55 })
56
57 return text.trim()
58}
59
60// Generate a slug from text
61function 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
77function 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}