markdownlint 0.20.0 → 0.20.4
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 +47 -47
- package/LICENSE +21 -21
- package/README.md +881 -868
- package/demo/markdownlint-browser.js +5438 -5306
- package/doc/CustomRules.md +313 -313
- package/doc/Rules.md +1847 -1795
- package/helpers/LICENSE +21 -21
- package/helpers/README.md +50 -50
- package/helpers/helpers.js +687 -627
- package/helpers/package.json +18 -18
- package/lib/cache.js +24 -24
- package/lib/markdownlint.d.ts +352 -352
- package/lib/markdownlint.js +1101 -1101
- package/lib/md001.js +22 -22
- package/lib/md002.js +22 -22
- package/lib/md003.js +42 -42
- package/lib/md004.js +43 -43
- package/lib/md005.js +69 -69
- package/lib/md006.js +34 -34
- package/lib/md007.js +47 -47
- package/lib/md009.js +77 -77
- package/lib/md010.js +38 -38
- package/lib/md011.js +38 -38
- package/lib/md012.js +32 -32
- package/lib/md013.js +99 -99
- package/lib/md014.js +53 -53
- package/lib/md018.js +34 -34
- package/lib/md019.js +39 -39
- package/lib/md020.js +62 -62
- package/lib/md021.js +60 -60
- package/lib/md022.js +56 -56
- package/lib/md023.js +38 -38
- package/lib/md024.js +38 -38
- package/lib/md025.js +32 -32
- package/lib/md026.js +40 -40
- package/lib/md027.js +56 -56
- package/lib/md028.js +38 -38
- package/lib/md029.js +66 -66
- package/lib/md030.js +50 -50
- package/lib/md031.js +39 -39
- package/lib/md032.js +50 -50
- package/lib/md033.js +45 -45
- package/lib/md034.js +61 -61
- package/lib/md035.js +21 -21
- package/lib/md036.js +56 -56
- package/lib/md037.js +150 -89
- package/lib/md038.js +68 -68
- package/lib/md039.js +64 -64
- package/lib/md040.js +18 -18
- package/lib/md041.js +31 -31
- package/lib/md042.js +41 -41
- package/lib/md043.js +45 -45
- package/lib/md044.js +77 -71
- package/lib/md045.js +18 -18
- package/lib/md046.js +32 -32
- package/lib/md047.js +28 -28
- package/lib/md048.js +29 -29
- package/lib/rules.js +61 -61
- package/package.json +73 -67
- package/schema/build-config-schema.js +405 -405
- package/schema/markdownlint-config-schema.json +1550 -1550
- package/style/all.json +5 -5
- package/style/cirosantilli.json +22 -22
- package/style/relaxed.json +13 -13
package/lib/md030.js
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
"use strict";
|
|
4
|
-
|
|
5
|
-
const { addErrorDetailIf } = require("../helpers");
|
|
6
|
-
const { flattenedLists } = require("./cache");
|
|
7
|
-
|
|
8
|
-
module.exports = {
|
|
9
|
-
"names": [ "MD030", "list-marker-space" ],
|
|
10
|
-
"description": "Spaces after list markers",
|
|
11
|
-
"tags": [ "ol", "ul", "whitespace" ],
|
|
12
|
-
"function": function MD030(params, onError) {
|
|
13
|
-
const ulSingle = Number(params.config.ul_single || 1);
|
|
14
|
-
const olSingle = Number(params.config.ol_single || 1);
|
|
15
|
-
const ulMulti = Number(params.config.ul_multi || 1);
|
|
16
|
-
const olMulti = Number(params.config.ol_multi || 1);
|
|
17
|
-
flattenedLists().forEach((list) => {
|
|
18
|
-
const lineCount = list.lastLineIndex - list.open.map[0];
|
|
19
|
-
const allSingle = lineCount === list.items.length;
|
|
20
|
-
const expectedSpaces = list.unordered ?
|
|
21
|
-
(allSingle ? ulSingle : ulMulti) :
|
|
22
|
-
(allSingle ? olSingle : olMulti);
|
|
23
|
-
list.items.forEach((item) => {
|
|
24
|
-
const { line, lineNumber } = item;
|
|
25
|
-
const match = /^[\s>]*\S+(\s*)/.exec(line);
|
|
26
|
-
const [ { "length": matchLength }, { "length": actualSpaces } ] = match;
|
|
27
|
-
if (matchLength < line.length) {
|
|
28
|
-
let fixInfo = null;
|
|
29
|
-
if (expectedSpaces !== actualSpaces) {
|
|
30
|
-
fixInfo = {
|
|
31
|
-
"editColumn": matchLength - actualSpaces + 1,
|
|
32
|
-
"deleteCount": actualSpaces,
|
|
33
|
-
"insertText": "".padEnd(expectedSpaces)
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
addErrorDetailIf(
|
|
37
|
-
onError,
|
|
38
|
-
lineNumber,
|
|
39
|
-
expectedSpaces,
|
|
40
|
-
actualSpaces,
|
|
41
|
-
null,
|
|
42
|
-
null,
|
|
43
|
-
[ 1, matchLength ],
|
|
44
|
-
fixInfo
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
};
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { addErrorDetailIf } = require("../helpers");
|
|
6
|
+
const { flattenedLists } = require("./cache");
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
"names": [ "MD030", "list-marker-space" ],
|
|
10
|
+
"description": "Spaces after list markers",
|
|
11
|
+
"tags": [ "ol", "ul", "whitespace" ],
|
|
12
|
+
"function": function MD030(params, onError) {
|
|
13
|
+
const ulSingle = Number(params.config.ul_single || 1);
|
|
14
|
+
const olSingle = Number(params.config.ol_single || 1);
|
|
15
|
+
const ulMulti = Number(params.config.ul_multi || 1);
|
|
16
|
+
const olMulti = Number(params.config.ol_multi || 1);
|
|
17
|
+
flattenedLists().forEach((list) => {
|
|
18
|
+
const lineCount = list.lastLineIndex - list.open.map[0];
|
|
19
|
+
const allSingle = lineCount === list.items.length;
|
|
20
|
+
const expectedSpaces = list.unordered ?
|
|
21
|
+
(allSingle ? ulSingle : ulMulti) :
|
|
22
|
+
(allSingle ? olSingle : olMulti);
|
|
23
|
+
list.items.forEach((item) => {
|
|
24
|
+
const { line, lineNumber } = item;
|
|
25
|
+
const match = /^[\s>]*\S+(\s*)/.exec(line);
|
|
26
|
+
const [ { "length": matchLength }, { "length": actualSpaces } ] = match;
|
|
27
|
+
if (matchLength < line.length) {
|
|
28
|
+
let fixInfo = null;
|
|
29
|
+
if (expectedSpaces !== actualSpaces) {
|
|
30
|
+
fixInfo = {
|
|
31
|
+
"editColumn": matchLength - actualSpaces + 1,
|
|
32
|
+
"deleteCount": actualSpaces,
|
|
33
|
+
"insertText": "".padEnd(expectedSpaces)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
addErrorDetailIf(
|
|
37
|
+
onError,
|
|
38
|
+
lineNumber,
|
|
39
|
+
expectedSpaces,
|
|
40
|
+
actualSpaces,
|
|
41
|
+
null,
|
|
42
|
+
null,
|
|
43
|
+
[ 1, matchLength ],
|
|
44
|
+
fixInfo
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
};
|
package/lib/md031.js
CHANGED
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
"use strict";
|
|
4
|
-
|
|
5
|
-
const { addErrorContext, forEachLine, isBlankLine } = require("../helpers");
|
|
6
|
-
const { lineMetadata } = require("./cache");
|
|
7
|
-
|
|
8
|
-
const codeFencePrefixRe = /^(.*?)\s*[`~]/;
|
|
9
|
-
|
|
10
|
-
module.exports = {
|
|
11
|
-
"names": [ "MD031", "blanks-around-fences" ],
|
|
12
|
-
"description": "Fenced code blocks should be surrounded by blank lines",
|
|
13
|
-
"tags": [ "code", "blank_lines" ],
|
|
14
|
-
"function": function MD031(params, onError) {
|
|
15
|
-
const listItems = params.config.list_items;
|
|
16
|
-
const includeListItems = (listItems === undefined) ? true : !!listItems;
|
|
17
|
-
const { lines } = params;
|
|
18
|
-
forEachLine(lineMetadata(), (line, i, inCode, onFence, inTable, inItem) => {
|
|
19
|
-
const onTopFence = (onFence > 0);
|
|
20
|
-
const onBottomFence = (onFence < 0);
|
|
21
|
-
if ((includeListItems || !inItem) &&
|
|
22
|
-
((onTopFence && !isBlankLine(lines[i - 1])) ||
|
|
23
|
-
(onBottomFence && !isBlankLine(lines[i + 1])))) {
|
|
24
|
-
const [ , prefix ] = line.match(codeFencePrefixRe);
|
|
25
|
-
addErrorContext(
|
|
26
|
-
onError,
|
|
27
|
-
i + 1,
|
|
28
|
-
lines[i].trim(),
|
|
29
|
-
null,
|
|
30
|
-
null,
|
|
31
|
-
null,
|
|
32
|
-
{
|
|
33
|
-
"lineNumber": i + (onTopFence ? 1 : 2),
|
|
34
|
-
"insertText": `${prefix}\n`
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
};
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { addErrorContext, forEachLine, isBlankLine } = require("../helpers");
|
|
6
|
+
const { lineMetadata } = require("./cache");
|
|
7
|
+
|
|
8
|
+
const codeFencePrefixRe = /^(.*?)\s*[`~]/;
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
"names": [ "MD031", "blanks-around-fences" ],
|
|
12
|
+
"description": "Fenced code blocks should be surrounded by blank lines",
|
|
13
|
+
"tags": [ "code", "blank_lines" ],
|
|
14
|
+
"function": function MD031(params, onError) {
|
|
15
|
+
const listItems = params.config.list_items;
|
|
16
|
+
const includeListItems = (listItems === undefined) ? true : !!listItems;
|
|
17
|
+
const { lines } = params;
|
|
18
|
+
forEachLine(lineMetadata(), (line, i, inCode, onFence, inTable, inItem) => {
|
|
19
|
+
const onTopFence = (onFence > 0);
|
|
20
|
+
const onBottomFence = (onFence < 0);
|
|
21
|
+
if ((includeListItems || !inItem) &&
|
|
22
|
+
((onTopFence && !isBlankLine(lines[i - 1])) ||
|
|
23
|
+
(onBottomFence && !isBlankLine(lines[i + 1])))) {
|
|
24
|
+
const [ , prefix ] = line.match(codeFencePrefixRe);
|
|
25
|
+
addErrorContext(
|
|
26
|
+
onError,
|
|
27
|
+
i + 1,
|
|
28
|
+
lines[i].trim(),
|
|
29
|
+
null,
|
|
30
|
+
null,
|
|
31
|
+
null,
|
|
32
|
+
{
|
|
33
|
+
"lineNumber": i + (onTopFence ? 1 : 2),
|
|
34
|
+
"insertText": `${prefix}\n`
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
};
|
package/lib/md032.js
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
"use strict";
|
|
4
|
-
|
|
5
|
-
const { addErrorContext, isBlankLine } = require("../helpers");
|
|
6
|
-
const { flattenedLists } = require("./cache");
|
|
7
|
-
|
|
8
|
-
const quotePrefixRe = /^[>\s]*/;
|
|
9
|
-
|
|
10
|
-
module.exports = {
|
|
11
|
-
"names": [ "MD032", "blanks-around-lists" ],
|
|
12
|
-
"description": "Lists should be surrounded by blank lines",
|
|
13
|
-
"tags": [ "bullet", "ul", "ol", "blank_lines" ],
|
|
14
|
-
"function": function MD032(params, onError) {
|
|
15
|
-
const { lines } = params;
|
|
16
|
-
flattenedLists().filter((list) => !list.nesting).forEach((list) => {
|
|
17
|
-
const firstIndex = list.open.map[0];
|
|
18
|
-
if (!isBlankLine(lines[firstIndex - 1])) {
|
|
19
|
-
const line = lines[firstIndex];
|
|
20
|
-
const quotePrefix = line.match(quotePrefixRe)[0].trimRight();
|
|
21
|
-
addErrorContext(
|
|
22
|
-
onError,
|
|
23
|
-
firstIndex + 1,
|
|
24
|
-
line.trim(),
|
|
25
|
-
null,
|
|
26
|
-
null,
|
|
27
|
-
null,
|
|
28
|
-
{
|
|
29
|
-
"insertText": `${quotePrefix}\n`
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
const lastIndex = list.lastLineIndex - 1;
|
|
33
|
-
if (!isBlankLine(lines[lastIndex + 1])) {
|
|
34
|
-
const line = lines[lastIndex];
|
|
35
|
-
const quotePrefix = line.match(quotePrefixRe)[0].trimRight();
|
|
36
|
-
addErrorContext(
|
|
37
|
-
onError,
|
|
38
|
-
lastIndex + 1,
|
|
39
|
-
line.trim(),
|
|
40
|
-
null,
|
|
41
|
-
null,
|
|
42
|
-
null,
|
|
43
|
-
{
|
|
44
|
-
"lineNumber": lastIndex + 2,
|
|
45
|
-
"insertText": `${quotePrefix}\n`
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
};
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { addErrorContext, isBlankLine } = require("../helpers");
|
|
6
|
+
const { flattenedLists } = require("./cache");
|
|
7
|
+
|
|
8
|
+
const quotePrefixRe = /^[>\s]*/;
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
"names": [ "MD032", "blanks-around-lists" ],
|
|
12
|
+
"description": "Lists should be surrounded by blank lines",
|
|
13
|
+
"tags": [ "bullet", "ul", "ol", "blank_lines" ],
|
|
14
|
+
"function": function MD032(params, onError) {
|
|
15
|
+
const { lines } = params;
|
|
16
|
+
flattenedLists().filter((list) => !list.nesting).forEach((list) => {
|
|
17
|
+
const firstIndex = list.open.map[0];
|
|
18
|
+
if (!isBlankLine(lines[firstIndex - 1])) {
|
|
19
|
+
const line = lines[firstIndex];
|
|
20
|
+
const quotePrefix = line.match(quotePrefixRe)[0].trimRight();
|
|
21
|
+
addErrorContext(
|
|
22
|
+
onError,
|
|
23
|
+
firstIndex + 1,
|
|
24
|
+
line.trim(),
|
|
25
|
+
null,
|
|
26
|
+
null,
|
|
27
|
+
null,
|
|
28
|
+
{
|
|
29
|
+
"insertText": `${quotePrefix}\n`
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
const lastIndex = list.lastLineIndex - 1;
|
|
33
|
+
if (!isBlankLine(lines[lastIndex + 1])) {
|
|
34
|
+
const line = lines[lastIndex];
|
|
35
|
+
const quotePrefix = line.match(quotePrefixRe)[0].trimRight();
|
|
36
|
+
addErrorContext(
|
|
37
|
+
onError,
|
|
38
|
+
lastIndex + 1,
|
|
39
|
+
line.trim(),
|
|
40
|
+
null,
|
|
41
|
+
null,
|
|
42
|
+
null,
|
|
43
|
+
{
|
|
44
|
+
"lineNumber": lastIndex + 2,
|
|
45
|
+
"insertText": `${quotePrefix}\n`
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
};
|
package/lib/md033.js
CHANGED
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
"use strict";
|
|
4
|
-
|
|
5
|
-
const { addError, forEachLine, unescapeMarkdown } = require("../helpers");
|
|
6
|
-
const { lineMetadata } = require("./cache");
|
|
7
|
-
|
|
8
|
-
const htmlElementRe = /<(([A-Za-z][A-Za-z0-9-]*)(?:\s[^>]*)?)\/?>/g;
|
|
9
|
-
const linkDestinationRe = /]\(\s*$/;
|
|
10
|
-
const inlineCodeRe = /^[^`]*(`+[^`]+`+[^`]+)*`+[^`]*$/;
|
|
11
|
-
// See https://spec.commonmark.org/0.29/#autolinks
|
|
12
|
-
const emailAddressRe =
|
|
13
|
-
// eslint-disable-next-line max-len
|
|
14
|
-
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
15
|
-
|
|
16
|
-
module.exports = {
|
|
17
|
-
"names": [ "MD033", "no-inline-html" ],
|
|
18
|
-
"description": "Inline HTML",
|
|
19
|
-
"tags": [ "html" ],
|
|
20
|
-
"function": function MD033(params, onError) {
|
|
21
|
-
let allowedElements = params.config.allowed_elements;
|
|
22
|
-
allowedElements = Array.isArray(allowedElements) ? allowedElements : [];
|
|
23
|
-
allowedElements = allowedElements.map((element) => element.toLowerCase());
|
|
24
|
-
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
|
25
|
-
let match = null;
|
|
26
|
-
// eslint-disable-next-line no-unmodified-loop-condition
|
|
27
|
-
while (!inCode && ((match = htmlElementRe.exec(line)) !== null)) {
|
|
28
|
-
const [ tag, content, element ] = match;
|
|
29
|
-
if (!allowedElements.includes(element.toLowerCase()) &&
|
|
30
|
-
!tag.endsWith("\\>") &&
|
|
31
|
-
!emailAddressRe.test(content)) {
|
|
32
|
-
const prefix = line.substring(0, match.index);
|
|
33
|
-
if (!linkDestinationRe.test(prefix) && !inlineCodeRe.test(prefix)) {
|
|
34
|
-
const unescaped = unescapeMarkdown(prefix + "<", "_");
|
|
35
|
-
if (!unescaped.endsWith("_") &&
|
|
36
|
-
((unescaped + "`").match(/`/g).length % 2)) {
|
|
37
|
-
addError(onError, lineIndex + 1, "Element: " + element,
|
|
38
|
-
null, [ match.index + 1, tag.length ]);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
};
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { addError, forEachLine, unescapeMarkdown } = require("../helpers");
|
|
6
|
+
const { lineMetadata } = require("./cache");
|
|
7
|
+
|
|
8
|
+
const htmlElementRe = /<(([A-Za-z][A-Za-z0-9-]*)(?:\s[^>]*)?)\/?>/g;
|
|
9
|
+
const linkDestinationRe = /]\(\s*$/;
|
|
10
|
+
const inlineCodeRe = /^[^`]*(`+[^`]+`+[^`]+)*`+[^`]*$/;
|
|
11
|
+
// See https://spec.commonmark.org/0.29/#autolinks
|
|
12
|
+
const emailAddressRe =
|
|
13
|
+
// eslint-disable-next-line max-len
|
|
14
|
+
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
15
|
+
|
|
16
|
+
module.exports = {
|
|
17
|
+
"names": [ "MD033", "no-inline-html" ],
|
|
18
|
+
"description": "Inline HTML",
|
|
19
|
+
"tags": [ "html" ],
|
|
20
|
+
"function": function MD033(params, onError) {
|
|
21
|
+
let allowedElements = params.config.allowed_elements;
|
|
22
|
+
allowedElements = Array.isArray(allowedElements) ? allowedElements : [];
|
|
23
|
+
allowedElements = allowedElements.map((element) => element.toLowerCase());
|
|
24
|
+
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
|
25
|
+
let match = null;
|
|
26
|
+
// eslint-disable-next-line no-unmodified-loop-condition
|
|
27
|
+
while (!inCode && ((match = htmlElementRe.exec(line)) !== null)) {
|
|
28
|
+
const [ tag, content, element ] = match;
|
|
29
|
+
if (!allowedElements.includes(element.toLowerCase()) &&
|
|
30
|
+
!tag.endsWith("\\>") &&
|
|
31
|
+
!emailAddressRe.test(content)) {
|
|
32
|
+
const prefix = line.substring(0, match.index);
|
|
33
|
+
if (!linkDestinationRe.test(prefix) && !inlineCodeRe.test(prefix)) {
|
|
34
|
+
const unescaped = unescapeMarkdown(prefix + "<", "_");
|
|
35
|
+
if (!unescaped.endsWith("_") &&
|
|
36
|
+
((unescaped + "`").match(/`/g).length % 2)) {
|
|
37
|
+
addError(onError, lineIndex + 1, "Element: " + element,
|
|
38
|
+
null, [ match.index + 1, tag.length ]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
};
|
package/lib/md034.js
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
"use strict";
|
|
4
|
-
|
|
5
|
-
const { addErrorContext, bareUrlRe, filterTokens } = require("../helpers");
|
|
6
|
-
|
|
7
|
-
module.exports = {
|
|
8
|
-
"names": [ "MD034", "no-bare-urls" ],
|
|
9
|
-
"description": "Bare URL used",
|
|
10
|
-
"tags": [ "links", "url" ],
|
|
11
|
-
"function": function MD034(params, onError) {
|
|
12
|
-
filterTokens(params, "inline", (token) => {
|
|
13
|
-
let inLink = false;
|
|
14
|
-
token.children.forEach((child) => {
|
|
15
|
-
const { content, line, lineNumber, type } = child;
|
|
16
|
-
let match = null;
|
|
17
|
-
if (type === "link_open") {
|
|
18
|
-
inLink = true;
|
|
19
|
-
} else if (type === "link_close") {
|
|
20
|
-
inLink = false;
|
|
21
|
-
} else if ((type === "text") && !inLink) {
|
|
22
|
-
while ((match = bareUrlRe.exec(content)) !== null) {
|
|
23
|
-
const [ bareUrl ] = match;
|
|
24
|
-
const matchIndex = match.index;
|
|
25
|
-
const bareUrlLength = bareUrl.length;
|
|
26
|
-
// Allow "[https://example.com]" to avoid conflicts with
|
|
27
|
-
// MD011/no-reversed-links; allow quoting as another way
|
|
28
|
-
// of deliberately including a bare URL
|
|
29
|
-
const leftChar = content[matchIndex - 1];
|
|
30
|
-
const rightChar = content[matchIndex + bareUrlLength];
|
|
31
|
-
if (
|
|
32
|
-
!((leftChar === "[") && (rightChar === "]")) &&
|
|
33
|
-
!((leftChar === "\"") && (rightChar === "\"")) &&
|
|
34
|
-
!((leftChar === "'") && (rightChar === "'"))
|
|
35
|
-
) {
|
|
36
|
-
const index = line.indexOf(content);
|
|
37
|
-
const range = (index === -1) ? null : [
|
|
38
|
-
index + matchIndex + 1,
|
|
39
|
-
bareUrlLength
|
|
40
|
-
];
|
|
41
|
-
const fixInfo = range ? {
|
|
42
|
-
"editColumn": range[0],
|
|
43
|
-
"deleteCount": range[1],
|
|
44
|
-
"insertText": `<${bareUrl}>`
|
|
45
|
-
} : null;
|
|
46
|
-
addErrorContext(
|
|
47
|
-
onError,
|
|
48
|
-
lineNumber,
|
|
49
|
-
bareUrl,
|
|
50
|
-
null,
|
|
51
|
-
null,
|
|
52
|
-
range,
|
|
53
|
-
fixInfo
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
};
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { addErrorContext, bareUrlRe, filterTokens } = require("../helpers");
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
"names": [ "MD034", "no-bare-urls" ],
|
|
9
|
+
"description": "Bare URL used",
|
|
10
|
+
"tags": [ "links", "url" ],
|
|
11
|
+
"function": function MD034(params, onError) {
|
|
12
|
+
filterTokens(params, "inline", (token) => {
|
|
13
|
+
let inLink = false;
|
|
14
|
+
token.children.forEach((child) => {
|
|
15
|
+
const { content, line, lineNumber, type } = child;
|
|
16
|
+
let match = null;
|
|
17
|
+
if (type === "link_open") {
|
|
18
|
+
inLink = true;
|
|
19
|
+
} else if (type === "link_close") {
|
|
20
|
+
inLink = false;
|
|
21
|
+
} else if ((type === "text") && !inLink) {
|
|
22
|
+
while ((match = bareUrlRe.exec(content)) !== null) {
|
|
23
|
+
const [ bareUrl ] = match;
|
|
24
|
+
const matchIndex = match.index;
|
|
25
|
+
const bareUrlLength = bareUrl.length;
|
|
26
|
+
// Allow "[https://example.com]" to avoid conflicts with
|
|
27
|
+
// MD011/no-reversed-links; allow quoting as another way
|
|
28
|
+
// of deliberately including a bare URL
|
|
29
|
+
const leftChar = content[matchIndex - 1];
|
|
30
|
+
const rightChar = content[matchIndex + bareUrlLength];
|
|
31
|
+
if (
|
|
32
|
+
!((leftChar === "[") && (rightChar === "]")) &&
|
|
33
|
+
!((leftChar === "\"") && (rightChar === "\"")) &&
|
|
34
|
+
!((leftChar === "'") && (rightChar === "'"))
|
|
35
|
+
) {
|
|
36
|
+
const index = line.indexOf(content);
|
|
37
|
+
const range = (index === -1) ? null : [
|
|
38
|
+
index + matchIndex + 1,
|
|
39
|
+
bareUrlLength
|
|
40
|
+
];
|
|
41
|
+
const fixInfo = range ? {
|
|
42
|
+
"editColumn": range[0],
|
|
43
|
+
"deleteCount": range[1],
|
|
44
|
+
"insertText": `<${bareUrl}>`
|
|
45
|
+
} : null;
|
|
46
|
+
addErrorContext(
|
|
47
|
+
onError,
|
|
48
|
+
lineNumber,
|
|
49
|
+
bareUrl,
|
|
50
|
+
null,
|
|
51
|
+
null,
|
|
52
|
+
range,
|
|
53
|
+
fixInfo
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
};
|
package/lib/md035.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
"use strict";
|
|
4
|
-
|
|
5
|
-
const { addErrorDetailIf, filterTokens } = require("../helpers");
|
|
6
|
-
|
|
7
|
-
module.exports = {
|
|
8
|
-
"names": [ "MD035", "hr-style" ],
|
|
9
|
-
"description": "Horizontal rule style",
|
|
10
|
-
"tags": [ "hr" ],
|
|
11
|
-
"function": function MD035(params, onError) {
|
|
12
|
-
let style = String(params.config.style || "consistent");
|
|
13
|
-
filterTokens(params, "hr", function forToken(token) {
|
|
14
|
-
const lineTrim = token.line.trim();
|
|
15
|
-
if (style === "consistent") {
|
|
16
|
-
style = lineTrim;
|
|
17
|
-
}
|
|
18
|
-
addErrorDetailIf(onError, token.lineNumber, style, lineTrim);
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
};
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { addErrorDetailIf, filterTokens } = require("../helpers");
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
"names": [ "MD035", "hr-style" ],
|
|
9
|
+
"description": "Horizontal rule style",
|
|
10
|
+
"tags": [ "hr" ],
|
|
11
|
+
"function": function MD035(params, onError) {
|
|
12
|
+
let style = String(params.config.style || "consistent");
|
|
13
|
+
filterTokens(params, "hr", function forToken(token) {
|
|
14
|
+
const lineTrim = token.line.trim();
|
|
15
|
+
if (style === "consistent") {
|
|
16
|
+
style = lineTrim;
|
|
17
|
+
}
|
|
18
|
+
addErrorDetailIf(onError, token.lineNumber, style, lineTrim);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
};
|
package/lib/md036.js
CHANGED
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
"use strict";
|
|
4
|
-
|
|
5
|
-
const { addErrorContext, allPunctuation } = require("../helpers");
|
|
6
|
-
|
|
7
|
-
module.exports = {
|
|
8
|
-
"names": [ "MD036", "no-emphasis-as-heading", "no-emphasis-as-header" ],
|
|
9
|
-
"description": "Emphasis used instead of a heading",
|
|
10
|
-
"tags": [ "headings", "headers", "emphasis" ],
|
|
11
|
-
"function": function MD036(params, onError) {
|
|
12
|
-
let punctuation = params.config.punctuation;
|
|
13
|
-
punctuation =
|
|
14
|
-
String((punctuation === undefined) ? allPunctuation : punctuation);
|
|
15
|
-
const re = new RegExp("[" + punctuation + "]$");
|
|
16
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
17
|
-
function base(token) {
|
|
18
|
-
if (token.type === "paragraph_open") {
|
|
19
|
-
return function inParagraph(t) {
|
|
20
|
-
// Always paragraph_open/inline/paragraph_close,
|
|
21
|
-
const children = t.children.filter(function notEmptyText(child) {
|
|
22
|
-
return (child.type !== "text") || (child.content !== "");
|
|
23
|
-
});
|
|
24
|
-
if ((children.length === 3) &&
|
|
25
|
-
((children[0].type === "strong_open") ||
|
|
26
|
-
(children[0].type === "em_open")) &&
|
|
27
|
-
(children[1].type === "text") &&
|
|
28
|
-
!re.test(children[1].content)) {
|
|
29
|
-
addErrorContext(onError, t.lineNumber,
|
|
30
|
-
children[1].content);
|
|
31
|
-
}
|
|
32
|
-
return base;
|
|
33
|
-
};
|
|
34
|
-
} else if (token.type === "blockquote_open") {
|
|
35
|
-
return function inBlockquote(t) {
|
|
36
|
-
if (t.type !== "blockquote_close") {
|
|
37
|
-
return inBlockquote;
|
|
38
|
-
}
|
|
39
|
-
return base;
|
|
40
|
-
};
|
|
41
|
-
} else if (token.type === "list_item_open") {
|
|
42
|
-
return function inListItem(t) {
|
|
43
|
-
if (t.type !== "list_item_close") {
|
|
44
|
-
return inListItem;
|
|
45
|
-
}
|
|
46
|
-
return base;
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
return base;
|
|
50
|
-
}
|
|
51
|
-
let state = base;
|
|
52
|
-
params.tokens.forEach(function forToken(token) {
|
|
53
|
-
state = state(token);
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
};
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { addErrorContext, allPunctuation } = require("../helpers");
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
"names": [ "MD036", "no-emphasis-as-heading", "no-emphasis-as-header" ],
|
|
9
|
+
"description": "Emphasis used instead of a heading",
|
|
10
|
+
"tags": [ "headings", "headers", "emphasis" ],
|
|
11
|
+
"function": function MD036(params, onError) {
|
|
12
|
+
let punctuation = params.config.punctuation;
|
|
13
|
+
punctuation =
|
|
14
|
+
String((punctuation === undefined) ? allPunctuation : punctuation);
|
|
15
|
+
const re = new RegExp("[" + punctuation + "]$");
|
|
16
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
17
|
+
function base(token) {
|
|
18
|
+
if (token.type === "paragraph_open") {
|
|
19
|
+
return function inParagraph(t) {
|
|
20
|
+
// Always paragraph_open/inline/paragraph_close,
|
|
21
|
+
const children = t.children.filter(function notEmptyText(child) {
|
|
22
|
+
return (child.type !== "text") || (child.content !== "");
|
|
23
|
+
});
|
|
24
|
+
if ((children.length === 3) &&
|
|
25
|
+
((children[0].type === "strong_open") ||
|
|
26
|
+
(children[0].type === "em_open")) &&
|
|
27
|
+
(children[1].type === "text") &&
|
|
28
|
+
!re.test(children[1].content)) {
|
|
29
|
+
addErrorContext(onError, t.lineNumber,
|
|
30
|
+
children[1].content);
|
|
31
|
+
}
|
|
32
|
+
return base;
|
|
33
|
+
};
|
|
34
|
+
} else if (token.type === "blockquote_open") {
|
|
35
|
+
return function inBlockquote(t) {
|
|
36
|
+
if (t.type !== "blockquote_close") {
|
|
37
|
+
return inBlockquote;
|
|
38
|
+
}
|
|
39
|
+
return base;
|
|
40
|
+
};
|
|
41
|
+
} else if (token.type === "list_item_open") {
|
|
42
|
+
return function inListItem(t) {
|
|
43
|
+
if (t.type !== "list_item_close") {
|
|
44
|
+
return inListItem;
|
|
45
|
+
}
|
|
46
|
+
return base;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return base;
|
|
50
|
+
}
|
|
51
|
+
let state = base;
|
|
52
|
+
params.tokens.forEach(function forToken(token) {
|
|
53
|
+
state = state(token);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
};
|