mirror of
https://github.com/lobehub/lobehub
synced 2026-04-21 09:37:28 +00:00
🌐 chore: translate non-English comments to English in scripts (#13690)
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b268f44f06
commit
f804d0fc7c
8 changed files with 77 additions and 77 deletions
|
|
@ -18,7 +18,7 @@ import {
|
||||||
root,
|
root,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
||||||
// 定义常量
|
// Define constants
|
||||||
const GITHUB_CDN = 'https://github.com/lobehub/lobe-chat/assets/';
|
const GITHUB_CDN = 'https://github.com/lobehub/lobe-chat/assets/';
|
||||||
const CHECK_CDN = [
|
const CHECK_CDN = [
|
||||||
'https://cdn.nlark.com/yuque/0/',
|
'https://cdn.nlark.com/yuque/0/',
|
||||||
|
|
@ -41,7 +41,7 @@ class ImageCDNUploader {
|
||||||
this.loadCache();
|
this.loadCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从文件加载缓存数据
|
// Load cache data from file
|
||||||
private loadCache() {
|
private loadCache() {
|
||||||
try {
|
try {
|
||||||
this.cache = JSON.parse(readFileSync(CACHE_FILE, 'utf8'));
|
this.cache = JSON.parse(readFileSync(CACHE_FILE, 'utf8'));
|
||||||
|
|
@ -50,7 +50,7 @@ class ImageCDNUploader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将缓存数据写入文件
|
// Write cache data to file
|
||||||
private writeCache() {
|
private writeCache() {
|
||||||
try {
|
try {
|
||||||
writeFileSync(CACHE_FILE, JSON.stringify(this.cache, null, 2));
|
writeFileSync(CACHE_FILE, JSON.stringify(this.cache, null, 2));
|
||||||
|
|
@ -59,18 +59,18 @@ class ImageCDNUploader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 收集所有的图片链接
|
// Collect all image links
|
||||||
private collectImageLinks(): string[] {
|
private collectImageLinks(): string[] {
|
||||||
const links: string[][] = posts.map((post) => {
|
const links: string[][] = posts.map((post) => {
|
||||||
const mdx = readFileSync(post, 'utf8');
|
const mdx = readFileSync(post, 'utf8');
|
||||||
const { content, data } = matter(mdx);
|
const { content, data } = matter(mdx);
|
||||||
const inlineLinks: string[] = extractHttpsLinks(content);
|
const inlineLinks: string[] = extractHttpsLinks(content);
|
||||||
|
|
||||||
// 添加特定字段中的图片链接
|
// Add image links from specific fields
|
||||||
if (data?.image) inlineLinks.push(data.image);
|
if (data?.image) inlineLinks.push(data.image);
|
||||||
if (data?.seo?.image) inlineLinks.push(data.seo.image);
|
if (data?.seo?.image) inlineLinks.push(data.seo.image);
|
||||||
|
|
||||||
// 过滤出有效的 CDN 链接
|
// Filter out valid CDN links
|
||||||
return inlineLinks.filter(
|
return inlineLinks.filter(
|
||||||
(link) =>
|
(link) =>
|
||||||
(link.startsWith(GITHUB_CDN) || CHECK_CDN.some((cdn) => link.startsWith(cdn))) &&
|
(link.startsWith(GITHUB_CDN) || CHECK_CDN.some((cdn) => link.startsWith(cdn))) &&
|
||||||
|
|
@ -96,11 +96,11 @@ class ImageCDNUploader {
|
||||||
!this.cache[link],
|
!this.cache[link],
|
||||||
) as string[];
|
) as string[];
|
||||||
|
|
||||||
// 合并和去重链接数组
|
// Merge and deduplicate link arrays
|
||||||
return mergeAndDeduplicateArrays(links.flat().concat(communityLinks, cloudLinks));
|
return mergeAndDeduplicateArrays(links.flat().concat(communityLinks, cloudLinks));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 上传图片到 CDN
|
// Upload images to CDN
|
||||||
private async uploadImagesToCDN(links: string[]) {
|
private async uploadImagesToCDN(links: string[]) {
|
||||||
const cdnLinks: { [link: string]: string } = {};
|
const cdnLinks: { [link: string]: string } = {};
|
||||||
|
|
||||||
|
|
@ -120,12 +120,12 @@ class ImageCDNUploader {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 更新缓存
|
// Update cache
|
||||||
this.cache = { ...this.cache, ...cdnLinks };
|
this.cache = { ...this.cache, ...cdnLinks };
|
||||||
this.writeCache();
|
this.writeCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据不同的 CDN 来处理文件上传
|
// Handle file upload based on CDN type
|
||||||
private async uploadFileToCDN(file: File, link: string): Promise<string | undefined> {
|
private async uploadFileToCDN(file: File, link: string): Promise<string | undefined> {
|
||||||
if (link.startsWith(GITHUB_CDN)) {
|
if (link.startsWith(GITHUB_CDN)) {
|
||||||
const filename = link.replaceAll(GITHUB_CDN, '');
|
const filename = link.replaceAll(GITHUB_CDN, '');
|
||||||
|
|
@ -139,7 +139,7 @@ class ImageCDNUploader {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 替换文章中的图片链接
|
// Replace image links in posts
|
||||||
private replaceLinksInPosts() {
|
private replaceLinksInPosts() {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
|
|
@ -155,7 +155,7 @@ class ImageCDNUploader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新特定字段的图片链接
|
// Update image links in specific fields
|
||||||
|
|
||||||
if (data['image'] && this.cache[data['image']]) {
|
if (data['image'] && this.cache[data['image']]) {
|
||||||
data['image'] = this.cache[data['image']];
|
data['image'] = this.cache[data['image']];
|
||||||
|
|
@ -206,7 +206,7 @@ class ImageCDNUploader {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 运行上传过程
|
// Run upload process
|
||||||
async run() {
|
async run() {
|
||||||
const links = this.collectImageLinks();
|
const links = this.collectImageLinks();
|
||||||
|
|
||||||
|
|
@ -218,13 +218,13 @@ class ImageCDNUploader {
|
||||||
consola.info('No new images to upload.');
|
consola.info('No new images to upload.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 替换文章和 changelog index 中的图片链接
|
// Replace image links in posts and changelog index
|
||||||
this.replaceLinksInPosts();
|
this.replaceLinksInPosts();
|
||||||
this.replaceLinksInChangelogIndex();
|
this.replaceLinksInChangelogIndex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 实例化并运行
|
// Instantiate and run
|
||||||
const instance = new ImageCDNUploader();
|
const instance = new ImageCDNUploader();
|
||||||
|
|
||||||
instance.run();
|
instance.run();
|
||||||
|
|
|
||||||
|
|
@ -39,12 +39,12 @@ export const mergeAndDeduplicateArrays = (...arrays: string[][]) => {
|
||||||
|
|
||||||
const mimeToExtensions = {
|
const mimeToExtensions = {
|
||||||
'image/gif': '.gif',
|
'image/gif': '.gif',
|
||||||
// 图片类型
|
// Image types
|
||||||
'image/jpeg': '.jpg',
|
'image/jpeg': '.jpg',
|
||||||
'image/png': '.png',
|
'image/png': '.png',
|
||||||
'image/svg+xml': '.svg',
|
'image/svg+xml': '.svg',
|
||||||
'image/webp': '.webp',
|
'image/webp': '.webp',
|
||||||
// 视频类型
|
// Video types
|
||||||
'video/mp4': '.mp4',
|
'video/mp4': '.mp4',
|
||||||
'video/mpeg': '.mpeg',
|
'video/mpeg': '.mpeg',
|
||||||
'video/ogg': '.ogv',
|
'video/ogg': '.ogv',
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,7 @@ async function migrateFromClerk() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clerk API 不返回 credential external_account;若用户开启密码并且 CSV 提供散列,则补齐本地密码账号
|
// Clerk API does not return credential external_account; if the user has password enabled and the CSV provides a hash, supplement the local password account
|
||||||
const passwordEnabled = Boolean(clerkUser?.password_enabled);
|
const passwordEnabled = Boolean(clerkUser?.password_enabled);
|
||||||
if (passwordEnabled && user.password_digest) {
|
if (passwordEnabled && user.password_digest) {
|
||||||
const passwordUpdatedAt = clerkUser?.password_last_updated_at;
|
const passwordUpdatedAt = clerkUser?.password_last_updated_at;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
|
|
||||||
// 配置项
|
// Configuration
|
||||||
const config: Config = {
|
const config: Config = {
|
||||||
dirPath: './locales/en-US', // 替换为你的目录路径
|
dirPath: './locales/en-US', // Replace with your directory path
|
||||||
ignoredFiles: ['models', 'providers', 'auth'], // 需要忽略的文件名
|
ignoredFiles: ['models', 'providers', 'auth'], // Files to ignore
|
||||||
};
|
};
|
||||||
|
|
||||||
interface FileCount {
|
interface FileCount {
|
||||||
|
|
@ -17,13 +17,13 @@ interface Config {
|
||||||
ignoredFiles: string[];
|
ignoredFiles: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 统计字符串中的字符数量
|
// Count the number of characters in a string
|
||||||
function countChineseChars(str: string): number {
|
function countChineseChars(str: string): number {
|
||||||
if (typeof str !== 'string') return 0;
|
if (typeof str !== 'string') return 0;
|
||||||
return str.split(' ').length;
|
return str.split(' ').length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 递归处理对象中的所有值
|
// Recursively process all values in an object
|
||||||
function processValue(value: any): number {
|
function processValue(value: any): number {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
|
|
@ -42,7 +42,7 @@ function processValue(value: any): number {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 读取并处理 JSON 文件
|
// Read and process JSON file
|
||||||
function processJsonFile(filePath: string): number {
|
function processJsonFile(filePath: string): number {
|
||||||
try {
|
try {
|
||||||
const content = fs.readFileSync(filePath, 'utf8');
|
const content = fs.readFileSync(filePath, 'utf8');
|
||||||
|
|
@ -54,7 +54,7 @@ function processJsonFile(filePath: string): number {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 递归遍历目录
|
// Recursively traverse directory
|
||||||
function traverseDirectory(dirPath: string, ignoredFiles: string[]): FileCount[] {
|
function traverseDirectory(dirPath: string, ignoredFiles: string[]): FileCount[] {
|
||||||
const results: FileCount[] = [];
|
const results: FileCount[] = [];
|
||||||
const files = fs.readdirSync(dirPath);
|
const files = fs.readdirSync(dirPath);
|
||||||
|
|
@ -64,7 +64,7 @@ function traverseDirectory(dirPath: string, ignoredFiles: string[]): FileCount[]
|
||||||
const stat = fs.statSync(fullPath);
|
const stat = fs.statSync(fullPath);
|
||||||
const filename = path.parse(file).name;
|
const filename = path.parse(file).name;
|
||||||
|
|
||||||
// 跳过被忽略的文件
|
// Skip ignored files
|
||||||
if (ignoredFiles.includes(filename)) {
|
if (ignoredFiles.includes(filename)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -80,7 +80,7 @@ function traverseDirectory(dirPath: string, ignoredFiles: string[]): FileCount[]
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 主函数
|
// Main function
|
||||||
function main(config: Config): void {
|
function main(config: Config): void {
|
||||||
const { dirPath, ignoredFiles } = config;
|
const { dirPath, ignoredFiles } = config;
|
||||||
|
|
||||||
|
|
@ -89,13 +89,13 @@ function main(config: Config): void {
|
||||||
|
|
||||||
const results = traverseDirectory(dirPath, ignoredFiles);
|
const results = traverseDirectory(dirPath, ignoredFiles);
|
||||||
|
|
||||||
// 按单词数降序排序
|
// Sort by word count in descending order
|
||||||
const sortedResults = results.sort((a, b) => b.count - a.count);
|
const sortedResults = results.sort((a, b) => b.count - a.count);
|
||||||
|
|
||||||
// 计算总数
|
// Calculate total count
|
||||||
const totalCount = results.reduce((sum, item) => sum + item.count, 0);
|
const totalCount = results.reduce((sum, item) => sum + item.count, 0);
|
||||||
|
|
||||||
// 输出结果
|
// Output results
|
||||||
console.log('文件统计结果(按单词数降序):');
|
console.log('文件统计结果(按单词数降序):');
|
||||||
console.log('----------------------------------------');
|
console.log('----------------------------------------');
|
||||||
sortedResults.forEach(({ filename, count }) => {
|
sortedResults.forEach(({ filename, count }) => {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import {
|
||||||
root,
|
root,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
||||||
// 定义常量
|
// Define constants
|
||||||
const GITHUB_CDN = 'https://github.com/lobehub/lobe-chat/assets/';
|
const GITHUB_CDN = 'https://github.com/lobehub/lobe-chat/assets/';
|
||||||
const CHECK_CDN = [
|
const CHECK_CDN = [
|
||||||
'https://cdn.nlark.com/yuque/0/',
|
'https://cdn.nlark.com/yuque/0/',
|
||||||
|
|
@ -38,7 +38,7 @@ class ImageCDNUploader {
|
||||||
this.loadCache();
|
this.loadCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从文件加载缓存数据
|
// Load cache data from file
|
||||||
private loadCache() {
|
private loadCache() {
|
||||||
try {
|
try {
|
||||||
this.cache = JSON.parse(readFileSync(CACHE_FILE, 'utf8'));
|
this.cache = JSON.parse(readFileSync(CACHE_FILE, 'utf8'));
|
||||||
|
|
@ -47,7 +47,7 @@ class ImageCDNUploader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将缓存数据写入文件
|
// Write cache data to file
|
||||||
private writeCache() {
|
private writeCache() {
|
||||||
try {
|
try {
|
||||||
writeFileSync(CACHE_FILE, JSON.stringify(this.cache, null, 2));
|
writeFileSync(CACHE_FILE, JSON.stringify(this.cache, null, 2));
|
||||||
|
|
@ -56,18 +56,18 @@ class ImageCDNUploader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 收集所有的图片链接
|
// Collect all image links
|
||||||
private collectImageLinks(): string[] {
|
private collectImageLinks(): string[] {
|
||||||
const links: string[][] = posts.map((post) => {
|
const links: string[][] = posts.map((post) => {
|
||||||
const mdx = readFileSync(post, 'utf8');
|
const mdx = readFileSync(post, 'utf8');
|
||||||
const { content, data } = matter(mdx);
|
const { content, data } = matter(mdx);
|
||||||
const inlineLinks: string[] = extractHttpsLinks(content);
|
const inlineLinks: string[] = extractHttpsLinks(content);
|
||||||
|
|
||||||
// 添加特定字段中的图片链接
|
// Add image links from specific fields
|
||||||
if (data?.image) inlineLinks.push(data.image);
|
if (data?.image) inlineLinks.push(data.image);
|
||||||
if (data?.seo?.image) inlineLinks.push(data.seo.image);
|
if (data?.seo?.image) inlineLinks.push(data.seo.image);
|
||||||
|
|
||||||
// 过滤出有效的 CDN 链接
|
// Filter out valid CDN links
|
||||||
return inlineLinks.filter(
|
return inlineLinks.filter(
|
||||||
(link) =>
|
(link) =>
|
||||||
(link.startsWith(GITHUB_CDN) || CHECK_CDN.some((cdn) => link.startsWith(cdn))) &&
|
(link.startsWith(GITHUB_CDN) || CHECK_CDN.some((cdn) => link.startsWith(cdn))) &&
|
||||||
|
|
@ -75,11 +75,11 @@ class ImageCDNUploader {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 合并和去重链接数组
|
// Merge and deduplicate link arrays
|
||||||
return mergeAndDeduplicateArrays(...links);
|
return mergeAndDeduplicateArrays(...links);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 上传图片到 CDN
|
// Upload images to CDN
|
||||||
private async uploadImagesToCDN(links: string[]) {
|
private async uploadImagesToCDN(links: string[]) {
|
||||||
const cdnLinks: { [link: string]: string } = {};
|
const cdnLinks: { [link: string]: string } = {};
|
||||||
|
|
||||||
|
|
@ -99,12 +99,12 @@ class ImageCDNUploader {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 更新缓存
|
// Update cache
|
||||||
this.cache = { ...this.cache, ...cdnLinks };
|
this.cache = { ...this.cache, ...cdnLinks };
|
||||||
this.writeCache();
|
this.writeCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据不同的 CDN 来处理文件上传
|
// Handle file upload based on CDN type
|
||||||
private async uploadFileToCDN(file: File, link: string): Promise<string | undefined> {
|
private async uploadFileToCDN(file: File, link: string): Promise<string | undefined> {
|
||||||
if (link.startsWith(GITHUB_CDN)) {
|
if (link.startsWith(GITHUB_CDN)) {
|
||||||
const filename = link.replaceAll(GITHUB_CDN, '');
|
const filename = link.replaceAll(GITHUB_CDN, '');
|
||||||
|
|
@ -118,7 +118,7 @@ class ImageCDNUploader {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 替换文章中的图片链接
|
// Replace image links in posts
|
||||||
private replaceLinksInPosts() {
|
private replaceLinksInPosts() {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
|
|
@ -134,7 +134,7 @@ class ImageCDNUploader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新特定字段的图片链接
|
// Update image links in specific fields
|
||||||
|
|
||||||
if (data['image'] && this.cache[data['image']]) {
|
if (data['image'] && this.cache[data['image']]) {
|
||||||
data['image'] = this.cache[data['image']];
|
data['image'] = this.cache[data['image']];
|
||||||
|
|
@ -152,7 +152,7 @@ class ImageCDNUploader {
|
||||||
consola.success(`${count} images have been uploaded to CDN and links have been replaced`);
|
consola.success(`${count} images have been uploaded to CDN and links have been replaced`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 运行上传过程
|
// Run upload process
|
||||||
async run() {
|
async run() {
|
||||||
const links = this.collectImageLinks();
|
const links = this.collectImageLinks();
|
||||||
|
|
||||||
|
|
@ -167,7 +167,7 @@ class ImageCDNUploader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 实例化并运行
|
// Instantiate and run
|
||||||
const instance = new ImageCDNUploader();
|
const instance = new ImageCDNUploader();
|
||||||
|
|
||||||
instance.run();
|
instance.run();
|
||||||
|
|
|
||||||
|
|
@ -61,12 +61,12 @@ export const mergeAndDeduplicateArrays = (...arrays: string[][]) => {
|
||||||
|
|
||||||
const mimeToExtensions = {
|
const mimeToExtensions = {
|
||||||
'image/gif': '.gif',
|
'image/gif': '.gif',
|
||||||
// 图片类型
|
// Image types
|
||||||
'image/jpeg': '.jpg',
|
'image/jpeg': '.jpg',
|
||||||
'image/png': '.png',
|
'image/png': '.png',
|
||||||
'image/svg+xml': '.svg',
|
'image/svg+xml': '.svg',
|
||||||
'image/webp': '.webp',
|
'image/webp': '.webp',
|
||||||
// 视频类型
|
// Video types
|
||||||
'video/mp4': '.mp4',
|
'video/mp4': '.mp4',
|
||||||
'video/mpeg': '.mpeg',
|
'video/mpeg': '.mpeg',
|
||||||
'video/ogg': '.ogv',
|
'video/ogg': '.ogv',
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ import fs from 'fs-extra';
|
||||||
|
|
||||||
type ReleaseType = 'stable' | 'beta' | 'nightly' | 'canary';
|
type ReleaseType = 'stable' | 'beta' | 'nightly' | 'canary';
|
||||||
|
|
||||||
// 获取脚本的命令行参数
|
// Get command line arguments for the script
|
||||||
const version = process.argv[2];
|
const version = process.argv[2];
|
||||||
const releaseType = process.argv[3] as ReleaseType;
|
const releaseType = process.argv[3] as ReleaseType;
|
||||||
|
|
||||||
// 验证参数
|
// Validate parameters
|
||||||
if (!version || !releaseType) {
|
if (!version || !releaseType) {
|
||||||
console.error(
|
console.error(
|
||||||
'Missing parameters. Usage: bun run setDesktopVersion.ts <version> <stable|beta|nightly|canary>',
|
'Missing parameters. Usage: bun run setDesktopVersion.ts <version> <stable|beta|nightly|canary>',
|
||||||
|
|
@ -23,14 +23,14 @@ if (!['stable', 'beta', 'nightly', 'canary'].includes(releaseType)) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取根目录
|
// Get root directory
|
||||||
const rootDir = path.resolve(__dirname, '../..');
|
const rootDir = path.resolve(__dirname, '../..');
|
||||||
|
|
||||||
// 桌面应用 package.json 的路径
|
// Path to the desktop app package.json
|
||||||
const desktopPackageJsonPath = path.join(rootDir, 'apps/desktop/package.json');
|
const desktopPackageJsonPath = path.join(rootDir, 'apps/desktop/package.json');
|
||||||
const buildDir = path.join(rootDir, 'apps/desktop/build');
|
const buildDir = path.join(rootDir, 'apps/desktop/build');
|
||||||
|
|
||||||
// 更新应用图标
|
// Update app icon
|
||||||
function updateAppIcon(type: 'beta' | 'nightly') {
|
function updateAppIcon(type: 'beta' | 'nightly') {
|
||||||
console.log(`📦 Updating app icon for ${type} version...`);
|
console.log(`📦 Updating app icon for ${type} version...`);
|
||||||
try {
|
try {
|
||||||
|
|
@ -56,7 +56,7 @@ function updateAppIcon(type: 'beta' | 'nightly') {
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(' ❌ Error updating icons:', error);
|
console.error(' ❌ Error updating icons:', error);
|
||||||
// 不终止程序,继续处理 package.json
|
// Don't terminate the program, continue processing package.json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,10 +70,10 @@ function updatePackageJson() {
|
||||||
|
|
||||||
const packageJson = fs.readJSONSync(desktopPackageJsonPath);
|
const packageJson = fs.readJSONSync(desktopPackageJsonPath);
|
||||||
|
|
||||||
// 始终更新版本号
|
// Always update the version number
|
||||||
packageJson.version = version;
|
packageJson.version = version;
|
||||||
|
|
||||||
// 根据 releaseType 修改其他字段
|
// Modify other fields based on releaseType
|
||||||
switch (releaseType) {
|
switch (releaseType) {
|
||||||
case 'stable': {
|
case 'stable': {
|
||||||
packageJson.productName = 'LobeHub';
|
packageJson.productName = 'LobeHub';
|
||||||
|
|
@ -103,7 +103,7 @@ function updatePackageJson() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 写回文件
|
// Write back to file
|
||||||
fs.writeJsonSync(desktopPackageJsonPath, packageJson, { spaces: 2 });
|
fs.writeJsonSync(desktopPackageJsonPath, packageJson, { spaces: 2 });
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
|
|
@ -115,5 +115,5 @@ function updatePackageJson() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行更新
|
// Execute update
|
||||||
updatePackageJson();
|
updatePackageJson();
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,22 @@ import { readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
||||||
import { join, relative } from 'node:path';
|
import { join, relative } from 'node:path';
|
||||||
|
|
||||||
interface ReplaceConfig {
|
interface ReplaceConfig {
|
||||||
/** 要替换的组件列表 */
|
/** List of components to replace */
|
||||||
components: string[];
|
components: string[];
|
||||||
/** 是否为 dry-run 模式(仅预览,不实际修改) */
|
/** Whether to run in dry-run mode (preview only, no actual modifications) */
|
||||||
dryRun?: boolean;
|
dryRun?: boolean;
|
||||||
/** 文件扩展名白名单 */
|
/** File extension whitelist */
|
||||||
fileExtensions?: string[];
|
fileExtensions?: string[];
|
||||||
/** 原始包名 */
|
/** Source package name */
|
||||||
fromPackage: string;
|
fromPackage: string;
|
||||||
/** 要扫描的目录 */
|
/** Directory to scan */
|
||||||
targetDir: string;
|
targetDir: string;
|
||||||
/** 目标包名 */
|
/** Target package name */
|
||||||
toPackage: string;
|
toPackage: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 递归获取目录下所有文件
|
* Recursively get all files in a directory
|
||||||
*/
|
*/
|
||||||
function getAllFiles(dir: string, extensions: string[]): string[] {
|
function getAllFiles(dir: string, extensions: string[]): string[] {
|
||||||
const files: string[] = [];
|
const files: string[] = [];
|
||||||
|
|
@ -30,7 +30,7 @@ function getAllFiles(dir: string, extensions: string[]): string[] {
|
||||||
const stat = statSync(fullPath);
|
const stat = statSync(fullPath);
|
||||||
|
|
||||||
if (stat.isDirectory()) {
|
if (stat.isDirectory()) {
|
||||||
// 跳过 node_modules 等目录
|
// Skip directories like node_modules
|
||||||
if (!['node_modules', '.git', 'dist', 'build', '.next'].includes(item)) {
|
if (!['node_modules', '.git', 'dist', 'build', '.next'].includes(item)) {
|
||||||
walk(fullPath);
|
walk(fullPath);
|
||||||
}
|
}
|
||||||
|
|
@ -48,10 +48,10 @@ function getAllFiles(dir: string, extensions: string[]): string[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析 import 语句,提取导入的组件
|
* Parse import statements and extract imported components
|
||||||
*/
|
*/
|
||||||
function parseImportStatement(line: string, packageName: string) {
|
function parseImportStatement(line: string, packageName: string) {
|
||||||
// 匹配 import { ... } from 'package'
|
// Match import { ... } from 'package'
|
||||||
const importRegex = new RegExp(
|
const importRegex = new RegExp(
|
||||||
`import\\s+{([^}]+)}\\s+from\\s+['"]${packageName.replaceAll(/[$()*+.?[\\\]^{|}]/g, '\\$&')}['"]`,
|
`import\\s+{([^}]+)}\\s+from\\s+['"]${packageName.replaceAll(/[$()*+.?[\\\]^{|}]/g, '\\$&')}['"]`,
|
||||||
);
|
);
|
||||||
|
|
@ -64,7 +64,7 @@ function parseImportStatement(line: string, packageName: string) {
|
||||||
.split(',')
|
.split(',')
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
const trimmed = item.trim();
|
const trimmed = item.trim();
|
||||||
// 处理 as 别名: ComponentName as AliasName
|
// Handle as aliases: ComponentName as AliasName
|
||||||
const asMatch = trimmed.match(/^(\w+)(?:\s+as\s+(\w+))?/);
|
const asMatch = trimmed.match(/^(\w+)(?:\s+as\s+(\w+))?/);
|
||||||
return asMatch
|
return asMatch
|
||||||
? {
|
? {
|
||||||
|
|
@ -84,7 +84,7 @@ function parseImportStatement(line: string, packageName: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 替换文件中的 import 语句
|
* Replace import statements in a file
|
||||||
*/
|
*/
|
||||||
function replaceImportsInFile(filePath: string, config: ReplaceConfig): boolean {
|
function replaceImportsInFile(filePath: string, config: ReplaceConfig): boolean {
|
||||||
const content = readFileSync(filePath, 'utf8');
|
const content = readFileSync(filePath, 'utf8');
|
||||||
|
|
@ -100,28 +100,28 @@ function replaceImportsInFile(filePath: string, config: ReplaceConfig): boolean
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 找出需要替换的组件和保留的组件
|
// Find components to replace and components to keep
|
||||||
const toReplace = parsed.components.filter((comp) => config.components.includes(comp.name));
|
const toReplace = parsed.components.filter((comp) => config.components.includes(comp.name));
|
||||||
const toKeep = parsed.components.filter((comp) => !config.components.includes(comp.name));
|
const toKeep = parsed.components.filter((comp) => !config.components.includes(comp.name));
|
||||||
|
|
||||||
if (toReplace.length === 0) {
|
if (toReplace.length === 0) {
|
||||||
// 没有需要替换的组件
|
// No components to replace
|
||||||
newLines.push(line);
|
newLines.push(line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
modified = true;
|
modified = true;
|
||||||
|
|
||||||
// 生成新的 import 语句
|
// Generate new import statement
|
||||||
const { indentation } = parsed;
|
const { indentation } = parsed;
|
||||||
|
|
||||||
// 如果有保留的组件,保留原来的 import
|
// If there are components to keep, preserve the original import
|
||||||
if (toKeep.length > 0) {
|
if (toKeep.length > 0) {
|
||||||
const keepImports = toKeep.map((c) => c.raw).join(', ');
|
const keepImports = toKeep.map((c) => c.raw).join(', ');
|
||||||
newLines.push(`${indentation}import { ${keepImports} } from '${config.fromPackage}';`);
|
newLines.push(`${indentation}import { ${keepImports} } from '${config.fromPackage}';`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加新的 import
|
// Add new import
|
||||||
const replaceImports = toReplace.map((c) => c.raw).join(', ');
|
const replaceImports = toReplace.map((c) => c.raw).join(', ');
|
||||||
newLines.push(`${indentation}import { ${replaceImports} } from '${config.toPackage}';`);
|
newLines.push(`${indentation}import { ${replaceImports} } from '${config.toPackage}';`);
|
||||||
}
|
}
|
||||||
|
|
@ -138,7 +138,7 @@ function replaceImportsInFile(filePath: string, config: ReplaceConfig): boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行替换
|
* Execute replacement
|
||||||
*/
|
*/
|
||||||
function executeReplace(config: ReplaceConfig) {
|
function executeReplace(config: ReplaceConfig) {
|
||||||
const extensions = config.fileExtensions || ['.ts', '.tsx', '.js', '.jsx'];
|
const extensions = config.fileExtensions || ['.ts', '.tsx', '.js', '.jsx'];
|
||||||
|
|
@ -175,10 +175,10 @@ function executeReplace(config: ReplaceConfig) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============ 主函数 ============
|
// ============ Main function ============
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从命令行参数解析配置
|
* Parse configuration from command line arguments
|
||||||
*/
|
*/
|
||||||
function parseArgs(): ReplaceConfig | null {
|
function parseArgs(): ReplaceConfig | null {
|
||||||
const args = process.argv.slice(2);
|
const args = process.argv.slice(2);
|
||||||
|
|
@ -244,7 +244,7 @@ function parseArgs(): ReplaceConfig | null {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行脚本
|
// Execute script
|
||||||
const config = parseArgs();
|
const config = parseArgs();
|
||||||
if (config) {
|
if (config) {
|
||||||
executeReplace(config);
|
executeReplace(config);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue