markdownlint 0.26.2 → 0.28.0
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 +378 -0
- package/CONTRIBUTING.md +82 -59
- package/LICENSE +1 -1
- package/README.md +304 -305
- package/demo/markdownlint-browser.js +4973 -3379
- package/doc/CustomRules.md +99 -51
- package/doc/Prettier.md +14 -10
- package/doc/ReleaseProcess.md +20 -0
- package/doc/Rules.md +474 -311
- package/doc/md001.md +37 -0
- package/doc/md002.md +37 -0
- package/doc/md003.md +59 -0
- package/doc/md004.md +49 -0
- package/doc/md005.md +53 -0
- package/doc/md006.md +46 -0
- package/doc/md007.md +55 -0
- package/doc/md009.md +51 -0
- package/doc/md010.md +56 -0
- package/doc/md011.md +30 -0
- package/doc/md012.md +38 -0
- package/doc/md013.md +60 -0
- package/doc/md014.md +54 -0
- package/doc/md018.md +27 -0
- package/doc/md019.md +28 -0
- package/doc/md020.md +29 -0
- package/doc/md021.md +31 -0
- package/doc/md022.md +46 -0
- package/doc/md023.md +26 -0
- package/doc/md024.md +47 -0
- package/doc/md025.md +49 -0
- package/doc/md026.md +41 -0
- package/doc/md027.md +24 -0
- package/doc/md028.md +40 -0
- package/doc/md029.md +98 -0
- package/doc/md030.md +82 -0
- package/doc/md031.md +50 -0
- package/doc/md032.md +38 -0
- package/doc/md033.md +27 -0
- package/doc/md034.md +50 -0
- package/doc/md035.md +42 -0
- package/doc/md036.md +45 -0
- package/doc/md037.md +37 -0
- package/doc/md038.md +40 -0
- package/doc/md039.md +21 -0
- package/doc/md040.md +52 -0
- package/doc/md041.md +49 -0
- package/doc/md042.md +32 -0
- package/doc/md043.md +72 -0
- package/doc/md044.md +35 -0
- package/doc/md045.md +34 -0
- package/doc/md046.md +40 -0
- package/doc/md047.md +34 -0
- package/doc/md048.md +41 -0
- package/doc/md049.md +32 -0
- package/doc/md050.md +32 -0
- package/doc/md051.md +50 -0
- package/doc/md052.md +33 -0
- package/doc/md053.md +38 -0
- package/helpers/LICENSE +1 -1
- package/helpers/README.md +35 -15
- package/helpers/helpers.js +182 -162
- package/helpers/micromark.cjs +209 -0
- package/helpers/package.json +5 -2
- package/lib/constants.js +8 -1
- package/lib/markdownlint.d.ts +5 -5
- package/lib/markdownlint.js +46 -24
- package/lib/md002.js +1 -1
- package/lib/md011.js +2 -2
- package/lib/md013.js +7 -6
- package/lib/md019.js +1 -1
- package/lib/md022.js +15 -3
- package/lib/md023.js +1 -1
- package/lib/md026.js +1 -1
- package/lib/md027.js +1 -1
- package/lib/md028.js +1 -1
- package/lib/md033.js +47 -29
- package/lib/md034.js +54 -47
- package/lib/md035.js +9 -11
- package/lib/md036.js +1 -1
- package/lib/md037.js +2 -2
- package/lib/md038.js +81 -56
- package/lib/md039.js +1 -1
- package/lib/md040.js +21 -2
- package/lib/md041.js +1 -1
- package/lib/md043.js +4 -2
- package/lib/md044.js +58 -43
- package/lib/md046.js +1 -1
- package/lib/md048.js +3 -1
- package/lib/md051.js +37 -5
- package/lib/rules.js +1 -1
- package/package.json +43 -28
- package/schema/.markdownlint.jsonc +11 -4
- package/schema/.markdownlint.yaml +11 -6
- package/schema/markdownlint-config-schema.json +27 -3
- package/style/prettier.json +26 -0
package/lib/md033.js
CHANGED
|
@@ -2,16 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const { codeBlockAndSpanRanges, lineMetadata } = require("./cache");
|
|
5
|
+
const { addError } = require("../helpers");
|
|
6
|
+
const { filterByTypes, getHtmlTagInfo, parse } =
|
|
7
|
+
require("../helpers/micromark.cjs");
|
|
9
8
|
|
|
10
|
-
const
|
|
11
|
-
// See https://spec.commonmark.org/0.29/#autolinks
|
|
12
|
-
const emailAddressRe =
|
|
13
|
-
// eslint-disable-next-line max-len
|
|
14
|
-
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
9
|
+
const nextLinesRe = /[\r\n][\s\S]*$/;
|
|
15
10
|
|
|
16
11
|
module.exports = {
|
|
17
12
|
"names": [ "MD033", "no-inline-html" ],
|
|
@@ -21,28 +16,51 @@ module.exports = {
|
|
|
21
16
|
let allowedElements = params.config.allowed_elements;
|
|
22
17
|
allowedElements = Array.isArray(allowedElements) ? allowedElements : [];
|
|
23
18
|
allowedElements = allowedElements.map((element) => element.toLowerCase());
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
19
|
+
const pending = [ [ 0, params.parsers.micromark.tokens ] ];
|
|
20
|
+
let current = null;
|
|
21
|
+
while ((current = pending.shift())) {
|
|
22
|
+
const [ offset, tokens ] = current;
|
|
23
|
+
for (const token of filterByTypes(tokens, [ "htmlFlow", "htmlText" ])) {
|
|
24
|
+
if (token.type === "htmlText") {
|
|
25
|
+
const htmlTagInfo = getHtmlTagInfo(token);
|
|
26
|
+
if (
|
|
27
|
+
htmlTagInfo &&
|
|
28
|
+
!htmlTagInfo.close &&
|
|
29
|
+
!allowedElements.includes(htmlTagInfo.name.toLowerCase())
|
|
30
|
+
) {
|
|
31
|
+
const range = [
|
|
32
|
+
token.startColumn,
|
|
33
|
+
token.text.replace(nextLinesRe, "").length
|
|
34
|
+
];
|
|
35
|
+
addError(
|
|
36
|
+
onError,
|
|
37
|
+
token.startLine + offset,
|
|
38
|
+
"Element: " + htmlTagInfo.name,
|
|
39
|
+
undefined,
|
|
40
|
+
range
|
|
41
|
+
);
|
|
43
42
|
}
|
|
43
|
+
} else {
|
|
44
|
+
// token.type === "htmlFlow"
|
|
45
|
+
// Re-parse without "htmlFlow" to get only "htmlText" tokens
|
|
46
|
+
const options = {
|
|
47
|
+
"extensions": [
|
|
48
|
+
{
|
|
49
|
+
"disable": {
|
|
50
|
+
"null": [ "codeIndented", "htmlFlow" ]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
};
|
|
55
|
+
// Use lines instead of token.text for accurate columns
|
|
56
|
+
const lines =
|
|
57
|
+
params.lines.slice(token.startLine - 1, token.endLine).join("\n");
|
|
58
|
+
const flowTokens = parse(lines, options);
|
|
59
|
+
pending.push(
|
|
60
|
+
[ token.startLine - 1, flowTokens ]
|
|
61
|
+
);
|
|
44
62
|
}
|
|
45
63
|
}
|
|
46
|
-
}
|
|
64
|
+
}
|
|
47
65
|
}
|
|
48
66
|
};
|
package/lib/md034.js
CHANGED
|
@@ -2,60 +2,67 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorContext
|
|
5
|
+
const { addErrorContext } = require("../helpers");
|
|
6
|
+
const { filterByPredicate, getHtmlTagInfo } =
|
|
7
|
+
require("../helpers/micromark.cjs");
|
|
6
8
|
|
|
7
9
|
module.exports = {
|
|
8
10
|
"names": [ "MD034", "no-bare-urls" ],
|
|
9
11
|
"description": "Bare URL used",
|
|
10
12
|
"tags": [ "links", "url" ],
|
|
11
13
|
"function": function MD034(params, onError) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const fixInfo = range ? {
|
|
42
|
-
"editColumn": range[0],
|
|
43
|
-
"deleteCount": range[1],
|
|
44
|
-
"insertText": `<${bareUrl}>`
|
|
45
|
-
} : null;
|
|
46
|
-
addErrorContext(
|
|
47
|
-
onError,
|
|
48
|
-
lineNumber,
|
|
49
|
-
bareUrl,
|
|
50
|
-
null,
|
|
51
|
-
null,
|
|
52
|
-
range,
|
|
53
|
-
fixInfo
|
|
54
|
-
);
|
|
14
|
+
const literalAutolinks =
|
|
15
|
+
filterByPredicate(
|
|
16
|
+
params.parsers.micromark.tokens,
|
|
17
|
+
(token) => token.type === "literalAutolink",
|
|
18
|
+
(token) => {
|
|
19
|
+
const { children } = token;
|
|
20
|
+
const result = [];
|
|
21
|
+
for (let i = 0; i < children.length; i++) {
|
|
22
|
+
const openToken = children[i];
|
|
23
|
+
const openTagInfo = getHtmlTagInfo(openToken);
|
|
24
|
+
if (openTagInfo && !openTagInfo.close) {
|
|
25
|
+
let count = 1;
|
|
26
|
+
for (let j = i + 1; j < children.length; j++) {
|
|
27
|
+
const closeToken = children[j];
|
|
28
|
+
const closeTagInfo = getHtmlTagInfo(closeToken);
|
|
29
|
+
if (closeTagInfo && (openTagInfo.name === closeTagInfo.name)) {
|
|
30
|
+
if (closeTagInfo.close) {
|
|
31
|
+
count--;
|
|
32
|
+
if (count === 0) {
|
|
33
|
+
i = j;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
count++;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
result.push(openToken);
|
|
55
43
|
}
|
|
56
44
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
45
|
+
return result;
|
|
46
|
+
});
|
|
47
|
+
for (const token of literalAutolinks) {
|
|
48
|
+
const range = [
|
|
49
|
+
token.startColumn,
|
|
50
|
+
token.endColumn - token.startColumn
|
|
51
|
+
];
|
|
52
|
+
const fixInfo = {
|
|
53
|
+
"editColumn": range[0],
|
|
54
|
+
"deleteCount": range[1],
|
|
55
|
+
"insertText": `<${token.text}>`
|
|
56
|
+
};
|
|
57
|
+
addErrorContext(
|
|
58
|
+
onError,
|
|
59
|
+
token.startLine,
|
|
60
|
+
token.text,
|
|
61
|
+
null,
|
|
62
|
+
null,
|
|
63
|
+
range,
|
|
64
|
+
fixInfo
|
|
65
|
+
);
|
|
66
|
+
}
|
|
60
67
|
}
|
|
61
68
|
};
|
package/lib/md035.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorDetailIf
|
|
5
|
+
const { addErrorDetailIf } = require("../helpers");
|
|
6
|
+
const { filterByTypes } = require("../helpers/micromark.cjs");
|
|
6
7
|
|
|
7
8
|
module.exports = {
|
|
8
9
|
"names": [ "MD035", "hr-style" ],
|
|
@@ -10,17 +11,14 @@ module.exports = {
|
|
|
10
11
|
"tags": [ "hr" ],
|
|
11
12
|
"function": function MD035(params, onError) {
|
|
12
13
|
let style = String(params.config.style || "consistent").trim();
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
if (match) {
|
|
18
|
-
markup = match[0].trim();
|
|
19
|
-
}
|
|
14
|
+
const thematicBreaks =
|
|
15
|
+
filterByTypes(params.parsers.micromark.tokens, [ "thematicBreak" ]);
|
|
16
|
+
for (const token of thematicBreaks) {
|
|
17
|
+
const { startLine, text } = token;
|
|
20
18
|
if (style === "consistent") {
|
|
21
|
-
style =
|
|
19
|
+
style = text;
|
|
22
20
|
}
|
|
23
|
-
addErrorDetailIf(onError,
|
|
24
|
-
}
|
|
21
|
+
addErrorDetailIf(onError, startLine, style, text);
|
|
22
|
+
}
|
|
25
23
|
}
|
|
26
24
|
};
|
package/lib/md036.js
CHANGED
package/lib/md037.js
CHANGED
|
@@ -6,8 +6,8 @@ const { addErrorContext, emphasisMarkersInContent, forEachLine, isBlankLine,
|
|
|
6
6
|
withinAnyRange } = require("../helpers");
|
|
7
7
|
const { htmlElementRanges, lineMetadata } = require("./cache");
|
|
8
8
|
|
|
9
|
-
const emphasisRe = /(^|[^\\]|\\\\)(?:(
|
|
10
|
-
const embeddedUnderscoreRe = /([A-Za-
|
|
9
|
+
const emphasisRe = /(^|[^\\]|\\\\)(?:(\*{1,3})|(_{1,3}))/g;
|
|
10
|
+
const embeddedUnderscoreRe = /([A-Za-z\d])_([A-Za-z\d])/g;
|
|
11
11
|
const asteriskListItemMarkerRe = /^([\s>]*)\*(\s+)/;
|
|
12
12
|
const leftSpaceRe = /^\s+/;
|
|
13
13
|
const rightSpaceRe = /\s+$/;
|
package/lib/md038.js
CHANGED
|
@@ -2,70 +2,95 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorContext
|
|
6
|
-
|
|
5
|
+
const { addErrorContext } = require("../helpers");
|
|
6
|
+
const { filterByTypes } = require("../helpers/micromark.cjs");
|
|
7
7
|
|
|
8
|
-
const leftSpaceRe = /^\s([^`]|$)/;
|
|
8
|
+
const leftSpaceRe = /^\s(?:[^`]|$)/;
|
|
9
9
|
const rightSpaceRe = /[^`]\s$/;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
(
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
const trimCodeText = (text, start, end) => {
|
|
11
|
+
text = text.replace(/^\s+$/, "");
|
|
12
|
+
if (start) {
|
|
13
|
+
text = text.replace(/^\s+?(\s`|\S)/, "$1");
|
|
14
|
+
}
|
|
15
|
+
if (end) {
|
|
16
|
+
text = text.replace(/(`\s|\S)\s+$/, "$1");
|
|
17
|
+
}
|
|
18
|
+
return text;
|
|
19
|
+
};
|
|
20
|
+
const tokenIfType = (token, type) => token && (token.type === type) && token;
|
|
15
21
|
|
|
16
22
|
module.exports = {
|
|
17
23
|
"names": [ "MD038", "no-space-in-code" ],
|
|
18
24
|
"description": "Spaces inside code span elements",
|
|
19
25
|
"tags": [ "whitespace", "code" ],
|
|
20
26
|
"function": function MD038(params, onError) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
27
|
+
const codeTextTokens =
|
|
28
|
+
filterByTypes(params.parsers.micromark.tokens, [ "codeText" ]);
|
|
29
|
+
for (const token of codeTextTokens) {
|
|
30
|
+
const { children } = token;
|
|
31
|
+
const first = 0;
|
|
32
|
+
const last = children.length - 1;
|
|
33
|
+
const startSequence = tokenIfType(children[first], "codeTextSequence");
|
|
34
|
+
const endSequence = tokenIfType(children[last], "codeTextSequence");
|
|
35
|
+
const startData =
|
|
36
|
+
tokenIfType(children[first + 1], "codeTextData") ||
|
|
37
|
+
tokenIfType(children[first + 2], "codeTextData");
|
|
38
|
+
const endData =
|
|
39
|
+
tokenIfType(children[last - 1], "codeTextData") ||
|
|
40
|
+
tokenIfType(children[last - 2], "codeTextData");
|
|
41
|
+
if (startSequence && endSequence && startData && endData) {
|
|
42
|
+
const spaceLeft = leftSpaceRe.test(startData.text);
|
|
43
|
+
const spaceRight = !spaceLeft && rightSpaceRe.test(endData.text);
|
|
44
|
+
if (spaceLeft || spaceRight) {
|
|
45
|
+
let lineNumber = startSequence.startLine;
|
|
46
|
+
let range = null;
|
|
47
|
+
let fixInfo = null;
|
|
48
|
+
if (startSequence.startLine === endSequence.endLine) {
|
|
49
|
+
range = [
|
|
50
|
+
startSequence.startColumn,
|
|
51
|
+
endSequence.endColumn - startSequence.startColumn
|
|
52
|
+
];
|
|
53
|
+
fixInfo = {
|
|
54
|
+
"editColumn": startSequence.endColumn,
|
|
55
|
+
"deleteCount": endSequence.startColumn - startSequence.endColumn,
|
|
56
|
+
"insertText": trimCodeText(startData.text, true, true)
|
|
57
|
+
};
|
|
58
|
+
} else if (spaceLeft) {
|
|
59
|
+
range = [
|
|
60
|
+
startSequence.startColumn,
|
|
61
|
+
startData.endColumn - startSequence.startColumn
|
|
62
|
+
];
|
|
63
|
+
fixInfo = {
|
|
64
|
+
"editColumn": startSequence.endColumn,
|
|
65
|
+
"deleteCount": startData.endColumn - startData.startColumn,
|
|
66
|
+
"insertText": trimCodeText(startData.text, true, false)
|
|
67
|
+
};
|
|
68
|
+
} else {
|
|
69
|
+
lineNumber = endSequence.endLine;
|
|
70
|
+
range = [
|
|
71
|
+
endData.startColumn,
|
|
72
|
+
endSequence.endColumn - endData.startColumn
|
|
73
|
+
];
|
|
74
|
+
fixInfo = {
|
|
75
|
+
"editColumn": endData.startColumn,
|
|
76
|
+
"deleteCount": endData.endColumn - endData.startColumn,
|
|
77
|
+
"insertText": trimCodeText(endData.text, false, true)
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const context = params
|
|
81
|
+
.lines[lineNumber - 1]
|
|
82
|
+
.substring(range[0] - 1, range[0] - 1 + range[1]);
|
|
83
|
+
addErrorContext(
|
|
84
|
+
onError,
|
|
85
|
+
lineNumber,
|
|
86
|
+
context,
|
|
87
|
+
spaceLeft,
|
|
88
|
+
spaceRight,
|
|
89
|
+
range,
|
|
90
|
+
fixInfo
|
|
91
|
+
);
|
|
92
|
+
}
|
|
68
93
|
}
|
|
69
|
-
}
|
|
94
|
+
}
|
|
70
95
|
}
|
|
71
96
|
};
|
package/lib/md039.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
const { addErrorContext, filterTokens } = require("../helpers");
|
|
6
6
|
|
|
7
7
|
const spaceInLinkRe =
|
|
8
|
-
/\[(?:\s
|
|
8
|
+
/\[(?:\s[^\]]*|[^\]]*?\s)\](?=(\([^)]*\)|\[[^\]]*\]))/;
|
|
9
9
|
|
|
10
10
|
module.exports = {
|
|
11
11
|
"names": [ "MD039", "no-space-in-links" ],
|
package/lib/md040.js
CHANGED
|
@@ -2,16 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorContext, filterTokens } = require("../helpers");
|
|
5
|
+
const { addError, addErrorContext, filterTokens } = require("../helpers");
|
|
6
6
|
|
|
7
7
|
module.exports = {
|
|
8
8
|
"names": [ "MD040", "fenced-code-language" ],
|
|
9
9
|
"description": "Fenced code blocks should have a language specified",
|
|
10
10
|
"tags": [ "code", "language" ],
|
|
11
11
|
"function": function MD040(params, onError) {
|
|
12
|
+
let allowed = params.config.allowed_languages;
|
|
13
|
+
allowed = Array.isArray(allowed) ? allowed : [];
|
|
14
|
+
const languageOnly = !!params.config.language_only;
|
|
15
|
+
|
|
12
16
|
filterTokens(params, "fence", function forToken(token) {
|
|
13
|
-
|
|
17
|
+
const lang = token.info.trim().split(/\s+/u).shift();
|
|
18
|
+
if (lang === "") {
|
|
14
19
|
addErrorContext(onError, token.lineNumber, token.line);
|
|
20
|
+
} else if ((allowed.length > 0) && !allowed.includes(lang)) {
|
|
21
|
+
addError(
|
|
22
|
+
onError,
|
|
23
|
+
token.lineNumber,
|
|
24
|
+
`"${lang}" is not allowed`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (languageOnly && (token.info !== lang)) {
|
|
29
|
+
addError(
|
|
30
|
+
onError,
|
|
31
|
+
token.lineNumber,
|
|
32
|
+
`Info string contains more than language: "${token.info}"`
|
|
33
|
+
);
|
|
15
34
|
}
|
|
16
35
|
});
|
|
17
36
|
}
|
package/lib/md041.js
CHANGED
|
@@ -18,7 +18,7 @@ module.exports = {
|
|
|
18
18
|
);
|
|
19
19
|
if (!foundFrontMatterTitle) {
|
|
20
20
|
const htmlHeadingRe = new RegExp(`^<h${level}[ />]`, "i");
|
|
21
|
-
params.tokens.every((token) => {
|
|
21
|
+
params.parsers.markdownit.tokens.every((token) => {
|
|
22
22
|
let isError = false;
|
|
23
23
|
if (token.type === "html_block") {
|
|
24
24
|
if (token.content.startsWith("<!--")) {
|
package/lib/md043.js
CHANGED
|
@@ -11,6 +11,7 @@ module.exports = {
|
|
|
11
11
|
"tags": [ "headings", "headers" ],
|
|
12
12
|
"function": function MD043(params, onError) {
|
|
13
13
|
const requiredHeadings = params.config.headings || params.config.headers;
|
|
14
|
+
const matchCase = params.config.match_case || false;
|
|
14
15
|
if (Array.isArray(requiredHeadings)) {
|
|
15
16
|
const levels = {};
|
|
16
17
|
for (const level of [ 1, 2, 3, 4, 5, 6 ]) {
|
|
@@ -21,6 +22,7 @@ module.exports = {
|
|
|
21
22
|
let hasError = false;
|
|
22
23
|
let anyHeadings = false;
|
|
23
24
|
const getExpected = () => requiredHeadings[i++] || "[None]";
|
|
25
|
+
const handleCase = (str) => (matchCase ? str : str.toLowerCase());
|
|
24
26
|
forEachHeading(params, (heading, content) => {
|
|
25
27
|
if (!hasError) {
|
|
26
28
|
anyHeadings = true;
|
|
@@ -28,13 +30,13 @@ module.exports = {
|
|
|
28
30
|
const expected = getExpected();
|
|
29
31
|
if (expected === "*") {
|
|
30
32
|
const nextExpected = getExpected();
|
|
31
|
-
if (nextExpected
|
|
33
|
+
if (handleCase(nextExpected) !== handleCase(actual)) {
|
|
32
34
|
matchAny = true;
|
|
33
35
|
i--;
|
|
34
36
|
}
|
|
35
37
|
} else if (expected === "+") {
|
|
36
38
|
matchAny = true;
|
|
37
|
-
} else if (expected
|
|
39
|
+
} else if (handleCase(expected) === handleCase(actual)) {
|
|
38
40
|
matchAny = false;
|
|
39
41
|
} else if (matchAny) {
|
|
40
42
|
i--;
|
package/lib/md044.js
CHANGED
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorDetailIf,
|
|
6
|
-
forEachLink, withinAnyRange, linkReferenceDefinitionRe } =
|
|
5
|
+
const { addErrorDetailIf, escapeForRegExp, withinAnyRange } =
|
|
7
6
|
require("../helpers");
|
|
8
|
-
const {
|
|
9
|
-
require("
|
|
7
|
+
const { filterByPredicate, filterByTypes, parse } =
|
|
8
|
+
require("../helpers/micromark.cjs");
|
|
9
|
+
|
|
10
|
+
const ignoredChildTypes = new Set(
|
|
11
|
+
[ "codeFencedFence", "definition", "reference", "resource" ]
|
|
12
|
+
);
|
|
10
13
|
|
|
11
14
|
module.exports = {
|
|
12
15
|
"names": [ "MD044", "proper-names" ],
|
|
@@ -22,30 +25,25 @@ module.exports = {
|
|
|
22
25
|
const htmlElements = params.config.html_elements;
|
|
23
26
|
const includeHtmlElements =
|
|
24
27
|
(htmlElements === undefined) ? true : !!htmlElements;
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
} else {
|
|
30
|
-
let match = null;
|
|
31
|
-
while ((match = bareUrlRe.exec(line)) !== null) {
|
|
32
|
-
exclusions.push([ lineIndex, match.index, match[0].length ]);
|
|
33
|
-
}
|
|
34
|
-
forEachLink(line, (index, _, text, destination) => {
|
|
35
|
-
if (destination) {
|
|
36
|
-
exclusions.push(
|
|
37
|
-
[ lineIndex, index + text.length, destination.length ]
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
if (!includeCodeBlocks) {
|
|
44
|
-
exclusions.push(...codeBlockAndSpanRanges());
|
|
45
|
-
}
|
|
46
|
-
if (!includeHtmlElements) {
|
|
47
|
-
exclusions.push(...htmlElementRanges());
|
|
28
|
+
const scannedTypes = new Set([ "data", "htmlFlowData" ]);
|
|
29
|
+
if (includeCodeBlocks) {
|
|
30
|
+
scannedTypes.add("codeFlowValue");
|
|
31
|
+
scannedTypes.add("codeTextData");
|
|
48
32
|
}
|
|
33
|
+
const contentTokens =
|
|
34
|
+
filterByPredicate(
|
|
35
|
+
params.parsers.micromark.tokens,
|
|
36
|
+
(token) => scannedTypes.has(token.type),
|
|
37
|
+
(token) => {
|
|
38
|
+
let { children } = token;
|
|
39
|
+
if (!includeHtmlElements && (token.type === "htmlFlow")) {
|
|
40
|
+
children = children.slice(1, -1);
|
|
41
|
+
}
|
|
42
|
+
return children.filter((t) => !ignoredChildTypes.has(t.type));
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
const exclusions = [];
|
|
46
|
+
const autoLinked = new Set();
|
|
49
47
|
for (const name of names) {
|
|
50
48
|
const escapedName = escapeForRegExp(name);
|
|
51
49
|
const startNamePattern = /^\W/.test(name) ? "" : "\\b_*";
|
|
@@ -53,36 +51,53 @@ module.exports = {
|
|
|
53
51
|
const namePattern =
|
|
54
52
|
`(${startNamePattern})(${escapedName})${endNamePattern}`;
|
|
55
53
|
const nameRe = new RegExp(namePattern, "gi");
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
for (const token of contentTokens) {
|
|
55
|
+
let match = null;
|
|
56
|
+
while ((match = nameRe.exec(token.text)) !== null) {
|
|
57
|
+
const [ , leftMatch, nameMatch ] = match;
|
|
58
|
+
const index = token.startColumn - 1 + match.index + leftMatch.length;
|
|
59
|
+
const length = nameMatch.length;
|
|
60
|
+
const lineIndex = token.startLine - 1;
|
|
61
|
+
if (
|
|
62
|
+
!withinAnyRange(exclusions, lineIndex, index, length) &&
|
|
63
|
+
!names.includes(nameMatch)
|
|
64
|
+
) {
|
|
65
|
+
let urlRanges = [];
|
|
66
|
+
if (!autoLinked.has(token)) {
|
|
67
|
+
urlRanges = filterByTypes(
|
|
68
|
+
parse(token.text),
|
|
69
|
+
[ "literalAutolink" ]
|
|
70
|
+
).map(
|
|
71
|
+
(t) => [
|
|
72
|
+
lineIndex,
|
|
73
|
+
token.startColumn - 1 + t.startColumn - 1,
|
|
74
|
+
t.endColumn - t.startColumn
|
|
75
|
+
]
|
|
76
|
+
);
|
|
77
|
+
exclusions.push(...urlRanges);
|
|
78
|
+
autoLinked.add(token);
|
|
79
|
+
}
|
|
80
|
+
if (!withinAnyRange(urlRanges, lineIndex, index, length)) {
|
|
81
|
+
const column = index + 1;
|
|
67
82
|
addErrorDetailIf(
|
|
68
83
|
onError,
|
|
69
|
-
|
|
84
|
+
token.startLine,
|
|
70
85
|
name,
|
|
71
86
|
nameMatch,
|
|
72
87
|
null,
|
|
73
88
|
null,
|
|
74
|
-
[
|
|
89
|
+
[ column, length ],
|
|
75
90
|
{
|
|
76
|
-
"editColumn":
|
|
91
|
+
"editColumn": column,
|
|
77
92
|
"deleteCount": length,
|
|
78
93
|
"insertText": name
|
|
79
94
|
}
|
|
80
95
|
);
|
|
81
96
|
}
|
|
82
|
-
exclusions.push([ lineIndex, index, length ]);
|
|
83
97
|
}
|
|
98
|
+
exclusions.push([ lineIndex, index, length ]);
|
|
84
99
|
}
|
|
85
|
-
}
|
|
100
|
+
}
|
|
86
101
|
}
|
|
87
102
|
}
|
|
88
103
|
};
|