Files
drawlogo/scripts/build-skill-manifest.js

108 lines
4.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 生成技能库机器可读 manifest:js/data/manifest/skills.json
* 用法:node scripts/build-skill-manifest.js
* 仅导出技能元数据(含流程步骤/性质/工作区),run/test 实现留在 js/skills/、js/poster-skills/、js/sticker-skills/ 供系统执行。
* 注意:技能文件顶层 const HGB_* 是词法绑定,不挂 sandbox,必须全部拼接进同一 vm 代码串后直接引用。
*/
const fs = require('fs');
const path = require('path');
const vm = require('vm');
const ROOT = process.cwd();
const read = f => fs.readFileSync(path.join(ROOT, f), 'utf8');
// 共享技能(core + 7 分类)+ 海报技能(core + skills)+ 表情技能(core + skills)
const SKILL_FILES = [
'js/skills/core.js',
'js/skills/layout.js', 'js/skills/color.js', 'js/skills/typography.js',
'js/skills/icon.js', 'js/skills/ai.js', 'js/skills/presentation.js', 'js/skills/export.js',
'js/poster-skills/core.js', 'js/poster-skills/skills.js',
'js/sticker-skills/core.js', 'js/sticker-skills/skills.js'
];
// 技能定义期/自测可能引用的数据依赖(与浏览器加载顺序一致;表情技能可能引用动画引擎)
const DEP_FILES = [
'js/data/icons.js', 'js/data/industries.js', 'js/data/styles.js',
'js/data/decorations.js', 'js/data/palettes.js', 'js/data/fonts.js',
'js/data/builtin-icons.js', 'js/core/generator.js', 'js/core/motion.js'
];
const code = DEP_FILES.map(read).join('\n') + '\n' + SKILL_FILES.map(read).join('\n') + `
;globalThis.__MANIFEST = (function () {
var catOf = function (list) {
var m = {};
list.forEach(function (s) { m[s.category] = (m[s.category] || 0) + 1; });
return m;
};
var shared = (typeof HGB_Skills !== 'undefined') ? HGB_Skills.all().map(function (s) {
return {
id: s.id, name: s.name, category: s.category, emoji: s.emoji,
scene: s.scene, summary: s.summary, params: s.params, source: s.source,
step: HGB_Skills.stepOf(s.id), kind: HGB_Skills.kind(s.id),
workspaces: HGB_Skills.workspacesOf(s.id)
};
}) : [];
var poster = (typeof HGB_PosterSkills !== 'undefined') ? HGB_PosterSkills.all().map(function (s) {
return {
id: s.id, name: s.name, category: s.category, emoji: s.emoji,
scene: s.scene, summary: s.summary, params: s.params, source: s.source,
workspaces: HGB_PosterSkills.workspacesOf(s.id)
};
}) : [];
var sticker = (typeof HGB_StickerSkills !== 'undefined') ? HGB_StickerSkills.all().map(function (s) {
return {
id: s.id, name: s.name, category: s.category, emoji: s.emoji,
scene: s.scene, summary: s.summary, params: s.params, source: s.source,
workspaces: HGB_StickerSkills.workspacesOf(s.id)
};
}) : [];
return {
shared: shared,
poster: poster,
sticker: sticker,
steps: (typeof HGB_Skills !== 'undefined' && HGB_Skills.steps) ? HGB_Skills.steps() : []
};
})();
`;
const sandbox = { console, setTimeout, clearTimeout, window: null, self: null };
sandbox.window = sandbox;
sandbox.self = sandbox;
try {
vm.runInNewContext(code, sandbox, { filename: 'skills-manifest.js' });
} catch (e) {
console.error('❌ 技能 manifest 生成失败:' + e.message);
process.exit(1);
}
const m = sandbox.__MANIFEST;
if (!m.shared.length && !m.poster.length && !m.sticker.length) {
console.error('❌ 未注册任何技能,检查技能文件加载');
process.exit(1);
}
const out = {
kind: 'skills',
generatedAt: new Date().toISOString(),
guide: 'js/data/manifest/README.md',
shared: {
total: m.shared.length,
categories: m.steps.map(s => s), // 设计流程 5 步元数据(共享技能按流水线组织)
skills: m.shared
},
poster: {
total: m.poster.length,
categories: null, // 海报技能按 8 分类,见各 skill.category
skills: m.poster
},
sticker: {
total: m.sticker.length,
categories: null, // 表情技能按 motion/emotion 分类,见各 skill.category
skills: m.sticker
}
};
const manifestDir = path.join(ROOT, 'js/data/manifest');
fs.mkdirSync(manifestDir, { recursive: true });
fs.writeFileSync(path.join(manifestDir, 'skills.json'), JSON.stringify(out, null, 1), 'utf8');
console.log(`✅ 技能 manifest:共享 ${m.shared.length} 个 / 海报 ${m.poster.length} 个 / 表情 ${m.sticker.length} 个 → js/data/manifest/skills.json`);