From 729678b6f753ef25cc56b393ed3d81f2b1f0d9f6 Mon Sep 17 00:00:00 2001 From: Remco Haszing Date: Sat, 8 Aug 2020 15:31:41 +0200 Subject: [PATCH] New `jsx-filename-extension`: Add allow option --- docs/rules/jsx-filename-extension.md | 12 ++++++++++++ lib/rules/jsx-filename-extension.js | 15 ++++++++++++++- tests/lib/rules/jsx-filename-extension.js | 13 +++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/docs/rules/jsx-filename-extension.md b/docs/rules/jsx-filename-extension.md index a5866e6ab6..4f9278ff40 100644 --- a/docs/rules/jsx-filename-extension.md +++ b/docs/rules/jsx-filename-extension.md @@ -22,6 +22,18 @@ function MyComponent() { ## Rule Options +### `allow` (default: `"always"`) + +When to allow a JSX filename extension. By default all files may have a JSX extension. Set this to `as-needed` to only allow JSX file extensions in files that contain JSX syntax. + +```js +"rules": { + "react/jsx-filename-extension": [1, { "allow": "as-needed" }] +} +``` + +### `extensions` (default: `[".jsx"]`) + The set of allowed extensions is configurable. By default '.jsx' is allowed. If you wanted to allow both '.jsx' and '.js', the configuration would be: ```js diff --git a/lib/rules/jsx-filename-extension.js b/lib/rules/jsx-filename-extension.js index c210a552b1..b07bc5518e 100644 --- a/lib/rules/jsx-filename-extension.js +++ b/lib/rules/jsx-filename-extension.js @@ -13,6 +13,7 @@ const docsUrl = require('../util/docsUrl'); // ------------------------------------------------------------------------------ const DEFAULTS = { + allow: 'always', extensions: ['.jsx'] }; @@ -32,6 +33,9 @@ module.exports = { schema: [{ type: 'object', properties: { + allow: { + enum: ['always', 'as-needed'] + }, extensions: { type: 'array', items: { @@ -53,6 +57,7 @@ module.exports = { return {}; } + const allow = (context.options[0] && context.options[0].allow) || DEFAULTS.allow; const allowedExtensions = (context.options[0] && context.options[0].extensions) || DEFAULTS.extensions; const isAllowedExtension = allowedExtensions.some((extension) => filename.slice(-extension.length) === extension); @@ -70,7 +75,7 @@ module.exports = { JSXElement: handleJSX, JSXFragment: handleJSX, - 'Program:exit'() { + 'Program:exit'(node) { if (jsxNode) { if (!isAllowedExtension) { context.report({ @@ -78,6 +83,14 @@ module.exports = { message: `JSX not allowed in files with extension '${path.extname(filename)}'` }); } + return; + } + + if (isAllowedExtension && allow === 'as-needed') { + context.report({ + node, + message: `Only files containing JSX may use the extension '${path.extname(filename)}'` + }); } } }; diff --git a/tests/lib/rules/jsx-filename-extension.js b/tests/lib/rules/jsx-filename-extension.js index 6435bfabce..96c71ec9e5 100644 --- a/tests/lib/rules/jsx-filename-extension.js +++ b/tests/lib/rules/jsx-filename-extension.js @@ -45,6 +45,14 @@ ruleTester.run('jsx-filename-extension', rule, { { filename: 'MyComponent.jsx', code: withJSXElement + }, { + filename: 'MyComponent.js', + code: withoutJSX, + options: [{allow: 'as-needed'}] + }, { + filename: 'MyComponent.jsx', + code: withJSXElement, + options: [{allow: 'as-needed'}] }, { filename: 'MyComponent.js', options: [{extensions: ['.js', '.jsx']}], @@ -74,6 +82,11 @@ ruleTester.run('jsx-filename-extension', rule, { filename: 'MyComponent.js', code: withJSXElement, errors: [{message: 'JSX not allowed in files with extension \'.js\''}] + }, { + filename: 'MyComponent.jsx', + code: withoutJSX, + options: [{allow: 'as-needed'}], + errors: [{message: 'Only files containing JSX may use the extension \'.jsx\''}] }, { filename: 'MyComponent.jsx', code: withJSXElement,