remark plugins to check (lint) markdown code style.
- What is this?
- When should I use this?
- Presets
- Rules
- Configure
- Ignore warnings
- Examples
- Integrations
- Syntax
- Compatibility
- Security
- Contribute
- License
You can use this to check markdown.
Say we have a markdown file doc/example.md
that contains:
1) Hello, _Jupiter_ and *Neptune*!
Then assuming we installed dependencies and run:
npx remark doc/ --use remark-preset-lint-consistent --use remark-preset-lint-recommended
We would get a report like this:
doc/example.md
1:2 warning Unexpected ordered list marker `)`, expected `.` ordered-list-marker-style remark-lint
1:25-1:34 warning Unexpected emphasis marker `*`, expected `_` emphasis-marker remark-lint
[cause]:
1:11-1:20 info Emphasis marker style `'_'` first defined for `'consistent'` here emphasis-marker remark-lint
β 2 warnings
This GitHub repository is a monorepo that contains Β±70 plugins (each a rule that checks one specific thing) and 3 presets (combinations of rules configured to check for certain styles).
These packages are build on unified (remark). unified is a project that inspects and transforms content with abstract syntax trees (ASTs). remark adds support for markdown to unified. mdast is the markdown AST that remark uses. These lint rules inspect mdast.
This project is useful when developers or technical writers are authoring documentation in markdown and you want to ensure that the markdown is consistent, free of bugs, and works well across different markdown parsers.
These packages are quite good at checking markdown. They especially shine when combined with other remark plugins and at letting you make your own rules.
Presets are combinations of rules configured to check for certain styles. The following presets only contain lint rules but you can make your own that include any remark plugins or other presets. The presets that are maintained here:
-
remark-preset-lint-consistent
β rules that enforce consistency -
remark-preset-lint-markdown-style-guide
β rules that enforce the markdown style guide -
remark-preset-lint-recommended
β rules that prevent mistakes or stuff that fails across vendors.
The rules that are maintained here:
-
remark-lint-blockquote-indentation
β warn when block quotes are either indented too much or too little -
remark-lint-checkbox-character-style
β warn when list item checkboxes violate a given style -
remark-lint-checkbox-content-indent
β warn when list item checkboxes are followed by too much whitespace -
remark-lint-code-block-style
β warn when code blocks do not adhere to a given style -
remark-lint-definition-case
β warn when definition labels are not lowercase -
remark-lint-definition-spacing
β warn when consecutive whitespace is used in a definition -
remark-lint-emphasis-marker
β warn when emphasis markers violate the given style -
remark-lint-fenced-code-flag
β warn when fenced code blocks occur without language flag -
remark-lint-fenced-code-marker
β warn when fenced code markers violate the given style -
remark-lint-file-extension
β warn when the fileβs extension violates the given style -
remark-lint-final-definition
β warn when definitions are not placed at the end of the file -
remark-lint-final-newline
β warn when a newline at the end of a file is missing -
remark-lint-first-heading-level
β warn when the first heading has a level other than a specified value -
remark-lint-hard-break-spaces
β warn when too many spaces are used to create a hard break -
remark-lint-heading-increment
β warn when headings increment with more than 1 level at a time -
remark-lint-heading-style
β warn when heading style violates the given style -
remark-lint-linebreak-style
β warn when linebreaks violate a given or detected style -
remark-lint-link-title-style
β warn when link and definition titles occur with incorrect quotes -
remark-lint-list-item-bullet-indent
β warn when list item bullets are indented -
remark-lint-list-item-content-indent
β warn when the content of a list item has mixed indentation -
remark-lint-list-item-indent
β warn when the spacing between a list itemβs bullet and its content violates a given style -
remark-lint-list-item-spacing
β warn when list looseness is incorrect -
remark-lint-maximum-heading-length
β warn when headings are too long -
remark-lint-maximum-line-length
β warn when lines are too long -
remark-lint-no-blockquote-without-marker
β warn when blank lines without markers (`>`) are found in a block quote -
remark-lint-no-consecutive-blank-lines
β warn for too many consecutive blank lines -
remark-lint-no-duplicate-defined-urls
β warn on definitions that define the same urls -
remark-lint-no-duplicate-definitions
β warn on duplicate definitions -
remark-lint-no-duplicate-headings
β warn on duplicate headings -
remark-lint-no-duplicate-headings-in-section
β warn on duplicate headings in a section -
remark-lint-no-emphasis-as-heading
β warn when emphasis or importance is used instead of a heading -
remark-lint-no-empty-url
β warn on empty URLs in links and images -
remark-lint-no-file-name-articles
β warn when file name start with an article -
remark-lint-no-file-name-consecutive-dashes
β warn when file names contain consecutive dashes -
remark-lint-no-file-name-irregular-characters
β warn when file names contain irregular characters -
remark-lint-no-file-name-mixed-case
β warn when file names use mixed case -
remark-lint-no-file-name-outer-dashes
β warn when file names contain initial or final dashes -
remark-lint-no-heading-content-indent
β warn when heading content is indented -
remark-lint-no-heading-indent
β warn when headings are indented -
remark-lint-no-heading-like-paragraph
β for too many hashes (h7+ βheadingsβ) -
remark-lint-no-heading-punctuation
β warn when headings end in illegal characters -
remark-lint-no-html
β warn when HTML nodes are used -
remark-lint-no-literal-urls
β warn when URLs without angle brackets are used -
remark-lint-no-missing-blank-lines
β warn when missing blank lines -
remark-lint-no-multiple-toplevel-headings
β warn when multiple top level headings are used -
remark-lint-no-paragraph-content-indent
β warn when the content in paragraphs are indented -
remark-lint-no-reference-like-url
β warn when URLs are also defined identifiers -
remark-lint-no-shell-dollars
β warn when shell code is prefixed by dollars -
remark-lint-no-shortcut-reference-image
β warn when shortcut reference images are used -
remark-lint-no-shortcut-reference-link
β warn when shortcut reference links are used -
remark-lint-no-table-indentation
β warn when tables are indented -
remark-lint-no-tabs
β warn when hard tabs are used instead of spaces -
remark-lint-no-undefined-references
β warn when references to undefined definitions are found -
remark-lint-no-unneeded-full-reference-image
β warn when full reference images are used if they can be collapsed -
remark-lint-no-unneeded-full-reference-link
β warn when full reference links are used if they can be collapsed -
remark-lint-no-unused-definitions
β warn when unused definitions are found -
remark-lint-ordered-list-marker-style
β warn when the markers of ordered lists violate a given style -
remark-lint-ordered-list-marker-value
β warn when the marker value of ordered lists violates a given style -
remark-lint-rule-style
β warn when horizontal rules violate a given style -
remark-lint-strikethrough-marker
β warn when strikethrough markers violate the given style -
remark-lint-strong-marker
β warn when importance (strong) markers violate the given style -
remark-lint-table-cell-padding
β warn when table cells are incorrectly padded -
remark-lint-table-pipe-alignment
β warn when table pipes are not aligned -
remark-lint-table-pipes
β warn when table rows are not fenced with pipes -
remark-lint-unordered-list-marker-style
β warn when markers of unordered lists violate a given style
You can make and share your own rules, which can be used just like the rules maintained here. The following rules are maintained by the community:
-
remark-lint-alphabetize-lists
β ensure list items are in alphabetical order -
remark-lint-appropriate-heading
β check that the top level heading matches the directory name -
remark-lint-are-links-valid
β check if your links are reachable and/or unique -
remark-lint-blank-lines-1-0-2
β ensure a specific number of lines between blocks -
remark-lint-books-links
β ensure links in lists of books follow a standard format -
remark-lint-check-toc
β ensure TOC is correct -
remark-lint-code
β lint fenced code blocks by corresponding language tags, currently supporting ESLint -
remark-lint-code-block-split-list
β ensure code block inside list doesn't split the list -
remark-lint-double-link
β ensure the same URL is not linked multiple times. -
remark-lint-emoji-limit
β enforce a limit of emoji per paragraph -
remark-lint-fenced-code-flag-case
β warn when fenced code blocks have improperly cased language flags -
remark-lint-frontmatter-schema
β validate YAML frontmatter against a JSON schema -
remark-lint-heading-capitalization
β ensure headings capitalization is correct -
remark-lint-heading-length
β ensure headings have the appropriate length -
remark-lint-heading-whitespace
β ensure heading parsing is not broken by weird whitespace -
remark-lint-heading-word-length
β warn when headings have too many or too few words with unicode support -
remark-lint-list-item-style
β warn when list items violate a given capitalization or punctuation style -
remark-lint-match-punctuation
β ensures punctuations are used in pairs if necessary. -
remark-lint-mdash-style
β ensure em-dash (β
) style follows a standard format -
remark-lint-no-chinese-punctuation-in-number
β ensures that Chinese punctuationβs not used in numbers -
remark-lint-no-dead-urls
β check that external links are alive -
remark-lint-no-empty-sections
β ensure every heading is followed by content (forming a section) -
remark-lint-no-long-code
β ensures that each line in code block won't be too long. -
remark-lint-no-repeat-punctuation
β ensures punctuation is not repeated -
remark-lint-no-url-trailing-slash
β ensure that thehref
of links has no trailing slash -
remark-lint-spaces-around-number
β ensures there are spaces around number and Chinese. -
remark-lint-spaces-around-word
β ensures there are spaces around English word and Chinese. -
remark-lint-write-good
β wrapper forwrite-good
For help creating your own rule, itβs suggested to look at existing rules and to follow this tutorial.
All rules can be configured in one standard way:
import {remark} from 'remark'
import remarkLintFinalNewline from 'remark-lint-final-newline'
import remarkLintMaximumLineLength from 'remark-lint-maximum-line-length'
import remarkLintUnorderedListMarkerStyle from 'remark-lint-unordered-list-marker-style'
remark()
// Pass `false` to turn a rule off β the code no longer runs:
.use(remarkLintFinalNewline, false)
// Pass `true` to turn a rule on again:
.use(remarkLintFinalNewline, true)
// You can also configure whether messages by the rule should be ignored,
// are seen as code style warnings (default), or are seen as exceptions.
// Ignore messages with `'off'` or `0` as the first value of an array:
.use(remarkLintFinalNewline, ['off'])
.use(remarkLintFinalNewline, [0])
// Use `'warn'`, `'on'`, or `1` to treat messages as code style warnings:
.use(remarkLintFinalNewline, ['warn'])
.use(remarkLintFinalNewline, ['on'])
.use(remarkLintFinalNewline, [1])
// Use `'error'` or `2` to treat messages as exceptions:
.use(remarkLintFinalNewline, ['error'])
.use(remarkLintFinalNewline, [2])
// Some rules accept options, and what they exactly accept is different for
// each rule (sometimes a string, a number, or an object).
// The following rule accepts a string:
.use(remarkLintUnorderedListMarkerStyle, '*')
.use(remarkLintUnorderedListMarkerStyle, ['on', '*'])
.use(remarkLintUnorderedListMarkerStyle, [1, '*'])
// The following rule accepts a number:
.use(remarkLintMaximumLineLength, 72)
.use(remarkLintMaximumLineLength, ['on', 72])
.use(remarkLintMaximumLineLength, [1, 72])
See use()
in unified
s readme for more info on how to use
plugins.
π§βπ« Info: messages in
remark-lint
are warnings instead of errors. Other linters (such as ESLint) almost always use errors. Why? Those tools only check code style. They donβt generate, transform, and format code, which is what remark and unified focus on, too. Errors in unified mean the same as an exception in your JavaScript code: a crash. Thatβs why we use warnings instead, because we continue checking more markdown and continue running more plugins.
You can use HTML comments to hide or show warnings from within markdown.
Turn off all remark lint messages with <!--lint disable-->
and turn them on
again with <!--lint enable-->
:
<!--lint disable-->
[Naiad]: https://naiad.neptune
[Thalassa]: https://thalassa.neptune
<!--lint enable-->
You can toggle specific rules by using their names without remark-lint-
:
<!--lint disable no-unused-definitions definition-case-->
[Naiad]: https://naiad.neptune
[Thalassa]: https://thalassa.neptune
<!--lint enable no-unused-definitions definition-case-->
You can ignore a message in the next block with <!--lint ignore-->
:
<!--lint ignore-->
[Naiad]: https://naiad.neptune
ignore
also accepts a list of rules:
<!--lint ignore no-unused-definitions definition-case-->
[Naiad]: https://naiad.neptune
π Note: youβll typically need blank lines between HTML comments and other constructs. More info is available at the package that handles comments,
remark-message-control
.
π‘ Tip: MDX comments are supported when
remark-mdx
is used:{/* lint ignore no-unused-definitions definition-case */}
The following example checks that markdown code style is consistent and follows some best practices. It also reconfigures a rule. First install dependencies:
npm install vfile-reporter remark remark-preset-lint-consistent remark-preset-lint-recommended remark-lint-list-item-indent --save-dev
Then create a module example.js
that contains:
import {remark} from 'remark'
import remarkLintListItemIndent from 'remark-lint-list-item-indent'
import remarkPresetLintConsistent from 'remark-preset-lint-consistent'
import remarkPresetLintRecommended from 'remark-preset-lint-recommended'
import {reporter} from 'vfile-reporter'
const file = await remark()
// Check that markdown is consistent.
.use(remarkPresetLintConsistent)
// Few recommended rules.
.use(remarkPresetLintRecommended)
// `remark-lint-list-item-indent` is configured with `one` in the
// recommended preset, but if weβd prefer something else, it can be
// reconfigured:
.use(remarkLintListItemIndent, 'tab')
.process('1) Hello, _Jupiter_ and *Neptune*!')
console.error(reporter(file))
Running that with node example.js
yields:
1:2 warning Unexpected ordered list marker `)`, expected `.` ordered-list-marker-style remark-lint
1:4 warning Unexpected `1` space between list item marker and content, expected `2` spaces, add `1` space list-item-indent remark-lint
1:25-1:34 warning Unexpected emphasis marker `*`, expected `_` emphasis-marker remark-lint
[cause]:
1:11-1:20 info Emphasis marker style `'_'` first defined for `'consistent'` here emphasis-marker remark-lint
1:35 warning Unexpected missing final newline character, expected line feed (`\n`) at end of file final-newline remark-lint
β 4 warnings
remark lint rules check markdown.
remark-stringify
(used in remark) formats markdown.
When you configure lint rules and use remark to format markdown, you must
manually synchronize their configuration:
import {remark} from 'remark'
import remarkLintEmphasisMarker from 'remark-lint-emphasis-marker'
import remarkLintStrongMarker from 'remark-lint-strong-marker'
import {reporter} from 'vfile-reporter'
const file = await remark()
.use(remarkLintEmphasisMarker, '*')
.use(remarkLintStrongMarker, '*')
.use({
settings: {emphasis: '*', strong: '*'} // `remark-stringify` settings.
})
.process('_Hello_, __world__!')
console.error(reporter(file))
console.log(String(file))
Yields:
1:1-1:8 warning Emphasis should use `*` as a marker emphasis-marker remark-lint
1:10-1:19 warning Strong should use `*` as a marker strong-marker remark-lint
β 2 warnings
*Hello*, **world**!
Observe that the lint rules check the input and afterwards remark formats using asterisks. If that output was given the the processor, the lint rules would be satisfied.
This example checks markdown with remark-cli
.
It assumes youβre in a Node.js package.
First install dependencies:
npm install remark-cli remark-preset-lint-consistent remark-preset-lint-recommended remark-lint-list-item-indent --save-dev
Then add an npm script to your package.json
:
/* β¦ */
"scripts": {
/* β¦ */
"check": "remark . --quiet --frail",
/* β¦ */
},
/* β¦ */
π‘ Tip: add ESLint and such in the
check
script too.
Observe that the above change adds a check
script, which can be run with
npm run check
.
It runs remark on all markdown files (.
), shows only warnings and errors
(--quiet
), and exits as failed on warnings (--frail
).
Run ./node_modules/.bin/remark --help
for more info on the CLI.
Now add a remarkConfig
to your package.json
to configure remark:
/* β¦ */
"remarkConfig": {
"plugins": [
"remark-preset-lint-consistent", // Check that markdown is consistent.
"remark-preset-lint-recommended", // Few recommended rules.
// `remark-lint-list-item-indent` is configured with `one` in the
// recommended preset, but if weβd prefer something else, it can be
// reconfigured:
[
"remark-lint-list-item-indent",
"tab"
]
]
},
/* β¦ */
π Note: you must remove the comments in the above examples when copy/pasting them, as comments are not supported in
package.json
files.
Finally run the npm script to check markdown files in your project:
npm run check
remark lint rules check markdown. The CLI can format markdown. You can combine these features but have to manually synchronize their configuration. Please first follow the previous example (checking markdown on the CLI) and then change the npm script:
/* β¦ */
"scripts": {
/* β¦ */
"format": "remark . --frail --output --quiet",
/* β¦ */
},
/* β¦ */
The script is now called format
to reflect what it does.
It now includes an --output
flag, which means it will overwrite existing files
with changes.
Update remarkConfig
:
/* β¦ */
"remarkConfig": {
"settings": {
"emphasis": "*",
"strong": "*"
},
"plugins": [
"remark-preset-lint-consistent",
"remark-preset-lint-recommended",
["remark-lint-list-item-indent", "tab"]
["remark-lint-emphasis-marker", "*"],
["remark-lint-strong-marker", "*"]
]
},
/* β¦ */
This now includes settings
, which configures
remark-stringify
, and explicitly prefers asterisks
for emphasis and strong.
Install the new dependencies:
npm install remark-lint-emphasis-marker remark-lint-strong-marker --save-dev
Finally run the npm script to format markdown files in your project:
npm run format
π Note: running
npm run format
now checks and formats your files. The first time you run it, assuming you have underscores for emphasis and strong, it would first warn and then format. The second time you run it, no warnings should appear.
-
vscode-remark-lint
(VS Code) β useremark-lint
from Visual Studio Code -
SublimeLinter-contrib-remark-lint
(Sublime) β useremark-lint
from Sublime Text -
ale
(Vim) β useremark-lint
from Vim -
jest-runner-remark
(Jest) β use remark with Jest
Markdown is parsed by remark-parse
(included in remark
)
according to CommonMark.
You can combine it with other plugins to add syntax extensions.
Notable examples that deeply integrate with it are
remark-gfm
,
remark-mdx
,
remark-frontmatter
,
remark-math
, and
remark-directive
.
Projects maintained by the unified collective are compatible with maintained versions of Node.js.
When we cut a new major release, we drop support for unmaintained versions of
Node.
This means we try to keep the current release line, remark-lint@9
, compatible
with Node.js 16.
Use of remark-lint
does not change the tree so there are no openings for
cross-site scripting (XSS) attacks.
Messages from linting rules may be hidden from user content though, causing
builds to fail or pass.
See contributing.md
in remarkjs/.github
for ways
to get started.
See support.md
for ways to get help.
This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.
MIT Β© Titus Wormer