Lint Markdown files with markdownlint in GitHub Actions
Sometimes I wonder... am I the only one with this tiny little obsession for consistency in how I write Markdown files? Hell no! See the folks behind markdownlint, they definitely have the same itch. With this linter and its CLI, gone are the chaotic days of incongruous Markdown files. Now, I can sleep better again, and you can too! (Not based on scientific evidence... but who knows?)
Don't go sleep yet though, let's start lintin' those pesky Markdown files with markdownlint. You'll even see how this can be nicely added to a project's continuous integration (CI) with GitHub Actions.
1, 2, 3 ― Lint!
You don't run before you walk, ehm... I mean you don't lint Markdown files before you install markdownlint's CLI:
npm install [email protected] --global
Done? Great! In a repository with some Markdown files, execute this command to lint them all:
markdownlint-cli2 '**/*.md' '#vendor'
In the snippet above, I showcase how you can exclude a directory. Any file under
the vendor
directory won't be linted. You can omit this part if you don't need
it.
Now you tell me "What's the point of having a tool if I cannot make it my
own?". After all, it's your files and repositories, your rules! Just put them in
.markdownlint.yml
...
# Default state for all rules
default: true
# Trailing punctuation in headings
MD026:
# The following punctuation characters aren't accepted in headings
# This differs from the default configuration by accepting exclamation marks in headings
punctuation: ".,;:。,;:"
And if this isn't enough for you... go wild with the rules, the world is yours!
Time for a Bit of (GitHub) Action(s)
So you have a GitHub repository, maybe two or even more (impressive!), and they
all got some Markdown files you want to lint? It's your lucky day ― automate
this with a sweet continuous integration built with GitHub Actions. Create the
file .github/workflows/lint.yml
with this YAML:
name: Lint
on:
# Run this workflow when a commit is pushed to `main`
push:
branches:
- main
# Run this workflow on any PR targeting `main`
pull_request:
branches:
- main
jobs:
lint:
runs-on: ubuntu-24.04
steps:
# https://github.com/actions/checkout
- uses: actions/checkout@v4
# https://github.com/actions/setup-node
- uses: actions/setup-node@v4
- name: Install CLI for markdownlint
run: npm install [email protected] --global
- name: Lint Markdown files, while excluding anything under the node_modules directories (which is generated by `npm install` above)
run: markdownlint-cli2 "**/*.md" "#node_modules"
Every commit pushed to main
and PRs targeting main
will now lint Markdown
files automatically in your continuous integration. Automation is the best!
A Bit Too Eager?
Maybe markdownlint is sometimes a bit too trigger-happy? Calm it down for a few lines, like in this example below:
<!-- markdownlint-disable -->
Markdown which doesn't satisfy some *markdownlint* rule(s).
<!-- markdownlint-enable -->
Do You Even Lint?
Yes, you do now! Linting Markdown files, then having this run with GitHub Actions, it's awesome. Keep those files in check, while I subtly go to bed... I did hint about getting a better sleep now 🥳. But in all seriousness, enjoy your day!