@zwa73/dev-utils 1.0.38 → 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');
@@ -53,13 +53,25 @@ 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
+ /**展开宏的目标文件 */
61
+ filePath: string;
62
+ /**展开宏区域的原文本 */
63
+ text: string;
64
+ /**缩进 会自动应用 */
65
+ inent: string;
66
+ };
56
67
  /**将codeText写入对应region
57
68
  * @param regionId - 区域id \`//#region ${id}\`
58
69
  * @param codeText - 文本
59
70
  * @param opt - 可选参数
60
- * @param opt.targetPath - 目标文件 默认为去除".macro"的同名文件
71
+ * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
72
+ * @param opt.glob - 使用glob匹配而非文件路径
61
73
  */
62
- export function regionMacro(regionId: string, codeText: string | (() => string | Promise<string>), opt?: MacroOpt): Promise<void>;
74
+ export function regionMacro(regionId: string | RegExp, codeText: string | ((opt: CodeTextOpt) => string | Promise<string>), opt?: MacroOpt): Promise<void>;
63
75
  /**将codeText写入对应注释下
64
76
  * @param commentId - 注释id \`// ${id}\`
65
77
  * @param codeText - 文本
@@ -67,13 +79,13 @@ export declare namespace UtilDT {
67
79
  * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
68
80
  * @param opt.glob - 使用glob匹配而非文件路径
69
81
  */
70
- export function commentMacro(commentId: string, codeText: string | (() => string | Promise<string>), opt?: MacroOpt): Promise<void>;
82
+ export function commentMacro(commentId: string | RegExp, codeText: string | ((opt: CodeTextOpt) => string | Promise<string>), opt?: MacroOpt): Promise<void>;
71
83
  /**将codeText写入对应文件 不存在则创建
72
84
  * @param codeText - 文本
73
85
  * @param opt - 可选参数
74
86
  * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
75
87
  * @param opt.glob - 使用glob匹配而非文件路径
76
88
  */
77
- export function fileMacro(codeText: string | (() => string | Promise<string>), opt?: MacroOpt): Promise<void>;
89
+ export function fileMacro(codeText: string | ((opt: CodeTextOpt) => string | Promise<string>), opt?: MacroOpt): Promise<void>;
78
90
  export {};
79
91
  }
@@ -126,59 +126,83 @@ 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
+ 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;
177
201
  }
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');
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}`);
182
206
  };
183
207
  plist.push(utils_1.UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\", "/")), queuefunc));
184
208
  }
@@ -193,36 +217,49 @@ var UtilDT;
193
217
  * @param opt.glob - 使用glob匹配而非文件路径
194
218
  */
195
219
  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
220
  const plist = [];
202
- const filePaths = parseMacroPaths(loc.filePath, opt);
221
+ const filePaths = parseMacroPaths(opt);
203
222
  for (const filePath of filePaths) {
204
223
  const queuefunc = async () => {
205
224
  if (!(await utils_1.UtilFT.pathExists(filePath))) {
206
225
  utils_1.SLogger.error(`UtilDT.commentMacro ${filePath} 不存在`);
207
226
  return;
208
227
  }
209
- const text = await readFile(filePath);
210
- const getregex = () => new RegExp(`([^\\S\\n]*)(// ${commentId}(?!\\S).*)` +
211
- /(\n|)/.source +
228
+ let fileText = await readFile(filePath);
229
+ const regex = new RegExp(/(^|\n)([^\S\n]*)(\/\/ (.*))(\n|)/.source +
212
230
  /([^\n]*)/.source, "g");
213
- if (!getregex().test(text)) {
214
- if (!opt?.glob)
215
- utils_1.SLogger.error(`UtilDT.commentMacro 无法找到注释 ${commentId}`);
216
- return;
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;
217
258
  }
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');
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}`);
226
263
  };
227
264
  plist.push(utils_1.UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\", "/")), queuefunc));
228
265
  }
@@ -236,18 +273,13 @@ var UtilDT;
236
273
  * @param opt.glob - 使用glob匹配而非文件路径
237
274
  */
238
275
  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
276
  const plist = [];
245
- const filePaths = parseMacroPaths(loc.filePath, opt);
277
+ const filePaths = parseMacroPaths(opt);
246
278
  for (const filePath of filePaths) {
247
279
  const queuefunc = async () => {
248
280
  await utils_1.UtilFT.ensurePathExists(filePath);
249
281
  const text = await readFile(filePath);
250
- const parseCode = await parseCodeText(codeText, { text, inent: '', filePath });
282
+ const parseCode = await parseCodeText(codeText, { matchId: '', text, inent: '', filePath });
251
283
  await fs.promises.writeFile(filePath, parseCode, 'utf-8');
252
284
  };
253
285
  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,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.38",
3
+ "version": "1.0.39",
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,9 @@ 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;
143
145
  /**展开宏的目标文件 */
144
146
  filePath:string;
145
147
  /**展开宏区域的原文本 */
@@ -148,54 +150,78 @@ type CdeeTextOpt = {
148
150
  inent:string;
149
151
  }
150
152
  //#region macro工具
151
- const parseMacroPaths = (basePath:string,opt?:MacroOpt)=>{
153
+ const parseMacroPaths = (opt?:MacroOpt)=>{
154
+ const loc = UtilFunc.getFuncLoc(3);
155
+ if(!loc && !opt?.filePath) throwError(`parseMacroPaths 未能找到函数位置`);
156
+ const basePath = loc?.filePath!;
152
157
  return opt?.filePath
153
158
  ? 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")];
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('\\','/')];
157
164
  }
158
165
  const readFile = async (basePath:string)=>
159
166
  (await fs.promises.readFile(basePath,'utf-8')).replaceAll("\r\n","\n");
160
- const parseCodeText = async (codeText:string|((opt:CdeeTextOpt)=>string|Promise<string>),opt:CdeeTextOpt)=>{
167
+ const parseCodeText = async (codeText:string|((opt:CodeTextOpt)=>string|Promise<string>),opt:CodeTextOpt)=>{
161
168
  const strText = typeof codeText === "function" ? await codeText(opt) : codeText;
162
169
  return strText.split('\n').map((line)=>`${opt.inent}${line}`).join('\n');
163
170
  }
171
+ const literalRegex = (str:string)=>new RegExp(
172
+ `^${str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')}(?!\\S)`);
164
173
  //#endregion
165
174
  /**将codeText写入对应region
166
175
  * @param regionId - 区域id \`//#region ${id}\`
167
176
  * @param codeText - 文本
168
177
  * @param opt - 可选参数
169
- * @param opt.targetPath - 目标文件 默认为去除".macro"的同名文件
178
+ * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
179
+ * @param opt.glob - 使用glob匹配而非文件路径
170
180
  */
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
- }
181
+ export async function regionMacro(regionId:string|RegExp,codeText:string|((opt:CodeTextOpt)=>string|Promise<string>),opt?:MacroOpt){
177
182
  const plist:Promise<void>[] = [];
178
- const filePaths = parseMacroPaths(loc.filePath,opt);
183
+ const filePaths = parseMacroPaths(opt);
179
184
  for(const filePath of filePaths){
180
185
  const queuefunc = async ()=>{
181
186
  if(!(await UtilFT.pathExists(filePath))) {
182
187
  SLogger.error(`UtilDT.regionMacro ${filePath} 不存在`);
183
188
  return
184
189
  }
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;
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;
194
221
  }
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');
222
+ if(hasMatch)
223
+ await fs.promises.writeFile(filePath, fileText, 'utf-8');
224
+ else if(!opt?.glob) SLogger.error(`UtilDT.regionMacro 无法找到区域 ${regionId}`);
199
225
  }
200
226
  plist.push(UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\","/")),queuefunc))
201
227
  }
@@ -208,38 +234,51 @@ export async function regionMacro(regionId:string,codeText:string|(()=>string|Pr
208
234
  * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
209
235
  * @param opt.glob - 使用glob匹配而非文件路径
210
236
  */
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
- }
237
+ export async function commentMacro(commentId:string|RegExp,codeText:string|((opt:CodeTextOpt)=>string|Promise<string>),opt?:MacroOpt){
217
238
  const plist:Promise<void>[] = [];
218
- const filePaths = parseMacroPaths(loc.filePath,opt);
239
+ const filePaths = parseMacroPaths(opt);
219
240
  for(const filePath of filePaths){
220
241
  const queuefunc = async ()=>{
221
242
  if(!(await UtilFT.pathExists(filePath))) {
222
243
  SLogger.error(`UtilDT.commentMacro ${filePath} 不存在`);
223
244
  return
224
245
  }
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;
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;
240
278
  }
241
- const ntext = text.replace(getregex(), `$1$2\n${parseCode}`);
242
- await fs.promises.writeFile(filePath, ntext, 'utf-8');
279
+ if(hasMatch)
280
+ await fs.promises.writeFile(filePath, fileText, 'utf-8');
281
+ else if(!opt?.glob) SLogger.error(`UtilDT.commentMacro 无法找到注释 ${commentId}`);
243
282
  }
244
283
  plist.push(UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\","/")),queuefunc))
245
284
  }
@@ -251,19 +290,14 @@ export async function commentMacro(commentId:string,codeText:string|(()=>string|
251
290
  * @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
252
291
  * @param opt.glob - 使用glob匹配而非文件路径
253
292
  */
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
- }
293
+ export async function fileMacro(codeText:string|((opt:CodeTextOpt)=>string|Promise<string>),opt?:MacroOpt){
260
294
  const plist:Promise<void>[] = [];
261
- const filePaths = parseMacroPaths(loc.filePath,opt);
295
+ const filePaths = parseMacroPaths(opt);
262
296
  for(const filePath of filePaths){
263
297
  const queuefunc = async ()=>{
264
298
  await UtilFT.ensurePathExists(filePath);
265
299
  const text = await readFile(filePath);
266
- const parseCode = await parseCodeText(codeText,{text,inent:'',filePath});
300
+ const parseCode = await parseCodeText(codeText,{matchId:'',text,inent:'',filePath});
267
301
  await fs.promises.writeFile(filePath, parseCode, 'utf-8');
268
302
  }
269
303
  plist.push(UtilFunc.queueProc(path.posix.normalize(filePath.replaceAll("\\","/")),queuefunc))
@@ -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 *