denvash / eslint-config

My default eslint-config

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

eslint-config

npm

My default ESLint configuration , pairs well with Prettier configuration.

Quick Start

Pre-commit + prettier + eslint for React project:

  1. Install deps

    yarn add -D @dennisvash/eslint-config eslint babel-eslint prettier eslint-config-prettier eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y lint-staged husky pretty-quick
  2. In .eslintrc:

    {
      "extends": "@dennisvash/eslint-config/react"
    }
  3. In package.json

    {
     "husky": {
       "hooks": {
         "pre-commit": "pretty-quick --staged && lint-staged"
       }
     },
     "lint-staged": {
       "*.js": [
         "eslint --fix",
         "prettier --write",
         "git add"
       ]
     }
    }

Default Config Installation

  1. Install all dependencies

      # npx
      npx install-peerdeps --dev @dennisvash/eslint-config
    
      # yarn
      yarn add --dev @dennisvash/eslint-config eslint babel-eslint prettier eslint-config-prettier
    
      # npm
      npm install --save-dev @dennisvash/eslint-config eslint babel-eslint prettier eslint-config-prettier

Configurations

Export four ESLint configurations for your usage:

  1. Default (2 space)
  2. Four Spaces
  3. React
  4. Vue

Default Config

In .eslintrc:

{
  "extends": "@dennisvash"
}

NOTE: Make sure to specify your environment based on your project

Four Spaces Config

Includes everything in the default config, but replaces the indent rule with 4 spaces instead of 2 spaces.

In your .eslintrc:

{
  "extends": "@dennisvash/eslint-config/four-spaces"
}

NOTE: Make sure to specify your environment based on your project

React Config

Includes everything in the default config, plus environment specification and react-specific rules with

Check Quick Start

Vue Config

Includes everything in the default config, plus environment specification and vue-specific rules with

npm install --save-dev @dennisvash/eslint-config eslint babel-eslint prettier eslint-config-prettier eslint-plugin-vue vue-eslint-parser

In your .eslintrc:

{
  "extends": "@dennisvash/eslint-config/vue"
}

Specifying Environments

For default & four spaces configs purposefully do not specify a certain environment as to not make any assumptions about your project. The only environment it specifies is es6. You can see all the default settings here.

Therefore, you should specify your project's environment yourself in your ESLint config. For example:

{
  "extends": "@dennisvash",
  "env": {
    "browser": true,
    "node": true
  }
}

View all available environments in the ESLint Docs

Editor Integration & Autoformatting

Once you've installed the config, you probably want your editor to lint and fix your code for you.

VS Code

  1. Install the ESLint extension: View → Extensions then find and install ESLint

  2. Reload the editor

  3. In your VS Code user settings Code/File → Preferences → Settings or CMD/CTRL + , click the {} icon in the top right corner to modify your settings.json file

    // Format on save with Prettier rules
    "editor.formatOnSave": true,
    // Turn it off for vue files, we will do this via ESLint
    "[vue]": {
      "editor.formatOnSave": false
    },
    "eslint.alwaysShowStatus": true,
    // Tell the ESLint plugin to run on save
    "eslint.autoFixOnSave": true,
    // An array of language identifiers specify the files to be validated
    "eslint.validate": [
      { "language": "html", "autoFix": true },
      { "language": "vue", "autoFix": true },
      { "language": "javascript", "autoFix": true },
      { "language": "javascriptreact", "autoFix": true }
    ],
    // Turn off prettier extension for js, jsx, and vue files since we're handling that with ESLint
    "prettier.disableLanguages": ["javascript", "javascriptreact", "vue"],

Sublime Text

  1. Install Package Control
  2. Install ESLint-Formatter
  3. And then allow auto fix on save: Preferences → Package Settings → ESLint Formatter → Settings then add "format_on_save": true to the settings file

Atom

  1. Install linter-eslint plugin: Preferences → Install then type and install linter-eslint
  2. Install all dependencies (and restart the editor couple of times during installation)
  3. Enable auto fix on save: Preferences → Packages → linter-eslint then check Fix errors on save checkbox

Pre-commit Hook

As another line of defense, if you want ESLint to automatically fix your errors on commit, you can use lint-staged with husky, which manages git hooks.

  1. npm install --save-dev lint-staged husky

  2. In your package.json:

    {
      "lint-staged": {
        "*.js": ["eslint --fix", "git add"]
      },
      "husky": {
        "hooks": {
          "pre-commit": "lint-staged"
        }
      }
    }

Overriding Rules

If you'd like to override any rules, you can add the rules to your .eslintrc file.

{
  "extends": "@dennisvash",
  "rules": {
    "no-console": "off"
  }
}

Publishing to npm

Read npm's docs on How to Update a Package.

  1. npm login
    • Make sure you're logged into npm account with the credentials from 1pass. npm whoami will tell you if you're already logged in.
  2. npm version <update_type>
    • update_type can be patch, minor, or major. If you don't know which one to use, read up about semantic versioning.
  3. npm publish

Enforced Rules

Mine ESLint config extends eslint:recommended which enables rules that report common problems, which are marked with check marks in the large list of ESLint rules.

The rules listed below are rules we have enabled on top of those enabled by eslint:recommended.

no-console

It's perfectly fine to use console.log during development, but you shouldn't use console.log in production code. If you really need to print something to the console, use console.warn or console.error.

Why? In JavaScript that's designed to be executed in the browser, it’s considered a best practice to avoid using methods on console. Such messages are considered to be for debugging purposes and therefore not suitable to ship to the client. In general, calls using console should be stripped before being pushed to production.

// bad
console.log("bad");

// good
console.warn("Log a warn level message.");
console.error("Log an error level message.");
curly

Always use curly braces.

Why? Omitting curly braces can cause bugs and decrease code clarity.

// bad
if (foo) foo++;

if (foo) {
  baz();
} else qux();

// good
if (foo) {
  foo++;
}

if (foo) {
  baz();
} else {
  qux();
}
eqeqeq

Use === and !== over == and !=.

Why? It's considered good practice to use the type-safe equality operators === and !== instead of their regular counterparts == and !=. The reason for this is that == and != do type coercion which follows the rather obscure Abstract Equality Comparison Algorithm. For instance, the following statements are all considered true:

  • [] == false
  • [] == ![]
  • 3 == 03

TL;DR JavaScript is WILD

// bad
a == b;
foo == true;
bananas != 1;
value == undefined;
typeof foo == "undefined";

// good
a === b;
foo === true;
bananas !== 1;
value === undefined;
typeof foo === "undefined";
no-eq-null

Don't write null comparisons without type-checking operators.

Why? Comparing to null without a type-checking operator (== or !=), can have unintended results as the comparison will evaluate to true when comparing to not just a null, but also an undefined value.

// bad
if (foo == null) {
  bar();
}

while (qux != null) {
  baz();
}

// good
if (foo === null) {
  bar();
}

while (qux !== null) {
  baz();
}
no-use-before-define

Don't use constiables before they are defined.

Why? In JavaScript, prior to ES6, constiable and function declarations are hoisted to the top of a scope, so it’s possible to use identifiers before their formal declarations in code. This can be confusing and some believe it is best to always declare constiables and functions before using them. In ES6, block-level bindings (let and const) introduce a “temporal dead zone” where a ReferenceError will be thrown with any attempt to access the constiable before its declaration.

// bad
alert(a);
const a = 10;

f();
function f() {}

// good
let a;
a = 10;
alert(a);

function f() {}
f(1);
brace-style

Be consistent with brace style for blocks. Keep else on the same line as the preceding curly brace.

// bad
if (foo) {
  bar();
} else {
  baz();
}

// good
if (foo) {
  bar();
} else {
  baz();
}
comma-dangle

Use trailing commas when possible.

Why? Trailing commas simplify adding and removing items to objects and arrays, since only the lines you are modifying must be touched. They improve the clarity of diffs when an item is added or removed from an object or array.

// bad
const foo = {
  bar: baz,
  qux: quux
};

const arr = [1, 2];

// good
const foo = {
  bar: baz,
  qux: quux
};

const arr = [1, 2];
comma-spacing

Put spaces after commas. Don't put spaces before commas.

// bad
const foo = 1,
  bar = 2;
const arr = [1, 2];
const obj = { foo: bar, baz: qur };
foo(a, b);

// good
const foo = 1,
  bar = 2;
const arr = [1, 2];
const obj = { foo: bar, baz: qur };
foo(a, b);
comma-style

Commas should come after and on the same line as an array element, object property, or constiable declaration.

// bad
const foo = 1,
  bar = 2;

const foo = 1,
  bar = 2;

const foo = ["apples", "oranges"];

function bar() {
  return {
    a: 1,
    b: 2
  };
}

// good
const foo = 1,
  bar = 2;

const foo = ["apples", "oranges"];

function bar() {
  return {
    a: 1,
    b: 2
  };
}
func-call-spacing

Don't add a space between a function name and the opening parenthesis.

// bad
fn();

// good
fn();
indent

This ESLint config defaults to 2 space indentation.

Why? The general convention within the JavaScript community is 2 spaces, and ESLint is a "pluggable linting utility for JavaScript and JSX". We could debate 2 spaces vs 4 spaces all day long, so that's why we've provided another configuration for 4 spaces.

// bad
if (a) {
  b = c;
  function foo(d) {
    e = f;
  }
}

// good
if (a) {
  b = c;
  function foo(d) {
    e = f;
  }
}
key-spacing

Use consistent spacing between keys and values in object literals. Use a space after the colon and disallows a space before the colon.

// bad
const obj = { foo: 42 };
const obj = { foo: 42 };

// good
const obj = { foo: 42 };
keyword-spacing

Use consistent spacing before and after keywords. Use at least one space before and after keywords.

// bad
if (foo) {
  //...
} else if (bar) {
  //...
} else {
  //...
}

// good
if (foo) {
  //...
} else if (bar) {
  //...
} else {
  //...
}
object-curly-spacing

Use a space inside of braces (except {})

// bad
const obj = { foo: "bar" };
const obj = { foo: "bar" };
const obj = { foo: "bar" };
const { x } = y;
import { foo } from "bar";

// good
const obj = {};
const obj = { foo: "bar" };
const obj = {
  foo: "bar"
};
const { x } = y;
import { foo } from "bar";
one-const

Use multiple constiable declarations per scope.

Why? It simplifies adding and removing constiables, since only the lines you are modifying must be touched. It improves the clarity of diffs when a constiable is added to a scope.

// bad
function foo() {
  let bar, baz;
  const bar = true,
    baz = false;
}

// good
function foo() {
  let bar;
  let baz;
  const bar = true;
  const baz = false;
}
quotes

Use single quotes wherever possible. Use backticks with template literals.

// bad
const double = double;
const unescaped = 'a string containing "double" quotes';

// good
const single = "single";
const backtick = `back${x}tick`;
semi

Use semicolons at the end of statements.

Why? When JavaScript encounters a line break without a semicolon, it uses a set of rules called Automatic Semicolon Insertion to determine whether or not it should regard that line break as the end of a statement, and (as the name implies) place a semicolon into your code before the line break if it thinks so. ASI contains a few eccentric behaviors, though, and your code will break if JavaScript misinterprets your line break. These rules will become more complicated as new features become a part of JavaScript. Explicitly terminating your statements and configuring your linter to catch missing semicolons will help prevent you from encountering issues.

// bad
const name = "ESLint";
let object = {};

object.method = function() {
  // ...
};

// good
const name = "ESLint";
let object = {};

object.method = function() {
  // ...
};
space-before-function-paren

Don't put a space before the ( of arguments.

// bad
function foo() {
  // ...
}

const bar = function() {
  // ...
};

// good
function foo() {
  // ...
}

const bar = function() {
  // ...
};
space-infix-ops

Put spaces around infix operators.

// bad
a + b;

a + b;

a ? b : c;

const a = { b: 1 };

// good
a + b;

a ? b : c;

const a = { b: 1 };
arrow-body-style

Disallow the use of braces around arrow function body as needed. One-liners can be more readable!

// bad
let foo = () => {
  return 0;
};
let foo = () => {
  return {
    bar: {
      foo: 1,
      bar: 2
    }
  };
};

// good
let foo = () => 0;
let foo = (retv, name) => {
  retv[name] = true;
  return retv;
};
let foo = () => ({
  bar: {
    foo: 1,
    bar: 2
  }
});
arrow-parens

Omit parens when there is only one argument. Unnecessary parens make code less readable.

// bad
a => {};
a => a;
a => {
  "\n";
};
a.then(foo => {});
a.then(foo => a);
a(foo => {
  if (true) {
  }
});

// good
() => {};
a => {};
a => a;
() => {
  "\n";
};
arrow-spacing

Put spaces before and after an arrow function’s arrow.

// bad
() => {};
() => {};
a => {};
a => {};

// good
() => {};
a => {};
a => a;
() => {
  "\n";
};
no-duplicate-imports

All imports from a single module should exist in a single import statement.

// bad
import { merge } from "module";
import something from "another-module";
import { find } from "module";

// good
import { merge, find } from "module";
import something from "another-module";
no-useless-constructor

Don't include useless class constructors that can be safely removed without changing how the class works.

// bad
class A {
  constructor() {}
}

class A extends B {
  constructor(...args) {
    super(...args);
  }
}

// good

class A {
  constructor() {
    doSomething();
  }
}

class A extends B {
  constructor() {
    super("foo");
  }
}
no-var

Use let or const instead of var.

Why? ECMAScript 6 allows programmers to create constiables with block scope instead of function scope using the let and const keywords.

// bad
var x = y;
var CONFIG = {};

// good
let x = y;
const CONFIG = {};
prefer-const

Use const instead of let when a constiable is never reassigned.

Why? If a constiable is never reassigned, using the const declaration is better. const declaration tells readers, “this constiable is never reassigned,” reducing cognitive load and improving maintainability.

// bad

// it's initialized and never reassigned.
let a = 3;
console.log(a);

let a;
a = 0;
console.log(a);

// good

// it's reassigned after initialized.
let a;
a = 0;
a = 1;
console.log(a);

// it's initialized in a different block from the declaration.
let a;
if (true) {
  a = 0;
}
console.log(a);
prefer-template

Use template literals instead of string concatenation.

// bad
const str = "Hello," + name + "!";
const str = "Time: " + 12 * 60 * 60 * 1000;

// good
const str = "Hello World!";
const str = `Hello, ${name}!`;
const str = `Time: ${12 * 60 * 60 * 1000}`;

About

My default eslint-config


Languages

Language:JavaScript 100.0%