eslint-plugin-nextfriday 1.5.3 → 1.7.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 +15 -0
- package/README.md +120 -70
- package/docs/rules/BOOLEAN_NAMING_PREFIX.md +102 -0
- package/docs/rules/ENFORCE_SORTED_DESTRUCTURING.md +122 -0
- package/docs/rules/JSX_NO_NON_COMPONENT_FUNCTION.md +114 -0
- package/docs/rules/JSX_NO_VARIABLE_IN_CALLBACK.md +144 -0
- package/docs/rules/NO_DIRECT_DATE.md +36 -0
- package/docs/rules/NO_SINGLE_CHAR_VARIABLES.md +108 -0
- package/docs/rules/PREFER_FUNCTION_DECLARATION.md +139 -0
- package/docs/rules/PREFER_JSX_TEMPLATE_LITERALS.md +78 -0
- package/docs/rules/REQUIRE_EXPLICIT_RETURN_TYPE.md +130 -0
- package/lib/index.cjs +1078 -172
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +126 -14
- package/lib/index.d.ts +126 -14
- package/lib/index.js +1079 -173
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/docs/rules/NO_EXPLICIT_RETURN_TYPE.md +0 -71
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.7.0",
|
|
5
5
|
description: "A comprehensive ESLint plugin providing custom rules and configurations for Next Friday development workflows.",
|
|
6
6
|
keywords: [
|
|
7
7
|
"eslint",
|
|
@@ -115,12 +115,143 @@ var package_default = {
|
|
|
115
115
|
}
|
|
116
116
|
};
|
|
117
117
|
|
|
118
|
-
// src/rules/
|
|
119
|
-
import {
|
|
118
|
+
// src/rules/boolean-naming-prefix.ts
|
|
119
|
+
import { ESLintUtils, AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
120
120
|
var createRule = ESLintUtils.RuleCreator(
|
|
121
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
121
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
122
122
|
);
|
|
123
|
-
var
|
|
123
|
+
var BOOLEAN_PREFIXES = ["is", "has", "should", "can", "did", "will", "was", "are", "does", "had"];
|
|
124
|
+
var startsWithBooleanPrefix = (name) => {
|
|
125
|
+
const lowerName = name.toLowerCase();
|
|
126
|
+
return BOOLEAN_PREFIXES.some((prefix) => {
|
|
127
|
+
if (!lowerName.startsWith(prefix)) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
if (name.length === prefix.length) {
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
const nextChar = name.charAt(prefix.length);
|
|
134
|
+
return nextChar === nextChar.toUpperCase();
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
var isBooleanLiteral = (node) => node.type === AST_NODE_TYPES.Literal && typeof node.value === "boolean";
|
|
138
|
+
var isBooleanExpression = (node) => {
|
|
139
|
+
if (isBooleanLiteral(node)) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
if (node.type === AST_NODE_TYPES.UnaryExpression && node.operator === "!") {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
if (node.type === AST_NODE_TYPES.BinaryExpression) {
|
|
146
|
+
const comparisonOperators = ["===", "!==", "==", "!=", "<", ">", "<=", ">=", "in", "instanceof"];
|
|
147
|
+
return comparisonOperators.includes(node.operator);
|
|
148
|
+
}
|
|
149
|
+
if (node.type === AST_NODE_TYPES.LogicalExpression) {
|
|
150
|
+
return node.operator === "&&" || node.operator === "||";
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
};
|
|
154
|
+
var hasBooleanTypeAnnotation = (node) => {
|
|
155
|
+
if (node.type === AST_NODE_TYPES.Identifier) {
|
|
156
|
+
const { typeAnnotation } = node;
|
|
157
|
+
if (typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES.TSBooleanKeyword) {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if ("id" in node && node.id.type === AST_NODE_TYPES.Identifier) {
|
|
162
|
+
const { typeAnnotation } = node.id;
|
|
163
|
+
if (typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES.TSBooleanKeyword) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
};
|
|
169
|
+
var booleanNamingPrefix = createRule({
|
|
170
|
+
name: "boolean-naming-prefix",
|
|
171
|
+
meta: {
|
|
172
|
+
type: "suggestion",
|
|
173
|
+
docs: {
|
|
174
|
+
description: "Enforce boolean variables and parameters to have a prefix like is, has, should, can, did, will for better readability"
|
|
175
|
+
},
|
|
176
|
+
messages: {
|
|
177
|
+
missingPrefix: "Boolean variable '{{name}}' should have a prefix like is, has, should, can, did, or will. Example: 'is{{suggestedName}}' or 'has{{suggestedName}}'."
|
|
178
|
+
},
|
|
179
|
+
schema: []
|
|
180
|
+
},
|
|
181
|
+
defaultOptions: [],
|
|
182
|
+
create(context) {
|
|
183
|
+
const checkBooleanNaming = (name, node) => {
|
|
184
|
+
if (startsWithBooleanPrefix(name)) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const suggestedName = name.charAt(0).toUpperCase() + name.slice(1);
|
|
188
|
+
context.report({
|
|
189
|
+
node,
|
|
190
|
+
messageId: "missingPrefix",
|
|
191
|
+
data: { name, suggestedName }
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
return {
|
|
195
|
+
VariableDeclarator(node) {
|
|
196
|
+
if (node.id.type !== AST_NODE_TYPES.Identifier) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const { name } = node.id;
|
|
200
|
+
if (hasBooleanTypeAnnotation(node)) {
|
|
201
|
+
checkBooleanNaming(name, node.id);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (node.init && isBooleanExpression(node.init)) {
|
|
205
|
+
checkBooleanNaming(name, node.id);
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
FunctionDeclaration(node) {
|
|
209
|
+
node.params.forEach((param) => {
|
|
210
|
+
if (param.type === AST_NODE_TYPES.Identifier && hasBooleanTypeAnnotation(param)) {
|
|
211
|
+
checkBooleanNaming(param.name, param);
|
|
212
|
+
}
|
|
213
|
+
if (param.type === AST_NODE_TYPES.AssignmentPattern) {
|
|
214
|
+
if (param.left.type === AST_NODE_TYPES.Identifier && param.right && isBooleanLiteral(param.right)) {
|
|
215
|
+
checkBooleanNaming(param.left.name, param.left);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
},
|
|
220
|
+
FunctionExpression(node) {
|
|
221
|
+
node.params.forEach((param) => {
|
|
222
|
+
if (param.type === AST_NODE_TYPES.Identifier && hasBooleanTypeAnnotation(param)) {
|
|
223
|
+
checkBooleanNaming(param.name, param);
|
|
224
|
+
}
|
|
225
|
+
if (param.type === AST_NODE_TYPES.AssignmentPattern) {
|
|
226
|
+
if (param.left.type === AST_NODE_TYPES.Identifier && param.right && isBooleanLiteral(param.right)) {
|
|
227
|
+
checkBooleanNaming(param.left.name, param.left);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
},
|
|
232
|
+
ArrowFunctionExpression(node) {
|
|
233
|
+
node.params.forEach((param) => {
|
|
234
|
+
if (param.type === AST_NODE_TYPES.Identifier && hasBooleanTypeAnnotation(param)) {
|
|
235
|
+
checkBooleanNaming(param.name, param);
|
|
236
|
+
}
|
|
237
|
+
if (param.type === AST_NODE_TYPES.AssignmentPattern) {
|
|
238
|
+
if (param.left.type === AST_NODE_TYPES.Identifier && param.right && isBooleanLiteral(param.right)) {
|
|
239
|
+
checkBooleanNaming(param.left.name, param.left);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
var boolean_naming_prefix_default = booleanNamingPrefix;
|
|
248
|
+
|
|
249
|
+
// src/rules/enforce-readonly-component-props.ts
|
|
250
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES2, ESLintUtils as ESLintUtils2 } from "@typescript-eslint/utils";
|
|
251
|
+
var createRule2 = ESLintUtils2.RuleCreator(
|
|
252
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
253
|
+
);
|
|
254
|
+
var enforceReadonlyComponentProps = createRule2({
|
|
124
255
|
name: "enforce-readonly-component-props",
|
|
125
256
|
meta: {
|
|
126
257
|
type: "suggestion",
|
|
@@ -136,54 +267,54 @@ var enforceReadonlyComponentProps = createRule({
|
|
|
136
267
|
defaultOptions: [],
|
|
137
268
|
create(context) {
|
|
138
269
|
function hasJSXInConditional(node) {
|
|
139
|
-
return node.consequent.type ===
|
|
270
|
+
return node.consequent.type === AST_NODE_TYPES2.JSXElement || node.consequent.type === AST_NODE_TYPES2.JSXFragment || node.alternate.type === AST_NODE_TYPES2.JSXElement || node.alternate.type === AST_NODE_TYPES2.JSXFragment;
|
|
140
271
|
}
|
|
141
272
|
function hasJSXInLogical(node) {
|
|
142
|
-
return node.right.type ===
|
|
273
|
+
return node.right.type === AST_NODE_TYPES2.JSXElement || node.right.type === AST_NODE_TYPES2.JSXFragment;
|
|
143
274
|
}
|
|
144
275
|
function hasJSXReturn(block) {
|
|
145
276
|
return block.body.some((stmt) => {
|
|
146
|
-
if (stmt.type ===
|
|
147
|
-
return stmt.argument.type ===
|
|
277
|
+
if (stmt.type === AST_NODE_TYPES2.ReturnStatement && stmt.argument) {
|
|
278
|
+
return stmt.argument.type === AST_NODE_TYPES2.JSXElement || stmt.argument.type === AST_NODE_TYPES2.JSXFragment || stmt.argument.type === AST_NODE_TYPES2.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === AST_NODE_TYPES2.LogicalExpression && hasJSXInLogical(stmt.argument);
|
|
148
279
|
}
|
|
149
280
|
return false;
|
|
150
281
|
});
|
|
151
282
|
}
|
|
152
|
-
function
|
|
153
|
-
if (node.type ===
|
|
154
|
-
if (node.body.type ===
|
|
283
|
+
function isReactComponent2(node) {
|
|
284
|
+
if (node.type === AST_NODE_TYPES2.ArrowFunctionExpression) {
|
|
285
|
+
if (node.body.type === AST_NODE_TYPES2.JSXElement || node.body.type === AST_NODE_TYPES2.JSXFragment) {
|
|
155
286
|
return true;
|
|
156
287
|
}
|
|
157
|
-
if (node.body.type ===
|
|
288
|
+
if (node.body.type === AST_NODE_TYPES2.BlockStatement) {
|
|
158
289
|
return hasJSXReturn(node.body);
|
|
159
290
|
}
|
|
160
|
-
} else if (node.type ===
|
|
161
|
-
if (node.body && node.body.type ===
|
|
291
|
+
} else if (node.type === AST_NODE_TYPES2.FunctionExpression || node.type === AST_NODE_TYPES2.FunctionDeclaration) {
|
|
292
|
+
if (node.body && node.body.type === AST_NODE_TYPES2.BlockStatement) {
|
|
162
293
|
return hasJSXReturn(node.body);
|
|
163
294
|
}
|
|
164
295
|
}
|
|
165
296
|
return false;
|
|
166
297
|
}
|
|
167
298
|
function isNamedType(node) {
|
|
168
|
-
return node.type ===
|
|
299
|
+
return node.type === AST_NODE_TYPES2.TSTypeReference;
|
|
169
300
|
}
|
|
170
301
|
function isAlreadyReadonly(node) {
|
|
171
|
-
if (node.type ===
|
|
172
|
-
if (node.typeName.type ===
|
|
302
|
+
if (node.type === AST_NODE_TYPES2.TSTypeReference && node.typeName) {
|
|
303
|
+
if (node.typeName.type === AST_NODE_TYPES2.Identifier && node.typeName.name === "Readonly") {
|
|
173
304
|
return true;
|
|
174
305
|
}
|
|
175
306
|
}
|
|
176
307
|
return false;
|
|
177
308
|
}
|
|
178
309
|
function checkFunction(node) {
|
|
179
|
-
if (!
|
|
310
|
+
if (!isReactComponent2(node)) {
|
|
180
311
|
return;
|
|
181
312
|
}
|
|
182
313
|
if (node.params.length !== 1) {
|
|
183
314
|
return;
|
|
184
315
|
}
|
|
185
316
|
const param = node.params[0];
|
|
186
|
-
if (param.type ===
|
|
317
|
+
if (param.type === AST_NODE_TYPES2.Identifier && param.typeAnnotation) {
|
|
187
318
|
const { typeAnnotation } = param.typeAnnotation;
|
|
188
319
|
if (isNamedType(typeAnnotation) && !isAlreadyReadonly(typeAnnotation)) {
|
|
189
320
|
const { sourceCode } = context;
|
|
@@ -207,11 +338,132 @@ var enforceReadonlyComponentProps = createRule({
|
|
|
207
338
|
});
|
|
208
339
|
var enforce_readonly_component_props_default = enforceReadonlyComponentProps;
|
|
209
340
|
|
|
341
|
+
// src/rules/enforce-sorted-destructuring.ts
|
|
342
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES3, ESLintUtils as ESLintUtils3 } from "@typescript-eslint/utils";
|
|
343
|
+
var createRule3 = ESLintUtils3.RuleCreator(
|
|
344
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
345
|
+
);
|
|
346
|
+
var enforceSortedDestructuring = createRule3({
|
|
347
|
+
name: "enforce-sorted-destructuring",
|
|
348
|
+
meta: {
|
|
349
|
+
type: "suggestion",
|
|
350
|
+
docs: {
|
|
351
|
+
description: "Enforce alphabetical sorting of destructured properties with defaults first"
|
|
352
|
+
},
|
|
353
|
+
schema: [],
|
|
354
|
+
messages: {
|
|
355
|
+
unsortedDestructuring: "Destructured properties should be sorted alphabetically. Properties with defaults should come first, sorted by type (string, number, boolean, object) then alphabetically."
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
defaultOptions: [],
|
|
359
|
+
create(context) {
|
|
360
|
+
function getPropertyName(property) {
|
|
361
|
+
if (property.type === AST_NODE_TYPES3.RestElement) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
if (property.key.type === AST_NODE_TYPES3.Identifier) {
|
|
365
|
+
return property.key.name;
|
|
366
|
+
}
|
|
367
|
+
return null;
|
|
368
|
+
}
|
|
369
|
+
function hasDefaultValue(property) {
|
|
370
|
+
return property.value.type === AST_NODE_TYPES3.AssignmentPattern && Boolean(property.value.right);
|
|
371
|
+
}
|
|
372
|
+
function getDefaultValueType(property) {
|
|
373
|
+
if (!hasDefaultValue(property)) {
|
|
374
|
+
return "none";
|
|
375
|
+
}
|
|
376
|
+
const assignmentPattern = property.value;
|
|
377
|
+
const { right } = assignmentPattern;
|
|
378
|
+
if (!right) {
|
|
379
|
+
return "none";
|
|
380
|
+
}
|
|
381
|
+
switch (right.type) {
|
|
382
|
+
case AST_NODE_TYPES3.Literal:
|
|
383
|
+
if (typeof right.value === "string") {
|
|
384
|
+
return "string";
|
|
385
|
+
}
|
|
386
|
+
if (typeof right.value === "number") {
|
|
387
|
+
return "number";
|
|
388
|
+
}
|
|
389
|
+
if (typeof right.value === "boolean") {
|
|
390
|
+
return "boolean";
|
|
391
|
+
}
|
|
392
|
+
return "other";
|
|
393
|
+
case AST_NODE_TYPES3.TemplateLiteral:
|
|
394
|
+
return "string";
|
|
395
|
+
case AST_NODE_TYPES3.ObjectExpression:
|
|
396
|
+
case AST_NODE_TYPES3.ArrayExpression:
|
|
397
|
+
return "object";
|
|
398
|
+
default:
|
|
399
|
+
return "other";
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
function getTypeSortOrder(type) {
|
|
403
|
+
const order = {
|
|
404
|
+
string: 0,
|
|
405
|
+
number: 1,
|
|
406
|
+
boolean: 2,
|
|
407
|
+
object: 3,
|
|
408
|
+
other: 4,
|
|
409
|
+
none: 5
|
|
410
|
+
};
|
|
411
|
+
return order[type] ?? 5;
|
|
412
|
+
}
|
|
413
|
+
function checkVariableDeclarator(node) {
|
|
414
|
+
if (node.id.type !== AST_NODE_TYPES3.ObjectPattern) {
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
const { properties } = node.id;
|
|
418
|
+
if (properties.length < 2) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
const propertyInfo = properties.map((prop) => {
|
|
422
|
+
if (prop.type === AST_NODE_TYPES3.RestElement) {
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
return {
|
|
426
|
+
property: prop,
|
|
427
|
+
name: getPropertyName(prop),
|
|
428
|
+
hasDefault: hasDefaultValue(prop),
|
|
429
|
+
defaultType: getDefaultValueType(prop)
|
|
430
|
+
};
|
|
431
|
+
}).filter((info) => info !== null && info.name !== null);
|
|
432
|
+
const sorted = [...propertyInfo].sort((a, b) => {
|
|
433
|
+
if (a.hasDefault && !b.hasDefault) {
|
|
434
|
+
return -1;
|
|
435
|
+
}
|
|
436
|
+
if (!a.hasDefault && b.hasDefault) {
|
|
437
|
+
return 1;
|
|
438
|
+
}
|
|
439
|
+
if (a.hasDefault && b.hasDefault) {
|
|
440
|
+
const typeComparison = getTypeSortOrder(a.defaultType) - getTypeSortOrder(b.defaultType);
|
|
441
|
+
if (typeComparison !== 0) {
|
|
442
|
+
return typeComparison;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
return a.name.localeCompare(b.name);
|
|
446
|
+
});
|
|
447
|
+
const isSorted = propertyInfo.every((info, index) => info.name === sorted[index].name);
|
|
448
|
+
if (!isSorted) {
|
|
449
|
+
context.report({
|
|
450
|
+
node: node.id,
|
|
451
|
+
messageId: "unsortedDestructuring"
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return {
|
|
456
|
+
VariableDeclarator: checkVariableDeclarator
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
var enforce_sorted_destructuring_default = enforceSortedDestructuring;
|
|
461
|
+
|
|
210
462
|
// src/rules/file-kebab-case.ts
|
|
211
463
|
import path from "path";
|
|
212
|
-
import { ESLintUtils as
|
|
213
|
-
var
|
|
214
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
464
|
+
import { ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
|
|
465
|
+
var createRule4 = ESLintUtils4.RuleCreator(
|
|
466
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
215
467
|
);
|
|
216
468
|
var isKebabCase = (str) => {
|
|
217
469
|
if (/\.(config|rc|setup|spec|test)$/.test(str) || /^[a-z0-9]+(?:-[a-z0-9]+)*\.[a-z0-9]+(?:-[a-z0-9]+)*$/.test(str)) {
|
|
@@ -219,7 +471,7 @@ var isKebabCase = (str) => {
|
|
|
219
471
|
}
|
|
220
472
|
return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(str);
|
|
221
473
|
};
|
|
222
|
-
var fileKebabCase =
|
|
474
|
+
var fileKebabCase = createRule4({
|
|
223
475
|
name: "file-kebab-case",
|
|
224
476
|
meta: {
|
|
225
477
|
type: "problem",
|
|
@@ -240,8 +492,8 @@ var fileKebabCase = createRule2({
|
|
|
240
492
|
if (ext !== ".ts" && ext !== ".js") {
|
|
241
493
|
return;
|
|
242
494
|
}
|
|
243
|
-
const
|
|
244
|
-
if (!isKebabCase(
|
|
495
|
+
const basename2 = path.basename(filename, ext);
|
|
496
|
+
if (!isKebabCase(basename2)) {
|
|
245
497
|
context.report({
|
|
246
498
|
loc: { line: 1, column: 0 },
|
|
247
499
|
messageId: "fileKebabCase"
|
|
@@ -255,12 +507,12 @@ var file_kebab_case_default = fileKebabCase;
|
|
|
255
507
|
|
|
256
508
|
// src/rules/jsx-pascal-case.ts
|
|
257
509
|
import path2 from "path";
|
|
258
|
-
import { ESLintUtils as
|
|
259
|
-
var
|
|
260
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
510
|
+
import { ESLintUtils as ESLintUtils5 } from "@typescript-eslint/utils";
|
|
511
|
+
var createRule5 = ESLintUtils5.RuleCreator(
|
|
512
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
261
513
|
);
|
|
262
514
|
var isPascalCase = (str) => /^[A-Z][a-zA-Z0-9]*$/.test(str) && !/^[A-Z]+$/.test(str);
|
|
263
|
-
var jsxPascalCase =
|
|
515
|
+
var jsxPascalCase = createRule5({
|
|
264
516
|
name: "jsx-pascal-case",
|
|
265
517
|
meta: {
|
|
266
518
|
type: "problem",
|
|
@@ -281,8 +533,8 @@ var jsxPascalCase = createRule3({
|
|
|
281
533
|
if (ext !== ".jsx" && ext !== ".tsx") {
|
|
282
534
|
return;
|
|
283
535
|
}
|
|
284
|
-
const
|
|
285
|
-
if (!isPascalCase(
|
|
536
|
+
const basename2 = path2.basename(filename, ext);
|
|
537
|
+
if (!isPascalCase(basename2)) {
|
|
286
538
|
context.report({
|
|
287
539
|
loc: { line: 1, column: 0 },
|
|
288
540
|
messageId: "jsxPascalCase"
|
|
@@ -294,13 +546,136 @@ var jsxPascalCase = createRule3({
|
|
|
294
546
|
});
|
|
295
547
|
var jsx_pascal_case_default = jsxPascalCase;
|
|
296
548
|
|
|
549
|
+
// src/rules/no-direct-date.ts
|
|
550
|
+
import { ESLintUtils as ESLintUtils6, AST_NODE_TYPES as AST_NODE_TYPES4 } from "@typescript-eslint/utils";
|
|
551
|
+
var createRule6 = ESLintUtils6.RuleCreator(
|
|
552
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
553
|
+
);
|
|
554
|
+
var noDirectDate = createRule6({
|
|
555
|
+
name: "no-direct-date",
|
|
556
|
+
meta: {
|
|
557
|
+
type: "problem",
|
|
558
|
+
docs: {
|
|
559
|
+
description: "Disallow direct usage of Date constructor and methods to enforce centralized date utilities"
|
|
560
|
+
},
|
|
561
|
+
messages: {
|
|
562
|
+
noNewDate: "Avoid using 'new Date()'. Use a centralized date utility like dayjs instead.",
|
|
563
|
+
noDateNow: "Avoid using 'Date.now()'. Use a centralized date utility like dayjs instead.",
|
|
564
|
+
noDateParse: "Avoid using 'Date.parse()'. Use a centralized date utility like dayjs instead."
|
|
565
|
+
},
|
|
566
|
+
schema: []
|
|
567
|
+
},
|
|
568
|
+
defaultOptions: [],
|
|
569
|
+
create(context) {
|
|
570
|
+
return {
|
|
571
|
+
NewExpression(node) {
|
|
572
|
+
if (node.callee.type === AST_NODE_TYPES4.Identifier && node.callee.name === "Date") {
|
|
573
|
+
context.report({
|
|
574
|
+
node,
|
|
575
|
+
messageId: "noNewDate"
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
CallExpression(node) {
|
|
580
|
+
if (node.callee.type === AST_NODE_TYPES4.MemberExpression && node.callee.object.type === AST_NODE_TYPES4.Identifier && node.callee.object.name === "Date" && node.callee.property.type === AST_NODE_TYPES4.Identifier) {
|
|
581
|
+
const methodName = node.callee.property.name;
|
|
582
|
+
if (methodName === "now") {
|
|
583
|
+
context.report({
|
|
584
|
+
node,
|
|
585
|
+
messageId: "noDateNow"
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
if (methodName === "parse") {
|
|
589
|
+
context.report({
|
|
590
|
+
node,
|
|
591
|
+
messageId: "noDateParse"
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
var no_direct_date_default = noDirectDate;
|
|
600
|
+
|
|
601
|
+
// src/rules/jsx-no-variable-in-callback.ts
|
|
602
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES5, ESLintUtils as ESLintUtils7 } from "@typescript-eslint/utils";
|
|
603
|
+
var createRule7 = ESLintUtils7.RuleCreator(
|
|
604
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
605
|
+
);
|
|
606
|
+
var jsxNoVariableInCallback = createRule7({
|
|
607
|
+
name: "jsx-no-variable-in-callback",
|
|
608
|
+
meta: {
|
|
609
|
+
type: "suggestion",
|
|
610
|
+
docs: {
|
|
611
|
+
description: "Disallow variable declarations inside callback functions within JSX"
|
|
612
|
+
},
|
|
613
|
+
schema: [],
|
|
614
|
+
messages: {
|
|
615
|
+
noVariableInCallback: "Variable declarations should not be inside callback functions within JSX. Extract the logic to a separate function outside the JSX."
|
|
616
|
+
}
|
|
617
|
+
},
|
|
618
|
+
defaultOptions: [],
|
|
619
|
+
create(context) {
|
|
620
|
+
function isInsideJSX(node) {
|
|
621
|
+
let current = node.parent;
|
|
622
|
+
while (current) {
|
|
623
|
+
if (current.type === AST_NODE_TYPES5.JSXElement || current.type === AST_NODE_TYPES5.JSXFragment) {
|
|
624
|
+
return true;
|
|
625
|
+
}
|
|
626
|
+
current = current.parent;
|
|
627
|
+
}
|
|
628
|
+
return false;
|
|
629
|
+
}
|
|
630
|
+
function isCallbackInJSX(node) {
|
|
631
|
+
if (!node.parent) {
|
|
632
|
+
return false;
|
|
633
|
+
}
|
|
634
|
+
if (!isInsideJSX(node)) {
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
637
|
+
if (node.parent.type === AST_NODE_TYPES5.CallExpression || node.parent.type === AST_NODE_TYPES5.JSXExpressionContainer) {
|
|
638
|
+
return true;
|
|
639
|
+
}
|
|
640
|
+
if (node.parent.type === AST_NODE_TYPES5.ArrayExpression && node.parent.parent) {
|
|
641
|
+
if (node.parent.parent.type === AST_NODE_TYPES5.CallExpression || node.parent.parent.type === AST_NODE_TYPES5.JSXExpressionContainer) {
|
|
642
|
+
return true;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
return false;
|
|
646
|
+
}
|
|
647
|
+
function checkFunctionBody(node) {
|
|
648
|
+
if (!isCallbackInJSX(node)) {
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
const { body } = node;
|
|
652
|
+
if (body.type !== AST_NODE_TYPES5.BlockStatement) {
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
body.body.forEach((statement) => {
|
|
656
|
+
if (statement.type === AST_NODE_TYPES5.VariableDeclaration) {
|
|
657
|
+
context.report({
|
|
658
|
+
node: statement,
|
|
659
|
+
messageId: "noVariableInCallback"
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
return {
|
|
665
|
+
ArrowFunctionExpression: checkFunctionBody,
|
|
666
|
+
FunctionExpression: checkFunctionBody
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
});
|
|
670
|
+
var jsx_no_variable_in_callback_default = jsxNoVariableInCallback;
|
|
671
|
+
|
|
297
672
|
// src/rules/md-filename-case-restriction.ts
|
|
298
673
|
import path3 from "path";
|
|
299
|
-
import { ESLintUtils as
|
|
300
|
-
var
|
|
301
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
674
|
+
import { ESLintUtils as ESLintUtils8 } from "@typescript-eslint/utils";
|
|
675
|
+
var createRule8 = ESLintUtils8.RuleCreator(
|
|
676
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
302
677
|
);
|
|
303
|
-
var mdFilenameCaseRestriction =
|
|
678
|
+
var mdFilenameCaseRestriction = createRule8({
|
|
304
679
|
name: "md-filename-case-restriction",
|
|
305
680
|
meta: {
|
|
306
681
|
type: "problem",
|
|
@@ -320,18 +695,18 @@ var mdFilenameCaseRestriction = createRule4({
|
|
|
320
695
|
if (!filename.endsWith(".md")) {
|
|
321
696
|
return;
|
|
322
697
|
}
|
|
323
|
-
const
|
|
698
|
+
const basename2 = path3.basename(filename, ".md");
|
|
324
699
|
function isSnakeCase(text) {
|
|
325
700
|
return /^[A-Z][A-Z0-9_]*$/.test(text);
|
|
326
701
|
}
|
|
327
702
|
function isValidCase(text) {
|
|
328
703
|
return isSnakeCase(text);
|
|
329
704
|
}
|
|
330
|
-
if (!isValidCase(
|
|
705
|
+
if (!isValidCase(basename2)) {
|
|
331
706
|
context.report({
|
|
332
707
|
node: context.sourceCode.ast,
|
|
333
708
|
messageId: "invalidFilenameCase",
|
|
334
|
-
data: { filename:
|
|
709
|
+
data: { filename: basename2 }
|
|
335
710
|
});
|
|
336
711
|
}
|
|
337
712
|
}
|
|
@@ -341,11 +716,11 @@ var mdFilenameCaseRestriction = createRule4({
|
|
|
341
716
|
var md_filename_case_restriction_default = mdFilenameCaseRestriction;
|
|
342
717
|
|
|
343
718
|
// src/rules/no-complex-inline-return.ts
|
|
344
|
-
import { ESLintUtils as
|
|
345
|
-
var
|
|
346
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
719
|
+
import { ESLintUtils as ESLintUtils9, AST_NODE_TYPES as AST_NODE_TYPES6 } from "@typescript-eslint/utils";
|
|
720
|
+
var createRule9 = ESLintUtils9.RuleCreator(
|
|
721
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
347
722
|
);
|
|
348
|
-
var noComplexInlineReturn =
|
|
723
|
+
var noComplexInlineReturn = createRule9({
|
|
349
724
|
name: "no-complex-inline-return",
|
|
350
725
|
meta: {
|
|
351
726
|
type: "suggestion",
|
|
@@ -361,13 +736,13 @@ var noComplexInlineReturn = createRule5({
|
|
|
361
736
|
create(context) {
|
|
362
737
|
const isComplexExpression = (node) => {
|
|
363
738
|
if (!node) return false;
|
|
364
|
-
if (node.type ===
|
|
739
|
+
if (node.type === AST_NODE_TYPES6.ConditionalExpression) {
|
|
365
740
|
return true;
|
|
366
741
|
}
|
|
367
|
-
if (node.type ===
|
|
742
|
+
if (node.type === AST_NODE_TYPES6.LogicalExpression) {
|
|
368
743
|
return true;
|
|
369
744
|
}
|
|
370
|
-
if (node.type ===
|
|
745
|
+
if (node.type === AST_NODE_TYPES6.NewExpression) {
|
|
371
746
|
return true;
|
|
372
747
|
}
|
|
373
748
|
return false;
|
|
@@ -388,11 +763,11 @@ var no_complex_inline_return_default = noComplexInlineReturn;
|
|
|
388
763
|
|
|
389
764
|
// src/rules/no-emoji.ts
|
|
390
765
|
import emojiRegex from "emoji-regex";
|
|
391
|
-
import { ESLintUtils as
|
|
392
|
-
var
|
|
393
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
766
|
+
import { ESLintUtils as ESLintUtils10 } from "@typescript-eslint/utils";
|
|
767
|
+
var createRule10 = ESLintUtils10.RuleCreator(
|
|
768
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
394
769
|
);
|
|
395
|
-
var noEmoji =
|
|
770
|
+
var noEmoji = createRule10({
|
|
396
771
|
name: "no-emoji",
|
|
397
772
|
meta: {
|
|
398
773
|
type: "problem",
|
|
@@ -426,11 +801,11 @@ var noEmoji = createRule6({
|
|
|
426
801
|
var no_emoji_default = noEmoji;
|
|
427
802
|
|
|
428
803
|
// src/rules/no-env-fallback.ts
|
|
429
|
-
import { ESLintUtils as
|
|
430
|
-
var
|
|
431
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
804
|
+
import { ESLintUtils as ESLintUtils11, AST_NODE_TYPES as AST_NODE_TYPES7 } from "@typescript-eslint/utils";
|
|
805
|
+
var createRule11 = ESLintUtils11.RuleCreator(
|
|
806
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
432
807
|
);
|
|
433
|
-
var noEnvFallback =
|
|
808
|
+
var noEnvFallback = createRule11({
|
|
434
809
|
name: "no-env-fallback",
|
|
435
810
|
meta: {
|
|
436
811
|
type: "problem",
|
|
@@ -445,16 +820,16 @@ var noEnvFallback = createRule7({
|
|
|
445
820
|
defaultOptions: [],
|
|
446
821
|
create(context) {
|
|
447
822
|
const isProcessEnvAccess = (node) => {
|
|
448
|
-
if (node.type !==
|
|
823
|
+
if (node.type !== AST_NODE_TYPES7.MemberExpression) {
|
|
449
824
|
return false;
|
|
450
825
|
}
|
|
451
826
|
const { object } = node;
|
|
452
|
-
if (object.type !==
|
|
827
|
+
if (object.type !== AST_NODE_TYPES7.MemberExpression) {
|
|
453
828
|
return false;
|
|
454
829
|
}
|
|
455
830
|
const processNode = object.object;
|
|
456
831
|
const envNode = object.property;
|
|
457
|
-
return processNode.type ===
|
|
832
|
+
return processNode.type === AST_NODE_TYPES7.Identifier && processNode.name === "process" && envNode.type === AST_NODE_TYPES7.Identifier && envNode.name === "env";
|
|
458
833
|
};
|
|
459
834
|
return {
|
|
460
835
|
LogicalExpression(node) {
|
|
@@ -478,38 +853,93 @@ var noEnvFallback = createRule7({
|
|
|
478
853
|
});
|
|
479
854
|
var no_env_fallback_default = noEnvFallback;
|
|
480
855
|
|
|
481
|
-
// src/rules/
|
|
482
|
-
import { ESLintUtils as
|
|
483
|
-
var
|
|
484
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
856
|
+
// src/rules/require-explicit-return-type.ts
|
|
857
|
+
import { ESLintUtils as ESLintUtils12, AST_NODE_TYPES as AST_NODE_TYPES8 } from "@typescript-eslint/utils";
|
|
858
|
+
var createRule12 = ESLintUtils12.RuleCreator(
|
|
859
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
485
860
|
);
|
|
486
|
-
var
|
|
487
|
-
|
|
861
|
+
var isReactComponent = (node) => {
|
|
862
|
+
if (node.type === AST_NODE_TYPES8.ArrowFunctionExpression) {
|
|
863
|
+
const { parent } = node;
|
|
864
|
+
if (parent?.type === AST_NODE_TYPES8.VariableDeclarator) {
|
|
865
|
+
const { id } = parent;
|
|
866
|
+
if (id.type === AST_NODE_TYPES8.Identifier) {
|
|
867
|
+
return /^[A-Z]/.test(id.name);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
if (node.type === AST_NODE_TYPES8.FunctionDeclaration && node.id) {
|
|
872
|
+
return /^[A-Z]/.test(node.id.name);
|
|
873
|
+
}
|
|
874
|
+
return false;
|
|
875
|
+
};
|
|
876
|
+
var isCallbackFunction = (node) => {
|
|
877
|
+
if (node.type === AST_NODE_TYPES8.FunctionDeclaration) {
|
|
878
|
+
return false;
|
|
879
|
+
}
|
|
880
|
+
const { parent } = node;
|
|
881
|
+
if (!parent) {
|
|
882
|
+
return false;
|
|
883
|
+
}
|
|
884
|
+
if (parent.type === AST_NODE_TYPES8.CallExpression && parent.arguments.includes(node)) {
|
|
885
|
+
return true;
|
|
886
|
+
}
|
|
887
|
+
if (parent.type === AST_NODE_TYPES8.Property) {
|
|
888
|
+
return true;
|
|
889
|
+
}
|
|
890
|
+
if (parent.type === AST_NODE_TYPES8.ArrayExpression) {
|
|
891
|
+
return true;
|
|
892
|
+
}
|
|
893
|
+
return false;
|
|
894
|
+
};
|
|
895
|
+
var getFunctionName = (node) => {
|
|
896
|
+
if (node.type === AST_NODE_TYPES8.FunctionDeclaration && node.id) {
|
|
897
|
+
return node.id.name;
|
|
898
|
+
}
|
|
899
|
+
if (node.type === AST_NODE_TYPES8.FunctionExpression && node.id) {
|
|
900
|
+
return node.id.name;
|
|
901
|
+
}
|
|
902
|
+
if ((node.type === AST_NODE_TYPES8.ArrowFunctionExpression || node.type === AST_NODE_TYPES8.FunctionExpression) && node.parent?.type === AST_NODE_TYPES8.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES8.Identifier) {
|
|
903
|
+
return node.parent.id.name;
|
|
904
|
+
}
|
|
905
|
+
return null;
|
|
906
|
+
};
|
|
907
|
+
var requireExplicitReturnType = createRule12({
|
|
908
|
+
name: "require-explicit-return-type",
|
|
488
909
|
meta: {
|
|
489
910
|
type: "suggestion",
|
|
490
911
|
docs: {
|
|
491
|
-
description: "
|
|
912
|
+
description: "Require explicit return types on functions for better code documentation and type safety"
|
|
492
913
|
},
|
|
493
|
-
fixable: "code",
|
|
494
|
-
schema: [],
|
|
495
914
|
messages: {
|
|
496
|
-
|
|
497
|
-
|
|
915
|
+
missingReturnType: "Function '{{name}}' is missing an explicit return type. Add a return type annotation for better documentation.",
|
|
916
|
+
missingReturnTypeAnonymous: "Function is missing an explicit return type. Add a return type annotation for better documentation."
|
|
917
|
+
},
|
|
918
|
+
schema: []
|
|
498
919
|
},
|
|
499
920
|
defaultOptions: [],
|
|
500
921
|
create(context) {
|
|
501
922
|
const checkFunction = (node) => {
|
|
502
923
|
if (node.returnType) {
|
|
503
|
-
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
if (isCallbackFunction(node)) {
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
if (isReactComponent(node)) {
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
const functionName = getFunctionName(node);
|
|
933
|
+
if (functionName) {
|
|
504
934
|
context.report({
|
|
505
|
-
node
|
|
506
|
-
messageId: "
|
|
507
|
-
data: {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
935
|
+
node,
|
|
936
|
+
messageId: "missingReturnType",
|
|
937
|
+
data: { name: functionName }
|
|
938
|
+
});
|
|
939
|
+
} else {
|
|
940
|
+
context.report({
|
|
941
|
+
node,
|
|
942
|
+
messageId: "missingReturnTypeAnonymous"
|
|
513
943
|
});
|
|
514
944
|
}
|
|
515
945
|
};
|
|
@@ -520,14 +950,99 @@ var noExplicitReturnType = createRule8({
|
|
|
520
950
|
};
|
|
521
951
|
}
|
|
522
952
|
});
|
|
523
|
-
var
|
|
953
|
+
var require_explicit_return_type_default = requireExplicitReturnType;
|
|
954
|
+
|
|
955
|
+
// src/rules/jsx-no-non-component-function.ts
|
|
956
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES10, ESLintUtils as ESLintUtils13 } from "@typescript-eslint/utils";
|
|
957
|
+
|
|
958
|
+
// src/utils.ts
|
|
959
|
+
import { basename, extname } from "path";
|
|
960
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES9 } from "@typescript-eslint/utils";
|
|
961
|
+
var getFileExtension = (filename) => extname(filename).slice(1);
|
|
962
|
+
|
|
963
|
+
// src/rules/jsx-no-non-component-function.ts
|
|
964
|
+
var createRule13 = ESLintUtils13.RuleCreator(
|
|
965
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
966
|
+
);
|
|
967
|
+
var jsxNoNonComponentFunction = createRule13({
|
|
968
|
+
name: "jsx-no-non-component-function",
|
|
969
|
+
meta: {
|
|
970
|
+
type: "problem",
|
|
971
|
+
docs: {
|
|
972
|
+
description: "Disallow non-component functions defined at top level in .tsx and .jsx files"
|
|
973
|
+
},
|
|
974
|
+
schema: [],
|
|
975
|
+
messages: {
|
|
976
|
+
noTopLevelFunction: "Non-component functions should not be defined at top level in .tsx/.jsx files. Either move it inside the component or extract it to a separate file."
|
|
977
|
+
}
|
|
978
|
+
},
|
|
979
|
+
defaultOptions: [],
|
|
980
|
+
create(context) {
|
|
981
|
+
const { filename } = context;
|
|
982
|
+
const extension = getFileExtension(filename);
|
|
983
|
+
if (extension !== "tsx" && extension !== "jsx") {
|
|
984
|
+
return {};
|
|
985
|
+
}
|
|
986
|
+
function isReactComponent2(node) {
|
|
987
|
+
const functionName = node.type === AST_NODE_TYPES10.FunctionDeclaration && node.id ? node.id.name : null;
|
|
988
|
+
if (functionName && /^[A-Z]/.test(functionName)) {
|
|
989
|
+
return true;
|
|
990
|
+
}
|
|
991
|
+
if (node.returnType?.typeAnnotation) {
|
|
992
|
+
const returnTypeNode = node.returnType.typeAnnotation;
|
|
993
|
+
if (returnTypeNode.type === AST_NODE_TYPES10.TSTypeReference && returnTypeNode.typeName.type === AST_NODE_TYPES10.Identifier) {
|
|
994
|
+
const typeName = returnTypeNode.typeName.name;
|
|
995
|
+
if (typeName === "JSX" || typeName === "ReactElement" || typeName === "ReactNode") {
|
|
996
|
+
return true;
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
return false;
|
|
1001
|
+
}
|
|
1002
|
+
function checkTopLevelFunction(node, declaratorNode) {
|
|
1003
|
+
if (isReactComponent2(node)) {
|
|
1004
|
+
return;
|
|
1005
|
+
}
|
|
1006
|
+
const { parent } = node;
|
|
1007
|
+
if (!parent) {
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
if (parent.type === AST_NODE_TYPES10.ExportDefaultDeclaration || parent.type === AST_NODE_TYPES10.ExportNamedDeclaration) {
|
|
1011
|
+
return;
|
|
1012
|
+
}
|
|
1013
|
+
if (declaratorNode?.parent?.parent?.type === AST_NODE_TYPES10.ExportNamedDeclaration) {
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
if (declaratorNode?.id.type === AST_NODE_TYPES10.Identifier) {
|
|
1017
|
+
const varName = declaratorNode.id.name;
|
|
1018
|
+
if (/^[A-Z]/.test(varName)) {
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
context.report({
|
|
1023
|
+
node: declaratorNode || node,
|
|
1024
|
+
messageId: "noTopLevelFunction"
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
return {
|
|
1028
|
+
"Program > VariableDeclaration > VariableDeclarator > ArrowFunctionExpression": function checkArrowFunction(node) {
|
|
1029
|
+
const declarator = node.parent;
|
|
1030
|
+
checkTopLevelFunction(node, declarator);
|
|
1031
|
+
},
|
|
1032
|
+
"Program > FunctionDeclaration": function checkFunctionDeclaration(node) {
|
|
1033
|
+
checkTopLevelFunction(node);
|
|
1034
|
+
}
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
});
|
|
1038
|
+
var jsx_no_non_component_function_default = jsxNoNonComponentFunction;
|
|
524
1039
|
|
|
525
1040
|
// src/rules/no-logic-in-params.ts
|
|
526
|
-
import { ESLintUtils as
|
|
527
|
-
var
|
|
528
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
1041
|
+
import { ESLintUtils as ESLintUtils14, AST_NODE_TYPES as AST_NODE_TYPES11 } from "@typescript-eslint/utils";
|
|
1042
|
+
var createRule14 = ESLintUtils14.RuleCreator(
|
|
1043
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
529
1044
|
);
|
|
530
|
-
var noLogicInParams =
|
|
1045
|
+
var noLogicInParams = createRule14({
|
|
531
1046
|
name: "no-logic-in-params",
|
|
532
1047
|
meta: {
|
|
533
1048
|
type: "suggestion",
|
|
@@ -542,20 +1057,20 @@ var noLogicInParams = createRule9({
|
|
|
542
1057
|
defaultOptions: [],
|
|
543
1058
|
create(context) {
|
|
544
1059
|
const isComplexExpression = (node) => {
|
|
545
|
-
if (node.type ===
|
|
1060
|
+
if (node.type === AST_NODE_TYPES11.SpreadElement) {
|
|
546
1061
|
return false;
|
|
547
1062
|
}
|
|
548
|
-
if (node.type ===
|
|
1063
|
+
if (node.type === AST_NODE_TYPES11.ConditionalExpression) {
|
|
549
1064
|
return true;
|
|
550
1065
|
}
|
|
551
|
-
if (node.type ===
|
|
1066
|
+
if (node.type === AST_NODE_TYPES11.LogicalExpression) {
|
|
552
1067
|
return true;
|
|
553
1068
|
}
|
|
554
|
-
if (node.type ===
|
|
1069
|
+
if (node.type === AST_NODE_TYPES11.BinaryExpression) {
|
|
555
1070
|
const logicalOperators = ["==", "===", "!=", "!==", "<", ">", "<=", ">=", "in", "instanceof"];
|
|
556
1071
|
return logicalOperators.includes(node.operator);
|
|
557
1072
|
}
|
|
558
|
-
if (node.type ===
|
|
1073
|
+
if (node.type === AST_NODE_TYPES11.UnaryExpression) {
|
|
559
1074
|
return node.operator === "!";
|
|
560
1075
|
}
|
|
561
1076
|
return false;
|
|
@@ -586,12 +1101,127 @@ var noLogicInParams = createRule9({
|
|
|
586
1101
|
});
|
|
587
1102
|
var no_logic_in_params_default = noLogicInParams;
|
|
588
1103
|
|
|
1104
|
+
// src/rules/no-single-char-variables.ts
|
|
1105
|
+
import { ESLintUtils as ESLintUtils15, AST_NODE_TYPES as AST_NODE_TYPES12 } from "@typescript-eslint/utils";
|
|
1106
|
+
var createRule15 = ESLintUtils15.RuleCreator(
|
|
1107
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
1108
|
+
);
|
|
1109
|
+
var ALLOWED_IN_FOR_LOOPS = /* @__PURE__ */ new Set(["i", "j", "k", "n"]);
|
|
1110
|
+
var ALLOWED_UNDERSCORE = "_";
|
|
1111
|
+
var isForLoopInit = (node) => {
|
|
1112
|
+
let current = node;
|
|
1113
|
+
while (current) {
|
|
1114
|
+
const parentNode = current.parent;
|
|
1115
|
+
if (!parentNode) {
|
|
1116
|
+
return false;
|
|
1117
|
+
}
|
|
1118
|
+
if (parentNode.type === AST_NODE_TYPES12.ForStatement) {
|
|
1119
|
+
const { init } = parentNode;
|
|
1120
|
+
if (init && init === current) {
|
|
1121
|
+
return true;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
current = parentNode;
|
|
1125
|
+
}
|
|
1126
|
+
return false;
|
|
1127
|
+
};
|
|
1128
|
+
var isAllowedInContext = (name, node) => {
|
|
1129
|
+
if (name === ALLOWED_UNDERSCORE) {
|
|
1130
|
+
return true;
|
|
1131
|
+
}
|
|
1132
|
+
if (ALLOWED_IN_FOR_LOOPS.has(name) && isForLoopInit(node)) {
|
|
1133
|
+
return true;
|
|
1134
|
+
}
|
|
1135
|
+
return false;
|
|
1136
|
+
};
|
|
1137
|
+
var noSingleCharVariables = createRule15({
|
|
1138
|
+
name: "no-single-char-variables",
|
|
1139
|
+
meta: {
|
|
1140
|
+
type: "suggestion",
|
|
1141
|
+
docs: {
|
|
1142
|
+
description: "Disallow single character variable and parameter names for better code readability"
|
|
1143
|
+
},
|
|
1144
|
+
messages: {
|
|
1145
|
+
noSingleChar: "Avoid single character variable name '{{name}}'. Use a descriptive name that clearly indicates the purpose."
|
|
1146
|
+
},
|
|
1147
|
+
schema: []
|
|
1148
|
+
},
|
|
1149
|
+
defaultOptions: [],
|
|
1150
|
+
create(context) {
|
|
1151
|
+
const checkIdentifier = (node, declarationNode) => {
|
|
1152
|
+
const { name } = node;
|
|
1153
|
+
if (name.length !== 1) {
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
if (isAllowedInContext(name, declarationNode)) {
|
|
1157
|
+
return;
|
|
1158
|
+
}
|
|
1159
|
+
context.report({
|
|
1160
|
+
node,
|
|
1161
|
+
messageId: "noSingleChar",
|
|
1162
|
+
data: { name }
|
|
1163
|
+
});
|
|
1164
|
+
};
|
|
1165
|
+
const checkPattern = (pattern, declarationNode) => {
|
|
1166
|
+
if (pattern.type === AST_NODE_TYPES12.Identifier) {
|
|
1167
|
+
checkIdentifier(pattern, declarationNode);
|
|
1168
|
+
} else if (pattern.type === AST_NODE_TYPES12.ObjectPattern) {
|
|
1169
|
+
pattern.properties.forEach((prop) => {
|
|
1170
|
+
if (prop.type === AST_NODE_TYPES12.Property && prop.value.type === AST_NODE_TYPES12.Identifier) {
|
|
1171
|
+
checkIdentifier(prop.value, declarationNode);
|
|
1172
|
+
} else if (prop.type === AST_NODE_TYPES12.RestElement && prop.argument.type === AST_NODE_TYPES12.Identifier) {
|
|
1173
|
+
checkIdentifier(prop.argument, declarationNode);
|
|
1174
|
+
}
|
|
1175
|
+
});
|
|
1176
|
+
} else if (pattern.type === AST_NODE_TYPES12.ArrayPattern) {
|
|
1177
|
+
pattern.elements.forEach((element) => {
|
|
1178
|
+
if (element?.type === AST_NODE_TYPES12.Identifier) {
|
|
1179
|
+
checkIdentifier(element, declarationNode);
|
|
1180
|
+
} else if (element?.type === AST_NODE_TYPES12.RestElement && element.argument.type === AST_NODE_TYPES12.Identifier) {
|
|
1181
|
+
checkIdentifier(element.argument, declarationNode);
|
|
1182
|
+
}
|
|
1183
|
+
});
|
|
1184
|
+
} else if (pattern.type === AST_NODE_TYPES12.AssignmentPattern && pattern.left.type === AST_NODE_TYPES12.Identifier) {
|
|
1185
|
+
checkIdentifier(pattern.left, declarationNode);
|
|
1186
|
+
} else if (pattern.type === AST_NODE_TYPES12.RestElement && pattern.argument.type === AST_NODE_TYPES12.Identifier) {
|
|
1187
|
+
checkIdentifier(pattern.argument, declarationNode);
|
|
1188
|
+
}
|
|
1189
|
+
};
|
|
1190
|
+
return {
|
|
1191
|
+
VariableDeclarator(node) {
|
|
1192
|
+
checkPattern(node.id, node);
|
|
1193
|
+
},
|
|
1194
|
+
FunctionDeclaration(node) {
|
|
1195
|
+
if (node.id) {
|
|
1196
|
+
checkIdentifier(node.id, node);
|
|
1197
|
+
}
|
|
1198
|
+
node.params.forEach((param) => checkPattern(param, node));
|
|
1199
|
+
},
|
|
1200
|
+
FunctionExpression(node) {
|
|
1201
|
+
if (node.id) {
|
|
1202
|
+
checkIdentifier(node.id, node);
|
|
1203
|
+
}
|
|
1204
|
+
node.params.forEach((param) => checkPattern(param, node));
|
|
1205
|
+
},
|
|
1206
|
+
ArrowFunctionExpression(node) {
|
|
1207
|
+
node.params.forEach((param) => checkPattern(param, node));
|
|
1208
|
+
},
|
|
1209
|
+
CatchClause(node) {
|
|
1210
|
+
if (node.param) {
|
|
1211
|
+
checkPattern(node.param, node);
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
});
|
|
1217
|
+
var no_single_char_variables_default = noSingleCharVariables;
|
|
1218
|
+
|
|
589
1219
|
// src/rules/prefer-destructuring-params.ts
|
|
590
|
-
import { AST_NODE_TYPES as
|
|
591
|
-
var
|
|
592
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
1220
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES13, ESLintUtils as ESLintUtils16 } from "@typescript-eslint/utils";
|
|
1221
|
+
var createRule16 = ESLintUtils16.RuleCreator(
|
|
1222
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
593
1223
|
);
|
|
594
|
-
var preferDestructuringParams =
|
|
1224
|
+
var preferDestructuringParams = createRule16({
|
|
595
1225
|
name: "prefer-destructuring-params",
|
|
596
1226
|
meta: {
|
|
597
1227
|
type: "suggestion",
|
|
@@ -605,20 +1235,20 @@ var preferDestructuringParams = createRule10({
|
|
|
605
1235
|
},
|
|
606
1236
|
defaultOptions: [],
|
|
607
1237
|
create(context) {
|
|
608
|
-
const
|
|
1238
|
+
const isCallbackFunction2 = (node) => {
|
|
609
1239
|
const { parent } = node;
|
|
610
|
-
return parent?.type ===
|
|
1240
|
+
return parent?.type === AST_NODE_TYPES13.CallExpression;
|
|
611
1241
|
};
|
|
612
1242
|
const isDeveloperFunction = (node) => {
|
|
613
|
-
if (node.type ===
|
|
1243
|
+
if (node.type === AST_NODE_TYPES13.FunctionDeclaration) {
|
|
614
1244
|
return true;
|
|
615
1245
|
}
|
|
616
|
-
if (node.type ===
|
|
617
|
-
if (
|
|
1246
|
+
if (node.type === AST_NODE_TYPES13.FunctionExpression || node.type === AST_NODE_TYPES13.ArrowFunctionExpression) {
|
|
1247
|
+
if (isCallbackFunction2(node)) {
|
|
618
1248
|
return false;
|
|
619
1249
|
}
|
|
620
1250
|
const { parent } = node;
|
|
621
|
-
return parent?.type ===
|
|
1251
|
+
return parent?.type === AST_NODE_TYPES13.VariableDeclarator || parent?.type === AST_NODE_TYPES13.AssignmentExpression || parent?.type === AST_NODE_TYPES13.Property || parent?.type === AST_NODE_TYPES13.MethodDefinition;
|
|
622
1252
|
}
|
|
623
1253
|
return false;
|
|
624
1254
|
};
|
|
@@ -630,7 +1260,7 @@ var preferDestructuringParams = createRule10({
|
|
|
630
1260
|
if (!isDeveloperFunction(node)) {
|
|
631
1261
|
return;
|
|
632
1262
|
}
|
|
633
|
-
if (node.type ===
|
|
1263
|
+
if (node.type === AST_NODE_TYPES13.FunctionDeclaration && node.id) {
|
|
634
1264
|
const functionName = node.id.name;
|
|
635
1265
|
if (functionName.startsWith("_") || functionName.includes("$") || /^[A-Z][a-zA-Z]*$/.test(functionName)) {
|
|
636
1266
|
return;
|
|
@@ -640,7 +1270,7 @@ var preferDestructuringParams = createRule10({
|
|
|
640
1270
|
return;
|
|
641
1271
|
}
|
|
642
1272
|
const hasNonDestructuredParams = node.params.some(
|
|
643
|
-
(param) => param.type !==
|
|
1273
|
+
(param) => param.type !== AST_NODE_TYPES13.ObjectPattern && param.type !== AST_NODE_TYPES13.RestElement
|
|
644
1274
|
);
|
|
645
1275
|
if (hasNonDestructuredParams) {
|
|
646
1276
|
context.report({
|
|
@@ -658,12 +1288,103 @@ var preferDestructuringParams = createRule10({
|
|
|
658
1288
|
});
|
|
659
1289
|
var prefer_destructuring_params_default = preferDestructuringParams;
|
|
660
1290
|
|
|
1291
|
+
// src/rules/prefer-function-declaration.ts
|
|
1292
|
+
import { ESLintUtils as ESLintUtils17, AST_NODE_TYPES as AST_NODE_TYPES14 } from "@typescript-eslint/utils";
|
|
1293
|
+
var createRule17 = ESLintUtils17.RuleCreator(
|
|
1294
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
1295
|
+
);
|
|
1296
|
+
var isTsFile = (filename) => filename.endsWith(".ts") && !filename.endsWith(".d.ts");
|
|
1297
|
+
var isCallbackContext = (node) => {
|
|
1298
|
+
const { parent } = node;
|
|
1299
|
+
if (!parent) {
|
|
1300
|
+
return false;
|
|
1301
|
+
}
|
|
1302
|
+
if (parent.type === AST_NODE_TYPES14.CallExpression && parent.arguments.includes(node)) {
|
|
1303
|
+
return true;
|
|
1304
|
+
}
|
|
1305
|
+
if (parent.type === AST_NODE_TYPES14.NewExpression && parent.arguments.includes(node)) {
|
|
1306
|
+
return true;
|
|
1307
|
+
}
|
|
1308
|
+
if (parent.type === AST_NODE_TYPES14.ReturnStatement) {
|
|
1309
|
+
return true;
|
|
1310
|
+
}
|
|
1311
|
+
if (parent.type === AST_NODE_TYPES14.Property) {
|
|
1312
|
+
return true;
|
|
1313
|
+
}
|
|
1314
|
+
if (parent.type === AST_NODE_TYPES14.ArrayExpression) {
|
|
1315
|
+
return true;
|
|
1316
|
+
}
|
|
1317
|
+
if (parent.type === AST_NODE_TYPES14.ConditionalExpression) {
|
|
1318
|
+
return true;
|
|
1319
|
+
}
|
|
1320
|
+
if (parent.type === AST_NODE_TYPES14.LogicalExpression) {
|
|
1321
|
+
return true;
|
|
1322
|
+
}
|
|
1323
|
+
if (parent.type === AST_NODE_TYPES14.AssignmentExpression && parent.left !== node) {
|
|
1324
|
+
return true;
|
|
1325
|
+
}
|
|
1326
|
+
return false;
|
|
1327
|
+
};
|
|
1328
|
+
var preferFunctionDeclaration = createRule17({
|
|
1329
|
+
name: "prefer-function-declaration",
|
|
1330
|
+
meta: {
|
|
1331
|
+
type: "suggestion",
|
|
1332
|
+
docs: {
|
|
1333
|
+
description: "Enforce function declarations over arrow functions assigned to variables in .ts files for better readability and hoisting"
|
|
1334
|
+
},
|
|
1335
|
+
messages: {
|
|
1336
|
+
preferDeclaration: "Use function declaration instead of arrow function. Replace 'const {{name}} = () => ...' with 'function {{name}}() ...'",
|
|
1337
|
+
preferDeclarationExpr: "Use function declaration instead of function expression. Replace 'const {{name}} = function() ...' with 'function {{name}}() ...'"
|
|
1338
|
+
},
|
|
1339
|
+
schema: []
|
|
1340
|
+
},
|
|
1341
|
+
defaultOptions: [],
|
|
1342
|
+
create(context) {
|
|
1343
|
+
const { filename } = context;
|
|
1344
|
+
if (!isTsFile(filename)) {
|
|
1345
|
+
return {};
|
|
1346
|
+
}
|
|
1347
|
+
return {
|
|
1348
|
+
VariableDeclarator(node) {
|
|
1349
|
+
if (node.id.type !== AST_NODE_TYPES14.Identifier) {
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
const { init } = node;
|
|
1353
|
+
if (!init) {
|
|
1354
|
+
return;
|
|
1355
|
+
}
|
|
1356
|
+
if (init.type === AST_NODE_TYPES14.ArrowFunctionExpression) {
|
|
1357
|
+
if (isCallbackContext(init)) {
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
context.report({
|
|
1361
|
+
node: init,
|
|
1362
|
+
messageId: "preferDeclaration",
|
|
1363
|
+
data: { name: node.id.name }
|
|
1364
|
+
});
|
|
1365
|
+
}
|
|
1366
|
+
if (init.type === AST_NODE_TYPES14.FunctionExpression) {
|
|
1367
|
+
if (isCallbackContext(init)) {
|
|
1368
|
+
return;
|
|
1369
|
+
}
|
|
1370
|
+
context.report({
|
|
1371
|
+
node: init,
|
|
1372
|
+
messageId: "preferDeclarationExpr",
|
|
1373
|
+
data: { name: node.id.name }
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
};
|
|
1378
|
+
}
|
|
1379
|
+
});
|
|
1380
|
+
var prefer_function_declaration_default = preferFunctionDeclaration;
|
|
1381
|
+
|
|
661
1382
|
// src/rules/prefer-import-type.ts
|
|
662
|
-
import { AST_NODE_TYPES as
|
|
663
|
-
var
|
|
664
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
1383
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES15, ESLintUtils as ESLintUtils18 } from "@typescript-eslint/utils";
|
|
1384
|
+
var createRule18 = ESLintUtils18.RuleCreator(
|
|
1385
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
665
1386
|
);
|
|
666
|
-
var preferImportType =
|
|
1387
|
+
var preferImportType = createRule18({
|
|
667
1388
|
name: "prefer-import-type",
|
|
668
1389
|
meta: {
|
|
669
1390
|
type: "suggestion",
|
|
@@ -678,6 +1399,81 @@ var preferImportType = createRule11({
|
|
|
678
1399
|
},
|
|
679
1400
|
defaultOptions: [],
|
|
680
1401
|
create(context) {
|
|
1402
|
+
function isInTypeContext(node) {
|
|
1403
|
+
let current = node;
|
|
1404
|
+
while (current) {
|
|
1405
|
+
switch (current.type) {
|
|
1406
|
+
case AST_NODE_TYPES15.TSTypeReference:
|
|
1407
|
+
case AST_NODE_TYPES15.TSTypeAnnotation:
|
|
1408
|
+
case AST_NODE_TYPES15.TSTypeParameterInstantiation:
|
|
1409
|
+
case AST_NODE_TYPES15.TSInterfaceHeritage:
|
|
1410
|
+
case AST_NODE_TYPES15.TSClassImplements:
|
|
1411
|
+
case AST_NODE_TYPES15.TSTypeQuery:
|
|
1412
|
+
case AST_NODE_TYPES15.TSTypeAssertion:
|
|
1413
|
+
case AST_NODE_TYPES15.TSAsExpression:
|
|
1414
|
+
case AST_NODE_TYPES15.TSSatisfiesExpression:
|
|
1415
|
+
case AST_NODE_TYPES15.TSTypeAliasDeclaration:
|
|
1416
|
+
case AST_NODE_TYPES15.TSInterfaceDeclaration:
|
|
1417
|
+
case AST_NODE_TYPES15.TSTypeParameter:
|
|
1418
|
+
case AST_NODE_TYPES15.TSQualifiedName:
|
|
1419
|
+
return true;
|
|
1420
|
+
case AST_NODE_TYPES15.MemberExpression:
|
|
1421
|
+
case AST_NODE_TYPES15.Identifier:
|
|
1422
|
+
current = current.parent;
|
|
1423
|
+
break;
|
|
1424
|
+
default:
|
|
1425
|
+
return false;
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
return false;
|
|
1429
|
+
}
|
|
1430
|
+
function isUsedAsValue(localName, scope) {
|
|
1431
|
+
const variable = scope.set.get(localName);
|
|
1432
|
+
if (!variable) {
|
|
1433
|
+
return false;
|
|
1434
|
+
}
|
|
1435
|
+
if (variable.references.length === 0) {
|
|
1436
|
+
return false;
|
|
1437
|
+
}
|
|
1438
|
+
return variable.references.some((ref) => {
|
|
1439
|
+
if (ref.isWrite()) {
|
|
1440
|
+
return false;
|
|
1441
|
+
}
|
|
1442
|
+
const { identifier } = ref;
|
|
1443
|
+
const { parent } = identifier;
|
|
1444
|
+
if (!parent) {
|
|
1445
|
+
return false;
|
|
1446
|
+
}
|
|
1447
|
+
if (isInTypeContext(parent)) {
|
|
1448
|
+
return false;
|
|
1449
|
+
}
|
|
1450
|
+
switch (parent.type) {
|
|
1451
|
+
case AST_NODE_TYPES15.CallExpression:
|
|
1452
|
+
case AST_NODE_TYPES15.NewExpression:
|
|
1453
|
+
case AST_NODE_TYPES15.JSXOpeningElement:
|
|
1454
|
+
case AST_NODE_TYPES15.JSXClosingElement:
|
|
1455
|
+
case AST_NODE_TYPES15.MemberExpression:
|
|
1456
|
+
case AST_NODE_TYPES15.VariableDeclarator:
|
|
1457
|
+
case AST_NODE_TYPES15.TaggedTemplateExpression:
|
|
1458
|
+
case AST_NODE_TYPES15.SpreadElement:
|
|
1459
|
+
case AST_NODE_TYPES15.ExportSpecifier:
|
|
1460
|
+
case AST_NODE_TYPES15.ArrayExpression:
|
|
1461
|
+
case AST_NODE_TYPES15.ObjectExpression:
|
|
1462
|
+
case AST_NODE_TYPES15.BinaryExpression:
|
|
1463
|
+
case AST_NODE_TYPES15.LogicalExpression:
|
|
1464
|
+
case AST_NODE_TYPES15.UnaryExpression:
|
|
1465
|
+
case AST_NODE_TYPES15.ReturnStatement:
|
|
1466
|
+
case AST_NODE_TYPES15.ArrowFunctionExpression:
|
|
1467
|
+
case AST_NODE_TYPES15.ConditionalExpression:
|
|
1468
|
+
case AST_NODE_TYPES15.AwaitExpression:
|
|
1469
|
+
case AST_NODE_TYPES15.YieldExpression:
|
|
1470
|
+
case AST_NODE_TYPES15.Property:
|
|
1471
|
+
return true;
|
|
1472
|
+
default:
|
|
1473
|
+
return false;
|
|
1474
|
+
}
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
681
1477
|
function checkImportDeclaration(node) {
|
|
682
1478
|
if (node.importKind === "type") {
|
|
683
1479
|
return;
|
|
@@ -693,19 +1489,17 @@ var preferImportType = createRule11({
|
|
|
693
1489
|
if (isRuntimeImport) {
|
|
694
1490
|
return;
|
|
695
1491
|
}
|
|
1492
|
+
const scope = context.sourceCode.getScope(node);
|
|
696
1493
|
const isTypeOnlyImport = node.specifiers.every((specifier) => {
|
|
697
|
-
if (specifier.type ===
|
|
1494
|
+
if (specifier.type === AST_NODE_TYPES15.ImportDefaultSpecifier) {
|
|
698
1495
|
return false;
|
|
699
1496
|
}
|
|
700
|
-
if (specifier.type ===
|
|
1497
|
+
if (specifier.type === AST_NODE_TYPES15.ImportNamespaceSpecifier) {
|
|
701
1498
|
return false;
|
|
702
1499
|
}
|
|
703
|
-
if (specifier.type ===
|
|
704
|
-
const
|
|
705
|
-
|
|
706
|
-
importedName
|
|
707
|
-
) || importedName.endsWith("Type") || importedName.endsWith("Interface") || importedName.endsWith("Props");
|
|
708
|
-
return isKnownTypeOnly;
|
|
1500
|
+
if (specifier.type === AST_NODE_TYPES15.ImportSpecifier) {
|
|
1501
|
+
const localName = specifier.local.name;
|
|
1502
|
+
return !isUsedAsValue(localName, scope);
|
|
709
1503
|
}
|
|
710
1504
|
return false;
|
|
711
1505
|
});
|
|
@@ -729,11 +1523,11 @@ var preferImportType = createRule11({
|
|
|
729
1523
|
var prefer_import_type_default = preferImportType;
|
|
730
1524
|
|
|
731
1525
|
// src/rules/prefer-interface-over-inline-types.ts
|
|
732
|
-
import { AST_NODE_TYPES as
|
|
733
|
-
var
|
|
734
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
1526
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES16, ESLintUtils as ESLintUtils19 } from "@typescript-eslint/utils";
|
|
1527
|
+
var createRule19 = ESLintUtils19.RuleCreator(
|
|
1528
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
735
1529
|
);
|
|
736
|
-
var preferInterfaceOverInlineTypes =
|
|
1530
|
+
var preferInterfaceOverInlineTypes = createRule19({
|
|
737
1531
|
name: "prefer-interface-over-inline-types",
|
|
738
1532
|
meta: {
|
|
739
1533
|
type: "suggestion",
|
|
@@ -749,67 +1543,67 @@ var preferInterfaceOverInlineTypes = createRule12({
|
|
|
749
1543
|
defaultOptions: [],
|
|
750
1544
|
create(context) {
|
|
751
1545
|
function hasJSXInConditional(node) {
|
|
752
|
-
return node.consequent.type ===
|
|
1546
|
+
return node.consequent.type === AST_NODE_TYPES16.JSXElement || node.consequent.type === AST_NODE_TYPES16.JSXFragment || node.alternate.type === AST_NODE_TYPES16.JSXElement || node.alternate.type === AST_NODE_TYPES16.JSXFragment;
|
|
753
1547
|
}
|
|
754
1548
|
function hasJSXInLogical(node) {
|
|
755
|
-
return node.right.type ===
|
|
1549
|
+
return node.right.type === AST_NODE_TYPES16.JSXElement || node.right.type === AST_NODE_TYPES16.JSXFragment;
|
|
756
1550
|
}
|
|
757
1551
|
function hasJSXReturn(block) {
|
|
758
1552
|
return block.body.some((stmt) => {
|
|
759
|
-
if (stmt.type ===
|
|
760
|
-
return stmt.argument.type ===
|
|
1553
|
+
if (stmt.type === AST_NODE_TYPES16.ReturnStatement && stmt.argument) {
|
|
1554
|
+
return stmt.argument.type === AST_NODE_TYPES16.JSXElement || stmt.argument.type === AST_NODE_TYPES16.JSXFragment || stmt.argument.type === AST_NODE_TYPES16.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === AST_NODE_TYPES16.LogicalExpression && hasJSXInLogical(stmt.argument);
|
|
761
1555
|
}
|
|
762
1556
|
return false;
|
|
763
1557
|
});
|
|
764
1558
|
}
|
|
765
|
-
function
|
|
766
|
-
if (node.type ===
|
|
767
|
-
if (node.body.type ===
|
|
1559
|
+
function isReactComponent2(node) {
|
|
1560
|
+
if (node.type === AST_NODE_TYPES16.ArrowFunctionExpression) {
|
|
1561
|
+
if (node.body.type === AST_NODE_TYPES16.JSXElement || node.body.type === AST_NODE_TYPES16.JSXFragment) {
|
|
768
1562
|
return true;
|
|
769
1563
|
}
|
|
770
|
-
if (node.body.type ===
|
|
1564
|
+
if (node.body.type === AST_NODE_TYPES16.BlockStatement) {
|
|
771
1565
|
return hasJSXReturn(node.body);
|
|
772
1566
|
}
|
|
773
|
-
} else if (node.type ===
|
|
774
|
-
if (node.body && node.body.type ===
|
|
1567
|
+
} else if (node.type === AST_NODE_TYPES16.FunctionExpression || node.type === AST_NODE_TYPES16.FunctionDeclaration) {
|
|
1568
|
+
if (node.body && node.body.type === AST_NODE_TYPES16.BlockStatement) {
|
|
775
1569
|
return hasJSXReturn(node.body);
|
|
776
1570
|
}
|
|
777
1571
|
}
|
|
778
1572
|
return false;
|
|
779
1573
|
}
|
|
780
1574
|
function isInlineTypeAnnotation(node) {
|
|
781
|
-
if (node.type ===
|
|
1575
|
+
if (node.type === AST_NODE_TYPES16.TSTypeLiteral) {
|
|
782
1576
|
return true;
|
|
783
1577
|
}
|
|
784
|
-
if (node.type ===
|
|
785
|
-
return node.typeArguments.params.some((param) => param.type ===
|
|
1578
|
+
if (node.type === AST_NODE_TYPES16.TSTypeReference && node.typeArguments) {
|
|
1579
|
+
return node.typeArguments.params.some((param) => param.type === AST_NODE_TYPES16.TSTypeLiteral);
|
|
786
1580
|
}
|
|
787
|
-
if (node.type ===
|
|
1581
|
+
if (node.type === AST_NODE_TYPES16.TSUnionType) {
|
|
788
1582
|
return node.types.some((type) => isInlineTypeAnnotation(type));
|
|
789
1583
|
}
|
|
790
1584
|
return false;
|
|
791
1585
|
}
|
|
792
1586
|
function hasInlineObjectType(node) {
|
|
793
|
-
if (node.type ===
|
|
1587
|
+
if (node.type === AST_NODE_TYPES16.TSTypeLiteral) {
|
|
794
1588
|
return true;
|
|
795
1589
|
}
|
|
796
|
-
if (node.type ===
|
|
797
|
-
return node.typeArguments.params.some((param) => param.type ===
|
|
1590
|
+
if (node.type === AST_NODE_TYPES16.TSTypeReference && node.typeArguments) {
|
|
1591
|
+
return node.typeArguments.params.some((param) => param.type === AST_NODE_TYPES16.TSTypeLiteral);
|
|
798
1592
|
}
|
|
799
|
-
if (node.type ===
|
|
1593
|
+
if (node.type === AST_NODE_TYPES16.TSUnionType) {
|
|
800
1594
|
return node.types.some((type) => hasInlineObjectType(type));
|
|
801
1595
|
}
|
|
802
1596
|
return false;
|
|
803
1597
|
}
|
|
804
1598
|
function checkFunction(node) {
|
|
805
|
-
if (!
|
|
1599
|
+
if (!isReactComponent2(node)) {
|
|
806
1600
|
return;
|
|
807
1601
|
}
|
|
808
1602
|
if (node.params.length !== 1) {
|
|
809
1603
|
return;
|
|
810
1604
|
}
|
|
811
1605
|
const param = node.params[0];
|
|
812
|
-
if (param.type ===
|
|
1606
|
+
if (param.type === AST_NODE_TYPES16.Identifier && param.typeAnnotation) {
|
|
813
1607
|
const { typeAnnotation } = param.typeAnnotation;
|
|
814
1608
|
if (isInlineTypeAnnotation(typeAnnotation) && hasInlineObjectType(typeAnnotation)) {
|
|
815
1609
|
context.report({
|
|
@@ -828,12 +1622,100 @@ var preferInterfaceOverInlineTypes = createRule12({
|
|
|
828
1622
|
});
|
|
829
1623
|
var prefer_interface_over_inline_types_default = preferInterfaceOverInlineTypes;
|
|
830
1624
|
|
|
1625
|
+
// src/rules/prefer-jsx-template-literals.ts
|
|
1626
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES17, ESLintUtils as ESLintUtils20 } from "@typescript-eslint/utils";
|
|
1627
|
+
var createRule20 = ESLintUtils20.RuleCreator(
|
|
1628
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
1629
|
+
);
|
|
1630
|
+
var preferJSXTemplateLiterals = createRule20({
|
|
1631
|
+
name: "prefer-jsx-template-literals",
|
|
1632
|
+
meta: {
|
|
1633
|
+
type: "suggestion",
|
|
1634
|
+
docs: {
|
|
1635
|
+
description: "Enforce using template literals instead of mixing text and JSX expressions"
|
|
1636
|
+
},
|
|
1637
|
+
fixable: "code",
|
|
1638
|
+
schema: [],
|
|
1639
|
+
messages: {
|
|
1640
|
+
preferTemplate: "Use template literal instead of mixing text with JSX expressions"
|
|
1641
|
+
}
|
|
1642
|
+
},
|
|
1643
|
+
defaultOptions: [],
|
|
1644
|
+
create(context) {
|
|
1645
|
+
function handleTextBeforeExpression(textNode, exprNode) {
|
|
1646
|
+
const textValue = textNode.value;
|
|
1647
|
+
const trimmedText = textValue.trim();
|
|
1648
|
+
if (!trimmedText) {
|
|
1649
|
+
return;
|
|
1650
|
+
}
|
|
1651
|
+
const hasTextContent = trimmedText.length > 0 && textValue !== trimmedText;
|
|
1652
|
+
const hasNoTrailingSpace = trimmedText.length > 0 && /\S$/.test(textValue);
|
|
1653
|
+
if (!hasTextContent && !hasNoTrailingSpace) {
|
|
1654
|
+
return;
|
|
1655
|
+
}
|
|
1656
|
+
context.report({
|
|
1657
|
+
node: textNode,
|
|
1658
|
+
messageId: "preferTemplate",
|
|
1659
|
+
fix(fixer) {
|
|
1660
|
+
const textPart = textValue.trimEnd();
|
|
1661
|
+
const exprText = context.sourceCode.getText(exprNode.expression);
|
|
1662
|
+
const templateLiteral = `{\`${textPart}\${${exprText}}\`}`;
|
|
1663
|
+
return [fixer.replaceText(textNode, templateLiteral), fixer.remove(exprNode)];
|
|
1664
|
+
}
|
|
1665
|
+
});
|
|
1666
|
+
}
|
|
1667
|
+
function handleExpressionBeforeText(exprNode, textNode) {
|
|
1668
|
+
const textValue = textNode.value;
|
|
1669
|
+
const trimmedText = textValue.trim();
|
|
1670
|
+
if (!trimmedText) {
|
|
1671
|
+
return;
|
|
1672
|
+
}
|
|
1673
|
+
const startsWithNonWhitespace = /^\S/.test(trimmedText);
|
|
1674
|
+
if (!startsWithNonWhitespace) {
|
|
1675
|
+
return;
|
|
1676
|
+
}
|
|
1677
|
+
context.report({
|
|
1678
|
+
node: textNode,
|
|
1679
|
+
messageId: "preferTemplate",
|
|
1680
|
+
fix(fixer) {
|
|
1681
|
+
const exprText = context.sourceCode.getText(exprNode.expression);
|
|
1682
|
+
const textPart = textValue.trim();
|
|
1683
|
+
const templateLiteral = `{\`\${${exprText}}${textPart}\`}`;
|
|
1684
|
+
return [fixer.replaceText(exprNode, templateLiteral), fixer.remove(textNode)];
|
|
1685
|
+
}
|
|
1686
|
+
});
|
|
1687
|
+
}
|
|
1688
|
+
function checkJSXElement(node) {
|
|
1689
|
+
const { children } = node;
|
|
1690
|
+
if (children.length < 2) {
|
|
1691
|
+
return;
|
|
1692
|
+
}
|
|
1693
|
+
for (let i = 0; i < children.length - 1; i += 1) {
|
|
1694
|
+
const child = children[i];
|
|
1695
|
+
const nextChild = children[i + 1];
|
|
1696
|
+
if (!child || !nextChild) {
|
|
1697
|
+
return;
|
|
1698
|
+
}
|
|
1699
|
+
if (child.type === AST_NODE_TYPES17.JSXText && nextChild.type === AST_NODE_TYPES17.JSXExpressionContainer) {
|
|
1700
|
+
handleTextBeforeExpression(child, nextChild);
|
|
1701
|
+
} else if (child.type === AST_NODE_TYPES17.JSXExpressionContainer && nextChild.type === AST_NODE_TYPES17.JSXText) {
|
|
1702
|
+
handleExpressionBeforeText(child, nextChild);
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
return {
|
|
1707
|
+
JSXElement: checkJSXElement
|
|
1708
|
+
};
|
|
1709
|
+
}
|
|
1710
|
+
});
|
|
1711
|
+
var prefer_jsx_template_literals_default = preferJSXTemplateLiterals;
|
|
1712
|
+
|
|
831
1713
|
// src/rules/prefer-named-param-types.ts
|
|
832
|
-
import { AST_NODE_TYPES as
|
|
833
|
-
var
|
|
834
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
1714
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES18, ESLintUtils as ESLintUtils21 } from "@typescript-eslint/utils";
|
|
1715
|
+
var createRule21 = ESLintUtils21.RuleCreator(
|
|
1716
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
835
1717
|
);
|
|
836
|
-
var preferNamedParamTypes =
|
|
1718
|
+
var preferNamedParamTypes = createRule21({
|
|
837
1719
|
name: "prefer-named-param-types",
|
|
838
1720
|
meta: {
|
|
839
1721
|
type: "suggestion",
|
|
@@ -848,16 +1730,16 @@ var preferNamedParamTypes = createRule13({
|
|
|
848
1730
|
defaultOptions: [],
|
|
849
1731
|
create(context) {
|
|
850
1732
|
function hasInlineObjectType(param) {
|
|
851
|
-
if (param.type ===
|
|
1733
|
+
if (param.type === AST_NODE_TYPES18.AssignmentPattern) {
|
|
852
1734
|
return hasInlineObjectType(param.left);
|
|
853
1735
|
}
|
|
854
|
-
if (param.type ===
|
|
855
|
-
if (param.typeAnnotation?.typeAnnotation.type ===
|
|
1736
|
+
if (param.type === AST_NODE_TYPES18.ObjectPattern) {
|
|
1737
|
+
if (param.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES18.TSTypeLiteral) {
|
|
856
1738
|
return true;
|
|
857
1739
|
}
|
|
858
1740
|
}
|
|
859
|
-
if (param.type ===
|
|
860
|
-
if (param.typeAnnotation?.typeAnnotation.type ===
|
|
1741
|
+
if (param.type === AST_NODE_TYPES18.Identifier) {
|
|
1742
|
+
if (param.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES18.TSTypeLiteral) {
|
|
861
1743
|
return true;
|
|
862
1744
|
}
|
|
863
1745
|
}
|
|
@@ -891,11 +1773,11 @@ var preferNamedParamTypes = createRule13({
|
|
|
891
1773
|
var prefer_named_param_types_default = preferNamedParamTypes;
|
|
892
1774
|
|
|
893
1775
|
// src/rules/prefer-react-import-types.ts
|
|
894
|
-
import { AST_NODE_TYPES as
|
|
895
|
-
var
|
|
896
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
1776
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES19, ESLintUtils as ESLintUtils22 } from "@typescript-eslint/utils";
|
|
1777
|
+
var createRule22 = ESLintUtils22.RuleCreator(
|
|
1778
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
897
1779
|
);
|
|
898
|
-
var preferReactImportTypes =
|
|
1780
|
+
var preferReactImportTypes = createRule22({
|
|
899
1781
|
name: "prefer-react-import-types",
|
|
900
1782
|
meta: {
|
|
901
1783
|
type: "suggestion",
|
|
@@ -971,7 +1853,7 @@ var preferReactImportTypes = createRule14({
|
|
|
971
1853
|
]);
|
|
972
1854
|
const allReactExports = /* @__PURE__ */ new Set([...reactTypes, ...reactRuntimeExports]);
|
|
973
1855
|
function checkMemberExpression(node) {
|
|
974
|
-
if (node.object.type ===
|
|
1856
|
+
if (node.object.type === AST_NODE_TYPES19.Identifier && node.object.name === "React" && node.property.type === AST_NODE_TYPES19.Identifier && allReactExports.has(node.property.name)) {
|
|
975
1857
|
const typeName = node.property.name;
|
|
976
1858
|
const isType = reactTypes.has(typeName);
|
|
977
1859
|
const importStatement = isType ? `import type { ${typeName} } from "react"` : `import { ${typeName} } from "react"`;
|
|
@@ -988,7 +1870,7 @@ var preferReactImportTypes = createRule14({
|
|
|
988
1870
|
return {
|
|
989
1871
|
MemberExpression: checkMemberExpression,
|
|
990
1872
|
"TSTypeReference > TSQualifiedName": (node) => {
|
|
991
|
-
if (node.left.type ===
|
|
1873
|
+
if (node.left.type === AST_NODE_TYPES19.Identifier && node.left.name === "React" && node.right.type === AST_NODE_TYPES19.Identifier && allReactExports.has(node.right.name)) {
|
|
992
1874
|
const typeName = node.right.name;
|
|
993
1875
|
const isType = reactTypes.has(typeName);
|
|
994
1876
|
const importStatement = isType ? `import type { ${typeName} } from "react"` : `import { ${typeName} } from "react"`;
|
|
@@ -1008,11 +1890,11 @@ var preferReactImportTypes = createRule14({
|
|
|
1008
1890
|
var prefer_react_import_types_default = preferReactImportTypes;
|
|
1009
1891
|
|
|
1010
1892
|
// src/rules/react-props-destructure.ts
|
|
1011
|
-
import { AST_NODE_TYPES as
|
|
1012
|
-
var
|
|
1013
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
1893
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES20, ESLintUtils as ESLintUtils23 } from "@typescript-eslint/utils";
|
|
1894
|
+
var createRule23 = ESLintUtils23.RuleCreator(
|
|
1895
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
1014
1896
|
);
|
|
1015
|
-
var reactPropsDestructure =
|
|
1897
|
+
var reactPropsDestructure = createRule23({
|
|
1016
1898
|
name: "react-props-destructure",
|
|
1017
1899
|
meta: {
|
|
1018
1900
|
type: "suggestion",
|
|
@@ -1028,45 +1910,45 @@ var reactPropsDestructure = createRule15({
|
|
|
1028
1910
|
defaultOptions: [],
|
|
1029
1911
|
create(context) {
|
|
1030
1912
|
function hasJSXInConditional(node) {
|
|
1031
|
-
return node.consequent.type ===
|
|
1913
|
+
return node.consequent.type === AST_NODE_TYPES20.JSXElement || node.consequent.type === AST_NODE_TYPES20.JSXFragment || node.alternate.type === AST_NODE_TYPES20.JSXElement || node.alternate.type === AST_NODE_TYPES20.JSXFragment;
|
|
1032
1914
|
}
|
|
1033
1915
|
function hasJSXInLogical(node) {
|
|
1034
|
-
return node.right.type ===
|
|
1916
|
+
return node.right.type === AST_NODE_TYPES20.JSXElement || node.right.type === AST_NODE_TYPES20.JSXFragment;
|
|
1035
1917
|
}
|
|
1036
1918
|
function hasJSXReturn(block) {
|
|
1037
1919
|
return block.body.some((stmt) => {
|
|
1038
|
-
if (stmt.type ===
|
|
1039
|
-
return stmt.argument.type ===
|
|
1920
|
+
if (stmt.type === AST_NODE_TYPES20.ReturnStatement && stmt.argument) {
|
|
1921
|
+
return stmt.argument.type === AST_NODE_TYPES20.JSXElement || stmt.argument.type === AST_NODE_TYPES20.JSXFragment || stmt.argument.type === AST_NODE_TYPES20.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === AST_NODE_TYPES20.LogicalExpression && hasJSXInLogical(stmt.argument);
|
|
1040
1922
|
}
|
|
1041
1923
|
return false;
|
|
1042
1924
|
});
|
|
1043
1925
|
}
|
|
1044
|
-
function
|
|
1045
|
-
if (node.type ===
|
|
1046
|
-
if (node.body.type ===
|
|
1926
|
+
function isReactComponent2(node) {
|
|
1927
|
+
if (node.type === AST_NODE_TYPES20.ArrowFunctionExpression) {
|
|
1928
|
+
if (node.body.type === AST_NODE_TYPES20.JSXElement || node.body.type === AST_NODE_TYPES20.JSXFragment) {
|
|
1047
1929
|
return true;
|
|
1048
1930
|
}
|
|
1049
|
-
if (node.body.type ===
|
|
1931
|
+
if (node.body.type === AST_NODE_TYPES20.BlockStatement) {
|
|
1050
1932
|
return hasJSXReturn(node.body);
|
|
1051
1933
|
}
|
|
1052
|
-
} else if (node.type ===
|
|
1053
|
-
if (node.body && node.body.type ===
|
|
1934
|
+
} else if (node.type === AST_NODE_TYPES20.FunctionExpression || node.type === AST_NODE_TYPES20.FunctionDeclaration) {
|
|
1935
|
+
if (node.body && node.body.type === AST_NODE_TYPES20.BlockStatement) {
|
|
1054
1936
|
return hasJSXReturn(node.body);
|
|
1055
1937
|
}
|
|
1056
1938
|
}
|
|
1057
1939
|
return false;
|
|
1058
1940
|
}
|
|
1059
1941
|
function checkFunction(node) {
|
|
1060
|
-
if (!
|
|
1942
|
+
if (!isReactComponent2(node)) {
|
|
1061
1943
|
return;
|
|
1062
1944
|
}
|
|
1063
1945
|
if (node.params.length !== 1) {
|
|
1064
1946
|
return;
|
|
1065
1947
|
}
|
|
1066
1948
|
const param = node.params[0];
|
|
1067
|
-
if (param.type ===
|
|
1068
|
-
const properties = param.properties.filter((prop) => prop.type ===
|
|
1069
|
-
if (prop.key.type ===
|
|
1949
|
+
if (param.type === AST_NODE_TYPES20.ObjectPattern) {
|
|
1950
|
+
const properties = param.properties.filter((prop) => prop.type === AST_NODE_TYPES20.Property).map((prop) => {
|
|
1951
|
+
if (prop.key.type === AST_NODE_TYPES20.Identifier) {
|
|
1070
1952
|
return prop.key.name;
|
|
1071
1953
|
}
|
|
1072
1954
|
return null;
|
|
@@ -1098,18 +1980,26 @@ var meta = {
|
|
|
1098
1980
|
version: package_default.version
|
|
1099
1981
|
};
|
|
1100
1982
|
var rules = {
|
|
1983
|
+
"boolean-naming-prefix": boolean_naming_prefix_default,
|
|
1101
1984
|
"enforce-readonly-component-props": enforce_readonly_component_props_default,
|
|
1985
|
+
"enforce-sorted-destructuring": enforce_sorted_destructuring_default,
|
|
1102
1986
|
"file-kebab-case": file_kebab_case_default,
|
|
1103
1987
|
"jsx-pascal-case": jsx_pascal_case_default,
|
|
1988
|
+
"jsx-no-non-component-function": jsx_no_non_component_function_default,
|
|
1989
|
+
"jsx-no-variable-in-callback": jsx_no_variable_in_callback_default,
|
|
1104
1990
|
"md-filename-case-restriction": md_filename_case_restriction_default,
|
|
1105
1991
|
"no-complex-inline-return": no_complex_inline_return_default,
|
|
1992
|
+
"no-direct-date": no_direct_date_default,
|
|
1106
1993
|
"no-emoji": no_emoji_default,
|
|
1107
1994
|
"no-env-fallback": no_env_fallback_default,
|
|
1108
|
-
"
|
|
1995
|
+
"require-explicit-return-type": require_explicit_return_type_default,
|
|
1109
1996
|
"no-logic-in-params": no_logic_in_params_default,
|
|
1997
|
+
"no-single-char-variables": no_single_char_variables_default,
|
|
1110
1998
|
"prefer-destructuring-params": prefer_destructuring_params_default,
|
|
1999
|
+
"prefer-function-declaration": prefer_function_declaration_default,
|
|
1111
2000
|
"prefer-import-type": prefer_import_type_default,
|
|
1112
2001
|
"prefer-interface-over-inline-types": prefer_interface_over_inline_types_default,
|
|
2002
|
+
"prefer-jsx-template-literals": prefer_jsx_template_literals_default,
|
|
1113
2003
|
"prefer-named-param-types": prefer_named_param_types_default,
|
|
1114
2004
|
"prefer-react-import-types": prefer_react_import_types_default,
|
|
1115
2005
|
"react-props-destructure": react_props_destructure_default
|
|
@@ -1119,40 +2009,56 @@ var plugin = {
|
|
|
1119
2009
|
rules
|
|
1120
2010
|
};
|
|
1121
2011
|
var baseRules = {
|
|
2012
|
+
"nextfriday/boolean-naming-prefix": "warn",
|
|
1122
2013
|
"nextfriday/no-emoji": "warn",
|
|
2014
|
+
"nextfriday/enforce-sorted-destructuring": "warn",
|
|
1123
2015
|
"nextfriday/file-kebab-case": "warn",
|
|
1124
2016
|
"nextfriday/md-filename-case-restriction": "warn",
|
|
1125
2017
|
"nextfriday/prefer-destructuring-params": "warn",
|
|
1126
|
-
"nextfriday/
|
|
2018
|
+
"nextfriday/prefer-function-declaration": "warn",
|
|
2019
|
+
"nextfriday/require-explicit-return-type": "warn",
|
|
1127
2020
|
"nextfriday/prefer-import-type": "warn",
|
|
1128
2021
|
"nextfriday/prefer-named-param-types": "warn",
|
|
1129
2022
|
"nextfriday/prefer-react-import-types": "warn",
|
|
1130
2023
|
"nextfriday/no-complex-inline-return": "warn",
|
|
2024
|
+
"nextfriday/no-direct-date": "warn",
|
|
1131
2025
|
"nextfriday/no-logic-in-params": "warn",
|
|
1132
|
-
"nextfriday/no-env-fallback": "warn"
|
|
2026
|
+
"nextfriday/no-env-fallback": "warn",
|
|
2027
|
+
"nextfriday/no-single-char-variables": "warn"
|
|
1133
2028
|
};
|
|
1134
2029
|
var baseRecommendedRules = {
|
|
2030
|
+
"nextfriday/boolean-naming-prefix": "error",
|
|
1135
2031
|
"nextfriday/no-emoji": "error",
|
|
2032
|
+
"nextfriday/enforce-sorted-destructuring": "error",
|
|
1136
2033
|
"nextfriday/file-kebab-case": "error",
|
|
1137
2034
|
"nextfriday/md-filename-case-restriction": "error",
|
|
1138
2035
|
"nextfriday/prefer-destructuring-params": "error",
|
|
1139
|
-
"nextfriday/
|
|
2036
|
+
"nextfriday/prefer-function-declaration": "error",
|
|
2037
|
+
"nextfriday/require-explicit-return-type": "error",
|
|
1140
2038
|
"nextfriday/prefer-import-type": "error",
|
|
1141
2039
|
"nextfriday/prefer-named-param-types": "error",
|
|
1142
2040
|
"nextfriday/prefer-react-import-types": "error",
|
|
1143
2041
|
"nextfriday/no-complex-inline-return": "error",
|
|
2042
|
+
"nextfriday/no-direct-date": "error",
|
|
1144
2043
|
"nextfriday/no-logic-in-params": "error",
|
|
1145
|
-
"nextfriday/no-env-fallback": "error"
|
|
2044
|
+
"nextfriday/no-env-fallback": "error",
|
|
2045
|
+
"nextfriday/no-single-char-variables": "error"
|
|
1146
2046
|
};
|
|
1147
2047
|
var jsxRules = {
|
|
1148
2048
|
"nextfriday/jsx-pascal-case": "warn",
|
|
2049
|
+
"nextfriday/jsx-no-non-component-function": "warn",
|
|
2050
|
+
"nextfriday/jsx-no-variable-in-callback": "warn",
|
|
1149
2051
|
"nextfriday/prefer-interface-over-inline-types": "warn",
|
|
2052
|
+
"nextfriday/prefer-jsx-template-literals": "warn",
|
|
1150
2053
|
"nextfriday/react-props-destructure": "warn",
|
|
1151
2054
|
"nextfriday/enforce-readonly-component-props": "warn"
|
|
1152
2055
|
};
|
|
1153
2056
|
var jsxRecommendedRules = {
|
|
1154
2057
|
"nextfriday/jsx-pascal-case": "error",
|
|
2058
|
+
"nextfriday/jsx-no-non-component-function": "error",
|
|
2059
|
+
"nextfriday/jsx-no-variable-in-callback": "error",
|
|
1155
2060
|
"nextfriday/prefer-interface-over-inline-types": "error",
|
|
2061
|
+
"nextfriday/prefer-jsx-template-literals": "error",
|
|
1156
2062
|
"nextfriday/react-props-destructure": "error",
|
|
1157
2063
|
"nextfriday/enforce-readonly-component-props": "error"
|
|
1158
2064
|
};
|