mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-12-16 22:10:13 +01:00
Update MD051/link-fragments to identify and fix scenarios where the link fragment has the wrong case (fixes #605).
This commit is contained in:
parent
d352d4ece1
commit
ac8f495ea2
8 changed files with 146 additions and 14 deletions
|
|
@ -1247,7 +1247,7 @@ module.exports.fixableRuleNames = [
|
||||||
"MD011", "MD012", "MD014", "MD018", "MD019", "MD020",
|
"MD011", "MD012", "MD014", "MD018", "MD019", "MD020",
|
||||||
"MD021", "MD022", "MD023", "MD026", "MD027", "MD030",
|
"MD021", "MD022", "MD023", "MD026", "MD027", "MD030",
|
||||||
"MD031", "MD032", "MD034", "MD037", "MD038", "MD039",
|
"MD031", "MD032", "MD034", "MD037", "MD038", "MD039",
|
||||||
"MD044", "MD047", "MD049", "MD050", "MD053"
|
"MD044", "MD047", "MD049", "MD050", "MD051", "MD053"
|
||||||
];
|
];
|
||||||
module.exports.homepage = "https://github.com/DavidAnson/markdownlint";
|
module.exports.homepage = "https://github.com/DavidAnson/markdownlint";
|
||||||
module.exports.version = "0.26.2";
|
module.exports.version = "0.26.2";
|
||||||
|
|
@ -4705,7 +4705,7 @@ module.exports = [
|
||||||
"use strict";
|
"use strict";
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
const { addError, escapeForRegExp, filterTokens, forEachInlineChild, forEachHeading, htmlElementRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
const { addError, addErrorDetailIf, escapeForRegExp, filterTokens, forEachInlineChild, forEachHeading, htmlElementRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
||||||
// Regular expression for identifying HTML anchor names
|
// Regular expression for identifying HTML anchor names
|
||||||
const idRe = /\sid\s*=\s*['"]?([^'"\s>]+)/iu;
|
const idRe = /\sid\s*=\s*['"]?([^'"\s>]+)/iu;
|
||||||
const nameRe = /\sname\s*=\s*['"]?([^'"\s>]+)/iu;
|
const nameRe = /\sname\s*=\s*['"]?([^'"\s>]+)/iu;
|
||||||
|
|
@ -4767,12 +4767,31 @@ module.exports = {
|
||||||
if (id && (id.length > 1) && (id[0] === "#") && !fragments.has(id)) {
|
if (id && (id.length > 1) && (id[0] === "#") && !fragments.has(id)) {
|
||||||
let context = id;
|
let context = id;
|
||||||
let range = null;
|
let range = null;
|
||||||
|
let fixInfo = null;
|
||||||
const match = line.match(new RegExp(`\\[.*?\\]\\(${escapeForRegExp(context)}\\)`));
|
const match = line.match(new RegExp(`\\[.*?\\]\\(${escapeForRegExp(context)}\\)`));
|
||||||
if (match) {
|
if (match) {
|
||||||
context = match[0];
|
[context] = match;
|
||||||
range = [match.index + 1, match[0].length];
|
const index = match.index;
|
||||||
|
const length = context.length;
|
||||||
|
range = [index + 1, length];
|
||||||
|
fixInfo = {
|
||||||
|
"editColumn": index + (length - id.length),
|
||||||
|
"deleteCount": id.length,
|
||||||
|
"insertText": null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const idLower = id.toLowerCase();
|
||||||
|
const mixedCaseKey = [...fragments.keys()]
|
||||||
|
.find((key) => idLower === key.toLowerCase());
|
||||||
|
if (mixedCaseKey) {
|
||||||
|
(fixInfo || {}).insertText = mixedCaseKey;
|
||||||
|
addErrorDetailIf(onError, lineNumber, mixedCaseKey, id, undefined, context, range, fixInfo);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addError(onError, lineNumber, undefined, context,
|
||||||
|
// @ts-ignore
|
||||||
|
range);
|
||||||
}
|
}
|
||||||
addError(onError, lineNumber, undefined, context, range);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2141,6 +2141,8 @@ Tags: `links`
|
||||||
|
|
||||||
Aliases: `link-fragments`
|
Aliases: `link-fragments`
|
||||||
|
|
||||||
|
Fixable: Most violations can be fixed by tooling
|
||||||
|
|
||||||
This rule is triggered when a link fragment does not match any of the fragments
|
This rule is triggered when a link fragment does not match any of the fragments
|
||||||
that are automatically generated for headings in a document:
|
that are automatically generated for headings in a document:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ Tags: `links`
|
||||||
|
|
||||||
Aliases: `link-fragments`
|
Aliases: `link-fragments`
|
||||||
|
|
||||||
|
Fixable: Most violations can be fixed by tooling
|
||||||
|
|
||||||
This rule is triggered when a link fragment does not match any of the fragments
|
This rule is triggered when a link fragment does not match any of the fragments
|
||||||
that are automatically generated for headings in a document:
|
that are automatically generated for headings in a document:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ module.exports.fixableRuleNames = [
|
||||||
"MD011", "MD012", "MD014", "MD018", "MD019", "MD020",
|
"MD011", "MD012", "MD014", "MD018", "MD019", "MD020",
|
||||||
"MD021", "MD022", "MD023", "MD026", "MD027", "MD030",
|
"MD021", "MD022", "MD023", "MD026", "MD027", "MD030",
|
||||||
"MD031", "MD032", "MD034", "MD037", "MD038", "MD039",
|
"MD031", "MD032", "MD034", "MD037", "MD038", "MD039",
|
||||||
"MD044", "MD047", "MD049", "MD050", "MD053"
|
"MD044", "MD047", "MD049", "MD050", "MD051", "MD053"
|
||||||
];
|
];
|
||||||
module.exports.homepage = "https://github.com/DavidAnson/markdownlint";
|
module.exports.homepage = "https://github.com/DavidAnson/markdownlint";
|
||||||
module.exports.version = "0.26.2";
|
module.exports.version = "0.26.2";
|
||||||
|
|
|
||||||
42
lib/md051.js
42
lib/md051.js
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const { addError, escapeForRegExp, filterTokens, forEachInlineChild,
|
const { addError, addErrorDetailIf, escapeForRegExp, filterTokens,
|
||||||
forEachHeading, htmlElementRe } = require("../helpers");
|
forEachInlineChild, forEachHeading, htmlElementRe } = require("../helpers");
|
||||||
|
|
||||||
// Regular expression for identifying HTML anchor names
|
// Regular expression for identifying HTML anchor names
|
||||||
const idRe = /\sid\s*=\s*['"]?([^'"\s>]+)/iu;
|
const idRe = /\sid\s*=\s*['"]?([^'"\s>]+)/iu;
|
||||||
|
|
@ -73,14 +73,46 @@ module.exports = {
|
||||||
if (id && (id.length > 1) && (id[0] === "#") && !fragments.has(id)) {
|
if (id && (id.length > 1) && (id[0] === "#") && !fragments.has(id)) {
|
||||||
let context = id;
|
let context = id;
|
||||||
let range = null;
|
let range = null;
|
||||||
|
let fixInfo = null;
|
||||||
const match = line.match(
|
const match = line.match(
|
||||||
new RegExp(`\\[.*?\\]\\(${escapeForRegExp(context)}\\)`)
|
new RegExp(`\\[.*?\\]\\(${escapeForRegExp(context)}\\)`)
|
||||||
);
|
);
|
||||||
if (match) {
|
if (match) {
|
||||||
context = match[0];
|
[ context ] = match;
|
||||||
range = [ match.index + 1, match[0].length ];
|
const index = match.index;
|
||||||
|
const length = context.length;
|
||||||
|
range = [ index + 1, length ];
|
||||||
|
fixInfo = {
|
||||||
|
"editColumn": index + (length - id.length),
|
||||||
|
"deleteCount": id.length,
|
||||||
|
"insertText": null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const idLower = id.toLowerCase();
|
||||||
|
const mixedCaseKey = [ ...fragments.keys() ]
|
||||||
|
.find((key) => idLower === key.toLowerCase());
|
||||||
|
if (mixedCaseKey) {
|
||||||
|
(fixInfo || {}).insertText = mixedCaseKey;
|
||||||
|
addErrorDetailIf(
|
||||||
|
onError,
|
||||||
|
lineNumber,
|
||||||
|
mixedCaseKey,
|
||||||
|
id,
|
||||||
|
undefined,
|
||||||
|
context,
|
||||||
|
range,
|
||||||
|
fixInfo
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
addError(
|
||||||
|
onError,
|
||||||
|
lineNumber,
|
||||||
|
undefined,
|
||||||
|
context,
|
||||||
|
// @ts-ignore
|
||||||
|
range
|
||||||
|
);
|
||||||
}
|
}
|
||||||
addError(onError, lineNumber, undefined, context, range);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,16 @@ Text
|
||||||
|
|
||||||
[badref]: #missing
|
[badref]: #missing
|
||||||
|
|
||||||
|
## Inconsistent Case Fragments
|
||||||
|
|
||||||
|
[Title](#Valid-Fragments) {MD051}
|
||||||
|
|
||||||
|
[ALL CAPS](#NAMEDLINK) {MD051}
|
||||||
|
|
||||||
|
[MiXeD][mixedref] {MD051}
|
||||||
|
|
||||||
|
[mixedref]: #idLINK
|
||||||
|
|
||||||
<!-- markdownlint-configure-file {
|
<!-- markdownlint-configure-file {
|
||||||
"emphasis-style": false,
|
"emphasis-style": false,
|
||||||
"heading-style": false,
|
"heading-style": false,
|
||||||
|
|
|
||||||
|
|
@ -21814,12 +21814,16 @@ Generated by [AVA](https://avajs.dev).
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
errorContext: '[Invalid](#hrefandid)',
|
errorContext: '[Invalid](#hrefandid)',
|
||||||
errorDetail: null,
|
errorDetail: 'Expected: #HREFandID; Actual: #hrefandid',
|
||||||
errorRange: [
|
errorRange: [
|
||||||
1,
|
1,
|
||||||
21,
|
21,
|
||||||
],
|
],
|
||||||
fixInfo: null,
|
fixInfo: {
|
||||||
|
deleteCount: 10,
|
||||||
|
editColumn: 11,
|
||||||
|
insertText: '#HREFandID',
|
||||||
|
},
|
||||||
lineNumber: 152,
|
lineNumber: 152,
|
||||||
ruleDescription: 'Link fragments should be valid',
|
ruleDescription: 'Link fragments should be valid',
|
||||||
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md051.md',
|
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md051.md',
|
||||||
|
|
@ -21889,6 +21893,59 @@ Generated by [AVA](https://avajs.dev).
|
||||||
'link-fragments',
|
'link-fragments',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
errorContext: '[Title](#Valid-Fragments)',
|
||||||
|
errorDetail: 'Expected: #valid-fragments; Actual: #Valid-Fragments',
|
||||||
|
errorRange: [
|
||||||
|
1,
|
||||||
|
25,
|
||||||
|
],
|
||||||
|
fixInfo: {
|
||||||
|
deleteCount: 16,
|
||||||
|
editColumn: 9,
|
||||||
|
insertText: '#valid-fragments',
|
||||||
|
},
|
||||||
|
lineNumber: 166,
|
||||||
|
ruleDescription: 'Link fragments should be valid',
|
||||||
|
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md051.md',
|
||||||
|
ruleNames: [
|
||||||
|
'MD051',
|
||||||
|
'link-fragments',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errorContext: '[ALL CAPS](#NAMEDLINK)',
|
||||||
|
errorDetail: 'Expected: #namedlink; Actual: #NAMEDLINK',
|
||||||
|
errorRange: [
|
||||||
|
1,
|
||||||
|
22,
|
||||||
|
],
|
||||||
|
fixInfo: {
|
||||||
|
deleteCount: 10,
|
||||||
|
editColumn: 12,
|
||||||
|
insertText: '#namedlink',
|
||||||
|
},
|
||||||
|
lineNumber: 168,
|
||||||
|
ruleDescription: 'Link fragments should be valid',
|
||||||
|
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md051.md',
|
||||||
|
ruleNames: [
|
||||||
|
'MD051',
|
||||||
|
'link-fragments',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errorContext: '#idLINK',
|
||||||
|
errorDetail: 'Expected: #idlink; Actual: #idLINK',
|
||||||
|
errorRange: null,
|
||||||
|
fixInfo: null,
|
||||||
|
lineNumber: 170,
|
||||||
|
ruleDescription: 'Link fragments should be valid',
|
||||||
|
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md051.md',
|
||||||
|
ruleNames: [
|
||||||
|
'MD051',
|
||||||
|
'link-fragments',
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
fixed: `# Valid/Invalid Link Fragments␊
|
fixed: `# Valid/Invalid Link Fragments␊
|
||||||
␊
|
␊
|
||||||
|
|
@ -22041,7 +22098,7 @@ Generated by [AVA](https://avajs.dev).
|
||||||
␊
|
␊
|
||||||
[Invalid](#myname) {MD051}␊
|
[Invalid](#myname) {MD051}␊
|
||||||
␊
|
␊
|
||||||
[Invalid](#hrefandid) {MD051}␊
|
[Invalid](#HREFandID) {MD051}␊
|
||||||
␊
|
␊
|
||||||
[Invalid](#name-for-other-element) {MD051}␊
|
[Invalid](#name-for-other-element) {MD051}␊
|
||||||
␊
|
␊
|
||||||
|
|
@ -22053,6 +22110,16 @@ Generated by [AVA](https://avajs.dev).
|
||||||
␊
|
␊
|
||||||
[badref]: #missing␊
|
[badref]: #missing␊
|
||||||
␊
|
␊
|
||||||
|
## Inconsistent Case Fragments␊
|
||||||
|
␊
|
||||||
|
[Title](#valid-fragments) {MD051}␊
|
||||||
|
␊
|
||||||
|
[ALL CAPS](#namedlink) {MD051}␊
|
||||||
|
␊
|
||||||
|
[MiXeD][mixedref] {MD051}␊
|
||||||
|
␊
|
||||||
|
[mixedref]: #idLINK␊
|
||||||
|
␊
|
||||||
<!-- markdownlint-configure-file {␊
|
<!-- markdownlint-configure-file {␊
|
||||||
"emphasis-style": false,␊
|
"emphasis-style": false,␊
|
||||||
"heading-style": false,␊
|
"heading-style": false,␊
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue