@zwa73/dev-utils 1.0.53 → 1.0.55

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.
@@ -7,30 +7,35 @@ exports.CmdGenI18n = void 0;
7
7
  const utils_1 = require("@zwa73/utils");
8
8
  const ts_morph_1 = require("ts-morph");
9
9
  const UtilAst_1 = require("../UtilAst");
10
- const fs_1 = __importDefault(require("fs"));
11
10
  const pathe_1 = __importDefault(require("pathe"));
12
- async function procFile(p, filePath) {
11
+ function format(str) {
12
+ return str.replace(/\\(.)/g, '$1').replace(/%/g, '\\%');
13
+ }
14
+ async function procFile(p, filePath, funckey) {
13
15
  const date = new Date().toISOString();
14
- const content = await fs_1.default.promises.readFile(filePath, 'utf-8');
15
- const b = p.createSourceFile(pathe_1.default.relative(process.cwd(), filePath), content);
16
+ //const content = await fs.promises.readFile(filePath,'utf-8');
17
+ const b = p.addSourceFileAtPath(filePath);
18
+ //const b = p.createSourceFile(path.relative(process.cwd(),filePath),content,{overwrite:true});
16
19
  const ds = b.getDescendantsOfKind(ts_morph_1.SyntaxKind.TaggedTemplateExpression);
17
20
  const dats = [];
18
21
  for (const d of ds) {
22
+ if (!funckey.includes(d.getTag().getText()))
23
+ continue;
19
24
  const template = d.getTemplate();
20
25
  let result = '';
21
26
  let i = 0;
22
27
  UtilAst_1.UtilAst.withKind(template, {
23
- [ts_morph_1.SyntaxKind.NoSubstitutionTemplateLiteral]: (t) => result += t.getLiteralText(),
28
+ [ts_morph_1.SyntaxKind.NoSubstitutionTemplateLiteral]: (t) => result += format(t.getLiteralText()),
24
29
  [ts_morph_1.SyntaxKind.TemplateExpression]: (t) => {
25
30
  t.getChildren().forEach((c) => {
26
31
  UtilAst_1.UtilAst.withKind(c, {
27
- [ts_morph_1.SyntaxKind.TemplateHead]: (sc) => result += sc.getLiteralText(),
32
+ [ts_morph_1.SyntaxKind.TemplateHead]: (sc) => result += format(sc.getLiteralText()),
28
33
  [ts_morph_1.SyntaxKind.SyntaxList]: (sc) => {
29
34
  sc.getChildrenOfKind(ts_morph_1.SyntaxKind.TemplateSpan).forEach((span) => {
30
35
  span.getChildren().forEach((ssc) => {
31
36
  result += UtilAst_1.UtilAst.withKind(ssc, {
32
- [ts_morph_1.SyntaxKind.TemplateMiddle]: (sssc) => sssc.getLiteralText(),
33
- [ts_morph_1.SyntaxKind.TemplateTail]: (sssc) => sssc.getLiteralText(),
37
+ [ts_morph_1.SyntaxKind.TemplateMiddle]: (sssc) => format(sssc.getLiteralText()),
38
+ [ts_morph_1.SyntaxKind.TemplateTail]: (sssc) => format(sssc.getLiteralText()),
34
39
  }) ?? String(`%${i++}`);
35
40
  });
36
41
  });
@@ -51,12 +56,14 @@ async function procFile(p, filePath) {
51
56
  }
52
57
  return dats;
53
58
  }
54
- async function scanI18n(i18nDataDir, include, exclude) {
59
+ async function scanI18n(i18nDataDir, include, exclude, funckey) {
60
+ const fixedKey = typeof funckey == 'string' ? [funckey] : funckey;
55
61
  const filePaths = (await utils_1.UtilFT.fileSearchGlob(process.cwd(), include, { ingore: exclude }))
56
62
  .filter(p => ['.ts', '.tsx'].includes(pathe_1.default.parse(p).ext));
57
63
  const project = new ts_morph_1.Project();
58
64
  await utils_1.SI18n.init(i18nDataDir, '*');
59
- (await Promise.all(filePaths.map(p => procFile(project, p))))
65
+ //console.log(filePaths);
66
+ (await Promise.all(filePaths.map(p => procFile(project, p, fixedKey))))
60
67
  .flat().forEach(dat => utils_1.SI18n.addOriginalText(dat));
61
68
  await utils_1.SI18n.saveTable();
62
69
  }
@@ -65,10 +72,23 @@ const CmdGenI18n = (program) => program
65
72
  .command("Gen-I18n")
66
73
  .alias("geni18n")
67
74
  .description("根据文件行为树生成i18n数据")
68
- .option("-o, --output <path>", "输出的数据目录位置")
69
- .option("-i, --include <glob>", "包含的glob 默认 src/**/*.macro.ts", "src/**/*.macro.ts")
75
+ .option("-o, --output <path>", "输出的数据目录位置 默认 i18n", 'i18n')
76
+ .option("-i, --include <glob>", "包含的glob 默认 src/**/*.ts", "src/**/*.ts")
70
77
  .option("-g, --exclude <glob>", "忽略的glob")
78
+ .option("-f, --funckey <string|string[]>", "扫描的目标函数名, 默认 t", (i) => {
79
+ const v = (0, utils_1.ivk)(() => {
80
+ try {
81
+ return JSON.parse(i);
82
+ }
83
+ catch (e) {
84
+ return undefined;
85
+ }
86
+ });
87
+ if (Array.isArray(v))
88
+ return v;
89
+ return i;
90
+ }, 't')
71
91
  .action(async (opt) => {
72
- await scanI18n(opt.output, opt.include, opt.exclude);
92
+ await scanI18n(opt.output, opt.include, opt.exclude, opt.funckey);
73
93
  });
74
94
  exports.CmdGenI18n = CmdGenI18n;
@@ -10,13 +10,15 @@ const CmdGenSchema = (program) => program
10
10
  .option("-i, --include <glob>", "包含的glob 默认 src/**/*.schema.ts", "src/**/*.schema.ts")
11
11
  .option("-g, --exclude <glob>", "忽略的glob")
12
12
  .option("-p, --project <path>", "tsconfig路径 默认tsconfig.json", "tsconfig.json")
13
- .option("-o, --out-dir <dir>", "schema输出路径目录 默认 ./schema/")
13
+ .option("-o, --out <dir>", "schema输出路径目录 默认 ./schema/")
14
+ .option("-t, --type <string>", "若传入则仅输出 type 对应的类型 此时将直接输出至outDir/type.json, 且不会展开")
14
15
  .action(async (opt) => {
15
16
  await UtilDevTool_1.UtilDT.generateSchema(process.cwd(), {
16
17
  include: opt.include,
17
18
  exclude: opt.exclude,
18
19
  project: opt.project,
19
20
  outDir: opt.outDir,
21
+ typeName: opt.type
20
22
  });
21
23
  });
22
24
  exports.CmdGenSchema = CmdGenSchema;
@@ -18,6 +18,8 @@ export declare namespace UtilDT {
18
18
  coverDefine: JObject;
19
19
  /**schema输出路径目录 如 ./schema/ */
20
20
  outDir: string;
21
+ /**若传入则仅输出 typeName 对应的类型 此时将直接输出至outDir/typeName.json, 且不会展开 */
22
+ typeName?: string;
21
23
  }> & BuildMatchOpt;
22
24
  /**生成匹配的文件的所有type的schema
23
25
  * @async
@@ -28,6 +30,7 @@ export declare namespace UtilDT {
28
30
  * @param opt.coverDefine - 将会覆盖 definitions 对应内容的表
29
31
  * @param opt.project - tsconfig路径
30
32
  * @param opt.outDir - schema输出路径目录 默认 ./schema/
33
+ * @param opt.typeName - 若传入则仅输出 typeName 对应的类型 此时将直接输出至outDir/typeName.json, 且不会展开
31
34
  */
32
35
  export function generateSchema(dir: string, opt?: BuildSchemaOpt): Promise<void>;
33
36
  /**运行所有匹配的的js/ts文件
@@ -42,6 +42,7 @@ var UtilDT;
42
42
  * @param opt.coverDefine - 将会覆盖 definitions 对应内容的表
43
43
  * @param opt.project - tsconfig路径
44
44
  * @param opt.outDir - schema输出路径目录 默认 ./schema/
45
+ * @param opt.typeName - 若传入则仅输出 typeName 对应的类型 此时将直接输出至outDir/typeName.json, 且不会展开
45
46
  */
46
47
  async function generateSchema(dir, opt) {
47
48
  //生成
@@ -49,6 +50,7 @@ var UtilDT;
49
50
  required: true,
50
51
  aliasRef: true,
51
52
  tsNodeRegister: true,
53
+ ignoreErrors: true,
52
54
  };
53
55
  const compilerOptions = {
54
56
  strictNullChecks: true,
@@ -57,21 +59,30 @@ var UtilDT;
57
59
  Object.assign(compilerOptions, (await utils_1.UtilFT.loadJSONFile(opt.project)).compilerOptions);
58
60
  const files = await utils_1.UtilFT.fileSearchGlob(dir, opt?.include ?? "**/*.schema.ts", { ingore: opt?.exclude });
59
61
  const program = TJS.getProgramFromFiles(files, compilerOptions);
60
- const schema = TJS.generateSchema(program, "*", settings);
62
+ const schema = TJS.generateSchema(program, opt?.typeName ?? "*", settings);
61
63
  const outDir = opt?.outDir ?? pathe_1.default.join(process.cwd(), 'schema');
62
- const schemasPath = pathe_1.default.join(outDir, 'schemas.json');
63
- //进行预处理并展开
64
- await expandSchema(schemasPath, schema, opt?.coverDefine ?? {});
64
+ const schemasPath = opt?.typeName != undefined
65
+ ? pathe_1.default.join(outDir, `${opt.typeName}.json`)
66
+ : pathe_1.default.join(outDir, 'schemas.json');
67
+ //预处理
68
+ const proced = procSchema(schema, opt?.coverDefine ?? {});
69
+ await Promise.all([
70
+ utils_1.UtilFT.writeJSONFile(schemasPath, schema),
71
+ //全范围类型则展开
72
+ opt?.typeName != undefined ? undefined : expandSchema(proced, schemasPath),
73
+ ]);
65
74
  }
66
75
  UtilDT.generateSchema = generateSchema;
67
- /**展开schema以供使用 */
68
- async function expandSchema(schemasPath, schema, coverDefine) {
76
+ function procSchema(schema, coverDefine) {
69
77
  //覆盖
70
78
  coverObj(schema["definitions"], coverDefine);
71
79
  //替换SchemaString标识符
72
80
  schema = JSON.parse(JSON.stringify(schema).replace(/\^\.\*SchemaString\$/g, '^.*$'));
81
+ return schema;
82
+ }
83
+ /**展开schema以供使用 */
84
+ async function expandSchema(schema, schemasPath) {
73
85
  const plist = [];
74
- plist.push(utils_1.UtilFT.writeJSONFile(schemasPath, schema));
75
86
  const definitions = schema["definitions"];
76
87
  //展开定义
77
88
  for (const typeName in definitions) {
@@ -0,0 +1,23 @@
1
+ {
2
+ "base_lang": "zh-CN",
3
+ "texts": [
4
+ {
5
+ "original": "你好?%0,吗?",
6
+ "scan_time": "2024-07-22T04:08:33.552Z",
7
+ "position": "F:/Sosarciel/SosarcielCore/NodeJs/dev-utils/jest/UtilI18n/test.ts:6:13",
8
+ "source": "Ast"
9
+ },
10
+ {
11
+ "original": "abcdefg %0rst",
12
+ "scan_time": "2024-07-22T04:08:33.552Z",
13
+ "position": "F:/Sosarciel/SosarcielCore/NodeJs/dev-utils/jest/UtilI18n/test.ts:7:13",
14
+ "source": "Ast"
15
+ },
16
+ {
17
+ "original": "higklmn%0",
18
+ "scan_time": "2024-07-22T04:08:33.552Z",
19
+ "position": "F:/Sosarciel/SosarcielCore/NodeJs/dev-utils/jest/UtilI18n/test.ts:7:25",
20
+ "source": "Ast"
21
+ }
22
+ ]
23
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "base_lang": "zh-CN",
3
+ "modify_time": "2024-07-22T04:08:33.570Z",
4
+ "target_lang": "en",
5
+ "translate_table": {
6
+ "你好?%0,吗?": "hello? %0 \\%0",
7
+ "abcdefg %0rst": "ABCDEFG %0RST",
8
+ "higklmn%0": "HIJKLMN%0"
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "base_lang": "zh-CN",
3
+ "modify_time": "2024-07-22T04:08:33.570Z",
4
+ "target_lang": "template",
5
+ "translate_table": {
6
+ "你好?%0,吗?": null,
7
+ "abcdefg %0rst": null,
8
+ "higklmn%0": null
9
+ }
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zwa73/dev-utils",
3
- "version": "1.0.53",
3
+ "version": "1.0.55",
4
4
  "description": "编译与调试工具",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -16,7 +16,7 @@
16
16
  "author": "zwa73",
17
17
  "license": "ISC",
18
18
  "dependencies": {
19
- "@zwa73/utils": "^1.0.143",
19
+ "@zwa73/utils": "^1.0.144",
20
20
  "commander": "^11.1.0",
21
21
  "pathe": "^1.1.2",
22
22
  "ts-morph": "^23.0.0",
@@ -1,32 +1,37 @@
1
1
  import { Command } from "commander";
2
- import { I18nTextData, SI18n, UtilFT } from "@zwa73/utils";
3
- import { Project,SourceFile,SyntaxKind } from 'ts-morph';
2
+ import { AnyFunc, I18nTextData, SI18n, UtilFT, ivk } from "@zwa73/utils";
3
+ import { Project,SyntaxKind } from 'ts-morph';
4
4
  import { UtilAst } from "@src/UtilAst";
5
- import fs from 'fs';
6
5
  import path from 'pathe';
7
6
 
8
- async function procFile(p:Project,filePath:string){
7
+ function format(str:string){
8
+ return str.replace(/\\(.)/g,'$1').replace(/%/g,'\\%');
9
+ }
10
+
11
+ async function procFile(p:Project,filePath:string,funckey:string[]){
9
12
  const date = new Date().toISOString();
10
- const content = await fs.promises.readFile(filePath,'utf-8');
11
- const b = p.createSourceFile(path.relative(process.cwd(),filePath),content);
13
+ //const content = await fs.promises.readFile(filePath,'utf-8');
14
+ const b = p.addSourceFileAtPath(filePath);
15
+ //const b = p.createSourceFile(path.relative(process.cwd(),filePath),content,{overwrite:true});
12
16
  const ds = b.getDescendantsOfKind(SyntaxKind.TaggedTemplateExpression);
13
17
  const dats:I18nTextData[] = [];
14
18
  for(const d of ds){
19
+ if(!funckey.includes(d.getTag().getText())) continue;
15
20
  const template = d.getTemplate();
16
21
  let result = '';
17
22
  let i=0;
18
23
  UtilAst.withKind(template,{
19
- [SyntaxKind.NoSubstitutionTemplateLiteral]:(t)=>result+=t.getLiteralText(),
24
+ [SyntaxKind.NoSubstitutionTemplateLiteral]:(t)=>result+=format(t.getLiteralText()),
20
25
  [SyntaxKind.TemplateExpression]:(t)=>{
21
26
  t.getChildren().forEach((c)=>{
22
27
  UtilAst.withKind(c,{
23
- [SyntaxKind.TemplateHead]:(sc)=>result += sc.getLiteralText(),
28
+ [SyntaxKind.TemplateHead]:(sc)=>result += format(sc.getLiteralText()),
24
29
  [SyntaxKind.SyntaxList]:(sc)=>{
25
30
  sc.getChildrenOfKind(SyntaxKind.TemplateSpan).forEach((span)=>{
26
31
  span.getChildren().forEach((ssc)=>{
27
32
  result += UtilAst.withKind(ssc,{
28
- [SyntaxKind.TemplateMiddle]:(sssc)=>sssc.getLiteralText(),
29
- [SyntaxKind.TemplateTail] :(sssc)=>sssc.getLiteralText(),
33
+ [SyntaxKind.TemplateMiddle]:(sssc)=>format(sssc.getLiteralText()),
34
+ [SyntaxKind.TemplateTail] :(sssc)=>format(sssc.getLiteralText()),
30
35
  })??String(`%${i++}`);
31
36
  })
32
37
  })
@@ -48,12 +53,14 @@ async function procFile(p:Project,filePath:string){
48
53
  return dats;
49
54
  }
50
55
 
51
- async function scanI18n(i18nDataDir:string,include:string,exclude:string){
56
+ async function scanI18n(i18nDataDir:string,include:string,exclude:string,funckey:string[]|string){
57
+ const fixedKey = typeof funckey == 'string' ? [funckey] : funckey;
52
58
  const filePaths = (await UtilFT.fileSearchGlob(process.cwd(),include,{ingore:exclude}))
53
59
  .filter(p=>['.ts','.tsx'].includes(path.parse(p).ext));
54
60
  const project = new Project();
55
61
  await SI18n.init(i18nDataDir,'*');
56
- (await Promise.all(filePaths.map(p=>procFile(project,p))))
62
+ //console.log(filePaths);
63
+ (await Promise.all(filePaths.map(p=>procFile(project,p,fixedKey))))
57
64
  .flat().forEach(dat=>SI18n.addOriginalText(dat));
58
65
  await SI18n.saveTable();
59
66
  }
@@ -63,13 +70,25 @@ export const CmdGenI18n = (program:Command) => program
63
70
  .command("Gen-I18n")
64
71
  .alias("geni18n")
65
72
  .description("根据文件行为树生成i18n数据")
66
- .option("-o, --output <path>" , "输出的数据目录位置")
67
- .option("-i, --include <glob>", "包含的glob 默认 src/**/*.macro.ts","src/**/*.macro.ts")
73
+ .option("-o, --output <path>" , "输出的数据目录位置 默认 i18n",'i18n')
74
+ .option("-i, --include <glob>", "包含的glob 默认 src/**/*.ts","src/**/*.ts")
68
75
  .option("-g, --exclude <glob>", "忽略的glob")
76
+ .option("-f, --funckey <string|string[]>", "扫描的目标函数名, 默认 t",(i:string)=>{
77
+ const v = ivk(()=>{
78
+ try{
79
+ return JSON.parse(i);
80
+ } catch(e){
81
+ return undefined;
82
+ }
83
+ })
84
+ if(Array.isArray(v)) return v;
85
+ return i;
86
+ },'t')
69
87
  .action(async (opt) => {
70
88
  await scanI18n(
71
- opt.output,
89
+ opt.output ,
72
90
  opt.include,
73
91
  opt.exclude,
92
+ opt.funckey,
74
93
  );
75
94
  });
@@ -9,12 +9,14 @@ export const CmdGenSchema = (program:Command) => program
9
9
  .option("-i, --include <glob>", "包含的glob 默认 src/**/*.schema.ts","src/**/*.schema.ts")
10
10
  .option("-g, --exclude <glob>", "忽略的glob")
11
11
  .option("-p, --project <path>", "tsconfig路径 默认tsconfig.json","tsconfig.json")
12
- .option("-o, --out-dir <dir>" , "schema输出路径目录 默认 ./schema/")
12
+ .option("-o, --out <dir>", "schema输出路径目录 默认 ./schema/")
13
+ .option("-t, --type <string>", "若传入则仅输出 type 对应的类型 此时将直接输出至outDir/type.json, 且不会展开")
13
14
  .action(async (opt) => {
14
15
  await UtilDT.generateSchema(process.cwd(), {
15
- include: opt.include,
16
- exclude: opt.exclude,
17
- project: opt.project,
18
- outDir: opt.outDir,
16
+ include : opt.include,
17
+ exclude : opt.exclude,
18
+ project : opt.project,
19
+ outDir : opt.outDir,
20
+ typeName: opt.type
19
21
  });
20
22
  });
@@ -25,6 +25,8 @@ type BuildSchemaOpt = Partial<{
25
25
  coverDefine:JObject;
26
26
  /**schema输出路径目录 如 ./schema/ */
27
27
  outDir:string;
28
+ /**若传入则仅输出 typeName 对应的类型 此时将直接输出至outDir/typeName.json, 且不会展开 */
29
+ typeName?:string;
28
30
  }>&BuildMatchOpt;
29
31
 
30
32
 
@@ -38,6 +40,7 @@ type BuildSchemaOpt = Partial<{
38
40
  * @param opt.coverDefine - 将会覆盖 definitions 对应内容的表
39
41
  * @param opt.project - tsconfig路径
40
42
  * @param opt.outDir - schema输出路径目录 默认 ./schema/
43
+ * @param opt.typeName - 若传入则仅输出 typeName 对应的类型 此时将直接输出至outDir/typeName.json, 且不会展开
41
44
  */
42
45
  export async function generateSchema(dir:string,opt?:BuildSchemaOpt){
43
46
  //生成
@@ -45,6 +48,7 @@ export async function generateSchema(dir:string,opt?:BuildSchemaOpt){
45
48
  required: true,
46
49
  aliasRef:true,
47
50
  tsNodeRegister:true,
51
+ ignoreErrors:true,
48
52
  };
49
53
  const compilerOptions: TJS.CompilerOptions = {
50
54
  strictNullChecks: true,
@@ -56,21 +60,29 @@ export async function generateSchema(dir:string,opt?:BuildSchemaOpt){
56
60
  files,
57
61
  compilerOptions,
58
62
  );
59
- const schema = TJS.generateSchema(program, "*", settings) as JObject;
63
+ const schema = TJS.generateSchema(program, opt?.typeName??"*", settings) as JObject;
60
64
  const outDir = opt?.outDir ?? path.join(process.cwd(),'schema');
61
- const schemasPath = path.join(outDir,'schemas.json');
62
- //进行预处理并展开
63
- await expandSchema(schemasPath,schema,opt?.coverDefine??{});
65
+ const schemasPath = opt?.typeName !=undefined
66
+ ? path.join(outDir,`${opt.typeName}.json`)
67
+ : path.join(outDir,'schemas.json');
68
+ //预处理
69
+ const proced = procSchema(schema,opt?.coverDefine??{});
70
+ await Promise.all([
71
+ UtilFT.writeJSONFile(schemasPath,schema),
72
+ //全范围类型则展开
73
+ opt?.typeName !=undefined ? undefined : expandSchema(proced,schemasPath),
74
+ ]);
64
75
  }
65
- /**展开schema以供使用 */
66
- async function expandSchema(schemasPath:string,schema:JObject,coverDefine:JObject){
76
+ function procSchema(schema:JObject,coverDefine:JObject){
67
77
  //覆盖
68
78
  coverObj(schema["definitions"] as JObject,coverDefine);
69
79
  //替换SchemaString标识符
70
80
  schema = JSON.parse(JSON.stringify(schema).replace(/\^\.\*SchemaString\$/g,'^.*$'));
81
+ return schema;
82
+ }
83
+ /**展开schema以供使用 */
84
+ async function expandSchema(schema:JObject,schemasPath:string){
71
85
  const plist:Promise<void>[] = [];
72
- plist.push(UtilFT.writeJSONFile(schemasPath,schema));
73
-
74
86
  const definitions = schema["definitions"] as Record<string,JObject>;
75
87
  //展开定义
76
88
  for(const typeName in definitions){