A fast Markdown linter written in Rust. Compatible with CommonMark and GitHub Flavored Markdown (GFM).
mado check .
mado check path/to/*.mdApprox. 49-60x faster than existing linters (e.g. markdownlint).
---
config:
xyChart:
height: 200
titleFontSize: 14
chartOrientation: horizontal
xAxis:
labelFontSize: 12
titleFontSize: 14
yAxis:
labelFontSize: 12
titleFontSize: 14
---
xychart-beta
title "Linting ~1,500 Markdown files (Lower is faster)"
x-axis ["mado (rust)", "markdownlint-cli (node.js)", "markdownlint (ruby)", "markdownlint-cli2 (node.js)"]
y-axis "Time (seconds)" 0 --> 10
bar [0.129, 6.381, 6.609, 7.817]
This benchmark was conducted on a MacBook Pro (2021, M1 Max) using hyperfine with GitLab documentation as the dataset.
brew tap akiomik/mado https://github.com/akiomik/mado.git
brew install madonix profile install github:akiomik/madopacman -S madoscoop install https://raw.githubusercontent.com/akiomik/mado/refs/heads/main/pkg/scoop/mado.json# For security reasons, installing from local manifest files requires that this feature be enabled by an administrator.
# For more details, see https://learn.microsoft.com/en-us/windows/package-manager/winget/install#local-install
winget settings --enable LocalManifestFiles
curl.exe -o mado.yml https://raw.githubusercontent.com/akiomik/mado/refs/heads/main/pkg/winget/mado.yml
winget install -m mado.ymlPre-built binaries are available for download from the release page.
Mado supports most markdownlint rules.
- β Stable support
- π¨ Unstable support
β οΈ Unsupported option(s)- β Not supported
| Rule | Support | Note |
|---|---|---|
| MD001 | β | |
| MD002 | β | |
| MD003 | π¨ | |
| MD004 | β | |
| MD005 | β | |
| MD006 | β | |
| MD007 | π¨ | |
| MD009 | β | |
| MD010 | β | |
| MD012 | β | |
| MD013 | β | |
| MD014 | β | |
| MD018 | β | |
| MD019 | β | |
| MD020 | π¨ | |
| MD021 | β | |
| MD022 | β | |
| MD023 | β | |
| MD024 | β | |
| MD025 | β | |
| MD026 | β | |
| MD027 | π¨ | |
| MD028 | β | |
| MD029 | β | |
| MD030 | β | |
| MD031 | β | |
| MD032 | π¨ | |
| MD033 | β | |
| MD034 | β | |
| MD035 | β | |
| MD036 | β | |
| MD037 | β | |
| MD038 | β | |
| MD039 | β | |
| MD040 | β | |
| MD041 | β | |
| MD046 | β | |
| MD047 | β |
Mado can be configured via mado.toml or .mado.toml file in the current directory.
You can also use global configuration files located in:
Linux:~/.config/mado/mado.tomlmacOS:~/.config/mado/mado.tomlWindows:~\AppData\Roaming\mado\mado.toml
For more details,
see the example mado.toml
and the JSON Schema for mado.toml.
respect-ignore decides whether .ignore files exclude what they list.
respect-gitignore decides when .gitignore files do:
| value | .gitignore files are read |
|---|---|
"never" |
not at all |
"repository-only" (default) |
inside a Git repository, as Git does |
"always" |
whether or not the tree carries Git metadata |
A repository here is a .git directory, the .git file a worktree or a
submodule carries, or a .jj directory, which the ignore crate stops at as
well.
"always" suits a tree that arrives without its Git metadata β a source
archive, or a Docker context copied without .git. It stops mado looking for a
repository at all, for every tree rather than only those without one, which is
what the ignore crate offers and what
rg --no-require-git does. So .gitignore files apply from every parent
directory, above a clone's own repository root included, and a repository below
the path being linted does not bound the search.
The global Git ignore file and .git/info/exclude are never read. Neither
travels with the tree being linted, so reading them would have one source lint
differently on another machine.
Mado is compatible with GitHub Actions.
# Basic usage (runs `mado check .`)
- uses: akiomik/mado@v0.3.2
# Custom usage (runs `mado` with specified arguments)
- uses: akiomik/mado@v0.3.2
with:
args: '--config path/to/mado.toml check path/to/*.md'The action downloads the mado release it was published with. Setting the
version input names a different release to run; a pin from before the input
was added ignores it.
just is required.
just testjust lintCompares what mado and mdl
report for markdownlint's own rule fixtures. This needs mdl, cargo and
git on PATH.
# Download the fixtures and set aside the ones written against their own style
./scripts/acceptance/setup.sh
# Write each tool's findings to tmp/mdl.txt and tmp/mado.txt
./scripts/acceptance/test.sh
diff tmp/mdl.txt tmp/mado.txtThat diff is not expected to be empty. Some of it is the two tools disagreeing and some of it is the two configurations differing, which is being worked out in #401.
This needs hyperfine,
mdl, node, npm, cargo
and git on PATH.
# Download Markdown dataset
./scripts/benchmarks/setup.sh
# Install the markdownlint commands the comparison runs against
npm --prefix scripts/benchmarks ci
# Benchmark mado, mdl and markdownlint-cli using hyperfine
./scripts/benchmarks/comparison.shFirst, install flamegraph:
cargo install flamegraphThen run:
just flamegraphFirst, install cargo-fuzz:
cargo install cargo-fuzzThen run:
just fuzz