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
package/helpers/README.md CHANGED
@@ -17,30 +17,13 @@ change from release to release. There are brief descriptive comments above each
17
17
  function, but no [JSDoc][jsdoc] annotations. That said, some of what's here will
18
18
  be useful to custom rule authors and may avoid duplicating code.
19
19
 
20
- ## Examples
21
-
22
- ### Applying Recommended Fixes
23
-
24
- ```javascript
25
- const { "sync": markdownlintSync } = require("markdownlint");
26
- const markdownlintRuleHelpers = require("markdownlint-rule-helpers");
27
-
28
- function fixMarkdownlintViolations(content) {
29
- const fixResults = markdownlintSync({ strings: { content } });
30
- return markdownlintRuleHelpers.applyFixes(content, fixResults.content);
31
- }
32
- ```
33
-
34
- See also: [`markdownlint` built-in rule implementations][lib].
35
-
36
20
  ## Tests
37
21
 
38
22
  *None* - The entire body of code is tested to 100% coverage by the core
39
23
  `markdownlint` project, so there are no additional tests here.
40
24
 
41
- [custom-rules]: https://github.com/DavidAnson/markdownlint/blob/v0.35.0/doc/CustomRules.md
25
+ [custom-rules]: https://github.com/DavidAnson/markdownlint/blob/v0.36.0/doc/CustomRules.md
42
26
  [jsdoc]: https://en.m.wikipedia.org/wiki/JSDoc
43
- [lib]: https://github.com/DavidAnson/markdownlint/tree/v0.35.0/lib
44
27
  [markdown]: https://en.wikipedia.org/wiki/Markdown
45
28
  [markdownlint]: https://github.com/DavidAnson/markdownlint
46
- [rules]: https://github.com/DavidAnson/markdownlint/blob/v0.35.0/doc/Rules.md
29
+ [rules]: https://github.com/DavidAnson/markdownlint/blob/v0.36.0/doc/Rules.md
@@ -2,30 +2,25 @@
2
2
 
3
3
  "use strict";
4
4
 
5
- const micromark = require("./micromark.cjs");
5
+ const micromark = require("./micromark-helpers.cjs");
6
6
 
7
7
  const { newLineRe, nextLinesRe } = require("./shared.js");
8
8
 
9
9
  module.exports.newLineRe = newLineRe;
10
10
  module.exports.nextLinesRe = nextLinesRe;
11
11
 
12
+ /** @typedef {import("../lib/markdownlint.js").RuleOnError} RuleOnError */
13
+ /** @typedef {import("../lib/markdownlint.js").RuleOnErrorFixInfo} RuleOnErrorFixInfo */
14
+
12
15
  // Regular expression for matching common front matter (YAML and TOML)
13
16
  module.exports.frontMatterRe =
14
- /((^---\s*$[\s\S]+?^---\s*)|(^\+\+\+\s*$[\s\S]+?^(\+\+\+|\.\.\.)\s*)|(^\{\s*$[\s\S]+?^\}\s*))(\r\n|\r|\n|$)/m;
17
+ /((^---[^\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;
15
18
 
16
19
  // Regular expression for matching the start of inline disable/enable comments
17
20
  const inlineCommentStartRe =
18
21
  /(<!--\s*markdownlint-(disable|enable|capture|restore|disable-file|enable-file|disable-line|disable-next-line|configure-file))(?:\s|-->)/gi;
19
22
  module.exports.inlineCommentStartRe = inlineCommentStartRe;
20
23
 
21
- // Regular expression for blockquote prefixes
22
- const blockquotePrefixRe = /^[>\s]*/;
23
- module.exports.blockquotePrefixRe = blockquotePrefixRe;
24
-
25
- // Regular expression for link reference definitions
26
- const linkReferenceDefinitionRe = /^ {0,3}\[([^\]]*[^\\])\]:/;
27
- module.exports.linkReferenceDefinitionRe = linkReferenceDefinitionRe;
28
-
29
24
  // Regular expression for identifying an HTML entity at the end of a line
30
25
  module.exports.endOfLineHtmlEntityRe =
31
26
  /&(?:#\d+|#[xX][\da-fA-F]+|[a-zA-Z]{2,31}|blk\d{2}|emsp1[34]|frac\d{2}|sup\d|there4);$/;
@@ -223,99 +218,6 @@ module.exports.escapeForRegExp = function escapeForRegExp(str) {
223
218
  return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
224
219
  };
225
220
 
226
- /**
227
- * Return the string representation of a fence markup character.
228
- *
229
- * @param {string} markup Fence string.
230
- * @returns {string} String representation.
231
- */
232
- module.exports.fencedCodeBlockStyleFor =
233
- function fencedCodeBlockStyleFor(markup) {
234
- switch (markup[0]) {
235
- case "~":
236
- return "tilde";
237
- default:
238
- return "backtick";
239
- }
240
- };
241
-
242
- /**
243
- * Return the string representation of a emphasis or strong markup character.
244
- *
245
- * @param {string} markup Emphasis or strong string.
246
- * @returns {"asterisk" | "underscore"} String representation.
247
- */
248
- module.exports.emphasisOrStrongStyleFor =
249
- function emphasisOrStrongStyleFor(markup) {
250
- switch (markup[0]) {
251
- case "*":
252
- return "asterisk";
253
- default:
254
- return "underscore";
255
- }
256
- };
257
-
258
- /**
259
- * @callback InlineCodeSpanCallback
260
- * @param {string} code Code content.
261
- * @param {number} lineIndex Line index (0-based).
262
- * @param {number} columnIndex Column index (0-based).
263
- * @param {number} ticks Count of backticks.
264
- * @returns {void}
265
- */
266
-
267
- /**
268
- * Calls the provided function for each inline code span's content.
269
- *
270
- * @param {string} input Markdown content.
271
- * @param {InlineCodeSpanCallback} handler Callback function taking (code,
272
- * lineIndex, columnIndex, ticks).
273
- * @returns {void}
274
- */
275
- function forEachInlineCodeSpan(input, handler) {
276
- const backtickRe = /`+/g;
277
- let match = null;
278
- const backticksLengthAndIndex = [];
279
- while ((match = backtickRe.exec(input)) !== null) {
280
- backticksLengthAndIndex.push([ match[0].length, match.index ]);
281
- }
282
- const newLinesIndex = [];
283
- while ((match = newLineRe.exec(input)) !== null) {
284
- newLinesIndex.push(match.index);
285
- }
286
- let lineIndex = 0;
287
- let lineStartIndex = 0;
288
- let k = 0;
289
- for (let i = 0; i < backticksLengthAndIndex.length - 1; i++) {
290
- const [ startLength, startIndex ] = backticksLengthAndIndex[i];
291
- if ((startIndex === 0) || (input[startIndex - 1] !== "\\")) {
292
- for (let j = i + 1; j < backticksLengthAndIndex.length; j++) {
293
- const [ endLength, endIndex ] = backticksLengthAndIndex[j];
294
- if (startLength === endLength) {
295
- for (; k < newLinesIndex.length; k++) {
296
- const newLineIndex = newLinesIndex[k];
297
- if (startIndex < newLineIndex) {
298
- break;
299
- }
300
- lineIndex++;
301
- lineStartIndex = newLineIndex + 1;
302
- }
303
- const columnIndex = startIndex - lineStartIndex + startLength;
304
- handler(
305
- input.slice(startIndex + startLength, endIndex),
306
- lineIndex,
307
- columnIndex,
308
- startLength
309
- );
310
- i = j;
311
- break;
312
- }
313
- }
314
- }
315
- }
316
- }
317
- module.exports.forEachInlineCodeSpan = forEachInlineCodeSpan;
318
-
319
221
  /**
320
222
  * Adds ellipsis to the left/right/middle of the specified text.
321
223
  *
@@ -341,12 +243,12 @@ module.exports.ellipsify = ellipsify;
341
243
  /**
342
244
  * Adds a generic error object via the onError callback.
343
245
  *
344
- * @param {Object} onError RuleOnError instance.
246
+ * @param {RuleOnError} onError RuleOnError instance.
345
247
  * @param {number} lineNumber Line number.
346
248
  * @param {string} [detail] Error details.
347
249
  * @param {string} [context] Error context.
348
250
  * @param {number[]} [range] Column and length of error.
349
- * @param {Object} [fixInfo] RuleOnErrorFixInfo instance.
251
+ * @param {RuleOnErrorFixInfo} [fixInfo] RuleOnErrorFixInfo instance.
350
252
  * @returns {void}
351
253
  */
352
254
  function addError(onError, lineNumber, detail, context, range, fixInfo) {
@@ -363,14 +265,14 @@ module.exports.addError = addError;
363
265
  /**
364
266
  * Adds an error object with details conditionally via the onError callback.
365
267
  *
366
- * @param {Object} onError RuleOnError instance.
268
+ * @param {RuleOnError} onError RuleOnError instance.
367
269
  * @param {number} lineNumber Line number.
368
270
  * @param {Object} expected Expected value.
369
271
  * @param {Object} actual Actual value.
370
272
  * @param {string} [detail] Error details.
371
273
  * @param {string} [context] Error context.
372
274
  * @param {number[]} [range] Column and length of error.
373
- * @param {Object} [fixInfo] RuleOnErrorFixInfo instance.
275
+ * @param {RuleOnErrorFixInfo} [fixInfo] RuleOnErrorFixInfo instance.
374
276
  * @returns {void}
375
277
  */
376
278
  function addErrorDetailIf(
@@ -391,13 +293,13 @@ module.exports.addErrorDetailIf = addErrorDetailIf;
391
293
  /**
392
294
  * Adds an error object with context via the onError callback.
393
295
  *
394
- * @param {Object} onError RuleOnError instance.
296
+ * @param {RuleOnError} onError RuleOnError instance.
395
297
  * @param {number} lineNumber Line number.
396
298
  * @param {string} context Error context.
397
299
  * @param {boolean} [start] True iff the start of the text is important.
398
300
  * @param {boolean} [end] True iff the end of the text is important.
399
301
  * @param {number[]} [range] Column and length of error.
400
- * @param {Object} [fixInfo] RuleOnErrorFixInfo instance.
302
+ * @param {RuleOnErrorFixInfo} [fixInfo] RuleOnErrorFixInfo instance.
401
303
  * @returns {void}
402
304
  */
403
305
  function addErrorContext(
@@ -408,50 +310,42 @@ function addErrorContext(
408
310
  module.exports.addErrorContext = addErrorContext;
409
311
 
410
312
  /**
411
- * Adds an error object with context for a construct missing a blank line.
313
+ * Defines a range within a file (start line/column to end line/column, subset of MicromarkToken).
412
314
  *
413
- * @param {Object} onError RuleOnError instance.
414
- * @param {string[]} lines Lines of Markdown content.
415
- * @param {number} lineIndex Line index of line.
416
- * @param {number} [lineNumber] Line number for override.
417
- * @returns {void}
315
+ * @typedef {Object} FileRange
316
+ * @property {number} startLine Start line (1-based).
317
+ * @property {number} startColumn Start column (1-based).
318
+ * @property {number} endLine End line (1-based).
319
+ * @property {number} endColumn End column (1-based).
418
320
  */
419
- function addErrorContextForLine(onError, lines, lineIndex, lineNumber) {
420
- const line = lines[lineIndex];
421
- // @ts-ignore
422
- const quotePrefix = line.match(blockquotePrefixRe)[0].trimEnd();
423
- addErrorContext(
424
- onError,
425
- lineIndex + 1,
426
- line.trim(),
427
- undefined,
428
- undefined,
429
- undefined,
430
- {
431
- lineNumber,
432
- "insertText": `${quotePrefix}\n`
433
- }
434
- );
435
- }
436
- module.exports.addErrorContextForLine = addErrorContextForLine;
437
321
 
438
322
  /**
439
- * Determines whether the specified range is within another range.
323
+ * Returns whether line/column A is less than or equal to line/column B.
440
324
  *
441
- * @param {number[][]} ranges Array of ranges (line, index, length).
442
- * @param {number} lineIndex Line index to check.
443
- * @param {number} index Index to check.
444
- * @param {number} length Length to check.
445
- * @returns {boolean} True iff the specified range is within.
325
+ * @param {number} lineA Line A.
326
+ * @param {number} columnA Column A.
327
+ * @param {number} lineB Line B.
328
+ * @param {number} columnB Column B.
329
+ * @returns {boolean} True iff A is less than or equal to B.
446
330
  */
447
- const withinAnyRange = (ranges, lineIndex, index, length) => (
448
- !ranges.every((span) => (
449
- (lineIndex !== span[0]) ||
450
- (index < span[1]) ||
451
- (index + length > span[1] + span[2])
452
- ))
331
+ const positionLessThanOrEqual = (lineA, columnA, lineB, columnB) => (
332
+ (lineA < lineB) ||
333
+ ((lineA === lineB) && (columnA <= columnB))
453
334
  );
454
- module.exports.withinAnyRange = withinAnyRange;
335
+
336
+ /**
337
+ * Returns whether two ranges (or MicromarkTokens) overlap anywhere.
338
+ *
339
+ * @param {FileRange|import("../lib/markdownlint.js").MicromarkToken} rangeA Range A.
340
+ * @param {FileRange|import("../lib/markdownlint.js").MicromarkToken} rangeB Range B.
341
+ * @returns {boolean} True iff the two ranges overlap.
342
+ */
343
+ module.exports.hasOverlap = function hasOverlap(rangeA, rangeB) {
344
+ const lte = positionLessThanOrEqual(rangeA.startLine, rangeA.startColumn, rangeB.startLine, rangeB.startColumn);
345
+ const first = lte ? rangeA : rangeB;
346
+ const second = lte ? rangeB : rangeA;
347
+ return positionLessThanOrEqual(second.startLine, second.startColumn, first.endLine, first.endColumn);
348
+ };
455
349
 
456
350
  // Determines if the front matter includes a title
457
351
  module.exports.frontMatterHasTitle =
@@ -470,16 +364,28 @@ module.exports.frontMatterHasTitle =
470
364
  /**
471
365
  * Returns an object with information about reference links and images.
472
366
  *
473
- * @param {import("../helpers/micromark.cjs").Token[]} tokens Micromark tokens.
367
+ * @param {import("../helpers/micromark-helpers.cjs").Token[]} tokens Micromark tokens.
474
368
  * @returns {Object} Reference link/image data.
475
369
  */
476
370
  function getReferenceLinkImageData(tokens) {
477
371
  const normalizeReference = (s) => s.toLowerCase().trim().replace(/\s+/g, " ");
372
+ const references = new Map();
373
+ const shortcuts = new Map();
374
+ const addReferenceToDictionary = (token, label, isShortcut) => {
375
+ const referenceDatum = [
376
+ token.startLine - 1,
377
+ token.startColumn - 1,
378
+ token.text.length
379
+ ];
380
+ const reference = normalizeReference(label);
381
+ const dictionary = isShortcut ? shortcuts : references;
382
+ const referenceData = dictionary.get(reference) || [];
383
+ referenceData.push(referenceDatum);
384
+ dictionary.set(reference, referenceData);
385
+ };
478
386
  const definitions = new Map();
479
387
  const definitionLineIndices = [];
480
388
  const duplicateDefinitions = [];
481
- const references = new Map();
482
- const shortcuts = new Map();
483
389
  const filteredTokens =
484
390
  micromark.filterByTypes(
485
391
  tokens,
@@ -489,7 +395,9 @@ function getReferenceLinkImageData(tokens) {
489
395
  // definitions and definitionLineIndices
490
396
  "definitionLabelString", "gfmFootnoteDefinitionLabelString",
491
397
  // references and shortcuts
492
- "gfmFootnoteCall", "image", "link"
398
+ "gfmFootnoteCall", "image", "link",
399
+ // undefined link labels
400
+ "undefinedReferenceCollapsed", "undefinedReferenceFull", "undefinedReferenceShortcut"
493
401
  ]
494
402
  );
495
403
  for (const token of filteredTokens) {
@@ -512,15 +420,10 @@ function getReferenceLinkImageData(tokens) {
512
420
  if (definitions.has(reference)) {
513
421
  duplicateDefinitions.push([ reference, token.startLine - 1 ]);
514
422
  } else {
515
- let destinationString = null;
516
423
  const parent =
517
- micromark.getTokenParentOfType(token, [ "definition" ]);
518
- if (parent) {
519
- destinationString = micromark.getTokenTextByType(
520
- micromark.filterByPredicate(parent.children),
521
- "definitionDestinationString"
522
- );
523
- }
424
+ micromark.getParentOfType(token, [ "definition" ]);
425
+ const destinationString = parent &&
426
+ micromark.getDescendantsByType(parent, [ "definitionDestination", "definitionDestinationRaw", "definitionDestinationString" ])[0]?.text;
524
427
  definitions.set(
525
428
  reference,
526
429
  [ token.startLine - 1, destinationString ]
@@ -532,67 +435,38 @@ function getReferenceLinkImageData(tokens) {
532
435
  case "image":
533
436
  case "link":
534
437
  {
535
- let isShortcut = false;
536
- let isFullOrCollapsed = false;
537
- let labelText = null;
538
- let referenceStringText = null;
539
- const shortcutCandidate =
540
- micromark.matchAndGetTokensByType(token.children, [ "label" ]);
541
- if (shortcutCandidate) {
542
- labelText =
543
- micromark.getTokenTextByType(
544
- shortcutCandidate[0].children, "labelText"
545
- );
546
- isShortcut = (labelText !== null);
547
- }
548
- const fullAndCollapsedCandidate =
549
- micromark.matchAndGetTokensByType(
550
- token.children, [ "label", "reference" ]
438
+ // Identify if shortcut or full/collapsed
439
+ let isShortcut = (token.children.length === 1);
440
+ const isFullOrCollapsed = (token.children.length === 2) && !token.children.some((t) => t.type === "resource");
441
+ const [ labelText ] = micromark.getDescendantsByType(token, [ "label", "labelText" ]);
442
+ const [ referenceString ] = micromark.getDescendantsByType(token, [ "reference", "referenceString" ]);
443
+ let label = labelText?.text;
444
+ // Identify if footnote
445
+ if (!isShortcut && !isFullOrCollapsed) {
446
+ const [ footnoteCallMarker, footnoteCallString ] = token.children.filter(
447
+ (t) => [ "gfmFootnoteCallMarker", "gfmFootnoteCallString" ].includes(t.type)
551
448
  );
552
- if (fullAndCollapsedCandidate) {
553
- labelText =
554
- micromark.getTokenTextByType(
555
- fullAndCollapsedCandidate[0].children, "labelText"
556
- );
557
- referenceStringText =
558
- micromark.getTokenTextByType(
559
- fullAndCollapsedCandidate[1].children, "referenceString"
560
- );
561
- isFullOrCollapsed = (labelText !== null);
562
- }
563
- const footnote = micromark.matchAndGetTokensByType(
564
- token.children,
565
- [
566
- "gfmFootnoteCallLabelMarker", "gfmFootnoteCallMarker",
567
- "gfmFootnoteCallString", "gfmFootnoteCallLabelMarker"
568
- ],
569
- [ "gfmFootnoteCallMarker", "gfmFootnoteCallString" ]
570
- );
571
- if (footnote) {
572
- const callMarkerText = footnote[0].text;
573
- const callString = footnote[1].text;
574
- labelText = `${callMarkerText}${callString}`;
575
- isShortcut = true;
449
+ if (footnoteCallMarker && footnoteCallString) {
450
+ label = `${footnoteCallMarker.text}${footnoteCallString.text}`;
451
+ isShortcut = true;
452
+ }
576
453
  }
577
- // Track shortcuts separately due to ambiguity in "text [text] text"
454
+ // Track link (handle shortcuts separately due to ambiguity in "text [text] text")
578
455
  if (isShortcut || isFullOrCollapsed) {
579
- const referenceDatum = [
580
- token.startLine - 1,
581
- token.startColumn - 1,
582
- token.text.length,
583
- // @ts-ignore
584
- labelText.length,
585
- (referenceStringText || "").length
586
- ];
587
- const reference =
588
- normalizeReference(referenceStringText || labelText);
589
- const dictionary = isShortcut ? shortcuts : references;
590
- const referenceData = dictionary.get(reference) || [];
591
- referenceData.push(referenceDatum);
592
- dictionary.set(reference, referenceData);
456
+ addReferenceToDictionary(token, referenceString?.text || label, isShortcut);
593
457
  }
594
458
  }
595
459
  break;
460
+ case "undefinedReferenceCollapsed":
461
+ case "undefinedReferenceFull":
462
+ case "undefinedReferenceShortcut":
463
+ {
464
+ const undefinedReference = micromark.getDescendantsByType(token, [ "undefinedReference" ])[0];
465
+ const label = undefinedReference.children.map((t) => t.text).join("");
466
+ const isShortcut = (token.type === "undefinedReferenceShortcut");
467
+ addReferenceToDictionary(token, label, isShortcut);
468
+ }
469
+ break;
596
470
  }
597
471
  }
598
472
  return {
@@ -645,120 +519,6 @@ function getPreferredLineEnding(input, os) {
645
519
  }
646
520
  module.exports.getPreferredLineEnding = getPreferredLineEnding;
647
521
 
648
- /**
649
- * Normalizes the fields of a RuleOnErrorFixInfo instance.
650
- *
651
- * @param {Object} fixInfo RuleOnErrorFixInfo instance.
652
- * @param {number} [lineNumber] Line number.
653
- * @returns {Object} Normalized RuleOnErrorFixInfo instance.
654
- */
655
- function normalizeFixInfo(fixInfo, lineNumber) {
656
- return {
657
- "lineNumber": fixInfo.lineNumber || lineNumber,
658
- "editColumn": fixInfo.editColumn || 1,
659
- "deleteCount": fixInfo.deleteCount || 0,
660
- "insertText": fixInfo.insertText || ""
661
- };
662
- }
663
-
664
- /**
665
- * Fixes the specified error on a line of Markdown content.
666
- *
667
- * @param {string} line Line of Markdown content.
668
- * @param {Object} fixInfo RuleOnErrorFixInfo instance.
669
- * @param {string} [lineEnding] Line ending to use.
670
- * @returns {string | null} Fixed content.
671
- */
672
- function applyFix(line, fixInfo, lineEnding) {
673
- const { editColumn, deleteCount, insertText } = normalizeFixInfo(fixInfo);
674
- const editIndex = editColumn - 1;
675
- return (deleteCount === -1) ?
676
- null :
677
- line.slice(0, editIndex) +
678
- insertText.replace(/\n/g, lineEnding || "\n") +
679
- line.slice(editIndex + deleteCount);
680
- }
681
- module.exports.applyFix = applyFix;
682
-
683
- /**
684
- * Applies as many fixes as possible to Markdown content.
685
- *
686
- * @param {string} input Lines of Markdown content.
687
- * @param {Object[]} errors RuleOnErrorInfo instances.
688
- * @returns {string} Corrected content.
689
- */
690
- function applyFixes(input, errors) {
691
- const lineEnding = getPreferredLineEnding(input, require("node:os"));
692
- const lines = input.split(newLineRe);
693
- // Normalize fixInfo objects
694
- let fixInfos = errors
695
- .filter((error) => error.fixInfo)
696
- .map((error) => normalizeFixInfo(error.fixInfo, error.lineNumber));
697
- // Sort bottom-to-top, line-deletes last, right-to-left, long-to-short
698
- fixInfos.sort((a, b) => {
699
- const aDeletingLine = (a.deleteCount === -1);
700
- const bDeletingLine = (b.deleteCount === -1);
701
- return (
702
- (b.lineNumber - a.lineNumber) ||
703
- (aDeletingLine ? 1 : (bDeletingLine ? -1 : 0)) ||
704
- (b.editColumn - a.editColumn) ||
705
- (b.insertText.length - a.insertText.length)
706
- );
707
- });
708
- // Remove duplicate entries (needed for following collapse step)
709
- let lastFixInfo = {};
710
- fixInfos = fixInfos.filter((fixInfo) => {
711
- const unique = (
712
- (fixInfo.lineNumber !== lastFixInfo.lineNumber) ||
713
- (fixInfo.editColumn !== lastFixInfo.editColumn) ||
714
- (fixInfo.deleteCount !== lastFixInfo.deleteCount) ||
715
- (fixInfo.insertText !== lastFixInfo.insertText)
716
- );
717
- lastFixInfo = fixInfo;
718
- return unique;
719
- });
720
- // Collapse insert/no-delete and no-insert/delete for same line/column
721
- lastFixInfo = {
722
- "lineNumber": -1
723
- };
724
- for (const fixInfo of fixInfos) {
725
- if (
726
- (fixInfo.lineNumber === lastFixInfo.lineNumber) &&
727
- (fixInfo.editColumn === lastFixInfo.editColumn) &&
728
- !fixInfo.insertText &&
729
- (fixInfo.deleteCount > 0) &&
730
- lastFixInfo.insertText &&
731
- !lastFixInfo.deleteCount) {
732
- fixInfo.insertText = lastFixInfo.insertText;
733
- lastFixInfo.lineNumber = 0;
734
- }
735
- lastFixInfo = fixInfo;
736
- }
737
- fixInfos = fixInfos.filter((fixInfo) => fixInfo.lineNumber);
738
- // Apply all (remaining/updated) fixes
739
- let lastLineIndex = -1;
740
- let lastEditIndex = -1;
741
- for (const fixInfo of fixInfos) {
742
- const { lineNumber, editColumn, deleteCount } = fixInfo;
743
- const lineIndex = lineNumber - 1;
744
- const editIndex = editColumn - 1;
745
- if (
746
- (lineIndex !== lastLineIndex) ||
747
- (deleteCount === -1) ||
748
- ((editIndex + deleteCount) <=
749
- (lastEditIndex - ((deleteCount > 0) ? 0 : 1)))
750
- ) {
751
- // @ts-ignore
752
- lines[lineIndex] = applyFix(lines[lineIndex], fixInfo, lineEnding);
753
- }
754
- lastLineIndex = lineIndex;
755
- lastEditIndex = editIndex;
756
- }
757
- // Return corrected input
758
- return lines.filter((line) => line !== null).join(lineEnding);
759
- }
760
- module.exports.applyFixes = applyFixes;
761
-
762
522
  /**
763
523
  * Expands a path with a tilde to an absolute path.
764
524
  *
@@ -771,23 +531,3 @@ function expandTildePath(file, os) {
771
531
  return homedir ? file.replace(/^~($|\/|\\)/, `${homedir}$1`) : file;
772
532
  }
773
533
  module.exports.expandTildePath = expandTildePath;
774
-
775
- // Copied from markdownlint.js to avoid TypeScript compiler import() issue.
776
- /**
777
- * @typedef {Object} MarkdownItToken
778
- * @property {string[][]} attrs HTML attributes.
779
- * @property {boolean} block Block-level token.
780
- * @property {MarkdownItToken[]} children Child nodes.
781
- * @property {string} content Tag contents.
782
- * @property {boolean} hidden Ignore element.
783
- * @property {string} info Fence info.
784
- * @property {number} level Nesting level.
785
- * @property {number[]} map Beginning/ending line numbers.
786
- * @property {string} markup Markup text.
787
- * @property {Object} meta Arbitrary data.
788
- * @property {number} nesting Level change.
789
- * @property {string} tag HTML tag name.
790
- * @property {string} type Token type.
791
- * @property {number} lineNumber Line number (1-based).
792
- * @property {string} line Line content.
793
- */