react and a11y linting

This commit is contained in:
Sérgio Ramos 2016-10-25 20:15:33 +01:00
parent 52deeae260
commit 6bf401b3bb
22 changed files with 270 additions and 57 deletions

View File

@ -10,19 +10,90 @@
}, },
"plugins": [ "plugins": [
"babel", "babel",
"react" "react",
"jsx-a11y"
], ],
"rules": { "rules": {
"react/jsx-no-undef": 2,
"react/jsx-uses-react": 2,
"react/jsx-uses-vars": 2,
"react/no-deprecated": 2,
"react/no-direct-mutation-state": 2,
"react/no-find-dom-node": 2,
"react/no-is-mounted": 2,
"react/no-unknown-property": 2,
"react/no-render-return-value": 2,
"react/prop-types": 2,
"react/react-in-jsx-scope": 2,
"react/require-render-return": 2,
"react/no-children-prop": 2,
"react/no-danger": 2,
"react/no-danger-with-children": 2,
"react/no-did-mount-set-state": 2,
"react/no-did-update-set-state": 2,
"react/no-multi-comp": 1,
"react/no-string-refs": 2,
"react/no-unescaped-entities": 2,
"react/no-unused-prop-types": 2,
"react/prefer-stateless-function": 2,
"react/self-closing-comp": 2,
"react/sort-comp": 2,
"react/sort-prop-types": 2,
"react/style-prop-object": 2,
"react/jsx-boolean-value": [2, "never"],
"react/jsx-closing-bracket-location": 2,
"react/jsx-curly-spacing": [2, "never"],
"react/jsx-equals-spacing": [2, "never"],
"react/jsx-filename-extension": [2, {
"extensions": [".js"]
}],
"react/jsx-first-prop-new-line": [2, "multiline"],
"react/jsx-handler-names": 2,
"react/jsx-indent": [2, 2],
"react/jsx-indent-props": [2, 2],
"react/jsx-key": 2,
"react/jsx-max-props-per-line": [2, {
"maximum": 2
}],
"react/jsx-no-bind": 2,
"react/jsx-no-comment-textnodes": 2,
"react/jsx-no-duplicate-props": 2,
"react/jsx-no-target-blank": 2,
"react/jsx-pascal-case": 2,
"react/jsx-sort-props": 2,
"react/jsx-space-before-closing": 2,
"react/jsx-wrap-multilines": 2,
"jsx-a11y/anchor-has-content": 2,
"jsx-a11y/href-no-hash": 2,
"jsx-a11y/aria-props": 2,
"jsx-a11y/aria-proptypes": 2,
"jsx-a11y/aria-role": 2,
"jsx-a11y/aria-unsupported-elements": 2,
"jsx-a11y/click-events-have-key-events": 2,
"jsx-a11y/mouse-events-have-key-events": 2,
"jsx-a11y/heading-has-content": 2,
"jsx-a11y/html-has-lang": 2,
"jsx-a11y/img-has-alt": 2,
"jsx-a11y/img-redundant-alt": 2,
"jsx-a11y/label-has-for": 2,
"jsx-a11y/lang": 2,
"jsx-a11y/no-access-key": 2,
"jsx-a11y/no-marquee": 2,
"jsx-a11y/no-onchange": 2,
"jsx-a11y/no-static-element-interactions": 2,
"jsx-a11y/onclick-has-focus": 2,
"jsx-a11y/onclick-has-role": 2,
"jsx-a11y/role-has-required-aria-props": 2,
"jsx-a11y/role-supports-aria-props": 2,
"jsx-a11y/scope": 2,
"jsx-a11y/tabindex-no-positive": 2,
"generator-star-spacing": 0, "generator-star-spacing": 0,
"babel/generator-star-spacing": 1, "babel/generator-star-spacing": 1,
"space-before-function-paren": [2, "never"], "space-before-function-paren": [2, "never"],
"react/jsx-uses-react": 2, "object-curly-newline": [2, {
"react/jsx-uses-vars": 2,
"react/react-in-jsx-scope": 2,
"object-curly-newline": ["error", {
"minProperties": 1 "minProperties": 1
}], }],
"sort-vars": ["error", { "sort-vars": [2, {
"ignoreCase": true "ignoreCase": true
}] }]
} }

View File

@ -62,6 +62,7 @@
"eslint-config-semistandard": "^7.0.0", "eslint-config-semistandard": "^7.0.0",
"eslint-config-standard": "^6.2.0", "eslint-config-standard": "^6.2.0",
"eslint-plugin-babel": "^3.3.0", "eslint-plugin-babel": "^3.3.0",
"eslint-plugin-jsx-a11y": "^2.2.3",
"eslint-plugin-promise": "^3.3.0", "eslint-plugin-promise": "^3.3.0",
"eslint-plugin-react": "^6.4.1", "eslint-plugin-react": "^6.4.1",
"eslint-plugin-standard": "^2.0.1", "eslint-plugin-standard": "^2.0.1",

View File

@ -20,6 +20,11 @@ const {
} = ReactRouter; } = ReactRouter;
const App = connect()(React.createClass({ const App = connect()(React.createClass({
propTypes: {
children: React.PropTypes.node,
dispatch: React.PropTypes.func,
router: React.PropTypes.object
},
componentWillMount: function() { componentWillMount: function() {
const { const {
router, router,
@ -51,8 +56,14 @@ const App = connect()(React.createClass({
module.exports = (props) => { module.exports = (props) => {
return ( return (
<App {...props}> <App {...props}>
<Match exactly pattern='/' component={Home} /> <Match
<Miss component={NotFound}/> component={Home}
exactly
pattern='/'
/>
<Miss
component={NotFound}
/>
</App> </App>
); );
}; };

View File

@ -6,7 +6,7 @@ const {
FormattedMessage FormattedMessage
} = ReactIntl; } = ReactIntl;
module.exports = () => { const Home = () => {
return ( return (
<div className={styles.home}> <div className={styles.home}>
<h1> <h1>
@ -15,3 +15,5 @@ module.exports = () => {
</div> </div>
); );
}; };
module.exports = Home;

View File

@ -1,6 +1,6 @@
const React = require('react'); const React = require('react');
module.exports = () => { const NotFound = () => {
return ( return (
<div> <div>
<h1>404</h1> <h1>404</h1>
@ -8,3 +8,5 @@ module.exports = () => {
</div> </div>
); );
}; };
module.exports = NotFound;

View File

@ -1928,6 +1928,10 @@ d@^0.1.1, d@~0.1.1:
dependencies: dependencies:
es5-ext "~0.10.2" es5-ext "~0.10.2"
damerau-levenshtein@^1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.3.tgz#ae4f4ce0b62acae10ff63a01bb08f652f5213af2"
dashdash@^1.12.0: dashdash@^1.12.0:
version "1.14.0" version "1.14.0"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.0.tgz#29e486c5418bf0f356034a993d51686a33e84141" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.0.tgz#29e486c5418bf0f356034a993d51686a33e84141"
@ -2279,6 +2283,14 @@ eslint-plugin-babel@^3.3.0:
version "3.3.0" version "3.3.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-3.3.0.tgz#2f494aedcf6f4aa4e75b9155980837bc1fbde193" resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-3.3.0.tgz#2f494aedcf6f4aa4e75b9155980837bc1fbde193"
eslint-plugin-jsx-a11y:
version "2.2.3"
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-2.2.3.tgz#4e35cb71b8a7db702ac415c806eb8e8d9ea6c65d"
dependencies:
damerau-levenshtein "^1.0.0"
jsx-ast-utils "^1.0.0"
object-assign "^4.0.1"
eslint-plugin-promise@^3.3.0: eslint-plugin-promise@^3.3.0:
version "3.3.0" version "3.3.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.3.0.tgz#20a1ef58b4243ffdaef82ee9360a02353a7cca89" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.3.0.tgz#20a1ef58b4243ffdaef82ee9360a02353a7cca89"
@ -3443,7 +3455,7 @@ jsprim@^1.2.2:
json-schema "0.2.3" json-schema "0.2.3"
verror "1.3.6" verror "1.3.6"
jsx-ast-utils@^1.3.1: jsx-ast-utils@^1.0.0, jsx-ast-utils@^1.3.1:
version "1.3.2" version "1.3.2"
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.3.2.tgz#dff658782705352111f9865d40471bc4a955961e" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.3.2.tgz#dff658782705352111f9865d40471bc4a955961e"
dependencies: dependencies:

View File

@ -2,4 +2,5 @@
coverage coverage
.nyc_output .nyc_output
docs/static docs/static
static static
webpack/embed-markdown-loader

View File

@ -10,19 +10,90 @@
}, },
"plugins": [ "plugins": [
"babel", "babel",
"react" "react",
"jsx-a11y"
], ],
"rules": { "rules": {
"react/jsx-no-undef": 2,
"react/jsx-uses-react": 2,
"react/jsx-uses-vars": 2,
"react/no-deprecated": 2,
"react/no-direct-mutation-state": 2,
"react/no-find-dom-node": 2,
"react/no-is-mounted": 2,
"react/no-unknown-property": 2,
"react/no-render-return-value": 2,
"react/prop-types": 2,
"react/react-in-jsx-scope": 2,
"react/require-render-return": 2,
"react/no-children-prop": 2,
"react/no-danger": 2,
"react/no-danger-with-children": 2,
"react/no-did-mount-set-state": 2,
"react/no-did-update-set-state": 2,
"react/no-multi-comp": 1,
"react/no-string-refs": 2,
"react/no-unescaped-entities": 2,
"react/no-unused-prop-types": 2,
"react/prefer-stateless-function": 2,
"react/self-closing-comp": 2,
"react/sort-comp": 2,
"react/sort-prop-types": 2,
"react/style-prop-object": 2,
"react/jsx-boolean-value": [2, "never"],
"react/jsx-closing-bracket-location": 2,
"react/jsx-curly-spacing": [2, "never"],
"react/jsx-equals-spacing": [2, "never"],
"react/jsx-filename-extension": [2, {
"extensions": [".js"]
}],
"react/jsx-first-prop-new-line": [2, "multiline"],
"react/jsx-handler-names": 2,
"react/jsx-indent": [2, 2],
"react/jsx-indent-props": [2, 2],
"react/jsx-key": 2,
"react/jsx-max-props-per-line": [2, {
"maximum": 2
}],
"react/jsx-no-bind": 2,
"react/jsx-no-comment-textnodes": 2,
"react/jsx-no-duplicate-props": 2,
"react/jsx-no-target-blank": 2,
"react/jsx-pascal-case": 2,
"react/jsx-sort-props": 2,
"react/jsx-space-before-closing": 2,
"react/jsx-wrap-multilines": 2,
"jsx-a11y/anchor-has-content": 2,
"jsx-a11y/href-no-hash": 2,
"jsx-a11y/aria-props": 2,
"jsx-a11y/aria-proptypes": 2,
"jsx-a11y/aria-role": 2,
"jsx-a11y/aria-unsupported-elements": 2,
"jsx-a11y/click-events-have-key-events": 2,
"jsx-a11y/mouse-events-have-key-events": 2,
"jsx-a11y/heading-has-content": 2,
"jsx-a11y/html-has-lang": 2,
"jsx-a11y/img-has-alt": 2,
"jsx-a11y/img-redundant-alt": 2,
"jsx-a11y/label-has-for": 2,
"jsx-a11y/lang": 2,
"jsx-a11y/no-access-key": 2,
"jsx-a11y/no-marquee": 2,
"jsx-a11y/no-onchange": 2,
"jsx-a11y/no-static-element-interactions": 2,
"jsx-a11y/onclick-has-focus": 2,
"jsx-a11y/onclick-has-role": 2,
"jsx-a11y/role-has-required-aria-props": 2,
"jsx-a11y/role-supports-aria-props": 2,
"jsx-a11y/scope": 2,
"jsx-a11y/tabindex-no-positive": 2,
"generator-star-spacing": 0, "generator-star-spacing": 0,
"babel/generator-star-spacing": 1, "babel/generator-star-spacing": 1,
"space-before-function-paren": [2, "never"], "space-before-function-paren": [2, "never"],
"react/jsx-uses-react": 2, "object-curly-newline": [2, {
"react/jsx-uses-vars": 2,
"react/react-in-jsx-scope": 2,
"object-curly-newline": ["error", {
"minProperties": 1 "minProperties": 1
}], }],
"sort-vars": ["error", { "sort-vars": [2, {
"ignoreCase": true "ignoreCase": true
}] }]
} }

View File

@ -7,7 +7,7 @@ const Item = require('../item/');
const { const {
Base Base
} = require('../../../src');; } = require('../../../src');
const { const {
Match Match
@ -17,8 +17,15 @@ module.exports = () => {
return ( return (
<Base> <Base>
<Navigation /> <Navigation />
<Match exactly pattern='/' component={Home} /> <Match
<Match pattern='/:parent?/:name' component={Item} /> component={Home}
exactly
pattern='/'
/>
<Match
component={Item}
pattern='/:parent?/:name'
/>
</Base> </Base>
); );
}; };

View File

@ -39,7 +39,7 @@ const getList = (items, parent) => {
); );
}; };
module.exports = () => { const Navigation = () => {
return ( return (
<div> <div>
<div className={styles.navigation}> <div className={styles.navigation}>
@ -50,3 +50,5 @@ module.exports = () => {
</div> </div>
); );
}; };
module.exports = Navigation;

View File

@ -1,5 +1,5 @@
const React = require('react'); const React = require('react');
module.exports = () => { module.exports = () => {
return (<div></div>); return (<div />);
}; };

View File

@ -6,7 +6,7 @@ const titleCase = require('title-case');
const Docs = require('../../../src/docs'); const Docs = require('../../../src/docs');
module.exports = ({ const Item = ({
params params
}) => { }) => {
const path = (params.parent !== 'undefined') const path = (params.parent !== 'undefined')
@ -26,3 +26,9 @@ module.exports = ({
</div> </div>
); );
}; };
Item.propTypes = {
params: React.PropTypes.object
};
module.exports = Item;

View File

@ -35,6 +35,7 @@
"eslint-config-semistandard": "^7.0.0", "eslint-config-semistandard": "^7.0.0",
"eslint-config-standard": "^6.2.0", "eslint-config-standard": "^6.2.0",
"eslint-plugin-babel": "^3.3.0", "eslint-plugin-babel": "^3.3.0",
"eslint-plugin-jsx-a11y": "^2.2.3",
"eslint-plugin-promise": "^3.3.0", "eslint-plugin-promise": "^3.3.0",
"eslint-plugin-react": "^6.4.1", "eslint-plugin-react": "^6.4.1",
"eslint-plugin-standard": "^2.0.1", "eslint-plugin-standard": "^2.0.1",

View File

@ -2,10 +2,10 @@ const React = require('react');
const classNames = require('classnames'); const classNames = require('classnames');
const styles = require('./style.css'); const styles = require('./style.css');
const Base = module.exports = ({ const Base = ({
children,
className, className,
style, style
children
}) => { }) => {
const cn = classNames( const cn = classNames(
className, className,
@ -13,14 +13,16 @@ const Base = module.exports = ({
); );
return ( return (
<div style={style} className={cn}> <div className={cn} style={style}>
{children} {children}
</div> </div>
); );
}; };
Base.propTypes = { Base.propTypes = {
children: React.PropTypes.node,
className: React.PropTypes.string, className: React.PropTypes.string,
style: React.PropTypes.object, style: React.PropTypes.object
children: React.PropTypes.node
}; };
module.exports = Base;

View File

@ -1,16 +1,28 @@
const React = require('react'); const React = require('react');
const styles = require('./style.css'); const styles = require('./style.css');
module.exports = ({ const Button = ({
disabled = false, disabled = false,
className,
style,
children children
}) => { }) => {
return ( return (
<button <button
className={styles.button} className={styles.button}
disabled={disabled} disabled={disabled}
style={style}
> >
{children} {children}
</button> </button>
); );
}; };
Button.propTypes = {
children: React.PropTypes.node,
className: React.PropTypes.string,
disabled: React.PropTypes.bool,
style: React.PropTypes.object
};
module.exports = Button;

View File

@ -27,11 +27,11 @@ const getClasses = (props) => {
})).filter(Boolean); })).filter(Boolean);
}; };
const Column = module.exports = (props) => { const Column = (props) => {
const { const {
children,
className, className,
reverse, reverse,
children,
style style
} = props; } = props;
@ -43,20 +43,22 @@ const Column = module.exports = (props) => {
); );
return ( return (
<div style={style} className={cn}> <div className={cn} style={style}>
{children} {children}
</div> </div>
); );
}; };
Column.propTypes = { Column.propTypes = {
reverse: React.PropTypes.bool,
className: React.PropTypes.string,
style: React.PropTypes.object,
children: React.PropTypes.node, children: React.PropTypes.node,
className: React.PropTypes.string,
reverse: React.PropTypes.bool,
style: React.PropTypes.object,
...breakpoints.reduce((all, bp) => ({ ...breakpoints.reduce((all, bp) => ({
...all, ...all,
[`${bp}Offset`]: React.PropTypes.number, [`${bp}Offset`]: React.PropTypes.number,
[bp]: React.PropTypes.number [bp]: React.PropTypes.number
}), {}) }), {})
}; };
module.exports = Column;

View File

@ -7,7 +7,7 @@ const React = require('react');
const classNames = require('classnames'); const classNames = require('classnames');
const styles = require('./style.css'); const styles = require('./style.css');
const Container = module.exports = ({ const Container = ({
fluid = false, fluid = false,
className, className,
children, children,
@ -19,15 +19,17 @@ const Container = module.exports = ({
); );
return ( return (
<div style={style} className={cn}> <div className={cn} style={style}>
{children} {children}
</div> </div>
); );
}; };
Container.propTypes = { Container.propTypes = {
fluid: React.PropTypes.bool, children: React.PropTypes.node,
className: React.PropTypes.string, className: React.PropTypes.string,
style: React.PropTypes.object, fluid: React.PropTypes.bool,
children: React.PropTypes.node style: React.PropTypes.object
}; };
module.exports = Container;

View File

@ -52,7 +52,7 @@ const getClasses = (props) => {
})).filter(Boolean); })).filter(Boolean);
}; };
const Row = module.exports = (props) => { const Row = (props) => {
const { const {
className, className,
reverse, reverse,
@ -68,7 +68,7 @@ const Row = module.exports = (props) => {
); );
return ( return (
<div style={style} className={cn}> <div className={cn} style={style}>
{children} {children}
</div> </div>
); );
@ -81,12 +81,14 @@ const ModificatorType = React.PropTypes.oneOfType([
]); ]);
Row.propTypes = { Row.propTypes = {
reverse: React.PropTypes.bool,
className: React.PropTypes.string,
style: React.PropTypes.object,
children: React.PropTypes.node, children: React.PropTypes.node,
className: React.PropTypes.string,
reverse: React.PropTypes.bool,
style: React.PropTypes.object,
...modifiers.reduce((all, m) => ({ ...modifiers.reduce((all, m) => ({
...all, ...all,
[m]: ModificatorType [m]: ModificatorType
}), {}) }), {})
}; };
module.exports = Row;

View File

@ -16,13 +16,10 @@ const plugins = {
require('postcss-modules-values'), require('postcss-modules-values'),
require('postcss-mixins')(), require('postcss-mixins')(),
require('postcss-for'), require('postcss-for'),
require('postcss-cssnext')(), require('postcss-cssnext')()
] ]
}, },
'embed-markdown-loader': { 'embed-markdown-loader': {}
// don't detach yet (has a bug in the production config)
// webpackConfigFullpath: path.join(__dirname, 'index.js')
}
} }
}) })
}; };

View File

@ -2,7 +2,6 @@ const WebpackShellPlugin = require('webpack-shell-plugin');
const base = require('./base.js'); const base = require('./base.js');
const webpack = require('webpack'); const webpack = require('webpack');
const entries = require('./entrypoints'); const entries = require('./entrypoints');
const path = require('path');
module.exports = Object.assign(base.config, { module.exports = Object.assign(base.config, {
entry: entries.reduce((all, entry) => { entry: entries.reduce((all, entry) => {

View File

@ -1,6 +1,4 @@
const base = require('./base'); const base = require('./base');
const webpack = require('webpack');
const path = require('path');
module.exports = { module.exports = {
output: { output: {
@ -16,4 +14,4 @@ module.exports = {
loader: 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader' loader: 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader'
}] }]
} }
}; };

View File

@ -1856,6 +1856,10 @@ d@^0.1.1, d@~0.1.1:
dependencies: dependencies:
es5-ext "~0.10.2" es5-ext "~0.10.2"
damerau-levenshtein@^1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.3.tgz#ae4f4ce0b62acae10ff63a01bb08f652f5213af2"
dangerously-set-inner-html@2.0.0: dangerously-set-inner-html@2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/dangerously-set-inner-html/-/dangerously-set-inner-html-2.0.0.tgz#da73f26330c9ef0b6b12ca443091904406ddb73a" resolved "https://registry.yarnpkg.com/dangerously-set-inner-html/-/dangerously-set-inner-html-2.0.0.tgz#da73f26330c9ef0b6b12ca443091904406ddb73a"
@ -2249,6 +2253,14 @@ eslint-plugin-babel@^3.3.0:
version "3.3.0" version "3.3.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-3.3.0.tgz#2f494aedcf6f4aa4e75b9155980837bc1fbde193" resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-3.3.0.tgz#2f494aedcf6f4aa4e75b9155980837bc1fbde193"
eslint-plugin-jsx-a11y:
version "2.2.3"
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-2.2.3.tgz#4e35cb71b8a7db702ac415c806eb8e8d9ea6c65d"
dependencies:
damerau-levenshtein "^1.0.0"
jsx-ast-utils "^1.0.0"
object-assign "^4.0.1"
eslint-plugin-promise@^3.3.0: eslint-plugin-promise@^3.3.0:
version "3.3.0" version "3.3.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.3.0.tgz#20a1ef58b4243ffdaef82ee9360a02353a7cca89" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.3.0.tgz#20a1ef58b4243ffdaef82ee9360a02353a7cca89"
@ -3328,7 +3340,7 @@ jsprim@^1.2.2:
json-schema "0.2.3" json-schema "0.2.3"
verror "1.3.6" verror "1.3.6"
jsx-ast-utils@^1.3.1: jsx-ast-utils@^1.0.0, jsx-ast-utils@^1.3.1:
version "1.3.2" version "1.3.2"
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.3.2.tgz#dff658782705352111f9865d40471bc4a955961e" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.3.2.tgz#dff658782705352111f9865d40471bc4a955961e"
dependencies: dependencies: