zixulu 1.80.1 → 1.80.3

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/dist/index.js CHANGED
@@ -4865,23 +4865,10 @@ description:
4865
4865
  throw error;
4866
4866
  }
4867
4867
  }
4868
- const getEditorExtensions_userDir = homedir();
4869
- const editorExtensionCommandMap = {
4870
- Code: {
4871
- command: "code",
4872
- win32Command: "code.cmd",
4873
- win32Path: join(getEditorExtensions_userDir, "AppData/Local/Programs/Microsoft VS Code/bin/code.cmd")
4874
- },
4875
- Cursor: {
4876
- command: "cursor",
4877
- win32Command: "cursor.cmd",
4878
- win32Path: join(getEditorExtensions_userDir, "AppData/Local/Programs/cursor/resources/app/bin/cursor.cmd")
4879
- },
4880
- Antigravity: {
4881
- command: "antigravity",
4882
- win32Command: "antigravity.cmd",
4883
- win32Path: join(getEditorExtensions_userDir, "AppData/Local/Programs/Antigravity/bin/antigravity.cmd")
4884
- }
4868
+ const EditorExtensionCommandMap = {
4869
+ Code: "code",
4870
+ Cursor: "cursor",
4871
+ Antigravity: "antigravity"
4885
4872
  };
4886
4873
  async function canGetEditorExtensions({ editor }) {
4887
4874
  const command = getEditorExtensionCommand({
@@ -4895,11 +4882,7 @@ async function canGetEditorExtensions({ editor }) {
4895
4882
  }
4896
4883
  }
4897
4884
  function getEditorExtensionCommand({ editor }) {
4898
- const item = editorExtensionCommandMap[editor];
4899
- if ("win32" !== process.platform) return item.command;
4900
- if (item.win32Path && existsSync(item.win32Path)) return `"${item.win32Path}"`;
4901
- if (item.win32Command) return item.win32Command;
4902
- return item.command;
4885
+ return EditorExtensionCommandMap[editor];
4903
4886
  }
4904
4887
  async function getEditorExtensions({ source }) {
4905
4888
  let data = [];
@@ -5258,13 +5241,10 @@ async function getVscodeExtInfo(ext) {
5258
5241
  const reg = /^(.+?)\.(.+?)$/;
5259
5242
  const [, author, name] = ext.match(reg);
5260
5243
  let version;
5261
- const codeCommand = getEditorExtensionCommand({
5262
- editor: "Code"
5263
- });
5264
5244
  if ("ms-ceintl.vscode-language-pack-zh-hans" === ext) {
5265
5245
  const reg2 = /"Versions":(\[\{".+?\])/;
5266
5246
  const versions = JSON.parse(html.match(reg2)[1]);
5267
- const output = await execAsync(`${codeCommand} --version`);
5247
+ const output = await execAsync("code --version");
5268
5248
  const codeVersions = output.split("\n")[0].split(".").map(Number);
5269
5249
  const item = versions.find(({ version })=>version.split(".").map(Number).every((item, index)=>index >= 2 || item <= codeVersions[index])) ?? versions[0];
5270
5250
  version = item.version;
@@ -5287,10 +5267,7 @@ async function downloadVscodeExts(dir) {
5287
5267
  recursive: true
5288
5268
  });
5289
5269
  consola.start("正在获取 VS Code 扩展列表");
5290
- const codeCommand = getEditorExtensionCommand({
5291
- editor: "Code"
5292
- });
5293
- const extList = await execAsync(`${codeCommand} --list-extensions`);
5270
+ const extList = await execAsync("code --list-extensions");
5294
5271
  const exts = await Promise.all(extList.split(/[\n\r]/).filter(Boolean).filter((item)=>!item.startsWith("anysphere.")).map((ext)=>getVscodeExtInfo(ext)));
5295
5272
  const setting = await readZixuluSetting();
5296
5273
  const vscodeDownloadHistory = setting?.vscodeDownloadHistory;
@@ -5308,37 +5285,189 @@ async function downloadVscodeExts(dir) {
5308
5285
  await writeZixuluSetting(setting);
5309
5286
  await Promise.all(exts.filter((ext)=>exts2.exts.includes(ext.id)).map((ext)=>retry(()=>download_download(ext.url, dir, `${ext.id}-${ext.version}.vsix`), 4)));
5310
5287
  }
5311
- var syncVscode_VscodeSyncOption = /*#__PURE__*/ function(VscodeSyncOption) {
5312
- VscodeSyncOption["配置"] = "SETTING";
5313
- VscodeSyncOption["插件"] = "EXTENSION";
5314
- VscodeSyncOption["软件"] = "SOFTWARE";
5315
- VscodeSyncOption["PowerShell"] = "POWERSHELL";
5316
- return VscodeSyncOption;
5317
- }({});
5288
+ const VscodeSyncOption = {
5289
+ 配置: "SETTING",
5290
+ 插件: "EXTENSION",
5291
+ 软件: "SOFTWARE",
5292
+ PowerShell: "POWERSHELL"
5293
+ };
5294
+ function createSyncVscodeScript(options) {
5295
+ const needUserDir = options.includes(VscodeSyncOption.配置) || options.includes(VscodeSyncOption.PowerShell);
5296
+ return `// @ts-check
5297
+
5298
+ import { spawn } from "node:child_process"
5299
+ import { access, copyFile, mkdir, readdir, rm } from "node:fs/promises"
5300
+ import { homedir } from "node:os"
5301
+ import { delimiter, join } from "node:path"
5302
+
5303
+ /**
5304
+ * @param {string} path
5305
+ */
5306
+ async function pathExists(path) {
5307
+ try {
5308
+ await access(path)
5309
+ return true
5310
+ } catch {
5311
+ return false
5312
+ }
5313
+ }
5314
+
5315
+ // Windows 上优先查找 code.cmd,避免直接调用 Code.exe 打开编辑器窗口
5316
+ async function resolveCodeCli() {
5317
+ if (process.platform !== "win32") return "code"
5318
+
5319
+ const candidates = new Set()
5320
+ const localAppData = process.env.LOCALAPPDATA ?? join(homedir(), "AppData", "Local")
5321
+ const programFiles = process.env.ProgramFiles ?? "C:/Program Files"
5322
+ const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:/Program Files (x86)"
5323
+
5324
+ candidates.add(join(localAppData, "Programs", "Microsoft VS Code", "bin", "code.cmd"))
5325
+ candidates.add(join(programFiles, "Microsoft VS Code", "bin", "code.cmd"))
5326
+ candidates.add(join(programFilesX86, "Microsoft VS Code", "bin", "code.cmd"))
5327
+
5328
+ const pathDirs = process.env.PATH?.split(delimiter).filter(Boolean) ?? []
5329
+ for (const dir of pathDirs) {
5330
+ candidates.add(join(dir, "code.cmd"))
5331
+ candidates.add(join(dir, "code"))
5332
+ }
5333
+
5334
+ for (const candidate of candidates) {
5335
+ if (await pathExists(candidate)) return candidate
5336
+ }
5337
+
5338
+ throw new Error("未找到 VS Code 命令行工具,请先安装 VS Code,并确认安装时勾选了“添加到 PATH”")
5339
+ }
5340
+
5341
+ /**
5342
+ * @param {string} value
5343
+ */
5344
+ function quoteWindowsArg(value) {
5345
+ return "\\"" + value.replace(/"/g, "\\"\\"") + "\\""
5346
+ }
5347
+
5348
+ /**
5349
+ * @param {string[]} args
5350
+ * @param {string} output
5351
+ */
5352
+ function isCliCommandSuccessful(args, output) {
5353
+ if (args.includes("--install-extension")) return output.includes("was successfully installed.") || output.includes("is already installed.")
5354
+ if (args.includes("--uninstall-extension")) return output.includes("was successfully uninstalled.") || output.includes("is not installed.")
5355
+ return false
5356
+ }
5357
+
5358
+ /**
5359
+ * @param {Buffer | string} data
5360
+ * @param {string[]} chunks
5361
+ * @param {NodeJS.WriteStream} stream
5362
+ */
5363
+ function writeChildOutput(data, chunks, stream) {
5364
+ const text = data.toString()
5365
+ chunks.push(text)
5366
+ stream.write(text)
5367
+ }
5368
+
5369
+ /**
5370
+ * @param {string} command
5371
+ * @param {string[]} args
5372
+ */
5373
+ function spawnAsync(command, args) {
5374
+ return new Promise((resolve, reject) => {
5375
+ // Windows 不能直接 spawn .cmd 或 .bat 文件,需要交给 cmd.exe 执行
5376
+ const needCmdShell = process.platform === "win32" && /\\.(cmd|bat)$/i.test(command)
5377
+ const chunks = []
5378
+ const child = needCmdShell
5379
+ ? spawn(
5380
+ process.env.ComSpec ?? "cmd.exe",
5381
+ ["/d", "/s", "/c", "\\"" + quoteWindowsArg(command) + " " + args.map(quoteWindowsArg).join(" ") + "\\""],
5382
+ {
5383
+ stdio: ["ignore", "pipe", "pipe"],
5384
+ windowsVerbatimArguments: true,
5385
+ },
5386
+ )
5387
+ : spawn(command, args, { stdio: ["ignore", "pipe", "pipe"] })
5388
+
5389
+ child.stdout?.on("data", data => writeChildOutput(data, chunks, process.stdout))
5390
+ child.stderr?.on("data", data => writeChildOutput(data, chunks, process.stderr))
5391
+ child.on("error", reject)
5392
+ child.on("exit", code => {
5393
+ const output = chunks.join("")
5394
+
5395
+ if (code !== 0) {
5396
+ if (isCliCommandSuccessful(args, output)) {
5397
+ console.warn(\`VS Code 命令退出码为 \${code},但操作已完成,继续执行后续步骤\`)
5398
+ return resolve(0)
5399
+ }
5400
+
5401
+ return reject(new Error(\`Command failed with code \${code}: \${command} \${args.join(" ")}\`))
5402
+ }
5403
+
5404
+ resolve(0)
5405
+ })
5406
+ })
5407
+ }
5408
+
5409
+ async function main() {
5410
+ const workspaceDir = process.cwd()
5411
+ ${needUserDir ? ` const userDir = homedir()
5412
+ ` : ""}${options.includes(VscodeSyncOption.插件) ? ` const extensionsDir = join(workspaceDir, "extensions")
5413
+ const codeCli = await resolveCodeCli()
5414
+ const dir = await readdir(extensionsDir)
5415
+ const extensionErrors = []
5416
+ for (const ext of dir) {
5417
+ try {
5418
+ await spawnAsync(codeCli, ["--install-extension", join(extensionsDir, ext), "--force"])
5419
+ } catch (error) {
5420
+ const message = error instanceof Error ? error.message : String(error)
5421
+ extensionErrors.push(\`\${ext}: \${message}\`)
5422
+ console.error(\`扩展同步失败:\${ext}\`)
5423
+ }
5424
+ }
5425
+ if (extensionErrors.length > 0) {
5426
+ throw new Error(\`以下扩展同步失败:\\n\${extensionErrors.join("\\n")}\`)
5427
+ }
5428
+ ` : ""}${options.includes(VscodeSyncOption.配置) ? ` const codeUserDir = join(userDir, "AppData", "Roaming", "Code", "User")
5429
+ await mkdir(codeUserDir, { recursive: true })
5430
+ const setting = join(codeUserDir, "settings.json")
5431
+ await rm(setting, { force: true })
5432
+ await copyFile(join(workspaceDir, "settings.json"), setting)
5433
+ const snippetTarget = join(codeUserDir, "snippets")
5434
+ await mkdir(snippetTarget, { recursive: true })
5435
+ const dir2 = await readdir(join(workspaceDir, "snippets"))
5436
+ for (const file of dir2) {
5437
+ await rm(join(snippetTarget, file), { force: true })
5438
+ await copyFile(join(workspaceDir, "snippets", file), join(snippetTarget, file))
5439
+ }` : ""}${options.includes(VscodeSyncOption.PowerShell) ? `
5440
+ const profileDir = join(userDir, "Documents", "PowerShell")
5441
+ await mkdir(profileDir, { recursive: true })
5442
+ const profile = join(profileDir, "Microsoft.PowerShell_profile.ps1")
5443
+ await copyFile(join(workspaceDir, "Microsoft.PowerShell_profile.ps1"), profile)` : ""}
5444
+ }
5445
+
5446
+ main()
5447
+ `;
5448
+ }
5318
5449
  async function syncVscode() {
5319
- const codeCommand = getEditorExtensionCommand({
5320
- editor: "Code"
5321
- });
5322
5450
  const options = (await inquirer_0.prompt({
5323
5451
  type: "checkbox",
5324
5452
  name: "options",
5325
5453
  message: "请选择要同步的内容",
5326
- choices: getEnumEntries(syncVscode_VscodeSyncOption).map(([name, value])=>({
5454
+ choices: getEnumEntries(VscodeSyncOption).map(([name, value])=>({
5327
5455
  name,
5328
5456
  value
5329
5457
  })),
5330
- default: getEnumValues(syncVscode_VscodeSyncOption)
5458
+ default: getEnumValues(VscodeSyncOption)
5331
5459
  })).options;
5332
5460
  if (0 === options.length) return;
5333
5461
  const userDir = homedir();
5334
- const snippetSource = join(userDir, "AppData/Roaming/Code/User/snippets");
5335
- const setting = (await readFile(join(userDir, "AppData/Roaming/Code/User/settings.json"), "utf-8")).replace(/}[ \n\r]*$/, ` "chat.disableAIFeatures": true,\n}`);
5462
+ const codeUserDir = join(userDir, "AppData", "Roaming", "Code", "User");
5463
+ const snippetSource = join(codeUserDir, "snippets");
5464
+ const setting = (await readFile(join(codeUserDir, "settings.json"), "utf-8")).replace(/}[ \n\r]*$/, ` "chat.disableAIFeatures": true,\n}`);
5336
5465
  const dir = `vscode-${dayjs().format("YYYYMMDDHHmmss")}`;
5337
5466
  try {
5338
5467
  await mkdir(dir, {
5339
5468
  recursive: true
5340
5469
  });
5341
- if (options.includes("SETTING")) {
5470
+ if (options.includes(VscodeSyncOption.配置)) {
5342
5471
  const snippetTarget = join(dir, "snippets");
5343
5472
  await mkdir(snippetTarget, {
5344
5473
  recursive: true
@@ -5349,62 +5478,20 @@ async function syncVscode() {
5349
5478
  for (const file of files)await copyFile(join(snippetSource, file), join(snippetTarget, file));
5350
5479
  consola.success("下载最新 VSCode 配置完成");
5351
5480
  }
5352
- if (options.includes("EXTENSION")) {
5481
+ if (options.includes(VscodeSyncOption.插件)) {
5353
5482
  await downloadVscodeExts(join(dir, "extensions"));
5354
5483
  consola.success("下载最新 VSCode 插件完成");
5355
5484
  }
5356
- if (options.includes("SETTING") || options.includes("EXTENSION")) {
5357
- const script = `// @ts-check
5358
-
5359
- import { spawn } from "node:child_process"
5360
- import { readdir, copyFile, rm } from "node:fs/promises"
5361
- import { homedir } from "node:os"
5362
- import { join } from "node:path"
5363
-
5364
- const codeCommand = ${JSON.stringify(codeCommand)}
5365
-
5366
- /**
5367
- * @param {string} command
5368
- */
5369
- function spawnAsync(command) {
5370
- return new Promise((resolve, reject) => {
5371
- const child = spawn(command, { shell: true, stdio: "inherit" })
5372
- child.on("exit", code => {
5373
- if (code !== 0) return reject(new Error(\`Command failed with code \${code}\`))
5374
- resolve(0)
5375
- })
5376
- })
5377
- }
5378
-
5379
- async function main() {
5380
- ${options.includes("EXTENSION") ? ` const dir = await readdir("./extensions")
5381
- for (const ext of dir) {
5382
- await spawnAsync(\`\${codeCommand} --install-extension "./extensions/\${ext}"\`)
5383
- }
5384
- ` : ""}${options.includes("SETTING") ? ` const userDir = homedir()
5385
- const setting = join(userDir, "AppData/Roaming/Code/User/settings.json")
5386
- await rm(setting, { force: true })
5387
- await copyFile("./settings.json", setting)
5388
- const snippetTarget = join(userDir, "AppData/Roaming/Code/User/snippets")
5389
- const dir2 = await readdir("./snippets")
5390
- for (const file of dir2) {
5391
- await rm(join(snippetTarget, file), { force: true })
5392
- await copyFile(join("./snippets", file), join(snippetTarget, file))
5393
- }` : ""}${options.includes("POWERSHELL") ? `
5394
- ${options.includes("SETTING") ? "" : `const userDir = homedir()
5395
- `}const profile = join(userDir, "Documents/PowerShell/Microsoft.PowerShell_profile.ps1")
5396
- await copyFile("./Microsoft.PowerShell_profile.ps1", profile)` : ""}
5397
- }
5398
-
5399
- main()`;
5485
+ if (options.includes(VscodeSyncOption.配置) || options.includes(VscodeSyncOption.插件) || options.includes(VscodeSyncOption.PowerShell)) {
5486
+ const script = createSyncVscodeScript(options);
5400
5487
  await writeFile(join(dir, "syncVscode.mjs"), script, "utf-8");
5401
5488
  }
5402
- if (options.includes("SOFTWARE")) {
5489
+ if (options.includes(VscodeSyncOption.软件)) {
5403
5490
  consola.start("开始下载最新 VSCode");
5404
5491
  await download_download("https://code.visualstudio.com/sha/download?build=stable&os=win32-x64", dir);
5405
5492
  consola.success("下载最新 VSCode 完成");
5406
5493
  }
5407
- if (options.includes("POWERSHELL")) {
5494
+ if (options.includes(VscodeSyncOption.PowerShell)) {
5408
5495
  consola.start("开始同步 PowerShell 配置");
5409
5496
  const userDir = homedir();
5410
5497
  const profile = join(userDir, "Documents/PowerShell/Microsoft.PowerShell_profile.ps1");