@agile-team/wl-skills-ui 1.6.6 → 1.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to **@agile-team/wl-skills-ui** will be documented in this f
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
+ ## [1.6.7] - 2026-05-11
8
+
9
+ ### Added
10
+
11
+ - 新增 `standards/architecture/01-layer-boundaries.md`,明确 tokens、Element Plus、vendors、layouts、runtime、scanner、skills 的职责边界和扩展规则。
12
+ - 新增 `npm run docs:check`,校验旧命名、旧命令、README 版本文案、CHANGELOG 版本记录和编辑器配置完整性。
13
+
14
+ ### Changed
15
+
16
+ - CLI 编辑器安装配置改为读取 `skills/_meta/_compat/editors.json`,消除代码内第二份 `EDITOR_TARGETS` 路径映射。
17
+ - `editors.json` 补齐 `ext`、`singleFile`、`headerFile` 等安装行为字段,使 AI 编辑器配置成为单一事实源。
18
+
7
19
  ## [1.6.6] - 2026-05-11
8
20
 
9
21
  ### Changed
package/README.md CHANGED
@@ -193,10 +193,13 @@ yarn add @agile-team/wl-skills-ui
193
193
 
194
194
  ## 版本亮点
195
195
 
196
- 当前 v1.6.5 版本重点强化“统一规则源 + 多编辑器分发 + UI 细节精准修复”的闭环:
196
+ 当前 v1.6.7 版本重点强化“统一规则源 + 多编辑器分发 + 分层边界治理 + UI 细节精准修复”的闭环:
197
197
 
198
198
  - `skills/**/*.md` 作为唯一规则源,`wl-ui init/update` 会按编辑器格式转换并覆盖写入目标 rules
199
+ - `skills/_meta/_compat/editors.json` 作为 AI 编辑器安装配置唯一来源,CLI 不再维护第二份编辑器路径映射
199
200
  - `wl-ui update --editor all --force` 可一次性刷新全部支持编辑器;未指定编辑器时会刷新 manifest 与项目中已存在的编辑器规则目录
201
+ - `standards/architecture/01-layer-boundaries.md` 固化 tokens、Element Plus、vendors、layouts、runtime、scanner、skills 的扩展边界,避免胶水补丁污染
202
+ - `npm run docs:check` 校验旧命名、旧命令、版本文案和编辑器配置,防止规则文档回退
200
203
  - 表格空状态改为对应表格区域内自适应居中,避免嵌套表格靠固定高度猜效果
201
204
  - 查询区/工具栏按钮补齐 token fallback,禁用按钮独立保留清晰禁用态
202
205
  - 表单控件圆角统一使用 `--wk-form-control-radius`,覆盖 input/select/date/textarea/upload 等控件家族
package/bin/wl-ui.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * wl-ui — wl-skills-ui 统一 CLI
4
4
  *
5
5
  * 子命令:
6
- * wl-ui init [--project <path>] [--editor copilot|cursor|windsurf|kiro|trae] [--dry-run]
6
+ * wl-ui init [--project <path>] [--editor <editor|all>] [--dry-run]
7
7
  * 把 skills/ 写入目标项目的 AI 编辑器规则目录
8
8
  * wl-ui scan → 委托给 scanner/index.mjs
9
9
  * wl-ui check → 委托给 scanner/index.mjs
@@ -40,21 +40,7 @@ const MANIFEST_NAME = ".wl-skills-ui-manifest.json";
40
40
  // 常量
41
41
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
42
42
 
43
- /** 编辑器 安装目录映射 */
44
- const EDITOR_TARGETS = {
45
- "github-copilot": {
46
- dir: ".github/instructions/wk-skills",
47
- ext: ".instructions.md",
48
- },
49
- cursor: { dir: ".cursor/rules", ext: ".mdc" },
50
- windsurf: { dir: ".windsurf/rules", ext: ".md" },
51
- kiro: { dir: ".kiro/steering", ext: ".md" },
52
- trae: { dir: ".trae/rules", ext: ".md" },
53
- "claude-code": { dir: ".", ext: ".md", singleFile: "CLAUDE.md" },
54
- cline: { dir: ".", ext: ".md", singleFile: ".clinerules" },
55
- "agents-generic": { dir: ".", ext: ".md", singleFile: "AGENTS.md" },
56
- qoder: { dir: ".qoder/rules", ext: ".md" },
57
- };
43
+ const EDITOR_TARGETS = loadEditorTargets();
58
44
  const EDITOR_IDS = Object.keys(EDITOR_TARGETS);
59
45
 
60
46
  // ── 参数解析 ─────────────────────────────────────────────────────────────────
@@ -265,6 +251,33 @@ function detectEditor(projectRoot) {
265
251
  return "github-copilot";
266
252
  }
267
253
 
254
+ function loadEditorTargets() {
255
+ const configPath = join(
256
+ PKG_ROOT,
257
+ "skills",
258
+ "_meta",
259
+ "_compat",
260
+ "editors.json",
261
+ );
262
+ const config = JSON.parse(readFileSync(configPath, "utf8"));
263
+ return Object.fromEntries(
264
+ config.editors.map((editor) => [
265
+ editor.id,
266
+ {
267
+ dir: normalizeInstallDir(editor.installPath),
268
+ ext: editor.ext || ".md",
269
+ singleFile: editor.singleFile,
270
+ headerFile: editor.headerFile,
271
+ },
272
+ ]),
273
+ );
274
+ }
275
+
276
+ function normalizeInstallDir(installPath) {
277
+ const normalized = installPath.replace(/\\/g, "/").replace(/\/+$/, "");
278
+ return normalized === "." || normalized === "" ? "." : normalized;
279
+ }
280
+
268
281
  function detectInstalledEditors(projectRoot) {
269
282
  return EDITOR_IDS.filter((editor) => {
270
283
  const target = EDITOR_TARGETS[editor];
@@ -338,13 +351,14 @@ function collectSkills(skillsDir) {
338
351
 
339
352
  /** 读取编辑器 frontmatter 模板 */
340
353
  function getHeaderTemplate(editor) {
354
+ const target = EDITOR_TARGETS[editor];
355
+ const headerFile = target?.headerFile;
341
356
  const headerPath = join(
342
357
  PKG_ROOT,
343
358
  "skills",
344
359
  "_meta",
345
360
  "_compat",
346
- "headers",
347
- `${editorHeaderName(editor)}.txt`,
361
+ headerFile || join("headers", `${editor}.txt`),
348
362
  );
349
363
  if (existsSync(headerPath)) return readFileSync(headerPath, "utf8");
350
364
  return "";
@@ -543,22 +557,6 @@ function capitalize(s) {
543
557
  return s.charAt(0).toUpperCase() + s.slice(1);
544
558
  }
545
559
 
546
- function editorHeaderName(editor) {
547
- return (
548
- {
549
- cursor: "cursor-mdc",
550
- "github-copilot": "github-copilot",
551
- windsurf: "windsurf",
552
- kiro: "kiro",
553
- trae: "trae",
554
- "claude-code": "claude-code",
555
- cline: "cline",
556
- "agents-generic": "agents",
557
- qoder: "qoder",
558
- }[editor] || editor
559
- );
560
- }
561
-
562
560
  function installSupportFiles({ projectRoot, dryRun }) {
563
561
  const files = [
564
562
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agile-team/wl-skills-ui",
3
- "version": "1.6.6",
3
+ "version": "1.6.7",
4
4
  "description": "企业级 UI 风格对齐框架 — Vue + Element Plus 项目通用化妆/原生双模式(tokens / element / vendors / layouts / runtime / scanner / fixer / skills)",
5
5
  "type": "module",
6
6
  "main": "./es/index.js",
@@ -40,6 +40,7 @@
40
40
  "build": "tsup && npm run sync:tokens",
41
41
  "prepare": "npm run build",
42
42
  "sync:tokens": "node -e \"import('fs').then(fs=>fs.copyFileSync('design/tokens/base.css','dist/tokens.css'))\"",
43
+ "docs:check": "node scripts/check-docs.mjs",
43
44
  "scan": "node scanner/index.mjs scan",
44
45
  "check": "node scanner/index.mjs check",
45
46
  "fix": "node scanner/index.mjs fix",
@@ -58,6 +59,7 @@
58
59
  "skills",
59
60
  "templates",
60
61
  "bin",
62
+ "scripts",
61
63
  "mcp",
62
64
  "reference",
63
65
  "examples",
@@ -0,0 +1,83 @@
1
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
2
+ import { dirname, join, relative } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+ const root = join(__dirname, "..");
8
+ const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
9
+ const readme = readFileSync(join(root, "README.md"), "utf8");
10
+ const changelog = readFileSync(join(root, "CHANGELOG.md"), "utf8");
11
+ const editorConfig = JSON.parse(
12
+ readFileSync(
13
+ join(root, "skills", "_meta", "_compat", "editors.json"),
14
+ "utf8",
15
+ ),
16
+ );
17
+
18
+ const errors = [];
19
+ const forbiddenPatterns = [
20
+ { pattern: /\bwk-ui\b/, message: "旧 CLI 名称 wk-ui" },
21
+ { pattern: /\bwk-skills-ui\b/, message: "旧包名 wk-skills-ui" },
22
+ {
23
+ pattern: /@agile-team\/wk-skills-ui/,
24
+ message: "旧 npm 包名 @agile-team/wk-skills-ui",
25
+ },
26
+ { pattern: /--editor auto/, message: "无效编辑器参数 --editor auto" },
27
+ { pattern: /当前 v1\.6\.2/, message: "过期 README 当前版本文案" },
28
+ ];
29
+
30
+ function walk(dir) {
31
+ const files = [];
32
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
33
+ if (["node_modules", ".git", "dist", "es"].includes(entry.name)) continue;
34
+ const full = join(dir, entry.name);
35
+ if (entry.isDirectory()) files.push(...walk(full));
36
+ if (entry.isFile() && entry.name.endsWith(".md")) files.push(full);
37
+ }
38
+ return files;
39
+ }
40
+
41
+ for (const file of walk(root)) {
42
+ const rel = relative(root, file).replace(/\\/g, "/");
43
+ const content = readFileSync(file, "utf8");
44
+ for (const { pattern, message } of forbiddenPatterns) {
45
+ if (rel === "CHANGELOG.md") continue;
46
+ if (pattern.test(content)) errors.push(`${rel}: ${message}`);
47
+ }
48
+ }
49
+
50
+ if (!readme.includes(`当前 v${pkg.version}`)) {
51
+ errors.push(
52
+ `README.md: 当前版本文案未同步 package.json version ${pkg.version}`,
53
+ );
54
+ }
55
+
56
+ if (!changelog.includes(`## [${pkg.version}]`)) {
57
+ errors.push(`CHANGELOG.md: 缺少 ${pkg.version} 版本记录`);
58
+ }
59
+
60
+ for (const editor of editorConfig.editors) {
61
+ if (!editor.id) errors.push("editors.json: editor 缺少 id");
62
+ if (!editor.installPath)
63
+ errors.push(`editors.json: ${editor.id} 缺少 installPath`);
64
+ if (!editor.ext) errors.push(`editors.json: ${editor.id} 缺少 ext`);
65
+ if (!editor.headerFile)
66
+ errors.push(`editors.json: ${editor.id} 缺少 headerFile`);
67
+ if (
68
+ !existsSync(join(root, "skills", "_meta", "_compat", editor.headerFile))
69
+ ) {
70
+ errors.push(
71
+ `editors.json: ${editor.id} headerFile 不存在:${editor.headerFile}`,
72
+ );
73
+ }
74
+ }
75
+
76
+ if (errors.length > 0) {
77
+ console.error(
78
+ "docs:check failed:\n" + errors.map((error) => `- ${error}`).join("\n"),
79
+ );
80
+ process.exit(1);
81
+ }
82
+
83
+ console.log("docs:check passed");
@@ -6,6 +6,7 @@
6
6
  "description": "VS Code GitHub Copilot Chat Agent 模式",
7
7
  "skillFormat": "SKILL.md with YAML frontmatter (applyTo: glob)",
8
8
  "installPath": ".github/instructions/wk-skills/",
9
+ "ext": ".instructions.md",
9
10
  "headerFile": "headers/github-copilot.txt"
10
11
  },
11
12
  {
@@ -14,6 +15,7 @@
14
15
  "description": "Cursor AI 编辑器 .mdc 规则文件",
15
16
  "skillFormat": ".mdc files with YAML frontmatter (globs:)",
16
17
  "installPath": ".cursor/rules/",
18
+ "ext": ".mdc",
17
19
  "headerFile": "headers/cursor-mdc.txt"
18
20
  },
19
21
  {
@@ -22,6 +24,7 @@
22
24
  "description": "Windsurf AI 编辑器规则文件",
23
25
  "skillFormat": "Plain markdown, no frontmatter",
24
26
  "installPath": ".windsurf/rules/",
27
+ "ext": ".md",
25
28
  "headerFile": "headers/windsurf.txt"
26
29
  },
27
30
  {
@@ -30,6 +33,7 @@
30
33
  "description": "Kiro AI 编辑器 steering 文档",
31
34
  "skillFormat": "Markdown with YAML frontmatter (inclusion: manual)",
32
35
  "installPath": ".kiro/steering/",
36
+ "ext": ".md",
33
37
  "headerFile": "headers/kiro.txt"
34
38
  },
35
39
  {
@@ -38,6 +42,7 @@
38
42
  "description": "Trae AI 编辑器规则文件",
39
43
  "skillFormat": "Markdown with description frontmatter",
40
44
  "installPath": ".trae/rules/",
45
+ "ext": ".md",
41
46
  "headerFile": "headers/trae.txt"
42
47
  },
43
48
  {
@@ -46,6 +51,8 @@
46
51
  "description": "Claude Code 项目规则文件",
47
52
  "skillFormat": "Plain markdown",
48
53
  "installPath": "./",
54
+ "ext": ".md",
55
+ "singleFile": "CLAUDE.md",
49
56
  "headerFile": "headers/claude-code.txt"
50
57
  },
51
58
  {
@@ -54,6 +61,8 @@
54
61
  "description": "Cline 规则文件",
55
62
  "skillFormat": "Plain markdown",
56
63
  "installPath": "./",
64
+ "ext": ".md",
65
+ "singleFile": ".clinerules",
57
66
  "headerFile": "headers/cline.txt"
58
67
  },
59
68
  {
@@ -62,6 +71,8 @@
62
71
  "description": "AGENTS.md 通用代理协议",
63
72
  "skillFormat": "Plain markdown",
64
73
  "installPath": "./",
74
+ "ext": ".md",
75
+ "singleFile": "AGENTS.md",
65
76
  "headerFile": "headers/agents.txt"
66
77
  },
67
78
  {
@@ -70,6 +81,7 @@
70
81
  "description": "Qoder IDE 规则文件",
71
82
  "skillFormat": "Markdown with description frontmatter",
72
83
  "installPath": ".qoder/rules/",
84
+ "ext": ".md",
73
85
  "headerFile": "headers/qoder.txt"
74
86
  }
75
87
  ]
@@ -0,0 +1,122 @@
1
+ # wl-skills-ui 架构分层与扩展边界
2
+
3
+ ## 核心原则
4
+
5
+ `wl-skills-ui` 当前服务于既定项目集群,因此默认 tokens、配色、圆角、密度、组件视觉和工程接入方式是固化体系;但这些固化内容必须保持为可替换的独立变量层,不能散落到组件覆盖、vendor 化妆或 AI rules 中形成补丁污染。
6
+
7
+ 任何新增能力都必须遵守:
8
+
9
+ - 单一事实源:同一类配置只能有一个权威来源。
10
+ - 分层隔离:tokens、Element Plus 原子覆盖、vendor 封装覆盖、layouts、runtime、scanner、skills 各自负责自己的边界。
11
+ - 向下依赖:上层可以使用下层 token 和规范,下层不能反向依赖上层实现。
12
+ - 覆盖有序:后写入和高优先级覆盖必须有明确目录和加载顺序,不能靠零散 `!important` 补丁堆叠。
13
+ - 项目集群优先:当前风格先服务当前项目集群;未来多项目集群主题替换应通过 theme/tokens/preset 入口扩展,而不是修改组件规则本身。
14
+
15
+ ## 分层边界
16
+
17
+ | 层级 | 目录 | 职责 | 不允许做的事 |
18
+ | --- | --- | --- | --- |
19
+ | L0 Design Tokens | `design/tokens`、`styles/tokens` | 定义颜色、圆角、间距、字号、阴影等基础变量 | 不写具体组件选择器,不绑定业务组件名 |
20
+ | L1 Element Plus | `styles/element`、`skills/element` | 统一 Element Plus 原生组件视觉 | 不处理 `Base*`、`jh-*`、`C_*` 等封装私有结构 |
21
+ | L2 Vendors | `styles/vendors`、`skills/vendors` | 覆盖业务项目封装组件和第三方组合组件 | 不重新定义品牌色体系,不覆盖 layout 骨架语义 |
22
+ | L3 Layouts | `styles/layouts`、`skills/layouts`、`templates` | 约束列表页、树表页、表单弹窗等页面骨架 | 不改 token,不写 vendor 私有修复 |
23
+ | L4 Runtime | `runtime`、`reference` | 提供 `defineColumns`、`renderOps`、preset 等业务渲染能力 | 不直接承担老项目 skin 化妆职责 |
24
+ | Automation | `scanner`、`mcp` | 扫描、检查、dry-run 修复和 AI 工具入口 | 不绕过 skills/standards 私自定义新规则语义 |
25
+ | AI Rules | `skills`、`standards` | AI 可读规范、流程和修复策略 | 不和代码实现产生第二套事实源 |
26
+
27
+ ## Tokens 与主题替换边界
28
+
29
+ 当前默认主题位于:
30
+
31
+ ```text
32
+ design/tokens/base.css
33
+ styles/tokens/index.scss
34
+ ```
35
+
36
+ 这些文件是当前项目集群的默认主题源。组件样式只能引用 token,不应硬编码品牌色、表单圆角、按钮颜色、空状态颜色等可主题化变量。
37
+
38
+ 推荐写法:
39
+
40
+ ```scss
41
+ color: var(--el-text-color-secondary, #909399);
42
+ border-radius: var(--wk-form-control-radius, 6px);
43
+ ```
44
+
45
+ 不推荐写法:
46
+
47
+ ```scss
48
+ color: #909399;
49
+ border-radius: 6px;
50
+ ```
51
+
52
+ 未来如果不同项目集群需要切换主题,应优先增加新的 token/preset 入口,例如:
53
+
54
+ ```text
55
+ design/tokens/<cluster>.css
56
+ styles/presets/<cluster>.scss
57
+ ```
58
+
59
+ 而不是在 `styles/element` 或 `styles/vendors` 中追加按项目名区分的补丁选择器。
60
+
61
+ ## Element Plus 覆盖边界
62
+
63
+ Element Plus 原生组件覆盖必须保持组件族独立:
64
+
65
+ ```text
66
+ styles/element/_button.scss
67
+ styles/element/_form.scss
68
+ styles/element/_table.scss
69
+ styles/element/_feedback.scss
70
+ styles/element/_upload.scss
71
+ ```
72
+
73
+ 每个文件只处理对应组件族或强相关子组件。跨组件一致性通过 token 解决,例如表单圆角统一使用 `--wk-form-control-radius`,不能在 input、select、upload 中分别写不同硬编码。
74
+
75
+ ## Vendor 覆盖边界
76
+
77
+ vendor 层用于承接老项目封装和组合组件,优先级必须明确:
78
+
79
+ ```text
80
+ Base* > jh-* > C_*/c_* > custom wrappers
81
+ ```
82
+
83
+ 新增 vendor 覆盖时应同时补齐:
84
+
85
+ 1. `styles/vendors/_xxx.scss`
86
+ 2. `styles/vendors/index.scss` 加载顺序
87
+ 3. `skills/vendors/xxx/SKILL.md`
88
+ 4. `skills/_meta/_detection.md`
89
+ 5. 如需自动检查,补 `scanner/rules/*`
90
+
91
+ 不能只在某个页面局部追加样式补丁。
92
+
93
+ ## AI Rules 单一源原则
94
+
95
+ AI 编辑器规则由 `skills/**/*.md` 统一生成。不同编辑器只允许通过 `skills/_meta/_compat/editors.json` 和 `headers/*.txt` 做格式转换。
96
+
97
+ 禁止在以下目录手写与 `skills` 不一致的规则语义:
98
+
99
+ ```text
100
+ .github/instructions/wk-skills
101
+ .cursor/rules
102
+ .windsurf/rules
103
+ .kiro/steering
104
+ .trae/rules
105
+ .qoder/rules
106
+ CLAUDE.md
107
+ .clinerules
108
+ AGENTS.md
109
+ ```
110
+
111
+ 这些目录是安装产物,应由 `wl-ui init/update` 覆盖生成。
112
+
113
+ ## 新增能力检查清单
114
+
115
+ 新增任何 UI 规则或样式覆盖前,先确认:
116
+
117
+ - 是否能通过 token 解决,而不是新增组件补丁。
118
+ - 是否属于 Element Plus 原子层,还是 vendor 封装层。
119
+ - 是否需要同步 Skill、Standard、Scanner 和 Template。
120
+ - 是否会影响 skin 模式老项目布局。
121
+ - 是否会污染未来主题替换能力。
122
+ - 是否可以通过 `wl-ui update --editor all --force` 分发给全部 AI 编辑器。