From c62665c96f9aa8bd200715900a252b651f7df632 Mon Sep 17 00:00:00 2001 From: Yannick Croissant Date: Tue, 16 Dec 2014 02:12:15 +0100 Subject: [PATCH] First revision --- README.md | 65 +++++++++++++++++++++++++++++++++++++- index.js | 12 +++++++ lib/rules/no-multi-comp.js | 26 +++++++++++++++ lib/rules/prop-types.js | 43 +++++++++++++++++++++++++ package.json | 30 ++++++++++++++++++ 5 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 index.js create mode 100644 lib/rules/no-multi-comp.js create mode 100644 lib/rules/prop-types.js create mode 100644 package.json diff --git a/README.md b/README.md index 5bf3dda69f..1af32b42ab 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,67 @@ -eslint-plugin-react +ESLint-plugin-React =================== React specific linting rules for ESLint + +# Installation + +Install [ESLint](https://www.github.com/eslint/eslint) either locally or globally. + + npm install eslint@es6jsx + +ESLint-plugin-React requires `ESLint` with JSX support which is only available on the `es6jsx` branch for now. + +If you installed `ESLint` globally, you have to install React plugin globally too. Otherwise, install it locally. + + $ npm install eslint-plugin-react + +# Configuration + +Add `plugins` section and specify ESLint-plugin-React as a plugin. + +```json +{ + "plugins": [ + "react" + ] +} +``` + +If it is not already the case you must also configure `ESLint` to support ECMAScript 6 and JSX. + +```json +{ + "settings": { + "ecmascript": 6, + "jsx": true + } +} +``` + +Finally, enable all of the rules that you would like to use. + +```json +{ + "rules": { + "react/no-multi-comp": 1, + "react/prop-types": 1 + } +} +``` + +# List of supported rules + +* no-multi-comp: Prevent multiple component definition per file +* prop-types: Prevent missing propTypes in a React component definition + +## Not supported yet + +* display-name: Prevent missing displayName in a React component definition +* no-deprecated: Prevent usage of deprecated methods ([React 0.12 Updated API](http://facebook.github.io/react/blog/2014/10/28/react-v0.12.html#new-terminology-amp-updated-apis)) +* no-classic: Prevent usage of "classic" methods ([#2700](https://github.com/facebook/react/pull/2700)) + +[Any rule idea is welcome !](https://github.com/yannickcr/eslint-plugin-react/issues) + +# License + +ESLint-plugin-React is licensed under the [MIT License](http://www.opensource.org/licenses/mit-license.php). diff --git a/index.js b/index.js new file mode 100644 index 0000000000..31a61270c7 --- /dev/null +++ b/index.js @@ -0,0 +1,12 @@ +'use strict'; + +module.exports = { + rules: { + 'no-multi-comp': require('./lib/rules/no-multi-comp'), + 'prop-types': require('./lib/rules/prop-types') + }, + rulesConfig: { + 'no-multi-comp': 0, + 'prop-types': 0 + } +}; diff --git a/lib/rules/no-multi-comp.js b/lib/rules/no-multi-comp.js new file mode 100644 index 0000000000..18e9a68bd7 --- /dev/null +++ b/lib/rules/no-multi-comp.js @@ -0,0 +1,26 @@ +/** + * @fileoverview Prevent multiple component definition per file + * @author Yannick Croissant + */ +'use strict'; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = function(context) { + + var componentCounter = 0; + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + return { + 'MemberExpression': function(node) { + if (node.object.name === 'React' && node.property.name === 'createClass' && ++componentCounter > 1) { + context.report(node, 'Declare only one React component per file'); + } + } + }; +}; diff --git a/lib/rules/prop-types.js b/lib/rules/prop-types.js new file mode 100644 index 0000000000..5c7d9f752a --- /dev/null +++ b/lib/rules/prop-types.js @@ -0,0 +1,43 @@ +/** + * @fileoverview Prevent missing propTypes in a React component definition + * @author Yannick Croissant + */ +'use strict'; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = function(context) { + + var hasPropTypes = false; + + return { + + 'ObjectExpression': function(node) { + + if (!node.parent.callee || node.parent.callee.object.name !== 'React' || node.parent.callee.property.name !== 'createClass') { + return; + } + + node.properties.forEach(function(property) { + var keyName = property.key.name || property.key.value; + if (keyName === 'propTypes') { + hasPropTypes = true; + } + }); + + }, + + 'ObjectExpression:exit': function(node) { + if (!node.parent.callee || node.parent.callee.object.name !== 'React' || node.parent.callee.property.name !== 'createClass') { + return; + } + if (!hasPropTypes) { + context.report(node, 'Component definition is missing props validation'); + } + hasPropTypes = false; + } + }; + +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000000..4dbb6565ed --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "eslint-plugin-react", + "version": "1.0.0", + "description": "React specific linting rules for ESLint", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/yannickcr/eslint-plugin-react" + }, + "keywords": [ + "eslint-plugin", + "eslintplugin", + "eslint", + "react" + ], + "author": "Yannick Croissant (https://github.com/yannickcr)", + "licenses": [ + { + "type": "MIT", + "url": "https://raw.github.com/yannickcr/eslint-plugin-react/master/LICENSE" + } + ], + "bugs": { + "url": "https://github.com/yannickcr/eslint-plugin-react/issues" + }, + "homepage": "https://github.com/yannickcr/eslint-plugin-react" +}