1 |
|
2 |
|
3 | const RE = /{([\d,-]+)}/
|
4 | const wrapperRE = /^<pre .*?><code>/
|
5 |
|
6 | module.exports = md => {
|
7 | const fence = md.renderer.rules.fence
|
8 | md.renderer.rules.fence = (...args) => {
|
9 | const [tokens, idx, options] = args
|
10 | const token = tokens[idx]
|
11 |
|
12 | const rawInfo = token.info
|
13 | if (!rawInfo || !RE.test(rawInfo)) {
|
14 | return fence(...args)
|
15 | }
|
16 |
|
17 | const langName = rawInfo.replace(RE, '').trim()
|
18 |
|
19 | token.info = langName
|
20 |
|
21 | const lineNumbers = RE.exec(rawInfo)[1]
|
22 | .split(',')
|
23 | .map(v => v.split('-').map(v => parseInt(v, 10)))
|
24 |
|
25 | const code = options.highlight
|
26 | ? options.highlight(token.content, langName)
|
27 | : token.content
|
28 |
|
29 | const rawCode = code.replace(wrapperRE, '')
|
30 | const highlightLinesCode = rawCode.split('\n').map((split, index) => {
|
31 | const lineNumber = index + 1
|
32 | const inRange = lineNumbers.some(([start, end]) => {
|
33 | if (start && end) {
|
34 | return lineNumber >= start && lineNumber <= end
|
35 | }
|
36 | return lineNumber === start
|
37 | })
|
38 | if (inRange) {
|
39 | return `<div class="highlighted"> </div>`
|
40 | }
|
41 | return '<br>'
|
42 | }).join('')
|
43 |
|
44 | const highlightLinesWrapperCode =
|
45 | `<div class="highlight-lines">${highlightLinesCode}</div>`
|
46 |
|
47 | return highlightLinesWrapperCode + code
|
48 | }
|
49 | }
|