eslint-plugin-react-naming-convention 1.26.3-beta.2 → 1.26.3-beta.21

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.
package/README.md CHANGED
@@ -2,9 +2,6 @@
2
2
 
3
3
  Naming convention rules.
4
4
 
5
- > [!NOTE]
6
- > This plugin is already included in `@eslint-react/eslint-plugin`. You don't need to install it separately if you are using `@eslint-react/eslint-plugin`.
7
-
8
5
  ## Install
9
6
 
10
7
  ```sh
package/dist/index.d.mts CHANGED
@@ -1,33 +1,74 @@
1
1
  import * as _typescript_eslint_utils_ts_eslint from '@typescript-eslint/utils/ts-eslint';
2
+ import { RulePreset } from '@eslint-react/shared';
2
3
 
3
- type MessageID$1 = "filenameExtensionInvalid" | "filenameExtensionUnexpected";
4
+ type MessageID$2 = "useJsxFileExtension" | "useJsxFileExtensionAsNeeded";
4
5
 
5
- type MessageID = "filenameCaseMismatchSuggestion" | "filenameEmpty";
6
+ type MessageID$1 = "filenameCaseMismatch" | "filenameEmpty";
7
+
8
+ type MessageID = "usePascalCase" | "useConstantCase";
6
9
 
7
10
  declare const _default: {
8
- readonly meta: {
11
+ configs: {
12
+ recommended: {
13
+ plugins: {
14
+ "react-naming-convention": {
15
+ readonly meta: {
16
+ readonly name: string;
17
+ readonly version: string;
18
+ };
19
+ readonly rules: {
20
+ readonly "component-name": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID, readonly [("CONSTANT_CASE" | "PascalCase") | {
21
+ allowAllCaps?: boolean;
22
+ allowLeadingUnderscore?: boolean;
23
+ allowNamespace?: boolean;
24
+ excepts?: readonly string[];
25
+ rule?: "CONSTANT_CASE" | "PascalCase";
26
+ } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
27
+ readonly filename: _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$1, readonly [("PascalCase" | "camelCase" | "kebab-case" | "snake_case") | {
28
+ excepts?: readonly string[];
29
+ extensions?: readonly string[];
30
+ rule?: "PascalCase" | "camelCase" | "kebab-case" | "snake_case";
31
+ } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
32
+ readonly "filename-extension": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$2, readonly [("always" | "as-needed") | {
33
+ allow?: "always" | "as-needed";
34
+ extensions?: readonly string[];
35
+ ignoreFilesWithoutCode?: boolean;
36
+ } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
37
+ readonly "use-state": _typescript_eslint_utils_ts_eslint.RuleModule<"unexpected", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
38
+ };
39
+ };
40
+ };
41
+ name: string;
42
+ rules: RulePreset;
43
+ };
44
+ "recommended-legacy": {
45
+ plugins: string[];
46
+ rules: RulePreset;
47
+ };
48
+ };
49
+ meta: {
9
50
  readonly name: string;
10
51
  readonly version: string;
11
52
  };
12
- readonly rules: {
13
- readonly "component-name": _typescript_eslint_utils_ts_eslint.RuleModule<"componentName", readonly [("CONSTANT_CASE" | "PascalCase") | {
53
+ rules: {
54
+ readonly "component-name": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID, readonly [("CONSTANT_CASE" | "PascalCase") | {
14
55
  allowAllCaps?: boolean;
15
56
  allowLeadingUnderscore?: boolean;
16
57
  allowNamespace?: boolean;
17
58
  excepts?: readonly string[];
18
59
  rule?: "CONSTANT_CASE" | "PascalCase";
19
60
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
20
- readonly filename: _typescript_eslint_utils_ts_eslint.RuleModule<MessageID, readonly [("PascalCase" | "camelCase" | "kebab-case" | "snake_case") | {
61
+ readonly filename: _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$1, readonly [("PascalCase" | "camelCase" | "kebab-case" | "snake_case") | {
21
62
  excepts?: readonly string[];
22
63
  extensions?: readonly string[];
23
64
  rule?: "PascalCase" | "camelCase" | "kebab-case" | "snake_case";
24
65
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
25
- readonly "filename-extension": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$1, readonly [("always" | "as-needed") | {
66
+ readonly "filename-extension": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$2, readonly [("always" | "as-needed") | {
26
67
  allow?: "always" | "as-needed";
27
68
  extensions?: readonly string[];
28
69
  ignoreFilesWithoutCode?: boolean;
29
70
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
30
- readonly "use-state": _typescript_eslint_utils_ts_eslint.RuleModule<"useState", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
71
+ readonly "use-state": _typescript_eslint_utils_ts_eslint.RuleModule<"unexpected", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
31
72
  };
32
73
  };
33
74
 
package/dist/index.d.ts CHANGED
@@ -1,33 +1,74 @@
1
1
  import * as _typescript_eslint_utils_ts_eslint from '@typescript-eslint/utils/ts-eslint';
2
+ import { RulePreset } from '@eslint-react/shared';
2
3
 
3
- type MessageID$1 = "filenameExtensionInvalid" | "filenameExtensionUnexpected";
4
+ type MessageID$2 = "useJsxFileExtension" | "useJsxFileExtensionAsNeeded";
4
5
 
5
- type MessageID = "filenameCaseMismatchSuggestion" | "filenameEmpty";
6
+ type MessageID$1 = "filenameCaseMismatch" | "filenameEmpty";
7
+
8
+ type MessageID = "usePascalCase" | "useConstantCase";
6
9
 
7
10
  declare const _default: {
8
- readonly meta: {
11
+ configs: {
12
+ recommended: {
13
+ plugins: {
14
+ "react-naming-convention": {
15
+ readonly meta: {
16
+ readonly name: string;
17
+ readonly version: string;
18
+ };
19
+ readonly rules: {
20
+ readonly "component-name": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID, readonly [("CONSTANT_CASE" | "PascalCase") | {
21
+ allowAllCaps?: boolean;
22
+ allowLeadingUnderscore?: boolean;
23
+ allowNamespace?: boolean;
24
+ excepts?: readonly string[];
25
+ rule?: "CONSTANT_CASE" | "PascalCase";
26
+ } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
27
+ readonly filename: _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$1, readonly [("PascalCase" | "camelCase" | "kebab-case" | "snake_case") | {
28
+ excepts?: readonly string[];
29
+ extensions?: readonly string[];
30
+ rule?: "PascalCase" | "camelCase" | "kebab-case" | "snake_case";
31
+ } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
32
+ readonly "filename-extension": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$2, readonly [("always" | "as-needed") | {
33
+ allow?: "always" | "as-needed";
34
+ extensions?: readonly string[];
35
+ ignoreFilesWithoutCode?: boolean;
36
+ } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
37
+ readonly "use-state": _typescript_eslint_utils_ts_eslint.RuleModule<"unexpected", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
38
+ };
39
+ };
40
+ };
41
+ name: string;
42
+ rules: RulePreset;
43
+ };
44
+ "recommended-legacy": {
45
+ plugins: string[];
46
+ rules: RulePreset;
47
+ };
48
+ };
49
+ meta: {
9
50
  readonly name: string;
10
51
  readonly version: string;
11
52
  };
12
- readonly rules: {
13
- readonly "component-name": _typescript_eslint_utils_ts_eslint.RuleModule<"componentName", readonly [("CONSTANT_CASE" | "PascalCase") | {
53
+ rules: {
54
+ readonly "component-name": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID, readonly [("CONSTANT_CASE" | "PascalCase") | {
14
55
  allowAllCaps?: boolean;
15
56
  allowLeadingUnderscore?: boolean;
16
57
  allowNamespace?: boolean;
17
58
  excepts?: readonly string[];
18
59
  rule?: "CONSTANT_CASE" | "PascalCase";
19
60
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
20
- readonly filename: _typescript_eslint_utils_ts_eslint.RuleModule<MessageID, readonly [("PascalCase" | "camelCase" | "kebab-case" | "snake_case") | {
61
+ readonly filename: _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$1, readonly [("PascalCase" | "camelCase" | "kebab-case" | "snake_case") | {
21
62
  excepts?: readonly string[];
22
63
  extensions?: readonly string[];
23
64
  rule?: "PascalCase" | "camelCase" | "kebab-case" | "snake_case";
24
65
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
25
- readonly "filename-extension": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$1, readonly [("always" | "as-needed") | {
66
+ readonly "filename-extension": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$2, readonly [("always" | "as-needed") | {
26
67
  allow?: "always" | "as-needed";
27
68
  extensions?: readonly string[];
28
69
  ignoreFilesWithoutCode?: boolean;
29
70
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
30
- readonly "use-state": _typescript_eslint_utils_ts_eslint.RuleModule<"useState", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
71
+ readonly "use-state": _typescript_eslint_utils_ts_eslint.RuleModule<"unexpected", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
31
72
  };
32
73
  };
33
74
 
package/dist/index.js CHANGED
@@ -34,9 +34,24 @@ var AST__namespace = /*#__PURE__*/_interopNamespace(AST);
34
34
  var JSX__namespace = /*#__PURE__*/_interopNamespace(JSX);
35
35
  var path__default = /*#__PURE__*/_interopDefault(path);
36
36
 
37
+ var __defProp = Object.defineProperty;
38
+ var __export = (target, all) => {
39
+ for (var name3 in all)
40
+ __defProp(target, name3, { get: all[name3], enumerable: true });
41
+ };
42
+
43
+ // src/configs/recommended.ts
44
+ var recommended_exports = {};
45
+ __export(recommended_exports, {
46
+ name: () => name,
47
+ rules: () => rules
48
+ });
49
+ var name = "react-naming-convention/recommended";
50
+ var rules = {};
51
+
37
52
  // package.json
38
- var name = "eslint-plugin-react-naming-convention";
39
- var version = "1.26.3-beta.2";
53
+ var name2 = "eslint-plugin-react-naming-convention";
54
+ var version = "1.26.3-beta.21";
40
55
  var createRule = shared.createRuleForPlugin("naming-convention");
41
56
 
42
57
  // src/rules/component-name.ts
@@ -90,26 +105,32 @@ function normalizeOptions(options) {
90
105
  excepts: opts.excepts?.map((pattern) => new RegExp(pattern, "u")) ?? []
91
106
  };
92
107
  }
93
- function validate(name2, options) {
94
- if (name2 == null) return false;
95
- if (options.excepts.some((regex) => regex.test(name2))) {
96
- return true;
108
+ function getViolationMessage(name3, options) {
109
+ if (name3 == null) return eff._;
110
+ const {
111
+ allowAllCaps = false,
112
+ allowLeadingUnderscore = false,
113
+ allowNamespace = false,
114
+ excepts,
115
+ rule
116
+ } = options;
117
+ if (excepts.some((regex) => regex.test(name3))) {
118
+ return eff._;
97
119
  }
98
- let normalized = name2.normalize("NFKD").replace(/[\u0300-\u036F]/g, "");
120
+ let normalized = name3.normalize("NFKD").replace(/[\u0300-\u036F]/g, "");
99
121
  normalized = normalized.split(".").at(-1) ?? normalized;
100
- const { allowLeadingUnderscore = false, allowNamespace = false } = options;
101
122
  if (allowNamespace) {
102
123
  normalized = normalized.replace(":", "");
103
124
  }
104
125
  if (allowLeadingUnderscore) {
105
126
  normalized = normalized.replace(/^_/, "");
106
127
  }
107
- return tsPattern.match(options.rule).with("CONSTANT_CASE", () => shared.RE_CONSTANT_CASE.test(normalized)).with("PascalCase", () => {
128
+ return tsPattern.match(rule).with("CONSTANT_CASE", () => shared.RE_CONSTANT_CASE.test(normalized) ? eff._ : "useConstantCase").with("PascalCase", () => {
108
129
  if (normalized.length > 3 && /^[A-Z]+$/u.test(normalized)) {
109
- return options.allowAllCaps ?? false;
130
+ return allowAllCaps ? eff._ : "usePascalCase";
110
131
  }
111
- return shared.RE_PASCAL_CASE.test(normalized);
112
- }).otherwise(eff.constFalse);
132
+ return shared.RE_PASCAL_CASE.test(normalized) ? eff._ : "usePascalCase";
133
+ }).otherwise(() => eff._);
113
134
  }
114
135
  var component_name_default = createRule({
115
136
  meta: {
@@ -119,7 +140,8 @@ var component_name_default = createRule({
119
140
  description: "enforce component naming convention to 'PascalCase' or 'CONSTANT_CASE'"
120
141
  },
121
142
  messages: {
122
- componentName: "A component name must be in {{case}}."
143
+ useConstantCase: "Component name '{{name}}' must be in CONSTANT_CASE.",
144
+ usePascalCase: "Component name '{{name}}' must be in PascalCase."
123
145
  },
124
146
  schema
125
147
  },
@@ -132,18 +154,17 @@ var component_name_default = createRule({
132
154
  ...collector.listeners,
133
155
  ...collectorLegacy.listeners,
134
156
  JSXOpeningElement(node) {
135
- const name2 = JSX__namespace.getElementName(node.parent);
136
- if (/^[a-z]/u.test(name2)) {
137
- return;
138
- }
139
- if (validate(name2, options)) {
157
+ const name3 = JSX__namespace.getElementName(node.parent);
158
+ if (/^[a-z]/u.test(name3)) {
140
159
  return;
141
160
  }
161
+ const violation = getViolationMessage(name3, options);
162
+ if (violation == null) return;
142
163
  context.report({
143
- messageId: "componentName",
164
+ messageId: violation,
144
165
  node,
145
166
  data: {
146
- case: options.rule
167
+ name: name3
147
168
  }
148
169
  });
149
170
  },
@@ -153,29 +174,30 @@ var component_name_default = createRule({
153
174
  for (const { node: component } of functionComponents.values()) {
154
175
  const id = AST__namespace.getFunctionIdentifier(component);
155
176
  if (id?.name == null) continue;
156
- if (validate(id.name, options)) {
157
- continue;
158
- }
177
+ const name3 = id.name;
178
+ const violation = getViolationMessage(name3, options);
179
+ if (violation == null) continue;
159
180
  context.report({
160
- messageId: "componentName",
181
+ messageId: violation,
161
182
  node: id,
162
183
  data: {
163
- case: options.rule
184
+ name: name3
164
185
  }
165
186
  });
166
187
  }
167
188
  for (const { node: component } of classComponents.values()) {
168
189
  const id = AST__namespace.getClassIdentifier(component);
169
190
  if (id?.name == null) continue;
170
- if (!validate(id.name, options)) {
171
- context.report({
172
- messageId: "componentName",
173
- node: id,
174
- data: {
175
- case: options.rule
176
- }
177
- });
178
- }
191
+ const name3 = id.name;
192
+ const violation = getViolationMessage(name3, options);
193
+ if (violation == null) continue;
194
+ context.report({
195
+ messageId: violation,
196
+ node: id,
197
+ data: {
198
+ case: options.rule
199
+ }
200
+ });
179
201
  }
180
202
  }
181
203
  };
@@ -227,8 +249,7 @@ var filename_default = createRule({
227
249
  description: "enforce naming convention for JSX filenames"
228
250
  },
229
251
  messages: {
230
- // filenameCaseMismatch: "A file with name '{{name}}' does not match {{rule}}.",
231
- filenameCaseMismatchSuggestion: "A file with name '{{name}}' does not match {{rule}}. Should rename to '{{suggestion}}'.",
252
+ filenameCaseMismatch: "A file with name '{{name}}' does not match {{rule}}. Should rename to '{{suggestion}}'.",
232
253
  filenameEmpty: "A file must have non-empty name."
233
254
  },
234
255
  schema: schema2
@@ -238,13 +259,13 @@ var filename_default = createRule({
238
259
  const options = context.options[0] ?? defaultOptions2[0];
239
260
  const rule = typeof options === "string" ? options : options.rule ?? "PascalCase";
240
261
  const excepts = typeof options === "string" ? [] : options.excepts ?? [];
241
- function validate2(name2, casing = rule, ignores = excepts) {
242
- const shouldIgnore = ignores.map((pattern) => new RegExp(pattern, "u")).some((pattern) => pattern.test(name2));
262
+ function validate(name3, casing = rule, ignores = excepts) {
263
+ const shouldIgnore = ignores.map((pattern) => new RegExp(pattern, "u")).some((pattern) => pattern.test(name3));
243
264
  if (shouldIgnore) return true;
244
- return tsPattern.match(casing).with("PascalCase", () => shared.RE_PASCAL_CASE.test(name2)).with("camelCase", () => shared.RE_CAMEL_CASE.test(name2)).with("kebab-case", () => shared.RE_KEBAB_CASE.test(name2)).with("snake_case", () => shared.RE_SNAKE_CASE.test(name2)).exhaustive();
265
+ return tsPattern.match(casing).with("PascalCase", () => shared.RE_PASCAL_CASE.test(name3)).with("camelCase", () => shared.RE_CAMEL_CASE.test(name3)).with("kebab-case", () => shared.RE_KEBAB_CASE.test(name3)).with("snake_case", () => shared.RE_SNAKE_CASE.test(name3)).exhaustive();
245
266
  }
246
- function getSuggestion(name2, casing = rule) {
247
- return tsPattern.match(casing).with("PascalCase", () => stringTs.pascalCase(name2)).with("camelCase", () => stringTs.camelCase(name2)).with("kebab-case", () => stringTs.kebabCase(name2)).with("snake_case", () => stringTs.snakeCase(name2)).exhaustive();
267
+ function getSuggestion(name3, casing = rule) {
268
+ return tsPattern.match(casing).with("PascalCase", () => stringTs.pascalCase(name3)).with("camelCase", () => stringTs.camelCase(name3)).with("kebab-case", () => stringTs.kebabCase(name3)).with("snake_case", () => stringTs.snakeCase(name3)).exhaustive();
248
269
  }
249
270
  return {
250
271
  Program(node) {
@@ -253,11 +274,11 @@ var filename_default = createRule({
253
274
  context.report({ messageId: "filenameEmpty", node });
254
275
  return;
255
276
  }
256
- if (validate2(basename)) {
277
+ if (validate(basename)) {
257
278
  return;
258
279
  }
259
280
  context.report({
260
- messageId: "filenameCaseMismatchSuggestion",
281
+ messageId: "filenameCaseMismatch",
261
282
  node,
262
283
  data: {
263
284
  name: context.filename,
@@ -314,8 +335,8 @@ var filename_extension_default = createRule({
314
335
  description: "enforce naming convention for JSX file extensions"
315
336
  },
316
337
  messages: {
317
- filenameExtensionInvalid: "The JSX file extension is required.",
318
- filenameExtensionUnexpected: "Use JSX file extension as needed."
338
+ useJsxFileExtension: "Use {{extensions}} file extension for JSX files.",
339
+ useJsxFileExtensionAsNeeded: "Do not use {{extensions}} file extension for files without JSX."
319
340
  },
320
341
  schema: schema3
321
342
  },
@@ -324,6 +345,7 @@ var filename_extension_default = createRule({
324
345
  const options = context.options[0] ?? defaultOptions3[0];
325
346
  const allow = eff.isObject(options) ? options.allow : options;
326
347
  const extensions = eff.isObject(options) && "extensions" in options ? options.extensions : defaultOptions3[0].extensions;
348
+ const extensionsString = extensions.map((ext) => `'${ext}'`).join(", ");
327
349
  const filename = context.filename;
328
350
  let hasJSXNode = false;
329
351
  return {
@@ -338,8 +360,11 @@ var filename_extension_default = createRule({
338
360
  const isJSXExt = extensions.includes(fileNameExt);
339
361
  if (hasJSXNode && !isJSXExt) {
340
362
  context.report({
341
- messageId: "filenameExtensionInvalid",
342
- node
363
+ messageId: "useJsxFileExtension",
364
+ node,
365
+ data: {
366
+ extensions: extensionsString
367
+ }
343
368
  });
344
369
  return;
345
370
  }
@@ -350,8 +375,11 @@ var filename_extension_default = createRule({
350
375
  }
351
376
  if (!hasJSXNode && isJSXExt && allow === "as-needed") {
352
377
  context.report({
353
- messageId: "filenameExtensionUnexpected",
354
- node
378
+ messageId: "useJsxFileExtensionAsNeeded",
379
+ node,
380
+ data: {
381
+ extensions: extensionsString
382
+ }
355
383
  });
356
384
  }
357
385
  }
@@ -363,19 +391,19 @@ var RULE_NAME4 = "use-state";
363
391
  var RULE_FEATURES = [
364
392
  "CHK"
365
393
  ];
366
- function isSetterNameLoose(name2) {
367
- const fourthChar = [...name2][3];
368
- return name2.startsWith("set") && fourthChar === fourthChar?.toUpperCase();
394
+ function isSetterNameLoose(name3) {
395
+ const fourthChar = [...name3][3];
396
+ return name3.startsWith("set") && fourthChar === fourthChar?.toUpperCase();
369
397
  }
370
398
  var use_state_default = createRule({
371
399
  meta: {
372
400
  type: "problem",
373
401
  docs: {
374
- description: "enforce destructuring and symmetric naming of 'useState' hook value and setter variables",
402
+ description: "enforce destructuring and symmetric naming of 'useState' hook value and setter",
375
403
  [Symbol.for("rule_features")]: RULE_FEATURES
376
404
  },
377
405
  messages: {
378
- useState: "An useState call is not destructured into value + setter pair."
406
+ unexpected: "An useState call is not destructured into value + setter pair."
379
407
  },
380
408
  schema: []
381
409
  },
@@ -411,14 +439,14 @@ var use_state_default = createRule({
411
439
  const { id } = hookCall.parent;
412
440
  switch (id.type) {
413
441
  case types.AST_NODE_TYPES.Identifier: {
414
- context.report({ messageId: "useState", node: id });
442
+ context.report({ messageId: "unexpected", node: id });
415
443
  break;
416
444
  }
417
445
  case types.AST_NODE_TYPES.ArrayPattern: {
418
446
  const [state, setState] = id.elements;
419
447
  if (state?.type === types.AST_NODE_TYPES.ObjectPattern && setState?.type === types.AST_NODE_TYPES.Identifier) {
420
448
  if (!isSetterNameLoose(setState.name)) {
421
- context.report({ messageId: "useState", node: id });
449
+ context.report({ messageId: "unexpected", node: id });
422
450
  }
423
451
  break;
424
452
  }
@@ -430,7 +458,7 @@ var use_state_default = createRule({
430
458
  if (setStateName === expectedSetterName) {
431
459
  return;
432
460
  }
433
- context.report({ messageId: "useState", node: id });
461
+ context.report({ messageId: "unexpected", node: id });
434
462
  }
435
463
  }
436
464
  }
@@ -441,10 +469,10 @@ var use_state_default = createRule({
441
469
  defaultOptions: []
442
470
  });
443
471
 
444
- // src/index.ts
445
- var index_default = {
472
+ // src/plugin.ts
473
+ var plugin = {
446
474
  meta: {
447
- name,
475
+ name: name2,
448
476
  version
449
477
  },
450
478
  rules: {
@@ -455,4 +483,27 @@ var index_default = {
455
483
  }
456
484
  };
457
485
 
486
+ // src/index.ts
487
+ function makeConfig(config) {
488
+ return {
489
+ ...config,
490
+ plugins: {
491
+ "react-naming-convention": plugin
492
+ }
493
+ };
494
+ }
495
+ function makeLegacyConfig({ rules: rules2 }) {
496
+ return {
497
+ plugins: ["react-naming-convention"],
498
+ rules: rules2
499
+ };
500
+ }
501
+ var index_default = {
502
+ ...plugin,
503
+ configs: {
504
+ ["recommended"]: makeConfig(recommended_exports),
505
+ ["recommended-legacy"]: makeLegacyConfig(recommended_exports)
506
+ }
507
+ };
508
+
458
509
  module.exports = index_default;
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as AST from '@eslint-react/ast';
2
2
  import { useComponentCollector, useComponentCollectorLegacy, DEFAULT_COMPONENT_HINT, isUseStateCall, isReactHookCallWithNameLoose } from '@eslint-react/core';
3
- import { isObject, constFalse } from '@eslint-react/eff';
3
+ import { isObject, _ } from '@eslint-react/eff';
4
4
  import * as JSX from '@eslint-react/jsx';
5
5
  import { createRuleForPlugin, getSettingsFromContext, RE_CONSTANT_CASE, RE_PASCAL_CASE, RE_CAMEL_CASE, RE_KEBAB_CASE, RE_SNAKE_CASE } from '@eslint-react/shared';
6
6
  import { match } from 'ts-pattern';
@@ -8,9 +8,24 @@ import path from 'node:path';
8
8
  import { capitalize, pascalCase, camelCase, kebabCase, snakeCase } from 'string-ts';
9
9
  import { AST_NODE_TYPES } from '@typescript-eslint/types';
10
10
 
11
+ var __defProp = Object.defineProperty;
12
+ var __export = (target, all) => {
13
+ for (var name3 in all)
14
+ __defProp(target, name3, { get: all[name3], enumerable: true });
15
+ };
16
+
17
+ // src/configs/recommended.ts
18
+ var recommended_exports = {};
19
+ __export(recommended_exports, {
20
+ name: () => name,
21
+ rules: () => rules
22
+ });
23
+ var name = "react-naming-convention/recommended";
24
+ var rules = {};
25
+
11
26
  // package.json
12
- var name = "eslint-plugin-react-naming-convention";
13
- var version = "1.26.3-beta.2";
27
+ var name2 = "eslint-plugin-react-naming-convention";
28
+ var version = "1.26.3-beta.21";
14
29
  var createRule = createRuleForPlugin("naming-convention");
15
30
 
16
31
  // src/rules/component-name.ts
@@ -64,26 +79,32 @@ function normalizeOptions(options) {
64
79
  excepts: opts.excepts?.map((pattern) => new RegExp(pattern, "u")) ?? []
65
80
  };
66
81
  }
67
- function validate(name2, options) {
68
- if (name2 == null) return false;
69
- if (options.excepts.some((regex) => regex.test(name2))) {
70
- return true;
82
+ function getViolationMessage(name3, options) {
83
+ if (name3 == null) return _;
84
+ const {
85
+ allowAllCaps = false,
86
+ allowLeadingUnderscore = false,
87
+ allowNamespace = false,
88
+ excepts,
89
+ rule
90
+ } = options;
91
+ if (excepts.some((regex) => regex.test(name3))) {
92
+ return _;
71
93
  }
72
- let normalized = name2.normalize("NFKD").replace(/[\u0300-\u036F]/g, "");
94
+ let normalized = name3.normalize("NFKD").replace(/[\u0300-\u036F]/g, "");
73
95
  normalized = normalized.split(".").at(-1) ?? normalized;
74
- const { allowLeadingUnderscore = false, allowNamespace = false } = options;
75
96
  if (allowNamespace) {
76
97
  normalized = normalized.replace(":", "");
77
98
  }
78
99
  if (allowLeadingUnderscore) {
79
100
  normalized = normalized.replace(/^_/, "");
80
101
  }
81
- return match(options.rule).with("CONSTANT_CASE", () => RE_CONSTANT_CASE.test(normalized)).with("PascalCase", () => {
102
+ return match(rule).with("CONSTANT_CASE", () => RE_CONSTANT_CASE.test(normalized) ? _ : "useConstantCase").with("PascalCase", () => {
82
103
  if (normalized.length > 3 && /^[A-Z]+$/u.test(normalized)) {
83
- return options.allowAllCaps ?? false;
104
+ return allowAllCaps ? _ : "usePascalCase";
84
105
  }
85
- return RE_PASCAL_CASE.test(normalized);
86
- }).otherwise(constFalse);
106
+ return RE_PASCAL_CASE.test(normalized) ? _ : "usePascalCase";
107
+ }).otherwise(() => _);
87
108
  }
88
109
  var component_name_default = createRule({
89
110
  meta: {
@@ -93,7 +114,8 @@ var component_name_default = createRule({
93
114
  description: "enforce component naming convention to 'PascalCase' or 'CONSTANT_CASE'"
94
115
  },
95
116
  messages: {
96
- componentName: "A component name must be in {{case}}."
117
+ useConstantCase: "Component name '{{name}}' must be in CONSTANT_CASE.",
118
+ usePascalCase: "Component name '{{name}}' must be in PascalCase."
97
119
  },
98
120
  schema
99
121
  },
@@ -106,18 +128,17 @@ var component_name_default = createRule({
106
128
  ...collector.listeners,
107
129
  ...collectorLegacy.listeners,
108
130
  JSXOpeningElement(node) {
109
- const name2 = JSX.getElementName(node.parent);
110
- if (/^[a-z]/u.test(name2)) {
111
- return;
112
- }
113
- if (validate(name2, options)) {
131
+ const name3 = JSX.getElementName(node.parent);
132
+ if (/^[a-z]/u.test(name3)) {
114
133
  return;
115
134
  }
135
+ const violation = getViolationMessage(name3, options);
136
+ if (violation == null) return;
116
137
  context.report({
117
- messageId: "componentName",
138
+ messageId: violation,
118
139
  node,
119
140
  data: {
120
- case: options.rule
141
+ name: name3
121
142
  }
122
143
  });
123
144
  },
@@ -127,29 +148,30 @@ var component_name_default = createRule({
127
148
  for (const { node: component } of functionComponents.values()) {
128
149
  const id = AST.getFunctionIdentifier(component);
129
150
  if (id?.name == null) continue;
130
- if (validate(id.name, options)) {
131
- continue;
132
- }
151
+ const name3 = id.name;
152
+ const violation = getViolationMessage(name3, options);
153
+ if (violation == null) continue;
133
154
  context.report({
134
- messageId: "componentName",
155
+ messageId: violation,
135
156
  node: id,
136
157
  data: {
137
- case: options.rule
158
+ name: name3
138
159
  }
139
160
  });
140
161
  }
141
162
  for (const { node: component } of classComponents.values()) {
142
163
  const id = AST.getClassIdentifier(component);
143
164
  if (id?.name == null) continue;
144
- if (!validate(id.name, options)) {
145
- context.report({
146
- messageId: "componentName",
147
- node: id,
148
- data: {
149
- case: options.rule
150
- }
151
- });
152
- }
165
+ const name3 = id.name;
166
+ const violation = getViolationMessage(name3, options);
167
+ if (violation == null) continue;
168
+ context.report({
169
+ messageId: violation,
170
+ node: id,
171
+ data: {
172
+ case: options.rule
173
+ }
174
+ });
153
175
  }
154
176
  }
155
177
  };
@@ -201,8 +223,7 @@ var filename_default = createRule({
201
223
  description: "enforce naming convention for JSX filenames"
202
224
  },
203
225
  messages: {
204
- // filenameCaseMismatch: "A file with name '{{name}}' does not match {{rule}}.",
205
- filenameCaseMismatchSuggestion: "A file with name '{{name}}' does not match {{rule}}. Should rename to '{{suggestion}}'.",
226
+ filenameCaseMismatch: "A file with name '{{name}}' does not match {{rule}}. Should rename to '{{suggestion}}'.",
206
227
  filenameEmpty: "A file must have non-empty name."
207
228
  },
208
229
  schema: schema2
@@ -212,13 +233,13 @@ var filename_default = createRule({
212
233
  const options = context.options[0] ?? defaultOptions2[0];
213
234
  const rule = typeof options === "string" ? options : options.rule ?? "PascalCase";
214
235
  const excepts = typeof options === "string" ? [] : options.excepts ?? [];
215
- function validate2(name2, casing = rule, ignores = excepts) {
216
- const shouldIgnore = ignores.map((pattern) => new RegExp(pattern, "u")).some((pattern) => pattern.test(name2));
236
+ function validate(name3, casing = rule, ignores = excepts) {
237
+ const shouldIgnore = ignores.map((pattern) => new RegExp(pattern, "u")).some((pattern) => pattern.test(name3));
217
238
  if (shouldIgnore) return true;
218
- return match(casing).with("PascalCase", () => RE_PASCAL_CASE.test(name2)).with("camelCase", () => RE_CAMEL_CASE.test(name2)).with("kebab-case", () => RE_KEBAB_CASE.test(name2)).with("snake_case", () => RE_SNAKE_CASE.test(name2)).exhaustive();
239
+ return match(casing).with("PascalCase", () => RE_PASCAL_CASE.test(name3)).with("camelCase", () => RE_CAMEL_CASE.test(name3)).with("kebab-case", () => RE_KEBAB_CASE.test(name3)).with("snake_case", () => RE_SNAKE_CASE.test(name3)).exhaustive();
219
240
  }
220
- function getSuggestion(name2, casing = rule) {
221
- return match(casing).with("PascalCase", () => pascalCase(name2)).with("camelCase", () => camelCase(name2)).with("kebab-case", () => kebabCase(name2)).with("snake_case", () => snakeCase(name2)).exhaustive();
241
+ function getSuggestion(name3, casing = rule) {
242
+ return match(casing).with("PascalCase", () => pascalCase(name3)).with("camelCase", () => camelCase(name3)).with("kebab-case", () => kebabCase(name3)).with("snake_case", () => snakeCase(name3)).exhaustive();
222
243
  }
223
244
  return {
224
245
  Program(node) {
@@ -227,11 +248,11 @@ var filename_default = createRule({
227
248
  context.report({ messageId: "filenameEmpty", node });
228
249
  return;
229
250
  }
230
- if (validate2(basename)) {
251
+ if (validate(basename)) {
231
252
  return;
232
253
  }
233
254
  context.report({
234
- messageId: "filenameCaseMismatchSuggestion",
255
+ messageId: "filenameCaseMismatch",
235
256
  node,
236
257
  data: {
237
258
  name: context.filename,
@@ -288,8 +309,8 @@ var filename_extension_default = createRule({
288
309
  description: "enforce naming convention for JSX file extensions"
289
310
  },
290
311
  messages: {
291
- filenameExtensionInvalid: "The JSX file extension is required.",
292
- filenameExtensionUnexpected: "Use JSX file extension as needed."
312
+ useJsxFileExtension: "Use {{extensions}} file extension for JSX files.",
313
+ useJsxFileExtensionAsNeeded: "Do not use {{extensions}} file extension for files without JSX."
293
314
  },
294
315
  schema: schema3
295
316
  },
@@ -298,6 +319,7 @@ var filename_extension_default = createRule({
298
319
  const options = context.options[0] ?? defaultOptions3[0];
299
320
  const allow = isObject(options) ? options.allow : options;
300
321
  const extensions = isObject(options) && "extensions" in options ? options.extensions : defaultOptions3[0].extensions;
322
+ const extensionsString = extensions.map((ext) => `'${ext}'`).join(", ");
301
323
  const filename = context.filename;
302
324
  let hasJSXNode = false;
303
325
  return {
@@ -312,8 +334,11 @@ var filename_extension_default = createRule({
312
334
  const isJSXExt = extensions.includes(fileNameExt);
313
335
  if (hasJSXNode && !isJSXExt) {
314
336
  context.report({
315
- messageId: "filenameExtensionInvalid",
316
- node
337
+ messageId: "useJsxFileExtension",
338
+ node,
339
+ data: {
340
+ extensions: extensionsString
341
+ }
317
342
  });
318
343
  return;
319
344
  }
@@ -324,8 +349,11 @@ var filename_extension_default = createRule({
324
349
  }
325
350
  if (!hasJSXNode && isJSXExt && allow === "as-needed") {
326
351
  context.report({
327
- messageId: "filenameExtensionUnexpected",
328
- node
352
+ messageId: "useJsxFileExtensionAsNeeded",
353
+ node,
354
+ data: {
355
+ extensions: extensionsString
356
+ }
329
357
  });
330
358
  }
331
359
  }
@@ -337,19 +365,19 @@ var RULE_NAME4 = "use-state";
337
365
  var RULE_FEATURES = [
338
366
  "CHK"
339
367
  ];
340
- function isSetterNameLoose(name2) {
341
- const fourthChar = [...name2][3];
342
- return name2.startsWith("set") && fourthChar === fourthChar?.toUpperCase();
368
+ function isSetterNameLoose(name3) {
369
+ const fourthChar = [...name3][3];
370
+ return name3.startsWith("set") && fourthChar === fourthChar?.toUpperCase();
343
371
  }
344
372
  var use_state_default = createRule({
345
373
  meta: {
346
374
  type: "problem",
347
375
  docs: {
348
- description: "enforce destructuring and symmetric naming of 'useState' hook value and setter variables",
376
+ description: "enforce destructuring and symmetric naming of 'useState' hook value and setter",
349
377
  [Symbol.for("rule_features")]: RULE_FEATURES
350
378
  },
351
379
  messages: {
352
- useState: "An useState call is not destructured into value + setter pair."
380
+ unexpected: "An useState call is not destructured into value + setter pair."
353
381
  },
354
382
  schema: []
355
383
  },
@@ -385,14 +413,14 @@ var use_state_default = createRule({
385
413
  const { id } = hookCall.parent;
386
414
  switch (id.type) {
387
415
  case AST_NODE_TYPES.Identifier: {
388
- context.report({ messageId: "useState", node: id });
416
+ context.report({ messageId: "unexpected", node: id });
389
417
  break;
390
418
  }
391
419
  case AST_NODE_TYPES.ArrayPattern: {
392
420
  const [state, setState] = id.elements;
393
421
  if (state?.type === AST_NODE_TYPES.ObjectPattern && setState?.type === AST_NODE_TYPES.Identifier) {
394
422
  if (!isSetterNameLoose(setState.name)) {
395
- context.report({ messageId: "useState", node: id });
423
+ context.report({ messageId: "unexpected", node: id });
396
424
  }
397
425
  break;
398
426
  }
@@ -404,7 +432,7 @@ var use_state_default = createRule({
404
432
  if (setStateName === expectedSetterName) {
405
433
  return;
406
434
  }
407
- context.report({ messageId: "useState", node: id });
435
+ context.report({ messageId: "unexpected", node: id });
408
436
  }
409
437
  }
410
438
  }
@@ -415,10 +443,10 @@ var use_state_default = createRule({
415
443
  defaultOptions: []
416
444
  });
417
445
 
418
- // src/index.ts
419
- var index_default = {
446
+ // src/plugin.ts
447
+ var plugin = {
420
448
  meta: {
421
- name,
449
+ name: name2,
422
450
  version
423
451
  },
424
452
  rules: {
@@ -429,4 +457,27 @@ var index_default = {
429
457
  }
430
458
  };
431
459
 
460
+ // src/index.ts
461
+ function makeConfig(config) {
462
+ return {
463
+ ...config,
464
+ plugins: {
465
+ "react-naming-convention": plugin
466
+ }
467
+ };
468
+ }
469
+ function makeLegacyConfig({ rules: rules2 }) {
470
+ return {
471
+ plugins: ["react-naming-convention"],
472
+ rules: rules2
473
+ };
474
+ }
475
+ var index_default = {
476
+ ...plugin,
477
+ configs: {
478
+ ["recommended"]: makeConfig(recommended_exports),
479
+ ["recommended-legacy"]: makeLegacyConfig(recommended_exports)
480
+ }
481
+ };
482
+
432
483
  export { index_default as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-naming-convention",
3
- "version": "1.26.3-beta.2",
3
+ "version": "1.26.3-beta.21",
4
4
  "description": "ESLint React's ESLint plugin for naming convention related rules.",
5
5
  "keywords": [
6
6
  "react",
@@ -43,23 +43,23 @@
43
43
  "./package.json"
44
44
  ],
45
45
  "dependencies": {
46
- "@typescript-eslint/scope-manager": "^8.23.0",
47
- "@typescript-eslint/type-utils": "^8.23.0",
48
- "@typescript-eslint/types": "^8.23.0",
49
- "@typescript-eslint/utils": "^8.23.0",
46
+ "@typescript-eslint/scope-manager": "^8.24.1",
47
+ "@typescript-eslint/type-utils": "^8.24.1",
48
+ "@typescript-eslint/types": "^8.24.1",
49
+ "@typescript-eslint/utils": "^8.24.1",
50
50
  "string-ts": "^2.2.1",
51
51
  "ts-pattern": "^5.6.2",
52
- "@eslint-react/ast": "1.26.3-beta.2",
53
- "@eslint-react/eff": "1.26.3-beta.2",
54
- "@eslint-react/core": "1.26.3-beta.2",
55
- "@eslint-react/jsx": "1.26.3-beta.2",
56
- "@eslint-react/shared": "1.26.3-beta.2"
52
+ "@eslint-react/ast": "1.26.3-beta.21",
53
+ "@eslint-react/core": "1.26.3-beta.21",
54
+ "@eslint-react/eff": "1.26.3-beta.21",
55
+ "@eslint-react/jsx": "1.26.3-beta.21",
56
+ "@eslint-react/shared": "1.26.3-beta.21"
57
57
  },
58
58
  "devDependencies": {
59
- "@types/react": "^19.0.8",
60
- "@types/react-dom": "^19.0.3",
59
+ "@types/react": "^19.0.10",
60
+ "@types/react-dom": "^19.0.4",
61
61
  "tsup": "^8.3.6",
62
- "@workspace/configs": "0.0.0"
62
+ "@local/configs": "0.0.0"
63
63
  },
64
64
  "peerDependencies": {
65
65
  "eslint": "^8.57.0 || ^9.0.0",
@@ -83,6 +83,6 @@
83
83
  "scripts": {
84
84
  "build": "tsup --dts-resolve",
85
85
  "lint:publish": "publint",
86
- "lint:type": "tsc --noEmit"
86
+ "lint:ts": "tsc --noEmit"
87
87
  }
88
88
  }