markdownlint 0.26.2 → 0.28.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 (95) hide show
  1. package/CHANGELOG.md +378 -0
  2. package/CONTRIBUTING.md +82 -59
  3. package/LICENSE +1 -1
  4. package/README.md +304 -305
  5. package/demo/markdownlint-browser.js +4973 -3379
  6. package/doc/CustomRules.md +99 -51
  7. package/doc/Prettier.md +14 -10
  8. package/doc/ReleaseProcess.md +20 -0
  9. package/doc/Rules.md +474 -311
  10. package/doc/md001.md +37 -0
  11. package/doc/md002.md +37 -0
  12. package/doc/md003.md +59 -0
  13. package/doc/md004.md +49 -0
  14. package/doc/md005.md +53 -0
  15. package/doc/md006.md +46 -0
  16. package/doc/md007.md +55 -0
  17. package/doc/md009.md +51 -0
  18. package/doc/md010.md +56 -0
  19. package/doc/md011.md +30 -0
  20. package/doc/md012.md +38 -0
  21. package/doc/md013.md +60 -0
  22. package/doc/md014.md +54 -0
  23. package/doc/md018.md +27 -0
  24. package/doc/md019.md +28 -0
  25. package/doc/md020.md +29 -0
  26. package/doc/md021.md +31 -0
  27. package/doc/md022.md +46 -0
  28. package/doc/md023.md +26 -0
  29. package/doc/md024.md +47 -0
  30. package/doc/md025.md +49 -0
  31. package/doc/md026.md +41 -0
  32. package/doc/md027.md +24 -0
  33. package/doc/md028.md +40 -0
  34. package/doc/md029.md +98 -0
  35. package/doc/md030.md +82 -0
  36. package/doc/md031.md +50 -0
  37. package/doc/md032.md +38 -0
  38. package/doc/md033.md +27 -0
  39. package/doc/md034.md +50 -0
  40. package/doc/md035.md +42 -0
  41. package/doc/md036.md +45 -0
  42. package/doc/md037.md +37 -0
  43. package/doc/md038.md +40 -0
  44. package/doc/md039.md +21 -0
  45. package/doc/md040.md +52 -0
  46. package/doc/md041.md +49 -0
  47. package/doc/md042.md +32 -0
  48. package/doc/md043.md +72 -0
  49. package/doc/md044.md +35 -0
  50. package/doc/md045.md +34 -0
  51. package/doc/md046.md +40 -0
  52. package/doc/md047.md +34 -0
  53. package/doc/md048.md +41 -0
  54. package/doc/md049.md +32 -0
  55. package/doc/md050.md +32 -0
  56. package/doc/md051.md +50 -0
  57. package/doc/md052.md +33 -0
  58. package/doc/md053.md +38 -0
  59. package/helpers/LICENSE +1 -1
  60. package/helpers/README.md +35 -15
  61. package/helpers/helpers.js +182 -162
  62. package/helpers/micromark.cjs +209 -0
  63. package/helpers/package.json +5 -2
  64. package/lib/constants.js +8 -1
  65. package/lib/markdownlint.d.ts +5 -5
  66. package/lib/markdownlint.js +46 -24
  67. package/lib/md002.js +1 -1
  68. package/lib/md011.js +2 -2
  69. package/lib/md013.js +7 -6
  70. package/lib/md019.js +1 -1
  71. package/lib/md022.js +15 -3
  72. package/lib/md023.js +1 -1
  73. package/lib/md026.js +1 -1
  74. package/lib/md027.js +1 -1
  75. package/lib/md028.js +1 -1
  76. package/lib/md033.js +47 -29
  77. package/lib/md034.js +54 -47
  78. package/lib/md035.js +9 -11
  79. package/lib/md036.js +1 -1
  80. package/lib/md037.js +2 -2
  81. package/lib/md038.js +81 -56
  82. package/lib/md039.js +1 -1
  83. package/lib/md040.js +21 -2
  84. package/lib/md041.js +1 -1
  85. package/lib/md043.js +4 -2
  86. package/lib/md044.js +58 -43
  87. package/lib/md046.js +1 -1
  88. package/lib/md048.js +3 -1
  89. package/lib/md051.js +37 -5
  90. package/lib/rules.js +1 -1
  91. package/package.json +43 -28
  92. package/schema/.markdownlint.jsonc +11 -4
  93. package/schema/.markdownlint.yaml +11 -6
  94. package/schema/markdownlint-config-schema.json +27 -3
  95. package/style/prettier.json +26 -0
@@ -0,0 +1,209 @@
1
+ // @ts-check
2
+
3
+ "use strict";
4
+
5
+ // @ts-ignore
6
+ const {
7
+ gfmAutolinkLiteral, gfmFootnote, gfmTable, parse, postprocess, preprocess
8
+ // @ts-ignore
9
+ } = require("markdownlint-micromark");
10
+
11
+ /**
12
+ * Markdown token.
13
+ *
14
+ * @typedef {Object} Token
15
+ * @property {string} type Token type.
16
+ * @property {number} startLine Start line (1-based).
17
+ * @property {number} startColumn Start column (1-based).
18
+ * @property {number} endLine End line (1-based).
19
+ * @property {number} endColumn End column (1-based).
20
+ * @property {string} text Token text.
21
+ * @property {Token[]} children Child tokens.
22
+ */
23
+
24
+ /**
25
+ * Parses a Markdown document and returns Micromark events.
26
+ *
27
+ * @param {string} markdown Markdown document.
28
+ * @param {Object} [options] Options for micromark.
29
+ * @returns {Object[]} Micromark events.
30
+ */
31
+ function getMicromarkEvents(markdown, options = {}) {
32
+
33
+ // Customize options object to add useful extensions
34
+ options.extensions = options.extensions || [];
35
+ options.extensions.push(gfmAutolinkLiteral, gfmFootnote(), gfmTable);
36
+
37
+ // Use micromark to parse document into Events
38
+ const encoding = undefined;
39
+ const eol = true;
40
+ const parseContext = parse(options);
41
+ // Customize ParseContext to treat all references as defined
42
+ parseContext.defined.includes = (searchElement) => searchElement.length > 0;
43
+ const chunks = preprocess()(markdown, encoding, eol);
44
+ const events = postprocess(parseContext.document().write(chunks));
45
+ return events;
46
+ }
47
+
48
+ /**
49
+ * Parses a Markdown document and returns (frozen) tokens.
50
+ *
51
+ * @param {string} markdown Markdown document.
52
+ * @param {Object} [options] Options for micromark.
53
+ * @returns {Token[]} Micromark tokens (frozen).
54
+ */
55
+ function micromarkParse(markdown, options = {}) {
56
+
57
+ // Use micromark to parse document into Events
58
+ const events = getMicromarkEvents(markdown, options);
59
+
60
+ // Create Token objects
61
+ const document = [];
62
+ let current = {
63
+ "children": document
64
+ };
65
+ const history = [ current ];
66
+ for (const event of events) {
67
+ const [ kind, token, context ] = event;
68
+ const { type, start, end } = token;
69
+ const { "column": startColumn, "line": startLine } = start;
70
+ const { "column": endColumn, "line": endLine } = end;
71
+ let text = null;
72
+ try {
73
+ text = context.sliceSerialize(token);
74
+ } catch {
75
+ // https://github.com/micromark/micromark/issues/131
76
+ }
77
+ if (kind === "enter") {
78
+ const previous = current;
79
+ history.push(previous);
80
+ current = {
81
+ type,
82
+ startLine,
83
+ startColumn,
84
+ endLine,
85
+ endColumn,
86
+ text,
87
+ "children": []
88
+ };
89
+ previous.children.push(current);
90
+ } else if (kind === "exit") {
91
+ Object.freeze(current.children);
92
+ Object.freeze(current);
93
+ // @ts-ignore
94
+ current = history.pop();
95
+ }
96
+ }
97
+
98
+ // Return document
99
+ Object.freeze(document);
100
+ return document;
101
+ }
102
+
103
+ /**
104
+ * Filter a list of Micromark tokens by predicate.
105
+ *
106
+ * @param {Token[]} tokens Micromark tokens.
107
+ * @param {Function} allowed Allowed token predicate.
108
+ * @param {Function} [transformChildren] Transform children predicate.
109
+ * @returns {Token[]} Filtered tokens.
110
+ */
111
+ function filterByPredicate(tokens, allowed, transformChildren) {
112
+ const result = [];
113
+ const pending = [ ...tokens ];
114
+ let token = null;
115
+ while ((token = pending.shift())) {
116
+ if (allowed(token)) {
117
+ result.push(token);
118
+ }
119
+ if (token.children.length > 0) {
120
+ const transformed =
121
+ transformChildren ? transformChildren(token) : token.children;
122
+ pending.unshift(...transformed);
123
+ }
124
+ }
125
+ return result;
126
+ }
127
+
128
+ /**
129
+ * Filter a list of Micromark tokens by type.
130
+ *
131
+ * @param {Token[]} tokens Micromark tokens.
132
+ * @param {string[]} allowed Types to allow.
133
+ * @returns {Token[]} Filtered tokens.
134
+ */
135
+ function filterByTypes(tokens, allowed) {
136
+ return filterByPredicate(
137
+ tokens,
138
+ (token) => allowed.includes(token.type)
139
+ );
140
+ }
141
+
142
+ /**
143
+ * Gets information about the tag in an HTML token.
144
+ *
145
+ * @param {Token} token Micromark token.
146
+ * @returns {Object | null} HTML tag information.
147
+ */
148
+ function getHtmlTagInfo(token) {
149
+ const htmlTagNameRe = /^<([^!>][^/\s>]*)/;
150
+ if (token.type === "htmlText") {
151
+ const match = htmlTagNameRe.exec(token.text);
152
+ if (match) {
153
+ const name = match[1];
154
+ const close = name.startsWith("/");
155
+ return {
156
+ close,
157
+ "name": close ? name.slice(1) : name
158
+ };
159
+ }
160
+ }
161
+ return null;
162
+ }
163
+
164
+ /**
165
+ * Get the text of a single token from a list of Micromark tokens by type.
166
+ *
167
+ * @param {Token[]} tokens Micromark tokens.
168
+ * @param {string} type Types to match.
169
+ * @returns {string | null} Text of token.
170
+ */
171
+ function getTokenTextByType(tokens, type) {
172
+ const filtered = tokens.filter((token) => token.type === type);
173
+ return (filtered.length === 1) ? filtered[0].text : null;
174
+ }
175
+
176
+ /**
177
+ * Determines a list of Micromark tokens matches and returns a subset.
178
+ *
179
+ * @param {Token[]} tokens Micromark tokens.
180
+ * @param {string[]} matchTypes Types to match.
181
+ * @param {string[]} [resultTypes] Types to return.
182
+ * @returns {Token[] | null} Matching tokens.
183
+ */
184
+ function matchAndGetTokensByType(tokens, matchTypes, resultTypes) {
185
+ if (tokens.length !== matchTypes.length) {
186
+ return null;
187
+ }
188
+ resultTypes = resultTypes || matchTypes;
189
+ const result = [];
190
+ // eslint-disable-next-line unicorn/no-for-loop
191
+ for (let i = 0; i < matchTypes.length; i++) {
192
+ if (tokens[i].type !== matchTypes[i]) {
193
+ return null;
194
+ } else if (resultTypes.includes(matchTypes[i])) {
195
+ result.push(tokens[i]);
196
+ }
197
+ }
198
+ return result;
199
+ }
200
+
201
+ module.exports = {
202
+ "parse": micromarkParse,
203
+ filterByPredicate,
204
+ filterByTypes,
205
+ getHtmlTagInfo,
206
+ getMicromarkEvents,
207
+ getTokenTextByType,
208
+ matchAndGetTokensByType
209
+ };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markdownlint-rule-helpers",
3
- "version": "0.17.2",
3
+ "version": "0.19.0",
4
4
  "description": "A collection of markdownlint helper functions for custom rules",
5
5
  "main": "./helpers.js",
6
6
  "exports": "./helpers.js",
@@ -13,7 +13,10 @@
13
13
  },
14
14
  "bugs": "https://github.com/DavidAnson/markdownlint/issues",
15
15
  "engines": {
16
- "node": ">=12"
16
+ "node": ">=14.18.0"
17
+ },
18
+ "dependencies": {
19
+ "markdownlint-micromark": "0.1.2"
17
20
  },
18
21
  "keywords": [
19
22
  "markdownlint",
package/lib/constants.js CHANGED
@@ -3,5 +3,12 @@
3
3
  "use strict";
4
4
 
5
5
  module.exports.deprecatedRuleNames = [ "MD002", "MD006" ];
6
+ module.exports.fixableRuleNames = [
7
+ "MD004", "MD005", "MD006", "MD007", "MD009", "MD010",
8
+ "MD011", "MD012", "MD014", "MD018", "MD019", "MD020",
9
+ "MD021", "MD022", "MD023", "MD026", "MD027", "MD030",
10
+ "MD031", "MD032", "MD034", "MD037", "MD038", "MD039",
11
+ "MD044", "MD047", "MD049", "MD050", "MD051", "MD053"
12
+ ];
6
13
  module.exports.homepage = "https://github.com/DavidAnson/markdownlint";
7
- module.exports.version = "0.26.2";
14
+ module.exports.version = "0.28.0";
@@ -2,11 +2,11 @@ export = markdownlint;
2
2
  /**
3
3
  * Lint specified Markdown files.
4
4
  *
5
- * @param {Options} options Configuration options.
5
+ * @param {Options | null} options Configuration options.
6
6
  * @param {LintCallback} callback Callback (err, result) function.
7
7
  * @returns {void}
8
8
  */
9
- declare function markdownlint(options: Options, callback: LintCallback): void;
9
+ declare function markdownlint(options: Options | null, callback: LintCallback): void;
10
10
  declare namespace markdownlint {
11
11
  export { markdownlintSync as sync, readConfig, readConfigSync, getVersion, promises, RuleFunction, RuleParams, MarkdownItToken, RuleOnError, RuleOnErrorInfo, RuleOnErrorFixInfo, Rule, Options, Plugin, ToStringCallback, LintResults, LintError, FixInfo, LintCallback, Configuration, RuleConfiguration, ConfigurationParser, ReadConfigCallback, ResolveConfigExtendsCallback };
12
12
  }
@@ -33,7 +33,7 @@ type Options = {
33
33
  /**
34
34
  * Front matter pattern.
35
35
  */
36
- frontMatter?: RegExp;
36
+ frontMatter?: RegExp | null;
37
37
  /**
38
38
  * File system implementation.
39
39
  */
@@ -68,10 +68,10 @@ type LintCallback = (err: Error | null, results?: LintResults) => void;
68
68
  /**
69
69
  * Lint specified Markdown files synchronously.
70
70
  *
71
- * @param {Options} options Configuration options.
71
+ * @param {Options | null} options Configuration options.
72
72
  * @returns {LintResults} Results object.
73
73
  */
74
- declare function markdownlintSync(options: Options): LintResults;
74
+ declare function markdownlintSync(options: Options | null): LintResults;
75
75
  /**
76
76
  * Read specified configuration file.
77
77
  *
@@ -2,9 +2,10 @@
2
2
 
3
3
  "use strict";
4
4
 
5
- const path = require("path");
6
- const { promisify } = require("util");
7
- const markdownIt = require("markdown-it");
5
+ const path = require("node:path");
6
+ const { promisify } = require("node:util");
7
+ const markdownit = require("markdown-it");
8
+ const micromark = require("../helpers/micromark.cjs");
8
9
  const { deprecatedRuleNames } = require("./constants");
9
10
  const rules = require("./rules");
10
11
  const helpers = require("../helpers");
@@ -166,7 +167,7 @@ function newResults(ruleList) {
166
167
  * Remove front matter (if present at beginning of content).
167
168
  *
168
169
  * @param {string} content Markdown content.
169
- * @param {RegExp} frontMatter Regular expression to match front matter.
170
+ * @param {RegExp | null} frontMatter Regular expression to match front matter.
170
171
  * @returns {Object} Trimmed content and front matter lines.
171
172
  */
172
173
  function removeFrontMatter(content, frontMatter) {
@@ -508,12 +509,14 @@ function getEnabledRulesPerLineNumber(
508
509
  * Lints a string containing Markdown content.
509
510
  *
510
511
  * @param {Rule[]} ruleList List of rules.
512
+ * @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule
513
+ * names.
511
514
  * @param {string} name Identifier for the content.
512
515
  * @param {string} content Markdown content.
513
516
  * @param {Object} md Instance of markdown-it.
514
517
  * @param {Configuration} config Configuration object.
515
518
  * @param {ConfigurationParser[] | null} configParsers Configuration parsers.
516
- * @param {RegExp} frontMatter Regular expression for front matter.
519
+ * @param {RegExp | null} frontMatter Regular expression for front matter.
517
520
  * @param {boolean} handleRuleFailures Whether to handle exceptions in rules.
518
521
  * @param {boolean} noInlineConfig Whether to allow inline configuration.
519
522
  * @param {number} resultVersion Version of the LintResults object to return.
@@ -522,6 +525,7 @@ function getEnabledRulesPerLineNumber(
522
525
  */
523
526
  function lintContent(
524
527
  ruleList,
528
+ aliasToRuleNames,
525
529
  name,
526
530
  content,
527
531
  md,
@@ -547,18 +551,29 @@ function lintContent(
547
551
  noInlineConfig,
548
552
  config,
549
553
  configParsers,
550
- mapAliasToRuleNames(ruleList)
554
+ aliasToRuleNames
551
555
  );
552
- // Hide the content of HTML comments from rules, etc.
556
+ // Parse content into parser tokens
557
+ const markdownitTokens = md.parse(content, {});
558
+ const micromarkTokens = micromark.parse(content);
559
+ // Hide the content of HTML comments from rules
553
560
  content = helpers.clearHtmlCommentText(content);
554
- // Parse content into tokens and lines
555
- const tokens = md.parse(content, {});
561
+ // Parse content into lines and update markdown-it tokens
556
562
  const lines = content.split(helpers.newLineRe);
557
- annotateAndFreezeTokens(tokens, lines);
563
+ annotateAndFreezeTokens(markdownitTokens, lines);
558
564
  // Create (frozen) parameters for rules
565
+ const parsers = Object.freeze({
566
+ "markdownit": Object.freeze({
567
+ "tokens": markdownitTokens
568
+ }),
569
+ "micromark": Object.freeze({
570
+ "tokens": micromarkTokens
571
+ })
572
+ });
559
573
  const paramsBase = {
560
574
  name,
561
- tokens,
575
+ parsers,
576
+ "tokens": markdownitTokens,
562
577
  "lines": Object.freeze(lines),
563
578
  "frontMatterLines": Object.freeze(frontMatterLines)
564
579
  };
@@ -567,11 +582,11 @@ function lintContent(
567
582
  const codeBlockAndSpanRanges =
568
583
  helpers.codeBlockAndSpanRanges(paramsBase, lineMetadata);
569
584
  const flattenedLists =
570
- helpers.flattenLists(paramsBase.tokens);
585
+ helpers.flattenLists(paramsBase.parsers.markdownit.tokens);
571
586
  const htmlElementRanges =
572
587
  helpers.htmlElementRanges(paramsBase, lineMetadata);
573
588
  const referenceLinkImageData =
574
- helpers.getReferenceLinkImageData(lineMetadata);
589
+ helpers.getReferenceLinkImageData(paramsBase);
575
590
  cache.set({
576
591
  codeBlockAndSpanRanges,
577
592
  flattenedLists,
@@ -780,11 +795,13 @@ function lintContent(
780
795
  * Lints a file containing Markdown content.
781
796
  *
782
797
  * @param {Rule[]} ruleList List of rules.
798
+ * @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule
799
+ * names.
783
800
  * @param {string} file Path of file to lint.
784
801
  * @param {Object} md Instance of markdown-it.
785
802
  * @param {Configuration} config Configuration object.
786
803
  * @param {ConfigurationParser[] | null} configParsers Configuration parsers.
787
- * @param {RegExp} frontMatter Regular expression for front matter.
804
+ * @param {RegExp | null} frontMatter Regular expression for front matter.
788
805
  * @param {boolean} handleRuleFailures Whether to handle exceptions in rules.
789
806
  * @param {boolean} noInlineConfig Whether to allow inline configuration.
790
807
  * @param {number} resultVersion Version of the LintResults object to return.
@@ -795,6 +812,7 @@ function lintContent(
795
812
  */
796
813
  function lintFile(
797
814
  ruleList,
815
+ aliasToRuleNames,
798
816
  file,
799
817
  md,
800
818
  config,
@@ -813,6 +831,7 @@ function lintFile(
813
831
  }
814
832
  return lintContent(
815
833
  ruleList,
834
+ aliasToRuleNames,
816
835
  file,
817
836
  content,
818
837
  md,
@@ -836,7 +855,7 @@ function lintFile(
836
855
  /**
837
856
  * Lint files and strings specified in the Options object.
838
857
  *
839
- * @param {Options} options Options object.
858
+ * @param {Options | null} options Options object.
840
859
  * @param {boolean} synchronous Whether to execute synchronously.
841
860
  * @param {Function} callback Callback (err, result) function.
842
861
  * @returns {void}
@@ -868,13 +887,14 @@ function lintInput(options, synchronous, callback) {
868
887
  const noInlineConfig = !!options.noInlineConfig;
869
888
  const resultVersion = (options.resultVersion === undefined) ?
870
889
  3 : options.resultVersion;
871
- const md = markdownIt({ "html": true });
890
+ const md = markdownit({ "html": true });
872
891
  const markdownItPlugins = options.markdownItPlugins || [];
873
892
  for (const plugin of markdownItPlugins) {
874
893
  // @ts-ignore
875
894
  md.use(...plugin);
876
895
  }
877
- const fs = options.fs || require("fs");
896
+ const fs = options.fs || require("node:fs");
897
+ const aliasToRuleNames = mapAliasToRuleNames(ruleList);
878
898
  const results = newResults(ruleList);
879
899
  let done = false;
880
900
  let concurrency = 0;
@@ -902,6 +922,7 @@ function lintInput(options, synchronous, callback) {
902
922
  currentItem = files.shift();
903
923
  lintFile(
904
924
  ruleList,
925
+ aliasToRuleNames,
905
926
  currentItem,
906
927
  md,
907
928
  config,
@@ -919,6 +940,7 @@ function lintInput(options, synchronous, callback) {
919
940
  concurrency++;
920
941
  lintContent(
921
942
  ruleList,
943
+ aliasToRuleNames,
922
944
  currentItem,
923
945
  strings[currentItem] || "",
924
946
  md,
@@ -959,7 +981,7 @@ function lintInput(options, synchronous, callback) {
959
981
  /**
960
982
  * Lint specified Markdown files.
961
983
  *
962
- * @param {Options} options Configuration options.
984
+ * @param {Options | null} options Configuration options.
963
985
  * @param {LintCallback} callback Callback (err, result) function.
964
986
  * @returns {void}
965
987
  */
@@ -983,7 +1005,7 @@ function markdownlintPromise(options) {
983
1005
  /**
984
1006
  * Lint specified Markdown files synchronously.
985
1007
  *
986
- * @param {Options} options Configuration options.
1008
+ * @param {Options | null} options Configuration options.
987
1009
  * @returns {LintResults} Results object.
988
1010
  */
989
1011
  function markdownlintSync(options) {
@@ -1080,10 +1102,10 @@ function readConfig(file, parsers, fs, callback) {
1080
1102
  }
1081
1103
  }
1082
1104
  if (!fs) {
1083
- fs = require("fs");
1105
+ fs = require("node:fs");
1084
1106
  }
1085
1107
  // Read file
1086
- const os = require("os");
1108
+ const os = require("node:os");
1087
1109
  file = helpers.expandTildePath(file, os);
1088
1110
  fs.readFile(file, "utf8", (err, content) => {
1089
1111
  if (err) {
@@ -1155,10 +1177,10 @@ function readConfigPromise(file, parsers, fs) {
1155
1177
  */
1156
1178
  function readConfigSync(file, parsers, fs) {
1157
1179
  if (!fs) {
1158
- fs = require("fs");
1180
+ fs = require("node:fs");
1159
1181
  }
1160
1182
  // Read file
1161
- const os = require("os");
1183
+ const os = require("node:os");
1162
1184
  file = helpers.expandTildePath(file, os);
1163
1185
  const content = fs.readFileSync(file, "utf8");
1164
1186
  // Try to parse file
@@ -1295,7 +1317,7 @@ module.exports = markdownlint;
1295
1317
  * @property {ConfigurationParser[]} [configParsers] Configuration parsers.
1296
1318
  * @property {Rule[] | Rule} [customRules] Custom rules.
1297
1319
  * @property {string[] | string} [files] Files to lint.
1298
- * @property {RegExp} [frontMatter] Front matter pattern.
1320
+ * @property {RegExp | null} [frontMatter] Front matter pattern.
1299
1321
  * @property {Object} [fs] File system implementation.
1300
1322
  * @property {boolean} [handleRuleFailures] True to catch exceptions.
1301
1323
  * @property {Plugin[]} [markdownItPlugins] Additional plugins.
package/lib/md002.js CHANGED
@@ -11,7 +11,7 @@ module.exports = {
11
11
  "function": function MD002(params, onError) {
12
12
  const level = Number(params.config.level || 1);
13
13
  const tag = "h" + level;
14
- params.tokens.every(function forToken(token) {
14
+ params.parsers.markdownit.tokens.every(function forToken(token) {
15
15
  if (token.type === "heading_open") {
16
16
  addErrorDetailIf(onError, token.lineNumber, tag, token.tag);
17
17
  return false;
package/lib/md011.js CHANGED
@@ -6,7 +6,7 @@ const { addError, forEachLine, withinAnyRange } = require("../helpers");
6
6
  const { codeBlockAndSpanRanges, lineMetadata } = require("./cache");
7
7
 
8
8
  const reversedLinkRe =
9
- /(^|[^\\])\(([^)]+)\)\[([^\]^][^\]]*)](?!\()/g;
9
+ /(^|[^\\])\(([^()]+)\)\[([^\]^][^\]]*)\](?!\()/g;
10
10
 
11
11
  module.exports = {
12
12
  "names": [ "MD011", "no-reversed-links" ],
@@ -30,7 +30,7 @@ module.exports = {
30
30
  onError,
31
31
  lineIndex + 1,
32
32
  reversedLink.slice(preChar.length),
33
- null,
33
+ undefined,
34
34
  [ index + 1, length ],
35
35
  {
36
36
  "editColumn": index + 1,
package/lib/md013.js CHANGED
@@ -3,14 +3,14 @@
3
3
  "use strict";
4
4
 
5
5
  const { addErrorDetailIf, filterTokens, forEachHeading, forEachLine,
6
- includesSorted, linkReferenceDefinitionRe } = require("../helpers");
7
- const { lineMetadata } = require("./cache");
6
+ includesSorted } = require("../helpers");
7
+ const { lineMetadata, referenceLinkImageData } = require("./cache");
8
8
 
9
9
  const longLineRePrefix = "^.{";
10
10
  const longLineRePostfixRelaxed = "}.*\\s.*$";
11
11
  const longLineRePostfixStrict = "}.+$";
12
- const linkOrImageOnlyLineRe = /^[es]*(lT?L|I)[ES]*$/;
13
- const sternModeRe = /^([#>\s]*\s)?\S*$/;
12
+ const linkOrImageOnlyLineRe = /^[es]*(?:lT?L|I)[ES]*$/;
13
+ const sternModeRe = /^(?:[#>\s]*\s)?\S*$/;
14
14
  const tokenTypeMap = {
15
15
  "em_open": "e",
16
16
  "em_close": "E",
@@ -67,6 +67,7 @@ module.exports = {
67
67
  linkOnlyLineNumbers.push(token.lineNumber);
68
68
  }
69
69
  });
70
+ const { definitionLineIndices } = referenceLinkImageData();
70
71
  forEachLine(lineMetadata(), (line, lineIndex, inCode, onFence, inTable) => {
71
72
  const lineNumber = lineIndex + 1;
72
73
  const isHeading = includesSorted(headingLineNumbers, lineNumber);
@@ -79,10 +80,10 @@ module.exports = {
79
80
  if ((includeCodeBlocks || !inCode) &&
80
81
  (includeTables || !inTable) &&
81
82
  (includeHeadings || !isHeading) &&
83
+ !includesSorted(definitionLineIndices, lineIndex) &&
82
84
  (strict ||
83
85
  (!(stern && sternModeRe.test(line)) &&
84
- !includesSorted(linkOnlyLineNumbers, lineNumber) &&
85
- !linkReferenceDefinitionRe.test(line))) &&
86
+ !includesSorted(linkOnlyLineNumbers, lineNumber))) &&
86
87
  lengthRe.test(line)) {
87
88
  addErrorDetailIf(
88
89
  onError,
package/lib/md019.js CHANGED
@@ -13,7 +13,7 @@ module.exports = {
13
13
  filterTokens(params, "heading_open", (token) => {
14
14
  if (headingStyleFor(token) === "atx") {
15
15
  const { line, lineNumber } = token;
16
- const match = /^(#+)([ \t]{2,})(?:\S)/.exec(line);
16
+ const match = /^(#+)([ \t]{2,})\S/.exec(line);
17
17
  if (match) {
18
18
  const [
19
19
  ,
package/lib/md022.js CHANGED
@@ -2,7 +2,17 @@
2
2
 
3
3
  "use strict";
4
4
 
5
- const { addErrorDetailIf, filterTokens, isBlankLine } = require("../helpers");
5
+ const { addErrorDetailIf, blockquotePrefixRe, filterTokens, isBlankLine } =
6
+ require("../helpers");
7
+
8
+ const getBlockQuote = (str, count) => (
9
+ (str || "")
10
+ .match(blockquotePrefixRe)[0]
11
+ .trimEnd()
12
+ // eslint-disable-next-line unicorn/prefer-spread
13
+ .concat("\n")
14
+ .repeat(count)
15
+ );
6
16
 
7
17
  module.exports = {
8
18
  "names": [ "MD022", "blanks-around-headings", "blanks-around-headers" ],
@@ -31,7 +41,8 @@ module.exports = {
31
41
  lines[topIndex].trim(),
32
42
  null,
33
43
  {
34
- "insertText": "".padEnd(linesAbove - actualAbove, "\n")
44
+ "insertText":
45
+ getBlockQuote(lines[topIndex - 1], linesAbove - actualAbove)
35
46
  });
36
47
  let actualBelow = 0;
37
48
  for (let i = 0; i < linesBelow; i++) {
@@ -49,7 +60,8 @@ module.exports = {
49
60
  null,
50
61
  {
51
62
  "lineNumber": nextIndex + 1,
52
- "insertText": "".padEnd(linesBelow - actualBelow, "\n")
63
+ "insertText":
64
+ getBlockQuote(lines[nextIndex], linesBelow - actualBelow)
53
65
  });
54
66
  });
55
67
  }
package/lib/md023.js CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  const { addErrorContext, filterTokens } = require("../helpers");
6
6
 
7
- const spaceBeforeHeadingRe = /^((?:\s+)|(?:[>\s]+\s\s))[^>\s]/;
7
+ const spaceBeforeHeadingRe = /^(\s+|[>\s]+\s\s)[^>\s]/;
8
8
 
9
9
  module.exports = {
10
10
  "names": [ "MD023", "heading-start-left", "header-start-left" ],
package/lib/md026.js CHANGED
@@ -5,7 +5,7 @@
5
5
  const { addError, allPunctuationNoQuestion, escapeForRegExp, forEachHeading } =
6
6
  require("../helpers");
7
7
 
8
- const endOfLineHtmlEntityRe = /&#?[0-9a-zA-Z]+;$/;
8
+ const endOfLineHtmlEntityRe = /&#?[\da-zA-Z]+;$/;
9
9
 
10
10
  module.exports = {
11
11
  "names": [ "MD026", "no-trailing-punctuation" ],
package/lib/md027.js CHANGED
@@ -13,7 +13,7 @@ module.exports = {
13
13
  "function": function MD027(params, onError) {
14
14
  let blockquoteNesting = 0;
15
15
  let listItemNesting = 0;
16
- for (const token of params.tokens) {
16
+ for (const token of params.parsers.markdownit.tokens) {
17
17
  const { content, lineNumber, type } = token;
18
18
  if (type === "blockquote_open") {
19
19
  blockquoteNesting++;
package/lib/md028.js CHANGED
@@ -11,7 +11,7 @@ module.exports = {
11
11
  "function": function MD028(params, onError) {
12
12
  let prevToken = {};
13
13
  let prevLineNumber = null;
14
- for (const token of params.tokens) {
14
+ for (const token of params.parsers.markdownit.tokens) {
15
15
  if ((token.type === "blockquote_open") &&
16
16
  (prevToken.type === "blockquote_close")) {
17
17
  for (