markdownlint 0.35.0 → 0.36.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +72 -35
- package/demo/markdownlint-browser.js +1259 -1215
- package/doc/CustomRules.md +55 -249
- package/doc/Rules.md +36 -29
- package/doc/md003.md +2 -2
- package/doc/md004.md +4 -3
- package/doc/md035.md +3 -8
- package/doc/md046.md +2 -2
- package/doc/md048.md +3 -2
- package/doc/md049.md +4 -3
- package/doc/md050.md +4 -4
- package/doc/md051.md +11 -3
- package/doc/md055.md +3 -2
- package/helpers/README.md +2 -19
- package/helpers/helpers.js +87 -347
- package/helpers/micromark-helpers.cjs +296 -0
- package/helpers/micromark-parse.cjs +313 -0
- package/helpers/package.json +5 -2
- package/helpers/shared.js +6 -0
- package/helpers/test.cjs +28 -0
- package/lib/cache.js +3 -3
- package/lib/configuration-strict.d.ts +120 -106
- package/lib/constants.js +1 -1
- package/lib/markdownit.cjs +172 -0
- package/lib/markdownlint.d.ts +41 -3
- package/lib/markdownlint.js +153 -115
- package/lib/md001.js +1 -1
- package/lib/md003.js +1 -1
- package/lib/md004.js +3 -3
- package/lib/md007.js +3 -3
- package/lib/md009.js +1 -1
- package/lib/md010.js +18 -14
- package/lib/md011.js +24 -23
- package/lib/md012.js +1 -1
- package/lib/md013.js +1 -1
- package/lib/md014.js +5 -9
- package/lib/md018.js +1 -1
- package/lib/md019-md021.js +1 -1
- package/lib/md020.js +2 -2
- package/lib/md022.js +9 -15
- package/lib/md024.js +1 -1
- package/lib/md025.js +1 -1
- package/lib/md027.js +2 -2
- package/lib/md029.js +3 -3
- package/lib/md031.js +8 -6
- package/lib/md032.js +27 -15
- package/lib/md033.js +1 -1
- package/lib/md034.js +21 -29
- package/lib/md036.js +18 -24
- package/lib/md037.js +1 -1
- package/lib/md038.js +9 -14
- package/lib/md039.js +13 -15
- package/lib/md040.js +11 -13
- package/lib/md041.js +4 -4
- package/lib/md042.js +2 -6
- package/lib/md043.js +1 -1
- package/lib/md044.js +31 -28
- package/lib/md045.js +2 -2
- package/lib/md048.js +28 -17
- package/lib/md049-md050.js +20 -5
- package/lib/md051.js +16 -18
- package/lib/md053.js +5 -4
- package/lib/md054.js +11 -13
- package/lib/md055.js +39 -46
- package/lib/md056.js +31 -36
- package/lib/md058.js +29 -14
- package/package.json +14 -13
- package/schema/.markdownlint.jsonc +55 -52
- package/schema/.markdownlint.yaml +54 -52
- package/schema/markdownlint-config-schema-strict.json +132 -110
- package/schema/markdownlint-config-schema.json +132 -110
- package/helpers/micromark.cjs +0 -544
package/lib/md038.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
5
|
const { addErrorContext } = require("../helpers");
|
|
6
|
-
const {
|
|
6
|
+
const { getDescendantsByType } = require("../helpers/micromark-helpers.cjs");
|
|
7
7
|
const { filterByTypesCached } = require("./cache");
|
|
8
8
|
|
|
9
9
|
const leftSpaceRe = /^\s(?:[^`]|$)/;
|
|
@@ -29,24 +29,19 @@ module.exports = {
|
|
|
29
29
|
"function": function MD038(params, onError) {
|
|
30
30
|
const codeTexts = filterByTypesCached([ "codeText" ]);
|
|
31
31
|
for (const codeText of codeTexts) {
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
tokenIfType(children[first + 1], "codeTextData") ||
|
|
39
|
-
tokenIfType(children[first + 2], "codeTextData");
|
|
40
|
-
const endData =
|
|
41
|
-
tokenIfType(children[last - 1], "codeTextData") ||
|
|
42
|
-
tokenIfType(children[last - 2], "codeTextData");
|
|
32
|
+
const sequences = getDescendantsByType(codeText, [ "codeTextSequence" ]);
|
|
33
|
+
const startSequence = sequences[0];
|
|
34
|
+
const endSequence = sequences[sequences.length - 1];
|
|
35
|
+
const datas = getDescendantsByType(codeText, [ "codeTextData" ]);
|
|
36
|
+
const startData = datas[0];
|
|
37
|
+
const endData = datas[datas.length - 1];
|
|
43
38
|
if (startSequence && endSequence && startData && endData) {
|
|
44
39
|
const spaceLeft = leftSpaceRe.test(startData.text);
|
|
45
40
|
const spaceRight = rightSpaceRe.test(endData.text);
|
|
46
41
|
if (spaceLeft || spaceRight) {
|
|
47
42
|
let lineNumber = startSequence.startLine;
|
|
48
|
-
let range =
|
|
49
|
-
let fixInfo =
|
|
43
|
+
let range = undefined;
|
|
44
|
+
let fixInfo = undefined;
|
|
50
45
|
if (startSequence.startLine === endSequence.endLine) {
|
|
51
46
|
range = [
|
|
52
47
|
startSequence.startColumn,
|
package/lib/md039.js
CHANGED
|
@@ -3,15 +3,14 @@
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
5
|
const { addErrorContext } = require("../helpers");
|
|
6
|
-
const { filterByTypes } = require("../helpers/micromark.cjs");
|
|
7
6
|
const { getReferenceLinkImageData, filterByTypesCached } = require("./cache");
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* Adds an error for a label space issue.
|
|
11
10
|
*
|
|
12
11
|
* @param {import("./markdownlint").RuleOnError} onError Error-reporting callback.
|
|
13
|
-
* @param {import("../helpers/micromark.cjs").Token} label Label token.
|
|
14
|
-
* @param {import("../helpers/micromark.cjs").Token} labelText LabelText token.
|
|
12
|
+
* @param {import("../helpers/micromark-helpers.cjs").Token} label Label token.
|
|
13
|
+
* @param {import("../helpers/micromark-helpers.cjs").Token} labelText LabelText token.
|
|
15
14
|
* @param {boolean} isStart True iff error is at the start of the link.
|
|
16
15
|
*/
|
|
17
16
|
function addLabelSpaceError(onError, label, labelText, isStart) {
|
|
@@ -29,18 +28,20 @@ function addLabelSpaceError(onError, label, labelText, isStart) {
|
|
|
29
28
|
isStart,
|
|
30
29
|
!isStart,
|
|
31
30
|
range,
|
|
32
|
-
range ?
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
range ?
|
|
32
|
+
{
|
|
33
|
+
"editColumn": range[0],
|
|
34
|
+
"deleteCount": range[1]
|
|
35
|
+
} :
|
|
36
|
+
undefined
|
|
36
37
|
);
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
41
|
* Determines if a link is a valid link (and not a fake shortcut link due to parser tricks).
|
|
41
42
|
*
|
|
42
|
-
* @param {import("../helpers/micromark.cjs").Token} label Label token.
|
|
43
|
-
* @param {import("../helpers/micromark.cjs").Token} labelText LabelText token.
|
|
43
|
+
* @param {import("../helpers/micromark-helpers.cjs").Token} label Label token.
|
|
44
|
+
* @param {import("../helpers/micromark-helpers.cjs").Token} labelText LabelText token.
|
|
44
45
|
* @param {Map<string, any>} definitions Map of link definitions.
|
|
45
46
|
* @returns {boolean} True iff the link is valid.
|
|
46
47
|
*/
|
|
@@ -57,13 +58,10 @@ module.exports = {
|
|
|
57
58
|
"parser": "micromark",
|
|
58
59
|
"function": function MD039(params, onError) {
|
|
59
60
|
const { definitions } = getReferenceLinkImageData();
|
|
60
|
-
const labels = filterByTypesCached([ "label" ])
|
|
61
|
-
filter((label) => label.parent?.type === "link");
|
|
61
|
+
const labels = filterByTypesCached([ "label" ])
|
|
62
|
+
.filter((label) => label.parent?.type === "link");
|
|
62
63
|
for (const label of labels) {
|
|
63
|
-
const labelTexts =
|
|
64
|
-
label.children,
|
|
65
|
-
[ "labelText" ]
|
|
66
|
-
);
|
|
64
|
+
const labelTexts = label.children.filter((child) => child.type === "labelText");
|
|
67
65
|
for (const labelText of labelTexts) {
|
|
68
66
|
if (
|
|
69
67
|
(labelText.text.trimStart().length !== labelText.text.length) &&
|
package/lib/md040.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
5
|
const { addError, addErrorContext } = require("../helpers");
|
|
6
|
-
const {
|
|
6
|
+
const { getDescendantsByType } = require("../helpers/micromark-helpers.cjs");
|
|
7
7
|
const { filterByTypesCached } = require("./cache");
|
|
8
8
|
|
|
9
9
|
// eslint-disable-next-line jsdoc/valid-types
|
|
@@ -19,18 +19,16 @@ module.exports = {
|
|
|
19
19
|
const languageOnly = !!params.config.language_only;
|
|
20
20
|
const fencedCodes = filterByTypesCached([ "codeFenced" ]);
|
|
21
21
|
for (const fencedCode of fencedCodes) {
|
|
22
|
-
const openingFence =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
addError(onError, startLine, `Info string contains more than language: "${text}"`);
|
|
33
|
-
}
|
|
22
|
+
const openingFence = getDescendantsByType(fencedCode, [ "codeFencedFence" ])[0];
|
|
23
|
+
const { startLine, text } = openingFence;
|
|
24
|
+
const info = getDescendantsByType(openingFence, [ "codeFencedFenceInfo" ])[0]?.text;
|
|
25
|
+
if (!info) {
|
|
26
|
+
addErrorContext(onError, startLine, text);
|
|
27
|
+
} else if ((allowed.length > 0) && !allowed.includes(info)) {
|
|
28
|
+
addError(onError, startLine, `"${info}" is not allowed`);
|
|
29
|
+
}
|
|
30
|
+
if (languageOnly && getDescendantsByType(openingFence, [ "codeFencedFenceMeta" ]).length > 0) {
|
|
31
|
+
addError(onError, startLine, `Info string contains more than language: "${text}"`);
|
|
34
32
|
}
|
|
35
33
|
}
|
|
36
34
|
}
|
package/lib/md041.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const { addErrorContext, frontMatterHasTitle } = require("../helpers");
|
|
6
6
|
const { filterByTypes, getHeadingLevel, getHtmlTagInfo, isHtmlFlowComment, nonContentTokens } =
|
|
7
|
-
require("../helpers/micromark.cjs");
|
|
7
|
+
require("../helpers/micromark-helpers.cjs");
|
|
8
8
|
|
|
9
9
|
// eslint-disable-next-line jsdoc/valid-types
|
|
10
10
|
/** @type import("./markdownlint").Rule */
|
|
@@ -16,9 +16,9 @@ module.exports = {
|
|
|
16
16
|
"function": function MD041(params, onError) {
|
|
17
17
|
const level = Number(params.config.level || 1);
|
|
18
18
|
if (!frontMatterHasTitle(params.frontMatterLines, params.config.front_matter_title)) {
|
|
19
|
-
params.parsers.micromark.tokens
|
|
20
|
-
filter((token) => !nonContentTokens.has(token.type) && !isHtmlFlowComment(token))
|
|
21
|
-
every((token) => {
|
|
19
|
+
params.parsers.micromark.tokens
|
|
20
|
+
.filter((token) => !nonContentTokens.has(token.type) && !isHtmlFlowComment(token))
|
|
21
|
+
.every((token) => {
|
|
22
22
|
let isError = true;
|
|
23
23
|
if ((token.type === "atxHeading") || (token.type === "setextHeading")) {
|
|
24
24
|
isError = (getHeadingLevel(token) !== level);
|
package/lib/md042.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
5
|
const { addErrorContext } = require("../helpers");
|
|
6
|
-
const { getDescendantsByType } = require("../helpers/micromark.cjs");
|
|
6
|
+
const { getDescendantsByType } = require("../helpers/micromark-helpers.cjs");
|
|
7
7
|
const { getReferenceLinkImageData, filterByTypesCached } = require("./cache");
|
|
8
8
|
|
|
9
9
|
// eslint-disable-next-line jsdoc/valid-types
|
|
@@ -25,11 +25,7 @@ module.exports = {
|
|
|
25
25
|
const reference = getDescendantsByType(link, [ "reference" ]);
|
|
26
26
|
const resource = getDescendantsByType(link, [ "resource" ]);
|
|
27
27
|
const referenceString = getDescendantsByType(reference, [ "referenceString" ]);
|
|
28
|
-
const
|
|
29
|
-
const resourceDestinationString = [
|
|
30
|
-
...getDescendantsByType(resourceDestination, [ "resourceDestinationRaw", "resourceDestinationString" ]),
|
|
31
|
-
...getDescendantsByType(resourceDestination, [ "resourceDestinationLiteral", "resourceDestinationString" ])
|
|
32
|
-
];
|
|
28
|
+
const resourceDestinationString = getDescendantsByType(resource, [ "resourceDestination", [ "resourceDestinationLiteral", "resourceDestinationRaw" ], "resourceDestinationString" ]);
|
|
33
29
|
const hasLabelText = labelText.length > 0;
|
|
34
30
|
const hasReference = reference.length > 0;
|
|
35
31
|
const hasResource = resource.length > 0;
|
package/lib/md043.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
5
|
const { addErrorContext, addErrorDetailIf } = require("../helpers");
|
|
6
|
-
const { getHeadingLevel, getHeadingText } = require("../helpers/micromark.cjs");
|
|
6
|
+
const { getHeadingLevel, getHeadingText } = require("../helpers/micromark-helpers.cjs");
|
|
7
7
|
const { filterByTypesCached } = require("./cache");
|
|
8
8
|
|
|
9
9
|
// eslint-disable-next-line jsdoc/valid-types
|
package/lib/md044.js
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorDetailIf, escapeForRegExp,
|
|
6
|
-
|
|
7
|
-
const {
|
|
8
|
-
require("../helpers/micromark.cjs");
|
|
5
|
+
const { addErrorDetailIf, escapeForRegExp, hasOverlap } = require("../helpers");
|
|
6
|
+
const { filterByPredicate, filterByTypes } = require("../helpers/micromark-helpers.cjs");
|
|
7
|
+
const { parse } = require("../helpers/micromark-parse.cjs");
|
|
9
8
|
|
|
10
9
|
const ignoredChildTypes = new Set(
|
|
11
10
|
[ "codeFencedFence", "definition", "reference", "resource" ]
|
|
@@ -49,43 +48,47 @@ module.exports = {
|
|
|
49
48
|
token.children.filter((t) => !ignoredChildTypes.has(t.type))
|
|
50
49
|
)
|
|
51
50
|
);
|
|
51
|
+
/** @type {import("../helpers").FileRange[]} */
|
|
52
52
|
const exclusions = [];
|
|
53
|
-
const
|
|
53
|
+
const scannedTokens = new Set();
|
|
54
54
|
for (const name of names) {
|
|
55
55
|
const escapedName = escapeForRegExp(name);
|
|
56
56
|
const startNamePattern = /^\W/.test(name) ? "" : "\\b_*";
|
|
57
57
|
const endNamePattern = /\W$/.test(name) ? "" : "_*\\b";
|
|
58
|
-
const namePattern =
|
|
59
|
-
`(${startNamePattern})(${escapedName})${endNamePattern}`;
|
|
58
|
+
const namePattern = `(${startNamePattern})(${escapedName})${endNamePattern}`;
|
|
60
59
|
const nameRe = new RegExp(namePattern, "gi");
|
|
61
60
|
for (const token of contentTokens) {
|
|
62
61
|
let match = null;
|
|
63
62
|
while ((match = nameRe.exec(token.text)) !== null) {
|
|
64
63
|
const [ , leftMatch, nameMatch ] = match;
|
|
65
|
-
const
|
|
64
|
+
const column = token.startColumn + match.index + leftMatch.length;
|
|
66
65
|
const length = nameMatch.length;
|
|
67
|
-
const
|
|
66
|
+
const lineNumber = token.startLine;
|
|
67
|
+
/** @type {import("../helpers").FileRange} */
|
|
68
|
+
const nameRange = {
|
|
69
|
+
"startLine": lineNumber,
|
|
70
|
+
"startColumn": column,
|
|
71
|
+
"endLine": lineNumber,
|
|
72
|
+
"endColumn": column + length - 1
|
|
73
|
+
};
|
|
68
74
|
if (
|
|
69
|
-
!
|
|
70
|
-
!
|
|
75
|
+
!names.includes(nameMatch) &&
|
|
76
|
+
!exclusions.some((exclusion) => hasOverlap(exclusion, nameRange))
|
|
71
77
|
) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
token.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
);
|
|
84
|
-
exclusions.push(...urlRanges);
|
|
85
|
-
autoLinked.add(token);
|
|
78
|
+
/** @type {import("../helpers").FileRange[]} */
|
|
79
|
+
let autolinkRanges = [];
|
|
80
|
+
if (!scannedTokens.has(token)) {
|
|
81
|
+
autolinkRanges = filterByTypes(parse(token.text), [ "literalAutolink" ])
|
|
82
|
+
.map((tok) => ({
|
|
83
|
+
"startLine": lineNumber,
|
|
84
|
+
"startColumn": token.startColumn + tok.startColumn - 1,
|
|
85
|
+
"endLine": lineNumber,
|
|
86
|
+
"endColumn": token.endColumn + tok.endColumn - 1
|
|
87
|
+
}));
|
|
88
|
+
exclusions.push(...autolinkRanges);
|
|
89
|
+
scannedTokens.add(token);
|
|
86
90
|
}
|
|
87
|
-
if (!
|
|
88
|
-
const column = index + 1;
|
|
91
|
+
if (!autolinkRanges.some((autolinkRange) => hasOverlap(autolinkRange, nameRange))) {
|
|
89
92
|
addErrorDetailIf(
|
|
90
93
|
onError,
|
|
91
94
|
token.startLine,
|
|
@@ -102,7 +105,7 @@ module.exports = {
|
|
|
102
105
|
);
|
|
103
106
|
}
|
|
104
107
|
}
|
|
105
|
-
exclusions.push(
|
|
108
|
+
exclusions.push(nameRange);
|
|
106
109
|
}
|
|
107
110
|
}
|
|
108
111
|
}
|
package/lib/md045.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
5
|
const { addError, getHtmlAttributeRe, nextLinesRe } = require("../helpers");
|
|
6
|
-
const {
|
|
6
|
+
const { getHtmlTagInfo, getDescendantsByType } = require("../helpers/micromark-helpers.cjs");
|
|
7
7
|
const { filterByTypesCached } = require("./cache");
|
|
8
8
|
|
|
9
9
|
const altRe = getHtmlAttributeRe("alt");
|
|
@@ -19,7 +19,7 @@ module.exports = {
|
|
|
19
19
|
// Process Markdown images
|
|
20
20
|
const images = filterByTypesCached([ "image" ]);
|
|
21
21
|
for (const image of images) {
|
|
22
|
-
const labelTexts =
|
|
22
|
+
const labelTexts = getDescendantsByType(image, [ "label", "labelText" ]);
|
|
23
23
|
if (labelTexts.some((labelText) => labelText.text.length === 0)) {
|
|
24
24
|
const range = (image.startLine === image.endLine) ?
|
|
25
25
|
[ image.startColumn, image.endColumn - image.startColumn ] :
|
package/lib/md048.js
CHANGED
|
@@ -2,10 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorDetailIf
|
|
6
|
-
const {
|
|
5
|
+
const { addErrorDetailIf } = require("../helpers");
|
|
6
|
+
const { getDescendantsByType } = require("../helpers/micromark-helpers.cjs");
|
|
7
7
|
const { filterByTypesCached } = require("./cache");
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Return the string representation of a fence markup character.
|
|
11
|
+
*
|
|
12
|
+
* @param {string} markup Fence string.
|
|
13
|
+
* @returns {"tilde" | "backtick"} String representation.
|
|
14
|
+
*/
|
|
15
|
+
function fencedCodeBlockStyleFor(markup) {
|
|
16
|
+
switch (markup[0]) {
|
|
17
|
+
case "~":
|
|
18
|
+
return "tilde";
|
|
19
|
+
default:
|
|
20
|
+
return "backtick";
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
9
24
|
// eslint-disable-next-line jsdoc/valid-types
|
|
10
25
|
/** @type import("./markdownlint").Rule */
|
|
11
26
|
module.exports = {
|
|
@@ -18,22 +33,18 @@ module.exports = {
|
|
|
18
33
|
let expectedStyle = style;
|
|
19
34
|
const codeFenceds = filterByTypesCached([ "codeFenced" ]);
|
|
20
35
|
for (const codeFenced of codeFenceds) {
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (expectedStyle === "consistent") {
|
|
27
|
-
expectedStyle = fencedCodeBlockStyleFor(text);
|
|
28
|
-
}
|
|
29
|
-
addErrorDetailIf(
|
|
30
|
-
onError,
|
|
31
|
-
startLine,
|
|
32
|
-
expectedStyle,
|
|
33
|
-
fencedCodeBlockStyleFor(text)
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
+
const codeFencedFenceSequence =
|
|
37
|
+
getDescendantsByType(codeFenced, [ "codeFencedFence", "codeFencedFenceSequence" ])[0];
|
|
38
|
+
const { startLine, text } = codeFencedFenceSequence;
|
|
39
|
+
if (expectedStyle === "consistent") {
|
|
40
|
+
expectedStyle = fencedCodeBlockStyleFor(text);
|
|
36
41
|
}
|
|
42
|
+
addErrorDetailIf(
|
|
43
|
+
onError,
|
|
44
|
+
startLine,
|
|
45
|
+
expectedStyle,
|
|
46
|
+
fencedCodeBlockStyleFor(text)
|
|
47
|
+
);
|
|
37
48
|
}
|
|
38
49
|
}
|
|
39
50
|
};
|
package/lib/md049-md050.js
CHANGED
|
@@ -2,11 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addError
|
|
6
|
-
const { filterByPredicate,
|
|
5
|
+
const { addError } = require("../helpers");
|
|
6
|
+
const { filterByPredicate, getDescendantsByType } = require("../helpers/micromark-helpers.cjs");
|
|
7
7
|
|
|
8
8
|
const intrawordRe = /^\w$/;
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Return the string representation of a emphasis or strong markup character.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} markup Emphasis or strong string.
|
|
14
|
+
* @returns {"asterisk" | "underscore"} String representation.
|
|
15
|
+
*/
|
|
16
|
+
function emphasisOrStrongStyleFor(markup) {
|
|
17
|
+
switch (markup[0]) {
|
|
18
|
+
case "*":
|
|
19
|
+
return "asterisk";
|
|
20
|
+
default:
|
|
21
|
+
return "underscore";
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
10
25
|
/**
|
|
11
26
|
* @param {import("./markdownlint").RuleParams} params Rule parameters.
|
|
12
27
|
* @param {import("./markdownlint").RuleOnError} onError Error-reporting callback.
|
|
@@ -25,9 +40,9 @@ const impl =
|
|
|
25
40
|
(token) => ((token.type === "htmlFlow") ? [] : token.children)
|
|
26
41
|
);
|
|
27
42
|
for (const token of emphasisTokens) {
|
|
28
|
-
const
|
|
29
|
-
const startSequence =
|
|
30
|
-
const endSequence =
|
|
43
|
+
const sequences = getDescendantsByType(token, [ typeSequence ]);
|
|
44
|
+
const startSequence = sequences[0];
|
|
45
|
+
const endSequence = sequences[sequences.length - 1];
|
|
31
46
|
if (startSequence && endSequence) {
|
|
32
47
|
const markupStyle = emphasisOrStrongStyleFor(startSequence.text);
|
|
33
48
|
if (style === "consistent") {
|
package/lib/md051.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addError,
|
|
6
|
-
const { filterByPredicate, filterByTypes, getHtmlTagInfo } = require("../helpers/micromark.cjs");
|
|
5
|
+
const { addError, getHtmlAttributeRe } = require("../helpers");
|
|
6
|
+
const { filterByPredicate, filterByTypes, getHtmlTagInfo } = require("../helpers/micromark-helpers.cjs");
|
|
7
7
|
const { filterByTypesCached } = require("./cache");
|
|
8
8
|
|
|
9
9
|
// Regular expression for identifying HTML anchor names
|
|
@@ -22,7 +22,7 @@ const tokensInclude = new Set(
|
|
|
22
22
|
* Converts a Markdown heading into an HTML fragment according to the rules
|
|
23
23
|
* used by GitHub.
|
|
24
24
|
*
|
|
25
|
-
* @param {import("../helpers/micromark.cjs").Token} headingText Heading text token.
|
|
25
|
+
* @param {import("../helpers/micromark-helpers.cjs").Token} headingText Heading text token.
|
|
26
26
|
* @returns {string} Fragment string for heading.
|
|
27
27
|
*/
|
|
28
28
|
function convertHeadingToHTMLFragment(headingText) {
|
|
@@ -51,7 +51,7 @@ function convertHeadingToHTMLFragment(headingText) {
|
|
|
51
51
|
/**
|
|
52
52
|
* Unescapes the text of a String-type micromark Token.
|
|
53
53
|
*
|
|
54
|
-
* @param {import("../helpers/micromark.cjs").Token} token String-type micromark Token.
|
|
54
|
+
* @param {import("../helpers/micromark-helpers.cjs").Token} token String-type micromark Token.
|
|
55
55
|
* @returns {string} Unescaped token text.
|
|
56
56
|
*/
|
|
57
57
|
function unescapeStringTokenText(token) {
|
|
@@ -68,6 +68,7 @@ module.exports = {
|
|
|
68
68
|
"tags": [ "links" ],
|
|
69
69
|
"parser": "micromark",
|
|
70
70
|
"function": function MD051(params, onError) {
|
|
71
|
+
const ignoreCase = params.config.ignore_case || false;
|
|
71
72
|
const fragments = new Map();
|
|
72
73
|
|
|
73
74
|
// Process headings
|
|
@@ -104,7 +105,7 @@ module.exports = {
|
|
|
104
105
|
|
|
105
106
|
// Process link and definition fragments
|
|
106
107
|
// eslint-disable-next-line jsdoc/valid-types
|
|
107
|
-
/** @type import("../helpers/micromark.cjs").TokenType[][] */
|
|
108
|
+
/** @type import("../helpers/micromark-helpers.cjs").TokenType[][] */
|
|
108
109
|
const parentChilds = [
|
|
109
110
|
[ "link", "resourceDestinationString" ],
|
|
110
111
|
[ "definition", "definitionDestinationString" ]
|
|
@@ -123,11 +124,8 @@ module.exports = {
|
|
|
123
124
|
!fragments.has(encodedText) &&
|
|
124
125
|
!lineFragmentRe.test(encodedText)
|
|
125
126
|
) {
|
|
126
|
-
// eslint-disable-next-line no-undef-init
|
|
127
127
|
let context = undefined;
|
|
128
|
-
// eslint-disable-next-line no-undef-init
|
|
129
128
|
let range = undefined;
|
|
130
|
-
// eslint-disable-next-line no-undef-init
|
|
131
129
|
let fixInfo = undefined;
|
|
132
130
|
if (link.startLine === link.endLine) {
|
|
133
131
|
context = link.text;
|
|
@@ -143,16 +141,16 @@ module.exports = {
|
|
|
143
141
|
if (mixedCaseKey) {
|
|
144
142
|
// @ts-ignore
|
|
145
143
|
(fixInfo || {}).insertText = mixedCaseKey;
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
144
|
+
if (!ignoreCase && (mixedCaseKey !== text)) {
|
|
145
|
+
addError(
|
|
146
|
+
onError,
|
|
147
|
+
link.startLine,
|
|
148
|
+
`Expected: ${mixedCaseKey}; Actual: ${text}`,
|
|
149
|
+
context,
|
|
150
|
+
range,
|
|
151
|
+
fixInfo
|
|
152
|
+
);
|
|
153
|
+
}
|
|
156
154
|
} else {
|
|
157
155
|
addError(
|
|
158
156
|
onError,
|
package/lib/md053.js
CHANGED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addError, ellipsify
|
|
6
|
-
require("../helpers");
|
|
5
|
+
const { addError, ellipsify } = require("../helpers");
|
|
7
6
|
const { getReferenceLinkImageData } = require("./cache");
|
|
8
7
|
|
|
8
|
+
const linkReferenceDefinitionRe = /^ {0,3}\[([^\]]*[^\\])\]:/;
|
|
9
|
+
|
|
9
10
|
// eslint-disable-next-line jsdoc/valid-types
|
|
10
11
|
/** @type import("./markdownlint").Rule */
|
|
11
12
|
module.exports = {
|
|
@@ -39,7 +40,7 @@ module.exports = {
|
|
|
39
40
|
`Unused link or image reference definition: "${label}"`,
|
|
40
41
|
ellipsify(line),
|
|
41
42
|
[ 1, line.length ],
|
|
42
|
-
singleLineDefinition(line) ? deleteFixInfo :
|
|
43
|
+
singleLineDefinition(line) ? deleteFixInfo : undefined
|
|
43
44
|
);
|
|
44
45
|
}
|
|
45
46
|
}
|
|
@@ -54,7 +55,7 @@ module.exports = {
|
|
|
54
55
|
`Duplicate link or image reference definition: "${label}"`,
|
|
55
56
|
ellipsify(line),
|
|
56
57
|
[ 1, line.length ],
|
|
57
|
-
singleLineDefinition(line) ? deleteFixInfo :
|
|
58
|
+
singleLineDefinition(line) ? deleteFixInfo : undefined
|
|
58
59
|
);
|
|
59
60
|
}
|
|
60
61
|
}
|
package/lib/md054.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
5
|
const { addErrorContext, nextLinesRe } = require("../helpers");
|
|
6
|
-
const {
|
|
6
|
+
const { getDescendantsByType } = require("../helpers/micromark-helpers.cjs");
|
|
7
7
|
const { getReferenceLinkImageData, filterByTypesCached } = require("./cache");
|
|
8
8
|
|
|
9
9
|
const backslashEscapeRe = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g;
|
|
@@ -45,24 +45,23 @@ module.exports = {
|
|
|
45
45
|
let label = null;
|
|
46
46
|
let destination = null;
|
|
47
47
|
const {
|
|
48
|
-
|
|
48
|
+
endColumn, endLine, startColumn, startLine, text, type
|
|
49
49
|
} = link;
|
|
50
50
|
const image = (type === "image");
|
|
51
51
|
let isError = false;
|
|
52
52
|
if (type === "autolink") {
|
|
53
53
|
// link kind is an autolink
|
|
54
|
-
destination =
|
|
54
|
+
destination = getDescendantsByType(link, [ [ "autolinkEmail", "autolinkProtocol" ] ])[0]?.text;
|
|
55
55
|
label = destination;
|
|
56
|
-
isError = !autolink;
|
|
56
|
+
isError = !autolink && Boolean(destination);
|
|
57
57
|
} else {
|
|
58
58
|
// link type is "image" or "link"
|
|
59
|
-
|
|
60
|
-
label = getTokenTextByType(descendents, "labelText");
|
|
59
|
+
label = getDescendantsByType(link, [ "label", "labelText" ])[0].text;
|
|
61
60
|
destination =
|
|
62
|
-
|
|
61
|
+
getDescendantsByType(link, [ "resource", "resourceDestination", [ "resourceDestinationLiteral", "resourceDestinationRaw" ], "resourceDestinationString" ])[0]?.text;
|
|
63
62
|
if (destination) {
|
|
64
63
|
// link kind is an inline link
|
|
65
|
-
const title =
|
|
64
|
+
const title = getDescendantsByType(link, [ "resource", "resourceTitle", "resourceTitleString" ])[0]?.text;
|
|
66
65
|
isError = !inline || (
|
|
67
66
|
!urlInline &&
|
|
68
67
|
autolink &&
|
|
@@ -73,9 +72,9 @@ module.exports = {
|
|
|
73
72
|
);
|
|
74
73
|
} else {
|
|
75
74
|
// link kind is a full/collapsed/shortcut reference link
|
|
76
|
-
const isShortcut =
|
|
77
|
-
const referenceString =
|
|
78
|
-
const isCollapsed = (referenceString ===
|
|
75
|
+
const isShortcut = getDescendantsByType(link, [ "reference" ]).length === 0;
|
|
76
|
+
const referenceString = getDescendantsByType(link, [ "reference", "referenceString" ])[0]?.text;
|
|
77
|
+
const isCollapsed = (referenceString === undefined);
|
|
79
78
|
const definition = definitions.get(referenceString || label);
|
|
80
79
|
destination = definition && definition[1];
|
|
81
80
|
isError = destination &&
|
|
@@ -83,9 +82,8 @@ module.exports = {
|
|
|
83
82
|
}
|
|
84
83
|
}
|
|
85
84
|
if (isError) {
|
|
86
|
-
// eslint-disable-next-line no-undef-init
|
|
87
85
|
let range = undefined;
|
|
88
|
-
let fixInfo =
|
|
86
|
+
let fixInfo = undefined;
|
|
89
87
|
if (startLine === endLine) {
|
|
90
88
|
range = [ startColumn, endColumn - startColumn ];
|
|
91
89
|
let insertText = null;
|