@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.
- package/dist/Macro.macro.d.ts +1 -0
- package/dist/Macro.macro.js +3 -0
- package/dist/QuickFunc.d.ts +1 -1
- package/dist/QuickFunc.js +2 -2
- package/dist/UtilDevTool.d.ts +34 -5
- package/dist/UtilDevTool.js +148 -32
- package/dist/UtilMacro.d.ts +7 -0
- package/dist/UtilMacro.js +30 -0
- package/dist/index.js +1 -0
- package/package.json +3 -2
- package/src/Macro.macro.ts +4 -0
- package/src/QuickFunc.ts +3 -1
- package/src/UtilDevTool.ts +165 -36
- package/src/UtilMacro.ts +24 -0
- package/src/index.ts +4 -3
- package/data/tsconfig.compile.json +0 -4
- package/data/tsconfig.json +0 -22
- package/tsconfig.compile.json +0 -4
- package/tsconfig.json +0 -22
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
package/dist/QuickFunc.d.ts
CHANGED
@@ -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;
|
package/dist/UtilDevTool.d.ts
CHANGED
@@ -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
|
-
|
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.
|
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
|
89
|
+
export function fileMacro(codeText: string | ((opt: CodeTextOpt) => string | Promise<string>), opt?: MacroOpt): Promise<void>;
|
61
90
|
export {};
|
62
91
|
}
|
package/dist/UtilDevTool.js
CHANGED
@@ -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}')
|
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.
|
160
|
+
* @param opt.filePath - 目标文件 默认为去除".macro"的同名文件
|
161
|
+
* @param opt.glob - 使用glob匹配而非文件路径
|
140
162
|
*/
|
141
163
|
async function regionMacro(regionId, codeText, opt) {
|
142
|
-
const
|
143
|
-
|
144
|
-
|
145
|
-
|
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,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
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@zwa73/dev-utils",
|
3
|
-
"version": "1.0.
|
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.
|
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",
|
package/src/QuickFunc.ts
CHANGED
package/src/UtilDevTool.ts
CHANGED
@@ -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,
|
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}')
|
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
|
-
|
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.
|
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
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
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
|
-
|
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
|
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
|
}
|
package/src/UtilMacro.ts
ADDED
@@ -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 *
|
package/data/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
|
-
}
|
package/tsconfig.compile.json
DELETED
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
|
-
}
|