Repository: HiDeoo/starlight-links-validator (ts)

Issue:
Doesn’t account for multiple headings with the same text
### Describe the bug

Given a Markdown document with headings containing the same text, for example like this contrived one:

```md
## Heading

## Heading
```

`github-slugger` will auto-increment and attach an integer to the end of the generated `id`. So the above Markdown generates the following HTML:

```html
<h2 id="heading">Heading</h2>
<h2 id="heading-1">Heading</h2>
```

This tool [uses the stateless version of `github-slugger`](https://github.com/HiDeoo/starlight-links-validator/blob/f9c988bece239a17c38d1f1c64ffd0c98e15cd6e/packages/starlight-links-validator/libs/remark.ts#L38), so does not expect this behaviour and will fail for links to `#heading-1` in this case:


### To Reproduce

1. Create a document with headings containing the same text.
2. Link to one of the later headings (e.g. with a `-1` suffix).
3. Run the link validator.
4. It will error and flag the `-1` link.

### Expected behavior

Link anchor slugging logic should match the Astro project’s logic and the validation should pass.

### How often does this bug happen?

Every time

### System Info

Observed on macOS, but I suspect that’s not relevant.

### Additional Context

_No response_

Pull request:
fix: account for multiple headings with the same text


**Describe the pull request**

This PR updates the code generating the ID for Markdown headings to use `github-slugger`’s stateful default export, creating an instance for each file.

**Why**

Fixes #11

Ensures headings with the same text each get a unique slug.

**How**

By importing `github-slugger`’s default export and instantiating it inside the remark file processor.

**Screenshots**

n/a


Patch:
diff --git a/packages/starlight-links-validator/libs/remark.ts b/packages/starlight-links-validator/libs/remark.ts
index b0123c3..423483f 100644
--- a/packages/starlight-links-validator/libs/remark.ts
+++ b/packages/starlight-links-validator/libs/remark.ts
@@ -2,7 +2,7 @@ import 'mdast-util-mdx-jsx'
 
 import nodePath from 'node:path'
 
-import { slug } from 'github-slugger'
+import GitHubSlugger, { slug } from 'github-slugger'
 import type { Nodes } from 'hast'
 import { fromHtml } from 'hast-util-from-html'
 import { hasProperty } from 'hast-util-has-property'
@@ -19,6 +19,7 @@ const links: Links = new Map()
 
 export const remarkStarlightLinksValidator: Plugin<[], Root> = function () {
   return (tree, file) => {
+    const slugger = new GitHubSlugger()
     const filePath = normalizeFilePath(file.history[0])
 
     const fileHeadings: string[] = []
@@ -35,7 +36,7 @@ export const remarkStarlightLinksValidator: Plugin<[], Root> = function () {
             break
           }
 
-          fileHeadings.push(slug(content))
+          fileHeadings.push(slugger.slug(content))
 
           break
         }


Test patch:
diff --git a/packages/starlight-links-validator/tests/fixtures/with-valid-links/src/content/docs/index.md b/packages/starlight-links-validator/tests/fixtures/with-valid-links/src/content/docs/index.md
index f1fadbf..b8bdc35 100644
--- a/packages/starlight-links-validator/tests/fixtures/with-valid-links/src/content/docs/index.md
+++ b/packages/starlight-links-validator/tests/fixtures/with-valid-links/src/content/docs/index.md
@@ -14,6 +14,8 @@ title: Index
 - [Test page with hash](/test#title)
 - [Test page with hash](/test/#title)
 
+- [Test page with duplicated hash](/test#title-1)
+
 - [An MDX nested page](/guides/example)
 - [An MDX nested page](/guides/example/)
 
diff --git a/packages/starlight-links-validator/tests/fixtures/with-valid-links/src/content/docs/test.md b/packages/starlight-links-validator/tests/fixtures/with-valid-links/src/content/docs/test.md
index bce953b..9afdc14 100644
--- a/packages/starlight-links-validator/tests/fixtures/with-valid-links/src/content/docs/test.md
+++ b/packages/starlight-links-validator/tests/fixtures/with-valid-links/src/content/docs/test.md
@@ -21,3 +21,7 @@ some content
     test
   </a>
 </div>
+
+## Title
+
+More content.