@blumintinc/eslint-plugin-blumint 1.9.1 → 1.11.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.
- package/README.md +99 -83
- package/lib/index.js +16 -1
- package/lib/rules/class-methods-read-top-to-bottom.js +10 -0
- package/lib/rules/consistent-callback-naming.js +20 -16
- package/lib/rules/enforce-assert-throws.js +10 -5
- package/lib/rules/enforce-boolean-naming-prefixes.d.ts +7 -0
- package/lib/rules/enforce-boolean-naming-prefixes.js +462 -0
- package/lib/rules/enforce-callable-types.d.ts +1 -1
- package/lib/rules/enforce-callable-types.js +13 -13
- package/lib/rules/enforce-callback-memo.js +6 -3
- package/lib/rules/enforce-centralized-mock-firestore.js +8 -6
- package/lib/rules/enforce-css-media-queries.js +3 -3
- package/lib/rules/enforce-dynamic-file-naming.d.ts +3 -0
- package/lib/rules/enforce-dynamic-file-naming.js +82 -0
- package/lib/rules/enforce-dynamic-imports.js +1 -1
- package/lib/rules/enforce-firestore-doc-ref-generic.js +16 -12
- package/lib/rules/enforce-firestore-facade.js +7 -3
- package/lib/rules/enforce-firestore-path-utils.js +5 -2
- package/lib/rules/enforce-id-capitalization.js +59 -0
- package/lib/rules/enforce-identifiable-firestore-type.js +17 -10
- package/lib/rules/enforce-memoize-async.js +2 -2
- package/lib/rules/enforce-positive-naming.js +71 -27
- package/lib/rules/enforce-props-argument-name.js +31 -9
- package/lib/rules/enforce-realtimedb-path-utils.js +2 -1
- package/lib/rules/enforce-singular-type-names.js +4 -1
- package/lib/rules/enforce-timestamp-now.js +3 -4
- package/lib/rules/enforce-verb-noun-naming.js +18 -8
- package/lib/rules/ensure-pointer-events-none.js +20 -11
- package/lib/rules/extract-global-constants.js +25 -10
- package/lib/rules/fast-deep-equal-over-microdiff.d.ts +3 -0
- package/lib/rules/fast-deep-equal-over-microdiff.js +182 -0
- package/lib/rules/key-only-outermost-element.js +13 -7
- package/lib/rules/no-always-true-false-conditions.js +189 -5
- package/lib/rules/no-async-array-filter.js +1 -1
- package/lib/rules/no-circular-references.js +121 -59
- package/lib/rules/no-complex-cloud-params.js +4 -2
- package/lib/rules/no-entire-object-hook-deps.js +113 -29
- package/lib/rules/no-explicit-return-type.js +3 -2
- package/lib/rules/no-firestore-jest-mock.js +1 -1
- package/lib/rules/no-firestore-object-arrays.js +2 -1
- package/lib/rules/no-hungarian.js +18 -1
- package/lib/rules/no-jsx-in-hooks.js +4 -3
- package/lib/rules/no-margin-properties.d.ts +1 -0
- package/lib/rules/no-margin-properties.js +314 -0
- package/lib/rules/no-mixed-firestore-transactions.js +8 -4
- package/lib/rules/no-mock-firebase-admin.js +6 -1
- package/lib/rules/no-object-values-on-strings.js +28 -10
- package/lib/rules/no-type-assertion-returns.js +47 -6
- package/lib/rules/no-unnecessary-destructuring.js +1 -1
- package/lib/rules/no-unnecessary-verb-suffix.js +0 -31
- package/lib/rules/no-unused-props.js +10 -7
- package/lib/rules/no-unused-usestate.js +19 -6
- package/lib/rules/omit-index-html.js +1 -1
- package/lib/rules/prefer-batch-operations.js +19 -6
- package/lib/rules/prefer-clone-deep.js +16 -11
- package/lib/rules/prefer-destructuring-no-class.js +19 -0
- package/lib/rules/prefer-fragment-component.js +19 -16
- package/lib/rules/prefer-global-router-state-key.js +6 -4
- package/lib/rules/prefer-settings-object.js +1 -1
- package/lib/rules/prefer-usecallback-over-usememo-for-functions.d.ts +8 -0
- package/lib/rules/prefer-usecallback-over-usememo-for-functions.js +180 -0
- package/lib/rules/react-usememo-should-be-component.js +139 -17
- package/lib/rules/require-hooks-default-params.js +25 -15
- package/lib/rules/require-usememo-object-literals.js +3 -2
- package/lib/rules/semantic-function-prefixes.js +15 -3
- package/lib/rules/sync-onwrite-name-func.js +5 -3
- package/lib/utils/ASTHelpers.js +6 -2
- package/lib/utils/graph/ClassGraphBuilder.js +4 -1
- package/lib/utils/graph/ClassGraphSorterReadability.js +3 -1
- package/package.json +3 -3
- package/lib/rules/require-image-overlayed.d.ts +0 -7
- package/lib/rules/require-image-overlayed.js +0 -82
|
@@ -25,7 +25,7 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
|
|
|
25
25
|
function hasAllOptionalProperties(typeNode) {
|
|
26
26
|
// Handle type literals directly
|
|
27
27
|
if (typeNode.type === utils_1.AST_NODE_TYPES.TSTypeLiteral) {
|
|
28
|
-
return typeNode.members.every(member => {
|
|
28
|
+
return typeNode.members.every((member) => {
|
|
29
29
|
if (member.type !== utils_1.AST_NODE_TYPES.TSPropertySignature) {
|
|
30
30
|
return false;
|
|
31
31
|
}
|
|
@@ -39,7 +39,7 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
|
|
|
39
39
|
return false;
|
|
40
40
|
}
|
|
41
41
|
const scope = context.getScope();
|
|
42
|
-
const variable = scope.variables.find(v => v.name === typeName.name);
|
|
42
|
+
const variable = scope.variables.find((v) => v.name === typeName.name);
|
|
43
43
|
if (!variable || !variable.defs[0]?.node) {
|
|
44
44
|
// If we can't find the type definition, assume it's a type with required properties
|
|
45
45
|
// This handles cases where the type is imported from another module
|
|
@@ -50,7 +50,7 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
|
|
|
50
50
|
return hasAllOptionalProperties(def.typeAnnotation);
|
|
51
51
|
}
|
|
52
52
|
else if (def.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration) {
|
|
53
|
-
return def.body.body.every(member => {
|
|
53
|
+
return def.body.body.every((member) => {
|
|
54
54
|
if (member.type !== utils_1.AST_NODE_TYPES.TSPropertySignature) {
|
|
55
55
|
return false;
|
|
56
56
|
}
|
|
@@ -68,7 +68,7 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
|
|
|
68
68
|
}
|
|
69
69
|
// Handle interface declarations
|
|
70
70
|
if (typeNode.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration) {
|
|
71
|
-
return typeNode.body.body.every(member => {
|
|
71
|
+
return typeNode.body.body.every((member) => {
|
|
72
72
|
if (member.type !== utils_1.AST_NODE_TYPES.TSPropertySignature) {
|
|
73
73
|
return false;
|
|
74
74
|
}
|
|
@@ -106,13 +106,14 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
|
|
|
106
106
|
return;
|
|
107
107
|
}
|
|
108
108
|
// Check if the parameter has a type annotation
|
|
109
|
-
if (param.type === utils_1.AST_NODE_TYPES.ObjectPattern &&
|
|
109
|
+
if (param.type === utils_1.AST_NODE_TYPES.ObjectPattern &&
|
|
110
|
+
param.typeAnnotation) {
|
|
110
111
|
const typeAnnotation = param.typeAnnotation.typeAnnotation;
|
|
111
112
|
if (typeAnnotation.type === utils_1.AST_NODE_TYPES.TSTypeReference) {
|
|
112
113
|
const typeName = typeAnnotation.typeName;
|
|
113
114
|
if (typeName.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
114
115
|
const scope = context.getScope();
|
|
115
|
-
const variable = scope.variables.find(v => v.name === typeName.name);
|
|
116
|
+
const variable = scope.variables.find((v) => v.name === typeName.name);
|
|
116
117
|
if (variable && variable.defs[0]?.node) {
|
|
117
118
|
const def = variable.defs[0].node;
|
|
118
119
|
if (def.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration) {
|
|
@@ -121,14 +122,16 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
|
|
|
121
122
|
node: param,
|
|
122
123
|
messageId: 'requireDefaultParams',
|
|
123
124
|
fix(fixer) {
|
|
124
|
-
const paramText = context
|
|
125
|
+
const paramText = context
|
|
126
|
+
.getSourceCode()
|
|
127
|
+
.getText(param);
|
|
125
128
|
return fixer.replaceText(param, `${paramText} = {}`);
|
|
126
129
|
},
|
|
127
130
|
});
|
|
128
131
|
}
|
|
129
132
|
}
|
|
130
133
|
else if (def.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration) {
|
|
131
|
-
if (def.body.body.every(member => {
|
|
134
|
+
if (def.body.body.every((member) => {
|
|
132
135
|
if (member.type !== utils_1.AST_NODE_TYPES.TSPropertySignature) {
|
|
133
136
|
return false;
|
|
134
137
|
}
|
|
@@ -138,7 +141,9 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
|
|
|
138
141
|
node: param,
|
|
139
142
|
messageId: 'requireDefaultParams',
|
|
140
143
|
fix(fixer) {
|
|
141
|
-
const paramText = context
|
|
144
|
+
const paramText = context
|
|
145
|
+
.getSourceCode()
|
|
146
|
+
.getText(param);
|
|
142
147
|
return fixer.replaceText(param, `${paramText} = {}`);
|
|
143
148
|
},
|
|
144
149
|
});
|
|
@@ -148,8 +153,9 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
|
|
|
148
153
|
else {
|
|
149
154
|
// If we can't find the type definition, check if it's defined in the same file
|
|
150
155
|
const program = context.getSourceCode().ast;
|
|
151
|
-
const typeDefinitions = program.body.filter(node => {
|
|
152
|
-
if (node.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration ||
|
|
156
|
+
const typeDefinitions = program.body.filter((node) => {
|
|
157
|
+
if (node.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration ||
|
|
158
|
+
node.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration) {
|
|
153
159
|
if (node.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration) {
|
|
154
160
|
return node.id.name === typeName.name;
|
|
155
161
|
}
|
|
@@ -167,14 +173,16 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
|
|
|
167
173
|
node: param,
|
|
168
174
|
messageId: 'requireDefaultParams',
|
|
169
175
|
fix(fixer) {
|
|
170
|
-
const paramText = context
|
|
176
|
+
const paramText = context
|
|
177
|
+
.getSourceCode()
|
|
178
|
+
.getText(param);
|
|
171
179
|
return fixer.replaceText(param, `${paramText} = {}`);
|
|
172
180
|
},
|
|
173
181
|
});
|
|
174
182
|
}
|
|
175
183
|
}
|
|
176
184
|
else if (def.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration) {
|
|
177
|
-
if (def.body.body.every(member => {
|
|
185
|
+
if (def.body.body.every((member) => {
|
|
178
186
|
if (member.type !== utils_1.AST_NODE_TYPES.TSPropertySignature) {
|
|
179
187
|
return false;
|
|
180
188
|
}
|
|
@@ -184,7 +192,9 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
|
|
|
184
192
|
node: param,
|
|
185
193
|
messageId: 'requireDefaultParams',
|
|
186
194
|
fix(fixer) {
|
|
187
|
-
const paramText = context
|
|
195
|
+
const paramText = context
|
|
196
|
+
.getSourceCode()
|
|
197
|
+
.getText(param);
|
|
188
198
|
return fixer.replaceText(param, `${paramText} = {}`);
|
|
189
199
|
},
|
|
190
200
|
});
|
|
@@ -195,7 +205,7 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
|
|
|
195
205
|
}
|
|
196
206
|
}
|
|
197
207
|
else if (typeAnnotation.type === utils_1.AST_NODE_TYPES.TSTypeLiteral) {
|
|
198
|
-
if (typeAnnotation.members.every(member => {
|
|
208
|
+
if (typeAnnotation.members.every((member) => {
|
|
199
209
|
if (member.type !== utils_1.AST_NODE_TYPES.TSPropertySignature) {
|
|
200
210
|
return false;
|
|
201
211
|
}
|
|
@@ -7,7 +7,7 @@ exports.requireUseMemoObjectLiterals = (0, createRule_1.createRule)({
|
|
|
7
7
|
meta: {
|
|
8
8
|
type: 'suggestion',
|
|
9
9
|
docs: {
|
|
10
|
-
description:
|
|
10
|
+
description: "Enforce using useMemo for inline object/array literals passed as props to JSX components to prevent unnecessary re-renders. When object/array literals are defined inline in JSX, they create new references on every render, causing child components to re-render even if the values haven't changed. Wrap them in useMemo to maintain referential equality.",
|
|
11
11
|
recommended: 'error',
|
|
12
12
|
},
|
|
13
13
|
messages: {
|
|
@@ -25,7 +25,8 @@ exports.requireUseMemoObjectLiterals = (0, createRule_1.createRule)({
|
|
|
25
25
|
}
|
|
26
26
|
// Skip if the prop name is 'sx' or ends with 'Sx'
|
|
27
27
|
const propName = node.name.name;
|
|
28
|
-
if (typeof propName === 'string' &&
|
|
28
|
+
if (typeof propName === 'string' &&
|
|
29
|
+
(propName === 'sx' || propName.endsWith('Sx'))) {
|
|
29
30
|
return;
|
|
30
31
|
}
|
|
31
32
|
const { expression } = node.value;
|
|
@@ -3,8 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.semanticFunctionPrefixes = void 0;
|
|
4
4
|
const utils_1 = require("@typescript-eslint/utils");
|
|
5
5
|
const createRule_1 = require("../utils/createRule");
|
|
6
|
-
const DISALLOWED_PREFIXES = new Set([
|
|
7
|
-
|
|
6
|
+
const DISALLOWED_PREFIXES = new Set([
|
|
7
|
+
'get',
|
|
8
|
+
'update',
|
|
9
|
+
'check',
|
|
10
|
+
'manage',
|
|
11
|
+
'process',
|
|
12
|
+
'do',
|
|
13
|
+
]);
|
|
14
|
+
const NEXTJS_DATA_FUNCTIONS = new Set([
|
|
15
|
+
'getServerSideProps',
|
|
16
|
+
'getStaticProps',
|
|
17
|
+
'getStaticPaths',
|
|
18
|
+
]);
|
|
8
19
|
const SUGGESTED_ALTERNATIVES = {
|
|
9
20
|
get: ['fetch', 'retrieve', 'compute', 'derive'],
|
|
10
21
|
update: ['modify', 'set', 'apply'],
|
|
@@ -75,7 +86,8 @@ exports.semanticFunctionPrefixes = (0, createRule_1.createRule)({
|
|
|
75
86
|
if (node.id) {
|
|
76
87
|
functionName = node.id.name;
|
|
77
88
|
}
|
|
78
|
-
else if (node.parent?.type === utils_1.AST_NODE_TYPES.VariableDeclarator &&
|
|
89
|
+
else if (node.parent?.type === utils_1.AST_NODE_TYPES.VariableDeclarator &&
|
|
90
|
+
node.parent.id.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
79
91
|
functionName = node.parent.id.name;
|
|
80
92
|
}
|
|
81
93
|
if (!functionName)
|
|
@@ -40,14 +40,16 @@ exports.syncOnwriteNameFunc = (0, createRule_1.createRule)({
|
|
|
40
40
|
if (!nameProperty || !funcProperty) {
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
|
-
const nameValue = nameProperty.value
|
|
43
|
+
const nameValue = nameProperty.value
|
|
44
|
+
.value;
|
|
44
45
|
let funcName;
|
|
45
46
|
// Handle variable references
|
|
46
47
|
if (funcProperty.value.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
47
48
|
const funcIdentifier = funcProperty.value;
|
|
48
49
|
const scope = context.getScope();
|
|
49
|
-
const variable = scope.references.find(ref => ref.identifier === funcIdentifier)?.resolved;
|
|
50
|
-
if (variable?.defs[0]?.node.type ===
|
|
50
|
+
const variable = scope.references.find((ref) => ref.identifier === funcIdentifier)?.resolved;
|
|
51
|
+
if (variable?.defs[0]?.node.type ===
|
|
52
|
+
utils_1.AST_NODE_TYPES.VariableDeclarator &&
|
|
51
53
|
variable.defs[0].node.init?.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
52
54
|
// If the variable is initialized with another identifier, use that name
|
|
53
55
|
funcName = variable.defs[0].node.init.name;
|
package/lib/utils/ASTHelpers.js
CHANGED
|
@@ -262,9 +262,13 @@ class ASTHelpers {
|
|
|
262
262
|
default:
|
|
263
263
|
break;
|
|
264
264
|
}
|
|
265
|
-
// Removing duplicates
|
|
265
|
+
// Removing duplicates and ensuring exact matches only
|
|
266
266
|
return [
|
|
267
|
-
...new Set(dependencies.filter((dep) =>
|
|
267
|
+
...new Set(dependencies.filter((dep) => {
|
|
268
|
+
// Only include dependencies that exist exactly in the graph
|
|
269
|
+
// This prevents substring matches (e.g., 'nextMatches' vs 'nextMatchesWithResults')
|
|
270
|
+
return (graph?.[dep] !== undefined && graph?.[dep]?.type !== 'property');
|
|
271
|
+
})),
|
|
268
272
|
];
|
|
269
273
|
}
|
|
270
274
|
static isNode(value) {
|
|
@@ -63,7 +63,10 @@ class ClassGraphBuilder {
|
|
|
63
63
|
return node.type === 'MethodDefinition';
|
|
64
64
|
}
|
|
65
65
|
addDependencies(node, methodName) {
|
|
66
|
-
const newDependencies = ASTHelpers_1.ASTHelpers.classMethodDependenciesOf(node, this.graph, this.className).filter((name) =>
|
|
66
|
+
const newDependencies = ASTHelpers_1.ASTHelpers.classMethodDependenciesOf(node, this.graph, this.className).filter((name) => {
|
|
67
|
+
// Only include dependencies that exist exactly in the graph and aren't self-references
|
|
68
|
+
return !!this.graph[name] && name !== methodName;
|
|
69
|
+
});
|
|
67
70
|
if (this.graph[methodName]) {
|
|
68
71
|
// Ensure dependencies is initialized as an array
|
|
69
72
|
if (!Array.isArray(this.graph[methodName].dependencies)) {
|
|
@@ -72,7 +72,9 @@ class ClassGraphSorterReadability extends ClassGraphSorter_1.ClassGraphSorter {
|
|
|
72
72
|
visited.add(node.name);
|
|
73
73
|
dfsSortedNodes.push(node);
|
|
74
74
|
// Ensure node.dependencies exists and is an array before iterating
|
|
75
|
-
const dependencies = Array.isArray(node.dependencies)
|
|
75
|
+
const dependencies = Array.isArray(node.dependencies)
|
|
76
|
+
? node.dependencies
|
|
77
|
+
: [];
|
|
76
78
|
for (const dep of dependencies) {
|
|
77
79
|
const depNode = this.graph[String(dep)];
|
|
78
80
|
if (depNode) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blumintinc/eslint-plugin-blumint",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"description": "Custom eslint rules for use within BluMint",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Brodie McGuire",
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
"lint:eslint-docs": "npm-run-all \"update:eslint-docs -- --check\"",
|
|
31
31
|
"lint:js": "eslint ./src",
|
|
32
32
|
"lint:shell": "shellcheck .devcontainer/git-flow-completion.bash",
|
|
33
|
-
"lint:fix": "tsc && eslint
|
|
33
|
+
"lint:fix": "tsc && eslint \"./src/**/*\" --quiet --fix",
|
|
34
34
|
"test": "jest --passWithNoTests --reporters=default --reporters=jest-junit",
|
|
35
35
|
"test:ci": "jest --ci --passWithNoTests --reporters=default --reporters=jest-junit",
|
|
36
36
|
"docs": "./scripts/make-docs.sh && npm run update:eslint-docs",
|
|
37
|
-
"update:eslint-docs": "eslint-doc-generator",
|
|
37
|
+
"update:eslint-docs": "eslint-doc-generator --init-rule-docs",
|
|
38
38
|
"build": "tsc",
|
|
39
39
|
"prepare": "husky install && npm run build",
|
|
40
40
|
"version": "git add -A src",
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
const createRule_1 = require("../utils/createRule");
|
|
3
|
-
module.exports = (0, createRule_1.createRule)({
|
|
4
|
-
name: 'require-image-overlayed',
|
|
5
|
-
meta: {
|
|
6
|
-
type: 'problem',
|
|
7
|
-
docs: {
|
|
8
|
-
description: 'Enforce using ImageOverlayed component instead of next/image or img tags',
|
|
9
|
-
recommended: 'error',
|
|
10
|
-
requiresTypeChecking: false,
|
|
11
|
-
},
|
|
12
|
-
fixable: 'code',
|
|
13
|
-
schema: [
|
|
14
|
-
{
|
|
15
|
-
type: 'object',
|
|
16
|
-
properties: {
|
|
17
|
-
componentPath: {
|
|
18
|
-
type: 'string',
|
|
19
|
-
description: 'The import path for the ImageOverlayed component',
|
|
20
|
-
default: 'src/components/ImageOverlayed',
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
additionalProperties: false,
|
|
24
|
-
},
|
|
25
|
-
],
|
|
26
|
-
messages: {
|
|
27
|
-
useImageOverlayed: 'Use ImageOverlayed component from {{ componentPath }} instead of {{ component }}',
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
defaultOptions: [{ componentPath: 'src/components/ImageOverlayed' }],
|
|
31
|
-
create(context) {
|
|
32
|
-
const options = context.options[0] || {
|
|
33
|
-
componentPath: 'src/components/ImageOverlayed',
|
|
34
|
-
};
|
|
35
|
-
const sourceCode = context.getSourceCode();
|
|
36
|
-
return {
|
|
37
|
-
// Handle JSX img elements
|
|
38
|
-
JSXElement(node) {
|
|
39
|
-
if (node.openingElement.name.name === 'img') {
|
|
40
|
-
context.report({
|
|
41
|
-
node,
|
|
42
|
-
messageId: 'useImageOverlayed',
|
|
43
|
-
data: {
|
|
44
|
-
componentPath: options.componentPath,
|
|
45
|
-
component: 'img tag',
|
|
46
|
-
},
|
|
47
|
-
fix(fixer) {
|
|
48
|
-
const attributes = node.openingElement.attributes
|
|
49
|
-
.map((attr) => sourceCode.getText(attr))
|
|
50
|
-
.join(' ');
|
|
51
|
-
return fixer.replaceText(node, `<ImageOverlayed ${attributes} />`);
|
|
52
|
-
},
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
// Handle next/image imports and usage
|
|
57
|
-
ImportDeclaration(node) {
|
|
58
|
-
if (node.source.value === 'next/image' && node.specifiers.length > 0) {
|
|
59
|
-
const imageSpecifier = node.specifiers.find((spec) => (spec.type === 'ImportDefaultSpecifier' ||
|
|
60
|
-
spec.type === 'ImportSpecifier') &&
|
|
61
|
-
(spec.local.name === 'Image' || spec.imported?.name === 'Image'));
|
|
62
|
-
if (imageSpecifier) {
|
|
63
|
-
const localName = imageSpecifier.local.name;
|
|
64
|
-
// Report the import
|
|
65
|
-
context.report({
|
|
66
|
-
node,
|
|
67
|
-
messageId: 'useImageOverlayed',
|
|
68
|
-
data: {
|
|
69
|
-
componentPath: options.componentPath,
|
|
70
|
-
component: 'next/image',
|
|
71
|
-
},
|
|
72
|
-
fix(fixer) {
|
|
73
|
-
return fixer.replaceText(node, `import ${localName} from '${options.componentPath}';`);
|
|
74
|
-
},
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
},
|
|
79
|
-
};
|
|
80
|
-
},
|
|
81
|
-
});
|
|
82
|
-
//# sourceMappingURL=require-image-overlayed.js.map
|