⚡ perf(vscode): 代码阅读预览发给页面的块只记相对位置:块在源码里占的地方记成离前一块多远、自己多长,块里名字的下标从块的开头算,页面从文件开头累加回文件里的位置、和扩展端打交道的地方都在一处换算;靠前改了代码,后面内容没变的块发过去一模一样,扩展端自己的块和发给页面的块分成两种类型

This commit is contained in:
cruldra committed 2026-10-13 16:32:18 +11:00
1 parent 3a2815c19c
commit ad5f559e92
43 files changed
+980 -424

No files matched your search

@@ -2,36 +2,50 @@ import type { LucideIcon } from 'lucide-react'
import type { CSSProperties, ReactElement } from 'react'
import type { NameMap } from './displayNames'
import type { Highlight, OccurrenceStyle } from './occurrences'
import type { Placement } from './placement'
import type { ReadableStore } from './store'
import type { GroupStyle, Inline, Segment, SegmentGroup, ShownName } from './types'
import { createContext, memo, useContext, useState } from 'react'
import { sameShownName, shownName } from './displayNames'
import { KIND_ICON_COMPONENTS } from './kindIcons'
import { isCurrent, segmentOccurrence, sourceOf } from './occurrences'
import { NO_PLACEMENT } from './placement'
import { staticStore, useStore } from './store'
/** 页面上文字的两样标记:中文名(下标 → 显示成什么),眼下高亮着的名字(没有高亮时没有)。 */
/**
* 页面上文字的标记:中文名(文件里的下标 → 显示成什么),眼下高亮着的名字(没有高亮时没有),和各块在文件里的位置
* (文字里的下标从所在那块的开头算,按它换成文件里的下标再去查)。
*/
export interface TextMarks {
names: NameMap
highlight?: Highlight
placement: Placement
}
/**
* 文字的标记从哪份 store 读:页面上是 App 的那份(中文名、单击高亮都记在里面);定义卡片浮窗是那个文件的中文名,钉住的行不画高亮。
* 每段文字只订阅自己那几段的标记。
*/
export const TextMarksContext = createContext<ReadableStore<TextMarks>>(staticStore({ names: new Map() }))
export const TextMarksContext = createContext<ReadableStore<TextMarks>>(staticStore({ names: new Map(), placement: NO_PLACEMENT }))
/** 文字在哪块的卡片里(块 id):卡片、钉住的卡片头按它给里面的文字;卡片外面的文字(编辑框的着色)不带下标,没有 */
export const BlockIdContext = createContext<string | undefined>(undefined)
/**
* 按词性给每一段上色,颜色在 codeReader.css 的 .cr-role-* 里按主题切换,带自己颜色(color)的段用它(.cr-colored);带源码下标的名字记在 data-offset 上
* (讲别处名字的段记那个名字的下标,见 sourceOf),跳到定义、高亮各处出现用;是眼下高亮着的名字的一处出现时 data-occurrence 标出底色,是当前那一处(点中的、用键盘跳到的)时
* 按词性给每一段上色,颜色在 codeReader.css 的 .cr-role-* 里按主题切换,带自己颜色(color)的段用它(.cr-colored);带下标的名字把块里的下标记在 data-offset 上
* (讲别处名字的段记那个名字的下标,见 sourceOf;换成文件里的见 nameOffset),跳到定义、高亮各处出现用;是眼下高亮着的名字的一处出现时 data-occurrence 标出底色,是当前那一处(点中的、用键盘跳到的)时
* 再标 data-current。起了中文名的名字显示中文名(data-name),悬停看原名,定义处本身在后面淡淡写原名;下标照旧,跳到定义、高亮照常。
* 带悬停提示(tooltip)的段悬停看它。
* 框起来的一组词画成小框,框里的词同样处理。
* 中文名和高亮只订阅自己这几段的(TextMarksContext):中文名到了、换了高亮的名字,只有字或底色变了的那几串文字重画。
* 中文名和高亮只订阅自己这几段的(TextMarksContext),按所在那块(BlockIdContext)在文件里的位置查:中文名到了、换了高亮的名字,只有字或底色变了的那几串文字重画;
* 块只是挪了位置时查出来的还是那些,不重画。
*/
export const SegmentText = memo(({ segments }: { segments: Inline[] }): ReactElement => {
const marks = useStore(useContext(TextMarksContext), current => segments.map(piece => 'role' in piece ? markOf(piece, current) : undefined), sameMarks)
const block = useContext(BlockIdContext)
const marks = useStore(useContext(TextMarksContext), (current) => {
const base = block === undefined ? undefined : current.placement.of(block)?.offset
return segments.map(piece => 'role' in piece && base !== undefined ? markOf(piece, base, current) : undefined)
}, sameMarks)
return (
<>
{segments.map((piece, index) => {
@@ -44,7 +58,7 @@ export const SegmentText = memo(({ segments }: { segments: Inline[] }): ReactEle
key={index}
className={piece.color ? `cr-role-${piece.role} cr-colored` : `cr-role-${piece.role}`}
style={piece.color && { '--color-dark': piece.color.dark, '--color-light': piece.color.light } as CSSProperties}
data-offset={sourceOf(piece)?.start}
data-offset={sourceOf(piece, 0)?.start}
data-occurrence={mark?.occurrence}
data-current={mark?.current ? '' : undefined}
data-name={shown?.name}
@@ -67,10 +81,11 @@ interface SegmentMark {
current: boolean
}
function markOf(piece: Segment, { names, highlight }: TextMarks): SegmentMark | undefined {
const shown = shownName(piece, names)
const occurrence = highlight && segmentOccurrence(piece, highlight.occurrences)
const current = highlight !== undefined && isCurrent(piece, highlight)
/** 一段的标记;段里的下标从所在那块的开头算,那块的开头在文件里的下标是 base。 */
function markOf(piece: Segment, base: number, { names, highlight }: TextMarks): SegmentMark | undefined {
const shown = shownName(piece, base, names)
const occurrence = highlight && segmentOccurrence(piece, base, highlight.occurrences)
const current = highlight !== undefined && isCurrent(piece, base, highlight)
return shown || occurrence || current ? { shown, occurrence, current } : undefined
}