diff --git a/README.md b/README.md index 3a257530..e00182a0 100644 --- a/README.md +++ b/README.md @@ -86,11 +86,13 @@ playground for learning and exploring. * **[MD042](doc/Rules.md#md042)** *no-empty-links* - No empty links * **[MD043](doc/Rules.md#md043)** *required-headers* - Required header structure * **[MD044](doc/Rules.md#md044)** *proper-names* - Proper names should have the correct capitalization +* **[MD045](doc/Rules.md#md045)** *no-alt-text* - Images should have alternate text (alt text) See [Rules.md](doc/Rules.md) for more details. ## Tags +* **accessibility** - MD045 * **atx** - MD018, MD019 * **atx_closed** - MD020, MD021 * **blank_lines** - MD012, MD022, MD031, MD032 @@ -103,6 +105,7 @@ See [Rules.md](doc/Rules.md) for more details. MD024, MD025, MD026, MD036, MD041, MD043 * **hr** - MD035 * **html** - MD033 +* **images** - MD045 * **indentation** - MD005, MD006, MD007, MD027 * **language** - MD040 * **line_length** - MD013 diff --git a/doc/Rules.md b/doc/Rules.md index b73b66e8..67224365 100644 --- a/doc/Rules.md +++ b/doc/Rules.md @@ -1243,3 +1243,35 @@ the proper capitalization, specify the desired letter case in the `names` array: ] Set the `code_blocks` parameter to `false` to disable this rule for code blocks. + + + +## MD045 - Images should have alternate text (alt text) + +Tags: accessibility, images + +Aliases: no-alt-text + +This rule is triggered when an image is missing alternate text (alt text) information. +Alternate text is important for accessibility, describing the content of an image for +people who may not be able to see it. + +Alternate text is commonly specified inline as: + +```md +![Alternate text](image.jpg) +``` + +Or with reference syntax as: + +```md +![Alternate text][ref] + +... + +[ref]: image.jpg "Optional title" +``` + +Guidance for writing alternate text is available from the [W3C](https://www.w3.org/WAI/alt/), +[Wikipedia](https://en.wikipedia.org/wiki/Alt_attribute), and +[other locations](https://www.phase2technology.com/blog/no-more-excuses-definitive-guide-alt-text-field). diff --git a/lib/rules.js b/lib/rules.js index 613d0800..52ce57ad 100644 --- a/lib/rules.js +++ b/lib/rules.js @@ -1219,5 +1219,19 @@ module.exports = [ } }); } + }, + { + "name": "MD045", + "desc": "Images should have alternate text (alt text)", + "tags": [ "accessibility", "images" ], + "aliases": [ "no-alt-text" ], + "regexp": null, + "func": function MD045(params, errors) { + forEachInlineChild(params, "image", function forToken(token) { + if (token.content === "") { + errors.add(token.lineNumber); + } + }); + } } ]; diff --git a/schema/markdownlint-config-schema.json b/schema/markdownlint-config-schema.json index a4c2a81c..2c01631c 100644 --- a/schema/markdownlint-config-schema.json +++ b/schema/markdownlint-config-schema.json @@ -956,6 +956,16 @@ }, "additionalProperties": false }, + "MD045": { + "description": "MD045/no-alt-text - Images should have alternate text (alt text)", + "type": "boolean", + "default": true + }, + "no-alt-text": { + "description": "MD045/no-alt-text - Images should have alternate text (alt text)", + "type": "boolean", + "default": true + }, "headers": { "description": "headers - MD001, MD002, MD003, MD018, MD019, MD020, MD021, MD022, MD023, MD024, MD025, MD026, MD036, MD041, MD043", "type": "boolean", @@ -1060,6 +1070,16 @@ "description": "spelling - MD044", "type": "boolean", "default": true + }, + "accessibility": { + "description": "accessibility - MD045", + "type": "boolean", + "default": true + }, + "images": { + "description": "images - MD045", + "type": "boolean", + "default": true } }, "additionalProperties": false diff --git a/test/detailed-results-MD041-MD050.md b/test/detailed-results-MD041-MD050.md index a19515d3..31b027b4 100644 --- a/test/detailed-results-MD041-MD050.md +++ b/test/detailed-results-MD041-MD050.md @@ -15,3 +15,5 @@ name wrong twice: MarkDownLint. A [normal](link) and an [empty one]() and a [fragment](#one). + +An image without alternate text ![](image.jpg) diff --git a/test/detailed-results-MD041-MD050.results.json b/test/detailed-results-MD041-MD050.results.json index 2a74d2a9..252138a6 100644 --- a/test/detailed-results-MD041-MD050.results.json +++ b/test/detailed-results-MD041-MD050.results.json @@ -45,7 +45,7 @@ "errorRange": [25, 13] }, { - "lineNumber": 18, + "lineNumber": 20, "ruleName": "MD043", "ruleAlias": "required-headers", "ruleDescription": "Required header structure", @@ -79,5 +79,14 @@ "errorDetail": "Expected: markdownlint; Actual: MarkDownLint", "errorContext": null, "errorRange": [1, 12] + }, + { + "lineNumber": 19, + "ruleName": "MD045", + "ruleAlias": "no-alt-text", + "ruleDescription": "Images should have alternate text (alt text)", + "errorDetail": null, + "errorContext": null, + "errorRange": null } ] \ No newline at end of file diff --git a/test/markdownlint-test.js b/test/markdownlint-test.js index 917c7cb1..26689bc7 100644 --- a/test/markdownlint-test.js +++ b/test/markdownlint-test.js @@ -965,7 +965,7 @@ module.exports.missingStringValue = function missingStringValue(test) { }; module.exports.ruleNamesUpperCase = function ruleNamesUpperCase(test) { - test.expect(40); + test.expect(41); rules.forEach(function forRule(rule) { test.equal(rule.name, rule.name.toUpperCase(), "Rule name not upper-case."); }); @@ -973,7 +973,7 @@ module.exports.ruleNamesUpperCase = function ruleNamesUpperCase(test) { }; module.exports.uniqueAliases = function uniqueAliases(test) { - test.expect(80); + test.expect(82); var tags = []; rules.forEach(function forRule(rule) { Array.prototype.push.apply(tags, rule.tags); @@ -990,7 +990,7 @@ module.exports.uniqueAliases = function uniqueAliases(test) { }; module.exports.readme = function readme(test) { - test.expect(104); + test.expect(108); var tagToRules = {}; rules.forEach(function forRule(rule) { rule.tags.forEach(function forTag(tag) { @@ -1052,7 +1052,7 @@ module.exports.readme = function readme(test) { }; module.exports.doc = function doc(test) { - test.expect(303); + test.expect(310); fs.readFile("doc/Rules.md", shared.utf8Encoding, function readFile(err, contents) { test.ifError(err); diff --git a/test/no-alt-text.md b/test/no-alt-text.md new file mode 100644 index 00000000..768e537c --- /dev/null +++ b/test/no-alt-text.md @@ -0,0 +1,26 @@ +# Images with and without alternate text + +![Alternate text](image.jpg) + +![](image.jpg) {MD045} + +![Alternate text](image.jpg "Title") + +![](image.jpg "Title") {MD045} + +Image without alternate text ![](image.jpg) in a sentence. {MD045} + +Reference image with alternate text ![Alternate text][notitle] + +Reference image without alternate text ![][notitle] {MD045} + +Reference image with alternate text and title ![Alternate text][title] + +Reference image without alternate text and title ![][title] {MD045} + +Link to image with alternate text [![Alternate text](image.jpg)](image.jpg) + +Link to image without alternate text [![](image.jpg)](image.jpg) {MD045} + +[notitle]: image.jpg +[title]: image.jpg "Title"