iter(g66): verify 反向校验入参接口字段均已登记文档

This commit is contained in:
HIsheR
2026-10-26 12:34:23 +08:00
parent 31442958ce
commit 805b54d035
5 changed files with 54 additions and 4 deletions
+36 -1
View File
@@ -883,6 +883,40 @@ function checkPropsImpl(pkg, comps) {
return issues;
}
/*** 反向漂移校验:入参接口的每个字段都必须在文档 props 表登记(新加字段忘了写文档会命中) ***/
function checkPropsDoc(pkg, comps) {
const issues = [];
const typesPath = path.join(ROOT, pkg.dir, 'src', 'types.ts'); // 约定:类型集中在 src/types.ts
if (!fs.existsSync(typesPath)) return issues;
const src = fs.readFileSync(typesPath, 'utf8');
const ifaces = new Map(); // 接口基名(已去掉 Props 后缀)→ 字段名数组
for (const m of src.matchAll(/export interface (\w+)Props(?:<[^>]*>)?\s*\{([\s\S]*?)\n\}/g)) {
const fields = [];
for (const line of m[2].split(/\r?\n/)) {
const hit = /^\s{2}(\w+)(\?|:)/.exec(line); // 缩进两格的字段声明
if (hit) fields.push(hit[1]);
}
ifaces.set(m[1], fields);
}
if (!ifaces.size) return issues;
const pascal = (id) => id[0].toUpperCase() + id.slice(1);
for (const c of comps) {
if (!c.id || c.propsType === false) continue; // propsType: false 表示该组件没有入参接口
const tag = `${pkg.name}#${c.id}`;
const base = String(c.propsType ?? '').replace(/Props$/, '') || pascal(c.id); // 清单可覆盖接口名
const fields = ifaces.get(base);
if (!fields) {
issues.push(`${tag}: 找不到入参接口 ${base}Props(命名不同请在清单用 propsType 指定,无入参写 false)`);
continue;
}
const documented = new Set((c.props ?? []).map((p) => String(p.n ?? '').replace(/^([^)]*)/, '').replace(/^\.\.\./, '').trim())); // 去掉前缀注记与展开符
for (const f of fields) {
if (!documented.has(f)) issues.push(`${tag}: 入参接口 ${base}Props 的字段「${f}」未在文档 props 表登记`);
}
}
return issues;
}
/*** 清单一致性校验:组件文档块的 id / props 说明 / demo 锚点必须与代码和演示产物对齐 ***/
function cmdVerify() {
const issues = [];
@@ -901,6 +935,7 @@ function cmdVerify() {
issues.push(...checkSkinCss(pkg));
issues.push(...checkTokenRefs(pkg, tokenVars));
issues.push(...checkPropsImpl(pkg, comps));
issues.push(...checkPropsDoc(pkg, comps));
}
if (comps.length && !exports.length) issues.push(`${pkg.name}: docs.components 有 ${comps.length} 项但 api.exports 为空`);
@@ -940,7 +975,7 @@ function cmdVerify() {
console.error(`${issues.length} violation(s)`);
process.exit(1);
}
console.log('verify OK (manifest ↔ docs ↔ demo 一致,文档 props 均能落到实现,皮肤无硬编码颜色与未定义令牌,README 组件清单与分组同步,backlog ↔ 留痕一致)');
console.log('verify OK (manifest ↔ docs ↔ demo 一致,文档 props ↔ 入参接口双向一致,皮肤无硬编码颜色与未定义令牌,README 组件清单与分组同步,backlog ↔ 留痕一致)');
}
/*** 校验 git 提交信息是否符合 COMMITTING.md 规范(参数为 message 文件路径或直接 message 文本),违规退出码 1 ***/