@zwa73/dev-utils 1.0.38 → 1.0.40

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,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const UtilMacro_1 = require("./UtilMacro");
4
+ UtilMacro_1.UtilMacro.exportComment('src/**/*.ts');
@@ -53,13 +53,27 @@ export declare namespace UtilDT {
53
53
  /**使用glob匹配而非文件路径 */
54
54
  glob: boolean;
55
55
  }>;
56
+ /**codeText的参数 */
57
+ type CodeTextOpt = {
58
+ /**匹配的region/comment id */
59
+ matchId: string;
60
+ /**region/comment id正则的执行结果*/
61
+ execArr: RegExpExecArray;
62
+ /**展开宏的目标文件 */
63
+ filePath: string;
64
+ /**展开宏区域的原文本 */
65
+ text: string;
66
+ /**缩进 会自动应用 */
67
+ inent: string;
68
+ };
56
69
  /**将codeText写入对应region
57
70
  * @param regionId - 区域id \`//#region ${id}\`
58
71
  * @param codeText - 文本
59
72
  * @param opt - 可选参数
60
- * @param opt.targetPath - 目标文件 默认为去除".macro"的同名文件
73
+ * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
74
+ * @param opt.glob - 使用glob匹配而非文件路径
61
75
  */
62
- export function regionMacro(regionId: string, codeText: string | (() => string | Promise<string>), opt?: MacroOpt): Promise<void>;
76
+ export function regionMacro(regionId: string | RegExp, codeText: string | ((opt: CodeTextOpt) => string | Promise<string>), opt?: MacroOpt): Promise<void>;
63
77
  /**将codeText写入对应注释下
64
78
  * @param commentId - 注释id \`// ${id}\`
65
79
  * @param codeText - 文本
@@ -67,13 +81,13 @@ export declare namespace UtilDT {
67
81
  * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
68
82
  * @param opt.glob - 使用glob匹配而非文件路径
69
83
  */
70
- export function commentMacro(commentId: string, codeText: string | (() => string | Promise<string>), opt?: MacroOpt): Promise<void>;
84
+ export function commentMacro(commentId: string | RegExp, codeText: string | ((opt: CodeTextOpt) => string | Promise<string>), opt?: MacroOpt): Promise<void>;
71
85
  /**将codeText写入对应文件 不存在则创建
72
86
  * @param codeText - 文本
73
87
  * @param opt - 可选参数
74
88
  * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
75
89
  * @param opt.glob - 使用glob匹配而非文件路径
76
90
  */
77
- export function fileMacro(codeText: string | (() => string | Promise<string>), opt?: MacroOpt): Promise<void>;
91
+ export function fileMacro(codeText: string | ((opt: Omit<CodeTextOpt, 'ident' | 'matchId' | 'execArr'>) => string | Promise<string>), opt?: MacroOpt): Promise<void>;
78
92
  export {};
79
93
  }
@@ -126,59 +126,84 @@ 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
135
  //#region macro工具
136
- const parseMacroPaths = (basePath, opt) => {
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;
137
141
  return opt?.filePath
138
142
  ? opt.glob
139
- ? utils_1.UtilFT.fileSearchGlob(process.cwd(), opt.filePath)
140
- : typeof opt?.filePath === "string" ? [opt?.filePath] : opt?.filePath
141
- : [basePath.replace(/(.+)\.macro\.(js|ts|cjs|mjs)$/, "$1.$2")];
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('\\', '/')];
142
148
  };
143
149
  const readFile = async (basePath) => (await fs.promises.readFile(basePath, 'utf-8')).replaceAll("\r\n", "\n");
144
150
  const parseCodeText = async (codeText, opt) => {
145
151
  const strText = typeof codeText === "function" ? await codeText(opt) : codeText;
146
152
  return strText.split('\n').map((line) => `${opt.inent}${line}`).join('\n');
147
153
  };
154
+ const literalRegex = (str) => new RegExp(`^${str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')}(?!\\S)`);
148
155
  //#endregion
149
156
  /**将codeText写入对应region
150
157
  * @param regionId - 区域id \`//#region ${id}\`
151
158
  * @param codeText - 文本
152
159
  * @param opt - 可选参数
153
- * @param opt.targetPath - 目标文件 默认为去除".macro"的同名文件
160
+ * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
161
+ * @param opt.glob - 使用glob匹配而非文件路径
154
162
  */
155
163
  async function regionMacro(regionId, codeText, opt) {
156
- const loc = utils_1.UtilFunc.getFuncLoc(2);
157
- if (!loc) {
158
- utils_1.SLogger.error(`UtilDT.regionMacro 未能找到函数位置`);
159
- return;
160
- }
161
164
  const plist = [];
162
- const filePaths = parseMacroPaths(loc.filePath, opt);
165
+ const filePaths = parseMacroPaths(opt);
163
166
  for (const filePath of filePaths) {
164
167
  const queuefunc = async () => {
165
168
  if (!(await utils_1.UtilFT.pathExists(filePath))) {
166
169
  utils_1.SLogger.error(`UtilDT.regionMacro ${filePath} 不存在`);
167
170
  return;
168
171
  }
169
- const text = await readFile(filePath);
170
- const getregex = () => new RegExp(`([^\\S\\n]*)(//#region ${regionId}(?!\\S).*\\n)` +
172
+ let fileText = await readFile(filePath);
173
+ const regex = new RegExp(/(^|\n)([^\S\n]*)(\/\/#region (.*)\n)/.source +
171
174
  /([\s\S]*?)/.source +
172
175
  /([^\S\n]*\/\/#endregion(?!\S).*)/.source, "g");
173
- if (!getregex().test(text)) {
174
- if (!opt?.glob)
175
- utils_1.SLogger.error(`UtilDT.regionMacro 无法找到区域 ${regionId}`);
176
- return;
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
+ execArr: idmatch,
196
+ text: (0, utils_1.dedent)(content),
197
+ inent,
198
+ filePath
199
+ });
200
+ fileText = fileText.replace(match[0], `${prefix}${inent}${comment}${parseCode}\n${endcomment}`);
201
+ regex.lastIndex += fileText.length - ol;
177
202
  }
178
- const match = getregex().exec(text);
179
- const parseCode = await parseCodeText(codeText, { text: (0, utils_1.dedent)(match[3]), inent: match[1], filePath });
180
- const ntext = text.replace(getregex(), `$1$2${parseCode}\n$4`);
181
- await fs.promises.writeFile(filePath, ntext, 'utf-8');
203
+ if (hasMatch)
204
+ await fs.promises.writeFile(filePath, fileText, 'utf-8');
205
+ else if (!opt?.glob)
206
+ utils_1.SLogger.error(`UtilDT.regionMacro 无法找到区域 ${regionId}`);
182
207
  };
183
208
  plist.push(utils_1.UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\", "/")), queuefunc));
184
209
  }
@@ -193,36 +218,50 @@ var UtilDT;
193
218
  * @param opt.glob - 使用glob匹配而非文件路径
194
219
  */
195
220
  async function commentMacro(commentId, codeText, opt) {
196
- const loc = utils_1.UtilFunc.getFuncLoc(2);
197
- if (!loc) {
198
- utils_1.SLogger.error(`UtilDT.commentMacro 未能找到函数位置`);
199
- return;
200
- }
201
221
  const plist = [];
202
- const filePaths = parseMacroPaths(loc.filePath, opt);
222
+ const filePaths = parseMacroPaths(opt);
203
223
  for (const filePath of filePaths) {
204
224
  const queuefunc = async () => {
205
225
  if (!(await utils_1.UtilFT.pathExists(filePath))) {
206
226
  utils_1.SLogger.error(`UtilDT.commentMacro ${filePath} 不存在`);
207
227
  return;
208
228
  }
209
- const text = await readFile(filePath);
210
- const getregex = () => new RegExp(`([^\\S\\n]*)(// ${commentId}(?!\\S).*)` +
211
- /(\n|)/.source +
229
+ let fileText = await readFile(filePath);
230
+ const regex = new RegExp(/(^|\n)([^\S\n]*)(\/\/ (.*))(\n|)/.source +
212
231
  /([^\n]*)/.source, "g");
213
- if (!getregex().test(text)) {
214
- if (!opt?.glob)
215
- utils_1.SLogger.error(`UtilDT.commentMacro 无法找到注释 ${commentId}`);
216
- return;
232
+ let match;
233
+ let hasMatch = false;
234
+ while (match = regex.exec(fileText)) {
235
+ const id = match[4];
236
+ const prefix = match[1];
237
+ const content = match[6];
238
+ const inent = match[2];
239
+ const comment = match[3];
240
+ const idregex = typeof commentId === "string"
241
+ ? literalRegex(commentId) : commentId;
242
+ let idmatch = idregex.exec(id);
243
+ if (idmatch == null)
244
+ continue;
245
+ hasMatch = true;
246
+ const ol = fileText.length;
247
+ const parseCode = await parseCodeText(codeText, {
248
+ matchId: idmatch[0],
249
+ execArr: idmatch,
250
+ text: (0, utils_1.dedent)(content),
251
+ inent,
252
+ filePath
253
+ });
254
+ if (parseCode.includes('\n')) {
255
+ utils_1.SLogger.error(`UtilDT.commentMacro 无法使用多行文本, 考虑使用regionMacro ${codeText}`);
256
+ return;
257
+ }
258
+ fileText = fileText.replace(match[0], `${prefix}${inent}${comment}\n${parseCode}`);
259
+ regex.lastIndex += fileText.length - ol;
217
260
  }
218
- const match = getregex().exec(text);
219
- const parseCode = await parseCodeText(codeText, { text: match[3], inent: match[1], filePath });
220
- if (parseCode.includes('\n')) {
221
- utils_1.SLogger.error(`UtilDT.commentMacro 无法使用多行文本, 考虑使用regionMacro ${codeText}`);
222
- return;
223
- }
224
- const ntext = text.replace(getregex(), `$1$2\n${parseCode}`);
225
- await fs.promises.writeFile(filePath, ntext, 'utf-8');
261
+ if (hasMatch)
262
+ await fs.promises.writeFile(filePath, fileText, 'utf-8');
263
+ else if (!opt?.glob)
264
+ utils_1.SLogger.error(`UtilDT.commentMacro 无法找到注释 ${commentId}`);
226
265
  };
227
266
  plist.push(utils_1.UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\", "/")), queuefunc));
228
267
  }
@@ -236,18 +275,19 @@ var UtilDT;
236
275
  * @param opt.glob - 使用glob匹配而非文件路径
237
276
  */
238
277
  async function fileMacro(codeText, opt) {
239
- const loc = utils_1.UtilFunc.getFuncLoc(2);
240
- if (!loc) {
241
- utils_1.SLogger.error(`UtilDT.fileMacro 未能找到函数位置`);
242
- return;
243
- }
244
278
  const plist = [];
245
- const filePaths = parseMacroPaths(loc.filePath, opt);
279
+ const filePaths = parseMacroPaths(opt);
246
280
  for (const filePath of filePaths) {
247
281
  const queuefunc = async () => {
248
282
  await utils_1.UtilFT.ensurePathExists(filePath);
249
283
  const text = await readFile(filePath);
250
- const parseCode = await parseCodeText(codeText, { text, inent: '', filePath });
284
+ const parseCode = await parseCodeText(codeText, {
285
+ matchId: '',
286
+ execArr: /''/.exec(''),
287
+ text,
288
+ inent: '',
289
+ filePath
290
+ });
251
291
  await fs.promises.writeFile(filePath, parseCode, 'utf-8');
252
292
  };
253
293
  plist.push(utils_1.UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\", "/")), queuefunc));
@@ -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,29 @@
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, execArr }) => {
18
+ const basedir = path_1.default.dirname(filePath).replaceAll('\\', '/');
19
+ const result = utils_1.UtilFT.fileSearchGlob(basedir, execArr[1], { normalize: 'posix' })
20
+ .map((file) => path_1.default.posix.relative(basedir, file))
21
+ .map((file) => path_1.default.parse(file).name)
22
+ .filter((file) => file != path_1.default.parse(filePath).name)
23
+ .map((file) => `export * from './${file}'`)
24
+ .join(';');
25
+ return result.length > 0 ? `${result};` : result;
26
+ }, { glob: true, filePath: glob });
27
+ }
28
+ UtilMacro.exportComment = exportComment;
29
+ })(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.38",
3
+ "version": "1.0.40",
4
4
  "description": "编译与调试工具",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,4 @@
1
+ import { UtilMacro } from "./UtilMacro";
2
+
3
+
4
+ UtilMacro.exportComment('src/**/*.ts');
@@ -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, dedent } from '@zwa73/utils';
4
+ import { JObject, SLogger, UtilFT, UtilFunc, dedent, throwError } from '@zwa73/utils';
5
5
 
6
6
  export namespace UtilDT{
7
7
 
@@ -125,7 +125,7 @@ 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' });
@@ -139,7 +139,11 @@ type MacroOpt = Partial<{
139
139
  glob:boolean;
140
140
  }>
141
141
  /**codeText的参数 */
142
- type CdeeTextOpt = {
142
+ type CodeTextOpt = {
143
+ /**匹配的region/comment id */
144
+ matchId:string;
145
+ /**region/comment id正则的执行结果*/
146
+ execArr:RegExpExecArray;
143
147
  /**展开宏的目标文件 */
144
148
  filePath:string;
145
149
  /**展开宏区域的原文本 */
@@ -148,54 +152,79 @@ type CdeeTextOpt = {
148
152
  inent:string;
149
153
  }
150
154
  //#region macro工具
151
- const parseMacroPaths = (basePath:string,opt?:MacroOpt)=>{
155
+ const parseMacroPaths = (opt?:MacroOpt)=>{
156
+ const loc = UtilFunc.getFuncLoc(3);
157
+ if(!loc && !opt?.filePath) throwError(`parseMacroPaths 未能找到函数位置`);
158
+ const basePath = loc?.filePath!;
152
159
  return opt?.filePath
153
160
  ? opt.glob
154
- ? UtilFT.fileSearchGlob(process.cwd(),opt.filePath)
155
- : typeof opt?.filePath==="string" ? [opt?.filePath] : opt?.filePath
156
- : [basePath.replace(/(.+)\.macro\.(js|ts|cjs|mjs)$/,"$1.$2")];
161
+ ? UtilFT.fileSearchGlob(process.cwd(),opt.filePath,{normalize:"posix"})
162
+ : typeof opt?.filePath==="string"
163
+ ? [opt?.filePath.replaceAll('\\','/')]
164
+ : opt?.filePath.map((filepath)=>filepath.replaceAll('\\','/'))
165
+ : [basePath.replace(/(.+)\.macro\.(js|ts|cjs|mjs)$/,"$1.$2").replaceAll('\\','/')];
157
166
  }
158
167
  const readFile = async (basePath:string)=>
159
168
  (await fs.promises.readFile(basePath,'utf-8')).replaceAll("\r\n","\n");
160
- const parseCodeText = async (codeText:string|((opt:CdeeTextOpt)=>string|Promise<string>),opt:CdeeTextOpt)=>{
169
+ const parseCodeText = async (codeText:string|((opt:CodeTextOpt)=>string|Promise<string>),opt:CodeTextOpt)=>{
161
170
  const strText = typeof codeText === "function" ? await codeText(opt) : codeText;
162
171
  return strText.split('\n').map((line)=>`${opt.inent}${line}`).join('\n');
163
172
  }
173
+ const literalRegex = (str:string)=>new RegExp(
174
+ `^${str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')}(?!\\S)`);
164
175
  //#endregion
165
176
  /**将codeText写入对应region
166
177
  * @param regionId - 区域id \`//#region ${id}\`
167
178
  * @param codeText - 文本
168
179
  * @param opt - 可选参数
169
- * @param opt.targetPath - 目标文件 默认为去除".macro"的同名文件
180
+ * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
181
+ * @param opt.glob - 使用glob匹配而非文件路径
170
182
  */
171
- export async function regionMacro(regionId:string,codeText:string|(()=>string|Promise<string>),opt?:MacroOpt){
172
- const loc = UtilFunc.getFuncLoc(2);
173
- if(!loc){
174
- SLogger.error(`UtilDT.regionMacro 未能找到函数位置`);
175
- return
176
- }
183
+ export async function regionMacro(regionId:string|RegExp,codeText:string|((opt:CodeTextOpt)=>string|Promise<string>),opt?:MacroOpt){
177
184
  const plist:Promise<void>[] = [];
178
- const filePaths = parseMacroPaths(loc.filePath,opt);
185
+ const filePaths = parseMacroPaths(opt);
179
186
  for(const filePath of filePaths){
180
187
  const queuefunc = async ()=>{
181
188
  if(!(await UtilFT.pathExists(filePath))) {
182
189
  SLogger.error(`UtilDT.regionMacro ${filePath} 不存在`);
183
190
  return
184
191
  }
185
- const text = await readFile(filePath);
186
- const getregex = ()=>new RegExp(
187
- `([^\\S\\n]*)(//#region ${regionId}(?!\\S).*\\n)`+
188
- /([\s\S]*?)/.source+
189
- /([^\S\n]*\/\/#endregion(?!\S).*)/.source
190
- ,"g");
191
- if (!getregex().test(text)) {
192
- if(!opt?.glob) SLogger.error(`UtilDT.regionMacro 无法找到区域 ${regionId}`);
193
- return;
192
+ let fileText = await readFile(filePath);
193
+ const regex = new RegExp(
194
+ /(^|\n)([^\S\n]*)(\/\/#region (.*)\n)/.source+
195
+ /([\s\S]*?)/.source+
196
+ /([^\S\n]*\/\/#endregion(?!\S).*)/.source
197
+ ,"g")
198
+ regex.lastIndex=0;
199
+ let match:RegExpExecArray|null;
200
+ let hasMatch = false;
201
+ while(match = regex.exec(fileText)){
202
+ const id = match[4];
203
+ const prefix = match[1];
204
+ const content = match[5];
205
+ const inent = match[2];
206
+ const comment = match[3];
207
+ const endcomment = match[6];
208
+
209
+ const idregex = typeof regionId === "string"
210
+ ? literalRegex(regionId) : regionId;
211
+ let idmatch = idregex.exec(id);
212
+ if(idmatch==null) continue;
213
+ hasMatch=true;
214
+ const ol = fileText.length;
215
+ const parseCode = await parseCodeText(codeText,{
216
+ matchId :idmatch[0],
217
+ execArr :idmatch,
218
+ text :dedent(content),
219
+ inent ,
220
+ filePath
221
+ });
222
+ fileText = fileText.replace(match[0], `${prefix}${inent}${comment}${parseCode}\n${endcomment}`);
223
+ regex.lastIndex += fileText.length - ol;
194
224
  }
195
- const match = getregex().exec(text)!;
196
- const parseCode = await parseCodeText(codeText,{text:dedent(match[3]),inent:match[1],filePath});
197
- const ntext = text.replace(getregex(), `$1$2${parseCode}\n$4`);
198
- await fs.promises.writeFile(filePath, ntext, 'utf-8');
225
+ if(hasMatch)
226
+ await fs.promises.writeFile(filePath, fileText, 'utf-8');
227
+ else if(!opt?.glob) SLogger.error(`UtilDT.regionMacro 无法找到区域 ${regionId}`);
199
228
  }
200
229
  plist.push(UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\","/")),queuefunc))
201
230
  }
@@ -208,38 +237,52 @@ export async function regionMacro(regionId:string,codeText:string|(()=>string|Pr
208
237
  * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
209
238
  * @param opt.glob - 使用glob匹配而非文件路径
210
239
  */
211
- export async function commentMacro(commentId:string,codeText:string|(()=>string|Promise<string>),opt?:MacroOpt){
212
- const loc = UtilFunc.getFuncLoc(2);
213
- if(!loc){
214
- SLogger.error(`UtilDT.commentMacro 未能找到函数位置`);
215
- return
216
- }
240
+ export async function commentMacro(commentId:string|RegExp,codeText:string|((opt:CodeTextOpt)=>string|Promise<string>),opt?:MacroOpt){
217
241
  const plist:Promise<void>[] = [];
218
- const filePaths = parseMacroPaths(loc.filePath,opt);
242
+ const filePaths = parseMacroPaths(opt);
219
243
  for(const filePath of filePaths){
220
244
  const queuefunc = async ()=>{
221
245
  if(!(await UtilFT.pathExists(filePath))) {
222
246
  SLogger.error(`UtilDT.commentMacro ${filePath} 不存在`);
223
247
  return
224
248
  }
225
- const text = await readFile(filePath);
226
- const getregex = ()=>new RegExp(
227
- `([^\\S\\n]*)(// ${commentId}(?!\\S).*)`+
228
- /(\n|)/.source +
229
- /([^\n]*)/.source
230
- ,"g");
231
- if (!getregex().test(text)) {
232
- if(!opt?.glob) SLogger.error(`UtilDT.commentMacro 无法找到注释 ${commentId}`);
233
- return;
234
- }
235
- const match = getregex().exec(text)!;
236
- const parseCode = await parseCodeText(codeText,{text:match[3],inent:match[1],filePath});
237
- if(parseCode.includes('\n')){
238
- SLogger.error(`UtilDT.commentMacro 无法使用多行文本, 考虑使用regionMacro ${codeText}`);
239
- return;
249
+ let fileText = await readFile(filePath);
250
+ const regex = new RegExp(
251
+ /(^|\n)([^\S\n]*)(\/\/ (.*))(\n|)/.source+
252
+ /([^\n]*)/.source
253
+ ,"g")
254
+ let match:RegExpExecArray|null;
255
+ let hasMatch = false;
256
+ while(match = regex.exec(fileText)){
257
+ const id = match[4];
258
+ const prefix = match[1];
259
+ const content = match[6];
260
+ const inent = match[2];
261
+ const comment = match[3];
262
+
263
+ const idregex = typeof commentId === "string"
264
+ ? literalRegex(commentId) : commentId;
265
+ let idmatch = idregex.exec(id);
266
+ if(idmatch==null) continue;
267
+ hasMatch=true;
268
+ const ol = fileText.length;
269
+ const parseCode = await parseCodeText(codeText,{
270
+ matchId :idmatch[0],
271
+ execArr :idmatch,
272
+ text :dedent(content),
273
+ inent ,
274
+ filePath
275
+ });
276
+ if(parseCode.includes('\n')){
277
+ SLogger.error(`UtilDT.commentMacro 无法使用多行文本, 考虑使用regionMacro ${codeText}`);
278
+ return;
279
+ }
280
+ fileText = fileText.replace(match[0], `${prefix}${inent}${comment}\n${parseCode}`);
281
+ regex.lastIndex += fileText.length - ol;
240
282
  }
241
- const ntext = text.replace(getregex(), `$1$2\n${parseCode}`);
242
- await fs.promises.writeFile(filePath, ntext, 'utf-8');
283
+ if(hasMatch)
284
+ await fs.promises.writeFile(filePath, fileText, 'utf-8');
285
+ else if(!opt?.glob) SLogger.error(`UtilDT.commentMacro 无法找到注释 ${commentId}`);
243
286
  }
244
287
  plist.push(UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\","/")),queuefunc))
245
288
  }
@@ -251,19 +294,20 @@ export async function commentMacro(commentId:string,codeText:string|(()=>string|
251
294
  * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
252
295
  * @param opt.glob - 使用glob匹配而非文件路径
253
296
  */
254
- export async function fileMacro(codeText:string|(()=>string|Promise<string>),opt?:MacroOpt){
255
- const loc = UtilFunc.getFuncLoc(2);
256
- if(!loc){
257
- SLogger.error(`UtilDT.fileMacro 未能找到函数位置`);
258
- return
259
- }
297
+ export async function fileMacro(codeText:string|((opt:Omit<CodeTextOpt,'ident'|'matchId'|'execArr'>)=>string|Promise<string>),opt?:MacroOpt){
260
298
  const plist:Promise<void>[] = [];
261
- const filePaths = parseMacroPaths(loc.filePath,opt);
299
+ const filePaths = parseMacroPaths(opt);
262
300
  for(const filePath of filePaths){
263
301
  const queuefunc = async ()=>{
264
302
  await UtilFT.ensurePathExists(filePath);
265
303
  const text = await readFile(filePath);
266
- const parseCode = await parseCodeText(codeText,{text,inent:'',filePath});
304
+ const parseCode = await parseCodeText(codeText,{
305
+ matchId:'',
306
+ execArr:/''/.exec('')!,
307
+ text,
308
+ inent:'',
309
+ filePath
310
+ });
267
311
  await fs.promises.writeFile(filePath, parseCode, 'utf-8');
268
312
  }
269
313
  plist.push(UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\","/")),queuefunc))
@@ -0,0 +1,23 @@
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,execArr})=>{
13
+ const basedir = path.dirname(filePath).replaceAll('\\','/');
14
+ const result = UtilFT.fileSearchGlob(basedir,execArr[1],{normalize:'posix'})
15
+ .map((file)=>path.posix.relative(basedir,file))
16
+ .map((file)=>path.parse(file).name)
17
+ .filter((file)=>file!=path.parse(filePath).name)
18
+ .map((file)=>`export * from './${file}'`)
19
+ .join(';');
20
+ return result.length>0? `${result};` : result;
21
+ },{glob:true,filePath:glob});
22
+ }
23
+ }
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 *