markdownlint 0.34.0 → 0.35.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 +11 -0
- package/README.md +25 -10
- package/demo/markdownlint-browser.js +1144 -1166
- package/doc/CustomRules.md +11 -6
- package/doc/Rules.md +66 -0
- package/doc/md034.md +5 -0
- package/doc/md044.md +10 -0
- package/doc/md058.md +48 -0
- package/helpers/README.md +3 -29
- package/helpers/helpers.js +56 -288
- package/helpers/micromark.cjs +111 -12
- package/helpers/package.json +1 -1
- package/lib/cache.js +62 -13
- package/lib/configuration-strict.d.ts +1185 -0
- package/lib/configuration.d.ts +3 -1173
- package/lib/constants.js +3 -2
- package/lib/markdownlint.d.ts +65 -56
- package/lib/markdownlint.js +59 -37
- package/lib/md001.js +15 -9
- package/lib/md003.js +14 -9
- package/lib/md004.js +55 -48
- package/lib/md005.js +4 -13
- package/lib/md007.js +5 -9
- package/lib/md009.js +50 -44
- package/lib/md010.js +48 -33
- package/lib/md011.js +16 -8
- package/lib/md012.js +17 -9
- package/lib/md013.js +44 -38
- package/lib/md014.js +35 -38
- package/lib/md018.js +17 -9
- package/lib/md019-md021.js +80 -0
- package/lib/md020.js +13 -7
- package/lib/md022.js +6 -16
- package/lib/md023.js +22 -23
- package/lib/md024.js +12 -9
- package/lib/md025.js +15 -10
- package/lib/md026.js +2 -7
- package/lib/md027.js +5 -10
- package/lib/md028.js +3 -8
- package/lib/md029.js +40 -34
- package/lib/md030.js +4 -10
- package/lib/md031.js +43 -23
- package/lib/md032.js +16 -26
- package/lib/md033.js +3 -8
- package/lib/md034.js +5 -10
- package/lib/md035.js +2 -7
- package/lib/md036.js +3 -2
- package/lib/md037.js +2 -7
- package/lib/md038.js +3 -9
- package/lib/md039.js +66 -54
- package/lib/md040.js +3 -8
- package/lib/md041.js +1 -1
- package/lib/md042.js +48 -38
- package/lib/md043.js +20 -14
- package/lib/md044.js +3 -8
- package/lib/md045.js +3 -8
- package/lib/md046.js +2 -8
- package/lib/md048.js +3 -7
- package/lib/md049-md050.js +2 -7
- package/lib/md051.js +6 -12
- package/lib/md052.js +2 -2
- package/lib/md053.js +2 -2
- package/lib/md054.js +8 -13
- package/lib/md055.js +7 -8
- package/lib/md056.js +15 -11
- package/lib/md058.js +43 -0
- package/lib/rules.js +11 -4
- package/package.json +19 -17
- package/schema/.markdownlint.jsonc +54 -51
- package/schema/.markdownlint.yaml +53 -50
- package/schema/ValidatingConfiguration.md +6 -8
- package/schema/markdownlint-config-schema-strict.json +1819 -0
- package/schema/markdownlint-config-schema.json +115 -105
- package/style/prettier.json +1 -0
- package/lib/md019.js +0 -42
- package/lib/md021.js +0 -65
package/lib/md007.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
5
|
const { addErrorDetailIf } = require("../helpers");
|
|
6
|
-
const {
|
|
7
|
-
|
|
6
|
+
const { getTokenParentOfType } = require("../helpers/micromark.cjs");
|
|
7
|
+
const { filterByTypesCached } = require("./cache");
|
|
8
8
|
|
|
9
9
|
// eslint-disable-next-line jsdoc/valid-types
|
|
10
10
|
/** @type import("markdownlint-micromark").TokenType[] */
|
|
@@ -26,14 +26,9 @@ module.exports = {
|
|
|
26
26
|
const indent = Number(params.config.indent || 2);
|
|
27
27
|
const startIndented = !!params.config.start_indented;
|
|
28
28
|
const startIndent = Number(params.config.start_indent || indent);
|
|
29
|
-
// eslint-disable-next-line jsdoc/valid-types
|
|
30
|
-
/** @type import("../helpers/micromark.cjs").Token[] */
|
|
31
|
-
const micromarkTokens =
|
|
32
|
-
// @ts-ignore
|
|
33
|
-
params.parsers.micromark.tokens;
|
|
34
29
|
const unorderedListNesting = new Map();
|
|
35
30
|
let lastBlockQuotePrefix = null;
|
|
36
|
-
const tokens =
|
|
31
|
+
const tokens = filterByTypesCached(unorderedListTypes);
|
|
37
32
|
for (const token of tokens) {
|
|
38
33
|
const { endColumn, parent, startColumn, startLine, type } = token;
|
|
39
34
|
if (type === "blockQuotePrefix") {
|
|
@@ -43,6 +38,7 @@ module.exports = {
|
|
|
43
38
|
/** @type {import("../helpers/micromark.cjs").Token | null} */
|
|
44
39
|
let current = token;
|
|
45
40
|
while (
|
|
41
|
+
// @ts-ignore
|
|
46
42
|
(current = getTokenParentOfType(current, unorderedParentTypes))
|
|
47
43
|
) {
|
|
48
44
|
if (current.type === "listUnordered") {
|
|
@@ -57,7 +53,7 @@ module.exports = {
|
|
|
57
53
|
if (nesting >= 0) {
|
|
58
54
|
unorderedListNesting.set(token, nesting);
|
|
59
55
|
}
|
|
60
|
-
} else
|
|
56
|
+
} else {
|
|
61
57
|
// listItemPrefix
|
|
62
58
|
const nesting = unorderedListNesting.get(parent);
|
|
63
59
|
if (nesting !== undefined) {
|
package/lib/md009.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addError
|
|
6
|
-
|
|
7
|
-
const {
|
|
5
|
+
const { addError } = require("../helpers");
|
|
6
|
+
const { addRangeToSet } = require("../helpers/micromark.cjs");
|
|
7
|
+
const { filterByTypesCached } = require("./cache");
|
|
8
8
|
|
|
9
9
|
// eslint-disable-next-line jsdoc/valid-types
|
|
10
10
|
/** @type import("./markdownlint").Rule */
|
|
@@ -12,63 +12,68 @@ module.exports = {
|
|
|
12
12
|
"names": [ "MD009", "no-trailing-spaces" ],
|
|
13
13
|
"description": "Trailing spaces",
|
|
14
14
|
"tags": [ "whitespace" ],
|
|
15
|
-
"parser": "
|
|
15
|
+
"parser": "micromark",
|
|
16
16
|
"function": function MD009(params, onError) {
|
|
17
17
|
let brSpaces = params.config.br_spaces;
|
|
18
18
|
brSpaces = Number((brSpaces === undefined) ? 2 : brSpaces);
|
|
19
19
|
const listItemEmptyLines = !!params.config.list_item_empty_lines;
|
|
20
20
|
const strict = !!params.config.strict;
|
|
21
|
-
const
|
|
21
|
+
const codeBlockLineNumbers = new Set();
|
|
22
|
+
for (const codeBlock of filterByTypesCached([ "codeFenced" ])) {
|
|
23
|
+
addRangeToSet(codeBlockLineNumbers, codeBlock.startLine + 1, codeBlock.endLine - 1);
|
|
24
|
+
}
|
|
25
|
+
for (const codeBlock of filterByTypesCached([ "codeIndented" ])) {
|
|
26
|
+
addRangeToSet(codeBlockLineNumbers, codeBlock.startLine, codeBlock.endLine);
|
|
27
|
+
}
|
|
28
|
+
const listItemLineNumbers = new Set();
|
|
22
29
|
if (listItemEmptyLines) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
for (const listBlock of filterByTypesCached([ "listOrdered", "listUnordered" ])) {
|
|
31
|
+
addRangeToSet(listItemLineNumbers, listBlock.startLine, listBlock.endLine);
|
|
32
|
+
let trailingIndent = true;
|
|
33
|
+
for (let i = listBlock.children.length - 1; i >= 0; i--) {
|
|
34
|
+
const child = listBlock.children[i];
|
|
35
|
+
switch (child.type) {
|
|
36
|
+
case "content":
|
|
37
|
+
trailingIndent = false;
|
|
38
|
+
break;
|
|
39
|
+
case "listItemIndent":
|
|
40
|
+
if (trailingIndent) {
|
|
41
|
+
listItemLineNumbers.delete(child.startLine);
|
|
42
|
+
}
|
|
43
|
+
break;
|
|
44
|
+
case "listItemPrefix":
|
|
45
|
+
trailingIndent = true;
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
26
50
|
}
|
|
27
|
-
}
|
|
28
|
-
listItemLineNumbers.sort(numericSortAscending);
|
|
51
|
+
}
|
|
29
52
|
}
|
|
30
|
-
const paragraphLineNumbers =
|
|
31
|
-
const codeInlineLineNumbers =
|
|
53
|
+
const paragraphLineNumbers = new Set();
|
|
54
|
+
const codeInlineLineNumbers = new Set();
|
|
32
55
|
if (strict) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
for (let i = start; i < end; i++) {
|
|
40
|
-
codeInlineLineNumbers.push(i);
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
filterTokens(params, "inline", (token) => {
|
|
44
|
-
let start = 0;
|
|
45
|
-
for (const child of token.children) {
|
|
46
|
-
if (start > 0) {
|
|
47
|
-
addLineNumberRange(start, child.lineNumber);
|
|
48
|
-
start = 0;
|
|
49
|
-
}
|
|
50
|
-
if (child.type === "code_inline") {
|
|
51
|
-
start = child.lineNumber;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (start > 0) {
|
|
55
|
-
addLineNumberRange(start, token.map[1]);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
56
|
+
for (const paragraph of filterByTypesCached([ "paragraph" ])) {
|
|
57
|
+
addRangeToSet(paragraphLineNumbers, paragraph.startLine, paragraph.endLine - 1);
|
|
58
|
+
}
|
|
59
|
+
for (const codeText of filterByTypesCached([ "codeText" ])) {
|
|
60
|
+
addRangeToSet(codeInlineLineNumbers, codeText.startLine, codeText.endLine - 1);
|
|
61
|
+
}
|
|
58
62
|
}
|
|
59
63
|
const expected = (brSpaces < 2) ? 0 : brSpaces;
|
|
60
|
-
|
|
64
|
+
for (let lineIndex = 0; lineIndex < params.lines.length; lineIndex++) {
|
|
65
|
+
const line = params.lines[lineIndex];
|
|
61
66
|
const lineNumber = lineIndex + 1;
|
|
62
67
|
const trailingSpaces = line.length - line.trimEnd().length;
|
|
63
68
|
if (
|
|
64
69
|
trailingSpaces &&
|
|
65
|
-
!
|
|
66
|
-
!
|
|
70
|
+
!codeBlockLineNumbers.has(lineNumber) &&
|
|
71
|
+
!listItemLineNumbers.has(lineNumber) &&
|
|
67
72
|
(
|
|
68
73
|
(expected !== trailingSpaces) ||
|
|
69
74
|
(strict &&
|
|
70
|
-
(!
|
|
71
|
-
|
|
75
|
+
(!paragraphLineNumbers.has(lineNumber) ||
|
|
76
|
+
codeInlineLineNumbers.has(lineNumber)))
|
|
72
77
|
)
|
|
73
78
|
) {
|
|
74
79
|
const column = line.length - trailingSpaces + 1;
|
|
@@ -82,8 +87,9 @@ module.exports = {
|
|
|
82
87
|
{
|
|
83
88
|
"editColumn": column,
|
|
84
89
|
"deleteCount": trailingSpaces
|
|
85
|
-
}
|
|
90
|
+
}
|
|
91
|
+
);
|
|
86
92
|
}
|
|
87
|
-
}
|
|
93
|
+
}
|
|
88
94
|
}
|
|
89
95
|
};
|
package/lib/md010.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addError,
|
|
6
|
-
|
|
7
|
-
const {
|
|
5
|
+
const { addError, withinAnyRange } = require("../helpers");
|
|
6
|
+
const { getDescendantsByType, getExclusionsForToken } = require("../helpers/micromark.cjs");
|
|
7
|
+
const { filterByTypesCached } = require("./cache");
|
|
8
8
|
|
|
9
9
|
const tabRe = /\t+/g;
|
|
10
10
|
|
|
@@ -14,7 +14,7 @@ module.exports = {
|
|
|
14
14
|
"names": [ "MD010", "no-hard-tabs" ],
|
|
15
15
|
"description": "Hard tabs",
|
|
16
16
|
"tags": [ "whitespace", "hard_tab" ],
|
|
17
|
-
"parser": "
|
|
17
|
+
"parser": "micromark",
|
|
18
18
|
"function": function MD010(params, onError) {
|
|
19
19
|
const codeBlocks = params.config.code_blocks;
|
|
20
20
|
const includeCode = (codeBlocks === undefined) ? true : !!codeBlocks;
|
|
@@ -26,38 +26,53 @@ module.exports = {
|
|
|
26
26
|
const spaceMultiplier = (spacesPerTab === undefined) ?
|
|
27
27
|
1 :
|
|
28
28
|
Math.max(0, Number(spacesPerTab));
|
|
29
|
-
const exclusions =
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
const exclusions = [];
|
|
30
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
31
|
+
/** @type import("../helpers/micromark.cjs").TokenType[] */
|
|
32
|
+
const exclusionTypes = [];
|
|
33
|
+
if (includeCode) {
|
|
34
|
+
if (ignoreCodeLanguages.size > 0) {
|
|
35
|
+
exclusionTypes.push("codeFenced");
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
exclusionTypes.push("codeFenced", "codeIndented", "codeText");
|
|
39
|
+
}
|
|
40
|
+
const codeTokens = filterByTypesCached(exclusionTypes).filter((token) => {
|
|
41
|
+
if ((token.type === "codeFenced") && (ignoreCodeLanguages.size > 0)) {
|
|
42
|
+
const fenceInfos = getDescendantsByType(token, [ "codeFencedFence", "codeFencedFenceInfo" ]);
|
|
43
|
+
return fenceInfos.every((fenceInfo) => ignoreCodeLanguages.has(fenceInfo.text.toLowerCase()));
|
|
36
44
|
}
|
|
45
|
+
return true;
|
|
37
46
|
});
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
47
|
+
for (const codeToken of codeTokens) {
|
|
48
|
+
const exclusionsForToken = getExclusionsForToken(params.lines, codeToken);
|
|
49
|
+
if (codeToken.type === "codeFenced") {
|
|
50
|
+
exclusionsForToken.pop();
|
|
51
|
+
exclusionsForToken.shift();
|
|
52
|
+
}
|
|
53
|
+
exclusions.push(...exclusionsForToken);
|
|
54
|
+
}
|
|
55
|
+
for (let lineIndex = 0; lineIndex < params.lines.length; lineIndex++) {
|
|
56
|
+
const line = params.lines[lineIndex];
|
|
57
|
+
let match = null;
|
|
58
|
+
while ((match = tabRe.exec(line)) !== null) {
|
|
59
|
+
const column = match.index + 1;
|
|
60
|
+
const length = match[0].length;
|
|
61
|
+
if (!withinAnyRange(exclusions, lineIndex + 1, column, length)) {
|
|
62
|
+
addError(
|
|
63
|
+
onError,
|
|
64
|
+
lineIndex + 1,
|
|
65
|
+
"Column: " + column,
|
|
66
|
+
undefined,
|
|
67
|
+
[ column, length ],
|
|
68
|
+
{
|
|
69
|
+
"editColumn": column,
|
|
70
|
+
"deleteCount": length,
|
|
71
|
+
"insertText": "".padEnd(length * spaceMultiplier)
|
|
72
|
+
}
|
|
73
|
+
);
|
|
59
74
|
}
|
|
60
75
|
}
|
|
61
|
-
}
|
|
76
|
+
}
|
|
62
77
|
}
|
|
63
78
|
};
|
package/lib/md011.js
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addError,
|
|
6
|
-
const {
|
|
5
|
+
const { addError, withinAnyRange } = require("../helpers");
|
|
6
|
+
const { addRangeToSet, getExclusionsForToken } = require("../helpers/micromark.cjs");
|
|
7
|
+
const { filterByTypesCached } = require("./cache");
|
|
7
8
|
|
|
8
9
|
const reversedLinkRe =
|
|
9
10
|
/(^|[^\\])\(([^()]+)\)\[([^\]^][^\]]*)\](?!\()/g;
|
|
@@ -14,11 +15,18 @@ module.exports = {
|
|
|
14
15
|
"names": [ "MD011", "no-reversed-links" ],
|
|
15
16
|
"description": "Reversed link syntax",
|
|
16
17
|
"tags": [ "links" ],
|
|
17
|
-
"parser": "
|
|
18
|
+
"parser": "micromark",
|
|
18
19
|
"function": function MD011(params, onError) {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
const codeBlockLineNumbers = new Set();
|
|
21
|
+
for (const codeBlock of filterByTypesCached([ "codeFenced", "codeIndented" ])) {
|
|
22
|
+
addRangeToSet(codeBlockLineNumbers, codeBlock.startLine, codeBlock.endLine);
|
|
23
|
+
}
|
|
24
|
+
const exclusions = [];
|
|
25
|
+
for (const codeText of filterByTypesCached([ "codeText" ])) {
|
|
26
|
+
exclusions.push(...getExclusionsForToken(params.lines, codeText));
|
|
27
|
+
}
|
|
28
|
+
for (const [ lineIndex, line ] of params.lines.entries()) {
|
|
29
|
+
if (!codeBlockLineNumbers.has(lineIndex + 1)) {
|
|
22
30
|
let match = null;
|
|
23
31
|
while ((match = reversedLinkRe.exec(line)) !== null) {
|
|
24
32
|
const [ reversedLink, preChar, linkText, linkDestination ] = match;
|
|
@@ -27,7 +35,7 @@ module.exports = {
|
|
|
27
35
|
if (
|
|
28
36
|
!linkText.endsWith("\\") &&
|
|
29
37
|
!linkDestination.endsWith("\\") &&
|
|
30
|
-
!withinAnyRange(exclusions, lineIndex, index, length)
|
|
38
|
+
!withinAnyRange(exclusions, lineIndex + 1, index, length)
|
|
31
39
|
) {
|
|
32
40
|
addError(
|
|
33
41
|
onError,
|
|
@@ -44,6 +52,6 @@ module.exports = {
|
|
|
44
52
|
}
|
|
45
53
|
}
|
|
46
54
|
}
|
|
47
|
-
}
|
|
55
|
+
}
|
|
48
56
|
}
|
|
49
57
|
};
|
package/lib/md012.js
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorDetailIf
|
|
6
|
-
const {
|
|
5
|
+
const { addErrorDetailIf } = require("../helpers");
|
|
6
|
+
const { addRangeToSet } = require("../helpers/micromark.cjs");
|
|
7
|
+
const { filterByTypesCached } = require("./cache");
|
|
7
8
|
|
|
8
9
|
// eslint-disable-next-line jsdoc/valid-types
|
|
9
10
|
/** @type import("./markdownlint").Rule */
|
|
@@ -11,11 +12,17 @@ module.exports = {
|
|
|
11
12
|
"names": [ "MD012", "no-multiple-blanks" ],
|
|
12
13
|
"description": "Multiple consecutive blank lines",
|
|
13
14
|
"tags": [ "whitespace", "blank_lines" ],
|
|
14
|
-
"parser": "
|
|
15
|
+
"parser": "micromark",
|
|
15
16
|
"function": function MD012(params, onError) {
|
|
16
17
|
const maximum = Number(params.config.maximum || 1);
|
|
18
|
+
const { lines } = params;
|
|
19
|
+
const codeBlockLineNumbers = new Set();
|
|
20
|
+
for (const codeBlock of filterByTypesCached([ "codeFenced", "codeIndented" ])) {
|
|
21
|
+
addRangeToSet(codeBlockLineNumbers, codeBlock.startLine, codeBlock.endLine);
|
|
22
|
+
}
|
|
17
23
|
let count = 0;
|
|
18
|
-
|
|
24
|
+
for (const [ lineIndex, line ] of lines.entries()) {
|
|
25
|
+
const inCode = codeBlockLineNumbers.has(lineIndex + 1);
|
|
19
26
|
count = (inCode || (line.trim().length > 0)) ? 0 : count + 1;
|
|
20
27
|
if (maximum < count) {
|
|
21
28
|
addErrorDetailIf(
|
|
@@ -23,13 +30,14 @@ module.exports = {
|
|
|
23
30
|
lineIndex + 1,
|
|
24
31
|
maximum,
|
|
25
32
|
count,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
undefined,
|
|
34
|
+
undefined,
|
|
35
|
+
undefined,
|
|
29
36
|
{
|
|
30
37
|
"deleteCount": -1
|
|
31
|
-
}
|
|
38
|
+
}
|
|
39
|
+
);
|
|
32
40
|
}
|
|
33
|
-
}
|
|
41
|
+
}
|
|
34
42
|
}
|
|
35
43
|
};
|
package/lib/md013.js
CHANGED
|
@@ -2,25 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorDetailIf
|
|
6
|
-
|
|
7
|
-
const {
|
|
5
|
+
const { addErrorDetailIf } = require("../helpers");
|
|
6
|
+
const { getReferenceLinkImageData } = require("./cache");
|
|
7
|
+
const { addRangeToSet, getDescendantsByType } = require("../helpers/micromark.cjs");
|
|
8
|
+
const { filterByTypesCached } = require("./cache");
|
|
8
9
|
|
|
9
10
|
const longLineRePrefix = "^.{";
|
|
10
11
|
const longLineRePostfixRelaxed = "}.*\\s.*$";
|
|
11
12
|
const longLineRePostfixStrict = "}.+$";
|
|
12
|
-
const linkOrImageOnlyLineRe = /^[es]*(?:lT?L|I)[ES]*$/;
|
|
13
13
|
const sternModeRe = /^(?:[#>\s]*\s)?\S*$/;
|
|
14
|
-
const tokenTypeMap = {
|
|
15
|
-
"em_open": "e",
|
|
16
|
-
"em_close": "E",
|
|
17
|
-
"image": "I",
|
|
18
|
-
"link_open": "l",
|
|
19
|
-
"link_close": "L",
|
|
20
|
-
"strong_open": "s",
|
|
21
|
-
"strong_close": "S",
|
|
22
|
-
"text": "T"
|
|
23
|
-
};
|
|
24
14
|
|
|
25
15
|
// eslint-disable-next-line jsdoc/valid-types
|
|
26
16
|
/** @type import("./markdownlint").Rule */
|
|
@@ -28,7 +18,7 @@ module.exports = {
|
|
|
28
18
|
"names": [ "MD013", "line-length" ],
|
|
29
19
|
"description": "Line length",
|
|
30
20
|
"tags": [ "line_length" ],
|
|
31
|
-
"parser": "
|
|
21
|
+
"parser": "micromark",
|
|
32
22
|
"function": function MD013(params, onError) {
|
|
33
23
|
const lineLength = Number(params.config.line_length || 80);
|
|
34
24
|
const headingLineLength =
|
|
@@ -51,26 +41,41 @@ module.exports = {
|
|
|
51
41
|
const includeTables = (tables === undefined) ? true : !!tables;
|
|
52
42
|
const headings = params.config.headings;
|
|
53
43
|
const includeHeadings = (headings === undefined) ? true : !!headings;
|
|
54
|
-
const headingLineNumbers =
|
|
55
|
-
|
|
56
|
-
headingLineNumbers.
|
|
57
|
-
}
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
44
|
+
const headingLineNumbers = new Set();
|
|
45
|
+
for (const heading of filterByTypesCached([ "atxHeading", "setextHeading" ])) {
|
|
46
|
+
addRangeToSet(headingLineNumbers, heading.startLine, heading.endLine);
|
|
47
|
+
}
|
|
48
|
+
const codeBlockLineNumbers = new Set();
|
|
49
|
+
for (const codeBlock of filterByTypesCached([ "codeFenced", "codeIndented" ])) {
|
|
50
|
+
addRangeToSet(codeBlockLineNumbers, codeBlock.startLine, codeBlock.endLine);
|
|
51
|
+
}
|
|
52
|
+
const tableLineNumbers = new Set();
|
|
53
|
+
for (const table of filterByTypesCached([ "table" ])) {
|
|
54
|
+
addRangeToSet(tableLineNumbers, table.startLine, table.endLine);
|
|
55
|
+
}
|
|
56
|
+
const linkLineNumbers = new Set();
|
|
57
|
+
for (const link of filterByTypesCached([ "autolink", "image", "link", "literalAutolink" ])) {
|
|
58
|
+
addRangeToSet(linkLineNumbers, link.startLine, link.endLine);
|
|
59
|
+
}
|
|
60
|
+
const paragraphDataLineNumbers = new Set();
|
|
61
|
+
for (const paragraph of filterByTypesCached([ "paragraph" ])) {
|
|
62
|
+
for (const data of getDescendantsByType(paragraph, [ "data" ])) {
|
|
63
|
+
addRangeToSet(paragraphDataLineNumbers, data.startLine, data.endLine);
|
|
65
64
|
}
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
}
|
|
66
|
+
const linkOnlyLineNumbers = new Set();
|
|
67
|
+
for (const lineNumber of linkLineNumbers) {
|
|
68
|
+
if (!paragraphDataLineNumbers.has(lineNumber)) {
|
|
69
|
+
linkOnlyLineNumbers.add(lineNumber);
|
|
68
70
|
}
|
|
69
|
-
}
|
|
70
|
-
const
|
|
71
|
-
|
|
71
|
+
}
|
|
72
|
+
const definitionLineIndices = new Set(getReferenceLinkImageData().definitionLineIndices);
|
|
73
|
+
for (let lineIndex = 0; lineIndex < params.lines.length; lineIndex++) {
|
|
74
|
+
const line = params.lines[lineIndex];
|
|
72
75
|
const lineNumber = lineIndex + 1;
|
|
73
|
-
const isHeading =
|
|
76
|
+
const isHeading = headingLineNumbers.has(lineNumber);
|
|
77
|
+
const inCode = codeBlockLineNumbers.has(lineNumber);
|
|
78
|
+
const inTable = tableLineNumbers.has(lineNumber);
|
|
74
79
|
const length = inCode ?
|
|
75
80
|
codeLineLength :
|
|
76
81
|
(isHeading ? headingLineLength : lineLength);
|
|
@@ -80,20 +85,21 @@ module.exports = {
|
|
|
80
85
|
if ((includeCodeBlocks || !inCode) &&
|
|
81
86
|
(includeTables || !inTable) &&
|
|
82
87
|
(includeHeadings || !isHeading) &&
|
|
83
|
-
!
|
|
88
|
+
!definitionLineIndices.has(lineIndex) &&
|
|
84
89
|
(strict ||
|
|
85
90
|
(!(stern && sternModeRe.test(line)) &&
|
|
86
|
-
!
|
|
91
|
+
!linkOnlyLineNumbers.has(lineNumber))) &&
|
|
87
92
|
lengthRe.test(line)) {
|
|
88
93
|
addErrorDetailIf(
|
|
89
94
|
onError,
|
|
90
95
|
lineNumber,
|
|
91
96
|
length,
|
|
92
97
|
line.length,
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
[ length + 1, line.length - length ]
|
|
98
|
+
undefined,
|
|
99
|
+
undefined,
|
|
100
|
+
[ length + 1, line.length - length ]
|
|
101
|
+
);
|
|
96
102
|
}
|
|
97
|
-
}
|
|
103
|
+
}
|
|
98
104
|
}
|
|
99
105
|
};
|
package/lib/md014.js
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorContext
|
|
5
|
+
const { addErrorContext } = require("../helpers");
|
|
6
|
+
const { filterByTypes } = require("../helpers/micromark.cjs");
|
|
7
|
+
const { filterByTypesCached } = require("./cache");
|
|
6
8
|
|
|
7
9
|
const dollarCommandRe = /^(\s*)(\$\s+)/;
|
|
8
10
|
|
|
@@ -12,46 +14,41 @@ module.exports = {
|
|
|
12
14
|
"names": [ "MD014", "commands-show-output" ],
|
|
13
15
|
"description": "Dollar signs used before commands without showing output",
|
|
14
16
|
"tags": [ "code" ],
|
|
15
|
-
"parser": "
|
|
17
|
+
"parser": "micromark",
|
|
16
18
|
"function": function MD014(params, onError) {
|
|
17
|
-
for (const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
19
|
+
for (const codeBlock of filterByTypesCached([ "codeFenced", "codeIndented" ])) {
|
|
20
|
+
const codeFlowValues = filterByTypes(
|
|
21
|
+
codeBlock.children,
|
|
22
|
+
[ "codeFlowValue" ]
|
|
23
|
+
);
|
|
24
|
+
const dollarMatches = codeFlowValues.
|
|
25
|
+
map((codeFlowValue) => ({
|
|
26
|
+
"result": codeFlowValue.text.match(dollarCommandRe),
|
|
27
|
+
"startColumn": codeFlowValue.startColumn,
|
|
28
|
+
"startLine": codeFlowValue.startLine,
|
|
29
|
+
"text": codeFlowValue.text
|
|
30
|
+
})).
|
|
31
|
+
filter((dollarMatch) => dollarMatch.result);
|
|
32
|
+
if (dollarMatches.length === codeFlowValues.length) {
|
|
33
|
+
for (const dollarMatch of dollarMatches) {
|
|
34
|
+
// @ts-ignore
|
|
35
|
+
const column = dollarMatch.startColumn + dollarMatch.result[1].length;
|
|
36
|
+
// @ts-ignore
|
|
37
|
+
const length = dollarMatch.result[2].length;
|
|
38
|
+
addErrorContext(
|
|
39
|
+
onError,
|
|
40
|
+
dollarMatch.startLine,
|
|
41
|
+
dollarMatch.text,
|
|
42
|
+
undefined,
|
|
43
|
+
undefined,
|
|
44
|
+
[ column, length ],
|
|
45
|
+
{
|
|
46
|
+
"editColumn": column,
|
|
47
|
+
"deleteCount": length
|
|
33
48
|
}
|
|
34
|
-
|
|
49
|
+
);
|
|
35
50
|
}
|
|
36
|
-
|
|
37
|
-
for (const instance of dollarInstances) {
|
|
38
|
-
const [ i, lineTrim, column, length ] = instance;
|
|
39
|
-
addErrorContext(
|
|
40
|
-
onError,
|
|
41
|
-
// @ts-ignore
|
|
42
|
-
i + 1,
|
|
43
|
-
lineTrim,
|
|
44
|
-
null,
|
|
45
|
-
null,
|
|
46
|
-
[ column, length ],
|
|
47
|
-
{
|
|
48
|
-
"editColumn": column,
|
|
49
|
-
"deleteCount": length
|
|
50
|
-
}
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
});
|
|
51
|
+
}
|
|
55
52
|
}
|
|
56
53
|
}
|
|
57
54
|
};
|
package/lib/md018.js
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorContext
|
|
6
|
-
const {
|
|
5
|
+
const { addErrorContext } = require("../helpers");
|
|
6
|
+
const { addRangeToSet } = require("../helpers/micromark.cjs");
|
|
7
|
+
const { filterByTypesCached } = require("./cache");
|
|
7
8
|
|
|
8
9
|
// eslint-disable-next-line jsdoc/valid-types
|
|
9
10
|
/** @type import("./markdownlint").Rule */
|
|
@@ -11,21 +12,28 @@ module.exports = {
|
|
|
11
12
|
"names": [ "MD018", "no-missing-space-atx" ],
|
|
12
13
|
"description": "No space after hash on atx style heading",
|
|
13
14
|
"tags": [ "headings", "atx", "spaces" ],
|
|
14
|
-
"parser": "
|
|
15
|
+
"parser": "micromark",
|
|
15
16
|
"function": function MD018(params, onError) {
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
const { lines } = params;
|
|
18
|
+
const ignoreBlockLineNumbers = new Set();
|
|
19
|
+
for (const ignoreBlock of filterByTypesCached([ "codeFenced", "codeIndented", "htmlFlow" ])) {
|
|
20
|
+
addRangeToSet(ignoreBlockLineNumbers, ignoreBlock.startLine, ignoreBlock.endLine);
|
|
21
|
+
}
|
|
22
|
+
for (const [ lineIndex, line ] of lines.entries()) {
|
|
23
|
+
if (
|
|
24
|
+
!ignoreBlockLineNumbers.has(lineIndex + 1) &&
|
|
18
25
|
/^#+[^# \t]/.test(line) &&
|
|
19
26
|
!/#\s*$/.test(line) &&
|
|
20
|
-
!line.startsWith("#️⃣")
|
|
27
|
+
!line.startsWith("#️⃣")
|
|
28
|
+
) {
|
|
21
29
|
// @ts-ignore
|
|
22
30
|
const hashCount = /^#+/.exec(line)[0].length;
|
|
23
31
|
addErrorContext(
|
|
24
32
|
onError,
|
|
25
33
|
lineIndex + 1,
|
|
26
34
|
line.trim(),
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
undefined,
|
|
36
|
+
undefined,
|
|
29
37
|
[ 1, hashCount + 1 ],
|
|
30
38
|
{
|
|
31
39
|
"editColumn": hashCount + 1,
|
|
@@ -33,6 +41,6 @@ module.exports = {
|
|
|
33
41
|
}
|
|
34
42
|
);
|
|
35
43
|
}
|
|
36
|
-
}
|
|
44
|
+
}
|
|
37
45
|
}
|
|
38
46
|
};
|