markdownlint 0.23.1 → 0.24.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/README.md +35 -10
- package/demo/markdownlint-browser.js +253 -166
- package/doc/Prettier.md +23 -0
- package/doc/Rules.md +16 -1
- package/helpers/helpers.js +47 -5
- package/helpers/package.json +1 -1
- package/lib/cache.js +18 -9
- package/lib/markdownlint.d.ts +24 -8
- package/lib/markdownlint.js +106 -38
- package/lib/md010.js +5 -1
- package/lib/md011.js +31 -27
- package/lib/md037.js +14 -2
- package/lib/md043.js +8 -3
- package/lib/md044.js +54 -71
- package/package.json +24 -16
- package/schema/.markdownlint.jsonc +4 -2
- package/schema/.markdownlint.yaml +3 -1
- package/schema/markdownlint-config-schema.json +13 -3
package/lib/md011.js
CHANGED
|
@@ -2,40 +2,44 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addError,
|
|
6
|
-
|
|
5
|
+
const { addError, forEachLine, overlapsAnyRange } = require("../helpers");
|
|
6
|
+
const { inlineCodeSpanRanges, lineMetadata } = require("./cache");
|
|
7
7
|
|
|
8
|
-
const reversedLinkRe =
|
|
8
|
+
const reversedLinkRe =
|
|
9
|
+
/(^|[^\\])\(([^)]+)\)\[([^\]^][^\]]*)](?!\()/g;
|
|
9
10
|
|
|
10
11
|
module.exports = {
|
|
11
12
|
"names": [ "MD011", "no-reversed-links" ],
|
|
12
13
|
"description": "Reversed link syntax",
|
|
13
14
|
"tags": [ "links" ],
|
|
14
15
|
"function": function MD011(params, onError) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
16
|
+
const exclusions = inlineCodeSpanRanges();
|
|
17
|
+
forEachLine(lineMetadata(), (line, lineIndex, inCode, onFence) => {
|
|
18
|
+
if (!inCode && !onFence) {
|
|
19
|
+
let match = null;
|
|
20
|
+
while ((match = reversedLinkRe.exec(line)) !== null) {
|
|
21
|
+
const [ reversedLink, preChar, linkText, linkDestination ] = match;
|
|
22
|
+
const index = match.index + preChar.length;
|
|
23
|
+
const length = match[0].length - preChar.length;
|
|
24
|
+
if (
|
|
25
|
+
!linkText.endsWith("\\") &&
|
|
26
|
+
!linkDestination.endsWith("\\") &&
|
|
27
|
+
!overlapsAnyRange(exclusions, lineIndex, index, length)
|
|
28
|
+
) {
|
|
29
|
+
addError(
|
|
30
|
+
onError,
|
|
31
|
+
lineIndex + 1,
|
|
32
|
+
reversedLink.slice(preChar.length),
|
|
33
|
+
null,
|
|
34
|
+
[ index + 1, length ],
|
|
35
|
+
{
|
|
36
|
+
"editColumn": index + 1,
|
|
37
|
+
"deleteCount": length,
|
|
38
|
+
"insertText": `[${linkText}](${linkDestination})`
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
39
43
|
}
|
|
40
44
|
});
|
|
41
45
|
}
|
package/lib/md037.js
CHANGED
|
@@ -78,11 +78,23 @@ module.exports = {
|
|
|
78
78
|
lineMetadata(),
|
|
79
79
|
(line, lineIndex, inCode, onFence, inTable, inItem, onBreak, inMath) => {
|
|
80
80
|
const onItemStart = (inItem === 1);
|
|
81
|
-
if (
|
|
81
|
+
if (
|
|
82
|
+
inCode ||
|
|
83
|
+
onFence ||
|
|
84
|
+
inTable ||
|
|
85
|
+
onBreak ||
|
|
86
|
+
onItemStart ||
|
|
87
|
+
isBlankLine(line)
|
|
88
|
+
) {
|
|
82
89
|
// Emphasis resets when leaving a block
|
|
83
90
|
resetRunTracking();
|
|
84
91
|
}
|
|
85
|
-
if (
|
|
92
|
+
if (
|
|
93
|
+
inCode ||
|
|
94
|
+
onFence ||
|
|
95
|
+
onBreak ||
|
|
96
|
+
inMath
|
|
97
|
+
) {
|
|
86
98
|
// Emphasis has no meaning here
|
|
87
99
|
return;
|
|
88
100
|
}
|
package/lib/md043.js
CHANGED
|
@@ -28,8 +28,11 @@ module.exports = {
|
|
|
28
28
|
const actual = levels[heading.tag] + " " + content;
|
|
29
29
|
const expected = getExpected();
|
|
30
30
|
if (expected === "*") {
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
const nextExpected = getExpected();
|
|
32
|
+
if (nextExpected.toLowerCase() !== actual.toLowerCase()) {
|
|
33
|
+
matchAny = true;
|
|
34
|
+
i--;
|
|
35
|
+
}
|
|
33
36
|
} else if (expected === "+") {
|
|
34
37
|
matchAny = true;
|
|
35
38
|
} else if (expected.toLowerCase() === actual.toLowerCase()) {
|
|
@@ -43,9 +46,11 @@ module.exports = {
|
|
|
43
46
|
}
|
|
44
47
|
}
|
|
45
48
|
});
|
|
49
|
+
const extraHeadings = requiredHeadings.length - i;
|
|
46
50
|
if (
|
|
47
51
|
!hasError &&
|
|
48
|
-
(
|
|
52
|
+
((extraHeadings > 1) ||
|
|
53
|
+
((extraHeadings === 1) && (requiredHeadings[i] !== "*"))) &&
|
|
49
54
|
(anyHeadings || !requiredHeadings.every((heading) => heading === "*"))
|
|
50
55
|
) {
|
|
51
56
|
addErrorContext(onError, params.lines.length,
|
package/lib/md044.js
CHANGED
|
@@ -2,11 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { addErrorDetailIf, bareUrlRe, escapeForRegExp,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const startNonWordRe = /^\W/;
|
|
9
|
-
const endNonWordRe = /\W$/;
|
|
5
|
+
const { addErrorDetailIf, bareUrlRe, escapeForRegExp, forEachLine,
|
|
6
|
+
overlapsAnyRange, linkRe, linkReferenceRe } = require("../helpers");
|
|
7
|
+
const { inlineCodeSpanRanges, lineMetadata } = require("./cache");
|
|
10
8
|
|
|
11
9
|
module.exports = {
|
|
12
10
|
"names": [ "MD044", "proper-names" ],
|
|
@@ -15,80 +13,65 @@ module.exports = {
|
|
|
15
13
|
"function": function MD044(params, onError) {
|
|
16
14
|
let names = params.config.names;
|
|
17
15
|
names = Array.isArray(names) ? names : [];
|
|
16
|
+
names.sort((a, b) => (b.length - a.length) || a.localeCompare(b));
|
|
18
17
|
const codeBlocks = params.config.code_blocks;
|
|
19
18
|
const includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
} else if (type === "link_close") {
|
|
29
|
-
inAutoLink = false;
|
|
30
|
-
} else if ((type === "text") && inAutoLink) {
|
|
31
|
-
autolinkText.add(child);
|
|
19
|
+
const exclusions = [];
|
|
20
|
+
forEachLine(lineMetadata(), (line, lineIndex) => {
|
|
21
|
+
if (linkReferenceRe.test(line)) {
|
|
22
|
+
exclusions.push([ lineIndex, 0, line.length ]);
|
|
23
|
+
} else {
|
|
24
|
+
let match = null;
|
|
25
|
+
while ((match = bareUrlRe.exec(line)) !== null) {
|
|
26
|
+
exclusions.push([ lineIndex, match.index, match[0].length ]);
|
|
32
27
|
}
|
|
33
|
-
|
|
28
|
+
while ((match = linkRe.exec(line)) !== null) {
|
|
29
|
+
const [ , text, destination ] = match;
|
|
30
|
+
if (destination) {
|
|
31
|
+
exclusions.push(
|
|
32
|
+
[ lineIndex, match.index + text.length, destination.length ]
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
34
37
|
});
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
if (!includeCodeBlocks) {
|
|
39
|
+
exclusions.push(...inlineCodeSpanRanges());
|
|
40
|
+
}
|
|
41
|
+
for (const name of names) {
|
|
37
42
|
const escapedName = escapeForRegExp(name);
|
|
38
|
-
const startNamePattern =
|
|
39
|
-
const endNamePattern =
|
|
43
|
+
const startNamePattern = /^\W/.test(name) ? "" : "\\b_*";
|
|
44
|
+
const endNamePattern = /\W$/.test(name) ? "" : "_*\\b";
|
|
40
45
|
const namePattern =
|
|
41
|
-
`(${startNamePattern})(${escapedName})
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const fixInfo = (matchIndex === -1) ?
|
|
64
|
-
null :
|
|
65
|
-
{
|
|
66
|
-
"editColumn": matchIndex + 1,
|
|
67
|
-
"deleteCount": matchLength,
|
|
68
|
-
"insertText": name
|
|
69
|
-
};
|
|
70
|
-
addErrorDetailIf(
|
|
71
|
-
onError,
|
|
72
|
-
lineNumber,
|
|
73
|
-
name,
|
|
74
|
-
nameMatch,
|
|
75
|
-
null,
|
|
76
|
-
null,
|
|
77
|
-
range,
|
|
78
|
-
fixInfo
|
|
79
|
-
);
|
|
46
|
+
`(${startNamePattern})(${escapedName})${endNamePattern}`;
|
|
47
|
+
const nameRe = new RegExp(namePattern, "gi");
|
|
48
|
+
forEachLine(lineMetadata(), (line, lineIndex, inCode, onFence) => {
|
|
49
|
+
if (includeCodeBlocks || (!inCode && !onFence)) {
|
|
50
|
+
let match = null;
|
|
51
|
+
while ((match = nameRe.exec(line)) !== null) {
|
|
52
|
+
const [ , leftMatch, nameMatch ] = match;
|
|
53
|
+
const index = match.index + leftMatch.length;
|
|
54
|
+
const length = nameMatch.length;
|
|
55
|
+
if (!overlapsAnyRange(exclusions, lineIndex, index, length)) {
|
|
56
|
+
addErrorDetailIf(
|
|
57
|
+
onError,
|
|
58
|
+
lineIndex + 1,
|
|
59
|
+
name,
|
|
60
|
+
nameMatch,
|
|
61
|
+
null,
|
|
62
|
+
null,
|
|
63
|
+
[ index + 1, length ],
|
|
64
|
+
{
|
|
65
|
+
"editColumn": index + 1,
|
|
66
|
+
"deleteCount": length,
|
|
67
|
+
"insertText": name
|
|
80
68
|
}
|
|
81
|
-
|
|
69
|
+
);
|
|
82
70
|
}
|
|
83
|
-
|
|
71
|
+
exclusions.push([ lineIndex, index, length ]);
|
|
72
|
+
}
|
|
84
73
|
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (includeCodeBlocks) {
|
|
88
|
-
forEachInlineChild(params, "code_inline", forToken);
|
|
89
|
-
filterTokens(params, "code_block", forToken);
|
|
90
|
-
filterTokens(params, "fence", forToken);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
93
76
|
}
|
|
94
77
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markdownlint",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
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",
|
|
@@ -21,8 +21,16 @@
|
|
|
21
21
|
"build-example": "npm install --no-save --ignore-scripts grunt grunt-cli gulp through2",
|
|
22
22
|
"ci": "npm-run-all --continue-on-error --parallel test-cover lint declaration build-config build-demo && git diff --exit-code",
|
|
23
23
|
"clean-test-repos": "rimraf test-repos",
|
|
24
|
-
"clone-test-repos": "
|
|
25
|
-
"clone-test-repos-
|
|
24
|
+
"clone-test-repos-dotnet-docs": "cd test-repos && git clone https://github.com/dotnet/docs dotnet-docs --depth 1 --no-tags --quiet",
|
|
25
|
+
"clone-test-repos-eslint-eslint": "cd test-repos && git clone https://github.com/eslint/eslint eslint-eslint --depth 1 --no-tags --quiet",
|
|
26
|
+
"clone-test-repos-mkdocs-mkdocs": "cd test-repos && git clone https://github.com/mkdocs/mkdocs mkdocs-mkdocs --depth 1 --no-tags --quiet",
|
|
27
|
+
"clone-test-repos-mochajs-mocha": "cd test-repos && git clone https://github.com/mochajs/mocha mochajs-mocha --depth 1 --no-tags --quiet",
|
|
28
|
+
"clone-test-repos-pi-hole-docs": "cd test-repos && git clone https://github.com/pi-hole/docs pi-hole-docs --depth 1 --no-tags --quiet",
|
|
29
|
+
"clone-test-repos-v8-v8-dev": "cd test-repos && git clone https://github.com/v8/v8.dev v8-v8-dev --depth 1 --no-tags --quiet",
|
|
30
|
+
"clone-test-repos-webhintio-hint": "cd test-repos && git clone https://github.com/webhintio/hint webhintio-hint --depth 1 --no-tags --quiet",
|
|
31
|
+
"clone-test-repos-webpack-webpack-js-org": "cd test-repos && git clone https://github.com/webpack/webpack.js.org webpack-webpack-js-org --depth 1 --no-tags --quiet",
|
|
32
|
+
"clone-test-repos": "mkdir test-repos && cd test-repos && npm run clone-test-repos-eslint-eslint && npm run clone-test-repos-mkdocs-mkdocs && npm run clone-test-repos-mochajs-mocha && npm run clone-test-repos-pi-hole-docs && npm run clone-test-repos-webhintio-hint && npm run clone-test-repos-webpack-webpack-js-org",
|
|
33
|
+
"clone-test-repos-large": "npm run clone-test-repos && cd test-repos && npm run clone-test-repos-dotnet-docs && npm run clone-test-repos-v8-v8-dev",
|
|
26
34
|
"declaration": "npm run build-declaration && npm run test-declaration",
|
|
27
35
|
"example": "cd example && node standalone.js && grunt markdownlint --force && gulp markdownlint",
|
|
28
36
|
"lint": "eslint --max-warnings 0 .",
|
|
@@ -36,32 +44,32 @@
|
|
|
36
44
|
"node": ">=10"
|
|
37
45
|
},
|
|
38
46
|
"dependencies": {
|
|
39
|
-
"markdown-it": "12.0
|
|
47
|
+
"markdown-it": "12.2.0"
|
|
40
48
|
},
|
|
41
49
|
"devDependencies": {
|
|
42
50
|
"ava": "~3.15.0",
|
|
43
|
-
"c8": "~7.
|
|
51
|
+
"c8": "~7.8.0",
|
|
44
52
|
"cpy-cli": "~3.1.1",
|
|
45
|
-
"eslint": "~7.
|
|
46
|
-
"eslint-plugin-jsdoc": "~
|
|
53
|
+
"eslint": "~7.32.0",
|
|
54
|
+
"eslint-plugin-jsdoc": "~36.0.7",
|
|
47
55
|
"eslint-plugin-node": "~11.1.0",
|
|
48
|
-
"eslint-plugin-unicorn": "~
|
|
49
|
-
"globby": "~11.0.
|
|
50
|
-
"js-yaml": "~4.
|
|
56
|
+
"eslint-plugin-unicorn": "~35.0.0",
|
|
57
|
+
"globby": "~11.0.4",
|
|
58
|
+
"js-yaml": "~4.1.0",
|
|
51
59
|
"markdown-it-for-inline": "~0.1.1",
|
|
52
60
|
"markdown-it-sub": "~1.0.0",
|
|
53
61
|
"markdown-it-sup": "~1.0.0",
|
|
54
|
-
"markdown-it-texmath": "~0.
|
|
55
|
-
"markdownlint-rule-helpers": "~0.
|
|
62
|
+
"markdown-it-texmath": "~0.9.1",
|
|
63
|
+
"markdownlint-rule-helpers": "~0.14.0",
|
|
56
64
|
"npm-run-all": "~4.1.5",
|
|
57
65
|
"rimraf": "~3.0.2",
|
|
58
66
|
"strip-json-comments": "~3.1.1",
|
|
59
67
|
"toml": "~3.0.0",
|
|
60
|
-
"ts-loader": "~
|
|
68
|
+
"ts-loader": "~9.2.5",
|
|
61
69
|
"tv4": "~1.3.0",
|
|
62
|
-
"typescript": "~4.
|
|
63
|
-
"webpack": "~5.
|
|
64
|
-
"webpack-cli": "~4.
|
|
70
|
+
"typescript": "~4.3.5",
|
|
71
|
+
"webpack": "~5.51.1",
|
|
72
|
+
"webpack-cli": "~4.8.0"
|
|
65
73
|
},
|
|
66
74
|
"keywords": [
|
|
67
75
|
"markdown",
|
|
@@ -55,7 +55,9 @@
|
|
|
55
55
|
// MD010/no-hard-tabs - Hard tabs
|
|
56
56
|
"MD010": {
|
|
57
57
|
// Include code blocks
|
|
58
|
-
"code_blocks": true
|
|
58
|
+
"code_blocks": true,
|
|
59
|
+
// Number of spaces for each hard tab
|
|
60
|
+
"spaces_per_tab": 1
|
|
59
61
|
},
|
|
60
62
|
|
|
61
63
|
// MD011/no-reversed-links - Reversed link syntax
|
|
@@ -244,7 +246,7 @@
|
|
|
244
246
|
|
|
245
247
|
// MD048/code-fence-style - Code fence style
|
|
246
248
|
"MD048": {
|
|
247
|
-
// Code fence
|
|
249
|
+
// Code fence style
|
|
248
250
|
"style": "consistent"
|
|
249
251
|
}
|
|
250
252
|
}
|
|
@@ -50,6 +50,8 @@ MD009:
|
|
|
50
50
|
MD010:
|
|
51
51
|
# Include code blocks
|
|
52
52
|
code_blocks: true
|
|
53
|
+
# Number of spaces for each hard tab
|
|
54
|
+
spaces_per_tab: 1
|
|
53
55
|
|
|
54
56
|
# MD011/no-reversed-links - Reversed link syntax
|
|
55
57
|
MD011: true
|
|
@@ -221,5 +223,5 @@ MD047: true
|
|
|
221
223
|
|
|
222
224
|
# MD048/code-fence-style - Code fence style
|
|
223
225
|
MD048:
|
|
224
|
-
# Code fence
|
|
226
|
+
# Code fence style
|
|
225
227
|
style: "consistent"
|
|
@@ -327,6 +327,11 @@
|
|
|
327
327
|
"description": "Include code blocks",
|
|
328
328
|
"type": "boolean",
|
|
329
329
|
"default": true
|
|
330
|
+
},
|
|
331
|
+
"spaces_per_tab": {
|
|
332
|
+
"description": "Number of spaces for each hard tab",
|
|
333
|
+
"type": "number",
|
|
334
|
+
"default": 1
|
|
330
335
|
}
|
|
331
336
|
},
|
|
332
337
|
"additionalProperties": false
|
|
@@ -343,6 +348,11 @@
|
|
|
343
348
|
"description": "Include code blocks",
|
|
344
349
|
"type": "boolean",
|
|
345
350
|
"default": true
|
|
351
|
+
},
|
|
352
|
+
"spaces_per_tab": {
|
|
353
|
+
"description": "Number of spaces for each hard tab",
|
|
354
|
+
"type": "number",
|
|
355
|
+
"default": 1
|
|
346
356
|
}
|
|
347
357
|
},
|
|
348
358
|
"additionalProperties": false
|
|
@@ -1396,7 +1406,7 @@
|
|
|
1396
1406
|
"default": true,
|
|
1397
1407
|
"properties": {
|
|
1398
1408
|
"style": {
|
|
1399
|
-
"description": "Code fence
|
|
1409
|
+
"description": "Code fence style",
|
|
1400
1410
|
"type": "string",
|
|
1401
1411
|
"enum": [
|
|
1402
1412
|
"consistent",
|
|
@@ -1417,7 +1427,7 @@
|
|
|
1417
1427
|
"default": true,
|
|
1418
1428
|
"properties": {
|
|
1419
1429
|
"style": {
|
|
1420
|
-
"description": "Code fence
|
|
1430
|
+
"description": "Code fence style",
|
|
1421
1431
|
"type": "string",
|
|
1422
1432
|
"enum": [
|
|
1423
1433
|
"consistent",
|
|
@@ -1551,7 +1561,7 @@
|
|
|
1551
1561
|
}
|
|
1552
1562
|
},
|
|
1553
1563
|
"additionalProperties": {
|
|
1554
|
-
"type
|
|
1564
|
+
"type": [
|
|
1555
1565
|
"boolean",
|
|
1556
1566
|
"object"
|
|
1557
1567
|
]
|