@zwa73/dev-utils 1.0.37 → 1.0.39

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 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //UtilMacro.exportComment('src/**/*.ts');
@@ -1,2 +1,2 @@
1
1
  import { UtilDT } from "./UtilDevTool";
2
- export declare const regionMacro: typeof UtilDT.regionMacro;
2
+ export declare const regionMacro: typeof UtilDT.regionMacro, fileMacro: typeof UtilDT.fileMacro, commentMacro: typeof UtilDT.commentMacro;
package/dist/QuickFunc.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.regionMacro = void 0;
3
+ exports.commentMacro = exports.fileMacro = exports.regionMacro = void 0;
4
4
  const UtilDevTool_1 = require("./UtilDevTool");
5
- exports.regionMacro = UtilDevTool_1.UtilDT.regionMacro;
5
+ exports.regionMacro = UtilDevTool_1.UtilDT.regionMacro, exports.fileMacro = UtilDevTool_1.UtilDT.fileMacro, exports.commentMacro = UtilDevTool_1.UtilDT.commentMacro;
@@ -47,16 +47,45 @@ export declare namespace UtilDT {
47
47
  */
48
48
  export function batchNode(filepath: string | string[], opt?: BatchNodeOpt): Promise<void>;
49
49
  /**宏的可选参数 */
50
- type MacroOpt = {
50
+ type MacroOpt = Partial<{
51
51
  /**宏展开的目标文件 */
52
- targetPath: string;
52
+ filePath: string[] | string;
53
+ /**使用glob匹配而非文件路径 */
54
+ glob: boolean;
55
+ }>;
56
+ /**codeText的参数 */
57
+ type CodeTextOpt = {
58
+ /**匹配的region/comment id */
59
+ matchId: string;
60
+ /**展开宏的目标文件 */
61
+ filePath: string;
62
+ /**展开宏区域的原文本 */
63
+ text: string;
64
+ /**缩进 会自动应用 */
65
+ inent: string;
53
66
  };
54
67
  /**将codeText写入对应region
55
- * @param regionId - 区域id
68
+ * @param regionId - 区域id \`//#region ${id}\`
56
69
  * @param codeText - 文本
57
70
  * @param opt - 可选参数
58
- * @param opt.targetPath - 目标文件 默认为去除".macro"的同名文件
71
+ * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
72
+ * @param opt.glob - 使用glob匹配而非文件路径
73
+ */
74
+ export function regionMacro(regionId: string | RegExp, codeText: string | ((opt: CodeTextOpt) => string | Promise<string>), opt?: MacroOpt): Promise<void>;
75
+ /**将codeText写入对应注释下
76
+ * @param commentId - 注释id \`// ${id}\`
77
+ * @param codeText - 文本
78
+ * @param opt - 可选参数
79
+ * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
80
+ * @param opt.glob - 使用glob匹配而非文件路径
81
+ */
82
+ export function commentMacro(commentId: string | RegExp, codeText: string | ((opt: CodeTextOpt) => string | Promise<string>), opt?: MacroOpt): Promise<void>;
83
+ /**将codeText写入对应文件 不存在则创建
84
+ * @param codeText - 文本
85
+ * @param opt - 可选参数
86
+ * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
87
+ * @param opt.glob - 使用glob匹配而非文件路径
59
88
  */
60
- export function regionMacro(regionId: string, codeText: string | (() => string | Promise<string>), opt?: MacroOpt): Promise<void>;
89
+ export function fileMacro(codeText: string | ((opt: CodeTextOpt) => string | Promise<string>), opt?: MacroOpt): Promise<void>;
61
90
  export {};
62
91
  }
@@ -126,49 +126,165 @@ var UtilDT;
126
126
  // 将所有的相对路径转换为绝对路径
127
127
  const absolutePaths = filepath.map(fp => path.resolve(process.cwd(), fp).replaceAll("\\", "/"));
128
128
  // 创建一个字符串,其中包含所有文件的 require 语句
129
- const requires = absolutePaths.map(fp => `require('${fp}');`).join('\n');
129
+ const requires = absolutePaths.map(fp => `require('${fp}')`).join(';');
130
130
  // 创建并执行 ts-node 命令
131
131
  const cmd = `ts-node -r tsconfig-paths/register -e "${requires}" ${opt?.project ? `-P "${opt.project}"` : ""}`;
132
132
  await utils_1.UtilFunc.exec(cmd, { outlvl: 'info', errlvl: 'warn' });
133
133
  }
134
134
  UtilDT.batchNode = batchNode;
135
+ //#region macro工具
136
+ const parseMacroPaths = (opt) => {
137
+ const loc = utils_1.UtilFunc.getFuncLoc(3);
138
+ if (!loc && !opt?.filePath)
139
+ (0, utils_1.throwError)(`parseMacroPaths 未能找到函数位置`);
140
+ const basePath = loc?.filePath;
141
+ return opt?.filePath
142
+ ? opt.glob
143
+ ? utils_1.UtilFT.fileSearchGlob(process.cwd(), opt.filePath, { normalize: "posix" })
144
+ : typeof opt?.filePath === "string"
145
+ ? [opt?.filePath.replaceAll('\\', '/')]
146
+ : opt?.filePath.map((filepath) => filepath.replaceAll('\\', '/'))
147
+ : [basePath.replace(/(.+)\.macro\.(js|ts|cjs|mjs)$/, "$1.$2").replaceAll('\\', '/')];
148
+ };
149
+ const readFile = async (basePath) => (await fs.promises.readFile(basePath, 'utf-8')).replaceAll("\r\n", "\n");
150
+ const parseCodeText = async (codeText, opt) => {
151
+ const strText = typeof codeText === "function" ? await codeText(opt) : codeText;
152
+ return strText.split('\n').map((line) => `${opt.inent}${line}`).join('\n');
153
+ };
154
+ const literalRegex = (str) => new RegExp(`^${str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')}(?!\\S)`);
155
+ //#endregion
135
156
  /**将codeText写入对应region
136
- * @param regionId - 区域id
157
+ * @param regionId - 区域id \`//#region ${id}\`
137
158
  * @param codeText - 文本
138
159
  * @param opt - 可选参数
139
- * @param opt.targetPath - 目标文件 默认为去除".macro"的同名文件
160
+ * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
161
+ * @param opt.glob - 使用glob匹配而非文件路径
140
162
  */
141
163
  async function regionMacro(regionId, codeText, opt) {
142
- const loc = utils_1.UtilFunc.getFuncLoc(2);
143
- if (!loc) {
144
- utils_1.SLogger.error(`UtilDT.macro 未能找到函数位置`);
145
- return;
164
+ const plist = [];
165
+ const filePaths = parseMacroPaths(opt);
166
+ for (const filePath of filePaths) {
167
+ const queuefunc = async () => {
168
+ if (!(await utils_1.UtilFT.pathExists(filePath))) {
169
+ utils_1.SLogger.error(`UtilDT.regionMacro ${filePath} 不存在`);
170
+ return;
171
+ }
172
+ let fileText = await readFile(filePath);
173
+ const regex = new RegExp(/(^|\n)([^\S\n]*)(\/\/#region (.*)\n)/.source +
174
+ /([\s\S]*?)/.source +
175
+ /([^\S\n]*\/\/#endregion(?!\S).*)/.source, "g");
176
+ regex.lastIndex = 0;
177
+ let match;
178
+ let hasMatch = false;
179
+ while (match = regex.exec(fileText)) {
180
+ const id = match[4];
181
+ const prefix = match[1];
182
+ const content = match[5];
183
+ const inent = match[2];
184
+ const comment = match[3];
185
+ const endcomment = match[6];
186
+ const idregex = typeof regionId === "string"
187
+ ? literalRegex(regionId) : regionId;
188
+ let idmatch = idregex.exec(id);
189
+ if (idmatch == null)
190
+ continue;
191
+ hasMatch = true;
192
+ const ol = fileText.length;
193
+ const parseCode = await parseCodeText(codeText, {
194
+ matchId: idmatch[0],
195
+ text: (0, utils_1.dedent)(content),
196
+ inent,
197
+ filePath
198
+ });
199
+ fileText = fileText.replace(match[0], `${prefix}${inent}${comment}${parseCode}\n${endcomment}`);
200
+ regex.lastIndex += fileText.length - ol;
201
+ }
202
+ if (hasMatch)
203
+ await fs.promises.writeFile(filePath, fileText, 'utf-8');
204
+ else if (!opt?.glob)
205
+ utils_1.SLogger.error(`UtilDT.regionMacro 无法找到区域 ${regionId}`);
206
+ };
207
+ plist.push(utils_1.UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\", "/")), queuefunc));
146
208
  }
147
- ;
148
- const baseFilePath = opt?.targetPath
149
- ? path.resolve(process.cwd(), opt.targetPath)
150
- : loc.filePath.replace(/(.+)\.macro\.(js|ts|cjs|mjs)$/, "$1.$2");
151
- const queuefunc = async () => {
152
- if (!(await utils_1.UtilFT.pathExists(baseFilePath))) {
153
- utils_1.SLogger.error(`UtilDT.macro ${baseFilePath} 不存在`);
154
- return;
155
- }
156
- ;
157
- const text = (await fs.promises.readFile(baseFilePath, 'utf-8')).replaceAll("\r\n", "\n");
158
- const getregex = () => new RegExp(`([^\\S\\n]*)(//#region ${regionId}(?!\\S).*\\n)` +
159
- /([\s\S]*?)/.source +
160
- /([^\S\n]*\/\/#endregion(?!\S).*)/.source, "g");
161
- if (!(getregex().test(text))) {
162
- utils_1.SLogger.error(`UtilDT.macro 无法找到区域 ${regionId}`);
163
- return;
164
- }
165
- const match = getregex().exec(text);
166
- const strText = typeof codeText === "function" ? await codeText() : codeText;
167
- const mapText = strText.split('\n').map((line) => `${match[1]}${line}`).join('\n');
168
- const ntext = text.replace(getregex(), `$1$2${mapText}\n$4`);
169
- await fs.promises.writeFile(baseFilePath, ntext, 'utf-8');
170
- };
171
- await utils_1.UtilFunc.queueProc(path.posix.normalize(baseFilePath.replaceAll("\\", "/")), queuefunc);
209
+ await Promise.all(plist);
172
210
  }
173
211
  UtilDT.regionMacro = regionMacro;
212
+ /**将codeText写入对应注释下
213
+ * @param commentId - 注释id \`// ${id}\`
214
+ * @param codeText - 文本
215
+ * @param opt - 可选参数
216
+ * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
217
+ * @param opt.glob - 使用glob匹配而非文件路径
218
+ */
219
+ async function commentMacro(commentId, codeText, opt) {
220
+ const plist = [];
221
+ const filePaths = parseMacroPaths(opt);
222
+ for (const filePath of filePaths) {
223
+ const queuefunc = async () => {
224
+ if (!(await utils_1.UtilFT.pathExists(filePath))) {
225
+ utils_1.SLogger.error(`UtilDT.commentMacro ${filePath} 不存在`);
226
+ return;
227
+ }
228
+ let fileText = await readFile(filePath);
229
+ const regex = new RegExp(/(^|\n)([^\S\n]*)(\/\/ (.*))(\n|)/.source +
230
+ /([^\n]*)/.source, "g");
231
+ let match;
232
+ let hasMatch = false;
233
+ while (match = regex.exec(fileText)) {
234
+ const id = match[4];
235
+ const prefix = match[1];
236
+ const content = match[6];
237
+ const inent = match[2];
238
+ const comment = match[3];
239
+ const idregex = typeof commentId === "string"
240
+ ? literalRegex(commentId) : commentId;
241
+ let idmatch = idregex.exec(id);
242
+ if (idmatch == null)
243
+ continue;
244
+ hasMatch = true;
245
+ const ol = fileText.length;
246
+ const parseCode = await parseCodeText(codeText, {
247
+ matchId: idmatch[0],
248
+ text: (0, utils_1.dedent)(content),
249
+ inent,
250
+ filePath
251
+ });
252
+ if (parseCode.includes('\n')) {
253
+ utils_1.SLogger.error(`UtilDT.commentMacro 无法使用多行文本, 考虑使用regionMacro ${codeText}`);
254
+ return;
255
+ }
256
+ fileText = fileText.replace(match[0], `${prefix}${inent}${comment}\n${parseCode}`);
257
+ regex.lastIndex += fileText.length - ol;
258
+ }
259
+ if (hasMatch)
260
+ await fs.promises.writeFile(filePath, fileText, 'utf-8');
261
+ else if (!opt?.glob)
262
+ utils_1.SLogger.error(`UtilDT.commentMacro 无法找到注释 ${commentId}`);
263
+ };
264
+ plist.push(utils_1.UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\", "/")), queuefunc));
265
+ }
266
+ await Promise.all(plist);
267
+ }
268
+ UtilDT.commentMacro = commentMacro;
269
+ /**将codeText写入对应文件 不存在则创建
270
+ * @param codeText - 文本
271
+ * @param opt - 可选参数
272
+ * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
273
+ * @param opt.glob - 使用glob匹配而非文件路径
274
+ */
275
+ async function fileMacro(codeText, opt) {
276
+ const plist = [];
277
+ const filePaths = parseMacroPaths(opt);
278
+ for (const filePath of filePaths) {
279
+ const queuefunc = async () => {
280
+ await utils_1.UtilFT.ensurePathExists(filePath);
281
+ const text = await readFile(filePath);
282
+ const parseCode = await parseCodeText(codeText, { matchId: '', text, inent: '', filePath });
283
+ await fs.promises.writeFile(filePath, parseCode, 'utf-8');
284
+ };
285
+ plist.push(utils_1.UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\", "/")), queuefunc));
286
+ }
287
+ await Promise.all(plist);
288
+ }
289
+ UtilDT.fileMacro = fileMacro;
174
290
  })(UtilDT || (exports.UtilDT = UtilDT = {}));
@@ -0,0 +1,7 @@
1
+ export declare namespace UtilMacro {
2
+ /**根据注释批量生成导出
3
+ * @param glob - 应用的golb
4
+ * @example
5
+ */
6
+ function exportComment(glob: string): void;
7
+ }
@@ -0,0 +1,30 @@
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.UtilMacro = void 0;
7
+ const utils_1 = require("@zwa73/utils");
8
+ const QuickFunc_1 = require("./QuickFunc");
9
+ const path_1 = __importDefault(require("path"));
10
+ var UtilMacro;
11
+ (function (UtilMacro) {
12
+ /**根据注释批量生成导出
13
+ * @param glob - 应用的golb
14
+ * @example
15
+ */
16
+ function exportComment(glob) {
17
+ (0, QuickFunc_1.commentMacro)(/export (\S*)/, ({ filePath, matchId }) => {
18
+ const globp = /export (\S*)/.exec(matchId)[1];
19
+ const basedir = path_1.default.dirname(filePath).replaceAll('\\', '/');
20
+ const result = utils_1.UtilFT.fileSearchGlob(basedir, globp, { normalize: 'posix' })
21
+ .map((file) => path_1.default.posix.relative(basedir, file))
22
+ .map((file) => path_1.default.parse(file).name)
23
+ .filter((file) => file != path_1.default.parse(filePath).name)
24
+ .map((file) => `export * from './${file}'`)
25
+ .join(';');
26
+ return result;
27
+ }, { glob: true, filePath: glob });
28
+ }
29
+ UtilMacro.exportComment = exportComment;
30
+ })(UtilMacro || (exports.UtilMacro = UtilMacro = {}));
package/dist/index.js CHANGED
@@ -17,3 +17,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./UtilDevTool"), exports);
18
18
  __exportStar(require("./Command"), exports);
19
19
  __exportStar(require("./QuickFunc"), exports);
20
+ //export *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zwa73/dev-utils",
3
- "version": "1.0.37",
3
+ "version": "1.0.39",
4
4
  "description": "编译与调试工具",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -16,13 +16,14 @@
16
16
  "author": "zwa73",
17
17
  "license": "ISC",
18
18
  "dependencies": {
19
- "@zwa73/utils": "^1.0.114",
19
+ "@zwa73/utils": "^1.0.117",
20
20
  "commander": "^11.1.0",
21
21
  "ts-node": "^10.9.2",
22
22
  "tsconfig-paths": "^4.2.0",
23
23
  "typescript-json-schema": "^0.63.0"
24
24
  },
25
25
  "devDependencies": {
26
+ "@types/fluent-ffmpeg": "^2.1.24",
26
27
  "@types/jest": "^29.5.12",
27
28
  "@types/node": "^20.11.19",
28
29
  "jest": "^29.7.0",
@@ -0,0 +1,4 @@
1
+ import { UtilMacro } from "./UtilMacro";
2
+
3
+
4
+ //UtilMacro.exportComment('src/**/*.ts');
package/src/QuickFunc.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { UtilDT } from "./UtilDevTool";
2
2
 
3
3
  export const {
4
- regionMacro
4
+ regionMacro ,
5
+ fileMacro ,
6
+ commentMacro,
5
7
  } = UtilDT;
@@ -1,7 +1,7 @@
1
1
  import * as path from 'path';
2
2
  import * as TJS from 'typescript-json-schema';
3
3
  import * as fs from 'fs';
4
- import { JObject, SLogger, UtilFT, UtilFunc, getFuncLoc } from '@zwa73/utils';
4
+ import { JObject, SLogger, UtilFT, UtilFunc, dedent, throwError } from '@zwa73/utils';
5
5
 
6
6
  export namespace UtilDT{
7
7
 
@@ -125,54 +125,183 @@ export async function batchNode(filepath:string|string[],opt?:BatchNodeOpt) {
125
125
  // 将所有的相对路径转换为绝对路径
126
126
  const absolutePaths = filepath.map(fp => path.resolve(process.cwd(), fp).replaceAll("\\","/"));
127
127
  // 创建一个字符串,其中包含所有文件的 require 语句
128
- const requires = absolutePaths.map(fp => `require('${fp}');`).join('\n');
128
+ const requires = absolutePaths.map(fp => `require('${fp}')`).join(';');
129
129
  // 创建并执行 ts-node 命令
130
130
  const cmd = `ts-node -r tsconfig-paths/register -e "${requires}" ${opt?.project?`-P "${opt.project}"` : ""}`;
131
131
  await UtilFunc.exec(cmd, { outlvl: 'info', errlvl: 'warn' });
132
132
  }
133
133
 
134
134
  /**宏的可选参数 */
135
- type MacroOpt = {
135
+ type MacroOpt = Partial<{
136
136
  /**宏展开的目标文件 */
137
- targetPath:string;
137
+ filePath:string[]|string;
138
+ /**使用glob匹配而非文件路径 */
139
+ glob:boolean;
140
+ }>
141
+ /**codeText的参数 */
142
+ type CodeTextOpt = {
143
+ /**匹配的region/comment id */
144
+ matchId:string;
145
+ /**展开宏的目标文件 */
146
+ filePath:string;
147
+ /**展开宏区域的原文本 */
148
+ text:string;
149
+ /**缩进 会自动应用 */
150
+ inent:string;
138
151
  }
139
-
152
+ //#region macro工具
153
+ const parseMacroPaths = (opt?:MacroOpt)=>{
154
+ const loc = UtilFunc.getFuncLoc(3);
155
+ if(!loc && !opt?.filePath) throwError(`parseMacroPaths 未能找到函数位置`);
156
+ const basePath = loc?.filePath!;
157
+ return opt?.filePath
158
+ ? opt.glob
159
+ ? UtilFT.fileSearchGlob(process.cwd(),opt.filePath,{normalize:"posix"})
160
+ : typeof opt?.filePath==="string"
161
+ ? [opt?.filePath.replaceAll('\\','/')]
162
+ : opt?.filePath.map((filepath)=>filepath.replaceAll('\\','/'))
163
+ : [basePath.replace(/(.+)\.macro\.(js|ts|cjs|mjs)$/,"$1.$2").replaceAll('\\','/')];
164
+ }
165
+ const readFile = async (basePath:string)=>
166
+ (await fs.promises.readFile(basePath,'utf-8')).replaceAll("\r\n","\n");
167
+ const parseCodeText = async (codeText:string|((opt:CodeTextOpt)=>string|Promise<string>),opt:CodeTextOpt)=>{
168
+ const strText = typeof codeText === "function" ? await codeText(opt) : codeText;
169
+ return strText.split('\n').map((line)=>`${opt.inent}${line}`).join('\n');
170
+ }
171
+ const literalRegex = (str:string)=>new RegExp(
172
+ `^${str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')}(?!\\S)`);
173
+ //#endregion
140
174
  /**将codeText写入对应region
141
- * @param regionId - 区域id
175
+ * @param regionId - 区域id \`//#region ${id}\`
142
176
  * @param codeText - 文本
143
177
  * @param opt - 可选参数
144
- * @param opt.targetPath - 目标文件 默认为去除".macro"的同名文件
178
+ * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
179
+ * @param opt.glob - 使用glob匹配而非文件路径
145
180
  */
146
- export async function regionMacro(regionId:string,codeText:string|(()=>string|Promise<string>),opt?:MacroOpt){
147
- const loc = UtilFunc.getFuncLoc(2);
148
- if(!loc){
149
- SLogger.error(`UtilDT.macro 未能找到函数位置`);
150
- return
151
- };
152
- const baseFilePath = opt?.targetPath
153
- ? path.resolve(process.cwd(),opt.targetPath)
154
- : loc.filePath.replace(/(.+)\.macro\.(js|ts|cjs|mjs)$/,"$1.$2");
155
- const queuefunc = async ()=>{
156
- if(!(await UtilFT.pathExists(baseFilePath))) {
157
- SLogger.error(`UtilDT.macro ${baseFilePath} 不存在`);
158
- return
159
- };
160
- const text = (await fs.promises.readFile(baseFilePath,'utf-8')).replaceAll("\r\n","\n");
161
- const getregex = ()=>new RegExp(
162
- `([^\\S\\n]*)(//#region ${regionId}(?!\\S).*\\n)`+
163
- /([\s\S]*?)/.source+
164
- /([^\S\n]*\/\/#endregion(?!\S).*)/.source
165
- ,"g");
166
- if (!(getregex().test(text))) {
167
- SLogger.error(`UtilDT.macro 无法找到区域 ${regionId}`);
168
- return;
181
+ export async function regionMacro(regionId:string|RegExp,codeText:string|((opt:CodeTextOpt)=>string|Promise<string>),opt?:MacroOpt){
182
+ const plist:Promise<void>[] = [];
183
+ const filePaths = parseMacroPaths(opt);
184
+ for(const filePath of filePaths){
185
+ const queuefunc = async ()=>{
186
+ if(!(await UtilFT.pathExists(filePath))) {
187
+ SLogger.error(`UtilDT.regionMacro ${filePath} 不存在`);
188
+ return
189
+ }
190
+ let fileText = await readFile(filePath);
191
+ const regex = new RegExp(
192
+ /(^|\n)([^\S\n]*)(\/\/#region (.*)\n)/.source+
193
+ /([\s\S]*?)/.source+
194
+ /([^\S\n]*\/\/#endregion(?!\S).*)/.source
195
+ ,"g")
196
+ regex.lastIndex=0;
197
+ let match:RegExpExecArray|null;
198
+ let hasMatch = false;
199
+ while(match = regex.exec(fileText)){
200
+ const id = match[4];
201
+ const prefix = match[1];
202
+ const content = match[5];
203
+ const inent = match[2];
204
+ const comment = match[3];
205
+ const endcomment = match[6];
206
+
207
+ const idregex = typeof regionId === "string"
208
+ ? literalRegex(regionId) : regionId;
209
+ let idmatch = idregex.exec(id);
210
+ if(idmatch==null) continue;
211
+ hasMatch=true;
212
+ const ol = fileText.length;
213
+ const parseCode = await parseCodeText(codeText,{
214
+ matchId :idmatch[0],
215
+ text :dedent(content),
216
+ inent ,
217
+ filePath
218
+ });
219
+ fileText = fileText.replace(match[0], `${prefix}${inent}${comment}${parseCode}\n${endcomment}`);
220
+ regex.lastIndex += fileText.length - ol;
221
+ }
222
+ if(hasMatch)
223
+ await fs.promises.writeFile(filePath, fileText, 'utf-8');
224
+ else if(!opt?.glob) SLogger.error(`UtilDT.regionMacro 无法找到区域 ${regionId}`);
169
225
  }
170
- const match = getregex().exec(text)!;
171
- const strText = typeof codeText === "function" ? await codeText() : codeText;
172
- const mapText = strText.split('\n').map((line)=>`${match[1]}${line}`).join('\n');
173
- const ntext = text.replace(getregex(), `$1$2${mapText}\n$4`);
174
- await fs.promises.writeFile(baseFilePath, ntext, 'utf-8');
226
+ plist.push(UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\","/")),queuefunc))
175
227
  }
176
- await UtilFunc.queueProc(path.posix.normalize(baseFilePath.replaceAll("\\","/")),queuefunc);
228
+ await Promise.all(plist);
229
+ }
230
+ /**将codeText写入对应注释下
231
+ * @param commentId - 注释id \`// ${id}\`
232
+ * @param codeText - 文本
233
+ * @param opt - 可选参数
234
+ * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
235
+ * @param opt.glob - 使用glob匹配而非文件路径
236
+ */
237
+ export async function commentMacro(commentId:string|RegExp,codeText:string|((opt:CodeTextOpt)=>string|Promise<string>),opt?:MacroOpt){
238
+ const plist:Promise<void>[] = [];
239
+ const filePaths = parseMacroPaths(opt);
240
+ for(const filePath of filePaths){
241
+ const queuefunc = async ()=>{
242
+ if(!(await UtilFT.pathExists(filePath))) {
243
+ SLogger.error(`UtilDT.commentMacro ${filePath} 不存在`);
244
+ return
245
+ }
246
+ let fileText = await readFile(filePath);
247
+ const regex = new RegExp(
248
+ /(^|\n)([^\S\n]*)(\/\/ (.*))(\n|)/.source+
249
+ /([^\n]*)/.source
250
+ ,"g")
251
+ let match:RegExpExecArray|null;
252
+ let hasMatch = false;
253
+ while(match = regex.exec(fileText)){
254
+ const id = match[4];
255
+ const prefix = match[1];
256
+ const content = match[6];
257
+ const inent = match[2];
258
+ const comment = match[3];
259
+
260
+ const idregex = typeof commentId === "string"
261
+ ? literalRegex(commentId) : commentId;
262
+ let idmatch = idregex.exec(id);
263
+ if(idmatch==null) continue;
264
+ hasMatch=true;
265
+ const ol = fileText.length;
266
+ const parseCode = await parseCodeText(codeText,{
267
+ matchId :idmatch[0],
268
+ text :dedent(content),
269
+ inent ,
270
+ filePath
271
+ });
272
+ if(parseCode.includes('\n')){
273
+ SLogger.error(`UtilDT.commentMacro 无法使用多行文本, 考虑使用regionMacro ${codeText}`);
274
+ return;
275
+ }
276
+ fileText = fileText.replace(match[0], `${prefix}${inent}${comment}\n${parseCode}`);
277
+ regex.lastIndex += fileText.length - ol;
278
+ }
279
+ if(hasMatch)
280
+ await fs.promises.writeFile(filePath, fileText, 'utf-8');
281
+ else if(!opt?.glob) SLogger.error(`UtilDT.commentMacro 无法找到注释 ${commentId}`);
282
+ }
283
+ plist.push(UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\","/")),queuefunc))
284
+ }
285
+ await Promise.all(plist);
286
+ }
287
+ /**将codeText写入对应文件 不存在则创建
288
+ * @param codeText - 文本
289
+ * @param opt - 可选参数
290
+ * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
291
+ * @param opt.glob - 使用glob匹配而非文件路径
292
+ */
293
+ export async function fileMacro(codeText:string|((opt:CodeTextOpt)=>string|Promise<string>),opt?:MacroOpt){
294
+ const plist:Promise<void>[] = [];
295
+ const filePaths = parseMacroPaths(opt);
296
+ for(const filePath of filePaths){
297
+ const queuefunc = async ()=>{
298
+ await UtilFT.ensurePathExists(filePath);
299
+ const text = await readFile(filePath);
300
+ const parseCode = await parseCodeText(codeText,{matchId:'',text,inent:'',filePath});
301
+ await fs.promises.writeFile(filePath, parseCode, 'utf-8');
302
+ }
303
+ plist.push(UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\","/")),queuefunc))
304
+ }
305
+ await Promise.all(plist);
177
306
  }
178
307
  }
@@ -0,0 +1,24 @@
1
+ import { UtilFT } from "@zwa73/utils";
2
+ import { commentMacro } from "./QuickFunc"
3
+ import path from "path";
4
+
5
+
6
+ export namespace UtilMacro{
7
+ /**根据注释批量生成导出
8
+ * @param glob - 应用的golb
9
+ * @example
10
+ */
11
+ export function exportComment(glob:string){
12
+ commentMacro(/export (\S*)/,({filePath,matchId})=>{
13
+ const globp = /export (\S*)/.exec(matchId)![1];
14
+ const basedir = path.dirname(filePath).replaceAll('\\','/');
15
+ const result = UtilFT.fileSearchGlob(basedir,globp,{normalize:'posix'})
16
+ .map((file)=>path.posix.relative(basedir,file))
17
+ .map((file)=>path.parse(file).name)
18
+ .filter((file)=>file!=path.parse(filePath).name)
19
+ .map((file)=>`export * from './${file}'`)
20
+ .join(';');
21
+ return result;
22
+ },{glob:true,filePath:glob});
23
+ }
24
+ }
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
- export * from './UtilDevTool';
2
- export * from './Command';
3
- export * from "./QuickFunc";
1
+ export * from './UtilDevTool';
2
+ export * from './Command';
3
+ export * from "./QuickFunc";
4
+ //export *
@@ -1,4 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "include": ["./src/**/*.ts", "./src/**/*.js"]
4
- }
@@ -1,22 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "allowJs": true,
4
- "strict": true,
5
- "target": "ES2022",
6
- "module": "CommonJS",
7
- "moduleResolution": "node",
8
- "esModuleInterop": true,
9
- "outDir": "./dist",
10
- "declaration": true,
11
- "baseUrl": ".",
12
- "emitDecoratorMetadata": true,
13
- "experimentalDecorators": true,
14
- "paths": {
15
- "@src/*": ["./src/*"],
16
- "@/*": ["./*"],
17
- "@": ["./src/index"]
18
- }
19
- },
20
- "include": ["./src/**/*.ts", "./src/**/*.js", "./jest/**/*.ts"],
21
- "exclude": ["./node_modules/**/*"]
22
- }
@@ -1,4 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "include": ["./src/**/*.ts", "./src/**/*.js"]
4
- }
package/tsconfig.json DELETED
@@ -1,22 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "allowJs": true,
4
- "strict": true,
5
- "target": "ES2022",
6
- "module": "commonjs",
7
- "moduleResolution": "node",
8
- "esModuleInterop": true,
9
- "outDir": "./dist",
10
- "declaration": true,
11
- "baseUrl": ".",
12
- "emitDecoratorMetadata": true,
13
- "experimentalDecorators": true,
14
- "paths": {
15
- "@src/*": ["./src/*"],
16
- "@/*" : ["./*"],
17
- "@" : ["./src/index"]
18
- }
19
- },
20
- "include": ["./src/**/*.ts", "./src/**/*.js","./jest/**/*.ts"],
21
- "exclude": ["./node_modules/**/*"]
22
- }