juice-email-cli 2.1.10 → 2.1.12

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/context-menu.js +37 -28
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "juice-email-cli",
3
- "version": "2.1.10",
3
+ "version": "2.1.12",
4
4
  "description": "CLI tool to generate email-client-compatible HTML with juice (CSS inlining) + Mustache templating + minification",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -14,7 +14,8 @@
14
14
  * └── 📂 打开 PowerShell (可选)
15
15
  */
16
16
 
17
- const { execSync } = require('child_process');
17
+ const { spawnSync } = require('child_process');
18
+ const fs = require('fs');
18
19
  const path = require('path');
19
20
  const chalk = require('chalk');
20
21
 
@@ -34,41 +35,38 @@ function getIconPath() {
34
35
 
35
36
  // ─── 注册表操作封装 ───────────────────────────────────────────────────────────
36
37
 
38
+ const isWindows = process.platform === 'win32';
39
+
37
40
  /**
38
- * 执行 reg add,失败时打印警告而不中断
41
+ * 执行 reg add — 使用 spawnSync 直接调用 reg.exe,避免 cmd.exe 解析特殊字符
39
42
  */
40
43
  function regAdd(key, valueName, type, data) {
41
- const vFlag = valueName === '' ? '/ve' : `/v "${valueName}"`;
42
- const tFlag = type ? `/t ${type}` : '';
43
- const dFlag = data !== undefined ? `/d "${escapeRegData(data)}"` : '';
44
- const cmd = `reg add "${key}" ${vFlag} ${tFlag} ${dFlag} /f`.replace(/\s+/g, ' ').trim();
45
- try {
46
- execSync(cmd, { stdio: 'pipe' });
47
- return true;
48
- } catch (e) {
49
- const msg = e.stderr ? e.stderr.toString().trim() : e.message;
50
- console.warn(chalk.yellow(` ⚠ reg add 失败\n 键:${key}\n 原因:${msg}`));
51
- return false;
44
+ if (!isWindows) return false;
45
+ const args = ['add', key, '/f'];
46
+ if (valueName === '') {
47
+ args.push('/ve');
48
+ } else {
49
+ args.push('/v', valueName);
52
50
  }
53
- }
51
+ if (type) args.push('/t', type);
52
+ if (data !== undefined) args.push('/d', data);
54
53
 
55
- /**
56
- * 执行 reg delete,键不存在时静默忽略,返回是否实际删除了
57
- */
58
- function regDelete(key) {
59
- try {
60
- execSync(`reg delete "${key}" /f`, { stdio: 'pipe' });
61
- return true;
62
- } catch (_) {
54
+ const result = spawnSync('reg', args, { stdio: 'pipe' });
55
+ if (result.status !== 0) {
56
+ const msg = (result.stderr || '').toString().trim();
57
+ console.warn(chalk.yellow(` ⚠ reg add 失败\n 键:${key}\n 原因:${msg}`));
63
58
  return false;
64
59
  }
60
+ return true;
65
61
  }
66
62
 
67
63
  /**
68
- * 转义注册表数据中的特殊字符
64
+ * 执行 reg delete — 键不存在时静默忽略
69
65
  */
70
- function escapeRegData(str) {
71
- return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/%/g, '%%');
66
+ function regDelete(key) {
67
+ if (!isWindows) return false;
68
+ const result = spawnSync('reg', ['delete', key, '/f'], { stdio: 'pipe' });
69
+ return result.status === 0;
72
70
  }
73
71
 
74
72
  // ─── 菜单结构常量 ─────────────────────────────────────────────────────────────
@@ -126,6 +124,11 @@ function wrapInteractive(nodePath, scriptPath, cliArgs) {
126
124
  // ─── 注册 ─────────────────────────────────────────────────────────────────────
127
125
 
128
126
  async function registerContextMenu() {
127
+ if (!isWindows) {
128
+ console.log(chalk.gray(' 右键菜单仅支持 Windows,已跳过。\n'));
129
+ return;
130
+ }
131
+
129
132
  console.log(chalk.cyan('\n 注册 juice 右键菜单(当前用户,无需管理员权限)...\n'));
130
133
 
131
134
  const nodePath = getNodePath();
@@ -204,6 +207,11 @@ async function registerContextMenu() {
204
207
  // ─── 取消注册 ─────────────────────────────────────────────────────────────────
205
208
 
206
209
  async function unregisterContextMenu() {
210
+ if (!isWindows) {
211
+ console.log(chalk.gray(' 右键菜单仅支持 Windows,已跳过。\n'));
212
+ return;
213
+ }
214
+
207
215
  console.log(chalk.cyan('\n 取消注册 juice 右键菜单...\n'));
208
216
 
209
217
  let removed = 0;
@@ -239,11 +247,12 @@ function resolvePwsh() {
239
247
  path.join(process.env['LOCALAPPDATA'] || '', 'Microsoft', 'PowerShell', 'pwsh.exe'),
240
248
  ];
241
249
  for (const p of candidates) {
242
- if (require('fs').existsSync(p)) return p;
250
+ if (fs.existsSync(p)) return p;
243
251
  }
244
252
  try {
245
- const result = execSync('where pwsh', { stdio: 'pipe' }).toString().trim().split('\n')[0].trim();
246
- if (result && require('fs').existsSync(result)) return result;
253
+ const result = spawnSync('where', ['pwsh'], { stdio: 'pipe' });
254
+ const line = result.stdout.toString().trim().split('\n')[0].trim();
255
+ if (line && fs.existsSync(line)) return line;
247
256
  } catch (_) {}
248
257
  return null;
249
258
  }