markdownlint 0.41.1 → 0.42.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/CHANGELOG.md +18 -0
- package/CONTRIBUTING.md +62 -77
- package/README.md +7 -7
- package/doc/CustomRules.md +6 -4
- package/doc/Rules.md +76 -35
- package/doc/md010.md +0 -1
- package/doc/md024.md +1 -1
- package/doc/md043.md +47 -9
- package/doc/md051.md +19 -19
- package/doc/md055.md +6 -3
- package/doc/md060.md +3 -2
- package/helpers/README.md +2 -2
- package/helpers/helpers.cjs +16 -7
- package/helpers/micromark-helpers.cjs +7 -10
- package/helpers/package.json +1 -5
- package/lib/configuration-strict.d.ts +124 -112
- package/lib/constants.mjs +1 -1
- package/lib/defer-require.cjs +1 -0
- package/lib/exports.d.mts +29 -1
- package/lib/markdownit.cjs +8 -1
- package/lib/markdownlint.d.mts +337 -195
- package/lib/markdownlint.mjs +78 -85
- package/lib/md007.mjs +2 -2
- package/lib/md009.mjs +2 -3
- package/lib/md010.mjs +1 -1
- package/lib/md011.mjs +10 -7
- package/lib/md012.mjs +1 -1
- package/lib/md013.mjs +13 -9
- package/lib/md018.mjs +1 -1
- package/lib/md020.mjs +1 -1
- package/lib/md022.mjs +5 -6
- package/lib/md025.mjs +1 -1
- package/lib/md027.mjs +1 -1
- package/lib/md028.mjs +1 -2
- package/lib/md029.mjs +1 -2
- package/lib/md030.mjs +4 -4
- package/lib/md031.mjs +1 -1
- package/lib/md033.mjs +1 -1
- package/lib/md034.mjs +1 -1
- package/lib/md039.mjs +5 -1
- package/lib/md041.mjs +1 -1
- package/lib/md043.mjs +98 -44
- package/lib/md044.mjs +2 -2
- package/lib/md048.mjs +1 -3
- package/lib/md051.mjs +2 -3
- package/lib/md055.mjs +11 -1
- package/lib/md056.mjs +1 -1
- package/lib/md058.mjs +1 -1
- package/lib/md060.mjs +24 -4
- package/lib/micromark-parse.mjs +1 -1
- package/lib/resolve-module.d.cts +15 -10
- package/package.json +31 -34
- package/schema/.markdownlint.jsonc +54 -54
- package/schema/.markdownlint.yaml +54 -54
- package/schema/markdownlint-config-schema-strict.json +126 -118
- package/schema/markdownlint-config-schema.json +126 -118
package/lib/md030.mjs
CHANGED
|
@@ -10,10 +10,10 @@ export default {
|
|
|
10
10
|
"tags": [ "ol", "ul", "whitespace" ],
|
|
11
11
|
"parser": "micromark",
|
|
12
12
|
"function": function MD030(params, onError) {
|
|
13
|
-
const ulSingle = Number(params.config.ul_single
|
|
14
|
-
const olSingle = Number(params.config.ol_single
|
|
15
|
-
const ulMulti = Number(params.config.ul_multi
|
|
16
|
-
const olMulti = Number(params.config.ol_multi
|
|
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
17
|
for (const list of filterByTypesCached([ "listOrdered", "listUnordered" ])) {
|
|
18
18
|
const ordered = (list.type === "listOrdered");
|
|
19
19
|
const listItemPrefixes =
|
package/lib/md031.mjs
CHANGED
|
@@ -45,7 +45,7 @@ export default {
|
|
|
45
45
|
"parser": "micromark",
|
|
46
46
|
"function": function MD031(params, onError) {
|
|
47
47
|
const listItems = params.config.list_items;
|
|
48
|
-
const includeListItems = (listItems === undefined)
|
|
48
|
+
const includeListItems = (listItems === undefined) || !!listItems;
|
|
49
49
|
const { lines } = params;
|
|
50
50
|
for (const codeBlock of filterByTypesCached([ "codeFenced" ])) {
|
|
51
51
|
if (includeListItems || !(getParentOfType(codeBlock, [ "listOrdered", "listUnordered" ]))) {
|
package/lib/md033.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { addError, nextLinesRe } from "../helpers/helpers.cjs";
|
|
|
4
4
|
import { getHtmlTagInfo, getParentOfType } from "../helpers/micromark-helpers.cjs";
|
|
5
5
|
import { filterByTypesCached } from "./cache.mjs";
|
|
6
6
|
|
|
7
|
-
/** @typedef {import("micromark-extension-gfm-table")} */
|
|
7
|
+
/** @typedef {typeof import("micromark-extension-gfm-table")} _ambient_ */
|
|
8
8
|
|
|
9
9
|
// eslint-disable-next-line jsdoc/reject-any-type
|
|
10
10
|
const toLowerCaseStringArray = (/** @type {any} */ arr) => Array.isArray(arr) ? arr.map((elm) => String(elm).toLowerCase()) : [];
|
package/lib/md034.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { addErrorContext } from "../helpers/helpers.cjs";
|
|
|
4
4
|
import { filterByPredicate, getHtmlTagInfo, inHtmlFlow } from "../helpers/micromark-helpers.cjs";
|
|
5
5
|
|
|
6
6
|
/** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
|
|
7
|
-
/** @typedef {import("micromark-extension-gfm-autolink-literal")} */
|
|
7
|
+
/** @typedef {typeof import("micromark-extension-gfm-autolink-literal")} _ambient_ */
|
|
8
8
|
|
|
9
9
|
/** @type {import("markdownlint").Rule} */
|
|
10
10
|
export default {
|
package/lib/md039.mjs
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
+
import { re } from "re2js";
|
|
3
4
|
import { addErrorContext } from "../helpers/helpers.cjs";
|
|
4
5
|
import { filterByTypesCached } from "./cache.mjs";
|
|
5
6
|
|
|
7
|
+
const startRe = re`^[^\S\r\n]+`;
|
|
8
|
+
const endRe = re`[^\S\r\n]+$`;
|
|
9
|
+
|
|
6
10
|
/**
|
|
7
11
|
* Adds an error for a label space issue.
|
|
8
12
|
*
|
|
@@ -12,7 +16,7 @@ import { filterByTypesCached } from "./cache.mjs";
|
|
|
12
16
|
* @param {boolean} isStart True iff error is at the start of the link.
|
|
13
17
|
*/
|
|
14
18
|
function addLabelSpaceError(onError, label, labelText, isStart) {
|
|
15
|
-
const match =
|
|
19
|
+
const match = (isStart ? startRe : endRe).exec(labelText.text);
|
|
16
20
|
const range = match ?
|
|
17
21
|
[
|
|
18
22
|
(isStart ? (labelText.startColumn) : (labelText.endColumn - match[0].length)),
|
package/lib/md041.mjs
CHANGED
|
@@ -31,7 +31,7 @@ export default {
|
|
|
31
31
|
"parser": "micromark",
|
|
32
32
|
"function": function MD041(params, onError) {
|
|
33
33
|
const allowPreamble = !!params.config.allow_preamble;
|
|
34
|
-
const level = Number(params.config.level
|
|
34
|
+
const level = Number(params.config.level ?? 1);
|
|
35
35
|
const { tokens } = params.parsers.micromark;
|
|
36
36
|
if (
|
|
37
37
|
!frontMatterHasTitle(
|
package/lib/md043.mjs
CHANGED
|
@@ -1,9 +1,32 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { addError, addErrorDetailIf } from "../helpers/helpers.cjs";
|
|
4
4
|
import { getHeadingLevel, getHeadingText } from "../helpers/micromark-helpers.cjs";
|
|
5
5
|
import { filterByTypesCached } from "./cache.mjs";
|
|
6
6
|
|
|
7
|
+
export const headingsItemsRe = /^(?:[*+?]|\^+|[#%]{1,6}\s+\S.*)$/u;
|
|
8
|
+
const prefixedHeadingPartsRe = /^([#%]{1,6})\s+(\S.*)$/u;
|
|
9
|
+
const loopHeadingRe = /^\^+$/u;
|
|
10
|
+
const canMatchNothingHeadingsRe = /^(?:\*|\^+)$/u;
|
|
11
|
+
const maximumLoopsAllowed = 1000;
|
|
12
|
+
|
|
13
|
+
const headingIsExpected = (/** @type {string} */ actual, /** @type {string} */ expected, /** @type {boolean} */ matchCase) => {
|
|
14
|
+
if (expected.startsWith("%")) {
|
|
15
|
+
// Regular expression comparison
|
|
16
|
+
const [ , actualLevel, actualText ] = prefixedHeadingPartsRe.exec(actual) || [];
|
|
17
|
+
const [ , expectedLevel, expectedText ] = prefixedHeadingPartsRe.exec(expected) || [];
|
|
18
|
+
return (
|
|
19
|
+
(actualLevel.length === expectedLevel.length) &&
|
|
20
|
+
// eslint-disable-next-line unicorn/no-unreadable-new-expression
|
|
21
|
+
(new RegExp(expectedText, `${matchCase ? "" : "i"}u`)).test(actualText)
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
// Text comparison
|
|
25
|
+
const actualLower = matchCase ? actual : actual.toLowerCase();
|
|
26
|
+
const expectedLower = matchCase ? expected : expected.toLowerCase();
|
|
27
|
+
return actualLower === expectedLower;
|
|
28
|
+
};
|
|
29
|
+
|
|
7
30
|
/** @type {import("markdownlint").Rule} */
|
|
8
31
|
export default {
|
|
9
32
|
"names": [ "MD043", "required-headings" ],
|
|
@@ -11,62 +34,93 @@ export default {
|
|
|
11
34
|
"tags": [ "headings" ],
|
|
12
35
|
"parser": "micromark",
|
|
13
36
|
"function": function MD043(params, onError) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
37
|
+
/** @type {string[] | null | undefined} */
|
|
38
|
+
const headings = params.config.headings;
|
|
39
|
+
if (!headings) {
|
|
17
40
|
return;
|
|
18
41
|
}
|
|
19
|
-
const
|
|
42
|
+
const requiredHeadings = headings.map((heading) => headingsItemsRe.test(heading) ? heading : "[Invalid syntax]");
|
|
43
|
+
const matchCase = Boolean(params.config.match_case);
|
|
20
44
|
let i = 0;
|
|
21
|
-
let
|
|
45
|
+
let remainingLoopsAllowed = maximumLoopsAllowed;
|
|
46
|
+
let allowAnyMatchFallback = false;
|
|
22
47
|
let hasError = false;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
48
|
+
const getExpected = (/** @type {boolean} */ skipLoopHeadings) => {
|
|
49
|
+
let expected = null;
|
|
50
|
+
do {
|
|
51
|
+
expected = requiredHeadings[i++] || "[No heading]";
|
|
52
|
+
// eslint-disable-next-line no-unmodified-loop-condition
|
|
53
|
+
} while (skipLoopHeadings && loopHeadingRe.test(expected));
|
|
54
|
+
return expected;
|
|
55
|
+
};
|
|
26
56
|
for (const heading of filterByTypesCached([ "atxHeading", "setextHeading" ])) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
57
|
+
const headingText = getHeadingText(heading);
|
|
58
|
+
const headingLevel = getHeadingLevel(heading);
|
|
59
|
+
const actual = `${"".padEnd(headingLevel, "#")} ${headingText}`;
|
|
60
|
+
let expected = getExpected(false);
|
|
61
|
+
if (expected.startsWith("^")) {
|
|
62
|
+
// Handle loop
|
|
63
|
+
const current = i;
|
|
64
|
+
const nextExpected = getExpected(true);
|
|
65
|
+
if (headingIsExpected(actual, nextExpected, matchCase)) {
|
|
66
|
+
// No need to loop (again)
|
|
67
|
+
expected = nextExpected;
|
|
68
|
+
} else {
|
|
69
|
+
// Try to loop to previous matching marker
|
|
70
|
+
remainingLoopsAllowed--;
|
|
71
|
+
let j = current - 2;
|
|
72
|
+
for (; j >= 0; j--) {
|
|
73
|
+
if (requiredHeadings[j] === expected) {
|
|
74
|
+
// Perform loop
|
|
75
|
+
i = j + 1;
|
|
76
|
+
expected = getExpected(false);
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
38
79
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
80
|
+
if (j < 0) {
|
|
81
|
+
// No matching loop marker
|
|
82
|
+
expected = nextExpected;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (remainingLoopsAllowed < 0) {
|
|
87
|
+
// Too many loops performed
|
|
88
|
+
addError(onError, heading.startLine, "Too many loops", `Limit: ${maximumLoopsAllowed}`);
|
|
89
|
+
hasError = true;
|
|
90
|
+
break;
|
|
91
|
+
} else if (expected === "*") {
|
|
92
|
+
// Handle "zero or more of anything"
|
|
93
|
+
const nextExpected = getExpected(true);
|
|
94
|
+
if (!headingIsExpected(actual, nextExpected, matchCase)) {
|
|
95
|
+
allowAnyMatchFallback = true;
|
|
46
96
|
i--;
|
|
47
|
-
} else {
|
|
48
|
-
addErrorDetailIf(
|
|
49
|
-
onError,
|
|
50
|
-
heading.startLine,
|
|
51
|
-
expected,
|
|
52
|
-
actual
|
|
53
|
-
);
|
|
54
|
-
hasError = true;
|
|
55
97
|
}
|
|
98
|
+
} else if (expected === "+") {
|
|
99
|
+
// Handle "one or more of anything"
|
|
100
|
+
allowAnyMatchFallback = true;
|
|
101
|
+
} else if (expected === "?") {
|
|
102
|
+
// Handle "exactly one of anything"
|
|
103
|
+
// Nothing to do
|
|
104
|
+
} else if (headingIsExpected(actual, expected, matchCase)) {
|
|
105
|
+
// Handle successful match
|
|
106
|
+
allowAnyMatchFallback = false;
|
|
107
|
+
} else if (allowAnyMatchFallback) {
|
|
108
|
+
// Handle "anything" match by restoring index
|
|
109
|
+
i--;
|
|
110
|
+
} else {
|
|
111
|
+
// Report heading mismatch
|
|
112
|
+
addErrorDetailIf(onError, heading.startLine, expected, actual);
|
|
113
|
+
hasError = true;
|
|
114
|
+
break;
|
|
56
115
|
}
|
|
57
116
|
}
|
|
58
|
-
const
|
|
117
|
+
const remainingRequiredHeadings = requiredHeadings.slice(i).filter((heading) => !canMatchNothingHeadingsRe.test(heading));
|
|
59
118
|
if (
|
|
60
119
|
!hasError &&
|
|
61
|
-
(
|
|
62
|
-
((extraHeadings === 1) && (requiredHeadings[i] !== "*"))) &&
|
|
63
|
-
(anyHeadings || !requiredHeadings.every((heading) => heading === "*"))
|
|
120
|
+
(remainingRequiredHeadings.length > 0)
|
|
64
121
|
) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
params.lines.length,
|
|
68
|
-
requiredHeadings[i]
|
|
69
|
-
);
|
|
122
|
+
// Report unmatched heading(s)
|
|
123
|
+
addErrorDetailIf(onError, params.lines.length, remainingRequiredHeadings[0], "[End of file]");
|
|
70
124
|
}
|
|
71
125
|
}
|
|
72
126
|
};
|
package/lib/md044.mjs
CHANGED
|
@@ -24,10 +24,10 @@ export default {
|
|
|
24
24
|
}
|
|
25
25
|
const codeBlocks = params.config.code_blocks;
|
|
26
26
|
const includeCodeBlocks =
|
|
27
|
-
(codeBlocks === undefined)
|
|
27
|
+
(codeBlocks === undefined) || !!codeBlocks;
|
|
28
28
|
const htmlElements = params.config.html_elements;
|
|
29
29
|
const includeHtmlElements =
|
|
30
|
-
(htmlElements === undefined)
|
|
30
|
+
(htmlElements === undefined) || !!htmlElements;
|
|
31
31
|
const scannedTypes = new Set([ "data" ]);
|
|
32
32
|
if (includeCodeBlocks) {
|
|
33
33
|
scannedTypes.add("codeFlowValue");
|
package/lib/md048.mjs
CHANGED
|
@@ -30,9 +30,7 @@ export default {
|
|
|
30
30
|
let expectedStyle = style;
|
|
31
31
|
const codeFenceds = filterByTypesCached([ "codeFenced" ]);
|
|
32
32
|
for (const codeFenced of codeFenceds) {
|
|
33
|
-
const codeFencedFenceSequence
|
|
34
|
-
getDescendantsByType(codeFenced, [ "codeFencedFence", "codeFencedFenceSequence" ])[0];
|
|
35
|
-
const { startLine, text } = codeFencedFenceSequence;
|
|
33
|
+
const { startLine, text } = getDescendantsByType(codeFenced, [ "codeFencedFence", "codeFencedFenceSequence" ])[0];
|
|
36
34
|
if (expectedStyle === "consistent") {
|
|
37
35
|
expectedStyle = fencedCodeBlockStyleFor(text);
|
|
38
36
|
}
|
package/lib/md051.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { filterByTypesCached } from "./cache.mjs";
|
|
|
7
7
|
// Regular expression for identifying HTML anchor names
|
|
8
8
|
const idRe = getHtmlAttributeRe("id");
|
|
9
9
|
const nameRe = getHtmlAttributeRe("name");
|
|
10
|
-
const anchorRe = /\{(#[a-z\d]+(?:[-_][a-z\d]+)*)\}/gu;
|
|
10
|
+
const anchorRe = /\{(#[a-z\d]+(?:[-_]+[a-z\d]+)*)\}/gu;
|
|
11
11
|
const lineFragmentRe = /^#(?:L\d+(?:C\d+)?-L\d+(?:C\d+)?|L\d+)$/;
|
|
12
12
|
|
|
13
13
|
// Sets for filtering heading tokens during conversion
|
|
@@ -17,8 +17,7 @@ const tokensInclude = new Set(
|
|
|
17
17
|
);
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* Converts a Markdown heading into an HTML fragment according to the rules
|
|
21
|
-
* used by GitHub.
|
|
20
|
+
* Converts a Markdown heading into an HTML fragment according to the rules used by GitHub.
|
|
22
21
|
*
|
|
23
22
|
* @param {import("markdownlint").MicromarkToken} headingText Heading text token.
|
|
24
23
|
* @returns {string} Fragment string for heading.
|
package/lib/md055.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
import { addErrorDetailIf } from "../helpers/helpers.cjs";
|
|
4
|
+
import { getParentOfType } from "../helpers/micromark-helpers.cjs";
|
|
4
5
|
import { filterByTypesCached } from "./cache.mjs";
|
|
5
6
|
|
|
6
7
|
/** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
|
|
7
|
-
/** @typedef {import("micromark-extension-gfm-table")} */
|
|
8
|
+
/** @typedef {typeof import("micromark-extension-gfm-table")} _ambient_ */
|
|
8
9
|
|
|
9
10
|
const whitespaceTypes = new Set([ "linePrefix", "whitespace" ]);
|
|
10
11
|
const ignoreWhitespace = (/** @type {MicromarkToken[]} */ tokens) => tokens.filter(
|
|
@@ -27,8 +28,17 @@ export default {
|
|
|
27
28
|
((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "trailing_only"));
|
|
28
29
|
let expectedTrailingPipe =
|
|
29
30
|
((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "leading_only"));
|
|
31
|
+
let currentTable = null;
|
|
30
32
|
const rows = filterByTypesCached([ "tableDelimiterRow", "tableRow" ]);
|
|
31
33
|
for (const row of rows) {
|
|
34
|
+
if (style === "per_table") {
|
|
35
|
+
// Reset style for each new table
|
|
36
|
+
const rowTable = getParentOfType(row, [ "table" ]);
|
|
37
|
+
if (rowTable !== currentTable) {
|
|
38
|
+
expectedStyle = "consistent";
|
|
39
|
+
currentTable = rowTable;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
32
42
|
// The following uses of first/lastOrNothing lack fallback handling
|
|
33
43
|
// because it seems not to be possible (i.e., 0% coverage)
|
|
34
44
|
const firstCell = firstOrNothing(row.children);
|
package/lib/md056.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { filterByTypesCached } from "./cache.mjs";
|
|
|
6
6
|
|
|
7
7
|
const makeRange = (/** @type {number} */ start, /** @type {number} */ end) => [ start, end - start + 1 ];
|
|
8
8
|
|
|
9
|
-
/** @typedef {import("micromark-extension-gfm-table")} */
|
|
9
|
+
/** @typedef {typeof import("micromark-extension-gfm-table")} _ambient_ */
|
|
10
10
|
|
|
11
11
|
/** @type {import("markdownlint").Rule} */
|
|
12
12
|
export default {
|
package/lib/md058.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { addErrorContext, isBlankLine } from "../helpers/helpers.cjs";
|
|
|
4
4
|
import { getBlockQuotePrefixText } from "../helpers/micromark-helpers.cjs";
|
|
5
5
|
import { filterByTypesCached } from "./cache.mjs";
|
|
6
6
|
|
|
7
|
-
/** @typedef {import("micromark-extension-gfm-table")} */
|
|
7
|
+
/** @typedef {typeof import("micromark-extension-gfm-table")} _ambient_ */
|
|
8
8
|
|
|
9
9
|
/** @type {import("markdownlint").Rule} */
|
|
10
10
|
export default {
|
package/lib/md060.mjs
CHANGED
|
@@ -4,21 +4,35 @@ import { filterByTypes } from "../helpers/micromark-helpers.cjs";
|
|
|
4
4
|
import { filterByTypesCached } from "./cache.mjs";
|
|
5
5
|
import stringWidth from "string-width";
|
|
6
6
|
|
|
7
|
-
/** @typedef {import("micromark-extension-gfm-table")} */
|
|
7
|
+
/** @typedef {typeof import("micromark-extension-gfm-table")} _ambient_ */
|
|
8
8
|
/** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
|
|
9
9
|
/** @typedef {import("markdownlint").RuleOnErrorInfo} RuleOnErrorInfo */
|
|
10
10
|
/** @typedef {import("markdownlint").RuleOnErrorFixInfo} RuleOnErrorFixInfo */
|
|
11
11
|
|
|
12
|
+
// Regular expression to match text that could represent an unordered list item prefix
|
|
13
|
+
const unorderedListPrefix = /^[>\s]*[-+*]$/;
|
|
14
|
+
|
|
12
15
|
/**
|
|
13
16
|
* Adds a RuleOnErrorInfo object to a list of RuleOnErrorInfo objects.
|
|
14
17
|
*
|
|
15
18
|
* @param {RuleOnErrorInfo[]} errors List of errors.
|
|
19
|
+
* @param {readonly string[]} lines File/string lines.
|
|
16
20
|
* @param {number} lineNumber Line number.
|
|
17
21
|
* @param {number} column Column number.
|
|
18
22
|
* @param {string} detail Detail message.
|
|
19
23
|
* @param {RuleOnErrorFixInfo} [fixInfo] Fix information.
|
|
24
|
+
* @returns {void}
|
|
20
25
|
*/
|
|
21
|
-
function addError(errors, lineNumber, column, detail, fixInfo) {
|
|
26
|
+
function addError(errors, lines, lineNumber, column, detail, fixInfo) {
|
|
27
|
+
if (
|
|
28
|
+
fixInfo &&
|
|
29
|
+
(fixInfo.insertText === " ") &&
|
|
30
|
+
fixInfo.editColumn &&
|
|
31
|
+
unorderedListPrefix.test(lines[lineNumber - 1].slice(0, fixInfo.editColumn - 1))
|
|
32
|
+
) {
|
|
33
|
+
// Do not apply edits that would change a table cell into an unordered list item
|
|
34
|
+
fixInfo = undefined;
|
|
35
|
+
}
|
|
22
36
|
errors.push({
|
|
23
37
|
lineNumber,
|
|
24
38
|
detail,
|
|
@@ -70,7 +84,7 @@ function checkStyleAligned(lines, rows, detail) {
|
|
|
70
84
|
const rowDividerColumns = getTableDividerColumns(lines, row);
|
|
71
85
|
for (const dividerColumn of rowDividerColumns) {
|
|
72
86
|
if ((remainingHeaderDividerColumns.size > 0) && !remainingHeaderDividerColumns.delete(dividerColumn.effective)) {
|
|
73
|
-
addError(errorInfos, row.startLine, dividerColumn.actual, detail);
|
|
87
|
+
addError(errorInfos, lines, row.startLine, dividerColumn.actual, detail);
|
|
74
88
|
}
|
|
75
89
|
}
|
|
76
90
|
}
|
|
@@ -128,6 +142,7 @@ export default {
|
|
|
128
142
|
if (previous.text.length !== 1) {
|
|
129
143
|
addError(
|
|
130
144
|
errorsIfCompact,
|
|
145
|
+
lines,
|
|
131
146
|
startLine,
|
|
132
147
|
startColumn,
|
|
133
148
|
"Table pipe has extra space to the left for style \"compact\"",
|
|
@@ -136,6 +151,7 @@ export default {
|
|
|
136
151
|
}
|
|
137
152
|
addError(
|
|
138
153
|
errorsIfTight,
|
|
154
|
+
lines,
|
|
139
155
|
startLine,
|
|
140
156
|
startColumn,
|
|
141
157
|
"Table pipe has space to the left for style \"tight\"",
|
|
@@ -144,6 +160,7 @@ export default {
|
|
|
144
160
|
} else {
|
|
145
161
|
addError(
|
|
146
162
|
errorsIfCompact,
|
|
163
|
+
lines,
|
|
147
164
|
startLine,
|
|
148
165
|
startColumn,
|
|
149
166
|
"Table pipe is missing space to the left for style \"compact\"",
|
|
@@ -158,6 +175,7 @@ export default {
|
|
|
158
175
|
if (next.text.length !== 1) {
|
|
159
176
|
addError(
|
|
160
177
|
errorsIfCompact,
|
|
178
|
+
lines,
|
|
161
179
|
startLine,
|
|
162
180
|
startColumn,
|
|
163
181
|
"Table pipe has extra space to the right for style \"compact\"",
|
|
@@ -166,6 +184,7 @@ export default {
|
|
|
166
184
|
}
|
|
167
185
|
addError(
|
|
168
186
|
errorsIfTight,
|
|
187
|
+
lines,
|
|
169
188
|
startLine,
|
|
170
189
|
startColumn,
|
|
171
190
|
"Table pipe has space to the right for style \"tight\"",
|
|
@@ -175,6 +194,7 @@ export default {
|
|
|
175
194
|
} else {
|
|
176
195
|
addError(
|
|
177
196
|
errorsIfCompact,
|
|
197
|
+
lines,
|
|
178
198
|
startLine,
|
|
179
199
|
startColumn,
|
|
180
200
|
"Table pipe is missing space to the right for style \"compact\"",
|
|
@@ -191,7 +211,7 @@ export default {
|
|
|
191
211
|
let errorInfos = errorsIfAligned;
|
|
192
212
|
if (
|
|
193
213
|
styleCompactAllowed &&
|
|
194
|
-
((errorsIfCompact.length < errorInfos.length)
|
|
214
|
+
(!styleAlignedAllowed || (errorsIfCompact.length < errorInfos.length))
|
|
195
215
|
) {
|
|
196
216
|
errorInfos = errorsIfCompact;
|
|
197
217
|
}
|
package/lib/micromark-parse.mjs
CHANGED
|
@@ -19,7 +19,7 @@ import { flatTokensSymbol, htmlFlowSymbol, newlineRe } from "../helpers/shared.c
|
|
|
19
19
|
/** @typedef {import("micromark-util-types").Token} Token */
|
|
20
20
|
/** @typedef {import("micromark-util-types").Tokenizer} Tokenizer */
|
|
21
21
|
/** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
|
|
22
|
-
/** @typedef {import("./micromark-types.d.mts")} */
|
|
22
|
+
/** @typedef {typeof import("./micromark-types.d.mts")} _ambient_ */
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Gets a modified micromark-extension-directive without support for inline directives.
|
package/lib/resolve-module.d.cts
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
|
+
declare const _exports: {
|
|
2
|
+
resolveModule: typeof resolveModule;
|
|
3
|
+
resolveModuleCustomResolve: typeof resolveModuleCustomResolve;
|
|
4
|
+
};
|
|
5
|
+
export = _exports;
|
|
1
6
|
export type RequireResolveOptions = {
|
|
2
7
|
/**
|
|
3
8
|
* Additional paths to resolve from.
|
|
4
9
|
*/
|
|
5
|
-
paths?: string[]
|
|
10
|
+
paths?: string[];
|
|
6
11
|
};
|
|
7
12
|
export type RequireResolve = (id: string, options: RequireResolveOptions) => string;
|
|
8
|
-
/**
|
|
9
|
-
* Resolves modules according to Node's resolution rules.
|
|
10
|
-
*
|
|
11
|
-
* @param {string} id Module name or path.
|
|
12
|
-
* @param {string[]} [paths] Additional paths to resolve from.
|
|
13
|
-
* @returns {string} Resolved module path.
|
|
14
|
-
*/
|
|
15
|
-
export function resolveModule(id: string, paths?: string[]): string;
|
|
16
13
|
/**
|
|
17
14
|
* @typedef RequireResolveOptions
|
|
18
15
|
* @property {string[]} [paths] Additional paths to resolve from.
|
|
@@ -31,4 +28,12 @@ export function resolveModule(id: string, paths?: string[]): string;
|
|
|
31
28
|
* @param {string[]} [paths] Additional paths to resolve from.
|
|
32
29
|
* @returns {string} Resolved module path.
|
|
33
30
|
*/
|
|
34
|
-
|
|
31
|
+
declare const resolveModuleCustomResolve: (resolve: RequireResolve, id: string, paths?: string[]) => string;
|
|
32
|
+
/**
|
|
33
|
+
* Resolves modules according to Node's resolution rules.
|
|
34
|
+
*
|
|
35
|
+
* @param {string} id Module name or path.
|
|
36
|
+
* @param {string[]} [paths] Additional paths to resolve from.
|
|
37
|
+
* @returns {string} Resolved module path.
|
|
38
|
+
*/
|
|
39
|
+
declare const resolveModule: (id: string, paths?: string[]) => string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markdownlint",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A Node.js style checker and lint tool for Markdown/CommonMark files
|
|
3
|
+
"version": "0.42.0",
|
|
4
|
+
"description": "A Node.js style checker and lint tool for Markdown/CommonMark files",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./lib/exports.mjs",
|
|
@@ -26,21 +26,16 @@
|
|
|
26
26
|
"author": "David Anson (https://dlaa.me/)",
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"homepage": "https://github.com/DavidAnson/markdownlint",
|
|
29
|
-
"repository":
|
|
30
|
-
"type": "git",
|
|
31
|
-
"url": "git+https://github.com/DavidAnson/markdownlint.git"
|
|
32
|
-
},
|
|
33
|
-
"bugs": "https://github.com/DavidAnson/markdownlint/issues",
|
|
29
|
+
"repository": "github:DavidAnson/markdownlint",
|
|
34
30
|
"funding": "https://github.com/sponsors/DavidAnson",
|
|
35
31
|
"scripts": {
|
|
36
32
|
"build-config": "npm run build-config-schema && npm run build-config-example",
|
|
37
33
|
"build-config-example": "node schema/build-config-example.mjs",
|
|
38
34
|
"build-config-schema": "node schema/build-config-schema.mjs",
|
|
39
35
|
"build-declaration": "tsc --project ./declaration/tsconfig.json && node scripts/index.mjs copy dts/lib/exports.d.mts lib/exports.d.mts && node scripts/index.mjs copy dts/lib/exports-async.d.mts lib/exports-async.d.mts && node scripts/index.mjs copy dts/lib/exports-promise.d.mts lib/exports-promise.d.mts && node scripts/index.mjs copy dts/lib/exports-sync.d.mts lib/exports-sync.d.mts && node scripts/index.mjs copy dts/lib/markdownlint.d.mts lib/markdownlint.d.mts && node scripts/index.mjs copy dts/lib/resolve-module.d.cts lib/resolve-module.d.cts && node scripts/index.mjs remove dts",
|
|
40
|
-
"build-demo": "node scripts/index.mjs copy node_modules/markdown-it/dist/markdown-it.min.js demo/markdown-it.min.js && cd demo && webpack --no-stats",
|
|
36
|
+
"build-demo": "node scripts/index.mjs copy node_modules/markdown-it/dist/browser/markdown-it.umd.min.js demo/markdown-it.umd.min.js && cd demo && webpack --no-stats",
|
|
41
37
|
"build-docs": "node doc-build/build-rules.mjs",
|
|
42
38
|
"ci": "concurrently npm:build-demo npm:lint npm:serial-config-docs npm:serial-declaration npm:test npm:test-webpack && git diff --exit-code && echo PASS",
|
|
43
|
-
"clone-test-repos-apache-airflow": "cd test-repos && git clone https://github.com/apache/airflow apache-airflow --depth 1 --no-tags --quiet",
|
|
44
39
|
"clone-test-repos-dotnet-docs": "cd test-repos && git clone https://github.com/dotnet/docs dotnet-docs --depth 1 --no-tags --quiet",
|
|
45
40
|
"clone-test-repos-electron-electron": "cd test-repos && git clone https://github.com/electron/electron electron-electron --depth 1 --no-tags --quiet && cd electron-electron && node ../../scripts/index.mjs delete package.json && npm install --no-save --ignore-scripts @electron/lint-roller",
|
|
46
41
|
"clone-test-repos-eslint-eslint": "cd test-repos && git clone https://github.com/eslint/eslint eslint-eslint --depth 1 --no-tags --quiet",
|
|
@@ -51,9 +46,9 @@
|
|
|
51
46
|
"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",
|
|
52
47
|
"clone-test-repos-webhintio-hint": "cd test-repos && git clone https://github.com/webhintio/hint webhintio-hint --depth 1 --no-tags --quiet",
|
|
53
48
|
"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",
|
|
54
|
-
"clone-test-repos": "mkdir test-repos && cd test-repos && npm run clone-test-repos-
|
|
49
|
+
"clone-test-repos": "mkdir test-repos && cd test-repos && npm run clone-test-repos-dotnet-docs && npm run clone-test-repos-electron-electron && npm run clone-test-repos-eslint-eslint && npm run clone-test-repos-mdn-content && 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-v8-v8-dev && npm run clone-test-repos-webhintio-hint && npm run clone-test-repos-webpack-webpack-js-org",
|
|
55
50
|
"example": "cd example && node standalone.mjs",
|
|
56
|
-
"lint": "eslint --max-warnings 0",
|
|
51
|
+
"lint": "cross-env RECHECK_BACKEND=pure eslint --max-warnings 0",
|
|
57
52
|
"lint-test-repos": "node --test test/markdownlint-test-repos-*.mjs",
|
|
58
53
|
"serial-config-docs": "npm run build-config && npm run build-docs",
|
|
59
54
|
"serial-declaration": "npm run build-declaration && npm run test-declaration",
|
|
@@ -71,52 +66,54 @@
|
|
|
71
66
|
"node": ">=22"
|
|
72
67
|
},
|
|
73
68
|
"dependencies": {
|
|
74
|
-
"micromark": "
|
|
75
|
-
"micromark-core-commonmark": "2.0.3",
|
|
69
|
+
"micromark-core-commonmark": "2.0.4",
|
|
76
70
|
"micromark-extension-directive": "4.0.0",
|
|
77
71
|
"micromark-extension-gfm-autolink-literal": "2.1.0",
|
|
78
72
|
"micromark-extension-gfm-footnote": "2.1.0",
|
|
79
|
-
"micromark-extension-gfm-table": "2.1.
|
|
73
|
+
"micromark-extension-gfm-table": "2.1.2",
|
|
80
74
|
"micromark-extension-math": "3.1.0",
|
|
81
|
-
"micromark-util-types": "2.0.
|
|
82
|
-
"
|
|
75
|
+
"micromark-util-types": "2.0.3",
|
|
76
|
+
"micromark": "4.0.3",
|
|
77
|
+
"re2js": "2.8.6",
|
|
78
|
+
"string-width": "8.3.0"
|
|
83
79
|
},
|
|
84
80
|
"devDependencies": {
|
|
85
81
|
"@eslint/js": "10.0.1",
|
|
86
82
|
"@stylistic/eslint-plugin": "5.10.0",
|
|
87
|
-
"@types/markdown-it": "14.1.2",
|
|
88
83
|
"ajv": "8.20.0",
|
|
89
84
|
"character-entities": "2.0.2",
|
|
90
|
-
"concurrently": "10.0.
|
|
91
|
-
"
|
|
92
|
-
"eslint-node-test": "0.1
|
|
93
|
-
"eslint-
|
|
94
|
-
"eslint-plugin-
|
|
95
|
-
"eslint-plugin-
|
|
96
|
-
"eslint-plugin-
|
|
85
|
+
"concurrently": "10.0.5",
|
|
86
|
+
"cross-env": "10.1.0",
|
|
87
|
+
"eslint-node-test": "1.0.1",
|
|
88
|
+
"eslint-package-json": "2.0.0",
|
|
89
|
+
"eslint-plugin-jsdoc": "65.1.0",
|
|
90
|
+
"eslint-plugin-n": "18.4.1",
|
|
91
|
+
"eslint-plugin-redos": "4.5.0",
|
|
92
|
+
"eslint-plugin-regexp": "3.3.1",
|
|
93
|
+
"eslint-plugin-unicorn": "77.0.0",
|
|
94
|
+
"eslint": "10.12.0",
|
|
97
95
|
"gemoji": "8.1.0",
|
|
98
|
-
"globby": "16.2.
|
|
99
|
-
"js-yaml": "5.2
|
|
100
|
-
"json-schema-to-typescript": "
|
|
96
|
+
"globby": "16.2.4",
|
|
97
|
+
"js-yaml": "5.4.2",
|
|
98
|
+
"json-schema-to-typescript": "16.0.0",
|
|
101
99
|
"json-stringify-safe": "5.0.1",
|
|
102
100
|
"jsonc-parser": "3.3.1",
|
|
103
|
-
"markdown-it": "14.3.0",
|
|
104
101
|
"markdown-it-for-inline": "2.0.1",
|
|
105
102
|
"markdown-it-sub": "2.0.0",
|
|
106
103
|
"markdown-it-sup": "2.0.0",
|
|
104
|
+
"markdown-it": "15.0.2",
|
|
107
105
|
"markdownlint-rule-extended-ascii": "0.2.1",
|
|
108
106
|
"nano-spawn": "2.1.0",
|
|
107
|
+
"smol-toml": "1.9.0",
|
|
109
108
|
"terser-webpack-plugin": "5.6.1",
|
|
110
|
-
"
|
|
111
|
-
"
|
|
112
|
-
"webpack": "5.
|
|
113
|
-
"webpack-cli": "7.1.0"
|
|
109
|
+
"typescript": "7.0.2",
|
|
110
|
+
"webpack-cli": "7.2.3",
|
|
111
|
+
"webpack": "5.111.1"
|
|
114
112
|
},
|
|
115
113
|
"keywords": [
|
|
116
114
|
"markdown",
|
|
117
115
|
"lint",
|
|
118
116
|
"md",
|
|
119
|
-
"
|
|
120
|
-
"markdownlint"
|
|
117
|
+
"commonmark"
|
|
121
118
|
]
|
|
122
119
|
}
|