@zzclub/z-cli 0.7.1 → 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/LICENSE +20 -20
- package/dist/commands/config.d.ts +9 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +33 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/set.d.ts +11 -0
- package/dist/commands/set.d.ts.map +1 -0
- package/dist/commands/set.js +43 -0
- package/dist/commands/set.js.map +1 -0
- package/dist/commands/tiny/compressor.d.ts +11 -0
- package/dist/commands/tiny/compressor.d.ts.map +1 -0
- package/dist/commands/tiny/compressor.js +46 -0
- package/dist/commands/tiny/compressor.js.map +1 -0
- package/dist/commands/tiny/file-processor.d.ts +40 -0
- package/dist/commands/tiny/file-processor.d.ts.map +1 -0
- package/dist/commands/tiny/file-processor.js +137 -0
- package/dist/commands/tiny/file-processor.js.map +1 -0
- package/dist/commands/tiny/index.d.ts +15 -0
- package/dist/commands/tiny/index.d.ts.map +1 -0
- package/dist/commands/tiny/index.js +55 -0
- package/dist/commands/tiny/index.js.map +1 -0
- package/dist/commands/tiny/types.d.ts +55 -0
- package/dist/commands/tiny/types.d.ts.map +1 -0
- package/dist/commands/tiny/types.js +5 -0
- package/dist/commands/tiny/types.js.map +1 -0
- package/dist/core/config-manager.d.ts +38 -0
- package/dist/core/config-manager.d.ts.map +1 -0
- package/dist/core/config-manager.js +87 -0
- package/dist/core/config-manager.js.map +1 -0
- package/dist/core/logger.d.ts +17 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +30 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +177 -0
- package/dist/index.js.map +1 -0
- package/dist/types/config.d.ts +32 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +18 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +34 -19
- package/readme.md +457 -0
- package/CHANGELOG.md +0 -211
- package/README.md +0 -329
- package/src/command/config.js +0 -97
- package/src/command/i18n.js +0 -318
- package/src/command/index.js +0 -30
- package/src/command/picgo.js +0 -122
- package/src/command/replace.js +0 -81
- package/src/command/set.js +0 -47
- package/src/command/tiny.js +0 -328
- package/src/command/translate.js +0 -337
- package/src/config.json +0 -16
- package/src/index.js +0 -31
- package/src/translate-api/index.js +0 -77
- package/src/translate-api/md5.js +0 -231
- package/src/utils/common.js +0 -218
- package/src/utils/file.js +0 -61
- package/src/utils/picgo.js +0 -149
package/src/command/i18n.js
DELETED
|
@@ -1,318 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import fs from "node:fs";
|
|
3
|
-
import chalk from "chalk";
|
|
4
|
-
import ora from "ora";
|
|
5
|
-
|
|
6
|
-
const i18nCmd = {
|
|
7
|
-
name: "i18n",
|
|
8
|
-
alias: "i",
|
|
9
|
-
description: "从 Vue 文件中生成国际化配置文件",
|
|
10
|
-
options: [
|
|
11
|
-
{
|
|
12
|
-
flags: "-f, --file <file>",
|
|
13
|
-
description: "转换文件的路径",
|
|
14
|
-
defaultValue: null,
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
flags: "-d, --dir <dirpath>",
|
|
18
|
-
description: "转换文件夹的路径",
|
|
19
|
-
defaultValue: null,
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
flags: "-o, --output <output>",
|
|
23
|
-
description: "输出目录",
|
|
24
|
-
defaultValue: "",
|
|
25
|
-
},
|
|
26
|
-
],
|
|
27
|
-
action: async (option) => {
|
|
28
|
-
let filePath = option.file;
|
|
29
|
-
let dirPath = option.dir;
|
|
30
|
-
let outputDir = option.output;
|
|
31
|
-
let file_spinner = ora();
|
|
32
|
-
|
|
33
|
-
if (!filePath && !dirPath) {
|
|
34
|
-
file_spinner.fail('请指定文件或目录')
|
|
35
|
-
process.exit(1);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// 有文件夹路径时忽略文件
|
|
39
|
-
if (dirPath) {
|
|
40
|
-
dirPath = path.resolve(process.cwd(), dirPath);
|
|
41
|
-
let stat;
|
|
42
|
-
try {
|
|
43
|
-
stat = fs.statSync(dirPath);
|
|
44
|
-
} catch (err) {
|
|
45
|
-
file_spinner.fail(`${chalk.red(dirPath)}不存在!`);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (!stat.isDirectory()) {
|
|
50
|
-
file_spinner.fail(`${chalk.red(dirPath)}不是一个文件夹!`);
|
|
51
|
-
return;
|
|
52
|
-
} else {
|
|
53
|
-
let filePaths = [];
|
|
54
|
-
file_spinner.succeed(`开始检索${chalk.red(dirPath)}`);
|
|
55
|
-
|
|
56
|
-
// 获取所有 .vue 文件
|
|
57
|
-
getAllVueFiles(dirPath, filePaths);
|
|
58
|
-
|
|
59
|
-
if (filePaths.length) {
|
|
60
|
-
file_spinner.succeed(
|
|
61
|
-
`共找到${chalk.red(filePaths.length)}个要处理的文件`
|
|
62
|
-
);
|
|
63
|
-
file_spinner.start();
|
|
64
|
-
|
|
65
|
-
// 处理所有文件
|
|
66
|
-
const i18nMap = {};
|
|
67
|
-
|
|
68
|
-
for (const file of filePaths) {
|
|
69
|
-
const content = fs.readFileSync(file, 'utf-8');
|
|
70
|
-
const fileName = path.basename(file, '.vue');
|
|
71
|
-
const { keys: i18nKeys, commentMap } = extractI18nKeys(content);
|
|
72
|
-
|
|
73
|
-
if (i18nKeys.length > 0) {
|
|
74
|
-
file_spinner.succeed(`从 ${chalk.yellow(fileName)} 中提取了 ${chalk.green(i18nKeys.length)} 个国际化键值`);
|
|
75
|
-
|
|
76
|
-
// 处理每个提取的键值
|
|
77
|
-
for (const key of i18nKeys) {
|
|
78
|
-
await processI18nKey(key, i18nMap, commentMap);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// 如果没有指定输出目录,使用处理的第一个文件所在目录
|
|
84
|
-
if (!outputDir && filePaths.length > 0) {
|
|
85
|
-
outputDir = path.dirname(filePaths[0]);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// 生成国际化文件
|
|
89
|
-
await generateI18nFiles(i18nMap, outputDir, file_spinner);
|
|
90
|
-
|
|
91
|
-
file_spinner.succeed('国际化文件生成完成');
|
|
92
|
-
file_spinner.stop();
|
|
93
|
-
} else {
|
|
94
|
-
file_spinner.warn(
|
|
95
|
-
`未找到任何 .vue 文件`
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
} else {
|
|
100
|
-
filePath = path.resolve(process.cwd(), filePath);
|
|
101
|
-
file_spinner.succeed(`正在处理${chalk.yellowBright(filePath)}`);
|
|
102
|
-
file_spinner.start();
|
|
103
|
-
|
|
104
|
-
// 处理单个 vue 文件
|
|
105
|
-
if (!filePath.endsWith('.vue')) {
|
|
106
|
-
file_spinner.fail('只能处理 .vue 文件');
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
111
|
-
const fileName = path.basename(filePath, '.vue');
|
|
112
|
-
const { keys: i18nKeys, commentMap } = extractI18nKeys(content);
|
|
113
|
-
|
|
114
|
-
if (i18nKeys.length > 0) {
|
|
115
|
-
const i18nMap = {};
|
|
116
|
-
|
|
117
|
-
file_spinner.succeed(`从 ${chalk.yellow(fileName)} 中提取了 ${chalk.green(i18nKeys.length)} 个国际化键值`);
|
|
118
|
-
|
|
119
|
-
// 处理每个提取的键值
|
|
120
|
-
for (const key of i18nKeys) {
|
|
121
|
-
await processI18nKey(key, i18nMap, commentMap);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// 如果没有指定输出目录,使用当前处理的文件所在目录
|
|
125
|
-
if (!outputDir) {
|
|
126
|
-
outputDir = path.dirname(filePath);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// 生成国际化文件
|
|
130
|
-
await generateI18nFiles(i18nMap, outputDir, file_spinner);
|
|
131
|
-
|
|
132
|
-
file_spinner.succeed('国际化文件生成完成');
|
|
133
|
-
} else {
|
|
134
|
-
file_spinner.warn(`未从 ${chalk.yellow(fileName)} 中找到任何国际化键值`);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
file_spinner.stop();
|
|
138
|
-
}
|
|
139
|
-
},
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* 递归获取所有 .vue 文件
|
|
144
|
-
* @param {string} dirPath 目录路径
|
|
145
|
-
* @param {Array} filePaths 文件路径数组
|
|
146
|
-
*/
|
|
147
|
-
function getAllVueFiles(dirPath, filePaths) {
|
|
148
|
-
const files = fs.readdirSync(dirPath);
|
|
149
|
-
|
|
150
|
-
files.forEach(file => {
|
|
151
|
-
const fullPath = path.join(dirPath, file);
|
|
152
|
-
const stat = fs.statSync(fullPath);
|
|
153
|
-
|
|
154
|
-
if (stat.isDirectory()) {
|
|
155
|
-
getAllVueFiles(fullPath, filePaths);
|
|
156
|
-
} else if (file.endsWith('.vue')) {
|
|
157
|
-
filePaths.push(fullPath);
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* 从 Vue 文件内容中提取国际化键值
|
|
164
|
-
* @param {string} content 文件内容
|
|
165
|
-
* @param {string} ignorePrefix 要忽略的前缀
|
|
166
|
-
* @returns {Object} 提取的键值数组和注释映射
|
|
167
|
-
*/
|
|
168
|
-
function extractI18nKeys(content, ignorePrefix = "common") {
|
|
169
|
-
// 原有正则表达式,提取键名
|
|
170
|
-
const regex = /\$t\(['"]i18n\.([^'"]+)['"]\)/g;
|
|
171
|
-
// 提取键名和注释中的中文
|
|
172
|
-
const regexWithComment = /\$t\(['"]i18n\.([^'"]+)['"]\)[\s,]*\/\/\s*([\u4e00-\u9fa5].*?)(?=\n|$)/g;
|
|
173
|
-
// 新增:提取HTML注释中的i18n信息
|
|
174
|
-
const regexHtmlComment = /<!--i18n\s+(.*?)-->/g;
|
|
175
|
-
|
|
176
|
-
const keys = [];
|
|
177
|
-
const commentMap = {}; // 存储键名和对应的注释内容
|
|
178
|
-
let match;
|
|
179
|
-
|
|
180
|
-
// 提取HTML注释中的i18n信息
|
|
181
|
-
while ((match = regexHtmlComment.exec(content)) !== null) {
|
|
182
|
-
const commentContent = match[1].trim();
|
|
183
|
-
// 解析注释内容中的多个键值对
|
|
184
|
-
const keyValuePairs = commentContent.split(/\s+/);
|
|
185
|
-
|
|
186
|
-
for (const pair of keyValuePairs) {
|
|
187
|
-
const [key, value] = pair.split('=');
|
|
188
|
-
if (key && value) {
|
|
189
|
-
// 将简短键(如addTitle)与完整键(如monthlyForecast.pageTitle.addTitle)进行匹配
|
|
190
|
-
// 这里我们需要在后续处理中找到对应的完整键
|
|
191
|
-
commentMap[key] = value;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// 提取带注释的国际化键
|
|
197
|
-
while ((match = regexWithComment.exec(content)) !== null) {
|
|
198
|
-
const key = match[1];
|
|
199
|
-
const comment = match[2].trim();
|
|
200
|
-
|
|
201
|
-
// 如果设置了忽略前缀且键以该前缀开头,则跳过
|
|
202
|
-
if (ignorePrefix && key.startsWith(`${ignorePrefix}.`)) {
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
keys.push(key);
|
|
207
|
-
// JS注释优先级高于HTML注释
|
|
208
|
-
commentMap[key] = comment;
|
|
209
|
-
|
|
210
|
-
// 同时为简短键名存储注释
|
|
211
|
-
const shortKey = key.split('.').pop();
|
|
212
|
-
if (!commentMap[shortKey]) {
|
|
213
|
-
commentMap[shortKey] = comment;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// 提取不带注释的国际化键
|
|
218
|
-
while ((match = regex.exec(content)) !== null) {
|
|
219
|
-
const key = match[1];
|
|
220
|
-
|
|
221
|
-
// 如果设置了忽略前缀且键以该前缀开头,则跳过
|
|
222
|
-
if (ignorePrefix && key.startsWith(`${ignorePrefix}.`)) {
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
keys.push(key);
|
|
227
|
-
|
|
228
|
-
// 检查是否有对应的HTML注释
|
|
229
|
-
const shortKey = key.split('.').pop();
|
|
230
|
-
if (commentMap[shortKey] && !commentMap[key]) {
|
|
231
|
-
commentMap[key] = commentMap[shortKey];
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// 返回去重后的键名数组和注释映射
|
|
236
|
-
return {
|
|
237
|
-
keys: [...new Set(keys)],
|
|
238
|
-
commentMap
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
function unquoteKeys(json) {
|
|
242
|
-
return json.replace(/"(\\[^]|[^\\"])*"\s*:?/g, function (match) {
|
|
243
|
-
if (/:$/.test(match)) {
|
|
244
|
-
return match.replace(/^"|"(?=\s*:$)/g, "");
|
|
245
|
-
} else {
|
|
246
|
-
return match;
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* 处理单个国际化键值
|
|
253
|
-
* @param {string} key 键值
|
|
254
|
-
* @param {Object} i18nMap 国际化映射对象
|
|
255
|
-
* @param {Object} commentMap 注释映射
|
|
256
|
-
*/
|
|
257
|
-
async function processI18nKey(key, i18nMap, commentMap = {}) {
|
|
258
|
-
// 解析键值 fee-forecast-maintain.placeholder.yearNum
|
|
259
|
-
const parts = key.split('.');
|
|
260
|
-
|
|
261
|
-
if (parts.length < 2) return;
|
|
262
|
-
|
|
263
|
-
const fileKey = parts[0]; // fee-forecast-maintain
|
|
264
|
-
const lastKey = parts[parts.length - 1]; // yearNum
|
|
265
|
-
const objKeys = parts.slice(1, parts.length - 1); // ['placeholder']
|
|
266
|
-
|
|
267
|
-
// 确保文件键存在,并且是一个对象
|
|
268
|
-
if (!i18nMap[fileKey] || typeof i18nMap[fileKey] !== 'object') {
|
|
269
|
-
i18nMap[fileKey] = {};
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// 构建嵌套对象
|
|
273
|
-
let current = i18nMap[fileKey];
|
|
274
|
-
for (const objKey of objKeys) {
|
|
275
|
-
if (!current[objKey] || typeof current[objKey] !== 'object') {
|
|
276
|
-
current[objKey] = {};
|
|
277
|
-
}
|
|
278
|
-
current = current[objKey];
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// 设置最终的键值
|
|
282
|
-
if (!current[lastKey]) {
|
|
283
|
-
// 如果有注释,使用注释作为值,否则使用键名
|
|
284
|
-
current[lastKey] = commentMap[key] || lastKey;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* 生成国际化文件
|
|
290
|
-
* @param {Object} i18nMap 国际化映射对象
|
|
291
|
-
* @param {string} outputDir 输出目录
|
|
292
|
-
* @param {Object} spinner 加载指示器
|
|
293
|
-
*/
|
|
294
|
-
async function generateI18nFiles(i18nMap, outputDir, spinner) {
|
|
295
|
-
// 确保输出目录存在
|
|
296
|
-
if (!outputDir) {
|
|
297
|
-
spinner.fail('未指定输出目录');
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// 确保输出目录存在
|
|
302
|
-
outputDir = path.resolve(process.cwd(), outputDir);
|
|
303
|
-
if (!fs.existsSync(outputDir)) {
|
|
304
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// 为每个文件键生成文件
|
|
308
|
-
for (const fileKey in i18nMap) {
|
|
309
|
-
const filePath = path.join(outputDir, `${fileKey}.js`);
|
|
310
|
-
// 使用 unquoteKeys 去掉对象键的引号
|
|
311
|
-
const content = `export default ${unquoteKeys(JSON.stringify(i18nMap[fileKey], null, 2))}`;
|
|
312
|
-
|
|
313
|
-
fs.writeFileSync(filePath, content);
|
|
314
|
-
spinner.succeed(`生成文件: ${chalk.green(filePath)}`);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
export { i18nCmd };
|
package/src/command/index.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { dirname } from "node:path";
|
|
2
|
-
import { fileURLToPath } from "node:url";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import ora from "ora";
|
|
5
|
-
import { readJsonFile } from "../utils/common.js";
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
-
const __dirname = dirname(__filename);
|
|
8
|
-
|
|
9
|
-
export const registerCommand = (program, config) => {
|
|
10
|
-
let app = program.command(config.name).description(config.description);
|
|
11
|
-
|
|
12
|
-
if (config.alias) {
|
|
13
|
-
app.alias(config.alias);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
config.options.forEach((option) => {
|
|
17
|
-
app.option(option.flags, option.description, option.defaultValue);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
app.action(config.action);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export const initProgram = async (program, cb) => {
|
|
24
|
-
readJsonFile(path.resolve(__dirname, "../../package.json")).then((pkg) => {
|
|
25
|
-
program.usage("<command> [options]");
|
|
26
|
-
program.version(pkg.version);
|
|
27
|
-
|
|
28
|
-
cb && cb();
|
|
29
|
-
});
|
|
30
|
-
};
|
package/src/command/picgo.js
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
writeFileContent,
|
|
3
|
-
getLocalConfig,
|
|
4
|
-
setHighLightStr,
|
|
5
|
-
} from "../utils/common.js";
|
|
6
|
-
import {
|
|
7
|
-
requestPicGo,
|
|
8
|
-
checkFileSize,
|
|
9
|
-
checkFileSizeAndFilter,
|
|
10
|
-
uploadFileByPicGo,
|
|
11
|
-
batchUploadByPicGo,
|
|
12
|
-
} from "../utils/picgo.js";
|
|
13
|
-
import { getFormatedFileSize, replaceFileContent } from "../utils/file.js";
|
|
14
|
-
import chalk from "chalk";
|
|
15
|
-
import ora from "ora";
|
|
16
|
-
import path from "node:path";
|
|
17
|
-
import { dirname } from "node:path";
|
|
18
|
-
import { fileURLToPath } from "node:url";
|
|
19
|
-
import fs from "node:fs";
|
|
20
|
-
|
|
21
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
22
|
-
const __dirname = dirname(__filename);
|
|
23
|
-
|
|
24
|
-
const supportFileTypes = ["png", "jpg", "jpeg", "gif", "webp"];
|
|
25
|
-
|
|
26
|
-
export const picgoCmd = {
|
|
27
|
-
name: "picgo",
|
|
28
|
-
description: "上传图片(此命令暂时废弃, 原因见readme)",
|
|
29
|
-
options: [
|
|
30
|
-
{
|
|
31
|
-
flags: "-f, --file <file>",
|
|
32
|
-
description: "要上传的图片文件",
|
|
33
|
-
defaultValue: null,
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
flags: "-d, --dir <dir>",
|
|
37
|
-
description: "上传文件夹内所有文件",
|
|
38
|
-
defaultValue: null,
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
flags: "-co, --condition <condition>",
|
|
42
|
-
description: "上传文件夹内所有名称包含[--condition]的图片文件",
|
|
43
|
-
defaultValue: null,
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
flags: "-m, --max <max>",
|
|
47
|
-
description: "大于指定大小的图片不会被上传",
|
|
48
|
-
defaultValue: 60,
|
|
49
|
-
},
|
|
50
|
-
],
|
|
51
|
-
action: async (option, test) => {
|
|
52
|
-
const spinner = ora();
|
|
53
|
-
const config = await getLocalConfig();
|
|
54
|
-
const { file, dir, condition, tinyFiles } = option;
|
|
55
|
-
|
|
56
|
-
if (!file && !dir && !condition && (!tinyFiles || !tinyFiles.length)) {
|
|
57
|
-
spinner.fail("请指定要上传的文件(--file=xxx)或文件夹(--dir=/a/b)");
|
|
58
|
-
process.exit(1);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// const _replaceMaps = replaceMaps.concat();
|
|
62
|
-
// 从压缩命令调用过来的
|
|
63
|
-
if (tinyFiles && tinyFiles.length) {
|
|
64
|
-
await batchUploadByPicGo(tinyFiles, option);
|
|
65
|
-
if (!option.replace) process.exit(1);
|
|
66
|
-
spinner.start("开始替换文件内容, 替换后请仔细检查!");
|
|
67
|
-
const fileContent = await replaceFileContent(
|
|
68
|
-
option.replaceFile,
|
|
69
|
-
option.replaceMaps
|
|
70
|
-
);
|
|
71
|
-
if (!fileContent) {
|
|
72
|
-
spinner.fail("替换文件内容失败! 请检查要替换的文件是否存在!");
|
|
73
|
-
process.exit(1);
|
|
74
|
-
}
|
|
75
|
-
fs.writeFile(option.replaceFile, fileContent, "utf-8", (error) => {
|
|
76
|
-
if (!error) {
|
|
77
|
-
spinner.succeed(
|
|
78
|
-
`[${chalk.red(
|
|
79
|
-
path.basename(option.replaceFile)
|
|
80
|
-
)}]图片链接替换完成!请前往检查!`
|
|
81
|
-
);
|
|
82
|
-
} else {
|
|
83
|
-
console.log(error);
|
|
84
|
-
// spinner.fail(`写入${chalk.red(filePath)}文件失败, 请重试`);
|
|
85
|
-
spinner.fail("图片链接替换失败!");
|
|
86
|
-
}
|
|
87
|
-
process.exit(1);
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
// 指定文件上传
|
|
91
|
-
if (file) {
|
|
92
|
-
await uploadFileByPicGo(file, option);
|
|
93
|
-
process.exit(1);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// 指定文件夹, 翻译文件夹内所有文件
|
|
97
|
-
if (dir || condition) {
|
|
98
|
-
let inputDirPath = dir || "./";
|
|
99
|
-
let files;
|
|
100
|
-
try {
|
|
101
|
-
// 读取所有文件
|
|
102
|
-
files = fs.readdirSync(inputDirPath);
|
|
103
|
-
files = files.map((filePath) =>
|
|
104
|
-
path.resolve(process.cwd(), inputDirPath, filePath)
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
files = files.filter((f) => {
|
|
108
|
-
let fileName = path.basename(f);
|
|
109
|
-
let index = fileName.indexOf(condition);
|
|
110
|
-
return index !== -1;
|
|
111
|
-
});
|
|
112
|
-
await batchUploadByPicGo(files, option);
|
|
113
|
-
// spinner.succeed(`共有${files.length}个文件${files}`);
|
|
114
|
-
} catch (err) {
|
|
115
|
-
spinner.fail("出错啦, 文件夹似乎不存在");
|
|
116
|
-
process.exit(1);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
process.exit(1);
|
|
120
|
-
}
|
|
121
|
-
},
|
|
122
|
-
};
|
package/src/command/replace.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
writeFileContent,
|
|
3
|
-
getLocalConfig,
|
|
4
|
-
setHighLightStr,
|
|
5
|
-
} from "../utils/common.js";
|
|
6
|
-
import {
|
|
7
|
-
requestPicGo,
|
|
8
|
-
checkFileSize,
|
|
9
|
-
checkFileSizeAndFilter,
|
|
10
|
-
uploadFileByPicGo,
|
|
11
|
-
batchUploadByPicGo,
|
|
12
|
-
} from "../utils/picgo.js";
|
|
13
|
-
import { getFormatedFileSize } from "../utils/file.js";
|
|
14
|
-
import chalk from "chalk";
|
|
15
|
-
import ora from "ora";
|
|
16
|
-
import path from "node:path";
|
|
17
|
-
import { dirname } from "node:path";
|
|
18
|
-
import { fileURLToPath } from "node:url";
|
|
19
|
-
import fs from "node:fs";
|
|
20
|
-
|
|
21
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
22
|
-
const __dirname = dirname(__filename);
|
|
23
|
-
|
|
24
|
-
const supportFileTypes = ["png", "jpg", "jpeg", "gif", "webp"];
|
|
25
|
-
|
|
26
|
-
export const replaceCmd = {
|
|
27
|
-
name: "replace",
|
|
28
|
-
description:
|
|
29
|
-
"替换文字功能, 用于上传后文件后, 自动更换markdown里的图片链接(还在开发中)",
|
|
30
|
-
options: [
|
|
31
|
-
{
|
|
32
|
-
flags: "-f, --file <file>",
|
|
33
|
-
description: "目标文件",
|
|
34
|
-
defaultValue: "",
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
flags: "-t, --text <text>",
|
|
38
|
-
description: "要替换的文字",
|
|
39
|
-
defaultValue: "",
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
flags: "-nt, --new-text <nextText>",
|
|
43
|
-
description: "替换后的文字内容",
|
|
44
|
-
defaultValue: null,
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
flags: "-co, --condition <condition>",
|
|
48
|
-
description: "上传文件夹内所有名称包含[--condition]的图片文件",
|
|
49
|
-
defaultValue: null,
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
flags: "-m, --max <max>",
|
|
53
|
-
description: "大于指定大小的图片不会被上传",
|
|
54
|
-
defaultValue: 60,
|
|
55
|
-
},
|
|
56
|
-
],
|
|
57
|
-
action: async (option) => {
|
|
58
|
-
const spinner = ora();
|
|
59
|
-
const config = await getLocalConfig();
|
|
60
|
-
const { text, newText, file } = option;
|
|
61
|
-
|
|
62
|
-
if (!text && !newText && !file) {
|
|
63
|
-
spinner.fail("请指定要替换的文件及替换方式");
|
|
64
|
-
process.exit(1);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// 绝对路径
|
|
68
|
-
let filePath = path.resolve(process.cwd(), file);
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
// 使用fs.readFileSync读取文件内容
|
|
72
|
-
// let fileContent = fs.readFileSync(filePath);
|
|
73
|
-
// 将文件内容转换为JSON对象
|
|
74
|
-
// fileContent = fileContent.replaceAll(text, newText)
|
|
75
|
-
// replaceFileContent(filePath, [{text, newText}])
|
|
76
|
-
} catch (err) {
|
|
77
|
-
// 如果读取文件失败,则将jsonData初始化为空对象
|
|
78
|
-
jsonData = {};
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
};
|
package/src/command/set.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { writeFileContent, getLocalConfig, setLocalConfig } from "../utils/common.js";
|
|
2
|
-
import chalk from "chalk";
|
|
3
|
-
import ora from "ora";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { dirname } from "node:path";
|
|
6
|
-
import { fileURLToPath } from "node:url";
|
|
7
|
-
import os from 'node:os'
|
|
8
|
-
|
|
9
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
-
const __dirname = dirname(__filename);
|
|
11
|
-
|
|
12
|
-
export const setCmd = {
|
|
13
|
-
name: "set <configName> [payload...]",
|
|
14
|
-
description:
|
|
15
|
-
"设置全局config.json配置, 只有两个命令, 复制即可 \n 1. zz set translate account.appId <value> \n 2. zz set translate account.key <value>",
|
|
16
|
-
options: [],
|
|
17
|
-
action: async (configName, payload, cmd) => {
|
|
18
|
-
let set_spinner = ora();
|
|
19
|
-
let config = await getLocalConfig();
|
|
20
|
-
let configItem = config[configName];
|
|
21
|
-
if (configItem) {
|
|
22
|
-
if (config.editableConfig.includes(configName)) {
|
|
23
|
-
if (payload.length === 2) {
|
|
24
|
-
let key = payload[0];
|
|
25
|
-
if (!["account.key", "account.appId"].includes(key)) {
|
|
26
|
-
set_spinner.warn(`设置appId: zz set translate account.appId <value>`);
|
|
27
|
-
set_spinner.warn(`设置key: zz set translate account.key <value>`);
|
|
28
|
-
process.exit(1);
|
|
29
|
-
}
|
|
30
|
-
let value = payload[1];
|
|
31
|
-
eval(`configItem.${key} = "${value}"`);
|
|
32
|
-
// configItem[key] = value
|
|
33
|
-
setLocalConfig(config, set_spinner)
|
|
34
|
-
} else {
|
|
35
|
-
set_spinner.warn(`设置appId: zz set translate account.appId <value>`);
|
|
36
|
-
set_spinner.warn(`设置key: zz set translate account.key <value>`);
|
|
37
|
-
process.exit(1);
|
|
38
|
-
}
|
|
39
|
-
} else {
|
|
40
|
-
set_spinner.fail(`配置项[${chalk.red(configName)}]不允许修改`);
|
|
41
|
-
}
|
|
42
|
-
} else {
|
|
43
|
-
set_spinner.fail(`配置项[${chalk.red(configName)}]不存在`);
|
|
44
|
-
process.exit(1);
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
};
|