├── .editorconfig ├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── linters ├── .eslintrc └── .markdownlint.json ├── package.json └── packages ├── eslint-config-eser-react ├── .eslintrc ├── .npmrc ├── README.md ├── index.js ├── package.json ├── rules │ ├── react-a11y.js │ ├── react-hooks.js │ └── react.js └── tsconfig.json └── eslint-config-eser ├── .eslintrc ├── .npmrc ├── README.md ├── index.js ├── package.json ├── rules ├── best-practices.js ├── errors.js ├── es6.js ├── imports.js ├── node.js ├── strict.js ├── style.js ├── typescript.js └── variables.js └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | end_of_line = lf 10 | # editorconfig-tools is unable to ignore longs strings or urls 11 | max_line_length = off 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text eol=lf 3 | 4 | *.png binary 5 | *.jpg binary 6 | *.ico binary 7 | *.jpg binary 8 | *.eot binary 9 | *.ttf binary 10 | *.woff binary 11 | *.woff2 binary 12 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [eserozvataf] 4 | patreon: eserozvataf 5 | open_collective: eser 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS-specific files 2 | .DS_Store 3 | 4 | # NPM-specific files 5 | node_modules/ 6 | yarn.lock 7 | package-lock.json 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Eser Ozvataf 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 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Eser: JavaScript Style Guide](https://github.com/eserozvataf/eser) 2 | 3 | [![npm version][npm-image]][npm-url] 4 | [![npm download][download-image]][npm-url] 5 | [![dependencies][dep-image]][dep-url] 6 | [![license][license-image]][license-url] 7 | 8 | 9 | ## Contributors 10 | 11 | This project is forked from airbnb's JavaScript Guide. 12 | 13 | - [View Base Project](https://github.com/airbnb/javascript) 14 | - [View Contributors](https://github.com/airbnb/javascript/graphs/contributors) 15 | 16 | 17 | ## License 18 | 19 | MIT License, for further details, please see [LICENSE](LICENSE) file 20 | 21 | 22 | ## To Support 23 | 24 | [Visit my patreon profile at patreon.com/eserozvataf](https://www.patreon.com/eserozvataf) 25 | 26 | 27 | [npm-image]: https://img.shields.io/npm/v/eser.svg?style=flat-square 28 | [npm-url]: https://www.npmjs.com/package/eser 29 | [download-image]: https://img.shields.io/npm/dt/eser.svg?style=flat-square 30 | [dep-image]: https://img.shields.io/david/eserozvataf/eser.svg?style=flat-square 31 | [dep-url]: https://github.com/eserozvataf/eser 32 | [license-image]: https://img.shields.io/npm/l/eser.svg?style=flat-square 33 | [license-url]: https://github.com/eserozvataf/eser/blob/master/LICENSE 34 | -------------------------------------------------------------------------------- /linters/.eslintrc: -------------------------------------------------------------------------------- 1 | // Use this file as a starting point for your project's .eslintrc. 2 | // Copy this file, and add rule overrides as needed. 3 | { 4 | "extends": "eser" 5 | } 6 | -------------------------------------------------------------------------------- /linters/.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "Be explicit by listing every available rule. https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md", 3 | "comment": "Note that there will be numeric gaps, not every MD number is implemented in markdownlint.", 4 | 5 | "comment": "MD001: Header levels should only increment by one level at a time.", 6 | "header-increment": true, 7 | 8 | "comment": "MD002: First header should be a top level header.", 9 | "first-header-h1": true, 10 | 11 | "comment": "MD003: Header style: start with hashes.", 12 | "header-style": { 13 | "style": "atx" 14 | }, 15 | 16 | "comment": "MD004: Unordered list style", 17 | "ul-style": { 18 | "style": "dash" 19 | }, 20 | 21 | "comment": "MD005: Consistent indentation for list items at the same level.", 22 | "list-indent": true, 23 | 24 | "comment": "MD006: Consider starting bulleted lists at the beginning of the line.", 25 | "ul-start-left": false, 26 | 27 | "comment": "MD007: Unordered list indentation: 2 spaces.", 28 | "ul-indent": { 29 | "indent": 2 30 | }, 31 | 32 | "comment": "MD009: Disallow trailing spaces!", 33 | "no-trailing-spaces": { 34 | "br_spaces": 0, 35 | "comment": "Empty lines inside list items should not be indented.", 36 | "list_item_empty_lines": false 37 | }, 38 | 39 | "comment": "MD010: No hard tabs, not even in code blocks.", 40 | "no-hard-tabs": { 41 | "code_blocks": true 42 | }, 43 | 44 | "comment": "MD011: Prevent reversed link syntax", 45 | "no-reversed-links": true, 46 | 47 | "comment": "MD012: Disallow multiple consecutive blank lines.", 48 | "no-multiple-blanks": { 49 | "maximum": 2 50 | }, 51 | 52 | "comment": "MD013: Line length", 53 | "line-length": false, 54 | 55 | "comment": "MD014: Disallow use of dollar signs($) before commands without showing output.", 56 | "commands-show-output": true, 57 | 58 | "comment": "MD018: Disallow space after hash on atx style header.", 59 | "no-missing-space-atx": true, 60 | 61 | "comment": "MD019: Disallow multiple spaces after hash on atx style header.", 62 | "no-multiple-space-atx": true, 63 | 64 | "comment": "MD020: No space should be inside hashes on closed atx style header.", 65 | "no-missing-space-closed-atx": true, 66 | 67 | "comment": "MD021: Disallow multiple spaces inside hashes on closed atx style header.", 68 | "no-multiple-space-closed-atx": true, 69 | 70 | "comment": "MD022: Headers should be surrounded by blank lines.", 71 | "comment": "Some headers have preceeding HTML anchors. Unfortunate that we have to disable this, as it otherwise catches a real problem that trips up some Markdown renderers", 72 | "blanks-around-headers": false, 73 | 74 | "comment": "MD023: Headers must start at the beginning of the line.", 75 | "header-start-left": true, 76 | 77 | "comment": "MD024: Disallow multiple headers with the same content.", 78 | "no-duplicate-header": true, 79 | 80 | "comment": "MD025: Disallow multiple top level headers in the same document.", 81 | "comment": "Gotta have a matching closing brace at the end.", 82 | "single-h1": false, 83 | 84 | "comment": "MD026: Disallow trailing punctuation in header.", 85 | "comment": "You must have a semicolon after the ending closing brace.", 86 | "no-trailing-punctuation": { 87 | "punctuation" : ".,:!?" 88 | }, 89 | "comment": "MD027: Dissalow multiple spaces after blockquote symbol", 90 | "no-multiple-space-blockquote": true, 91 | 92 | "comment": "MD028: Blank line inside blockquote", 93 | "comment": "Some 'Why?' and 'Why not?' blocks are separated by a blank line", 94 | "no-blanks-blockquote": false, 95 | 96 | "comment": "MD029: Ordered list item prefix", 97 | "ol-prefix": { 98 | "style": "one" 99 | }, 100 | 101 | "comment": "MD030: Spaces after list markers", 102 | "list-marker-space": { 103 | "ul_single": 1, 104 | "ol_single": 1, 105 | "ul_multi": 1, 106 | "ol_multi": 1 107 | }, 108 | 109 | "comment": "MD031: Fenced code blocks should be surrounded by blank lines", 110 | "blanks-around-fences": true, 111 | 112 | "comment": "MD032: Lists should be surrounded by blank lines", 113 | "comment": "Some lists have preceeding HTML anchors. Unfortunate that we have to disable this, as it otherwise catches a real problem that trips up some Markdown renderers", 114 | "blanks-around-lists": false, 115 | 116 | "comment": "MD033: Disallow inline HTML", 117 | "comment": "HTML is needed for explicit anchors", 118 | "no-inline-html": false, 119 | 120 | "comment": "MD034: No bare URLs should be used", 121 | "no-bare-urls": true, 122 | 123 | "comment": "MD035: Horizontal rule style", 124 | "hr-style": { 125 | "style": "consistent" 126 | }, 127 | 128 | "comment": "MD036: Do not use emphasis instead of a header.", 129 | "no-emphasis-as-header": false, 130 | 131 | "comment": "MD037: Disallow spaces inside emphasis markers.", 132 | "no-space-in-emphasis": true, 133 | 134 | "comment": "MD038: Disallow spaces inside code span elements.", 135 | "no-space-in-code": true, 136 | 137 | "comment": "MD039: Disallow spaces inside link text.", 138 | "no-space-in-links": true, 139 | 140 | "comment": "MD040: Fenced code blocks should have a language specified.", 141 | "fenced-code-language": true, 142 | 143 | "comment": "MD041: First line in file should be a top level header.", 144 | "first-line-h1": true, 145 | 146 | "comment": "MD042: No empty links", 147 | "no-empty-links": true, 148 | 149 | "comment": "MD043: Required header structure.", 150 | "required-headers": false, 151 | 152 | "comment": "MD044: Proper names should have the correct capitalization.", 153 | "proper-names": false 154 | } 155 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eser", 3 | "version": "2.2.6", 4 | "description": "A mostly reasonable approach to JavaScript.", 5 | "scripts": { 6 | "cleanup": "rm -rf package-lock.json node_modules/", 7 | "lint": "markdownlint --config linters/.markdownlint.json README.md */README.md", 8 | "lint:fix": "markdownlint --config linters/.markdownlint.json --fix README.md */README.md", 9 | "test": "", 10 | "test:coverage": "" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/eserozvataf/eser.git" 15 | }, 16 | "keywords": [ 17 | "style guide", 18 | "lint", 19 | "eser", 20 | "airbnb", 21 | "es6", 22 | "es2015", 23 | "es2016", 24 | "es2017", 25 | "es2018", 26 | "react", 27 | "hooks", 28 | "jsx", 29 | "tsx", 30 | "a11y" 31 | ], 32 | "author": "Eser Ozvataf (https://twitter.com/eser)", 33 | "license": "MIT", 34 | "bugs": { 35 | "url": "https://github.com/eserozvataf/eser/issues" 36 | }, 37 | "homepage": "https://github.com/eserozvataf/eser", 38 | "devDependencies": { 39 | "markdownlint-cli": "^0.24.0" 40 | }, 41 | "private": true, 42 | "workspaces": [ 43 | "packages/*" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /packages/eslint-config-eser-react/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./index.js" 3 | } 4 | -------------------------------------------------------------------------------- /packages/eslint-config-eser-react/.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /packages/eslint-config-eser-react/README.md: -------------------------------------------------------------------------------- 1 | # [Eser: JavaScript Style Guide](https://github.com/eserozvataf/eser) 2 | 3 | This package consists of ESLint rule definitions for [eser](https://github.com/eserozvataf/eser). 4 | 5 | To use this package, execute: 6 | 7 | ```sh 8 | npm install eslint eslint-plugin-import eslint-import-resolver-typescript eslint-plugin-jsx-a11y eslint-plugin-react eslint-plugin-react-hooks @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-eser-react --save-dev 9 | ``` 10 | 11 | Then create an `.eslintrc` file: 12 | 13 | ```json 14 | { 15 | "extends": "eser-react" 16 | } 17 | ``` 18 | 19 | See [main repository](https://github.com/eserozvataf/eser) for further details. 20 | -------------------------------------------------------------------------------- /packages/eslint-config-eser-react/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | "eslint-config-eser", 4 | "./rules/react.js", 5 | "./rules/react-a11y.js", 6 | "./rules/react-hooks.js", 7 | ].map(require.resolve), 8 | 9 | rules: {}, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/eslint-config-eser-react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-eser-react", 3 | "version": "2.2.6", 4 | "description": "Eser's ESLint config for React, following our styleguide", 5 | "main": "index.js", 6 | "scripts": { 7 | "cleanup": "rm -rf package-lock.json node_modules/", 8 | "prelint": "# editorconfig-tools check *", 9 | "lint": "eslint ./", 10 | "lint:fix": "eslint --fix ./", 11 | "test": "", 12 | "test:coverage": "" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/eserozvataf/eser" 17 | }, 18 | "keywords": [ 19 | "eslint", 20 | "eslintconfig", 21 | "config", 22 | "eser", 23 | "airbnb", 24 | "javascript", 25 | "styleguide", 26 | "react", 27 | "hooks", 28 | "jsx", 29 | "a11y" 30 | ], 31 | "author": "Eser Ozvataf (https://twitter.com/eser)", 32 | "license": "MIT", 33 | "bugs": { 34 | "url": "https://github.com/eserozvataf/eser/issues" 35 | }, 36 | "homepage": "https://github.com/eserozvataf/eser", 37 | "dependencies": { 38 | "eslint-config-eser": "^2.2.6" 39 | }, 40 | "devDependencies": { 41 | "@typescript-eslint/eslint-plugin": "^4.8.0", 42 | "@typescript-eslint/parser": "^4.8.0", 43 | "editorconfig-tools": "^0.1.1", 44 | "eslint": "^7.13.0", 45 | "eslint-find-rules": "^3.6.1", 46 | "eslint-import-resolver-typescript": "^2.3.0", 47 | "eslint-plugin-import": "^2.22.1", 48 | "eslint-plugin-jsx-a11y": "^6.4.1", 49 | "eslint-plugin-react": "^7.21.5", 50 | "eslint-plugin-react-hooks": "^4.2.0", 51 | "typescript": "^4.0.5" 52 | }, 53 | "peerDependencies": { 54 | "eslint": "^7.13.0", 55 | "eslint-plugin-jsx-a11y": "^6.4.1", 56 | "eslint-plugin-react": "^7.21.5", 57 | "eslint-plugin-react-hooks": "^4.2.0" 58 | }, 59 | "engines": { 60 | "node": ">= 14" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/eslint-config-eser-react/rules/react-a11y.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | "jsx-a11y", 4 | "react", 5 | ], 6 | 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | }, 12 | 13 | rules: { 14 | // Enforce that anchors have content 15 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-has-content.md 16 | "jsx-a11y/anchor-has-content": ["error", { components: [] }], 17 | 18 | // Require ARIA roles to be valid and non-abstract 19 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-role.md 20 | "jsx-a11y/aria-role": ["error", { ignoreNonDOM: false }], 21 | 22 | // Enforce all aria-* props are valid. 23 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-props.md 24 | "jsx-a11y/aria-props": "error", 25 | 26 | // Enforce ARIA state and property values are valid. 27 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-proptypes.md 28 | "jsx-a11y/aria-proptypes": "error", 29 | 30 | // Enforce that elements that do not support ARIA roles, states, and 31 | // properties do not have those attributes. 32 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-unsupported-elements.md 33 | "jsx-a11y/aria-unsupported-elements": "error", 34 | 35 | // Enforce that all elements that require alternative text have meaningful information 36 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/alt-text.md 37 | "jsx-a11y/alt-text": ["error", { 38 | "elements": ["img", "object", "area", 'input[type="image"]'], 39 | "img": [], 40 | "object": [], 41 | "area": [], 42 | 'input[type="image"]': [], 43 | }], 44 | 45 | // Prevent img alt text from containing redundant words like "image", "picture", or "photo" 46 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/img-redundant-alt.md 47 | "jsx-a11y/img-redundant-alt": "error", 48 | 49 | // require that JSX labels use "htmlFor" 50 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/label-has-for.md 51 | // deprecated: replaced by `label-has-associated-control` rule 52 | "jsx-a11y/label-has-for": ["off", { 53 | components: [], 54 | required: { 55 | every: ["nesting", "id"], 56 | }, 57 | allowChildren: false, 58 | }], 59 | 60 | // Enforce that a label tag has a text label and an associated control. 61 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/b800f40a2a69ad48015ae9226fbe879f946757ed/docs/rules/label-has-associated-control.md 62 | "jsx-a11y/label-has-associated-control": ["error", { 63 | labelComponents: [], 64 | labelAttributes: [], 65 | controlComponents: [], 66 | assert: "both", 67 | depth: 25, 68 | }], 69 | 70 | // Enforce that a control (an interactive element) has a text label. 71 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/control-has-associated-label.md 72 | "jsx-a11y/control-has-associated-label": ["error", { 73 | labelAttributes: ["label"], 74 | controlComponents: [], 75 | ignoreElements: [ 76 | "audio", 77 | "canvas", 78 | "embed", 79 | "input", 80 | "textarea", 81 | "tr", 82 | "video", 83 | ], 84 | ignoreRoles: [ 85 | "grid", 86 | "listbox", 87 | "menu", 88 | "menubar", 89 | "radiogroup", 90 | "row", 91 | "tablist", 92 | "toolbar", 93 | "tree", 94 | "treegrid", 95 | ], 96 | depth: 5, 97 | }], 98 | 99 | // require that mouseover/out come with focus/blur, for keyboard-only users 100 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/mouse-events-have-key-events.md 101 | "jsx-a11y/mouse-events-have-key-events": "error", 102 | 103 | // Prevent use of `accessKey` 104 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-access-key.md 105 | "jsx-a11y/no-access-key": "error", 106 | 107 | // require onBlur instead of onChange 108 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-onchange.md 109 | "jsx-a11y/no-onchange": "off", 110 | 111 | // Elements with an interactive role and interaction handlers must be focusable 112 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/interactive-supports-focus.md 113 | "jsx-a11y/interactive-supports-focus": "error", 114 | 115 | // Enforce that elements with ARIA roles must have all required attributes 116 | // for that role. 117 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-has-required-aria-props.md 118 | "jsx-a11y/role-has-required-aria-props": "error", 119 | 120 | // Enforce that elements with explicit or implicit roles defined contain 121 | // only aria-* properties supported by that role. 122 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-supports-aria-props.md 123 | "jsx-a11y/role-supports-aria-props": "error", 124 | 125 | // Enforce tabIndex value is not greater than zero. 126 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/tabindex-no-positive.md 127 | "jsx-a11y/tabindex-no-positive": "error", 128 | 129 | // ensure tags have content and are not aria-hidden 130 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/heading-has-content.md 131 | "jsx-a11y/heading-has-content": ["error", { components: [""] }], 132 | 133 | // require HTML elements to have a "lang" prop 134 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/html-has-lang.md 135 | "jsx-a11y/html-has-lang": "error", 136 | 137 | // require HTML element's lang prop to be valid 138 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/lang.md 139 | "jsx-a11y/lang": "error", 140 | 141 | // prevent distracting elements, like and 142 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-distracting-elements.md 143 | "jsx-a11y/no-distracting-elements": ["error", { 144 | elements: ["marquee", "blink"], 145 | }], 146 | 147 | // only allow to have the "scope" attr 148 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/scope.md 149 | "jsx-a11y/scope": "error", 150 | 151 | // require onClick be accompanied by onKeyUp/onKeyDown/onKeyPress 152 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/click-events-have-key-events.md 153 | "jsx-a11y/click-events-have-key-events": "error", 154 | 155 | // Enforce that DOM elements without semantic behavior not have interaction handlers 156 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-static-element-interactions.md 157 | "jsx-a11y/no-static-element-interactions": ["error", { 158 | handlers: [ 159 | "onClick", 160 | "onMouseDown", 161 | "onMouseUp", 162 | "onKeyPress", 163 | "onKeyDown", 164 | "onKeyUp", 165 | ], 166 | }], 167 | 168 | // A non-interactive element does not support event handlers (mouse and key handlers) 169 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-interactions.md 170 | "jsx-a11y/no-noninteractive-element-interactions": ["error", { 171 | handlers: [ 172 | "onClick", 173 | "onMouseDown", 174 | "onMouseUp", 175 | "onKeyPress", 176 | "onKeyDown", 177 | "onKeyUp", 178 | ], 179 | }], 180 | 181 | // ensure emoji are accessible 182 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/accessible-emoji.md 183 | // disabled; rule is deprecated 184 | "jsx-a11y/accessible-emoji": "off", 185 | 186 | // elements with aria-activedescendant must be tabbable 187 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-activedescendant-has-tabindex.md 188 | "jsx-a11y/aria-activedescendant-has-tabindex": "error", 189 | 190 | // ensure iframe elements have a unique title 191 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/iframe-has-title.md 192 | "jsx-a11y/iframe-has-title": "error", 193 | 194 | // prohibit autoFocus prop 195 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-autofocus.md 196 | "jsx-a11y/no-autofocus": ["error", { ignoreNonDOM: true }], 197 | 198 | // ensure HTML elements do not specify redundant ARIA roles 199 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-redundant-roles.md 200 | "jsx-a11y/no-redundant-roles": "error", 201 | 202 | // media elements must have captions 203 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/media-has-caption.md 204 | "jsx-a11y/media-has-caption": ["error", { 205 | audio: [], 206 | video: [], 207 | track: [], 208 | }], 209 | 210 | // WAI-ARIA roles should not be used to convert an interactive element to non-interactive 211 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-interactive-element-to-noninteractive-role.md 212 | "jsx-a11y/no-interactive-element-to-noninteractive-role": ["error", { 213 | tr: ["none", "presentation"], 214 | }], 215 | 216 | // WAI-ARIA roles should not be used to convert a non-interactive element to interactive 217 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-to-interactive-role.md 218 | "jsx-a11y/no-noninteractive-element-to-interactive-role": ["error", { 219 | ul: [ 220 | "listbox", 221 | "menu", 222 | "menubar", 223 | "radiogroup", 224 | "tablist", 225 | "tree", 226 | "treegrid", 227 | ], 228 | ol: [ 229 | "listbox", 230 | "menu", 231 | "menubar", 232 | "radiogroup", 233 | "tablist", 234 | "tree", 235 | "treegrid", 236 | ], 237 | li: ["menuitem", "option", "row", "tab", "treeitem"], 238 | table: ["grid"], 239 | td: ["gridcell"], 240 | }], 241 | 242 | // Tab key navigation should be limited to elements on the page that can be interacted with. 243 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-tabindex.md 244 | "jsx-a11y/no-noninteractive-tabindex": ["error", { 245 | tags: [], 246 | roles: ["tabpanel"], 247 | }], 248 | 249 | // ensure tags are valid 250 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/0745af376cdc8686d85a361ce36952b1fb1ccf6e/docs/rules/anchor-is-valid.md 251 | "jsx-a11y/anchor-is-valid": ["error", { 252 | components: ["Link"], 253 | specialLink: ["to"], 254 | aspects: ["noHref", "invalidHref", "preferButton"], 255 | }], 256 | 257 | // Ensure the autocomplete attribute is correct and suitable for the form field it is used with 258 | // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/29c68596b15c4ff0a40daae6d4a2670e36e37d35/docs/rules/autocomplete-valid.md 259 | "jsx-a11y/autocomplete-valid": ["off", { 260 | inputComponents: [], 261 | }], 262 | }, 263 | }; 264 | -------------------------------------------------------------------------------- /packages/eslint-config-eser-react/rules/react-hooks.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | "react-hooks", 4 | ], 5 | 6 | parserOptions: { 7 | ecmaFeatures: { 8 | jsx: true, 9 | }, 10 | }, 11 | 12 | rules: { 13 | // Enforce Rules of Hooks 14 | // https://github.com/facebook/react/blob/c11015ff4f610ac2924d1fc6d569a17657a404fd/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js 15 | "react-hooks/rules-of-hooks": "error", 16 | 17 | // Verify the list of the dependencies for Hooks like useEffect and similar 18 | // https://github.com/facebook/react/blob/1204c789776cb01fbaf3e9f032e7e2ba85a44137/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js 19 | "react-hooks/exhaustive-deps": "error", 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /packages/eslint-config-eser-react/rules/react.js: -------------------------------------------------------------------------------- 1 | const baseStyleRules = require("eslint-config-eser/rules/style").rules; 2 | 3 | const dangleRules = baseStyleRules["no-underscore-dangle"]; 4 | 5 | module.exports = { 6 | plugins: [ 7 | "react", 8 | ], 9 | 10 | parserOptions: { 11 | ecmaFeatures: { 12 | jsx: true, 13 | }, 14 | }, 15 | 16 | // View link below for react rules documentation 17 | // https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules 18 | rules: { 19 | "no-underscore-dangle": [ 20 | dangleRules[0], 21 | { 22 | ...dangleRules[1], 23 | allow: dangleRules[1].allow.concat( 24 | ["__REDUX_DEVTOOLS_EXTENSION_COMPOSE__"], 25 | ), 26 | }, 27 | ], 28 | 29 | // Specify whether double or single quotes should be used in JSX attributes 30 | // https://eslint.org/docs/rules/jsx-quotes 31 | "jsx-quotes": ["error", "prefer-double"], 32 | 33 | "class-methods-use-this": ["error", { 34 | exceptMethods: [ 35 | "render", 36 | "getInitialState", 37 | "getDefaultProps", 38 | "getChildContext", 39 | "componentWillMount", 40 | "UNSAFE_componentWillMount", 41 | "componentDidMount", 42 | "componentWillReceiveProps", 43 | "UNSAFE_componentWillReceiveProps", 44 | "shouldComponentUpdate", 45 | "componentWillUpdate", 46 | "UNSAFE_componentWillUpdate", 47 | "componentDidUpdate", 48 | "componentWillUnmount", 49 | "componentDidCatch", 50 | "getSnapshotBeforeUpdate", 51 | ], 52 | }], 53 | 54 | // Prevent missing displayName in a React component definition 55 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md 56 | "react/display-name": ["off", { ignoreTranspilerName: false }], 57 | 58 | // Forbid certain propTypes (any, array, object) 59 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/forbid-prop-types.md 60 | "react/forbid-prop-types": ["error", { 61 | forbid: ["any", "array", "object"], 62 | checkContextTypes: true, 63 | checkChildContextTypes: true, 64 | }], 65 | 66 | // Forbid certain props on DOM Nodes 67 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/forbid-dom-props.md 68 | "react/forbid-dom-props": ["off", { forbid: [] }], 69 | 70 | // Enforce boolean attributes notation in JSX 71 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md 72 | "react/jsx-boolean-value": ["error", "never", { always: [] }], 73 | 74 | // Validate closing bracket location in JSX 75 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md 76 | "react/jsx-closing-bracket-location": ["error", "line-aligned"], 77 | 78 | // Validate closing tag location in JSX 79 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-tag-location.md 80 | "react/jsx-closing-tag-location": "error", 81 | 82 | // Enforce or disallow spaces inside of curly braces in JSX attributes 83 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md 84 | "react/jsx-curly-spacing": ["error", "never", { allowMultiline: true }], 85 | 86 | // Enforce event handler naming conventions in JSX 87 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-handler-names.md 88 | "react/jsx-handler-names": ["off", { 89 | eventHandlerPrefix: "handle", 90 | eventHandlerPropPrefix: "on", 91 | }], 92 | 93 | // Validate props indentation in JSX 94 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent-props.md 95 | "react/jsx-indent-props": ["error", 2], 96 | 97 | // Validate JSX has key prop when in array or iterator 98 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-key.md 99 | "react/jsx-key": "off", 100 | 101 | // Limit maximum of props on a single line in JSX 102 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-max-props-per-line.md 103 | "react/jsx-max-props-per-line": [ 104 | "error", 105 | { maximum: 1, when: "multiline" }, 106 | ], 107 | 108 | // Prevent usage of .bind() in JSX props 109 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md 110 | "react/jsx-no-bind": ["error", { 111 | ignoreRefs: true, 112 | allowArrowFunctions: true, 113 | allowFunctions: false, 114 | allowBind: false, 115 | ignoreDOMComponents: true, 116 | }], 117 | 118 | // Prevent duplicate props in JSX 119 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-duplicate-props.md 120 | "react/jsx-no-duplicate-props": ["error", { ignoreCase: true }], 121 | 122 | // Prevent usage of unwrapped JSX strings 123 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-literals.md 124 | "react/jsx-no-literals": ["off", { noStrings: true }], 125 | 126 | // Disallow undeclared variables in JSX 127 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-undef.md 128 | "react/jsx-no-undef": "error", 129 | 130 | // Enforce PascalCase for user-defined JSX components 131 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md 132 | "react/jsx-pascal-case": ["error", { 133 | allowAllCaps: true, 134 | ignore: [], 135 | }], 136 | 137 | // Enforce propTypes declarations alphabetical sorting 138 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-prop-types.md 139 | "react/sort-prop-types": ["off", { 140 | ignoreCase: true, 141 | callbacksLast: false, 142 | requiredFirst: false, 143 | sortShapeProp: true, 144 | }], 145 | 146 | // Deprecated in favor of react/jsx-sort-props 147 | "react/jsx-sort-prop-types": "off", 148 | 149 | // Enforce props alphabetical sorting 150 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-sort-props.md 151 | "react/jsx-sort-props": ["off", { 152 | ignoreCase: true, 153 | callbacksLast: false, 154 | shorthandFirst: false, 155 | shorthandLast: false, 156 | noSortAlphabetically: false, 157 | reservedFirst: true, 158 | }], 159 | 160 | // Enforce defaultProps declarations alphabetical sorting 161 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-sort-default-props.md 162 | "react/jsx-sort-default-props": ["off", { 163 | ignoreCase: true, 164 | }], 165 | 166 | // Prevent React to be incorrectly marked as unused 167 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-react.md 168 | "react/jsx-uses-react": ["error"], 169 | 170 | // Prevent variables used in JSX to be incorrectly marked as unused 171 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-vars.md 172 | "react/jsx-uses-vars": "error", 173 | 174 | // Prevent usage of dangerous JSX properties 175 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-danger.md 176 | "react/no-danger": "warn", 177 | 178 | // Prevent usage of deprecated methods 179 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-deprecated.md 180 | "react/no-deprecated": ["error"], 181 | 182 | // Prevent usage of setState in componentDidMount 183 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-mount-set-state.md 184 | // this is necessary for server-rendering 185 | "react/no-did-mount-set-state": "off", 186 | 187 | // Prevent usage of setState in componentDidUpdate 188 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-update-set-state.md 189 | "react/no-did-update-set-state": "error", 190 | 191 | // Prevent usage of setState in componentWillUpdate 192 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-will-update-set-state.md 193 | "react/no-will-update-set-state": "error", 194 | 195 | // Prevent direct mutation of this.state 196 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-direct-mutation-state.md 197 | "react/no-direct-mutation-state": "off", 198 | 199 | // Prevent usage of isMounted 200 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-is-mounted.md 201 | "react/no-is-mounted": "error", 202 | 203 | // Prevent multiple component definition per file 204 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md 205 | "react/no-multi-comp": "off", 206 | 207 | // Prevent usage of setState 208 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-set-state.md 209 | "react/no-set-state": "off", 210 | 211 | // Prevent using string references 212 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-string-refs.md 213 | "react/no-string-refs": "error", 214 | 215 | // Prevent usage of unknown DOM property 216 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unknown-property.md 217 | "react/no-unknown-property": "error", 218 | 219 | // Require ES6 class declarations over React.createClass 220 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md 221 | "react/prefer-es6-class": ["error", "always"], 222 | 223 | // Require stateless functions when not using lifecycle methods, setState or ref 224 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md 225 | "react/prefer-stateless-function": [ 226 | "error", 227 | { ignorePureComponents: true }, 228 | ], 229 | 230 | // Prevent missing props validation in a React component definition 231 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prop-types.md 232 | "react/prop-types": ["error", { 233 | ignore: [], 234 | customValidators: [], 235 | skipUndeclared: false, 236 | }], 237 | 238 | // Prevent missing React when using JSX 239 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md 240 | "react/react-in-jsx-scope": "error", 241 | 242 | // Require render() methods to return something 243 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-render-return.md 244 | "react/require-render-return": "error", 245 | 246 | // Prevent extra closing tags for components without children 247 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md 248 | "react/self-closing-comp": "error", 249 | 250 | // Enforce component methods order 251 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/sort-comp.md 252 | "react/sort-comp": ["error", { 253 | order: [ 254 | "static-variables", 255 | "static-methods", 256 | "instance-variables", 257 | "lifecycle", 258 | "/^handle.+$/", 259 | "/^on.+$/", 260 | "getters", 261 | "setters", 262 | "/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/", 263 | "instance-methods", 264 | "everything-else", 265 | "rendering", 266 | ], 267 | groups: { 268 | lifecycle: [ 269 | "displayName", 270 | "propTypes", 271 | "contextTypes", 272 | "childContextTypes", 273 | "mixins", 274 | "statics", 275 | "defaultProps", 276 | "constructor", 277 | "getDefaultProps", 278 | "getInitialState", 279 | "state", 280 | "getChildContext", 281 | "getDerivedStateFromProps", 282 | "componentWillMount", 283 | "UNSAFE_componentWillMount", 284 | "componentDidMount", 285 | "componentWillReceiveProps", 286 | "UNSAFE_componentWillReceiveProps", 287 | "shouldComponentUpdate", 288 | "componentWillUpdate", 289 | "UNSAFE_componentWillUpdate", 290 | "getSnapshotBeforeUpdate", 291 | "componentDidUpdate", 292 | "componentDidCatch", 293 | "componentWillUnmount", 294 | ], 295 | rendering: [ 296 | "/^render.+$/", 297 | "render", 298 | ], 299 | }, 300 | }], 301 | 302 | // Prevent missing parentheses around multilines JSX 303 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-wrap-multilines.md 304 | "react/jsx-wrap-multilines": ["error", { 305 | declaration: "parens-new-line", 306 | assignment: "parens-new-line", 307 | return: "parens-new-line", 308 | arrow: "parens-new-line", 309 | condition: "parens-new-line", 310 | logical: "parens-new-line", 311 | prop: "parens-new-line", 312 | }], 313 | 314 | // Require that the first prop in a JSX element be on a new line when the element is multiline 315 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-first-prop-new-line.md 316 | "react/jsx-first-prop-new-line": ["error", "multiline-multiprop"], 317 | 318 | // Enforce spacing around jsx equals signs 319 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-equals-spacing.md 320 | "react/jsx-equals-spacing": ["error", "never"], 321 | 322 | // Enforce JSX indentation 323 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent.md 324 | "react/jsx-indent": ["error", 2], 325 | 326 | // Disallow target="_blank" on links 327 | // https://github.com/yannickcr/eslint-plugin-react/blob/ac102885765be5ff37847a871f239c6703e1c7cc/docs/rules/jsx-no-target-blank.md 328 | "react/jsx-no-target-blank": ["error", { enforceDynamicLinks: "always" }], 329 | 330 | // only .jsx files may have JSX 331 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-filename-extension.md 332 | "react/jsx-filename-extension": ["error", { extensions: [".jsx", ".tsx"] }], 333 | 334 | // prevent accidental JS comments from being injected into JSX as text 335 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-comment-textnodes.md 336 | "react/jsx-no-comment-textnodes": "error", 337 | 338 | // disallow using React.render/ReactDOM.render's return value 339 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-render-return-value.md 340 | "react/no-render-return-value": "error", 341 | 342 | // require a shouldComponentUpdate method, or PureRenderMixin 343 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-optimization.md 344 | "react/require-optimization": ["off", { allowDecorators: [] }], 345 | 346 | // warn against using findDOMNode() 347 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-find-dom-node.md 348 | "react/no-find-dom-node": "error", 349 | 350 | // Forbid certain props on Components 351 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-component-props.md 352 | "react/forbid-component-props": ["off", { forbid: [] }], 353 | 354 | // Forbid certain elements 355 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-elements.md 356 | "react/forbid-elements": ["off", { forbid: [] }], 357 | 358 | // Prevent problem with children and props.dangerouslySetInnerHTML 359 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-danger-with-children.md 360 | "react/no-danger-with-children": "error", 361 | 362 | // Prevent unused propType definitions 363 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unused-prop-types.md 364 | "react/no-unused-prop-types": ["error", { 365 | customValidators: [], 366 | skipShapeProps: true, 367 | }], 368 | 369 | // Require style prop value be an object or var 370 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/style-prop-object.md 371 | "react/style-prop-object": "error", 372 | 373 | // Prevent invalid characters from appearing in markup 374 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unescaped-entities.md 375 | "react/no-unescaped-entities": "error", 376 | 377 | // Prevent passing of children as props 378 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-children-prop.md 379 | "react/no-children-prop": "error", 380 | 381 | // Validate whitespace in and around the JSX opening and closing brackets 382 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-tag-spacing.md 383 | "react/jsx-tag-spacing": ["error", { 384 | closingSlash: "never", 385 | beforeSelfClosing: "always", 386 | afterOpening: "never", 387 | beforeClosing: "never", 388 | }], 389 | 390 | // Enforce spaces before the closing bracket of self-closing JSX elements 391 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-space-before-closing.md 392 | // Deprecated in favor of jsx-tag-spacing 393 | "react/jsx-space-before-closing": ["off", "always"], 394 | 395 | // Prevent usage of Array index in keys 396 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-array-index-key.md 397 | "react/no-array-index-key": "error", 398 | 399 | // Enforce a defaultProps definition for every prop that is not a required prop 400 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/require-default-props.md 401 | "react/require-default-props": ["error", { 402 | forbidDefaultForRequired: true, 403 | }], 404 | 405 | // Forbids using non-exported propTypes 406 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-foreign-prop-types.md 407 | // this is intentionally set to "warn". it would be "error", 408 | // but it's only critical if you're stripping propTypes in production. 409 | "react/forbid-foreign-prop-types": ["warn", { allowInPropTypes: true }], 410 | 411 | // Prevent void DOM elements from receiving children 412 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/void-dom-elements-no-children.md 413 | "react/void-dom-elements-no-children": "error", 414 | 415 | // Enforce all defaultProps have a corresponding non-required PropType 416 | // https://github.com/yannickcr/eslint-plugin-react/blob/9e13ae2c51e44872b45cc15bf1ac3a72105bdd0e/docs/rules/default-props-match-prop-types.md 417 | "react/default-props-match-prop-types": [ 418 | "error", 419 | { allowRequiredDefaults: false }, 420 | ], 421 | 422 | // Prevent usage of shouldComponentUpdate when extending React.PureComponent 423 | // https://github.com/yannickcr/eslint-plugin-react/blob/9e13ae2c51e44872b45cc15bf1ac3a72105bdd0e/docs/rules/no-redundant-should-component-update.md 424 | "react/no-redundant-should-component-update": "error", 425 | 426 | // Prevent unused state values 427 | // https://github.com/yannickcr/eslint-plugin-react/pull/1103/ 428 | "react/no-unused-state": "error", 429 | 430 | // Enforces consistent naming for boolean props 431 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/boolean-prop-naming.md 432 | "react/boolean-prop-naming": ["off", { 433 | propTypeNames: ["bool", "mutuallyExclusiveTrueProps"], 434 | rule: "^(is|has)[A-Z]([A-Za-z0-9]?)+", 435 | message: "", 436 | }], 437 | 438 | // Prevents common casing typos 439 | // https://github.com/yannickcr/eslint-plugin-react/blob/73abadb697034b5ccb514d79fb4689836fe61f91/docs/rules/no-typos.md 440 | "react/no-typos": "error", 441 | 442 | // Enforce curly braces or disallow unnecessary curly braces in JSX props and/or children 443 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-brace-presence.md 444 | "react/jsx-curly-brace-presence": [ 445 | "error", 446 | { props: "never", children: "never" }, 447 | ], 448 | 449 | // One JSX Element Per Line 450 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-one-expression-per-line.md 451 | "react/jsx-one-expression-per-line": ["error", { allow: "single-child" }], 452 | 453 | // Enforce consistent usage of destructuring assignment of props, state, and context 454 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/destructuring-assignment.md 455 | "react/destructuring-assignment": ["error", "always"], 456 | 457 | // Prevent using this.state within a this.setState 458 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/no-access-state-in-setstate.md 459 | "react/no-access-state-in-setstate": "error", 460 | 461 | // Prevent usage of button elements without an explicit type attribute 462 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/button-has-type.md 463 | "react/button-has-type": ["error", { 464 | button: true, 465 | submit: true, 466 | reset: false, 467 | }], 468 | 469 | // Ensures inline tags are not rendered without spaces between them 470 | "react/jsx-child-element-spacing": "off", 471 | 472 | // Prevent this from being used in stateless functional components 473 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/no-this-in-sfc.md 474 | "react/no-this-in-sfc": "error", 475 | 476 | // Validate JSX maximum depth 477 | // https://github.com/yannickcr/eslint-plugin-react/blob/abe8381c0d6748047224c430ce47f02e40160ed0/docs/rules/jsx-max-depth.md 478 | "react/jsx-max-depth": "off", 479 | 480 | // Disallow multiple spaces between inline JSX props 481 | // https://github.com/yannickcr/eslint-plugin-react/blob/ac102885765be5ff37847a871f239c6703e1c7cc/docs/rules/jsx-props-no-multi-spaces.md 482 | "react/jsx-props-no-multi-spaces": "error", 483 | 484 | // Prevent usage of UNSAFE_ methods 485 | // https://github.com/yannickcr/eslint-plugin-react/blob/157cc932be2cfaa56b3f5b45df6f6d4322a2f660/docs/rules/no-unsafe.md 486 | "react/no-unsafe": "off", 487 | 488 | // Enforce shorthand or standard form for React fragments 489 | // https://github.com/yannickcr/eslint-plugin-react/blob/bc976b837abeab1dffd90ac6168b746a83fc83cc/docs/rules/jsx-fragments.md 490 | "react/jsx-fragments": ["error", "syntax"], 491 | 492 | // Enforce linebreaks in curly braces in JSX attributes and expressions. 493 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-newline.md 494 | "react/jsx-curly-newline": ["error", { 495 | multiline: "consistent", 496 | singleline: "consistent", 497 | }], 498 | 499 | // Enforce state initialization style 500 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/state-in-constructor.md 501 | // TODO: set to "never" once babel-preset-airbnb supports public class fields 502 | "react/state-in-constructor": ["error", "always"], 503 | 504 | // Enforces where React component static properties should be positioned 505 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/static-property-placement.md 506 | // TODO: set to "static public field" once babel-preset-airbnb supports public class fields 507 | "react/static-property-placement": ["error", "property assignment"], 508 | 509 | // Disallow JSX props spreading 510 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-props-no-spreading.md 511 | "react/jsx-props-no-spreading": ["error", { 512 | html: "enforce", 513 | custom: "enforce", 514 | explicitSpread: "ignore", 515 | exceptions: [], 516 | }], 517 | 518 | // Enforce that props are read-only 519 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-read-only-props.md 520 | "react/prefer-read-only-props": "off", 521 | 522 | // Prevent usage of `javascript:` URLs 523 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-script-url.md 524 | // TODO: enable, semver-major 525 | "react/jsx-no-script-url": ["off", [ 526 | { 527 | name: "Link", 528 | props: ["to"], 529 | }, 530 | ]], 531 | 532 | // Disallow unnecessary fragments 533 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-useless-fragment.md 534 | // TODO: enable, semver-major 535 | "react/jsx-no-useless-fragment": "off", 536 | 537 | // Prevent adjacent inline elements not separated by whitespace 538 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-adjacent-inline-elements.md 539 | // TODO: enable? semver-major 540 | "react/no-adjacent-inline-elements": "off", 541 | 542 | // Enforce a specific function type for function components 543 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/function-component-definition.md 544 | // TODO: enable! semver-minor, but do it in a major to be safe 545 | // TODO: investigate if setting namedComponents to expression vs declaration is problematic 546 | "react/function-component-definition": ["off", { 547 | namedComponents: "function-expression", 548 | unnamedComponents: "function-expression", 549 | }], 550 | }, 551 | 552 | settings: { 553 | "import/resolver": { 554 | node: { 555 | extensions: [".js", ".mjs", ".jsx", ".ts", ".tsx", ".d.ts", ".json"], 556 | }, 557 | }, 558 | "react": { 559 | pragma: "React", 560 | version: "detect", 561 | }, 562 | "propWrapperFunctions": [ 563 | "forbidExtraProps", // https://www.npmjs.com/package/airbnb-prop-types 564 | "exact", // https://www.npmjs.com/package/prop-types-exact 565 | "Object.freeze", // https://tc39.github.io/ecma262/#sec-object.freeze 566 | ], 567 | }, 568 | }; 569 | -------------------------------------------------------------------------------- /packages/eslint-config-eser-react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Basic Options */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ 8 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 9 | // "lib": [], /* Specify library files to be included in the compilation. */ 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | // "checkJs": true, /* Report errors in .js files. */ 12 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 13 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 15 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 16 | // "outFile": "./", /* Concatenate and emit output to single file. */ 17 | // "outDir": "./", /* Redirect output structure to the directory. */ 18 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 19 | // "composite": true, /* Enable project compilation */ 20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 21 | // "removeComments": true, /* Do not emit comments to output. */ 22 | // "noEmit": true, /* Do not emit outputs. */ 23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 26 | 27 | /* Strict Type-Checking Options */ 28 | "strict": true, /* Enable all strict type-checking options. */ 29 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 30 | // "strictNullChecks": true, /* Enable strict null checks. */ 31 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 32 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 33 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 34 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 35 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 36 | 37 | /* Additional Checks */ 38 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 39 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 40 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 41 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 42 | 43 | /* Module Resolution Options */ 44 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 45 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 46 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 47 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 48 | // "typeRoots": [], /* List of folders to include type definitions from. */ 49 | // "types": [], /* Type declaration files to be included in compilation. */ 50 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 51 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 52 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 53 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 54 | 55 | /* Source Map Options */ 56 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 58 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 59 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 60 | 61 | /* Experimental Options */ 62 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 63 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 64 | 65 | /* Advanced Options */ 66 | "skipLibCheck": true, /* Skip type checking of declaration files. */ 67 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /packages/eslint-config-eser/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./index.js" 3 | } 4 | -------------------------------------------------------------------------------- /packages/eslint-config-eser/.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /packages/eslint-config-eser/README.md: -------------------------------------------------------------------------------- 1 | # [Eser: JavaScript Style Guide](https://github.com/eserozvataf/eser) 2 | 3 | This package consists of ESLint rule definitions for [eser](https://github.com/eserozvataf/eser). 4 | 5 | To use this package, execute: 6 | 7 | ```sh 8 | npm install eslint eslint-plugin-import eslint-import-resolver-typescript @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-eser --save-dev 9 | ``` 10 | 11 | Then create an `.eslintrc` file: 12 | 13 | ```json 14 | { 15 | "extends": "eser" 16 | } 17 | ``` 18 | 19 | See [main repository](https://github.com/eserozvataf/eser) for further details. 20 | -------------------------------------------------------------------------------- /packages/eslint-config-eser/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | "./rules/best-practices.js", 4 | "./rules/errors.js", 5 | "./rules/node.js", 6 | "./rules/style.js", 7 | "./rules/variables.js", 8 | "./rules/es6.js", 9 | "./rules/imports.js", 10 | "./rules/strict.js", 11 | "./rules/typescript.js", 12 | ].map(require.resolve), 13 | 14 | parserOptions: { 15 | ecmaVersion: 2018, 16 | sourceType: "module", 17 | }, 18 | 19 | rules: {}, 20 | }; 21 | -------------------------------------------------------------------------------- /packages/eslint-config-eser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-eser", 3 | "version": "2.2.6", 4 | "description": "Eser's ESLint config, following our styleguide", 5 | "main": "index.js", 6 | "scripts": { 7 | "cleanup": "rm -rf package-lock.json node_modules/", 8 | "prelint": "# editorconfig-tools check *", 9 | "lint": "eslint ./", 10 | "lint:fix": "eslint --fix ./", 11 | "test": "", 12 | "test:coverage": "" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/eserozvataf/eser" 17 | }, 18 | "keywords": [ 19 | "eslint", 20 | "eslintconfig", 21 | "config", 22 | "eser", 23 | "airbnb", 24 | "javascript", 25 | "styleguide" 26 | ], 27 | "author": "Eser Ozvataf (https://twitter.com/eser)", 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/eserozvataf/eser/issues" 31 | }, 32 | "homepage": "https://github.com/eserozvataf/eser", 33 | "dependencies": { 34 | "confusing-browser-globals": "^1.0.10" 35 | }, 36 | "devDependencies": { 37 | "@typescript-eslint/eslint-plugin": "^4.8.0", 38 | "@typescript-eslint/parser": "^4.8.0", 39 | "editorconfig-tools": "^0.1.1", 40 | "eslint": "^7.13.0", 41 | "eslint-find-rules": "^3.6.1", 42 | "eslint-import-resolver-typescript": "^2.3.0", 43 | "eslint-plugin-import": "^2.22.1", 44 | "typescript": "^4.0.5" 45 | }, 46 | "peerDependencies": { 47 | "@typescript-eslint/eslint-plugin": "^4.8.0", 48 | "@typescript-eslint/parser": "^4.8.0", 49 | "eslint": "^7.13.0", 50 | "eslint-import-resolver-typescript": "^2.3.0", 51 | "eslint-plugin-import": "^2.22.1", 52 | "typescript": "^4.0.5" 53 | }, 54 | "engines": { 55 | "node": ">= 14" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/eslint-config-eser/rules/best-practices.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rules: { 3 | // enforces getter/setter pairs in objects 4 | "accessor-pairs": [ 5 | "error", 6 | { getWithoutSet: true, setWithoutGet: false }, 7 | ], 8 | 9 | // enforces return statements in callbacks of array's methods 10 | // https://eslint.org/docs/rules/array-callback-return 11 | "array-callback-return": ["error", { allowImplicit: false }], 12 | 13 | // treat var statements as if they were block scoped 14 | "block-scoped-var": "error", 15 | 16 | // specify the maximum cyclomatic complexity allowed in a program 17 | "complexity": ["off", 11], 18 | 19 | // enforce that class methods use "this" 20 | // https://eslint.org/docs/rules/class-methods-use-this 21 | "class-methods-use-this": ["error", { 22 | exceptMethods: [], 23 | }], 24 | 25 | // require return statements to either always or never specify values 26 | "consistent-return": "error", 27 | 28 | // specify curly brace conventions for all control statements 29 | "curly": ["error", "all"], // multi-line 30 | 31 | // require default case in switch statements 32 | "default-case": ["error", { commentPattern: "^no default$" }], 33 | 34 | // Enforce default clauses in switch statements to be last 35 | // https://eslint.org/docs/rules/default-case-last 36 | "default-case-last": "error", 37 | 38 | // https://eslint.org/docs/rules/default-param-last 39 | "default-param-last": "error", 40 | 41 | // encourages use of dot notation whenever possible 42 | "dot-notation": "off", 43 | "@typescript-eslint/dot-notation": ["error", { allowKeywords: true }], 44 | 45 | // enforces consistent newlines before or after dots 46 | // https://eslint.org/docs/rules/dot-location 47 | "dot-location": ["error", "property"], 48 | 49 | // require the use of === and !== 50 | // https://eslint.org/docs/rules/eqeqeq 51 | "eqeqeq": ["error", "always", { null: "ignore" }], 52 | 53 | // Require grouped accessor pairs in object literals and classes 54 | // https://eslint.org/docs/rules/grouped-accessor-pairs 55 | "grouped-accessor-pairs": ["error", "getBeforeSet"], 56 | 57 | // make sure for-in loops have an if statement 58 | "guard-for-in": "error", 59 | 60 | // enforce a maximum number of classes per file 61 | // https://eslint.org/docs/rules/max-classes-per-file 62 | "max-classes-per-file": ["error", 1], 63 | 64 | // disallow the use of alert, confirm, and prompt 65 | "no-alert": "warn", 66 | 67 | // disallow use of arguments.caller or arguments.callee 68 | "no-caller": "error", 69 | 70 | // disallow lexical declarations in case/default clauses 71 | // https://eslint.org/docs/rules/no-case-declarations.html 72 | "no-case-declarations": "error", 73 | 74 | // Disallow returning value in constructor 75 | // https://eslint.org/docs/rules/no-constructor-return 76 | "no-constructor-return": "error", 77 | 78 | // disallow division operators explicitly at beginning of regular expression 79 | // https://eslint.org/docs/rules/no-div-regex 80 | "no-div-regex": "off", 81 | 82 | // disallow else after a return in an if 83 | // https://eslint.org/docs/rules/no-else-return 84 | "no-else-return": ["error", { allowElseIf: false }], 85 | 86 | // disallow empty functions, except for standalone funcs/arrows 87 | // https://eslint.org/docs/rules/no-empty-function 88 | "no-empty-function": "off", 89 | "@typescript-eslint/no-empty-function": ["error", { 90 | allow: [ 91 | "arrowFunctions", 92 | "functions", 93 | "methods", 94 | "asyncFunctions", 95 | "asyncMethods", 96 | ], 97 | }], 98 | 99 | // disallow empty destructuring patterns 100 | // https://eslint.org/docs/rules/no-empty-pattern 101 | "no-empty-pattern": "error", 102 | 103 | // disallow comparisons to null without a type-checking operator 104 | "no-eq-null": "off", 105 | 106 | // disallow use of eval() 107 | "no-eval": "error", 108 | 109 | // disallow adding to native types 110 | "no-extend-native": "error", 111 | 112 | // disallow unnecessary function binding 113 | "no-extra-bind": "error", 114 | 115 | // disallow Unnecessary Labels 116 | // https://eslint.org/docs/rules/no-extra-label 117 | "no-extra-label": "error", 118 | 119 | // disallow fallthrough of case statements 120 | "no-fallthrough": "error", 121 | 122 | // disallow the use of leading or trailing decimal points in numeric literals 123 | "no-floating-decimal": "error", 124 | 125 | // disallow reassignments of native objects or read-only globals 126 | // https://eslint.org/docs/rules/no-global-assign 127 | "no-global-assign": ["error", { exceptions: [] }], 128 | // deprecated in favor of no-global-assign 129 | "no-native-reassign": "off", 130 | 131 | // disallow implicit type conversions 132 | // https://eslint.org/docs/rules/no-implicit-coercion 133 | "no-implicit-coercion": ["off", { 134 | boolean: true, 135 | number: true, 136 | string: true, 137 | allow: [], 138 | }], 139 | 140 | // disallow var and named functions in global scope 141 | // https://eslint.org/docs/rules/no-implicit-globals 142 | "no-implicit-globals": "off", 143 | 144 | // disallow use of eval()-like methods 145 | "no-implied-eval": "off", 146 | "@typescript-eslint/no-implied-eval": "error", 147 | 148 | // disallow this keywords outside of classes or class-like objects 149 | "no-invalid-this": "off", 150 | 151 | // disallow usage of __iterator__ property 152 | "no-iterator": "error", 153 | 154 | // disallow use of labels for anything other then loops and switches 155 | "no-labels": ["error", { allowLoop: false, allowSwitch: false }], 156 | 157 | // disallow unnecessary nested blocks 158 | "no-lone-blocks": "error", 159 | 160 | // disallow creation of functions within loops 161 | "no-loop-func": "off", 162 | "@typescript-eslint/no-loop-func": "error", 163 | 164 | // disallow magic numbers 165 | // https://eslint.org/docs/rules/no-magic-numbers 166 | "no-magic-numbers": "off", 167 | "@typescript-eslint/no-magic-numbers": ["off", { 168 | ignore: [], 169 | ignoreArrayIndexes: true, 170 | enforceConst: true, 171 | detectObjects: false, 172 | }], 173 | 174 | // disallow use of multiple spaces 175 | "no-multi-spaces": ["error", { 176 | ignoreEOLComments: false, 177 | }], 178 | 179 | // disallow use of multiline strings 180 | "no-multi-str": "error", 181 | 182 | // disallow use of new operator when not part of the assignment or comparison 183 | "no-new": "error", 184 | 185 | // disallow use of new operator for Function object 186 | "no-new-func": "error", 187 | 188 | // disallows creating new instances of String, Number, and Boolean 189 | "no-new-wrappers": "error", 190 | 191 | // disallow use of (old style) octal literals 192 | "no-octal": "error", 193 | 194 | // disallow use of octal escape sequences in string literals, such as 195 | // var foo = 'Copyright \251'; 196 | "no-octal-escape": "error", 197 | 198 | // disallow reassignment of function parameters 199 | // disallow parameter object manipulation except for specific exclusions 200 | // rule: https://eslint.org/docs/rules/no-param-reassign.html 201 | "no-param-reassign": ["error", { 202 | props: true, 203 | ignorePropertyModificationsFor: [ 204 | "acc", // for reduce accumulators 205 | "accumulator", // for reduce accumulators 206 | "e", // for e.returnvalue 207 | "ctx", // for Koa routing 208 | "context", // for Koa routing 209 | "req", // for Express requests 210 | "request", // for Express requests 211 | "res", // for Express responses 212 | "response", // for Express responses 213 | "$scope", // for Angular 1 scopes 214 | "staticContext", // for ReactRouter context 215 | ], 216 | }], 217 | 218 | // disallow usage of __proto__ property 219 | "no-proto": "error", 220 | 221 | // disallow declaring the same variable more then once 222 | "no-redeclare": "off", 223 | "@typescript-eslint/no-redeclare": "error", 224 | 225 | // disallow certain object properties 226 | // https://eslint.org/docs/rules/no-restricted-properties 227 | "no-restricted-properties": ["error", { 228 | object: "arguments", 229 | property: "callee", 230 | message: "arguments.callee is deprecated", 231 | }, { 232 | object: "global", 233 | property: "isFinite", 234 | message: "Please use Number.isFinite instead", 235 | }, { 236 | object: "self", 237 | property: "isFinite", 238 | message: "Please use Number.isFinite instead", 239 | }, { 240 | object: "window", 241 | property: "isFinite", 242 | message: "Please use Number.isFinite instead", 243 | }, { 244 | object: "global", 245 | property: "isNaN", 246 | message: "Please use Number.isNaN instead", 247 | }, { 248 | object: "self", 249 | property: "isNaN", 250 | message: "Please use Number.isNaN instead", 251 | }, { 252 | object: "window", 253 | property: "isNaN", 254 | message: "Please use Number.isNaN instead", 255 | }, { 256 | property: "__defineGetter__", 257 | message: "Please use Object.defineProperty instead.", 258 | }, { 259 | property: "__defineSetter__", 260 | message: "Please use Object.defineProperty instead.", 261 | }, { 262 | object: "Math", 263 | property: "pow", 264 | message: "Use the exponentiation operator (**) instead.", 265 | }], 266 | 267 | // disallow use of assignment in return statement 268 | "no-return-assign": ["error", "always"], 269 | 270 | // disallow redundant `return await` 271 | "no-return-await": "error", 272 | 273 | // disallow use of `javascript:` urls. 274 | "no-script-url": "error", 275 | 276 | // disallow self assignment 277 | // https://eslint.org/docs/rules/no-self-assign 278 | "no-self-assign": ["error", { 279 | props: true, 280 | }], 281 | 282 | // disallow comparisons where both sides are exactly the same 283 | "no-self-compare": "error", 284 | 285 | // disallow use of comma operator 286 | "no-sequences": "error", 287 | 288 | // restrict what can be thrown as an exception 289 | "no-throw-literal": "off", 290 | "@typescript-eslint/no-throw-literal": "error", 291 | 292 | // disallow unmodified conditions of loops 293 | // https://eslint.org/docs/rules/no-unmodified-loop-condition 294 | "no-unmodified-loop-condition": "off", 295 | 296 | // disallow usage of expressions in statement position 297 | "no-unused-expressions": "off", 298 | "@typescript-eslint/no-unused-expressions": ["error", { 299 | allowShortCircuit: false, 300 | allowTernary: false, 301 | allowTaggedTemplates: false, 302 | }], 303 | 304 | // disallow unused labels 305 | // https://eslint.org/docs/rules/no-unused-labels 306 | "no-unused-labels": "error", 307 | 308 | // disallow unnecessary .call() and .apply() 309 | "no-useless-call": "off", 310 | 311 | // Disallow unnecessary catch clauses 312 | // https://eslint.org/docs/rules/no-useless-catch 313 | "no-useless-catch": "error", 314 | 315 | // disallow useless string concatenation 316 | // https://eslint.org/docs/rules/no-useless-concat 317 | "no-useless-concat": "error", 318 | 319 | // disallow unnecessary string escaping 320 | // https://eslint.org/docs/rules/no-useless-escape 321 | "no-useless-escape": "error", 322 | 323 | // disallow redundant return; keywords 324 | // https://eslint.org/docs/rules/no-useless-return 325 | "no-useless-return": "error", 326 | 327 | // disallow use of void operator 328 | // https://eslint.org/docs/rules/no-void 329 | "no-void": "error", 330 | 331 | // disallow usage of configurable warning terms in comments: e.g. todo 332 | "no-warning-comments": [ 333 | "off", 334 | { terms: ["todo", "fixme", "xxx"], location: "start" }, 335 | ], 336 | 337 | // disallow use of the with statement 338 | "no-with": "error", 339 | 340 | // require using Error objects as Promise rejection reasons 341 | // https://eslint.org/docs/rules/prefer-promise-reject-errors 342 | "prefer-promise-reject-errors": ["error", { allowEmptyReject: true }], 343 | 344 | // Suggest using named capture group in regular expression 345 | // https://eslint.org/docs/rules/prefer-named-capture-group 346 | "prefer-named-capture-group": "off", 347 | 348 | // https://eslint.org/docs/rules/prefer-regex-literals 349 | "prefer-regex-literals": ["error", { disallowRedundantWrapping: true }], 350 | 351 | // require use of the second argument for parseInt() 352 | "radix": "error", 353 | 354 | // require `await` in `async function` (note: this is a horrible rule that should never be used) 355 | // https://eslint.org/docs/rules/require-await 356 | "require-await": "off", 357 | 358 | // Enforce the use of u flag on RegExp 359 | // https://eslint.org/docs/rules/require-unicode-regexp 360 | "require-unicode-regexp": "off", 361 | 362 | // requires to declare all vars on top of their containing scope 363 | "vars-on-top": "error", 364 | 365 | // require immediate function invocation to be wrapped in parentheses 366 | // https://eslint.org/docs/rules/wrap-iife.html 367 | "wrap-iife": ["error", "outside", { functionPrototypeMethods: false }], 368 | 369 | // require or disallow Yoda conditions 370 | "yoda": ["error", "never"], 371 | }, 372 | }; 373 | -------------------------------------------------------------------------------- /packages/eslint-config-eser/rules/errors.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rules: { 3 | // Enforce “for” loop update clause moving the counter in the right direction 4 | // https://eslint.org/docs/rules/for-direction 5 | "for-direction": "error", 6 | 7 | // Enforces that a return statement is present in property getters 8 | // https://eslint.org/docs/rules/getter-return 9 | "getter-return": ["error", { allowImplicit: true }], 10 | 11 | // disallow using an async function as a Promise executor 12 | // https://eslint.org/docs/rules/no-async-promise-executor 13 | "no-async-promise-executor": "error", 14 | 15 | // Disallow await inside of loops 16 | // https://eslint.org/docs/rules/no-await-in-loop 17 | "no-await-in-loop": "error", 18 | 19 | // Disallow comparisons to negative zero 20 | // https://eslint.org/docs/rules/no-compare-neg-zero 21 | "no-compare-neg-zero": "error", 22 | 23 | // disallow assignment in conditional expressions 24 | "no-cond-assign": ["error", "always"], 25 | 26 | // disallow use of console 27 | "no-console": "warn", 28 | 29 | // disallow use of constant expressions in conditions 30 | "no-constant-condition": "warn", 31 | 32 | // disallow control characters in regular expressions 33 | "no-control-regex": "error", 34 | 35 | // disallow use of debugger 36 | "no-debugger": "error", 37 | 38 | // disallow duplicate arguments in functions 39 | "no-dupe-args": "error", 40 | 41 | // Disallow duplicate conditions in if-else-if chains 42 | // https://eslint.org/docs/rules/no-dupe-else-if 43 | "no-dupe-else-if": "error", 44 | 45 | // disallow duplicate keys when creating object literals 46 | "no-dupe-keys": "error", 47 | 48 | // disallow a duplicate case label. 49 | "no-duplicate-case": "error", 50 | 51 | // disallow empty statements 52 | "no-empty": "error", 53 | 54 | // disallow the use of empty character classes in regular expressions 55 | "no-empty-character-class": "error", 56 | 57 | // disallow assigning to the exception in a catch block 58 | "no-ex-assign": "error", 59 | 60 | // disallow double-negation boolean casts in a boolean context 61 | // https://eslint.org/docs/rules/no-extra-boolean-cast 62 | "no-extra-boolean-cast": "error", 63 | 64 | // disallow unnecessary parentheses 65 | // https://eslint.org/docs/rules/no-extra-parens 66 | "no-extra-parens": "off", 67 | "@typescript-eslint/no-extra-parens": ["off", "all", { 68 | conditionalAssign: true, 69 | nestedBinaryExpressions: false, 70 | returnAssign: false, 71 | ignoreJSX: "all", // delegate to eslint-plugin-react 72 | enforceForArrowConditionals: false, 73 | }], 74 | 75 | // disallow unnecessary semicolons 76 | "no-extra-semi": "off", 77 | "@typescript-eslint/no-extra-semi": "error", 78 | 79 | // disallow overwriting functions written as function declarations 80 | "no-func-assign": "error", 81 | 82 | // https://eslint.org/docs/rules/no-import-assign 83 | "no-import-assign": "error", 84 | 85 | // disallow function or variable declarations in nested blocks 86 | "no-inner-declarations": "error", 87 | 88 | // disallow invalid regular expression strings in the RegExp constructor 89 | "no-invalid-regexp": "error", 90 | 91 | // disallow irregular whitespace outside of strings and comments 92 | "no-irregular-whitespace": "error", 93 | 94 | // Disallow Number Literals That Lose Precision 95 | // https://eslint.org/docs/rules/no-loss-of-precision 96 | "no-loss-of-precision": "error", 97 | 98 | // Disallow characters which are made with multiple code points in character class syntax 99 | // https://eslint.org/docs/rules/no-misleading-character-class 100 | "no-misleading-character-class": "error", 101 | 102 | // disallow the use of object properties of the global object (Math and JSON) as functions 103 | "no-obj-calls": "error", 104 | 105 | // Disallow returning values from Promise executor functions 106 | // https://eslint.org/docs/rules/no-promise-executor-return 107 | "no-promise-executor-return": "error", 108 | 109 | // disallow use of Object.prototypes builtins directly 110 | // https://eslint.org/docs/rules/no-prototype-builtins 111 | "no-prototype-builtins": "error", 112 | 113 | // disallow multiple spaces in a regular expression literal 114 | "no-regex-spaces": "error", 115 | 116 | // Disallow returning values from setters 117 | // https://eslint.org/docs/rules/no-setter-return 118 | "no-setter-return": "error", 119 | 120 | // disallow sparse arrays 121 | "no-sparse-arrays": "error", 122 | 123 | // Disallow template literal placeholder syntax in regular strings 124 | // https://eslint.org/docs/rules/no-template-curly-in-string 125 | "no-template-curly-in-string": "error", 126 | 127 | // Avoid code that looks like two expressions but is actually one 128 | // https://eslint.org/docs/rules/no-unexpected-multiline 129 | "no-unexpected-multiline": "error", 130 | 131 | // disallow unreachable statements after a return, throw, continue, or break statement 132 | "no-unreachable": "error", 133 | 134 | // Disallow loops with a body that allows only one iteration 135 | // https://eslint.org/docs/rules/no-unreachable-loop 136 | "no-unreachable-loop": ["error", { 137 | ignore: [], // WhileStatement, DoWhileStatement, ForStatement, ForInStatement, ForOfStatement 138 | }], 139 | 140 | // disallow return/throw/break/continue inside finally blocks 141 | // https://eslint.org/docs/rules/no-unsafe-finally 142 | "no-unsafe-finally": "error", 143 | 144 | // disallow negating the left operand of relational operators 145 | // https://eslint.org/docs/rules/no-unsafe-negation 146 | "no-unsafe-negation": "error", 147 | 148 | // Disallow useless backreferences in regular expressions 149 | // https://eslint.org/docs/rules/no-useless-backreference 150 | "no-useless-backreference": "error", 151 | 152 | // disallow negation of the left operand of an in expression 153 | // deprecated in favor of no-unsafe-negation 154 | "no-negated-in-lhs": "off", 155 | 156 | // Disallow assignments that can lead to race conditions due to usage of await or yield 157 | // https://eslint.org/docs/rules/require-atomic-updates 158 | // note: not enabled because it is very buggy 159 | "require-atomic-updates": "off", 160 | 161 | // disallow comparisons with the value NaN 162 | "use-isnan": "error", 163 | 164 | // ensure JSDoc comments are valid 165 | // https://eslint.org/docs/rules/valid-jsdoc 166 | "valid-jsdoc": "error", 167 | 168 | // ensure that the results of typeof are compared against a valid string 169 | // https://eslint.org/docs/rules/valid-typeof 170 | "valid-typeof": ["error", { requireStringLiterals: true }], 171 | }, 172 | }; 173 | -------------------------------------------------------------------------------- /packages/eslint-config-eser/rules/es6.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | es6: true, 4 | }, 5 | parserOptions: { 6 | ecmaVersion: 6, 7 | sourceType: "module", 8 | ecmaFeatures: { 9 | generators: false, 10 | objectLiteralDuplicateProperties: false, 11 | }, 12 | }, 13 | 14 | rules: { 15 | // enforces no braces where they can be omitted 16 | // https://eslint.org/docs/rules/arrow-body-style 17 | "arrow-body-style": ["error", "as-needed", { 18 | requireReturnForObjectLiteral: true, 19 | }], 20 | 21 | // require parens in arrow function arguments 22 | // https://eslint.org/docs/rules/arrow-parens 23 | "arrow-parens": ["error", "always", { 24 | requireForBlockBody: true, 25 | }], 26 | 27 | // require space before/after arrow function's arrow 28 | // https://eslint.org/docs/rules/arrow-spacing 29 | "arrow-spacing": ["error", { before: true, after: true }], 30 | 31 | // verify super() callings in constructors 32 | "constructor-super": "error", 33 | 34 | // enforce the spacing around the * in generator functions 35 | // https://eslint.org/docs/rules/generator-star-spacing 36 | "generator-star-spacing": ["error", { before: false, after: true }], 37 | 38 | // disallow modifying variables of class declarations 39 | // https://eslint.org/docs/rules/no-class-assign 40 | "no-class-assign": "error", 41 | 42 | // disallow arrow functions where they could be confused with comparisons 43 | // https://eslint.org/docs/rules/no-confusing-arrow 44 | "no-confusing-arrow": ["error", { 45 | allowParens: true, 46 | }], 47 | 48 | // disallow modifying variables that are declared using const 49 | "no-const-assign": "error", 50 | 51 | // disallow duplicate class members 52 | // https://eslint.org/docs/rules/no-dupe-class-members 53 | "no-dupe-class-members": "off", 54 | "@typescript-eslint/no-dupe-class-members": "error", 55 | 56 | // disallow importing from the same path more than once 57 | // https://eslint.org/docs/rules/no-duplicate-imports 58 | // replaced by https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md 59 | "no-duplicate-imports": "off", 60 | 61 | // disallow symbol constructor 62 | // https://eslint.org/docs/rules/no-new-symbol 63 | "no-new-symbol": "error", 64 | 65 | // Disallow specified names in exports 66 | // https://eslint.org/docs/rules/no-restricted-exports 67 | "no-restricted-exports": ["error", { 68 | restrictedNamedExports: [ 69 | // "default", // use `export default` to provide a default export 70 | "then", // this will cause tons of confusion when your module is dynamically `import()`ed 71 | ], 72 | }], 73 | 74 | // disallow specific imports 75 | // https://eslint.org/docs/rules/no-restricted-imports 76 | "no-restricted-imports": ["off", { 77 | paths: [], 78 | patterns: [], 79 | }], 80 | 81 | // disallow to use this/super before super() calling in constructors. 82 | // https://eslint.org/docs/rules/no-this-before-super 83 | "no-this-before-super": "error", 84 | 85 | // disallow useless computed property keys 86 | // https://eslint.org/docs/rules/no-useless-computed-key 87 | "no-useless-computed-key": "error", 88 | 89 | // disallow unnecessary constructor 90 | // https://eslint.org/docs/rules/no-useless-constructor 91 | "no-useless-constructor": "off", 92 | "@typescript-eslint/no-useless-constructor": "error", 93 | 94 | // disallow renaming import, export, and destructured assignments to the same name 95 | // https://eslint.org/docs/rules/no-useless-rename 96 | "no-useless-rename": ["error", { 97 | ignoreDestructuring: false, 98 | ignoreImport: false, 99 | ignoreExport: false, 100 | }], 101 | 102 | // require let or const instead of var 103 | "no-var": "error", 104 | 105 | // require method and property shorthand syntax for object literals 106 | // https://eslint.org/docs/rules/object-shorthand 107 | "object-shorthand": ["error", "always", { 108 | ignoreConstructors: false, 109 | avoidQuotes: true, 110 | }], 111 | 112 | // suggest using arrow functions as callbacks 113 | "prefer-arrow-callback": ["error", { 114 | allowNamedFunctions: false, 115 | allowUnboundThis: true, 116 | }], 117 | 118 | // suggest using of const declaration for variables that are never modified after declared 119 | "prefer-const": ["error", { 120 | destructuring: "any", 121 | ignoreReadBeforeAssign: true, 122 | }], 123 | 124 | // Prefer destructuring from arrays and objects 125 | // https://eslint.org/docs/rules/prefer-destructuring 126 | "prefer-destructuring": ["error", { 127 | VariableDeclarator: { 128 | array: false, 129 | object: true, 130 | }, 131 | AssignmentExpression: { 132 | array: true, 133 | object: false, 134 | }, 135 | }, { 136 | enforceForRenamedProperties: false, 137 | }], 138 | 139 | // disallow parseInt() in favor of binary, octal, and hexadecimal literals 140 | // https://eslint.org/docs/rules/prefer-numeric-literals 141 | "prefer-numeric-literals": "error", 142 | 143 | // suggest using Reflect methods where applicable 144 | // https://eslint.org/docs/rules/prefer-reflect 145 | "prefer-reflect": "off", 146 | 147 | // use rest parameters instead of arguments 148 | // https://eslint.org/docs/rules/prefer-rest-params 149 | "prefer-rest-params": "error", 150 | 151 | // suggest using the spread operator instead of .apply() 152 | // https://eslint.org/docs/rules/prefer-spread 153 | "prefer-spread": "error", 154 | 155 | // suggest using template literals instead of string concatenation 156 | // https://eslint.org/docs/rules/prefer-template 157 | "prefer-template": "error", 158 | 159 | // disallow generator functions that do not have yield 160 | // https://eslint.org/docs/rules/require-yield 161 | "require-yield": "error", 162 | 163 | // enforce spacing between object rest-spread 164 | // https://eslint.org/docs/rules/rest-spread-spacing 165 | "rest-spread-spacing": ["error", "never"], 166 | 167 | // import sorting 168 | // https://eslint.org/docs/rules/sort-imports 169 | "sort-imports": ["off", { 170 | ignoreCase: false, 171 | ignoreDeclarationSort: false, 172 | ignoreMemberSort: false, 173 | memberSyntaxSortOrder: ["none", "all", "multiple", "single"], 174 | }], 175 | 176 | // require a Symbol description 177 | // https://eslint.org/docs/rules/symbol-description 178 | "symbol-description": "error", 179 | 180 | // enforce usage of spacing in template strings 181 | // https://eslint.org/docs/rules/template-curly-spacing 182 | "template-curly-spacing": "error", 183 | 184 | // enforce spacing around the * in yield* expressions 185 | // https://eslint.org/docs/rules/yield-star-spacing 186 | "yield-star-spacing": ["error", "after"], 187 | }, 188 | }; 189 | -------------------------------------------------------------------------------- /packages/eslint-config-eser/rules/imports.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | es6: true, 4 | }, 5 | parserOptions: { 6 | ecmaVersion: 6, 7 | sourceType: "module", 8 | }, 9 | plugins: [ 10 | "import", 11 | ], 12 | 13 | settings: { 14 | "import/resolver": { 15 | node: { 16 | extensions: [".js", ".mjs", ".ts", ".d.ts", ".json"], 17 | }, 18 | }, 19 | "import/extensions": [ 20 | ".js", 21 | ".mjs", 22 | ".jsx", 23 | ".ts", 24 | ".tsx", 25 | ".d.ts", 26 | ], 27 | "import/core-modules": [], 28 | "import/ignore": [ 29 | // "node_modules", 30 | "\\.(scss|sass|css|less|svg|json)$", 31 | ], 32 | "import/external-module-folders": [ 33 | "node_modules", 34 | "node_modules/@types", 35 | ], 36 | }, 37 | 38 | rules: { 39 | // Static analysis: 40 | 41 | // ensure imports point to files/modules that can be resolved 42 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unresolved.md 43 | "import/no-unresolved": ["error", { commonjs: true, caseSensitive: true }], 44 | 45 | // ensure named imports coupled with named exports 46 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/named.md#when-not-to-use-it 47 | "import/named": "error", 48 | 49 | // ensure default import coupled with default export 50 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/default.md#when-not-to-use-it 51 | "import/default": "off", 52 | 53 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/namespace.md 54 | "import/namespace": "off", 55 | 56 | // Helpful warnings: 57 | 58 | // disallow invalid exports, e.g. multiple defaults 59 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/export.md 60 | "import/export": "error", 61 | 62 | // do not allow a default import name to match a named export 63 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-as-default.md 64 | "import/no-named-as-default": "error", 65 | 66 | // warn on accessing default export property names that are also named exports 67 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-as-default-member.md 68 | "import/no-named-as-default-member": "error", 69 | 70 | // disallow use of jsdoc-marked-deprecated imports 71 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-deprecated.md 72 | "import/no-deprecated": "off", 73 | 74 | // Forbid the use of extraneous packages 75 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-extraneous-dependencies.md 76 | // paths are treated both as absolute paths, and relative to process.cwd() 77 | "import/no-extraneous-dependencies": ["error", { 78 | devDependencies: [ 79 | "test/**", // tape, common npm pattern 80 | "tests/**", // also common npm pattern 81 | "spec/**", // mocha, rspec-like pattern 82 | "**/__tests__/**", // jest pattern 83 | "**/__mocks__/**", // jest pattern 84 | "test.{js,jsx,ts,tsx}", // repos with a single test file 85 | "test-*.{js,jsx,ts,tsx}", // repos with multiple top-level test files 86 | "**/*{.,_}{test,spec}.{js,jsx,ts,tsx}", // tests where the extension or filename suffix denotes that it is a test 87 | "**/jest.config.js", // jest config 88 | "**/jest.setup.js", // jest setup 89 | "**/vue.config.js", // vue-cli config 90 | "**/webpack.config.js", // webpack config 91 | "**/webpack.config.*.js", // webpack config 92 | "**/rollup.config.js", // rollup config 93 | "**/rollup.config.*.js", // rollup config 94 | "**/gulpfile.js", // gulp config 95 | "**/gulpfile.*.js", // gulp config 96 | "**/Gruntfile{,.js}", // grunt config 97 | "**/protractor.conf.js", // protractor config 98 | "**/protractor.conf.*.js", // protractor config 99 | "**/karma.conf.js", // karma config 100 | "**/.eslintrc.js", // eslint config 101 | ], 102 | optionalDependencies: false, 103 | }], 104 | 105 | // Forbid mutable exports 106 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-mutable-exports.md 107 | "import/no-mutable-exports": "error", 108 | 109 | // Module systems: 110 | 111 | // disallow require() 112 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-commonjs.md 113 | "import/no-commonjs": "off", 114 | 115 | // disallow AMD require/define 116 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-amd.md 117 | "import/no-amd": "error", 118 | 119 | // No Node.js builtin modules 120 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-nodejs-modules.md 121 | // TODO: enable? 122 | "import/no-nodejs-modules": "off", 123 | 124 | // Style guide: 125 | 126 | // disallow non-import statements appearing before import statements 127 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/first.md 128 | "import/first": "error", 129 | 130 | // disallow non-import statements appearing before import statements 131 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/imports-first.md 132 | // deprecated: use `import/first` 133 | "import/imports-first": "off", 134 | 135 | // disallow duplicate imports 136 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md 137 | "import/no-duplicates": "error", 138 | 139 | // disallow namespace imports 140 | // TODO: enable? 141 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-namespace.md 142 | "import/no-namespace": "off", 143 | 144 | // Ensure consistent use of file extension within the import path 145 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md 146 | "import/extensions": ["error", "ignorePackages"], 147 | 148 | // ensure absolute imports are above relative imports and that unassigned imports are ignored 149 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/order.md 150 | // TODO: enforce a stricter convention in module import order? 151 | "import/order": [ 152 | "error", 153 | { groups: [["builtin", "external", "internal"]] }, 154 | ], 155 | 156 | // Require a newline after the last import/require in a group 157 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/newline-after-import.md 158 | "import/newline-after-import": "error", 159 | 160 | // Require modules with a single export to use a default export 161 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/prefer-default-export.md 162 | "import/prefer-default-export": "off", 163 | 164 | // Restrict which files can be imported in a given folder 165 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-restricted-paths.md 166 | "import/no-restricted-paths": "off", 167 | 168 | // Forbid modules to have too many dependencies 169 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/max-dependencies.md 170 | "import/max-dependencies": ["off", { max: 10 }], 171 | 172 | // Forbid import of modules using absolute paths 173 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-absolute-path.md 174 | "import/no-absolute-path": "error", 175 | 176 | // Forbid require() calls with expressions 177 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-dynamic-require.md 178 | "import/no-dynamic-require": "error", 179 | 180 | // prevent importing the submodules of other modules 181 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-internal-modules.md 182 | "import/no-internal-modules": ["off", { 183 | allow: [], 184 | }], 185 | 186 | // Warn if a module could be mistakenly parsed as a script by a consumer 187 | // leveraging Unambiguous JavaScript Grammar 188 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/unambiguous.md 189 | // this should not be enabled until this proposal has at least been *presented* to TC39. 190 | // At the moment, it's not a thing. 191 | "import/unambiguous": "off", 192 | 193 | // Forbid Webpack loader syntax in imports 194 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-webpack-loader-syntax.md 195 | "import/no-webpack-loader-syntax": "error", 196 | 197 | // Prevent unassigned imports 198 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unassigned-import.md 199 | // importing for side effects is perfectly acceptable, if you need side effects. 200 | "import/no-unassigned-import": "off", 201 | 202 | // Prevent importing the default as if it were named 203 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-default.md 204 | "import/no-named-default": "error", 205 | 206 | // Reports if a module's default export is unnamed 207 | // https://github.com/benmosher/eslint-plugin-import/blob/d9b712ac7fd1fddc391f7b234827925c160d956f/docs/rules/no-anonymous-default-export.md 208 | "import/no-anonymous-default-export": ["off", { 209 | allowArray: false, 210 | allowArrowFunction: false, 211 | allowAnonymousClass: false, 212 | allowAnonymousFunction: false, 213 | allowLiteral: false, 214 | allowObject: false, 215 | }], 216 | 217 | // This rule enforces that all exports are declared at the bottom of the file. 218 | // https://github.com/benmosher/eslint-plugin-import/blob/98acd6afd04dcb6920b81330114e146dc8532ea4/docs/rules/exports-last.md 219 | "import/exports-last": "error", 220 | 221 | // Reports when named exports are not grouped together in a single export declaration 222 | // or when multiple assignments to CommonJS module.exports or exports object are present 223 | // in a single file. 224 | // https://github.com/benmosher/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/group-exports.md 225 | "import/group-exports": "error", 226 | 227 | // forbid default exports. this is a terrible rule, do not use it. 228 | // https://github.com/benmosher/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/no-default-export.md 229 | "import/no-default-export": "off", 230 | 231 | // Prohibit named exports. this is a terrible rule, do not use it. 232 | // https://github.com/benmosher/eslint-plugin-import/blob/1ec80fa35fa1819e2d35a70e68fb6a149fb57c5e/docs/rules/no-named-export.md 233 | "import/no-named-export": "off", 234 | 235 | // Forbid a module from importing itself 236 | // https://github.com/benmosher/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/no-self-import.md 237 | "import/no-self-import": "error", 238 | 239 | // Forbid cyclical dependencies between modules 240 | // https://github.com/benmosher/eslint-plugin-import/blob/d81f48a2506182738409805f5272eff4d77c9348/docs/rules/no-cycle.md 241 | "import/no-cycle": ["error", { maxDepth: "∞" }], 242 | 243 | // Ensures that there are no useless path segments 244 | // https://github.com/benmosher/eslint-plugin-import/blob/ebafcbf59ec9f653b2ac2a0156ca3bcba0a7cf57/docs/rules/no-useless-path-segments.md 245 | "import/no-useless-path-segments": ["error", { commonjs: true }], 246 | 247 | // dynamic imports require a leading comment with a webpackChunkName 248 | // https://github.com/benmosher/eslint-plugin-import/blob/ebafcbf59ec9f653b2ac2a0156ca3bcba0a7cf57/docs/rules/dynamic-import-chunkname.md 249 | "import/dynamic-import-chunkname": ["off", { 250 | importFunctions: [], 251 | webpackChunknameFormat: "[0-9a-zA-Z-_/.]+", 252 | }], 253 | 254 | // Use this rule to prevent imports to folders in relative parent paths. 255 | // https://github.com/benmosher/eslint-plugin-import/blob/c34f14f67f077acd5a61b3da9c0b0de298d20059/docs/rules/no-relative-parent-imports.md 256 | "import/no-relative-parent-imports": "off", 257 | 258 | // Reports modules without any exports, or with unused exports 259 | // https://github.com/benmosher/eslint-plugin-import/blob/f63dd261809de6883b13b6b5b960e6d7f42a7813/docs/rules/no-unused-modules.md 260 | "import/no-unused-modules": "off", 261 | }, 262 | }; 263 | -------------------------------------------------------------------------------- /packages/eslint-config-eser/rules/node.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | node: true, 4 | }, 5 | 6 | rules: { 7 | // enforce return after a callback 8 | "callback-return": "off", 9 | 10 | // require all requires be top-level 11 | // https://eslint.org/docs/rules/global-require 12 | "global-require": "error", 13 | 14 | // enforces error handling in callbacks (node environment) 15 | "handle-callback-err": "off", 16 | 17 | // disallow use of the Buffer() constructor 18 | // https://eslint.org/docs/rules/no-buffer-constructor 19 | "no-buffer-constructor": "error", 20 | 21 | // disallow mixing regular variable and require declarations 22 | "no-mixed-requires": ["off", false], 23 | 24 | // disallow use of new operator with the require function 25 | "no-new-require": "error", 26 | 27 | // disallow string concatenation with __dirname and __filename 28 | // https://eslint.org/docs/rules/no-path-concat 29 | "no-path-concat": "error", 30 | 31 | // disallow use of process.env 32 | "no-process-env": "off", 33 | 34 | // disallow process.exit() 35 | "no-process-exit": "off", 36 | 37 | // restrict usage of specified node modules 38 | "no-restricted-modules": "off", 39 | 40 | // disallow use of synchronous methods (off by default) 41 | "no-sync": "off", 42 | }, 43 | }; 44 | -------------------------------------------------------------------------------- /packages/eslint-config-eser/rules/strict.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rules: { 3 | // babel inserts `'use strict';` for us 4 | strict: ["error", "never"], 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/eslint-config-eser/rules/style.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rules: { 3 | // enforce line breaks after opening and before closing array brackets 4 | // https://eslint.org/docs/rules/array-bracket-newline 5 | // TODO: enable? semver-major 6 | "array-bracket-newline": ["off", "consistent"], // object option alternative: { multiline: true, minItems: 3 } 7 | 8 | // enforce line breaks between array elements 9 | // https://eslint.org/docs/rules/array-element-newline 10 | // TODO: enable? semver-major 11 | "array-element-newline": ["off", { multiline: true, minItems: 3 }], 12 | 13 | // enforce spacing inside array brackets 14 | "array-bracket-spacing": ["error", "never"], 15 | 16 | // enforce spacing inside single-line blocks 17 | // https://eslint.org/docs/rules/block-spacing 18 | "block-spacing": ["error", "always"], 19 | 20 | // enforce one true brace style 21 | "brace-style": "off", 22 | "@typescript-eslint/brace-style": [ 23 | "error", 24 | "1tbs", 25 | { allowSingleLine: true }, 26 | ], 27 | 28 | // require camel case names 29 | "camelcase": "off", // was { properties: "never", ignoreDestructuring: false }, 30 | "@typescript-eslint/naming-convention": [ 31 | "error", 32 | // Allow camelCase variables (23.2), 33 | // PascalCase variables (23.8), 34 | // and UPPER_CASE variables (23.10) 35 | { 36 | selector: "variable", 37 | format: ["camelCase", "PascalCase", "UPPER_CASE"], 38 | }, 39 | // Allow camelCase functions (23.2), 40 | // and PascalCase functions (23.8) 41 | { 42 | selector: "function", 43 | format: ["camelCase", "PascalCase"], 44 | }, 45 | // Airbnb recommends PascalCase for classes (23.3), 46 | // and although Airbnb does not make TypeScript 47 | // recommendations, we are assuming this rule would 48 | // similarly apply to anything "type like", including 49 | // interfaces, type aliases, and enums 50 | { 51 | selector: "typeLike", 52 | format: ["PascalCase"], 53 | }, 54 | ], 55 | 56 | // enforce or disallow capitalization of the first letter of a comment 57 | // https://eslint.org/docs/rules/capitalized-comments 58 | "capitalized-comments": ["off", "never", { 59 | line: { 60 | ignorePattern: ".*", 61 | ignoreInlineComments: true, 62 | ignoreConsecutiveComments: true, 63 | }, 64 | block: { 65 | ignorePattern: ".*", 66 | ignoreInlineComments: true, 67 | ignoreConsecutiveComments: true, 68 | }, 69 | }], 70 | 71 | // require trailing commas in multiline object literals 72 | "comma-dangle": "off", 73 | "@typescript-eslint/comma-dangle": ["error", { 74 | arrays: "always-multiline", 75 | objects: "always-multiline", 76 | imports: "always-multiline", 77 | exports: "always-multiline", 78 | functions: "always-multiline", 79 | // typescript 80 | enums: "always-multiline", 81 | generics: "always-multiline", 82 | tuples: "always-multiline", 83 | }], 84 | 85 | // enforce spacing before and after comma 86 | "comma-spacing": "off", 87 | "@typescript-eslint/comma-spacing": [ 88 | "error", 89 | { before: false, after: true }, 90 | ], 91 | 92 | // enforce one true comma style 93 | "comma-style": ["error", "last", { 94 | exceptions: { 95 | ArrayExpression: false, 96 | ArrayPattern: false, 97 | ArrowFunctionExpression: false, 98 | CallExpression: false, 99 | FunctionDeclaration: false, 100 | FunctionExpression: false, 101 | ImportDeclaration: false, 102 | ObjectExpression: false, 103 | ObjectPattern: false, 104 | VariableDeclaration: false, 105 | NewExpression: false, 106 | }, 107 | }], 108 | 109 | // disallow padding inside computed properties 110 | "computed-property-spacing": ["error", "never"], 111 | 112 | // enforces consistent naming when capturing the current execution context 113 | "consistent-this": "off", 114 | 115 | // enforce newline at the end of file, with no multiple empty lines 116 | "eol-last": ["error", "always"], 117 | 118 | // https://eslint.org/docs/rules/function-call-argument-newline 119 | // TODO: enable, semver-minor, once eslint v6.2 is required (which is a major) 120 | "function-call-argument-newline": ["off", "consistent"], 121 | 122 | // enforce spacing between functions and their invocations 123 | // https://eslint.org/docs/rules/func-call-spacing 124 | "func-call-spacing": "off", 125 | "@typescript-eslint/func-call-spacing": ["error", "never"], 126 | 127 | // requires function names to match the name of the variable or property to which they are 128 | // assigned 129 | // https://eslint.org/docs/rules/func-name-matching 130 | "func-name-matching": ["off", "always", { 131 | includeCommonJSModuleExports: false, 132 | considerPropertyDescriptor: true, 133 | }], 134 | 135 | // require function expressions to have a name 136 | // https://eslint.org/docs/rules/func-names 137 | "func-names": "warn", 138 | 139 | // enforces use of function declarations or expressions 140 | // https://eslint.org/docs/rules/func-style 141 | // TODO: enable 142 | "func-style": ["off", "expression"], 143 | 144 | // enforce consistent line breaks inside function parentheses 145 | // https://eslint.org/docs/rules/function-paren-newline 146 | "function-paren-newline": ["error", "consistent"], 147 | 148 | // Blacklist certain identifiers to prevent them being used 149 | // https://eslint.org/docs/rules/id-blacklist 150 | // TODO: semver-major, remove once eslint v7.4+ is required 151 | "id-blacklist": "off", 152 | 153 | // disallow specified identifiers 154 | // https://eslint.org/docs/rules/id-denylist 155 | "id-denylist": "off", 156 | 157 | // this option enforces minimum and maximum identifier lengths 158 | // (variable names, property names etc.) 159 | "id-length": "off", 160 | 161 | // require identifiers to match the provided regular expression 162 | "id-match": "off", 163 | 164 | // Enforce the location of arrow function bodies with implicit returns 165 | // https://eslint.org/docs/rules/implicit-arrow-linebreak 166 | "implicit-arrow-linebreak": ["error", "beside"], 167 | 168 | // this option sets a specific tab width for your code 169 | // https://eslint.org/docs/rules/indent 170 | "indent": "off", 171 | "@typescript-eslint/indent": ["error", 2, { 172 | SwitchCase: 1, 173 | VariableDeclarator: 1, 174 | outerIIFEBody: 1, 175 | // MemberExpression: null, 176 | FunctionDeclaration: { 177 | parameters: 1, 178 | body: 1, 179 | }, 180 | FunctionExpression: { 181 | parameters: 1, 182 | body: 1, 183 | }, 184 | CallExpression: { 185 | arguments: 1, 186 | }, 187 | ArrayExpression: 1, 188 | ObjectExpression: 1, 189 | ImportDeclaration: 1, 190 | flatTernaryExpressions: false, 191 | // list derived from https://github.com/benjamn/ast-types/blob/HEAD/def/jsx.js 192 | ignoredNodes: [ 193 | "JSXElement", 194 | "JSXElement > *", 195 | "JSXAttribute", 196 | "JSXIdentifier", 197 | "JSXNamespacedName", 198 | "JSXMemberExpression", 199 | "JSXSpreadAttribute", 200 | "JSXExpressionContainer", 201 | "JSXOpeningElement", 202 | "JSXClosingElement", 203 | "JSXFragment", 204 | "JSXOpeningFragment", 205 | "JSXClosingFragment", 206 | "JSXText", 207 | "JSXEmptyExpression", 208 | "JSXSpreadChild", 209 | ], 210 | ignoreComments: false, 211 | }], 212 | 213 | // specify whether double or single quotes should be used in JSX attributes 214 | // https://eslint.org/docs/rules/jsx-quotes 215 | "jsx-quotes": ["off", "prefer-double"], 216 | 217 | // enforces spacing between keys and values in object literal properties 218 | "key-spacing": ["error", { beforeColon: false, afterColon: true }], 219 | 220 | // require a space before & after certain keywords 221 | "keyword-spacing": "off", 222 | "@typescript-eslint/keyword-spacing": ["error", { 223 | before: true, 224 | after: true, 225 | overrides: { 226 | return: { after: true }, 227 | throw: { after: true }, 228 | case: { after: true }, 229 | }, 230 | }], 231 | 232 | // enforce position of line comments 233 | // https://eslint.org/docs/rules/line-comment-position 234 | // TODO: enable? 235 | "line-comment-position": ["off", { 236 | position: "above", 237 | ignorePattern: "", 238 | applyDefaultPatterns: true, 239 | }], 240 | 241 | // disallow mixed 'LF' and 'CRLF' as linebreaks 242 | // https://eslint.org/docs/rules/linebreak-style 243 | "linebreak-style": ["error", "unix"], 244 | 245 | // require or disallow an empty line between class members 246 | // https://eslint.org/docs/rules/lines-between-class-members 247 | "lines-between-class-members": "off", 248 | "@typescript-eslint/lines-between-class-members": [ 249 | "error", 250 | "always", 251 | { exceptAfterSingleLine: false }, 252 | ], 253 | 254 | // enforces empty lines around comments 255 | "lines-around-comment": "off", 256 | 257 | // require or disallow newlines around directives 258 | // https://eslint.org/docs/rules/lines-around-directive 259 | "lines-around-directive": ["error", { 260 | before: "always", 261 | after: "always", 262 | }], 263 | 264 | // specify the maximum depth that blocks can be nested 265 | "max-depth": ["off", 4], 266 | 267 | // specify the maximum length of a line in your program 268 | // https://eslint.org/docs/rules/max-len 269 | "max-len": ["error", 100, 2, { 270 | ignoreUrls: true, 271 | ignoreComments: false, 272 | ignoreRegExpLiterals: true, 273 | ignoreStrings: true, 274 | ignoreTemplateLiterals: true, 275 | }], 276 | 277 | // specify the max number of lines in a file 278 | // https://eslint.org/docs/rules/max-lines 279 | "max-lines": ["off", { 280 | max: 300, 281 | skipBlankLines: true, 282 | skipComments: true, 283 | }], 284 | 285 | // enforce a maximum function length 286 | // https://eslint.org/docs/rules/max-lines-per-function 287 | "max-lines-per-function": ["off", { 288 | max: 50, 289 | skipBlankLines: true, 290 | skipComments: true, 291 | IIFEs: true, 292 | }], 293 | 294 | // specify the maximum depth callbacks can be nested 295 | "max-nested-callbacks": "off", 296 | 297 | // limits the number of parameters that can be used in the function declaration. 298 | "max-params": ["off", 3], 299 | 300 | // specify the maximum number of statement allowed in a function 301 | "max-statements": ["off", 10], 302 | 303 | // restrict the number of statements per line 304 | // https://eslint.org/docs/rules/max-statements-per-line 305 | "max-statements-per-line": ["off", { max: 1 }], 306 | 307 | // enforce a particular style for multiline comments 308 | // https://eslint.org/docs/rules/multiline-comment-style 309 | "multiline-comment-style": ["off", "starred-block"], 310 | 311 | // require multiline ternary 312 | // https://eslint.org/docs/rules/multiline-ternary 313 | // TODO: enable? 314 | "multiline-ternary": ["off", "never"], 315 | 316 | // require a capital letter for constructors 317 | "new-cap": ["error", { 318 | newIsCap: true, 319 | newIsCapExceptions: [], 320 | capIsNew: false, 321 | capIsNewExceptions: ["Immutable.Map", "Immutable.Set", "Immutable.List"], 322 | }], 323 | 324 | // disallow the omission of parentheses when invoking a constructor with no arguments 325 | // https://eslint.org/docs/rules/new-parens 326 | "new-parens": "error", 327 | 328 | // allow/disallow an empty newline after var statement 329 | "newline-after-var": "off", 330 | 331 | // https://eslint.org/docs/rules/newline-before-return 332 | "newline-before-return": "off", 333 | 334 | // enforces new line after each method call in the chain to make it 335 | // more readable and easy to maintain 336 | // https://eslint.org/docs/rules/newline-per-chained-call 337 | "newline-per-chained-call": ["error", { ignoreChainWithDepth: 4 }], 338 | 339 | // disallow use of the Array constructor 340 | "no-array-constructor": "off", 341 | "@typescript-eslint/no-array-constructor": "error", 342 | 343 | // disallow use of bitwise operators 344 | // https://eslint.org/docs/rules/no-bitwise 345 | "no-bitwise": "error", 346 | 347 | // disallow use of the continue statement 348 | // https://eslint.org/docs/rules/no-continue 349 | "no-continue": "error", 350 | 351 | // disallow comments inline after code 352 | "no-inline-comments": "off", 353 | 354 | // disallow if as the only statement in an else block 355 | // https://eslint.org/docs/rules/no-lonely-if 356 | "no-lonely-if": "error", 357 | 358 | // disallow un-paren'd mixes of different operators 359 | // https://eslint.org/docs/rules/no-mixed-operators 360 | "no-mixed-operators": ["error", { 361 | // the list of arthmetic groups disallows mixing `%` and `**` 362 | // with other arithmetic operators. 363 | groups: [ 364 | ["%", "**"], 365 | ["%", "+"], 366 | ["%", "-"], 367 | ["%", "*"], 368 | ["%", "/"], 369 | ["/", "*"], 370 | ["&", "|", "<<", ">>", ">>>"], 371 | ["==", "!=", "===", "!=="], 372 | ["&&", "||"], 373 | ], 374 | allowSamePrecedence: false, 375 | }], 376 | 377 | // disallow mixed spaces and tabs for indentation 378 | "no-mixed-spaces-and-tabs": "error", 379 | 380 | // disallow use of chained assignment expressions 381 | // https://eslint.org/docs/rules/no-multi-assign 382 | "no-multi-assign": ["error"], 383 | 384 | // disallow multiple empty lines, only one newline at the end, and no new lines at the beginning 385 | // https://eslint.org/docs/rules/no-multiple-empty-lines 386 | "no-multiple-empty-lines": ["error", { max: 1, maxBOF: 0, maxEOF: 0 }], 387 | 388 | // disallow negated conditions 389 | // https://eslint.org/docs/rules/no-negated-condition 390 | "no-negated-condition": "off", 391 | 392 | // disallow nested ternary expressions 393 | "no-nested-ternary": "error", 394 | 395 | // disallow use of the Object constructor 396 | "no-new-object": "error", 397 | 398 | // disallow use of unary operators, ++ and -- 399 | // https://eslint.org/docs/rules/no-plusplus 400 | "no-plusplus": "error", 401 | 402 | // disallow certain syntax forms 403 | // https://eslint.org/docs/rules/no-restricted-syntax 404 | "no-restricted-syntax": [ 405 | "error", 406 | { 407 | selector: "ForInStatement", 408 | message: 409 | "for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.", 410 | }, 411 | { 412 | selector: "ForOfStatement", 413 | message: 414 | "iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.", 415 | }, 416 | { 417 | selector: "LabeledStatement", 418 | message: 419 | "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.", 420 | }, 421 | { 422 | selector: "WithStatement", 423 | message: 424 | "`with` is disallowed in strict mode because it makes code impossible to predict and optimize.", 425 | }, 426 | ], 427 | 428 | // disallow space between function identifier and application 429 | "no-spaced-func": "error", 430 | 431 | // disallow tab characters entirely 432 | "no-tabs": "error", 433 | 434 | // disallow the use of ternary operators 435 | "no-ternary": "off", 436 | 437 | // disallow trailing whitespace at the end of lines 438 | "no-trailing-spaces": ["error", { 439 | skipBlankLines: false, 440 | ignoreComments: false, 441 | }], 442 | 443 | // disallow dangling underscores in identifiers 444 | // https://eslint.org/docs/rules/no-underscore-dangle 445 | "no-underscore-dangle": ["error", { 446 | allow: [], 447 | allowAfterThis: false, 448 | allowAfterSuper: false, 449 | enforceInMethodNames: true, 450 | }], 451 | 452 | // disallow the use of Boolean literals in conditional expressions 453 | // also, prefer `a || b` over `a ? a : b` 454 | // https://eslint.org/docs/rules/no-unneeded-ternary 455 | "no-unneeded-ternary": ["error", { defaultAssignment: false }], 456 | 457 | // disallow whitespace before properties 458 | // https://eslint.org/docs/rules/no-whitespace-before-property 459 | "no-whitespace-before-property": "error", 460 | 461 | // enforce the location of single-line statements 462 | // https://eslint.org/docs/rules/nonblock-statement-body-position 463 | "nonblock-statement-body-position": ["error", "beside", { overrides: {} }], 464 | 465 | // require padding inside curly braces 466 | "object-curly-spacing": ["error", "always"], 467 | 468 | // enforce line breaks between braces 469 | // https://eslint.org/docs/rules/object-curly-newline 470 | "object-curly-newline": ["error", { 471 | ObjectExpression: { minProperties: 4, multiline: true, consistent: true }, 472 | ObjectPattern: { minProperties: 4, multiline: true, consistent: true }, 473 | ImportDeclaration: { 474 | minProperties: 4, 475 | multiline: true, 476 | consistent: true, 477 | }, 478 | ExportDeclaration: { 479 | minProperties: 4, 480 | multiline: true, 481 | consistent: true, 482 | }, 483 | }], 484 | 485 | // enforce "same line" or "multiple line" on object properties. 486 | // https://eslint.org/docs/rules/object-property-newline 487 | "object-property-newline": ["error", { 488 | allowAllPropertiesOnSameLine: true, 489 | }], 490 | 491 | // allow just one var statement per function 492 | "one-var": ["error", "never"], 493 | 494 | // require a newline around variable declaration 495 | // https://eslint.org/docs/rules/one-var-declaration-per-line 496 | "one-var-declaration-per-line": ["error", "always"], 497 | 498 | // require assignment operator shorthand where possible or prohibit it entirely 499 | // https://eslint.org/docs/rules/operator-assignment 500 | "operator-assignment": ["error", "always"], 501 | 502 | // Requires operator at the beginning of the line in multiline statements 503 | // https://eslint.org/docs/rules/operator-linebreak 504 | "operator-linebreak": ["error", "before", { overrides: { "=": "none" } }], 505 | 506 | // disallow padding within blocks 507 | "padded-blocks": ["error", { 508 | blocks: "never", 509 | classes: "never", 510 | switches: "never", 511 | }, { 512 | allowSingleLineBlocks: true, 513 | }], 514 | 515 | // Require or disallow padding lines between statements 516 | // https://eslint.org/docs/rules/padding-line-between-statements 517 | "padding-line-between-statements": "off", 518 | 519 | // Disallow the use of Math.pow in favor of the ** operator 520 | // https://eslint.org/docs/rules/prefer-exponentiation-operator 521 | // TODO: enable, semver-major when eslint 5 is dropped 522 | "prefer-exponentiation-operator": "off", 523 | 524 | // Prefer use of an object spread over Object.assign 525 | // https://eslint.org/docs/rules/prefer-object-spread 526 | "prefer-object-spread": "error", 527 | 528 | // require quotes around object literal property names 529 | // https://eslint.org/docs/rules/quote-props.html 530 | "quote-props": [ 531 | "error", 532 | "consistent-as-needed", 533 | { keywords: false, unnecessary: true, numbers: false }, 534 | ], 535 | 536 | // specify whether double or single quotes should be used 537 | "quotes": "off", 538 | "@typescript-eslint/quotes": ["error", "double", { avoidEscape: true }], 539 | 540 | // do not require jsdoc 541 | // https://eslint.org/docs/rules/require-jsdoc 542 | "require-jsdoc": "off", 543 | 544 | // require or disallow use of semicolons instead of ASI 545 | "semi": "off", 546 | "@typescript-eslint/semi": ["error", "always"], 547 | 548 | // enforce spacing before and after semicolons 549 | "semi-spacing": ["error", { before: false, after: true }], 550 | 551 | // Enforce location of semicolons 552 | // https://eslint.org/docs/rules/semi-style 553 | "semi-style": ["error", "last"], 554 | 555 | // requires object keys to be sorted 556 | "sort-keys": ["off", "asc", { caseSensitive: false, natural: true }], 557 | 558 | // sort variables within the same declaration block 559 | "sort-vars": "off", 560 | 561 | // require or disallow space before blocks 562 | "space-before-blocks": "error", 563 | 564 | // require or disallow space before function opening parenthesis 565 | // https://eslint.org/docs/rules/space-before-function-paren 566 | "space-before-function-paren": "off", 567 | "@typescript-eslint/space-before-function-paren": ["error", { 568 | anonymous: "always", 569 | named: "never", 570 | asyncArrow: "always", 571 | }], 572 | 573 | // require or disallow spaces inside parentheses 574 | "space-in-parens": ["error", "never"], 575 | 576 | // require spaces around operators 577 | "space-infix-ops": "error", 578 | 579 | // Require or disallow spaces before/after unary operators 580 | // https://eslint.org/docs/rules/space-unary-ops 581 | "space-unary-ops": ["error", { 582 | words: true, 583 | nonwords: false, 584 | overrides: {}, 585 | }], 586 | 587 | // require or disallow a space immediately following the // or /* in a comment 588 | // https://eslint.org/docs/rules/spaced-comment 589 | "spaced-comment": ["error", "always", { 590 | line: { 591 | exceptions: ["-", "+"], 592 | markers: ["=", "!", "/"], // space here to support sprockets directives, slash for TS /// comments 593 | }, 594 | block: { 595 | exceptions: ["-", "+"], 596 | markers: ["=", "!", ":", "::"], // space here to support sprockets directives and flow comment types 597 | balanced: true, 598 | }, 599 | }], 600 | 601 | // Enforce spacing around colons of switch statements 602 | // https://eslint.org/docs/rules/switch-colon-spacing 603 | "switch-colon-spacing": ["error", { after: true, before: false }], 604 | 605 | // Require or disallow spacing between template tags and their literals 606 | // https://eslint.org/docs/rules/template-tag-spacing 607 | "template-tag-spacing": ["error", "never"], 608 | 609 | // require or disallow the Unicode Byte Order Mark 610 | // https://eslint.org/docs/rules/unicode-bom 611 | "unicode-bom": ["error", "never"], 612 | 613 | // require regex literals to be wrapped in parentheses 614 | "wrap-regex": "off", 615 | }, 616 | }; 617 | -------------------------------------------------------------------------------- /packages/eslint-config-eser/rules/typescript.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: "@typescript-eslint/parser", 3 | parserOptions: { 4 | sourceType: "module", 5 | project: "./tsconfig.json", 6 | }, 7 | 8 | plugins: [ 9 | "@typescript-eslint", 10 | ], 11 | 12 | rules: {}, 13 | 14 | settings: { 15 | "import/parsers": { 16 | "@typescript-eslint/parser": [".ts", ".tsx", ".d.ts"], 17 | }, 18 | "import/resolver": { 19 | typescript: {}, 20 | }, 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /packages/eslint-config-eser/rules/variables.js: -------------------------------------------------------------------------------- 1 | const confusingBrowserGlobals = require("confusing-browser-globals"); 2 | 3 | module.exports = { 4 | rules: { 5 | // enforce or disallow variable initializations at definition 6 | "init-declarations": "off", 7 | 8 | // disallow the catch clause parameter name being the same as a variable in the outer scope 9 | "no-catch-shadow": "off", 10 | 11 | // disallow deletion of variables 12 | "no-delete-var": "error", 13 | 14 | // disallow labels that share a name with a variable 15 | // https://eslint.org/docs/rules/no-label-var 16 | "no-label-var": "error", 17 | 18 | // disallow specific globals 19 | "no-restricted-globals": [ 20 | "error", 21 | { 22 | name: "isFinite", 23 | message: 24 | "Use Number.isFinite instead https://github.com/airbnb/javascript#standard-library--isfinite", 25 | }, 26 | { 27 | name: "isNaN", 28 | message: 29 | "Use Number.isNaN instead https://github.com/airbnb/javascript#standard-library--isnan", 30 | }, 31 | ].concat(confusingBrowserGlobals), 32 | 33 | // disallow declaration of variables already declared in the outer scope 34 | "no-shadow": "off", 35 | "@typescript-eslint/no-shadow": "error", 36 | 37 | // disallow shadowing of names such as arguments 38 | "no-shadow-restricted-names": "error", 39 | 40 | // disallow use of undeclared variables unless mentioned in a /*global */ block 41 | "no-undef": "error", 42 | 43 | // disallow use of undefined when initializing variables 44 | "no-undef-init": "error", 45 | 46 | // disallow use of undefined variable 47 | // https://eslint.org/docs/rules/no-undefined 48 | // TODO: enable? 49 | "no-undefined": "off", 50 | 51 | // disallow declaration of variables that are not used in the code 52 | "no-unused-vars": "off", 53 | "@typescript-eslint/no-unused-vars": [ 54 | "error", 55 | { vars: "all", args: "after-used", ignoreRestSiblings: true }, 56 | ], 57 | 58 | // disallow use of variables before they are defined 59 | "no-use-before-define": "off", 60 | "@typescript-eslint/no-use-before-define": [ 61 | "error", 62 | { functions: true, classes: true, variables: true }, 63 | ], 64 | }, 65 | }; 66 | -------------------------------------------------------------------------------- /packages/eslint-config-eser/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Basic Options */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ 8 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 9 | // "lib": [], /* Specify library files to be included in the compilation. */ 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | // "checkJs": true, /* Report errors in .js files. */ 12 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 13 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 15 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 16 | // "outFile": "./", /* Concatenate and emit output to single file. */ 17 | // "outDir": "./", /* Redirect output structure to the directory. */ 18 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 19 | // "composite": true, /* Enable project compilation */ 20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 21 | // "removeComments": true, /* Do not emit comments to output. */ 22 | // "noEmit": true, /* Do not emit outputs. */ 23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 26 | 27 | /* Strict Type-Checking Options */ 28 | "strict": true, /* Enable all strict type-checking options. */ 29 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 30 | // "strictNullChecks": true, /* Enable strict null checks. */ 31 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 32 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 33 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 34 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 35 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 36 | 37 | /* Additional Checks */ 38 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 39 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 40 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 41 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 42 | 43 | /* Module Resolution Options */ 44 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 45 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 46 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 47 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 48 | // "typeRoots": [], /* List of folders to include type definitions from. */ 49 | // "types": [], /* Type declaration files to be included in compilation. */ 50 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 51 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 52 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 53 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 54 | 55 | /* Source Map Options */ 56 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 58 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 59 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 60 | 61 | /* Experimental Options */ 62 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 63 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 64 | 65 | /* Advanced Options */ 66 | "skipLibCheck": true, /* Skip type checking of declaration files. */ 67 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 68 | } 69 | } 70 | --------------------------------------------------------------------------------