mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2026-02-12 08:34:20 +01:00
Add MD052/reference-links-images and MD053/link-image-reference-definitions for reporting issues with link and image references (fixes #144, fixes #390, fixes #425, fixes #456).
This commit is contained in:
parent
2c947abf7b
commit
c5ca661b96
21 changed files with 1333 additions and 65 deletions
|
|
@ -34,9 +34,18 @@ module.exports.lineMetadata = (value) => {
|
|||
return lineMetadata;
|
||||
};
|
||||
|
||||
let referenceLinkImageData = null;
|
||||
module.exports.referenceLinkImageData = (value) => {
|
||||
if (value) {
|
||||
referenceLinkImageData = value;
|
||||
}
|
||||
return referenceLinkImageData;
|
||||
};
|
||||
|
||||
module.exports.clear = () => {
|
||||
codeBlockAndSpanRanges = null;
|
||||
flattenedLists = null;
|
||||
htmlElementRanges = null;
|
||||
lineMetadata = null;
|
||||
referenceLinkImageData = null;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -499,14 +499,17 @@ function lintContent(
|
|||
frontMatterLines
|
||||
});
|
||||
const lineMetadata = helpers.getLineMetadata(paramsBase);
|
||||
cache.lineMetadata(lineMetadata);
|
||||
cache.codeBlockAndSpanRanges(
|
||||
helpers.codeBlockAndSpanRanges(paramsBase, lineMetadata)
|
||||
);
|
||||
cache.flattenedLists(helpers.flattenLists(paramsBase.tokens));
|
||||
cache.htmlElementRanges(
|
||||
helpers.htmlElementRanges(paramsBase, lineMetadata)
|
||||
);
|
||||
cache.flattenedLists(helpers.flattenLists(paramsBase.tokens));
|
||||
cache.lineMetadata(lineMetadata);
|
||||
cache.referenceLinkImageData(
|
||||
helpers.getReferenceLinkImageData(paramsBase, lineMetadata)
|
||||
);
|
||||
// Function to run for each rule
|
||||
let results = [];
|
||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@
|
|||
"use strict";
|
||||
|
||||
const { addErrorDetailIf, filterTokens, forEachHeading, forEachLine,
|
||||
includesSorted } = require("../helpers");
|
||||
includesSorted, linkReferenceDefinitionRe } = require("../helpers");
|
||||
const { lineMetadata } = require("./cache");
|
||||
|
||||
const longLineRePrefix = "^.{";
|
||||
const longLineRePostfixRelaxed = "}.*\\s.*$";
|
||||
const longLineRePostfixStrict = "}.+$";
|
||||
const labelRe = /^\s*\[.*[^\\]]:/;
|
||||
const linkOrImageOnlyLineRe = /^[es]*(lT?L|I)[ES]*$/;
|
||||
const sternModeRe = /^([#>\s]*\s)?\S*$/;
|
||||
const tokenTypeMap = {
|
||||
|
|
@ -83,7 +82,7 @@ module.exports = {
|
|||
(strict ||
|
||||
(!(stern && sternModeRe.test(line)) &&
|
||||
!includesSorted(linkOnlyLineNumbers, lineNumber) &&
|
||||
!labelRe.test(line))) &&
|
||||
!linkReferenceDefinitionRe.test(line))) &&
|
||||
lengthRe.test(line)) {
|
||||
addErrorDetailIf(
|
||||
onError,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
"use strict";
|
||||
|
||||
const { addErrorDetailIf, bareUrlRe, escapeForRegExp, forEachLine,
|
||||
forEachLink, overlapsAnyRange, linkReferenceRe } = require("../helpers");
|
||||
forEachLink, overlapsAnyRange, linkReferenceDefinitionRe } =
|
||||
require("../helpers");
|
||||
const { codeBlockAndSpanRanges, htmlElementRanges, lineMetadata } =
|
||||
require("./cache");
|
||||
|
||||
|
|
@ -23,7 +24,7 @@ module.exports = {
|
|||
(htmlElements === undefined) ? true : !!htmlElements;
|
||||
const exclusions = [];
|
||||
forEachLine(lineMetadata(), (line, lineIndex) => {
|
||||
if (linkReferenceRe.test(line)) {
|
||||
if (linkReferenceDefinitionRe.test(line)) {
|
||||
exclusions.push([ lineIndex, 0, line.length ]);
|
||||
} else {
|
||||
let match = null;
|
||||
|
|
|
|||
35
lib/md052.js
Normal file
35
lib/md052.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// @ts-check
|
||||
|
||||
"use strict";
|
||||
|
||||
const { addError } = require("../helpers");
|
||||
const { referenceLinkImageData } = require("./cache");
|
||||
|
||||
module.exports = {
|
||||
"names": [ "MD052", "reference-links-images" ],
|
||||
"description":
|
||||
"Reference links and images should use a label that is defined",
|
||||
"tags": [ "images", "links" ],
|
||||
"function": function MD052(params, onError) {
|
||||
const { lines } = params;
|
||||
const { references, definitions } = referenceLinkImageData();
|
||||
// Look for links/images that use an undefined link reference
|
||||
for (const reference of references.entries()) {
|
||||
const [ label, datas ] = reference;
|
||||
if (!definitions.has(label)) {
|
||||
for (const data of datas) {
|
||||
const [ lineIndex, index, length ] = data;
|
||||
// Context will be incomplete if reporting for a multi-line link
|
||||
const context = lines[lineIndex].slice(index, index + length);
|
||||
addError(
|
||||
onError,
|
||||
lineIndex + 1,
|
||||
`Missing link or image reference definition: "${label}"`,
|
||||
context,
|
||||
[ index + 1, context.length ]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
52
lib/md053.js
Normal file
52
lib/md053.js
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// @ts-check
|
||||
|
||||
"use strict";
|
||||
|
||||
const { addError, ellipsify, linkReferenceDefinitionRe } =
|
||||
require("../helpers");
|
||||
const { referenceLinkImageData } = require("./cache");
|
||||
|
||||
module.exports = {
|
||||
"names": [ "MD053", "link-image-reference-definitions" ],
|
||||
"description": "Link and image reference definitions should be needed",
|
||||
"tags": [ "images", "links" ],
|
||||
"function": function MD053(params, onError) {
|
||||
const { lines } = params;
|
||||
const { references, shortcuts, definitions, duplicateDefinitions } =
|
||||
referenceLinkImageData();
|
||||
const singleLineDefinition = (line) => (
|
||||
line.replace(linkReferenceDefinitionRe, "").trim().length > 0
|
||||
);
|
||||
const deleteFixInfo = {
|
||||
"deleteCount": -1
|
||||
};
|
||||
// Look for unused link references (unreferenced by any link/image)
|
||||
for (const definition of definitions.entries()) {
|
||||
const [ label, lineIndex ] = definition;
|
||||
if (!references.has(label) && !shortcuts.has(label)) {
|
||||
const line = lines[lineIndex];
|
||||
addError(
|
||||
onError,
|
||||
lineIndex + 1,
|
||||
`Unused link or image reference definition: "${label}"`,
|
||||
ellipsify(line),
|
||||
[ 1, line.length ],
|
||||
singleLineDefinition(line) ? deleteFixInfo : 0
|
||||
);
|
||||
}
|
||||
}
|
||||
// Look for duplicate link references (defined more than once)
|
||||
for (const duplicateDefinition of duplicateDefinitions) {
|
||||
const [ label, lineIndex ] = duplicateDefinition;
|
||||
const line = lines[lineIndex];
|
||||
addError(
|
||||
onError,
|
||||
lineIndex + 1,
|
||||
`Duplicate link or image reference definition: "${label}"`,
|
||||
ellipsify(line),
|
||||
[ 1, line.length ],
|
||||
singleLineDefinition(line) ? deleteFixInfo : 0
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -50,7 +50,9 @@ const rules = [
|
|||
require("./md047"),
|
||||
require("./md048"),
|
||||
...require("./md049-md050"),
|
||||
require("./md051")
|
||||
require("./md051"),
|
||||
require("./md052"),
|
||||
require("./md053")
|
||||
];
|
||||
rules.forEach((rule) => {
|
||||
const name = rule.names[0].toLowerCase();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue