Skip to content

Commit 8078a9b

Browse files
committed
handle custom slugify
1 parent 0cabe66 commit 8078a9b

File tree

2 files changed

+17
-13
lines changed

2 files changed

+17
-13
lines changed

src/node/markdown/markdown.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ export async function createMarkdownRenderer(
242242
.use(
243243
linkPlugin,
244244
{ target: '_blank', rel: 'noreferrer', ...options.externalLinks },
245-
base
245+
base,
246+
options.anchor?.slugify ?? slugify
246247
)
247248
.use(lineNumberPlugin, options.lineNumbers)
248249

src/node/markdown/plugins/link.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ const indexRE = /(^|.*\/)index.md(#?.*)$/i
1616
export const linkPlugin = (
1717
md: MarkdownItAsync,
1818
externalAttrs: Record<string, string>,
19-
base: string
19+
base: string,
20+
slugify: (str: string) => string
2021
) => {
2122
md.renderer.rules.link_open = (
2223
tokens,
@@ -27,9 +28,12 @@ export const linkPlugin = (
2728
) => {
2829
const token = tokens[idx]
2930
const hrefIndex = token.attrIndex('href')
30-
const targetIndex = token.attrIndex('target')
31-
const downloadIndex = token.attrIndex('download')
32-
if (hrefIndex >= 0 && targetIndex < 0 && downloadIndex < 0) {
31+
if (
32+
hrefIndex >= 0 &&
33+
token.attrIndex('target') < 0 &&
34+
token.attrIndex('download') < 0 &&
35+
token.attrGet('class') !== 'header-anchor' // header anchors are already normalized
36+
) {
3337
const hrefAttr = token.attrs![hrefIndex]
3438
const url = hrefAttr[1]
3539
if (isExternal(url)) {
@@ -54,9 +58,7 @@ export const linkPlugin = (
5458
) {
5559
normalizeHref(hrefAttr, env)
5660
} else if (url.startsWith('#')) {
57-
hrefAttr[1] = decodeURI(hrefAttr[1])
58-
.normalize('NFKD')
59-
.replace(/[\u0300-\u036F]/g, '')
61+
hrefAttr[1] = decodeURI(normalizeHash(hrefAttr[1]))
6062
}
6163

6264
// append base to internal (non-relative) urls
@@ -74,7 +76,7 @@ export const linkPlugin = (
7476
const indexMatch = url.match(indexRE)
7577
if (indexMatch) {
7678
const [, path, hash] = indexMatch
77-
url = path + hash.normalize('NFKD').replace(/[\u0300-\u036F]/g, '')
79+
url = path + normalizeHash(hash)
7880
} else {
7981
let cleanUrl = url.replace(/[?#].*$/, '')
8082
// transform foo.md -> foo[.html]
@@ -90,10 +92,7 @@ export const linkPlugin = (
9092
cleanUrl += '.html'
9193
}
9294
const parsed = new URL(url, 'http://a.com')
93-
url =
94-
cleanUrl +
95-
parsed.search +
96-
parsed.hash.normalize('NFKD').replace(/[\u0300-\u036F]/g, '')
95+
url = cleanUrl + parsed.search + normalizeHash(parsed.hash)
9796
}
9897

9998
// ensure leading . for relative paths
@@ -108,6 +107,10 @@ export const linkPlugin = (
108107
hrefAttr[1] = decodeURI(url)
109108
}
110109

110+
function normalizeHash(str: string) {
111+
return str ? encodeURI('#' + slugify(decodeURI(str).slice(1))) : ''
112+
}
113+
111114
function pushLink(link: string, env: MarkdownEnv) {
112115
const links = env.links || (env.links = [])
113116
links.push(link)

0 commit comments

Comments
 (0)