@wot-ui/cli 0.0.1-beta.9 → 1.0.0

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/README.md CHANGED
@@ -49,11 +49,11 @@ wot mcp
49
49
 
50
50
  ### 组件知识
51
51
 
52
- - `wot list`:列出可用的 wot-ui 组件
53
- - `wot info <Component>`:查看组件 props、events、slots、CSS 变量
54
- - `wot doc <Component>`:输出组件 markdown 文档
55
- - `wot demo <Component> [name]`:查看 demo 列表或指定 demo 源码
56
- - `wot token [Component]`:查看组件 CSS 变量与默认值
52
+ - `wot list [keyword]`:列出可用的 wot-ui 组件,支持按名称过滤
53
+ - `wot info <component>`:查看组件 props、events、slots、CSS 变量
54
+ - `wot doc <component>`:输出组件 markdown 文档
55
+ - `wot demo <component> [name]`:查看 demo 列表或指定 demo 源码
56
+ - `wot token [component]`:查看组件 CSS 变量与默认值
57
57
  - `wot changelog [version] [component]`:查看版本更新记录
58
58
 
59
59
  ### 项目分析
@@ -66,11 +66,20 @@ wot mcp
66
66
 
67
67
  多数查询命令支持以下参数:
68
68
 
69
- - `--format text`
70
- - `--format json`
71
- - `--lang zh`
72
- - `--lang en`
73
- - `--version v2`
69
+ - `--format text`(默认)或 `--format json`:输出格式
70
+ - `--version <ver>`:指定 wot-ui 版本,支持以下格式:
71
+ - `2.0`(minor,自动解析到最新 patch)
72
+ - `2.0.4`(exact patch)
73
+ - `latest`(始终使用最新稳定版)
74
+ - 不传时自动从项目 `node_modules/@wot-ui/ui` 或 `package.json` 依赖声明检测,检测不到则回退到最新版
75
+
76
+ 示例:
77
+
78
+ ```bash
79
+ wot info Button --version 2.0.0
80
+ wot doc Button --version 2.0
81
+ wot list --format json --version latest
82
+ ```
74
83
 
75
84
  ## MCP 集成
76
85
 
@@ -105,20 +114,34 @@ wot mcp
105
114
  - `docs/guide/changelog.md`
106
115
  - `src/uni_modules/wot-ui/components/*/index.scss`
107
116
 
108
- 重新生成本地数据有两种方式。
117
+ `data/` 目录保存每个 stable patch 版本的独立快照(`v2.0.0.json`、`v2.0.1.json`、…),以及一个始终指向最新版的 `v2.json`。
118
+
119
+ ### 更新数据
109
120
 
110
- 使用本地已有的 wot-ui 仓库:
121
+ **全量同步所有历史 tag(推荐,首次或需要补全历史版本时使用):**
111
122
 
112
123
  ```bash
113
- pnpm extract:cli --wot-dir ../wot-ui --output data/v2.json
124
+ pnpm sync:clone
114
125
  ```
115
126
 
116
- 直接克隆最新的 wot-ui 仓库并提取:
127
+ 克隆 wot-ui 仓库(`--filter=tree:0 --no-checkout`,不下载文件树),按所有 stable tag 逐一 checkout + 提取,已有快照自动跳过。
128
+
129
+ **仅更新最新版本(快速,CI 单版本触发时使用):**
117
130
 
118
131
  ```bash
119
132
  pnpm extract:clone
120
133
  ```
121
134
 
135
+ **使用本地已有的 wot-ui 仓库:**
136
+
137
+ ```bash
138
+ # 全量多版本
139
+ pnpm sync --wot-dir ../wot-ui
140
+
141
+ # 单个版本,手动指定 checkout 后提取
142
+ pnpm extract --wot-dir ../wot-ui --output data/v2.0.4.json
143
+ ```
144
+
122
145
  ## 开发本仓库
123
146
 
124
147
  当前根目录就是主发布包,核心源码位于 `src`,离线数据位于 `data`,提取脚本位于 `scripts`。
@@ -137,13 +160,11 @@ pnpm install
137
160
  ### 常用开发命令
138
161
 
139
162
  ```bash
140
- pnpm lint
141
- pnpm test:all
142
- pnpm build:all
143
- pnpm typecheck:all
144
- pnpm build:cli
145
- pnpm test:cli
146
- pnpm typecheck:cli
163
+ pnpm lint # ESLint 检查
164
+ pnpm typecheck # TypeScript 类型检查
165
+ pnpm test # 单元测试
166
+ pnpm build # 构建产物到 dist/
167
+ pnpm compress # 压缩 data/*.json → data/*.json.gz(发布前自动执行)
147
168
  ```
148
169
 
149
170
  ### 本地调试 CLI
@@ -153,13 +174,16 @@ pnpm typecheck:cli
153
174
  ```bash
154
175
  pnpm exec tsx src/index.ts list
155
176
  pnpm exec tsx src/index.ts info Button
177
+ pnpm exec tsx src/index.ts info Button --version 2.0.0
178
+ pnpm exec tsx src/index.ts doc Button --version 2.0
156
179
  ```
157
180
 
158
181
  如果要调试构建产物:
159
182
 
160
183
  ```bash
161
- pnpm build:cli
184
+ pnpm build
162
185
  node dist/index.mjs list
186
+ node dist/index.mjs info Button --version 2.0.0
163
187
  ```
164
188
 
165
189
  ### 本地调试 MCP
@@ -172,9 +196,10 @@ MCP 走 stdio,终端无交互输出属于正常现象。若要查看 tools 与
172
196
 
173
197
  ## 自动化流程
174
198
 
175
- - `.github/workflows/ci.yml`:执行主包的 lint、typecheck、build、test
176
- - `.github/workflows/release.yml`:在 `v*` tag 上通过 reusable workflow 发布 `@wot-ui/cli`
177
- - `.github/workflows/sync.yml`:拉取上游 `wot-ui/wot-ui`,提取最新元数据,并自动创建同步 PR
199
+ - `.github/workflows/ci.yml`:在 `push`/`PR` 时执行 lint、typecheck、build、test(多 OS × Node 版本矩阵)
200
+ - `.github/workflows/sync.yml`:每日 02:00 UTC 自动检测 `@wot-ui/ui` 最新版本,有更新时拉取全量多版本快照并创建同步 PR;也可手动触发单版本提取
201
+ - `.github/workflows/release.yml`:`v*` tag 触发自动发布 `@wot-ui/cli` 到 npm(发布前自动运行 `pnpm compress && pnpm build`,npm 包只含 `.json.gz`)
202
+ - `.github/workflows/coverage-upload.yml`:`v*` tag 触发,上传测试覆盖率到 Codecov
178
203
 
179
204
  ## 当前边界
180
205
 
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,10 +1,13 @@
1
1
  {
2
- "latest": "2.0.0-alpha.5",
2
+ "latest": "2.0.4",
3
3
  "supported": [
4
- "2.0.0-alpha.5"
4
+ "2.0.4"
5
5
  ],
6
6
  "aliases": {
7
- "v2": "2.0.0-alpha.5",
8
- "latest": "2.0.0-alpha.5"
7
+ "v2": "2.0.4",
8
+ "latest": "2.0.4"
9
+ },
10
+ "v2": {
11
+ "2.0": "2.0.4"
9
12
  }
10
13
  }
Binary file
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as resolveVersion, i as listComponents, n as lintProject, o as loadMetadataFile, r as findComponent, s as version, t as analyzeUsage } from "./scanner-L5XVf4jh.mjs";
2
+ import { a as detectVersion, c as version, i as listComponents, n as lintProject, o as resolveVersion, r as findComponent, s as loadMetadataFile, t as analyzeUsage } from "./scanner-CcCQIYDr.mjs";
3
3
  import process from "node:process";
4
4
  import { Command } from "commander";
5
5
  import { existsSync, readFileSync } from "node:fs";
@@ -19,13 +19,15 @@ function writeJson(value) {
19
19
  //#endregion
20
20
  //#region src/commands/shared.ts
21
21
  function addQueryOptions(command) {
22
- return command.option("--format <format>", "output format: text, json, markdown", "text").option("--lang <lang>", "output language: zh, en", "zh").option("--version <version>", "target wot-ui version");
22
+ return command.option("--format <format>", "output format: text, json, markdown", "text").option("--version <version>", "target wot-ui version");
23
23
  }
24
24
  function normalizeQueryOptions(options) {
25
+ const format = options.format === "json" || options.format === "markdown" ? options.format : "text";
26
+ const info = detectVersion(typeof options.version === "string" ? options.version : void 0);
27
+ if (info.source === "fallback") process.stderr.write(`[wot] version not detected in project, falling back to ${info.version}\n`);
25
28
  return {
26
- format: options.format === "json" || options.format === "markdown" ? options.format : "text",
27
- lang: options.lang === "en" ? "en" : "zh",
28
- version: typeof options.version === "string" ? options.version : void 0
29
+ format,
30
+ version: info.version
29
31
  };
30
32
  }
31
33
  function printError(message, format) {
@@ -35,11 +37,11 @@ function printError(message, format) {
35
37
  });
36
38
  else console.error(message);
37
39
  }
38
- function getComponentLabel(component, lang) {
39
- return lang === "zh" ? `${component.name} ${component.nameZh}` : component.name;
40
+ function getComponentLabel(component) {
41
+ return `${component.name} ${component.nameZh}`;
40
42
  }
41
- function getComponentDescription(component, lang) {
42
- return lang === "zh" ? component.descriptionZh : component.description;
43
+ function getComponentDescription(component) {
44
+ return component.descriptionZh;
43
45
  }
44
46
  function formatCssVars(cssVars) {
45
47
  return cssVars.map((cssVar) => ({
@@ -251,8 +253,8 @@ function registerInfoCommand(program) {
251
253
  return;
252
254
  }
253
255
  writeLine([
254
- `${getComponentLabel(component, query.lang)} (${component.tag})`,
255
- getComponentDescription(component, query.lang),
256
+ `${getComponentLabel(component)} (${component.tag})`,
257
+ getComponentDescription(component),
256
258
  "",
257
259
  "Props:",
258
260
  ...component.props.map((prop) => `- ${prop.name}: ${prop.type}${prop.default ? ` = ${prop.default}` : ""} | ${prop.description}`),
@@ -310,7 +312,7 @@ function registerListCommand(program) {
310
312
  writeJson({ components });
311
313
  return;
312
314
  }
313
- writeLine(components.map((component) => `- ${getComponentLabel(component, query.lang)} (${component.tag}): ${getComponentDescription(component, query.lang)}`).join("\n"));
315
+ writeLine(components.map((component) => `- ${getComponentLabel(component)} (${component.tag}): ${getComponentDescription(component)}`).join("\n"));
314
316
  } catch (error) {
315
317
  printError(error instanceof Error ? error.message : "Failed to list components", query.format);
316
318
  process.exitCode = 1;
@@ -322,7 +324,7 @@ function registerListCommand(program) {
322
324
  //#region src/commands/mcp.ts
323
325
  function registerMcpCommand(program) {
324
326
  program.command("mcp").description("Start the wot-ui MCP server").action(async () => {
325
- const { startMcpServer } = await import("./server-BIz6B24d.mjs");
327
+ const { startMcpServer } = await import("./server-BiSLWBUo.mjs");
326
328
  await startMcpServer();
327
329
  });
328
330
  }
@@ -393,7 +395,7 @@ function registerUsageCommand(program) {
393
395
  //#region src/app.ts
394
396
  function createCliProgram() {
395
397
  const program = new Command();
396
- program.name("wot").description("wot-ui AI toolkit CLI").version(version);
398
+ program.name("wot").description("wot-ui AI toolkit CLI").version(version, "-V", "output the current version");
397
399
  registerListCommand(program);
398
400
  registerInfoCommand(program);
399
401
  registerDocCommand(program);
@@ -1,3 +1,4 @@
1
+ import process from "node:process";
1
2
  import { existsSync, readFileSync, readdirSync } from "node:fs";
2
3
  import { dirname, join, relative, resolve } from "node:path";
3
4
  import { fileURLToPath } from "node:url";
@@ -5,7 +6,7 @@ import { gunzipSync } from "node:zlib";
5
6
  import { parse } from "@vue/compiler-sfc";
6
7
 
7
8
  //#region package.json
8
- var version = "0.0.1-beta.9";
9
+ var version = "1.0.0";
9
10
 
10
11
  //#endregion
11
12
  //#region src/data/loader.ts
@@ -39,14 +40,91 @@ function loadMetadataFile(versionKey) {
39
40
 
40
41
  //#endregion
41
42
  //#region src/data/version.ts
42
- const VERSION_KEY = "v2";
43
+ /** Strip semver range operators (^, ~, >=, >, <=, <, =, whitespace). */
44
+ function stripRange(ver) {
45
+ return ver.replace(/[\^~>=<\s]/g, "");
46
+ }
47
+ /**
48
+ * Returns all stable version strings for major key 'v2',
49
+ * sorted ascending by semver.
50
+ */
51
+ function stableV2Versions() {
52
+ const map = loadVersionsFile().v2 ?? {};
53
+ return Object.values(map).filter((v) => !v.includes("-")).sort((a, b) => {
54
+ const pa = a.split(".").map(Number);
55
+ const pb = b.split(".").map(Number);
56
+ for (let i = 0; i < 3; i++) {
57
+ const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
58
+ if (diff !== 0) return diff;
59
+ }
60
+ return 0;
61
+ });
62
+ }
63
+ /**
64
+ * Auto-detect the wot-ui version to use.
65
+ *
66
+ * Priority:
67
+ * 1. --version flag (flagVersion arg)
68
+ * 2. node_modules/@wot-ui/ui/package.json in cwd
69
+ * 3. package.json dependencies[@wot-ui/ui] in cwd
70
+ * 4. Fallback to latest stable version from versions.json
71
+ */
72
+ function detectVersion(flagVersion, cwd) {
73
+ const dir = cwd ?? process.cwd();
74
+ if (flagVersion) return {
75
+ version: flagVersion,
76
+ source: "flag"
77
+ };
78
+ const nmPath = join(dir, "node_modules", "@wot-ui", "ui", "package.json");
79
+ if (existsSync(nmPath)) try {
80
+ const pkg = JSON.parse(readFileSync(nmPath, "utf8"));
81
+ if (pkg.version) return {
82
+ version: pkg.version,
83
+ source: "node_modules"
84
+ };
85
+ } catch {}
86
+ const pkgPath = join(dir, "package.json");
87
+ if (existsSync(pkgPath)) try {
88
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
89
+ const depVersion = pkg.dependencies?.["@wot-ui/ui"] ?? pkg.devDependencies?.["@wot-ui/ui"] ?? pkg.peerDependencies?.["@wot-ui/ui"];
90
+ if (depVersion) return {
91
+ version: stripRange(depVersion),
92
+ source: "package.json"
93
+ };
94
+ } catch {}
95
+ return {
96
+ version: stableV2Versions().at(-1) ?? "2.0.0",
97
+ source: "fallback"
98
+ };
99
+ }
100
+ /**
101
+ * Resolve a version string (from detectVersion or CLI flag) to a data file key.
102
+ *
103
+ * Examples:
104
+ * undefined / 'v2' → 'v2' (major alias, data/v2.json)
105
+ * 'latest' → 'v2.0.4' (latest stable snapshot)
106
+ * '2.0' → 'v2.0.4' (minor → lookup in versions.json)
107
+ * '2.0.4' → 'v2.0.4' (exact patch)
108
+ * '2.0.0-alpha.5' → 'v2.0.0-alpha.5' (pre-release exact)
109
+ */
43
110
  function resolveVersion(requested) {
44
- const versions = loadVersionsFile();
45
- if (!requested) return VERSION_KEY;
111
+ if (!requested || requested === "v2") return "v2";
46
112
  const normalized = requested.trim();
47
- if (versions.aliases[normalized]) return VERSION_KEY;
48
- if (versions.supported.includes(normalized)) return VERSION_KEY;
49
- if (normalized === VERSION_KEY) return VERSION_KEY;
113
+ if (normalized === "latest") {
114
+ const latest = stableV2Versions().at(-1);
115
+ if (!latest) return "v2";
116
+ return `v${latest}`;
117
+ }
118
+ const map = loadVersionsFile().v2 ?? {};
119
+ if (/^\d+\.\d+$/.test(normalized)) {
120
+ const patch = map[normalized];
121
+ if (!patch) throw new Error(`Unsupported wot-ui version: ${requested}`);
122
+ return `v${patch}`;
123
+ }
124
+ if (/^\d+\.\d+\.\d+/.test(normalized)) {
125
+ if (normalized.split(".")[0] !== "2") throw new Error(`Unsupported wot-ui version: ${requested}`);
126
+ return `v${normalized}`;
127
+ }
50
128
  throw new Error(`Unsupported wot-ui version: ${requested}`);
51
129
  }
52
130
 
@@ -200,4 +278,4 @@ function lintProject(targetDir, version$1) {
200
278
  }
201
279
 
202
280
  //#endregion
203
- export { resolveVersion as a, listComponents as i, lintProject as n, loadMetadataFile as o, findComponent as r, version as s, analyzeUsage as t };
281
+ export { detectVersion as a, version as c, listComponents as i, lintProject as n, resolveVersion as o, findComponent as r, loadMetadataFile as s, analyzeUsage as t };
@@ -1,4 +1,4 @@
1
- import { a as resolveVersion, i as listComponents, n as lintProject, o as loadMetadataFile, r as findComponent, s as version } from "./scanner-L5XVf4jh.mjs";
1
+ import { c as version, i as listComponents, n as lintProject, o as resolveVersion, r as findComponent, s as loadMetadataFile } from "./scanner-CcCQIYDr.mjs";
2
2
  import process from "node:process";
3
3
  import { McpServer, StdioServerTransport } from "@modelcontextprotocol/server";
4
4
  import * as z from "zod/v4";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wot-ui/cli",
3
3
  "type": "module",
4
- "version": "0.0.1-beta.9",
4
+ "version": "1.0.0",
5
5
  "description": "面向 wot-ui 的 CLI、MCP 与数据提取工具集",
6
6
  "license": "MIT",
7
7
  "funding": "https://github.com/sponsors/antfu",
@@ -67,16 +67,16 @@
67
67
  "build": "tsdown",
68
68
  "dev": "tsdown --watch",
69
69
  "extract": "tsx scripts/extract.ts",
70
- "extract:cli": "pnpm extract",
71
70
  "extract:clone": "rm -rf /tmp/open-wot-wot-ui && git clone --depth 1 https://github.com/wot-ui/wot-ui.git /tmp/open-wot-wot-ui && pnpm extract --wot-dir /tmp/open-wot-wot-ui --output data/v2.json",
71
+ "sync": "tsx scripts/sync.ts",
72
+ "sync:clone": "rm -rf /tmp/open-wot-wot-ui && git clone --filter=tree:0 --no-checkout https://github.com/wot-ui/wot-ui.git /tmp/open-wot-wot-ui && pnpm sync --wot-dir /tmp/open-wot-wot-ui",
73
+ "compress": "tsx scripts/compress.ts",
72
74
  "lint": "eslint",
73
75
  "release": "bumpp",
74
76
  "start": "tsx src/index.ts",
75
77
  "test": "vitest run",
76
78
  "test:coverage": "vitest run --coverage --coverage.reporter=lcov --coverage.reporter=text",
77
79
  "test:watch": "vitest",
78
- "typecheck": "tsc --noEmit",
79
- "typecheck:all": "pnpm typecheck",
80
- "typecheck:cli": "pnpm typecheck"
80
+ "typecheck": "tsc --noEmit"
81
81
  }
82
82
  }