Many linting, code formatting, and static analysis tools exist for code. You can use eslint
, gofmt
, or many other static analysis tools, combined with a great continuous integration process, and ensure that your code stays in good shape. But what about markdown files and documentation? How do you ensure you aren't committing spelling and grammar mistakes? How do you ensure your files are valid markdown and that the language you are using is clear and correct? You can do this and more with a documentation linter.
Many tools exist for finding problems in text files. You can use this list as a starting point for finding the markdown and prose linting tools that best fit your needs.
Docs as Code
The movement behind testing and linting prose is known as Docs as Code, and the Writing The Docs website is a great place to learn more.
Criteria
For Ease of skimming, I'll rate each tool based on this criteria:
- Formatting: The ability to find errors in the formatting of text files (markdown, txt, asciidoc).
- Spelling: The ability to find spelling mistakes.
- Grammar: The ability to detect grammar errors.
- Clarity: The ability to suggest changes that can improve writing clarity.
Additionally, I will rate tools based on their feature set:
- Remediation: The ability to fix errors without manual intervention.
- Customization: How well the tool can be customized to fit your use case. If you can't exclude a rule or disable a warning, CI usage may be challenging. The most robust tools support custom rules and documentation style guides.
- Integrated Developer Environment (IDE) support: Ability to use in common code editors
- Continuous Integration (CI) / Command Line Interface (CLI) Usage: Ability to be used at the command line and in a continuous integration environment.
Markdown Lint
markdownlint
is a node.js markdown linter that is easy to install and easy to customize. It is based on an earlier Ruby tool, also called markdownlint. Both are great, but the Node.js tool is easy to install and easy to customize.
You can disable specific rules inline ( <!-- markdownlint-disable-file MD001 -->
) and set up a per-project config in a .markdownlintrc
file. It also supports writing custom rules in JavaScript and can remediate many problems itself with the fix
option:
markdownlint --fix "./_posts/*.md"
It doesn't handle spelling, grammar, or sentence structure, but it can't be beaten for dealing with markdown structure and it has a great online demo site.
Coverage
- Formatting: 5
- Spelling: 0
- Grammar: 0
- Clarity: 0
Features
- Ease of Use: 5
- Remediation: 5
- Customization: 5
- IDE support: 5
- CI / CLI Support: 5
mdspell
mdspell
is a tool specifically for spelling checking markdown documents. Install it like this:
npm i markdown-spellcheck -g
You can run it on markdown files in an interactive mode that builds up a custom dictionary of exceptions. You can then use that list later in a continuous integration process.
mdspell -n -a --en-us ./blog/_posts/2021-02-11-mitmproxy.md
The downsides of mdspell
are that the dictionary will likely complain about lots of words that are quite common. It may take some time to build up a list of exceptions. As a shortcut, you might be able to find some more .spelling
files on GitHub.
Coverage
- Formatting: 0
- Spelling: 5
- Grammar: 0
- Clarity: 0
Features
- Ease of Use: 5
- Remediation: 5
- Customization: 5
- IDE support: 5
- CI / CLI Support: 5
alex
alex
does one thing: catches insensitive and inconsiderate writing. It supports markdown files, and works via command-line, and has various IDE integrations. The specificity of alex
is its strength. For my rubric, I am scoring it under clarity as catching insensitive writing certainly improves clarity.
Coverage
- Formatting: 0
- Spelling: 0
- Grammar: 0
- Clarity: 3
Features
- Ease of Use: 5
- Remediation: 5
- Customization: 5
- IDE support: 5
- CI / CLI Support: 5
write-good
write-good
is designed for "developers who can't write good and wanna learn to do other stuff good too." The tool's focus is on improving the clarity of writing (and helping developers write well).
Install:
npm install -g write-good
Run:
$ write-good ./blog/_posts/2021-02-11-mitmproxy.md
here are several ways to accomplish this.
^^^^^^^^^^
"accomplish" is wordy or unneeded on line 305 at column 26
-------------
e-ca-certificates` is an excellent proof of concept, but if you want to run a do
^^^^^^^^^
"excellent" is a weasel word on line 367 at column 84
write-good
has many exciting suggestions. It will highlight passive voice, cliches, weak adverbs, and much more. Unfortunately, it's not easy to exclude items or configure rules. It might be helpful as a writing suggestion tool, but this lack of configurability means you will have difficulty using it in a continuous integration process.
Coverage
- Formatting: 0
- Spelling: 0
- Grammar: 0
- Clarity: 2
Features
- Ease of Use: 5
- Remediation: 0
- Customization: 1
- IDE support: 2
- CI / CLI Support: 2
textlint
textlint
is a pluggable linting tool that supports markdown, plain text, and HTML. The plug-in architecture means that it can offer the features of some of the previous items by wrapping them up as a plug-in. It has a plug-in for alex
, write-good
, and for many spell checkers and grammar checkers. The downside of this flexibility is that it is a bit harder to set up and configure: you have to install each plug-in separately.
Install:
$ npm install textlint --global
# install each plugin
$ npm install --global textlint-rule-no-todo
....
Run:
textlint "docs/**"
textlint
is configurable via an textlintrc
and has inline exclude rules ( <!-- textlint-disable ruleA,ruleB -->
) -- which may make it a possible way to use write-good
or other tools that lack this functionality.
Coverage
- Formatting: 0
- Spelling: 3
- Grammar: 3
- Clarity: 4
Features
- Ease of Use: 1
- Remediation: 3
- Customization: 4
- IDE support: 5
- CI / CLI Support: 2
proselint
proselint
goes deep on writing clarity improvements in the same way the alex
goes deep on inclusive writing:
proselint
places the world's greatest writers and editors by your side, where they whisper suggestions on how to improve your prose. You'll be guided by advice inspired by Bryan Garner, David Foster Wallace, Chuck Palahniuk, Steve Pinker, Mary Norris, Mark Twain, Elmore Leonard, George Orwell, Matthew Butterick, William Strunk, E. B. White, Philip Corbett, Ernest Gowers, and the editorial staff of the world's finest literary magazines and newspapers, among others. Our goal is to aggregate knowledge about best practices in writing and to make that knowledge immediately accessible to all authors in the form of a linter for prose.
Some of the writing advice included is great:
echo "The very first thing you'll see at the top of every (well-written) bash script " | proselint
<stdin>:1:5: weasel_words.very Substitute 'damn' every time you're inclined to write 'very'; your editor will delete it and the writing will be just as it should be.
echo "Thankfully, not all the advice I received was bad. " | proselint
<stdin>:1:2: skunked_terms.misc 'Thankfully,' is a bit of a skunked term — impossible to use without issue. Find some other way to say it.
echo "it is worth noting that both for CI and CD, the operating principles and coding philosophy are equally as important as the technical aspect of the implementation." | proselint
<stdin>:1:96: after_the_deadline.redundancy Redundancy. Use 'as' instead of 'equally as'.
This one is awesome considering the context of the original article:
echo "thought leaders" | proselint
<stdin>:1:2: cliches.garner 'thought leaders' is cliché.
echo "One elephant in the room with ngrok is" | proselint
<stdin>:1:5: corporate_speak.misc Minimize your use of corporate catchphrases like this one.
Learning from all the best writers is a very lofty objective, and proselint
has accumulated some valuable rules, but it falls short of its goal of collecting all the worlds writing advice in a parsable form. Ignoring and excluding rules are also not fully supported.
Coverage
- Formatting: 0
- Spelling: 0
- Grammar: 0
- Clarity: 5
Features
- Ease of Use: 5
- Remediation: 0
- Customization: 0
- IDE support: 5
- CI / CLI Support: 2
Vale
Vale, created by Joseph Kato, supports spelling, grammar, and clarity checks. It is extendable using a YAML rule format and is designed around the idea of a style guide -- a specific house style that you put together and vale enforces. It has an implementation of most proselint
as a style guide, most of write-good
, as well as the Microsoft Writing Style Guide and the Google
developer documentation style guide. Vale is targeted directly at the Docs-as-Code community and documentation teams, who take the writing style of documents very seriously.
Vale is fast and configurable but not necessarily easy to get started with. Initially, I couldn't get it to find any problems until I realized that it needs a config file to run:
Additionally, to use it effectively, you will need to copy an existing style-guide into your repository. Separating the styles from the tool is Vale's biggest strength. It's also could be a weakness as the rules you build up are specific to your repository. It is easy to write and customize rules but hard to share them back as they need to live in your source code repository.
Besides the official Vale style guides Buildkite, Linode, and Write The Docs have rules online that you can copy into your repo or use as inspiration for your own rules.
If you are taking linting documentation seriously and can take the time to set up a style that works for you, then Vale is the way to go. The rules of most other tools can be implemented inside value, and many already are.
Coverage
- Formatting: 2
- Spelling: 5
- Grammar: 5
- Clarity: 5
Features
- Ease of Use: 1
- Remediation: 0
- Customization: 5
- IDE support: 5
- CI / CLI Support: 5
Vale Styles
Summary
Many tools exist for testing and linting English prose. You can start as simply as just spelling checking your readme before you commit it or go as complex as a full style guide running on every change to your software documentation.
If you are willing to invest the time, then Vale
, with its flexible rules, is the clear leader. Combining Vale
with markdownlint
and running both in a continuous integration build should ensure that documents are spelling correctly, grammatically correct, and written in a properly formatted and exclusive way.
If you're looking for a more accessible place to start or don't need the grammar and clarity suggestions, then mdspell
and markdownlint
make a great combination.
Once you have decided on what tools will work best for you, make sure you find a way to automate their usage. This blog uses Vale
and markdownlint
inside an Earthfile that is run every commit. This helps us prevent mistakes from getting into the blog.
Top comments (3)
Appreciate the post, I have seen some of this stuff before, but not used it. I will be looking at this stuff soon. To be honest, at this point in my life I only use MD for basic project READMEs and just tend to use VSCode's 'Markdown-All-In-One' extension (READMEs are the ONLY thing I use Code for...). Really that plugin by itself is good enough to install Code.
As for grammar I'm lazy and just stick what I know:
apsell
. I also use the 'Spell Checker' plugin for Code, but still runaspell
on it just in case...Saved this, thanks again.
Thanks! Vale is reallly amazing in what it can do but you have to setup rules, which can be a bit of a pain. You can approach grammarly type advice for markdown.
markdownlint is amazing though. Easy to start with and pushes towards better markdown. All of this is probably overkill from readmes, but I use it on my markdown based blog and its great.
Yeah, but I never know what I'll be doing and it's always nice to be familiar with options...