markdownlint 0.25.1 → 0.26.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/CONTRIBUTING.md +2 -0
- package/README.md +123 -83
- package/demo/markdownlint-browser.js +1716 -1269
- package/doc/Rules.md +133 -15
- package/helpers/helpers.js +427 -192
- package/helpers/package.json +4 -1
- package/lib/cache.js +15 -25
- package/lib/constants.js +1 -1
- package/lib/markdownlint.d.ts +21 -17
- package/lib/markdownlint.js +237 -146
- package/lib/md004.js +4 -4
- package/lib/md005.js +4 -4
- package/lib/md006.js +4 -4
- package/lib/md007.js +4 -4
- package/lib/md009.js +20 -13
- package/lib/md010.js +15 -2
- package/lib/md011.js +2 -2
- package/lib/md013.js +4 -5
- package/lib/md014.js +4 -4
- package/lib/md021.js +3 -1
- package/lib/md026.js +1 -1
- package/lib/md027.js +2 -2
- package/lib/md028.js +2 -2
- package/lib/md029.js +5 -4
- package/lib/md030.js +4 -4
- package/lib/md031.js +2 -2
- package/lib/md032.js +3 -2
- package/lib/md033.js +2 -3
- package/lib/md034.js +2 -2
- package/lib/md035.js +7 -2
- package/lib/md036.js +2 -2
- package/lib/md038.js +7 -4
- package/lib/md039.js +6 -4
- package/lib/md042.js +17 -10
- package/lib/md043.js +2 -2
- package/lib/md044.js +20 -9
- package/lib/md046.js +14 -13
- package/lib/md048.js +13 -14
- package/lib/md049-md050.js +73 -0
- package/lib/md051.js +84 -0
- package/lib/md052.js +35 -0
- package/lib/md053.js +52 -0
- package/lib/rules.js +6 -4
- package/package.json +19 -16
- package/schema/.markdownlint.jsonc +15 -2
- package/schema/.markdownlint.yaml +14 -1
- package/schema/markdownlint-config-schema.json +119 -737
- package/lib/md049.js +0 -45
- package/lib/md050.js +0 -45
package/lib/md004.js
CHANGED
|
@@ -26,12 +26,12 @@ module.exports = {
|
|
|
26
26
|
const style = String(params.config.style || "consistent");
|
|
27
27
|
let expectedStyle = style;
|
|
28
28
|
const nestingStyles = [];
|
|
29
|
-
flattenedLists()
|
|
29
|
+
for (const list of flattenedLists()) {
|
|
30
30
|
if (list.unordered) {
|
|
31
31
|
if (expectedStyle === "consistent") {
|
|
32
32
|
expectedStyle = unorderedListStyleFor(list.items[0]);
|
|
33
33
|
}
|
|
34
|
-
list.items
|
|
34
|
+
for (const item of list.items) {
|
|
35
35
|
const itemStyle = unorderedListStyleFor(item);
|
|
36
36
|
if (style === "sublist") {
|
|
37
37
|
const nesting = list.nesting;
|
|
@@ -69,8 +69,8 @@ module.exports = {
|
|
|
69
69
|
range,
|
|
70
70
|
fixInfo
|
|
71
71
|
);
|
|
72
|
-
}
|
|
72
|
+
}
|
|
73
73
|
}
|
|
74
|
-
}
|
|
74
|
+
}
|
|
75
75
|
}
|
|
76
76
|
};
|
package/lib/md005.js
CHANGED
|
@@ -11,12 +11,12 @@ module.exports = {
|
|
|
11
11
|
"description": "Inconsistent indentation for list items at the same level",
|
|
12
12
|
"tags": [ "bullet", "ul", "indentation" ],
|
|
13
13
|
"function": function MD005(params, onError) {
|
|
14
|
-
flattenedLists()
|
|
14
|
+
for (const list of flattenedLists()) {
|
|
15
15
|
const expectedIndent = list.indent;
|
|
16
16
|
let expectedEnd = 0;
|
|
17
17
|
let actualEnd = -1;
|
|
18
18
|
let endMatching = false;
|
|
19
|
-
list.items
|
|
19
|
+
for (const item of list.items) {
|
|
20
20
|
const { line, lineNumber } = item;
|
|
21
21
|
const actualIndent = indentFor(item);
|
|
22
22
|
let match = null;
|
|
@@ -63,7 +63,7 @@ module.exports = {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
68
|
}
|
|
69
69
|
};
|
package/lib/md006.js
CHANGED
|
@@ -12,9 +12,9 @@ module.exports = {
|
|
|
12
12
|
"Consider starting bulleted lists at the beginning of the line",
|
|
13
13
|
"tags": [ "bullet", "ul", "indentation" ],
|
|
14
14
|
"function": function MD006(params, onError) {
|
|
15
|
-
flattenedLists()
|
|
15
|
+
for (const list of flattenedLists()) {
|
|
16
16
|
if (list.unordered && !list.nesting && (list.indent !== 0)) {
|
|
17
|
-
list.items
|
|
17
|
+
for (const item of list.items) {
|
|
18
18
|
const { lineNumber, line } = item;
|
|
19
19
|
addErrorDetailIf(
|
|
20
20
|
onError,
|
|
@@ -27,8 +27,8 @@ module.exports = {
|
|
|
27
27
|
{
|
|
28
28
|
"deleteCount": line.length - line.trimStart().length
|
|
29
29
|
});
|
|
30
|
-
}
|
|
30
|
+
}
|
|
31
31
|
}
|
|
32
|
-
}
|
|
32
|
+
}
|
|
33
33
|
}
|
|
34
34
|
};
|
package/lib/md007.js
CHANGED
|
@@ -14,9 +14,9 @@ module.exports = {
|
|
|
14
14
|
const indent = Number(params.config.indent || 2);
|
|
15
15
|
const startIndented = !!params.config.start_indented;
|
|
16
16
|
const startIndent = Number(params.config.start_indent || indent);
|
|
17
|
-
flattenedLists()
|
|
17
|
+
for (const list of flattenedLists()) {
|
|
18
18
|
if (list.unordered && list.parentsUnordered) {
|
|
19
|
-
list.items
|
|
19
|
+
for (const item of list.items) {
|
|
20
20
|
const { lineNumber, line } = item;
|
|
21
21
|
const expectedIndent =
|
|
22
22
|
(startIndented ? startIndent : 0) +
|
|
@@ -42,8 +42,8 @@ module.exports = {
|
|
|
42
42
|
"deleteCount": actualIndent,
|
|
43
43
|
"insertText": "".padEnd(expectedIndent)
|
|
44
44
|
});
|
|
45
|
-
}
|
|
45
|
+
}
|
|
46
46
|
}
|
|
47
|
-
}
|
|
47
|
+
}
|
|
48
48
|
}
|
|
49
49
|
};
|
package/lib/md009.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addError, filterTokens,
|
|
6
|
-
|
|
5
|
+
const { addError, filterTokens, forEachLine, includesSorted,
|
|
6
|
+
numericSortAscending } = require("../helpers");
|
|
7
7
|
const { lineMetadata } = require("./cache");
|
|
8
8
|
|
|
9
9
|
module.exports = {
|
|
@@ -32,19 +32,26 @@ module.exports = {
|
|
|
32
32
|
paragraphLineNumbers.push(i + 1);
|
|
33
33
|
}
|
|
34
34
|
});
|
|
35
|
-
|
|
35
|
+
const addLineNumberRange = (start, end) => {
|
|
36
|
+
for (let i = start; i < end; i++) {
|
|
37
|
+
codeInlineLineNumbers.push(i);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
36
40
|
filterTokens(params, "inline", (token) => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
let start = 0;
|
|
42
|
+
for (const child of token.children) {
|
|
43
|
+
if (start > 0) {
|
|
44
|
+
addLineNumberRange(start, child.lineNumber);
|
|
45
|
+
start = 0;
|
|
46
|
+
}
|
|
47
|
+
if (child.type === "code_inline") {
|
|
48
|
+
start = child.lineNumber;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (start > 0) {
|
|
52
|
+
addLineNumberRange(start, token.map[1]);
|
|
45
53
|
}
|
|
46
54
|
});
|
|
47
|
-
codeInlineLineNumbers.sort(numericSortAscending);
|
|
48
55
|
}
|
|
49
56
|
const expected = (brSpaces < 2) ? 0 : brSpaces;
|
|
50
57
|
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
|
@@ -67,7 +74,7 @@ module.exports = {
|
|
|
67
74
|
lineNumber,
|
|
68
75
|
"Expected: " + (expected === 0 ? "" : "0 or ") +
|
|
69
76
|
expected + "; Actual: " + trailingSpaces,
|
|
70
|
-
|
|
77
|
+
undefined,
|
|
71
78
|
[ column, trailingSpaces ],
|
|
72
79
|
{
|
|
73
80
|
"editColumn": column,
|
package/lib/md010.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addError, forEachLine,
|
|
5
|
+
const { addError, filterTokens, forEachLine, withinAnyRange } =
|
|
6
|
+
require("../helpers");
|
|
6
7
|
const { codeBlockAndSpanRanges, lineMetadata } = require("./cache");
|
|
7
8
|
|
|
8
9
|
const tabRe = /\t+/g;
|
|
@@ -14,11 +15,23 @@ module.exports = {
|
|
|
14
15
|
"function": function MD010(params, onError) {
|
|
15
16
|
const codeBlocks = params.config.code_blocks;
|
|
16
17
|
const includeCode = (codeBlocks === undefined) ? true : !!codeBlocks;
|
|
18
|
+
const ignoreCodeLanguages = new Set(
|
|
19
|
+
(params.config.ignore_code_languages || [])
|
|
20
|
+
.map((language) => language.toLowerCase())
|
|
21
|
+
);
|
|
17
22
|
const spacesPerTab = params.config.spaces_per_tab;
|
|
18
23
|
const spaceMultiplier = (spacesPerTab === undefined) ?
|
|
19
24
|
1 :
|
|
20
25
|
Math.max(0, Number(spacesPerTab));
|
|
21
26
|
const exclusions = includeCode ? [] : codeBlockAndSpanRanges();
|
|
27
|
+
filterTokens(params, "fence", (token) => {
|
|
28
|
+
const language = token.info.trim().toLowerCase();
|
|
29
|
+
if (ignoreCodeLanguages.has(language)) {
|
|
30
|
+
for (let i = token.map[0] + 1; i < token.map[1] - 1; i++) {
|
|
31
|
+
exclusions.push([ i, 0, params.lines[i].length ]);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
22
35
|
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
|
23
36
|
if (includeCode || !inCode) {
|
|
24
37
|
let match = null;
|
|
@@ -26,7 +39,7 @@ module.exports = {
|
|
|
26
39
|
const { index } = match;
|
|
27
40
|
const column = index + 1;
|
|
28
41
|
const length = match[0].length;
|
|
29
|
-
if (!
|
|
42
|
+
if (!withinAnyRange(exclusions, lineIndex, index, length)) {
|
|
30
43
|
addError(
|
|
31
44
|
onError,
|
|
32
45
|
lineIndex + 1,
|
package/lib/md011.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addError, forEachLine,
|
|
5
|
+
const { addError, forEachLine, withinAnyRange } = require("../helpers");
|
|
6
6
|
const { codeBlockAndSpanRanges, lineMetadata } = require("./cache");
|
|
7
7
|
|
|
8
8
|
const reversedLinkRe =
|
|
@@ -24,7 +24,7 @@ module.exports = {
|
|
|
24
24
|
if (
|
|
25
25
|
!linkText.endsWith("\\") &&
|
|
26
26
|
!linkDestination.endsWith("\\") &&
|
|
27
|
-
!
|
|
27
|
+
!withinAnyRange(exclusions, lineIndex, index, length)
|
|
28
28
|
) {
|
|
29
29
|
addError(
|
|
30
30
|
onError,
|
package/lib/md013.js
CHANGED
|
@@ -3,13 +3,12 @@
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
5
|
const { addErrorDetailIf, filterTokens, forEachHeading, forEachLine,
|
|
6
|
-
includesSorted } = require("../helpers");
|
|
6
|
+
includesSorted, linkReferenceDefinitionRe } = require("../helpers");
|
|
7
7
|
const { lineMetadata } = require("./cache");
|
|
8
8
|
|
|
9
9
|
const longLineRePrefix = "^.{";
|
|
10
10
|
const longLineRePostfixRelaxed = "}.*\\s.*$";
|
|
11
11
|
const longLineRePostfixStrict = "}.+$";
|
|
12
|
-
const labelRe = /^\s*\[.*[^\\]]:/;
|
|
13
12
|
const linkOrImageOnlyLineRe = /^[es]*(lT?L|I)[ES]*$/;
|
|
14
13
|
const sternModeRe = /^([#>\s]*\s)?\S*$/;
|
|
15
14
|
const tokenTypeMap = {
|
|
@@ -59,11 +58,11 @@ module.exports = {
|
|
|
59
58
|
const linkOnlyLineNumbers = [];
|
|
60
59
|
filterTokens(params, "inline", (token) => {
|
|
61
60
|
let childTokenTypes = "";
|
|
62
|
-
token.children
|
|
61
|
+
for (const child of token.children) {
|
|
63
62
|
if (child.type !== "text" || child.content !== "") {
|
|
64
63
|
childTokenTypes += tokenTypeMap[child.type] || "x";
|
|
65
64
|
}
|
|
66
|
-
}
|
|
65
|
+
}
|
|
67
66
|
if (linkOrImageOnlyLineRe.test(childTokenTypes)) {
|
|
68
67
|
linkOnlyLineNumbers.push(token.lineNumber);
|
|
69
68
|
}
|
|
@@ -83,7 +82,7 @@ module.exports = {
|
|
|
83
82
|
(strict ||
|
|
84
83
|
(!(stern && sternModeRe.test(line)) &&
|
|
85
84
|
!includesSorted(linkOnlyLineNumbers, lineNumber) &&
|
|
86
|
-
!
|
|
85
|
+
!linkReferenceDefinitionRe.test(line))) &&
|
|
87
86
|
lengthRe.test(line)) {
|
|
88
87
|
addErrorDetailIf(
|
|
89
88
|
onError,
|
package/lib/md014.js
CHANGED
|
@@ -11,7 +11,7 @@ module.exports = {
|
|
|
11
11
|
"description": "Dollar signs used before commands without showing output",
|
|
12
12
|
"tags": [ "code" ],
|
|
13
13
|
"function": function MD014(params, onError) {
|
|
14
|
-
[ "code_block", "fence" ]
|
|
14
|
+
for (const type of [ "code_block", "fence" ]) {
|
|
15
15
|
filterTokens(params, type, (token) => {
|
|
16
16
|
const margin = (token.type === "fence") ? 1 : 0;
|
|
17
17
|
const dollarInstances = [];
|
|
@@ -31,7 +31,7 @@ module.exports = {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
if (allDollars) {
|
|
34
|
-
|
|
34
|
+
for (const instance of dollarInstances) {
|
|
35
35
|
const [ i, lineTrim, column, length ] = instance;
|
|
36
36
|
addErrorContext(
|
|
37
37
|
onError,
|
|
@@ -45,9 +45,9 @@ module.exports = {
|
|
|
45
45
|
"deleteCount": length
|
|
46
46
|
}
|
|
47
47
|
);
|
|
48
|
-
}
|
|
48
|
+
}
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
|
-
}
|
|
51
|
+
}
|
|
52
52
|
}
|
|
53
53
|
};
|
package/lib/md021.js
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
const { addErrorContext, filterTokens, headingStyleFor } =
|
|
6
6
|
require("../helpers");
|
|
7
7
|
|
|
8
|
+
const closedAtxRe = /^(#+)([ \t]+)([^ \t]|[^ \t].*[^ \t])([ \t]+)(#+)(\s*)$/;
|
|
9
|
+
|
|
8
10
|
module.exports = {
|
|
9
11
|
"names": [ "MD021", "no-multiple-space-closed-atx" ],
|
|
10
12
|
"description": "Multiple spaces inside hashes on closed atx style heading",
|
|
@@ -13,7 +15,7 @@ module.exports = {
|
|
|
13
15
|
filterTokens(params, "heading_open", (token) => {
|
|
14
16
|
if (headingStyleFor(token) === "atx_closed") {
|
|
15
17
|
const { line, lineNumber } = token;
|
|
16
|
-
const match =
|
|
18
|
+
const match = closedAtxRe.exec(line);
|
|
17
19
|
if (match) {
|
|
18
20
|
const [
|
|
19
21
|
,
|
package/lib/md026.js
CHANGED
|
@@ -20,7 +20,7 @@ module.exports = {
|
|
|
20
20
|
new RegExp("\\s*[" + escapeForRegExp(punctuation) + "]+$");
|
|
21
21
|
forEachHeading(params, (heading) => {
|
|
22
22
|
const { line, lineNumber } = heading;
|
|
23
|
-
const trimmedLine = line.replace(/[\s#]
|
|
23
|
+
const trimmedLine = line.replace(/([^\s#])[\s#]+$/, "$1");
|
|
24
24
|
const match = trailingPunctuationRe.exec(trimmedLine);
|
|
25
25
|
if (match && !endOfLineHtmlEntityRe.test(trimmedLine)) {
|
|
26
26
|
const fullMatch = match[0];
|
package/lib/md027.js
CHANGED
|
@@ -13,7 +13,7 @@ module.exports = {
|
|
|
13
13
|
"function": function MD027(params, onError) {
|
|
14
14
|
let blockquoteNesting = 0;
|
|
15
15
|
let listItemNesting = 0;
|
|
16
|
-
params.tokens
|
|
16
|
+
for (const token of params.tokens) {
|
|
17
17
|
const { content, lineNumber, type } = token;
|
|
18
18
|
if (type === "blockquote_open") {
|
|
19
19
|
blockquoteNesting++;
|
|
@@ -51,6 +51,6 @@ module.exports = {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
}
|
|
54
|
+
}
|
|
55
55
|
}
|
|
56
56
|
};
|
package/lib/md028.js
CHANGED
|
@@ -11,7 +11,7 @@ module.exports = {
|
|
|
11
11
|
"function": function MD028(params, onError) {
|
|
12
12
|
let prevToken = {};
|
|
13
13
|
let prevLineNumber = null;
|
|
14
|
-
params.tokens
|
|
14
|
+
for (const token of params.tokens) {
|
|
15
15
|
if ((token.type === "blockquote_open") &&
|
|
16
16
|
(prevToken.type === "blockquote_close")) {
|
|
17
17
|
for (
|
|
@@ -25,6 +25,6 @@ module.exports = {
|
|
|
25
25
|
if (token.type === "blockquote_open") {
|
|
26
26
|
prevLineNumber = token.map[1] + 1;
|
|
27
27
|
}
|
|
28
|
-
}
|
|
28
|
+
}
|
|
29
29
|
}
|
|
30
30
|
};
|
package/lib/md029.js
CHANGED
|
@@ -18,7 +18,8 @@ module.exports = {
|
|
|
18
18
|
"tags": [ "ol" ],
|
|
19
19
|
"function": function MD029(params, onError) {
|
|
20
20
|
const style = String(params.config.style || "one_or_ordered");
|
|
21
|
-
flattenedLists().filter((list) => !list.unordered)
|
|
21
|
+
const filteredLists = flattenedLists().filter((list) => !list.unordered);
|
|
22
|
+
for (const list of filteredLists) {
|
|
22
23
|
const { items } = list;
|
|
23
24
|
let current = 1;
|
|
24
25
|
let incrementing = false;
|
|
@@ -49,7 +50,7 @@ module.exports = {
|
|
|
49
50
|
current = 1;
|
|
50
51
|
}
|
|
51
52
|
// Validate each list item marker
|
|
52
|
-
|
|
53
|
+
for (const item of items) {
|
|
53
54
|
const match = orderedListItemMarkerRe.exec(item.line);
|
|
54
55
|
if (match) {
|
|
55
56
|
addErrorDetailIf(onError, item.lineNumber,
|
|
@@ -60,7 +61,7 @@ module.exports = {
|
|
|
60
61
|
current++;
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
65
66
|
}
|
|
66
67
|
};
|
package/lib/md030.js
CHANGED
|
@@ -14,13 +14,13 @@ module.exports = {
|
|
|
14
14
|
const olSingle = Number(params.config.ol_single || 1);
|
|
15
15
|
const ulMulti = Number(params.config.ul_multi || 1);
|
|
16
16
|
const olMulti = Number(params.config.ol_multi || 1);
|
|
17
|
-
flattenedLists()
|
|
17
|
+
for (const list of flattenedLists()) {
|
|
18
18
|
const lineCount = list.lastLineIndex - list.open.map[0];
|
|
19
19
|
const allSingle = lineCount === list.items.length;
|
|
20
20
|
const expectedSpaces = list.unordered ?
|
|
21
21
|
(allSingle ? ulSingle : ulMulti) :
|
|
22
22
|
(allSingle ? olSingle : olMulti);
|
|
23
|
-
list.items
|
|
23
|
+
for (const item of list.items) {
|
|
24
24
|
const { line, lineNumber } = item;
|
|
25
25
|
const match = /^[\s>]*\S+(\s*)/.exec(line);
|
|
26
26
|
const [ { "length": matchLength }, { "length": actualSpaces } ] = match;
|
|
@@ -44,7 +44,7 @@ module.exports = {
|
|
|
44
44
|
fixInfo
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
49
|
}
|
|
50
50
|
};
|
package/lib/md031.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
const { addErrorContext, forEachLine, isBlankLine } = require("../helpers");
|
|
6
6
|
const { lineMetadata } = require("./cache");
|
|
7
7
|
|
|
8
|
-
const codeFencePrefixRe = /^(.*?)
|
|
8
|
+
const codeFencePrefixRe = /^(.*?)[`~]/;
|
|
9
9
|
|
|
10
10
|
module.exports = {
|
|
11
11
|
"names": [ "MD031", "blanks-around-fences" ],
|
|
@@ -24,7 +24,7 @@ module.exports = {
|
|
|
24
24
|
const [ , prefix ] = line.match(codeFencePrefixRe) || [];
|
|
25
25
|
const fixInfo = (prefix === undefined) ? null : {
|
|
26
26
|
"lineNumber": i + (onTopFence ? 1 : 2),
|
|
27
|
-
"insertText": `${prefix}\n`
|
|
27
|
+
"insertText": `${prefix.replace(/[^>]/g, " ").trim()}\n`
|
|
28
28
|
};
|
|
29
29
|
addErrorContext(
|
|
30
30
|
onError,
|
package/lib/md032.js
CHANGED
|
@@ -13,7 +13,8 @@ module.exports = {
|
|
|
13
13
|
"tags": [ "bullet", "ul", "ol", "blank_lines" ],
|
|
14
14
|
"function": function MD032(params, onError) {
|
|
15
15
|
const { lines } = params;
|
|
16
|
-
flattenedLists().filter((list) => !list.nesting)
|
|
16
|
+
const filteredLists = flattenedLists().filter((list) => !list.nesting);
|
|
17
|
+
for (const list of filteredLists) {
|
|
17
18
|
const firstIndex = list.open.map[0];
|
|
18
19
|
if (!isBlankLine(lines[firstIndex - 1])) {
|
|
19
20
|
const line = lines[firstIndex];
|
|
@@ -45,6 +46,6 @@ module.exports = {
|
|
|
45
46
|
"insertText": `${quotePrefix}\n`
|
|
46
47
|
});
|
|
47
48
|
}
|
|
48
|
-
}
|
|
49
|
+
}
|
|
49
50
|
}
|
|
50
51
|
};
|
package/lib/md033.js
CHANGED
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
5
|
const {
|
|
6
|
-
addError, forEachLine,
|
|
6
|
+
addError, forEachLine, htmlElementRe, withinAnyRange, unescapeMarkdown
|
|
7
7
|
} = require("../helpers");
|
|
8
8
|
const { codeBlockAndSpanRanges, lineMetadata } = require("./cache");
|
|
9
9
|
|
|
10
|
-
const htmlElementRe = /<(([A-Za-z][A-Za-z0-9-]*)(?:\s[^>]*)?)\/?>/g;
|
|
11
10
|
const linkDestinationRe = /]\(\s*$/;
|
|
12
11
|
// See https://spec.commonmark.org/0.29/#autolinks
|
|
13
12
|
const emailAddressRe =
|
|
@@ -32,7 +31,7 @@ module.exports = {
|
|
|
32
31
|
!allowedElements.includes(element.toLowerCase()) &&
|
|
33
32
|
!tag.endsWith("\\>") &&
|
|
34
33
|
!emailAddressRe.test(content) &&
|
|
35
|
-
!
|
|
34
|
+
!withinAnyRange(exclusions, lineIndex, match.index, match[0].length)
|
|
36
35
|
) {
|
|
37
36
|
const prefix = line.substring(0, match.index);
|
|
38
37
|
if (!linkDestinationRe.test(prefix)) {
|
package/lib/md034.js
CHANGED
|
@@ -11,7 +11,7 @@ module.exports = {
|
|
|
11
11
|
"function": function MD034(params, onError) {
|
|
12
12
|
filterTokens(params, "inline", (token) => {
|
|
13
13
|
let inLink = false;
|
|
14
|
-
token.children
|
|
14
|
+
for (const child of token.children) {
|
|
15
15
|
const { content, line, lineNumber, type } = child;
|
|
16
16
|
let match = null;
|
|
17
17
|
if (type === "link_open") {
|
|
@@ -55,7 +55,7 @@ module.exports = {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
}
|
|
58
|
+
}
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
};
|
package/lib/md035.js
CHANGED
|
@@ -9,9 +9,14 @@ module.exports = {
|
|
|
9
9
|
"description": "Horizontal rule style",
|
|
10
10
|
"tags": [ "hr" ],
|
|
11
11
|
"function": function MD035(params, onError) {
|
|
12
|
-
let style = String(params.config.style || "consistent");
|
|
12
|
+
let style = String(params.config.style || "consistent").trim();
|
|
13
13
|
filterTokens(params, "hr", (token) => {
|
|
14
|
-
const {
|
|
14
|
+
const { line, lineNumber } = token;
|
|
15
|
+
let { markup } = token;
|
|
16
|
+
const match = line.match(/[_*\-\s\t]+$/);
|
|
17
|
+
if (match) {
|
|
18
|
+
markup = match[0].trim();
|
|
19
|
+
}
|
|
15
20
|
if (style === "consistent") {
|
|
16
21
|
style = markup;
|
|
17
22
|
}
|
package/lib/md036.js
CHANGED
package/lib/md038.js
CHANGED
|
@@ -7,7 +7,11 @@ const { addErrorContext, filterTokens, forEachInlineCodeSpan, newLineRe } =
|
|
|
7
7
|
|
|
8
8
|
const leftSpaceRe = /^\s([^`]|$)/;
|
|
9
9
|
const rightSpaceRe = /[^`]\s$/;
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
const spaceInsideCodeInline = (token) => (
|
|
12
|
+
(token.type === "code_inline") &&
|
|
13
|
+
(leftSpaceRe.test(token.content) || rightSpaceRe.test(token.content))
|
|
14
|
+
);
|
|
11
15
|
|
|
12
16
|
module.exports = {
|
|
13
17
|
"names": [ "MD038", "no-space-in-code" ],
|
|
@@ -15,7 +19,7 @@ module.exports = {
|
|
|
15
19
|
"tags": [ "whitespace", "code" ],
|
|
16
20
|
"function": function MD038(params, onError) {
|
|
17
21
|
filterTokens(params, "inline", (token) => {
|
|
18
|
-
if (token.children.some(
|
|
22
|
+
if (token.children.some(spaceInsideCodeInline)) {
|
|
19
23
|
const tokenLines = params.lines.slice(token.map[0], token.map[1]);
|
|
20
24
|
forEachInlineCodeSpan(
|
|
21
25
|
tokenLines.join("\n"),
|
|
@@ -33,8 +37,7 @@ module.exports = {
|
|
|
33
37
|
rangeLineOffset = codeLines.length - 1;
|
|
34
38
|
fixIndex = 0;
|
|
35
39
|
}
|
|
36
|
-
|
|
37
|
-
if ((left || right) && !allowed) {
|
|
40
|
+
if (left || right) {
|
|
38
41
|
const codeLinesRange = codeLines[rangeLineOffset];
|
|
39
42
|
if (codeLines.length > 1) {
|
|
40
43
|
rangeLength = codeLinesRange.length + tickCount;
|
package/lib/md039.js
CHANGED
|
@@ -18,8 +18,8 @@ module.exports = {
|
|
|
18
18
|
let inLink = false;
|
|
19
19
|
let linkText = "";
|
|
20
20
|
let lineIndex = 0;
|
|
21
|
-
|
|
22
|
-
const { content, type } = child;
|
|
21
|
+
for (const child of children) {
|
|
22
|
+
const { content, markup, type } = child;
|
|
23
23
|
if (type === "link_open") {
|
|
24
24
|
inLink = true;
|
|
25
25
|
linkText = "";
|
|
@@ -57,9 +57,11 @@ module.exports = {
|
|
|
57
57
|
lineNumber++;
|
|
58
58
|
lineIndex = 0;
|
|
59
59
|
} else if (inLink) {
|
|
60
|
-
linkText +=
|
|
60
|
+
linkText += type.endsWith("_inline") ?
|
|
61
|
+
`${markup}${content}${markup}` :
|
|
62
|
+
(content || markup);
|
|
61
63
|
}
|
|
62
|
-
}
|
|
64
|
+
}
|
|
63
65
|
});
|
|
64
66
|
}
|
|
65
67
|
};
|
package/lib/md042.js
CHANGED
|
@@ -2,11 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorContext,
|
|
5
|
+
const { addErrorContext, escapeForRegExp, filterTokens } =
|
|
6
6
|
require("../helpers");
|
|
7
7
|
|
|
8
|
-
const emptyLinkRe = /\[[^\]]*](?:\((?:#?|(?:<>))\))/;
|
|
9
|
-
|
|
10
8
|
module.exports = {
|
|
11
9
|
"names": [ "MD042", "no-empty-links" ],
|
|
12
10
|
"description": "No empty links",
|
|
@@ -16,27 +14,36 @@ module.exports = {
|
|
|
16
14
|
let inLink = false;
|
|
17
15
|
let linkText = "";
|
|
18
16
|
let emptyLink = false;
|
|
19
|
-
token.children
|
|
17
|
+
for (const child of token.children) {
|
|
20
18
|
if (child.type === "link_open") {
|
|
21
19
|
inLink = true;
|
|
22
20
|
linkText = "";
|
|
23
|
-
child.attrs
|
|
21
|
+
for (const attr of child.attrs) {
|
|
24
22
|
if (attr[0] === "href" && (!attr[1] || (attr[1] === "#"))) {
|
|
25
23
|
emptyLink = true;
|
|
26
24
|
}
|
|
27
|
-
}
|
|
25
|
+
}
|
|
28
26
|
} else if (child.type === "link_close") {
|
|
29
27
|
inLink = false;
|
|
30
28
|
if (emptyLink) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
let context = `[${linkText}]`;
|
|
30
|
+
let range = null;
|
|
31
|
+
const match = child.line.match(
|
|
32
|
+
new RegExp(`${escapeForRegExp(context)}\\((?:|#|<>)\\)`)
|
|
33
|
+
);
|
|
34
|
+
if (match) {
|
|
35
|
+
context = match[0];
|
|
36
|
+
range = [ match.index + 1, match[0].length ];
|
|
37
|
+
}
|
|
38
|
+
addErrorContext(
|
|
39
|
+
onError, child.lineNumber, context, null, null, range
|
|
40
|
+
);
|
|
34
41
|
emptyLink = false;
|
|
35
42
|
}
|
|
36
43
|
} else if (inLink) {
|
|
37
44
|
linkText += child.content;
|
|
38
45
|
}
|
|
39
|
-
}
|
|
46
|
+
}
|
|
40
47
|
});
|
|
41
48
|
}
|
|
42
49
|
};
|
package/lib/md043.js
CHANGED
|
@@ -13,9 +13,9 @@ 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 ]
|
|
16
|
+
for (const level of [ 1, 2, 3, 4, 5, 6 ]) {
|
|
17
17
|
levels["h" + level] = "######".substr(-level);
|
|
18
|
-
}
|
|
18
|
+
}
|
|
19
19
|
let i = 0;
|
|
20
20
|
let matchAny = false;
|
|
21
21
|
let hasError = false;
|