At Mapbox, we write a majority of documentation in markdown. We have a suite of markdown linters to help us stay consistent and improve the quality of our documentation.
Our suite includes remark plugins to lint markdown. We have built our own plugins and use many from the community:
- Check links
- Assert frontmatter
- Lint JSX in markdown
- Check variables
- Improve link text
- Improve accessibility
- Assert heading level increment
- A shared remark configuration
When reviewing content, it’s easy to forget to check that links work and since it can be automated, you shouldn’t have to do it.
Our link checker:
- Checks for broken links in markdown files.
- Fails links that have a hardcoded Mapbox access token. We prefer the contributor use a variable so we can manage access tokens in one place.
- Swaps out any variables in links (such as version numbers) to properly check the link.
- Requires links that are relative to our subdomain be formatted consistently to improve search engine optimization (SEO).
I’m only scratching the surface with the intricacies of our link checker and for that reason our linter in private. Our linter is based off of David Clark’s remark-lint-no-dead-urls.
For SEO, we assert that every page has a
description that will be used by the
title and meta description elements in the page’s
head. We also assert:
layout- Used by our component library’s
PageLayoutcomponent to choose which layout to display.
contentType- One of:
tutorial. This allows us to internally define the content for reporting and tracking.
products- An array of Mapbox product names that are included on the page. This helps us track documentation for every product.
We have several more properties that we assert that can disable or enable features on the page.
Lint JSX in markdown
Our static site generator, Batfish, uses jsxtreme-markdown to transform markdown into React components. This means that many our of markdown pages include JSX syntax.
Our linter, affectionately known as xtreme-linter, will:
- Make sure an imported module can be resolved to a module on the local file system (
- Check for undeclared variables in JSX (
- Find unused variables (
- Find undeclared variables (
I love all our linters, but this one the most.
Since we can use JSX in markdown, we also use variables for repeated information like access tokens and version numbers. We built a remark-linter that will scan markdown pages for variables and then assert that the variable exists in the repository’s local
Improve link text
We developed a remark linter, remark-lint-link-text, that warns against non-descriptive link text. The linter warns against the following link text:
- click here
- read more
- this link
- more here
- this article
Our newest remark linter helps check that all
iframe elements and our React component
DemoIframe have a
title attribute and all
img elements and our React component
AppropriateImage have an
alt attribute. While remark linters already exist to find missing alt text like remark-lint-no-empty-image-alt-text and @double-great/remark-lint-alt-text, we needed to extend it to our React components since we use them in our markdown files.
Assert heading level increment
Another remark linter that we love is remark-lint-heading-increment. This linter asserts that headings are always in order. This is especially helpful for longer pages and pages with a lots of sections.
A shared remark configuration
Finally, we bundle all the remark linters into a shared remark configuration. The shared configuration prevents us from having to repeat code in every repository and help streamline updates.
These linters help guide our contributors to writing better documentation and allows our team to focus more closely on the content during reviews.