iter(g150): ua info 反查所属配方

查完 props 顺手给出「这个组件出现在哪几条配方」,把两套入口接上。
--json 与 MCP get_component 的组件级返回同步带 recipes 字段。
This commit is contained in:
HIsheR
2026-10-26 15:50:44 +08:00
parent 1455f82602
commit 04f6df87f5
2 changed files with 21 additions and 2 deletions
+8
View File
@@ -1556,6 +1556,14 @@
"acceptance": "ua search <关键词> 按 id/标题/props 名/步骤匹配并排序输出,支持 --json;ua info 与 search 未命中时给出编辑距离 ≤3 的相近 id;usage 与 CLI 清单 steps、README、AGENTS 同步。",
"notes": "",
"status": "done"
},
{
"id": "g150",
"title": "ua info 反查组件出现在哪些配方",
"motivation": "配方与组件是两套入口:查完 props 往往还要自己判断「这组件平时和谁一起用」,而 recipes.md 里已有答案却没接上。",
"acceptance": "ua info <组件id> 末尾列出包含该组件的配方 id 与标题(无命中不追加空行);--json 输出增加 recipes 字段;MCP get_component 组件级返回同步带 recipes。",
"notes": "",
"status": "open"
}
]
}
+13 -2
View File
@@ -146,6 +146,14 @@ function formatComponent(pkg, comp) {
return lines.join('\n');
}
/*** 反查某组件出现在哪些配方里:查参数时顺带给出「它通常和谁一起用」的组合线索 ***/
function recipesFor(compId) {
const re = new RegExp(`\\b${compId}\\b`);
return parseRecipes()
.filter((r) => re.test(`${r.code}\n${r.text}`))
.map((r) => ({ id: r.id, title: r.title }));
}
/*** 编辑距离(截断版):只用来给拼错的名字找相近候选,超过 3 直接当无建议 ***/
function editDistance(a, b) {
const prev = Array.from({ length: b.length + 1 }, (_, j) => j);
@@ -219,7 +227,10 @@ function cmdInfo(name, args = []) {
console.error(`not found: ${name}(包名与组件 id 都没命中)${near.length ? `;相近:${near.join(' / ')}` : ''}`);
return process.exit(1);
}
console.log(asJson ? JSON.stringify({ package: hit.pkg.name, ...hit.comp }, null, 2) : formatComponent(hit.pkg, hit.comp));
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 tail = related.length ? `\n\n出现在配方:${related.map((r) => `${r.id}(${r.title})`).join('、')}(ua mcp 的 get_recipe 可取骨架)` : '';
console.log(formatComponent(hit.pkg, hit.comp) + tail);
}
// ---- 静态文档站生成 ----
@@ -586,7 +597,7 @@ function cmdMcp() {
if (p) return p;
const hit = collectComponents(packages).find((x) => x.comp.id === args.name); // 退化到组件级查询
if (!hit) throw new Error(`not found: ${args.name}`);
return { package: hit.pkg.name, ...hit.comp };
return { package: hit.pkg.name, ...hit.comp, recipes: recipesFor(hit.comp.id) };
}
if (name === 'search_components') {
const q = String(args.query ?? '').toLowerCase();