IMPORTANT: This project was moved to my packages
monorepo and is now being published as @homer0/eslint-plugin
.
eslint-plugin-homer0

My custom configurations for ESLint
Motivation
Let's start with... I LOVE ESLint and I use it on every project.
Together with ESLint, I use the Airbnb's plugin, eslint-plugin-import
and eslint-plugin-node
.
Everything is great, but...I'm always overwriting the same rules, and every time one the packages mentioned above is released, I have to go and update every single project.
So, I decided to make my own plugin, with the configurations I use.
Usage
Just include the plugin and extend
from the configuration you want to use:
{
"root": true,
"plugins": ["homer0"],
"extends": ["plugin:homer0/node"]
}
Available configurations
There are a few different configurations that can be used, dependending on the project and/or the scope:
Node
This is a basic configuration for Node that extends from plugin:node/recommended
.
Name: plugin:homer0/node
Browser
This extends the base rules and disables a few ones from the import
plugin, as most of the browser code I wrote goes through transpilation, so there's no need to validate production/development dependencies.
Name: plugin:homer0/browser
Jest
Jest is my favorite tool for testing, so all my projects (with test) use it. This configuration not only changes the environment to jest
but it also disables a few rules from the import
plugin. In this case, the reason for the disabled rules is that I also use (my own) jest-ex
, which allows the use of absolute paths (that reference the root of the project).
Name: plugin:homer0/jest
JSDoc
I'm a big fan of documenting EVERY class, method/function, property, etc; so this configuration helps me validate that all my comments are valid JSDoc.
Name: plugin:homer0/jsdoc
Rules
Here's a list of the rules I modified and the reason I did it:
Best practices
off
-> warn
.
I want the linter to warn me if I'm writing big function/methods.
error
-> off
I write almost everything using OOP, and some times I want to create a method to extract some logic and I don't want to be restricted by this rule.
off
-> ['error', { ignore: [0, 1, -1, 60, 1000]}]
I like self explanatory code, and magic numbers get in the way of that. The reason I left those 4 "ignore cases" is because...
0
and 1
: To work with arrays. Examples: To check if an array is empty or not, and to check if an array has a single element or more.
-1
: To work with indexOf
.
60
and 1000
: To work with timestamps.
Now, this rule is disabled on the jest
config, as it's not uncommon to use random numbers for "fake data" or to check calls with .toHaveBeenCalledTimes()
.
['error', {...}]
-> error
I don't believe this is a good practice (as explained by the rule) and I prefer having to add an exception in the cases I need to use instead of having a lot of exceptions by default.
off
-> error
No idea why do they disabled this rule, it's a great help to avoid infinite loops.
off
-> error
I haven't use call
or apply
for years now, as I believe that with ES6 you can cover 99% of the cases in which they were useful. Now, I enabled this rule because if I can't prevent their use, I want to make it as restricted as possible.
error
-> off
Not all the time, but I use regular expressions quite a lot, and I have found cases in which this rule is unnecessarily triggered.
Node
off
-> ['error', '^(err|error|\\w+Error)$']
I consider error handling a "required good practice" on every project.
error
-> off
You can't tell ESLint which part of the project is tooling for development and which part is for production, and I don't want to have to create different directories with other .eslintrc
for this... at least for now.
off
-> error
It helps to organize the code a little bit.
off
-> error
No, I'm not crazy and is not that I don't use process.env
. The reason I enabled this rule is because I think environment variables should be consumed on a single place, instead of reading them all over the project.
Instead of having the rule disable for all files, I prefer writing the "disable comment" on a single file.
error
-> off
I don't get how this rule works...it gets triggered for some packages that comply with all the requirements a "published package" must have.
error
-> off
This is because is not unusual for me to write .sh
or extension-less files with the Node shebang...which triggers the rule.
Style
off
-> ['error', 'consistent']
Consistency.
['error', 2, {...}]
-> ['error', 2, {..., MemberExpression: 0 }]
I don't like to indent when there's really no need for it:
something()
.then(() => ...);
something()
.then(() => ...);
['error', {...}]
-> off
Most of the times, I write JSDoc block comments between methods, and I consider that is enough "separation".
off
-> ['error', { max: 1 }]
Readability
error
-> off
Yes, the reason for having this rule enabled is valid, but I don't believe that's a very common case.
['error', {
allow: [],
allowAfterThis: false,
allowAfterSuper: false,
enforceInMethodNames: true,
}]
->
['error', {
allowAfterThis: true,
allowAfterSuper: true,
enforceInMethodNames: false,
}]
Since I don't use TypeScript, I follow the convention of prefixing protected/private property/methods with underscore.
['error', 'before', {...}]
-> ['error', 'after', {...}]
I know that having the operators at the beginning of the line may better for readability for some people, but in my case, I find it easier to read if they are at the end. Yes, I may be that I've been using it like this for years.
JSDoc
These are not overwrites, the plugin I use doesn't have a default preset, so I'm just going to explain why did enabled each rule and what values they have.
'error'
Since most of the things I write are classes, I use the @access
tag a lot, and this rule is more about protecting you from typos and invalid values than a restriction.
'error'
It's not uncommon for IDEs/editors to "auto align" JSDoc blocks when you copy them and mess the alignment of the asterisks.
['error', { allowExtraTrailingParamDocs: true }]
This is a big helper for when you update a function/method signature, you won't forget to update the JSDoc block.
The allowExtraTrailingParamDocs
option is enabled so you won't get errors when documenting parameters for abstract methods.
'error'
It helps you prevent duplicated properties and avoid incomplete declarations.
'error'
Helps avoid invalid syntax.
['error', {
definedTags: ['parent'],
}]
This rule prevents the use of invalid JSDoc tags; the definedTags
is used to add the following exceptions:
parent
: I use it as an alias of memberof
to be able use module:
and avoid issues with the plugin. I transform it to memberof
using the jsdoc-ts-utils
when generating the JSDoc site.
'error'
Helps with consistency as it forces you to always use the same casing for native types.
'error'
The @implements
tag should only be used on classes.
'error'
Consistency.
'error'
The block looks better with a little padding.
['error', { checkConstructors: false }]
Everything should have a description.
The checkConstructors
option is to avoid comments like "class constructor".
'error'
All descriptions should formatted as sentences.
['error', 'never']
I never used, and I don't like, hyphens as separators on JSDoc blocks.
['error', {
require: {
allowAfterThis: true,
ArrowFunctionExpression: true,
ClassDeclaration: true,
ClassExpression: true,
FunctionDeclaration: true,
MethodDefinition: true,
},
exemptEmptyConstructors: true,
}]
EVERYTHING should be documented!
The require
option is so the rule will be applied to all available contexts, and exemptEmptyConstructors
is so it will skip constructors with no pameters.
'error'
Yes, every parameter should be documented.
'error'
Yes, every parameter should have a human-readable description.
'error'
I'm still not sure why this rule even exists, it should be part of jsdoc/require-param
.
'error'
Of course every parameter should have its type documented.
'error'
The type Object
is like the any
on TypeScript, it doesn't say anything; if you are going to use it, you should documented the properties too.
'error'
Yes, every property should have a human-readable description.
'error'
Like jsdoc/require-param-name
, this shouldn't exist.
'error'
Yes, the types should be documented.
'error'
Yes, the @returns
tag is as importan as @param
.
'error'
I like this rule because is not that it validates the comments based on the code, but it's the other way around: if you use @returns
, the function/method should have a return
(it's only logical).
'error'
Yes, if there's a @returns
, it should have a type
.
'error'
This helps a lot when writing error handling code.
'error'
Prevents invalid definitions.
Development
NPM/Yarn Tasks
lint | Lint the modified files. |
lint:all | Lint the project code. |
todo | List all the pending to-do's. |
Repository hooks
I use husky
to automatically install the repository hooks so the code will be tested and linted before any commit and the dependencies updated after every merge.
The configuration is on the husky
property of the package.json
and the hooks' files are on ./utils/hooks
.
Commits convention
I use conventional commits with commitizen
in order to support semantic releases. The one that sets it up is actually husky, that installs a script that runs commitizen on the git commit
command.
The hook for this is on ./utils/hooks/prepare-commit-msg
and the configuration for comitizen is on the config.commitizen
property of the package.json
.