vue-i18n-auto-plugin 1.0.0 → 1.0.2

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 CHANGED
@@ -1,6 +1,10 @@
1
- # vite-plugin-i18n-auto
1
+ # vue-i18n-auto-plugin
2
2
 
3
- Vite 插件,用于自动将 Vue/TypeScript 项目中的中文硬编码转换为 i18n 函数调用。
3
+ Vite 插件和 CLI 工具,用于自动将 Vue/TypeScript 项目中的中文硬编码转换为 i18n 函数调用。
4
+
5
+ 支持两种使用方式:
6
+ - **Vite 插件**:在构建时自动转换
7
+ - **CLI 工具**:本地开发时手动转换(推荐)
4
8
 
5
9
  ## 功能特点
6
10
 
@@ -23,6 +27,8 @@ pnpm add vite-plugin-i18n-auto -D
23
27
 
24
28
  ## 使用方法
25
29
 
30
+ ### 方式一:作为 Vite 插件使用(构建时转换)
31
+
26
32
  在 `vite.config.ts` 中配置:
27
33
 
28
34
  ```typescript
@@ -52,6 +58,39 @@ export default defineConfig({
52
58
  });
53
59
  ```
54
60
 
61
+ ### 方式二:使用 CLI 进行本地转换(推荐)
62
+
63
+ 安装后,可以使用命令行工具进行本地转换:
64
+
65
+ ```bash
66
+ # 基本使用(使用默认配置)
67
+ npx vue-i18n-auto
68
+
69
+ # 或全局安装后使用
70
+ npm install -g vue-i18n-auto-plugin
71
+ vue-i18n-auto
72
+
73
+ # 自定义配置
74
+ npx vue-i18n-auto --i18n-path src/locales/zh-CN.ts --pre-text app.
75
+ ```
76
+
77
+ **CLI 选项:**
78
+ - `--i18n-path <path>` - 主语言文件路径(默认: `src/locales/zh-CN.ts`)
79
+ - `--lang-path <paths>` - 其他语言文件路径,逗号分隔(默认: `src/locales/en.ts`)
80
+ - `--pre-text <text>` - key 生成的前缀(默认: `common.`)
81
+ - `--key-length <number>` - 生成的 key 长度(默认: `16`)
82
+ - `--crypto-key <key>` - 加密密钥(默认: `i18n`)
83
+ - `--help, -h` - 显示帮助信息
84
+
85
+ **示例:**
86
+ ```bash
87
+ # 使用自定义前缀
88
+ npx vue-i18n-auto --pre-text app.
89
+
90
+ # 指定多个语言文件
91
+ npx vue-i18n-auto --lang-path src/locales/en.ts,src/locales/ja.ts
92
+ ```
93
+
55
94
  ## 配置选项
56
95
 
57
96
  | 选项 | 类型 | 默认值 | 说明 |
@@ -0,0 +1,596 @@
1
+ #!/usr/bin/env node
2
+ #!/usr/bin/env node
3
+ 'use strict';
4
+
5
+ var fs = require('fs');
6
+ var path = require('path');
7
+ var fastGlob = require('fast-glob');
8
+ var compilerSfc = require('@vue/compiler-sfc');
9
+ var babelParser = require('@babel/parser');
10
+ var _generate = require('@babel/generator');
11
+ var _traverse = require('@babel/traverse');
12
+ var crypto = require('crypto');
13
+ var JSON5 = require('json5');
14
+
15
+ function _interopNamespaceDefault(e) {
16
+ var n = Object.create(null);
17
+ if (e) {
18
+ Object.keys(e).forEach(function (k) {
19
+ if (k !== 'default') {
20
+ var d = Object.getOwnPropertyDescriptor(e, k);
21
+ Object.defineProperty(n, k, d.get ? d : {
22
+ enumerable: true,
23
+ get: function () { return e[k]; }
24
+ });
25
+ }
26
+ });
27
+ }
28
+ n.default = e;
29
+ return Object.freeze(n);
30
+ }
31
+
32
+ var babelParser__namespace = /*#__PURE__*/_interopNamespaceDefault(babelParser);
33
+ var _generate__namespace = /*#__PURE__*/_interopNamespaceDefault(_generate);
34
+ var _traverse__namespace = /*#__PURE__*/_interopNamespaceDefault(_traverse);
35
+
36
+ // 中文字符匹配函数(判断字符串是否包含中文字符)
37
+ function containsChinese(str) {
38
+ return /[\u4e00-\u9fa5]/.test(str);
39
+ }
40
+ // 收集字符串中的字符, '我的测试' + 'abc' + '测试呀', 针对这种字符串的拼接处理
41
+ function extractQuotedStrings(str) {
42
+ // 如果是 `这种拼接的`
43
+ const regex = /(["'])(.*?)\1/g;
44
+ let match;
45
+ const matches = [];
46
+ while ((match = regex.exec(str)) !== null) {
47
+ matches.push(match[0]);
48
+ }
49
+ return matches;
50
+ }
51
+ // 对js 字符串的模板进行处理 类似 `我的测试${variable}`
52
+ function extractTransformString(str) {
53
+ // 正则表达式匹配 ${variable} 中的内容
54
+ const regex = /\$\{([^}]+)\}/g;
55
+ if (!regex.test(str)) {
56
+ return;
57
+ }
58
+ const placeholders = [];
59
+ let index = 1;
60
+ let transformedStr = str.replace(regex, (match, p1) => {
61
+ placeholders.push(`name${index}: ${p1}`);
62
+ const placeholder = `{name${index}}`;
63
+ index++;
64
+ return placeholder;
65
+ }).replace(/`/g, '');
66
+ return {
67
+ key: transformedStr,
68
+ data: placeholders.join(', ')
69
+ };
70
+ }
71
+ // 生成唯一key
72
+ function generateKey(chineseStr) {
73
+ const text = (globalThis.preText || '') + chineseStr;
74
+ const hash = crypto.createHmac('sha256', globalThis.cryptoKey || 'i18n').update(text).digest('hex');
75
+ // 保留加密结果的前N位,N由配置中的keyLength决定
76
+ const len = globalThis.keyLength || 16;
77
+ return hash.slice(0, len);
78
+ }
79
+ // 获取和收集key
80
+ function getChineseKey(text) {
81
+ let key = '';
82
+ if (containsChinese(text)) {
83
+ const chineseText = text.trim().replace(/^&%&/, '');
84
+ key = generateKey(chineseText);
85
+ if (!globalThis.translationsMap[key]) {
86
+ globalThis.addTranslations.push({
87
+ key,
88
+ value: chineseText
89
+ });
90
+ }
91
+ // 这里一定是 use key ,使用的key值,修改中文和书写中文的时候会一个 标注
92
+ globalThis.translationsMap[key] = chineseText;
93
+ }
94
+ let isKey = false;
95
+ if (text) {
96
+ // 使用正则的方法进行判断
97
+ isKey = /^&%\&/.test(text);
98
+ }
99
+ return {
100
+ key,
101
+ isKey
102
+ };
103
+ }
104
+ // 读取文件映射相关的内容
105
+ function getFileJson(filePath) {
106
+ if (!fs.existsSync(filePath)) {
107
+ return {};
108
+ }
109
+ // 读取文件内容
110
+ const fileContent = fs.readFileSync(filePath, 'utf8');
111
+ // 使用贪婪模式匹配到最后一个 }
112
+ const objectStr = fileContent.replace(/export\s+default\s+/, '').trim();
113
+ try {
114
+ // 解析对象
115
+ return JSON5.parse(objectStr);
116
+ }
117
+ catch (e) {
118
+ console.log('解析语言映射文件报错:', filePath);
119
+ return {};
120
+ }
121
+ }
122
+ // 更新文件中的json
123
+ function updateJSONInFile(filePath, obj) {
124
+ // 确保目录存在(兼容 Windows 和 Unix 路径)
125
+ const dir = path.dirname(filePath);
126
+ if (!fs.existsSync(dir)) {
127
+ fs.mkdirSync(dir, { recursive: true });
128
+ }
129
+ // 生成新的对象字符串
130
+ const newObjectStr = JSON.stringify(obj, null, 2);
131
+ // 替换回文件内容
132
+ const newFileContent = `export default ${newObjectStr}`;
133
+ // 保存文件
134
+ fs.writeFileSync(filePath, newFileContent, 'utf8');
135
+ }
136
+
137
+ //@ts-ignore
138
+ const traverse = _traverse__namespace.default || _traverse__namespace;
139
+ //@ts-ignore
140
+ const generate = _generate__namespace.default || _generate__namespace;
141
+ // 提取 script 中的中文
142
+ function extractChineseFromScript(content, jsText) {
143
+ if (!content)
144
+ return undefined;
145
+ let flag = false; // 是否有更新
146
+ try {
147
+ const ast = babelParser__namespace.parse(content, {
148
+ sourceType: 'module',
149
+ plugins: ['jsx', 'typescript', 'decorators-legacy'],
150
+ });
151
+ traverse(ast, {
152
+ StringLiteral(path) {
153
+ // 第一层:AST 上下文过滤
154
+ const parent = path.parent;
155
+ // 跳过 import/export 语句
156
+ if (parent.type === 'ImportDeclaration' || parent.type === 'ImportSpecifier' ||
157
+ parent.type === 'ExportDeclaration' || parent.type === 'ExportSpecifier') {
158
+ return;
159
+ }
160
+ // 跳过 require() 调用
161
+ if (parent.type === 'CallExpression' &&
162
+ parent.callee.type === 'Identifier' &&
163
+ parent.callee.name === 'require') {
164
+ return;
165
+ }
166
+ // 跳过对象属性键
167
+ if (parent.type === 'ObjectProperty' && parent.key === path.node) {
168
+ return;
169
+ }
170
+ // 跳过函数参数名
171
+ if ((parent.type === 'FunctionDeclaration' || parent.type === 'FunctionExpression' ||
172
+ parent.type === 'ArrowFunctionExpression') &&
173
+ parent.params && parent.params.includes(path.node)) {
174
+ return;
175
+ }
176
+ // 跳过变量声明标识符
177
+ if (parent.type === 'VariableDeclarator' && parent.id === path.node) {
178
+ return;
179
+ }
180
+ // 排除打印等代码的中文文案(console.log, alert)
181
+ if (parent.type === 'CallExpression') {
182
+ const callee = parent.callee;
183
+ if ((callee.type === 'MemberExpression' &&
184
+ callee.object.name === 'console') ||
185
+ (callee.type === 'Identifier' && callee.name === 'alert')) {
186
+ return;
187
+ }
188
+ }
189
+ // 第二层:内容正则过滤(在 getChineseKey 中已包含)
190
+ const { key, isKey } = getChineseKey(path.node.value);
191
+ if (key) {
192
+ if (parent.type === 'JSXAttribute') {
193
+ if (isKey) {
194
+ path.node.extra.raw = `'${key}'`;
195
+ }
196
+ else {
197
+ path.node.extra.raw = `{${jsText}('${key}')}`;
198
+ }
199
+ }
200
+ else {
201
+ // 其他的jsx 基本就是直接替换
202
+ if (isKey) {
203
+ path.node.extra.raw = `'${key}'`;
204
+ }
205
+ else {
206
+ path.node.extra.raw = `${jsText}('${key}')`;
207
+ }
208
+ }
209
+ flag = true;
210
+ }
211
+ },
212
+ // 处理js 字符串模板的代码,我的测试${test}你在哪里啊?
213
+ TemplateLiteral(path) {
214
+ // 存储转换后的模板字符串和占位符对象
215
+ let transformedTemplate = '';
216
+ const placeholders = {};
217
+ let placeholderCounter = 0;
218
+ const rawTemplate = path.node.quasis.map((q) => q.value.raw).join('.{.*?}');
219
+ if (containsChinese(rawTemplate)) {
220
+ // 遍历模板字符串的静态部分和插值表达式
221
+ path.node.quasis.forEach((quasi, index) => {
222
+ // 添加静态部分到转换后的模板字符串
223
+ transformedTemplate += quasi.value.raw;
224
+ // 如果当前不是最后一个元素,则添加插值表达式的占位符
225
+ if (index < path.node.expressions.length) {
226
+ // 生成唯一的占位符名称
227
+ const placeholderName = `name${++placeholderCounter}`;
228
+ // 添加占位符到转换后的模板字符串
229
+ transformedTemplate += `{${placeholderName}}`;
230
+ // 添加占位符对象,其键为占位符名称,值为插值表达式的源代码
231
+ placeholders[placeholderName] = generate(path.node.expressions[index]).code;
232
+ }
233
+ });
234
+ // 中文模板的不进行处理
235
+ const { key, isKey } = getChineseKey(transformedTemplate);
236
+ const regex = new RegExp('`' + rawTemplate + '`');
237
+ const keyData = JSON.stringify(placeholders).replace(/"/g, '');
238
+ if (isKey) {
239
+ path.replaceWithSourceString(`'${key}&%&${keyData}'`);
240
+ }
241
+ else {
242
+ path.replaceWithSourceString(`${jsText}('${key}',${keyData})`);
243
+ }
244
+ flag = true;
245
+ }
246
+ },
247
+ JSXElement(path) {
248
+ path.traverse({
249
+ // 处理jsx中标签包含的文本
250
+ JSXText(node) {
251
+ const { key } = getChineseKey(node.node.value);
252
+ if (key) {
253
+ node.node.value = `{${jsText}('${key}')}`;
254
+ flag = true;
255
+ }
256
+ },
257
+ });
258
+ },
259
+ });
260
+ // 是否有更新
261
+ if (flag) {
262
+ return generate(ast).code;
263
+ }
264
+ }
265
+ catch (error) {
266
+ console.warn('解析脚本文件出错:', error);
267
+ return undefined;
268
+ }
269
+ }
270
+
271
+ // 对拼接的字符串进行处理整理
272
+ function concatenatedString(str, tempText) {
273
+ const strList = extractQuotedStrings(str);
274
+ if (!strList.length)
275
+ return;
276
+ if (strList.length) {
277
+ let strSource = str;
278
+ strList.forEach((item) => {
279
+ const { key } = getChineseKey(item.replace(/'|"/g, ''));
280
+ if (key) {
281
+ strSource = strSource.replace(item, `${tempText}('${key}')`);
282
+ }
283
+ });
284
+ return strSource;
285
+ }
286
+ }
287
+ // 提取 template 中的中文
288
+ function extractChineseFromTemplate(content, tempText) {
289
+ if (!content) {
290
+ return;
291
+ }
292
+ let templateContent = content;
293
+ // 使用@vue/compiler-sfc来解析模板
294
+ const descriptor = compilerSfc.parse(`<template>${content}</template>`).descriptor;
295
+ // 获取模板的AST
296
+ const ast = descriptor.template?.ast;
297
+ if (!ast)
298
+ return content;
299
+ // 定义一个函数来递归遍历AST并收集所有文本节点和插值节点
300
+ // AST 逆向 template 存在者问题这里使用替换的方式进行处理
301
+ function extractNodes(node, source) {
302
+ // 这是中的类型 {{ }}, 事件,也就是模板解析的都在这里
303
+ if (node.type === 5 && containsChinese(node.content?.content)) {
304
+ const tempStr = extractTransformString(node.content.content);
305
+ if (tempStr) {
306
+ const { key } = getChineseKey(tempStr.key);
307
+ if (key) {
308
+ const results = source.replace(node.content?.content.trim(), `${tempText}('${key}', { ${tempStr.data} })`);
309
+ templateContent = templateContent.replace(source, results);
310
+ }
311
+ }
312
+ else {
313
+ const strSource = concatenatedString(node.content.content, tempText);
314
+ if (strSource) {
315
+ const results = source.replace(node.content?.content.trim(), strSource);
316
+ templateContent = templateContent.replace(source, results);
317
+ }
318
+ }
319
+ }
320
+ // 这是 TEXT 类型
321
+ if (node.type === 2) {
322
+ const { key } = getChineseKey(node.content);
323
+ if (key) {
324
+ const results = source.replace(node.content.trim(), `{{${tempText}('${key}')}}`);
325
+ templateContent = templateContent.replace(source, results);
326
+ }
327
+ }
328
+ if (node.children) {
329
+ let pstr = node.loc.source;
330
+ // 优先处理属性值
331
+ if (node?.props?.length) {
332
+ // 这里是处理属性值的地方
333
+ node.props.forEach((item) => {
334
+ if (item.type === 6) {
335
+ // 这个是纯的属性类型 title="我的测试"
336
+ const { key } = getChineseKey(item?.value?.content);
337
+ if (key) {
338
+ pstr = pstr.replace(item.loc.source, `:${item.name}="${tempText}('${key}')"`);
339
+ }
340
+ }
341
+ else if (item.type === 7 && item.exp?.content) {
342
+ // 这里是一个bind 这里统一对 等号后面的字符串提取出来处理
343
+ const strSource = concatenatedString(item.exp.content, tempText);
344
+ if (strSource) {
345
+ pstr = pstr.replace(item.exp.content, strSource);
346
+ }
347
+ }
348
+ });
349
+ templateContent = templateContent.replace(node.loc.source, pstr);
350
+ }
351
+ // 同级的children 值
352
+ node.children.forEach((item) => {
353
+ // res 修改的值就是父级的值,父级的 source
354
+ extractNodes(item, pstr);
355
+ });
356
+ }
357
+ }
358
+ // 检查 AST 的有效性
359
+ if (ast.children && ast.children.length > 0) {
360
+ ast.children.forEach((child) => {
361
+ extractNodes(child, ast.source);
362
+ });
363
+ return templateContent;
364
+ }
365
+ return content;
366
+ }
367
+
368
+ // 初始化全局变量
369
+ globalThis.translationsMap = {};
370
+ globalThis.addTranslations = [];
371
+ globalThis.useTranslations = [];
372
+ globalThis.keyLength = 16;
373
+ // 默认配置
374
+ const defaultConfig = {
375
+ i18nPath: 'src/locales/zh-CN.ts',
376
+ langPath: ['src/locales/en.ts'],
377
+ regi18n: 'useI18n',
378
+ excludes: ['locale', 'useI18n', 'node_modules', 'dist', '.git'],
379
+ tempText: 't',
380
+ jsText: 't',
381
+ injectToJS: `\nimport { useI18n } from 'vue-i18n'\nconst { t } = useI18n()\n`,
382
+ delay: 1000,
383
+ reserveKeys: [],
384
+ runBuild: true,
385
+ keyLength: 16,
386
+ cryptoKey: 'i18n',
387
+ preText: 'common.',
388
+ };
389
+ // 解析命令行参数
390
+ function parseArgs() {
391
+ const args = process.argv.slice(2);
392
+ const config = {};
393
+ for (let i = 0; i < args.length; i++) {
394
+ const arg = args[i];
395
+ if (arg === '--i18n-path' && args[i + 1]) {
396
+ config.i18nPath = args[++i];
397
+ }
398
+ else if (arg === '--lang-path' && args[i + 1]) {
399
+ config.langPath = args[++i].split(',');
400
+ }
401
+ else if (arg === '--pre-text' && args[i + 1]) {
402
+ config.preText = args[++i];
403
+ }
404
+ else if (arg === '--key-length' && args[i + 1]) {
405
+ config.keyLength = parseInt(args[++i], 10);
406
+ }
407
+ else if (arg === '--crypto-key' && args[i + 1]) {
408
+ config.cryptoKey = args[++i];
409
+ }
410
+ else if (arg === '--help' || arg === '-h') {
411
+ console.log(`
412
+ 用法: vue-i18n-auto-plugin [选项]
413
+
414
+ 选项:
415
+ --i18n-path <path> 主语言文件路径 (默认: src/locales/zh-CN.ts)
416
+ --lang-path <paths> 其他语言文件路径,逗号分隔 (默认: src/locales/en.ts)
417
+ --pre-text <text> key 生成的前缀 (默认: common.)
418
+ --key-length <number> 生成的 key 长度 (默认: 16)
419
+ --crypto-key <key> 加密密钥 (默认: i18n)
420
+ --help, -h 显示帮助信息
421
+
422
+ 示例:
423
+ vue-i18n-auto-plugin
424
+ vue-i18n-auto-plugin --i18n-path src/locales/zh-CN.ts --pre-text app.
425
+ `);
426
+ process.exit(0);
427
+ }
428
+ }
429
+ return config;
430
+ }
431
+ // 处理 JS/TS 文件
432
+ function processJsFile(jsFilePath, options) {
433
+ try {
434
+ const jsFileContent = fs.readFileSync(jsFilePath, 'utf-8');
435
+ let scriptTemp = extractChineseFromScript(jsFileContent, options.jsText);
436
+ if (scriptTemp) {
437
+ if (options.regi18n && !jsFileContent.includes(options.regi18n)) {
438
+ scriptTemp = `${options.injectToJS}${scriptTemp}`;
439
+ }
440
+ fs.writeFileSync(jsFilePath, scriptTemp, 'utf-8');
441
+ console.log(`✓ 已转换: ${jsFilePath}`);
442
+ return true;
443
+ }
444
+ return false;
445
+ }
446
+ catch (error) {
447
+ console.error(`✗ 处理文件失败 ${jsFilePath}:`, error);
448
+ return false;
449
+ }
450
+ }
451
+ // 处理 Vue 文件
452
+ function processVueFile(vueFilePath, options) {
453
+ try {
454
+ let vueFileContent = fs.readFileSync(vueFilePath, 'utf-8');
455
+ const originalContent = vueFileContent;
456
+ const { descriptor, errors } = compilerSfc.parse(vueFileContent);
457
+ if (errors && errors.length) {
458
+ console.error(`✗ 解析 Vue 文件失败 ${vueFilePath}:`, errors);
459
+ return false;
460
+ }
461
+ let hasChanges = false;
462
+ let vueTemplate;
463
+ if (descriptor.template?.content) {
464
+ vueTemplate = extractChineseFromTemplate(descriptor.template.content, options.tempText);
465
+ if (vueTemplate && vueTemplate !== descriptor.template.content) {
466
+ vueFileContent = vueFileContent.replace(descriptor.template.content, vueTemplate);
467
+ hasChanges = true;
468
+ }
469
+ }
470
+ const dsScript = descriptor.script || descriptor.scriptSetup;
471
+ if (dsScript?.content) {
472
+ let scriptTemp = extractChineseFromScript(dsScript.content, options.jsText);
473
+ if (scriptTemp) {
474
+ if (options.regi18n && !scriptTemp.includes(options.regi18n)) {
475
+ scriptTemp = `${options.injectToJS}${scriptTemp}`;
476
+ }
477
+ vueFileContent = vueFileContent.replace(dsScript.content, scriptTemp);
478
+ hasChanges = true;
479
+ }
480
+ else if (vueTemplate && vueTemplate !== descriptor.template?.content) {
481
+ let strcontent = dsScript.content;
482
+ if (options.regi18n && !strcontent.includes(options.regi18n)) {
483
+ strcontent = `${options.injectToJS}${strcontent}`;
484
+ vueFileContent = vueFileContent.replace(dsScript.content, strcontent);
485
+ hasChanges = true;
486
+ }
487
+ }
488
+ }
489
+ if (hasChanges && vueFileContent !== originalContent) {
490
+ fs.writeFileSync(vueFilePath, vueFileContent, 'utf-8');
491
+ console.log(`✓ 已转换: ${vueFilePath}`);
492
+ return true;
493
+ }
494
+ return false;
495
+ }
496
+ catch (error) {
497
+ console.error(`✗ 处理文件失败 ${vueFilePath}:`, error);
498
+ return false;
499
+ }
500
+ }
501
+ // 主函数
502
+ async function main() {
503
+ const userConfig = parseArgs();
504
+ const configOption = { ...defaultConfig, ...userConfig };
505
+ // 初始化全局配置
506
+ globalThis.keyLength = configOption.keyLength;
507
+ globalThis.cryptoKey = configOption.cryptoKey;
508
+ globalThis.preText = configOption.preText;
509
+ // 加载现有的语言文件
510
+ const root = process.cwd();
511
+ const i18nPath = path.resolve(root, configOption.i18nPath);
512
+ if (fs.existsSync(i18nPath)) {
513
+ const obj = getFileJson(i18nPath);
514
+ Object.keys(obj).forEach(key => {
515
+ globalThis.translationsMap[key] = obj[key];
516
+ });
517
+ }
518
+ console.log('🚀 开始转换 i18n 硬编码...\n');
519
+ const patterns = [
520
+ 'src/**/*.vue',
521
+ 'src/**/*.ts',
522
+ 'src/**/*.js',
523
+ 'src/**/*.tsx',
524
+ 'src/**/*.jsx',
525
+ ];
526
+ const allFiles = await fastGlob.glob(patterns, {
527
+ cwd: root,
528
+ absolute: true,
529
+ ignore: [
530
+ '**/node_modules/**',
531
+ '**/dist/**',
532
+ '**/.git/**',
533
+ '**/locales/**',
534
+ ...configOption.excludes.map(exclude => `**/${exclude}/**`),
535
+ ],
536
+ });
537
+ console.log(`📁 找到 ${allFiles.length} 个文件需要处理\n`);
538
+ let processedCount = 0;
539
+ let errorCount = 0;
540
+ for (const filePath of allFiles) {
541
+ const ext = path.extname(filePath);
542
+ try {
543
+ if (ext === '.vue') {
544
+ if (processVueFile(filePath, configOption)) {
545
+ processedCount++;
546
+ }
547
+ }
548
+ else if (['.ts', '.js', '.tsx', '.jsx'].includes(ext)) {
549
+ if (processJsFile(filePath, configOption)) {
550
+ processedCount++;
551
+ }
552
+ }
553
+ }
554
+ catch (error) {
555
+ errorCount++;
556
+ console.error(`✗ 处理文件出错 ${filePath}:`, error);
557
+ }
558
+ }
559
+ console.log('\n📝 更新语言文件...');
560
+ updateJSONInFile(i18nPath, globalThis.translationsMap);
561
+ console.log(`✓ 已更新: ${i18nPath}`);
562
+ if (configOption.langPath) {
563
+ configOption.langPath.forEach(langFile => {
564
+ const lf = path.resolve(root, langFile);
565
+ const lm = getFileJson(lf);
566
+ const obj = {};
567
+ const endList = [];
568
+ Object.keys(globalThis.translationsMap).forEach(key => {
569
+ if (lm[key]) {
570
+ obj[key] = lm[key];
571
+ }
572
+ else {
573
+ endList.push({
574
+ key: key,
575
+ value: globalThis.translationsMap[key]
576
+ });
577
+ }
578
+ });
579
+ endList.forEach((item) => {
580
+ obj[item.key] = item.value;
581
+ });
582
+ updateJSONInFile(lf, obj);
583
+ console.log(`✓ 已更新: ${lf}`);
584
+ });
585
+ }
586
+ console.log(`\n✨ 转换完成!`);
587
+ console.log(` - 处理文件数: ${processedCount}`);
588
+ console.log(` - 错误文件数: ${errorCount}`);
589
+ console.log(` - 新增翻译 key: ${globalThis.addTranslations.length}`);
590
+ console.log(`\n💡 提示:转换后的文件已直接修改源文件,请检查 git diff 确认更改`);
591
+ }
592
+ main().catch(error => {
593
+ console.error('❌ 转换失败:', error);
594
+ process.exit(1);
595
+ });
596
+ //# sourceMappingURL=cli.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.cjs.js","sources":["../../utils.ts","../../scriptTransform.ts","../../templateTransform.ts","../../cli.ts"],"sourcesContent":["import crypto from 'crypto';\nimport fs from 'fs';\nimport path from 'path';\nimport JSON5 from 'json5';\n\n// 中文字符匹配函数(判断字符串是否包含中文字符)\nexport function containsChinese(str: string): boolean {\n return /[\\u4e00-\\u9fa5]/.test(str);\n}\n\n// 对正则表达式中的特殊字符进行转义\nexport function escapeRegExp(str: string): string {\n return str.replace(/[.*+?^=!:${}()|\\[\\]\\/\\\\]/g, '\\\\$&');\n}\n\n// 收集字符串中的字符, '我的测试' + 'abc' + '测试呀', 针对这种字符串的拼接处理\nexport function extractQuotedStrings(str: string): string[] {\n // 如果是 `这种拼接的`\n const regex = /([\"'])(.*?)\\1/g;\n let match;\n const matches: string[] = [];\n while ((match = regex.exec(str)) !== null) {\n matches.push(match[0]);\n }\n return matches;\n}\n\n// 对js 字符串的模板进行处理 类似 `我的测试${variable}`\nexport function extractTransformString(str: string) {\n // 正则表达式匹配 ${variable} 中的内容\n const regex = /\\$\\{([^}]+)\\}/g;\n if (!regex.test(str)) {\n return;\n }\n const placeholders: string[] = [];\n let index = 1;\n\n let transformedStr = str.replace(regex, (match, p1) => {\n placeholders.push(`name${index}: ${p1}`);\n const placeholder = `{name${index}}`;\n index++;\n return placeholder;\n }).replace(/`/g, '');\n return {\n key: transformedStr,\n data: placeholders.join(', ')\n };\n}\n\n// 生成唯一key\nfunction generateKey(chineseStr: string): string {\n const text = (globalThis.preText || '') + chineseStr;\n const hash = crypto.createHmac('sha256', globalThis.cryptoKey || 'i18n').update(text).digest('hex');\n // 保留加密结果的前N位,N由配置中的keyLength决定\n const len = globalThis.keyLength || 16;\n return hash.slice(0, len);\n}\n\n// 获取和收集key\nexport function getChineseKey(text: string): { key: string; isKey: boolean } {\n let key = '';\n if (containsChinese(text)) {\n const chineseText = text.trim().replace(/^&%&/, '');\n key = generateKey(chineseText);\n if (!globalThis.translationsMap[key]) {\n globalThis.addTranslations.push({\n key,\n value: chineseText\n });\n }\n // 这里一定是 use key ,使用的key值,修改中文和书写中文的时候会一个 标注\n globalThis.translationsMap[key] = chineseText;\n }\n let isKey = false;\n if (text) {\n // 使用正则的方法进行判断\n isKey = /^&%\\&/.test(text);\n }\n return {\n key,\n isKey\n };\n}\n\n// 读取文件映射相关的内容\nexport function getFileJson(filePath: string): Record<string, string> {\n if (!fs.existsSync(filePath)) {\n return {};\n }\n // 读取文件内容\n const fileContent = fs.readFileSync(filePath, 'utf8');\n // 使用贪婪模式匹配到最后一个 }\n const objectStr = fileContent.replace(/export\\s+default\\s+/, '').trim();\n try {\n // 解析对象\n return JSON5.parse(objectStr);\n } catch (e) {\n console.log('解析语言映射文件报错:', filePath);\n return {};\n }\n}\n\n// 更新文件中的json\nexport function updateJSONInFile(filePath: string, obj: Record<string, string>): void {\n // 确保目录存在(兼容 Windows 和 Unix 路径)\n const dir = path.dirname(filePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n // 生成新的对象字符串\n const newObjectStr = JSON.stringify(obj, null, 2);\n // 替换回文件内容\n const newFileContent = `export default ${newObjectStr}`;\n // 保存文件\n fs.writeFileSync(filePath, newFileContent, 'utf8');\n}\n\nexport function debounce<T extends (...args: any[]) => any>(\n func: T,\n wait: number,\n immediate = false\n): (...args: Parameters<T>) => void {\n let timeout: NodeJS.Timeout | null;\n\n return function (...args: Parameters<T>) {\n //@ts-ignore\n const context = this;\n\n const later = () => {\n timeout = null;\n if (!immediate) {\n func.apply(context, args);\n }\n };\n\n const callNow = immediate && !timeout;\n\n if (timeout) {\n clearTimeout(timeout);\n }\n timeout = setTimeout(later, wait);\n\n if (callNow) {\n func.apply(context, args);\n }\n };\n}\n","import * as babelParser from '@babel/parser';\nimport * as _generate from '@babel/generator';\nimport * as _traverse from '@babel/traverse';\n//@ts-ignore\nconst traverse = (_traverse as any).default || _traverse;\n//@ts-ignore\nconst generate = (_generate as any).default || _generate;\n\nimport {\n containsChinese,\n getChineseKey\n} from './utils';\n\n// 提取 script 中的中文\nexport function extractChineseFromScript(content: string, jsText: string): string | undefined {\n if (!content) return undefined;\n\n let flag = false; // 是否有更新\n try {\n const ast = babelParser.parse(content, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript', 'decorators-legacy'],\n });\n\n traverse(ast, {\n StringLiteral(path: any) {\n // 第一层:AST 上下文过滤\n const parent = path.parent;\n \n // 跳过 import/export 语句\n if (parent.type === 'ImportDeclaration' || parent.type === 'ImportSpecifier' || \n parent.type === 'ExportDeclaration' || parent.type === 'ExportSpecifier') {\n return;\n }\n \n // 跳过 require() 调用\n if (parent.type === 'CallExpression' && \n parent.callee.type === 'Identifier' && \n parent.callee.name === 'require') {\n return;\n }\n \n // 跳过对象属性键\n if (parent.type === 'ObjectProperty' && parent.key === path.node) {\n return;\n }\n \n // 跳过函数参数名\n if ((parent.type === 'FunctionDeclaration' || parent.type === 'FunctionExpression' || \n parent.type === 'ArrowFunctionExpression') && \n parent.params && parent.params.includes(path.node)) {\n return;\n }\n \n // 跳过变量声明标识符\n if (parent.type === 'VariableDeclarator' && parent.id === path.node) {\n return;\n }\n \n // 排除打印等代码的中文文案(console.log, alert)\n if (parent.type === 'CallExpression') {\n const callee = parent.callee;\n if (\n (callee.type === 'MemberExpression' &&\n callee.object.name === 'console') ||\n (callee.type === 'Identifier' && callee.name === 'alert')\n ) {\n return;\n }\n }\n \n // 第二层:内容正则过滤(在 getChineseKey 中已包含)\n const { key, isKey } = getChineseKey(path.node.value);\n if (key) {\n if (parent.type === 'JSXAttribute') {\n if (isKey) {\n path.node.extra.raw = `'${key}'`;\n } else {\n path.node.extra.raw = `{${jsText}('${key}')}`;\n }\n } else {\n // 其他的jsx 基本就是直接替换\n if (isKey) {\n path.node.extra.raw = `'${key}'`;\n } else {\n path.node.extra.raw = `${jsText}('${key}')`;\n }\n }\n flag = true;\n }\n },\n // 处理js 字符串模板的代码,我的测试${test}你在哪里啊?\n TemplateLiteral(path: any) {\n // 存储转换后的模板字符串和占位符对象\n let transformedTemplate = '';\n const placeholders: any = {};\n let placeholderCounter = 0;\n const rawTemplate = path.node.quasis.map((q: any) => q.value.raw).join('.{.*?}');\n if (containsChinese(rawTemplate)) {\n // 遍历模板字符串的静态部分和插值表达式\n path.node.quasis.forEach((quasi: any, index: number) => {\n // 添加静态部分到转换后的模板字符串\n transformedTemplate += quasi.value.raw;\n // 如果当前不是最后一个元素,则添加插值表达式的占位符\n if (index < path.node.expressions.length) {\n // 生成唯一的占位符名称\n const placeholderName = `name${++placeholderCounter}`;\n // 添加占位符到转换后的模板字符串\n transformedTemplate += `{${placeholderName}}`;\n // 添加占位符对象,其键为占位符名称,值为插值表达式的源代码\n placeholders[placeholderName] = generate(path.node.expressions[index]).code;\n }\n });\n // 中文模板的不进行处理\n const { key, isKey } = getChineseKey(transformedTemplate);\n const regex = new RegExp('`' + rawTemplate + '`');\n const keyData = JSON.stringify(placeholders).replace(/\"/g, '');\n if (isKey) {\n path.replaceWithSourceString(`'${key}&%&${keyData}'`);\n } else {\n path.replaceWithSourceString(`${jsText}('${key}',${keyData})`);\n }\n flag = true;\n }\n },\n JSXElement(path: any) {\n path.traverse({\n // 处理jsx中标签包含的文本\n JSXText(node: any) {\n const { key } = getChineseKey(node.node.value);\n if (key) {\n node.node.value = `{${jsText}('${key}')}`;\n flag = true;\n }\n },\n });\n },\n });\n // 是否有更新\n if (flag) {\n return generate(ast).code;\n }\n } catch (error) {\n console.warn('解析脚本文件出错:', error);\n return undefined;\n }\n}\n","import { parse } from '@vue/compiler-sfc';\nimport {\n containsChinese,\n extractQuotedStrings,\n extractTransformString,\n getChineseKey\n} from './utils';\n\n// 对拼接的字符串进行处理整理\nexport function concatenatedString(str: string, tempText: string): string | undefined {\n const strList = extractQuotedStrings(str);\n if (!strList.length) return;\n if (strList.length) {\n let strSource = str;\n strList.forEach((item: string) => {\n const { key } = getChineseKey(item.replace(/'|\"/g, ''));\n if (key) {\n strSource = strSource.replace(item, `${tempText}('${key}')`);\n }\n });\n return strSource;\n }\n}\n\n// 提取 template 中的中文\nexport function extractChineseFromTemplate(content: string, tempText: string): string | undefined {\n if (!content) {\n return;\n }\n\n let templateContent = content;\n\n // 使用@vue/compiler-sfc来解析模板\n const descriptor = parse(`<template>${content}</template>`).descriptor;\n // 获取模板的AST\n const ast = descriptor.template?.ast;\n if (!ast) return content;\n // 定义一个函数来递归遍历AST并收集所有文本节点和插值节点\n // AST 逆向 template 存在者问题这里使用替换的方式进行处理\n function extractNodes(node: any, source: string) {\n // 这是中的类型 {{ }}, 事件,也就是模板解析的都在这里\n if (node.type === 5 && containsChinese(node.content?.content)) {\n const tempStr = extractTransformString(node.content.content);\n if (tempStr) {\n const { key } = getChineseKey(tempStr.key);\n if (key) {\n const results = source.replace(node.content?.content.trim(), `${tempText}('${key}', { ${tempStr.data} })`);\n templateContent = templateContent.replace(source, results);\n }\n } else {\n const strSource = concatenatedString(node.content.content, tempText);\n if (strSource) {\n const results = source.replace(node.content?.content.trim(), strSource);\n templateContent = templateContent.replace(source, results);\n }\n }\n }\n // 这是 TEXT 类型\n if (node.type === 2) {\n const { key } = getChineseKey(node.content);\n if (key) {\n const results = source.replace(node.content.trim(), `{{${tempText}('${key}')}}`);\n templateContent = templateContent.replace(source, results);\n }\n }\n if (node.children) {\n let pstr = node.loc.source;\n // 优先处理属性值\n if (node?.props?.length) {\n // 这里是处理属性值的地方\n node.props.forEach((item: any) => {\n if (item.type === 6) {\n // 这个是纯的属性类型 title=\"我的测试\"\n const { key } = getChineseKey(item?.value?.content);\n if (key) {\n pstr = pstr.replace(item.loc.source, `:${item.name}=\"${tempText}('${key}')\"`);\n }\n } else if (item.type === 7 && item.exp?.content) {\n // 这里是一个bind 这里统一对 等号后面的字符串提取出来处理\n const strSource = concatenatedString(item.exp.content, tempText);\n if (strSource) {\n pstr = pstr.replace(item.exp.content, strSource);\n }\n }\n });\n templateContent = templateContent.replace(node.loc.source, pstr);\n }\n // 同级的children 值\n node.children.forEach((item: any) => {\n // res 修改的值就是父级的值,父级的 source\n extractNodes(item, pstr);\n });\n }\n }\n // 检查 AST 的有效性\n if (ast.children && ast.children.length > 0) {\n ast.children.forEach((child: any) => {\n extractNodes(child, ast.source);\n });\n return templateContent;\n }\n return content;\n}\n","#!/usr/bin/env node\nimport fs from 'fs';\nimport path from 'path';\nimport { glob } from 'fast-glob';\nimport { parse } from '@vue/compiler-sfc';\nimport { extractChineseFromScript } from './scriptTransform';\nimport { extractChineseFromTemplate } from './templateTransform';\nimport { getFileJson, updateJSONInFile } from './utils';\nimport type { I18nPluginOptions } from './types';\n\n// 初始化全局变量\nglobalThis.translationsMap = {};\nglobalThis.addTranslations = [];\nglobalThis.useTranslations = [];\n(globalThis as any).keyLength = 16;\n\n// 默认配置\nconst defaultConfig: I18nPluginOptions = {\n i18nPath: 'src/locales/zh-CN.ts',\n langPath: ['src/locales/en.ts'],\n regi18n: 'useI18n',\n excludes: ['locale', 'useI18n', 'node_modules', 'dist', '.git'],\n tempText: 't',\n jsText: 't',\n injectToJS: `\\nimport { useI18n } from 'vue-i18n'\\nconst { t } = useI18n()\\n`,\n delay: 1000,\n reserveKeys: [],\n runBuild: true,\n keyLength: 16,\n cryptoKey: 'i18n',\n preText: 'common.',\n};\n\n// 解析命令行参数\nfunction parseArgs(): Partial<I18nPluginOptions> {\n const args = process.argv.slice(2);\n const config: Partial<I18nPluginOptions> = {};\n \n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === '--i18n-path' && args[i + 1]) {\n config.i18nPath = args[++i];\n } else if (arg === '--lang-path' && args[i + 1]) {\n config.langPath = args[++i].split(',');\n } else if (arg === '--pre-text' && args[i + 1]) {\n config.preText = args[++i];\n } else if (arg === '--key-length' && args[i + 1]) {\n config.keyLength = parseInt(args[++i], 10);\n } else if (arg === '--crypto-key' && args[i + 1]) {\n config.cryptoKey = args[++i];\n } else if (arg === '--help' || arg === '-h') {\n console.log(`\n用法: vue-i18n-auto-plugin [选项]\n\n选项:\n --i18n-path <path> 主语言文件路径 (默认: src/locales/zh-CN.ts)\n --lang-path <paths> 其他语言文件路径,逗号分隔 (默认: src/locales/en.ts)\n --pre-text <text> key 生成的前缀 (默认: common.)\n --key-length <number> 生成的 key 长度 (默认: 16)\n --crypto-key <key> 加密密钥 (默认: i18n)\n --help, -h 显示帮助信息\n\n示例:\n vue-i18n-auto-plugin\n vue-i18n-auto-plugin --i18n-path src/locales/zh-CN.ts --pre-text app.\n `);\n process.exit(0);\n }\n }\n \n return config;\n}\n\n// 处理 JS/TS 文件\nfunction processJsFile(jsFilePath: string, options: I18nPluginOptions): boolean {\n try {\n const jsFileContent = fs.readFileSync(jsFilePath, 'utf-8');\n let scriptTemp = extractChineseFromScript(jsFileContent, options.jsText!);\n \n if (scriptTemp) {\n if (options.regi18n && !jsFileContent.includes(options.regi18n)) {\n scriptTemp = `${options.injectToJS}${scriptTemp}`;\n }\n fs.writeFileSync(jsFilePath, scriptTemp, 'utf-8');\n console.log(`✓ 已转换: ${jsFilePath}`);\n return true;\n }\n return false;\n } catch (error) {\n console.error(`✗ 处理文件失败 ${jsFilePath}:`, error);\n return false;\n }\n}\n\n// 处理 Vue 文件\nfunction processVueFile(vueFilePath: string, options: I18nPluginOptions): boolean {\n try {\n let vueFileContent = fs.readFileSync(vueFilePath, 'utf-8');\n const originalContent = vueFileContent;\n \n const { descriptor, errors } = parse(vueFileContent);\n \n if (errors && errors.length) {\n console.error(`✗ 解析 Vue 文件失败 ${vueFilePath}:`, errors);\n return false;\n }\n \n let hasChanges = false;\n let vueTemplate: string | undefined;\n \n if (descriptor.template?.content) {\n vueTemplate = extractChineseFromTemplate(descriptor.template.content, options.tempText!);\n if (vueTemplate && vueTemplate !== descriptor.template.content) {\n vueFileContent = vueFileContent.replace(descriptor.template.content, vueTemplate);\n hasChanges = true;\n }\n }\n \n const dsScript = descriptor.script || descriptor.scriptSetup;\n if (dsScript?.content) {\n let scriptTemp = extractChineseFromScript(dsScript.content, options.jsText!);\n \n if (scriptTemp) {\n if (options.regi18n && !scriptTemp.includes(options.regi18n)) {\n scriptTemp = `${options.injectToJS}${scriptTemp}`;\n }\n vueFileContent = vueFileContent.replace(dsScript.content, scriptTemp);\n hasChanges = true;\n } else if (vueTemplate && vueTemplate !== descriptor.template?.content) {\n let strcontent = dsScript.content;\n if (options.regi18n && !strcontent.includes(options.regi18n)) {\n strcontent = `${options.injectToJS}${strcontent}`;\n vueFileContent = vueFileContent.replace(dsScript.content, strcontent);\n hasChanges = true;\n }\n }\n }\n \n if (hasChanges && vueFileContent !== originalContent) {\n fs.writeFileSync(vueFilePath, vueFileContent, 'utf-8');\n console.log(`✓ 已转换: ${vueFilePath}`);\n return true;\n }\n \n return false;\n } catch (error) {\n console.error(`✗ 处理文件失败 ${vueFilePath}:`, error);\n return false;\n }\n}\n\n// 主函数\nasync function main() {\n const userConfig = parseArgs();\n const configOption: I18nPluginOptions = { ...defaultConfig, ...userConfig };\n \n // 初始化全局配置\n (globalThis as any).keyLength = configOption.keyLength;\n (globalThis as any).cryptoKey = configOption.cryptoKey;\n (globalThis as any).preText = configOption.preText;\n \n // 加载现有的语言文件\n const root = process.cwd();\n const i18nPath = path.resolve(root, configOption.i18nPath!);\n if (fs.existsSync(i18nPath)) {\n const obj = getFileJson(i18nPath);\n Object.keys(obj).forEach(key => {\n globalThis.translationsMap[key] = obj[key];\n });\n }\n \n console.log('🚀 开始转换 i18n 硬编码...\\n');\n \n const patterns = [\n 'src/**/*.vue',\n 'src/**/*.ts',\n 'src/**/*.js',\n 'src/**/*.tsx',\n 'src/**/*.jsx',\n ];\n \n const allFiles = await glob(patterns, {\n cwd: root,\n absolute: true,\n ignore: [\n '**/node_modules/**',\n '**/dist/**',\n '**/.git/**',\n '**/locales/**',\n ...configOption.excludes!.map(exclude => `**/${exclude}/**`),\n ],\n });\n \n console.log(`📁 找到 ${allFiles.length} 个文件需要处理\\n`);\n \n let processedCount = 0;\n let errorCount = 0;\n \n for (const filePath of allFiles) {\n const ext = path.extname(filePath);\n \n try {\n if (ext === '.vue') {\n if (processVueFile(filePath, configOption)) {\n processedCount++;\n }\n } else if (['.ts', '.js', '.tsx', '.jsx'].includes(ext)) {\n if (processJsFile(filePath, configOption)) {\n processedCount++;\n }\n }\n } catch (error) {\n errorCount++;\n console.error(`✗ 处理文件出错 ${filePath}:`, error);\n }\n }\n \n console.log('\\n📝 更新语言文件...');\n updateJSONInFile(i18nPath, globalThis.translationsMap);\n console.log(`✓ 已更新: ${i18nPath}`);\n \n if (configOption.langPath) {\n configOption.langPath.forEach(langFile => {\n const lf = path.resolve(root, langFile);\n const lm = getFileJson(lf);\n const obj: any = {};\n const endList: any = [];\n \n Object.keys(globalThis.translationsMap).forEach(key => {\n if (lm[key]) {\n obj[key] = lm[key];\n } else {\n endList.push({\n key: key,\n value: globalThis.translationsMap[key]\n });\n }\n });\n \n endList.forEach((item: any) => {\n obj[item.key] = item.value;\n });\n \n updateJSONInFile(lf, obj);\n console.log(`✓ 已更新: ${lf}`);\n });\n }\n \n console.log(`\\n✨ 转换完成!`);\n console.log(` - 处理文件数: ${processedCount}`);\n console.log(` - 错误文件数: ${errorCount}`);\n console.log(` - 新增翻译 key: ${globalThis.addTranslations.length}`);\n console.log(`\\n💡 提示:转换后的文件已直接修改源文件,请检查 git diff 确认更改`);\n}\n\nmain().catch(error => {\n console.error('❌ 转换失败:', error);\n process.exit(1);\n});\n"],"names":["_traverse","_generate","babelParser","parse","glob"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA;AACM,SAAU,eAAe,CAAC,GAAW,EAAA;AACzC,IAAA,OAAO,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC;AACpC;AAOA;AACM,SAAU,oBAAoB,CAAC,GAAW,EAAA;;IAE9C,MAAM,KAAK,GAAG,gBAAgB;AAC9B,IAAA,IAAI,KAAK;IACT,MAAM,OAAO,GAAa,EAAE;AAC5B,IAAA,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE;QACzC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACxB;AACA,IAAA,OAAO,OAAO;AAChB;AAEA;AACM,SAAU,sBAAsB,CAAC,GAAW,EAAA;;IAEhD,MAAM,KAAK,GAAG,gBAAgB;IAC9B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QACpB;IACF;IACA,MAAM,YAAY,GAAa,EAAE;IACjC,IAAI,KAAK,GAAG,CAAC;AAEb,IAAA,IAAI,cAAc,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,KAAI;QACpD,YAAY,CAAC,IAAI,CAAC,CAAA,IAAA,EAAO,KAAK,CAAA,EAAA,EAAK,EAAE,CAAA,CAAE,CAAC;AACxC,QAAA,MAAM,WAAW,GAAG,CAAA,KAAA,EAAQ,KAAK,GAAG;AACpC,QAAA,KAAK,EAAE;AACP,QAAA,OAAO,WAAW;IACpB,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;IACpB,OAAO;AACL,QAAA,GAAG,EAAE,cAAc;AACnB,QAAA,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,IAAI;KAC7B;AACH;AAEA;AACA,SAAS,WAAW,CAAC,UAAkB,EAAA;IACrC,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,IAAI,EAAE,IAAI,UAAU;IACpD,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,SAAS,IAAI,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;;AAEnG,IAAA,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,IAAI,EAAE;IACtC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;AAC3B;AAEA;AACM,SAAU,aAAa,CAAC,IAAY,EAAA;IACxC,IAAI,GAAG,GAAG,EAAE;AACZ,IAAA,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE;AACzB,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;AACnD,QAAA,GAAG,GAAG,WAAW,CAAC,WAAW,CAAC;QAC9B,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE;AACpC,YAAA,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC;gBAC9B,GAAG;AACH,gBAAA,KAAK,EAAE;AACR,aAAA,CAAC;QACJ;;AAEA,QAAA,UAAU,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,WAAW;IAC/C;IACA,IAAI,KAAK,GAAG,KAAK;IACjB,IAAI,IAAI,EAAE;;AAER,QAAA,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;IAC5B;IACA,OAAO;QACL,GAAG;QACH;KACD;AACH;AAEA;AACM,SAAU,WAAW,CAAC,QAAgB,EAAA;IAC1C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;AAC5B,QAAA,OAAO,EAAE;IACX;;IAEA,MAAM,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC;;AAErD,IAAA,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE;AACvE,IAAA,IAAI;;AAEF,QAAA,OAAO,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC;IAC/B;IAAE,OAAO,CAAC,EAAE;AACV,QAAA,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,QAAQ,CAAC;AACpC,QAAA,OAAO,EAAE;IACX;AACF;AAEA;AACM,SAAU,gBAAgB,CAAC,QAAgB,EAAE,GAA2B,EAAA;;IAE5E,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;IAClC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;QACvB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACxC;;AAEA,IAAA,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;;AAEjD,IAAA,MAAM,cAAc,GAAG,CAAA,eAAA,EAAkB,YAAY,EAAE;;IAEvD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,cAAc,EAAE,MAAM,CAAC;AACpD;;AChHA;AACA,MAAM,QAAQ,GAAIA,oBAAiB,CAAC,OAAO,IAAIA,oBAAS;AACxD;AACA,MAAM,QAAQ,GAAIC,oBAAiB,CAAC,OAAO,IAAIA,oBAAS;AAOxD;AACM,SAAU,wBAAwB,CAAC,OAAe,EAAE,MAAc,EAAA;AACtE,IAAA,IAAI,CAAC,OAAO;AAAE,QAAA,OAAO,SAAS;AAE9B,IAAA,IAAI,IAAI,GAAG,KAAK,CAAC;AACjB,IAAA,IAAI;AACF,QAAA,MAAM,GAAG,GAAGC,sBAAW,CAAC,KAAK,CAAC,OAAO,EAAE;AACrC,YAAA,UAAU,EAAE,QAAQ;AACpB,YAAA,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,mBAAmB,CAAC;AACpD,SAAA,CAAC;QAEF,QAAQ,CAAC,GAAG,EAAE;AACZ,YAAA,aAAa,CAAC,IAAS,EAAA;;AAErB,gBAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM;;gBAG1B,IAAI,MAAM,CAAC,IAAI,KAAK,mBAAmB,IAAI,MAAM,CAAC,IAAI,KAAK,iBAAiB;oBACxE,MAAM,CAAC,IAAI,KAAK,mBAAmB,IAAI,MAAM,CAAC,IAAI,KAAK,iBAAiB,EAAE;oBAC5E;gBACF;;AAGA,gBAAA,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB;AAChC,oBAAA,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY;AACnC,oBAAA,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE;oBACpC;gBACF;;AAGA,gBAAA,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI,CAAC,IAAI,EAAE;oBAChE;gBACF;;gBAGA,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,qBAAqB,IAAI,MAAM,CAAC,IAAI,KAAK,oBAAoB;AAC7E,oBAAA,MAAM,CAAC,IAAI,KAAK,yBAAyB;AAC1C,oBAAA,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;oBACtD;gBACF;;AAGA,gBAAA,IAAI,MAAM,CAAC,IAAI,KAAK,oBAAoB,IAAI,MAAM,CAAC,EAAE,KAAK,IAAI,CAAC,IAAI,EAAE;oBACnE;gBACF;;AAGA,gBAAA,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,EAAE;AACpC,oBAAA,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM;AAC5B,oBAAA,IACE,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB;AACjC,wBAAA,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS;AAClC,yBAAC,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,EACzD;wBACA;oBACF;gBACF;;AAGA,gBAAA,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;gBACrD,IAAI,GAAG,EAAE;AACP,oBAAA,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,EAAE;wBAClC,IAAI,KAAK,EAAE;4BACT,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA,CAAG;wBAClC;6BAAO;AACL,4BAAA,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAA,CAAA,EAAI,MAAM,CAAA,EAAA,EAAK,GAAG,CAAA,GAAA,CAAK;wBAC/C;oBACF;yBAAO;;wBAEL,IAAI,KAAK,EAAE;4BACT,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA,CAAG;wBAClC;6BAAO;AACL,4BAAA,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAA,EAAG,MAAM,CAAA,EAAA,EAAK,GAAG,CAAA,EAAA,CAAI;wBAC7C;oBACF;oBACA,IAAI,GAAG,IAAI;gBACb;YACF,CAAC;;AAED,YAAA,eAAe,CAAC,IAAS,EAAA;;gBAEvB,IAAI,mBAAmB,GAAG,EAAE;gBAC5B,MAAM,YAAY,GAAQ,EAAE;gBAC5B,IAAI,kBAAkB,GAAG,CAAC;gBAC1B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAM,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC;AAChF,gBAAA,IAAI,eAAe,CAAC,WAAW,CAAC,EAAE;;AAEhC,oBAAA,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAU,EAAE,KAAa,KAAI;;AAErD,wBAAA,mBAAmB,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG;;wBAEtC,IAAI,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE;;AAExC,4BAAA,MAAM,eAAe,GAAG,CAAA,IAAA,EAAO,EAAE,kBAAkB,EAAE;;AAErD,4BAAA,mBAAmB,IAAI,CAAA,CAAA,EAAI,eAAe,CAAA,CAAA,CAAG;;AAE7C,4BAAA,YAAY,CAAC,eAAe,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;wBAC7E;AACF,oBAAA,CAAC,CAAC;;oBAEF,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC,mBAAmB,CAAC;oBACzD,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG,WAAW,GAAG,GAAG,CAAC;AACjD,oBAAA,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;oBAC9D,IAAI,KAAK,EAAE;wBACT,IAAI,CAAC,uBAAuB,CAAC,CAAA,CAAA,EAAI,GAAG,CAAA,GAAA,EAAM,OAAO,CAAA,CAAA,CAAG,CAAC;oBACvD;yBAAO;wBACL,IAAI,CAAC,uBAAuB,CAAC,CAAA,EAAG,MAAM,CAAA,EAAA,EAAK,GAAG,CAAA,EAAA,EAAK,OAAO,CAAA,CAAA,CAAG,CAAC;oBAChE;oBACA,IAAI,GAAG,IAAI;gBACb;YACF,CAAC;AACD,YAAA,UAAU,CAAC,IAAS,EAAA;gBAClB,IAAI,CAAC,QAAQ,CAAC;;AAEZ,oBAAA,OAAO,CAAC,IAAS,EAAA;AACf,wBAAA,MAAM,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;wBAC9C,IAAI,GAAG,EAAE;4BACP,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,MAAM,CAAA,EAAA,EAAK,GAAG,CAAA,GAAA,CAAK;4BACzC,IAAI,GAAG,IAAI;wBACb;oBACF,CAAC;AACF,iBAAA,CAAC;YACJ,CAAC;AACF,SAAA,CAAC;;QAEF,IAAI,IAAI,EAAE;AACR,YAAA,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI;QAC3B;IACF;IAAE,OAAO,KAAK,EAAE;AACd,QAAA,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC;AAChC,QAAA,OAAO,SAAS;IAClB;AACF;;AC1IA;AACM,SAAU,kBAAkB,CAAC,GAAW,EAAE,QAAgB,EAAA;AAC9D,IAAA,MAAM,OAAO,GAAG,oBAAoB,CAAC,GAAG,CAAC;IACzC,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE;AACrB,IAAA,IAAI,OAAO,CAAC,MAAM,EAAE;QAClB,IAAI,SAAS,GAAG,GAAG;AACnB,QAAA,OAAO,CAAC,OAAO,CAAC,CAAC,IAAY,KAAI;AAC/B,YAAA,MAAM,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YACvD,IAAI,GAAG,EAAE;AACP,gBAAA,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA,EAAG,QAAQ,CAAA,EAAA,EAAK,GAAG,CAAA,EAAA,CAAI,CAAC;YAC9D;AACF,QAAA,CAAC,CAAC;AACF,QAAA,OAAO,SAAS;IAClB;AACF;AAEA;AACM,SAAU,0BAA0B,CAAC,OAAe,EAAE,QAAgB,EAAA;IAC1E,IAAI,CAAC,OAAO,EAAE;QACZ;IACF;IAEA,IAAI,eAAe,GAAG,OAAO;;IAG7B,MAAM,UAAU,GAAGC,iBAAK,CAAC,CAAA,UAAA,EAAa,OAAO,CAAA,WAAA,CAAa,CAAC,CAAC,UAAU;;AAEtE,IAAA,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,EAAE,GAAG;AACpC,IAAA,IAAI,CAAC,GAAG;AAAE,QAAA,OAAO,OAAO;;;AAGxB,IAAA,SAAS,YAAY,CAAC,IAAS,EAAE,MAAc,EAAA;;AAE7C,QAAA,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE;YAC7D,MAAM,OAAO,GAAG,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;YAC5D,IAAI,OAAO,EAAE;gBACX,MAAM,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC;gBAC1C,IAAI,GAAG,EAAE;oBACP,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,CAAA,EAAG,QAAQ,CAAA,EAAA,EAAK,GAAG,CAAA,KAAA,EAAQ,OAAO,CAAC,IAAI,CAAA,GAAA,CAAK,CAAC;oBAC1G,eAAe,GAAG,eAAe,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC;gBAC5D;YACF;iBAAO;AACL,gBAAA,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC;gBACpE,IAAI,SAAS,EAAE;AACb,oBAAA,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,SAAS,CAAC;oBACvE,eAAe,GAAG,eAAe,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC;gBAC5D;YACF;QACF;;AAEA,QAAA,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE;YACnB,MAAM,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC;YAC3C,IAAI,GAAG,EAAE;AACP,gBAAA,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAA,EAAA,EAAK,QAAQ,KAAK,GAAG,CAAA,IAAA,CAAM,CAAC;gBAChF,eAAe,GAAG,eAAe,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC;YAC5D;QACF;AACA,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE;AACjB,YAAA,IAAI,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM;;AAE1B,YAAA,IAAI,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE;;gBAEvB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAS,KAAI;AAC/B,oBAAA,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE;;AAEnB,wBAAA,MAAM,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC;wBACnD,IAAI,GAAG,EAAE;4BACP,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAA,CAAA,EAAI,IAAI,CAAC,IAAI,CAAA,EAAA,EAAK,QAAQ,CAAA,EAAA,EAAK,GAAG,CAAA,GAAA,CAAK,CAAC;wBAC/E;oBACF;AAAO,yBAAA,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE;;AAE/C,wBAAA,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC;wBAChE,IAAI,SAAS,EAAE;AACb,4BAAA,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC;wBAClD;oBACF;AACF,gBAAA,CAAC,CAAC;AACF,gBAAA,eAAe,GAAG,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC;YAClE;;YAEA,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAS,KAAI;;AAElC,gBAAA,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC;AAC1B,YAAA,CAAC,CAAC;QACJ;IACF;;AAEA,IAAA,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;QAC3C,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAU,KAAI;AAClC,YAAA,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC;AACjC,QAAA,CAAC,CAAC;AACF,QAAA,OAAO,eAAe;IACxB;AACA,IAAA,OAAO,OAAO;AAChB;;AC5FA;AACA,UAAU,CAAC,eAAe,GAAG,EAAE;AAC/B,UAAU,CAAC,eAAe,GAAG,EAAE;AAC/B,UAAU,CAAC,eAAe,GAAG,EAAE;AAC9B,UAAkB,CAAC,SAAS,GAAG,EAAE;AAElC;AACA,MAAM,aAAa,GAAsB;AACvC,IAAA,QAAQ,EAAE,sBAAsB;IAChC,QAAQ,EAAE,CAAC,mBAAmB,CAAC;AAC/B,IAAA,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC;AAC/D,IAAA,QAAQ,EAAE,GAAG;AACb,IAAA,MAAM,EAAE,GAAG;AACX,IAAA,UAAU,EAAE,CAAA,+DAAA,CAAiE;AAC7E,IAAA,KAAK,EAAE,IAAI;AACX,IAAA,WAAW,EAAE,EAAE;AACf,IAAA,QAAQ,EAAE,IAAI;AACd,IAAA,SAAS,EAAE,EAAE;AACb,IAAA,SAAS,EAAE,MAAM;AACjB,IAAA,OAAO,EAAE,SAAS;CACnB;AAED;AACA,SAAS,SAAS,GAAA;IAChB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAClC,MAAM,MAAM,GAA+B,EAAE;AAE7C,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACpC,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC;QACnB,IAAI,GAAG,KAAK,aAAa,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE;YACxC,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7B;aAAO,IAAI,GAAG,KAAK,aAAa,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE;AAC/C,YAAA,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;QACxC;aAAO,IAAI,GAAG,KAAK,YAAY,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE;YAC9C,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5B;aAAO,IAAI,GAAG,KAAK,cAAc,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE;AAChD,YAAA,MAAM,CAAC,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QAC5C;aAAO,IAAI,GAAG,KAAK,cAAc,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE;YAChD,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9B;aAAO,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE;YAC3C,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;AAcX,MAAA,CAAA,CAAC;AACF,YAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACjB;IACF;AAEA,IAAA,OAAO,MAAM;AACf;AAEA;AACA,SAAS,aAAa,CAAC,UAAkB,EAAE,OAA0B,EAAA;AACnE,IAAA,IAAI;QACF,MAAM,aAAa,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC;QAC1D,IAAI,UAAU,GAAG,wBAAwB,CAAC,aAAa,EAAE,OAAO,CAAC,MAAO,CAAC;QAEzE,IAAI,UAAU,EAAE;AACd,YAAA,IAAI,OAAO,CAAC,OAAO,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;gBAC/D,UAAU,GAAG,GAAG,OAAO,CAAC,UAAU,CAAA,EAAG,UAAU,EAAE;YACnD;YACA,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC;AACjD,YAAA,OAAO,CAAC,GAAG,CAAC,UAAU,UAAU,CAAA,CAAE,CAAC;AACnC,YAAA,OAAO,IAAI;QACb;AACA,QAAA,OAAO,KAAK;IACd;IAAE,OAAO,KAAK,EAAE;QACd,OAAO,CAAC,KAAK,CAAC,CAAA,SAAA,EAAY,UAAU,CAAA,CAAA,CAAG,EAAE,KAAK,CAAC;AAC/C,QAAA,OAAO,KAAK;IACd;AACF;AAEA;AACA,SAAS,cAAc,CAAC,WAAmB,EAAE,OAA0B,EAAA;AACrE,IAAA,IAAI;QACF,IAAI,cAAc,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC;QAC1D,MAAM,eAAe,GAAG,cAAc;QAEtC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAGA,iBAAK,CAAC,cAAc,CAAC;AAEpD,QAAA,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE;YAC3B,OAAO,CAAC,KAAK,CAAC,CAAA,cAAA,EAAiB,WAAW,CAAA,CAAA,CAAG,EAAE,MAAM,CAAC;AACtD,YAAA,OAAO,KAAK;QACd;QAEA,IAAI,UAAU,GAAG,KAAK;AACtB,QAAA,IAAI,WAA+B;AAEnC,QAAA,IAAI,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE;AAChC,YAAA,WAAW,GAAG,0BAA0B,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,QAAS,CAAC;YACxF,IAAI,WAAW,IAAI,WAAW,KAAK,UAAU,CAAC,QAAQ,CAAC,OAAO,EAAE;AAC9D,gBAAA,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;gBACjF,UAAU,GAAG,IAAI;YACnB;QACF;QAEA,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,WAAW;AAC5D,QAAA,IAAI,QAAQ,EAAE,OAAO,EAAE;AACrB,YAAA,IAAI,UAAU,GAAG,wBAAwB,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,MAAO,CAAC;YAE5E,IAAI,UAAU,EAAE;AACd,gBAAA,IAAI,OAAO,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;oBAC5D,UAAU,GAAG,GAAG,OAAO,CAAC,UAAU,CAAA,EAAG,UAAU,EAAE;gBACnD;gBACA,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;gBACrE,UAAU,GAAG,IAAI;YACnB;iBAAO,IAAI,WAAW,IAAI,WAAW,KAAK,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE;AACtE,gBAAA,IAAI,UAAU,GAAG,QAAQ,CAAC,OAAO;AACjC,gBAAA,IAAI,OAAO,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;oBAC5D,UAAU,GAAG,GAAG,OAAO,CAAC,UAAU,CAAA,EAAG,UAAU,EAAE;oBACjD,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;oBACrE,UAAU,GAAG,IAAI;gBACnB;YACF;QACF;AAEA,QAAA,IAAI,UAAU,IAAI,cAAc,KAAK,eAAe,EAAE;YACpD,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,cAAc,EAAE,OAAO,CAAC;AACtD,YAAA,OAAO,CAAC,GAAG,CAAC,UAAU,WAAW,CAAA,CAAE,CAAC;AACpC,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,OAAO,KAAK;IACd;IAAE,OAAO,KAAK,EAAE;QACd,OAAO,CAAC,KAAK,CAAC,CAAA,SAAA,EAAY,WAAW,CAAA,CAAA,CAAG,EAAE,KAAK,CAAC;AAChD,QAAA,OAAO,KAAK;IACd;AACF;AAEA;AACA,eAAe,IAAI,GAAA;AACjB,IAAA,MAAM,UAAU,GAAG,SAAS,EAAE;IAC9B,MAAM,YAAY,GAAsB,EAAE,GAAG,aAAa,EAAE,GAAG,UAAU,EAAE;;AAG1E,IAAA,UAAkB,CAAC,SAAS,GAAG,YAAY,CAAC,SAAS;AACrD,IAAA,UAAkB,CAAC,SAAS,GAAG,YAAY,CAAC,SAAS;AACrD,IAAA,UAAkB,CAAC,OAAO,GAAG,YAAY,CAAC,OAAO;;AAGlD,IAAA,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;AAC1B,IAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,QAAS,CAAC;AAC3D,IAAA,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;AAC3B,QAAA,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,IAAG;YAC7B,UAAU,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC;AAC5C,QAAA,CAAC,CAAC;IACJ;AAEA,IAAA,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;AAEpC,IAAA,MAAM,QAAQ,GAAG;QACf,cAAc;QACd,aAAa;QACb,aAAa;QACb,cAAc;QACd,cAAc;KACf;AAED,IAAA,MAAM,QAAQ,GAAG,MAAMC,aAAI,CAAC,QAAQ,EAAE;AACpC,QAAA,GAAG,EAAE,IAAI;AACT,QAAA,QAAQ,EAAE,IAAI;AACd,QAAA,MAAM,EAAE;YACN,oBAAoB;YACpB,YAAY;YACZ,YAAY;YACZ,eAAe;AACf,YAAA,GAAG,YAAY,CAAC,QAAS,CAAC,GAAG,CAAC,OAAO,IAAI,CAAA,GAAA,EAAM,OAAO,KAAK,CAAC;AAC7D,SAAA;AACF,KAAA,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,CAAA,MAAA,EAAS,QAAQ,CAAC,MAAM,CAAA,UAAA,CAAY,CAAC;IAEjD,IAAI,cAAc,GAAG,CAAC;IACtB,IAAI,UAAU,GAAG,CAAC;AAElB,IAAA,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;AAElC,QAAA,IAAI;AACF,YAAA,IAAI,GAAG,KAAK,MAAM,EAAE;AAClB,gBAAA,IAAI,cAAc,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE;AAC1C,oBAAA,cAAc,EAAE;gBAClB;YACF;AAAO,iBAAA,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AACvD,gBAAA,IAAI,aAAa,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE;AACzC,oBAAA,cAAc,EAAE;gBAClB;YACF;QACF;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,UAAU,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,CAAA,SAAA,EAAY,QAAQ,CAAA,CAAA,CAAG,EAAE,KAAK,CAAC;QAC/C;IACF;AAEA,IAAA,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;AAC7B,IAAA,gBAAgB,CAAC,QAAQ,EAAE,UAAU,CAAC,eAAe,CAAC;AACtD,IAAA,OAAO,CAAC,GAAG,CAAC,UAAU,QAAQ,CAAA,CAAE,CAAC;AAEjC,IAAA,IAAI,YAAY,CAAC,QAAQ,EAAE;AACzB,QAAA,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,IAAG;YACvC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;AACvC,YAAA,MAAM,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC;YAC1B,MAAM,GAAG,GAAQ,EAAE;YACnB,MAAM,OAAO,GAAQ,EAAE;AAEvB,YAAA,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,GAAG,IAAG;AACpD,gBAAA,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE;oBACX,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC;gBACpB;qBAAO;oBACL,OAAO,CAAC,IAAI,CAAC;AACX,wBAAA,GAAG,EAAE,GAAG;AACR,wBAAA,KAAK,EAAE,UAAU,CAAC,eAAe,CAAC,GAAG;AACtC,qBAAA,CAAC;gBACJ;AACF,YAAA,CAAC,CAAC;AAEF,YAAA,OAAO,CAAC,OAAO,CAAC,CAAC,IAAS,KAAI;gBAC5B,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK;AAC5B,YAAA,CAAC,CAAC;AAEF,YAAA,gBAAgB,CAAC,EAAE,EAAE,GAAG,CAAC;AACzB,YAAA,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,CAAA,CAAE,CAAC;AAC7B,QAAA,CAAC,CAAC;IACJ;AAEA,IAAA,OAAO,CAAC,GAAG,CAAC,CAAA,SAAA,CAAW,CAAC;AACxB,IAAA,OAAO,CAAC,GAAG,CAAC,eAAe,cAAc,CAAA,CAAE,CAAC;AAC5C,IAAA,OAAO,CAAC,GAAG,CAAC,eAAe,UAAU,CAAA,CAAE,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,CAAA,eAAA,EAAkB,UAAU,CAAC,eAAe,CAAC,MAAM,CAAA,CAAE,CAAC;AAClE,IAAA,OAAO,CAAC,GAAG,CAAC,CAAA,wCAAA,CAA0C,CAAC;AACzD;AAEA,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,IAAG;AACnB,IAAA,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC;AAC/B,IAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AACjB,CAAC,CAAC;;"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-i18n-auto-plugin",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Vite plugin for automatically converting Chinese hardcoded strings to i18n function calls",
5
5
  "keywords": [
6
6
  "vite",
@@ -37,6 +37,9 @@
37
37
  "dist",
38
38
  "README.md"
39
39
  ],
40
+ "bin": {
41
+ "vue-i18n-auto": "./dist/cli.cjs.js"
42
+ },
40
43
  "scripts": {
41
44
  "build": "rollup -c",
42
45
  "dev": "rollup -c -w",
@@ -50,6 +53,7 @@
50
53
  "@babel/parser": "^7.28.6",
51
54
  "@babel/traverse": "^7.28.6",
52
55
  "@vue/compiler-sfc": "^3.5.0",
56
+ "fast-glob": "^3.3.3",
53
57
  "json5": "^2.2.3"
54
58
  },
55
59
  "devDependencies": {