-
-
Notifications
You must be signed in to change notification settings - Fork 32
/
ECodeBlock.ts
103 lines (97 loc) 路 2.58 KB
/
ECodeBlock.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import type { PropType } from 'vue'
import { defineComponent, h } from 'vue'
import type { BundledLanguage, BundledTheme, SpecialLanguage, ThemeRegistrationAny } from 'shiki'
export default defineComponent({
name: 'ECodeBlock',
props: {
code: {
type: String,
required: true,
},
lang: {
type: String as PropType<BundledLanguage | SpecialLanguage>,
required: true,
},
theme: {
type: String as PropType<BundledTheme | ThemeRegistrationAny>,
required: true,
},
class: {
type: String,
default: '',
},
showLineNumbers: {
type: Boolean,
default: false,
},
lineNumberColor: {
type: String,
default: '#636E7B',
},
lineHighlightingColor: {
type: String,
default: 'rgba(101, 117, 133, .16)',
},
highlightedLines: {
type: Array as PropType<number[]>,
default: () => [],
},
},
async setup({ code, lang, theme, showLineNumbers, lineNumberColor, highlightedLines, lineHighlightingColor }) {
const { getHighlighter } = await import('shiki')
const shiki = await getHighlighter({
langs: [lang],
themes: [theme],
})
const themeColorBg = shiki.getTheme(theme).bg
const html = shiki.codeToHtml(code, {
lang,
theme,
transformers: [
{
code(node) {
node.properties.style = 'display: table; width: 100%;'
},
},
{
line(node, line) {
node.properties.style = 'display: table-row; line-height: 1.5; height: 1.5em;'
if (showLineNumbers) {
node.children.unshift({
type: 'element',
tagName: 'span',
properties: {
className: ['line-number'],
style: `padding-left: 5px; padding-right: 15px; color: ${lineNumberColor}; user-select: none;`,
},
children: [
{
type: 'text',
value: `${line}`,
},
],
})
}
if (highlightedLines.includes(line))
node.properties.style += `background-color: ${lineHighlightingColor};`
},
},
],
})
return () =>
h('pre', {
class: ['shiki', theme],
style: {
backgroundColor: themeColorBg,
display: 'block',
whiteSpace: 'pre',
fontFamily: 'monospace',
},
tabindex: 0,
}, [
h('span', {
innerHTML: html,
}),
])
},
})