mirror of
https://github.com/jnMetaCode/superpowers-zh.git
synced 2026-09-03 07:23:56 +08:00
补上之前简化版未实现的 plugins.0.version 路径,把
.claude-plugin/marketplace.json 纳入版本同步目标。
修复 marketplace.json 卡在 1.1.8 的老漂移(自 v1.1.8 起没动过):
plugins[0].version 1.1.8 -> 1.2.1(追上其他 4 个 manifest)。
实现:
- TARGETS 改为对象数组 { path, field },对齐上游 .version-bump.json 格式
- field='version' 走顶层 regex(保留原行为)
- field='plugins.0.version' 走嵌套 regex(锚定到 plugins 数组首项)
- 都用 regex 替换而非 JSON.stringify,保持原文件格式(缩进/数组写法等)
测试:
- 升级场景 1.2.1 → 1.3.0:4 个 manifest 全部同步
- 幂等性:版本相同时输出 "already at"
- 边界:marketplace.json 其他字段完全未动(diff 仅 version 一行)
- npm pack:90 文件 228KB 不变
58 lines
2.3 KiB
JavaScript
58 lines
2.3 KiB
JavaScript
#!/usr/bin/env node
|
||
// 把 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'));
|
||
|
||
// 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' },
|
||
];
|
||
|
||
function buildPattern(field) {
|
||
if (field === 'version') {
|
||
return /("version"\s*:\s*")[^"]+(")/;
|
||
}
|
||
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}`);
|