markdownlint 0.32.1 → 0.34.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 +18 -0
- package/CONTRIBUTING.md +4 -3
- package/README.md +6 -0
- package/demo/markdownlint-browser.js +3866 -3564
- package/doc/CustomRules.md +14 -7
- package/doc/Rules.md +139 -12
- package/doc/md013.md +8 -7
- package/doc/md024.md +2 -5
- package/doc/md049.md +3 -0
- package/doc/md050.md +3 -0
- package/doc/md051.md +26 -0
- package/doc/md055.md +54 -0
- package/doc/md056.md +37 -0
- package/helpers/README.md +5 -3
- package/helpers/helpers.js +5 -5
- package/helpers/micromark.cjs +46 -27
- package/helpers/package.json +2 -2
- package/lib/configuration.d.ts +136 -110
- package/lib/constants.js +1 -1
- package/lib/markdownlint.d.ts +79 -6
- package/lib/markdownlint.js +95 -21
- package/lib/md001.js +3 -0
- package/lib/md003.js +3 -0
- package/lib/md004.js +3 -0
- package/lib/md005.js +12 -4
- package/lib/md007.js +17 -11
- package/lib/md009.js +3 -0
- package/lib/md010.js +4 -1
- package/lib/md011.js +3 -0
- package/lib/md012.js +3 -0
- package/lib/md013.js +3 -0
- package/lib/md014.js +4 -0
- package/lib/md018.js +4 -0
- package/lib/md019.js +3 -0
- package/lib/md020.js +3 -0
- package/lib/md021.js +3 -0
- package/lib/md022.js +10 -2
- package/lib/md023.js +3 -0
- package/lib/md024.js +11 -4
- package/lib/md025.js +3 -0
- package/lib/md026.js +11 -7
- package/lib/md027.js +29 -43
- package/lib/md028.js +31 -14
- package/lib/md029.js +3 -0
- package/lib/md030.js +9 -4
- package/lib/md031.js +3 -0
- package/lib/md032.js +12 -14
- package/lib/md033.js +9 -2
- package/lib/md034.js +31 -5
- package/lib/md035.js +9 -2
- package/lib/md036.js +33 -39
- package/lib/md037.js +10 -2
- package/lib/md038.js +27 -18
- package/lib/md039.js +4 -0
- package/lib/md040.js +26 -21
- package/lib/md041.js +21 -26
- package/lib/md042.js +4 -0
- package/lib/md043.js +3 -0
- package/lib/md044.js +9 -1
- package/lib/md045.js +10 -3
- package/lib/md046.js +14 -7
- package/lib/md047.js +5 -2
- package/lib/md048.js +26 -13
- package/lib/md049-md050.js +26 -7
- package/lib/md051.js +20 -16
- package/lib/md052.js +3 -0
- package/lib/md053.js +3 -0
- package/lib/md054.js +10 -5
- package/lib/md055.js +80 -0
- package/lib/md056.js +52 -0
- package/lib/rules.js +5 -3
- package/package.json +26 -32
- package/schema/.markdownlint.jsonc +58 -51
- package/schema/.markdownlint.yaml +56 -50
- package/schema/ValidatingConfiguration.md +28 -0
- package/schema/markdownlint-config-schema.json +165 -113
package/lib/md037.js
CHANGED
|
@@ -5,20 +5,28 @@
|
|
|
5
5
|
const { addError } = require("../helpers");
|
|
6
6
|
const { filterByPredicate, inHtmlFlow } = require("../helpers/micromark.cjs");
|
|
7
7
|
|
|
8
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
9
|
+
/** @type import("./markdownlint").Rule */
|
|
8
10
|
module.exports = {
|
|
9
11
|
"names": [ "MD037", "no-space-in-emphasis" ],
|
|
10
12
|
"description": "Spaces inside emphasis markers",
|
|
11
13
|
"tags": [ "whitespace", "emphasis" ],
|
|
14
|
+
"parser": "micromark",
|
|
12
15
|
"function": function MD037(params, onError) {
|
|
13
16
|
|
|
14
17
|
// Initialize variables
|
|
15
|
-
|
|
18
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
19
|
+
/** @type import("../helpers/micromark.cjs").Token[] */
|
|
20
|
+
const micromarkTokens =
|
|
21
|
+
// @ts-ignore
|
|
22
|
+
params.parsers.micromark.tokens;
|
|
23
|
+
const { lines } = params;
|
|
16
24
|
const emphasisTokensByMarker = new Map();
|
|
17
25
|
for (const marker of [ "_", "__", "___", "*", "**", "***" ]) {
|
|
18
26
|
emphasisTokensByMarker.set(marker, []);
|
|
19
27
|
}
|
|
20
28
|
const tokens = filterByPredicate(
|
|
21
|
-
|
|
29
|
+
micromarkTokens,
|
|
22
30
|
(token) => token.children.some((child) => child.type === "data")
|
|
23
31
|
);
|
|
24
32
|
for (const token of tokens) {
|
package/lib/md038.js
CHANGED
|
@@ -19,14 +19,21 @@ const trimCodeText = (text, start, end) => {
|
|
|
19
19
|
return text;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
23
|
+
/** @type import("./markdownlint").Rule */
|
|
22
24
|
module.exports = {
|
|
23
25
|
"names": [ "MD038", "no-space-in-code" ],
|
|
24
26
|
"description": "Spaces inside code span elements",
|
|
25
27
|
"tags": [ "whitespace", "code" ],
|
|
28
|
+
"parser": "micromark",
|
|
26
29
|
"function": function MD038(params, onError) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
31
|
+
/** @type import("../helpers/micromark.cjs").Token[] */
|
|
32
|
+
const micromarkTokens =
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
params.parsers.micromark.tokens;
|
|
35
|
+
const codeTexts = filterByTypes(micromarkTokens, [ "codeText" ])
|
|
36
|
+
.filter((codeText) => !inHtmlFlow(codeText));
|
|
30
37
|
for (const codeText of codeTexts) {
|
|
31
38
|
const { children } = codeText;
|
|
32
39
|
const first = 0;
|
|
@@ -41,7 +48,7 @@ module.exports = {
|
|
|
41
48
|
tokenIfType(children[last - 2], "codeTextData");
|
|
42
49
|
if (startSequence && endSequence && startData && endData) {
|
|
43
50
|
const spaceLeft = leftSpaceRe.test(startData.text);
|
|
44
|
-
const spaceRight =
|
|
51
|
+
const spaceRight = rightSpaceRe.test(endData.text);
|
|
45
52
|
if (spaceLeft || spaceRight) {
|
|
46
53
|
let lineNumber = startSequence.startLine;
|
|
47
54
|
let range = null;
|
|
@@ -56,7 +63,7 @@ module.exports = {
|
|
|
56
63
|
"deleteCount": endSequence.startColumn - startSequence.endColumn,
|
|
57
64
|
"insertText": trimCodeText(startData.text, true, true)
|
|
58
65
|
};
|
|
59
|
-
} else if (spaceLeft) {
|
|
66
|
+
} else if (spaceLeft && (startSequence.endLine === startData.startLine)) {
|
|
60
67
|
range = [
|
|
61
68
|
startSequence.startColumn,
|
|
62
69
|
startData.endColumn - startSequence.startColumn
|
|
@@ -66,7 +73,7 @@ module.exports = {
|
|
|
66
73
|
"deleteCount": startData.endColumn - startData.startColumn,
|
|
67
74
|
"insertText": trimCodeText(startData.text, true, false)
|
|
68
75
|
};
|
|
69
|
-
} else {
|
|
76
|
+
} else if (spaceRight && (endData.text.trim().length > 0)) {
|
|
70
77
|
lineNumber = endSequence.endLine;
|
|
71
78
|
range = [
|
|
72
79
|
endData.startColumn,
|
|
@@ -78,18 +85,20 @@ module.exports = {
|
|
|
78
85
|
"insertText": trimCodeText(endData.text, false, true)
|
|
79
86
|
};
|
|
80
87
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
if (range) {
|
|
89
|
+
const context = params
|
|
90
|
+
.lines[lineNumber - 1]
|
|
91
|
+
.substring(range[0] - 1, range[0] - 1 + range[1]);
|
|
92
|
+
addErrorContext(
|
|
93
|
+
onError,
|
|
94
|
+
lineNumber,
|
|
95
|
+
context,
|
|
96
|
+
spaceLeft,
|
|
97
|
+
spaceRight,
|
|
98
|
+
range,
|
|
99
|
+
fixInfo
|
|
100
|
+
);
|
|
101
|
+
}
|
|
93
102
|
}
|
|
94
103
|
}
|
|
95
104
|
}
|
package/lib/md039.js
CHANGED
|
@@ -7,10 +7,13 @@ const { addErrorContext, filterTokens } = require("../helpers");
|
|
|
7
7
|
const spaceInLinkRe =
|
|
8
8
|
/\[(?:\s[^\]]*|[^\]]*?\s)\](?=(\([^)]*\)|\[[^\]]*\]))/;
|
|
9
9
|
|
|
10
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
11
|
+
/** @type import("./markdownlint").Rule */
|
|
10
12
|
module.exports = {
|
|
11
13
|
"names": [ "MD039", "no-space-in-links" ],
|
|
12
14
|
"description": "Spaces inside link text",
|
|
13
15
|
"tags": [ "whitespace", "links" ],
|
|
16
|
+
"parser": "markdownit",
|
|
14
17
|
"function": function MD039(params, onError) {
|
|
15
18
|
filterTokens(params, "inline", (token) => {
|
|
16
19
|
const { children } = token;
|
|
@@ -33,6 +36,7 @@ module.exports = {
|
|
|
33
36
|
let fixInfo = null;
|
|
34
37
|
const match = line.slice(lineIndex).match(spaceInLinkRe);
|
|
35
38
|
if (match) {
|
|
39
|
+
// @ts-ignore
|
|
36
40
|
const column = match.index + lineIndex + 1;
|
|
37
41
|
const length = match[0].length;
|
|
38
42
|
range = [ column, length ];
|
package/lib/md040.js
CHANGED
|
@@ -2,36 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addError, addErrorContext
|
|
5
|
+
const { addError, addErrorContext } = require("../helpers");
|
|
6
|
+
const { filterByTypes, getTokenTextByType, tokenIfType } =
|
|
7
|
+
require("../helpers/micromark.cjs");
|
|
6
8
|
|
|
9
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
10
|
+
/** @type import("./markdownlint").Rule */
|
|
7
11
|
module.exports = {
|
|
8
12
|
"names": [ "MD040", "fenced-code-language" ],
|
|
9
13
|
"description": "Fenced code blocks should have a language specified",
|
|
10
14
|
"tags": [ "code", "language" ],
|
|
15
|
+
"parser": "micromark",
|
|
11
16
|
"function": function MD040(params, onError) {
|
|
12
17
|
let allowed = params.config.allowed_languages;
|
|
13
18
|
allowed = Array.isArray(allowed) ? allowed : [];
|
|
14
19
|
const languageOnly = !!params.config.language_only;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
`Info string contains more than language: "${
|
|
33
|
-
|
|
20
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
21
|
+
/** @type import("../helpers/micromark.cjs").Token[] */
|
|
22
|
+
const micromarkTokens =
|
|
23
|
+
// @ts-ignore
|
|
24
|
+
params.parsers.micromark.tokens;
|
|
25
|
+
const fencedCodes = filterByTypes(micromarkTokens, [ "codeFenced" ]);
|
|
26
|
+
for (const fencedCode of fencedCodes) {
|
|
27
|
+
const openingFence = tokenIfType(fencedCode.children[0], "codeFencedFence");
|
|
28
|
+
if (openingFence) {
|
|
29
|
+
const { children, startLine, text } = openingFence;
|
|
30
|
+
const info = getTokenTextByType(children, "codeFencedFenceInfo");
|
|
31
|
+
if (!info) {
|
|
32
|
+
addErrorContext(onError, startLine, text);
|
|
33
|
+
} else if ((allowed.length > 0) && !allowed.includes(info)) {
|
|
34
|
+
addError(onError, startLine, `"${info}" is not allowed`);
|
|
35
|
+
}
|
|
36
|
+
if (languageOnly && getTokenTextByType(children, "codeFencedFenceMeta")) {
|
|
37
|
+
addError(onError, startLine, `Info string contains more than language: "${text}"`);
|
|
38
|
+
}
|
|
34
39
|
}
|
|
35
|
-
}
|
|
40
|
+
}
|
|
36
41
|
}
|
|
37
42
|
};
|
package/lib/md041.js
CHANGED
|
@@ -3,40 +3,35 @@
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
5
|
const { addErrorContext, frontMatterHasTitle } = require("../helpers");
|
|
6
|
+
const { filterByTypes, getHeadingLevel, getHtmlTagInfo, isHtmlFlowComment, nonContentTokens } =
|
|
7
|
+
require("../helpers/micromark.cjs");
|
|
6
8
|
|
|
9
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
10
|
+
/** @type import("./markdownlint").Rule */
|
|
7
11
|
module.exports = {
|
|
8
12
|
"names": [ "MD041", "first-line-heading", "first-line-h1" ],
|
|
9
13
|
"description": "First line in a file should be a top-level heading",
|
|
10
14
|
"tags": [ "headings" ],
|
|
15
|
+
"parser": "micromark",
|
|
11
16
|
"function": function MD041(params, onError) {
|
|
12
17
|
const level = Number(params.config.level || 1);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (token.content.startsWith("<!--")) {
|
|
25
|
-
// Ignore leading HTML comments
|
|
26
|
-
return true;
|
|
27
|
-
} else if (!htmlHeadingRe.test(token.content)) {
|
|
28
|
-
// Something other than an HTML heading
|
|
29
|
-
isError = true;
|
|
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) => {
|
|
22
|
+
let isError = true;
|
|
23
|
+
if ((token.type === "atxHeading") || (token.type === "setextHeading")) {
|
|
24
|
+
isError = (getHeadingLevel(token) !== level);
|
|
25
|
+
} else if (token.type === "htmlFlow") {
|
|
26
|
+
const htmlTexts = filterByTypes(token.children, [ "htmlText" ]);
|
|
27
|
+
const tagInfo = (htmlTexts.length > 0) && getHtmlTagInfo(htmlTexts[0]);
|
|
28
|
+
isError = !tagInfo || (tagInfo.name.toLowerCase() !== `h${level}`);
|
|
30
29
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
addErrorContext(onError, token.lineNumber, token.line);
|
|
37
|
-
}
|
|
38
|
-
return false;
|
|
39
|
-
});
|
|
30
|
+
if (isError) {
|
|
31
|
+
addErrorContext(onError, token.startLine, params.lines[token.startLine - 1]);
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
});
|
|
40
35
|
}
|
|
41
36
|
}
|
|
42
37
|
};
|
package/lib/md042.js
CHANGED
|
@@ -5,10 +5,13 @@
|
|
|
5
5
|
const { addErrorContext, escapeForRegExp, filterTokens } =
|
|
6
6
|
require("../helpers");
|
|
7
7
|
|
|
8
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
9
|
+
/** @type import("./markdownlint").Rule */
|
|
8
10
|
module.exports = {
|
|
9
11
|
"names": [ "MD042", "no-empty-links" ],
|
|
10
12
|
"description": "No empty links",
|
|
11
13
|
"tags": [ "links" ],
|
|
14
|
+
"parser": "markdownit",
|
|
12
15
|
"function": function MD042(params, onError) {
|
|
13
16
|
filterTokens(params, "inline", function forToken(token) {
|
|
14
17
|
let inLink = false;
|
|
@@ -33,6 +36,7 @@ module.exports = {
|
|
|
33
36
|
);
|
|
34
37
|
if (match) {
|
|
35
38
|
context = match[0];
|
|
39
|
+
// @ts-ignore
|
|
36
40
|
range = [ match.index + 1, match[0].length ];
|
|
37
41
|
}
|
|
38
42
|
addErrorContext(
|
package/lib/md043.js
CHANGED
|
@@ -5,10 +5,13 @@
|
|
|
5
5
|
const { addErrorContext, addErrorDetailIf, forEachHeading } =
|
|
6
6
|
require("../helpers");
|
|
7
7
|
|
|
8
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
9
|
+
/** @type import("./markdownlint").Rule */
|
|
8
10
|
module.exports = {
|
|
9
11
|
"names": [ "MD043", "required-headings" ],
|
|
10
12
|
"description": "Required heading structure",
|
|
11
13
|
"tags": [ "headings" ],
|
|
14
|
+
"parser": "markdownit",
|
|
12
15
|
"function": function MD043(params, onError) {
|
|
13
16
|
const requiredHeadings = params.config.headings;
|
|
14
17
|
if (!Array.isArray(requiredHeadings)) {
|
package/lib/md044.js
CHANGED
|
@@ -11,10 +11,13 @@ const ignoredChildTypes = new Set(
|
|
|
11
11
|
[ "codeFencedFence", "definition", "reference", "resource" ]
|
|
12
12
|
);
|
|
13
13
|
|
|
14
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
15
|
+
/** @type import("./markdownlint").Rule */
|
|
14
16
|
module.exports = {
|
|
15
17
|
"names": [ "MD044", "proper-names" ],
|
|
16
18
|
"description": "Proper names should have the correct capitalization",
|
|
17
19
|
"tags": [ "spelling" ],
|
|
20
|
+
"parser": "micromark",
|
|
18
21
|
"function": function MD044(params, onError) {
|
|
19
22
|
let names = params.config.names;
|
|
20
23
|
names = Array.isArray(names) ? names : [];
|
|
@@ -29,6 +32,11 @@ module.exports = {
|
|
|
29
32
|
const htmlElements = params.config.html_elements;
|
|
30
33
|
const includeHtmlElements =
|
|
31
34
|
(htmlElements === undefined) ? true : !!htmlElements;
|
|
35
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
36
|
+
/** @type import("../helpers/micromark.cjs").Token[] */
|
|
37
|
+
const micromarkTokens =
|
|
38
|
+
// @ts-ignore
|
|
39
|
+
params.parsers.micromark.tokens;
|
|
32
40
|
const scannedTypes = new Set([ "data" ]);
|
|
33
41
|
if (includeCodeBlocks) {
|
|
34
42
|
scannedTypes.add("codeFlowValue");
|
|
@@ -40,7 +48,7 @@ module.exports = {
|
|
|
40
48
|
}
|
|
41
49
|
const contentTokens =
|
|
42
50
|
filterByPredicate(
|
|
43
|
-
|
|
51
|
+
micromarkTokens,
|
|
44
52
|
(token) => scannedTypes.has(token.type),
|
|
45
53
|
(token) => (
|
|
46
54
|
token.children.filter((t) => !ignoredChildTypes.has(t.type))
|
package/lib/md045.js
CHANGED
|
@@ -7,15 +7,22 @@ const { filterByTypes, getHtmlTagInfo } = require("../helpers/micromark.cjs");
|
|
|
7
7
|
|
|
8
8
|
const altRe = getHtmlAttributeRe("alt");
|
|
9
9
|
|
|
10
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
11
|
+
/** @type import("./markdownlint").Rule */
|
|
10
12
|
module.exports = {
|
|
11
13
|
"names": [ "MD045", "no-alt-text" ],
|
|
12
14
|
"description": "Images should have alternate text (alt text)",
|
|
13
15
|
"tags": [ "accessibility", "images" ],
|
|
16
|
+
"parser": "micromark",
|
|
14
17
|
"function": function MD045(params, onError) {
|
|
15
|
-
|
|
18
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
19
|
+
/** @type import("../helpers/micromark.cjs").Token[] */
|
|
20
|
+
const micromarkTokens =
|
|
21
|
+
// @ts-ignore
|
|
22
|
+
params.parsers.micromark.tokens;
|
|
16
23
|
|
|
17
24
|
// Process Markdown images
|
|
18
|
-
const images = filterByTypes(
|
|
25
|
+
const images = filterByTypes(micromarkTokens, [ "image" ]);
|
|
19
26
|
for (const image of images) {
|
|
20
27
|
const labelTexts = filterByTypes(image.children, [ "labelText" ]);
|
|
21
28
|
if (labelTexts.some((labelText) => labelText.text.length === 0)) {
|
|
@@ -33,7 +40,7 @@ module.exports = {
|
|
|
33
40
|
}
|
|
34
41
|
|
|
35
42
|
// Process HTML images
|
|
36
|
-
const htmlTexts = filterByTypes(
|
|
43
|
+
const htmlTexts = filterByTypes(micromarkTokens, [ "htmlText" ]);
|
|
37
44
|
for (const htmlText of htmlTexts) {
|
|
38
45
|
const { startColumn, startLine, text } = htmlText;
|
|
39
46
|
const htmlTagInfo = getHtmlTagInfo(htmlText);
|
package/lib/md046.js
CHANGED
|
@@ -3,29 +3,36 @@
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
5
|
const { addErrorDetailIf } = require("../helpers");
|
|
6
|
+
const { filterByTypes } = require("../helpers/micromark.cjs");
|
|
6
7
|
|
|
7
8
|
const tokenTypeToStyle = {
|
|
8
|
-
"
|
|
9
|
-
"
|
|
9
|
+
"codeFenced": "fenced",
|
|
10
|
+
"codeIndented": "indented"
|
|
10
11
|
};
|
|
11
12
|
|
|
13
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
14
|
+
/** @type import("./markdownlint").Rule */
|
|
12
15
|
module.exports = {
|
|
13
16
|
"names": [ "MD046", "code-block-style" ],
|
|
14
17
|
"description": "Code block style",
|
|
15
18
|
"tags": [ "code" ],
|
|
19
|
+
"parser": "micromark",
|
|
16
20
|
"function": function MD046(params, onError) {
|
|
17
21
|
let expectedStyle = String(params.config.style || "consistent");
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
23
|
+
/** @type import("../helpers/micromark.cjs").Token[] */
|
|
24
|
+
const micromarkTokens =
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
params.parsers.micromark.tokens;
|
|
27
|
+
const codeBlocksAndFences = filterByTypes(micromarkTokens, [ "codeFenced", "codeIndented" ]);
|
|
21
28
|
for (const token of codeBlocksAndFences) {
|
|
22
|
-
const {
|
|
29
|
+
const { startLine, type } = token;
|
|
23
30
|
if (expectedStyle === "consistent") {
|
|
24
31
|
expectedStyle = tokenTypeToStyle[type];
|
|
25
32
|
}
|
|
26
33
|
addErrorDetailIf(
|
|
27
34
|
onError,
|
|
28
|
-
|
|
35
|
+
startLine,
|
|
29
36
|
expectedStyle,
|
|
30
37
|
tokenTypeToStyle[type]);
|
|
31
38
|
}
|
package/lib/md047.js
CHANGED
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
const { addError, isBlankLine } = require("../helpers");
|
|
6
6
|
|
|
7
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
8
|
+
/** @type import("./markdownlint").Rule */
|
|
7
9
|
module.exports = {
|
|
8
10
|
"names": [ "MD047", "single-trailing-newline" ],
|
|
9
11
|
"description": "Files should end with a single newline character",
|
|
10
12
|
"tags": [ "blank_lines" ],
|
|
13
|
+
"parser": "none",
|
|
11
14
|
"function": function MD047(params, onError) {
|
|
12
15
|
const lastLineNumber = params.lines.length;
|
|
13
16
|
const lastLine = params.lines[lastLineNumber - 1];
|
|
@@ -15,8 +18,8 @@ module.exports = {
|
|
|
15
18
|
addError(
|
|
16
19
|
onError,
|
|
17
20
|
lastLineNumber,
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
undefined,
|
|
22
|
+
undefined,
|
|
20
23
|
[ lastLine.length, 1 ],
|
|
21
24
|
{
|
|
22
25
|
"insertText": "\n",
|
package/lib/md048.js
CHANGED
|
@@ -3,28 +3,41 @@
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
5
|
const { addErrorDetailIf, fencedCodeBlockStyleFor } = require("../helpers");
|
|
6
|
+
const { filterByTypes, tokenIfType } = require("../helpers/micromark.cjs");
|
|
6
7
|
|
|
8
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
9
|
+
/** @type import("./markdownlint").Rule */
|
|
7
10
|
module.exports = {
|
|
8
11
|
"names": [ "MD048", "code-fence-style" ],
|
|
9
12
|
"description": "Code fence style",
|
|
10
13
|
"tags": [ "code" ],
|
|
14
|
+
"parser": "micromark",
|
|
11
15
|
"function": function MD048(params, onError) {
|
|
12
16
|
const style = String(params.config.style || "consistent");
|
|
17
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
18
|
+
/** @type import("../helpers/micromark.cjs").Token[] */
|
|
19
|
+
const micromarkTokens =
|
|
20
|
+
// @ts-ignore
|
|
21
|
+
params.parsers.micromark.tokens;
|
|
13
22
|
let expectedStyle = style;
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
const codeFenceds = filterByTypes(micromarkTokens, [ "codeFenced" ]);
|
|
24
|
+
for (const codeFenced of codeFenceds) {
|
|
25
|
+
const codeFencedFence = tokenIfType(codeFenced.children[0], "codeFencedFence");
|
|
26
|
+
if (codeFencedFence) {
|
|
27
|
+
const codeFencedFenceSequence = tokenIfType(codeFencedFence.children[0], "codeFencedFenceSequence");
|
|
28
|
+
if (codeFencedFenceSequence) {
|
|
29
|
+
const { startLine, text } = codeFencedFenceSequence;
|
|
30
|
+
if (expectedStyle === "consistent") {
|
|
31
|
+
expectedStyle = fencedCodeBlockStyleFor(text);
|
|
32
|
+
}
|
|
33
|
+
addErrorDetailIf(
|
|
34
|
+
onError,
|
|
35
|
+
startLine,
|
|
36
|
+
expectedStyle,
|
|
37
|
+
fencedCodeBlockStyleFor(text)
|
|
38
|
+
);
|
|
39
|
+
}
|
|
21
40
|
}
|
|
22
|
-
addErrorDetailIf(
|
|
23
|
-
onError,
|
|
24
|
-
lineNumber,
|
|
25
|
-
expectedStyle,
|
|
26
|
-
fencedCodeBlockStyleFor(markup)
|
|
27
|
-
);
|
|
28
41
|
}
|
|
29
42
|
}
|
|
30
43
|
};
|
package/lib/md049-md050.js
CHANGED
|
@@ -5,21 +5,34 @@
|
|
|
5
5
|
const { addError, emphasisOrStrongStyleFor } = require("../helpers");
|
|
6
6
|
const { filterByPredicate, tokenIfType } = require("../helpers/micromark.cjs");
|
|
7
7
|
|
|
8
|
-
const intrawordRe =
|
|
8
|
+
const intrawordRe = /^\w$/;
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* @param {import("./markdownlint").RuleParams} params Rule parameters.
|
|
12
|
+
* @param {import("./markdownlint").RuleOnError} onError Error-reporting callback.
|
|
13
|
+
* @param {import("markdownlint-micromark").TokenType} type Token type.
|
|
14
|
+
* @param {import("markdownlint-micromark").TokenType} typeSequence Token sequence type.
|
|
15
|
+
* @param {"*" | "**"} asterisk Asterisk kind.
|
|
16
|
+
* @param {"_" | "__"} underline Underline kind.
|
|
17
|
+
* @param {"asterisk" | "consistent" | "underscore"} style Style string.
|
|
18
|
+
*/
|
|
10
19
|
const impl =
|
|
11
|
-
(params, onError, type, asterisk, underline, style = "consistent") => {
|
|
12
|
-
|
|
20
|
+
(params, onError, type, typeSequence, asterisk, underline, style = "consistent") => {
|
|
21
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
22
|
+
/** @type import("../helpers/micromark.cjs").Token[] */
|
|
23
|
+
const micromarkTokens =
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
params.parsers.micromark.tokens;
|
|
26
|
+
const { lines } = params;
|
|
13
27
|
const emphasisTokens = filterByPredicate(
|
|
14
|
-
|
|
28
|
+
micromarkTokens,
|
|
15
29
|
(token) => token.type === type,
|
|
16
30
|
(token) => ((token.type === "htmlFlow") ? [] : token.children)
|
|
17
31
|
);
|
|
18
32
|
for (const token of emphasisTokens) {
|
|
19
33
|
const { children } = token;
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const endSequence = tokenIfType(children[children.length - 1], childType);
|
|
34
|
+
const startSequence = tokenIfType(children[0], typeSequence);
|
|
35
|
+
const endSequence = tokenIfType(children[children.length - 1], typeSequence);
|
|
23
36
|
if (startSequence && endSequence) {
|
|
24
37
|
const markupStyle = emphasisOrStrongStyleFor(startSequence.text);
|
|
25
38
|
if (style === "consistent") {
|
|
@@ -55,16 +68,20 @@ const impl =
|
|
|
55
68
|
}
|
|
56
69
|
};
|
|
57
70
|
|
|
71
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
72
|
+
/** @type import("./markdownlint").Rule[] */
|
|
58
73
|
module.exports = [
|
|
59
74
|
{
|
|
60
75
|
"names": [ "MD049", "emphasis-style" ],
|
|
61
76
|
"description": "Emphasis style",
|
|
62
77
|
"tags": [ "emphasis" ],
|
|
78
|
+
"parser": "micromark",
|
|
63
79
|
"function": function MD049(params, onError) {
|
|
64
80
|
return impl(
|
|
65
81
|
params,
|
|
66
82
|
onError,
|
|
67
83
|
"emphasis",
|
|
84
|
+
"emphasisSequence",
|
|
68
85
|
"*",
|
|
69
86
|
"_",
|
|
70
87
|
params.config.style || undefined
|
|
@@ -75,11 +92,13 @@ module.exports = [
|
|
|
75
92
|
"names": [ "MD050", "strong-style" ],
|
|
76
93
|
"description": "Strong style",
|
|
77
94
|
"tags": [ "emphasis" ],
|
|
95
|
+
"parser": "micromark",
|
|
78
96
|
"function": function MD050(params, onError) {
|
|
79
97
|
return impl(
|
|
80
98
|
params,
|
|
81
99
|
onError,
|
|
82
100
|
"strong",
|
|
101
|
+
"strongSequence",
|
|
83
102
|
"**",
|
|
84
103
|
"__",
|
|
85
104
|
params.config.style || undefined
|