Skip to content

Commit 3080de7

Browse files
committed
feat(filename): enhance default excepts patterns and improve validation
- Add default excepts patterns for common framework files: - Files starting with underscore (_app.tsx, _layout.tsx) - Numeric files (404.tsx) - Square bracket files ([slug].tsx) - Improve validation logic to filter non-word/dash characters - Update documentation with excepts option details - Add comprehensive test cases for new exception patterns This enhances the filename rule to be more framework-agnostic and handles edge cases with special characters in filenames.
1 parent cd5befe commit 3080de7

File tree

4 files changed

+64
-21
lines changed

4 files changed

+64
-21
lines changed

.github/instructions/nx.instructions.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
applyTo: "**"
2+
applyTo: '**'
33
---
44

55
// This file is automatically generated by Nx Console
@@ -9,14 +9,12 @@ You are in an nx workspace using Nx 21.4.0 and pnpm as the package manager.
99
You have access to the Nx MCP server and the tools it provides. Use them. Follow these guidelines in order to best help the user:
1010

1111
# General Guidelines
12-
1312
- When answering questions, use the nx_workspace tool first to gain an understanding of the workspace architecture
1413
- For questions around nx configuration, best practices or if you're unsure, use the nx_docs tool to get relevant, up-to-date docs!! Always use this instead of assuming things about nx configuration
1514
- If the user needs help with an Nx configuration or project graph error, use the 'nx_workspace' tool to get any errors
1615
- To help answer questions about the workspace structure or simply help with demonstrating how tasks depend on each other, use the 'nx_visualize_graph' tool
1716

1817
# Generation Guidelines
19-
2018
If the user wants to generate something, use the following flow:
2119

2220
- learn about the nx workspace and any specifics the user needs by using the 'nx_workspace' tool and the 'nx_project_details' tool if applicable
@@ -31,11 +29,12 @@ If the user wants to generate something, use the following flow:
3129
- use the information provided in the log file to answer the user's question or continue with what they were doing
3230

3331
# Running Tasks Guidelines
34-
3532
If the user wants help with tasks or commands (which include keywords like "test", "build", "lint", or other similar actions), use the following flow:
36-
3733
- Use the 'nx_current_running_tasks_details' tool to get the list of tasks (this can include tasks that were completed, stopped or failed).
3834
- If there are any tasks, ask the user if they would like help with a specific task then use the 'nx_current_running_task_output' tool to get the terminal output for that task/command
3935
- Use the terminal output from 'nx_current_running_task_output' to see what's wrong and help the user fix their problem. Use the appropriate tools if necessary
4036
- If the user would like to rerun the task or command, always use `nx run <taskId>` to rerun in the terminal. This will ensure that the task will run in the nx context and will be run the same way it originally executed
41-
- If the task was marked as "continuous" do not offer to rerun the task. This task is already running and the user can see the output in the terminal. You can use 'nx_current_running_task_output' to get the output of the task to verify the output.
37+
- If the task was marked as "continuous" do not offer to rerun the task. This task is already running and the user can see the output in the terminal. You can use 'nx_current_running_task_output' to get the output of the task to verify the output.
38+
39+
40+

packages/plugins/eslint-plugin-react-naming-convention/src/rules/filename.md

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ src/components/example-component.tsx
6969
2. `camelCase`: camelCase
7070
3. `kebab-case`: kebab-case
7171
4. `snake_case`: snake_case
72+
- `excepts`: An array of regular expressions to ignore specific file names. Default is:
73+
- `"$"`: Ignore `$` files (e.g., `$.tsx`).
74+
- `"index"`: Ignore `index` files (e.g., `index.tsx`).
75+
- `"/^_/"`: Ignore files starting with an underscore (e.g., `_app.tsx`, `_layout.tsx`).
76+
- `"/^[0-9]+$/"`: Ignore files with only numbers (e.g., `404.tsx`).
77+
- `"/^\[[^\]]+\]$/"`: Ignore files with square brackets (e.g., `[slug].tsx`).
7278

7379
## Rule Options Examples
7480

@@ -103,23 +109,36 @@ export default [
103109
export default [
104110
// ...
105111
{
106-
files: ["src/**/*.{ts,tsx}"],
107-
ignore: ["**/index.{ts,tsx}"],
112+
files: ["src/components/**/*.{ts,tsx}"],
108113
rules: {
109114
"@eslint-react/naming-convention/filename": ["warn", "PascalCase"],
110115
},
111116
},
112117
{
113-
files: ["src/pages/**/*.{ts,tsx}"],
114-
ignore: ["**/index.{ts,tsx}"],
118+
files: ["src/hooks/**/use*.{ts,tsx}"],
119+
rules: {
120+
"@eslint-react/naming-convention/filename": ["warn", "camelCase"],
121+
},
122+
},
123+
];
124+
```
125+
126+
### Opting out of the rule for framework-specific files
127+
128+
```js title="eslint.config.js"
129+
// ...
130+
export default [
131+
// ...
132+
{
133+
files: ["**/*.{ts,tsx}"],
115134
rules: {
116135
"@eslint-react/naming-convention/filename": ["warn", "kebab-case"],
117136
},
118137
},
119138
{
120-
files: ["src/hooks/**/use*.{ts,tsx}"],
139+
files: ["app/**/*.{ts,tsx}"], // Opting out of the rule for framework-specific files
121140
rules: {
122-
"@eslint-react/naming-convention/filename": ["warn", "camelCase"],
141+
"@eslint-react/naming-convention/filename": "off",
123142
},
124143
},
125144
];

packages/plugins/eslint-plugin-react-naming-convention/src/rules/filename.spec.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,5 +151,25 @@ ruleTester.run(RULE_NAME, rule, {
151151
filename: "snake_case.tsx",
152152
options: [{ rule: "snake_case" }],
153153
},
154+
{
155+
code,
156+
filename: "404.tsx",
157+
options: [{ rule: "PascalCase" }],
158+
},
159+
{
160+
code,
161+
filename: "$.tsx",
162+
options: [{ rule: "PascalCase" }],
163+
},
164+
{
165+
code,
166+
filename: "_app.tsx",
167+
options: [{ rule: "PascalCase" }],
168+
},
169+
{
170+
code,
171+
filename: "[slug].tsx",
172+
options: [{ rule: "PascalCase" }],
173+
},
154174
],
155175
});

packages/plugins/eslint-plugin-react-naming-convention/src/rules/filename.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,13 @@ type Options = readonly [
3232

3333
const defaultOptions = [
3434
{
35-
excepts: ["^index$"],
35+
excepts: [
36+
"$",
37+
"index",
38+
"/^_/",
39+
"/^[0-9]+$/",
40+
"/^\\[[^\\]]+\\]$/",
41+
],
3642
rule: "PascalCase",
3743
},
3844
] as const satisfies Options;
@@ -95,15 +101,14 @@ export function create(context: RuleContext<MessageID, Options>): RuleListener {
95101
: (options.excepts ?? []).map((s) => RE.toRegExp(s));
96102

97103
function validate(name: string, casing: Case = rule, ignores = excepts) {
98-
const shouldIgnore = ignores
99-
.some((pattern) => pattern.test(name));
100-
if (shouldIgnore) return true;
101-
104+
if (ignores.some((pattern) => pattern.test(name))) return true;
105+
const filteredName = name.match(/[\w-]/gu)?.join("") ?? "";
106+
if (filteredName.length === 0) return false;
102107
return match(casing)
103-
.with("PascalCase", () => RE.PASCAL_CASE.test(name))
104-
.with("camelCase", () => RE.CAMEL_CASE.test(name))
105-
.with("kebab-case", () => RE.KEBAB_CASE.test(name))
106-
.with("snake_case", () => RE.SNAKE_CASE.test(name))
108+
.with("PascalCase", () => RE.PASCAL_CASE.test(filteredName))
109+
.with("camelCase", () => RE.CAMEL_CASE.test(filteredName))
110+
.with("kebab-case", () => RE.KEBAB_CASE.test(filteredName))
111+
.with("snake_case", () => RE.SNAKE_CASE.test(filteredName))
107112
.exhaustive();
108113
}
109114

0 commit comments

Comments
 (0)