@conorroberts/utils 0.0.78 → 0.0.82

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.
@@ -15,7 +15,7 @@ import { definePlugin, defineRule } from "oxlint";
15
15
  * @property {boolean} returnsJsx
16
16
  */
17
17
  const JSX_NODE_TYPES$2 = new Set(["JSXElement", "JSXFragment"]);
18
- const FUNCTION_NODE_TYPES$4 = new Set([
18
+ const FUNCTION_NODE_TYPES$5 = new Set([
19
19
  "FunctionDeclaration",
20
20
  "FunctionExpression",
21
21
  "ArrowFunctionExpression"
@@ -24,12 +24,12 @@ const FUNCTION_NODE_TYPES$4 = new Set([
24
24
  * @param {unknown} node
25
25
  * @returns {node is ESTNode & { type: string }}
26
26
  */
27
- const isNode$4 = (node) => Boolean(node && typeof node === "object" && "type" in node);
27
+ const isNode$5 = (node) => Boolean(node && typeof node === "object" && "type" in node);
28
28
  /**
29
29
  * @param {unknown} node
30
30
  * @returns {node is FunctionLikeNode}
31
31
  */
32
- const isFunctionLike$4 = (node) => isNode$4(node) && FUNCTION_NODE_TYPES$4.has(node.type);
32
+ const isFunctionLike$5 = (node) => isNode$5(node) && FUNCTION_NODE_TYPES$5.has(node.type);
33
33
  /**
34
34
  * @param {unknown} name
35
35
  * @returns {name is string}
@@ -50,13 +50,13 @@ const getFunctionName$2 = (node) => {
50
50
  if (node.id.type === "Identifier") return node.id.name;
51
51
  }
52
52
  const parent = node.parent;
53
- if (!parent || !isNode$4(parent)) return "";
53
+ if (!parent || !isNode$5(parent)) return "";
54
54
  if (parent.type === "VariableDeclarator") return parent.id && parent.id.type === "Identifier" ? parent.id.name : "";
55
55
  if (parent.type === "AssignmentExpression") return parent.left && parent.left.type === "Identifier" ? parent.left.name : "";
56
56
  if (parent.type === "Property" || parent.type === "MethodDefinition") return "";
57
57
  if (parent.type === "CallExpression") {
58
58
  const callParent = parent.parent;
59
- if (callParent && isNode$4(callParent)) {
59
+ if (callParent && isNode$5(callParent)) {
60
60
  if (callParent.type === "VariableDeclarator") return callParent.id && callParent.id.type === "Identifier" ? callParent.id.name : "";
61
61
  if (callParent.type === "AssignmentExpression") return callParent.left && callParent.left.type === "Identifier" ? callParent.left.name : "";
62
62
  }
@@ -67,25 +67,25 @@ const getFunctionName$2 = (node) => {
67
67
  * @param {ESTExpression | null | undefined} root
68
68
  */
69
69
  const expressionContainsJsx$2 = (root) => {
70
- if (!root || !isNode$4(root)) return false;
70
+ if (!root || !isNode$5(root)) return false;
71
71
  const stack = [root];
72
72
  while (stack.length > 0) {
73
73
  const current = stack.pop();
74
- if (!current || !isNode$4(current)) continue;
74
+ if (!current || !isNode$5(current)) continue;
75
75
  if (JSX_NODE_TYPES$2.has(current.type)) return true;
76
- if (FUNCTION_NODE_TYPES$4.has(current.type) && current !== root) continue;
76
+ if (FUNCTION_NODE_TYPES$5.has(current.type) && current !== root) continue;
77
77
  for (const key of Object.keys(current)) {
78
78
  if (key === "parent") continue;
79
79
  const value = current[key];
80
80
  if (!value) continue;
81
81
  if (Array.isArray(value)) {
82
- for (const element of value) if (isNode$4(element)) stack.push(element);
83
- } else if (isNode$4(value)) stack.push(value);
82
+ for (const element of value) if (isNode$5(element)) stack.push(element);
83
+ } else if (isNode$5(value)) stack.push(value);
84
84
  }
85
85
  }
86
86
  return false;
87
87
  };
88
- const rule$13 = defineRule({
88
+ const rule$14 = defineRule({
89
89
  meta: {
90
90
  type: "problem",
91
91
  docs: {
@@ -126,20 +126,20 @@ const rule$13 = defineRule({
126
126
  const fnCtx = currentFunction();
127
127
  if (!fnCtx) return;
128
128
  const argument = node.argument;
129
- if (!argument || isFunctionLike$4(argument)) return;
129
+ if (!argument || isFunctionLike$5(argument)) return;
130
130
  if (expressionContainsJsx$2(argument)) fnCtx.returnsJsx = true;
131
131
  };
132
132
  return {
133
133
  FunctionDeclaration(node) {
134
- if (isFunctionLike$4(node)) enterFunction(node);
134
+ if (isFunctionLike$5(node)) enterFunction(node);
135
135
  },
136
136
  "FunctionDeclaration:exit": exitFunction,
137
137
  FunctionExpression(node) {
138
- if (isFunctionLike$4(node)) enterFunction(node);
138
+ if (isFunctionLike$5(node)) enterFunction(node);
139
139
  },
140
140
  "FunctionExpression:exit": exitFunction,
141
141
  ArrowFunctionExpression(node) {
142
- if (isFunctionLike$4(node)) enterFunction(node);
142
+ if (isFunctionLike$5(node)) enterFunction(node);
143
143
  },
144
144
  "ArrowFunctionExpression:exit": exitFunction,
145
145
  ReturnStatement(node) {
@@ -148,11 +148,11 @@ const rule$13 = defineRule({
148
148
  };
149
149
  }
150
150
  });
151
- const jsxComponentPascalCaseRule = rule$13;
151
+ const jsxComponentPascalCaseRule = rule$14;
152
152
 
153
153
  //#endregion
154
154
  //#region src/oxlint-plugins/no-array-type.js
155
- const rule$12 = defineRule({
155
+ const rule$13 = defineRule({
156
156
  meta: {
157
157
  type: "problem",
158
158
  docs: {
@@ -171,7 +171,7 @@ const rule$12 = defineRule({
171
171
  } };
172
172
  }
173
173
  });
174
- const noArrayTypeRule = rule$12;
174
+ const noArrayTypeRule = rule$13;
175
175
 
176
176
  //#endregion
177
177
  //#region src/oxlint-plugins/no-component-date-instantiation.js
@@ -190,7 +190,7 @@ const noArrayTypeRule = rule$12;
190
190
  * @property {boolean} returnsJsx
191
191
  * @property {NewExpressionNode[]} dateInstantiations
192
192
  */
193
- const FUNCTION_NODE_TYPES$3 = new Set([
193
+ const FUNCTION_NODE_TYPES$4 = new Set([
194
194
  "FunctionDeclaration",
195
195
  "FunctionExpression",
196
196
  "ArrowFunctionExpression"
@@ -199,12 +199,12 @@ const FUNCTION_NODE_TYPES$3 = new Set([
199
199
  * @param {unknown} node
200
200
  * @returns {node is ESTNode & { type: string }}
201
201
  */
202
- const isNode$3 = (node) => Boolean(node && typeof node === "object" && "type" in node);
202
+ const isNode$4 = (node) => Boolean(node && typeof node === "object" && "type" in node);
203
203
  /**
204
204
  * @param {unknown} node
205
205
  * @returns {node is FunctionLikeNode}
206
206
  */
207
- const isFunctionLike$3 = (node) => isNode$3(node) && FUNCTION_NODE_TYPES$3.has(node.type);
207
+ const isFunctionLike$4 = (node) => isNode$4(node) && FUNCTION_NODE_TYPES$4.has(node.type);
208
208
  /**
209
209
  * Check if a function name follows React component naming convention (PascalCase)
210
210
  * @param {unknown} name
@@ -222,7 +222,7 @@ const getFunctionName$1 = (node) => {
222
222
  if (node.id.type === "Identifier") return node.id.name;
223
223
  }
224
224
  const parent = node.parent;
225
- if (!parent || !isNode$3(parent)) return "";
225
+ if (!parent || !isNode$4(parent)) return "";
226
226
  if (parent.type === "VariableDeclarator") return parent.id && parent.id.type === "Identifier" ? parent.id.name : "";
227
227
  if (parent.type === "AssignmentExpression") return parent.left && parent.left.type === "Identifier" ? parent.left.name : "";
228
228
  if (parent.type === "Property" || parent.type === "MethodDefinition") return parent.key && parent.key.type === "Identifier" ? parent.key.name : "";
@@ -234,7 +234,7 @@ const getFunctionName$1 = (node) => {
234
234
  * @returns {boolean}
235
235
  */
236
236
  const isJSXNode = (node) => {
237
- if (!node || !isNode$3(node)) return false;
237
+ if (!node || !isNode$4(node)) return false;
238
238
  return node.type === "JSXElement" || node.type === "JSXFragment";
239
239
  };
240
240
  /**
@@ -246,7 +246,7 @@ const isDateInstantiation = (node) => {
246
246
  if (node.callee.type === "Identifier" && node.callee.name === "Date") return true;
247
247
  return false;
248
248
  };
249
- const rule$11 = defineRule({
249
+ const rule$12 = defineRule({
250
250
  meta: {
251
251
  type: "problem",
252
252
  docs: {
@@ -303,15 +303,15 @@ const rule$11 = defineRule({
303
303
  };
304
304
  return {
305
305
  FunctionDeclaration(node) {
306
- if (isFunctionLike$3(node)) enterFunction(node);
306
+ if (isFunctionLike$4(node)) enterFunction(node);
307
307
  },
308
308
  "FunctionDeclaration:exit": exitFunction,
309
309
  FunctionExpression(node) {
310
- if (isFunctionLike$3(node)) enterFunction(node);
310
+ if (isFunctionLike$4(node)) enterFunction(node);
311
311
  },
312
312
  "FunctionExpression:exit": exitFunction,
313
313
  ArrowFunctionExpression(node) {
314
- if (isFunctionLike$3(node)) enterFunction(node);
314
+ if (isFunctionLike$4(node)) enterFunction(node);
315
315
  },
316
316
  "ArrowFunctionExpression:exit": exitFunction,
317
317
  ReturnStatement(node) {
@@ -323,7 +323,7 @@ const rule$11 = defineRule({
323
323
  };
324
324
  }
325
325
  });
326
- const noComponentDateInstantiationRule = rule$11;
326
+ const noComponentDateInstantiationRule = rule$12;
327
327
 
328
328
  //#endregion
329
329
  //#region src/oxlint-plugins/no-inline-components.js
@@ -358,7 +358,7 @@ const noComponentDateInstantiationRule = rule$11;
358
358
  * @property {NestedFunctionRecord[]} nestedJsxChildren
359
359
  */
360
360
  const JSX_NODE_TYPES$1 = new Set(["JSXElement", "JSXFragment"]);
361
- const FUNCTION_NODE_TYPES$2 = new Set([
361
+ const FUNCTION_NODE_TYPES$3 = new Set([
362
362
  "FunctionDeclaration",
363
363
  "FunctionExpression",
364
364
  "ArrowFunctionExpression"
@@ -372,23 +372,23 @@ const isComponentName = (name) => typeof name === "string" && /^[A-Z]/.test(name
372
372
  * @param {unknown} node
373
373
  * @returns {node is ESTNode & { type: string }}
374
374
  */
375
- const isNode$2 = (node) => Boolean(node && typeof node === "object" && "type" in node);
375
+ const isNode$3 = (node) => Boolean(node && typeof node === "object" && "type" in node);
376
376
  /**
377
377
  * @param {unknown} node
378
378
  * @returns {node is FunctionLikeNode}
379
379
  */
380
- const isFunctionLike$2 = (node) => isNode$2(node) && FUNCTION_NODE_TYPES$2.has(node.type);
380
+ const isFunctionLike$3 = (node) => isNode$3(node) && FUNCTION_NODE_TYPES$3.has(node.type);
381
381
  /**
382
382
  * @param {ESTNode | null | undefined} node
383
383
  * @returns {FunctionLikeNode | null}
384
384
  */
385
- const getEnclosingFunction$1 = (node) => {
385
+ const getEnclosingFunction = (node) => {
386
386
  const findFunction = (current) => {
387
387
  if (!current) return null;
388
- if (isFunctionLike$2(current)) return current;
389
- return findFunction(isNode$2(current) ? current.parent ?? null : null);
388
+ if (isFunctionLike$3(current)) return current;
389
+ return findFunction(isNode$3(current) ? current.parent ?? null : null);
390
390
  };
391
- return findFunction(isNode$2(node) ? node.parent ?? null : null);
391
+ return findFunction(isNode$3(node) ? node.parent ?? null : null);
392
392
  };
393
393
  /**
394
394
  * @param {FunctionLikeNode} node
@@ -397,16 +397,16 @@ const isFunctionUsedAsJsxProp = (node) => {
397
397
  const checkJsxProp = (current) => {
398
398
  if (!current) return false;
399
399
  if (current.type === "JSXAttribute") return true;
400
- if (isFunctionLike$2(current)) return false;
401
- return checkJsxProp(isNode$2(current) ? current.parent ?? null : null);
400
+ if (isFunctionLike$3(current)) return false;
401
+ return checkJsxProp(isNode$3(current) ? current.parent ?? null : null);
402
402
  };
403
- return checkJsxProp(isNode$2(node) ? node.parent ?? null : null);
403
+ return checkJsxProp(isNode$3(node) ? node.parent ?? null : null);
404
404
  };
405
405
  /**
406
406
  * @param {FunctionLikeNode} node
407
407
  */
408
408
  const isFunctionImmediatelyInvoked = (node) => {
409
- const parent = isNode$2(node) ? node.parent ?? null : null;
409
+ const parent = isNode$3(node) ? node.parent ?? null : null;
410
410
  if (!parent) return false;
411
411
  if (parent.type === "CallExpression" && parent.callee === node) return true;
412
412
  return false;
@@ -415,20 +415,20 @@ const isFunctionImmediatelyInvoked = (node) => {
415
415
  * @param {ESTExpression | null | undefined} root
416
416
  */
417
417
  const expressionContainsJsx$1 = (root) => {
418
- if (!root || !isNode$2(root)) return false;
418
+ if (!root || !isNode$3(root)) return false;
419
419
  const stack = [root];
420
420
  while (stack.length > 0) {
421
421
  const current = stack.pop();
422
- if (!current || !isNode$2(current)) continue;
422
+ if (!current || !isNode$3(current)) continue;
423
423
  if (JSX_NODE_TYPES$1.has(current.type)) return true;
424
- if (FUNCTION_NODE_TYPES$2.has(current.type) && current !== root) continue;
424
+ if (FUNCTION_NODE_TYPES$3.has(current.type) && current !== root) continue;
425
425
  for (const key of Object.keys(current)) {
426
426
  if (key === "parent") continue;
427
427
  const value = current[key];
428
428
  if (!value) continue;
429
429
  if (Array.isArray(value)) {
430
- for (const element of value) if (isNode$2(element)) stack.push(element);
431
- } else if (isNode$2(value)) stack.push(value);
430
+ for (const element of value) if (isNode$3(element)) stack.push(element);
431
+ } else if (isNode$3(value)) stack.push(value);
432
432
  }
433
433
  }
434
434
  return false;
@@ -440,7 +440,7 @@ const expressionContainsJsx$1 = (root) => {
440
440
  const expressionProducesJsx = (root, bindingNames) => {
441
441
  if (!root) return false;
442
442
  if (expressionContainsJsx$1(root)) return true;
443
- if (!isNode$2(root)) return false;
443
+ if (!isNode$3(root)) return false;
444
444
  const type = root.type;
445
445
  if (type === "Identifier") return bindingNames.has(root.name);
446
446
  if (type === "ConditionalExpression") return expressionProducesJsx(root.consequent, bindingNames) || expressionProducesJsx(root.alternate, bindingNames);
@@ -466,7 +466,7 @@ const expressionProducesJsx = (root, bindingNames) => {
466
466
  * @param {string[]} names
467
467
  */
468
468
  const collectBindingNames = (pattern, names) => {
469
- if (!pattern || !isNode$2(pattern)) return;
469
+ if (!pattern || !isNode$3(pattern)) return;
470
470
  const type = pattern.type;
471
471
  if (type === "Identifier") {
472
472
  names.push(pattern.name);
@@ -503,13 +503,13 @@ const getFunctionName = (node) => {
503
503
  if (node.id.type === "Identifier") return node.id.name;
504
504
  }
505
505
  const parent = node.parent;
506
- if (!parent || !isNode$2(parent)) return "";
506
+ if (!parent || !isNode$3(parent)) return "";
507
507
  if (parent.type === "VariableDeclarator") return parent.id && parent.id.type === "Identifier" ? parent.id.name : "";
508
508
  if (parent.type === "AssignmentExpression") return parent.left && parent.left.type === "Identifier" ? parent.left.name : "";
509
509
  if (parent.type === "Property" || parent.type === "MethodDefinition") return parent.key && parent.key.type === "Identifier" ? parent.key.name : "";
510
510
  if (parent.type === "CallExpression") {
511
511
  const callParent = parent.parent;
512
- if (callParent && isNode$2(callParent)) {
512
+ if (callParent && isNode$3(callParent)) {
513
513
  if (callParent.type === "VariableDeclarator") return callParent.id && callParent.id.type === "Identifier" ? callParent.id.name : "";
514
514
  if (callParent.type === "AssignmentExpression") return callParent.left && callParent.left.type === "Identifier" ? callParent.left.name : "";
515
515
  }
@@ -540,7 +540,7 @@ const createNestedFunctionMessage = (childName, parentName) => `JSX-returning ${
540
540
  * @param {string} name
541
541
  */
542
542
  const createIIFEMessage = (name) => `JSX-returning ${describeNested(name)} should not be declared as an immediately invoked function expression (IIFE). Extract it to a named function at module scope.`;
543
- const rule$10 = defineRule({
543
+ const rule$11 = defineRule({
544
544
  meta: {
545
545
  type: "problem",
546
546
  docs: {
@@ -601,7 +601,7 @@ const rule$10 = defineRule({
601
601
  const fnCtx = currentFunction();
602
602
  if (!fnCtx) return;
603
603
  const argument = node.argument;
604
- if (!argument || isFunctionLike$2(argument)) return;
604
+ if (!argument || isFunctionLike$3(argument)) return;
605
605
  if (expressionProducesJsx(argument, fnCtx.jsxBindingNames)) fnCtx.returnsJsx = true;
606
606
  };
607
607
  /** @param {VariableDeclaratorNode} node */
@@ -609,7 +609,7 @@ const rule$10 = defineRule({
609
609
  const fnCtx = currentFunction();
610
610
  if (!fnCtx) return;
611
611
  const init = node.init;
612
- if (!init || isFunctionLike$2(init)) return;
612
+ if (!init || isFunctionLike$3(init)) return;
613
613
  if (!expressionContainsJsx$1(init)) return;
614
614
  const names = [];
615
615
  collectBindingNames(node.id, names);
@@ -625,7 +625,7 @@ const rule$10 = defineRule({
625
625
  const fnCtx = currentFunction();
626
626
  if (!fnCtx) return;
627
627
  const right = node.right;
628
- if (!right || isFunctionLike$2(right)) return;
628
+ if (!right || isFunctionLike$3(right)) return;
629
629
  if (!expressionContainsJsx$1(right)) return;
630
630
  const names = [];
631
631
  if (node.left && node.left.type === "Identifier") {
@@ -662,15 +662,15 @@ const rule$10 = defineRule({
662
662
  };
663
663
  return {
664
664
  FunctionDeclaration(node) {
665
- if (isFunctionLike$2(node)) enterFunction(node);
665
+ if (isFunctionLike$3(node)) enterFunction(node);
666
666
  },
667
667
  "FunctionDeclaration:exit": exitFunction,
668
668
  FunctionExpression(node) {
669
- if (isFunctionLike$2(node)) enterFunction(node);
669
+ if (isFunctionLike$3(node)) enterFunction(node);
670
670
  },
671
671
  "FunctionExpression:exit": exitFunction,
672
672
  ArrowFunctionExpression(node) {
673
- if (isFunctionLike$2(node)) enterFunction(node);
673
+ if (isFunctionLike$3(node)) enterFunction(node);
674
674
  },
675
675
  "ArrowFunctionExpression:exit": exitFunction,
676
676
  ReturnStatement(node) {
@@ -688,7 +688,7 @@ const rule$10 = defineRule({
688
688
  };
689
689
  }
690
690
  });
691
- const noInlineComponentsRule = rule$10;
691
+ const noInlineComponentsRule = rule$11;
692
692
 
693
693
  //#endregion
694
694
  //#region src/oxlint-plugins/no-component-pure-functions.js
@@ -698,7 +698,7 @@ const noInlineComponentsRule = rule$10;
698
698
  * @typedef {import("oxlint").ESTree.Function | import("oxlint").ESTree.ArrowFunctionExpression} FunctionLikeNode
699
699
  * @typedef {import("oxlint").ESTree.VariableDeclarator} VariableDeclaratorNode
700
700
  */
701
- const FUNCTION_NODE_TYPES$1 = new Set([
701
+ const FUNCTION_NODE_TYPES$2 = new Set([
702
702
  "FunctionDeclaration",
703
703
  "FunctionExpression",
704
704
  "ArrowFunctionExpression"
@@ -707,18 +707,18 @@ const FUNCTION_NODE_TYPES$1 = new Set([
707
707
  * @param {unknown} node
708
708
  * @returns {node is ESTNode & { type: string }}
709
709
  */
710
- const isNode$1 = (node) => Boolean(node && typeof node === "object" && "type" in node);
710
+ const isNode$2 = (node) => Boolean(node && typeof node === "object" && "type" in node);
711
711
  /**
712
712
  * @param {unknown} node
713
713
  * @returns {node is FunctionLikeNode}
714
714
  */
715
- const isFunctionLike$1 = (node) => isNode$1(node) && FUNCTION_NODE_TYPES$1.has(node.type);
715
+ const isFunctionLike$2 = (node) => isNode$2(node) && FUNCTION_NODE_TYPES$2.has(node.type);
716
716
  /**
717
717
  * Checks if a node is a React Hook call (e.g., useState, useEffect, useCallback)
718
718
  * @param {ESTNode} node
719
719
  * @returns {boolean}
720
720
  */
721
- const isReactHookCall = (node) => {
721
+ const isReactHookCall$1 = (node) => {
722
722
  if (node.type !== "CallExpression") return false;
723
723
  const callee = node.callee;
724
724
  if (!callee) return false;
@@ -731,21 +731,21 @@ const isReactHookCall = (node) => {
731
731
  * @param {ESTNode} node
732
732
  * @returns {boolean}
733
733
  */
734
- const containsJSX = (node) => {
735
- if (!node || !isNode$1(node)) return false;
734
+ const containsJSX$1 = (node) => {
735
+ if (!node || !isNode$2(node)) return false;
736
736
  const stack = [node];
737
737
  while (stack.length > 0) {
738
738
  const current = stack.pop();
739
- if (!current || !isNode$1(current)) continue;
739
+ if (!current || !isNode$2(current)) continue;
740
740
  if (current.type === "JSXElement" || current.type === "JSXFragment") return true;
741
- if (isFunctionLike$1(current) && current !== node) continue;
741
+ if (isFunctionLike$2(current) && current !== node) continue;
742
742
  for (const key of Object.keys(current)) {
743
743
  if (key === "parent") continue;
744
744
  const value = current[key];
745
745
  if (!value) continue;
746
746
  if (Array.isArray(value)) {
747
- for (const element of value) if (isNode$1(element)) stack.push(element);
748
- } else if (isNode$1(value)) stack.push(value);
747
+ for (const element of value) if (isNode$2(element)) stack.push(element);
748
+ } else if (isNode$2(value)) stack.push(value);
749
749
  }
750
750
  }
751
751
  return false;
@@ -757,26 +757,26 @@ const containsJSX = (node) => {
757
757
  * @param {Set<string>} localNames - Names of local variables and parameters
758
758
  * @returns {boolean}
759
759
  */
760
- const accessesEnclosingScope = (node, localNames) => {
760
+ const accessesEnclosingScope$1 = (node, localNames) => {
761
761
  if (!node.body) return false;
762
762
  const body = node.body;
763
- if (body.type !== "BlockStatement") return checkExpressionForScopeAccess(body, localNames);
764
- return checkNodeForScopeAccess(body, localNames);
763
+ if (body.type !== "BlockStatement") return checkExpressionForScopeAccess$1(body, localNames);
764
+ return checkNodeForScopeAccess$1(body, localNames);
765
765
  };
766
766
  /**
767
767
  * @param {ESTNode} node
768
768
  * @param {Set<string>} localNames
769
769
  * @returns {boolean}
770
770
  */
771
- const checkNodeForScopeAccess = (node, localNames) => {
772
- if (!node || !isNode$1(node)) return false;
771
+ const checkNodeForScopeAccess$1 = (node, localNames) => {
772
+ if (!node || !isNode$2(node)) return false;
773
773
  const stack = [node];
774
774
  while (stack.length > 0) {
775
775
  const current = stack.pop();
776
- if (!current || !isNode$1(current)) continue;
776
+ if (!current || !isNode$2(current)) continue;
777
777
  if (current.type === "Identifier") {
778
778
  const parent = current.parent;
779
- if (parent && isNode$1(parent) && (parent.type === "VariableDeclarator" || parent.type === "FunctionDeclaration" || parent.type === "Property" && parent.key === current)) continue;
779
+ if (parent && isNode$2(parent) && (parent.type === "VariableDeclarator" || parent.type === "FunctionDeclaration" || parent.type === "Property" && parent.key === current)) continue;
780
780
  if (!localNames.has(current.name)) {
781
781
  if (!new Set([
782
782
  "console",
@@ -811,14 +811,14 @@ const checkNodeForScopeAccess = (node, localNames) => {
811
811
  ]).has(current.name)) return true;
812
812
  }
813
813
  }
814
- if (isFunctionLike$1(current) && current !== node) continue;
814
+ if (isFunctionLike$2(current) && current !== node) continue;
815
815
  for (const key of Object.keys(current)) {
816
816
  if (key === "parent") continue;
817
817
  const value = current[key];
818
818
  if (!value) continue;
819
819
  if (Array.isArray(value)) {
820
- for (const element of value) if (isNode$1(element)) stack.push(element);
821
- } else if (isNode$1(value)) stack.push(value);
820
+ for (const element of value) if (isNode$2(element)) stack.push(element);
821
+ } else if (isNode$2(value)) stack.push(value);
822
822
  }
823
823
  }
824
824
  return false;
@@ -828,19 +828,19 @@ const checkNodeForScopeAccess = (node, localNames) => {
828
828
  * @param {Set<string>} localNames
829
829
  * @returns {boolean}
830
830
  */
831
- const checkExpressionForScopeAccess = (node, localNames) => {
832
- return checkNodeForScopeAccess(node, localNames);
831
+ const checkExpressionForScopeAccess$1 = (node, localNames) => {
832
+ return checkNodeForScopeAccess$1(node, localNames);
833
833
  };
834
834
  /**
835
835
  * Collects all local variable names including parameters
836
836
  * @param {FunctionLikeNode} node
837
837
  * @returns {Set<string>}
838
838
  */
839
- const collectLocalNames = (node) => {
839
+ const collectLocalNames$1 = (node) => {
840
840
  const names = /* @__PURE__ */ new Set();
841
- if (node.params) for (const param of node.params) collectPatternNames(param, names);
841
+ if (node.params) for (const param of node.params) collectPatternNames$1(param, names);
842
842
  if (node.body && node.body.type === "BlockStatement") {
843
- for (const statement of node.body.body) if (statement.type === "VariableDeclaration") for (const declarator of statement.declarations) collectPatternNames(declarator.id, names);
843
+ for (const statement of node.body.body) if (statement.type === "VariableDeclaration") for (const declarator of statement.declarations) collectPatternNames$1(declarator.id, names);
844
844
  }
845
845
  return names;
846
846
  };
@@ -848,8 +848,8 @@ const collectLocalNames = (node) => {
848
848
  * @param {import("oxlint").ESTree.Pattern} pattern
849
849
  * @param {Set<string>} names
850
850
  */
851
- const collectPatternNames = (pattern, names) => {
852
- if (!pattern || !isNode$1(pattern)) return;
851
+ const collectPatternNames$1 = (pattern, names) => {
852
+ if (!pattern || !isNode$2(pattern)) return;
853
853
  if (pattern.type === "Identifier") {
854
854
  names.add(pattern.name);
855
855
  return;
@@ -857,24 +857,24 @@ const collectPatternNames = (pattern, names) => {
857
857
  if (pattern.type === "ArrayPattern") {
858
858
  for (const element of pattern.elements) {
859
859
  if (!element) continue;
860
- if (element.type === "RestElement") collectPatternNames(element.argument, names);
861
- else collectPatternNames(element, names);
860
+ if (element.type === "RestElement") collectPatternNames$1(element.argument, names);
861
+ else collectPatternNames$1(element, names);
862
862
  }
863
863
  return;
864
864
  }
865
865
  if (pattern.type === "ObjectPattern") {
866
866
  for (const property of pattern.properties) {
867
867
  if (!property) continue;
868
- if (property.type === "Property") collectPatternNames(property.value, names);
869
- else if (property.type === "RestElement") collectPatternNames(property.argument, names);
868
+ if (property.type === "Property") collectPatternNames$1(property.value, names);
869
+ else if (property.type === "RestElement") collectPatternNames$1(property.argument, names);
870
870
  }
871
871
  return;
872
872
  }
873
873
  if (pattern.type === "AssignmentPattern") {
874
- collectPatternNames(pattern.left, names);
874
+ collectPatternNames$1(pattern.left, names);
875
875
  return;
876
876
  }
877
- if (pattern.type === "RestElement") collectPatternNames(pattern.argument, names);
877
+ if (pattern.type === "RestElement") collectPatternNames$1(pattern.argument, names);
878
878
  };
879
879
  /**
880
880
  * Checks if a function is likely a React component
@@ -883,28 +883,28 @@ const collectPatternNames = (pattern, names) => {
883
883
  */
884
884
  const isReactComponent = (node) => {
885
885
  if (!isComponentName(getFunctionName(node))) return false;
886
- return containsJSX(node) || containsHooks(node);
886
+ return containsJSX$1(node) || containsHooks$1(node);
887
887
  };
888
888
  /**
889
889
  * Checks if a function contains React Hook calls
890
890
  * @param {FunctionLikeNode} node
891
891
  * @returns {boolean}
892
892
  */
893
- const containsHooks = (node) => {
893
+ const containsHooks$1 = (node) => {
894
894
  if (!node.body) return false;
895
895
  const stack = [node.body];
896
896
  while (stack.length > 0) {
897
897
  const current = stack.pop();
898
- if (!current || !isNode$1(current)) continue;
899
- if (isReactHookCall(current)) return true;
900
- if (isFunctionLike$1(current) && current !== node.body) continue;
898
+ if (!current || !isNode$2(current)) continue;
899
+ if (isReactHookCall$1(current)) return true;
900
+ if (isFunctionLike$2(current) && current !== node.body) continue;
901
901
  for (const key of Object.keys(current)) {
902
902
  if (key === "parent") continue;
903
903
  const value = current[key];
904
904
  if (!value) continue;
905
905
  if (Array.isArray(value)) {
906
- for (const element of value) if (isNode$1(element)) stack.push(element);
907
- } else if (isNode$1(value)) stack.push(value);
906
+ for (const element of value) if (isNode$2(element)) stack.push(element);
907
+ } else if (isNode$2(value)) stack.push(value);
908
908
  }
909
909
  }
910
910
  return false;
@@ -914,10 +914,10 @@ const containsHooks = (node) => {
914
914
  * @param {FunctionLikeNode} node
915
915
  * @returns {boolean}
916
916
  */
917
- const isWrappedInHook = (node) => {
917
+ const isWrappedInHook$1 = (node) => {
918
918
  const parent = node.parent;
919
- if (!parent || !isNode$1(parent)) return false;
920
- if (parent.type === "CallExpression" && isReactHookCall(parent)) return true;
919
+ if (!parent || !isNode$2(parent)) return false;
920
+ if (parent.type === "CallExpression" && isReactHookCall$1(parent)) return true;
921
921
  return false;
922
922
  };
923
923
  /**
@@ -925,14 +925,14 @@ const isWrappedInHook = (node) => {
925
925
  * @param {FunctionLikeNode} node
926
926
  * @returns {boolean}
927
927
  */
928
- const isPureFunction = (node) => {
929
- if (containsJSX(node)) return false;
930
- if (containsHooks(node)) return false;
931
- if (isWrappedInHook(node)) return false;
932
- if (accessesEnclosingScope(node, collectLocalNames(node))) return false;
928
+ const isPureFunction$1 = (node) => {
929
+ if (containsJSX$1(node)) return false;
930
+ if (containsHooks$1(node)) return false;
931
+ if (isWrappedInHook$1(node)) return false;
932
+ if (accessesEnclosingScope$1(node, collectLocalNames$1(node))) return false;
933
933
  return true;
934
934
  };
935
- const rule$9 = defineRule({
935
+ const rule$10 = defineRule({
936
936
  meta: {
937
937
  type: "suggestion",
938
938
  docs: {
@@ -947,11 +947,11 @@ const rule$9 = defineRule({
947
947
  */
948
948
  const handleVariableDeclarator = (node) => {
949
949
  const init = node.init;
950
- if (!init || !isFunctionLike$1(init)) return;
951
- const enclosingFunction = getEnclosingFunction$1(node);
950
+ if (!init || !isFunctionLike$2(init)) return;
951
+ const enclosingFunction = getEnclosingFunction(node);
952
952
  if (!enclosingFunction) return;
953
953
  if (!isReactComponent(enclosingFunction)) return;
954
- if (!isPureFunction(init)) return;
954
+ if (!isPureFunction$1(init)) return;
955
955
  const functionName = node.id && node.id.type === "Identifier" ? node.id.name : "this function";
956
956
  const componentName = getFunctionName(enclosingFunction);
957
957
  context.report({
@@ -964,12 +964,12 @@ const rule$9 = defineRule({
964
964
  } };
965
965
  }
966
966
  });
967
- const noComponentPureFunctionsRule = rule$9;
967
+ const noComponentPureFunctionsRule = rule$10;
968
968
 
969
969
  //#endregion
970
970
  //#region src/oxlint-plugins/no-delete.js
971
971
  /** @typedef {import("oxlint").ESTree.Node} ESTNode */
972
- const rule$8 = defineRule({
972
+ const rule$9 = defineRule({
973
973
  meta: {
974
974
  type: "problem",
975
975
  docs: {
@@ -988,7 +988,7 @@ const rule$8 = defineRule({
988
988
  } };
989
989
  }
990
990
  });
991
- const noDeleteRule = rule$8;
991
+ const noDeleteRule = rule$9;
992
992
 
993
993
  //#endregion
994
994
  //#region src/oxlint-plugins/no-emoji.js
@@ -1018,7 +1018,7 @@ const getEmojiPreview = (text) => {
1018
1018
  const preview = uniqueEmojis.slice(0, 3).join(" ");
1019
1019
  return uniqueEmojis.length > 3 ? `${preview} ...` : preview;
1020
1020
  };
1021
- const rule$7 = defineRule({
1021
+ const rule$8 = defineRule({
1022
1022
  meta: {
1023
1023
  type: "problem",
1024
1024
  docs: {
@@ -1069,12 +1069,12 @@ const rule$7 = defineRule({
1069
1069
  };
1070
1070
  }
1071
1071
  });
1072
- const noEmojiRule = rule$7;
1072
+ const noEmojiRule = rule$8;
1073
1073
 
1074
1074
  //#endregion
1075
1075
  //#region src/oxlint-plugins/no-finally.js
1076
1076
  /** @typedef {import("oxlint").ESTree.Node} ESTNode */
1077
- const rule$6 = defineRule({
1077
+ const rule$7 = defineRule({
1078
1078
  meta: {
1079
1079
  type: "problem",
1080
1080
  docs: {
@@ -1093,12 +1093,12 @@ const rule$6 = defineRule({
1093
1093
  } };
1094
1094
  }
1095
1095
  });
1096
- const noFinallyRule = rule$6;
1096
+ const noFinallyRule = rule$7;
1097
1097
 
1098
1098
  //#endregion
1099
1099
  //#region src/oxlint-plugins/no-iife.js
1100
1100
  /** @typedef {import("oxlint").ESTree.Node} ESTNode */
1101
- const rule$5 = defineRule({
1101
+ const rule$6 = defineRule({
1102
1102
  meta: {
1103
1103
  type: "problem",
1104
1104
  docs: {
@@ -1118,7 +1118,274 @@ const rule$5 = defineRule({
1118
1118
  } };
1119
1119
  }
1120
1120
  });
1121
- const noIifeRule = rule$5;
1121
+ const noIifeRule = rule$6;
1122
+
1123
+ //#endregion
1124
+ //#region src/oxlint-plugins/no-nested-pure-functions.js
1125
+ /**
1126
+ * @typedef {import("oxlint").Context} RuleContext
1127
+ * @typedef {import("oxlint").ESTree.Node} ESTNode
1128
+ * @typedef {import("oxlint").ESTree.Function | import("oxlint").ESTree.ArrowFunctionExpression} FunctionLikeNode
1129
+ * @typedef {import("oxlint").ESTree.VariableDeclarator} VariableDeclaratorNode
1130
+ */
1131
+ const FUNCTION_NODE_TYPES$1 = new Set([
1132
+ "FunctionDeclaration",
1133
+ "FunctionExpression",
1134
+ "ArrowFunctionExpression"
1135
+ ]);
1136
+ /**
1137
+ * @param {unknown} node
1138
+ * @returns {node is ESTNode & { type: string }}
1139
+ */
1140
+ const isNode$1 = (node) => Boolean(node && typeof node === "object" && "type" in node);
1141
+ /**
1142
+ * @param {unknown} node
1143
+ * @returns {node is FunctionLikeNode}
1144
+ */
1145
+ const isFunctionLike$1 = (node) => isNode$1(node) && FUNCTION_NODE_TYPES$1.has(node.type);
1146
+ /**
1147
+ * Checks if a node is a React Hook call (e.g., useState, useEffect, useCallback)
1148
+ * @param {ESTNode} node
1149
+ * @returns {boolean}
1150
+ */
1151
+ const isReactHookCall = (node) => {
1152
+ if (node.type !== "CallExpression") return false;
1153
+ const callee = node.callee;
1154
+ if (!callee) return false;
1155
+ if (callee.type === "Identifier" && callee.name.startsWith("use")) return true;
1156
+ if (callee.type === "MemberExpression" && callee.object && callee.object.type === "Identifier" && callee.object.name === "React" && callee.property && callee.property.type === "Identifier" && callee.property.name.startsWith("use")) return true;
1157
+ return false;
1158
+ };
1159
+ /**
1160
+ * Checks if a node contains JSX
1161
+ * @param {ESTNode} node
1162
+ * @returns {boolean}
1163
+ */
1164
+ const containsJSX = (node) => {
1165
+ if (!node || !isNode$1(node)) return false;
1166
+ const stack = [node];
1167
+ while (stack.length > 0) {
1168
+ const current = stack.pop();
1169
+ if (!current || !isNode$1(current)) continue;
1170
+ if (current.type === "JSXElement" || current.type === "JSXFragment") return true;
1171
+ if (isFunctionLike$1(current) && current !== node) continue;
1172
+ for (const key of Object.keys(current)) {
1173
+ if (key === "parent") continue;
1174
+ const value = current[key];
1175
+ if (!value) continue;
1176
+ if (Array.isArray(value)) {
1177
+ for (const element of value) if (isNode$1(element)) stack.push(element);
1178
+ } else if (isNode$1(value)) stack.push(value);
1179
+ }
1180
+ }
1181
+ return false;
1182
+ };
1183
+ /**
1184
+ * Checks if a function accesses variables from its enclosing scope
1185
+ * (excluding function parameters and locally declared variables)
1186
+ * @param {FunctionLikeNode} node
1187
+ * @param {Set<string>} localNames - Names of local variables and parameters
1188
+ * @returns {boolean}
1189
+ */
1190
+ const accessesEnclosingScope = (node, localNames) => {
1191
+ if (!node.body) return false;
1192
+ const body = node.body;
1193
+ if (body.type !== "BlockStatement") return checkExpressionForScopeAccess(body, localNames);
1194
+ return checkNodeForScopeAccess(body, localNames);
1195
+ };
1196
+ /**
1197
+ * @param {ESTNode} node
1198
+ * @param {Set<string>} localNames
1199
+ * @returns {boolean}
1200
+ */
1201
+ const checkNodeForScopeAccess = (node, localNames) => {
1202
+ if (!node || !isNode$1(node)) return false;
1203
+ const stack = [node];
1204
+ while (stack.length > 0) {
1205
+ const current = stack.pop();
1206
+ if (!current || !isNode$1(current)) continue;
1207
+ if (current.type === "Identifier") {
1208
+ const parent = current.parent;
1209
+ if (parent && isNode$1(parent) && (parent.type === "VariableDeclarator" || parent.type === "FunctionDeclaration" || parent.type === "Property" && parent.key === current)) continue;
1210
+ if (!localNames.has(current.name)) {
1211
+ if (!new Set([
1212
+ "console",
1213
+ "Math",
1214
+ "Date",
1215
+ "JSON",
1216
+ "Object",
1217
+ "Array",
1218
+ "String",
1219
+ "Number",
1220
+ "Boolean",
1221
+ "parseInt",
1222
+ "parseFloat",
1223
+ "isNaN",
1224
+ "isFinite",
1225
+ "undefined",
1226
+ "null",
1227
+ "true",
1228
+ "false",
1229
+ "Infinity",
1230
+ "NaN",
1231
+ "Map",
1232
+ "Set",
1233
+ "WeakMap",
1234
+ "WeakSet",
1235
+ "Promise",
1236
+ "Symbol",
1237
+ "Error",
1238
+ "TypeError",
1239
+ "ReferenceError",
1240
+ "SyntaxError"
1241
+ ]).has(current.name)) return true;
1242
+ }
1243
+ }
1244
+ if (isFunctionLike$1(current) && current !== node) continue;
1245
+ for (const key of Object.keys(current)) {
1246
+ if (key === "parent") continue;
1247
+ const value = current[key];
1248
+ if (!value) continue;
1249
+ if (Array.isArray(value)) {
1250
+ for (const element of value) if (isNode$1(element)) stack.push(element);
1251
+ } else if (isNode$1(value)) stack.push(value);
1252
+ }
1253
+ }
1254
+ return false;
1255
+ };
1256
+ /**
1257
+ * @param {ESTNode} node
1258
+ * @param {Set<string>} localNames
1259
+ * @returns {boolean}
1260
+ */
1261
+ const checkExpressionForScopeAccess = (node, localNames) => {
1262
+ return checkNodeForScopeAccess(node, localNames);
1263
+ };
1264
+ /**
1265
+ * Collects all local variable names including parameters
1266
+ * @param {FunctionLikeNode} node
1267
+ * @returns {Set<string>}
1268
+ */
1269
+ const collectLocalNames = (node) => {
1270
+ const names = /* @__PURE__ */ new Set();
1271
+ if (node.params) for (const param of node.params) collectPatternNames(param, names);
1272
+ if (node.body && node.body.type === "BlockStatement") {
1273
+ for (const statement of node.body.body) if (statement.type === "VariableDeclaration") for (const declarator of statement.declarations) collectPatternNames(declarator.id, names);
1274
+ }
1275
+ return names;
1276
+ };
1277
+ /**
1278
+ * @param {import("oxlint").ESTree.Pattern} pattern
1279
+ * @param {Set<string>} names
1280
+ */
1281
+ const collectPatternNames = (pattern, names) => {
1282
+ if (!pattern || !isNode$1(pattern)) return;
1283
+ if (pattern.type === "Identifier") {
1284
+ names.add(pattern.name);
1285
+ return;
1286
+ }
1287
+ if (pattern.type === "ArrayPattern") {
1288
+ for (const element of pattern.elements) {
1289
+ if (!element) continue;
1290
+ if (element.type === "RestElement") collectPatternNames(element.argument, names);
1291
+ else collectPatternNames(element, names);
1292
+ }
1293
+ return;
1294
+ }
1295
+ if (pattern.type === "ObjectPattern") {
1296
+ for (const property of pattern.properties) {
1297
+ if (!property) continue;
1298
+ if (property.type === "Property") collectPatternNames(property.value, names);
1299
+ else if (property.type === "RestElement") collectPatternNames(property.argument, names);
1300
+ }
1301
+ return;
1302
+ }
1303
+ if (pattern.type === "AssignmentPattern") {
1304
+ collectPatternNames(pattern.left, names);
1305
+ return;
1306
+ }
1307
+ if (pattern.type === "RestElement") collectPatternNames(pattern.argument, names);
1308
+ };
1309
+ /**
1310
+ * Checks if a function contains React Hook calls
1311
+ * @param {FunctionLikeNode} node
1312
+ * @returns {boolean}
1313
+ */
1314
+ const containsHooks = (node) => {
1315
+ if (!node.body) return false;
1316
+ const stack = [node.body];
1317
+ while (stack.length > 0) {
1318
+ const current = stack.pop();
1319
+ if (!current || !isNode$1(current)) continue;
1320
+ if (isReactHookCall(current)) return true;
1321
+ if (isFunctionLike$1(current) && current !== node.body) continue;
1322
+ for (const key of Object.keys(current)) {
1323
+ if (key === "parent") continue;
1324
+ const value = current[key];
1325
+ if (!value) continue;
1326
+ if (Array.isArray(value)) {
1327
+ for (const element of value) if (isNode$1(element)) stack.push(element);
1328
+ } else if (isNode$1(value)) stack.push(value);
1329
+ }
1330
+ }
1331
+ return false;
1332
+ };
1333
+ /**
1334
+ * Checks if a function is wrapped in a React Hook (useCallback, useMemo, etc.)
1335
+ * @param {FunctionLikeNode} node
1336
+ * @returns {boolean}
1337
+ */
1338
+ const isWrappedInHook = (node) => {
1339
+ const parent = node.parent;
1340
+ if (!parent || !isNode$1(parent)) return false;
1341
+ if (parent.type === "CallExpression" && isReactHookCall(parent)) return true;
1342
+ return false;
1343
+ };
1344
+ /**
1345
+ * Checks if a function is pure (doesn't access enclosing scope, hooks, or JSX)
1346
+ * @param {FunctionLikeNode} node
1347
+ * @returns {boolean}
1348
+ */
1349
+ const isPureFunction = (node) => {
1350
+ if (containsJSX(node)) return false;
1351
+ if (containsHooks(node)) return false;
1352
+ if (isWrappedInHook(node)) return false;
1353
+ if (accessesEnclosingScope(node, collectLocalNames(node))) return false;
1354
+ return true;
1355
+ };
1356
+ const rule$5 = defineRule({
1357
+ meta: {
1358
+ type: "suggestion",
1359
+ docs: {
1360
+ description: "Prevent declaring named pure functions inside other functions. Pure functions should be extracted to module scope for better performance and reusability.",
1361
+ recommended: false
1362
+ },
1363
+ schema: []
1364
+ },
1365
+ createOnce(context) {
1366
+ /**
1367
+ * @param {VariableDeclaratorNode} node
1368
+ */
1369
+ const handleVariableDeclarator = (node) => {
1370
+ const init = node.init;
1371
+ if (!init || !isFunctionLike$1(init)) return;
1372
+ if (!node.id || node.id.type !== "Identifier") return;
1373
+ const functionName = node.id.name;
1374
+ const enclosingFunction = getEnclosingFunction(node);
1375
+ if (!enclosingFunction) return;
1376
+ if (!isPureFunction(init)) return;
1377
+ const enclosingFunctionName = getFunctionName(enclosingFunction);
1378
+ context.report({
1379
+ node: init,
1380
+ message: `Named pure function '${functionName}' should not be declared inside '${enclosingFunctionName}'. Extract it to module scope.`
1381
+ });
1382
+ };
1383
+ return { VariableDeclarator(node) {
1384
+ if (node.type === "VariableDeclarator") handleVariableDeclarator(node);
1385
+ } };
1386
+ }
1387
+ });
1388
+ const noNestedPureFunctionsRule = rule$5;
1122
1389
 
1123
1390
  //#endregion
1124
1391
  //#region src/oxlint-plugins/no-promise-then.js
@@ -1239,38 +1506,11 @@ const noSwitchRule = defineRule({
1239
1506
  //#endregion
1240
1507
  //#region src/oxlint-plugins/no-top-level-let.js
1241
1508
  /** @typedef {import("oxlint").ESTree.Node} ESTNode */
1242
- /**
1243
- * Get the enclosing function node for a given node
1244
- * @param {ESTNode} node
1245
- * @returns {ESTNode | null}
1246
- */
1247
- const getEnclosingFunction = (node) => {
1248
- const findFunction = (current) => {
1249
- if (!current) return null;
1250
- if (current.type === "FunctionDeclaration" || current.type === "FunctionExpression" || current.type === "ArrowFunctionExpression") return current;
1251
- return findFunction(current.parent);
1252
- };
1253
- return findFunction(node.parent);
1254
- };
1255
- /**
1256
- * Check if a node is inside a loop
1257
- * @param {ESTNode} node
1258
- * @param {ESTNode} stopAt - Stop searching when we reach this node
1259
- * @returns {boolean}
1260
- */
1261
- const isInsideLoop = (node, stopAt) => {
1262
- const checkLoop = (current) => {
1263
- if (!current || current === stopAt) return false;
1264
- if (current.type === "ForStatement" || current.type === "ForInStatement" || current.type === "ForOfStatement" || current.type === "WhileStatement" || current.type === "DoWhileStatement") return true;
1265
- return checkLoop(current.parent);
1266
- };
1267
- return checkLoop(node.parent);
1268
- };
1269
1509
  const rule$2 = defineRule({
1270
1510
  meta: {
1271
1511
  type: "problem",
1272
1512
  docs: {
1273
- description: "Disallow top-level `let` declarations inside functions to prevent conditional reassignment.",
1513
+ description: "Disallow `let` keyword everywhere except in for loop initializers.",
1274
1514
  recommended: false
1275
1515
  },
1276
1516
  schema: []
@@ -1280,14 +1520,14 @@ const rule$2 = defineRule({
1280
1520
  if (rawNode.type !== "VariableDeclaration") return;
1281
1521
  const node = rawNode;
1282
1522
  if (node.kind !== "let") return;
1283
- const fn = getEnclosingFunction(node);
1284
- if (!fn || fn.type !== "FunctionDeclaration" && fn.type !== "FunctionExpression" && fn.type !== "ArrowFunctionExpression") return;
1285
1523
  const parent = node.parent;
1286
- if (!parent || parent.type !== "BlockStatement" || parent.parent !== fn) return;
1287
- if (isInsideLoop(node, fn)) return;
1524
+ if (parent) {
1525
+ if (parent.type === "ForStatement" && parent.init === node) return;
1526
+ if ((parent.type === "ForInStatement" || parent.type === "ForOfStatement") && parent.left === node) return;
1527
+ }
1288
1528
  context.report({
1289
1529
  node,
1290
- message: "Avoid using `let` at the top level of functions; prefer `const` with extracted functions to avoid conditional reassignment. Extract conditional logic into a separate function that returns the appropriate value."
1530
+ message: "Avoid using `let`; prefer `const` or use `let` only in for loop initializers."
1291
1531
  });
1292
1532
  } };
1293
1533
  }
@@ -1514,6 +1754,7 @@ const plugin = definePlugin({
1514
1754
  "no-finally": noFinallyRule,
1515
1755
  "no-iife": noIifeRule,
1516
1756
  "no-inline-components": noInlineComponentsRule,
1757
+ "no-nested-pure-functions": noNestedPureFunctionsRule,
1517
1758
  "no-promise-then": noPromiseThenRule,
1518
1759
  "no-react-namespace": noReactNamespaceRule,
1519
1760
  "no-switch": noSwitchRule,