⚡ perf(vscode): 代码阅读预览的文档消息里源码和着色只带一份:块不再各带一份连子块在内的整段源码和上色,编辑框按块的编辑范围从整份源码和着色里取,5126 行的消息 4.3MB → 1.9MB

This commit is contained in:
cruldra committed 2026-10-13 15:50:33 +11:00
1 parent 0371712176
commit 2e3602242e
43 files changed
+501 -239

No files matched your search

@@ -1,6 +1,8 @@
import type { ChangeEvent, KeyboardEvent, ReactElement } from 'react'
import type { SourceText } from './blockSource'
import type { BlockView } from './types'
import { useEffect, useLayoutEffect, useRef, useState } from 'react'
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
import { blockSource } from './blockSource'
import { recolor } from './segments'
import { SegmentText } from './SegmentText'
import { postMessage } from './vscode'
@@ -9,6 +11,8 @@ const EDIT_DEBOUNCE_MS = 200
interface CodeEditorProps {
block: BlockView
/** 这一版文档的源码和着色:这块的源码按它的编辑范围从里面取 */
sourceText: SourceText
/** 文档版本:每来一份新文档都要对一次输入框内容,哪怕这一块的代码没变 */
version: number
autoFocus: boolean
@@ -17,8 +21,9 @@ interface CodeEditorProps {
}
/** 一块源码的编辑状态:着色层显示,透明输入框接收输入,改动防抖后整行替换回文件。 */
export function CodeEditor({ block, version, autoFocus, onAutoFocused, onExit }: CodeEditorProps): ReactElement {
const [text, setText] = useState(block.code)
export function CodeEditor({ block, sourceText, version, autoFocus, onAutoFocused, onExit }: CodeEditorProps): ReactElement {
const { code, tokens } = useMemo(() => blockSource(sourceText, block.startLine, block.endLine), [sourceText, block.startLine, block.endLine])
const [text, setText] = useState(code)
const textareaRef = useRef<HTMLTextAreaElement>(null)
const blockRef = useRef(block)
blockRef.current = block
@@ -51,16 +56,16 @@ export function CodeEditor({ block, version, autoFocus, onAutoFocused, onExit }:
useEffect(() => {
const el = textareaRef.current
const focused = el !== null && document.activeElement === el
if (focused && unconfirmed.current !== null && unconfirmed.current !== block.code)
if (focused && unconfirmed.current !== null && unconfirmed.current !== code)
return
unconfirmed.current = null
sentLineCount.current = null
if (block.code === textRef.current)
if (code === textRef.current)
return
if (focused)
restoreSelection.current = [el.selectionStart, el.selectionEnd]
setText(block.code)
}, [version, block.code])
setText(code)
}, [version, code])
useLayoutEffect(() => {
const el = textareaRef.current
@@ -121,7 +126,7 @@ export function CodeEditor({ block, version, autoFocus, onAutoFocused, onExit }:
onBlur={flush}
/>
<pre className="cr-code" aria-hidden="true">
<SegmentText segments={recolor(block.codeTokens, block.code, text)} />
<SegmentText segments={recolor(tokens, code, text)} />
{text === '' || text.endsWith('\n') ? ' ' : ''}
</pre>
</div>