eslint-plugin-react-naming-convention 1.29.1-next.5 → 1.29.1-next.7

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/dist/index.d.mts CHANGED
@@ -1,11 +1,9 @@
1
1
  import * as _typescript_eslint_utils_ts_eslint from '@typescript-eslint/utils/ts-eslint';
2
2
  import { RulePreset } from '@eslint-react/shared';
3
3
 
4
- type MessageID$2 = "useJsxFileExtension" | "useJsxFileExtensionAsNeeded";
4
+ type MessageID$1 = "useJsxFileExtension" | "useNonJsxFileExtension";
5
5
 
6
- type MessageID$1 = "filenameCaseMismatch" | "filenameEmpty";
7
-
8
- type MessageID = "usePascalCase" | "useConstantCase";
6
+ type MessageID = "filenameEmpty" | "filenameInvalid";
9
7
 
10
8
  declare const _default: {
11
9
  configs: {
@@ -17,25 +15,25 @@ declare const _default: {
17
15
  readonly version: string;
18
16
  };
19
17
  readonly rules: {
20
- readonly "component-name": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID, readonly [("CONSTANT_CASE" | "PascalCase") | {
18
+ readonly "component-name": _typescript_eslint_utils_ts_eslint.RuleModule<"invalid", readonly [("CONSTANT_CASE" | "PascalCase") | {
21
19
  allowAllCaps?: boolean;
22
20
  allowLeadingUnderscore?: boolean;
23
21
  allowNamespace?: boolean;
24
22
  excepts?: readonly string[];
25
23
  rule?: "CONSTANT_CASE" | "PascalCase";
26
24
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
27
- readonly "context-name": _typescript_eslint_utils_ts_eslint.RuleModule<"contextName", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
28
- readonly filename: _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$1, readonly [("PascalCase" | "camelCase" | "kebab-case" | "snake_case") | {
25
+ readonly "context-name": _typescript_eslint_utils_ts_eslint.RuleModule<"invalid", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
26
+ readonly filename: _typescript_eslint_utils_ts_eslint.RuleModule<MessageID, readonly [("PascalCase" | "camelCase" | "kebab-case" | "snake_case") | {
29
27
  excepts?: readonly string[];
30
28
  extensions?: readonly string[];
31
29
  rule?: "PascalCase" | "camelCase" | "kebab-case" | "snake_case";
32
30
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
33
- readonly "filename-extension": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$2, readonly [("always" | "as-needed") | {
31
+ readonly "filename-extension": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$1, readonly [("always" | "as-needed") | {
34
32
  allow?: "always" | "as-needed";
35
33
  extensions?: readonly string[];
36
34
  ignoreFilesWithoutCode?: boolean;
37
35
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
38
- readonly "use-state": _typescript_eslint_utils_ts_eslint.RuleModule<"badValueOrSetterName", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
36
+ readonly "use-state": _typescript_eslint_utils_ts_eslint.RuleModule<"invalid", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
39
37
  };
40
38
  };
41
39
  };
@@ -52,25 +50,25 @@ declare const _default: {
52
50
  readonly version: string;
53
51
  };
54
52
  rules: {
55
- readonly "component-name": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID, readonly [("CONSTANT_CASE" | "PascalCase") | {
53
+ readonly "component-name": _typescript_eslint_utils_ts_eslint.RuleModule<"invalid", readonly [("CONSTANT_CASE" | "PascalCase") | {
56
54
  allowAllCaps?: boolean;
57
55
  allowLeadingUnderscore?: boolean;
58
56
  allowNamespace?: boolean;
59
57
  excepts?: readonly string[];
60
58
  rule?: "CONSTANT_CASE" | "PascalCase";
61
59
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
62
- readonly "context-name": _typescript_eslint_utils_ts_eslint.RuleModule<"contextName", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
63
- readonly filename: _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$1, readonly [("PascalCase" | "camelCase" | "kebab-case" | "snake_case") | {
60
+ readonly "context-name": _typescript_eslint_utils_ts_eslint.RuleModule<"invalid", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
61
+ readonly filename: _typescript_eslint_utils_ts_eslint.RuleModule<MessageID, readonly [("PascalCase" | "camelCase" | "kebab-case" | "snake_case") | {
64
62
  excepts?: readonly string[];
65
63
  extensions?: readonly string[];
66
64
  rule?: "PascalCase" | "camelCase" | "kebab-case" | "snake_case";
67
65
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
68
- readonly "filename-extension": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$2, readonly [("always" | "as-needed") | {
66
+ readonly "filename-extension": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$1, readonly [("always" | "as-needed") | {
69
67
  allow?: "always" | "as-needed";
70
68
  extensions?: readonly string[];
71
69
  ignoreFilesWithoutCode?: boolean;
72
70
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
73
- readonly "use-state": _typescript_eslint_utils_ts_eslint.RuleModule<"badValueOrSetterName", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
71
+ readonly "use-state": _typescript_eslint_utils_ts_eslint.RuleModule<"invalid", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
74
72
  };
75
73
  };
76
74
 
package/dist/index.d.ts CHANGED
@@ -1,11 +1,9 @@
1
1
  import * as _typescript_eslint_utils_ts_eslint from '@typescript-eslint/utils/ts-eslint';
2
2
  import { RulePreset } from '@eslint-react/shared';
3
3
 
4
- type MessageID$2 = "useJsxFileExtension" | "useJsxFileExtensionAsNeeded";
4
+ type MessageID$1 = "useJsxFileExtension" | "useNonJsxFileExtension";
5
5
 
6
- type MessageID$1 = "filenameCaseMismatch" | "filenameEmpty";
7
-
8
- type MessageID = "usePascalCase" | "useConstantCase";
6
+ type MessageID = "filenameEmpty" | "filenameInvalid";
9
7
 
10
8
  declare const _default: {
11
9
  configs: {
@@ -17,25 +15,25 @@ declare const _default: {
17
15
  readonly version: string;
18
16
  };
19
17
  readonly rules: {
20
- readonly "component-name": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID, readonly [("CONSTANT_CASE" | "PascalCase") | {
18
+ readonly "component-name": _typescript_eslint_utils_ts_eslint.RuleModule<"invalid", readonly [("CONSTANT_CASE" | "PascalCase") | {
21
19
  allowAllCaps?: boolean;
22
20
  allowLeadingUnderscore?: boolean;
23
21
  allowNamespace?: boolean;
24
22
  excepts?: readonly string[];
25
23
  rule?: "CONSTANT_CASE" | "PascalCase";
26
24
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
27
- readonly "context-name": _typescript_eslint_utils_ts_eslint.RuleModule<"contextName", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
28
- readonly filename: _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$1, readonly [("PascalCase" | "camelCase" | "kebab-case" | "snake_case") | {
25
+ readonly "context-name": _typescript_eslint_utils_ts_eslint.RuleModule<"invalid", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
26
+ readonly filename: _typescript_eslint_utils_ts_eslint.RuleModule<MessageID, readonly [("PascalCase" | "camelCase" | "kebab-case" | "snake_case") | {
29
27
  excepts?: readonly string[];
30
28
  extensions?: readonly string[];
31
29
  rule?: "PascalCase" | "camelCase" | "kebab-case" | "snake_case";
32
30
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
33
- readonly "filename-extension": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$2, readonly [("always" | "as-needed") | {
31
+ readonly "filename-extension": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$1, readonly [("always" | "as-needed") | {
34
32
  allow?: "always" | "as-needed";
35
33
  extensions?: readonly string[];
36
34
  ignoreFilesWithoutCode?: boolean;
37
35
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
38
- readonly "use-state": _typescript_eslint_utils_ts_eslint.RuleModule<"badValueOrSetterName", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
36
+ readonly "use-state": _typescript_eslint_utils_ts_eslint.RuleModule<"invalid", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
39
37
  };
40
38
  };
41
39
  };
@@ -52,25 +50,25 @@ declare const _default: {
52
50
  readonly version: string;
53
51
  };
54
52
  rules: {
55
- readonly "component-name": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID, readonly [("CONSTANT_CASE" | "PascalCase") | {
53
+ readonly "component-name": _typescript_eslint_utils_ts_eslint.RuleModule<"invalid", readonly [("CONSTANT_CASE" | "PascalCase") | {
56
54
  allowAllCaps?: boolean;
57
55
  allowLeadingUnderscore?: boolean;
58
56
  allowNamespace?: boolean;
59
57
  excepts?: readonly string[];
60
58
  rule?: "CONSTANT_CASE" | "PascalCase";
61
59
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
62
- readonly "context-name": _typescript_eslint_utils_ts_eslint.RuleModule<"contextName", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
63
- readonly filename: _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$1, readonly [("PascalCase" | "camelCase" | "kebab-case" | "snake_case") | {
60
+ readonly "context-name": _typescript_eslint_utils_ts_eslint.RuleModule<"invalid", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
61
+ readonly filename: _typescript_eslint_utils_ts_eslint.RuleModule<MessageID, readonly [("PascalCase" | "camelCase" | "kebab-case" | "snake_case") | {
64
62
  excepts?: readonly string[];
65
63
  extensions?: readonly string[];
66
64
  rule?: "PascalCase" | "camelCase" | "kebab-case" | "snake_case";
67
65
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
68
- readonly "filename-extension": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$2, readonly [("always" | "as-needed") | {
66
+ readonly "filename-extension": _typescript_eslint_utils_ts_eslint.RuleModule<MessageID$1, readonly [("always" | "as-needed") | {
69
67
  allow?: "always" | "as-needed";
70
68
  extensions?: readonly string[];
71
69
  ignoreFilesWithoutCode?: boolean;
72
70
  } | undefined], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
73
- readonly "use-state": _typescript_eslint_utils_ts_eslint.RuleModule<"badValueOrSetterName", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
71
+ readonly "use-state": _typescript_eslint_utils_ts_eslint.RuleModule<"invalid", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
74
72
  };
75
73
  };
76
74
 
package/dist/index.js CHANGED
@@ -2,9 +2,8 @@
2
2
 
3
3
  var AST = require('@eslint-react/ast');
4
4
  var core = require('@eslint-react/core');
5
- var eff = require('@eslint-react/eff');
6
- var JSX = require('@eslint-react/jsx');
7
5
  var shared = require('@eslint-react/shared');
6
+ var eff = require('@eslint-react/eff');
8
7
  var types = require('@typescript-eslint/types');
9
8
  var tsPattern = require('ts-pattern');
10
9
  var path = require('path');
@@ -31,7 +30,6 @@ function _interopNamespace(e) {
31
30
  }
32
31
 
33
32
  var AST__namespace = /*#__PURE__*/_interopNamespace(AST);
34
- var JSX__namespace = /*#__PURE__*/_interopNamespace(JSX);
35
33
  var path__default = /*#__PURE__*/_interopDefault(path);
36
34
 
37
35
  var __defProp = Object.defineProperty;
@@ -54,16 +52,13 @@ var rules = {
54
52
 
55
53
  // package.json
56
54
  var name2 = "eslint-plugin-react-naming-convention";
57
- var version = "1.29.1-next.5";
55
+ var version = "1.29.1-next.7";
58
56
  var createRule = shared.createRuleForPlugin("naming-convention");
59
57
 
60
58
  // src/rules/component-name.ts
61
- var RULE_NAME = "component-name";
62
59
  var defaultOptions = [
63
60
  {
64
61
  allowAllCaps: false,
65
- allowLeadingUnderscore: false,
66
- allowNamespace: false,
67
62
  excepts: [],
68
63
  rule: "PascalCase"
69
64
  }
@@ -80,7 +75,15 @@ var schema = [
80
75
  additionalProperties: false,
81
76
  properties: {
82
77
  allowAllCaps: { type: "boolean" },
78
+ /**
79
+ * @todo Remove in the next major version
80
+ * @deprecated
81
+ */
83
82
  allowLeadingUnderscore: { type: "boolean" },
83
+ /**
84
+ * @todo Remove in the next major version
85
+ * @deprecated
86
+ */
84
87
  allowNamespace: { type: "boolean" },
85
88
  excepts: {
86
89
  type: "array",
@@ -95,72 +98,28 @@ var schema = [
95
98
  ]
96
99
  }
97
100
  ];
98
- function normalizeOptions(options) {
99
- const opts = options[0];
100
- const defaultOpts = defaultOptions[0];
101
- if (opts == null) return defaultOpts;
102
- return {
103
- ...defaultOpts,
104
- ...typeof opts === "string" ? { rule: opts } : {
105
- ...opts,
106
- excepts: opts.excepts?.map((pattern) => new RegExp(pattern, "u")) ?? []
107
- }
108
- };
109
- }
110
- function getViolationMessage(name3, options) {
111
- if (name3 == null) return eff._;
112
- if (options.excepts.some((regex) => regex.test(name3))) return eff._;
113
- let normalized = name3.split(".").at(-1) ?? name3;
114
- if (options.allowNamespace) normalized = normalized.replace(":", "");
115
- if (options.allowLeadingUnderscore) normalized = normalized.replace(/^_/, "");
116
- switch (options.rule) {
117
- case "CONSTANT_CASE":
118
- return shared.RE_CONSTANT_CASE.test(normalized) ? eff._ : "useConstantCase";
119
- case "PascalCase":
120
- if (normalized.length > 3 && /^[A-Z]+$/u.test(normalized)) {
121
- return options.allowAllCaps ? eff._ : "usePascalCase";
122
- }
123
- return shared.RE_PASCAL_CASE.test(normalized) ? eff._ : "usePascalCase";
124
- default:
125
- return eff._;
126
- }
127
- }
101
+ var RULE_NAME = "component-name";
128
102
  var component_name_default = createRule({
129
103
  meta: {
130
104
  type: "problem",
131
105
  defaultOptions: [...defaultOptions],
132
106
  docs: {
133
- description: "enforce component naming convention to 'PascalCase' or 'CONSTANT_CASE'"
107
+ description: "enforce naming convention for components"
134
108
  },
135
109
  messages: {
136
- useConstantCase: "Component name '{{name}}' must be in CONSTANT_CASE.",
137
- usePascalCase: "Component name '{{name}}' must be in PascalCase."
110
+ invalid: "A component name '{{name}}' does not match {{rule}}."
138
111
  },
139
112
  schema
140
113
  },
141
114
  name: RULE_NAME,
142
115
  create(context) {
143
116
  const options = normalizeOptions(context.options);
117
+ const { rule } = options;
144
118
  const collector = core.useComponentCollector(context);
145
119
  const collectorLegacy = core.useComponentCollectorLegacy();
146
120
  return {
147
121
  ...collector.listeners,
148
122
  ...collectorLegacy.listeners,
149
- JSXOpeningElement(node) {
150
- const name3 = JSX__namespace.getElementName(node.parent);
151
- if (/^[a-z]/u.test(name3)) {
152
- return;
153
- }
154
- const violation = getViolationMessage(name3, options);
155
- if (violation == null) return;
156
- context.report({
157
- messageId: violation,
158
- node,
159
- data: {
160
- name: name3
161
- }
162
- });
163
- },
164
123
  "Program:exit"(node) {
165
124
  const functionComponents = collector.ctx.getAllComponents(node);
166
125
  const classComponents = collectorLegacy.ctx.getAllComponents(node);
@@ -168,28 +127,22 @@ var component_name_default = createRule({
168
127
  const id = AST__namespace.getFunctionIdentifier(component);
169
128
  if (id?.name == null) continue;
170
129
  const name3 = id.name;
171
- const violation = getViolationMessage(name3, options);
172
- if (violation == null) continue;
130
+ if (isValidName(name3, options)) return;
173
131
  context.report({
174
- messageId: violation,
132
+ messageId: "invalid",
175
133
  node: id,
176
- data: {
177
- name: name3
178
- }
134
+ data: { name: name3, rule }
179
135
  });
180
136
  }
181
137
  for (const { node: component } of classComponents.values()) {
182
138
  const id = AST__namespace.getClassIdentifier(component);
183
139
  if (id?.name == null) continue;
184
140
  const name3 = id.name;
185
- const violation = getViolationMessage(name3, options);
186
- if (violation == null) continue;
141
+ if (isValidName(name3, options)) continue;
187
142
  context.report({
188
- messageId: violation,
143
+ messageId: "invalid",
189
144
  node: id,
190
- data: {
191
- case: options.rule
192
- }
145
+ data: { name: name3, rule }
193
146
  });
194
147
  }
195
148
  }
@@ -197,15 +150,41 @@ var component_name_default = createRule({
197
150
  },
198
151
  defaultOptions
199
152
  });
153
+ function normalizeOptions(options) {
154
+ const opts = options[0];
155
+ const defaultOpts = defaultOptions[0];
156
+ if (opts == null) return defaultOpts;
157
+ return {
158
+ ...defaultOpts,
159
+ ...typeof opts === "string" ? { rule: opts } : {
160
+ ...opts,
161
+ excepts: opts.excepts?.map((pattern) => new RegExp(pattern, "u")) ?? []
162
+ }
163
+ };
164
+ }
165
+ function isValidName(name3, options) {
166
+ if (name3 == null) return true;
167
+ if (options.excepts.some((regex) => regex.test(name3))) return true;
168
+ const normalized = name3.split(".").at(-1) ?? name3;
169
+ switch (options.rule) {
170
+ case "CONSTANT_CASE":
171
+ return shared.RE_CONSTANT_CASE.test(normalized);
172
+ case "PascalCase":
173
+ if (normalized.length > 3 && /^[A-Z]+$/u.test(normalized)) {
174
+ return options.allowAllCaps;
175
+ }
176
+ return shared.RE_PASCAL_CASE.test(normalized);
177
+ }
178
+ }
200
179
  var RULE_NAME2 = "context-name";
201
180
  var context_name_default = createRule({
202
181
  meta: {
203
182
  type: "problem",
204
183
  docs: {
205
- description: "enforces context name to be a valid component name with the suffix 'Context'"
184
+ description: "enforce context name to be a valid component name with the suffix 'Context'"
206
185
  },
207
186
  messages: {
208
- contextName: "In React 19, you can render '<Context>' as a provider instead of '<Context.Provider>', it's name must be a valid component name with the suffix 'Context'."
187
+ invalid: "A context name must be a valid component name with the suffix 'Context'."
209
188
  },
210
189
  schema: []
211
190
  },
@@ -220,7 +199,7 @@ var context_name_default = createRule({
220
199
  const name3 = tsPattern.match(id).with({ type: types.AST_NODE_TYPES.Identifier, name: tsPattern.P.select() }, eff.identity).with({ type: types.AST_NODE_TYPES.MemberExpression, property: { name: tsPattern.P.select(tsPattern.P.string) } }, eff.identity).otherwise(() => eff._);
221
200
  if (name3 != null && /^[A-Z]/u.test(name3) && name3.endsWith("Context")) return;
222
201
  context.report({
223
- messageId: "contextName",
202
+ messageId: "invalid",
224
203
  node: id
225
204
  });
226
205
  }
@@ -273,8 +252,8 @@ var filename_default = createRule({
273
252
  description: "enforce naming convention for JSX filenames"
274
253
  },
275
254
  messages: {
276
- filenameCaseMismatch: "A file with name '{{name}}' does not match {{rule}}. Should rename to '{{suggestion}}'.",
277
- filenameEmpty: "A file must have non-empty name."
255
+ filenameEmpty: "A file must have non-empty name.",
256
+ filenameInvalid: "A file with name '{{name}}' does not match {{rule}}. Rename it to '{{suggestion}}'."
278
257
  },
279
258
  schema: schema2
280
259
  },
@@ -302,7 +281,7 @@ var filename_default = createRule({
302
281
  return;
303
282
  }
304
283
  context.report({
305
- messageId: "filenameCaseMismatch",
284
+ messageId: "filenameInvalid",
306
285
  node,
307
286
  data: {
308
287
  name: context.filename,
@@ -360,7 +339,7 @@ var filename_extension_default = createRule({
360
339
  },
361
340
  messages: {
362
341
  useJsxFileExtension: "Use {{extensions}} file extension for JSX files.",
363
- useJsxFileExtensionAsNeeded: "Do not use {{extensions}} file extension for files without JSX."
342
+ useNonJsxFileExtension: "Do not use {{extensions}} file extension for files without JSX."
364
343
  },
365
344
  schema: schema3
366
345
  },
@@ -399,7 +378,7 @@ var filename_extension_default = createRule({
399
378
  }
400
379
  if (!hasJSXNode && isJSXExt && allow === "as-needed") {
401
380
  context.report({
402
- messageId: "useJsxFileExtensionAsNeeded",
381
+ messageId: "useNonJsxFileExtension",
403
382
  node,
404
383
  data: {
405
384
  extensions: extensionsString
@@ -423,7 +402,7 @@ var use_state_default = createRule({
423
402
  [Symbol.for("rule_features")]: RULE_FEATURES
424
403
  },
425
404
  messages: {
426
- badValueOrSetterName: "An useState call is not destructured into value + setter pair."
405
+ invalid: "An useState call is not destructured into value + setter pair."
427
406
  },
428
407
  schema: []
429
408
  },
@@ -432,21 +411,21 @@ var use_state_default = createRule({
432
411
  return {
433
412
  "CallExpression[callee.name='useState']"(node) {
434
413
  if (node.parent.type !== types.AST_NODE_TYPES.VariableDeclarator) {
435
- context.report({ messageId: "badValueOrSetterName", node });
414
+ context.report({ messageId: "invalid", node });
436
415
  }
437
416
  const id = core.getInstanceId(node);
438
417
  if (id?.type !== types.AST_NODE_TYPES.ArrayPattern) {
439
- context.report({ messageId: "badValueOrSetterName", node });
418
+ context.report({ messageId: "invalid", node });
440
419
  return;
441
420
  }
442
421
  const [value, setter] = id.elements;
443
422
  if (value == null || setter == null) {
444
- context.report({ messageId: "badValueOrSetterName", node });
423
+ context.report({ messageId: "invalid", node });
445
424
  return;
446
425
  }
447
426
  const setterName = tsPattern.match(setter).with({ type: types.AST_NODE_TYPES.Identifier }, (id2) => id2.name).otherwise(() => eff._);
448
427
  if (setterName == null || !setterName.startsWith("set")) {
449
- context.report({ messageId: "badValueOrSetterName", node });
428
+ context.report({ messageId: "invalid", node });
450
429
  return;
451
430
  }
452
431
  const valueName = tsPattern.match(value).with({ type: types.AST_NODE_TYPES.Identifier }, (id2) => id2.name).with({ type: types.AST_NODE_TYPES.ObjectPattern }, ({ properties }) => {
@@ -459,7 +438,7 @@ var use_state_default = createRule({
459
438
  return values.join("_");
460
439
  }).otherwise(() => eff._);
461
440
  if (valueName == null || `set_${valueName}` !== stringTs.snakeCase(setterName)) {
462
- context.report({ messageId: "badValueOrSetterName", node });
441
+ context.report({ messageId: "invalid", node });
463
442
  return;
464
443
  }
465
444
  }
@@ -475,11 +454,11 @@ var plugin = {
475
454
  version
476
455
  },
477
456
  rules: {
478
- "component-name": component_name_default,
479
- "context-name": context_name_default,
480
- filename: filename_default,
481
- "filename-extension": filename_extension_default,
482
- "use-state": use_state_default
457
+ ["component-name"]: component_name_default,
458
+ ["context-name"]: context_name_default,
459
+ ["filename"]: filename_default,
460
+ ["filename-extension"]: filename_extension_default,
461
+ ["use-state"]: use_state_default
483
462
  }
484
463
  };
485
464
 
package/dist/index.mjs CHANGED
@@ -1,8 +1,7 @@
1
1
  import * as AST from '@eslint-react/ast';
2
2
  import { useComponentCollector, useComponentCollectorLegacy, isCreateContextCall, getInstanceId } from '@eslint-react/core';
3
- import { identity, _, isObject } from '@eslint-react/eff';
4
- import * as JSX from '@eslint-react/jsx';
5
3
  import { createRuleForPlugin, RE_PASCAL_CASE, RE_CONSTANT_CASE, RE_CAMEL_CASE, RE_KEBAB_CASE, RE_SNAKE_CASE } from '@eslint-react/shared';
4
+ import { identity, _, isObject } from '@eslint-react/eff';
6
5
  import { AST_NODE_TYPES } from '@typescript-eslint/types';
7
6
  import { match, P } from 'ts-pattern';
8
7
  import path from 'node:path';
@@ -28,16 +27,13 @@ var rules = {
28
27
 
29
28
  // package.json
30
29
  var name2 = "eslint-plugin-react-naming-convention";
31
- var version = "1.29.1-next.5";
30
+ var version = "1.29.1-next.7";
32
31
  var createRule = createRuleForPlugin("naming-convention");
33
32
 
34
33
  // src/rules/component-name.ts
35
- var RULE_NAME = "component-name";
36
34
  var defaultOptions = [
37
35
  {
38
36
  allowAllCaps: false,
39
- allowLeadingUnderscore: false,
40
- allowNamespace: false,
41
37
  excepts: [],
42
38
  rule: "PascalCase"
43
39
  }
@@ -54,7 +50,15 @@ var schema = [
54
50
  additionalProperties: false,
55
51
  properties: {
56
52
  allowAllCaps: { type: "boolean" },
53
+ /**
54
+ * @todo Remove in the next major version
55
+ * @deprecated
56
+ */
57
57
  allowLeadingUnderscore: { type: "boolean" },
58
+ /**
59
+ * @todo Remove in the next major version
60
+ * @deprecated
61
+ */
58
62
  allowNamespace: { type: "boolean" },
59
63
  excepts: {
60
64
  type: "array",
@@ -69,72 +73,28 @@ var schema = [
69
73
  ]
70
74
  }
71
75
  ];
72
- function normalizeOptions(options) {
73
- const opts = options[0];
74
- const defaultOpts = defaultOptions[0];
75
- if (opts == null) return defaultOpts;
76
- return {
77
- ...defaultOpts,
78
- ...typeof opts === "string" ? { rule: opts } : {
79
- ...opts,
80
- excepts: opts.excepts?.map((pattern) => new RegExp(pattern, "u")) ?? []
81
- }
82
- };
83
- }
84
- function getViolationMessage(name3, options) {
85
- if (name3 == null) return _;
86
- if (options.excepts.some((regex) => regex.test(name3))) return _;
87
- let normalized = name3.split(".").at(-1) ?? name3;
88
- if (options.allowNamespace) normalized = normalized.replace(":", "");
89
- if (options.allowLeadingUnderscore) normalized = normalized.replace(/^_/, "");
90
- switch (options.rule) {
91
- case "CONSTANT_CASE":
92
- return RE_CONSTANT_CASE.test(normalized) ? _ : "useConstantCase";
93
- case "PascalCase":
94
- if (normalized.length > 3 && /^[A-Z]+$/u.test(normalized)) {
95
- return options.allowAllCaps ? _ : "usePascalCase";
96
- }
97
- return RE_PASCAL_CASE.test(normalized) ? _ : "usePascalCase";
98
- default:
99
- return _;
100
- }
101
- }
76
+ var RULE_NAME = "component-name";
102
77
  var component_name_default = createRule({
103
78
  meta: {
104
79
  type: "problem",
105
80
  defaultOptions: [...defaultOptions],
106
81
  docs: {
107
- description: "enforce component naming convention to 'PascalCase' or 'CONSTANT_CASE'"
82
+ description: "enforce naming convention for components"
108
83
  },
109
84
  messages: {
110
- useConstantCase: "Component name '{{name}}' must be in CONSTANT_CASE.",
111
- usePascalCase: "Component name '{{name}}' must be in PascalCase."
85
+ invalid: "A component name '{{name}}' does not match {{rule}}."
112
86
  },
113
87
  schema
114
88
  },
115
89
  name: RULE_NAME,
116
90
  create(context) {
117
91
  const options = normalizeOptions(context.options);
92
+ const { rule } = options;
118
93
  const collector = useComponentCollector(context);
119
94
  const collectorLegacy = useComponentCollectorLegacy();
120
95
  return {
121
96
  ...collector.listeners,
122
97
  ...collectorLegacy.listeners,
123
- JSXOpeningElement(node) {
124
- const name3 = JSX.getElementName(node.parent);
125
- if (/^[a-z]/u.test(name3)) {
126
- return;
127
- }
128
- const violation = getViolationMessage(name3, options);
129
- if (violation == null) return;
130
- context.report({
131
- messageId: violation,
132
- node,
133
- data: {
134
- name: name3
135
- }
136
- });
137
- },
138
98
  "Program:exit"(node) {
139
99
  const functionComponents = collector.ctx.getAllComponents(node);
140
100
  const classComponents = collectorLegacy.ctx.getAllComponents(node);
@@ -142,28 +102,22 @@ var component_name_default = createRule({
142
102
  const id = AST.getFunctionIdentifier(component);
143
103
  if (id?.name == null) continue;
144
104
  const name3 = id.name;
145
- const violation = getViolationMessage(name3, options);
146
- if (violation == null) continue;
105
+ if (isValidName(name3, options)) return;
147
106
  context.report({
148
- messageId: violation,
107
+ messageId: "invalid",
149
108
  node: id,
150
- data: {
151
- name: name3
152
- }
109
+ data: { name: name3, rule }
153
110
  });
154
111
  }
155
112
  for (const { node: component } of classComponents.values()) {
156
113
  const id = AST.getClassIdentifier(component);
157
114
  if (id?.name == null) continue;
158
115
  const name3 = id.name;
159
- const violation = getViolationMessage(name3, options);
160
- if (violation == null) continue;
116
+ if (isValidName(name3, options)) continue;
161
117
  context.report({
162
- messageId: violation,
118
+ messageId: "invalid",
163
119
  node: id,
164
- data: {
165
- case: options.rule
166
- }
120
+ data: { name: name3, rule }
167
121
  });
168
122
  }
169
123
  }
@@ -171,15 +125,41 @@ var component_name_default = createRule({
171
125
  },
172
126
  defaultOptions
173
127
  });
128
+ function normalizeOptions(options) {
129
+ const opts = options[0];
130
+ const defaultOpts = defaultOptions[0];
131
+ if (opts == null) return defaultOpts;
132
+ return {
133
+ ...defaultOpts,
134
+ ...typeof opts === "string" ? { rule: opts } : {
135
+ ...opts,
136
+ excepts: opts.excepts?.map((pattern) => new RegExp(pattern, "u")) ?? []
137
+ }
138
+ };
139
+ }
140
+ function isValidName(name3, options) {
141
+ if (name3 == null) return true;
142
+ if (options.excepts.some((regex) => regex.test(name3))) return true;
143
+ const normalized = name3.split(".").at(-1) ?? name3;
144
+ switch (options.rule) {
145
+ case "CONSTANT_CASE":
146
+ return RE_CONSTANT_CASE.test(normalized);
147
+ case "PascalCase":
148
+ if (normalized.length > 3 && /^[A-Z]+$/u.test(normalized)) {
149
+ return options.allowAllCaps;
150
+ }
151
+ return RE_PASCAL_CASE.test(normalized);
152
+ }
153
+ }
174
154
  var RULE_NAME2 = "context-name";
175
155
  var context_name_default = createRule({
176
156
  meta: {
177
157
  type: "problem",
178
158
  docs: {
179
- description: "enforces context name to be a valid component name with the suffix 'Context'"
159
+ description: "enforce context name to be a valid component name with the suffix 'Context'"
180
160
  },
181
161
  messages: {
182
- contextName: "In React 19, you can render '<Context>' as a provider instead of '<Context.Provider>', it's name must be a valid component name with the suffix 'Context'."
162
+ invalid: "A context name must be a valid component name with the suffix 'Context'."
183
163
  },
184
164
  schema: []
185
165
  },
@@ -194,7 +174,7 @@ var context_name_default = createRule({
194
174
  const name3 = match(id).with({ type: AST_NODE_TYPES.Identifier, name: P.select() }, identity).with({ type: AST_NODE_TYPES.MemberExpression, property: { name: P.select(P.string) } }, identity).otherwise(() => _);
195
175
  if (name3 != null && /^[A-Z]/u.test(name3) && name3.endsWith("Context")) return;
196
176
  context.report({
197
- messageId: "contextName",
177
+ messageId: "invalid",
198
178
  node: id
199
179
  });
200
180
  }
@@ -247,8 +227,8 @@ var filename_default = createRule({
247
227
  description: "enforce naming convention for JSX filenames"
248
228
  },
249
229
  messages: {
250
- filenameCaseMismatch: "A file with name '{{name}}' does not match {{rule}}. Should rename to '{{suggestion}}'.",
251
- filenameEmpty: "A file must have non-empty name."
230
+ filenameEmpty: "A file must have non-empty name.",
231
+ filenameInvalid: "A file with name '{{name}}' does not match {{rule}}. Rename it to '{{suggestion}}'."
252
232
  },
253
233
  schema: schema2
254
234
  },
@@ -276,7 +256,7 @@ var filename_default = createRule({
276
256
  return;
277
257
  }
278
258
  context.report({
279
- messageId: "filenameCaseMismatch",
259
+ messageId: "filenameInvalid",
280
260
  node,
281
261
  data: {
282
262
  name: context.filename,
@@ -334,7 +314,7 @@ var filename_extension_default = createRule({
334
314
  },
335
315
  messages: {
336
316
  useJsxFileExtension: "Use {{extensions}} file extension for JSX files.",
337
- useJsxFileExtensionAsNeeded: "Do not use {{extensions}} file extension for files without JSX."
317
+ useNonJsxFileExtension: "Do not use {{extensions}} file extension for files without JSX."
338
318
  },
339
319
  schema: schema3
340
320
  },
@@ -373,7 +353,7 @@ var filename_extension_default = createRule({
373
353
  }
374
354
  if (!hasJSXNode && isJSXExt && allow === "as-needed") {
375
355
  context.report({
376
- messageId: "useJsxFileExtensionAsNeeded",
356
+ messageId: "useNonJsxFileExtension",
377
357
  node,
378
358
  data: {
379
359
  extensions: extensionsString
@@ -397,7 +377,7 @@ var use_state_default = createRule({
397
377
  [Symbol.for("rule_features")]: RULE_FEATURES
398
378
  },
399
379
  messages: {
400
- badValueOrSetterName: "An useState call is not destructured into value + setter pair."
380
+ invalid: "An useState call is not destructured into value + setter pair."
401
381
  },
402
382
  schema: []
403
383
  },
@@ -406,21 +386,21 @@ var use_state_default = createRule({
406
386
  return {
407
387
  "CallExpression[callee.name='useState']"(node) {
408
388
  if (node.parent.type !== AST_NODE_TYPES.VariableDeclarator) {
409
- context.report({ messageId: "badValueOrSetterName", node });
389
+ context.report({ messageId: "invalid", node });
410
390
  }
411
391
  const id = getInstanceId(node);
412
392
  if (id?.type !== AST_NODE_TYPES.ArrayPattern) {
413
- context.report({ messageId: "badValueOrSetterName", node });
393
+ context.report({ messageId: "invalid", node });
414
394
  return;
415
395
  }
416
396
  const [value, setter] = id.elements;
417
397
  if (value == null || setter == null) {
418
- context.report({ messageId: "badValueOrSetterName", node });
398
+ context.report({ messageId: "invalid", node });
419
399
  return;
420
400
  }
421
401
  const setterName = match(setter).with({ type: AST_NODE_TYPES.Identifier }, (id2) => id2.name).otherwise(() => _);
422
402
  if (setterName == null || !setterName.startsWith("set")) {
423
- context.report({ messageId: "badValueOrSetterName", node });
403
+ context.report({ messageId: "invalid", node });
424
404
  return;
425
405
  }
426
406
  const valueName = match(value).with({ type: AST_NODE_TYPES.Identifier }, (id2) => id2.name).with({ type: AST_NODE_TYPES.ObjectPattern }, ({ properties }) => {
@@ -433,7 +413,7 @@ var use_state_default = createRule({
433
413
  return values.join("_");
434
414
  }).otherwise(() => _);
435
415
  if (valueName == null || `set_${valueName}` !== snakeCase(setterName)) {
436
- context.report({ messageId: "badValueOrSetterName", node });
416
+ context.report({ messageId: "invalid", node });
437
417
  return;
438
418
  }
439
419
  }
@@ -449,11 +429,11 @@ var plugin = {
449
429
  version
450
430
  },
451
431
  rules: {
452
- "component-name": component_name_default,
453
- "context-name": context_name_default,
454
- filename: filename_default,
455
- "filename-extension": filename_extension_default,
456
- "use-state": use_state_default
432
+ ["component-name"]: component_name_default,
433
+ ["context-name"]: context_name_default,
434
+ ["filename"]: filename_default,
435
+ ["filename-extension"]: filename_extension_default,
436
+ ["use-state"]: use_state_default
457
437
  }
458
438
  };
459
439
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-naming-convention",
3
- "version": "1.29.1-next.5",
3
+ "version": "1.29.1-next.7",
4
4
  "description": "ESLint React's ESLint plugin for naming convention related rules.",
5
5
  "keywords": [
6
6
  "react",
@@ -49,12 +49,12 @@
49
49
  "@typescript-eslint/utils": "^8.25.0",
50
50
  "string-ts": "^2.2.1",
51
51
  "ts-pattern": "^5.6.2",
52
- "@eslint-react/ast": "1.29.1-next.5",
53
- "@eslint-react/eff": "1.29.1-next.5",
54
- "@eslint-react/shared": "1.29.1-next.5",
55
- "@eslint-react/jsx": "1.29.1-next.5",
56
- "@eslint-react/core": "1.29.1-next.5",
57
- "@eslint-react/var": "1.29.1-next.5"
52
+ "@eslint-react/ast": "1.29.1-next.7",
53
+ "@eslint-react/core": "1.29.1-next.7",
54
+ "@eslint-react/jsx": "1.29.1-next.7",
55
+ "@eslint-react/var": "1.29.1-next.7",
56
+ "@eslint-react/eff": "1.29.1-next.7",
57
+ "@eslint-react/shared": "1.29.1-next.7"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@types/react": "^19.0.10",