eslint-plugin-nextfriday 4.3.2 → 5.0.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/CHANGELOG.md +38 -0
- package/README.md +9 -38
- package/docs/rules/BOOLEAN_NAMING_PREFIX.md +0 -1
- package/docs/rules/ENFORCE_CONSTANT_CASE.md +0 -2
- package/docs/rules/ENFORCE_READONLY_COMPONENT_PROPS.md +0 -1
- package/docs/rules/INDEX_EXPORT_ONLY.md +7 -0
- package/docs/rules/NO_GHOST_WRAPPER.md +0 -4
- package/docs/rules/NO_LAZY_IDENTIFIERS.md +1 -2
- package/docs/rules/NO_MISLEADING_CONSTANT_CASE.md +0 -1
- package/docs/rules/PREFER_PROPS_WITH_CHILDREN.md +17 -35
- package/docs/rules/SORT_IMPORTS.md +24 -14
- package/lib/index.cjs +110 -690
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +28 -448
- package/lib/index.d.cts.map +1 -1
- package/lib/index.d.ts +28 -448
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +110 -690
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/docs/rules/ENFORCE_CAMEL_CASE.md +0 -68
- package/docs/rules/ENFORCE_PROPERTY_CASE.md +0 -63
- package/docs/rules/NO_INLINE_DEFAULT_EXPORT.md +0 -97
- package/docs/rules/NO_NESTED_TERNARY.md +0 -45
- package/docs/rules/NO_REDUNDANT_FRAGMENT.md +0 -56
- package/docs/rules/NO_SINGLE_CHAR_VARIABLES.md +0 -98
- package/docs/rules/PREFER_FUNCTION_DECLARATION.md +0 -118
- package/docs/rules/PREFER_INLINE_TYPE_EXPORT.md +0 -64
- package/docs/rules/PREFER_JSX_TEMPLATE_LITERALS.md +0 -80
- package/docs/rules/REACT_PROPS_DESTRUCTURE.md +0 -99
package/lib/index.js
CHANGED
|
@@ -4,10 +4,10 @@ import path from "path";
|
|
|
4
4
|
import emojiRegex from "emoji-regex";
|
|
5
5
|
//#region package.json
|
|
6
6
|
var name = "eslint-plugin-nextfriday";
|
|
7
|
-
var version = "
|
|
7
|
+
var version = "5.0.0";
|
|
8
8
|
//#endregion
|
|
9
9
|
//#region src/rules/boolean-naming-prefix.ts
|
|
10
|
-
const createRule$
|
|
10
|
+
const createRule$26 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
11
11
|
const BOOLEAN_PREFIXES = [
|
|
12
12
|
"is",
|
|
13
13
|
"has",
|
|
@@ -56,7 +56,7 @@ const hasBooleanTypeAnnotation = (node) => {
|
|
|
56
56
|
}
|
|
57
57
|
return false;
|
|
58
58
|
};
|
|
59
|
-
const booleanNamingPrefix = createRule$
|
|
59
|
+
const booleanNamingPrefix = createRule$26({
|
|
60
60
|
name: "boolean-naming-prefix",
|
|
61
61
|
meta: {
|
|
62
62
|
type: "suggestion",
|
|
@@ -116,99 +116,6 @@ const booleanNamingPrefix = createRule$32({
|
|
|
116
116
|
}
|
|
117
117
|
});
|
|
118
118
|
//#endregion
|
|
119
|
-
//#region src/rules/enforce-camel-case.ts
|
|
120
|
-
const createRule$31 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
121
|
-
const SNAKE_CASE_REGEX$2 = /^[a-z]+_[a-z0-9_]*$/;
|
|
122
|
-
const PASCAL_CASE_REGEX = /^[A-Z][a-zA-Z0-9]*$/;
|
|
123
|
-
const REACT_WRAPPERS = [
|
|
124
|
-
"memo",
|
|
125
|
-
"forwardRef",
|
|
126
|
-
"lazy"
|
|
127
|
-
];
|
|
128
|
-
const returnsJsx$1 = (node) => {
|
|
129
|
-
if (node.type === AST_NODE_TYPES.JSXElement || node.type === AST_NODE_TYPES.JSXFragment) return true;
|
|
130
|
-
if (node.type === AST_NODE_TYPES.ConditionalExpression) return returnsJsx$1(node.consequent) || returnsJsx$1(node.alternate);
|
|
131
|
-
if (node.type === AST_NODE_TYPES.LogicalExpression) return returnsJsx$1(node.left) || returnsJsx$1(node.right);
|
|
132
|
-
return false;
|
|
133
|
-
};
|
|
134
|
-
const bodyReturnsJsx$1 = (body) => {
|
|
135
|
-
if (body.type !== AST_NODE_TYPES.BlockStatement) return returnsJsx$1(body);
|
|
136
|
-
return body.body.some((stmt) => stmt.type === AST_NODE_TYPES.ReturnStatement && stmt.argument !== null && returnsJsx$1(stmt.argument));
|
|
137
|
-
};
|
|
138
|
-
const isComponentFunction$1 = (init) => {
|
|
139
|
-
if (init.type === AST_NODE_TYPES.ArrowFunctionExpression || init.type === AST_NODE_TYPES.FunctionExpression) return bodyReturnsJsx$1(init.body);
|
|
140
|
-
if (init.type === AST_NODE_TYPES.CallExpression) {
|
|
141
|
-
const { callee } = init;
|
|
142
|
-
if (callee.type === AST_NODE_TYPES.Identifier && REACT_WRAPPERS.includes(callee.name)) return true;
|
|
143
|
-
if (callee.type === AST_NODE_TYPES.MemberExpression && callee.object.type === AST_NODE_TYPES.Identifier && callee.object.name === "React" && callee.property.type === AST_NODE_TYPES.Identifier && REACT_WRAPPERS.includes(callee.property.name)) return true;
|
|
144
|
-
}
|
|
145
|
-
return false;
|
|
146
|
-
};
|
|
147
|
-
const isGlobalScope$2 = (node) => {
|
|
148
|
-
const declaration = node.parent;
|
|
149
|
-
if (!declaration || declaration.type !== AST_NODE_TYPES.VariableDeclaration) return false;
|
|
150
|
-
const { parent } = declaration;
|
|
151
|
-
if (parent.type === AST_NODE_TYPES.Program) return true;
|
|
152
|
-
if (parent.type === AST_NODE_TYPES.ExportNamedDeclaration && parent.parent?.type === AST_NODE_TYPES.Program) return true;
|
|
153
|
-
return false;
|
|
154
|
-
};
|
|
155
|
-
const isStaticValue$1 = (init) => {
|
|
156
|
-
if (init.type === AST_NODE_TYPES.Literal) return true;
|
|
157
|
-
if (init.type === AST_NODE_TYPES.UnaryExpression && init.argument.type === AST_NODE_TYPES.Literal) return true;
|
|
158
|
-
if (init.type === AST_NODE_TYPES.TemplateLiteral && init.expressions.length === 0) return true;
|
|
159
|
-
if (init.type === AST_NODE_TYPES.ArrayExpression) return init.elements.every((el) => el !== null && el.type !== AST_NODE_TYPES.SpreadElement && isStaticValue$1(el));
|
|
160
|
-
if (init.type === AST_NODE_TYPES.ObjectExpression) return init.properties.every((prop) => prop.type === AST_NODE_TYPES.Property && isStaticValue$1(prop.value));
|
|
161
|
-
if (init.type === AST_NODE_TYPES.TSAsExpression && init.typeAnnotation.type === AST_NODE_TYPES.TSTypeReference && init.typeAnnotation.typeName.type === AST_NODE_TYPES.Identifier && init.typeAnnotation.typeName.name === "const") return true;
|
|
162
|
-
return false;
|
|
163
|
-
};
|
|
164
|
-
const enforceCamelCase = createRule$31({
|
|
165
|
-
name: "enforce-camel-case",
|
|
166
|
-
meta: {
|
|
167
|
-
type: "suggestion",
|
|
168
|
-
docs: { description: "Enforce camelCase for variables and functions, ban snake_case, and restrict PascalCase to React components" },
|
|
169
|
-
messages: {
|
|
170
|
-
noSnakeCase: "Variable '{{ name }}' should not use snake_case. Use camelCase instead.",
|
|
171
|
-
pascalCaseReserved: "Variable '{{ name }}' uses PascalCase but is not a React component. PascalCase is reserved for components."
|
|
172
|
-
},
|
|
173
|
-
schema: []
|
|
174
|
-
},
|
|
175
|
-
defaultOptions: [],
|
|
176
|
-
create(context) {
|
|
177
|
-
return {
|
|
178
|
-
VariableDeclarator(node) {
|
|
179
|
-
if (node.id.type !== AST_NODE_TYPES.Identifier) return;
|
|
180
|
-
const { name } = node.id;
|
|
181
|
-
if (SNAKE_CASE_REGEX$2.test(name)) {
|
|
182
|
-
if (node.parent.kind === "const" && isGlobalScope$2(node) && node.init && isStaticValue$1(node.init)) return;
|
|
183
|
-
context.report({
|
|
184
|
-
node: node.id,
|
|
185
|
-
messageId: "noSnakeCase",
|
|
186
|
-
data: { name }
|
|
187
|
-
});
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
if (!node.init || !PASCAL_CASE_REGEX.test(name)) return;
|
|
191
|
-
if (isComponentFunction$1(node.init)) return;
|
|
192
|
-
if (node.init.type !== AST_NODE_TYPES.ArrowFunctionExpression && node.init.type !== AST_NODE_TYPES.FunctionExpression && node.init.type !== AST_NODE_TYPES.CallExpression) return;
|
|
193
|
-
context.report({
|
|
194
|
-
node: node.id,
|
|
195
|
-
messageId: "pascalCaseReserved",
|
|
196
|
-
data: { name }
|
|
197
|
-
});
|
|
198
|
-
},
|
|
199
|
-
FunctionDeclaration(node) {
|
|
200
|
-
if (!node.id) return;
|
|
201
|
-
const { name } = node.id;
|
|
202
|
-
if (SNAKE_CASE_REGEX$2.test(name)) context.report({
|
|
203
|
-
node: node.id,
|
|
204
|
-
messageId: "noSnakeCase",
|
|
205
|
-
data: { name }
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
//#endregion
|
|
212
119
|
//#region src/utils.ts
|
|
213
120
|
const getFileExtension = (filename) => extname(filename).slice(1);
|
|
214
121
|
const getBaseName = (filename) => basename(filename, extname(filename));
|
|
@@ -222,9 +129,9 @@ const isConfigFile = (filename) => {
|
|
|
222
129
|
};
|
|
223
130
|
//#endregion
|
|
224
131
|
//#region src/rules/enforce-constant-case.ts
|
|
225
|
-
const createRule$
|
|
226
|
-
const SCREAMING_SNAKE_CASE_REGEX$
|
|
227
|
-
const SNAKE_CASE_REGEX
|
|
132
|
+
const createRule$25 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
133
|
+
const SCREAMING_SNAKE_CASE_REGEX$1 = /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/;
|
|
134
|
+
const SNAKE_CASE_REGEX = /^[a-z]+_[a-z0-9_]*$/;
|
|
228
135
|
const toScreamingSnakeCase = (str) => str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toUpperCase();
|
|
229
136
|
const isMagicLiteral = (init) => {
|
|
230
137
|
if (init.type === AST_NODE_TYPES.Literal) return typeof init.value === "string" || typeof init.value === "number";
|
|
@@ -240,7 +147,7 @@ const isGlobalScope$1 = (node) => {
|
|
|
240
147
|
if (parent.type === AST_NODE_TYPES.ExportNamedDeclaration && parent.parent?.type === AST_NODE_TYPES.Program) return true;
|
|
241
148
|
return false;
|
|
242
149
|
};
|
|
243
|
-
const enforceConstantCase = createRule$
|
|
150
|
+
const enforceConstantCase = createRule$25({
|
|
244
151
|
name: "enforce-constant-case",
|
|
245
152
|
meta: {
|
|
246
153
|
type: "suggestion",
|
|
@@ -260,7 +167,7 @@ const enforceConstantCase = createRule$30({
|
|
|
260
167
|
if (declarator.id.type !== AST_NODE_TYPES.Identifier || !declarator.init) return;
|
|
261
168
|
if (!isMagicLiteral(declarator.init)) return;
|
|
262
169
|
const { name } = declarator.id;
|
|
263
|
-
if (SNAKE_CASE_REGEX
|
|
170
|
+
if (SNAKE_CASE_REGEX.test(name)) {
|
|
264
171
|
context.report({
|
|
265
172
|
node: declarator.id,
|
|
266
173
|
messageId: "noSnakeCase",
|
|
@@ -271,7 +178,7 @@ const enforceConstantCase = createRule$30({
|
|
|
271
178
|
});
|
|
272
179
|
return;
|
|
273
180
|
}
|
|
274
|
-
if (!SCREAMING_SNAKE_CASE_REGEX$
|
|
181
|
+
if (!SCREAMING_SNAKE_CASE_REGEX$1.test(name)) context.report({
|
|
275
182
|
node: declarator.id,
|
|
276
183
|
messageId: "useScreamingSnakeCase",
|
|
277
184
|
data: {
|
|
@@ -363,44 +270,6 @@ const enforceHookNaming = ESLintUtils.RuleCreator((name) => `https://github.com/
|
|
|
363
270
|
}
|
|
364
271
|
});
|
|
365
272
|
//#endregion
|
|
366
|
-
//#region src/rules/enforce-property-case.ts
|
|
367
|
-
const createRule$29 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
368
|
-
const SNAKE_CASE_REGEX = /^[a-z]+_[a-z0-9_]*$/;
|
|
369
|
-
const SCREAMING_SNAKE_CASE_REGEX$1 = /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/;
|
|
370
|
-
const isInsideAsConst = (node) => {
|
|
371
|
-
const { parent } = node;
|
|
372
|
-
if (parent.type === AST_NODE_TYPES.TSAsExpression && parent.typeAnnotation.type === AST_NODE_TYPES.TSTypeReference && parent.typeAnnotation.typeName.type === AST_NODE_TYPES.Identifier && parent.typeAnnotation.typeName.name === "const") return true;
|
|
373
|
-
if (parent.type === AST_NODE_TYPES.ArrayExpression) {
|
|
374
|
-
const grandparent = parent.parent;
|
|
375
|
-
if (grandparent?.type === AST_NODE_TYPES.TSAsExpression && grandparent.typeAnnotation.type === AST_NODE_TYPES.TSTypeReference && grandparent.typeAnnotation.typeName.type === AST_NODE_TYPES.Identifier && grandparent.typeAnnotation.typeName.name === "const") return true;
|
|
376
|
-
}
|
|
377
|
-
return false;
|
|
378
|
-
};
|
|
379
|
-
const enforcePropertyCase = createRule$29({
|
|
380
|
-
name: "enforce-property-case",
|
|
381
|
-
meta: {
|
|
382
|
-
type: "suggestion",
|
|
383
|
-
docs: { description: "Enforce camelCase for unquoted object property keys" },
|
|
384
|
-
messages: { useCamelCase: "Property '{{ name }}' should use camelCase. Use camelCase for object properties, or wrap in quotes if required by an API." },
|
|
385
|
-
schema: []
|
|
386
|
-
},
|
|
387
|
-
defaultOptions: [],
|
|
388
|
-
create(context) {
|
|
389
|
-
return { Property(node) {
|
|
390
|
-
if (node.parent.type !== AST_NODE_TYPES.ObjectExpression) return;
|
|
391
|
-
if (isInsideAsConst(node.parent)) return;
|
|
392
|
-
if (node.computed) return;
|
|
393
|
-
if (node.key.type !== AST_NODE_TYPES.Identifier) return;
|
|
394
|
-
const { name } = node.key;
|
|
395
|
-
if (SNAKE_CASE_REGEX.test(name) || SCREAMING_SNAKE_CASE_REGEX$1.test(name)) context.report({
|
|
396
|
-
node: node.key,
|
|
397
|
-
messageId: "useCamelCase",
|
|
398
|
-
data: { name }
|
|
399
|
-
});
|
|
400
|
-
} };
|
|
401
|
-
}
|
|
402
|
-
});
|
|
403
|
-
//#endregion
|
|
404
273
|
//#region src/rules/enforce-props-suffix.ts
|
|
405
274
|
const enforcePropsSuffix = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
|
|
406
275
|
name: "enforce-props-suffix",
|
|
@@ -509,7 +378,7 @@ const enforceReadonlyComponentProps = ESLintUtils.RuleCreator((name) => `https:/
|
|
|
509
378
|
});
|
|
510
379
|
//#endregion
|
|
511
380
|
//#region src/rules/enforce-render-naming.ts
|
|
512
|
-
const createRule$
|
|
381
|
+
const createRule$24 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
513
382
|
const ARRAY_RETURNING_METHODS = new Set([
|
|
514
383
|
"map",
|
|
515
384
|
"flatMap",
|
|
@@ -558,7 +427,7 @@ function isComponentFunction(node) {
|
|
|
558
427
|
if (parent?.type === AST_NODE_TYPES.VariableDeclarator && parent.id.type === AST_NODE_TYPES.Identifier && isPascalCase$1(parent.id.name)) return true;
|
|
559
428
|
return false;
|
|
560
429
|
}
|
|
561
|
-
const enforceRenderNaming = createRule$
|
|
430
|
+
const enforceRenderNaming = createRule$24({
|
|
562
431
|
name: "enforce-render-naming",
|
|
563
432
|
meta: {
|
|
564
433
|
type: "problem",
|
|
@@ -610,7 +479,7 @@ const enforceRenderNaming = createRule$28({
|
|
|
610
479
|
});
|
|
611
480
|
//#endregion
|
|
612
481
|
//#region src/rules/enforce-service-naming.ts
|
|
613
|
-
const createRule$
|
|
482
|
+
const createRule$23 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
614
483
|
const BANNED_PREFIXES = {
|
|
615
484
|
delete: ["remove", "archive"],
|
|
616
485
|
do: ["submit", "process"],
|
|
@@ -621,7 +490,7 @@ const BANNED_PREFIXES = {
|
|
|
621
490
|
"patch"
|
|
622
491
|
]
|
|
623
492
|
};
|
|
624
|
-
const enforceServiceNaming = createRule$
|
|
493
|
+
const enforceServiceNaming = createRule$23({
|
|
625
494
|
name: "enforce-service-naming",
|
|
626
495
|
meta: {
|
|
627
496
|
type: "suggestion",
|
|
@@ -659,7 +528,7 @@ const enforceServiceNaming = createRule$27({
|
|
|
659
528
|
});
|
|
660
529
|
//#endregion
|
|
661
530
|
//#region src/rules/enforce-test-filename.ts
|
|
662
|
-
const createRule$
|
|
531
|
+
const createRule$22 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
663
532
|
const TEST_GLOBALS = new Set([
|
|
664
533
|
"describe",
|
|
665
534
|
"it",
|
|
@@ -669,7 +538,7 @@ const TEST_GLOBALS = new Set([
|
|
|
669
538
|
"afterEach",
|
|
670
539
|
"afterAll"
|
|
671
540
|
]);
|
|
672
|
-
const enforceTestFilename = createRule$
|
|
541
|
+
const enforceTestFilename = createRule$22({
|
|
673
542
|
name: "enforce-test-filename",
|
|
674
543
|
meta: {
|
|
675
544
|
type: "suggestion",
|
|
@@ -749,7 +618,7 @@ const enforceSortedDestructuring = ESLintUtils.RuleCreator((name) => `https://gi
|
|
|
749
618
|
});
|
|
750
619
|
//#endregion
|
|
751
620
|
//#region src/rules/enforce-type-declaration-order.ts
|
|
752
|
-
const createRule$
|
|
621
|
+
const createRule$21 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
753
622
|
function getTypeDeclarationName(node) {
|
|
754
623
|
if (node.type === AST_NODE_TYPES.TSInterfaceDeclaration && node.id.type === AST_NODE_TYPES.Identifier) return {
|
|
755
624
|
name: node.id.name,
|
|
@@ -761,7 +630,7 @@ function getTypeDeclarationName(node) {
|
|
|
761
630
|
};
|
|
762
631
|
return null;
|
|
763
632
|
}
|
|
764
|
-
const enforceTypeDeclarationOrder = createRule$
|
|
633
|
+
const enforceTypeDeclarationOrder = createRule$21({
|
|
765
634
|
name: "enforce-type-declaration-order",
|
|
766
635
|
meta: {
|
|
767
636
|
type: "suggestion",
|
|
@@ -816,7 +685,7 @@ const enforceTypeDeclarationOrder = createRule$25({
|
|
|
816
685
|
});
|
|
817
686
|
//#endregion
|
|
818
687
|
//#region src/rules/index-export-only.ts
|
|
819
|
-
const createRule$
|
|
688
|
+
const createRule$20 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
820
689
|
const isIndexFile = (filename) => getBaseName(filename) === "index";
|
|
821
690
|
const isAllowedExportNamed = (node) => {
|
|
822
691
|
if (!node.declaration) return true;
|
|
@@ -830,12 +699,16 @@ const isAllowedTopLevel = (node) => {
|
|
|
830
699
|
case AST_NODE_TYPES.TSTypeAliasDeclaration:
|
|
831
700
|
case AST_NODE_TYPES.TSInterfaceDeclaration:
|
|
832
701
|
case AST_NODE_TYPES.TSImportEqualsDeclaration: return true;
|
|
702
|
+
case AST_NODE_TYPES.ExpressionStatement: {
|
|
703
|
+
const { expression } = node;
|
|
704
|
+
return expression.type === AST_NODE_TYPES.Literal && typeof expression.value === "string";
|
|
705
|
+
}
|
|
833
706
|
case AST_NODE_TYPES.ExportNamedDeclaration: return isAllowedExportNamed(node);
|
|
834
707
|
case AST_NODE_TYPES.ExportDefaultDeclaration: return isAllowedExportDefault(node);
|
|
835
708
|
default: return false;
|
|
836
709
|
}
|
|
837
710
|
};
|
|
838
|
-
const indexExportOnly = createRule$
|
|
711
|
+
const indexExportOnly = createRule$20({
|
|
839
712
|
name: "index-export-only",
|
|
840
713
|
meta: {
|
|
841
714
|
type: "suggestion",
|
|
@@ -909,7 +782,7 @@ const jsxNewlineBetweenElements = ESLintUtils.RuleCreator((name) => `https://git
|
|
|
909
782
|
});
|
|
910
783
|
//#endregion
|
|
911
784
|
//#region src/rules/jsx-no-data-array.ts
|
|
912
|
-
const createRule$
|
|
785
|
+
const createRule$19 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
913
786
|
function isObjectLikeElement(node) {
|
|
914
787
|
if (!node) return false;
|
|
915
788
|
if (node.type === AST_NODE_TYPES.ObjectExpression) return true;
|
|
@@ -922,7 +795,7 @@ function getArrayInitializer(init) {
|
|
|
922
795
|
if (init.type === AST_NODE_TYPES.TSAsExpression || init.type === AST_NODE_TYPES.TSSatisfiesExpression) return getArrayInitializer(init.expression);
|
|
923
796
|
return null;
|
|
924
797
|
}
|
|
925
|
-
const jsxNoDataArray = createRule$
|
|
798
|
+
const jsxNoDataArray = createRule$19({
|
|
926
799
|
name: "jsx-no-data-array",
|
|
927
800
|
meta: {
|
|
928
801
|
type: "problem",
|
|
@@ -963,7 +836,7 @@ const jsxNoDataArray = createRule$23({
|
|
|
963
836
|
});
|
|
964
837
|
//#endregion
|
|
965
838
|
//#region src/rules/jsx-no-data-object.ts
|
|
966
|
-
const createRule$
|
|
839
|
+
const createRule$18 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
967
840
|
function unwrapAssertion(node) {
|
|
968
841
|
if (!node) return null;
|
|
969
842
|
if (node.type === AST_NODE_TYPES.TSAsExpression || node.type === AST_NODE_TYPES.TSSatisfiesExpression) return unwrapAssertion(node.expression);
|
|
@@ -993,7 +866,7 @@ function getObjectInitializer(init) {
|
|
|
993
866
|
if (unwrapped.type === AST_NODE_TYPES.ObjectExpression) return unwrapped;
|
|
994
867
|
return null;
|
|
995
868
|
}
|
|
996
|
-
const jsxNoDataObject = createRule$
|
|
869
|
+
const jsxNoDataObject = createRule$18({
|
|
997
870
|
name: "jsx-no-data-object",
|
|
998
871
|
meta: {
|
|
999
872
|
type: "problem",
|
|
@@ -1046,14 +919,14 @@ const jsxNoInlineObjectProp = ESLintUtils.RuleCreator((name) => `https://github.
|
|
|
1046
919
|
});
|
|
1047
920
|
//#endregion
|
|
1048
921
|
//#region src/rules/jsx-no-newline-single-line-elements.ts
|
|
1049
|
-
const createRule$
|
|
922
|
+
const createRule$17 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
1050
923
|
function isJSXElementOrFragment(node) {
|
|
1051
924
|
return node.type === AST_NODE_TYPES.JSXElement || node.type === AST_NODE_TYPES.JSXFragment;
|
|
1052
925
|
}
|
|
1053
926
|
function isSingleLine(node) {
|
|
1054
927
|
return node.loc.start.line === node.loc.end.line;
|
|
1055
928
|
}
|
|
1056
|
-
const jsxNoNewlineSingleLineElements = createRule$
|
|
929
|
+
const jsxNoNewlineSingleLineElements = createRule$17({
|
|
1057
930
|
name: "jsx-no-newline-single-line-elements",
|
|
1058
931
|
meta: {
|
|
1059
932
|
type: "layout",
|
|
@@ -1152,7 +1025,7 @@ const jsxNoNonComponentFunction = ESLintUtils.RuleCreator((name) => `https://git
|
|
|
1152
1025
|
});
|
|
1153
1026
|
//#endregion
|
|
1154
1027
|
//#region src/rules/jsx-no-sub-interface.ts
|
|
1155
|
-
const createRule$
|
|
1028
|
+
const createRule$16 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
1156
1029
|
const PROPS_WRAPPER_NAMES = new Set([
|
|
1157
1030
|
"Readonly",
|
|
1158
1031
|
"Required",
|
|
@@ -1184,7 +1057,7 @@ function getDeclarationFromExportWrapper(node) {
|
|
|
1184
1057
|
if (node.type === AST_NODE_TYPES.ExportDefaultDeclaration) return node.declaration;
|
|
1185
1058
|
return node;
|
|
1186
1059
|
}
|
|
1187
|
-
const jsxNoSubInterface = createRule$
|
|
1060
|
+
const jsxNoSubInterface = createRule$16({
|
|
1188
1061
|
name: "jsx-no-sub-interface",
|
|
1189
1062
|
meta: {
|
|
1190
1063
|
type: "problem",
|
|
@@ -1251,13 +1124,13 @@ const jsxNoSubInterface = createRule$20({
|
|
|
1251
1124
|
});
|
|
1252
1125
|
//#endregion
|
|
1253
1126
|
//#region src/rules/jsx-no-ternary-null.ts
|
|
1254
|
-
const createRule$
|
|
1127
|
+
const createRule$15 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
1255
1128
|
function isNullOrUndefined(node) {
|
|
1256
1129
|
if (node.type === AST_NODE_TYPES.Literal && node.value === null) return true;
|
|
1257
1130
|
if (node.type === AST_NODE_TYPES.Identifier && node.name === "undefined") return true;
|
|
1258
1131
|
return false;
|
|
1259
1132
|
}
|
|
1260
|
-
const jsxNoTernaryNull = createRule$
|
|
1133
|
+
const jsxNoTernaryNull = createRule$15({
|
|
1261
1134
|
name: "jsx-no-ternary-null",
|
|
1262
1135
|
meta: {
|
|
1263
1136
|
type: "suggestion",
|
|
@@ -1424,7 +1297,7 @@ const jsxSimpleProps = ESLintUtils.RuleCreator((name) => `https://github.com/nex
|
|
|
1424
1297
|
});
|
|
1425
1298
|
//#endregion
|
|
1426
1299
|
//#region src/rules/jsx-sort-props.ts
|
|
1427
|
-
const createRule$
|
|
1300
|
+
const createRule$14 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
1428
1301
|
const TYPE_GROUP = {
|
|
1429
1302
|
STRING: 1,
|
|
1430
1303
|
HYPHENATED_STRING: 2,
|
|
@@ -1507,7 +1380,7 @@ function getSegments(attributes) {
|
|
|
1507
1380
|
if (current.length > 0) result.push(current);
|
|
1508
1381
|
return result;
|
|
1509
1382
|
}
|
|
1510
|
-
const jsxSortProps = createRule$
|
|
1383
|
+
const jsxSortProps = createRule$14({
|
|
1511
1384
|
name: "jsx-sort-props",
|
|
1512
1385
|
meta: {
|
|
1513
1386
|
type: "suggestion",
|
|
@@ -1562,7 +1435,7 @@ const jsxSpreadPropsLast = ESLintUtils.RuleCreator((name) => `https://github.com
|
|
|
1562
1435
|
});
|
|
1563
1436
|
//#endregion
|
|
1564
1437
|
//#region src/rules/newline-after-multiline-block.ts
|
|
1565
|
-
const createRule$
|
|
1438
|
+
const createRule$13 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
1566
1439
|
function isImportDeclaration(node) {
|
|
1567
1440
|
return node.type === AST_NODE_TYPES.ImportDeclaration;
|
|
1568
1441
|
}
|
|
@@ -1587,7 +1460,7 @@ function checkStatements(statements, context) {
|
|
|
1587
1460
|
});
|
|
1588
1461
|
});
|
|
1589
1462
|
}
|
|
1590
|
-
const newlineAfterMultilineBlock = createRule$
|
|
1463
|
+
const newlineAfterMultilineBlock = createRule$13({
|
|
1591
1464
|
name: "newline-after-multiline-block",
|
|
1592
1465
|
meta: {
|
|
1593
1466
|
type: "layout",
|
|
@@ -1773,12 +1646,12 @@ const noEnvFallback = ESLintUtils.RuleCreator((name) => `https://github.com/next
|
|
|
1773
1646
|
});
|
|
1774
1647
|
//#endregion
|
|
1775
1648
|
//#region src/rules/no-ghost-wrapper.ts
|
|
1776
|
-
const createRule$
|
|
1649
|
+
const createRule$12 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
1777
1650
|
const GHOST_TAGS = new Set(["div", "span"]);
|
|
1778
1651
|
function isKeyAttribute(attribute) {
|
|
1779
1652
|
return attribute.type === AST_NODE_TYPES.JSXAttribute && attribute.name.type === AST_NODE_TYPES.JSXIdentifier && attribute.name.name === "key";
|
|
1780
1653
|
}
|
|
1781
|
-
const noGhostWrapper = createRule$
|
|
1654
|
+
const noGhostWrapper = createRule$12({
|
|
1782
1655
|
name: "no-ghost-wrapper",
|
|
1783
1656
|
meta: {
|
|
1784
1657
|
type: "problem",
|
|
@@ -1875,82 +1748,8 @@ const noHelperFunctionInTest = ESLintUtils.RuleCreator((name) => `https://github
|
|
|
1875
1748
|
}
|
|
1876
1749
|
});
|
|
1877
1750
|
//#endregion
|
|
1878
|
-
//#region src/rules/no-inline-default-export.ts
|
|
1879
|
-
const noInlineDefaultExport = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
|
|
1880
|
-
name: "no-inline-default-export",
|
|
1881
|
-
meta: {
|
|
1882
|
-
type: "suggestion",
|
|
1883
|
-
docs: { description: "Disallow inline exports. Prefer declaring first, then exporting separately." },
|
|
1884
|
-
messages: {
|
|
1885
|
-
noInlineDefaultExport: "Avoid inline default export. Declare the {{type}} first, then export it separately: `export default {{name}};`",
|
|
1886
|
-
noAnonymousDefaultExport: "Avoid anonymous default export. Declare a named {{type}} first, then export it separately.",
|
|
1887
|
-
noInlineNamedExport: "Avoid inline named export. Declare the {{type}} first, then export it separately: `export { {{name}} };`"
|
|
1888
|
-
},
|
|
1889
|
-
schema: []
|
|
1890
|
-
},
|
|
1891
|
-
defaultOptions: [],
|
|
1892
|
-
create(context) {
|
|
1893
|
-
return {
|
|
1894
|
-
ExportDefaultDeclaration(node) {
|
|
1895
|
-
const { declaration } = node;
|
|
1896
|
-
if (declaration.type === AST_NODE_TYPES.FunctionDeclaration) if (declaration.id) context.report({
|
|
1897
|
-
node,
|
|
1898
|
-
messageId: "noInlineDefaultExport",
|
|
1899
|
-
data: {
|
|
1900
|
-
type: "function",
|
|
1901
|
-
name: declaration.id.name
|
|
1902
|
-
}
|
|
1903
|
-
});
|
|
1904
|
-
else context.report({
|
|
1905
|
-
node,
|
|
1906
|
-
messageId: "noAnonymousDefaultExport",
|
|
1907
|
-
data: { type: "function" }
|
|
1908
|
-
});
|
|
1909
|
-
if (declaration.type === AST_NODE_TYPES.ClassDeclaration) if (declaration.id) context.report({
|
|
1910
|
-
node,
|
|
1911
|
-
messageId: "noInlineDefaultExport",
|
|
1912
|
-
data: {
|
|
1913
|
-
type: "class",
|
|
1914
|
-
name: declaration.id.name
|
|
1915
|
-
}
|
|
1916
|
-
});
|
|
1917
|
-
else context.report({
|
|
1918
|
-
node,
|
|
1919
|
-
messageId: "noAnonymousDefaultExport",
|
|
1920
|
-
data: { type: "class" }
|
|
1921
|
-
});
|
|
1922
|
-
if (declaration.type === AST_NODE_TYPES.ArrowFunctionExpression || declaration.type === AST_NODE_TYPES.FunctionExpression) context.report({
|
|
1923
|
-
node,
|
|
1924
|
-
messageId: "noAnonymousDefaultExport",
|
|
1925
|
-
data: { type: "function" }
|
|
1926
|
-
});
|
|
1927
|
-
},
|
|
1928
|
-
ExportNamedDeclaration(node) {
|
|
1929
|
-
const { declaration } = node;
|
|
1930
|
-
if (!declaration) return;
|
|
1931
|
-
if (declaration.type === AST_NODE_TYPES.FunctionDeclaration && declaration.id) context.report({
|
|
1932
|
-
node,
|
|
1933
|
-
messageId: "noInlineNamedExport",
|
|
1934
|
-
data: {
|
|
1935
|
-
type: "function",
|
|
1936
|
-
name: declaration.id.name
|
|
1937
|
-
}
|
|
1938
|
-
});
|
|
1939
|
-
if (declaration.type === AST_NODE_TYPES.ClassDeclaration && declaration.id) context.report({
|
|
1940
|
-
node,
|
|
1941
|
-
messageId: "noInlineNamedExport",
|
|
1942
|
-
data: {
|
|
1943
|
-
type: "class",
|
|
1944
|
-
name: declaration.id.name
|
|
1945
|
-
}
|
|
1946
|
-
});
|
|
1947
|
-
}
|
|
1948
|
-
};
|
|
1949
|
-
}
|
|
1950
|
-
});
|
|
1951
|
-
//#endregion
|
|
1952
1751
|
//#region src/rules/no-inline-nested-object.ts
|
|
1953
|
-
const createRule$
|
|
1752
|
+
const createRule$11 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
1954
1753
|
function isObjectOrArray(node) {
|
|
1955
1754
|
return node.type === AST_NODE_TYPES.ObjectExpression || node.type === AST_NODE_TYPES.ArrayExpression || node.type === AST_NODE_TYPES.TSAsExpression;
|
|
1956
1755
|
}
|
|
@@ -1972,7 +1771,7 @@ function containsNestedStructure(node) {
|
|
|
1972
1771
|
return isNestedStructure(el);
|
|
1973
1772
|
});
|
|
1974
1773
|
}
|
|
1975
|
-
const noInlineNestedObject = createRule$
|
|
1774
|
+
const noInlineNestedObject = createRule$11({
|
|
1976
1775
|
name: "no-inline-nested-object",
|
|
1977
1776
|
meta: {
|
|
1978
1777
|
type: "layout",
|
|
@@ -2014,13 +1813,13 @@ const noInlineNestedObject = createRule$15({
|
|
|
2014
1813
|
});
|
|
2015
1814
|
//#endregion
|
|
2016
1815
|
//#region src/rules/no-inline-return-properties.ts
|
|
2017
|
-
const createRule$
|
|
1816
|
+
const createRule$10 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
2018
1817
|
const isShorthandProperty = (property) => {
|
|
2019
1818
|
if (property.type === AST_NODE_TYPES.SpreadElement) return true;
|
|
2020
1819
|
if (property.type !== AST_NODE_TYPES.Property) return false;
|
|
2021
1820
|
return property.shorthand;
|
|
2022
1821
|
};
|
|
2023
|
-
const noInlineReturnProperties = createRule$
|
|
1822
|
+
const noInlineReturnProperties = createRule$10({
|
|
2024
1823
|
name: "no-inline-return-properties",
|
|
2025
1824
|
meta: {
|
|
2026
1825
|
type: "suggestion",
|
|
@@ -2049,9 +1848,9 @@ const noInlineReturnProperties = createRule$14({
|
|
|
2049
1848
|
});
|
|
2050
1849
|
//#endregion
|
|
2051
1850
|
//#region src/rules/no-inline-type-import.ts
|
|
2052
|
-
const createRule$
|
|
1851
|
+
const createRule$9 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
2053
1852
|
const isInlineTypeSpecifier = (specifier) => specifier.type === AST_NODE_TYPES.ImportSpecifier && specifier.importKind === "type";
|
|
2054
|
-
const noInlineTypeImport = createRule$
|
|
1853
|
+
const noInlineTypeImport = createRule$9({
|
|
2055
1854
|
name: "no-inline-type-import",
|
|
2056
1855
|
meta: {
|
|
2057
1856
|
type: "suggestion",
|
|
@@ -2093,7 +1892,7 @@ const noInlineTypeImport = createRule$13({
|
|
|
2093
1892
|
});
|
|
2094
1893
|
//#endregion
|
|
2095
1894
|
//#region src/rules/no-lazy-identifiers.ts
|
|
2096
|
-
const createRule$
|
|
1895
|
+
const createRule$8 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
2097
1896
|
const KEYBOARD_ROWS = [
|
|
2098
1897
|
"qwertyuiop",
|
|
2099
1898
|
"asdfghjkl",
|
|
@@ -2124,7 +1923,7 @@ const isLazyIdentifier = (name) => {
|
|
|
2124
1923
|
if (hasKeyboardSequence(name)) return true;
|
|
2125
1924
|
return false;
|
|
2126
1925
|
};
|
|
2127
|
-
const noLazyIdentifiers = createRule$
|
|
1926
|
+
const noLazyIdentifiers = createRule$8({
|
|
2128
1927
|
name: "no-lazy-identifiers",
|
|
2129
1928
|
meta: {
|
|
2130
1929
|
type: "problem",
|
|
@@ -2243,7 +2042,7 @@ const noLogicInParams = ESLintUtils.RuleCreator((name) => `https://github.com/ne
|
|
|
2243
2042
|
});
|
|
2244
2043
|
//#endregion
|
|
2245
2044
|
//#region src/rules/no-misleading-constant-case.ts
|
|
2246
|
-
const createRule$
|
|
2045
|
+
const createRule$7 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
2247
2046
|
const SCREAMING_SNAKE_CASE_REGEX = /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/;
|
|
2248
2047
|
const isAsConstAssertion = (node) => node.type === AST_NODE_TYPES.TSAsExpression && node.typeAnnotation.type === AST_NODE_TYPES.TSTypeReference && node.typeAnnotation.typeName.type === AST_NODE_TYPES.Identifier && node.typeAnnotation.typeName.name === "const";
|
|
2249
2048
|
const isStaticValue = (init) => {
|
|
@@ -2261,7 +2060,7 @@ const isGlobalScope = (node) => {
|
|
|
2261
2060
|
if (parent.type === AST_NODE_TYPES.ExportNamedDeclaration && parent.parent?.type === AST_NODE_TYPES.Program) return true;
|
|
2262
2061
|
return false;
|
|
2263
2062
|
};
|
|
2264
|
-
const noMisleadingConstantCase = createRule$
|
|
2063
|
+
const noMisleadingConstantCase = createRule$7({
|
|
2265
2064
|
name: "no-misleading-constant-case",
|
|
2266
2065
|
meta: {
|
|
2267
2066
|
type: "suggestion",
|
|
@@ -2349,82 +2148,6 @@ const noNestedInterfaceDeclaration = ESLintUtils.RuleCreator((name) => `https://
|
|
|
2349
2148
|
}
|
|
2350
2149
|
});
|
|
2351
2150
|
//#endregion
|
|
2352
|
-
//#region src/rules/no-nested-ternary.ts
|
|
2353
|
-
const noNestedTernary = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
|
|
2354
|
-
name: "no-nested-ternary",
|
|
2355
|
-
meta: {
|
|
2356
|
-
type: "suggestion",
|
|
2357
|
-
docs: { description: "Disallow nested ternary expressions" },
|
|
2358
|
-
messages: { noNestedTernary: "Nested ternary expressions are not allowed. Use a function with early returns instead." },
|
|
2359
|
-
schema: []
|
|
2360
|
-
},
|
|
2361
|
-
defaultOptions: [],
|
|
2362
|
-
create(context) {
|
|
2363
|
-
return { ConditionalExpression(node) {
|
|
2364
|
-
const { consequent, alternate } = node;
|
|
2365
|
-
if (consequent.type === AST_NODE_TYPES.ConditionalExpression) context.report({
|
|
2366
|
-
node: consequent,
|
|
2367
|
-
messageId: "noNestedTernary"
|
|
2368
|
-
});
|
|
2369
|
-
if (alternate.type === AST_NODE_TYPES.ConditionalExpression) context.report({
|
|
2370
|
-
node: alternate,
|
|
2371
|
-
messageId: "noNestedTernary"
|
|
2372
|
-
});
|
|
2373
|
-
} };
|
|
2374
|
-
}
|
|
2375
|
-
});
|
|
2376
|
-
//#endregion
|
|
2377
|
-
//#region src/rules/no-redundant-fragment.ts
|
|
2378
|
-
const createRule$10 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
2379
|
-
function isFragmentName(name) {
|
|
2380
|
-
if (name.type === AST_NODE_TYPES.JSXIdentifier && name.name === "Fragment") return true;
|
|
2381
|
-
if (name.type === AST_NODE_TYPES.JSXMemberExpression && name.object.type === AST_NODE_TYPES.JSXIdentifier && name.object.name === "React" && name.property.type === AST_NODE_TYPES.JSXIdentifier && name.property.name === "Fragment") return true;
|
|
2382
|
-
return false;
|
|
2383
|
-
}
|
|
2384
|
-
function hasKeyAttribute(attributes) {
|
|
2385
|
-
return attributes.some((attribute) => attribute.type === AST_NODE_TYPES.JSXAttribute && attribute.name.type === AST_NODE_TYPES.JSXIdentifier && attribute.name.name === "key");
|
|
2386
|
-
}
|
|
2387
|
-
function countMeaningfulChildren(children) {
|
|
2388
|
-
return children.filter((child) => {
|
|
2389
|
-
if (child.type === AST_NODE_TYPES.JSXText) return child.value.trim() !== "";
|
|
2390
|
-
return true;
|
|
2391
|
-
}).length;
|
|
2392
|
-
}
|
|
2393
|
-
const noRedundantFragment = createRule$10({
|
|
2394
|
-
name: "no-redundant-fragment",
|
|
2395
|
-
meta: {
|
|
2396
|
-
type: "problem",
|
|
2397
|
-
docs: { description: "Disallow Fragments that wrap zero or one child (unless a key prop is needed)" },
|
|
2398
|
-
schema: [],
|
|
2399
|
-
messages: { redundantFragment: "Fragment is redundant when wrapping {{ count }} child. Remove the Fragment or replace it with the child directly." }
|
|
2400
|
-
},
|
|
2401
|
-
defaultOptions: [],
|
|
2402
|
-
create(context) {
|
|
2403
|
-
if (!isJsxFile(context.filename)) return {};
|
|
2404
|
-
return {
|
|
2405
|
-
JSXFragment(node) {
|
|
2406
|
-
const count = countMeaningfulChildren(node.children);
|
|
2407
|
-
if (count <= 1) context.report({
|
|
2408
|
-
node,
|
|
2409
|
-
messageId: "redundantFragment",
|
|
2410
|
-
data: { count: String(count) }
|
|
2411
|
-
});
|
|
2412
|
-
},
|
|
2413
|
-
JSXElement(node) {
|
|
2414
|
-
const opening = node.openingElement;
|
|
2415
|
-
if (!isFragmentName(opening.name)) return;
|
|
2416
|
-
if (hasKeyAttribute(opening.attributes)) return;
|
|
2417
|
-
const count = countMeaningfulChildren(node.children);
|
|
2418
|
-
if (count <= 1) context.report({
|
|
2419
|
-
node,
|
|
2420
|
-
messageId: "redundantFragment",
|
|
2421
|
-
data: { count: String(count) }
|
|
2422
|
-
});
|
|
2423
|
-
}
|
|
2424
|
-
};
|
|
2425
|
-
}
|
|
2426
|
-
});
|
|
2427
|
-
//#endregion
|
|
2428
2151
|
//#region src/rules/no-relative-imports.ts
|
|
2429
2152
|
const noRelativeImports = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
|
|
2430
2153
|
name: "no-relative-imports",
|
|
@@ -2459,88 +2182,6 @@ const noRelativeImports = ESLintUtils.RuleCreator((name) => `https://github.com/
|
|
|
2459
2182
|
}
|
|
2460
2183
|
});
|
|
2461
2184
|
//#endregion
|
|
2462
|
-
//#region src/rules/no-single-char-variables.ts
|
|
2463
|
-
const createRule$9 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
2464
|
-
const ALLOWED_IN_FOR_LOOPS = new Set([
|
|
2465
|
-
"i",
|
|
2466
|
-
"j",
|
|
2467
|
-
"k",
|
|
2468
|
-
"n"
|
|
2469
|
-
]);
|
|
2470
|
-
const ALLOWED_UNDERSCORE = "_";
|
|
2471
|
-
const isForLoopInit = (node) => {
|
|
2472
|
-
let current = node;
|
|
2473
|
-
while (current) {
|
|
2474
|
-
const parentNode = current.parent;
|
|
2475
|
-
if (!parentNode) return false;
|
|
2476
|
-
if (parentNode.type === AST_NODE_TYPES.ForStatement) {
|
|
2477
|
-
const { init } = parentNode;
|
|
2478
|
-
if (init && init === current) return true;
|
|
2479
|
-
}
|
|
2480
|
-
current = parentNode;
|
|
2481
|
-
}
|
|
2482
|
-
return false;
|
|
2483
|
-
};
|
|
2484
|
-
const isAllowedInContext = (name, node) => {
|
|
2485
|
-
if (name === ALLOWED_UNDERSCORE) return true;
|
|
2486
|
-
if (ALLOWED_IN_FOR_LOOPS.has(name) && isForLoopInit(node)) return true;
|
|
2487
|
-
return false;
|
|
2488
|
-
};
|
|
2489
|
-
const noSingleCharVariables = createRule$9({
|
|
2490
|
-
name: "no-single-char-variables",
|
|
2491
|
-
meta: {
|
|
2492
|
-
type: "suggestion",
|
|
2493
|
-
docs: { description: "Disallow single character variable and parameter names for better code readability" },
|
|
2494
|
-
messages: { noSingleChar: "Avoid single character variable name '{{name}}'. Use a descriptive name that clearly indicates the purpose." },
|
|
2495
|
-
schema: []
|
|
2496
|
-
},
|
|
2497
|
-
defaultOptions: [],
|
|
2498
|
-
create(context) {
|
|
2499
|
-
const checkIdentifier = (node, declarationNode) => {
|
|
2500
|
-
const { name } = node;
|
|
2501
|
-
if (name.length !== 1) return;
|
|
2502
|
-
if (isAllowedInContext(name, declarationNode)) return;
|
|
2503
|
-
context.report({
|
|
2504
|
-
node,
|
|
2505
|
-
messageId: "noSingleChar",
|
|
2506
|
-
data: { name }
|
|
2507
|
-
});
|
|
2508
|
-
};
|
|
2509
|
-
const checkPattern = (pattern, declarationNode) => {
|
|
2510
|
-
if (pattern.type === AST_NODE_TYPES.Identifier) checkIdentifier(pattern, declarationNode);
|
|
2511
|
-
else if (pattern.type === AST_NODE_TYPES.ObjectPattern) pattern.properties.forEach((prop) => {
|
|
2512
|
-
if (prop.type === AST_NODE_TYPES.Property && prop.value.type === AST_NODE_TYPES.Identifier) checkIdentifier(prop.value, declarationNode);
|
|
2513
|
-
else if (prop.type === AST_NODE_TYPES.RestElement && prop.argument.type === AST_NODE_TYPES.Identifier) checkIdentifier(prop.argument, declarationNode);
|
|
2514
|
-
});
|
|
2515
|
-
else if (pattern.type === AST_NODE_TYPES.ArrayPattern) pattern.elements.forEach((element) => {
|
|
2516
|
-
if (element?.type === AST_NODE_TYPES.Identifier) checkIdentifier(element, declarationNode);
|
|
2517
|
-
else if (element?.type === AST_NODE_TYPES.RestElement && element.argument.type === AST_NODE_TYPES.Identifier) checkIdentifier(element.argument, declarationNode);
|
|
2518
|
-
});
|
|
2519
|
-
else if (pattern.type === AST_NODE_TYPES.AssignmentPattern && pattern.left.type === AST_NODE_TYPES.Identifier) checkIdentifier(pattern.left, declarationNode);
|
|
2520
|
-
else if (pattern.type === AST_NODE_TYPES.RestElement && pattern.argument.type === AST_NODE_TYPES.Identifier) checkIdentifier(pattern.argument, declarationNode);
|
|
2521
|
-
};
|
|
2522
|
-
return {
|
|
2523
|
-
VariableDeclarator(node) {
|
|
2524
|
-
checkPattern(node.id, node);
|
|
2525
|
-
},
|
|
2526
|
-
FunctionDeclaration(node) {
|
|
2527
|
-
if (node.id) checkIdentifier(node.id, node);
|
|
2528
|
-
node.params.forEach((param) => checkPattern(param, node));
|
|
2529
|
-
},
|
|
2530
|
-
FunctionExpression(node) {
|
|
2531
|
-
if (node.id) checkIdentifier(node.id, node);
|
|
2532
|
-
node.params.forEach((param) => checkPattern(param, node));
|
|
2533
|
-
},
|
|
2534
|
-
ArrowFunctionExpression(node) {
|
|
2535
|
-
node.params.forEach((param) => checkPattern(param, node));
|
|
2536
|
-
},
|
|
2537
|
-
CatchClause(node) {
|
|
2538
|
-
if (node.param) checkPattern(node.param, node);
|
|
2539
|
-
}
|
|
2540
|
-
};
|
|
2541
|
-
}
|
|
2542
|
-
});
|
|
2543
|
-
//#endregion
|
|
2544
2185
|
//#region src/rules/prefer-async-await.ts
|
|
2545
2186
|
const preferAsyncAwait = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
|
|
2546
2187
|
name: "prefer-async-await",
|
|
@@ -2607,61 +2248,6 @@ const preferDestructuringParams = ESLintUtils.RuleCreator((name) => `https://git
|
|
|
2607
2248
|
}
|
|
2608
2249
|
});
|
|
2609
2250
|
//#endregion
|
|
2610
|
-
//#region src/rules/prefer-function-declaration.ts
|
|
2611
|
-
const createRule$8 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
2612
|
-
const isTsFile = (filename) => filename.endsWith(".ts") && !filename.endsWith(".d.ts");
|
|
2613
|
-
const isCallbackContext = (node) => {
|
|
2614
|
-
const { parent } = node;
|
|
2615
|
-
if (!parent) return false;
|
|
2616
|
-
if (parent.type === AST_NODE_TYPES.CallExpression && parent.arguments.includes(node)) return true;
|
|
2617
|
-
if (parent.type === AST_NODE_TYPES.NewExpression && parent.arguments.includes(node)) return true;
|
|
2618
|
-
if (parent.type === AST_NODE_TYPES.ReturnStatement) return true;
|
|
2619
|
-
if (parent.type === AST_NODE_TYPES.Property) return true;
|
|
2620
|
-
if (parent.type === AST_NODE_TYPES.ArrayExpression) return true;
|
|
2621
|
-
if (parent.type === AST_NODE_TYPES.ConditionalExpression) return true;
|
|
2622
|
-
if (parent.type === AST_NODE_TYPES.LogicalExpression) return true;
|
|
2623
|
-
if (parent.type === AST_NODE_TYPES.AssignmentExpression && parent.left !== node) return true;
|
|
2624
|
-
return false;
|
|
2625
|
-
};
|
|
2626
|
-
const preferFunctionDeclaration = createRule$8({
|
|
2627
|
-
name: "prefer-function-declaration",
|
|
2628
|
-
meta: {
|
|
2629
|
-
type: "suggestion",
|
|
2630
|
-
docs: { description: "Enforce function declarations over arrow functions assigned to variables in .ts files for better readability and hoisting" },
|
|
2631
|
-
messages: {
|
|
2632
|
-
preferDeclaration: "Use function declaration instead of arrow function. Replace 'const {{name}} = () => ...' with 'function {{name}}() ...'",
|
|
2633
|
-
preferDeclarationExpr: "Use function declaration instead of function expression. Replace 'const {{name}} = function() ...' with 'function {{name}}() ...'"
|
|
2634
|
-
},
|
|
2635
|
-
schema: []
|
|
2636
|
-
},
|
|
2637
|
-
defaultOptions: [],
|
|
2638
|
-
create(context) {
|
|
2639
|
-
const { filename } = context;
|
|
2640
|
-
if (!isTsFile(filename)) return {};
|
|
2641
|
-
return { VariableDeclarator(node) {
|
|
2642
|
-
if (node.id.type !== AST_NODE_TYPES.Identifier) return;
|
|
2643
|
-
const { init } = node;
|
|
2644
|
-
if (!init) return;
|
|
2645
|
-
if (init.type === AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
2646
|
-
if (isCallbackContext(init)) return;
|
|
2647
|
-
context.report({
|
|
2648
|
-
node: init,
|
|
2649
|
-
messageId: "preferDeclaration",
|
|
2650
|
-
data: { name: node.id.name }
|
|
2651
|
-
});
|
|
2652
|
-
}
|
|
2653
|
-
if (init.type === AST_NODE_TYPES.FunctionExpression) {
|
|
2654
|
-
if (isCallbackContext(init)) return;
|
|
2655
|
-
context.report({
|
|
2656
|
-
node: init,
|
|
2657
|
-
messageId: "preferDeclarationExpr",
|
|
2658
|
-
data: { name: node.id.name }
|
|
2659
|
-
});
|
|
2660
|
-
}
|
|
2661
|
-
} };
|
|
2662
|
-
}
|
|
2663
|
-
});
|
|
2664
|
-
//#endregion
|
|
2665
2251
|
//#region src/rules/prefer-guard-clause.ts
|
|
2666
2252
|
const preferGuardClause = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
|
|
2667
2253
|
name: "prefer-guard-clause",
|
|
@@ -2738,6 +2324,7 @@ const preferImportType = ESLintUtils.RuleCreator((name) => `https://github.com/n
|
|
|
2738
2324
|
switch (parent.type) {
|
|
2739
2325
|
case AST_NODE_TYPES.CallExpression:
|
|
2740
2326
|
case AST_NODE_TYPES.NewExpression:
|
|
2327
|
+
case AST_NODE_TYPES.JSXMemberExpression:
|
|
2741
2328
|
case AST_NODE_TYPES.JSXOpeningElement:
|
|
2742
2329
|
case AST_NODE_TYPES.JSXClosingElement:
|
|
2743
2330
|
case AST_NODE_TYPES.MemberExpression:
|
|
@@ -2791,12 +2378,12 @@ const preferImportType = ESLintUtils.RuleCreator((name) => `https://github.com/n
|
|
|
2791
2378
|
});
|
|
2792
2379
|
//#endregion
|
|
2793
2380
|
//#region src/rules/prefer-inline-literal-union.ts
|
|
2794
|
-
const createRule$
|
|
2381
|
+
const createRule$6 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
2795
2382
|
function isLiteralUnionType(node) {
|
|
2796
2383
|
if (node.type !== AST_NODE_TYPES.TSUnionType) return false;
|
|
2797
2384
|
return node.types.every((member) => member.type === AST_NODE_TYPES.TSLiteralType || member.type === AST_NODE_TYPES.TSNullKeyword || member.type === AST_NODE_TYPES.TSUndefinedKeyword);
|
|
2798
2385
|
}
|
|
2799
|
-
const preferInlineLiteralUnion = createRule$
|
|
2386
|
+
const preferInlineLiteralUnion = createRule$6({
|
|
2800
2387
|
name: "prefer-inline-literal-union",
|
|
2801
2388
|
meta: {
|
|
2802
2389
|
type: "suggestion",
|
|
@@ -2834,65 +2421,6 @@ const preferInlineLiteralUnion = createRule$7({
|
|
|
2834
2421
|
}
|
|
2835
2422
|
});
|
|
2836
2423
|
//#endregion
|
|
2837
|
-
//#region src/rules/prefer-inline-type-export.ts
|
|
2838
|
-
const createRule$6 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
2839
|
-
const isTypeDeclaration = (node) => node.type === AST_NODE_TYPES.TSInterfaceDeclaration || node.type === AST_NODE_TYPES.TSTypeAliasDeclaration;
|
|
2840
|
-
const preferInlineTypeExport = createRule$6({
|
|
2841
|
-
name: "prefer-inline-type-export",
|
|
2842
|
-
meta: {
|
|
2843
|
-
type: "suggestion",
|
|
2844
|
-
docs: { description: "Require type and interface declarations to be exported inline rather than via a separate export statement" },
|
|
2845
|
-
fixable: "code",
|
|
2846
|
-
messages: { preferInlineExport: "Export '{{name}}' inline at its declaration instead of using a separate export statement." },
|
|
2847
|
-
schema: []
|
|
2848
|
-
},
|
|
2849
|
-
defaultOptions: [],
|
|
2850
|
-
create(context) {
|
|
2851
|
-
const typeDeclarations = /* @__PURE__ */ new Map();
|
|
2852
|
-
function collectDeclaration(node) {
|
|
2853
|
-
if (node.parent.type !== AST_NODE_TYPES.ExportNamedDeclaration) typeDeclarations.set(node.id.name, node);
|
|
2854
|
-
}
|
|
2855
|
-
function reportSpecifier(specifier, statement, declarationNode) {
|
|
2856
|
-
if (specifier.local.type !== AST_NODE_TYPES.Identifier) return;
|
|
2857
|
-
const { name } = specifier.local;
|
|
2858
|
-
context.report({
|
|
2859
|
-
node: specifier,
|
|
2860
|
-
messageId: "preferInlineExport",
|
|
2861
|
-
data: { name },
|
|
2862
|
-
fix(fixer) {
|
|
2863
|
-
const { sourceCode } = context;
|
|
2864
|
-
const declarationToken = sourceCode.getFirstToken(declarationNode);
|
|
2865
|
-
if (!declarationToken) return null;
|
|
2866
|
-
if (statement.specifiers.length === 1) {
|
|
2867
|
-
const nextToken = sourceCode.getTokenAfter(statement);
|
|
2868
|
-
const end = nextToken ? nextToken.range[0] : statement.range[1];
|
|
2869
|
-
return [fixer.insertTextBefore(declarationToken, "export "), fixer.removeRange([statement.range[0], end])];
|
|
2870
|
-
}
|
|
2871
|
-
const tokenBefore = sourceCode.getTokenBefore(specifier);
|
|
2872
|
-
const tokenAfter = sourceCode.getTokenAfter(specifier);
|
|
2873
|
-
if (!tokenBefore || !tokenAfter) return null;
|
|
2874
|
-
const removalRange = statement.specifiers.at(-1) === specifier && tokenBefore.value === "," ? [tokenBefore.range[0], specifier.range[1]] : [specifier.range[0], tokenAfter.range[1]];
|
|
2875
|
-
return [fixer.insertTextBefore(declarationToken, "export "), fixer.removeRange(removalRange)];
|
|
2876
|
-
}
|
|
2877
|
-
});
|
|
2878
|
-
}
|
|
2879
|
-
return { Program(node) {
|
|
2880
|
-
node.body.forEach((statement) => {
|
|
2881
|
-
if (statement.type === AST_NODE_TYPES.TSInterfaceDeclaration || statement.type === AST_NODE_TYPES.TSTypeAliasDeclaration) collectDeclaration(statement);
|
|
2882
|
-
});
|
|
2883
|
-
node.body.forEach((statement) => {
|
|
2884
|
-
if (statement.type !== AST_NODE_TYPES.ExportNamedDeclaration || statement.declaration !== null) return;
|
|
2885
|
-
statement.specifiers.forEach((specifier) => {
|
|
2886
|
-
if (specifier.local.type !== AST_NODE_TYPES.Identifier) return;
|
|
2887
|
-
const declarationNode = typeDeclarations.get(specifier.local.name);
|
|
2888
|
-
if (!declarationNode || !isTypeDeclaration(declarationNode)) return;
|
|
2889
|
-
reportSpecifier(specifier, statement, declarationNode);
|
|
2890
|
-
});
|
|
2891
|
-
});
|
|
2892
|
-
} };
|
|
2893
|
-
}
|
|
2894
|
-
});
|
|
2895
|
-
//#endregion
|
|
2896
2424
|
//#region src/rules/prefer-interface-for-component-props.ts
|
|
2897
2425
|
const preferInterfaceForComponentProps = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
|
|
2898
2426
|
name: "prefer-interface-for-component-props",
|
|
@@ -2993,64 +2521,6 @@ const preferInterfaceOverInlineTypes = ESLintUtils.RuleCreator((name) => `https:
|
|
|
2993
2521
|
}
|
|
2994
2522
|
});
|
|
2995
2523
|
//#endregion
|
|
2996
|
-
//#region src/rules/prefer-jsx-template-literals.ts
|
|
2997
|
-
const preferJSXTemplateLiterals = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
|
|
2998
|
-
name: "prefer-jsx-template-literals",
|
|
2999
|
-
meta: {
|
|
3000
|
-
type: "suggestion",
|
|
3001
|
-
docs: { description: "Enforce using template literals instead of mixing text and JSX expressions" },
|
|
3002
|
-
fixable: "code",
|
|
3003
|
-
schema: [],
|
|
3004
|
-
messages: { preferTemplate: "Use template literal instead of mixing text with JSX expressions" }
|
|
3005
|
-
},
|
|
3006
|
-
defaultOptions: [],
|
|
3007
|
-
create(context) {
|
|
3008
|
-
if (!isJsxFile(context.filename)) return {};
|
|
3009
|
-
function handleTextBeforeExpression(textNode, exprNode) {
|
|
3010
|
-
const textValue = textNode.value;
|
|
3011
|
-
const trimmedText = textValue.trim();
|
|
3012
|
-
if (!trimmedText) return;
|
|
3013
|
-
const hasTextContent = trimmedText.length > 0 && textValue !== trimmedText;
|
|
3014
|
-
const hasNoTrailingSpace = trimmedText.length > 0 && /\S$/.test(textValue);
|
|
3015
|
-
if (!hasTextContent && !hasNoTrailingSpace) return;
|
|
3016
|
-
context.report({
|
|
3017
|
-
node: textNode,
|
|
3018
|
-
messageId: "preferTemplate",
|
|
3019
|
-
fix(fixer) {
|
|
3020
|
-
const templateLiteral = `{\`${textValue.trimEnd()}\${${context.sourceCode.getText(exprNode.expression)}}\`}`;
|
|
3021
|
-
return [fixer.replaceText(textNode, templateLiteral), fixer.remove(exprNode)];
|
|
3022
|
-
}
|
|
3023
|
-
});
|
|
3024
|
-
}
|
|
3025
|
-
function handleExpressionBeforeText(exprNode, textNode) {
|
|
3026
|
-
const textValue = textNode.value;
|
|
3027
|
-
const trimmedText = textValue.trim();
|
|
3028
|
-
if (!trimmedText) return;
|
|
3029
|
-
if (!/^\S/.test(trimmedText)) return;
|
|
3030
|
-
context.report({
|
|
3031
|
-
node: textNode,
|
|
3032
|
-
messageId: "preferTemplate",
|
|
3033
|
-
fix(fixer) {
|
|
3034
|
-
const templateLiteral = `{\`\${${context.sourceCode.getText(exprNode.expression)}}${textValue.trim()}\`}`;
|
|
3035
|
-
return [fixer.replaceText(exprNode, templateLiteral), fixer.remove(textNode)];
|
|
3036
|
-
}
|
|
3037
|
-
});
|
|
3038
|
-
}
|
|
3039
|
-
function checkJSXElement(node) {
|
|
3040
|
-
const { children } = node;
|
|
3041
|
-
if (children.length < 2) return;
|
|
3042
|
-
for (let i = 0; i < children.length - 1; i += 1) {
|
|
3043
|
-
const child = children[i];
|
|
3044
|
-
const nextChild = children[i + 1];
|
|
3045
|
-
if (!child || !nextChild) return;
|
|
3046
|
-
if (child.type === AST_NODE_TYPES.JSXText && nextChild.type === AST_NODE_TYPES.JSXExpressionContainer) handleTextBeforeExpression(child, nextChild);
|
|
3047
|
-
else if (child.type === AST_NODE_TYPES.JSXExpressionContainer && nextChild.type === AST_NODE_TYPES.JSXText) handleExpressionBeforeText(child, nextChild);
|
|
3048
|
-
}
|
|
3049
|
-
}
|
|
3050
|
-
return { JSXElement: checkJSXElement };
|
|
3051
|
-
}
|
|
3052
|
-
});
|
|
3053
|
-
//#endregion
|
|
3054
2524
|
//#region src/rules/prefer-named-param-types.ts
|
|
3055
2525
|
const createRule$5 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
3056
2526
|
const returnsJsx = (node) => {
|
|
@@ -3113,7 +2583,7 @@ const preferPropsWithChildren = ESLintUtils.RuleCreator((name) => `https://githu
|
|
|
3113
2583
|
type: "suggestion",
|
|
3114
2584
|
docs: { description: "Prefer PropsWithChildren<T> over manually declaring children: ReactNode in component props" },
|
|
3115
2585
|
schema: [],
|
|
3116
|
-
messages: { usePropsWithChildren: "Use 'PropsWithChildren<T>' instead of manually declaring 'children
|
|
2586
|
+
messages: { usePropsWithChildren: "Use 'PropsWithChildren<T>' instead of manually declaring 'children?: ReactNode'." }
|
|
3117
2587
|
},
|
|
3118
2588
|
defaultOptions: [],
|
|
3119
2589
|
create(context) {
|
|
@@ -3132,7 +2602,7 @@ const preferPropsWithChildren = ESLintUtils.RuleCreator((name) => `https://githu
|
|
|
3132
2602
|
if (member.key.type !== AST_NODE_TYPES.Identifier) continue;
|
|
3133
2603
|
if (member.key.name !== "children") continue;
|
|
3134
2604
|
if (!member.typeAnnotation) continue;
|
|
3135
|
-
if (isReactNodeType(member.typeAnnotation.typeAnnotation)) return member;
|
|
2605
|
+
if (member.optional && isReactNodeType(member.typeAnnotation.typeAnnotation)) return member;
|
|
3136
2606
|
}
|
|
3137
2607
|
}
|
|
3138
2608
|
return {
|
|
@@ -3267,65 +2737,6 @@ const preferReactImportTypes = ESLintUtils.RuleCreator((name) => `https://github
|
|
|
3267
2737
|
}
|
|
3268
2738
|
});
|
|
3269
2739
|
//#endregion
|
|
3270
|
-
//#region src/rules/react-props-destructure.ts
|
|
3271
|
-
const reactPropsDestructure = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
|
|
3272
|
-
name: "react-props-destructure",
|
|
3273
|
-
meta: {
|
|
3274
|
-
type: "suggestion",
|
|
3275
|
-
docs: { description: "Enforce destructuring props inside React component body instead of parameters" },
|
|
3276
|
-
fixable: void 0,
|
|
3277
|
-
schema: [],
|
|
3278
|
-
messages: { noParameterDestructuring: "Destructure props inside component body instead of parameters. Use 'const { {{properties}} } = props;'" }
|
|
3279
|
-
},
|
|
3280
|
-
defaultOptions: [],
|
|
3281
|
-
create(context) {
|
|
3282
|
-
if (!isJsxFile(context.filename)) return {};
|
|
3283
|
-
function hasJSXInConditional(node) {
|
|
3284
|
-
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;
|
|
3285
|
-
}
|
|
3286
|
-
function hasJSXInLogical(node) {
|
|
3287
|
-
return node.right.type === AST_NODE_TYPES.JSXElement || node.right.type === AST_NODE_TYPES.JSXFragment;
|
|
3288
|
-
}
|
|
3289
|
-
function hasJSXReturn(block) {
|
|
3290
|
-
return block.body.some((stmt) => {
|
|
3291
|
-
if (stmt.type === AST_NODE_TYPES.ReturnStatement && stmt.argument) 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);
|
|
3292
|
-
return false;
|
|
3293
|
-
});
|
|
3294
|
-
}
|
|
3295
|
-
function isReactComponent(node) {
|
|
3296
|
-
if (node.type === AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
3297
|
-
if (node.body.type === AST_NODE_TYPES.JSXElement || node.body.type === AST_NODE_TYPES.JSXFragment) return true;
|
|
3298
|
-
if (node.body.type === AST_NODE_TYPES.BlockStatement) return hasJSXReturn(node.body);
|
|
3299
|
-
} else if (node.type === AST_NODE_TYPES.FunctionExpression || node.type === AST_NODE_TYPES.FunctionDeclaration) {
|
|
3300
|
-
if (node.body && node.body.type === AST_NODE_TYPES.BlockStatement) return hasJSXReturn(node.body);
|
|
3301
|
-
}
|
|
3302
|
-
return false;
|
|
3303
|
-
}
|
|
3304
|
-
function checkFunction(node) {
|
|
3305
|
-
if (!isReactComponent(node)) return;
|
|
3306
|
-
if (node.params.length !== 1) return;
|
|
3307
|
-
const param = node.params[0];
|
|
3308
|
-
if (param.type === AST_NODE_TYPES.ObjectPattern) {
|
|
3309
|
-
const properties = param.properties.filter((prop) => prop.type === AST_NODE_TYPES.Property).map((prop) => {
|
|
3310
|
-
if (prop.key.type === AST_NODE_TYPES.Identifier) return prop.key.name;
|
|
3311
|
-
return null;
|
|
3312
|
-
}).filter((name) => name !== null);
|
|
3313
|
-
if (properties.length === 0) return;
|
|
3314
|
-
context.report({
|
|
3315
|
-
node: param,
|
|
3316
|
-
messageId: "noParameterDestructuring",
|
|
3317
|
-
data: { properties: properties.join(", ") }
|
|
3318
|
-
});
|
|
3319
|
-
}
|
|
3320
|
-
}
|
|
3321
|
-
return {
|
|
3322
|
-
ArrowFunctionExpression: checkFunction,
|
|
3323
|
-
FunctionExpression: checkFunction,
|
|
3324
|
-
FunctionDeclaration: checkFunction
|
|
3325
|
-
};
|
|
3326
|
-
}
|
|
3327
|
-
});
|
|
3328
|
-
//#endregion
|
|
3329
2740
|
//#region src/rules/require-explicit-return-type.ts
|
|
3330
2741
|
const createRule$4 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
|
|
3331
2742
|
const isReactComponent = (node) => {
|
|
@@ -3502,21 +2913,29 @@ const GROUP_NAMES = [
|
|
|
3502
2913
|
"",
|
|
3503
2914
|
"side-effect",
|
|
3504
2915
|
"builtin",
|
|
2916
|
+
"builtin type",
|
|
3505
2917
|
"external",
|
|
2918
|
+
"external type",
|
|
3506
2919
|
"internal alias",
|
|
3507
|
-
"
|
|
2920
|
+
"internal alias type",
|
|
2921
|
+
"parent relative",
|
|
2922
|
+
"parent relative type",
|
|
2923
|
+
"relative",
|
|
2924
|
+
"relative type"
|
|
3508
2925
|
];
|
|
3509
|
-
function getImportGroup(node) {
|
|
3510
|
-
const source = node.source.value;
|
|
3511
|
-
if (node.specifiers.length === 0 && node.importKind !== "type") return 1;
|
|
3512
|
-
if (source.startsWith("node:") || NODE_BUILTINS.has(source.split("/")[0])) return 2;
|
|
3513
|
-
if (source.startsWith("@/") || source.startsWith("~/") || source.startsWith("#")) return 4;
|
|
3514
|
-
if (source.startsWith(".")) return 5;
|
|
3515
|
-
return 3;
|
|
3516
|
-
}
|
|
3517
2926
|
function isTypeOnlyImport(node) {
|
|
3518
2927
|
return node.importKind === "type" && node.specifiers.length > 0;
|
|
3519
2928
|
}
|
|
2929
|
+
function getImportGroup(node) {
|
|
2930
|
+
const source = node.source.value;
|
|
2931
|
+
const isType = isTypeOnlyImport(node);
|
|
2932
|
+
if (node.specifiers.length === 0 && !isType) return 1;
|
|
2933
|
+
if (source.startsWith("node:") || NODE_BUILTINS.has(source.split("/")[0])) return isType ? 3 : 2;
|
|
2934
|
+
if (source.startsWith("@/") || source.startsWith("~/") || source.startsWith("#")) return isType ? 7 : 6;
|
|
2935
|
+
if (source.startsWith("../")) return isType ? 9 : 8;
|
|
2936
|
+
if (source.startsWith(".")) return isType ? 11 : 10;
|
|
2937
|
+
return isType ? 5 : 4;
|
|
2938
|
+
}
|
|
3520
2939
|
const sortImports = createRule$2({
|
|
3521
2940
|
name: "sort-imports",
|
|
3522
2941
|
meta: {
|
|
@@ -3524,14 +2943,43 @@ const sortImports = createRule$2({
|
|
|
3524
2943
|
docs: { description: "Enforce a consistent ordering of import groups" },
|
|
3525
2944
|
fixable: "code",
|
|
3526
2945
|
schema: [],
|
|
3527
|
-
messages: {
|
|
2946
|
+
messages: {
|
|
2947
|
+
unsortedImports: "Import group '{{current}}' should come before '{{previous}}'. Expected order: side-effect, builtin, external, internal alias, parent relative, relative — each followed by its type imports.",
|
|
2948
|
+
missingBlankLine: "Expected a blank line before '{{current}}' imports (new group after '{{previous}}')."
|
|
2949
|
+
}
|
|
3528
2950
|
},
|
|
3529
2951
|
defaultOptions: [],
|
|
3530
2952
|
create(context) {
|
|
2953
|
+
function getMainGroup(group) {
|
|
2954
|
+
if (group === 1) return 1;
|
|
2955
|
+
return Math.floor((group - 2) / 2) + 2;
|
|
2956
|
+
}
|
|
2957
|
+
function checkBlankLines(imports) {
|
|
2958
|
+
const { sourceCode } = context;
|
|
2959
|
+
for (let i = 1; i < imports.length; i++) {
|
|
2960
|
+
const prev = imports[i - 1];
|
|
2961
|
+
const curr = imports[i];
|
|
2962
|
+
if (getMainGroup(prev.group) === getMainGroup(curr.group)) continue;
|
|
2963
|
+
if (curr.node.loc.start.line - prev.node.loc.end.line > 1) continue;
|
|
2964
|
+
context.report({
|
|
2965
|
+
node: curr.node,
|
|
2966
|
+
messageId: "missingBlankLine",
|
|
2967
|
+
data: {
|
|
2968
|
+
current: GROUP_NAMES[curr.group],
|
|
2969
|
+
previous: GROUP_NAMES[prev.group]
|
|
2970
|
+
},
|
|
2971
|
+
fix(fixer) {
|
|
2972
|
+
const firstToken = sourceCode.getFirstToken(curr.node);
|
|
2973
|
+
if (!firstToken) return null;
|
|
2974
|
+
return fixer.insertTextBefore(firstToken, "\n");
|
|
2975
|
+
}
|
|
2976
|
+
});
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
3531
2979
|
function checkOrder(imports) {
|
|
3532
|
-
if (imports.every((entry, index) => index === 0 || entry.group >= imports[index - 1].group)) return;
|
|
2980
|
+
if (imports.every((entry, index) => index === 0 || entry.group >= imports[index - 1].group)) return false;
|
|
3533
2981
|
const firstUnsorted = imports.find((entry, index) => index > 0 && entry.group < imports[index - 1].group);
|
|
3534
|
-
if (!firstUnsorted) return;
|
|
2982
|
+
if (!firstUnsorted) return false;
|
|
3535
2983
|
const previous = imports[imports.indexOf(firstUnsorted) - 1];
|
|
3536
2984
|
context.report({
|
|
3537
2985
|
node: firstUnsorted.node,
|
|
@@ -3546,24 +2994,26 @@ const sortImports = createRule$2({
|
|
|
3546
2994
|
return imports.map((entry, index) => fixer.replaceText(entry.node, sortedTexts[index]));
|
|
3547
2995
|
}
|
|
3548
2996
|
});
|
|
2997
|
+
return true;
|
|
3549
2998
|
}
|
|
3550
2999
|
return { Program(node) {
|
|
3551
3000
|
const importGroups = [];
|
|
3552
3001
|
node.body.forEach((statement) => {
|
|
3553
3002
|
if (statement.type !== AST_NODE_TYPES.ImportDeclaration) {
|
|
3554
3003
|
if (importGroups.length > 0) {
|
|
3555
|
-
checkOrder(importGroups);
|
|
3004
|
+
if (!checkOrder(importGroups)) checkBlankLines(importGroups);
|
|
3556
3005
|
importGroups.length = 0;
|
|
3557
3006
|
}
|
|
3558
3007
|
return;
|
|
3559
3008
|
}
|
|
3560
|
-
if (isTypeOnlyImport(statement)) return;
|
|
3561
3009
|
importGroups.push({
|
|
3562
3010
|
node: statement,
|
|
3563
3011
|
group: getImportGroup(statement)
|
|
3564
3012
|
});
|
|
3565
3013
|
});
|
|
3566
|
-
if (importGroups.length > 0)
|
|
3014
|
+
if (importGroups.length > 0) {
|
|
3015
|
+
if (!checkOrder(importGroups)) checkBlankLines(importGroups);
|
|
3016
|
+
}
|
|
3567
3017
|
} };
|
|
3568
3018
|
}
|
|
3569
3019
|
});
|
|
@@ -3696,11 +3146,9 @@ const meta = {
|
|
|
3696
3146
|
};
|
|
3697
3147
|
const rules = {
|
|
3698
3148
|
"boolean-naming-prefix": booleanNamingPrefix,
|
|
3699
|
-
"enforce-camel-case": enforceCamelCase,
|
|
3700
3149
|
"enforce-constant-case": enforceConstantCase,
|
|
3701
3150
|
"enforce-hook-filename": enforceHookFilename,
|
|
3702
3151
|
"enforce-hook-naming": enforceHookNaming,
|
|
3703
|
-
"enforce-property-case": enforcePropertyCase,
|
|
3704
3152
|
"enforce-props-suffix": enforcePropsSuffix,
|
|
3705
3153
|
"enforce-readonly-component-props": enforceReadonlyComponentProps,
|
|
3706
3154
|
"enforce-render-naming": enforceRenderNaming,
|
|
@@ -3731,7 +3179,6 @@ const rules = {
|
|
|
3731
3179
|
"no-ghost-wrapper": noGhostWrapper,
|
|
3732
3180
|
"no-helper-function-in-hook": noHelperFunctionInHook,
|
|
3733
3181
|
"no-helper-function-in-test": noHelperFunctionInTest,
|
|
3734
|
-
"no-inline-default-export": noInlineDefaultExport,
|
|
3735
3182
|
"no-inline-nested-object": noInlineNestedObject,
|
|
3736
3183
|
"no-inline-return-properties": noInlineReturnProperties,
|
|
3737
3184
|
"no-inline-type-import": noInlineTypeImport,
|
|
@@ -3739,24 +3186,17 @@ const rules = {
|
|
|
3739
3186
|
"no-logic-in-params": noLogicInParams,
|
|
3740
3187
|
"no-misleading-constant-case": noMisleadingConstantCase,
|
|
3741
3188
|
"no-nested-interface-declaration": noNestedInterfaceDeclaration,
|
|
3742
|
-
"no-nested-ternary": noNestedTernary,
|
|
3743
|
-
"no-redundant-fragment": noRedundantFragment,
|
|
3744
3189
|
"no-relative-imports": noRelativeImports,
|
|
3745
|
-
"no-single-char-variables": noSingleCharVariables,
|
|
3746
3190
|
"prefer-async-await": preferAsyncAwait,
|
|
3747
3191
|
"prefer-destructuring-params": preferDestructuringParams,
|
|
3748
|
-
"prefer-function-declaration": preferFunctionDeclaration,
|
|
3749
3192
|
"prefer-guard-clause": preferGuardClause,
|
|
3750
3193
|
"prefer-import-type": preferImportType,
|
|
3751
3194
|
"prefer-inline-literal-union": preferInlineLiteralUnion,
|
|
3752
|
-
"prefer-inline-type-export": preferInlineTypeExport,
|
|
3753
3195
|
"prefer-interface-for-component-props": preferInterfaceForComponentProps,
|
|
3754
3196
|
"prefer-interface-over-inline-types": preferInterfaceOverInlineTypes,
|
|
3755
|
-
"prefer-jsx-template-literals": preferJSXTemplateLiterals,
|
|
3756
3197
|
"prefer-named-param-types": preferNamedParamTypes,
|
|
3757
3198
|
"prefer-props-with-children": preferPropsWithChildren,
|
|
3758
3199
|
"prefer-react-import-types": preferReactImportTypes,
|
|
3759
|
-
"react-props-destructure": reactPropsDestructure,
|
|
3760
3200
|
"require-explicit-return-type": requireExplicitReturnType,
|
|
3761
3201
|
"sort-exports": sortExports,
|
|
3762
3202
|
"sort-imports": sortImports,
|
|
@@ -3769,11 +3209,9 @@ const plugin = {
|
|
|
3769
3209
|
};
|
|
3770
3210
|
const baseRules = {
|
|
3771
3211
|
"nextfriday/boolean-naming-prefix": "warn",
|
|
3772
|
-
"nextfriday/enforce-camel-case": "warn",
|
|
3773
3212
|
"nextfriday/enforce-constant-case": "warn",
|
|
3774
3213
|
"nextfriday/enforce-hook-filename": "warn",
|
|
3775
3214
|
"nextfriday/enforce-hook-naming": "warn",
|
|
3776
|
-
"nextfriday/enforce-property-case": "warn",
|
|
3777
3215
|
"nextfriday/enforce-service-naming": "warn",
|
|
3778
3216
|
"nextfriday/enforce-test-filename": "warn",
|
|
3779
3217
|
"nextfriday/enforce-sorted-destructuring": "warn",
|
|
@@ -3787,7 +3225,6 @@ const baseRules = {
|
|
|
3787
3225
|
"nextfriday/no-env-fallback": "warn",
|
|
3788
3226
|
"nextfriday/no-helper-function-in-hook": "warn",
|
|
3789
3227
|
"nextfriday/no-helper-function-in-test": "warn",
|
|
3790
|
-
"nextfriday/no-inline-default-export": "warn",
|
|
3791
3228
|
"nextfriday/no-inline-nested-object": "warn",
|
|
3792
3229
|
"nextfriday/no-inline-return-properties": "warn",
|
|
3793
3230
|
"nextfriday/no-inline-type-import": "warn",
|
|
@@ -3795,16 +3232,12 @@ const baseRules = {
|
|
|
3795
3232
|
"nextfriday/no-logic-in-params": "warn",
|
|
3796
3233
|
"nextfriday/no-misleading-constant-case": "warn",
|
|
3797
3234
|
"nextfriday/no-nested-interface-declaration": "warn",
|
|
3798
|
-
"nextfriday/no-nested-ternary": "warn",
|
|
3799
3235
|
"nextfriday/no-relative-imports": "warn",
|
|
3800
|
-
"nextfriday/no-single-char-variables": "warn",
|
|
3801
3236
|
"nextfriday/prefer-async-await": "warn",
|
|
3802
3237
|
"nextfriday/prefer-destructuring-params": "warn",
|
|
3803
|
-
"nextfriday/prefer-function-declaration": "warn",
|
|
3804
3238
|
"nextfriday/prefer-guard-clause": "warn",
|
|
3805
3239
|
"nextfriday/prefer-import-type": "warn",
|
|
3806
3240
|
"nextfriday/prefer-inline-literal-union": "warn",
|
|
3807
|
-
"nextfriday/prefer-inline-type-export": "warn",
|
|
3808
3241
|
"nextfriday/prefer-named-param-types": "warn",
|
|
3809
3242
|
"nextfriday/prefer-react-import-types": "warn",
|
|
3810
3243
|
"nextfriday/require-explicit-return-type": "warn",
|
|
@@ -3815,11 +3248,9 @@ const baseRules = {
|
|
|
3815
3248
|
};
|
|
3816
3249
|
const baseRecommendedRules = {
|
|
3817
3250
|
"nextfriday/boolean-naming-prefix": "error",
|
|
3818
|
-
"nextfriday/enforce-camel-case": "error",
|
|
3819
3251
|
"nextfriday/enforce-constant-case": "error",
|
|
3820
3252
|
"nextfriday/enforce-hook-filename": "error",
|
|
3821
3253
|
"nextfriday/enforce-hook-naming": "error",
|
|
3822
|
-
"nextfriday/enforce-property-case": "error",
|
|
3823
3254
|
"nextfriday/enforce-service-naming": "error",
|
|
3824
3255
|
"nextfriday/enforce-test-filename": "error",
|
|
3825
3256
|
"nextfriday/enforce-sorted-destructuring": "error",
|
|
@@ -3833,7 +3264,6 @@ const baseRecommendedRules = {
|
|
|
3833
3264
|
"nextfriday/no-env-fallback": "error",
|
|
3834
3265
|
"nextfriday/no-helper-function-in-hook": "error",
|
|
3835
3266
|
"nextfriday/no-helper-function-in-test": "error",
|
|
3836
|
-
"nextfriday/no-inline-default-export": "error",
|
|
3837
3267
|
"nextfriday/no-inline-nested-object": "error",
|
|
3838
3268
|
"nextfriday/no-inline-return-properties": "error",
|
|
3839
3269
|
"nextfriday/no-inline-type-import": "error",
|
|
@@ -3841,16 +3271,12 @@ const baseRecommendedRules = {
|
|
|
3841
3271
|
"nextfriday/no-logic-in-params": "error",
|
|
3842
3272
|
"nextfriday/no-misleading-constant-case": "error",
|
|
3843
3273
|
"nextfriday/no-nested-interface-declaration": "error",
|
|
3844
|
-
"nextfriday/no-nested-ternary": "error",
|
|
3845
3274
|
"nextfriday/no-relative-imports": "error",
|
|
3846
|
-
"nextfriday/no-single-char-variables": "error",
|
|
3847
3275
|
"nextfriday/prefer-async-await": "error",
|
|
3848
3276
|
"nextfriday/prefer-destructuring-params": "error",
|
|
3849
|
-
"nextfriday/prefer-function-declaration": "error",
|
|
3850
3277
|
"nextfriday/prefer-guard-clause": "error",
|
|
3851
3278
|
"nextfriday/prefer-import-type": "error",
|
|
3852
3279
|
"nextfriday/prefer-inline-literal-union": "error",
|
|
3853
|
-
"nextfriday/prefer-inline-type-export": "error",
|
|
3854
3280
|
"nextfriday/prefer-named-param-types": "error",
|
|
3855
3281
|
"nextfriday/prefer-react-import-types": "error",
|
|
3856
3282
|
"nextfriday/require-explicit-return-type": "error",
|
|
@@ -3877,12 +3303,9 @@ const jsxRules = {
|
|
|
3877
3303
|
"nextfriday/jsx-sort-props": "warn",
|
|
3878
3304
|
"nextfriday/jsx-spread-props-last": "warn",
|
|
3879
3305
|
"nextfriday/no-ghost-wrapper": "warn",
|
|
3880
|
-
"nextfriday/no-redundant-fragment": "warn",
|
|
3881
3306
|
"nextfriday/prefer-interface-for-component-props": "warn",
|
|
3882
3307
|
"nextfriday/prefer-interface-over-inline-types": "warn",
|
|
3883
|
-
"nextfriday/prefer-
|
|
3884
|
-
"nextfriday/prefer-props-with-children": "warn",
|
|
3885
|
-
"nextfriday/react-props-destructure": "warn"
|
|
3308
|
+
"nextfriday/prefer-props-with-children": "warn"
|
|
3886
3309
|
};
|
|
3887
3310
|
const jsxRecommendedRules = {
|
|
3888
3311
|
"nextfriday/enforce-props-suffix": "error",
|
|
@@ -3902,12 +3325,9 @@ const jsxRecommendedRules = {
|
|
|
3902
3325
|
"nextfriday/jsx-sort-props": "error",
|
|
3903
3326
|
"nextfriday/jsx-spread-props-last": "error",
|
|
3904
3327
|
"nextfriday/no-ghost-wrapper": "error",
|
|
3905
|
-
"nextfriday/no-redundant-fragment": "error",
|
|
3906
3328
|
"nextfriday/prefer-interface-for-component-props": "error",
|
|
3907
3329
|
"nextfriday/prefer-interface-over-inline-types": "error",
|
|
3908
|
-
"nextfriday/prefer-
|
|
3909
|
-
"nextfriday/prefer-props-with-children": "error",
|
|
3910
|
-
"nextfriday/react-props-destructure": "error"
|
|
3330
|
+
"nextfriday/prefer-props-with-children": "error"
|
|
3911
3331
|
};
|
|
3912
3332
|
const createConfig = (configRules) => ({
|
|
3913
3333
|
plugins: { nextfriday: plugin },
|