iter(g319): ua info 支持逗号分隔批量查询,一次拿全多个组件

This commit is contained in:
HIsheR
2026-10-27 01:03:33 +08:00
parent 77d1c72e1e
commit dcf470c0c7
5 changed files with 58 additions and 24 deletions
+44 -19
View File
@@ -315,31 +315,56 @@ function cmdSearch(words = [], args = []) {
console.log(`\n共 ${parts.join('、')}命中;查参数:ua info <组件id>,看骨架:ua recipes <编号>`);
}
/*** 输出单包或单组件信息:默认人读摘要,--json 输出原始 JSON ***/
/*** 输出包或组件信息:默认人读摘要,--json 输出原始 JSON;name 支持逗号分隔一次查多个(单值保持原输出结构不破坏脚本) ***/
function cmdInfo(name, args = []) {
const { packages } = loadIndex();
const asJson = args.includes('--json');
const pkg = packages.find((x) => x.name === name || x.name === `@ui-arch/${name}`);
if (pkg) {
if (asJson) return console.log(JSON.stringify(pkg, null, 2));
return console.log(
`${pkg.name} v${pkg.version} [${pkg.type}] ${pkg.description}\n(--json 看完整清单;按组件查:ua info <组件id>)`,
);
const asMd = args.includes('--md');
const names = name.split(',').map((s) => s.trim()).filter(Boolean); // 批量:逗号分隔多组件一次拿全,省 Agent 往返
const comps = collectComponents(packages);
const resolve = (n) => { // 单个名字 → 包或组件条目;都没命中返回 null 交由调用方报错
const pkg = packages.find((x) => x.name === n || x.name === `@ui-arch/${n}`);
if (pkg) return { kind: 'pkg', pkg };
const hit = comps.find((x) => x.comp.id === n);
return hit ? { kind: 'comp', hit } : null;
};
if (names.length === 1) {
const r = resolve(names[0]);
if (!r) {
const near = nearIds(names[0]);
console.error(`not found: ${names[0]}(包名与组件 id 都没命中)${near.length ? `;相近:${near.join(' / ')}` : ''}`);
return process.exit(1);
}
if (r.kind === 'pkg') {
if (asJson) return console.log(JSON.stringify(r.pkg, null, 2));
return console.log(
`${r.pkg.name} v${r.pkg.version} [${r.pkg.type}] ${r.pkg.description}\n(--json 看完整清单;按组件查:ua info <组件id>)`,
);
}
const { hit } = r;
if (asJson) return console.log(JSON.stringify({ package: hit.pkg.name, ...hit.comp, recipes: recipesFor(hit.comp.id) }, null, 2));
const related = recipesFor(hit.comp.id);
const recipeTail = related.length ? `\n\n出现在配方:${related.map((x) => `${x.id}(${x.title})`).join('、')}(ua mcp 的 get_recipe 可取骨架)` : '';
if (asMd) return console.log(formatComponentMd(hit.pkg, hit.comp) + recipeTail); // Markdown 片段:贴进文档 / issue / 回复时不用手抄参数表
return console.log(formatComponent(hit.pkg, hit.comp) + recipeTail);
}
const hit = collectComponents(packages).find((x) => x.comp.id === name);
if (!hit) {
const near = nearIds(name);
console.error(`not found: ${name}(包名与组件 id 都没命中)${near.length ? `;相近:${near.join(' / ')}` : ''}`);
const resolved = names.map((n) => resolve(n)); // 批量路径:先全量解析,任一失败整条拒绝(输出一半再报错会让脚本误判成功)
const bad = names.filter((n, i) => !resolved[i]);
if (bad.length) {
const near = nearIds(bad[0]);
console.error(`not found: ${bad.join(' / ')}(第 ${names.indexOf(bad[0]) + 1} 个,包名与组件 id 都没命中)${near.length ? `;相近:${near.join(' / ')}` : ''}`);
return process.exit(1);
}
if (asJson) return console.log(JSON.stringify({ package: hit.pkg.name, ...hit.comp, recipes: recipesFor(hit.comp.id) }, null, 2));
const related = recipesFor(hit.comp.id);
const recipeTail = related.length ? `\n\n出现在配方:${related.map((r) => `${r.id}(${r.title})`).join('、')}(ua mcp 的 get_recipe 可取骨架)` : '';
if (args.includes('--md')) {
// Markdown 片段:贴进文档 / issue / 回复时不用手抄参数表;配方清单压成一行尾注
return console.log(formatComponentMd(hit.pkg, hit.comp) + recipeTail);
const compMd = (r) => { // 批量输出统一用组件片段格式:包条目退化为标题行
if (r.kind === 'pkg') return `## ${r.pkg.name}(${r.pkg.type})\n\n${r.pkg.description}`;
const related = recipesFor(r.hit.comp.id);
const tail = related.length ? `\n\n> 出现在配方:${related.map((x) => `${x.id}(${x.title})`).join('、')}` : '';
return formatComponentMd(r.hit.pkg, r.hit.comp) + tail;
};
if (asJson) {
return console.log(JSON.stringify(resolved.map((r) => (r.kind === 'pkg' ? r.pkg : { package: r.hit.pkg.name, ...r.hit.comp, recipes: recipesFor(r.hit.comp.id) })), null, 2));
}
console.log(formatComponent(hit.pkg, hit.comp) + recipeTail);
console.log(resolved.map(compMd).join('\n\n---\n\n')); // 片段间以水平线分隔,方便人读与脚本按线切块
}
// ---- 静态文档站生成 ----
@@ -2033,6 +2058,6 @@ switch (cmd) {
cmdMcp();
break;
default:
console.log('usage: ua <index|list|search <kw>|info <name> [--json|--md]|recipes [编号] [--json]|docs|tokens [--json|--unused]|style|sync-counts|verify|doctor|commit-lint|lint-iterations|iter|audit:visual [--json|--baseline]|audit:contrast [--json|--list]|audit:motion [--json]|audit:surface [--json|--list]|loop [--json]|changelog|mcp>');
console.log('usage: ua <index|list|search <kw>|info <name[,name…]> [--json|--md]|recipes [编号] [--json]|docs|tokens [--json|--unused]|style|sync-counts|verify|doctor|commit-lint|lint-iterations|iter|audit:visual [--json|--baseline]|audit:contrast [--json|--list]|audit:motion [--json]|audit:surface [--json|--list]|loop [--json]|changelog|mcp>');
process.exit(cmd ? 1 : 0);
}
+2 -2
View File
@@ -34,7 +34,7 @@
"MCP tool 入参 schema"
]
},
"usage": "node packages/tools/cli/bin/ua.js <index|list|info <包名|组件id> [--json|--md]|docs|tokens [--json|--unused]|style|verify|commit-lint|audit:visual|audit:contrast|audit:motion|doctor|mcp>;仓库内等价于 npm run index / docs / style / verify / audit:visual / audit:contrast / audit:motion / doctor",
"usage": "node packages/tools/cli/bin/ua.js <index|list|info <包名|组件id[,组件id…]> [--json|--md]|docs|tokens [--json|--unused]|style|verify|commit-lint|audit:visual|audit:contrast|audit:motion|doctor|mcp>;仓库内等价于 npm run index / docs / style / verify / audit:visual / audit:contrast / audit:motion / doctor",
"conventions": [
"零依赖:只用 node 标准库,Node >= 18",
"清单是单一来源:代码注释、文档站、llms-full.txt、MCP 全部从 ua.manifest.json 派生",
@@ -56,4 +56,4 @@
],
"components": []
}
}
}