markdownlint 0.21.0 → 0.23.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/CONTRIBUTING.md +1 -0
- package/LICENSE +1 -1
- package/README.md +106 -70
- package/demo/markdownlint-browser.js +1037 -1600
- package/doc/Rules.md +106 -76
- package/helpers/LICENSE +1 -1
- package/helpers/helpers.js +83 -33
- package/helpers/package.json +1 -1
- package/lib/markdownlint.d.ts +11 -5
- package/lib/markdownlint.js +102 -38
- package/lib/md002.js +1 -1
- package/lib/md004.js +46 -13
- package/lib/md006.js +1 -1
- package/lib/md009.js +25 -23
- package/lib/md011.js +10 -6
- package/lib/md018.js +1 -1
- package/lib/md019.js +1 -1
- package/lib/md020.js +1 -1
- package/lib/md021.js +1 -1
- package/lib/md023.js +1 -1
- package/lib/md025.js +1 -1
- package/lib/md026.js +7 -4
- package/lib/md028.js +1 -9
- package/lib/md031.js +6 -5
- package/lib/md032.js +2 -2
- package/lib/md037.js +22 -8
- package/lib/md039.js +2 -2
- package/lib/md041.js +14 -3
- package/lib/md043.js +22 -11
- package/lib/rules.js +2 -1
- package/package.json +32 -33
- package/schema/.markdownlint.jsonc +250 -0
- package/schema/.markdownlint.yaml +225 -0
- package/schema/markdownlint-config-schema.json +23 -20
- package/schema/build-config-schema.js +0 -410
package/lib/md004.js
CHANGED
|
@@ -2,10 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorDetailIf, listItemMarkerRe,
|
|
6
|
-
|
|
5
|
+
const { addErrorDetailIf, listItemMarkerRe, unorderedListStyleFor } =
|
|
6
|
+
require("../helpers");
|
|
7
7
|
const { flattenedLists } = require("./cache");
|
|
8
8
|
|
|
9
|
+
const expectedStyleToMarker = {
|
|
10
|
+
"dash": "-",
|
|
11
|
+
"plus": "+",
|
|
12
|
+
"asterisk": "*"
|
|
13
|
+
};
|
|
14
|
+
const differentItemStyle = {
|
|
15
|
+
"dash": "plus",
|
|
16
|
+
"plus": "asterisk",
|
|
17
|
+
"asterisk": "dash"
|
|
18
|
+
};
|
|
19
|
+
const validStyles = Object.keys(expectedStyleToMarker);
|
|
20
|
+
|
|
9
21
|
module.exports = {
|
|
10
22
|
"names": [ "MD004", "ul-style" ],
|
|
11
23
|
"description": "Unordered list style",
|
|
@@ -23,19 +35,40 @@ module.exports = {
|
|
|
23
35
|
const itemStyle = unorderedListStyleFor(item);
|
|
24
36
|
if (style === "sublist") {
|
|
25
37
|
const nesting = list.nesting;
|
|
26
|
-
if (!nestingStyles[nesting]
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
nestingStyles[nesting], itemStyle, null, null,
|
|
32
|
-
rangeFromRegExp(item.line, listItemMarkerRe));
|
|
38
|
+
if (!nestingStyles[nesting]) {
|
|
39
|
+
nestingStyles[nesting] =
|
|
40
|
+
(itemStyle === nestingStyles[nesting - 1]) ?
|
|
41
|
+
differentItemStyle[itemStyle] :
|
|
42
|
+
itemStyle;
|
|
33
43
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
44
|
+
expectedStyle = nestingStyles[nesting];
|
|
45
|
+
}
|
|
46
|
+
if (!validStyles.includes(expectedStyle)) {
|
|
47
|
+
expectedStyle = validStyles[0];
|
|
48
|
+
}
|
|
49
|
+
let range = null;
|
|
50
|
+
let fixInfo = null;
|
|
51
|
+
const match = item.line.match(listItemMarkerRe);
|
|
52
|
+
if (match) {
|
|
53
|
+
const column = match.index + 1;
|
|
54
|
+
const length = match[0].length;
|
|
55
|
+
range = [ column, length ];
|
|
56
|
+
fixInfo = {
|
|
57
|
+
"editColumn": match[1].length + 1,
|
|
58
|
+
"deleteCount": 1,
|
|
59
|
+
"insertText": expectedStyleToMarker[expectedStyle]
|
|
60
|
+
};
|
|
38
61
|
}
|
|
62
|
+
addErrorDetailIf(
|
|
63
|
+
onError,
|
|
64
|
+
item.lineNumber,
|
|
65
|
+
expectedStyle,
|
|
66
|
+
itemStyle,
|
|
67
|
+
null,
|
|
68
|
+
null,
|
|
69
|
+
range,
|
|
70
|
+
fixInfo
|
|
71
|
+
);
|
|
39
72
|
});
|
|
40
73
|
}
|
|
41
74
|
});
|
package/lib/md006.js
CHANGED
package/lib/md009.js
CHANGED
|
@@ -47,30 +47,32 @@ module.exports = {
|
|
|
47
47
|
codeInlineLineNumbers.sort(numericSortAscending);
|
|
48
48
|
}
|
|
49
49
|
const expected = (brSpaces < 2) ? 0 : brSpaces;
|
|
50
|
-
|
|
51
|
-
forEachLine(lineMetadata(), (line, lineIndex, inCode, onFence) => {
|
|
52
|
-
inFencedCode += onFence;
|
|
50
|
+
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
|
53
51
|
const lineNumber = lineIndex + 1;
|
|
54
|
-
const trailingSpaces = line.length - line.
|
|
55
|
-
if (
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
52
|
+
const trailingSpaces = line.length - line.trimEnd().length;
|
|
53
|
+
if (
|
|
54
|
+
trailingSpaces &&
|
|
55
|
+
!inCode &&
|
|
56
|
+
!includesSorted(listItemLineNumbers, lineNumber) &&
|
|
57
|
+
(
|
|
58
|
+
(expected !== trailingSpaces) ||
|
|
59
|
+
(strict &&
|
|
60
|
+
(!includesSorted(paragraphLineNumbers, lineNumber) ||
|
|
61
|
+
includesSorted(codeInlineLineNumbers, lineNumber)))
|
|
62
|
+
)
|
|
63
|
+
) {
|
|
64
|
+
const column = line.length - trailingSpaces + 1;
|
|
65
|
+
addError(
|
|
66
|
+
onError,
|
|
67
|
+
lineNumber,
|
|
68
|
+
"Expected: " + (expected === 0 ? "" : "0 or ") +
|
|
69
|
+
expected + "; Actual: " + trailingSpaces,
|
|
70
|
+
null,
|
|
71
|
+
[ column, trailingSpaces ],
|
|
72
|
+
{
|
|
73
|
+
"editColumn": column,
|
|
74
|
+
"deleteCount": trailingSpaces
|
|
75
|
+
});
|
|
74
76
|
}
|
|
75
77
|
});
|
|
76
78
|
}
|
package/lib/md011.js
CHANGED
|
@@ -20,17 +20,21 @@ module.exports = {
|
|
|
20
20
|
const line = params.lines[lineNumber - 1];
|
|
21
21
|
const column = unescapeMarkdown(line).indexOf(reversedLink) + 1;
|
|
22
22
|
const length = reversedLink.length;
|
|
23
|
+
const range = column ? [ column, length ] : null;
|
|
24
|
+
const fixInfo = column ?
|
|
25
|
+
{
|
|
26
|
+
"editColumn": column,
|
|
27
|
+
"deleteCount": length,
|
|
28
|
+
"insertText": `[${linkText}](${linkDestination})`
|
|
29
|
+
} :
|
|
30
|
+
null;
|
|
23
31
|
addError(
|
|
24
32
|
onError,
|
|
25
33
|
lineNumber,
|
|
26
34
|
reversedLink,
|
|
27
35
|
null,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"editColumn": column,
|
|
31
|
-
"deleteCount": length,
|
|
32
|
-
"insertText": `[${linkText}](${linkDestination})`
|
|
33
|
-
}
|
|
36
|
+
range,
|
|
37
|
+
fixInfo
|
|
34
38
|
);
|
|
35
39
|
}
|
|
36
40
|
});
|
package/lib/md018.js
CHANGED
|
@@ -12,7 +12,7 @@ module.exports = {
|
|
|
12
12
|
"function": function MD018(params, onError) {
|
|
13
13
|
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
|
14
14
|
if (!inCode &&
|
|
15
|
-
/^#+[
|
|
15
|
+
/^#+[^# \t]/.test(line) &&
|
|
16
16
|
!/#\s*$/.test(line) &&
|
|
17
17
|
!line.startsWith("#️⃣")) {
|
|
18
18
|
const hashCount = /^#+/.exec(line)[0].length;
|
package/lib/md019.js
CHANGED
|
@@ -13,7 +13,7 @@ module.exports = {
|
|
|
13
13
|
filterTokens(params, "heading_open", (token) => {
|
|
14
14
|
if (headingStyleFor(token) === "atx") {
|
|
15
15
|
const { line, lineNumber } = token;
|
|
16
|
-
const match = /^(#+)(\
|
|
16
|
+
const match = /^(#+)([ \t]{2,})(?:\S)/.exec(line);
|
|
17
17
|
if (match) {
|
|
18
18
|
const [
|
|
19
19
|
,
|
package/lib/md020.js
CHANGED
|
@@ -13,7 +13,7 @@ module.exports = {
|
|
|
13
13
|
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
|
14
14
|
if (!inCode) {
|
|
15
15
|
const match =
|
|
16
|
-
/^(#+)(\
|
|
16
|
+
/^(#+)([ \t]*)([^#]*?[^#\\])([ \t]*)((?:\\#)?)(#+)(\s*)$/.exec(line);
|
|
17
17
|
if (match) {
|
|
18
18
|
const [
|
|
19
19
|
,
|
package/lib/md021.js
CHANGED
|
@@ -13,7 +13,7 @@ module.exports = {
|
|
|
13
13
|
filterTokens(params, "heading_open", (token) => {
|
|
14
14
|
if (headingStyleFor(token) === "atx_closed") {
|
|
15
15
|
const { line, lineNumber } = token;
|
|
16
|
-
const match = /^(#+)(\
|
|
16
|
+
const match = /^(#+)([ \t]+)([^#]+?)([ \t]+)(#+)(\s*)$/.exec(line);
|
|
17
17
|
if (match) {
|
|
18
18
|
const [
|
|
19
19
|
,
|
package/lib/md023.js
CHANGED
|
@@ -17,7 +17,7 @@ module.exports = {
|
|
|
17
17
|
if (match) {
|
|
18
18
|
const [ prefixAndFirstChar, prefix ] = match;
|
|
19
19
|
let deleteCount = prefix.length;
|
|
20
|
-
const prefixLengthNoSpace = prefix.
|
|
20
|
+
const prefixLengthNoSpace = prefix.trimEnd().length;
|
|
21
21
|
if (prefixLengthNoSpace) {
|
|
22
22
|
deleteCount -= prefixLengthNoSpace - 1;
|
|
23
23
|
}
|
package/lib/md025.js
CHANGED
|
@@ -7,7 +7,7 @@ const { addErrorContext, filterTokens, frontMatterHasTitle } =
|
|
|
7
7
|
|
|
8
8
|
module.exports = {
|
|
9
9
|
"names": [ "MD025", "single-title", "single-h1" ],
|
|
10
|
-
"description": "Multiple top
|
|
10
|
+
"description": "Multiple top-level headings in the same document",
|
|
11
11
|
"tags": [ "headings", "headers" ],
|
|
12
12
|
"function": function MD025(params, onError) {
|
|
13
13
|
const level = Number(params.config.level || 1);
|
package/lib/md026.js
CHANGED
|
@@ -2,24 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addError,
|
|
5
|
+
const { addError, allPunctuationNoQuestion, escapeForRegExp, forEachHeading } =
|
|
6
6
|
require("../helpers");
|
|
7
7
|
|
|
8
|
+
const endOfLineHtmlEntityRe = /&#?[0-9a-zA-Z]+;$/;
|
|
9
|
+
|
|
8
10
|
module.exports = {
|
|
9
11
|
"names": [ "MD026", "no-trailing-punctuation" ],
|
|
10
12
|
"description": "Trailing punctuation in heading",
|
|
11
13
|
"tags": [ "headings", "headers" ],
|
|
12
14
|
"function": function MD026(params, onError) {
|
|
13
15
|
let punctuation = params.config.punctuation;
|
|
14
|
-
punctuation =
|
|
15
|
-
|
|
16
|
+
punctuation = String(
|
|
17
|
+
(punctuation === undefined) ? allPunctuationNoQuestion : punctuation
|
|
18
|
+
);
|
|
16
19
|
const trailingPunctuationRe =
|
|
17
20
|
new RegExp("\\s*[" + escapeForRegExp(punctuation) + "]+$");
|
|
18
21
|
forEachHeading(params, (heading) => {
|
|
19
22
|
const { line, lineNumber } = heading;
|
|
20
23
|
const trimmedLine = line.replace(/[\s#]*$/, "");
|
|
21
24
|
const match = trailingPunctuationRe.exec(trimmedLine);
|
|
22
|
-
if (match) {
|
|
25
|
+
if (match && !endOfLineHtmlEntityRe.test(trimmedLine)) {
|
|
23
26
|
const fullMatch = match[0];
|
|
24
27
|
const column = match.index + 1;
|
|
25
28
|
const length = fullMatch.length;
|
package/lib/md028.js
CHANGED
|
@@ -18,15 +18,7 @@ module.exports = {
|
|
|
18
18
|
let lineNumber = prevLineNumber;
|
|
19
19
|
lineNumber < token.lineNumber;
|
|
20
20
|
lineNumber++) {
|
|
21
|
-
addError(
|
|
22
|
-
onError,
|
|
23
|
-
lineNumber,
|
|
24
|
-
null,
|
|
25
|
-
null,
|
|
26
|
-
null,
|
|
27
|
-
{
|
|
28
|
-
"deleteCount": -1
|
|
29
|
-
});
|
|
21
|
+
addError(onError, lineNumber);
|
|
30
22
|
}
|
|
31
23
|
}
|
|
32
24
|
prevToken = token;
|
package/lib/md031.js
CHANGED
|
@@ -21,7 +21,11 @@ module.exports = {
|
|
|
21
21
|
if ((includeListItems || !inItem) &&
|
|
22
22
|
((onTopFence && !isBlankLine(lines[i - 1])) ||
|
|
23
23
|
(onBottomFence && !isBlankLine(lines[i + 1])))) {
|
|
24
|
-
const [ , prefix ] = line.match(codeFencePrefixRe);
|
|
24
|
+
const [ , prefix ] = line.match(codeFencePrefixRe) || [];
|
|
25
|
+
const fixInfo = (prefix === undefined) ? null : {
|
|
26
|
+
"lineNumber": i + (onTopFence ? 1 : 2),
|
|
27
|
+
"insertText": `${prefix}\n`
|
|
28
|
+
};
|
|
25
29
|
addErrorContext(
|
|
26
30
|
onError,
|
|
27
31
|
i + 1,
|
|
@@ -29,10 +33,7 @@ module.exports = {
|
|
|
29
33
|
null,
|
|
30
34
|
null,
|
|
31
35
|
null,
|
|
32
|
-
|
|
33
|
-
"lineNumber": i + (onTopFence ? 1 : 2),
|
|
34
|
-
"insertText": `${prefix}\n`
|
|
35
|
-
});
|
|
36
|
+
fixInfo);
|
|
36
37
|
}
|
|
37
38
|
});
|
|
38
39
|
}
|
package/lib/md032.js
CHANGED
|
@@ -17,7 +17,7 @@ module.exports = {
|
|
|
17
17
|
const firstIndex = list.open.map[0];
|
|
18
18
|
if (!isBlankLine(lines[firstIndex - 1])) {
|
|
19
19
|
const line = lines[firstIndex];
|
|
20
|
-
const quotePrefix = line.match(quotePrefixRe)[0].
|
|
20
|
+
const quotePrefix = line.match(quotePrefixRe)[0].trimEnd();
|
|
21
21
|
addErrorContext(
|
|
22
22
|
onError,
|
|
23
23
|
firstIndex + 1,
|
|
@@ -32,7 +32,7 @@ module.exports = {
|
|
|
32
32
|
const lastIndex = list.lastLineIndex - 1;
|
|
33
33
|
if (!isBlankLine(lines[lastIndex + 1])) {
|
|
34
34
|
const line = lines[lastIndex];
|
|
35
|
-
const quotePrefix = line.match(quotePrefixRe)[0].
|
|
35
|
+
const quotePrefix = line.match(quotePrefixRe)[0].trimEnd();
|
|
36
36
|
addErrorContext(
|
|
37
37
|
onError,
|
|
38
38
|
lastIndex + 1,
|
package/lib/md037.js
CHANGED
|
@@ -10,6 +10,7 @@ const emphasisRe = /(^|[^\\]|\\\\)(?:(\*\*?\*?)|(__?_?))/g;
|
|
|
10
10
|
const asteriskListItemMarkerRe = /^([\s>]*)\*(\s+)/;
|
|
11
11
|
const leftSpaceRe = /^\s+/;
|
|
12
12
|
const rightSpaceRe = /\s+$/;
|
|
13
|
+
const tablePipeRe = /\|/;
|
|
13
14
|
|
|
14
15
|
module.exports = {
|
|
15
16
|
"names": [ "MD037", "no-space-in-emphasis" ],
|
|
@@ -28,18 +29,23 @@ module.exports = {
|
|
|
28
29
|
pendingError = null;
|
|
29
30
|
}
|
|
30
31
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
31
|
-
function handleRunEnd(
|
|
32
|
+
function handleRunEnd(
|
|
33
|
+
line, lineIndex, contextLength, match, matchIndex, inTable
|
|
34
|
+
) {
|
|
32
35
|
// Close current run
|
|
33
36
|
let content = line.substring(emphasisIndex, matchIndex);
|
|
34
37
|
if (!emphasisLength) {
|
|
35
|
-
content = content.
|
|
38
|
+
content = content.trimStart();
|
|
36
39
|
}
|
|
37
40
|
if (!match) {
|
|
38
|
-
content = content.
|
|
41
|
+
content = content.trimEnd();
|
|
39
42
|
}
|
|
40
43
|
const leftSpace = leftSpaceRe.test(content);
|
|
41
44
|
const rightSpace = rightSpaceRe.test(content);
|
|
42
|
-
if (
|
|
45
|
+
if (
|
|
46
|
+
(leftSpace || rightSpace) &&
|
|
47
|
+
(!inTable || !tablePipeRe.test(content))
|
|
48
|
+
) {
|
|
43
49
|
// Report the violation
|
|
44
50
|
const contextStart = emphasisIndex - emphasisLength;
|
|
45
51
|
const contextEnd = matchIndex + contextLength;
|
|
@@ -70,13 +76,13 @@ module.exports = {
|
|
|
70
76
|
resetRunTracking();
|
|
71
77
|
forEachLine(
|
|
72
78
|
lineMetadata(),
|
|
73
|
-
(line, lineIndex, inCode, onFence, inTable, inItem, onBreak) => {
|
|
79
|
+
(line, lineIndex, inCode, onFence, inTable, inItem, onBreak, inMath) => {
|
|
74
80
|
const onItemStart = (inItem === 1);
|
|
75
81
|
if (inCode || inTable || onBreak || onItemStart || isBlankLine(line)) {
|
|
76
82
|
// Emphasis resets when leaving a block
|
|
77
83
|
resetRunTracking();
|
|
78
84
|
}
|
|
79
|
-
if (inCode || onBreak) {
|
|
85
|
+
if (inCode || onBreak || inMath) {
|
|
80
86
|
// Emphasis has no meaning here
|
|
81
87
|
return;
|
|
82
88
|
}
|
|
@@ -106,12 +112,20 @@ module.exports = {
|
|
|
106
112
|
if (matchLength === effectiveEmphasisLength) {
|
|
107
113
|
// Ending an existing run, report any pending error
|
|
108
114
|
if (pendingError) {
|
|
115
|
+
// @ts-ignore
|
|
109
116
|
addErrorContext(...pendingError);
|
|
110
117
|
pendingError = null;
|
|
111
118
|
}
|
|
112
119
|
const error = handleRunEnd(
|
|
113
|
-
line,
|
|
120
|
+
line,
|
|
121
|
+
lineIndex,
|
|
122
|
+
effectiveEmphasisLength,
|
|
123
|
+
match,
|
|
124
|
+
matchIndex,
|
|
125
|
+
inTable
|
|
126
|
+
);
|
|
114
127
|
if (error) {
|
|
128
|
+
// @ts-ignore
|
|
115
129
|
addErrorContext(...error);
|
|
116
130
|
}
|
|
117
131
|
// Reset
|
|
@@ -139,7 +153,7 @@ module.exports = {
|
|
|
139
153
|
}
|
|
140
154
|
if (emphasisIndex !== -1) {
|
|
141
155
|
pendingError = pendingError ||
|
|
142
|
-
handleRunEnd(line, lineIndex, 0, null, line.length);
|
|
156
|
+
handleRunEnd(line, lineIndex, 0, null, line.length, inTable);
|
|
143
157
|
// Adjust for pending run on new line
|
|
144
158
|
emphasisIndex = 0;
|
|
145
159
|
emphasisLength = 0;
|
package/lib/md039.js
CHANGED
|
@@ -24,8 +24,8 @@ module.exports = {
|
|
|
24
24
|
linkText = "";
|
|
25
25
|
} else if (type === "link_close") {
|
|
26
26
|
inLink = false;
|
|
27
|
-
const left = linkText.
|
|
28
|
-
const right = linkText.
|
|
27
|
+
const left = linkText.trimStart().length !== linkText.length;
|
|
28
|
+
const right = linkText.trimEnd().length !== linkText.length;
|
|
29
29
|
if (left || right) {
|
|
30
30
|
const line = params.lines[lineNumber - 1];
|
|
31
31
|
let range = null;
|
package/lib/md041.js
CHANGED
|
@@ -6,7 +6,7 @@ const { addErrorContext, frontMatterHasTitle } = require("../helpers");
|
|
|
6
6
|
|
|
7
7
|
module.exports = {
|
|
8
8
|
"names": [ "MD041", "first-line-heading", "first-line-h1" ],
|
|
9
|
-
"description": "First line in file should be a top
|
|
9
|
+
"description": "First line in a file should be a top-level heading",
|
|
10
10
|
"tags": [ "headings", "headers" ],
|
|
11
11
|
"function": function MD041(params, onError) {
|
|
12
12
|
const level = Number(params.config.level || 1);
|
|
@@ -17,11 +17,22 @@ module.exports = {
|
|
|
17
17
|
params.config.front_matter_title
|
|
18
18
|
);
|
|
19
19
|
if (!foundFrontMatterTitle) {
|
|
20
|
+
const htmlHeadingRe = new RegExp(`^<h${level}[ />]`, "i");
|
|
20
21
|
params.tokens.every((token) => {
|
|
22
|
+
let isError = false;
|
|
21
23
|
if (token.type === "html_block") {
|
|
22
|
-
|
|
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;
|
|
30
|
+
}
|
|
31
|
+
} else if ((token.type !== "heading_open") || (token.tag !== tag)) {
|
|
32
|
+
// Something other than a Markdown heading
|
|
33
|
+
isError = true;
|
|
23
34
|
}
|
|
24
|
-
if (
|
|
35
|
+
if (isError) {
|
|
25
36
|
addErrorContext(onError, token.lineNumber, token.line);
|
|
26
37
|
}
|
|
27
38
|
return false;
|
package/lib/md043.js
CHANGED
|
@@ -13,30 +13,41 @@ module.exports = {
|
|
|
13
13
|
const requiredHeadings = params.config.headings || params.config.headers;
|
|
14
14
|
if (Array.isArray(requiredHeadings)) {
|
|
15
15
|
const levels = {};
|
|
16
|
-
[ 1, 2, 3, 4, 5, 6 ].forEach(
|
|
16
|
+
[ 1, 2, 3, 4, 5, 6 ].forEach((level) => {
|
|
17
17
|
levels["h" + level] = "######".substr(-level);
|
|
18
18
|
});
|
|
19
19
|
let i = 0;
|
|
20
|
-
let
|
|
21
|
-
let
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
let matchAny = false;
|
|
21
|
+
let hasError = false;
|
|
22
|
+
let anyHeadings = false;
|
|
23
|
+
// eslint-disable-next-line func-style
|
|
24
|
+
const getExpected = () => requiredHeadings[i++] || "[None]";
|
|
25
|
+
forEachHeading(params, (heading, content) => {
|
|
26
|
+
if (!hasError) {
|
|
27
|
+
anyHeadings = true;
|
|
24
28
|
const actual = levels[heading.tag] + " " + content;
|
|
25
|
-
const expected =
|
|
29
|
+
const expected = getExpected();
|
|
26
30
|
if (expected === "*") {
|
|
27
|
-
|
|
31
|
+
matchAny = true;
|
|
32
|
+
getExpected();
|
|
33
|
+
} else if (expected === "+") {
|
|
34
|
+
matchAny = true;
|
|
28
35
|
} else if (expected.toLowerCase() === actual.toLowerCase()) {
|
|
29
|
-
|
|
30
|
-
} else if (
|
|
36
|
+
matchAny = false;
|
|
37
|
+
} else if (matchAny) {
|
|
31
38
|
i--;
|
|
32
39
|
} else {
|
|
33
40
|
addErrorDetailIf(onError, heading.lineNumber,
|
|
34
41
|
expected, actual);
|
|
35
|
-
|
|
42
|
+
hasError = true;
|
|
36
43
|
}
|
|
37
44
|
}
|
|
38
45
|
});
|
|
39
|
-
if (
|
|
46
|
+
if (
|
|
47
|
+
!hasError &&
|
|
48
|
+
(i < requiredHeadings.length) &&
|
|
49
|
+
(anyHeadings || !requiredHeadings.every((heading) => heading === "*"))
|
|
50
|
+
) {
|
|
40
51
|
addErrorContext(onError, params.lines.length,
|
|
41
52
|
requiredHeadings[i]);
|
|
42
53
|
}
|
package/lib/rules.js
CHANGED
|
@@ -54,7 +54,8 @@ const rules = [
|
|
|
54
54
|
];
|
|
55
55
|
rules.forEach((rule) => {
|
|
56
56
|
const name = rule.names[0].toLowerCase();
|
|
57
|
-
|
|
57
|
+
// eslint-disable-next-line dot-notation
|
|
58
|
+
rule["information"] =
|
|
58
59
|
new URL(`${homepage}/blob/v${version}/doc/Rules.md#${name}`);
|
|
59
60
|
});
|
|
60
61
|
module.exports = rules;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markdownlint",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.1",
|
|
4
4
|
"description": "A Node.js style checker and lint tool for Markdown/CommonMark files.",
|
|
5
5
|
"main": "lib/markdownlint.js",
|
|
6
6
|
"types": "lib/markdownlint.d.ts",
|
|
@@ -13,53 +13,55 @@
|
|
|
13
13
|
},
|
|
14
14
|
"bugs": "https://github.com/DavidAnson/markdownlint/issues",
|
|
15
15
|
"scripts": {
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"test-declaration": "cd example/typescript && tsc && node type-check.js",
|
|
19
|
-
"test-extra": "node test/markdownlint-test-extra.js",
|
|
20
|
-
"lint": "eslint --max-warnings 0 lib helpers test schema && eslint --env browser --global markdownit --global markdownlint --rule \"no-unused-vars: 0, no-extend-native: 0, max-statements: 0, no-console: 0, no-var: 0, unicorn/prefer-add-event-listener: 0, unicorn/prefer-query-selector: 0, unicorn/prefer-replace-all: 0\" demo && eslint --rule \"no-console: 0, no-invalid-this: 0, no-shadow: 0, object-property-newline: 0, node/no-missing-require: 0, node/no-extraneous-require: 0\" example",
|
|
21
|
-
"ci": "npm run test-cover && npm run lint && npm run test-declaration",
|
|
16
|
+
"build-config": "npm run build-config-schema && npm run build-config-example",
|
|
17
|
+
"build-config-example": "node schema/build-config-example.js",
|
|
22
18
|
"build-config-schema": "node schema/build-config-schema.js",
|
|
23
|
-
"build-declaration": "tsc --allowJs --declaration --
|
|
24
|
-
"build-demo": "cpy node_modules/markdown-it/dist/markdown-it.min.js demo && cd demo && rimraf markdownlint-browser.* &&
|
|
19
|
+
"build-declaration": "tsc --allowJs --declaration --emitDeclarationOnly --resolveJsonModule lib/markdownlint.js && rimraf 'lib/{c,md,r}*.d.ts' 'helpers/*.d.ts'",
|
|
20
|
+
"build-demo": "cpy node_modules/markdown-it/dist/markdown-it.min.js demo && cd demo && rimraf markdownlint-browser.* && webpack --no-stats",
|
|
25
21
|
"build-example": "npm install --no-save --ignore-scripts grunt grunt-cli gulp through2",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
22
|
+
"ci": "npm-run-all --continue-on-error --parallel test-cover lint declaration build-config build-demo && git diff --exit-code",
|
|
23
|
+
"clean-test-repos": "rimraf test-repos",
|
|
24
|
+
"clone-test-repos": "mkdir test-repos && cd test-repos && git clone https://github.com/eslint/eslint eslint-eslint --depth 1 --no-tags --quiet && git clone https://github.com/mkdocs/mkdocs mkdocs-mkdocs --depth 1 --no-tags --quiet && git clone https://github.com/pi-hole/docs pi-hole-docs --depth 1 --no-tags --quiet",
|
|
28
25
|
"clone-test-repos-large": "npm run clone-test-repos && cd test-repos && git clone https://github.com/dotnet/docs dotnet-docs --depth 1 --no-tags --quiet",
|
|
29
|
-
"
|
|
30
|
-
"
|
|
26
|
+
"declaration": "npm run build-declaration && npm run test-declaration",
|
|
27
|
+
"example": "cd example && node standalone.js && grunt markdownlint --force && gulp markdownlint",
|
|
28
|
+
"lint": "eslint --max-warnings 0 .",
|
|
29
|
+
"lint-test-repos": "ava --timeout=5m test/markdownlint-test-repos.js",
|
|
30
|
+
"test": "ava test/markdownlint-test.js test/markdownlint-test-custom-rules.js test/markdownlint-test-helpers.js test/markdownlint-test-result-object.js test/markdownlint-test-scenarios.js",
|
|
31
|
+
"test-cover": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 npm test",
|
|
32
|
+
"test-declaration": "cd example/typescript && tsc && node type-check.js",
|
|
33
|
+
"test-extra": "ava --timeout=5m test/markdownlint-test-extra.js"
|
|
31
34
|
},
|
|
32
35
|
"engines": {
|
|
33
36
|
"node": ">=10"
|
|
34
37
|
},
|
|
35
38
|
"dependencies": {
|
|
36
|
-
"markdown-it": "
|
|
39
|
+
"markdown-it": "12.0.4"
|
|
37
40
|
},
|
|
38
41
|
"devDependencies": {
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"c8": "~7.3.0",
|
|
42
|
+
"ava": "~3.15.0",
|
|
43
|
+
"c8": "~7.5.0",
|
|
42
44
|
"cpy-cli": "~3.1.1",
|
|
43
|
-
"eslint": "~7.
|
|
44
|
-
"eslint-plugin-jsdoc": "~
|
|
45
|
+
"eslint": "~7.19.0",
|
|
46
|
+
"eslint-plugin-jsdoc": "~31.6.0",
|
|
45
47
|
"eslint-plugin-node": "~11.1.0",
|
|
46
|
-
"eslint-plugin-unicorn": "~
|
|
47
|
-
"globby": "~11.0.
|
|
48
|
-
"js-yaml": "~
|
|
49
|
-
"make-dir-cli": "~2.0.0",
|
|
48
|
+
"eslint-plugin-unicorn": "~27.0.0",
|
|
49
|
+
"globby": "~11.0.2",
|
|
50
|
+
"js-yaml": "~4.0.0",
|
|
50
51
|
"markdown-it-for-inline": "~0.1.1",
|
|
51
|
-
"@iktakahiro/markdown-it-katex": "~4.0.0",
|
|
52
52
|
"markdown-it-sub": "~1.0.0",
|
|
53
53
|
"markdown-it-sup": "~1.0.0",
|
|
54
|
-
"
|
|
54
|
+
"markdown-it-texmath": "~0.8.0",
|
|
55
|
+
"markdownlint-rule-helpers": "~0.13.0",
|
|
56
|
+
"npm-run-all": "~4.1.5",
|
|
55
57
|
"rimraf": "~3.0.2",
|
|
56
58
|
"strip-json-comments": "~3.1.1",
|
|
57
|
-
"tape": "~5.0.1",
|
|
58
|
-
"tape-player": "~0.1.1",
|
|
59
59
|
"toml": "~3.0.0",
|
|
60
|
+
"ts-loader": "~8.0.15",
|
|
60
61
|
"tv4": "~1.3.0",
|
|
61
|
-
"typescript": "~4.
|
|
62
|
-
"
|
|
62
|
+
"typescript": "~4.1.3",
|
|
63
|
+
"webpack": "~5.21.1",
|
|
64
|
+
"webpack-cli": "~4.5.0"
|
|
63
65
|
},
|
|
64
66
|
"keywords": [
|
|
65
67
|
"markdown",
|
|
@@ -67,8 +69,5 @@
|
|
|
67
69
|
"md",
|
|
68
70
|
"CommonMark",
|
|
69
71
|
"markdownlint"
|
|
70
|
-
]
|
|
71
|
-
"browser": {
|
|
72
|
-
"markdown-it": "../demo/markdown-it-stub.js"
|
|
73
|
-
}
|
|
72
|
+
]
|
|
74
73
|
}
|