├── .editorconfig ├── .eslintrc ├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── .ncurc ├── .npmignore ├── .npmrc ├── .prettierignore ├── .prettierrc ├── .snyk ├── LICENSE ├── README.md ├── configs.js ├── docs ├── typescript.md └── vue.md ├── index.js ├── lib ├── is-module-available.js ├── loaded.js ├── loggers.js ├── missing.js └── utils.js ├── package.json └── rules ├── array-func.js ├── ava.js ├── chai-expect.js ├── chai-friendly.js ├── const-case.js ├── cypress.js ├── eslint-comments.js ├── fsa.js ├── html.js ├── jasmine.js ├── jest-async.js ├── jest-dom.js ├── jest.js ├── json-format.js ├── json.js ├── lodash-fp.js ├── lodash.js ├── markdown.js ├── mocha-cleanup.js ├── mocha.js ├── no-constructor-bind.js ├── no-secrets.js ├── no-unsanitized.js ├── no-use-extend-native.js ├── optimize-regex.js ├── pii.js ├── prettier.js ├── promise.js ├── qunit.js ├── ramda.js ├── react-redux.js ├── redux-saga.js ├── security.js ├── simple-import-sort.js ├── sonarjs.js ├── switch-case.js ├── test-overrides.js ├── testing-library.js ├── unicorn.js └── xss.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | # editorconfig-tools is unable to ignore longs strings or urls 9 | max_line_length = null 10 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["airbnb", "./index.js"], 3 | "rules": { 4 | "security/detect-non-literal-fs-filename": 0, 5 | "unicorn/prevent-abbreviations": 0, 6 | "unicorn/prefer-module": 0, 7 | "unicorn/prefer-node-protocol": 0 8 | }, 9 | "env": { 10 | "es6": true, 11 | "node": true 12 | }, 13 | "parserOptions": { 14 | "ecmaVersion": 6, 15 | "sourceType": "module", 16 | "ecmaFeatures": { 17 | "generators": false, 18 | "objectLiteralDuplicateProperties": false 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.js text eol=lf -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | # github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | # patreon: # Replace with a single Patreon username 5 | # open_collective: # Replace with a single Open Collective username 6 | # ko_fi: # Replace with a single Ko-fi username 7 | # tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | # community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | # liberapay: # Replace with a single Liberapay username 10 | # issuehunt: # Replace with a single IssueHunt username 11 | # otechie: # Replace with a single Otechie username 12 | # custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | 14 | github: davidjbradshaw 15 | custom: ['https://www.buymeacoffee.com/davidjbradshaw'] 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | -------------------------------------------------------------------------------- /.ncurc: -------------------------------------------------------------------------------- 1 | { 2 | "reject": ["arrify","read-pkg-up"] 3 | } 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .coveralls.yml 3 | .idea 4 | node_modules 5 | bin 6 | docs 7 | example 8 | test 9 | spec 10 | src 11 | npm-debug.log 12 | bower_components 13 | bower.json 14 | gruntfile.js 15 | karma.conf.js 16 | test-main.js 17 | coverage* 18 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | package.json 2 | node_modules 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": false, 6 | "singleQuote": true, 7 | "trailingComma": "es5", 8 | "bracketSpacing": true, 9 | "jsxBracketSameLine": false 10 | } 11 | -------------------------------------------------------------------------------- /.snyk: -------------------------------------------------------------------------------- 1 | # Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. 2 | version: v1.14.1 3 | ignore: {} 4 | # patches apply the minimum changes required to fix a vulnerability 5 | patch: 6 | SNYK-JS-LODASH-567746: 7 | - lodash: 8 | patched: '2020-06-06T17:07:42.550Z' 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 - 2020 David J. Bradshaw 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | # eslint-config-adjunct 5 | _A reasonable collection of *plugins* to use alongside your main esLint configuration_ 6 |
7 | 8 | This config is designed to be used alongside any of the major esLint configs, such as [airbnb](https://github.com/airbnb/javascript), [standard](https://github.com/standard/eslint-config-standard) or [eslint:recommended](https://eslint.org/docs/rules/). It provides a range of useful plugins that are often too time-consuming to setup and provides an easy way to install just the plugins you need, based on your project's dependencies. 9 | 10 | ## Install 11 | 12 | To install this config, run the following command. 13 | 14 | ```sh 15 | npm install eslint-config-adjunct --save-dev 16 | ``` 17 | 18 | ## Configure 19 | 20 | Extend your `.eslintrc`, with `adjunct`, which should be the last item in the `extends` array. For example if your using `eslint-config-airbnb` as your main rule set, your `.eslintrc` should look like the following. For more advanced use cases see the example configurations for [TypeScript](https://github.com/davidjbradshaw/eslint-config-adjunct/blob/master/docs/typescript.md) and [Vue](https://github.com/davidjbradshaw/eslint-config-adjunct/blob/master/docs/vue.md). 21 | 22 | ```json 23 | { 24 | "extends": ["airbnb", "adjunct"] 25 | } 26 | ``` 27 | 28 | You can now include `html`, `json` and `markdown` in the list of files passed to `eslint` to lint any JavaScript contained. 29 | 30 | ```json 31 | { 32 | "scripts": { 33 | "eslint": "eslint --color --ext .html,.js,.json,.jsx,.md *.* src", 34 | "eslint:fix": "npm run eslint -- --fix" 35 | } 36 | } 37 | ``` 38 | 39 | ## Install Dependencies 40 | 41 | After you have configured `eslint` to include this package, the first time you run `eslint` it will output the `npm` command to install the dependencies required for your project. Cut'n'paste this command into the console, and you are then ready to start linting. 42 | 43 | ## Plugins 44 | 45 | ### Code Quality 46 | 47 | These two plugins provide a range of code quality rules: 48 | 49 | - [eslint-plugin-sonarjs](https://github.com/SonarSource/eslint-plugin-sonarjs) 50 | - [eslint-plugin-unicorn](https://github.com/sindresorhus/eslint-plugin-unicorn) 51 | 52 | ### Langauges 53 | 54 | The following plugins expand esLint to work with json files, and lint JavaScript contiained in HTML and MarkDown: 55 | 56 | - [eslint-plugin-html](https://github.com/BenoitZugmeyer/eslint-plugin-html) 57 | - [eslint-plugin-json](https://github.com/azeemba/eslint-plugin-json) 58 | - [eslint-plugin-markdown](https://github.com/eslint/eslint-plugin-markdown) 59 | 60 | _When linting code snippets in Markdown files, a few [rules](https://github.com/davidjbradshaw/eslint-config-adjunct/blob/master/rules/markdown.js#L3) relating to globals and unused vars are disabled._ 61 | 62 | ### Library Plugins 63 | 64 | These plugins will be loaded in based on your project `dependencies` in `package.json`. If a supported library is part of your project then it's related esLint plugins will be loaded. The following packages are supported: 65 | 66 | - [eslint-plugin-fsa](https://github.com/joseph-galindo/eslint-plugin-fsa) 67 | - [eslint-plugin-lodash](https://github.com/wix/eslint-plugin-lodash) 68 | - [eslint-plugin-lodash-fp](https://github.com/jfmengels/eslint-plugin-lodash-fp) 69 | - [eslint-plugin-ramda](https://github.com/ramda/eslint-plugin-ramda) 70 | - [eslint-plugin-react-redux](https://github.com/DianaSuvorova/eslint-plugin-react-redux#readme) 71 | - [eslint-plugin-redux-saga](https://github.com/pke/eslint-plugin-redux-saga) 72 | 73 | ### Practices 74 | 75 | The following esLint plugins enforce good coding practices: 76 | 77 | - [eslint-plugin-const-case](https://github.com/k03mad/eslint-plugin-const-case#readme) 78 | - [eslint-plugin-array-func](https://github.com/freaktechnik/eslint-plugin-array-func) 79 | - [eslint-plugin-eslint-comments](https://github.com/mysticatea/eslint-plugin-eslint-comments) 80 | - [eslint-plugin-no-constructor-bind](https://github.com/markalfred/eslint-plugin-no-constructor-bind) 81 | - [eslint-plugin-no-use-extend-native](https://github.com/dustinspecker/eslint-plugin-no-use-extend-native) 82 | - [eslint-plugin-optimize-regex](https://github.com/BrainMaestro/eslint-plugin-optimize-regex) 83 | - [eslint-plugin-promise](https://github.com/xjamundx/eslint-plugin-promise) 84 | - [eslint-plugin-simple-import-sort](https://github.com/lydell/eslint-plugin-simple-import-sort) 85 | - [eslint-plugin-switch-case](https://github.com/lukeapage/eslint-plugin-switch-case) 86 | 87 | ### Prettier 88 | 89 | If prettier is installed, any rules that may conflict with Prettier will be disabled. The plugin should read you Prettier config from your project's root. 90 | 91 | - [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) 92 | 93 | The prettier configs for different eslint plugins are also automatically included based on which eslint plugins have been installed into your project. 94 | 95 | ### Security 96 | 97 | These plugins add code security rules to esLint: 98 | 99 | - [eslint-plugin-no-secrets](https://github.com/nickdeis/eslint-plugin-no-secrets) 100 | - [eslint-plugin-no-unsanitized](https://github.com/mozilla/eslint-plugin-no-unsanitized) 101 | - [eslint-plugin-pii](https://github.com/shiva-hack/eslint-plugin-pii) 102 | - [eslint-plugin-security](https://github.com/nodesecurity/eslint-plugin-security) 103 | - [eslint-plugin-xss](https://github.com/Rantanen/eslint-plugin-xss) 104 | 105 | ### Test Libraries 106 | 107 | Test plugins are loaded based on which testing tools you have listed in `devDependencies` of `package.json`. The following test plugins are supported: 108 | 109 | - [eslint-plugin-ava](https://github.com/avajs/eslint-plugin-ava) 110 | - [eslint-plugin-chai-expect](https://github.com/turbo87/eslint-plugin-chai-expect) 111 | - [eslint-plugin-chai-friendly](https://github.com/ihordiachenko/eslint-plugin-chai-friendly) 112 | - [eslint-plugin-cypress](https://github.com/cypress-io/eslint-plugin-cypress) 113 | - [eslint-plugin-jasmine](https://github.com/tlvince/eslint-plugin-jasmine) 114 | - [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) 115 | - [eslint-plugin-jest-async](https://www.npmjs.com/package/eslint-plugin-jest-async) 116 | - [eslint-plugin-mocha](https://github.com/lo1tuma/eslint-plugin-mocha) 117 | - [eslint-plugin-mocha-cleanup](https://github.com/onechiporenko/eslint-plugin-mocha-cleanup/) 118 | - [eslint-plugin-qunit](https://github.com/platinumazure/eslint-plugin-qunit) 119 | - [eslint-plugin-testing-library](https://github.com/testing-library/eslint-plugin-testing-library) 120 | 121 | _For test files a few [rules](https://github.com/davidjbradshaw/eslint-config-adjunct/blob/master/rules/test-overrides.js) are turned off, to better to support normal unit test code styles._ 122 | 123 | ## Rules 124 | 125 | In the most part the default rules are used for the plugins listed above, with the following exceptions. 126 | 127 | ### Switch-Case 128 | 129 | Adds the `fallthrough: 'never'` option to the `newline-between-switch-case` rule. 130 | 131 | ```js 132 | // Good 133 | 134 | switch (foo) { 135 | case 1: 136 | something() 137 | break 138 | 139 | case 2: 140 | case 3: 141 | somethingElse() 142 | break 143 | 144 | default: 145 | defaultThing() 146 | } 147 | ``` 148 | 149 | ### Disabled rules 150 | 151 | The following rules are disabled due to them being considered unduly restrictive or unhelpful. 152 | 153 | - jest/no-disabled-tests 154 | - react-redux/prefer-separate-component-file 155 | - redux-saga/no-unhandled-errors 156 | - lodash/prefer over native rules 157 | - lodash-fp/use-fp 158 | - unicorn/no-array-for-each 159 | - unicorn/no-fn-reference-in-iterator 160 | - unicorn/no-array-for-each 161 | - unicorn/no-reduce 162 | - unicorn/no-null 163 | - unicorn/prefer-number-properties 164 | - unicorn/prefer-optional-catch-binding 165 | - unicorn/prevent-abbreviations 166 | 167 | The following rules are disabled due to clashing with other plugins 168 | 169 | - array-func/prefer-array-from 170 | - import/order 171 | - sort-imports 172 | 173 | ## License 174 | 175 | Copyright © 2019-21 [David J. Bradshaw](https://github.com/davidjbradshaw). 176 | Licensed under the [MIT License](LICENSE). 177 | -------------------------------------------------------------------------------- /configs.js: -------------------------------------------------------------------------------- 1 | const { hasAnyDep } = require('./lib/utils') 2 | const isModuleAvailable = require('./lib/is-module-available') 3 | 4 | // Base rules 5 | const rules = [ 6 | // 'array-func', 7 | 'const-case', 8 | 'eslint-comments', 9 | 'html', 10 | 'json', 11 | // 'json-format', 12 | 'markdown', 13 | 'no-constructor-bind', 14 | 'no-use-extend-native', 15 | 'optimize-regex', 16 | 'promise', 17 | 'simple-import-sort', 18 | 'sonarjs', 19 | 'switch-case', 20 | 'unicorn', 21 | 22 | // Security Rules 23 | 'no-secrets', 24 | 'no-unsanitized', 25 | 'pii', 26 | 'security', 27 | 'xss', 28 | ] 29 | 30 | // Optionals rules besed on project dependencies 31 | const depRules = [ 32 | ['redux', 'fsa'], 33 | 'lodash', 34 | ['lodash', 'lodash-fp'], 35 | 'ramda', 36 | 'react-redux', 37 | 'redux-saga', 38 | ] 39 | 40 | const testRules = [ 41 | 'ava', 42 | ['chai', 'chai-expect'], 43 | ['chai', 'chai-friendly'], 44 | 'cypress', 45 | 'jasmine', 46 | 'jest', 47 | ['jest', 'jest-async'], 48 | 'jest-dom', 49 | ['@testing-library/jest-dom', 'jest-dom'], 50 | 'mocha', 51 | ['mocha', 'mocha-cleanup'], 52 | 'qunit', 53 | ['grunt-contrib-qunit', 'qunit'], 54 | ['@testing-library/dom', 'testing-library'], 55 | ] 56 | 57 | depRules.forEach((depRule) => { 58 | const rule = typeof depRule === 'string' ? [depRule, depRule] : depRule 59 | if (hasAnyDep(rule[0])) rules.push(rule[1]) 60 | }) 61 | 62 | testRules.forEach((depRule) => { 63 | const rule = typeof depRule === 'string' ? [depRule, depRule] : depRule 64 | if (isModuleAvailable(rule[0])) rules.push(rule[1]) 65 | }) 66 | 67 | if (hasAnyDep('prettier')) rules.push('prettier') 68 | 69 | // Extra required optional packages 70 | const extraInstallPackage = [['prettier', 'eslint-config-prettier']] 71 | 72 | module.exports = { rules, extraInstallPackage } 73 | -------------------------------------------------------------------------------- /docs/typescript.md: -------------------------------------------------------------------------------- 1 | ## TypeScript 2 | 3 | All of the packages in _eslint-config-adjuct_ should work with TypeScript. The following is an example config using the AirBnB ruleset with Adjunct and TypeScript-Eslint. 4 | 5 | ```json 6 | { 7 | "extends": [ 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:@typescript-eslint/recommended-requiring-type-checking", 10 | "airbnb-typescript", 11 | "airbnb/hooks", 12 | "adjunct" 13 | ], 14 | "parserOptions": { 15 | "project": "./tsconfig.json" 16 | } 17 | } 18 | ``` 19 | -------------------------------------------------------------------------------- /docs/vue.md: -------------------------------------------------------------------------------- 1 | ## Vue 2 | 3 | Example Vue configuration with AirBnB rules. 4 | 5 | ```js 6 | module.exports = { 7 | root: true, 8 | env: { 9 | node: true, 10 | }, 11 | extends: [ 12 | 'plugin:vue/recommended', 13 | '@vue/airbnb', 14 | '@vue/typescript/recommended', 15 | 'adjunct', 16 | ], 17 | rules: { 18 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 19 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 20 | }, 21 | }; 22 | ``` 23 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const checkMissing = require('./lib/missing') 2 | const showLoaded = require('./lib/loaded') 3 | const { rules, extraInstallPackage } = require('./configs') 4 | 5 | // Workaround VS Code trying to run this file twice! 6 | if (!global.hasAdjunctLoaded) { 7 | checkMissing(rules, extraInstallPackage) 8 | showLoaded(rules, []) 9 | 10 | // Disable some rules in unit tests 11 | rules.push('test-overrides') // eslint-disable-line unicorn/no-array-push-push 12 | global.hasAdjunctLoaded = true 13 | } 14 | 15 | module.exports = { 16 | extends: rules.map((plugin) => 17 | require.resolve(`./rules/${plugin.split('@')[0]}`) 18 | ), 19 | } 20 | -------------------------------------------------------------------------------- /lib/is-module-available.js: -------------------------------------------------------------------------------- 1 | module.exports = function isModuleAvailable(name) { 2 | try { 3 | require.resolve(name) 4 | return true 5 | } catch (error) { 6 | return false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /lib/loaded.js: -------------------------------------------------------------------------------- 1 | const { consoleLog, consolePlugin } = require('./loggers') 2 | const { hasAnyDep } = require('./utils') 3 | 4 | module.exports = function showLoaded(rules, extraInstallPackage) { 5 | const installed = [...rules] 6 | 7 | extraInstallPackage.forEach(([dep, package_]) => { 8 | if (hasAnyDep(dep)) { 9 | installed.push(package_) 10 | } 11 | }) 12 | 13 | consoleLog('\neslint-config-adjunct loaded the following packages:\n') 14 | installed.forEach((plugin) => consolePlugin(plugin)) 15 | } 16 | -------------------------------------------------------------------------------- /lib/loggers.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line unicorn/no-useless-undefined 2 | const noop = () => undefined 3 | 4 | const consolePrefix = (prefix) => 5 | // eslint-disable-next-line no-console 6 | process.env.NO_LOGS ? noop : (file) => console.log(`${prefix}${file}`) 7 | 8 | const consolePlugin = consolePrefix(' eslint-plugin-') 9 | const consoleConfig = consolePrefix(' eslint-config-') 10 | const consoleLog = consolePrefix('') 11 | 12 | module.exports = { 13 | consolePlugin, 14 | consoleConfig, 15 | consoleLog, 16 | } 17 | -------------------------------------------------------------------------------- /lib/missing.js: -------------------------------------------------------------------------------- 1 | const { equals, indexOf, pipe, when } = require('ramda') 2 | 3 | const { hasAnyDep } = require('./utils') 4 | const isModuleAvailable = require('./is-module-available') 5 | const { consoleLog } = require('./loggers') 6 | 7 | const moduleNotAvailable = (pkg) => !isModuleAvailable(pkg.split('@')[0]) 8 | 9 | const atLatest = when(pipe(indexOf('@'), equals(-1)), (pkg) => `${pkg}@latest`) 10 | 11 | module.exports = function checkMissing(rules, extraInstallPackage) { 12 | const notInstalled = rules 13 | .map((plugin) => `eslint-plugin-${plugin}`) 14 | .filter((pkg) => moduleNotAvailable(pkg)) 15 | 16 | extraInstallPackage.forEach(([dep, pkg]) => { 17 | if (hasAnyDep(dep) && moduleNotAvailable(pkg)) { 18 | notInstalled.push(pkg) 19 | } 20 | }) 21 | 22 | if (notInstalled.length === 0) return 23 | 24 | const s = notInstalled.length === 1 ? '' : 's' 25 | 26 | consoleLog(`\nOops! Something went wrong! :( 27 | 28 | EsLint-config-adjunct could not find the following package${s} 29 | 30 | ${notInstalled.join('\n ')} 31 | 32 | To install the missing package${s}, please run the following command: 33 | 34 | npm install ${notInstalled.map((pkg) => atLatest(pkg)).join(' ')} --save-dev 35 | 36 | `) 37 | 38 | process.exit(1) // eslint-disable-line unicorn/no-process-exit 39 | } 40 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | // From kcd-scripts 2 | 3 | const fs = require('fs') 4 | const path = require('path') 5 | const rimraf = require('rimraf') 6 | const mkdirp = require('mkdirp') 7 | const arrify = require('arrify') 8 | const has = require('lodash/has') 9 | const readPkgUp = require('read-pkg-up') 10 | const { cosmiconfigSync } = require('cosmiconfig') 11 | 12 | const { packageJson: package_, path: packagePath } = readPkgUp.sync({ 13 | cwd: fs.realpathSync(process.cwd()), 14 | }) 15 | 16 | const appDirectory = path.dirname(packagePath) 17 | 18 | const fromRoot = (...p) => path.join(appDirectory, ...p) 19 | const hasFile = (...p) => fs.existsSync(fromRoot(...p)) 20 | 21 | const hasPackageProperty = (properties) => 22 | arrify(properties).some((property) => has(package_, property)) // eslint-disable-line lodash-fp/no-extraneous-function-wrapping 23 | 24 | const hasPackageSubProperty = (packageProperty) => (properties) => 25 | hasPackageProperty(arrify(properties).map((p) => `${packageProperty}.${p}`)) 26 | 27 | const hasScript = hasPackageSubProperty('scripts') 28 | const hasPeerDep = hasPackageSubProperty('peerDependencies') 29 | const hasDep = hasPackageSubProperty('dependencies') 30 | const hasDevelopmentDep = hasPackageSubProperty('devDependencies') 31 | const hasAnyDep = (arguments_) => 32 | [hasDep, hasDevelopmentDep, hasPeerDep].some((fn) => fn(arguments_)) 33 | 34 | function environmentIsSet(name) { 35 | return ( 36 | process.env.hasOwnProperty(name) && // eslint-disable-line no-prototype-builtins 37 | process.env[name] && 38 | process.env[name] !== 'undefined' 39 | ) 40 | } 41 | 42 | function parseEnvironment(name, def) { 43 | if (environmentIsSet(name)) { 44 | try { 45 | return JSON.parse(process.env[name]) 46 | } catch (error) { 47 | return process.env[name] 48 | } 49 | } 50 | return def 51 | } 52 | 53 | function uniq(array) { 54 | return [...new Set(array)] 55 | } 56 | 57 | function writeExtraEntry(name, { cjs, esm }, clean = true) { 58 | if (clean) { 59 | rimraf.sync(fromRoot(name)) 60 | } 61 | mkdirp.sync(fromRoot(name)) 62 | 63 | const packageJson = fromRoot(`${name}/package.json`) 64 | const entryDir = fromRoot(name) 65 | 66 | fs.writeFileSync( 67 | packageJson, 68 | JSON.stringify( 69 | { 70 | main: path.relative(entryDir, cjs), 71 | 'jsnext:main': path.relative(entryDir, esm), 72 | module: path.relative(entryDir, esm), 73 | }, 74 | null, 75 | 2 76 | ) 77 | ) 78 | } 79 | 80 | function hasLocalConfig(moduleName, searchOptions = {}) { 81 | const explorerSync = cosmiconfigSync(moduleName, searchOptions) 82 | const result = explorerSync.search(packagePath) 83 | 84 | return result !== null 85 | } 86 | 87 | module.exports = { 88 | appDirectory, 89 | fromRoot, 90 | hasFile, 91 | hasLocalConfig, 92 | hasPkgProp: hasPackageProperty, 93 | hasScript, 94 | hasAnyDep, 95 | parseEnv: parseEnvironment, 96 | pkg: package_, 97 | uniq, 98 | writeExtraEntry, 99 | } 100 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-adjunct", 3 | "version": "4.13.0", 4 | "type": "commonjs", 5 | "author": "David J. Bradshaw", 6 | "license": "MIT", 7 | "description": "A reasonable collection of plugins to use alongside your main esLint configuration", 8 | "funding": { 9 | "type": "github", 10 | "url": "https://github.com/sponsors/davidjbradshaw" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/davidjbradshaw/eslint-config-adjunct.git" 15 | }, 16 | "main": "index.js", 17 | "scripts": { 18 | "ci-test": "npm run test", 19 | "eslint": "eslint --color --ext .html,js,json,jsx,md *.* rules lib docs", 20 | "eslint:fix": "npm run eslint --fix", 21 | "prepublishOnly": "npm run test", 22 | "postpublish": "PACKAGE_VERSION=$(cat package.json | grep \\\"version\\\" | head -1 | awk -F: '{ print $2 }' | sed 's/[\",]//g' | tr -d '[[:space:]]') && git tag v$PACKAGE_VERSION && git push --tags", 23 | "test": "npm run eslint && eslint-find-rules -d --no-core" 24 | }, 25 | "keywords": [ 26 | "airbnb", 27 | "config", 28 | "eslint", 29 | "eslintconfig", 30 | "javascript", 31 | "standard", 32 | "styleguide" 33 | ], 34 | "dependencies": { 35 | "@eslint/eslintrc": "^3.0.1", 36 | "arrify": "^2.0.1", 37 | "cosmiconfig": "^9.0.0", 38 | "lodash": "^4.17.21", 39 | "mkdirp": "^3.0.1", 40 | "path": "^0.12.7", 41 | "ramda": "^0.29.1", 42 | "read-pkg-up": "7.0.1", 43 | "rimraf": "^5.0.5", 44 | "url": "^0.11.3" 45 | }, 46 | "devDependencies": { 47 | "@testing-library/dom": "^9.3.4", 48 | "@testing-library/jest-dom": "^6.4.2", 49 | "@typescript-eslint/eslint-plugin": "^7.0.1", 50 | "ava": "^6.1.1", 51 | "babel-eslint": "^10.1.0", 52 | "chai": "^5.1.0", 53 | "cypress": "^13.6.4", 54 | "eslint": "^8.56.0", 55 | "eslint-config-airbnb": "^19.0.4", 56 | "eslint-config-prettier": "^9.1.0", 57 | "eslint-find-rules": "^4.1.0", 58 | "eslint-plugin-ava": "^14.0.0", 59 | "eslint-plugin-chai-expect": "^3.0.0", 60 | "eslint-plugin-chai-friendly": "^0.7.4", 61 | "eslint-plugin-const-case": "^1.2.2", 62 | "eslint-plugin-cypress": "^2.15.1", 63 | "eslint-plugin-eslint-comments": "^3.2.0", 64 | "eslint-plugin-fsa": "^1.0.12", 65 | "eslint-plugin-html": "^8.0.0", 66 | "eslint-plugin-jasmine": "^4.1.3", 67 | "eslint-plugin-jest": "^27.8.0", 68 | "eslint-plugin-jest-async": "^1.0.3", 69 | "eslint-plugin-jest-dom": "^5.1.0", 70 | "eslint-plugin-json": "^3.1.0", 71 | "eslint-plugin-lodash": "^7.4.0", 72 | "eslint-plugin-lodash-fp": "^2.2.0-a1", 73 | "eslint-plugin-markdown": "^3.0.1", 74 | "eslint-plugin-mocha": "^10.2.0", 75 | "eslint-plugin-mocha-cleanup": "^1.11.3", 76 | "eslint-plugin-no-constructor-bind": "^2.0.4", 77 | "eslint-plugin-no-secrets": "^0.8.9", 78 | "eslint-plugin-no-unsanitized": "^4.0.2", 79 | "eslint-plugin-no-use-extend-native": "^0.5.0", 80 | "eslint-plugin-optimize-regex": "^1.2.1", 81 | "eslint-plugin-pii": "^1.0.2", 82 | "eslint-plugin-prettier": "^5.1.3", 83 | "eslint-plugin-promise": "^6.1.1", 84 | "eslint-plugin-qunit": "^8.1.1", 85 | "eslint-plugin-ramda": "^2.5.1", 86 | "eslint-plugin-react-redux": "^4.1.0", 87 | "eslint-plugin-redux-saga": "^1.3.2", 88 | "eslint-plugin-security": "^2.1.0", 89 | "eslint-plugin-simple-import-sort": "^12.0.0", 90 | "eslint-plugin-sonarjs": "^0.24.0", 91 | "eslint-plugin-switch-case": "^1.1.2", 92 | "eslint-plugin-testing-library": "^6.2.0", 93 | "eslint-plugin-unicorn": "^51.0.1", 94 | "eslint-plugin-xss": "^0.1.12", 95 | "husky": "^9.0.11", 96 | "in-publish": "^2.0.1", 97 | "jasmine": "^5.1.0", 98 | "jest": "^29.7.0", 99 | "jest-dom": "^4.0.0", 100 | "lint-staged": "^15.2.2", 101 | "lodash-fp": "^0.10.4", 102 | "mocha": "^10.3.0", 103 | "prettier": "^3.2.5", 104 | "prettier-cli": "^0.1.0", 105 | "qunit": "^2.20.0", 106 | "react": "^18.2.0", 107 | "react-redux": "^9.1.0", 108 | "redux": "^5.0.1", 109 | "redux-saga": "^1.3.0", 110 | "safe-publish-latest": "^2.0.0", 111 | "snyk": "^1.1279.0", 112 | "testing-library": "0.0.2" 113 | }, 114 | "engines": { 115 | "node": ">= 6.5" 116 | }, 117 | "snyk": false 118 | } 119 | -------------------------------------------------------------------------------- /rules/array-func.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['array-func'], 3 | // extends: ['plugin:array-func/recommended'], 4 | rules: { 5 | // Rule disabled due to clash with Unicorn 6 | 'array-func/prefer-array-from': 'off', 7 | 8 | // Rules not in recommended config 9 | 'array-func/prefer-flat': 0, 10 | 'array-func/prefer-flat-map': 0, 11 | 12 | // Rules in recommended config 13 | 'array-func/from-map': 'error', 14 | 'array-func/no-unnecessary-this-arg': 'error', 15 | 'array-func/avoid-reverse': 'error', 16 | }, 17 | } 18 | -------------------------------------------------------------------------------- /rules/ava.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:ava/recommended'], 3 | } 4 | -------------------------------------------------------------------------------- /rules/chai-expect.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:chai-expect/recommended'], 3 | } 4 | -------------------------------------------------------------------------------- /rules/chai-friendly.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:chai-friendly/recommended'], 3 | } 4 | -------------------------------------------------------------------------------- /rules/const-case.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['const-case'], 3 | rules: { 'const-case/uppercase': 'error' }, 4 | } 5 | -------------------------------------------------------------------------------- /rules/cypress.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | 'cypress/globals': true, 4 | }, 5 | extends: ['plugin:cypress/recommended'], 6 | plugins: ['cypress'], 7 | rules: { 8 | // Rules not in recommmend config 9 | 'cypress/assertion-before-screenshot': 0, 10 | 'cypress/no-force': 0, 11 | 'cypress/require-data-selectors': 0, 12 | }, 13 | } 14 | -------------------------------------------------------------------------------- /rules/eslint-comments.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:eslint-comments/recommended'], 3 | plugins: ['eslint-comments'], 4 | rules: { 5 | // Rules are not in recommended config 6 | 'eslint-comments/no-restricted-disable': 0, 7 | 'eslint-comments/no-unused-disable': 0, 8 | 'eslint-comments/no-use': 0, 9 | 'eslint-comments/require-description': 0, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /rules/fsa.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:fsa/recommended'], 3 | plugins: ['fsa'], 4 | } 5 | -------------------------------------------------------------------------------- /rules/html.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['html'], 3 | } 4 | -------------------------------------------------------------------------------- /rules/jasmine.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | jasmine: true, 4 | }, 5 | extends: ['plugin:jasmine/recommended'], 6 | plugins: ['jasmine'], 7 | rules: { 8 | 'jasmine/valid-expect': 0, 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /rules/jest-async.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['jest-async'], 3 | rules: { 4 | 'jest-async/expect-return': 'error', 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /rules/jest-dom.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:jest-dom/recommended'], 3 | } 4 | -------------------------------------------------------------------------------- /rules/jest.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | jest: true, 4 | }, 5 | extends: ['plugin:jest/recommended', 'plugin:jest/style'], 6 | overrides: [ 7 | { 8 | files: ['setupJest.js'], 9 | rules: { 10 | 'import/no-extraneous-dependencies': 'off', 11 | }, 12 | }, 13 | ], 14 | plugins: ['jest'], 15 | rules: { 16 | 'jest/no-disabled-tests': 'off', 17 | 18 | // Not included in jest/recommended 19 | 'jest/consistent-test-it': 0, 20 | 'jest/lowercase-name': 0, 21 | 'jest/no-conditional-expect': 0, 22 | 'jest/no-deprecated-functions': 0, 23 | 'jest/no-duplicate-hooks': 0, 24 | 'jest/no-expect-resolves': 0, 25 | 'jest/no-hooks': 0, 26 | // 'jest/no-if': 0, deprecaded 27 | 'jest/no-interpolation-in-snapshots': 0, 28 | 'jest/no-large-snapshots': 0, 29 | 'jest/no-restricted-matchers': 0, 30 | 'jest/no-test-return-statement': 0, 31 | 'jest/no-truthy-falsy': 0, 32 | 'jest/prefer-called-with': 0, 33 | 'jest/prefer-expect-assertions': 0, 34 | 'jest/prefer-hooks-on-top': 0, 35 | 'jest/prefer-inline-snapshots': 0, 36 | 'jest/prefer-spy-on': 0, 37 | 'jest/prefer-strict-equal': 0, 38 | 'jest/prefer-todo': 0, 39 | 'jest/require-to-throw-message': 0, 40 | 'jest/require-top-level-describe': 0, 41 | 'jest/unbound-method': 0, 42 | 'jest/valid-title': 0, 43 | }, 44 | } 45 | -------------------------------------------------------------------------------- /rules/json-format.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['json-format'], 3 | settings: { 4 | 'json/sort-package-json': [ 5 | 'name', 6 | 'version', 7 | 'author', 8 | 'contributors', 9 | 'license', 10 | 'private', 11 | 'description', 12 | 'homepage', 13 | 'funding', 14 | 'bugs', 15 | 'repository', 16 | 'files', 17 | 'sideEffects', 18 | 'main', 19 | 'umd:main', 20 | 'unpkg', 21 | 'module', 22 | 'source', 23 | 'jsnext:main', 24 | 'browser', 25 | 'types', 26 | 'typings', 27 | 'style', 28 | 'example', 29 | 'examplestyle', 30 | 'assets', 31 | 'bin', 32 | 'man', 33 | 'directories', 34 | 'workspaces', 35 | 'scripts', 36 | 'betterScripts', 37 | 'husky', 38 | 'pre-commit', 39 | 'commitlint', 40 | 'lint-staged', 41 | 'config', 42 | 'keywords', 43 | 'nodemonConfig', 44 | 'browserify', 45 | 'babel', 46 | 'browserslist', 47 | 'xo', 48 | 'prettier', 49 | 'eslintConfig', 50 | 'eslintIgnore', 51 | 'stylelint', 52 | 'jest', 53 | 'dependencies', 54 | 'devDependencies', 55 | 'peerDependencies', 56 | 'bundledDependencies', 57 | 'bundleDependencies', 58 | 'optionalDependencies', 59 | 'flat', 60 | 'resolutions', 61 | 'engines', 62 | 'engineStrict', 63 | 'os', 64 | 'cpu', 65 | 'preferGlobal', 66 | 'publishConfig', 67 | ], 68 | 'json/ignore-files': ['**/package-lock.json'], 69 | 'json/json-with-comments-files': ['**/tsconfig.json', '.vscode/**'], 70 | }, 71 | } 72 | -------------------------------------------------------------------------------- /rules/json.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:json/recommended-with-comments'], 3 | overrides: [ 4 | { 5 | files: ['**.json'], 6 | plugins: ['json'], 7 | rules: { 8 | 'comma-dangle': 0, 9 | 'no-var': 0, 10 | 'no-unused-vars': 0, 11 | quotes: 0, 12 | 'quote-props': 0, 13 | semi: 0, 14 | }, 15 | }, 16 | ], 17 | rules: { 18 | // Not included in json/recommended-with-comments 19 | 'json/colon-expected': 0, 20 | 'json/comma-expected': 0, 21 | 'json/comma-or-close-backet-expected': 0, 22 | 'json/comma-or-close-brace-expected': 0, 23 | 'json/comment-not-permitted': 0, 24 | 'json/duplicate-key': 0, 25 | 'json/enum-value-mismatch': 0, 26 | 'json/invalid-character': 0, 27 | 'json/invalid-escape-character': 0, 28 | 'json/invalid-unicode': 0, 29 | 'json/json': 0, 30 | 'json/property-expected': 0, 31 | 'json/schema-resolve-error': 0, 32 | 'json/trailing-comma': 0, 33 | 'json/undefined': 0, 34 | 'json/unexpected-end-of-comment': 0, 35 | 'json/unexpected-end-of-number': 0, 36 | 'json/unexpected-end-of-string': 0, 37 | 'json/unknown': 0, 38 | 'json/value-expected': 0, 39 | }, 40 | } 41 | -------------------------------------------------------------------------------- /rules/lodash-fp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:lodash-fp/recommended'], 3 | plugins: ['lodash-fp'], 4 | rules: { 5 | 'lodash-fp/use-fp': 0, 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /rules/lodash.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['lodash'], 3 | rules: { 4 | // Possible Errors 5 | 'lodash/callback-binding': 2, 6 | 'lodash/collection-method-value': 2, 7 | 'lodash/collection-return': 2, 8 | 'lodash/no-double-unwrap': 2, 9 | 'lodash/no-extra-args': 2, 10 | 'lodash/no-unbound-this': 2, 11 | 'lodash/unwrap': 2, 12 | 13 | // Disable stylistic rules = Use prettier 14 | 'lodash/chain-style': [2, 'as-needed'], 15 | 'lodash/chaining': 2, 16 | 'lodash/collection-ordering': 2, 17 | 'lodash/consistent-compose': [2, 'flow'], 18 | 'lodash/identity-shorthand': [2, 'always'], 19 | 'lodash/import-scope': [2], 20 | 'lodash/matches-prop-shorthand': [2, 'always'], 21 | 'lodash/matches-shorthand': [2, 'always', 3], 22 | 'lodash/no-commit': 2, 23 | 'lodash/path-style': [2, 'string'], 24 | 'lodash/prefer-compact': 2, 25 | 'lodash/prefer-filter': [2, 3], 26 | 'lodash/prefer-find': 2, 27 | 'lodash/prefer-flat-map': 2, 28 | 'lodash/prefer-immutable-method': 2, 29 | 'lodash/prefer-invoke-map': 2, 30 | 'lodash/prefer-map': 2, 31 | 'lodash/prefer-noop': 2, 32 | 'lodash/prefer-reject': [2, 3], 33 | 'lodash/prefer-thru': 2, 34 | 'lodash/prefer-wrapper-method': 2, 35 | 'lodash/preferred-alias': 2, 36 | 'lodash/prop-shorthand': [2, 'always'], 37 | 38 | // Prefer over Native - DISABLED 39 | 'lodash/prefer-constant': 0, 40 | 'lodash/prefer-get': 0, 41 | 'lodash/prefer-includes': 0, 42 | 'lodash/prefer-is-nil': 0, 43 | 'lodash/prefer-lodash-chain': 0, 44 | 'lodash/prefer-lodash-method': 0, 45 | 'lodash/prefer-lodash-typecheck': 0, 46 | 'lodash/prefer-matches': 0, 47 | 'lodash/prefer-over-quantifier': 0, 48 | 'lodash/prefer-some': 0, 49 | 'lodash/prefer-startswith': 0, 50 | 'lodash/prefer-times': 0, 51 | }, 52 | } 53 | -------------------------------------------------------------------------------- /rules/markdown.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['markdown'], 3 | overrides: [ 4 | { 5 | files: ['*.md', '**/*.md'], 6 | processor: 'markdown/markdown', 7 | }, 8 | { 9 | files: ['*.md/*.js', '**/*.md/*.js'], 10 | rules: { 11 | 'global-require': 'off', 12 | 'import/no-unresolved': 'off', 13 | 'import/order': 'off', 14 | 'no-undef': 'off', 15 | 'no-console': 'off', 16 | 'no-unused-vars': 'off', 17 | 'prefer-reflect': 'off', 18 | strict: 'off', 19 | }, 20 | }, 21 | ], 22 | } 23 | -------------------------------------------------------------------------------- /rules/mocha-cleanup.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:mocha-cleanup/recommended-no-limits'], 3 | plugins: ['mocha-cleanup'], 4 | rules: { 5 | // Rules are not in recommended config 6 | 'mocha-cleanup/asserts-limit': 0, 7 | 'mocha-cleanup/complexity-it': 0, 8 | 'mocha-cleanup/disallow-stub-window': 0, 9 | 'mocha-cleanup/disallowed-usage': 0, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /rules/mocha.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:mocha/recommended'], 3 | plugins: ['mocha'], 4 | } 5 | -------------------------------------------------------------------------------- /rules/no-constructor-bind.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['no-constructor-bind'], 3 | rules: { 4 | 'no-constructor-bind/no-constructor-bind': 'error', 5 | 'no-constructor-bind/no-constructor-state': 'error', 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /rules/no-secrets.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | overrides: [ 3 | { 4 | plugins: ['no-secrets'], 5 | rules: { 6 | 'no-secrets/no-secrets': 'error', 7 | }, 8 | files: ['*', '*/**'], 9 | excludedFiles: [ 10 | 'package.json', 11 | '**/package.json', 12 | 'package-lock.json', 13 | '**/package-lock.json', 14 | 'tsconfig.json', 15 | '**/tsconfig.json', 16 | ], 17 | }, 18 | ], 19 | } 20 | -------------------------------------------------------------------------------- /rules/no-unsanitized.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['no-unsanitized'], 3 | rules: { 4 | 'no-unsanitized/method': 'error', 5 | 'no-unsanitized/property': 'error', 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /rules/no-use-extend-native.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['no-use-extend-native'], 3 | rules: { 4 | 'no-use-extend-native/no-use-extend-native': 'error', 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /rules/optimize-regex.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['optimize-regex'], 3 | rules: { 4 | 'optimize-regex/optimize-regex': 'warn', 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /rules/pii.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:pii/recommended'], 3 | rules: { 4 | 'pii/no-dob': 0, // Buggy rule 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /rules/prettier.js: -------------------------------------------------------------------------------- 1 | const { hasAnyDep } = require('../lib/utils') 2 | const { consoleConfig } = require('../lib/loggers') 3 | const isModuleAvailable = require('../lib/is-module-available') 4 | 5 | const configs = ['prettier'] 6 | 7 | const optionalConfigs = [ 8 | ['@typescript-eslint/eslint-plugin', 'prettier/@typescript-eslint'], 9 | 'babel', 10 | 'flowtype', 11 | 'react', 12 | ['eslint-config-standard', 'prettier/standard'], 13 | 'vue', 14 | 'unicorn', 15 | ] 16 | 17 | optionalConfigs.forEach((optConfig) => { 18 | const config = 19 | typeof optConfig === 'string' 20 | ? [`eslint-plugin-${optConfig}`, `prettier/${optConfig}`] 21 | : optConfig 22 | 23 | if (hasAnyDep(config[0]) && isModuleAvailable(config[1])) 24 | configs.push(config[1]) 25 | }) 26 | 27 | if (!global.hasAdjunctPrettierLoaded) { 28 | configs.map((config) => consoleConfig(config)) 29 | global.hasAdjunctPrettierLoaded = true 30 | } 31 | 32 | module.exports = { 33 | extends: configs, 34 | plugins: ['prettier'], 35 | rules: { 36 | 'prettier/prettier': 'error', 37 | }, 38 | overrides: [ 39 | { 40 | files: ['**.md', '**.json'], 41 | rules: { 42 | 'prettier/prettier': 'off', 43 | }, 44 | }, 45 | ], 46 | } 47 | -------------------------------------------------------------------------------- /rules/promise.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:promise/recommended'], 3 | plugins: ['promise'], 4 | rules: { 5 | 'promise/prefer-await-to-callbacks': 'off', 6 | 'promise/prefer-await-to-then': 'off', 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /rules/qunit.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['qunit'], 3 | extends: ['plugin:qunit/recommended'], 4 | } 5 | -------------------------------------------------------------------------------- /rules/ramda.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:ramda/recommended'], 3 | plugins: ['ramda'], 4 | } 5 | -------------------------------------------------------------------------------- /rules/react-redux.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:react-redux/recommended'], 3 | plugins: ['react-redux'], 4 | rules: { 5 | 'react-redux/prefer-separate-component-file': 'off', 6 | 'react-redux/mapStateToProps-prefer-selectors': 'off', 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /rules/redux-saga.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:redux-saga/recommended'], 3 | plugins: ['redux-saga'], 4 | rules: { 5 | 'redux-saga/no-unhandled-errors': 'off', 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /rules/security.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['security'], 3 | extends: ['plugin:security/recommended-legacy'], 4 | rules: { 5 | 'security/detect-object-injection': 0, 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /rules/simple-import-sort.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['simple-import-sort'], 3 | rules: { 4 | 'simple-import-sort/imports': 'error', 5 | 'simple-import-sort/exports': 'error', 6 | 'sort-imports': 'off', 7 | 'import/order': 'off', 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /rules/sonarjs.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['sonarjs'], 3 | extends: ['plugin:sonarjs/recommended'], 4 | overrides: [ 5 | { 6 | files: ['**.md', '**.json'], 7 | rules: { 8 | 'sonarjs/no-duplicate-string': 'off', 9 | }, 10 | }, 11 | ], 12 | } 13 | -------------------------------------------------------------------------------- /rules/switch-case.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:switch-case/recommended'], 3 | plugins: ['switch-case'], 4 | rules: { 5 | 'switch-case/newline-between-switch-case': [ 6 | 'error', 7 | 'always', 8 | { fallthrough: 'never' }, 9 | ], 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /rules/test-overrides.js: -------------------------------------------------------------------------------- 1 | require('../lib/loggers').consoleLog(' eslint-test-overrides\n') 2 | 3 | module.exports = { 4 | overrides: [ 5 | { 6 | files: [ 7 | '*.spec.js', 8 | '*.spec.ts', 9 | '*.spec.jsx', 10 | '*.spec.tsx', 11 | '*.test.js', 12 | '*.test.ts', 13 | '*.test.jsx', 14 | '*.test.tsx', 15 | '**/tests/**', 16 | '**/test/**', 17 | '**/__test__/**', 18 | '**/__tests__/**', 19 | ], 20 | rules: { 21 | 'func-names': 'off', 22 | 'global-require': 'off', 23 | 'no-shadow': 'off', 24 | 'max-lines': 'off', 25 | 'max-nested-callbacks': 'off', 26 | 'max-statements': 'off', 27 | 'promise/always-return': 'off', 28 | 'promise/no-callback-in-promise': 'off', 29 | 'security/detect-non-literal-regexp': 'off', 30 | 'sonarjs/no-duplicate-string': 'off', 31 | 'sonarjs/no-identical-functions': 'off', 32 | }, 33 | }, 34 | ], 35 | } 36 | -------------------------------------------------------------------------------- /rules/testing-library.js: -------------------------------------------------------------------------------- 1 | const isModuleAvailable = require('../lib/is-module-available') 2 | const { consoleLog } = require('../lib/loggers') 3 | 4 | let ruleset = '' 5 | 6 | switch (true) { 7 | case isModuleAvailable('react'): 8 | ruleset = 'react' 9 | break 10 | 11 | case isModuleAvailable('vue'): 12 | ruleset = 'vue' 13 | break 14 | 15 | default: 16 | ruleset = 'recommended' 17 | } 18 | 19 | consoleLog(` eslint-plugin-testing-library/${ruleset}`) 20 | 21 | module.exports = { 22 | extends: [`plugin:testing-library/${ruleset}`], 23 | rules: { 24 | // Not included in jest/recommended 25 | 'testing-library/await-fire-event': 0, 26 | 'testing-library/consistent-data-testid': 0, 27 | 'testing-library/no-debug': 0, 28 | 'testing-library/no-dom-import': 0, 29 | 'testing-library/no-manual-cleanup': 0, 30 | 'testing-library/no-render-in-setup': 0, 31 | 'testing-library/no-await-sync-events': 0, 32 | 'testing-library/no-wait-for-empty-callback': 0, 33 | 'testing-library/no-wait-for-snapshot': 0, 34 | 'testing-library/prefer-explicit-assert': 0, 35 | 'testing-library/prefer-presence-queries': 0, 36 | 'testing-library/prefer-screen-queries': 0, 37 | 'testing-library/prefer-wait-for': 0, 38 | }, 39 | } 40 | -------------------------------------------------------------------------------- /rules/unicorn.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:unicorn/recommended'], 3 | rules: { 4 | 'unicorn/expiring-todo-comments': 0, 5 | 'unicorn/filename-case': 0, 6 | 'unicorn/no-array-for-each': 0, 7 | 'unicorn/no-null': 0, 8 | 'unicorn/prefer-number-properties': 0, 9 | 'unicorn/prefer-optional-catch-binding': 0, 10 | 'unicorn/prevent-abbreviations': 0, 11 | 'unicorn/switch-case-braces': ['error', 'avoid'], 12 | }, 13 | } 14 | -------------------------------------------------------------------------------- /rules/xss.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:xss/recommended'], 3 | } 4 | --------------------------------------------------------------------------------