diff --git a/CHANGELOG.md b/CHANGELOG.md index 14e77cb..745ddbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). Except add new rule (it is breaking changed by default). +## 93.0.0 - 2018-12-11 + +- Added: `react/forbid-foreign-prop-types` rule. +- Added: `react/no-unused-state` rule. +- Added: `react/destructuring-assignment` rule. +- Added: `lodash/collection-ordering` rule. +- Added: `mjs` extesion for `import/extensions` rules. +- Changed: `checkContextTypes` and `checkChildContextTypes` for `react/forbid-prop-types` rule. +- Changed: use `React` pragma. +- Changed: add `ignoreCase` to `react/jsx-no-duplicate-props` rule. +- Changed: disable `react/sort-prop-types` rule. +- Changed: disable `react/jsx-handler-names` rule. +- Changed: better order for `react/sort-comp` rule. +- Changed: disable `react/jsx-sort-props` rule. +- Changed: disable `react/jsx-sort-default-props` rule. +- Changed: disable `sort-keys` rule. + ## 92.0.1 - 2018-12-07 - Fixed: `no-process-exit` should disable, but `recommended` preset of `eslint-plugin-node` enable rule. diff --git a/__tests__/all-rules/.eslintrc.js b/__tests__/all-rules/.eslintrc.js new file mode 100644 index 0000000..fc3eb59 --- /dev/null +++ b/__tests__/all-rules/.eslintrc.js @@ -0,0 +1,8 @@ +const path = require("path"); + +module.exports = { + extends: [path.resolve(__dirname, "../../lib/config/all.js")], + rules: { + "node/no-unsupported-features/es-syntax": "off" + } +}; diff --git a/__tests__/all-rules/index.jsx b/__tests__/all-rules/index.jsx new file mode 100644 index 0000000..2072907 --- /dev/null +++ b/__tests__/all-rules/index.jsx @@ -0,0 +1,28 @@ +import React from "react"; +import PropTypes from "prop-types"; + +class Greeting extends React.Component { + static propTypes = { + name: PropTypes.string.isRequired, + count: PropTypes.string.isRequired + }; + + constructor(props) { + super(props); + + this.state = { count: props.count }; + } + + render() { + const { name } = this.props; + const { count } = this.state; + + return ( +

+ Hello, {name}, count ${count}! +

+ ); + } +} + +export default Greeting; diff --git a/__tests__/fixtures/react/.eslintrc.json b/__tests__/fixtures/react/.eslintrc.json index b6034eb..d2d01df 100644 --- a/__tests__/fixtures/react/.eslintrc.json +++ b/__tests__/fixtures/react/.eslintrc.json @@ -2,6 +2,9 @@ "env": { "browser": true }, - "extends": ["../../../lib/config/react.js"], + "extends": [ + "../../../lib/config/esnext.js", + "../../../lib/config/react.js" + ], "root": true } diff --git a/__tests__/fixtures/react/App.jsx b/__tests__/fixtures/react/App.jsx index ea40844..a125355 100644 --- a/__tests__/fixtures/react/App.jsx +++ b/__tests__/fixtures/react/App.jsx @@ -1,28 +1,22 @@ -import "./app.scss"; -import Profile from "./Profile"; import React from "react"; import ReactDOM from "react-dom"; import SearchProfile from "./SearchProfile"; +import Profile from "./Profile"; +import "./app.scss"; class App extends React.Component { constructor(props) { super(props); this.state = { - avatar: "", - followers: "", - following: "", - homeUrl: "", - location: "", - name: "", - notFound: "", - repos: "", username: "hesmaili" }; } componentDidMount() { - SearchProfile.fetchProfile(this.state.username); + const { username } = this.state; + + SearchProfile.fetchProfile(username); } render() { diff --git a/__tests__/index.js b/__tests__/index.js index 63bcdbe..7dddf9e 100644 --- a/__tests__/index.js +++ b/__tests__/index.js @@ -381,7 +381,7 @@ test("integration tests for `esnext`", t => { test("integration tests for `react`", t => { const cli = new eslint.CLIEngine({ - baseConfig: Object.assign({}, configs.react) + baseConfig: Object.assign({}, configs.esnext, configs.react) }); const report = cli.executeOnFiles([ diff --git a/lib/config/all.js b/lib/config/all.js index 3e585eb..4fd592b 100644 --- a/lib/config/all.js +++ b/lib/config/all.js @@ -6,6 +6,7 @@ const deprecatedRules = require("./rules/deprecated"); const ecmascript6Rules = require("./rules/ecmascript-6"); const importRules = require("./rules/import"); const jestRules = require("./rules/jest"); +const lodashRules = require("./rules/lodash"); const jsxA11yRules = require("./rules/jsx-a11y"); const nodeRules = require("./rules/node"); const possibleErrorsRules = require("./rules/possible-errors"); @@ -57,23 +58,12 @@ module.exports = { avaRules, unicornRules, jestRules, + lodashRules, importRules, promiseRules, jsxA11yRules, reactRules ), - extends: [ - "eslint:recommended", - "plugin:ava/recommended", - "plugin:import/recommended", - "plugin:jsx-a11y/recommended", - "plugin:promise/recommended", - "plugin:unicorn/recommended", - "plugin:jest/recommended", - "plugin:lodash/recommended", - "plugin:node/recommended", - "plugin:react/recommended" - ], settings: { react: { version: "999.999.999" diff --git a/lib/config/ava.js b/lib/config/ava.js index 82af0bc..ee74286 100644 --- a/lib/config/ava.js +++ b/lib/config/ava.js @@ -7,6 +7,5 @@ module.exports = { es6: true }, plugins: ["ava"], - extends: ["plugin:ava/recommended"], rules: Object.assign({}, avaRules) }; diff --git a/lib/config/core.js b/lib/config/core.js index e446d8a..7fca25a 100644 --- a/lib/config/core.js +++ b/lib/config/core.js @@ -11,11 +11,6 @@ const unicornRules = require("./rules/unicorn"); module.exports = { plugins: ["import", "unicorn"], - extends: [ - "eslint:recommended", - "plugin:import/recommended", - "plugin:unicorn/recommended" - ], env: { es6: false }, diff --git a/lib/config/esnext.js b/lib/config/esnext.js index e951c6a..d6e2159 100644 --- a/lib/config/esnext.js +++ b/lib/config/esnext.js @@ -14,6 +14,6 @@ module.exports = { allowImportExportEverywhere: true }, plugins: ["promise"], - extends: [path.resolve(__dirname, "./core.js"), "plugin:promise/recommended"], + extends: [path.resolve(__dirname, "./core.js")], rules: Object.assign({}, ecmascript6Rules, promiseRules) }; diff --git a/lib/config/jest.js b/lib/config/jest.js index 97b67ae..51cd505 100644 --- a/lib/config/jest.js +++ b/lib/config/jest.js @@ -5,6 +5,5 @@ const jestRules = require("./rules/jest"); module.exports = { env: { es6: true }, plugins: ["jest"], - extends: ["plugin:jest/recommended", "plugin:jest/style"], rules: Object.assign({}, jestRules) }; diff --git a/lib/config/lodash.js b/lib/config/lodash.js index 9953ec2..4a9fd0c 100644 --- a/lib/config/lodash.js +++ b/lib/config/lodash.js @@ -4,6 +4,5 @@ const lodashRules = require("./rules/lodash"); module.exports = { plugins: ["lodash"], - extends: ["plugin:lodash/recommended"], rules: Object.assign({}, lodashRules) }; diff --git a/lib/config/node.js b/lib/config/node.js index d7cd354..eaf3993 100644 --- a/lib/config/node.js +++ b/lib/config/node.js @@ -15,7 +15,6 @@ module.exports = { SharedArrayBuffer: false }, plugins: ["node"], - extends: ["plugin:node/recommended"], settings: { node: { tryExtensions: [".js", ".jsx", ".json", ".node"], diff --git a/lib/config/react.js b/lib/config/react.js index 9e765f2..3dd24b9 100644 --- a/lib/config/react.js +++ b/lib/config/react.js @@ -22,11 +22,11 @@ module.exports = { }, settings: { react: { + pragma: "React", version: "999.999.999" } }, plugins: ["react", "jsx-a11y"], - extends: ["plugin:react/recommended", "plugin:jsx-a11y/recommended"], rules: Object.assign({}, reactRules, jsxA11yRules, { "class-methods-use-this": [ "error", @@ -37,12 +37,17 @@ module.exports = { "getDefaultProps", "getChildContext", "componentWillMount", + "UNSAFE_componentWillMount", "componentDidMount", "componentWillReceiveProps", + "UNSAFE_componentWillReceiveProps", "shouldComponentUpdate", "componentWillUpdate", + "UNSAFE_componentWillUpdate", "componentDidUpdate", - "componentWillUnmount" + "componentWillUnmount", + "componentDidCatch", + "getSnapshotBeforeUpdate" ] } ] diff --git a/lib/config/rules/ava.js b/lib/config/rules/ava.js index 2281060..bccf8e5 100644 --- a/lib/config/rules/ava.js +++ b/lib/config/rules/ava.js @@ -4,79 +4,55 @@ module.exports = { // Enforce passing correct arguments to assertions. - // In recommended - // "ava/assertion-arguments": "error", + "ava/assertion-arguments": "error", // Limit the number of assertions in a test. - // In recommended - // "ava/max-asserts": ["off", 5], + "ava/max-asserts": ["off", 5], // Ensure that async tests use await - // In recommended - // "ava/no-async-fn-without-await": "error", + "ava/no-async-fn-without-await": "error", // Ensure no test.cb() is used. - // In recommended - // "ava/no-cb-test": "off", + "ava/no-cb-test": "off", // Ensure tests do not have duplicate modifiers. - // In recommended - // "ava/no-duplicate-modifiers": "error", + "ava/no-duplicate-modifiers": "error", // Ensure no tests have the same title. - // In recommended - // "ava/no-identical-title": "error", + "ava/no-identical-title": "error", // Ensure no tests are written in ignored files. - // In recommended - // "ava/no-ignored-test-files": "error", + "ava/no-ignored-test-files": "error", // Ensure no test files are imported anywhere - // In recommended - // "ava/no-import-test-files": "error", + "ava/no-import-test-files": "error", // Ensure t.end() is only called inside test.cb(). - // In recommended - // "ava/no-invalid-end": "error", + "ava/no-invalid-end": "error", // Ensure no tests are nested. - // In recommended - // "ava/no-nested-tests": "error", + "ava/no-nested-tests": "error", // Ensure no test.only() are present. - // In recommended - // "ava/no-only-test": "error", + "ava/no-only-test": "error", // Ensure no assertions are skipped. - // In recommended - // "ava/no-skip-assert": "error", + "ava/no-skip-assert": "error", // Ensure no tests are skipped. - // In recommended - // "ava/no-skip-test": "error", + "ava/no-skip-test": "error", // Ensure t.end() is the last statement executed. - // In recommended - // "ava/no-statement-after-end": "error", + "ava/no-statement-after-end": "error", // Ensure test.todo() is not given an implementation function. - // In recommended - // "ava/no-todo-implementation": "error", - /* eslint-enable */ + "ava/no-todo-implementation": "error", // Ensure no test.todo() is used. - /* eslint-enable */ - "ava/no-todo-test": "error" + "ava/no-todo-test": "error", // Prevent the use of unknown test modifiers. - // In recommended - // "ava/no-unknown-modifiers": "error", + "ava/no-unknown-modifiers": "error", // Prefer using async/await instead of returning a Promise. - // In recommended - // "ava/prefer-async-await": "off", + // In `recommended` it is `error`, we need activate this in next major + // for `jest` too + "ava/prefer-async-await": "off", // Allow only use of the asserts that have no power-assert alternative. - // In recommended - // "ava/prefer-power-assert": "off", + "ava/prefer-power-assert": "off", // Ensure callback tests are explicitly ended. - // In recommended - // "ava/test-ended": "error", + "ava/test-ended": "error", // Ensure tests have a title. - // In recommended - // "ava/test-title": ["error", "if-multiple"], + "ava/test-title": ["error", "if-multiple"], // Prevent the incorrect use of t. - // In recommended - // "ava/use-t-well": "error", + "ava/use-t-well": "error", // Ensure test functions use t as their parameter. - // In recommended - // "ava/use-t": "error", + "ava/use-t": "error", // Ensure that AVA is imported with test as the variable name. - // In recommended - // "ava/use-test": "error", + "ava/use-test": "error", // Ensure that t.true()/t.false() are used instead of t.truthy()/t.falsy(). - // In recommended - // "ava/use-true-false": "error" + "ava/use-true-false": "error" }; diff --git a/lib/config/rules/best-practices.js b/lib/config/rules/best-practices.js index c05f65a..d3d9267 100644 --- a/lib/config/rules/best-practices.js +++ b/lib/config/rules/best-practices.js @@ -55,8 +55,7 @@ module.exports = { // Disallow use of arguments.caller or arguments.callee "no-caller": "error", // disallow lexical declarations in case clauses - // In recommended - // "no-case-declarations": "error", + "no-case-declarations": "error", // Disallow division operators explicitly at beginning of regular expression "no-div-regex": "error", // Disallow else after a return in an if @@ -64,8 +63,7 @@ module.exports = { // Disallow use of empty functions "no-empty-function": "error", // Disallow use of empty destructuring patterns - // In recommended - // "no-empty-pattern": "error", + "no-empty-pattern": "error", // Disallow comparisons to null without a type-checking operator "no-eq-null": "error", // Disallow use of eval() @@ -77,13 +75,11 @@ module.exports = { // Disallow unnecessary labels "no-extra-label": "error", // Disallow fallthrough of case statements - // In recommended - // "no-fallthrough": "error", + "no-fallthrough": "error", // Disallow the use of leading or trailing decimal points in numeric literals "no-floating-decimal": "off", // Disallow assignments to native objects or read-only global variables - // In recommended - // "no-global-assign": "error", + "no-global-assign": "error", // Disallow the type conversions with shorter notations "no-implicit-coercion": [ "error", @@ -130,8 +126,7 @@ module.exports = { // Disallow use of octal escape sequences in string literals, such as var foo = 'Copyright \251'; "no-octal-escape": "error", // Disallow use of octal literals - // In recommended - // "no-octal": "error", + "no-octal": "error", // Allow reassignment of function parameters "no-param-reassign": [ "error", @@ -142,8 +137,7 @@ module.exports = { // Disallow usage of __proto__ property "no-proto": "error", // Disallow declaring the same variable more than once - // In recommended - // "no-redeclare": ["error"], + "no-redeclare": ["error"], // Disallow use of assignment in return statement "no-return-assign": ["error", "always"], // Disallows unnecessary return await @@ -151,7 +145,6 @@ module.exports = { // Disallow use of javascript: urls., "no-script-url": "error", // Disallow assignments where both sides are exactly the same - // In recommended "no-self-assign": ["error"], // Disallow comparisons where both sides are exactly the same "no-self-compare": "error", @@ -171,15 +164,13 @@ module.exports = { } ], // Disallow unused labels - // In recommended - // "no-unused-labels": "error", + "no-unused-labels": "error", // Disallow unnecessary .call() and .apply() "no-useless-call": "error", // Disallow unnecessary concatenation of literals or template literals "no-useless-concat": "error", // Disallow unnecessary usage of escape character - // In recommended - // "no-useless-escape": "error", + "no-useless-escape": "error", // Disallow redundant return statements "no-useless-return": "error", // Disallow use of `void` operator diff --git a/lib/config/rules/deprecated.js b/lib/config/rules/deprecated.js index d8fca13..fbf7bda 100644 --- a/lib/config/rules/deprecated.js +++ b/lib/config/rules/deprecated.js @@ -7,8 +7,11 @@ module.exports = { "lines-around-directive": "off", "newline-after-var": "off", "newline-before-return": "off", + "no-catch-shadow": "off", "no-native-reassign": "off", "no-negated-in-lhs": "off", "no-spaced-func": "off", - "prefer-reflect": "off" + "prefer-reflect": "off", + "require-jsdoc": "off", + "valid-jsdoc": "off" }; diff --git a/lib/config/rules/ecmascript-6.js b/lib/config/rules/ecmascript-6.js index 65163e6..85c17fd 100644 --- a/lib/config/rules/ecmascript-6.js +++ b/lib/config/rules/ecmascript-6.js @@ -16,32 +16,26 @@ module.exports = { // Require space before/after arrow function's arrow "arrow-spacing": "off", // Verify super() callings in constructors - // In recommended - // "constructor-super": "error", + "constructor-super": "error", // Enforce the spacing around the * in generator functions "generator-star-spacing": "off", // Disallow modifying variables of class declarations - // In recommended - // "no-class-assign": "error", + "no-class-assign": "error", // Disallow arrow functions where they could be confused with comparisons "no-confusing-arrow": "off", // Disallow modifying variables that are declared using const - // In recommended - // "no-const-assign": "error", + "no-const-assign": "error", // Disallow duplicate name in class members - // In recommended - // "no-dupe-class-members": "error", + "no-dupe-class-members": "error", // Disallow duplicate module imports // Replaced by https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md "no-duplicate-imports": "off", // Disallow use of the new operator with the Symbol object - // In recommended - // "no-new-symbol": "error", + "no-new-symbol": "error", // Restrict usage of specified node imports "no-restricted-imports": "off", // Disallow to use this/super before super() calling in constructors. - // In recommended - // "no-this-before-super": "error", + "no-this-before-super": "error", // Disallow unnecessary computed property keys in object literals "no-useless-computed-key": "error", // Disallow unnecessary constructor @@ -101,13 +95,11 @@ module.exports = { // Suggest using template literals instead of strings concatenation "prefer-template": "error", // Disallow generator functions that do not have yield - // In recommended - // "require-yield": "error", + "require-yield": "error", // Enforce spacing between rest and spread operators and their expressions "rest-spread-spacing": "off", // Enforce sorted import declarations within modules - // In recommended - // "sort-imports": ["off"], + "sort-imports": "off", // Require symbol descriptions "symbol-description": "error", // Enforce spacing around embedded expressions of template strings diff --git a/lib/config/rules/import.js b/lib/config/rules/import.js index 522c7eb..a280617 100644 --- a/lib/config/rules/import.js +++ b/lib/config/rules/import.js @@ -11,14 +11,11 @@ module.exports = { { amd: true, commonjs: true, caseSensitive: true } ], // Ensure named imports correspond to a named export in the remote file. - // In recommended - // "import/named": "error", + "import/named": "error", // Ensure a default export is present, given a default import. - // In recommended - // "import/default": "error", + "import/default": "error", // Ensure imported namespaces contain dereferenced properties as they are dereferenced. - // In recommended - // "import/namespace": "error", + "import/namespace": "error", // Restrict which files can be imported in a given folder "import/no-restricted-paths": "off", // Forbid import of modules using absolute paths @@ -39,8 +36,7 @@ module.exports = { // Helpful warnings // Report any invalid exports, i.e. re-export of the same name - // In recommended - // "import/export": "error", + "import/export": "error", // Report use of exported name as identifier of default export "import/no-named-as-default": "error", // Report use of exported name as property of default export @@ -83,6 +79,7 @@ module.exports = { "error", "always", { + mjs: "never", js: "never", jsx: "never" } diff --git a/lib/config/rules/jest.js b/lib/config/rules/jest.js index f4d4d65..095b63f 100644 --- a/lib/config/rules/jest.js +++ b/lib/config/rules/jest.js @@ -14,25 +14,21 @@ module.exports = { // Disallow disabled tests "jest/no-disabled-tests": "error", // Disallow focused tests - // In recommended - // "jest/no-focused-tests": "error", + "jest/no-focused-tests": "error", // Disallow setup and teardown hooks "jest/no-hooks": "off", // Disallow identical titles - // In recommended - // "jest/no-identical-title": "error", + "jest/no-identical-title": "error", // Disallow Jasmine globals "jest/no-jasmine-globals": "error", // Disallow importing `jest` - // In recommended - // "jest/no-jest-import": "error", + "jest/no-jest-import": "error", // Disallow large snapshots "jest/no-large-snapshots": "off", // Using a callback in asynchronous tests "jest/no-test-callback": "off", // Disallow using `f` & `x` prefixes to define focused/skipped tests - // In recommended - // "jest/no-test-prefixes": "error", + "jest/no-test-prefixes": "error", // Disallow explicitly returning from tests "jest/no-test-return-statement": "off", // Disallow using `toBeTruthy()` & `toBeFalsy()` @@ -44,28 +40,21 @@ module.exports = { // Suggest using `toStrictEqual()` "jest/prefer-strict-equal": "off", // Suggest using `toBeNull()` - // In recommended - // "jest/prefer-to-be-null": "error", + "jest/prefer-to-be-null": "error", // Suggest using `toBeUndefined()` - // In recommended - // "jest/prefer-to-be-undefined": "error", + "jest/prefer-to-be-undefined": "error", // Suggest using `toContain()` - // In recommended - // "jest/prefer-to-contain": "error", + "jest/prefer-to-contain": "error", // Suggest using `toHaveLength()` - // In recommended - // "jest/prefer-to-have-length": "error", + "jest/prefer-to-have-length": "error", // Suggest using `toMatchInlineSnapshot()` "jest/prefer-inline-snapshots": "off", // Require that `toThrow()` and `toThrowError()` includes a message - "jest/require-tothrow-message": "error" + "jest/require-tothrow-message": "error", // Enforce valid `describe()` callback - // In recommended - // "jest/valid-describe": "error", + "jest/valid-describe": "error", // Enforce having return statement when testing with promises - // In recommended - // "jest/valid-expect-in-promise": "error", + "jest/valid-expect-in-promise": "error", // Enforce valid `expect()` usage - // In recommended - // "jest/valid-expect": "error" + "jest/valid-expect": "error" }; diff --git a/lib/config/rules/jsx-a11y.js b/lib/config/rules/jsx-a11y.js index 3cbe249..7f4bd81 100644 --- a/lib/config/rules/jsx-a11y.js +++ b/lib/config/rules/jsx-a11y.js @@ -4,190 +4,200 @@ module.exports = { // Enforce emojis are wrapped in and provide screenreader access. - // In recommended - // "jsx-a11y/accessible-emoji": "error", + "jsx-a11y/accessible-emoji": "error", // Enforce all elements that require alternative text have meaningful information to relay back to end user. - // In recommended - // "jsx-a11y/alt-text": "error", + "jsx-a11y/alt-text": [ + "error", + { + elements: ["img", "object", "area", 'input[type="image"]'], + img: [], + object: [], + area: [], + 'input[type="image"]': [] + } + ], + // Enforce all anchors to contain accessible content. - // In recommended - // "jsx-a11y/anchor-has-content": "error", + "jsx-a11y/anchor-has-content": ["error", { components: [] }], // Enforce all anchors are valid, navigable elements. - // In recommended - // "jsx-a11y/anchor-is-valid": "error", + "jsx-a11y/anchor-is-valid": [ + "error", + { + components: ["Link"], + specialLink: ["to"], + aspects: ["noHref", "invalidHref", "preferButton"] + } + ], // Enforce elements with aria-activedescendant are tabbable. - // In recommended - // "jsx-a11y/aria-activedescendant-has-tabindex": "error", + "jsx-a11y/aria-activedescendant-has-tabindex": "error", // Enforce all aria-* props are valid. - // In recommended - // "jsx-a11y/aria-props": "error", + "jsx-a11y/aria-props": "error", // Enforce ARIA state and property values are valid. - // In recommended - // "jsx-a11y/aria-proptypes": "error", + "jsx-a11y/aria-proptypes": "error", // Enforce that elements with ARIA roles must use a valid, non-abstract ARIA role. - // In recommended - // "jsx-a11y/aria-role": "error", + "jsx-a11y/aria-role": ["error", { ignoreNonDom: false }], // Enforce that elements that do not support ARIA roles, states, and properties do not have those attributes. - // In recommended - // "jsx-a11y/aria-unsupported-elements": "error", + "jsx-a11y/aria-unsupported-elements": "error", // Enforce a clickable non-interactive element has at least one keyboard event listener. - // In recommended - // "jsx-a11y/click-events-have-key-events": "error", + "jsx-a11y/click-events-have-key-events": "error", // Enforce heading (h1, h2, etc) elements contain accessible content. - // In recommended - // "jsx-a11y/heading-has-content": "error", + "jsx-a11y/heading-has-content": ["error", { components: [] }], // Enforce an anchor element's href prop value is not just #. - // In recommended - // "jsx-a11y/href-no-hash": "off", + "jsx-a11y/href-no-hash": "off", // Enforce element has lang prop. - // In recommended - // "jsx-a11y/html-has-lang": "error", + "jsx-a11y/html-has-lang": "error", // Enforce iframe elements have a title attribute. - // In recommended - // "jsx-a11y/iframe-has-title": "error", + "jsx-a11y/iframe-has-title": "error", // Enforce alt prop does not contain the word "image", "picture", or "photo". - // In recommended - // "jsx-a11y/img-redundant-alt": "error", + "jsx-a11y/img-redundant-alt": "error", // Elements with an interactive role and interaction handlers (mouse or key press) must be focusable. - // In recommended - // "jsx-a11y/interactive-supports-focus": [ - // "error", - // { - // tabbable: [ - // 'button', - // 'checkbox', - // 'link', - // 'progressbar', - // 'searchbox', - // 'slider', - // 'spinbutton', - // 'switch', - // 'textbox' - // ] - // } - // ], + "jsx-a11y/interactive-supports-focus": [ + "error", + { + tabbable: [ + "button", + "checkbox", + "link", + "searchbox", + "spinbutton", + "switch", + "textbox" + ] + } + ], // Enforce that