mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-09-21 21:30:47 +02:00
Add MD042 no-empty-links "No empty links" (fixes #24).
This commit is contained in:
parent
efe9c9e73c
commit
2612a96ae8
7 changed files with 95 additions and 17 deletions
|
@ -163,7 +163,7 @@
|
|||
"max-len": [2, 80, 4],
|
||||
"max-nested-callbacks": [2, 3],
|
||||
"max-params": [2, 5],
|
||||
"max-statements": [2, 20],
|
||||
"max-statements": [2, 21],
|
||||
"new-cap": 2,
|
||||
"new-parens": 2,
|
||||
"newline-after-var": 0,
|
||||
|
|
|
@ -81,6 +81,7 @@ playground for learning and exploring.
|
|||
* **MD039** *no-space-in-links* - Spaces inside link text
|
||||
* **MD040** *fenced-code-language* - Fenced code blocks should have a language specified
|
||||
* **MD041** *first-line-h1* - First line in file should be a top level header
|
||||
* **MD042** *no-empty-links* - No empty links
|
||||
|
||||
See [Rules.md](doc/Rules.md) for more details.
|
||||
|
||||
|
@ -101,7 +102,7 @@ See [Rules.md](doc/Rules.md) for more details.
|
|||
* **indentation** - MD005, MD006, MD007, MD027
|
||||
* **language** - MD040
|
||||
* **line_length** - MD013
|
||||
* **links** - MD011, MD034, MD039
|
||||
* **links** - MD011, MD034, MD039, MD042
|
||||
* **ol** - MD029, MD030, MD032
|
||||
* **spaces** - MD018, MD019, MD020, MD021, MD023
|
||||
* **ul** - MD004, MD005, MD006, MD007, MD030, MD032
|
||||
|
|
22
doc/Rules.md
22
doc/Rules.md
|
@ -1004,3 +1004,25 @@ To fix this, add a header to the top of your file:
|
|||
|
||||
This is a file with a top level header
|
||||
```
|
||||
|
||||
## MD042 - No empty links
|
||||
|
||||
Tags: links
|
||||
|
||||
Aliases: no-empty-links
|
||||
|
||||
This rule is triggered when an empty link is encountered:
|
||||
|
||||
[an empty link]()
|
||||
|
||||
To fix the violation, provide a destination for the link:
|
||||
|
||||
[a valid link](https://example.com/)
|
||||
|
||||
Empty fragments will trigger this rule:
|
||||
|
||||
[an empty fragment](#)
|
||||
|
||||
But non-empty fragments will not:
|
||||
|
||||
[a valid fragment](#fragment)
|
||||
|
|
16
lib/rules.js
16
lib/rules.js
|
@ -891,5 +891,21 @@ module.exports = [
|
|||
errors.push(1);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "MD042",
|
||||
"desc": "No empty links",
|
||||
"tags": [ "links" ],
|
||||
"aliases": [ "no-empty-links" ],
|
||||
"func": function MD034(params, errors) {
|
||||
forEachInlineChild(params, "link_open", function forToken(token) {
|
||||
token.attrs.forEach(function forAttr(attr) {
|
||||
if (attr[0] === "href" && (!attr[1] || (attr[1] === "#"))) {
|
||||
errors.push(token.lineNumber);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
];
|
||||
|
|
|
@ -73,3 +73,5 @@ Code `with ` space {MD038}
|
|||
```
|
||||
code fence without language {MD040:73}
|
||||
```
|
||||
|
||||
[empty link]() {MD042}
|
||||
|
|
31
test/empty-links.md
Normal file
31
test/empty-links.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Heading
|
||||
|
||||
## Empty links
|
||||
|
||||
[text]() {MD042}
|
||||
|
||||
[text](<>) {MD042}
|
||||
|
||||
[text](#) {MD042}
|
||||
|
||||
[text][frag] {MD042}
|
||||
|
||||
[frag]: #
|
||||
|
||||
## Non-empty links
|
||||
|
||||
[text](link)
|
||||
|
||||
[text](link "title")
|
||||
|
||||
[text](<link>)
|
||||
|
||||
[text](#frag)
|
||||
|
||||
[text][ref]
|
||||
|
||||
[ref]: link
|
||||
|
||||
[text]
|
||||
|
||||
[text]: link
|
|
@ -543,7 +543,8 @@ module.exports.styleAll = function styleAll(test) {
|
|||
"MD038": [ 69 ],
|
||||
"MD039": [ 71 ],
|
||||
"MD040": [ 73 ],
|
||||
"MD041": [ 1 ]
|
||||
"MD041": [ 1 ],
|
||||
"MD042": [ 77 ]
|
||||
}
|
||||
};
|
||||
test.deepEqual(actualResult, expectedResult, "Undetected issues.");
|
||||
|
@ -580,7 +581,8 @@ module.exports.styleRelaxed = function styleRelaxed(test) {
|
|||
"MD031": [ 50 ],
|
||||
"MD032": [ 51 ],
|
||||
"MD035": [ 61 ],
|
||||
"MD036": [ 65 ]
|
||||
"MD036": [ 65 ],
|
||||
"MD042": [ 77 ]
|
||||
}
|
||||
};
|
||||
test.deepEqual(actualResult, expectedResult, "Undetected issues.");
|
||||
|
@ -731,7 +733,7 @@ module.exports.missingStringValue = function missingStringValue(test) {
|
|||
};
|
||||
|
||||
module.exports.ruleNamesUpperCase = function ruleNamesUpperCase(test) {
|
||||
test.expect(37);
|
||||
test.expect(38);
|
||||
rules.forEach(function forRule(rule) {
|
||||
test.equal(rule.name, rule.name.toUpperCase(), "Rule name not upper-case.");
|
||||
});
|
||||
|
@ -739,7 +741,7 @@ module.exports.ruleNamesUpperCase = function ruleNamesUpperCase(test) {
|
|||
};
|
||||
|
||||
module.exports.uniqueAliases = function uniqueAliases(test) {
|
||||
test.expect(74);
|
||||
test.expect(76);
|
||||
var tags = [];
|
||||
rules.forEach(function forRule(rule) {
|
||||
Array.prototype.push.apply(tags, rule.tags);
|
||||
|
@ -756,7 +758,7 @@ module.exports.uniqueAliases = function uniqueAliases(test) {
|
|||
};
|
||||
|
||||
module.exports.readme = function readme(test) {
|
||||
test.expect(97);
|
||||
test.expect(99);
|
||||
var tagToRules = {};
|
||||
rules.forEach(function forRule(rule) {
|
||||
rule.tags.forEach(function forTag(tag) {
|
||||
|
@ -817,7 +819,7 @@ module.exports.readme = function readme(test) {
|
|||
};
|
||||
|
||||
module.exports.doc = function doc(test) {
|
||||
test.expect(274);
|
||||
test.expect(281);
|
||||
fs.readFile("doc/Rules.md", shared.utf8Encoding,
|
||||
function readFile(err, contents) {
|
||||
test.ifError(err);
|
||||
|
@ -848,14 +850,16 @@ module.exports.doc = function doc(test) {
|
|||
ruleHasTags = ruleHasAliases = false;
|
||||
test.ok(rule,
|
||||
"Missing rule implementation for " + token.content + ".");
|
||||
test.equal(token.content, rule.name + " - " + rule.desc,
|
||||
"Rule mismatch.");
|
||||
ruleUsesParams = rule.func.toString()
|
||||
.match(/params\.options\.[_a-z]*/gi);
|
||||
if (ruleUsesParams) {
|
||||
ruleUsesParams = ruleUsesParams.map(function forUse(use) {
|
||||
return use.split(".").pop();
|
||||
});
|
||||
if (rule) {
|
||||
test.equal(token.content, rule.name + " - " + rule.desc,
|
||||
"Rule mismatch.");
|
||||
ruleUsesParams = rule.func.toString()
|
||||
.match(/params\.options\.[_a-z]*/gi);
|
||||
if (ruleUsesParams) {
|
||||
ruleUsesParams = ruleUsesParams.map(function forUse(use) {
|
||||
return use.split(".").pop();
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (/^Tags: /.test(token.content) && rule) {
|
||||
test.deepEqual(token.content.split(tagAliasParameterRe).slice(1),
|
||||
|
@ -882,7 +886,9 @@ module.exports.doc = function doc(test) {
|
|||
var ruleLeft = rulesLeft.shift();
|
||||
test.ok(!ruleLeft,
|
||||
"Missing rule documentation for " + (ruleLeft || {}).name + ".");
|
||||
testTagsAliasesParams();
|
||||
if (rule) {
|
||||
testTagsAliasesParams();
|
||||
}
|
||||
test.done();
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue