From e6bf801679ab9a6796d712520494444cd7e9daf5 Mon Sep 17 00:00:00 2001 From: HIsheR Date: Mon, 26 Oct 2026 12:20:33 +0800 Subject: [PATCH] =?UTF-8?q?iter(g56):=20ua=20style=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8D=95=E6=96=87=E4=BB=B6=20200=20=E8=A1=8C=E9=97=A8=E7=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 2 +- CODING.md | 3 ++- README.md | 2 +- packages/tools/cli/bin/ua.js | 19 +++++++++++++++++-- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 2e4f086..ca49d61 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,7 +13,7 @@ 所有 TS / JS 代码遵循 `CODING.md`:注释一律中文(函数级 `/*** 作用 ***/`、行尾 `// 短注释`),代码紧凑 + 行工整、卫语句单行,高可扩展、低抽象、可读性优先。 -**注释强制门禁**:`npm run style`(即 `ua style`)机器检查——导出必须有 `/*** ***/` 注释、接口字段必须有行尾注释、行注释必须中文;有违规即退出码 1,改完才能提交。 +**注释强制门禁**:`npm run style`(即 `ua style`)机器检查——导出必须有 `/*** ***/` 注释、接口字段必须有行尾注释、行注释必须中文,并强制**分层包 src 下单文件 ≤ 200 行**(`types.ts` 与 `index.ts` 作为类型/导出汇总豁免);有违规即退出码 1,改完才能提交。 ## 项目结构(权威定义见 ARCHITECTURE.md) diff --git a/CODING.md b/CODING.md index 1afb7e5..e235b22 100644 --- a/CODING.md +++ b/CODING.md @@ -66,4 +66,5 @@ let cached: RowModel | null = null; // memo:缓存产物 ## 7. 落地方式 - 新代码必须符合本规范;旧代码顺手迁移,不强制一次性全量重写。 -- 后续可做成 `ua style` 检查项:导出缺注释、接口字段缺注释、类型散落实现文件、闭包状态未集中顶部。 +- 已落地为 `ua style` 检查项:导出缺注释、接口字段缺注释、行注释非中文、分层包 src 内单文件超过 200 行(`types.ts` / `index.ts` 豁免)。 +- 仍靠人工守的:类型散落实现文件、闭包状态未集中顶部。 diff --git a/README.md b/README.md index 6afe25d..417a678 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ accordion · alert · autoComplete · avatar · backTop · badge · breadcrumb ## 三道门禁 -1. `ua style`:注释规范——导出必须有 `/*** 作用 ***/`、接口字段行尾注释、行注释用中文。 +1. `ua style`:注释规范——导出必须有 `/*** 作用 ***/`、接口字段行尾注释、行注释用中文,且分层包 src 内单文件 ≤ 200 行(`types.ts` / `index.ts` 豁免)。 2. `ua verify`:清单 ↔ 文档 ↔ 演示一致(id 唯一、exports 对应、props 带 n/t/d、steps ≥ 3、demo 锚点存在),皮肤样式表禁止 `#hex` 硬编码颜色,`var(--ua-*)` 必须引用 tokens.css 已定义或组件自设的变量。 3. `ua index`:刷新 `.ua/index.json` / `llms.txt`,供 MCP 与 Agent 查询。 diff --git a/packages/tools/cli/bin/ua.js b/packages/tools/cli/bin/ua.js index d3ca7dd..05e61c9 100644 --- a/packages/tools/cli/bin/ua.js +++ b/packages/tools/cli/bin/ua.js @@ -639,19 +639,34 @@ function styleCheckFile(file, src) { return issues; } -/*** 全仓风格检查:有违规退出码 1,全绿输出 OK ***/ +// 单文件行数上限:CODING.md「单文件尽量 < 200 行」,只约束包内实现文件 +const MAX_LINES = 200; +// 不受行数限制的汇总文件:类型集中文件与导出入口天然会长 +const SIZE_EXEMPT = new Set(['types.ts', 'index.ts']); + +/*** 行数检查:只查分层包 src 目录下的实现文件,超出上限即违规 ***/ +function sizeCheckFile(file) { + const rel = path.relative(ROOT, file).replace(/\\/g, '/'); + if (!/^packages\/[^/]+\/[^/]+\/src\//.test(rel)) return []; // 只约束分层包源码 + if (SIZE_EXEMPT.has(path.basename(file))) return []; // 类型 / 导出汇总豁免 + const lines = fs.readFileSync(file, 'utf8').split(/\r?\n/).length; + return lines > MAX_LINES ? [`${rel} 共 ${lines} 行,超过单文件 ${MAX_LINES} 行上限(CODING.md)`] : []; +} + +/*** 全仓风格检查:注释规范 + 单文件行数,有违规退出码 1,全绿输出 OK ***/ function cmdStyle() { const files = collectSourceFiles(); const issues = []; for (const f of files) { issues.push(...styleCheckFile(f, fs.readFileSync(f, 'utf8'))); + issues.push(...sizeCheckFile(f)); } if (issues.length) { for (const it of issues) console.error('style: ' + it); console.error(`${issues.length} violation(s)`); process.exit(1); } - console.log(`style OK (${files.length} files)`); + console.log(`style OK (${files.length} files, 实现文件 ≤ ${MAX_LINES} 行)`); } /*** 皮肤包硬编码颜色检查:#hex 字面量一律禁止,颜色必须走 --ua-* 令牌(rgba 仅限阴影/遮罩的透明度叠加) ***/