js-dev-tool 1.0.13 → 1.0.15

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/README.md CHANGED
@@ -37,12 +37,13 @@ rws help: (R)ecord(W)ebpack(S)ize
37
37
  dest - if not specified then apply "./logs/webpack-size.json"
38
38
 
39
39
  cjbm help: (C)onvert (J)S to (B)rowser (M)odule
40
- ex - jstool -cmd cjbm [-root ./build | -basePath "./dist/esm,extra-tests/mini-semaphore"] [-ext js] [-targets "['core.js', 'object.js']"]
40
+ ex - jstool -cmd cjbm [-root ./build | -basePath "./dist/esm,extra-tests/mini-semaphore"] [-ext js] [-test /\.js$/] [-targets "['core.js', 'object.js']"]
41
41
  note:
42
42
  root - Recursively searches for files.
43
43
  This option is useful, but if there are directories that need to be avoided, use the 'basePath' option
44
44
  basePath - can be "<path>,<path>,..." (array type arg)
45
45
  ext - specifies the module extension for import clauses. default is "js"
46
+ test - Any file extension can be specified. (The default is /\.js$/)
46
47
  targets - specify this if you want to apply it only to a specific file.
47
48
  the file specified here should be directly under `basePath`!
48
49
  value must be array type arg, "['<path>', '<path>',...]" or "<path>,<path>,..."
@@ -75,12 +76,15 @@ minify help: jstool -cmd minify -basePath extra-tests/web/mini-semaphore [-test
75
76
  test - can be omit, default is `/\.js$/`
76
77
  suffix - can be omit, default is ".mini"
77
78
 
78
- rmc help: $ jstool -cmd rmc -basePath "./dist/cjs,./dist/cjs/gulp" -test "/\.(js|d\.ts)$/"
79
+ rmc help: $ jstool -cmd rmc [-rmc4ts[:keepBangLine]] -basePath "./dist/cjs,./dist/cjs/gulp" -test "/\.(js|d\.ts)$/"
79
80
  note: basePath - can be "<path>,<path>,..." (array type arg)
80
- test - can be omit, defulat `/.js$/`
81
- rmc4ts - for typescript source.
81
+ test - can be omit, defulat `/.js$/`
82
+ rmc4ts- for typescript source.
82
83
  keep comment that start with "/*" when "*/" end mark appears in same line.
83
84
  if start with "/*-" remove it
85
+ rmc4ts=keepBangLine (2025/12/24)
86
+ - In addition to the "rmc4ts" processing, it also preserves line comments that start with "//!".
87
+
84
88
  ```
85
89
 
86
90
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-dev-tool",
3
- "version": "1.0.13",
3
+ "version": "1.0.15",
4
4
  "bin": {
5
5
  "jstool": "tools.js"
6
6
  },
package/regex.d.ts CHANGED
@@ -8,14 +8,32 @@
8
8
  /**
9
9
  * @file js-dev-scripts/regex.d.ts
10
10
  */
11
+ declare global {
12
+ interface RegExpConstructor {
13
+ new <const P extends string, const F extends string = "">(pattern: string, flags?: F): RegExp & {
14
+ readonly source: P;
15
+ readonly flags: F;
16
+ };
17
+ <const P extends string, const F extends string = "">(pattern: string, flags?: F): RegExp & {
18
+ readonly source: P;
19
+ readonly flags: F;
20
+ };
21
+ readonly "prototype": RegExp;
22
+ }
23
+ }
11
24
  /**
12
25
  * Extracts the literal type from the source property of a RegExp.
13
26
  * @template R - A RegExp type.
14
27
  */
15
28
  export type ReSource<R extends RegExp> = R extends RegExp & { readonly source: infer T } ? T : never;
16
- export declare function createRegExp<P extends string>(pattern: P, flags?: string): RegExp & {
29
+ export type TypedRegExp<const P extends string, const F extends string = ""> = RegExp & {
17
30
  readonly source: P;
31
+ readonly flags: F;
18
32
  };
33
+ export declare function createRegExp<
34
+ const P extends string,
35
+ const F extends string = ""
36
+ >(pattern: P, flags?: F): TypedRegExp<P, F>;
19
37
  type FirstChar<S extends string> = S extends `${infer F}${infer _}` ? F : never;
20
38
  /**
21
39
  * Recursively extracts parts that match the format (?<GroupName>...) from a string pattern,
@@ -38,25 +56,37 @@ export type ExtractGroupNames<S extends string> =
38
56
  export type ReGroups<R extends RegExp> = {
39
57
  [K in ExtractGroupNames<ReSource<R>>]?: string;
40
58
  };
59
+ /**
60
+ * Preprocesses escape sequences in a string pattern by replacing escaped backslashes and characters.
61
+ *
62
+ * + NOTE: This type is used to preprocess the pattern string before counting capture groups.
63
+ *
64
+ * @template S - A string pattern.
65
+ * @template Result - The resulting string after preprocessing.
66
+ * @internal
67
+ */
68
+ export type __PreprocessEscapes<S extends string, Result extends string = ""> =
69
+ S extends `\\\\${infer Rest}`
70
+ ? __PreprocessEscapes<Rest, `${Result}__`>
71
+ : S extends `\\${infer Next}${infer Rest}`
72
+ ? __PreprocessEscapes<Rest, `${Result}_!`>
73
+ : S extends `${infer Char}${infer Rest}`
74
+ ? __PreprocessEscapes<Rest, `${Result}${Char}`>
75
+ : Result;
41
76
  /**
42
77
  * Counts the exact number of capture groups in a string pattern.
43
78
  * @template S - A string pattern.
44
79
  * @template Counter - An array used to count the capture groups.
45
- *
46
- * @todo FIXME: 多く count してしまう場合あり. 2025/3/18 15:47:57
47
- * @deprecated text base の parse には限界があり cost が見合わないので、この type は将来削除予定!
48
80
  */
49
- export type CountCaptureGroups<S extends string, Counter extends unknown[] = []> =
50
- S extends `${infer _Before}(${infer Rest}`
51
- ? Rest extends `?:${infer After}`
52
- ? CountCaptureGroups<After, Counter>
53
- : Rest extends `?=${infer After}`
54
- | `?!${infer After}`
55
- | `?<=${infer After}`
56
- | `?<!${infer After}`
57
- ? CountCaptureGroups<After, Counter>
58
- : CountCaptureGroups<Rest, [...Counter, unknown]>
59
- : Counter['length'];
81
+ export type CountCaptureGroups<
82
+ S extends string,
83
+ Counter extends unknown[] = []
84
+ > =
85
+ __PreprocessEscapes<S> extends `${infer _Before}(${infer Rest}`
86
+ ? Rest extends `${"?:" | "?=" | "?!" | "?<=" | "?<!"}${infer After}`
87
+ ? CountCaptureGroups<After, Counter>
88
+ : CountCaptureGroups<Rest, [...Counter, unknown]>
89
+ : Counter['length'];
60
90
  /**
61
91
  * Represents a fixed version of RegExpExecArray that includes the matched string,
62
92
  * captures, and optionally named groups.
@@ -70,6 +100,8 @@ export type RegExpExecArrayFixed<
70
100
  GroupCount extends number = CountCaptureGroups<S>
71
101
  > = [match: string, ...ExtractCaptures<GroupCount>] & {
72
102
  groups?: ReGroups<R>;
103
+ index: number;
104
+ input: string;
73
105
  };
74
106
  /**
75
107
  * Generates an array type with a length corresponding to the number of capture groups.
@@ -79,9 +111,30 @@ export type RegExpExecArrayFixed<
79
111
  export type ExtractCaptures<Count extends number, Result extends unknown[] = []> =
80
112
  Result['length'] extends Count
81
113
  ? Result : ExtractCaptures<Count, [...Result, string]>;
82
- const re1 = createRegExp("(test)(group)", "g");
114
+ /**
115
+ * Creates the parameter types for String.replace callback function.
116
+ *
117
+ * @example
118
+ * type Params = ReplaceCallbackParams<typeof myRegex>;
119
+ * // [match: string, ...captures: string[], offset: number, string: string, groups?: {...}]
120
+ */
121
+ export type ReplaceCallbackParams<
122
+ R extends RegExp,
123
+ S extends ReSource<R> = ReSource<R>,
124
+ GroupCount extends number = CountCaptureGroups<S>
125
+ > = [
126
+ match: string,
127
+ ...captures: ExtractCaptures<GroupCount>,
128
+ offset: number,
129
+ input: string,
130
+ groups: ReGroups<R>
131
+ ];
132
+ export type ReplacerFunctionSignature<R extends RegExp> = (...args: ReplaceCallbackParams<R>) => string;
133
+ const re1 = createRegExp("(test)(group)()()()()()()()(22)", "g");
134
+ type TRe1Replacer = ReplacerFunctionSignature<typeof re1>;
83
135
  type ExecResult1 = RegExpExecArrayFixed<typeof re1>;
84
136
  const re2 = createRegExp("(?<name1>test)(?<name2>group)", "g");
137
+ type TRe2Replacer = ReplacerFunctionSignature<typeof re2>;
85
138
  type ExecResult2 = RegExpExecArrayFixed<typeof re2>;
86
139
  const result = re2.exec("test group") as RegExpExecArrayFixed<typeof re2>;
87
140
  if (result) {
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "1.0.13"
2
+ "version": "1.0.15"
3
3
  }
package/tool-lib/cjbm.js CHANGED
@@ -6,7 +6,6 @@
6
6
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7
7
  */
8
8
  /// <reference path="./tools.d.ts"/>
9
- /// <reference path="../regex.d.ts"/>
10
9
  // @ts-check
11
10
  /**
12
11
  * @file (C)onvert (J)S to (B)rowser (M)odule
@@ -14,44 +13,25 @@
14
13
  const fs = require("fs");
15
14
  const path = require("path");
16
15
  /**
17
- * @import * as Regex from "../regex.d.ts";
16
+ * @type {typeof XRegex.createRegExp}
18
17
  */
19
- const RE_TEXT = String.raw`
20
- # NOTE: PCRE での検証時は line comment assertion を (?<!\/\/|\/\/\s)(?:(?<!@)import|export) とすること (regex101.com)
21
- # 正しくは: (?<!\s*\/\/+.*?)(?:(?<!@)import|export)
22
- (?<!\s*\/\/+.*?)(?:(?<!@)import|export)
23
- \s*
24
- (?:
25
- # 2025/12/22 14:57:44 - support quote character detection ["']
26
- # global import, import "./"; import './global.mjs';
27
- (?<qcGlobal>["'])(?!https?:)(?=[.\/]+)(?:
28
- (?<globalName>(?:[.\/]+)?[^'"]+?)(?:\.(?<globalExt>(?:c|m)?jsx?))?
29
- )\k<qcGlobal>|
30
- # dynamic import, import("...") import('...')
31
- \(\s*
32
- (?<qcDynamic>["'])(?!https?:)(?=[.\/]+)(?<dynamicName>(?:[.\/]+)?[^'"]+?)(?:\.(?<dynamicExt>(?:c|m)?jsx?))?\k<qcDynamic>
33
- \s*\)|
34
- # esm import/export
35
- (?:(?<clause>.+?|(?:\w+\s*,)?\s*\{[^}]+\})\s*from)\s*
36
- (?<qcEsm>["'])(?!https?:)(?=[.\/]+)
37
- (?:
38
- (?<moduleName>(?:[.\/]+)?[^'"]+?)(?:\.(?<moduleExt>(?:c|m)?jsx?))?
39
- )\k<qcEsm>
40
- )
41
- (?=\s*;)?
42
- `;
18
+ function createRegExp(pattern, flags) {
19
+ return new RegExp(pattern, flags);
20
+ }
21
+ const reImportExportDetection = createRegExp(
22
+ `(?<!\\s*\\/\\/+.*?)(?:(?<!@)import|export)\\s*(?:(?<qcGlobal>["'])(?!https?:)(?=[.\\/]+)\
23
+ (?:(?<globalName>(?:[.\\/]+)?[^'"]+?)(?:\\.(?<globalExt>(?:c|m)?jsx?))?)\\k<qcGlobal>|\\(\\s*(?<qcDynamic>["'])(?!https?:)(?=[.\\/]+)(?<dynamicName>(?:[.\\/]+)?[^'"]+?)\
24
+ (?:\\.(?<dynamicExt>(?:c|m)?jsx?))?\\k<qcDynamic>\\s*\\)|(?:(?<clause>.+?|(?:\\w+\\s*,)?\\s*\\{[^}]+\\})\\s*from)\\s*(?<qcEsm>["'])(?!https?:)(?=[.\\/]+)\
25
+ (?:(?<moduleName>(?:[.\\/]+)?[^'"]+?)(?:\\.(?<moduleExt>(?:c|m)?jsx?))?)\\k<qcEsm>)(?=\\s*;)?`, "g"
26
+ );
43
27
  /**
44
- * @date 2025/12/22 16:09:36
45
- * @see https://regex101.com/r/uMMsD4/31
28
+ * @typedef {XRegex.ReplacerFunctionSignature<typeof reImportExportDetection>} TImportExportDetectRegexReplacer
46
29
  */
47
- const reImportExportDetection = new RegExp(
48
- RE_TEXT.replace(/\s*\(\?\#.*\)\s*$|(?<!\\)\#\s*.*$|\s+/gm, ""), "g",
49
- );
50
30
  /**
51
31
  * Generates a replacer function to update import/export statements with a new file extension.
52
32
  *
53
33
  * @param {string} ext - The new file extension to use.
54
- * @returns {TRegexImportExportDetectorReplacer} A function to update import/export statements with the specified file extension.
34
+ * @returns {TImportExportDetectRegexReplacer} A function to update import/export statements with the specified file extension.
55
35
  * @date 2025/2/16 18:38:39
56
36
  * @date 2025/12/22 16:05:13 - ./tool-lib/cjbm-resources/cjbm-browser-test.mjs を参照
57
37
  */
@@ -60,11 +40,18 @@ function getReplacer(ext) {
60
40
  * NOTE: Replacement is only performed with the syntax "$` is $1".
61
41
  * String concatenation is not allowed.
62
42
  */
63
- /** @type {TRegexImportExportDetectorReplacer} */
64
- const replacer = (
65
- $0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _o, _s, { clause, dynamicName, globalName, moduleName, qcDynamic, qcEsm, qcGlobal }
43
+ /** @type {TImportExportDetectRegexReplacer} */
44
+ return (
45
+ match, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _offset, _input, groups
66
46
  ) => {
67
- const kw = $0.startsWith("import") ? "import" : "export";
47
+ const {
48
+ clause,
49
+ dynamicName,
50
+ globalName,
51
+ moduleName,
52
+ qcDynamic, qcEsm, qcGlobal,
53
+ } = groups;
54
+ const kword = match.startsWith("import") ? "import" : "export";
68
55
  const qc = qcDynamic || qcEsm || qcGlobal;
69
56
  let whichName = /** @type {string} */ (
70
57
  globalName || moduleName || dynamicName
@@ -72,9 +59,16 @@ function getReplacer(ext) {
72
59
  if (whichName[whichName.length - 1] === "/") {
73
60
  whichName += "index";
74
61
  }
75
- return `${kw}${globalName? ` ${qc}${whichName}.${ext}${qc}`: clause? ` ${clause} from ${qc}${whichName}.${ext}${qc}`: `(${qc}${whichName}.${ext}${qc})`}`;
62
+ const modId = `${qc}${whichName}.${ext}${qc}`;
63
+ return `${kword}${
64
+
65
+ globalName ? ` ${modId}` :
66
+
67
+ clause? ` ${clause} from ${modId}` :
68
+
69
+ `(${modId})`
70
+ }`;
76
71
  };
77
- return replacer;
78
72
  }
79
73
  /**
80
74
  * @param {string} ext
@@ -6,21 +6,10 @@
6
6
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7
7
  */
8
8
  /// <reference path="../regex.d.ts"/>
9
- declare const ImportExportDetectRegex = `(?<!\\s*\\/\\/+.*?)(?:(?<!@)import|export)\\s*(?:(?<qcGlobal>["'])(?!https?:)(?=[.\\/]+)\
10
- (?:(?<globalName>(?:[.\\/]+)?[^'"]+?)(?:\\.(?<globalExt>(?:c|m)?jsx?))?)\\k<qcGlobal>|\\(\\s*(?<qcDynamic>["'])(?!https?:)(?=[.\\/]+)(?<dynamicName>(?:[.\\/]+)?[^'"]+?)\
11
- (?:\\.(?<dynamicExt>(?:c|m)?jsx?))?\\k<qcDynamic>\\s*\\)|(?:(?<clause>.+?|(?:\\w+\\s*,)?\\s*\\{[^}]+\\})\\s*from)\\s*(?<qcEsm>["'])(?!https?:)(?=[.\\/]+)\
12
- (?:(?<moduleName>(?:[.\\/]+)?[^'"]+?)(?:\\.(?<moduleExt>(?:c|m)?jsx?))?)\\k<qcEsm>)(?=\\s*;)?`;
13
- declare const reOk: ReturnType<typeof XRegex.createRegExp<typeof ImportExportDetectRegex>>;
14
- type TRegexDetectRet = XRegex.ReGroups<typeof reOk>;
15
9
  /**
16
10
  * @date 2023-10-25
17
11
  */
18
12
  declare global {
19
- type TRegexImportExportDetectorReplacer = function(
20
- string, string, string, string, string, string, string, string, string, string, string,
21
- number, string,
22
- TRegexDetectRet
23
- ): string;
24
13
  declare function processSources(
25
14
  taskName: string,
26
15
  process: (source: string) => Promise<string> | string,
@@ -87,7 +76,7 @@ declare global {
87
76
  /** replace */
88
77
  regex: RegExp;
89
78
  /** rmc */
90
- rmc4ts: boolean;
79
+ rmc4ts: boolean | "keepBangLine";
91
80
  /**
92
81
  * webpacked source path.
93
82
  * @default `./dist/webpack/index.js`
package/tools.js CHANGED
@@ -206,9 +206,12 @@ const ToolFunctions = {
206
206
  fn() {
207
207
  const rmc = require("rm-cstyle-cmts");
208
208
  if (params.rmc4ts) {
209
+ const keepBangLine = params.rmc4ts === "keepBangLine";
209
210
  rmc.setListener(({ event, fragment }) => {
210
211
  if (event === /*EScannerEvent.MultiLineComment*/ 1) {
211
212
  return /^\/\*(\*|!)\s|^\/\*(?!-).+\*\/$/.test(fragment);
213
+ } else if (keepBangLine && event === /*EScannerEvent.SingleLineComment*/0) {
214
+ return /^\/\/+!/.test(fragment);
212
215
  }
213
216
  return false;
214
217
  });
@@ -228,12 +231,14 @@ const ToolFunctions = {
228
231
  },
229
232
  );
230
233
  },
231
- help: `$ jstool -cmd rmc -basePath "./dist/cjs,./dist/cjs/gulp" -test "/\\.(js|d\\.ts)$/"
234
+ help: `$ jstool -cmd rmc [-rmc4ts[:keepBangLine]] -basePath "./dist/cjs,./dist/cjs/gulp" -test "/\\.(js|d\\.ts)$/"
232
235
  note: basePath - can be "<path>,<path>,..." (array type arg)
233
- test - can be omit, defulat \`/\.js$/\`
234
- rmc4ts - for typescript source.
236
+ test - can be omit, defulat \`/\.js$/\`
237
+ rmc4ts- for typescript source.
235
238
  keep comment that start with "/*" when "*/" end mark appears in same line.
236
239
  if start with "/*-" remove it
240
+ rmc4ts=keepBangLine (2025/12/24)
241
+ - In addition to the "rmc4ts" processing, it also preserves line comments that start with "//!".
237
242
  `,
238
243
  },
239
244
  backup: {