Photo by Markus Spiske on Unsplash

Why not Prettier ?

Prettier is a well-known solution to enforce a consistent coding style along a project. It can address things like rewriting code where lines are over 80 characters, handling trailing commas or semicolons, …

ESLint, as a linter, implement rules ensuring code quality, helping developers to avoid mistakes which could often have an impact during the code transpilation or execution. But as a rewriting/formatting system, it is a lot more powerful than that, and also has code formatting rules like Prettier.

And Prettier, as a very opinionated tool, has very few options you can configurate. So if You are also very opiniated about how to format your code, there is a big conflict.

In this article, I’ll list and explain how to quickly replace Prettier rules by equivalent ESLint rules, to then allow you to really fit the styling to your needs.

I know than Prettier is opiniated by design :

By far the biggest reason for adopting Prettier is to stop all the on-going debates over styles.

But coming from Python, and “formatted” to follow what we’re calling the PEP8, which describe common Python Code Styling, the more important rule for me is the following :

So, when Prettier rewrite the code to ensure the 80 characters line length replacing some local consistency, wisely choosen for a particular piece of code, it is a hobgoblin.

For example, this code …

{ message &&

<Text style={styles.message}>{message}</Text>

}

{ confirmationMessage &&

<Text style={styles.message}>{confirmationMessage}</Text>

}

became …

{message && <Text style={styles.message}>{message}</Text>}

{confirmationMessage && (

<Text style={styles.message}>{confirmationMessage}</Text>

)}

Seriously ?! … I don’t want a tool just rewriting code this way because it is “too long”. I wan’t a smarter tool. Because I think consistency is more important, for developer experience and for maintainability, than a lot of other things.

And ESLint rules allow this type of “smarter” configuration.

From Prettier to ESLint

Line length, spacing style and size

[Prettier] Print Width can be replaced by [ESLint] Max-Len rule :

max-len: ["error", { "code": 80 }]

And the ESLint rule can be tuned in various ways, for example to allow different length for comments.

Space / Tabs consistency

[Prettier] Tabs & [Prettier] Tab Width can be replaced by [ESLint] Indent :

indent: ["error", 2]

Consistency along a file can be enforced with [ESLint] No-mixed-spaces-and-tabs.

And these ESLint rules have options to specify indentation for specific situations, like the case when dealing with a switch , like the ability to use smartTabs to align items vertically in some cases, …

Semicolons

[Prettier] Semicolons can be replaced by [ESLint] Semi :

semi: ["error", "always"]

Quotes

[Prettier] Quotes and [Prettier] JSX Quotes can be replaced by [ESLint] Quotes :

quotes: ["error", "double"]

ESLint options allow to also choose backticks, or to use single quotes when possible, and fallback on double quotes to avoid escaping, …

Trailing commas

[Prettier] Trailing Commas can be replaced by [ESLint] Comma-dangle :

comma-dangle: ["error", "never"]

Here, the rule can be tuned to enfore more or less strongly the trailing commas, and to choose wich elements should have a trailing commas, to achieve the same as es5 or all Prettier’s parameter.

Spacing consistency

[Prettier] Bracket Spacing can be replaced by [ESLint] Object-curly-spacing :

object-curly-spacing: ["error", "always"]

But it also exists [ESLint] Array-bracket-spacing and [ESLint] Space-in-parens to configure spaces in arrays and parenthesis, or [ESLint] comma-spacing for … commas !

The options allow to specifically tune spaces for nested brackets, nested arrays in brackets, …

JSX Brackets position

[Prettier] JSX Brackets can be replaced by [ESLint/React] Jsx-closing-bracket-location which is part of eslint-plugin-react :

react/jsx-closing-bracket-location: [1, "ligne-aligned"]

It exists other positions, like always after the props, or aligned with the open tag.

Of course, the plugin also have a lot of other rules available.

Arrow function parentheses

[Prettier] Arrow Function Parentheses can be replaced by [ESLint] Arrow-parens :

arrow-parens: ["error", "as-needed"]

An option is available to always use parenthesis only for arrow functions with a “block” body (with curly brackets).

[ESLint] Arrow-body-style let you set the body style of arrow functions.

End of lines

[Prettier] End of Line is almost equivalent to [ESLint] Linebreak-style but this last one doesn’t have an “auto” mode like Prettier. So the “closest” behaviour is to disable the rule :

linebreak-style: 0

Specific parser

[Prettier] Parser is not really a rule, but can be configured in ESLint parser options.

Files to format

[Prettier] File Path can be achieved with ESLint configuration or CLI parameters, and honestly, ESLint documentation is more obvious and clear than Prettier one so it allows a lot more.

The options not available (or not easily) in ESLint

Complete rewriting : as a “linter”, ESLint is more focused in “warning” you when something goes wrong, than rewriting. So some rules doesn’t have an automatic resolution when using eslint --fix . For example

. For example [Prettier] Range allows to format a segment of the files, only. As I know, ESLint doesn’t have a configuration to do that “out-of-the-box”, but maybe a plugin could do the job

[Prettier] Require pragma & [Prettier] Insert Pragma are probably the Prettier feature which are missing the most in ESLint, because it allows to “softly” migrate a code base. But, as ESLint is more configurable, you can achieve the same thing with overrides and with turning errors into warnings

[Prettier] Prose Wrap is a “markdown” specific rule, and I don’t know an equivalent in ESLint. Maybe something is achievable with overrides and [ESLint] No trailing space

[Prettier] HTML Whitespace Sensitivity is not addressed by ESLint, as I know. I use the following trick when it happens (which is not so ugly in an IDE, configured to color HTML comments in a soft color) :

<div><!--

-->Ne se dici quod cognatione inter vinculum <!--

-->dici disciplina dici disciplina nos dici <!--

-->nos quod in alia disciplina disciplina <!--

-->cognatione nobis dicendi nobis disciplina <!--

-->uni habent artes ne artes et uni aut quae <!--

-->huic continentur ratio et ita dicendi studio.

</div>

[Prettier] End of Line : pay attention to the absence of “auto” mode, event if I think nowadays, it should not be a problem to enforce lf in most of the projects.

TLDR & Disclaimer

As I am not a big fan of prettier, I don’t used to have it formatting my code, so I can’t ensure the given ESLint rules are exactly achieving the same formatting than Prettier. But I think it give you a good start to break your chains.

rules: {

"max-len": ["error", { code: 80 }],

"indent": ["error", 2],

"semi": ["error", "always"],

"quotes": ["error", "double"],

"comma-dangle": ["error", "never"],

"object-curly-spacing": ["error", "always"],

"react/jsx-closing-bracket-location": [1, "line-aligned"],

"arrow-parens": ["error", "as-needed"],

"linebreak-style": 0,

}

If you have any suggestions, improvements, plugins, please comment !