reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
63
vendor-new/rev-skills/bin/convert.mjs
Normal file
63
vendor-new/rev-skills/bin/convert.mjs
Normal file
@@ -0,0 +1,63 @@
|
||||
// bin/convert.mjs — SKILL.md → 规则文件转换器
|
||||
import { readdirSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
|
||||
import { join, dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { parseFrontmatterDocument } from '../lib/frontmatter.mjs';
|
||||
|
||||
export function skillDirs(skillsRoot) {
|
||||
return readdirSync(skillsRoot, { withFileTypes: true })
|
||||
.filter(e => e.isDirectory() && e.name.startsWith('re-'))
|
||||
.map(e => join(skillsRoot, e.name));
|
||||
}
|
||||
|
||||
export function readSkill(dir) {
|
||||
const md = readFileSync(join(dir, 'SKILL.md'), 'utf8');
|
||||
const { fm, body } = parseFrontmatterDocument(md); // 与 validate.mjs 同一解析器(lib/frontmatter.mjs)
|
||||
return { name: fm.name, description: fm.description, body };
|
||||
}
|
||||
|
||||
// parseSkill:readSkill 的别名,保持调用方兼容
|
||||
export function parseSkill(dir) { return readSkill(dir); }
|
||||
|
||||
const HERE = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export function convertAll(type, destDir) {
|
||||
// 初版:cursor/windsurf 每技能一文件;copilot 聚合单文件
|
||||
const skills = skillDirs(join(HERE, '..', '.claude', 'skills'))
|
||||
.map(readSkill);
|
||||
mkdirSync(destDir, { recursive: true });
|
||||
const files = [];
|
||||
if (type === 'cursor') {
|
||||
for (const s of skills) {
|
||||
const p = join(destDir, `${s.name}.mdc`);
|
||||
writeFileSync(p, `---\ndescription: ${JSON.stringify(s.description)}\nglobs: **/*\n---\n\n${s.body}`);
|
||||
files.push(p);
|
||||
}
|
||||
} else if (type === 'windsurf') {
|
||||
for (const s of skills) {
|
||||
const p = join(destDir, `${s.name}.md`);
|
||||
writeFileSync(p, `# ${s.name}\n\n${s.description}\n\n${s.body}`);
|
||||
files.push(p);
|
||||
}
|
||||
} else if (type === 'copilot') {
|
||||
const p = join(destDir, 'copilot-instructions.md');
|
||||
const head = '# 逆向工程技能库(AI 助手指令)\n\n本文件由技能库自动聚合生成,作为分析时的知识参考。\n\n';
|
||||
writeFileSync(p, head + skills.map(s =>
|
||||
`## ${s.name}\n\n${s.description}\n\n${s.body}`).join('\n\n---\n\n'));
|
||||
files.push(p);
|
||||
} else {
|
||||
throw new Error(`unknown rule type: ${type}`);
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
// —— 追加到 convert.mjs 末尾 ——
|
||||
function cli() {
|
||||
const args = process.argv.slice(2);
|
||||
const type = args[args.indexOf('--target') + 1];
|
||||
const out = args[args.indexOf('--out') + 1];
|
||||
if (!type || !out) { console.error('usage: node bin/convert.mjs --target cursor|copilot|windsurf --out <dir>'); process.exit(1); }
|
||||
const files = convertAll(type, out);
|
||||
console.log(`generated ${files.length} file(s) in ${out}`);
|
||||
}
|
||||
if (process.argv[1] && process.argv[1].endsWith('convert.mjs')) cli();
|
||||
Reference in New Issue
Block a user