eslint-plugin-code-style 1.9.1 → 1.9.2

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 (4) hide show
  1. package/CHANGELOG.md +22 -6
  2. package/README.md +16 -8
  3. package/index.js +147 -26
  4. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,15 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
- ## [1.9.1] - 2026-02-03
10
+ ## [1.9.2] - 2026-02-03
11
11
 
12
12
  ### Enhanced
13
13
 
14
- - **`no-hardcoded-strings`** - Now detects additional hardcoded values:
15
- - HTTP status codes (4xx, 5xx like "404", "422", "500") with descriptive error message
16
- - Role/permission names ("admin", "user", "moderator", etc.) with descriptive error message
17
- - Added `@/data` as preferred import source for enums/objects
18
- - Improved error messages to mention all valid import sources
14
+ - **`no-hardcoded-strings`** - Now detects special strings that should be enums:
15
+ - HTTP status codes (2xx, 4xx, 5xx like "200", "404", "500")
16
+ - HTTP methods ("GET", "POST", "PUT", "DELETE", etc.)
17
+ - Role/permission names ("admin", "user", "moderator", etc.)
18
+ - Environment names ("production", "development", "staging", etc.)
19
+ - Log levels ("debug", "info", "warn", "error", etc.)
20
+ - Status strings ("active", "pending", "approved", "rejected", etc.)
21
+ - Priority levels ("high", "medium", "low", "critical", etc.)
22
+ - All above → import from `@/enums` or `@/data`
23
+ - Regular strings → import from `@/data or @/strings or @/constants or @/@constants or @/@strings`
19
24
 
20
25
  ### Fixed
21
26
 
@@ -23,6 +28,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
23
28
 
24
29
  ---
25
30
 
31
+ ## [1.9.1] - 2026-02-03
32
+
33
+ ### Enhanced
34
+
35
+ - **`no-hardcoded-strings`** - Initial special string detection:
36
+ - HTTP status codes (4xx, 5xx)
37
+ - Role/permission names
38
+
39
+ ---
40
+
26
41
  ## [1.9.0] - 2026-02-03
27
42
 
28
43
  **New Rule: class-method-definition-format + Enhanced Spacing Rules**
@@ -1260,6 +1275,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1260
1275
 
1261
1276
  ---
1262
1277
 
1278
+ [1.9.2]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.9.1...v1.9.2
1263
1279
  [1.9.1]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.9.0...v1.9.1
1264
1280
  [1.9.0]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.8.4...v1.9.0
1265
1281
  [1.8.4]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.8.3...v1.8.4
package/README.md CHANGED
@@ -3427,9 +3427,14 @@ const YetAnotherBad = ({ title }) => {
3427
3427
 
3428
3428
  **Why use it:** Hardcoded strings scattered throughout your codebase are hard to maintain, translate, and keep consistent. Centralizing strings in constants makes them easy to find, update, and potentially translate.
3429
3429
 
3430
- **Special detection:**
3431
- - **HTTP status codes** (4xx, 5xx like "404", "500") — should be imported from `@/data` as enums/objects
3432
- - **Role/permission names** ("admin", "user", "moderator", etc.) — should be imported from `@/data` as enums/objects
3430
+ **Special detection (should be imported from `@/enums` or `@/data`):**
3431
+ - **HTTP status codes** — 2xx, 4xx, 5xx like "200", "404", "500"
3432
+ - **HTTP methods** "GET", "POST", "PUT", "DELETE", "PATCH", etc.
3433
+ - **Role/permission names** — "admin", "user", "moderator", "editor", etc.
3434
+ - **Environment names** — "production", "development", "staging", "test", etc.
3435
+ - **Log levels** — "debug", "info", "warn", "error", "fatal", etc.
3436
+ - **Status strings** — "active", "pending", "approved", "rejected", "completed", etc.
3437
+ - **Priority levels** — "high", "medium", "low", "critical", "urgent", etc.
3433
3438
 
3434
3439
  **Options:**
3435
3440
 
@@ -3447,7 +3452,7 @@ const YetAnotherBad = ({ title }) => {
3447
3452
  // ✅ Good — strings imported from constants
3448
3453
  import { BUTTON_LABEL, ERROR_MESSAGE, welcomeText } from "@/constants";
3449
3454
  import { FORM_LABELS } from "@/strings";
3450
- import { HttpStatus, UserRole } from "@/data";
3455
+ import { HttpStatus, UserRole } from "@/enums";
3451
3456
 
3452
3457
  const ComponentHandler = () => (
3453
3458
  <div>
@@ -3490,11 +3495,14 @@ if (role === "admin") { ... }
3490
3495
  }]
3491
3496
  ```
3492
3497
 
3493
- **Valid import paths for constants:**
3494
- - `@/data` (preferred for enums/objects like HttpStatus, UserRole)
3495
- - `@/constants` or `@/@constants`
3498
+ **Valid import paths for strings:**
3499
+ - `@/data`
3496
3500
  - `@/strings` or `@/@strings`
3497
- - `@/data/constants` or `@/data/strings`
3501
+ - `@/constants` or `@/@constants`
3502
+
3503
+ **Valid import paths for enums (status codes, roles):**
3504
+ - `@/enums`
3505
+ - `@/data`
3498
3506
 
3499
3507
  ---
3500
3508
 
package/index.js CHANGED
@@ -13826,17 +13826,26 @@ const stringPropertySpacing = {
13826
13826
  * This promotes maintainability, consistency, and enables
13827
13827
  * easier internationalization.
13828
13828
  *
13829
- * The rule also detects:
13830
- * - HTTP status codes (4xx, 5xx) that should be imported from @/data or enums
13831
- * - Role/permission names (admin, user, moderator, etc.) that should be from @/data
13832
- *
13833
- * Valid import sources:
13834
- * - @/data (enums, objects)
13829
+ * The rule also detects special strings that should be enums:
13830
+ * - HTTP status codes (2xx, 4xx, 5xx like "200", "404", "500")
13831
+ * - HTTP methods ("GET", "POST", "PUT", "DELETE", etc.)
13832
+ * - Role/permission names ("admin", "user", "moderator", etc.)
13833
+ * - Environment names ("production", "development", "staging", etc.)
13834
+ * - Log levels ("debug", "info", "warn", "error", etc.)
13835
+ * - Status strings ("active", "pending", "approved", "rejected", etc.)
13836
+ * - Priority levels ("high", "medium", "low", "critical", etc.)
13837
+ *
13838
+ * Valid import sources for strings:
13839
+ * - @/data
13835
13840
  * - @/strings
13836
13841
  * - @/constants
13837
13842
  * - @/@strings
13838
13843
  * - @/@constants
13839
13844
  *
13845
+ * Valid import sources for enums:
13846
+ * - @/enums
13847
+ * - @/data
13848
+ *
13840
13849
  * Options:
13841
13850
  * { ignoreAttributes: ["className", "id", ...] } - JSX attributes to ignore (replaces defaults)
13842
13851
  * { extraIgnoreAttributes: ["tooltip", ...] } - Additional JSX attributes to ignore (extends defaults)
@@ -13845,7 +13854,7 @@ const stringPropertySpacing = {
13845
13854
  * ✓ Good:
13846
13855
  * import { BUTTON_LABEL, ERROR_MESSAGE } from "@/constants";
13847
13856
  * import { welcomeText } from "@/strings";
13848
- * import { HttpStatus, UserRole } from "@/data";
13857
+ * import { HttpStatus, UserRole } from "@/enums";
13849
13858
  *
13850
13859
  * <button>{BUTTON_LABEL}</button>
13851
13860
  * <span>{ERROR_MESSAGE}</span>
@@ -14052,8 +14061,6 @@ const noHardcodedStrings = {
14052
14061
  /^[A-Z][A-Z0-9_]*$/,
14053
14062
  // Common technical strings
14054
14063
  /^(true|false|null|undefined|NaN|Infinity)$/,
14055
- // HTTP methods
14056
- /^(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS|CONNECT|TRACE)$/,
14057
14064
  // Content types
14058
14065
  /^application\//,
14059
14066
  // Environment variables pattern
@@ -14082,10 +14089,10 @@ const noHardcodedStrings = {
14082
14089
 
14083
14090
  const allIgnorePatterns = [...technicalPatterns, ...extraIgnorePatterns];
14084
14091
 
14085
- // HTTP status codes that should NOT be hardcoded (4xx and 5xx error codes)
14086
- const httpStatusCodePattern = /^[45]\d{2}$/;
14092
+ // HTTP status codes that should NOT be hardcoded (2xx, 4xx, and 5xx)
14093
+ const httpStatusCodePattern = /^[245]\d{2}$/;
14087
14094
 
14088
- // Common role/permission names that should be imported from data/enums
14095
+ // Common role/permission names that should be imported from enums/data
14089
14096
  const rolePermissionNames = new Set([
14090
14097
  "admin",
14091
14098
  "administrator",
@@ -14104,14 +14111,107 @@ const noHardcodedStrings = {
14104
14111
  "viewer",
14105
14112
  ]);
14106
14113
 
14107
- // Check if string looks like an HTTP status code
14108
- const isHttpStatusCodeHandler = (str) => httpStatusCodePattern.test(str);
14114
+ // HTTP methods that should be imported from enums/data
14115
+ const httpMethods = new Set([
14116
+ "CONNECT",
14117
+ "DELETE",
14118
+ "GET",
14119
+ "HEAD",
14120
+ "OPTIONS",
14121
+ "PATCH",
14122
+ "POST",
14123
+ "PUT",
14124
+ "TRACE",
14125
+ ]);
14126
+
14127
+ // Environment names that should be imported from enums/data
14128
+ const environmentNames = new Set([
14129
+ "dev",
14130
+ "development",
14131
+ "local",
14132
+ "prod",
14133
+ "production",
14134
+ "qa",
14135
+ "sandbox",
14136
+ "staging",
14137
+ "test",
14138
+ "testing",
14139
+ "uat",
14140
+ ]);
14141
+
14142
+ // Log levels that should be imported from enums/data
14143
+ const logLevels = new Set([
14144
+ "debug",
14145
+ "error",
14146
+ "fatal",
14147
+ "info",
14148
+ "log",
14149
+ "trace",
14150
+ "warn",
14151
+ "warning",
14152
+ ]);
14153
+
14154
+ // Status/state strings that should be imported from enums/data
14155
+ const statusStrings = new Set([
14156
+ "accepted",
14157
+ "active",
14158
+ "approved",
14159
+ "archived",
14160
+ "blocked",
14161
+ "cancelled",
14162
+ "closed",
14163
+ "completed",
14164
+ "declined",
14165
+ "deleted",
14166
+ "disabled",
14167
+ "draft",
14168
+ "enabled",
14169
+ "expired",
14170
+ "failed",
14171
+ "inactive",
14172
+ "open",
14173
+ "paused",
14174
+ "pending",
14175
+ "processing",
14176
+ "published",
14177
+ "rejected",
14178
+ "resolved",
14179
+ "scheduled",
14180
+ "submitted",
14181
+ "success",
14182
+ "suspended",
14183
+ "verified",
14184
+ ]);
14185
+
14186
+ // Priority levels that should be imported from enums/data
14187
+ const priorityLevels = new Set([
14188
+ "critical",
14189
+ "high",
14190
+ "highest",
14191
+ "low",
14192
+ "lowest",
14193
+ "medium",
14194
+ "normal",
14195
+ "urgent",
14196
+ ]);
14109
14197
 
14110
- // Check if string is a role/permission name
14198
+ // Check functions for each category
14199
+ const isHttpStatusCodeHandler = (str) => httpStatusCodePattern.test(str);
14111
14200
  const isRoleNameHandler = (str) => rolePermissionNames.has(str.toLowerCase());
14201
+ const isHttpMethodHandler = (str) => httpMethods.has(str.toUpperCase());
14202
+ const isEnvironmentNameHandler = (str) => environmentNames.has(str.toLowerCase());
14203
+ const isLogLevelHandler = (str) => logLevels.has(str.toLowerCase());
14204
+ const isStatusStringHandler = (str) => statusStrings.has(str.toLowerCase());
14205
+ const isPriorityLevelHandler = (str) => priorityLevels.has(str.toLowerCase());
14112
14206
 
14113
14207
  // Check if string should be flagged even if it matches technical patterns
14114
- const isFlaggedSpecialStringHandler = (str) => isHttpStatusCodeHandler(str) || isRoleNameHandler(str);
14208
+ const isFlaggedSpecialStringHandler = (str) => isHttpStatusCodeHandler(str)
14209
+ || isRoleNameHandler(str)
14210
+ || isHttpMethodHandler(str)
14211
+ || isEnvironmentNameHandler(str)
14212
+ || isLogLevelHandler(str)
14213
+ || isStatusStringHandler(str)
14214
+ || isPriorityLevelHandler(str);
14115
14215
 
14116
14216
  // Get descriptive error message based on string type
14117
14217
  const getErrorMessageHandler = (str, context = "") => {
@@ -14119,14 +14219,34 @@ const noHardcodedStrings = {
14119
14219
  const contextPart = context ? ` in ${context}` : "";
14120
14220
 
14121
14221
  if (isHttpStatusCodeHandler(str)) {
14122
- return `Hardcoded HTTP status code "${truncatedStr}"${contextPart} should be imported from @/data (enum/object) or @/constants`;
14222
+ return `Hardcoded HTTP status code "${truncatedStr}"${contextPart} should be imported from @/enums or @/data`;
14123
14223
  }
14124
14224
 
14125
14225
  if (isRoleNameHandler(str)) {
14126
- return `Hardcoded role/permission "${truncatedStr}"${contextPart} should be imported from @/data (enum/object) or @/constants`;
14226
+ return `Hardcoded role/permission "${truncatedStr}"${contextPart} should be imported from @/enums or @/data`;
14227
+ }
14228
+
14229
+ if (isHttpMethodHandler(str)) {
14230
+ return `Hardcoded HTTP method "${truncatedStr}"${contextPart} should be imported from @/enums or @/data`;
14231
+ }
14232
+
14233
+ if (isEnvironmentNameHandler(str)) {
14234
+ return `Hardcoded environment name "${truncatedStr}"${contextPart} should be imported from @/enums or @/data`;
14235
+ }
14236
+
14237
+ if (isLogLevelHandler(str)) {
14238
+ return `Hardcoded log level "${truncatedStr}"${contextPart} should be imported from @/enums or @/data`;
14239
+ }
14240
+
14241
+ if (isStatusStringHandler(str)) {
14242
+ return `Hardcoded status "${truncatedStr}"${contextPart} should be imported from @/enums or @/data`;
14243
+ }
14244
+
14245
+ if (isPriorityLevelHandler(str)) {
14246
+ return `Hardcoded priority level "${truncatedStr}"${contextPart} should be imported from @/enums or @/data`;
14127
14247
  }
14128
14248
 
14129
- return `Hardcoded string "${truncatedStr}"${contextPart} should be imported from @/data, @/strings, @/constants, or constants module`;
14249
+ return `Hardcoded string "${truncatedStr}"${contextPart} should be imported from @/data or @/strings or @/constants or @/@constants or @/@strings`;
14130
14250
  };
14131
14251
 
14132
14252
  // Check if a string matches any ignore pattern (but not if it's a flagged special string)
@@ -14137,13 +14257,13 @@ const noHardcodedStrings = {
14137
14257
  return allIgnorePatterns.some((pattern) => pattern.test(str));
14138
14258
  };
14139
14259
 
14140
- // Check if we're inside a constants/strings/data file
14260
+ // Check if we're inside a constants/strings/data/enums file
14141
14261
  const isConstantsFileHandler = () => {
14142
14262
  const filename = context.filename || context.getFilename();
14143
14263
  const normalizedPath = filename.replace(/\\/g, "/").toLowerCase();
14144
14264
 
14145
- // Check if file is in constants/strings/data folders
14146
- return /\/(constants|strings|@constants|@strings|data|@data)(\/|\.)/i.test(normalizedPath)
14265
+ // Check if file is in constants/strings/data/enums folders
14266
+ return /\/(constants|strings|@constants|@strings|data|@data|enums|@enums)(\/|\.)/i.test(normalizedPath)
14147
14267
  || /\/data\/(constants|strings)/i.test(normalizedPath);
14148
14268
  };
14149
14269
 
@@ -14156,8 +14276,8 @@ const noHardcodedStrings = {
14156
14276
 
14157
14277
  if (typeof importPath !== "string") return;
14158
14278
 
14159
- // Check if import is from constants/strings/data
14160
- const isFromConstants = /@?\/?(@?constants|@?strings|@?data|data\/constants|data\/strings)/i
14279
+ // Check if import is from constants/strings/data/enums
14280
+ const isFromConstants = /@?\/?(@?constants|@?strings|@?data|@?enums|data\/constants|data\/strings)/i
14161
14281
  .test(importPath);
14162
14282
 
14163
14283
  if (isFromConstants) {
@@ -14255,8 +14375,9 @@ const noHardcodedStrings = {
14255
14375
  return true;
14256
14376
  }
14257
14377
 
14258
- // Check for keywords that suggest constants (case-insensitive)
14259
- if (/CONSTANTS?|STRINGS?|MESSAGES?|LABELS?|TEXTS?|DATA$/i.test(varName)) {
14378
+ // Check for exact keywords or keywords at word boundaries (not in Handler names)
14379
+ // Match: MESSAGES, Messages, userMessages, but NOT longMessageHandler
14380
+ if (/^(constants?|strings?|messages?|labels?|texts?|data)$/i.test(varName)) {
14260
14381
  return true;
14261
14382
  }
14262
14383
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-code-style",
3
- "version": "1.9.1",
3
+ "version": "1.9.2",
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",