Skip to content

Commit e08e3d2

Browse files
committed
fix: generate better slugs for non latin langs (close #45)
1 parent 55f250c commit e08e3d2

File tree

6 files changed

+46
-6
lines changed

6 files changed

+46
-6
lines changed

docs/config/README.md

+9-2
Original file line numberDiff line numberDiff line change
@@ -113,19 +113,26 @@ Provide config options to the used theme. The options will vary depending on the
113113

114114
## Markdown
115115

116+
### markdown.slugify
117+
118+
- Type: `Function`
119+
- Default: [source](https://github.com/vuejs/vuepress/blob/master/lib/markdown/slugify.js)
120+
121+
Function for transforming header texts into slugs. This affects the ids/links generated for header anchors, table of contents and sidebar links.
122+
116123
### markdown.anchor
117124

118125
- Type: `Object`
119126
- Default: `{ permalink: true, permalinkBefore: true, permalinkSymbol: '#' }`
120127

121-
Options for [markdown-it-anchor](https://github.com/valeriangalliat/markdown-it-anchor).
128+
Options for [markdown-it-anchor](https://github.com/valeriangalliat/markdown-it-anchor). (Note: prefer `markdown.slugify` if you want to customize header ids.)
122129

123130
### markdown.toc
124131

125132
- Type: `Object`
126133
- Default: `{ includeLevel: [2, 3] }`
127134

128-
Options for [markdown-it-table-of-contents](https://github.com/Oktavilla/markdown-it-table-of-contents).
135+
Options for [markdown-it-table-of-contents](https://github.com/Oktavilla/markdown-it-table-of-contents). (Note: prefer `markdown.slugify` if you want to customize header ids.)
129136

130137
### markdown.config
131138

lib/markdown/index.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@ const containers = require('./containers')
77
const emoji = require('markdown-it-emoji')
88
const anchor = require('markdown-it-anchor')
99
const toc = require('markdown-it-table-of-contents')
10+
const _slugify = require('./slugify')
11+
12+
module.exports = ({ markdown = {}} = {}) => {
13+
// allow user config slugify
14+
const slugify = markdown.slugify || _slugify
1015

11-
module.exports = ({ markdown = {}}) => {
1216
const md = require('markdown-it')({
1317
html: true,
1418
typographer: true,
@@ -24,11 +28,13 @@ module.exports = ({ markdown = {}}) => {
2428
// 3rd party plugins
2529
.use(emoji)
2630
.use(anchor, Object.assign({
31+
slugify,
2732
permalink: true,
2833
permalinkBefore: true,
2934
permalinkSymbol: '#'
3035
}, markdown.anchor))
3136
.use(toc, Object.assign({
37+
slugify,
3238
includeLevel: [2, 3]
3339
}, markdown.toc))
3440

@@ -48,5 +54,8 @@ module.exports = ({ markdown = {}}) => {
4854
}
4955
}
5056

57+
// expose slugify
58+
md.slugify = slugify
59+
5160
return md
5261
}

lib/markdown/slugify.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// string.js slugify drops non ascii chars so we have to
2+
// use a custom implementation here
3+
const removeDiacritics = require('diacritics').remove
4+
// eslint-disable-next-line no-control-regex
5+
const rControl = /[\u0000-\u001f]/g
6+
const rSpecial = /[\s~`!@#$%^&*()\-_+=[\]{}|\\;:"'<>,.?/]+/g
7+
8+
module.exports = function slugify (str) {
9+
return removeDiacritics(str)
10+
// Remove control characters
11+
.replace(rControl, '')
12+
// Replace special characters
13+
.replace(rSpecial, '-')
14+
// Remove continous separators
15+
.replace(/\-{2,}/g, '-')
16+
// Remove prefixing and trailing separtors
17+
.replace(/^\-+|\-+$/g, '')
18+
// lowercase
19+
.toLowerCase()
20+
}

lib/util.js lib/util/index.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ exports.parseFrontmatter = content => {
4545

4646
const LRU = require('lru-cache')
4747
const cache = LRU({ max: 1000 })
48+
const md = require('../markdown')()
4849

4950
exports.extractHeaders = (content, include = []) => {
5051
const key = content + include.join(',')
@@ -53,8 +54,6 @@ exports.extractHeaders = (content, include = []) => {
5354
return hit
5455
}
5556

56-
const md = require('./markdown')({})
57-
const S = require('string')
5857
const tokens = md.parse(content, {})
5958

6059
const res = []
@@ -64,7 +63,7 @@ exports.extractHeaders = (content, include = []) => {
6463
res.push({
6564
level: parseInt(t.tag.slice(1), 10),
6665
title,
67-
slug: S(title).slugify().s
66+
slug: md.slugify(title)
6867
})
6968
}
7069
})

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"connect-history-api-fallback": "^1.5.0",
5151
"copy-webpack-plugin": "^4.5.1",
5252
"css-loader": "^0.28.11",
53+
"diacritics": "^1.3.0",
5354
"es6-promise": "^4.2.4",
5455
"escape-html": "^1.0.3",
5556
"file-loader": "^1.1.11",

yarn.lock

+4
Original file line numberDiff line numberDiff line change
@@ -1381,6 +1381,10 @@ detect-libc@^1.0.2:
13811381
version "1.0.3"
13821382
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
13831383

1384+
diacritics@^1.3.0:
1385+
version "1.3.0"
1386+
resolved "https://registry.yarnpkg.com/diacritics/-/diacritics-1.3.0.tgz#3efa87323ebb863e6696cebb0082d48ff3d6f7a1"
1387+
13841388
diff@^3.2.0:
13851389
version "3.5.0"
13861390
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"

0 commit comments

Comments
 (0)