Skip to content

Commit

Permalink
[New] jsx-filename-extension: add ignoreFilesWithoutCode option t…
Browse files Browse the repository at this point in the history
…o allow empty files
  • Loading branch information
burtek authored and ljharb committed Jan 9, 2024
1 parent ca162fd commit 2e30897
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [`prefer-read-only-props`], [`prop-types`], component detection: allow components to be async functions ([#3654][] @pnodet)
* [`no-unknown-property`]: support `onResize` on audio/video tags ([#3662][] @caesar1030)
* [`jsx-wrap-multilines`]: add `never` option to prohibit wrapping parens on multiline JSX ([#3668][] @reedws)
* [`jsx-filename-extension`]: add `ignoreFilesWithoutCode` option to allow empty files ([#3674][] @burtek)

### Fixed
* [`jsx-no-leaked-render`]: preserve RHS parens for multiline jsx elements while fixing ([#3623][] @akulsr0)
Expand All @@ -27,6 +28,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [Refactor] [`jsx-props-no-multi-spaces`]: extract type parameters to var ([#3634][] @HenryBrown0)
* [Docs] [`jsx-key`]: fix correct example ([#3656][] @developer-bandi)

[#3674]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3674
[#3668]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3668
[#3666]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3666
[#3662]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3662
Expand Down
10 changes: 10 additions & 0 deletions docs/rules/jsx-filename-extension.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ The set of allowed extensions is configurable. By default '.jsx' is allowed. If
}
```

### `ignoreFilesWithoutCode` (default: `false`)

If enabled, files that do not contain code (i.e. are empty, contain only whitespaces or comments) will not be rejected.

```js
"rules": {
"react/jsx-filename-extension": [1, { "ignoreFilesWithoutCode": true }]
}
```

## When Not To Use It

If you don't care about restricting the file extensions that may contain JSX.
9 changes: 9 additions & 0 deletions lib/rules/jsx-filename-extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const report = require('../util/report');
const DEFAULTS = {
allow: 'always',
extensions: ['.jsx'],
ignoreFilesWithoutCode: false,
};

// ------------------------------------------------------------------------------
Expand Down Expand Up @@ -50,6 +51,9 @@ module.exports = {
type: 'string',
},
},
ignoreFilesWithoutCode: {
type: 'boolean',
},
},
additionalProperties: false,
}],
Expand All @@ -67,6 +71,8 @@ module.exports = {

const allow = (context.options[0] && context.options[0].allow) || DEFAULTS.allow;
const allowedExtensions = (context.options[0] && context.options[0].extensions) || DEFAULTS.extensions;
const ignoreFilesWithoutCode = (context.options[0] && context.options[0].ignoreFilesWithoutCode)
|| DEFAULTS.ignoreFilesWithoutCode;
const isAllowedExtension = allowedExtensions.some((extension) => filename.slice(-extension.length) === extension);

function handleJSX(node) {
Expand Down Expand Up @@ -97,6 +103,9 @@ module.exports = {
}

if (isAllowedExtension && allow === 'as-needed') {
if (ignoreFilesWithoutCode && node.body.length === 0) {
return;
}
report(context, messages.extensionOnlyForJSX, 'extensionOnlyForJSX', {
node,
data: {
Expand Down
22 changes: 22 additions & 0 deletions tests/lib/rules/jsx-filename-extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ const parserOptions = {
const withJSXElement = 'module.exports = function MyComponent() { return <div>\n<div />\n</div>; }';
const withJSXFragment = 'module.exports = function MyComponent() { return <>\n</>; }';
const withoutJSX = 'module.exports = {}';
const onlyComments = [
'// some initial comment',
'',
'/* multiline',
' * comment',
' */',
].join('\n');

// ------------------------------------------------------------------------------
// Tests
Expand Down Expand Up @@ -80,6 +87,21 @@ ruleTester.run('jsx-filename-extension', rule, {
code: withJSXFragment,
features: ['fragment'],
},
{
filename: 'MyComponent.js',
code: onlyComments,
options: [{ allow: 'as-needed' }],
},
{
filename: 'MyComponent.jsx',
code: onlyComments,
options: [{ allow: 'as-needed', ignoreFilesWithoutCode: true }],
},
{
filename: 'MyComponent.jsx',
code: '',
options: [{ allow: 'as-needed', ignoreFilesWithoutCode: true }],
},
]),

invalid: parsers.all([
Expand Down

0 comments on commit 2e30897

Please sign in to comment.