mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-09-21 21:30:47 +02:00
Add passing tests, refactor to introduce forEachLine.
This commit is contained in:
parent
9bedd25234
commit
b21548a992
10 changed files with 72 additions and 38 deletions
|
@ -127,7 +127,7 @@
|
|||
"max-depth": [2, 4],
|
||||
"max-len": [2, 80, 2],
|
||||
"max-nested-callbacks": [2, 2],
|
||||
"max-params": [2, 3],
|
||||
"max-params": [2, 4],
|
||||
"max-statements": [0, 10],
|
||||
"new-cap": 2,
|
||||
"new-parens": 2,
|
||||
|
|
70
lib/rules.js
70
lib/rules.js
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
|
3
test/consistent_bullet_styles_asterisk.md
Normal file
3
test/consistent_bullet_styles_asterisk.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
* Item
|
||||
* Item
|
||||
* Item
|
3
test/consistent_bullet_styles_dash.md
Normal file
3
test/consistent_bullet_styles_dash.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
- Item
|
||||
- Item
|
||||
- Item
|
3
test/consistent_bullet_styles_plus.md
Normal file
3
test/consistent_bullet_styles_plus.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
+ Item
|
||||
+ Item
|
||||
+ Item
|
0
test/empty_doc.md
Normal file
0
test/empty_doc.md
Normal file
21
test/fenced_code_blocks.md
Normal file
21
test/fenced_code_blocks.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
This is a GFM-style fenced code block:
|
||||
|
||||
``` bash
|
||||
#!/bin/bash
|
||||
|
||||
# Print something to stdout:
|
||||
echo "Hello"
|
||||
echo "World"
|
||||
```
|
||||
|
||||
This is a kramdown-style fenced code block:
|
||||
|
||||
~~~ bash
|
||||
#!/bin/bash
|
||||
|
||||
# Print something to stdout:
|
||||
echo "Hello"
|
||||
echo "World"
|
||||
~~~
|
||||
|
||||
None of the above should trigger any heading related rules.
|
1
test/first_header_good_atx.md
Normal file
1
test/first_header_good_atx.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Header
|
2
test/first_header_good_setext.md
Normal file
2
test/first_header_good_setext.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
Header
|
||||
======
|
5
test/header_mutliple_h1_no_toplevel.md
Normal file
5
test/header_mutliple_h1_no_toplevel.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
Some introductory text
|
||||
|
||||
# Heading 1
|
||||
|
||||
# Heading 2
|
Loading…
Add table
Add a link
Reference in a new issue