diff --git a/lib/markdownlint.js b/lib/markdownlint.js index 009accb6..dc327978 100644 --- a/lib/markdownlint.js +++ b/lib/markdownlint.js @@ -1,6 +1,7 @@ "use strict"; var fs = require("fs"); +var md = require("markdown-it")(); var rules = require("./rules"); function numberComparison(a, b) { @@ -16,10 +17,11 @@ function lintFile(file, options, callback) { if (err) { callback(err); } else { - var lines = contents.split(/\r\n|\n/g); + var tokens = md.parse(contents); + var lines = contents.split(/\r\n|\r|\n/g); var result = {}; rules.forEach(function forRule(rule) { - var errors = rule.func(lines); + var errors = rule.func(tokens, lines); if (errors.length) { errors.sort(numberComparison); result[rule.name] = errors.filter(uniqueFilterForSorted); diff --git a/lib/rules.js b/lib/rules.js index 1ad26739..e6a3f455 100644 --- a/lib/rules.js +++ b/lib/rules.js @@ -10,10 +10,26 @@ function padAndTrim(lines) { } module.exports = [ + { + "name": "MD002", + "desc": "First header should be a h1 header", + "func": function MD002(tokens) { + var errors = []; + tokens.every(function forToken(token) { + if ((token.type === "heading_open") && (token.hLevel !== 1)) { + errors.push(token.lines[0] + 1); + return false; + } + return true; + }); + return errors; + } + }, + { "name": "MD031", "desc": "Fenced code blocks should be surrounded by blank lines", - "func": function MD031(lines) { + "func": function MD031(tokens, lines) { // Some parsers have trouble detecting fenced code blocks without // surrounding whitespace, so examine the lines directly. lines = padAndTrim(lines); @@ -35,7 +51,7 @@ module.exports = [ { "name": "MD032", "desc": "Lists should be surrounded by blank lines", - "func": function MD032(lines) { + "func": function MD032(tokens, lines) { // Some parsers have trouble detecting lists without surrounding // whitespace, so examine the lines directly. var errors = []; diff --git a/package.json b/package.json index 2ab3317b..5da366cb 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,9 @@ "test": "nodeunit", "lint": "eslint lib test" }, + "dependencies": { + "markdown-it": "^3.0.7" + }, "devDependencies": { "eslint": "^0.15.0", "nodeunit": "^0.9.0" diff --git a/test/first_header_bad_atx.md b/test/first_header_bad_atx.md new file mode 100644 index 00000000..a8e79371 --- /dev/null +++ b/test/first_header_bad_atx.md @@ -0,0 +1 @@ +## Header {MD002} \ No newline at end of file diff --git a/test/first_header_bad_setext.md b/test/first_header_bad_setext.md new file mode 100644 index 00000000..207501fb --- /dev/null +++ b/test/first_header_bad_setext.md @@ -0,0 +1,2 @@ +Header {MD002} +-------------- \ No newline at end of file diff --git a/test/markdownlint-test.js b/test/markdownlint-test.js index b33a2c53..cdc3ad18 100644 --- a/test/markdownlint-test.js +++ b/test/markdownlint-test.js @@ -12,7 +12,7 @@ function createTestForFile(file) { { "encoding": "utf8" }, function readFileCallback(err, contents) { test.ifError(err); - var lines = contents.split(/\r\n|\n/g); + var lines = contents.split(/\r\n|\r|\n/g); var results = {}; lines.forEach(function forLine(line, lineNum) { var match = line.match(/\{(MD\d+)(?::(\d+))?\}/);