A fast, flexible, configuration-based command-line interface for linting Markdown/CommonMark files with the
markdownlintlibrary
As a global CLI:
npm install markdownlint-cli2 --globalAs a development dependency of the current Node.js package:
npm install markdownlint-cli2 --save-devAs a Docker container image:
docker pull davidanson/markdownlint-cli2As a global CLI with Homebrew:
brew install markdownlint-cli2As a GitHub Action via
markdownlint-cli2-action:
- name: markdownlint-cli2-action
uses: DavidAnson/markdownlint-cli2-action@mainmarkdownlintis a library for linting Markdown/ CommonMark files on Node.js using the markdown-it parser.markdownlint-cliis a traditional command-line interface formarkdownlint.markdownlint-cli2is a slightly unconventional command-line interface formarkdownlint.markdownlint-cli2is configuration-based and prioritizes speed and simplicity.markdownlint-cli2supports all the features ofmarkdownlint-cli(sometimes a little differently).vscode-markdownlintis amarkdownlintextension for the Visual Studio Code editor.markdownlint-cli2is designed to work well in conjunction withvscode-markdownlint.- More about the motivation for
markdownlint-cli2.
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) passing
glob0 ... globN on the command-line.
As shown above, a typical command-line for markdownlint-cli2 looks something
like:
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 (see
below) to true (though it can still be overridden by a configuration file):
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 any
supported configuration file (except package.json):
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
can also be used (e.g., as part of a CI pipeline):
docker run -v $PWD:/workdir davidanson/markdownlint-cli2:v0.19.0 "**/*.md" "#node_modules"Notes:
- As when using the command line, glob patterns are passed as arguments.
- This image is built on the official Node.js Docker image.
Per security best practices, the default user
noderuns with restricted permissions. If it is necessary to run asroot, pass the-u rootoption when invokingdocker. - By default,
markdownlint-cli2will execute within the/workdirdirectory inside the container. So, as shown above, bind mount the project's directory there.-
A custom working directory can be specified with Docker's
-wflag:docker run -w /myfolder -v $PWD:/myfolder davidanson/markdownlint-cli2:v0.19.0 "**/*.md" "#node_modules"
-
For convenience, the container image
davidanson/markdownlint-cli2-rules
includes the latest versions of custom rules published to npm with the tag
markdownlint-rule. These rules are installed globally
onto the base image davidanson/markdownlint-cli2.
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)
- List of issues with color and links
- GitLab Code Quality report file
- JSON file
- JUnit XML file
- Static Analysis Results Interchange Format/SARIF file
- Summary of issues found
- Flexible string template supporting:
- Azure Pipelines Task command LogIssue format
- GitHub Actions workflow commands format
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), and
reading the formatted result from standard output (stdout). This scenario is
supported by the --format command-line parameter. When --format is set:
- Globs and other input sources are ignored
- The
--fixparameter is implicitly set - The exit code
1is not used
- See the Rules / Aliases and
Tags sections of the
markdownlintdocumentation.
- Globbing is performed by the globby library; refer to that documentation for more information and examples.
- See the Configuration section of the
markdownlintdocumentation 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 (typically$HOMEon UNIX and%USERPROFILE%on Windows) - There are two kinds of configuration file (both detailed below):
- Configuration files like
.markdownlint-cli2.*allow complete control ofmarkdownlint-cli2behavior and are also used byvscode-markdownlint.- If multiple of these files are present in the same directory, only one is
used according to the following precedence:
.markdownlint-cli2.jsonc.markdownlint-cli2.yaml.markdownlint-cli2.cjs.markdownlint-cli2.mjspackage.json(only supported in the current directory)
- If multiple of these files are present in the same directory, only one is
used according to the following precedence:
- Configuration files like
.markdownlint.*allow control over only themarkdownlintconfigobject and tend to be supported more broadly (such as bymarkdownlint-cli).- If multiple of these files are present in the same directory, only one is
used according to the following precedence:
.markdownlint.jsonc.markdownlint.json.markdownlint.yaml.markdownlint.yml.markdownlint.cjs.markdownlint.mjs
- If multiple of these files are present in the same directory, only one is
used according to the following precedence:
- Configuration files like
- The VS Code extension includes a JSON Schema definition for the
JSON(C)configuration files described below. This adds auto-complete and can make it easier to define proper structure. - See markdownlint-cli2-config-schema.json for that schema and ValidatingConfiguration.md for ways to use it to validate configuration files.
- The format of this file is a JSONC object similar to the
markdownlintoptionsobject. - Valid properties are:
config:markdownlintconfigobject to configure rules for this part of the directory tree- If a
.markdownlint.{jsonc,json,yaml,yml,js}file (see below) is present in the same directory, it overrides the value of this property - If the
configobject contains anextendsproperty, it will be resolved the same as.markdownlint.{jsonc,json,yaml,yml,js}(see below)
- If a
customRules:ArrayofStrings (orArrays ofStrings) of module names/paths of custom rules to load and use when linting- Relative paths are resolved based on the location of the
JSONCfile - Search
markdownlint-ruleon npm
- Relative paths are resolved based on the location of the
fix:Booleanvalue to enable fixing of linting errors reported by rules that emit fix information- Fixes are made directly to the relevant file(s); no backup is created
frontMatter:Stringdefining theRegExpused to match and ignore any front matter at the beginning of a document- The
Stringis passed as thepatternparameter to theRegExpconstructor - For example:
(^---\s*$[^]*?^---\s*$)(\r\n|\r|\n|$)
- The
gitignore:BooleanorStringvalue to automatically ignore files referenced by.gitignore(or similar) when linting- When the value
trueis specified, all.gitignorefiles in the tree are imported (defaultgitbehavior) - When a
Stringvalue is specified, that glob pattern is used to identify the set of ignore files to import- The value
**/.gitignorecorresponds to theBooleanvaluetrue - The value
.gitignoreimports only the file in the root of the tree; this is usually equivalent and can be much faster for large trees
- The value
- This top-level setting is valid only in the directory from which
markdownlint-cli2is run
- When the value
globs:ArrayofStrings defining glob expressions to append to the 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
--no-globsparameter is passed on the command-line - This top-level setting is valid only in the directory from which
markdownlint-cli2is run
ignores:ArrayofStrings defining glob expressions to ignore when linting- This setting has the best performance when applied to the directory from
which
markdownlint-cli2is run- In this case, glob expressions are negated (by adding a leading
!) and appended to the command-line arguments before file enumeration - The setting is not inherited by nested configuration files in this case
- In this case, glob expressions are negated (by adding a leading
- 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
- This setting has the best performance when applied to the directory from
which
markdownItPlugins:ArrayofArrays, each of which has aStringnaming a markdown-it plugin followed by parameters- Plugins can be used to add support for additional Markdown syntax
- Relative paths are resolved based on the location of the
JSONCfile - For example:
[ [ "plugin-name", param_0, param_1, ... ], ... ] - Search
markdown-it-pluginson npm
modulePaths:ArrayofStrings providing additional paths to use when resolving module references (e.g., alternate locations fornode_modules)noBanner:Booleanvalue to disable the display of the banner message and version numbers onstdout- This top-level setting is valid only in the directory from which
markdownlint-cli2is run - Use with
noProgressto suppress all output tostdout(i.e.,--quiet)
- This top-level setting is valid only in the directory from which
noInlineConfig:Booleanvalue to disable the support of HTML comments within Markdown content- For example:
<!-- markdownlint-disable some-rule -->
- For example:
noProgress:Booleanvalue to disable the display of progress onstdout- This top-level setting is valid only in the directory from which
markdownlint-cli2is run - Use with
noBannerto suppress all output tostdout(i.e.,--quiet)
- This top-level setting is valid only in the directory from which
outputFormatters:ArrayofArrays, each of which has aStringnaming an output formatter 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
JSONCfile - For example:
[ [ "formatter-name", param_0, param_1, ... ], ... ] - This top-level setting is valid only in the directory from which
markdownlint-cli2is run - Search
markdownlint-cli2-formatteron npm
showFound:Booleanvalue to display the list of found files onstdout- This top-level setting is valid only in the directory from which
markdownlint-cli2is run and only whennoProgresshas not been set
- This top-level setting is valid only in the directory from which
- When referencing a module via the
customRules,markdownItPlugins, oroutputFormattersproperties, eachStringidentifier is passed to Node'srequirefunction then (if that failed) itsimportexpression- Importing a locally-installed module using a bare specifier (ex:
package-name) or using a directory name (ex:./package-dir) will not work untilimport.meta.resolveis available
- Importing a locally-installed module using a bare specifier (ex:
- 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.jsoncwith all properties set
- The format of this file is a YAML object with the structure described
above for
.markdownlint-cli2.jsonc. - Other details are the same as for
.markdownlint-cli2.jsoncdescribed above. - For example:
.markdownlint-cli2.yamlwith all properties set
- The format of this file is a CommonJS module (
.cjs) or ECMAScript module (.mjs) that exports the object described above for.markdownlint-cli2.jsonc(directly or from aPromise). - Instead of passing a
Stringto identify the module name/path to load forcustomRules,markdownItPlugins, andoutputFormatters, the correspondingObjectorFunctioncan be provided directly. - Other details are the same as for
.markdownlint-cli2.jsoncdescribed above. - For example:
.markdownlint-cli2.cjsor.markdownlint-cli2.mjs
- The format of this file is a standard npm
package.jsonfile including amarkdownlint-cli2property at the root and a value corresponding to the object described above for.markdownlint-cli2.jsonc. package.jsonis only supported in the current directory.package.jsonis not supported by the--configargument.- For example:
package-json-sample
- The format of this file is a JSONC or JSON object matching
the
markdownlintconfigobject. - 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
extendsproperty (documented in the link above). - Both file types support comments in JSON.
- For example:
.markdownlint.jsonc
- The format of this file is a YAML object representing the
markdownlintconfigobject. - Other details are the same as for
jsonc/jsonfiles described above. - For example:
.markdownlint.yaml
- The format of this file is a CommonJS module (
.cjs) or ECMAScript module (.mjs) that exports themarkdownlintconfigobject (directly or from aPromise). - Other details are the same as for
jsonc/jsonfiles described above. - For example:
.markdownlint.cjsor.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
INIconfig format,.markdownlintrc, and.markdownlintignoreare not supported.
To run markdownlint-cli2 as part of a pre-commit workflow, add a
reference to the repos list in that project's .pre-commit-config.yaml like:
- repo: https://github.com/DavidAnson/markdownlint-cli2
rev: v0.19.0
hooks:
- id: markdownlint-cli2Depending on the environment that workflow runs in, it may be necessary to override the version of Node.js used by pre-commit.
See CHANGELOG.md.