@wrongstack/plugins 0.285.0 → 0.286.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/accessibility-auditor/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAQ/C,MAAM,MAAM,QAAQ,GAChB,aAAa,GACb,qBAAqB,GACrB,0BAA0B,GAC1B,qBAAqB,GACrB,cAAc,CAAC;AAEnB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB;AA6SD,QAAA,MAAM,MAAM,EAAE,MA0Nb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/accessibility-auditor/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAQ/C,MAAM,MAAM,QAAQ,GAChB,aAAa,GACb,qBAAqB,GACrB,0BAA0B,GAC1B,qBAAqB,GACrB,cAAc,CAAC;AAEnB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB;AAwSD,QAAA,MAAM,MAAM,EAAE,MA0Nb,CAAC;eAEa,MAAM"}
@@ -119,24 +119,21 @@ function auditFile(filePath, projectRoot) {
119
119
  for (let i = 0; i < lines.length; i++) {
120
120
  const line = lines[i];
121
121
  const lineNo = i + 1;
122
- let idMatch;
123
- while ((idMatch = ATTR_ID.exec(line)) !== null) {
122
+ for (const idMatch of line.matchAll(ATTR_ID)) {
124
123
  const id = idMatch[1];
125
124
  const list = idsByValue.get(id) ?? [];
126
125
  list.push(lineNo);
127
126
  idsByValue.set(id, list);
128
127
  }
129
128
  ATTR_ID.lastIndex = 0;
130
- let imgMatch;
131
- while ((imgMatch = TAG_IMG.exec(line)) !== null) {
129
+ for (const imgMatch of line.matchAll(TAG_IMG)) {
132
130
  const tag = imgMatch[0];
133
131
  if (!hasMeaningfulAlt(tag)) {
134
132
  add(lineNo, "missing-alt", "error", "<img> is missing meaningful alt text");
135
133
  }
136
134
  }
137
135
  TAG_IMG.lastIndex = 0;
138
- let inputMatch;
139
- while ((inputMatch = TAG_INPUT.exec(line)) !== null) {
136
+ for (const inputMatch of line.matchAll(TAG_INPUT)) {
140
137
  const tag = inputMatch[0];
141
138
  const typeMatch = tag.match(/\btype\s*=\s*["']?([^"'\s>]*)["']?/i);
142
139
  const type = typeMatch ? typeMatch[1].toLowerCase() : "text";
@@ -161,8 +158,7 @@ function auditFile(filePath, projectRoot) {
161
158
  }
162
159
  }
163
160
  TAG_INPUT.lastIndex = 0;
164
- let buttonMatch;
165
- while ((buttonMatch = TAG_BUTTON.exec(line)) !== null) {
161
+ for (const buttonMatch of line.matchAll(TAG_BUTTON)) {
166
162
  const tag = buttonMatch[0];
167
163
  const inner = buttonMatch[1] ?? "";
168
164
  const hasText = inner.replace(/\s+/g, "").length > 0;
@@ -173,8 +169,7 @@ function auditFile(filePath, projectRoot) {
173
169
  }
174
170
  }
175
171
  TAG_BUTTON.lastIndex = 0;
176
- let inputButtonMatch;
177
- while ((inputButtonMatch = INPUT_BUTTON.exec(line)) !== null) {
172
+ for (const inputButtonMatch of line.matchAll(INPUT_BUTTON)) {
178
173
  const tag = inputButtonMatch[0];
179
174
  if (!ATTR_VALUE.test(tag) && !ATTR_ARIA_LABEL.test(tag) && !ATTR_TITLE.test(tag)) {
180
175
  add(lineNo, "missing-button-text", "error", `<input type="${inputButtonMatch[1]}"> is missing value/aria-label/title`);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auto-i18n-extractor/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAiL/C,QAAA,MAAM,MAAM,EAAE,MAsQb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auto-i18n-extractor/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAgL/C,QAAA,MAAM,MAAM,EAAE,MAsQb,CAAC;eAEa,MAAM"}
@@ -83,8 +83,7 @@ function extractStrings(content, cfg) {
83
83
  for (let i = 0; i < lines.length; i += 1) {
84
84
  const line = lines[i];
85
85
  stringRegex.lastIndex = 0;
86
- let match;
87
- while ((match = stringRegex.exec(line)) !== null) {
86
+ for (const match of line.matchAll(stringRegex)) {
88
87
  const value = match[2] ?? "";
89
88
  const quoteIndex = match.index + (match[1]?.length ?? 1);
90
89
  if (!looksLikeUserText(value, cfg.minLength)) continue;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/code-metrics/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA8P/C,QAAA,MAAM,MAAM,EAAE,MAgMb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/code-metrics/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA4P/C,QAAA,MAAM,MAAM,EAAE,MAgMb,CAAC;eAEa,MAAM"}
@@ -85,33 +85,31 @@ function countFunctions(content) {
85
85
  const declRe = /\bfunction\s+[A-Za-z_$][A-Za-z0-9_$]*\s*\(/g;
86
86
  const methodRe = /\b[A-Za-z_$][A-Za-z0-9_$]*\s*\([^)]*\)\s*\{/g;
87
87
  const arrowRe = /=>\s*(?:\{|\(|[^\s;{}])/g;
88
- let m;
89
88
  declRe.lastIndex = 0;
90
- while ((m = declRe.exec(content)) !== null) count++;
89
+ for (const _match of content.matchAll(declRe)) count++;
91
90
  methodRe.lastIndex = 0;
92
- while ((m = methodRe.exec(content)) !== null) {
93
- const prefix = content.slice(0, m.index).trimEnd();
91
+ for (const match of content.matchAll(methodRe)) {
92
+ const prefix = content.slice(0, match.index).trimEnd();
94
93
  if (/\bfunction\s*$/.test(prefix)) continue;
95
94
  count++;
96
95
  }
97
96
  arrowRe.lastIndex = 0;
98
- while ((m = arrowRe.exec(content)) !== null) count++;
97
+ for (const _match of content.matchAll(arrowRe)) count++;
99
98
  return count;
100
99
  }
101
100
  function countComplexity(content) {
102
101
  const controlRe = /\b(if|else\s+if|for|while|switch|catch)\b/g;
103
102
  const operatorRe = /[?&|]/g;
104
103
  let complexity = 0;
105
- let m;
106
104
  controlRe.lastIndex = 0;
107
- while ((m = controlRe.exec(content)) !== null) complexity++;
105
+ for (const _match of content.matchAll(controlRe)) complexity++;
108
106
  operatorRe.lastIndex = 0;
109
- while ((m = operatorRe.exec(content)) !== null) {
110
- const ch = m[0];
107
+ for (const match of content.matchAll(operatorRe)) {
108
+ const ch = match[0];
111
109
  if (ch === "?") {
112
110
  complexity++;
113
111
  } else {
114
- const next = content[m.index + 1];
112
+ const next = content[match.index + 1];
115
113
  if (next === ch) complexity++;
116
114
  }
117
115
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dead-code-detector/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA2Q/C,QAAA,MAAM,MAAM,EAAE,MAkOb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dead-code-detector/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAyQ/C,QAAA,MAAM,MAAM,EAAE,MAkOb,CAAC;eAEa,MAAM"}
@@ -73,9 +73,8 @@ var DECLARATION_EXPORT_RE = /export\s+(?:async\s+|abstract\s+)?(?:const|let|var|
73
73
  var NAMED_EXPORT_RE = /export\s*\{([^}]+)\}/g;
74
74
  function extractExports(content, filePath) {
75
75
  const exports = [];
76
- let match;
77
76
  DECLARATION_EXPORT_RE.lastIndex = 0;
78
- while ((match = DECLARATION_EXPORT_RE.exec(content)) !== null) {
77
+ for (const match of content.matchAll(DECLARATION_EXPORT_RE)) {
79
78
  exports.push({
80
79
  identifier: match[1],
81
80
  file: filePath,
@@ -84,7 +83,7 @@ function extractExports(content, filePath) {
84
83
  });
85
84
  }
86
85
  NAMED_EXPORT_RE.lastIndex = 0;
87
- while ((match = NAMED_EXPORT_RE.exec(content)) !== null) {
86
+ for (const match of content.matchAll(NAMED_EXPORT_RE)) {
88
87
  const line = lineNumber(content, match.index);
89
88
  const names = match[1].split(",").map((s) => s.trim()).filter(Boolean);
90
89
  for (const name of names) {
@@ -227,7 +226,7 @@ var plugin = {
227
226
  let result;
228
227
  try {
229
228
  result = scan(scanRoot, 1, cfg);
230
- } catch (err) {
229
+ } catch {
231
230
  state.errorCount += 1;
232
231
  return;
233
232
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/feature-flag-tracker/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAQ/C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AA8LD,QAAA,MAAM,MAAM,EAAE,MA+Mb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/feature-flag-tracker/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAQ/C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AA6LD,QAAA,MAAM,MAAM,EAAE,MA+Mb,CAAC;eAEa,MAAM"}
@@ -98,8 +98,7 @@ function scanFile(filePath, content, patterns, maxFindings) {
98
98
  const lines = content.split(/\r?\n/);
99
99
  for (const re of patterns) {
100
100
  re.lastIndex = 0;
101
- let m;
102
- while ((m = re.exec(content)) !== null) {
101
+ for (const m of content.matchAll(re)) {
103
102
  const flag = m[1] ?? m[0];
104
103
  const lineNo = content.slice(0, m.index).split(/\r?\n/).length;
105
104
  const context = (lines[lineNo - 1] ?? "").trim();
package/dist/index.js CHANGED
@@ -11815,7 +11815,7 @@ function runRunnerCommand(argv, options) {
11815
11815
  });
11816
11816
  return;
11817
11817
  }
11818
- let timedOut = false;
11818
+ const timedOut = false;
11819
11819
  let spawnErrored = false;
11820
11820
  const stdoutChunks = [];
11821
11821
  const stderrChunks = [];
@@ -13446,24 +13446,21 @@ function auditFile(filePath, projectRoot) {
13446
13446
  for (let i = 0; i < lines.length; i++) {
13447
13447
  const line = lines[i];
13448
13448
  const lineNo = i + 1;
13449
- let idMatch;
13450
- while ((idMatch = ATTR_ID.exec(line)) !== null) {
13449
+ for (const idMatch of line.matchAll(ATTR_ID)) {
13451
13450
  const id = idMatch[1];
13452
13451
  const list = idsByValue.get(id) ?? [];
13453
13452
  list.push(lineNo);
13454
13453
  idsByValue.set(id, list);
13455
13454
  }
13456
13455
  ATTR_ID.lastIndex = 0;
13457
- let imgMatch;
13458
- while ((imgMatch = TAG_IMG.exec(line)) !== null) {
13456
+ for (const imgMatch of line.matchAll(TAG_IMG)) {
13459
13457
  const tag = imgMatch[0];
13460
13458
  if (!hasMeaningfulAlt(tag)) {
13461
13459
  add(lineNo, "missing-alt", "error", "<img> is missing meaningful alt text");
13462
13460
  }
13463
13461
  }
13464
13462
  TAG_IMG.lastIndex = 0;
13465
- let inputMatch;
13466
- while ((inputMatch = TAG_INPUT.exec(line)) !== null) {
13463
+ for (const inputMatch of line.matchAll(TAG_INPUT)) {
13467
13464
  const tag = inputMatch[0];
13468
13465
  const typeMatch = tag.match(/\btype\s*=\s*["']?([^"'\s>]*)["']?/i);
13469
13466
  const type = typeMatch ? typeMatch[1].toLowerCase() : "text";
@@ -13488,8 +13485,7 @@ function auditFile(filePath, projectRoot) {
13488
13485
  }
13489
13486
  }
13490
13487
  TAG_INPUT.lastIndex = 0;
13491
- let buttonMatch;
13492
- while ((buttonMatch = TAG_BUTTON.exec(line)) !== null) {
13488
+ for (const buttonMatch of line.matchAll(TAG_BUTTON)) {
13493
13489
  const tag = buttonMatch[0];
13494
13490
  const inner = buttonMatch[1] ?? "";
13495
13491
  const hasText = inner.replace(/\s+/g, "").length > 0;
@@ -13500,8 +13496,7 @@ function auditFile(filePath, projectRoot) {
13500
13496
  }
13501
13497
  }
13502
13498
  TAG_BUTTON.lastIndex = 0;
13503
- let inputButtonMatch;
13504
- while ((inputButtonMatch = INPUT_BUTTON.exec(line)) !== null) {
13499
+ for (const inputButtonMatch of line.matchAll(INPUT_BUTTON)) {
13505
13500
  const tag = inputButtonMatch[0];
13506
13501
  if (!ATTR_VALUE.test(tag) && !ATTR_ARIA_LABEL.test(tag) && !ATTR_TITLE.test(tag)) {
13507
13502
  add(lineNo, "missing-button-text", "error", `<input type="${inputButtonMatch[1]}"> is missing value/aria-label/title`);
@@ -14174,8 +14169,7 @@ function extractStrings(content, cfg) {
14174
14169
  for (let i = 0; i < lines.length; i += 1) {
14175
14170
  const line = lines[i];
14176
14171
  stringRegex.lastIndex = 0;
14177
- let match;
14178
- while ((match = stringRegex.exec(line)) !== null) {
14172
+ for (const match of line.matchAll(stringRegex)) {
14179
14173
  const value = match[2] ?? "";
14180
14174
  const quoteIndex = match.index + (match[1]?.length ?? 1);
14181
14175
  if (!looksLikeUserText(value, cfg.minLength)) continue;
@@ -14509,33 +14503,31 @@ function countFunctions(content) {
14509
14503
  const declRe = /\bfunction\s+[A-Za-z_$][A-Za-z0-9_$]*\s*\(/g;
14510
14504
  const methodRe = /\b[A-Za-z_$][A-Za-z0-9_$]*\s*\([^)]*\)\s*\{/g;
14511
14505
  const arrowRe = /=>\s*(?:\{|\(|[^\s;{}])/g;
14512
- let m;
14513
14506
  declRe.lastIndex = 0;
14514
- while ((m = declRe.exec(content)) !== null) count++;
14507
+ for (const _match of content.matchAll(declRe)) count++;
14515
14508
  methodRe.lastIndex = 0;
14516
- while ((m = methodRe.exec(content)) !== null) {
14517
- const prefix = content.slice(0, m.index).trimEnd();
14509
+ for (const match of content.matchAll(methodRe)) {
14510
+ const prefix = content.slice(0, match.index).trimEnd();
14518
14511
  if (/\bfunction\s*$/.test(prefix)) continue;
14519
14512
  count++;
14520
14513
  }
14521
14514
  arrowRe.lastIndex = 0;
14522
- while ((m = arrowRe.exec(content)) !== null) count++;
14515
+ for (const _match of content.matchAll(arrowRe)) count++;
14523
14516
  return count;
14524
14517
  }
14525
14518
  function countComplexity(content) {
14526
14519
  const controlRe = /\b(if|else\s+if|for|while|switch|catch)\b/g;
14527
14520
  const operatorRe = /[?&|]/g;
14528
14521
  let complexity = 0;
14529
- let m;
14530
14522
  controlRe.lastIndex = 0;
14531
- while ((m = controlRe.exec(content)) !== null) complexity++;
14523
+ for (const _match of content.matchAll(controlRe)) complexity++;
14532
14524
  operatorRe.lastIndex = 0;
14533
- while ((m = operatorRe.exec(content)) !== null) {
14534
- const ch = m[0];
14525
+ for (const match of content.matchAll(operatorRe)) {
14526
+ const ch = match[0];
14535
14527
  if (ch === "?") {
14536
14528
  complexity++;
14537
14529
  } else {
14538
- const next = content[m.index + 1];
14530
+ const next = content[match.index + 1];
14539
14531
  if (next === ch) complexity++;
14540
14532
  }
14541
14533
  }
@@ -14833,9 +14825,8 @@ var DECLARATION_EXPORT_RE = /export\s+(?:async\s+|abstract\s+)?(?:const|let|var|
14833
14825
  var NAMED_EXPORT_RE = /export\s*\{([^}]+)\}/g;
14834
14826
  function extractExports2(content, filePath) {
14835
14827
  const exports = [];
14836
- let match;
14837
14828
  DECLARATION_EXPORT_RE.lastIndex = 0;
14838
- while ((match = DECLARATION_EXPORT_RE.exec(content)) !== null) {
14829
+ for (const match of content.matchAll(DECLARATION_EXPORT_RE)) {
14839
14830
  exports.push({
14840
14831
  identifier: match[1],
14841
14832
  file: filePath,
@@ -14844,7 +14835,7 @@ function extractExports2(content, filePath) {
14844
14835
  });
14845
14836
  }
14846
14837
  NAMED_EXPORT_RE.lastIndex = 0;
14847
- while ((match = NAMED_EXPORT_RE.exec(content)) !== null) {
14838
+ for (const match of content.matchAll(NAMED_EXPORT_RE)) {
14848
14839
  const line = lineNumber(content, match.index);
14849
14840
  const names = match[1].split(",").map((s) => s.trim()).filter(Boolean);
14850
14841
  for (const name of names) {
@@ -14987,7 +14978,7 @@ var plugin45 = {
14987
14978
  let result;
14988
14979
  try {
14989
14980
  result = scan(scanRoot, 1, cfg);
14990
- } catch (err) {
14981
+ } catch {
14991
14982
  state42.errorCount += 1;
14992
14983
  return;
14993
14984
  }
@@ -16119,8 +16110,7 @@ function scanFile(filePath, content, patterns, maxFindings) {
16119
16110
  const lines = content.split(/\r?\n/);
16120
16111
  for (const re of patterns) {
16121
16112
  re.lastIndex = 0;
16122
- let m;
16123
- while ((m = re.exec(content)) !== null) {
16113
+ for (const m of content.matchAll(re)) {
16124
16114
  const flag = m[1] ?? m[0];
16125
16115
  const lineNo = content.slice(0, m.index).split(/\r?\n/).length;
16126
16116
  const context = (lines[lineNo - 1] ?? "").trim();
@@ -16419,9 +16409,8 @@ function relativePath5(p) {
16419
16409
  var INTERFACE_RE = /(?:export\s+)?interface\s+([A-Za-z_$][A-Za-z0-9_$]*)/g;
16420
16410
  function extractInterfaceNames(content) {
16421
16411
  const names = [];
16422
- let m;
16423
16412
  INTERFACE_RE.lastIndex = 0;
16424
- while ((m = INTERFACE_RE.exec(content)) !== null) {
16413
+ for (const m of content.matchAll(INTERFACE_RE)) {
16425
16414
  names.push({ name: m[1], line: content.slice(0, m.index).split(/\r?\n/).length });
16426
16415
  }
16427
16416
  return names;
@@ -16689,8 +16678,7 @@ var INSTALL_RE3 = /(?:^|[;&|]\s*)(npm|pnpm|yarn|bun)\s+(?:install|i|add)\s+([^;&
16689
16678
  function parsePackageNames(command) {
16690
16679
  const names = [];
16691
16680
  INSTALL_RE3.lastIndex = 0;
16692
- let m;
16693
- while ((m = INSTALL_RE3.exec(command)) !== null) {
16681
+ for (const m of command.matchAll(INSTALL_RE3)) {
16694
16682
  const argString = m[2] ?? "";
16695
16683
  for (const token of argString.split(/\s+/)) {
16696
16684
  if (!token || token.startsWith("-")) continue;
@@ -17657,21 +17645,20 @@ function detectSmells(filePath, content, rules) {
17657
17645
  const lines = content.split(/\r?\n/);
17658
17646
  const stripped = content.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, " ");
17659
17647
  const functionLikeRe = /(?:export\s+)?(?:async\s+)?(?:function\s+)?([A-Za-z_$][A-Za-z0-9_$]*)\s*\(([^)]*)\)\s*\{/g;
17660
- let m;
17661
17648
  functionLikeRe.lastIndex = 0;
17662
- while ((m = functionLikeRe.exec(stripped)) !== null) {
17663
- const name = m[1];
17664
- const paramsRaw = m[2];
17649
+ for (const match of stripped.matchAll(functionLikeRe)) {
17650
+ const name = match[1];
17651
+ const paramsRaw = match[2];
17665
17652
  const params = paramsRaw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
17666
17653
  if (params.length > rules.maxParams) {
17667
17654
  suggestions.push({
17668
17655
  file: relativePath6(filePath),
17669
- line: content.slice(0, m.index).split(/\r?\n/).length,
17656
+ line: content.slice(0, match.index).split(/\r?\n/).length,
17670
17657
  type: "many-parameters",
17671
17658
  message: `${name} has ${params.length} parameters (limit ${rules.maxParams})`
17672
17659
  });
17673
17660
  }
17674
- const bodyStart = m.index + m[0].length;
17661
+ const bodyStart = match.index + match[0].length;
17675
17662
  let depth = 1;
17676
17663
  let lineEnd = bodyStart;
17677
17664
  for (let i = bodyStart; i < stripped.length && depth > 0; i++) {
@@ -17684,7 +17671,7 @@ function detectSmells(filePath, content, rules) {
17684
17671
  if (bodyLines > rules.longFunctionLines) {
17685
17672
  suggestions.push({
17686
17673
  file: relativePath6(filePath),
17687
- line: content.slice(0, m.index).split(/\r?\n/).length,
17674
+ line: content.slice(0, match.index).split(/\r?\n/).length,
17688
17675
  type: "long-function",
17689
17676
  message: `${name} spans ~${bodyLines} lines (limit ${rules.longFunctionLines})`
17690
17677
  });
@@ -17715,15 +17702,15 @@ function detectSmells(filePath, content, rules) {
17715
17702
  const magicRe = /\b-?\d+(?:\.\d+)?\b/g;
17716
17703
  const allowed = /* @__PURE__ */ new Set(["0", "1", "-1", "2"]);
17717
17704
  magicRe.lastIndex = 0;
17718
- while ((m = magicRe.exec(content)) !== null) {
17719
- const match = m[0];
17705
+ for (const magicNumberMatch of content.matchAll(magicRe)) {
17706
+ const match = magicNumberMatch[0];
17720
17707
  if (allowed.has(match)) continue;
17721
- const before = content[m.index - 1];
17722
- const after = content[m.index + match.length];
17708
+ const before = content[magicNumberMatch.index - 1];
17709
+ const after = content[magicNumberMatch.index + match.length];
17723
17710
  if (before === "[" && after === "]") continue;
17724
17711
  suggestions.push({
17725
17712
  file: relativePath6(filePath),
17726
- line: content.slice(0, m.index).split(/\r?\n/).length,
17713
+ line: content.slice(0, magicNumberMatch.index).split(/\r?\n/).length,
17727
17714
  type: "magic-number",
17728
17715
  message: `magic number ${match} should be a named constant`
17729
17716
  });
@@ -18520,7 +18507,7 @@ var PATTERNS4 = [
18520
18507
  {
18521
18508
  type: "hardcoded_http",
18522
18509
  severity: "medium",
18523
- regex: /http:\/\/[a-zA-Z0-9][^\s'"\)\\]*/i
18510
+ regex: /http:\/\/[a-zA-Z0-9][^\s'")\\]*/i
18524
18511
  },
18525
18512
  {
18526
18513
  type: "console_log_credentials",
@@ -19953,31 +19940,30 @@ function detectExports(content) {
19953
19940
  const arrowRe = /export\s+(?:const|let|var)\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*=\s*(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>/g;
19954
19941
  const classRe = /export\s+(?:abstract\s+)?class\s+([A-Za-z_$][A-Za-z0-9_$]*)/g;
19955
19942
  const namedRe = /export\s*\{([^}]+)\}/g;
19956
- let m;
19957
19943
  functionRe.lastIndex = 0;
19958
- while ((m = functionRe.exec(content)) !== null) {
19959
- if (!seen.has(m[1])) {
19960
- seen.add(m[1]);
19961
- exports.push({ name: m[1], kind: "function" });
19944
+ for (const match of content.matchAll(functionRe)) {
19945
+ if (!seen.has(match[1])) {
19946
+ seen.add(match[1]);
19947
+ exports.push({ name: match[1], kind: "function" });
19962
19948
  }
19963
19949
  }
19964
19950
  arrowRe.lastIndex = 0;
19965
- while ((m = arrowRe.exec(content)) !== null) {
19966
- if (!seen.has(m[1])) {
19967
- seen.add(m[1]);
19968
- exports.push({ name: m[1], kind: "arrow" });
19951
+ for (const match of content.matchAll(arrowRe)) {
19952
+ if (!seen.has(match[1])) {
19953
+ seen.add(match[1]);
19954
+ exports.push({ name: match[1], kind: "arrow" });
19969
19955
  }
19970
19956
  }
19971
19957
  classRe.lastIndex = 0;
19972
- while ((m = classRe.exec(content)) !== null) {
19973
- if (!seen.has(m[1])) {
19974
- seen.add(m[1]);
19975
- exports.push({ name: m[1], kind: "class" });
19958
+ for (const match of content.matchAll(classRe)) {
19959
+ if (!seen.has(match[1])) {
19960
+ seen.add(match[1]);
19961
+ exports.push({ name: match[1], kind: "class" });
19976
19962
  }
19977
19963
  }
19978
19964
  namedRe.lastIndex = 0;
19979
- while ((m = namedRe.exec(content)) !== null) {
19980
- const names = m[1].split(",").map((s) => s.trim()).filter(Boolean);
19965
+ for (const match of content.matchAll(namedRe)) {
19966
+ const names = match[1].split(",").map((s) => s.trim()).filter(Boolean);
19981
19967
  for (const raw of names) {
19982
19968
  const parts = raw.split(/\s+as\s+/);
19983
19969
  const name = (parts.length > 1 ? parts[parts.length - 1] : raw).trim();
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/interface-contract-guard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAQ/C,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAyLD,QAAA,MAAM,MAAM,EAAE,MAuMb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/interface-contract-guard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAQ/C,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAwLD,QAAA,MAAM,MAAM,EAAE,MAuMb,CAAC;eAEa,MAAM"}
@@ -84,9 +84,8 @@ function relativePath(p) {
84
84
  var INTERFACE_RE = /(?:export\s+)?interface\s+([A-Za-z_$][A-Za-z0-9_$]*)/g;
85
85
  function extractInterfaceNames(content) {
86
86
  const names = [];
87
- let m;
88
87
  INTERFACE_RE.lastIndex = 0;
89
- while ((m = INTERFACE_RE.exec(content)) !== null) {
88
+ for (const m of content.matchAll(INTERFACE_RE)) {
90
89
  names.push({ name: m[1], line: content.slice(0, m.index).split(/\r?\n/).length });
91
90
  }
92
91
  return names;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/license-audit-gate/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAmK/C,QAAA,MAAM,MAAM,EAAE,MAqMb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/license-audit-gate/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAkK/C,QAAA,MAAM,MAAM,EAAE,MAqMb,CAAC;eAEa,MAAM"}
@@ -54,8 +54,7 @@ var INSTALL_RE = /(?:^|[;&|]\s*)(npm|pnpm|yarn|bun)\s+(?:install|i|add)\s+([^;&|
54
54
  function parsePackageNames(command) {
55
55
  const names = [];
56
56
  INSTALL_RE.lastIndex = 0;
57
- let m;
58
- while ((m = INSTALL_RE.exec(command)) !== null) {
57
+ for (const m of command.matchAll(INSTALL_RE)) {
59
58
  const argString = m[2] ?? "";
60
59
  for (const token of argString.split(/\s+/)) {
61
60
  if (!token || token.startsWith("-")) continue;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/refactor-suggester/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAQ/C,MAAM,MAAM,SAAS,GACjB,eAAe,GACf,cAAc,GACd,iBAAiB,GACjB,cAAc,GACd,aAAa,CAAC;AAElB,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAiRD,QAAA,MAAM,MAAM,EAAE,MA4Nb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/refactor-suggester/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAQ/C,MAAM,MAAM,SAAS,GACjB,eAAe,GACf,cAAc,GACd,iBAAiB,GACjB,cAAc,GACd,aAAa,CAAC;AAElB,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAgRD,QAAA,MAAM,MAAM,EAAE,MA4Nb,CAAC;eAEa,MAAM"}
@@ -104,21 +104,20 @@ function detectSmells(filePath, content, rules) {
104
104
  const lines = content.split(/\r?\n/);
105
105
  const stripped = content.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, " ");
106
106
  const functionLikeRe = /(?:export\s+)?(?:async\s+)?(?:function\s+)?([A-Za-z_$][A-Za-z0-9_$]*)\s*\(([^)]*)\)\s*\{/g;
107
- let m;
108
107
  functionLikeRe.lastIndex = 0;
109
- while ((m = functionLikeRe.exec(stripped)) !== null) {
110
- const name = m[1];
111
- const paramsRaw = m[2];
108
+ for (const match of stripped.matchAll(functionLikeRe)) {
109
+ const name = match[1];
110
+ const paramsRaw = match[2];
112
111
  const params = paramsRaw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
113
112
  if (params.length > rules.maxParams) {
114
113
  suggestions.push({
115
114
  file: relativePath(filePath),
116
- line: content.slice(0, m.index).split(/\r?\n/).length,
115
+ line: content.slice(0, match.index).split(/\r?\n/).length,
117
116
  type: "many-parameters",
118
117
  message: `${name} has ${params.length} parameters (limit ${rules.maxParams})`
119
118
  });
120
119
  }
121
- const bodyStart = m.index + m[0].length;
120
+ const bodyStart = match.index + match[0].length;
122
121
  let depth = 1;
123
122
  let lineEnd = bodyStart;
124
123
  for (let i = bodyStart; i < stripped.length && depth > 0; i++) {
@@ -131,7 +130,7 @@ function detectSmells(filePath, content, rules) {
131
130
  if (bodyLines > rules.longFunctionLines) {
132
131
  suggestions.push({
133
132
  file: relativePath(filePath),
134
- line: content.slice(0, m.index).split(/\r?\n/).length,
133
+ line: content.slice(0, match.index).split(/\r?\n/).length,
135
134
  type: "long-function",
136
135
  message: `${name} spans ~${bodyLines} lines (limit ${rules.longFunctionLines})`
137
136
  });
@@ -162,15 +161,15 @@ function detectSmells(filePath, content, rules) {
162
161
  const magicRe = /\b-?\d+(?:\.\d+)?\b/g;
163
162
  const allowed = /* @__PURE__ */ new Set(["0", "1", "-1", "2"]);
164
163
  magicRe.lastIndex = 0;
165
- while ((m = magicRe.exec(content)) !== null) {
166
- const match = m[0];
164
+ for (const magicNumberMatch of content.matchAll(magicRe)) {
165
+ const match = magicNumberMatch[0];
167
166
  if (allowed.has(match)) continue;
168
- const before = content[m.index - 1];
169
- const after = content[m.index + match.length];
167
+ const before = content[magicNumberMatch.index - 1];
168
+ const after = content[magicNumberMatch.index + match.length];
170
169
  if (before === "[" && after === "]") continue;
171
170
  suggestions.push({
172
171
  file: relativePath(filePath),
173
- line: content.slice(0, m.index).split(/\r?\n/).length,
172
+ line: content.slice(0, magicNumberMatch.index).split(/\r?\n/).length,
174
173
  type: "magic-number",
175
174
  message: `magic number ${match} should be a named constant`
176
175
  });
package/dist/runtime.js CHANGED
@@ -100,7 +100,7 @@ function runRunnerCommand(argv, options) {
100
100
  });
101
101
  return;
102
102
  }
103
- let timedOut = false;
103
+ const timedOut = false;
104
104
  let spawnErrored = false;
105
105
  const stdoutChunks = [];
106
106
  const stderrChunks = [];
@@ -45,7 +45,7 @@ var PATTERNS = [
45
45
  {
46
46
  type: "hardcoded_http",
47
47
  severity: "medium",
48
- regex: /http:\/\/[a-zA-Z0-9][^\s'"\)\\]*/i
48
+ regex: /http:\/\/[a-zA-Z0-9][^\s'")\\]*/i
49
49
  },
50
50
  {
51
51
  type: "console_log_credentials",
@@ -11815,7 +11815,7 @@ function runRunnerCommand(argv, options) {
11815
11815
  });
11816
11816
  return;
11817
11817
  }
11818
- let timedOut = false;
11818
+ const timedOut = false;
11819
11819
  let spawnErrored = false;
11820
11820
  const stdoutChunks = [];
11821
11821
  const stderrChunks = [];
@@ -13446,24 +13446,21 @@ function auditFile(filePath, projectRoot) {
13446
13446
  for (let i = 0; i < lines.length; i++) {
13447
13447
  const line = lines[i];
13448
13448
  const lineNo = i + 1;
13449
- let idMatch;
13450
- while ((idMatch = ATTR_ID.exec(line)) !== null) {
13449
+ for (const idMatch of line.matchAll(ATTR_ID)) {
13451
13450
  const id = idMatch[1];
13452
13451
  const list = idsByValue.get(id) ?? [];
13453
13452
  list.push(lineNo);
13454
13453
  idsByValue.set(id, list);
13455
13454
  }
13456
13455
  ATTR_ID.lastIndex = 0;
13457
- let imgMatch;
13458
- while ((imgMatch = TAG_IMG.exec(line)) !== null) {
13456
+ for (const imgMatch of line.matchAll(TAG_IMG)) {
13459
13457
  const tag = imgMatch[0];
13460
13458
  if (!hasMeaningfulAlt(tag)) {
13461
13459
  add(lineNo, "missing-alt", "error", "<img> is missing meaningful alt text");
13462
13460
  }
13463
13461
  }
13464
13462
  TAG_IMG.lastIndex = 0;
13465
- let inputMatch;
13466
- while ((inputMatch = TAG_INPUT.exec(line)) !== null) {
13463
+ for (const inputMatch of line.matchAll(TAG_INPUT)) {
13467
13464
  const tag = inputMatch[0];
13468
13465
  const typeMatch = tag.match(/\btype\s*=\s*["']?([^"'\s>]*)["']?/i);
13469
13466
  const type = typeMatch ? typeMatch[1].toLowerCase() : "text";
@@ -13488,8 +13485,7 @@ function auditFile(filePath, projectRoot) {
13488
13485
  }
13489
13486
  }
13490
13487
  TAG_INPUT.lastIndex = 0;
13491
- let buttonMatch;
13492
- while ((buttonMatch = TAG_BUTTON.exec(line)) !== null) {
13488
+ for (const buttonMatch of line.matchAll(TAG_BUTTON)) {
13493
13489
  const tag = buttonMatch[0];
13494
13490
  const inner = buttonMatch[1] ?? "";
13495
13491
  const hasText = inner.replace(/\s+/g, "").length > 0;
@@ -13500,8 +13496,7 @@ function auditFile(filePath, projectRoot) {
13500
13496
  }
13501
13497
  }
13502
13498
  TAG_BUTTON.lastIndex = 0;
13503
- let inputButtonMatch;
13504
- while ((inputButtonMatch = INPUT_BUTTON.exec(line)) !== null) {
13499
+ for (const inputButtonMatch of line.matchAll(INPUT_BUTTON)) {
13505
13500
  const tag = inputButtonMatch[0];
13506
13501
  if (!ATTR_VALUE.test(tag) && !ATTR_ARIA_LABEL.test(tag) && !ATTR_TITLE.test(tag)) {
13507
13502
  add(lineNo, "missing-button-text", "error", `<input type="${inputButtonMatch[1]}"> is missing value/aria-label/title`);
@@ -14174,8 +14169,7 @@ function extractStrings(content, cfg) {
14174
14169
  for (let i = 0; i < lines.length; i += 1) {
14175
14170
  const line = lines[i];
14176
14171
  stringRegex.lastIndex = 0;
14177
- let match;
14178
- while ((match = stringRegex.exec(line)) !== null) {
14172
+ for (const match of line.matchAll(stringRegex)) {
14179
14173
  const value = match[2] ?? "";
14180
14174
  const quoteIndex = match.index + (match[1]?.length ?? 1);
14181
14175
  if (!looksLikeUserText(value, cfg.minLength)) continue;
@@ -14509,33 +14503,31 @@ function countFunctions(content) {
14509
14503
  const declRe = /\bfunction\s+[A-Za-z_$][A-Za-z0-9_$]*\s*\(/g;
14510
14504
  const methodRe = /\b[A-Za-z_$][A-Za-z0-9_$]*\s*\([^)]*\)\s*\{/g;
14511
14505
  const arrowRe = /=>\s*(?:\{|\(|[^\s;{}])/g;
14512
- let m;
14513
14506
  declRe.lastIndex = 0;
14514
- while ((m = declRe.exec(content)) !== null) count++;
14507
+ for (const _match of content.matchAll(declRe)) count++;
14515
14508
  methodRe.lastIndex = 0;
14516
- while ((m = methodRe.exec(content)) !== null) {
14517
- const prefix = content.slice(0, m.index).trimEnd();
14509
+ for (const match of content.matchAll(methodRe)) {
14510
+ const prefix = content.slice(0, match.index).trimEnd();
14518
14511
  if (/\bfunction\s*$/.test(prefix)) continue;
14519
14512
  count++;
14520
14513
  }
14521
14514
  arrowRe.lastIndex = 0;
14522
- while ((m = arrowRe.exec(content)) !== null) count++;
14515
+ for (const _match of content.matchAll(arrowRe)) count++;
14523
14516
  return count;
14524
14517
  }
14525
14518
  function countComplexity(content) {
14526
14519
  const controlRe = /\b(if|else\s+if|for|while|switch|catch)\b/g;
14527
14520
  const operatorRe = /[?&|]/g;
14528
14521
  let complexity = 0;
14529
- let m;
14530
14522
  controlRe.lastIndex = 0;
14531
- while ((m = controlRe.exec(content)) !== null) complexity++;
14523
+ for (const _match of content.matchAll(controlRe)) complexity++;
14532
14524
  operatorRe.lastIndex = 0;
14533
- while ((m = operatorRe.exec(content)) !== null) {
14534
- const ch = m[0];
14525
+ for (const match of content.matchAll(operatorRe)) {
14526
+ const ch = match[0];
14535
14527
  if (ch === "?") {
14536
14528
  complexity++;
14537
14529
  } else {
14538
- const next = content[m.index + 1];
14530
+ const next = content[match.index + 1];
14539
14531
  if (next === ch) complexity++;
14540
14532
  }
14541
14533
  }
@@ -14833,9 +14825,8 @@ var DECLARATION_EXPORT_RE = /export\s+(?:async\s+|abstract\s+)?(?:const|let|var|
14833
14825
  var NAMED_EXPORT_RE = /export\s*\{([^}]+)\}/g;
14834
14826
  function extractExports2(content, filePath) {
14835
14827
  const exports = [];
14836
- let match;
14837
14828
  DECLARATION_EXPORT_RE.lastIndex = 0;
14838
- while ((match = DECLARATION_EXPORT_RE.exec(content)) !== null) {
14829
+ for (const match of content.matchAll(DECLARATION_EXPORT_RE)) {
14839
14830
  exports.push({
14840
14831
  identifier: match[1],
14841
14832
  file: filePath,
@@ -14844,7 +14835,7 @@ function extractExports2(content, filePath) {
14844
14835
  });
14845
14836
  }
14846
14837
  NAMED_EXPORT_RE.lastIndex = 0;
14847
- while ((match = NAMED_EXPORT_RE.exec(content)) !== null) {
14838
+ for (const match of content.matchAll(NAMED_EXPORT_RE)) {
14848
14839
  const line = lineNumber(content, match.index);
14849
14840
  const names = match[1].split(",").map((s) => s.trim()).filter(Boolean);
14850
14841
  for (const name of names) {
@@ -14987,7 +14978,7 @@ var plugin45 = {
14987
14978
  let result;
14988
14979
  try {
14989
14980
  result = scan(scanRoot, 1, cfg);
14990
- } catch (err) {
14981
+ } catch {
14991
14982
  state42.errorCount += 1;
14992
14983
  return;
14993
14984
  }
@@ -16119,8 +16110,7 @@ function scanFile(filePath, content, patterns, maxFindings) {
16119
16110
  const lines = content.split(/\r?\n/);
16120
16111
  for (const re of patterns) {
16121
16112
  re.lastIndex = 0;
16122
- let m;
16123
- while ((m = re.exec(content)) !== null) {
16113
+ for (const m of content.matchAll(re)) {
16124
16114
  const flag = m[1] ?? m[0];
16125
16115
  const lineNo = content.slice(0, m.index).split(/\r?\n/).length;
16126
16116
  const context = (lines[lineNo - 1] ?? "").trim();
@@ -16419,9 +16409,8 @@ function relativePath5(p) {
16419
16409
  var INTERFACE_RE = /(?:export\s+)?interface\s+([A-Za-z_$][A-Za-z0-9_$]*)/g;
16420
16410
  function extractInterfaceNames(content) {
16421
16411
  const names = [];
16422
- let m;
16423
16412
  INTERFACE_RE.lastIndex = 0;
16424
- while ((m = INTERFACE_RE.exec(content)) !== null) {
16413
+ for (const m of content.matchAll(INTERFACE_RE)) {
16425
16414
  names.push({ name: m[1], line: content.slice(0, m.index).split(/\r?\n/).length });
16426
16415
  }
16427
16416
  return names;
@@ -16689,8 +16678,7 @@ var INSTALL_RE3 = /(?:^|[;&|]\s*)(npm|pnpm|yarn|bun)\s+(?:install|i|add)\s+([^;&
16689
16678
  function parsePackageNames(command) {
16690
16679
  const names = [];
16691
16680
  INSTALL_RE3.lastIndex = 0;
16692
- let m;
16693
- while ((m = INSTALL_RE3.exec(command)) !== null) {
16681
+ for (const m of command.matchAll(INSTALL_RE3)) {
16694
16682
  const argString = m[2] ?? "";
16695
16683
  for (const token of argString.split(/\s+/)) {
16696
16684
  if (!token || token.startsWith("-")) continue;
@@ -17657,21 +17645,20 @@ function detectSmells(filePath, content, rules) {
17657
17645
  const lines = content.split(/\r?\n/);
17658
17646
  const stripped = content.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, " ");
17659
17647
  const functionLikeRe = /(?:export\s+)?(?:async\s+)?(?:function\s+)?([A-Za-z_$][A-Za-z0-9_$]*)\s*\(([^)]*)\)\s*\{/g;
17660
- let m;
17661
17648
  functionLikeRe.lastIndex = 0;
17662
- while ((m = functionLikeRe.exec(stripped)) !== null) {
17663
- const name = m[1];
17664
- const paramsRaw = m[2];
17649
+ for (const match of stripped.matchAll(functionLikeRe)) {
17650
+ const name = match[1];
17651
+ const paramsRaw = match[2];
17665
17652
  const params = paramsRaw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
17666
17653
  if (params.length > rules.maxParams) {
17667
17654
  suggestions.push({
17668
17655
  file: relativePath6(filePath),
17669
- line: content.slice(0, m.index).split(/\r?\n/).length,
17656
+ line: content.slice(0, match.index).split(/\r?\n/).length,
17670
17657
  type: "many-parameters",
17671
17658
  message: `${name} has ${params.length} parameters (limit ${rules.maxParams})`
17672
17659
  });
17673
17660
  }
17674
- const bodyStart = m.index + m[0].length;
17661
+ const bodyStart = match.index + match[0].length;
17675
17662
  let depth = 1;
17676
17663
  let lineEnd = bodyStart;
17677
17664
  for (let i = bodyStart; i < stripped.length && depth > 0; i++) {
@@ -17684,7 +17671,7 @@ function detectSmells(filePath, content, rules) {
17684
17671
  if (bodyLines > rules.longFunctionLines) {
17685
17672
  suggestions.push({
17686
17673
  file: relativePath6(filePath),
17687
- line: content.slice(0, m.index).split(/\r?\n/).length,
17674
+ line: content.slice(0, match.index).split(/\r?\n/).length,
17688
17675
  type: "long-function",
17689
17676
  message: `${name} spans ~${bodyLines} lines (limit ${rules.longFunctionLines})`
17690
17677
  });
@@ -17715,15 +17702,15 @@ function detectSmells(filePath, content, rules) {
17715
17702
  const magicRe = /\b-?\d+(?:\.\d+)?\b/g;
17716
17703
  const allowed = /* @__PURE__ */ new Set(["0", "1", "-1", "2"]);
17717
17704
  magicRe.lastIndex = 0;
17718
- while ((m = magicRe.exec(content)) !== null) {
17719
- const match = m[0];
17705
+ for (const magicNumberMatch of content.matchAll(magicRe)) {
17706
+ const match = magicNumberMatch[0];
17720
17707
  if (allowed.has(match)) continue;
17721
- const before = content[m.index - 1];
17722
- const after = content[m.index + match.length];
17708
+ const before = content[magicNumberMatch.index - 1];
17709
+ const after = content[magicNumberMatch.index + match.length];
17723
17710
  if (before === "[" && after === "]") continue;
17724
17711
  suggestions.push({
17725
17712
  file: relativePath6(filePath),
17726
- line: content.slice(0, m.index).split(/\r?\n/).length,
17713
+ line: content.slice(0, magicNumberMatch.index).split(/\r?\n/).length,
17727
17714
  type: "magic-number",
17728
17715
  message: `magic number ${match} should be a named constant`
17729
17716
  });
@@ -18520,7 +18507,7 @@ var PATTERNS4 = [
18520
18507
  {
18521
18508
  type: "hardcoded_http",
18522
18509
  severity: "medium",
18523
- regex: /http:\/\/[a-zA-Z0-9][^\s'"\)\\]*/i
18510
+ regex: /http:\/\/[a-zA-Z0-9][^\s'")\\]*/i
18524
18511
  },
18525
18512
  {
18526
18513
  type: "console_log_credentials",
@@ -19953,31 +19940,30 @@ function detectExports(content) {
19953
19940
  const arrowRe = /export\s+(?:const|let|var)\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*=\s*(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>/g;
19954
19941
  const classRe = /export\s+(?:abstract\s+)?class\s+([A-Za-z_$][A-Za-z0-9_$]*)/g;
19955
19942
  const namedRe = /export\s*\{([^}]+)\}/g;
19956
- let m;
19957
19943
  functionRe.lastIndex = 0;
19958
- while ((m = functionRe.exec(content)) !== null) {
19959
- if (!seen.has(m[1])) {
19960
- seen.add(m[1]);
19961
- exports.push({ name: m[1], kind: "function" });
19944
+ for (const match of content.matchAll(functionRe)) {
19945
+ if (!seen.has(match[1])) {
19946
+ seen.add(match[1]);
19947
+ exports.push({ name: match[1], kind: "function" });
19962
19948
  }
19963
19949
  }
19964
19950
  arrowRe.lastIndex = 0;
19965
- while ((m = arrowRe.exec(content)) !== null) {
19966
- if (!seen.has(m[1])) {
19967
- seen.add(m[1]);
19968
- exports.push({ name: m[1], kind: "arrow" });
19951
+ for (const match of content.matchAll(arrowRe)) {
19952
+ if (!seen.has(match[1])) {
19953
+ seen.add(match[1]);
19954
+ exports.push({ name: match[1], kind: "arrow" });
19969
19955
  }
19970
19956
  }
19971
19957
  classRe.lastIndex = 0;
19972
- while ((m = classRe.exec(content)) !== null) {
19973
- if (!seen.has(m[1])) {
19974
- seen.add(m[1]);
19975
- exports.push({ name: m[1], kind: "class" });
19958
+ for (const match of content.matchAll(classRe)) {
19959
+ if (!seen.has(match[1])) {
19960
+ seen.add(match[1]);
19961
+ exports.push({ name: match[1], kind: "class" });
19976
19962
  }
19977
19963
  }
19978
19964
  namedRe.lastIndex = 0;
19979
- while ((m = namedRe.exec(content)) !== null) {
19980
- const names = m[1].split(",").map((s) => s.trim()).filter(Boolean);
19965
+ for (const match of content.matchAll(namedRe)) {
19966
+ const names = match[1].split(",").map((s) => s.trim()).filter(Boolean);
19981
19967
  for (const raw of names) {
19982
19968
  const parts = raw.split(/\s+as\s+/);
19983
19969
  const name = (parts.length > 1 ? parts[parts.length - 1] : raw).trim();
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-generator/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA4E/C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;CAChD;AAyHD,QAAA,MAAM,MAAM,EAAE,MAuHb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-generator/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA4E/C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;CAChD;AAuHD,QAAA,MAAM,MAAM,EAAE,MAuHb,CAAC;eAEa,MAAM"}
@@ -46,31 +46,30 @@ function detectExports(content) {
46
46
  const arrowRe = /export\s+(?:const|let|var)\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*=\s*(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>/g;
47
47
  const classRe = /export\s+(?:abstract\s+)?class\s+([A-Za-z_$][A-Za-z0-9_$]*)/g;
48
48
  const namedRe = /export\s*\{([^}]+)\}/g;
49
- let m;
50
49
  functionRe.lastIndex = 0;
51
- while ((m = functionRe.exec(content)) !== null) {
52
- if (!seen.has(m[1])) {
53
- seen.add(m[1]);
54
- exports.push({ name: m[1], kind: "function" });
50
+ for (const match of content.matchAll(functionRe)) {
51
+ if (!seen.has(match[1])) {
52
+ seen.add(match[1]);
53
+ exports.push({ name: match[1], kind: "function" });
55
54
  }
56
55
  }
57
56
  arrowRe.lastIndex = 0;
58
- while ((m = arrowRe.exec(content)) !== null) {
59
- if (!seen.has(m[1])) {
60
- seen.add(m[1]);
61
- exports.push({ name: m[1], kind: "arrow" });
57
+ for (const match of content.matchAll(arrowRe)) {
58
+ if (!seen.has(match[1])) {
59
+ seen.add(match[1]);
60
+ exports.push({ name: match[1], kind: "arrow" });
62
61
  }
63
62
  }
64
63
  classRe.lastIndex = 0;
65
- while ((m = classRe.exec(content)) !== null) {
66
- if (!seen.has(m[1])) {
67
- seen.add(m[1]);
68
- exports.push({ name: m[1], kind: "class" });
64
+ for (const match of content.matchAll(classRe)) {
65
+ if (!seen.has(match[1])) {
66
+ seen.add(match[1]);
67
+ exports.push({ name: match[1], kind: "class" });
69
68
  }
70
69
  }
71
70
  namedRe.lastIndex = 0;
72
- while ((m = namedRe.exec(content)) !== null) {
73
- const names = m[1].split(",").map((s) => s.trim()).filter(Boolean);
71
+ for (const match of content.matchAll(namedRe)) {
72
+ const names = match[1].split(",").map((s) => s.trim()).filter(Boolean);
74
73
  for (const raw of names) {
75
74
  const parts = raw.split(/\s+as\s+/);
76
75
  const name = (parts.length > 1 ? parts[parts.length - 1] : raw).trim();
package/dist/type-gate.js CHANGED
@@ -104,7 +104,7 @@ function runRunnerCommand(argv, options) {
104
104
  });
105
105
  return;
106
106
  }
107
- let timedOut = false;
107
+ const timedOut = false;
108
108
  let spawnErrored = false;
109
109
  const stdoutChunks = [];
110
110
  const stderrChunks = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/plugins",
3
- "version": "0.285.0",
3
+ "version": "0.286.0",
4
4
  "description": "Official WrongStack plugin collection — 63 focused, single-purpose plugins for code quality, security, observability, planning, and agent coordination",
5
5
  "license": "MIT",
6
6
  "author": "ECOSTACK TECHNOLOGY OÜ",
@@ -278,8 +278,8 @@
278
278
  "vitest": "^4.1.9"
279
279
  },
280
280
  "dependencies": {
281
- "@wrongstack/tools": "0.285.0",
282
- "@wrongstack/core": "0.285.0"
281
+ "@wrongstack/core": "0.286.0",
282
+ "@wrongstack/tools": "0.286.0"
283
283
  },
284
284
  "scripts": {
285
285
  "build": "node ../../scripts/build-package.mjs",