VS Code 1.139 带的 Electron 43 在 macOS 上只在鼠标压着带 title 的元素自身边缘时才弹原生提示, 停在它里面的图标、文字上不弹(electron/electron#49843,Electron 38 起)。种类图标 20px 的框 几乎被 16px 的图形占满,所以基本看不到种类名;块右上角按钮同样受影响。页面上核对过:图标中心点 命中的是图标里的线条,没有盖在上面的东西。 - components/ui/tooltip.tsx 改成整页只挂一次的 TooltipHost:元素只写 data-tooltip,事件统一交给它; 样子照 VS Code 悬停框(editorHoverWidget 那组变量、widget-shadow 阴影),停 500ms 才弹、弹着时换元素 立刻换,移开 / 按下 / 按键 / 滚动收起;键盘聚焦立刻弹,提示不是元素自己的名字时挂 aria-describedby - 代码阅读里所有 title(种类图标、块按钮、筛选栏、问答区、中文名的「原名」)改成 data-tooltip; SelectMenu 的 title 属性改名 tooltip;看板工单详情原来包一层的 Tooltip 也改成 data-tooltip - 何时弹 / 收的规则抽成纯函数加测试;更新代码阅读 spec
82 lines
4.4 KiB
TypeScript
82 lines
4.4 KiB
TypeScript
import type { Inline, ShownName, WebviewToExtension } from './types'
|
|
import { renderToStaticMarkup } from 'react-dom/server'
|
|
import { describe, expect, it, vi } from 'vitest'
|
|
import { acceptNames, DisplayNameContext, documentNames, nameMap, shownName } from './displayNames'
|
|
import { OccurrenceHighlight } from './occurrences'
|
|
import { SegmentText } from './SegmentText'
|
|
|
|
// 高亮的上下文所在的模块连着和 VS Code 收发消息的那一套,渲染成 HTML 用不着
|
|
vi.mock('./useOccurrences', async () => {
|
|
const { createContext } = await import('react')
|
|
return { HighlightContext: createContext(undefined) }
|
|
})
|
|
|
|
const CURRENT_USER: ShownName = { offset: 40, length: 12, name: '当前用户', definition: true }
|
|
const USE: ShownName = { offset: 90, length: 12, name: '当前用户' }
|
|
const ADMIN: ShownName = { offset: 130, length: 5, name: '管理员' }
|
|
|
|
function render(segments: Inline[], names: ShownName[]): string {
|
|
return renderToStaticMarkup(
|
|
<DisplayNameContext value={nameMap(names)}>
|
|
<SegmentText segments={segments} />
|
|
</DisplayNameContext>,
|
|
)
|
|
}
|
|
|
|
describe('页面上的中文名', () => {
|
|
it('收到新文档换成它带来的;查到的是页面上这个版本的才换上,迟到的旧版本不理', () => {
|
|
const current = documentNames(3, [USE])
|
|
expect([...current.names.values()]).toEqual([USE])
|
|
expect(acceptNames(current, 2, [ADMIN])).toBe(current)
|
|
expect([...acceptNames(current, 3, [USE, ADMIN])!.names.values()]).toEqual([USE, ADMIN])
|
|
expect(acceptNames(undefined, 3, [ADMIN])).toBeUndefined()
|
|
})
|
|
|
|
it('只认下标和长度都对得上的名字:没下标的译词、长度不一样的(名字改长了)不换', () => {
|
|
const names = nameMap([USE])
|
|
expect(shownName({ text: 'current_user', role: 'variable', offset: 90 }, names)).toBe(USE)
|
|
expect(shownName({ text: 'current_userx', role: 'variable', offset: 90 }, names)).toBeUndefined()
|
|
expect(shownName({ text: 'current_user', role: 'variable' }, names)).toBeUndefined()
|
|
expect(shownName({ text: 'current_user', role: 'variable', offset: 91 }, names)).toBeUndefined()
|
|
})
|
|
|
|
it('用到的地方显示中文名,悬停写「原名 x」,下标照旧(⌘ 点击跳到定义、单击高亮都认它)', () => {
|
|
const html = render([
|
|
{ text: '如果', role: 'keyword' },
|
|
{ text: ' ', role: 'plain' },
|
|
{ text: 'current_user', role: 'variable', offset: 90 },
|
|
{ text: '.', role: 'plain' },
|
|
{ text: 'role', role: 'variable', offset: 103 },
|
|
{ text: ' 不等于 ', role: 'operator' },
|
|
{ text: 'UserRole', role: 'variable', offset: 120 },
|
|
{ text: '.', role: 'plain' },
|
|
{ text: 'ADMIN', role: 'variable', offset: 130 },
|
|
], [USE, ADMIN])
|
|
expect(html.replace(/<[^>]*>/g, '')).toBe('如果 当前用户.role 不等于 UserRole.管理员')
|
|
expect(html).toContain('<span class="cr-role-variable" data-offset="90" data-name="当前用户" data-tooltip="原名 current_user">当前用户</span>')
|
|
expect(html).toContain('<span class="cr-role-variable" data-offset="103">role</span>')
|
|
expect(html).not.toContain('cr-original')
|
|
})
|
|
|
|
it('定义处本身(名称格子、名称行):中文名后面跟着淡淡的原名;框里的名字同样换', () => {
|
|
const html = render([
|
|
{ text: 'current_user', role: 'variable', offset: 40 },
|
|
{ style: 'iteration', label: '列表', segments: [{ text: 'ADMIN', role: 'variable', offset: 130 }] },
|
|
], [CURRENT_USER, ADMIN])
|
|
expect(html).toContain('data-offset="40" data-name="当前用户" data-tooltip="原名 current_user">当前用户<span class="cr-original">current_user</span></span>')
|
|
expect(html).toContain('data-offset="130" data-name="管理员" data-tooltip="原名 ADMIN">管理员</span>')
|
|
})
|
|
|
|
it('单击显示成中文名的名字:筛选栏写中文名,当前那一处按点中的下标认', () => {
|
|
const sent: WebviewToExtension[] = []
|
|
let shown: string | undefined
|
|
const highlight = new OccurrenceHighlight(msg => sent.push(msg), next => shown = next && `${next.name} ${next.current}`)
|
|
highlight.setDocument(1, 'zh')
|
|
highlight.click({ kind: 'find', offset: 90, name: '当前用户' })
|
|
const asked = sent.at(-1)
|
|
expect(asked).toMatchObject({ type: 'findOccurrences', offset: 90 })
|
|
highlight.answer(asked?.type === 'findOccurrences' ? asked.id : -1, [{ start: 40, end: 52, kind: 'write' }, { start: 90, end: 102, kind: 'read' }])
|
|
expect(shown).toBe('当前用户 1')
|
|
})
|
|
})
|