From 3fe543c57af91e31ee80a3360b600f1286d2dc69 Mon Sep 17 00:00:00 2001 From: Rel1cx Date: Sun, 2 Mar 2025 21:03:53 +0800 Subject: [PATCH] fix: rework 'naming-convention/component-name' rule --- .../src/rules/no-missing-button-type.ts | 4 +- .../src/rules/no-missing-iframe-sandbox.ts | 4 +- .../src/rules/no-namespace.ts | 2 +- .../src/rules/no-unsafe-iframe-sandbox.ts | 4 +- .../src/rules/no-unsafe-target-blank.ts | 4 +- .../rules/no-void-elements-with-children.ts | 2 +- ....ts => get-element-type-on-jsx-and-dom.ts} | 4 +- .../src/utils/index.ts | 2 +- .../src/plugin.ts | 10 +- .../src/rules/component-name.md | 19 ++- .../src/rules/component-name.spec.ts | 110 ++++++++++------- .../src/rules/component-name.ts | 113 +++++++++--------- .../src/rules/filename-extension.ts | 3 +- .../src/rules/filename.ts | 7 +- .../eslint-plugin-react-x/src/plugin.ts | 6 +- .../src/rules/no-context-provider.ts | 2 +- .../src/rules/no-unstable-context-value.ts | 2 +- ...et-element-name.ts => get-element-type.ts} | 2 +- packages/utilities/jsx/src/index.ts | 2 +- .../utilities/jsx/src/is-kind-of-element.ts | 4 +- 20 files changed, 162 insertions(+), 144 deletions(-) rename packages/plugins/eslint-plugin-react-dom/src/utils/{get-element-name-on-jsx-and-dom.ts => get-element-type-on-jsx-and-dom.ts} (94%) rename packages/utilities/jsx/src/{get-element-name.ts => get-element-type.ts} (86%) diff --git a/packages/plugins/eslint-plugin-react-dom/src/rules/no-missing-button-type.ts b/packages/plugins/eslint-plugin-react-dom/src/rules/no-missing-button-type.ts index 452b45270..c20e038da 100644 --- a/packages/plugins/eslint-plugin-react-dom/src/rules/no-missing-button-type.ts +++ b/packages/plugins/eslint-plugin-react-dom/src/rules/no-missing-button-type.ts @@ -3,7 +3,7 @@ import type { RuleFeature } from "@eslint-react/shared"; import { getSettingsFromContext } from "@eslint-react/shared"; import type { CamelCase } from "string-ts"; -import { createRule, findCustomComponent, findCustomComponentProp, getElementNameOnJsxAndDom } from "../utils"; +import { createRule, findCustomComponent, findCustomComponentProp, getElementTypeOnJsxAndDom } from "../utils"; export const RULE_NAME = "no-missing-button-type"; @@ -33,7 +33,7 @@ export default createRule<[], MessageID>({ return { JSXElement(node) { - const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom( + const [elementNameOnJsx, elementNameOnDom] = getElementTypeOnJsxAndDom( context, node, polymorphicPropName, diff --git a/packages/plugins/eslint-plugin-react-dom/src/rules/no-missing-iframe-sandbox.ts b/packages/plugins/eslint-plugin-react-dom/src/rules/no-missing-iframe-sandbox.ts index 3a818bc8e..777d7b2f0 100644 --- a/packages/plugins/eslint-plugin-react-dom/src/rules/no-missing-iframe-sandbox.ts +++ b/packages/plugins/eslint-plugin-react-dom/src/rules/no-missing-iframe-sandbox.ts @@ -3,7 +3,7 @@ import type { RuleFeature } from "@eslint-react/shared"; import { getSettingsFromContext } from "@eslint-react/shared"; import type { CamelCase } from "string-ts"; -import { createRule, findCustomComponent, findCustomComponentProp, getElementNameOnJsxAndDom } from "../utils"; +import { createRule, findCustomComponent, findCustomComponentProp, getElementTypeOnJsxAndDom } from "../utils"; export const RULE_NAME = "no-missing-iframe-sandbox"; @@ -58,7 +58,7 @@ export default createRule<[], MessageID>({ const additionalComponents = settings.additionalComponents.filter((c) => c.as === "iframe"); return { JSXElement(node) { - const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom( + const [elementNameOnJsx, elementNameOnDom] = getElementTypeOnJsxAndDom( context, node, polymorphicPropName, diff --git a/packages/plugins/eslint-plugin-react-dom/src/rules/no-namespace.ts b/packages/plugins/eslint-plugin-react-dom/src/rules/no-namespace.ts index c736256e1..5a631dc96 100644 --- a/packages/plugins/eslint-plugin-react-dom/src/rules/no-namespace.ts +++ b/packages/plugins/eslint-plugin-react-dom/src/rules/no-namespace.ts @@ -28,7 +28,7 @@ export default createRule<[], MessageID>({ create(context) { return { JSXElement(node) { - const name = JSX.getElementName(node); + const name = JSX.getElementType(node); if (typeof name !== "string" || !name.includes(":")) { return; } diff --git a/packages/plugins/eslint-plugin-react-dom/src/rules/no-unsafe-iframe-sandbox.ts b/packages/plugins/eslint-plugin-react-dom/src/rules/no-unsafe-iframe-sandbox.ts index 993eeaa48..52324661c 100644 --- a/packages/plugins/eslint-plugin-react-dom/src/rules/no-unsafe-iframe-sandbox.ts +++ b/packages/plugins/eslint-plugin-react-dom/src/rules/no-unsafe-iframe-sandbox.ts @@ -3,7 +3,7 @@ import type { RuleFeature } from "@eslint-react/shared"; import { getSettingsFromContext } from "@eslint-react/shared"; import type { CamelCase } from "string-ts"; -import { createRule, findCustomComponent, findCustomComponentProp, getElementNameOnJsxAndDom } from "../utils"; +import { createRule, findCustomComponent, findCustomComponentProp, getElementTypeOnJsxAndDom } from "../utils"; export const RULE_NAME = "no-unsafe-iframe-sandbox"; @@ -43,7 +43,7 @@ export default createRule<[], MessageID>({ const additionalComponents = settings.additionalComponents.filter((c) => c.as === "iframe"); return { JSXElement(node) { - const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom( + const [elementNameOnJsx, elementNameOnDom] = getElementTypeOnJsxAndDom( context, node, polymorphicPropName, diff --git a/packages/plugins/eslint-plugin-react-dom/src/rules/no-unsafe-target-blank.ts b/packages/plugins/eslint-plugin-react-dom/src/rules/no-unsafe-target-blank.ts index 07fad236f..c38229a53 100644 --- a/packages/plugins/eslint-plugin-react-dom/src/rules/no-unsafe-target-blank.ts +++ b/packages/plugins/eslint-plugin-react-dom/src/rules/no-unsafe-target-blank.ts @@ -5,7 +5,7 @@ import { getSettingsFromContext } from "@eslint-react/shared"; import type { TSESTree } from "@typescript-eslint/types"; import type { CamelCase } from "string-ts"; -import { createRule, findCustomComponent, findCustomComponentProp, getElementNameOnJsxAndDom } from "../utils"; +import { createRule, findCustomComponent, findCustomComponentProp, getElementTypeOnJsxAndDom } from "../utils"; export const RULE_NAME = "no-unsafe-target-blank"; @@ -48,7 +48,7 @@ export default createRule<[], MessageID>({ return { JSXElement(node: TSESTree.JSXElement) { - const [elementNameOnJsx, elementNameOnDom] = getElementNameOnJsxAndDom( + const [elementNameOnJsx, elementNameOnDom] = getElementTypeOnJsxAndDom( context, node, polymorphicPropName, diff --git a/packages/plugins/eslint-plugin-react-dom/src/rules/no-void-elements-with-children.ts b/packages/plugins/eslint-plugin-react-dom/src/rules/no-void-elements-with-children.ts index 9e8a46453..b510e04dc 100644 --- a/packages/plugins/eslint-plugin-react-dom/src/rules/no-void-elements-with-children.ts +++ b/packages/plugins/eslint-plugin-react-dom/src/rules/no-void-elements-with-children.ts @@ -48,7 +48,7 @@ export default createRule<[], MessageID>({ create(context) { return { JSXElement(node) { - const elementName = JSX.getElementName(node); + const elementName = JSX.getElementType(node); if (elementName.length === 0 || !voidElements.has(elementName)) { return; } diff --git a/packages/plugins/eslint-plugin-react-dom/src/utils/get-element-name-on-jsx-and-dom.ts b/packages/plugins/eslint-plugin-react-dom/src/utils/get-element-type-on-jsx-and-dom.ts similarity index 94% rename from packages/plugins/eslint-plugin-react-dom/src/utils/get-element-name-on-jsx-and-dom.ts rename to packages/plugins/eslint-plugin-react-dom/src/utils/get-element-type-on-jsx-and-dom.ts index ad10b8db5..1d100f6b8 100644 --- a/packages/plugins/eslint-plugin-react-dom/src/utils/get-element-name-on-jsx-and-dom.ts +++ b/packages/plugins/eslint-plugin-react-dom/src/utils/get-element-type-on-jsx-and-dom.ts @@ -2,13 +2,13 @@ import * as JSX from "@eslint-react/jsx"; import type { CustomComponentNormalized, RuleContext } from "@eslint-react/shared"; import type { TSESTree } from "@typescript-eslint/types"; -export function getElementNameOnJsxAndDom( +export function getElementTypeOnJsxAndDom( context: RuleContext, node: TSESTree.JSXElement, polymorphicPropName?: string, additionalComponents: CustomComponentNormalized[] = [], ): [string, string] { - const name = JSX.getElementName(node); + const name = JSX.getElementType(node); // Skip JsxIntrinsicElements if (name === name.toLowerCase()) return [name, name]; // Get the component name using the `settings["react-x"].additionalComponents` setting diff --git a/packages/plugins/eslint-plugin-react-dom/src/utils/index.ts b/packages/plugins/eslint-plugin-react-dom/src/utils/index.ts index 6f83f8eb5..0f22b88b9 100644 --- a/packages/plugins/eslint-plugin-react-dom/src/utils/index.ts +++ b/packages/plugins/eslint-plugin-react-dom/src/utils/index.ts @@ -1,3 +1,3 @@ export * from "./create-rule"; export * from "./find-custom-component"; -export * from "./get-element-name-on-jsx-and-dom"; +export * from "./get-element-type-on-jsx-and-dom"; diff --git a/packages/plugins/eslint-plugin-react-naming-convention/src/plugin.ts b/packages/plugins/eslint-plugin-react-naming-convention/src/plugin.ts index 6a1f31b53..362edcc1e 100644 --- a/packages/plugins/eslint-plugin-react-naming-convention/src/plugin.ts +++ b/packages/plugins/eslint-plugin-react-naming-convention/src/plugin.ts @@ -11,10 +11,10 @@ export const plugin = { version, }, rules: { - "component-name": componentName, - "context-name": contextName, - filename, - "filename-extension": filenameExtension, - "use-state": useState, + ["component-name"]: componentName, + ["context-name"]: contextName, + ["filename"]: filename, + ["filename-extension"]: filenameExtension, + ["use-state"]: useState, }, } as const; diff --git a/packages/plugins/eslint-plugin-react-naming-convention/src/rules/component-name.md b/packages/plugins/eslint-plugin-react-naming-convention/src/rules/component-name.md index 297ea1186..7e3a23dda 100644 --- a/packages/plugins/eslint-plugin-react-naming-convention/src/rules/component-name.md +++ b/packages/plugins/eslint-plugin-react-naming-convention/src/rules/component-name.md @@ -24,7 +24,7 @@ Enforces naming conventions for components. ## Examples -This rule enforces naming conventions for components. Can be used to enforce PascalCase and CONSTANT_CASE. By default, it enforces PascalCase. +This rule enforces naming conventions for components. Can be used to enforce `PascalCase` and `CONSTANT_CASE`. By default, it enforces `PascalCase`. ### Failing @@ -50,13 +50,13 @@ function MyComponent() { ## Rule Options -- `rule`: The rule to apply to the file name. Default is `"PascalCase"`. Possible values: - 1. `PascalCase`: PascalCase - 2. `CONSTANT_CASE`: CONSTANT_CASE +- `rule`: The rule to apply to the component name. Possible values: + - `PascalCase` (default) + - `CONSTANT_CASE` - `excepts`: (optional) An array of component names that are allowed to not follow the rule. -- `allowAllCaps`: (optional) If `true`, allows all caps file names. Default is `false`. -- `allowNamespace`: (optional) If `true`, allows namespace in JSX elements. Default is `false`. -- `allowLeadingUnderscore`: (optional) If `true`, allows leading underscore in file names. Default is `false`. +- `allowAllCaps`: (optional) If `true`, allows all caps component names. Default is `false`. + +## Rule Options Examples ```json { @@ -66,10 +66,7 @@ function MyComponent() { ```json { - "@eslint-react/naming-convention/component-name": [ - "warn", - { "rule": "PascalCase", "excepts": ["MyComponent"] } - ] + "@eslint-react/naming-convention/component-name": ["warn", { "rule": "PascalCase", "allowAllCaps": true }] } ``` diff --git a/packages/plugins/eslint-plugin-react-naming-convention/src/rules/component-name.spec.ts b/packages/plugins/eslint-plugin-react-naming-convention/src/rules/component-name.spec.ts index c5b4a2c56..c9b728a84 100644 --- a/packages/plugins/eslint-plugin-react-naming-convention/src/rules/component-name.spec.ts +++ b/packages/plugins/eslint-plugin-react-naming-convention/src/rules/component-name.spec.ts @@ -4,21 +4,40 @@ import rule, { RULE_NAME } from "./component-name"; ruleTester.run(RULE_NAME, rule, { invalid: [ { - code: /* tsx */ ``, + code: /* tsx */ ` + function Test_component() { + return
foo
+ } + `, errors: [{ messageId: "invalid", data: { name: "Test_component", rule: "PascalCase" } }], }, { - code: /* tsx */ ``, + code: /* tsx */ ` + function TestComponent() { + return
foo
+ } + `, errors: [{ messageId: "invalid", data: { name: "TestComponent", rule: "CONSTANT_CASE" } }], options: [{ rule: "CONSTANT_CASE" }], }, { - code: /* tsx */ ``, - errors: [{ messageId: "invalid", data: { name: "TestComponent", rule: "CONSTANT_CASE" } }], + code: /* tsx */ ` + function TestComponent() { + return
foo
+ } + `, + errors: [{ + messageId: "invalid", + data: { name: "TestComponent", rule: "CONSTANT_CASE" }, + }], options: ["CONSTANT_CASE"], }, { - code: /* tsx */ ``, + code: /* tsx */ ` + function FULLUPPERCASE() { + return
foo
+ } + `, errors: [{ messageId: "invalid", data: { name: "FULLUPPERCASE", rule: "PascalCase" } }], options: [{ allowAllCaps: false, rule: "PascalCase" }], }, @@ -39,50 +58,51 @@ ruleTester.run(RULE_NAME, rule, { ) } `, - errors: [{ messageId: "invalid", data: { name: "_Test", rule: "CONSTANT_CASE" } }], - options: [{ allowLeadingUnderscore: false, rule: "CONSTANT_CASE" }], - }, - ], - valid: [ - ...allFunctions, - "", - "", - "", - "", - "", - "", - "
", - "", - "", - "", - "", - "", - "

Hello!

", - "", - { - code: "", - options: [{ rule: "PascalCase" }], - }, - { - code: "", - options: [{ rule: "PascalCase" }], - }, - { - code: "", - options: [{ rule: "PascalCase" }], + errors: [{ + messageId: "invalid", + data: { + name: "_Test", + rule: "PascalCase", + }, + }], }, { - code: "", + code: /* tsx */ ` + export function _Test() { + return ( +
+ ) + } + `, + errors: [{ + messageId: "invalid", + data: { + name: "_Test", + rule: "PascalCase", + }, + }], options: [{ rule: "PascalCase" }], }, { - code: "", - options: [{ allowAllCaps: true, rule: "PascalCase" }], - }, - { - code: "", - options: [{ allowNamespace: true, rule: "PascalCase" }], + code: /* tsx */ ` + export function _TEST() { + return ( +
+ ) + } + `, + errors: [{ + messageId: "invalid", + data: { + name: "_TEST", + rule: "CONSTANT_CASE", + }, + }], + options: [{ rule: "CONSTANT_CASE" }], }, + ], + valid: [ + ...allFunctions, /* tsx */ ` function AppHome() { return
foo
@@ -94,7 +114,7 @@ ruleTester.run(RULE_NAME, rule, { return
foo
} `, - options: [{ allowLeadingUnderscore: true, rule: "CONSTANT_CASE" }], + options: [{ rule: "CONSTANT_CASE" }], }, /* tsx */ ` const AppHome = () => { @@ -107,7 +127,7 @@ ruleTester.run(RULE_NAME, rule, { return
foo
} `, - options: [{ allowAllCaps: true, allowLeadingUnderscore: true, rule: "CONSTANT_CASE" }], + options: [{ allowAllCaps: true, rule: "CONSTANT_CASE" }], }, { code: /* tsx */ ` diff --git a/packages/plugins/eslint-plugin-react-naming-convention/src/rules/component-name.ts b/packages/plugins/eslint-plugin-react-naming-convention/src/rules/component-name.ts index ed62f91d3..6c588c40e 100644 --- a/packages/plugins/eslint-plugin-react-naming-convention/src/rules/component-name.ts +++ b/packages/plugins/eslint-plugin-react-naming-convention/src/rules/component-name.ts @@ -1,31 +1,29 @@ import * as AST from "@eslint-react/ast"; import { useComponentCollector, useComponentCollectorLegacy } from "@eslint-react/core"; import type { _ } from "@eslint-react/eff"; -import * as JSX from "@eslint-react/jsx"; import type { RuleFeature } from "@eslint-react/shared"; import { RE_CONSTANT_CASE, RE_PASCAL_CASE } from "@eslint-react/shared"; import type { JSONSchema4 } from "@typescript-eslint/utils/json-schema"; import { createRule } from "../utils"; -export const RULE_NAME = "component-name"; - -export const RULE_FEATURES = [ - "CHK", - "CFG", -] as const satisfies RuleFeature[]; - -export type MessageID = "invalid"; - type Case = "CONSTANT_CASE" | "PascalCase"; /* eslint-disable no-restricted-syntax */ type Options = readonly [ + | _ | Case - | undefined | { allowAllCaps?: boolean; + /** + * @todo Remove in the next major version + * @deprecated Component names now need to start with an uppercase letter instead of a non-lowercase letter. This means `_Button` or `_component` are no longer valid. (@kassens) in https://github.com/facebook/react/pull/25162 + */ allowLeadingUnderscore?: boolean; + /** + * @todo Remove in the next major version + * @deprecated This option has no actual effect on the rule + */ allowNamespace?: boolean; excepts?: readonly string[]; rule?: Case; @@ -36,8 +34,6 @@ type Options = readonly [ const defaultOptions = [ { allowAllCaps: false, - allowLeadingUnderscore: false, - allowNamespace: false, excepts: [], rule: "PascalCase", }, @@ -55,7 +51,15 @@ const schema = [ additionalProperties: false, properties: { allowAllCaps: { type: "boolean" }, + /** + * @todo Remove in the next major version + * @deprecated + */ allowLeadingUnderscore: { type: "boolean" }, + /** + * @todo Remove in the next major version + * @deprecated + */ allowNamespace: { type: "boolean" }, excepts: { type: "array", @@ -71,37 +75,14 @@ const schema = [ }, ] satisfies [JSONSchema4]; -function normalizeOptions(options: Options) { - const opts = options[0]; - const defaultOpts = defaultOptions[0]; - if (opts == null) return defaultOpts; - return { - ...defaultOpts, - ...typeof opts === "string" - ? { rule: opts } - : { - ...opts, - excepts: opts.excepts?.map((pattern) => new RegExp(pattern, "u")) ?? [], - }, - } as const; -} +export const RULE_NAME = "component-name"; -function isValidComponentName(name: string | _, options: ReturnType) { - if (name == null) return true; - if (options.excepts.some((regex) => regex.test(name))) return true; - let normalized = name.split(".").at(-1) ?? name; - if (options.allowNamespace) normalized = normalized.replace(":", ""); - if (options.allowLeadingUnderscore) normalized = normalized.replace(/^_/, ""); - switch (options.rule) { - case "CONSTANT_CASE": - return RE_CONSTANT_CASE.test(normalized); - case "PascalCase": - if (normalized.length > 3 && /^[A-Z]+$/u.test(normalized)) { - return options.allowAllCaps; - } - return RE_PASCAL_CASE.test(normalized); - } -} +export const RULE_FEATURES = [ + "CHK", + "CFG", +] as const satisfies RuleFeature[]; + +export type MessageID = "invalid"; export default createRule({ meta: { @@ -125,18 +106,6 @@ export default createRule({ return { ...collector.listeners, ...collectorLegacy.listeners, - JSXOpeningElement(node) { - const name = JSX.getElementName(node.parent); - if (/^[a-z]/u.test(name)) { - return; - } - if (isValidComponentName(name, options)) return; - context.report({ - messageId: "invalid", - node, - data: { name, rule }, - }); - }, "Program:exit"(node) { const functionComponents = collector.ctx.getAllComponents(node); const classComponents = collectorLegacy.ctx.getAllComponents(node); @@ -144,7 +113,7 @@ export default createRule({ const id = AST.getFunctionIdentifier(component); if (id?.name == null) continue; const name = id.name; - if (isValidComponentName(name, options)) return; + if (isValidName(name, options)) return; context.report({ messageId: "invalid", node: id, @@ -155,7 +124,7 @@ export default createRule({ const id = AST.getClassIdentifier(component); if (id?.name == null) continue; const name = id.name; - if (isValidComponentName(name, options)) continue; + if (isValidName(name, options)) continue; context.report({ messageId: "invalid", node: id, @@ -167,3 +136,33 @@ export default createRule({ }, defaultOptions, }); + +function normalizeOptions(options: Options) { + const opts = options[0]; + const defaultOpts = defaultOptions[0]; + if (opts == null) return defaultOpts; + return { + ...defaultOpts, + ...typeof opts === "string" + ? { rule: opts } + : { + ...opts, + excepts: opts.excepts?.map((pattern) => new RegExp(pattern, "u")) ?? [], + }, + } as const; +} + +function isValidName(name: string | _, options: ReturnType) { + if (name == null) return true; + if (options.excepts.some((regex) => regex.test(name))) return true; + const normalized = name.split(".").at(-1) ?? name; + switch (options.rule) { + case "CONSTANT_CASE": + return RE_CONSTANT_CASE.test(normalized); + case "PascalCase": + if (normalized.length > 3 && /^[A-Z]+$/u.test(normalized)) { + return options.allowAllCaps; + } + return RE_PASCAL_CASE.test(normalized); + } +} diff --git a/packages/plugins/eslint-plugin-react-naming-convention/src/rules/filename-extension.ts b/packages/plugins/eslint-plugin-react-naming-convention/src/rules/filename-extension.ts index 1f1a19aae..b7ae309b6 100644 --- a/packages/plugins/eslint-plugin-react-naming-convention/src/rules/filename-extension.ts +++ b/packages/plugins/eslint-plugin-react-naming-convention/src/rules/filename-extension.ts @@ -1,3 +1,4 @@ +import type { _ } from "@eslint-react/eff"; import { isObject } from "@eslint-react/eff"; import type { RuleFeature } from "@eslint-react/shared"; import type { JSONSchema4 } from "@typescript-eslint/utils/json-schema"; @@ -19,8 +20,8 @@ type Allow = "always" | "as-needed"; /* eslint-disable no-restricted-syntax */ type Options = readonly [ + | _ | Allow - | undefined | { allow?: Allow; extensions?: readonly string[]; diff --git a/packages/plugins/eslint-plugin-react-naming-convention/src/rules/filename.ts b/packages/plugins/eslint-plugin-react-naming-convention/src/rules/filename.ts index a0af86edf..b9eb7f669 100644 --- a/packages/plugins/eslint-plugin-react-naming-convention/src/rules/filename.ts +++ b/packages/plugins/eslint-plugin-react-naming-convention/src/rules/filename.ts @@ -1,5 +1,6 @@ import path from "node:path"; +import type { _ } from "@eslint-react/eff"; import type { RuleFeature } from "@eslint-react/shared"; import { RE_CAMEL_CASE, RE_KEBAB_CASE, RE_PASCAL_CASE, RE_SNAKE_CASE } from "@eslint-react/shared"; import type { JSONSchema4 } from "@typescript-eslint/utils/json-schema"; @@ -23,15 +24,15 @@ type Case = "camelCase" | "kebab-case" | "PascalCase" | "snake_case"; /* eslint-disable no-restricted-syntax */ type Options = readonly [ + | _ | Case - | undefined | { /** - * @deprecated Use ESLint's [files](https://eslint.org/docs/latest/use/configure/configuration-files#specifying-files-and-ignores) feature instead. + * @deprecated Use ESLint's [files](https://eslint.org/docs/latest/use/configure/configuration-files#specifying-files-and-ignores) feature instead */ excepts?: readonly string[]; /** - * @deprecated Use ESLint's [files](https://eslint.org/docs/latest/use/configure/configuration-files#specifying-files-and-ignores) feature instead. + * @deprecated Use ESLint's [files](https://eslint.org/docs/latest/use/configure/configuration-files#specifying-files-and-ignores) feature instead */ extensions?: readonly string[]; rule?: Case; diff --git a/packages/plugins/eslint-plugin-react-x/src/plugin.ts b/packages/plugins/eslint-plugin-react-x/src/plugin.ts index b009efccb..713ea6366 100644 --- a/packages/plugins/eslint-plugin-react-x/src/plugin.ts +++ b/packages/plugins/eslint-plugin-react-x/src/plugin.ts @@ -112,11 +112,11 @@ export const plugin = { "use-jsx-vars": useJsxVars, // Part: deprecated rules - /** @deprecated Use `no-duplicate-jsx-props` instead. */ + /** @deprecated Use `no-duplicate-jsx-props` instead */ "jsx-no-duplicate-props": noDuplicateJsxProps, - /** @deprecated Use `use-jsx-vars` instead. */ + /** @deprecated Use `use-jsx-vars` instead */ "jsx-uses-vars": useJsxVars, - /** @deprecated Use `no-complex-conditional-rendering` instead. */ + /** @deprecated Use `no-complex-conditional-rendering` instead */ "no-complicated-conditional-rendering": noComplexConditionalRendering, }, } as const; diff --git a/packages/plugins/eslint-plugin-react-x/src/rules/no-context-provider.ts b/packages/plugins/eslint-plugin-react-x/src/rules/no-context-provider.ts index 291233070..69f6bbc57 100644 --- a/packages/plugins/eslint-plugin-react-x/src/rules/no-context-provider.ts +++ b/packages/plugins/eslint-plugin-react-x/src/rules/no-context-provider.ts @@ -38,7 +38,7 @@ export default createRule<[], MessageID>({ } return { JSXElement(node) { - const [name, ...rest] = JSX.getElementName(node).split(".").reverse(); + const [name, ...rest] = JSX.getElementType(node).split(".").reverse(); if (name !== "Provider") return; const contextName = rest.reverse().join("."); context.report({ diff --git a/packages/plugins/eslint-plugin-react-x/src/rules/no-unstable-context-value.ts b/packages/plugins/eslint-plugin-react-x/src/rules/no-unstable-context-value.ts index 5c3a38d58..6cfa12c06 100644 --- a/packages/plugins/eslint-plugin-react-x/src/rules/no-unstable-context-value.ts +++ b/packages/plugins/eslint-plugin-react-x/src/rules/no-unstable-context-value.ts @@ -40,7 +40,7 @@ export default createRule<[], MessageID>({ return { ...listeners, JSXOpeningElement(node) { - const fullName = JSX.getElementName(node.parent); + const fullName = JSX.getElementType(node.parent); const selfName = fullName.split(".").at(-1); if (selfName == null) return; if (!isContextName(selfName, isReact18OrBelow)) return; diff --git a/packages/utilities/jsx/src/get-element-name.ts b/packages/utilities/jsx/src/get-element-type.ts similarity index 86% rename from packages/utilities/jsx/src/get-element-name.ts rename to packages/utilities/jsx/src/get-element-type.ts index d1ae3300d..51fc1689a 100644 --- a/packages/utilities/jsx/src/get-element-name.ts +++ b/packages/utilities/jsx/src/get-element-type.ts @@ -8,7 +8,7 @@ import { toString } from "./to-string"; * @param node The JSX element node * @returns The name of the element */ -export function getElementName(node: TSESTree.JSXElement | TSESTree.JSXFragment) { +export function getElementType(node: TSESTree.JSXElement | TSESTree.JSXFragment) { if (node.type === T.JSXFragment) { return ""; } diff --git a/packages/utilities/jsx/src/index.ts b/packages/utilities/jsx/src/index.ts index 6122c9d3c..3934cd459 100644 --- a/packages/utilities/jsx/src/index.ts +++ b/packages/utilities/jsx/src/index.ts @@ -2,7 +2,7 @@ export * from "./find-parent-attribute"; export * from "./get-attribute"; export * from "./get-attribute-name"; export * from "./get-attribute-value"; -export * from "./get-element-name"; +export * from "./get-element-type"; export * from "./has-attribute"; export * from "./is-jsx-value"; export * from "./is-kind-of-element"; diff --git a/packages/utilities/jsx/src/is-kind-of-element.ts b/packages/utilities/jsx/src/is-kind-of-element.ts index a242e2445..b60e80613 100644 --- a/packages/utilities/jsx/src/is-kind-of-element.ts +++ b/packages/utilities/jsx/src/is-kind-of-element.ts @@ -2,7 +2,7 @@ import type { Scope } from "@typescript-eslint/scope-manager"; import type { TSESTree } from "@typescript-eslint/types"; import { AST_NODE_TYPES as T } from "@typescript-eslint/types"; -import { getElementName } from "./get-element-name"; +import { getElementType } from "./get-element-type"; import { hasAttribute } from "./has-attribute"; /** @@ -12,7 +12,7 @@ import { hasAttribute } from "./has-attribute"; */ export function isFragmentElement(node: TSESTree.Node) { if (node.type !== T.JSXElement) return false; - return getElementName(node) + return getElementType(node) .split(".") .at(-1) === "Fragment"; }