eslint-plugin-code-style 1.7.3 → 1.7.4

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/CHANGELOG.md +12 -0
  2. package/index.js +80 -11
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
+ ## [1.7.4] - 2026-02-02
11
+
12
+ ### Fixed
13
+
14
+ - **`no-empty-lines-in-function-params`** - Fix bug that deleted TypeScript type annotations when fixing empty lines in destructured params; now uses `getTokenAfter` instead of `getLastToken` to find closing brace
15
+ - **`no-inline-type-definitions`** - Change threshold comparison from `>` to `>=` so 2-member unions are now flagged (with default `maxUnionMembers: 2`)
16
+ - **`ternary-condition-multiline`** - Fix multiline formatting for >3 operands: first operand stays on same line as property key, `?` and `:` each on their own lines; fix circular fix bug for ≤3 operands case
17
+
18
+ ---
19
+
10
20
  ## [1.7.3] - 2026-02-02
11
21
 
12
22
  ### Fixed
@@ -1107,6 +1117,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1107
1117
 
1108
1118
  ---
1109
1119
 
1120
+ [1.7.4]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.7.3...v1.7.4
1121
+ [1.7.3]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.7.2...v1.7.3
1110
1122
  [1.7.2]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.7.1...v1.7.2
1111
1123
  [1.7.1]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.7.0...v1.7.1
1112
1124
  [1.7.0]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.6.6...v1.7.0
package/index.js CHANGED
@@ -4197,6 +4197,23 @@ const ternaryConditionMultiline = {
4197
4197
  message: `Ternary with ≤${maxOperands} operands should be on single line when it fits`,
4198
4198
  node,
4199
4199
  });
4200
+ } else if (needsOperatorFix) {
4201
+ // Format as proper multiline with ? and : on their own lines with values
4202
+ context.report({
4203
+ fix: (fixer) => {
4204
+ const lineText = sourceCode.lines[node.loc.start.line - 1];
4205
+ const baseIndent = lineText.match(/^\s*/)[0];
4206
+ const conditionIndent = baseIndent + " ";
4207
+ const conditionText = buildSameLineHandler(test);
4208
+ const consequentText = sourceCode.getText(node.consequent);
4209
+ const alternateText = sourceCode.getText(node.alternate);
4210
+ const newText = `${conditionText}\n${conditionIndent}? ${consequentText}\n${conditionIndent}: ${alternateText}`;
4211
+
4212
+ return fixer.replaceText(node, newText);
4213
+ },
4214
+ message: `Ternary with ≤${maxOperands} operands should have ? and : with their values on the same line`,
4215
+ node,
4216
+ });
4200
4217
  } else if (needsConditionFix) {
4201
4218
  // Otherwise just fix the condition to be on single line
4202
4219
  context.report({
@@ -4212,6 +4229,7 @@ const ternaryConditionMultiline = {
4212
4229
 
4213
4230
  // More than maxOperands: each on its own line
4214
4231
  let isCorrectionNeeded = !isMultiLine;
4232
+ const parent = node.parent;
4215
4233
 
4216
4234
  if (isMultiLine) {
4217
4235
  for (let i = 0; i < operands.length - 1; i += 1) {
@@ -4257,14 +4275,57 @@ const ternaryConditionMultiline = {
4257
4275
  if (!isCorrectionNeeded && isOperatorOnOwnLineHandler(node)) {
4258
4276
  isCorrectionNeeded = true;
4259
4277
  }
4278
+
4279
+ // Check if : is on same line as ? (both should be on their own lines for multiline)
4280
+ if (!isCorrectionNeeded) {
4281
+ const questionToken = sourceCode.getTokenAfter(test, (t) => t.value === "?");
4282
+ const colonToken = sourceCode.getTokenAfter(node.consequent, (t) => t.value === ":");
4283
+
4284
+ if (questionToken && colonToken && questionToken.loc.start.line === colonToken.loc.start.line) {
4285
+ isCorrectionNeeded = true;
4286
+ }
4287
+ }
4288
+
4289
+ // Check if first operand is not on same line as parent property key
4290
+ if (!isCorrectionNeeded && parent && parent.type === "Property" && parent.value === node) {
4291
+ const keyEndLine = parent.key.loc.end.line;
4292
+ const firstOperandLine = operands[0].loc.start.line;
4293
+
4294
+ if (firstOperandLine !== keyEndLine) {
4295
+ isCorrectionNeeded = true;
4296
+ }
4297
+ }
4260
4298
  }
4261
4299
 
4262
4300
  if (isCorrectionNeeded) {
4263
4301
  context.report({
4264
4302
  fix: (fixer) => {
4265
- // Get the indentation based on where the ternary starts
4266
- const lineText = sourceCode.lines[node.loc.start.line - 1];
4267
- const baseIndent = lineText.match(/^\s*/)[0];
4303
+ // Get proper base indent
4304
+ let baseIndent;
4305
+ let includePropertyKey = false;
4306
+ let propertyKeyText = "";
4307
+
4308
+ // Check if parent is Property and value starts on different line
4309
+ if (parent && parent.type === "Property" && parent.value === node) {
4310
+ const keyEndLine = parent.key.loc.end.line;
4311
+ const firstOperandLine = operands[0].loc.start.line;
4312
+
4313
+ if (firstOperandLine !== keyEndLine) {
4314
+ // Need to include property key in fix
4315
+ includePropertyKey = true;
4316
+ propertyKeyText = sourceCode.getText(parent.key) + ": ";
4317
+ const propertyLineText = sourceCode.lines[parent.loc.start.line - 1];
4318
+
4319
+ baseIndent = propertyLineText.match(/^\s*/)[0];
4320
+ }
4321
+ }
4322
+
4323
+ if (!baseIndent) {
4324
+ const lineText = sourceCode.lines[node.loc.start.line - 1];
4325
+
4326
+ baseIndent = lineText.match(/^\s*/)[0];
4327
+ }
4328
+
4268
4329
  const conditionIndent = baseIndent + " ";
4269
4330
 
4270
4331
  const buildMultilineHandler = (n) => {
@@ -4281,9 +4342,17 @@ const ternaryConditionMultiline = {
4281
4342
  const consequentText = sourceCode.getText(node.consequent);
4282
4343
  const alternateText = sourceCode.getText(node.alternate);
4283
4344
 
4284
- // No leading newline - keep first operand on same line as whatever precedes it
4285
- // Use conditionIndent for ? and : to align with || operators
4286
- const newText = `${buildMultilineHandler(test)}\n${conditionIndent}? ${consequentText}\n${conditionIndent}: ${alternateText}`;
4345
+ // Build multiline with ? and : each on their own lines
4346
+ const conditionPart = buildMultilineHandler(test);
4347
+ const newText = `${conditionPart}\n${conditionIndent}? ${consequentText}\n${conditionIndent}: ${alternateText}`;
4348
+
4349
+ if (includePropertyKey) {
4350
+ // Replace the entire property value including fixing the key position
4351
+ return fixer.replaceTextRange(
4352
+ [parent.key.range[0], node.range[1]],
4353
+ `${propertyKeyText}${newText}`,
4354
+ );
4355
+ }
4287
4356
 
4288
4357
  return fixer.replaceText(node, newText);
4289
4358
  },
@@ -9747,10 +9816,10 @@ const noEmptyLinesInFunctionParams = {
9747
9816
  }
9748
9817
  }
9749
9818
 
9750
- // Find the closing brace of ObjectPattern
9751
- const closeBrace = sourceCode.getLastToken(param);
9819
+ // Find the closing brace of ObjectPattern (first } after last prop, not last token which could be from type annotation)
9820
+ const closeBrace = sourceCode.getTokenAfter(lastProp, (t) => t.value === "}");
9752
9821
 
9753
- if (closeBrace && closeBrace.value === "}") {
9822
+ if (closeBrace) {
9754
9823
  // Check for empty line before closing brace
9755
9824
  if (closeBrace.loc.start.line - lastProp.loc.end.line > 1) {
9756
9825
  context.report({
@@ -14993,7 +15062,7 @@ const noInlineTypeDefinitions = {
14993
15062
  const memberCount = countUnionMembersHandler(typeNode);
14994
15063
  const typeText = sourceCode.getText(typeNode);
14995
15064
 
14996
- if (memberCount > maxUnionMembers || typeText.length > maxLength) {
15065
+ if (memberCount >= maxUnionMembers || typeText.length > maxLength) {
14997
15066
  context.report({
14998
15067
  message: `Inline union type with ${memberCount} members is too complex. Extract to a named type in a types file.`,
14999
15068
  node: typeNode,
@@ -15023,7 +15092,7 @@ const noInlineTypeDefinitions = {
15023
15092
  const memberCount = countUnionMembersHandler(propType);
15024
15093
  const typeText = sourceCode.getText(propType);
15025
15094
 
15026
- if (memberCount > maxUnionMembers || typeText.length > maxLength) {
15095
+ if (memberCount >= maxUnionMembers || typeText.length > maxLength) {
15027
15096
  context.report({
15028
15097
  message: `Property "${propName}" has inline union type with ${memberCount} members. Extract to a named type in a types file.`,
15029
15098
  node: propType,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-code-style",
3
- "version": "1.7.3",
3
+ "version": "1.7.4",
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",