11<template >
2- <div class =" flex bg-white h-full" >
2+ <div class =" flex bg-white h-full relative " >
33 <!-- 行号 -->
44 <div ref =" lineNumbersRef"
5- class =" bg-gray-50 text-gray-400 text-sm font-mono py-4 px-3 select-none border-r border-gray-200 overflow-hidden" >
5+ class =" bg-gray-50 text-gray-400 text-sm font-mono py-4 px-3 select-none border-r border-gray-200 overflow-hidden flex-shrink-0 z-10 " >
66 <div v-for =" (num, index) in lineNumbers" :key =" index" class =" h-6 leading-6 text-right" >
77 {{ num }}
88 </div >
99 </div >
1010
11- <!-- 代码输入框 -->
12- <textarea ref =" textareaRef"
13- :value =" modelValue"
14- @input =" handleInput"
15- @keydown =" handleKeyDown"
16- @scroll =" handleScroll"
17- class =" flex-1 p-4 font-mono text-sm leading-6 resize-none outline-none bg-white"
18- placeholder =" 在此输入代码..."
19- spellcheck =" false" >
20- </textarea >
11+ <!-- 语法高亮容器 -->
12+ <div class =" flex-1 relative" >
13+ <!-- 高亮显示层 -->
14+ <pre ref =" highlightRef"
15+ class =" absolute inset-0 p-4 font-mono text-sm leading-6 bg-transparent pointer-events-none overflow-hidden whitespace-pre-wrap z-0"
16+ style =" margin : 0 ; border : 0 ; word-break : break-word ; white-space : pre-wrap ;"
17+ v-html =" highlightedCode" ></pre >
18+
19+ <!-- 代码输入框 -->
20+ <textarea ref =" textareaRef"
21+ :value =" modelValue"
22+ @input =" handleInput"
23+ @keydown =" handleKeyDown"
24+ @scroll =" handleScroll"
25+ class =" absolute inset-0 p-4 font-mono text-sm leading-6 resize-none outline-none bg-transparent z-10"
26+ style =" color : transparent ; caret-color : #374151 ; margin : 0 ; border : 0 ; word-break : break-word ; white-space : pre-wrap ;"
27+ placeholder =" 在此输入代码..."
28+ spellcheck =" false" >
29+ </textarea >
30+ </div >
2131 </div >
2232</template >
2333
2434<script setup lang="ts">
2535import { computed , nextTick , ref } from ' vue'
36+ import { highlightCode } from ' ../utils/highlighter'
2637
2738const props = defineProps <{
2839 modelValue: string
@@ -35,12 +46,17 @@ const emit = defineEmits<{
3546
3647const textareaRef = ref <HTMLTextAreaElement >()
3748const lineNumbersRef = ref <HTMLElement >()
49+ const highlightRef = ref <HTMLPreElement >()
3850
3951const lineNumbers = computed (() => {
4052 const lines = props .modelValue .split (' \n ' )
4153 return lines .map ((_ , index ) => String (index + 1 ))
4254})
4355
56+ const highlightedCode = computed (() => {
57+ return highlightCode (props .modelValue , props .language || ' python3' )
58+ })
59+
4460const handleInput = (e : Event ) => {
4561 const target = e .target as HTMLTextAreaElement
4662 emit (' update:modelValue' , target .value )
@@ -65,5 +81,9 @@ const handleScroll = (e: Event) => {
6581 if (lineNumbersRef .value ) {
6682 lineNumbersRef .value .scrollTop = target .scrollTop
6783 }
84+ if (highlightRef .value ) {
85+ highlightRef .value .scrollTop = target .scrollTop
86+ highlightRef .value .scrollLeft = target .scrollLeft
87+ }
6888}
6989 </script >
0 commit comments