diff --git a/demo/markdownlint-browser.js b/demo/markdownlint-browser.js index c9579628..7d017db1 100644 --- a/demo/markdownlint-browser.js +++ b/demo/markdownlint-browser.js @@ -1539,6 +1539,26 @@ function getHeadingLevel(heading) { 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. * @@ -1663,6 +1683,7 @@ module.exports = { filterByPredicate, filterByTypes, getHeadingLevel, + getHeadingStyle, getHtmlTagInfo, getMicromarkEvents, getTokenParentOfType, @@ -3352,8 +3373,9 @@ module.exports = { -const { addErrorDetailIf, filterTokens, headingStyleFor } = - __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); +const { addErrorDetailIf } = __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 /** @type import("./markdownlint").Rule */ @@ -3361,16 +3383,20 @@ module.exports = { "names": [ "MD003", "heading-style" ], "description": "Heading style", "tags": [ "headings" ], - "parser": "markdownit", + "parser": "micromark", "function": function MD003(params, onError) { let style = String(params.config.style || "consistent"); - filterTokens(params, "heading_open", function forToken(token) { - const styleForToken = headingStyleFor(token); + const headings = filterByTypes( + params.parsers.micromark.tokens, + [ "atxHeading", "setextHeading" ] + ); + for (const heading of headings) { + const styleForToken = getHeadingStyle(heading); if (style === "consistent") { style = styleForToken; } - if (styleForToken !== style) { - const h12 = /h[12]/.test(token.tag); + if ((styleForToken !== style) && !inHtmlFlow(heading)) { + const h12 = getHeadingLevel(heading) <= 2; const setextWithAtx = (style === "setext_with_atx") && ((h12 && (styleForToken === "setext")) || @@ -3386,11 +3412,15 @@ module.exports = { } else if (style === "setext_with_atx_closed") { expected = h12 ? "setext" : "atx_closed"; } - addErrorDetailIf(onError, token.lineNumber, - expected, styleForToken); + addErrorDetailIf( + onError, + heading.startLine, + expected, + styleForToken + ); } } - }); + } } }; @@ -4061,8 +4091,8 @@ module.exports = { lineNumber, length, line.length, - null, - null, + undefined, + undefined, [ length + 1, line.length - length ]); } }); @@ -4226,8 +4256,8 @@ module.exports = { onError, lineNumber, line.trim(), - null, - null, + undefined, + undefined, [ 1, hashLength + spacesLength + 1 ], { "editColumn": hashLength + 1, diff --git a/helpers/micromark.cjs b/helpers/micromark.cjs index 9fa49204..8f30d693 100644 --- a/helpers/micromark.cjs +++ b/helpers/micromark.cjs @@ -309,6 +309,26 @@ function getHeadingLevel(heading) { 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. * @@ -433,6 +453,7 @@ module.exports = { filterByPredicate, filterByTypes, getHeadingLevel, + getHeadingStyle, getHtmlTagInfo, getMicromarkEvents, getTokenParentOfType, diff --git a/lib/md003.js b/lib/md003.js index 7ce3a319..d0a8c6fb 100644 --- a/lib/md003.js +++ b/lib/md003.js @@ -2,8 +2,9 @@ "use strict"; -const { addErrorDetailIf, filterTokens, headingStyleFor } = - require("../helpers"); +const { addErrorDetailIf } = require("../helpers"); +const { filterByTypes, getHeadingLevel, getHeadingStyle, inHtmlFlow } = + require("../helpers/micromark.cjs"); // eslint-disable-next-line jsdoc/valid-types /** @type import("./markdownlint").Rule */ @@ -11,16 +12,20 @@ module.exports = { "names": [ "MD003", "heading-style" ], "description": "Heading style", "tags": [ "headings" ], - "parser": "markdownit", + "parser": "micromark", "function": function MD003(params, onError) { let style = String(params.config.style || "consistent"); - filterTokens(params, "heading_open", function forToken(token) { - const styleForToken = headingStyleFor(token); + const headings = filterByTypes( + params.parsers.micromark.tokens, + [ "atxHeading", "setextHeading" ] + ); + for (const heading of headings) { + const styleForToken = getHeadingStyle(heading); if (style === "consistent") { style = styleForToken; } - if (styleForToken !== style) { - const h12 = /h[12]/.test(token.tag); + if ((styleForToken !== style) && !inHtmlFlow(heading)) { + const h12 = getHeadingLevel(heading) <= 2; const setextWithAtx = (style === "setext_with_atx") && ((h12 && (styleForToken === "setext")) || @@ -36,10 +41,14 @@ module.exports = { } else if (style === "setext_with_atx_closed") { expected = h12 ? "setext" : "atx_closed"; } - addErrorDetailIf(onError, token.lineNumber, - expected, styleForToken); + addErrorDetailIf( + onError, + heading.startLine, + expected, + styleForToken + ); } } - }); + } } }; diff --git a/lib/md013.js b/lib/md013.js index 59c7170b..877325c9 100644 --- a/lib/md013.js +++ b/lib/md013.js @@ -90,8 +90,8 @@ module.exports = { lineNumber, length, line.length, - null, - null, + undefined, + undefined, [ length + 1, line.length - length ]); } }); diff --git a/lib/md019.js b/lib/md019.js index ea7c9ea7..a1d73e21 100644 --- a/lib/md019.js +++ b/lib/md019.js @@ -27,8 +27,8 @@ module.exports = { onError, lineNumber, line.trim(), - null, - null, + undefined, + undefined, [ 1, hashLength + spacesLength + 1 ], { "editColumn": hashLength + 1, diff --git a/test/atx_closed_heading_spacing.md b/test/atx_closed_heading_spacing.md index e7b1c55b..fbc885a5 100644 --- a/test/atx_closed_heading_spacing.md +++ b/test/atx_closed_heading_spacing.md @@ -12,12 +12,13 @@ ## Heading 7 {MD021} ## -## Heading 8 {MD003}\# +## Heading 8\# -## Heading 9 {MD003} \# +## Heading 9 \# -## Heading 10 {MD003} \# +## Heading 10 \# diff --git a/test/markdown-in-html.md b/test/markdown-in-html.md index 6274b507..4f3591d6 100644 --- a/test/markdown-in-html.md +++ b/test/markdown-in-html.md @@ -34,4 +34,4 @@ Text

- + diff --git a/test/md003-escaped-trailing-hash.md b/test/md003-escaped-trailing-hash.md index 78c97998..1548133c 100644 --- a/test/md003-escaped-trailing-hash.md +++ b/test/md003-escaped-trailing-hash.md @@ -14,8 +14,8 @@ ### 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}\## diff --git a/test/snapshots/markdownlint-test-scenarios.js.md b/test/snapshots/markdownlint-test-scenarios.js.md index d86d6331..e7ba926d 100644 --- a/test/snapshots/markdownlint-test-scenarios.js.md +++ b/test/snapshots/markdownlint-test-scenarios.js.md @@ -2786,45 +2786,6 @@ Generated by [AVA](https://avajs.dev). { 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} #', errorDetail: null, @@ -2980,14 +2941,15 @@ Generated by [AVA](https://avajs.dev). ␊ ## Heading 7 {MD021} ##␊ ␊ - ## Heading 8 {MD003}\\#␊ + ## Heading 8\\#␊ ␊ - ## Heading 9 {MD003} \\#␊ + ## Heading 9 \\#␊ ␊ - ## Heading 10 {MD003} \\#␊ + ## Heading 10 \\#␊ ␊ ␊ `, } @@ -38202,7 +38164,7 @@ Generated by [AVA](https://avajs.dev). ␊

␊ ␊ - ␊ + ␊ `, } @@ -38250,55 +38212,16 @@ Generated by [AVA](https://avajs.dev). ], }, { - errorContext: null, - 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}##', + errorContext: '...railing hash no space{MD020}##', errorDetail: null, errorRange: [ - 53, + 46, 3, ], fixInfo: { - deleteCount: 55, + deleteCount: 48, editColumn: 1, - insertText: '### Heading with trailing hash no space{MD003}{MD020} ##', + insertText: '### Heading with trailing hash no space{MD020} ##', }, lineNumber: 17, 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, errorRange: [ 48, @@ -38318,27 +38261,7 @@ Generated by [AVA](https://avajs.dev). fixInfo: { deleteCount: 49, editColumn: 1, - insertText: '### Heading with trailing hash {MD003}{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} \\# #', + insertText: '### Heading with trailing hash no space{MD020} \\# #', }, lineNumber: 21, 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 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} \\# #␊ `, } diff --git a/test/snapshots/markdownlint-test-scenarios.js.snap b/test/snapshots/markdownlint-test-scenarios.js.snap index 106e803c..5d3976bf 100644 Binary files a/test/snapshots/markdownlint-test-scenarios.js.snap and b/test/snapshots/markdownlint-test-scenarios.js.snap differ