add jsxPascalCase rule and tests
MODIFY
packages/@romejs/compiler/lint/rules/index.ts
packages/@romejs/compiler/lint/rules/index.ts
@@ -84,6 +84,7 @@ import jsxFragments from "./react/jsxFragments";
import jsxKey from "./react/jsxKey";
import jsxNoCommentText from "./react/jsxNoCommentText";
import jsxNoDuplicateProps from "./react/jsxNoDuplicateProps";
+import jsxPascalCase from "./react/jsxPascalCase";
import noAccessStateInSetState from "./react/noAccessStateInSetState";
import noChildrenProp from "./react/noChildrenProp";
import noDanger from "./react/noDanger";
@@ -180,6 +181,7 @@ export const lintTransforms = [
jsxKey,
jsxNoCommentText,
jsxNoDuplicateProps,
+ jsxPascalCase,
noAccessStateInSetState,
noChildrenProp,
noDanger,

ADD
packages/@romejs/compiler/lint/rules/react/jsxPascalCase.test.ts
+import {test} from "rome";
+import {testLint} from "../testHelpers";
+
+test(
+ "react jsx pascal case",
+ async (t) => {
+ await testLint(
+ t,
+ {
+ invalid: ["<Foo_component />", "<FOO_COMPONENT />"],
+ valid: [
+ "<Foo />",
+ "<foo_bar />",
+ "<fooBar />",
+ "<foo_COMPONENT />",
+ "<foo />",
+ "<div />",
+ "<FooComponent />",
+ ],
+ },
+ {category: "lint/react/jsxPascalCase"},
+ );
+ },
+);

ADD
packages/@romejs/compiler/lint/rules/react/jsxPascalCase.ts
+import {Path, TransformExitResult} from "@romejs/compiler";
+import {descriptions} from "@romejs/diagnostics";
+import {isJSXElement} from "@romejs/js-ast-utils";
+import {toCamelCase} from "@romejs/string-utils";
+
+export default {
+ name: "reactJsxPascalCase",
+ enter(path: Path): TransformExitResult {
+ const {node} = path;
+
+ if (isJSXElement(node) && node.name.type === "JSXReferenceIdentifier") {
+ const pascalCaseName = toCamelCase(node.name.name, true);
+ if (node.name.name !== pascalCaseName) {
+ path.context.addNodeDiagnostic(
+ node,
+ descriptions.LINT.REACT_JSX_PASCAL_CASE(
+ node.name.name,
+ pascalCaseName,
+ ),
+ );
+ }
+ }
+ return node;
+ },
+};

MODIFY
packages/@romejs/diagnostics/categories.ts
packages/@romejs/diagnostics/categories.ts
@@ -171,6 +171,7 @@ type LintDiagnosticCategory =
| "lint/react/jsxKey"
| "lint/react/jsxNoCommentText"
| "lint/react/jsxNoDuplicateProps"
+ | "lint/react/jsxPascalCase"
| "lint/react/noAccessStateInSetState"
| "lint/react/noChildrenProp"
| "lint/react/noDanger"

MODIFY
packages/@romejs/diagnostics/descriptions/lint.ts
packages/@romejs/diagnostics/descriptions/lint.ts
@@ -27,6 +27,17 @@ export const lint = createDiagnosticsCategory({
},
],
}),
+ REACT_JSX_PASCAL_CASE: (oldName: string, newName: string) => ({
+ category: "lint/react/jsxPascalCase",
+ message: `Switch <emphasis>${oldName}</emphasis> to <emphasis>${newName}</emphasis>.`,
+ advice: [
+ {
+ type: "log",
+ category: "info",
+ text: "User-defined JSX components should be defined and referenced in PascalCase.",
+ },
+ ],
+ }),
REACT_NO_USELESS_FRAGMENT: {
category: "lint/react/noUselessFragment",
message: "Avoid using unnecessary <emphasis>Fragment</emphasis>.",

add jsxPascalCase rule and tests (#551)