diff --git a/demo/markdownlint-browser.js b/demo/markdownlint-browser.js index 9b170ee4..176f325c 100644 --- a/demo/markdownlint-browser.js +++ b/demo/markdownlint-browser.js @@ -4236,8 +4236,8 @@ module.exports = { -const { addErrorContext, filterTokens, headingStyleFor } = - __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); +const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); +const { filterByTypes, getHeadingStyle } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs"); // eslint-disable-next-line jsdoc/valid-types /** @type import("./markdownlint").Rule */ @@ -4245,33 +4245,35 @@ module.exports = { "names": [ "MD019", "no-multiple-space-atx" ], "description": "Multiple spaces after hash on atx style heading", "tags": [ "headings", "atx", "spaces" ], - "parser": "markdownit", + "parser": "micromark", "function": function MD019(params, onError) { - filterTokens(params, "heading_open", (token) => { - if (headingStyleFor(token) === "atx") { - const { line, lineNumber } = token; - const match = /^(#+)([ \t]{2,})\S/.exec(line); - if (match) { - const [ - , - { "length": hashLength }, - { "length": spacesLength } - ] = match; - addErrorContext( - onError, - lineNumber, - line.trim(), - undefined, - undefined, - [ 1, hashLength + spacesLength + 1 ], - { - "editColumn": hashLength + 1, - "deleteCount": spacesLength - 1 - } - ); - } + const atxHeadings = filterByTypes( + params.parsers.micromark.tokens, + [ "atxHeading" ] + ).filter((heading) => getHeadingStyle(heading) === "atx"); + for (const atxHeading of atxHeadings) { + const [ atxHeadingSequence, whitespace ] = atxHeading.children; + if ( + (atxHeadingSequence?.type === "atxHeadingSequence") && + (whitespace?.type === "whitespace") && + (whitespace.text.length > 1) + ) { + const column = whitespace.startColumn + 1; + const length = whitespace.endColumn - column; + addErrorContext( + onError, + atxHeading.startLine, + atxHeading.text.trim(), + undefined, + undefined, + [ column, length ], + { + "editColumn": column, + "deleteCount": length + } + ); } - }); + } } }; diff --git a/lib/md019.js b/lib/md019.js index a1d73e21..9ad6517c 100644 --- a/lib/md019.js +++ b/lib/md019.js @@ -2,8 +2,8 @@ "use strict"; -const { addErrorContext, filterTokens, headingStyleFor } = - require("../helpers"); +const { addErrorContext } = require("../helpers"); +const { filterByTypes, getHeadingStyle } = require("../helpers/micromark.cjs"); // eslint-disable-next-line jsdoc/valid-types /** @type import("./markdownlint").Rule */ @@ -11,32 +11,34 @@ module.exports = { "names": [ "MD019", "no-multiple-space-atx" ], "description": "Multiple spaces after hash on atx style heading", "tags": [ "headings", "atx", "spaces" ], - "parser": "markdownit", + "parser": "micromark", "function": function MD019(params, onError) { - filterTokens(params, "heading_open", (token) => { - if (headingStyleFor(token) === "atx") { - const { line, lineNumber } = token; - const match = /^(#+)([ \t]{2,})\S/.exec(line); - if (match) { - const [ - , - { "length": hashLength }, - { "length": spacesLength } - ] = match; - addErrorContext( - onError, - lineNumber, - line.trim(), - undefined, - undefined, - [ 1, hashLength + spacesLength + 1 ], - { - "editColumn": hashLength + 1, - "deleteCount": spacesLength - 1 - } - ); - } + const atxHeadings = filterByTypes( + params.parsers.micromark.tokens, + [ "atxHeading" ] + ).filter((heading) => getHeadingStyle(heading) === "atx"); + for (const atxHeading of atxHeadings) { + const [ atxHeadingSequence, whitespace ] = atxHeading.children; + if ( + (atxHeadingSequence?.type === "atxHeadingSequence") && + (whitespace?.type === "whitespace") && + (whitespace.text.length > 1) + ) { + const column = whitespace.startColumn + 1; + const length = whitespace.endColumn - column; + addErrorContext( + onError, + atxHeading.startLine, + atxHeading.text.trim(), + undefined, + undefined, + [ column, length ], + { + "editColumn": column, + "deleteCount": length + } + ); } - }); + } } }; diff --git a/test/headings-without-content.md b/test/headings-without-content.md index 0bc6e3e4..e9d3eaa5 100644 --- a/test/headings-without-content.md +++ b/test/headings-without-content.md @@ -18,3 +18,5 @@ ## ## + +{MD019:10} {MD019:12} {MD019:18} {MD019:20} diff --git a/test/markdownlint-test-result-object.js b/test/markdownlint-test-result-object.js index 675df4c2..321d51ee 100644 --- a/test/markdownlint-test-result-object.js +++ b/test/markdownlint-test-result-object.js @@ -186,7 +186,7 @@ test("resultFormattingV1", (t) => new Promise((resolve) => { "ruleInformation": `${homepage}/blob/v${version}/doc/md019.md`, "errorDetail": null, "errorContext": "## Heading 2 {MD019}", - "errorRange": [ 1, 5 ] }, + "errorRange": [ 4, 1 ] }, { "lineNumber": 5, "ruleName": "MD019", "ruleAlias": "no-multiple-space-atx", @@ -194,7 +194,7 @@ test("resultFormattingV1", (t) => new Promise((resolve) => { "ruleInformation": `${homepage}/blob/v${version}/doc/md019.md`, "errorDetail": null, "errorContext": "## Heading 3 {MD019}", - "errorRange": [ 1, 6 ] }, + "errorRange": [ 4, 2 ] }, { "lineNumber": 1, "ruleName": "MD041", "ruleAlias": "first-line-heading", @@ -287,14 +287,14 @@ test("resultFormattingV2", (t) => new Promise((resolve) => { "ruleInformation": `${homepage}/blob/v${version}/doc/md019.md`, "errorDetail": null, "errorContext": "## Heading 2 {MD019}", - "errorRange": [ 1, 5 ] }, + "errorRange": [ 4, 1 ] }, { "lineNumber": 5, "ruleNames": [ "MD019", "no-multiple-space-atx" ], "ruleDescription": "Multiple spaces after hash on atx style heading", "ruleInformation": `${homepage}/blob/v${version}/doc/md019.md`, "errorDetail": null, "errorContext": "## Heading 3 {MD019}", - "errorRange": [ 1, 6 ] }, + "errorRange": [ 4, 2 ] }, { "lineNumber": 1, "ruleNames": [ "MD041", "first-line-heading", "first-line-h1" ], "ruleDescription": "First line in a file should be a top-level heading", diff --git a/test/snapshots/markdownlint-test-scenarios.js.md b/test/snapshots/markdownlint-test-scenarios.js.md index caca2e0a..e9ff763b 100644 --- a/test/snapshots/markdownlint-test-scenarios.js.md +++ b/test/snapshots/markdownlint-test-scenarios.js.md @@ -465,12 +465,12 @@ Generated by [AVA](https://avajs.dev). errorContext: '## Multiple spaces B {MD019}', errorDetail: null, errorRange: [ + 4, 1, - 5, ], fixInfo: { deleteCount: 1, - editColumn: 3, + editColumn: 4, }, lineNumber: 16, ruleDescription: 'Multiple spaces after hash on atx style heading', @@ -2622,12 +2622,12 @@ Generated by [AVA](https://avajs.dev). errorContext: '## Heading 2 {MD019}', errorDetail: null, errorRange: [ - 1, - 7, + 4, + 3, ], fixInfo: { deleteCount: 3, - editColumn: 3, + editColumn: 4, }, lineNumber: 7, ruleDescription: 'Multiple spaces after hash on atx style heading', @@ -2983,12 +2983,12 @@ Generated by [AVA](https://avajs.dev). errorContext: '## Heading 2 {MD019}', errorDetail: null, errorRange: [ + 4, 1, - 5, ], fixInfo: { deleteCount: 1, - editColumn: 3, + editColumn: 4, }, lineNumber: 3, ruleDescription: 'Multiple spaces after hash on atx style heading', @@ -3002,12 +3002,12 @@ Generated by [AVA](https://avajs.dev). errorContext: '## Heading 3 {MD019}', errorDetail: null, errorRange: [ - 1, - 6, + 4, + 2, ], fixInfo: { deleteCount: 2, - editColumn: 3, + editColumn: 4, }, lineNumber: 5, ruleDescription: 'Multiple spaces after hash on atx style heading', @@ -6999,12 +6999,12 @@ Generated by [AVA](https://avajs.dev). errorContext: '# Heading 5 {MD019}', errorDetail: null, errorRange: [ + 3, 1, - 4, ], fixInfo: { deleteCount: 1, - editColumn: 2, + editColumn: 3, }, lineNumber: 27, ruleDescription: 'Multiple spaces after hash on atx style heading', @@ -15812,12 +15812,12 @@ Generated by [AVA](https://avajs.dev). errorContext: '## Extra normal space {MD019}', errorDetail: null, errorRange: [ + 4, 1, - 5, ], fixInfo: { deleteCount: 1, - editColumn: 3, + editColumn: 4, }, lineNumber: 23, ruleDescription: 'Multiple spaces after hash on atx style heading', @@ -15831,12 +15831,12 @@ Generated by [AVA](https://avajs.dev). errorContext: '## Extra Tab {MD019}', errorDetail: null, errorRange: [ + 4, 1, - 5, ], fixInfo: { deleteCount: 1, - editColumn: 3, + editColumn: 4, }, lineNumber: 27, ruleDescription: 'Multiple spaces after hash on atx style heading', @@ -16037,7 +16037,84 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 { - errors: [], + errors: [ + { + errorContext: '#', + errorDetail: null, + errorRange: [ + 3, + 1, + ], + fixInfo: { + deleteCount: 1, + editColumn: 3, + }, + lineNumber: 10, + ruleDescription: 'Multiple spaces after hash on atx style heading', + ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md019.md', + ruleNames: [ + 'MD019', + 'no-multiple-space-atx', + ], + }, + { + errorContext: '#', + errorDetail: null, + errorRange: [ + 3, + 2, + ], + fixInfo: { + deleteCount: 2, + editColumn: 3, + }, + lineNumber: 12, + ruleDescription: 'Multiple spaces after hash on atx style heading', + ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md019.md', + ruleNames: [ + 'MD019', + 'no-multiple-space-atx', + ], + }, + { + errorContext: '##', + errorDetail: null, + errorRange: [ + 4, + 1, + ], + fixInfo: { + deleteCount: 1, + editColumn: 4, + }, + lineNumber: 18, + ruleDescription: 'Multiple spaces after hash on atx style heading', + ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md019.md', + ruleNames: [ + 'MD019', + 'no-multiple-space-atx', + ], + }, + { + errorContext: '##', + errorDetail: null, + errorRange: [ + 4, + 2, + ], + fixInfo: { + deleteCount: 2, + editColumn: 4, + }, + lineNumber: 20, + ruleDescription: 'Multiple spaces after hash on atx style heading', + ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md019.md', + ruleNames: [ + 'MD019', + 'no-multiple-space-atx', + ], + }, + ], fixed: `# Headings Without Content␊ ␊ ␊ @@ -16047,17 +16124,19 @@ Generated by [AVA](https://avajs.dev). ␊ # ␊ ␊ - # ␊ + # ␊ ␊ - # ␊ + # ␊ ␊ ##␊ ␊ ## ␊ ␊ - ## ␊ + ## ␊ ␊ - ## ␊ + ## ␊ + ␊ + {MD019:10} {MD019:12} {MD019:18} {MD019:20}␊ `, } @@ -37916,12 +37995,12 @@ Generated by [AVA](https://avajs.dev). errorContext: '## Heading 2b {MD019} {MD022}', errorDetail: null, errorRange: [ + 4, 1, - 5, ], fixInfo: { deleteCount: 1, - editColumn: 3, + editColumn: 4, }, lineNumber: 24, ruleDescription: 'Multiple spaces after hash on atx style heading', @@ -46613,12 +46692,12 @@ Generated by [AVA](https://avajs.dev). errorContext: '# C', errorDetail: null, errorRange: [ + 3, 1, - 4, ], fixInfo: { deleteCount: 1, - editColumn: 2, + editColumn: 3, }, lineNumber: 11, ruleDescription: 'Multiple spaces after hash on atx style heading', @@ -46632,12 +46711,12 @@ Generated by [AVA](https://avajs.dev). errorContext: '## I', errorDetail: null, errorRange: [ + 4, 1, - 5, ], fixInfo: { deleteCount: 1, - editColumn: 3, + editColumn: 4, }, lineNumber: 31, ruleDescription: 'Multiple spaces after hash on atx style heading', @@ -46651,12 +46730,12 @@ Generated by [AVA](https://avajs.dev). errorContext: '# OO', errorDetail: null, errorRange: [ + 3, 1, - 4, ], fixInfo: { deleteCount: 1, - editColumn: 2, + editColumn: 3, }, lineNumber: 51, ruleDescription: 'Multiple spaces after hash on atx style heading', @@ -46670,12 +46749,12 @@ Generated by [AVA](https://avajs.dev). errorContext: '## UU', errorDetail: null, errorRange: [ + 4, 1, - 5, ], fixInfo: { deleteCount: 1, - editColumn: 3, + editColumn: 4, }, lineNumber: 71, ruleDescription: 'Multiple spaces after hash on atx style heading', diff --git a/test/snapshots/markdownlint-test-scenarios.js.snap b/test/snapshots/markdownlint-test-scenarios.js.snap index e7020180..931e91ba 100644 Binary files a/test/snapshots/markdownlint-test-scenarios.js.snap and b/test/snapshots/markdownlint-test-scenarios.js.snap differ