iter(g150): ua info 反查所属配方
查完 props 顺手给出「这个组件出现在哪几条配方」,把两套入口接上。 --json 与 MCP get_component 的组件级返回同步带 recipes 字段。
This commit is contained in:
@@ -1556,6 +1556,14 @@
|
|||||||
"acceptance": "ua search <关键词> 按 id/标题/props 名/步骤匹配并排序输出,支持 --json;ua info 与 search 未命中时给出编辑距离 ≤3 的相近 id;usage 与 CLI 清单 steps、README、AGENTS 同步。",
|
"acceptance": "ua search <关键词> 按 id/标题/props 名/步骤匹配并排序输出,支持 --json;ua info 与 search 未命中时给出编辑距离 ≤3 的相近 id;usage 与 CLI 清单 steps、README、AGENTS 同步。",
|
||||||
"notes": "",
|
"notes": "",
|
||||||
"status": "done"
|
"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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,6 +146,14 @@ function formatComponent(pkg, comp) {
|
|||||||
return lines.join('\n');
|
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 直接当无建议 ***/
|
/*** 编辑距离(截断版):只用来给拼错的名字找相近候选,超过 3 直接当无建议 ***/
|
||||||
function editDistance(a, b) {
|
function editDistance(a, b) {
|
||||||
const prev = Array.from({ length: b.length + 1 }, (_, j) => j);
|
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(' / ')}` : ''}`);
|
console.error(`not found: ${name}(包名与组件 id 都没命中)${near.length ? `;相近:${near.join(' / ')}` : ''}`);
|
||||||
return process.exit(1);
|
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;
|
if (p) return p;
|
||||||
const hit = collectComponents(packages).find((x) => x.comp.id === args.name); // 退化到组件级查询
|
const hit = collectComponents(packages).find((x) => x.comp.id === args.name); // 退化到组件级查询
|
||||||
if (!hit) throw new Error(`not found: ${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') {
|
if (name === 'search_components') {
|
||||||
const q = String(args.query ?? '').toLowerCase();
|
const q = String(args.query ?? '').toLowerCase();
|
||||||
|
|||||||
Reference in New Issue
Block a user