Skip to content

Commit

Permalink
Add jsx-filename-extension rule (fixes #495)
Browse files Browse the repository at this point in the history
Some projects want to require that any file that uses JSX to end in
.jsx, and others prefer to use .js. This rule can be used to enforce
this. I see this as complimentary to require-extension.
  • Loading branch information
lencioni authored and yannickcr committed Jun 5, 2016
1 parent 8cbbe4d commit fd35cbf
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ The plugin has a [recommended configuration](#user-content-recommended-configura
* [jsx-closing-bracket-location](docs/rules/jsx-closing-bracket-location.md): Validate closing bracket location in JSX (fixable)
* [jsx-curly-spacing](docs/rules/jsx-curly-spacing.md): Enforce or disallow spaces inside of curly braces in JSX attributes (fixable)
* [jsx-equals-spacing](docs/rules/jsx-equals-spacing.md): Enforce or disallow spaces around equal signs in JSX attributes (fixable)
* [jsx-filename-extension](docs/rules/jsx-filename-extension.md): Restrict file extensions that may contain JSX
* [jsx-first-prop-new-line](docs/rules/jsx-first-prop-new-line.md): Enforce position of the first prop in JSX
* [jsx-handler-names](docs/rules/jsx-handler-names.md): Enforce event handler naming conventions in JSX
* [jsx-indent](docs/rules/jsx-indent.md): Validate JSX indentation
Expand Down
35 changes: 35 additions & 0 deletions docs/rules/jsx-filename-extension.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Restrict file extensions that may contain JSX (jsx-filename-extension)

## Rule Details

The following pattern is considered a warning:

```jsx
// filename: MyComponent.js
function MyComponent() {
return <div />;
}
```

The following pattern is not considered a warning:

```jsx
// filename: MyComponent.jsx
function MyComponent() {
return <div />;
}
```

## Rule Options

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
"rules": {
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
}
```

## When Not To Use It

If you don't care about restricting the file extensions that may contain JSX.
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ module.exports = {
'prefer-stateless-function': require('./lib/rules/prefer-stateless-function'),
'require-render-return': require('./lib/rules/require-render-return'),
'jsx-first-prop-new-line': require('./lib/rules/jsx-first-prop-new-line'),
'jsx-no-target-blank': require('./lib/rules/jsx-no-target-blank')
'jsx-no-target-blank': require('./lib/rules/jsx-no-target-blank'),
'jsx-filename-extension': require('./lib/rules/jsx-filename-extension')
},
configs: {
recommended: {
Expand Down
68 changes: 68 additions & 0 deletions lib/rules/jsx-filename-extension.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* @fileoverview Restrict file extensions that may contain JSX
* @author Joe Lencioni
*/
'use strict';

var path = require('path');

// ------------------------------------------------------------------------------
// Constants
// ------------------------------------------------------------------------------

var DEFAULTS = {
extensions: ['.jsx']
};

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

module.exports = function(context) {


function getExtensionsConfig() {
return context.options[0] && context.options[0].extensions || DEFAULTS.extensions;
}

// --------------------------------------------------------------------------
// Public
// --------------------------------------------------------------------------

return {

JSXElement: function(node) {
var allowedExtensions = getExtensionsConfig();
var filename = context.getFilename();

var isAllowedExtension = allowedExtensions.some(function (extension) {
return filename.slice(-extension.length) === extension;
});

if (isAllowedExtension) {
return;
}

var extension = path.extname(filename);

context.report({
node: node,
message: 'JSX not allowed in files with extension \'' + extension + '\''
});
}
};

};

module.exports.schema = [{
type: 'object',
properties: {
extensions: {
type: 'array',
items: {
type: 'string'
}
}
},
additionalProperties: false
}];
66 changes: 66 additions & 0 deletions tests/lib/rules/jsx-filename-extension.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* @fileoverview Restrict file extensions that may contain JSX
* @author Joe Lencioni
*/
'use strict';

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

var rule = require('../../../lib/rules/jsx-filename-extension');
var RuleTester = require('eslint').RuleTester;

var parserOptions = {
ecmaVersion: 6,
ecmaFeatures: {
jsx: true
}
};

// ------------------------------------------------------------------------------
// Code Snippets
// ------------------------------------------------------------------------------

var withJSX = 'module.exports = function MyComponent() { return <div />; }';
var withoutJSX = 'module.exports = {}';

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------

var ruleTester = new RuleTester();
ruleTester.run('jsx-filename-extension', rule, {

valid: [
{
filename: 'MyComponent.jsx',
code: withJSX,
parserOptions: parserOptions
}, {
filename: 'MyComponent.js',
options: [{extensions: ['.js', '.jsx']}],
code: withJSX,
parserOptions: parserOptions
}, {
filename: 'notAComponent.js',
code: withoutJSX
}
],

invalid: [
{
filename: 'MyComponent.js',
code: withJSX,
parserOptions: parserOptions,
errors: [{message: 'JSX not allowed in files with extension \'.js\''}]
}, {
filename: 'MyComponent.jsx',
code: withJSX,
parserOptions: parserOptions,
options: [{extensions: ['.js']}],
errors: [{message: 'JSX not allowed in files with extension \'.jsx\''}]
}
]

});

0 comments on commit fd35cbf

Please sign in to comment.