Add rule MD059/descriptive-link-text "Link text should be descriptive" (fixes #681).

This commit is contained in:
Kate Higa 2025-01-06 11:35:17 -05:00 committed by David Anson
parent 4117394250
commit b8374ec5d2
40 changed files with 1159 additions and 234 deletions

View file

@ -1100,6 +1100,28 @@ export interface ConfigurationStrict {
* MD058/blanks-around-tables : Tables should be surrounded by blank lines : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md058.md
*/
"blanks-around-tables"?: boolean;
/**
* MD059/descriptive-link-text : Link text should be descriptive : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md059.md
*/
MD059?:
| boolean
| {
/**
* List of restricted link texts
*/
link_texts?: string[];
};
/**
* MD059/descriptive-link-text : Link text should be descriptive : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md059.md
*/
"descriptive-link-text"?:
| boolean
| {
/**
* List of restricted link texts
*/
link_texts?: string[];
};
/**
* headings : MD001, MD003, MD018, MD019, MD020, MD021, MD022, MD023, MD024, MD025, MD026, MD036, MD041, MD043
*/
@ -1125,7 +1147,7 @@ export interface ConfigurationStrict {
*/
hard_tab?: boolean;
/**
* links : MD011, MD034, MD039, MD042, MD051, MD052, MD053, MD054
* links : MD011, MD034, MD039, MD042, MD051, MD052, MD053, MD054, MD059
*/
links?: boolean;
/**
@ -1185,7 +1207,7 @@ export interface ConfigurationStrict {
*/
spelling?: boolean;
/**
* accessibility : MD045
* accessibility : MD045, MD059
*/
accessibility?: boolean;
/**

60
lib/md059.mjs Normal file
View file

@ -0,0 +1,60 @@
// @ts-check
import { addErrorContext } from "../helpers/helpers.cjs";
import { filterByTypesCached } from "./cache.mjs";
const defaultBannedText = [
"click here",
"here",
"learn more",
"link",
"more",
"read more"
];
/**
* Normalizes a string and removes extra whitespaces and punctuations.
*
* @param {string} text String to transform.
* @returns {string} Normalized string with no punctuations or extra whitespaces.
*/
function normalizeText(text) {
return text
.toLowerCase()
.replace(/\W+/g, " ")
.replace(/\s+/g, " ")
.trim();
}
/** @type {import("markdownlint").Rule} */
export default {
"names": [ "MD059", "descriptive-link-text" ],
"description": "Link text should be descriptive",
"tags": [ "links", "accessibility" ],
"parser": "micromark",
"function": function MD059(params, onError) {
const bannedNames = new Set(params.config.link_texts || defaultBannedText);
const labels = filterByTypesCached([ "label" ])
.filter((label) => label.parent?.type === "link");
for (const label of labels) {
const labelTexts = label.children.filter((child) => child.type === "labelText");
for (const labelText of labelTexts) {
const { text } = label;
if (bannedNames.has(normalizeText(text))) {
const range = labelText.startLine === labelText.endLine ?
[ labelText.startColumn, text.length ] :
undefined;
addErrorContext(
onError,
labelText.startLine,
text,
undefined,
undefined,
range
);
}
}
}
}
};

View file

@ -53,6 +53,7 @@ import md054 from "./md054.mjs";
import md055 from "./md055.mjs";
import md056 from "./md056.mjs";
import md058 from "./md058.mjs";
import md059 from "./md059.mjs";
const rules = [
md001,
@ -108,7 +109,8 @@ const rules = [
md055,
md056,
// md057: See https://github.com/markdownlint/markdownlint
md058
md058,
md059
];
for (const rule of rules) {
const name = rule.names[0].toLowerCase();