// 契约:自定义组件的 WXSS 不得使用标签 / ID / 属性选择器 // // 由来(2026-09-19)开发者工具警告: // [pages/index/index] Some selectors are not allowed in component wxss, // including tag name selectors, ID selectors, and attribute selectors. // (./components/recommend-card/index.wxss:1:1092) // 实测违规 1 处:`.compact-like image`。 // // ⚠️ 作用域刻意限定 `miniapp/components/`:**page 的 wxss 允许标签选择器**, // 把本规则套到 pages 上会立刻产生误报 —— 守卫一旦有假阳性就会被绕过。 // // 自检:内置正向样例(合法类选择器 + 伪类 + `>` 子选择器)与反向样例 // (标签 / ID / 属性各一),确保判据既不全哑、也不误伤。 import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import { relative, resolve } from 'node:path' import { checkWxss, walkWxss } from '../scripts/lib/wxss-selectors.mjs' const root = resolve(import.meta.dirname, '..') // WXSS_SCAN_ROOT 仅用于负向注入自证(指向临时目录),默认 miniapp/components const scanRoot = resolve(root, process.env.WXSS_SCAN_ROOT ?? 'miniapp/components') // ── 1. 判据自检 ────────────────────────────────────────────────── const selfCheckCases = [ { name: '正向:纯类选择器 / 伪类 / 子选择器 均合法', src: [ '.a { color: red }', '.a .b { color: red }', '.a > .b { color: red }', '.a:active, .b::after { color: red }', '.a:nth-child(2) { color: red }', '@media (min-width: 600px) { .a { color: red } }', '/* .commented-out image { color: red } */', ].join('\n'), expect: 0, }, { name: '反向:标签选择器', src: '.a image { width: 1px }', expect: 1 }, { name: '反向:ID 选择器', src: '#main { width: 1px }', expect: 1 }, { name: '反向:属性选择器', src: '.a[data-x="1"] { width: 1px }', expect: 1 }, ] for (const c of selfCheckCases) { const got = checkWxss(c.src) assert.equal( got.length, c.expect, `判据自检失败 —— ${c.name}\n期望 ${c.expect} 条,实得 ${got.length} 条:\n${got.map((x) => x.message).join('\n')}`, ) } // ── 2. 全量扫描组件 WXSS ──────────────────────────────────────── const files = walkWxss(scanRoot) assert.ok(files.length > 0, `未在 ${scanRoot} 下找到任何 .wxss —— 扫描清单可能失配,拒绝报绿`) const broken = [] for (const file of files) { for (const p of checkWxss(readFileSync(file, 'utf8'))) { broken.push(`${relative(root, file).replace(/\\/g, '/')}:${p.line} ${p.message}`) } } assert.deepEqual( broken, [], `以下组件 WXSS 使用了不允许的选择器(开发者工具会警告,样式不生效):\n${broken.join('\n')}`, ) console.log(`WXSS component selector contracts passed(${files.length} 个组件样式文件)`)