eslint-plugin-nextfriday 1.1.1 → 1.2.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.
- package/CHANGELOG.md +12 -0
- package/README.md +4 -0
- package/docs/rules/ENFORCE_READONLY_COMPONENT_PROPS.md +104 -0
- package/lib/index.cjs +175 -70
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +14 -0
- package/lib/index.d.ts +14 -0
- package/lib/index.js +175 -70
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// package.json
|
|
2
2
|
var package_default = {
|
|
3
3
|
name: "eslint-plugin-nextfriday",
|
|
4
|
-
version: "1.
|
|
4
|
+
version: "1.2.1",
|
|
5
5
|
description: "A comprehensive ESLint plugin providing custom rules and configurations for Next Friday development workflows.",
|
|
6
6
|
keywords: [
|
|
7
7
|
"eslint",
|
|
@@ -116,10 +116,102 @@ var package_default = {
|
|
|
116
116
|
}
|
|
117
117
|
};
|
|
118
118
|
|
|
119
|
+
// src/rules/enforce-readonly-component-props.ts
|
|
120
|
+
import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
|
|
121
|
+
var createRule = ESLintUtils.RuleCreator(
|
|
122
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name}.md`
|
|
123
|
+
);
|
|
124
|
+
var enforceReadonlyComponentProps = createRule({
|
|
125
|
+
name: "enforce-readonly-component-props",
|
|
126
|
+
meta: {
|
|
127
|
+
type: "suggestion",
|
|
128
|
+
docs: {
|
|
129
|
+
description: "Enforce Readonly wrapper for React component props when using named types or interfaces"
|
|
130
|
+
},
|
|
131
|
+
fixable: "code",
|
|
132
|
+
schema: [],
|
|
133
|
+
messages: {
|
|
134
|
+
useReadonly: "Component props should be wrapped with Readonly<> for immutability"
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
defaultOptions: [],
|
|
138
|
+
create(context) {
|
|
139
|
+
function hasJSXInConditional(node) {
|
|
140
|
+
return node.consequent.type === AST_NODE_TYPES.JSXElement || node.consequent.type === AST_NODE_TYPES.JSXFragment || node.alternate.type === AST_NODE_TYPES.JSXElement || node.alternate.type === AST_NODE_TYPES.JSXFragment;
|
|
141
|
+
}
|
|
142
|
+
function hasJSXInLogical(node) {
|
|
143
|
+
return node.right.type === AST_NODE_TYPES.JSXElement || node.right.type === AST_NODE_TYPES.JSXFragment;
|
|
144
|
+
}
|
|
145
|
+
function hasJSXReturn(block) {
|
|
146
|
+
return block.body.some((stmt) => {
|
|
147
|
+
if (stmt.type === AST_NODE_TYPES.ReturnStatement && stmt.argument) {
|
|
148
|
+
return stmt.argument.type === AST_NODE_TYPES.JSXElement || stmt.argument.type === AST_NODE_TYPES.JSXFragment || stmt.argument.type === AST_NODE_TYPES.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === AST_NODE_TYPES.LogicalExpression && hasJSXInLogical(stmt.argument);
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
function isReactComponent(node) {
|
|
154
|
+
if (node.type === AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
155
|
+
if (node.body.type === AST_NODE_TYPES.JSXElement || node.body.type === AST_NODE_TYPES.JSXFragment) {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
if (node.body.type === AST_NODE_TYPES.BlockStatement) {
|
|
159
|
+
return hasJSXReturn(node.body);
|
|
160
|
+
}
|
|
161
|
+
} else if (node.type === AST_NODE_TYPES.FunctionExpression || node.type === AST_NODE_TYPES.FunctionDeclaration) {
|
|
162
|
+
if (node.body && node.body.type === AST_NODE_TYPES.BlockStatement) {
|
|
163
|
+
return hasJSXReturn(node.body);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
function isNamedType(node) {
|
|
169
|
+
return node.type === AST_NODE_TYPES.TSTypeReference;
|
|
170
|
+
}
|
|
171
|
+
function isAlreadyReadonly(node) {
|
|
172
|
+
if (node.type === AST_NODE_TYPES.TSTypeReference && node.typeName) {
|
|
173
|
+
if (node.typeName.type === AST_NODE_TYPES.Identifier && node.typeName.name === "Readonly") {
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
function checkFunction(node) {
|
|
180
|
+
if (!isReactComponent(node)) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
if (node.params.length !== 1) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const param = node.params[0];
|
|
187
|
+
if (param.type === AST_NODE_TYPES.Identifier && param.typeAnnotation) {
|
|
188
|
+
const { typeAnnotation } = param.typeAnnotation;
|
|
189
|
+
if (isNamedType(typeAnnotation) && !isAlreadyReadonly(typeAnnotation)) {
|
|
190
|
+
const { sourceCode } = context;
|
|
191
|
+
const typeText = sourceCode.getText(typeAnnotation);
|
|
192
|
+
context.report({
|
|
193
|
+
node: param.typeAnnotation,
|
|
194
|
+
messageId: "useReadonly",
|
|
195
|
+
fix(fixer) {
|
|
196
|
+
return fixer.replaceText(typeAnnotation, `Readonly<${typeText}>`);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
ArrowFunctionExpression: checkFunction,
|
|
204
|
+
FunctionExpression: checkFunction,
|
|
205
|
+
FunctionDeclaration: checkFunction
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
var enforce_readonly_component_props_default = enforceReadonlyComponentProps;
|
|
210
|
+
|
|
119
211
|
// src/rules/file-kebab-case.ts
|
|
120
212
|
import path from "path";
|
|
121
|
-
import { ESLintUtils } from "@typescript-eslint/utils";
|
|
122
|
-
var
|
|
213
|
+
import { ESLintUtils as ESLintUtils2 } from "@typescript-eslint/utils";
|
|
214
|
+
var createRule2 = ESLintUtils2.RuleCreator(
|
|
123
215
|
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name}.md`
|
|
124
216
|
);
|
|
125
217
|
var isKebabCase = (str) => {
|
|
@@ -128,7 +220,7 @@ var isKebabCase = (str) => {
|
|
|
128
220
|
}
|
|
129
221
|
return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(str);
|
|
130
222
|
};
|
|
131
|
-
var fileKebabCase =
|
|
223
|
+
var fileKebabCase = createRule2({
|
|
132
224
|
name: "file-kebab-case",
|
|
133
225
|
meta: {
|
|
134
226
|
type: "problem",
|
|
@@ -164,12 +256,12 @@ var file_kebab_case_default = fileKebabCase;
|
|
|
164
256
|
|
|
165
257
|
// src/rules/jsx-pascal-case.ts
|
|
166
258
|
import path2 from "path";
|
|
167
|
-
import { ESLintUtils as
|
|
168
|
-
var
|
|
259
|
+
import { ESLintUtils as ESLintUtils3 } from "@typescript-eslint/utils";
|
|
260
|
+
var createRule3 = ESLintUtils3.RuleCreator(
|
|
169
261
|
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name}.md`
|
|
170
262
|
);
|
|
171
263
|
var isPascalCase = (str) => /^[A-Z][a-zA-Z0-9]*$/.test(str) && !/^[A-Z]+$/.test(str);
|
|
172
|
-
var jsxPascalCase =
|
|
264
|
+
var jsxPascalCase = createRule3({
|
|
173
265
|
name: "jsx-pascal-case",
|
|
174
266
|
meta: {
|
|
175
267
|
type: "problem",
|
|
@@ -205,11 +297,11 @@ var jsx_pascal_case_default = jsxPascalCase;
|
|
|
205
297
|
|
|
206
298
|
// src/rules/md-filename-case-restriction.ts
|
|
207
299
|
import path3 from "path";
|
|
208
|
-
import { ESLintUtils as
|
|
209
|
-
var
|
|
300
|
+
import { ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
|
|
301
|
+
var createRule4 = ESLintUtils4.RuleCreator(
|
|
210
302
|
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name}.md`
|
|
211
303
|
);
|
|
212
|
-
var mdFilenameCaseRestriction =
|
|
304
|
+
var mdFilenameCaseRestriction = createRule4({
|
|
213
305
|
name: "md-filename-case-restriction",
|
|
214
306
|
meta: {
|
|
215
307
|
type: "problem",
|
|
@@ -251,11 +343,11 @@ var md_filename_case_restriction_default = mdFilenameCaseRestriction;
|
|
|
251
343
|
|
|
252
344
|
// src/rules/no-emoji.ts
|
|
253
345
|
import emojiRegex from "emoji-regex";
|
|
254
|
-
import { ESLintUtils as
|
|
255
|
-
var
|
|
346
|
+
import { ESLintUtils as ESLintUtils5 } from "@typescript-eslint/utils";
|
|
347
|
+
var createRule5 = ESLintUtils5.RuleCreator(
|
|
256
348
|
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name}.md`
|
|
257
349
|
);
|
|
258
|
-
var noEmoji =
|
|
350
|
+
var noEmoji = createRule5({
|
|
259
351
|
name: "no-emoji",
|
|
260
352
|
meta: {
|
|
261
353
|
type: "problem",
|
|
@@ -289,11 +381,11 @@ var noEmoji = createRule4({
|
|
|
289
381
|
var no_emoji_default = noEmoji;
|
|
290
382
|
|
|
291
383
|
// src/rules/no-explicit-return-type.ts
|
|
292
|
-
import { ESLintUtils as
|
|
293
|
-
var
|
|
384
|
+
import { ESLintUtils as ESLintUtils6 } from "@typescript-eslint/utils";
|
|
385
|
+
var createRule6 = ESLintUtils6.RuleCreator(
|
|
294
386
|
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name}.md`
|
|
295
387
|
);
|
|
296
|
-
var noExplicitReturnType =
|
|
388
|
+
var noExplicitReturnType = createRule6({
|
|
297
389
|
name: "no-explicit-return-type",
|
|
298
390
|
meta: {
|
|
299
391
|
type: "suggestion",
|
|
@@ -333,11 +425,11 @@ var noExplicitReturnType = createRule5({
|
|
|
333
425
|
var no_explicit_return_type_default = noExplicitReturnType;
|
|
334
426
|
|
|
335
427
|
// src/rules/prefer-destructuring-params.ts
|
|
336
|
-
import { AST_NODE_TYPES, ESLintUtils as
|
|
337
|
-
var
|
|
428
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES2, ESLintUtils as ESLintUtils7 } from "@typescript-eslint/utils";
|
|
429
|
+
var createRule7 = ESLintUtils7.RuleCreator(
|
|
338
430
|
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name}.md`
|
|
339
431
|
);
|
|
340
|
-
var preferDestructuringParams =
|
|
432
|
+
var preferDestructuringParams = createRule7({
|
|
341
433
|
name: "prefer-destructuring-params",
|
|
342
434
|
meta: {
|
|
343
435
|
type: "suggestion",
|
|
@@ -352,11 +444,21 @@ var preferDestructuringParams = createRule6({
|
|
|
352
444
|
defaultOptions: [],
|
|
353
445
|
create(context) {
|
|
354
446
|
const checkFunction = (node) => {
|
|
447
|
+
const { filename } = context;
|
|
448
|
+
if (filename.includes("node_modules") || filename.includes(".d.ts")) {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
if (node.type === AST_NODE_TYPES2.FunctionDeclaration && node.id) {
|
|
452
|
+
const functionName = node.id.name;
|
|
453
|
+
if (functionName.startsWith("_") || functionName.includes("$") || /^[A-Z][a-zA-Z]*$/.test(functionName)) {
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
355
457
|
if (node.params.length <= 1) {
|
|
356
458
|
return;
|
|
357
459
|
}
|
|
358
460
|
const hasNonDestructuredParams = node.params.some(
|
|
359
|
-
(param) => param.type !==
|
|
461
|
+
(param) => param.type !== AST_NODE_TYPES2.ObjectPattern && param.type !== AST_NODE_TYPES2.RestElement
|
|
360
462
|
);
|
|
361
463
|
if (hasNonDestructuredParams) {
|
|
362
464
|
context.report({
|
|
@@ -375,11 +477,11 @@ var preferDestructuringParams = createRule6({
|
|
|
375
477
|
var prefer_destructuring_params_default = preferDestructuringParams;
|
|
376
478
|
|
|
377
479
|
// src/rules/prefer-import-type.ts
|
|
378
|
-
import { AST_NODE_TYPES as
|
|
379
|
-
var
|
|
480
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES3, ESLintUtils as ESLintUtils8 } from "@typescript-eslint/utils";
|
|
481
|
+
var createRule8 = ESLintUtils8.RuleCreator(
|
|
380
482
|
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name}.md`
|
|
381
483
|
);
|
|
382
|
-
var preferImportType =
|
|
484
|
+
var preferImportType = createRule8({
|
|
383
485
|
name: "prefer-import-type",
|
|
384
486
|
meta: {
|
|
385
487
|
type: "suggestion",
|
|
@@ -410,14 +512,14 @@ var preferImportType = createRule7({
|
|
|
410
512
|
return;
|
|
411
513
|
}
|
|
412
514
|
const isTypeOnlyImport = node.specifiers.every((specifier) => {
|
|
413
|
-
if (specifier.type ===
|
|
515
|
+
if (specifier.type === AST_NODE_TYPES3.ImportDefaultSpecifier) {
|
|
414
516
|
return false;
|
|
415
517
|
}
|
|
416
|
-
if (specifier.type ===
|
|
518
|
+
if (specifier.type === AST_NODE_TYPES3.ImportNamespaceSpecifier) {
|
|
417
519
|
return false;
|
|
418
520
|
}
|
|
419
|
-
if (specifier.type ===
|
|
420
|
-
const importedName = specifier.imported.type ===
|
|
521
|
+
if (specifier.type === AST_NODE_TYPES3.ImportSpecifier) {
|
|
522
|
+
const importedName = specifier.imported.type === AST_NODE_TYPES3.Identifier ? specifier.imported.name : specifier.imported.value;
|
|
421
523
|
const isKnownTypeOnly = node.source.value === "@typescript-eslint/utils" && ["TSESTree", "RuleContext"].includes(importedName) || node.source.value === "react" && ["Component", "ComponentProps", "ReactNode", "FC", "JSX", "ReactElement", "PropsWithChildren"].includes(
|
|
422
524
|
importedName
|
|
423
525
|
) || importedName.endsWith("Type") || importedName.endsWith("Interface") || importedName.endsWith("Props");
|
|
@@ -445,11 +547,11 @@ var preferImportType = createRule7({
|
|
|
445
547
|
var prefer_import_type_default = preferImportType;
|
|
446
548
|
|
|
447
549
|
// src/rules/prefer-interface-over-inline-types.ts
|
|
448
|
-
import { AST_NODE_TYPES as
|
|
449
|
-
var
|
|
550
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES4, ESLintUtils as ESLintUtils9 } from "@typescript-eslint/utils";
|
|
551
|
+
var createRule9 = ESLintUtils9.RuleCreator(
|
|
450
552
|
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name}.md`
|
|
451
553
|
);
|
|
452
|
-
var preferInterfaceOverInlineTypes =
|
|
554
|
+
var preferInterfaceOverInlineTypes = createRule9({
|
|
453
555
|
name: "prefer-interface-over-inline-types",
|
|
454
556
|
meta: {
|
|
455
557
|
type: "suggestion",
|
|
@@ -465,54 +567,54 @@ var preferInterfaceOverInlineTypes = createRule8({
|
|
|
465
567
|
defaultOptions: [],
|
|
466
568
|
create(context) {
|
|
467
569
|
function hasJSXInConditional(node) {
|
|
468
|
-
return node.consequent.type ===
|
|
570
|
+
return node.consequent.type === AST_NODE_TYPES4.JSXElement || node.consequent.type === AST_NODE_TYPES4.JSXFragment || node.alternate.type === AST_NODE_TYPES4.JSXElement || node.alternate.type === AST_NODE_TYPES4.JSXFragment;
|
|
469
571
|
}
|
|
470
572
|
function hasJSXInLogical(node) {
|
|
471
|
-
return node.right.type ===
|
|
573
|
+
return node.right.type === AST_NODE_TYPES4.JSXElement || node.right.type === AST_NODE_TYPES4.JSXFragment;
|
|
472
574
|
}
|
|
473
575
|
function hasJSXReturn(block) {
|
|
474
576
|
return block.body.some((stmt) => {
|
|
475
|
-
if (stmt.type ===
|
|
476
|
-
return stmt.argument.type ===
|
|
577
|
+
if (stmt.type === AST_NODE_TYPES4.ReturnStatement && stmt.argument) {
|
|
578
|
+
return stmt.argument.type === AST_NODE_TYPES4.JSXElement || stmt.argument.type === AST_NODE_TYPES4.JSXFragment || stmt.argument.type === AST_NODE_TYPES4.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === AST_NODE_TYPES4.LogicalExpression && hasJSXInLogical(stmt.argument);
|
|
477
579
|
}
|
|
478
580
|
return false;
|
|
479
581
|
});
|
|
480
582
|
}
|
|
481
583
|
function isReactComponent(node) {
|
|
482
|
-
if (node.type ===
|
|
483
|
-
if (node.body.type ===
|
|
584
|
+
if (node.type === AST_NODE_TYPES4.ArrowFunctionExpression) {
|
|
585
|
+
if (node.body.type === AST_NODE_TYPES4.JSXElement || node.body.type === AST_NODE_TYPES4.JSXFragment) {
|
|
484
586
|
return true;
|
|
485
587
|
}
|
|
486
|
-
if (node.body.type ===
|
|
588
|
+
if (node.body.type === AST_NODE_TYPES4.BlockStatement) {
|
|
487
589
|
return hasJSXReturn(node.body);
|
|
488
590
|
}
|
|
489
|
-
} else if (node.type ===
|
|
490
|
-
if (node.body && node.body.type ===
|
|
591
|
+
} else if (node.type === AST_NODE_TYPES4.FunctionExpression || node.type === AST_NODE_TYPES4.FunctionDeclaration) {
|
|
592
|
+
if (node.body && node.body.type === AST_NODE_TYPES4.BlockStatement) {
|
|
491
593
|
return hasJSXReturn(node.body);
|
|
492
594
|
}
|
|
493
595
|
}
|
|
494
596
|
return false;
|
|
495
597
|
}
|
|
496
598
|
function isInlineTypeAnnotation(node) {
|
|
497
|
-
if (node.type ===
|
|
599
|
+
if (node.type === AST_NODE_TYPES4.TSTypeLiteral) {
|
|
498
600
|
return true;
|
|
499
601
|
}
|
|
500
|
-
if (node.type ===
|
|
501
|
-
return node.typeArguments.params.some((param) => param.type ===
|
|
602
|
+
if (node.type === AST_NODE_TYPES4.TSTypeReference && node.typeArguments) {
|
|
603
|
+
return node.typeArguments.params.some((param) => param.type === AST_NODE_TYPES4.TSTypeLiteral);
|
|
502
604
|
}
|
|
503
|
-
if (node.type ===
|
|
605
|
+
if (node.type === AST_NODE_TYPES4.TSUnionType) {
|
|
504
606
|
return node.types.some((type) => isInlineTypeAnnotation(type));
|
|
505
607
|
}
|
|
506
608
|
return false;
|
|
507
609
|
}
|
|
508
610
|
function hasInlineObjectType(node) {
|
|
509
|
-
if (node.type ===
|
|
611
|
+
if (node.type === AST_NODE_TYPES4.TSTypeLiteral) {
|
|
510
612
|
return true;
|
|
511
613
|
}
|
|
512
|
-
if (node.type ===
|
|
513
|
-
return node.typeArguments.params.some((param) => param.type ===
|
|
614
|
+
if (node.type === AST_NODE_TYPES4.TSTypeReference && node.typeArguments) {
|
|
615
|
+
return node.typeArguments.params.some((param) => param.type === AST_NODE_TYPES4.TSTypeLiteral);
|
|
514
616
|
}
|
|
515
|
-
if (node.type ===
|
|
617
|
+
if (node.type === AST_NODE_TYPES4.TSUnionType) {
|
|
516
618
|
return node.types.some((type) => hasInlineObjectType(type));
|
|
517
619
|
}
|
|
518
620
|
return false;
|
|
@@ -525,7 +627,7 @@ var preferInterfaceOverInlineTypes = createRule8({
|
|
|
525
627
|
return;
|
|
526
628
|
}
|
|
527
629
|
const param = node.params[0];
|
|
528
|
-
if (param.type ===
|
|
630
|
+
if (param.type === AST_NODE_TYPES4.Identifier && param.typeAnnotation) {
|
|
529
631
|
const { typeAnnotation } = param.typeAnnotation;
|
|
530
632
|
if (isInlineTypeAnnotation(typeAnnotation) && hasInlineObjectType(typeAnnotation)) {
|
|
531
633
|
context.report({
|
|
@@ -545,11 +647,11 @@ var preferInterfaceOverInlineTypes = createRule8({
|
|
|
545
647
|
var prefer_interface_over_inline_types_default = preferInterfaceOverInlineTypes;
|
|
546
648
|
|
|
547
649
|
// src/rules/prefer-react-import-types.ts
|
|
548
|
-
import { AST_NODE_TYPES as
|
|
549
|
-
var
|
|
650
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES5, ESLintUtils as ESLintUtils10 } from "@typescript-eslint/utils";
|
|
651
|
+
var createRule10 = ESLintUtils10.RuleCreator(
|
|
550
652
|
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name}.md`
|
|
551
653
|
);
|
|
552
|
-
var preferReactImportTypes =
|
|
654
|
+
var preferReactImportTypes = createRule10({
|
|
553
655
|
name: "prefer-react-import-types",
|
|
554
656
|
meta: {
|
|
555
657
|
type: "suggestion",
|
|
@@ -625,7 +727,7 @@ var preferReactImportTypes = createRule9({
|
|
|
625
727
|
]);
|
|
626
728
|
const allReactExports = /* @__PURE__ */ new Set([...reactTypes, ...reactRuntimeExports]);
|
|
627
729
|
function checkMemberExpression(node) {
|
|
628
|
-
if (node.object.type ===
|
|
730
|
+
if (node.object.type === AST_NODE_TYPES5.Identifier && node.object.name === "React" && node.property.type === AST_NODE_TYPES5.Identifier && allReactExports.has(node.property.name)) {
|
|
629
731
|
const typeName = node.property.name;
|
|
630
732
|
const isType = reactTypes.has(typeName);
|
|
631
733
|
const importStatement = isType ? `import type { ${typeName} } from "react"` : `import { ${typeName} } from "react"`;
|
|
@@ -642,7 +744,7 @@ var preferReactImportTypes = createRule9({
|
|
|
642
744
|
return {
|
|
643
745
|
MemberExpression: checkMemberExpression,
|
|
644
746
|
"TSTypeReference > TSQualifiedName": (node) => {
|
|
645
|
-
if (node.left.type ===
|
|
747
|
+
if (node.left.type === AST_NODE_TYPES5.Identifier && node.left.name === "React" && node.right.type === AST_NODE_TYPES5.Identifier && allReactExports.has(node.right.name)) {
|
|
646
748
|
const typeName = node.right.name;
|
|
647
749
|
const isType = reactTypes.has(typeName);
|
|
648
750
|
const importStatement = isType ? `import type { ${typeName} } from "react"` : `import { ${typeName} } from "react"`;
|
|
@@ -662,11 +764,11 @@ var preferReactImportTypes = createRule9({
|
|
|
662
764
|
var prefer_react_import_types_default = preferReactImportTypes;
|
|
663
765
|
|
|
664
766
|
// src/rules/react-props-destructure.ts
|
|
665
|
-
import { AST_NODE_TYPES as
|
|
666
|
-
var
|
|
767
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES6, ESLintUtils as ESLintUtils11 } from "@typescript-eslint/utils";
|
|
768
|
+
var createRule11 = ESLintUtils11.RuleCreator(
|
|
667
769
|
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name}.md`
|
|
668
770
|
);
|
|
669
|
-
var reactPropsDestructure =
|
|
771
|
+
var reactPropsDestructure = createRule11({
|
|
670
772
|
name: "react-props-destructure",
|
|
671
773
|
meta: {
|
|
672
774
|
type: "suggestion",
|
|
@@ -682,29 +784,29 @@ var reactPropsDestructure = createRule10({
|
|
|
682
784
|
defaultOptions: [],
|
|
683
785
|
create(context) {
|
|
684
786
|
function hasJSXInConditional(node) {
|
|
685
|
-
return node.consequent.type ===
|
|
787
|
+
return node.consequent.type === AST_NODE_TYPES6.JSXElement || node.consequent.type === AST_NODE_TYPES6.JSXFragment || node.alternate.type === AST_NODE_TYPES6.JSXElement || node.alternate.type === AST_NODE_TYPES6.JSXFragment;
|
|
686
788
|
}
|
|
687
789
|
function hasJSXInLogical(node) {
|
|
688
|
-
return node.right.type ===
|
|
790
|
+
return node.right.type === AST_NODE_TYPES6.JSXElement || node.right.type === AST_NODE_TYPES6.JSXFragment;
|
|
689
791
|
}
|
|
690
792
|
function hasJSXReturn(block) {
|
|
691
793
|
return block.body.some((stmt) => {
|
|
692
|
-
if (stmt.type ===
|
|
693
|
-
return stmt.argument.type ===
|
|
794
|
+
if (stmt.type === AST_NODE_TYPES6.ReturnStatement && stmt.argument) {
|
|
795
|
+
return stmt.argument.type === AST_NODE_TYPES6.JSXElement || stmt.argument.type === AST_NODE_TYPES6.JSXFragment || stmt.argument.type === AST_NODE_TYPES6.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === AST_NODE_TYPES6.LogicalExpression && hasJSXInLogical(stmt.argument);
|
|
694
796
|
}
|
|
695
797
|
return false;
|
|
696
798
|
});
|
|
697
799
|
}
|
|
698
800
|
function isReactComponent(node) {
|
|
699
|
-
if (node.type ===
|
|
700
|
-
if (node.body.type ===
|
|
801
|
+
if (node.type === AST_NODE_TYPES6.ArrowFunctionExpression) {
|
|
802
|
+
if (node.body.type === AST_NODE_TYPES6.JSXElement || node.body.type === AST_NODE_TYPES6.JSXFragment) {
|
|
701
803
|
return true;
|
|
702
804
|
}
|
|
703
|
-
if (node.body.type ===
|
|
805
|
+
if (node.body.type === AST_NODE_TYPES6.BlockStatement) {
|
|
704
806
|
return hasJSXReturn(node.body);
|
|
705
807
|
}
|
|
706
|
-
} else if (node.type ===
|
|
707
|
-
if (node.body && node.body.type ===
|
|
808
|
+
} else if (node.type === AST_NODE_TYPES6.FunctionExpression || node.type === AST_NODE_TYPES6.FunctionDeclaration) {
|
|
809
|
+
if (node.body && node.body.type === AST_NODE_TYPES6.BlockStatement) {
|
|
708
810
|
return hasJSXReturn(node.body);
|
|
709
811
|
}
|
|
710
812
|
}
|
|
@@ -718,9 +820,9 @@ var reactPropsDestructure = createRule10({
|
|
|
718
820
|
return;
|
|
719
821
|
}
|
|
720
822
|
const param = node.params[0];
|
|
721
|
-
if (param.type ===
|
|
722
|
-
const properties = param.properties.filter((prop) => prop.type ===
|
|
723
|
-
if (prop.key.type ===
|
|
823
|
+
if (param.type === AST_NODE_TYPES6.ObjectPattern) {
|
|
824
|
+
const properties = param.properties.filter((prop) => prop.type === AST_NODE_TYPES6.Property).map((prop) => {
|
|
825
|
+
if (prop.key.type === AST_NODE_TYPES6.Identifier) {
|
|
724
826
|
return prop.key.name;
|
|
725
827
|
}
|
|
726
828
|
return null;
|
|
@@ -752,6 +854,7 @@ var meta = {
|
|
|
752
854
|
version: package_default.version
|
|
753
855
|
};
|
|
754
856
|
var rules = {
|
|
857
|
+
"enforce-readonly-component-props": enforce_readonly_component_props_default,
|
|
755
858
|
"file-kebab-case": file_kebab_case_default,
|
|
756
859
|
"jsx-pascal-case": jsx_pascal_case_default,
|
|
757
860
|
"md-filename-case-restriction": md_filename_case_restriction_default,
|
|
@@ -788,12 +891,14 @@ var baseRecommendedRules = {
|
|
|
788
891
|
var jsxRules = {
|
|
789
892
|
"nextfriday/jsx-pascal-case": "warn",
|
|
790
893
|
"nextfriday/prefer-interface-over-inline-types": "warn",
|
|
791
|
-
"nextfriday/react-props-destructure": "warn"
|
|
894
|
+
"nextfriday/react-props-destructure": "warn",
|
|
895
|
+
"nextfriday/enforce-readonly-component-props": "warn"
|
|
792
896
|
};
|
|
793
897
|
var jsxRecommendedRules = {
|
|
794
898
|
"nextfriday/jsx-pascal-case": "error",
|
|
795
899
|
"nextfriday/prefer-interface-over-inline-types": "error",
|
|
796
|
-
"nextfriday/react-props-destructure": "error"
|
|
900
|
+
"nextfriday/react-props-destructure": "error",
|
|
901
|
+
"nextfriday/enforce-readonly-component-props": "error"
|
|
797
902
|
};
|
|
798
903
|
var createConfig = (configRules) => ({
|
|
799
904
|
plugins: {
|