Skip to content

Commit 2e30897

Browse files
burtekljharb
authored andcommitted
[New] jsx-filename-extension: add ignoreFilesWithoutCode option to allow empty files
1 parent ca162fd commit 2e30897

File tree

4 files changed

+43
-0
lines changed

4 files changed

+43
-0
lines changed

Diff for: CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
1313
* [`prefer-read-only-props`], [`prop-types`], component detection: allow components to be async functions ([#3654][] @pnodet)
1414
* [`no-unknown-property`]: support `onResize` on audio/video tags ([#3662][] @caesar1030)
1515
* [`jsx-wrap-multilines`]: add `never` option to prohibit wrapping parens on multiline JSX ([#3668][] @reedws)
16+
* [`jsx-filename-extension`]: add `ignoreFilesWithoutCode` option to allow empty files ([#3674][] @burtek)
1617

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

31+
[#3674]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3674
3032
[#3668]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3668
3133
[#3666]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3666
3234
[#3662]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3662

Diff for: docs/rules/jsx-filename-extension.md

+10
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ The set of allowed extensions is configurable. By default '.jsx' is allowed. If
4646
}
4747
```
4848

49+
### `ignoreFilesWithoutCode` (default: `false`)
50+
51+
If enabled, files that do not contain code (i.e. are empty, contain only whitespaces or comments) will not be rejected.
52+
53+
```js
54+
"rules": {
55+
"react/jsx-filename-extension": [1, { "ignoreFilesWithoutCode": true }]
56+
}
57+
```
58+
4959
## When Not To Use It
5060

5161
If you don't care about restricting the file extensions that may contain JSX.

Diff for: lib/rules/jsx-filename-extension.js

+9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const report = require('../util/report');
1616
const DEFAULTS = {
1717
allow: 'always',
1818
extensions: ['.jsx'],
19+
ignoreFilesWithoutCode: false,
1920
};
2021

2122
// ------------------------------------------------------------------------------
@@ -50,6 +51,9 @@ module.exports = {
5051
type: 'string',
5152
},
5253
},
54+
ignoreFilesWithoutCode: {
55+
type: 'boolean',
56+
},
5357
},
5458
additionalProperties: false,
5559
}],
@@ -67,6 +71,8 @@ module.exports = {
6771

6872
const allow = (context.options[0] && context.options[0].allow) || DEFAULTS.allow;
6973
const allowedExtensions = (context.options[0] && context.options[0].extensions) || DEFAULTS.extensions;
74+
const ignoreFilesWithoutCode = (context.options[0] && context.options[0].ignoreFilesWithoutCode)
75+
|| DEFAULTS.ignoreFilesWithoutCode;
7076
const isAllowedExtension = allowedExtensions.some((extension) => filename.slice(-extension.length) === extension);
7177

7278
function handleJSX(node) {
@@ -97,6 +103,9 @@ module.exports = {
97103
}
98104

99105
if (isAllowedExtension && allow === 'as-needed') {
106+
if (ignoreFilesWithoutCode && node.body.length === 0) {
107+
return;
108+
}
100109
report(context, messages.extensionOnlyForJSX, 'extensionOnlyForJSX', {
101110
node,
102111
data: {

Diff for: tests/lib/rules/jsx-filename-extension.js

+22
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ const parserOptions = {
2929
const withJSXElement = 'module.exports = function MyComponent() { return <div>\n<div />\n</div>; }';
3030
const withJSXFragment = 'module.exports = function MyComponent() { return <>\n</>; }';
3131
const withoutJSX = 'module.exports = {}';
32+
const onlyComments = [
33+
'// some initial comment',
34+
'',
35+
'/* multiline',
36+
' * comment',
37+
' */',
38+
].join('\n');
3239

3340
// ------------------------------------------------------------------------------
3441
// Tests
@@ -80,6 +87,21 @@ ruleTester.run('jsx-filename-extension', rule, {
8087
code: withJSXFragment,
8188
features: ['fragment'],
8289
},
90+
{
91+
filename: 'MyComponent.js',
92+
code: onlyComments,
93+
options: [{ allow: 'as-needed' }],
94+
},
95+
{
96+
filename: 'MyComponent.jsx',
97+
code: onlyComments,
98+
options: [{ allow: 'as-needed', ignoreFilesWithoutCode: true }],
99+
},
100+
{
101+
filename: 'MyComponent.jsx',
102+
code: '',
103+
options: [{ allow: 'as-needed', ignoreFilesWithoutCode: true }],
104+
},
83105
]),
84106

85107
invalid: parsers.all([

0 commit comments

Comments
 (0)