const path = require( 'path' ); const { nodeConfig } = require( '@automattic/calypso-eslint-overrides' ); const { merge } = require( 'lodash' ); const reactVersion = require( './client/package.json' ).dependencies.react; module.exports = { root: true, parserOptions: { babelOptions: { configFile: path.join( __dirname, './babel.config.js' ), }, }, extends: [ 'plugin:wpcalypso/react', 'plugin:jsx-a11y/recommended', 'plugin:jest/recommended', 'plugin:prettier/recommended', 'plugin:md/prettier', 'plugin:@wordpress/eslint-plugin/i18n', ], overrides: [ { // Nothing to override for these files. This is here so eslint also checks for `.jsx` files by default files: [ '**/*.jsx' ], }, { files: [ '*.md' ], parser: 'markdown-eslint-parser', rules: { 'md/remark': [ 'error', { plugins: [ // This is the original ruleset from `plugin:md/prettier`. // We need to include it again because eslint doesn't compose overrides ...require( 'eslint-plugin-md' ).configs.prettier.rules[ 'md/remark' ][ 1 ].plugins, // Disabled because they don't make a lot of sense or they are buggy [ 'lint-maximum-heading-length', false ], [ 'lint-no-duplicate-headings', false ], // Rules we would like to enable eventually. Violations needs to be fixed manually before enabling the rule. [ 'lint-fenced-code-flag', false ], // This special plugin is used to allow the syntax . It has to come last. [ 'message-control', { name: 'eslint', source: 'remark-lint' } ], ], }, ], }, }, { files: [ 'packages/**/*' ], rules: { // These two rules are to ensure packages don't import from calypso by accident to avoid circular deps. 'no-restricted-imports': [ 'error', { patterns: [ 'calypso/*' ] } ], 'no-restricted-modules': [ 'error', { patterns: [ 'calypso/*' ] } ], }, }, { files: [ 'bin/**/*', 'test/**/*' ], ...nodeConfig, }, merge( // ESLint doesn't allow the `extends` field inside `overrides`, so we need to compose // the TypeScript config manually using internal bits from various plugins {}, // base TypeScript config: parser options, add plugin with rules require( '@typescript-eslint/eslint-plugin' ).configs.base, // basic recommended rules config from the TypeScript plugin { rules: require( '@typescript-eslint/eslint-plugin' ).configs.recommended.rules }, // disables rules that are already checked by the TypeScript compiler // see https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin/src/configs#eslint-recommended { rules: require( '@typescript-eslint/eslint-plugin' ).configs[ 'eslint-recommended' ] .overrides[ 0 ].rules, }, // Prettier rules config require( 'eslint-config-prettier' ), // Our own overrides { files: [ '**/*.ts', '**/*.tsx' ], rules: { // Disable vanilla eslint rules that have a Typescript implementation // See https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/README.md#extension-rules 'brace-style': 'off', 'comma-dangle': 'off', 'comma-spacing': 'off', 'default-param-last': 'off', 'dot-notation': 'off', 'func-call-spacing': 'off', indent: 'off', 'init-declarations': 'off', 'keyword-spacing': 'off', 'lines-between-class-members': 'off', 'no-array-constructor': 'off', 'no-dupe-class-members': 'off', 'no-duplicate-imports': 'off', 'no-empty-function': 'off', 'no-extra-parens': 'off', 'no-extra-semi': 'off', 'no-invalid-this': 'off', 'no-loop-func': 'off', 'no-loss-of-precision': 'off', 'no-magic-numbers': 'off', 'no-redeclare': 'off', 'no-shadow': 'off', 'no-unused-expressions': 'off', 'no-unused-vars': 'off', 'no-use-before-define': 'off', 'no-useless-constructor': 'off', quotes: 'off', 'require-await': 'off', 'return-await': 'off', semi: 'off', 'space-before-function-paren': 'off', '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-member-accessibility': 'off', '@typescript-eslint/no-unused-vars': [ 'error', { ignoreRestSiblings: true } ], '@typescript-eslint/no-use-before-define': [ 'error', { functions: false, typedefs: false }, ], '@typescript-eslint/no-var-requires': 'off', // REST API objects include underscores '@typescript-eslint/camelcase': 'off', // TypeScript compiler already takes care of these errors 'import/no-extraneous-dependencies': 'off', 'import/named': 'off', 'import/namespace': 'off', 'import/default': 'off', }, } ), { // This lints the codeblocks marked as `javascript`, `js`, `cjs` or `ejs`, all valid aliases // See: // eslint-disable-next-line inclusive-language/use-inclusive-words // * https://github.com/highlightjs/highlight.js/blob/master/SUPPORTED_LANGUAGES.md) // * https://www.npmjs.com/package/eslint-plugin-md#modifying-eslint-setup-for-js-code-inside-md-files files: [ '*.md.js', '*.md.javascript', '*.md.cjs', '*.md.ejs', '*.md.jsx', '*.md.tsx', '*.md.ts', ], rules: { // These are ok for examples 'import/no-extraneous-dependencies': 'off', 'jest/expect-expect': 'off', 'jest/no-focused-tests': 'off', 'jest/no-standalone-expect': 'off', 'jsdoc/require-param-description': 'off', 'no-console': 'off', 'no-redeclare': 'off', 'no-restricted-imports': 'off', 'no-undef': 'off', 'no-unused-vars': 'off', 'react/jsx-no-undef': 'off', 'react/jsx-uses-react': 'off', 'react/react-in-jsx-scope': 'off', 'wpcalypso/jsx-classname-namespace': 'off', '@typescript-eslint/no-unused-vars': 'off', 'jsdoc/require-param': 'off', 'jsdoc/check-param-names': 'off', '@typescript-eslint/no-empty-function': 'off', 'prettier/prettier': [ 'error', { parser: 'babel' } ], }, }, ], env: { jest: true, // mocha is only still on because we have not finished porting all of our tests to jest's syntax mocha: true, node: true, }, globals: { // allow the browser globals. ESLint's `browser` env is too permissive and allows referencing // directly hundreds of properties that are available on `window` and `document`. That // frequently caused bugs where we used an undefined variable and ESLint didn't warn us. globalThis: true, window: true, document: true, // this is our custom function that's transformed by babel into either a dynamic import or a normal require asyncRequire: true, // this is the SHA of the current commit. Injected at boot in a script tag. COMMIT_SHA: true, // this is when Webpack last built the bundle BUILD_TIMESTAMP: true, }, plugins: [ 'import', 'you-dont-need-lodash-underscore' ], settings: { react: { version: reactVersion, }, jsdoc: { mode: 'typescript', }, 'import/internal-regex': '^calypso/', }, rules: { // REST API objects include underscores camelcase: 'off', 'no-constant-condition': [ 'error', { checkLoops: false } ], 'no-path-concat': 'error', 'one-var': [ 'error', 'never' ], // TODO: why did we turn this off? 'jest/valid-expect': 'off', 'jest/expect-expect': [ 'error', { assertFunctionNames: [ // Jest 'expect', // Chai 'chai.assert', 'chai.assert.*', 'assert', 'assert.*', 'equal', 'ok', 'deepStrictEqual', 'chaiExpect', // Sinon 'sinon.assert.*', ], }, ], // Only use known tag names plus `jest-environment`. 'jsdoc/check-tag-names': [ 'error', { definedTags: [ 'jest-environment', 'jsxImportSource' ] }, ], // Do not require param/return description, see https://github.com/Automattic/wp-calypso/issues/56330 'jsdoc/require-param-description': 'off', 'jsdoc/require-param': 'off', 'jsdoc/require-returns-description': 'off', // Deprecated rule, fails in some valid cases with custom input components 'jsx-a11y/label-has-for': 'off', // i18n-calypso translate triggers false failures 'jsx-a11y/anchor-has-content': 'off', // Deprecated rule, the problems using