Skip to content

Commit db4982e

Browse files
authored
fix(markdown): avoid leading number in link hash (#1644)
1 parent 7a43fae commit db4982e

File tree

5 files changed

+18
-11
lines changed

5 files changed

+18
-11
lines changed

e2e/docs/router/navigate-by-link.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
<a :href="$withBase('/404.html')" class="not-found">404</a>
1414
<a :href="$withBase('/?home=true')" class="home-with-query">Home</a>
1515
<a :href="$withBase('/?home=true#home')" class="home-with-query-and-hash">Home</a>
16-
<a :href="$withBase('/404.html#404')" class="not-found-with-hash">404</a>
17-
<a :href="$withBase('/404.html#404?notFound=true')" class="not-found-with-hash-and-query">404</a>
16+
<a :href="$withBase('/404.html#_404')" class="not-found-with-hash">404</a>
17+
<a :href="$withBase('/404.html#_404?notFound=true')" class="not-found-with-hash-and-query">404</a>
1818

1919
## Markdown Links with html paths
2020

e2e/docs/router/navigate-by-router.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ const goHomeWithQueryAndHash = () => {
2828
}
2929

3030
const go404WithHash = () => {
31-
router.push('/404.html#404');
31+
router.push('/404.html#_404');
3232
}
3333

3434
const go404WithHashAndQuery = () => {
35-
router.push('/404.html#404?notFound=true');
35+
router.push('/404.html#_404?notFound=true');
3636
}
3737
</script>

e2e/tests/router/navigate-by-link.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ test.describe('markdown links', () => {
3232

3333
test('should preserve hash', async ({ page }) => {
3434
await page.locator('#markdown-links + ul > li > a').nth(4).click()
35-
await expect(page).toHaveURL(`${BASE}404.html#404`)
35+
await expect(page).toHaveURL(`${BASE}404.html#_404`)
3636
await expect(page.locator('#notfound-h2')).toHaveText('NotFound H2')
3737
})
3838

3939
test('should preserve hash and query', async ({ page }) => {
4040
await page.locator('#markdown-links + ul > li > a').nth(5).click()
41-
await expect(page).toHaveURL(`${BASE}404.html#404?notFound=true`)
41+
await expect(page).toHaveURL(`${BASE}404.html#_404?notFound=true`)
4242
await expect(page.locator('#notfound-h2')).toHaveText('NotFound H2')
4343
})
4444
})
@@ -70,13 +70,13 @@ test.describe('html links', () => {
7070

7171
test('should preserve hash', async ({ page }) => {
7272
await page.locator('#html-links + p > a').nth(4).click()
73-
await expect(page).toHaveURL(`${BASE}404.html#404`)
73+
await expect(page).toHaveURL(`${BASE}404.html#_404`)
7474
await expect(page.locator('#notfound-h2')).toHaveText('NotFound H2')
7575
})
7676

7777
test('should preserve hash and query', async ({ page }) => {
7878
await page.locator('#html-links + p > a').nth(5).click()
79-
await expect(page).toHaveURL(`${BASE}404.html#404?notFound=true`)
79+
await expect(page).toHaveURL(`${BASE}404.html#_404?notFound=true`)
8080
await expect(page.locator('#notfound-h2')).toHaveText('NotFound H2')
8181
})
8282
})

e2e/tests/router/navigate-by-router.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ test('should preserve query and hash', async ({ page }) => {
3131

3232
test('should preserve hash', async ({ page }) => {
3333
await page.locator('#not-found-with-hash').click()
34-
await expect(page).toHaveURL(`${BASE}404.html#404`)
34+
await expect(page).toHaveURL(`${BASE}404.html#_404`)
3535
await expect(page.locator('#notfound-h2')).toHaveText('NotFound H2')
3636
})
3737

3838
test('should preserve hash and query', async ({ page }) => {
3939
await page.locator('#not-found-with-hash-and-query').click()
40-
await expect(page).toHaveURL(`${BASE}404.html#404?notFound=true`)
40+
await expect(page).toHaveURL(`${BASE}404.html#_404?notFound=true`)
4141
await expect(page.locator('#notfound-h2')).toHaveText('NotFound H2')
4242
})

packages/markdown/src/plugins/linksPlugin/linksPlugin.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,14 @@ export const linksPlugin: PluginWithOptions<LinksPluginOptions> = (
106106

107107
// notice that the path and hash are encoded by markdown-it
108108
const rawPath = internalLinkMatch[1]
109-
const rawHashAndQueries = internalLinkMatch[2] || ''
109+
110+
// The default slugification function processes anchor links (hash fragments)
111+
// If an anchor starts with a number (e.g., #123), it is replaced with #_number (e.g., #_123)
112+
// This rule is designed to prevent potential URL conflicts, though manually written anchors like #123 are rare in Markdown—hence the special handling.
113+
const rawHashAndQueries = (internalLinkMatch[2] || '').replace(
114+
/^#(\d)/,
115+
'#_$1',
116+
)
110117

111118
// resolve relative and absolute path
112119
const { relativePath, absolutePath } = resolvePaths(

0 commit comments

Comments
 (0)