A Node.js style checker and lint tool for Markdown/CommonMark files.
Find a file
2015-04-15 18:24:42 -07:00
doc Add MD038, MD039 with tests. 2015-04-15 18:24:42 -07:00
example Add synchronous version of the API, with tests and documentation. 2015-03-20 00:09:55 -07:00
lib Add MD038, MD039 with tests. 2015-04-15 18:24:42 -07:00
style Add MD035 with tests. 2015-04-14 09:40:16 -07:00
test Add MD038, MD039 with tests. 2015-04-15 18:24:42 -07:00
.eslintrc Add synchronous version of the API, with tests and documentation. 2015-03-20 00:09:55 -07:00
.gitignore Create scaffolding for markdownlint package. 2015-02-22 21:30:09 -08:00
.travis.yml Add .travis.yml for build status via Travis CI and code coverage via Coveralls. 2015-03-17 22:51:59 -07:00
LICENSE Create scaffolding for markdownlint package. 2015-02-22 21:30:09 -08:00
package.json Update to version 0.0.3. 2015-03-20 00:29:36 -07:00
README.md Add MD038, MD039 with tests. 2015-04-15 18:24:42 -07:00

markdownlint

A Node.js style checker and lint tool for Markdown files.

npm version GitHub tag Build status Coverage License

Install

npm install markdownlint --save-dev

Overview

The Markdown markup language is designed to be easy to read, write, and understand. It succeeds - and its flexibility is both a benefit and a drawback. Many styles are possible, so formatting can be inconsistent. Some constructs don't work well in all parsers and should be avoided.

markdownlint is a static analysis tool for Node.js and io.js with a library of rules to enforce standards and consistency for Markdown files. It was inspired by - and heavily influenced by - Mark Harrison's markdownlint for Ruby. The rules, rule documentation, and test cases come directly from that project.

If you need a Ruby implementation or a CLI, please consider the mdl gem.

Rules

  • MD001 - Header levels should only increment by one level at a time
  • MD002 - First header should be a h1 header
  • MD003 - Header style
  • MD004 - Unordered list style
  • MD005 - Inconsistent indentation for list items at the same level
  • MD006 - Consider starting bulleted lists at the beginning of the line
  • MD007 - Unordered list indentation
  • MD009 - Trailing spaces
  • MD010 - Hard tabs
  • MD011 - Reversed link syntax
  • MD012 - Multiple consecutive blank lines
  • MD013 - Line length
  • MD014 - Dollar signs used before commands without showing output
  • MD018 - No space after hash on atx style header
  • MD019 - Multiple spaces after hash on atx style header
  • MD020 - No space inside hashes on closed atx style header
  • MD021 - Multiple spaces inside hashes on closed atx style header
  • MD022 - Headers should be surrounded by blank lines
  • MD023 - Headers must start at the beginning of the line
  • MD024 - Multiple headers with the same content
  • MD025 - Multiple top level headers in the same document
  • MD026 - Trailing punctuation in header
  • MD027 - Multiple spaces after blockquote symbol
  • MD028 - Blank line inside blockquote
  • MD029 - Ordered list item prefix
  • MD030 - Spaces after list markers
  • MD031 - Fenced code blocks should be surrounded by blank lines
  • MD032 - Lists should be surrounded by blank lines
  • MD033 - Inline HTML
  • MD034 - Bare URL used
  • MD035 - Horizontal rule style
  • MD036 - Emphasis used instead of a header
  • MD037 - Spaces inside emphasis markers
  • MD038 - Spaces inside code span elements
  • MD039 - Spaces inside link text

See Rules.md for more details.

Tags

  • atx - MD018, MD019
  • atx_closed - MD020, MD021
  • blank_lines - MD012, MD022, MD031, MD032
  • blockquote - MD027, MD028
  • bullet - MD004, MD005, MD006, MD007, MD032
  • code - MD014, MD031, MD038
  • emphasis - MD036, MD037
  • hard_tab - MD010
  • headers - MD001, MD002, MD003, MD018, MD019, MD020, MD021, MD022, MD023, MD024, MD025, MD026, MD036
  • hr - MD035
  • html - MD033
  • indentation - MD005, MD006, MD007, MD027
  • line_length - MD013
  • links - MD011, MD034, MD039
  • ol - MD029, MD030, MD032
  • spaces - MD018, MD019, MD020, MD021, MD023
  • ul - MD004, MD005, MD006, MD007, MD030, MD032
  • url - MD034
  • whitespace - MD009, MD010, MD012, MD027, MD028, MD030, MD037, MD038, MD039

API

Standard asynchronous interface:

/**
 * Lint specified Markdown files according to configurable rules.
 *
 * @param {Object} options Configuration options.
 * @param {Function} callback Callback (err, result) function.
 * @returns {void}
 */
function markdownlint(options, callback) { ... }

Synchronous interface (for build scripts, etc.):

/**
 * Lint specified Markdown files according to configurable rules.
 *
 * @param {Object} options Configuration options.
 * @returns {Object} Result object.
 */
function markdownlint.sync(options) { ... }

options

Type: Object

Configures the function.

options.files

Type: Array of String

List of files to lint.

Each array element should be a single file (via relative or absolute path); globbing is the caller's responsibility.

Example: [ "one.md", "dir/two.md" ]

options.config

Type: Object mapping String to Boolean | Object

Configures the rules to use.

Object keys are rule names and values are the rule's configuration. The value false disables a rule, true enables its default configuration, and passing an object customizes its settings. Setting the special default rule to true or false includes/excludes all rules by default. Enabling or disabling a tag name (ex: whitespace) affects all rules having that tag.

The default rule is applied first, then keys are processed in order from top to bottom with later values overriding earlier ones.

Example:

{
  "default": true,
  "MD003": { "style": "atx_closed" },
  "MD007": { "indent": 4 },
  "MD009": false,
  "whitespace": false
}

Sets of rules (known as a "style") can be stored separately and loaded as JSON.

Example:

var options = {
  "files": [ "..." ],
  "config": require("style/relaxed.json")
};

See the style directory for more samples.

callback

Type: Function taking (Error, Object)

Standard completion callback.

result

Type: Object

Call result.toString() for convenience or see below for an example of the structure of the result object.

Usage

Invoke markdownlint and use the result object's toString method:

var markdownlint = require("markdownlint");

var options = {
  "files": [ "good.md", "bad.md" ]
};

markdownlint(options, function callback(err, result) {
  if (!err) {
    console.log(result.toString());
  }
});

Or invoke markdownlint.sync for a synchronous call:

var result = markdownlint.sync(options);
console.log(result.toString());

Output of both calls:

bad.md: 3: MD010 Hard tabs
bad.md: 1: MD018 No space after hash on atx style header
bad.md: 3: MD018 No space after hash on atx style header

To examine the result object directly:

markdownlint(options, function callback(err, result) {
  if (!err) {
    console.dir(result, { "colors": true });
  }
});

Output:

{
  "good.md": {},
  "bad.md": {
    "MD010": [ 3 ],
    "MD018": [ 1, 3 ]
  }
}

Integration with the gulp build system is straightforward:

var gulp = require("gulp");
var through2 = require("through2");
var markdownlint = require("markdownlint");

gulp.task("markdownlint", function task() {
  return gulp.src("*.md", { "read": false })
    .pipe(through2.obj(function obj(file, enc, next) {
      markdownlint(
        { "files": [ file.relative ] },
        function callback(err, result) {
          var resultString = (result || "").toString();
          if (resultString) {
            console.log(resultString);
          }
          next(err, file);
        });
    }));
});

Output:

[00:00:00] Starting 'markdownlint'...
bad.md: 3: MD010 Hard tabs
bad.md: 1: MD018 No space after hash on atx style header
bad.md: 3: MD018 No space after hash on atx style header
[00:00:00] Finished 'markdownlint' after 10 ms

Integration with the Grunt build system is similar:

var markdownlint = require("markdownlint");

module.exports = function wrapper(grunt) {
  grunt.initConfig({
    "markdownlint": {
      "example": {
        "src": [ "*.md" ]
      }
    }
  });

  grunt.registerMultiTask("markdownlint", function task() {
    var done = this.async();
    markdownlint(
      { "files": this.filesSrc },
      function callback(err, result) {
        var resultString = err || ((result || "").toString());
        if (resultString) {
          grunt.fail.warn("\n" + resultString + "\n");
        }
        done(!err || !resultString);
      });
  });
};

Output:

Running "markdownlint:example" (markdownlint) task
Warning:
bad.md: 3: MD010 Hard tabs
bad.md: 1: MD018 No space after hash on atx style header
bad.md: 3: MD018 No space after hash on atx style header
 Use --force to continue.

Release History

  • 0.0.1 - Initial release.
  • 0.0.2 - Improve documentation, tests, and code.
  • 0.0.3 - Add synchronous API, improve documentation and code.