豆备 DOUBAK
← 开发日志

一个复选框,三处静默

它本该默认藏着,却从第一天起就露在外面;而即使藏住了,藏的判据也是错的;而它有时什么都不做,标签却说自己在做事。

导出卡片上有个小复选框,「将豆瓣上无法检测私密状态的日记导出成公开状态」。 它的设计是默认藏着,只有真碰上才露面。 写完,测试绿了,发了两个版本。

然后项目主人在 issue 上贴了一张截图,问我另一件事——而那张截图里, 那个框好端端地露在外面。

它从第一天起就没藏住过。一个小复选框,三处静默,每一处都是这个项目已经取过名字的类别。

一、它从来没藏住过

HTML 是对的:

<label class="opt" id="export-neodb-unknown-row" hidden>

CSS 也没写错任何一条:

.opt { display: flex; align-items: flex-start; gap: var(--s1); }

问题在两者之间。浏览器自带的 [hidden] { display: none } 特指度是 0,1,0——跟一条 .opt 一模一样。 同分的时候,作者样式表赢。于是那个 hidden 属性被一条 display: flex 静静盖掉了。

这一路上没有任何东西会响el.hidden = false 照常执行, 「HTML 里有 hidden」的断言照常通过,元素照常看得见。

而测试断言的是「HTML 里写了 hidden」,要守的性质是 「用户看不见它」。两者只在「没人给那个类写 display」的时候等价—— 又一条代理断言,这个文件里已经记到第六条了。

更值得记的是,样式表里本来就有一条 section[hidden] { display: none; }这个坑当年为标签页踩过一次,当时只按住了一种元素。 现在改成兜住全部,!important 在这里是对的:这不是版式偏好, 是「藏起来」的定义。

二、它本来就不该藏

修好隐藏之后,项目主人给了一个更狠的理由——那个露面条件本身就是错的

原来的判据是「上一次导出发现了这种日记就露面」。可 unsure(读不出公私状态)是抽取器在解析那一刻的判断, 不是档案的属性

档案抽取器结果
v1.1 抓的,v1.1 解析冻住不变unsure
同一批档案,扩展升级后解析一模一样不再 unsure
豆瓣改版后新抓的页没跟上变成 unsure

所以那个条件描述的是「档案 × 抽取器版本」这个组合,而不是用户的数据。 升级一次抽取器,控件就会在用户可能正需要它的时候消失。

常驻反而是诚实的。顺带它也终于跟上面那组单选并进了同一个 fieldset—— 原来放在组外,它的上外边距和整组的下外边距折叠成一个更大的值,看起来离老远,像是另一件事。

三、它有时什么都不做,却不吭声

改完之后项目主人又问了一句:「私密 + 勾上『读不出来的也公开』」呢?

跑一遍:

面板上的选择        你公开的  豆瓣锁的  读不出的  你设私密的
公开                公开      公开      私密      私密
公开 + 勾           公开      公开      公开      私密
私密                私密      私密      私密      私密
私密 + 勾           私密      私密      私密      私密   ← 那个勾毫无作用

行为是对的。 判据链是「每一级只收紧、不放松」—— 读不出公私状态的日记,绝不该比读得出来的日记还公开。

错的是它不吭声。那个勾的标签写着「导出成公开状态」, 而它此刻什么也不做,还没有任何提示。这正是这个项目栽过三次的形状: 封面回退那次、remote 数封面那次、「有 5 张图没取到」那次—— 消息说的后果和实际发生的事对不上

修法是让「不起作用」看得见:选「私密」时禁用它,整行连文字一起变淡。 只禁不清——勾选状态留着,拨回「公开」就还在; 替他把勾清掉是又一次替他拿主意,而他并没有改变那个意愿。

三次都问了同一个错问题

判据比要守的性质宽,就是漏。 而三次都漏在同一个控件上,是因为三次问的都是「代码里写了吗」, 没有一次问「用户看到的是什么」。

  • 「HTML 里有 hidden 吗」——有。用户看得见它。
  • 「露面逻辑写对了吗」——写对了。它描述的东西不属于用户的档案。
  • 「勾上会传 0 吗」——会。传了也不影响任何东西。

每一条都能在源码里查证,每一条都查证通过,每一条都没碰到真正要守的那件事。 这三处最后是被一张截图破的——一张为了别的事顺手贴上来的截图。

这个项目已经写过一次:「一个不可能失败的检查证明不了什么。」 今天补上它的近亲——一个查得动的检查,也可能一直在查一件不要紧的事。

更早:他花了一个小时锁日记 →