Skip to content

Commit 9b42690

Browse files
authored
feat: code line numbers (close: #365) (#379)
1 parent c4424c8 commit 9b42690

File tree

8 files changed

+116
-22
lines changed

8 files changed

+116
-22
lines changed

docs/config/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,13 @@ Provide config options to the used theme. The options will vary depending on the
127127

128128
## Markdown
129129

130+
### markdown.lineNumbers
131+
132+
- Type: `boolean`
133+
- Default: `undefined`
134+
135+
Whether to show line numbers to the left of each code blocks.
136+
130137
### markdown.slugify
131138

132139
- Type: `Function`

docs/zh/config/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ module.exports = {
126126

127127
## Markdown
128128

129+
### markdown.lineNumbers
130+
131+
- 类型: `boolean`
132+
- 默认值: `undefined`
133+
134+
是否在每个代码块的左侧显示行号。
135+
129136
### markdown.anchor
130137

131138
- 类型: `Object`

lib/default-theme/styles/code.styl

+66-20
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ div[class*="language-"]
3030
user-select none
3131
padding-top 1.3rem
3232
position absolute
33-
z-index 0
33+
top 0
34+
left 0
3435
width 100%
3536
line-height 1.4
3637
.highlighted
@@ -45,61 +46,106 @@ div[class*="language-"]
4546
right 1em
4647
font-size 0.75rem
4748
color rgba(255, 255, 255, 0.4)
48-
49-
div[class="language-js"], div[class="language-javascript"]
49+
&:not(.line-numbers-mode)
50+
.line-numbers-wrapper
51+
display none
52+
&.line-numbers-mode
53+
.highlight-lines .highlighted
54+
position relative
55+
&:before
56+
content ' '
57+
position absolute
58+
z-index 3
59+
left 0
60+
top 0
61+
display block
62+
width $lineNumbersWrapperWidth
63+
height 100%
64+
background-color rgba(0, 0, 0, 66%)
65+
pre
66+
padding-left $lineNumbersWrapperWidth + 1 rem
67+
vertical-align middle
68+
.line-numbers-wrapper
69+
position absolute
70+
top 0
71+
width $lineNumbersWrapperWidth
72+
text-align center
73+
color rgba(255, 255, 255, 0.3)
74+
padding 1.25rem 0
75+
line-height 1.4
76+
br
77+
user-select none
78+
.line-number
79+
position relative
80+
z-index 4
81+
user-select none
82+
font-size 0.85em
83+
&::after
84+
content ''
85+
position absolute
86+
z-index 2
87+
top 0
88+
left 0
89+
width $lineNumbersWrapperWidth
90+
height 100%
91+
border-radius 6px 0 0 6px
92+
border-right 1px solid rgba(0, 0, 0, 66%)
93+
background-color $codeBgColor
94+
95+
div[class*="language-js"], div[class*="language-javascript"]
5096
&:before
5197
content "js"
5298

53-
div[class="language-ts"], div[class="language-typescript"]
99+
div[class*="language-ts"], div[class*="language-typescript"]
54100
&:before
55101
content "ts"
56102

57-
div[class="language-html"], div[class="language-markup"]
103+
div[class*="language-html"], div[class*="language-markup"]
58104
&:before
59105
content "html"
60106

61-
div[class="language-markdown"], div[class="language-md"]
107+
div[class*="language-markdown"], div[class*="language-md"]
62108
&:before
63109
content "md"
64110

65-
div[class="language-vue"]:before
111+
div[class*="language-vue"]:before
66112
content "vue"
67113

68-
div[class="language-css"]:before
114+
div[class*="language-css"]:before
69115
content "css"
70116

71-
div[class="language-sass"]:before
117+
div[class*="language-sass"]:before
72118
content "sass"
73119

74-
div[class="language-less"]:before
120+
div[class*="language-less"]:before
75121
content "less"
76122

77-
div[class="language-scss"]:before
123+
div[class*="language-scss"]:before
78124
content "scss"
79125

80-
div[class="language-stylus"]:before
126+
div[class*="language-stylus"]:before
81127
content "stylus"
82128

83-
div[class="language-json"]:before
129+
div[class*="language-json"]:before
84130
content "json"
85131

86-
div[class="language-ruby"]:before
132+
div[class*="language-ruby"]:before
87133
content "rb"
88134

89-
div[class="language-python"]:before
135+
div[class*="language-python"]:before
90136
content "py"
91137

92-
div[class="language-go"]:before
138+
div[class*="language-go"]:before
93139
content "go"
94140

95-
div[class="language-java"]:before
141+
div[class*="language-java"]:before
96142
content "java"
97143

98-
div[class="language-c"]:before
144+
div[class*="language-c"]:before
99145
content "c"
100146

101-
div[class="language-bash"]:before
147+
div[class*="language-bash"]:before
102148
content "sh"
103149

104-
div[class="language-yaml"]:before
150+
div[class*="language-yaml"]:before
105151
content "yaml"

lib/default-theme/styles/config.styl

+3
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,7 @@ $MQNarrow = 959px
1515
$MQMobile = 719px
1616
$MQMobileNarrow = 419px
1717

18+
// code
19+
$lineNumbersWrapperWidth = 3.5rem
20+
1821
@import '~@temp/override.styl' // generated from user config

lib/default-theme/styles/theme.styl

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ a.header-anchor
138138
&:hover
139139
text-decoration none
140140

141-
code, kbd
141+
code, kbd, .line-number
142142
font-family source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace
143143

144144
p, ul, ol

lib/markdown/index.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const highlight = require('./highlight')
22
const highlightLines = require('./highlightLines')
33
const preWrapper = require('./preWrapper')
4+
const lineNumbers = require('./lineNumbers')
45
const component = require('./component')
56
const hoistScriptStyle = require('./hoist')
67
const convertRouterLink = require('./link')
@@ -49,6 +50,10 @@ module.exports = ({ markdown = {}} = {}) => {
4950
markdown.config(md)
5051
}
5152

53+
if (markdown.lineNumbers) {
54+
md.use(lineNumbers)
55+
}
56+
5257
// override render to allow custom plugins return data
5358
const render = md.render
5459
md.render = (...args) => {

lib/markdown/lineNumbers.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// markdown-it plugin for generating line numbers.
2+
// It depends on preWrapper plugin.
3+
4+
module.exports = md => {
5+
const fence = md.renderer.rules.fence
6+
md.renderer.rules.fence = (...args) => {
7+
const rawCode = fence(...args)
8+
const code = rawCode.slice(
9+
rawCode.indexOf('<code>'),
10+
rawCode.indexOf('</code>')
11+
)
12+
13+
const lines = code.split('\n')
14+
const lineNumbersCode = [...Array(lines.length - 1)]
15+
.map((line, index) => `<span class="line-number">${index + 1}</span><br>`).join('')
16+
17+
const lineNumbersWrapperCode =
18+
`<div class="line-numbers-wrapper">${lineNumbersCode}</div>`
19+
20+
const finalCode = rawCode
21+
.replace('<!--beforeend-->', `${lineNumbersWrapperCode}<!--beforeend-->`)
22+
.replace('extra-class', 'line-numbers-mode')
23+
24+
return finalCode
25+
}
26+
}

lib/markdown/preWrapper.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module.exports = md => {
1313
const [tokens, idx] = args
1414
const token = tokens[idx]
1515
const rawCode = fence(...args)
16-
return `<!--beforebegin--><div class="language-${token.info.trim()}">` +
16+
return `<!--beforebegin--><div class="language-${token.info.trim()} extra-class">` +
1717
`<!--afterbegin-->${rawCode}<!--beforeend--></div><!--afterend-->`
1818
}
1919
}

0 commit comments

Comments
 (0)