markdownlint 0.26.1 → 0.27.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 +81 -59
- package/README.md +424 -301
- package/demo/markdownlint-browser.js +445 -210
- package/doc/CustomRules.md +101 -50
- package/doc/Prettier.md +14 -10
- package/doc/ReleaseProcess.md +20 -0
- package/doc/Rules.md +464 -296
- package/doc/md001.md +37 -0
- package/doc/md002.md +37 -0
- package/doc/md003.md +59 -0
- package/doc/md004.md +49 -0
- package/doc/md005.md +53 -0
- package/doc/md006.md +46 -0
- package/doc/md007.md +55 -0
- package/doc/md009.md +51 -0
- package/doc/md010.md +56 -0
- package/doc/md011.md +30 -0
- package/doc/md012.md +38 -0
- package/doc/md013.md +60 -0
- package/doc/md014.md +54 -0
- package/doc/md018.md +27 -0
- package/doc/md019.md +28 -0
- package/doc/md020.md +29 -0
- package/doc/md021.md +31 -0
- package/doc/md022.md +46 -0
- package/doc/md023.md +26 -0
- package/doc/md024.md +47 -0
- package/doc/md025.md +49 -0
- package/doc/md026.md +41 -0
- package/doc/md027.md +24 -0
- package/doc/md028.md +40 -0
- package/doc/md029.md +98 -0
- package/doc/md030.md +82 -0
- package/doc/md031.md +50 -0
- package/doc/md032.md +38 -0
- package/doc/md033.md +27 -0
- package/doc/md034.md +44 -0
- package/doc/md035.md +42 -0
- package/doc/md036.md +45 -0
- package/doc/md037.md +37 -0
- package/doc/md038.md +40 -0
- package/doc/md039.md +21 -0
- package/doc/md040.md +52 -0
- package/doc/md041.md +49 -0
- package/doc/md042.md +32 -0
- package/doc/md043.md +72 -0
- package/doc/md044.md +35 -0
- package/doc/md045.md +34 -0
- package/doc/md046.md +40 -0
- package/doc/md047.md +34 -0
- package/doc/md048.md +41 -0
- package/doc/md049.md +32 -0
- package/doc/md050.md +32 -0
- package/doc/md051.md +50 -0
- package/doc/md052.md +33 -0
- package/doc/md053.md +38 -0
- package/helpers/README.md +35 -15
- package/helpers/helpers.js +234 -70
- package/helpers/package.json +2 -2
- package/lib/constants.js +8 -1
- package/lib/markdownlint.js +7 -12
- package/lib/md011.js +2 -2
- package/lib/md013.js +7 -6
- package/lib/md019.js +1 -1
- package/lib/md022.js +15 -3
- package/lib/md023.js +1 -1
- package/lib/md026.js +1 -1
- package/lib/md032.js +4 -5
- package/lib/md033.js +16 -5
- package/lib/md034.js +70 -45
- package/lib/md035.js +1 -1
- package/lib/md037.js +25 -22
- package/lib/md038.js +1 -1
- package/lib/md039.js +1 -1
- package/lib/md040.js +21 -2
- package/lib/md043.js +4 -2
- package/lib/md044.js +4 -3
- package/lib/md051.js +43 -11
- package/lib/md053.js +18 -11
- package/lib/rules.js +1 -1
- package/package.json +31 -21
- package/schema/.markdownlint.jsonc +16 -4
- package/schema/.markdownlint.yaml +13 -3
- package/schema/markdownlint-config-schema.json +45 -5
- package/style/prettier.json +26 -0
package/lib/markdownlint.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const path = require("path");
|
|
6
|
-
const { promisify } = require("util");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
const { promisify } = require("node:util");
|
|
7
7
|
const markdownIt = require("markdown-it");
|
|
8
8
|
const { deprecatedRuleNames } = require("./constants");
|
|
9
9
|
const rules = require("./rules");
|
|
@@ -233,11 +233,6 @@ function annotateAndFreezeTokens(tokens, lines) {
|
|
|
233
233
|
if (!token.map && trMap) {
|
|
234
234
|
token.map = [ ...trMap ];
|
|
235
235
|
}
|
|
236
|
-
// Adjust maps for math blocks
|
|
237
|
-
if (helpers.isMathBlock(token) && token.map[1]) {
|
|
238
|
-
// markdown-it-texmath plugin does not account for math_block_end
|
|
239
|
-
token.map[1]++;
|
|
240
|
-
}
|
|
241
236
|
// Update token metadata
|
|
242
237
|
if (token.map) {
|
|
243
238
|
token.line = lines[token.map[0]];
|
|
@@ -879,7 +874,7 @@ function lintInput(options, synchronous, callback) {
|
|
|
879
874
|
// @ts-ignore
|
|
880
875
|
md.use(...plugin);
|
|
881
876
|
}
|
|
882
|
-
const fs = options.fs || require("fs");
|
|
877
|
+
const fs = options.fs || require("node:fs");
|
|
883
878
|
const results = newResults(ruleList);
|
|
884
879
|
let done = false;
|
|
885
880
|
let concurrency = 0;
|
|
@@ -1085,10 +1080,10 @@ function readConfig(file, parsers, fs, callback) {
|
|
|
1085
1080
|
}
|
|
1086
1081
|
}
|
|
1087
1082
|
if (!fs) {
|
|
1088
|
-
fs = require("fs");
|
|
1083
|
+
fs = require("node:fs");
|
|
1089
1084
|
}
|
|
1090
1085
|
// Read file
|
|
1091
|
-
const os = require("os");
|
|
1086
|
+
const os = require("node:os");
|
|
1092
1087
|
file = helpers.expandTildePath(file, os);
|
|
1093
1088
|
fs.readFile(file, "utf8", (err, content) => {
|
|
1094
1089
|
if (err) {
|
|
@@ -1160,10 +1155,10 @@ function readConfigPromise(file, parsers, fs) {
|
|
|
1160
1155
|
*/
|
|
1161
1156
|
function readConfigSync(file, parsers, fs) {
|
|
1162
1157
|
if (!fs) {
|
|
1163
|
-
fs = require("fs");
|
|
1158
|
+
fs = require("node:fs");
|
|
1164
1159
|
}
|
|
1165
1160
|
// Read file
|
|
1166
|
-
const os = require("os");
|
|
1161
|
+
const os = require("node:os");
|
|
1167
1162
|
file = helpers.expandTildePath(file, os);
|
|
1168
1163
|
const content = fs.readFileSync(file, "utf8");
|
|
1169
1164
|
// Try to parse file
|
package/lib/md011.js
CHANGED
|
@@ -6,7 +6,7 @@ const { addError, forEachLine, withinAnyRange } = require("../helpers");
|
|
|
6
6
|
const { codeBlockAndSpanRanges, lineMetadata } = require("./cache");
|
|
7
7
|
|
|
8
8
|
const reversedLinkRe =
|
|
9
|
-
/(^|[^\\])\(([^)]+)\)\[([^\]^][^\]]*)](?!\()/g;
|
|
9
|
+
/(^|[^\\])\(([^()]+)\)\[([^\]^][^\]]*)\](?!\()/g;
|
|
10
10
|
|
|
11
11
|
module.exports = {
|
|
12
12
|
"names": [ "MD011", "no-reversed-links" ],
|
|
@@ -30,7 +30,7 @@ module.exports = {
|
|
|
30
30
|
onError,
|
|
31
31
|
lineIndex + 1,
|
|
32
32
|
reversedLink.slice(preChar.length),
|
|
33
|
-
|
|
33
|
+
undefined,
|
|
34
34
|
[ index + 1, length ],
|
|
35
35
|
{
|
|
36
36
|
"editColumn": index + 1,
|
package/lib/md013.js
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
5
|
const { addErrorDetailIf, filterTokens, forEachHeading, forEachLine,
|
|
6
|
-
includesSorted
|
|
7
|
-
const { lineMetadata } = require("./cache");
|
|
6
|
+
includesSorted } = require("../helpers");
|
|
7
|
+
const { lineMetadata, referenceLinkImageData } = require("./cache");
|
|
8
8
|
|
|
9
9
|
const longLineRePrefix = "^.{";
|
|
10
10
|
const longLineRePostfixRelaxed = "}.*\\s.*$";
|
|
11
11
|
const longLineRePostfixStrict = "}.+$";
|
|
12
|
-
const linkOrImageOnlyLineRe = /^[es]*(lT?L|I)[ES]*$/;
|
|
13
|
-
const sternModeRe = /^([#>\s]*\s)?\S*$/;
|
|
12
|
+
const linkOrImageOnlyLineRe = /^[es]*(?:lT?L|I)[ES]*$/;
|
|
13
|
+
const sternModeRe = /^(?:[#>\s]*\s)?\S*$/;
|
|
14
14
|
const tokenTypeMap = {
|
|
15
15
|
"em_open": "e",
|
|
16
16
|
"em_close": "E",
|
|
@@ -67,6 +67,7 @@ module.exports = {
|
|
|
67
67
|
linkOnlyLineNumbers.push(token.lineNumber);
|
|
68
68
|
}
|
|
69
69
|
});
|
|
70
|
+
const { definitionLineIndices } = referenceLinkImageData();
|
|
70
71
|
forEachLine(lineMetadata(), (line, lineIndex, inCode, onFence, inTable) => {
|
|
71
72
|
const lineNumber = lineIndex + 1;
|
|
72
73
|
const isHeading = includesSorted(headingLineNumbers, lineNumber);
|
|
@@ -79,10 +80,10 @@ module.exports = {
|
|
|
79
80
|
if ((includeCodeBlocks || !inCode) &&
|
|
80
81
|
(includeTables || !inTable) &&
|
|
81
82
|
(includeHeadings || !isHeading) &&
|
|
83
|
+
!includesSorted(definitionLineIndices, lineIndex) &&
|
|
82
84
|
(strict ||
|
|
83
85
|
(!(stern && sternModeRe.test(line)) &&
|
|
84
|
-
!includesSorted(linkOnlyLineNumbers, lineNumber) &&
|
|
85
|
-
!linkReferenceDefinitionRe.test(line))) &&
|
|
86
|
+
!includesSorted(linkOnlyLineNumbers, lineNumber))) &&
|
|
86
87
|
lengthRe.test(line)) {
|
|
87
88
|
addErrorDetailIf(
|
|
88
89
|
onError,
|
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 = /^(#+)([ \t]{2,})
|
|
16
|
+
const match = /^(#+)([ \t]{2,})\S/.exec(line);
|
|
17
17
|
if (match) {
|
|
18
18
|
const [
|
|
19
19
|
,
|
package/lib/md022.js
CHANGED
|
@@ -2,7 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorDetailIf, filterTokens, isBlankLine } =
|
|
5
|
+
const { addErrorDetailIf, blockquotePrefixRe, filterTokens, isBlankLine } =
|
|
6
|
+
require("../helpers");
|
|
7
|
+
|
|
8
|
+
const getBlockQuote = (str, count) => (
|
|
9
|
+
(str || "")
|
|
10
|
+
.match(blockquotePrefixRe)[0]
|
|
11
|
+
.trimEnd()
|
|
12
|
+
// eslint-disable-next-line unicorn/prefer-spread
|
|
13
|
+
.concat("\n")
|
|
14
|
+
.repeat(count)
|
|
15
|
+
);
|
|
6
16
|
|
|
7
17
|
module.exports = {
|
|
8
18
|
"names": [ "MD022", "blanks-around-headings", "blanks-around-headers" ],
|
|
@@ -31,7 +41,8 @@ module.exports = {
|
|
|
31
41
|
lines[topIndex].trim(),
|
|
32
42
|
null,
|
|
33
43
|
{
|
|
34
|
-
"insertText":
|
|
44
|
+
"insertText":
|
|
45
|
+
getBlockQuote(lines[topIndex - 1], linesAbove - actualAbove)
|
|
35
46
|
});
|
|
36
47
|
let actualBelow = 0;
|
|
37
48
|
for (let i = 0; i < linesBelow; i++) {
|
|
@@ -49,7 +60,8 @@ module.exports = {
|
|
|
49
60
|
null,
|
|
50
61
|
{
|
|
51
62
|
"lineNumber": nextIndex + 1,
|
|
52
|
-
"insertText":
|
|
63
|
+
"insertText":
|
|
64
|
+
getBlockQuote(lines[nextIndex], linesBelow - actualBelow)
|
|
53
65
|
});
|
|
54
66
|
});
|
|
55
67
|
}
|
package/lib/md023.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const { addErrorContext, filterTokens } = require("../helpers");
|
|
6
6
|
|
|
7
|
-
const spaceBeforeHeadingRe = /^(
|
|
7
|
+
const spaceBeforeHeadingRe = /^(\s+|[>\s]+\s\s)[^>\s]/;
|
|
8
8
|
|
|
9
9
|
module.exports = {
|
|
10
10
|
"names": [ "MD023", "heading-start-left", "header-start-left" ],
|
package/lib/md026.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
const { addError, allPunctuationNoQuestion, escapeForRegExp, forEachHeading } =
|
|
6
6
|
require("../helpers");
|
|
7
7
|
|
|
8
|
-
const endOfLineHtmlEntityRe = /&#?[
|
|
8
|
+
const endOfLineHtmlEntityRe = /&#?[\da-zA-Z]+;$/;
|
|
9
9
|
|
|
10
10
|
module.exports = {
|
|
11
11
|
"names": [ "MD026", "no-trailing-punctuation" ],
|
package/lib/md032.js
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorContext, isBlankLine } =
|
|
5
|
+
const { addErrorContext, blockquotePrefixRe, isBlankLine } =
|
|
6
|
+
require("../helpers");
|
|
6
7
|
const { flattenedLists } = require("./cache");
|
|
7
8
|
|
|
8
|
-
const quotePrefixRe = /^[>\s]*/;
|
|
9
|
-
|
|
10
9
|
module.exports = {
|
|
11
10
|
"names": [ "MD032", "blanks-around-lists" ],
|
|
12
11
|
"description": "Lists should be surrounded by blank lines",
|
|
@@ -18,7 +17,7 @@ module.exports = {
|
|
|
18
17
|
const firstIndex = list.open.map[0];
|
|
19
18
|
if (!isBlankLine(lines[firstIndex - 1])) {
|
|
20
19
|
const line = lines[firstIndex];
|
|
21
|
-
const quotePrefix = line.match(
|
|
20
|
+
const quotePrefix = line.match(blockquotePrefixRe)[0].trimEnd();
|
|
22
21
|
addErrorContext(
|
|
23
22
|
onError,
|
|
24
23
|
firstIndex + 1,
|
|
@@ -33,7 +32,7 @@ module.exports = {
|
|
|
33
32
|
const lastIndex = list.lastLineIndex - 1;
|
|
34
33
|
if (!isBlankLine(lines[lastIndex + 1])) {
|
|
35
34
|
const line = lines[lastIndex];
|
|
36
|
-
const quotePrefix = line.match(
|
|
35
|
+
const quotePrefix = line.match(blockquotePrefixRe)[0].trimEnd();
|
|
37
36
|
addErrorContext(
|
|
38
37
|
onError,
|
|
39
38
|
lastIndex + 1,
|
package/lib/md033.js
CHANGED
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
const {
|
|
6
6
|
addError, forEachLine, htmlElementRe, withinAnyRange, unescapeMarkdown
|
|
7
7
|
} = require("../helpers");
|
|
8
|
-
const { codeBlockAndSpanRanges, lineMetadata } =
|
|
8
|
+
const { codeBlockAndSpanRanges, lineMetadata, referenceLinkImageData } =
|
|
9
|
+
require("./cache");
|
|
9
10
|
|
|
10
|
-
const linkDestinationRe =
|
|
11
|
+
const linkDestinationRe = /\]\(\s*$/;
|
|
11
12
|
// See https://spec.commonmark.org/0.29/#autolinks
|
|
12
13
|
const emailAddressRe =
|
|
13
14
|
// eslint-disable-next-line max-len
|
|
14
|
-
/^[
|
|
15
|
+
/^[\w.!#$%&'*+/=?^`{|}~-]+@[a-zA-Z\d](?:[a-zA-Z\d-]{0,61}[a-zA-Z\d])?(?:\.[a-zA-Z\d](?:[a-zA-Z\d-]{0,61}[a-zA-Z\d])?)*$/;
|
|
15
16
|
|
|
16
17
|
module.exports = {
|
|
17
18
|
"names": [ "MD033", "no-inline-html" ],
|
|
@@ -22,6 +23,15 @@ module.exports = {
|
|
|
22
23
|
allowedElements = Array.isArray(allowedElements) ? allowedElements : [];
|
|
23
24
|
allowedElements = allowedElements.map((element) => element.toLowerCase());
|
|
24
25
|
const exclusions = codeBlockAndSpanRanges();
|
|
26
|
+
const { references, definitionLineIndices } = referenceLinkImageData();
|
|
27
|
+
for (const datas of references.values()) {
|
|
28
|
+
for (const data of datas) {
|
|
29
|
+
const [ lineIndex, index, , textLength, labelLength ] = data;
|
|
30
|
+
if (labelLength > 0) {
|
|
31
|
+
exclusions.push([ lineIndex, index + 3 + textLength, labelLength ]);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
25
35
|
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
|
26
36
|
let match = null;
|
|
27
37
|
// eslint-disable-next-line no-unmodified-loop-condition
|
|
@@ -31,14 +41,15 @@ module.exports = {
|
|
|
31
41
|
!allowedElements.includes(element.toLowerCase()) &&
|
|
32
42
|
!tag.endsWith("\\>") &&
|
|
33
43
|
!emailAddressRe.test(content) &&
|
|
34
|
-
!withinAnyRange(exclusions, lineIndex, match.index,
|
|
44
|
+
!withinAnyRange(exclusions, lineIndex, match.index, tag.length) &&
|
|
45
|
+
!definitionLineIndices.includes(lineIndex)
|
|
35
46
|
) {
|
|
36
47
|
const prefix = line.substring(0, match.index);
|
|
37
48
|
if (!linkDestinationRe.test(prefix)) {
|
|
38
49
|
const unescaped = unescapeMarkdown(prefix + "<", "_");
|
|
39
50
|
if (!unescaped.endsWith("_")) {
|
|
40
51
|
addError(onError, lineIndex + 1, "Element: " + element,
|
|
41
|
-
|
|
52
|
+
undefined, [ match.index + 1, tag.length ]);
|
|
42
53
|
}
|
|
43
54
|
}
|
|
44
55
|
}
|
package/lib/md034.js
CHANGED
|
@@ -2,60 +2,85 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorContext,
|
|
5
|
+
const { addErrorContext, filterTokens, funcExpExec, urlFe, withinAnyRange } =
|
|
6
|
+
require("../helpers");
|
|
7
|
+
const { codeBlockAndSpanRanges, htmlElementRanges, referenceLinkImageData } =
|
|
8
|
+
require("./cache");
|
|
9
|
+
|
|
10
|
+
const htmlLinkRe = /<a(?:\s[^>]*)?>[^<>]*<\/a\s*>/gi;
|
|
6
11
|
|
|
7
12
|
module.exports = {
|
|
8
13
|
"names": [ "MD034", "no-bare-urls" ],
|
|
9
14
|
"description": "Bare URL used",
|
|
10
15
|
"tags": [ "links", "url" ],
|
|
11
16
|
"function": function MD034(params, onError) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
const { lines } = params;
|
|
18
|
+
const codeExclusions = [
|
|
19
|
+
...codeBlockAndSpanRanges(),
|
|
20
|
+
...htmlElementRanges()
|
|
21
|
+
];
|
|
22
|
+
filterTokens(params, "html_block", (token) => {
|
|
23
|
+
for (let i = token.map[0]; i < token.map[1]; i++) {
|
|
24
|
+
codeExclusions.push([ i, 0, lines[i].length ]);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
const { definitionLineIndices } = referenceLinkImageData();
|
|
28
|
+
for (const [ lineIndex, line ] of lines.entries()) {
|
|
29
|
+
if (definitionLineIndices[0] === lineIndex) {
|
|
30
|
+
definitionLineIndices.shift();
|
|
31
|
+
} else {
|
|
16
32
|
let match = null;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
33
|
+
const lineExclusions = [];
|
|
34
|
+
while ((match = htmlLinkRe.exec(line)) !== null) {
|
|
35
|
+
lineExclusions.push([ lineIndex, match.index, match[0].length ]);
|
|
36
|
+
}
|
|
37
|
+
while ((match = funcExpExec(urlFe, line)) !== null) {
|
|
38
|
+
const [ bareUrl ] = match;
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
const matchIndex = match.index;
|
|
41
|
+
const bareUrlLength = bareUrl.length;
|
|
42
|
+
const prefix = line.slice(0, matchIndex);
|
|
43
|
+
const postfix = line.slice(matchIndex + bareUrlLength);
|
|
44
|
+
if (
|
|
45
|
+
// Allow <...> to avoid reporting non-bare links
|
|
46
|
+
!(prefix.endsWith("<") && postfix.startsWith(">")) &&
|
|
47
|
+
// Allow >...</ to avoid reporting <code>...</code>
|
|
48
|
+
!(prefix.endsWith(">") && postfix.startsWith("</")) &&
|
|
49
|
+
// Allow "..." and '...' to allow quoting a bare link
|
|
50
|
+
!(prefix.endsWith("\"") && postfix.startsWith("\"")) &&
|
|
51
|
+
!(prefix.endsWith("'") && postfix.startsWith("'")) &&
|
|
52
|
+
// Allow ](... to avoid reporting Markdown-style links
|
|
53
|
+
!(/\]\(\s*$/.test(prefix)) &&
|
|
54
|
+
// Allow [...] to avoid MD011/no-reversed-links and nested links
|
|
55
|
+
!(/\[[^\]]*$/.test(prefix) && /^[^[]*\]/.test(postfix)) &&
|
|
56
|
+
!withinAnyRange(
|
|
57
|
+
lineExclusions, lineIndex, matchIndex, bareUrlLength
|
|
58
|
+
) &&
|
|
59
|
+
!withinAnyRange(
|
|
60
|
+
codeExclusions, lineIndex, matchIndex, bareUrlLength
|
|
61
|
+
)
|
|
62
|
+
) {
|
|
63
|
+
const range = [
|
|
64
|
+
matchIndex + 1,
|
|
65
|
+
bareUrlLength
|
|
66
|
+
];
|
|
67
|
+
const fixInfo = {
|
|
68
|
+
"editColumn": range[0],
|
|
69
|
+
"deleteCount": range[1],
|
|
70
|
+
"insertText": `<${bareUrl}>`
|
|
71
|
+
};
|
|
72
|
+
addErrorContext(
|
|
73
|
+
onError,
|
|
74
|
+
lineIndex + 1,
|
|
75
|
+
bareUrl,
|
|
76
|
+
null,
|
|
77
|
+
null,
|
|
78
|
+
range,
|
|
79
|
+
fixInfo
|
|
80
|
+
);
|
|
56
81
|
}
|
|
57
82
|
}
|
|
58
83
|
}
|
|
59
|
-
}
|
|
84
|
+
}
|
|
60
85
|
}
|
|
61
86
|
};
|
package/lib/md035.js
CHANGED
|
@@ -13,7 +13,7 @@ module.exports = {
|
|
|
13
13
|
filterTokens(params, "hr", (token) => {
|
|
14
14
|
const { line, lineNumber } = token;
|
|
15
15
|
let { markup } = token;
|
|
16
|
-
const match = line.match(/[_*\-\s
|
|
16
|
+
const match = line.match(/[_*\-\s]+$/);
|
|
17
17
|
if (match) {
|
|
18
18
|
markup = match[0].trim();
|
|
19
19
|
}
|
package/lib/md037.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorContext, emphasisMarkersInContent, forEachLine, isBlankLine
|
|
6
|
-
require("../helpers");
|
|
7
|
-
const { lineMetadata } = require("./cache");
|
|
5
|
+
const { addErrorContext, emphasisMarkersInContent, forEachLine, isBlankLine,
|
|
6
|
+
withinAnyRange } = require("../helpers");
|
|
7
|
+
const { htmlElementRanges, lineMetadata } = require("./cache");
|
|
8
8
|
|
|
9
|
-
const emphasisRe = /(^|[^\\]|\\\\)(?:(
|
|
10
|
-
const embeddedUnderscoreRe = /([A-Za-
|
|
9
|
+
const emphasisRe = /(^|[^\\]|\\\\)(?:(\*{1,3})|(_{1,3}))/g;
|
|
10
|
+
const embeddedUnderscoreRe = /([A-Za-z\d])_([A-Za-z\d])/g;
|
|
11
11
|
const asteriskListItemMarkerRe = /^([\s>]*)\*(\s+)/;
|
|
12
12
|
const leftSpaceRe = /^\s+/;
|
|
13
13
|
const rightSpaceRe = /\s+$/;
|
|
@@ -18,6 +18,7 @@ module.exports = {
|
|
|
18
18
|
"description": "Spaces inside emphasis markers",
|
|
19
19
|
"tags": [ "whitespace", "emphasis" ],
|
|
20
20
|
"function": function MD037(params, onError) {
|
|
21
|
+
const exclusions = htmlElementRanges();
|
|
21
22
|
// eslint-disable-next-line init-declarations
|
|
22
23
|
let effectiveEmphasisLength, emphasisIndex, emphasisKind, emphasisLength,
|
|
23
24
|
pendingError = null;
|
|
@@ -50,25 +51,27 @@ module.exports = {
|
|
|
50
51
|
// Report the violation
|
|
51
52
|
const contextStart = emphasisIndex - emphasisLength;
|
|
52
53
|
const contextEnd = matchIndex + contextLength;
|
|
53
|
-
const context = line.substring(contextStart, contextEnd);
|
|
54
54
|
const column = contextStart + 1;
|
|
55
55
|
const length = contextEnd - contextStart;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
56
|
+
if (!withinAnyRange(exclusions, lineIndex, column, length)) {
|
|
57
|
+
const context = line.substring(contextStart, contextEnd);
|
|
58
|
+
const leftMarker = line.substring(contextStart, emphasisIndex);
|
|
59
|
+
const rightMarker = match ? (match[2] || match[3]) : "";
|
|
60
|
+
const fixedText = `${leftMarker}${content.trim()}${rightMarker}`;
|
|
61
|
+
return [
|
|
62
|
+
onError,
|
|
63
|
+
lineIndex + 1,
|
|
64
|
+
context,
|
|
65
|
+
leftSpace,
|
|
66
|
+
rightSpace,
|
|
67
|
+
[ column, length ],
|
|
68
|
+
{
|
|
69
|
+
"editColumn": column,
|
|
70
|
+
"deleteCount": length,
|
|
71
|
+
"insertText": fixedText
|
|
72
|
+
}
|
|
73
|
+
];
|
|
74
|
+
}
|
|
72
75
|
}
|
|
73
76
|
return null;
|
|
74
77
|
}
|
package/lib/md038.js
CHANGED
package/lib/md039.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
const { addErrorContext, filterTokens } = require("../helpers");
|
|
6
6
|
|
|
7
7
|
const spaceInLinkRe =
|
|
8
|
-
/\[(?:\s
|
|
8
|
+
/\[(?:\s[^\]]*|[^\]]*?\s)\](?=(\([^)]*\)|\[[^\]]*\]))/;
|
|
9
9
|
|
|
10
10
|
module.exports = {
|
|
11
11
|
"names": [ "MD039", "no-space-in-links" ],
|
package/lib/md040.js
CHANGED
|
@@ -2,16 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorContext, filterTokens } = require("../helpers");
|
|
5
|
+
const { addError, addErrorContext, filterTokens } = require("../helpers");
|
|
6
6
|
|
|
7
7
|
module.exports = {
|
|
8
8
|
"names": [ "MD040", "fenced-code-language" ],
|
|
9
9
|
"description": "Fenced code blocks should have a language specified",
|
|
10
10
|
"tags": [ "code", "language" ],
|
|
11
11
|
"function": function MD040(params, onError) {
|
|
12
|
+
let allowed = params.config.allowed_languages;
|
|
13
|
+
allowed = Array.isArray(allowed) ? allowed : [];
|
|
14
|
+
const languageOnly = !!params.config.language_only;
|
|
15
|
+
|
|
12
16
|
filterTokens(params, "fence", function forToken(token) {
|
|
13
|
-
|
|
17
|
+
const lang = token.info.trim().split(/\s+/u).shift();
|
|
18
|
+
if (lang === "") {
|
|
14
19
|
addErrorContext(onError, token.lineNumber, token.line);
|
|
20
|
+
} else if ((allowed.length > 0) && !allowed.includes(lang)) {
|
|
21
|
+
addError(
|
|
22
|
+
onError,
|
|
23
|
+
token.lineNumber,
|
|
24
|
+
`"${lang}" is not allowed`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (languageOnly && (token.info !== lang)) {
|
|
29
|
+
addError(
|
|
30
|
+
onError,
|
|
31
|
+
token.lineNumber,
|
|
32
|
+
`Info string contains more than language: "${token.info}"`
|
|
33
|
+
);
|
|
15
34
|
}
|
|
16
35
|
});
|
|
17
36
|
}
|
package/lib/md043.js
CHANGED
|
@@ -11,6 +11,7 @@ module.exports = {
|
|
|
11
11
|
"tags": [ "headings", "headers" ],
|
|
12
12
|
"function": function MD043(params, onError) {
|
|
13
13
|
const requiredHeadings = params.config.headings || params.config.headers;
|
|
14
|
+
const matchCase = params.config.match_case || false;
|
|
14
15
|
if (Array.isArray(requiredHeadings)) {
|
|
15
16
|
const levels = {};
|
|
16
17
|
for (const level of [ 1, 2, 3, 4, 5, 6 ]) {
|
|
@@ -21,6 +22,7 @@ module.exports = {
|
|
|
21
22
|
let hasError = false;
|
|
22
23
|
let anyHeadings = false;
|
|
23
24
|
const getExpected = () => requiredHeadings[i++] || "[None]";
|
|
25
|
+
const handleCase = (str) => (matchCase ? str : str.toLowerCase());
|
|
24
26
|
forEachHeading(params, (heading, content) => {
|
|
25
27
|
if (!hasError) {
|
|
26
28
|
anyHeadings = true;
|
|
@@ -28,13 +30,13 @@ module.exports = {
|
|
|
28
30
|
const expected = getExpected();
|
|
29
31
|
if (expected === "*") {
|
|
30
32
|
const nextExpected = getExpected();
|
|
31
|
-
if (nextExpected
|
|
33
|
+
if (handleCase(nextExpected) !== handleCase(actual)) {
|
|
32
34
|
matchAny = true;
|
|
33
35
|
i--;
|
|
34
36
|
}
|
|
35
37
|
} else if (expected === "+") {
|
|
36
38
|
matchAny = true;
|
|
37
|
-
} else if (expected
|
|
39
|
+
} else if (handleCase(expected) === handleCase(actual)) {
|
|
38
40
|
matchAny = false;
|
|
39
41
|
} else if (matchAny) {
|
|
40
42
|
i--;
|
package/lib/md044.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorDetailIf,
|
|
6
|
-
|
|
5
|
+
const { addErrorDetailIf, escapeForRegExp, forEachLine, forEachLink,
|
|
6
|
+
funcExpExec, linkReferenceDefinitionRe, urlFe, withinAnyRange } =
|
|
7
7
|
require("../helpers");
|
|
8
8
|
const { codeBlockAndSpanRanges, htmlElementRanges, lineMetadata } =
|
|
9
9
|
require("./cache");
|
|
@@ -28,7 +28,8 @@ module.exports = {
|
|
|
28
28
|
exclusions.push([ lineIndex, 0, line.length ]);
|
|
29
29
|
} else {
|
|
30
30
|
let match = null;
|
|
31
|
-
while ((match =
|
|
31
|
+
while ((match = funcExpExec(urlFe, line)) !== null) {
|
|
32
|
+
// @ts-ignore
|
|
32
33
|
exclusions.push([ lineIndex, match.index, match[0].length ]);
|
|
33
34
|
}
|
|
34
35
|
forEachLink(line, (index, _, text, destination) => {
|