Skip to content

Commit 06deeb2

Browse files
committed
[jsx-filename-extension]: option to allow empty files
1 parent ca162fd commit 06deeb2

File tree

3 files changed

+36
-0
lines changed

3 files changed

+36
-0
lines changed

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.

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: {

tests/lib/rules/jsx-filename-extension.js

+17
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,16 @@ 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+
},
83100
]),
84101

85102
invalid: parsers.all([

0 commit comments

Comments
 (0)