Most elemental code formatting for Typescript/Javascript: .editorconfig vs prettier
Tags: editorconfig, prettier, format, linting
Published: 2024-04-18 06:10:43

# Context

When working on Javascript/Typescript projects probably most of us know the following;
- [eslint](https://eslint.org/) is used to avoid code errors
- [prettier](https://prettier.io/) is used to format you text

# Enter editorconfig

These are tools that you need to add. But the most elemental code formatting is not here, it is in the widely supported [.editorconfig](https://editorconfig.org/) file.

You can generate such a file with this command:

```sh
npx editorconfig-cli init -y
```
It is basically an `ini` file 

```ini
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 100
quote_type = single
```
The best thing is that your code editor or IDE will recognise this file automatically and formats your code per this `.editorconfig` file by default, or there is a plugin. 

# IDE support for prettier and editorconfig

- Visual Studio Code (VSC) uses a [plugin](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig)
- Vim uses a [plugin](https://github.com/editorconfig/editorconfig-vim)
- Nvim supports this by [default](https://neovim.io/doc/user/editorconfig.html)
- IntelliJ IDEA uses a [plugin](https://www.jetbrains.com/help/idea/editorconfig.html)
- Sublime uses a [plugin](https://packagecontrol.io/packages/EditorConfig)
- Atom uses a [plugin](https://github.com/sindresorhus/atom-editorconfig)

In table format:

| Editor/IDE         | Prettier Support                                         | .editorconfig Support                                             |
|--------------------|----------------------------------------------------------|--------------------------------------------------------------------|
| Visual Studio Code | ✅ [Plugin](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) | ☑️ [Plugin](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) |
| Vim                | ☑️ [Plugin](https://github.com/prettier/vim-prettier)      | ☑️ [Plugin](https://github.com/editorconfig/editorconfig-vim)        |
| Nvim               | ✅ [Default](https://prettier.io/docs/en/vim-plugin.html)  | ✅ [Native](https://neovim.io/doc/user/editorconfig.html)             |
| IntelliJ IDEA      | ☑️ [Plugin](https://plugins.jetbrains.com/plugin/10456-prettier) | ☑️ [Plugin](https://www.jetbrains.com/help/idea/editorconfig.html)   |
| Sublime Text       | ☑️ [Plugin](https://packagecontrol.io/packages/JsPrettier) | ☑️ [Plugin](https://packagecontrol.io/packages/EditorConfig)         |
| Atom               | ☑️ [Plugin](https://github.com/prettier/prettier-atom)      | ☑️ [Plugin](https://github.com/sindresorhus/atom-editorconfig)       |
| Emacs              | ☑️ [Plugin](https://github.com/prettier/prettier-emacs)     | ✅ [Plugin](https://github.com/editorconfig/editorconfig-emacs)      |
| PyCharm            | ☑️ [Plugin](https://plugins.jetbrains.com/plugin/10456-prettier) | ☑️ [Plugin](https://www.jetbrains.com/help/idea/editorconfig.html)   |
| Eclipse            | ☑️ [Plugin](https://github.com/prettier/prettier-eclipse)   | ☑️ [Plugin](https://marketplace.eclipse.org/content/editorconfig-eclipse) |
| Notepad++          | ☑️ [Plugin](https://github.com/prettier/prettier-notepad-plus-plus) | ☑️ [Plugin](https://github.com/editorconfig/editorconfig-notepad-plus-plus) |
| Brackets           | ☑️ [Plugin](https://github.com/prettier/prettier-brackets) | ☑️ [Plugin](https://github.com/kidwm/brackets-editorconfig)         |
| WebStorm           | ☑️ [Plugin](https://plugins.jetbrains.com/plugin/10456-prettier) | ☑️ [Plugin](https://www.jetbrains.com/help/idea/editorconfig.html)   |
| PyCharm            | ☑️ [Plugin](https://plugins.jetbrains.com/plugin/10456-prettier) | ☑️ [Plugin](https://www.jetbrains.com/help/idea/editorconfig.html)   |
| Eclipse            | ☑️ [Plugin](https://github.com/prettier/prettier-eclipse)   | ☑️ [Plugin](https://marketplace.eclipse.org/content/editorconfig-eclipse) |
| Notepad++          | ☑️ [Plugin](https://github.com/prettier/prettier-notepad-plus-plus) | ☑️ [Plugin](https://github.com/editorconfig/editorconfig-notepad-plus-plus) |

And if you want to include these rules in linting locally or in the pipeline, even [prettier supports it](https://prettier.io/docs/en/configuration.html#editorconfig)!

I give you one better; usually I keep prettier settings like this `.prettierrc` (or even better, stick it in `package.json`'s prettier value):

```json
{
  "singleQuote": true,
  "printWidth": 140,
  "tabWidth": 2,
  "useTabs": false
}
```

But you can go [all-out](https://www.boag.online/notepad/post/full-prettier-prettierrc-config) if you want. The important thing is that there is a huge overlap with `.editorconfig`:

# Prettier and editorconfig feature comparison

| Feature          | Prettier Setting         | .editorconfig Setting | Description                                                       |
|------------------|--------------------------|------------------------|-------------------------------------------------------------------|
| Indent Style     | `useTabs: true`          | `indent_style = tab`   | Use tabs for indentation.                                         |
|                  | `useTabs: false`         | `indent_style = space` | Use spaces for indentation.                                       |
| Indent Size      | `tabWidth: N`            | `indent_size = N`      | Number of spaces or tabs for indentation.                         |
| Line Length      | `printWidth: N`          | `max_line_length = N`  | Maximum line length.                                              |
| Newline Style    | `endOfLine: lf`          | `end_of_line = lf`     | Use LF for line endings.                                          |
|                  | `endOfLine: crlf`        | `end_of_line = crlf`   | Use CRLF for line endings.                                        |
|                  | `endOfLine: cr`          | `end_of_line = cr`     | Use CR for line endings (rarely used).                            |
| Trailing Spaces  | `trailingComma: none`    | `trim_trailing_whitespace = true` | Remove trailing whitespaces.                                      |
|                  | `trailingComma: es5`     |                        | Add trailing commas where valid in ES5 syntax.                    |
|                  | `trailingComma: all`     |                        | Add trailing commas in all places (arrays, objects, etc.).        |
| Tabs or Spaces   |                          | `insert_final_newline = true` | Insert a final newline at the end of files.                        |
| Quote Style      | `singleQuote: true`      |                        | Use single quotes.                                                |
|                  | `singleQuote: false`     |                        | Use double quotes.                                                |
| Experimental     | `singleAttributePerLine` |                        | Experimental feature: format single attributes per line.         |
| Arrow Function   | `arrowParens: avoid`     |                        | Avoid parentheses around a sole arrow function parameter.         |
|                  | `arrowParens: always`    |                        | Always include parentheses around arrow function parameters.      |
| Tab Width        | `tabWidth: N`            |                        | Number of spaces per tab.                                         |
| Semicolons       | `semi: true`             |                        | Use semicolons.                                                   |
|                  | `semi: false`            |                        | Omit semicolons.                                                  |
| JSX Quotes       | `jsxSingleQuote: true`   |                        | Use single quotes in JSX.                                         |
|                  | `jsxSingleQuote: false`  |                        | Use double quotes in JSX.                                         |
| Bracket Spacing  | `bracketSpacing: true`   |                        | Include spaces between brackets in object literals.               |
|                  | `bracketSpacing: false`  |                        | Exclude spaces between brackets in object literals.               |
| Prose Wrap       | `proseWrap: always`      |                        | Wrap prose text in Markdown or HTML as necessary.                 |
|                  | `proseWrap: never`       |                        | Do not wrap prose text.                                           |
|                  | `proseWrap: preserve`    |                        | Preserve existing line breaks.                                    |
| Tab Preferences  |                          | `tab_width = N`        | Number of spaces per tab when using spaces.                       |
| File Encoding    |                          | `charset = utf-8`      | File character encoding.                                          |
| Root Indicator   |                          | `root = true`          | Marks the directory as the root for `.editorconfig` settings.     |

# Lab - funny discovery

1. I have a repo with no `.prettierrc`
2. I run `npx prettier . --write`; I see some changes in the files; e.g. strings are now double quoted, breaks up lines > 80 chars etc. Very nice. 
2. I generate a clean default `.editorconfig` using `npx editorconfig-cli init -y`
3. Without any configuration of prettier, when I run `npx prettier . --write` again....
   it respects the `quote_type` = single and `max_line_length` *from the .editorconfig* ＼ ٩( ᐛ )و /／ ʕ•̫͡•ʕ*̫͡*ʕ•͓͡•ʔ-̫͡-ʕ•̫͡•ʔ*̫͡*ʔ-̫͡-ʔ 

My point is, why have a `.prettierrc` file at all when all settings can be in `.editorconfig` and still use prettier? At least you won't have conflicting settings. `.editorconfig` file needs to be there anyway [because you can't stick it in package.json](https://github.com/editorconfig/editorconfig-core-js/issues/30) like you can do with prettier:

```json
{
  "scripts": {},
  "prettier": {
    "semi": false,
    "singleQuote": false,
    "trailingComma": "all"
  } 
}
```

Which is a huge win IMHO, however prettier is considered scoped within Node/Typescript/Javascript ecosystem, where editorconfig is more widely supported:

# Language support prettier vs editorconfig

Consider the current top 25 languages supported by Prettier and .editorconfig:

| Language         | Prettier Support     | .editorconfig Support |
|------------------|----------------------|-----------------------|
| JavaScript       | ✅                    | ✅                     |
| TypeScript       | ✅                    | ✅                     |
| HTML             | ✅                    | ✅                     |
| CSS              | ✅                    | ✅                     |
| SCSS             | ✅                    | ✅                     |
| JSON             | ✅                    | ✅                     |
| Markdown         | ✅                    | ✅                     |
| YAML             | ✅                    | ✅                     |
| XML              | ✅                    | ✅                     |
| Python           | ❌                    | ✅                     |
| Java             | ❌                    | ✅                     |
| C                | ❌                    | ✅                     |
| C++              | ❌                    | ✅                     |
| C#               | ❌                    | ✅                     |
| Ruby             | ❌                    | ✅                     |
| PHP              | ❌                    | ✅                     |
| Go               | ❌                    | ✅                     |
| Kotlin           | ❌                    | ✅                     |
| Swift            | ❌                    | ✅                     |
| Rust             | ❌                    | ✅                     |
| Dart             | ✅                    | ✅                     |
| Lua              | ❌                    | ✅                     |
| Groovy           | ❌                    | ✅                     |
| SQL              | ❌                    | ✅                     |
| Shell scripts    | ✅                    | ✅                     |


# Advice

So my advice:

## If you use multiple programming languages in one repo:
1. use `.editorconfig` everywhere
2. let prettier use `.editorconfig`, only use `.prettierrc` to append settings `.editorconfig` doesn't support, avoid conflicting settings. Use following script: `npx editorconfig-cli init -y`, remove any prettier settings.
3. include [prettier in eslint](https://prettier.io/docs/en/integrating-with-linters.html) settings

## If you only use TS/JS/HTML/CSS
1. totally ignore `.editorconfig`
2. use `.prettierrc` instead with prettier configuration
3. include [prettier in eslint](https://prettier.io/docs/en/integrating-with-linters.html) settings

Happy coding!