eslint-config-airtame

3.0.1 • Public • Published

Airtame eslint configuration

Build Status npm version David Greenkeeper badge

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

{
  "extends": "airtame"
}

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.

// bad
const OBJEcttsssss = {};
const this_is_my_object = {};
function c() {}
 
// good
const thisIsMyObject = {};
function thisIsMyFunction() {}

curly

Always use curly brackets, even when doing single line blocks.

// bad
if (foo) foo++;
 
while (bar)
    baz();
 
if (foo) {
    baz();
} else qux();
 
// good
if (foo) {
    foo++;
}
 
while (bar) {
    baz();
}
 
if (foo) {
    baz();
} else {
    qux();
}

dot-notation

Use dot notation when accessing properties, unless they are variables.

const luke = {
  jedi: true,
  age: 28,
};
 
// bad
const isJedi = luke['jedi'];
 
// good
const isJedi = luke.jedi;
 
function getProp(prop) {
  return luke[prop];
}
 
const isJedi = getProp('jedi');

eqeqeq

Prefer === and !== over == and != to guarantee proper comparisons.

// bad
if (== 5) {
  console.log(x);
}
 
if (!= 5) {
  console.log(x);
}
 
// good
if (=== 5) {
  console.log(x);
}
 
if (!== 5) {
  console.log(x);
}

import/default

Make sure that there is an export for every import in the file.

Given

// ./foo.js
export default function () { return 42 }
 
// ./bar.js
export function bar() { return null }
 
// ./baz.js
module.exports = function () { /* ... */ }
 
// node_modules/some-module/index.js
exports.sharedFunction = function shared() { /* ... */ }

Expect

// bad
import bar from './bar' // no default export found in ./bar
import baz from './baz' // no default export found in ./baz
// good
import foo from './foo'
 
// assuming 'node_modules' are ignored (true by default)
import someModule from 'some-module'

import/export

Only allow valid exports.

// bad
export default class MyClass { /*...*/ } // Multiple default exports.
 
function makeClass() { return new MyClass(...arguments) }
 
export default makeClass // Multiple default exports.
// also bad
export const foo = function () { /*...*/ } // Multiple exports of name 'foo'.
 
function bar() { /*...*/ }
export { bar as foo } // Multiple exports of name 'foo'.

import/first

Ensure all imports appear before any other statements.

// bad
import foo from './foo'
 
// some module-level initializer
initWith(foo)
 
import bar from './bar'
// good
import foo from './foo'
import bar from './bar'
 
// some module-level initializer
initWith(foo)

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.js
export const foo = "I'm so foo"

Expect

// bad
// ./baz.js
import { notFoo } from './foo'
// good
import { foo } from './foo'

import/namespace

Ensure named imports correspond to a named export in the remote file.

Given

// @module ./named-exports
export const a = 1
const b = 2
export { b }
 
const c = 3
export { c as d }
 
export class ExportedClass { }

and

// @module ./deep
export const e = "MC2"

Expect

// good
// @module ./foo
import * as names from './named-exports'
 
function great() {
  return names.a + names.b  // so great https://youtu.be/ei7mb8UxEl8
}
 
function notGreat() {
  doSomethingWith(names.c) // Reported: 'c' not found in imported namespace 'names'.
 
  const { a, b, c } = names // also reported, only for 'c'
}
 
// also tunnels through re-exported namespaces!
function deepTrouble() {
  doSomethingWith(names.deep.e) // fine
  doSomethingWith(names.deep.f) // Reported: 'f' not found in deeply imported namespace 'names.deep'.
}

import/no-mutable-exports

Forbid the use of mutable exports with var or let.

// bad
export let count = 2
export var count = 3
 
let count = 4
export { count }
 
// good
export const count = 1
export function getCount() {}
export class Counter {}

import/no-webpack-loader-syntax

Forbid Webpack loader syntax in imports to avoid dependency on a bundler.

// bad
import myModule from 'my-loader!my-module';
import theme from 'style!css!./theme.css';
 
var myModule = require('my-loader!./my-module');
var theme = require('style!css!./theme.css');
 
// good
import myModule from 'my-module';
import theme from './theme.css';
 
var myModule = require('my-module');
var theme = require('./theme.css');

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.
export const foo = 'foo';
// good1.js
 
// There is a default export.
export const foo = 'foo';
const bar = 'bar';
export default 'bar';
// good2.js
 
// There is more than one named export in the module.
export const foo = 'foo';
export const bar = 'bar';
// good3.js
 
// There is more than one named export in the module
const foo = 'foo';
const bar = 'bar';
export { foo, bar }
// good4.js
 
// There is a default export.
const foo = 'foo';
export { foo as default }
// export-star.js
 
// Any batch export will disable this rule. The remote module is not inspected.
export * from './other-module'

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
function user(options) {
  this.name = options.name;
}
 
const bad = new user({
  name: 'nope',
});
 
// good
class User {
  constructor(options) {
    this.name = options.name;
  }
}
 
const good = new User({
  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.

// bad
const items = new Array();
 
// good
const 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
switch (foo) {
  case 1:
    let x = 1;
    break;
  case 2:
    const y = 2;
    break;
  default:
    class C {}
}
 
// good
switch (foo) {
  case 1: {
    let x = 1;
    break;
  }
  case 2: {
    const y = 2;
    break;
  }
  case 4:
    bar();
    break;
  default: {
    class C {}
  }
}

no-cond-assign

Prevent variable assignments in conditions

// bad
if (foo = 5) {
  // stuff
}

no-confusing-arrow

Avoid confusing arrow function syntax (=>) with comparison operators (<=, >=).

// bad
const itemHeight = item => item.height > 256 ? item.largeSize : item.smallSize;
 
// bad
const itemHeight = (item) => item.height > 256 ? item.largeSize : item.smallSize;
 
// good
const itemHeight = item => (item.height > 256 ? item.largeSize : item.smallSize);
 
// good
const itemHeight = (item) => {
  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
class Foo {
  bar() { return 1; }
  bar() { return 2; }
}
 
// good
class Foo {
  bar() { return 1; }
}
 
// good
class Foo {
  bar() { 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
import foo from 'foo';
// … some other imports … //
import { named1, named2 } from 'foo';
 
// good
import foo, { named1, named2 } from 'foo';
 
// good
import foo, {
  named1,
  named2,
} from 'foo';

no-empty

Do not write empty blocks of code

// bad
 
if (foo) {
}
 
while (foo) {
}
 
switch(foo) {
}
 
try {
    doSomething();
} catch(ex) {
 
} finally {
 
}
 
// good
if (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.

// bad
let sum = 0;
for (let num of numbers) {
  sum += num;
}
sum === 15;
 
// good
let sum = 0;
numbers.forEach(num => sum += num);
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.

// bad
for (var i=10; i; i--) {
    (function() { return i; })();
}
 
// good
var a = function() {};
 
for (var i=10; i; i--) {
    a();
}

no-multiple-empty-lines

Do not add more empty lines than needed

// bad
var foo = 5;
 
 
 
var bar = 3;
 
// good
var biz = 2;
 
function foo() {
  ...
}

no-multi-spaces

Do not use more than one space between identifiers unless it's for indentation

// bad
if(foo  === "bar") {}
 
 
// good
if (foo === "bar") {}

no-nested-ternary

Ternaries should not be nested and generally be single line expressions, unless it's inside JSX

// bad
const foo = maybe1 > maybe2
  ? "bar"
  : value1 > value2 ? "baz" : null;
 
// better
const maybeNull = value1 > value2 ? 'baz' : null;
 
const foo = maybe1 > maybe2
  ? 'bar'
  : maybeNull;
 
// best
const 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.

// bad
var add = new Function('a', 'b', 'return a + b');
 
// still bad
var subtract = Function('a', 'b', 'return a - b');
 
// good
const multiply = function(a, b) { return a * b };

no-new-object

Use the literal object syntax for object creation

// bad
const item = new Object();
 
// good
const item = {};

no-param-reassign

Do not reasign the value of you're parameters. This usually means you're creating some unwanted behavior

// bad
function foo(bar) {
  bar = bar * 5;
  return bar;
}
 
// good
function foo(bar) {
  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 of num++ or num ++. 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.

// bad
a++;
 
// good
+= 1;

no-restricted-syntax

See no-iterator

no-throw-literal

Only throw valid errors as part of a throw.

// bad
throw "error";
 
throw 0;
 
throw undefined;
 
throw null;
 
// good
throw new Error();
 
throw new Error("error");

no-undef

Make sure all variables are defined. Use let or const to define your variables.

// bad
= 5;
 
// good
let b = 5;
const x = 10;

no-unneeded-ternary

Only used a ternary when it's necessary and not for implicit conditions

// bad
const foo = a ? a : b;
const bar = c ? true : false;
const baz = c ? false : true;
 
// good
const foo = a || b;
const bar = !!c;
const baz = !c;

no-unused-vars

All declared variables must be used. Otherwise the variable shouldn't exist;

// bad
var x = 5;
...
 
// good
var y = 5;
myFunctionCall(y);

no-useless-constructor

Classes have a default constructor if one is not specified, which means an empty constructor is not necessary

// bad
class Jedi {
  constructor() {}
 
  getName() {
    return this.name;
  }
}
 
// bad
class Rey extends Jedi {
  constructor(...args) {
    super(...args);
  }
}
 
// good
class Rey extends Jedi {
  constructor(...args) {
    super(...args);
    this.name = 'Rey';
  }
}

no-useless-escape

Only escape characters that need to be escaped

Why? Backslashes harm readability, thus they should only be present when necessary.

// bad
const foo = '\'this\' \i\s \"quoted\"';
 
// good
const foo = '\'this\' is "quoted"';
const foo = `my name is '${name}'`;

no-var

Never use var. Use let or const instead.

Why? let is block-scoped rather than function-scoped like var.

// bad
var x = 5;
 
// good
let y = 5;

object-shorthand

Use object shorthand notation when possible.

// bad
function foo(bar) {
  let awesome = bar;
  return {
    awesome: awesome
  }
}
 
// good
function biz(bar) {
  let awesome = bar;
  return {awesome};
}

one-var

Declare each variable individually

Why? Readability

// bad
var 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.

// bad
[1, 2, 3].map(function (x) {
  const y = x + 1;
  return x * y;
});
 
// good
[1, 2, 3].map((x) => {
  const y = x + 1;
  return x * y;
});

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 like arguments.

// bad
function concatenateAll() {
  const args = Array.prototype.slice.call(arguments);
  return args.join('');
}
 
// good
function concatenateAll(...args) {
  return args.join('');
}

prefer-spread

Prefer the use of the spread operator ... to call variadic functions.

// bad
const x = [1, 2, 3, 4, 5];
console.log.apply(console, x);
 
// good
const x = [1, 2, 3, 4, 5];
console.log(...x);
 
// bad
new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]));
 
// good
new Date(...[2016, 8, 5]);

prefer-template

Use template strings instead of doing string concatenation

let age = 10;
 
// bad
const greeting = 'Mary is ' + age + ' years old';
 
// good
const greeting2 = `Tim is also ${age} years old`;

radix

Always set the radix when using parseInt()

// bad
var num = parseInt("071");      // 57
 
// good
var num = parseInt("071", 10);  // 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
render() {
  return (
    <Component onClick={this.myMethod.bind(this)} />
  );
}
 
// good
constructor() {
  super();
 
  this.myMethod = this.myMethod.bind(this);
}
 
render() {
  return (
    <div>
      <Component onClick={this.myMethod} />
      <Component onClick={(evt) => { this.myMethod(evt) }} />
    </div>
  );
}

react/jsx-pascal-case

Use pascal case for your component names

// bad
class myComponent extends React.Component {
  ...
}
 
// good
class MyComponent extends React.Component {
 
}

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

// bad
var Hello = React.createClass({
 render: function() {
  return <div ref="hello">Hello, world.</div>;
 }
});
 
// good
class Hello extends React.Component {
  constructor() {
 
  super();
    var component = this.hello;
  }
 
  myMethod() {
    // ...do something with component
  }
 
  render() {
    return <div ref={(c) => { this.hello = c; }}>Hello, world.</div>;
  }
}

react/prefer-es6-class

Write react components using ES6 Class vs React.createClass

// bad
const Listing = React.createClass({
  // ...
  render() {
    return <div>{this.state.hello}</div>;
  }
});
 
// good
class Listing extends React.Component {
  // ...
  render() {
    return <div>{this.state.hello}</div>;
  }
}

react/prefer-stateless-function

Use stateless functions when possibles

// bad
class ComponentThatOnlyRenders extends React.Component {
  render() {
    return (
      <div className={this.props.className}>Hello World</div>
    )
  }
}
 
// good
const ComponentThatOnlyRenders = function(props) {
  return (
    <div className={props.className}>Hello World</div>
  );
}

react/require-render-return

Always return a value in the render function

// bad
render() {
  (<div />);
}
 
// good
render() {
  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
function add(a, b) {
  return a + b;
}
 
// good
 
/**
 * Multiplies to values
 * @param  {number} a The first number to be multiplied
 * @param  {number} b The second number to be multiplied
 * @return {number}   The result of the multiplication
 */
function multiply(a, b) {
  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
function foo (bar, biz) {
  var y;
  // do stuff
  return y;
}
 
/**
 * This is function foo
 */
function foo (bar, biz) {
  var y;
  // do stuff
  return y;
}
 
/**
 * This is function foo
 * @param {number} foo - Only one parameter explained and no return is bad
 */
function foo (bar, biz) {
  var y;
  // do stuff
  return y;
}
 
// good
 
/**
 * This is function foo
 * @param  {number} foo - description of first param
 * @param  {number} bar - description of second param
 * @return {number} Description of the return
 */
function foo (bar, biz) {
  var y;
  // do stuff
  return y;
}

Package Sidebar

Install

npm i eslint-config-airtame

Weekly Downloads

1

Version

3.0.1

License

MIT

Last publish

Collaborators

  • mmellado