--- name: html-lint-false-positive-zero-visual-fix description: 当「行级」HTML/设计检测器(如 impeccable 的 detect.mjs)对生成的静态 HTML 产物批量报「压行假红」时,如何做到**零视觉变化**地收敛——不改元素、不改配色、不改字体,只按元素/令牌拆源码行。当用户说「这些告警逐条判真红假红」「消掉检测器的假红」「检测器告警太多,别改样式」时使用。核心手法:把换行插在**解析器会吃掉的位置**(标签收尾 `>` 之前)或 **class 值内部令牌之间**。 agent_created: true --- # 行级检测器的「压行假红」零视觉变化收敛 > 治「设计检测器一次报几十上百条告警,但逐条看下来大半是它自己判歪了;用户又明确说『样式保持现在的』,不许借机改字体改配色」。 > **前置**:先确认告警到底是**真红**还是**假红**(§1),⛔ 不要一上来就改东西。 --- ## 0. 铁律 1. **先读检测器源码,再判真假。** 告警的判定逻辑写在规则里(正则 + 行级/文件级 test)。不读源码就判真假,等于猜。 2. **假红只能「消音」,真红只能「改设计」。** 两者混在一起做,会把「改样式」偷偷夹带进「消告警」批次。 3. **本技能只处理「可零视觉变化收敛」的假红。** 真要改视觉(换配色/字体/渐变)=设计决策,**必须单独问用户**,⛔ 不并入本批。 4. **⛔ 不要「重跑生成器」来修。** 产物往往已被后续手工改动领先于生成器;重跑会回退。**一律就地改产物。** 5. **每条改动都要有「渲染零变化」的**证据**,不是"我觉得没事"。** 见 §4。 --- ## 1. 判真假:行级规则长什么样 典型「行级」规则(impeccable `detector/engines/regex/detect-text.mjs`): ```js { id: 'gray-on-color', regex: /\btext-(?:gray|slate|zinc|neutral|stone)-(\d+)\b/g, test: (m, line) => /\bbg-(?:red|orange|...|rose)-\d+\b/.test(line), // ← 按【行】判 fmt: (m, line) => `${m[0]} on ${line.match(/\bbg-.../)[0]}` } ``` ⇒ **只要同一源码行里同时出现两类令牌就报**,不管它们是不是同一个元素、也不管 `bg-*` 是不是 `hover:` 变体。 **由此产生的两类假红**: | 类型 | 成因 | 判定依据 | |---|---|---| | **压行假红** | 一行里塞了多个元素(生成的 HTML 常把整段 `
` 压一行,或按钮组压一行):`bg-red-500` 的元素和 `text-neutral-700` 的元素**相邻但不同元素** | 灰字元素自己的底是 `bg-white`/无色 | | **变体假红** | 同一元素,但被报的 `bg-*` 出自 `hover:bg-*`/`focus:bg-*`,静止态是 `bg-white`,且悬停时文字也换色(`hover:text-rose-600`) | 静止态与悬停态**两态都不是**规则描述的病态 | 判据脚本骨架:把告警行的行号取出 → 取该源码行 → 用正则切标签 → 看「灰令牌」和「彩色 bg 令牌」是否落在**同一个 tag** 里、且那个 bg 是否带 `hover:` 之类的变体前缀。 --- ## 2. 两种零视觉变化的拆行手法(本技能的**核心**) 目标:让两类令牌落到**不同的源码行**,但**不动渲染**。关键是「换行必须插在解析器/序列化器会丢掉的位置」。 | 手法 | 插在哪 | 为什么零变化 | 保证 | |---|---|---|---| | **A. 标签收尾前** | 标签的 `>` 之前(自闭合则 `/>` 之前) | HTML 解析器会吃掉标签名/属性与 `>` 之间的空白;序列化时又统一输出 `>` | **DOM 逐字节不变** ⇒ `outerHTML` **原样**指纹不变 | | **B. class 值内部** | `class="…"` 里**两个 class 令牌之间** | `class` 是**空白分隔的令牌表**,换行 ≡ 空格(CSS 匹配、`classList` 取值都按令牌集合) | `classList`/计算样式/几何全不变;只有该属性**字面量**里多一个换行 | **什么时候用哪个**: - 跨元素(压行假红)→ 手法 A 就够(每个带令牌的标签前都插一个)。 - 同一元素内(变体假红)→ 必须用手法 B:按令牌顺序扫,遇到「当前段已含一类、下一个令牌是另一类」就在该令牌前断行(贪心分段,保证每段不含两类)。 **切分点够不够**:给「行内每个带令牌的标签」都在其 `>` 前断一次 ⇒ 每个源码行最多只含**一个**带令牌标签的 class,于是跨元素假红必然消失。 ⛔ **安全边界**:必须**全文件扫描**标签,跳过 `` 与 `