Skip to content

Commit

Permalink
feat(jsx/pascal-case): new rule port from eslint-plugin-react (#271)
Browse files Browse the repository at this point in the history
* feat(jsx/pascal-case): bring up

* Apply code review suggestions from @kecrily

Co-authored-by: Percy Ma <kecrily@gmail.com>

---------

Co-authored-by: Percy Ma <kecrily@gmail.com>
  • Loading branch information
SukkaW and kecrily committed Jan 27, 2024
1 parent 8eaf62d commit 7a5b9ef
Show file tree
Hide file tree
Showing 11 changed files with 579 additions and 1 deletion.
1 change: 1 addition & 0 deletions packages/eslint-plugin-jsx/configs/disable-legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const config: Linter.FlatConfig = {
'react/jsx-max-props-per-line': 0,
'react/jsx-newline': 0,
'react/jsx-one-expression-per-line': 0,
'react/jsx-pascal-case': 0,
'react/jsx-props-no-multi-spaces': 0,
'react/jsx-self-closing-comp': 0,
'react/jsx-sort-props': 0,
Expand Down
11 changes: 11 additions & 0 deletions packages/eslint-plugin-jsx/dts/rule-options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type { RuleOptions as JsxIndentPropsRuleOptions } from '../rules/jsx-inde
import type { RuleOptions as JsxMaxPropsPerLineRuleOptions } from '../rules/jsx-max-props-per-line/types'
import type { RuleOptions as JsxNewlineRuleOptions } from '../rules/jsx-newline/types'
import type { RuleOptions as JsxOneExpressionPerLineRuleOptions } from '../rules/jsx-one-expression-per-line/types'
import type { RuleOptions as JsxPascalCaseRuleOptions } from '../rules/jsx-pascal-case/types'
import type { RuleOptions as JsxPropsNoMultiSpacesRuleOptions } from '../rules/jsx-props-no-multi-spaces/types'
import type { RuleOptions as JsxSelfClosingCompRuleOptions } from '../rules/jsx-self-closing-comp/types'
import type { RuleOptions as JsxSortPropsRuleOptions } from '../rules/jsx-sort-props/types'
Expand Down Expand Up @@ -85,6 +86,11 @@ export interface RuleOptions {
* @see https://eslint.style/rules/jsx/jsx-one-expression-per-line
*/
'@stylistic/jsx/jsx-one-expression-per-line': JsxOneExpressionPerLineRuleOptions
/**
* Enforce PascalCase for user-defined JSX components
* @see https://eslint.style/rules/jsx/jsx-pascal-case
*/
'@stylistic/jsx/jsx-pascal-case': JsxPascalCaseRuleOptions
/**
* Disallow multiple spaces between inline JSX props
* @see https://eslint.style/rules/jsx/jsx-props-no-multi-spaces
Expand Down Expand Up @@ -178,6 +184,11 @@ export interface UnprefixedRuleOptions {
* @see https://eslint.style/rules/jsx/jsx-one-expression-per-line
*/
'jsx-one-expression-per-line': JsxOneExpressionPerLineRuleOptions
/**
* Enforce PascalCase for user-defined JSX components
* @see https://eslint.style/rules/jsx/jsx-pascal-case
*/
'jsx-pascal-case': JsxPascalCaseRuleOptions
/**
* Disallow multiple spaces between inline JSX props
* @see https://eslint.style/rules/jsx/jsx-props-no-multi-spaces
Expand Down
5 changes: 4 additions & 1 deletion packages/eslint-plugin-jsx/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"./rules/jsx-max-props-per-line": "./dist/jsx-max-props-per-line.js",
"./rules/jsx-newline": "./dist/jsx-newline.js",
"./rules/jsx-one-expression-per-line": "./dist/jsx-one-expression-per-line.js",
"./rules/jsx-pascal-case": "./dist/jsx-pascal-case.js",
"./rules/jsx-props-no-multi-spaces": "./dist/jsx-props-no-multi-spaces.js",
"./rules/jsx-self-closing-comp": "./dist/jsx-self-closing-comp.js",
"./rules/jsx-sort-props": "./dist/jsx-sort-props.js",
Expand All @@ -63,14 +64,16 @@
},
"dependencies": {
"@stylistic/eslint-plugin-js": "workspace:^",
"estraverse": "^5.3.0"
"estraverse": "^5.3.0",
"picomatch": "^3.0.1"
},
"devDependencies": {
"@babel/eslint-parser": "^7.23.3",
"@babel/plugin-syntax-decorators": "^7.23.3",
"@babel/plugin-syntax-do-expressions": "^7.23.3",
"@babel/plugin-syntax-function-bind": "^7.23.3",
"@babel/preset-react": "^7.23.3",
"@types/picomatch": "^2.3.3",
"@typescript-eslint/parser": "^6.19.0",
"babel-eslint": "^10.1.0",
"eslint": "^8.56.0",
Expand Down
1 change: 1 addition & 0 deletions packages/eslint-plugin-jsx/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
| [`@stylistic/jsx/jsx-max-props-per-line`](./rules/jsx-max-props-per-line) | Enforce maximum of props on a single line in JSX || |
| [`@stylistic/jsx/jsx-newline`](./rules/jsx-newline) | Require or prevent a new line after jsx elements and expressions. || |
| [`@stylistic/jsx/jsx-one-expression-per-line`](./rules/jsx-one-expression-per-line) | Require one JSX element per line || |
| [`@stylistic/jsx/jsx-pascal-case`](./rules/jsx-pascal-case) | Enforce PascalCase for user-defined JSX components | | |
| [`@stylistic/jsx/jsx-props-no-multi-spaces`](./rules/jsx-props-no-multi-spaces) | Disallow multiple spaces between inline JSX props || |
| [`@stylistic/jsx/jsx-self-closing-comp`](./rules/jsx-self-closing-comp) | Disallow extra closing tags for components without children || |
| [`@stylistic/jsx/jsx-sort-props`](./rules/jsx-sort-props) | Enforce props alphabetical sorting || |
Expand Down
2 changes: 2 additions & 0 deletions packages/eslint-plugin-jsx/rules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import jsxIndentProps from './jsx-indent-props/jsx-indent-props'
import jsxMaxPropsPerLine from './jsx-max-props-per-line/jsx-max-props-per-line'
import jsxNewline from './jsx-newline/jsx-newline'
import jsxOneExpressionPerLine from './jsx-one-expression-per-line/jsx-one-expression-per-line'
import jsxPascalCase from './jsx-pascal-case/jsx-pascal-case'
import jsxPropsNoMultiSpaces from './jsx-props-no-multi-spaces/jsx-props-no-multi-spaces'
import jsxSelfClosingComp from './jsx-self-closing-comp/jsx-self-closing-comp'
import jsxSortProps from './jsx-sort-props/jsx-sort-props'
Expand All @@ -39,6 +40,7 @@ export default {
'jsx-max-props-per-line': jsxMaxPropsPerLine,
'jsx-newline': jsxNewline,
'jsx-one-expression-per-line': jsxOneExpressionPerLine,
'jsx-pascal-case': jsxPascalCase,
'jsx-props-no-multi-spaces': jsxPropsNoMultiSpaces,
'jsx-self-closing-comp': jsxSelfClosingComp,
'jsx-sort-props': jsxSortProps,
Expand Down
75 changes: 75 additions & 0 deletions packages/eslint-plugin-jsx/rules/jsx-pascal-case/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
Enforces coding style that user-defined JSX components are defined and referenced in PascalCase.

Note that since React's JSX uses the upper vs. lower case convention to distinguish between local component classes and HTML tags this rule will not warn on components that start with a lower case letter.

## Rule Details

Examples of **incorrect** code for this rule:

```jsx
<Test_component />

<TEST_COMPONENT />
```

Examples of **correct** code for this rule:

```jsx
<div />

<TestComponent />

<TestComponent>
<div />
</TestComponent>

<CSSTransitionGroup />
```

## Rule Options

```js
...
"@stylistic/jsx/jsx-pascal-case": [<enabled>, { allowAllCaps: <boolean>, allowNamespace: <boolean>, allowLeadingUnderscore: <boolean>, ignore: <string[]> }]
```

- `enabled`: for enabling the rule. 0=off, 1=warn, 2=error. Defaults to 0.
- `allowAllCaps`: optional boolean set to `true` to allow components name in all caps (default to `false`).
- `allowLeadingUnderscore`: optional boolean set to `true` to allow components name with that starts with an underscore (default to `false`).
- `allowNamespace`: optional boolean set to `true` to ignore namespaced components (default to `false`).
- `ignore`: optional string-array of component names to ignore during validation (supports [picomatch](https://github.com/micromatch/picomatch)-style globs).

### `allowAllCaps`

Examples of **correct** code for this rule, when `allowAllCaps` is `true`:

```jsx
<ALLOWED />
<TEST_COMPONENT />
```

### `allowNamespace`

Examples of **correct** code for this rule, when `allowNamespace` is `true`:

```jsx
<Allowed.div />
<TestComponent.p />
```

### `allowLeadingUnderscore`

Examples of **correct** code for this rule, when `allowLeadingUnderscore` is `true`:

```jsx
<_AllowedComponent />
<_AllowedComponent>
<div />
</_AllowedComponent>
```

**WARNING:** Adding a leading underscore to the name of a component does **NOT** affect the visibility or accessibility of that component. Attempting to use leading underscores to enforce privacy of your components is an error.

## When Not To Use It

If you are not using JSX.
Loading

0 comments on commit 7a5b9ef

Please sign in to comment.