markdownlint 0.39.0 → 0.41.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.
Files changed (45) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/CONTRIBUTING.md +2 -2
  3. package/README.md +17 -30
  4. package/doc/CustomRules.md +1 -1
  5. package/doc/Rules.md +140 -43
  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/md034.md +1 -1
  13. package/doc/md035.md +12 -5
  14. package/doc/md041.md +2 -2
  15. package/doc/md042.md +6 -0
  16. package/doc/md045.md +1 -1
  17. package/doc/md051.md +10 -5
  18. package/doc/md060.md +76 -16
  19. package/helpers/README.md +4 -4
  20. package/helpers/helpers.cjs +45 -46
  21. package/helpers/micromark-helpers.cjs +4 -3
  22. package/helpers/package.json +2 -2
  23. package/helpers/shared.cjs +1 -1
  24. package/lib/configuration-strict.d.ts +124 -108
  25. package/lib/constants.mjs +2 -2
  26. package/lib/exports.d.mts +1 -0
  27. package/lib/exports.mjs +1 -0
  28. package/lib/markdownit.cjs +8 -7
  29. package/lib/markdownlint.d.mts +56 -41
  30. package/lib/markdownlint.mjs +35 -103
  31. package/lib/md011.mjs +8 -6
  32. package/lib/md013.mjs +14 -27
  33. package/lib/md022.mjs +14 -11
  34. package/lib/md029.mjs +3 -3
  35. package/lib/md036.mjs +1 -0
  36. package/lib/md051.mjs +2 -1
  37. package/lib/md060.mjs +107 -19
  38. package/lib/micromark-parse.mjs +21 -7
  39. package/lib/resolve-module.cjs +3 -3
  40. package/lib/resolve-module.d.cts +1 -1
  41. package/package.json +36 -38
  42. package/schema/.markdownlint.jsonc +58 -54
  43. package/schema/.markdownlint.yaml +57 -53
  44. package/schema/markdownlint-config-schema-strict.json +130 -110
  45. package/schema/markdownlint-config-schema.json +130 -110
package/lib/md013.mjs CHANGED
@@ -4,10 +4,8 @@ import { addErrorDetailIf } from "../helpers/helpers.cjs";
4
4
  import { filterByTypesCached, getReferenceLinkImageData } from "./cache.mjs";
5
5
  import { addRangeToSet, getDescendantsByType } from "../helpers/micromark-helpers.cjs";
6
6
 
7
- const longLineRePrefix = "^.{";
8
- const longLineRePostfixRelaxed = "}.*\\s.*$";
9
- const longLineRePostfixStrict = "}.+$";
10
- const sternModeRe = /^(?:[#>\s]*\s)?\S*$/;
7
+ // Regular expression for a line that is not wrappable
8
+ const notWrappableRe = /^(?:[#>\s]*\s)?\S*$/;
11
9
 
12
10
  /** @typedef {import("micromark-extension-gfm-autolink-literal")} */
13
11
  /** @typedef {import("micromark-extension-gfm-table")} */
@@ -20,20 +18,10 @@ export default {
20
18
  "parser": "micromark",
21
19
  "function": function MD013(params, onError) {
22
20
  const lineLength = Number(params.config.line_length || 80);
23
- const headingLineLength =
24
- Number(params.config.heading_line_length || lineLength);
25
- const codeLineLength =
26
- Number(params.config.code_block_line_length || lineLength);
21
+ const headingLineLength = Number(params.config.heading_line_length || lineLength);
22
+ const codeLineLength = Number(params.config.code_block_line_length || lineLength);
27
23
  const strict = !!params.config.strict;
28
24
  const stern = !!params.config.stern;
29
- const longLineRePostfix =
30
- (strict || stern) ? longLineRePostfixStrict : longLineRePostfixRelaxed;
31
- const longLineRe =
32
- new RegExp(longLineRePrefix + lineLength + longLineRePostfix);
33
- const longHeadingLineRe =
34
- new RegExp(longLineRePrefix + headingLineLength + longLineRePostfix);
35
- const longCodeLineRe =
36
- new RegExp(longLineRePrefix + codeLineLength + longLineRePostfix);
37
25
  const codeBlocks = params.config.code_blocks;
38
26
  const includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks;
39
27
  const tables = params.config.tables;
@@ -75,28 +63,27 @@ export default {
75
63
  const isHeading = headingLineNumbers.has(lineNumber);
76
64
  const inCode = codeBlockLineNumbers.has(lineNumber);
77
65
  const inTable = tableLineNumbers.has(lineNumber);
78
- const length = inCode ?
79
- codeLineLength :
80
- (isHeading ? headingLineLength : lineLength);
81
- const lengthRe = inCode ?
82
- longCodeLineRe :
83
- (isHeading ? longHeadingLineRe : longLineRe);
84
- if ((includeCodeBlocks || !inCode) &&
66
+ const maxLength = inCode ? codeLineLength : (isHeading ? headingLineLength : lineLength);
67
+ // If not strict/stern, the last run of non-whitespace is allowed to go
68
+ // beyond the limit as long as it begins within the limit
69
+ const text = (strict || stern) ? line : line.replace(/\S*$/u, "#");
70
+ if ((maxLength > 0) &&
71
+ (includeCodeBlocks || !inCode) &&
85
72
  (includeTables || !inTable) &&
86
73
  (includeHeadings || !isHeading) &&
87
74
  !definitionLineIndices.has(lineIndex) &&
88
75
  (strict ||
89
- (!(stern && sternModeRe.test(line)) &&
76
+ (!(stern && notWrappableRe.test(line)) &&
90
77
  !linkOnlyLineNumbers.has(lineNumber))) &&
91
- lengthRe.test(line)) {
78
+ (text.length > maxLength)) {
92
79
  addErrorDetailIf(
93
80
  onError,
94
81
  lineNumber,
95
- length,
82
+ maxLength,
96
83
  line.length,
97
84
  undefined,
98
85
  undefined,
99
- [ length + 1, line.length - length ]
86
+ [ maxLength + 1, line.length - maxLength ]
100
87
  );
101
88
  }
102
89
  }
package/lib/md022.mjs CHANGED
@@ -22,6 +22,16 @@ const getLinesFunction = (/** @type {any} */ linesParam) => {
22
22
  return () => lines;
23
23
  };
24
24
 
25
+ const getLine = (/** @type {readonly string[]} */ lines, /** @type {number} */ index, /** @type {readonly string[]} */ frontMatterLines, /** @type {boolean} */ includeFrontMatter) => {
26
+ if ((index >= 0) && (index < lines.length)) {
27
+ return lines[index];
28
+ }
29
+ if (includeFrontMatter && (frontMatterLines.length > 0) && (index < 0) && (index >= -frontMatterLines.length)) {
30
+ return frontMatterLines[frontMatterLines.length + index];
31
+ }
32
+ return "";
33
+ };
34
+
25
35
  /** @type {import("markdownlint").Rule} */
26
36
  export default {
27
37
  "names": [ "MD022", "blanks-around-headings" ],
@@ -31,7 +41,8 @@ export default {
31
41
  "function": function MD022(params, onError) {
32
42
  const getLinesAbove = getLinesFunction(params.config.lines_above);
33
43
  const getLinesBelow = getLinesFunction(params.config.lines_below);
34
- const { lines } = params;
44
+ const includeFrontMatter = !!params.config.include_front_matter;
45
+ const { lines, frontMatterLines } = params;
35
46
  const blockQuotePrefixes = filterByTypesCached([ "blockQuotePrefix", "linePrefix" ]);
36
47
  for (const heading of filterByTypesCached([ "atxHeading", "setextHeading" ])) {
37
48
  const { startLine, endLine } = heading;
@@ -41,11 +52,7 @@ export default {
41
52
  const linesAbove = getLinesAbove(heading);
42
53
  if (linesAbove >= 0) {
43
54
  let actualAbove = 0;
44
- for (
45
- let i = 0;
46
- (i < linesAbove) && isBlankLine(lines[startLine - 2 - i]);
47
- i++
48
- ) {
55
+ for (let i = 0; (i < linesAbove) && isBlankLine(getLine(lines, startLine - 2 - i, frontMatterLines, includeFrontMatter)); i++) {
49
56
  actualAbove++;
50
57
  }
51
58
  addErrorDetailIf(
@@ -70,11 +77,7 @@ export default {
70
77
  const linesBelow = getLinesBelow(heading);
71
78
  if (linesBelow >= 0) {
72
79
  let actualBelow = 0;
73
- for (
74
- let i = 0;
75
- (i < linesBelow) && isBlankLine(lines[endLine + i]);
76
- i++
77
- ) {
80
+ for (let i = 0; (i < linesBelow) && isBlankLine(getLine(lines, endLine + i, frontMatterLines, false)); i++) {
78
81
  actualBelow++;
79
82
  }
80
83
  addErrorDetailIf(
package/lib/md029.mjs CHANGED
@@ -9,6 +9,7 @@ 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.
@@ -48,9 +49,7 @@ export default {
48
49
  }
49
50
  }
50
51
  // Determine effective style
51
- const listStyle = ((style === "one") || (style === "ordered") || (style === "zero")) ?
52
- style :
53
- (incrementing ? "ordered" : "one");
52
+ const listStyle = listStyles.includes(style) ? style : (incrementing ? "ordered" : "one");
54
53
  if (listStyle === "zero") {
55
54
  expected = 0;
56
55
  } else if (listStyle === "one") {
@@ -70,6 +69,7 @@ export default {
70
69
  listItemPrefix.startLine,
71
70
  expected,
72
71
  actual,
72
+ // @ts-ignore
73
73
  "Style: " + listStyleExamples[listStyle],
74
74
  undefined,
75
75
  [ listItemPrefix.startColumn, listItemPrefix.endColumn - listItemPrefix.startColumn ],
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/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("#") &&
package/lib/md060.mjs CHANGED
@@ -2,9 +2,12 @@
2
2
 
3
3
  import { filterByTypes } from "../helpers/micromark-helpers.cjs";
4
4
  import { filterByTypesCached } from "./cache.mjs";
5
+ import stringWidth from "string-width";
5
6
 
6
7
  /** @typedef {import("micromark-extension-gfm-table")} */
8
+ /** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
7
9
  /** @typedef {import("markdownlint").RuleOnErrorInfo} RuleOnErrorInfo */
10
+ /** @typedef {import("markdownlint").RuleOnErrorFixInfo} RuleOnErrorFixInfo */
8
11
 
9
12
  /**
10
13
  * Adds a RuleOnErrorInfo object to a list of RuleOnErrorInfo objects.
@@ -13,15 +16,67 @@ import { filterByTypesCached } from "./cache.mjs";
13
16
  * @param {number} lineNumber Line number.
14
17
  * @param {number} column Column number.
15
18
  * @param {string} detail Detail message.
19
+ * @param {RuleOnErrorFixInfo} [fixInfo] Fix information.
16
20
  */
17
- function addError(errors, lineNumber, column, detail) {
21
+ function addError(errors, lineNumber, column, detail, fixInfo) {
18
22
  errors.push({
19
23
  lineNumber,
20
24
  detail,
21
- "range": [ column, 1 ]
25
+ "range": [ column, 1 ],
26
+ fixInfo
22
27
  });
23
28
  }
24
29
 
30
+ /**
31
+ * @typedef Column
32
+ * @property {number} actual Actual column (1-based).
33
+ * @property {number} effective Effective column (1-based).
34
+ */
35
+
36
+ /**
37
+ * Gets a list of table cell divider columns.
38
+ *
39
+ * @param {readonly string[]} lines File/string lines.
40
+ * @param {MicromarkToken} row Micromark row token.
41
+ * @returns {Column[]} Divider columns.
42
+ */
43
+ function getTableDividerColumns(lines, row) {
44
+ return filterByTypes(
45
+ row.children,
46
+ [ "tableCellDivider" ]
47
+ ).map(
48
+ (divider) => ({
49
+ "actual": divider.startColumn,
50
+ "effective": stringWidth(lines[row.startLine - 1].slice(0, divider.startColumn - 1))
51
+ })
52
+ );
53
+ }
54
+
55
+ /**
56
+ * Checks the specified table rows for consistency with the "aligned" style.
57
+ *
58
+ * @param {readonly string[]} lines File/string lines.
59
+ * @param {MicromarkToken[]} rows Micromark row tokens.
60
+ * @param {string} detail Detail message.
61
+ * @returns {RuleOnErrorInfo[]} List of errors.
62
+ */
63
+ function checkStyleAligned(lines, rows, detail) {
64
+ /** @type {RuleOnErrorInfo[]} */
65
+ const errorInfos = [];
66
+ const headerRow = rows[0];
67
+ const headerDividerColumns = getTableDividerColumns(lines, headerRow);
68
+ for (const row of rows.slice(1)) {
69
+ const remainingHeaderDividerColumns = new Set(headerDividerColumns.map((column) => column.effective));
70
+ const rowDividerColumns = getTableDividerColumns(lines, row);
71
+ for (const dividerColumn of rowDividerColumns) {
72
+ if ((remainingHeaderDividerColumns.size > 0) && !remainingHeaderDividerColumns.delete(dividerColumn.effective)) {
73
+ addError(errorInfos, row.startLine, dividerColumn.actual, detail);
74
+ }
75
+ }
76
+ }
77
+ return errorInfos;
78
+ }
79
+
25
80
  /** @type {import("markdownlint").Rule} */
26
81
  export default {
27
82
  "names": [ "MD060", "table-column-style" ],
@@ -33,27 +88,19 @@ export default {
33
88
  const styleAlignedAllowed = (style === "any") || (style === "aligned");
34
89
  const styleCompactAllowed = (style === "any") || (style === "compact");
35
90
  const styleTightAllowed = (style === "any") || (style === "tight");
91
+ const alignedDelimiter = !!params.config.aligned_delimiter;
92
+ const lines = params.lines;
36
93
 
37
94
  // Scan all tables/rows
38
95
  const tables = filterByTypesCached([ "table" ]);
39
96
  for (const table of tables) {
40
97
  const rows = filterByTypes(table.children, [ "tableDelimiterRow", "tableRow" ]);
41
- const headingRow = rows[0];
42
98
 
43
99
  // Determine errors for style "aligned"
44
100
  /** @type {RuleOnErrorInfo[]} */
45
101
  const errorsIfAligned = [];
46
102
  if (styleAlignedAllowed) {
47
- const headingDividerColumns = filterByTypes(headingRow.children, [ "tableCellDivider" ]).map((divider) => divider.startColumn);
48
- for (const row of rows.slice(1)) {
49
- const remainingHeadingDividerColumns = new Set(headingDividerColumns);
50
- const rowDividerColumns = filterByTypes(row.children, [ "tableCellDivider" ]).map((divider) => divider.startColumn);
51
- for (const dividerColumn of rowDividerColumns) {
52
- if ((remainingHeadingDividerColumns.size > 0) && !remainingHeadingDividerColumns.delete(dividerColumn)) {
53
- addError(errorsIfAligned, row.startLine, dividerColumn, "Table pipe does not align with heading for style \"aligned\"");
54
- }
55
- }
56
- }
103
+ errorsIfAligned.push(...checkStyleAligned(lines, rows, "Table pipe does not align with header for style \"aligned\""));
57
104
  }
58
105
 
59
106
  // Determine errors for styles "compact" and "tight"
@@ -65,6 +112,11 @@ export default {
65
112
  (styleCompactAllowed || styleTightAllowed) &&
66
113
  !(styleAlignedAllowed && (errorsIfAligned.length === 0))
67
114
  ) {
115
+ if (alignedDelimiter) {
116
+ const errorInfos = checkStyleAligned(lines, rows.slice(0, 2), "Table pipe does not align with header for option \"aligned_delimiter\"");
117
+ errorsIfCompact.push(...errorInfos);
118
+ errorsIfTight.push(...errorInfos);
119
+ }
68
120
  for (const row of rows) {
69
121
  const tokensOfInterest = filterByTypes(row.children, [ "tableCellDivider", "tableContent", "whitespace" ]);
70
122
  for (let i = 0; i < tokensOfInterest.length; i++) {
@@ -74,11 +126,29 @@ export default {
74
126
  if (previous) {
75
127
  if (previous.type === "whitespace") {
76
128
  if (previous.text.length !== 1) {
77
- 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
+ );
78
136
  }
79
- 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
+ );
80
144
  } else {
81
- 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
+ );
82
152
  }
83
153
  }
84
154
  const next = tokensOfInterest[i + 1];
@@ -86,12 +156,30 @@ export default {
86
156
  if (next.type === "whitespace") {
87
157
  if (next.endColumn !== row.endColumn) {
88
158
  if (next.text.length !== 1) {
89
- 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
+ );
90
166
  }
91
- 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
+ );
92
174
  }
93
175
  } else {
94
- 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
+ );
95
183
  }
96
184
  }
97
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
 
@@ -142,11 +157,10 @@ export function getEvents(
142
157
  .trim();
143
158
  if ((text.length > 0) && !text.includes("]")) {
144
159
  /** @type {Event[]} */
145
- const artificialEvents = [];
146
- artificialEvents.push(
160
+ const artificialEvents = [
147
161
  [ "enter", undefinedReferenceType, tokenizeContext ],
148
162
  [ "enter", undefinedReference, tokenizeContext ]
149
- );
163
+ ];
150
164
  for (const event of eventsToReplicate) {
151
165
  const [ kind, token ] = event;
152
166
  // Copy token because the current object will get modified by the parser
@@ -270,7 +284,7 @@ function parseInternal(
270
284
  }
271
285
  ]
272
286
  };
273
- lines = markdown.split(newLineRe);
287
+ lines = markdown.split(newlineRe);
274
288
  }
275
289
  const reparseMarkdown = lines
276
290
  .slice(current.startLine - 1, current.endLine)
@@ -2,10 +2,10 @@
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
+ // @ts-ignore
7
+ // eslint-disable-next-line no-underscore-dangle
8
+ const nativeRequire = globalThis.__non_webpack_require__ ?? require;
9
9
 
10
10
  /**
11
11
  * @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.39.0",
3
+ "version": "0.41.0",
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 && 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,22 @@
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
+ "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",
66
+ "update-snapshots-test-repos": "node --test --test-update-snapshots test/markdownlint-test-repos-*.mjs",
67
+ "update-test-repos": "node scripts/index.mjs remove ./test-repos && npm run clone-test-repos && npm run update-snapshots-test-repos"
71
68
  },
72
69
  "engines": {
73
- "node": ">=20"
70
+ "node": ">=22"
74
71
  },
75
72
  "dependencies": {
76
73
  "micromark": "4.0.2",
@@ -80,37 +77,38 @@
80
77
  "micromark-extension-gfm-footnote": "2.1.0",
81
78
  "micromark-extension-gfm-table": "2.1.1",
82
79
  "micromark-extension-math": "3.1.0",
83
- "micromark-util-types": "2.0.2"
80
+ "micromark-util-types": "2.0.2",
81
+ "string-width": "8.2.1"
84
82
  },
85
83
  "devDependencies": {
86
- "@eslint/js": "9.37.0",
87
- "@stylistic/eslint-plugin": "5.4.0",
88
- "ajv": "8.17.1",
89
- "ava": "6.4.1",
90
- "c8": "10.1.3",
84
+ "@eslint/js": "10.0.1",
85
+ "@stylistic/eslint-plugin": "5.10.0",
86
+ "@types/markdown-it": "14.1.2",
87
+ "ajv": "8.20.0",
91
88
  "character-entities": "2.0.2",
92
- "eslint": "9.37.0",
93
- "eslint-plugin-jsdoc": "61.1.1",
94
- "eslint-plugin-n": "17.23.1",
95
- "eslint-plugin-regexp": "2.10.0",
96
- "eslint-plugin-unicorn": "61.0.2",
89
+ "concurrently": "10.0.3",
90
+ "eslint": "10.4.1",
91
+ "eslint-plugin-jsdoc": "63.0.2",
92
+ "eslint-plugin-n": "18.1.0",
93
+ "eslint-plugin-regexp": "3.1.0",
94
+ "eslint-plugin-unicorn": "65.0.1",
97
95
  "gemoji": "8.1.0",
98
- "globby": "15.0.0",
99
- "js-yaml": "4.1.0",
96
+ "globby": "16.2.0",
97
+ "js-yaml": "4.2.0",
100
98
  "json-schema-to-typescript": "15.0.4",
99
+ "json-stringify-safe": "5.0.1",
101
100
  "jsonc-parser": "3.3.1",
102
- "markdown-it": "14.1.0",
101
+ "markdown-it": "14.2.0",
103
102
  "markdown-it-for-inline": "2.0.1",
104
103
  "markdown-it-sub": "2.0.0",
105
104
  "markdown-it-sup": "2.0.0",
106
105
  "markdownlint-rule-extended-ascii": "0.2.1",
107
- "nano-spawn": "2.0.0",
108
- "npm-run-all": "4.1.5",
109
- "terser-webpack-plugin": "5.3.14",
110
- "toml": "3.0.0",
111
- "typescript": "5.9.3",
112
- "webpack": "5.102.1",
113
- "webpack-cli": "6.0.1"
106
+ "nano-spawn": "2.1.0",
107
+ "terser-webpack-plugin": "5.6.1",
108
+ "toml": "4.1.1",
109
+ "typescript": "6.0.3",
110
+ "webpack": "5.107.2",
111
+ "webpack-cli": "7.0.3"
114
112
  },
115
113
  "keywords": [
116
114
  "markdown",
@@ -119,4 +117,4 @@
119
117
  "CommonMark",
120
118
  "markdownlint"
121
119
  ]
122
- }
120
+ }