Add passing tests, refactor to introduce forEachLine.

This commit is contained in:
David Anson 2015-03-09 00:31:07 -07:00
parent 9bedd25234
commit b21548a992
10 changed files with 72 additions and 38 deletions

View file

@ -35,13 +35,23 @@ function filterTokens(tokens, tokenA, tokenB) {
});
}
function padAndTrim(lines) {
return [].concat(
"",
lines.map(function mapLine(line) {
return line.trim();
}),
"");
function forEachLine(params, callback) {
var codeBlocks = [];
filterTokens(params.tokens, "code_block")
.forEach(function forToken(token) {
for (var i = token.lines[0]; i < token.lines[1]; i++) {
codeBlocks.push(i);
}
});
var inFence = false;
params.lines.forEach(function forLine(line, lineIndex) {
var onFence = /^(```|~~~)/.test(line);
if (onFence) {
inFence = !inFence;
}
var codeBlock = (codeBlocks.indexOf(lineIndex) !== -1);
callback(line, lineIndex, inFence || codeBlock, onFence);
});
}
module.exports = [
@ -215,18 +225,10 @@ module.exports = [
"name": "MD012",
"desc": "Multiple consecutive blank lines",
"func": function MD012(params, errors) {
var exclusions = [];
filterTokens(params.tokens, "code_block", "fence")
.forEach(function forToken(token) {
for (var i = token.lines[0]; i < token.lines[1]; i++) {
exclusions.push(i);
}
});
var prevLine = "-";
params.lines.forEach(function forLine(line, lineIndex) {
forEachLine(params, function forLine(line, lineIndex, inCode) {
line = line.trim();
if (!line.length && !prevLine.length &&
(exclusions.indexOf(lineIndex) === -1)) {
if (!inCode && !line.length && !prevLine.length) {
errors.push(lineIndex + 1);
}
prevLine = line;
@ -271,8 +273,8 @@ module.exports = [
"name": "MD018",
"desc": "No space after hash on atx style header",
"func": function MD018(params, errors) {
params.lines.forEach(function forLine(line, lineIndex) {
if (/^#+[^#\s]/.test(line) && !/#$/.test(line)) {
forEachLine(params, function forLine(line, lineIndex, inCode) {
if (!inCode && /^#+[^#\s]/.test(line) && !/#$/.test(line)) {
errors.push(lineIndex + 1);
}
});
@ -297,8 +299,8 @@ module.exports = [
"name": "MD020",
"desc": "No space inside hashes on closed atx style header",
"func": function MD020(params, errors) {
params.lines.forEach(function forLine(line, lineIndex) {
if (/^#+[^#]*[^\\]#+$/.test(line) &&
forEachLine(params, function forLine(line, lineIndex, inCode) {
if (!inCode && /^#+[^#]*[^\\]#+$/.test(line) &&
(/^#+[^#\s]/.test(line) || /[^#\s]#+$/.test(line))) {
errors.push(lineIndex + 1);
}
@ -401,15 +403,13 @@ module.exports = [
"func": function MD031(params, errors) {
// Some parsers have trouble detecting fenced code blocks without
// surrounding whitespace, so examine the lines directly.
var lines = padAndTrim(params.lines);
var inCode = false;
lines.forEach(function forLine(line, lineNumber) {
if (/^(```|~~~)/.test(line)) {
inCode = !inCode;
if ((inCode && lines[lineNumber - 1].length) ||
(!inCode && lines[lineNumber + 1].length)) {
errors.push(lineNumber);
}
forEachLine(params, function forLine(line, lineIndex, inCode, onFence) {
if (onFence &&
((inCode && (lineIndex - 1 >= 0) &&
params.lines[lineIndex - 1].length) ||
(!inCode && (lineIndex + 1 < params.lines.length) &&
params.lines[lineIndex + 1].length))) {
errors.push(lineIndex + 1);
}
});
}
@ -422,10 +422,9 @@ module.exports = [
// Some parsers have trouble detecting lists without surrounding
// whitespace, so examine the lines directly.
var inList = false;
var inCode = false;
var prevLine = "";
params.lines.forEach(function forLine(line, lineIndex) {
if (!inCode) {
forEachLine(params, function forLine(line, lineIndex, inCode, onFence) {
if (!inCode || onFence) {
var listMarker = /^([\*\+\-]|(\d+\.))\s/.test(line.trim());
if (listMarker && !inList && !/^($|\s)/.test(prevLine)) {
errors.push(lineIndex + 1);
@ -434,10 +433,7 @@ module.exports = [
}
inList = listMarker;
}
if (/^(```|~~~)/.test(line.trim())) {
inCode = !inCode;
inList = false;
}
inList = inList && !onFence;
prevLine = line;
});
}