eslint-plugin-nextfriday 1.5.3 → 1.6.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 +9 -0
- package/README.md +4 -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/PREFER_JSX_TEMPLATE_LITERALS.md +78 -0
- package/lib/index.cjs +577 -127
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +56 -0
- package/lib/index.d.ts +56 -0
- package/lib/index.js +577 -127
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/index.cjs
CHANGED
|
@@ -40,7 +40,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
40
40
|
// package.json
|
|
41
41
|
var package_default = {
|
|
42
42
|
name: "eslint-plugin-nextfriday",
|
|
43
|
-
version: "1.
|
|
43
|
+
version: "1.6.0",
|
|
44
44
|
description: "A comprehensive ESLint plugin providing custom rules and configurations for Next Friday development workflows.",
|
|
45
45
|
keywords: [
|
|
46
46
|
"eslint",
|
|
@@ -157,7 +157,7 @@ var package_default = {
|
|
|
157
157
|
// src/rules/enforce-readonly-component-props.ts
|
|
158
158
|
var import_utils = require("@typescript-eslint/utils");
|
|
159
159
|
var createRule = import_utils.ESLintUtils.RuleCreator(
|
|
160
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
160
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
161
161
|
);
|
|
162
162
|
var enforceReadonlyComponentProps = createRule({
|
|
163
163
|
name: "enforce-readonly-component-props",
|
|
@@ -246,11 +246,132 @@ var enforceReadonlyComponentProps = createRule({
|
|
|
246
246
|
});
|
|
247
247
|
var enforce_readonly_component_props_default = enforceReadonlyComponentProps;
|
|
248
248
|
|
|
249
|
-
// src/rules/
|
|
250
|
-
var import_path = __toESM(require("path"), 1);
|
|
249
|
+
// src/rules/enforce-sorted-destructuring.ts
|
|
251
250
|
var import_utils2 = require("@typescript-eslint/utils");
|
|
252
251
|
var createRule2 = import_utils2.ESLintUtils.RuleCreator(
|
|
253
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
252
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
253
|
+
);
|
|
254
|
+
var enforceSortedDestructuring = createRule2({
|
|
255
|
+
name: "enforce-sorted-destructuring",
|
|
256
|
+
meta: {
|
|
257
|
+
type: "suggestion",
|
|
258
|
+
docs: {
|
|
259
|
+
description: "Enforce alphabetical sorting of destructured properties with defaults first"
|
|
260
|
+
},
|
|
261
|
+
schema: [],
|
|
262
|
+
messages: {
|
|
263
|
+
unsortedDestructuring: "Destructured properties should be sorted alphabetically. Properties with defaults should come first, sorted by type (string, number, boolean, object) then alphabetically."
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
defaultOptions: [],
|
|
267
|
+
create(context) {
|
|
268
|
+
function getPropertyName(property) {
|
|
269
|
+
if (property.type === import_utils2.AST_NODE_TYPES.RestElement) {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
if (property.key.type === import_utils2.AST_NODE_TYPES.Identifier) {
|
|
273
|
+
return property.key.name;
|
|
274
|
+
}
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
function hasDefaultValue(property) {
|
|
278
|
+
return property.value.type === import_utils2.AST_NODE_TYPES.AssignmentPattern && Boolean(property.value.right);
|
|
279
|
+
}
|
|
280
|
+
function getDefaultValueType(property) {
|
|
281
|
+
if (!hasDefaultValue(property)) {
|
|
282
|
+
return "none";
|
|
283
|
+
}
|
|
284
|
+
const assignmentPattern = property.value;
|
|
285
|
+
const { right } = assignmentPattern;
|
|
286
|
+
if (!right) {
|
|
287
|
+
return "none";
|
|
288
|
+
}
|
|
289
|
+
switch (right.type) {
|
|
290
|
+
case import_utils2.AST_NODE_TYPES.Literal:
|
|
291
|
+
if (typeof right.value === "string") {
|
|
292
|
+
return "string";
|
|
293
|
+
}
|
|
294
|
+
if (typeof right.value === "number") {
|
|
295
|
+
return "number";
|
|
296
|
+
}
|
|
297
|
+
if (typeof right.value === "boolean") {
|
|
298
|
+
return "boolean";
|
|
299
|
+
}
|
|
300
|
+
return "other";
|
|
301
|
+
case import_utils2.AST_NODE_TYPES.TemplateLiteral:
|
|
302
|
+
return "string";
|
|
303
|
+
case import_utils2.AST_NODE_TYPES.ObjectExpression:
|
|
304
|
+
case import_utils2.AST_NODE_TYPES.ArrayExpression:
|
|
305
|
+
return "object";
|
|
306
|
+
default:
|
|
307
|
+
return "other";
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function getTypeSortOrder(type) {
|
|
311
|
+
const order = {
|
|
312
|
+
string: 0,
|
|
313
|
+
number: 1,
|
|
314
|
+
boolean: 2,
|
|
315
|
+
object: 3,
|
|
316
|
+
other: 4,
|
|
317
|
+
none: 5
|
|
318
|
+
};
|
|
319
|
+
return order[type] ?? 5;
|
|
320
|
+
}
|
|
321
|
+
function checkVariableDeclarator(node) {
|
|
322
|
+
if (node.id.type !== import_utils2.AST_NODE_TYPES.ObjectPattern) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const { properties } = node.id;
|
|
326
|
+
if (properties.length < 2) {
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
const propertyInfo = properties.map((prop) => {
|
|
330
|
+
if (prop.type === import_utils2.AST_NODE_TYPES.RestElement) {
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
return {
|
|
334
|
+
property: prop,
|
|
335
|
+
name: getPropertyName(prop),
|
|
336
|
+
hasDefault: hasDefaultValue(prop),
|
|
337
|
+
defaultType: getDefaultValueType(prop)
|
|
338
|
+
};
|
|
339
|
+
}).filter((info) => info !== null && info.name !== null);
|
|
340
|
+
const sorted = [...propertyInfo].sort((a, b) => {
|
|
341
|
+
if (a.hasDefault && !b.hasDefault) {
|
|
342
|
+
return -1;
|
|
343
|
+
}
|
|
344
|
+
if (!a.hasDefault && b.hasDefault) {
|
|
345
|
+
return 1;
|
|
346
|
+
}
|
|
347
|
+
if (a.hasDefault && b.hasDefault) {
|
|
348
|
+
const typeComparison = getTypeSortOrder(a.defaultType) - getTypeSortOrder(b.defaultType);
|
|
349
|
+
if (typeComparison !== 0) {
|
|
350
|
+
return typeComparison;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return a.name.localeCompare(b.name);
|
|
354
|
+
});
|
|
355
|
+
const isSorted = propertyInfo.every((info, index) => info.name === sorted[index].name);
|
|
356
|
+
if (!isSorted) {
|
|
357
|
+
context.report({
|
|
358
|
+
node: node.id,
|
|
359
|
+
messageId: "unsortedDestructuring"
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return {
|
|
364
|
+
VariableDeclarator: checkVariableDeclarator
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
var enforce_sorted_destructuring_default = enforceSortedDestructuring;
|
|
369
|
+
|
|
370
|
+
// src/rules/file-kebab-case.ts
|
|
371
|
+
var import_path = __toESM(require("path"), 1);
|
|
372
|
+
var import_utils3 = require("@typescript-eslint/utils");
|
|
373
|
+
var createRule3 = import_utils3.ESLintUtils.RuleCreator(
|
|
374
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
254
375
|
);
|
|
255
376
|
var isKebabCase = (str) => {
|
|
256
377
|
if (/\.(config|rc|setup|spec|test)$/.test(str) || /^[a-z0-9]+(?:-[a-z0-9]+)*\.[a-z0-9]+(?:-[a-z0-9]+)*$/.test(str)) {
|
|
@@ -258,7 +379,7 @@ var isKebabCase = (str) => {
|
|
|
258
379
|
}
|
|
259
380
|
return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(str);
|
|
260
381
|
};
|
|
261
|
-
var fileKebabCase =
|
|
382
|
+
var fileKebabCase = createRule3({
|
|
262
383
|
name: "file-kebab-case",
|
|
263
384
|
meta: {
|
|
264
385
|
type: "problem",
|
|
@@ -279,8 +400,8 @@ var fileKebabCase = createRule2({
|
|
|
279
400
|
if (ext !== ".ts" && ext !== ".js") {
|
|
280
401
|
return;
|
|
281
402
|
}
|
|
282
|
-
const
|
|
283
|
-
if (!isKebabCase(
|
|
403
|
+
const basename2 = import_path.default.basename(filename, ext);
|
|
404
|
+
if (!isKebabCase(basename2)) {
|
|
284
405
|
context.report({
|
|
285
406
|
loc: { line: 1, column: 0 },
|
|
286
407
|
messageId: "fileKebabCase"
|
|
@@ -294,12 +415,12 @@ var file_kebab_case_default = fileKebabCase;
|
|
|
294
415
|
|
|
295
416
|
// src/rules/jsx-pascal-case.ts
|
|
296
417
|
var import_path2 = __toESM(require("path"), 1);
|
|
297
|
-
var
|
|
298
|
-
var
|
|
299
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
418
|
+
var import_utils4 = require("@typescript-eslint/utils");
|
|
419
|
+
var createRule4 = import_utils4.ESLintUtils.RuleCreator(
|
|
420
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
300
421
|
);
|
|
301
422
|
var isPascalCase = (str) => /^[A-Z][a-zA-Z0-9]*$/.test(str) && !/^[A-Z]+$/.test(str);
|
|
302
|
-
var jsxPascalCase =
|
|
423
|
+
var jsxPascalCase = createRule4({
|
|
303
424
|
name: "jsx-pascal-case",
|
|
304
425
|
meta: {
|
|
305
426
|
type: "problem",
|
|
@@ -320,8 +441,8 @@ var jsxPascalCase = createRule3({
|
|
|
320
441
|
if (ext !== ".jsx" && ext !== ".tsx") {
|
|
321
442
|
return;
|
|
322
443
|
}
|
|
323
|
-
const
|
|
324
|
-
if (!isPascalCase(
|
|
444
|
+
const basename2 = import_path2.default.basename(filename, ext);
|
|
445
|
+
if (!isPascalCase(basename2)) {
|
|
325
446
|
context.report({
|
|
326
447
|
loc: { line: 1, column: 0 },
|
|
327
448
|
messageId: "jsxPascalCase"
|
|
@@ -333,13 +454,84 @@ var jsxPascalCase = createRule3({
|
|
|
333
454
|
});
|
|
334
455
|
var jsx_pascal_case_default = jsxPascalCase;
|
|
335
456
|
|
|
457
|
+
// src/rules/jsx-no-variable-in-callback.ts
|
|
458
|
+
var import_utils5 = require("@typescript-eslint/utils");
|
|
459
|
+
var createRule5 = import_utils5.ESLintUtils.RuleCreator(
|
|
460
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
461
|
+
);
|
|
462
|
+
var jsxNoVariableInCallback = createRule5({
|
|
463
|
+
name: "jsx-no-variable-in-callback",
|
|
464
|
+
meta: {
|
|
465
|
+
type: "suggestion",
|
|
466
|
+
docs: {
|
|
467
|
+
description: "Disallow variable declarations inside callback functions within JSX"
|
|
468
|
+
},
|
|
469
|
+
schema: [],
|
|
470
|
+
messages: {
|
|
471
|
+
noVariableInCallback: "Variable declarations should not be inside callback functions within JSX. Extract the logic to a separate function outside the JSX."
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
defaultOptions: [],
|
|
475
|
+
create(context) {
|
|
476
|
+
function isInsideJSX(node) {
|
|
477
|
+
let current = node.parent;
|
|
478
|
+
while (current) {
|
|
479
|
+
if (current.type === import_utils5.AST_NODE_TYPES.JSXElement || current.type === import_utils5.AST_NODE_TYPES.JSXFragment) {
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
current = current.parent;
|
|
483
|
+
}
|
|
484
|
+
return false;
|
|
485
|
+
}
|
|
486
|
+
function isCallbackInJSX(node) {
|
|
487
|
+
if (!node.parent) {
|
|
488
|
+
return false;
|
|
489
|
+
}
|
|
490
|
+
if (!isInsideJSX(node)) {
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
if (node.parent.type === import_utils5.AST_NODE_TYPES.CallExpression || node.parent.type === import_utils5.AST_NODE_TYPES.JSXExpressionContainer) {
|
|
494
|
+
return true;
|
|
495
|
+
}
|
|
496
|
+
if (node.parent.type === import_utils5.AST_NODE_TYPES.ArrayExpression && node.parent.parent) {
|
|
497
|
+
if (node.parent.parent.type === import_utils5.AST_NODE_TYPES.CallExpression || node.parent.parent.type === import_utils5.AST_NODE_TYPES.JSXExpressionContainer) {
|
|
498
|
+
return true;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
return false;
|
|
502
|
+
}
|
|
503
|
+
function checkFunctionBody(node) {
|
|
504
|
+
if (!isCallbackInJSX(node)) {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
const { body } = node;
|
|
508
|
+
if (body.type !== import_utils5.AST_NODE_TYPES.BlockStatement) {
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
body.body.forEach((statement) => {
|
|
512
|
+
if (statement.type === import_utils5.AST_NODE_TYPES.VariableDeclaration) {
|
|
513
|
+
context.report({
|
|
514
|
+
node: statement,
|
|
515
|
+
messageId: "noVariableInCallback"
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
return {
|
|
521
|
+
ArrowFunctionExpression: checkFunctionBody,
|
|
522
|
+
FunctionExpression: checkFunctionBody
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
var jsx_no_variable_in_callback_default = jsxNoVariableInCallback;
|
|
527
|
+
|
|
336
528
|
// src/rules/md-filename-case-restriction.ts
|
|
337
529
|
var import_path3 = __toESM(require("path"), 1);
|
|
338
|
-
var
|
|
339
|
-
var
|
|
340
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
530
|
+
var import_utils6 = require("@typescript-eslint/utils");
|
|
531
|
+
var createRule6 = import_utils6.ESLintUtils.RuleCreator(
|
|
532
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
341
533
|
);
|
|
342
|
-
var mdFilenameCaseRestriction =
|
|
534
|
+
var mdFilenameCaseRestriction = createRule6({
|
|
343
535
|
name: "md-filename-case-restriction",
|
|
344
536
|
meta: {
|
|
345
537
|
type: "problem",
|
|
@@ -359,18 +551,18 @@ var mdFilenameCaseRestriction = createRule4({
|
|
|
359
551
|
if (!filename.endsWith(".md")) {
|
|
360
552
|
return;
|
|
361
553
|
}
|
|
362
|
-
const
|
|
554
|
+
const basename2 = import_path3.default.basename(filename, ".md");
|
|
363
555
|
function isSnakeCase(text) {
|
|
364
556
|
return /^[A-Z][A-Z0-9_]*$/.test(text);
|
|
365
557
|
}
|
|
366
558
|
function isValidCase(text) {
|
|
367
559
|
return isSnakeCase(text);
|
|
368
560
|
}
|
|
369
|
-
if (!isValidCase(
|
|
561
|
+
if (!isValidCase(basename2)) {
|
|
370
562
|
context.report({
|
|
371
563
|
node: context.sourceCode.ast,
|
|
372
564
|
messageId: "invalidFilenameCase",
|
|
373
|
-
data: { filename:
|
|
565
|
+
data: { filename: basename2 }
|
|
374
566
|
});
|
|
375
567
|
}
|
|
376
568
|
}
|
|
@@ -380,11 +572,11 @@ var mdFilenameCaseRestriction = createRule4({
|
|
|
380
572
|
var md_filename_case_restriction_default = mdFilenameCaseRestriction;
|
|
381
573
|
|
|
382
574
|
// src/rules/no-complex-inline-return.ts
|
|
383
|
-
var
|
|
384
|
-
var
|
|
385
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
575
|
+
var import_utils7 = require("@typescript-eslint/utils");
|
|
576
|
+
var createRule7 = import_utils7.ESLintUtils.RuleCreator(
|
|
577
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
386
578
|
);
|
|
387
|
-
var noComplexInlineReturn =
|
|
579
|
+
var noComplexInlineReturn = createRule7({
|
|
388
580
|
name: "no-complex-inline-return",
|
|
389
581
|
meta: {
|
|
390
582
|
type: "suggestion",
|
|
@@ -400,13 +592,13 @@ var noComplexInlineReturn = createRule5({
|
|
|
400
592
|
create(context) {
|
|
401
593
|
const isComplexExpression = (node) => {
|
|
402
594
|
if (!node) return false;
|
|
403
|
-
if (node.type ===
|
|
595
|
+
if (node.type === import_utils7.AST_NODE_TYPES.ConditionalExpression) {
|
|
404
596
|
return true;
|
|
405
597
|
}
|
|
406
|
-
if (node.type ===
|
|
598
|
+
if (node.type === import_utils7.AST_NODE_TYPES.LogicalExpression) {
|
|
407
599
|
return true;
|
|
408
600
|
}
|
|
409
|
-
if (node.type ===
|
|
601
|
+
if (node.type === import_utils7.AST_NODE_TYPES.NewExpression) {
|
|
410
602
|
return true;
|
|
411
603
|
}
|
|
412
604
|
return false;
|
|
@@ -427,11 +619,11 @@ var no_complex_inline_return_default = noComplexInlineReturn;
|
|
|
427
619
|
|
|
428
620
|
// src/rules/no-emoji.ts
|
|
429
621
|
var import_emoji_regex = __toESM(require("emoji-regex"), 1);
|
|
430
|
-
var
|
|
431
|
-
var
|
|
432
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
622
|
+
var import_utils8 = require("@typescript-eslint/utils");
|
|
623
|
+
var createRule8 = import_utils8.ESLintUtils.RuleCreator(
|
|
624
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
433
625
|
);
|
|
434
|
-
var noEmoji =
|
|
626
|
+
var noEmoji = createRule8({
|
|
435
627
|
name: "no-emoji",
|
|
436
628
|
meta: {
|
|
437
629
|
type: "problem",
|
|
@@ -465,11 +657,11 @@ var noEmoji = createRule6({
|
|
|
465
657
|
var no_emoji_default = noEmoji;
|
|
466
658
|
|
|
467
659
|
// src/rules/no-env-fallback.ts
|
|
468
|
-
var
|
|
469
|
-
var
|
|
470
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
660
|
+
var import_utils9 = require("@typescript-eslint/utils");
|
|
661
|
+
var createRule9 = import_utils9.ESLintUtils.RuleCreator(
|
|
662
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
471
663
|
);
|
|
472
|
-
var noEnvFallback =
|
|
664
|
+
var noEnvFallback = createRule9({
|
|
473
665
|
name: "no-env-fallback",
|
|
474
666
|
meta: {
|
|
475
667
|
type: "problem",
|
|
@@ -484,16 +676,16 @@ var noEnvFallback = createRule7({
|
|
|
484
676
|
defaultOptions: [],
|
|
485
677
|
create(context) {
|
|
486
678
|
const isProcessEnvAccess = (node) => {
|
|
487
|
-
if (node.type !==
|
|
679
|
+
if (node.type !== import_utils9.AST_NODE_TYPES.MemberExpression) {
|
|
488
680
|
return false;
|
|
489
681
|
}
|
|
490
682
|
const { object } = node;
|
|
491
|
-
if (object.type !==
|
|
683
|
+
if (object.type !== import_utils9.AST_NODE_TYPES.MemberExpression) {
|
|
492
684
|
return false;
|
|
493
685
|
}
|
|
494
686
|
const processNode = object.object;
|
|
495
687
|
const envNode = object.property;
|
|
496
|
-
return processNode.type ===
|
|
688
|
+
return processNode.type === import_utils9.AST_NODE_TYPES.Identifier && processNode.name === "process" && envNode.type === import_utils9.AST_NODE_TYPES.Identifier && envNode.name === "env";
|
|
497
689
|
};
|
|
498
690
|
return {
|
|
499
691
|
LogicalExpression(node) {
|
|
@@ -518,11 +710,11 @@ var noEnvFallback = createRule7({
|
|
|
518
710
|
var no_env_fallback_default = noEnvFallback;
|
|
519
711
|
|
|
520
712
|
// src/rules/no-explicit-return-type.ts
|
|
521
|
-
var
|
|
522
|
-
var
|
|
523
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
713
|
+
var import_utils10 = require("@typescript-eslint/utils");
|
|
714
|
+
var createRule10 = import_utils10.ESLintUtils.RuleCreator(
|
|
715
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
524
716
|
);
|
|
525
|
-
var noExplicitReturnType =
|
|
717
|
+
var noExplicitReturnType = createRule10({
|
|
526
718
|
name: "no-explicit-return-type",
|
|
527
719
|
meta: {
|
|
528
720
|
type: "suggestion",
|
|
@@ -561,12 +753,97 @@ var noExplicitReturnType = createRule8({
|
|
|
561
753
|
});
|
|
562
754
|
var no_explicit_return_type_default = noExplicitReturnType;
|
|
563
755
|
|
|
756
|
+
// src/rules/jsx-no-non-component-function.ts
|
|
757
|
+
var import_utils12 = require("@typescript-eslint/utils");
|
|
758
|
+
|
|
759
|
+
// src/utils.ts
|
|
760
|
+
var import_node_path = require("path");
|
|
761
|
+
var import_utils11 = require("@typescript-eslint/utils");
|
|
762
|
+
var getFileExtension = (filename) => (0, import_node_path.extname)(filename).slice(1);
|
|
763
|
+
|
|
764
|
+
// src/rules/jsx-no-non-component-function.ts
|
|
765
|
+
var createRule11 = import_utils12.ESLintUtils.RuleCreator(
|
|
766
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
767
|
+
);
|
|
768
|
+
var jsxNoNonComponentFunction = createRule11({
|
|
769
|
+
name: "jsx-no-non-component-function",
|
|
770
|
+
meta: {
|
|
771
|
+
type: "problem",
|
|
772
|
+
docs: {
|
|
773
|
+
description: "Disallow non-component functions defined at top level in .tsx and .jsx files"
|
|
774
|
+
},
|
|
775
|
+
schema: [],
|
|
776
|
+
messages: {
|
|
777
|
+
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."
|
|
778
|
+
}
|
|
779
|
+
},
|
|
780
|
+
defaultOptions: [],
|
|
781
|
+
create(context) {
|
|
782
|
+
const { filename } = context;
|
|
783
|
+
const extension = getFileExtension(filename);
|
|
784
|
+
if (extension !== "tsx" && extension !== "jsx") {
|
|
785
|
+
return {};
|
|
786
|
+
}
|
|
787
|
+
function isReactComponent(node) {
|
|
788
|
+
const functionName = node.type === import_utils12.AST_NODE_TYPES.FunctionDeclaration && node.id ? node.id.name : null;
|
|
789
|
+
if (functionName && /^[A-Z]/.test(functionName)) {
|
|
790
|
+
return true;
|
|
791
|
+
}
|
|
792
|
+
if (node.returnType?.typeAnnotation) {
|
|
793
|
+
const returnTypeNode = node.returnType.typeAnnotation;
|
|
794
|
+
if (returnTypeNode.type === import_utils12.AST_NODE_TYPES.TSTypeReference && returnTypeNode.typeName.type === import_utils12.AST_NODE_TYPES.Identifier) {
|
|
795
|
+
const typeName = returnTypeNode.typeName.name;
|
|
796
|
+
if (typeName === "JSX" || typeName === "ReactElement" || typeName === "ReactNode") {
|
|
797
|
+
return true;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
return false;
|
|
802
|
+
}
|
|
803
|
+
function checkTopLevelFunction(node, declaratorNode) {
|
|
804
|
+
if (isReactComponent(node)) {
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
const { parent } = node;
|
|
808
|
+
if (!parent) {
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
if (parent.type === import_utils12.AST_NODE_TYPES.ExportDefaultDeclaration || parent.type === import_utils12.AST_NODE_TYPES.ExportNamedDeclaration) {
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
if (declaratorNode?.parent?.parent?.type === import_utils12.AST_NODE_TYPES.ExportNamedDeclaration) {
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
if (declaratorNode?.id.type === import_utils12.AST_NODE_TYPES.Identifier) {
|
|
818
|
+
const varName = declaratorNode.id.name;
|
|
819
|
+
if (/^[A-Z]/.test(varName)) {
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
context.report({
|
|
824
|
+
node: declaratorNode || node,
|
|
825
|
+
messageId: "noTopLevelFunction"
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
return {
|
|
829
|
+
"Program > VariableDeclaration > VariableDeclarator > ArrowFunctionExpression": function checkArrowFunction(node) {
|
|
830
|
+
const declarator = node.parent;
|
|
831
|
+
checkTopLevelFunction(node, declarator);
|
|
832
|
+
},
|
|
833
|
+
"Program > FunctionDeclaration": function checkFunctionDeclaration(node) {
|
|
834
|
+
checkTopLevelFunction(node);
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
});
|
|
839
|
+
var jsx_no_non_component_function_default = jsxNoNonComponentFunction;
|
|
840
|
+
|
|
564
841
|
// src/rules/no-logic-in-params.ts
|
|
565
|
-
var
|
|
566
|
-
var
|
|
567
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
842
|
+
var import_utils14 = require("@typescript-eslint/utils");
|
|
843
|
+
var createRule12 = import_utils14.ESLintUtils.RuleCreator(
|
|
844
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
568
845
|
);
|
|
569
|
-
var noLogicInParams =
|
|
846
|
+
var noLogicInParams = createRule12({
|
|
570
847
|
name: "no-logic-in-params",
|
|
571
848
|
meta: {
|
|
572
849
|
type: "suggestion",
|
|
@@ -581,20 +858,20 @@ var noLogicInParams = createRule9({
|
|
|
581
858
|
defaultOptions: [],
|
|
582
859
|
create(context) {
|
|
583
860
|
const isComplexExpression = (node) => {
|
|
584
|
-
if (node.type ===
|
|
861
|
+
if (node.type === import_utils14.AST_NODE_TYPES.SpreadElement) {
|
|
585
862
|
return false;
|
|
586
863
|
}
|
|
587
|
-
if (node.type ===
|
|
864
|
+
if (node.type === import_utils14.AST_NODE_TYPES.ConditionalExpression) {
|
|
588
865
|
return true;
|
|
589
866
|
}
|
|
590
|
-
if (node.type ===
|
|
867
|
+
if (node.type === import_utils14.AST_NODE_TYPES.LogicalExpression) {
|
|
591
868
|
return true;
|
|
592
869
|
}
|
|
593
|
-
if (node.type ===
|
|
870
|
+
if (node.type === import_utils14.AST_NODE_TYPES.BinaryExpression) {
|
|
594
871
|
const logicalOperators = ["==", "===", "!=", "!==", "<", ">", "<=", ">=", "in", "instanceof"];
|
|
595
872
|
return logicalOperators.includes(node.operator);
|
|
596
873
|
}
|
|
597
|
-
if (node.type ===
|
|
874
|
+
if (node.type === import_utils14.AST_NODE_TYPES.UnaryExpression) {
|
|
598
875
|
return node.operator === "!";
|
|
599
876
|
}
|
|
600
877
|
return false;
|
|
@@ -626,11 +903,11 @@ var noLogicInParams = createRule9({
|
|
|
626
903
|
var no_logic_in_params_default = noLogicInParams;
|
|
627
904
|
|
|
628
905
|
// src/rules/prefer-destructuring-params.ts
|
|
629
|
-
var
|
|
630
|
-
var
|
|
631
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
906
|
+
var import_utils15 = require("@typescript-eslint/utils");
|
|
907
|
+
var createRule13 = import_utils15.ESLintUtils.RuleCreator(
|
|
908
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
632
909
|
);
|
|
633
|
-
var preferDestructuringParams =
|
|
910
|
+
var preferDestructuringParams = createRule13({
|
|
634
911
|
name: "prefer-destructuring-params",
|
|
635
912
|
meta: {
|
|
636
913
|
type: "suggestion",
|
|
@@ -646,18 +923,18 @@ var preferDestructuringParams = createRule10({
|
|
|
646
923
|
create(context) {
|
|
647
924
|
const isCallbackFunction = (node) => {
|
|
648
925
|
const { parent } = node;
|
|
649
|
-
return parent?.type ===
|
|
926
|
+
return parent?.type === import_utils15.AST_NODE_TYPES.CallExpression;
|
|
650
927
|
};
|
|
651
928
|
const isDeveloperFunction = (node) => {
|
|
652
|
-
if (node.type ===
|
|
929
|
+
if (node.type === import_utils15.AST_NODE_TYPES.FunctionDeclaration) {
|
|
653
930
|
return true;
|
|
654
931
|
}
|
|
655
|
-
if (node.type ===
|
|
932
|
+
if (node.type === import_utils15.AST_NODE_TYPES.FunctionExpression || node.type === import_utils15.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
656
933
|
if (isCallbackFunction(node)) {
|
|
657
934
|
return false;
|
|
658
935
|
}
|
|
659
936
|
const { parent } = node;
|
|
660
|
-
return parent?.type ===
|
|
937
|
+
return parent?.type === import_utils15.AST_NODE_TYPES.VariableDeclarator || parent?.type === import_utils15.AST_NODE_TYPES.AssignmentExpression || parent?.type === import_utils15.AST_NODE_TYPES.Property || parent?.type === import_utils15.AST_NODE_TYPES.MethodDefinition;
|
|
661
938
|
}
|
|
662
939
|
return false;
|
|
663
940
|
};
|
|
@@ -669,7 +946,7 @@ var preferDestructuringParams = createRule10({
|
|
|
669
946
|
if (!isDeveloperFunction(node)) {
|
|
670
947
|
return;
|
|
671
948
|
}
|
|
672
|
-
if (node.type ===
|
|
949
|
+
if (node.type === import_utils15.AST_NODE_TYPES.FunctionDeclaration && node.id) {
|
|
673
950
|
const functionName = node.id.name;
|
|
674
951
|
if (functionName.startsWith("_") || functionName.includes("$") || /^[A-Z][a-zA-Z]*$/.test(functionName)) {
|
|
675
952
|
return;
|
|
@@ -679,7 +956,7 @@ var preferDestructuringParams = createRule10({
|
|
|
679
956
|
return;
|
|
680
957
|
}
|
|
681
958
|
const hasNonDestructuredParams = node.params.some(
|
|
682
|
-
(param) => param.type !==
|
|
959
|
+
(param) => param.type !== import_utils15.AST_NODE_TYPES.ObjectPattern && param.type !== import_utils15.AST_NODE_TYPES.RestElement
|
|
683
960
|
);
|
|
684
961
|
if (hasNonDestructuredParams) {
|
|
685
962
|
context.report({
|
|
@@ -698,11 +975,11 @@ var preferDestructuringParams = createRule10({
|
|
|
698
975
|
var prefer_destructuring_params_default = preferDestructuringParams;
|
|
699
976
|
|
|
700
977
|
// src/rules/prefer-import-type.ts
|
|
701
|
-
var
|
|
702
|
-
var
|
|
703
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
978
|
+
var import_utils16 = require("@typescript-eslint/utils");
|
|
979
|
+
var createRule14 = import_utils16.ESLintUtils.RuleCreator(
|
|
980
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
704
981
|
);
|
|
705
|
-
var preferImportType =
|
|
982
|
+
var preferImportType = createRule14({
|
|
706
983
|
name: "prefer-import-type",
|
|
707
984
|
meta: {
|
|
708
985
|
type: "suggestion",
|
|
@@ -717,6 +994,81 @@ var preferImportType = createRule11({
|
|
|
717
994
|
},
|
|
718
995
|
defaultOptions: [],
|
|
719
996
|
create(context) {
|
|
997
|
+
function isInTypeContext(node) {
|
|
998
|
+
let current = node;
|
|
999
|
+
while (current) {
|
|
1000
|
+
switch (current.type) {
|
|
1001
|
+
case import_utils16.AST_NODE_TYPES.TSTypeReference:
|
|
1002
|
+
case import_utils16.AST_NODE_TYPES.TSTypeAnnotation:
|
|
1003
|
+
case import_utils16.AST_NODE_TYPES.TSTypeParameterInstantiation:
|
|
1004
|
+
case import_utils16.AST_NODE_TYPES.TSInterfaceHeritage:
|
|
1005
|
+
case import_utils16.AST_NODE_TYPES.TSClassImplements:
|
|
1006
|
+
case import_utils16.AST_NODE_TYPES.TSTypeQuery:
|
|
1007
|
+
case import_utils16.AST_NODE_TYPES.TSTypeAssertion:
|
|
1008
|
+
case import_utils16.AST_NODE_TYPES.TSAsExpression:
|
|
1009
|
+
case import_utils16.AST_NODE_TYPES.TSSatisfiesExpression:
|
|
1010
|
+
case import_utils16.AST_NODE_TYPES.TSTypeAliasDeclaration:
|
|
1011
|
+
case import_utils16.AST_NODE_TYPES.TSInterfaceDeclaration:
|
|
1012
|
+
case import_utils16.AST_NODE_TYPES.TSTypeParameter:
|
|
1013
|
+
case import_utils16.AST_NODE_TYPES.TSQualifiedName:
|
|
1014
|
+
return true;
|
|
1015
|
+
case import_utils16.AST_NODE_TYPES.MemberExpression:
|
|
1016
|
+
case import_utils16.AST_NODE_TYPES.Identifier:
|
|
1017
|
+
current = current.parent;
|
|
1018
|
+
break;
|
|
1019
|
+
default:
|
|
1020
|
+
return false;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
return false;
|
|
1024
|
+
}
|
|
1025
|
+
function isUsedAsValue(localName, scope) {
|
|
1026
|
+
const variable = scope.set.get(localName);
|
|
1027
|
+
if (!variable) {
|
|
1028
|
+
return false;
|
|
1029
|
+
}
|
|
1030
|
+
if (variable.references.length === 0) {
|
|
1031
|
+
return false;
|
|
1032
|
+
}
|
|
1033
|
+
return variable.references.some((ref) => {
|
|
1034
|
+
if (ref.isWrite()) {
|
|
1035
|
+
return false;
|
|
1036
|
+
}
|
|
1037
|
+
const { identifier } = ref;
|
|
1038
|
+
const { parent } = identifier;
|
|
1039
|
+
if (!parent) {
|
|
1040
|
+
return false;
|
|
1041
|
+
}
|
|
1042
|
+
if (isInTypeContext(parent)) {
|
|
1043
|
+
return false;
|
|
1044
|
+
}
|
|
1045
|
+
switch (parent.type) {
|
|
1046
|
+
case import_utils16.AST_NODE_TYPES.CallExpression:
|
|
1047
|
+
case import_utils16.AST_NODE_TYPES.NewExpression:
|
|
1048
|
+
case import_utils16.AST_NODE_TYPES.JSXOpeningElement:
|
|
1049
|
+
case import_utils16.AST_NODE_TYPES.JSXClosingElement:
|
|
1050
|
+
case import_utils16.AST_NODE_TYPES.MemberExpression:
|
|
1051
|
+
case import_utils16.AST_NODE_TYPES.VariableDeclarator:
|
|
1052
|
+
case import_utils16.AST_NODE_TYPES.TaggedTemplateExpression:
|
|
1053
|
+
case import_utils16.AST_NODE_TYPES.SpreadElement:
|
|
1054
|
+
case import_utils16.AST_NODE_TYPES.ExportSpecifier:
|
|
1055
|
+
case import_utils16.AST_NODE_TYPES.ArrayExpression:
|
|
1056
|
+
case import_utils16.AST_NODE_TYPES.ObjectExpression:
|
|
1057
|
+
case import_utils16.AST_NODE_TYPES.BinaryExpression:
|
|
1058
|
+
case import_utils16.AST_NODE_TYPES.LogicalExpression:
|
|
1059
|
+
case import_utils16.AST_NODE_TYPES.UnaryExpression:
|
|
1060
|
+
case import_utils16.AST_NODE_TYPES.ReturnStatement:
|
|
1061
|
+
case import_utils16.AST_NODE_TYPES.ArrowFunctionExpression:
|
|
1062
|
+
case import_utils16.AST_NODE_TYPES.ConditionalExpression:
|
|
1063
|
+
case import_utils16.AST_NODE_TYPES.AwaitExpression:
|
|
1064
|
+
case import_utils16.AST_NODE_TYPES.YieldExpression:
|
|
1065
|
+
case import_utils16.AST_NODE_TYPES.Property:
|
|
1066
|
+
return true;
|
|
1067
|
+
default:
|
|
1068
|
+
return false;
|
|
1069
|
+
}
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
720
1072
|
function checkImportDeclaration(node) {
|
|
721
1073
|
if (node.importKind === "type") {
|
|
722
1074
|
return;
|
|
@@ -732,19 +1084,17 @@ var preferImportType = createRule11({
|
|
|
732
1084
|
if (isRuntimeImport) {
|
|
733
1085
|
return;
|
|
734
1086
|
}
|
|
1087
|
+
const scope = context.sourceCode.getScope(node);
|
|
735
1088
|
const isTypeOnlyImport = node.specifiers.every((specifier) => {
|
|
736
|
-
if (specifier.type ===
|
|
1089
|
+
if (specifier.type === import_utils16.AST_NODE_TYPES.ImportDefaultSpecifier) {
|
|
737
1090
|
return false;
|
|
738
1091
|
}
|
|
739
|
-
if (specifier.type ===
|
|
1092
|
+
if (specifier.type === import_utils16.AST_NODE_TYPES.ImportNamespaceSpecifier) {
|
|
740
1093
|
return false;
|
|
741
1094
|
}
|
|
742
|
-
if (specifier.type ===
|
|
743
|
-
const
|
|
744
|
-
|
|
745
|
-
importedName
|
|
746
|
-
) || importedName.endsWith("Type") || importedName.endsWith("Interface") || importedName.endsWith("Props");
|
|
747
|
-
return isKnownTypeOnly;
|
|
1095
|
+
if (specifier.type === import_utils16.AST_NODE_TYPES.ImportSpecifier) {
|
|
1096
|
+
const localName = specifier.local.name;
|
|
1097
|
+
return !isUsedAsValue(localName, scope);
|
|
748
1098
|
}
|
|
749
1099
|
return false;
|
|
750
1100
|
});
|
|
@@ -768,11 +1118,11 @@ var preferImportType = createRule11({
|
|
|
768
1118
|
var prefer_import_type_default = preferImportType;
|
|
769
1119
|
|
|
770
1120
|
// src/rules/prefer-interface-over-inline-types.ts
|
|
771
|
-
var
|
|
772
|
-
var
|
|
773
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
1121
|
+
var import_utils17 = require("@typescript-eslint/utils");
|
|
1122
|
+
var createRule15 = import_utils17.ESLintUtils.RuleCreator(
|
|
1123
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
774
1124
|
);
|
|
775
|
-
var preferInterfaceOverInlineTypes =
|
|
1125
|
+
var preferInterfaceOverInlineTypes = createRule15({
|
|
776
1126
|
name: "prefer-interface-over-inline-types",
|
|
777
1127
|
meta: {
|
|
778
1128
|
type: "suggestion",
|
|
@@ -788,54 +1138,54 @@ var preferInterfaceOverInlineTypes = createRule12({
|
|
|
788
1138
|
defaultOptions: [],
|
|
789
1139
|
create(context) {
|
|
790
1140
|
function hasJSXInConditional(node) {
|
|
791
|
-
return node.consequent.type ===
|
|
1141
|
+
return node.consequent.type === import_utils17.AST_NODE_TYPES.JSXElement || node.consequent.type === import_utils17.AST_NODE_TYPES.JSXFragment || node.alternate.type === import_utils17.AST_NODE_TYPES.JSXElement || node.alternate.type === import_utils17.AST_NODE_TYPES.JSXFragment;
|
|
792
1142
|
}
|
|
793
1143
|
function hasJSXInLogical(node) {
|
|
794
|
-
return node.right.type ===
|
|
1144
|
+
return node.right.type === import_utils17.AST_NODE_TYPES.JSXElement || node.right.type === import_utils17.AST_NODE_TYPES.JSXFragment;
|
|
795
1145
|
}
|
|
796
1146
|
function hasJSXReturn(block) {
|
|
797
1147
|
return block.body.some((stmt) => {
|
|
798
|
-
if (stmt.type ===
|
|
799
|
-
return stmt.argument.type ===
|
|
1148
|
+
if (stmt.type === import_utils17.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
|
|
1149
|
+
return stmt.argument.type === import_utils17.AST_NODE_TYPES.JSXElement || stmt.argument.type === import_utils17.AST_NODE_TYPES.JSXFragment || stmt.argument.type === import_utils17.AST_NODE_TYPES.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === import_utils17.AST_NODE_TYPES.LogicalExpression && hasJSXInLogical(stmt.argument);
|
|
800
1150
|
}
|
|
801
1151
|
return false;
|
|
802
1152
|
});
|
|
803
1153
|
}
|
|
804
1154
|
function isReactComponent(node) {
|
|
805
|
-
if (node.type ===
|
|
806
|
-
if (node.body.type ===
|
|
1155
|
+
if (node.type === import_utils17.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
1156
|
+
if (node.body.type === import_utils17.AST_NODE_TYPES.JSXElement || node.body.type === import_utils17.AST_NODE_TYPES.JSXFragment) {
|
|
807
1157
|
return true;
|
|
808
1158
|
}
|
|
809
|
-
if (node.body.type ===
|
|
1159
|
+
if (node.body.type === import_utils17.AST_NODE_TYPES.BlockStatement) {
|
|
810
1160
|
return hasJSXReturn(node.body);
|
|
811
1161
|
}
|
|
812
|
-
} else if (node.type ===
|
|
813
|
-
if (node.body && node.body.type ===
|
|
1162
|
+
} else if (node.type === import_utils17.AST_NODE_TYPES.FunctionExpression || node.type === import_utils17.AST_NODE_TYPES.FunctionDeclaration) {
|
|
1163
|
+
if (node.body && node.body.type === import_utils17.AST_NODE_TYPES.BlockStatement) {
|
|
814
1164
|
return hasJSXReturn(node.body);
|
|
815
1165
|
}
|
|
816
1166
|
}
|
|
817
1167
|
return false;
|
|
818
1168
|
}
|
|
819
1169
|
function isInlineTypeAnnotation(node) {
|
|
820
|
-
if (node.type ===
|
|
1170
|
+
if (node.type === import_utils17.AST_NODE_TYPES.TSTypeLiteral) {
|
|
821
1171
|
return true;
|
|
822
1172
|
}
|
|
823
|
-
if (node.type ===
|
|
824
|
-
return node.typeArguments.params.some((param) => param.type ===
|
|
1173
|
+
if (node.type === import_utils17.AST_NODE_TYPES.TSTypeReference && node.typeArguments) {
|
|
1174
|
+
return node.typeArguments.params.some((param) => param.type === import_utils17.AST_NODE_TYPES.TSTypeLiteral);
|
|
825
1175
|
}
|
|
826
|
-
if (node.type ===
|
|
1176
|
+
if (node.type === import_utils17.AST_NODE_TYPES.TSUnionType) {
|
|
827
1177
|
return node.types.some((type) => isInlineTypeAnnotation(type));
|
|
828
1178
|
}
|
|
829
1179
|
return false;
|
|
830
1180
|
}
|
|
831
1181
|
function hasInlineObjectType(node) {
|
|
832
|
-
if (node.type ===
|
|
1182
|
+
if (node.type === import_utils17.AST_NODE_TYPES.TSTypeLiteral) {
|
|
833
1183
|
return true;
|
|
834
1184
|
}
|
|
835
|
-
if (node.type ===
|
|
836
|
-
return node.typeArguments.params.some((param) => param.type ===
|
|
1185
|
+
if (node.type === import_utils17.AST_NODE_TYPES.TSTypeReference && node.typeArguments) {
|
|
1186
|
+
return node.typeArguments.params.some((param) => param.type === import_utils17.AST_NODE_TYPES.TSTypeLiteral);
|
|
837
1187
|
}
|
|
838
|
-
if (node.type ===
|
|
1188
|
+
if (node.type === import_utils17.AST_NODE_TYPES.TSUnionType) {
|
|
839
1189
|
return node.types.some((type) => hasInlineObjectType(type));
|
|
840
1190
|
}
|
|
841
1191
|
return false;
|
|
@@ -848,7 +1198,7 @@ var preferInterfaceOverInlineTypes = createRule12({
|
|
|
848
1198
|
return;
|
|
849
1199
|
}
|
|
850
1200
|
const param = node.params[0];
|
|
851
|
-
if (param.type ===
|
|
1201
|
+
if (param.type === import_utils17.AST_NODE_TYPES.Identifier && param.typeAnnotation) {
|
|
852
1202
|
const { typeAnnotation } = param.typeAnnotation;
|
|
853
1203
|
if (isInlineTypeAnnotation(typeAnnotation) && hasInlineObjectType(typeAnnotation)) {
|
|
854
1204
|
context.report({
|
|
@@ -867,12 +1217,100 @@ var preferInterfaceOverInlineTypes = createRule12({
|
|
|
867
1217
|
});
|
|
868
1218
|
var prefer_interface_over_inline_types_default = preferInterfaceOverInlineTypes;
|
|
869
1219
|
|
|
1220
|
+
// src/rules/prefer-jsx-template-literals.ts
|
|
1221
|
+
var import_utils18 = require("@typescript-eslint/utils");
|
|
1222
|
+
var createRule16 = import_utils18.ESLintUtils.RuleCreator(
|
|
1223
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
1224
|
+
);
|
|
1225
|
+
var preferJSXTemplateLiterals = createRule16({
|
|
1226
|
+
name: "prefer-jsx-template-literals",
|
|
1227
|
+
meta: {
|
|
1228
|
+
type: "suggestion",
|
|
1229
|
+
docs: {
|
|
1230
|
+
description: "Enforce using template literals instead of mixing text and JSX expressions"
|
|
1231
|
+
},
|
|
1232
|
+
fixable: "code",
|
|
1233
|
+
schema: [],
|
|
1234
|
+
messages: {
|
|
1235
|
+
preferTemplate: "Use template literal instead of mixing text with JSX expressions"
|
|
1236
|
+
}
|
|
1237
|
+
},
|
|
1238
|
+
defaultOptions: [],
|
|
1239
|
+
create(context) {
|
|
1240
|
+
function handleTextBeforeExpression(textNode, exprNode) {
|
|
1241
|
+
const textValue = textNode.value;
|
|
1242
|
+
const trimmedText = textValue.trim();
|
|
1243
|
+
if (!trimmedText) {
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1246
|
+
const hasTextContent = trimmedText.length > 0 && textValue !== trimmedText;
|
|
1247
|
+
const hasNoTrailingSpace = trimmedText.length > 0 && /\S$/.test(textValue);
|
|
1248
|
+
if (!hasTextContent && !hasNoTrailingSpace) {
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
context.report({
|
|
1252
|
+
node: textNode,
|
|
1253
|
+
messageId: "preferTemplate",
|
|
1254
|
+
fix(fixer) {
|
|
1255
|
+
const textPart = textValue.trimEnd();
|
|
1256
|
+
const exprText = context.sourceCode.getText(exprNode.expression);
|
|
1257
|
+
const templateLiteral = `{\`${textPart}\${${exprText}}\`}`;
|
|
1258
|
+
return [fixer.replaceText(textNode, templateLiteral), fixer.remove(exprNode)];
|
|
1259
|
+
}
|
|
1260
|
+
});
|
|
1261
|
+
}
|
|
1262
|
+
function handleExpressionBeforeText(exprNode, textNode) {
|
|
1263
|
+
const textValue = textNode.value;
|
|
1264
|
+
const trimmedText = textValue.trim();
|
|
1265
|
+
if (!trimmedText) {
|
|
1266
|
+
return;
|
|
1267
|
+
}
|
|
1268
|
+
const startsWithNonWhitespace = /^\S/.test(trimmedText);
|
|
1269
|
+
if (!startsWithNonWhitespace) {
|
|
1270
|
+
return;
|
|
1271
|
+
}
|
|
1272
|
+
context.report({
|
|
1273
|
+
node: textNode,
|
|
1274
|
+
messageId: "preferTemplate",
|
|
1275
|
+
fix(fixer) {
|
|
1276
|
+
const exprText = context.sourceCode.getText(exprNode.expression);
|
|
1277
|
+
const textPart = textValue.trim();
|
|
1278
|
+
const templateLiteral = `{\`\${${exprText}}${textPart}\`}`;
|
|
1279
|
+
return [fixer.replaceText(exprNode, templateLiteral), fixer.remove(textNode)];
|
|
1280
|
+
}
|
|
1281
|
+
});
|
|
1282
|
+
}
|
|
1283
|
+
function checkJSXElement(node) {
|
|
1284
|
+
const { children } = node;
|
|
1285
|
+
if (children.length < 2) {
|
|
1286
|
+
return;
|
|
1287
|
+
}
|
|
1288
|
+
for (let i = 0; i < children.length - 1; i += 1) {
|
|
1289
|
+
const child = children[i];
|
|
1290
|
+
const nextChild = children[i + 1];
|
|
1291
|
+
if (!child || !nextChild) {
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
if (child.type === import_utils18.AST_NODE_TYPES.JSXText && nextChild.type === import_utils18.AST_NODE_TYPES.JSXExpressionContainer) {
|
|
1295
|
+
handleTextBeforeExpression(child, nextChild);
|
|
1296
|
+
} else if (child.type === import_utils18.AST_NODE_TYPES.JSXExpressionContainer && nextChild.type === import_utils18.AST_NODE_TYPES.JSXText) {
|
|
1297
|
+
handleExpressionBeforeText(child, nextChild);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
return {
|
|
1302
|
+
JSXElement: checkJSXElement
|
|
1303
|
+
};
|
|
1304
|
+
}
|
|
1305
|
+
});
|
|
1306
|
+
var prefer_jsx_template_literals_default = preferJSXTemplateLiterals;
|
|
1307
|
+
|
|
870
1308
|
// src/rules/prefer-named-param-types.ts
|
|
871
|
-
var
|
|
872
|
-
var
|
|
873
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
1309
|
+
var import_utils19 = require("@typescript-eslint/utils");
|
|
1310
|
+
var createRule17 = import_utils19.ESLintUtils.RuleCreator(
|
|
1311
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
874
1312
|
);
|
|
875
|
-
var preferNamedParamTypes =
|
|
1313
|
+
var preferNamedParamTypes = createRule17({
|
|
876
1314
|
name: "prefer-named-param-types",
|
|
877
1315
|
meta: {
|
|
878
1316
|
type: "suggestion",
|
|
@@ -887,16 +1325,16 @@ var preferNamedParamTypes = createRule13({
|
|
|
887
1325
|
defaultOptions: [],
|
|
888
1326
|
create(context) {
|
|
889
1327
|
function hasInlineObjectType(param) {
|
|
890
|
-
if (param.type ===
|
|
1328
|
+
if (param.type === import_utils19.AST_NODE_TYPES.AssignmentPattern) {
|
|
891
1329
|
return hasInlineObjectType(param.left);
|
|
892
1330
|
}
|
|
893
|
-
if (param.type ===
|
|
894
|
-
if (param.typeAnnotation?.typeAnnotation.type ===
|
|
1331
|
+
if (param.type === import_utils19.AST_NODE_TYPES.ObjectPattern) {
|
|
1332
|
+
if (param.typeAnnotation?.typeAnnotation.type === import_utils19.AST_NODE_TYPES.TSTypeLiteral) {
|
|
895
1333
|
return true;
|
|
896
1334
|
}
|
|
897
1335
|
}
|
|
898
|
-
if (param.type ===
|
|
899
|
-
if (param.typeAnnotation?.typeAnnotation.type ===
|
|
1336
|
+
if (param.type === import_utils19.AST_NODE_TYPES.Identifier) {
|
|
1337
|
+
if (param.typeAnnotation?.typeAnnotation.type === import_utils19.AST_NODE_TYPES.TSTypeLiteral) {
|
|
900
1338
|
return true;
|
|
901
1339
|
}
|
|
902
1340
|
}
|
|
@@ -930,11 +1368,11 @@ var preferNamedParamTypes = createRule13({
|
|
|
930
1368
|
var prefer_named_param_types_default = preferNamedParamTypes;
|
|
931
1369
|
|
|
932
1370
|
// src/rules/prefer-react-import-types.ts
|
|
933
|
-
var
|
|
934
|
-
var
|
|
935
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
1371
|
+
var import_utils20 = require("@typescript-eslint/utils");
|
|
1372
|
+
var createRule18 = import_utils20.ESLintUtils.RuleCreator(
|
|
1373
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
936
1374
|
);
|
|
937
|
-
var preferReactImportTypes =
|
|
1375
|
+
var preferReactImportTypes = createRule18({
|
|
938
1376
|
name: "prefer-react-import-types",
|
|
939
1377
|
meta: {
|
|
940
1378
|
type: "suggestion",
|
|
@@ -1010,7 +1448,7 @@ var preferReactImportTypes = createRule14({
|
|
|
1010
1448
|
]);
|
|
1011
1449
|
const allReactExports = /* @__PURE__ */ new Set([...reactTypes, ...reactRuntimeExports]);
|
|
1012
1450
|
function checkMemberExpression(node) {
|
|
1013
|
-
if (node.object.type ===
|
|
1451
|
+
if (node.object.type === import_utils20.AST_NODE_TYPES.Identifier && node.object.name === "React" && node.property.type === import_utils20.AST_NODE_TYPES.Identifier && allReactExports.has(node.property.name)) {
|
|
1014
1452
|
const typeName = node.property.name;
|
|
1015
1453
|
const isType = reactTypes.has(typeName);
|
|
1016
1454
|
const importStatement = isType ? `import type { ${typeName} } from "react"` : `import { ${typeName} } from "react"`;
|
|
@@ -1027,7 +1465,7 @@ var preferReactImportTypes = createRule14({
|
|
|
1027
1465
|
return {
|
|
1028
1466
|
MemberExpression: checkMemberExpression,
|
|
1029
1467
|
"TSTypeReference > TSQualifiedName": (node) => {
|
|
1030
|
-
if (node.left.type ===
|
|
1468
|
+
if (node.left.type === import_utils20.AST_NODE_TYPES.Identifier && node.left.name === "React" && node.right.type === import_utils20.AST_NODE_TYPES.Identifier && allReactExports.has(node.right.name)) {
|
|
1031
1469
|
const typeName = node.right.name;
|
|
1032
1470
|
const isType = reactTypes.has(typeName);
|
|
1033
1471
|
const importStatement = isType ? `import type { ${typeName} } from "react"` : `import { ${typeName} } from "react"`;
|
|
@@ -1047,11 +1485,11 @@ var preferReactImportTypes = createRule14({
|
|
|
1047
1485
|
var prefer_react_import_types_default = preferReactImportTypes;
|
|
1048
1486
|
|
|
1049
1487
|
// src/rules/react-props-destructure.ts
|
|
1050
|
-
var
|
|
1051
|
-
var
|
|
1052
|
-
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.
|
|
1488
|
+
var import_utils21 = require("@typescript-eslint/utils");
|
|
1489
|
+
var createRule19 = import_utils21.ESLintUtils.RuleCreator(
|
|
1490
|
+
(name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
|
|
1053
1491
|
);
|
|
1054
|
-
var reactPropsDestructure =
|
|
1492
|
+
var reactPropsDestructure = createRule19({
|
|
1055
1493
|
name: "react-props-destructure",
|
|
1056
1494
|
meta: {
|
|
1057
1495
|
type: "suggestion",
|
|
@@ -1067,29 +1505,29 @@ var reactPropsDestructure = createRule15({
|
|
|
1067
1505
|
defaultOptions: [],
|
|
1068
1506
|
create(context) {
|
|
1069
1507
|
function hasJSXInConditional(node) {
|
|
1070
|
-
return node.consequent.type ===
|
|
1508
|
+
return node.consequent.type === import_utils21.AST_NODE_TYPES.JSXElement || node.consequent.type === import_utils21.AST_NODE_TYPES.JSXFragment || node.alternate.type === import_utils21.AST_NODE_TYPES.JSXElement || node.alternate.type === import_utils21.AST_NODE_TYPES.JSXFragment;
|
|
1071
1509
|
}
|
|
1072
1510
|
function hasJSXInLogical(node) {
|
|
1073
|
-
return node.right.type ===
|
|
1511
|
+
return node.right.type === import_utils21.AST_NODE_TYPES.JSXElement || node.right.type === import_utils21.AST_NODE_TYPES.JSXFragment;
|
|
1074
1512
|
}
|
|
1075
1513
|
function hasJSXReturn(block) {
|
|
1076
1514
|
return block.body.some((stmt) => {
|
|
1077
|
-
if (stmt.type ===
|
|
1078
|
-
return stmt.argument.type ===
|
|
1515
|
+
if (stmt.type === import_utils21.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
|
|
1516
|
+
return stmt.argument.type === import_utils21.AST_NODE_TYPES.JSXElement || stmt.argument.type === import_utils21.AST_NODE_TYPES.JSXFragment || stmt.argument.type === import_utils21.AST_NODE_TYPES.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === import_utils21.AST_NODE_TYPES.LogicalExpression && hasJSXInLogical(stmt.argument);
|
|
1079
1517
|
}
|
|
1080
1518
|
return false;
|
|
1081
1519
|
});
|
|
1082
1520
|
}
|
|
1083
1521
|
function isReactComponent(node) {
|
|
1084
|
-
if (node.type ===
|
|
1085
|
-
if (node.body.type ===
|
|
1522
|
+
if (node.type === import_utils21.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
1523
|
+
if (node.body.type === import_utils21.AST_NODE_TYPES.JSXElement || node.body.type === import_utils21.AST_NODE_TYPES.JSXFragment) {
|
|
1086
1524
|
return true;
|
|
1087
1525
|
}
|
|
1088
|
-
if (node.body.type ===
|
|
1526
|
+
if (node.body.type === import_utils21.AST_NODE_TYPES.BlockStatement) {
|
|
1089
1527
|
return hasJSXReturn(node.body);
|
|
1090
1528
|
}
|
|
1091
|
-
} else if (node.type ===
|
|
1092
|
-
if (node.body && node.body.type ===
|
|
1529
|
+
} else if (node.type === import_utils21.AST_NODE_TYPES.FunctionExpression || node.type === import_utils21.AST_NODE_TYPES.FunctionDeclaration) {
|
|
1530
|
+
if (node.body && node.body.type === import_utils21.AST_NODE_TYPES.BlockStatement) {
|
|
1093
1531
|
return hasJSXReturn(node.body);
|
|
1094
1532
|
}
|
|
1095
1533
|
}
|
|
@@ -1103,9 +1541,9 @@ var reactPropsDestructure = createRule15({
|
|
|
1103
1541
|
return;
|
|
1104
1542
|
}
|
|
1105
1543
|
const param = node.params[0];
|
|
1106
|
-
if (param.type ===
|
|
1107
|
-
const properties = param.properties.filter((prop) => prop.type ===
|
|
1108
|
-
if (prop.key.type ===
|
|
1544
|
+
if (param.type === import_utils21.AST_NODE_TYPES.ObjectPattern) {
|
|
1545
|
+
const properties = param.properties.filter((prop) => prop.type === import_utils21.AST_NODE_TYPES.Property).map((prop) => {
|
|
1546
|
+
if (prop.key.type === import_utils21.AST_NODE_TYPES.Identifier) {
|
|
1109
1547
|
return prop.key.name;
|
|
1110
1548
|
}
|
|
1111
1549
|
return null;
|
|
@@ -1138,8 +1576,11 @@ var meta = {
|
|
|
1138
1576
|
};
|
|
1139
1577
|
var rules = {
|
|
1140
1578
|
"enforce-readonly-component-props": enforce_readonly_component_props_default,
|
|
1579
|
+
"enforce-sorted-destructuring": enforce_sorted_destructuring_default,
|
|
1141
1580
|
"file-kebab-case": file_kebab_case_default,
|
|
1142
1581
|
"jsx-pascal-case": jsx_pascal_case_default,
|
|
1582
|
+
"jsx-no-non-component-function": jsx_no_non_component_function_default,
|
|
1583
|
+
"jsx-no-variable-in-callback": jsx_no_variable_in_callback_default,
|
|
1143
1584
|
"md-filename-case-restriction": md_filename_case_restriction_default,
|
|
1144
1585
|
"no-complex-inline-return": no_complex_inline_return_default,
|
|
1145
1586
|
"no-emoji": no_emoji_default,
|
|
@@ -1149,6 +1590,7 @@ var rules = {
|
|
|
1149
1590
|
"prefer-destructuring-params": prefer_destructuring_params_default,
|
|
1150
1591
|
"prefer-import-type": prefer_import_type_default,
|
|
1151
1592
|
"prefer-interface-over-inline-types": prefer_interface_over_inline_types_default,
|
|
1593
|
+
"prefer-jsx-template-literals": prefer_jsx_template_literals_default,
|
|
1152
1594
|
"prefer-named-param-types": prefer_named_param_types_default,
|
|
1153
1595
|
"prefer-react-import-types": prefer_react_import_types_default,
|
|
1154
1596
|
"react-props-destructure": react_props_destructure_default
|
|
@@ -1159,6 +1601,7 @@ var plugin = {
|
|
|
1159
1601
|
};
|
|
1160
1602
|
var baseRules = {
|
|
1161
1603
|
"nextfriday/no-emoji": "warn",
|
|
1604
|
+
"nextfriday/enforce-sorted-destructuring": "warn",
|
|
1162
1605
|
"nextfriday/file-kebab-case": "warn",
|
|
1163
1606
|
"nextfriday/md-filename-case-restriction": "warn",
|
|
1164
1607
|
"nextfriday/prefer-destructuring-params": "warn",
|
|
@@ -1172,6 +1615,7 @@ var baseRules = {
|
|
|
1172
1615
|
};
|
|
1173
1616
|
var baseRecommendedRules = {
|
|
1174
1617
|
"nextfriday/no-emoji": "error",
|
|
1618
|
+
"nextfriday/enforce-sorted-destructuring": "error",
|
|
1175
1619
|
"nextfriday/file-kebab-case": "error",
|
|
1176
1620
|
"nextfriday/md-filename-case-restriction": "error",
|
|
1177
1621
|
"nextfriday/prefer-destructuring-params": "error",
|
|
@@ -1185,13 +1629,19 @@ var baseRecommendedRules = {
|
|
|
1185
1629
|
};
|
|
1186
1630
|
var jsxRules = {
|
|
1187
1631
|
"nextfriday/jsx-pascal-case": "warn",
|
|
1632
|
+
"nextfriday/jsx-no-non-component-function": "warn",
|
|
1633
|
+
"nextfriday/jsx-no-variable-in-callback": "warn",
|
|
1188
1634
|
"nextfriday/prefer-interface-over-inline-types": "warn",
|
|
1635
|
+
"nextfriday/prefer-jsx-template-literals": "warn",
|
|
1189
1636
|
"nextfriday/react-props-destructure": "warn",
|
|
1190
1637
|
"nextfriday/enforce-readonly-component-props": "warn"
|
|
1191
1638
|
};
|
|
1192
1639
|
var jsxRecommendedRules = {
|
|
1193
1640
|
"nextfriday/jsx-pascal-case": "error",
|
|
1641
|
+
"nextfriday/jsx-no-non-component-function": "error",
|
|
1642
|
+
"nextfriday/jsx-no-variable-in-callback": "error",
|
|
1194
1643
|
"nextfriday/prefer-interface-over-inline-types": "error",
|
|
1644
|
+
"nextfriday/prefer-jsx-template-literals": "error",
|
|
1195
1645
|
"nextfriday/react-props-destructure": "error",
|
|
1196
1646
|
"nextfriday/enforce-readonly-component-props": "error"
|
|
1197
1647
|
};
|