UNPKG

23.2 kBMarkdownView Raw
1# eslint-config-prettier [![Build Status][travis-badge]][travis]
2
3Turns off all rules that are unnecessary or might conflict with [Prettier].
4
5This lets you use you favorite shareable config without letting its stylistic
6choices get in the way when using Prettier.
7
8Note that this config _only_ turns rules _off,_ so it only makes sense using
9it together with some other config.
10
11## Contents
12
13<!-- START doctoc generated TOC please keep comment here to allow auto update -->
14<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
15
16
17- [Installation](#installation)
18- [CLI helper tool](#cli-helper-tool)
19- [Example configuration](#example-configuration)
20- [Special rules](#special-rules)
21 - [arrow-body-style and prefer-arrow-callback](#arrow-body-style-and-prefer-arrow-callback)
22 - [curly](#curly)
23 - [lines-around-comment](#lines-around-comment)
24 - [max-len](#max-len)
25 - [no-confusing-arrow](#no-confusing-arrow)
26 - [no-mixed-operators](#no-mixed-operators)
27 - [no-tabs](#no-tabs)
28 - [no-unexpected-multiline](#no-unexpected-multiline)
29 - [quotes](#quotes)
30 - [Enforce backticks](#enforce-backticks)
31 - [Forbid unnecessary backticks](#forbid-unnecessary-backticks)
32 - [Example _double_ quote configuration](#example-_double_-quote-configuration)
33 - [Example _single_ quote configuration](#example-_single_-quote-configuration)
34 - [vue/html-self-closing](#vuehtml-self-closing)
35- [Other rules worth mentioning](#other-rules-worth-mentioning)
36 - [no-sequences](#no-sequences)
37- [Contributing](#contributing)
38- [License](#license)
39
40<!-- END doctoc generated TOC please keep comment here to allow auto update -->
41
42## Installation
43
44Tip: First, you might be interested in installing [eslint-plugin-prettier].
45Follow the instructions over there. This is optional, though.
46
47Install eslint-config-prettier:
48
49```
50npm install --save-dev eslint-config-prettier
51```
52
53Then, add eslint-config-prettier to the "extends" array in your `.eslintrc.*`
54file. Make sure to put it **last,** so it gets the chance to override other
55configs.
56
57```json
58{
59 "extends": [
60 "some-other-config-you-use",
61 "prettier"
62 ]
63}
64```
65
66A few ESLint plugins are supported as well:
67
68- [@typescript-eslint/eslint-plugin]
69- [eslint-plugin-babel]
70- [eslint-plugin-flowtype]
71- [eslint-plugin-react]
72- [eslint-plugin-standard]
73- [eslint-plugin-unicorn]
74- [eslint-plugin-vue]
75
76Add extra exclusions for the plugins you use like so:
77
78```json
79{
80 "extends": [
81 "some-other-config-you-use",
82 "prettier",
83 "prettier/@typescript-eslint",
84 "prettier/babel",
85 "prettier/flowtype",
86 "prettier/react",
87 "prettier/standard",
88 "prettier/unicorn",
89 "prettier/vue"
90 ]
91}
92```
93
94If you extend a config which uses a plugin, it is recommended to add
95`"prettier/that-plugin"` (if available). For example, [eslint-config-airbnb]
96enables [eslint-plugin-react] rules, so `"prettier/react"` is needed:
97
98```json
99{
100 "extends": [
101 "airbnb",
102 "prettier",
103 "prettier/react"
104 ]
105}
106```
107
108If you’re unsure which plugins are used, you can usually find them in your
109`package.json`.
110
111## CLI helper tool
112
113eslint-config-prettier also ships with a little CLI tool to help you check if
114your configuration contains any rules that are unnecessary or conflict with
115Prettier.
116
117First, add a script for it to package.json:
118
119```json
120{
121 "scripts": {
122 "eslint-check": "eslint --print-config . | eslint-config-prettier-check"
123 }
124}
125```
126
127Then run `npm run eslint-check`.
128
129If you use [multiple configuration files] or [overrides], you may need to run
130the above script several times with different `--print-config` arguments, such
131as:
132
133```
134eslint --print-config test/index.js | eslint-config-prettier-check
135```
136
137Exit codes:
138
139- 0: No problems found.
140- 1: Unexpected error.
141- 2: Conflicting rules found.
142
143## Example configuration
144
145```json
146{
147 "extends": [
148 "standard",
149 "plugin:@typescript-eslint/recommended",
150 "plugin:flowtype/recommended",
151 "plugin:react/recommended",
152 "plugin:unicorn/recommended",
153 "plugin:vue/recommended",
154 "prettier",
155 "prettier/@typescript-eslint",
156 "prettier/babel",
157 "prettier/flowtype",
158 "prettier/react",
159 "prettier/standard",
160 "prettier/unicorn",
161 "prettier/vue"
162 ],
163 "plugins": [
164 "@typescript-eslint",
165 "babel",
166 "flowtype",
167 "prettier",
168 "react",
169 "standard",
170 "unicorn",
171 "vue"
172 ],
173 "parserOptions": {
174 "sourceType": "module",
175 "ecmaFeatures": {
176 "jsx": true
177 }
178 },
179 "env": {
180 "es6": true,
181 "node": true
182 },
183 "rules": {
184 "prettier/prettier": "error"
185 }
186}
187```
188
189## Special rules
190
191There a few rules that eslint-config-prettier disables that actually can be
192enabled in some cases.
193
194- Some require certain options. The CLI helper tool validates this.
195- Some require special attention when writing code. The CLI helper tool warns
196 you if any of those rules are enabled, but can’t tell if anything is
197 problematic.
198- Some can cause problems if using [eslint-plugin-prettier] and `--fix`.
199
200For maximum ease of use, the special rules are disabled by default. If you want
201them, you need to explicitly specify them in your ESLint config.
202
203### [arrow-body-style] and [prefer-arrow-callback]
204
205**These rules might cause problems if using [eslint-plugin-prettier] and `--fix`.**
206
207If you use any of these rules together with the `prettier/prettier` rule from
208[eslint-plugin-prettier], you can in some cases end up with invalid code due to
209a bug in ESLint’s autofix.
210
211These rules are safe to use if:
212
213- You don’t use [eslint-plugin-prettier]. In other words, you run `eslint --fix`
214 and `prettier --write` as separate steps.
215- You _do_ use [eslint-plugin-prettier], but don’t use `--fix`. (But then,
216 what’s the point?)
217
218You _can_ still use these rules together with [eslint-plugin-prettier] if you
219want, because the bug does not occur _all the time._ But if you do, you need to
220keep in mind that you might end up with invalid code, where you manually have to
221insert a missing closing parenthesis to get going again.
222
223If you’re fixing large of amounts of previously unformatted code, consider
224temporarily disabling the `prettier/prettier` rule and running `eslint --fix`
225and `prettier --write` separately.
226
227See these issues for more information:
228
229- [eslint-config-prettier#31]
230- [eslint-config-prettier#71]
231- [eslint-plugin-prettier#65]
232
233When the autofix bug in ESLint has been fixed, the special case for these rules
234can be removed.
235
236### [curly]
237
238**This rule requires certain options.**
239
240If a block (for example after `if`, `else`, `for` or `while`) contains only one
241statement, JavaScript allows omitting the curly braces around that statement.
242This rule enforces if or when those optional curly braces should be omitted.
243
244If you use the `"multi-line"` or `"multi-or-nest"` option, the rule can conflict
245with Prettier.
246
247For example, the `"multi-line"` option allows this line:
248
249```js
250if (cart.items && cart.items[0] && cart.items[0].quantity === 0) updateCart(cart);
251```
252
253However, Prettier might consider the line too long and turn it into the
254following, which the `"multi-line"` option does _not_ allow:
255
256```js
257if (cart.items && cart.items[0] && cart.items[0].quantity === 0)
258 updateCart(cart);
259```
260
261If you like this rule, it can be used just fine with Prettier as long as you
262don’t use the `"multi-line"` or `"multi-or-nest"` option.
263
264Example ESLint configuration:
265
266```json
267{
268 "rules": {
269 "curly": ["error", "all"]
270 }
271}
272```
273
274### [lines-around-comment]
275
276**This rule can be used with certain options.**
277
278This rule requires empty lines before and/or after comments. Prettier preserves
279blank lines, with two exceptions:
280
281- Several blank lines in a row are collapsed into a single blank line. This is
282 fine.
283- Blank lines at the beginning and end of blocks, objects and arrays are always
284 removed. This may lead to conflicts.
285
286By default, ESLint requires a blank line above the comment is this case:
287
288```js
289if (result) {
290
291 /* comment */
292 return result;
293}
294```
295
296However, Prettier removes the blank line:
297
298```js
299if (result) {
300 /* comment */
301 return result;
302}
303```
304
305If you like this rule, it can be used just fine with Prettier as long as you add
306some extra configuration to allow comments at the start and end of blocks,
307objects and arrays.
308
309Example ESLint configuration:
310
311```json
312{
313 "rules": {
314 "lines-around-comment": [
315 "error",
316 {
317 "beforeBlockComment": true,
318 "afterBlockComment": true,
319 "beforeLineComment": true,
320 "afterLineComment": true,
321 "allowBlockStart": true,
322 "allowBlockEnd": true,
323 "allowObjectStart": true,
324 "allowObjectEnd": true,
325 "allowArrayStart": true,
326 "allowArrayEnd": true
327 }
328 ]
329 }
330}
331```
332
333### [max-len]
334
335**This rule requires special attention when writing code.**
336
337Usually, Prettier takes care of following a maximum line length automatically.
338However, there are cases where Prettier can’t do anything, such as for long
339strings, regular expressions and comments. Those need to be split up by a human.
340
341If you’d like to enforce an even stricter maximum line length policy than
342Prettier can provide automatically, you can enable this rule. Just remember to
343keep `max-len`’s options and Prettier’s `printWidth` option in sync.
344
345Keep in mind that you might have to refactor code slightly if Prettier formats
346lines in a way that the `max-len` rule does not approve of.
347
348Example ESLint configuration:
349
350```json
351{
352 "rules": {
353 "max-len": ["error", {"code": 80, "ignoreUrls": true}]
354 }
355}
356```
357
358### [no-confusing-arrow]
359
360**This rule requires certain options.**
361
362For example, the rule could warn about this line:
363
364```js
365var x = a => 1 ? 2 : 3;
366```
367
368By default, ESLint suggests switching to an explicit return:
369
370```js
371var x = a => { return 1 ? 2 : 3; };
372```
373
374That causes no problems with Prettier.
375
376With `{allowParens: true}`, adding parentheses is also considered a valid way to
377avoid the arrow confusion:
378
379```js
380var x = a => (1 ? 2 : 3);
381```
382
383While Prettier keeps thoses parentheses, it removes them if the line is long
384enough to introduce a line break:
385
386```js
387EnterpriseCalculator.prototype.calculateImportantNumbers = inputNumber =>
388 1 ? 2 : 3;
389```
390
391If you like this rule, it can be used just fine with Prettier as long as the
392`allowParens` option is off.
393
394Example ESLint configuration:
395
396```json
397{
398 "rules": {
399 "no-confusing-arrow": "error"
400 }
401}
402```
403
404### [no-mixed-operators]
405
406**This rule requires special attention when writing code.**
407
408This rule forbids mixing certain operators, such as `&&` and `||`.
409
410For example, the rule could warn about this line:
411
412```js
413var foo = a + b * c;
414```
415
416The rule suggests adding parentheses, like this:
417
418```js
419var foo = a + (b * c);
420```
421
422However, Prettier removes many “unnecessary” parentheses, turning it back to:
423
424```js
425var foo = a + b * c;
426```
427
428If you want to use this rule with Prettier, you need to split the expression
429into another variable:
430
431```js
432var bar = b * c;
433var foo = a + bar;
434```
435
436Keep in mind that Prettier prints _some_ “unnecessary” parentheses, though:
437
438```js
439var foo = (a && b) || c;
440```
441
442Example ESLint configuration:
443
444```json
445{
446 "rules": {
447 "no-mixed-operators": "error"
448 }
449}
450```
451
452### [no-tabs]
453
454**This rule requires certain Prettier options.**
455
456This rule disallows the use of tab characters at all. It can be used just fine
457with Prettier as long as you don’t configure Prettier to indent using tabs.
458
459Example ESLint configuration:
460
461```json
462{
463 "rules": {
464 "no-tabs": "error"
465 }
466}
467```
468
469Example Prettier configuration (this is the default, so adding this is not
470required):
471
472```json
473{
474 "useTabs": false
475}
476```
477
478**Note:** Since [ESlint 5.7.0] this rule can be configured to work regardless of
479your Prettier configuration:
480
481```json
482{
483 "rules": {
484 "no-tabs": ["error", {"allowIndentationTabs": true}]
485 }
486}
487```
488
489A future version of eslint-config-prettier might check for that automatically.
490
491### [no-unexpected-multiline]
492
493**This rule requires special attention when writing code.**
494
495This rule disallows confusing multiline expressions where a newline looks like
496it is ending a statement, but is not.
497
498For example, the rule could warn about this:
499
500```js
501var hello = "world"
502[1, 2, 3].forEach(addNumber)
503```
504
505Prettier usually formats this in a way that makes it obvious that a semicolon
506was missing:
507
508```js
509var hello = "world"[(1, 2, 3)].forEach(addNumber);
510```
511
512However, there are cases where Prettier breaks things into several lines such
513that the `no-unexpected-multiline` conflicts.
514
515```js
516const value = text.trim().split("\n")[position].toLowerCase();
517```
518
519Prettier breaks it up into several lines, though, causing a conflict:
520
521```js
522const value = text
523 .trim()
524 .split("\n")
525 [position].toLowerCase();
526```
527
528If you like this rule, it can usually be used with Prettier without problems,
529but occasionally you might need to either temporarily disable the rule or
530refactor your code.
531
532```js
533const value = text
534 .trim()
535 .split("\n")
536 // eslint-disable-next-line no-unexpected-multiline
537 [position].toLowerCase();
538
539// Or:
540
541const lines = text.trim().split("\n");
542const value = lines[position].toLowerCase();
543```
544
545**Note:** If you _do_ enable this rule, you have to run ESLint and Prettier as
546two separate steps (and ESLint first) in order to get any value out of it.
547Otherwise Prettier might reformat your code in such a way that ESLint never gets
548a chance to report anything (as seen in the first example).
549
550Example configuration:
551
552```json
553{
554 "rules": {
555 "no-unexpected-multiline": "error"
556 }
557}
558```
559
560### [quotes]
561
562(The following applies to [babel/quotes] as well.)
563
564**This rule requires certain options and certain Prettier options.**
565
566Usually, you don’t need this rule at all. But there are two cases where it could
567be useful:
568
569- To enforce the use of backticks rather than single or double quotes for
570 strings.
571- To forbid backticks where regular strings could have been used.
572
573#### Enforce backticks
574
575If you’d like all strings to use backticks (never quotes), enable the
576`"backtick"` option.
577
578Example ESLint configuration:
579
580```json
581{
582 "rules": {
583 "quotes": ["error", "backtick"]
584 }
585}
586```
587
588#### Forbid unnecessary backticks
589
590In the following example, the first array item could have been written with
591quotes instead of backticks.
592
593```js
594const strings = [
595 `could have been a regular string`,
596 `
597 multiple
598 lines
599 `,
600 `uses ${interpolation}`,
601 String.raw`\tagged/`,
602];
603```
604
605If you’d like ESLint to enforce `` `could have been a regular string` `` being
606written as either `"could have been a regular string"` or `'could have been a
607regular string'`, you need to use some specific configuration. The `quotes` rule has two options, a string option and an object option.
608
609- The first (string) option needs to be set to `"single"` or `"double"` and be
610 kept in sync with Prettier’s [singleQuote] option.
611- The second (object) option needs the following properties:
612 - `"avoidEscape": true` to follow Prettier’s [string formatting rules].
613 - `"allowTemplateLiterals": false` to disallow unnecessary backticks.
614
615##### Example _double_ quote configuration
616
617ESLint:
618
619```json
620{
621 "rules": {
622 "quotes": [
623 "error",
624 "double",
625 { "avoidEscape": true, "allowTemplateLiterals": false }
626 ]
627 }
628}
629```
630
631Prettier (this is the default, so adding this is not required):
632
633```json
634{
635 "singleQuote": false
636}
637```
638
639##### Example _single_ quote configuration
640
641ESLint:
642
643```json
644{
645 "rules": {
646 "quotes": [
647 "error",
648 "single",
649 { "avoidEscape": true, "allowTemplateLiterals": false }
650 ]
651 }
652}
653```
654
655Prettier:
656
657```json
658{
659 "singleQuote": true
660}
661```
662
663### [vue/html-self-closing]
664
665**This rule requires certain options.**
666
667This rule enforces whether elements should be self-closing or not.
668
669Prettier generally preserves the way you wrote your elements:
670
671```vue
672<div />
673<div></div>
674<MyComponent />
675<MyComponent></MyComponent>
676<svg><path d="" /></svg>
677<svg><path d=""></path></svg>
678```
679
680But for known _void_ HTML elements, Prettier always uses the self-closing style.
681For example, `<img>` is turned into `<img />`.
682
683If you like this rule, it can be used just fine with Prettier as long as you
684set `html.void` to `"any"`.
685
686Example ESLint configuration:
687
688```json
689{
690 "rules": {
691 "vue/html-self-closing": [
692 "error",
693 {
694 "html": {
695 "void": "any"
696 }
697 }
698 ]
699 }
700}
701```
702
703## Other rules worth mentioning
704
705These rules don’t conflict with Prettier, but have some gotchas when used with
706Prettier.
707
708### [no-sequences]
709
710This rule forbids using JavaScript’s confusing comma operator (sequence
711expressions). This piece of code is not doing what it looks like:
712
713```js
714matrix[4, 7];
715```
716
717Prettier adds parentheses to the above to make it clear that a sequence
718expression is used:
719
720```js
721matrix[(4, 7)];
722```
723
724However, the `no-sequences` rule allows comma operators if the expression
725sequence is explicitly wrapped in parentheses. Since Prettier automatically
726wraps them in parentheses, you might never see any warnings from ESLint about
727comma operators.
728
729Ending up with an accidental sequence expression can easily happen while
730refactoring. If you want ESLint to catch such mistakes, it is recommended to
731forbid sequence expressions entirely using [no-restricted-syntax] \([as
732mentioned in the `no-sequences` documentation][no-sequences-full]):
733
734```json
735{
736 "rules": {
737 "no-restricted-syntax": ["error", "SequenceExpression"]
738 }
739}
740```
741
742If you still need to use the comma operator for some edge case, you can place an
743`// eslint-disable-next-line no-restricted-syntax` comment on the line above the
744expression. `no-sequences` can safely be disabled if you use the
745`no-restricted-syntax` approach.
746
747You can also supply a custom message if you want:
748
749```json
750{
751 "rules": {
752 "no-restricted-syntax": [
753 "error",
754 {
755 "selector": "SequenceExpression",
756 "message": "The comma operator is confusing and a common mistake. Don’t use it!"
757 }
758 ]
759 }
760}
761```
762
763## Contributing
764
765eslint-config-prettier has been tested with:
766
767- ESLint 5.16.0
768 - eslint-config-prettier 2.10.0 and older were tested with ESLint 4.x
769 - eslint-config-prettier 2.1.1 and older were tested with ESLint 3.x
770- prettier 1.17.0
771- @typescript-eslint/eslint-plugin 1.7.0
772- eslint-plugin-babel 5.3.0
773- eslint-plugin-flowtype 3.6.1
774- eslint-plugin-react 7.12.4
775- eslint-plugin-standard 4.0.0
776- eslint-plugin-unicorn 8.0.2
777- eslint-plugin-vue 5.1.0
778
779Have new rules been added since those versions? Have we missed any rules? Is
780there a plugin you would like to see exclusions for? Open an issue or a pull
781request!
782
783If you’d like to add support for eslint-plugin-foobar, this is how you’d go
784about it:
785
786First, create `foobar.js`:
787
788```js
789"use strict";
790
791module.exports = {
792 rules: {
793 "foobar/some-rule": "off"
794 }
795};
796```
797
798Then, create `test-lint/foobar.js`:
799
800```js
801/* eslint-disable quotes */
802"use strict";
803
804// Prettier does not want spaces before the parentheses, but
805// `plugin:foobar/recommended` wants one.
806console.log();
807```
808
809`test-lint/foobar.js` must fail when used with eslint-plugin-foobar and
810eslint-plugin-prettier at the same time – until `"prettier/foobar"` is added to
811the "extends" property of an ESLint config. The file should be formatted
812according to Prettier, and that formatting should disagree with the plugin.
813
814Finally, you need to mention the plugin in several places:
815
816- Add `"foobar.js"` to the "files" field in `package.json`.
817- Add eslint-plugin-foobar to the "devDependencies" field in `package.json`.
818- Make sure that at least one rule from eslint-plugin-foobar gets used in
819 `.eslintrc.base.js`.
820- Add it to the list of supported plugins, to the example config and to
821 Contributing section in `README.md`.
822
823When you’re done, run `npm test` to verify that you got it all right. It runs
824several other npm scripts:
825
826- `"test:lint"` makes sure that the files in `test-lint/` pass ESLint when
827 the exclusions from eslint-config-prettier are used. It also lints the code of
828 eslint-config-prettier itself.
829- `"test:lint-verify-fail"` is run by a test in `test/lint-verify-fail.test.js`.
830- `"test:lint-rules"` is run by a test in `test/rules.test.js`.
831- `"test:jest"` runs unit tests that check a number of things:
832 - That eslint-plugin-foobar is mentioned in all the places shown above.
833 - That no unknown rules are turned off. This helps catching typos, for
834 example.
835 - That the CLI works.
836- `"test:cli-sanity"` and `"test:cli-sanity-warning"` are sanity checks for the
837 CLI.
838
839## License
840
841[MIT](LICENSE).
842
843[@typescript-eslint/eslint-plugin]: https://github.com/typescript-eslint/typescript-eslint
844[ESlint 5.7.0]: https://eslint.org/blog/2018/10/eslint-v5.7.0-released
845[Prettier]: https://github.com/prettier/prettier
846[arrow-body-style]: https://eslint.org/docs/rules/arrow-body-style
847[babel/quotes]: https://github.com/babel/eslint-plugin-babel#rules
848[curly]: https://eslint.org/docs/rules/curly
849[eslint-config-airbnb]: https://www.npmjs.com/package/eslint-config-airbnb
850[eslint-config-prettier#31]: https://github.com/prettier/eslint-config-prettier/issues/31
851[eslint-config-prettier#71]: https://github.com/prettier/eslint-config-prettier/issues/71
852[eslint-plugin-babel]: https://github.com/babel/eslint-plugin-babel
853[eslint-plugin-flowtype]: https://github.com/gajus/eslint-plugin-flowtype
854[eslint-plugin-prettier#65]: https://github.com/prettier/eslint-plugin-prettier/issues/65
855[eslint-plugin-prettier]: https://github.com/prettier/eslint-plugin-prettier
856[eslint-plugin-react]: https://github.com/yannickcr/eslint-plugin-react
857[eslint-plugin-standard]: https://github.com/xjamundx/eslint-plugin-standard
858[eslint-plugin-unicorn]: https://github.com/sindresorhus/eslint-plugin-unicorn
859[eslint-plugin-vue]: https://github.com/vuejs/eslint-plugin-vue
860[lines-around-comment]: https://eslint.org/docs/rules/lines-around-comment
861[max-len]: https://eslint.org/docs/rules/max-len
862[multiple configuration files]: https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy
863[no-confusing-arrow]: https://eslint.org/docs/rules/no-confusing-arrow
864[no-mixed-operators]: https://eslint.org/docs/rules/no-mixed-operators
865[no-restricted-syntax]: https://eslint.org/docs/rules/no-restricted-syntax
866[no-sequences-full]: https://eslint.org/docs/rules/no-sequences#when-not-to-use-it
867[no-sequences]: https://eslint.org/docs/rules/no-sequences
868[no-tabs]: https://eslint.org/docs/rules/no-tabs
869[no-unexpected-multiline]: https://eslint.org/docs/rules/no-unexpected-multiline
870[overrides]: https://eslint.org/docs/user-guide/configuring#configuration-based-on-glob-patterns
871[prefer-arrow-callback]: https://eslint.org/docs/rules/prefer-arrow-callback
872[quotes]: https://eslint.org/docs/rules/quotes
873[singleQuote]: https://prettier.io/docs/en/options.html#quotes
874[string formatting rules]: https://prettier.io/docs/en/rationale.html#strings
875[travis-badge]: https://travis-ci.org/prettier/eslint-config-prettier.svg?branch=master
876[travis]: https://travis-ci.org/prettier/eslint-config-prettier
877[vue/html-self-closing]: https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/html-self-closing.md