返回 slidev
ShikiEditor.vue
根目录 / packages / client / internals / ShikiEditor.vue
1 <script setup lang="ts">
2 import { shallowRef } from 'vue'
3 import { useIME } from '../composables/useIME'
4
5 const props = defineProps<{
6 placeholder?: string
7 }>()
8 const content = defineModel<string>({ required: true })
9 const { composingContent, onInput, onCompositionEnd } = useIME(content)
10
11 const highlight = shallowRef<((code: string) => string) | null>(null)
12 import('../setup/shiki').then(async (m) => {
13 const { getEagerHighlighter, defaultHighlightOptions } = await m.default()
14 const highlighter = await getEagerHighlighter()
15 highlight.value = (code: string) => highlighter.codeToHtml(code, {
16 ...defaultHighlightOptions,
17 lang: 'markdown',
18 })
19 })
20 </script>
21
22 <template>
23 <div class="absolute left-3 right-0 inset-y-2 font-mono overflow-x-hidden overflow-y-auto cursor-text">
24 <div v-if="highlight" class="relative w-full h-max min-h-full">
25 <div class="relative w-full h-max" v-html="`${highlight(composingContent)}&nbsp;`" />
26 <textarea
27 v-model="composingContent" :placeholder="props.placeholder"
28 class="absolute inset-0 resize-none text-transparent bg-transparent focus:outline-none caret-black dark:caret-white overflow-y-hidden"
29 @input="onInput"
30 @compositionend="onCompositionEnd"
31 />
32 </div>
33 </div>
34 </template>
35
36 <style scoped>
37 :deep(code),
38 textarea {
39 font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
40 font-feature-settings: normal;
41 font-variation-settings: normal;
42 font-size: 1em;
43 text-wrap: wrap;
44 word-break: normal;
45 overflow-wrap: break-word;
46 display: block;
47 width: 100%;
48 }
49 :deep(pre.shiki) {
50 background-color: transparent;
51 }
52 </style>
53
53 lines Plain Text