diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 5d52690..ccc604f 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,7 +9,7 @@ { "name": "superpowers-zh", "description": "AI 编程超能力中文增强版:20 个 skills(14 翻译 + 6 中国原创),支持 Claude Code / Hermes Agent / Cursor / Claw Code 等 17 款工具", - "version": "1.1.8", + "version": "1.2.1", "source": "./", "author": { "name": "jnMetaCode", diff --git a/package.json b/package.json index 1993699..96b4e72 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "superpowers-zh": "bin/superpowers-zh.js" }, "scripts": { - "version": "node scripts/sync-plugin-version.js && git add .claude-plugin/plugin.json .cursor-plugin/plugin.json .codex-plugin/plugin.json" + "version": "node scripts/sync-plugin-version.js && git add .claude-plugin/plugin.json .claude-plugin/marketplace.json .cursor-plugin/plugin.json .codex-plugin/plugin.json" }, "files": [ "bin/", diff --git a/scripts/sync-plugin-version.js b/scripts/sync-plugin-version.js index 6f7ea27..cf5cf7b 100644 --- a/scripts/sync-plugin-version.js +++ b/scripts/sync-plugin-version.js @@ -1,31 +1,57 @@ #!/usr/bin/env node -// 把 package.json 的 version 同步到 plugin manifest -// 由 npm version 钩子触发,跑在 version commit 创建之前 +// 把 package.json 的 version 同步到所有 plugin manifest(含嵌套字段)。 +// 由 npm version 钩子触发,跑在 version commit 创建之前。 +// +// 设计:用 regex 替换而不是 JSON.parse + stringify,目的是保留原文件格式 +// (缩进、行内/多行数组、空白等不被破坏)。每种 field 路径对应一个专用 regex。 import { readFileSync, writeFileSync } from 'fs'; import { resolve, dirname } from 'path'; import { fileURLToPath } from 'url'; const root = resolve(dirname(fileURLToPath(import.meta.url)), '..'); const pkg = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8')); -const targets = [ - '.claude-plugin/plugin.json', - '.cursor-plugin/plugin.json', - '.codex-plugin/plugin.json', + +// targets 字段对齐上游 .version-bump.json 格式(path + field 路径)。 +// 顶层用 "version",嵌套用 dot-path(如 "plugins.0.version")。 +const TARGETS = [ + { path: '.claude-plugin/plugin.json', field: 'version' }, + { path: '.cursor-plugin/plugin.json', field: 'version' }, + { path: '.codex-plugin/plugin.json', field: 'version' }, + { path: '.claude-plugin/marketplace.json', field: 'plugins.0.version' }, ]; -let touched = 0; -for (const rel of targets) { - const path = resolve(root, rel); - const text = readFileSync(path, 'utf8'); - const json = JSON.parse(text); - if (json.version === pkg.version) continue; - // 只替换顶层 version 字段一行,保留原文件其他字段的格式(数组单行/多行、缩进等) - const updated = text.replace(/("version":\s*")[^"]+(")/, `$1${pkg.version}$2`); - if (updated === text) { - throw new Error(`未能在 ${rel} 中定位 version 字段`); +function buildPattern(field) { + if (field === 'version') { + return /("version"\s*:\s*")[^"]+(")/; } - writeFileSync(path, updated, 'utf8'); - console.log(` ${rel}: ${json.version} -> ${pkg.version}`); + if (field === 'plugins.0.version') { + // 锚定到 "plugins": [ { ... 第一个对象内的 version 字段 + return /("plugins"\s*:\s*\[\s*\{[\s\S]*?"version"\s*:\s*")[^"]+(")/; + } + throw new Error(`Unsupported field path: ${field}`); +} + +function readField(json, field) { + if (field === 'version') return json.version; + if (field === 'plugins.0.version') return json.plugins?.[0]?.version; + throw new Error(`Unsupported field path: ${field}`); +} + +let touched = 0; +for (const { path: rel, field } of TARGETS) { + const fullPath = resolve(root, rel); + const text = readFileSync(fullPath, 'utf8'); + const json = JSON.parse(text); + const current = readField(json, field); + if (current === pkg.version) continue; + + const pattern = buildPattern(field); + const updated = text.replace(pattern, `$1${pkg.version}$2`); + if (updated === text) { + throw new Error(`未能在 ${rel} 中定位字段 ${field}`); + } + writeFileSync(fullPath, updated, 'utf8'); + console.log(` ${rel} (${field}): ${current} -> ${pkg.version}`); touched++; } if (touched === 0) console.log(` plugin manifests already at ${pkg.version}`);