markdownlint 0.35.0 → 0.36.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 (73) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +72 -35
  3. package/demo/markdownlint-browser.js +1258 -1214
  4. package/doc/CustomRules.md +55 -249
  5. package/doc/Rules.md +36 -29
  6. package/doc/md003.md +2 -2
  7. package/doc/md004.md +4 -3
  8. package/doc/md035.md +3 -8
  9. package/doc/md046.md +2 -2
  10. package/doc/md048.md +3 -2
  11. package/doc/md049.md +4 -3
  12. package/doc/md050.md +4 -4
  13. package/doc/md051.md +11 -3
  14. package/doc/md055.md +3 -2
  15. package/helpers/README.md +2 -19
  16. package/helpers/helpers.js +87 -347
  17. package/helpers/micromark-helpers.cjs +296 -0
  18. package/helpers/micromark-parse.cjs +313 -0
  19. package/helpers/package.json +5 -2
  20. package/helpers/shared.js +6 -0
  21. package/helpers/test.cjs +28 -0
  22. package/lib/cache.js +3 -3
  23. package/lib/configuration-strict.d.ts +120 -106
  24. package/lib/constants.js +1 -1
  25. package/lib/markdownit.cjs +172 -0
  26. package/lib/markdownlint.d.ts +41 -3
  27. package/lib/markdownlint.js +153 -115
  28. package/lib/md001.js +1 -1
  29. package/lib/md003.js +1 -1
  30. package/lib/md004.js +3 -3
  31. package/lib/md007.js +3 -3
  32. package/lib/md009.js +1 -1
  33. package/lib/md010.js +18 -14
  34. package/lib/md011.js +24 -23
  35. package/lib/md012.js +1 -1
  36. package/lib/md013.js +1 -1
  37. package/lib/md014.js +5 -9
  38. package/lib/md018.js +1 -1
  39. package/lib/md019-md021.js +1 -1
  40. package/lib/md020.js +2 -2
  41. package/lib/md022.js +9 -15
  42. package/lib/md024.js +1 -1
  43. package/lib/md025.js +1 -1
  44. package/lib/md027.js +2 -2
  45. package/lib/md029.js +3 -3
  46. package/lib/md031.js +8 -6
  47. package/lib/md032.js +27 -15
  48. package/lib/md033.js +1 -1
  49. package/lib/md034.js +21 -29
  50. package/lib/md036.js +18 -24
  51. package/lib/md037.js +1 -1
  52. package/lib/md038.js +9 -14
  53. package/lib/md039.js +13 -15
  54. package/lib/md040.js +11 -13
  55. package/lib/md041.js +4 -4
  56. package/lib/md042.js +2 -6
  57. package/lib/md043.js +1 -1
  58. package/lib/md044.js +31 -28
  59. package/lib/md045.js +2 -2
  60. package/lib/md048.js +28 -17
  61. package/lib/md049-md050.js +20 -5
  62. package/lib/md051.js +16 -18
  63. package/lib/md053.js +5 -4
  64. package/lib/md054.js +10 -12
  65. package/lib/md055.js +39 -46
  66. package/lib/md056.js +31 -36
  67. package/lib/md058.js +29 -14
  68. package/package.json +14 -13
  69. package/schema/.markdownlint.jsonc +55 -52
  70. package/schema/.markdownlint.yaml +54 -52
  71. package/schema/markdownlint-config-schema-strict.json +132 -110
  72. package/schema/markdownlint-config-schema.json +132 -110
  73. package/helpers/micromark.cjs +0 -544
@@ -1,4 +1,4 @@
1
- /*! markdownlint 0.35.0 https://github.com/DavidAnson/markdownlint @license MIT */
1
+ /*! markdownlint 0.36.0 https://github.com/DavidAnson/markdownlint @license MIT */
2
2
  var markdownlint;
3
3
  /******/ (() => { // webpackBootstrap
4
4
  /******/ var __webpack_modules__ = ({
@@ -14,30 +14,25 @@ var markdownlint;
14
14
 
15
15
 
16
16
 
17
- const micromark = __webpack_require__(/*! ./micromark.cjs */ "../helpers/micromark.cjs");
17
+ const micromark = __webpack_require__(/*! ./micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
18
18
 
19
19
  const { newLineRe, nextLinesRe } = __webpack_require__(/*! ./shared.js */ "../helpers/shared.js");
20
20
 
21
21
  module.exports.newLineRe = newLineRe;
22
22
  module.exports.nextLinesRe = nextLinesRe;
23
23
 
24
+ /** @typedef {import("../lib/markdownlint.js").RuleOnError} RuleOnError */
25
+ /** @typedef {import("../lib/markdownlint.js").RuleOnErrorFixInfo} RuleOnErrorFixInfo */
26
+
24
27
  // Regular expression for matching common front matter (YAML and TOML)
25
28
  module.exports.frontMatterRe =
26
- /((^---\s*$[\s\S]+?^---\s*)|(^\+\+\+\s*$[\s\S]+?^(\+\+\+|\.\.\.)\s*)|(^\{\s*$[\s\S]+?^\}\s*))(\r\n|\r|\n|$)/m;
29
+ /((^---[^\S\r\n\u2028\u2029]*$[\s\S]+?^---\s*)|(^\+\+\+[^\S\r\n\u2028\u2029]*$[\s\S]+?^(\+\+\+|\.\.\.)\s*)|(^\{[^\S\r\n\u2028\u2029]*$[\s\S]+?^\}\s*))(\r\n|\r|\n|$)/m;
27
30
 
28
31
  // Regular expression for matching the start of inline disable/enable comments
29
32
  const inlineCommentStartRe =
30
33
  /(<!--\s*markdownlint-(disable|enable|capture|restore|disable-file|enable-file|disable-line|disable-next-line|configure-file))(?:\s|-->)/gi;
31
34
  module.exports.inlineCommentStartRe = inlineCommentStartRe;
32
35
 
33
- // Regular expression for blockquote prefixes
34
- const blockquotePrefixRe = /^[>\s]*/;
35
- module.exports.blockquotePrefixRe = blockquotePrefixRe;
36
-
37
- // Regular expression for link reference definitions
38
- const linkReferenceDefinitionRe = /^ {0,3}\[([^\]]*[^\\])\]:/;
39
- module.exports.linkReferenceDefinitionRe = linkReferenceDefinitionRe;
40
-
41
36
  // Regular expression for identifying an HTML entity at the end of a line
42
37
  module.exports.endOfLineHtmlEntityRe =
43
38
  /&(?:#\d+|#[xX][\da-fA-F]+|[a-zA-Z]{2,31}|blk\d{2}|emsp1[34]|frac\d{2}|sup\d|there4);$/;
@@ -235,99 +230,6 @@ module.exports.escapeForRegExp = function escapeForRegExp(str) {
235
230
  return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
236
231
  };
237
232
 
238
- /**
239
- * Return the string representation of a fence markup character.
240
- *
241
- * @param {string} markup Fence string.
242
- * @returns {string} String representation.
243
- */
244
- module.exports.fencedCodeBlockStyleFor =
245
- function fencedCodeBlockStyleFor(markup) {
246
- switch (markup[0]) {
247
- case "~":
248
- return "tilde";
249
- default:
250
- return "backtick";
251
- }
252
- };
253
-
254
- /**
255
- * Return the string representation of a emphasis or strong markup character.
256
- *
257
- * @param {string} markup Emphasis or strong string.
258
- * @returns {"asterisk" | "underscore"} String representation.
259
- */
260
- module.exports.emphasisOrStrongStyleFor =
261
- function emphasisOrStrongStyleFor(markup) {
262
- switch (markup[0]) {
263
- case "*":
264
- return "asterisk";
265
- default:
266
- return "underscore";
267
- }
268
- };
269
-
270
- /**
271
- * @callback InlineCodeSpanCallback
272
- * @param {string} code Code content.
273
- * @param {number} lineIndex Line index (0-based).
274
- * @param {number} columnIndex Column index (0-based).
275
- * @param {number} ticks Count of backticks.
276
- * @returns {void}
277
- */
278
-
279
- /**
280
- * Calls the provided function for each inline code span's content.
281
- *
282
- * @param {string} input Markdown content.
283
- * @param {InlineCodeSpanCallback} handler Callback function taking (code,
284
- * lineIndex, columnIndex, ticks).
285
- * @returns {void}
286
- */
287
- function forEachInlineCodeSpan(input, handler) {
288
- const backtickRe = /`+/g;
289
- let match = null;
290
- const backticksLengthAndIndex = [];
291
- while ((match = backtickRe.exec(input)) !== null) {
292
- backticksLengthAndIndex.push([ match[0].length, match.index ]);
293
- }
294
- const newLinesIndex = [];
295
- while ((match = newLineRe.exec(input)) !== null) {
296
- newLinesIndex.push(match.index);
297
- }
298
- let lineIndex = 0;
299
- let lineStartIndex = 0;
300
- let k = 0;
301
- for (let i = 0; i < backticksLengthAndIndex.length - 1; i++) {
302
- const [ startLength, startIndex ] = backticksLengthAndIndex[i];
303
- if ((startIndex === 0) || (input[startIndex - 1] !== "\\")) {
304
- for (let j = i + 1; j < backticksLengthAndIndex.length; j++) {
305
- const [ endLength, endIndex ] = backticksLengthAndIndex[j];
306
- if (startLength === endLength) {
307
- for (; k < newLinesIndex.length; k++) {
308
- const newLineIndex = newLinesIndex[k];
309
- if (startIndex < newLineIndex) {
310
- break;
311
- }
312
- lineIndex++;
313
- lineStartIndex = newLineIndex + 1;
314
- }
315
- const columnIndex = startIndex - lineStartIndex + startLength;
316
- handler(
317
- input.slice(startIndex + startLength, endIndex),
318
- lineIndex,
319
- columnIndex,
320
- startLength
321
- );
322
- i = j;
323
- break;
324
- }
325
- }
326
- }
327
- }
328
- }
329
- module.exports.forEachInlineCodeSpan = forEachInlineCodeSpan;
330
-
331
233
  /**
332
234
  * Adds ellipsis to the left/right/middle of the specified text.
333
235
  *
@@ -353,12 +255,12 @@ module.exports.ellipsify = ellipsify;
353
255
  /**
354
256
  * Adds a generic error object via the onError callback.
355
257
  *
356
- * @param {Object} onError RuleOnError instance.
258
+ * @param {RuleOnError} onError RuleOnError instance.
357
259
  * @param {number} lineNumber Line number.
358
260
  * @param {string} [detail] Error details.
359
261
  * @param {string} [context] Error context.
360
262
  * @param {number[]} [range] Column and length of error.
361
- * @param {Object} [fixInfo] RuleOnErrorFixInfo instance.
263
+ * @param {RuleOnErrorFixInfo} [fixInfo] RuleOnErrorFixInfo instance.
362
264
  * @returns {void}
363
265
  */
364
266
  function addError(onError, lineNumber, detail, context, range, fixInfo) {
@@ -375,14 +277,14 @@ module.exports.addError = addError;
375
277
  /**
376
278
  * Adds an error object with details conditionally via the onError callback.
377
279
  *
378
- * @param {Object} onError RuleOnError instance.
280
+ * @param {RuleOnError} onError RuleOnError instance.
379
281
  * @param {number} lineNumber Line number.
380
282
  * @param {Object} expected Expected value.
381
283
  * @param {Object} actual Actual value.
382
284
  * @param {string} [detail] Error details.
383
285
  * @param {string} [context] Error context.
384
286
  * @param {number[]} [range] Column and length of error.
385
- * @param {Object} [fixInfo] RuleOnErrorFixInfo instance.
287
+ * @param {RuleOnErrorFixInfo} [fixInfo] RuleOnErrorFixInfo instance.
386
288
  * @returns {void}
387
289
  */
388
290
  function addErrorDetailIf(
@@ -403,13 +305,13 @@ module.exports.addErrorDetailIf = addErrorDetailIf;
403
305
  /**
404
306
  * Adds an error object with context via the onError callback.
405
307
  *
406
- * @param {Object} onError RuleOnError instance.
308
+ * @param {RuleOnError} onError RuleOnError instance.
407
309
  * @param {number} lineNumber Line number.
408
310
  * @param {string} context Error context.
409
311
  * @param {boolean} [start] True iff the start of the text is important.
410
312
  * @param {boolean} [end] True iff the end of the text is important.
411
313
  * @param {number[]} [range] Column and length of error.
412
- * @param {Object} [fixInfo] RuleOnErrorFixInfo instance.
314
+ * @param {RuleOnErrorFixInfo} [fixInfo] RuleOnErrorFixInfo instance.
413
315
  * @returns {void}
414
316
  */
415
317
  function addErrorContext(
@@ -420,50 +322,42 @@ function addErrorContext(
420
322
  module.exports.addErrorContext = addErrorContext;
421
323
 
422
324
  /**
423
- * Adds an error object with context for a construct missing a blank line.
325
+ * Defines a range within a file (start line/column to end line/column, subset of MicromarkToken).
424
326
  *
425
- * @param {Object} onError RuleOnError instance.
426
- * @param {string[]} lines Lines of Markdown content.
427
- * @param {number} lineIndex Line index of line.
428
- * @param {number} [lineNumber] Line number for override.
429
- * @returns {void}
327
+ * @typedef {Object} FileRange
328
+ * @property {number} startLine Start line (1-based).
329
+ * @property {number} startColumn Start column (1-based).
330
+ * @property {number} endLine End line (1-based).
331
+ * @property {number} endColumn End column (1-based).
430
332
  */
431
- function addErrorContextForLine(onError, lines, lineIndex, lineNumber) {
432
- const line = lines[lineIndex];
433
- // @ts-ignore
434
- const quotePrefix = line.match(blockquotePrefixRe)[0].trimEnd();
435
- addErrorContext(
436
- onError,
437
- lineIndex + 1,
438
- line.trim(),
439
- undefined,
440
- undefined,
441
- undefined,
442
- {
443
- lineNumber,
444
- "insertText": `${quotePrefix}\n`
445
- }
446
- );
447
- }
448
- module.exports.addErrorContextForLine = addErrorContextForLine;
449
333
 
450
334
  /**
451
- * Determines whether the specified range is within another range.
335
+ * Returns whether line/column A is less than or equal to line/column B.
452
336
  *
453
- * @param {number[][]} ranges Array of ranges (line, index, length).
454
- * @param {number} lineIndex Line index to check.
455
- * @param {number} index Index to check.
456
- * @param {number} length Length to check.
457
- * @returns {boolean} True iff the specified range is within.
337
+ * @param {number} lineA Line A.
338
+ * @param {number} columnA Column A.
339
+ * @param {number} lineB Line B.
340
+ * @param {number} columnB Column B.
341
+ * @returns {boolean} True iff A is less than or equal to B.
458
342
  */
459
- const withinAnyRange = (ranges, lineIndex, index, length) => (
460
- !ranges.every((span) => (
461
- (lineIndex !== span[0]) ||
462
- (index < span[1]) ||
463
- (index + length > span[1] + span[2])
464
- ))
343
+ const positionLessThanOrEqual = (lineA, columnA, lineB, columnB) => (
344
+ (lineA < lineB) ||
345
+ ((lineA === lineB) && (columnA <= columnB))
465
346
  );
466
- module.exports.withinAnyRange = withinAnyRange;
347
+
348
+ /**
349
+ * Returns whether two ranges (or MicromarkTokens) overlap anywhere.
350
+ *
351
+ * @param {FileRange|import("../lib/markdownlint.js").MicromarkToken} rangeA Range A.
352
+ * @param {FileRange|import("../lib/markdownlint.js").MicromarkToken} rangeB Range B.
353
+ * @returns {boolean} True iff the two ranges overlap.
354
+ */
355
+ module.exports.hasOverlap = function hasOverlap(rangeA, rangeB) {
356
+ const lte = positionLessThanOrEqual(rangeA.startLine, rangeA.startColumn, rangeB.startLine, rangeB.startColumn);
357
+ const first = lte ? rangeA : rangeB;
358
+ const second = lte ? rangeB : rangeA;
359
+ return positionLessThanOrEqual(second.startLine, second.startColumn, first.endLine, first.endColumn);
360
+ };
467
361
 
468
362
  // Determines if the front matter includes a title
469
363
  module.exports.frontMatterHasTitle =
@@ -482,16 +376,28 @@ module.exports.frontMatterHasTitle =
482
376
  /**
483
377
  * Returns an object with information about reference links and images.
484
378
  *
485
- * @param {import("../helpers/micromark.cjs").Token[]} tokens Micromark tokens.
379
+ * @param {import("../helpers/micromark-helpers.cjs").Token[]} tokens Micromark tokens.
486
380
  * @returns {Object} Reference link/image data.
487
381
  */
488
382
  function getReferenceLinkImageData(tokens) {
489
383
  const normalizeReference = (s) => s.toLowerCase().trim().replace(/\s+/g, " ");
384
+ const references = new Map();
385
+ const shortcuts = new Map();
386
+ const addReferenceToDictionary = (token, label, isShortcut) => {
387
+ const referenceDatum = [
388
+ token.startLine - 1,
389
+ token.startColumn - 1,
390
+ token.text.length
391
+ ];
392
+ const reference = normalizeReference(label);
393
+ const dictionary = isShortcut ? shortcuts : references;
394
+ const referenceData = dictionary.get(reference) || [];
395
+ referenceData.push(referenceDatum);
396
+ dictionary.set(reference, referenceData);
397
+ };
490
398
  const definitions = new Map();
491
399
  const definitionLineIndices = [];
492
400
  const duplicateDefinitions = [];
493
- const references = new Map();
494
- const shortcuts = new Map();
495
401
  const filteredTokens =
496
402
  micromark.filterByTypes(
497
403
  tokens,
@@ -501,7 +407,9 @@ function getReferenceLinkImageData(tokens) {
501
407
  // definitions and definitionLineIndices
502
408
  "definitionLabelString", "gfmFootnoteDefinitionLabelString",
503
409
  // references and shortcuts
504
- "gfmFootnoteCall", "image", "link"
410
+ "gfmFootnoteCall", "image", "link",
411
+ // undefined link labels
412
+ "undefinedReferenceCollapsed", "undefinedReferenceFull", "undefinedReferenceShortcut"
505
413
  ]
506
414
  );
507
415
  for (const token of filteredTokens) {
@@ -524,15 +432,10 @@ function getReferenceLinkImageData(tokens) {
524
432
  if (definitions.has(reference)) {
525
433
  duplicateDefinitions.push([ reference, token.startLine - 1 ]);
526
434
  } else {
527
- let destinationString = null;
528
435
  const parent =
529
- micromark.getTokenParentOfType(token, [ "definition" ]);
530
- if (parent) {
531
- destinationString = micromark.getTokenTextByType(
532
- micromark.filterByPredicate(parent.children),
533
- "definitionDestinationString"
534
- );
535
- }
436
+ micromark.getParentOfType(token, [ "definition" ]);
437
+ const destinationString = parent &&
438
+ micromark.getDescendantsByType(parent, [ "definitionDestination", "definitionDestinationRaw", "definitionDestinationString" ])[0]?.text;
536
439
  definitions.set(
537
440
  reference,
538
441
  [ token.startLine - 1, destinationString ]
@@ -544,67 +447,38 @@ function getReferenceLinkImageData(tokens) {
544
447
  case "image":
545
448
  case "link":
546
449
  {
547
- let isShortcut = false;
548
- let isFullOrCollapsed = false;
549
- let labelText = null;
550
- let referenceStringText = null;
551
- const shortcutCandidate =
552
- micromark.matchAndGetTokensByType(token.children, [ "label" ]);
553
- if (shortcutCandidate) {
554
- labelText =
555
- micromark.getTokenTextByType(
556
- shortcutCandidate[0].children, "labelText"
557
- );
558
- isShortcut = (labelText !== null);
559
- }
560
- const fullAndCollapsedCandidate =
561
- micromark.matchAndGetTokensByType(
562
- token.children, [ "label", "reference" ]
450
+ // Identify if shortcut or full/collapsed
451
+ let isShortcut = (token.children.length === 1);
452
+ const isFullOrCollapsed = (token.children.length === 2) && !token.children.some((t) => t.type === "resource");
453
+ const [ labelText ] = micromark.getDescendantsByType(token, [ "label", "labelText" ]);
454
+ const [ referenceString ] = micromark.getDescendantsByType(token, [ "reference", "referenceString" ]);
455
+ let label = labelText?.text;
456
+ // Identify if footnote
457
+ if (!isShortcut && !isFullOrCollapsed) {
458
+ const [ footnoteCallMarker, footnoteCallString ] = token.children.filter(
459
+ (t) => [ "gfmFootnoteCallMarker", "gfmFootnoteCallString" ].includes(t.type)
563
460
  );
564
- if (fullAndCollapsedCandidate) {
565
- labelText =
566
- micromark.getTokenTextByType(
567
- fullAndCollapsedCandidate[0].children, "labelText"
568
- );
569
- referenceStringText =
570
- micromark.getTokenTextByType(
571
- fullAndCollapsedCandidate[1].children, "referenceString"
572
- );
573
- isFullOrCollapsed = (labelText !== null);
574
- }
575
- const footnote = micromark.matchAndGetTokensByType(
576
- token.children,
577
- [
578
- "gfmFootnoteCallLabelMarker", "gfmFootnoteCallMarker",
579
- "gfmFootnoteCallString", "gfmFootnoteCallLabelMarker"
580
- ],
581
- [ "gfmFootnoteCallMarker", "gfmFootnoteCallString" ]
582
- );
583
- if (footnote) {
584
- const callMarkerText = footnote[0].text;
585
- const callString = footnote[1].text;
586
- labelText = `${callMarkerText}${callString}`;
587
- isShortcut = true;
461
+ if (footnoteCallMarker && footnoteCallString) {
462
+ label = `${footnoteCallMarker.text}${footnoteCallString.text}`;
463
+ isShortcut = true;
464
+ }
588
465
  }
589
- // Track shortcuts separately due to ambiguity in "text [text] text"
466
+ // Track link (handle shortcuts separately due to ambiguity in "text [text] text")
590
467
  if (isShortcut || isFullOrCollapsed) {
591
- const referenceDatum = [
592
- token.startLine - 1,
593
- token.startColumn - 1,
594
- token.text.length,
595
- // @ts-ignore
596
- labelText.length,
597
- (referenceStringText || "").length
598
- ];
599
- const reference =
600
- normalizeReference(referenceStringText || labelText);
601
- const dictionary = isShortcut ? shortcuts : references;
602
- const referenceData = dictionary.get(reference) || [];
603
- referenceData.push(referenceDatum);
604
- dictionary.set(reference, referenceData);
468
+ addReferenceToDictionary(token, referenceString?.text || label, isShortcut);
605
469
  }
606
470
  }
607
471
  break;
472
+ case "undefinedReferenceCollapsed":
473
+ case "undefinedReferenceFull":
474
+ case "undefinedReferenceShortcut":
475
+ {
476
+ const undefinedReference = micromark.getDescendantsByType(token, [ "undefinedReference" ])[0];
477
+ const label = undefinedReference.children.map((t) => t.text).join("");
478
+ const isShortcut = (token.type === "undefinedReferenceShortcut");
479
+ addReferenceToDictionary(token, label, isShortcut);
480
+ }
481
+ break;
608
482
  }
609
483
  }
610
484
  return {
@@ -657,120 +531,6 @@ function getPreferredLineEnding(input, os) {
657
531
  }
658
532
  module.exports.getPreferredLineEnding = getPreferredLineEnding;
659
533
 
660
- /**
661
- * Normalizes the fields of a RuleOnErrorFixInfo instance.
662
- *
663
- * @param {Object} fixInfo RuleOnErrorFixInfo instance.
664
- * @param {number} [lineNumber] Line number.
665
- * @returns {Object} Normalized RuleOnErrorFixInfo instance.
666
- */
667
- function normalizeFixInfo(fixInfo, lineNumber) {
668
- return {
669
- "lineNumber": fixInfo.lineNumber || lineNumber,
670
- "editColumn": fixInfo.editColumn || 1,
671
- "deleteCount": fixInfo.deleteCount || 0,
672
- "insertText": fixInfo.insertText || ""
673
- };
674
- }
675
-
676
- /**
677
- * Fixes the specified error on a line of Markdown content.
678
- *
679
- * @param {string} line Line of Markdown content.
680
- * @param {Object} fixInfo RuleOnErrorFixInfo instance.
681
- * @param {string} [lineEnding] Line ending to use.
682
- * @returns {string | null} Fixed content.
683
- */
684
- function applyFix(line, fixInfo, lineEnding) {
685
- const { editColumn, deleteCount, insertText } = normalizeFixInfo(fixInfo);
686
- const editIndex = editColumn - 1;
687
- return (deleteCount === -1) ?
688
- null :
689
- line.slice(0, editIndex) +
690
- insertText.replace(/\n/g, lineEnding || "\n") +
691
- line.slice(editIndex + deleteCount);
692
- }
693
- module.exports.applyFix = applyFix;
694
-
695
- /**
696
- * Applies as many fixes as possible to Markdown content.
697
- *
698
- * @param {string} input Lines of Markdown content.
699
- * @param {Object[]} errors RuleOnErrorInfo instances.
700
- * @returns {string} Corrected content.
701
- */
702
- function applyFixes(input, errors) {
703
- const lineEnding = getPreferredLineEnding(input, __webpack_require__(/*! node:os */ "?0176"));
704
- const lines = input.split(newLineRe);
705
- // Normalize fixInfo objects
706
- let fixInfos = errors
707
- .filter((error) => error.fixInfo)
708
- .map((error) => normalizeFixInfo(error.fixInfo, error.lineNumber));
709
- // Sort bottom-to-top, line-deletes last, right-to-left, long-to-short
710
- fixInfos.sort((a, b) => {
711
- const aDeletingLine = (a.deleteCount === -1);
712
- const bDeletingLine = (b.deleteCount === -1);
713
- return (
714
- (b.lineNumber - a.lineNumber) ||
715
- (aDeletingLine ? 1 : (bDeletingLine ? -1 : 0)) ||
716
- (b.editColumn - a.editColumn) ||
717
- (b.insertText.length - a.insertText.length)
718
- );
719
- });
720
- // Remove duplicate entries (needed for following collapse step)
721
- let lastFixInfo = {};
722
- fixInfos = fixInfos.filter((fixInfo) => {
723
- const unique = (
724
- (fixInfo.lineNumber !== lastFixInfo.lineNumber) ||
725
- (fixInfo.editColumn !== lastFixInfo.editColumn) ||
726
- (fixInfo.deleteCount !== lastFixInfo.deleteCount) ||
727
- (fixInfo.insertText !== lastFixInfo.insertText)
728
- );
729
- lastFixInfo = fixInfo;
730
- return unique;
731
- });
732
- // Collapse insert/no-delete and no-insert/delete for same line/column
733
- lastFixInfo = {
734
- "lineNumber": -1
735
- };
736
- for (const fixInfo of fixInfos) {
737
- if (
738
- (fixInfo.lineNumber === lastFixInfo.lineNumber) &&
739
- (fixInfo.editColumn === lastFixInfo.editColumn) &&
740
- !fixInfo.insertText &&
741
- (fixInfo.deleteCount > 0) &&
742
- lastFixInfo.insertText &&
743
- !lastFixInfo.deleteCount) {
744
- fixInfo.insertText = lastFixInfo.insertText;
745
- lastFixInfo.lineNumber = 0;
746
- }
747
- lastFixInfo = fixInfo;
748
- }
749
- fixInfos = fixInfos.filter((fixInfo) => fixInfo.lineNumber);
750
- // Apply all (remaining/updated) fixes
751
- let lastLineIndex = -1;
752
- let lastEditIndex = -1;
753
- for (const fixInfo of fixInfos) {
754
- const { lineNumber, editColumn, deleteCount } = fixInfo;
755
- const lineIndex = lineNumber - 1;
756
- const editIndex = editColumn - 1;
757
- if (
758
- (lineIndex !== lastLineIndex) ||
759
- (deleteCount === -1) ||
760
- ((editIndex + deleteCount) <=
761
- (lastEditIndex - ((deleteCount > 0) ? 0 : 1)))
762
- ) {
763
- // @ts-ignore
764
- lines[lineIndex] = applyFix(lines[lineIndex], fixInfo, lineEnding);
765
- }
766
- lastLineIndex = lineIndex;
767
- lastEditIndex = editIndex;
768
- }
769
- // Return corrected input
770
- return lines.filter((line) => line !== null).join(lineEnding);
771
- }
772
- module.exports.applyFixes = applyFixes;
773
-
774
534
  /**
775
535
  * Expands a path with a tilde to an absolute path.
776
536
  *
@@ -784,26 +544,6 @@ function expandTildePath(file, os) {
784
544
  }
785
545
  module.exports.expandTildePath = expandTildePath;
786
546
 
787
- // Copied from markdownlint.js to avoid TypeScript compiler import() issue.
788
- /**
789
- * @typedef {Object} MarkdownItToken
790
- * @property {string[][]} attrs HTML attributes.
791
- * @property {boolean} block Block-level token.
792
- * @property {MarkdownItToken[]} children Child nodes.
793
- * @property {string} content Tag contents.
794
- * @property {boolean} hidden Ignore element.
795
- * @property {string} info Fence info.
796
- * @property {number} level Nesting level.
797
- * @property {number[]} map Beginning/ending line numbers.
798
- * @property {string} markup Markup text.
799
- * @property {Object} meta Arbitrary data.
800
- * @property {number} nesting Level change.
801
- * @property {string} tag HTML tag name.
802
- * @property {string} type Token type.
803
- * @property {number} lineNumber Line number (1-based).
804
- * @property {string} line Line content.
805
- */
806
-
807
547
 
808
548
  /***/ }),
809
549
 
@@ -818,6 +558,12 @@ module.exports.expandTildePath = expandTildePath;
818
558
 
819
559
 
820
560
 
561
+ // Symbol for identifing the flat tokens array from micromark parse
562
+ module.exports.flatTokensSymbol = Symbol("flat-tokens");
563
+
564
+ // Symbol for identifying the htmlFlow token from micromark parse
565
+ module.exports.htmlFlowSymbol = Symbol("html-flow");
566
+
821
567
  // Regular expression for matching common newline characters
822
568
  // See NEWLINES_RE in markdown-it/lib/rules_core/normalize.js
823
569
  module.exports.newLineRe = /\r\n?|\n/g;
@@ -868,16 +614,6 @@ module.exports = micromarkBrowser;
868
614
 
869
615
  /***/ }),
870
616
 
871
- /***/ "?0176":
872
- /*!*************************!*\
873
- !*** node:os (ignored) ***!
874
- \*************************/
875
- /***/ (() => {
876
-
877
- /* (ignored) */
878
-
879
- /***/ }),
880
-
881
617
  /***/ "?d0ee":
882
618
  /*!*************************!*\
883
619
  !*** node:fs (ignored) ***!
@@ -937,10 +673,10 @@ module.exports = {
937
673
 
938
674
  /***/ }),
939
675
 
940
- /***/ "../helpers/micromark.cjs":
941
- /*!********************************!*\
942
- !*** ../helpers/micromark.cjs ***!
943
- \********************************/
676
+ /***/ "../helpers/micromark-helpers.cjs":
677
+ /*!****************************************!*\
678
+ !*** ../helpers/micromark-helpers.cjs ***!
679
+ \****************************************/
944
680
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
945
681
 
946
682
  "use strict";
@@ -948,30 +684,19 @@ module.exports = {
948
684
 
949
685
 
950
686
 
951
- // @ts-ignore
952
- const {
953
- directive, gfmAutolinkLiteral, gfmFootnote, gfmTable, math,
954
- parse, postprocess, preprocess
955
- // @ts-ignore
956
- } = __webpack_require__(/*! markdownlint-micromark */ "markdownlint-micromark");
957
- const { newLineRe } = __webpack_require__(/*! ./shared.js */ "../helpers/shared.js");
958
-
959
- const flatTokensSymbol = Symbol("flat-tokens");
960
- const reparseSymbol = Symbol("reparse");
687
+ const { flatTokensSymbol, htmlFlowSymbol } = __webpack_require__(/*! ./shared.js */ "../helpers/shared.js");
961
688
 
962
- /** @typedef {import("markdownlint-micromark").Event} Event */
963
- /** @typedef {import("markdownlint-micromark").ParseOptions} ParseOptions */
964
689
  /** @typedef {import("markdownlint-micromark").TokenType} TokenType */
965
690
  /** @typedef {import("../lib/markdownlint.js").MicromarkToken} Token */
966
691
 
967
692
  /**
968
- * Determines if a Micromark token is within an htmlFlow.
693
+ * Determines if a Micromark token is within an htmlFlow type.
969
694
  *
970
695
  * @param {Token} token Micromark token.
971
- * @returns {boolean} True iff the token is within an htmlFlow.
696
+ * @returns {boolean} True iff the token is within an htmlFlow type.
972
697
  */
973
698
  function inHtmlFlow(token) {
974
- return token[reparseSymbol];
699
+ return Boolean(token[htmlFlowSymbol]);
975
700
  }
976
701
 
977
702
  /**
@@ -1003,180 +728,6 @@ function isHtmlFlowComment(token) {
1003
728
  return false;
1004
729
  }
1005
730
 
1006
- /**
1007
- * Parses a Markdown document and returns Micromark events.
1008
- *
1009
- * @param {string} markdown Markdown document.
1010
- * @param {ParseOptions} [micromarkOptions] Options for micromark.
1011
- * @param {boolean} [referencesDefined] Treat references as defined.
1012
- * @returns {Event[]} Micromark events.
1013
- */
1014
- function getMicromarkEvents(
1015
- markdown,
1016
- micromarkOptions = {},
1017
- referencesDefined = true
1018
- ) {
1019
-
1020
- // Customize options object to add useful extensions
1021
- micromarkOptions.extensions = micromarkOptions.extensions || [];
1022
- micromarkOptions.extensions.push(
1023
- directive(),
1024
- gfmAutolinkLiteral(),
1025
- gfmFootnote(),
1026
- gfmTable(),
1027
- math()
1028
- );
1029
-
1030
- // Use micromark to parse document into Events
1031
- const encoding = undefined;
1032
- const eol = true;
1033
- const parseContext = parse(micromarkOptions);
1034
- if (referencesDefined) {
1035
- // Customize ParseContext to treat all references as defined
1036
- parseContext.defined.includes = (searchElement) => searchElement.length > 0;
1037
- }
1038
- const chunks = preprocess()(markdown, encoding, eol);
1039
- const events = postprocess(parseContext.document().write(chunks));
1040
- return events;
1041
- }
1042
-
1043
- /**
1044
- * Parses a Markdown document and returns (frozen) tokens.
1045
- *
1046
- * @param {string} markdown Markdown document.
1047
- * @param {ParseOptions} micromarkOptions Options for micromark.
1048
- * @param {boolean} referencesDefined Treat references as defined.
1049
- * @param {number} lineDelta Offset to apply to start/end line.
1050
- * @param {Token} [ancestor] Parent of top-most tokens.
1051
- * @returns {Token[]} Micromark tokens (frozen).
1052
- */
1053
- function micromarkParseWithOffset(
1054
- markdown,
1055
- micromarkOptions,
1056
- referencesDefined,
1057
- lineDelta,
1058
- ancestor
1059
- ) {
1060
- // Use micromark to parse document into Events
1061
- const events = getMicromarkEvents(
1062
- markdown, micromarkOptions, referencesDefined
1063
- );
1064
-
1065
- // Create Token objects
1066
- const document = [];
1067
- let flatTokens = [];
1068
- /** @type {Token} */
1069
- const root = {
1070
- "type": "data",
1071
- "startLine": -1,
1072
- "startColumn": -1,
1073
- "endLine": -1,
1074
- "endColumn": -1,
1075
- "text": "ROOT",
1076
- "children": document,
1077
- "parent": null
1078
- };
1079
- const history = [ root ];
1080
- let current = root;
1081
- // eslint-disable-next-line jsdoc/valid-types
1082
- /** @type ParseOptions | null */
1083
- let reparseOptions = null;
1084
- let lines = null;
1085
- let skipHtmlFlowChildren = false;
1086
- for (const event of events) {
1087
- const [ kind, token, context ] = event;
1088
- const { type, start, end } = token;
1089
- const { "column": startColumn, "line": startLine } = start;
1090
- const { "column": endColumn, "line": endLine } = end;
1091
- const text = context.sliceSerialize(token);
1092
- if ((kind === "enter") && !skipHtmlFlowChildren) {
1093
- const previous = current;
1094
- history.push(previous);
1095
- current = {
1096
- type,
1097
- "startLine": startLine + lineDelta,
1098
- startColumn,
1099
- "endLine": endLine + lineDelta,
1100
- endColumn,
1101
- text,
1102
- "children": [],
1103
- "parent": ((previous === root) ? (ancestor || null) : previous)
1104
- };
1105
- if (ancestor) {
1106
- Object.defineProperty(current, reparseSymbol, { "value": true });
1107
- }
1108
- previous.children.push(current);
1109
- flatTokens.push(current);
1110
- if ((current.type === "htmlFlow") && !isHtmlFlowComment(current)) {
1111
- skipHtmlFlowChildren = true;
1112
- if (!reparseOptions || !lines) {
1113
- reparseOptions = {
1114
- ...micromarkOptions,
1115
- "extensions": [
1116
- {
1117
- "disable": {
1118
- "null": [ "codeIndented", "htmlFlow" ]
1119
- }
1120
- }
1121
- ]
1122
- };
1123
- lines = markdown.split(newLineRe);
1124
- }
1125
- const reparseMarkdown = lines
1126
- .slice(current.startLine - 1, current.endLine)
1127
- .join("\n");
1128
- const tokens = micromarkParseWithOffset(
1129
- reparseMarkdown,
1130
- reparseOptions,
1131
- referencesDefined,
1132
- current.startLine - 1,
1133
- current
1134
- );
1135
- current.children = tokens;
1136
- // Avoid stack overflow of Array.push(...spread)
1137
- // eslint-disable-next-line unicorn/prefer-spread
1138
- flatTokens = flatTokens.concat(tokens[flatTokensSymbol]);
1139
- }
1140
- } else if (kind === "exit") {
1141
- if (type === "htmlFlow") {
1142
- skipHtmlFlowChildren = false;
1143
- }
1144
- if (!skipHtmlFlowChildren) {
1145
- Object.freeze(current.children);
1146
- Object.freeze(current);
1147
- // @ts-ignore
1148
- current = history.pop();
1149
- }
1150
- }
1151
- }
1152
-
1153
- // Return document
1154
- Object.defineProperty(document, flatTokensSymbol, { "value": flatTokens });
1155
- Object.freeze(document);
1156
- return document;
1157
- }
1158
-
1159
- /**
1160
- * Parses a Markdown document and returns (frozen) tokens.
1161
- *
1162
- * @param {string} markdown Markdown document.
1163
- * @param {ParseOptions} [micromarkOptions] Options for micromark.
1164
- * @param {boolean} [referencesDefined] Treat references as defined.
1165
- * @returns {Token[]} Micromark tokens (frozen).
1166
- */
1167
- function micromarkParse(
1168
- markdown,
1169
- micromarkOptions = {},
1170
- referencesDefined = true
1171
- ) {
1172
- return micromarkParseWithOffset(
1173
- markdown,
1174
- micromarkOptions,
1175
- referencesDefined,
1176
- 0
1177
- );
1178
- }
1179
-
1180
731
  /**
1181
732
  * Adds a range of numbers to a set.
1182
733
  *
@@ -1255,8 +806,7 @@ function filterByPredicate(tokens, allowed, transformChildren) {
1255
806
  * @returns {Token[]} Filtered tokens.
1256
807
  */
1257
808
  function filterByTypes(tokens, types, htmlFlow) {
1258
- const predicate = (token) =>
1259
- (htmlFlow || !inHtmlFlow(token)) && types.includes(token.type);
809
+ const predicate = (token) => types.includes(token.type) && (htmlFlow || !inHtmlFlow(token));
1260
810
  const flatTokens = tokens[flatTokensSymbol];
1261
811
  if (flatTokens) {
1262
812
  return flatTokens.filter(predicate);
@@ -1264,46 +814,41 @@ function filterByTypes(tokens, types, htmlFlow) {
1264
814
  return filterByPredicate(tokens, predicate);
1265
815
  }
1266
816
 
817
+ /**
818
+ * Gets the blockquote prefix text (if any) for the specified line number.
819
+ *
820
+ * @param {Token[]} tokens Micromark tokens.
821
+ * @param {number} lineNumber Line number to examine.
822
+ * @param {number} [count] Number of times to repeat.
823
+ * @returns {string} Blockquote prefix text.
824
+ */
825
+ function getBlockQuotePrefixText(tokens, lineNumber, count = 1) {
826
+ return filterByTypes(tokens, [ "blockQuotePrefix", "linePrefix" ])
827
+ .filter((prefix) => prefix.startLine === lineNumber)
828
+ .map((prefix) => prefix.text)
829
+ .join("")
830
+ .trimEnd()
831
+ // eslint-disable-next-line unicorn/prefer-spread
832
+ .concat("\n")
833
+ .repeat(count);
834
+ };
835
+
1267
836
  /**
1268
837
  * Gets a list of nested Micromark token descendants by type path.
1269
838
  *
1270
839
  * @param {Token|Token[]} parent Micromark token parent or parents.
1271
- * @param {TokenType[]} typePath Micromark token type path.
840
+ * @param {(TokenType|TokenType[])[]} typePath Micromark token type path.
1272
841
  * @returns {Token[]} Micromark token descendants.
1273
842
  */
1274
843
  function getDescendantsByType(parent, typePath) {
1275
844
  let tokens = Array.isArray(parent) ? parent : [ parent ];
1276
845
  for (const type of typePath) {
1277
- tokens = tokens.flatMap((t) => t.children).filter((t) => t.type === type);
846
+ const predicate = (token) => Array.isArray(type) ? type.includes(token.type) : (type === token.type);
847
+ tokens = tokens.flatMap((t) => t.children.filter(predicate));
1278
848
  }
1279
849
  return tokens;
1280
850
  }
1281
851
 
1282
- // eslint-disable-next-line jsdoc/valid-types
1283
- /** @typedef {readonly string[]} ReadonlyStringArray */
1284
-
1285
- /**
1286
- * Gets the line/column/length exclusions for a Micromark token.
1287
- *
1288
- * @param {ReadonlyStringArray} lines File/string lines.
1289
- * @param {Token} token Micromark token.
1290
- * @returns {number[][]} Exclusions (line number, start column, length).
1291
- */
1292
- function getExclusionsForToken(lines, token) {
1293
- const exclusions = [];
1294
- const { endColumn, endLine, startColumn, startLine } = token;
1295
- for (let lineNumber = startLine; lineNumber <= endLine; lineNumber++) {
1296
- const start = (lineNumber === startLine) ? startColumn : 1;
1297
- const end = (lineNumber === endLine) ? endColumn : lines[lineNumber - 1].length;
1298
- exclusions.push([
1299
- lineNumber,
1300
- start,
1301
- end - start + 1
1302
- ]);
1303
- }
1304
- return exclusions;
1305
- }
1306
-
1307
852
  /**
1308
853
  * Gets the heading level of a Micromark heading tokan.
1309
854
  *
@@ -1311,12 +856,12 @@ function getExclusionsForToken(lines, token) {
1311
856
  * @returns {number} Heading level.
1312
857
  */
1313
858
  function getHeadingLevel(heading) {
1314
- const headingSequence = filterByTypes(
1315
- heading.children,
1316
- [ "atxHeadingSequence", "setextHeadingLineSequence" ]
1317
- );
1318
859
  let level = 1;
1319
- const { text } = headingSequence[0];
860
+ const headingSequence = heading.children.find(
861
+ (child) => [ "atxHeadingSequence", "setextHeadingLine" ].includes(child.type)
862
+ );
863
+ // @ts-ignore
864
+ const { text } = headingSequence;
1320
865
  if (text[0] === "#") {
1321
866
  level = Math.min(text.length, 6);
1322
867
  } else if (text[0] === "-") {
@@ -1335,9 +880,8 @@ function getHeadingStyle(heading) {
1335
880
  if (heading.type === "setextHeading") {
1336
881
  return "setext";
1337
882
  }
1338
- const atxHeadingSequenceLength = filterByTypes(
1339
- heading.children,
1340
- [ "atxHeadingSequence" ]
883
+ const atxHeadingSequenceLength = heading.children.filter(
884
+ (child) => child.type === "atxHeadingSequence"
1341
885
  ).length;
1342
886
  if (atxHeadingSequenceLength === 1) {
1343
887
  return "atx";
@@ -1352,10 +896,7 @@ function getHeadingStyle(heading) {
1352
896
  * @returns {string} Heading text.
1353
897
  */
1354
898
  function getHeadingText(heading) {
1355
- const headingTexts = filterByTypes(
1356
- heading.children,
1357
- [ "atxHeadingText", "setextHeadingText" ]
1358
- );
899
+ const headingTexts = getDescendantsByType(heading, [ [ "atxHeadingText", "setextHeadingText" ] ]);
1359
900
  return headingTexts[0]?.text.replace(/[\r\n]+/g, " ") || "";
1360
901
  }
1361
902
 
@@ -1396,7 +937,7 @@ function getHtmlTagInfo(token) {
1396
937
  * @param {TokenType[]} types Types to allow.
1397
938
  * @returns {Token | null} Parent token.
1398
939
  */
1399
- function getTokenParentOfType(token, types) {
940
+ function getParentOfType(token, types) {
1400
941
  /** @type {Token | null} */
1401
942
  let current = token;
1402
943
  while ((current = current.parent) && !types.includes(current.type)) {
@@ -1405,54 +946,6 @@ function getTokenParentOfType(token, types) {
1405
946
  return current;
1406
947
  }
1407
948
 
1408
- /**
1409
- * Get the text of the first match from a list of Micromark tokens by type.
1410
- *
1411
- * @param {Token[]} tokens Micromark tokens.
1412
- * @param {TokenType} type Type to match.
1413
- * @returns {string | null} Text of token.
1414
- */
1415
- function getTokenTextByType(tokens, type) {
1416
- const filtered = tokens.filter((token) => token.type === type);
1417
- return (filtered.length > 0) ? filtered[0].text : null;
1418
- }
1419
-
1420
- /**
1421
- * Determines a list of Micromark tokens matches and returns a subset.
1422
- *
1423
- * @param {Token[]} tokens Micromark tokens.
1424
- * @param {TokenType[]} matchTypes Types to match.
1425
- * @param {TokenType[]} [resultTypes] Types to return.
1426
- * @returns {Token[] | null} Matching tokens.
1427
- */
1428
- function matchAndGetTokensByType(tokens, matchTypes, resultTypes) {
1429
- if (tokens.length !== matchTypes.length) {
1430
- return null;
1431
- }
1432
- resultTypes = resultTypes || matchTypes;
1433
- const result = [];
1434
- // eslint-disable-next-line unicorn/no-for-loop
1435
- for (let i = 0; i < matchTypes.length; i++) {
1436
- if (tokens[i].type !== matchTypes[i]) {
1437
- return null;
1438
- } else if (resultTypes.includes(matchTypes[i])) {
1439
- result.push(tokens[i]);
1440
- }
1441
- }
1442
- return result;
1443
- }
1444
-
1445
- /**
1446
- * Returns the specified token iff it is of the desired type.
1447
- *
1448
- * @param {Token} token Micromark token candidate.
1449
- * @param {TokenType} type Desired type.
1450
- * @returns {Token | null} Token instance.
1451
- */
1452
- function tokenIfType(token, type) {
1453
- return (token && (token.type === type)) ? token : null;
1454
- }
1455
-
1456
949
  /**
1457
950
  * Set containing token types that do not contain content.
1458
951
  *
@@ -1469,24 +962,343 @@ const nonContentTokens = new Set([
1469
962
  ]);
1470
963
 
1471
964
  module.exports = {
1472
- "parse": micromarkParse,
1473
965
  addRangeToSet,
1474
966
  filterByPredicate,
1475
967
  filterByTypes,
968
+ getBlockQuotePrefixText,
1476
969
  getDescendantsByType,
1477
- getExclusionsForToken,
1478
970
  getHeadingLevel,
1479
971
  getHeadingStyle,
1480
972
  getHeadingText,
1481
973
  getHtmlTagInfo,
1482
- getMicromarkEvents,
1483
- getTokenParentOfType,
1484
- getTokenTextByType,
974
+ getParentOfType,
1485
975
  inHtmlFlow,
1486
976
  isHtmlFlowComment,
1487
- matchAndGetTokensByType,
1488
- nonContentTokens,
1489
- tokenIfType
977
+ nonContentTokens
978
+ };
979
+
980
+
981
+ /***/ }),
982
+
983
+ /***/ "../helpers/micromark-parse.cjs":
984
+ /*!**************************************!*\
985
+ !*** ../helpers/micromark-parse.cjs ***!
986
+ \**************************************/
987
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
988
+
989
+ "use strict";
990
+ // @ts-check
991
+
992
+
993
+
994
+ const micromark = __webpack_require__(/*! markdownlint-micromark */ "markdownlint-micromark");
995
+ const { isHtmlFlowComment } = __webpack_require__(/*! ./micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
996
+ const { flatTokensSymbol, htmlFlowSymbol, newLineRe } = __webpack_require__(/*! ./shared.js */ "../helpers/shared.js");
997
+
998
+ /** @typedef {import("markdownlint-micromark").Construct} Construct */
999
+ /** @typedef {import("markdownlint-micromark").Event} Event */
1000
+ /** @typedef {import("markdownlint-micromark").ParseOptions} MicromarkParseOptions */
1001
+ /** @typedef {import("markdownlint-micromark").State} State */
1002
+ /** @typedef {import("markdownlint-micromark").Token} Token */
1003
+ /** @typedef {import("markdownlint-micromark").Tokenizer} Tokenizer */
1004
+ /** @typedef {import("../lib/markdownlint.js").MicromarkToken} MicromarkToken */
1005
+
1006
+ /**
1007
+ * Parse options.
1008
+ *
1009
+ * @typedef {Object} ParseOptions
1010
+ * @property {boolean} [freezeTokens] Whether to freeze output Tokens.
1011
+ */
1012
+
1013
+ /**
1014
+ * Parses a Markdown document and returns Micromark events.
1015
+ *
1016
+ * @param {string} markdown Markdown document.
1017
+ * @param {MicromarkParseOptions} [micromarkParseOptions] Options for micromark.
1018
+ * @returns {Event[]} Micromark events.
1019
+ */
1020
+ function getEvents(
1021
+ markdown,
1022
+ micromarkParseOptions = {}
1023
+ ) {
1024
+ // Customize extensions list to add useful extensions
1025
+ const extensions = [
1026
+ micromark.directive(),
1027
+ micromark.gfmAutolinkLiteral(),
1028
+ micromark.gfmFootnote(),
1029
+ micromark.gfmTable(),
1030
+ micromark.math(),
1031
+ ...(micromarkParseOptions.extensions || [])
1032
+ ];
1033
+
1034
+ // // Shim labelEnd to identify undefined link labels
1035
+ /** @type {Event[][]} */
1036
+ const artificialEventLists = [];
1037
+ /** @type {Construct} */
1038
+ const labelEnd =
1039
+ // @ts-ignore
1040
+ micromark.labelEnd;
1041
+ const tokenizeOriginal = labelEnd.tokenize;
1042
+
1043
+ /** @type {Tokenizer} */
1044
+ function tokenizeShim(effects, okOriginal, nokOriginal) {
1045
+ // eslint-disable-next-line consistent-this, unicorn/no-this-assignment, no-invalid-this
1046
+ const tokenizeContext = this;
1047
+ const events = tokenizeContext.events;
1048
+
1049
+ /** @type {State} */
1050
+ const nokShim = (code) => {
1051
+ // Find start of label (image or link)
1052
+ let indexStart = events.length;
1053
+ while (--indexStart >= 0) {
1054
+ const event = events[indexStart];
1055
+ const [ kind, token ] = event;
1056
+ if (kind === "enter") {
1057
+ const { type } = token;
1058
+ if ((type === "labelImage") || (type === "labelLink")) {
1059
+ // Found it
1060
+ break;
1061
+ }
1062
+ }
1063
+ }
1064
+
1065
+ // If found...
1066
+ if (indexStart >= 0) {
1067
+ // Create artificial enter/exit events and replicate all data/lineEnding events within
1068
+ const eventStart = events[indexStart];
1069
+ const [ , eventStartToken ] = eventStart;
1070
+ const eventEnd = events[events.length - 1];
1071
+ const [ , eventEndToken ] = eventEnd;
1072
+ /** @type {Token} */
1073
+ const undefinedReferenceType = {
1074
+ "type": "undefinedReferenceShortcut",
1075
+ "start": eventStartToken.start,
1076
+ "end": eventEndToken.end
1077
+ };
1078
+ /** @type {Token} */
1079
+ const undefinedReference = {
1080
+ "type": "undefinedReference",
1081
+ "start": eventStartToken.start,
1082
+ "end": eventEndToken.end
1083
+ };
1084
+ const eventsToReplicate = events
1085
+ .slice(indexStart)
1086
+ .filter((event) => {
1087
+ const [ , eventToken ] = event;
1088
+ const { type } = eventToken;
1089
+ return (type === "data") || (type === "lineEnding");
1090
+ });
1091
+
1092
+ // Determine the type of the undefined reference
1093
+ const previousUndefinedEvent = (artificialEventLists.length > 0) && artificialEventLists[artificialEventLists.length - 1][0];
1094
+ const previousUndefinedToken = previousUndefinedEvent && previousUndefinedEvent[1];
1095
+ if (
1096
+ previousUndefinedToken &&
1097
+ (previousUndefinedToken.end.line === undefinedReferenceType.start.line) &&
1098
+ (previousUndefinedToken.end.column === undefinedReferenceType.start.column)
1099
+ ) {
1100
+ // Previous undefined reference event is immediately before this one
1101
+ if (eventsToReplicate.length === 0) {
1102
+ // The pair represent a collapsed reference (ex: [...][])
1103
+ previousUndefinedToken.type = "undefinedReferenceCollapsed";
1104
+ previousUndefinedToken.end = eventEndToken.end;
1105
+ } else {
1106
+ // The pair represent a full reference (ex: [...][...])
1107
+ undefinedReferenceType.type = "undefinedReferenceFull";
1108
+ undefinedReferenceType.start = previousUndefinedToken.start;
1109
+ artificialEventLists.pop();
1110
+ }
1111
+ }
1112
+
1113
+ // Create artificial event list and replicate content
1114
+ const text = eventsToReplicate
1115
+ .filter((event) => event[0] === "enter")
1116
+ .map((event) => tokenizeContext.sliceSerialize(event[1]))
1117
+ .join("")
1118
+ .trim();
1119
+ if ((text.length > 0) && !text.includes("]")) {
1120
+ /** @type {Event[]} */
1121
+ const artificialEvents = [];
1122
+ artificialEvents.push(
1123
+ [ "enter", undefinedReferenceType, tokenizeContext ],
1124
+ [ "enter", undefinedReference, tokenizeContext ]
1125
+ );
1126
+ for (const event of eventsToReplicate) {
1127
+ const [ kind, token ] = event;
1128
+ // Copy token because the current object will get modified by the parser
1129
+ artificialEvents.push([ kind, { ...token }, tokenizeContext ]);
1130
+ }
1131
+ artificialEvents.push(
1132
+ [ "exit", undefinedReference, tokenizeContext ],
1133
+ [ "exit", undefinedReferenceType, tokenizeContext ]
1134
+ );
1135
+ artificialEventLists.push(artificialEvents);
1136
+ }
1137
+ }
1138
+
1139
+ // Continue with original behavior
1140
+ return nokOriginal(code);
1141
+ };
1142
+
1143
+ // Shim nok handler of labelEnd's tokenize
1144
+ return tokenizeOriginal.call(tokenizeContext, effects, okOriginal, nokShim);
1145
+ }
1146
+
1147
+ try {
1148
+ // Shim labelEnd behavior to detect undefined references
1149
+ labelEnd.tokenize = tokenizeShim;
1150
+
1151
+ // Use micromark to parse document into Events
1152
+ const encoding = undefined;
1153
+ const eol = true;
1154
+ const parseContext = micromark.parse({ ...micromarkParseOptions, extensions });
1155
+ const chunks = micromark.preprocess()(markdown, encoding, eol);
1156
+ const events = micromark.postprocess(parseContext.document().write(chunks));
1157
+
1158
+ // Append artificial events and return all events
1159
+ // eslint-disable-next-line unicorn/prefer-spread
1160
+ return events.concat(...artificialEventLists);
1161
+ } finally {
1162
+ // Restore shimmed labelEnd behavior
1163
+ labelEnd.tokenize = tokenizeOriginal;
1164
+ }
1165
+ }
1166
+
1167
+ /**
1168
+ * Parses a Markdown document and returns micromark tokens (internal).
1169
+ *
1170
+ * @param {string} markdown Markdown document.
1171
+ * @param {ParseOptions} [parseOptions] Options.
1172
+ * @param {MicromarkParseOptions} [micromarkParseOptions] Options for micromark.
1173
+ * @param {number} [lineDelta] Offset for start/end line.
1174
+ * @param {MicromarkToken} [ancestor] Parent of top-most tokens.
1175
+ * @returns {MicromarkToken[]} Micromark tokens.
1176
+ */
1177
+ function parseInternal(
1178
+ markdown,
1179
+ parseOptions = {},
1180
+ micromarkParseOptions = {},
1181
+ lineDelta = 0,
1182
+ ancestor = undefined
1183
+ ) {
1184
+ // Get options
1185
+ const freezeTokens = Boolean(parseOptions.freezeTokens);
1186
+
1187
+ // Use micromark to parse document into Events
1188
+ const events = getEvents(markdown, micromarkParseOptions);
1189
+
1190
+ // Create Token objects
1191
+ const document = [];
1192
+ let flatTokens = [];
1193
+ /** @type {MicromarkToken} */
1194
+ const root = {
1195
+ "type": "data",
1196
+ "startLine": -1,
1197
+ "startColumn": -1,
1198
+ "endLine": -1,
1199
+ "endColumn": -1,
1200
+ "text": "ROOT",
1201
+ "children": document,
1202
+ "parent": null
1203
+ };
1204
+ const history = [ root ];
1205
+ let current = root;
1206
+ // eslint-disable-next-line jsdoc/valid-types
1207
+ /** @type MicromarkParseOptions | null */
1208
+ let reparseOptions = null;
1209
+ let lines = null;
1210
+ let skipHtmlFlowChildren = false;
1211
+ for (const event of events) {
1212
+ const [ kind, token, context ] = event;
1213
+ const { type, start, end } = token;
1214
+ const { "column": startColumn, "line": startLine } = start;
1215
+ const { "column": endColumn, "line": endLine } = end;
1216
+ const text = context.sliceSerialize(token);
1217
+ if ((kind === "enter") && !skipHtmlFlowChildren) {
1218
+ const previous = current;
1219
+ history.push(previous);
1220
+ current = {
1221
+ type,
1222
+ "startLine": startLine + lineDelta,
1223
+ startColumn,
1224
+ "endLine": endLine + lineDelta,
1225
+ endColumn,
1226
+ text,
1227
+ "children": [],
1228
+ "parent": ((previous === root) ? (ancestor || null) : previous)
1229
+ };
1230
+ if (ancestor) {
1231
+ Object.defineProperty(current, htmlFlowSymbol, { "value": true });
1232
+ }
1233
+ previous.children.push(current);
1234
+ flatTokens.push(current);
1235
+ if ((current.type === "htmlFlow") && !isHtmlFlowComment(current)) {
1236
+ skipHtmlFlowChildren = true;
1237
+ if (!reparseOptions || !lines) {
1238
+ reparseOptions = {
1239
+ ...micromarkParseOptions,
1240
+ "extensions": [
1241
+ {
1242
+ "disable": {
1243
+ "null": [ "codeIndented", "htmlFlow" ]
1244
+ }
1245
+ }
1246
+ ]
1247
+ };
1248
+ lines = markdown.split(newLineRe);
1249
+ }
1250
+ const reparseMarkdown = lines
1251
+ .slice(current.startLine - 1, current.endLine)
1252
+ .join("\n");
1253
+ const tokens = parseInternal(
1254
+ reparseMarkdown,
1255
+ parseOptions,
1256
+ reparseOptions,
1257
+ current.startLine - 1,
1258
+ current
1259
+ );
1260
+ current.children = tokens;
1261
+ // Avoid stack overflow of Array.push(...spread)
1262
+ // eslint-disable-next-line unicorn/prefer-spread
1263
+ flatTokens = flatTokens.concat(tokens[flatTokensSymbol]);
1264
+ }
1265
+ } else if (kind === "exit") {
1266
+ if (type === "htmlFlow") {
1267
+ skipHtmlFlowChildren = false;
1268
+ }
1269
+ if (!skipHtmlFlowChildren) {
1270
+ if (freezeTokens) {
1271
+ Object.freeze(current.children);
1272
+ Object.freeze(current);
1273
+ }
1274
+ // @ts-ignore
1275
+ current = history.pop();
1276
+ }
1277
+ }
1278
+ }
1279
+
1280
+ // Return document
1281
+ Object.defineProperty(document, flatTokensSymbol, { "value": flatTokens });
1282
+ if (freezeTokens) {
1283
+ Object.freeze(document);
1284
+ }
1285
+ return document;
1286
+ }
1287
+
1288
+ /**
1289
+ * Parses a Markdown document and returns micromark tokens.
1290
+ *
1291
+ * @param {string} markdown Markdown document.
1292
+ * @param {ParseOptions} [parseOptions] Options.
1293
+ * @returns {MicromarkToken[]} Micromark tokens.
1294
+ */
1295
+ function parse(markdown, parseOptions) {
1296
+ return parseInternal(markdown, parseOptions);
1297
+ }
1298
+
1299
+ module.exports = {
1300
+ getEvents,
1301
+ parse
1490
1302
  };
1491
1303
 
1492
1304
 
@@ -1504,11 +1316,10 @@ module.exports = {
1504
1316
 
1505
1317
 
1506
1318
  const helpers = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
1507
- const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
1319
+ const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
1508
1320
 
1509
1321
  /** @type {Map<string, object>} */
1510
1322
  const map = new Map();
1511
- // eslint-disable-next-line no-undef-init
1512
1323
  let params = undefined;
1513
1324
 
1514
1325
  /**
@@ -1533,70 +1344,254 @@ function getCached(name, getValue) {
1533
1344
  if (map.has(name)) {
1534
1345
  return map.get(name);
1535
1346
  }
1536
- const value = getValue();
1537
- map.set(name, value);
1538
- return value;
1347
+ const value = getValue();
1348
+ map.set(name, value);
1349
+ return value;
1350
+ }
1351
+
1352
+ /**
1353
+ * Filters a list of Micromark tokens by type and caches the result.
1354
+ *
1355
+ * @param {import("./markdownlint").MicromarkTokenType[]} types Types to allow.
1356
+ * @param {boolean} [htmlFlow] Whether to include htmlFlow content.
1357
+ * @returns {import("./markdownlint").MicromarkToken[]} Filtered tokens.
1358
+ */
1359
+ function filterByTypesCached(types, htmlFlow) {
1360
+ return getCached(
1361
+ // eslint-disable-next-line prefer-rest-params
1362
+ JSON.stringify(arguments),
1363
+ () => filterByTypes(params.parsers.micromark.tokens, types, htmlFlow)
1364
+ );
1365
+ }
1366
+
1367
+ /**
1368
+ * Gets a reference link and image data object.
1369
+ *
1370
+ * @returns {Object} Reference link and image data object.
1371
+ */
1372
+ function getReferenceLinkImageData() {
1373
+ return getCached(
1374
+ getReferenceLinkImageData.name,
1375
+ () => helpers.getReferenceLinkImageData(params.parsers.micromark.tokens)
1376
+ );
1377
+ }
1378
+
1379
+ module.exports = {
1380
+ initialize,
1381
+ filterByTypesCached,
1382
+ getReferenceLinkImageData
1383
+ };
1384
+
1385
+
1386
+ /***/ }),
1387
+
1388
+ /***/ "../lib/constants.js":
1389
+ /*!***************************!*\
1390
+ !*** ../lib/constants.js ***!
1391
+ \***************************/
1392
+ /***/ ((module) => {
1393
+
1394
+ "use strict";
1395
+ // @ts-check
1396
+
1397
+
1398
+
1399
+ module.exports.deprecatedRuleNames = [];
1400
+ module.exports.fixableRuleNames = [
1401
+ "MD004", "MD005", "MD007", "MD009", "MD010", "MD011",
1402
+ "MD012", "MD014", "MD018", "MD019", "MD020", "MD021",
1403
+ "MD022", "MD023", "MD026", "MD027", "MD030", "MD031",
1404
+ "MD032", "MD034", "MD037", "MD038", "MD039", "MD044",
1405
+ "MD047", "MD049", "MD050", "MD051", "MD053", "MD054",
1406
+ "MD058"
1407
+ ];
1408
+ module.exports.homepage = "https://github.com/DavidAnson/markdownlint";
1409
+ module.exports.version = "0.36.0";
1410
+
1411
+
1412
+ /***/ }),
1413
+
1414
+ /***/ "../lib/markdownit.cjs":
1415
+ /*!*****************************!*\
1416
+ !*** ../lib/markdownit.cjs ***!
1417
+ \*****************************/
1418
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1419
+
1420
+ "use strict";
1421
+ // @ts-check
1422
+
1423
+
1424
+
1425
+ const { newLineRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
1426
+
1427
+ /**
1428
+ * @callback InlineCodeSpanCallback
1429
+ * @param {string} code Code content.
1430
+ * @param {number} lineIndex Line index (0-based).
1431
+ * @param {number} columnIndex Column index (0-based).
1432
+ * @param {number} ticks Count of backticks.
1433
+ * @returns {void}
1434
+ */
1435
+
1436
+ /**
1437
+ * Calls the provided function for each inline code span's content.
1438
+ *
1439
+ * @param {string} input Markdown content.
1440
+ * @param {InlineCodeSpanCallback} handler Callback function taking (code,
1441
+ * lineIndex, columnIndex, ticks).
1442
+ * @returns {void}
1443
+ */
1444
+ function forEachInlineCodeSpan(input, handler) {
1445
+ const backtickRe = /`+/g;
1446
+ let match = null;
1447
+ const backticksLengthAndIndex = [];
1448
+ while ((match = backtickRe.exec(input)) !== null) {
1449
+ backticksLengthAndIndex.push([ match[0].length, match.index ]);
1450
+ }
1451
+ const newLinesIndex = [];
1452
+ while ((match = newLineRe.exec(input)) !== null) {
1453
+ newLinesIndex.push(match.index);
1454
+ }
1455
+ let lineIndex = 0;
1456
+ let lineStartIndex = 0;
1457
+ let k = 0;
1458
+ for (let i = 0; i < backticksLengthAndIndex.length - 1; i++) {
1459
+ const [ startLength, startIndex ] = backticksLengthAndIndex[i];
1460
+ if ((startIndex === 0) || (input[startIndex - 1] !== "\\")) {
1461
+ for (let j = i + 1; j < backticksLengthAndIndex.length; j++) {
1462
+ const [ endLength, endIndex ] = backticksLengthAndIndex[j];
1463
+ if (startLength === endLength) {
1464
+ for (; k < newLinesIndex.length; k++) {
1465
+ const newLineIndex = newLinesIndex[k];
1466
+ if (startIndex < newLineIndex) {
1467
+ break;
1468
+ }
1469
+ lineIndex++;
1470
+ lineStartIndex = newLineIndex + 1;
1471
+ }
1472
+ const columnIndex = startIndex - lineStartIndex + startLength;
1473
+ handler(
1474
+ input.slice(startIndex + startLength, endIndex),
1475
+ lineIndex,
1476
+ columnIndex,
1477
+ startLength
1478
+ );
1479
+ i = j;
1480
+ break;
1481
+ }
1482
+ }
1483
+ }
1484
+ }
1485
+ }
1486
+
1487
+ /**
1488
+ * Freeze all freeze-able members of a token and its children.
1489
+ *
1490
+ * @param {import("./markdownlint").MarkdownItToken} token A markdown-it token.
1491
+ * @returns {void}
1492
+ */
1493
+ function freezeToken(token) {
1494
+ if (token.attrs) {
1495
+ for (const attr of token.attrs) {
1496
+ Object.freeze(attr);
1497
+ }
1498
+ Object.freeze(token.attrs);
1499
+ }
1500
+ if (token.children) {
1501
+ for (const child of token.children) {
1502
+ freezeToken(child);
1503
+ }
1504
+ Object.freeze(token.children);
1505
+ }
1506
+ if (token.map) {
1507
+ Object.freeze(token.map);
1508
+ }
1509
+ Object.freeze(token);
1539
1510
  }
1540
1511
 
1541
1512
  /**
1542
- * Filters a list of Micromark tokens by type and caches the result.
1513
+ * Annotate tokens with line/lineNumber and freeze them.
1543
1514
  *
1544
- * @param {import("./markdownlint").MicromarkTokenType[]} types Types to allow.
1545
- * @param {boolean} [htmlFlow] Whether to include htmlFlow content.
1546
- * @returns {import("./markdownlint").MicromarkToken[]} Filtered tokens.
1515
+ * @param {Object[]} tokens Array of markdown-it tokens.
1516
+ * @param {string[]} lines Lines of Markdown content.
1517
+ * @returns {void}
1547
1518
  */
1548
- function filterByTypesCached(types, htmlFlow) {
1549
- return getCached(
1550
- types.join("|"),
1551
- () => filterByTypes(params.parsers.micromark.tokens, types, htmlFlow)
1552
- );
1519
+ function annotateAndFreezeTokens(tokens, lines) {
1520
+ let trMap = null;
1521
+ // eslint-disable-next-line jsdoc/valid-types
1522
+ /** @type import("./markdownlint").MarkdownItToken[] */
1523
+ // @ts-ignore
1524
+ const markdownItTokens = tokens;
1525
+ for (const token of markdownItTokens) {
1526
+ // Provide missing maps for table content
1527
+ if (token.type === "tr_open") {
1528
+ trMap = token.map;
1529
+ } else if (token.type === "tr_close") {
1530
+ trMap = null;
1531
+ }
1532
+ if (!token.map && trMap) {
1533
+ token.map = [ ...trMap ];
1534
+ }
1535
+ // Update token metadata
1536
+ if (token.map) {
1537
+ token.line = lines[token.map[0]];
1538
+ token.lineNumber = token.map[0] + 1;
1539
+ // Trim bottom of token to exclude whitespace lines
1540
+ while (token.map[1] && !((lines[token.map[1] - 1] || "").trim())) {
1541
+ token.map[1]--;
1542
+ }
1543
+ }
1544
+ // Annotate children with lineNumber
1545
+ if (token.children) {
1546
+ const codeSpanExtraLines = [];
1547
+ if (token.children.some((child) => child.type === "code_inline")) {
1548
+ forEachInlineCodeSpan(token.content, (code) => {
1549
+ codeSpanExtraLines.push(code.split(newLineRe).length - 1);
1550
+ });
1551
+ }
1552
+ let lineNumber = token.lineNumber;
1553
+ for (const child of token.children) {
1554
+ child.lineNumber = lineNumber;
1555
+ child.line = lines[lineNumber - 1];
1556
+ if ((child.type === "softbreak") || (child.type === "hardbreak")) {
1557
+ lineNumber++;
1558
+ } else if (child.type === "code_inline") {
1559
+ lineNumber += codeSpanExtraLines.shift();
1560
+ }
1561
+ }
1562
+ }
1563
+ freezeToken(token);
1564
+ }
1565
+ Object.freeze(tokens);
1553
1566
  }
1554
1567
 
1555
1568
  /**
1556
- * Gets a reference link and image data object.
1569
+ * Gets an array of markdown-it tokens for the input.
1557
1570
  *
1558
- * @returns {Object} Reference link and image data object.
1571
+ * @param {import("./markdownlint").Plugin[]} markdownItPlugins Additional plugins.
1572
+ * @param {string} content Markdown content.
1573
+ * @param {string[]} lines Lines of Markdown content.
1574
+ * @returns {import("../lib/markdownlint").MarkdownItToken} Array of markdown-it tokens.
1559
1575
  */
1560
- function getReferenceLinkImageData() {
1561
- return getCached(
1562
- getReferenceLinkImageData.name,
1563
- () => helpers.getReferenceLinkImageData(params.parsers.micromark.tokens)
1564
- );
1565
- }
1576
+ function getMarkdownItTokens(markdownItPlugins, content, lines) {
1577
+ const markdownit = __webpack_require__(/*! markdown-it */ "markdown-it");
1578
+ const md = markdownit({ "html": true });
1579
+ for (const plugin of markdownItPlugins) {
1580
+ // @ts-ignore
1581
+ md.use(...plugin);
1582
+ }
1583
+ const tokens = md.parse(content, {});
1584
+ annotateAndFreezeTokens(tokens, lines);
1585
+ // @ts-ignore
1586
+ return tokens;
1587
+ };
1566
1588
 
1567
1589
  module.exports = {
1568
- initialize,
1569
- filterByTypesCached,
1570
- getReferenceLinkImageData
1590
+ forEachInlineCodeSpan,
1591
+ getMarkdownItTokens
1571
1592
  };
1572
1593
 
1573
1594
 
1574
- /***/ }),
1575
-
1576
- /***/ "../lib/constants.js":
1577
- /*!***************************!*\
1578
- !*** ../lib/constants.js ***!
1579
- \***************************/
1580
- /***/ ((module) => {
1581
-
1582
- "use strict";
1583
- // @ts-check
1584
-
1585
-
1586
-
1587
- module.exports.deprecatedRuleNames = [];
1588
- module.exports.fixableRuleNames = [
1589
- "MD004", "MD005", "MD007", "MD009", "MD010", "MD011",
1590
- "MD012", "MD014", "MD018", "MD019", "MD020", "MD021",
1591
- "MD022", "MD023", "MD026", "MD027", "MD030", "MD031",
1592
- "MD032", "MD034", "MD037", "MD038", "MD039", "MD044",
1593
- "MD047", "MD049", "MD050", "MD051", "MD053", "MD054",
1594
- "MD058"
1595
- ];
1596
- module.exports.homepage = "https://github.com/DavidAnson/markdownlint";
1597
- module.exports.version = "0.35.0";
1598
-
1599
-
1600
1595
  /***/ }),
1601
1596
 
1602
1597
  /***/ "../lib/markdownlint.js":
@@ -1612,8 +1607,8 @@ module.exports.version = "0.35.0";
1612
1607
 
1613
1608
  const path = __webpack_require__(/*! node:path */ "?9a52");
1614
1609
  const { promisify } = __webpack_require__(/*! node:util */ "?39e5");
1615
- const micromark = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
1616
- // const { deprecatedRuleNames } = require("./constants");
1610
+ const micromark = __webpack_require__(/*! ../helpers/micromark-parse.cjs */ "../helpers/micromark-parse.cjs");
1611
+ const { version } = __webpack_require__(/*! ./constants */ "../lib/constants.js");
1617
1612
  const rules = __webpack_require__(/*! ./rules */ "../lib/rules.js");
1618
1613
  const helpers = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
1619
1614
  const cache = __webpack_require__(/*! ./cache */ "../lib/cache.js");
@@ -1666,7 +1661,7 @@ function validateRuleList(ruleList, synchronous) {
1666
1661
  !result &&
1667
1662
  (rule.parser !== undefined) &&
1668
1663
  (rule.parser !== "markdownit") &&
1669
- !((customIndex < 0) && (rule.parser === "micromark")) &&
1664
+ (rule.parser !== "micromark") &&
1670
1665
  (rule.parser !== "none")
1671
1666
  ) {
1672
1667
  result = newError("parser", rule.parser);
@@ -1805,87 +1800,6 @@ function removeFrontMatter(content, frontMatter) {
1805
1800
  };
1806
1801
  }
1807
1802
 
1808
- /**
1809
- * Freeze all freeze-able members of a token and its children.
1810
- *
1811
- * @param {MarkdownItToken} token A markdown-it token.
1812
- * @returns {void}
1813
- */
1814
- function freezeToken(token) {
1815
- if (token.attrs) {
1816
- for (const attr of token.attrs) {
1817
- Object.freeze(attr);
1818
- }
1819
- Object.freeze(token.attrs);
1820
- }
1821
- if (token.children) {
1822
- for (const child of token.children) {
1823
- freezeToken(child);
1824
- }
1825
- Object.freeze(token.children);
1826
- }
1827
- if (token.map) {
1828
- Object.freeze(token.map);
1829
- }
1830
- Object.freeze(token);
1831
- }
1832
-
1833
- /**
1834
- * Annotate tokens with line/lineNumber and freeze them.
1835
- *
1836
- * @param {import("markdown-it").Token[]} tokens Array of markdown-it tokens.
1837
- * @param {string[]} lines Lines of Markdown content.
1838
- * @returns {void}
1839
- */
1840
- function annotateAndFreezeTokens(tokens, lines) {
1841
- let trMap = null;
1842
- // eslint-disable-next-line jsdoc/valid-types
1843
- /** @type MarkdownItToken[] */
1844
- // @ts-ignore
1845
- const markdownItTokens = tokens;
1846
- for (const token of markdownItTokens) {
1847
- // Provide missing maps for table content
1848
- if (token.type === "tr_open") {
1849
- trMap = token.map;
1850
- } else if (token.type === "tr_close") {
1851
- trMap = null;
1852
- }
1853
- if (!token.map && trMap) {
1854
- token.map = [ ...trMap ];
1855
- }
1856
- // Update token metadata
1857
- if (token.map) {
1858
- token.line = lines[token.map[0]];
1859
- token.lineNumber = token.map[0] + 1;
1860
- // Trim bottom of token to exclude whitespace lines
1861
- while (token.map[1] && !((lines[token.map[1] - 1] || "").trim())) {
1862
- token.map[1]--;
1863
- }
1864
- }
1865
- // Annotate children with lineNumber
1866
- if (token.children) {
1867
- const codeSpanExtraLines = [];
1868
- if (token.children.some((child) => child.type === "code_inline")) {
1869
- helpers.forEachInlineCodeSpan(token.content, (code) => {
1870
- codeSpanExtraLines.push(code.split(helpers.newLineRe).length - 1);
1871
- });
1872
- }
1873
- let lineNumber = token.lineNumber;
1874
- for (const child of token.children) {
1875
- child.lineNumber = lineNumber;
1876
- child.line = lines[lineNumber - 1];
1877
- if ((child.type === "softbreak") || (child.type === "hardbreak")) {
1878
- lineNumber++;
1879
- } else if (child.type === "code_inline") {
1880
- lineNumber += codeSpanExtraLines.shift();
1881
- }
1882
- }
1883
- }
1884
- freezeToken(token);
1885
- }
1886
- Object.freeze(tokens);
1887
- }
1888
-
1889
1803
  /**
1890
1804
  * Map rule names/tags to canonical rule name.
1891
1805
  *
@@ -2141,7 +2055,7 @@ function getEnabledRulesPerLineNumber(
2141
2055
  * names.
2142
2056
  * @param {string} name Identifier for the content.
2143
2057
  * @param {string} content Markdown content.
2144
- * @param {GetMarkdownIt} getMarkdownIt Getter for instance of markdown-it.
2058
+ * @param {Plugin[]} markdownItPlugins Additional plugins.
2145
2059
  * @param {Configuration} config Configuration object.
2146
2060
  * @param {ConfigurationParser[] | null} configParsers Configuration parsers.
2147
2061
  * @param {RegExp | null} frontMatter Regular expression for front matter.
@@ -2156,7 +2070,7 @@ function lintContent(
2156
2070
  aliasToRuleNames,
2157
2071
  name,
2158
2072
  content,
2159
- getMarkdownIt,
2073
+ markdownItPlugins,
2160
2074
  config,
2161
2075
  configParsers,
2162
2076
  frontMatter,
@@ -2184,14 +2098,20 @@ function lintContent(
2184
2098
  const needMarkdownItTokens = enabledRuleList.some(
2185
2099
  (rule) => (rule.parser === "markdownit") || (rule.parser === undefined)
2186
2100
  );
2101
+ const customRulesPresent = (ruleList.length !== rules.length);
2187
2102
  // Parse content into parser tokens
2188
- const markdownitTokens = needMarkdownItTokens ? getMarkdownIt().parse(content, {}) : [];
2189
- const micromarkTokens = micromark.parse(content);
2103
+ const micromarkTokens = micromark.parse(
2104
+ content,
2105
+ { "freezeTokens": customRulesPresent }
2106
+ );
2190
2107
  // Hide the content of HTML comments from rules
2108
+ const preClearedContent = content;
2191
2109
  content = helpers.clearHtmlCommentText(content);
2192
- // Parse content into lines and update markdown-it tokens
2110
+ // Parse content into lines and get markdown-it tokens
2193
2111
  const lines = content.split(helpers.newLineRe);
2194
- annotateAndFreezeTokens(markdownitTokens, lines);
2112
+ const markdownitTokens = needMarkdownItTokens ?
2113
+ (__webpack_require__(/*! ./markdownit.cjs */ "../lib/markdownit.cjs").getMarkdownItTokens)(markdownItPlugins, preClearedContent, lines) :
2114
+ [];
2195
2115
  // Create (frozen) parameters for rules
2196
2116
  /** @type {MarkdownParsers} */
2197
2117
  // @ts-ignore
@@ -2212,6 +2132,7 @@ function lintContent(
2212
2132
  const parsersNone = Object.freeze({});
2213
2133
  const paramsBase = {
2214
2134
  name,
2135
+ version,
2215
2136
  "lines": Object.freeze(lines),
2216
2137
  "frontMatterLines": Object.freeze(frontMatterLines)
2217
2138
  };
@@ -2444,7 +2365,7 @@ function lintContent(
2444
2365
  * @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule
2445
2366
  * names.
2446
2367
  * @param {string} file Path of file to lint.
2447
- * @param {GetMarkdownIt} getMarkdownIt Getter for instance of markdown-it.
2368
+ * @param {Plugin[]} markdownItPlugins Additional plugins.
2448
2369
  * @param {Configuration} config Configuration object.
2449
2370
  * @param {ConfigurationParser[] | null} configParsers Configuration parsers.
2450
2371
  * @param {RegExp | null} frontMatter Regular expression for front matter.
@@ -2460,7 +2381,7 @@ function lintFile(
2460
2381
  ruleList,
2461
2382
  aliasToRuleNames,
2462
2383
  file,
2463
- getMarkdownIt,
2384
+ markdownItPlugins,
2464
2385
  config,
2465
2386
  configParsers,
2466
2387
  frontMatter,
@@ -2480,7 +2401,7 @@ function lintFile(
2480
2401
  aliasToRuleNames,
2481
2402
  file,
2482
2403
  content,
2483
- getMarkdownIt,
2404
+ markdownItPlugins,
2484
2405
  config,
2485
2406
  configParsers,
2486
2407
  frontMatter,
@@ -2540,21 +2461,14 @@ function lintInput(options, synchronous, callback) {
2540
2461
  const config = options.config || { "default": true };
2541
2462
  const configParsers = options.configParsers || null;
2542
2463
  const frontMatter = (options.frontMatter === undefined) ?
2543
- helpers.frontMatterRe : options.frontMatter;
2464
+ helpers.frontMatterRe :
2465
+ options.frontMatter;
2544
2466
  const handleRuleFailures = !!options.handleRuleFailures;
2545
2467
  const noInlineConfig = !!options.noInlineConfig;
2546
2468
  const resultVersion = (options.resultVersion === undefined) ?
2547
- 3 : options.resultVersion;
2548
- const getMarkdownIt = () => {
2549
- const markdownit = __webpack_require__(/*! markdown-it */ "markdown-it");
2550
- const md = markdownit({ "html": true });
2551
- const markdownItPlugins = options.markdownItPlugins || [];
2552
- for (const plugin of markdownItPlugins) {
2553
- // @ts-ignore
2554
- md.use(...plugin);
2555
- }
2556
- return md;
2557
- };
2469
+ 3 :
2470
+ options.resultVersion;
2471
+ const markdownItPlugins = options.markdownItPlugins || [];
2558
2472
  const fs = options.fs || __webpack_require__(/*! node:fs */ "?d0ee");
2559
2473
  const aliasToRuleNames = mapAliasToRuleNames(ruleList);
2560
2474
  const results = newResults(ruleList);
@@ -2586,7 +2500,7 @@ function lintInput(options, synchronous, callback) {
2586
2500
  ruleList,
2587
2501
  aliasToRuleNames,
2588
2502
  currentItem,
2589
- getMarkdownIt,
2503
+ markdownItPlugins,
2590
2504
  config,
2591
2505
  configParsers,
2592
2506
  frontMatter,
@@ -2605,7 +2519,7 @@ function lintInput(options, synchronous, callback) {
2605
2519
  aliasToRuleNames,
2606
2520
  currentItem,
2607
2521
  strings[currentItem] || "",
2608
- getMarkdownIt,
2522
+ markdownItPlugins,
2609
2523
  config,
2610
2524
  configParsers,
2611
2525
  frontMatter,
@@ -2889,12 +2803,125 @@ function readConfigSync(file, parsers, fs) {
2889
2803
  helpers.expandTildePath(configExtends, os),
2890
2804
  fs
2891
2805
  );
2892
- return {
2893
- ...readConfigSync(resolvedExtends, parsers, fs),
2894
- ...config
2895
- };
2806
+ return {
2807
+ ...readConfigSync(resolvedExtends, parsers, fs),
2808
+ ...config
2809
+ };
2810
+ }
2811
+ return config;
2812
+ }
2813
+
2814
+ /**
2815
+ * Normalizes the fields of a RuleOnErrorFixInfo instance.
2816
+ *
2817
+ * @param {RuleOnErrorFixInfo} fixInfo RuleOnErrorFixInfo instance.
2818
+ * @param {number} [lineNumber] Line number.
2819
+ * @returns {RuleOnErrorFixInfoNormalized} Normalized RuleOnErrorFixInfo instance.
2820
+ */
2821
+ function normalizeFixInfo(fixInfo, lineNumber = 0) {
2822
+ return {
2823
+ "lineNumber": fixInfo.lineNumber || lineNumber,
2824
+ "editColumn": fixInfo.editColumn || 1,
2825
+ "deleteCount": fixInfo.deleteCount || 0,
2826
+ "insertText": fixInfo.insertText || ""
2827
+ };
2828
+ }
2829
+
2830
+ /**
2831
+ * Applies the specified fix to a Markdown content line.
2832
+ *
2833
+ * @param {string} line Line of Markdown content.
2834
+ * @param {RuleOnErrorFixInfo} fixInfo RuleOnErrorFixInfo instance.
2835
+ * @param {string} [lineEnding] Line ending to use.
2836
+ * @returns {string | null} Fixed content or null if deleted.
2837
+ */
2838
+ function applyFix(line, fixInfo, lineEnding = "\n") {
2839
+ const { editColumn, deleteCount, insertText } = normalizeFixInfo(fixInfo);
2840
+ const editIndex = editColumn - 1;
2841
+ return (deleteCount === -1) ?
2842
+ null :
2843
+ line.slice(0, editIndex) + insertText.replace(/\n/g, lineEnding) + line.slice(editIndex + deleteCount);
2844
+ }
2845
+
2846
+ /**
2847
+ * Applies as many of the specified fixes as possible to Markdown content.
2848
+ *
2849
+ * @param {string} input Lines of Markdown content.
2850
+ * @param {RuleOnErrorInfo[]} errors RuleOnErrorInfo instances.
2851
+ * @returns {string} Fixed content.
2852
+ */
2853
+ function applyFixes(input, errors) {
2854
+ const lineEnding = helpers.getPreferredLineEnding(input, __webpack_require__(/*! node:os */ "?e6c4"));
2855
+ const lines = input.split(helpers.newLineRe);
2856
+ // Normalize fixInfo objects
2857
+ let fixInfos = errors
2858
+ .filter((error) => error.fixInfo)
2859
+ // @ts-ignore
2860
+ .map((error) => normalizeFixInfo(error.fixInfo, error.lineNumber));
2861
+ // Sort bottom-to-top, line-deletes last, right-to-left, long-to-short
2862
+ fixInfos.sort((a, b) => {
2863
+ const aDeletingLine = (a.deleteCount === -1);
2864
+ const bDeletingLine = (b.deleteCount === -1);
2865
+ return (
2866
+ (b.lineNumber - a.lineNumber) ||
2867
+ (aDeletingLine ? 1 : (bDeletingLine ? -1 : 0)) ||
2868
+ (b.editColumn - a.editColumn) ||
2869
+ (b.insertText.length - a.insertText.length)
2870
+ );
2871
+ });
2872
+ // Remove duplicate entries (needed for following collapse step)
2873
+ // eslint-disable-next-line jsdoc/valid-types
2874
+ /** @type RuleOnErrorFixInfo */
2875
+ let lastFixInfo = {};
2876
+ fixInfos = fixInfos.filter((fixInfo) => {
2877
+ const unique = (
2878
+ (fixInfo.lineNumber !== lastFixInfo.lineNumber) ||
2879
+ (fixInfo.editColumn !== lastFixInfo.editColumn) ||
2880
+ (fixInfo.deleteCount !== lastFixInfo.deleteCount) ||
2881
+ (fixInfo.insertText !== lastFixInfo.insertText)
2882
+ );
2883
+ lastFixInfo = fixInfo;
2884
+ return unique;
2885
+ });
2886
+ // Collapse insert/no-delete and no-insert/delete for same line/column
2887
+ lastFixInfo = {
2888
+ "lineNumber": -1
2889
+ };
2890
+ for (const fixInfo of fixInfos) {
2891
+ if (
2892
+ (fixInfo.lineNumber === lastFixInfo.lineNumber) &&
2893
+ (fixInfo.editColumn === lastFixInfo.editColumn) &&
2894
+ !fixInfo.insertText &&
2895
+ (fixInfo.deleteCount > 0) &&
2896
+ lastFixInfo.insertText &&
2897
+ !lastFixInfo.deleteCount) {
2898
+ fixInfo.insertText = lastFixInfo.insertText;
2899
+ lastFixInfo.lineNumber = 0;
2900
+ }
2901
+ lastFixInfo = fixInfo;
2896
2902
  }
2897
- return config;
2903
+ fixInfos = fixInfos.filter((fixInfo) => fixInfo.lineNumber);
2904
+ // Apply all (remaining/updated) fixes
2905
+ let lastLineIndex = -1;
2906
+ let lastEditIndex = -1;
2907
+ for (const fixInfo of fixInfos) {
2908
+ const { lineNumber, editColumn, deleteCount } = fixInfo;
2909
+ const lineIndex = lineNumber - 1;
2910
+ const editIndex = editColumn - 1;
2911
+ if (
2912
+ (lineIndex !== lastLineIndex) ||
2913
+ (deleteCount === -1) ||
2914
+ ((editIndex + deleteCount) <=
2915
+ (lastEditIndex - ((deleteCount > 0) ? 0 : 1)))
2916
+ ) {
2917
+ // @ts-ignore
2918
+ lines[lineIndex] = applyFix(lines[lineIndex], fixInfo, lineEnding);
2919
+ }
2920
+ lastLineIndex = lineIndex;
2921
+ lastEditIndex = editIndex;
2922
+ }
2923
+ // Return corrected input
2924
+ return lines.filter((line) => line !== null).join(lineEnding);
2898
2925
  }
2899
2926
 
2900
2927
  /**
@@ -2903,7 +2930,7 @@ function readConfigSync(file, parsers, fs) {
2903
2930
  * @returns {string} SemVer string.
2904
2931
  */
2905
2932
  function getVersion() {
2906
- return (__webpack_require__(/*! ./constants */ "../lib/constants.js").version);
2933
+ return version;
2907
2934
  }
2908
2935
 
2909
2936
  // Export a/synchronous/Promise APIs
@@ -2916,17 +2943,12 @@ markdownlint.promises = {
2916
2943
  "extendConfig": extendConfigPromise,
2917
2944
  "readConfig": readConfigPromise
2918
2945
  };
2946
+ markdownlint.applyFix = applyFix;
2947
+ markdownlint.applyFixes = applyFixes;
2919
2948
  module.exports = markdownlint;
2920
2949
 
2921
2950
  // Type declarations
2922
2951
 
2923
- /**
2924
- * Function to get an instance of the markdown-it parser.
2925
- *
2926
- * @callback GetMarkdownIt
2927
- * @returns {import("markdown-it")}
2928
- */
2929
-
2930
2952
  /**
2931
2953
  * Function to implement rule logic.
2932
2954
  *
@@ -2947,6 +2969,7 @@ module.exports = markdownlint;
2947
2969
  * @property {readonly string[]} lines File/string lines.
2948
2970
  * @property {readonly string[]} frontMatterLines Front matter lines.
2949
2971
  * @property {RuleConfiguration} config Rule configuration.
2972
+ * @property {string} version Version of the markdownlint library.
2950
2973
  */
2951
2974
 
2952
2975
  /* eslint-enable jsdoc/valid-types */
@@ -3040,6 +3063,16 @@ module.exports = markdownlint;
3040
3063
  * @property {string} [insertText] Text to insert (after deleting).
3041
3064
  */
3042
3065
 
3066
+ /**
3067
+ * RuleOnErrorInfo with all optional properties present.
3068
+ *
3069
+ * @typedef {Object} RuleOnErrorFixInfoNormalized
3070
+ * @property {number} lineNumber Line number (1-based).
3071
+ * @property {number} editColumn Column of the fix (1-based).
3072
+ * @property {number} deleteCount Count of characters to delete.
3073
+ * @property {string} insertText Text to insert (after deleting).
3074
+ */
3075
+
3043
3076
  /**
3044
3077
  * Rule definition.
3045
3078
  *
@@ -3194,7 +3227,7 @@ module.exports = markdownlint;
3194
3227
 
3195
3228
 
3196
3229
  const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
3197
- const { getHeadingLevel } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
3230
+ const { getHeadingLevel } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
3198
3231
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
3199
3232
 
3200
3233
  // eslint-disable-next-line jsdoc/valid-types
@@ -3236,7 +3269,7 @@ module.exports = {
3236
3269
 
3237
3270
 
3238
3271
  const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
3239
- const { getHeadingLevel, getHeadingStyle } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
3272
+ const { getHeadingLevel, getHeadingStyle } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
3240
3273
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
3241
3274
 
3242
3275
  // eslint-disable-next-line jsdoc/valid-types
@@ -3297,7 +3330,7 @@ module.exports = {
3297
3330
 
3298
3331
 
3299
3332
  const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
3300
- const { getDescendantsByType, getTokenParentOfType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
3333
+ const { getDescendantsByType, getParentOfType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
3301
3334
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
3302
3335
 
3303
3336
  const markerToStyle = {
@@ -3337,10 +3370,10 @@ module.exports = {
3337
3370
  for (const listUnordered of filterByTypesCached([ "listUnordered" ])) {
3338
3371
  let nesting = 0;
3339
3372
  if (style === "sublist") {
3340
- /** @type {import("../helpers/micromark.cjs").Token | null} */
3373
+ /** @type {import("../helpers/micromark-helpers.cjs").Token | null} */
3341
3374
  let parent = listUnordered;
3342
3375
  // @ts-ignore
3343
- while ((parent = getTokenParentOfType(parent, [ "listOrdered", "listUnordered" ]))) {
3376
+ while ((parent = getParentOfType(parent, [ "listOrdered", "listUnordered" ]))) {
3344
3377
  nesting++;
3345
3378
  }
3346
3379
  }
@@ -3477,7 +3510,7 @@ module.exports = {
3477
3510
 
3478
3511
 
3479
3512
  const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
3480
- const { getTokenParentOfType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
3513
+ const { getParentOfType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
3481
3514
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
3482
3515
 
3483
3516
  // eslint-disable-next-line jsdoc/valid-types
@@ -3509,11 +3542,11 @@ module.exports = {
3509
3542
  lastBlockQuotePrefix = token;
3510
3543
  } else if (type === "listUnordered") {
3511
3544
  let nesting = 0;
3512
- /** @type {import("../helpers/micromark.cjs").Token | null} */
3545
+ /** @type {import("../helpers/micromark-helpers.cjs").Token | null} */
3513
3546
  let current = token;
3514
3547
  while (
3515
3548
  // @ts-ignore
3516
- (current = getTokenParentOfType(current, unorderedParentTypes))
3549
+ (current = getParentOfType(current, unorderedParentTypes))
3517
3550
  ) {
3518
3551
  if (current.type === "listUnordered") {
3519
3552
  nesting++;
@@ -3576,7 +3609,7 @@ module.exports = {
3576
3609
 
3577
3610
 
3578
3611
  const { addError } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
3579
- const { addRangeToSet } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
3612
+ const { addRangeToSet } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
3580
3613
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
3581
3614
 
3582
3615
  // eslint-disable-next-line jsdoc/valid-types
@@ -3681,8 +3714,8 @@ module.exports = {
3681
3714
 
3682
3715
 
3683
3716
 
3684
- const { addError, withinAnyRange } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
3685
- const { getDescendantsByType, getExclusionsForToken } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
3717
+ const { addError, hasOverlap } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
3718
+ const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
3686
3719
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
3687
3720
 
3688
3721
  const tabRe = /\t+/g;
@@ -3705,9 +3738,8 @@ module.exports = {
3705
3738
  const spaceMultiplier = (spacesPerTab === undefined) ?
3706
3739
  1 :
3707
3740
  Math.max(0, Number(spacesPerTab));
3708
- const exclusions = [];
3709
3741
  // eslint-disable-next-line jsdoc/valid-types
3710
- /** @type import("../helpers/micromark.cjs").TokenType[] */
3742
+ /** @type import("../helpers/micromark-helpers.cjs").TokenType[] */
3711
3743
  const exclusionTypes = [];
3712
3744
  if (includeCode) {
3713
3745
  if (ignoreCodeLanguages.size > 0) {
@@ -3723,24 +3755,29 @@ module.exports = {
3723
3755
  }
3724
3756
  return true;
3725
3757
  });
3726
- for (const codeToken of codeTokens) {
3727
- const exclusionsForToken = getExclusionsForToken(params.lines, codeToken);
3728
- if (codeToken.type === "codeFenced") {
3729
- exclusionsForToken.pop();
3730
- exclusionsForToken.shift();
3731
- }
3732
- exclusions.push(...exclusionsForToken);
3733
- }
3758
+ const codeRanges = codeTokens.map((token) => {
3759
+ const { type, startLine, startColumn, endLine, endColumn } = token;
3760
+ const codeFenced = (type === "codeFenced");
3761
+ return {
3762
+ "startLine": startLine + (codeFenced ? 1 : 0),
3763
+ "startColumn": codeFenced ? 0 : startColumn,
3764
+ "endLine": endLine - (codeFenced ? 1 : 0),
3765
+ "endColumn": codeFenced ? Number.MAX_SAFE_INTEGER : endColumn
3766
+ };
3767
+ });
3734
3768
  for (let lineIndex = 0; lineIndex < params.lines.length; lineIndex++) {
3735
3769
  const line = params.lines[lineIndex];
3736
3770
  let match = null;
3737
3771
  while ((match = tabRe.exec(line)) !== null) {
3772
+ const lineNumber = lineIndex + 1;
3738
3773
  const column = match.index + 1;
3739
3774
  const length = match[0].length;
3740
- if (!withinAnyRange(exclusions, lineIndex + 1, column, length)) {
3775
+ /** @type {import("../helpers").FileRange} */
3776
+ const range = { "startLine": lineNumber, "startColumn": column, "endLine": lineNumber, "endColumn": column + length - 1 };
3777
+ if (!codeRanges.some((codeRange) => hasOverlap(codeRange, range))) {
3741
3778
  addError(
3742
3779
  onError,
3743
- lineIndex + 1,
3780
+ lineNumber,
3744
3781
  "Column: " + column,
3745
3782
  undefined,
3746
3783
  [ column, length ],
@@ -3770,8 +3807,8 @@ module.exports = {
3770
3807
 
3771
3808
 
3772
3809
 
3773
- const { addError, withinAnyRange } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
3774
- const { addRangeToSet, getExclusionsForToken } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
3810
+ const { addError, hasOverlap } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
3811
+ const { addRangeToSet } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
3775
3812
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
3776
3813
 
3777
3814
  const reversedLinkRe =
@@ -3789,34 +3826,35 @@ module.exports = {
3789
3826
  for (const codeBlock of filterByTypesCached([ "codeFenced", "codeIndented" ])) {
3790
3827
  addRangeToSet(codeBlockLineNumbers, codeBlock.startLine, codeBlock.endLine);
3791
3828
  }
3792
- const exclusions = [];
3793
- for (const codeText of filterByTypesCached([ "codeText" ])) {
3794
- exclusions.push(...getExclusionsForToken(params.lines, codeText));
3795
- }
3829
+ const codeTexts = filterByTypesCached([ "codeText" ]);
3796
3830
  for (const [ lineIndex, line ] of params.lines.entries()) {
3797
- if (!codeBlockLineNumbers.has(lineIndex + 1)) {
3831
+ const lineNumber = lineIndex + 1;
3832
+ if (!codeBlockLineNumbers.has(lineNumber)) {
3798
3833
  let match = null;
3799
3834
  while ((match = reversedLinkRe.exec(line)) !== null) {
3800
3835
  const [ reversedLink, preChar, linkText, linkDestination ] = match;
3801
- const index = match.index + preChar.length;
3802
- const length = match[0].length - preChar.length;
3803
3836
  if (
3804
3837
  !linkText.endsWith("\\") &&
3805
- !linkDestination.endsWith("\\") &&
3806
- !withinAnyRange(exclusions, lineIndex + 1, index, length)
3838
+ !linkDestination.endsWith("\\")
3807
3839
  ) {
3808
- addError(
3809
- onError,
3810
- lineIndex + 1,
3811
- reversedLink.slice(preChar.length),
3812
- undefined,
3813
- [ index + 1, length ],
3814
- {
3815
- "editColumn": index + 1,
3816
- "deleteCount": length,
3817
- "insertText": `[${linkText}](${linkDestination})`
3818
- }
3819
- );
3840
+ const column = match.index + preChar.length + 1;
3841
+ const length = match[0].length - preChar.length;
3842
+ /** @type {import("../helpers").FileRange} */
3843
+ const range = { "startLine": lineNumber, "startColumn": column, "endLine": lineNumber, "endColumn": column + length - 1 };
3844
+ if (!codeTexts.some((codeText) => hasOverlap(codeText, range))) {
3845
+ addError(
3846
+ onError,
3847
+ lineNumber,
3848
+ reversedLink.slice(preChar.length),
3849
+ undefined,
3850
+ [ column, length ],
3851
+ {
3852
+ "editColumn": column,
3853
+ "deleteCount": length,
3854
+ "insertText": `[${linkText}](${linkDestination})`
3855
+ }
3856
+ );
3857
+ }
3820
3858
  }
3821
3859
  }
3822
3860
  }
@@ -3839,7 +3877,7 @@ module.exports = {
3839
3877
 
3840
3878
 
3841
3879
  const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
3842
- const { addRangeToSet } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
3880
+ const { addRangeToSet } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
3843
3881
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
3844
3882
 
3845
3883
  // eslint-disable-next-line jsdoc/valid-types
@@ -3894,7 +3932,7 @@ module.exports = {
3894
3932
 
3895
3933
  const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
3896
3934
  const { getReferenceLinkImageData } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
3897
- const { addRangeToSet, getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
3935
+ const { addRangeToSet, getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
3898
3936
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
3899
3937
 
3900
3938
  const longLineRePrefix = "^.{";
@@ -4009,7 +4047,6 @@ module.exports = {
4009
4047
 
4010
4048
 
4011
4049
  const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
4012
- const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
4013
4050
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
4014
4051
 
4015
4052
  const dollarCommandRe = /^(\s*)(\$\s+)/;
@@ -4023,18 +4060,15 @@ module.exports = {
4023
4060
  "parser": "micromark",
4024
4061
  "function": function MD014(params, onError) {
4025
4062
  for (const codeBlock of filterByTypesCached([ "codeFenced", "codeIndented" ])) {
4026
- const codeFlowValues = filterByTypes(
4027
- codeBlock.children,
4028
- [ "codeFlowValue" ]
4029
- );
4030
- const dollarMatches = codeFlowValues.
4031
- map((codeFlowValue) => ({
4063
+ const codeFlowValues = codeBlock.children.filter((child) => child.type === "codeFlowValue");
4064
+ const dollarMatches = codeFlowValues
4065
+ .map((codeFlowValue) => ({
4032
4066
  "result": codeFlowValue.text.match(dollarCommandRe),
4033
4067
  "startColumn": codeFlowValue.startColumn,
4034
4068
  "startLine": codeFlowValue.startLine,
4035
4069
  "text": codeFlowValue.text
4036
- })).
4037
- filter((dollarMatch) => dollarMatch.result);
4070
+ }))
4071
+ .filter((dollarMatch) => dollarMatch.result);
4038
4072
  if (dollarMatches.length === codeFlowValues.length) {
4039
4073
  for (const dollarMatch of dollarMatches) {
4040
4074
  // @ts-ignore
@@ -4074,7 +4108,7 @@ module.exports = {
4074
4108
 
4075
4109
 
4076
4110
  const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
4077
- const { addRangeToSet } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
4111
+ const { addRangeToSet } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
4078
4112
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
4079
4113
 
4080
4114
  // eslint-disable-next-line jsdoc/valid-types
@@ -4131,7 +4165,7 @@ module.exports = {
4131
4165
 
4132
4166
 
4133
4167
  const { addErrorContext } = __webpack_require__(/*! ../helpers/helpers */ "../helpers/helpers.js");
4134
- const { getHeadingStyle } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
4168
+ const { getHeadingStyle } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
4135
4169
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
4136
4170
 
4137
4171
  /**
@@ -4222,7 +4256,7 @@ module.exports = [
4222
4256
 
4223
4257
 
4224
4258
  const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
4225
- const { addRangeToSet } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
4259
+ const { addRangeToSet } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
4226
4260
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
4227
4261
 
4228
4262
  // eslint-disable-next-line jsdoc/valid-types
@@ -4241,7 +4275,7 @@ module.exports = {
4241
4275
  for (const [ lineIndex, line ] of lines.entries()) {
4242
4276
  if (!ignoreBlockLineNumbers.has(lineIndex + 1)) {
4243
4277
  const match =
4244
- /^(#+)([ \t]*)([^#]*?[^#\\])([ \t]*)((?:\\#)?)(#+)(\s*)$/.exec(line);
4278
+ /^(#+)([ \t]*)([^# \t\\]|[^# \t][^#]*?[^# \t\\])([ \t]*)((?:\\#)?)(#+)(\s*)$/.exec(line);
4245
4279
  if (match) {
4246
4280
  const [
4247
4281
  ,
@@ -4303,8 +4337,8 @@ module.exports = {
4303
4337
 
4304
4338
 
4305
4339
 
4306
- const { addErrorDetailIf, blockquotePrefixRe, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
4307
- const { getHeadingLevel } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
4340
+ const { addErrorDetailIf, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
4341
+ const { getBlockQuotePrefixText, getHeadingLevel } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
4308
4342
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
4309
4343
 
4310
4344
  const defaultLines = 1;
@@ -4322,15 +4356,6 @@ const getLinesFunction = (linesParam) => {
4322
4356
  return () => lines;
4323
4357
  };
4324
4358
 
4325
- const getBlockQuote = (str, count) => (
4326
- (str || "")
4327
- .match(blockquotePrefixRe)[0]
4328
- .trimEnd()
4329
- // eslint-disable-next-line unicorn/prefer-spread
4330
- .concat("\n")
4331
- .repeat(count)
4332
- );
4333
-
4334
4359
  // eslint-disable-next-line jsdoc/valid-types
4335
4360
  /** @type import("./markdownlint").Rule */
4336
4361
  module.exports = {
@@ -4342,6 +4367,7 @@ module.exports = {
4342
4367
  const getLinesAbove = getLinesFunction(params.config.lines_above);
4343
4368
  const getLinesBelow = getLinesFunction(params.config.lines_below);
4344
4369
  const { lines } = params;
4370
+ const blockQuotePrefixes = filterByTypesCached([ "blockQuotePrefix", "linePrefix" ]);
4345
4371
  for (const heading of filterByTypesCached([ "atxHeading", "setextHeading" ])) {
4346
4372
  const { startLine, endLine } = heading;
4347
4373
  const line = lines[startLine - 1].trim();
@@ -4366,8 +4392,9 @@ module.exports = {
4366
4392
  line,
4367
4393
  undefined,
4368
4394
  {
4369
- "insertText": getBlockQuote(
4370
- lines[startLine - 2],
4395
+ "insertText": getBlockQuotePrefixText(
4396
+ blockQuotePrefixes,
4397
+ startLine - 1,
4371
4398
  linesAbove - actualAbove
4372
4399
  )
4373
4400
  }
@@ -4395,8 +4422,9 @@ module.exports = {
4395
4422
  undefined,
4396
4423
  {
4397
4424
  "lineNumber": endLine + 1,
4398
- "insertText": getBlockQuote(
4399
- lines[endLine],
4425
+ "insertText": getBlockQuotePrefixText(
4426
+ blockQuotePrefixes,
4427
+ endLine + 1,
4400
4428
  linesBelow - actualBelow
4401
4429
  )
4402
4430
  }
@@ -4472,7 +4500,7 @@ module.exports = {
4472
4500
 
4473
4501
 
4474
4502
  const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
4475
- const { getHeadingLevel, getHeadingText } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
4503
+ const { getHeadingLevel, getHeadingText } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
4476
4504
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
4477
4505
 
4478
4506
  // eslint-disable-next-line jsdoc/valid-types
@@ -4531,7 +4559,7 @@ module.exports = {
4531
4559
 
4532
4560
 
4533
4561
  const { addErrorContext, frontMatterHasTitle } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
4534
- const { getHeadingLevel, getHeadingText } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
4562
+ const { getHeadingLevel, getHeadingText } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
4535
4563
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
4536
4564
 
4537
4565
  // eslint-disable-next-line jsdoc/valid-types
@@ -4647,9 +4675,9 @@ const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache
4647
4675
  // eslint-disable-next-line jsdoc/valid-types
4648
4676
  /** @type import("./markdownlint").Rule */
4649
4677
  module.exports = {
4650
- "names": ["MD027", "no-multiple-space-blockquote"],
4678
+ "names": [ "MD027", "no-multiple-space-blockquote" ],
4651
4679
  "description": "Multiple spaces after blockquote symbol",
4652
- "tags": ["blockquote", "whitespace", "indentation"],
4680
+ "tags": [ "blockquote", "whitespace", "indentation" ],
4653
4681
  "parser": "micromark",
4654
4682
  "function": function MD027(params, onError) {
4655
4683
  for (const token of filterByTypesCached([ "linePrefix" ])) {
@@ -4743,7 +4771,7 @@ module.exports = {
4743
4771
 
4744
4772
 
4745
4773
  const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
4746
- const { getDescendantsByType, getTokenTextByType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
4774
+ const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
4747
4775
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
4748
4776
 
4749
4777
  const listStyleExamples = {
@@ -4755,11 +4783,11 @@ const listStyleExamples = {
4755
4783
  /**
4756
4784
  * Gets the value of an ordered list item prefix token.
4757
4785
  *
4758
- * @param {import("../helpers/micromark.cjs").Token} listItemPrefix List item prefix token.
4786
+ * @param {import("../helpers/micromark-helpers.cjs").Token} listItemPrefix List item prefix token.
4759
4787
  * @returns {number} List item value.
4760
4788
  */
4761
4789
  function getOrderedListItemValue(listItemPrefix) {
4762
- return Number(getTokenTextByType(listItemPrefix.children, "listItemValue"));
4790
+ return Number(getDescendantsByType(listItemPrefix, [ "listItemValue" ])[0].text);
4763
4791
  }
4764
4792
 
4765
4793
  // eslint-disable-next-line jsdoc/valid-types
@@ -4901,7 +4929,7 @@ module.exports = {
4901
4929
 
4902
4930
 
4903
4931
  const { addErrorContext, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
4904
- const { getTokenParentOfType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
4932
+ const { getParentOfType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
4905
4933
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
4906
4934
 
4907
4935
  const codeFencePrefixRe = /^(.*?)[`~]/;
@@ -4921,10 +4949,12 @@ const codeFencePrefixRe = /^(.*?)[`~]/;
4921
4949
  function addError(onError, lines, lineNumber, top) {
4922
4950
  const line = lines[lineNumber - 1];
4923
4951
  const [ , prefix ] = line.match(codeFencePrefixRe) || [];
4924
- const fixInfo = (prefix === undefined) ? null : {
4925
- "lineNumber": lineNumber + (top ? 0 : 1),
4926
- "insertText": `${prefix.replace(/[^>]/g, " ").trim()}\n`
4927
- };
4952
+ const fixInfo = (prefix === undefined) ?
4953
+ null :
4954
+ {
4955
+ "lineNumber": lineNumber + (top ? 0 : 1),
4956
+ "insertText": `${prefix.replace(/[^>]/g, " ").trim()}\n`
4957
+ };
4928
4958
  addErrorContext(
4929
4959
  onError,
4930
4960
  lineNumber,
@@ -4948,7 +4978,7 @@ module.exports = {
4948
4978
  const includeListItems = (listItems === undefined) ? true : !!listItems;
4949
4979
  const { lines } = params;
4950
4980
  for (const codeBlock of filterByTypesCached([ "codeFenced" ])) {
4951
- if (includeListItems || !(getTokenParentOfType(codeBlock, [ "listOrdered", "listUnordered" ]))) {
4981
+ if (includeListItems || !(getParentOfType(codeBlock, [ "listOrdered", "listUnordered" ]))) {
4952
4982
  if (!isBlankLine(lines[codeBlock.startLine - 2])) {
4953
4983
  addError(onError, lines, codeBlock.startLine, true);
4954
4984
  }
@@ -4974,8 +5004,9 @@ module.exports = {
4974
5004
 
4975
5005
 
4976
5006
 
4977
- const { addErrorContextForLine, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
4978
- const { filterByPredicate, nonContentTokens } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
5007
+ const { addErrorContext, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
5008
+ const { filterByPredicate, getBlockQuotePrefixText, nonContentTokens } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
5009
+ const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
4979
5010
 
4980
5011
  const isList = (token) => (
4981
5012
  (token.type === "listOrdered") || (token.type === "listUnordered")
@@ -4990,6 +5021,7 @@ module.exports = {
4990
5021
  "parser": "micromark",
4991
5022
  "function": function MD032(params, onError) {
4992
5023
  const { lines, parsers } = params;
5024
+ const blockQuotePrefixes = filterByTypesCached([ "blockQuotePrefix", "linePrefix" ]);
4993
5025
 
4994
5026
  // For every top-level list...
4995
5027
  const topLevelLists = filterByPredicate(
@@ -5002,13 +5034,18 @@ module.exports = {
5002
5034
  for (const list of topLevelLists) {
5003
5035
 
5004
5036
  // Look for a blank line above the list
5005
- const firstIndex = list.startLine - 1;
5006
- if (!isBlankLine(lines[firstIndex - 1])) {
5007
- addErrorContextForLine(
5037
+ const firstLineNumber = list.startLine;
5038
+ if (!isBlankLine(lines[firstLineNumber - 2])) {
5039
+ addErrorContext(
5008
5040
  onError,
5009
- // @ts-ignore
5010
- lines,
5011
- firstIndex
5041
+ firstLineNumber,
5042
+ lines[firstLineNumber - 1].trim(),
5043
+ undefined,
5044
+ undefined,
5045
+ undefined,
5046
+ {
5047
+ "insertText": getBlockQuotePrefixText(blockQuotePrefixes, firstLineNumber)
5048
+ }
5012
5049
  );
5013
5050
  }
5014
5051
 
@@ -5023,14 +5060,19 @@ module.exports = {
5023
5060
  }
5024
5061
 
5025
5062
  // Look for a blank line below the list
5026
- const lastIndex = endLine - 1;
5027
- if (!isBlankLine(lines[lastIndex + 1])) {
5028
- addErrorContextForLine(
5063
+ const lastLineNumber = endLine;
5064
+ if (!isBlankLine(lines[lastLineNumber])) {
5065
+ addErrorContext(
5029
5066
  onError,
5030
- // @ts-ignore
5031
- lines,
5032
- lastIndex,
5033
- lastIndex + 2
5067
+ lastLineNumber,
5068
+ lines[lastLineNumber - 1].trim(),
5069
+ undefined,
5070
+ undefined,
5071
+ undefined,
5072
+ {
5073
+ "lineNumber": lastLineNumber + 1,
5074
+ "insertText": getBlockQuotePrefixText(blockQuotePrefixes, lastLineNumber)
5075
+ }
5034
5076
  );
5035
5077
  }
5036
5078
  }
@@ -5052,7 +5094,7 @@ module.exports = {
5052
5094
 
5053
5095
 
5054
5096
  const { addError, nextLinesRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
5055
- const { getHtmlTagInfo } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
5097
+ const { getHtmlTagInfo } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
5056
5098
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
5057
5099
 
5058
5100
  // eslint-disable-next-line jsdoc/valid-types
@@ -5104,8 +5146,7 @@ module.exports = {
5104
5146
 
5105
5147
 
5106
5148
  const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
5107
- const { filterByPredicate, getHtmlTagInfo, inHtmlFlow, parse } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
5108
- const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
5149
+ const { filterByPredicate, getHtmlTagInfo, inHtmlFlow } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
5109
5150
 
5110
5151
  // eslint-disable-next-line jsdoc/valid-types
5111
5152
  /** @type import("./markdownlint").Rule */
@@ -5122,8 +5163,6 @@ module.exports = {
5122
5163
  if ((token.type === "literalAutolink") && !inHtmlFlow(token)) {
5123
5164
  // Detect and ignore https://github.com/micromark/micromark/issues/164
5124
5165
  const siblings = token.parent?.children;
5125
- // Commented-out due to not being able to exercise in test/code coverage
5126
- // || micromarkTokens;
5127
5166
  const index = siblings?.indexOf(token);
5128
5167
  // @ts-ignore
5129
5168
  const prev = siblings?.at(index - 1);
@@ -5141,6 +5180,7 @@ module.exports = {
5141
5180
  return false;
5142
5181
  },
5143
5182
  (token) => {
5183
+ // Ignore content of inline HTML tags
5144
5184
  const { children } = token;
5145
5185
  const result = [];
5146
5186
  for (let i = 0; i < children.length; i++) {
@@ -5171,31 +5211,25 @@ module.exports = {
5171
5211
  }
5172
5212
  )
5173
5213
  );
5174
- const autoLinks = filterByTypesCached([ "literalAutolink" ]);
5175
- if (autoLinks.length > 0) {
5176
- // Re-parse with correct link/image reference definition handling
5177
- const document = params.lines.join("\n");
5178
- const tokens = parse(document, undefined, false);
5179
- for (const token of literalAutolinks(tokens)) {
5180
- const range = [
5181
- token.startColumn,
5182
- token.endColumn - token.startColumn
5183
- ];
5184
- const fixInfo = {
5185
- "editColumn": range[0],
5186
- "deleteCount": range[1],
5187
- "insertText": `<${token.text}>`
5188
- };
5189
- addErrorContext(
5190
- onError,
5191
- token.startLine,
5192
- token.text,
5193
- undefined,
5194
- undefined,
5195
- range,
5196
- fixInfo
5197
- );
5198
- }
5214
+ for (const token of literalAutolinks(params.parsers.micromark.tokens)) {
5215
+ const range = [
5216
+ token.startColumn,
5217
+ token.endColumn - token.startColumn
5218
+ ];
5219
+ const fixInfo = {
5220
+ "editColumn": range[0],
5221
+ "deleteCount": range[1],
5222
+ "insertText": `<${token.text}>`
5223
+ };
5224
+ addErrorContext(
5225
+ onError,
5226
+ token.startLine,
5227
+ token.text,
5228
+ undefined,
5229
+ undefined,
5230
+ range,
5231
+ fixInfo
5232
+ );
5199
5233
  }
5200
5234
  }
5201
5235
  };
@@ -5252,15 +5286,15 @@ module.exports = {
5252
5286
 
5253
5287
 
5254
5288
  const { addErrorContext, allPunctuation } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
5255
- const { matchAndGetTokensByType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
5289
+ const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
5256
5290
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
5257
5291
 
5258
- /** @typedef {import("../helpers/micromark.cjs").TokenType} TokenType */
5259
- /** @type {Map<TokenType, TokenType[]>} */
5260
- const emphasisAndChildrenTypes = new Map([
5261
- [ "emphasis", [ "emphasisSequence", "emphasisText", "emphasisSequence" ] ],
5262
- [ "strong", [ "strongSequence", "strongText", "strongSequence" ] ]
5263
- ]);
5292
+ /** @typedef {import("../helpers/micromark-helpers.cjs").TokenType} TokenType */
5293
+ /** @type {TokenType[][]} */
5294
+ const emphasisTypes = [
5295
+ [ "emphasis", "emphasisText" ],
5296
+ [ "strong", "strongText" ]
5297
+ ];
5264
5298
 
5265
5299
  // eslint-disable-next-line jsdoc/valid-types
5266
5300
  /** @type import("./markdownlint").Rule */
@@ -5274,25 +5308,19 @@ module.exports = {
5274
5308
  punctuation = String((punctuation === undefined) ? allPunctuation : punctuation);
5275
5309
  const punctuationRe = new RegExp("[" + punctuation + "]$");
5276
5310
  const paragraphTokens =
5277
- filterByTypesCached([ "paragraph" ]).
5278
- filter((token) =>
5311
+ filterByTypesCached([ "paragraph" ])
5312
+ .filter((token) =>
5279
5313
  (token.parent?.type === "content") && !token.parent?.parent && (token.children.length === 1)
5280
5314
  );
5281
- for (const paragraphToken of paragraphTokens) {
5282
- const childToken = paragraphToken.children[0];
5283
- for (const [ emphasisType, emphasisChildrenTypes ] of emphasisAndChildrenTypes) {
5284
- if (childToken.type === emphasisType) {
5285
- const matchingTokens = matchAndGetTokensByType(childToken.children, emphasisChildrenTypes);
5286
- if (matchingTokens) {
5287
- const textToken = matchingTokens[1];
5288
- if (
5289
- (textToken.children.length === 1) &&
5290
- (textToken.children[0].type === "data") &&
5291
- !punctuationRe.test(textToken.text)
5292
- ) {
5293
- addErrorContext(onError, textToken.startLine, textToken.text);
5294
- }
5295
- }
5315
+ for (const emphasisType of emphasisTypes) {
5316
+ const textTokens = getDescendantsByType(paragraphTokens, emphasisType);
5317
+ for (const textToken of textTokens) {
5318
+ if (
5319
+ (textToken.children.length === 1) &&
5320
+ (textToken.children[0].type === "data") &&
5321
+ !punctuationRe.test(textToken.text)
5322
+ ) {
5323
+ addErrorContext(onError, textToken.startLine, textToken.text);
5296
5324
  }
5297
5325
  }
5298
5326
  }
@@ -5314,7 +5342,7 @@ module.exports = {
5314
5342
 
5315
5343
 
5316
5344
  const { addError } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
5317
- const { filterByPredicate, inHtmlFlow } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
5345
+ const { filterByPredicate, inHtmlFlow } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
5318
5346
 
5319
5347
  // eslint-disable-next-line jsdoc/valid-types
5320
5348
  /** @type import("./markdownlint").Rule */
@@ -5419,7 +5447,7 @@ module.exports = {
5419
5447
 
5420
5448
 
5421
5449
  const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
5422
- const { tokenIfType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
5450
+ const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
5423
5451
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
5424
5452
 
5425
5453
  const leftSpaceRe = /^\s(?:[^`]|$)/;
@@ -5445,24 +5473,19 @@ module.exports = {
5445
5473
  "function": function MD038(params, onError) {
5446
5474
  const codeTexts = filterByTypesCached([ "codeText" ]);
5447
5475
  for (const codeText of codeTexts) {
5448
- const { children } = codeText;
5449
- const first = 0;
5450
- const last = children.length - 1;
5451
- const startSequence = tokenIfType(children[first], "codeTextSequence");
5452
- const endSequence = tokenIfType(children[last], "codeTextSequence");
5453
- const startData =
5454
- tokenIfType(children[first + 1], "codeTextData") ||
5455
- tokenIfType(children[first + 2], "codeTextData");
5456
- const endData =
5457
- tokenIfType(children[last - 1], "codeTextData") ||
5458
- tokenIfType(children[last - 2], "codeTextData");
5476
+ const sequences = getDescendantsByType(codeText, [ "codeTextSequence" ]);
5477
+ const startSequence = sequences[0];
5478
+ const endSequence = sequences[sequences.length - 1];
5479
+ const datas = getDescendantsByType(codeText, [ "codeTextData" ]);
5480
+ const startData = datas[0];
5481
+ const endData = datas[datas.length - 1];
5459
5482
  if (startSequence && endSequence && startData && endData) {
5460
5483
  const spaceLeft = leftSpaceRe.test(startData.text);
5461
5484
  const spaceRight = rightSpaceRe.test(endData.text);
5462
5485
  if (spaceLeft || spaceRight) {
5463
5486
  let lineNumber = startSequence.startLine;
5464
- let range = null;
5465
- let fixInfo = null;
5487
+ let range = undefined;
5488
+ let fixInfo = undefined;
5466
5489
  if (startSequence.startLine === endSequence.endLine) {
5467
5490
  range = [
5468
5491
  startSequence.startColumn,
@@ -5530,15 +5553,14 @@ module.exports = {
5530
5553
 
5531
5554
 
5532
5555
  const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
5533
- const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
5534
5556
  const { getReferenceLinkImageData, filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
5535
5557
 
5536
5558
  /**
5537
5559
  * Adds an error for a label space issue.
5538
5560
  *
5539
5561
  * @param {import("./markdownlint").RuleOnError} onError Error-reporting callback.
5540
- * @param {import("../helpers/micromark.cjs").Token} label Label token.
5541
- * @param {import("../helpers/micromark.cjs").Token} labelText LabelText token.
5562
+ * @param {import("../helpers/micromark-helpers.cjs").Token} label Label token.
5563
+ * @param {import("../helpers/micromark-helpers.cjs").Token} labelText LabelText token.
5542
5564
  * @param {boolean} isStart True iff error is at the start of the link.
5543
5565
  */
5544
5566
  function addLabelSpaceError(onError, label, labelText, isStart) {
@@ -5556,18 +5578,20 @@ function addLabelSpaceError(onError, label, labelText, isStart) {
5556
5578
  isStart,
5557
5579
  !isStart,
5558
5580
  range,
5559
- range ? {
5560
- "editColumn": range[0],
5561
- "deleteCount": range[1]
5562
- } : undefined
5581
+ range ?
5582
+ {
5583
+ "editColumn": range[0],
5584
+ "deleteCount": range[1]
5585
+ } :
5586
+ undefined
5563
5587
  );
5564
5588
  }
5565
5589
 
5566
5590
  /**
5567
5591
  * Determines if a link is a valid link (and not a fake shortcut link due to parser tricks).
5568
5592
  *
5569
- * @param {import("../helpers/micromark.cjs").Token} label Label token.
5570
- * @param {import("../helpers/micromark.cjs").Token} labelText LabelText token.
5593
+ * @param {import("../helpers/micromark-helpers.cjs").Token} label Label token.
5594
+ * @param {import("../helpers/micromark-helpers.cjs").Token} labelText LabelText token.
5571
5595
  * @param {Map<string, any>} definitions Map of link definitions.
5572
5596
  * @returns {boolean} True iff the link is valid.
5573
5597
  */
@@ -5584,13 +5608,10 @@ module.exports = {
5584
5608
  "parser": "micromark",
5585
5609
  "function": function MD039(params, onError) {
5586
5610
  const { definitions } = getReferenceLinkImageData();
5587
- const labels = filterByTypesCached([ "label" ]).
5588
- filter((label) => label.parent?.type === "link");
5611
+ const labels = filterByTypesCached([ "label" ])
5612
+ .filter((label) => label.parent?.type === "link");
5589
5613
  for (const label of labels) {
5590
- const labelTexts = filterByTypes(
5591
- label.children,
5592
- [ "labelText" ]
5593
- );
5614
+ const labelTexts = label.children.filter((child) => child.type === "labelText");
5594
5615
  for (const labelText of labelTexts) {
5595
5616
  if (
5596
5617
  (labelText.text.trimStart().length !== labelText.text.length) &&
@@ -5624,7 +5645,7 @@ module.exports = {
5624
5645
 
5625
5646
 
5626
5647
  const { addError, addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
5627
- const { getTokenTextByType, tokenIfType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
5648
+ const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
5628
5649
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
5629
5650
 
5630
5651
  // eslint-disable-next-line jsdoc/valid-types
@@ -5640,18 +5661,16 @@ module.exports = {
5640
5661
  const languageOnly = !!params.config.language_only;
5641
5662
  const fencedCodes = filterByTypesCached([ "codeFenced" ]);
5642
5663
  for (const fencedCode of fencedCodes) {
5643
- const openingFence = tokenIfType(fencedCode.children[0], "codeFencedFence");
5644
- if (openingFence) {
5645
- const { children, startLine, text } = openingFence;
5646
- const info = getTokenTextByType(children, "codeFencedFenceInfo");
5647
- if (!info) {
5648
- addErrorContext(onError, startLine, text);
5649
- } else if ((allowed.length > 0) && !allowed.includes(info)) {
5650
- addError(onError, startLine, `"${info}" is not allowed`);
5651
- }
5652
- if (languageOnly && getTokenTextByType(children, "codeFencedFenceMeta")) {
5653
- addError(onError, startLine, `Info string contains more than language: "${text}"`);
5654
- }
5664
+ const openingFence = getDescendantsByType(fencedCode, [ "codeFencedFence" ])[0];
5665
+ const { startLine, text } = openingFence;
5666
+ const info = getDescendantsByType(openingFence, [ "codeFencedFenceInfo" ])[0]?.text;
5667
+ if (!info) {
5668
+ addErrorContext(onError, startLine, text);
5669
+ } else if ((allowed.length > 0) && !allowed.includes(info)) {
5670
+ addError(onError, startLine, `"${info}" is not allowed`);
5671
+ }
5672
+ if (languageOnly && getDescendantsByType(openingFence, [ "codeFencedFenceMeta" ]).length > 0) {
5673
+ addError(onError, startLine, `Info string contains more than language: "${text}"`);
5655
5674
  }
5656
5675
  }
5657
5676
  }
@@ -5673,7 +5692,7 @@ module.exports = {
5673
5692
 
5674
5693
  const { addErrorContext, frontMatterHasTitle } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
5675
5694
  const { filterByTypes, getHeadingLevel, getHtmlTagInfo, isHtmlFlowComment, nonContentTokens } =
5676
- __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
5695
+ __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
5677
5696
 
5678
5697
  // eslint-disable-next-line jsdoc/valid-types
5679
5698
  /** @type import("./markdownlint").Rule */
@@ -5685,9 +5704,9 @@ module.exports = {
5685
5704
  "function": function MD041(params, onError) {
5686
5705
  const level = Number(params.config.level || 1);
5687
5706
  if (!frontMatterHasTitle(params.frontMatterLines, params.config.front_matter_title)) {
5688
- params.parsers.micromark.tokens.
5689
- filter((token) => !nonContentTokens.has(token.type) && !isHtmlFlowComment(token)).
5690
- every((token) => {
5707
+ params.parsers.micromark.tokens
5708
+ .filter((token) => !nonContentTokens.has(token.type) && !isHtmlFlowComment(token))
5709
+ .every((token) => {
5691
5710
  let isError = true;
5692
5711
  if ((token.type === "atxHeading") || (token.type === "setextHeading")) {
5693
5712
  isError = (getHeadingLevel(token) !== level);
@@ -5720,7 +5739,7 @@ module.exports = {
5720
5739
 
5721
5740
 
5722
5741
  const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
5723
- const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
5742
+ const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
5724
5743
  const { getReferenceLinkImageData, filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
5725
5744
 
5726
5745
  // eslint-disable-next-line jsdoc/valid-types
@@ -5742,11 +5761,7 @@ module.exports = {
5742
5761
  const reference = getDescendantsByType(link, [ "reference" ]);
5743
5762
  const resource = getDescendantsByType(link, [ "resource" ]);
5744
5763
  const referenceString = getDescendantsByType(reference, [ "referenceString" ]);
5745
- const resourceDestination = getDescendantsByType(resource, [ "resourceDestination" ]);
5746
- const resourceDestinationString = [
5747
- ...getDescendantsByType(resourceDestination, [ "resourceDestinationRaw", "resourceDestinationString" ]),
5748
- ...getDescendantsByType(resourceDestination, [ "resourceDestinationLiteral", "resourceDestinationString" ])
5749
- ];
5764
+ const resourceDestinationString = getDescendantsByType(resource, [ "resourceDestination", [ "resourceDestinationLiteral", "resourceDestinationRaw" ], "resourceDestinationString" ]);
5750
5765
  const hasLabelText = labelText.length > 0;
5751
5766
  const hasReference = reference.length > 0;
5752
5767
  const hasResource = resource.length > 0;
@@ -5794,7 +5809,7 @@ module.exports = {
5794
5809
 
5795
5810
 
5796
5811
  const { addErrorContext, addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
5797
- const { getHeadingLevel, getHeadingText } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
5812
+ const { getHeadingLevel, getHeadingText } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
5798
5813
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
5799
5814
 
5800
5815
  // eslint-disable-next-line jsdoc/valid-types
@@ -5877,10 +5892,9 @@ module.exports = {
5877
5892
 
5878
5893
 
5879
5894
 
5880
- const { addErrorDetailIf, escapeForRegExp, withinAnyRange } =
5881
- __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
5882
- const { filterByPredicate, filterByTypes, parse } =
5883
- __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
5895
+ const { addErrorDetailIf, escapeForRegExp, hasOverlap } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
5896
+ const { filterByPredicate, filterByTypes } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
5897
+ const { parse } = __webpack_require__(/*! ../helpers/micromark-parse.cjs */ "../helpers/micromark-parse.cjs");
5884
5898
 
5885
5899
  const ignoredChildTypes = new Set(
5886
5900
  [ "codeFencedFence", "definition", "reference", "resource" ]
@@ -5924,43 +5938,47 @@ module.exports = {
5924
5938
  token.children.filter((t) => !ignoredChildTypes.has(t.type))
5925
5939
  )
5926
5940
  );
5941
+ /** @type {import("../helpers").FileRange[]} */
5927
5942
  const exclusions = [];
5928
- const autoLinked = new Set();
5943
+ const scannedTokens = new Set();
5929
5944
  for (const name of names) {
5930
5945
  const escapedName = escapeForRegExp(name);
5931
5946
  const startNamePattern = /^\W/.test(name) ? "" : "\\b_*";
5932
5947
  const endNamePattern = /\W$/.test(name) ? "" : "_*\\b";
5933
- const namePattern =
5934
- `(${startNamePattern})(${escapedName})${endNamePattern}`;
5948
+ const namePattern = `(${startNamePattern})(${escapedName})${endNamePattern}`;
5935
5949
  const nameRe = new RegExp(namePattern, "gi");
5936
5950
  for (const token of contentTokens) {
5937
5951
  let match = null;
5938
5952
  while ((match = nameRe.exec(token.text)) !== null) {
5939
5953
  const [ , leftMatch, nameMatch ] = match;
5940
- const index = token.startColumn - 1 + match.index + leftMatch.length;
5954
+ const column = token.startColumn + match.index + leftMatch.length;
5941
5955
  const length = nameMatch.length;
5942
- const lineIndex = token.startLine - 1;
5956
+ const lineNumber = token.startLine;
5957
+ /** @type {import("../helpers").FileRange} */
5958
+ const nameRange = {
5959
+ "startLine": lineNumber,
5960
+ "startColumn": column,
5961
+ "endLine": lineNumber,
5962
+ "endColumn": column + length - 1
5963
+ };
5943
5964
  if (
5944
- !withinAnyRange(exclusions, lineIndex, index, length) &&
5945
- !names.includes(nameMatch)
5965
+ !names.includes(nameMatch) &&
5966
+ !exclusions.some((exclusion) => hasOverlap(exclusion, nameRange))
5946
5967
  ) {
5947
- let urlRanges = [];
5948
- if (!autoLinked.has(token)) {
5949
- urlRanges = filterByTypes(
5950
- parse(token.text),
5951
- [ "literalAutolink" ]
5952
- ).map(
5953
- (t) => [
5954
- lineIndex,
5955
- token.startColumn - 1 + t.startColumn - 1,
5956
- t.endColumn - t.startColumn
5957
- ]
5958
- );
5959
- exclusions.push(...urlRanges);
5960
- autoLinked.add(token);
5968
+ /** @type {import("../helpers").FileRange[]} */
5969
+ let autolinkRanges = [];
5970
+ if (!scannedTokens.has(token)) {
5971
+ autolinkRanges = filterByTypes(parse(token.text), [ "literalAutolink" ])
5972
+ .map((tok) => ({
5973
+ "startLine": lineNumber,
5974
+ "startColumn": token.startColumn + tok.startColumn - 1,
5975
+ "endLine": lineNumber,
5976
+ "endColumn": token.endColumn + tok.endColumn - 1
5977
+ }));
5978
+ exclusions.push(...autolinkRanges);
5979
+ scannedTokens.add(token);
5961
5980
  }
5962
- if (!withinAnyRange(urlRanges, lineIndex, index, length)) {
5963
- const column = index + 1;
5981
+ if (!autolinkRanges.some((autolinkRange) => hasOverlap(autolinkRange, nameRange))) {
5964
5982
  addErrorDetailIf(
5965
5983
  onError,
5966
5984
  token.startLine,
@@ -5977,7 +5995,7 @@ module.exports = {
5977
5995
  );
5978
5996
  }
5979
5997
  }
5980
- exclusions.push([ lineIndex, index, length ]);
5998
+ exclusions.push(nameRange);
5981
5999
  }
5982
6000
  }
5983
6001
  }
@@ -5999,7 +6017,7 @@ module.exports = {
5999
6017
 
6000
6018
 
6001
6019
  const { addError, getHtmlAttributeRe, nextLinesRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
6002
- const { filterByTypes, getHtmlTagInfo } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
6020
+ const { getHtmlTagInfo, getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
6003
6021
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
6004
6022
 
6005
6023
  const altRe = getHtmlAttributeRe("alt");
@@ -6015,7 +6033,7 @@ module.exports = {
6015
6033
  // Process Markdown images
6016
6034
  const images = filterByTypesCached([ "image" ]);
6017
6035
  for (const image of images) {
6018
- const labelTexts = filterByTypes(image.children, [ "labelText" ]);
6036
+ const labelTexts = getDescendantsByType(image, [ "label", "labelText" ]);
6019
6037
  if (labelTexts.some((labelText) => labelText.text.length === 0)) {
6020
6038
  const range = (image.startLine === image.endLine) ?
6021
6039
  [ image.startColumn, image.endColumn - image.startColumn ] :
@@ -6158,10 +6176,25 @@ module.exports = {
6158
6176
 
6159
6177
 
6160
6178
 
6161
- const { addErrorDetailIf, fencedCodeBlockStyleFor } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
6162
- const { tokenIfType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
6179
+ const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
6180
+ const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
6163
6181
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
6164
6182
 
6183
+ /**
6184
+ * Return the string representation of a fence markup character.
6185
+ *
6186
+ * @param {string} markup Fence string.
6187
+ * @returns {"tilde" | "backtick"} String representation.
6188
+ */
6189
+ function fencedCodeBlockStyleFor(markup) {
6190
+ switch (markup[0]) {
6191
+ case "~":
6192
+ return "tilde";
6193
+ default:
6194
+ return "backtick";
6195
+ }
6196
+ };
6197
+
6165
6198
  // eslint-disable-next-line jsdoc/valid-types
6166
6199
  /** @type import("./markdownlint").Rule */
6167
6200
  module.exports = {
@@ -6174,22 +6207,18 @@ module.exports = {
6174
6207
  let expectedStyle = style;
6175
6208
  const codeFenceds = filterByTypesCached([ "codeFenced" ]);
6176
6209
  for (const codeFenced of codeFenceds) {
6177
- const codeFencedFence = tokenIfType(codeFenced.children[0], "codeFencedFence");
6178
- if (codeFencedFence) {
6179
- const codeFencedFenceSequence = tokenIfType(codeFencedFence.children[0], "codeFencedFenceSequence");
6180
- if (codeFencedFenceSequence) {
6181
- const { startLine, text } = codeFencedFenceSequence;
6182
- if (expectedStyle === "consistent") {
6183
- expectedStyle = fencedCodeBlockStyleFor(text);
6184
- }
6185
- addErrorDetailIf(
6186
- onError,
6187
- startLine,
6188
- expectedStyle,
6189
- fencedCodeBlockStyleFor(text)
6190
- );
6191
- }
6210
+ const codeFencedFenceSequence =
6211
+ getDescendantsByType(codeFenced, [ "codeFencedFence", "codeFencedFenceSequence" ])[0];
6212
+ const { startLine, text } = codeFencedFenceSequence;
6213
+ if (expectedStyle === "consistent") {
6214
+ expectedStyle = fencedCodeBlockStyleFor(text);
6192
6215
  }
6216
+ addErrorDetailIf(
6217
+ onError,
6218
+ startLine,
6219
+ expectedStyle,
6220
+ fencedCodeBlockStyleFor(text)
6221
+ );
6193
6222
  }
6194
6223
  }
6195
6224
  };
@@ -6208,11 +6237,26 @@ module.exports = {
6208
6237
 
6209
6238
 
6210
6239
 
6211
- const { addError, emphasisOrStrongStyleFor } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
6212
- const { filterByPredicate, tokenIfType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
6240
+ const { addError } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
6241
+ const { filterByPredicate, getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
6213
6242
 
6214
6243
  const intrawordRe = /^\w$/;
6215
6244
 
6245
+ /**
6246
+ * Return the string representation of a emphasis or strong markup character.
6247
+ *
6248
+ * @param {string} markup Emphasis or strong string.
6249
+ * @returns {"asterisk" | "underscore"} String representation.
6250
+ */
6251
+ function emphasisOrStrongStyleFor(markup) {
6252
+ switch (markup[0]) {
6253
+ case "*":
6254
+ return "asterisk";
6255
+ default:
6256
+ return "underscore";
6257
+ }
6258
+ };
6259
+
6216
6260
  /**
6217
6261
  * @param {import("./markdownlint").RuleParams} params Rule parameters.
6218
6262
  * @param {import("./markdownlint").RuleOnError} onError Error-reporting callback.
@@ -6231,9 +6275,9 @@ const impl =
6231
6275
  (token) => ((token.type === "htmlFlow") ? [] : token.children)
6232
6276
  );
6233
6277
  for (const token of emphasisTokens) {
6234
- const { children } = token;
6235
- const startSequence = tokenIfType(children[0], typeSequence);
6236
- const endSequence = tokenIfType(children[children.length - 1], typeSequence);
6278
+ const sequences = getDescendantsByType(token, [ typeSequence ]);
6279
+ const startSequence = sequences[0];
6280
+ const endSequence = sequences[sequences.length - 1];
6237
6281
  if (startSequence && endSequence) {
6238
6282
  const markupStyle = emphasisOrStrongStyleFor(startSequence.text);
6239
6283
  if (style === "consistent") {
@@ -6322,8 +6366,8 @@ module.exports = [
6322
6366
 
6323
6367
 
6324
6368
 
6325
- const { addError, addErrorDetailIf, getHtmlAttributeRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
6326
- const { filterByPredicate, filterByTypes, getHtmlTagInfo } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
6369
+ const { addError, getHtmlAttributeRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
6370
+ const { filterByPredicate, filterByTypes, getHtmlTagInfo } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
6327
6371
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
6328
6372
 
6329
6373
  // Regular expression for identifying HTML anchor names
@@ -6342,7 +6386,7 @@ const tokensInclude = new Set(
6342
6386
  * Converts a Markdown heading into an HTML fragment according to the rules
6343
6387
  * used by GitHub.
6344
6388
  *
6345
- * @param {import("../helpers/micromark.cjs").Token} headingText Heading text token.
6389
+ * @param {import("../helpers/micromark-helpers.cjs").Token} headingText Heading text token.
6346
6390
  * @returns {string} Fragment string for heading.
6347
6391
  */
6348
6392
  function convertHeadingToHTMLFragment(headingText) {
@@ -6371,7 +6415,7 @@ function convertHeadingToHTMLFragment(headingText) {
6371
6415
  /**
6372
6416
  * Unescapes the text of a String-type micromark Token.
6373
6417
  *
6374
- * @param {import("../helpers/micromark.cjs").Token} token String-type micromark Token.
6418
+ * @param {import("../helpers/micromark-helpers.cjs").Token} token String-type micromark Token.
6375
6419
  * @returns {string} Unescaped token text.
6376
6420
  */
6377
6421
  function unescapeStringTokenText(token) {
@@ -6388,6 +6432,7 @@ module.exports = {
6388
6432
  "tags": [ "links" ],
6389
6433
  "parser": "micromark",
6390
6434
  "function": function MD051(params, onError) {
6435
+ const ignoreCase = params.config.ignore_case || false;
6391
6436
  const fragments = new Map();
6392
6437
 
6393
6438
  // Process headings
@@ -6424,7 +6469,7 @@ module.exports = {
6424
6469
 
6425
6470
  // Process link and definition fragments
6426
6471
  // eslint-disable-next-line jsdoc/valid-types
6427
- /** @type import("../helpers/micromark.cjs").TokenType[][] */
6472
+ /** @type import("../helpers/micromark-helpers.cjs").TokenType[][] */
6428
6473
  const parentChilds = [
6429
6474
  [ "link", "resourceDestinationString" ],
6430
6475
  [ "definition", "definitionDestinationString" ]
@@ -6443,11 +6488,8 @@ module.exports = {
6443
6488
  !fragments.has(encodedText) &&
6444
6489
  !lineFragmentRe.test(encodedText)
6445
6490
  ) {
6446
- // eslint-disable-next-line no-undef-init
6447
6491
  let context = undefined;
6448
- // eslint-disable-next-line no-undef-init
6449
6492
  let range = undefined;
6450
- // eslint-disable-next-line no-undef-init
6451
6493
  let fixInfo = undefined;
6452
6494
  if (link.startLine === link.endLine) {
6453
6495
  context = link.text;
@@ -6463,16 +6505,16 @@ module.exports = {
6463
6505
  if (mixedCaseKey) {
6464
6506
  // @ts-ignore
6465
6507
  (fixInfo || {}).insertText = mixedCaseKey;
6466
- addErrorDetailIf(
6467
- onError,
6468
- link.startLine,
6469
- mixedCaseKey,
6470
- text,
6471
- undefined,
6472
- context,
6473
- range,
6474
- fixInfo
6475
- );
6508
+ if (!ignoreCase && (mixedCaseKey !== text)) {
6509
+ addError(
6510
+ onError,
6511
+ link.startLine,
6512
+ `Expected: ${mixedCaseKey}; Actual: ${text}`,
6513
+ context,
6514
+ range,
6515
+ fixInfo
6516
+ );
6517
+ }
6476
6518
  } else {
6477
6519
  addError(
6478
6520
  onError,
@@ -6556,10 +6598,11 @@ module.exports = {
6556
6598
 
6557
6599
 
6558
6600
 
6559
- const { addError, ellipsify, linkReferenceDefinitionRe } =
6560
- __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
6601
+ const { addError, ellipsify } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
6561
6602
  const { getReferenceLinkImageData } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
6562
6603
 
6604
+ const linkReferenceDefinitionRe = /^ {0,3}\[([^\]]*[^\\])\]:/;
6605
+
6563
6606
  // eslint-disable-next-line jsdoc/valid-types
6564
6607
  /** @type import("./markdownlint").Rule */
6565
6608
  module.exports = {
@@ -6593,7 +6636,7 @@ module.exports = {
6593
6636
  `Unused link or image reference definition: "${label}"`,
6594
6637
  ellipsify(line),
6595
6638
  [ 1, line.length ],
6596
- singleLineDefinition(line) ? deleteFixInfo : 0
6639
+ singleLineDefinition(line) ? deleteFixInfo : undefined
6597
6640
  );
6598
6641
  }
6599
6642
  }
@@ -6608,7 +6651,7 @@ module.exports = {
6608
6651
  `Duplicate link or image reference definition: "${label}"`,
6609
6652
  ellipsify(line),
6610
6653
  [ 1, line.length ],
6611
- singleLineDefinition(line) ? deleteFixInfo : 0
6654
+ singleLineDefinition(line) ? deleteFixInfo : undefined
6612
6655
  );
6613
6656
  }
6614
6657
  }
@@ -6630,7 +6673,7 @@ module.exports = {
6630
6673
 
6631
6674
 
6632
6675
  const { addErrorContext, nextLinesRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
6633
- const { filterByPredicate, getTokenTextByType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
6676
+ const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
6634
6677
  const { getReferenceLinkImageData, filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
6635
6678
 
6636
6679
  const backslashEscapeRe = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g;
@@ -6672,24 +6715,23 @@ module.exports = {
6672
6715
  let label = null;
6673
6716
  let destination = null;
6674
6717
  const {
6675
- children, endColumn, endLine, startColumn, startLine, text, type
6718
+ endColumn, endLine, startColumn, startLine, text, type
6676
6719
  } = link;
6677
6720
  const image = (type === "image");
6678
6721
  let isError = false;
6679
6722
  if (type === "autolink") {
6680
6723
  // link kind is an autolink
6681
- destination = getTokenTextByType(children, "autolinkProtocol");
6724
+ destination = getDescendantsByType(link, [ "autolinkProtocol" ])[0].text;
6682
6725
  label = destination;
6683
6726
  isError = !autolink;
6684
6727
  } else {
6685
6728
  // link type is "image" or "link"
6686
- const descendents = filterByPredicate(children);
6687
- label = getTokenTextByType(descendents, "labelText");
6729
+ label = getDescendantsByType(link, [ "label", "labelText" ])[0].text;
6688
6730
  destination =
6689
- getTokenTextByType(descendents, "resourceDestinationString");
6731
+ getDescendantsByType(link, [ "resource", "resourceDestination", [ "resourceDestinationLiteral", "resourceDestinationRaw" ], "resourceDestinationString" ])[0]?.text;
6690
6732
  if (destination) {
6691
6733
  // link kind is an inline link
6692
- const title = getTokenTextByType(descendents, "resourceTitleString");
6734
+ const title = getDescendantsByType(link, [ "resource", "resourceTitle", "resourceTitleString" ])[0]?.text;
6693
6735
  isError = !inline || (
6694
6736
  !urlInline &&
6695
6737
  autolink &&
@@ -6700,9 +6742,9 @@ module.exports = {
6700
6742
  );
6701
6743
  } else {
6702
6744
  // link kind is a full/collapsed/shortcut reference link
6703
- const isShortcut = !children.some((t) => t.type === "reference");
6704
- const referenceString = getTokenTextByType(descendents, "referenceString");
6705
- const isCollapsed = (referenceString === null);
6745
+ const isShortcut = getDescendantsByType(link, [ "reference" ]).length === 0;
6746
+ const referenceString = getDescendantsByType(link, [ "reference", "referenceString" ])[0]?.text;
6747
+ const isCollapsed = (referenceString === undefined);
6706
6748
  const definition = definitions.get(referenceString || label);
6707
6749
  destination = definition && definition[1];
6708
6750
  isError = destination &&
@@ -6710,9 +6752,8 @@ module.exports = {
6710
6752
  }
6711
6753
  }
6712
6754
  if (isError) {
6713
- // eslint-disable-next-line no-undef-init
6714
6755
  let range = undefined;
6715
- let fixInfo = null;
6756
+ let fixInfo = undefined;
6716
6757
  if (startLine === endLine) {
6717
6758
  range = [ startColumn, endColumn - startColumn ];
6718
6759
  let insertText = null;
@@ -6766,7 +6807,6 @@ module.exports = {
6766
6807
 
6767
6808
 
6768
6809
  const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
6769
- const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
6770
6810
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
6771
6811
 
6772
6812
  const whitespaceTypes = new Set([ "linePrefix", "whitespace" ]);
@@ -6791,51 +6831,45 @@ module.exports = {
6791
6831
  ((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "trailing_only"));
6792
6832
  let expectedTrailingPipe =
6793
6833
  ((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "leading_only"));
6794
- const tables = filterByTypesCached([ "table" ]);
6795
- for (const table of tables) {
6796
- const rows = filterByTypes(
6797
- table.children,
6798
- [ "tableDelimiterRow", "tableRow" ]
6799
- );
6800
- for (const row of rows) {
6801
- // The following uses of first/lastOrNothing lack fallback handling
6802
- // because it seems not to be possible (i.e., 0% coverage)
6803
- const firstCell = firstOrNothing(row.children);
6804
- const leadingToken = firstOrNothing(ignoreWhitespace(firstCell.children));
6805
- const actualLeadingPipe = (leadingToken.type === "tableCellDivider");
6806
- const lastCell = lastOrNothing(row.children);
6807
- const trailingToken = lastOrNothing(ignoreWhitespace(lastCell.children));
6808
- const actualTrailingPipe = (trailingToken.type === "tableCellDivider");
6809
- const actualStyle = actualLeadingPipe ?
6810
- (actualTrailingPipe ? "leading_and_trailing" : "leading_only") :
6811
- (actualTrailingPipe ? "trailing_only" : "no_leading_or_trailing");
6812
- if (expectedStyle === "consistent") {
6813
- expectedStyle = actualStyle;
6814
- expectedLeadingPipe = actualLeadingPipe;
6815
- expectedTrailingPipe = actualTrailingPipe;
6816
- }
6817
- if (actualLeadingPipe !== expectedLeadingPipe) {
6818
- addErrorDetailIf(
6819
- onError,
6820
- firstCell.startLine,
6821
- expectedStyle,
6822
- actualStyle,
6823
- `${expectedLeadingPipe ? "Missing" : "Unexpected"} leading pipe`,
6824
- undefined,
6825
- makeRange(row.startColumn, firstCell.startColumn)
6826
- );
6827
- }
6828
- if (actualTrailingPipe !== expectedTrailingPipe) {
6829
- addErrorDetailIf(
6830
- onError,
6831
- lastCell.endLine,
6832
- expectedStyle,
6833
- actualStyle,
6834
- `${expectedTrailingPipe ? "Missing" : "Unexpected"} trailing pipe`,
6835
- undefined,
6836
- makeRange(lastCell.endColumn - 1, row.endColumn - 1)
6837
- );
6838
- }
6834
+ const rows = filterByTypesCached([ "tableDelimiterRow", "tableRow" ]);
6835
+ for (const row of rows) {
6836
+ // The following uses of first/lastOrNothing lack fallback handling
6837
+ // because it seems not to be possible (i.e., 0% coverage)
6838
+ const firstCell = firstOrNothing(row.children);
6839
+ const leadingToken = firstOrNothing(ignoreWhitespace(firstCell.children));
6840
+ const actualLeadingPipe = (leadingToken.type === "tableCellDivider");
6841
+ const lastCell = lastOrNothing(row.children);
6842
+ const trailingToken = lastOrNothing(ignoreWhitespace(lastCell.children));
6843
+ const actualTrailingPipe = (trailingToken.type === "tableCellDivider");
6844
+ const actualStyle = actualLeadingPipe ?
6845
+ (actualTrailingPipe ? "leading_and_trailing" : "leading_only") :
6846
+ (actualTrailingPipe ? "trailing_only" : "no_leading_or_trailing");
6847
+ if (expectedStyle === "consistent") {
6848
+ expectedStyle = actualStyle;
6849
+ expectedLeadingPipe = actualLeadingPipe;
6850
+ expectedTrailingPipe = actualTrailingPipe;
6851
+ }
6852
+ if (actualLeadingPipe !== expectedLeadingPipe) {
6853
+ addErrorDetailIf(
6854
+ onError,
6855
+ firstCell.startLine,
6856
+ expectedStyle,
6857
+ actualStyle,
6858
+ `${expectedLeadingPipe ? "Missing" : "Unexpected"} leading pipe`,
6859
+ undefined,
6860
+ makeRange(row.startColumn, firstCell.startColumn)
6861
+ );
6862
+ }
6863
+ if (actualTrailingPipe !== expectedTrailingPipe) {
6864
+ addErrorDetailIf(
6865
+ onError,
6866
+ lastCell.endLine,
6867
+ expectedStyle,
6868
+ actualStyle,
6869
+ `${expectedTrailingPipe ? "Missing" : "Unexpected"} trailing pipe`,
6870
+ undefined,
6871
+ makeRange(lastCell.endColumn - 1, row.endColumn - 1)
6872
+ );
6839
6873
  }
6840
6874
  }
6841
6875
  }
@@ -6856,7 +6890,7 @@ module.exports = {
6856
6890
 
6857
6891
 
6858
6892
  const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
6859
- const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
6893
+ const { getParentOfType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
6860
6894
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
6861
6895
 
6862
6896
  const makeRange = (start, end) => [ start, end - start + 1 ];
@@ -6869,44 +6903,39 @@ module.exports = {
6869
6903
  "tags": [ "table" ],
6870
6904
  "parser": "micromark",
6871
6905
  "function": function MD056(params, onError) {
6872
- const tables = filterByTypesCached([ "table" ]);
6873
- for (const table of tables) {
6874
- const rows = filterByTypes(
6875
- table.children,
6876
- [ "tableDelimiterRow", "tableRow" ]
6877
- );
6878
- let expectedCount = 0;
6879
- for (const row of rows) {
6880
- const cells = filterByTypes(
6881
- row.children,
6882
- [ "tableData", "tableDelimiter", "tableHeader" ]
6883
- );
6884
- const actualCount = cells.length;
6885
- expectedCount ||= actualCount;
6886
- // eslint-disable-next-line no-undef-init
6887
- let detail = undefined;
6888
- // eslint-disable-next-line no-undef-init
6889
- let range = undefined;
6890
- if (actualCount < expectedCount) {
6891
- detail = "Too few cells, row will be missing data";
6892
- range = [ row.endColumn - 1, 1 ];
6893
- } else if (expectedCount < actualCount) {
6894
- detail = "Too many cells, extra data will be missing";
6895
- range = makeRange(cells[expectedCount].startColumn, row.endColumn - 1);
6896
- }
6897
- addErrorDetailIf(
6898
- onError,
6899
- row.endLine,
6900
- expectedCount,
6901
- actualCount,
6902
- detail,
6903
- undefined,
6904
- range
6905
- );
6906
+ const rows = filterByTypesCached([ "tableDelimiterRow", "tableRow" ]);
6907
+ let expectedCount = 0;
6908
+ let currentTable = null;
6909
+ for (const row of rows) {
6910
+ const table = getParentOfType(row, [ "table" ]);
6911
+ if (currentTable !== table) {
6912
+ expectedCount = 0;
6913
+ currentTable = table;
6914
+ }
6915
+ const cells = row.children.filter((child) => [ "tableData", "tableDelimiter", "tableHeader" ].includes(child.type));
6916
+ const actualCount = cells.length;
6917
+ expectedCount ||= actualCount;
6918
+ let detail = undefined;
6919
+ let range = undefined;
6920
+ if (actualCount < expectedCount) {
6921
+ detail = "Too few cells, row will be missing data";
6922
+ range = [ row.endColumn - 1, 1 ];
6923
+ } else if (expectedCount < actualCount) {
6924
+ detail = "Too many cells, extra data will be missing";
6925
+ range = makeRange(cells[expectedCount].startColumn, row.endColumn - 1);
6906
6926
  }
6927
+ addErrorDetailIf(
6928
+ onError,
6929
+ row.endLine,
6930
+ expectedCount,
6931
+ actualCount,
6932
+ detail,
6933
+ undefined,
6934
+ range
6935
+ );
6907
6936
  }
6908
6937
  }
6909
- }
6938
+ };
6910
6939
 
6911
6940
 
6912
6941
  /***/ }),
@@ -6922,7 +6951,8 @@ module.exports = {
6922
6951
 
6923
6952
 
6924
6953
 
6925
- const { addErrorContextForLine, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
6954
+ const { addErrorContext, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
6955
+ const { getBlockQuotePrefixText } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs");
6926
6956
  const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
6927
6957
 
6928
6958
  // eslint-disable-next-line jsdoc/valid-types
@@ -6934,28 +6964,42 @@ module.exports = {
6934
6964
  "parser": "micromark",
6935
6965
  "function": function MD058(params, onError) {
6936
6966
  const { lines } = params;
6967
+ const blockQuotePrefixes = filterByTypesCached([ "blockQuotePrefix", "linePrefix" ]);
6968
+
6937
6969
  // For every table...
6938
6970
  const tables = filterByTypesCached([ "table" ]);
6939
6971
  for (const table of tables) {
6972
+
6940
6973
  // Look for a blank line above the table
6941
- const firstIndex = table.startLine - 1;
6942
- if (!isBlankLine(lines[firstIndex - 1])) {
6943
- addErrorContextForLine(
6974
+ const firstLineNumber = table.startLine;
6975
+ if (!isBlankLine(lines[firstLineNumber - 2])) {
6976
+ addErrorContext(
6944
6977
  onError,
6945
- // @ts-ignore
6946
- lines,
6947
- firstIndex
6978
+ firstLineNumber,
6979
+ lines[firstLineNumber - 1].trim(),
6980
+ undefined,
6981
+ undefined,
6982
+ undefined,
6983
+ {
6984
+ "insertText": getBlockQuotePrefixText(blockQuotePrefixes, firstLineNumber)
6985
+ }
6948
6986
  );
6949
6987
  }
6988
+
6950
6989
  // Look for a blank line below the table
6951
- const lastIndex = table.endLine - 1;
6952
- if (!isBlankLine(lines[lastIndex + 1])) {
6953
- addErrorContextForLine(
6990
+ const lastLineNumber = table.endLine;
6991
+ if (!isBlankLine(lines[lastLineNumber])) {
6992
+ addErrorContext(
6954
6993
  onError,
6955
- // @ts-ignore
6956
- lines,
6957
- lastIndex,
6958
- lastIndex + 2
6994
+ lastLineNumber,
6995
+ lines[lastLineNumber - 1].trim(),
6996
+ undefined,
6997
+ undefined,
6998
+ undefined,
6999
+ {
7000
+ "lineNumber": lastLineNumber + 1,
7001
+ "insertText": getBlockQuotePrefixText(blockQuotePrefixes, lastLineNumber)
7002
+ }
6959
7003
  );
6960
7004
  }
6961
7005
  }