Configuring Markdownlint Alongside Prettier
January 25, 2023
Concept art from the Halo 3: ODST character, Superintendent, known for saying keep it clean. [source]
As a maintainer of a popular linting tool, typescript-eslint, I often get asked how I configure linting for my projects. My JavaScript code gets ESLint; my TypeScript code gets typescript-eslint added on top, and my Markdown code gets Markdownlint.
For all three of those tools (and others like them), keep in mind that linters are not good formatters. Linters are great at catching bugs, enforcing stylistic decisions such as naming, and detecting violations of best practices - but theyâre inherently terrible at formatting your code. Whenever you enable a linter, you should make sure it isnât also trying to format your code.
Markdownlint
I generally use
markdownlint
with
markdownlint-cli
for linting my Markdown code. Theyâre fast and straightforward
to configure. You can get started with them by installing
markdownlint-cli
to your
projectâs devDependencies:
npm i -D markdownlint-cli
âŚand then adding a script to run it on all your
.md
files:
{
"scripts": {
"lint:md": "markdownlint \"**/*.md\" \".github/**/*.md\""
}
}
Markdownlint and Prettier
Until recently, Markdownlint didnât have a built-in way to
disable all formatting lint rules the way ESLint does with
eslint-config-prettier. Previously, whenever I configured Markdownlint, Iâd add at
least the following line in my
.markdownlint.json
to make
it not try to apply formatting logic:
// .markdownlint.json
{
"line-length": false
}
Unfortunately, depending on how you configure Prettier (or any other auto-formatter), there are over a dozen Markdownlint rules that might conflict with formatting!
// .markdownlint.json
{
"blanks-around-fences": false,
"blanks-around-headings": false,
"blanks-around-lists": false,
"code-fence-style": false,
"emphasis-style": false,
"heading-start-left": false,
"hr-style": false,
"line-length": false,
"list-indent": false,
"list-marker-space": false,
"no-blanks-blockquote": false,
"no-hard-tabs": false,
"no-missing-space-atx": false,
"no-missing-space-closed-atx": false,
"no-multiple-blanks": false,
"no-multiple-space-atx": false,
"no-multiple-space-blockquote": false,
"no-multiple-space-closed-atx": false,
"no-trailing-spaces": false,
"ol-prefix": false,
"strong-style": false,
"ul-indent": false
}
style/prettier.json
To The
Rescue
We shouldnât be expected to add any or all of those
configurations to every project that uses both Markdownlint
and a dedicated formatter. Thatâs why I
added a
style/prettier.json
extension option to Markdownlint. Now, instead of adding all those lines to your
.markdownlint.json
, you can
include a single
extends
directive:
// .markdownlint.json
{
"extends": "markdownlint/style/prettier"
}
Note that because that file is provided in the
markdownlint
package,
youâll want to explicitly have
markdownlint
installed,
even though itâs already a dependency of
markdownlint-cli
:
npm i markdownlint@latest markdownlint-cli@latest -D
You can read more about configuring Markdownlint alongside Prettier in Markdownlintâs Prettier documentation.
Aside: Sentences Per Line
By the way, I wrote my own
sentences-per-line
Markdownlint rule. It enforces that each sentence is on its
own line (or, in other words, that no line contains more than
one sentence). I like keeping to one sentence per line because
it enforces simpler Git diffs and shorter, more readable
lines.
npm i -D sentences-per-line
markdownlint --rules sentences-per-line
Putting It All Together
You can see a repository that uses Markdownlint with
formatting rules disabled over at
JoshuaKGoldberg/template-typescript-node-package. Its
package.json
lint:md
script
runs Markdownlint with
sentences-per-line
on all
Markdown files (including those in the
.github/
directory, since
dotfile folders arenât linted by default):
{
"scripts": {
"lint:md": "markdownlint \"**/*.md\" \".github/**/*.md\" --rules sentences-per-line"
}
}
Its
.markdownlint.json
extends from
markdownlint/style/prettier
and disables a couple more rules I tend to prefer off in my
repositories:
{
"extends": "markdownlint/style/prettier",
"first-line-h1": false,
"no-inline-html": false
}
Anyway, thanks for reading. I hope you found some of this useful! đ§š