mng-cli 1.0.0

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/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # mnggiflab-cli
2
+
3
+ To install dependencies:
4
+
5
+ ```bash
6
+ pnpm install
7
+ ```
8
+
9
+ To run:
10
+
11
+ ```bash
12
+ pnpm dev
13
+ ```
14
+
15
+ 这是一个基于Node.js的TypeScript CLI项目。
@@ -0,0 +1,73 @@
1
+ import { Result } from 'mng-base';
2
+
3
+ export declare namespace gifCompress {
4
+ export {
5
+ GifCompressor,
6
+ interfaces
7
+ }
8
+ }
9
+
10
+ declare class GifCompressor {
11
+ private gifsiclePath;
12
+ constructor();
13
+ private ensureGifsicle;
14
+ private runGifsicle;
15
+ private deltaByFileSize;
16
+ private convertDropFrame;
17
+ /**
18
+ * gif压缩函数,逻辑如下
19
+ * 1. 检查settings中所有必填参数是否非空,检查所有字段是否符合Settings中定义的类型
20
+ * 2. 解析原始gif
21
+ * @param settings
22
+ */
23
+ compress(settings: Settings): Promise<Result<Blob, string>>;
24
+ /**
25
+ * 调用gifsicle解析原始gif
26
+ * @param file
27
+ */
28
+ parseOriginalGif(file: File): Promise<Result<GifInfo, string>>;
29
+ private resetDelayGif;
30
+ private singleCompress;
31
+ /**
32
+ *
33
+ * @param gifInfo
34
+ * @param settings
35
+ */
36
+ doCompressOnce(gifInfo: GifInfo, settings: Settings): Promise<Result<Blob, string>>;
37
+ }
38
+
39
+ declare interface GifFrame {
40
+ index: number;
41
+ delay: number;
42
+ }
43
+
44
+ declare interface GifInfo {
45
+ /** kb */
46
+ size: number;
47
+ width: number;
48
+ height: number;
49
+ colorTableSize: number | null;
50
+ frameNum: number;
51
+ frames: GifFrame[];
52
+ }
53
+
54
+ export declare namespace interfaces {
55
+ export {
56
+ Settings,
57
+ GifInfo,
58
+ GifFrame
59
+ }
60
+ }
61
+
62
+ declare interface Settings {
63
+ width?: number;
64
+ height?: number;
65
+ /** 抽帧比例 */
66
+ dropFrame: number;
67
+ /** 单位 kb */
68
+ exportSize: number;
69
+ /** 原始gif */
70
+ originalGif: File;
71
+ }
72
+
73
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,329 @@
1
+ import { Result as S } from "mng-base";
2
+ import { execa as v } from "execa";
3
+ import { promises as N } from "fs";
4
+ import { dirname as H, join as _ } from "path";
5
+ import { tmpdir as B } from "os";
6
+ import { fileURLToPath as C } from "url";
7
+ const V = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
8
+ __proto__: null
9
+ }, Symbol.toStringTag, { value: "Module" })), u = A;
10
+ (function(r, e) {
11
+ const x = A, t = r();
12
+ for (; ; )
13
+ try {
14
+ if (-parseInt(x(486)) / 1 * (-parseInt(x(585)) / 2) + -parseInt(x(521)) / 3 + parseInt(x(563)) / 4 + -parseInt(x(515)) / 5 + parseInt(x(518)) / 6 + -parseInt(x(576)) / 7 + parseInt(x(549)) / 8 * (parseInt(x(582)) / 9) === e) break;
15
+ t.push(t.shift());
16
+ } catch {
17
+ t.push(t.shift());
18
+ }
19
+ })(F, 434961);
20
+ function F() {
21
+ const r = ["无法解析帧数", "无法解析GIF尺寸", "无法找到gifsicle vendor目录,尝试的路径: ", "COMPRESSION_FAILED", "gifsicle路径:", "originalGif", "find", "gifsicle未生成输出文件", "INVALID_FRAME_COUNT", "toString", "HUGE", "3337070pKdtmA", "XXLARGE", "file", "2809824NbEoCd", "无法解析帧延迟信息", "split", "498357GZaVzZ", "startsWith", "substring", "map", "logical screen", "input.gif", "macos", "No output file from gifsicle", "路径: ", "抽帧比例必须在0到1之间", "push", "platform", "trim", "win32", "input.gif --no-warnings --resize-width ", "gifsicle", "INVALID_EXPORT_SIZE", "CANNOT_READ_FILE_DATA", "数值错误", "unwrap", "indexOf", "resetDelayGif", "win", "exportSize", "/out/", "convertDropFrame", "join", "PARSING_FAILED", "24xmgnBe", "runGifsicle", "x86", " -o /out/out.gif", "message", "name", "log", "getError", "catch", "out", "MAX_ATTEMPTS", "readdir", "length", "size", "321388RlgzeK", "SMALL", "dropFrame", "height", "处理文件失败", "writeFile", "XLARGE", "ensureGifsicle", "未生成输出文件", "../gifsicle-bin/vendor", "MEDIUM", "--info input.gif -o /out/out.txt", "frames", "3747534XudoJx", "parseOriginalGif", "输出文件为空", "可以尝试降低压缩宽/高", "readFile", "导出大小不能为负数", "1669833vWmlyE", "err", "压缩GIF超时,请调整压缩参数后再进行压缩", "52HzktZo", "isErr", "重置帧延迟失败", "darwin", "UNSUPPORTED_FILE_TYPE", "random", "image/gif", "LARGE", "尺寸数值错误", "GIFSICLE_BINARY_NOT_FOUND", "compress", "RESET_DELAY_FAILED", "lib不可用", "filter", "尺寸格式错误", "INVALID_DROP_FRAME_RATIO", "读取文件数据失败", "function", "arch", " --lossy=", "MISSING_ORIGINAL_GIF", "deltaByFileSize", "string", "images", "LOW_GAP_THRESHOLD", "linux", "arrayBuffer", "pop", "index", "singleCompress", "width", "NO_OUTPUT_FILE", "from", "原始GIF文件不能为空", "格式错误", "object", "application/octet-stream", "cwd", "COMPRESSION_TIMEOUT", "gifsicle.exe", "vendor", "access", "26869djNzAH", "delay", "压缩GIF失败", "x64", "replace", "GAP_RATIO_THRESHOLD", "lib未找到", "slice", "mkdir", "global color table", "round", "INVALID_GIF_DIMENSIONS", "includes", "FILE_PROCESSING_FAILED", "GIFSICLE_NOT_AVAILABLE", "--delete ", "Result.err:", "gifsiclePath"];
22
+ return F = function() {
23
+ return r;
24
+ }, F();
25
+ }
26
+ function A(r, e) {
27
+ return r = r - 457, F()[r];
28
+ }
29
+ const z = C(import.meta.url), M = H(z);
30
+ function X(r) {
31
+ return r instanceof ArrayBuffer;
32
+ }
33
+ function k(r) {
34
+ return r instanceof Blob;
35
+ }
36
+ function Y(r) {
37
+ return r instanceof File;
38
+ }
39
+ function j(r) {
40
+ const e = A;
41
+ return typeof r === e(479) && r !== null && typeof r[e(470)] === e(461);
42
+ }
43
+ var Z = ((r) => {
44
+ const e = A;
45
+ return r[e(497)] = e(497), r[e(512)] = e(512), r[e(482)] = e(482), r.GIFSICLE_BINARY_NOT_FOUND = "GIFSICLE_BINARY_NOT_FOUND", r[e(500)] = "GIFSICLE_NOT_AVAILABLE", r[e(589)] = "UNSUPPORTED_FILE_TYPE", r[e(538)] = e(538), r[e(464)] = e(464), r[e(459)] = "INVALID_DROP_FRAME_RATIO", r[e(537)] = e(537), r[e(548)] = "PARSING_FAILED", r[e(507)] = e(507), r[e(596)] = "RESET_DELAY_FAILED", r[e(475)] = e(475), r[e(499)] = e(499), r;
46
+ })(Z || {});
47
+ function o(r, e) {
48
+ const x = A, t = { [x(497)]: x(505), [x(512)]: x(504), [x(482)]: x(584), [x(594)]: x(492), [x(500)]: x(597), UNSUPPORTED_FILE_TYPE: "不支持的输入文件类型", [x(538)]: x(460), [x(464)]: "原始GIF文件不能为空", [x(459)]: x(530), [x(537)]: x(581), [x(548)]: "解析GIF失败", [x(507)]: x(488), RESET_DELAY_FAILED: x(587), [x(475)]: x(571), [x(499)]: x(567) }, n = e ? t[r] + ": " + e : t[r];
49
+ return S[x(583)](n);
50
+ }
51
+ const O = { MAX_ATTEMPTS: 50, LOW_GAP_THRESHOLD: 10, GAP_RATIO_THRESHOLD: 0.01, FILE_SIZE_THRESHOLDS: { SMALL: 1 * 1024 * 1024, MEDIUM: 3 * 1024 * 1024, LARGE: 5 * 1024 * 1024, XLARGE: 10 * 1024 * 1024, XXLARGE: 50 * 1024 * 1024, HUGE: 100 * 1024 * 1024 }, DELTA_VALUES: { SMALL: 10, MEDIUM: 20, LARGE: 30, XLARGE: 40, XXLARGE: 50, HUGE: 100, VERY_HUGE: 200 } };
52
+ function W() {
53
+ const r = A, e = process[r(532)], x = process[r(462)];
54
+ if (e === "win32") {
55
+ const n = x === r(489) ? r(489) : r(551);
56
+ return { platformDir: _("win", n), binaryName: r(483) };
57
+ }
58
+ if (e === "darwin") return { platformDir: r(527), binaryName: r(536) };
59
+ const t = x === "x64" ? "x64" : r(551);
60
+ return { platformDir: _(r(469), t), binaryName: r(536) };
61
+ }
62
+ async function J() {
63
+ const r = A, e = process[r(532)], x = process[r(462)];
64
+ let t = "";
65
+ if (e === r(534)) {
66
+ const s = r(x === "x64" ? 489 : 551);
67
+ t = _(r(543), s, "gifsicle.exe");
68
+ } else if (e === r(588)) t = _(r(527), r(536));
69
+ else {
70
+ const s = x === r(489) ? r(489) : r(551);
71
+ t = _(r(469), s, r(536));
72
+ }
73
+ const n = [_(M, r(572)), _(M, r(484)), _(process[r(481)](), r(484)), _(process.cwd(), "dist/vendor")];
74
+ for (const s of n)
75
+ try {
76
+ return await N[r(485)](_(s, t)), s;
77
+ } catch {
78
+ }
79
+ throw new Error(r(506) + n[r(547)](", "));
80
+ }
81
+ async function K(r) {
82
+ const e = A;
83
+ if (typeof r === e(466)) return await N.readFile(r);
84
+ if (X(r)) return Buffer.from(r);
85
+ if (Y(r) || k(r) || j(r)) try {
86
+ const x = await r[e(470)]();
87
+ return Buffer[e(476)](x);
88
+ } catch (x) {
89
+ throw o(e(538), x instanceof Error ? x[e(553)] : String(x));
90
+ }
91
+ throw o(e(589), typeof r);
92
+ }
93
+ async function $(r) {
94
+ const e = A, x = _(B(), "gifsicle-" + Date.now() + "-" + Math[e(590)]()[e(513)](36).substring(2)), t = _(x, e(558));
95
+ try {
96
+ return await N[e(494)](x, { recursive: !0 }), await N[e(494)](t, { recursive: !0 }), await r(x, t);
97
+ } finally {
98
+ await N.rm(x, { recursive: !0, force: !0 })[e(557)](() => {
99
+ });
100
+ }
101
+ }
102
+ function q(r, e, x, t) {
103
+ const n = A, s = [];
104
+ for (const f of r) {
105
+ const l = f[n(520)](" ")[n(457)]((d) => d.trim() !== "");
106
+ for (const d of l) {
107
+ let c = d;
108
+ if (d[n(522)](n(545))) {
109
+ const a = d[n(523)](5);
110
+ c = _(t, a);
111
+ }
112
+ e.find((a) => a[n(554)] === d) && (c = _(x, d)), s[n(531)](c);
113
+ }
114
+ }
115
+ return s;
116
+ }
117
+ class Q {
118
+ constructor() {
119
+ const e = A;
120
+ this[e(503)] = null;
121
+ }
122
+ async [u(570)]() {
123
+ const e = u;
124
+ try {
125
+ const { platformDir: x, binaryName: t } = W(), n = await J(), s = _(n, x, t);
126
+ try {
127
+ await N[e(485)](s);
128
+ } catch {
129
+ throw o(e(594), e(529) + s);
130
+ }
131
+ this[e(503)] = s, console[e(555)](e(508), this.gifsiclePath);
132
+ } catch (x) {
133
+ throw o(e(500), x instanceof Error ? x[e(553)] : String(x));
134
+ }
135
+ }
136
+ async [u(550)](e, x) {
137
+ const t = u;
138
+ !this[t(503)] && await this.ensureGifsicle();
139
+ try {
140
+ return await $(async (n, s) => {
141
+ const f = t;
142
+ for (const i of e)
143
+ try {
144
+ const a = await K(i[f(517)]), I = _(n, i.name);
145
+ await N[f(568)](I, a);
146
+ } catch (a) {
147
+ return a instanceof Error && a[f(553)][f(522)](f(502)) ? a : o(f(499), i.name + ": " + (a instanceof Error ? a.message : String(a)));
148
+ }
149
+ const l = q(x, e, n, s);
150
+ await v(this.gifsiclePath, l, { cwd: n });
151
+ const d = [], c = await N[f(560)](s);
152
+ for (const i of c) {
153
+ const a = _(s, i), I = await N[f(580)](a), h = new File([I], i, { type: f(480) });
154
+ d[f(531)](h);
155
+ }
156
+ return S.ok(d);
157
+ });
158
+ } catch (n) {
159
+ return n instanceof Error && n[t(553)][t(522)]("Result.err:") ? n : o(t(507), n instanceof Error ? n.message : String(n));
160
+ }
161
+ }
162
+ [u(465)](e) {
163
+ const x = u, { FILE_SIZE_THRESHOLDS: t, DELTA_VALUES: n } = O;
164
+ return e > t.HUGE ? n.VERY_HUGE : e > t[x(516)] && e <= t[x(514)] ? n[x(514)] : e > t.XLARGE && e <= t[x(516)] ? n[x(516)] : e > t[x(592)] && e <= t[x(569)] ? n[x(569)] : e > t[x(573)] && e <= t[x(592)] ? n.LARGE : e > t[x(564)] && e <= t[x(573)] ? n[x(573)] : n[x(564)];
165
+ }
166
+ [u(546)](e, x) {
167
+ const t = u;
168
+ if (e <= 0 || e >= 1) return { deleteParam: null, delayParam: null };
169
+ const n = Math[t(496)](1 / e), s = x[t(575)], f = s[t(457)]((a, I) => (I + 1) % n === 0)[t(524)]((a) => "#" + a[t(472)]), l = f.length > 0 ? t(501) + f[t(547)](" ") : null, d = [];
170
+ let c = 0;
171
+ for (let a = 0; a < s[t(561)]; a++) {
172
+ const I = s[a];
173
+ (a + 1) % n === 0 ? c += I[t(487)] : (d[t(531)](I[t(487)] + c), c = 0);
174
+ }
175
+ const i = d[t(561)] > 0 ? d[t(524)]((a, I) => "-d" + Math[t(496)](a / 10) + " #" + I)[t(547)](" ") : null;
176
+ return { deleteParam: l, delayParam: i };
177
+ }
178
+ async [u(595)](e) {
179
+ const x = u;
180
+ if (!e.originalGif) return o("MISSING_ORIGINAL_GIF");
181
+ if (e[x(565)] === void 0 || e[x(565)] < 0 || e[x(565)] > 1) return o(x(459));
182
+ if (e[x(544)] === void 0 || e[x(544)] < 0) return o(x(537));
183
+ const t = await this.parseOriginalGif(e[x(509)]);
184
+ if (t[x(586)]()) return o(x(548), t[x(556)]());
185
+ const n = t[x(540)]();
186
+ return await this.doCompressOnce(n, e);
187
+ }
188
+ async [u(577)](e) {
189
+ const x = u;
190
+ try {
191
+ const t = await this.runGifsicle([{ file: e, name: x(526) }], [x(574)]);
192
+ if (t.isErr()) return o("PARSING_FAILED", t[x(556)]());
193
+ const n = t[x(540)]();
194
+ if (n[x(561)] === 0) return o(x(475), x(528));
195
+ const s = n[0];
196
+ if (!s) return o(x(475), x(578));
197
+ const f = await s.text(), l = f.split(`
198
+ `), d = l.find((p) => p[x(498)](x(525)));
199
+ if (!d) return o(x(497));
200
+ const c = d[x(490)](x(525), "")[x(533)]()[x(520)]("x");
201
+ if (c[x(561)] !== 2) return o(x(497), x(478));
202
+ const i = c[0]?.[x(533)](), a = c[1]?.[x(533)]();
203
+ if (!i || !a) return o(x(497), x(458));
204
+ const I = parseInt(i, 10), h = parseInt(a, 10);
205
+ if (isNaN(I) || isNaN(h)) return o("INVALID_GIF_DIMENSIONS", x(593));
206
+ let D = null;
207
+ const y = l[x(510)]((p) => p.includes(x(495)));
208
+ if (y) {
209
+ const p = y.replace(x(495), "").replace("[", "")[x(490)]("]", "")[x(533)]();
210
+ D = parseInt(p, 10) || null;
211
+ }
212
+ const L = l.find((p) => {
213
+ const m = x, R = p[m(533)]();
214
+ return R[m(522)]("*") && R.endsWith("images");
215
+ });
216
+ if (!L) return o(x(512));
217
+ const w = L[x(490)](x(467), "")[x(533)]()[x(520)](" ")[x(471)](), E = w ? parseInt(w, 10) : NaN;
218
+ if (isNaN(E)) return o(x(512), x(539));
219
+ const G = [];
220
+ for (const p of l)
221
+ if (p[x(498)]("delay")) {
222
+ const m = p[x(541)](x(487));
223
+ if (m !== -1) {
224
+ const R = p[x(493)](m + 5)[x(533)]()[x(490)]("s", ""), P = parseFloat(R);
225
+ !isNaN(P) && G.push(Math[x(496)](P * 1e3));
226
+ }
227
+ }
228
+ const b = G[x(524)]((p, m) => ({ index: m, delay: p }));
229
+ let g = b;
230
+ if (b[x(561)] !== E) {
231
+ if (b.length === 0) return o(x(548), x(519));
232
+ if (b[x(561)] > E) g = b[x(493)](0, E);
233
+ else {
234
+ const p = b[b[x(561)] - 1][x(487)];
235
+ g = [...b];
236
+ for (let m = b[x(561)]; m < E; m++)
237
+ g.push({ index: m, delay: p });
238
+ }
239
+ }
240
+ const U = e[x(562)] / 1024;
241
+ return S.ok({ size: U, width: I, height: h, colorTableSize: D, frameNum: E, frames: g });
242
+ } catch (t) {
243
+ return o("PARSING_FAILED", t instanceof Error ? t[x(553)] : String(t));
244
+ }
245
+ }
246
+ async resetDelayGif(e, x) {
247
+ const t = u;
248
+ if (!x) return S.ok(e);
249
+ const n = ["input.gif " + x + t(552)], s = await this[t(550)]([{ file: e, name: t(526) }], n);
250
+ if (s[t(586)]()) return o("RESET_DELAY_FAILED", s[t(556)]());
251
+ const f = s[t(540)]();
252
+ return f[t(561)] === 0 ? o(t(475), t(511)) : S.ok(f[0]);
253
+ }
254
+ async [u(473)](e, x, t, n, s, f, l, d, c) {
255
+ const i = u;
256
+ if (f >= O[i(559)]) return o(i(482));
257
+ const a = n || "", I = [i(535) + x + i(463) + l + " " + a + i(552)], h = await this.runGifsicle([{ file: e, name: "input.gif" }], I);
258
+ if (h[i(586)]()) return o(i(507), h[i(556)]());
259
+ const D = h[i(540)]();
260
+ if (D[i(561)] === 0) return o(i(507), i(579));
261
+ const y = D[0];
262
+ if (t === null) {
263
+ const E = await this[i(542)](y, s);
264
+ if (E[i(586)]()) return E;
265
+ const G = E[i(540)](), b = await G.arrayBuffer(), g = new Blob([b], { type: i(591) });
266
+ return S.ok(g);
267
+ }
268
+ const L = y[i(562)];
269
+ if (L <= t) {
270
+ const E = await this.resetDelayGif(y, s);
271
+ if (E[i(586)]()) return E;
272
+ const G = E.unwrap(), b = await G[i(470)](), g = new Blob([b], { type: i(591) });
273
+ return S.ok(g);
274
+ }
275
+ if (c !== null && Math.abs(L - c) / e.size <= O[i(491)]) {
276
+ if (d + 1 > O[i(468)]) return o(i(507), i(579));
277
+ const b = this[i(465)](L);
278
+ return this[i(473)](e, x, t, n, s, f + 1, l + b, d + 1, L);
279
+ }
280
+ const w = this[i(465)](L);
281
+ return this[i(473)](e, x, t, n, s, f + 1, l + w, 0, L);
282
+ }
283
+ async doCompressOnce(e, x) {
284
+ const t = u, n = x[t(509)];
285
+ if (!n) return S.err(t(477));
286
+ let s;
287
+ if (x[t(474)] !== void 0) s = x[t(474)];
288
+ else if (x.height !== void 0) {
289
+ const c = e[t(474)] / e[t(566)];
290
+ s = Math.round(x[t(566)] * c);
291
+ } else s = e[t(474)];
292
+ const f = x[t(544)] > 0 ? x[t(544)] * 1024 : null, { deleteParam: l, delayParam: d } = this.convertDropFrame(x[t(565)], e);
293
+ try {
294
+ const c = this[t(465)](n[t(562)]);
295
+ return await this[t(473)](n, s, f, l, d, 0, c, 0, null);
296
+ } catch (c) {
297
+ return S[t(583)](c instanceof Error ? c.message : String(c));
298
+ }
299
+ }
300
+ }
301
+ const a0 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
302
+ __proto__: null,
303
+ GifCompressor: Q,
304
+ interfaces: V
305
+ }, Symbol.toStringTag, { value: "Module" }));
306
+ (function(r, e) {
307
+ for (var x = x0, t = r(); ; )
308
+ try {
309
+ var n = parseInt(x(440)) / 1 * (-parseInt(x(436)) / 2) + parseInt(x(434)) / 3 * (-parseInt(x(438)) / 4) + -parseInt(x(439)) / 5 * (-parseInt(x(433)) / 6) + -parseInt(x(441)) / 7 * (-parseInt(x(437)) / 8) + parseInt(x(435)) / 9 * (-parseInt(x(442)) / 10) + -parseInt(x(443)) / 11 + parseInt(x(444)) / 12;
310
+ if (n === e) break;
311
+ t.push(t.shift());
312
+ } catch {
313
+ t.push(t.shift());
314
+ }
315
+ })(T, 673755);
316
+ function x0(r, e) {
317
+ r = r - 433;
318
+ var x = T(), t = x[r];
319
+ return t;
320
+ }
321
+ function T() {
322
+ var r = ["34897IxYVkE", "21UHZecD", "1140850JmtLIf", "6792687ZkhNtJ", "34607988jqzpVW", "1532334mDxJSO", "58347ezNIrB", "9XydKSY", "76SHyElW", "298864mFekKE", "212sQFlrs", "15ejaveP"];
323
+ return T = function() {
324
+ return r;
325
+ }, T();
326
+ }
327
+ export {
328
+ a0 as gifCompress
329
+ };
Binary file
Binary file
Binary file
Binary file
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "mng-cli",
3
+ "private": false,
4
+ "version": "1.0.0",
5
+ "type": "module",
6
+ "files": ["dist", "package.json"],
7
+ "devDependencies": {
8
+ "@types/node": "^22.10.6",
9
+ "@vitest/ui": "^2.1.8",
10
+ "cpx": "^1.5.0",
11
+ "javascript-obfuscator": "^5.1.0",
12
+ "rollup-plugin-obfuscator": "^1.1.0",
13
+ "ts-node": "^10.9.2",
14
+ "vite": "^6.2.0",
15
+ "vite-plugin-copy": "^0.1.6",
16
+ "vite-plugin-dts": "^4.5.4",
17
+ "vitest": "^2.1.8"
18
+ },
19
+ "peerDependencies": {
20
+ "typescript": "^5.9.3"
21
+ },
22
+ "main": "dist/index.js",
23
+ "module": "dist/index.js",
24
+ "types": "dist/index.d.ts",
25
+ "exports": "./dist/index.js",
26
+ "dependencies": {
27
+ "bin-build": "^3.0.0",
28
+ "bin-wrapper": "^4.0.0",
29
+ "execa": "^6.1.0",
30
+ "mng-base": "^1.3.3"
31
+ },
32
+ "scripts": {
33
+ "dev": "node --loader ts-node/esm src/index.ts",
34
+ "build": "vite build && cpx \"src/gifsicle-bin/vendor/**/*\" \"dist/vendor\"",
35
+ "test": "vitest",
36
+ "test:ui": "vitest --ui",
37
+ "coverage": "vitest --coverage"
38
+ }
39
+ }