diff --git a/.travis.yml b/.travis.yml
index df4ad7cf56..b43ee559d0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,6 +11,7 @@ install:
- 'if [ -n "${PACKAGE-}" ]; then cd "packages/${PACKAGE}"; fi'
- 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ] || [ "${TRAVIS_NODE_VERSION}" = "0.9" ]; then nvm install --latest-npm 0.8 && npm install && nvm use "${TRAVIS_NODE_VERSION}"; else npm install; fi;'
- 'if [ -n "${ESLINT}" ]; then npm install --no-save "eslint@${ESLINT}"; fi'
+ - 'if [ -n "${REACT_HOOKS}" ]; then npm install --no-save "eslint-plugin-react-hooks@${REACT_HOOKS}"; fi'
script:
- 'if [ -n "${PREPUBLISH-}" ]; then npm run pretravis && npm run prepublish && npm run posttravis; elif [ -n "${LINT-}" ]; then npm run lint; else npm run travis; fi'
sudo: false
@@ -18,8 +19,10 @@ env:
matrix:
- 'TEST=true ESLINT=6 PACKAGE=eslint-config-airbnb-base'
- 'TEST=true ESLINT=6 PACKAGE=eslint-config-airbnb'
+ - 'TEST=true ESLINT=6 REACT_HOOKS=1.7 PACKAGE=eslint-config-airbnb'
- 'TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb-base'
- 'TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb'
+ - 'TEST=true ESLINT=5 REACT_HOOKS=1.7 PACKAGE=eslint-config-airbnb'
matrix:
fast_finish: true
include:
@@ -27,20 +30,28 @@ matrix:
env: PREPUBLISH=true ESLINT=6 PACKAGE=eslint-config-airbnb-base
- node_js: "lts/*"
env: PREPUBLISH=true ESLINT=6 PACKAGE=eslint-config-airbnb
+ - node_js: "lts/*"
+ env: PREPUBLISH=true ESLINT=6 REACT_HOOKS=1.7 PACKAGE=eslint-config-airbnb
- node_js: "lts/*"
env: PREPUBLISH=true ESLINT=5 PACKAGE=eslint-config-airbnb-base
- node_js: "lts/*"
env: PREPUBLISH=true ESLINT=5 PACKAGE=eslint-config-airbnb
+ - node_js: "lts/*"
+ env: PREPUBLISH=true ESLINT=5 REACT_HOOKS=1.7 PACKAGE=eslint-config-airbnb
- node_js: "lts/*"
env: LINT=true
- node_js: "7"
env: TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb-base
- node_js: "7"
env: TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb
+ - node_js: "7"
+ env: TEST=true ESLINT=5 REACT_HOOKS=1.7 PACKAGE=eslint-config-airbnb
- node_js: "6"
env: TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb-base
- node_js: "6"
env: TEST=true ESLINT=5 PACKAGE=eslint-config-airbnb
+ - node_js: "6"
+ env: TEST=true ESLINT=5 REACT_HOOKS=1.7 PACKAGE=eslint-config-airbnb
exclude:
allow_failures:
- node_js: "11"
diff --git a/README.md b/README.md
index 73371e6b44..ed145f3f17 100644
--- a/README.md
+++ b/README.md
@@ -1590,6 +1590,7 @@ Other Style Guides
const isJedi = getProp('jedi');
```
+
- [12.3](#es2016-properties--exponentiation-operator) Use exponentiation operator `**` when calculating exponentiations. eslint: [`no-restricted-properties`](https://eslint.org/docs/rules/no-restricted-properties).
@@ -1703,6 +1704,7 @@ Other Style Guides
return name;
}
```
+
- [13.5](#variables--no-chain-assignment) Don’t chain variable assignments. eslint: [`no-multi-assign`](https://eslint.org/docs/rules/no-multi-assign)
diff --git a/linters/.markdownlint.json b/linters/.markdownlint.json
index 594886042d..118b8a6ec6 100644
--- a/linters/.markdownlint.json
+++ b/linters/.markdownlint.json
@@ -26,7 +26,8 @@
"comment": "MD007: Unordered list indentation: 2 spaces.",
"ul-indent": {
- "indent": 2
+ "indent": 2,
+ "start_indented": true
},
"comment": "MD009: Disallow trailing spaces!",
diff --git a/package.json b/package.json
index 581c94f612..36b4e19fab 100644
--- a/package.json
+++ b/package.json
@@ -4,6 +4,7 @@
"description": "A mostly reasonable approach to JavaScript.",
"scripts": {
"preinstall": "npm run install:config && npm run install:config:base",
+ "postinstall": "rm -rf node_modules/markdownlint-cli/node_modules/markdownlint",
"install:config": "cd packages/eslint-config-airbnb && npm prune && npm install",
"install:config:base": "cd packages/eslint-config-airbnb-base && npm prune && npm install",
"lint": "markdownlint --config linters/.markdownlint.json README.md */README.md",
@@ -39,6 +40,7 @@
},
"homepage": "https://github.com/airbnb/javascript",
"devDependencies": {
- "markdownlint-cli": "^0.13.0"
+ "markdownlint": "^0.19.0",
+ "markdownlint-cli": "^0.21.0"
}
}
diff --git a/packages/eslint-config-airbnb/package.json b/packages/eslint-config-airbnb/package.json
index c58f98a902..74a699a34c 100644
--- a/packages/eslint-config-airbnb/package.json
+++ b/packages/eslint-config-airbnb/package.json
@@ -68,7 +68,7 @@
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-react": "^7.18.3",
- "eslint-plugin-react-hooks": "^1.7.0",
+ "eslint-plugin-react-hooks": "^2.0.0 || ^1.7.0",
"in-publish": "^2.0.0",
"react": ">= 0.13.0",
"safe-publish-latest": "^1.1.4",
@@ -79,7 +79,7 @@
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-react": "^7.18.3",
- "eslint-plugin-react-hooks": "^1.7.0"
+ "eslint-plugin-react-hooks": "^2.0.0 || ^1.7.0"
},
"engines": {
"node": ">= 6"
diff --git a/packages/eslint-config-airbnb/rules/react.js b/packages/eslint-config-airbnb/rules/react.js
index fc1a3a90a9..e712f0d77f 100644
--- a/packages/eslint-config-airbnb/rules/react.js
+++ b/packages/eslint-config-airbnb/rules/react.js
@@ -500,6 +500,35 @@ module.exports = {
// Enforce that props are read-only
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-read-only-props.md
'react/prefer-read-only-props': 'off',
+
+ // Prevent usage of `javascript:` URLs
+ // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-script-url.md
+ // TODO: enable, semver-major
+ 'react/jsx-no-script-url': ['off', [
+ {
+ name: 'Link',
+ props: ['to'],
+ },
+ ]],
+
+ // Disallow unnecessary fragments
+ // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-useless-fragment.md
+ // TODO: enable, semver-major
+ 'react/jsx-no-useless-fragment': 'off',
+
+ // Prevent adjacent inline elements not separated by whitespace
+ // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-adjacent-inline-elements.md
+ // TODO: enable? semver-major
+ 'react/no-adjacent-inline-elements': 'off',
+
+ // Enforce a specific function type for function components
+ // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/function-component-definition.md
+ // TODO: enable! semver-minor, but do it in a major to be safe
+ // TODO: investigate if setting namedComponents to expression vs declaration is problematic
+ 'react/function-component-definition': ['off', {
+ namedComponents: 'function-expression',
+ unnamedComponents: 'function-expression',
+ }],
},
settings: {
diff --git a/react/README.md b/react/README.md
index a17cdf7a5b..af8c13d720 100644
--- a/react/README.md
+++ b/react/README.md
@@ -111,6 +111,7 @@ This style guide is mostly based on the standards that are currently prevalent i
// good
import Footer from './Footer';
```
+
- **Higher-order Component Naming**: Use a composite of the higher-order component’s name and the passed-in component’s name as the `displayName` on the generated component. For example, the higher-order component `withFoo()`, when passed a component `Bar` should produce a component with a `displayName` of `withFoo(Bar)`.
> Why? A component’s `displayName` may be used by developer tools or in error messages, and having a value that clearly expresses this relationship helps people understand what is happening.