@zwa73/dev-utils 1.0.52 → 1.0.53

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.
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ /**生成i18n */
3
+ export declare const CmdGenI18n: (program: Command) => Command;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CmdGenI18n = void 0;
7
+ const utils_1 = require("@zwa73/utils");
8
+ const ts_morph_1 = require("ts-morph");
9
+ const UtilAst_1 = require("../UtilAst");
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const pathe_1 = __importDefault(require("pathe"));
12
+ async function procFile(p, filePath) {
13
+ 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 ds = b.getDescendantsOfKind(ts_morph_1.SyntaxKind.TaggedTemplateExpression);
17
+ const dats = [];
18
+ for (const d of ds) {
19
+ const template = d.getTemplate();
20
+ let result = '';
21
+ let i = 0;
22
+ UtilAst_1.UtilAst.withKind(template, {
23
+ [ts_morph_1.SyntaxKind.NoSubstitutionTemplateLiteral]: (t) => result += t.getLiteralText(),
24
+ [ts_morph_1.SyntaxKind.TemplateExpression]: (t) => {
25
+ t.getChildren().forEach((c) => {
26
+ UtilAst_1.UtilAst.withKind(c, {
27
+ [ts_morph_1.SyntaxKind.TemplateHead]: (sc) => result += sc.getLiteralText(),
28
+ [ts_morph_1.SyntaxKind.SyntaxList]: (sc) => {
29
+ sc.getChildrenOfKind(ts_morph_1.SyntaxKind.TemplateSpan).forEach((span) => {
30
+ span.getChildren().forEach((ssc) => {
31
+ result += UtilAst_1.UtilAst.withKind(ssc, {
32
+ [ts_morph_1.SyntaxKind.TemplateMiddle]: (sssc) => sssc.getLiteralText(),
33
+ [ts_morph_1.SyntaxKind.TemplateTail]: (sssc) => sssc.getLiteralText(),
34
+ }) ?? String(`%${i++}`);
35
+ });
36
+ });
37
+ },
38
+ });
39
+ });
40
+ }
41
+ });
42
+ const pos = b.getLineAndColumnAtPos(d.getStart());
43
+ const dat = {
44
+ original: result,
45
+ scan_time: date,
46
+ position: `${filePath}:${pos.line}:${pos.column}`,
47
+ lang_table: {},
48
+ source: "Ast"
49
+ };
50
+ dats.push(dat);
51
+ }
52
+ return dats;
53
+ }
54
+ async function scanI18n(i18nDataDir, include, exclude) {
55
+ const filePaths = (await utils_1.UtilFT.fileSearchGlob(process.cwd(), include, { ingore: exclude }))
56
+ .filter(p => ['.ts', '.tsx'].includes(pathe_1.default.parse(p).ext));
57
+ const project = new ts_morph_1.Project();
58
+ await utils_1.SI18n.init(i18nDataDir, '*');
59
+ (await Promise.all(filePaths.map(p => procFile(project, p))))
60
+ .flat().forEach(dat => utils_1.SI18n.addOriginalText(dat));
61
+ await utils_1.SI18n.saveTable();
62
+ }
63
+ /**生成i18n */
64
+ const CmdGenI18n = (program) => program
65
+ .command("Gen-I18n")
66
+ .alias("geni18n")
67
+ .description("根据文件行为树生成i18n数据")
68
+ .option("-o, --output <path>", "输出的数据目录位置")
69
+ .option("-i, --include <glob>", "包含的glob 默认 src/**/*.macro.ts", "src/**/*.macro.ts")
70
+ .option("-g, --exclude <glob>", "忽略的glob")
71
+ .action(async (opt) => {
72
+ await scanI18n(opt.output, opt.include, opt.exclude);
73
+ });
74
+ exports.CmdGenI18n = CmdGenI18n;
@@ -10,11 +10,11 @@ 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, --outDir <dir>", "schema输出路径目录 默认 ./schema/")
13
+ .option("-o, --out-dir <dir>", "schema输出路径目录 默认 ./schema/")
14
14
  .action(async (opt) => {
15
15
  await UtilDevTool_1.UtilDT.generateSchema(process.cwd(), {
16
16
  include: opt.include,
17
- exclude: opt.ignore,
17
+ exclude: opt.exclude,
18
18
  project: opt.project,
19
19
  outDir: opt.outDir,
20
20
  });
@@ -9,6 +9,7 @@ const MapPath_1 = require("./MapPath");
9
9
  const ScanDups_1 = require("./ScanDups");
10
10
  const GenSchema_1 = require("./GenSchema");
11
11
  const ExpandMacro_1 = require("./ExpandMacro");
12
+ const GenI18n_1 = require("./GenI18n");
12
13
  async function cliRoute() {
13
14
  (0, Init_1.CmdInit)(commander_1.program);
14
15
  (0, Node_1.CmdNode)(commander_1.program);
@@ -17,6 +18,7 @@ async function cliRoute() {
17
18
  (0, ScanDups_1.CmdScanDups)(commander_1.program);
18
19
  (0, GenSchema_1.CmdGenSchema)(commander_1.program);
19
20
  (0, ExpandMacro_1.CmdExpandMacro)(commander_1.program);
21
+ (0, GenI18n_1.CmdGenI18n)(commander_1.program);
20
22
  commander_1.program.parse(process.argv);
21
23
  }
22
24
  exports.cliRoute = cliRoute;
@@ -0,0 +1,13 @@
1
+ import { AnyFunc } from "@zwa73/utils";
2
+ import { SyntaxKind, KindToNodeMappings, Node } from "ts-morph";
3
+ export declare namespace UtilAst {
4
+ /**匹配Node的类型进行处理 无法匹配时返回undefined
5
+ * @param node - ast节点
6
+ * @param funcMap - 处理函数映射表
7
+ */
8
+ function withKind<T extends Partial<{
9
+ [P in SyntaxKind]: ((n: KindToNodeMappings[P]) => unknown);
10
+ }>>(node: Node, funcMap: T): {
11
+ [P in keyof T]: T[P] extends AnyFunc ? ReturnType<T[P]> : never;
12
+ }[keyof T] | undefined;
13
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UtilAst = void 0;
4
+ var UtilAst;
5
+ (function (UtilAst) {
6
+ /**匹配Node的类型进行处理 无法匹配时返回undefined
7
+ * @param node - ast节点
8
+ * @param funcMap - 处理函数映射表
9
+ */
10
+ function withKind(node, funcMap) {
11
+ const kind = node.getKind();
12
+ const func = funcMap[kind];
13
+ if (func)
14
+ return func(node);
15
+ return undefined;
16
+ }
17
+ UtilAst.withKind = withKind;
18
+ })(UtilAst || (exports.UtilAst = UtilAst = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zwa73/dev-utils",
3
- "version": "1.0.52",
3
+ "version": "1.0.53",
4
4
  "description": "编译与调试工具",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -16,9 +16,10 @@
16
16
  "author": "zwa73",
17
17
  "license": "ISC",
18
18
  "dependencies": {
19
- "@zwa73/utils": "^1.0.128",
19
+ "@zwa73/utils": "^1.0.143",
20
20
  "commander": "^11.1.0",
21
21
  "pathe": "^1.1.2",
22
+ "ts-morph": "^23.0.0",
22
23
  "ts-node": "^10.9.2",
23
24
  "tsconfig-paths": "^4.2.0",
24
25
  "typescript-json-schema": "^0.63.0"
@@ -0,0 +1,75 @@
1
+ import { Command } from "commander";
2
+ import { I18nTextData, SI18n, UtilFT } from "@zwa73/utils";
3
+ import { Project,SourceFile,SyntaxKind } from 'ts-morph';
4
+ import { UtilAst } from "@src/UtilAst";
5
+ import fs from 'fs';
6
+ import path from 'pathe';
7
+
8
+ async function procFile(p:Project,filePath:string){
9
+ 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);
12
+ const ds = b.getDescendantsOfKind(SyntaxKind.TaggedTemplateExpression);
13
+ const dats:I18nTextData[] = [];
14
+ for(const d of ds){
15
+ const template = d.getTemplate();
16
+ let result = '';
17
+ let i=0;
18
+ UtilAst.withKind(template,{
19
+ [SyntaxKind.NoSubstitutionTemplateLiteral]:(t)=>result+=t.getLiteralText(),
20
+ [SyntaxKind.TemplateExpression]:(t)=>{
21
+ t.getChildren().forEach((c)=>{
22
+ UtilAst.withKind(c,{
23
+ [SyntaxKind.TemplateHead]:(sc)=>result += sc.getLiteralText(),
24
+ [SyntaxKind.SyntaxList]:(sc)=>{
25
+ sc.getChildrenOfKind(SyntaxKind.TemplateSpan).forEach((span)=>{
26
+ span.getChildren().forEach((ssc)=>{
27
+ result += UtilAst.withKind(ssc,{
28
+ [SyntaxKind.TemplateMiddle]:(sssc)=>sssc.getLiteralText(),
29
+ [SyntaxKind.TemplateTail] :(sssc)=>sssc.getLiteralText(),
30
+ })??String(`%${i++}`);
31
+ })
32
+ })
33
+ },
34
+ });
35
+ });
36
+ }
37
+ });
38
+ const pos = b.getLineAndColumnAtPos(d.getStart());
39
+ const dat:I18nTextData={
40
+ original:result,
41
+ scan_time:date,
42
+ position: `${filePath}:${pos.line}:${pos.column}`,
43
+ lang_table:{},
44
+ source:"Ast"
45
+ }
46
+ dats.push(dat);
47
+ }
48
+ return dats;
49
+ }
50
+
51
+ async function scanI18n(i18nDataDir:string,include:string,exclude:string){
52
+ const filePaths = (await UtilFT.fileSearchGlob(process.cwd(),include,{ingore:exclude}))
53
+ .filter(p=>['.ts','.tsx'].includes(path.parse(p).ext));
54
+ const project = new Project();
55
+ await SI18n.init(i18nDataDir,'*');
56
+ (await Promise.all(filePaths.map(p=>procFile(project,p))))
57
+ .flat().forEach(dat=>SI18n.addOriginalText(dat));
58
+ await SI18n.saveTable();
59
+ }
60
+
61
+ /**生成i18n */
62
+ export const CmdGenI18n = (program:Command) => program
63
+ .command("Gen-I18n")
64
+ .alias("geni18n")
65
+ .description("根据文件行为树生成i18n数据")
66
+ .option("-o, --output <path>" , "输出的数据目录位置")
67
+ .option("-i, --include <glob>", "包含的glob 默认 src/**/*.macro.ts","src/**/*.macro.ts")
68
+ .option("-g, --exclude <glob>", "忽略的glob")
69
+ .action(async (opt) => {
70
+ await scanI18n(
71
+ opt.output,
72
+ opt.include,
73
+ opt.exclude,
74
+ );
75
+ });
@@ -9,11 +9,11 @@ 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, --outDir <dir>", "schema输出路径目录 默认 ./schema/")
12
+ .option("-o, --out-dir <dir>" , "schema输出路径目录 默认 ./schema/")
13
13
  .action(async (opt) => {
14
14
  await UtilDT.generateSchema(process.cwd(), {
15
15
  include: opt.include,
16
- exclude: opt.ignore,
16
+ exclude: opt.exclude,
17
17
  project: opt.project,
18
18
  outDir: opt.outDir,
19
19
  });
@@ -7,6 +7,7 @@ import { CmdMapPath } from './MapPath';
7
7
  import { CmdScanDups } from './ScanDups';
8
8
  import { CmdGenSchema } from './GenSchema';
9
9
  import { CmdExpandMacro } from './ExpandMacro';
10
+ import { CmdGenI18n } from './GenI18n';
10
11
 
11
12
  export async function cliRoute(){
12
13
  CmdInit(program);
@@ -16,5 +17,6 @@ export async function cliRoute(){
16
17
  CmdScanDups(program);
17
18
  CmdGenSchema(program);
18
19
  CmdExpandMacro(program);
20
+ CmdGenI18n(program);
19
21
  program.parse(process.argv);
20
22
  }
package/src/UtilAst.ts ADDED
@@ -0,0 +1,25 @@
1
+ import { AnyFunc,I18nTextData } from "@zwa73/utils";
2
+ import { SyntaxKind , KindToNodeMappings, Node} from "ts-morph";
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+ export namespace UtilAst{
11
+ /**匹配Node的类型进行处理 无法匹配时返回undefined
12
+ * @param node - ast节点
13
+ * @param funcMap - 处理函数映射表
14
+ */
15
+ export function withKind<T extends Partial<{
16
+ [P in SyntaxKind]:((n:KindToNodeMappings[P])=>unknown)
17
+ }>>(node:Node,funcMap:T):{
18
+ [P in keyof T]:T[P] extends AnyFunc ? ReturnType<T[P]> : never
19
+ }[keyof T]|undefined{
20
+ const kind = node.getKind();
21
+ const func = funcMap[kind] as any;
22
+ if(func) return func(node);
23
+ return undefined;
24
+ }
25
+ }