Airtame eslint configuration
An Airtame approach to Javascript and React
This config is inspired by Airbnb's Javascript and React styleguides with an Airtame touch and the help of Prettier for styling.
Usage
Install as a development dependency to your project
$ yarn add --dev eslint-config-airtame
or
$ npm install --save-dev eslint-config-airtame
Then, on your eslint
configuration file
If using prettier extension on your text editor, the following options are necessary
"eslintIntegration": true,
"printWidth": 100,
"trailingComma": "es5",
"singleQuote": true
Rules
camelcase
Use camelCase when naming objects, functions, and instances.
// badconst OBJEcttsssss = {};const this_is_my_object = {}; {} // goodconst thisIsMyObject = {}; {}
curly
Always use curly brackets, even when doing single line blocks.
// badif foo foo++; while bar ; if foo ; else ; // goodif foo foo++; while bar ; if foo ; else ;
dot-notation
Use dot notation when accessing properties, unless they are variables.
const luke = jedi: true age: 28; // badconst isJedi = luke'jedi'; // goodconst isJedi = lukejedi; { return lukeprop;} const isJedi = ;
eqeqeq
Prefer ===
and !==
over ==
and !=
to guarantee proper comparisons.
// badif x == 5 console; if x != 5 console; // goodif x === 5 console; if x !== 5 console;
import/default
Make sure that there is an export
for every import
in the file.
Given
// ./foo.js { return 42 } // ./bar.js { return null } // ./baz.jsmodule { /* ... */ } // node_modules/some-module/index.jsexports { /* ... */ }
Expect
// bad
// good // assuming 'node_modules' are ignored (true by default)
import/export
Only allow valid exports.
// bad /*...*/ // Multiple default exports. { return ...arguments } // Multiple default exports.
// also badconst foo = { /*...*/ } // Multiple exports of name 'foo'. { /*...*/ }
import/first
Ensure all imports appear before any other statements.
// bad // some module-level initializer
// good // some module-level initializer
import/no-unresolved
Ensures an imported module can be resolved to a module. This includes CommonJS and AMD modules.
import/named
Ensure named imports correspond to a named export in the remote file.
Given
// ./foo.jsconst foo = "I'm so foo"
Expect
// bad// ./baz.js
// good
import/namespace
Ensure named imports correspond to a named export in the remote file.
Given
// @module ./named-exportsconst a = 1const b = 2 const c = 3
and
// @module ./deepconst e = "MC2"
Expect
// good// @module ./foo { return namesa + namesb // so great https://youtu.be/ei7mb8UxEl8} { // Reported: 'c' not found in imported namespace 'names'. const a b c = names // also reported, only for 'c'} // also tunnels through re-exported namespaces! { // fine // Reported: 'f' not found in deeply imported namespace 'names.deep'.}
import/no-mutable-exports
Forbid the use of mutable exports with var
or let
.
// badlet count = 2var count = 3 let count = 4 // goodconst count = 1 {} {}
import/no-webpack-loader-syntax
Forbid Webpack loader syntax in imports to avoid dependency on a bundler.
// bad;; var myModule = ;var theme = ; // good;; var myModule = ;var theme = ;
import/prefer-default-export
Prefer a default export if module exports a single name
// bad.js // There is only a single module export and it's a named export.const foo = 'foo';
// good1.js // There is a default export.const foo = 'foo';const bar = 'bar'; 'bar';
// good2.js // There is more than one named export in the module.const foo = 'foo';const bar = 'bar';
// good3.js // There is more than one named export in the moduleconst foo = 'foo';const bar = 'bar';
// good4.js // There is a default export.const foo = 'foo';
// export-star.js // Any batch export will disable this rule. The remote module is not inspected.
jsx-a11y/aria-role
Enforce that elements with ARIA roles must use a valid, non-abstract ARIA role.
// bad<div role="datepicker"></div><div role="range"></div><div role=""></div> // good<div role="button"></div><div role=role></div><div></div>
jsx-a11y/alt-text
Make sure all images have the alt
prop
// bad
<img {...props} />
// good
<img alt="Airtame logo" {...props} />
jsx-a11y/img-redundant-alt
Make sure alt
props don't contain image or picture as part of it, as screen readers already call this out.
// bad<img src="foo" alt="Photo of foo being weird." /> // good<img src="foo" alt="Foo eating a sandwich." />
jsx-a11y/no-access-key
Do not use the accessKey
prop.
Why? Inconsistencies between keyboard shortcuts and keyboard commands used by people using screenreaders and keyboards complicate accessibility.
// bad<div accessKey="h" /> // good<div />
max-len
Each line of code should be no longer than 100 characters
new-cap
Only use PascalCase to name classes or constructors
// bad { thisname = optionsname;} const bad = name: 'nope'; // good { thisname = optionsname; } const good = name: 'yup';
no-alert
Alerts are thrown as warnings to allow debugging. Make sure to remove before deployment.
no-array-constructor
Use literal syntax for array creation.
// badconst items = ; // goodconst items = ;
no-case-declarations
Use braces to create blocks in case and default clauses that contain lexical declarations (e.g. let
, const
, function
, and class
).
Why? Lexical declarations are visible in the entire switch block but only get initialized when assigned, which only happens when its case is reached. This causes problems when multiple case clauses attempt to define the same thing.
// bad // good
no-cond-assign
Prevent variable assignments in conditions
// badif foo = 5 // stuff
no-confusing-arrow
Avoid confusing arrow function syntax (=>
) with comparison operators (<=
, >=
).
// badconst itemHeight = itemheight > 256 ? itemlargeSize : itemsmallSize; // badconst itemHeight = itemheight > 256 ? itemlargeSize : itemsmallSize; // goodconst itemHeight = itemheight > 256 ? itemlargeSize : itemsmallSize; // goodconst itemHeight = { const height largeSize smallSize = item; return height > 256 ? largeSize : smallSize;};
no-console
Console logs are thrown as warnings to allow debugging. Make sure to remove before deployment.
no-dupe-class-members
Avoid duplicate class members.
Why? Duplicate class member declarations will silently prefer the last one - having duplicates is almost certainly a bug.
// bad { return 1; } { return 2; } // good { return 1; } // good { return 2; }
no-duplicate-imports
Only import a path once per file
Why? Having multiple lines that import from the same path can make code harder to maintain.
// bad;// … some other imports … //; // good; // good;
no-empty
Do not write empty blocks of code
// bad if foo while foo try ; catchex finally // goodif foo // empty
no-iterator
Do not use iterators like for-in
and for-of
Why? This enforces the immutable rule. Dealing with pure functions that return values is easier to reason about than side effects.
// badlet sum = 0;for let num of numbers sum += num;sum === 15; // goodlet sum = 0;numbers;sum === 15;
no-loop-func
Never declare a function in a non-function block (if, while, etc). Assign the function to a variable instead.
Why? Browsers will allow you to do it, but they all interpret it differently.
// badfor var i=10; i; i-- { return i; }; // goodvar {}; for var i=10; i; i-- ;
no-multiple-empty-lines
Do not add more empty lines than needed
// badvar foo = 5; var bar = 3; // goodvar biz = 2; { ...}
no-multi-spaces
Do not use more than one space between identifiers unless it's for indentation
// badiffoo === "bar" {} // goodif foo === "bar" {}
no-nested-ternary
Ternaries should not be nested and generally be single line expressions, unless it's inside JSX
// badconst foo = maybe1 > maybe2 ? "bar" : value1 > value2 ? "baz" : null; // betterconst maybeNull = value1 > value2 ? 'baz' : null; const foo = maybe1 > maybe2 ? 'bar' : maybeNull; // bestconst maybeNull = value1 > value2 ? 'baz' : null; const foo = maybe1 > maybe2 ? 'bar' : maybeNull;
no-new-func
Never use the Function constructor to create a new function.
Why? Creating a function in this way evaluates a string similarly to eval(), which opens vulnerabilities.
// badvar add = 'a' 'b' 'return a + b'; // still badvar subtract = Function'a' 'b' 'return a - b'; // goodconst multiply = { return a * b };
no-new-object
Use the literal object syntax for object creation
// badconst item = ; // goodconst item = {};
no-param-reassign
Do not reasign the value of you're parameters. This usually means you're creating some unwanted behavior
// bad { bar = bar * 5; return bar;} // good { return bar * 5;}
no-plusplus
Avoid using ++
and --
Why? Per the eslint documentation, unary increment and decrement statements are subject to automatic semicolon insertion and can cause silent errors with incrementing or decrementing values within an application. It is also more expressive to mutate your values with statements like
num += 1
instead ofnum++
ornum ++
. Disallowing unary increment and decrement statements also prevents you from pre-incrementing/pre-decrementing values unintentionally which can also cause unexpected behavior in your programs.
// bada++; // gooda += 1;
no-restricted-syntax
See no-iterator
no-throw-literal
Only throw valid errors as part of a throw
.
// badthrow "error"; throw 0; throw undefined; throw null; // goodthrow ; throw "error";
no-undef
Make sure all variables are defined. Use let
or const
to define your variables.
// bada = 5; // goodlet b = 5;const x = 10;
no-unneeded-ternary
Only used a ternary when it's necessary and not for implicit conditions
// badconst foo = a ? a : b;const bar = c ? true : false;const baz = c ? false : true; // goodconst foo = a || b;const bar = !!c;const baz = !c;
no-unused-vars
All declared variables must be used. Otherwise the variable shouldn't exist;
// badvar x = 5;... // goodvar y = 5;;
no-useless-constructor
Classes have a default constructor if one is not specified, which means an empty constructor is not necessary
// bad {} { return thisname; } // bad { super...args; } // good { super...args; thisname = 'Rey'; }
no-useless-escape
Only escape characters that need to be escaped
Why? Backslashes harm readability, thus they should only be present when necessary.
// badconst foo = '\'this\' \i\s \"quoted\"'; // goodconst foo = '\'this\' is "quoted"';const foo = `my name is ''`;
no-var
Never use var
. Use let
or const
instead.
Why?
let
is block-scoped rather than function-scoped likevar
.
// badvar x = 5; // goodlet y = 5;
object-shorthand
Use object shorthand notation when possible.
// bad { let awesome = bar; return awesome: awesome } // good { let awesome = bar; return awesome;}
one-var
Declare each variable individually
Why? Readability
// badvar foo bar biz; // good;let foo;let bar;let biz;
prefer-arrow-callback
User arrow functions for your callbacks
Why? It creates a version of the function that executes in the context of
this,
which is usually what you want, and is a more concise syntax.
// bad1 2 3; // good1 2 3;
prefer-const
If your variable is never reassigned, use const
instead of let
prefer-rest-params
Never use arguments
, opt to use rest syntax ...
instead
Why?
...
is explicit about which arguments you want pulled. Plus, rest arguments are a real Array, and not merely Array-like likearguments
.
// bad { const args = Arrayprototypeslice; return args;} // good { return args;}
prefer-spread
Prefer the use of the spread operator ...
to call variadic functions.
// badconst x = 1 2 3 4 5;consolelog; // goodconst x = 1 2 3 4 5;console; // badnew Functionprototypebind; // good...2016 8 5;
prefer-template
Use template strings instead of doing string concatenation
let age = 10; // badconst greeting = 'Mary is ' + age + ' years old'; // goodconst greeting2 = `Tim is also years old`;
radix
Always set the radix when using parseInt()
// badvar num = ; // 57 // goodvar num = ; // 71
react/jsx-boolean-value
Do not set explicit value for boolean JSX attributes.
// bad<Component disabled=true /> // good<Component disabled />
react/jsx-no-bind
Never use bind in the render
function. Arrow functions are allowed.
// bad { return <Component onClick=thismyMethod /> ;} // good { super; thismyMethod = thismyMethod;} { return <div> <Component onClick=thismyMethod /> <Component onClick= { this } /> </div> ;}
react/jsx-pascal-case
Use pascal case for your component names
// badComponent ... // goodComponent
react/jsx-tag-spacing
Always use a space before a self closing tag.
// bad<Component/> // good<Component />
react/jsx-uses-react
Prevents React from being marked as unused
react/jsx-uses-vars
Prevent variables used in JSX to be incorrectly marked as unused
react/no-is-mounted
Prevents the use of the isMounted lifecycle method
Why? isMounted is an anti-pattern, is not available when using ES6 classes, and is on its way to being officially deprecated.
react/no-multi-comp
Write only one React component per file, unless they are Stateless components
react/no-string-refs
Always use ref callbacks
Why? String callbacks will be deprecated in future versions of React
// badvar Hello = React; // goodComponent { super; var component = thishello; } { // ...do something with component } { return <div ref= { thishello = c; }>Hello world</div>; }
react/prefer-es6-class
Write react components using ES6 Class vs React.createClass
// badconst Listing = React; // goodComponent // ... { return <div>thisstatehello</div>; }
react/prefer-stateless-function
Use stateless functions when possibles
// badComponent { return <div className=thispropsclassName>Hello World</div> } // goodconst ComponentThatOnlyRenders = { return <div className=propsclassName>Hello World</div> ;}
react/require-render-return
Always return a value in the render
function
// bad { <div />;} // good { return <div />;}
react/self-closing-comp
Always self close Components that have no children
// bad<Foo className="stuff"></Foo> // good<Foo className="stuff" />
require-jsdoc
Always include JSDoc documentation for all your methods and functions
// bad { return a + b;} // good /** * Multiplies to values * @param * @param * @return */ { return a * b;}
spaced-comment
Always add a space after your comments
Why? Readability
// bad //my comment/*my comment*/ // good// My comment/** * My block comment */ /****************************** * A pretty block comment * ******************************/
valid-jsdoc
Ensure your JSDoc is valid and all parameters and your return are documented
// bad { var y; // do stuff return y;} /** * This is function foo */ { var y; // do stuff return y;} /** * This is function foo * @param */ { var y; // do stuff return y;} // good /** * This is function foo * @param * @param * @return */ { var y; // do stuff return y;}