Add MD034 with tests, improve validation of README and Rules.

This commit is contained in:
David Anson 2015-04-14 00:01:57 -07:00
parent 495fbac6fd
commit 0e24df7cf7
7 changed files with 104 additions and 34 deletions

View file

@ -64,6 +64,7 @@ cases come directly from that project.
* **MD031** - Fenced code blocks should be surrounded by blank lines * **MD031** - Fenced code blocks should be surrounded by blank lines
* **MD032** - Lists should be surrounded by blank lines * **MD032** - Lists should be surrounded by blank lines
* **MD033** - Inline HTML * **MD033** - Inline HTML
* **MD034** - Bare URL used
See [Rules.md](doc/Rules.md) for more details. See [Rules.md](doc/Rules.md) for more details.
@ -78,12 +79,14 @@ See [Rules.md](doc/Rules.md) for more details.
* **hard_tab** - MD010 * **hard_tab** - MD010
* **headers** - MD001, MD002, MD003, MD018, MD019, MD020, MD021, MD022, MD023, * **headers** - MD001, MD002, MD003, MD018, MD019, MD020, MD021, MD022, MD023,
MD024, MD025, MD026 MD024, MD025, MD026
* **html** - MD033
* **indentation** - MD005, MD006, MD007, MD027 * **indentation** - MD005, MD006, MD007, MD027
* **line_length** - MD013 * **line_length** - MD013
* **links** - MD011 * **links** - MD011, MD034
* **ol** - MD029, MD030, MD032 * **ol** - MD029, MD030, MD032
* **spaces** - MD018, MD019, MD020, MD021, MD023 * **spaces** - MD018, MD019, MD020, MD021, MD023
* **ul** - MD004, MD005, MD006, MD007, MD030, MD032 * **ul** - MD004, MD005, MD006, MD007, MD030, MD032
* **url** - MD034
* **whitespace** - MD009, MD010, MD012, MD027, MD028, MD030 * **whitespace** - MD009, MD010, MD012, MD027, MD028, MD030
## API ## API

View file

@ -698,3 +698,25 @@ To fix this, use 'pure' markdown instead of including raw HTML:
Rationale: Raw HTML is allowed in markdown, but this rule is included for Rationale: Raw HTML is allowed in markdown, but this rule is included for
those who want their documents to only include "pure" markdown, or for those those who want their documents to only include "pure" markdown, or for those
who are rendering markdown documents in something other than HTML. who are rendering markdown documents in something other than HTML.
## MD034 - Bare URL used
Tags: links, url
This rule is triggered whenever a URL is given that isn't surrounded by angle
brackets:
For more information, see http://www.example.com/.
To fix this, add angle brackets around the URL:
For more information, see <http://www.example.com/>.
Rationale: Without angle brackets, the URL isn't converted into a link in many
markdown parsers.
Note: if you do want a bare URL without it being converted into a link,
enclose it in a code block, otherwise in some markdown parsers it _will_ be
converted:
`http://www.example.com`

View file

@ -619,5 +619,32 @@ module.exports = [
errors.push(token.lineNumber); errors.push(token.lineNumber);
}); });
} }
},
{
"name": "MD034",
"desc": "Bare URL used",
"tags": [ "links", "url" ],
"func": function MD034(params, errors) {
filterTokens(params.tokens, "inline")
.forEach(function forToken(token) {
var lineNumber = token.lineNumber;
var inLink = false;
token.children.forEach(function forChild(child) {
if (child.type === "link_open") {
inLink = true;
} else if (child.type === "link_close") {
inLink = false;
} else if ((child.type === "text") &&
!inLink &&
/https?:\/\//.test(child.content)) {
errors.push(lineNumber);
} else if ((child.type === "softbreak") ||
(child.type === "hardbreak")) {
lineNumber++;
}
});
});
}
} }
]; ];

View file

@ -6,5 +6,6 @@
"line_length": false, "line_length": false,
"MD006": false, "MD006": false,
"MD007": false, "MD007": false,
"MD033": false "MD033": false,
"MD034": false
} }

9
test/links.md Normal file
View file

@ -0,0 +1,9 @@
# Link test
For more information, please see the
following page: http://www.example.com/ {MD034}
which will tell you all you want to know.
http://www.google.com/ {MD034}
This link should be fine: <http://www.google.com/>

View file

@ -498,7 +498,15 @@ module.exports.badFileSync = function badFileSync(test) {
}; };
module.exports.readme = function readme(test) { module.exports.readme = function readme(test) {
test.expect(144); test.expect(80);
var tagToRules = {};
rules.forEach(function forRule(rule) {
rule.tags.forEach(function forTag(tag) {
var tagRules = tagToRules[tag] || [];
tagRules.push(rule.name);
tagToRules[tag] = tagRules;
});
});
fs.readFile("README.md", shared.utf8Encoding, fs.readFile("README.md", shared.utf8Encoding,
function readFile(err, contents) { function readFile(err, contents) {
test.ifError(err); test.ifError(err);
@ -507,8 +515,6 @@ module.exports.readme = function readme(test) {
var inRules = false; var inRules = false;
var seenTags = false; var seenTags = false;
var inTags = false; var inTags = false;
var docTags = [];
var usedTags = [];
md.parse(contents, {}).forEach(function forToken(token) { md.parse(contents, {}).forEach(function forToken(token) {
if (token.type === "bullet_list_open") { if (token.type === "bullet_list_open") {
if (!seenRules) { if (!seenRules) {
@ -524,38 +530,32 @@ module.exports.readme = function readme(test) {
} else if (token.type === "inline") { } else if (token.type === "inline") {
if (inRules) { if (inRules) {
var rule = rulesLeft.shift(); var rule = rulesLeft.shift();
var expected = "**" + rule.name + "** - " + rule.desc; test.ok(rule,
test.equal(token.content, expected, "Rule mismatch."); "Missing rule implementation for " + token.content + ".");
if (rule) {
var expected = "**" + rule.name + "** - " + rule.desc;
test.equal(token.content, expected, "Rule mismatch.");
}
} else if (inTags) { } else if (inTags) {
var parts = token.content.replace(/\*\*/g, "").split(/ - |, |,\n/); var parts = token.content.replace(/\*\*/g, "").split(/ - |, |,\n/);
var tag = parts.shift(); var tag = parts.shift();
docTags.push(tag); test.deepEqual(parts, tagToRules[tag] || [],
parts.forEach(function forPart(part) { "Rule mismatch for tag " + tag + ".");
var found = rules.some(function forRule(r) { delete tagToRules[tag];
if (r.name === part) {
test.ok(r.tags.indexOf(tag) !== -1, "Missing tag.");
r.tags.forEach(function forTag(t) {
if (usedTags.indexOf(t) === -1) {
usedTags.push(t);
}
});
return true;
}
return false;
});
test.ok(found, "Unknown rule." + part);
});
} }
} }
}); });
test.ok(!rulesLeft.length, "Missing rule."); var ruleLeft = rulesLeft.shift();
test.deepEqual(docTags, usedTags.sort(), "Tag mismatch."); test.ok(!ruleLeft,
"Missing rule documentation for " + (ruleLeft || {}).name + ".");
var tagLeft = Object.keys(tagToRules).shift();
test.ok(!tagLeft, "Undocumented tag " + tagLeft + ".");
test.done(); test.done();
}); });
}; };
module.exports.doc = function doc(test) { module.exports.doc = function doc(test) {
test.expect(90); test.expect(123);
fs.readFile("doc/Rules.md", shared.utf8Encoding, fs.readFile("doc/Rules.md", shared.utf8Encoding,
function readFile(err, contents) { function readFile(err, contents) {
test.ifError(err); test.ifError(err);
@ -569,19 +569,27 @@ module.exports.doc = function doc(test) {
inHeading = false; inHeading = false;
} else if (token.type === "inline") { } else if (token.type === "inline") {
if (inHeading) { if (inHeading) {
test.ok(!rule, "Missing tags."); test.ok(!rule,
"Missing tags for rule " + (rule || {}).name + ".");
rule = rulesLeft.shift(); rule = rulesLeft.shift();
var expected = rule.name + " - " + rule.desc; test.ok(rule,
test.equal(token.content, expected, "Rule mismatch."); "Missing rule implementation for " + token.content + ".");
} else if (/^Tags: /.test(token.content)) { if (rule) {
var expected = rule.name + " - " + rule.desc;
test.equal(token.content, expected, "Rule mismatch.");
}
} else if (/^Tags: /.test(token.content) && rule) {
var tags = token.content.split(/, |: | /).slice(1); var tags = token.content.split(/, |: | /).slice(1);
test.deepEqual(tags, rule.tags, "Tag mismatch."); test.deepEqual(tags, rule.tags,
"Tag mismatch for rule " + rule.name + ".");
rule = null; rule = null;
} }
} }
}); });
test.ok(!rulesLeft.length, "Missing rule."); var ruleLeft = rulesLeft.shift();
test.ok(!rule, "Missing tags."); test.ok(!ruleLeft,
"Missing rule documentation for " + (ruleLeft || {}).name + ".");
test.ok(!rule, "Missing tags for rule " + (rule || {}).name + ".");
test.done(); test.done();
}); });
}; };

View file

@ -1,4 +1,4 @@
Go to (this website)[http://www.example.com] {MD011} Go to (this website)[http://www.example.com] {MD011} {MD034}
However, this shouldn't trigger inside code blocks: However, this shouldn't trigger inside code blocks: