Skip to content

Commit 72cebf1

Browse files
committed
refactor: compress syntax and language identity palettes
1 parent bceded2 commit 72cebf1

5 files changed

Lines changed: 133 additions & 91 deletions

File tree

‎docs/architecture/theme-token-optimization.md‎

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,18 @@ Mermaid、Monaco/editor、Prism syntax、terminal ANSI、language identity 和 U
152152
registry。Mobile Web 和 Installer 已纳入同一审计口径,但各自使用独立 baseline,
153153
避免移动端或安装器的独立 token 被误算为 web-ui 游离 key。
154154

155-
`395` 个 web-ui 唯一颜色是前端生产文件的全域审计数,不是普通 app UI 的色值预算。
155+
`356` 个 web-ui 唯一颜色是前端生产文件的全域审计数,不是普通 app UI 的色值预算。
156156
其中包含主题 preset、token contract、Mermaid、Monaco/editor、terminal、syntax、
157-
language identity 和 UI exception 等专用 palette。真正需要继续压缩的是这些专用域
157+
language identity 和 UI exception 等专用 palette。language identity 已收敛为 8 个大类身份色,
158+
不再按每种语言或文件类型保留独立色值。真正需要继续压缩的是这些专用域
158159
内部能被证明等价的近似色,而不是把它们直接并入普通 app semantic token。前后端职责边界
159160
已经收敛为:web-ui/TS 侧维护完整主题源;Rust/desktop 侧只读取 TS 生成的首屏和
160161
prompt snapshot 投影;mobile-web 和 installer 颜色在各自 TS root 中维护;CLI/TUI
161162
颜色作为独立终端产品 surface 单独治理。
162163

164+
language/file identity 色只允许作为类别辅助 accent。消费方展示语言或文件身份时必须同时渲染
165+
label、icon、扩展名或文件名之一,不允许构建只靠颜色区分语言或文件类型的 UI。
166+
163167
补充看 resolved theme 输出而不是只看源码字面量:相邻状态、主题个性和 elevation
164168
强度不能只按数值近似强行合并。复审后暗色主题 `effects.shadow` 保留各 preset 的
165169
原有 ramp;本轮只压缩非相邻、非语义的 surface/token 微差。
@@ -170,12 +174,12 @@ prompt snapshot 投影;mobile-web 和 installer 颜色在各自 TS root 中维
170174

171175
| 指标 | 当前基线 |
172176
| --- | ---: |
173-
| 扫描的生产前端文件数 | 1540 |
177+
| 扫描的生产前端文件数 | 1542 |
174178
| 忽略的测试文件数 | 224 |
175179
| 忽略的构建生成文件数 | 1 |
176180
| 包含颜色字面量的文件数 | 25 |
177-
| 颜色字面量出现次数 | 599 |
178-
| 唯一颜色字面量数量 | 395 |
181+
| 颜色字面量出现次数 | 553 |
182+
| 唯一颜色字面量数量 | 356 |
179183
| 组件或非 token 文件中的颜色出现次数 | 0 |
180184
| 组件或非 token 唯一颜色数量 | 0 |
181185
| App UI 颜色出现次数 | 0 |
@@ -193,7 +197,7 @@ prompt snapshot 投影;mobile-web 和 installer 颜色在各自 TS root 中维
193197

194198
| root | 颜色出现次数 | 唯一颜色 | App UI raw | fallback var | unresolved / non-contract key | dynamic family | 说明 |
195199
| --- | ---: | ---: | ---: | ---: | ---: | ---: | --- |
196-
| `src/web-ui/src` | 599 | 395 | 0 | 0 | 0 | 13 | 主应用完整主题、专用 palette、widget payload 和 editor/terminal/Mermaid 域;UI exception 与 boundary fallback 已收敛到小型语义 palette,未读取的 git 同义 runtime/static key 已退役。 |
200+
| `src/web-ui/src` | 553 | 356 | 0 | 0 | 0 | 13 | 主应用完整主题、专用 palette、widget payload 和 editor/terminal/Mermaid 域;UI exception、syntax、language identity 与 boundary fallback 已收敛到小型语义 palette,未读取的 git 同义 runtime/static key 已退役。 |
197201
| `src/mobile-web/src` | 35 | 30 | 0 | 0 | 0 | 3 | mobile-web 图片缩略图关闭按钮已读取 `--color-static-white`,普通 app UI raw 归零。 |
198202
| `BitFun-Installer/src` | 81 | 66 | 0 | 0 | 0 | 1 | 安装器主题数据保留主题卡可见的 primary/secondary background、accent、text 和状态反馈;runtime 只导出实际消费的 accent family、基础 text/border/element/status key,不复制主应用 purple/info/tooltip 等完整主题面。 |
199203

@@ -277,14 +281,14 @@ PR 通过而放宽 `appUi`、fallback、unresolved、non-contract 或 dynamic fa
277281
| Editor | 52 | 48 | Monaco/editor 专用域,不能直接泛化到 app token;被动 selection/word highlight 的重复弱高亮已收敛 |
278282
| Mermaid | 91 | 73 | Mermaid 专用渲染域 |
279283
| Theme runtime | 30 | 29 | `ThemeService.ts` 运行时注入;黑白 overlay alpha 与静态 token、payload shell 保持相同 stop,避免 early render 与 runtime 状态层级漂移 |
280-
| Language identity | 52 | 50 | 语言身份色,已集中到 identity registry |
284+
| Language identity | 8 | 8 | 语言/文件身份色,已收敛到 8 个大类色;具体识别继续由 key、label、icon 和扩展名承担 |
281285
| Terminal | 37 | 29 | terminal/ANSI 专用域;工具命令空状态已复用 `--tool-command-empty-rgb`,不再保留独立 raw 色 |
282286
| Boundary fallback | 18 | 18 | iframe/miniapp/截图兜底值,不作为普通 app token;generated widget 初始 CSS 需要覆盖 retired alias 的 canonical 目标 |
283287
| Visual effects | 0 | 0 | StreamText/TextStroke raw literal 已迁出普通组件层 |
284288
| UI exception registry | 17 | 17 | 已归档的 UI 例外色,包含 review team、agent capability、template context、insights 和 inspector 等固定身份色;非相邻同语义私有色已归并到小型 exception palette |
285289
| Generated widget | 0 | 0 | 颜色默认值已迁到 boundary fallback registry |
286290
| App UI | 0 | 0 | 普通 app/component raw color 已清零;后续新增必须先进入 token/exception 决策 |
287-
| Syntax | 18 | 17 | Prism syntax palette,保留为专用渲染域 |
291+
| Syntax | 16 | 16 | Prism syntax palette,已按 foreground、muted/comment、keyword、literal、function、markup 等角色收敛;light punctuation 与 dark tag/property 保留相邻代码可读性差异 |
288292

289293
专用域 near color pair 已单独进入证据队列,避免把 editor、terminal、Mermaid、
290294
theme preset 或 boundary fallback 误算成普通 app UI 债务。当前队列不是自动合并指令,
@@ -306,12 +310,14 @@ theme preset 或 boundary fallback 误算成普通 app UI 债务。当前队列
306310
| --- | ---: | --- |
307311
| `src/web-ui/src/component-library/styles/tokens.scss` | 100 | 根 token 契约;优先处理同语义 alias,避免把状态/层级 ramp 按数值强合并 |
308312
| `src/web-ui/src/tools/mermaid-editor/theme/mermaidThemeFallbacks.ts` | 64 | Mermaid 专用渲染兜底;需以节点、边、文本、错误态截图为依据 |
309-
| `src/web-ui/src/shared/theme/languageIdentityAccents.ts` | 52 | 内置 language/file identity registry;调用方复用常量 |
310313
| `src/web-ui/src/tools/editor/themes/bitfun-dark.theme.ts` | 46 | Monaco theme palette;不拆散到普通 app token |
311314
| `src/web-ui/src/infrastructure/theme/core/ThemeService.ts` | 30 | 运行时注入;需保持 early render、system theme 和 payload 导出兼容 |
312-
| `src/web-ui/src/shared/theme/uiExceptionAccents.ts` | 17 | 固定 UI 身份/角色色 registry;新增必须说明 owner/role |
313315
| `src/web-ui/src/tools/terminal/utils/xtermTheme.ts` | 36 | terminal ANSI palette;不与 app semantic color 合并 |
316+
| `src/web-ui/src/tools/mermaid-editor/theme/_tokens.scss` | 27 | Mermaid SCSS token 兜底;只在 Mermaid owner 内治理 |
317+
| `src/web-ui/src/infrastructure/theme/presets/midnight-theme.ts` | 23 | theme preset palette;保留主题个性、状态色和 alpha ramp 边界 |
314318
| `src/web-ui/src/infrastructure/theme/presets/slate-theme.ts` | 22 | theme preset palette;保留主题个性、状态色和 alpha ramp 边界 |
319+
| `src/web-ui/src/shared/theme/themeBoundaryFallbacks.ts` | 18 | iframe/miniapp/截图兜底 palette;只作为边界 fallback 治理 |
320+
| `src/web-ui/src/shared/theme/uiExceptionAccents.ts` | 17 | 固定 UI 身份/角色色 registry;新增必须说明 owner/role |
315321

316322
组件级 `var(--token, fallback)` 已收敛到 0;原先的 7 个 fallback token 不再需要
317323
fallback contract registry 保留。
@@ -351,12 +357,13 @@ Phase 5 决策记录:
351357
| `#ffdd00` -> `#ffd700` | merge | `StreamText.scss` fire yellow;editor/reference yellow | RGB distance = 6,均为亮黄强调色,调用点不相邻,不承担不同业务状态 |
352358
| `#7dd3fc` -> `#7DCFFF` | merge | `GenerativeWidgetToolCard.scss`;`bitfun-dark.theme.ts` editor link | RGB distance = 5,均为非状态 sky/cyan 强调,调用点跨 surface 且不相邻 |
353359
| `#00b4d8` -> `#00add8` | merge | `StreamText.scss` ocean mid;Go language identity | RGB distance = 7,同为 cyan/blue identity/visual-effect 色,非错误/警告/状态强度 |
360+
| language identity palette | category-compress | `languageIdentityAccents.ts` 内置 language/file identity registry;`LanguageRegistry.ts` 和 code snippet metadata 读取 | 原 52 个出现、50 个唯一色改为 8 个大类色;保持所有 language/file key、label、icon、extension 和 helper API 不变,颜色不再承担唯一识别职责;消费方必须同时显示 label/icon/extension/file name 之一 |
361+
| syntax palette roles | role-compress | `syntaxHighlightAccents.ts` Prism/Markdown/CodePreview palette | 浅色 `string/number` 共享 literal blue;light `punctuation` 独立于 comment,dark `tag/property` 保持区分,避免 12px code preview 和 JSX/HTML 相邻 token 可读性下降;syntax 18/17 -> 16/16 |
354362
| Mermaid `#dfe2e8` -> `#e0e2e8` | merge | light `nodeFillHover`;dark `nodeText` | RGB distance = 1,跨 light/dark fallback 角色,不在同一主题视口中承担相邻状态区分;合并后保留 `nodeFillHover` 和 `nodeText` 语义 key |
355363
| Mermaid `#5a5e68` -> `#5a5e6a` | merge | dark `edgeLabelBorderHover`;dark `nodeStroke`/`edgeStroke` | RGB distance = 2,均为深色 Mermaid neutral stroke/border;edge label hover border 不表达独立状态严重程度,合并后仍通过 key 区分角色 |
356364
| Mermaid `#6a6e78` -> `#6a6e7a` | merge | dark `textMuted`;dark `nodeStrokeHover` | RGB distance = 2,均为深色 Mermaid subdued neutral;不是 success/warning/error 或数据类别色,合并后保留 muted text 与 hover stroke 语义 |
357365
| Cyber `#141414` -> `#151515` | merge | `bitfun-cyber` scene background;secondary background;Monaco line highlight | RGB distance = 1.73,三者都在 Cyber 暗色 neutral surface 内,不表达不同状态、严重程度或数据类别;保留 `bgScene`/`secondary`/`lineHighlight` 语义 key,实际色值统一 |
358366
| dark card white alpha literal | merge to canonical overlay stops | `ThemeService.ts` dark `--card-bg-*` runtime injection | `0.015/0.025/0.035/0.09/0.13` 仅是 dark card fallback 的微弱层级色,合并到现有 canonical overlay stop;复审后保留 default/elevated/subtle/hover/active 的相邻状态差异 |
359-
| `#141414` vs `#121214` | preserve | `LanguageRegistry.ts` reStructuredText identity;Flow Chat capture/editor fallback | RGB distance = 2.83,但 `#141414` 是已存在的 language identity,迁移到 registry 时保持原值;`#121214` 仅作为截图/边界兜底 |
360367
| `#f3f3f5` vs `#f4f4f5` | preserve | light theme primary background;dark theme status text | RGB distance = 1.41,但跨 light/dark theme 且角色不同;不通过数值相近抹平主题个性或状态文本对比 |
361368
| `#b8c6ff` -> `#b8c4ff` | merge | Slate theme purple alpha ramp;Slate purple solid stop | RGB distance = 2,同一 Slate purple ramp 内肉眼不可区分;alpha ramp 继续保留独立语义 key,实际 RGB channel 收敛到 solid 500 stop |
362369
| `#fafafa` -> `#ffffff` | merge | Dark theme primary button hover/active text | RGB distance = 8.66,均为同一 dark primary button 交互前景,不承担相邻区域或状态类别区分;默认态 `#f4f4f5` 保留以维持按钮交互层级 |
@@ -416,7 +423,9 @@ Phase 6 防回退约束:
416423
| `colorDomainNearPairs.nearTotal` | 26 | 26 | 控制 theme preset/runtime/token/editor/Mermaid 等专用域 near 队列规模 |
417424
| `colorScopes.appUi.uniqueColors` | 0 | 0 | 阻止普通组件 raw color 唯一色回涨 |
418425
| `colorScopes.appUi.occurrences` | 0 | 0 | 阻止普通组件 raw color 出现次数回涨 |
419-
| `colorScopes.exception.uniqueColors` | 229 | 229 | 控制专用域/例外域总体规模;UI exception 已收敛,但 Mermaid/editor/terminal/language identity 仍按各自 owner 单独治理 |
426+
| `colorScopes.exception.uniqueColors` | 190 | 190 | 控制专用域/例外域总体规模;UI exception、syntax 和 language identity 已收敛,但 Mermaid/editor/terminal 仍按各自 owner 单独治理 |
427+
| `colorDomainScopes.syntax.occurrences` | 16 | 16 | 阻止 Prism syntax palette 回到一 token class 一色的不可扩展模式,同时保留相邻 token 可读性边界 |
428+
| `colorDomainScopes.languageIdentity.uniqueColors` | 8 | 8 | 阻止 language/file identity 回到一语言一色或一扩展一色的不可扩展模式 |
420429
| `colorDomainScopes.boundaryFallback.occurrences` | 18 | 18 | 防止 iframe/mini app/截图兜底色重新散写;导出 key 可保留语义,实际字面值必须回到 boundary fallback palette |
421430
| `tokenAliasLiterals.occurrences` | 0 | 0 | 阻止重新出现可映射到 token 的 app literal |
422431
| `colorDomainScopes.appUi.occurrences` | 0 | 0 | 阻止未归类 app UI 色值回涨 |

‎scripts/theme-color-governance-baseline.json‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@
108108
"max": 205
109109
},
110110
"colorScopes.exception.uniqueColors": {
111-
"max": 229
111+
"max": 190
112112
},
113113
"cssVarDefinitions.unresolvedRequiredUnique": {
114114
"max": 0
@@ -267,7 +267,7 @@
267267
"max": 52
268268
},
269269
"colorDomainScopes.syntax.occurrences": {
270-
"max": 18
270+
"max": 16
271271
},
272272
"colorDomainScopes.terminal.occurrences": {
273273
"max": 37
@@ -282,10 +282,10 @@
282282
"max": 17
283283
},
284284
"colorDomainScopes.languageIdentity.occurrences": {
285-
"max": 52
285+
"max": 8
286286
},
287287
"colorDomainScopes.languageIdentity.uniqueColors": {
288-
"max": 50
288+
"max": 8
289289
},
290290
"colorDomainScopes.visualEffect.occurrences": {
291291
"max": 0

‎src/web-ui/src/shared/context-system/core/types/CodeSnippetContextImpl.test.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ describe('CodeSnippetContextImpl language metadata', () => {
1414

1515
it('keeps code snippet language accents centralized', () => {
1616
expect(getLanguageColor('typescript')).toBe('#3178c6');
17-
expect(getLanguageColor('rust')).toBe('var(--color-bg-primary)');
18-
expect(getLanguageColor('java')).toBe('#007396');
19-
expect(getLanguageColor('unknown-lang')).toBe('#858585');
20-
expect(getLanguageColor()).toBe('#858585');
17+
expect(getLanguageColor('rust')).toBe('#e38c00');
18+
expect(getLanguageColor('java')).toBe('#e38c00');
19+
expect(getLanguageColor('unknown-lang')).toBe('#64748b');
20+
expect(getLanguageColor()).toBe('#64748b');
2121
});
2222

2323
it('keeps mermaid diagram context color in the UI exception registry', () => {

‎src/web-ui/src/shared/theme/languageIdentityAccents.ts‎

Lines changed: 64 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,79 @@
11
// Language identity colors are data semantics, not app theme surface colors.
22
// Keep this registry narrow and only add values that are consumed outside the
33
// full language registry.
4+
const LANGUAGE_IDENTITY_PALETTE = {
5+
blue: '#3178c6',
6+
cyan: '#00add8',
7+
yellow: '#f7df1e',
8+
orange: '#e38c00',
9+
red: '#ef4444',
10+
green: '#22c55e',
11+
purple: '#8b5cf6',
12+
slate: '#64748b',
13+
} as const;
14+
415
export const BUILTIN_LANGUAGE_ACCENTS = {
5-
typescript: '#3178c6',
6-
typescriptReact: '#61dafb',
7-
javascript: '#f7df1e',
8-
javascriptReact: '#61dafb',
9-
python: '#3776ab',
10-
rust: '#ce422b',
11-
go: '#00add8',
12-
java: '#b07219',
13-
kotlin: '#a97bff',
14-
cpp: '#f34b7d',
15-
c: '#555555',
16-
csharp: '#178600',
17-
swift: '#f05138',
18-
php: '#4f5d95',
19-
ruby: '#cc342d',
20-
scala: '#c22d40',
21-
dart: '#00b4ab',
22-
lua: '#000080',
23-
r: '#198ce7',
24-
html: '#e34c26',
25-
xml: '#0060ac',
26-
vue: '#41b883',
27-
svelte: '#ff3e00',
28-
css: '#563d7c',
29-
scss: '#c6538c',
30-
sass: '#c6538c',
31-
less: '#1d365d',
32-
json: '#cbcb41',
33-
yaml: '#cb171e',
34-
toml: '#9c4121',
35-
sql: '#e38c00',
36-
graphql: '#e10098',
37-
dockerfile: '#2496ed',
38-
makefile: '#427819',
39-
ini: '#d1dbe0',
40-
env: '#ecd53f',
41-
shell: '#89e051',
42-
powershell: '#012456',
43-
batch: '#c1f12e',
44-
markdown: '#083fa1',
45-
restructuredtext: '#141414',
46-
image: '#a855f7',
47-
audio: '#22c55e',
48-
video: '#ef4444',
49-
font: '#f59e0b',
50-
archive: '#8b5cf6',
51-
binary: '#64748b',
52-
plaintext: '#6e7781',
16+
typescript: LANGUAGE_IDENTITY_PALETTE.blue,
17+
typescriptReact: LANGUAGE_IDENTITY_PALETTE.cyan,
18+
javascript: LANGUAGE_IDENTITY_PALETTE.yellow,
19+
javascriptReact: LANGUAGE_IDENTITY_PALETTE.cyan,
20+
python: LANGUAGE_IDENTITY_PALETTE.blue,
21+
rust: LANGUAGE_IDENTITY_PALETTE.orange,
22+
go: LANGUAGE_IDENTITY_PALETTE.cyan,
23+
java: LANGUAGE_IDENTITY_PALETTE.orange,
24+
kotlin: LANGUAGE_IDENTITY_PALETTE.purple,
25+
cpp: LANGUAGE_IDENTITY_PALETTE.red,
26+
c: LANGUAGE_IDENTITY_PALETTE.slate,
27+
csharp: LANGUAGE_IDENTITY_PALETTE.green,
28+
swift: LANGUAGE_IDENTITY_PALETTE.red,
29+
php: LANGUAGE_IDENTITY_PALETTE.purple,
30+
ruby: LANGUAGE_IDENTITY_PALETTE.red,
31+
scala: LANGUAGE_IDENTITY_PALETTE.red,
32+
dart: LANGUAGE_IDENTITY_PALETTE.cyan,
33+
lua: LANGUAGE_IDENTITY_PALETTE.blue,
34+
r: LANGUAGE_IDENTITY_PALETTE.blue,
35+
html: LANGUAGE_IDENTITY_PALETTE.red,
36+
xml: LANGUAGE_IDENTITY_PALETTE.blue,
37+
vue: LANGUAGE_IDENTITY_PALETTE.green,
38+
svelte: LANGUAGE_IDENTITY_PALETTE.orange,
39+
css: LANGUAGE_IDENTITY_PALETTE.blue,
40+
scss: LANGUAGE_IDENTITY_PALETTE.purple,
41+
sass: LANGUAGE_IDENTITY_PALETTE.purple,
42+
less: LANGUAGE_IDENTITY_PALETTE.blue,
43+
json: LANGUAGE_IDENTITY_PALETTE.yellow,
44+
yaml: LANGUAGE_IDENTITY_PALETTE.red,
45+
toml: LANGUAGE_IDENTITY_PALETTE.orange,
46+
sql: LANGUAGE_IDENTITY_PALETTE.orange,
47+
graphql: LANGUAGE_IDENTITY_PALETTE.purple,
48+
dockerfile: LANGUAGE_IDENTITY_PALETTE.blue,
49+
makefile: LANGUAGE_IDENTITY_PALETTE.green,
50+
ini: LANGUAGE_IDENTITY_PALETTE.slate,
51+
env: LANGUAGE_IDENTITY_PALETTE.yellow,
52+
shell: LANGUAGE_IDENTITY_PALETTE.green,
53+
powershell: LANGUAGE_IDENTITY_PALETTE.blue,
54+
batch: LANGUAGE_IDENTITY_PALETTE.green,
55+
markdown: LANGUAGE_IDENTITY_PALETTE.blue,
56+
restructuredtext: LANGUAGE_IDENTITY_PALETTE.slate,
57+
image: LANGUAGE_IDENTITY_PALETTE.purple,
58+
audio: LANGUAGE_IDENTITY_PALETTE.green,
59+
video: LANGUAGE_IDENTITY_PALETTE.red,
60+
font: LANGUAGE_IDENTITY_PALETTE.orange,
61+
archive: LANGUAGE_IDENTITY_PALETTE.purple,
62+
binary: LANGUAGE_IDENTITY_PALETTE.slate,
63+
plaintext: LANGUAGE_IDENTITY_PALETTE.slate,
5364
} as const;
5465

5566
export const CODE_SNIPPET_LANGUAGE_ACCENTS = {
5667
javascript: BUILTIN_LANGUAGE_ACCENTS.javascript,
5768
typescript: BUILTIN_LANGUAGE_ACCENTS.typescript,
5869
python: BUILTIN_LANGUAGE_ACCENTS.python,
59-
rust: 'var(--color-bg-primary)',
70+
rust: BUILTIN_LANGUAGE_ACCENTS.rust,
6071
go: BUILTIN_LANGUAGE_ACCENTS.go,
61-
java: '#007396',
72+
java: BUILTIN_LANGUAGE_ACCENTS.java,
6273
html: BUILTIN_LANGUAGE_ACCENTS.html,
63-
css: '#1572b6',
64-
scss: '#cc6699',
65-
fallback: '#858585',
74+
css: BUILTIN_LANGUAGE_ACCENTS.css,
75+
scss: BUILTIN_LANGUAGE_ACCENTS.scss,
76+
fallback: LANGUAGE_IDENTITY_PALETTE.slate,
6677
} as const;
6778

6879
export function getCodeSnippetLanguageAccent(language?: string): string {

0 commit comments

Comments
 (0)