change-image-suffix 2.1.4 → 2.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [2.1.6](https://github.com/GuoSirius/change-image-suffix/compare/v2.1.5...v2.1.6) (2026-05-25)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* use inline shell sub-keys instead of ExtendedSubCommandsKey for context menu ([2f50376](https://github.com/GuoSirius/change-image-suffix/commit/2f50376a62a17bcf317530e0662f5b2d718d53d0))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Chores
|
|
14
|
+
|
|
15
|
+
* update local settings permissions and refresh lockfile ([71d0c1e](https://github.com/GuoSirius/change-image-suffix/commit/71d0c1e6124006e827a3c0d078f9cc47699a3f4c))
|
|
16
|
+
|
|
17
|
+
### [2.1.5](https://github.com/GuoSirius/change-image-suffix/compare/v2.1.4...v2.1.5) (2026-05-23)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Chores
|
|
21
|
+
|
|
22
|
+
* upgrade deps (sharp 0.34, TS6, @types/node 25), migrate to ESM, require node >=24 ([d3a3234](https://github.com/GuoSirius/change-image-suffix/commit/d3a323410ccd1f5ed9f04443adc25c6edd96f7df))
|
|
23
|
+
|
|
5
24
|
### [2.1.4](https://github.com/GuoSirius/change-image-suffix/compare/v2.1.3...v2.1.4) (2026-05-23)
|
|
6
25
|
|
|
7
26
|
|
package/dist/index.js
CHANGED
|
@@ -1,47 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}) : (function(o, m, k, k2) {
|
|
11
|
-
if (k2 === undefined) k2 = k;
|
|
12
|
-
o[k2] = m[k];
|
|
13
|
-
}));
|
|
14
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
-
}) : function(o, v) {
|
|
17
|
-
o["default"] = v;
|
|
18
|
-
});
|
|
19
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
-
var ownKeys = function(o) {
|
|
21
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
-
var ar = [];
|
|
23
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
-
return ar;
|
|
25
|
-
};
|
|
26
|
-
return ownKeys(o);
|
|
27
|
-
};
|
|
28
|
-
return function (mod) {
|
|
29
|
-
if (mod && mod.__esModule) return mod;
|
|
30
|
-
var result = {};
|
|
31
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
-
__setModuleDefault(result, mod);
|
|
33
|
-
return result;
|
|
34
|
-
};
|
|
35
|
-
})();
|
|
36
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
-
};
|
|
39
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
const fs = __importStar(require("fs"));
|
|
41
|
-
const path = __importStar(require("path"));
|
|
42
|
-
const os = __importStar(require("os"));
|
|
43
|
-
const child_process_1 = require("child_process");
|
|
44
|
-
const sharp_1 = __importDefault(require("sharp"));
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import * as os from 'os';
|
|
5
|
+
import { execSync } from 'child_process';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import sharp from 'sharp';
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
45
10
|
// 支持的输入/输出格式
|
|
46
11
|
const SUPPORTED_INPUT_EXTENSIONS = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'tiff', 'tif', 'webp', 'avif'];
|
|
47
12
|
const SUPPORTED_OUTPUT_FORMATS = ['webp', 'jpg', 'jpeg', 'png', 'avif', 'tiff', 'tif'];
|
|
@@ -58,7 +23,7 @@ function requireWindows() {
|
|
|
58
23
|
}
|
|
59
24
|
function regDelete(key) {
|
|
60
25
|
try {
|
|
61
|
-
|
|
26
|
+
execSync(`reg delete "${key}" /f`, { stdio: 'ignore' });
|
|
62
27
|
}
|
|
63
28
|
catch {
|
|
64
29
|
// 忽略不存在的键
|
|
@@ -69,11 +34,11 @@ function installContextMenu() {
|
|
|
69
34
|
// ── 查找 cis.cmd 路径 ──
|
|
70
35
|
let cisCmd = '';
|
|
71
36
|
try {
|
|
72
|
-
cisCmd =
|
|
37
|
+
cisCmd = execSync('where cis.cmd', { encoding: 'utf8' }).trim().split('\n')[0].trim();
|
|
73
38
|
}
|
|
74
39
|
catch {
|
|
75
40
|
try {
|
|
76
|
-
cisCmd =
|
|
41
|
+
cisCmd = execSync('where cis', { encoding: 'utf8' }).trim().split('\n')[0].trim();
|
|
77
42
|
}
|
|
78
43
|
catch {
|
|
79
44
|
console.error('❌ 找不到 cis 命令,请先执行 npm link 或 npm install -g change-image-suffix');
|
|
@@ -155,44 +120,37 @@ endlocal
|
|
|
155
120
|
{ verb: 'avif', label: '📺 AVIF' },
|
|
156
121
|
{ verb: 'tiff', label: '📋 TIFF' },
|
|
157
122
|
];
|
|
158
|
-
// ── 使用 ExtendedSubCommandsKey
|
|
159
|
-
// 文件右键和目录右键均使用 bat 脚本,混合选择时自动分类文件和目录
|
|
123
|
+
// ── 使用 inline shell 子菜单(比 ExtendedSubCommandsKey 更可靠地传递参数)──
|
|
160
124
|
const menuBases = [
|
|
161
|
-
{
|
|
162
|
-
|
|
163
|
-
|
|
125
|
+
{
|
|
126
|
+
base: 'HKCU\\Software\\Classes\\*\\shell\\cis',
|
|
127
|
+
cmd: (fmt) => `"${batPath}" ${fmt} "%1"`,
|
|
128
|
+
multiSelect: true,
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
base: 'HKCU\\Software\\Classes\\Directory\\shell\\cis',
|
|
132
|
+
cmd: (fmt) => `"${batPath}" ${fmt} "%1"`,
|
|
133
|
+
multiSelect: false,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
base: 'HKCU\\Software\\Classes\\Directory\\Background\\shell\\cis',
|
|
137
|
+
cmd: (fmt) => `"${cisCmd}" -t ${fmt} -p "%V"`,
|
|
138
|
+
multiSelect: false,
|
|
139
|
+
},
|
|
164
140
|
];
|
|
165
|
-
// 1. 注册公共子菜单(每种菜单类型独立注册)
|
|
166
|
-
const REG_ROOT = 'HKCU\\Software\\Classes\\';
|
|
167
141
|
for (const menu of menuBases) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
// 最终执行: cmd /c "bat" "格式" "文件路径"
|
|
174
|
-
cmd = `"${batPath}" ${fmt.verb}`;
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
cmd = `"${cisCmd}" -t ${fmt.verb} ${menu.arg}`;
|
|
178
|
-
}
|
|
179
|
-
(0, child_process_1.execSync)(`reg add "${shellKey}" /ve /d "${fmt.label}" /f`, { stdio: 'ignore' });
|
|
180
|
-
(0, child_process_1.execSync)(`reg add "${shellKey}" /v Icon /d "${iconPath}" /f`, { stdio: 'ignore' });
|
|
181
|
-
// 直接调用 bat,不需要 cmd /c,Windows 会自动追加文件路径
|
|
182
|
-
(0, child_process_1.execSync)(`reg add "${shellKey}\\command" /ve /d "${cmd}" /f`, { stdio: 'ignore' });
|
|
142
|
+
// 注册主菜单项
|
|
143
|
+
execSync(`reg add "${menu.base}" /ve /d "🖼 转换图片 (cis)" /f`, { stdio: 'ignore' });
|
|
144
|
+
execSync(`reg add "${menu.base}" /v Icon /d "${iconPath}" /f`, { stdio: 'ignore' });
|
|
145
|
+
if (menu.multiSelect) {
|
|
146
|
+
execSync(`reg add "${menu.base}" /v MultiSelectModel /d Player /f`, { stdio: 'ignore' });
|
|
183
147
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
// 使用 bat 的菜单(文件右键和目录右键):设置 command 接收文件路径 %1
|
|
191
|
-
// Windows 会将父命令收到的 %1 自动传递给子命令
|
|
192
|
-
if (menu.useBat) {
|
|
193
|
-
(0, child_process_1.execSync)(`reg add "${menu.base}\\command" /ve /d "cmd /c echo %1 > nul" /f`, { stdio: 'ignore' });
|
|
194
|
-
// 注意:不添加 AppliesTo 限制,让菜单始终显示
|
|
195
|
-
// bat 脚本会检查文件扩展名,自动忽略非图片文件
|
|
148
|
+
// 注册格式子菜单(inline shell 子键,确保参数正确传递)
|
|
149
|
+
for (const fmt of formats) {
|
|
150
|
+
const subKey = `${menu.base}\\shell\\${fmt.verb}`;
|
|
151
|
+
execSync(`reg add "${subKey}" /ve /d "${fmt.label}" /f`, { stdio: 'ignore' });
|
|
152
|
+
execSync(`reg add "${subKey}" /v Icon /d "${iconPath}" /f`, { stdio: 'ignore' });
|
|
153
|
+
execSync(`reg add "${subKey}\\command" /ve /d "${menu.cmd(fmt.verb)}" /f`, { stdio: 'ignore' });
|
|
196
154
|
}
|
|
197
155
|
}
|
|
198
156
|
// 写入版本标记,用于检测 npm update 后自动刷新菜单
|
|
@@ -216,19 +174,7 @@ function uninstallContextMenu() {
|
|
|
216
174
|
];
|
|
217
175
|
for (const key of mainKeys) {
|
|
218
176
|
try {
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
catch { /* ignore */ }
|
|
222
|
-
}
|
|
223
|
-
// 删除公共子菜单(三个:目录空白、目录图标、文件)
|
|
224
|
-
const subMenuRoots = [
|
|
225
|
-
'HKCU\\Software\\Classes\\Directory\\ContextMenus\\cis',
|
|
226
|
-
'HKCU\\Software\\Classes\\Directory\\ContextMenus\\cis_dir',
|
|
227
|
-
'HKCU\\Software\\Classes\\Directory\\ContextMenus\\cis_file',
|
|
228
|
-
];
|
|
229
|
-
for (const root of subMenuRoots) {
|
|
230
|
-
try {
|
|
231
|
-
(0, child_process_1.execSync)(`reg delete "${root}" /f`, { stdio: 'ignore' });
|
|
177
|
+
execSync(`reg delete "${key}" /f`, { stdio: 'ignore' });
|
|
232
178
|
}
|
|
233
179
|
catch { /* ignore */ }
|
|
234
180
|
}
|
|
@@ -543,7 +489,7 @@ async function convertImage(inputPath, targetFormat, allInputFiles) {
|
|
|
543
489
|
fs.copyFileSync(inputPath, outputPath);
|
|
544
490
|
return { success: true, outputPath };
|
|
545
491
|
}
|
|
546
|
-
const image = (
|
|
492
|
+
const image = sharp(inputPath);
|
|
547
493
|
switch (fmt) {
|
|
548
494
|
case 'webp':
|
|
549
495
|
await image.webp({ quality: 90 }).toFile(outputPath);
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "change-image-suffix",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.6",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"description": "批量转换图片格式的CLI工具,支持递归搜索、深度限制、指定后缀、Windows右键菜单等功能",
|
|
5
6
|
"main": "dist/index.js",
|
|
6
7
|
"files": [
|
|
@@ -9,8 +10,8 @@
|
|
|
9
10
|
"README.md",
|
|
10
11
|
"LICENSE",
|
|
11
12
|
"CHANGELOG.md",
|
|
12
|
-
"scripts/postinstall.
|
|
13
|
-
"scripts/preuninstall.
|
|
13
|
+
"scripts/postinstall.cjs",
|
|
14
|
+
"scripts/preuninstall.cjs"
|
|
14
15
|
],
|
|
15
16
|
"bin": {
|
|
16
17
|
"change-image-suffix": "./dist/index.js",
|
|
@@ -24,13 +25,13 @@
|
|
|
24
25
|
"clean": "rimraf dist",
|
|
25
26
|
"build": "tsc",
|
|
26
27
|
"dev": "tsc --watch",
|
|
27
|
-
"postinstall": "node scripts/postinstall.
|
|
28
|
-
"preuninstall": "node scripts/preuninstall.
|
|
28
|
+
"postinstall": "node scripts/postinstall.cjs",
|
|
29
|
+
"preuninstall": "node scripts/preuninstall.cjs",
|
|
29
30
|
"prepublishOnly": "npm run clean && npm run build",
|
|
30
|
-
"release": "node scripts/release.
|
|
31
|
-
"release:patch": "node scripts/release.
|
|
32
|
-
"release:minor": "node scripts/release.
|
|
33
|
-
"release:major": "node scripts/release.
|
|
31
|
+
"release": "node scripts/release.cjs",
|
|
32
|
+
"release:patch": "node scripts/release.cjs --patch",
|
|
33
|
+
"release:minor": "node scripts/release.cjs --minor",
|
|
34
|
+
"release:major": "node scripts/release.cjs --major",
|
|
34
35
|
"lint": "tsc --noEmit",
|
|
35
36
|
"typecheck": "tsc --noEmit"
|
|
36
37
|
},
|
|
@@ -56,19 +57,19 @@
|
|
|
56
57
|
},
|
|
57
58
|
"homepage": "https://github.com/GuoSirius/change-image-suffix#readme",
|
|
58
59
|
"dependencies": {
|
|
59
|
-
"sharp": "^0.
|
|
60
|
+
"sharp": "^0.34.5"
|
|
60
61
|
},
|
|
61
62
|
"devDependencies": {
|
|
62
63
|
"@commitlint/cli": "^21.0.1",
|
|
63
64
|
"@commitlint/config-conventional": "^21.0.1",
|
|
64
|
-
"@types/node": "^
|
|
65
|
+
"@types/node": "^25.9.1",
|
|
65
66
|
"enquirer": "^2.4.1",
|
|
66
67
|
"husky": "^9.1.7",
|
|
67
68
|
"rimraf": "^6.1.3",
|
|
68
69
|
"standard-version": "^9.5.0",
|
|
69
|
-
"typescript": "^
|
|
70
|
+
"typescript": "^6.0.3"
|
|
70
71
|
},
|
|
71
72
|
"engines": {
|
|
72
|
-
"node": ">=
|
|
73
|
+
"node": ">=24.0.0"
|
|
73
74
|
}
|
|
74
75
|
}
|
|
File without changes
|
|
File without changes
|