@blumintinc/eslint-plugin-blumint 1.7.3 → 1.8.1

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.
Files changed (70) hide show
  1. package/README.md +83 -61
  2. package/lib/index.js +85 -1
  3. package/lib/rules/enforce-assert-throws.js +48 -3
  4. package/lib/rules/enforce-assertSafe-object-key.d.ts +2 -0
  5. package/lib/rules/enforce-assertSafe-object-key.js +284 -0
  6. package/lib/rules/enforce-centralized-mock-firestore.js +192 -14
  7. package/lib/rules/enforce-css-media-queries.d.ts +5 -0
  8. package/lib/rules/enforce-css-media-queries.js +87 -0
  9. package/lib/rules/enforce-dynamic-imports.d.ts +9 -0
  10. package/lib/rules/enforce-dynamic-imports.js +84 -0
  11. package/lib/rules/enforce-firestore-facade.js +8 -0
  12. package/lib/rules/enforce-id-capitalization.d.ts +6 -0
  13. package/lib/rules/enforce-id-capitalization.js +78 -0
  14. package/lib/rules/enforce-microdiff.d.ts +3 -0
  15. package/lib/rules/enforce-microdiff.js +379 -0
  16. package/lib/rules/enforce-mui-rounded-icons.d.ts +1 -0
  17. package/lib/rules/enforce-mui-rounded-icons.js +54 -0
  18. package/lib/rules/enforce-object-literal-as-const.d.ts +4 -0
  19. package/lib/rules/enforce-object-literal-as-const.js +88 -0
  20. package/lib/rules/enforce-positive-naming.d.ts +1 -0
  21. package/lib/rules/enforce-positive-naming.js +387 -0
  22. package/lib/rules/enforce-props-argument-name.d.ts +8 -0
  23. package/lib/rules/enforce-props-argument-name.js +182 -0
  24. package/lib/rules/enforce-react-type-naming.d.ts +3 -0
  25. package/lib/rules/enforce-react-type-naming.js +191 -0
  26. package/lib/rules/enforce-render-hits-memoization.js +155 -26
  27. package/lib/rules/enforce-singular-type-names.d.ts +2 -0
  28. package/lib/rules/enforce-singular-type-names.js +112 -0
  29. package/lib/rules/enforce-timestamp-now.d.ts +1 -0
  30. package/lib/rules/enforce-timestamp-now.js +223 -0
  31. package/lib/rules/enforce-verb-noun-naming.js +5 -2
  32. package/lib/rules/ensure-pointer-events-none.d.ts +1 -0
  33. package/lib/rules/ensure-pointer-events-none.js +211 -0
  34. package/lib/rules/extract-global-constants.d.ts +1 -1
  35. package/lib/rules/extract-global-constants.js +109 -1
  36. package/lib/rules/global-const-style.js +3 -2
  37. package/lib/rules/key-only-outermost-element.d.ts +3 -0
  38. package/lib/rules/key-only-outermost-element.js +152 -0
  39. package/lib/rules/no-always-true-false-conditions.d.ts +3 -0
  40. package/lib/rules/no-always-true-false-conditions.js +1221 -0
  41. package/lib/rules/no-circular-references.d.ts +1 -0
  42. package/lib/rules/no-circular-references.js +523 -0
  43. package/lib/rules/no-firestore-jest-mock.js +27 -4
  44. package/lib/rules/no-hungarian.d.ts +5 -0
  45. package/lib/rules/no-hungarian.js +223 -0
  46. package/lib/rules/no-mock-firebase-admin.js +20 -7
  47. package/lib/rules/no-object-values-on-strings.d.ts +2 -0
  48. package/lib/rules/no-object-values-on-strings.js +294 -0
  49. package/lib/rules/no-type-assertion-returns.d.ts +9 -0
  50. package/lib/rules/no-type-assertion-returns.js +299 -0
  51. package/lib/rules/no-unnecessary-destructuring.d.ts +5 -0
  52. package/lib/rules/no-unnecessary-destructuring.js +69 -0
  53. package/lib/rules/no-unnecessary-verb-suffix.d.ts +1 -0
  54. package/lib/rules/no-unnecessary-verb-suffix.js +203 -0
  55. package/lib/rules/no-unused-props.js +10 -5
  56. package/lib/rules/no-unused-usestate.d.ts +8 -0
  57. package/lib/rules/no-unused-usestate.js +84 -0
  58. package/lib/rules/omit-index-html.d.ts +7 -0
  59. package/lib/rules/omit-index-html.js +91 -0
  60. package/lib/rules/prefer-clone-deep.js +294 -22
  61. package/lib/rules/prefer-fragment-component.js +265 -34
  62. package/lib/rules/prefer-global-router-state-key.d.ts +5 -0
  63. package/lib/rules/prefer-global-router-state-key.js +89 -0
  64. package/lib/rules/prefer-usememo-over-useeffect-usestate.d.ts +5 -0
  65. package/lib/rules/prefer-usememo-over-useeffect-usestate.js +129 -0
  66. package/lib/rules/prefer-utility-function-over-private-static.d.ts +1 -0
  67. package/lib/rules/prefer-utility-function-over-private-static.js +77 -0
  68. package/lib/rules/react-usememo-should-be-component.d.ts +1 -0
  69. package/lib/rules/react-usememo-should-be-component.js +623 -0
  70. package/package.json +10 -7
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.keyOnlyOutermostElement = void 0;
4
+ const createRule_1 = require("../utils/createRule");
5
+ exports.keyOnlyOutermostElement = (0, createRule_1.createRule)({
6
+ name: 'key-only-outermost-element',
7
+ meta: {
8
+ type: 'problem',
9
+ docs: {
10
+ description: 'Enforce that only the outermost element in list rendering has a key prop',
11
+ recommended: 'error',
12
+ },
13
+ messages: {
14
+ keyOnlyOutermostElement: 'Only the outermost element in a list rendering should have a key prop. Remove the key from this nested element.',
15
+ fragmentShouldHaveKey: 'Fragment used as the outermost element in a list should use <React.Fragment key={...}> instead of shorthand syntax.',
16
+ },
17
+ schema: [],
18
+ fixable: 'code',
19
+ },
20
+ defaultOptions: [],
21
+ create(context) {
22
+ // Track JSXElements that are direct children of a map callback
23
+ const mapCallbackElements = new Set();
24
+ // Track JSXFragments that are direct children of a map callback
25
+ const mapCallbackFragments = new Set();
26
+ // Track JSX attributes that have already been reported to avoid duplicate reports
27
+ const reportedAttributes = new Set();
28
+ // Helper function to process map calls
29
+ const processMapCall = (node) => {
30
+ // Get the callback function
31
+ const callback = node.arguments[0];
32
+ if (callback && (callback.type === 'ArrowFunctionExpression' ||
33
+ callback.type === 'FunctionExpression')) {
34
+ // Find the return statement or expression
35
+ let returnExpr = null;
36
+ if (callback.type === 'ArrowFunctionExpression' &&
37
+ callback.expression &&
38
+ callback.body.type !== 'BlockStatement') {
39
+ // Arrow function with implicit return
40
+ returnExpr = callback.body;
41
+ }
42
+ else {
43
+ // Look for return statements in the function body
44
+ const body = callback.body;
45
+ if (body.type === 'BlockStatement') {
46
+ for (const stmt of body.body) {
47
+ if (stmt.type === 'ReturnStatement' && stmt.argument) {
48
+ returnExpr = stmt.argument;
49
+ break;
50
+ }
51
+ }
52
+ }
53
+ }
54
+ // If we found a JSX element or fragment as the return value, mark it
55
+ if (returnExpr) {
56
+ if (returnExpr.type === 'JSXElement') {
57
+ mapCallbackElements.add(returnExpr);
58
+ }
59
+ else if (returnExpr.type === 'JSXFragment') {
60
+ mapCallbackFragments.add(returnExpr);
61
+ // Check if it's a shorthand fragment (<>)
62
+ // Shorthand fragments can't have keys, so suggest using React.Fragment
63
+ context.report({
64
+ node: returnExpr.openingFragment,
65
+ messageId: 'fragmentShouldHaveKey',
66
+ });
67
+ }
68
+ }
69
+ }
70
+ };
71
+ return {
72
+ // Find array.map() calls
73
+ 'CallExpression[callee.property.name="map"]'(node) {
74
+ processMapCall(node);
75
+ },
76
+ // Check all JSX elements for key props
77
+ JSXElement(node) {
78
+ // Skip if this is the outermost element in a map callback
79
+ if (mapCallbackElements.has(node)) {
80
+ return;
81
+ }
82
+ // Check if this element has a key prop
83
+ const openingElement = node.openingElement;
84
+ const attributes = openingElement.attributes;
85
+ for (let i = 0; i < attributes.length; i++) {
86
+ const attr = attributes[i];
87
+ if (attr.type === 'JSXAttribute' && attr.name.name === 'key' && !reportedAttributes.has(attr)) {
88
+ // Check if this element is nested inside a map callback element or fragment
89
+ let parent = node.parent;
90
+ let isNestedInMapCallback = false;
91
+ while (parent) {
92
+ if ((parent.type === 'JSXElement' && mapCallbackElements.has(parent)) ||
93
+ (parent.type === 'JSXFragment' && mapCallbackFragments.has(parent))) {
94
+ isNestedInMapCallback = true;
95
+ break;
96
+ }
97
+ parent = parent.parent;
98
+ }
99
+ if (isNestedInMapCallback) {
100
+ // Mark this attribute as reported to avoid duplicate reports
101
+ reportedAttributes.add(attr);
102
+ const sourceCode = context.getSourceCode();
103
+ context.report({
104
+ node: attr,
105
+ messageId: 'keyOnlyOutermostElement',
106
+ fix(fixer) {
107
+ // Find the exact range of the attribute in the source code
108
+ const startPos = attr.range[0];
109
+ const endPos = attr.range[1];
110
+ // Get the text before and after the attribute to check for whitespace
111
+ const fullText = sourceCode.getText();
112
+ // Check if there's a space after the attribute
113
+ let rangeEnd = endPos;
114
+ if (rangeEnd < fullText.length && fullText[rangeEnd] === ' ') {
115
+ rangeEnd++;
116
+ }
117
+ return fixer.replaceTextRange([startPos, rangeEnd], '');
118
+ },
119
+ });
120
+ }
121
+ }
122
+ }
123
+ },
124
+ // Handle conditional expressions that might contain map callbacks
125
+ ConditionalExpression(node) {
126
+ // Check both the consequent and alternate branches
127
+ if (node.consequent.type === 'CallExpression' &&
128
+ node.consequent.callee.type === 'MemberExpression' &&
129
+ node.consequent.callee.property.type === 'Identifier' &&
130
+ node.consequent.callee.property.name === 'map') {
131
+ processMapCall(node.consequent);
132
+ }
133
+ if (node.alternate.type === 'CallExpression' &&
134
+ node.alternate.callee.type === 'MemberExpression' &&
135
+ node.alternate.callee.property.type === 'Identifier' &&
136
+ node.alternate.callee.property.name === 'map') {
137
+ processMapCall(node.alternate);
138
+ }
139
+ },
140
+ // Handle logical expressions (&&, ||) that might contain map callbacks
141
+ LogicalExpression(node) {
142
+ if (node.right.type === 'CallExpression' &&
143
+ node.right.callee.type === 'MemberExpression' &&
144
+ node.right.callee.property.type === 'Identifier' &&
145
+ node.right.callee.property.name === 'map') {
146
+ processMapCall(node.right);
147
+ }
148
+ }
149
+ };
150
+ },
151
+ });
152
+ //# sourceMappingURL=key-only-outermost-element.js.map
@@ -0,0 +1,3 @@
1
+ type MessageIds = 'alwaysTrueCondition' | 'alwaysFalseCondition';
2
+ export declare const noAlwaysTrueFalseConditions: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<MessageIds, [], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
3
+ export {};