eslint-plugin-code-style 1.17.0 → 1.17.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.
Files changed (3) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/index.js +63 -16
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
+ ## [1.17.1] - 2026-02-09
11
+
12
+ **Fix: Index File Behavior in Wrapped Folders**
13
+
14
+ **Version Range:** v1.17.0 → v1.17.1
15
+
16
+ ### Fixed
17
+
18
+ - **`index-exports-only`** - Enforce dual index file behavior for wrapped folder structure
19
+ - Root module index (`views/index.ts`) → barrel only (re-exports)
20
+ - Subfolder index (`views/assessment/index.tsx`) → must contain component code, not just re-exports
21
+ - Only one barrel per module — subfolder index files that simulate a barrel are flagged
22
+ - **`no-redundant-folder-suffix`** - Detect file name matching parent folder name (e.g., `assessment/assessment.tsx` → use `assessment/index.tsx`)
23
+
24
+ **Full Changelog:** [v1.17.0...v1.17.1](https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.17.0...v1.17.1)
25
+
26
+ ---
27
+
10
28
  ## [1.17.0] - 2026-02-09
11
29
 
12
30
  **New Rule + Enhancements to Naming & Import Rules**
@@ -1806,6 +1824,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1806
1824
 
1807
1825
  ---
1808
1826
 
1827
+ [1.17.1]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.17.0...v1.17.1
1809
1828
  [1.17.0]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.16.0...v1.17.0
1810
1829
  [1.16.0]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.15.0...v1.16.0
1811
1830
  [1.15.0]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.14.4...v1.15.0
package/index.js CHANGED
@@ -8022,23 +8022,37 @@ const indexExportsOnly = {
8022
8022
 
8023
8023
  if (!isIndexFile) return {};
8024
8024
 
8025
- // Helper to check if a node is an import or export statement
8026
- const isImportOrExportHandler = (node) => {
8025
+ // Determine if this is a subfolder index inside a module folder
8026
+ // e.g., views/assessment/index.tsx (depth >= 2 from module folder) = subfolder index
8027
+ // vs views/index.ts (depth == 1 from module folder) = root barrel
8028
+ const moduleFolders = [
8029
+ "actions", "apis", "assets", "atoms", "components", "config", "configs",
8030
+ "constants", "contexts", "data", "enums", "helpers", "hooks", "interfaces",
8031
+ "layouts", "lib", "middlewares", "pages", "providers", "reducers", "redux",
8032
+ "requests", "routes", "schemas", "services", "store", "strings", "styles",
8033
+ "theme", "themes", "thunks", "types", "ui", "utils", "utilities", "views",
8034
+ ];
8035
+ const parts = normalizedFilename.split("/");
8036
+ const indexPos = parts.length - 1;
8037
+ let isSubfolderIndex = false;
8038
+
8039
+ for (let i = 0; i < indexPos; i++) {
8040
+ if (moduleFolders.includes(parts[i])) {
8041
+ if (indexPos - i >= 2) isSubfolderIndex = true;
8042
+
8043
+ break;
8044
+ }
8045
+ }
8046
+
8047
+ // Helper to check if a node is an import or re-export (no inline declarations)
8048
+ const isImportOrReexportHandler = (node) => {
8027
8049
  const { type } = node;
8028
8050
 
8029
- // Import statements
8030
8051
  if (type === "ImportDeclaration") return true;
8031
8052
 
8032
- // Export statements (named, default, all)
8033
- if (type === "ExportNamedDeclaration") {
8034
- // Only allow re-exports (export { x } from "./module" or export { x })
8035
- // If it has a declaration, it's defining something (not allowed)
8036
- return !node.declaration;
8037
- }
8053
+ if (type === "ExportNamedDeclaration") return !node.declaration;
8038
8054
 
8039
8055
  if (type === "ExportDefaultDeclaration") {
8040
- // Allow export default <identifier> (re-exporting)
8041
- // Disallow export default function/class/object (defining something)
8042
8056
  return node.declaration && node.declaration.type === "Identifier";
8043
8057
  }
8044
8058
 
@@ -8047,6 +8061,21 @@ const indexExportsOnly = {
8047
8061
  return false;
8048
8062
  };
8049
8063
 
8064
+ // Helper to check if a node contains actual code (declarations, logic)
8065
+ const hasCodeDeclarationHandler = (node) => {
8066
+ const { type } = node;
8067
+
8068
+ if (type === "VariableDeclaration" || type === "FunctionDeclaration" || type === "ClassDeclaration") return true;
8069
+
8070
+ if (type === "ExportNamedDeclaration" && node.declaration) return true;
8071
+
8072
+ if (type === "ExportDefaultDeclaration") {
8073
+ return node.declaration && node.declaration.type !== "Identifier";
8074
+ }
8075
+
8076
+ return false;
8077
+ };
8078
+
8050
8079
  // Get a friendly description of what the disallowed node is
8051
8080
  const getNodeDescriptionHandler = (node) => {
8052
8081
  switch (node.type) {
@@ -8063,9 +8092,7 @@ const indexExportsOnly = {
8063
8092
  case "ClassDeclaration":
8064
8093
  return "Class declaration";
8065
8094
  case "ExportNamedDeclaration":
8066
- if (node.declaration) {
8067
- return getNodeDescriptionHandler(node.declaration);
8068
- }
8095
+ if (node.declaration) return getNodeDescriptionHandler(node.declaration);
8069
8096
 
8070
8097
  return "Export with inline declaration";
8071
8098
  case "ExportDefaultDeclaration":
@@ -8077,8 +8104,28 @@ const indexExportsOnly = {
8077
8104
 
8078
8105
  return {
8079
8106
  Program(programNode) {
8107
+ if (isSubfolderIndex) {
8108
+ // Subfolder index (e.g., views/assessment/index.tsx):
8109
+ // Must contain component code — must NOT be a barrel (re-exports only)
8110
+ // Only one barrel per module (the root index)
8111
+ const hasCode = programNode.body.some((node) => hasCodeDeclarationHandler(node));
8112
+
8113
+ if (!hasCode) {
8114
+ const subfolder = parts[indexPos - 1];
8115
+
8116
+ context.report({
8117
+ message: `Subfolder index file "${subfolder}/index" should contain component code, not just re-exports. Only the module root index file should be a barrel for imports and re-exports.`,
8118
+ node: programNode,
8119
+ });
8120
+ }
8121
+
8122
+ return;
8123
+ }
8124
+
8125
+ // Root module index (e.g., views/index.ts):
8126
+ // Must be barrel only — no code declarations allowed
8080
8127
  for (const node of programNode.body) {
8081
- if (!isImportOrExportHandler(node)) {
8128
+ if (!isImportOrReexportHandler(node)) {
8082
8129
  const description = getNodeDescriptionHandler(node);
8083
8130
 
8084
8131
  context.report({
@@ -8091,7 +8138,7 @@ const indexExportsOnly = {
8091
8138
  };
8092
8139
  },
8093
8140
  meta: {
8094
- docs: { description: "Index files should only contain imports and re-exports, not code definitions" },
8141
+ docs: { description: "Enforce index files as barrels (re-exports only) at module root, and as component entry points (with code) in subfolders" },
8095
8142
  schema: [],
8096
8143
  type: "suggestion",
8097
8144
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-code-style",
3
- "version": "1.17.0",
3
+ "version": "1.17.1",
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",