From 9bedd252344becfc83c86b2cdcf2f4b45d8e573c Mon Sep 17 00:00:00 2001 From: David Anson Date: Sun, 8 Mar 2015 23:08:43 -0700 Subject: [PATCH] Add MD022 with tests, create shared module. --- lib/markdownlint.js | 3 +- lib/rules.js | 40 +++++++++++++++++++++++- lib/shared.js | 3 ++ test/headers_good.md | 5 +++ test/headers_surrounding_space_atx.md | 9 ++++++ test/headers_surrounding_space_setext.md | 15 +++++++++ test/markdownlint-test.js | 3 +- 7 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 lib/shared.js create mode 100644 test/headers_good.md create mode 100644 test/headers_surrounding_space_atx.md create mode 100644 test/headers_surrounding_space_setext.md diff --git a/lib/markdownlint.js b/lib/markdownlint.js index 03568418..9c643c7c 100644 --- a/lib/markdownlint.js +++ b/lib/markdownlint.js @@ -3,6 +3,7 @@ var fs = require("fs"); var md = require("markdown-it")(); var rules = require("./rules"); +var shared = require("./shared"); function numberComparison(a, b) { return a - b; @@ -18,7 +19,7 @@ function lintFile(file, config, callback) { callback(err); } else { var tokens = md.parse(contents, {}); - var lines = contents.split(/\r\n|\r|\n/); + var lines = contents.split(shared.newLineRe); tokens.forEach(function forToken(token) { if (token.lines) { token.line = lines[token.lines[0]]; diff --git a/lib/rules.js b/lib/rules.js index 2495df83..3928e86e 100644 --- a/lib/rules.js +++ b/lib/rules.js @@ -1,5 +1,7 @@ "use strict"; +var shared = require("./shared"); + function indentFor(token) { return token.line.length - token.line.trimLeft().length; } @@ -253,7 +255,7 @@ module.exports = [ filterTokens(params.tokens, "code_block", "fence") .forEach(function forToken(token) { if (token.content && token.content - .split(/\r\n|\r|\n/) + .split(shared.newLineRe) .filter(function filterLine(line) { return line; }).every(function forLine(line) { @@ -318,6 +320,42 @@ module.exports = [ } }, + { + "name": "MD022", + "desc": "Headers should be surrounded by blank lines", + "func": function MD022(params, errors) { + var prevHeadingLineNumber = 0; + var prevMaxLineIndex = -1; + var needBlankLine = false; + params.tokens.forEach(function forToken(token) { + if (token.type === "heading_open") { + if ((token.lines[0] - prevMaxLineIndex) === 0) { + errors.push(token.lineNumber); + } + prevHeadingLineNumber = token.lineNumber; + } else if (token.type === "heading_close") { + needBlankLine = true; + } else if (token.type === "inline") { + token.content.split(shared.newLineRe) + .forEach(function forLine(line, offset) { + if (/^(-+|=+)\s*$/.test(line)) { + errors.push(token.lines[0] + offset); + } + }); + } + if (token.lines) { + if (needBlankLine) { + if ((token.lines[0] - prevMaxLineIndex) === 0) { + errors.push(prevHeadingLineNumber); + } + needBlankLine = false; + } + prevMaxLineIndex = Math.max(prevMaxLineIndex, token.lines[1]); + } + }); + } + }, + { "name": "MD028", "desc": "Blank line inside blockquote", diff --git a/lib/shared.js b/lib/shared.js new file mode 100644 index 00000000..28d00977 --- /dev/null +++ b/lib/shared.js @@ -0,0 +1,3 @@ +"use strict"; + +module.exports.newLineRe = /\r\n|\r|\n/; diff --git a/test/headers_good.md b/test/headers_good.md new file mode 100644 index 00000000..f2576043 --- /dev/null +++ b/test/headers_good.md @@ -0,0 +1,5 @@ +# Heading 1 + +## Heading 2 + +## Heading 3 \ No newline at end of file diff --git a/test/headers_surrounding_space_atx.md b/test/headers_surrounding_space_atx.md new file mode 100644 index 00000000..c811b190 --- /dev/null +++ b/test/headers_surrounding_space_atx.md @@ -0,0 +1,9 @@ +# Header 1 + +## Header 2 {MD022} +Some text +## Header 3 {MD022} +Some text +## Header 4 {MD022} + +## Header 5 \ No newline at end of file diff --git a/test/headers_surrounding_space_setext.md b/test/headers_surrounding_space_setext.md new file mode 100644 index 00000000..1a741c40 --- /dev/null +++ b/test/headers_surrounding_space_setext.md @@ -0,0 +1,15 @@ +Header 1 +======== + +Header 2 {MD022} +---------------- +Some text +Header 3 {MD022} +================ +Some text +Header 4 {MD022} +================ +Some text + +Header 5 +-------- \ No newline at end of file diff --git a/test/markdownlint-test.js b/test/markdownlint-test.js index 9bf2ed55..47c27302 100644 --- a/test/markdownlint-test.js +++ b/test/markdownlint-test.js @@ -3,6 +3,7 @@ var fs = require("fs"); var path = require("path"); var markdownlint = require("../lib/markdownlint"); +var shared = require("../lib/shared"); var Q = require("q"); function createTestForFile(file) { @@ -31,7 +32,7 @@ function createTestForFile(file) { var expectedPromise = Q.nfcall(fs.readFile, file, { "encoding": "utf8" }) .then( function fileContents(contents) { - var lines = contents.split(/\r\n|\r|\n/); + var lines = contents.split(shared.newLineRe); var results = {}; lines.forEach(function forLine(line, lineNum) { var regex = /\{(MD\d+)(?::(\d+))?\}/g;