27 - EditorConfig + Prettier + ESLint + Stylelint + Markdownlint - All you can lint

将各式 linter 与 formatter 工具整合於同个专案中,让开发者可以:

  • 使用 EditorConfig 配置的设定做输入。
  • 使用 Prettier 作为所有语言的 formatter 。
  • 使用 ESLint 作为 JavaScript 的 linter 。
  • 使用 Stylelint 作为 Style 的 linter 。
  • 使用 Markdownlint 作为 Markdown 的 linter 。

配置理念

https://ithelp.ithome.com.tw/upload/images/20211013/20107789AY5Cu0Y2i6.png

EditorConfig 、 Prettier 、 ESLint 、 Stylelint 与 Markdownlint 之间,由於功能相近,因此会有些许的功能重叠:

  • EditorConfig 与 Prettier (例如: EditorConfig 的 end_of_line 属性与 Prettier 的 endOfLine 选项)。
  • ESLint 与 Prettier (例如: ESLint 的 linebreak-style 规则与 Prettier 的 endOfLine 选项)。
  • Stylelint 与 Prettier (例如: Stylelint 的 linebreaks 规则与 Prettier 的 endOfLine 选项)。
  • Markdownlint 与 Prettier (例如: Markdownlint 的 no-multiple-blanks 规则与 Prettier 的 Empty lines 原则)。

为了避免个工具间产生冲突,理想的配置应该让各工具专职於它们主要的工作,把那些重叠的工作分配至合适的工具上,并将其他工具中有重叠到的部分给关闭。

为此,我们需要作下列的处理:

  • Prettier 依照 EditorConfig 的配置设定格式。
  • ESLint 、 Stylelint 与 Markdownlint 关闭 format 相关的规则。

前置条件

在整合前,我们需要先安装 EditorConfig 、 Prettier 、 ESLint 、 Stylelint 与 Markdownlint 并加入它们的配置,详细资讯可以参考「 16 - EditorConfig - 配置输入方式」、「 23 - Prettier - 格式化程序码工具」、「 24 - ESLint - Lint JavaScript 程序码」、「 25 - Stylelint - Lint CSS 程序码」与「 26 - MarkdownLint - Lint Markdown 文件」。

之前的章节介绍各个工具的配置方式都是独立的,还未做整合,接下来就让我们来看看如何整合这些工具吧。

整合 EditorConfig 与 Prettier

Prettier 预设会侦测专案中是否有 EditorConfig 的配置档 .editorconfig ,如果有的话, Prettier 会将 EditorConfig 的设定转为自己的配置做使用。

Prettier 可以转换的 EditorConfig 属性如下:

EditorConfig Prettier
end_of_line endOfLine
indent_style useTabs
indent_size/tab_width tabWidth
max_line_length printWidth

Prettier 使用 editorconfig-to-prettier 转换 EditorConfig 属性。

如果在 Prettier 的配置档(例如: .prettierrc.js )中设定上列的属性,则会忽略 EditorConfig 的设定,改以 Prettier 配置档为准。

如果 EditorConfig 与 Prettier 对相同的属性设定不同的值时,就会造成输入与格式化间的格式不一致,导致冲突的发生。

为了避免这问题发生,我们可以将 EditorConfig 能够配置的属性都交由 EditorConfig 设定,避免在 Prettier 中设定这些属性:

module.exports = {
  singleQuote: true,
  htmlWhitespaceSensitivity: 'strict',
  // The options below config in EditorConfig, do not config here
  // endOfLine: 'lf', // `end_of_line`
  // useTabs: false, // `indent_style`
  // tabWidth: 2, // `indent_size` / `tab_width`
  // printWidth: 80, // `max_line_length`
};

这些属性可以在 EditorConfig 的配置档中做设定:

root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
max_line_length = 80
# ...

这样一来格式化时, Prettier 就会依照 EditorConfig 的配置做处理,避免冲突的产生。

如果不想要 Prettier 参考 EditorConfig 的配置,可以在指令中加上 --no-editorconfig 参数。

整合 Prettier 、 ESLint 、 Stylelint 与 Markdownlint

各式的 Linters 对於其专注的语言( JavaScript 、 Stylelint 与 Markdownlint )都拥有 format 的能力,我们可以单纯使用它们做 format ,而不需要 Prettier ,但这样做会有缺点:

  • 格式化的对象仅限於特定语言:与 Prettier 可以支援多语言不同, Linters 的格式化都仅限於特定的语言( JavaScript 、 CSS 或 Markdown 等)。为了格式化其他格式的档案,你需要另外引入其他的格式化工具。
  • 同时维护多个格式化配置: 各 Linters 间的配置不共通,为了格式化的一致性,你需要自己确保各个配置拥有相同的格式化规则。
  • Linters 的提示依照配置会以红(黄)色毛毛虫线显示於编辑器上,如果加上格式化的提示,会破坏画面的整洁,难以保持专注。

由於上述的原因,将 Prettier 作为专案中唯一的格式化工具是个最佳选择。

要将 Prettier 作为格式化工具,就需要将 Linters 格式化相关的规则关闭

使用 eslint-config-prettier 关闭 ESLint 的格式化规则

eslint-config-prettier 为 ESLint 的规则包,它会将所有与 Prettier 规则有重叠到的规则关闭。

首先安装 eslint-config-prettier

npm install eslint-config-prettier --save-dev

prettier 设置於 extends 阵列的最後一个元素(设置於最後是为了避免被其他的规则覆写):

module.exports = {
  extends: ['airbnb-base', 'prettier'],
};

这样 ESLint 就不会处理任何与 Prettier 有关的规则了。

使用 stylelint-config-prettier 关闭 Stylelint 的格式化规则

stylelint-config-prettier 为 Stylelint 的规则包,它会将所有与 Prettier 规则有重叠到的规则关闭。

首先安装 stylelint-config-prettier

npm install stylelint-config-prettier --save-dev

stylelint-config-prettier 设置於 extends 阵列的最後一个元素(设置於最後是为了避免被其他的规则覆写):

module.exports = {
  extends: ['stylelint-config-standard', 'stylelint-config-prettier'],
};

这样 Stylelint 就不会处理任何与 Prettier 有关的规则了。

关闭 Markdownlint 中的格式化规则

Markdownlint 中有几个规则包含於 Prettier 的范围内,我们需要将这些规则关闭:

module.exports = {
  // ...
  // Prettier overrides
  'line-length': false, // `printWidth`
  'no-multiple-blanks': false, // Rationale: Empty lines
  'list-marker-space': false, // Rationale
};

这样一来, Markdownlint 就不会处理 Prettier 相关的规则了。

本文重点整理

  • 在整合输入、格式化与 lint 工具时,秉持着一事不二做的精神,将各工具专注於它们擅长的领域上,避免工具间发生冲突。
  • 整合完成後,我们可以将专案中的各种档案格式的程序码品质都兼顾到,来避免错误的产生。

参考资料


<<:  Day29_CSS语法12

>>:  Day28-JDK可视化监控工具:visualVM(四)

Day 5:口罩即时库存开放资料

本篇文章同步发表在 HKT 线上教室 部落格,线上影音教学课程已上架至 Udemy 和 Youtu...

Day 9 情报收集 - Information Gathering (netmask)

今天要介绍netmask,是可以让我们自由转换各种不同表示类型的网路地址以及子网遮罩,在划分子网路的...

【从零开始的 C 语言笔记】第二十一篇-continue & break

不怎麽重要的前言 到现在我们大概介绍完了所有的回圈语法,大家可以依照自己的需要使用不同的回圈。 这次...

IT铁人DAY 17-State 状态模式

  今天介绍的State Pattern与昨天的Strategy Pattern非常的相似,不过它们...

Day 02 : 你所知道的「笔记工具」,早就演化成不同的物种

【Obsidian 双向链结型笔记工具研究与应用,打造属於个人的专业知识图谱】Day 02 : 你所...