eslint-plugin-react-naming-convention 2.13.0-next.0 → 2.13.0-next.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 (2) hide show
  1. package/dist/index.js +206 -172
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -5,10 +5,10 @@ import { findEnclosingAssignmentTarget } from "@eslint-react/var";
5
5
  import { AST_NODE_TYPES } from "@typescript-eslint/types";
6
6
  import { compare } from "compare-versions";
7
7
  import { P, match } from "ts-pattern";
8
- import path from "node:path";
8
+ import * as ast from "@eslint-react/ast";
9
9
  import { camelCase, kebabCase, pascalCase, snakeCase } from "string-ts";
10
+ import path from "node:path";
10
11
  import { isObject } from "@eslint-react/eff";
11
- import * as ast from "@eslint-react/ast";
12
12
 
13
13
  //#region \0rolldown/runtime.js
14
14
  var __defProp = Object.defineProperty;
@@ -35,6 +35,7 @@ var recommended_exports = /* @__PURE__ */ __exportAll({
35
35
  const name$1 = "react-naming-convention/recommended";
36
36
  const rules = {
37
37
  "react-naming-convention/context-name": "warn",
38
+ "react-naming-convention/id-name": "warn",
38
39
  "react-naming-convention/ref-name": "warn",
39
40
  "react-naming-convention/use-state": "warn"
40
41
  };
@@ -42,7 +43,7 @@ const rules = {
42
43
  //#endregion
43
44
  //#region package.json
44
45
  var name = "eslint-plugin-react-naming-convention";
45
- var version = "2.13.0-next.0";
46
+ var version = "2.13.0-next.2";
46
47
 
47
48
  //#endregion
48
49
  //#region src/utils/create-rule.ts
@@ -79,7 +80,7 @@ const schema$3 = [{ anyOf: [{
79
80
  }
80
81
  }
81
82
  }] }];
82
- const RULE_NAME$5 = "component-name";
83
+ const RULE_NAME$6 = "component-name";
83
84
  var component_name_default = createRule({
84
85
  meta: {
85
86
  type: "problem",
@@ -88,11 +89,11 @@ var component_name_default = createRule({
88
89
  messages: { invalidComponentName: "A component name '{{name}}' does not match {{rule}}." },
89
90
  schema: schema$3
90
91
  },
91
- name: RULE_NAME$5,
92
- create: create$5,
92
+ name: RULE_NAME$6,
93
+ create: create$6,
93
94
  defaultOptions: defaultOptions$3
94
95
  });
95
- function create$5(context) {
96
+ function create$6(context) {
96
97
  const options = normalizeOptions(context.options);
97
98
  const { rule } = options;
98
99
  const fCollector = core.useComponentCollector(context);
@@ -148,7 +149,7 @@ function isValidName(name, options) {
148
149
 
149
150
  //#endregion
150
151
  //#region src/rules/context-name.ts
151
- const RULE_NAME$4 = "context-name";
152
+ const RULE_NAME$5 = "context-name";
152
153
  var context_name_default = createRule({
153
154
  meta: {
154
155
  type: "suggestion",
@@ -156,11 +157,11 @@ var context_name_default = createRule({
156
157
  messages: { invalidContextName: "A context name must be a valid component name with the suffix 'Context'." },
157
158
  schema: []
158
159
  },
159
- name: RULE_NAME$4,
160
- create: create$4,
160
+ name: RULE_NAME$5,
161
+ create: create$5,
161
162
  defaultOptions: []
162
163
  });
163
- function create$4(context) {
164
+ function create$5(context) {
164
165
  if (!context.sourceCode.text.includes("createContext")) return {};
165
166
  const { version } = getSettingsFromContext(context);
166
167
  if (compare(version, "19.0.0", "<")) return {};
@@ -183,9 +184,175 @@ function create$4(context) {
183
184
  }
184
185
 
185
186
  //#endregion
186
- //#region src/rules/file-name.ts
187
- const RULE_NAME$3 = "file-name";
187
+ //#region src/rules/id-name.ts
188
+ const RULE_NAME$4 = "id-name";
189
+ var id_name_default = createRule({
190
+ meta: {
191
+ type: "suggestion",
192
+ docs: { description: "Enforces identifier names assigned from 'useId' calls to be either 'id' or end with 'Id'." },
193
+ messages: { invalidIdName: "An identifier assigned from 'useId' must be named 'id' or end with 'Id'." },
194
+ schema: []
195
+ },
196
+ name: RULE_NAME$4,
197
+ create: create$4,
198
+ defaultOptions: []
199
+ });
200
+ function create$4(context) {
201
+ if (!context.sourceCode.text.includes("useId")) return {};
202
+ return { CallExpression(node) {
203
+ if (!core.isUseIdCall(node)) return;
204
+ const [id, name] = match(findEnclosingAssignmentTarget(node)).with({
205
+ type: AST_NODE_TYPES.Identifier,
206
+ name: P.string
207
+ }, (id) => [id, id.name]).with({
208
+ type: AST_NODE_TYPES.MemberExpression,
209
+ property: { name: P.string }
210
+ }, (id) => [id, id.property.name]).otherwise(() => [null, null]);
211
+ if (id == null) return;
212
+ if (name.endsWith("Id") || name === "id") return;
213
+ context.report({
214
+ messageId: "invalidIdName",
215
+ node: id
216
+ });
217
+ } };
218
+ }
219
+
220
+ //#endregion
221
+ //#region src/rules/ref-name.ts
222
+ const RULE_NAME$3 = "ref-name";
223
+ var ref_name_default = createRule({
224
+ meta: {
225
+ type: "suggestion",
226
+ docs: { description: "Enforces identifier names assigned from 'useRef' calls to be either 'ref' or end with 'Ref'." },
227
+ messages: { invalidRefName: "A ref identifier must be named 'ref' or ending in 'Ref'." },
228
+ schema: []
229
+ },
230
+ name: RULE_NAME$3,
231
+ create: create$3,
232
+ defaultOptions: []
233
+ });
234
+ function create$3(context) {
235
+ if (!context.sourceCode.text.includes("useRef")) return {};
236
+ return { CallExpression(node) {
237
+ if (!core.isUseRefCall(node)) return;
238
+ if (ast.getUnderlyingExpression(node.parent).type === AST_NODE_TYPES.MemberExpression) return;
239
+ const [id, name] = match(findEnclosingAssignmentTarget(node)).with({
240
+ type: AST_NODE_TYPES.Identifier,
241
+ name: P.string
242
+ }, (id) => [id, id.name]).with({
243
+ type: AST_NODE_TYPES.MemberExpression,
244
+ property: { name: P.string }
245
+ }, (id) => [id, id.property.name]).otherwise(() => [null, null]);
246
+ if (id == null) return;
247
+ if (name.endsWith("Ref") || name === "ref") return;
248
+ context.report({
249
+ messageId: "invalidRefName",
250
+ node: id
251
+ });
252
+ } };
253
+ }
254
+
255
+ //#endregion
256
+ //#region src/rules/use-state.ts
257
+ const RULE_NAME$2 = "use-state";
188
258
  const defaultOptions$2 = [{
259
+ enforceAssignment: false,
260
+ enforceSetterName: true
261
+ }];
262
+ const schema$2 = [{
263
+ type: "object",
264
+ additionalProperties: false,
265
+ properties: {
266
+ enforceAssignment: {
267
+ type: "boolean",
268
+ default: false
269
+ },
270
+ enforceSetterName: {
271
+ type: "boolean",
272
+ default: true
273
+ }
274
+ }
275
+ }];
276
+ var use_state_default = createRule({
277
+ meta: {
278
+ type: "suggestion",
279
+ docs: { description: "Enforces destructuring and symmetric naming of the 'useState' hook value and setter." },
280
+ messages: {
281
+ invalidAssignment: "useState should be destructured into a value and setter pair, e.g., const [state, setState] = useState(...).",
282
+ invalidSetterName: "The setter should be named 'set' followed by the capitalized state variable name, e.g., 'setState' for 'state'."
283
+ },
284
+ schema: schema$2
285
+ },
286
+ name: RULE_NAME$2,
287
+ create: create$2,
288
+ defaultOptions: defaultOptions$2
289
+ });
290
+ function create$2(context) {
291
+ const { enforceAssignment = false, enforceSetterName = true } = context.options[0] ?? defaultOptions$2[0];
292
+ return { CallExpression(node) {
293
+ if (!core.isUseStateCall(node)) return;
294
+ if (node.parent.type !== AST_NODE_TYPES.VariableDeclarator) {
295
+ if (!enforceAssignment) return;
296
+ context.report({
297
+ messageId: "invalidAssignment",
298
+ node
299
+ });
300
+ return;
301
+ }
302
+ const id = findEnclosingAssignmentTarget(node);
303
+ if (id?.type !== AST_NODE_TYPES.ArrayPattern) {
304
+ if (!enforceAssignment) return;
305
+ context.report({
306
+ messageId: "invalidAssignment",
307
+ node: id ?? node
308
+ });
309
+ return;
310
+ }
311
+ const [value, setter] = id.elements;
312
+ if (value == null) {
313
+ if (!enforceAssignment) return;
314
+ context.report({
315
+ messageId: "invalidAssignment",
316
+ node: id
317
+ });
318
+ return;
319
+ }
320
+ if (setter == null || !enforceSetterName) return;
321
+ const setterName = match(setter).with({ type: AST_NODE_TYPES.Identifier }, (id) => id.name).otherwise(() => null);
322
+ if (setterName == null || !setterName.startsWith("set")) {
323
+ context.report({
324
+ messageId: "invalidSetterName",
325
+ node: setter
326
+ });
327
+ return;
328
+ }
329
+ const valueName = match(value).with({ type: AST_NODE_TYPES.Identifier }, ({ name }) => snakeCase(name)).with({ type: AST_NODE_TYPES.ObjectPattern }, ({ properties }) => {
330
+ return properties.reduce((acc, prop) => {
331
+ if (prop.type === AST_NODE_TYPES.Property && prop.key.type === AST_NODE_TYPES.Identifier) return [...acc, prop.key.name];
332
+ return acc;
333
+ }, []).join("_");
334
+ }).otherwise(() => null);
335
+ if (valueName == null) {
336
+ context.report({
337
+ messageId: "invalidSetterName",
338
+ node: value
339
+ });
340
+ return;
341
+ }
342
+ if (snakeCase(setterName) !== `set_${valueName}`) {
343
+ context.report({
344
+ messageId: "invalidSetterName",
345
+ node: setter
346
+ });
347
+ return;
348
+ }
349
+ } };
350
+ }
351
+
352
+ //#endregion
353
+ //#region src/rules-removed/filename.ts
354
+ const RULE_NAME$1 = "filename";
355
+ const defaultOptions$1 = [{
189
356
  excepts: [
190
357
  "index",
191
358
  String.raw`/^_/`,
@@ -195,7 +362,7 @@ const defaultOptions$2 = [{
195
362
  ],
196
363
  rule: "PascalCase"
197
364
  }];
198
- const schema$2 = [{ anyOf: [{
365
+ const schema$1 = [{ anyOf: [{
199
366
  type: "string",
200
367
  enum: [
201
368
  "PascalCase",
@@ -230,23 +397,23 @@ const schema$2 = [{ anyOf: [{
230
397
  }
231
398
  }
232
399
  }] }];
233
- var file_name_default = createRule({
400
+ var filename_default = createRule({
234
401
  meta: {
235
402
  type: "suggestion",
236
- defaultOptions: [...defaultOptions$2],
403
+ defaultOptions: [...defaultOptions$1],
237
404
  docs: { description: "Enforces consistent file-naming conventions." },
238
405
  messages: {
239
406
  fileNameEmpty: "A source file must have non-empty name.",
240
407
  fileNameInvalidCase: "A source file with name '{{name}}' does not match {{rule}}. Rename it to '{{suggestion}}'."
241
408
  },
242
- schema: schema$2
409
+ schema: schema$1
243
410
  },
244
- name: RULE_NAME$3,
245
- create: create$3,
246
- defaultOptions: defaultOptions$2
411
+ name: RULE_NAME$1,
412
+ create: create$1,
413
+ defaultOptions: defaultOptions$1
247
414
  });
248
- function create$3(context) {
249
- const options = context.options[0] ?? defaultOptions$2[0];
415
+ function create$1(context) {
416
+ const options = context.options[0] ?? defaultOptions$1[0];
250
417
  const rule = typeof options === "string" ? options : options.rule ?? "PascalCase";
251
418
  const excepts = typeof options === "string" ? [] : (options.excepts ?? []).map((s) => toRegExp(s));
252
419
  function validate(name, casing = rule, ignores = excepts) {
@@ -281,14 +448,14 @@ function create$3(context) {
281
448
  }
282
449
 
283
450
  //#endregion
284
- //#region src/rules/file-name-extension.ts
285
- const RULE_NAME$2 = "file-name-extension";
286
- const defaultOptions$1 = [{
451
+ //#region src/rules-removed/filename-extension.ts
452
+ const RULE_NAME = "filename-extension";
453
+ const defaultOptions = [{
287
454
  allow: "as-needed",
288
455
  extensions: [".jsx", ".tsx"],
289
456
  ignoreFilesWithoutCode: false
290
457
  }];
291
- const schema$1 = [{ anyOf: [{
458
+ const schema = [{ anyOf: [{
292
459
  type: "string",
293
460
  enum: ["always", "as-needed"]
294
461
  }, {
@@ -307,25 +474,25 @@ const schema$1 = [{ anyOf: [{
307
474
  ignoreFilesWithoutCode: { type: "boolean" }
308
475
  }
309
476
  }] }];
310
- var file_name_extension_default = createRule({
477
+ var filename_extension_default = createRule({
311
478
  meta: {
312
479
  type: "suggestion",
313
- defaultOptions: [...defaultOptions$1],
480
+ defaultOptions: [...defaultOptions],
314
481
  docs: { description: "Enforces consistent use of the JSX file extension." },
315
482
  messages: {
316
483
  missingJsxExtension: "Use {{extensions}} file extension for JSX files.",
317
484
  unnecessaryJsxExtension: "Do not use {{extensions}} file extension for files without JSX."
318
485
  },
319
- schema: schema$1
486
+ schema
320
487
  },
321
- name: RULE_NAME$2,
322
- create: create$2,
323
- defaultOptions: defaultOptions$1
488
+ name: RULE_NAME,
489
+ create,
490
+ defaultOptions
324
491
  });
325
- function create$2(context) {
326
- const options = context.options[0] ?? defaultOptions$1[0];
492
+ function create(context) {
493
+ const options = context.options[0] ?? defaultOptions[0];
327
494
  const allow = isObject(options) ? options.allow : options;
328
- const extensions = isObject(options) && "extensions" in options ? options.extensions : defaultOptions$1[0].extensions;
495
+ const extensions = isObject(options) && "extensions" in options ? options.extensions : defaultOptions[0].extensions;
329
496
  const extensionsString = extensions.map((ext) => `'${ext}'`).join(", ");
330
497
  const filename = context.filename;
331
498
  let hasJSXNode = false;
@@ -359,138 +526,6 @@ function create$2(context) {
359
526
  };
360
527
  }
361
528
 
362
- //#endregion
363
- //#region src/rules/ref-name.ts
364
- const RULE_NAME$1 = "ref-name";
365
- var ref_name_default = createRule({
366
- meta: {
367
- type: "suggestion",
368
- docs: { description: "Enforces identifier names assigned from 'useRef' calls to be either 'ref' or end with 'Ref'." },
369
- messages: { invalidRefName: "A ref identifier must be named 'ref' or ending in 'Ref'." },
370
- schema: []
371
- },
372
- name: RULE_NAME$1,
373
- create: create$1,
374
- defaultOptions: []
375
- });
376
- function create$1(context) {
377
- if (!context.sourceCode.text.includes("useRef")) return {};
378
- return { CallExpression(node) {
379
- if (!core.isUseRefCall(node)) return;
380
- if (ast.getUnderlyingExpression(node.parent).type === AST_NODE_TYPES.MemberExpression) return;
381
- const [id, name] = match(findEnclosingAssignmentTarget(node)).with({
382
- type: AST_NODE_TYPES.Identifier,
383
- name: P.string
384
- }, (id) => [id, id.name]).with({
385
- type: AST_NODE_TYPES.MemberExpression,
386
- property: { name: P.string }
387
- }, (id) => [id, id.property.name]).otherwise(() => [null, null]);
388
- if (id == null) return;
389
- if (name.endsWith("Ref") || name === "ref") return;
390
- context.report({
391
- messageId: "invalidRefName",
392
- node: id
393
- });
394
- } };
395
- }
396
-
397
- //#endregion
398
- //#region src/rules/use-state.ts
399
- const RULE_NAME = "use-state";
400
- const defaultOptions = [{
401
- enforceAssignment: false,
402
- enforceSetterName: true
403
- }];
404
- const schema = [{
405
- type: "object",
406
- additionalProperties: false,
407
- properties: {
408
- enforceAssignment: {
409
- type: "boolean",
410
- default: false
411
- },
412
- enforceSetterName: {
413
- type: "boolean",
414
- default: true
415
- }
416
- }
417
- }];
418
- var use_state_default = createRule({
419
- meta: {
420
- type: "suggestion",
421
- docs: { description: "Enforces destructuring and symmetric naming of the 'useState' hook value and setter." },
422
- messages: {
423
- invalidAssignment: "useState should be destructured into a value and setter pair, e.g., const [state, setState] = useState(...).",
424
- invalidSetterName: "The setter should be named 'set' followed by the capitalized state variable name, e.g., 'setState' for 'state'."
425
- },
426
- schema
427
- },
428
- name: RULE_NAME,
429
- create,
430
- defaultOptions
431
- });
432
- function create(context) {
433
- const { enforceAssignment = false, enforceSetterName = true } = context.options[0] ?? defaultOptions[0];
434
- return { CallExpression(node) {
435
- if (!core.isUseStateCall(node)) return;
436
- if (node.parent.type !== AST_NODE_TYPES.VariableDeclarator) {
437
- if (!enforceAssignment) return;
438
- context.report({
439
- messageId: "invalidAssignment",
440
- node
441
- });
442
- return;
443
- }
444
- const id = findEnclosingAssignmentTarget(node);
445
- if (id?.type !== AST_NODE_TYPES.ArrayPattern) {
446
- if (!enforceAssignment) return;
447
- context.report({
448
- messageId: "invalidAssignment",
449
- node: id ?? node
450
- });
451
- return;
452
- }
453
- const [value, setter] = id.elements;
454
- if (value == null) {
455
- if (!enforceAssignment) return;
456
- context.report({
457
- messageId: "invalidAssignment",
458
- node: id
459
- });
460
- return;
461
- }
462
- if (setter == null || !enforceSetterName) return;
463
- const setterName = match(setter).with({ type: AST_NODE_TYPES.Identifier }, (id) => id.name).otherwise(() => null);
464
- if (setterName == null || !setterName.startsWith("set")) {
465
- context.report({
466
- messageId: "invalidSetterName",
467
- node: setter
468
- });
469
- return;
470
- }
471
- const valueName = match(value).with({ type: AST_NODE_TYPES.Identifier }, ({ name }) => snakeCase(name)).with({ type: AST_NODE_TYPES.ObjectPattern }, ({ properties }) => {
472
- return properties.reduce((acc, prop) => {
473
- if (prop.type === AST_NODE_TYPES.Property && prop.key.type === AST_NODE_TYPES.Identifier) return [...acc, prop.key.name];
474
- return acc;
475
- }, []).join("_");
476
- }).otherwise(() => null);
477
- if (valueName == null) {
478
- context.report({
479
- messageId: "invalidSetterName",
480
- node: value
481
- });
482
- return;
483
- }
484
- if (snakeCase(setterName) !== `set_${valueName}`) {
485
- context.report({
486
- messageId: "invalidSetterName",
487
- node: setter
488
- });
489
- return;
490
- }
491
- } };
492
- }
493
-
494
529
  //#endregion
495
530
  //#region src/plugin.ts
496
531
  const plugin = {
@@ -501,12 +536,11 @@ const plugin = {
501
536
  rules: {
502
537
  ["component-name"]: component_name_default,
503
538
  ["context-name"]: context_name_default,
504
- ["file-name"]: file_name_default,
505
- ["file-name-extension"]: file_name_extension_default,
506
- ["filename"]: file_name_default,
507
- ["filename-extension"]: file_name_extension_default,
539
+ ["id-name"]: id_name_default,
508
540
  ["ref-name"]: ref_name_default,
509
- ["use-state"]: use_state_default
541
+ ["use-state"]: use_state_default,
542
+ ["filename"]: filename_default,
543
+ ["filename-extension"]: filename_extension_default
510
544
  }
511
545
  };
512
546
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-naming-convention",
3
- "version": "2.13.0-next.0",
3
+ "version": "2.13.0-next.2",
4
4
  "description": "ESLint React's ESLint plugin for naming convention related rules.",
5
5
  "keywords": [
6
6
  "react",
@@ -45,11 +45,11 @@
45
45
  "compare-versions": "^6.1.1",
46
46
  "string-ts": "^2.3.1",
47
47
  "ts-pattern": "^5.9.0",
48
- "@eslint-react/ast": "2.13.0-next.0",
49
- "@eslint-react/core": "2.13.0-next.0",
50
- "@eslint-react/eff": "2.13.0-next.0",
51
- "@eslint-react/shared": "2.13.0-next.0",
52
- "@eslint-react/var": "2.13.0-next.0"
48
+ "@eslint-react/ast": "2.13.0-next.2",
49
+ "@eslint-react/core": "2.13.0-next.2",
50
+ "@eslint-react/eff": "2.13.0-next.2",
51
+ "@eslint-react/shared": "2.13.0-next.2",
52
+ "@eslint-react/var": "2.13.0-next.2"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@types/react": "^19.2.14",