cordova-13/scripts/logo.ts
2024-12-17 09:23:24 +08:00

180 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import * as fs from 'fs';
import { resolve } from 'path';
import { execSync } from 'child_process';
import * as path from 'path';
import consola from 'consola';
import axios from 'axios';
import { URL } from 'url';
// 错误信息常量
const ErrorMessages = {
NO_SOURCE: '请提供源文件路径或URL',
INVALID_FILE_TYPE: '无效的文件类型,仅支持 PNG、JPG、JPEG 和 GIF',
FILE_NOT_EXIST: '源文件不存在',
DOWNLOAD_FAILED: '文件下载失败:',
COPY_FAILED: '文件复制失败:',
CONVERT_FAILED: '文件转换失败:',
UNEXPECTED_ERROR: '发生意外错误:',
};
// 配置常量
const CONFIG = {
ALLOWED_EXTENSIONS: ['.png', '.jpg', '.jpeg', '.gif'],
OUTPUT_FILENAME: 'logo.png',
TEMP_PREFIX: 'temp-logo-'
};
/**
* 从URL下载文件到指定目录
* @param url 文件的URL地址
* @param destination 目标保存路径
*/
async function downloadFile(url: string, destination: string): Promise<void> {
try {
const response = await axios({
url,
method: 'GET',
responseType: 'stream',
timeout: 10000 // 10秒超时
});
const writer = fs.createWriteStream(destination);
response.data.pipe(writer);
return new Promise((resolve, reject) => {
writer.on('finish', resolve);
writer.on('error', reject);
});
} catch (error) {
throw new Error(`${ErrorMessages.DOWNLOAD_FAILED} ${error.message}`);
}
}
/**
* 转换图片为PNG格式
* @param source 源文件路径
* @param destination 目标文件路径
*/
function convertToPng(source: string, destination: string): void {
try {
// 使用 ImageMagick 转换图片格式
execSync(`convert "${source}" "${destination}"`);
} catch (error) {
throw new Error(`${ErrorMessages.CONVERT_FAILED} ${error.message}`);
}
}
/**
* 验证字符串是否为有效URL
* @param string 待验证的字符串
*/
function isValidUrl(string: string): boolean {
try {
new URL(string);
return true;
} catch {
return false;
}
}
/**
* 验证文件是否为支持的图片类型
* @param filePath 文件路径
*/
function isValidImageFile(filePath: string): boolean {
const ext = path.extname(filePath).toLowerCase();
return CONFIG.ALLOWED_EXTENSIONS.includes(ext);
}
/**
* 清理临时文件
* @param filePath 文件路径
*/
function cleanupTempFile(filePath: string): void {
if (fs.existsSync(filePath)) {
try {
fs.unlinkSync(filePath);
} catch (error) {
consola.warn('清理临时文件失败:', error.message);
}
}
}
/**
* 主函数 - 处理Logo替换逻辑
*/
async function main(): Promise<void> {
const tempFiles: string[] = [];
try {
// 获取命令行参数中的源文件路径
const sourcePath = process.argv[2];
if (!sourcePath) {
throw new Error(ErrorMessages.NO_SOURCE);
}
const baseDir: string = resolve('./');
const finalDestination = path.join(baseDir, CONFIG.OUTPUT_FILENAME);
// 打印初始信息
consola.info('开始处理Logo');
consola.info('源文件:', sourcePath);
consola.info('目标位置:', finalDestination);
// 验证文件类型
if (!isValidImageFile(sourcePath)) {
throw new Error(ErrorMessages.INVALID_FILE_TYPE);
}
// 处理URL或本地文件
if (isValidUrl(sourcePath)) {
consola.info('正在从URL下载文件...');
const tempFile = path.join(baseDir, CONFIG.TEMP_PREFIX + Date.now() + path.extname(sourcePath));
tempFiles.push(tempFile);
// 下载文件
await downloadFile(sourcePath, tempFile);
consola.success('文件下载完成');
// 转换为PNG如果需要
if (path.extname(tempFile).toLowerCase() !== '.png') {
consola.info('正在转换为PNG格式...');
convertToPng(tempFile, finalDestination);
} else {
fs.copyFileSync(tempFile, finalDestination);
}
} else {
// 处理本地文件
const localPath = path.resolve(sourcePath);
if (!fs.existsSync(localPath)) {
throw new Error(ErrorMessages.FILE_NOT_EXIST);
}
// 转换为PNG如果需要
if (path.extname(localPath).toLowerCase() !== '.png') {
consola.info('正在转换为PNG格式...');
convertToPng(localPath, finalDestination);
} else {
fs.copyFileSync(localPath, finalDestination);
}
}
consola.success('Logo处理完成');
consola.info(`文件已保存至: ${finalDestination}`);
} catch (error) {
consola.error('Logo处理失败:', error.message);
process.exit(1);
} finally {
// 清理所有临时文件
tempFiles.forEach(cleanupTempFile);
}
}
// 执行主函数
main().catch(error => {
consola.error(ErrorMessages.UNEXPECTED_ERROR, error);
process.exit(1);
});