eslint-plugin-nextfriday 4.4.0 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -4,10 +4,10 @@ import path from "path";
4
4
  import emojiRegex from "emoji-regex";
5
5
  //#region package.json
6
6
  var name = "eslint-plugin-nextfriday";
7
- var version = "4.4.0";
7
+ var version = "5.0.1";
8
8
  //#endregion
9
9
  //#region src/rules/boolean-naming-prefix.ts
10
- const createRule$31 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
10
+ const createRule$26 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
11
11
  const BOOLEAN_PREFIXES = [
12
12
  "is",
13
13
  "has",
@@ -56,7 +56,7 @@ const hasBooleanTypeAnnotation = (node) => {
56
56
  }
57
57
  return false;
58
58
  };
59
- const booleanNamingPrefix = createRule$31({
59
+ const booleanNamingPrefix = createRule$26({
60
60
  name: "boolean-naming-prefix",
61
61
  meta: {
62
62
  type: "suggestion",
@@ -116,99 +116,6 @@ const booleanNamingPrefix = createRule$31({
116
116
  }
117
117
  });
118
118
  //#endregion
119
- //#region src/rules/enforce-camel-case.ts
120
- const createRule$30 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
121
- const SNAKE_CASE_REGEX$2 = /^[a-z]+_[a-z0-9_]*$/;
122
- const PASCAL_CASE_REGEX = /^[A-Z][a-zA-Z0-9]*$/;
123
- const REACT_WRAPPERS = [
124
- "memo",
125
- "forwardRef",
126
- "lazy"
127
- ];
128
- const returnsJsx$1 = (node) => {
129
- if (node.type === AST_NODE_TYPES.JSXElement || node.type === AST_NODE_TYPES.JSXFragment) return true;
130
- if (node.type === AST_NODE_TYPES.ConditionalExpression) return returnsJsx$1(node.consequent) || returnsJsx$1(node.alternate);
131
- if (node.type === AST_NODE_TYPES.LogicalExpression) return returnsJsx$1(node.left) || returnsJsx$1(node.right);
132
- return false;
133
- };
134
- const bodyReturnsJsx$1 = (body) => {
135
- if (body.type !== AST_NODE_TYPES.BlockStatement) return returnsJsx$1(body);
136
- return body.body.some((stmt) => stmt.type === AST_NODE_TYPES.ReturnStatement && stmt.argument !== null && returnsJsx$1(stmt.argument));
137
- };
138
- const isComponentFunction$1 = (init) => {
139
- if (init.type === AST_NODE_TYPES.ArrowFunctionExpression || init.type === AST_NODE_TYPES.FunctionExpression) return bodyReturnsJsx$1(init.body);
140
- if (init.type === AST_NODE_TYPES.CallExpression) {
141
- const { callee } = init;
142
- if (callee.type === AST_NODE_TYPES.Identifier && REACT_WRAPPERS.includes(callee.name)) return true;
143
- if (callee.type === AST_NODE_TYPES.MemberExpression && callee.object.type === AST_NODE_TYPES.Identifier && callee.object.name === "React" && callee.property.type === AST_NODE_TYPES.Identifier && REACT_WRAPPERS.includes(callee.property.name)) return true;
144
- }
145
- return false;
146
- };
147
- const isGlobalScope$2 = (node) => {
148
- const declaration = node.parent;
149
- if (!declaration || declaration.type !== AST_NODE_TYPES.VariableDeclaration) return false;
150
- const { parent } = declaration;
151
- if (parent.type === AST_NODE_TYPES.Program) return true;
152
- if (parent.type === AST_NODE_TYPES.ExportNamedDeclaration && parent.parent?.type === AST_NODE_TYPES.Program) return true;
153
- return false;
154
- };
155
- const isStaticValue$1 = (init) => {
156
- if (init.type === AST_NODE_TYPES.Literal) return true;
157
- if (init.type === AST_NODE_TYPES.UnaryExpression && init.argument.type === AST_NODE_TYPES.Literal) return true;
158
- if (init.type === AST_NODE_TYPES.TemplateLiteral && init.expressions.length === 0) return true;
159
- if (init.type === AST_NODE_TYPES.ArrayExpression) return init.elements.every((el) => el !== null && el.type !== AST_NODE_TYPES.SpreadElement && isStaticValue$1(el));
160
- if (init.type === AST_NODE_TYPES.ObjectExpression) return init.properties.every((prop) => prop.type === AST_NODE_TYPES.Property && isStaticValue$1(prop.value));
161
- if (init.type === AST_NODE_TYPES.TSAsExpression && init.typeAnnotation.type === AST_NODE_TYPES.TSTypeReference && init.typeAnnotation.typeName.type === AST_NODE_TYPES.Identifier && init.typeAnnotation.typeName.name === "const") return true;
162
- return false;
163
- };
164
- const enforceCamelCase = createRule$30({
165
- name: "enforce-camel-case",
166
- meta: {
167
- type: "suggestion",
168
- docs: { description: "Enforce camelCase for variables and functions, ban snake_case, and restrict PascalCase to React components" },
169
- messages: {
170
- noSnakeCase: "Variable '{{ name }}' should not use snake_case. Use camelCase instead.",
171
- pascalCaseReserved: "Variable '{{ name }}' uses PascalCase but is not a React component. PascalCase is reserved for components."
172
- },
173
- schema: []
174
- },
175
- defaultOptions: [],
176
- create(context) {
177
- return {
178
- VariableDeclarator(node) {
179
- if (node.id.type !== AST_NODE_TYPES.Identifier) return;
180
- const { name } = node.id;
181
- if (SNAKE_CASE_REGEX$2.test(name)) {
182
- if (node.parent.kind === "const" && isGlobalScope$2(node) && node.init && isStaticValue$1(node.init)) return;
183
- context.report({
184
- node: node.id,
185
- messageId: "noSnakeCase",
186
- data: { name }
187
- });
188
- return;
189
- }
190
- if (!node.init || !PASCAL_CASE_REGEX.test(name)) return;
191
- if (isComponentFunction$1(node.init)) return;
192
- if (node.init.type !== AST_NODE_TYPES.ArrowFunctionExpression && node.init.type !== AST_NODE_TYPES.FunctionExpression && node.init.type !== AST_NODE_TYPES.CallExpression) return;
193
- context.report({
194
- node: node.id,
195
- messageId: "pascalCaseReserved",
196
- data: { name }
197
- });
198
- },
199
- FunctionDeclaration(node) {
200
- if (!node.id) return;
201
- const { name } = node.id;
202
- if (SNAKE_CASE_REGEX$2.test(name)) context.report({
203
- node: node.id,
204
- messageId: "noSnakeCase",
205
- data: { name }
206
- });
207
- }
208
- };
209
- }
210
- });
211
- //#endregion
212
119
  //#region src/utils.ts
213
120
  const getFileExtension = (filename) => extname(filename).slice(1);
214
121
  const getBaseName = (filename) => basename(filename, extname(filename));
@@ -222,9 +129,9 @@ const isConfigFile = (filename) => {
222
129
  };
223
130
  //#endregion
224
131
  //#region src/rules/enforce-constant-case.ts
225
- const createRule$29 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
226
- const SCREAMING_SNAKE_CASE_REGEX$2 = /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/;
227
- const SNAKE_CASE_REGEX$1 = /^[a-z]+_[a-z0-9_]*$/;
132
+ const createRule$25 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
133
+ const SCREAMING_SNAKE_CASE_REGEX$1 = /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/;
134
+ const SNAKE_CASE_REGEX = /^[a-z]+_[a-z0-9_]*$/;
228
135
  const toScreamingSnakeCase = (str) => str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toUpperCase();
229
136
  const isMagicLiteral = (init) => {
230
137
  if (init.type === AST_NODE_TYPES.Literal) return typeof init.value === "string" || typeof init.value === "number";
@@ -240,7 +147,7 @@ const isGlobalScope$1 = (node) => {
240
147
  if (parent.type === AST_NODE_TYPES.ExportNamedDeclaration && parent.parent?.type === AST_NODE_TYPES.Program) return true;
241
148
  return false;
242
149
  };
243
- const enforceConstantCase = createRule$29({
150
+ const enforceConstantCase = createRule$25({
244
151
  name: "enforce-constant-case",
245
152
  meta: {
246
153
  type: "suggestion",
@@ -260,7 +167,7 @@ const enforceConstantCase = createRule$29({
260
167
  if (declarator.id.type !== AST_NODE_TYPES.Identifier || !declarator.init) return;
261
168
  if (!isMagicLiteral(declarator.init)) return;
262
169
  const { name } = declarator.id;
263
- if (SNAKE_CASE_REGEX$1.test(name)) {
170
+ if (SNAKE_CASE_REGEX.test(name)) {
264
171
  context.report({
265
172
  node: declarator.id,
266
173
  messageId: "noSnakeCase",
@@ -271,7 +178,7 @@ const enforceConstantCase = createRule$29({
271
178
  });
272
179
  return;
273
180
  }
274
- if (!SCREAMING_SNAKE_CASE_REGEX$2.test(name)) context.report({
181
+ if (!SCREAMING_SNAKE_CASE_REGEX$1.test(name)) context.report({
275
182
  node: declarator.id,
276
183
  messageId: "useScreamingSnakeCase",
277
184
  data: {
@@ -363,44 +270,6 @@ const enforceHookNaming = ESLintUtils.RuleCreator((name) => `https://github.com/
363
270
  }
364
271
  });
365
272
  //#endregion
366
- //#region src/rules/enforce-property-case.ts
367
- const createRule$28 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
368
- const SNAKE_CASE_REGEX = /^[a-z]+_[a-z0-9_]*$/;
369
- const SCREAMING_SNAKE_CASE_REGEX$1 = /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/;
370
- const isInsideAsConst = (node) => {
371
- const { parent } = node;
372
- if (parent.type === AST_NODE_TYPES.TSAsExpression && parent.typeAnnotation.type === AST_NODE_TYPES.TSTypeReference && parent.typeAnnotation.typeName.type === AST_NODE_TYPES.Identifier && parent.typeAnnotation.typeName.name === "const") return true;
373
- if (parent.type === AST_NODE_TYPES.ArrayExpression) {
374
- const grandparent = parent.parent;
375
- if (grandparent?.type === AST_NODE_TYPES.TSAsExpression && grandparent.typeAnnotation.type === AST_NODE_TYPES.TSTypeReference && grandparent.typeAnnotation.typeName.type === AST_NODE_TYPES.Identifier && grandparent.typeAnnotation.typeName.name === "const") return true;
376
- }
377
- return false;
378
- };
379
- const enforcePropertyCase = createRule$28({
380
- name: "enforce-property-case",
381
- meta: {
382
- type: "suggestion",
383
- docs: { description: "Enforce camelCase for unquoted object property keys" },
384
- messages: { useCamelCase: "Property '{{ name }}' should use camelCase. Use camelCase for object properties, or wrap in quotes if required by an API." },
385
- schema: []
386
- },
387
- defaultOptions: [],
388
- create(context) {
389
- return { Property(node) {
390
- if (node.parent.type !== AST_NODE_TYPES.ObjectExpression) return;
391
- if (isInsideAsConst(node.parent)) return;
392
- if (node.computed) return;
393
- if (node.key.type !== AST_NODE_TYPES.Identifier) return;
394
- const { name } = node.key;
395
- if (SNAKE_CASE_REGEX.test(name) || SCREAMING_SNAKE_CASE_REGEX$1.test(name)) context.report({
396
- node: node.key,
397
- messageId: "useCamelCase",
398
- data: { name }
399
- });
400
- } };
401
- }
402
- });
403
- //#endregion
404
273
  //#region src/rules/enforce-props-suffix.ts
405
274
  const enforcePropsSuffix = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
406
275
  name: "enforce-props-suffix",
@@ -509,7 +378,7 @@ const enforceReadonlyComponentProps = ESLintUtils.RuleCreator((name) => `https:/
509
378
  });
510
379
  //#endregion
511
380
  //#region src/rules/enforce-render-naming.ts
512
- const createRule$27 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
381
+ const createRule$24 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
513
382
  const ARRAY_RETURNING_METHODS = new Set([
514
383
  "map",
515
384
  "flatMap",
@@ -558,7 +427,7 @@ function isComponentFunction(node) {
558
427
  if (parent?.type === AST_NODE_TYPES.VariableDeclarator && parent.id.type === AST_NODE_TYPES.Identifier && isPascalCase$1(parent.id.name)) return true;
559
428
  return false;
560
429
  }
561
- const enforceRenderNaming = createRule$27({
430
+ const enforceRenderNaming = createRule$24({
562
431
  name: "enforce-render-naming",
563
432
  meta: {
564
433
  type: "problem",
@@ -610,7 +479,7 @@ const enforceRenderNaming = createRule$27({
610
479
  });
611
480
  //#endregion
612
481
  //#region src/rules/enforce-service-naming.ts
613
- const createRule$26 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
482
+ const createRule$23 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
614
483
  const BANNED_PREFIXES = {
615
484
  delete: ["remove", "archive"],
616
485
  do: ["submit", "process"],
@@ -621,7 +490,7 @@ const BANNED_PREFIXES = {
621
490
  "patch"
622
491
  ]
623
492
  };
624
- const enforceServiceNaming = createRule$26({
493
+ const enforceServiceNaming = createRule$23({
625
494
  name: "enforce-service-naming",
626
495
  meta: {
627
496
  type: "suggestion",
@@ -659,7 +528,7 @@ const enforceServiceNaming = createRule$26({
659
528
  });
660
529
  //#endregion
661
530
  //#region src/rules/enforce-test-filename.ts
662
- const createRule$25 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
531
+ const createRule$22 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
663
532
  const TEST_GLOBALS = new Set([
664
533
  "describe",
665
534
  "it",
@@ -669,7 +538,7 @@ const TEST_GLOBALS = new Set([
669
538
  "afterEach",
670
539
  "afterAll"
671
540
  ]);
672
- const enforceTestFilename = createRule$25({
541
+ const enforceTestFilename = createRule$22({
673
542
  name: "enforce-test-filename",
674
543
  meta: {
675
544
  type: "suggestion",
@@ -749,7 +618,7 @@ const enforceSortedDestructuring = ESLintUtils.RuleCreator((name) => `https://gi
749
618
  });
750
619
  //#endregion
751
620
  //#region src/rules/enforce-type-declaration-order.ts
752
- const createRule$24 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
621
+ const createRule$21 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
753
622
  function getTypeDeclarationName(node) {
754
623
  if (node.type === AST_NODE_TYPES.TSInterfaceDeclaration && node.id.type === AST_NODE_TYPES.Identifier) return {
755
624
  name: node.id.name,
@@ -761,7 +630,7 @@ function getTypeDeclarationName(node) {
761
630
  };
762
631
  return null;
763
632
  }
764
- const enforceTypeDeclarationOrder = createRule$24({
633
+ const enforceTypeDeclarationOrder = createRule$21({
765
634
  name: "enforce-type-declaration-order",
766
635
  meta: {
767
636
  type: "suggestion",
@@ -816,7 +685,7 @@ const enforceTypeDeclarationOrder = createRule$24({
816
685
  });
817
686
  //#endregion
818
687
  //#region src/rules/index-export-only.ts
819
- const createRule$23 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
688
+ const createRule$20 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
820
689
  const isIndexFile = (filename) => getBaseName(filename) === "index";
821
690
  const isAllowedExportNamed = (node) => {
822
691
  if (!node.declaration) return true;
@@ -830,12 +699,16 @@ const isAllowedTopLevel = (node) => {
830
699
  case AST_NODE_TYPES.TSTypeAliasDeclaration:
831
700
  case AST_NODE_TYPES.TSInterfaceDeclaration:
832
701
  case AST_NODE_TYPES.TSImportEqualsDeclaration: return true;
702
+ case AST_NODE_TYPES.ExpressionStatement: {
703
+ const { expression } = node;
704
+ return expression.type === AST_NODE_TYPES.Literal && typeof expression.value === "string";
705
+ }
833
706
  case AST_NODE_TYPES.ExportNamedDeclaration: return isAllowedExportNamed(node);
834
707
  case AST_NODE_TYPES.ExportDefaultDeclaration: return isAllowedExportDefault(node);
835
708
  default: return false;
836
709
  }
837
710
  };
838
- const indexExportOnly = createRule$23({
711
+ const indexExportOnly = createRule$20({
839
712
  name: "index-export-only",
840
713
  meta: {
841
714
  type: "suggestion",
@@ -909,7 +782,7 @@ const jsxNewlineBetweenElements = ESLintUtils.RuleCreator((name) => `https://git
909
782
  });
910
783
  //#endregion
911
784
  //#region src/rules/jsx-no-data-array.ts
912
- const createRule$22 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
785
+ const createRule$19 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
913
786
  function isObjectLikeElement(node) {
914
787
  if (!node) return false;
915
788
  if (node.type === AST_NODE_TYPES.ObjectExpression) return true;
@@ -922,7 +795,7 @@ function getArrayInitializer(init) {
922
795
  if (init.type === AST_NODE_TYPES.TSAsExpression || init.type === AST_NODE_TYPES.TSSatisfiesExpression) return getArrayInitializer(init.expression);
923
796
  return null;
924
797
  }
925
- const jsxNoDataArray = createRule$22({
798
+ const jsxNoDataArray = createRule$19({
926
799
  name: "jsx-no-data-array",
927
800
  meta: {
928
801
  type: "problem",
@@ -963,7 +836,7 @@ const jsxNoDataArray = createRule$22({
963
836
  });
964
837
  //#endregion
965
838
  //#region src/rules/jsx-no-data-object.ts
966
- const createRule$21 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
839
+ const createRule$18 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
967
840
  function unwrapAssertion(node) {
968
841
  if (!node) return null;
969
842
  if (node.type === AST_NODE_TYPES.TSAsExpression || node.type === AST_NODE_TYPES.TSSatisfiesExpression) return unwrapAssertion(node.expression);
@@ -993,7 +866,7 @@ function getObjectInitializer(init) {
993
866
  if (unwrapped.type === AST_NODE_TYPES.ObjectExpression) return unwrapped;
994
867
  return null;
995
868
  }
996
- const jsxNoDataObject = createRule$21({
869
+ const jsxNoDataObject = createRule$18({
997
870
  name: "jsx-no-data-object",
998
871
  meta: {
999
872
  type: "problem",
@@ -1046,14 +919,14 @@ const jsxNoInlineObjectProp = ESLintUtils.RuleCreator((name) => `https://github.
1046
919
  });
1047
920
  //#endregion
1048
921
  //#region src/rules/jsx-no-newline-single-line-elements.ts
1049
- const createRule$20 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
922
+ const createRule$17 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1050
923
  function isJSXElementOrFragment(node) {
1051
924
  return node.type === AST_NODE_TYPES.JSXElement || node.type === AST_NODE_TYPES.JSXFragment;
1052
925
  }
1053
926
  function isSingleLine(node) {
1054
927
  return node.loc.start.line === node.loc.end.line;
1055
928
  }
1056
- const jsxNoNewlineSingleLineElements = createRule$20({
929
+ const jsxNoNewlineSingleLineElements = createRule$17({
1057
930
  name: "jsx-no-newline-single-line-elements",
1058
931
  meta: {
1059
932
  type: "layout",
@@ -1152,7 +1025,7 @@ const jsxNoNonComponentFunction = ESLintUtils.RuleCreator((name) => `https://git
1152
1025
  });
1153
1026
  //#endregion
1154
1027
  //#region src/rules/jsx-no-sub-interface.ts
1155
- const createRule$19 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1028
+ const createRule$16 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1156
1029
  const PROPS_WRAPPER_NAMES = new Set([
1157
1030
  "Readonly",
1158
1031
  "Required",
@@ -1184,7 +1057,7 @@ function getDeclarationFromExportWrapper(node) {
1184
1057
  if (node.type === AST_NODE_TYPES.ExportDefaultDeclaration) return node.declaration;
1185
1058
  return node;
1186
1059
  }
1187
- const jsxNoSubInterface = createRule$19({
1060
+ const jsxNoSubInterface = createRule$16({
1188
1061
  name: "jsx-no-sub-interface",
1189
1062
  meta: {
1190
1063
  type: "problem",
@@ -1251,13 +1124,13 @@ const jsxNoSubInterface = createRule$19({
1251
1124
  });
1252
1125
  //#endregion
1253
1126
  //#region src/rules/jsx-no-ternary-null.ts
1254
- const createRule$18 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1127
+ const createRule$15 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1255
1128
  function isNullOrUndefined(node) {
1256
1129
  if (node.type === AST_NODE_TYPES.Literal && node.value === null) return true;
1257
1130
  if (node.type === AST_NODE_TYPES.Identifier && node.name === "undefined") return true;
1258
1131
  return false;
1259
1132
  }
1260
- const jsxNoTernaryNull = createRule$18({
1133
+ const jsxNoTernaryNull = createRule$15({
1261
1134
  name: "jsx-no-ternary-null",
1262
1135
  meta: {
1263
1136
  type: "suggestion",
@@ -1424,7 +1297,7 @@ const jsxSimpleProps = ESLintUtils.RuleCreator((name) => `https://github.com/nex
1424
1297
  });
1425
1298
  //#endregion
1426
1299
  //#region src/rules/jsx-sort-props.ts
1427
- const createRule$17 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1300
+ const createRule$14 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1428
1301
  const TYPE_GROUP = {
1429
1302
  STRING: 1,
1430
1303
  HYPHENATED_STRING: 2,
@@ -1507,7 +1380,7 @@ function getSegments(attributes) {
1507
1380
  if (current.length > 0) result.push(current);
1508
1381
  return result;
1509
1382
  }
1510
- const jsxSortProps = createRule$17({
1383
+ const jsxSortProps = createRule$14({
1511
1384
  name: "jsx-sort-props",
1512
1385
  meta: {
1513
1386
  type: "suggestion",
@@ -1562,7 +1435,7 @@ const jsxSpreadPropsLast = ESLintUtils.RuleCreator((name) => `https://github.com
1562
1435
  });
1563
1436
  //#endregion
1564
1437
  //#region src/rules/newline-after-multiline-block.ts
1565
- const createRule$16 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1438
+ const createRule$13 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1566
1439
  function isImportDeclaration(node) {
1567
1440
  return node.type === AST_NODE_TYPES.ImportDeclaration;
1568
1441
  }
@@ -1587,7 +1460,7 @@ function checkStatements(statements, context) {
1587
1460
  });
1588
1461
  });
1589
1462
  }
1590
- const newlineAfterMultilineBlock = createRule$16({
1463
+ const newlineAfterMultilineBlock = createRule$13({
1591
1464
  name: "newline-after-multiline-block",
1592
1465
  meta: {
1593
1466
  type: "layout",
@@ -1773,12 +1646,12 @@ const noEnvFallback = ESLintUtils.RuleCreator((name) => `https://github.com/next
1773
1646
  });
1774
1647
  //#endregion
1775
1648
  //#region src/rules/no-ghost-wrapper.ts
1776
- const createRule$15 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1649
+ const createRule$12 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1777
1650
  const GHOST_TAGS = new Set(["div", "span"]);
1778
1651
  function isKeyAttribute(attribute) {
1779
1652
  return attribute.type === AST_NODE_TYPES.JSXAttribute && attribute.name.type === AST_NODE_TYPES.JSXIdentifier && attribute.name.name === "key";
1780
1653
  }
1781
- const noGhostWrapper = createRule$15({
1654
+ const noGhostWrapper = createRule$12({
1782
1655
  name: "no-ghost-wrapper",
1783
1656
  meta: {
1784
1657
  type: "problem",
@@ -1875,85 +1748,8 @@ const noHelperFunctionInTest = ESLintUtils.RuleCreator((name) => `https://github
1875
1748
  }
1876
1749
  });
1877
1750
  //#endregion
1878
- //#region src/rules/no-inline-default-export.ts
1879
- const noInlineDefaultExport = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
1880
- name: "no-inline-default-export",
1881
- meta: {
1882
- type: "suggestion",
1883
- docs: { description: "Disallow inline exports. Prefer declaring first, then exporting separately." },
1884
- messages: {
1885
- noInlineDefaultExport: "Avoid inline default export. Declare the {{type}} first, then export it separately: `export default {{name}};`",
1886
- noAnonymousDefaultExport: "Avoid anonymous default export. Declare a named {{type}} first, then export it separately.",
1887
- noInlineNamedExport: "Avoid inline named export. Declare the {{type}} first, then export it separately: `export { {{name}} };`"
1888
- },
1889
- schema: []
1890
- },
1891
- defaultOptions: [],
1892
- create(context) {
1893
- return {
1894
- ExportDefaultDeclaration(node) {
1895
- const { declaration } = node;
1896
- if (declaration.type === AST_NODE_TYPES.FunctionDeclaration) if (declaration.id) context.report({
1897
- node,
1898
- messageId: "noInlineDefaultExport",
1899
- data: {
1900
- type: "function",
1901
- name: declaration.id.name
1902
- }
1903
- });
1904
- else context.report({
1905
- node,
1906
- messageId: "noAnonymousDefaultExport",
1907
- data: { type: "function" }
1908
- });
1909
- if (declaration.type === AST_NODE_TYPES.ClassDeclaration) if (declaration.id) context.report({
1910
- node,
1911
- messageId: "noInlineDefaultExport",
1912
- data: {
1913
- type: "class",
1914
- name: declaration.id.name
1915
- }
1916
- });
1917
- else context.report({
1918
- node,
1919
- messageId: "noAnonymousDefaultExport",
1920
- data: { type: "class" }
1921
- });
1922
- if (declaration.type === AST_NODE_TYPES.ArrowFunctionExpression || declaration.type === AST_NODE_TYPES.FunctionExpression) context.report({
1923
- node,
1924
- messageId: "noAnonymousDefaultExport",
1925
- data: { type: "function" }
1926
- });
1927
- },
1928
- ExportNamedDeclaration(node) {
1929
- const { declaration } = node;
1930
- if (!declaration) return;
1931
- if (declaration.type === AST_NODE_TYPES.FunctionDeclaration && declaration.id) context.report({
1932
- node,
1933
- messageId: "noInlineNamedExport",
1934
- data: {
1935
- type: "function",
1936
- name: declaration.id.name
1937
- }
1938
- });
1939
- if (declaration.type === AST_NODE_TYPES.ClassDeclaration && declaration.id) context.report({
1940
- node,
1941
- messageId: "noInlineNamedExport",
1942
- data: {
1943
- type: "class",
1944
- name: declaration.id.name
1945
- }
1946
- });
1947
- }
1948
- };
1949
- }
1950
- });
1951
- //#endregion
1952
1751
  //#region src/rules/no-inline-nested-object.ts
1953
- const createRule$14 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1954
- function isObjectOrArray(node) {
1955
- return node.type === AST_NODE_TYPES.ObjectExpression || node.type === AST_NODE_TYPES.ArrayExpression || node.type === AST_NODE_TYPES.TSAsExpression;
1956
- }
1752
+ const createRule$11 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1957
1753
  function getInnerExpression(node) {
1958
1754
  if (node.type === AST_NODE_TYPES.TSAsExpression) return getInnerExpression(node.expression);
1959
1755
  return node;
@@ -1972,11 +1768,11 @@ function containsNestedStructure(node) {
1972
1768
  return isNestedStructure(el);
1973
1769
  });
1974
1770
  }
1975
- const noInlineNestedObject = createRule$14({
1771
+ const noInlineNestedObject = createRule$11({
1976
1772
  name: "no-inline-nested-object",
1977
1773
  meta: {
1978
1774
  type: "layout",
1979
- docs: { description: "Require object or array values that contain further nested objects or arrays to span multiple lines" },
1775
+ docs: { description: "Require object or array values passed to functions, returned, or used as JSX attributes to span multiple lines when they contain nested objects or arrays" },
1980
1776
  fixable: "whitespace",
1981
1777
  messages: { requireMultiline: "Inline collections containing nested objects or arrays should span multiple lines" },
1982
1778
  schema: []
@@ -1984,43 +1780,65 @@ const noInlineNestedObject = createRule$14({
1984
1780
  defaultOptions: [],
1985
1781
  create(context) {
1986
1782
  const { sourceCode } = context;
1987
- return { Property(node) {
1988
- if (!node.value || !isObjectOrArray(node.value)) return;
1989
- const valueNode = getInnerExpression(node.value);
1990
- if (valueNode.type !== AST_NODE_TYPES.ObjectExpression && valueNode.type !== AST_NODE_TYPES.ArrayExpression) return;
1991
- if (!valueNode.loc) return;
1992
- if (valueNode.loc.start.line !== valueNode.loc.end.line) return;
1993
- if (!containsNestedStructure(valueNode)) return;
1994
- const elements = valueNode.type === AST_NODE_TYPES.ObjectExpression ? valueNode.properties : valueNode.elements;
1783
+ function checkValue(node) {
1784
+ if (!node) return;
1785
+ const inner = getInnerExpression(node);
1786
+ if (inner.type !== AST_NODE_TYPES.ObjectExpression && inner.type !== AST_NODE_TYPES.ArrayExpression) return;
1787
+ if (!inner.loc) return;
1788
+ if (inner.loc.start.line !== inner.loc.end.line) return;
1789
+ if (!containsNestedStructure(inner)) return;
1790
+ const elements = inner.type === AST_NODE_TYPES.ObjectExpression ? inner.properties : inner.elements;
1995
1791
  context.report({
1996
- node: valueNode,
1792
+ node: inner,
1997
1793
  messageId: "requireMultiline",
1998
1794
  fix(fixer) {
1999
- const openBrace = sourceCode.getFirstToken(valueNode);
2000
- const closeBrace = sourceCode.getLastToken(valueNode);
2001
- if (!openBrace || !closeBrace) return null;
2002
- const indent = " ".repeat(node.loc?.start.column ?? 0);
2003
- const innerIndent = `${indent} `;
1795
+ const lineIndentMatch = (sourceCode.lines[inner.loc.start.line - 1] ?? "").match(/^(\s*)/);
1796
+ const lineIndent = lineIndentMatch ? lineIndentMatch[1] : "";
1797
+ const innerIndent = `${lineIndent} `;
2004
1798
  const elementTexts = elements.filter((el) => el !== null).map((el) => sourceCode.getText(el));
2005
- const isObject = valueNode.type === AST_NODE_TYPES.ObjectExpression;
1799
+ const isObject = inner.type === AST_NODE_TYPES.ObjectExpression;
2006
1800
  const openChar = isObject ? "{" : "[";
2007
1801
  const closeChar = isObject ? "}" : "]";
2008
- const newContent = `${openChar}\n${elementTexts.map((text) => `${innerIndent}${text},`).join("\n")}\n${indent}${closeChar}`;
2009
- return fixer.replaceText(valueNode, newContent);
1802
+ const newContent = `${openChar}\n${elementTexts.map((text) => `${innerIndent}${text},`).join("\n")}\n${lineIndent}${closeChar}`;
1803
+ return fixer.replaceText(inner, newContent);
2010
1804
  }
2011
1805
  });
2012
- } };
1806
+ }
1807
+ function checkArguments(args) {
1808
+ args.forEach((arg) => {
1809
+ if (arg.type === AST_NODE_TYPES.SpreadElement) return;
1810
+ checkValue(arg);
1811
+ });
1812
+ }
1813
+ return {
1814
+ CallExpression(node) {
1815
+ checkArguments(node.arguments);
1816
+ },
1817
+ NewExpression(node) {
1818
+ checkArguments(node.arguments);
1819
+ },
1820
+ ReturnStatement(node) {
1821
+ checkValue(node.argument);
1822
+ },
1823
+ ArrowFunctionExpression(node) {
1824
+ if (node.body.type !== AST_NODE_TYPES.BlockStatement) checkValue(node.body);
1825
+ },
1826
+ JSXExpressionContainer(node) {
1827
+ if (node.expression.type === AST_NODE_TYPES.JSXEmptyExpression) return;
1828
+ checkValue(node.expression);
1829
+ }
1830
+ };
2013
1831
  }
2014
1832
  });
2015
1833
  //#endregion
2016
1834
  //#region src/rules/no-inline-return-properties.ts
2017
- const createRule$13 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1835
+ const createRule$10 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
2018
1836
  const isShorthandProperty = (property) => {
2019
1837
  if (property.type === AST_NODE_TYPES.SpreadElement) return true;
2020
1838
  if (property.type !== AST_NODE_TYPES.Property) return false;
2021
1839
  return property.shorthand;
2022
1840
  };
2023
- const noInlineReturnProperties = createRule$13({
1841
+ const noInlineReturnProperties = createRule$10({
2024
1842
  name: "no-inline-return-properties",
2025
1843
  meta: {
2026
1844
  type: "suggestion",
@@ -2049,9 +1867,9 @@ const noInlineReturnProperties = createRule$13({
2049
1867
  });
2050
1868
  //#endregion
2051
1869
  //#region src/rules/no-inline-type-import.ts
2052
- const createRule$12 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1870
+ const createRule$9 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
2053
1871
  const isInlineTypeSpecifier = (specifier) => specifier.type === AST_NODE_TYPES.ImportSpecifier && specifier.importKind === "type";
2054
- const noInlineTypeImport = createRule$12({
1872
+ const noInlineTypeImport = createRule$9({
2055
1873
  name: "no-inline-type-import",
2056
1874
  meta: {
2057
1875
  type: "suggestion",
@@ -2093,7 +1911,7 @@ const noInlineTypeImport = createRule$12({
2093
1911
  });
2094
1912
  //#endregion
2095
1913
  //#region src/rules/no-lazy-identifiers.ts
2096
- const createRule$11 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1914
+ const createRule$8 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
2097
1915
  const KEYBOARD_ROWS = [
2098
1916
  "qwertyuiop",
2099
1917
  "asdfghjkl",
@@ -2124,7 +1942,7 @@ const isLazyIdentifier = (name) => {
2124
1942
  if (hasKeyboardSequence(name)) return true;
2125
1943
  return false;
2126
1944
  };
2127
- const noLazyIdentifiers = createRule$11({
1945
+ const noLazyIdentifiers = createRule$8({
2128
1946
  name: "no-lazy-identifiers",
2129
1947
  meta: {
2130
1948
  type: "problem",
@@ -2243,7 +2061,7 @@ const noLogicInParams = ESLintUtils.RuleCreator((name) => `https://github.com/ne
2243
2061
  });
2244
2062
  //#endregion
2245
2063
  //#region src/rules/no-misleading-constant-case.ts
2246
- const createRule$10 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
2064
+ const createRule$7 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
2247
2065
  const SCREAMING_SNAKE_CASE_REGEX = /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/;
2248
2066
  const isAsConstAssertion = (node) => node.type === AST_NODE_TYPES.TSAsExpression && node.typeAnnotation.type === AST_NODE_TYPES.TSTypeReference && node.typeAnnotation.typeName.type === AST_NODE_TYPES.Identifier && node.typeAnnotation.typeName.name === "const";
2249
2067
  const isStaticValue = (init) => {
@@ -2261,7 +2079,7 @@ const isGlobalScope = (node) => {
2261
2079
  if (parent.type === AST_NODE_TYPES.ExportNamedDeclaration && parent.parent?.type === AST_NODE_TYPES.Program) return true;
2262
2080
  return false;
2263
2081
  };
2264
- const noMisleadingConstantCase = createRule$10({
2082
+ const noMisleadingConstantCase = createRule$7({
2265
2083
  name: "no-misleading-constant-case",
2266
2084
  meta: {
2267
2085
  type: "suggestion",
@@ -2349,82 +2167,6 @@ const noNestedInterfaceDeclaration = ESLintUtils.RuleCreator((name) => `https://
2349
2167
  }
2350
2168
  });
2351
2169
  //#endregion
2352
- //#region src/rules/no-nested-ternary.ts
2353
- const noNestedTernary = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
2354
- name: "no-nested-ternary",
2355
- meta: {
2356
- type: "suggestion",
2357
- docs: { description: "Disallow nested ternary expressions" },
2358
- messages: { noNestedTernary: "Nested ternary expressions are not allowed. Use a function with early returns instead." },
2359
- schema: []
2360
- },
2361
- defaultOptions: [],
2362
- create(context) {
2363
- return { ConditionalExpression(node) {
2364
- const { consequent, alternate } = node;
2365
- if (consequent.type === AST_NODE_TYPES.ConditionalExpression) context.report({
2366
- node: consequent,
2367
- messageId: "noNestedTernary"
2368
- });
2369
- if (alternate.type === AST_NODE_TYPES.ConditionalExpression) context.report({
2370
- node: alternate,
2371
- messageId: "noNestedTernary"
2372
- });
2373
- } };
2374
- }
2375
- });
2376
- //#endregion
2377
- //#region src/rules/no-redundant-fragment.ts
2378
- const createRule$9 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
2379
- function isFragmentName(name) {
2380
- if (name.type === AST_NODE_TYPES.JSXIdentifier && name.name === "Fragment") return true;
2381
- if (name.type === AST_NODE_TYPES.JSXMemberExpression && name.object.type === AST_NODE_TYPES.JSXIdentifier && name.object.name === "React" && name.property.type === AST_NODE_TYPES.JSXIdentifier && name.property.name === "Fragment") return true;
2382
- return false;
2383
- }
2384
- function hasKeyAttribute(attributes) {
2385
- return attributes.some((attribute) => attribute.type === AST_NODE_TYPES.JSXAttribute && attribute.name.type === AST_NODE_TYPES.JSXIdentifier && attribute.name.name === "key");
2386
- }
2387
- function countMeaningfulChildren(children) {
2388
- return children.filter((child) => {
2389
- if (child.type === AST_NODE_TYPES.JSXText) return child.value.trim() !== "";
2390
- return true;
2391
- }).length;
2392
- }
2393
- const noRedundantFragment = createRule$9({
2394
- name: "no-redundant-fragment",
2395
- meta: {
2396
- type: "problem",
2397
- docs: { description: "Disallow Fragments that wrap zero or one child (unless a key prop is needed)" },
2398
- schema: [],
2399
- messages: { redundantFragment: "Fragment is redundant when wrapping {{ count }} child. Remove the Fragment or replace it with the child directly." }
2400
- },
2401
- defaultOptions: [],
2402
- create(context) {
2403
- if (!isJsxFile(context.filename)) return {};
2404
- return {
2405
- JSXFragment(node) {
2406
- const count = countMeaningfulChildren(node.children);
2407
- if (count <= 1) context.report({
2408
- node,
2409
- messageId: "redundantFragment",
2410
- data: { count: String(count) }
2411
- });
2412
- },
2413
- JSXElement(node) {
2414
- const opening = node.openingElement;
2415
- if (!isFragmentName(opening.name)) return;
2416
- if (hasKeyAttribute(opening.attributes)) return;
2417
- const count = countMeaningfulChildren(node.children);
2418
- if (count <= 1) context.report({
2419
- node,
2420
- messageId: "redundantFragment",
2421
- data: { count: String(count) }
2422
- });
2423
- }
2424
- };
2425
- }
2426
- });
2427
- //#endregion
2428
2170
  //#region src/rules/no-relative-imports.ts
2429
2171
  const noRelativeImports = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
2430
2172
  name: "no-relative-imports",
@@ -2459,88 +2201,6 @@ const noRelativeImports = ESLintUtils.RuleCreator((name) => `https://github.com/
2459
2201
  }
2460
2202
  });
2461
2203
  //#endregion
2462
- //#region src/rules/no-single-char-variables.ts
2463
- const createRule$8 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
2464
- const ALLOWED_IN_FOR_LOOPS = new Set([
2465
- "i",
2466
- "j",
2467
- "k",
2468
- "n"
2469
- ]);
2470
- const ALLOWED_UNDERSCORE = "_";
2471
- const isForLoopInit = (node) => {
2472
- let current = node;
2473
- while (current) {
2474
- const parentNode = current.parent;
2475
- if (!parentNode) return false;
2476
- if (parentNode.type === AST_NODE_TYPES.ForStatement) {
2477
- const { init } = parentNode;
2478
- if (init && init === current) return true;
2479
- }
2480
- current = parentNode;
2481
- }
2482
- return false;
2483
- };
2484
- const isAllowedInContext = (name, node) => {
2485
- if (name === ALLOWED_UNDERSCORE) return true;
2486
- if (ALLOWED_IN_FOR_LOOPS.has(name) && isForLoopInit(node)) return true;
2487
- return false;
2488
- };
2489
- const noSingleCharVariables = createRule$8({
2490
- name: "no-single-char-variables",
2491
- meta: {
2492
- type: "suggestion",
2493
- docs: { description: "Disallow single character variable and parameter names for better code readability" },
2494
- messages: { noSingleChar: "Avoid single character variable name '{{name}}'. Use a descriptive name that clearly indicates the purpose." },
2495
- schema: []
2496
- },
2497
- defaultOptions: [],
2498
- create(context) {
2499
- const checkIdentifier = (node, declarationNode) => {
2500
- const { name } = node;
2501
- if (name.length !== 1) return;
2502
- if (isAllowedInContext(name, declarationNode)) return;
2503
- context.report({
2504
- node,
2505
- messageId: "noSingleChar",
2506
- data: { name }
2507
- });
2508
- };
2509
- const checkPattern = (pattern, declarationNode) => {
2510
- if (pattern.type === AST_NODE_TYPES.Identifier) checkIdentifier(pattern, declarationNode);
2511
- else if (pattern.type === AST_NODE_TYPES.ObjectPattern) pattern.properties.forEach((prop) => {
2512
- if (prop.type === AST_NODE_TYPES.Property && prop.value.type === AST_NODE_TYPES.Identifier) checkIdentifier(prop.value, declarationNode);
2513
- else if (prop.type === AST_NODE_TYPES.RestElement && prop.argument.type === AST_NODE_TYPES.Identifier) checkIdentifier(prop.argument, declarationNode);
2514
- });
2515
- else if (pattern.type === AST_NODE_TYPES.ArrayPattern) pattern.elements.forEach((element) => {
2516
- if (element?.type === AST_NODE_TYPES.Identifier) checkIdentifier(element, declarationNode);
2517
- else if (element?.type === AST_NODE_TYPES.RestElement && element.argument.type === AST_NODE_TYPES.Identifier) checkIdentifier(element.argument, declarationNode);
2518
- });
2519
- else if (pattern.type === AST_NODE_TYPES.AssignmentPattern && pattern.left.type === AST_NODE_TYPES.Identifier) checkIdentifier(pattern.left, declarationNode);
2520
- else if (pattern.type === AST_NODE_TYPES.RestElement && pattern.argument.type === AST_NODE_TYPES.Identifier) checkIdentifier(pattern.argument, declarationNode);
2521
- };
2522
- return {
2523
- VariableDeclarator(node) {
2524
- checkPattern(node.id, node);
2525
- },
2526
- FunctionDeclaration(node) {
2527
- if (node.id) checkIdentifier(node.id, node);
2528
- node.params.forEach((param) => checkPattern(param, node));
2529
- },
2530
- FunctionExpression(node) {
2531
- if (node.id) checkIdentifier(node.id, node);
2532
- node.params.forEach((param) => checkPattern(param, node));
2533
- },
2534
- ArrowFunctionExpression(node) {
2535
- node.params.forEach((param) => checkPattern(param, node));
2536
- },
2537
- CatchClause(node) {
2538
- if (node.param) checkPattern(node.param, node);
2539
- }
2540
- };
2541
- }
2542
- });
2543
- //#endregion
2544
2204
  //#region src/rules/prefer-async-await.ts
2545
2205
  const preferAsyncAwait = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
2546
2206
  name: "prefer-async-await",
@@ -2607,61 +2267,6 @@ const preferDestructuringParams = ESLintUtils.RuleCreator((name) => `https://git
2607
2267
  }
2608
2268
  });
2609
2269
  //#endregion
2610
- //#region src/rules/prefer-function-declaration.ts
2611
- const createRule$7 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
2612
- const isTsFile = (filename) => filename.endsWith(".ts") && !filename.endsWith(".d.ts");
2613
- const isCallbackContext = (node) => {
2614
- const { parent } = node;
2615
- if (!parent) return false;
2616
- if (parent.type === AST_NODE_TYPES.CallExpression && parent.arguments.includes(node)) return true;
2617
- if (parent.type === AST_NODE_TYPES.NewExpression && parent.arguments.includes(node)) return true;
2618
- if (parent.type === AST_NODE_TYPES.ReturnStatement) return true;
2619
- if (parent.type === AST_NODE_TYPES.Property) return true;
2620
- if (parent.type === AST_NODE_TYPES.ArrayExpression) return true;
2621
- if (parent.type === AST_NODE_TYPES.ConditionalExpression) return true;
2622
- if (parent.type === AST_NODE_TYPES.LogicalExpression) return true;
2623
- if (parent.type === AST_NODE_TYPES.AssignmentExpression && parent.left !== node) return true;
2624
- return false;
2625
- };
2626
- const preferFunctionDeclaration = createRule$7({
2627
- name: "prefer-function-declaration",
2628
- meta: {
2629
- type: "suggestion",
2630
- docs: { description: "Enforce function declarations over arrow functions assigned to variables in .ts files for better readability and hoisting" },
2631
- messages: {
2632
- preferDeclaration: "Use function declaration instead of arrow function. Replace 'const {{name}} = () => ...' with 'function {{name}}() ...'",
2633
- preferDeclarationExpr: "Use function declaration instead of function expression. Replace 'const {{name}} = function() ...' with 'function {{name}}() ...'"
2634
- },
2635
- schema: []
2636
- },
2637
- defaultOptions: [],
2638
- create(context) {
2639
- const { filename } = context;
2640
- if (!isTsFile(filename)) return {};
2641
- return { VariableDeclarator(node) {
2642
- if (node.id.type !== AST_NODE_TYPES.Identifier) return;
2643
- const { init } = node;
2644
- if (!init) return;
2645
- if (init.type === AST_NODE_TYPES.ArrowFunctionExpression) {
2646
- if (isCallbackContext(init)) return;
2647
- context.report({
2648
- node: init,
2649
- messageId: "preferDeclaration",
2650
- data: { name: node.id.name }
2651
- });
2652
- }
2653
- if (init.type === AST_NODE_TYPES.FunctionExpression) {
2654
- if (isCallbackContext(init)) return;
2655
- context.report({
2656
- node: init,
2657
- messageId: "preferDeclarationExpr",
2658
- data: { name: node.id.name }
2659
- });
2660
- }
2661
- } };
2662
- }
2663
- });
2664
- //#endregion
2665
2270
  //#region src/rules/prefer-guard-clause.ts
2666
2271
  const preferGuardClause = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
2667
2272
  name: "prefer-guard-clause",
@@ -2935,64 +2540,6 @@ const preferInterfaceOverInlineTypes = ESLintUtils.RuleCreator((name) => `https:
2935
2540
  }
2936
2541
  });
2937
2542
  //#endregion
2938
- //#region src/rules/prefer-jsx-template-literals.ts
2939
- const preferJSXTemplateLiterals = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
2940
- name: "prefer-jsx-template-literals",
2941
- meta: {
2942
- type: "suggestion",
2943
- docs: { description: "Enforce using template literals instead of mixing text and JSX expressions" },
2944
- fixable: "code",
2945
- schema: [],
2946
- messages: { preferTemplate: "Use template literal instead of mixing text with JSX expressions" }
2947
- },
2948
- defaultOptions: [],
2949
- create(context) {
2950
- if (!isJsxFile(context.filename)) return {};
2951
- function handleTextBeforeExpression(textNode, exprNode) {
2952
- const textValue = textNode.value;
2953
- const trimmedText = textValue.trim();
2954
- if (!trimmedText) return;
2955
- const hasTextContent = trimmedText.length > 0 && textValue !== trimmedText;
2956
- const hasNoTrailingSpace = trimmedText.length > 0 && /\S$/.test(textValue);
2957
- if (!hasTextContent && !hasNoTrailingSpace) return;
2958
- context.report({
2959
- node: textNode,
2960
- messageId: "preferTemplate",
2961
- fix(fixer) {
2962
- const templateLiteral = `{\`${textValue.trimEnd()}\${${context.sourceCode.getText(exprNode.expression)}}\`}`;
2963
- return [fixer.replaceText(textNode, templateLiteral), fixer.remove(exprNode)];
2964
- }
2965
- });
2966
- }
2967
- function handleExpressionBeforeText(exprNode, textNode) {
2968
- const textValue = textNode.value;
2969
- const trimmedText = textValue.trim();
2970
- if (!trimmedText) return;
2971
- if (!/^\S/.test(trimmedText)) return;
2972
- context.report({
2973
- node: textNode,
2974
- messageId: "preferTemplate",
2975
- fix(fixer) {
2976
- const templateLiteral = `{\`\${${context.sourceCode.getText(exprNode.expression)}}${textValue.trim()}\`}`;
2977
- return [fixer.replaceText(exprNode, templateLiteral), fixer.remove(textNode)];
2978
- }
2979
- });
2980
- }
2981
- function checkJSXElement(node) {
2982
- const { children } = node;
2983
- if (children.length < 2) return;
2984
- for (let i = 0; i < children.length - 1; i += 1) {
2985
- const child = children[i];
2986
- const nextChild = children[i + 1];
2987
- if (!child || !nextChild) return;
2988
- if (child.type === AST_NODE_TYPES.JSXText && nextChild.type === AST_NODE_TYPES.JSXExpressionContainer) handleTextBeforeExpression(child, nextChild);
2989
- else if (child.type === AST_NODE_TYPES.JSXExpressionContainer && nextChild.type === AST_NODE_TYPES.JSXText) handleExpressionBeforeText(child, nextChild);
2990
- }
2991
- }
2992
- return { JSXElement: checkJSXElement };
2993
- }
2994
- });
2995
- //#endregion
2996
2543
  //#region src/rules/prefer-named-param-types.ts
2997
2544
  const createRule$5 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
2998
2545
  const returnsJsx = (node) => {
@@ -3209,65 +2756,6 @@ const preferReactImportTypes = ESLintUtils.RuleCreator((name) => `https://github
3209
2756
  }
3210
2757
  });
3211
2758
  //#endregion
3212
- //#region src/rules/react-props-destructure.ts
3213
- const reactPropsDestructure = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`)({
3214
- name: "react-props-destructure",
3215
- meta: {
3216
- type: "suggestion",
3217
- docs: { description: "Enforce destructuring props inside React component body instead of parameters" },
3218
- fixable: void 0,
3219
- schema: [],
3220
- messages: { noParameterDestructuring: "Destructure props inside component body instead of parameters. Use 'const { {{properties}} } = props;'" }
3221
- },
3222
- defaultOptions: [],
3223
- create(context) {
3224
- if (!isJsxFile(context.filename)) return {};
3225
- function hasJSXInConditional(node) {
3226
- return node.consequent.type === AST_NODE_TYPES.JSXElement || node.consequent.type === AST_NODE_TYPES.JSXFragment || node.alternate.type === AST_NODE_TYPES.JSXElement || node.alternate.type === AST_NODE_TYPES.JSXFragment;
3227
- }
3228
- function hasJSXInLogical(node) {
3229
- return node.right.type === AST_NODE_TYPES.JSXElement || node.right.type === AST_NODE_TYPES.JSXFragment;
3230
- }
3231
- function hasJSXReturn(block) {
3232
- return block.body.some((stmt) => {
3233
- if (stmt.type === AST_NODE_TYPES.ReturnStatement && stmt.argument) return stmt.argument.type === AST_NODE_TYPES.JSXElement || stmt.argument.type === AST_NODE_TYPES.JSXFragment || stmt.argument.type === AST_NODE_TYPES.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === AST_NODE_TYPES.LogicalExpression && hasJSXInLogical(stmt.argument);
3234
- return false;
3235
- });
3236
- }
3237
- function isReactComponent(node) {
3238
- if (node.type === AST_NODE_TYPES.ArrowFunctionExpression) {
3239
- if (node.body.type === AST_NODE_TYPES.JSXElement || node.body.type === AST_NODE_TYPES.JSXFragment) return true;
3240
- if (node.body.type === AST_NODE_TYPES.BlockStatement) return hasJSXReturn(node.body);
3241
- } else if (node.type === AST_NODE_TYPES.FunctionExpression || node.type === AST_NODE_TYPES.FunctionDeclaration) {
3242
- if (node.body && node.body.type === AST_NODE_TYPES.BlockStatement) return hasJSXReturn(node.body);
3243
- }
3244
- return false;
3245
- }
3246
- function checkFunction(node) {
3247
- if (!isReactComponent(node)) return;
3248
- if (node.params.length !== 1) return;
3249
- const param = node.params[0];
3250
- if (param.type === AST_NODE_TYPES.ObjectPattern) {
3251
- const properties = param.properties.filter((prop) => prop.type === AST_NODE_TYPES.Property).map((prop) => {
3252
- if (prop.key.type === AST_NODE_TYPES.Identifier) return prop.key.name;
3253
- return null;
3254
- }).filter((name) => name !== null);
3255
- if (properties.length === 0) return;
3256
- context.report({
3257
- node: param,
3258
- messageId: "noParameterDestructuring",
3259
- data: { properties: properties.join(", ") }
3260
- });
3261
- }
3262
- }
3263
- return {
3264
- ArrowFunctionExpression: checkFunction,
3265
- FunctionExpression: checkFunction,
3266
- FunctionDeclaration: checkFunction
3267
- };
3268
- }
3269
- });
3270
- //#endregion
3271
2759
  //#region src/rules/require-explicit-return-type.ts
3272
2760
  const createRule$4 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
3273
2761
  const isReactComponent = (node) => {
@@ -3444,21 +2932,29 @@ const GROUP_NAMES = [
3444
2932
  "",
3445
2933
  "side-effect",
3446
2934
  "builtin",
2935
+ "builtin type",
3447
2936
  "external",
2937
+ "external type",
3448
2938
  "internal alias",
3449
- "relative"
2939
+ "internal alias type",
2940
+ "parent relative",
2941
+ "parent relative type",
2942
+ "relative",
2943
+ "relative type"
3450
2944
  ];
3451
- function getImportGroup(node) {
3452
- const source = node.source.value;
3453
- if (node.specifiers.length === 0 && node.importKind !== "type") return 1;
3454
- if (source.startsWith("node:") || NODE_BUILTINS.has(source.split("/")[0])) return 2;
3455
- if (source.startsWith("@/") || source.startsWith("~/") || source.startsWith("#")) return 4;
3456
- if (source.startsWith(".")) return 5;
3457
- return 3;
3458
- }
3459
2945
  function isTypeOnlyImport(node) {
3460
2946
  return node.importKind === "type" && node.specifiers.length > 0;
3461
2947
  }
2948
+ function getImportGroup(node) {
2949
+ const source = node.source.value;
2950
+ const isType = isTypeOnlyImport(node);
2951
+ if (node.specifiers.length === 0 && !isType) return 1;
2952
+ if (source.startsWith("node:") || NODE_BUILTINS.has(source.split("/")[0])) return isType ? 3 : 2;
2953
+ if (source.startsWith("@/") || source.startsWith("~/") || source.startsWith("#")) return isType ? 7 : 6;
2954
+ if (source.startsWith("../")) return isType ? 9 : 8;
2955
+ if (source.startsWith(".")) return isType ? 11 : 10;
2956
+ return isType ? 5 : 4;
2957
+ }
3462
2958
  const sortImports = createRule$2({
3463
2959
  name: "sort-imports",
3464
2960
  meta: {
@@ -3466,14 +2962,43 @@ const sortImports = createRule$2({
3466
2962
  docs: { description: "Enforce a consistent ordering of import groups" },
3467
2963
  fixable: "code",
3468
2964
  schema: [],
3469
- messages: { unsortedImports: "Import group '{{current}}' should come before '{{previous}}'. Expected order: side-effect, builtin, external, internal alias, relative." }
2965
+ messages: {
2966
+ unsortedImports: "Import group '{{current}}' should come before '{{previous}}'. Expected order: side-effect, builtin, external, internal alias, parent relative, relative — each followed by its type imports.",
2967
+ missingBlankLine: "Expected a blank line before '{{current}}' imports (new group after '{{previous}}')."
2968
+ }
3470
2969
  },
3471
2970
  defaultOptions: [],
3472
2971
  create(context) {
2972
+ function getMainGroup(group) {
2973
+ if (group === 1) return 1;
2974
+ return Math.floor((group - 2) / 2) + 2;
2975
+ }
2976
+ function checkBlankLines(imports) {
2977
+ const { sourceCode } = context;
2978
+ for (let i = 1; i < imports.length; i++) {
2979
+ const prev = imports[i - 1];
2980
+ const curr = imports[i];
2981
+ if (getMainGroup(prev.group) === getMainGroup(curr.group)) continue;
2982
+ if (curr.node.loc.start.line - prev.node.loc.end.line > 1) continue;
2983
+ context.report({
2984
+ node: curr.node,
2985
+ messageId: "missingBlankLine",
2986
+ data: {
2987
+ current: GROUP_NAMES[curr.group],
2988
+ previous: GROUP_NAMES[prev.group]
2989
+ },
2990
+ fix(fixer) {
2991
+ const firstToken = sourceCode.getFirstToken(curr.node);
2992
+ if (!firstToken) return null;
2993
+ return fixer.insertTextBefore(firstToken, "\n");
2994
+ }
2995
+ });
2996
+ }
2997
+ }
3473
2998
  function checkOrder(imports) {
3474
- if (imports.every((entry, index) => index === 0 || entry.group >= imports[index - 1].group)) return;
2999
+ if (imports.every((entry, index) => index === 0 || entry.group >= imports[index - 1].group)) return false;
3475
3000
  const firstUnsorted = imports.find((entry, index) => index > 0 && entry.group < imports[index - 1].group);
3476
- if (!firstUnsorted) return;
3001
+ if (!firstUnsorted) return false;
3477
3002
  const previous = imports[imports.indexOf(firstUnsorted) - 1];
3478
3003
  context.report({
3479
3004
  node: firstUnsorted.node,
@@ -3488,24 +3013,26 @@ const sortImports = createRule$2({
3488
3013
  return imports.map((entry, index) => fixer.replaceText(entry.node, sortedTexts[index]));
3489
3014
  }
3490
3015
  });
3016
+ return true;
3491
3017
  }
3492
3018
  return { Program(node) {
3493
3019
  const importGroups = [];
3494
3020
  node.body.forEach((statement) => {
3495
3021
  if (statement.type !== AST_NODE_TYPES.ImportDeclaration) {
3496
3022
  if (importGroups.length > 0) {
3497
- checkOrder(importGroups);
3023
+ if (!checkOrder(importGroups)) checkBlankLines(importGroups);
3498
3024
  importGroups.length = 0;
3499
3025
  }
3500
3026
  return;
3501
3027
  }
3502
- if (isTypeOnlyImport(statement)) return;
3503
3028
  importGroups.push({
3504
3029
  node: statement,
3505
3030
  group: getImportGroup(statement)
3506
3031
  });
3507
3032
  });
3508
- if (importGroups.length > 0) checkOrder(importGroups);
3033
+ if (importGroups.length > 0) {
3034
+ if (!checkOrder(importGroups)) checkBlankLines(importGroups);
3035
+ }
3509
3036
  } };
3510
3037
  }
3511
3038
  });
@@ -3638,11 +3165,9 @@ const meta = {
3638
3165
  };
3639
3166
  const rules = {
3640
3167
  "boolean-naming-prefix": booleanNamingPrefix,
3641
- "enforce-camel-case": enforceCamelCase,
3642
3168
  "enforce-constant-case": enforceConstantCase,
3643
3169
  "enforce-hook-filename": enforceHookFilename,
3644
3170
  "enforce-hook-naming": enforceHookNaming,
3645
- "enforce-property-case": enforcePropertyCase,
3646
3171
  "enforce-props-suffix": enforcePropsSuffix,
3647
3172
  "enforce-readonly-component-props": enforceReadonlyComponentProps,
3648
3173
  "enforce-render-naming": enforceRenderNaming,
@@ -3673,7 +3198,6 @@ const rules = {
3673
3198
  "no-ghost-wrapper": noGhostWrapper,
3674
3199
  "no-helper-function-in-hook": noHelperFunctionInHook,
3675
3200
  "no-helper-function-in-test": noHelperFunctionInTest,
3676
- "no-inline-default-export": noInlineDefaultExport,
3677
3201
  "no-inline-nested-object": noInlineNestedObject,
3678
3202
  "no-inline-return-properties": noInlineReturnProperties,
3679
3203
  "no-inline-type-import": noInlineTypeImport,
@@ -3681,23 +3205,17 @@ const rules = {
3681
3205
  "no-logic-in-params": noLogicInParams,
3682
3206
  "no-misleading-constant-case": noMisleadingConstantCase,
3683
3207
  "no-nested-interface-declaration": noNestedInterfaceDeclaration,
3684
- "no-nested-ternary": noNestedTernary,
3685
- "no-redundant-fragment": noRedundantFragment,
3686
3208
  "no-relative-imports": noRelativeImports,
3687
- "no-single-char-variables": noSingleCharVariables,
3688
3209
  "prefer-async-await": preferAsyncAwait,
3689
3210
  "prefer-destructuring-params": preferDestructuringParams,
3690
- "prefer-function-declaration": preferFunctionDeclaration,
3691
3211
  "prefer-guard-clause": preferGuardClause,
3692
3212
  "prefer-import-type": preferImportType,
3693
3213
  "prefer-inline-literal-union": preferInlineLiteralUnion,
3694
3214
  "prefer-interface-for-component-props": preferInterfaceForComponentProps,
3695
3215
  "prefer-interface-over-inline-types": preferInterfaceOverInlineTypes,
3696
- "prefer-jsx-template-literals": preferJSXTemplateLiterals,
3697
3216
  "prefer-named-param-types": preferNamedParamTypes,
3698
3217
  "prefer-props-with-children": preferPropsWithChildren,
3699
3218
  "prefer-react-import-types": preferReactImportTypes,
3700
- "react-props-destructure": reactPropsDestructure,
3701
3219
  "require-explicit-return-type": requireExplicitReturnType,
3702
3220
  "sort-exports": sortExports,
3703
3221
  "sort-imports": sortImports,
@@ -3710,11 +3228,9 @@ const plugin = {
3710
3228
  };
3711
3229
  const baseRules = {
3712
3230
  "nextfriday/boolean-naming-prefix": "warn",
3713
- "nextfriday/enforce-camel-case": "warn",
3714
3231
  "nextfriday/enforce-constant-case": "warn",
3715
3232
  "nextfriday/enforce-hook-filename": "warn",
3716
3233
  "nextfriday/enforce-hook-naming": "warn",
3717
- "nextfriday/enforce-property-case": "warn",
3718
3234
  "nextfriday/enforce-service-naming": "warn",
3719
3235
  "nextfriday/enforce-test-filename": "warn",
3720
3236
  "nextfriday/enforce-sorted-destructuring": "warn",
@@ -3728,7 +3244,6 @@ const baseRules = {
3728
3244
  "nextfriday/no-env-fallback": "warn",
3729
3245
  "nextfriday/no-helper-function-in-hook": "warn",
3730
3246
  "nextfriday/no-helper-function-in-test": "warn",
3731
- "nextfriday/no-inline-default-export": "warn",
3732
3247
  "nextfriday/no-inline-nested-object": "warn",
3733
3248
  "nextfriday/no-inline-return-properties": "warn",
3734
3249
  "nextfriday/no-inline-type-import": "warn",
@@ -3736,12 +3251,9 @@ const baseRules = {
3736
3251
  "nextfriday/no-logic-in-params": "warn",
3737
3252
  "nextfriday/no-misleading-constant-case": "warn",
3738
3253
  "nextfriday/no-nested-interface-declaration": "warn",
3739
- "nextfriday/no-nested-ternary": "warn",
3740
3254
  "nextfriday/no-relative-imports": "warn",
3741
- "nextfriday/no-single-char-variables": "warn",
3742
3255
  "nextfriday/prefer-async-await": "warn",
3743
3256
  "nextfriday/prefer-destructuring-params": "warn",
3744
- "nextfriday/prefer-function-declaration": "warn",
3745
3257
  "nextfriday/prefer-guard-clause": "warn",
3746
3258
  "nextfriday/prefer-import-type": "warn",
3747
3259
  "nextfriday/prefer-inline-literal-union": "warn",
@@ -3755,11 +3267,9 @@ const baseRules = {
3755
3267
  };
3756
3268
  const baseRecommendedRules = {
3757
3269
  "nextfriday/boolean-naming-prefix": "error",
3758
- "nextfriday/enforce-camel-case": "error",
3759
3270
  "nextfriday/enforce-constant-case": "error",
3760
3271
  "nextfriday/enforce-hook-filename": "error",
3761
3272
  "nextfriday/enforce-hook-naming": "error",
3762
- "nextfriday/enforce-property-case": "error",
3763
3273
  "nextfriday/enforce-service-naming": "error",
3764
3274
  "nextfriday/enforce-test-filename": "error",
3765
3275
  "nextfriday/enforce-sorted-destructuring": "error",
@@ -3773,7 +3283,6 @@ const baseRecommendedRules = {
3773
3283
  "nextfriday/no-env-fallback": "error",
3774
3284
  "nextfriday/no-helper-function-in-hook": "error",
3775
3285
  "nextfriday/no-helper-function-in-test": "error",
3776
- "nextfriday/no-inline-default-export": "error",
3777
3286
  "nextfriday/no-inline-nested-object": "error",
3778
3287
  "nextfriday/no-inline-return-properties": "error",
3779
3288
  "nextfriday/no-inline-type-import": "error",
@@ -3781,12 +3290,9 @@ const baseRecommendedRules = {
3781
3290
  "nextfriday/no-logic-in-params": "error",
3782
3291
  "nextfriday/no-misleading-constant-case": "error",
3783
3292
  "nextfriday/no-nested-interface-declaration": "error",
3784
- "nextfriday/no-nested-ternary": "error",
3785
3293
  "nextfriday/no-relative-imports": "error",
3786
- "nextfriday/no-single-char-variables": "error",
3787
3294
  "nextfriday/prefer-async-await": "error",
3788
3295
  "nextfriday/prefer-destructuring-params": "error",
3789
- "nextfriday/prefer-function-declaration": "error",
3790
3296
  "nextfriday/prefer-guard-clause": "error",
3791
3297
  "nextfriday/prefer-import-type": "error",
3792
3298
  "nextfriday/prefer-inline-literal-union": "error",
@@ -3816,12 +3322,9 @@ const jsxRules = {
3816
3322
  "nextfriday/jsx-sort-props": "warn",
3817
3323
  "nextfriday/jsx-spread-props-last": "warn",
3818
3324
  "nextfriday/no-ghost-wrapper": "warn",
3819
- "nextfriday/no-redundant-fragment": "warn",
3820
3325
  "nextfriday/prefer-interface-for-component-props": "warn",
3821
3326
  "nextfriday/prefer-interface-over-inline-types": "warn",
3822
- "nextfriday/prefer-jsx-template-literals": "warn",
3823
- "nextfriday/prefer-props-with-children": "warn",
3824
- "nextfriday/react-props-destructure": "warn"
3327
+ "nextfriday/prefer-props-with-children": "warn"
3825
3328
  };
3826
3329
  const jsxRecommendedRules = {
3827
3330
  "nextfriday/enforce-props-suffix": "error",
@@ -3841,12 +3344,9 @@ const jsxRecommendedRules = {
3841
3344
  "nextfriday/jsx-sort-props": "error",
3842
3345
  "nextfriday/jsx-spread-props-last": "error",
3843
3346
  "nextfriday/no-ghost-wrapper": "error",
3844
- "nextfriday/no-redundant-fragment": "error",
3845
3347
  "nextfriday/prefer-interface-for-component-props": "error",
3846
3348
  "nextfriday/prefer-interface-over-inline-types": "error",
3847
- "nextfriday/prefer-jsx-template-literals": "error",
3848
- "nextfriday/prefer-props-with-children": "error",
3849
- "nextfriday/react-props-destructure": "error"
3349
+ "nextfriday/prefer-props-with-children": "error"
3850
3350
  };
3851
3351
  const createConfig = (configRules) => ({
3852
3352
  plugins: { nextfriday: plugin },