markdownlint 0.32.1 → 0.34.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 (76) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/CONTRIBUTING.md +4 -3
  3. package/README.md +6 -0
  4. package/demo/markdownlint-browser.js +3866 -3564
  5. package/doc/CustomRules.md +14 -7
  6. package/doc/Rules.md +139 -12
  7. package/doc/md013.md +8 -7
  8. package/doc/md024.md +2 -5
  9. package/doc/md049.md +3 -0
  10. package/doc/md050.md +3 -0
  11. package/doc/md051.md +26 -0
  12. package/doc/md055.md +54 -0
  13. package/doc/md056.md +37 -0
  14. package/helpers/README.md +5 -3
  15. package/helpers/helpers.js +5 -5
  16. package/helpers/micromark.cjs +46 -27
  17. package/helpers/package.json +2 -2
  18. package/lib/configuration.d.ts +136 -110
  19. package/lib/constants.js +1 -1
  20. package/lib/markdownlint.d.ts +79 -6
  21. package/lib/markdownlint.js +95 -21
  22. package/lib/md001.js +3 -0
  23. package/lib/md003.js +3 -0
  24. package/lib/md004.js +3 -0
  25. package/lib/md005.js +12 -4
  26. package/lib/md007.js +17 -11
  27. package/lib/md009.js +3 -0
  28. package/lib/md010.js +4 -1
  29. package/lib/md011.js +3 -0
  30. package/lib/md012.js +3 -0
  31. package/lib/md013.js +3 -0
  32. package/lib/md014.js +4 -0
  33. package/lib/md018.js +4 -0
  34. package/lib/md019.js +3 -0
  35. package/lib/md020.js +3 -0
  36. package/lib/md021.js +3 -0
  37. package/lib/md022.js +10 -2
  38. package/lib/md023.js +3 -0
  39. package/lib/md024.js +11 -4
  40. package/lib/md025.js +3 -0
  41. package/lib/md026.js +11 -7
  42. package/lib/md027.js +29 -43
  43. package/lib/md028.js +31 -14
  44. package/lib/md029.js +3 -0
  45. package/lib/md030.js +9 -4
  46. package/lib/md031.js +3 -0
  47. package/lib/md032.js +12 -14
  48. package/lib/md033.js +9 -2
  49. package/lib/md034.js +31 -5
  50. package/lib/md035.js +9 -2
  51. package/lib/md036.js +33 -39
  52. package/lib/md037.js +10 -2
  53. package/lib/md038.js +27 -18
  54. package/lib/md039.js +4 -0
  55. package/lib/md040.js +26 -21
  56. package/lib/md041.js +21 -26
  57. package/lib/md042.js +4 -0
  58. package/lib/md043.js +3 -0
  59. package/lib/md044.js +9 -1
  60. package/lib/md045.js +10 -3
  61. package/lib/md046.js +14 -7
  62. package/lib/md047.js +5 -2
  63. package/lib/md048.js +26 -13
  64. package/lib/md049-md050.js +26 -7
  65. package/lib/md051.js +20 -16
  66. package/lib/md052.js +3 -0
  67. package/lib/md053.js +3 -0
  68. package/lib/md054.js +10 -5
  69. package/lib/md055.js +80 -0
  70. package/lib/md056.js +52 -0
  71. package/lib/rules.js +5 -3
  72. package/package.json +26 -32
  73. package/schema/.markdownlint.jsonc +58 -51
  74. package/schema/.markdownlint.yaml +56 -50
  75. package/schema/ValidatingConfiguration.md +28 -0
  76. package/schema/markdownlint-config-schema.json +165 -113
package/lib/md037.js CHANGED
@@ -5,20 +5,28 @@
5
5
  const { addError } = require("../helpers");
6
6
  const { filterByPredicate, inHtmlFlow } = require("../helpers/micromark.cjs");
7
7
 
8
+ // eslint-disable-next-line jsdoc/valid-types
9
+ /** @type import("./markdownlint").Rule */
8
10
  module.exports = {
9
11
  "names": [ "MD037", "no-space-in-emphasis" ],
10
12
  "description": "Spaces inside emphasis markers",
11
13
  "tags": [ "whitespace", "emphasis" ],
14
+ "parser": "micromark",
12
15
  "function": function MD037(params, onError) {
13
16
 
14
17
  // Initialize variables
15
- const { lines, parsers } = params;
18
+ // eslint-disable-next-line jsdoc/valid-types
19
+ /** @type import("../helpers/micromark.cjs").Token[] */
20
+ const micromarkTokens =
21
+ // @ts-ignore
22
+ params.parsers.micromark.tokens;
23
+ const { lines } = params;
16
24
  const emphasisTokensByMarker = new Map();
17
25
  for (const marker of [ "_", "__", "___", "*", "**", "***" ]) {
18
26
  emphasisTokensByMarker.set(marker, []);
19
27
  }
20
28
  const tokens = filterByPredicate(
21
- parsers.micromark.tokens,
29
+ micromarkTokens,
22
30
  (token) => token.children.some((child) => child.type === "data")
23
31
  );
24
32
  for (const token of tokens) {
package/lib/md038.js CHANGED
@@ -19,14 +19,21 @@ const trimCodeText = (text, start, end) => {
19
19
  return text;
20
20
  };
21
21
 
22
+ // eslint-disable-next-line jsdoc/valid-types
23
+ /** @type import("./markdownlint").Rule */
22
24
  module.exports = {
23
25
  "names": [ "MD038", "no-space-in-code" ],
24
26
  "description": "Spaces inside code span elements",
25
27
  "tags": [ "whitespace", "code" ],
28
+ "parser": "micromark",
26
29
  "function": function MD038(params, onError) {
27
- const codeTexts =
28
- filterByTypes(params.parsers.micromark.tokens, [ "codeText" ])
29
- .filter((codeText) => !inHtmlFlow(codeText));
30
+ // eslint-disable-next-line jsdoc/valid-types
31
+ /** @type import("../helpers/micromark.cjs").Token[] */
32
+ const micromarkTokens =
33
+ // @ts-ignore
34
+ params.parsers.micromark.tokens;
35
+ const codeTexts = filterByTypes(micromarkTokens, [ "codeText" ])
36
+ .filter((codeText) => !inHtmlFlow(codeText));
30
37
  for (const codeText of codeTexts) {
31
38
  const { children } = codeText;
32
39
  const first = 0;
@@ -41,7 +48,7 @@ module.exports = {
41
48
  tokenIfType(children[last - 2], "codeTextData");
42
49
  if (startSequence && endSequence && startData && endData) {
43
50
  const spaceLeft = leftSpaceRe.test(startData.text);
44
- const spaceRight = !spaceLeft && rightSpaceRe.test(endData.text);
51
+ const spaceRight = rightSpaceRe.test(endData.text);
45
52
  if (spaceLeft || spaceRight) {
46
53
  let lineNumber = startSequence.startLine;
47
54
  let range = null;
@@ -56,7 +63,7 @@ module.exports = {
56
63
  "deleteCount": endSequence.startColumn - startSequence.endColumn,
57
64
  "insertText": trimCodeText(startData.text, true, true)
58
65
  };
59
- } else if (spaceLeft) {
66
+ } else if (spaceLeft && (startSequence.endLine === startData.startLine)) {
60
67
  range = [
61
68
  startSequence.startColumn,
62
69
  startData.endColumn - startSequence.startColumn
@@ -66,7 +73,7 @@ module.exports = {
66
73
  "deleteCount": startData.endColumn - startData.startColumn,
67
74
  "insertText": trimCodeText(startData.text, true, false)
68
75
  };
69
- } else {
76
+ } else if (spaceRight && (endData.text.trim().length > 0)) {
70
77
  lineNumber = endSequence.endLine;
71
78
  range = [
72
79
  endData.startColumn,
@@ -78,18 +85,20 @@ module.exports = {
78
85
  "insertText": trimCodeText(endData.text, false, true)
79
86
  };
80
87
  }
81
- const context = params
82
- .lines[lineNumber - 1]
83
- .substring(range[0] - 1, range[0] - 1 + range[1]);
84
- addErrorContext(
85
- onError,
86
- lineNumber,
87
- context,
88
- spaceLeft,
89
- spaceRight,
90
- range,
91
- fixInfo
92
- );
88
+ if (range) {
89
+ const context = params
90
+ .lines[lineNumber - 1]
91
+ .substring(range[0] - 1, range[0] - 1 + range[1]);
92
+ addErrorContext(
93
+ onError,
94
+ lineNumber,
95
+ context,
96
+ spaceLeft,
97
+ spaceRight,
98
+ range,
99
+ fixInfo
100
+ );
101
+ }
93
102
  }
94
103
  }
95
104
  }
package/lib/md039.js CHANGED
@@ -7,10 +7,13 @@ const { addErrorContext, filterTokens } = require("../helpers");
7
7
  const spaceInLinkRe =
8
8
  /\[(?:\s[^\]]*|[^\]]*?\s)\](?=(\([^)]*\)|\[[^\]]*\]))/;
9
9
 
10
+ // eslint-disable-next-line jsdoc/valid-types
11
+ /** @type import("./markdownlint").Rule */
10
12
  module.exports = {
11
13
  "names": [ "MD039", "no-space-in-links" ],
12
14
  "description": "Spaces inside link text",
13
15
  "tags": [ "whitespace", "links" ],
16
+ "parser": "markdownit",
14
17
  "function": function MD039(params, onError) {
15
18
  filterTokens(params, "inline", (token) => {
16
19
  const { children } = token;
@@ -33,6 +36,7 @@ module.exports = {
33
36
  let fixInfo = null;
34
37
  const match = line.slice(lineIndex).match(spaceInLinkRe);
35
38
  if (match) {
39
+ // @ts-ignore
36
40
  const column = match.index + lineIndex + 1;
37
41
  const length = match[0].length;
38
42
  range = [ column, length ];
package/lib/md040.js CHANGED
@@ -2,36 +2,41 @@
2
2
 
3
3
  "use strict";
4
4
 
5
- const { addError, addErrorContext, filterTokens } = require("../helpers");
5
+ const { addError, addErrorContext } = require("../helpers");
6
+ const { filterByTypes, getTokenTextByType, tokenIfType } =
7
+ require("../helpers/micromark.cjs");
6
8
 
9
+ // eslint-disable-next-line jsdoc/valid-types
10
+ /** @type import("./markdownlint").Rule */
7
11
  module.exports = {
8
12
  "names": [ "MD040", "fenced-code-language" ],
9
13
  "description": "Fenced code blocks should have a language specified",
10
14
  "tags": [ "code", "language" ],
15
+ "parser": "micromark",
11
16
  "function": function MD040(params, onError) {
12
17
  let allowed = params.config.allowed_languages;
13
18
  allowed = Array.isArray(allowed) ? allowed : [];
14
19
  const languageOnly = !!params.config.language_only;
15
-
16
- filterTokens(params, "fence", function forToken(token) {
17
- const lang = token.info.trim().split(/\s+/u).shift();
18
- if (lang === "") {
19
- addErrorContext(onError, token.lineNumber, token.line);
20
- } else if ((allowed.length > 0) && !allowed.includes(lang)) {
21
- addError(
22
- onError,
23
- token.lineNumber,
24
- `"${lang}" is not allowed`
25
- );
26
- }
27
-
28
- if (languageOnly && (token.info !== lang)) {
29
- addError(
30
- onError,
31
- token.lineNumber,
32
- `Info string contains more than language: "${token.info}"`
33
- );
20
+ // eslint-disable-next-line jsdoc/valid-types
21
+ /** @type import("../helpers/micromark.cjs").Token[] */
22
+ const micromarkTokens =
23
+ // @ts-ignore
24
+ params.parsers.micromark.tokens;
25
+ const fencedCodes = filterByTypes(micromarkTokens, [ "codeFenced" ]);
26
+ for (const fencedCode of fencedCodes) {
27
+ const openingFence = tokenIfType(fencedCode.children[0], "codeFencedFence");
28
+ if (openingFence) {
29
+ const { children, startLine, text } = openingFence;
30
+ const info = getTokenTextByType(children, "codeFencedFenceInfo");
31
+ if (!info) {
32
+ addErrorContext(onError, startLine, text);
33
+ } else if ((allowed.length > 0) && !allowed.includes(info)) {
34
+ addError(onError, startLine, `"${info}" is not allowed`);
35
+ }
36
+ if (languageOnly && getTokenTextByType(children, "codeFencedFenceMeta")) {
37
+ addError(onError, startLine, `Info string contains more than language: "${text}"`);
38
+ }
34
39
  }
35
- });
40
+ }
36
41
  }
37
42
  };
package/lib/md041.js CHANGED
@@ -3,40 +3,35 @@
3
3
  "use strict";
4
4
 
5
5
  const { addErrorContext, frontMatterHasTitle } = require("../helpers");
6
+ const { filterByTypes, getHeadingLevel, getHtmlTagInfo, isHtmlFlowComment, nonContentTokens } =
7
+ require("../helpers/micromark.cjs");
6
8
 
9
+ // eslint-disable-next-line jsdoc/valid-types
10
+ /** @type import("./markdownlint").Rule */
7
11
  module.exports = {
8
12
  "names": [ "MD041", "first-line-heading", "first-line-h1" ],
9
13
  "description": "First line in a file should be a top-level heading",
10
14
  "tags": [ "headings" ],
15
+ "parser": "micromark",
11
16
  "function": function MD041(params, onError) {
12
17
  const level = Number(params.config.level || 1);
13
- const tag = "h" + level;
14
- const foundFrontMatterTitle =
15
- frontMatterHasTitle(
16
- params.frontMatterLines,
17
- params.config.front_matter_title
18
- );
19
- if (!foundFrontMatterTitle) {
20
- const htmlHeadingRe = new RegExp(`^<h${level}[ />]`, "i");
21
- params.parsers.markdownit.tokens.every((token) => {
22
- let isError = false;
23
- if (token.type === "html_block") {
24
- if (token.content.startsWith("<!--")) {
25
- // Ignore leading HTML comments
26
- return true;
27
- } else if (!htmlHeadingRe.test(token.content)) {
28
- // Something other than an HTML heading
29
- isError = true;
18
+ if (!frontMatterHasTitle(params.frontMatterLines, params.config.front_matter_title)) {
19
+ params.parsers.micromark.tokens.
20
+ filter((token) => !nonContentTokens.has(token.type) && !isHtmlFlowComment(token)).
21
+ every((token) => {
22
+ let isError = true;
23
+ if ((token.type === "atxHeading") || (token.type === "setextHeading")) {
24
+ isError = (getHeadingLevel(token) !== level);
25
+ } else if (token.type === "htmlFlow") {
26
+ const htmlTexts = filterByTypes(token.children, [ "htmlText" ]);
27
+ const tagInfo = (htmlTexts.length > 0) && getHtmlTagInfo(htmlTexts[0]);
28
+ isError = !tagInfo || (tagInfo.name.toLowerCase() !== `h${level}`);
30
29
  }
31
- } else if ((token.type !== "heading_open") || (token.tag !== tag)) {
32
- // Something other than a Markdown heading
33
- isError = true;
34
- }
35
- if (isError) {
36
- addErrorContext(onError, token.lineNumber, token.line);
37
- }
38
- return false;
39
- });
30
+ if (isError) {
31
+ addErrorContext(onError, token.startLine, params.lines[token.startLine - 1]);
32
+ }
33
+ return false;
34
+ });
40
35
  }
41
36
  }
42
37
  };
package/lib/md042.js CHANGED
@@ -5,10 +5,13 @@
5
5
  const { addErrorContext, escapeForRegExp, filterTokens } =
6
6
  require("../helpers");
7
7
 
8
+ // eslint-disable-next-line jsdoc/valid-types
9
+ /** @type import("./markdownlint").Rule */
8
10
  module.exports = {
9
11
  "names": [ "MD042", "no-empty-links" ],
10
12
  "description": "No empty links",
11
13
  "tags": [ "links" ],
14
+ "parser": "markdownit",
12
15
  "function": function MD042(params, onError) {
13
16
  filterTokens(params, "inline", function forToken(token) {
14
17
  let inLink = false;
@@ -33,6 +36,7 @@ module.exports = {
33
36
  );
34
37
  if (match) {
35
38
  context = match[0];
39
+ // @ts-ignore
36
40
  range = [ match.index + 1, match[0].length ];
37
41
  }
38
42
  addErrorContext(
package/lib/md043.js CHANGED
@@ -5,10 +5,13 @@
5
5
  const { addErrorContext, addErrorDetailIf, forEachHeading } =
6
6
  require("../helpers");
7
7
 
8
+ // eslint-disable-next-line jsdoc/valid-types
9
+ /** @type import("./markdownlint").Rule */
8
10
  module.exports = {
9
11
  "names": [ "MD043", "required-headings" ],
10
12
  "description": "Required heading structure",
11
13
  "tags": [ "headings" ],
14
+ "parser": "markdownit",
12
15
  "function": function MD043(params, onError) {
13
16
  const requiredHeadings = params.config.headings;
14
17
  if (!Array.isArray(requiredHeadings)) {
package/lib/md044.js CHANGED
@@ -11,10 +11,13 @@ const ignoredChildTypes = new Set(
11
11
  [ "codeFencedFence", "definition", "reference", "resource" ]
12
12
  );
13
13
 
14
+ // eslint-disable-next-line jsdoc/valid-types
15
+ /** @type import("./markdownlint").Rule */
14
16
  module.exports = {
15
17
  "names": [ "MD044", "proper-names" ],
16
18
  "description": "Proper names should have the correct capitalization",
17
19
  "tags": [ "spelling" ],
20
+ "parser": "micromark",
18
21
  "function": function MD044(params, onError) {
19
22
  let names = params.config.names;
20
23
  names = Array.isArray(names) ? names : [];
@@ -29,6 +32,11 @@ module.exports = {
29
32
  const htmlElements = params.config.html_elements;
30
33
  const includeHtmlElements =
31
34
  (htmlElements === undefined) ? true : !!htmlElements;
35
+ // eslint-disable-next-line jsdoc/valid-types
36
+ /** @type import("../helpers/micromark.cjs").Token[] */
37
+ const micromarkTokens =
38
+ // @ts-ignore
39
+ params.parsers.micromark.tokens;
32
40
  const scannedTypes = new Set([ "data" ]);
33
41
  if (includeCodeBlocks) {
34
42
  scannedTypes.add("codeFlowValue");
@@ -40,7 +48,7 @@ module.exports = {
40
48
  }
41
49
  const contentTokens =
42
50
  filterByPredicate(
43
- params.parsers.micromark.tokens,
51
+ micromarkTokens,
44
52
  (token) => scannedTypes.has(token.type),
45
53
  (token) => (
46
54
  token.children.filter((t) => !ignoredChildTypes.has(t.type))
package/lib/md045.js CHANGED
@@ -7,15 +7,22 @@ const { filterByTypes, getHtmlTagInfo } = require("../helpers/micromark.cjs");
7
7
 
8
8
  const altRe = getHtmlAttributeRe("alt");
9
9
 
10
+ // eslint-disable-next-line jsdoc/valid-types
11
+ /** @type import("./markdownlint").Rule */
10
12
  module.exports = {
11
13
  "names": [ "MD045", "no-alt-text" ],
12
14
  "description": "Images should have alternate text (alt text)",
13
15
  "tags": [ "accessibility", "images" ],
16
+ "parser": "micromark",
14
17
  "function": function MD045(params, onError) {
15
- const { tokens } = params.parsers.micromark;
18
+ // eslint-disable-next-line jsdoc/valid-types
19
+ /** @type import("../helpers/micromark.cjs").Token[] */
20
+ const micromarkTokens =
21
+ // @ts-ignore
22
+ params.parsers.micromark.tokens;
16
23
 
17
24
  // Process Markdown images
18
- const images = filterByTypes(tokens, [ "image" ]);
25
+ const images = filterByTypes(micromarkTokens, [ "image" ]);
19
26
  for (const image of images) {
20
27
  const labelTexts = filterByTypes(image.children, [ "labelText" ]);
21
28
  if (labelTexts.some((labelText) => labelText.text.length === 0)) {
@@ -33,7 +40,7 @@ module.exports = {
33
40
  }
34
41
 
35
42
  // Process HTML images
36
- const htmlTexts = filterByTypes(tokens, [ "htmlText" ]);
43
+ const htmlTexts = filterByTypes(micromarkTokens, [ "htmlText" ]);
37
44
  for (const htmlText of htmlTexts) {
38
45
  const { startColumn, startLine, text } = htmlText;
39
46
  const htmlTagInfo = getHtmlTagInfo(htmlText);
package/lib/md046.js CHANGED
@@ -3,29 +3,36 @@
3
3
  "use strict";
4
4
 
5
5
  const { addErrorDetailIf } = require("../helpers");
6
+ const { filterByTypes } = require("../helpers/micromark.cjs");
6
7
 
7
8
  const tokenTypeToStyle = {
8
- "fence": "fenced",
9
- "code_block": "indented"
9
+ "codeFenced": "fenced",
10
+ "codeIndented": "indented"
10
11
  };
11
12
 
13
+ // eslint-disable-next-line jsdoc/valid-types
14
+ /** @type import("./markdownlint").Rule */
12
15
  module.exports = {
13
16
  "names": [ "MD046", "code-block-style" ],
14
17
  "description": "Code block style",
15
18
  "tags": [ "code" ],
19
+ "parser": "micromark",
16
20
  "function": function MD046(params, onError) {
17
21
  let expectedStyle = String(params.config.style || "consistent");
18
- const codeBlocksAndFences = params.parsers.markdownit.tokens.filter(
19
- (token) => (token.type === "code_block") || (token.type === "fence")
20
- );
22
+ // eslint-disable-next-line jsdoc/valid-types
23
+ /** @type import("../helpers/micromark.cjs").Token[] */
24
+ const micromarkTokens =
25
+ // @ts-ignore
26
+ params.parsers.micromark.tokens;
27
+ const codeBlocksAndFences = filterByTypes(micromarkTokens, [ "codeFenced", "codeIndented" ]);
21
28
  for (const token of codeBlocksAndFences) {
22
- const { lineNumber, type } = token;
29
+ const { startLine, type } = token;
23
30
  if (expectedStyle === "consistent") {
24
31
  expectedStyle = tokenTypeToStyle[type];
25
32
  }
26
33
  addErrorDetailIf(
27
34
  onError,
28
- lineNumber,
35
+ startLine,
29
36
  expectedStyle,
30
37
  tokenTypeToStyle[type]);
31
38
  }
package/lib/md047.js CHANGED
@@ -4,10 +4,13 @@
4
4
 
5
5
  const { addError, isBlankLine } = require("../helpers");
6
6
 
7
+ // eslint-disable-next-line jsdoc/valid-types
8
+ /** @type import("./markdownlint").Rule */
7
9
  module.exports = {
8
10
  "names": [ "MD047", "single-trailing-newline" ],
9
11
  "description": "Files should end with a single newline character",
10
12
  "tags": [ "blank_lines" ],
13
+ "parser": "none",
11
14
  "function": function MD047(params, onError) {
12
15
  const lastLineNumber = params.lines.length;
13
16
  const lastLine = params.lines[lastLineNumber - 1];
@@ -15,8 +18,8 @@ module.exports = {
15
18
  addError(
16
19
  onError,
17
20
  lastLineNumber,
18
- null,
19
- null,
21
+ undefined,
22
+ undefined,
20
23
  [ lastLine.length, 1 ],
21
24
  {
22
25
  "insertText": "\n",
package/lib/md048.js CHANGED
@@ -3,28 +3,41 @@
3
3
  "use strict";
4
4
 
5
5
  const { addErrorDetailIf, fencedCodeBlockStyleFor } = require("../helpers");
6
+ const { filterByTypes, tokenIfType } = require("../helpers/micromark.cjs");
6
7
 
8
+ // eslint-disable-next-line jsdoc/valid-types
9
+ /** @type import("./markdownlint").Rule */
7
10
  module.exports = {
8
11
  "names": [ "MD048", "code-fence-style" ],
9
12
  "description": "Code fence style",
10
13
  "tags": [ "code" ],
14
+ "parser": "micromark",
11
15
  "function": function MD048(params, onError) {
12
16
  const style = String(params.config.style || "consistent");
17
+ // eslint-disable-next-line jsdoc/valid-types
18
+ /** @type import("../helpers/micromark.cjs").Token[] */
19
+ const micromarkTokens =
20
+ // @ts-ignore
21
+ params.parsers.micromark.tokens;
13
22
  let expectedStyle = style;
14
- const fenceTokens = params.parsers.markdownit.tokens.filter(
15
- (token) => token.type === "fence"
16
- );
17
- for (const fenceToken of fenceTokens) {
18
- const { lineNumber, markup } = fenceToken;
19
- if (expectedStyle === "consistent") {
20
- expectedStyle = fencedCodeBlockStyleFor(markup);
23
+ const codeFenceds = filterByTypes(micromarkTokens, [ "codeFenced" ]);
24
+ for (const codeFenced of codeFenceds) {
25
+ const codeFencedFence = tokenIfType(codeFenced.children[0], "codeFencedFence");
26
+ if (codeFencedFence) {
27
+ const codeFencedFenceSequence = tokenIfType(codeFencedFence.children[0], "codeFencedFenceSequence");
28
+ if (codeFencedFenceSequence) {
29
+ const { startLine, text } = codeFencedFenceSequence;
30
+ if (expectedStyle === "consistent") {
31
+ expectedStyle = fencedCodeBlockStyleFor(text);
32
+ }
33
+ addErrorDetailIf(
34
+ onError,
35
+ startLine,
36
+ expectedStyle,
37
+ fencedCodeBlockStyleFor(text)
38
+ );
39
+ }
21
40
  }
22
- addErrorDetailIf(
23
- onError,
24
- lineNumber,
25
- expectedStyle,
26
- fencedCodeBlockStyleFor(markup)
27
- );
28
41
  }
29
42
  }
30
43
  };
@@ -5,21 +5,34 @@
5
5
  const { addError, emphasisOrStrongStyleFor } = require("../helpers");
6
6
  const { filterByPredicate, tokenIfType } = require("../helpers/micromark.cjs");
7
7
 
8
- const intrawordRe = /\w/;
8
+ const intrawordRe = /^\w$/;
9
9
 
10
+ /**
11
+ * @param {import("./markdownlint").RuleParams} params Rule parameters.
12
+ * @param {import("./markdownlint").RuleOnError} onError Error-reporting callback.
13
+ * @param {import("markdownlint-micromark").TokenType} type Token type.
14
+ * @param {import("markdownlint-micromark").TokenType} typeSequence Token sequence type.
15
+ * @param {"*" | "**"} asterisk Asterisk kind.
16
+ * @param {"_" | "__"} underline Underline kind.
17
+ * @param {"asterisk" | "consistent" | "underscore"} style Style string.
18
+ */
10
19
  const impl =
11
- (params, onError, type, asterisk, underline, style = "consistent") => {
12
- const { lines, parsers } = params;
20
+ (params, onError, type, typeSequence, asterisk, underline, style = "consistent") => {
21
+ // eslint-disable-next-line jsdoc/valid-types
22
+ /** @type import("../helpers/micromark.cjs").Token[] */
23
+ const micromarkTokens =
24
+ // @ts-ignore
25
+ params.parsers.micromark.tokens;
26
+ const { lines } = params;
13
27
  const emphasisTokens = filterByPredicate(
14
- parsers.micromark.tokens,
28
+ micromarkTokens,
15
29
  (token) => token.type === type,
16
30
  (token) => ((token.type === "htmlFlow") ? [] : token.children)
17
31
  );
18
32
  for (const token of emphasisTokens) {
19
33
  const { children } = token;
20
- const childType = `${type}Sequence`;
21
- const startSequence = tokenIfType(children[0], childType);
22
- const endSequence = tokenIfType(children[children.length - 1], childType);
34
+ const startSequence = tokenIfType(children[0], typeSequence);
35
+ const endSequence = tokenIfType(children[children.length - 1], typeSequence);
23
36
  if (startSequence && endSequence) {
24
37
  const markupStyle = emphasisOrStrongStyleFor(startSequence.text);
25
38
  if (style === "consistent") {
@@ -55,16 +68,20 @@ const impl =
55
68
  }
56
69
  };
57
70
 
71
+ // eslint-disable-next-line jsdoc/valid-types
72
+ /** @type import("./markdownlint").Rule[] */
58
73
  module.exports = [
59
74
  {
60
75
  "names": [ "MD049", "emphasis-style" ],
61
76
  "description": "Emphasis style",
62
77
  "tags": [ "emphasis" ],
78
+ "parser": "micromark",
63
79
  "function": function MD049(params, onError) {
64
80
  return impl(
65
81
  params,
66
82
  onError,
67
83
  "emphasis",
84
+ "emphasisSequence",
68
85
  "*",
69
86
  "_",
70
87
  params.config.style || undefined
@@ -75,11 +92,13 @@ module.exports = [
75
92
  "names": [ "MD050", "strong-style" ],
76
93
  "description": "Strong style",
77
94
  "tags": [ "emphasis" ],
95
+ "parser": "micromark",
78
96
  "function": function MD050(params, onError) {
79
97
  return impl(
80
98
  params,
81
99
  onError,
82
100
  "strong",
101
+ "strongSequence",
83
102
  "**",
84
103
  "__",
85
104
  params.config.style || undefined