eslint-plugin-code-style 1.0.39 → 1.0.41

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.
Files changed (3) hide show
  1. package/README.md +22 -0
  2. package/index.js +95 -17
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -890,44 +890,66 @@ useEffect(() => {}, [
890
890
  // ✅ Good — consistent formatting
891
891
  if (condition) {
892
892
  doSomething();
893
+
894
+ doMore();
893
895
  }
894
896
 
895
897
  if (condition) {
896
898
  doSomething();
899
+
900
+ doMore();
897
901
  } else {
898
902
  doOther();
903
+
904
+ doAnother();
899
905
  }
900
906
 
901
907
  if (conditionA) {
902
908
  handleA();
909
+
910
+ processA();
903
911
  } else if (conditionB) {
904
912
  handleB();
913
+
914
+ processB();
905
915
  } else {
906
916
  handleDefault();
917
+
918
+ processDefault();
907
919
  }
908
920
 
909
921
  // ❌ Bad — brace on new line
910
922
  if (condition)
911
923
  {
912
924
  doSomething();
925
+
926
+ doMore();
913
927
  }
914
928
 
915
929
  // ❌ Bad — else on new line
916
930
  if (condition) {
917
931
  doSomething();
932
+
933
+ doMore();
918
934
  }
919
935
  else {
920
936
  doOther();
937
+
938
+ doAnother();
921
939
  }
922
940
 
923
941
  // ❌ Bad — inconsistent formatting
924
942
  if (condition)
925
943
  {
926
944
  doSomething();
945
+
946
+ doMore();
927
947
  }
928
948
  else
929
949
  {
930
950
  doOther();
951
+
952
+ doAnother();
931
953
  }
932
954
  ```
933
955
 
package/index.js CHANGED
@@ -2128,21 +2128,28 @@ const hookDepsPerLine = {
2128
2128
  * opening brace on the same line as the condition and else
2129
2129
  * on the same line as the closing brace.
2130
2130
  *
2131
+ *
2131
2132
  * ✓ Good:
2132
2133
  * if (condition) {
2133
2134
  * doSomething();
2135
+ *
2136
+ * doMore();
2134
2137
  * } else {
2135
2138
  * doOther();
2139
+ *
2140
+ * doAnother();
2136
2141
  * }
2137
2142
  *
2138
2143
  * ✗ Bad:
2139
2144
  * if (condition)
2140
2145
  * {
2141
2146
  * doSomething();
2147
+ * doMore();
2142
2148
  * }
2143
2149
  * else
2144
2150
  * {
2145
2151
  * doOther();
2152
+ * doAnother();
2146
2153
  * }
2147
2154
  */
2148
2155
  const ifStatementFormat = {
@@ -4708,12 +4715,46 @@ const jsxTernaryFormat = {
4708
4715
  return tokenBefore && tokenAfter && tokenBefore.value === "(" && tokenAfter.value === ")";
4709
4716
  };
4710
4717
 
4718
+ // Check if condition has broken operators (spread across lines)
4719
+ const hasConditionBrokenAcrossLinesHandler = (testNode) => {
4720
+ // Check binary expressions (===, !==, etc.)
4721
+ if (testNode.type === "BinaryExpression") {
4722
+ const leftEnd = testNode.left.loc.end.line;
4723
+ const rightStart = testNode.right.loc.start.line;
4724
+
4725
+ if (leftEnd !== rightStart) return true;
4726
+
4727
+ // Recursively check nested expressions
4728
+ return hasConditionBrokenAcrossLinesHandler(testNode.left)
4729
+ || hasConditionBrokenAcrossLinesHandler(testNode.right);
4730
+ }
4731
+
4732
+ // Check logical expressions (&&, ||)
4733
+ if (testNode.type === "LogicalExpression") {
4734
+ const leftEnd = testNode.left.loc.end.line;
4735
+ const rightStart = testNode.right.loc.start.line;
4736
+
4737
+ if (leftEnd !== rightStart) return true;
4738
+
4739
+ return hasConditionBrokenAcrossLinesHandler(testNode.left)
4740
+ || hasConditionBrokenAcrossLinesHandler(testNode.right);
4741
+ }
4742
+
4743
+ return false;
4744
+ };
4745
+
4746
+ // Get the full condition text collapsed to single line
4747
+ const getCollapsedConditionTextHandler = (testNode) => sourceCode.getText(testNode).replace(/\s*\n\s*/g, " ").trim();
4748
+
4711
4749
  return {
4712
4750
  ConditionalExpression(node) {
4713
- // Only handle ternaries in JSX context
4714
4751
  const parent = node.parent;
4715
4752
 
4716
- if (!parent || parent.type !== "JSXExpressionContainer") return;
4753
+ // Handle ternaries in JSX context or return statements
4754
+ const isJsxContext = parent && parent.type === "JSXExpressionContainer";
4755
+ const isReturnContext = parent && parent.type === "ReturnStatement";
4756
+
4757
+ if (!isJsxContext && !isReturnContext) return;
4717
4758
 
4718
4759
  const {
4719
4760
  alternate,
@@ -4732,19 +4773,32 @@ const jsxTernaryFormat = {
4732
4773
  const baseIndent = getIndentHandler(node);
4733
4774
  const contentIndent = baseIndent + " ";
4734
4775
 
4735
- // Check 0: Condition should be on same line as opening {
4736
- const openBrace = sourceCode.getFirstToken(parent);
4776
+ // Check: Condition should not be broken across multiple lines
4777
+ if (hasConditionBrokenAcrossLinesHandler(node.test)) {
4778
+ const collapsedCondition = getCollapsedConditionTextHandler(node.test);
4737
4779
 
4738
- if (openBrace && openBrace.value === "{") {
4739
- if (openBrace.loc.end.line !== node.test.loc.start.line) {
4740
- context.report({
4741
- fix: (fixer) => fixer.replaceTextRange(
4742
- [openBrace.range[1], node.test.range[0]],
4743
- "",
4744
- ),
4745
- message: "Ternary condition should be on same line as opening '{'",
4746
- node: node.test,
4747
- });
4780
+ context.report({
4781
+ fix: (fixer) => fixer.replaceText(node.test, collapsedCondition),
4782
+ message: "Ternary condition should not be broken across multiple lines",
4783
+ node: node.test,
4784
+ });
4785
+ }
4786
+
4787
+ // Check: Condition should be on same line as opening { (for JSX context)
4788
+ if (isJsxContext) {
4789
+ const openBrace = sourceCode.getFirstToken(parent);
4790
+
4791
+ if (openBrace && openBrace.value === "{") {
4792
+ if (openBrace.loc.end.line !== node.test.loc.start.line) {
4793
+ context.report({
4794
+ fix: (fixer) => fixer.replaceTextRange(
4795
+ [openBrace.range[1], node.test.range[0]],
4796
+ "",
4797
+ ),
4798
+ message: "Ternary condition should be on same line as opening '{'",
4799
+ node: node.test,
4800
+ });
4801
+ }
4748
4802
  }
4749
4803
  }
4750
4804
 
@@ -4764,8 +4818,8 @@ const jsxTernaryFormat = {
4764
4818
 
4765
4819
  if (!colonToken) return;
4766
4820
 
4767
- // Get closing brace of JSXExpressionContainer
4768
- const closeBrace = sourceCode.getLastToken(parent);
4821
+ // Get closing brace of JSXExpressionContainer (null for return statements)
4822
+ const closeBrace = isJsxContext ? sourceCode.getLastToken(parent) : null;
4769
4823
 
4770
4824
  // Check for unnecessary parentheses around simple JSX
4771
4825
  if (consequentSimple && hasUnnecessaryParensHandler(consequent)) {
@@ -5059,6 +5113,30 @@ const jsxTernaryFormat = {
5059
5113
  }
5060
5114
  }
5061
5115
 
5116
+ // Check if simple alternate is wrapped in unnecessary parentheses
5117
+ const tokenAfterColon = sourceCode.getTokenAfter(colonToken);
5118
+
5119
+ if (tokenAfterColon && tokenAfterColon.value === "(") {
5120
+ // Find the matching closing paren
5121
+ const closingParen = sourceCode.getTokenAfter(alternate);
5122
+
5123
+ if (closingParen && closingParen.value === ")") {
5124
+ // Remove parentheses and put simple alternate on same line as :
5125
+ const alternateText = sourceCode.getText(alternate);
5126
+
5127
+ context.report({
5128
+ fix: (fixer) => fixer.replaceTextRange(
5129
+ [colonToken.range[1], closingParen.range[1]],
5130
+ ` ${alternateText}`,
5131
+ ),
5132
+ message: "Simple JSX should not be wrapped in parentheses; put on same line as ':'",
5133
+ node: alternate,
5134
+ });
5135
+
5136
+ return;
5137
+ }
5138
+ }
5139
+
5062
5140
  // Simple alternate should be on same line as :
5063
5141
  if (colonToken.loc.end.line !== alternate.loc.start.line) {
5064
5142
  context.report({
@@ -5071,7 +5149,7 @@ const jsxTernaryFormat = {
5071
5149
  });
5072
5150
  }
5073
5151
 
5074
- // } should be on same line as simple alternate
5152
+ // } should be on same line as simple alternate (only for JSX context)
5075
5153
  if (closeBrace && closeBrace.value === "}" && alternate.loc.end.line !== closeBrace.loc.start.line) {
5076
5154
  context.report({
5077
5155
  fix: (fixer) => fixer.replaceTextRange(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-code-style",
3
- "version": "1.0.39",
3
+ "version": "1.0.41",
4
4
  "description": "A custom ESLint plugin for enforcing consistent code formatting and style rules in React/JSX projects",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",