## 改法
- **`Sidebar.tsx` 底部两个按钮还是旧的深色导航假设**(`text-chrome-400
hover:text-white hover:bg-chrome-800`、外层 `border-chrome-700`):导航改成白玻璃
(`--nav-bg: 255 255 255 / 0.72`)之后,`chrome-400` 落在白底上约 2.6:1(图标要
3:1),hover 还会在白导航上闪出一块近黑。账号头像那个按钮当时换成了 `.nav-item`,
这两个漏了 —— 就是"导航令牌迁移做了一半"。已换成 `.nav-item` + `border-gray-200`。
没加"Sidebar 里不许有 chrome-*"的判据:另有一处 `bg-chrome-600 text-chrome-100`
是实心小色块(正常用法),一刀切会误红。
- **`background-takeover.generated.css` 的头注释提前闭合**:生成器在注释里写了
「src」加「/」加两颗星加「/」加「.tsx」,其中那对「星号 + 斜杠」把 CSS 注释就地
结束 —— 尾巴变成 CSS 正文,并与第一条规则的选择器连在一起成为非法选择器 ⇒
**`.bg-amber-100` 那条接管规则被浏览器整条丢掉**(壁纸模式下不再变半透明)。
构建只给一条 `[WARNING] Unexpected "14" [css-syntax-error]`,不报错、不影响构建,
正是这套判据存在的理由。改在生成器(注释里只描述、不写 glob 字面量)并重新生成:
压缩输出现在以 `html[data-bg=on] .bg-amber-100{` 起头、14 条规则全在、无告警。
另加两条判据("头注释没提前闭合" + 自检)。
- **`background.test.mjs` 第 18 组三条重写**:原先断言「浅色/深色两套 `--nav-bg` 都
定义」与「壁纸模式下 `.nav-rail` 里有 `backdrop-filter`」,两条编码的都是**已被
有意撤掉的设计**(`faacd3c` 撤深色导航、`9aa702b` 撤导航自叠模糊),于是 `npm test`
在 HEAD 上恒红。判据红成常态就不再是判据 —— 该改的是判据本身,而不是把缺陷写回代码。
改成方向相反的两条:`.dark` 不许单独给导航换色 / 模糊只由壁纸层负责。
- **`cross-client-theme.test.mjs` 从来不在 `npm test` 链里**(vitest 只收
`test/components` 与 `test/stores`)—— 那条"防漂移判据"从没在默认套件里跑过。
已加进 `npm test`。
## 验证
- 变异测试:往 `.dark { }` 塞一行 `--nav-bg: 15 23 42 / 0.72;` → 红;往
`html[data-bg='on'] .nav-rail` 塞 `backdrop-filter: blur(18px);` → 红;撤回 → 绿。
- `npm test` 退出码 0:窄屏布局全通过、主题 30、背景 34、cross-client 8、packaging 3、
vitest 258/258;`npm run typecheck` 通过。
- packaging 第 3 条此前是红的,但**不是判据过期**:安装包真的落后于 dist,而 `npm test`
的 `&&` 链一直在 background 那条就中断,`packaging` 从没跑到过。已 `npm run build`
+ `npx electron-builder --linux -c.electronDownload.isVerifyChecksum=false` 重打包。
⚠️ deb 目标在本机打不出来(fpm 的 portable ruby 在 `Dir.chdir` 处退出),
AppImage 与 `linux-unpacked` 正常。
84 lines
3.8 KiB
JavaScript
84 lines
3.8 KiB
JavaScript
/**
|
||
* 生成"背景开启时哪些浅色表面类要变半透明"的 CSS。
|
||
*
|
||
* # 为什么要生成而不是手写
|
||
*
|
||
* 手写清单必然烂:2026-09-13 用户报「很多界面是不透明的,导致壁纸露不出来」,
|
||
* 一查代码里在用的浅色表面类有 gray-100(24 处)、blue-50(17)、red-50(13)、
|
||
* gray-200(8)、green-50(8)… 而当时的接管清单只有 white / gray-50 / slate-100 ——
|
||
* 漏掉的那些全是实心的,正好盖住壁纸。
|
||
*
|
||
* 所以清单从**源码里实际出现的类**推导:出现什么就接管什么。新增一个
|
||
* `bg-purple-50` 而忘了同步,`test/background.test.mjs` 里那条判据会红。
|
||
*
|
||
* 只接管"表面段"(50/100/200):它们是面板底、提示条、卡片这类大面积浅色。
|
||
* 600/700 那一段是按钮与徽标(小控件、要读得清),**故意保持不透明** —— 见
|
||
* index.css 里 chrome-600/700 那段注释(实测可读性从 4.46:1 掉到 AA 以下)。
|
||
*/
|
||
import { readdir, readFile, writeFile } from 'node:fs/promises';
|
||
import { join, dirname } from 'node:path';
|
||
import { fileURLToPath } from 'node:url';
|
||
|
||
const HERE = dirname(fileURLToPath(import.meta.url));
|
||
const SRC = join(HERE, '..', 'src');
|
||
const OUT = join(SRC, 'background-takeover.generated.css');
|
||
|
||
/** 表面段:浅色大类 + 50/100/200 三档。 */
|
||
const SURFACE = /^bg-([a-z]+)-(50|100|200)$/;
|
||
|
||
/**
|
||
* 页面底:**必须完全透明**(背景开启时),不能进这份"半透明"清单。
|
||
*
|
||
* 它们铺满整屏,给它们 0.3 的不透明度等于在壁纸上盖一层白纱;而 index.css 里
|
||
* 已经把它们设成 transparent —— 谁后加载谁生效,生成物在 index.css 之后引入,
|
||
* 所以漏了这条排除就会把"完全透明"悄悄改回"半透明"。
|
||
*/
|
||
const PAGE_BASE = new Set(['bg-gray-50', 'bg-slate-100']);
|
||
|
||
async function walk(dir) {
|
||
const out = [];
|
||
for (const e of await readdir(dir, { withFileTypes: true })) {
|
||
const p = join(dir, e.name);
|
||
if (e.isDirectory()) out.push(...(await walk(p)));
|
||
else if (/\.(tsx?|jsx?)$/.test(e.name)) out.push(p);
|
||
}
|
||
return out;
|
||
}
|
||
|
||
const found = new Set();
|
||
for (const file of await walk(SRC)) {
|
||
const text = await readFile(file, 'utf8');
|
||
for (const m of text.matchAll(/bg-[a-z]+-\d{2,3}/g)) {
|
||
if (SURFACE.test(m[0]) && !PAGE_BASE.has(m[0])) found.add(m[0]);
|
||
}
|
||
}
|
||
|
||
const classes = [...found].sort();
|
||
const body = classes
|
||
.map(
|
||
(cls) =>
|
||
`html[data-bg='on'] .${cls} {\n` +
|
||
` background-color: rgb(var(--c-${cls.slice(3)}) / var(--bg-glass-inner));\n` +
|
||
` backdrop-filter: none; /* 外层已经模糊过,嵌套层再糊一次会把图案糊成灰块 */\n` +
|
||
` -webkit-backdrop-filter: none;\n}`,
|
||
)
|
||
.join('\n\n');
|
||
|
||
await writeFile(
|
||
OUT,
|
||
/*
|
||
* ★ 头注释里**不许写出「星号紧接斜杠」的 glob 字面量**(2026-09-14 修)。
|
||
*
|
||
* 这里原先写的是「src」加「/」加两颗星加「/」加「.tsx」,而中间那对
|
||
* 「星号 + 斜杠」会把 CSS 注释**提前闭合**:剩下的尾巴(`.tsx 的实际用法)。`)
|
||
* 变成 CSS 正文,跟后面第一条规则的**选择器连在一起** —— 非法选择器 ⇒
|
||
* **那条规则被浏览器整条丢掉**(`.bg-amber-100` 在壁纸模式下不再变半透明),
|
||
* 而构建只在日志里给一条 `[WARNING] Unexpected "14"`,不报错、不影响构建。
|
||
* 所以这里只描述、不写 glob 字面量。
|
||
*/
|
||
`/* 由 scripts/gen-background-takeover.mjs 生成 —— 不要手改。\n` +
|
||
` * 背景开启时把源码里在用的浅色表面类改成半透明(清单来自 src 目录下全部 .tsx 的实际用法)。\n` +
|
||
` * 共 ${classes.length} 个类:${classes.join(', ')}\n */\n\n${body}\n`,
|
||
);
|
||
console.log(` 生成 ${classes.length} 个类 → ${OUT}`);
|