✨ feat(vscode): 预览里代码的上色和卡片种类色跟着当前颜色主题走

This commit is contained in:
cruldra committed 2026-10-13 11:27:24 +11:00
1 parent 19302bbed0
commit dff38ee0c5
26 files changed
+1286 -75

No files matched your search

+26 -16
View File
@@ -2104,27 +2104,33 @@ type BlockView = BlockViewBase & ({ translation: PreviewText, table?: PreviewTab
## 颜色
词性(暗色取 VS Code Dark+,亮色取 Light+):
词性和内置种类的颜色跟着当前颜色主题走,和编辑器里看到的代码颜色一致(`theme/`):
| 词性 | 暗色 | 亮色 |
| --- | --- | --- |
| keyword | #c586c0 | #af00db |
| storage / operator | #569cd6 | #0000ff |
| variable | #9cdcfe | #001080 |
| function | #dcdcaa | #795e26 |
| type | #4ec9b0 | #267f99 |
| string | #ce9178 | #a31515 |
| number / literal | #b5cea8 | #098658 |
| comment | #6a9955 | #008000 |
| hint | `--vscode-descriptionForeground` | 同左 |
| constant | #4fc1ff | #0070c1 |
| plain | `--vscode-editor-foreground` | 同左 |
- 当前主题照 VS Code 自己的规则定:开着 `window.autoDetectHighContrast` 且当前是高对比主题时取两个高对比的设置,开着 `window.autoDetectColorScheme` 时按当前主题的明暗取 `workbench.preferredDarkColorTheme` / `preferredLightColorTheme`,否则是 `workbench.colorTheme`;老名字照 VS Code 换成现在的。在 `vscode.extensions.all`(内置主题也在里面)各扩展贡献的 `themes` 里按 id(没有用 label,再没有用文件名)找到主题文件。
- 读主题文件:JSON 带注释、尾逗号;`include` 的在前、自己的在后;`tokenColors` 可以是数组,也可以是指向 `.tmTheme` 的路径;主题本身也可以是 `.tmTheme`(plist,`plist` 包解析)。
- 叠用户设置:`editor.tokenColorCustomizations`(几组颜色、`textMateRules`、`"[主题名]"` 专属块)排在主题后面;`editor.semanticHighlighting.enabled`、主题的 `semanticHighlighting`、`semanticTokenColors` 和 `editor.semanticTokenColorCustomizations`(`enabled`、`rules`、专属块)定开没开语义上色、语义规则。先后照 VS Code 的 `colorThemeData.ts`。
- 每种颜色查什么在 `theme/codeColors.ts` 的对照表:开了语义上色时先看语义规则(函数 `function`、类型 `class`、变量 `variable`、常量 `variable.readonly`、枚举 `enum`、构建阶段 / 模块 `namespace`),没有再依次查几个 TextMate 范围。范围照 vscode-textmate 匹配:规则的范围按点分段是查的范围的前缀才算,段数多的胜,一样具体时后写的胜,逗号分隔的选择器拆开,带父级的选择器不算。都没配的用编辑器前景色(`--vscode-editor-foreground`)。语义规则不分语言(所有预览共用一份),带语言的规则不算。
- 宿主共用一份(`ThemeColors`),换主题(`onDidChangeActiveColorTheme`)、改上面这些设置时作废重读,发 `codeColors` 给所有 ready 的预览;页面 ready 时先于第一份文档发。页面设成 body 上的 `--cr-<词性>`、`--cr-kind-<种类>`(`codeColors.ts`)。主题找不到、读不出来时记一条警告,全用编辑器前景色。
| 词性 | 查什么 |
| --- | --- |
| keyword | `keyword.control` |
| storage / operator | `storage.type` |
| variable | 语义 `variable`;`variable.other.readwrite`、`entity.name.variable` |
| function | 语义 `function`;`entity.name.function`、`support.function` |
| type | 语义 `class`;`entity.name.type.class`、`support.class` |
| string | `string` |
| number / literal | `constant.numeric` |
| comment | `comment` |
| hint | `--vscode-descriptionForeground` |
| constant | 语义 `variable.readonly`;`variable.other.constant`、`variable.other.readwrite`、`entity.name.variable` |
| plain | `--vscode-editor-foreground` |
属性表里:说明按 comment,访问级别(公共 / 私有 / 受保护)和「作为」按 keyword,是 / 否按 storage,函数名称按 function,类名称按 type,未标注、无、N 个、字典 N 项、对象 N 项、展开、默认导出、全部、整个模块、匿名按 hint;输入参数表格的列名是界面文字(`descriptionForeground`),不是着色的词。推导式框里的「遍历」「的每个」「仅当」「取」「异步遍历」按 keyword,框头按「循环」块的种类色。父类名(TypeScript `extends` 后面、JavaScript `class_heritage` 里、Python 类名后面括号里直接写的名字)源码着色和属性表里都按 type。
带自己颜色的段(`Segment.color`,库规则按库的配色给,例如 FastAPI 的 HTTP 方法、成功的状态码):暗色、亮色两个写在元素的 style 上(`--color-dark` / `--color-light`),`.cr-colored` 按主题挑一个,盖过词性的颜色;词性照旧报(`role`)。
种类(种类图标的颜色 + 块底 7% + 边框 35%;亮色主题同色系;图标见「预览(代码块树)」):import 导入 #c586c0;function 函数、impl 实现 #dcdcaa;class 类、type 类型 #4ec9b0;trait 特质同声明关键字的蓝;enum 枚举 #b180d7(亮色 #652d90);exception 异常 #f14c4c(亮色 #cd3131,和尝试、捕获、最终同一色系,更红一些);field 字段、const 常量、variable 变量 #9cdcfe;if 条件、else 否则 #ce9178;loop 循环 #8f9cff;try 尝试、catch 捕获、finally 最终 #f48771;return 返回 #89d185;statement 语句 #9d9d9d;comment 注释 #6a9955(虚线框);Shell 的 interpreter 解释器同语句 #9d9d9d,options 选项 #e5c07b(亮色 #9a6a00),case 分情况同条件 #ce9178,command 命令、pipeline 管道 #d7ba7d(亮色 #7c5f12);Dockerfile 的 directive 解析指令同语句,stage 阶段、module 模块 #56b6c2(亮色 #127f8c),run 执行同命令,copy 复制同导入,setting 设置同选项,label 标签同变量,health 健康检查同尝试 / 捕获,start 启动同返回(原型 DOCKER_KINDS 的颜色);库规则的种类用规则给的颜色(`badge.color` 的 dark / light,webview 写在块的 style 上按主题挑),内置 SQLAlchemy 数据表 #e8a860 / #a3590d,Celery 应用 #98c379 / #4d7f17,定时任务 #56b6c2 / #127f8c,数据类 #ef7fb0 / #b3306c,FastAPI 接口 #61afef / #1a6fb5,FastAPI 路由器 #7aa2f7 / #34548a。编辑状态:底色 `--vscode-editor-background`,边框 `--vscode-focusBorder`。
种类(种类图标的颜色 + 块底 7% + 边框 35%;图标见「预览(代码块树)」):同一类语义共用一个 `--cr-kind-*`,查主题的什么见下;主题给几类配了同一个色就同色,靠图标区分。import 导入、copy 复制查 `keyword.control.import`;function 函数、impl 实现同函数名;class 类、type 类型同类型名;trait 特质同 storage;attribute 同 constant;enum 枚举查语义 `enum`、`entity.name.type.enum`;exception 异常查 `support.type.exception`;field 字段、const 常量、variable 变量、label 标签同变量名;if 条件、else 否则、case 分情况查 `keyword.control.conditional`;loop 循环查 `keyword.control.loop`;try 尝试、catch 捕获、finally 最终、health 健康检查查 `keyword.control.trycatch`;return 返回、start 启动查 `keyword.control.flow`;statement 语句、interpreter 解释器、directive 解析指令查 `source`(一般就是编辑器前景色);comment 注释查 `comment`(虚线框);options 选项、setting 设置查 `constant.other.option`;command 命令、pipeline 管道、run 执行查 `entity.name.command`,没配落回 `entity.name.function.call`;stage 阶段、module 模块查语义 `namespace`、`entity.name.namespace`。查不到具体的会落回更泛的(`keyword.control.loop` 落回 `keyword.control`)。库规则的种类用规则给的颜色(`badge.color` 的 dark / light,webview 写在块的 style 上按主题挑),内置 SQLAlchemy 数据表 #e8a860 / #a3590d,Celery 应用 #98c379 / #4d7f17,定时任务 #56b6c2 / #127f8c,数据类 #ef7fb0 / #b3306c,FastAPI 接口 #61afef / #1a6fb5,FastAPI 路由器 #7aa2f7 / #34548a。编辑状态:底色 `--vscode-editor-background`,边框 `--vscode-focusBorder`。
## 代码位置
@@ -2240,8 +2246,12 @@ vscode/src/codeReader/
editor/openTarget.ts 打开别的文件用哪种编辑器:语言有代码阅读的用预览(滚到定义处),其余用默认的打开方式(选中名字);侧栏点文件、跳到定义、注释里的链接共用
editor/occurrences.ts 查名字的各处出现(vscode.executeDocumentHighlights)
editor/occurrenceNavigation.ts 跳到下一处 / 上一处高亮:命令、上下文键
theme/currentTheme.ts 当前正在用的颜色主题:照 VS Code 的规则定设置里的名字,在装着的扩展里找主题文件
theme/themeFile.ts 读颜色主题文件:JSON(带注释、include 链、tokenColors 指向 .tmTheme)或 .tmTheme(不碰 VS Code)
theme/tokenStyles.ts 主题叠上用户设置后一个 TextMate 范围、一种语义记号是什么颜色,照 VS Code 和 vscode-textmate 的规则(不碰 VS Code)
theme/codeColors.ts 词性、种类 → 查什么的对照表;ThemeColors:所有预览共用的一份代码配色,换主题、改设置时重读、通知预览
index.ts registerCodeReader(context): CodeReaderApi
vscode/webview-ui/code-reader.html + src/codeReader/ 预览界面(React,Vite 第二个入口;块右上角的图标按钮在 BlockTools.tsx,悬停提示在 src/components/ui/tooltip.tsx(和看板共用,页面根上挂一次),块的概念图标(图标名 → 图标组件只在 kindIcons.tsx;内置种类 → 图标名在 contract.ts 的 KIND_ICONS,宿主写进概念列表)在 kindIcons.tsx,属性表在 PropertyGrid.tsx,子行排成表格还是列表在 subRows.ts,着色的词和框在 SegmentText.tsx,中文名换字在 displayNames.ts,Markdown 渲染在 markdown.ts / TextPreview.tsx(不带路径的引用的行内规则也在 markdown.ts),仓库链接和引用的点击、问坏没坏在 repoLink.ts / useRepoLinks.ts,悬停看定义卡片什么时候弹、收、放在哪在 definitionPeek.ts、接到页面上在 useDefinitionPeek.ts、浮窗和只读的卡片在 DefinitionPeekPopup.tsx,筛选栏在 FilterBar.tsx,筛选规则在 filter.ts,编辑时盖住哪些块、点「编辑」退出哪些块在 editing.ts,高亮各处出现的规则在 occurrences.ts、接到页面上在 useOccurrences.ts,问 AI 的问答区在 AskThread.tsx、状态和规则在 qa.ts、贴图拖图的规则在 qaImages.ts、收发在 useQa.ts;代码差异:页面上怎么标(块 id、删掉的块挂哪、只看改动折哪几段、各处改动、上一处 / 下一处跳到哪)在 diffView.ts,筛选栏第二行和新文件横幅在 DiffBar.tsx,卡片里的增删在 DiffText.tsx(Markdown 的增删在 markdown.ts 的 renderMarkdownDiff),总览条在 OverviewRuler.tsx,跳到一处改动在 useChangeNav.ts;钉住卡片:钉哪几张、顶上去多少在 stickyScroll.ts,量页面、收设置在 useStickyScroll.ts,钉住的几行在 StickyLines.tsx)
vscode/webview-ui/code-reader.html + src/codeReader/ 预览界面(React,Vite 第二个入口;块右上角的图标按钮在 BlockTools.tsx,悬停提示在 src/components/ui/tooltip.tsx(和看板共用,页面根上挂一次),块的概念图标(图标名 → 图标组件只在 kindIcons.tsx;内置种类 → 图标名在 contract.ts 的 KIND_ICONS,宿主写进概念列表)在 kindIcons.tsx,属性表在 PropertyGrid.tsx,子行排成表格还是列表在 subRows.ts,着色的词和框在 SegmentText.tsx,中文名换字在 displayNames.ts,Markdown 渲染在 markdown.ts / TextPreview.tsx(不带路径的引用的行内规则也在 markdown.ts),仓库链接和引用的点击、问坏没坏在 repoLink.ts / useRepoLinks.ts,悬停看定义卡片什么时候弹、收、放在哪在 definitionPeek.ts、接到页面上在 useDefinitionPeek.ts、浮窗和只读的卡片在 DefinitionPeekPopup.tsx,筛选栏在 FilterBar.tsx,筛选规则在 filter.ts,扩展端发来的代码配色设成颜色变量在 codeColors.ts,编辑时盖住哪些块、点「编辑」退出哪些块在 editing.ts,高亮各处出现的规则在 occurrences.ts、接到页面上在 useOccurrences.ts,问 AI 的问答区在 AskThread.tsx、状态和规则在 qa.ts、贴图拖图的规则在 qaImages.ts、收发在 useQa.ts;代码差异:页面上怎么标(块 id、删掉的块挂哪、只看改动折哪几段、各处改动、上一处 / 下一处跳到哪)在 diffView.ts,筛选栏第二行和新文件横幅在 DiffBar.tsx,卡片里的增删在 DiffText.tsx(Markdown 的增删在 markdown.ts 的 renderMarkdownDiff),总览条在 OverviewRuler.tsx,跳到一处改动在 useChangeNav.ts;钉住卡片:钉哪几张、顶上去多少在 stickyScroll.ts,量页面、收设置在 useStickyScroll.ts,钉住的几行在 StickyLines.tsx)
```
## 测试