@spark-apps/piclet 1.0.4 → 1.0.5

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/cli.js CHANGED
@@ -1,10 +1,4 @@
1
1
  #!/usr/bin/env node
2
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
3
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
4
- }) : x)(function(x) {
5
- if (typeof require !== "undefined") return require.apply(this, arguments);
6
- throw Error('Dynamic require of "' + x + '" is not supported');
7
- });
8
2
 
9
3
  // src/cli.ts
10
4
  import chalk17 from "chalk";
@@ -46,14 +40,15 @@ ${renderLogo()}`);
46
40
  import chalk2 from "chalk";
47
41
 
48
42
  // src/tools/border.ts
49
- import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
43
+ import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
50
44
  import { tmpdir } from "os";
51
- import { basename as basename2, join as join3 } from "path";
45
+ import { basename as basename2, join as join4 } from "path";
52
46
 
53
47
  // src/lib/gui-server.ts
54
48
  import { spawn } from "child_process";
49
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
55
50
  import { createServer } from "http";
56
- import { dirname as dirname2, join as join2 } from "path";
51
+ import { dirname as dirname2, extname, join as join2 } from "path";
57
52
  import { fileURLToPath } from "url";
58
53
  import express from "express";
59
54
 
@@ -506,14 +501,12 @@ function startGuiServer(options) {
506
501
  return;
507
502
  }
508
503
  try {
509
- const fs = __require("fs");
510
- const path = __require("path");
511
- if (!fs.existsSync(outputPath)) {
504
+ if (!existsSync2(outputPath)) {
512
505
  res.json({ success: false, error: "Output file not found" });
513
506
  return;
514
507
  }
515
- const buffer = fs.readFileSync(outputPath);
516
- const ext = path.extname(outputPath).toLowerCase();
508
+ const buffer = readFileSync2(outputPath);
509
+ const ext = extname(outputPath).toLowerCase();
517
510
  const mimeTypes = {
518
511
  ".png": "image/png",
519
512
  ".jpg": "image/jpeg",
@@ -632,7 +625,7 @@ function clearLine() {
632
625
 
633
626
  // src/lib/magick.ts
634
627
  import { exec } from "child_process";
635
- import { copyFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, unlinkSync } from "fs";
628
+ import { copyFileSync, existsSync as existsSync3, mkdirSync as mkdirSync2, unlinkSync } from "fs";
636
629
  import { dirname as dirname3 } from "path";
637
630
  import { promisify } from "util";
638
631
  var execAsync = promisify(exec);
@@ -822,14 +815,14 @@ async function createIcoFromMultiple(pngPaths, outputPath) {
822
815
  }
823
816
  function ensureDir(filePath) {
824
817
  const dir = dirname3(filePath);
825
- if (!existsSync2(dir)) {
818
+ if (!existsSync3(dir)) {
826
819
  mkdirSync2(dir, { recursive: true });
827
820
  }
828
821
  }
829
822
  function cleanup(...files) {
830
823
  for (const file of files) {
831
824
  try {
832
- if (existsSync2(file)) {
825
+ if (existsSync3(file)) {
833
826
  unlinkSync(file);
834
827
  }
835
828
  } catch {
@@ -1100,7 +1093,8 @@ async function simplifyGif(inputPath, outputPath, skipFactor) {
1100
1093
  }
1101
1094
 
1102
1095
  // src/lib/paths.ts
1103
- import { basename, dirname as dirname4, extname, resolve } from "path";
1096
+ import { existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
1097
+ import { basename, dirname as dirname4, extname as extname2, join as join3, resolve } from "path";
1104
1098
  function windowsToWsl(winPath) {
1105
1099
  if (winPath.startsWith("/mnt/")) {
1106
1100
  return winPath;
@@ -1131,7 +1125,7 @@ function normalizePath(inputPath) {
1131
1125
  function getFileInfo(filePath) {
1132
1126
  const dir = dirname4(filePath);
1133
1127
  const base = basename(filePath);
1134
- const ext = extname(filePath);
1128
+ const ext = extname2(filePath);
1135
1129
  const name = base.slice(0, -ext.length);
1136
1130
  return {
1137
1131
  dirname: dir,
@@ -1140,6 +1134,20 @@ function getFileInfo(filePath) {
1140
1134
  extension: ext
1141
1135
  };
1142
1136
  }
1137
+ function getOutputDir(inputPath) {
1138
+ const dir = dirname4(inputPath);
1139
+ if (basename(dir) === "PicLet") {
1140
+ return dir;
1141
+ }
1142
+ return join3(dir, "PicLet");
1143
+ }
1144
+ function ensureOutputDir(inputPath) {
1145
+ const outDir = getOutputDir(inputPath);
1146
+ if (!existsSync4(outDir)) {
1147
+ mkdirSync3(outDir, { recursive: true });
1148
+ }
1149
+ return outDir;
1150
+ }
1143
1151
 
1144
1152
  // src/lib/prompts.ts
1145
1153
  import prompts from "prompts";
@@ -1288,7 +1296,7 @@ async function run(inputRaw) {
1288
1296
  return false;
1289
1297
  }
1290
1298
  const input = normalizePath(inputRaw);
1291
- if (!existsSync3(input)) {
1299
+ if (!existsSync5(input)) {
1292
1300
  error(`File not found: ${input}`);
1293
1301
  await pauseOnError();
1294
1302
  return false;
@@ -1307,7 +1315,7 @@ async function run(inputRaw) {
1307
1315
  }
1308
1316
  async function runGUI(inputRaw) {
1309
1317
  const input = normalizePath(inputRaw);
1310
- if (!existsSync3(input)) {
1318
+ if (!existsSync5(input)) {
1311
1319
  error(`File not found: ${input}`);
1312
1320
  return false;
1313
1321
  }
@@ -1375,8 +1383,8 @@ async function runGUI(inputRaw) {
1375
1383
  async function generatePreview(input, options) {
1376
1384
  const tempDir = tmpdir();
1377
1385
  const timestamp = Date.now();
1378
- const tempSource = join3(tempDir, `piclet-preview-${timestamp}-src.png`);
1379
- const tempOutput = join3(tempDir, `piclet-preview-${timestamp}.png`);
1386
+ const tempSource = join4(tempDir, `piclet-preview-${timestamp}-src.png`);
1387
+ const tempOutput = join4(tempDir, `piclet-preview-${timestamp}.png`);
1380
1388
  try {
1381
1389
  let previewInput = input;
1382
1390
  if (isMultiFrame(input)) {
@@ -1390,7 +1398,7 @@ async function generatePreview(input, options) {
1390
1398
  cleanup(tempSource, tempOutput);
1391
1399
  return { success: false, error: "Border failed" };
1392
1400
  }
1393
- const buffer = readFileSync2(tempOutput);
1401
+ const buffer = readFileSync3(tempOutput);
1394
1402
  const base64 = buffer.toString("base64");
1395
1403
  const imageData = `data:image/png;base64,${base64}`;
1396
1404
  const dims = await getDimensions(tempOutput);
@@ -1413,16 +1421,10 @@ var config = {
1413
1421
  extensions: [".png", ".jpg", ".jpeg", ".gif", ".bmp"]
1414
1422
  };
1415
1423
 
1416
- // src/cli/utils.ts
1417
- import { extname as extname3 } from "path";
1418
- import { dirname as dirname9 } from "path";
1419
- import { fileURLToPath as fileURLToPath2 } from "url";
1420
- import chalk from "chalk";
1421
-
1422
1424
  // src/tools/extract-frames.ts
1423
- import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync3 } from "fs";
1425
+ import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync4 } from "fs";
1424
1426
  import { tmpdir as tmpdir2 } from "os";
1425
- import { basename as basename3, join as join4 } from "path";
1427
+ import { basename as basename3, join as join5 } from "path";
1426
1428
  async function run2(inputRaw) {
1427
1429
  if (!await checkImageMagick()) {
1428
1430
  error("ImageMagick not found. Please install it:");
@@ -1431,7 +1433,7 @@ async function run2(inputRaw) {
1431
1433
  return false;
1432
1434
  }
1433
1435
  const input = normalizePath(inputRaw);
1434
- if (!existsSync4(input)) {
1436
+ if (!existsSync6(input)) {
1435
1437
  error(`File not found: ${input}`);
1436
1438
  await pauseOnError();
1437
1439
  return false;
@@ -1462,7 +1464,7 @@ async function run2(inputRaw) {
1462
1464
  const outputDir = `${fileInfo.dirname}/${fileInfo.filename}_frames`;
1463
1465
  console.log("");
1464
1466
  wip("Extracting frames...");
1465
- mkdirSync3(outputDir, { recursive: true });
1467
+ mkdirSync4(outputDir, { recursive: true });
1466
1468
  const frames = await extractAllFrames(input, outputDir, "frame");
1467
1469
  if (frames.length === 0) {
1468
1470
  wipDone(false, "Extraction failed");
@@ -1475,7 +1477,7 @@ async function run2(inputRaw) {
1475
1477
  }
1476
1478
  async function runGUI2(inputRaw) {
1477
1479
  const input = normalizePath(inputRaw);
1478
- if (!existsSync4(input)) {
1480
+ if (!existsSync6(input)) {
1479
1481
  error(`File not found: ${input}`);
1480
1482
  return false;
1481
1483
  }
@@ -1514,7 +1516,7 @@ async function runGUI2(inputRaw) {
1514
1516
  }
1515
1517
  logs.push({ type: "info", message: `Extracting ${frameCount} frames...` });
1516
1518
  const outputDir = `${fileInfo.dirname}/${fileInfo.filename}_frames`;
1517
- mkdirSync3(outputDir, { recursive: true });
1519
+ mkdirSync4(outputDir, { recursive: true });
1518
1520
  const frames = await extractAllFrames(input, outputDir, "frame");
1519
1521
  if (frames.length > 0) {
1520
1522
  logs.push({ type: "success", message: `Extracted ${frames.length} frames` });
@@ -1532,12 +1534,12 @@ async function runGUI2(inputRaw) {
1532
1534
  async function generateFramePreview(input, frameIndex) {
1533
1535
  const tempDir = tmpdir2();
1534
1536
  const timestamp = Date.now();
1535
- const tempOutput = join4(tempDir, `piclet-frame-${timestamp}.png`);
1537
+ const tempOutput = join5(tempDir, `piclet-frame-${timestamp}.png`);
1536
1538
  try {
1537
1539
  if (!await extractFirstFrame(input, tempOutput, frameIndex)) {
1538
1540
  return { success: false, error: "Failed to extract frame" };
1539
1541
  }
1540
- const buffer = readFileSync3(tempOutput);
1542
+ const buffer = readFileSync4(tempOutput);
1541
1543
  const base64 = buffer.toString("base64");
1542
1544
  const imageData = `data:image/png;base64,${base64}`;
1543
1545
  const dims = await getDimensions(tempOutput);
@@ -1561,9 +1563,9 @@ var config2 = {
1561
1563
  };
1562
1564
 
1563
1565
  // src/tools/filter.ts
1564
- import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
1566
+ import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
1565
1567
  import { tmpdir as tmpdir3 } from "os";
1566
- import { basename as basename4, join as join5 } from "path";
1568
+ import { basename as basename4, join as join6 } from "path";
1567
1569
  var FILTER_LABELS = {
1568
1570
  "grayscale": "Grayscale",
1569
1571
  "sepia": "Sepia",
@@ -1637,7 +1639,7 @@ async function run3(inputRaw) {
1637
1639
  return false;
1638
1640
  }
1639
1641
  const input = normalizePath(inputRaw);
1640
- if (!existsSync5(input)) {
1642
+ if (!existsSync7(input)) {
1641
1643
  error(`File not found: ${input}`);
1642
1644
  await pauseOnError();
1643
1645
  return false;
@@ -1656,7 +1658,7 @@ async function run3(inputRaw) {
1656
1658
  }
1657
1659
  async function runGUI3(inputRaw) {
1658
1660
  const input = normalizePath(inputRaw);
1659
- if (!existsSync5(input)) {
1661
+ if (!existsSync7(input)) {
1660
1662
  error(`File not found: ${input}`);
1661
1663
  return false;
1662
1664
  }
@@ -1721,8 +1723,8 @@ async function runGUI3(inputRaw) {
1721
1723
  async function generatePreview2(input, options) {
1722
1724
  const tempDir = tmpdir3();
1723
1725
  const timestamp = Date.now();
1724
- const tempSource = join5(tempDir, `piclet-preview-${timestamp}-src.png`);
1725
- const tempOutput = join5(tempDir, `piclet-preview-${timestamp}.png`);
1726
+ const tempSource = join6(tempDir, `piclet-preview-${timestamp}-src.png`);
1727
+ const tempOutput = join6(tempDir, `piclet-preview-${timestamp}.png`);
1726
1728
  try {
1727
1729
  let previewInput = input;
1728
1730
  if (isMultiFrame(input)) {
@@ -1736,7 +1738,7 @@ async function generatePreview2(input, options) {
1736
1738
  cleanup(tempSource, tempOutput);
1737
1739
  return { success: false, error: "Filter failed" };
1738
1740
  }
1739
- const buffer = readFileSync4(tempOutput);
1741
+ const buffer = readFileSync5(tempOutput);
1740
1742
  const base64 = buffer.toString("base64");
1741
1743
  const imageData = `data:image/png;base64,${base64}`;
1742
1744
  const dims = await getDimensions(tempOutput);
@@ -1760,7 +1762,7 @@ var config3 = {
1760
1762
  };
1761
1763
 
1762
1764
  // src/tools/iconpack.ts
1763
- import { existsSync as existsSync6, mkdirSync as mkdirSync4 } from "fs";
1765
+ import { existsSync as existsSync8, mkdirSync as mkdirSync5 } from "fs";
1764
1766
  import { basename as basename5, dirname as dirname5 } from "path";
1765
1767
  var WEB_ICONS = [
1766
1768
  { filename: "favicon-16x16.png", size: 16 },
@@ -1811,8 +1813,8 @@ async function generateIcons(outputDir, sourceImg, icons) {
1811
1813
  current++;
1812
1814
  const outputPath = `${outputDir}/${icon.filename}`;
1813
1815
  const subdir = dirname5(outputPath);
1814
- if (!existsSync6(subdir)) {
1815
- mkdirSync4(subdir, { recursive: true });
1816
+ if (!existsSync8(subdir)) {
1817
+ mkdirSync5(subdir, { recursive: true });
1816
1818
  }
1817
1819
  clearLine();
1818
1820
  wip(`[${current}/${total}] Generating ${icon.filename}...`);
@@ -1857,7 +1859,7 @@ async function run4(inputRaw) {
1857
1859
  return false;
1858
1860
  }
1859
1861
  const input = normalizePath(inputRaw);
1860
- if (!existsSync6(input)) {
1862
+ if (!existsSync8(input)) {
1861
1863
  error(`File not found: ${input}`);
1862
1864
  await pauseOnError();
1863
1865
  return false;
@@ -1899,7 +1901,7 @@ async function run4(inputRaw) {
1899
1901
  const doAndroid = platforms.includes("android");
1900
1902
  const doIos = platforms.includes("ios");
1901
1903
  const outputDir = `${fileInfo.dirname}/${fileInfo.filename}_icons`;
1902
- mkdirSync4(outputDir, { recursive: true });
1904
+ mkdirSync5(outputDir, { recursive: true });
1903
1905
  info(`Output directory: ${outputDir}`);
1904
1906
  console.log("");
1905
1907
  wip("Preparing source image...");
@@ -1921,7 +1923,7 @@ async function run4(inputRaw) {
1921
1923
  console.log("");
1922
1924
  header("Web Icons");
1923
1925
  const webDir = `${outputDir}/web`;
1924
- mkdirSync4(webDir, { recursive: true });
1926
+ mkdirSync5(webDir, { recursive: true });
1925
1927
  if (!await generateFavicon(webDir, tempSource)) {
1926
1928
  totalFailed++;
1927
1929
  }
@@ -1931,14 +1933,14 @@ async function run4(inputRaw) {
1931
1933
  console.log("");
1932
1934
  header("Android Icons");
1933
1935
  const androidDir = `${outputDir}/android`;
1934
- mkdirSync4(androidDir, { recursive: true });
1936
+ mkdirSync5(androidDir, { recursive: true });
1935
1937
  totalFailed += await generateIcons(androidDir, tempSource, ANDROID_ICONS);
1936
1938
  }
1937
1939
  if (doIos) {
1938
1940
  console.log("");
1939
1941
  header("iOS Icons");
1940
1942
  const iosDir = `${outputDir}/ios`;
1941
- mkdirSync4(iosDir, { recursive: true });
1943
+ mkdirSync5(iosDir, { recursive: true });
1942
1944
  totalFailed += await generateIcons(iosDir, tempSource, IOS_ICONS);
1943
1945
  }
1944
1946
  cleanup(tempSource);
@@ -1964,7 +1966,7 @@ async function run4(inputRaw) {
1964
1966
  }
1965
1967
  async function runGUI4(inputRaw) {
1966
1968
  const input = normalizePath(inputRaw);
1967
- if (!existsSync6(input)) {
1969
+ if (!existsSync8(input)) {
1968
1970
  error(`File not found: ${input}`);
1969
1971
  return false;
1970
1972
  }
@@ -2009,7 +2011,7 @@ async function runGUI4(inputRaw) {
2009
2011
  };
2010
2012
  }
2011
2013
  const outputDir = `${fileInfo.dirname}/${fileInfo.filename}_icons`;
2012
- mkdirSync4(outputDir, { recursive: true });
2014
+ mkdirSync5(outputDir, { recursive: true });
2013
2015
  logs.push({ type: "info", message: `Output: ${outputDir}` });
2014
2016
  logs.push({ type: "info", message: "Preparing source image..." });
2015
2017
  const tempSource = `${outputDir}/.source_1024.png`;
@@ -2027,7 +2029,7 @@ async function runGUI4(inputRaw) {
2027
2029
  if (doWeb) {
2028
2030
  logs.push({ type: "info", message: "Generating Web icons..." });
2029
2031
  const webDir = `${outputDir}/web`;
2030
- mkdirSync4(webDir, { recursive: true });
2032
+ mkdirSync5(webDir, { recursive: true });
2031
2033
  if (!await generateFaviconSilent(webDir, tempSource)) {
2032
2034
  totalFailed++;
2033
2035
  }
@@ -2037,14 +2039,14 @@ async function runGUI4(inputRaw) {
2037
2039
  if (doAndroid) {
2038
2040
  logs.push({ type: "info", message: "Generating Android icons..." });
2039
2041
  const androidDir = `${outputDir}/android`;
2040
- mkdirSync4(androidDir, { recursive: true });
2042
+ mkdirSync5(androidDir, { recursive: true });
2041
2043
  totalFailed += await generateIconsSilent(androidDir, tempSource, ANDROID_ICONS, logs);
2042
2044
  logs.push({ type: "success", message: `Android: ${ANDROID_ICONS.length} icons` });
2043
2045
  }
2044
2046
  if (doIos) {
2045
2047
  logs.push({ type: "info", message: "Generating iOS icons..." });
2046
2048
  const iosDir = `${outputDir}/ios`;
2047
- mkdirSync4(iosDir, { recursive: true });
2049
+ mkdirSync5(iosDir, { recursive: true });
2048
2050
  totalFailed += await generateIconsSilent(iosDir, tempSource, IOS_ICONS, logs);
2049
2051
  logs.push({ type: "success", message: `iOS: ${IOS_ICONS.length} icons` });
2050
2052
  }
@@ -2069,8 +2071,8 @@ async function generateIconsSilent(outputDir, sourceImg, icons, _logs) {
2069
2071
  for (const icon of icons) {
2070
2072
  const outputPath = `${outputDir}/${icon.filename}`;
2071
2073
  const subdir = dirname5(outputPath);
2072
- if (!existsSync6(subdir)) {
2073
- mkdirSync4(subdir, { recursive: true });
2074
+ if (!existsSync8(subdir)) {
2075
+ mkdirSync5(subdir, { recursive: true });
2074
2076
  }
2075
2077
  if (!await scaleToSize(sourceImg, outputPath, icon.size)) {
2076
2078
  failed++;
@@ -2100,9 +2102,9 @@ var config4 = {
2100
2102
  };
2101
2103
 
2102
2104
  // src/tools/makeicon.ts
2103
- import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
2105
+ import { existsSync as existsSync9, readFileSync as readFileSync6 } from "fs";
2104
2106
  import { tmpdir as tmpdir4 } from "os";
2105
- import { basename as basename6, join as join6 } from "path";
2107
+ import { basename as basename6, join as join7 } from "path";
2106
2108
  async function run5(inputRaw) {
2107
2109
  if (!await checkImageMagick()) {
2108
2110
  error("ImageMagick not found. Please install it:");
@@ -2111,7 +2113,7 @@ async function run5(inputRaw) {
2111
2113
  return false;
2112
2114
  }
2113
2115
  const input = normalizePath(inputRaw);
2114
- if (!existsSync7(input)) {
2116
+ if (!existsSync9(input)) {
2115
2117
  error(`File not found: ${input}`);
2116
2118
  await pauseOnError();
2117
2119
  return false;
@@ -2209,9 +2211,9 @@ async function processForIcon(input, output, options, logs) {
2209
2211
  async function generatePreview3(input, options) {
2210
2212
  const tempDir = tmpdir4();
2211
2213
  const timestamp = Date.now();
2212
- const tempTrimmed = join6(tempDir, `piclet-preview-trimmed-${timestamp}.png`);
2213
- const tempSquare = join6(tempDir, `piclet-preview-square-${timestamp}.png`);
2214
- const tempOutput = join6(tempDir, `piclet-preview-${timestamp}.png`);
2214
+ const tempTrimmed = join7(tempDir, `piclet-preview-trimmed-${timestamp}.png`);
2215
+ const tempSquare = join7(tempDir, `piclet-preview-square-${timestamp}.png`);
2216
+ const tempOutput = join7(tempDir, `piclet-preview-${timestamp}.png`);
2215
2217
  try {
2216
2218
  let currentInput = input;
2217
2219
  if (options.trim) {
@@ -2235,7 +2237,7 @@ async function generatePreview3(input, options) {
2235
2237
  }
2236
2238
  if (currentInput === tempSquare) cleanup(tempSquare);
2237
2239
  else if (currentInput === tempTrimmed) cleanup(tempTrimmed);
2238
- const buffer = readFileSync5(tempOutput);
2240
+ const buffer = readFileSync6(tempOutput);
2239
2241
  const base64 = buffer.toString("base64");
2240
2242
  const imageData = `data:image/png;base64,${base64}`;
2241
2243
  const dims = await getDimensions(tempOutput);
@@ -2253,7 +2255,7 @@ async function generatePreview3(input, options) {
2253
2255
  }
2254
2256
  async function runGUI5(inputRaw) {
2255
2257
  const input = normalizePath(inputRaw);
2256
- if (!existsSync7(input)) {
2258
+ if (!existsSync9(input)) {
2257
2259
  error(`File not found: ${input}`);
2258
2260
  return false;
2259
2261
  }
@@ -2318,16 +2320,16 @@ var config5 = {
2318
2320
  };
2319
2321
 
2320
2322
  // src/tools/piclet-main.ts
2321
- import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync6, renameSync, writeFileSync as writeFileSync2 } from "fs";
2323
+ import { existsSync as existsSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync7, renameSync, writeFileSync as writeFileSync2 } from "fs";
2322
2324
  import { tmpdir as tmpdir5 } from "os";
2323
- import { basename as basename7, dirname as dirname6, extname as extname2, join as join7 } from "path";
2325
+ import { basename as basename7, dirname as dirname6, extname as extname3, join as join8 } from "path";
2324
2326
  var TOOL_ORDER = ["removebg", "scale", "icons", "storepack"];
2325
2327
  async function generateCombinedPreview(input, borderColor, opts) {
2326
2328
  const tempDir = tmpdir5();
2327
2329
  const ts = Date.now();
2328
2330
  const temps = [];
2329
2331
  const makeTempPath = (suffix) => {
2330
- const p = join7(tempDir, `piclet-${ts}-${suffix}.png`);
2332
+ const p = join8(tempDir, `piclet-${ts}-${suffix}.png`);
2331
2333
  temps.push(p);
2332
2334
  return p;
2333
2335
  };
@@ -2349,7 +2351,7 @@ async function generateCombinedPreview(input, borderColor, opts) {
2349
2351
  previewPath2 = scaled;
2350
2352
  }
2351
2353
  }
2352
- const buffer2 = readFileSync6(previewPath2);
2354
+ const buffer2 = readFileSync7(previewPath2);
2353
2355
  const finalDims2 = await getDimensions(previewPath2);
2354
2356
  cleanup(...temps);
2355
2357
  return {
@@ -2434,7 +2436,7 @@ async function generateCombinedPreview(input, borderColor, opts) {
2434
2436
  previewPath = scaled;
2435
2437
  }
2436
2438
  }
2437
- const buffer = readFileSync6(previewPath);
2439
+ const buffer = readFileSync7(previewPath);
2438
2440
  const finalDims = await getDimensions(previewPath);
2439
2441
  cleanup(...temps);
2440
2442
  return {
@@ -2504,7 +2506,8 @@ async function processCombined(input, borderColor, opts, logs) {
2504
2506
  current = out;
2505
2507
  }
2506
2508
  if (activeTools.indexOf(tool) === activeTools.length - 1) {
2507
- const finalOut = `${fileInfo.dirname}/${fileInfo.filename}_nobg${outputExt}`;
2509
+ const outDir = ensureOutputDir(input);
2510
+ const finalOut = join8(outDir, `${fileInfo.filename}_nobg${outputExt}`);
2508
2511
  renameSync(current, finalOut);
2509
2512
  temps.splice(temps.indexOf(current), 1);
2510
2513
  outputs.push(basename7(finalOut));
@@ -2536,7 +2539,8 @@ async function processCombined(input, borderColor, opts, logs) {
2536
2539
  }
2537
2540
  current = out;
2538
2541
  if (activeTools.indexOf(tool) === activeTools.length - 1) {
2539
- const finalOut = `${fileInfo.dirname}/${fileInfo.filename}_scaled${outputExt}`;
2542
+ const outDir = ensureOutputDir(input);
2543
+ const finalOut = join8(outDir, `${fileInfo.filename}_scaled${outputExt}`);
2540
2544
  renameSync(current, finalOut);
2541
2545
  temps.splice(temps.indexOf(current), 1);
2542
2546
  outputs.push(basename7(finalOut));
@@ -2580,7 +2584,8 @@ async function processCombined(input, borderColor, opts, logs) {
2580
2584
  let totalCount = 0;
2581
2585
  if (icOpts.ico) {
2582
2586
  logs.push({ type: "info", message: "Creating ICO file..." });
2583
- const icoOut = `${fileInfo.dirname}/${fileInfo.filename}.ico`;
2587
+ const outDir = ensureOutputDir(input);
2588
+ const icoOut = join8(outDir, `${fileInfo.filename}.ico`);
2584
2589
  if (await createIco(srcTemp, icoOut)) {
2585
2590
  logs.push({ type: "success", message: "ICO: 6 sizes (256, 128, 64, 48, 32, 16)" });
2586
2591
  outputs.push(basename7(icoOut));
@@ -2591,12 +2596,13 @@ async function processCombined(input, borderColor, opts, logs) {
2591
2596
  }
2592
2597
  const needsPacks = icOpts.web || icOpts.android || icOpts.ios;
2593
2598
  if (needsPacks) {
2594
- const outputDir = `${fileInfo.dirname}/${fileInfo.filename}_icons`;
2595
- mkdirSync5(outputDir, { recursive: true });
2599
+ const outDir = ensureOutputDir(input);
2600
+ const outputDir = join8(outDir, `${fileInfo.filename}_icons`);
2601
+ mkdirSync6(outputDir, { recursive: true });
2596
2602
  if (icOpts.web) {
2597
2603
  logs.push({ type: "info", message: "Generating Web icons..." });
2598
2604
  const webDir = `${outputDir}/web`;
2599
- mkdirSync5(webDir, { recursive: true });
2605
+ mkdirSync6(webDir, { recursive: true });
2600
2606
  const t16 = `${webDir}/.t16.png`, t32 = `${webDir}/.t32.png`, t48 = `${webDir}/.t48.png`;
2601
2607
  await scaleToSize(srcTemp, t16, 16);
2602
2608
  await scaleToSize(srcTemp, t32, 32);
@@ -2631,7 +2637,7 @@ async function processCombined(input, borderColor, opts, logs) {
2631
2637
  ];
2632
2638
  for (const i of androidIcons) {
2633
2639
  const p = `${androidDir}/${i.name}`;
2634
- mkdirSync5(dirname6(p), { recursive: true });
2640
+ mkdirSync6(dirname6(p), { recursive: true });
2635
2641
  await scaleToSize(srcTemp, p, i.size);
2636
2642
  totalCount++;
2637
2643
  }
@@ -2640,7 +2646,7 @@ async function processCombined(input, borderColor, opts, logs) {
2640
2646
  if (icOpts.ios) {
2641
2647
  logs.push({ type: "info", message: "Generating iOS icons..." });
2642
2648
  const iosDir = `${outputDir}/ios`;
2643
- mkdirSync5(iosDir, { recursive: true });
2649
+ mkdirSync6(iosDir, { recursive: true });
2644
2650
  const iosSizes = [20, 29, 40, 58, 60, 76, 80, 87, 120, 152, 167, 180, 1024];
2645
2651
  for (const s of iosSizes) {
2646
2652
  await scaleToSize(srcTemp, `${iosDir}/AppIcon-${s}.png`, s);
@@ -2662,12 +2668,13 @@ async function processCombined(input, borderColor, opts, logs) {
2662
2668
  return { outputs: [] };
2663
2669
  }
2664
2670
  const folderName = spOpts.presetName || "assets";
2665
- const outputDir = `${fileInfo.dirname}/${fileInfo.filename}_${folderName}`;
2666
- mkdirSync5(outputDir, { recursive: true });
2671
+ const outDir = ensureOutputDir(input);
2672
+ const outputDir = join8(outDir, `${fileInfo.filename}_${folderName}`);
2673
+ mkdirSync6(outputDir, { recursive: true });
2667
2674
  let count = 0;
2668
2675
  for (const dim of spOpts.dimensions) {
2669
2676
  const filename = dim.filename || `${dim.width}x${dim.height}.png`;
2670
- const out = join7(outputDir, filename);
2677
+ const out = join8(outputDir, filename);
2671
2678
  let success2 = false;
2672
2679
  switch (spOpts.scaleMode) {
2673
2680
  case "fill":
@@ -2692,7 +2699,7 @@ async function processCombined(input, borderColor, opts, logs) {
2692
2699
  }
2693
2700
  async function runGUI6(inputRaw) {
2694
2701
  let currentInput = normalizePath(inputRaw);
2695
- if (!existsSync8(currentInput)) {
2702
+ if (!existsSync10(currentInput)) {
2696
2703
  error(`File not found: ${currentInput}`);
2697
2704
  return false;
2698
2705
  }
@@ -2706,14 +2713,14 @@ async function runGUI6(inputRaw) {
2706
2713
  const presets = loadPresets();
2707
2714
  async function generateFrameThumbnail(frameIndex) {
2708
2715
  const tempDir = tmpdir5();
2709
- const tempOutput = join7(tempDir, `piclet-frame-${Date.now()}-${frameIndex}.png`);
2716
+ const tempOutput = join8(tempDir, `piclet-frame-${Date.now()}-${frameIndex}.png`);
2710
2717
  try {
2711
2718
  if (!await extractFirstFrame(currentInput, tempOutput, frameIndex)) {
2712
2719
  return { success: false, error: "Failed to extract frame" };
2713
2720
  }
2714
- const thumbOutput = join7(tempDir, `piclet-thumb-${Date.now()}-${frameIndex}.png`);
2721
+ const thumbOutput = join8(tempDir, `piclet-thumb-${Date.now()}-${frameIndex}.png`);
2715
2722
  await scaleToSize(tempOutput, thumbOutput, 96);
2716
- const buffer = readFileSync6(thumbOutput);
2723
+ const buffer = readFileSync7(thumbOutput);
2717
2724
  cleanup(tempOutput, thumbOutput);
2718
2725
  return {
2719
2726
  success: true,
@@ -2727,7 +2734,7 @@ async function runGUI6(inputRaw) {
2727
2734
  async function generateFramePreview2(frameIndex, opts) {
2728
2735
  const tempDir = tmpdir5();
2729
2736
  const ts = Date.now();
2730
- const frameFile = join7(tempDir, `piclet-fp-${ts}-${frameIndex}.png`);
2737
+ const frameFile = join8(tempDir, `piclet-fp-${ts}-${frameIndex}.png`);
2731
2738
  const temps = [frameFile];
2732
2739
  try {
2733
2740
  if (!await extractFirstFrame(currentInput, frameFile, frameIndex)) {
@@ -2736,7 +2743,7 @@ async function runGUI6(inputRaw) {
2736
2743
  let current = frameFile;
2737
2744
  const activeTools = ["removebg", "scale", "icons"].filter((t) => opts.tools.includes(t));
2738
2745
  for (const tool of activeTools) {
2739
- const tempOut = join7(tempDir, `piclet-fp-${ts}-${frameIndex}-${tool}.png`);
2746
+ const tempOut = join8(tempDir, `piclet-fp-${ts}-${frameIndex}-${tool}.png`);
2740
2747
  temps.push(tempOut);
2741
2748
  switch (tool) {
2742
2749
  case "removebg": {
@@ -2750,7 +2757,7 @@ async function runGUI6(inputRaw) {
2750
2757
  }
2751
2758
  if (success2) {
2752
2759
  if (rbOpts.trim) {
2753
- const trimOut = join7(tempDir, `piclet-fp-${ts}-${frameIndex}-trim.png`);
2760
+ const trimOut = join8(tempDir, `piclet-fp-${ts}-${frameIndex}-trim.png`);
2754
2761
  temps.push(trimOut);
2755
2762
  if (await trim(tempOut, trimOut)) {
2756
2763
  current = trimOut;
@@ -2780,7 +2787,7 @@ async function runGUI6(inputRaw) {
2780
2787
  case "icons": {
2781
2788
  const icOpts = opts.icons;
2782
2789
  if (icOpts.trim) {
2783
- const trimOut = join7(tempDir, `piclet-fp-${ts}-${frameIndex}-ictrim.png`);
2790
+ const trimOut = join8(tempDir, `piclet-fp-${ts}-${frameIndex}-ictrim.png`);
2784
2791
  temps.push(trimOut);
2785
2792
  if (await trim(current, trimOut)) {
2786
2793
  current = trimOut;
@@ -2795,10 +2802,10 @@ async function runGUI6(inputRaw) {
2795
2802
  }
2796
2803
  }
2797
2804
  }
2798
- const thumbOut = join7(tempDir, `piclet-fp-${ts}-${frameIndex}-thumb.png`);
2805
+ const thumbOut = join8(tempDir, `piclet-fp-${ts}-${frameIndex}-thumb.png`);
2799
2806
  temps.push(thumbOut);
2800
2807
  await scaleToSize(current, thumbOut, 96);
2801
- const buffer = readFileSync6(thumbOut);
2808
+ const buffer = readFileSync7(thumbOut);
2802
2809
  cleanup(...temps);
2803
2810
  return {
2804
2811
  success: true,
@@ -2837,7 +2844,7 @@ async function runGUI6(inputRaw) {
2837
2844
  if (isMultiFrame(currentInput) && typeof toolOpts.frameIndex === "number") {
2838
2845
  const tempDir = tmpdir5();
2839
2846
  const ts = Date.now();
2840
- const frameFile = join7(tempDir, `piclet-prev-${ts}.png`);
2847
+ const frameFile = join8(tempDir, `piclet-prev-${ts}.png`);
2841
2848
  if (!await extractFirstFrame(currentInput, frameFile, toolOpts.frameIndex)) {
2842
2849
  return { success: false, error: "Failed to extract frame" };
2843
2850
  }
@@ -2876,8 +2883,8 @@ async function runGUI6(inputRaw) {
2876
2883
  },
2877
2884
  onLoadImage: async (data) => {
2878
2885
  try {
2879
- const ext = extname2(data.fileName) || ".png";
2880
- const tempPath = join7(tmpdir5(), `piclet-load-${Date.now()}${ext}`);
2886
+ const ext = extname3(data.fileName) || ".png";
2887
+ const tempPath = join8(tmpdir5(), `piclet-load-${Date.now()}${ext}`);
2881
2888
  const buffer = Buffer.from(data.data, "base64");
2882
2889
  writeFileSync2(tempPath, buffer);
2883
2890
  const newDims = await getDimensions(tempPath);
@@ -2911,7 +2918,7 @@ async function runGUI6(inputRaw) {
2911
2918
  },
2912
2919
  onSimplifyGif: async (skipFactor) => {
2913
2920
  try {
2914
- const tempPath = join7(tmpdir5(), `piclet-simplified-${Date.now()}.gif`);
2921
+ const tempPath = join8(tmpdir5(), `piclet-simplified-${Date.now()}.gif`);
2915
2922
  const result = await simplifyGif(currentInput, tempPath, skipFactor);
2916
2923
  if (!result.success) {
2917
2924
  return { success: false, error: "Failed to simplify GIF" };
@@ -2937,7 +2944,7 @@ async function runGUI6(inputRaw) {
2937
2944
  },
2938
2945
  onDeleteFrame: async (frameIndex) => {
2939
2946
  try {
2940
- const tempPath = join7(tmpdir5(), `piclet-edited-${Date.now()}.gif`);
2947
+ const tempPath = join8(tmpdir5(), `piclet-edited-${Date.now()}.gif`);
2941
2948
  const result = await deleteGifFrame(currentInput, tempPath, frameIndex);
2942
2949
  if (!result.success) {
2943
2950
  return { success: false, error: "Failed to delete frame" };
@@ -2952,9 +2959,9 @@ async function runGUI6(inputRaw) {
2952
2959
  onReplaceFrame: async (frameIndex, imageData) => {
2953
2960
  try {
2954
2961
  const buffer = Buffer.from(imageData, "base64");
2955
- const tempImagePath = join7(tmpdir5(), `piclet-replace-${Date.now()}.png`);
2962
+ const tempImagePath = join8(tmpdir5(), `piclet-replace-${Date.now()}.png`);
2956
2963
  writeFileSync2(tempImagePath, buffer);
2957
- const tempPath = join7(tmpdir5(), `piclet-edited-${Date.now()}.gif`);
2964
+ const tempPath = join8(tmpdir5(), `piclet-edited-${Date.now()}.gif`);
2958
2965
  const result = await replaceGifFrame(currentInput, tempPath, frameIndex, tempImagePath);
2959
2966
  cleanup(tempImagePath);
2960
2967
  if (!result.success) {
@@ -2984,7 +2991,7 @@ async function processGifExport(input, borderColor, opts, logs) {
2984
2991
  case "frame": {
2985
2992
  const frameIndex = opts.frameIndex ?? 0;
2986
2993
  logs.push({ type: "info", message: `Exporting frame ${frameIndex + 1}...` });
2987
- const frameFile = join7(tempDir, `piclet-export-${ts}.png`);
2994
+ const frameFile = join8(tempDir, `piclet-export-${ts}.png`);
2988
2995
  if (!await extractFirstFrame(input, frameFile, frameIndex)) {
2989
2996
  logs.push({ type: "error", message: "Failed to extract frame" });
2990
2997
  return { success: false, error: "Failed to extract frame", logs };
@@ -2999,7 +3006,8 @@ async function processGifExport(input, borderColor, opts, logs) {
2999
3006
  return { success: false, error: "Processing failed", logs };
3000
3007
  }
3001
3008
  }
3002
- const finalOutput = `${fileInfo.dirname}/${fileInfo.filename}_frame${frameIndex + 1}.png`;
3009
+ const frameOutDir = ensureOutputDir(input);
3010
+ const finalOutput = join8(frameOutDir, `${fileInfo.filename}_frame${frameIndex + 1}.png`);
3003
3011
  if (outputFile === frameFile) {
3004
3012
  renameSync(frameFile, finalOutput);
3005
3013
  }
@@ -3008,8 +3016,9 @@ async function processGifExport(input, borderColor, opts, logs) {
3008
3016
  }
3009
3017
  case "all-frames": {
3010
3018
  logs.push({ type: "info", message: "Extracting all frames..." });
3011
- const outputDir = `${fileInfo.dirname}/${fileInfo.filename}_frames`;
3012
- mkdirSync5(outputDir, { recursive: true });
3019
+ const framesOutDir = ensureOutputDir(input);
3020
+ const outputDir = join8(framesOutDir, `${fileInfo.filename}_frames`);
3021
+ mkdirSync6(outputDir, { recursive: true });
3013
3022
  const frames = await extractAllFrames(input, outputDir, "frame");
3014
3023
  if (frames.length === 0) {
3015
3024
  logs.push({ type: "error", message: "Failed to extract frames" });
@@ -3046,9 +3055,9 @@ var config6 = {
3046
3055
  };
3047
3056
 
3048
3057
  // src/tools/recolor.ts
3049
- import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
3058
+ import { existsSync as existsSync11, readFileSync as readFileSync8 } from "fs";
3050
3059
  import { tmpdir as tmpdir6 } from "os";
3051
- import { basename as basename8, join as join8 } from "path";
3060
+ import { basename as basename8, join as join9 } from "path";
3052
3061
  async function processImage3(input, options) {
3053
3062
  const fileInfo = getFileInfo(input);
3054
3063
  const outputExt = fileInfo.extension.toLowerCase() === ".gif" ? ".gif" : ".png";
@@ -3111,7 +3120,7 @@ async function run6(inputRaw) {
3111
3120
  return false;
3112
3121
  }
3113
3122
  const input = normalizePath(inputRaw);
3114
- if (!existsSync9(input)) {
3123
+ if (!existsSync11(input)) {
3115
3124
  error(`File not found: ${input}`);
3116
3125
  await pauseOnError();
3117
3126
  return false;
@@ -3134,7 +3143,7 @@ async function run6(inputRaw) {
3134
3143
  }
3135
3144
  async function runGUI7(inputRaw) {
3136
3145
  const input = normalizePath(inputRaw);
3137
- if (!existsSync9(input)) {
3146
+ if (!existsSync11(input)) {
3138
3147
  error(`File not found: ${input}`);
3139
3148
  return false;
3140
3149
  }
@@ -3206,8 +3215,8 @@ async function runGUI7(inputRaw) {
3206
3215
  async function generatePreview4(input, options) {
3207
3216
  const tempDir = tmpdir6();
3208
3217
  const timestamp = Date.now();
3209
- const tempSource = join8(tempDir, `piclet-preview-${timestamp}-src.png`);
3210
- const tempOutput = join8(tempDir, `piclet-preview-${timestamp}.png`);
3218
+ const tempSource = join9(tempDir, `piclet-preview-${timestamp}-src.png`);
3219
+ const tempOutput = join9(tempDir, `piclet-preview-${timestamp}.png`);
3211
3220
  try {
3212
3221
  let previewInput = input;
3213
3222
  if (isMultiFrame(input)) {
@@ -3227,7 +3236,7 @@ async function generatePreview4(input, options) {
3227
3236
  cleanup(tempSource, tempOutput);
3228
3237
  return { success: false, error: "Color replacement failed" };
3229
3238
  }
3230
- const buffer = readFileSync7(tempOutput);
3239
+ const buffer = readFileSync8(tempOutput);
3231
3240
  const base64 = buffer.toString("base64");
3232
3241
  const imageData = `data:image/png;base64,${base64}`;
3233
3242
  const dims = await getDimensions(tempOutput);
@@ -3251,13 +3260,13 @@ var config7 = {
3251
3260
  };
3252
3261
 
3253
3262
  // src/tools/remove-bg.ts
3254
- import { existsSync as existsSync11, readFileSync as readFileSync9, renameSync as renameSync2 } from "fs";
3263
+ import { existsSync as existsSync13, readFileSync as readFileSync10, renameSync as renameSync2 } from "fs";
3255
3264
  import { tmpdir as tmpdir7 } from "os";
3256
- import { basename as basename9, join as join10 } from "path";
3265
+ import { basename as basename9, join as join11 } from "path";
3257
3266
 
3258
3267
  // src/lib/config.ts
3259
- import { existsSync as existsSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync3 } from "fs";
3260
- import { dirname as dirname7, join as join9 } from "path";
3268
+ import { existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as readFileSync9, writeFileSync as writeFileSync3 } from "fs";
3269
+ import { dirname as dirname7, join as join10 } from "path";
3261
3270
  import { homedir as homedir2 } from "os";
3262
3271
  var DEFAULT_CONFIG = {
3263
3272
  removeBg: {
@@ -3275,18 +3284,18 @@ var DEFAULT_CONFIG = {
3275
3284
  }
3276
3285
  };
3277
3286
  function getConfigDir() {
3278
- return join9(homedir2(), ".config", "piclet");
3287
+ return join10(homedir2(), ".config", "piclet");
3279
3288
  }
3280
3289
  function getConfigPath() {
3281
- return join9(getConfigDir(), "config.json");
3290
+ return join10(getConfigDir(), "config.json");
3282
3291
  }
3283
3292
  function loadConfig() {
3284
3293
  const configPath = getConfigPath();
3285
- if (!existsSync10(configPath)) {
3294
+ if (!existsSync12(configPath)) {
3286
3295
  return { ...DEFAULT_CONFIG };
3287
3296
  }
3288
3297
  try {
3289
- const content = readFileSync8(configPath, "utf-8");
3298
+ const content = readFileSync9(configPath, "utf-8");
3290
3299
  const loaded = JSON.parse(content);
3291
3300
  return {
3292
3301
  removeBg: { ...DEFAULT_CONFIG.removeBg, ...loaded.removeBg },
@@ -3300,8 +3309,8 @@ function loadConfig() {
3300
3309
  function resetConfig() {
3301
3310
  const configPath = getConfigPath();
3302
3311
  const configDir = dirname7(configPath);
3303
- if (!existsSync10(configDir)) {
3304
- mkdirSync6(configDir, { recursive: true });
3312
+ if (!existsSync12(configDir)) {
3313
+ mkdirSync7(configDir, { recursive: true });
3305
3314
  }
3306
3315
  writeFileSync3(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2));
3307
3316
  }
@@ -3404,7 +3413,7 @@ async function run7(inputRaw) {
3404
3413
  return false;
3405
3414
  }
3406
3415
  const input = normalizePath(inputRaw);
3407
- if (!existsSync11(input)) {
3416
+ if (!existsSync13(input)) {
3408
3417
  error(`File not found: ${input}`);
3409
3418
  await pauseOnError();
3410
3419
  return false;
@@ -3427,7 +3436,7 @@ async function run7(inputRaw) {
3427
3436
  }
3428
3437
  async function runGUI8(inputRaw) {
3429
3438
  const input = normalizePath(inputRaw);
3430
- if (!existsSync11(input)) {
3439
+ if (!existsSync13(input)) {
3431
3440
  error(`File not found: ${input}`);
3432
3441
  return false;
3433
3442
  }
@@ -3465,15 +3474,12 @@ async function runGUI8(inputRaw) {
3465
3474
  return generatePreview5(input, borderColor, options);
3466
3475
  },
3467
3476
  onProcess: async (opts) => {
3468
- const logs = [];
3469
3477
  if (!await checkImageMagick()) {
3470
3478
  return {
3471
3479
  success: false,
3472
- error: "ImageMagick not found",
3473
- logs: [{ type: "error", message: "ImageMagick not found. Install with: sudo apt install imagemagick" }]
3480
+ error: "ImageMagick not found"
3474
3481
  };
3475
3482
  }
3476
- logs.push({ type: "info", message: `Processing ${basename9(input)}...` });
3477
3483
  const options = {
3478
3484
  fuzz: opts.fuzz ?? defaults.fuzz,
3479
3485
  doTrim: opts.trim ?? defaults.trim,
@@ -3481,22 +3487,25 @@ async function runGUI8(inputRaw) {
3481
3487
  makeSquare: opts.makeSquare ?? defaults.makeSquare
3482
3488
  };
3483
3489
  const fileInfo = getFileInfo(input);
3484
- const output = `${fileInfo.dirname}/${fileInfo.filename}_nobg.png`;
3485
- logs.push({ type: "info", message: "Removing background..." });
3490
+ const outputExt = fileInfo.extension.toLowerCase() === ".gif" ? ".gif" : ".png";
3491
+ const output = `${fileInfo.dirname}/${fileInfo.filename}_nobg${outputExt}`;
3492
+ const logs = [];
3486
3493
  const success2 = await processImageSilent(input, borderColor, options, logs);
3487
- if (success2) {
3494
+ if (success2 && existsSync13(output)) {
3488
3495
  const finalDims = await getDimensions(output);
3489
3496
  const sizeStr = finalDims ? ` (${finalDims[0]}x${finalDims[1]})` : "";
3497
+ const buffer = readFileSync10(output);
3498
+ const mimeType = outputExt === ".gif" ? "image/gif" : "image/png";
3499
+ const imageData = `data:${mimeType};base64,${buffer.toString("base64")}`;
3490
3500
  return {
3491
3501
  success: true,
3492
3502
  output: `${basename9(output)}${sizeStr}`,
3493
- logs
3503
+ imageData
3494
3504
  };
3495
3505
  }
3496
3506
  return {
3497
3507
  success: false,
3498
- error: "Processing failed",
3499
- logs
3508
+ error: "Processing failed"
3500
3509
  };
3501
3510
  }
3502
3511
  });
@@ -3555,9 +3564,9 @@ async function processImageSilent(input, borderColor, options, logs) {
3555
3564
  async function generatePreview5(input, borderColor, options) {
3556
3565
  const tempDir = tmpdir7();
3557
3566
  const timestamp = Date.now();
3558
- const tempSource = join10(tempDir, `piclet-preview-${timestamp}-src.png`);
3559
- const tempFile = join10(tempDir, `piclet-preview-${timestamp}.png`);
3560
- const tempOutput = join10(tempDir, `piclet-preview-${timestamp}-out.png`);
3567
+ const tempSource = join11(tempDir, `piclet-preview-${timestamp}-src.png`);
3568
+ const tempFile = join11(tempDir, `piclet-preview-${timestamp}.png`);
3569
+ const tempOutput = join11(tempDir, `piclet-preview-${timestamp}-out.png`);
3561
3570
  try {
3562
3571
  let previewInput = input;
3563
3572
  if (isMultiFrame(input)) {
@@ -3585,13 +3594,13 @@ async function generatePreview5(input, borderColor, options) {
3585
3594
  }
3586
3595
  }
3587
3596
  if (options.makeSquare) {
3588
- const squareFile = join10(tempDir, `piclet-preview-${timestamp}-sq.png`);
3597
+ const squareFile = join11(tempDir, `piclet-preview-${timestamp}-sq.png`);
3589
3598
  if (await squarify(currentFile, squareFile)) {
3590
3599
  cleanup(currentFile);
3591
3600
  currentFile = squareFile;
3592
3601
  }
3593
3602
  }
3594
- const buffer = readFileSync9(currentFile);
3603
+ const buffer = readFileSync10(currentFile);
3595
3604
  const base64 = buffer.toString("base64");
3596
3605
  const imageData = `data:image/png;base64,${base64}`;
3597
3606
  const dims = await getDimensions(currentFile);
@@ -3615,9 +3624,9 @@ var config8 = {
3615
3624
  };
3616
3625
 
3617
3626
  // src/tools/rescale.ts
3618
- import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
3627
+ import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
3619
3628
  import { tmpdir as tmpdir8 } from "os";
3620
- import { basename as basename10, join as join11 } from "path";
3629
+ import { basename as basename10, join as join12 } from "path";
3621
3630
  async function run8(inputRaw) {
3622
3631
  if (!await checkImageMagick()) {
3623
3632
  error("ImageMagick not found. Please install it:");
@@ -3626,7 +3635,7 @@ async function run8(inputRaw) {
3626
3635
  return false;
3627
3636
  }
3628
3637
  const input = normalizePath(inputRaw);
3629
- if (!existsSync12(input)) {
3638
+ if (!existsSync14(input)) {
3630
3639
  error(`File not found: ${input}`);
3631
3640
  await pauseOnError();
3632
3641
  return false;
@@ -3687,7 +3696,7 @@ async function run8(inputRaw) {
3687
3696
  } else {
3688
3697
  scaled = await resize(input, output, targetW, targetH);
3689
3698
  }
3690
- if (!scaled || !existsSync12(output)) {
3699
+ if (!scaled || !existsSync14(output)) {
3691
3700
  wipDone(false, "Scaling failed");
3692
3701
  return false;
3693
3702
  }
@@ -3703,7 +3712,7 @@ async function run8(inputRaw) {
3703
3712
  }
3704
3713
  async function runGUI9(inputRaw) {
3705
3714
  const input = normalizePath(inputRaw);
3706
- if (!existsSync12(input)) {
3715
+ if (!existsSync14(input)) {
3707
3716
  error(`File not found: ${input}`);
3708
3717
  return false;
3709
3718
  }
@@ -3757,7 +3766,7 @@ async function runGUI9(inputRaw) {
3757
3766
  } else {
3758
3767
  scaled = await resize(input, output, options.width, options.height);
3759
3768
  }
3760
- if (scaled && existsSync12(output)) {
3769
+ if (scaled && existsSync14(output)) {
3761
3770
  const finalDims = await getDimensions(output);
3762
3771
  const sizeStr = finalDims ? ` (${finalDims[0]}x${finalDims[1]})` : "";
3763
3772
  logs.push({ type: "success", message: "Scaled successfully" });
@@ -3775,8 +3784,8 @@ async function runGUI9(inputRaw) {
3775
3784
  async function generatePreview6(input, options) {
3776
3785
  const tempDir = tmpdir8();
3777
3786
  const timestamp = Date.now();
3778
- const tempSource = join11(tempDir, `piclet-preview-${timestamp}-src.png`);
3779
- const tempOutput = join11(tempDir, `piclet-preview-${timestamp}.png`);
3787
+ const tempSource = join12(tempDir, `piclet-preview-${timestamp}-src.png`);
3788
+ const tempOutput = join12(tempDir, `piclet-preview-${timestamp}.png`);
3780
3789
  try {
3781
3790
  let previewInput = input;
3782
3791
  if (isMultiFrame(input)) {
@@ -3796,11 +3805,11 @@ async function generatePreview6(input, options) {
3796
3805
  } else {
3797
3806
  scaled = await resize(previewInput, tempOutput, targetW, targetH);
3798
3807
  }
3799
- if (!scaled || !existsSync12(tempOutput)) {
3808
+ if (!scaled || !existsSync14(tempOutput)) {
3800
3809
  cleanup(tempSource);
3801
3810
  return { success: false, error: "Scaling failed" };
3802
3811
  }
3803
- const buffer = readFileSync10(tempOutput);
3812
+ const buffer = readFileSync11(tempOutput);
3804
3813
  const base64 = buffer.toString("base64");
3805
3814
  const imageData = `data:image/png;base64,${base64}`;
3806
3815
  const dims = await getDimensions(tempOutput);
@@ -3824,8 +3833,8 @@ var config9 = {
3824
3833
  };
3825
3834
 
3826
3835
  // src/tools/storepack.ts
3827
- import { existsSync as existsSync13, mkdirSync as mkdirSync7 } from "fs";
3828
- import { basename as basename11, join as join12 } from "path";
3836
+ import { existsSync as existsSync15, mkdirSync as mkdirSync8 } from "fs";
3837
+ import { basename as basename11, join as join13 } from "path";
3829
3838
  async function scaleImage(input, output, width, height, mode) {
3830
3839
  switch (mode) {
3831
3840
  case "fill":
@@ -3842,7 +3851,7 @@ async function generatePresetImages(sourceImg, outputDir, preset, scaleMode = "f
3842
3851
  const total = preset.icons.length;
3843
3852
  for (let i = 0; i < total; i++) {
3844
3853
  const icon = preset.icons[i];
3845
- const outputPath = join12(outputDir, icon.filename);
3854
+ const outputPath = join13(outputDir, icon.filename);
3846
3855
  if (logs) {
3847
3856
  logs.push({ type: "info", message: `[${i + 1}/${total}] ${icon.filename}` });
3848
3857
  } else {
@@ -3878,7 +3887,7 @@ async function run9(inputRaw) {
3878
3887
  return false;
3879
3888
  }
3880
3889
  const input = normalizePath(inputRaw);
3881
- if (!existsSync13(input)) {
3890
+ if (!existsSync15(input)) {
3882
3891
  error(`File not found: ${input}`);
3883
3892
  await pauseOnError();
3884
3893
  return false;
@@ -3906,11 +3915,11 @@ async function run9(inputRaw) {
3906
3915
  return false;
3907
3916
  }
3908
3917
  const outputDir = `${fileInfo.dirname}/${fileInfo.filename}_${preset.id}`;
3909
- mkdirSync7(outputDir, { recursive: true });
3918
+ mkdirSync8(outputDir, { recursive: true });
3910
3919
  info(`Output: ${outputDir}`);
3911
3920
  console.log("");
3912
3921
  wip("Preparing source...");
3913
- const tempSource = join12(outputDir, ".source.png");
3922
+ const tempSource = join13(outputDir, ".source.png");
3914
3923
  if (!await squarify(input, tempSource)) {
3915
3924
  wipDone(false, "Failed to prepare source");
3916
3925
  return false;
@@ -3931,7 +3940,7 @@ async function run9(inputRaw) {
3931
3940
  }
3932
3941
  async function runGUI10(inputRaw) {
3933
3942
  const input = normalizePath(inputRaw);
3934
- if (!existsSync13(input)) {
3943
+ if (!existsSync15(input)) {
3935
3944
  error(`File not found: ${input}`);
3936
3945
  return false;
3937
3946
  }
@@ -3980,7 +3989,7 @@ async function runGUI10(inputRaw) {
3980
3989
  };
3981
3990
  }
3982
3991
  const outputDir = `${fileInfo.dirname}/${fileInfo.filename}_${preset.id}`;
3983
- mkdirSync7(outputDir, { recursive: true });
3992
+ mkdirSync8(outputDir, { recursive: true });
3984
3993
  logs.push({ type: "info", message: `Output: ${outputDir}` });
3985
3994
  logs.push({ type: "info", message: `Scale mode: ${scaleMode}` });
3986
3995
  logs.push({ type: "info", message: `Generating ${preset.icons.length} images...` });
@@ -4009,9 +4018,9 @@ var config10 = {
4009
4018
  };
4010
4019
 
4011
4020
  // src/tools/transform.ts
4012
- import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
4021
+ import { existsSync as existsSync16, readFileSync as readFileSync12 } from "fs";
4013
4022
  import { tmpdir as tmpdir9 } from "os";
4014
- import { basename as basename12, join as join13 } from "path";
4023
+ import { basename as basename12, join as join14 } from "path";
4015
4024
  var TRANSFORM_LABELS = {
4016
4025
  "flip-h": "Flip Horizontal",
4017
4026
  "flip-v": "Flip Vertical",
@@ -4087,7 +4096,7 @@ async function run10(inputRaw) {
4087
4096
  return false;
4088
4097
  }
4089
4098
  const input = normalizePath(inputRaw);
4090
- if (!existsSync14(input)) {
4099
+ if (!existsSync16(input)) {
4091
4100
  error(`File not found: ${input}`);
4092
4101
  await pauseOnError();
4093
4102
  return false;
@@ -4106,7 +4115,7 @@ async function run10(inputRaw) {
4106
4115
  }
4107
4116
  async function runGUI11(inputRaw) {
4108
4117
  const input = normalizePath(inputRaw);
4109
- if (!existsSync14(input)) {
4118
+ if (!existsSync16(input)) {
4110
4119
  error(`File not found: ${input}`);
4111
4120
  return false;
4112
4121
  }
@@ -4189,8 +4198,8 @@ async function runGUI11(inputRaw) {
4189
4198
  async function generatePreview7(input, options) {
4190
4199
  const tempDir = tmpdir9();
4191
4200
  const timestamp = Date.now();
4192
- const tempSource = join13(tempDir, `piclet-preview-${timestamp}-src.png`);
4193
- const tempOutput = join13(tempDir, `piclet-preview-${timestamp}.png`);
4201
+ const tempSource = join14(tempDir, `piclet-preview-${timestamp}-src.png`);
4202
+ const tempOutput = join14(tempDir, `piclet-preview-${timestamp}.png`);
4194
4203
  try {
4195
4204
  let previewInput = input;
4196
4205
  if (isMultiFrame(input)) {
@@ -4221,7 +4230,7 @@ async function generatePreview7(input, options) {
4221
4230
  cleanup(tempSource, tempOutput);
4222
4231
  return { success: false, error: "Transform failed" };
4223
4232
  }
4224
- const buffer = readFileSync11(tempOutput);
4233
+ const buffer = readFileSync12(tempOutput);
4225
4234
  const base64 = buffer.toString("base64");
4226
4235
  const imageData = `data:image/png;base64,${base64}`;
4227
4236
  const dims = await getDimensions(tempOutput);
@@ -4278,6 +4287,10 @@ function getToolsForExtension(extension) {
4278
4287
  }
4279
4288
 
4280
4289
  // src/cli/utils.ts
4290
+ import { extname as extname4 } from "path";
4291
+ import { dirname as dirname9 } from "path";
4292
+ import { fileURLToPath as fileURLToPath2 } from "url";
4293
+ import chalk from "chalk";
4281
4294
  function getDistDir() {
4282
4295
  const currentFile = fileURLToPath2(import.meta.url);
4283
4296
  return dirname9(currentFile);
@@ -4289,7 +4302,7 @@ function validateExtensions(files, allowedExtensions) {
4289
4302
  const valid = [];
4290
4303
  const invalid = [];
4291
4304
  for (const file of files) {
4292
- const ext = extname3(file).toLowerCase();
4305
+ const ext = extname4(file).toLowerCase();
4293
4306
  if (allowedExtensions.includes(ext)) {
4294
4307
  valid.push(file);
4295
4308
  } else {
@@ -4349,7 +4362,7 @@ function registerBorderCommand(program2) {
4349
4362
  if (valid.length === 0) {
4350
4363
  process.exit(1);
4351
4364
  }
4352
- const result = await runGUI(valid[0]);
4365
+ const result = await picletTool.runGUI(valid[0]);
4353
4366
  process.exit(result ? 0 : 1);
4354
4367
  }
4355
4368
  const success2 = await runToolOnFiles(
@@ -4393,7 +4406,7 @@ function registerExtractFramesCommand(program2) {
4393
4406
  if (valid.length === 0) {
4394
4407
  process.exit(1);
4395
4408
  }
4396
- const result = await runGUI2(valid[0]);
4409
+ const result = await picletTool.runGUI(valid[0]);
4397
4410
  process.exit(result ? 0 : 1);
4398
4411
  }
4399
4412
  const success2 = await runToolOnFiles(
@@ -4420,7 +4433,7 @@ function registerFilterCommand(program2) {
4420
4433
  if (valid.length === 0) {
4421
4434
  process.exit(1);
4422
4435
  }
4423
- const result = await runGUI3(valid[0]);
4436
+ const result = await picletTool.runGUI(valid[0]);
4424
4437
  process.exit(result ? 0 : 1);
4425
4438
  }
4426
4439
  const success2 = await runToolOnFiles(
@@ -4454,7 +4467,7 @@ function registerIconpackCommand(program2) {
4454
4467
  if (valid.length === 0) {
4455
4468
  process.exit(1);
4456
4469
  }
4457
- const result = await runGUI4(valid[0]);
4470
+ const result = await picletTool.runGUI(valid[0]);
4458
4471
  process.exit(result ? 0 : 1);
4459
4472
  }
4460
4473
  const success2 = await runToolOnFiles(
@@ -4471,7 +4484,7 @@ import chalk7 from "chalk";
4471
4484
 
4472
4485
  // src/lib/registry.ts
4473
4486
  import { exec as exec2 } from "child_process";
4474
- import { existsSync as existsSync15 } from "fs";
4487
+ import { existsSync as existsSync17 } from "fs";
4475
4488
  import { dirname as dirname10 } from "path";
4476
4489
  import { fileURLToPath as fileURLToPath3 } from "url";
4477
4490
  import { promisify as promisify2 } from "util";
@@ -4480,7 +4493,7 @@ function isWSL() {
4480
4493
  return process.platform === "linux" && (process.env.WSL_DISTRO_NAME !== void 0 || process.env.WSLENV !== void 0);
4481
4494
  }
4482
4495
  function isWSLInteropEnabled() {
4483
- return existsSync15("/proc/sys/fs/binfmt_misc/WSLInterop");
4496
+ return existsSync17("/proc/sys/fs/binfmt_misc/WSLInterop");
4484
4497
  }
4485
4498
  async function addRegistryKey(keyPath, valueName, value, type = "REG_SZ") {
4486
4499
  const valueArg = valueName ? `/v "${valueName}"` : "/ve";
@@ -4522,7 +4535,7 @@ async function deleteRegistryKey(keyPath) {
4522
4535
 
4523
4536
  // src/cli/registry.ts
4524
4537
  import { writeFile } from "fs/promises";
4525
- import { join as join14 } from "path";
4538
+ import { join as join15 } from "path";
4526
4539
  async function registerUnifiedMenu(extension, iconsDir, launcherPath) {
4527
4540
  const basePath = `HKCU\\Software\\Classes\\SystemFileAssociations\\${extension}\\shell\\PicLet`;
4528
4541
  const iconsDirWin = wslToWindows(iconsDir);
@@ -4558,8 +4571,8 @@ async function unregisterMenuForExtension(extension) {
4558
4571
  }
4559
4572
  async function registerAllTools() {
4560
4573
  const distDir = getDistDir();
4561
- const iconsDir = join14(distDir, "icons");
4562
- const launcherPath = join14(distDir, "launcher.vbs");
4574
+ const iconsDir = join15(distDir, "icons");
4575
+ const launcherPath = join15(distDir, "launcher.vbs");
4563
4576
  const results = [];
4564
4577
  for (const extension of picletTool.config.extensions) {
4565
4578
  const result = await registerUnifiedMenu(extension, iconsDir, launcherPath);
@@ -4635,8 +4648,8 @@ function escapeRegValue(value) {
4635
4648
  }
4636
4649
  function generateRegContent() {
4637
4650
  const distDir = getDistDir();
4638
- const iconsDir = join14(distDir, "icons");
4639
- const launcherPath = join14(distDir, "launcher.vbs");
4651
+ const iconsDir = join15(distDir, "icons");
4652
+ const launcherPath = join15(distDir, "launcher.vbs");
4640
4653
  const iconsDirWin = wslToWindows(iconsDir);
4641
4654
  const launcherWin = wslToWindows(launcherPath);
4642
4655
  const lines = ["Windows Registry Editor Version 5.00", ""];
@@ -4673,14 +4686,14 @@ function generateUninstallRegContent() {
4673
4686
  }
4674
4687
  async function generateRegFile() {
4675
4688
  const distDir = getDistDir();
4676
- const regPath = join14(distDir, "piclet-install.reg");
4689
+ const regPath = join15(distDir, "piclet-install.reg");
4677
4690
  const content = generateRegContent();
4678
4691
  await writeFile(regPath, content, "utf-8");
4679
4692
  return regPath;
4680
4693
  }
4681
4694
  async function generateUninstallRegFile() {
4682
4695
  const distDir = getDistDir();
4683
- const regPath = join14(distDir, "piclet-uninstall.reg");
4696
+ const regPath = join15(distDir, "piclet-uninstall.reg");
4684
4697
  const content = generateUninstallRegContent();
4685
4698
  await writeFile(regPath, content, "utf-8");
4686
4699
  return regPath;
@@ -4768,7 +4781,7 @@ function registerMakeiconCommand(program2) {
4768
4781
  if (valid.length === 0) {
4769
4782
  process.exit(1);
4770
4783
  }
4771
- const result = await runGUI5(valid[0]);
4784
+ const result = await picletTool.runGUI(valid[0]);
4772
4785
  process.exit(result ? 0 : 1);
4773
4786
  }
4774
4787
  const success2 = await runToolOnFiles(
@@ -4810,7 +4823,7 @@ function registerRecolorCommand(program2) {
4810
4823
  if (valid.length === 0) {
4811
4824
  process.exit(1);
4812
4825
  }
4813
- const result = await runGUI7(valid[0]);
4826
+ const result = await picletTool.runGUI(valid[0]);
4814
4827
  process.exit(result ? 0 : 1);
4815
4828
  }
4816
4829
  const success2 = await runToolOnFiles(
@@ -4837,7 +4850,7 @@ function registerRemoveBgCommand(program2) {
4837
4850
  if (valid.length === 0) {
4838
4851
  process.exit(1);
4839
4852
  }
4840
- const result = await runGUI8(valid[0]);
4853
+ const result = await picletTool.runGUI(valid[0]);
4841
4854
  process.exit(result ? 0 : 1);
4842
4855
  }
4843
4856
  if (options.fuzz !== void 0) {
@@ -4877,7 +4890,7 @@ function registerScaleCommand(program2) {
4877
4890
  if (valid.length === 0) {
4878
4891
  process.exit(1);
4879
4892
  }
4880
- const result = await runGUI9(valid[0]);
4893
+ const result = await picletTool.runGUI(valid[0]);
4881
4894
  process.exit(result ? 0 : 1);
4882
4895
  }
4883
4896
  const success2 = await runToolOnFiles(
@@ -4904,7 +4917,7 @@ function registerStorepackCommand(program2) {
4904
4917
  if (valid.length === 0) {
4905
4918
  process.exit(1);
4906
4919
  }
4907
- const result = await runGUI10(valid[0]);
4920
+ const result = await picletTool.runGUI(valid[0]);
4908
4921
  process.exit(result ? 0 : 1);
4909
4922
  }
4910
4923
  const success2 = await runToolOnFiles(
@@ -4931,7 +4944,7 @@ function registerTransformCommand(program2) {
4931
4944
  if (valid.length === 0) {
4932
4945
  process.exit(1);
4933
4946
  }
4934
- const result = await runGUI11(valid[0]);
4947
+ const result = await picletTool.runGUI(valid[0]);
4935
4948
  process.exit(result ? 0 : 1);
4936
4949
  }
4937
4950
  const success2 = await runToolOnFiles(