]>
Commit | Line | Data |
---|---|---|
f2a92ac6 DC |
1 | /** |
2 | * MIT License | |
3 | ||
4 | Copyright (c) 2019-present, Yuxi (Evan) You | |
5 | ||
6 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 | of this software and associated documentation files (the "Software"), to deal | |
8 | in the Software without restriction, including without limitation the rights | |
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 | copies of the Software, and to permit persons to whom the Software is | |
11 | furnished to do so, subject to the following conditions: | |
12 | ||
13 | The above copyright notice and this permission notice shall be included in all | |
14 | copies or substantial portions of the Software. | |
15 | ||
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
22 | SOFTWARE. | |
23 | */ | |
24 | ||
25 | /** @typedef {import("markdown-it")} MarkdownIt */ | |
26 | ||
27 | const Prism = require("prismjs"); | |
28 | const loadLanguages = require("prismjs/components/"); | |
29 | ||
30 | /** | |
31 | * | |
32 | * @param {MarkdownIt} md markdown-it | |
33 | * @param {string} str code | |
34 | * @param {string} lang code language | |
35 | * @returns {string} highlighted result wrapped in pre | |
36 | */ | |
37 | const highlighter = function (md, str, lang) { | |
38 | let result = ""; | |
39 | if (lang) { | |
40 | try { | |
41 | loadLanguages([lang]); | |
42 | result = Prism.highlight(str, Prism.languages[lang], lang); | |
43 | } catch (err) { | |
44 | console.log(lang, err); | |
45 | // we still want to wrap the result later | |
46 | result = md.utils.escapeHtml(str); | |
47 | } | |
48 | } else { | |
49 | result = md.utils.escapeHtml(str); | |
50 | } | |
51 | ||
52 | return `<pre class="language-${lang}"><code>${result}</code></pre>`; | |
53 | }; | |
54 | ||
55 | /** | |
56 | * | |
57 | * modified from https://github.com/vuejs/vitepress/blob/main/src/node/markdown/plugins/lineNumbers.ts | |
58 | * @param {MarkdownIt} md | |
59 | * @license MIT License. See file header. | |
60 | */ | |
61 | const lineNumberPlugin = (md) => { | |
62 | const fence = md.renderer.rules.fence; | |
63 | md.renderer.rules.fence = (...args) => { | |
64 | const [tokens, idx] = args; | |
65 | const lang = tokens[idx].info.trim(); | |
66 | const rawCode = fence(...args); | |
67 | const code = rawCode.slice( | |
68 | rawCode.indexOf("<code>"), | |
69 | rawCode.indexOf("</code>") | |
70 | ); | |
71 | const lines = code.split("\n"); | |
72 | const lineNumbersCode = [...Array(lines.length - 1)] | |
73 | .map( | |
74 | (line, index) => | |
75 | `<span class="line-number">${index + 1}</span><br>` | |
76 | ) | |
77 | .join(""); | |
78 | ||
79 | const lineNumbersWrapperCode = `<div class="line-numbers-wrapper" aria-hidden="true">${lineNumbersCode}</div>`; | |
80 | ||
81 | const finalCode = rawCode | |
82 | .replace(/<\/pre>\n/, `${lineNumbersWrapperCode}</pre>`) | |
83 | .replace(/"(language-\S*?)"/, '"$1 line-numbers-mode"') | |
84 | .replace(/<code>/, `<code class="language-${lang}">`) | |
85 | ||
86 | return finalCode; | |
87 | }; | |
88 | }; | |
89 | ||
90 | module.exports.highlighter = highlighter; | |
91 | module.exports.lineNumberPlugin = lineNumberPlugin; |