A fast, flexible, configuration-based command-line interface for linting Markdown/CommonMark files with the `markdownlint` library
npm install markdownlint-cli2> A fast, flexible, configuration-based command-line interface for linting
> Markdown/CommonMark files with the markdownlint library
[![npm version][npm-image]][npm-url]
[![License][license-image]][license-url]
As a global CLI:
``bash`
npm install markdownlint-cli2 --global
As a development dependency of the current [Node.js][nodejs] package:
`bash`
npm install markdownlint-cli2 --save-dev
As a [Docker][docker] container image:
`bash`
docker pull davidanson/markdownlint-cli2
As a global CLI with [Homebrew][homebrew]:
`bash`
brew install markdownlint-cli2
As a [GitHub Action][github-action] via
[markdownlint-cli2-action][markdownlint-cli2-action]:
`yaml`
- name: markdownlint-cli2-action
uses: DavidAnson/markdownlint-cli2-action@main
- [markdownlint][markdownlint] is a library for linting [Markdown][markdown]/markdownlint-cli
[CommonMark][commonmark] files on [Node.js][nodejs] using the
[markdown-it][markdown-it] parser.
- [][markdownlint-cli] is a traditional command-line interfacemarkdownlint
for .markdownlint-cli2
- [][markdownlint-cli2] is a slightly unconventionalmarkdownlint
command-line interface for .markdownlint-cli2
- is configuration-based and prioritizes speed andmarkdownlint-cli2
simplicity.
- supports all the features of markdownlint-cli (sometimesvscode-markdownlint
a little differently).
- [][vscode-markdownlint] is a markdownlint extension formarkdownlint-cli2
the [Visual Studio Code editor][vscode].
- is designed to work well in conjunction withvscode-markdownlint
.markdownlint-cli2
- More about the [motivation for ][markdownlint-cli2-blog].
`text
markdownlint-cli2 vX.Y.Z (markdownlint vX.Y.Z)
https://github.com/DavidAnson/markdownlint-cli2
Syntax: markdownlint-cli2 glob0 [glob1] [...] [globN] [--config file] [--fix] [--format] [--help] [--no-globs]
Glob expressions (from the globby library):
- * matches any number of characters, but not /
- ? matches a single character, but not /
- ** matches any number of characters, including /
- {} allows for a comma-separated list of "or" expressions
- ! or # at the beginning of a pattern negate the match
- : at the beginning identifies a literal file path
- - as a glob represents standard input (stdin)
Dot-only glob:
- The command "markdownlint-cli2 ." would lint every file in the current directory tree which is probably not intended
- Instead, it is mapped to "markdownlint-cli2 *.{md,markdown}" which lints all Markdown files in the current directory
- To lint every file in the current directory tree, the command "markdownlint-cli2 **" can be used instead
Optional parameters:
- --config specifies the path to a configuration file to define the base configuration
- --fix updates files to resolve fixable issues (can be overridden in configuration)
- --format reads standard input (stdin), applies fixes, writes standard output (stdout)
- --help writes this message to the console and exits without doing anything else
- --no-globs ignores the "globs" property if present in the top-level options object
Configuration via:
- .markdownlint-cli2.jsonc
- .markdownlint-cli2.yaml
- .markdownlint-cli2.cjs or .markdownlint-cli2.mjs
- .markdownlint.jsonc or .markdownlint.json
- .markdownlint.yaml or .markdownlint.yml
- .markdownlint.cjs or .markdownlint.mjs
- package.json
Cross-platform compatibility:
- UNIX and Windows shells expand globs according to different rules; quoting arguments is recommended
- Some Windows shells don't handle single-quoted (') arguments well; double-quote (") is recommended
- Shells that expand globs do not support negated patterns (!node_modules); quoting is required here
- Some UNIX shells parse exclamation (!) in double-quotes; hashtag (#) is recommended in these cases
- The path separator is forward slash (/) on all platforms; backslash (\) is automatically converted
- On any platform, passing the parameter "--" causes all remaining parameters to be treated literally
The most compatible syntax for cross-platform support:
$ markdownlint-cli2 "*/.md" "#node_modules"
`
For scenarios where it is preferable to specify glob expressions in a
configuration file, the globs property of .markdownlint-cli2.jsonc, .yaml,.cjs, or .mjs may be used instead of (or in addition to) passingglob0 ... globN on the command-line.
As shown above, a typical command-line for markdownlint-cli2 looks something
like:
`bash`
markdownlint-cli2 "*/.md" "#node_modules"
Because sharing the same configuration between "normal" and "fix" modes is
common, the --fix argument can be used to default the fix property (seetrue
below) to (though it can still be overridden by a configuration file):
`bash`
markdownlint-cli2 --fix "*/.md" "#node_modules"
In cases where it is not convenient to store a configuration file in the root
of a project, the --config argument can be used to provide a path to anypackage.json
supported configuration file (except ):
`bash`
markdownlint-cli2 --config "config/.markdownlint-cli2.jsonc" "*/.md" "#node_modules"
The configuration file name must be (or end with) one of the supported names
above. For example, .markdownlint.json or example.markdownlint-cli2.jsonc.
The specified configuration file will be loaded, parsed, and applied as a base
configuration for the current directory - which will then be handled normally.
A container image [davidanson/markdownlint-cli2][docker-hub-markdownlint-cli2]
can also be used (e.g., as part of a CI pipeline):
`bash`
docker run -v $PWD:/workdir davidanson/markdownlint-cli2:v0.20.0 "*/.md" "#node_modules"
Notes:
- As when using the [command line][command-line], glob patterns are passed as
arguments.
- This image is built on the official [Node.js Docker image][nodejs-docker].
Per security best practices, the [default user node][nodejs-docker-non-root]root
runs with restricted permissions. If it is necessary to run as , pass-u root
the option when invoking docker.markdownlint-cli2
- By default, will execute within the /workdir directory-w
inside the container. So, as shown above, [bind mount][docker-bind-mounts]
the project's directory there.
- A custom working directory can be specified with Docker's flag:
`bash`
docker run -w /myfolder -v $PWD:/myfolder davidanson/markdownlint-cli2:v0.20.0 "*/.md" "#node_modules"
For convenience, the container image
[davidanson/markdownlint-cli2-rules][docker-hub-markdownlint-cli2-rules]markdownlint-rule
includes the latest versions of custom rules published to npm with the tag
[][markdownlint-rule]. These rules are installed globallydavidanson/markdownlint-cli2
onto the base image .
Note: This container image exists for convenience and is not an endorsement
of the rules within.
In addition to (or instead of) the default behavior of writing a list of all
issues to the standard error (stderr) device, custom output formatters can be
configured to produce a variety of outputs like:
- [List of issues (default)][formatter-default]
- [List of issues with color and links][formatter-pretty]
- [GitLab Code Quality report file][formatter-codequality]
- [JSON file][formatter-json]
- [JUnit XML file][formatter-junit]
- [Static Analysis Results Interchange Format/SARIF file][formatter-sarif]
- [Summary of issues found][formatter-summarize]
- [Flexible string template][formatter-template] supporting:
- Azure Pipelines Task command LogIssue format
- GitHub Actions workflow commands format
[formatter-default]: ./formatter-default/README.md
[formatter-codequality]: ./formatter-codequality/README.md
[formatter-json]: ./formatter-json/README.md
[formatter-junit]: ./formatter-junit/README.md
[formatter-pretty]: ./formatter-pretty/README.md
[formatter-sarif]: ./formatter-sarif/README.md
[formatter-summarize]: ./formatter-summarize/README.md
[formatter-template]: ./formatter-template/README.md
For more information, refer to the documentation for the outputFormatters
parameter below.
- 0: Linting was successful and there were no errors (there may be warnings)1
- : Linting was successful and there were errors (and possibly warnings)2
- : Linting was not successful due to a problem or failure
Some editors implement document formatting by invoking an external program,
passing the text of the current document on standard input (stdin), andstdout
reading the formatted result from standard output (). This scenario is--format
supported by the command-line parameter. When --format is set:
- Globs and other input sources are ignored
- The --fix parameter is implicitly set1
- The exit code is not used
- See the [Rules / Aliases][markdownlint-rules-aliases] and
[Tags][markdownlint-rules-tags] sections of the markdownlint documentation.
- Globbing is performed by the [globby][globby] library; refer to that
documentation for more information and examples.
- See the [Configuration][markdownlint-configuration] section of the
markdownlint documentation for information about the inline comment syntax~
for enabling and disabling rules with HTML comments.
- In general, glob expressions should match files under the current directory;
the configuration for that directory will apply to the entire tree.
- When glob expressions match files not under the current directory,
configuration for the current directory is applied to the closest common
parent directory.
- Paths beginning with are resolved relative to the user's home directory$HOME
(typically on UNIX and %USERPROFILE% on Windows).markdownlint-cli2.*
- There are two kinds of configuration file (both detailed below):
- Configuration files like allow complete control ofmarkdownlint-cli2
behavior and are also used by vscode-markdownlint..markdownlint-cli2.jsonc
- If multiple of these files are present in the same directory, only one is
used according to the following precedence:
1. .markdownlint-cli2.yaml
2. .markdownlint-cli2.cjs
3. .markdownlint-cli2.mjs
4. package.json
5. (only supported in the current directory).markdownlint.*
- Configuration files like allow control over only themarkdownlint
config object and tend to be supported more broadly (suchmarkdownlint-cli
as by )..markdownlint.jsonc
- If multiple of these files are present in the same directory, only one is
used according to the following precedence:
1. .markdownlint.json
2. .markdownlint.yaml
3. .markdownlint.yml
4. .markdownlint.cjs
5. .markdownlint.mjs
6. JSON(C)
- The VS Code extension includes a [JSON Schema][json-schema] definition for the
configuration files described below. This adds auto-complete and can
make it easier to define proper structure.
- See [markdownlint-cli2-config-schema.json][markdownlint-cli2-config-schema]
for that schema and [ValidatingConfiguration.md][validating-configuration] for
ways to use it to validate configuration files.
- The format of this file is a [JSONC][jsonc] object similar to the
[markdownlint options object][markdownlint-options].config
- Valid properties are:
- : [markdownlint config object][markdownlint-config] to configure.markdownlint.{jsonc,json,yaml,yml,js}
rules for this part of the directory tree
- If a file (see below) is presentconfig
in the same directory, it overrides the value of this property
- If the object contains an extends property, it will be resolved.markdownlint.{jsonc,json,yaml,yml,js}
the same as (see below)customRules
- : Array of Strings (or Arrays of Strings) of moduleJSONC
names/paths of [custom rules][markdownlint-custom-rules] to load and use
when linting
- Relative paths are resolved based on the location of the filemarkdownlint-rule
- Search [ on npm][markdownlint-rule]fix
- : Boolean value to enable fixing of linting errors reported by rulesfrontMatter
that emit fix information
- Fixes are made directly to the relevant file(s); no backup is created
- : String defining the [RegExp][regexp] used to match andString
ignore any [front matter][front-matter] at the beginning of a document
- The is passed as the pattern parameter to theRegExp
[ constructor][regexp-constructor](^---\s$[^]?^---\s*$)(\r\n|\r|\n|$)
- For example: gitignore
- : Boolean or String value to automatically ignore files.gitignore
referenced by (or similar) when lintingtrue
- When the value is specified, all .gitignore files in the tree aregit
imported (default behavior)String
- When a value is specified, that glob pattern is used to identify**/.gitignore
the set of ignore files to import
- The value corresponds to the Boolean value true.gitignore
- The value imports only the file in the root of the tree;markdownlint-cli2
this is usually equivalent and can be much faster for large trees
- This top-level setting is valid only in the directory from which
is runglobs
- : Array of Strings defining glob expressions to append to the--no-globs
command-line arguments
- This setting can be used instead of (or in addition to) passing globs on
the command-line and offers identical performance
- This setting is ignored when the parameter is passed on themarkdownlint-cli2
command-line
- This top-level setting is valid only in the directory from which
is runignores
- : Array of Strings defining glob expressions to ignore whenmarkdownlint-cli2
linting
- This setting has the best performance when applied to the directory from
which is run!
- In this case, glob expressions are negated (by adding a leading ) andmarkdownItPlugins
appended to the command-line arguments before file enumeration
- The setting is not inherited by nested configuration files in this case
- When this setting is applied in subdirectories, ignoring of files is done
after file enumeration, so large directories can negatively impact
performance
- Nested configuration files inherit and reapply the setting to the
contents of nested directories in this case
- : Array of Arrays, each of which has a StringJSONC
naming a [markdown-it plugin][markdown-it-syntax-extensions] followed by
parameters
- Plugins can be used to add support for additional Markdown syntax
- Relative paths are resolved based on the location of the file[ [ "plugin-name", param_0, param_1, ... ], ... ]
- For example: markdown-it-plugins
- Search [ on npm][markdown-it-plugins]modulePaths
- : Array of Strings providing additional paths to use whennode_modules
resolving module references (e.g., alternate locations for )noBanner
- : Boolean value to disable the display of the banner message andstdout
version numbers on markdownlint-cli2
- This top-level setting is valid only in the directory from which
is runnoProgress
- Use with to suppress all output to stdout (i.e., --quiet)noInlineConfig
- : Boolean value to disable the support of
[HTML comments][html-comment] within Markdown content
- For example: noProgress
- : Boolean value to disable the display of progress on stdoutmarkdownlint-cli2
- This top-level setting is valid only in the directory from which
is runnoBanner
- Use with to suppress all output to stdout (i.e., --quiet)outputFormatters
- : Array of Arrays, each of which has a StringJSONC
naming an [output formatter][output-formatters] followed by parameters
- Formatters can be used to customize the tool's output for different
scenarios
- Relative paths are resolved based on the location of the file[ [ "formatter-name", param_0, param_1, ... ], ... ]
- For example: markdownlint-cli2
- This top-level setting is valid only in the directory from which
is runmarkdownlint-cli2-formatter
- Search [ on npm][markdownlint-cli2-formatter]showFound
- : Boolean value to display the list of found files on stdoutmarkdownlint-cli2
- This top-level setting is valid only in the directory from which
is run and only when noProgress has not been setcustomRules
- When referencing a module via the , markdownItPlugins, oroutputFormatters
properties, each String identifier is passed to Node'srequire
[ function][nodejs-require] then (if that failed) itsimport
[ expression][nodejs-import-expression]package-name
- Importing a locally-installed module using a bare specifier (ex:
) or using a directory name (ex: ./package-dir) will notimport.meta.resolve
work until [][nodejs-import-meta-resolve] is available.markdownlint-cli2.jsonc
- Settings in this file apply to the directory it is in and all subdirectories.
- Settings merge with those applied by any versions of this file in a parent
directory (up to the current directory).
- For example: [][markdownlint-cli2-jsonc] with all
properties set
- The format of this file is a [YAML][yaml] object with the structure described
above for .markdownlint-cli2.jsonc..markdownlint-cli2.jsonc
- Other details are the same as for described above..markdownlint-cli2.yaml
- For example: [][markdownlint-cli2-yaml] with all
properties set
- The format of this file is a [CommonJS module][commonjs-module] (.cjs) or.mjs
[ECMAScript module][ecmascript-module] () that exports the object.markdownlint-cli2.jsonc
described above for (directly or from a Promise).String
- Instead of passing a to identify the module name/path to load forcustomRules
, markdownItPlugins, and outputFormatters, the correspondingObject
or Function can be provided directly..markdownlint-cli2.jsonc
- Other details are the same as for described above..markdownlint-cli2.cjs
- For example: [][markdownlint-cli2-cjs] or.markdownlint-cli2.mjs
[][markdownlint-cli2-mjs]
- The format of this file is a standard [npm package.json][package-json] filemarkdownlint-cli2
including a property at the root and a value corresponding.markdownlint-cli2.jsonc
to the object described above for .package.json
- is only supported in the current directory.package.json
- is not supported by the --config argument.package-json-sample
- For example: [][package-json-sample]
- The format of this file is a [JSONC][jsonc] or [JSON][json] object matching
the [markdownlint config object][markdownlint-config].extends
- Settings in this file apply to the directory it is in and all subdirectories
- Settings override those applied by any versions of this file in a parent
directory (up to the current directory).
- To merge the settings of these files or share configuration, use the .markdownlint.jsonc
property (documented in the link above).
- Both file types support comments in JSON.
- For example: [][markdownlint-jsonc]
- The format of this file is a [YAML][yaml] object representing the
[markdownlint config object][markdownlint-config].jsonc
- Other details are the same as for /json files described above..markdownlint.yaml
- For example: [][markdownlint-yaml]
- The format of this file is a [CommonJS module][commonjs-module] (.cjs) or.mjs
[ECMAScript module][ecmascript-module] () that exports themarkdownlint
[ config object][markdownlint-config] (directly or from aPromise
).jsonc
- Other details are the same as for /json files described above..markdownlint.cjs
- For example: [][markdownlint-cjs] or.markdownlint.mjs
[][markdownlint-mjs]
- The glob implementation and handling of pattern matching is slightly
different.
- Configuration files are supported in every directory (vs. only one at the
root).
- The INI config format, .markdownlintrc, and .markdownlintignore are not
supported.
To run markdownlint-cli2 as part of a [pre-commit][pre-commit] workflow, add arepos
reference to the list in that project's .pre-commit-config.yaml like:
`yaml``
- repo: https://github.com/DavidAnson/markdownlint-cli2
rev: v0.20.0
hooks:
- id: markdownlint-cli2
> Depending on the environment that workflow runs in, it may be necessary to
> [override the version of Node.js used by pre-commit][pre-commit-version].
See [CHANGELOG.md][changelog].
[changelog]: CHANGELOG.md
[command-line]: #command-line
[commonmark]: https://commonmark.org/
[commonjs-module]: https://nodejs.org/api/modules.html#modules_modules_commonjs_modules
[ecmascript-module]: https://nodejs.org/api/esm.html#modules-ecmascript-modules
[docker]: https://www.docker.com
[docker-bind-mounts]: https://docs.docker.com/storage/bind-mounts/
[docker-hub-markdownlint-cli2]: https://hub.docker.com/r/davidanson/markdownlint-cli2
[docker-hub-markdownlint-cli2-rules]: https://hub.docker.com/r/davidanson/markdownlint-cli2-rules
[front-matter]: https://jekyllrb.com/docs/frontmatter/
[github-action]: https://docs.github.com/actions
[globby]: https://www.npmjs.com/package/globby
[homebrew]: https://brew.sh
[html-comment]: https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/Getting_started
[json]: https://wikipedia.org/wiki/JSON
[json-schema]: https://json-schema.org
[jsonc]: https://code.visualstudio.com/Docs/languages/json#_json-with-comments
[license-image]: https://img.shields.io/npm/l/markdownlint-cli2.svg
[license-url]: https://opensource.org/licenses/MIT
[markdown]: https://wikipedia.org/wiki/Markdown
[markdown-it]: https://www.npmjs.com/package/markdown-it
[markdown-it-plugins]: https://www.npmjs.com/search?q=keywords:markdown-it-plugin
[markdown-it-syntax-extensions]: https://github.com/markdown-it/markdown-it#syntax-extensions
[markdownlint]: https://github.com/DavidAnson/markdownlint
[markdownlint-config]: https://github.com/DavidAnson/markdownlint/blob/v0.40.0/README.md#optionsconfig
[markdownlint-configuration]: https://github.com/DavidAnson/markdownlint/blob/v0.40.0/README.md#configuration
[markdownlint-custom-rules]: https://github.com/DavidAnson/markdownlint/blob/v0.40.0/doc/CustomRules.md
[markdownlint-options]: https://github.com/DavidAnson/markdownlint/blob/v0.40.0/README.md#options
[markdownlint-rules-aliases]: https://github.com/DavidAnson/markdownlint/blob/v0.40.0/README.md#rules--aliases
[markdownlint-rules-tags]: https://github.com/DavidAnson/markdownlint/blob/v0.40.0/README.md#tags
[markdownlint-cli]: https://github.com/igorshubovych/markdownlint-cli
[markdownlint-cli2]: https://github.com/DavidAnson/markdownlint-cli2
[markdownlint-cli2-action]: https://github.com/marketplace/actions/markdownlint-cli2-action
[markdownlint-cli2-blog]: https://dlaa.me/blog/post/markdownlintcli2
[markdownlint-cli2-cjs]: test/markdownlint-cli2-cjs/.markdownlint-cli2.cjs
[markdownlint-cli2-config-schema]: schema/markdownlint-cli2-config-schema.json
[markdownlint-cli2-formatter]: https://www.npmjs.com/search?q=keywords:markdownlint-cli2-formatter
[markdownlint-cli2-jsonc]: test/markdownlint-cli2-jsonc-example/.markdownlint-cli2.jsonc
[markdownlint-cli2-mjs]: test/markdownlint-cli2-mjs/.markdownlint-cli2.mjs
[markdownlint-cli2-yaml]: test/markdownlint-cli2-yaml-example/.markdownlint-cli2.yaml
[markdownlint-cjs]: test/markdownlint-cjs/.markdownlint.cjs
[markdownlint-jsonc]: https://github.com/DavidAnson/markdownlint/blob/v0.40.0/schema/.markdownlint.jsonc
[markdownlint-mjs]: test/markdownlint-mjs/.markdownlint.mjs
[markdownlint-rule]: https://www.npmjs.com/search?q=keywords:markdownlint-rule
[markdownlint-yaml]: https://github.com/DavidAnson/markdownlint/blob/v0.40.0/schema/.markdownlint.yaml
[nodejs]: https://nodejs.org/
[nodejs-docker]: https://github.com/nodejs/docker-node
[nodejs-docker-non-root]: https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#non-root-user
[nodejs-import-expression]: https://nodejs.org/api/esm.html#import-expressions
[nodejs-import-meta-resolve]: https://nodejs.org/api/esm.html#importmetaresolvespecifier
[nodejs-require]: https://nodejs.org/api/modules.html#modules_require_id
[npm-image]: https://img.shields.io/npm/v/markdownlint-cli2.svg
[npm-url]: https://www.npmjs.com/package/markdownlint-cli2
[output-formatters]: doc/OutputFormatters.md
[package-json]: https://docs.npmjs.com/cli/v9/configuring-npm/package-json
[package-json-sample]: test/package-json/package.json
[pre-commit]: https://pre-commit.com/
[pre-commit-version]: https://pre-commit.com/#overriding-language-version
[regexp]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
[regexp-constructor]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/RegExp
[validating-configuration]: schema/ValidatingConfiguration.md
[vscode]: https://code.visualstudio.com/
[vscode-markdownlint]: https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint
[yaml]: https://wikipedia.org/wiki/YAML