Bundle
dsh-theme-colors
DSH Web 界面配色调节插件:在设置里直接调整会话栏、左右侧栏与文字色,含 OKLCH 深度/鲜亮度调节、日间夜间方案与预设
- Source
- Alicex7777
- License
- MIT
- Updated
- Updated 7 days ago
Readme
# dsh-theme-colors
[](https://github.com/Alicex7777/dsh-theme-colors/actions/workflows/test.yml)
[](LICENSE)
DSH(DeepSeek Harness)Web 界面的配色调节插件。**在界面里直接改**:不用改代码、不用重启浏览器,颜色即时生效并持久保存。
配色推导走 OKLCH 感知均匀空间,所有内置取值都用测试卡住可读性(WCAG 对比度)。
- 可调区域:**会话栏**(中间对话区)、**左侧会话列表栏**、**右侧栏**,三者互不牵连
- 每个区域支持取色器、十六进制输入、不透明度(0–100%),以及「跟随主题」清除覆盖
- 每行还有:**复制**(把色值写进剪贴板)、**统一**(把该区域的颜色与不透明度一次套用到全部区域)
- **深度 / 鲜亮度**滑杆:在 OKLCH 里只改明度(L)或只改彩度(C),色相与方案结构不变,超出 sRGB 时按 CSS Color 4 降彩度
- **26 套内置方案**:13 套日间(配官方浅色主题)+ 13 套夜间(深蓝 / 深绿 / 墨黑 / 暖褐…),全部 ≥ 12:1 对比度
- **文字色**三态:跟随官方(默认)/ **推荐色**(按方案表面推导并跟随变化)/ **自定义**(预设 + 自由色域图 + 文字深度鲜亮度 + 逐档手填)
- **浅色主题与深色主题各存一套**,跟着 DSH 的 设置 → 通用 → 主题 自动切换
- 两个入口都在界面内:
1. 悬浮入口「🎨 配色」——默认贴在左侧边栏右侧、会话区左下角(不压住边栏底部的「设置」),**可以拖动**,位置会记住
2. **设置 → 通用 → 配色** 卡片上的「调整配色…」→ 打开同一个面板
## 安装
DSH 的插件都装在 **profile** 里(本插件的 Web profile 名为 `web`),安装命令会把仓库以 `link:` 方式登记进 profile,
并自动追加到该 profile 的 `dsh.profile.bundles`。下面分两种情形:**你自己手动装** / **让 AI agent 帮你装**。
### A. 手动安装(你本人操作)
**前提**:`dsh` 可用(`dsh --version` 能出版本号)、`pnpm` 可用(`pnpm -v`;没有就 `npm i -g pnpm`)。
不需要 Node 依赖,本插件零依赖。
1. **取得代码**(二选一)
```powershell
git clone https://github.com/Alicex7777/dsh-theme-colors.git D:\repos\dsh-theme-colors
```
或在仓库页面点 **Code → Download ZIP** 后解压到任意固定目录(例如 `D:\repos\dsh-theme-colors`)。
> 建议放在**不含空格、之后不会随手移动**的目录;移动后需要重新执行第 2 步。
2. **装进 web profile**(在任意终端执行;`link:` 后面是**仓库根目录**,也就是含 `package.json` 的那一层)
```powershell
dsh plugin --profile web add link:D:\repos\dsh-theme-colors
```
> ⚠️ 不要写成 `link:D:\repos\dsh-theme-colors\lib` 这种子目录,否则会被当成普通依赖安装,插件不会生效。
3. **确认已登记**
```powershell
dsh --profile web --dump-config | Select-String dsh-theme-colors
```
输出里应能看到 `dsh-theme-colors`。
4. **重启 `dsh web`**(宿主侧插件在启动时加载,新增的路由只在启动时注册),然后**回到浏览器按 Ctrl+F5**。
5. **确认装好了**:左下角出现「🎨 配色」按钮;**设置 → 通用** 里多出「配色」卡片。
也可以直接看接口:
```powershell
curl.exe -s -o NUL -w "%{http_code}`n" http://127.0.0.1:3080/dsh-theme-colors/config.json # 期望 200
curl.exe -s http://127.0.0.1:3080/dsh-theme-colors/gui.js | Select-String dsh-theme-colors:open
```
**卸载 / 重装**
```powershell
dsh plugin --profile web remove dsh-theme-colors # 卸载(之后重启 dsh web)
dsh plugin --profile web add link:D:\repos\dsh-theme-colors # 移动过目录后重新登记
```
### B. 让 agent 帮你安装(把下面整段发给 AI)
````text
请帮我在这台机器上安装 DSH 插件 dsh-theme-colors,来源是 GitHub 仓库 Alicex7777/dsh-theme-colors。
背景知识(省得你摸索):
- DSH 的插件不是装到 DSH 自身目录里,而是装进「profile」。本机用到的 Web profile 名为 web,
目录在 $DSH_HOME/profiles/web(DSH_HOME 默认是 ~/.dsh,Windows 上是 C:\Users\<用户名>\.dsh)。
- 仓库根目录就是插件包本身(含 package.json 与 cordis.patch.yml),安装时用 link: 指向它。
- 宿主侧代码只在 dsh web 启动时加载,所以装完必须重启 dsh web;界面脚本虽按请求现读,但也要刷新页面。
请按这个顺序做,并把每一步的结果告诉我:
1. 检查工具:`dsh --version`、`pnpm -v`。pnpm 缺失就 `npm i -g pnpm`(Windows 上若 PowerShell 禁止运行 .ps1,
用 dsh.cmd / pnpm.cmd 调用)。
2. 取代码:克隆到固定目录,例如:
git clone https://github.com/Alicex7777/dsh-theme-colors.git <一个不含空格、不会随手移动的目录>
如果这台机器连不上 github.com:443,就改用浏览器下载 ZIP 解压,或问我要一个本地副本;
不要因为克隆失败就跳过——先告诉我卡在哪。
3. 安装(link: 指向仓库根目录,不要带 /lib 之类子目录):
dsh plugin --profile web add link:<仓库绝对路径>
4. 校验登记:`dsh --profile web --dump-config` 的输出里应出现 dsh-theme-colors;
另外 $DSH_HOME/profiles/web/package.json 的 dsh.profile.bundles 里也应有它。
5. 重启 dsh web;等端口 3080 起来后验证:
- `curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:3080/dsh-theme-colors/config.json` 期望 200
- `curl -s http://127.0.0.1:3080/dsh-theme-colors/gui.js` 里能看到 dsh-theme-colors:open
6. 让我在浏览器 Ctrl+F5,然后确认:左下角有「🎨 配色」按钮、设置 → 通用 里有「配色」卡片。
如果按钮没出现,先看浏览器控制台里有没有含 dsh-theme-colors 的告警,把原文发我。
排错提示:
- 若报 pnpm 找不到:装 pnpm 后重试;Windows 下注意 .ps1 执行策略会拦截 pnpm.ps1,改用 pnpm.cmd。
- 若安装成功但界面没变化:确认第 5 步的两个 200/输出,并确认真的重启过 dsh web、浏览器强刷过。
- 卸载:`dsh plugin --profile web remove dsh-theme-colors`,再重启 dsh web。
- 本插件不含任何密钥;它只在 $DSH_HOME/.dsh-theme-colors.json 里存配色,不会碰 DSH 自身安装目录。
````
## 使用
1. 点悬浮入口「🎨 配色」(或进 **设置 → 通用**,找到「配色」卡片点「调整配色…」)。
2. 顶部切「浅色主题 / 深色主题」——两套配色分别对应 DSH 主题的浅色与深色;
想调哪一套,先把 DSH 主题切到那一边,改完即时能看到效果。
3. 改颜色 / 拉不透明度,**改动即时保存并生效**,状态行显示「已保存 hh:mm:ss」。
每个区域只影响自己那一栏;想把几栏调成同一个颜色,就在其中一行点「统一」,
或者点「复制」拿到色值再粘到别处。
4. 某个区域想回到主题原样:点该行的「跟随主题」。
5. 全部复原:面板底部「全部重置」。
6. 入口按钮:**按住可拖到任意位置**(松手即记住,跨刷新保持);不想看到它就在面板里取消「显示悬浮入口」;拖乱了点「入口归位」回到默认位置(侧边栏右侧)。
> 面板打开时会自动切到当前生效的那套主题。配色写在 `$DSH_HOME/.dsh-theme-colors.json`
> (默认 `C:\Users\<你>\.dsh\.dsh-theme-colors.json`),面板底部会显示实际路径;手工编辑后刷新页面即生效。
## 内置配色方案
预设条分成两组,**日间方案配官方浅色主题、夜间方案配官方深色主题**,
点一下只写对应那一套(不互相覆盖),之后切官方主题就自动换。
**日间方案(13 套,配官方浅色主题)**——每格是「会话栏 / 左侧会话列表栏」,右侧栏与左侧栏同色。
取值由 `scripts/gen-presets.mjs` 按 OKLCH 目标反解:会话栏 L≈0.90、左栏 L≈0.85,彩度 0.012–0.026:
| 方案 | 会话栏 / 左栏 | OKLCH(L / C / H) | 说明 |
| --- | --- | --- | --- |
| 米白暖灰 | `#e3ddd5` / `#d3cdc4` | 0.90 / 0.013 / 75° | 莫兰迪暖灰,暖而不黄 |
| 青灰清透 | `#d4e1df` / `#c3d1cf` | 0.90 / 0.014 / 186° | 莫兰迪静物青灰(`#AFC0BC` `#699199`) |
| 雾霾蓝 | `#d1e0ed` / `#bfd0df` | 0.90 / 0.024 / 244° | 灰调蓝(`#84B5CE` `#305C71`) |
| 天青蓝 | `#cfe2e7` / `#bcd2d8` | 0.90 / 0.022 / 215° | 青蓝,比雾霾蓝更冷 |
| 鼠尾草绿 | `#d8e1d5` / `#c7d2c3` | 0.90 / 0.019 / 138° | 低饱和绿(`#81907F` `#B7B28F`) |
| 薄荷雾绿 | `#d3e2db` / `#c1d3ca` | 0.90 / 0.020 / 165° | 薄荷绿,清爽不刺眼 |
| 藕荷灰紫 | `#e0dbe8` / `#d0cbd9` | 0.90 / 0.018 / 303° | 灰紫调 |
| 丁香紫 | `#dcdceb` / `#ccccdd` | 0.90 / 0.020 / 285° | 蓝紫,偏冷 |
| 燕麦米 | `#e8dccb` / `#d9ccb9` | 0.90 / 0.026 / 77° | 奶油米色(`#B99C5A` 一族) |
| 灰粉胭脂 | `#ead9da` / `#dbc9c9` | 0.90 / 0.019 / 13° | 低饱和玫瑰灰(`#C9A9A6`) |
| 樱粉 | `#e7dadf` / `#d8c9cf` | 0.90 / 0.016 / 350° | 淡粉,偏紫调 |
| 蜜桃珊瑚 | `#edd9d3` / `#dfc8c2` | 0.90 / 0.024 / 35° | 珊瑚暖粉 |
| 极昼纯白 | `#ffffff` / `#f2f3f4` | — | 纯白底,最中性 |
**夜间方案(13 套,配官方深色主题)**。会话栏 L≈0.32、左栏 L≈0.26(墨黑 L=0.20)——比纯黑有层次
(与主流编辑器深色同级),彩度 0.006–0.058,所以「深蓝/深绿」确实是深蓝深绿,而不是一片近黑:
| 方案 | 会话栏 / 左栏 | OKLCH(L / C / H) | 说明 |
| --- | --- | --- | --- |
| 深蓝 | `#1d3450` / `#13253b` | 0.32 / 0.058 / 254° | 深海蓝,色感明确 |
| 深青蓝 | `#1f3641` / `#142730` | 0.32 / 0.035 / 230° | 板岩青蓝,偏冷静 |
| 墨绿蓝 | `#16393b` / `#0c292a` | 0.32 / 0.040 / 200° | 青蓝偏绿 |
| 青灰夜 | `#283632` / `#1b2723` | 0.32 / 0.020 / 175° | 冷青灰,最接近官方深色 |
| 深绿 | `#203a26` / `#152a19` | 0.32 / 0.048 / 150° | 松林深绿 |
| 深橄榄 | `#343421` / `#252516` | 0.32 / 0.032 / 110° | 暗橄榄绿 |
| 暗紫 | `#392e40` / `#29202e` | 0.32 / 0.034 / 312° | 灰紫夜调 |
| 墨蓝紫 | `#303049` / `#222136` | 0.32 / 0.045 / 285° | 靛蓝偏紫 |
| 暗酒红 | `#452b2a` / `#331d1d` | 0.32 / 0.040 / 20° | 酒红夜调 |
| 暖褐可可 | `#3b3027` / `#2b221b` | 0.32 / 0.022 / 62° | 陶土暖褐(`#C08A6E` 一族) |
| 暖黑(低蓝光) | `#2f2723` / `#1f1916` | 0.28 / 0.014 / 52° | 暖调深灰,夜间护眼 |
| 墨黑 | `#141619` / `#08090b` | 0.20 / 0.006 / 260° | 近黑,OLED 省电 |
| 石墨黑 | `#303337` / `#222427` | 0.32 / 0.008 / 250° | 中性石墨,不偏色 |
两组方案与对应主题文字色(浅色 `#0f1115`、深色 `#f9fafb`,取自 `--dsw-alias-label-primary`)的对比度
均 ≈**12:1**(最低 11.86:1),远高于 WCAG AA 的 4.5:1;日间底色亮度 > 0.6、夜间 < 0.1。
这几条都由 `scripts/test-gui.mjs` 逐条验算,不达标即测试失败。
取色参考:[莫兰迪静物取色](https://paletteinspiration.com/giorgio-morandi-palettes/giorgio-morandi-2-palette/)、
[灰粉 `#C9A9A6`](https://colorabacus.com/color.php?hex_code=C9A9A6)、[陶土 `#C08A6E`](https://zh.spycolor.com/c08a6e)、[纯黑 `#0B0B0C`](https://colors.to/0b0b0c)。
## 微调:深度与鲜亮度
预设下面两条滑杆针对**当前页签那套**重算颜色,改完即时生效:
- **深度**:只改 **OKLCH 的 L(感知明度)**。浅色主题范围 L 0.97 → 0.66(纯白 → 有明显色调的深底),
深色主题 L 0.48 → 0.05(深灰 → 近黑)。
- **鲜亮度**:只改 **OKLCH 的 C(彩度)**,以该 L/H 下 sRGB 能达到的最大彩度的 55% 为满值。
0 就是完全中性灰,拉高则颜色更鲜明。
- 「还原方案原值」回到滑杆基准(点方案、切页签、手改颜色都会重设基准,所以反复拖动不会累积失真)。
### 为什么用 OKLCH 而不是 HSL
HSL 的"亮度"不是感知亮度:同样 50% 亮度,黄色看起来远亮于蓝色,拿它做"深度"会随色相飘,改亮度还会把颜色推向意外色相。
OKLab([Ottosson, 2020](https://bottosson.github.io/posts/oklab/))是感知均匀空间——等量的 L 变化在任何色相上看起来一样,
且 C(彩度)与 H(色相)相互独立。因此本实现做到:
- 调深度**不改色相**、调鲜亮度**不改明度**;
- 三个区域各自保留色相,明度按"相对会话栏的深浅差"整体平移,方案结构(左栏比会话栏略深、右栏与左栏同色)不变;
- 超出 sRGB 色域时按 [CSS Color 4](https://www.w3.org/TR/css-color-4/#gamut-mapping) 的做法降彩度(保 L 与 H),不产生溢出的怪色。
### 永远看得清
每行右侧直接显示与官方该主题文字色的**对比度**(WCAG 比值),低于 4.5:1 会转成警示色。
滑杆两端本身就留了余量,`scripts/test-color.mjs` 会在「每套方案 × 深度 0–100 × 鲜亮度 0/50/100」的全部组合上验算
对比度 ≥ 4.5:1(实测最低 **4.69:1**);此外还有一层夹紧兜底:若基准色内部明暗差极大导致结果不可读,
明度会自动收到刚好达标处,并在面板上提示「已到可读性下限」。
颜色数学本身也有独立测试:OKLab 换算对照 Ottosson 文中给出的参考值(sRGB 红 → L 0.6279 / C 0.2577 / H 29.23°)、
hex→OKLCH→hex 往返误差 ≤ 2/255、色域上限、色相保持、彩度单调、结构保持等。
## 文字色(三态:跟随官方 / 推荐 / 自定义)
文字色有三种状态,**默认是「跟随官方」**;「推荐色」与「自定义」默认都关闭,且互斥(开一个会关掉另一个)。
两种非默认状态都会覆盖官方主题的 `--dsw-alias-label-primary` / `-secondary` / `-tertiary`
(`dimmed`、`caption`、`inverted` 与语义色仍由主题负责,避免影响按钮上的反白文字与状态色)。
### 推荐色(自动,跟随方案)
按当前方案**表面色相**推导三档文字色,表面一改就自动重算:
- 色相取自表面,彩度取**绝对目标值**(主 0.030 / 次 0.042 / 三级 0.052,OKLCH 的 C);
- 明度按对比度目标解出,明暗极性跟着**表面亮度**走(浅面配深字、深面配亮字);
- 实测:米白暖灰底 → `#1e1406`(暖褐,C 0.030,13.4:1)、深蓝底 → `#d7e6f9`(浅蓝,C 0.031,10.0:1),色相与表面一致。
### 自定义(手动)
- **预设**(一键写入浅色+深色两套):
| 预设 | 浅色面(主 / 次 / 三级) | 深色面(主 / 次 / 三级) |
| --- | --- | --- |
| 暖墨 | `#2a231c` / `#4a4036` / `#6b5f52` | `#ece5db` / `#c4b8a8` / `#9d9184` |
| 冷墨 | `#1b2029` / `#3a4250` / `#5a6373` | `#e2e7ef` / `#b6bfcc` / `#8c96a4` |
| 中性灰墨 | `#262626` / `#454545` / `#666666` | `#e8e8e8` / `#bdbdbd` / `#949494` |
| 纯黑纯白 | `#000000` / `#333333` / `#555555` | `#ffffff` / `#cccccc` / `#a3a3a3` |
| 同色相 | 按当前方案表面推导(同推荐色) | 同左 |
- **自由色域图**:横轴色相、纵轴明度,按当前彩度实时渲染**该深度下真正可达的颜色**(不是固定彩虹图)。
点 / 拖即在图上取色——横轴定色相、纵轴定明度,三档按各自相对明度差一起生成。
- **文字深度 / 文字鲜亮度**:与区域那对滑杆同理,作用在三档文字色上(同色相,保留三档明度差),
深度两端同样避开纯黑纯白(0.03 / 0.97),否则端点上彩度必然是 0、鲜亮度会失效。
- **逐档手填**:每档可取色、填 hex、「跟随」回官方;每档右侧显示对三个表面的**最差**对比度。
### 验收标准与一个警示
每套预设、每一档,对该模式下**全部 13 套方案的三个表面**逐一验算:主 ≥7:1(AAA)/ 次 ≥4.5:1(AA)/ 三级 ≥3:1,
不达标即测试失败;「推荐色」另有一条**彩度 ≥ 0.012** 的回归断言,防止再退回近黑近白。
若三个区域明暗本身相反(例如把浅色面放进深色那套),单一文字色不可能都看清——面板会直接提示
「各区域明暗相反,单一文字色无法都看清」,而不是默默给出读不清的颜色。
> 教训记录:更早的版本把文字彩度锚在「表面彩度比例 × 25%」上,而表面被刻意调成极低彩度(C 0.006–0.058),
> 乘完只剩 C≈0.002–0.005——实测就是 `#161615`、`#141618` 这类近黑,肉眼看等于没上色。改为绝对彩度目标后才真正有色调。
> 兼容:`text` 是新增字段。宿主未重启时(旧版归一化不认识它,保存会丢弃)取值先镜像在浏览器 localStorage,
> 重启 `dsh web` 后落进配置文件、镜像让位;旧的布尔开关 `text.enabled` 会被迁移成 `mode: custom`。
### 官方主题切换
面板顶部显示当前官方主题(浅色/深色)与「切到深色/浅色」按钮,点击通过宿主 settings 服务写入
`ui-theme.preference`(官方主题的权威入口,与官方设置页同步,不直接改配置文件)。
> 这条能力是宿主侧新增的:**运行中的实例若是在它之前启动的,需要重启一次 `dsh web` 才可用**;
> 未重启时点它会提示「需要重启一次 dsh web」,此时仍可用 设置 → 通用 → 主题 切换。
## 生效方式
| 区域 | 实现 | 说明 |
| --- | --- | --- |
| 会话栏 | 在 `[class*="centerCol"]` 上**就地重绑定** token `--dsw-alias-bg-base`,并同时设 `background` | 中列本身是透明的,真正铺满整列的是栏内会话根元素(`background: var(--dsw-alias-bg-base)`),只设背景会被它盖住 |
| 左侧会话列表栏 | 覆盖 token `--dsw-specific-sidebar-fill` | 左栏自己的 token,与其它区域无关 |
| 右侧栏 | 在 `[class*="rightbarCol"]` 上就地重绑定 `--dsw-alias-bg-base` 与 `--dsw-alias-bg-layer-1`,并同时设 `background` | 就是 Ctrl+Shift+B 唤出的右侧面板:文件 / 浏览器 / 终端各页签自己铺底色(面板用 base、页签栏与终端用 layer-1),只设列背景会被内容盖住 |
三个区域各写各的规则、互不牵连:没有「整体底色」这类会互相覆盖的层级。
- 配色 CSS 由宿主在每次渲染 `index.html` 时下发,**首帧就是目标配色**,不会先闪一下默认主题。
- 界面侧脚本还会用**同一份** `palette.js`(按请求现读磁盘)按当前配置重算 CSS 并覆盖上去,
因此**配色规则的改动刷新即生效**,只有宿主代码(`index.js`)的改动才需要重启 `dsh web`;
取不到该模块时用脚本内等价的兜底实现(`scripts/test-gui.mjs` 逐行校验两者一致)。
- 脚本每 2.5 秒对一次接口,手工改 JSON 或另开窗口调整都能同步。
## 配置文件
```jsonc
{
"version": 3,
"launcher": true, // 是否显示悬浮入口按钮
"launcherSpot": null, // 悬浮入口位置(视口比例 0..1);null = 自动贴在侧边栏右侧
"text": { // 文字色:off(跟随官方,默认)/ recommended(按方案推导)/ custom(自定义)
"mode": "custom",
"light": { "primary": { "color": "#2f2c28", "opacity": 100 }, "secondary": { "color": "#4b4741", "opacity": 100 }, "tertiary": { "color": "#645f57", "opacity": 100 } },
"dark": { "primary": { "color": "#eae7e3", "opacity": 100 }, "secondary": { "color": "#bbb6b0", "opacity": 100 }, "tertiary": { "color": "#948f89", "opacity": 100 } }
},
"regions": {
"conversation": { "light": { "color": "#1b2430", "opacity": 100 }, "dark": { "color": "", "opacity": 100 } },
"sidebar": { "light": { "color": "", "opacity": 100 }, "dark": { "color": "", "opacity": 100 } },
"rightbar": { "light": { "color": "", "opacity": 100 }, "dark": { "color": "", "opacity": 100 } }
}
}
```
`color` 为 `""` 表示跟随主题;非法颜色与越界不透明度在读写两侧都会被清掉/夹紧,坏文件不会影响界面。
`launcherSpot` 写成 `{"x": 0.5, "y": 0.9}` 这样的比例;拖动入口按钮就是写这个字段。
版本 2 起去掉了「页面背景」(旧字段读取时忽略、下次保存清除);版本 3 起加入 `text` 段(缺省即 `mode: "off"`,
旧的布尔开关 `enabled` 会迁移成 `mode: "custom"`)。
## 修改插件后如何生效
| 改动内容 | 生效方式 |
| --- | --- |
| 界面脚本 `lib/gui.js` | 刷新页面即可(宿主按请求现读该文件) |
| 配色语义 `lib/palette.js` | 刷新页面即可(界面侧用同一份文件重算 CSS);想让首帧也不闪,重启 `dsh web` |
| 宿主 `lib/index.js` | 重启 `dsh web` |
| 设置卡片 `lib/client.js` | 客户端模块会用新 rev 热更,刷新页面即生效 |
## 排查
- **左下角没按钮,设置里也没有「配色」卡片**:确认 `dsh --profile web --dump-config` 输出里有 `dsh-theme-colors`,并已重启 `dsh web`;浏览器控制台搜 `dsh-theme-colors` 看是否有告警。
- **入口按钮压住了别的控件**:直接把它拖走(位置会记住);也可以在面板里取消「显示悬浮入口」,只用设置页的卡片。
- **改了颜色但界面没变**:先看面板状态行是否「已保存」;再看设置的 DSH 主题与正在编辑的那一套是否对应(浅色/深色是两套值)。
- **字看不清 / 提示「各区域明暗相反」**:面板每行右侧都有与三个表面的最差对比度;三个区域本身明暗相反时,单一文字色不可能都看清,请把它们的明暗调回同一侧。
- **只想用设置页入口**:把配置文件里的 `launcher` 改成 `false`(或直接删掉 `$DSH_HOME/.dsh-theme-colors.json` 恢复默认)。
## 已知边界
- 不透明度用 `color-mix()`,需要 Chromium 111+ / Safari 16.2+(DSH Web 的目标浏览器满足)。
- 会话栏与右侧栏靠布局类名片段命中,若 DSH 后续改掉 `centerCol` / `rightbarCol` 这类命名,需要同步更新 `lib/palette.js` 的 `REGIONS`。
- 只改颜色,不改字体、圆角、阴影等其它主题参数。
- 文字色只接管 `label-primary / -secondary / -tertiary`;`dimmed`、`caption`、`inverted` 与语义色(成功/警告/错误)仍由官方主题负责。
- 面板内「切官方主题」与把文字色写进配置文件,都需要宿主重启过一次(见上文兼容说明)。
## 开发
无依赖,装好 Node 18+ 即可(`node:test` 之外没用到任何包)。跑全部测试:
```powershell
npm test # 等价于下面五条按序执行
```
单条:
```powershell
node --check lib/index.js
node scripts/test-palette.mjs # 配置归一化 + CSS 生成
node scripts/test-host.mjs # 桩 ctx + 真实 HTTP:路由、鉴权头、落盘、index 注入、官方主题写入
node scripts/test-gui.mjs # 最小 DOM:入口按钮、面板、方案、滑杆、文字色、保存与即时生效
node scripts/test-client.mjs # 最小 React:设置卡片注册与渲染
node scripts/test-color.mjs # 颜色科学:OKLab 参考值、往返精度、滑杆行为与可读性保证
node scripts/gen-presets.mjs # 按 OKLCH 目标反解方案色值(改方案时用它生成)
node scripts/gen-text-presets.mjs # 校验文字色预设对全部表面的对比度、以及"同色相"的彩度是否看得见
```
目录:
```
dsh-theme-colors/
├── lib/
│ ├── index.js # 宿主侧:配置读写、index 注入、官方主题写入接口
│ ├── palette.js # 配色语义与 CSS 生成(区域表、推荐文字色 token、归一化)
│ ├── client.js # 客户端卡片(设置 → 通用 → 配色)
│ └── gui.js # 界面侧:调色面板、OKLCH 颜色数学、滑杆、色域图
├── scripts/ # 五套测试 + 两个取色生成器
├── cordis.patch.yml # 插件挂载声明
└── package.json
```
Install
dsh plugin --profile web add github:Alicex7777/dsh-theme-colors
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-theme-colors from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.