dsh-background-by-model 0.7.4 → 0.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -1
- package/CHANGELOG.zh.md +23 -1
- package/README.md +62 -35
- package/README.zh.md +62 -35
- package/lib/client.js +1393 -556
- package/lib/index.js +483 -37
- package/package.json +6 -6
- package/example_img/rule-editor.webp +0 -0
- package/example_img/wallpaper-deepseek.webp +0 -0
- package/example_img/wallpaper-kimi.webp +0 -0
- package/holiday/mid-autumn.webp +0 -0
- package/holiday/national-day.webp +0 -0
- package/lib/client.js.map +0 -1
package/README.zh.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
> 派生自 [`Tkingxiao/dsh-any-background`](https://github.com/Tkingxiao/dsh-any-background),并重命名为 `dsh-background-by-model`。
|
|
11
11
|
|
|
12
|
-
一个 **DeepSeek Harness**
|
|
12
|
+
一个 **DeepSeek Harness** 外观插件,核心是一份**有序的模型规则列表**:每条规则自带壁纸(可多张)、透明度与模糊度,**每张图各有自己的布局模式、取景与主题色**,切换模型即切换背景,切换过程走你在「配置」页选定的全局[切换效果](#切换效果全局)。
|
|
13
13
|
|
|
14
14
|
> **v0.3.0 是破坏性更新**:视频背景、生成式背景与全局主题色均已被移除。详见 [CHANGELOG.zh.md 的 v0.3.0 条目](./CHANGELOG.zh.md#v030)。
|
|
15
15
|
|
|
@@ -49,21 +49,21 @@
|
|
|
49
49
|
同一套界面、同一份配置,只因为当前模型不同:
|
|
50
50
|
|
|
51
51
|
<p align="center">
|
|
52
|
-
<img src="
|
|
52
|
+
<img src="https://cdn.jsdelivr.net/gh/HarmlessFunny/assets@main/dsh-background-by-model/wallpaper-deepseek.webp" alt="DeepSeek 下的外观" width="880">
|
|
53
53
|
<br/>
|
|
54
54
|
<em>DeepSeek V4.1 Flash · 命中匹配串含 <code>deepseek</code> 的规则:浅色壁纸 + 与图相配的主题色</em>
|
|
55
55
|
</p>
|
|
56
56
|
|
|
57
57
|
<p align="center">
|
|
58
|
-
<img src="
|
|
58
|
+
<img src="https://cdn.jsdelivr.net/gh/HarmlessFunny/assets@main/dsh-background-by-model/wallpaper-kimi.webp" alt="Kimi 下的外观" width="880">
|
|
59
59
|
<br/>
|
|
60
60
|
<em>Kimi K2.7 Code · 命中匹配串含 <code>kimi</code> 的规则:深色壁纸 + 深色主题,整个界面跟着换肤</em>
|
|
61
61
|
</p>
|
|
62
62
|
|
|
63
63
|
<p align="center">
|
|
64
|
-
<img src="
|
|
64
|
+
<img src="https://cdn.jsdelivr.net/gh/HarmlessFunny/assets@main/dsh-background-by-model/rule-editor.webp" alt="单条规则的编辑器" width="660">
|
|
65
65
|
<br/>
|
|
66
|
-
<em>「模型背景」页的单条规则 ·
|
|
66
|
+
<em>「模型背景」页的单条规则 · 壁纸、透明度与模糊度属于这条规则;布局模式、取景与主题色(色轮 / HSL / RGB / 从本图提取 / 从图片取色)属于它正在编辑的那张图</em>
|
|
67
67
|
</p>
|
|
68
68
|
|
|
69
69
|
<p align="center">
|
|
@@ -76,11 +76,11 @@
|
|
|
76
76
|
|
|
77
77
|
- **有序规则列表** — 可新增、删除、拖动排序并命名规则;每条规则用自己的匹配串参与匹配,先命中者生效,规则 1 兼任兜底。
|
|
78
78
|
- **实时状态提示** — 「模型背景」页顶部会显示当前状态,例如「当前模型 deepseek-flash → 命中 · 规则 1」,方便当场验证规则写对没有;检测不到当前模型时会给出提示。
|
|
79
|
-
-
|
|
79
|
+
- **外观随规则走,逐图的三项随图走** — 壁纸(多张)、透明度与模糊度是每条规则自己的属性;**布局模式、取景和主题色则是每张图片自己的**。除「界面」页外没有任何全局外观项。
|
|
80
80
|
- **一条规则多张图** — 每条规则持有一组有序图片,用胶片条展示:可一次加多张(多选文件、拖放,或一行一个网址批量粘贴)、排序、把某张设为第一张、**原地替换某一张**(替换会保住它在轮换里的位置)、逐张删除。不轮换时规则画的就是**第一张**。删掉最后一张只是让这条规则变空,而空不等于失效:只要它还留着自己的主题色,它就照旧参与匹配与兜底、只给界面配色而不铺壁纸;连主题色也没有(比如刚新增的规则)才会被匹配跳过。空规则是一个看得见、退得回的状态,而不是卡住出不来的死胡同。一张图都没有时胶片条会隐藏、上方那块大预览**就是**上传按钮,所以添加图片的地方只有一个、也很显眼。
|
|
81
|
-
- **导入 / 导出** — 一键把**每一条规则连同它的全部图片**导出为 `dsh-background-by-model-theme.json`(版本 6,图片以 base64
|
|
81
|
+
- **导入 / 导出** — 一键把**每一条规则连同它的全部图片**导出为 `dsh-background-by-model-theme.json`(版本 6,图片以 base64 内联),可随时导入还原。更早版本导出的文件同样能导入:规则唯一的那张图会被还原成它的图片列表,在「主题色属于图片」之前写下的颜色会被抬升到每一张还没有自己颜色的图上,在布局模式下放到规则上时写下的值会被抬升到它的每一张图上,而在[切换效果](#切换效果全局)之前写下的文件会拿到这项设置的出厂默认——所以旧主题文件还原出来的观感与当初一模一样。同一个文件也可以不从本地选、而是**从项目的素材库下载**,见[推荐配置](#推荐配置)——只有一处不同:它会先把数据目录清空再写入。
|
|
82
82
|
- **文件持久化** — 所有设置与图片保存到文件系统 `~/.dsh/.dsh-background-by-model-data/`,不依赖 `localStorage`。
|
|
83
|
-
- **自动迁移** —
|
|
83
|
+
- **自动迁移** — 旧版单壁纸配置在首次读取时自动升级,曾经放在规则上的布局模式也会被抬升到它的每一张图上。详见 [CHANGELOG.zh.md 的 v0.3.0 条目](./CHANGELOG.zh.md#v030)。
|
|
84
84
|
- **中英双语** — 完整的中英文界面,自动跟随语言设置。
|
|
85
85
|
- **主题守护** — 宿主重置主题后自动重新激活自定义主题。
|
|
86
86
|
|
|
@@ -89,13 +89,13 @@
|
|
|
89
89
|
按规则开关,且**默认关闭** —— 轮换是真要花流量、内存和电的,不该由默认值替你决定。
|
|
90
90
|
|
|
91
91
|
- **按规则开启** — 开关就在规则卡片里,规则至少有两张图之后才能打开。
|
|
92
|
-
- **每张停留** — 10 秒 / 30 秒 / 1 分钟 / 5 分钟 / 30
|
|
92
|
+
- **每张停留** — 10 秒 / 30 秒 / 1 分钟 / 5 分钟 / 30 分钟,也可以自己填秒数(限制在 5 秒 – 24 小时)。
|
|
93
93
|
- **换图顺序** — 「按顺序」自上而下走完一圈再回到第一张;「随机」会在**除当前这张之外**的所有图里等概率挑一张,因为抽到同一张看起来就跟这一次没生效一模一样。
|
|
94
94
|
- **切换模型时也换一张** — 可选的第二种触发方式:每次切换模型落到这条规则上就往前走一张。对「每次都想看到不一样」的规则来说,这就是全部功能,而且不用挂任何定时器。
|
|
95
95
|
- **只有正在生效的规则会轮换** — 全插件只有一个定时器,始终对准当前模型解析出的那条规则。标签页不可见时它会停下、回来时重新计时;只有一张图的规则(以及所有[节日](#节日特殊背景))从不排期。
|
|
96
|
-
- **下一张** —
|
|
97
|
-
-
|
|
98
|
-
-
|
|
96
|
+
- **下一张** — 立刻换一张,方便当场检查这组图。它就在「轮换这组图」开关旁边(挨着「正在显示 N / M」),轮换开着还是关着都能用。
|
|
97
|
+
- **跟着规则走的是外观,跟着图片走的是布局、取景与颜色** — 透明度、模糊度留在规则上、原地不动;**布局模式、取景、主题色属于图片**,所以一组图可以一张高截图用适应、旁边那张横图用填充,也可以依次是绿的、红的、以及跟随系统主题的,界面配色跟着壁纸一起换。过渡用的就是切换模型时那套交叉淡入。
|
|
98
|
+
- **布局模式、取景、颜色都是逐图的** — 适应/填充决定的是**这一张**图怎么铺进这块区域,构图和配色也都属于某一张图:每张图各自保留自己的三项,同时共享规则的透明度与模糊度。胶片条会标出哪些图已经各自有颜色,调色区上方也会写明当前编辑的是哪一张。
|
|
99
99
|
- **只加载用得到的图** — 启动时只读每条规则的**第一张**,其余的在展开卡片时、或者在轮换即将用到它时再读。所以「五条规则各十张图」不等于首帧之前先传五十张壁纸。
|
|
100
100
|
|
|
101
101
|
### 切换效果(全局)
|
|
@@ -120,15 +120,15 @@
|
|
|
120
120
|
- **国庆节** — 公历 10 月 1–7 日。
|
|
121
121
|
- **两者重叠时中秋优先** — 它们确实会撞(2025-10-06 就是同一天),一个精确的单日比七天窗口里的某一天更值得采信。
|
|
122
122
|
- **没有图的节日会回落到模型规则**,而不是把背景刷空。
|
|
123
|
-
-
|
|
124
|
-
- **图片和配色都不可替换,这是刻意的** — 一个要求用户去配置的彩蛋就不是彩蛋了。节日槽位是只读的:往 `modelbg-h-midautumn` / `modelbg-h-nationalday`
|
|
123
|
+
- **画是下载来的,不是随包发的** — 每个节日一张压缩过的壁纸(原生分辨率下 228 KB 与 500 KB,原图共 8.37 MB),放在项目自己的 [assets 仓库](https://github.com/HarmlessFunny/assets)里,而不是打进包里 —— 它们占了整个 tarball 的三分之二,而这张画一年只被看一天。下载由**日历**把关:不在节日的配置一点流量都不会有;当天第一次读取会把它缓存到 `holiday-cache/`,此后每一次启动、往后每一年,都直接读磁盘、不再联网。引用钉死在一个 **commit** 上而不是分支,所以你以后整理仓库里的截图不可能弄坏一个已经发出去的节日;先走 `jsDelivr`、失败再走 `raw.githubusercontent.com`,两个都不通时这个节日就是不接管 —— 模型规则继续画,不会白屏。
|
|
124
|
+
- **图片和配色都不可替换,这是刻意的** — 一个要求用户去配置的彩蛋就不是彩蛋了。节日槽位是只读的:往 `modelbg-h-midautumn` / `modelbg-h-nationalday` 里放文件不会被任何一次读取采用,插件也拒绝写入、抓取和删除这两个槽位。下载落进 `holiday-cache/`,按**素材名**而不是槽位命名,所以数据目录里依然永远不会出现 `modelbg-h-*` 文件。主题色是节日定义里的常量、每次读取都强制覆盖——**节日条目和它的图片两处都覆盖**,所以手改 `theme-config.json` 里的 `color` 也换不掉节日配色。布局模式同理固定为定义里的**填充**(这些画本来就是满幅的,一个残留的 `fit` 会给它加黑边),而旁边的**取景**仍然是你自己的。导出的主题文件只包含你自己的规则。
|
|
125
125
|
- **不想要它** — 关掉「配置」页那个开关,或者在同一个文件里写 `"holidays": { "enabled": false }`。
|
|
126
126
|
|
|
127
|
-
###
|
|
127
|
+
### 规则与图片各自的设置
|
|
128
128
|
|
|
129
129
|
- **背景图片** — 一条规则可以放一张或多张图,每张图是独立文件。胶片条决定你正在编辑哪一张;不轮换时规则画的是**第一张**。规则也可以是**一张图都没有**的:这时它不再铺壁纸,但只要它有自己的主题色就照旧参与匹配与兜底(只是把界面按那个颜色配色),连主题色也没有才会被匹配跳过,直到你给它一点内容。
|
|
130
|
-
- **主题色** — HSL 色轮 +
|
|
131
|
-
- **布局模式** — 适应 / 填充 / 拉伸 / 平铺 /
|
|
130
|
+
- **主题色** — HSL 色轮 + 数值输入,外加「从本图提取」和吸管「从图片取色」。**颜色属于图片**:这些控件编辑的是胶片条里选中的那张,胶片条上会标出哪些图已经各自有颜色,而没有自己颜色的图**跟随系统主题**、不会去继承规则的颜色。**一张图都没有**的规则只剩它自己的主题色可编辑——那正是这种规则唯一能画的东西。实时生成整套 CSS 设计令牌。跟随系统主题时,界面配色交还宿主,而壁纸与「界面」页的透明度、模糊照旧生效——表面颜色是从宿主自己的令牌读出来后套上你的透明度的,所以壁纸不会被一块不透明底板盖住。
|
|
131
|
+
- **布局模式** — 适应 / 填充 / 拉伸 / 平铺 / 居中,并且**按图分别保存**:同一组轮换里可以一张适应、一张填充。规则还没有图片时这一行是**禁用**而不是隐藏(没有图可布局),这样卡片本身就说明了加上图片后会多出什么可调项。
|
|
132
132
|
- **取景** — 在视口比例的编辑器中拖动平移、滚轮缩放;**仅「适应」模式下可编辑**,提交的构图在窗口缩放、跨屏移动后保持一致。按图分别保存。
|
|
133
133
|
- **背景透明度** — `0–100%`,作用于该规则的壁纸层。
|
|
134
134
|
- **背景模糊** — `0–60 px`,作用于壁纸层。
|
|
@@ -140,6 +140,30 @@
|
|
|
140
140
|
- **对话与轨迹页** — 消息列表自动包裹为半透明卡片,轨迹页可整页调节透明度与模糊,让壁纸从内容后方透出来。
|
|
141
141
|
- **右侧栏** — 点开文件后从右侧滑出的那一栏有了自己的卡片:透明度默认跟随「主背景」(拖动后本卡片接管),模糊则在主背景模糊之上再叠加;关闭时不占位置、无副作用。
|
|
142
142
|
|
|
143
|
+
### 推荐配置
|
|
144
|
+
|
|
145
|
+
「配置」页的第一张卡会从项目自己的 [assets 仓库](https://github.com/HarmlessFunny/assets)下载作者本人正在用的那套配置 —— 规则、壁纸与接口设置 —— 一键装好。
|
|
146
|
+
|
|
147
|
+
**它托管在数据目录自己的形状里**,而不是打包成一个文档:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
preset/
|
|
151
|
+
├── preset.json 形状闸门 —— {"version": 6}
|
|
152
|
+
├── theme-config.json 规则与接口设置(6.5 KB)
|
|
153
|
+
└── modelbg-m1 … modelbg-m7 每张壁纸的原始字节
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
所以它在**所在的地方就是可编辑的**:配置是几 KB 的可读 JSON,可以直接在 GitHub 上改;换一张壁纸就是替换一个文件。发布它也因此变成从 `~/.dsh/.dsh-background-by-model-data/` 里 `cp` 一下。插件先取 manifest 与 config,从 `rules[].images[].slot` 推出文件清单 —— 没有第二处清单需要同步 —— 然后**一个文件一个请求**地取壁纸(最多四路并发),过程中按钮上显示进度。
|
|
157
|
+
|
|
158
|
+
它同时也是这个面板里**唯一会销毁东西**的操作,整个设计都在围着这一点转:
|
|
159
|
+
|
|
160
|
+
- **先下载,后询问。** 确认框出现在下载成功之后,所以它能如实说出手里到底有什么 —— *7 条规则 · 7 张壁纸 · 2.9 MB* —— 而不是让你先对「一个可能根本下不来的文件」做决定。下载失败时,什么都还没有发生。
|
|
161
|
+
- **少一张壁纸就整体失败,并且会说是哪一张。** 一份悄悄少了图的配置 —— 因为托管处的某个文件被改了名 —— 正是「节日素材钉死 commit」那条契约要防的静默失效;把文件名报出来,这个失败就仍然是响亮的,而这正是分支引用在这里可以被接受的原因。
|
|
162
|
+
- **写入之前先清空。** `nextSlot` 分配槽位用的是 `m1`、`m2`…… 一个计数器而不是随机串,所以下载来的配置和它落进去的那个数据目录**必然**在这些名字上撞车。「用它替换一切」只有在那个「一切」真的没了的时候才成立 —— 这也是它没有撤销的原因。
|
|
163
|
+
- **清空发生在下载之后,绝不会在之前。** CDN 不通不该让你在等一个永远没来的推荐配置的路上,先把自己的配置弄丢 —— 现在下载是多次传输而不是一次,这一点更重要。
|
|
164
|
+
- **不碰节日素材。** `holiday-cache/` 是下载来的、不属于任何槽位的画,不是任何人配置的一部分;重下一遍只是白白一次网络往返。而 config **确实**会列出那两个节日槽位(任何一份 config 都有),它们会被从请求清单里剔掉而不是去请求:数据目录里永远不可能存在 `modelbg-h-*` 文件。
|
|
165
|
+
- **它引用的是分支,而不是节日素材那样的 commit** —— 理由正好相反。推荐配置的失败是**响亮的**(文件下不来时你正盯着那个按钮),节日的失败却是静默的;所以钉 commit 在这里什么都买不到,反而会让「改一个 JSON 里的错别字」变成一次插件发版。真正存在的风险 —— 这份配置是写给一个本版本读不懂的配置形状的 —— 正是 `preset.json` 存在的理由:它在请求第一张壁纸之前、更在删除任何东西之前就被拒绝。
|
|
166
|
+
|
|
143
167
|
## 设置界面
|
|
144
168
|
|
|
145
169
|
设置的 **「主题」** 分类下现在有三个选项卡:
|
|
@@ -147,8 +171,8 @@
|
|
|
147
171
|
| 选项卡 | 作用范围 | 内容 |
|
|
148
172
|
| --- | --- | --- |
|
|
149
173
|
| **界面** | 全局,所有模型共用 | 主背景、左侧栏、右侧栏、卡片面板、输入框与控件、设置面板、对话文本框、轨迹页的透明度与模糊度 |
|
|
150
|
-
| **模型背景** |
|
|
151
|
-
| **配置** | — | 全局[切换效果](#切换效果全局)
|
|
174
|
+
| **模型背景** | 每条规则、每张图片 | 有序规则列表、顶部实时状态,以及每条规则的图片(胶片条)、**逐图布局模式 / 取景 / 主题色**,加上规则自己的透明度、模糊度与[多图轮换](#多图轮换) |
|
|
175
|
+
| **配置** | — | 全局[切换效果](#切换效果全局)、整套规则的进出 —— [推荐配置](#推荐配置)与导入 / 导出(`dsh-background-by-model-theme.json`)—— 外加[节日特殊背景](#节日特殊背景)那一个开关 |
|
|
152
176
|
|
|
153
177
|
原先的 **「色彩」** 选项卡已删除——主题色改为每条规则自己的属性;原 **「背景」** 选项卡已改造成 **「模型背景」**。
|
|
154
178
|
|
|
@@ -160,7 +184,7 @@
|
|
|
160
184
|
| --- | --- |
|
|
161
185
|
| `theme-config.json` | 规则列表(每条规则含图片列表与轮换设置)+ 全局「界面」设置 + 全局切换效果 + 节日覆盖配置 |
|
|
162
186
|
| `modelbg-<slot>` | 一张图片,保存为原始字节,无扩展名 —— 一张图一个文件,所以一条有三张图的规则占三个槽位 |
|
|
163
|
-
| `
|
|
187
|
+
| `holiday-cache/<asset>` | 从 CDN 下载的节日画,一个节日一个文件(`mid-autumn.webp`、`national-day.webp`)。按**素材名**命名,刻意放在槽位命名空间之外 —— 节日槽位里依然永远不会有文件,这正是它只读的原因。删掉这里的文件也没关系,下次那个节日生效时会重新下载 |
|
|
164
188
|
|
|
165
189
|
## 安装
|
|
166
190
|
|
|
@@ -212,14 +236,17 @@ pnpm run typecheck
|
|
|
212
236
|
|
|
213
237
|
改完 `src/` 必须重新执行 `pnpm run bundle` 才会生效——挂载的 profile 加载的是 `lib/`。
|
|
214
238
|
|
|
215
|
-
`pnpm test`
|
|
239
|
+
`pnpm test` 会构建、类型检查并跑九道校验(`tsdown && tsc -p tsconfig.json && node scripts/holiday-check.ts && node scripts/rotation-check.ts && node scripts/transition-check.ts && node scripts/repaint-check.ts && node scripts/code-plate-check.ts && node scripts/image-mode-check.ts && node scripts/rules-view-check.ts && node scripts/ui-strings-check.ts && node scripts/node-half-check.mjs`)。九道都不需要依赖、不需要转译器、也不需要浏览器,也可以单独跑:`pnpm check:holiday` / `pnpm check:rotation` / `pnpm check:transition` / `pnpm check:repaint` / `pnpm check:code-plate` / `pnpm check:image-mode` / `pnpm check:rules` / `pnpm check:ui` / `pnpm check:node`。
|
|
216
240
|
|
|
217
241
|
- **`check:holiday`** — 两个节日窗口对照已知日期、北京时间的跨日边界(23:59 与 00:01)、1900–2100 年间的闰八月,以及 `pickHoliday` 允许节日接管背景之前必须通过的四道闸门。
|
|
218
242
|
- **`check:rotation`** — 轮换的判定(`nextIndex` / `isRotating`):不会走越界、随机不会重复当前这张(在整个随机取值范围内穷举)、也不会把只有一张图的规则报成「正在轮换」。
|
|
219
243
|
- **`check:transition`** — 切换效果的判定(`resolveFadeMs` / `transitionPlan`),代码在 `src/client/transition.ts`,正是那些不报错、只是「看起来没生效」的部分:出厂默认仍然必须产出**与旧版本逐字符相同**的过渡串(`opacity 320ms ease`,且只动 opacity——没有变化的属性不能被写进过渡列表);`直接切换`、时长为 `0`、统一时长为 `0`、以及时长不是数字,四者都必须等于硬切;「减少动态效果」是否决而不是缩短;每个效果的起点都必须与终点不同(也就是「换了新效果却什么都没发生」);每个效果结束时都必须完全可见且**没有残留缩放**——一次没有复位的 zoom 会让之后每一张壁纸都被放大裁掉一圈。
|
|
220
244
|
- **`check:repaint`** — 「这次编辑要不要重画界面」的判定(`shouldRepaint`),其中就包含实际踩过的那个坑:**这次编辑本身**制造出了生效规则(某条规则的第一张图、第一个颜色或自动提取出的颜色)时,即使被编辑的规则此刻还不是生效规则,也必须立刻重画。它同时还会在 `src/client/index.tsx` 里任何一条写入路径不再询问这个判定时报错——也就是说,把老的 `id === activeRuleId` 判断写回去,会是构建校验失败,而不是你下一次上传时界面不动;轮换步骤不再重发调色板(主题色属于图片,换图就是换配色)同样会被它拦下。
|
|
245
|
+
- **`check:code-plate`** — 代码块底板:它读的那几个表面 token 必须在 `:root` **和** `body` 上都有声明(`var()` 是在**声明它的地方**就被替换的,只声明在 body 上的 token 被根元素消费时读到的是宿主的颜色而不是调色板的)、浅色分支也要发出 banner 而不是偷借宿主的近白色、以及两块表面各读**自己**的插件变量 —— 共用一个变量会让 banner 的写入把底板也一起画了。
|
|
246
|
+
- **`check:image-mode`** — 0.7.5 把布局模式下放到图片上的那次抬升,以及更要紧的**接线**:某个控件编辑的是哪张图、渲染层读的又是哪张图。接错了不会报错,只会让一轮轮换里的每张图长得一样。
|
|
247
|
+
- **`check:rules`** — 选项卡背后那两个纯判定(在 `src/client/rules-view.ts`:编辑器显示哪条规则、删除之后落在哪——落在邻居上,永远不是规则 1),以及布局所依赖的页面结构:只画一个编辑器、没有旧的堆叠容器、没有逐卡片的展开状态、胶片条既不换行也不长高,以及它的滚动条样式块仍然被限定在插件自己的类上。
|
|
221
248
|
- **`check:ui`** — 每个 `t('…')` 键在中英两本字典里都存在、两本字典键集完全一致、每个 `dab-…` 类在样式表里都有规则,且没有字典条目变成没人引用的死键。
|
|
222
|
-
- **`check:node`** — 把构建好的 node 半边通过它真实的 RPC 处理器跑一遍,`DSH_HOME`
|
|
249
|
+
- **`check:node`** — 把构建好的 node 半边通过它真实的 RPC 处理器跑一遍,`DSH_HOME` 指向临时目录,并把 `globalThis.fetch` 换成桩 —— 节日画现在住在 CDN 上,这套校验不能依赖某个 CDN 是活的,也不该去断言一个不属于自己的文件今天有多少字节。它覆盖:节日配置块穿过共享的 sanitizer;仅仅加载插件或读取配置不会发起任何下载;画是按需下载并缓存到 `holiday-cache/`、按**素材名**而不是槽位命名;第二次读取直接读盘、不再传输;两次并发的冷读取共用一次传输;第一个镜像不通时回落到第二个,且两个镜像钉在同一个 commit 上;所有镜像都不通时答案是「没有字节」而不是抛异常,失败的抓取什么都不缓存;镜像返回 200 但内容不是图片时被拒绝而不是被缓存;损坏的缓存条目被丢弃并重新下载;节日槽位拒绝写入 / 删除 / 抓取而丢进去的文件被忽略、且数据目录里永远不会出现 `modelbg-h-*` 文件;普通规则槽位照常写入和删除;手改过的配置无法把节日指向别的规则的图片。它还覆盖逐图主题色这套形状:读取时抬升的两个方向(缺键继承规则色、显式 `null` 不继承)、颜色经过文件往返后各自独立,以及 `null` 是写出键而不是省略。切换效果同样在覆盖范围内:旧配置拿到的出厂默认、选定的效果 / 缓动 / 统一时长能原样穿过文件往返、非法值回退而夸张时长被夹紧、时长为 `0` 被保留而不是回退成默认,以及 `transition` 内部的字段漂移会被上报而不是悄悄丢掉。推荐配置从 node 半边这一侧被整条覆盖:manifest 与 config 按序下载并当场穿过 sanitizer、请求清单由规则推导且把节日槽位剔掉、一张壁纸一个请求且类型是嗅出来的而不是信 header、jsDelivr 对单个文件死了会回落到 raw,以及它每一种失败都是返回值而不是抛异常 —— 所有镜像都不通、镜像回 500、回 200 但内容是 HTML、manifest 的版本不是数字、写给更新形状的配置在请求第一张壁纸之前就被拒绝、config 不是 JSON、config 是 JSON 数组、config 列出的图片数超限、镜像谎报一个超大的长度;再加上严格的那一半(config 点名而托管处没有的壁纸是一个错误,而不是一份短了的配置)、两次在任何请求之前就发生的拒绝(节日槽位、以及一个根本不是槽位的名字),以及清空那一步:配置和每一张规则图片都没了、`holiday-cache/` 原封不动、清空后再读拿到的是全新配置而不是报错,以及随后能往空目录里写入这份配置。
|
|
223
250
|
|
|
224
251
|
## 常见问题
|
|
225
252
|
|
|
@@ -270,23 +297,23 @@ pnpm run typecheck
|
|
|
270
297
|
|
|
271
298
|
## 近期优化
|
|
272
299
|
|
|
273
|
-
> 这里只列最近两个版本;更早的版本(v0.7.
|
|
300
|
+
> 这里只列最近两个版本;更早的版本(v0.7.4 及以前)见 [CHANGELOG.zh.md](./CHANGELOG.zh.md)。
|
|
274
301
|
|
|
275
|
-
### v0.7.
|
|
302
|
+
### v0.7.6
|
|
276
303
|
|
|
277
|
-
-
|
|
278
|
-
-
|
|
304
|
+
- **规则页从一摞会自己长大的卡片变成一条选项卡 + 一个编辑器** —— 此前每条规则是一张自展开的卡片,页面高度等于所有卡片之和,只有手动一张张收起才会变短。现在每条规则是一个选项卡、页面上只挂载一个编辑器,所以高度只跟「一张卡片 + 一条选项卡」有关,与规则条数无关。选项卡带上原本只在卡头才有的东西(序号、首图缩略图、匹配串,以及它是不是当前生效的那条、是否在轮换);条子横向滚动不换行、固定 34px、匹配串省略号截断,所以切换规则不会让整行抖动。**「+」和「切换哪条规则」挪到滚动区之外** —— 放在里面时,长列表里唯一能新增规则的控件会被滚走。匹配测试器搬到「资料」页:它回答的是关于整份配置的问题,而在规则页上它把选项卡整整推下去一张卡片的高度。背后两个判定抽成了纯函数(`src/client/rules-view.ts`),由新的 `check:rules` 钉住,同时钉住布局所依赖的页面结构。
|
|
305
|
+
- **轮换卡片的控件按你的要求重排了一遍** —— 「下一张」和「正在显示第 2 / 3 张」搬到了「轮换这组图」那一行的外侧、**常驻**:那句读数是这张卡片上唯一说明当前是哪张图的地方,此前它会跟着轮换开关一起消失。判据只剩一条 —— 当前生效的规则有两张以上图就可用(`rotateNow` 自己的判据),不足两张时按钮禁用、读数整句省略。**「切换模型时也换一张」挪到顺序那一行**(三者都在回答「什么时候换」);**「1 小时」从停留时长预设里删掉**(自定义输入照旧接受 3600 秒);**八个固定预设色板删掉**(滚轮、数值输入、从本图提取、吸管、跟随系统主题都还在,那一排只是同一个 setter 的快捷方式);**整个轮换块移到第二列、主题色之下** —— 折叠成单列的窄版里它此前是卡片最高的一块,正好夹在图片和编辑图片的颜色控件中间。
|
|
306
|
+
- **节日画不再随包发布:当天按需下载、按素材名缓存** —— 两张节日壁纸(228 KB + 500 KB)此前占了整个 tarball 的三分之二,为的是一张一年只被看一天的画,还要把二进制历史永久留在 `.git` 里。现在它们托管在项目自己的 [`HarmlessFunny/assets`](https://github.com/HarmlessFunny/assets):下载由**日历**把关,不在节日的配置一点流量都没有;当天第一次读取会把它缓存到 `holiday-cache/`,此后每次启动、往后每一年都直接读磁盘。引用**钉死在 commit 上而不是分支** —— 运行时素材必须不可变,否则以后整理一次文档截图就能让已发布的功能在某个没人盯着的那天静默失效;jsDelivr 主用、raw 兜底,两个都不通时这个节日就是不接管、模型规则继续画(那道「槽位里到底有没有字节」的闸门本来就是为这个写的)。缓存按**素材名**命名、刻意放在槽位命名空间之外,所以「节日槽位只读」「数据目录里永远没有 `modelbg-h-*`」两条不变量一个字没改;缓存条目会被**校验**,不是图片的按未命中处理并重下。`check:node` 里 `globalThis.fetch` 被整体换成桩,测试因此不依赖任何 CDN 是活的。
|
|
307
|
+
- **一键装上「推荐配置」** —— 「配置」页多了第三张卡,从同一个 assets 仓库下载作者本人正在用的那套配置并就地覆盖你的(见[推荐配置](#推荐配置))。**它托管在数据目录自己的形状里** —— 一个 `preset.json` 形状闸门、一份可读的 `theme-config.json`、加上每个槽位一个原始文件 —— 这正是它「在所在的地方就可编辑」的原因:配置是 6.5 KB 的 JSON,可以直接在 GitHub 上改;换一张壁纸就是替换一个文件;发布它就是从数据目录里 `cp` 一下。它一开始被写成单个主题文件、所有壁纸内联成 base64,2.9 MB 里 99.8% 是图片 —— 那不是任何人能手改的东西,格式就是为这个改的。插件先取 manifest 与 config,从 `rules[].images[].slot` 推出文件清单(没有第二处要同步),再一个文件一个请求地取壁纸(四路并发) —— 过程中按钮上显示 `3/7` —— 于是每个文件都有自己的镜像回退和校验。落地时走的还是本地文件那条 `applyThemeFile`,在客户端组装成 `exportTheme` 写出的形状;它是这个面板里唯一会销毁东西的操作,所以也是唯一会先问一句的,而下载发生在**提问之前**,确认框因此能如实说出手里到底有什么(7 条规则 · 7 张壁纸 · 2.9 MB)。**先清空再写入是刻意的**:`nextSlot` 分配槽位用的是 `m1`、`m2`…… 一个计数器而不是随机串,所以下载来的配置和它落进去的那个数据目录必然在这些名字上撞车,「用它替换一切」只有在那个「一切」真的没了的时候才成立 —— 这也是它没有撤销的原因。清空跑在下载**之后**、绝不在之前,因为 CDN 不通不该让你在等一个永远没来的推荐配置的路上先弄丢自己的配置;而一个旧到写不了这套配置形状的宿主,会在删除任何东西之前就被拒绝。**少一张壁纸就整体失败并报出是哪个文件** —— 一份悄悄少了图的配置,恰恰是「节日素材钉死 commit」那条契约要防的静默失效,所以这个响亮的失败正是分支引用在这里可以被接受的原因;config 合法列出的那两个节日槽位会被从请求清单里剔掉而不是去请求,因为数据目录里永远不可能有 `modelbg-h-*` 文件。`holiday-cache/` 不碰,配置也从不写进数据目录、从不落盘缓存 —— 那个按钮的全部意义就是拿到**此刻**的那一份。
|
|
308
|
+
- **发布包从 1.1 MB 瘦到约 220 kB** —— 文档截图(`example_img/`,三个 webp 共 220 KB)搬去同一个 assets 仓库、两份 README 改用 jsDelivr 绝对地址(绝对地址同样能让 npm 页面上的图不裂,还不用把二进制塞进包和 `.git` 历史);没有消费方的 `screenshots.json` 删掉;`lib/client.js.map`(624 KB 的源码映射,对装包的人没用)不再发布,仓库里仍然保留。13 个文件 → 10 个。
|
|
279
309
|
|
|
280
|
-
### v0.7.
|
|
310
|
+
### v0.7.5
|
|
281
311
|
|
|
282
|
-
-
|
|
283
|
-
-
|
|
284
|
-
-
|
|
285
|
-
-
|
|
286
|
-
-
|
|
287
|
-
- **墨色现在是同步写入的,而那是一个真实存在、且只有一个写入者的 bug(修复)** —— 把一条规则换成深色主题色时,面板的文字可能留在**上一套**调色板上,而所有表面都已经跟到新的一套:深色面板上的深色墨色,读不出来,只有重新加载才能清掉,日志里什么都不会说。这是从报告里的截图**量出来**的:面板是插件自己的深色 `bg-layer-2`(`hsl(229,59%,27%)` = `rgb(28,43,109)`,在 87% 面板透明度下合成为采样到的 `rgb(23,36,91)`),而墨色是画在它上面的**浅色**分支令牌(`rgba(0,0,0,0.85)` 压在那块藏青上恰好就是字形核心采样到的 `rgb(3,6,14)`,`rgba(0,0,0,0.7)` 恰好是提示行采样到的 `rgb(7,10,27)`)。其它每个表面都有第二个同步的写入者,所以只有令牌样式表可能变旧 —— 而它唯一的写入者只能从一个包在 `catch {}` 里的 `requestAnimationFrame` 回调到达:不在渲染的窗口会吞掉那一帧,id 却仍然武装着、把此后每一次更新都堵在它后面,写入内部出错则什么都不说。现在调色板一旦移动,就在**与它必须保持一致的表面同一个任务里**同步写入;帧路径留给它本来要做的事(合并一次滑块拖动),积压超过一秒的帧会被丢掉而不是永久阻塞,写入者也会把失败记进日志而不是吞掉。
|
|
288
|
-
- **配置格式升到 5、导出格式升到 6** —— schema 4 的 sanitizer 会**按自己认识的键重建**配置,所以一个旧宿主进程会在刷新后的第一次写入时丢掉效果、缓动与时长,悄无声息,宿主日志里也什么都没有。公布的 `schema` 随之前进,「扣住写入」分支会拦住这样的宿主,`warnUnknownConfigKeys` 也出于同样的理由往深一层比较固定形状的 `transition` 块。
|
|
289
|
-
- **门禁** —— `check:transition` 加入 `pnpm test`,现在是**六道**;`check:repaint` 钉住这个墨色 bug 由之构成的三行(调色板变化时同步写入、不许吞掉失败、在令牌与内联两个调用点都把渐变问题的两半问全);`check:node` 覆盖出厂默认值、往返、恶意取值、被保留的 `0` 时长、漂移检查与旧值折算;`check:ui` 覆盖新文案与新类,并把胶囊标签登记进 `TABLE_KEYS`。
|
|
312
|
+
- **布局模式属于图片,不属于规则** —— 适应 / 填充 / 拉伸 / 平铺 / 居中 此前是每条规则一个值,于是一轮里既有横构图照片又有竖屏截图时,没法让一张留黑边、另一张铺满。现在它存在 `images[].bgMode` 上、从**正在画的那张图**读回,胶片条下面那排胶囊编辑的也是那里选中的图(规则还没有图片时是**禁用**而不是隐藏)。`SCHEMA_VERSION` 因此升到 **6**,因为两个方向都是无声的:schema 5 的宿主会在第一次写入时丢掉逐图模式(设成 拉伸 的图变回 适应),而 schema 6 读老配置时会把规则级的值抬到每一张图上,现成壁纸不会掉到默认值。节日的图按**定义**就是 填充(和它旁边的槽位、颜色同一条规矩),旁边的取景仍然是你自己的。
|
|
313
|
+
- **渐变只作用于当前调色板真正写入的东西(修复)** —— 「有时候切换背景时,白色色块会渐变为黑色色块…白色渐变完黑色后立马切到白色」,白色值量到 `237, 243, 254`。那就是 `#edf3fe` = `--dsw-static-deepseek-50`,也就是宿主浅色方案的 `--dsw-specific-bubble`(你自己的消息气泡;深色方案是 `#2c2c2e`)。渐变之所以注册了这个名字,是因为它要的是**深色**分支的 token 表、又把整张表交给了 `:root`/`body` —— 浅色分支只写这 80 个名字里的 35 个,剩下 45 个(气泡、设置里的下拉框底色、提示与气泡框、代码块右上角小按钮、状态色)仍然归**宿主**;而让宿主短暂换方案的正是插件自己:每次换配色都销毁并重新注册主题,宿主的销毁器把偏好重置为 `system`,在深色桌面上那一瞬间画的就是宿主的深色调色板。配上报告里 3000ms 的切换时长,一帧的错色就成了三秒的渐变。现在只有当前调色板真正写入的 token 才会拿到过渡(注册表仍是全部 80 个,深色调色板完全没变),配色方案没变也不再重建皮肤。实测:`body` 的过渡列表 80 → 35 个名字,气泡与下拉框出局,`--dsw-alias-bg-base` / `-layer-2` / 代码块底板仍在。
|
|
314
|
+
- **代码块跟着调色板走,底板有了自己的透明度(修复)** —— 「代码块背景有点问题」:浅色界面里深绿文字压在近黑底板上。宿主的 shiki 表在 `:root` 上声明 `--shiki-background: var(--dsw-alias-markdown-code-block)`,而该 token 只声明在 `body` 上,于是根元素只能读到过渡注册的 `initial-value` —— 采样一次的宿主颜色。现在调色板规则对 `:root` 一并发出(`:root` 也加入渐变作用域),底板与 banner 重新是调色板的染色,并新增 **`code`** 档位驱动这两块表面、各读自己的变量,默认不透明。
|
|
315
|
+
- **四个小修** —— 删图删到不足两张时轮换开关不再卡在「开」(面板在那里本来就把它禁用了,于是也关不掉;`normalizeRule` 对导入的配置强制同一条不变量);「切换时长」只印一次;资料页页脚的包名与品牌磁贴现在是指向仓库的链接,`check:ui` 拿那一个地址和 `package.json` 对比。
|
|
316
|
+
- **门禁** —— `pnpm test` 现在是**八道**:`check:code-plate` 与 `check:image-mode` 加入,`check:rotation` 增加开关不变量,`check:ui` 增加链接一致性,`check:transition` 增加渐变归属规则,`check:repaint` 钉住武装渐变的那两行。
|
|
290
317
|
|
|
291
318
|
## Star History
|
|
292
319
|
|