Archived
fix(w05): 三份件的机械抽样式补齐缺失 class —— 落账件同款会炸,提前拦下
浏览器走查实测:差异评估结论审核件里三个 <svg class="zic"> 撑成 946×946,
整份文档拉到 4625px 高,正文全被挤走 —— 人打开只见灰色巨块,没法逐条核四态。
根因:.zic{width:14px;height:14px} 只在 P08_CSS(数据工单那一段),而
difference-review 用的是 ACC1_CSS。ACC1_CSS / ACC2_CSS 是从目标件机械抽出来的,
report.ts:538 那句既有注释早已承认漏过一批(.jc-vcell/.jc-cell/…),补了几个,
这几个漏了。
按「一次查干净」逐个核三份件用到的每个 class,补齐:
· .zic —— ACC1_CSS **与 ACC2_CSS**(后者即 landing-confirm,同款会炸,走查下一步就会撞上)
· .note .done / .note .need —— ACC1_CSS 与 ACC2_CSS
· .kv-box —— BIND_LANDING
· .risk-badge 缺基座形状(只有配色没有胶囊盒子)—— 人工核对徽标家族一致性时发现,机械扫描漏网
新增自测:三份件用到的 class 必须都能在它自己那段 CSS 里找到定义 ——
将来谁再加一个没定义的 class 就变红。变异验证:删掉 .zic 那条真红,补回真绿。
另:嵌套 data-by 的「只读态显示了并不存在的值」已坐实为渲染器侧机制
(递归合并时行内没有该字段会落回外层同名字段),加 it.fails 钉住,平台修法另议。
包版本 2.1.7。pnpm gates 退出码 0(164 文件 / 2450 测)。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -40,6 +40,41 @@ const viewHtml = (name: string) => manifest.assets.viewTemplates.find((t) => t.n
|
||||
const ledgerOf = (address: string) => manifest.declarations.ledger.find((l) => `${l.domain}.${l.object}` === address);
|
||||
const colOf = (address: string, name: string) => ledgerOf(address)?.fields.find((f) => f.name === name);
|
||||
|
||||
/**
|
||||
* 从一段 CSS 文本里摘出**选择器里提到过的所有 class token**(2026-08-30 task-12,缺陷③用)。
|
||||
* 只扫选择器,不扫规则体(`content:"…"` 这类属性值里的文字不算);`@media`/`@supports`
|
||||
* 这类带嵌套一层规则体的 at-rule 会往里再走一遍(本仓三份件的 `@media(max-width:600px)` 与
|
||||
* `@media (prefers-reduced-motion: reduce)` 都嵌着真正的选择器,不能漏)。
|
||||
* 这是**存在性**扫描(选择器里出没出现过这个 class),不判断它是不是复合选择器的一部分 ——
|
||||
* `.zic` 完全不存在是这份扫描要抓的那种漏(缺陷③的两个真实事故都是这一种:某个 class
|
||||
* 在目标件自己的 `<style>` 里一次都没被提到)。
|
||||
*/
|
||||
function definedClassesOf(css: string): Set<string> {
|
||||
const defined = new Set<string>();
|
||||
const noComments = css.replace(/\/\*[\s\S]*?\*\//g, '');
|
||||
const walk = (text: string): void => {
|
||||
let i = 0;
|
||||
while (i < text.length) {
|
||||
const openIdx = text.indexOf('{', i);
|
||||
if (openIdx === -1) break;
|
||||
const selector = text.slice(i, openIdx);
|
||||
for (const m of selector.matchAll(/\.([a-zA-Z0-9_-]+)/g)) defined.add(m[1] ?? '');
|
||||
let depth = 1;
|
||||
let j = openIdx + 1;
|
||||
while (j < text.length && depth > 0) {
|
||||
if (text[j] === '{') depth += 1;
|
||||
else if (text[j] === '}') depth -= 1;
|
||||
j += 1;
|
||||
}
|
||||
const body = text.slice(openIdx + 1, j - 1);
|
||||
if (/^\s*@media/.test(selector) || /^\s*@supports/.test(selector)) walk(body);
|
||||
i = j;
|
||||
}
|
||||
};
|
||||
walk(noComments);
|
||||
return defined;
|
||||
}
|
||||
|
||||
describe('清单本身合规', () => {
|
||||
it('过 @contracts 的 schema', () => {
|
||||
expect(() => activityManifestSchema.parse(manifest)).not.toThrow();
|
||||
@@ -445,6 +480,36 @@ describe('报告模版:编辑面与只读面各就各位', () => {
|
||||
expect(html, view).not.toContain('proto-root');
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 缺陷③(2026-08-30 task-12,浏览器真人走查逮到,阻塞人):差异评估结论审核件里三个
|
||||
* `<svg class="zic">` 因为 `ACC1_CSS` 里没有 `.zic` 而撑到 946×946 像素、把整份文档
|
||||
* 顶到 4625px 高,正文全被挤出可视区,人打开只看见三块灰色巨块加大片空白。
|
||||
* 根因是 `ACC1_CSS`/`ACC2_CSS`(target-style.ts)虽然叫「机械抽自目标件」,但
|
||||
* report.ts 的 `zone()`/`note()` 助手把 P08 目标件「视觉补充段 v3」的图标与强调色
|
||||
* 跨文档复用到了这两张验收件上,原验收工单目标件自己的 `<style>` 从没定义过它们 ——
|
||||
* 同一批复查还揪出 `.note .done`/`.note .need`(两张验收件的提示文案同样失色)与
|
||||
* `.kv-box`(落账确认件的「待验项」盒子没有边框底色)。
|
||||
* 这条测试把「三份件各自用到的 class,都能在它自己那段 `<style>` 里找到定义」钉成机检 ——
|
||||
* 拿掉本轮任何一条修复,这里就会变红(变异验证见 task-12 报告)。
|
||||
*/
|
||||
it('三份件各自用到的 class,都能在它自己那段 <style> 里找到定义(不许再有 .zic 946×946 那种漏)', () => {
|
||||
for (const view of VIEWS) {
|
||||
const html = viewHtml(view);
|
||||
const styleMatch = /<style>([\s\S]*?)<\/style>/.exec(html);
|
||||
expect(styleMatch, view).not.toBeNull();
|
||||
const css = styleMatch?.[1] ?? '';
|
||||
const body = html.slice((styleMatch?.[0] ?? '').length);
|
||||
const used = new Set<string>();
|
||||
for (const m of body.matchAll(/\sclass="([^"]*)"/g)) {
|
||||
for (const c of (m[1] ?? '').split(/\s+/)) if (c !== '') used.add(c);
|
||||
}
|
||||
const defined = definedClassesOf(css);
|
||||
for (const cls of used) {
|
||||
expect(defined.has(cls), `${view}: class="${cls}" 用到了,但它自己的 <style> 里没有任何选择器提到 .${cls}`).toBe(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user