This package provides Atomix's base .eslintrc config for ECMAScript 2017.
Our config bases on Airbnb's eslint config and Unicorn by Sindre Sorhus.
Installation:
npm install --save-dev eslint babel-eslint eslint-config-atomix-baseCreate .eslintrc:
{
"extends": "atomix-base",
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 2017
}
}Add test script to your package.json "test": "eslint src lib bin"
If you don't want es2017 features:
npm install --save-dev eslint eslint-config-atomix-base{
"extends": "atomix-base"
}Config extends airbnb-base and plugin:unicorn/recommended.
https://eslint.org/docs/rules/strict
Disable strict mode. You can manually enable it if required.
{ ignoreRestSiblings: false }https://eslint.org/docs/rules/no-unused-vars
Unused variables/functions/classes should be removed or commented.
https://eslint.org/docs/rules/semi
We don't write semicolons at each line. Only when needed.
https://eslint.org/docs/rules/no-confusing-arrow
Really? You can be confused with?
const x = (a) => 1 ? 2 : 3https://eslint.org/docs/rules/object-property-newline https://eslint.org/docs/rules/object-curly-newline https://eslint.org/docs/rules/object-curly-spacing
Disabled because broken
https://eslint.org/docs/rules/arrow-parens
As defined in Airbnb JS CodeStyle arrow parens should only for block body.
But when you add more params for lambda, you should add parens. Example:
-.map(value => rotate(value, 1))
+.map((value, index) => rotate(value, 1 - index))It provides inconsistency.
// Good
() => {};
(a) => {};
(a) => a;
(a) => {'\n'}
a.then((foo) => {});
a.then((foo) => { if (true) {} });
const foo = (bar, baz) => ({ bar: baz })
const bar = ({ bar }) => bar.baz
const baz = (example) => {
return 1
}// Bad
() => {};
a => {};
a => a;
a => {'\n'}
a.then(foo => {});
a.then(foo => { if (true) {} });
const foo = (bar, baz) => ({ bar: baz })
const bar = ({ bar }) => bar.baz
const baz = example => {
return 1
}{
properties: false,
onlyDeclarations: true,
}https://eslint.org/docs/rules/id-match
All identifiers should be camelCased and more that 2 symbols length. Constants can be SCREAMING_UNDERSCORED
// Good
let value = 1
const functionDummy = (argument) => {}
const CONSTANT_NAME = 123
class ExampleName {}// Bad
const Value = 1
const function_dummy = (MySuper_Argument) => {}
const constant_NAME = 1
class example_CLASS_name {}{
ignore: [1, 0, -1],
ignoreArrayIndexes: true,
enforceConst: true,
detectObjects: false,
}https://eslint.org/docs/rules/no-magic-numbers
Magic numbers is not descriptive. Please name it.
Exclude: 1, 0, -1, array indexes, object of numbers.
// Good
const TAX = 1.28
const Coeff = {
A: 0.924,
B: 0.759,
C: 0.552,
V: 0.308,
Z: 0.116,
}
const val = myList[5]
const prev = myList[val.next - 1]{
arrays: 'always-multiline',
objects: 'always-multiline',
imports: 'always-multiline',
functions: 'ignore',
}https://eslint.org/docs/rules/comma-dangle
Not all environments supports comma dangle in function call/definition.
{
overrides: {
'?': 'before',
':': 'before',
'&&': 'before',
'+': 'before',
'||': 'before',
},
}https://eslint.org/docs/rules/operator-linebreak
We like write idented code and readable code in any line width.
// Good
const foo = condition
? firstResult
: second + result
const demo = Foo.first
|| Foo.second
|| 'default value'
// Bad
const foo = condition ?
firstResult :
second + result
const demo = Foo.first ||
Foo.second ||
'default value'https://eslint.org/docs/rules/brace-style
Because, 1tbs is so dirty.
// Good
function Demo(argument) {
if (argument && argument.chained) {
try {
const result = Target.actionCall(argument, -1)
while (!result.active) {
result.status.to((status) => status + argument.value)
}
return result
.map((value) => value.resolver((res) => res[result.name]))
}
catch (error) {
return Target.chainCall(() => Target.wrapWith(argument, error))
}
}
else if (argument) {
const value = Target.wrap(argument)
try {
return value
.resolver((res) => value.getProp(res))
.map((value) => value.head())
}
catch (error) {
const rawValue = value.chain(Target.useRawSource)
return Target.chainCall(() => Target.wrapWith(rawValue, error))
}
}
else {
const defaultValue = Target.wrap(Target.null())
return defaultValue
.resolver((res) => null)
.map((value) => Target.useRawSource(null).value())
.chain((fut) => fut.status.to((status) => 0))
}
}
// Bad
function Demo(argument) {
if (argument && argument.chained) {
try {
const result = Target.actionCall(argument, -1)
while (!result.active) {
result.status.to((status) => status + argument.value)
}
return result
.map((value) => value.resolver((res) => res[result.name]))
} catch (error) {
return Target.chainCall(() => Target.wrapWith(argument, error))
}
} else if (argument) {
const value = Target.wrap(argument)
try {
return value
.resolver((res) => value.getProp(res))
.map((value) => value.head())
} catch (error) {
const rawValue = value.chain(Target.useRawSource)
return Target.chainCall(() => Target.wrapWith(rawValue, error))
}
} else {
const defaultValue = Target.wrap(Target.null())
return defaultValue
.resolver((res) => null)
.map((value) => Target.useRawSource(null).value())
.chain((fut) => fut.status.to((status) => 0))
}
}https://eslint.org/docs/rules/quote-props
Use quotes only if needed.
// Good
const foo = {
demo: 1,
'foo-bar': 2,
bar: {
lock: 4
},
baz: 3,
}
// Bad
const baz = {
'demo': 1,
'foo-bar': 2,
'bar': {
'lock': 4
},
'baz': 3,
}https://eslint.org/docs/rules/no-plusplus
We use it, because it good shorthand for some cases.
{ exceptAfterSingleLine: true }https://eslint.org/docs/rules/lines-between-class-members
Add lines between class methods/properties.
Example:
class Foo {
id = 1
name = 'Foo'
constructor() {
// code
}
toString() { /* single line */ }
member() {
// code
}
}https://eslint.org/docs/rules/implicit-arrow-linebreak
Implicit return in arrow function should be on same line.
Correct:
const foo = () => 1
const bar = () => (
2
)
const baz = () => {
const val = 3
return 3
}Incorrect:
const foo = () =>
1
const bar = () =>
(
2
)
const baz = () =>
() =>
3{ blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' },
{ blankLine: 'any', prev: ['const', 'let', 'var'], next: ['const', 'let', 'var'] },https://eslint.org/docs/rules/padding-line-between-statements
Add padding line after let, const definitions.
Correct:
const foo = 1
const bar = 2
runFunc(foo, bar)Incorrect:
const foo = 1
const bar = 2
runFunc(foo, bar)https://eslint.org/docs/rules/no-await-in-loop
In Node.js LTS await in loop is native and optimized.
Enabled in react
https://eslint.org/docs/rules/no-restricted-syntax
In node.js we want to use "await in for" without Futures.
https://github.com/airbnb/javascript#iterators--nope
Enabled in react
Because some projects use aliases or module resolvers.
But you can configure module resolver for eslint and enable it rule in your config.
always for: json, json5, less, css, scss, sass, styl, jpeg, jpg, png, svg, bmp, gif
Node, webpack, rollup not require .js in file path by default.
{
groups: [
['builtin', 'external'],
['internal', 'parent'],
['sibling', 'index'],
],
'newlines-between': 'ignore',
}https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/order.md
Prefer order of your imports. To correct resolving internal and external modules configure module resolver.
{ count: 2 }We separate our imports with main code with 2 empty lines.
Use named exports to resolve naming problem.
With default export you can implicitly rename import binding. And your import not found in search by project.
// foo.js
export default class Foo {}
// bar.js
import SomeAnyName from './foo'With named import you explicitly rename import binding.
// foo.js
export class Foo {}
// bar.js
import { Foo as SomeAnyName } from './foo'Rule is not resolving param-case naming of the files.
import FooBar from './foo-bar' // Correct import. But not solved by rule{ name: 'error' }Variable names like e, err, er is so short. Name should be comprehensive like error.
Disabled, because we like functional programming and we check all changelogs before update dependencies.
Disabled, because we like more descriptive paths.