Skip to content

Commit 6dbf685

Browse files
committed
now supporting react / jsx
1 parent f6bb83f commit 6dbf685

File tree

4 files changed

+156
-8
lines changed

4 files changed

+156
-8
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,22 @@ Any [rules](http://eslint.org/docs/rules/) added to your global or local `.eslin
4848

4949
This turns on enforcing the use of semicolons, a rule which is silenced by default in the current version of the `eslint-config-fullstack` package.
5050

51+
## React / JSX
52+
53+
With version 2, `eslint-config-fullstack` now has preliminary support for React/JSX projects. Note that you must manually install the peer dependency `eslint-plugin-react`:
54+
55+
```sh
56+
npm install --save eslint-plugin-react
57+
```
58+
59+
Then change your `.eslintrc.json` to extend the react sub-config:
60+
61+
```json
62+
{
63+
"extends": "fullstack/react"
64+
}
65+
```
66+
5167
## Background
5268

5369
The [ESLint](http://http://eslint.org/) linting system is a popular one for its support of ES6 syntax, pluggable [rules](http://eslint.org/docs/rules/), automatic rule names in warning messages, and [shareable](http://eslint.org/docs/developer-guide/shareable-configs) / [extendable](http://eslint.org/docs/user-guide/configuring#extending-configuration-files) config files.

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@
3737
"devDependencies": {
3838
"chai": "^3.5.0",
3939
"eslint": "~3.9.0",
40+
"eslint-plugin-react": "^6.7.1",
4041
"mocha": "^3.0.0"
42+
},
43+
"peerDependencies": {
44+
"eslint": ">=3.9.0",
45+
"eslint-plugin-react": "^6.7.1"
4146
}
4247
}

react.js

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
'use strict';
2+
3+
// Specifies additional options to use in React / React-JSX projects.
4+
// Note that you need to manually install `eslint-plugin-react` as a peer
5+
// dependency (see https://goo.gl/I4AYlb for more details).
6+
7+
// To opt-in, use `"extends": "fullstack/react"`.
8+
9+
module.exports = {
10+
extends: [
11+
require.resolve('./index'), // base config
12+
'plugin:react/recommended' // overridden below, unless this package falls behind plugin
13+
],
14+
plugins: [
15+
'react'
16+
],
17+
parserOptions: {
18+
sourceType: 'module',
19+
ecmaFeatures: {
20+
jsx: true
21+
}
22+
},
23+
rules: { // https://github.com/yannickcr/eslint-plugin-react
24+
25+
// general React rules
26+
27+
'react/display-name': 1, // Prevent missing displayName in a React component definition
28+
'react/forbid-component-props': 0, // Forbid certain props on Components
29+
'react/forbid-prop-types': 0, // Forbid certain propTypes
30+
'react/no-children-prop': 0, // Prevent passing children as props
31+
'react/no-danger': 0, // Prevent usage of dangerous JSX properties
32+
'react/no-danger-with-children': 0, // Prevent problem with children and props.dangerouslySetInnerHTML
33+
'react/no-deprecated': 1, // Prevent usage of deprecated methods
34+
'react/no-did-mount-set-state': 0, // Prevent usage of setState in componentDidMount
35+
'react/no-did-update-set-state': 0, // Prevent usage of setState in componentDidUpdate
36+
'react/no-direct-mutation-state': 1, // Prevent direct mutation of this.state
37+
'react/no-find-dom-node': 1, // Prevent usage of findDOMNode
38+
'react/no-is-mounted': 1, // Prevent usage of isMounted
39+
'react/no-multi-comp': 0, // Prevent multiple component definition per file
40+
'react/no-render-return-value': 1, // Prevent usage of the return value of React.render
41+
'react/no-set-state': 0, // Prevent usage of setState
42+
'react/no-string-refs': 0, // Prevent using string references in ref attribute.
43+
'react/no-unescaped-entities': 0, // Prevent invalid characters from appearing in markup
44+
'react/no-unknown-property': 1, // Prevent usage of unknown DOM property (fixable)
45+
'react/no-unused-prop-types': 0, // Prevent definitions of unused prop types
46+
'react/prefer-es6-class': 0, // Enforce ES5 or ES6 class for React Components
47+
'react/prefer-stateless-function': 0, // Enforce stateless React Components to be written as a pure function
48+
'react/prop-types': 1, // Prevent missing props validation in a React component definition
49+
'react/react-in-jsx-scope': 1, // Prevent missing React when using JSX
50+
'react/require-optimization': 0, // Enforce React components to have a shouldComponentUpdate method
51+
'react/require-render-return': 1, // Enforce ES5 or ES6 class for returning value in render function
52+
'react/self-closing-comp': 0, // Prevent extra closing tags for components without children (fixable)
53+
'react/sort-comp': 0, // Enforce component methods order
54+
'react/sort-prop-types': 0, // Enforce propTypes declarations alphabetical sorting
55+
'react/style-prop-object': 0, // Enforce style prop value being an object
56+
57+
// JSX-specific rules
58+
59+
'react/jsx-boolean-value': 0, // Enforce boolean attributes notation in JSX (fixable)
60+
'react/jsx-closing-bracket-location': 0, // Validate closing bracket location in JSX (fixable)
61+
'react/jsx-curly-spacing': 0, // Enforce or disallow spaces inside of curly braces in JSX attributes (fixable)
62+
'react/jsx-equals-spacing': 0, // Enforce or disallow spaces around equal signs in JSX attributes (fixable)
63+
'react/jsx-filename-extension': 0, // Restrict file extensions that may contain JSX
64+
'react/jsx-first-prop-new-line': 0, // Enforce position of the first prop in JSX (fixable)
65+
'react/jsx-handler-names': 0, // Enforce event handler naming conventions in JSX
66+
'react/jsx-indent': 0, // Validate JSX indentation (fixable)
67+
'react/jsx-indent-props': 0, // Validate props indentation in JSX (fixable)
68+
'react/jsx-key': 0, // Validate JSX has key prop when in array or iterator
69+
'react/jsx-max-props-per-line': 0, // Limit maximum of props on a single line in JSX
70+
'react/jsx-no-bind': 0, // Prevent usage of .bind() and arrow functions in JSX props
71+
'react/jsx-no-comment-textnodes': 0, // Prevent comments from being inserted as text nodes
72+
'react/jsx-no-duplicate-props': 1, // Prevent duplicate props in JSX
73+
'react/jsx-no-literals': 0, // Prevent usage of unwrapped JSX strings
74+
'react/jsx-no-target-blank': 0, // Prevent usage of unsafe target='_blank'
75+
'react/jsx-no-undef': 1, // Disallow undeclared variables in JSX
76+
'react/jsx-pascal-case': 0, // Enforce PascalCase for user-defined JSX components
77+
'react/jsx-sort-props': 0, // Enforce props alphabetical sorting
78+
'react/jsx-space-before-closing': 0, // Validate spacing before closing bracket in JSX (fixable)
79+
'react/jsx-tag-spacing': 0, // Validate whitespace in and around the JSX opening and closing brackets (fixable)
80+
'react/jsx-uses-react': 1, // Prevent React to be incorrectly marked as unused
81+
'react/jsx-uses-vars': 1, // Prevent variables used in JSX to be incorrectly marked as unused
82+
'react/jsx-wrap-multilines': 0, // Prevent missing parentheses around multilines JSX (fixable)
83+
}
84+
};

test/test.js

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
/* eslint-disable global-require, no-unused-expressions */
2-
var linter = require('eslint').linter;
2+
var path = require('path');
33
var expect = require('chai').expect;
4+
var CLIEngine = require('eslint').CLIEngine;
45

56
describe('eslint-config-fullstack', function () {
67

7-
var eConfigFs;
8+
var eConfigFs, cli;
89
before('load the module', function () {
910
eConfigFs = require('../index.js');
11+
cli = new CLIEngine({
12+
configFile: path.join(__dirname, '../index.js')
13+
});
1014
});
1115

1216
it('exports an object', function () {
@@ -22,15 +26,54 @@ describe('eslint-config-fullstack', function () {
2226
});
2327

2428
it('works with eslint', function () {
25-
var messages = linter.verify('var x = 1;', eConfigFs);
26-
expect(messages).to.be.an('array');
27-
if (messages[0]) expect(messages[0].fatal).not.to.be.true;
29+
var report = cli.executeOnText('var x = 1;');
30+
expect(report.errorCount).to.equal(0);
2831
});
2932

3033
it('has a parsing error for invalid source', function () {
31-
var messages = linter.verify('if;', eConfigFs);
32-
expect(messages).to.be.an('array');
33-
expect(messages[0].fatal).to.be.true;
34+
var report = cli.executeOnText('if;');
35+
expect(report.errorCount).to.equal(1);
36+
});
37+
38+
it('flags broken rules from the base config', function () {
39+
var report = cli.executeOnText('var x = typeof 5 === "_oops_"');
40+
expect(report.errorCount).to.equal(1);
41+
});
42+
43+
});
44+
45+
describe('eslint-config-fullstack/react', function () {
46+
47+
var cli;
48+
before('load the module', function () {
49+
cli = new CLIEngine({
50+
configFile: path.join(__dirname, '../react.js')
51+
});
52+
});
53+
54+
it('works with eslint', function () {
55+
var report = cli.executeOnText('var x = 1;');
56+
expect(report.errorCount).to.equal(0);
57+
});
58+
59+
it('has a parsing error for invalid source', function () {
60+
var report = cli.executeOnText('if;');
61+
expect(report.errorCount).to.equal(1);
62+
});
63+
64+
it('flags broken rules from the base config', function () {
65+
var report = cli.executeOnText('var x = typeof 5 === "_oops_"');
66+
expect(report.errorCount).to.equal(1);
67+
});
68+
69+
it('handles ES6 export and jsx', function () {
70+
var report = cli.executeOnText('import React from "react"; export default function Bar () { return (<div>qux</div>); } Bar.displayName = "Bar"\n');
71+
expect(report.errorCount).to.equal(0);
72+
});
73+
74+
it('flags broken jsx', function () {
75+
var report = cli.executeOnText('export default ({ foo }) => (<divs>{ foo }</div>);');
76+
expect(report.errorCount).to.equal(1);
3477
});
3578

3679
});

0 commit comments

Comments
 (0)