markdownlint 0.40.0 → 0.41.1

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.
Files changed (50) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/CONTRIBUTING.md +1 -1
  3. package/README.md +13 -25
  4. package/doc/CustomRules.md +1 -1
  5. package/doc/Rules.md +80 -26
  6. package/doc/md001.md +1 -1
  7. package/doc/md011.md +1 -1
  8. package/doc/md022.md +15 -0
  9. package/doc/md025.md +1 -1
  10. package/doc/md026.md +1 -1
  11. package/doc/md028.md +13 -9
  12. package/doc/md029.md +11 -1
  13. package/doc/md034.md +1 -1
  14. package/doc/md035.md +12 -5
  15. package/doc/md041.md +2 -2
  16. package/doc/md042.md +6 -0
  17. package/doc/md045.md +1 -1
  18. package/doc/md060.md +15 -3
  19. package/helpers/README.md +4 -4
  20. package/helpers/helpers.cjs +55 -49
  21. package/helpers/micromark-helpers.cjs +5 -5
  22. package/helpers/package.json +2 -2
  23. package/helpers/shared.cjs +2 -2
  24. package/lib/cache.mjs +1 -0
  25. package/lib/configuration-strict.d.ts +116 -108
  26. package/lib/constants.mjs +2 -2
  27. package/lib/exports.d.mts +1 -0
  28. package/lib/exports.mjs +1 -0
  29. package/lib/markdownit.cjs +8 -7
  30. package/lib/markdownlint.d.mts +56 -41
  31. package/lib/markdownlint.mjs +40 -105
  32. package/lib/md004.mjs +1 -0
  33. package/lib/md005.mjs +1 -1
  34. package/lib/md019-md021.mjs +1 -0
  35. package/lib/md022.mjs +15 -11
  36. package/lib/md024.mjs +1 -1
  37. package/lib/md029.mjs +37 -25
  38. package/lib/md032.mjs +5 -4
  39. package/lib/md036.mjs +1 -0
  40. package/lib/md037.mjs +1 -2
  41. package/lib/md051.mjs +3 -1
  42. package/lib/md060.mjs +47 -8
  43. package/lib/micromark-parse.mjs +21 -5
  44. package/lib/resolve-module.cjs +4 -3
  45. package/lib/resolve-module.d.cts +1 -1
  46. package/package.json +37 -38
  47. package/schema/.markdownlint.jsonc +55 -53
  48. package/schema/.markdownlint.yaml +77 -75
  49. package/schema/markdownlint-config-schema-strict.json +120 -110
  50. package/schema/markdownlint-config-schema.json +120 -110
package/lib/md022.mjs CHANGED
@@ -11,6 +11,7 @@ const defaultLines = 1;
11
11
  // eslint-disable-next-line jsdoc/reject-any-type
12
12
  const getLinesFunction = (/** @type {any} */ linesParam) => {
13
13
  if (Array.isArray(linesParam)) {
14
+ // eslint-disable-next-line unicorn/no-unreadable-new-expression
14
15
  const linesArray = new Array(6).fill(defaultLines);
15
16
  for (const [ index, value ] of [ ...linesParam.entries() ].slice(0, 6)) {
16
17
  linesArray[index] = value;
@@ -22,6 +23,16 @@ const getLinesFunction = (/** @type {any} */ linesParam) => {
22
23
  return () => lines;
23
24
  };
24
25
 
26
+ const getLine = (/** @type {readonly string[]} */ lines, /** @type {number} */ index, /** @type {readonly string[]} */ frontMatterLines, /** @type {boolean} */ includeFrontMatter) => {
27
+ if ((index >= 0) && (index < lines.length)) {
28
+ return lines[index];
29
+ }
30
+ if (includeFrontMatter && (frontMatterLines.length > 0) && (index < 0) && (index >= -frontMatterLines.length)) {
31
+ return frontMatterLines[frontMatterLines.length + index];
32
+ }
33
+ return "";
34
+ };
35
+
25
36
  /** @type {import("markdownlint").Rule} */
26
37
  export default {
27
38
  "names": [ "MD022", "blanks-around-headings" ],
@@ -31,7 +42,8 @@ export default {
31
42
  "function": function MD022(params, onError) {
32
43
  const getLinesAbove = getLinesFunction(params.config.lines_above);
33
44
  const getLinesBelow = getLinesFunction(params.config.lines_below);
34
- const { lines } = params;
45
+ const includeFrontMatter = !!params.config.include_front_matter;
46
+ const { lines, frontMatterLines } = params;
35
47
  const blockQuotePrefixes = filterByTypesCached([ "blockQuotePrefix", "linePrefix" ]);
36
48
  for (const heading of filterByTypesCached([ "atxHeading", "setextHeading" ])) {
37
49
  const { startLine, endLine } = heading;
@@ -41,11 +53,7 @@ export default {
41
53
  const linesAbove = getLinesAbove(heading);
42
54
  if (linesAbove >= 0) {
43
55
  let actualAbove = 0;
44
- for (
45
- let i = 0;
46
- (i < linesAbove) && isBlankLine(lines[startLine - 2 - i]);
47
- i++
48
- ) {
56
+ for (let i = 0; (i < linesAbove) && isBlankLine(getLine(lines, startLine - 2 - i, frontMatterLines, includeFrontMatter)); i++) {
49
57
  actualAbove++;
50
58
  }
51
59
  addErrorDetailIf(
@@ -70,11 +78,7 @@ export default {
70
78
  const linesBelow = getLinesBelow(heading);
71
79
  if (linesBelow >= 0) {
72
80
  let actualBelow = 0;
73
- for (
74
- let i = 0;
75
- (i < linesBelow) && isBlankLine(lines[endLine + i]);
76
- i++
77
- ) {
81
+ for (let i = 0; (i < linesBelow) && isBlankLine(getLine(lines, endLine + i, frontMatterLines, false)); i++) {
78
82
  actualBelow++;
79
83
  }
80
84
  addErrorDetailIf(
package/lib/md024.mjs CHANGED
@@ -11,7 +11,7 @@ export default {
11
11
  "tags": [ "headings" ],
12
12
  "parser": "micromark",
13
13
  "function": function MD024(params, onError) {
14
- const siblingsOnly = !!params.config.siblings_only || false;
14
+ const siblingsOnly = !!params.config.siblings_only;
15
15
  const knownContents = [ null, [] ];
16
16
  let lastLevel = 1;
17
17
  let knownContent = knownContents[lastLevel];
package/lib/md029.mjs CHANGED
@@ -9,18 +9,22 @@ const listStyleExamples = {
9
9
  "ordered": "1/2/3",
10
10
  "zero": "0/0/0"
11
11
  };
12
+ const listStyles = Object.keys(listStyleExamples);
12
13
 
13
14
  /**
14
15
  * Gets the column and text of an ordered list item prefix token.
15
16
  *
16
17
  * @param {import("markdownlint").MicromarkToken} listItemPrefix List item prefix token.
17
- * @returns {{column: number, value: number}} List item value column and text.
18
+ * @returns {{startColumn: number, endColumn: number, text: string, number: number}} List item value column and text.
18
19
  */
19
20
  function getOrderedListItemValue(listItemPrefix) {
20
21
  const listItemValue = getDescendantsByType(listItemPrefix, [ "listItemValue" ])[0];
22
+ const { startColumn, endColumn, text } = listItemValue;
21
23
  return {
22
- "column": listItemValue.startColumn,
23
- "value": Number(listItemValue.text)
24
+ startColumn,
25
+ endColumn,
26
+ text,
27
+ "number": Number(text)
24
28
  };
25
29
  }
26
30
 
@@ -34,49 +38,57 @@ export default {
34
38
  const style = String(params.config.style);
35
39
  for (const listOrdered of filterByTypesCached([ "listOrdered" ])) {
36
40
  const listItemPrefixes = getDescendantsByType(listOrdered, [ "listItemPrefix" ]);
37
- let expected = 1;
41
+ let expectedNumber = 1;
38
42
  let incrementing = false;
39
- // Check for incrementing number pattern 1/2/3 or 0/1/2
40
- if (listItemPrefixes.length >= 2) {
41
- const first = getOrderedListItemValue(listItemPrefixes[0]);
42
- const second = getOrderedListItemValue(listItemPrefixes[1]);
43
- if ((second.value !== 1) || (first.value === 0)) {
44
- incrementing = true;
45
- if (first.value === 0) {
46
- expected = 0;
43
+ let rightAligned = false;
44
+ let zeroPrefixed = false;
45
+ if (listItemPrefixes.length > 0) {
46
+ // Check for right alignment
47
+ const firstPrefixEndColumn = listItemPrefixes[0].endColumn;
48
+ rightAligned = listItemPrefixes.every((prefix) => prefix.endColumn === firstPrefixEndColumn);
49
+ if (listItemPrefixes.length > 1) {
50
+ // Check for incrementing number pattern 1/2/3 or 0/1/2
51
+ const firstValue = getOrderedListItemValue(listItemPrefixes[0]);
52
+ const secondValue = getOrderedListItemValue(listItemPrefixes[1]);
53
+ if ((secondValue.number !== 1) || (firstValue.number === 0)) {
54
+ incrementing = true;
55
+ if (firstValue.number === 0) {
56
+ expectedNumber = 0;
57
+ }
47
58
  }
59
+ zeroPrefixed = firstValue.text.startsWith("0");
48
60
  }
49
61
  }
50
62
  // Determine effective style
51
- const listStyle = ((style === "one") || (style === "ordered") || (style === "zero")) ?
52
- style :
53
- (incrementing ? "ordered" : "one");
63
+ const listStyle = listStyles.includes(style) ? style : (incrementing ? "ordered" : "one");
54
64
  if (listStyle === "zero") {
55
- expected = 0;
65
+ expectedNumber = 0;
56
66
  } else if (listStyle === "one") {
57
- expected = 1;
67
+ expectedNumber = 1;
58
68
  }
59
69
  // Validate each list item marker
60
70
  for (const listItemPrefix of listItemPrefixes) {
61
- const orderedListItemValue = getOrderedListItemValue(listItemPrefix);
62
- const actual = orderedListItemValue.value;
71
+ const expectedText = expectedNumber.toString();
72
+ const { endColumn, startColumn, "number": actualNumber } = getOrderedListItemValue(listItemPrefix);
73
+ const length = endColumn - startColumn;
63
74
  const fixInfo = {
64
- "editColumn": orderedListItemValue.column,
65
- "deleteCount": orderedListItemValue.value.toString().length,
66
- "insertText": expected.toString()
75
+ "editColumn": startColumn,
76
+ "deleteCount": length,
77
+ "insertText": rightAligned ? expectedText.padStart(length, (zeroPrefixed ? "0" : " ")) : expectedText
67
78
  };
68
79
  addErrorDetailIf(
69
80
  onError,
70
81
  listItemPrefix.startLine,
71
- expected,
72
- actual,
82
+ expectedNumber,
83
+ actualNumber,
84
+ // @ts-ignore
73
85
  "Style: " + listStyleExamples[listStyle],
74
86
  undefined,
75
87
  [ listItemPrefix.startColumn, listItemPrefix.endColumn - listItemPrefix.startColumn ],
76
88
  fixInfo
77
89
  );
78
90
  if (listStyle === "ordered") {
79
- expected++;
91
+ expectedNumber++;
80
92
  }
81
93
  }
82
94
  }
package/lib/md032.mjs CHANGED
@@ -52,10 +52,11 @@ export default {
52
52
  (token) => !nonContentTokens.has(token.type),
53
53
  (token) => nonContentTokens.has(token.type) ? [] : token.children
54
54
  );
55
- let endLine = list.endLine;
56
- if (flattenedChildren.length > 0) {
57
- endLine = flattenedChildren[flattenedChildren.length - 1].endLine;
58
- }
55
+ const endLine = (
56
+ (flattenedChildren.length > 0) ?
57
+ flattenedChildren[flattenedChildren.length - 1] :
58
+ list
59
+ ).endLine;
59
60
 
60
61
  // Look for a blank line below the list
61
62
  const lastLineNumber = endLine;
package/lib/md036.mjs CHANGED
@@ -43,6 +43,7 @@ export default {
43
43
  for (const textToken of textTokens) {
44
44
  if (
45
45
  (textToken.children.length === 1) &&
46
+ // eslint-disable-next-line unicorn/better-dom-traversing
46
47
  (textToken.children[0].type === "data") &&
47
48
  !punctuationRe.test(textToken.text)
48
49
  ) {
package/lib/md037.mjs CHANGED
@@ -38,8 +38,7 @@ export default {
38
38
  }
39
39
 
40
40
  // Process bare tokens for each emphasis marker type
41
- for (const entry of emphasisTokensByMarker.entries()) {
42
- const [ marker, emphasisTokens ] = entry;
41
+ for (const [ marker, emphasisTokens ] of emphasisTokensByMarker) {
43
42
  for (let i = 0; i + 1 < emphasisTokens.length; i += 2) {
44
43
 
45
44
  // Process start token of start/end pair
package/lib/md051.mjs CHANGED
@@ -43,6 +43,7 @@ function convertHeadingToHTMLFragment(headingText) {
43
43
  ""
44
44
  )
45
45
  .replace(/ /gu, "-")
46
+ .toWellFormed()
46
47
  );
47
48
  }
48
49
 
@@ -120,7 +121,7 @@ export default {
120
121
  const { endColumn, startColumn } = definition;
121
122
  const text = unescapeStringTokenText(definition);
122
123
  const textSliceOne = text.slice(1);
123
- const encodedText = `#${encodeURIComponent(textSliceOne)}`;
124
+ const encodedText = `#${encodeURIComponent(textSliceOne.toWellFormed())}`;
124
125
  if (
125
126
  (text.length > 1) &&
126
127
  text.startsWith("#") &&
@@ -140,6 +141,7 @@ export default {
140
141
  };
141
142
  }
142
143
  const textLower = text.toLowerCase();
144
+ // eslint-disable-next-line unicorn/prefer-iterator-helpers
143
145
  const mixedCaseKey = [ ...fragments.keys() ]
144
146
  .find((key) => textLower === key.toLowerCase());
145
147
  if (mixedCaseKey) {
package/lib/md060.mjs CHANGED
@@ -7,6 +7,7 @@ import stringWidth from "string-width";
7
7
  /** @typedef {import("micromark-extension-gfm-table")} */
8
8
  /** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
9
9
  /** @typedef {import("markdownlint").RuleOnErrorInfo} RuleOnErrorInfo */
10
+ /** @typedef {import("markdownlint").RuleOnErrorFixInfo} RuleOnErrorFixInfo */
10
11
 
11
12
  /**
12
13
  * Adds a RuleOnErrorInfo object to a list of RuleOnErrorInfo objects.
@@ -15,12 +16,14 @@ import stringWidth from "string-width";
15
16
  * @param {number} lineNumber Line number.
16
17
  * @param {number} column Column number.
17
18
  * @param {string} detail Detail message.
19
+ * @param {RuleOnErrorFixInfo} [fixInfo] Fix information.
18
20
  */
19
- function addError(errors, lineNumber, column, detail) {
21
+ function addError(errors, lineNumber, column, detail, fixInfo) {
20
22
  errors.push({
21
23
  lineNumber,
22
24
  detail,
23
- "range": [ column, 1 ]
25
+ "range": [ column, 1 ],
26
+ fixInfo
24
27
  });
25
28
  }
26
29
 
@@ -123,11 +126,29 @@ export default {
123
126
  if (previous) {
124
127
  if (previous.type === "whitespace") {
125
128
  if (previous.text.length !== 1) {
126
- addError(errorsIfCompact, startLine, startColumn, "Table pipe has extra space to the left for style \"compact\"");
129
+ addError(
130
+ errorsIfCompact,
131
+ startLine,
132
+ startColumn,
133
+ "Table pipe has extra space to the left for style \"compact\"",
134
+ { "editColumn": previous.startColumn, "deleteCount": previous.text.length - 1 }
135
+ );
127
136
  }
128
- addError(errorsIfTight, startLine, startColumn, "Table pipe has space to the left for style \"tight\"");
137
+ addError(
138
+ errorsIfTight,
139
+ startLine,
140
+ startColumn,
141
+ "Table pipe has space to the left for style \"tight\"",
142
+ { "editColumn": previous.startColumn, "deleteCount": previous.text.length }
143
+ );
129
144
  } else {
130
- addError(errorsIfCompact, startLine, startColumn, "Table pipe is missing space to the left for style \"compact\"");
145
+ addError(
146
+ errorsIfCompact,
147
+ startLine,
148
+ startColumn,
149
+ "Table pipe is missing space to the left for style \"compact\"",
150
+ { "editColumn": previous.endColumn, "insertText": " " }
151
+ );
131
152
  }
132
153
  }
133
154
  const next = tokensOfInterest[i + 1];
@@ -135,12 +156,30 @@ export default {
135
156
  if (next.type === "whitespace") {
136
157
  if (next.endColumn !== row.endColumn) {
137
158
  if (next.text.length !== 1) {
138
- addError(errorsIfCompact, startLine, startColumn, "Table pipe has extra space to the right for style \"compact\"");
159
+ addError(
160
+ errorsIfCompact,
161
+ startLine,
162
+ startColumn,
163
+ "Table pipe has extra space to the right for style \"compact\"",
164
+ { "editColumn": next.startColumn, "deleteCount": next.text.length - 1 }
165
+ );
139
166
  }
140
- addError(errorsIfTight, startLine, startColumn, "Table pipe has space to the right for style \"tight\"");
167
+ addError(
168
+ errorsIfTight,
169
+ startLine,
170
+ startColumn,
171
+ "Table pipe has space to the right for style \"tight\"",
172
+ { "editColumn": next.startColumn, "deleteCount": next.text.length }
173
+ );
141
174
  }
142
175
  } else {
143
- addError(errorsIfCompact, startLine, startColumn, "Table pipe is missing space to the right for style \"compact\"");
176
+ addError(
177
+ errorsIfCompact,
178
+ startLine,
179
+ startColumn,
180
+ "Table pipe is missing space to the right for style \"compact\"",
181
+ { "editColumn": next.startColumn, "insertText": " " }
182
+ );
144
183
  }
145
184
  }
146
185
  }
@@ -10,9 +10,10 @@ import { parse as micromarkParse, postprocess as micromarkPostprocess, preproces
10
10
  // Unfortunately, omitting this dependency from package.json breaks strict dependency resolution (e.g., pnpm)
11
11
  import { labelEnd } from "micromark-core-commonmark";
12
12
  import { isHtmlFlowComment } from "../helpers/micromark-helpers.cjs";
13
- import { flatTokensSymbol, htmlFlowSymbol, newLineRe } from "../helpers/shared.cjs";
13
+ import { flatTokensSymbol, htmlFlowSymbol, newlineRe } from "../helpers/shared.cjs";
14
14
 
15
15
  /** @typedef {import("micromark-util-types").Event} Event */
16
+ /** @typedef {import("micromark-util-types").Extension} Extension */
16
17
  /** @typedef {import("micromark-util-types").ParseOptions} MicromarkParseOptions */
17
18
  /** @typedef {import("micromark-util-types").State} State */
18
19
  /** @typedef {import("micromark-util-types").Token} Token */
@@ -20,6 +21,20 @@ import { flatTokensSymbol, htmlFlowSymbol, newLineRe } from "../helpers/shared.c
20
21
  /** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
21
22
  /** @typedef {import("./micromark-types.d.mts")} */
22
23
 
24
+ /**
25
+ * Gets a modified micromark-extension-directive without support for inline directives.
26
+ *
27
+ * @see {@link https://github.com/DavidAnson/markdownlint/issues/2080}
28
+ * @returns {Extension} Modified implementation.
29
+ */
30
+ function directiveNoInline() {
31
+ const extension = {
32
+ ...directive()
33
+ };
34
+ delete extension.text;
35
+ return extension;
36
+ }
37
+
23
38
  /**
24
39
  * Gets the Markdown text for a Micromark token.
25
40
  *
@@ -51,7 +66,7 @@ export function getEvents(
51
66
  ) {
52
67
  // Customize extensions list to add useful extensions
53
68
  const extensions = [
54
- directive(),
69
+ directiveNoInline(),
55
70
  gfmAutolinkLiteral(),
56
71
  gfmFootnote(),
57
72
  gfmTable(),
@@ -66,7 +81,7 @@ export function getEvents(
66
81
 
67
82
  /** @type {Tokenizer} */
68
83
  function tokenizeShim(effects, okOriginal, nokOriginal) {
69
- // eslint-disable-next-line consistent-this, unicorn/no-this-assignment, no-invalid-this
84
+ // eslint-disable-next-line consistent-this, no-invalid-this, unicorn/no-this-assignment, unicorn/no-this-outside-of-class
70
85
  const tokenizeContext = this;
71
86
  const events = tokenizeContext.events;
72
87
 
@@ -269,7 +284,7 @@ function parseInternal(
269
284
  }
270
285
  ]
271
286
  };
272
- lines = markdown.split(newLineRe);
287
+ lines = markdown.split(newlineRe);
273
288
  }
274
289
  const reparseMarkdown = lines
275
290
  .slice(current.startLine - 1, current.endLine)
@@ -282,9 +297,10 @@ function parseInternal(
282
297
  current
283
298
  );
284
299
  current.children = tokens;
300
+ // eslint-disable-next-line unicorn/comment-content
285
301
  // Avoid stack overflow of Array.push(...spread)
286
302
  // @ts-ignore
287
- // eslint-disable-next-line unicorn/prefer-spread
303
+ // eslint-disable-next-line unicorn/no-array-concat-in-loop
288
304
  flatTokens = flatTokens.concat(tokens[flatTokensSymbol]);
289
305
  }
290
306
  } else if (kind === "exit") {
@@ -2,10 +2,11 @@
2
2
 
3
3
  "use strict";
4
4
 
5
- // @ts-ignore
6
- // eslint-disable-next-line camelcase, no-inline-comments, no-undef
7
- const nativeRequire = (typeof __non_webpack_require__ === "undefined") ? require : /* c8 ignore next */ __non_webpack_require__;
8
5
  // Captures the native require implementation (even under webpack).
6
+ /* node:coverage ignore next 3 */
7
+ // @ts-ignore
8
+ // eslint-disable-next-line camelcase, no-undef
9
+ const nativeRequire = (typeof __non_webpack_require__ === "undefined") ? require : __non_webpack_require__;
9
10
 
10
11
  /**
11
12
  * @typedef RequireResolveOptions
@@ -2,7 +2,7 @@ export type RequireResolveOptions = {
2
2
  /**
3
3
  * Additional paths to resolve from.
4
4
  */
5
- paths?: string[];
5
+ paths?: string[] | undefined;
6
6
  };
7
7
  export type RequireResolve = (id: string, options: RequireResolveOptions) => string;
8
8
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markdownlint",
3
- "version": "0.40.0",
3
+ "version": "0.41.1",
4
4
  "description": "A Node.js style checker and lint tool for Markdown/CommonMark files.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -36,10 +36,10 @@
36
36
  "build-config": "npm run build-config-schema && npm run build-config-example",
37
37
  "build-config-example": "node schema/build-config-example.mjs",
38
38
  "build-config-schema": "node schema/build-config-schema.mjs",
39
- "build-declaration": "tsc --allowJs --checkJs --declaration --emitDeclarationOnly --module nodenext --outDir dts --rootDir . --target es2015 lib/exports.mjs lib/exports-async.mjs lib/exports-promise.mjs lib/exports-sync.mjs lib/markdownlint.mjs lib/resolve-module.cjs && 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",
39
+ "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
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",
41
41
  "build-docs": "node doc-build/build-rules.mjs",
42
- "ci": "npm-run-all --continue-on-error --parallel build-demo lint serial-config-docs serial-declaration test-cover && git diff --exit-code",
42
+ "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
43
  "clone-test-repos-apache-airflow": "cd test-repos && git clone https://github.com/apache/airflow apache-airflow --depth 1 --no-tags --quiet",
44
44
  "clone-test-repos-dotnet-docs": "cd test-repos && git clone https://github.com/dotnet/docs dotnet-docs --depth 1 --no-tags --quiet",
45
45
  "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",
@@ -52,25 +52,23 @@
52
52
  "clone-test-repos-webhintio-hint": "cd test-repos && git clone https://github.com/webhintio/hint webhintio-hint --depth 1 --no-tags --quiet",
53
53
  "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
54
  "clone-test-repos": "mkdir test-repos && cd test-repos && npm run clone-test-repos-apache-airflow && 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
- "declaration": "npm run build-declaration && npm run test-declaration",
56
55
  "example": "cd example && node standalone.mjs",
57
56
  "lint": "eslint --max-warnings 0",
58
- "lint-test-repos": "ava --timeout=10m test/markdownlint-test-repos-*.mjs",
57
+ "lint-test-repos": "node --test test/markdownlint-test-repos-*.mjs",
59
58
  "serial-config-docs": "npm run build-config && npm run build-docs",
60
59
  "serial-declaration": "npm run build-declaration && npm run test-declaration",
61
- "test": "ava --timeout=30s test/markdownlint-test.mjs test/markdownlint-test-config.mjs test/markdownlint-test-custom-rules.mjs test/markdownlint-test-exports.mjs test/markdownlint-test-fixes.mjs test/markdownlint-test-helpers.mjs test/markdownlint-test-micromark.mjs test/markdownlint-test-project.mjs test/markdownlint-test-result-object.mjs test/markdownlint-test-scenarios.mjs test/parse-configuration-test.mjs test/resolve-module-test.mjs helpers/test.cjs",
62
- "test-cover": "c8 --100 npm test",
63
- "test-declaration": "npm-run-all --continue-on-error --parallel test-declaration-cts test-declaration-mts",
64
- "test-declaration-cts": "cd example/typescript && node ../../scripts/index.mjs copy type-check.ts type-check-commonjs.cts && tsc --module commonjs --esModuleInterop type-check-commonjs.cts",
65
- "test-declaration-mts": "cd example/typescript && node ../../scripts/index.mjs copy type-check.ts type-check-nodenext.mts && tsc --module nodenext type-check-nodenext.mts && node type-check-nodenext.mjs",
66
- "test-extra": "ava --timeout=10m test/markdownlint-test-extra-parse.mjs test/markdownlint-test-extra-type.mjs",
67
- "update-snapshots": "ava --update-snapshots test/markdownlint-test-custom-rules.mjs test/markdownlint-test-exports.mjs test/markdownlint-test-micromark.mjs test/markdownlint-test-scenarios.mjs",
68
- "update-snapshots-test-repos": "ava --timeout=10m --update-snapshots test/markdownlint-test-repos-*.mjs",
69
- "update-test-repos": "node scripts/index.mjs remove ./test-repos && npm run clone-test-repos && npm run update-snapshots-test-repos",
70
- "upgrade": "npx --yes npm-check-updates --upgrade"
60
+ "test": "node --test --experimental-test-coverage --test-coverage-branches=100 --test-coverage-functions=100 --test-coverage-lines=100 --test-coverage-exclude=test/**/* test/markdownlint-test.mjs test/markdownlint-test-config.mjs test/markdownlint-test-custom-rules.mjs test/markdownlint-test-exports.mjs test/markdownlint-test-fixes.mjs test/markdownlint-test-helpers.mjs test/markdownlint-test-micromark.mjs test/markdownlint-test-project.mjs test/markdownlint-test-result-object.mjs test/markdownlint-test-scenarios.mjs test/parse-configuration-test.mjs test/resolve-module-test.mjs helpers/test.cjs",
61
+ "test-declaration": "concurrently npm:test-declaration-cts npm:test-declaration-mts",
62
+ "test-declaration-cts": "cd example/typescript && node ../../scripts/index.mjs copy type-check.ts type-check-commonjs.cts && tsc --project tsconfig.cts.json",
63
+ "test-declaration-mts": "cd example/typescript && node ../../scripts/index.mjs copy type-check.ts type-check-nodenext.mts && tsc --project tsconfig.mts.json && node type-check-nodenext.mjs",
64
+ "test-extra": "node --test test/markdownlint-test-extra-parse.mjs test/markdownlint-test-extra-type.mjs",
65
+ "test-webpack": "cd test && node resolve-module-webpack.mjs && webpack --entry ./resolve-module-webpack.mjs --output-path . --output-filename resolve-module-webpack.cjs --stats errors-only && node resolve-module-webpack.cjs",
66
+ "update-snapshots": "node --test --test-update-snapshots test/markdownlint-test-custom-rules.mjs test/markdownlint-test-exports.mjs test/markdownlint-test-micromark.mjs test/markdownlint-test-result-object.mjs test/markdownlint-test-scenarios.mjs",
67
+ "update-snapshots-test-repos": "node --test --test-update-snapshots test/markdownlint-test-repos-*.mjs",
68
+ "update-test-repos": "node scripts/index.mjs remove ./test-repos && npm run clone-test-repos && npm run update-snapshots-test-repos"
71
69
  },
72
70
  "engines": {
73
- "node": ">=20"
71
+ "node": ">=22"
74
72
  },
75
73
  "dependencies": {
76
74
  "micromark": "4.0.2",
@@ -81,37 +79,38 @@
81
79
  "micromark-extension-gfm-table": "2.1.1",
82
80
  "micromark-extension-math": "3.1.0",
83
81
  "micromark-util-types": "2.0.2",
84
- "string-width": "8.1.0"
82
+ "string-width": "8.2.1"
85
83
  },
86
84
  "devDependencies": {
87
- "@eslint/js": "9.39.1",
88
- "@stylistic/eslint-plugin": "5.6.1",
89
- "ajv": "8.17.1",
90
- "ava": "6.4.1",
91
- "c8": "10.1.3",
85
+ "@eslint/js": "10.0.1",
86
+ "@stylistic/eslint-plugin": "5.10.0",
87
+ "@types/markdown-it": "14.1.2",
88
+ "ajv": "8.20.0",
92
89
  "character-entities": "2.0.2",
93
- "eslint": "9.39.1",
94
- "eslint-plugin-jsdoc": "61.4.1",
95
- "eslint-plugin-n": "17.23.1",
96
- "eslint-plugin-regexp": "2.10.0",
97
- "eslint-plugin-unicorn": "62.0.0",
90
+ "concurrently": "10.0.3",
91
+ "eslint": "10.6.0",
92
+ "eslint-node-test": "0.1.0",
93
+ "eslint-plugin-jsdoc": "63.0.10",
94
+ "eslint-plugin-n": "18.2.1",
95
+ "eslint-plugin-regexp": "3.1.1",
96
+ "eslint-plugin-unicorn": "70.0.0",
98
97
  "gemoji": "8.1.0",
99
- "globby": "16.0.0",
100
- "js-yaml": "4.1.1",
98
+ "globby": "16.2.0",
99
+ "js-yaml": "5.2.1",
101
100
  "json-schema-to-typescript": "15.0.4",
101
+ "json-stringify-safe": "5.0.1",
102
102
  "jsonc-parser": "3.3.1",
103
- "markdown-it": "14.1.0",
103
+ "markdown-it": "14.3.0",
104
104
  "markdown-it-for-inline": "2.0.1",
105
105
  "markdown-it-sub": "2.0.0",
106
106
  "markdown-it-sup": "2.0.0",
107
107
  "markdownlint-rule-extended-ascii": "0.2.1",
108
- "nano-spawn": "2.0.0",
109
- "npm-run-all": "4.1.5",
110
- "terser-webpack-plugin": "5.3.14",
111
- "toml": "3.0.0",
112
- "typescript": "5.9.3",
113
- "webpack": "5.103.0",
114
- "webpack-cli": "6.0.1"
108
+ "nano-spawn": "2.1.0",
109
+ "terser-webpack-plugin": "5.6.1",
110
+ "toml": "4.1.2",
111
+ "typescript": "6.0.3",
112
+ "webpack": "5.108.3",
113
+ "webpack-cli": "7.1.0"
115
114
  },
116
115
  "keywords": [
117
116
  "markdown",
@@ -120,4 +119,4 @@
120
119
  "CommonMark",
121
120
  "markdownlint"
122
121
  ]
123
- }
122
+ }