ai-yuca 1.3.7 → 1.3.8
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/bin/cli.js +12 -0
- package/dist/package.json +4 -2
- package/dist/src/sharp.d.ts +2 -0
- package/dist/src/sharp.js +134 -0
- package/dist/src/types/index.d.ts +1 -0
- package/dist/src/types/index.js +2 -0
- package/dist/src/types/sharp.d.ts +6 -0
- package/dist/src/types/sharp.js +2 -0
- package/package.json +4 -2
package/dist/bin/cli.js
CHANGED
|
@@ -45,6 +45,7 @@ const download_1 = require("../src/download");
|
|
|
45
45
|
const uploadWithConfig_1 = require("../src/uploadWithConfig");
|
|
46
46
|
const deploy_1 = require("../src/deploy");
|
|
47
47
|
const pullCrowdin_1 = require("../src/pullCrowdin");
|
|
48
|
+
const sharp_1 = require("../src/sharp");
|
|
48
49
|
const program = new commander_1.Command();
|
|
49
50
|
// 设置版本和描述
|
|
50
51
|
program
|
|
@@ -59,6 +60,17 @@ program
|
|
|
59
60
|
.action((options) => {
|
|
60
61
|
(0, index_1.analyze)(options);
|
|
61
62
|
});
|
|
63
|
+
// 添加sharp命令
|
|
64
|
+
program
|
|
65
|
+
.command('sharp')
|
|
66
|
+
.description('压缩图片文件 (jpg, png, webp)')
|
|
67
|
+
.requiredOption('-s, --source <path>', '资源文件夹')
|
|
68
|
+
.requiredOption('-o, --output <path>', '导出的文件夹地址')
|
|
69
|
+
.option('-q, --quality <number>', '压缩质量 (1-100)', '80')
|
|
70
|
+
.option('-f, --force', '强制压缩,即使目标文件已存在')
|
|
71
|
+
.action(async (options) => {
|
|
72
|
+
await (0, sharp_1.compressImages)(options);
|
|
73
|
+
});
|
|
62
74
|
// 添加deploy命令
|
|
63
75
|
program
|
|
64
76
|
.command('deploy')
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-yuca",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.8",
|
|
4
4
|
"description": "一个用AI生成的开发辅助工具",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -31,13 +31,15 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@google-cloud/storage": "^7.17.1",
|
|
34
|
+
"@types/sharp": "^0.32.0",
|
|
34
35
|
"axios": "^1.12.1",
|
|
35
36
|
"chalk": "^4.1.2",
|
|
36
37
|
"commander": "^10.0.0",
|
|
37
38
|
"fast-glob": "^3.3.3",
|
|
38
39
|
"inquirer": "^12.9.4",
|
|
39
40
|
"md5-file": "^5.0.0",
|
|
40
|
-
"mime-types": "^3.0.1"
|
|
41
|
+
"mime-types": "^3.0.1",
|
|
42
|
+
"sharp": "^0.34.5"
|
|
41
43
|
},
|
|
42
44
|
"devDependencies": {
|
|
43
45
|
"@types/chai": "^5.2.2",
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.compressImages = compressImages;
|
|
40
|
+
const sharp_1 = __importDefault(require("sharp"));
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
44
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
45
|
+
async function compressImages(options) {
|
|
46
|
+
const { source, output, quality, force } = options;
|
|
47
|
+
const qualityNum = quality ? parseInt(quality, 10) : 80;
|
|
48
|
+
if (!source) {
|
|
49
|
+
console.error(chalk_1.default.red('错误: 必须提供源文件夹路径 (-s)'));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (!output) {
|
|
53
|
+
console.error(chalk_1.default.red('错误: 必须提供导出文件夹路径 (-o)'));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const sourceAbs = path.resolve(process.cwd(), source);
|
|
57
|
+
const outputAbs = path.resolve(process.cwd(), output);
|
|
58
|
+
if (!fs.existsSync(sourceAbs)) {
|
|
59
|
+
console.error(chalk_1.default.red(`源文件夹不存在: ${sourceAbs}`));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (!fs.existsSync(outputAbs)) {
|
|
63
|
+
try {
|
|
64
|
+
fs.mkdirSync(outputAbs, { recursive: true });
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
console.error(chalk_1.default.red(`无法创建导出文件夹: ${err}`));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
console.log(chalk_1.default.blue(`源目录: ${sourceAbs}`));
|
|
72
|
+
console.log(chalk_1.default.blue(`导出目录: ${outputAbs}`));
|
|
73
|
+
console.log(chalk_1.default.blue(`压缩质量: ${qualityNum}`));
|
|
74
|
+
// 支持的图片格式
|
|
75
|
+
const patterns = ['**/*.{jpg,jpeg,png,webp,JPG,JPEG,PNG,WEBP}'];
|
|
76
|
+
try {
|
|
77
|
+
const files = await (0, fast_glob_1.default)(patterns, { cwd: sourceAbs, absolute: false });
|
|
78
|
+
if (files.length === 0) {
|
|
79
|
+
console.log(chalk_1.default.yellow('未找到任何图片文件。'));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
console.log(chalk_1.default.blue(`找到 ${files.length} 个图片文件,开始压缩...`));
|
|
83
|
+
let successCount = 0;
|
|
84
|
+
let failCount = 0;
|
|
85
|
+
for (const file of files) {
|
|
86
|
+
const sourcePath = path.join(sourceAbs, file);
|
|
87
|
+
const outputPath = path.join(outputAbs, file);
|
|
88
|
+
const outputDir = path.dirname(outputPath);
|
|
89
|
+
if (!fs.existsSync(outputDir)) {
|
|
90
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
91
|
+
}
|
|
92
|
+
if (fs.existsSync(outputPath) && !force) {
|
|
93
|
+
console.log(chalk_1.default.yellow(`跳过 (已存在): ${path.basename(sourcePath)}`));
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const ext = path.extname(file).toLowerCase();
|
|
98
|
+
const image = (0, sharp_1.default)(sourcePath);
|
|
99
|
+
// 获取图片元数据
|
|
100
|
+
const metadata = await image.metadata();
|
|
101
|
+
if (ext === '.jpg' || ext === '.jpeg') {
|
|
102
|
+
await image.jpeg({ quality: qualityNum }).toFile(outputPath);
|
|
103
|
+
}
|
|
104
|
+
else if (ext === '.png') {
|
|
105
|
+
// PNG压缩策略:如果质量小于100,尝试使用palette量化以减少体积
|
|
106
|
+
// 注意:sharp默认的png压缩是无损的,除非指定palette或quality
|
|
107
|
+
await image.png({ quality: qualityNum, compressionLevel: 9 }).toFile(outputPath);
|
|
108
|
+
}
|
|
109
|
+
else if (ext === '.webp') {
|
|
110
|
+
await image.webp({ quality: qualityNum }).toFile(outputPath);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// 其他格式如果不特别处理,可以尝试直接输出或复制
|
|
114
|
+
// 这里我们假设 fastGlob 只匹配了我们支持的格式,所以应该不会走到这里
|
|
115
|
+
// 但为了健壮性,直接复制
|
|
116
|
+
await fs.promises.copyFile(sourcePath, outputPath);
|
|
117
|
+
}
|
|
118
|
+
const srcStats = fs.statSync(sourcePath);
|
|
119
|
+
const destStats = fs.statSync(outputPath);
|
|
120
|
+
const saved = ((srcStats.size - destStats.size) / srcStats.size * 100).toFixed(2);
|
|
121
|
+
console.log(chalk_1.default.green(`已处理: ${path.basename(sourcePath)} | 原始: ${(srcStats.size / 1024).toFixed(2)}KB -> 压缩: ${(destStats.size / 1024).toFixed(2)}KB | 节省: ${saved}% | 图片尺寸: ${metadata === null || metadata === void 0 ? void 0 : metadata.width} * ${metadata.height}`));
|
|
122
|
+
successCount++;
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
console.error(chalk_1.default.red(`✗ ${file}: ${error}`));
|
|
126
|
+
failCount++;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
console.log(chalk_1.default.blue(`\n压缩完成! 成功: ${successCount}, 失败: ${failCount}`));
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
console.error(chalk_1.default.red(`发生错误: ${err}`));
|
|
133
|
+
}
|
|
134
|
+
}
|
package/dist/src/types/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-yuca",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.8",
|
|
4
4
|
"description": "一个用AI生成的开发辅助工具",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -31,13 +31,15 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@google-cloud/storage": "^7.17.1",
|
|
34
|
+
"@types/sharp": "^0.32.0",
|
|
34
35
|
"axios": "^1.12.1",
|
|
35
36
|
"chalk": "^4.1.2",
|
|
36
37
|
"commander": "^10.0.0",
|
|
37
38
|
"fast-glob": "^3.3.3",
|
|
38
39
|
"inquirer": "^12.9.4",
|
|
39
40
|
"md5-file": "^5.0.0",
|
|
40
|
-
"mime-types": "^3.0.1"
|
|
41
|
+
"mime-types": "^3.0.1",
|
|
42
|
+
"sharp": "^0.34.5"
|
|
41
43
|
},
|
|
42
44
|
"devDependencies": {
|
|
43
45
|
"@types/chai": "^5.2.2",
|