├── .editorconfig ├── .gitignore ├── .npmrc ├── .travis.yml ├── LICENSE.md ├── README.md ├── css-in-javascript └── README.md ├── linters ├── .eslintrc ├── .jshintrc ├── .markdownlint.json └── SublimeLinter │ └── SublimeLinter.sublime-settings ├── package.json ├── packages ├── eslint-config-airbnb-base │ ├── .babelrc │ ├── .editorconfig │ ├── .eslintrc │ ├── .npmrc │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── index.js │ ├── legacy.js │ ├── package.json │ ├── rules │ │ ├── best-practices.js │ │ ├── errors.js │ │ ├── es6.js │ │ ├── imports.js │ │ ├── node.js │ │ ├── strict.js │ │ ├── style.js │ │ └── variables.js │ ├── test │ │ ├── .eslintrc │ │ ├── requires.js │ │ └── test-base.js │ └── whitespace.js └── eslint-config-airbnb │ ├── .babelrc │ ├── .editorconfig │ ├── .eslintrc │ ├── .npmrc │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── base.js │ ├── index.js │ ├── legacy.js │ ├── package.json │ ├── rules │ ├── react-a11y.js │ └── react.js │ ├── test │ ├── .eslintrc │ ├── requires.js │ ├── test-base.js │ └── test-react-order.js │ └── whitespace.js └── react └── README.md /.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 = null 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # gitignore 2 | 3 | node_modules 4 | 5 | # Only apps should have lockfiles 6 | yarn.lock 7 | package-lock.json 8 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "9" 4 | - "8" 5 | - "7" 6 | - "6" 7 | - "5" 8 | - "4" 9 | before_install: 10 | - 'nvm install-latest-npm' 11 | install: 12 | - 'if [ -n "${PACKAGE-}" ]; then cd "packages/${PACKAGE}"; fi' 13 | - 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ] || [ "${TRAVIS_NODE_VERSION}" = "0.9" ]; then nvm install --latest-npm 0.8 && npm install && nvm use "${TRAVIS_NODE_VERSION}"; else npm install; fi;' 14 | - 'if [ -n "${ESLINT}" ]; then npm install --no-save "eslint@${ESLINT}"; fi' 15 | script: 16 | - 'if [ -n "${PREPUBLISH-}" ]; then npm run pretravis && npm run prepublish && npm run posttravis; elif [ -n "${LINT-}" ]; then npm run lint; else npm run travis; fi' 17 | sudo: false 18 | env: 19 | matrix: 20 | - 'TEST=true ESLINT=4 PACKAGE=eslint-config-airbnb' 21 | - 'TEST=true ESLINT=4 PACKAGE=eslint-config-airbnb-base' 22 | matrix: 23 | fast_finish: true 24 | include: 25 | - node_js: "lts/*" 26 | env: PREPUBLISH=true ESLINT=4 PACKAGE=eslint-config-airbnb 27 | - node_js: "lts/*" 28 | env: PREPUBLISH=true ESLINT=4 PACKAGE=eslint-config-airbnb-base 29 | - node_js: "lts/*" 30 | env: LINT=true 31 | allow_failures: 32 | - node_js: "9" 33 | - node_js: "7" 34 | - node_js: "5" 35 | - env: PREPUBLISH=true ESLINT=4 PACKAGE=eslint-config-airbnb 36 | - env: PREPUBLISH=true ESLINT=4 PACKAGE=eslint-config-airbnb-base 37 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012 康兵奎 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 | -------------------------------------------------------------------------------- /css-in-javascript/README.md: -------------------------------------------------------------------------------- 1 | # Airbnb CSS-in-JavaScript 代码规范 2 | 3 | *一种 CSS-in-JavaScript 最合理的规范。* 4 | 5 | ## 目录 6 | 7 | 1. [命名](#naming) 8 | 1. [订阅](#ordering) 9 | 1. [嵌套](#nesting) 10 | 1. [内联](#inline) 11 | 1. [主题](#themes) 12 | 13 | ## 命名 14 | 15 | - 使用驼峰命名法给对象的 key 命名。 (i.e. "selectors") 16 | 17 | > 为什么? 我们在组件的 `styles` 对象上访问这些键作为属性,使用驼峰命名法最为方便。 18 | 19 | ```js 20 | // bad 21 | { 22 | 'bermuda-triangle': { 23 | display: 'none', 24 | }, 25 | } 26 | 27 | // good 28 | { 29 | bermudaTriangle: { 30 | display: 'none', 31 | }, 32 | } 33 | ``` 34 | 35 | - 使用下划线标识修改为其他样式。 36 | 37 | > 为什么? 与 BEM 类似,这种约定清楚明确的表明,修改样式的元素是下划线之前的元素。下划线不需要引导,因此它比其他字符(如破折号)更受欢迎。 38 | 39 | ```js 40 | // bad 41 | { 42 | bruceBanner: { 43 | color: 'pink', 44 | transition: 'color 10s', 45 | }, 46 | 47 | bruceBannerTheHulk: { 48 | color: 'green', 49 | }, 50 | } 51 | 52 | // good 53 | { 54 | bruceBanner: { 55 | color: 'pink', 56 | transition: 'color 10s', 57 | }, 58 | 59 | bruceBanner_theHulk: { 60 | color: 'green', 61 | }, 62 | } 63 | ``` 64 | 65 | - 使用 `selectorName_fallback` 设置回退样式集。 66 | 67 | > 为什么? 与修饰符类似,保持命名一致有助于揭示这些样式与在浏览器中覆盖它们的样式之间的关系。 68 | 69 | ```js 70 | // bad 71 | { 72 | muscles: { 73 | display: 'flex', 74 | }, 75 | 76 | muscles_sadBears: { 77 | width: '100%', 78 | }, 79 | } 80 | 81 | // good 82 | { 83 | muscles: { 84 | display: 'flex', 85 | }, 86 | 87 | muscles_fallback: { 88 | width: '100%', 89 | }, 90 | } 91 | ``` 92 | 93 | - 使用单独的选择器设置备用样式集。 94 | 95 | > 为什么? 保留一个单独的对象中包含的回退样式可以明确它们的目的,从而提高可读性。 96 | 97 | ```js 98 | // bad 99 | { 100 | muscles: { 101 | display: 'flex', 102 | }, 103 | 104 | left: { 105 | flexGrow: 1, 106 | display: 'inline-block', 107 | }, 108 | 109 | right: { 110 | display: 'inline-block', 111 | }, 112 | } 113 | 114 | // good 115 | { 116 | muscles: { 117 | display: 'flex', 118 | }, 119 | 120 | left: { 121 | flexGrow: 1, 122 | }, 123 | 124 | left_fallback: { 125 | display: 'inline-block', 126 | }, 127 | 128 | right_fallback: { 129 | display: 'inline-block', 130 | }, 131 | } 132 | ``` 133 | 134 | - 使用与设备无关的名字 (如: "small", "medium", and "large") 来命名媒体查询的断点。 135 | 136 | > 为什么? 常用的名字如: ”phone“, “tablet”,和 “desktop” 与现实世界的设备的特点不匹配。使用这些名字会带来错误的期望。 137 | 138 | ```js 139 | // bad 140 | const breakpoints = { 141 | mobile: '@media (max-width: 639px)', 142 | tablet: '@media (max-width: 1047px)', 143 | desktop: '@media (min-width: 1048px)', 144 | }; 145 | 146 | // good 147 | const breakpoints = { 148 | small: '@media (max-width: 639px)', 149 | medium: '@media (max-width: 1047px)', 150 | large: '@media (min-width: 1048px)', 151 | }; 152 | ``` 153 | 154 | ## 订阅 155 | 156 | - 在组件之后定义样式。 157 | 158 | > 为什么? 使用一个高阶组件来定义我们的主题,这是在组件定义之后自然使用的。 将样式对象直接传递给这个函数可以减少间接性。 159 | 160 | ```jsx 161 | // bad 162 | const styles = { 163 | container: { 164 | display: 'inline-block', 165 | }, 166 | }; 167 | 168 | function MyComponent({ styles }) { 169 | return ( 170 |
171 | Never doubt that a small group of thoughtful, committed citizens can 172 | change the world. Indeed, it’s the only thing that ever has. 173 |
174 | ); 175 | } 176 | 177 | export default withStyles(() => styles)(MyComponent); 178 | 179 | // good 180 | function MyComponent({ styles }) { 181 | return ( 182 |
183 | Never doubt that a small group of thoughtful, committed citizens can 184 | change the world. Indeed, it’s the only thing that ever has. 185 |
186 | ); 187 | } 188 | 189 | export default withStyles(() => ({ 190 | container: { 191 | display: 'inline-block', 192 | }, 193 | }))(MyComponent); 194 | ``` 195 | 196 | ## 嵌套 197 | 198 | - 在相同缩进级别的相邻块之间留下空白。 199 | 200 | > 为什么? 空间可以提高可读性,减少合并冲突的可能性。 201 | 202 | ```js 203 | // bad 204 | { 205 | bigBang: { 206 | display: 'inline-block', 207 | '::before': { 208 | content: "''", 209 | }, 210 | }, 211 | universe: { 212 | border: 'none', 213 | }, 214 | } 215 | 216 | // good 217 | { 218 | bigBang: { 219 | display: 'inline-block', 220 | 221 | '::before': { 222 | content: "''", 223 | }, 224 | }, 225 | 226 | universe: { 227 | border: 'none', 228 | }, 229 | } 230 | ``` 231 | 232 | ## 内联 233 | 234 | - 对于具有高基数的样式使用内联样式(例如:使用 prop 的值),而不是具有低基数的样式。 235 | > 为什么? 主题样式是非常昂贵的,因此对于不同类型的样式内联样式是最好的选择。 236 | 237 | ```jsx 238 | // bad 239 | export default function MyComponent({ spacing }) { 240 | return ( 241 |
242 | ); 243 | } 244 | 245 | // good 246 | function MyComponent({ styles, spacing }) { 247 | return ( 248 |
249 | ); 250 | } 251 | export default withStyles(() => ({ 252 | periodic: { 253 | display: 'table', 254 | }, 255 | }))(MyComponent); 256 | ``` 257 | 258 | ## 主题 259 | 260 | - 可以使用一个如 [react-with-styles](https://github.com/airbnb/react-with-styles) 的抽象层启用主题。*react-with-styles 给了我们像 `withStyles()`, `ThemedStyleSheet`, 和 `css()` 的一些示例在它的文档中。* 261 | 262 | > 为什么? 有一组共享的变量来设计组件式有用的。 使用抽象层使其更方便。 此外,这有助于防止组件与任何特定的底层实现逻辑实现紧密耦合,从而使你获得更多的自由。 263 | 264 | - 只在主题中定义颜色。 265 | 266 | ```js 267 | // bad 268 | export default withStyles(() => ({ 269 | chuckNorris: { 270 | color: '#bada55', 271 | }, 272 | }))(MyComponent); 273 | 274 | // good 275 | export default withStyles(({ color }) => ({ 276 | chuckNorris: { 277 | color: color.badass, 278 | }, 279 | }))(MyComponent); 280 | ``` 281 | 282 | - 只在主题中定义字体。 283 | 284 | ```js 285 | // bad 286 | export default withStyles(() => ({ 287 | towerOfPisa: { 288 | fontStyle: 'italic', 289 | }, 290 | }))(MyComponent); 291 | 292 | // good 293 | export default withStyles(({ font }) => ({ 294 | towerOfPisa: { 295 | fontStyle: font.italic, 296 | }, 297 | }))(MyComponent); 298 | ``` 299 | 300 | - 将字体定义为相关样式集。 301 | 302 | ```js 303 | // bad 304 | export default withStyles(() => ({ 305 | towerOfPisa: { 306 | fontFamily: 'Italiana, "Times New Roman", serif', 307 | fontSize: '2em', 308 | fontStyle: 'italic', 309 | lineHeight: 1.5, 310 | }, 311 | }))(MyComponent); 312 | 313 | // good 314 | export default withStyles(({ font }) => ({ 315 | towerOfPisa: { 316 | ...font.italian, 317 | }, 318 | }))(MyComponent); 319 | ``` 320 | 321 | - 在主题中定义基本网格单元(无论是作为一个值还是一个使用乘数的函数)。 322 | 323 | ```js 324 | // bad 325 | export default withStyles(() => ({ 326 | rip: { 327 | bottom: '-6912px', // 6 feet 328 | }, 329 | }))(MyComponent); 330 | 331 | // good 332 | export default withStyles(({ units }) => ({ 333 | rip: { 334 | bottom: units(864), // 6 feet, assuming our unit is 8px 335 | }, 336 | }))(MyComponent); 337 | 338 | // good 339 | export default withStyles(({ unit }) => ({ 340 | rip: { 341 | bottom: 864 * unit, // 6 feet, assuming our unit is 8px 342 | }, 343 | }))(MyComponent); 344 | ``` 345 | 346 | - 只在主题中定义媒体查询。 347 | 348 | ```js 349 | // bad 350 | export default withStyles(() => ({ 351 | container: { 352 | width: '100%', 353 | 354 | '@media (max-width: 1047px)': { 355 | width: '50%', 356 | }, 357 | }, 358 | }))(MyComponent); 359 | 360 | // good 361 | export default withStyles(({ breakpoint }) => ({ 362 | container: { 363 | width: '100%', 364 | 365 | [breakpoint.medium]: { 366 | width: '50%', 367 | }, 368 | }, 369 | }))(MyComponent); 370 | ``` 371 | 372 | - 在主题中定义棘手的回退属性。 373 | 374 | > 为什么? 许多 CSS-in-JavaScript 的实现中将样式对象合并在一起,这使得指定样式的属性(如: `display` )回退有点棘手。 为了保持统一的方法,把这些回退属性放在主题中。 375 | 376 | ```js 377 | // bad 378 | export default withStyles(() => ({ 379 | .muscles { 380 | display: 'flex', 381 | }, 382 | 383 | .muscles_fallback { 384 | 'display ': 'table', 385 | }, 386 | }))(MyComponent); 387 | 388 | // good 389 | export default withStyles(({ fallbacks }) => ({ 390 | .muscles { 391 | display: 'flex', 392 | }, 393 | 394 | .muscles_fallback { 395 | [fallbacks.display]: 'table', 396 | }, 397 | }))(MyComponent); 398 | 399 | // good 400 | export default withStyles(({ fallback }) => ({ 401 | .muscles { 402 | display: 'flex', 403 | }, 404 | 405 | .muscles_fallback { 406 | [fallback('display')]: 'table', 407 | }, 408 | }))(MyComponent); 409 | ``` 410 | 411 | - 尽可能少的自定义主题。 许多应用只有一套主题。 412 | 413 | - 自定义主题的命名空间是设置在一个具有独特和描述性的 key 之下的一个嵌套对象。 414 | 415 | ```js 416 | // bad 417 | ThemedStyleSheet.registerTheme('mySection', { 418 | mySectionPrimaryColor: 'green', 419 | }); 420 | 421 | // good 422 | ThemedStyleSheet.registerTheme('mySection', { 423 | mySection: { 424 | primaryColor: 'green', 425 | }, 426 | }); 427 | ``` 428 | 429 | --- 430 | 431 | CSS 规则改编自 [Saijo George](https://saijogeorge.com/css-puns/). 432 | -------------------------------------------------------------------------------- /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": "airbnb" 5 | } 6 | -------------------------------------------------------------------------------- /linters/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | /* 3 | * ENVIRONMENTS 4 | * ================= 5 | */ 6 | 7 | // Define globals exposed by modern browsers. 8 | "browser": true, 9 | 10 | // Define globals exposed by jQuery. 11 | "jquery": true, 12 | 13 | // Define globals exposed by Node.js. 14 | "node": true, 15 | 16 | // Allow ES6. 17 | "esversion": 6, 18 | 19 | /* 20 | * ENFORCING OPTIONS 21 | * ================= 22 | */ 23 | 24 | // Force all variable names to use either camelCase style or UPPER_CASE 25 | // with underscores. 26 | "camelcase": true, 27 | 28 | // Prohibit use of == and != in favor of === and !==. 29 | "eqeqeq": true, 30 | 31 | // Enforce tab width of 2 spaces. 32 | "indent": 2, 33 | 34 | // Prohibit use of a variable before it is defined. 35 | "latedef": true, 36 | 37 | // Enforce line length to 100 characters 38 | "maxlen": 100, 39 | 40 | // Require capitalized names for constructor functions. 41 | "newcap": true, 42 | 43 | // Enforce use of single quotation marks for strings. 44 | "quotmark": "single", 45 | 46 | // Enforce placing 'use strict' at the top function scope 47 | "strict": true, 48 | 49 | // Prohibit use of explicitly undeclared variables. 50 | "undef": true, 51 | 52 | // Warn when variables are defined but never used. 53 | "unused": true, 54 | 55 | /* 56 | * RELAXING OPTIONS 57 | * ================= 58 | */ 59 | 60 | // Suppress warnings about == null comparisons. 61 | "eqnull": true 62 | } 63 | -------------------------------------------------------------------------------- /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": 1 50 | }, 51 | 52 | "comment": "MD013: Line length", 53 | "line-length": false, 54 | 55 | "comment": "MD014: Disallow dollar signs used 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: Dissalow multiple spaces after hash on atx style header", 62 | "no-multiple-space-atx": true, 63 | 64 | "comment": "MD020: No space 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": "Gotta 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 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 | -------------------------------------------------------------------------------- /linters/SublimeLinter/SublimeLinter.sublime-settings: -------------------------------------------------------------------------------- 1 | /** 2 | * Airbnb JSHint settings for use with SublimeLinter and Sublime Text 2. 3 | * 4 | * 1. Install SublimeLinter at https://github.com/SublimeLinter/SublimeLinter 5 | * 2. Open user preferences for the SublimeLinter package in Sublime Text 2 6 | * * For Mac OS X go to _Sublime Text 2_ > _Preferences_ > _Package Settings_ > _SublimeLinter_ > _Settings - User_ 7 | * 3. Paste the contents of this file into your settings file 8 | * 4. Save the settings file 9 | * 10 | * @version 0.3.0 11 | * @see https://github.com/SublimeLinter/SublimeLinter 12 | * @see http://www.jshint.com/docs/ 13 | */ 14 | { 15 | "jshint_options": 16 | { 17 | /* 18 | * ENVIRONMENTS 19 | * ================= 20 | */ 21 | 22 | // Define globals exposed by modern browsers. 23 | "browser": true, 24 | 25 | // Define globals exposed by jQuery. 26 | "jquery": true, 27 | 28 | // Define globals exposed by Node.js. 29 | "node": true, 30 | 31 | /* 32 | * ENFORCING OPTIONS 33 | * ================= 34 | */ 35 | 36 | // Force all variable names to use either camelCase style or UPPER_CASE 37 | // with underscores. 38 | "camelcase": true, 39 | 40 | // Prohibit use of == and != in favor of === and !==. 41 | "eqeqeq": true, 42 | 43 | // Suppress warnings about == null comparisons. 44 | "eqnull": true, 45 | 46 | // Enforce tab width of 2 spaces. 47 | "indent": 2, 48 | 49 | // Prohibit use of a variable before it is defined. 50 | "latedef": true, 51 | 52 | // Require capitalized names for constructor functions. 53 | "newcap": true, 54 | 55 | // Enforce use of single quotation marks for strings. 56 | "quotmark": "single", 57 | 58 | // Prohibit trailing whitespace. 59 | "trailing": true, 60 | 61 | // Prohibit use of explicitly undeclared variables. 62 | "undef": true, 63 | 64 | // Warn when variables are defined but never used. 65 | "unused": true, 66 | 67 | // Enforce line length to 80 characters 68 | "maxlen": 80, 69 | 70 | // Enforce placing 'use strict' at the top function scope 71 | "strict": true 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "airbnb-style-zh", 3 | "version": "2.0.0", 4 | "description": "A mostly reasonable approach to JavaScript.", 5 | "scripts": { 6 | "preinstall": "npm run install:config && npm run install:config:base", 7 | "install:config": "cd packages/eslint-config-airbnb && npm prune && npm install", 8 | "install:config:base": "cd packages/eslint-config-airbnb-base && npm prune && npm install", 9 | "lint": "markdownlint --config linters/.markdownlint.json README.md */README.md", 10 | "pretest": "npm run --silent lint", 11 | "test": "npm run --silent test:config && npm run --silent test:config:base", 12 | "test:config": "cd packages/eslint-config-airbnb; npm test", 13 | "test:config:base": "cd packages/eslint-config-airbnb-base; npm test", 14 | "pretravis": "npm run --silent lint", 15 | "travis": "npm run --silent travis:config && npm run --silent travis:config:base", 16 | "travis:config": "cd packages/eslint-config-airbnb; npm run travis", 17 | "travis:config:base": "cd packages/eslint-config-airbnb-base; npm run travis" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/BingKui/javascript-zh.git" 22 | }, 23 | "keywords": [ 24 | "style guide", 25 | "lint", 26 | "airbnb", 27 | "es6", 28 | "es2015", 29 | "react", 30 | "jsx" 31 | ], 32 | "author": "康兵奎", 33 | "license": "MIT", 34 | "bugs": { 35 | "url": "https://github.com/BingKui/javascript-zh/issues" 36 | }, 37 | "homepage": "https://github.com/BingKui/javascript-zh", 38 | "devDependencies": { 39 | "markdownlint-cli": "^0.3.1" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["airbnb"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/.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 = null 12 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./index.js", 3 | "rules": { 4 | // disable requiring trailing commas because it might be nice to revert to 5 | // being JSON at some point, and I don't want to make big changes now. 6 | "comma-dangle": 0, 7 | // we support node 4 8 | "prefer-destructuring": 0, 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 12.1.0 / 2017-10-16 2 | ================== 3 | - [deps] update `eslint` to `v4.9` 4 | 5 | 12.0.2 / 2017-10-05 6 | ================== 7 | - [deps] update `eslint` 8 | 9 | 12.0.1 / 2017-09-27 10 | ================== 11 | - [fix] ensure all JSX elements are ignored by `indent` (#1569) 12 | - [deps] update `eslint` 13 | 14 | 12.0.0 / 2017-09-02 15 | ================== 16 | - [deps] [breaking] require `eslint` v4 17 | - enable `function-paren-newline`, `for-direction`, `getter-return`, `no-compare-neg-zero`, `semi-style`, `object-curly-newline`, `no-buffer-constructor`, `no-restricted-globals`, `switch-colon-spacing`, `template-tag-spacing`, `prefer-promise-reject-errors`, `prefer-destructuring` 18 | - improve `indent`, `no-multi-spaces`, `no-trailing-spaces`, `no-underscore-dangle` 19 | - [breaking] move `comma-dangle` to Stylistic Issues (#1514) 20 | - [breaking] Rules prohibiting global isNaN, isFinite (#1477) 21 | - [patch] also disallow padding in classes and switches (#1403) 22 | - [patch] support Protractor config files in import/no-extraneous-dependencies (#1543) 23 | 24 | 11.3.2 / 2017-08-22 25 | ================== 26 | - [patch] Add jest.config.js to import/no-extraneous-dependencies devDeps (#1522) 27 | - [patch] Improve Gruntfile glob pattern (#1503) 28 | - [deps] update `eslint` v4, `tape` 29 | - [docs] Specify yarn-specific install instructions (#1511) 30 | 31 | 11.3.1 / 2017-07-24 32 | ================== 33 | - [fix] `legacy`: remove top-level `ecmaFeatures` 34 | 35 | 11.3.0 / 2017-07-23 36 | ================== 37 | - [deps] allow eslint v3 or v4 (#1447) 38 | - [deps] update `eslint-plugin-import` 39 | - [minor] Balanced spacing for inline block comments (#1440) 40 | - [minor] `no-return-assign`: strengthen linting against returning assignments 41 | - [patch] Allow jsx extensions for test files (#1427) 42 | - [patch] `no-restricted-globals`: add confusing globals; leave disabled for now (#1420) 43 | - [patch] Support Protractor config files in import/no-extraneous-dependencies (#1456) 44 | - [docs] Remove TODO in prefer-reflect as it's deprecated (#1452) 45 | - [docs] add yarn instructions (#1463, #1464) 46 | 47 | 11.2.0 / 2017-05-14 48 | ================== 49 | - [minor] Disallow unused global variables 50 | 51 | 11.1.3 / 2017-04-03 52 | ================== 53 | - [patch] add error messages to `no-restricted-syntax` (#1353) 54 | - [deps] update `eslint` 55 | 56 | 11.1.2 / 2017-03-25 57 | ================== 58 | - [patch] `no-param-reassign`: add ignorePropertyModificationsFor (#1325) 59 | - [deps] update `eslint` 60 | 61 | 11.1.1 / 2017-03-03 62 | ================== 63 | - [deps] update `eslint` 64 | - [patch] enable `ignoreRestSiblings` in `no-unused-vars` 65 | 66 | 11.1.0 / 2017-01-08 67 | ================== 68 | - [minor] enable `no-multi-assign` 69 | - [deps] update `eslint`, `babel-preset-airbnb` 70 | - Update a deprecated option (`eqeqeq`) (#1244) 71 | 72 | 11.0.1 / 2017-01-08 73 | ================== 74 | - [deps] update `eslint` 75 | - [docs] add note about `install-peerdeps` (#1234) 76 | - [docs] Updated instructions to support non-bash users (#1214) 77 | 78 | 11.0.0 / 2016-12-11 79 | ================== 80 | - [breaking] enable `no-await-in-loop` 81 | - [patch] disable `no-duplicate-imports` rule (#1188, #1195, #1054) 82 | - [patch] `import/no-extraneous-dependencies`: add some comments to ignore patterns 83 | - [patch] add `import/no-extraneous-dependencies` ignore patterns for test files (#1174) 84 | - [patch] `import/no-extraneous-dependencies`: added ignore patterns for config files (#1168) 85 | - [deps] update `eslint`, `eslint-plugin-import`, `tape` 86 | 87 | 10.0.1 / 2016-11-07 88 | ================== 89 | - [fix] legacy config should not require `**` 90 | 91 | 10.0.0 / 2016-11-06 92 | ================== 93 | - [breaking] prefer `**` over `Math.pow` 94 | - [breaking] `comma-dangle`: require trailing commas for functions 95 | - [breaking] enable `no-useless-return` 96 | - [breaking] tighten up `indent` 97 | - [breaking] tighten up `spaced-comment` 98 | - [breaking] enable `import/no-named-default` 99 | - [patch] loosen `max-len` with `ignoreRegExpLiterals` option 100 | - [patch] loosen `no-extraneous-dependencies` for test files (#959, #1089) 101 | - [deps] update `eslint`, `eslint-plugin-import` 102 | - [dev deps] update `eslint-find-rules` 103 | - [Tests] on `node` `v7` 104 | 105 | 9.0.0 / 2016-10-16 106 | ================== 107 | - [breaking] Add `ForOfStatement` to `no-restricted-syntax` (#1122, #1134) 108 | - [breaking] enable `import/no-webpack-loader-syntax` (#1123) 109 | - [breaking] [deps] update `eslint` to `v3.8.0` (#1132) 110 | - [breaking] [deps] update `eslint-plugin-import` to v2 (#1101) 111 | - [patch] `new-cap`: add immutable.js exceptions 112 | - [docs] ensure latest version of config is installed 113 | - [dev deps] update `babel-preset-airbnb`, `eslint`, `eslint-find-rules`, `tape`, `safe-publish-latest` 114 | 115 | 8.0.0 / 2016-09-24 116 | ================== 117 | - [breaking] enable rules: `no-restricted-properties`, `prefer-numeric-literals`, `lines-around-directive`, `import/extensions`, `import/no-absolute-path`, `import/no-dynamic-require` 118 | 119 | 7.2.0 / 2016-09-23 120 | ================== 121 | - [new] set `ecmaVersion` to 2017; enable object rest/spread; update `babel-preset-airbnb` 122 | - [patch] fix category of `no-restricted-properties` 123 | - [deps] update `eslint`, `eslint-plugin-import`, `eslint-find-rules`, `safe-publish-latest` 124 | 125 | 7.1.0 / 2016-09-11 126 | ================== 127 | - [minor] enable `arrow-parens` rule 128 | 129 | 7.0.1 / 2016-09-10 130 | ================== 131 | - [patch] loosen `max-len` by ignoring strings 132 | - [deps] update to `eslint` `v3.5.0` 133 | 134 | 7.0.0 / 2016-09-06 135 | ================== 136 | - [breaking] Add no-plusplus in style.js and added explanation in README (#1012) 137 | 138 | 6.0.0 / 2016-09-06 139 | ================== 140 | - [breaking] `valid-typeof`: enable `requireStringLiterals` option 141 | - [breaking] enable `class-methods-use-this` 142 | - [breaking] enable `symbol-description` 143 | - [breaking] enable `no-bitwise` 144 | - [breaking] enable `no-tabs` 145 | - [breaking] enable `func-call-spacing` 146 | - [breaking] enable `no-template-curly-in-string` 147 | - [patch] remove redundant `DebuggerStatement` from `no-restricted-syntax` (#1031) 148 | - [deps] update `eslint`, `eslint-find-rules`, `eslint-plugin-import` 149 | - Update `ecmaVersion` to `2016` 150 | 151 | 5.0.3 / 2016-08-21 152 | ================== 153 | - [fix] correct `import/extensions` list (#1013) 154 | - [refactor] Changed ESLint rule configs to use 'off', 'warn', and 'error' instead of numbers for better readability (#946) 155 | - [deps] update `eslint`, `eslint-plugin-react` 156 | 157 | 5.0.2 / 2016-08-12 158 | ================== 159 | - [deps] update `eslint`, `eslint-find-rules`, `eslint-plugin-import` 160 | - [tests] add `safe-publish-latest` to `prepublish` 161 | 162 | 5.0.1 / 2016-07-29 163 | ================== 164 | - [patch] `no-unused-expressions`: flesh out options 165 | - [deps] update `eslint` to `v3.2`, `eslint-plugin-import` to `v1.12` 166 | - [tests] improve prepublish script 167 | 168 | 5.0.0 / 2016-07-24 169 | ================== 170 | - [breaking] enable `import/newline-after-import` 171 | - [breaking] enable overlooked rules: `linebreak-style`, `new-parens`, `no-continue`, `no-lonely-if`, `operator-assignment`, `space-unary-ops`, `dot-location`, `no-extra-boolean-cast`, `no-this-before-super`, `require-yield`, `no-path-concat`, `no-label-var`, `no-void`, `constructor-super`, `prefer-spread`, `no-new-require`, `no-undef-init`, `no-unexpected-multiline` 172 | - [deps] update `eslint`, `eslint-find-rules`, `eslint-plugin-import`, `babel-tape-runner`; add `babel-preset-airbnb` 173 | - [patch] flesh out defaults: `jsx-quotes` 174 | - [docs] update the peer dep install command to dynamically look up the right version numbers when installing peer deps 175 | - [tests] fix prepublish scripts 176 | 177 | 4.0.2 / 2016-07-14 178 | ================== 179 | - [fix] repair accidental comma-dangle change 180 | 181 | 4.0.1 / 2016-07-14 (unpublished) 182 | ================== 183 | - [fix] Prevent trailing commas in the legacy config (#950) 184 | - [deps] update `eslint-plugin-import` 185 | 186 | 4.0.0 / 2016-07-02 187 | ================== 188 | - [breaking] [deps] update `eslint` to v3; drop support for < node 4 189 | - [breaking] enable `rest-spread-spacing` rule 190 | - [breaking] enable `no-mixed-operators` rule 191 | - [breaking] enable `import` rules: `no-named-as-default`, `no-named-as-default-member`, `no-extraneous-dependencies` 192 | - [breaking] enable `object-property-newline` rule 193 | - [breaking] enable `no-prototype-builtins` rule 194 | - [breaking] enable `no-useless-rename` rule 195 | - [breaking] enable `unicode-bom` rule 196 | - [breaking] Enforce proper generator star spacing (#887) 197 | - [breaking] Enable imports/imports-first rule (#882) 198 | - [breaking] re-order rules; put import rules in separate file (#881) 199 | - [patch] `newline-per-chained-call`: bump the limit to 4 200 | - [patch] `object-shorthand`: do not warn when the concise form would have a string literal as a name 201 | - [patch] Loosen `prefer-const` to not warn when the variable is “read” before being assigned to 202 | - [refactor] fix quoting of rule properties (#885) 203 | - [refactor] `quotes`: Use object option form rather than deprecated string form. 204 | - [deps] update `eslint`, `eslint-plugin-import`, `eslint-find-rules`, `tape` 205 | - [tests] Only run `eslint-find-rules` on prepublish, not in tests 206 | 207 | 3.0.1 / 2016-05-08 208 | ================== 209 | - [patch] re-disable `no-extra-parens` (#869, #867) 210 | 211 | 3.0.0 / 2016-05-07 212 | ================== 213 | - [breaking] enable `import/no-mutable-exports` 214 | - [breaking] enable `no-class-assign` rule, to pair with `no-func-assign` 215 | - [breaking] widen `no-extra-parens` to include everything, except `nestedBinaryExpressions` 216 | - [breaking] Re-enabling `newline-per-chained-call` (#748) 217 | - [minor] enable `import/no-amd` 218 | - [patch] enable `import/no-duplicates` 219 | - [deps] update `eslint`, `eslint-plugin-import`, `eslint-find-rules` 220 | 221 | 2.0.0 / 2016-04-29 222 | ================== 223 | - [breaking] enable `no-unsafe-finally` rule 224 | - [semver-minor] enable `no-useless-computed-key` rule 225 | - [deps] update `eslint`, `eslint-plugin-import` 226 | 227 | 1.0.4 / 2016-04-26 228 | ================== 229 | - [deps] update `eslint-find-rules`, `eslint-plugin-import` 230 | 231 | 1.0.3 / 2016-04-21 232 | ================== 233 | - [patch: loosen rules] Allow empty class/object methods 234 | 235 | 1.0.2 / 2016-04-20 236 | ================== 237 | - [patch: loosen rules] Allow `break` (#840) 238 | 239 | 1.0.1 / 2016-04-19 240 | ================== 241 | - [patch: loosen rules] Allow `== null` (#542) 242 | 243 | 1.0.0 / 2016-04-19 244 | ================== 245 | - Initial commmit; moved content over from `eslint-config-airbnb` package. 246 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012 Airbnb 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 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/README.md: -------------------------------------------------------------------------------- 1 | # eslint-config-airbnb-base 2 | 3 | [![npm version](https://badge.fury.io/js/eslint-config-airbnb-base.svg)](http://badge.fury.io/js/eslint-config-airbnb-base) 4 | 5 | This package provides Airbnb's base JS .eslintrc (without React plugins) as an extensible shared config. 6 | 7 | ## Usage 8 | 9 | We export two ESLint configurations for your usage. 10 | 11 | ### eslint-config-airbnb-base 12 | 13 | Our default export contains all of our ESLint rules, including ECMAScript 6+. It requires `eslint` and `eslint-plugin-import`. 14 | 15 | If you use yarn, run `npm info "eslint-config-airbnb-base@latest" peerDependencies` to list the peer dependencies and versions, then run `yarn add --dev @` for each listed peer dependency. See below for npm instructions. 16 | 17 | 1. Install the correct versions of each package, which are listed by the command: 18 | 19 | ```sh 20 | npm info "eslint-config-airbnb-base@latest" peerDependencies 21 | ``` 22 | 23 | If using **npm 5+**, use this shortcut 24 | 25 | ```sh 26 | npx install-peerdeps --dev eslint-config-airbnb-base 27 | ``` 28 | 29 | If using **npm < 5**, Linux/OSX users can run 30 | 31 | ```sh 32 | ( 33 | export PKG=eslint-config-airbnb-base; 34 | npm info "$PKG@latest" peerDependencies --json | command sed 's/[\{\},]//g ; s/: /@/g' | xargs npm install --save-dev "$PKG@latest" 35 | ) 36 | ``` 37 | 38 | Which produces and runs a command like: 39 | 40 | ```sh 41 | npm install --save-dev eslint-config-airbnb-base eslint@^#.#.# eslint-plugin-import@^#.#.# 42 | ``` 43 | 44 | If using **npm < 5**, Windows users can either install all the peer dependencies manually, or use the [install-peerdeps](https://github.com/nathanhleung/install-peerdeps) cli tool. 45 | 46 | ```sh 47 | npm install -g install-peerdeps 48 | install-peerdeps --dev eslint-config-airbnb-base 49 | ``` 50 | 51 | The cli will produce and run a command like: 52 | 53 | ```sh 54 | npm install --save-dev eslint-config-airbnb-base eslint@^#.#.# eslint-plugin-import@^#.#.# 55 | ``` 56 | 57 | 2. Add `"extends": "airbnb-base"` to your .eslintrc. 58 | 59 | ### eslint-config-airbnb-base/legacy 60 | 61 | Lints ES5 and below. Requires `eslint` and `eslint-plugin-import`. 62 | 63 | 1. Install the correct versions of each package, which are listed by the command: 64 | 65 | ```sh 66 | npm info "eslint-config-airbnb-base@latest" peerDependencies 67 | ``` 68 | 69 | Linux/OSX users can run 70 | ```sh 71 | ( 72 | export PKG=eslint-config-airbnb-base; 73 | npm info "$PKG" peerDependencies --json | command sed 's/[\{\},]//g ; s/: /@/g' | xargs npm install --save-dev "$PKG" 74 | ) 75 | ``` 76 | 77 | Which produces and runs a command like: 78 | 79 | ```sh 80 | npm install --save-dev eslint-config-airbnb-base eslint@^3.0.1 eslint-plugin-import@^1.10.3 81 | ``` 82 | 83 | 2. Add `"extends": "airbnb-base/legacy"` to your .eslintrc 84 | 85 | See [Airbnb's overarching ESLint config](https://npmjs.com/eslint-config-airbnb), [Airbnb's Javascript styleguide](https://github.com/airbnb/javascript), and the [ESlint config docs](https://eslint.org/docs/user-guide/configuring#extending-configuration-files) for more information. 86 | 87 | ### eslint-config-airbnb-base/whitespace 88 | 89 | This entry point that only warns on whitespace rules and sets all other rules to warnings. View the list of whitespace rules [here](https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/whitespace.js). 90 | 91 | ## Improving this config 92 | 93 | Consider adding test cases if you're making complicated rules changes, like anything involving regexes. Perhaps in a distant future, we could use literate programming to structure our README as test cases for our .eslintrc? 94 | 95 | You can run tests with `npm test`. 96 | 97 | You can make sure this module lints with itself using `npm run lint`. 98 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | './rules/best-practices', 4 | './rules/errors', 5 | './rules/node', 6 | './rules/style', 7 | './rules/variables', 8 | './rules/es6', 9 | './rules/imports', 10 | ].map(require.resolve), 11 | parserOptions: { 12 | ecmaVersion: 2017, 13 | sourceType: 'module', 14 | ecmaFeatures: { 15 | experimentalObjectRestSpread: true, 16 | }, 17 | }, 18 | rules: { 19 | strict: 'error', 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/legacy.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | './rules/best-practices', 4 | './rules/errors', 5 | './rules/node', 6 | './rules/style', 7 | './rules/variables' 8 | ].map(require.resolve), 9 | env: { 10 | browser: true, 11 | node: true, 12 | amd: false, 13 | mocha: false, 14 | jasmine: false 15 | }, 16 | rules: { 17 | 'comma-dangle': ['error', 'never'], 18 | 'prefer-numeric-literals': 'off', 19 | 'no-restricted-properties': ['error', { 20 | object: 'arguments', 21 | property: 'callee', 22 | message: 'arguments.callee is deprecated', 23 | }, { 24 | property: '__defineGetter__', 25 | message: 'Please use Object.defineProperty instead.', 26 | }, { 27 | property: '__defineSetter__', 28 | message: 'Please use Object.defineProperty instead.', 29 | }], 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-airbnb-base", 3 | "version": "12.1.0", 4 | "description": "Airbnb's base JS ESLint config, following our styleguide", 5 | "main": "index.js", 6 | "scripts": { 7 | "prelint": "editorconfig-tools check * rules/* test/*", 8 | "lint": "eslint --report-unused-disable-directives .", 9 | "pretests-only": "node ./test/requires", 10 | "tests-only": "babel-tape-runner ./test/test-*.js", 11 | "prepublish": "(in-install || eslint-find-rules --unused) && (not-in-publish || npm test) && safe-publish-latest", 12 | "pretest": "npm run --silent lint", 13 | "test": "npm run --silent tests-only", 14 | "pretravis": ":", 15 | "travis": "npm run --silent test", 16 | "posttravis": ":" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/airbnb/javascript" 21 | }, 22 | "keywords": [ 23 | "eslint", 24 | "eslintconfig", 25 | "config", 26 | "airbnb", 27 | "javascript", 28 | "styleguide" 29 | ], 30 | "author": "Jake Teton-Landis (https://twitter.com/@jitl)", 31 | "contributors": [ 32 | { 33 | "name": "Jake Teton-Landis", 34 | "url": "https://twitter.com/jitl" 35 | }, 36 | { 37 | "name": "Jordan Harband", 38 | "email": "ljharb@gmail.com", 39 | "url": "http://ljharb.codes" 40 | }, 41 | { 42 | "name": "Harrison Shoff", 43 | "url": "https://twitter.com/hshoff" 44 | } 45 | ], 46 | "license": "MIT", 47 | "bugs": { 48 | "url": "https://github.com/airbnb/javascript/issues" 49 | }, 50 | "homepage": "https://github.com/airbnb/javascript", 51 | "devDependencies": { 52 | "babel-preset-airbnb": "^2.4.0", 53 | "babel-tape-runner": "^2.0.1", 54 | "editorconfig-tools": "^0.1.1", 55 | "eslint": "^4.19.1", 56 | "eslint-find-rules": "^3.2.2", 57 | "eslint-plugin-import": "^2.11.0", 58 | "in-publish": "^2.0.0", 59 | "safe-publish-latest": "^1.1.1", 60 | "tape": "^4.9.0" 61 | }, 62 | "peerDependencies": { 63 | "eslint": "^4.19.1", 64 | "eslint-plugin-import": "^2.11.0" 65 | }, 66 | "engines": { 67 | "node": ">= 4" 68 | }, 69 | "dependencies": { 70 | "eslint-restricted-globals": "^0.1.1", 71 | "object.assign": "^4.1.0", 72 | "object.entries": "^1.0.4" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/rules/best-practices.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rules: { 3 | // enforces getter/setter pairs in objects 4 | 'accessor-pairs': 'off', 5 | 6 | // enforces return statements in callbacks of array's methods 7 | // https://eslint.org/docs/rules/array-callback-return 8 | 'array-callback-return': ['error', { allowImplicit: true }], 9 | 10 | // treat var statements as if they were block scoped 11 | 'block-scoped-var': 'error', 12 | 13 | // specify the maximum cyclomatic complexity allowed in a program 14 | complexity: ['off', 11], 15 | 16 | // enforce that class methods use "this" 17 | // https://eslint.org/docs/rules/class-methods-use-this 18 | 'class-methods-use-this': ['error', { 19 | exceptMethods: [], 20 | }], 21 | 22 | // require return statements to either always or never specify values 23 | 'consistent-return': 'error', 24 | 25 | // specify curly brace conventions for all control statements 26 | curly: ['error', 'multi-line'], 27 | 28 | // require default case in switch statements 29 | 'default-case': ['error', { commentPattern: '^no default$' }], 30 | 31 | // encourages use of dot notation whenever possible 32 | 'dot-notation': ['error', { allowKeywords: true }], 33 | 34 | // enforces consistent newlines before or after dots 35 | // https://eslint.org/docs/rules/dot-location 36 | 'dot-location': ['error', 'property'], 37 | 38 | // require the use of === and !== 39 | // https://eslint.org/docs/rules/eqeqeq 40 | eqeqeq: ['error', 'always', { null: 'ignore' }], 41 | 42 | // make sure for-in loops have an if statement 43 | 'guard-for-in': 'error', 44 | 45 | // disallow the use of alert, confirm, and prompt 46 | 'no-alert': 'warn', 47 | 48 | // disallow use of arguments.caller or arguments.callee 49 | 'no-caller': 'error', 50 | 51 | // disallow lexical declarations in case/default clauses 52 | // https://eslint.org/docs/rules/no-case-declarations.html 53 | 'no-case-declarations': 'error', 54 | 55 | // disallow division operators explicitly at beginning of regular expression 56 | // https://eslint.org/docs/rules/no-div-regex 57 | 'no-div-regex': 'off', 58 | 59 | // disallow else after a return in an if 60 | // https://eslint.org/docs/rules/no-else-return 61 | 'no-else-return': ['error', { allowElseIf: false }], 62 | 63 | // disallow empty functions, except for standalone funcs/arrows 64 | // https://eslint.org/docs/rules/no-empty-function 65 | 'no-empty-function': ['error', { 66 | allow: [ 67 | 'arrowFunctions', 68 | 'functions', 69 | 'methods', 70 | ] 71 | }], 72 | 73 | // disallow empty destructuring patterns 74 | // https://eslint.org/docs/rules/no-empty-pattern 75 | 'no-empty-pattern': 'error', 76 | 77 | // disallow comparisons to null without a type-checking operator 78 | 'no-eq-null': 'off', 79 | 80 | // disallow use of eval() 81 | 'no-eval': 'error', 82 | 83 | // disallow adding to native types 84 | 'no-extend-native': 'error', 85 | 86 | // disallow unnecessary function binding 87 | 'no-extra-bind': 'error', 88 | 89 | // disallow Unnecessary Labels 90 | // https://eslint.org/docs/rules/no-extra-label 91 | 'no-extra-label': 'error', 92 | 93 | // disallow fallthrough of case statements 94 | 'no-fallthrough': 'error', 95 | 96 | // disallow the use of leading or trailing decimal points in numeric literals 97 | 'no-floating-decimal': 'error', 98 | 99 | // disallow reassignments of native objects or read-only globals 100 | // https://eslint.org/docs/rules/no-global-assign 101 | 'no-global-assign': ['error', { exceptions: [] }], 102 | // deprecated in favor of no-global-assign 103 | 'no-native-reassign': 'off', 104 | 105 | // disallow implicit type conversions 106 | // https://eslint.org/docs/rules/no-implicit-coercion 107 | 'no-implicit-coercion': ['off', { 108 | boolean: false, 109 | number: true, 110 | string: true, 111 | allow: [], 112 | }], 113 | 114 | // disallow var and named functions in global scope 115 | // https://eslint.org/docs/rules/no-implicit-globals 116 | 'no-implicit-globals': 'off', 117 | 118 | // disallow use of eval()-like methods 119 | 'no-implied-eval': 'error', 120 | 121 | // disallow this keywords outside of classes or class-like objects 122 | 'no-invalid-this': 'off', 123 | 124 | // disallow usage of __iterator__ property 125 | 'no-iterator': 'error', 126 | 127 | // disallow use of labels for anything other then loops and switches 128 | 'no-labels': ['error', { allowLoop: false, allowSwitch: false }], 129 | 130 | // disallow unnecessary nested blocks 131 | 'no-lone-blocks': 'error', 132 | 133 | // disallow creation of functions within loops 134 | 'no-loop-func': 'error', 135 | 136 | // disallow magic numbers 137 | // https://eslint.org/docs/rules/no-magic-numbers 138 | 'no-magic-numbers': ['off', { 139 | ignore: [], 140 | ignoreArrayIndexes: true, 141 | enforceConst: true, 142 | detectObjects: false, 143 | }], 144 | 145 | // disallow use of multiple spaces 146 | 'no-multi-spaces': ['error', { 147 | ignoreEOLComments: false, 148 | }], 149 | 150 | // disallow use of multiline strings 151 | 'no-multi-str': 'error', 152 | 153 | // disallow use of new operator when not part of the assignment or comparison 154 | 'no-new': 'error', 155 | 156 | // disallow use of new operator for Function object 157 | 'no-new-func': 'error', 158 | 159 | // disallows creating new instances of String, Number, and Boolean 160 | 'no-new-wrappers': 'error', 161 | 162 | // disallow use of (old style) octal literals 163 | 'no-octal': 'error', 164 | 165 | // disallow use of octal escape sequences in string literals, such as 166 | // var foo = 'Copyright \251'; 167 | 'no-octal-escape': 'error', 168 | 169 | // disallow reassignment of function parameters 170 | // disallow parameter object manipulation except for specific exclusions 171 | // rule: https://eslint.org/docs/rules/no-param-reassign.html 172 | 'no-param-reassign': ['error', { 173 | props: true, 174 | ignorePropertyModificationsFor: [ 175 | 'acc', // for reduce accumulators 176 | 'accumulator', // for reduce accumulators 177 | 'e', // for e.returnvalue 178 | 'ctx', // for Koa routing 179 | 'req', // for Express requests 180 | 'request', // for Express requests 181 | 'res', // for Express responses 182 | 'response', // for Express responses 183 | '$scope', // for Angular 1 scopes 184 | ] 185 | }], 186 | 187 | // disallow usage of __proto__ property 188 | 'no-proto': 'error', 189 | 190 | // disallow declaring the same variable more then once 191 | 'no-redeclare': 'error', 192 | 193 | // disallow certain object properties 194 | // https://eslint.org/docs/rules/no-restricted-properties 195 | 'no-restricted-properties': ['error', { 196 | object: 'arguments', 197 | property: 'callee', 198 | message: 'arguments.callee is deprecated', 199 | }, { 200 | object: 'global', 201 | property: 'isFinite', 202 | message: 'Please use Number.isFinite instead', 203 | }, { 204 | object: 'self', 205 | property: 'isFinite', 206 | message: 'Please use Number.isFinite instead', 207 | }, { 208 | object: 'window', 209 | property: 'isFinite', 210 | message: 'Please use Number.isFinite instead', 211 | }, { 212 | object: 'global', 213 | property: 'isNaN', 214 | message: 'Please use Number.isNaN instead', 215 | }, { 216 | object: 'self', 217 | property: 'isNaN', 218 | message: 'Please use Number.isNaN instead', 219 | }, { 220 | object: 'window', 221 | property: 'isNaN', 222 | message: 'Please use Number.isNaN instead', 223 | }, { 224 | property: '__defineGetter__', 225 | message: 'Please use Object.defineProperty instead.', 226 | }, { 227 | property: '__defineSetter__', 228 | message: 'Please use Object.defineProperty instead.', 229 | }, { 230 | object: 'Math', 231 | property: 'pow', 232 | message: 'Use the exponentiation operator (**) instead.', 233 | }], 234 | 235 | // disallow use of assignment in return statement 236 | 'no-return-assign': ['error', 'always'], 237 | 238 | // disallow redundant `return await` 239 | 'no-return-await': 'error', 240 | 241 | // disallow use of `javascript:` urls. 242 | 'no-script-url': 'error', 243 | 244 | // disallow self assignment 245 | // https://eslint.org/docs/rules/no-self-assign 246 | 'no-self-assign': 'error', 247 | 248 | // disallow comparisons where both sides are exactly the same 249 | 'no-self-compare': 'error', 250 | 251 | // disallow use of comma operator 252 | 'no-sequences': 'error', 253 | 254 | // restrict what can be thrown as an exception 255 | 'no-throw-literal': 'error', 256 | 257 | // disallow unmodified conditions of loops 258 | // https://eslint.org/docs/rules/no-unmodified-loop-condition 259 | 'no-unmodified-loop-condition': 'off', 260 | 261 | // disallow usage of expressions in statement position 262 | 'no-unused-expressions': ['error', { 263 | allowShortCircuit: false, 264 | allowTernary: false, 265 | allowTaggedTemplates: false, 266 | }], 267 | 268 | // disallow unused labels 269 | // https://eslint.org/docs/rules/no-unused-labels 270 | 'no-unused-labels': 'error', 271 | 272 | // disallow unnecessary .call() and .apply() 273 | 'no-useless-call': 'off', 274 | 275 | // disallow useless string concatenation 276 | // https://eslint.org/docs/rules/no-useless-concat 277 | 'no-useless-concat': 'error', 278 | 279 | // disallow unnecessary string escaping 280 | // https://eslint.org/docs/rules/no-useless-escape 281 | 'no-useless-escape': 'error', 282 | 283 | // disallow redundant return; keywords 284 | // https://eslint.org/docs/rules/no-useless-return 285 | 'no-useless-return': 'error', 286 | 287 | // disallow use of void operator 288 | // https://eslint.org/docs/rules/no-void 289 | 'no-void': 'error', 290 | 291 | // disallow usage of configurable warning terms in comments: e.g. todo 292 | 'no-warning-comments': ['off', { terms: ['todo', 'fixme', 'xxx'], location: 'start' }], 293 | 294 | // disallow use of the with statement 295 | 'no-with': 'error', 296 | 297 | // require using Error objects as Promise rejection reasons 298 | // https://eslint.org/docs/rules/prefer-promise-reject-errors 299 | 'prefer-promise-reject-errors': ['error', { allowEmptyReject: true }], 300 | 301 | // require use of the second argument for parseInt() 302 | radix: 'error', 303 | 304 | // require `await` in `async function` (note: this is a horrible rule that should never be used) 305 | // https://eslint.org/docs/rules/require-await 306 | 'require-await': 'off', 307 | 308 | // requires to declare all vars on top of their containing scope 309 | 'vars-on-top': 'error', 310 | 311 | // require immediate function invocation to be wrapped in parentheses 312 | // https://eslint.org/docs/rules/wrap-iife.html 313 | 'wrap-iife': ['error', 'outside', { functionPrototypeMethods: false }], 314 | 315 | // require or disallow Yoda conditions 316 | yoda: 'error' 317 | } 318 | }; 319 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/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 await inside of loops 12 | // https://eslint.org/docs/rules/no-await-in-loop 13 | 'no-await-in-loop': 'error', 14 | 15 | // Disallow comparisons to negative zero 16 | // https://eslint.org/docs/rules/no-compare-neg-zero 17 | 'no-compare-neg-zero': 'error', 18 | 19 | // disallow assignment in conditional expressions 20 | 'no-cond-assign': ['error', 'always'], 21 | 22 | // disallow use of console 23 | 'no-console': 'warn', 24 | 25 | // disallow use of constant expressions in conditions 26 | 'no-constant-condition': 'warn', 27 | 28 | // disallow control characters in regular expressions 29 | 'no-control-regex': 'error', 30 | 31 | // disallow use of debugger 32 | 'no-debugger': 'error', 33 | 34 | // disallow duplicate arguments in functions 35 | 'no-dupe-args': 'error', 36 | 37 | // disallow duplicate keys when creating object literals 38 | 'no-dupe-keys': 'error', 39 | 40 | // disallow a duplicate case label. 41 | 'no-duplicate-case': 'error', 42 | 43 | // disallow empty statements 44 | 'no-empty': 'error', 45 | 46 | // disallow the use of empty character classes in regular expressions 47 | 'no-empty-character-class': 'error', 48 | 49 | // disallow assigning to the exception in a catch block 50 | 'no-ex-assign': 'error', 51 | 52 | // disallow double-negation boolean casts in a boolean context 53 | // https://eslint.org/docs/rules/no-extra-boolean-cast 54 | 'no-extra-boolean-cast': 'error', 55 | 56 | // disallow unnecessary parentheses 57 | // https://eslint.org/docs/rules/no-extra-parens 58 | 'no-extra-parens': ['off', 'all', { 59 | conditionalAssign: true, 60 | nestedBinaryExpressions: false, 61 | returnAssign: false, 62 | ignoreJSX: 'all', // delegate to eslint-plugin-react 63 | enforceForArrowConditionals: false, 64 | }], 65 | 66 | // disallow unnecessary semicolons 67 | 'no-extra-semi': 'error', 68 | 69 | // disallow overwriting functions written as function declarations 70 | 'no-func-assign': 'error', 71 | 72 | // disallow function or variable declarations in nested blocks 73 | 'no-inner-declarations': 'error', 74 | 75 | // disallow invalid regular expression strings in the RegExp constructor 76 | 'no-invalid-regexp': 'error', 77 | 78 | // disallow irregular whitespace outside of strings and comments 79 | 'no-irregular-whitespace': 'error', 80 | 81 | // disallow the use of object properties of the global object (Math and JSON) as functions 82 | 'no-obj-calls': 'error', 83 | 84 | // disallow use of Object.prototypes builtins directly 85 | // https://eslint.org/docs/rules/no-prototype-builtins 86 | 'no-prototype-builtins': 'error', 87 | 88 | // disallow multiple spaces in a regular expression literal 89 | 'no-regex-spaces': 'error', 90 | 91 | // disallow sparse arrays 92 | 'no-sparse-arrays': 'error', 93 | 94 | // Disallow template literal placeholder syntax in regular strings 95 | // https://eslint.org/docs/rules/no-template-curly-in-string 96 | 'no-template-curly-in-string': 'error', 97 | 98 | // Avoid code that looks like two expressions but is actually one 99 | // https://eslint.org/docs/rules/no-unexpected-multiline 100 | 'no-unexpected-multiline': 'error', 101 | 102 | // disallow unreachable statements after a return, throw, continue, or break statement 103 | 'no-unreachable': 'error', 104 | 105 | // disallow return/throw/break/continue inside finally blocks 106 | // https://eslint.org/docs/rules/no-unsafe-finally 107 | 'no-unsafe-finally': 'error', 108 | 109 | // disallow negating the left operand of relational operators 110 | // https://eslint.org/docs/rules/no-unsafe-negation 111 | 'no-unsafe-negation': 'error', 112 | // disallow negation of the left operand of an in expression 113 | // deprecated in favor of no-unsafe-negation 114 | 'no-negated-in-lhs': 'off', 115 | 116 | // disallow comparisons with the value NaN 117 | 'use-isnan': 'error', 118 | 119 | // ensure JSDoc comments are valid 120 | // https://eslint.org/docs/rules/valid-jsdoc 121 | 'valid-jsdoc': 'off', 122 | 123 | // ensure that the results of typeof are compared against a valid string 124 | // https://eslint.org/docs/rules/valid-typeof 125 | 'valid-typeof': ['error', { requireStringLiterals: true }], 126 | } 127 | }; 128 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/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 | // TODO: enable requireReturnForObjectLiteral? 18 | 'arrow-body-style': ['error', 'as-needed', { 19 | requireReturnForObjectLiteral: false, 20 | }], 21 | 22 | // require parens in arrow function arguments 23 | // https://eslint.org/docs/rules/arrow-parens 24 | 'arrow-parens': ['error', 'as-needed', { 25 | requireForBlockBody: true, 26 | }], 27 | 28 | // require space before/after arrow function's arrow 29 | // https://eslint.org/docs/rules/arrow-spacing 30 | 'arrow-spacing': ['error', { before: true, after: true }], 31 | 32 | // verify super() callings in constructors 33 | 'constructor-super': 'error', 34 | 35 | // enforce the spacing around the * in generator functions 36 | // https://eslint.org/docs/rules/generator-star-spacing 37 | 'generator-star-spacing': ['error', { before: false, after: true }], 38 | 39 | // disallow modifying variables of class declarations 40 | // https://eslint.org/docs/rules/no-class-assign 41 | 'no-class-assign': 'error', 42 | 43 | // disallow arrow functions where they could be confused with comparisons 44 | // https://eslint.org/docs/rules/no-confusing-arrow 45 | 'no-confusing-arrow': ['error', { 46 | allowParens: true, 47 | }], 48 | 49 | // disallow modifying variables that are declared using const 50 | 'no-const-assign': 'error', 51 | 52 | // disallow duplicate class members 53 | // https://eslint.org/docs/rules/no-dupe-class-members 54 | '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 specific imports 66 | // https://eslint.org/docs/rules/no-restricted-imports 67 | 'no-restricted-imports': ['off', { 68 | paths: [], 69 | patterns: [] 70 | }], 71 | 72 | // disallow to use this/super before super() calling in constructors. 73 | // https://eslint.org/docs/rules/no-this-before-super 74 | 'no-this-before-super': 'error', 75 | 76 | // disallow useless computed property keys 77 | // https://eslint.org/docs/rules/no-useless-computed-key 78 | 'no-useless-computed-key': 'error', 79 | 80 | // disallow unnecessary constructor 81 | // https://eslint.org/docs/rules/no-useless-constructor 82 | 'no-useless-constructor': 'error', 83 | 84 | // disallow renaming import, export, and destructured assignments to the same name 85 | // https://eslint.org/docs/rules/no-useless-rename 86 | 'no-useless-rename': ['error', { 87 | ignoreDestructuring: false, 88 | ignoreImport: false, 89 | ignoreExport: false, 90 | }], 91 | 92 | // require let or const instead of var 93 | 'no-var': 'error', 94 | 95 | // require method and property shorthand syntax for object literals 96 | // https://eslint.org/docs/rules/object-shorthand 97 | 'object-shorthand': ['error', 'always', { 98 | ignoreConstructors: false, 99 | avoidQuotes: true, 100 | }], 101 | 102 | // suggest using arrow functions as callbacks 103 | 'prefer-arrow-callback': ['error', { 104 | allowNamedFunctions: false, 105 | allowUnboundThis: true, 106 | }], 107 | 108 | // suggest using of const declaration for variables that are never modified after declared 109 | 'prefer-const': ['error', { 110 | destructuring: 'any', 111 | ignoreReadBeforeAssign: true, 112 | }], 113 | 114 | // Prefer destructuring from arrays and objects 115 | // https://eslint.org/docs/rules/prefer-destructuring 116 | 'prefer-destructuring': ['error', { 117 | VariableDeclarator: { 118 | array: false, 119 | object: true, 120 | }, 121 | AssignmentExpression: { 122 | array: true, 123 | object: true, 124 | }, 125 | }, { 126 | enforceForRenamedProperties: false, 127 | }], 128 | 129 | // disallow parseInt() in favor of binary, octal, and hexadecimal literals 130 | // https://eslint.org/docs/rules/prefer-numeric-literals 131 | 'prefer-numeric-literals': 'error', 132 | 133 | // suggest using Reflect methods where applicable 134 | // https://eslint.org/docs/rules/prefer-reflect 135 | 'prefer-reflect': 'off', 136 | 137 | // use rest parameters instead of arguments 138 | // https://eslint.org/docs/rules/prefer-rest-params 139 | 'prefer-rest-params': 'error', 140 | 141 | // suggest using the spread operator instead of .apply() 142 | // https://eslint.org/docs/rules/prefer-spread 143 | 'prefer-spread': 'error', 144 | 145 | // suggest using template literals instead of string concatenation 146 | // https://eslint.org/docs/rules/prefer-template 147 | 'prefer-template': 'error', 148 | 149 | // disallow generator functions that do not have yield 150 | // https://eslint.org/docs/rules/require-yield 151 | 'require-yield': 'error', 152 | 153 | // enforce spacing between object rest-spread 154 | // https://eslint.org/docs/rules/rest-spread-spacing 155 | 'rest-spread-spacing': ['error', 'never'], 156 | 157 | // import sorting 158 | // https://eslint.org/docs/rules/sort-imports 159 | 'sort-imports': ['off', { 160 | ignoreCase: false, 161 | ignoreMemberSort: false, 162 | memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'], 163 | }], 164 | 165 | // require a Symbol description 166 | // https://eslint.org/docs/rules/symbol-description 167 | 'symbol-description': 'error', 168 | 169 | // enforce usage of spacing in template strings 170 | // https://eslint.org/docs/rules/template-curly-spacing 171 | 'template-curly-spacing': 'error', 172 | 173 | // enforce spacing around the * in yield* expressions 174 | // https://eslint.org/docs/rules/yield-star-spacing 175 | 'yield-star-spacing': ['error', 'after'] 176 | } 177 | }; 178 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/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: ['.mjs', '.js', '.json'] 17 | } 18 | }, 19 | 'import/extensions': [ 20 | '.js', 21 | '.mjs', 22 | '.jsx', 23 | ], 24 | 'import/core-modules': [ 25 | ], 26 | 'import/ignore': [ 27 | 'node_modules', 28 | '\\.(coffee|scss|css|less|hbs|svg|json)$', 29 | ], 30 | }, 31 | 32 | rules: { 33 | // Static analysis: 34 | 35 | // ensure imports point to files/modules that can be resolved 36 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unresolved.md 37 | 'import/no-unresolved': ['error', { commonjs: true, caseSensitive: true }], 38 | 39 | // ensure named imports coupled with named exports 40 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/named.md#when-not-to-use-it 41 | 'import/named': 'error', 42 | 43 | // ensure default import coupled with default export 44 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/default.md#when-not-to-use-it 45 | 'import/default': 'off', 46 | 47 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/namespace.md 48 | 'import/namespace': 'off', 49 | 50 | // Helpful warnings: 51 | 52 | // disallow invalid exports, e.g. multiple defaults 53 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/export.md 54 | 'import/export': 'error', 55 | 56 | // do not allow a default import name to match a named export 57 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-as-default.md 58 | 'import/no-named-as-default': 'error', 59 | 60 | // warn on accessing default export property names that are also named exports 61 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-as-default-member.md 62 | 'import/no-named-as-default-member': 'error', 63 | 64 | // disallow use of jsdoc-marked-deprecated imports 65 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-deprecated.md 66 | 'import/no-deprecated': 'off', 67 | 68 | // Forbid the use of extraneous packages 69 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-extraneous-dependencies.md 70 | // paths are treated both as absolute paths, and relative to process.cwd() 71 | 'import/no-extraneous-dependencies': ['error', { 72 | devDependencies: [ 73 | 'test/**', // tape, common npm pattern 74 | 'tests/**', // also common npm pattern 75 | 'spec/**', // mocha, rspec-like pattern 76 | '**/__tests__/**', // jest pattern 77 | '**/__mocks__/**', // jest pattern 78 | 'test.{js,jsx}', // repos with a single test file 79 | 'test-*.{js,jsx}', // repos with multiple top-level test files 80 | '**/*{.,_}{test,spec}.{js,jsx}', // tests where the extension or filename suffix denotes that it is a test 81 | '**/jest.config.js', // jest config 82 | '**/webpack.config.js', // webpack config 83 | '**/webpack.config.*.js', // webpack config 84 | '**/rollup.config.js', // rollup config 85 | '**/rollup.config.*.js', // rollup config 86 | '**/gulpfile.js', // gulp config 87 | '**/gulpfile.*.js', // gulp config 88 | '**/Gruntfile{,.js}', // grunt config 89 | '**/protractor.conf.js', // protractor config 90 | '**/protractor.conf.*.js', // protractor config 91 | ], 92 | optionalDependencies: false, 93 | }], 94 | 95 | // Forbid mutable exports 96 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-mutable-exports.md 97 | 'import/no-mutable-exports': 'error', 98 | 99 | // Module systems: 100 | 101 | // disallow require() 102 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-commonjs.md 103 | 'import/no-commonjs': 'off', 104 | 105 | // disallow AMD require/define 106 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-amd.md 107 | 'import/no-amd': 'error', 108 | 109 | // No Node.js builtin modules 110 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-nodejs-modules.md 111 | // TODO: enable? 112 | 'import/no-nodejs-modules': 'off', 113 | 114 | // Style guide: 115 | 116 | // disallow non-import statements appearing before import statements 117 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/first.md 118 | 'import/first': ['error', 'absolute-first'], 119 | 120 | // disallow non-import statements appearing before import statements 121 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/imports-first.md 122 | // deprecated: use `import/first` 123 | 'import/imports-first': 'off', 124 | 125 | // disallow duplicate imports 126 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md 127 | 'import/no-duplicates': 'error', 128 | 129 | // disallow namespace imports 130 | // TODO: enable? 131 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-namespace.md 132 | 'import/no-namespace': 'off', 133 | 134 | // Ensure consistent use of file extension within the import path 135 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md 136 | 'import/extensions': ['error', 'ignorePackages', { 137 | js: 'never', 138 | mjs: 'never', 139 | jsx: 'never', 140 | }], 141 | 142 | // Enforce a convention in module import order 143 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/order.md 144 | // TODO: enable? 145 | 'import/order': ['off', { 146 | groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], 147 | 'newlines-between': 'never', 148 | }], 149 | 150 | // Require a newline after the last import/require in a group 151 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/newline-after-import.md 152 | 'import/newline-after-import': 'error', 153 | 154 | // Require modules with a single export to use a default export 155 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/prefer-default-export.md 156 | 'import/prefer-default-export': 'error', 157 | 158 | // Restrict which files can be imported in a given folder 159 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-restricted-paths.md 160 | 'import/no-restricted-paths': 'off', 161 | 162 | // Forbid modules to have too many dependencies 163 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/max-dependencies.md 164 | 'import/max-dependencies': ['off', { max: 10 }], 165 | 166 | // Forbid import of modules using absolute paths 167 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-absolute-path.md 168 | 'import/no-absolute-path': 'error', 169 | 170 | // Forbid require() calls with expressions 171 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-dynamic-require.md 172 | 'import/no-dynamic-require': 'error', 173 | 174 | // prevent importing the submodules of other modules 175 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-internal-modules.md 176 | 'import/no-internal-modules': ['off', { 177 | allow: [], 178 | }], 179 | 180 | // Warn if a module could be mistakenly parsed as a script by a consumer 181 | // leveraging Unambiguous JavaScript Grammar 182 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/unambiguous.md 183 | // this should not be enabled until this proposal has at least been *presented* to TC39. 184 | // At the moment, it's not a thing. 185 | 'import/unambiguous': 'off', 186 | 187 | // Forbid Webpack loader syntax in imports 188 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-webpack-loader-syntax.md 189 | 'import/no-webpack-loader-syntax': 'error', 190 | 191 | // Prevent unassigned imports 192 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unassigned-import.md 193 | // importing for side effects is perfectly acceptable, if you need side effects. 194 | 'import/no-unassigned-import': 'off', 195 | 196 | // Prevent importing the default as if it were named 197 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-default.md 198 | 'import/no-named-default': 'error', 199 | 200 | // Reports if a module's default export is unnamed 201 | // https://github.com/benmosher/eslint-plugin-import/blob/d9b712ac7fd1fddc391f7b234827925c160d956f/docs/rules/no-anonymous-default-export.md 202 | 'import/no-anonymous-default-export': ['off', { 203 | allowArray: false, 204 | allowArrowFunction: false, 205 | allowAnonymousClass: false, 206 | allowAnonymousFunction: false, 207 | allowLiteral: false, 208 | allowObject: false, 209 | }], 210 | 211 | // This rule enforces that all exports are declared at the bottom of the file. 212 | // https://github.com/benmosher/eslint-plugin-import/blob/98acd6afd04dcb6920b81330114e146dc8532ea4/docs/rules/exports-last.md 213 | // TODO: enable? 214 | 'import/exports-last': 'off', 215 | 216 | // Reports when named exports are not grouped together in a single export declaration 217 | // or when multiple assignments to CommonJS module.exports or exports object are present 218 | // in a single file. 219 | // https://github.com/benmosher/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/group-exports.md 220 | 'import/group-exports': 'off', 221 | 222 | // forbid default exports. this is a terrible rule, do not use it. 223 | // https://github.com/benmosher/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/no-default-export.md 224 | 'import/no-default-export': 'off', 225 | 226 | // Forbid a module from importing itself 227 | // https://github.com/benmosher/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/no-self-import.md 228 | 'import/no-self-import': 'error', 229 | 230 | // Forbid cyclical dependencies between modules 231 | // https://github.com/benmosher/eslint-plugin-import/blob/d81f48a2506182738409805f5272eff4d77c9348/docs/rules/no-cycle.md 232 | 'import/no-cycle': ['error', { maxDepth: Infinity }], 233 | 234 | // Ensures that there are no useless path segments 235 | // https://github.com/benmosher/eslint-plugin-import/issues/1032 236 | 'import/no-useless-path-segments': 'error', 237 | }, 238 | }; 239 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/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-airbnb-base/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-airbnb-base/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': ['error', '1tbs', { allowSingleLine: true }], 22 | 23 | // require camel case names 24 | camelcase: ['error', { properties: 'never' }], 25 | 26 | // enforce or disallow capitalization of the first letter of a comment 27 | // https://eslint.org/docs/rules/capitalized-comments 28 | 'capitalized-comments': ['off', 'never', { 29 | line: { 30 | ignorePattern: '.*', 31 | ignoreInlineComments: true, 32 | ignoreConsecutiveComments: true, 33 | }, 34 | block: { 35 | ignorePattern: '.*', 36 | ignoreInlineComments: true, 37 | ignoreConsecutiveComments: true, 38 | }, 39 | }], 40 | 41 | // require trailing commas in multiline object literals 42 | 'comma-dangle': ['error', { 43 | arrays: 'always-multiline', 44 | objects: 'always-multiline', 45 | imports: 'always-multiline', 46 | exports: 'always-multiline', 47 | functions: 'always-multiline', 48 | }], 49 | 50 | // enforce spacing before and after comma 51 | 'comma-spacing': ['error', { before: false, after: true }], 52 | 53 | // enforce one true comma style 54 | 'comma-style': ['error', 'last', { 55 | exceptions: { 56 | ArrayExpression: false, 57 | ArrayPattern: false, 58 | ArrowFunctionExpression: false, 59 | CallExpression: false, 60 | FunctionDeclaration: false, 61 | FunctionExpression: false, 62 | ImportDeclaration: false, 63 | ObjectExpression: false, 64 | ObjectPattern: false, 65 | VariableDeclaration: false, 66 | NewExpression: false, 67 | } 68 | }], 69 | 70 | // disallow padding inside computed properties 71 | 'computed-property-spacing': ['error', 'never'], 72 | 73 | // enforces consistent naming when capturing the current execution context 74 | 'consistent-this': 'off', 75 | 76 | // enforce newline at the end of file, with no multiple empty lines 77 | 'eol-last': ['error', 'always'], 78 | 79 | // enforce spacing between functions and their invocations 80 | // https://eslint.org/docs/rules/func-call-spacing 81 | 'func-call-spacing': ['error', 'never'], 82 | 83 | // requires function names to match the name of the variable or property to which they are 84 | // assigned 85 | // https://eslint.org/docs/rules/func-name-matching 86 | 'func-name-matching': ['off', 'always', { 87 | includeCommonJSModuleExports: false 88 | }], 89 | 90 | // require function expressions to have a name 91 | // https://eslint.org/docs/rules/func-names 92 | 'func-names': 'warn', 93 | 94 | // enforces use of function declarations or expressions 95 | // https://eslint.org/docs/rules/func-style 96 | // TODO: enable 97 | 'func-style': ['off', 'expression'], 98 | 99 | // enforce consistent line breaks inside function parentheses 100 | // https://eslint.org/docs/rules/function-paren-newline 101 | 'function-paren-newline': ['error', 'consistent'], 102 | 103 | // Blacklist certain identifiers to prevent them being used 104 | // https://eslint.org/docs/rules/id-blacklist 105 | 'id-blacklist': 'off', 106 | 107 | // this option enforces minimum and maximum identifier lengths 108 | // (variable names, property names etc.) 109 | 'id-length': 'off', 110 | 111 | // require identifiers to match the provided regular expression 112 | 'id-match': 'off', 113 | 114 | // Enforce the location of arrow function bodies with implicit returns 115 | // https://eslint.org/docs/rules/implicit-arrow-linebreak 116 | 'implicit-arrow-linebreak': ['error', 'beside'], 117 | 118 | // this option sets a specific tab width for your code 119 | // https://eslint.org/docs/rules/indent 120 | indent: ['error', 2, { 121 | SwitchCase: 1, 122 | VariableDeclarator: 1, 123 | outerIIFEBody: 1, 124 | // MemberExpression: null, 125 | FunctionDeclaration: { 126 | parameters: 1, 127 | body: 1 128 | }, 129 | FunctionExpression: { 130 | parameters: 1, 131 | body: 1 132 | }, 133 | CallExpression: { 134 | arguments: 1 135 | }, 136 | ArrayExpression: 1, 137 | ObjectExpression: 1, 138 | ImportDeclaration: 1, 139 | flatTernaryExpressions: false, 140 | // list derived from https://github.com/benjamn/ast-types/blob/HEAD/def/jsx.js 141 | ignoredNodes: ['JSXElement', 'JSXElement > *', 'JSXAttribute', 'JSXIdentifier', 'JSXNamespacedName', 'JSXMemberExpression', 'JSXSpreadAttribute', 'JSXExpressionContainer', 'JSXOpeningElement', 'JSXClosingElement', 'JSXText', 'JSXEmptyExpression', 'JSXSpreadChild'], 142 | ignoreComments: false 143 | }], 144 | 145 | // specify whether double or single quotes should be used in JSX attributes 146 | // https://eslint.org/docs/rules/jsx-quotes 147 | 'jsx-quotes': ['off', 'prefer-double'], 148 | 149 | // enforces spacing between keys and values in object literal properties 150 | 'key-spacing': ['error', { beforeColon: false, afterColon: true }], 151 | 152 | // require a space before & after certain keywords 153 | 'keyword-spacing': ['error', { 154 | before: true, 155 | after: true, 156 | overrides: { 157 | return: { after: true }, 158 | throw: { after: true }, 159 | case: { after: true } 160 | } 161 | }], 162 | 163 | // enforce position of line comments 164 | // https://eslint.org/docs/rules/line-comment-position 165 | // TODO: enable? 166 | 'line-comment-position': ['off', { 167 | position: 'above', 168 | ignorePattern: '', 169 | applyDefaultPatterns: true, 170 | }], 171 | 172 | // disallow mixed 'LF' and 'CRLF' as linebreaks 173 | // https://eslint.org/docs/rules/linebreak-style 174 | 'linebreak-style': ['error', 'unix'], 175 | 176 | // require or disallow an empty line between class members 177 | // https://eslint.org/docs/rules/lines-between-class-members 178 | 'lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: false }], 179 | 180 | // enforces empty lines around comments 181 | 'lines-around-comment': 'off', 182 | 183 | // require or disallow newlines around directives 184 | // https://eslint.org/docs/rules/lines-around-directive 185 | 'lines-around-directive': ['error', { 186 | before: 'always', 187 | after: 'always', 188 | }], 189 | 190 | // specify the maximum depth that blocks can be nested 191 | 'max-depth': ['off', 4], 192 | 193 | // specify the maximum length of a line in your program 194 | // https://eslint.org/docs/rules/max-len 195 | 'max-len': ['error', 100, 2, { 196 | ignoreUrls: true, 197 | ignoreComments: false, 198 | ignoreRegExpLiterals: true, 199 | ignoreStrings: true, 200 | ignoreTemplateLiterals: true, 201 | }], 202 | 203 | // specify the max number of lines in a file 204 | // https://eslint.org/docs/rules/max-lines 205 | 'max-lines': ['off', { 206 | max: 300, 207 | skipBlankLines: true, 208 | skipComments: true 209 | }], 210 | 211 | // specify the maximum depth callbacks can be nested 212 | 'max-nested-callbacks': 'off', 213 | 214 | // limits the number of parameters that can be used in the function declaration. 215 | 'max-params': ['off', 3], 216 | 217 | // specify the maximum number of statement allowed in a function 218 | 'max-statements': ['off', 10], 219 | 220 | // restrict the number of statements per line 221 | // https://eslint.org/docs/rules/max-statements-per-line 222 | 'max-statements-per-line': ['off', { max: 1 }], 223 | 224 | // enforce a particular style for multiline comments 225 | // https://eslint.org/docs/rules/multiline-comment-style 226 | 'multiline-comment-style': ['off', 'starred-block'], 227 | 228 | // require multiline ternary 229 | // https://eslint.org/docs/rules/multiline-ternary 230 | // TODO: enable? 231 | 'multiline-ternary': ['off', 'never'], 232 | 233 | // require a capital letter for constructors 234 | 'new-cap': ['error', { 235 | newIsCap: true, 236 | newIsCapExceptions: [], 237 | capIsNew: false, 238 | capIsNewExceptions: ['Immutable.Map', 'Immutable.Set', 'Immutable.List'], 239 | }], 240 | 241 | // disallow the omission of parentheses when invoking a constructor with no arguments 242 | // https://eslint.org/docs/rules/new-parens 243 | 'new-parens': 'error', 244 | 245 | // allow/disallow an empty newline after var statement 246 | 'newline-after-var': 'off', 247 | 248 | // https://eslint.org/docs/rules/newline-before-return 249 | 'newline-before-return': 'off', 250 | 251 | // enforces new line after each method call in the chain to make it 252 | // more readable and easy to maintain 253 | // https://eslint.org/docs/rules/newline-per-chained-call 254 | 'newline-per-chained-call': ['error', { ignoreChainWithDepth: 4 }], 255 | 256 | // disallow use of the Array constructor 257 | 'no-array-constructor': 'error', 258 | 259 | // disallow use of bitwise operators 260 | // https://eslint.org/docs/rules/no-bitwise 261 | 'no-bitwise': 'error', 262 | 263 | // disallow use of the continue statement 264 | // https://eslint.org/docs/rules/no-continue 265 | 'no-continue': 'error', 266 | 267 | // disallow comments inline after code 268 | 'no-inline-comments': 'off', 269 | 270 | // disallow if as the only statement in an else block 271 | // https://eslint.org/docs/rules/no-lonely-if 272 | 'no-lonely-if': 'error', 273 | 274 | // disallow un-paren'd mixes of different operators 275 | // https://eslint.org/docs/rules/no-mixed-operators 276 | 'no-mixed-operators': ['error', { 277 | // the list of arthmetic groups disallows mixing `%` and `**` 278 | // with other arithmetic operators. 279 | groups: [ 280 | ['%', '**'], 281 | ['%', '+'], 282 | ['%', '-'], 283 | ['%', '*'], 284 | ['%', '/'], 285 | ['**', '+'], 286 | ['**', '-'], 287 | ['**', '*'], 288 | ['**', '/'], 289 | ['&', '|', '^', '~', '<<', '>>', '>>>'], 290 | ['==', '!=', '===', '!==', '>', '>=', '<', '<='], 291 | ['&&', '||'], 292 | ['in', 'instanceof'] 293 | ], 294 | allowSamePrecedence: false 295 | }], 296 | 297 | // disallow mixed spaces and tabs for indentation 298 | 'no-mixed-spaces-and-tabs': 'error', 299 | 300 | // disallow use of chained assignment expressions 301 | // https://eslint.org/docs/rules/no-multi-assign 302 | 'no-multi-assign': ['error'], 303 | 304 | // disallow multiple empty lines and only one newline at the end 305 | 'no-multiple-empty-lines': ['error', { max: 2, maxEOF: 0 }], 306 | 307 | // disallow negated conditions 308 | // https://eslint.org/docs/rules/no-negated-condition 309 | 'no-negated-condition': 'off', 310 | 311 | // disallow nested ternary expressions 312 | 'no-nested-ternary': 'error', 313 | 314 | // disallow use of the Object constructor 315 | 'no-new-object': 'error', 316 | 317 | // disallow use of unary operators, ++ and -- 318 | // https://eslint.org/docs/rules/no-plusplus 319 | 'no-plusplus': 'error', 320 | 321 | // disallow certain syntax forms 322 | // https://eslint.org/docs/rules/no-restricted-syntax 323 | 'no-restricted-syntax': [ 324 | 'error', 325 | { 326 | selector: 'ForInStatement', 327 | message: '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.', 328 | }, 329 | { 330 | selector: 'ForOfStatement', 331 | message: '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.', 332 | }, 333 | { 334 | selector: 'LabeledStatement', 335 | message: 'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.', 336 | }, 337 | { 338 | selector: 'WithStatement', 339 | message: '`with` is disallowed in strict mode because it makes code impossible to predict and optimize.', 340 | }, 341 | ], 342 | 343 | // disallow space between function identifier and application 344 | 'no-spaced-func': 'error', 345 | 346 | // disallow tab characters entirely 347 | 'no-tabs': 'error', 348 | 349 | // disallow the use of ternary operators 350 | 'no-ternary': 'off', 351 | 352 | // disallow trailing whitespace at the end of lines 353 | 'no-trailing-spaces': ['error', { 354 | skipBlankLines: false, 355 | ignoreComments: false, 356 | }], 357 | 358 | // disallow dangling underscores in identifiers 359 | 'no-underscore-dangle': ['error', { 360 | allow: [], 361 | allowAfterThis: false, 362 | allowAfterSuper: false, 363 | enforceInMethodNames: false, 364 | }], 365 | 366 | // disallow the use of Boolean literals in conditional expressions 367 | // also, prefer `a || b` over `a ? a : b` 368 | // https://eslint.org/docs/rules/no-unneeded-ternary 369 | 'no-unneeded-ternary': ['error', { defaultAssignment: false }], 370 | 371 | // disallow whitespace before properties 372 | // https://eslint.org/docs/rules/no-whitespace-before-property 373 | 'no-whitespace-before-property': 'error', 374 | 375 | // enforce the location of single-line statements 376 | // https://eslint.org/docs/rules/nonblock-statement-body-position 377 | 'nonblock-statement-body-position': ['error', 'beside', { overrides: {} }], 378 | 379 | // require padding inside curly braces 380 | 'object-curly-spacing': ['error', 'always'], 381 | 382 | // enforce line breaks between braces 383 | // https://eslint.org/docs/rules/object-curly-newline 384 | 'object-curly-newline': ['error', { 385 | ObjectExpression: { minProperties: 4, multiline: true, consistent: true }, 386 | ObjectPattern: { minProperties: 4, multiline: true, consistent: true }, 387 | ImportDeclaration: { minProperties: 4, multiline: true, consistent: true }, 388 | ExportDeclaration: { minProperties: 4, multiline: true, consistent: true }, 389 | }], 390 | 391 | // enforce "same line" or "multiple line" on object properties. 392 | // https://eslint.org/docs/rules/object-property-newline 393 | 'object-property-newline': ['error', { 394 | allowAllPropertiesOnSameLine: true, 395 | }], 396 | 397 | // allow just one var statement per function 398 | 'one-var': ['error', 'never'], 399 | 400 | // require a newline around variable declaration 401 | // https://eslint.org/docs/rules/one-var-declaration-per-line 402 | 'one-var-declaration-per-line': ['error', 'always'], 403 | 404 | // require assignment operator shorthand where possible or prohibit it entirely 405 | // https://eslint.org/docs/rules/operator-assignment 406 | 'operator-assignment': ['error', 'always'], 407 | 408 | // Requires operator at the beginning of the line in multiline statements 409 | // https://eslint.org/docs/rules/operator-linebreak 410 | 'operator-linebreak': ['error', 'before', { overrides: { '=': 'none' } }], 411 | 412 | // disallow padding within blocks 413 | 'padded-blocks': ['error', { blocks: 'never', classes: 'never', switches: 'never' }], 414 | 415 | // Require or disallow padding lines between statements 416 | // https://eslint.org/docs/rules/padding-line-between-statements 417 | 'padding-line-between-statements': 'off', 418 | 419 | // require quotes around object literal property names 420 | // https://eslint.org/docs/rules/quote-props.html 421 | 'quote-props': ['error', 'as-needed', { keywords: false, unnecessary: true, numbers: false }], 422 | 423 | // specify whether double or single quotes should be used 424 | quotes: ['error', 'single', { avoidEscape: true }], 425 | 426 | // do not require jsdoc 427 | // https://eslint.org/docs/rules/require-jsdoc 428 | 'require-jsdoc': 'off', 429 | 430 | // require or disallow use of semicolons instead of ASI 431 | semi: ['error', 'always'], 432 | 433 | // enforce spacing before and after semicolons 434 | 'semi-spacing': ['error', { before: false, after: true }], 435 | 436 | // Enforce location of semicolons 437 | // https://eslint.org/docs/rules/semi-style 438 | 'semi-style': ['error', 'last'], 439 | 440 | // requires object keys to be sorted 441 | 'sort-keys': ['off', 'asc', { caseSensitive: false, natural: true }], 442 | 443 | // sort variables within the same declaration block 444 | 'sort-vars': 'off', 445 | 446 | // require or disallow space before blocks 447 | 'space-before-blocks': 'error', 448 | 449 | // require or disallow space before function opening parenthesis 450 | // https://eslint.org/docs/rules/space-before-function-paren 451 | 'space-before-function-paren': ['error', { 452 | anonymous: 'always', 453 | named: 'never', 454 | asyncArrow: 'always' 455 | }], 456 | 457 | // require or disallow spaces inside parentheses 458 | 'space-in-parens': ['error', 'never'], 459 | 460 | // require spaces around operators 461 | 'space-infix-ops': 'error', 462 | 463 | // Require or disallow spaces before/after unary operators 464 | // https://eslint.org/docs/rules/space-unary-ops 465 | 'space-unary-ops': ['error', { 466 | words: true, 467 | nonwords: false, 468 | overrides: { 469 | }, 470 | }], 471 | 472 | // require or disallow a space immediately following the // or /* in a comment 473 | // https://eslint.org/docs/rules/spaced-comment 474 | 'spaced-comment': ['error', 'always', { 475 | line: { 476 | exceptions: ['-', '+'], 477 | markers: ['=', '!'], // space here to support sprockets directives 478 | }, 479 | block: { 480 | exceptions: ['-', '+'], 481 | markers: ['=', '!'], // space here to support sprockets directives 482 | balanced: true, 483 | } 484 | }], 485 | 486 | // Enforce spacing around colons of switch statements 487 | // https://eslint.org/docs/rules/switch-colon-spacing 488 | 'switch-colon-spacing': ['error', { after: true, before: false }], 489 | 490 | // Require or disallow spacing between template tags and their literals 491 | // https://eslint.org/docs/rules/template-tag-spacing 492 | 'template-tag-spacing': ['error', 'never'], 493 | 494 | // require or disallow the Unicode Byte Order Mark 495 | // https://eslint.org/docs/rules/unicode-bom 496 | 'unicode-bom': ['error', 'never'], 497 | 498 | // require regex literals to be wrapped in parentheses 499 | 'wrap-regex': 'off' 500 | } 501 | }; 502 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/rules/variables.js: -------------------------------------------------------------------------------- 1 | const restrictedGlobals = require('eslint-restricted-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': ['error', 'isFinite', 'isNaN'].concat(restrictedGlobals), 20 | 21 | // disallow declaration of variables already declared in the outer scope 22 | 'no-shadow': 'error', 23 | 24 | // disallow shadowing of names such as arguments 25 | 'no-shadow-restricted-names': 'error', 26 | 27 | // disallow use of undeclared variables unless mentioned in a /*global */ block 28 | 'no-undef': 'error', 29 | 30 | // disallow use of undefined when initializing variables 31 | 'no-undef-init': 'error', 32 | 33 | // disallow use of undefined variable 34 | // https://eslint.org/docs/rules/no-undefined 35 | // TODO: enable? 36 | 'no-undefined': 'off', 37 | 38 | // disallow declaration of variables that are not used in the code 39 | 'no-unused-vars': ['error', { vars: 'all', args: 'after-used', ignoreRestSiblings: true }], 40 | 41 | // disallow use of variables before they are defined 42 | 'no-use-before-define': ['error', { functions: true, classes: true, variables: true }], 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | // disabled because I find it tedious to write tests while following this rule 4 | "no-shadow": 0, 5 | // tests uses `t` for tape 6 | "id-length": [2, {"min": 2, "properties": "never", "exceptions": ["t"]}], 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/test/requires.js: -------------------------------------------------------------------------------- 1 | /* eslint 2 | strict: 0, 3 | global-require: 0, 4 | */ 5 | 6 | 'use strict'; 7 | 8 | const test = require('tape'); 9 | 10 | test('all entry points parse', (t) => { 11 | t.doesNotThrow(() => require('..'), 'index does not throw'); 12 | t.doesNotThrow(() => require('../legacy'), 'legacy does not throw'); 13 | t.doesNotThrow(() => require('../whitespace'), 'whitespace does not throw'); 14 | 15 | t.end(); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/test/test-base.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import test from 'tape'; 4 | 5 | import index from '..'; 6 | 7 | const files = { ...{ index } }; // object spread is to test parsing 8 | 9 | fs.readdirSync(path.join(__dirname, '../rules')).forEach((name) => { 10 | // eslint-disable-next-line import/no-dynamic-require 11 | files[name] = require(`../rules/${name}`); // eslint-disable-line global-require 12 | }); 13 | 14 | Object.keys(files).forEach(( 15 | name, // trailing function comma is to test parsing 16 | ) => { 17 | const config = files[name]; 18 | 19 | test(`${name}: does not reference react`, (t) => { 20 | t.plan(2); 21 | 22 | // scan plugins for react and fail if it is found 23 | const hasReactPlugin = Object.prototype.hasOwnProperty.call(config, 'plugins') 24 | && config.plugins.indexOf('react') !== -1; 25 | t.notOk(hasReactPlugin, 'there is no react plugin'); 26 | 27 | // scan rules for react/ and fail if any exist 28 | const reactRuleIds = Object.keys(config.rules) 29 | .filter(ruleId => ruleId.indexOf('react/') === 0); 30 | t.deepEquals(reactRuleIds, [], 'there are no react/ rules'); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb-base/whitespace.js: -------------------------------------------------------------------------------- 1 | const baseConfig = require('.'); 2 | const assign = require('object.assign'); 3 | const entries = require('object.entries'); 4 | const CLIEngine = require('eslint').CLIEngine; 5 | 6 | function onlyErrorOnRules(rulesToError, config) { 7 | const errorsOnly = assign({}, config); 8 | const cli = new CLIEngine({ baseConfig: config, useEslintrc: false }); 9 | const baseRules = cli.getConfigForFile('./').rules; 10 | 11 | entries(baseRules).forEach((rule) => { 12 | const ruleName = rule[0]; 13 | const ruleConfig = rule[1]; 14 | 15 | if (rulesToError.indexOf(ruleName) === -1) { 16 | if (Array.isArray(ruleConfig)) { 17 | errorsOnly.rules[ruleName] = ['warn'].concat(ruleConfig.slice(1)); 18 | } else if (typeof ruleConfig === 'number') { 19 | errorsOnly.rules[ruleName] = 1; 20 | } else { 21 | errorsOnly.rules[ruleName] = 'warn'; 22 | } 23 | } 24 | }); 25 | 26 | return errorsOnly; 27 | } 28 | 29 | module.exports = onlyErrorOnRules([ 30 | 'array-bracket-newline', 31 | 'array-bracket-spacing', 32 | 'array-element-newline', 33 | 'arrow-spacing', 34 | 'block-spacing', 35 | 'comma-spacing', 36 | 'computed-property-spacing', 37 | 'dot-location', 38 | 'eol-last', 39 | 'func-call-spacing', 40 | 'function-paren-newline', 41 | 'generator-star-spacing', 42 | 'implicit-arrow-linebreak', 43 | 'indent', 44 | 'key-spacing', 45 | 'keyword-spacing', 46 | 'line-comment-position', 47 | 'linebreak-style', 48 | 'multiline-ternary', 49 | 'newline-per-chained-call', 50 | 'no-irregular-whitespace', 51 | 'no-mixed-spaces-and-tabs', 52 | 'no-multi-spaces', 53 | 'no-regex-spaces', 54 | 'no-spaced-func', 55 | 'no-trailing-spaces', 56 | 'no-whitespace-before-property', 57 | 'nonblock-statement-body-position', 58 | 'object-curly-newline', 59 | 'object-curly-spacing', 60 | 'object-property-newline', 61 | 'one-var-declaration-per-line', 62 | 'operator-linebreak', 63 | 'padded-blocks', 64 | 'padding-line-between-statements', 65 | 'rest-spread-spacing', 66 | 'semi-spacing', 67 | 'semi-style', 68 | 'space-before-blocks', 69 | 'space-before-function-paren', 70 | 'space-in-parens', 71 | 'space-infix-ops', 72 | 'space-unary-ops', 73 | 'spaced-comment', 74 | 'switch-colon-spacing', 75 | 'template-tag-spacing', 76 | 'import/newline-after-import', 77 | ], baseConfig); 78 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["airbnb"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/.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 = null 12 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./index.js", 3 | "rules": { 4 | // disable requiring trailing commas because it might be nice to revert to 5 | // being JSON at some point, and I don't want to make big changes now. 6 | "comma-dangle": 0, 7 | // we support node 4 8 | "prefer-destructuring": 0, 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 16.1.0 / 2017-10-16 2 | ================== 3 | - [deps] update `eslint-config-airbnb-base`, `eslint` to v4.9 4 | 5 | 16.0.0 / 2017-10-06 6 | ================== 7 | - [breaking] [deps] require `eslint` `v4`, update `eslint-config-airbnb-base` 8 | - [breaking] [deps] Upgrade `eslint-plugin-jsx-a11y` to `v6`; enable more a11y rules (#1482) 9 | - [breaking] enable/add react rules: `react/jsx-curly-brace-presence`, `react/no-typos`, `react/no-unused-state`, `react/no-redundant-should-component-update`, `react/default-props-match-prop-types` 10 | - [new] add `propWrapperFunctions` default settings for `eslint-plugin-react` 11 | - [new] Enable `react/jsx-closing-tag-location` (#1533) 12 | - [deps] update `eslint` v4, `eslint-plugin-react`, `tape` 13 | - [docs] Specify yarn-specific install instructions (#1511) 14 | 15 | 15.1.0 / 2017-07-24 16 | ================== 17 | - [deps] allow eslint v3 or v4 (#1447) 18 | - [deps] update `eslint-plugin-import`, `eslint-config-airbnb-base` 19 | 20 | 15.0.2 / 2017-07-04 21 | ================== 22 | - [fix] jsx should be enabled via parserOptions, not via a root ecmaFeatures 23 | - [deps] update `babel-preset-airbnb`, `eslint-find-rules`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `tape` 24 | 25 | 15.0.1 / 2017-05-15 26 | ================== 27 | - [fix] set default React version to 15.0 (#1415) 28 | 29 | 15.0.0 / 2017-05-14 30 | ================== 31 | - [breaking] set default React version to 0.15 32 | - [breaking] `update eslint-plugin-jsx-a11y` to v5, enable new rules 33 | - [breaking] `update eslint-plugin-react` to v7, enable new rules 34 | - [minor] enable rules: `jsx-max-props-per-line`, `void-dom-elements-no-children` 35 | - [patch] Turn `ignorePureComponents` option on for react/prefer-stateless-function (#1378, #1398) 36 | - [deps] update `eslint`, `eslint-plugin-react`, `eslint-config-airbnb-base` 37 | 38 | 14.1.0 / 2017-02-05 39 | ================== 40 | - [patch] allow `eslint-plugin-jsx-a11y` to be v3 or v4. Remove `no-marquee` rule temporarily. 41 | - [deps] update `eslint-config-airbnb-base`, `babel-preset-airbnb`, `eslint` 42 | 43 | 14.0.0 / 2017-01-08 44 | ================== 45 | - [breaking] enable `react/no-array-index-key`, `react/require-default-props` 46 | - [breaking] [deps] update `eslint`, `eslint-plugin-import`, `eslint-plugin-react`, `eslint-config-airbnb-base` 47 | - [breaking] [deps] update `eslint-plugin-jsx-a11y` to v3 (#1166) 48 | - [docs] add note about `install-peerdeps` (#1234) 49 | - [docs] Updated instructions to support non-bash users (#1214) 50 | 51 | 13.0.0 / 2016-11-06 52 | ================== 53 | - [breaking] Enable `import/no-webpack-loader-syntax` rule (#1123) 54 | - [patch] `class-methods-use-this`: exempt React `getChildContext` (#1094) 55 | - [patch] set `react/no-unused-prop-types` skipShapeProps (#1099) 56 | - [deps] [breaking] update `eslint`, `eslint-config-airbnb-base`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `eslint-plugin-import` 57 | - [dev deps] update `babel-preset-airbnb`, `eslint`, `eslint-find-rules`, `tape`, `safe-publish-latest` 58 | - [Tests] on `node` `v7` 59 | - [docs] ensure latest version of config is installed (#1121) 60 | 61 | 12.0.0 / 2016-09-24 62 | ================== 63 | - [breaking] Enable react rules: `react/no-unescaped-entities`, `react/no-children-prop` 64 | - [breaking] [deps] update `eslint-config-airbnb-base` 65 | - [patch] disable deprecated and redundant `react/require-extension` rule (#978) 66 | 67 | 11.2.0 / 2016-09-23 68 | ================== 69 | - [new] set `ecmaVersion` to 2017; enable object rest/spread; update `babel-preset-airbnb` 70 | - [deps] update `eslint`, `eslint-config-airbnb-base`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `eslint-find-rules`, `safe-publish-latest` 71 | 72 | 11.1.0 / 2016-09-11 73 | ================== 74 | - [deps] update `eslint-config-airbnb-base`, `eslint` 75 | 76 | 11.0.0 / 2016-09-08 77 | ================== 78 | - [breaking] enable `react` rules: `react/no-danger-with-children`, `react/no-unused-prop-types`, `react/style-prop-object`, `react/forbid-prop-types`, `react/jsx-no-duplicate-props`; set `react/no-danger` to “warn” 79 | - [breaking] enable `jsx-a11y` rules: `jsx-a11y/anchor-has-content`, `jsx-a11y/tabindex-no-positive`, `jsx-a11y/no-static-element-interactions` 80 | - [deps] update `eslint`, `eslint-plugin-react`, `eslint-config-airbnb-base`, `eslint-find-rules`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y` 81 | - [patch] set `ignoreCase` to `true` in disabled rules. 82 | - [docs] use “#” in example command rather than version numbers (#984) 83 | 84 | 10.0.1 / 2016-08-12 85 | ================== 86 | - [deps] update `eslint`, `eslint-find-rules`, `eslint-plugin-jsx-a11y`, `eslint-plugin-import`, `eslint-config-airbnb-base` 87 | 88 | 10.0.0 / 2016-08-01 89 | ================== 90 | - [breaking] enable jsx-a11y rules: 91 | - `jsx-a11y/heading-has-content` 92 | - `jsx-a11y/html-has-lang` 93 | - `jsx-a11y/lang` 94 | - `jsx-a11y/no-marquee` 95 | - `jsx-a11y/scope` 96 | - `jsx-a11y/href-no-hash` 97 | - `jsx-a11y/label-has-for` 98 | - [breaking] enable aria rules: 99 | - `jsx-a11y/aria-props` 100 | - `jsx-a11y/aria-proptypes` 101 | - `jsx-a11y/aria-unsupported-elements` 102 | - `jsx-a11y/role-has-required-aria-props` 103 | - `jsx-a11y/role-supports-aria-props` 104 | - [breaking] enable react rules: 105 | - `react/jsx-filename-extension` 106 | - `react/jsx-no-comment-textnodes` 107 | - `react/jsx-no-target-blank` 108 | - `react/require-extension` 109 | - `react/no-render-return-value` 110 | - `react/no-find-dom-node` 111 | - `react/no-deprecated` 112 | - [deps] [breaking] update `eslint` to v3, `eslint-config-airbnb-base` to v5, `eslint-find-rules`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y` to v2, `eslint-plugin-react` to v6, `tape`. drop node < 4 support. 113 | - [deps] update `eslint-config-airbnb-base`, `eslint-plugin-react`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `babel-tape-runner`, add `babel-preset-airbnb`. ensure react is `>=` 0.13.0 114 | - [patch] loosen `jsx-pascal-case` rule to allow all caps component names 115 | - [tests] stop testing < node 4 116 | - [tests] use `in-publish` because coffeescript screwed up the prepublish script for everyone 117 | - [tests] Only run `eslint-find-rules` on prepublish, not in tests 118 | - [tests] Even though the base config may not be up to date in the main package, let’s `npm link` the base package into the main one for the sake of travis-ci tests 119 | - [docs] update the peer dep install command to dynamically look up the right version numbers when installing peer deps 120 | - add `safe-publish-latest` to `prepublish` 121 | 122 | 9.0.1 / 2016-05-08 123 | ================== 124 | - [patch] update `eslint-config-airbnb-base` to v3.0.1 125 | 126 | 9.0.0 / 2016-05-07 127 | ================== 128 | - [breaking] update `eslint-config-airbnb-base` to v3 129 | - [deps] update `eslint-find-rules`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y` 130 | 131 | 8.0.0 / 2016-04-21 132 | ================== 133 | - [breaking] Migrate non-React rules to a separate linter config (`eslint-config-airbnb-base`) 134 | - [breaking] disallow empty methods 135 | - [breaking] disallow empty restructuring patterns 136 | - [breaking] enable `no-restricted-syntax` rule 137 | - [breaking] enable `global-require` rule 138 | - [breaking] [react] enable `react/jsx-curly-spacing` rule ([#693](https://github.com/airbnb/javascript/issues/693)) 139 | - [semver-minor] [react] Add `react/jsx-first-prop-new-line` rule 140 | - [semver-minor] [react] enable `jsx-equals-spacing` rule 141 | - [semver-minor] [react] enable `jsx-indent` rule 142 | - [semver-minor] enforce spacing inside single-line blocks 143 | - [semver-minor] enforce `no-underscore-dangle` 144 | - [semver-minor] Enable import/no-unresolved and import/export rules ([#825](https://github.com/airbnb/javascript/issues/825)) 145 | - [semver-patch] Enable `no-useless-concat` rule which `prefer-template` already covers 146 | - [semver-patch] Allow `== null` ([#542](https://github.com/airbnb/javascript/issues/542)) 147 | - [dev deps / peer deps] update `eslint`, `eslint-plugin-react`, `eslint-plugin-import` 148 | - [dev deps / peer deps] update `eslint-plugin-jsx-a11y` and rename rules ([#838](https://github.com/airbnb/javascript/issues/838)) 149 | - [refactor] [react] separate a11y rules to their own file 150 | - [refactor] Add missing disabled rules. 151 | - [tests] Add `eslint-find-rules` to prevent missing rules 152 | 153 | 7.0.0 / 2016-04-11 154 | ================== 155 | - [react] [breaking] Add accessibility rules to the React style guide + `eslint-plugin-a11y` 156 | - [breaking] enable `react/require-render-return` 157 | - [breaking] Add `no-dupe-class-members` rule + section ([#785](https://github.com/airbnb/javascript/issues/785)) 158 | - [breaking] error on debugger statements 159 | - [breaking] add `no-useless-escape` rule 160 | - [breaking] add `no-duplicate-imports` rule 161 | - [semver-minor] enable `jsx-pascal-case` rule 162 | - [deps] update `eslint`, `react` 163 | - [dev deps] update `eslint`, `eslint-plugin-react` 164 | 165 | 6.2.0 / 2016-03-22 166 | ================== 167 | - [new] Allow arrow functions in JSX props 168 | - [fix] re-enable `no-confusing-arrow` rule, with `allowParens` option enabled ([#752](https://github.com/airbnb/javascript/issues/752), [#791](https://github.com/airbnb/javascript/issues/791)) 169 | - [dev deps] update `tape`, `eslint`, `eslint-plugin-react` 170 | - [peer deps] update `eslint`, `eslint-plugin-react` 171 | 172 | 6.1.0 / 2016-02-22 173 | ================== 174 | - [new] enable [`react/prefer-stateless-function`][react/prefer-stateless-function] 175 | - [dev deps] update `react-plugin-eslint`, `eslint`, `tape` 176 | 177 | 6.0.2 / 2016-02-22 178 | ================== 179 | - [fix] disable [`no-confusing-arrow`][no-confusing-arrow] due to an `eslint` bug ([#752](https://github.com/airbnb/javascript/issues/752)) 180 | 181 | 6.0.1 / 2016-02-21 182 | ================== 183 | - [fix] disable [`newline-per-chained-call`][newline-per-chained-call] due to an `eslint` bug ([#748](https://github.com/airbnb/javascript/issues/748)) 184 | 185 | 6.0.0 / 2016-02-21 186 | ================== 187 | - [breaking] enable [`array-callback-return`][array-callback-return] 188 | - [breaking] enable [`no-confusing-arrow`][no-confusing-arrow] 189 | - [breaking] enable [`no-new-symbol`][no-new-symbol] 190 | - [breaking] enable [`no-restricted-imports`][no-restricted-imports] 191 | - [breaking] enable [`no-useless-constructor`][no-useless-constructor] 192 | - [breaking] enable [`prefer-rest-params`][prefer-rest-params] 193 | - [breaking] enable [`template-curly-spacing`][template-curly-spacing] 194 | - [breaking] enable [`newline-per-chained-call`][newline-per-chained-call] 195 | - [breaking] enable [`one-var-declaration-per-line`][one-var-declaration-per-line] 196 | - [breaking] enable [`no-self-assign`][no-self-assign] 197 | - [breaking] enable [`no-whitespace-before-property`][no-whitespace-before-property] 198 | - [breaking] [react] enable [`react/jsx-space-before-closing`][react/jsx-space-before-closing] 199 | - [breaking] [react] enable `static-methods` at top of [`react/sort-comp`][react/sort-comp] 200 | - [breaking] [react] don't `ignoreTranspilerName` for [`react/display-name`][react/display-name] 201 | - [peer+dev deps] update `eslint`, `eslint-plugin-react` ([#730](https://github.com/airbnb/javascript/issues/730)) 202 | 203 | 5.0.1 / 2016-02-13 204 | ================== 205 | - [fix] `eslint` peerDep should not include breaking changes 206 | 207 | 5.0.0 / 2016-02-03 208 | ================== 209 | - [breaking] disallow unneeded ternary expressions 210 | - [breaking] Avoid lexical declarations in case/default clauses 211 | - [dev deps] update `babel-tape-runner`, `eslint-plugin-react`, `react`, `tape` 212 | 213 | 4.0.0 / 2016-01-22 214 | ================== 215 | - [breaking] require outer IIFE wrapping; flesh out guide section 216 | - [minor] Add missing [`arrow-body-style`][arrow-body-style], [`prefer-template`][prefer-template] rules ([#678](https://github.com/airbnb/javascript/issues/678)) 217 | - [minor] Add [`prefer-arrow-callback`][prefer-arrow-callback] to ES6 rules (to match the guide) ([#677](https://github.com/airbnb/javascript/issues/677)) 218 | - [Tests] run `npm run lint` as part of tests; fix errors 219 | - [Tests] use `parallelshell` to parallelize npm run-scripts 220 | 221 | 3.1.0 / 2016-01-07 222 | ================== 223 | - [minor] Allow multiple stateless components in a single file 224 | 225 | 3.0.2 / 2016-01-06 226 | ================== 227 | - [fix] Ignore URLs in [`max-len`][max-len] ([#664](https://github.com/airbnb/javascript/issues/664)) 228 | 229 | 3.0.1 / 2016-01-06 230 | ================== 231 | - [fix] because we use babel, keywords should not be quoted 232 | 233 | 3.0.0 / 2016-01-04 234 | ================== 235 | - [breaking] enable [`quote-props`][quote-props] rule ([#632](https://github.com/airbnb/javascript/issues/632)) 236 | - [breaking] Define a max line length of 100 characters ([#639](https://github.com/airbnb/javascript/issues/639)) 237 | - [breaking] [react] Minor cleanup for the React styleguide, add [`react/jsx-no-bind`][react/jsx-no-bind] ([#619](https://github.com/airbnb/javascript/issues/619)) 238 | - [breaking] update best-practices config to prevent parameter object manipulation ([#627](https://github.com/airbnb/javascript/issues/627)) 239 | - [minor] Enable [`react/no-is-mounted`][react/no-is-mounted] rule (#635, #633) 240 | - [minor] Sort [`react/prefer-es6-class`][react/prefer-es6-class] alphabetically ([#634](https://github.com/airbnb/javascript/issues/634)) 241 | - [minor] enable [`react/prefer-es6-class`][react/prefer-es6-class] rule 242 | - Permit strict mode in "legacy" config 243 | - [react] add missing rules from `eslint-plugin-react` (enforcing where necessary) ([#581](https://github.com/airbnb/javascript/issues/581)) 244 | - [dev deps] update `eslint-plugin-react` 245 | 246 | 2.1.1 / 2015-12-15 247 | ================== 248 | - [fix] Remove deprecated [`react/jsx-quotes`][react/jsx-quotes] ([#622](https://github.com/airbnb/javascript/issues/622)) 249 | 250 | 2.1.0 / 2015-12-15 251 | ================== 252 | - [fix] use `require.resolve` to allow nested `extend`s ([#582](https://github.com/airbnb/javascript/issues/582)) 253 | - [new] enable [`object-shorthand`][object-shorthand] rule ([#621](https://github.com/airbnb/javascript/issues/621)) 254 | - [new] enable [`arrow-spacing`][arrow-spacing] rule ([#517](https://github.com/airbnb/javascript/issues/517)) 255 | - [docs] flesh out react rule defaults ([#618](https://github.com/airbnb/javascript/issues/618)) 256 | 257 | 2.0.0 / 2015-12-03 258 | ================== 259 | - [breaking] [`space-before-function-paren`][space-before-function-paren]: require function spacing: `function (` ([#605](https://github.com/airbnb/javascript/issues/605)) 260 | - [breaking] [`indent`][indent]: Fix switch statement indentation rule ([#606](https://github.com/airbnb/javascript/issues/606)) 261 | - [breaking] [`array-bracket-spacing`][array-bracket-spacing], [`computed-property-spacing`][computed-property-spacing]: disallow spacing inside brackets ([#594](https://github.com/airbnb/javascript/issues/594)) 262 | - [breaking] [`object-curly-spacing`][object-curly-spacing]: require padding inside curly braces ([#594](https://github.com/airbnb/javascript/issues/594)) 263 | - [breaking] [`space-in-parens`][space-in-parens]: disallow spaces in parens ([#594](https://github.com/airbnb/javascript/issues/594)) 264 | 265 | 1.0.2 / 2015-11-25 266 | ================== 267 | - [breaking] [`no-multiple-empty-lines`][no-multiple-empty-lines]: only allow 1 blank line at EOF ([#578](https://github.com/airbnb/javascript/issues/578)) 268 | - [new] `restParams`: enable rest params ([#592](https://github.com/airbnb/javascript/issues/592)) 269 | 270 | 1.0.1 / 2015-11-25 271 | ================== 272 | - *erroneous publish* 273 | 274 | 1.0.0 / 2015-11-08 275 | ================== 276 | - require `eslint` `v1.0.0` or higher 277 | - remove `babel-eslint` dependency 278 | 279 | 0.1.1 / 2015-11-05 280 | ================== 281 | - remove [`id-length`][id-length] rule ([#569](https://github.com/airbnb/javascript/issues/569)) 282 | - enable [`no-mixed-spaces-and-tabs`][no-mixed-spaces-and-tabs] ([#539](https://github.com/airbnb/javascript/issues/539)) 283 | - enable [`no-const-assign`][no-const-assign] ([#560](https://github.com/airbnb/javascript/issues/560)) 284 | - enable [`space-before-keywords`][space-before-keywords] ([#554](https://github.com/airbnb/javascript/issues/554)) 285 | 286 | 0.1.0 / 2015-11-05 287 | ================== 288 | - switch to modular rules files courtesy the [eslint-config-default][ecd] project and [@taion][taion]. [PR][pr-modular] 289 | - export `eslint-config-airbnb/legacy` for ES5-only users. `eslint-config-airbnb/legacy` does not require the `babel-eslint` parser. [PR][pr-legacy] 290 | 291 | 0.0.9 / 2015-09-24 292 | ================== 293 | - add rule [`no-undef`][no-undef] 294 | - add rule [`id-length`][id-length] 295 | 296 | 0.0.8 / 2015-08-21 297 | ================== 298 | - now has a changelog 299 | - now is modular (see instructions above for with react and without react versions) 300 | 301 | 0.0.7 / 2015-07-30 302 | ================== 303 | - TODO: fill in 304 | 305 | 306 | [ecd]: https://github.com/walmartlabs/eslint-config-defaults 307 | [taion]: https://github.com/taion 308 | [pr-modular]: https://github.com/airbnb/javascript/pull/526 309 | [pr-legacy]: https://github.com/airbnb/javascript/pull/527 310 | 311 | [array-bracket-spacing]: https://eslint.org/docs/rules/array-bracket-spacing 312 | [array-callback-return]: https://eslint.org/docs/rules/array-callback-return 313 | [arrow-body-style]: https://eslint.org/docs/rules/arrow-body-style 314 | [arrow-spacing]: https://eslint.org/docs/rules/arrow-spacing 315 | [computed-property-spacing]: https://eslint.org/docs/rules/computed-property-spacing 316 | [id-length]: https://eslint.org/docs/rules/id-length 317 | [indent]: https://eslint.org/docs/rules/indent 318 | [max-len]: https://eslint.org/docs/rules/max-len 319 | [newline-per-chained-call]: https://eslint.org/docs/rules/newline-per-chained-call 320 | [no-confusing-arrow]: https://eslint.org/docs/rules/no-confusing-arrow 321 | [no-const-assign]: https://eslint.org/docs/rules/no-const-assign 322 | [no-mixed-spaces-and-tabs]: https://eslint.org/docs/rules/no-mixed-spaces-and-tabs 323 | [no-multiple-empty-lines]: https://eslint.org/docs/rules/no-multiple-empty-lines 324 | [no-new-symbol]: https://eslint.org/docs/rules/no-new-symbol 325 | [no-restricted-imports]: https://eslint.org/docs/rules/no-restricted-imports 326 | [no-self-assign]: https://eslint.org/docs/rules/no-self-assign 327 | [no-undef]: https://eslint.org/docs/rules/no-undef 328 | [no-useless-constructor]: https://eslint.org/docs/rules/no-useless-constructor 329 | [no-whitespace-before-property]: https://eslint.org/docs/rules/no-whitespace-before-property 330 | [object-curly-spacing]: https://eslint.org/docs/rules/object-curly-spacing 331 | [object-shorthand]: https://eslint.org/docs/rules/object-shorthand 332 | [one-var-declaration-per-line]: https://eslint.org/docs/rules/one-var-declaration-per-line 333 | [prefer-arrow-callback]: https://eslint.org/docs/rules/prefer-arrow-callback 334 | [prefer-rest-params]: https://eslint.org/docs/rules/prefer-rest-params 335 | [prefer-template]: https://eslint.org/docs/rules/prefer-template 336 | [quote-props]: https://eslint.org/docs/rules/quote-props 337 | [space-before-function-paren]: https://eslint.org/docs/rules/space-before-function-paren 338 | [space-before-keywords]: https://eslint.org/docs/rules/space-before-keywords 339 | [space-in-parens]: https://eslint.org/docs/rules/space-in-parens 340 | [template-curly-spacing]: https://eslint.org/docs/rules/template-curly-spacing 341 | 342 | [react/jsx-space-before-closing]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-space-before-closing.md 343 | [react/sort-comp]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md 344 | [react/display-name]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md 345 | [react/jsx-no-bind]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md 346 | [react/no-is-mounted]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-is-mounted.md 347 | [react/prefer-es6-class]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md 348 | [react/jsx-quotes]: https://github.com/yannickcr/eslint-plugin-react/blob/f817e37beddddc84b4788969f07c524fa7f0823b/docs/rules/jsx-quotes.md 349 | [react/prefer-stateless-function]: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md 350 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012 Airbnb 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 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/README.md: -------------------------------------------------------------------------------- 1 | # eslint-config-airbnb 2 | 3 | [![npm version](https://badge.fury.io/js/eslint-config-airbnb.svg)](http://badge.fury.io/js/eslint-config-airbnb) 4 | 5 | This package provides Airbnb's .eslintrc as an extensible shared config. 6 | 7 | ## Usage 8 | 9 | We export three ESLint configurations for your usage. 10 | 11 | ### eslint-config-airbnb 12 | 13 | Our default export contains all of our ESLint rules, including ECMAScript 6+ and React. It requires `eslint`, `eslint-plugin-import`, `eslint-plugin-react`, and `eslint-plugin-jsx-a11y`. If you don't need React, see [eslint-config-airbnb-base](https://npmjs.com/eslint-config-airbnb-base). 14 | 15 | If you use yarn, run `npm info "eslint-config-airbnb@latest" peerDependencies` to list the peer dependencies and versions, then run `yarn add --dev @` for each listed peer dependency. See below for npm instructions. 16 | 17 | 1. Install the correct versions of each package, which are listed by the command: 18 | 19 | ```sh 20 | npm info "eslint-config-airbnb@latest" peerDependencies 21 | ``` 22 | 23 | If using **npm 5+**, use this shortcut 24 | 25 | ```sh 26 | npx install-peerdeps --dev eslint-config-airbnb 27 | ``` 28 | 29 | If using **npm < 5**, Linux/OSX users can run 30 | 31 | ```sh 32 | ( 33 | export PKG=eslint-config-airbnb; 34 | npm info "$PKG@latest" peerDependencies --json | command sed 's/[\{\},]//g ; s/: /@/g' | xargs npm install --save-dev "$PKG@latest" 35 | ) 36 | ``` 37 | 38 | Which produces and runs a command like: 39 | 40 | ```sh 41 | npm install --save-dev eslint-config-airbnb eslint@^#.#.# eslint-plugin-jsx-a11y@^#.#.# eslint-plugin-import@^#.#.# eslint-plugin-react@^#.#.# 42 | ``` 43 | 44 | If using **npm < 5**, Windows users can either install all the peer dependencies manually, or use the [install-peerdeps](https://github.com/nathanhleung/install-peerdeps) cli tool. 45 | 46 | ```sh 47 | npm install -g install-peerdeps 48 | install-peerdeps --dev eslint-config-airbnb 49 | ``` 50 | The cli will produce and run a command like: 51 | 52 | ```sh 53 | npm install --save-dev eslint-config-airbnb eslint@^#.#.# eslint-plugin-jsx-a11y@^#.#.# eslint-plugin-import@^#.#.# eslint-plugin-react@^#.#.# 54 | ``` 55 | 56 | 2. Add `"extends": "airbnb"` to your .eslintrc 57 | 58 | ### eslint-config-airbnb/whitespace 59 | 60 | This entry point that only warns on whitespace rules and sets all other rules to warnings. View the list of whitespace rules [here](https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb/whitespace.js). 61 | 62 | ### eslint-config-airbnb/base 63 | 64 | This entry point is deprecated. See [eslint-config-airbnb-base](https://npmjs.com/eslint-config-airbnb-base). 65 | 66 | ### eslint-config-airbnb/legacy 67 | 68 | This entry point is deprecated. See [eslint-config-airbnb-base](https://npmjs.com/eslint-config-airbnb-base). 69 | 70 | See [Airbnb's Javascript styleguide](https://github.com/airbnb/javascript) and 71 | the [ESlint config docs](https://eslint.org/docs/user-guide/configuring#extending-configuration-files) 72 | for more information. 73 | 74 | ## Improving this config 75 | 76 | Consider adding test cases if you're making complicated rules changes, like anything involving regexes. Perhaps in a distant future, we could use literate programming to structure our README as test cases for our .eslintrc? 77 | 78 | You can run tests with `npm test`. 79 | 80 | You can make sure this module lints with itself using `npm run lint`. 81 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/base.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['eslint-config-airbnb-base'].map(require.resolve), 3 | rules: {}, 4 | }; 5 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | 'eslint-config-airbnb-base', 4 | 'eslint-config-airbnb-base/rules/strict', 5 | './rules/react', 6 | './rules/react-a11y', 7 | ].map(require.resolve), 8 | rules: {} 9 | }; 10 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/legacy.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['eslint-config-airbnb-base/legacy'].map(require.resolve), 3 | rules: {}, 4 | }; 5 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-airbnb", 3 | "version": "16.1.0", 4 | "description": "Airbnb's ESLint config, following our styleguide", 5 | "main": "index.js", 6 | "scripts": { 7 | "prelint": "editorconfig-tools check * rules/* test/*", 8 | "lint": "eslint .", 9 | "pretests-only": "node ./test/requires", 10 | "tests-only": "babel-tape-runner ./test/test-*.js", 11 | "prepublish": "(in-install || eslint-find-rules --unused) && (not-in-publish || npm test) && safe-publish-latest", 12 | "pretest": "npm run --silent lint", 13 | "test": "npm run --silent tests-only", 14 | "pretravis": "cd ../eslint-config-airbnb-base && npm install && npm link && cd - && npm link --no-save eslint-config-airbnb-base", 15 | "travis": "npm run --silent test", 16 | "posttravis": "npm unlink --no-save eslint-config-airbnb-base >/dev/null &" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/airbnb/javascript" 21 | }, 22 | "keywords": [ 23 | "eslint", 24 | "eslintconfig", 25 | "config", 26 | "airbnb", 27 | "javascript", 28 | "styleguide" 29 | ], 30 | "author": "Jake Teton-Landis (https://twitter.com/@jitl)", 31 | "contributors": [ 32 | { 33 | "name": "Jake Teton-Landis", 34 | "url": "https://twitter.com/jitl" 35 | }, 36 | { 37 | "name": "Jordan Harband", 38 | "email": "ljharb@gmail.com", 39 | "url": "http://ljharb.codes" 40 | }, 41 | { 42 | "name": "Harrison Shoff", 43 | "url": "https://twitter.com/hshoff" 44 | } 45 | ], 46 | "license": "MIT", 47 | "bugs": { 48 | "url": "https://github.com/airbnb/javascript/issues" 49 | }, 50 | "homepage": "https://github.com/airbnb/javascript", 51 | "dependencies": { 52 | "eslint-config-airbnb-base": "^12.1.0", 53 | "object.assign": "^4.1.0", 54 | "object.entries": "^1.0.4" 55 | }, 56 | "devDependencies": { 57 | "babel-preset-airbnb": "^2.4.0", 58 | "babel-tape-runner": "^2.0.1", 59 | "editorconfig-tools": "^0.1.1", 60 | "eslint": "^4.19.1", 61 | "eslint-find-rules": "^3.2.2", 62 | "eslint-plugin-import": "^2.11.0", 63 | "eslint-plugin-jsx-a11y": "^6.0.3", 64 | "eslint-plugin-react": "^7.7.0", 65 | "in-publish": "^2.0.0", 66 | "react": ">= 0.13.0", 67 | "safe-publish-latest": "^1.1.1", 68 | "tape": "^4.9.0" 69 | }, 70 | "peerDependencies": { 71 | "eslint": "^4.19.1", 72 | "eslint-plugin-import": "^2.11.0", 73 | "eslint-plugin-jsx-a11y": "^6.0.3", 74 | "eslint-plugin-react": "^7.7.0" 75 | }, 76 | "engines": { 77 | "node": ">= 4" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/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 | 'jsx-a11y/label-has-for': ['error', { 52 | components: [], 53 | required: { 54 | every: ['nesting', 'id'], 55 | }, 56 | allowChildren: false, 57 | }], 58 | 59 | // require that mouseover/out come with focus/blur, for keyboard-only users 60 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/mouse-events-have-key-events.md 61 | 'jsx-a11y/mouse-events-have-key-events': 'error', 62 | 63 | // Prevent use of `accessKey` 64 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-access-key.md 65 | 'jsx-a11y/no-access-key': 'error', 66 | 67 | // require onBlur instead of onChange 68 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-onchange.md 69 | 'jsx-a11y/no-onchange': 'off', 70 | 71 | // Elements with an interactive role and interaction handlers must be focusable 72 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/interactive-supports-focus.md 73 | 'jsx-a11y/interactive-supports-focus': 'error', 74 | 75 | // Enforce that elements with ARIA roles must have all required attributes 76 | // for that role. 77 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-has-required-aria-props.md 78 | 'jsx-a11y/role-has-required-aria-props': 'error', 79 | 80 | // Enforce that elements with explicit or implicit roles defined contain 81 | // only aria-* properties supported by that role. 82 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-supports-aria-props.md 83 | 'jsx-a11y/role-supports-aria-props': 'error', 84 | 85 | // Enforce tabIndex value is not greater than zero. 86 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/tabindex-no-positive.md 87 | 'jsx-a11y/tabindex-no-positive': 'error', 88 | 89 | // ensure tags have content and are not aria-hidden 90 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/heading-has-content.md 91 | 'jsx-a11y/heading-has-content': ['error', { components: [''] }], 92 | 93 | // require HTML elements to have a "lang" prop 94 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/html-has-lang.md 95 | 'jsx-a11y/html-has-lang': 'error', 96 | 97 | // require HTML element's lang prop to be valid 98 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/lang.md 99 | 'jsx-a11y/lang': 'error', 100 | 101 | // prevent distracting elements, like and 102 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-distracting-elements.md 103 | 'jsx-a11y/no-distracting-elements': ['error', { 104 | elements: ['marquee', 'blink'], 105 | }], 106 | 107 | // only allow to have the "scope" attr 108 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/scope.md 109 | 'jsx-a11y/scope': 'error', 110 | 111 | // require onClick be accompanied by onKeyUp/onKeyDown/onKeyPress 112 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/click-events-have-key-events.md 113 | 'jsx-a11y/click-events-have-key-events': 'error', 114 | 115 | // Enforce that DOM elements without semantic behavior not have interaction handlers 116 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-static-element-interactions.md 117 | 'jsx-a11y/no-static-element-interactions': ['error', { 118 | handlers: [ 119 | 'onClick', 120 | 'onMouseDown', 121 | 'onMouseUp', 122 | 'onKeyPress', 123 | 'onKeyDown', 124 | 'onKeyUp', 125 | ] 126 | }], 127 | 128 | // A non-interactive element does not support event handlers (mouse and key handlers) 129 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-interactions.md 130 | 'jsx-a11y/no-noninteractive-element-interactions': ['error', { 131 | handlers: [ 132 | 'onClick', 133 | 'onMouseDown', 134 | 'onMouseUp', 135 | 'onKeyPress', 136 | 'onKeyDown', 137 | 'onKeyUp', 138 | ] 139 | }], 140 | 141 | // ensure emoji are accessible 142 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/accessible-emoji.md 143 | 'jsx-a11y/accessible-emoji': 'error', 144 | 145 | // elements with aria-activedescendant must be tabbable 146 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-activedescendant-has-tabindex.md 147 | 'jsx-a11y/aria-activedescendant-has-tabindex': 'error', 148 | 149 | // ensure iframe elements have a unique title 150 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/iframe-has-title.md 151 | 'jsx-a11y/iframe-has-title': 'error', 152 | 153 | // prohibit autoFocus prop 154 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-autofocus.md 155 | 'jsx-a11y/no-autofocus': ['error', { ignoreNonDOM: true }], 156 | 157 | // ensure HTML elements do not specify redundant ARIA roles 158 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-redundant-roles.md 159 | 'jsx-a11y/no-redundant-roles': 'error', 160 | 161 | // media elements must have captions 162 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/media-has-caption.md 163 | 'jsx-a11y/media-has-caption': ['error', { 164 | audio: [], 165 | video: [], 166 | track: [], 167 | }], 168 | 169 | // WAI-ARIA roles should not be used to convert an interactive element to non-interactive 170 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-interactive-element-to-noninteractive-role.md 171 | 'jsx-a11y/no-interactive-element-to-noninteractive-role': ['error', { 172 | tr: ['none', 'presentation'], 173 | }], 174 | 175 | // WAI-ARIA roles should not be used to convert a non-interactive element to interactive 176 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-to-interactive-role.md 177 | 'jsx-a11y/no-noninteractive-element-to-interactive-role': ['error', { 178 | ul: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'], 179 | ol: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'], 180 | li: ['menuitem', 'option', 'row', 'tab', 'treeitem'], 181 | table: ['grid'], 182 | td: ['gridcell'], 183 | }], 184 | 185 | // Tab key navigation should be limited to elements on the page that can be interacted with. 186 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-tabindex.md 187 | 'jsx-a11y/no-noninteractive-tabindex': ['error', { 188 | tags: [], 189 | roles: ['tabpanel'], 190 | }], 191 | 192 | // ensure tags are valid 193 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/0745af376cdc8686d85a361ce36952b1fb1ccf6e/docs/rules/anchor-is-valid.md 194 | 'jsx-a11y/anchor-is-valid': ['error', { 195 | components: ['Link'], 196 | specialLink: ['to'], 197 | aspects: ['noHref', 'invalidHref', 'preferButton'], 198 | }], 199 | }, 200 | }; 201 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/rules/react.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | 'react', 4 | ], 5 | 6 | parserOptions: { 7 | ecmaFeatures: { 8 | jsx: true, 9 | }, 10 | }, 11 | 12 | // View link below for react rules documentation 13 | // https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules 14 | rules: { 15 | // Specify whether double or single quotes should be used in JSX attributes 16 | // https://eslint.org/docs/rules/jsx-quotes 17 | 'jsx-quotes': ['error', 'prefer-double'], 18 | 19 | 'class-methods-use-this': ['error', { 20 | exceptMethods: [ 21 | 'render', 22 | 'getInitialState', 23 | 'getDefaultProps', 24 | 'getChildContext', 25 | 'componentWillMount', 26 | 'componentDidMount', 27 | 'componentWillReceiveProps', 28 | 'shouldComponentUpdate', 29 | 'componentWillUpdate', 30 | 'componentDidUpdate', 31 | 'componentWillUnmount', 32 | 'componentDidCatch', 33 | ], 34 | }], 35 | 36 | // Prevent missing displayName in a React component definition 37 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md 38 | 'react/display-name': ['off', { ignoreTranspilerName: false }], 39 | 40 | // Forbid certain propTypes (any, array, object) 41 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/forbid-prop-types.md 42 | 'react/forbid-prop-types': ['error', { 43 | forbid: ['any', 'array', 'object'], 44 | checkContextTypes: true, 45 | checkChildContextTypes: true, 46 | }], 47 | 48 | // Forbid certain props on DOM Nodes 49 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/forbid-dom-props.md 50 | 'react/forbid-dom-props': ['off', { forbid: [] }], 51 | 52 | // Enforce boolean attributes notation in JSX 53 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md 54 | 'react/jsx-boolean-value': ['error', 'never', { always: [] }], 55 | 56 | // Validate closing bracket location in JSX 57 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md 58 | 'react/jsx-closing-bracket-location': ['error', 'line-aligned'], 59 | 60 | // Validate closing tag location in JSX 61 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-tag-location.md 62 | 'react/jsx-closing-tag-location': 'error', 63 | 64 | // Enforce or disallow spaces inside of curly braces in JSX attributes 65 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md 66 | 'react/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }], 67 | 68 | // Enforce event handler naming conventions in JSX 69 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-handler-names.md 70 | 'react/jsx-handler-names': ['off', { 71 | eventHandlerPrefix: 'handle', 72 | eventHandlerPropPrefix: 'on', 73 | }], 74 | 75 | // Validate props indentation in JSX 76 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent-props.md 77 | 'react/jsx-indent-props': ['error', 2], 78 | 79 | // Validate JSX has key prop when in array or iterator 80 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-key.md 81 | 'react/jsx-key': 'off', 82 | 83 | // Limit maximum of props on a single line in JSX 84 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-max-props-per-line.md 85 | 'react/jsx-max-props-per-line': ['error', { maximum: 1, when: 'multiline' }], 86 | 87 | // Prevent usage of .bind() in JSX props 88 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md 89 | 'react/jsx-no-bind': ['error', { 90 | ignoreRefs: true, 91 | allowArrowFunctions: true, 92 | allowBind: false, 93 | }], 94 | 95 | // Prevent duplicate props in JSX 96 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-duplicate-props.md 97 | 'react/jsx-no-duplicate-props': ['error', { ignoreCase: true }], 98 | 99 | // Prevent usage of unwrapped JSX strings 100 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-literals.md 101 | 'react/jsx-no-literals': ['off', { noStrings: true }], 102 | 103 | // Disallow undeclared variables in JSX 104 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-undef.md 105 | 'react/jsx-no-undef': 'error', 106 | 107 | // Enforce PascalCase for user-defined JSX components 108 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md 109 | 'react/jsx-pascal-case': ['error', { 110 | allowAllCaps: true, 111 | ignore: [], 112 | }], 113 | 114 | // Enforce propTypes declarations alphabetical sorting 115 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-prop-types.md 116 | 'react/sort-prop-types': ['off', { 117 | ignoreCase: true, 118 | callbacksLast: false, 119 | requiredFirst: false, 120 | sortShapeProp: true, 121 | }], 122 | 123 | // Deprecated in favor of react/jsx-sort-props 124 | 'react/jsx-sort-prop-types': 'off', 125 | 126 | // Enforce props alphabetical sorting 127 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-sort-props.md 128 | 'react/jsx-sort-props': ['off', { 129 | ignoreCase: true, 130 | callbacksLast: false, 131 | shorthandFirst: false, 132 | shorthandLast: false, 133 | noSortAlphabetically: false, 134 | reservedFirst: true, 135 | }], 136 | 137 | // Enforce defaultProps declarations alphabetical sorting 138 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-sort-default-props.md 139 | 'react/jsx-sort-default-props': ['off', { 140 | ignoreCase: true, 141 | }], 142 | 143 | // Prevent React to be incorrectly marked as unused 144 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-react.md 145 | 'react/jsx-uses-react': ['error'], 146 | 147 | // Prevent variables used in JSX to be incorrectly marked as unused 148 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-vars.md 149 | 'react/jsx-uses-vars': 'error', 150 | 151 | // Prevent usage of dangerous JSX properties 152 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-danger.md 153 | 'react/no-danger': 'warn', 154 | 155 | // Prevent usage of deprecated methods 156 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-deprecated.md 157 | 'react/no-deprecated': ['error'], 158 | 159 | // Prevent usage of setState in componentDidMount 160 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-mount-set-state.md 161 | // this is necessary for server-rendering 162 | 'react/no-did-mount-set-state': 'off', 163 | 164 | // Prevent usage of setState in componentDidUpdate 165 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-update-set-state.md 166 | 'react/no-did-update-set-state': 'error', 167 | 168 | // Prevent usage of setState in componentWillUpdate 169 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-will-update-set-state.md 170 | 'react/no-will-update-set-state': 'error', 171 | 172 | // Prevent direct mutation of this.state 173 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-direct-mutation-state.md 174 | 'react/no-direct-mutation-state': 'off', 175 | 176 | // Prevent usage of isMounted 177 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-is-mounted.md 178 | 'react/no-is-mounted': 'error', 179 | 180 | // Prevent multiple component definition per file 181 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md 182 | 'react/no-multi-comp': ['error', { ignoreStateless: true }], 183 | 184 | // Prevent usage of setState 185 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-set-state.md 186 | 'react/no-set-state': 'off', 187 | 188 | // Prevent using string references 189 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-string-refs.md 190 | 'react/no-string-refs': 'error', 191 | 192 | // Prevent usage of unknown DOM property 193 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unknown-property.md 194 | 'react/no-unknown-property': 'error', 195 | 196 | // Require ES6 class declarations over React.createClass 197 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md 198 | 'react/prefer-es6-class': ['error', 'always'], 199 | 200 | // Require stateless functions when not using lifecycle methods, setState or ref 201 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md 202 | 'react/prefer-stateless-function': ['error', { ignorePureComponents: true }], 203 | 204 | // Prevent missing props validation in a React component definition 205 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prop-types.md 206 | 'react/prop-types': ['error', { 207 | ignore: [], 208 | customValidators: [], 209 | skipUndeclared: false 210 | }], 211 | 212 | // Prevent missing React when using JSX 213 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md 214 | 'react/react-in-jsx-scope': 'error', 215 | 216 | // Require render() methods to return something 217 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-render-return.md 218 | 'react/require-render-return': 'error', 219 | 220 | // Prevent extra closing tags for components without children 221 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md 222 | 'react/self-closing-comp': 'error', 223 | 224 | // Enforce component methods order 225 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/sort-comp.md 226 | 'react/sort-comp': ['error', { 227 | order: [ 228 | 'static-methods', 229 | 'instance-variables', 230 | 'lifecycle', 231 | '/^on.+$/', 232 | 'getters', 233 | 'setters', 234 | '/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/', 235 | 'instance-methods', 236 | 'everything-else', 237 | 'rendering', 238 | ], 239 | groups: { 240 | lifecycle: [ 241 | 'displayName', 242 | 'propTypes', 243 | 'contextTypes', 244 | 'childContextTypes', 245 | 'mixins', 246 | 'statics', 247 | 'defaultProps', 248 | 'constructor', 249 | 'getDefaultProps', 250 | 'getInitialState', 251 | 'state', 252 | 'getChildContext', 253 | 'componentWillMount', 254 | 'componentDidMount', 255 | 'componentWillReceiveProps', 256 | 'shouldComponentUpdate', 257 | 'componentWillUpdate', 258 | 'componentDidUpdate', 259 | 'componentWillUnmount', 260 | ], 261 | rendering: [ 262 | '/^render.+$/', 263 | 'render' 264 | ], 265 | }, 266 | }], 267 | 268 | // Prevent missing parentheses around multilines JSX 269 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-wrap-multilines.md 270 | 'react/jsx-wrap-multilines': ['error', { 271 | declaration: 'parens-new-line', 272 | assignment: 'parens-new-line', 273 | return: 'parens-new-line', 274 | arrow: 'parens-new-line', 275 | condition: 'parens-new-line', 276 | logical: 'parens-new-line', 277 | prop: 'parens-new-line', 278 | }], 279 | 280 | // Require that the first prop in a JSX element be on a new line when the element is multiline 281 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-first-prop-new-line.md 282 | 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'], 283 | 284 | // Enforce spacing around jsx equals signs 285 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-equals-spacing.md 286 | 'react/jsx-equals-spacing': ['error', 'never'], 287 | 288 | // Enforce JSX indentation 289 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent.md 290 | 'react/jsx-indent': ['error', 2], 291 | 292 | // Disallow target="_blank" on links 293 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-target-blank.md 294 | 'react/jsx-no-target-blank': 'error', 295 | 296 | // only .jsx files may have JSX 297 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-filename-extension.md 298 | 'react/jsx-filename-extension': ['error', { extensions: ['.jsx'] }], 299 | 300 | // prevent accidental JS comments from being injected into JSX as text 301 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-comment-textnodes.md 302 | 'react/jsx-no-comment-textnodes': 'error', 303 | 304 | // disallow using React.render/ReactDOM.render's return value 305 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-render-return-value.md 306 | 'react/no-render-return-value': 'error', 307 | 308 | // require a shouldComponentUpdate method, or PureRenderMixin 309 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-optimization.md 310 | 'react/require-optimization': ['off', { allowDecorators: [] }], 311 | 312 | // warn against using findDOMNode() 313 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-find-dom-node.md 314 | 'react/no-find-dom-node': 'error', 315 | 316 | // Forbid certain props on Components 317 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-component-props.md 318 | 'react/forbid-component-props': ['off', { forbid: [] }], 319 | 320 | // Forbid certain elements 321 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-elements.md 322 | 'react/forbid-elements': ['off', { forbid: [], }], 323 | 324 | // Prevent problem with children and props.dangerouslySetInnerHTML 325 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-danger-with-children.md 326 | 'react/no-danger-with-children': 'error', 327 | 328 | // Prevent unused propType definitions 329 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unused-prop-types.md 330 | 'react/no-unused-prop-types': ['error', { 331 | customValidators: [ 332 | ], 333 | skipShapeProps: true, 334 | }], 335 | 336 | // Require style prop value be an object or var 337 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/style-prop-object.md 338 | 'react/style-prop-object': 'error', 339 | 340 | // Prevent invalid characters from appearing in markup 341 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unescaped-entities.md 342 | 'react/no-unescaped-entities': 'error', 343 | 344 | // Prevent passing of children as props 345 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-children-prop.md 346 | 'react/no-children-prop': 'error', 347 | 348 | // Validate whitespace in and around the JSX opening and closing brackets 349 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-tag-spacing.md 350 | 'react/jsx-tag-spacing': ['error', { 351 | closingSlash: 'never', 352 | beforeSelfClosing: 'always', 353 | afterOpening: 'never', 354 | beforeClosing: 'never', 355 | }], 356 | 357 | // Enforce spaces before the closing bracket of self-closing JSX elements 358 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-space-before-closing.md 359 | // Deprecated in favor of jsx-tag-spacing 360 | 'react/jsx-space-before-closing': ['off', 'always'], 361 | 362 | // Prevent usage of Array index in keys 363 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-array-index-key.md 364 | 'react/no-array-index-key': 'error', 365 | 366 | // Enforce a defaultProps definition for every prop that is not a required prop 367 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/require-default-props.md 368 | 'react/require-default-props': ['error', { 369 | forbidDefaultForRequired: true, 370 | }], 371 | 372 | // Forbids using non-exported propTypes 373 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-foreign-prop-types.md 374 | // TODO: enable? 375 | 'react/forbid-foreign-prop-types': ['off', { allowInPropTypes: true }], 376 | 377 | // Prevent void DOM elements from receiving children 378 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/void-dom-elements-no-children.md 379 | 'react/void-dom-elements-no-children': 'error', 380 | 381 | // Enforce all defaultProps have a corresponding non-required PropType 382 | // https://github.com/yannickcr/eslint-plugin-react/blob/9e13ae2c51e44872b45cc15bf1ac3a72105bdd0e/docs/rules/default-props-match-prop-types.md 383 | 'react/default-props-match-prop-types': ['error', { allowRequiredDefaults: false }], 384 | 385 | // Prevent usage of shouldComponentUpdate when extending React.PureComponent 386 | // https://github.com/yannickcr/eslint-plugin-react/blob/9e13ae2c51e44872b45cc15bf1ac3a72105bdd0e/docs/rules/no-redundant-should-component-update.md 387 | 'react/no-redundant-should-component-update': 'error', 388 | 389 | // Prevent unused state values 390 | // https://github.com/yannickcr/eslint-plugin-react/pull/1103/ 391 | 'react/no-unused-state': 'error', 392 | 393 | // Enforces consistent naming for boolean props 394 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/boolean-prop-naming.md 395 | 'react/boolean-prop-naming': ['off', { 396 | propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'], 397 | rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+', 398 | message: '', 399 | }], 400 | 401 | // Prevents common casing typos 402 | // https://github.com/yannickcr/eslint-plugin-react/blob/73abadb697034b5ccb514d79fb4689836fe61f91/docs/rules/no-typos.md 403 | 'react/no-typos': 'error', 404 | 405 | // Enforce curly braces or disallow unnecessary curly braces in JSX props and/or children 406 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-brace-presence.md 407 | 'react/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never' }], 408 | 409 | // One JSX Element Per Line 410 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-one-expression-per-line.md 411 | 'react/jsx-one-expression-per-line': 'error', 412 | 413 | // Enforce consistent usage of destructuring assignment of props, state, and context 414 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/destructuring-assignment.md 415 | 'react/destructuring-assignment': ['error', 'always'], 416 | 417 | // Prevent using this.state within a this.setState 418 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/no-access-state-in-setstate.md 419 | 'react/no-access-state-in-setstate': 'error', 420 | 421 | // Prevent usage of button elements without an explicit type attribute 422 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/button-has-type.md 423 | 'react/button-has-type': ['error', { 424 | button: true, 425 | submit: true, 426 | reset: false, 427 | }], 428 | 429 | // Ensures inline tags are not rendered without spaces between them 430 | 'react/jsx-child-element-spacing': 'off', 431 | 432 | // Prevent this from being used in stateless functional components 433 | // https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/no-this-in-sfc.md 434 | 'react/no-this-in-sfc': 'error', 435 | 436 | // Validate JSX maximum depth 437 | // https://github.com/yannickcr/eslint-plugin-react/blob/abe8381c0d6748047224c430ce47f02e40160ed0/docs/rules/jsx-max-depth.md 438 | 'react/jsx-max-depth': 'off', 439 | }, 440 | 441 | settings: { 442 | 'import/resolver': { 443 | node: { 444 | extensions: ['.js', '.jsx', '.json'] 445 | } 446 | }, 447 | react: { 448 | pragma: 'React', 449 | version: '16.0' 450 | }, 451 | propWrapperFunctions: [ 452 | 'forbidExtraProps', // https://www.npmjs.com/package/airbnb-prop-types 453 | 'exact', // https://www.npmjs.com/package/prop-types-exact 454 | 'Object.freeze', // https://tc39.github.io/ecma262/#sec-object.freeze 455 | ], 456 | } 457 | }; 458 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | // disabled because I find it tedious to write tests while following this rule 4 | "no-shadow": 0, 5 | 6 | // tests uses `t` for tape 7 | "id-length": [2, {"min": 2, "properties": "never", "exceptions": ["t"]}] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/test/requires.js: -------------------------------------------------------------------------------- 1 | /* eslint 2 | strict: 0, 3 | global-require: 0, 4 | */ 5 | 6 | 'use strict'; 7 | 8 | const test = require('tape'); 9 | 10 | test('all entry points parse', (t) => { 11 | t.doesNotThrow(() => require('..'), 'index does not throw'); 12 | t.doesNotThrow(() => require('../base'), 'base does not throw'); 13 | t.doesNotThrow(() => require('../legacy'), 'legacy does not throw'); 14 | t.doesNotThrow(() => require('../whitespace'), 'whitespace does not throw'); 15 | 16 | t.end(); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/test/test-base.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import test from 'tape'; 4 | 5 | const base = require('../base'); 6 | 7 | const files = { base }; 8 | 9 | fs.readdirSync(path.join(__dirname, '../rules')).forEach((name) => { 10 | if (name === 'react.js' || name === 'react-a11y.js') { 11 | return; 12 | } 13 | 14 | // eslint-disable-next-line import/no-dynamic-require 15 | files[name] = require(`../rules/${name}`); // eslint-disable-line global-require 16 | }); 17 | 18 | Object.keys(files).forEach((name) => { 19 | const config = files[name]; 20 | 21 | test(`${name}: does not reference react`, (t) => { 22 | t.plan(2); 23 | 24 | // scan plugins for react and fail if it is found 25 | const hasReactPlugin = Object.prototype.hasOwnProperty.call(config, 'plugins') 26 | && config.plugins.indexOf('react') !== -1; 27 | t.notOk(hasReactPlugin, 'there is no react plugin'); 28 | 29 | // scan rules for react/ and fail if any exist 30 | const reactRuleIds = Object.keys(config.rules) 31 | .filter(ruleId => ruleId.indexOf('react/') === 0); 32 | t.deepEquals(reactRuleIds, [], 'there are no react/ rules'); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/test/test-react-order.js: -------------------------------------------------------------------------------- 1 | import test from 'tape'; 2 | import { CLIEngine } from 'eslint'; 3 | import eslintrc from '..'; 4 | import reactRules from '../rules/react'; 5 | import reactA11yRules from '../rules/react-a11y'; 6 | 7 | const cli = new CLIEngine({ 8 | useEslintrc: false, 9 | baseConfig: eslintrc, 10 | 11 | rules: { 12 | // It is okay to import devDependencies in tests. 13 | 'import/no-extraneous-dependencies': [2, { devDependencies: true }], 14 | // this doesn't matter for tests 15 | 'lines-between-class-members': 0, 16 | }, 17 | }); 18 | 19 | function lint(text) { 20 | // @see https://eslint.org/docs/developer-guide/nodejs-api.html#executeonfiles 21 | // @see https://eslint.org/docs/developer-guide/nodejs-api.html#executeontext 22 | const linter = cli.executeOnText(text); 23 | return linter.results[0]; 24 | } 25 | 26 | function wrapComponent(body) { 27 | return ` 28 | import React from 'react'; 29 | 30 | export default class MyComponent extends React.Component { 31 | /* eslint no-empty-function: 0, class-methods-use-this: 0 */ 32 | ${body} 33 | } 34 | `; 35 | } 36 | 37 | test('validate react prop order', (t) => { 38 | t.test('make sure our eslintrc has React and JSX linting dependencies', (t) => { 39 | t.plan(2); 40 | t.deepEqual(reactRules.plugins, ['react']); 41 | t.deepEqual(reactA11yRules.plugins, ['jsx-a11y', 'react']); 42 | }); 43 | 44 | t.test('passes a good component', (t) => { 45 | t.plan(3); 46 | const result = lint(wrapComponent(` 47 | componentWillMount() {} 48 | componentDidMount() {} 49 | setFoo() {} 50 | getFoo() {} 51 | setBar() {} 52 | someMethod() {} 53 | renderDogs() {} 54 | render() { return
; }`)); 55 | 56 | t.notOk(result.warningCount, 'no warnings'); 57 | t.notOk(result.errorCount, 'no errors'); 58 | t.deepEquals(result.messages, [], 'no messages in results'); 59 | }); 60 | 61 | t.test('order: when random method is first', (t) => { 62 | t.plan(2); 63 | const result = lint(wrapComponent(` 64 | someMethod() {} 65 | componentWillMount() {} 66 | componentDidMount() {} 67 | setFoo() {} 68 | getFoo() {} 69 | setBar() {} 70 | renderDogs() {} 71 | render() { return
; } 72 | `)); 73 | 74 | t.ok(result.errorCount, 'fails'); 75 | t.equal(result.messages[0].ruleId, 'react/sort-comp', 'fails due to sort'); 76 | }); 77 | 78 | t.test('order: when random method after lifecycle methods', (t) => { 79 | t.plan(2); 80 | const result = lint(wrapComponent(` 81 | componentWillMount() {} 82 | componentDidMount() {} 83 | someMethod() {} 84 | setFoo() {} 85 | getFoo() {} 86 | setBar() {} 87 | renderDogs() {} 88 | render() { return
; } 89 | `)); 90 | 91 | t.ok(result.errorCount, 'fails'); 92 | t.equal(result.messages[0].ruleId, 'react/sort-comp', 'fails due to sort'); 93 | }); 94 | }); 95 | -------------------------------------------------------------------------------- /packages/eslint-config-airbnb/whitespace.js: -------------------------------------------------------------------------------- 1 | const baseConfig = require('.'); 2 | const assign = require('object.assign'); 3 | const entries = require('object.entries'); 4 | const CLIEngine = require('eslint').CLIEngine; 5 | 6 | function onlyErrorOnRules(rulesToError, config) { 7 | const errorsOnly = assign({}, config); 8 | const cli = new CLIEngine({ baseConfig: config, useEslintrc: false }); 9 | const baseRules = cli.getConfigForFile('./').rules; 10 | 11 | entries(baseRules).forEach((rule) => { 12 | const ruleName = rule[0]; 13 | const ruleConfig = rule[1]; 14 | 15 | if (rulesToError.indexOf(ruleName) === -1) { 16 | if (Array.isArray(ruleConfig)) { 17 | errorsOnly.rules[ruleName] = ['warn'].concat(ruleConfig.slice(1)); 18 | } else if (typeof ruleConfig === 'number') { 19 | errorsOnly.rules[ruleName] = 1; 20 | } else { 21 | errorsOnly.rules[ruleName] = 'warn'; 22 | } 23 | } 24 | }); 25 | 26 | return errorsOnly; 27 | } 28 | 29 | module.exports = onlyErrorOnRules([ 30 | 'array-bracket-newline', 31 | 'array-bracket-spacing', 32 | 'array-element-newline', 33 | 'arrow-spacing', 34 | 'block-spacing', 35 | 'comma-spacing', 36 | 'computed-property-spacing', 37 | 'dot-location', 38 | 'eol-last', 39 | 'func-call-spacing', 40 | 'function-paren-newline', 41 | 'generator-star-spacing', 42 | 'implicit-arrow-linebreak', 43 | 'indent', 44 | 'key-spacing', 45 | 'keyword-spacing', 46 | 'line-comment-position', 47 | 'linebreak-style', 48 | 'multiline-ternary', 49 | 'newline-per-chained-call', 50 | 'no-irregular-whitespace', 51 | 'no-mixed-spaces-and-tabs', 52 | 'no-multi-spaces', 53 | 'no-regex-spaces', 54 | 'no-spaced-func', 55 | 'no-trailing-spaces', 56 | 'no-whitespace-before-property', 57 | 'nonblock-statement-body-position', 58 | 'object-curly-newline', 59 | 'object-curly-spacing', 60 | 'object-property-newline', 61 | 'one-var-declaration-per-line', 62 | 'operator-linebreak', 63 | 'padded-blocks', 64 | 'padding-line-between-statements', 65 | 'rest-spread-spacing', 66 | 'semi-spacing', 67 | 'semi-style', 68 | 'space-before-blocks', 69 | 'space-before-function-paren', 70 | 'space-in-parens', 71 | 'space-infix-ops', 72 | 'space-unary-ops', 73 | 'spaced-comment', 74 | 'switch-colon-spacing', 75 | 'template-tag-spacing', 76 | 'import/newline-after-import', 77 | // eslint-plugin-react rules 78 | 'react/jsx-child-element-spacing', 79 | 'react/jsx-closing-bracket-location', 80 | 'react/jsx-closing-tag-location', 81 | 'react/jsx-curly-spacing', 82 | 'react/jsx-equals-spacing', 83 | 'react/jsx-first-prop-newline', 84 | 'react/jsx-indent', 85 | 'react/jsx-indent-props', 86 | 'react/jsx-max-props-per-line', 87 | 'react/jsx-one-expression-per-line', 88 | 'react/jsx-space-before-closing', 89 | 'react/jsx-tag-spacing', 90 | 'react/jsx-wrap-multilines', 91 | ], baseConfig); 92 | -------------------------------------------------------------------------------- /react/README.md: -------------------------------------------------------------------------------- 1 | # Airbnb React/JSX 代码规范 2 | 3 | *一套对于 React 和 JSX 基本合理的规范* 4 | 5 | 本指南是主要基于目前流行的 JavaScript 标准,因此一些惯例(如:async/await 或静态类字段)可能仍然包含其中或者被禁止。 目前,处在第 3 阶段的任何内容都不包含在本指南中,也不建议使用。 6 | 7 | ## 目录 8 | 9 | 1. [基本规则](#basic-rules) 10 | 1. [Class vs `React.createClass` vs stateless](#class-vs-reactcreateclass-vs-stateless) 11 | 1. [Mixins](#mixins) 12 | 1. [命名](#naming) 13 | 1. [声明模块](#declaration) 14 | 1. [代码对齐](#alignment) 15 | 1. [单引号和双引号](#quotes) 16 | 1. [空格](#spacing) 17 | 1. [属性](#props) 18 | 1. [Refs](#refs) 19 | 1. [括号](#parentheses) 20 | 1. [标签](#tags) 21 | 1. [方法](#methods) 22 | 1. [函数生命周期](#ordering) 23 | 1. [`isMounted`](#ismounted) 24 | 25 | ## 基本规则 26 | 27 | - 每个文件只存在一个 React 组件。 28 | - 但是,每个文件允许存在多个 [无状态或纯组件](https://facebook.github.io/react/docs/reusable-components.html#stateless-functions) 。 eslint: [`react/no-multi-comp`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md#ignorestateless). 29 | - 始终使用 JSX 语法。 30 | - 除非你从一个非 JSX 文件中初始化你的应用,否则不要使用 `React.createElement` 。 31 | 32 | **[⬆ 返回目录](#table-of-contents)** 33 | 34 | ## Class vs `React.createClass` vs stateless 35 | 36 | - 如果你的组件有内部状态或者是 `refs` ,推荐使用 `class extends React.Component` 而不是 `React.createClass`。 eslint: [`react/prefer-es6-class`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md) [`react/prefer-stateless-function`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md) 37 | 38 | ```jsx 39 | // bad 40 | const Listing = React.createClass({ 41 | // ... 42 | render() { 43 | return
{this.state.hello}
; 44 | } 45 | }); 46 | 47 | // good 48 | class Listing extends React.Component { 49 | // ... 50 | render() { 51 | return
{this.state.hello}
; 52 | } 53 | } 54 | ``` 55 | 56 | 如果你的组件没有状态或者 `refs` 推荐使用普通函数(不是箭头函数)而不是类定义: 57 | 58 | ```jsx 59 | // bad 60 | class Listing extends React.Component { 61 | render() { 62 | return
{this.props.hello}
; 63 | } 64 | } 65 | 66 | // bad (relying on function name inference is discouraged) 67 | const Listing = ({ hello }) => ( 68 |
{hello}
69 | ); 70 | 71 | // good 72 | function Listing({ hello }) { 73 | return
{hello}
; 74 | } 75 | ``` 76 | **[⬆ 返回目录](#table-of-contents)** 77 | 78 | ## Mixins 79 | 80 | - [不要使用 mixins](https://facebook.github.io/react/blog/2016/07/13/mixins-considered-harmful.html). 81 | 82 | > 为什么? Mixins 会引入隐式的依赖关系,会导致名称冲突,并致使复杂性指数级增加。 在多数情况下 mixins 能够被更好的方法替代,如:组件化,高阶组件,工具模块等。 83 | 84 | **[⬆ 返回目录](#table-of-contents)** 85 | 86 | ## 命名 87 | 88 | - **扩展名**: 使用 `.jsx` 作为 React 组件的扩展名。 89 | - **文件名**: 使用帕斯卡命名法给文件命名。 例如: `ReservationCard.jsx`. 90 | - **引用命名**: 使用帕斯卡命名法给 React 组件命名并用驼峰命名法给组件实例命名。 eslint: [`react/jsx-pascal-case`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md) 91 | 92 | ```jsx 93 | // bad 94 | import reservationCard from './ReservationCard'; 95 | 96 | // good 97 | import ReservationCard from './ReservationCard'; 98 | 99 | // bad 100 | const ReservationItem = ; 101 | 102 | // good 103 | const reservationItem = ; 104 | ``` 105 | 106 | - **组件命名**: 使用文件名作为组件的名字。 例如: `ReservationCard.jsx` 应该包含一个名字叫 `ReservationCard` 的组件。 但是,如果整个文件夹是一个模块,使用 `index.jsx` 作为入口文件,并使用目录名称作为组件名称: 107 | 108 | ```jsx 109 | // bad 110 | import Footer from './Footer/Footer'; 111 | 112 | // bad 113 | import Footer from './Footer/index'; 114 | 115 | // good 116 | import Footer from './Footer'; 117 | ``` 118 | - **高阶组件命名**: 在生成的新组件上,使用高阶组件的名称和传入组件的名称作为新组件的 `displayName` 。 例如:高价组件 `withFoo()`,当被传入到一个叫做 `Bar` 的组件中的时候,应该生成一个拥有 `displayName` 为 `withFoo(Bar)` 的组件。 119 | 120 | > 为什么? 一个组件的 `displayName` 可能在开发者工具或者错误信息中用到, 因此拥有一个能清楚表达层次结构的值能够帮助我们更好的理解触发的事件。 121 | 122 | ```jsx 123 | // bad 124 | export default function withFoo(WrappedComponent) { 125 | return function WithFoo(props) { 126 | return ; 127 | } 128 | } 129 | 130 | // good 131 | export default function withFoo(WrappedComponent) { 132 | function WithFoo(props) { 133 | return ; 134 | } 135 | 136 | const wrappedComponentName = WrappedComponent.displayName 137 | || WrappedComponent.name 138 | || 'Component'; 139 | 140 | WithFoo.displayName = `withFoo(${wrappedComponentName})`; 141 | return WithFoo; 142 | } 143 | ``` 144 | 145 | - **属性命名**: 避免使用 DOM 组件属性来用作其他用途。 146 | 147 | > 为什么? 对于像 `style` 和 `className` 这样的属性我们默认它们代表一些特殊的含义。 改变这些 API 会降低你代码的可读性和可维护性,并且可能导致问题。 148 | 149 | ```jsx 150 | // bad 151 | 152 | 153 | // bad 154 | 155 | 156 | // good 157 | 158 | ``` 159 | 160 | **[⬆ 返回目录](#table-of-contents)** 161 | 162 | ## 声明模块 163 | 164 | - 不要使用 `displayName` 来命名组件。 应该使用引用来命名组件。 165 | 166 | ```jsx 167 | // bad 168 | export default React.createClass({ 169 | displayName: 'ReservationCard', 170 | // stuff goes here 171 | }); 172 | 173 | // good 174 | export default class ReservationCard extends React.Component { 175 | } 176 | ``` 177 | 178 | **[⬆ 返回目录](#table-of-contents)** 179 | 180 | ## 代码对齐 181 | 182 | - 遵循以下的 JSX 代码对齐方式。 eslint: [`react/jsx-closing-bracket-location`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md) [`react/jsx-closing-tag-location`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-tag-location.md) 183 | 184 | ```jsx 185 | // bad 186 | 188 | 189 | // good 190 | 194 | 195 | // 如果能写在一行,直接写成一行 196 | 197 | 198 | // 子元素按照常规方式缩进 199 | 203 | 204 | 205 | ``` 206 | 207 | **[⬆ 返回目录](#table-of-contents)** 208 | 209 | ## 单引号和双引号 210 | 211 | - 对于 JSX 属性总是使用双引号 (`"`), 对于其他的 JS 来说使用单引号 (`'`)。 eslint: [`jsx-quotes`](https://eslint.org/docs/rules/jsx-quotes) 212 | 213 | > 为什么? HTML 属性的规则就是使用双引号而不是单引号,因此 JSX 的属性也遵循这个约定。 214 | 215 | ```jsx 216 | // bad 217 | 218 | 219 | // good 220 | 221 | 222 | // bad 223 | 224 | 225 | // good 226 | 227 | ``` 228 | 229 | **[⬆ 返回目录](#table-of-contents)** 230 | 231 | ## 空格 232 | 233 | - 总是在自闭和标签的标签前加一个空格。 eslint: [`no-multi-spaces`](https://eslint.org/docs/rules/no-multi-spaces), [`react/jsx-tag-spacing`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-tag-spacing.md) 234 | 235 | ```jsx 236 | // bad 237 | 238 | 239 | // very bad 240 | 241 | 242 | // bad 243 | 245 | 246 | // good 247 | 248 | ``` 249 | 250 | - 不要在 JSX 中的括号两边添加空格。 eslint: [`react/jsx-curly-spacing`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md) 251 | 252 | ```jsx 253 | // bad 254 | 255 | 256 | // good 257 | 258 | ``` 259 | 260 | **[⬆ 返回目录](#table-of-contents)** 261 | 262 | ## 属性 263 | 264 | - 总是使用驼峰命名法命名属性名。 265 | 266 | ```jsx 267 | // bad 268 | 272 | 273 | // good 274 | 278 | ``` 279 | 280 | - 当一个属性的值为显式的 `true` 时,应该省略。 eslint: [`react/jsx-boolean-value`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md) 281 | 282 | ```jsx 283 | // bad 284 |