Update MD011/no-reversed-links to ignore content of math blocks and spans (fixes #1864).
Some checks are pending
Checkers / linkcheck (push) Waiting to run
Checkers / spellcheck (push) Waiting to run
CI / build (20, macos-latest) (push) Waiting to run
CI / build (20, ubuntu-latest) (push) Waiting to run
CI / build (20, windows-latest) (push) Waiting to run
CI / build (22, macos-latest) (push) Waiting to run
CI / build (22, ubuntu-latest) (push) Waiting to run
CI / build (22, windows-latest) (push) Waiting to run
CI / build (24, macos-latest) (push) Waiting to run
CI / build (24, ubuntu-latest) (push) Waiting to run
CI / build (24, windows-latest) (push) Waiting to run
CI / pnpm (push) Waiting to run
CodeQL / Analyze (push) Waiting to run
TestRepos / build (latest, ubuntu-latest) (push) Waiting to run
UpdateTestRepos / update (push) Waiting to run

This commit is contained in:
David Anson 2025-11-17 21:32:18 -08:00
parent e88a71e7c8
commit 7668b0a263
5 changed files with 69 additions and 7 deletions

View file

@ -4,6 +4,8 @@ import { addError, hasOverlap } from "../helpers/helpers.cjs";
import { addRangeToSet } from "../helpers/micromark-helpers.cjs";
import { filterByTypesCached } from "./cache.mjs";
/** @typedef {import("micromark-extension-math")} */
const reversedLinkRe = /(^|[^\\])\(([^()]+)\)\[([^\]^][^\]]*)\](?!\()/g;
/** @type {import("markdownlint").Rule} */
@ -13,14 +15,14 @@ export default {
"tags": [ "links" ],
"parser": "micromark",
"function": function MD011(params, onError) {
const codeBlockLineNumbers = new Set();
for (const codeBlock of filterByTypesCached([ "codeFenced", "codeIndented" ])) {
addRangeToSet(codeBlockLineNumbers, codeBlock.startLine, codeBlock.endLine);
const ignoreBlockLineNumbers = new Set();
for (const ignoreBlock of filterByTypesCached([ "codeFenced", "codeIndented", "mathFlow" ])) {
addRangeToSet(ignoreBlockLineNumbers, ignoreBlock.startLine, ignoreBlock.endLine);
}
const codeTexts = filterByTypesCached([ "codeText" ]);
const ignoreTexts = filterByTypesCached([ "codeText", "mathText" ]);
for (const [ lineIndex, line ] of params.lines.entries()) {
const lineNumber = lineIndex + 1;
if (!codeBlockLineNumbers.has(lineNumber)) {
if (!ignoreBlockLineNumbers.has(lineNumber)) {
let match = null;
while ((match = reversedLinkRe.exec(line)) !== null) {
const [ reversedLink, preChar, linkText, linkDestination ] = match;
@ -32,7 +34,7 @@ export default {
const length = match[0].length - preChar.length;
/** @type {import("../helpers/helpers.cjs").FileRange} */
const range = { "startLine": lineNumber, "startColumn": column, "endLine": lineNumber, "endColumn": column + length - 1 };
if (!codeTexts.some((codeText) => hasOverlap(codeText, range))) {
if (!ignoreTexts.some((ignoreText) => hasOverlap(ignoreText, range))) {
addError(
onError,
lineNumber,

View file

@ -1101,7 +1101,7 @@ test("readme", async(t) => {
});
test("validateJsonUsingConfigSchemaStrict", async(t) => {
t.plan(218);
t.plan(219);
// @ts-ignore
const ajv = new Ajv(ajvOptions);
const validateSchemaStrict = ajv.compile(configSchemaStrict);

View file

@ -75717,6 +75717,36 @@ Generated by [AVA](https://avajs.dev).
$$␊
x * y = x * y␊
$$␊
## Content␊
$$␊
Text (reversed)[link] text␊
Text [invalid](#link) text␊
Text [link](not-descriptive-link-text) text␊
Text javascript text␊
$$␊
Text $ (reversed)[link] $ text␊
Text $ [invalid](#link) $ text␊
Text $ [link](not-descriptive-link-text) $ text␊
Text $ javascript $ text␊
<!-- markdownlint-configure-file {␊
"proper-names": {␊
"names": [␊
"JavaScript"␊
]␊
}␊
} -->␊
`,
}

View file

@ -17,3 +17,33 @@ text
$$
x * y = x * y
$$
## Content
$$
Text (reversed)[link] text
Text [invalid](#link) text
Text [link](not-descriptive-link-text) text
Text javascript text
$$
Text $ (reversed)[link] $ text
Text $ [invalid](#link) $ text
Text $ [link](not-descriptive-link-text) $ text
Text $ javascript $ text
<!-- markdownlint-configure-file {
"proper-names": {
"names": [
"JavaScript"
]
}
} -->