mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-09-21 21:30:47 +02:00
Reimplement MD003/heading-style using micromark tokens.
This commit is contained in:
parent
e447db33c9
commit
6daaa43410
10 changed files with 132 additions and 148 deletions
|
@ -1539,6 +1539,26 @@ function getHeadingLevel(heading) {
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the heading style of a Micromark heading tokan.
|
||||||
|
*
|
||||||
|
* @param {Token} heading Micromark heading token.
|
||||||
|
* @returns {"atx" | "atx_closed" | "setext"} Heading style.
|
||||||
|
*/
|
||||||
|
function getHeadingStyle(heading) {
|
||||||
|
if (heading.type === "setextHeading") {
|
||||||
|
return "setext";
|
||||||
|
}
|
||||||
|
const atxHeadingSequenceLength = filterByTypes(
|
||||||
|
heading.children,
|
||||||
|
[ "atxHeadingSequence" ]
|
||||||
|
).length;
|
||||||
|
if (atxHeadingSequenceLength === 1) {
|
||||||
|
return "atx";
|
||||||
|
}
|
||||||
|
return "atx_closed";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTML tag information.
|
* HTML tag information.
|
||||||
*
|
*
|
||||||
|
@ -1663,6 +1683,7 @@ module.exports = {
|
||||||
filterByPredicate,
|
filterByPredicate,
|
||||||
filterByTypes,
|
filterByTypes,
|
||||||
getHeadingLevel,
|
getHeadingLevel,
|
||||||
|
getHeadingStyle,
|
||||||
getHtmlTagInfo,
|
getHtmlTagInfo,
|
||||||
getMicromarkEvents,
|
getMicromarkEvents,
|
||||||
getTokenParentOfType,
|
getTokenParentOfType,
|
||||||
|
@ -3352,8 +3373,9 @@ module.exports = {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const { addErrorDetailIf, filterTokens, headingStyleFor } =
|
const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
||||||
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
const { filterByTypes, getHeadingLevel, getHeadingStyle, inHtmlFlow } =
|
||||||
|
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/valid-types
|
// eslint-disable-next-line jsdoc/valid-types
|
||||||
/** @type import("./markdownlint").Rule */
|
/** @type import("./markdownlint").Rule */
|
||||||
|
@ -3361,16 +3383,20 @@ module.exports = {
|
||||||
"names": [ "MD003", "heading-style" ],
|
"names": [ "MD003", "heading-style" ],
|
||||||
"description": "Heading style",
|
"description": "Heading style",
|
||||||
"tags": [ "headings" ],
|
"tags": [ "headings" ],
|
||||||
"parser": "markdownit",
|
"parser": "micromark",
|
||||||
"function": function MD003(params, onError) {
|
"function": function MD003(params, onError) {
|
||||||
let style = String(params.config.style || "consistent");
|
let style = String(params.config.style || "consistent");
|
||||||
filterTokens(params, "heading_open", function forToken(token) {
|
const headings = filterByTypes(
|
||||||
const styleForToken = headingStyleFor(token);
|
params.parsers.micromark.tokens,
|
||||||
|
[ "atxHeading", "setextHeading" ]
|
||||||
|
);
|
||||||
|
for (const heading of headings) {
|
||||||
|
const styleForToken = getHeadingStyle(heading);
|
||||||
if (style === "consistent") {
|
if (style === "consistent") {
|
||||||
style = styleForToken;
|
style = styleForToken;
|
||||||
}
|
}
|
||||||
if (styleForToken !== style) {
|
if ((styleForToken !== style) && !inHtmlFlow(heading)) {
|
||||||
const h12 = /h[12]/.test(token.tag);
|
const h12 = getHeadingLevel(heading) <= 2;
|
||||||
const setextWithAtx =
|
const setextWithAtx =
|
||||||
(style === "setext_with_atx") &&
|
(style === "setext_with_atx") &&
|
||||||
((h12 && (styleForToken === "setext")) ||
|
((h12 && (styleForToken === "setext")) ||
|
||||||
|
@ -3386,11 +3412,15 @@ module.exports = {
|
||||||
} else if (style === "setext_with_atx_closed") {
|
} else if (style === "setext_with_atx_closed") {
|
||||||
expected = h12 ? "setext" : "atx_closed";
|
expected = h12 ? "setext" : "atx_closed";
|
||||||
}
|
}
|
||||||
addErrorDetailIf(onError, token.lineNumber,
|
addErrorDetailIf(
|
||||||
expected, styleForToken);
|
onError,
|
||||||
|
heading.startLine,
|
||||||
|
expected,
|
||||||
|
styleForToken
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4061,8 +4091,8 @@ module.exports = {
|
||||||
lineNumber,
|
lineNumber,
|
||||||
length,
|
length,
|
||||||
line.length,
|
line.length,
|
||||||
null,
|
undefined,
|
||||||
null,
|
undefined,
|
||||||
[ length + 1, line.length - length ]);
|
[ length + 1, line.length - length ]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -4226,8 +4256,8 @@ module.exports = {
|
||||||
onError,
|
onError,
|
||||||
lineNumber,
|
lineNumber,
|
||||||
line.trim(),
|
line.trim(),
|
||||||
null,
|
undefined,
|
||||||
null,
|
undefined,
|
||||||
[ 1, hashLength + spacesLength + 1 ],
|
[ 1, hashLength + spacesLength + 1 ],
|
||||||
{
|
{
|
||||||
"editColumn": hashLength + 1,
|
"editColumn": hashLength + 1,
|
||||||
|
|
|
@ -309,6 +309,26 @@ function getHeadingLevel(heading) {
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the heading style of a Micromark heading tokan.
|
||||||
|
*
|
||||||
|
* @param {Token} heading Micromark heading token.
|
||||||
|
* @returns {"atx" | "atx_closed" | "setext"} Heading style.
|
||||||
|
*/
|
||||||
|
function getHeadingStyle(heading) {
|
||||||
|
if (heading.type === "setextHeading") {
|
||||||
|
return "setext";
|
||||||
|
}
|
||||||
|
const atxHeadingSequenceLength = filterByTypes(
|
||||||
|
heading.children,
|
||||||
|
[ "atxHeadingSequence" ]
|
||||||
|
).length;
|
||||||
|
if (atxHeadingSequenceLength === 1) {
|
||||||
|
return "atx";
|
||||||
|
}
|
||||||
|
return "atx_closed";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTML tag information.
|
* HTML tag information.
|
||||||
*
|
*
|
||||||
|
@ -433,6 +453,7 @@ module.exports = {
|
||||||
filterByPredicate,
|
filterByPredicate,
|
||||||
filterByTypes,
|
filterByTypes,
|
||||||
getHeadingLevel,
|
getHeadingLevel,
|
||||||
|
getHeadingStyle,
|
||||||
getHtmlTagInfo,
|
getHtmlTagInfo,
|
||||||
getMicromarkEvents,
|
getMicromarkEvents,
|
||||||
getTokenParentOfType,
|
getTokenParentOfType,
|
||||||
|
|
29
lib/md003.js
29
lib/md003.js
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const { addErrorDetailIf, filterTokens, headingStyleFor } =
|
const { addErrorDetailIf } = require("../helpers");
|
||||||
require("../helpers");
|
const { filterByTypes, getHeadingLevel, getHeadingStyle, inHtmlFlow } =
|
||||||
|
require("../helpers/micromark.cjs");
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/valid-types
|
// eslint-disable-next-line jsdoc/valid-types
|
||||||
/** @type import("./markdownlint").Rule */
|
/** @type import("./markdownlint").Rule */
|
||||||
|
@ -11,16 +12,20 @@ module.exports = {
|
||||||
"names": [ "MD003", "heading-style" ],
|
"names": [ "MD003", "heading-style" ],
|
||||||
"description": "Heading style",
|
"description": "Heading style",
|
||||||
"tags": [ "headings" ],
|
"tags": [ "headings" ],
|
||||||
"parser": "markdownit",
|
"parser": "micromark",
|
||||||
"function": function MD003(params, onError) {
|
"function": function MD003(params, onError) {
|
||||||
let style = String(params.config.style || "consistent");
|
let style = String(params.config.style || "consistent");
|
||||||
filterTokens(params, "heading_open", function forToken(token) {
|
const headings = filterByTypes(
|
||||||
const styleForToken = headingStyleFor(token);
|
params.parsers.micromark.tokens,
|
||||||
|
[ "atxHeading", "setextHeading" ]
|
||||||
|
);
|
||||||
|
for (const heading of headings) {
|
||||||
|
const styleForToken = getHeadingStyle(heading);
|
||||||
if (style === "consistent") {
|
if (style === "consistent") {
|
||||||
style = styleForToken;
|
style = styleForToken;
|
||||||
}
|
}
|
||||||
if (styleForToken !== style) {
|
if ((styleForToken !== style) && !inHtmlFlow(heading)) {
|
||||||
const h12 = /h[12]/.test(token.tag);
|
const h12 = getHeadingLevel(heading) <= 2;
|
||||||
const setextWithAtx =
|
const setextWithAtx =
|
||||||
(style === "setext_with_atx") &&
|
(style === "setext_with_atx") &&
|
||||||
((h12 && (styleForToken === "setext")) ||
|
((h12 && (styleForToken === "setext")) ||
|
||||||
|
@ -36,10 +41,14 @@ module.exports = {
|
||||||
} else if (style === "setext_with_atx_closed") {
|
} else if (style === "setext_with_atx_closed") {
|
||||||
expected = h12 ? "setext" : "atx_closed";
|
expected = h12 ? "setext" : "atx_closed";
|
||||||
}
|
}
|
||||||
addErrorDetailIf(onError, token.lineNumber,
|
addErrorDetailIf(
|
||||||
expected, styleForToken);
|
onError,
|
||||||
|
heading.startLine,
|
||||||
|
expected,
|
||||||
|
styleForToken
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -90,8 +90,8 @@ module.exports = {
|
||||||
lineNumber,
|
lineNumber,
|
||||||
length,
|
length,
|
||||||
line.length,
|
line.length,
|
||||||
null,
|
undefined,
|
||||||
null,
|
undefined,
|
||||||
[ length + 1, line.length - length ]);
|
[ length + 1, line.length - length ]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -27,8 +27,8 @@ module.exports = {
|
||||||
onError,
|
onError,
|
||||||
lineNumber,
|
lineNumber,
|
||||||
line.trim(),
|
line.trim(),
|
||||||
null,
|
undefined,
|
||||||
null,
|
undefined,
|
||||||
[ 1, hashLength + spacesLength + 1 ],
|
[ 1, hashLength + spacesLength + 1 ],
|
||||||
{
|
{
|
||||||
"editColumn": hashLength + 1,
|
"editColumn": hashLength + 1,
|
||||||
|
|
|
@ -12,12 +12,13 @@
|
||||||
|
|
||||||
## Heading 7 {MD021} ##
|
## Heading 7 {MD021} ##
|
||||||
|
|
||||||
## Heading 8 {MD003}\#
|
## Heading 8\#
|
||||||
|
|
||||||
## Heading 9 {MD003} \#
|
## Heading 9 \#
|
||||||
|
|
||||||
## Heading 10 {MD003} \#
|
## Heading 10 \#
|
||||||
|
|
||||||
<!-- markdownlint-configure-file {
|
<!-- markdownlint-configure-file {
|
||||||
"first-line-heading": false
|
"first-line-heading": false,
|
||||||
|
"heading-style": false
|
||||||
} -->
|
} -->
|
||||||
|
|
|
@ -34,4 +34,4 @@ Text
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<!-- markdownlint-disable-file MD013 MD033 -->
|
<!-- markdownlint-disable-file line-length no-inline-html -->
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
|
|
||||||
### Heading with trailing hash {MD003} ##
|
### Heading with trailing hash {MD003} ##
|
||||||
|
|
||||||
### Heading with trailing hash no space{MD003}{MD020}##
|
### Heading with trailing hash no space{MD020}##
|
||||||
|
|
||||||
### Heading with trailing hash {MD003}{MD020} \##
|
### Heading with trailing hash {MD020} \##
|
||||||
|
|
||||||
### Heading with trailing hash no space{MD003}{MD020}\##
|
### Heading with trailing hash no space{MD020}\##
|
||||||
|
|
|
@ -2786,45 +2786,6 @@ Generated by [AVA](https://avajs.dev).
|
||||||
|
|
||||||
{
|
{
|
||||||
errors: [
|
errors: [
|
||||||
{
|
|
||||||
errorContext: null,
|
|
||||||
errorDetail: 'Expected: atx_closed; Actual: atx',
|
|
||||||
errorRange: null,
|
|
||||||
fixInfo: null,
|
|
||||||
lineNumber: 15,
|
|
||||||
ruleDescription: 'Heading style',
|
|
||||||
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md003.md',
|
|
||||||
ruleNames: [
|
|
||||||
'MD003',
|
|
||||||
'heading-style',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
errorContext: null,
|
|
||||||
errorDetail: 'Expected: atx_closed; Actual: atx',
|
|
||||||
errorRange: null,
|
|
||||||
fixInfo: null,
|
|
||||||
lineNumber: 17,
|
|
||||||
ruleDescription: 'Heading style',
|
|
||||||
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md003.md',
|
|
||||||
ruleNames: [
|
|
||||||
'MD003',
|
|
||||||
'heading-style',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
errorContext: null,
|
|
||||||
errorDetail: 'Expected: atx_closed; Actual: atx',
|
|
||||||
errorRange: null,
|
|
||||||
fixInfo: null,
|
|
||||||
lineNumber: 19,
|
|
||||||
ruleDescription: 'Heading style',
|
|
||||||
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md003.md',
|
|
||||||
ruleNames: [
|
|
||||||
'MD003',
|
|
||||||
'heading-style',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
errorContext: '#Heading 1 {MD020} #',
|
errorContext: '#Heading 1 {MD020} #',
|
||||||
errorDetail: null,
|
errorDetail: null,
|
||||||
|
@ -2980,14 +2941,15 @@ Generated by [AVA](https://avajs.dev).
|
||||||
␊
|
␊
|
||||||
## Heading 7 {MD021} ##␊
|
## Heading 7 {MD021} ##␊
|
||||||
␊
|
␊
|
||||||
## Heading 8 {MD003}\\#␊
|
## Heading 8\\#␊
|
||||||
␊
|
␊
|
||||||
## Heading 9 {MD003} \\#␊
|
## Heading 9 \\#␊
|
||||||
␊
|
␊
|
||||||
## Heading 10 {MD003} \\#␊
|
## Heading 10 \\#␊
|
||||||
␊
|
␊
|
||||||
<!-- markdownlint-configure-file {␊
|
<!-- markdownlint-configure-file {␊
|
||||||
"first-line-heading": false␊
|
"first-line-heading": false,␊
|
||||||
|
"heading-style": false␊
|
||||||
} -->␊
|
} -->␊
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
@ -38202,7 +38164,7 @@ Generated by [AVA](https://avajs.dev).
|
||||||
␊
|
␊
|
||||||
</p>␊
|
</p>␊
|
||||||
␊
|
␊
|
||||||
<!-- markdownlint-disable-file MD013 MD033 -->␊
|
<!-- markdownlint-disable-file line-length no-inline-html -->␊
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38250,55 +38212,16 @@ Generated by [AVA](https://avajs.dev).
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
errorContext: null,
|
errorContext: '...railing hash no space{MD020}##',
|
||||||
errorDetail: 'Expected: atx; Actual: atx_closed',
|
|
||||||
errorRange: null,
|
|
||||||
fixInfo: null,
|
|
||||||
lineNumber: 17,
|
|
||||||
ruleDescription: 'Heading style',
|
|
||||||
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md003.md',
|
|
||||||
ruleNames: [
|
|
||||||
'MD003',
|
|
||||||
'heading-style',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
errorContext: null,
|
|
||||||
errorDetail: 'Expected: atx; Actual: atx_closed',
|
|
||||||
errorRange: null,
|
|
||||||
fixInfo: null,
|
|
||||||
lineNumber: 19,
|
|
||||||
ruleDescription: 'Heading style',
|
|
||||||
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md003.md',
|
|
||||||
ruleNames: [
|
|
||||||
'MD003',
|
|
||||||
'heading-style',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
errorContext: null,
|
|
||||||
errorDetail: 'Expected: atx; Actual: atx_closed',
|
|
||||||
errorRange: null,
|
|
||||||
fixInfo: null,
|
|
||||||
lineNumber: 21,
|
|
||||||
ruleDescription: 'Heading style',
|
|
||||||
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md003.md',
|
|
||||||
ruleNames: [
|
|
||||||
'MD003',
|
|
||||||
'heading-style',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
errorContext: '... hash no space{MD003}{MD020}##',
|
|
||||||
errorDetail: null,
|
errorDetail: null,
|
||||||
errorRange: [
|
errorRange: [
|
||||||
53,
|
46,
|
||||||
3,
|
3,
|
||||||
],
|
],
|
||||||
fixInfo: {
|
fixInfo: {
|
||||||
deleteCount: 55,
|
deleteCount: 48,
|
||||||
editColumn: 1,
|
editColumn: 1,
|
||||||
insertText: '### Heading with trailing hash no space{MD003}{MD020} ##',
|
insertText: '### Heading with trailing hash no space{MD020} ##',
|
||||||
},
|
},
|
||||||
lineNumber: 17,
|
lineNumber: 17,
|
||||||
ruleDescription: 'No space inside hashes on closed atx style heading',
|
ruleDescription: 'No space inside hashes on closed atx style heading',
|
||||||
|
@ -38309,7 +38232,27 @@ Generated by [AVA](https://avajs.dev).
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
errorContext: '...ailing hash {MD003}{MD020} \\##',
|
errorContext: '...with trailing hash {MD020} \\##',
|
||||||
|
errorDetail: null,
|
||||||
|
errorRange: [
|
||||||
|
41,
|
||||||
|
2,
|
||||||
|
],
|
||||||
|
fixInfo: {
|
||||||
|
deleteCount: 42,
|
||||||
|
editColumn: 1,
|
||||||
|
insertText: '### Heading with trailing hash {MD020} \\# #',
|
||||||
|
},
|
||||||
|
lineNumber: 19,
|
||||||
|
ruleDescription: 'No space inside hashes on closed atx style heading',
|
||||||
|
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md020.md',
|
||||||
|
ruleNames: [
|
||||||
|
'MD020',
|
||||||
|
'no-missing-space-closed-atx',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errorContext: '...ailing hash no space{MD020}\\##',
|
||||||
errorDetail: null,
|
errorDetail: null,
|
||||||
errorRange: [
|
errorRange: [
|
||||||
48,
|
48,
|
||||||
|
@ -38318,27 +38261,7 @@ Generated by [AVA](https://avajs.dev).
|
||||||
fixInfo: {
|
fixInfo: {
|
||||||
deleteCount: 49,
|
deleteCount: 49,
|
||||||
editColumn: 1,
|
editColumn: 1,
|
||||||
insertText: '### Heading with trailing hash {MD003}{MD020} \\# #',
|
insertText: '### Heading with trailing hash no space{MD020} \\# #',
|
||||||
},
|
|
||||||
lineNumber: 19,
|
|
||||||
ruleDescription: 'No space inside hashes on closed atx style heading',
|
|
||||||
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md020.md',
|
|
||||||
ruleNames: [
|
|
||||||
'MD020',
|
|
||||||
'no-missing-space-closed-atx',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
errorContext: '...hash no space{MD003}{MD020}\\##',
|
|
||||||
errorDetail: null,
|
|
||||||
errorRange: [
|
|
||||||
55,
|
|
||||||
2,
|
|
||||||
],
|
|
||||||
fixInfo: {
|
|
||||||
deleteCount: 56,
|
|
||||||
editColumn: 1,
|
|
||||||
insertText: '### Heading with trailing hash no space{MD003}{MD020} \\# #',
|
|
||||||
},
|
},
|
||||||
lineNumber: 21,
|
lineNumber: 21,
|
||||||
ruleDescription: 'No space inside hashes on closed atx style heading',
|
ruleDescription: 'No space inside hashes on closed atx style heading',
|
||||||
|
@ -38365,11 +38288,11 @@ Generated by [AVA](https://avajs.dev).
|
||||||
␊
|
␊
|
||||||
### Heading with trailing hash {MD003} ##␊
|
### Heading with trailing hash {MD003} ##␊
|
||||||
␊
|
␊
|
||||||
### Heading with trailing hash no space{MD003}{MD020} ##␊
|
### Heading with trailing hash no space{MD020} ##␊
|
||||||
␊
|
␊
|
||||||
### Heading with trailing hash {MD003}{MD020} \\# #␊
|
### Heading with trailing hash {MD020} \\# #␊
|
||||||
␊
|
␊
|
||||||
### Heading with trailing hash no space{MD003}{MD020} \\# #␊
|
### Heading with trailing hash no space{MD020} \\# #␊
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue