├── .editorconfig ├── .eslintrc.yaml ├── .gitignore ├── .markdownlint.json ├── .npmrc ├── .prettierrc.js ├── .travis.yml ├── LICENSE.md ├── README.md ├── babel.config.js ├── css-in-javascript └── README.md ├── lerna.json ├── package-lock.json ├── package.json ├── packages ├── babel-preset-zillow │ ├── CHANGELOG.md │ ├── README.md │ ├── index.js │ └── package.json ├── eslint-config-zillow-base │ ├── .editorconfig │ ├── .eslintrc.yaml │ ├── CHANGELOG-upstream.md │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── index.js │ ├── jest.js │ ├── mocha.js │ ├── package.json │ ├── prettier.config.js │ ├── rules │ │ ├── best-practices.js │ │ ├── errors.js │ │ ├── es6.js │ │ ├── imports.js │ │ ├── node.js │ │ ├── prettier.js │ │ ├── strict.js │ │ ├── style.js │ │ └── variables.js │ └── test │ │ ├── requires.js │ │ └── test-base.js ├── eslint-config-zillow-typescript │ ├── .editorconfig │ ├── .eslintrc.yaml │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── index.js │ ├── package.json │ ├── prettier.config.js │ ├── rules │ │ ├── all-remaining.js │ │ ├── eslint-recommended.js │ │ ├── other-plugin-overrides.js │ │ ├── prettier.js │ │ ├── recommended-requiring-type-checking.js │ │ └── recommended.js │ └── test │ │ └── requires.js ├── eslint-config-zillow │ ├── .editorconfig │ ├── .eslintrc.yaml │ ├── CHANGELOG-upstream.md │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── index.js │ ├── jest.js │ ├── mocha.js │ ├── package.json │ ├── prettier.config.js │ ├── rules │ │ ├── react-a11y.js │ │ └── react.js │ └── test │ │ ├── requires.js │ │ └── test-react-order.js ├── eslint-plugin-zillow │ ├── CHANGELOG.md │ ├── README.md │ ├── lib │ │ ├── configs │ │ │ └── .gitkeep │ │ ├── eslint-plugin-zillow.js │ │ ├── plugins.js │ │ └── render-plugin-configs.js │ ├── package.json │ ├── prettier.config.js │ └── test │ │ ├── __snapshots__ │ │ └── eslint-plugin-zillow.test.js.snap │ │ └── eslint-plugin-zillow.test.js ├── prettier-config-zillow │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── lib │ │ └── prettier-config-zillow.js │ ├── package.json │ └── test │ │ └── prettier-config-zillow.test.js ├── zillow-browser-shims │ ├── CHANGELOG-upstream.md │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── browser-only.js │ ├── document-contains.js │ ├── package.json │ ├── test │ │ └── zillow-browser-shims.test.js │ └── zillow-browser-shims.js └── zillow-js-shims │ ├── CHANGELOG-upstream.md │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── target │ ├── es2015.js │ ├── es2016.js │ ├── es2017.js │ ├── es2018.js │ ├── es2019.js │ └── es5.js │ ├── test │ └── zillow-js-shims.test.js │ └── zillow-js-shims.js └── react └── README.md /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 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 | 13 | [*.{json,yaml,yml}] 14 | indent_size = 2 15 | -------------------------------------------------------------------------------- /.eslintrc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | root: true 3 | extends: 4 | - zillow-base 5 | - plugin:jest/recommended 6 | plugins: 7 | - jest 8 | env: 9 | jest/globals: false 10 | rules: 11 | strict: "off" 12 | overrides: 13 | - files: "**/test/**" 14 | env: 15 | jest/globals: true 16 | - files: "packages/zillow-browser-shims/document-contains.js" 17 | rules: 18 | func-name-matching: "off" 19 | - files: "packages/babel-preset-zillow/index.js" 20 | rules: 21 | prefer-object-spread: "off" 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | node_modules 3 | .eslintcache 4 | packages/eslint-plugin-zillow/lib/configs/*.json 5 | -------------------------------------------------------------------------------- /.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 | "start_indented": true, 30 | "indent": 2 31 | }, 32 | 33 | "comment": "MD009: Disallow trailing spaces", 34 | "no-trailing-spaces": { 35 | "br-spaces": 0, 36 | "comment": "Empty lines inside list items should not be indented", 37 | "list_item_empty_lines": false 38 | }, 39 | 40 | "comment": "MD010: No hard tabs, not even in code blocks", 41 | "no-hard-tabs": { 42 | "code_blocks": true 43 | }, 44 | 45 | "comment": "MD011: Prevent reversed link syntax", 46 | "no-reversed-links": true, 47 | 48 | "comment": "MD012: Disallow multiple consecutive blank lines", 49 | "no-multiple-blanks": { 50 | "maximum": 1 51 | }, 52 | 53 | "comment": "MD013: Line length", 54 | "line-length": false, 55 | 56 | "comment": "MD014: Disallow dollar signs used before commands without showing output", 57 | "commands-show-output": true, 58 | 59 | "comment": "MD018: Disallow space after hash on atx style header", 60 | "no-missing-space-atx": true, 61 | 62 | "comment": "MD019: Dissalow multiple spaces after hash on atx style header", 63 | "no-multiple-space-atx": true, 64 | 65 | "comment": "MD020: No space inside hashes on closed atx style header", 66 | "no-missing-space-closed-atx": true, 67 | 68 | "comment": "MD021: Disallow multiple spaces inside hashes on closed atx style header", 69 | "no-multiple-space-closed-atx": true, 70 | 71 | "comment": "MD022: Headers should be surrounded by blank lines", 72 | "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", 73 | "blanks-around-headers": false, 74 | 75 | "comment": "MD023: Headers must start at the beginning of the line", 76 | "header-start-left": true, 77 | 78 | "comment": "MD024: Disallow multiple headers with the same content", 79 | "no-duplicate-header": true, 80 | 81 | "comment": "MD025: Disallow multiple top level headers in the same document", 82 | "comment": "Gotta have a matching closing brace at the end", 83 | "single-h1": false, 84 | 85 | "comment": "MD026: Disallow trailing punctuation in header", 86 | "comment": "Gotta have a semicolon after the ending closing brace", 87 | "no-trailing-punctuation": { 88 | "punctuation" : ".,:!?" 89 | }, 90 | "comment": "MD027: Dissalow multiple spaces after blockquote symbol", 91 | "no-multiple-space-blockquote": true, 92 | 93 | "comment": "MD028: Blank line inside blockquote", 94 | "comment": "Some 'Why?' and 'Why not?' blocks are separated by a blank line", 95 | "no-blanks-blockquote": false, 96 | 97 | "comment": "MD029: Ordered list item prefix", 98 | "ol-prefix": { 99 | "style": "one" 100 | }, 101 | 102 | "comment": "MD030: Spaces after list markers", 103 | "list-marker-space": { 104 | "ul_single": 1, 105 | "ol_single": 1, 106 | "ul_multi": 1, 107 | "ol_multi": 1 108 | }, 109 | 110 | "comment": "MD031: Fenced code blocks should be surrounded by blank lines", 111 | "blanks-around-fences": true, 112 | 113 | "comment": "MD032: Lists should be surrounded by blank lines", 114 | "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", 115 | "blanks-around-lists": false, 116 | 117 | "comment": "MD033: Disallow inline HTML", 118 | "comment": "HTML is needed for explicit anchors", 119 | "no-inline-html": false, 120 | 121 | "comment": "MD034: No bare URLs used", 122 | "no-bare-urls": true, 123 | 124 | "comment": "MD035: Horizontal rule style", 125 | "hr-style": { 126 | "style": "consistent" 127 | }, 128 | 129 | "comment": "MD036: Do not use emphasis instead of a header", 130 | "no-emphasis-as-header": false, 131 | 132 | "comment": "MD037: Disallow spaces inside emphasis markers", 133 | "no-space-in-emphasis": true, 134 | 135 | "comment": "MD038: Disallow spaces inside code span elements", 136 | "no-space-in-code": true, 137 | 138 | "comment": "MD039: Disallow spaces inside link text", 139 | "no-space-in-links": true, 140 | 141 | "comment": "MD040: Fenced code blocks should have a language specified", 142 | "fenced-code-language": true, 143 | 144 | "comment": "MD041: First line in file should be a top level header", 145 | "first-line-h1": true, 146 | 147 | "comment": "MD042: No empty links", 148 | "no-empty-links": true, 149 | 150 | "comment": "MD043: Required header structure", 151 | "required-headers": false, 152 | 153 | "comment": "MD044: Proper names should have the correct capitalization", 154 | "proper-names": false 155 | } 156 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry = https://registry.npmjs.org/ 2 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = require('prettier-config-zillow'); 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # don't build tags, it's redundant 2 | if: tag IS blank 3 | language: node_js 4 | node_js: 5 | - "12" 6 | - "10" 7 | cache: 8 | directories: 9 | - $HOME/.npm 10 | before_install: 11 | - nvm install-latest-npm 12 | install: 13 | - npm ci 14 | script: 15 | - npm t 16 | sudo: false 17 | env: 18 | global: 19 | - NO_UPDATE_NOTIFIER=1 20 | matrix: 21 | fast_finish: true 22 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012 Airbnb 4 | Copyright (c) 2018 Zillow 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | presets: [ 5 | [ 6 | '@babel/preset-env', 7 | { 8 | targets: { 9 | node: 'current', 10 | }, 11 | }, 12 | ], 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /css-in-javascript/README.md: -------------------------------------------------------------------------------- 1 | # Zillow CSS-in-JavaScript Code Conventions 2 | 3 | *A mostly reasonable approach to CSS-in-JavaScript* 4 | 5 | ## Table of Contents 6 | 7 | 1. [Naming](#naming) 8 | 1. [Ordering](#ordering) 9 | 1. [Nesting](#nesting) 10 | 1. [Inline](#inline) 11 | 1. [Themes](#themes) 12 | 13 | ## Naming 14 | 15 | - Use camelCase for object keys (i.e. "selectors"). 16 | 17 | > Why? We access these keys as properties on the `styles` object in the component, so it is most convenient to use camelCase. 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 | - Use an underscore for modifiers to other styles. 36 | 37 | > Why? Similar to BEM, this naming convention makes it clear that the styles are intended to modify the element preceded by the underscore. Underscores do not need to be quoted, so they are preferred over other characters, such as dashes. 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 | - Use `selectorName_fallback` for sets of fallback styles. 66 | 67 | > Why? Similar to modifiers, keeping the naming consistent helps reveal the relationship of these styles to the styles that override them in more adequate browsers. 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 | - Use a separate selector for sets of fallback styles. 94 | 95 | > Why? Keeping fallback styles contained in a separate object clarifies their purpose, which improves readability. 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 | - Use device-agnostic names (e.g. "small", "medium", and "large") to name media query breakpoints. 135 | 136 | > Why? Commonly used names like "phone", "tablet", and "desktop" do not match the characteristics of the devices in the real world. Using these names sets the wrong expectations. 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 | ## Ordering 155 | 156 | - Define styles after the component. 157 | 158 | > Why? We use a higher-order component to theme our styles, which is naturally used after the component definition. Passing the styles object directly to this function reduces indirection. 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 | ## Nesting 197 | 198 | - Leave a blank line between adjacent blocks at the same indentation level. 199 | 200 | > Why? The whitespace improves readability and reduces the likelihood of merge conflicts. 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 | ## Inline 233 | 234 | - Use inline styles for styles that have a high cardinality (e.g. uses the value of a prop) and not for styles that have a low cardinality. 235 | 236 | > Why? Generating themed stylesheets can be expensive, so they are best for discrete sets of styles. 237 | 238 | ```jsx 239 | // bad 240 | export default function MyComponent({ spacing }) { 241 | return ( 242 |
243 | ); 244 | } 245 | 246 | // good 247 | function MyComponent({ styles, spacing }) { 248 | return ( 249 |
250 | ); 251 | } 252 | export default withStyles(() => ({ 253 | periodic: { 254 | display: 'table', 255 | }, 256 | }))(MyComponent); 257 | ``` 258 | 259 | ## Themes 260 | 261 | - Use an abstraction layer such as [react-with-styles](https://github.com/airbnb/react-with-styles) that enables theming. *react-with-styles gives us things like `withStyles()`, `ThemedStyleSheet`, and `css()` which are used in some of the examples in this document.* 262 | 263 | > Why? It is useful to have a set of shared variables for styling your components. Using an abstraction layer makes this more convenient. Additionally, this can help prevent your components from being tightly coupled to any particular underlying implementation, which gives you more freedom. 264 | 265 | - Define colors only in themes. 266 | 267 | ```js 268 | // bad 269 | export default withStyles(() => ({ 270 | chuckNorris: { 271 | color: '#bada55', 272 | }, 273 | }))(MyComponent); 274 | 275 | // good 276 | export default withStyles(({ color }) => ({ 277 | chuckNorris: { 278 | color: color.badass, 279 | }, 280 | }))(MyComponent); 281 | ``` 282 | 283 | - Define fonts only in themes. 284 | 285 | ```js 286 | // bad 287 | export default withStyles(() => ({ 288 | towerOfPisa: { 289 | fontStyle: 'italic', 290 | }, 291 | }))(MyComponent); 292 | 293 | // good 294 | export default withStyles(({ font }) => ({ 295 | towerOfPisa: { 296 | fontStyle: font.italic, 297 | }, 298 | }))(MyComponent); 299 | ``` 300 | 301 | - Define fonts as sets of related styles. 302 | 303 | ```js 304 | // bad 305 | export default withStyles(() => ({ 306 | towerOfPisa: { 307 | fontFamily: 'Italiana, "Times New Roman", serif', 308 | fontSize: '2em', 309 | fontStyle: 'italic', 310 | lineHeight: 1.5, 311 | }, 312 | }))(MyComponent); 313 | 314 | // good 315 | export default withStyles(({ font }) => ({ 316 | towerOfPisa: { 317 | ...font.italian, 318 | }, 319 | }))(MyComponent); 320 | ``` 321 | 322 | - Define base grid units in theme (either as a value or a function that takes a multiplier). 323 | 324 | ```js 325 | // bad 326 | export default withStyles(() => ({ 327 | rip: { 328 | bottom: '-6912px', // 6 feet 329 | }, 330 | }))(MyComponent); 331 | 332 | // good 333 | export default withStyles(({ units }) => ({ 334 | rip: { 335 | bottom: units(864), // 6 feet, assuming our unit is 8px 336 | }, 337 | }))(MyComponent); 338 | 339 | // good 340 | export default withStyles(({ unit }) => ({ 341 | rip: { 342 | bottom: 864 * unit, // 6 feet, assuming our unit is 8px 343 | }, 344 | }))(MyComponent); 345 | ``` 346 | 347 | - Define media queries only in themes. 348 | 349 | ```js 350 | // bad 351 | export default withStyles(() => ({ 352 | container: { 353 | width: '100%', 354 | 355 | '@media (max-width: 1047px)': { 356 | width: '50%', 357 | }, 358 | }, 359 | }))(MyComponent); 360 | 361 | // good 362 | export default withStyles(({ breakpoint }) => ({ 363 | container: { 364 | width: '100%', 365 | 366 | [breakpoint.medium]: { 367 | width: '50%', 368 | }, 369 | }, 370 | }))(MyComponent); 371 | ``` 372 | 373 | - Define tricky fallback properties in themes. 374 | 375 | > Why? Many CSS-in-JavaScript implementations merge style objects together which makes specifying fallbacks for the same property (e.g. `display`) a little tricky. To keep the approach unified, put these fallbacks in the theme. 376 | 377 | ```js 378 | // bad 379 | export default withStyles(() => ({ 380 | .muscles { 381 | display: 'flex', 382 | }, 383 | 384 | .muscles_fallback { 385 | 'display ': 'table', 386 | }, 387 | }))(MyComponent); 388 | 389 | // good 390 | export default withStyles(({ fallbacks }) => ({ 391 | .muscles { 392 | display: 'flex', 393 | }, 394 | 395 | .muscles_fallback { 396 | [fallbacks.display]: 'table', 397 | }, 398 | }))(MyComponent); 399 | 400 | // good 401 | export default withStyles(({ fallback }) => ({ 402 | .muscles { 403 | display: 'flex', 404 | }, 405 | 406 | .muscles_fallback { 407 | [fallback('display')]: 'table', 408 | }, 409 | }))(MyComponent); 410 | ``` 411 | 412 | - Create as few custom themes as possible. Many applications may only have one theme. 413 | 414 | - Namespace custom theme settings under a nested object with a unique and descriptive key. 415 | 416 | ```js 417 | // bad 418 | ThemedStyleSheet.registerTheme('mySection', { 419 | mySectionPrimaryColor: 'green', 420 | }); 421 | 422 | // good 423 | ThemedStyleSheet.registerTheme('mySection', { 424 | mySection: { 425 | primaryColor: 'green', 426 | }, 427 | }); 428 | ``` 429 | 430 | --- 431 | 432 | CSS puns adapted from [Saijo George](https://saijogeorge.com/css-puns/). 433 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "command": { 3 | "create": { 4 | "license": "MIT" 5 | }, 6 | "version": { 7 | "allowBranch": "latest", 8 | "conventionalCommits": true, 9 | "exact": true, 10 | "message": "chore(release): Publish" 11 | } 12 | }, 13 | "ignoreChanges": [ 14 | "**/test/**", 15 | "**/*.md" 16 | ], 17 | "loglevel": "success", 18 | "packages": [ 19 | "packages/*" 20 | ], 21 | "version": "independent" 22 | } 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zillow-style", 3 | "version": "0.0.0-monorepo", 4 | "private": true, 5 | "description": "A mostly reasonable approach to JavaScript.", 6 | "scripts": { 7 | "build:plugin": "node ./packages/eslint-plugin-zillow/lib/render-plugin-configs.js", 8 | "check:prettier:parser": "prettier --debug-check --ignore-path ./.gitignore 'packages/**/*.@(js|md)'", 9 | "lint": "npm-run-all --silent lint:*", 10 | "lint:js": "eslint ./packages --cache --cache-location ./node_modules/.cache/eslint --report-unused-disable-directives", 11 | "lint:md": "markdownlint README.md */README.md packages/*/README.md", 12 | "lint:rules": "npm-run-all --silent --print-label lint:rules:*", 13 | "lint:rules:base": "eslint-find-rules --unused packages/eslint-config-zillow-base/index.js", 14 | "lint:rules:jest": "eslint-find-rules --unused packages/eslint-config-zillow-base/jest.js --no-core", 15 | "lint:rules:main": "eslint-find-rules --unused packages/eslint-config-zillow/index.js", 16 | "lint:rules:mocha": "eslint-find-rules --unused packages/eslint-config-zillow-base/mocha.js --no-core", 17 | "lint:rules:typescript": "eslint-find-rules --unused packages/eslint-config-zillow-typescript/index.js --no-core", 18 | "lint:prettier": "eslint --print-config packages/eslint-config-zillow/index.js | eslint-config-prettier-check", 19 | "pretest": "npm run build:plugin && npm run --silent lint", 20 | "test": "jest", 21 | "test:watch": "jest --watch", 22 | "preversion": "npm test" 23 | }, 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/zillow/javascript.git" 27 | }, 28 | "keywords": [ 29 | "style guide", 30 | "lint", 31 | "zillow", 32 | "es6", 33 | "es2015", 34 | "react", 35 | "jsx" 36 | ], 37 | "license": "MIT", 38 | "homepage": "https://github.com/zillow/javascript", 39 | "engines": { 40 | "node": ">= 10.17" 41 | }, 42 | "jest": { 43 | "testRunner": "jest-circus/runner", 44 | "testEnvironment": "node", 45 | "testMatch": [ 46 | "/packages/**/test/**/*.js" 47 | ] 48 | }, 49 | "devDependencies": { 50 | "@babel/code-frame": "^7.10.4", 51 | "@babel/core": "^7.11.6", 52 | "@babel/generator": "^7.11.6", 53 | "@babel/helper-annotate-as-pure": "^7.10.4", 54 | "@babel/helper-builder-react-jsx": "^7.10.4", 55 | "@babel/helper-builder-react-jsx-experimental": "^7.11.5", 56 | "@babel/helper-create-class-features-plugin": "^7.10.5", 57 | "@babel/helper-define-map": "^7.10.5", 58 | "@babel/helper-function-name": "^7.10.4", 59 | "@babel/helper-get-function-arity": "^7.10.4", 60 | "@babel/helper-member-expression-to-functions": "^7.11.0", 61 | "@babel/helper-module-imports": "^7.10.4", 62 | "@babel/helper-optimise-call-expression": "^7.10.4", 63 | "@babel/helper-plugin-utils": "^7.10.4", 64 | "@babel/helper-replace-supers": "^7.10.4", 65 | "@babel/helper-split-export-declaration": "^7.11.0", 66 | "@babel/highlight": "^7.10.4", 67 | "@babel/parser": "^7.11.5", 68 | "@babel/plugin-proposal-class-properties": "^7.10.4", 69 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 70 | "@babel/plugin-syntax-dynamic-import": "^7.8.3", 71 | "@babel/plugin-syntax-jsx": "^7.10.4", 72 | "@babel/plugin-syntax-object-rest-spread": "^7.8.3", 73 | "@babel/plugin-transform-classes": "^7.10.4", 74 | "@babel/plugin-transform-computed-properties": "^7.10.4", 75 | "@babel/plugin-transform-parameters": "^7.10.5", 76 | "@babel/plugin-transform-react-display-name": "^7.10.4", 77 | "@babel/plugin-transform-react-jsx": "^7.10.4", 78 | "@babel/plugin-transform-react-jsx-development": "^7.11.5", 79 | "@babel/plugin-transform-react-jsx-self": "^7.10.4", 80 | "@babel/plugin-transform-react-jsx-source": "^7.10.5", 81 | "@babel/plugin-transform-template-literals": "^7.10.5", 82 | "@babel/preset-env": "^7.11.5", 83 | "@babel/preset-react": "^7.10.4", 84 | "@babel/template": "^7.10.4", 85 | "@babel/traverse": "^7.11.5", 86 | "@babel/types": "^7.11.5", 87 | "@eslint/eslintrc": "^0.1.3", 88 | "@typescript-eslint/eslint-plugin": "^4.3.0", 89 | "@typescript-eslint/parser": "^4.3.0", 90 | "babel-eslint": "^10.1.0", 91 | "babel-plugin-dynamic-import-node": "2.3.3", 92 | "babel-plugin-jsx-remove-data-test-id": "^2.1.3", 93 | "babel-plugin-lodash": "^3.3.4", 94 | "babel-plugin-styled-components": "^1.11.1", 95 | "babel-plugin-transform-react-remove-prop-types": "^0.4.24", 96 | "es-abstract": "1.17.6", 97 | "eslint": "^7.10.0", 98 | "eslint-config-prettier": "^6.12.0", 99 | "eslint-find-rules": "^3.6.1", 100 | "eslint-plugin-import": "^2.22.1", 101 | "eslint-plugin-jest": "^24.0.2", 102 | "eslint-plugin-jsx-a11y": "^6.3.1", 103 | "eslint-plugin-mocha": "^8.0.0", 104 | "eslint-plugin-prettier": "^3.1.4", 105 | "eslint-plugin-react": "^7.21.2", 106 | "eslint-plugin-react-hooks": "^4.1.2", 107 | "fast-async": "^7.0.6", 108 | "jest": "^26.4.2", 109 | "jest-circus": "^26.4.2", 110 | "jsx-ast-utils": "2.4.1", 111 | "lerna": "^3.22.1", 112 | "markdownlint-cli": "^0.23.2", 113 | "npm-run-all": "^4.1.5", 114 | "object.assign": "4.1.0", 115 | "prettier": "^2.1.2", 116 | "react": "^16.13.1", 117 | "react-dom": "^16.13.1", 118 | "side-channel": "1.0.2", 119 | "string.prototype.matchall": "4.0.2", 120 | "styled-components": "^4.4.1", 121 | "typescript": "^4.0.3" 122 | }, 123 | "dependencies": { 124 | "babel-preset-zillow": "file:packages/babel-preset-zillow", 125 | "eslint-config-zillow": "file:packages/eslint-config-zillow", 126 | "eslint-config-zillow-base": "file:packages/eslint-config-zillow-base", 127 | "eslint-config-zillow-typescript": "file:packages/eslint-config-zillow-typescript", 128 | "eslint-plugin-zillow": "file:packages/eslint-plugin-zillow", 129 | "prettier-config-zillow": "file:packages/prettier-config-zillow", 130 | "zillow-browser-shims": "file:packages/zillow-browser-shims", 131 | "zillow-js-shims": "file:packages/zillow-js-shims" 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /packages/babel-preset-zillow/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | ## [4.4.1](https://github.com/zillow/javascript/compare/babel-preset-zillow@4.4.0...babel-preset-zillow@4.4.1) (2023-05-22) 7 | 8 | 9 | ### Bug Fixes 10 | 11 | * **preset:** class-properties, private-methods and private-property-in-object must have the same "loose" configuration ([#12](https://github.com/zillow/javascript/issues/12)) ([2ed49da](https://github.com/zillow/javascript/commit/2ed49da25c224ad6ee71f27ff687bb833e14cad7)) 12 | 13 | 14 | 15 | 16 | 17 | # [4.4.0](https://github.com/zillow/javascript/compare/babel-preset-zillow@4.3.0...babel-preset-zillow@4.4.0) (2020-09-24) 18 | 19 | 20 | ### Bug Fixes 21 | 22 | * **preset:** Do not transform lodash during tests ([a41af7d](https://github.com/zillow/javascript/commit/a41af7db49c7917f0da939c4ea79d2ce18428e73)) 23 | 24 | 25 | ### Features 26 | 27 | * **preset:** Update dependencies ([1bb9030](https://github.com/zillow/javascript/commit/1bb9030c79bc6b5f58a192acca261106339341d4)) 28 | 29 | 30 | 31 | 32 | 33 | # [4.3.0](https://github.com/zillow/javascript/compare/babel-preset-zillow@4.2.0...babel-preset-zillow@4.3.0) (2020-04-28) 34 | 35 | 36 | ### Features 37 | 38 | * **preset:** Pass loose:true to object-rest-spread plugin ([6413205](https://github.com/zillow/javascript/commit/6413205bb92b681477333cd6009145cdaa65c054)) 39 | * **preset:** Support nested configuration overrides ([51d9130](https://github.com/zillow/javascript/commit/51d913092105f985ea039cb5ef4544b6da4f2e3b)) 40 | * **preset:** Update dependencies ([c1a856f](https://github.com/zillow/javascript/commit/c1a856f12e3c6a4933b1bc32c1995c9069deb53e)) 41 | 42 | 43 | 44 | 45 | 46 | # [4.2.0](https://github.com/zillow/javascript/compare/babel-preset-zillow@4.1.0...babel-preset-zillow@4.2.0) (2019-08-07) 47 | 48 | 49 | ### Bug Fixes 50 | 51 | * **preset:** Restore customizability of `removeDataTestId` attributes ([c18c49c](https://github.com/zillow/javascript/commit/c18c49c)) 52 | 53 | 54 | ### Features 55 | 56 | * **preset:** Add `additionalExcludes` config for advanced plugin exclusion ([a04c389](https://github.com/zillow/javascript/commit/a04c389)) 57 | * **preset:** Update dependencies ([feb9349](https://github.com/zillow/javascript/commit/feb9349)) 58 | 59 | 60 | 61 | 62 | 63 | # [4.1.0](https://github.com/zillow/javascript/compare/babel-preset-zillow@4.0.3...babel-preset-zillow@4.1.0) (2019-05-06) 64 | 65 | 66 | ### Features 67 | 68 | * **preset:** Add `useBuiltIns` and `corejs` options, proxied directly to `@babel/preset-env` ([007eb00](https://github.com/zillow/javascript/commit/007eb00)) 69 | 70 | 71 | 72 | 73 | 74 | ## [4.0.3](https://github.com/zillow/javascript/compare/babel-preset-zillow@4.0.2...babel-preset-zillow@4.0.3) (2019-03-22) 75 | 76 | 77 | ### Bug Fixes 78 | 79 | * **preset:** Don't use full plugin names in exclude list, it's not backward-compatible ([7463ad4](https://github.com/zillow/javascript/commit/7463ad4)) 80 | 81 | 82 | 83 | 84 | 85 | ## [4.0.2](https://github.com/zillow/javascript/compare/babel-preset-zillow@4.0.1...babel-preset-zillow@4.0.2) (2019-03-22) 86 | 87 | 88 | ### Bug Fixes 89 | 90 | * **preset:** Relax babel plugin dependency ranges back to ^7.0.0 ([741ea9c](https://github.com/zillow/javascript/commit/741ea9c)) 91 | 92 | 93 | 94 | 95 | 96 | ## [4.0.1](https://github.com/zillow/javascript/compare/babel-preset-zillow@4.0.0...babel-preset-zillow@4.0.1) (2019-03-21) 97 | 98 | 99 | ### Bug Fixes 100 | 101 | * **babel-preset-zillow:** Remove browser targets that were removed in a silently-breaking minor release ([a50c64f](https://github.com/zillow/javascript/commit/a50c64f)) 102 | 103 | 104 | 105 | 106 | 107 | # [4.0.0](https://github.com/zillow/javascript/compare/babel-preset-zillow@3.0.0...babel-preset-zillow@4.0.0) (2019-03-15) 108 | 109 | 110 | ### Features 111 | 112 | * **babel-preset-zillow:** Omit many plugins when `targets.node` option is present ([adcfeb8](https://github.com/zillow/javascript/commit/adcfeb8)) 113 | * **babel-preset-zillow:** Remove ES3 and ES5 plugins ([ce6ce75](https://github.com/zillow/javascript/commit/ce6ce75)) 114 | 115 | 116 | ### BREAKING CHANGES 117 | 118 | * **babel-preset-zillow:** Ancient browsers such as IE 8 are no longer supported. 119 | 120 | 121 | 122 | 123 | 124 | # [3.0.0](https://github.com/zillow/javascript/compare/babel-preset-zillow@2.2.0...babel-preset-zillow@3.0.0) (2019-03-13) 125 | 126 | 127 | ### Features 128 | 129 | * **babel-preset-zillow:** Opt-out of loose mode ([0cb59e7](https://github.com/zillow/javascript/commit/0cb59e7)) 130 | 131 | 132 | ### BREAKING CHANGES 133 | 134 | * **babel-preset-zillow:** Formerly opt-in, the loose mode configuration is now opt-out. 135 | 136 | 137 | 138 | 139 | 140 | # [2.2.0](https://github.com/zillow/javascript/compare/babel-preset-zillow@2.1.2...babel-preset-zillow@2.2.0) (2019-03-13) 141 | 142 | 143 | ### Features 144 | 145 | * **babel-preset-zillow:** Add opt-in loose mode options ([262d55b](https://github.com/zillow/javascript/commit/262d55b)) 146 | * **babel-preset-zillow:** Add opt-out removal of JSX data-testid attributes ([8184c46](https://github.com/zillow/javascript/commit/8184c46)) 147 | * **babel-preset-zillow:** Add styled-components plugin ([29b391d](https://github.com/zillow/javascript/commit/29b391d)) 148 | 149 | 150 | 151 | 152 | 153 | ## [2.1.2](https://github.com/zillow/javascript/compare/babel-preset-zillow@2.1.1...babel-preset-zillow@2.1.2) (2019-03-13) 154 | 155 | 156 | ### Bug Fixes 157 | 158 | * **babel-preset-zillow:** Sync upstream changes ([a79abb4](https://github.com/zillow/javascript/commit/a79abb4)) 159 | 160 | 161 | 162 | 163 | 164 | ## [2.1.1](https://github.com/zillow/javascript/compare/babel-preset-zillow@2.1.0...babel-preset-zillow@2.1.1) (2018-11-16) 165 | 166 | 167 | ### Bug Fixes 168 | 169 | * **babel-preset-zillow:** Wrap `propTypes` by default with explicit opt-out ([606be92](https://github.com/zillow/javascript/commit/606be92)) 170 | 171 | 172 | 173 | 174 | 175 | # [2.1.0](https://github.com/zillow/javascript/compare/babel-preset-zillow@2.0.0...babel-preset-zillow@2.1.0) (2018-11-12) 176 | 177 | 178 | ### Features 179 | 180 | * **babel-preset-zillow:** Support dynamic import() with test fallback ([2a120ca](https://github.com/zillow/javascript/commit/2a120ca)) 181 | 182 | 183 | 184 | 185 | 186 | # [2.0.0](https://github.com/zillow/javascript/compare/babel-preset-zillow@1.0.0...babel-preset-zillow@2.0.0) (2018-11-06) 187 | 188 | 189 | ### Features 190 | 191 | * Upgrade to Babel 7 ([23bba84](https://github.com/zillow/javascript/commit/23bba84)) 192 | 193 | 194 | ### BREAKING CHANGES 195 | 196 | * Babel 6 is no longer supported. 197 | 198 | 199 | 200 | 201 | 202 | 203 | # [1.0.0](https://github.com/zillow/javascript/compare/babel-preset-zillow@1.0.0-rc.2...babel-preset-zillow@1.0.0) (2018-08-15) 204 | 205 | 206 | ### Bug Fixes 207 | 208 | * **pkg:** Correct homepage URL ([1b5e7f0](https://github.com/zillow/javascript/commit/1b5e7f0)) 209 | 210 | 211 | 212 | 213 | 214 | 215 | # [1.0.0-rc.2](https://github.com/zillow/javascript/compare/babel-preset-zillow@1.0.0-rc.0...babel-preset-zillow@1.0.0-rc.2) (2018-07-26) 216 | 217 | 218 | ### Bug Fixes 219 | 220 | * **babel-preset-zillow:** Preserve buildTargets when no options are passed ([#1](https://github.com/zillow/javascript/issues/1)) ([8138568](https://github.com/zillow/javascript/commit/8138568)) 221 | 222 | 223 | 224 | 225 | 226 | 227 | # [1.0.0-rc.1](https://github.com/zillow/javascript/compare/babel-preset-zillow@1.0.0-rc.0...babel-preset-zillow@1.0.0-rc.1) (2018-07-26) 228 | 229 | 230 | ### Bug Fixes 231 | 232 | * **babel-preset-zillow:** Preserve buildTargets when no options are passed ([#1](https://github.com/zillow/javascript/issues/1)) ([8138568](https://github.com/zillow/javascript/commit/8138568)) 233 | 234 | 235 | 236 | 237 | 238 | 239 | # [1.0.0-rc.0](https://github.com/zillow/javascript/compare/babel-preset-zillow@1.0.0-alpha.4...babel-preset-zillow@1.0.0-rc.0) (2018-06-05) 240 | 241 | **Note:** Version bump only for package babel-preset-zillow 242 | 243 | 244 | 245 | 246 | 247 | 248 | # [1.0.0-alpha.4](https://github.com/zillow/javascript/compare/babel-preset-zillow@1.0.0-alpha.3...babel-preset-zillow@1.0.0-alpha.4) (2018-04-10) 249 | 250 | 251 | ### Features 252 | 253 | * **babel-preset-zillow:** Update browser targets ([41ac056](https://github.com/zillow/javascript/commit/41ac056)) 254 | 255 | 256 | 257 | 258 | 259 | 260 | # [1.0.0-alpha.3](https://github.com/zillow/javascript/compare/babel-preset-zillow@1.0.0-alpha.2...babel-preset-zillow@1.0.0-alpha.3) (2018-04-06) 261 | 262 | 263 | ### Bug Fixes 264 | 265 | * Normalize author metadata ([bdcab0c](https://github.com/zillow/javascript/commit/bdcab0c)) 266 | 267 | 268 | 269 | 270 | 271 | 272 | # [1.0.0-alpha.2](https://github.com/zillow/javascript/compare/babel-preset-zillow@1.0.0-alpha.1...babel-preset-zillow@1.0.0-alpha.2) (2018-04-05) 273 | 274 | 275 | ### Features 276 | 277 | * **babel-preset-zillow:** Add dev-mode transforms react-jsx-self + react-jsx-source ([7e5712a](https://github.com/zillow/javascript/commit/7e5712a)) 278 | * **babel-preset-zillow:** Enable throwIfClosureRequired in transform-es2015-block-scoping ([1d6bc02](https://github.com/zillow/javascript/commit/1d6bc02)) 279 | 280 | 281 | 282 | 283 | 284 | 285 | # 1.0.0-alpha.1 (2018-04-04) 286 | 287 | 288 | ### Features 289 | 290 | * Add babel-preset-zillow ([88b0bb4](https://github.com/zillow/javascript/commit/88b0bb4)) 291 | -------------------------------------------------------------------------------- /packages/babel-preset-zillow/README.md: -------------------------------------------------------------------------------- 1 | # babel-preset-zillow 2 | 3 | > A Babel preset for transpiling JavaScript following our code conventions 4 | 5 | [![npm version](https://img.shields.io/npm/v/babel-preset-zillow.svg)](https://www.npmjs.com/package/babel-preset-zillow) 6 | [![Build Status](https://travis-ci.org/zillow/javascript.svg?branch=latest)](https://travis-ci.org/zillow/javascript) 7 | 8 | Currently contains transforms for all [stage 4](https://tc39.github.io/ecma262/) (ES2018) and [stage 3](https://github.com/tc39/proposals#active-proposals) syntax that is permitted in the [Zillow Style Guide](https://github.com/zillow/javascript). Please note that if usage of a stage 3 proposal is not explicitly mentioned in the Zillow Style Guide, then it will not be enabled here. Additionally, stage 4 syntax that is excluded is as follows: 9 | - generators: `regenerator-runtime` is too heavyweight for our use. 10 | - `SIMD`: this is a performance feature, so is pretty pointless to polyfill/transpile. 11 | - lifted template literal restrictions: we do not use tagged template literals, nor implement custom DSLs, otherwise we would enable this. 12 | 13 | Additionally, we also transpile the following: 14 | - [async/await](https://www.npmjs.com/package/fast-async) 15 | - [class properties](https://www.npmjs.com/package/babel-plugin-transform-class-properties) 16 | - [lodash](https://www.npmjs.com/package/babel-plugin-lodash) 17 | - [styled-components](https://www.styled-components.com/docs/tooling#babel-plugin) 18 | 19 | ## Install 20 | 21 | ```sh 22 | npm install --save-dev babel-preset-zillow 23 | ``` 24 | 25 | ## Usage 26 | 27 | ### Via `.babelrc` (Recommended) 28 | 29 | **.babelrc** 30 | 31 | ```json 32 | { 33 | "presets": ["babel-preset-zillow"] 34 | } 35 | ``` 36 | 37 | ### Via CLI 38 | 39 | ```sh 40 | babel script.js --presets zillow 41 | ``` 42 | 43 | ### Via Node API 44 | 45 | ```javascript 46 | require("babel-core").transform("code", { 47 | presets: ["babel-preset-zillow"] 48 | }); 49 | ``` 50 | 51 | ## Targeting Environments 52 | 53 | This module uses `@babel/preset-env` to target specific environments. 54 | 55 | Please refer to [babel-preset-env#targets](https://babeljs.io/docs/en/babel-preset-env#targets) for a list of available options. 56 | 57 | For a list of browsers please see [browserlist](https://github.com/ai/browserslist). 58 | 59 | You may override our default list of targets by providing your own `targets` key. 60 | 61 | ```json 62 | { 63 | "presets": [["babel-preset-zillow", { 64 | "targets": { 65 | "chrome": 50, 66 | "explorer": 11, 67 | "firefox": 45 68 | } 69 | }]] 70 | } 71 | ``` 72 | 73 | The following transpiles only for Node v8. 74 | 75 | ```json 76 | { 77 | "presets": [["babel-preset-zillow", { 78 | "targets": { 79 | "node": 8 80 | } 81 | }]] 82 | } 83 | ``` 84 | 85 | If you wish, you can also inherit our default list of browsers and extend them using `additionalTargets`. 86 | 87 | ```json 88 | { 89 | "presets": [["babel-preset-zillow", { 90 | "additionalTargets": { 91 | "chrome": 42, 92 | "explorer": 8 93 | } 94 | }]] 95 | } 96 | ``` 97 | 98 | ### Configuring Polyfills 99 | 100 | This preset also supports passing additional options directly to `@babel/preset-env`: 101 | 102 | - [`useBuiltIns`](https://babeljs.io/docs/en/babel-preset-env#usebuiltins) 103 | - [`corejs`](https://babeljs.io/docs/en/babel-plugin-transform-runtime#corejs) 104 | 105 | These options are best suited for applications, not libraries, as they require additional dependencies (like [core-js](https://www.npmjs.com/package/core-js)) that are not recommended for libraries. 106 | 107 | For example, the following config would provide all global polyfills necessary for IE11 in an application, based on usage: 108 | 109 | ```json 110 | { 111 | "presets": [["babel-preset-zillow", { 112 | "useBuiltIns": "usage", 113 | "corejs": 3 114 | }]] 115 | } 116 | ``` 117 | 118 | For more examples, please consult the [core-js docs](https://github.com/zloirock/core-js#babelpreset-env). 119 | 120 | ### Advanced Plugin Exclusions 121 | 122 | In some rare cases, it is necessary to explicitly [exclude](https://babeljs.io/docs/en/babel-preset-env#exclude) certain transforms that would otherwise be included by `@babel/preset-env`. 123 | 124 | To accomplish this goal, this preset's default exclusions can be extended with the `additionalExcludes` array. 125 | 126 | ```json 127 | { 128 | "presets": [["babel-preset-zillow", { 129 | "additionalExcludes": [ 130 | "@babel/plugin-transform-classes" 131 | ] 132 | }]] 133 | } 134 | ``` 135 | 136 | You should always pass the fully-qualified transform name, not the shorthand. 137 | When `targets.node` is configured no exclusions are allowed, as they are generally not necessary anyway. 138 | 139 | ## Nested Configuration Overrides 140 | 141 | For advanced use cases, configuration for many of the presets and plugins employed by this module can be passed as sub-keys of the top-level options object. These configuration objects are spread into the internal configuration objects, _overriding_ any keys already set. The currently supported preset option keys are: 142 | 143 | - [`preset-env`](https://babeljs.io/docs/en/babel-preset-env#options) 144 | - [`preset-react`](https://babeljs.io/docs/en/babel-preset-react#options) 145 | - [`styled-components`](https://styled-components.com/docs/tooling#babel-plugin) 146 | - [`object-rest-spread`](https://babeljs.io/docs/en/babel-plugin-proposal-object-rest-spread#options) 147 | 148 | ```json 149 | { 150 | "presets": [["babel-preset-zillow", { 151 | "preset-env": { 152 | "loose": true 153 | }, 154 | "preset-react": { 155 | "runtime": "automatic" 156 | }, 157 | "styled-components": { 158 | "pure": true 159 | }, 160 | "object-rest-spread": { 161 | "useBuiltIns": false 162 | } 163 | }]] 164 | } 165 | ``` 166 | 167 | **Note:** Any options passed under the `preset-env` key will _override_ top-level options such as `modules`, `additionalExcludes` or `additionalTargets` (as both of the "additional" keys are extending the non-prefixed option name). For the time being, you should use one or the other configuration patterns, not both. 168 | 169 | ## Debugging 170 | 171 | You may override our default debug option by providing your own `debug` key. 172 | 173 | ```json 174 | { 175 | "presets": [["babel-preset-zillow", { 176 | "debug": true 177 | }]] 178 | } 179 | ``` 180 | 181 | ## React Optimizations 182 | 183 | By default, this preset will [remove `data-testid` attributes](https://github.com/coderas/babel-plugin-jsx-remove-data-test-id#readme) from JSX elements in non-test builds and [remove `propTypes` definitions](https://github.com/oliviertassinari/babel-plugin-transform-react-remove-prop-types#readme) (via wrapping) from React components in production builds. To explicitly customize this behavior, either pass `false` (to disable) or a config object. 184 | 185 | Disable both optimizations: 186 | 187 | ```json 188 | { 189 | "presets": [["babel-preset-zillow", { 190 | "removeDataTestId": false, 191 | "removePropTypes": false 192 | }]] 193 | } 194 | ``` 195 | 196 | Replace the [attributes targeted by remove-data-test-id](https://github.com/coderas/babel-plugin-jsx-remove-data-test-id#define-custom-attribute-names): 197 | 198 | ```json 199 | { 200 | "presets": [["babel-preset-zillow", { 201 | "removeDataTestId": { 202 | "attributes": ["data-selenium-id"] 203 | } 204 | }]] 205 | } 206 | ``` 207 | 208 | Change the [`mode` option of remove-prop-types](https://github.com/oliviertassinari/babel-plugin-transform-react-remove-prop-types#mode): 209 | 210 | ```json 211 | { 212 | "presets": [["babel-preset-zillow", { 213 | "removePropTypes": { 214 | "mode": "remove", 215 | "removeImport": true 216 | } 217 | }]] 218 | } 219 | ``` 220 | 221 | ## Selective Loose Modes 222 | 223 | By default, this preset will compile as many modules as possible in loose mode. Normal mode is safer, but adds to bundle size and runtime overhead. We have options to selectively opt out of loose mode for applicable features. These options are: 224 | - [classes](https://babeljs.io/docs/en/babel-plugin-transform-classes#loose): `looseClasses` 225 | - [computed properties](https://babeljs.io/docs/en/babel-plugin-transform-computed-properties#loose): `looseComputedProperties` 226 | - [parameters](https://babeljs.io/docs/en/babel-plugin-transform-parameters#loose): `looseParameters` 227 | - [template literals](https://babeljs.io/docs/en/babel-plugin-transform-template-literals#loose): `looseTemplateLiterals` 228 | 229 | For example, disable _all_ loose compilation options: 230 | 231 | ```json 232 | { 233 | "presets": [["babel-preset-zillow", { 234 | "looseClasses": false, 235 | "looseComputedProperties": false, 236 | "looseParameters": false, 237 | "looseTemplateLiterals": false 238 | }]] 239 | } 240 | ``` 241 | -------------------------------------------------------------------------------- /packages/babel-preset-zillow/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { declare } = require('@babel/helper-plugin-utils'); 4 | 5 | const defaultExcludes = [ 6 | '@babel/plugin-transform-async-to-generator', 7 | '@babel/plugin-transform-regenerator', 8 | ]; 9 | 10 | function buildExcludes({ additionalExcludes = [] }) { 11 | return [...defaultExcludes, ...additionalExcludes]; 12 | } 13 | 14 | const defaultTargets = { 15 | android: 62, 16 | chrome: 64, 17 | edge: 16, 18 | ie: 11, 19 | firefox: 58, 20 | ios: 10, 21 | safari: 10, 22 | }; 23 | 24 | function buildTargets({ additionalTargets }) { 25 | return Object.assign({}, defaultTargets, additionalTargets); 26 | } 27 | 28 | module.exports = declare((api, options) => { 29 | // see docs about api at https://babeljs.io/docs/en/config-files#apicache 30 | api.assertVersion('^7.0.0'); 31 | 32 | const env = api.env(); 33 | const { 34 | corejs, 35 | modules, 36 | targets = buildTargets(options), 37 | useBuiltIns, 38 | removeDataTestId = env !== 'test', 39 | removePropTypes = true, 40 | looseClasses = true, 41 | looseComputedProperties = true, 42 | looseParameters = true, 43 | looseTemplateLiterals = true, 44 | } = options; 45 | 46 | if (typeof modules !== 'undefined' && typeof modules !== 'boolean' && modules !== 'auto') { 47 | throw new TypeError( 48 | 'babel-preset-zillow only accepts `true`, `false`, or `"auto"` as the value of the "modules" option' 49 | ); 50 | } 51 | 52 | const debug = typeof options.debug === 'boolean' ? options.debug : false; 53 | const development = 54 | typeof options.development === 'boolean' ? options.development : env === 'development'; 55 | const production = !development && env === 'production'; 56 | 57 | // we assume that those opting into node env know what they're doing, 58 | // and don't need a significant number of plugins or exclusions 59 | const isNode = 'node' in targets; 60 | 61 | // use a Set to streamline plugin conditionals 62 | const excluding = new Set(isNode ? [] : buildExcludes(options)); 63 | 64 | /* eslint global-require: off */ 65 | return { 66 | presets: [ 67 | [ 68 | require('@babel/preset-env'), 69 | { 70 | corejs, 71 | debug, 72 | exclude: Array.from(excluding), 73 | modules: modules === false ? false : 'auto', 74 | targets, 75 | useBuiltIns, 76 | ...options['preset-env'], 77 | }, 78 | ], 79 | [ 80 | require('@babel/preset-react'), 81 | { 82 | development, 83 | ...options['preset-react'], 84 | }, 85 | ], 86 | ], 87 | plugins: [ 88 | [ 89 | // this plugin _always_ needs to be loaded first 90 | require('babel-plugin-styled-components'), 91 | production 92 | ? { 93 | // help bundlers tree-shake 94 | pure: true, 95 | // remove dev-mode noise 96 | displayName: false, 97 | ...options['styled-components'], 98 | } 99 | : { 100 | // use defaults 101 | ...options['styled-components'], 102 | }, 103 | ], 104 | 105 | require('@babel/plugin-syntax-dynamic-import'), 106 | // TODO: Remove env test when Jest supports dynamic import() "natively" 107 | isNode || env === 'test' ? require('babel-plugin-dynamic-import-node') : null, 108 | 109 | // need to hoist this above (possible) class transformer, otherwise it explodes 110 | [require('@babel/plugin-proposal-class-properties'), { loose: true }], 111 | // class-properties, private-methods and private-property-in-object 112 | // must have the same "loose" configuration 113 | [require('@babel/plugin-proposal-private-methods'), { loose: true }], 114 | // class-properties, private-methods and private-property-in-object 115 | // must have the same "loose" configuration 116 | [require('@babel/plugin-proposal-private-property-in-object'), { loose: true }], 117 | 118 | // prettier-ignore 119 | !isNode && 120 | looseClasses && 121 | !excluding.has('@babel/plugin-transform-classes') 122 | ? [require('@babel/plugin-transform-classes'), { loose: true }] 123 | : null, 124 | 125 | !isNode && 126 | looseComputedProperties && 127 | !excluding.has('@babel/plugin-transform-computed-properties') 128 | ? [require('@babel/plugin-transform-computed-properties'), { loose: true }] 129 | : null, 130 | 131 | // prettier-ignore 132 | !isNode && 133 | looseParameters && 134 | !excluding.has('@babel/plugin-transform-parameters') 135 | ? [require('@babel/plugin-transform-parameters'), { loose: true }] 136 | : null, 137 | 138 | !isNode && 139 | looseTemplateLiterals && 140 | !excluding.has('@babel/plugin-transform-template-literals') 141 | ? [require('@babel/plugin-transform-template-literals'), { loose: true }] 142 | : null, 143 | 144 | removeDataTestId 145 | ? [ 146 | require('babel-plugin-jsx-remove-data-test-id'), 147 | Object.assign( 148 | { 149 | attributes: ['data-testid', 'data-test-id'], 150 | }, 151 | removeDataTestId 152 | ), 153 | ] 154 | : null, 155 | 156 | removePropTypes 157 | ? [ 158 | require('babel-plugin-transform-react-remove-prop-types'), 159 | Object.assign( 160 | { 161 | mode: 'wrap', 162 | additionalLibraries: ['airbnb-prop-types'], 163 | ignoreFilenames: ['node_modules'], 164 | }, 165 | removePropTypes 166 | ), 167 | ] 168 | : null, 169 | 170 | isNode 171 | ? null 172 | : [ 173 | require('@babel/plugin-proposal-object-rest-spread'), 174 | { 175 | loose: true, 176 | useBuiltIns: true, 177 | ...options['object-rest-spread'], 178 | }, 179 | ], 180 | 181 | isNode ? null : [require('fast-async'), { spec: true }], 182 | // avoid corrupting istanbul coverage during tests 183 | // https://github.com/istanbuljs/babel-plugin-istanbul/issues/116 184 | env !== 'test' ? require('babel-plugin-lodash') : null, 185 | ].filter(Boolean), 186 | }; 187 | }); 188 | -------------------------------------------------------------------------------- /packages/babel-preset-zillow/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "babel-preset-zillow", 3 | "version": "4.4.1", 4 | "description": "A Babel preset for transpiling JavaScript following our code conventions", 5 | "keywords": [ 6 | "babel", 7 | "es6", 8 | "es2015", 9 | "javascript" 10 | ], 11 | "author": "Daniel Stockman (https://twitter.com/@evocateur)", 12 | "homepage": "https://github.com/zillow/javascript/tree/latest/packages/babel-preset-zillow#readme", 13 | "license": "MIT", 14 | "main": "index.js", 15 | "files": [ 16 | "index.js" 17 | ], 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/zillow/javascript.git" 21 | }, 22 | "scripts": { 23 | "test": "echo \"Error: run tests from root\" && exit 1" 24 | }, 25 | "peerDependencies": { 26 | "@babel/core": "^7.0.0" 27 | }, 28 | "dependencies": { 29 | "@babel/helper-plugin-utils": "^7.10.4", 30 | "@babel/plugin-proposal-class-properties": "^7.10.4", 31 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 32 | "@babel/plugin-proposal-private-methods": "^7.16.7", 33 | "@babel/plugin-proposal-private-property-in-object": "^7.16.7", 34 | "@babel/plugin-syntax-dynamic-import": "^7.8.3", 35 | "@babel/plugin-transform-classes": "^7.10.4", 36 | "@babel/plugin-transform-computed-properties": "^7.10.4", 37 | "@babel/plugin-transform-parameters": "^7.10.5", 38 | "@babel/plugin-transform-template-literals": "^7.10.5", 39 | "@babel/preset-env": "^7.11.5", 40 | "@babel/preset-react": "^7.10.4", 41 | "babel-plugin-dynamic-import-node": "2.3.3", 42 | "babel-plugin-jsx-remove-data-test-id": "^2.1.3", 43 | "babel-plugin-lodash": "^3.3.4", 44 | "babel-plugin-styled-components": "^1.11.1", 45 | "babel-plugin-transform-react-remove-prop-types": "^0.4.24", 46 | "fast-async": "^7.0.6" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-base/.editorconfig: -------------------------------------------------------------------------------- 1 | # override root to minimize conflicts with upstream 2 | 3 | [*.js] 4 | indent_size = 2 5 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-base/.eslintrc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # root already extends zillow-base 3 | rules: 4 | # match upstream because dangling comma conflicts are _the worst_ 5 | comma-dangle: off 6 | # ditto for indent 7 | indent: [error, 2] 8 | # far too many disagreements to be useful 9 | prettier/prettier: off 10 | overrides: 11 | - files: './typescript.js' 12 | rules: 13 | prettier/prettier: [error, { tabWidth: 2 }] 14 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-base/CHANGELOG-upstream.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-zillow-base/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012 Airbnb 4 | Copyright (c) 2018 Zillow 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-base/README.md: -------------------------------------------------------------------------------- 1 | # eslint-config-zillow-base 2 | 3 | > Zillow's base ESLint config (without React plugins), following our code conventions 4 | 5 | [![npm version](https://img.shields.io/npm/v/eslint-config-zillow-base.svg)](https://www.npmjs.com/package/eslint-config-zillow-base) 6 | [![Build Status](https://travis-ci.org/zillow/javascript.svg?branch=latest)](https://travis-ci.org/zillow/javascript) 7 | 8 | ## Usage 9 | 10 | To install with all necessary `peerDependencies`, use [install-peerdeps](https://github.com/nathanhleung/install-peerdeps#usage): 11 | 12 | ```sh 13 | npx install-peerdeps --dev eslint-config-zillow-base 14 | ``` 15 | 16 | All exported configs should be added to your [ESlint configuration file](https://eslint.org/docs/user-guide/configuring#extending-configuration-files) `extends`. 17 | For example, in a JSON `.eslintrc`: 18 | 19 | ```json 20 | { 21 | "extends": "zillow-base" 22 | } 23 | ``` 24 | 25 | ### `"extends": "zillow-base"` 26 | 27 | Our default export contains all of our ESLint rules, including ECMAScript 6+ and Prettier. 28 | 29 | ### `"extends": ["zillow-base", "zillow-base/jest]` 30 | 31 | Jest-specific rules and environment added to the default export. 32 | 33 | ### `"extends": ["zillow-base", "zillow-base/mocha]` 34 | 35 | Mocha-specific rules and environment added to the default export. 36 | 37 | ### `prettier` Editor Plugin Integration 38 | 39 | Unfortunately, super-useful editor plugins like `prettier-atom` and `prettier-vscode` do not load Prettier settings from ESLint config, which is where we load our Prettier options from. To workaround this, add a `.prettierrc.js` or `prettier.config.js` file to your repo root with the following content: 40 | 41 | ```js 42 | module.exports = require('prettier-config-zillow'); 43 | ``` 44 | 45 | ## Related 46 | 47 | - [Zillow's overarching ESLint config](https://npmjs.com/eslint-config-zillow) 48 | - [Zillow's Prettier config](https://npmjs.com/prettier-config-zillow) 49 | - [Zillow's Javascript code conventions](https://github.com/zillow/javascript) 50 | 51 | ## Development 52 | 53 | 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? 54 | 55 | You can run tests (from the repo root) with `npm test`. 56 | 57 | You can make sure this module lints with itself using `npm run lint` (from the repo root). 58 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-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 | './rules/prettier', 11 | ].map(require.resolve), 12 | parserOptions: { 13 | ecmaVersion: 2018, 14 | sourceType: 'module', 15 | }, 16 | rules: { 17 | strict: 'error', 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-base/jest.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | 'jest/globals': true, 4 | }, 5 | plugins: ['jest'], 6 | 7 | rules: { 8 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/consistent-test-it.md 9 | 'jest/consistent-test-it': [ 10 | 'error', 11 | { 12 | fn: 'test', 13 | withinDescribe: 'it', 14 | }, 15 | ], 16 | 17 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/expect-expect.md 18 | 'jest/expect-expect': [ 19 | 'error', 20 | { 21 | assertFunctionNames: ['expect'], 22 | }, 23 | ], 24 | 25 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/lowercase-name.md 26 | 'jest/lowercase-name': 'off', 27 | 28 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-alias-methods.md 29 | 'jest/no-alias-methods': 'off', 30 | 31 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-commented-out-tests.md 32 | 'jest/no-commented-out-tests': 'off', 33 | 34 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-conditional-expect.md 35 | 'jest/no-conditional-expect': 'error', 36 | 37 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-deprecated-functions.md 38 | 'jest/no-deprecated-functions': 'error', 39 | 40 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-disabled-tests.md 41 | 'jest/no-disabled-tests': 'warn', 42 | 43 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-done-callback.md 44 | 'jest/no-done-callback': 'error', 45 | 46 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-duplicate-hooks.md 47 | 'jest/no-duplicate-hooks': 'off', 48 | 49 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-expect-resolves.md 50 | 'jest/no-expect-resolves': 'off', 51 | 52 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-export.md 53 | 'jest/no-export': 'error', 54 | 55 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-focused-tests.md 56 | 'jest/no-focused-tests': 'error', 57 | 58 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-hooks.md 59 | 'jest/no-hooks': 'off', 60 | 61 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-identical-title.md 62 | 'jest/no-identical-title': 'error', 63 | 64 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-if.md 65 | 'jest/no-if': 'off', 66 | 67 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-interpolation-in-snapshots.md 68 | 'jest/no-interpolation-in-snapshots': 'error', 69 | 70 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-jasmine-globals.md 71 | 'jest/no-jasmine-globals': 'error', 72 | 73 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-jest-import.md 74 | 'jest/no-jest-import': 'error', 75 | 76 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-large-snapshots.md 77 | 'jest/no-large-snapshots': ['warn', { maxSize: 50 }], 78 | 79 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-mocks-import.md 80 | 'jest/no-mocks-import': 'error', 81 | 82 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-restricted-matchers.md 83 | 'jest/no-restricted-matchers': 'off', 84 | 85 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-standalone-expect.md 86 | 'jest/no-standalone-expect': 'error', 87 | 88 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-test-prefixes.md 89 | 'jest/no-test-prefixes': 'error', 90 | 91 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-test-return-statement.md 92 | 'jest/no-test-return-statement': 'error', 93 | 94 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-truthy-falsy.md 95 | 'jest/no-truthy-falsy': 'error', 96 | 97 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-try-expect.md 98 | 'jest/no-try-expect': 'off', 99 | 100 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-called-with.md 101 | 'jest/prefer-called-with': 'off', 102 | 103 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-expect-assertions.md 104 | 'jest/prefer-expect-assertions': 'off', 105 | 106 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-hooks-on-top.md 107 | 'jest/prefer-hooks-on-top': 'error', 108 | 109 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-inline-snapshots.md 110 | // TODO: enable? 111 | 'jest/prefer-inline-snapshots': 'off', 112 | 113 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-spy-on.md 114 | // TODO: enable when bugs are fixed 115 | 'jest/prefer-spy-on': 'off', 116 | 117 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-strict-equal.md 118 | 'jest/prefer-strict-equal': 'error', 119 | 120 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-to-be-null.md 121 | 'jest/prefer-to-be-null': 'error', 122 | 123 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-to-be-undefined.md 124 | 'jest/prefer-to-be-undefined': 'error', 125 | 126 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-to-contain.md 127 | 'jest/prefer-to-contain': 'error', 128 | 129 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-to-have-length.md 130 | 'jest/prefer-to-have-length': 'error', 131 | 132 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-todo.md 133 | 'jest/prefer-todo': 'error', 134 | 135 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/require-top-level-describe.md 136 | 'jest/require-top-level-describe': 'off', 137 | 138 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/require-to-throw-message.md 139 | 'jest/require-to-throw-message': 'warn', 140 | 141 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/valid-describe.md 142 | 'jest/valid-describe': 'error', 143 | 144 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/valid-expect.md 145 | 'jest/valid-expect': 'error', 146 | 147 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/valid-title.md 148 | 'jest/valid-title': 'error', 149 | 150 | // https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/valid-expect-in-promise.md 151 | 'jest/valid-expect-in-promise': 'error', 152 | }, 153 | }; 154 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-base/mocha.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | mocha: true 4 | }, 5 | plugins: [ 6 | 'mocha', 7 | ], 8 | 9 | rules: { 10 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/handle-done-callback.md 11 | 'mocha/handle-done-callback': 'error', 12 | 13 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/max-top-level-suites.md 14 | 'mocha/max-top-level-suites': 'off', 15 | 16 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-async-describe.md 17 | 'mocha/no-async-describe': 'error', 18 | 19 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-exclusive-tests.md 20 | 'mocha/no-exclusive-tests': 'error', 21 | 22 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-exports.md 23 | 'mocha/no-exports': 'error', 24 | 25 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-global-tests.md 26 | 'mocha/no-global-tests': 'off', 27 | 28 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-hooks-for-single-case.md 29 | 'mocha/no-hooks-for-single-case': 'off', 30 | 31 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-hooks.md 32 | 'mocha/no-hooks': 'off', 33 | 34 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-identical-title.md 35 | 'mocha/no-identical-title': 'error', 36 | 37 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-mocha-arrows.md 38 | 'mocha/no-mocha-arrows': 'error', 39 | 40 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-nested-tests.md 41 | 'mocha/no-nested-tests': 'error', 42 | 43 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-pending-tests.md 44 | 'mocha/no-pending-tests': 'warn', 45 | 46 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-return-and-callback.md 47 | 'mocha/no-return-and-callback': 'error', 48 | 49 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-return-from-async.md 50 | 'mocha/no-return-from-async': 'error', 51 | 52 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-setup-in-describe.md 53 | 'mocha/no-setup-in-describe': 'off', 54 | 55 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-sibling-hooks.md 56 | 'mocha/no-sibling-hooks': 'off', 57 | 58 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-skipped-tests.md 59 | 'mocha/no-skipped-tests': 'warn', 60 | 61 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-synchronous-tests.md 62 | 'mocha/no-synchronous-tests': 'off', 63 | 64 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-top-level-hooks.md 65 | 'mocha/no-top-level-hooks': 'off', 66 | 67 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/prefer-arrow-callback.md 68 | 'mocha/prefer-arrow-callback': ['error', { 69 | allowNamedFunctions: false, 70 | allowUnboundThis: true, 71 | }], 72 | 73 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/valid-suite-description.md 74 | 'mocha/valid-suite-description': 'off', 75 | 76 | // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/valid-test-description.md 77 | 'mocha/valid-test-description': 'off', 78 | }, 79 | }; 80 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-base/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-zillow-base", 3 | "version": "4.0.0", 4 | "description": "Zillow's base ESLint config, following our code conventions", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js", 8 | "jest.js", 9 | "mocha.js", 10 | "prettier.config.js", 11 | "rules" 12 | ], 13 | "scripts": { 14 | "test": "echo \"Run tests from root\" && exit 1" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/zillow/javascript" 19 | }, 20 | "keywords": [ 21 | "eslint", 22 | "eslintconfig", 23 | "config", 24 | "zillow", 25 | "javascript", 26 | "code conventions" 27 | ], 28 | "author": "Daniel Stockman (https://twitter.com/@evocateur)", 29 | "license": "MIT", 30 | "homepage": "https://github.com/zillow/javascript/tree/latest/packages/eslint-config-zillow-base#readme", 31 | "engines": { 32 | "node": ">= 10.17" 33 | }, 34 | "peerDependencies": { 35 | "eslint": ">= 7.4.0", 36 | "eslint-plugin-import": "^2.22.0", 37 | "eslint-plugin-jest": "^24.0.2", 38 | "eslint-plugin-mocha": "^8.0.0", 39 | "eslint-plugin-prettier": "^3.1.4", 40 | "prettier": "^2.1.2" 41 | }, 42 | "dependencies": { 43 | "confusing-browser-globals": "^1.0.6", 44 | "prettier-config-zillow": "file:../prettier-config-zillow" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-base/prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('prettier-config-zillow'); 2 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-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 | // https://github.com/prettier/eslint-config-prettier#curly 27 | curly: ['error', 'all'], 28 | 29 | // require default case in switch statements 30 | 'default-case': ['error', { commentPattern: '^no default$' }], 31 | 32 | // https://eslint.org/docs/rules/default-case-last 33 | 'default-case-last': 'error', 34 | 35 | // https://eslint.org/docs/rules/default-param-last 36 | // TODO: enable when it is configurable (breaks valid redux reducers) 37 | 'default-param-last': 'off', 38 | 39 | // encourages use of dot notation whenever possible 40 | 'dot-notation': ['error', { allowKeywords: true }], 41 | 42 | // enforces consistent newlines before or after dots 43 | // https://eslint.org/docs/rules/dot-location 44 | 'dot-location': ['off'/* prettier */, 'property'], 45 | 46 | // require the use of === and !== 47 | // https://eslint.org/docs/rules/eqeqeq 48 | eqeqeq: ['error', 'always', { null: 'ignore' }], 49 | 50 | // make sure for-in loops have an if statement 51 | 'guard-for-in': 'error', 52 | 53 | // https://eslint.org/docs/rules/grouped-accessor-pairs 54 | 'grouped-accessor-pairs': 'off', 55 | 56 | // enforce a maximum number of classes per file 57 | // https://eslint.org/docs/rules/max-classes-per-file 58 | 'max-classes-per-file': ['error', 1], 59 | 60 | // disallow the use of alert, confirm, and prompt 61 | 'no-alert': 'warn', 62 | 63 | // disallow use of arguments.caller or arguments.callee 64 | 'no-caller': 'error', 65 | 66 | // disallow lexical declarations in case/default clauses 67 | // https://eslint.org/docs/rules/no-case-declarations.html 68 | 'no-case-declarations': 'error', 69 | 70 | // disallow division operators explicitly at beginning of regular expression 71 | // https://eslint.org/docs/rules/no-div-regex 72 | 'no-div-regex': 'off', 73 | 74 | // disallow else after a return in an if 75 | // https://eslint.org/docs/rules/no-else-return 76 | 'no-else-return': ['error', { allowElseIf: false }], 77 | 78 | // disallow empty functions, except for standalone funcs/arrows 79 | // https://eslint.org/docs/rules/no-empty-function 80 | 'no-empty-function': ['error', { 81 | allow: [ 82 | 'arrowFunctions', 83 | 'functions', 84 | 'methods', 85 | ] 86 | }], 87 | 88 | // disallow empty destructuring patterns 89 | // https://eslint.org/docs/rules/no-empty-pattern 90 | 'no-empty-pattern': 'error', 91 | 92 | // disallow comparisons to null without a type-checking operator 93 | 'no-eq-null': 'off', 94 | 95 | // disallow use of eval() 96 | 'no-eval': 'error', 97 | 98 | // disallow adding to native types 99 | 'no-extend-native': 'error', 100 | 101 | // disallow unnecessary function binding 102 | 'no-extra-bind': 'error', 103 | 104 | // disallow Unnecessary Labels 105 | // https://eslint.org/docs/rules/no-extra-label 106 | 'no-extra-label': 'error', 107 | 108 | // disallow fallthrough of case statements 109 | 'no-fallthrough': 'error', 110 | 111 | // disallow the use of leading or trailing decimal points in numeric literals 112 | 'no-floating-decimal': 'off'/* prettier */, 113 | 114 | // disallow reassignments of native objects or read-only globals 115 | // https://eslint.org/docs/rules/no-global-assign 116 | 'no-global-assign': ['error', { exceptions: [] }], 117 | // deprecated in favor of no-global-assign 118 | 'no-native-reassign': 'off', 119 | 120 | // disallow implicit type conversions 121 | // https://eslint.org/docs/rules/no-implicit-coercion 122 | 'no-implicit-coercion': ['off', { 123 | boolean: false, 124 | number: true, 125 | string: true, 126 | allow: [], 127 | }], 128 | 129 | // disallow var and named functions in global scope 130 | // https://eslint.org/docs/rules/no-implicit-globals 131 | 'no-implicit-globals': 'off', 132 | 133 | // disallow use of eval()-like methods 134 | 'no-implied-eval': 'error', 135 | 136 | // disallow this keywords outside of classes or class-like objects 137 | 'no-invalid-this': 'off', 138 | 139 | // disallow usage of __iterator__ property 140 | 'no-iterator': 'error', 141 | 142 | // disallow use of labels for anything other then loops and switches 143 | 'no-labels': ['error', { allowLoop: false, allowSwitch: false }], 144 | 145 | // disallow unnecessary nested blocks 146 | 'no-lone-blocks': 'error', 147 | 148 | // disallow creation of functions within loops 149 | 'no-loop-func': 'error', 150 | 151 | // disallow magic numbers 152 | // https://eslint.org/docs/rules/no-magic-numbers 153 | 'no-magic-numbers': ['off', { 154 | ignore: [], 155 | ignoreArrayIndexes: true, 156 | enforceConst: true, 157 | detectObjects: false, 158 | }], 159 | 160 | // disallow use of multiple spaces 161 | 'no-multi-spaces': ['off'/* prettier */, { 162 | ignoreEOLComments: false, 163 | }], 164 | 165 | // disallow use of multiline strings 166 | 'no-multi-str': 'error', 167 | 168 | // disallow use of new operator when not part of the assignment or comparison 169 | 'no-new': 'error', 170 | 171 | // disallow use of new operator for Function object 172 | 'no-new-func': 'error', 173 | 174 | // disallows creating new instances of String, Number, and Boolean 175 | 'no-new-wrappers': 'error', 176 | 177 | // disallow use of (old style) octal literals 178 | 'no-octal': 'error', 179 | 180 | // disallow use of octal escape sequences in string literals, such as 181 | // var foo = 'Copyright \251'; 182 | 'no-octal-escape': 'error', 183 | 184 | // disallow reassignment of function parameters 185 | // disallow parameter object manipulation except for specific exclusions 186 | // rule: https://eslint.org/docs/rules/no-param-reassign.html 187 | 'no-param-reassign': ['error', { 188 | props: true, 189 | ignorePropertyModificationsFor: [ 190 | // for reduce accumulators 191 | 'acc', 192 | 'accumulator', 193 | // for e.returnvalue 194 | 'e', 195 | // for Koa routing 196 | 'ctx', 197 | // for Express requests 198 | 'req', 199 | // for Express requests 200 | 'request', 201 | // for Express responses 202 | 'res', 203 | // for Express responses 204 | 'response', 205 | // for Angular 1 scopes 206 | '$scope', 207 | ] 208 | }], 209 | 210 | // disallow usage of __proto__ property 211 | 'no-proto': 'error', 212 | 213 | // disallow declaring the same variable more then once 214 | 'no-redeclare': 'error', 215 | 216 | // disallow certain object properties 217 | // https://eslint.org/docs/rules/no-restricted-properties 218 | 'no-restricted-properties': ['error', { 219 | object: 'arguments', 220 | property: 'callee', 221 | message: 'arguments.callee is deprecated', 222 | }, { 223 | object: 'global', 224 | property: 'isFinite', 225 | message: 'Please use Number.isFinite instead', 226 | }, { 227 | object: 'self', 228 | property: 'isFinite', 229 | message: 'Please use Number.isFinite instead', 230 | }, { 231 | object: 'window', 232 | property: 'isFinite', 233 | message: 'Please use Number.isFinite instead', 234 | }, { 235 | object: 'global', 236 | property: 'isNaN', 237 | message: 'Please use Number.isNaN instead', 238 | }, { 239 | object: 'self', 240 | property: 'isNaN', 241 | message: 'Please use Number.isNaN instead', 242 | }, { 243 | object: 'window', 244 | property: 'isNaN', 245 | message: 'Please use Number.isNaN instead', 246 | }, { 247 | property: '__defineGetter__', 248 | message: 'Please use Object.defineProperty instead.', 249 | }, { 250 | property: '__defineSetter__', 251 | message: 'Please use Object.defineProperty instead.', 252 | }], 253 | 254 | // disallow use of assignment in return statement 255 | 'no-return-assign': ['error', 'always'], 256 | 257 | // disallow redundant `return await` 258 | 'no-return-await': 'error', 259 | 260 | // disallow use of `javascript:` urls. 261 | 'no-script-url': 'error', 262 | 263 | // disallow self assignment 264 | // https://eslint.org/docs/rules/no-self-assign 265 | 'no-self-assign': ['error', { 266 | props: true, 267 | }], 268 | 269 | // disallow comparisons where both sides are exactly the same 270 | 'no-self-compare': 'error', 271 | 272 | // disallow use of comma operator 273 | 'no-sequences': 'error', 274 | 275 | // restrict what can be thrown as an exception 276 | 'no-throw-literal': 'error', 277 | 278 | // disallow unmodified conditions of loops 279 | // https://eslint.org/docs/rules/no-unmodified-loop-condition 280 | 'no-unmodified-loop-condition': 'off', 281 | 282 | // disallow usage of expressions in statement position 283 | 'no-unused-expressions': ['error', { 284 | allowShortCircuit: false, 285 | allowTernary: false, 286 | allowTaggedTemplates: false, 287 | }], 288 | 289 | // disallow unused labels 290 | // https://eslint.org/docs/rules/no-unused-labels 291 | 'no-unused-labels': 'error', 292 | 293 | // disallow unnecessary .call() and .apply() 294 | 'no-useless-call': 'off', 295 | 296 | // Disallow unnecessary catch clauses 297 | // https://eslint.org/docs/rules/no-useless-catch 298 | 'no-useless-catch': 'error', 299 | 300 | // disallow useless string concatenation 301 | // https://eslint.org/docs/rules/no-useless-concat 302 | 'no-useless-concat': 'error', 303 | 304 | // disallow unnecessary string escaping 305 | // https://eslint.org/docs/rules/no-useless-escape 306 | 'no-useless-escape': 'error', 307 | 308 | // disallow redundant return; keywords 309 | // https://eslint.org/docs/rules/no-useless-return 310 | 'no-useless-return': 'error', 311 | 312 | // disallow use of void operator 313 | // https://eslint.org/docs/rules/no-void 314 | 'no-void': 'error', 315 | 316 | // disallow usage of configurable warning terms in comments: e.g. todo 317 | 'no-warning-comments': ['off', { terms: ['todo', 'fixme', 'xxx'], location: 'start' }], 318 | 319 | // disallow use of the with statement 320 | 'no-with': 'error', 321 | 322 | // https://eslint.org/docs/rules/prefer-exponentiation-operator 323 | 'prefer-exponentiation-operator': 'error', 324 | 325 | // require using Error objects as Promise rejection reasons 326 | // https://eslint.org/docs/rules/prefer-promise-reject-errors 327 | 'prefer-promise-reject-errors': ['error', { allowEmptyReject: true }], 328 | 329 | // Suggest using named capture group in regular expression 330 | // https://eslint.org/docs/rules/prefer-named-capture-group 331 | 'prefer-named-capture-group': 'off', 332 | 333 | // https://eslint.org/docs/rules/prefer-regex-literals 334 | 'prefer-regex-literals': ['error', { disallowRedundantWrapping: true }], 335 | 336 | // require use of the second argument for parseInt() 337 | radix: 'error', 338 | 339 | // require `await` in `async function` (note: this is a horrible rule that should never be used) 340 | // https://eslint.org/docs/rules/require-await 341 | 'require-await': 'off', 342 | 343 | // Enforce the use of u flag on RegExp 344 | // https://eslint.org/docs/rules/require-unicode-regexp 345 | 'require-unicode-regexp': 'off', 346 | 347 | // requires to declare all vars on top of their containing scope 348 | 'vars-on-top': 'error', 349 | 350 | // require immediate function invocation to be wrapped in parentheses 351 | // https://eslint.org/docs/rules/wrap-iife.html 352 | 'wrap-iife': ['off'/* prettier */, 'outside', { functionPrototypeMethods: false }], 353 | 354 | // require or disallow Yoda conditions 355 | yoda: 'error' 356 | } 357 | }; 358 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-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 using an async function as a Promise executor 12 | // https://eslint.org/docs/rules/no-async-promise-executor 13 | 'no-async-promise-executor': 'error', 14 | 15 | // Disallow await inside of loops 16 | // https://eslint.org/docs/rules/no-await-in-loop 17 | 'no-await-in-loop': 'error', 18 | 19 | // Disallow comparisons to negative zero 20 | // https://eslint.org/docs/rules/no-compare-neg-zero 21 | 'no-compare-neg-zero': 'error', 22 | 23 | // disallow assignment in conditional expressions 24 | 'no-cond-assign': ['error', 'always'], 25 | 26 | // disallow use of console 27 | 'no-console': 'warn', 28 | 29 | // disallow use of constant expressions in conditions 30 | 'no-constant-condition': 'warn', 31 | 32 | // https://eslint.org/docs/rules/no-constructor-return 33 | 'no-constructor-return': 'error', 34 | 35 | // disallow control characters in regular expressions 36 | 'no-control-regex': 'error', 37 | 38 | // disallow use of debugger 39 | 'no-debugger': 'error', 40 | 41 | // disallow duplicate arguments in functions 42 | 'no-dupe-args': 'error', 43 | 44 | // https://eslint.org/docs/rules/no-dupe-else-if 45 | 'no-dupe-else-if': 'error', 46 | 47 | // disallow duplicate keys when creating object literals 48 | 'no-dupe-keys': 'error', 49 | 50 | // disallow a duplicate case label. 51 | 'no-duplicate-case': 'error', 52 | 53 | // disallow empty statements 54 | 'no-empty': 'error', 55 | 56 | // disallow the use of empty character classes in regular expressions 57 | 'no-empty-character-class': 'error', 58 | 59 | // disallow assigning to the exception in a catch block 60 | 'no-ex-assign': 'error', 61 | 62 | // disallow double-negation boolean casts in a boolean context 63 | // https://eslint.org/docs/rules/no-extra-boolean-cast 64 | 'no-extra-boolean-cast': 'error', 65 | 66 | // disallow unnecessary parentheses 67 | // https://eslint.org/docs/rules/no-extra-parens 68 | 'no-extra-parens': ['off', 'all', { 69 | conditionalAssign: true, 70 | nestedBinaryExpressions: false, 71 | returnAssign: false, 72 | // delegate to eslint-plugin-react 73 | ignoreJSX: 'all', 74 | enforceForArrowConditionals: false, 75 | }], 76 | 77 | // disallow unnecessary semicolons 78 | 'no-extra-semi': 'off'/* prettier */, 79 | 80 | // disallow overwriting functions written as function declarations 81 | 'no-func-assign': 'error', 82 | 83 | // https://eslint.org/docs/rules/no-import-assign 84 | 'no-import-assign': 'error', 85 | 86 | // disallow function or variable declarations in nested blocks 87 | 'no-inner-declarations': 'error', 88 | 89 | // disallow invalid regular expression strings in the RegExp constructor 90 | 'no-invalid-regexp': 'error', 91 | 92 | // disallow irregular whitespace outside of strings and comments 93 | 'no-irregular-whitespace': 'error', 94 | 95 | // https://eslint.org/docs/rules/no-loss-of-precision 96 | 'no-loss-of-precision': 'error', 97 | 98 | // Disallow characters which are made with multiple code points in character class syntax 99 | // https://eslint.org/docs/rules/no-misleading-character-class 100 | 'no-misleading-character-class': 'error', 101 | 102 | // disallow the use of object properties of the global object (Math and JSON) as functions 103 | 'no-obj-calls': 'error', 104 | 105 | // https://eslint.org/docs/rules/no-promise-executor-return 106 | 'no-promise-executor-return': 'error', 107 | 108 | // disallow use of Object.prototypes builtins directly 109 | // https://eslint.org/docs/rules/no-prototype-builtins 110 | 'no-prototype-builtins': 'error', 111 | 112 | // disallow multiple spaces in a regular expression literal 113 | 'no-regex-spaces': 'error', 114 | 115 | // https://eslint.org/docs/rules/no-setter-return 116 | 'no-setter-return': 'error', 117 | 118 | // disallow sparse arrays 119 | 'no-sparse-arrays': 'error', 120 | 121 | // Disallow template literal placeholder syntax in regular strings 122 | // https://eslint.org/docs/rules/no-template-curly-in-string 123 | 'no-template-curly-in-string': 'error', 124 | 125 | // Avoid code that looks like two expressions but is actually one 126 | // https://eslint.org/docs/rules/no-unexpected-multiline 127 | // https://github.com/prettier/eslint-config-prettier#no-unexpected-multiline 128 | 'no-unexpected-multiline': 'warn'/* prettier */, 129 | 130 | // disallow unreachable statements after a return, throw, continue, or break statement 131 | 'no-unreachable': 'error', 132 | 133 | // https://eslint.org/docs/rules/no-unreachable-loop 134 | 'no-unreachable-loop': 'error', 135 | 136 | // disallow return/throw/break/continue inside finally blocks 137 | // https://eslint.org/docs/rules/no-unsafe-finally 138 | 'no-unsafe-finally': 'error', 139 | 140 | // disallow negating the left operand of relational operators 141 | // https://eslint.org/docs/rules/no-unsafe-negation 142 | 'no-unsafe-negation': 'error', 143 | 144 | // https://eslint.org/docs/rules/no-useless-backreference 145 | 'no-useless-backreference': 'error', 146 | 147 | // disallow negation of the left operand of an in expression 148 | // deprecated in favor of no-unsafe-negation 149 | 'no-negated-in-lhs': 'off', 150 | 151 | // Disallow assignments that can lead to race conditions due to usage of await or yield 152 | // https://eslint.org/docs/rules/require-atomic-updates 153 | // NOTE: not enabled because it is very buggy 154 | 'require-atomic-updates': 'off', 155 | 156 | // disallow comparisons with the value NaN 157 | 'use-isnan': 'error', 158 | 159 | // ensure JSDoc comments are valid 160 | // https://eslint.org/docs/rules/valid-jsdoc 161 | 'valid-jsdoc': 'off', 162 | 163 | // ensure that the results of typeof are compared against a valid string 164 | // https://eslint.org/docs/rules/valid-typeof 165 | 'valid-typeof': ['error', { requireStringLiterals: true }], 166 | } 167 | }; 168 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-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': ['off'/* prettier */, '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': ['off'/* prettier */, { 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': ['off'/* prettier */, { 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 | // https://github.com/prettier/eslint-config-prettier#no-confusing-arrow 46 | 'no-confusing-arrow': ['warn'/* prettier */, { 47 | allowParens: false, 48 | }], 49 | 50 | // disallow modifying variables that are declared using const 51 | 'no-const-assign': 'error', 52 | 53 | // disallow duplicate class members 54 | // https://eslint.org/docs/rules/no-dupe-class-members 55 | 'no-dupe-class-members': 'error', 56 | 57 | // disallow importing from the same path more than once 58 | // https://eslint.org/docs/rules/no-duplicate-imports 59 | // replaced by https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md 60 | 'no-duplicate-imports': 'off', 61 | 62 | // disallow symbol constructor 63 | // https://eslint.org/docs/rules/no-new-symbol 64 | 'no-new-symbol': 'error', 65 | 66 | // Disallow specified names in exports 67 | // https://eslint.org/docs/rules/no-restricted-exports 68 | 'no-restricted-exports': ['error', { 69 | restrictedNamedExports: [ 70 | // use `export default` to provide a default export 71 | 'default', 72 | // this will cause tons of confusion when your module is dynamically `import()`ed 73 | 'then', 74 | ], 75 | }], 76 | 77 | // disallow specific imports 78 | // https://eslint.org/docs/rules/no-restricted-imports 79 | 'no-restricted-imports': ['off', { 80 | paths: [], 81 | patterns: [] 82 | }], 83 | 84 | // disallow to use this/super before super() calling in constructors. 85 | // https://eslint.org/docs/rules/no-this-before-super 86 | 'no-this-before-super': 'error', 87 | 88 | // disallow useless computed property keys 89 | // https://eslint.org/docs/rules/no-useless-computed-key 90 | 'no-useless-computed-key': 'error', 91 | 92 | // disallow unnecessary constructor 93 | // https://eslint.org/docs/rules/no-useless-constructor 94 | 'no-useless-constructor': 'error', 95 | 96 | // disallow renaming import, export, and destructured assignments to the same name 97 | // https://eslint.org/docs/rules/no-useless-rename 98 | 'no-useless-rename': ['error', { 99 | ignoreDestructuring: false, 100 | ignoreImport: false, 101 | ignoreExport: false, 102 | }], 103 | 104 | // require let or const instead of var 105 | 'no-var': 'error', 106 | 107 | // require method and property shorthand syntax for object literals 108 | // https://eslint.org/docs/rules/object-shorthand 109 | 'object-shorthand': ['error', 'always', { 110 | ignoreConstructors: false, 111 | avoidQuotes: true, 112 | }], 113 | 114 | // suggest using arrow functions as callbacks 115 | 'prefer-arrow-callback': ['error', { 116 | allowNamedFunctions: false, 117 | allowUnboundThis: true, 118 | }], 119 | 120 | // suggest using of const declaration for variables that are never modified after declared 121 | 'prefer-const': ['error', { 122 | destructuring: 'any', 123 | ignoreReadBeforeAssign: true, 124 | }], 125 | 126 | // Prefer destructuring from arrays and objects 127 | // https://eslint.org/docs/rules/prefer-destructuring 128 | 'prefer-destructuring': ['warn', { 129 | VariableDeclarator: { 130 | array: false, 131 | object: true, 132 | }, 133 | AssignmentExpression: { 134 | array: true, 135 | object: true, 136 | }, 137 | }, { 138 | enforceForRenamedProperties: false, 139 | }], 140 | 141 | // disallow parseInt() in favor of binary, octal, and hexadecimal literals 142 | // https://eslint.org/docs/rules/prefer-numeric-literals 143 | 'prefer-numeric-literals': 'error', 144 | 145 | // suggest using Reflect methods where applicable 146 | // https://eslint.org/docs/rules/prefer-reflect 147 | 'prefer-reflect': 'off', 148 | 149 | // use rest parameters instead of arguments 150 | // https://eslint.org/docs/rules/prefer-rest-params 151 | 'prefer-rest-params': 'error', 152 | 153 | // suggest using the spread operator instead of .apply() 154 | // https://eslint.org/docs/rules/prefer-spread 155 | 'prefer-spread': 'error', 156 | 157 | // suggest using template literals instead of string concatenation 158 | // https://eslint.org/docs/rules/prefer-template 159 | 'prefer-template': 'error', 160 | 161 | // disallow generator functions that do not have yield 162 | // https://eslint.org/docs/rules/require-yield 163 | 'require-yield': 'error', 164 | 165 | // enforce spacing between object rest-spread 166 | // https://eslint.org/docs/rules/rest-spread-spacing 167 | 'rest-spread-spacing': ['off'/* prettier */, 'never'], 168 | 169 | // import sorting 170 | // https://eslint.org/docs/rules/sort-imports 171 | 'sort-imports': ['off', { 172 | ignoreCase: false, 173 | ignoreDeclarationSort: false, 174 | ignoreMemberSort: false, 175 | memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'], 176 | }], 177 | 178 | // require a Symbol description 179 | // https://eslint.org/docs/rules/symbol-description 180 | 'symbol-description': 'error', 181 | 182 | // enforce usage of spacing in template strings 183 | // https://eslint.org/docs/rules/template-curly-spacing 184 | 'template-curly-spacing': 'off'/* prettier */, 185 | 186 | // enforce spacing around the * in yield* expressions 187 | // https://eslint.org/docs/rules/yield-star-spacing 188 | 'yield-star-spacing': ['off'/* prettier */, 'after'] 189 | } 190 | }; 191 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-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: [ 17 | // first three must match react's extensions list 18 | '.js', 19 | '.jsx', 20 | '.json', 21 | // because eslint merges arrays, whoops! 22 | '.ts', 23 | '.tsx', 24 | '.d.ts', 25 | '.cjs', 26 | '.mjs', 27 | ] 28 | } 29 | }, 30 | 'import/parsers': { 31 | '@typescript-eslint/parser': [ 32 | '.ts', 33 | '.tsx', 34 | '.d.ts', 35 | ], 36 | }, 37 | 'import/extensions': [ 38 | '.ts', 39 | '.tsx', 40 | '.d.ts', 41 | '.cjs', 42 | '.js', 43 | '.mjs', 44 | '.jsx', 45 | ], 46 | 'import/external-module-folders': [ 47 | 'node_modules', 48 | 'node_modules/@types', 49 | ], 50 | 'import/core-modules': [ 51 | ], 52 | 'import/ignore': [ 53 | 'node_modules', 54 | '\\.(coffee|scss|css|less|hbs|svg|json)$', 55 | ], 56 | }, 57 | 58 | rules: { 59 | // Static analysis: 60 | 61 | // ensure imports point to files/modules that can be resolved 62 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unresolved.md 63 | 'import/no-unresolved': ['error', { commonjs: true, caseSensitive: true }], 64 | 65 | // ensure named imports coupled with named exports 66 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/named.md#when-not-to-use-it 67 | 'import/named': 'error', 68 | 69 | // ensure default import coupled with default export 70 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/default.md#when-not-to-use-it 71 | 'import/default': 'off', 72 | 73 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/namespace.md 74 | 'import/namespace': 'off', 75 | 76 | // Helpful warnings: 77 | 78 | // disallow invalid exports, e.g. multiple defaults 79 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/export.md 80 | 'import/export': 'error', 81 | 82 | // do not allow a default import name to match a named export 83 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-as-default.md 84 | 'import/no-named-as-default': 'error', 85 | 86 | // warn on accessing default export property names that are also named exports 87 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-as-default-member.md 88 | 'import/no-named-as-default-member': 'error', 89 | 90 | // disallow use of jsdoc-marked-deprecated imports 91 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-deprecated.md 92 | 'import/no-deprecated': 'off', 93 | 94 | // Forbid the use of extraneous packages 95 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-extraneous-dependencies.md 96 | // paths are treated both as absolute paths, and relative to process.cwd() 97 | 'import/no-extraneous-dependencies': ['error', { 98 | devDependencies: [ 99 | // common npm patterns (tape, mocha, etc) 100 | 'test/**', 101 | 'tests/**', 102 | 'spec/**', 103 | // jest patterns 104 | '**/__tests__/**', 105 | '**/__mocks__/**', 106 | // repos with a single test file 107 | 'test.{js,jsx}', 108 | // repos with multiple top-level test files 109 | 'test-*.{js,jsx}', 110 | // tests where the extension denotes that it is a test 111 | '**/*.{test,spec}.{js,jsx}', 112 | // config files 113 | '**/jest.config.js', 114 | '**/jest.setup.js', 115 | '**/webpack.config.js', 116 | '**/webpack.config.*.js', 117 | '**/rollup.config.js', 118 | '**/rollup.config.*.js', 119 | '**/gulpfile.js', 120 | '**/gulpfile.*.js', 121 | '**/Gruntfile{,.js}', 122 | '**/protractor.conf.js', 123 | '**/protractor.conf.*.js', 124 | ], 125 | optionalDependencies: false, 126 | }], 127 | 128 | // Forbid mutable exports 129 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-mutable-exports.md 130 | 'import/no-mutable-exports': 'error', 131 | 132 | // Module systems: 133 | 134 | // disallow require() 135 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-commonjs.md 136 | 'import/no-commonjs': 'off', 137 | 138 | // disallow AMD require/define 139 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-amd.md 140 | 'import/no-amd': 'error', 141 | 142 | // No Node.js builtin modules 143 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-nodejs-modules.md 144 | // TODO: enable? 145 | 'import/no-nodejs-modules': 'off', 146 | 147 | // Style guide: 148 | 149 | // disallow non-import statements appearing before import statements 150 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/first.md 151 | 'import/first': ['error', 'absolute-first'], 152 | 153 | // disallow non-import statements appearing before import statements 154 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/imports-first.md 155 | // deprecated: use `import/first` 156 | 'import/imports-first': 'off', 157 | 158 | // disallow duplicate imports 159 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md 160 | 'import/no-duplicates': 'error', 161 | 162 | // disallow namespace imports 163 | // TODO: enable? 164 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-namespace.md 165 | 'import/no-namespace': 'off', 166 | 167 | // Ensure consistent use of file extension within the import path 168 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md 169 | 'import/extensions': ['error', 'ignorePackages', { 170 | js: 'never', 171 | ts: 'never', 172 | mjs: 'never', 173 | cjs: 'never', 174 | jsx: 'never', 175 | tsx: 'never', 176 | }], 177 | 178 | // Enforce a convention in module import order 179 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/order.md 180 | // TODO: enable? 181 | 'import/order': ['off', { 182 | groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], 183 | 'newlines-between': 'never', 184 | }], 185 | 186 | // Require a newline after the last import/require in a group 187 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/newline-after-import.md 188 | 'import/newline-after-import': 'error', 189 | 190 | // Require modules with a single export to use a default export 191 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/prefer-default-export.md 192 | 'import/prefer-default-export': 'off', 193 | 194 | // Restrict which files can be imported in a given folder 195 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-restricted-paths.md 196 | 'import/no-restricted-paths': 'off', 197 | 198 | // Forbid modules to have too many dependencies 199 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/max-dependencies.md 200 | 'import/max-dependencies': ['off', { max: 10 }], 201 | 202 | // Forbid import of modules using absolute paths 203 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-absolute-path.md 204 | 'import/no-absolute-path': 'error', 205 | 206 | // Forbid require() calls with expressions 207 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-dynamic-require.md 208 | 'import/no-dynamic-require': 'error', 209 | 210 | // prevent importing the submodules of other modules 211 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-internal-modules.md 212 | 'import/no-internal-modules': ['off', { 213 | allow: [], 214 | }], 215 | 216 | // Warn if a module could be mistakenly parsed as a script by a consumer 217 | // leveraging Unambiguous JavaScript Grammar 218 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/unambiguous.md 219 | // this should not be enabled until this proposal has at least been *presented* to TC39. 220 | // At the moment, it's not a thing. 221 | 'import/unambiguous': 'off', 222 | 223 | // Forbid Webpack loader syntax in imports 224 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-webpack-loader-syntax.md 225 | 'import/no-webpack-loader-syntax': 'error', 226 | 227 | // Prevent unassigned imports 228 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unassigned-import.md 229 | // importing for side effects is perfectly acceptable, if you need side effects. 230 | 'import/no-unassigned-import': 'off', 231 | 232 | // Prevent importing the default as if it were named 233 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-default.md 234 | 'import/no-named-default': 'error', 235 | 236 | // Reports if a module's default export is unnamed 237 | // https://github.com/benmosher/eslint-plugin-import/blob/d9b712ac7fd1fddc391f7b234827925c160d956f/docs/rules/no-anonymous-default-export.md 238 | 'import/no-anonymous-default-export': ['off', { 239 | allowArray: false, 240 | allowArrowFunction: false, 241 | allowAnonymousClass: false, 242 | allowAnonymousFunction: false, 243 | allowLiteral: false, 244 | allowObject: false, 245 | }], 246 | 247 | // This rule enforces that all exports are declared at the bottom of the file. 248 | // https://github.com/benmosher/eslint-plugin-import/blob/98acd6afd04dcb6920b81330114e146dc8532ea4/docs/rules/exports-last.md 249 | // TODO: enable? 250 | 'import/exports-last': 'off', 251 | 252 | // Reports when named exports are not grouped together in a single export declaration 253 | // or when multiple assignments to CommonJS module.exports or exports object are present 254 | // in a single file. 255 | // https://github.com/benmosher/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/group-exports.md 256 | 'import/group-exports': 'off', 257 | 258 | // forbid default exports. this is a terrible rule, do not use it. 259 | // https://github.com/benmosher/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/no-default-export.md 260 | 'import/no-default-export': 'off', 261 | 262 | // forbid named exports. this is a terrible rule, do not use it. 263 | // https://github.com/benmosher/eslint-plugin-import/blob/f04b7b6b0368f794f8dc0779d06f057aef4b8ff5/docs/rules/no-named-export.md 264 | 'import/no-named-export': 'off', 265 | 266 | // Forbid a module from importing itself 267 | // https://github.com/benmosher/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/no-self-import.md 268 | 'import/no-self-import': 'error', 269 | 270 | // Ensures that there are no useless path segments 271 | // https://github.com/benmosher/eslint-plugin-import/blob/ebafcbf59ec9f653b2ac2a0156ca3bcba0a7cf57/docs/rules/no-useless-path-segments.md 272 | 'import/no-useless-path-segments': 'error', 273 | 274 | // Ensures that there is no resolvable path back to this module via its dependencies. 275 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-cycle.md 276 | // TODO: enable? (LOTS of problems right now) 277 | 'import/no-cycle': ['off', { maxDepth: 10 }], 278 | // purportedly claims to honor { commonjs: true, caseSensitive: true }, but it fails instead 279 | 280 | // dynamic imports require a leading comment with a webpackChunkName 281 | // https://github.com/benmosher/eslint-plugin-import/blob/ebafcbf59ec9f653b2ac2a0156ca3bcba0a7cf57/docs/rules/dynamic-import-chunkname.md 282 | 'import/dynamic-import-chunkname': ['off', { 283 | importFunctions: [], 284 | webpackChunknameFormat: '[0-9a-zA-Z-_/.]+', 285 | }], 286 | 287 | // Use this rule to prevent imports to folders in relative parent paths. 288 | // https://github.com/benmosher/eslint-plugin-import/blob/c34f14f67f077acd5a61b3da9c0b0de298d20059/docs/rules/no-relative-parent-imports.md 289 | 'import/no-relative-parent-imports': 'off', 290 | 291 | // Ensure all modules are consumed via imports (dynamic import() unsupported) 292 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unused-modules.md 293 | // TODO: enable? (exceedingly problematic right now) 294 | 'import/no-unused-modules': 'off', 295 | }, 296 | }; 297 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-base/rules/node.js: -------------------------------------------------------------------------------- 1 | // FIXME: Remove when eslint v8.x supported: https://github.com/eslint/eslint/pull/12898 2 | module.exports = { 3 | env: { 4 | node: true 5 | }, 6 | 7 | rules: { 8 | // enforce return after a callback 9 | 'callback-return': 'off', 10 | 11 | // require all requires be top-level 12 | // https://eslint.org/docs/rules/global-require 13 | 'global-require': 'error', 14 | 15 | // enforces error handling in callbacks (node environment) 16 | 'handle-callback-err': 'off', 17 | 18 | // disallow use of the Buffer() constructor 19 | // https://eslint.org/docs/rules/no-buffer-constructor 20 | 'no-buffer-constructor': 'error', 21 | 22 | // disallow mixing regular variable and require declarations 23 | 'no-mixed-requires': ['off', false], 24 | 25 | // disallow use of new operator with the require function 26 | 'no-new-require': 'error', 27 | 28 | // disallow string concatenation with __dirname and __filename 29 | // https://eslint.org/docs/rules/no-path-concat 30 | 'no-path-concat': 'error', 31 | 32 | // disallow use of process.env 33 | 'no-process-env': 'off', 34 | 35 | // disallow process.exit() 36 | 'no-process-exit': 'off', 37 | 38 | // restrict usage of specified node modules 39 | 'no-restricted-modules': 'off', 40 | 41 | // disallow use of synchronous methods (off by default) 42 | 'no-sync': 'off', 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-base/rules/prettier.js: -------------------------------------------------------------------------------- 1 | const config = require('../prettier.config'); 2 | 3 | module.exports = { 4 | plugins: [ 5 | 'prettier' 6 | ], 7 | 8 | rules: { 9 | 'prettier/prettier': ['error', config, { 10 | usePrettierrc: false 11 | }] 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-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-zillow-base/rules/variables.js: -------------------------------------------------------------------------------- 1 | const confusingBrwoserGlobals = require('confusing-browser-globals'); 2 | 3 | module.exports = { 4 | rules: { 5 | // enforce or disallow variable initializations at definition 6 | 'init-declarations': 'off', 7 | 8 | // disallow the catch clause parameter name being the same as a variable in the outer scope 9 | 'no-catch-shadow': 'off', 10 | 11 | // disallow deletion of variables 12 | 'no-delete-var': 'error', 13 | 14 | // disallow labels that share a name with a variable 15 | // https://eslint.org/docs/rules/no-label-var 16 | 'no-label-var': 'error', 17 | 18 | // disallow specific globals 19 | 'no-restricted-globals': ['error', 'isFinite', 'isNaN'].concat(confusingBrwoserGlobals), 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 | // https://eslint.org/docs/rules/no-unused-vars 40 | 'no-unused-vars': ['error', { vars: 'all', args: 'after-used', ignoreRestSiblings: true }], 41 | 42 | // disallow use of variables before they are defined 43 | // https://eslint.org/docs/rules/no-use-before-define 44 | 'no-use-before-define': ['error', { functions: false, classes: true, variables: true }], 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-base/test/requires.js: -------------------------------------------------------------------------------- 1 | /* eslint 2 | strict: 0, 3 | global-require: 0, 4 | */ 5 | 6 | 'use strict'; 7 | 8 | test('all entry points parse', () => { 9 | expect(() => require('..')).not.toThrow(); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-base/test/test-base.js: -------------------------------------------------------------------------------- 1 | /* eslint function-paren-newline: error */ 2 | 3 | import fs from 'fs'; 4 | import path from 'path'; 5 | 6 | import index from '..'; 7 | 8 | // object spread is to test parsing 9 | const files = { ...{ index } }; 10 | 11 | fs.readdirSync(path.join(__dirname, '../rules')).forEach((name) => { 12 | // eslint-disable-next-line import/no-dynamic-require 13 | files[name] = require(`../rules/${name}`); // eslint-disable-line global-require 14 | }); 15 | 16 | Object.keys(files).forEach(( // eslint-disable-line function-paren-newline 17 | // trailing function comma is to test parsing 18 | name, 19 | ) => { // eslint-disable-line function-paren-newline 20 | const config = files[name]; 21 | 22 | test(`${name}: does not reference react`, () => { 23 | expect.assertions(2); 24 | 25 | // scan plugins for react and fail if it is found 26 | const hasReactPlugin = Object.prototype.hasOwnProperty.call(config, 'plugins') 27 | && config.plugins.indexOf('react') !== -1; 28 | expect(hasReactPlugin).toBe(false); 29 | 30 | // scan rules for react/ and fail if any exist 31 | const reactRuleIds = Object.keys(config.rules) 32 | .filter(ruleId => ruleId.indexOf('react/') === 0); 33 | expect(reactRuleIds).toHaveLength(0); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-typescript/.editorconfig: -------------------------------------------------------------------------------- 1 | # override root to minimize conflicts with upstream 2 | 3 | [*.js] 4 | indent_size = 2 5 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-typescript/.eslintrc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | rules: 3 | prettier/prettier: [error, { tabWidth: 2 }] 4 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-typescript/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [1.0.0](https://github.com/zillow/javascript/compare/eslint-config-zillow-typescript@1.0.0-alpha.3...eslint-config-zillow-typescript@1.0.0) (2020-09-30) 7 | 8 | **Note:** Version bump only for package eslint-config-zillow-typescript 9 | 10 | 11 | 12 | 13 | 14 | # [1.0.0-alpha.3](https://github.com/zillow/javascript/compare/eslint-config-zillow-typescript@1.0.0-alpha.2...eslint-config-zillow-typescript@1.0.0-alpha.3) (2020-09-29) 15 | 16 | 17 | ### Bug Fixes 18 | 19 | * **typescript:** Restore no-shadow builtinGlobals default ([06d4337](https://github.com/zillow/javascript/commit/06d4337227a754dc636a6b38100b9691c89c5848)) 20 | * **typescript:** Turn off prefer-readonly-parameter-types, too many bugs for too little benefit ([da2306e](https://github.com/zillow/javascript/commit/da2306e9f25bd00c4326d562f7a866264be8f514)) 21 | 22 | 23 | 24 | 25 | 26 | # [1.0.0-alpha.2](https://github.com/zillow/javascript/compare/eslint-config-zillow-typescript@1.0.0-alpha.1...eslint-config-zillow-typescript@1.0.0-alpha.2) (2020-09-29) 27 | 28 | 29 | ### Bug Fixes 30 | 31 | * **rules:** Turn off default-param-last until it is configurable ([c05d872](https://github.com/zillow/javascript/commit/c05d872f553c368b571f9babd82764a21189019a)) 32 | * **typescript:** Enable auto-fix for ban-types 'object' case ([bb70eb9](https://github.com/zillow/javascript/commit/bb70eb9d014a6c276e0446f6b09055023dc065e3)) 33 | * **typescript:** Extend no-shadow allow list to accommodate common patterns ([5e4013e](https://github.com/zillow/javascript/commit/5e4013e9697f2d28229bf964894941903f003d28)) 34 | * **typescript:** Flesh out no-empty-function allow list ([1d9438a](https://github.com/zillow/javascript/commit/1d9438acdef5e61dee9c78c16a7690654ab8668a)) 35 | * **typescript:** Turn off explicit-module-boundary-types, too much noise ([25ac226](https://github.com/zillow/javascript/commit/25ac226ffc2af781089f78f12fabb47255b0f308)) 36 | * **typescript:** Turn off no-implicit-any-catch, too much noise ([4e1ac62](https://github.com/zillow/javascript/commit/4e1ac62d1219b7380f984d429385e5e6134996b8)) 37 | * **typescript:** Turn off react/prop-types in TSX files ([6249318](https://github.com/zillow/javascript/commit/6249318bdc5b0250161d7a34070b4a104b7657c5)) 38 | 39 | 40 | ### Features 41 | 42 | * **peer:** eslint >= 7.4.0 ([828ce5a](https://github.com/zillow/javascript/commit/828ce5a7fa03d72e84976f679d8c582a77a4b987)) 43 | 44 | 45 | ### BREAKING CHANGES 46 | 47 | * **peer:** The minimum peer version of eslint is now 7.4.0. 48 | 49 | 50 | 51 | 52 | 53 | # [1.0.0-alpha.1](https://github.com/zillow/javascript/compare/eslint-config-zillow-typescript@1.0.0-alpha.0...eslint-config-zillow-typescript@1.0.0-alpha.1) (2020-09-28) 54 | 55 | **Note:** Version bump only for package eslint-config-zillow-typescript 56 | 57 | 58 | 59 | 60 | 61 | # 1.0.0-alpha.0 (2020-09-25) 62 | 63 | 64 | ### Features 65 | 66 | * Add module eslint-config-zillow-typescript ([cfff176](https://github.com/zillow/javascript/commit/cfff1766796a08d68f4c676f26c603fa55145662)) 67 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-typescript/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Zillow 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-zillow-typescript/README.md: -------------------------------------------------------------------------------- 1 | # eslint-config-zillow-typescript 2 | 3 | > Zillow's ESLint config for TypeScript, following our code conventions 4 | 5 | [![npm version](https://img.shields.io/npm/v/eslint-config-zillow-typescript.svg)](https://www.npmjs.com/package/eslint-config-zillow-typescript) 6 | [![Build Status](https://travis-ci.org/zillow/javascript.svg?branch=latest)](https://travis-ci.org/zillow/javascript) 7 | 8 | ## Usage 9 | 10 | Note: Unlike other Zillow eslint config plugins, this module is designed to be used in tandem with another extended config such as [eslint-config-zillow](https://npmjs.com/eslint-config-zillow). 11 | 12 | To install with all necessary `peerDependencies`, use [install-peerdeps](https://github.com/nathanhleung/install-peerdeps#usage): 13 | 14 | ```sh 15 | npx install-peerdeps --dev eslint-config-zillow eslint-config-zillow-typescript 16 | ``` 17 | 18 | All exported configs should be added to your [ESlint configuration file](https://eslint.org/docs/user-guide/configuring#extending-configuration-files) `extends`. 19 | For example, in a JSON `.eslintrc`: 20 | 21 | ```json 22 | { 23 | "extends": ["zillow", "zillow-typescript"] 24 | } 25 | ``` 26 | 27 | ### Project Config 28 | 29 | All flavors of this config expect your `tsconfig.json` to be in the current working directory (relative to your eslint config), which is extremely common. If it is elsewhere (say, a monorepo leaf), you will need to override various [`parserOptions`](https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/TYPED_LINTING.md): 30 | 31 | ```js 32 | // .eslintrc.js 33 | module.exports = { 34 | extends: ['zillow', 'zillow-typescript'], 35 | parserOptions: { 36 | tsconfigRootDir: __dirname, 37 | project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'], 38 | }, 39 | }; 40 | ``` 41 | 42 | ### `prettier` Editor Plugin Integration 43 | 44 | Unfortunately, super-useful editor plugins like `prettier-atom` and `prettier-vscode` do not load Prettier settings from ESLint config, which is where we load our Prettier options from. To workaround this, add a `.prettierrc.js` or `prettier.config.js` file to your repo root with the following content: 45 | 46 | ```js 47 | module.exports = require('prettier-config-zillow'); 48 | ``` 49 | 50 | ## Related 51 | 52 | - [Zillow's overarching ESLint config](https://npmjs.com/eslint-config-zillow) 53 | - [Zillow's Prettier config](https://npmjs.com/prettier-config-zillow) 54 | - [Zillow's Javascript code conventions](https://github.com/zillow/javascript) 55 | 56 | ## Development 57 | 58 | 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? 59 | 60 | You can run tests (from the repo root) with `npm test`. 61 | 62 | You can make sure this module lints with itself using `npm run lint` (from the repo root). 63 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-typescript/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | './rules/prettier', 4 | './rules/eslint-recommended', 5 | './rules/recommended', 6 | './rules/recommended-requiring-type-checking', 7 | './rules/all-remaining', 8 | './rules/other-plugin-overrides', 9 | ].map(require.resolve), 10 | 11 | parser: require.resolve('@typescript-eslint/parser'), 12 | 13 | parserOptions: { 14 | ecmaVersion: 2018, 15 | sourceType: 'module', 16 | project: ['./tsconfig.json'], 17 | }, 18 | 19 | plugins: ['@typescript-eslint'], 20 | 21 | rules: {}, 22 | }; 23 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-zillow-typescript", 3 | "version": "1.0.0", 4 | "description": "Zillow's ESLint config for TypeScript, following our code conventions", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js", 8 | "prettier.config.js", 9 | "rules" 10 | ], 11 | "scripts": { 12 | "test": "echo \"Run tests from root\" && exit 1" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/zillow/javascript" 17 | }, 18 | "keywords": [ 19 | "eslint", 20 | "eslintconfig", 21 | "config", 22 | "zillow", 23 | "typescript", 24 | "code conventions" 25 | ], 26 | "author": "Daniel Stockman (https://twitter.com/@evocateur)", 27 | "license": "MIT", 28 | "homepage": "https://github.com/zillow/javascript/tree/latest/packages/eslint-config-zillow-typescript#readme", 29 | "engines": { 30 | "node": ">= 10.17" 31 | }, 32 | "peerDependencies": { 33 | "@typescript-eslint/eslint-plugin": "^4.2.0", 34 | "@typescript-eslint/parser": "^4.2.0", 35 | "eslint": ">=7.4.0", 36 | "eslint-plugin-prettier": "^3.1.4", 37 | "prettier": "^2.1.2", 38 | "typescript": "^4.0.3" 39 | }, 40 | "dependencies": { 41 | "prettier-config-zillow": "file:../prettier-config-zillow" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-typescript/prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('prettier-config-zillow'); 2 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-typescript/rules/eslint-recommended.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Overrides of eslint-recommended (alphabetized) 3 | * @see https://github.com/typescript-eslint/typescript-eslint/blob/39c45f3/packages/eslint-plugin/src/configs/eslint-recommended.ts#L11-L31 4 | */ 5 | 6 | module.exports = { 7 | rules: { 8 | // ts(2335) & ts(2377) 9 | 'constructor-super': 'off', 10 | 11 | // ts(2378) 12 | 'getter-return': 'off', 13 | 14 | // ts(2588) 15 | 'no-const-assign': 'off', 16 | 17 | // ts(2300) 18 | 'no-dupe-args': 'off', 19 | 20 | // ts(2393) & ts(2300) 21 | 'no-dupe-class-members': 'off', 22 | 23 | // ts(1117) 24 | 'no-dupe-keys': 'off', 25 | 26 | // ts(2539) 27 | 'no-func-assign': 'off', 28 | 29 | // ts(2539) & ts(2540) 30 | 'no-import-assign': 'off', 31 | 32 | // ts(2588) 33 | 'no-new-symbol': 'off', 34 | 35 | // ts(2349) 36 | 'no-obj-calls': 'off', 37 | 38 | // ts(2451) 39 | 'no-redeclare': 'off', 40 | 41 | // ts(2408) 42 | 'no-setter-return': 'off', 43 | 44 | // ts(2376) 45 | 'no-this-before-super': 'off', 46 | 47 | // ts(2304) 48 | 'no-undef': 'off', 49 | 50 | // ts(7027) 51 | 'no-unreachable': 'off', 52 | 53 | // ts(2365) & ts(2360) & ts(2358) 54 | 'no-unsafe-negation': 'off', 55 | 56 | // ts transpiles let/const to var, so no need for vars any more 57 | 'no-var': 'error', 58 | 59 | // ts provides better types with const 60 | 'prefer-const': 'error', 61 | 62 | // ts provides better types with rest args over arguments 63 | 'prefer-rest-params': 'error', 64 | 65 | // ts transpiles spread to apply, so no need for manual apply 66 | 'prefer-spread': 'error', 67 | 68 | // ts(2367) 69 | 'valid-typeof': 'off', 70 | }, 71 | }; 72 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-typescript/rules/other-plugin-overrides.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom overrides 3 | */ 4 | 5 | module.exports = { 6 | rules: { 7 | // https://eslint.org/docs/rules/spaced-comment 8 | 'spaced-comment': [ 9 | 'error', 10 | 'always', 11 | { 12 | line: { 13 | // allow triple-slashed directives 14 | markers: ['/'], 15 | }, 16 | }, 17 | ], 18 | 19 | // pretty disastrous with type imports and whatnot 20 | // TODO: maybe fix? 21 | 'import/first': 'off', 22 | 23 | /** 24 | * Root Plugin Overrides 25 | */ 26 | 27 | // TSX is JSX, too! 28 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-filename-extension.md 29 | 'react/jsx-filename-extension': ['error', { extensions: ['.js', '.jsx', '.tsx'] }], 30 | 31 | // TypeScript > prop-types 32 | 'react/prop-types': 'off', 33 | 34 | // typescript parser doesn't play nicely with react plugin 35 | // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md 36 | 'react/sort-comp': 'off', 37 | }, 38 | }; 39 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-typescript/rules/prettier.js: -------------------------------------------------------------------------------- 1 | const prettierConfig = require('../prettier.config'); 2 | 3 | const amendedPrettierConfig = { 4 | ...prettierConfig, 5 | ...prettierConfig.overrides[2].options, 6 | overrides: undefined, 7 | }; 8 | 9 | module.exports = { 10 | plugins: ['prettier'], 11 | 12 | rules: { 13 | /** 14 | * Override prettier rules because prettier overrides aren't eslint overrides 15 | */ 16 | 'prettier/prettier': [ 17 | 'error', 18 | amendedPrettierConfig, 19 | { 20 | usePrettierrc: false, 21 | }, 22 | ], 23 | 24 | /** 25 | * Prettier overrides 26 | * @see https://github.com/prettier/eslint-config-prettier/blob/7cad28d0/%40typescript-eslint.js#L5-L17 27 | */ 28 | '@typescript-eslint/quotes': 'off', 29 | '@typescript-eslint/brace-style': 'off', 30 | '@typescript-eslint/comma-spacing': 'off', 31 | '@typescript-eslint/func-call-spacing': 'off', 32 | '@typescript-eslint/indent': 'off', 33 | '@typescript-eslint/keyword-spacing': 'off', 34 | '@typescript-eslint/member-delimiter-style': 'off', 35 | '@typescript-eslint/no-extra-parens': 'off', 36 | '@typescript-eslint/no-extra-semi': 'off', 37 | '@typescript-eslint/semi': 'off', 38 | '@typescript-eslint/space-before-function-paren': 'off', 39 | '@typescript-eslint/type-annotation-spacing': 'off', 40 | 41 | // v4.0+ 42 | '@typescript-eslint/comma-dangle': 'off', 43 | }, 44 | }; 45 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-typescript/rules/recommended-requiring-type-checking.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Recommended, requiring type information 3 | * @see https://github.com/typescript-eslint/typescript-eslint/blob/39c45f3/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts#L8-L23 4 | */ 5 | 6 | module.exports = { 7 | rules: { 8 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/await-thenable.md 9 | '@typescript-eslint/await-thenable': 'error', 10 | 11 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-floating-promises.md 12 | '@typescript-eslint/no-floating-promises': 'error', 13 | 14 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-for-in-array.md 15 | '@typescript-eslint/no-for-in-array': 'error', 16 | 17 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-implied-eval.md 18 | '@typescript-eslint/no-implied-eval': 'error', 19 | 20 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-misused-promises.md 21 | '@typescript-eslint/no-misused-promises': 'error', 22 | 23 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.md 24 | '@typescript-eslint/no-unnecessary-type-assertion': 'error', 25 | 26 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unsafe-assignment.md 27 | '@typescript-eslint/no-unsafe-assignment': 'error', 28 | 29 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unsafe-call.md 30 | '@typescript-eslint/no-unsafe-call': 'error', 31 | 32 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unsafe-member-access.md 33 | '@typescript-eslint/no-unsafe-member-access': 'error', 34 | 35 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unsafe-return.md 36 | '@typescript-eslint/no-unsafe-return': 'error', 37 | 38 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-regexp-exec.md 39 | '@typescript-eslint/prefer-regexp-exec': 'error', 40 | 41 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/require-await.md 42 | 'require-await': 'off', 43 | '@typescript-eslint/require-await': 'error', 44 | 45 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/restrict-plus-operands.md 46 | '@typescript-eslint/restrict-plus-operands': 'error', 47 | 48 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/restrict-template-expressions.md 49 | '@typescript-eslint/restrict-template-expressions': 'error', 50 | 51 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/unbound-method.md 52 | '@typescript-eslint/unbound-method': 'error', 53 | }, 54 | }; 55 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-typescript/rules/recommended.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @typescript-eslint/recommended 3 | * @see https://github.com/typescript-eslint/typescript-eslint/blob/39c45f3/packages/eslint-plugin/src/configs/recommended.ts#L8-L32 4 | */ 5 | 6 | module.exports = { 7 | rules: { 8 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/adjacent-overload-signatures.md 9 | '@typescript-eslint/adjacent-overload-signatures': 'error', 10 | 11 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-ts-comment.md 12 | '@typescript-eslint/ban-ts-comment': [ 13 | 'error', 14 | { 15 | 'ts-expect-error': 'allow-with-description', 16 | 'ts-ignore': true, 17 | 'ts-nocheck': true, 18 | 'ts-check': false, 19 | }, 20 | ], 21 | 22 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-types.md 23 | '@typescript-eslint/ban-types': [ 24 | 'error', 25 | { 26 | extendDefaults: true, 27 | types: { 28 | // make default 'object' rule fixable 29 | object: { 30 | fixWith: 'Record', 31 | message: [ 32 | 'The `object` type is currently hard to use ([see this issue](https://github.com/microsoft/TypeScript/issues/21732)).', 33 | 'Consider using `Record` instead, as it allows you to more easily inspect and use the keys.', 34 | ].join('\n'), 35 | }, 36 | }, 37 | }, 38 | ], 39 | 40 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md 41 | '@typescript-eslint/explicit-module-boundary-types': [ 42 | // TODO: move to "strict" variant, enable? 43 | 'off', 44 | { 45 | allowArgumentsExplicitlyTypedAsAny: false, 46 | allowDirectConstAssertionInArrowFunctions: true, 47 | allowedNames: [], 48 | allowHigherOrderFunctions: true, 49 | allowTypedFunctionExpressions: true, 50 | }, 51 | ], 52 | 53 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-array-constructor.md 54 | 'no-array-constructor': 'off', 55 | '@typescript-eslint/no-array-constructor': 'error', 56 | 57 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-empty-function.md 58 | 'no-empty-function': 'off', 59 | '@typescript-eslint/no-empty-function': [ 60 | 'error', 61 | { 62 | allow: [ 63 | // built-in: https://eslint.org/docs/rules/no-empty-function 64 | 'arrowFunctions', 65 | 'functions', 66 | 'methods', 67 | // this plugin 68 | /* 69 | 'private-constructors', 70 | 'protected-constructors', 71 | 'decoratedFunctions', 72 | */ 73 | ], 74 | }, 75 | ], 76 | 77 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-empty-interface.md 78 | '@typescript-eslint/no-empty-interface': 'error', 79 | 80 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-explicit-any.md 81 | '@typescript-eslint/no-explicit-any': 'warn', 82 | 83 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-extra-non-null-assertion.md 84 | '@typescript-eslint/no-extra-non-null-assertion': 'error', 85 | 86 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-inferrable-types.md 87 | '@typescript-eslint/no-inferrable-types': 'error', 88 | 89 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-misused-new.md 90 | '@typescript-eslint/no-misused-new': 'error', 91 | 92 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-namespace.md 93 | '@typescript-eslint/no-namespace': 'error', 94 | 95 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-non-null-asserted-optional-chain.md 96 | '@typescript-eslint/no-non-null-asserted-optional-chain': 'error', 97 | 98 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-non-null-assertion.md 99 | '@typescript-eslint/no-non-null-assertion': 'warn', 100 | 101 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-this-alias.md 102 | '@typescript-eslint/no-this-alias': 'error', 103 | 104 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-vars.md 105 | 'no-unused-vars': 'off', 106 | '@typescript-eslint/no-unused-vars': [ 107 | 'error', 108 | { 109 | argsIgnorePattern: '^_', 110 | varsIgnorePattern: '^ignored', 111 | args: 'after-used', 112 | ignoreRestSiblings: true, 113 | }, 114 | ], 115 | 116 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-use-before-define.md 117 | 'no-use-before-define': 'off', 118 | '@typescript-eslint/no-use-before-define': [ 119 | 'error', 120 | { 121 | // function declarations are hoisted 122 | functions: false, 123 | // type definitions are hoisted 124 | typedefs: false, 125 | }, 126 | ], 127 | 128 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-var-requires.md 129 | '@typescript-eslint/no-var-requires': 'error', 130 | 131 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-as-const.md 132 | '@typescript-eslint/prefer-as-const': 'error', 133 | 134 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-namespace-keyword.md 135 | '@typescript-eslint/prefer-namespace-keyword': 'error', 136 | 137 | // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/triple-slash-reference.md 138 | '@typescript-eslint/triple-slash-reference': [ 139 | 'error', 140 | { 141 | // TODO: get an informed opinion about this config 142 | lib: 'never', 143 | path: 'never', 144 | types: 'prefer-import', 145 | }, 146 | ], 147 | }, 148 | }; 149 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow-typescript/test/requires.js: -------------------------------------------------------------------------------- 1 | /* eslint 2 | strict: 0, 3 | global-require: 0, 4 | */ 5 | 6 | 'use strict'; 7 | 8 | test('all entry points parse', () => { 9 | expect(() => require('..')).not.toThrow(); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow/.editorconfig: -------------------------------------------------------------------------------- 1 | # override root to minimize conflicts with upstream 2 | 3 | [*.js] 4 | indent_size = 2 5 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow/.eslintrc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | extends: "./index.js" 3 | rules: 4 | # enable root lint:prettier to return useful results 5 | prettier/prettier: [error, { tabWidth: 2 }] 6 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012 Airbnb 4 | Copyright (c) 2018 Zillow 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow/README.md: -------------------------------------------------------------------------------- 1 | # eslint-config-zillow 2 | 3 | > Zillow's ESLint config, following our code conventions 4 | 5 | [![npm version](https://img.shields.io/npm/v/eslint-config-zillow.svg)](https://www.npmjs.com/package/eslint-config-zillow) 6 | [![Build Status](https://travis-ci.org/zillow/javascript.svg?branch=latest)](https://travis-ci.org/zillow/javascript) 7 | 8 | ## Usage 9 | 10 | To install with all necessary `peerDependencies`, use [install-peerdeps](https://github.com/nathanhleung/install-peerdeps#usage): 11 | 12 | ```sh 13 | npx install-peerdeps --dev eslint-config-zillow 14 | ``` 15 | 16 | All exported configs should be added to your [ESlint configuration file](https://eslint.org/docs/user-guide/configuring#extending-configuration-files) `extends`. 17 | For example, in a JSON `.eslintrc`: 18 | 19 | ```json 20 | { 21 | "extends": "zillow" 22 | } 23 | ``` 24 | 25 | ### `"extends": "zillow"` 26 | 27 | Lint all the things, including ECMAScript 6+, React, and Prettier. 28 | 29 | If you don't need React, use [eslint-config-zillow-base](https://npmjs.com/eslint-config-zillow-base). 30 | 31 | ### `"extends": ["zillow", "zillow/jest]` 32 | 33 | Jest-specific rules and environment added to the default export. 34 | 35 | ### `"extends": ["zillow", "zillow/mocha]` 36 | 37 | Mocha-specific rules and environment added to the default export. 38 | 39 | ### `prettier` Editor Plugin Integration 40 | 41 | Unfortunately, super-useful editor plugins like `prettier-atom` and `prettier-vscode` do not load Prettier settings from ESLint config, which is where we load our Prettier options from. To workaround this, add a `.prettierrc.js` or `prettier.config.js` file to your root with the following content: 42 | 43 | ```js 44 | module.exports = require('prettier-config-zillow'); 45 | ``` 46 | 47 | ## Related 48 | 49 | - [Zillow's Prettier config](https://npmjs.com/prettier-config-zillow) 50 | - [Zillow's Javascript code conventions](https://github.com/zillow/javascript) 51 | 52 | ## Development 53 | 54 | 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? 55 | 56 | You can run tests (from the repo root) with `npm test`. 57 | 58 | You can make sure this module lints with itself using `npm run lint` (from the repo root). 59 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | 'eslint-config-zillow-base', 4 | 'eslint-config-zillow-base/rules/strict', 5 | './rules/react', 6 | './rules/react-a11y', 7 | ].map(require.resolve), 8 | parser: require.resolve('babel-eslint'), 9 | rules: {}, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow/jest.js: -------------------------------------------------------------------------------- 1 | module.exports = require('eslint-config-zillow-base/jest'); 2 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow/mocha.js: -------------------------------------------------------------------------------- 1 | module.exports = require('eslint-config-zillow-base/mocha'); 2 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-zillow", 3 | "version": "4.0.0", 4 | "description": "Zillow's ESLint config, following our code conventions", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js", 8 | "jest.js", 9 | "mocha.js", 10 | "prettier.config.js", 11 | "rules" 12 | ], 13 | "scripts": { 14 | "test": "echo \"Run tests from root\" && exit 1" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/zillow/javascript" 19 | }, 20 | "keywords": [ 21 | "eslint", 22 | "eslintconfig", 23 | "config", 24 | "zillow", 25 | "javascript", 26 | "code conventions" 27 | ], 28 | "author": "Daniel Stockman (https://twitter.com/@evocateur)", 29 | "license": "MIT", 30 | "homepage": "https://github.com/zillow/javascript/tree/latest/packages/eslint-config-zillow#readme", 31 | "engines": { 32 | "node": ">= 10.17" 33 | }, 34 | "peerDependencies": { 35 | "babel-eslint": "^10.1.0", 36 | "eslint": ">= 7.4.0", 37 | "eslint-plugin-import": "^2.22.0", 38 | "eslint-plugin-jest": "^24.0.2", 39 | "eslint-plugin-jsx-a11y": "^6.3.1", 40 | "eslint-plugin-mocha": "^8.0.0", 41 | "eslint-plugin-prettier": "^3.1.4", 42 | "eslint-plugin-react": "^7.21.2", 43 | "eslint-plugin-react-hooks": "^4.1.2", 44 | "prettier": "^2.1.2" 45 | }, 46 | "dependencies": { 47 | "eslint-config-zillow-base": "file:../eslint-config-zillow-base", 48 | "prettier-config-zillow": "file:../prettier-config-zillow" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow/prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('prettier-config-zillow'); 2 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow/rules/react-a11y.js: -------------------------------------------------------------------------------- 1 | /* eslint prettier/prettier: off */ 2 | 3 | module.exports = { 4 | plugins: [ 5 | 'jsx-a11y', 6 | 'react' 7 | ], 8 | 9 | parserOptions: { 10 | ecmaFeatures: { 11 | jsx: true, 12 | }, 13 | }, 14 | 15 | rules: { 16 | // Enforce that anchors have content 17 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-has-content.md 18 | 'jsx-a11y/anchor-has-content': ['error', { components: [] }], 19 | 20 | // Require ARIA roles to be valid and non-abstract 21 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-role.md 22 | 'jsx-a11y/aria-role': ['error', { ignoreNonDom: false }], 23 | 24 | // Enforce all aria-* props are valid. 25 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-props.md 26 | 'jsx-a11y/aria-props': 'error', 27 | 28 | // Enforce ARIA state and property values are valid. 29 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-proptypes.md 30 | 'jsx-a11y/aria-proptypes': 'error', 31 | 32 | // Enforce that elements that do not support ARIA roles, states, and 33 | // properties do not have those attributes. 34 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-unsupported-elements.md 35 | 'jsx-a11y/aria-unsupported-elements': 'error', 36 | 37 | // Enforce that all elements that require alternative text have meaningful information 38 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/alt-text.md 39 | 'jsx-a11y/alt-text': ['error', { 40 | elements: ['img', 'object', 'area', 'input[type="image"]'], 41 | img: [], 42 | object: [], 43 | area: [], 44 | 'input[type="image"]': [], 45 | }], 46 | 47 | // Ensure the autocomplete attribute is correct and suitable for the form field it is used with 48 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/autocomplete-valid.md 49 | 'jsx-a11y/autocomplete-valid': ['off', { 50 | inputComponents: ['Input'] 51 | }], 52 | 53 | // Prevent img alt text from containing redundant words like "image", "picture", or "photo" 54 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/img-redundant-alt.md 55 | 'jsx-a11y/img-redundant-alt': 'error', 56 | 57 | // Enforce that a label tag has a text label and an associated control. 58 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/b800f40a2a69ad48015ae9226fbe879f946757ed/docs/rules/label-has-associated-control.md 59 | 'jsx-a11y/label-has-associated-control': ['error', { 60 | labelComponents: [], 61 | labelAttributes: [], 62 | controlComponents: [], 63 | assert: 'either', 64 | depth: 25 65 | }], 66 | 67 | // Enforce that a control (an interactive element) has a text label. 68 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/56506740f826433bd498be14a7ec1aff94753ace/docs/rules/control-has-associated-label.md 69 | 'jsx-a11y/control-has-associated-label': ['error', { 70 | labelAttributes: [], 71 | controlComponents: [], 72 | ignoreElements: [ 73 | 'audio', 74 | 'canvas', 75 | 'embed', 76 | 'input', 77 | 'textarea', 78 | 'tr', 79 | 'video', 80 | ], 81 | ignoreRoles: [ 82 | 'grid', 83 | 'listbox', 84 | 'menu', 85 | 'menubar', 86 | 'radiogroup', 87 | 'row', 88 | 'tablist', 89 | 'toolbar', 90 | 'tree', 91 | 'treegrid', 92 | ], 93 | includeRoles: [ 94 | 'alert', 95 | 'dialog', 96 | ], 97 | depth: 25 98 | }], 99 | 100 | // require that mouseover/out come with focus/blur, for keyboard-only users 101 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/mouse-events-have-key-events.md 102 | 'jsx-a11y/mouse-events-have-key-events': 'error', 103 | 104 | // Prevent use of `accessKey` 105 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-access-key.md 106 | 'jsx-a11y/no-access-key': 'error', 107 | 108 | // require onBlur instead of onChange 109 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-onchange.md 110 | 'jsx-a11y/no-onchange': 'off', 111 | 112 | // Elements with an interactive role and interaction handlers must be focusable 113 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/interactive-supports-focus.md 114 | 'jsx-a11y/interactive-supports-focus': 'error', 115 | 116 | // Enforce that elements with ARIA roles must have all required attributes 117 | // for that role. 118 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-has-required-aria-props.md 119 | 'jsx-a11y/role-has-required-aria-props': 'error', 120 | 121 | // Enforce that elements with explicit or implicit roles defined contain 122 | // only aria-* properties supported by that role. 123 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-supports-aria-props.md 124 | 'jsx-a11y/role-supports-aria-props': 'error', 125 | 126 | // Enforce tabIndex value is not greater than zero. 127 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/tabindex-no-positive.md 128 | 'jsx-a11y/tabindex-no-positive': 'error', 129 | 130 | // ensure tags have content and are not aria-hidden 131 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/heading-has-content.md 132 | 'jsx-a11y/heading-has-content': ['error', { components: [''] }], 133 | 134 | // require HTML elements to have a "lang" prop 135 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/html-has-lang.md 136 | 'jsx-a11y/html-has-lang': 'error', 137 | 138 | // require HTML element's lang prop to be valid 139 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/lang.md 140 | 'jsx-a11y/lang': 'error', 141 | 142 | // prevent distracting elements, like and 143 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-distracting-elements.md 144 | 'jsx-a11y/no-distracting-elements': ['error', { 145 | elements: ['marquee', 'blink'], 146 | }], 147 | 148 | // only allow to have the "scope" attr 149 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/scope.md 150 | 'jsx-a11y/scope': 'error', 151 | 152 | // require onClick be accompanied by onKeyUp/onKeyDown/onKeyPress 153 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/click-events-have-key-events.md 154 | 'jsx-a11y/click-events-have-key-events': 'error', 155 | 156 | // Enforce that DOM elements without semantic behavior not have interaction handlers 157 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-static-element-interactions.md 158 | 'jsx-a11y/no-static-element-interactions': ['error', { 159 | handlers: [ 160 | 'onClick', 161 | 'onMouseDown', 162 | 'onMouseUp', 163 | 'onKeyPress', 164 | 'onKeyDown', 165 | 'onKeyUp', 166 | ] 167 | }], 168 | 169 | // A non-interactive element does not support event handlers (mouse and key handlers) 170 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-interactions.md 171 | 'jsx-a11y/no-noninteractive-element-interactions': ['error', { 172 | handlers: [ 173 | 'onClick', 174 | 'onMouseDown', 175 | 'onMouseUp', 176 | 'onKeyPress', 177 | 'onKeyDown', 178 | 'onKeyUp', 179 | ] 180 | }], 181 | 182 | // ensure emoji are accessible 183 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/accessible-emoji.md 184 | 'jsx-a11y/accessible-emoji': 'error', 185 | 186 | // elements with aria-activedescendant must be tabbable 187 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-activedescendant-has-tabindex.md 188 | 'jsx-a11y/aria-activedescendant-has-tabindex': 'error', 189 | 190 | // ensure iframe elements have a unique title 191 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/iframe-has-title.md 192 | 'jsx-a11y/iframe-has-title': 'error', 193 | 194 | // prohibit autoFocus prop 195 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-autofocus.md 196 | 'jsx-a11y/no-autofocus': ['error', { ignoreNonDOM: true }], 197 | 198 | // ensure HTML elements do not specify redundant ARIA roles 199 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-redundant-roles.md 200 | 'jsx-a11y/no-redundant-roles': 'error', 201 | 202 | // media elements must have captions 203 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/media-has-caption.md 204 | // TODO: re-enable once `muted` fix is released 205 | 'jsx-a11y/media-has-caption': ['off', { 206 | audio: [], 207 | video: [], 208 | track: [], 209 | }], 210 | 211 | // WAI-ARIA roles should not be used to convert an interactive element to non-interactive 212 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-interactive-element-to-noninteractive-role.md 213 | 'jsx-a11y/no-interactive-element-to-noninteractive-role': ['error', { 214 | tr: ['none', 'presentation'], 215 | }], 216 | 217 | // WAI-ARIA roles should not be used to convert a non-interactive element to interactive 218 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-to-interactive-role.md 219 | 'jsx-a11y/no-noninteractive-element-to-interactive-role': ['error', { 220 | ul: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'], 221 | ol: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'], 222 | li: ['menuitem', 'option', 'row', 'tab', 'treeitem'], 223 | table: ['grid'], 224 | td: ['gridcell'], 225 | }], 226 | 227 | // Tab key navigation should be limited to elements on the page that can be interacted with. 228 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-tabindex.md 229 | 'jsx-a11y/no-noninteractive-tabindex': ['error', { 230 | tags: [], 231 | roles: ['tabpanel'], 232 | }], 233 | 234 | // ensure tags are valid 235 | // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/0745af376cdc8686d85a361ce36952b1fb1ccf6e/docs/rules/anchor-is-valid.md 236 | 'jsx-a11y/anchor-is-valid': ['error', { 237 | components: ['Link'], 238 | specialLink: ['to'], 239 | aspects: ['noHref', 'invalidHref', 'preferButton'], 240 | }], 241 | }, 242 | }; 243 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow/test/requires.js: -------------------------------------------------------------------------------- 1 | /* eslint 2 | strict: 0, 3 | global-require: 0, 4 | */ 5 | 6 | 'use strict'; 7 | 8 | test('all entry points parse', () => { 9 | expect(() => require('..')).not.toThrow(); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/eslint-config-zillow/test/test-react-order.js: -------------------------------------------------------------------------------- 1 | /* eslint prettier/prettier: off */ 2 | 3 | import { CLIEngine } from 'eslint'; 4 | import eslintrc from '..'; 5 | import reactRules from '../rules/react'; 6 | import reactA11yRules from '../rules/react-a11y'; 7 | 8 | const cli = new CLIEngine({ 9 | useEslintrc: false, 10 | baseConfig: eslintrc, 11 | 12 | rules: { 13 | // It is okay to import devDependencies in tests. 14 | 'import/no-extraneous-dependencies': [2, { devDependencies: true }], 15 | // this doesn't matter for tests 16 | 'lines-between-class-members': 0, 17 | // overrides indent to match upstream 18 | indent: ['error', 2], 19 | 'react/jsx-indent': ['error', 2], 20 | 'react/jsx-indent-props': ['error', 2], 21 | // prettier is irrelevant here 22 | 'prettier/prettier': 'off', 23 | }, 24 | }); 25 | 26 | function lint(text) { 27 | // @see https://eslint.org/docs/developer-guide/nodejs-api.html#executeonfiles 28 | // @see https://eslint.org/docs/developer-guide/nodejs-api.html#executeontext 29 | const linter = cli.executeOnText(text); 30 | 31 | return linter.results[0]; 32 | } 33 | 34 | function wrapComponent(body) { 35 | return ` 36 | import React from 'react'; 37 | 38 | export default class MyComponent extends React.Component { 39 | /* eslint no-empty-function: 0, class-methods-use-this: 0 */ 40 | ${body} 41 | } 42 | `; 43 | } 44 | 45 | describe('validate react prop order', () => { 46 | test('make sure our eslintrc has React and JSX linting dependencies', () => { 47 | expect(reactRules.plugins).toEqual(['react', 'react-hooks']); 48 | expect(reactA11yRules.plugins).toEqual(['jsx-a11y', 'react']); 49 | }); 50 | 51 | test('passes a good component', () => { 52 | expect.assertions(3); 53 | 54 | const result = lint(wrapComponent(` 55 | componentWillMount() {} 56 | componentDidMount() {} 57 | setFoo() {} 58 | getFoo() {} 59 | setBar() {} 60 | someMethod() {} 61 | renderDogs() {} 62 | render() { return
; }`)); 63 | 64 | expect(result.warningCount).toBe(0); 65 | expect(result.errorCount).toBe(0); 66 | expect(result.messages).toHaveLength(0); 67 | }); 68 | 69 | test('order: when random method is first', () => { 70 | expect.assertions(2); 71 | 72 | const result = lint(wrapComponent(` 73 | someMethod() {} 74 | componentWillMount() {} 75 | componentDidMount() {} 76 | setFoo() {} 77 | getFoo() {} 78 | setBar() {} 79 | renderDogs() {} 80 | render() { return
; } 81 | `)); 82 | 83 | expect(result.errorCount).toBeGreaterThan(0); 84 | expect(result.messages[0].ruleId).toBe('react/sort-comp'); 85 | }); 86 | 87 | test('order: when random method after lifecycle methods', () => { 88 | expect.assertions(2); 89 | 90 | const result = lint(wrapComponent(` 91 | componentWillMount() {} 92 | componentDidMount() {} 93 | someMethod() {} 94 | setFoo() {} 95 | getFoo() {} 96 | setBar() {} 97 | renderDogs() {} 98 | render() { return
; } 99 | `)); 100 | 101 | expect(result.errorCount).toBeGreaterThan(0); 102 | expect(result.messages[0].ruleId).toBe('react/sort-comp'); 103 | }); 104 | }); 105 | -------------------------------------------------------------------------------- /packages/eslint-plugin-zillow/README.md: -------------------------------------------------------------------------------- 1 | # eslint-plugin-zillow 2 | 3 | > Zillow's ESLint config bundled into a "zero-conf" plugin 4 | 5 | [![npm version](https://img.shields.io/npm/v/eslint-plugin-zillow.svg)](https://www.npmjs.com/package/eslint-plugin-zillow) 6 | [![Build Status](https://travis-ci.org/zillow/javascript.svg?branch=latest)](https://travis-ci.org/zillow/javascript) 7 | 8 | ## Why 9 | 10 | We want shareable configs to have as low of an overhead as possible. Users shouldn't have to know exactly what plugins are required by the config, install them and manage their versions manually. This plugin exposes [`eslint-config-zillow`](https://github.com/zillow/javascript/tree/latest/packages/eslint-config-zillow#readme) for reuse, with plugins automatically installed. 11 | 12 | > See [https://github.com/eslint/eslint/issues/3458](https://github.com/eslint/eslint/issues/3458) for further discussion on this topic. Approach inspired by [`eslint-plugin-react-app`](https://github.com/mmazzarolo/eslint-plugin-react-app) and [`eslint-plugin-springload`](https://github.com/springload/eslint-plugin-springload). 13 | 14 | ## Usage 15 | 16 | Install the plugin and its minimal peer dependencies: 17 | 18 | ```sh 19 | npm i -D eslint prettier eslint-plugin-zillow 20 | ``` 21 | 22 | Configure ESLint to use this config. For example, in your package.json, this would be: 23 | 24 | ```json 25 | "eslintConfig": { 26 | "extends": "plugin:zillow/recommended" 27 | }, 28 | ``` 29 | 30 | ### Jest 31 | 32 | Jest-specific rules and environment added to the default export. 33 | 34 | ```json 35 | "eslintConfig": { 36 | "extends": ["plugin:zillow/recommended", "plugin:zillow/jest"] 37 | }, 38 | ``` 39 | 40 | ### Mocha 41 | 42 | Mocha-specific rules and environment added to the default export. 43 | 44 | ```json 45 | "eslintConfig": { 46 | "extends": ["plugin:zillow/recommended", "plugin:zillow/mocha"] 47 | }, 48 | ``` 49 | 50 | ### TypeScript 51 | 52 | Enable TypeScript-specific linting rules. 53 | 54 | ```json 55 | "eslintConfig": { 56 | "extends": ["plugin:zillow/recommended", "plugin:zillow/typescript"] 57 | }, 58 | ``` 59 | 60 | This config expects your `tsconfig.json` to be in the current working directory (relative to your eslint config), which is extremely common. If it is elsewhere (say, a monorepo leaf), you will need to override various [`parserOptions`](https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/TYPED_LINTING.md): 61 | 62 | ```js 63 | // .eslintrc.js 64 | module.exports = { 65 | extends: ['plugin:zillow/recommended', 'plugin:zillow/typescript'], 66 | overrides: [ 67 | { 68 | test: '**/*.ts?(x)', 69 | parserOptions: { 70 | tsconfigRootDir: __dirname, 71 | project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'], 72 | }, 73 | }, 74 | ], 75 | }; 76 | ``` 77 | 78 | ### Customizing Rules 79 | 80 | You can configure the rules like every other `eslint` plugin. 81 | Just keep in mind that if you want to change a rule of an included plugin (for example, `eslint-plugin-react`) you must prefix the rule with `zillow/` (necessary to prevent namespace collisions). 82 | 83 | For example: 84 | 85 | ```json 86 | { 87 | "extends": [ 88 | "plugin:zillow/recommended" 89 | ], 90 | "rules": { 91 | "zillow/react/react-in-jsx-scope": ["warn"] 92 | } 93 | } 94 | ``` 95 | 96 | ### `prettier` Editor Plugin Integration 97 | 98 | Unfortunately, super-useful editor plugins like `prettier-atom` and `prettier-vscode` do not load Prettier settings from ESLint config, which is where we load our Prettier options from. To workaround this, add a `.prettierrc.js` or `prettier.config.js` file to your root with the following content: 99 | 100 | ```js 101 | module.exports = require('prettier-config-zillow'); 102 | ``` 103 | 104 | ## "Bundled" Plugins 105 | 106 | We currently encapsulate the following plugins: 107 | 108 | - [eslint-plugin-import](https://github.com/benmosher/eslint-plugin-import) 109 | - [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest#readme) 110 | - [eslint-plugin-jsx-a11y](https://github.com/evcohen/eslint-plugin-jsx-a11y) 111 | - [eslint-plugin-mocha](https://github.com/lo1tuma/eslint-plugin-mocha) 112 | - [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) 113 | - [eslint-plugin-react](https://github.com/yannickcr/eslint-plugin-react) 114 | - [eslint-plugin-react-hooks](https://reactjs.org/docs/hooks-rules.html) 115 | - [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#readme) 116 | -------------------------------------------------------------------------------- /packages/eslint-plugin-zillow/lib/configs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zillow/javascript/3d04d95d7f6f087cd61f70a191a5e81e8c175a9f/packages/eslint-plugin-zillow/lib/configs/.gitkeep -------------------------------------------------------------------------------- /packages/eslint-plugin-zillow/lib/eslint-plugin-zillow.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { getPluginEnvironments, getPluginProcessors, getPluginRules } = require('./plugins'); 4 | const jestConfig = require('./configs/jest.json'); 5 | const mochaConfig = require('./configs/mocha.json'); 6 | const recommendedConfig = require('./configs/recommended.json'); 7 | const typescriptConfig = require('./configs/typescript.json'); 8 | 9 | // resolve parser to support pnpm strict linking 10 | recommendedConfig.parser = require.resolve(recommendedConfig.parser); 11 | typescriptConfig.overrides[0].parser = require.resolve(typescriptConfig.overrides[0].parser); 12 | 13 | // ditto, but for import plugin resolver 14 | const importResolverNodeSettings = { 15 | ...recommendedConfig.settings['import/resolver'].node, 16 | }; 17 | 18 | recommendedConfig.settings['import/resolver'] = { 19 | [require.resolve('eslint-import-resolver-node')]: importResolverNodeSettings, 20 | // place default _after_ resolved bit so eslint v5 still works 21 | node: importResolverNodeSettings, 22 | }; 23 | 24 | module.exports = { 25 | configs: { 26 | jest: jestConfig, 27 | mocha: mochaConfig, 28 | recommended: recommendedConfig, 29 | typescript: typescriptConfig, 30 | }, 31 | environments: getPluginEnvironments(), 32 | processors: getPluginProcessors(), 33 | rules: getPluginRules(), 34 | }; 35 | -------------------------------------------------------------------------------- /packages/eslint-plugin-zillow/lib/plugins.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.getPluginEnvironments = getPluginEnvironments; 4 | exports.getPluginProcessors = getPluginProcessors; 5 | exports.getPluginRules = getPluginRules; 6 | 7 | const plugins = new Map(); 8 | 9 | plugins.set('import', require('eslint-plugin-import')); 10 | plugins.set('jest', require('eslint-plugin-jest')); 11 | plugins.set('jsx-a11y', require('eslint-plugin-jsx-a11y')); 12 | plugins.set('mocha', require('eslint-plugin-mocha')); 13 | plugins.set('react', require('eslint-plugin-react')); 14 | plugins.set('react-hooks', require('eslint-plugin-react-hooks')); 15 | plugins.set('prettier', require('eslint-plugin-prettier')); 16 | plugins.set('@typescript-eslint', require('@typescript-eslint/eslint-plugin')); 17 | 18 | /** 19 | * Create an environments object from plugin environments. 20 | * Each environment is prefixed by the name of the plugin it comes from. 21 | */ 22 | function getPluginEnvironments() { 23 | const result = {}; 24 | 25 | plugins.forEach(({ environments = {} }, namespace) => { 26 | Object.keys(environments).forEach(name => { 27 | result[`${namespace}/${name}`] = environments[name]; 28 | }); 29 | }); 30 | 31 | return result; 32 | } 33 | 34 | /** 35 | * Create a processors object from plugin processors. 36 | */ 37 | function getPluginProcessors() { 38 | const result = {}; 39 | 40 | plugins.forEach(({ processors = {} }) => { 41 | Object.assign(result, processors); 42 | }); 43 | 44 | return result; 45 | } 46 | 47 | /** 48 | * Create a rules object from plugin rules. 49 | * Each rule is prefixed by the name of the plugin it comes from. 50 | */ 51 | function getPluginRules() { 52 | const result = {}; 53 | 54 | plugins.forEach(({ rules }, namespace) => { 55 | Object.keys(rules).forEach(rule => { 56 | result[`${namespace}/${rule}`] = rules[rule]; 57 | }); 58 | }); 59 | 60 | return result; 61 | } 62 | -------------------------------------------------------------------------------- /packages/eslint-plugin-zillow/lib/render-plugin-configs.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | 'use strict'; 4 | 5 | const fs = require('fs'); 6 | const path = require('path'); 7 | const writeFile = require('util').promisify(fs.writeFile); 8 | /* eslint-disable import/no-extraneous-dependencies */ 9 | const { ESLint } = require('eslint'); 10 | const ConfigValidator = require('@eslint/eslintrc/lib/shared/config-validator'); 11 | const BuiltInEnvironments = require('@eslint/eslintrc/conf/environments'); 12 | /* eslint-enable import/no-extraneous-dependencies */ 13 | const { getPluginEnvironments } = require('./plugins'); 14 | 15 | const PLUGIN_ENVIRONMENTS = new Map(Object.entries(getPluginEnvironments())); 16 | 17 | async function main() { 18 | const jestTask = renderConfig( 19 | 'jest', 20 | { 21 | extends: ['zillow/jest'], 22 | rules: { 23 | // plugin-specific rules that hamper effective testing 24 | '@typescript-eslint/no-invalid-void-type': ['off'], 25 | 'no-import-assign': ['off'], 26 | 'react/prop-types': ['off'], 27 | }, 28 | }, 29 | [ 30 | // prettier-ignore 31 | '**/*{-,.}test.[jt]s?(x)', 32 | '**/*.stories.[jt]s?(x)', 33 | '**/__tests__/**/*.[jt]s?(x)', 34 | '**/__mocks__/**/*.[jt]s?(x)', 35 | '**/test/**/*.[jt]s?(x)', 36 | ] 37 | ); 38 | 39 | const mochaTask = renderConfig( 40 | 'mocha', 41 | { 42 | extends: ['zillow/mocha'], 43 | rules: { 44 | // mocha does fancy things with test case scope, 45 | // and this conflicts with mocha/no-mocha-arrow 46 | 'prefer-arrow-callback': 'off', 47 | 'func-names': 'off', 48 | 'no-import-assign': ['off'], 49 | 'react/prop-types': ['off'], 50 | }, 51 | }, 52 | [ 53 | // prettier-ignore 54 | '**/*-test.[jt]s?(x)', 55 | '**/test/**/*.[jt]s?(x)', 56 | ] 57 | ); 58 | 59 | const recommendedTask = renderConfig('recommended', { 60 | extends: ['zillow'], 61 | parser: 'babel-eslint', 62 | rules: { 63 | // TODO: re-enable when https://github.com/yannickcr/eslint-plugin-react/commit/2b0d70c is released 64 | 'react/prop-types': ['off'], 65 | }, 66 | }); 67 | 68 | const typescriptTask = renderConfig( 69 | 'typescript', 70 | { 71 | extends: ['zillow-typescript'], 72 | parser: '@typescript-eslint/parser', 73 | }, 74 | ['**/*.ts?(x)'] 75 | ); 76 | 77 | /* istanbul ignore next (catch doesn't need coverage) */ 78 | try { 79 | await Promise.all([jestTask, mochaTask, recommendedTask, typescriptTask]); 80 | } catch (error) { 81 | // eslint-disable-next-line no-console 82 | console.error(error); 83 | process.exitCode = 1; 84 | } 85 | } 86 | 87 | /** 88 | * Render specified ESLint config to JSON file 89 | * @param {string} name 90 | * @param {{ extends: string[], rules?: { [k: string]: any }}} config 91 | * @param {string[]} [overrides] List of override file globs 92 | */ 93 | async function renderConfig(name, config, overrides) { 94 | const validator = new ConfigValidator(); 95 | const computedConfig = await getComputedConfig(config); 96 | const wrappedConfig = wrapInPlugin(computedConfig, overrides); 97 | const targetPath = path.resolve(__dirname, `./configs/${name}.json`); 98 | 99 | validator.validate( 100 | wrappedConfig, 101 | config.extends[0], 102 | () => {}, 103 | // (slightly less) horrible cheese to avoid exploding 104 | envName => PLUGIN_ENVIRONMENTS.get(envName.replace('zillow/', '')) 105 | ); 106 | 107 | /* istanbul ignore if */ 108 | if (process.env.NODE_ENV !== 'test') { 109 | // eslint-disable-next-line no-console 110 | console.log(`writing ${path.relative('.', targetPath)}`); 111 | } 112 | 113 | await writeFile(targetPath, JSON.stringify(wrappedConfig, null, 2)); 114 | } 115 | 116 | /** 117 | * Generate ESLint config object from specified baseConfig 118 | * @param {{ extends: string[], rules?: { [k: string]: any }}} baseConfig 119 | */ 120 | async function getComputedConfig(baseConfig) { 121 | const engine = new ESLint({ 122 | useEslintrc: false, 123 | allowInlineConfig: false, 124 | baseConfig, 125 | }); 126 | 127 | const computed = await engine.calculateConfigForFile('index.js'); 128 | 129 | // remove unnecessary fields 130 | delete computed.filePath; 131 | delete computed.baseDirectory; 132 | 133 | // un-resolve parser (re-resolved during re-export) 134 | if (computed.parser && baseConfig.parser && computed.parser !== baseConfig.parser) { 135 | computed.parser = baseConfig.parser; 136 | } 137 | 138 | return computed; 139 | } 140 | 141 | function wrapInPlugin(config, files) { 142 | // if files passed, this whole block will be moved to overrides[0] 143 | const pluginConfig = { 144 | files, 145 | // We expose a config already computed from the whole extends chain, so no extends here. 146 | ...config, 147 | extends: [], 148 | // Plugins appear to come from this plugin, so it's the only one externally visible. 149 | plugins: ['zillow'], 150 | // The rules from third-party plugins need to be prefixed so they reference our namespace. 151 | rules: prefixRuleConfigs('zillow', config.rules), 152 | }; 153 | 154 | // if non-builtin envs are passed, make sure they're properly prefixed 155 | if (pluginConfig.env) { 156 | const ourEnv = {}; 157 | 158 | // eslint-disable-next-line no-restricted-syntax 159 | for (const envName of Object.keys(pluginConfig.env)) { 160 | if (BuiltInEnvironments.has(envName)) { 161 | // pass through builtin environments 162 | ourEnv[envName] = pluginConfig.env[envName]; 163 | } else { 164 | // needs prefix to find our wrapper 165 | ourEnv[`zillow/${envName}`] = pluginConfig.env[envName]; 166 | } 167 | } 168 | 169 | pluginConfig.env = ourEnv; 170 | } 171 | 172 | if (files) { 173 | // https://eslint.org/docs/user-guide/configuring#configuration-based-on-glob-patterns 174 | delete pluginConfig.extends; 175 | delete pluginConfig.ignorePatterns; 176 | delete pluginConfig.overrides; 177 | delete pluginConfig.root; 178 | 179 | if (pluginConfig.parserOptions && Object.keys(pluginConfig.parserOptions).length === 0) { 180 | delete pluginConfig.parserOptions; 181 | } 182 | 183 | return { overrides: [pluginConfig] }; 184 | } 185 | 186 | // "files" only valid in overrides 187 | delete pluginConfig.files; 188 | 189 | return pluginConfig; 190 | } 191 | 192 | /** 193 | * Adds a prefix to rules that come from plugins. 194 | */ 195 | function prefixRuleConfigs(prefix, rules) { 196 | return Object.keys(rules).reduce((acc, name) => { 197 | // Plugin rules always have a slash in the name 198 | if (name.indexOf('/') !== -1) { 199 | acc[`${prefix}/${name}`] = rules[name]; 200 | } else { 201 | acc[name] = rules[name]; 202 | } 203 | 204 | return acc; 205 | }, {}); 206 | } 207 | 208 | /* istanbul ignore if */ 209 | if (require.main === module) { 210 | // node lib/render-configs.js 211 | main(); 212 | } else { 213 | module.exports = main; 214 | } 215 | -------------------------------------------------------------------------------- /packages/eslint-plugin-zillow/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-plugin-zillow", 3 | "version": "4.0.1", 4 | "description": "Zillow's ESLint config bundled into a \"zero-conf\" plugin", 5 | "keywords": [ 6 | "eslint", 7 | "eslintconfig", 8 | "eslint-config", 9 | "eslintplugin", 10 | "eslint-plugin", 11 | "zillow", 12 | "javascript", 13 | "code conventions" 14 | ], 15 | "author": "Daniel Stockman (https://twitter.com/@evocateur)", 16 | "homepage": "https://github.com/zillow/javascript/tree/latest/packages/eslint-plugin-zillow#readme", 17 | "engines": { 18 | "node": ">= 10.17" 19 | }, 20 | "license": "MIT", 21 | "main": "lib/eslint-plugin-zillow.js", 22 | "files": [ 23 | "lib", 24 | "prettier.config.js" 25 | ], 26 | "repository": { 27 | "type": "git", 28 | "url": "git+https://github.com/zillow/javascript.git" 29 | }, 30 | "scripts": { 31 | "test": "echo \"Error: run tests from root\" && exit 1" 32 | }, 33 | "peerDependencies": { 34 | "eslint": ">= 7.4.0", 35 | "prettier": "^2.1.2" 36 | }, 37 | "dependencies": { 38 | "@typescript-eslint/eslint-plugin": "^4.3.0", 39 | "@typescript-eslint/parser": "^4.3.0", 40 | "babel-eslint": "^10.1.0", 41 | "eslint-config-zillow": "file:../eslint-config-zillow", 42 | "eslint-config-zillow-typescript": "file:../eslint-config-zillow-typescript", 43 | "eslint-import-resolver-node": "^0.3.4", 44 | "eslint-plugin-import": "^2.22.1", 45 | "eslint-plugin-jest": "^24.0.2", 46 | "eslint-plugin-jsx-a11y": "^6.3.1", 47 | "eslint-plugin-mocha": "^8.0.0", 48 | "eslint-plugin-prettier": "^3.1.4", 49 | "eslint-plugin-react": "^7.21.2", 50 | "eslint-plugin-react-hooks": "^4.1.2", 51 | "prettier-config-zillow": "file:../prettier-config-zillow", 52 | "typescript": "^4.0.2" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /packages/eslint-plugin-zillow/prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('prettier-config-zillow'); 2 | -------------------------------------------------------------------------------- /packages/eslint-plugin-zillow/test/eslint-plugin-zillow.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* eslint-disable global-require -- awaiting global beforeAll() */ 4 | 5 | // ensure up-to-date JSON 6 | beforeAll(() => require('../lib/render-plugin-configs')()); 7 | 8 | describe('eslint-plugin-zillow', () => { 9 | test('configs', () => { 10 | const { configs } = require('..'); 11 | 12 | expect(configs).toMatchObject({ 13 | jest: { 14 | overrides: [ 15 | { 16 | env: { 17 | 'zillow/jest/globals': true, 18 | }, 19 | files: [ 20 | '**/*{-,.}test.[jt]s?(x)', 21 | '**/*.stories.[jt]s?(x)', 22 | '**/__tests__/**/*.[jt]s?(x)', 23 | '**/__mocks__/**/*.[jt]s?(x)', 24 | '**/test/**/*.[jt]s?(x)', 25 | ], 26 | plugins: ['zillow'], 27 | rules: { 28 | 'zillow/jest/no-focused-tests': ['error'], 29 | }, 30 | }, 31 | ], 32 | }, 33 | mocha: { 34 | overrides: [ 35 | { 36 | env: { 37 | mocha: true, 38 | }, 39 | files: [ 40 | // prettier-ignore 41 | '**/*-test.[jt]s?(x)', 42 | '**/test/**/*.[jt]s?(x)', 43 | ], 44 | plugins: ['zillow'], 45 | rules: { 46 | 'zillow/mocha/no-exclusive-tests': ['error'], 47 | 'prefer-arrow-callback': ['off'], 48 | 'func-names': ['off'], 49 | }, 50 | }, 51 | ], 52 | }, 53 | recommended: { 54 | parser: require.resolve('babel-eslint'), 55 | rules: { 56 | 'zillow/react/jsx-indent': ['off', 4], 57 | 'max-len': ['warn', 100, 4, { ignoreComments: false }], 58 | 'zillow/import/prefer-default-export': ['off'], 59 | }, 60 | }, 61 | typescript: { 62 | overrides: [ 63 | { 64 | files: ['**/*.ts?(x)'], 65 | parser: require.resolve('@typescript-eslint/parser'), 66 | plugins: ['zillow'], 67 | rules: { 68 | 'zillow/@typescript-eslint/await-thenable': ['error'], 69 | }, 70 | }, 71 | ], 72 | }, 73 | }); 74 | 75 | const importResolverConfig = configs.recommended.settings['import/resolver']; 76 | const resolverConfigKeys = Object.keys(importResolverConfig); 77 | 78 | expect(resolverConfigKeys).toEqual([ 79 | expect.stringMatching(/eslint-import-resolver-node/), 80 | 'node', 81 | ]); 82 | expect(importResolverConfig[resolverConfigKeys[0]]).toStrictEqual({ 83 | extensions: [ 84 | // first three match react's override 85 | '.js', 86 | '.jsx', 87 | '.json', 88 | // the remainder from base imports spec 89 | '.ts', 90 | '.tsx', 91 | '.d.ts', 92 | '.cjs', 93 | '.mjs', 94 | ], 95 | }); 96 | expect(importResolverConfig[resolverConfigKeys[0]]).toStrictEqual( 97 | importResolverConfig.node 98 | ); 99 | }); 100 | 101 | test('environments', () => { 102 | const { environments } = require('..'); 103 | 104 | expect(environments).toStrictEqual({ 105 | 'jest/globals': require('eslint-plugin-jest').environments.globals, 106 | }); 107 | }); 108 | 109 | test('processors', () => { 110 | const { processors } = require('..'); 111 | 112 | expect(processors).toMatchObject({ 113 | '.snap': {}, 114 | }); 115 | }); 116 | 117 | test('rules', () => { 118 | const { rules } = require('..'); 119 | 120 | expect(rules).toMatchObject({ 121 | 'import/prefer-default-export': { 122 | meta: {}, 123 | create: expect.any(Function), 124 | }, 125 | 'react/sort-prop-types': { 126 | meta: {}, 127 | create: expect.any(Function), 128 | }, 129 | }); 130 | }); 131 | }); 132 | 133 | describe('rendered config', () => { 134 | // module entry mutates required JSON :P 135 | beforeAll(() => { 136 | jest.resetModules(); 137 | }); 138 | 139 | describe.each(['jest', 'mocha', 'recommended', 'typescript'])('%s.json', name => { 140 | it('matches snapshot', () => { 141 | // eslint-disable-next-line import/no-dynamic-require 142 | expect(require(`../lib/configs/${name}.json`)).toMatchSnapshot(); 143 | }); 144 | }); 145 | }); 146 | -------------------------------------------------------------------------------- /packages/prettier-config-zillow/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [1.3.0](https://github.com/zillow/javascript/compare/prettier-config-zillow@1.2.0...prettier-config-zillow@1.3.0) (2020-09-28) 7 | 8 | 9 | ### Features 10 | 11 | * **prettier:** Add embeddedLanguageFormatting default to config ([99708d0](https://github.com/zillow/javascript/commit/99708d0df097e455897583a9a17a907e8671a0d9)) 12 | 13 | 14 | 15 | 16 | 17 | # [1.2.0](https://github.com/zillow/javascript/compare/prettier-config-zillow@1.1.1...prettier-config-zillow@1.2.0) (2020-04-21) 18 | 19 | 20 | ### Features 21 | 22 | * **prettier:** Add tsconfig.json to 2-space indent override ([d4b7038](https://github.com/zillow/javascript/commit/d4b7038ecfdaea414b229235aeed8fa0a402f6b2)) 23 | * **prettier:** Add v2 arrowParens override for TypeScript files ([9ab8ef8](https://github.com/zillow/javascript/commit/9ab8ef85bad062a0bcfe9459ba8b3bd793464148)) 24 | 25 | 26 | 27 | 28 | 29 | ## [1.1.1](https://github.com/zillow/javascript/compare/prettier-config-zillow@1.1.0...prettier-config-zillow@1.1.1) (2019-06-26) 30 | 31 | 32 | ### Bug Fixes 33 | 34 | * **prettier-config-zillow:** Remove prettier peer, it is redundant ([4df8c1e](https://github.com/zillow/javascript/commit/4df8c1e)) 35 | 36 | 37 | 38 | 39 | 40 | # 1.1.0 (2019-04-22) 41 | 42 | 43 | ### Features 44 | 45 | * Add `prettier-config-zillow` package ([c62278e](https://github.com/zillow/javascript/commit/c62278e)) 46 | -------------------------------------------------------------------------------- /packages/prettier-config-zillow/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Zillow 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/prettier-config-zillow/README.md: -------------------------------------------------------------------------------- 1 | # `prettier-config-zillow` 2 | 3 | > Zillow's base Prettier config, following our code conventions 4 | 5 | ## Usage 6 | 7 | ```sh 8 | npm i -D prettier prettier-config-zillow 9 | ``` 10 | 11 | Reference in `package.json`: 12 | 13 | ```json 14 | { 15 | "name": "my-package", 16 | "version": "1.2.3", 17 | "prettier": "prettier-config-zillow" 18 | } 19 | ``` 20 | 21 | Please consult the [Prettier documentation](https://prettier.io/docs/en/configuration.html#sharing-configurations) for further options. 22 | -------------------------------------------------------------------------------- /packages/prettier-config-zillow/lib/prettier-config-zillow.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | $schema: 'http://json.schemastore.org/prettierrc', 5 | 6 | // defaults 7 | // TODO: (major) match v2 "arrowParens" default "always" 8 | arrowParens: 'avoid', 9 | bracketSpacing: true, 10 | embeddedLanguageFormatting: 'auto', 11 | jsxBracketSameLine: false, 12 | htmlWhitespaceSensitivity: 'css', 13 | requirePragma: false, 14 | insertPragma: false, 15 | proseWrap: 'preserve', 16 | semi: true, 17 | useTabs: false, 18 | 19 | // customized 20 | endOfLine: 'lf', 21 | printWidth: 100, 22 | singleQuote: true, 23 | tabWidth: 4, 24 | trailingComma: 'es5', 25 | quoteProps: 'consistent', 26 | 27 | overrides: [ 28 | // explicitly keep output consistent with npm 29 | { 30 | files: [ 31 | '.eslintrc.json', 32 | 'lerna.json', 33 | 'package.json', 34 | 'package-lock.json', 35 | 'npm-shrinkwrap.json', 36 | ], 37 | options: { 38 | parser: 'json-stringify', 39 | tabWidth: 2, 40 | trailingComma: 'none', 41 | }, 42 | }, 43 | { 44 | files: [ 45 | '*.yaml', 46 | '*.yml', 47 | // tsc --init outputs 2-space indent, but it is _not_ "pure" JSON 48 | 'tsconfig.json', 49 | ], 50 | options: { 51 | tabWidth: 2, 52 | }, 53 | }, 54 | { 55 | /** 56 | * Prettier v2 changed the default of arrowParens to "always". 57 | * This is very nice for TypeScript,but would cause dramatic diffs 58 | * with JS(X), so we're gonna avoid that for now. 59 | */ 60 | files: ['*.ts', '*.tsx'], 61 | options: { 62 | arrowParens: 'always', 63 | }, 64 | }, 65 | ], 66 | }; 67 | -------------------------------------------------------------------------------- /packages/prettier-config-zillow/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "prettier-config-zillow", 3 | "version": "1.3.0", 4 | "description": "Zillow's base Prettier config, following our code conventions", 5 | "keywords": [ 6 | "prettier", 7 | "config", 8 | "zillow", 9 | "javascript" 10 | ], 11 | "author": "Daniel Stockman (https://twitter.com/@evocateur)", 12 | "homepage": "https://github.com/zillow/javascript/tree/latest/packages/prettier-config-zillow#readme", 13 | "license": "MIT", 14 | "main": "lib/prettier-config-zillow.js", 15 | "files": [ 16 | "lib" 17 | ], 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/zillow/javascript.git" 21 | }, 22 | "scripts": { 23 | "test": "echo \"Error: run tests from root\" && exit 1" 24 | }, 25 | "engines": { 26 | "node": ">= 8.9.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/prettier-config-zillow/test/prettier-config-zillow.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const prettierConfig = require('..'); 4 | 5 | test('prettier-config-zillow', () => { 6 | expect(prettierConfig).toMatchObject({ 7 | $schema: 'http://json.schemastore.org/prettierrc', 8 | // only test customized props 9 | endOfLine: 'lf', 10 | printWidth: 100, 11 | singleQuote: true, 12 | tabWidth: 4, 13 | trailingComma: 'es5', 14 | quoteProps: 'consistent', 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/zillow-browser-shims/CHANGELOG-upstream.md: -------------------------------------------------------------------------------- 1 | Unreleased 2 | ================= 3 | 4 | 2.1.0 / 2018-01-24 5 | ================= 6 | * [New] add window.location.origin polyfill 7 | * [Deps] update `airbnb-js-shims`, `console-polyfill`, `raf` 8 | * [Dev Deps] update `eslint`, `eslint-config-airbnb-base`, `eslint-plugin-import` 9 | * [Tests] up to `node` `v9.4`, `v8.5`, `v6.12`; pin included builds to LTS 10 | 11 | 2.0.0 / 2017-09-22 12 | ================= 13 | * [Breaking] Remove `webrtc-adapter` 14 | * [Dev Deps] update `eslint` 15 | 16 | 1.12.0 / 2017-09-14 17 | ================= 18 | * [New] Bump the webrtc-adapter dependency to latest version 19 | * [Deps] update `airbnb-js-shims`, `smoothscroll-polyfill`, `whatwg-fetch` 20 | * [Dev Deps] update `eslint`, `eslint-config-airbnb-base`, `eslint-plugin-import`, `tape` 21 | * [Tests] up to `node` `v8.5`, `v6.11` 22 | * [Tests] use `nvm install-latest-npm` to ensure new npm doesn’t break on older node 23 | 24 | 1.11.1 / 2017-06-07 25 | ================= 26 | * [Fix] `TouchList` is a constructor 27 | * [Dev Deps] update `eslint-plugin-import` 28 | 29 | 1.11.0 / 2017-05-25 30 | ================= 31 | * [New] Add `smoothscroll-polyfill` 32 | 33 | 1.10.0 / 2017-05-23 34 | ================= 35 | * [New] Add Element.prototype.closest polyfill 36 | 37 | 1.9.0 / 2017-05-23 38 | ================= 39 | * [New] polyfill Symbol.iterator on TouchList 40 | * [Deps] update `classlist-polyfill`, `raf` 41 | * [Dev Deps] update `eslint`, `eslint-config-airbnb-base` 42 | 43 | 1.8.0 / 2017-03-22 44 | ================= 45 | * [Deps] update `airbnb-js-shims` 46 | * [Dev Deps] update `eslint`, `eslint-config-airbnb-base` 47 | * [Deps] downgrade `whatwg-fetch` to v0.11 for full IE9 support 48 | 49 | 1.7.0 / 2017-02-16 50 | ================= 51 | * [New] split out browser-only entry point 52 | 53 | 1.6.0 / 2017-02-06 54 | ================= 55 | * [New] add whatwg-fetch (#10) 56 | * [Deps] update `webrtc-adapter` 57 | * [Dev Deps] update `eslint`, `eslint-config-airbnb-base` 58 | * [Tests] up to `node` `v7.5`, `v6.9`, `v4.7`; improve test matrix 59 | 60 | 1.5.0 / 2016-11-23 61 | ================= 62 | * [New] add `console.*` polyfills (#7) 63 | 64 | 1.4.0 / 2016-11-18 65 | ================= 66 | * [New] add `requestIdleCallback` (#6) 67 | * [Deps] update `webrtc-adapter` 68 | * [Dev Deps] update `eslint`, `eslint-config-airbnb-base`, `eslint-plugin-import`, `safe-publish-latest`, `tape` 69 | 70 | 1.3.1 / 2016-10-23 71 | ================= 72 | * Fix v1.3.0 publish 73 | 74 | 1.3.0 / 2016-09-13 75 | ================= 76 | * [New] Add matchMedia polyfill (#3) 77 | 78 | 1.2.0 / 2016-09-02 79 | ================= 80 | * [New] add `requestAnimationFrame` polyfill. Works in browsers + node 81 | * [Dev Deps] update `eslint`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react` 82 | 83 | 1.1.0 / 2016-08-25 84 | ================= 85 | * [New] add `classList` polyfill; only require it in browsers 86 | * [Dev Deps] add `safe-publish-latest`; update `eslint-plugin-import` 87 | * [Docs] add npm version badge 88 | 89 | 1.0.0 / 2016-08-17 90 | ================= 91 | * Initial release. 92 | -------------------------------------------------------------------------------- /packages/zillow-browser-shims/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | ## [1.0.1](https://github.com/zillow/javascript/compare/zillow-browser-shims@1.0.0...zillow-browser-shims@1.0.1) (2020-09-23) 7 | 8 | **Note:** Version bump only for package zillow-browser-shims 9 | 10 | 11 | 12 | 13 | 14 | 15 | # [1.0.0](https://github.com/zillow/javascript/compare/zillow-browser-shims@1.0.0-rc.0...zillow-browser-shims@1.0.0) (2018-08-15) 16 | 17 | 18 | ### Bug Fixes 19 | 20 | * **pkg:** Correct homepage URL ([1b5e7f0](https://github.com/zillow/javascript/commit/1b5e7f0)) 21 | 22 | 23 | 24 | 25 | 26 | 27 | # [1.0.0-rc.0](https://github.com/zillow/javascript/compare/zillow-browser-shims@1.0.0-alpha.1...zillow-browser-shims@1.0.0-rc.0) (2018-06-05) 28 | 29 | **Note:** Version bump only for package zillow-browser-shims 30 | 31 | 32 | 33 | 34 | 35 | 36 | # 1.0.0-alpha.1 (2018-04-10) 37 | 38 | 39 | ### Features 40 | 41 | * Fork airbnb-browser-shims -> zillow-browser-shims ([a72da8f](https://github.com/zillow/javascript/commit/a72da8f)) 42 | -------------------------------------------------------------------------------- /packages/zillow-browser-shims/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Airbnb 4 | Copyright (c) 2018 Zillow 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /packages/zillow-browser-shims/README.md: -------------------------------------------------------------------------------- 1 | # zillow-browser-shims [![Version Badge][2]][1] 2 | 3 | > Browser and JS language shims used by Zillow 4 | 5 | Just require/import `zillow-browser-shims`, and the environment will be shimmed. 6 | 7 | ```js 8 | import 'zillow-browser-shims'; 9 | ``` 10 | 11 | ## Included shims 12 | 13 | - JS language shims from [zillow-js-shims](https://www.npmjs.com/package/zillow-js-shims) 14 | - [document.contains](https://developer.mozilla.org/en/docs/Web/API/Node/contains) 15 | - [classlist-polyfill](https://www.npmjs.com/package/classlist-polyfill) - Element.prototype.classList polyfill (only in browsers) 16 | - [raf](https://www.npmjs.com/package/raf) - requestAnimationFrame polyfill for browsers and node 17 | - [requestIdleCallback](https://www.npmjs.com/package/ric-shim) 18 | - [whatwg-fetch](https://github.com/github/fetch) - fetch polyfill (only in browsers, supports IE9+) 19 | - `TouchList[Symbol.iterator]` - when `Symbol` and `TouchList` are both present 20 | - [element-closest](https://npmjs.com/element-closest) - Element.prototype.closest polyfill (only in browsers) 21 | - [smoothscroll-polyfill](https://www.npmjs.com/package/smoothscroll-polyfill) - Scroll behavior specification polyfill (only in browsers) 22 | 23 | ## Only browser shims 24 | 25 | If you only want to bring in the browser shims and not the JS language shims 26 | (from `zillow-js-shims`), you can import `zillow-browser-shims/browser-only`. If 27 | you choose this route, you will want to be sure that you are properly bringing 28 | in the language shims for the browsers you support somehow. For example: 29 | 30 | ```js 31 | import 'zillow-js-shims/target/es2015'; 32 | import 'zillow-browser-shims/browser-only'; 33 | ``` 34 | 35 | [1]: https://npmjs.org/package/zillow-browser-shims 36 | [2]: http://versionbadg.es/zillow/browser-shims.svg 37 | -------------------------------------------------------------------------------- /packages/zillow-browser-shims/browser-only.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* eslint-disable global-require */ 4 | 5 | // document.contains polyfill 6 | require('./document-contains'); 7 | 8 | require('whatwg-fetch'); 9 | 10 | if (typeof window !== 'undefined') { 11 | // Element.classList polyfill 12 | require('classlist-polyfill'); 13 | 14 | // Element.closest polyfill 15 | require('element-closest'); 16 | 17 | // Polyfill for smooth scrolling behavior 18 | require('smoothscroll-polyfill').polyfill(); 19 | } 20 | 21 | require('raf/polyfill'); 22 | 23 | global.requestIdleCallback = require('ric-shim'); 24 | 25 | global.cancelIdleCallback = global.requestIdleCallback.cancelIdleCallback; 26 | 27 | const hasSymbols = typeof Symbol === 'function' && Symbol.iterator; 28 | 29 | /* globals TouchList */ 30 | if ( 31 | hasSymbols && 32 | typeof TouchList === 'function' && 33 | typeof TouchList.prototype[Symbol.iterator] !== 'function' 34 | ) { 35 | TouchList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]; 36 | } 37 | -------------------------------------------------------------------------------- /packages/zillow-browser-shims/document-contains.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* globals document, Element */ 4 | 5 | if (typeof document !== 'undefined' && !document.contains) { 6 | const shim = function contains(node) { 7 | /* eslint prefer-rest-params: 0, no-param-reassign: 0 */ 8 | if (arguments.length < 1) { 9 | throw new TypeError('1 argument is required'); 10 | } 11 | 12 | do { 13 | if (this === node) { 14 | return true; 15 | } 16 | if (node) { 17 | node = node.parentNode; 18 | } 19 | } while (node); 20 | 21 | return false; 22 | }; 23 | 24 | document.contains = shim; 25 | Element.prototype.contains = shim; 26 | } 27 | -------------------------------------------------------------------------------- /packages/zillow-browser-shims/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zillow-browser-shims", 3 | "version": "1.0.1", 4 | "description": "Browser and JS shims used by Zillow", 5 | "main": "zillow-browser-shims.js", 6 | "files": [ 7 | "browser-only.js", 8 | "document-contains.js", 9 | "zillow-browser-shims.js" 10 | ], 11 | "scripts": { 12 | "test": "echo \"Run tests from root\" && exit 1" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/zillow/javascript" 17 | }, 18 | "keywords": [ 19 | "shims", 20 | "polyfills" 21 | ], 22 | "author": "Daniel Stockman (https://twitter.com/@evocateur)", 23 | "license": "MIT", 24 | "homepage": "https://github.com/zillow/javascript/tree/latest/packages/zillow-browser-shims#readme", 25 | "engines": { 26 | "node": ">= 8.9.0" 27 | }, 28 | "dependencies": { 29 | "classlist-polyfill": "^1.2.0", 30 | "element-closest": "^2.0.2", 31 | "raf": "^3.4.0", 32 | "ric-shim": "^1.0.0", 33 | "smoothscroll-polyfill": "^0.4.3", 34 | "whatwg-fetch": "^2.0.4", 35 | "zillow-js-shims": "file:../zillow-js-shims" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/zillow-browser-shims/test/zillow-browser-shims.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* eslint-disable global-require */ 4 | 5 | test('zillow-browser-shims', () => { 6 | expect(() => require('..')).not.toThrow(); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/zillow-browser-shims/zillow-browser-shims.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('zillow-js-shims'); 4 | 5 | require('./browser-only'); 6 | -------------------------------------------------------------------------------- /packages/zillow-js-shims/CHANGELOG-upstream.md: -------------------------------------------------------------------------------- 1 | 1.4.1 / 2018-01-24 2 | ================= 3 | * [Docs] Promise.prototype.finally is at stage 4 4 | * [Deps] update `array.prototype.flatmap`, `array.prototype.flatten`, `es5-shim`, `function.prototype.name` 5 | * [Dev Deps] update `eslint` 6 | * [Tests] up to `node` `v9.4`; pin included builds to LTS 7 | 8 | 1.4.0 / 2017-11-29 9 | ================= 10 | * [New] add `Array.prototype.flat{ten,Map}`, now at stage 3 11 | * [Deps] update `promise.prototype.finally` 12 | * [Dev Deps] update `eslint`, `eslint-config-airbnb-base`, `eslint-plugin-import`, `tape` 13 | * [Tests] up to `node` `v9.2`, `v8.9`, `v6.12`; use `nvm install-latest-npm`; pin included builds to LTS 14 | 15 | 1.3.0 / 2017-07-28 16 | ================= 17 | * [New] add `promise.prototype.finally` shim, and ES2018 target 18 | * [Deps] update `function.prototype.name` 19 | * [Dev Deps] update `eslint`, `eslint-config-airbnb-base` 20 | 21 | 1.2.0 / 2017-07-14 22 | ================= 23 | * [New] add `Function#name` shim for IE 9-11 24 | * [Deps] update `array-includes`, `es6-shim`, `object.entries`, `object.values` 25 | * [Dev Deps] update `eslint`, `eslint-plugin-import`, `safe-publish-latest`, `tape`; switch to `eslint-config-airbnb-base` 26 | * [Tests] up to `node` `v8.1`, `v7.10`, `v6.11`, `v5.12`, `v4.8`; improve matrix; newer npms fail on older nodes 27 | * [Tests] ensure all target files parse 28 | 29 | 1.1.1 / 2017-02-16 30 | ================= 31 | * [Fix] Correctly require es2017 from es2016 32 | 33 | 1.1.0 / 2017-02-15 34 | ================= 35 | * [New] Add entry points for targeting specific ES versions 36 | 37 | 1.0.1 / 2016-08-17 38 | ================= 39 | * [Deps] update `es5-shim`, `es6-shim`, `object.getownpropertydescriptors` 40 | * [Dev Deps] update `tape` 41 | * [Docs] Update things that are now stage 4 42 | * [Tests] move tests into test dir 43 | * [Tests] add `npm run lint` 44 | 45 | 1.0.0 / 2016-03-24 46 | ================= 47 | * Initial release. 48 | -------------------------------------------------------------------------------- /packages/zillow-js-shims/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [1.1.0](https://github.com/zillow/javascript/compare/zillow-js-shims@1.0.0...zillow-js-shims@1.1.0) (2020-09-23) 7 | 8 | 9 | ### Features 10 | 11 | * **zillow-js-shims:** string.prototype.matchall@^4.0.2 ([e5ab699](https://github.com/zillow/javascript/commit/e5ab699519311c57073cb34a418ff6c3270357e3)) 12 | 13 | 14 | 15 | 16 | 17 | 18 | # [1.0.0](https://github.com/zillow/javascript/compare/zillow-js-shims@1.0.0-rc.0...zillow-js-shims@1.0.0) (2018-08-15) 19 | 20 | 21 | ### Bug Fixes 22 | 23 | * **pkg:** Correct homepage URL ([1b5e7f0](https://github.com/zillow/javascript/commit/1b5e7f0)) 24 | 25 | 26 | 27 | 28 | 29 | 30 | # [1.0.0-rc.0](https://github.com/zillow/javascript/compare/zillow-js-shims@1.0.0-alpha.1...zillow-js-shims@1.0.0-rc.0) (2018-06-05) 31 | 32 | 33 | ### Features 34 | 35 | * **js-shims:** Port airbnb-js-shims v1.6.0 changes ([9c11c1a](https://github.com/zillow/javascript/commit/9c11c1a)) 36 | 37 | 38 | 39 | 40 | 41 | 42 | # 1.0.0-alpha.1 (2018-04-10) 43 | 44 | 45 | ### Features 46 | 47 | * Fork airbnb-js-shims -> zillow-js-shims ([4a785a4](https://github.com/zillow/javascript/commit/4a785a4)) 48 | -------------------------------------------------------------------------------- /packages/zillow-js-shims/README.md: -------------------------------------------------------------------------------- 1 | # zillow-js-shims [![Version Badge][2]][1] 2 | 3 | > JS language shims used by Zillow 4 | 5 | Just require/import `zillow-js-shims`, and the environment will be shimmed. 6 | 7 | ```js 8 | import 'zillow-js-shims'; 9 | ``` 10 | 11 | ## Included shims 12 | 13 | - [es5-shim](https://www.npmjs.com/package/es5-shim) 14 | - [es5-sham](https://www.npmjs.com/package/es5-shim) 15 | - [es6-shim](https://www.npmjs.com/package/es6-shim) 16 | - [Function.prototype.name](https://www.npmjs.com/package/function.prototype.name) 17 | - [Array.prototype.includes](https://www.npmjs.com/package/array-includes) (ES7/ES2016) 18 | - [Object.entries](https://www.npmjs.com/package/object.entries) (ES8/ES2017) 19 | - [Object.values](https://www.npmjs.com/package/object.values) (ES8/ES2017) 20 | - [String.prototype.padStart](https://www.npmjs.com/package/string.prototype.padstart) (ES8/ES2017) 21 | - [String.prototype.padEnd](https://www.npmjs.com/package/string.prototype.padend) (ES8/ES2017) 22 | - [Promise.prototype.finally](https://npmjs.com/package/promise.prototype.finally) (Stage 4, ES2018) 23 | - [Array.prototype.flat](https://npmjs.com/package/array.prototype.flat) (Stage 3, ES2019 candidate) 24 | - [Array.prototype.flatMap](https://npmjs.com/package/array.prototype.flatMap) (Stage 3, ES2019 candidate) 25 | - [Symbol.prototype.description](https://npmjs.com/package/symbol.prototype.description) (Stage 3, ES2019 candidate) 26 | - [String.prototype.matchAll](https://npmjs.com/package/string.prototype.matchall) (Stage 3, ES2019 candidate) 27 | 28 | ## Targeting versions 29 | 30 | If you do not need to support older browsers, you can pick a subset of ES versions to target. For example, if you don't support pre-ES5 browsers, you can start your shims with ES2015 by requiring/importing the specific target file. This will shim the environment for that version and upward. 31 | 32 | ```js 33 | import 'zillow-js-shims/target/es2015'; 34 | ``` 35 | 36 | ### Included targets 37 | 38 | - `zillow-js-shims/target/es5` (default) 39 | - `zillow-js-shims/target/es2015` 40 | - `zillow-js-shims/target/es2016` 41 | - `zillow-js-shims/target/es2017` 42 | - `zillow-js-shims/target/es2018` 43 | - `zillow-js-shims/target/es2019` 44 | 45 | [1]: https://npmjs.org/package/zillow-js-shims 46 | [2]: http://versionbadg.es/zillow/js-shims.svg 47 | -------------------------------------------------------------------------------- /packages/zillow-js-shims/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zillow-js-shims", 3 | "version": "1.1.0", 4 | "description": "JS language shims used by Zillow", 5 | "main": "zillow-js-shims.js", 6 | "files": [ 7 | "target", 8 | "zillow-js-shims.js" 9 | ], 10 | "scripts": { 11 | "test": "echo \"Run tests from root\" && exit 1" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/zillow/javascript" 16 | }, 17 | "keywords": [ 18 | "shims", 19 | "polyfills" 20 | ], 21 | "author": "Daniel Stockman (https://twitter.com/@evocateur)", 22 | "license": "MIT", 23 | "homepage": "https://github.com/zillow/javascript/tree/latest/packages/zillow-js-shims#readme", 24 | "engines": { 25 | "node": ">= 8.9.0" 26 | }, 27 | "dependencies": { 28 | "array-includes": "^3.0.3", 29 | "array.prototype.flat": "^1.2.1", 30 | "array.prototype.flatmap": "^1.2.1", 31 | "es5-shim": "^4.5.10", 32 | "es6-shim": "^0.35.3", 33 | "function.prototype.name": "^1.1.0", 34 | "object.entries": "^1.0.4", 35 | "object.getownpropertydescriptors": "^2.0.3", 36 | "object.values": "^1.0.4", 37 | "promise.prototype.finally": "^3.1.0", 38 | "string.prototype.matchall": "^4.0.2", 39 | "string.prototype.padend": "^3.0.0", 40 | "string.prototype.padstart": "^3.0.0", 41 | "symbol.prototype.description": "^1.0.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/zillow-js-shims/target/es2015.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('es6-shim'); 4 | 5 | require('function.prototype.name/shim')(); 6 | 7 | require('./es2016'); 8 | -------------------------------------------------------------------------------- /packages/zillow-js-shims/target/es2016.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Array#includes is stage 4, in ES7/ES2016 4 | require('array-includes/shim')(); 5 | 6 | require('./es2017'); 7 | -------------------------------------------------------------------------------- /packages/zillow-js-shims/target/es2017.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Object.values/Object.entries are stage 4, in ES2017 4 | require('object.values/shim')(); 5 | require('object.entries/shim')(); 6 | 7 | // String#padStart/String#padEnd are stage 4, in ES2017 8 | require('string.prototype.padstart/shim')(); 9 | require('string.prototype.padend/shim')(); 10 | 11 | // Object.getOwnPropertyDescriptors is stage 4, in ES2017 12 | require('object.getownpropertydescriptors/shim')(); 13 | 14 | require('./es2018'); 15 | -------------------------------------------------------------------------------- /packages/zillow-js-shims/target/es2018.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | if (typeof Promise === 'function') { 4 | require('promise.prototype.finally/auto'); // eslint-disable-line global-require 5 | } 6 | 7 | require('./es2019'); 8 | -------------------------------------------------------------------------------- /packages/zillow-js-shims/target/es2019.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('array.prototype.flat/auto'); 4 | require('array.prototype.flatmap/auto'); 5 | 6 | require('symbol.prototype.description/auto'); 7 | 8 | require('string.prototype.matchall/auto'); 9 | -------------------------------------------------------------------------------- /packages/zillow-js-shims/target/es5.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('es5-shim'); 4 | require('es5-shim/es5-sham'); 5 | 6 | require('./es2015'); 7 | -------------------------------------------------------------------------------- /packages/zillow-js-shims/test/zillow-js-shims.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* eslint-disable global-require, import/no-dynamic-require */ 4 | 5 | const fs = require('fs'); 6 | const path = require('path'); 7 | 8 | test('main', () => { 9 | expect(() => require('..')).not.toThrow(); 10 | }); 11 | 12 | describe('target', () => { 13 | const targetsPath = path.join(__dirname, '../target'); 14 | const targets = fs.readdirSync(targetsPath); 15 | 16 | it.each(targets)('%s', target => { 17 | expect(() => require(path.join(targetsPath, target))).not.toThrow(); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/zillow-js-shims/zillow-js-shims.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('./target/es5'); 4 | --------------------------------------------------------------------------------