diff --git a/demo/markdownlint-browser.js b/demo/markdownlint-browser.js index 759146ff..0a5c8d02 100644 --- a/demo/markdownlint-browser.js +++ b/demo/markdownlint-browser.js @@ -4177,25 +4177,33 @@ module.exports = { var startLine = heading.startLine, endLine = heading.endLine; var line = lines[startLine - 1].trim(); - var actualAbove = 0; - for (var i = 0; i < linesAbove; i++) { - if (isBlankLine(lines[startLine - 2 - i])) { - actualAbove++; + + // Check lines above + if (linesAbove >= 0) { + var actualAbove = 0; + for (var i = 0; i < linesAbove; i++) { + if (isBlankLine(lines[startLine - 2 - i])) { + actualAbove++; + } } + addErrorDetailIf(onError, startLine, linesAbove, actualAbove, "Above", line, null, { + "insertText": getBlockQuote(lines[startLine - 2], linesAbove - actualAbove) + }); } - addErrorDetailIf(onError, startLine, linesAbove, actualAbove, "Above", line, null, { - "insertText": getBlockQuote(lines[startLine - 2], linesAbove - actualAbove) - }); - var actualBelow = 0; - for (var _i = 0; _i < linesBelow; _i++) { - if (isBlankLine(lines[endLine + _i])) { - actualBelow++; + + // Check lines below + if (linesBelow >= 0) { + var actualBelow = 0; + for (var _i = 0; _i < linesBelow; _i++) { + if (isBlankLine(lines[endLine + _i])) { + actualBelow++; + } } + addErrorDetailIf(onError, startLine, linesBelow, actualBelow, "Below", line, null, { + "lineNumber": endLine + 1, + "insertText": getBlockQuote(lines[endLine], linesBelow - actualBelow) + }); } - addErrorDetailIf(onError, startLine, linesBelow, actualBelow, "Below", line, null, { - "lineNumber": endLine + 1, - "insertText": getBlockQuote(lines[endLine], linesBelow - actualBelow) - }); } } catch (err) { _iterator.e(err); diff --git a/doc-build/md022.md b/doc-build/md022.md index 70fe0f5a..8366073e 100644 --- a/doc-build/md022.md +++ b/doc-build/md022.md @@ -23,7 +23,9 @@ Some more text ``` The `lines_above` and `lines_below` parameters can be used to specify a -different number of blank lines (including 0) above or below each heading. +different number of blank lines (including `0`) above or below each heading. If +the value `-1` is used for either parameter, any number of blank lines is +allowed. Note: If `lines_above` or `lines_below` are configured to require more than one blank line, [MD012/no-multiple-blanks](md012.md) should also be customized. diff --git a/doc/Rules.md b/doc/Rules.md index 185646c3..346ebbcd 100644 --- a/doc/Rules.md +++ b/doc/Rules.md @@ -836,7 +836,9 @@ Some more text ``` The `lines_above` and `lines_below` parameters can be used to specify a -different number of blank lines (including 0) above or below each heading. +different number of blank lines (including `0`) above or below each heading. If +the value `-1` is used for either parameter, any number of blank lines is +allowed. Note: If `lines_above` or `lines_below` are configured to require more than one blank line, [MD012/no-multiple-blanks](md012.md) should also be customized. diff --git a/doc/md022.md b/doc/md022.md index af0df57f..b3b4f5af 100644 --- a/doc/md022.md +++ b/doc/md022.md @@ -36,7 +36,9 @@ Some more text ``` The `lines_above` and `lines_below` parameters can be used to specify a -different number of blank lines (including 0) above or below each heading. +different number of blank lines (including `0`) above or below each heading. If +the value `-1` is used for either parameter, any number of blank lines is +allowed. Note: If `lines_above` or `lines_below` are configured to require more than one blank line, [MD012/no-multiple-blanks](md012.md) should also be customized. diff --git a/lib/md022.js b/lib/md022.js index 348e3416..88df9f2e 100644 --- a/lib/md022.js +++ b/lib/md022.js @@ -32,45 +32,53 @@ module.exports = { for (const heading of headings) { const { startLine, endLine } = heading; const line = lines[startLine - 1].trim(); - let actualAbove = 0; - for (let i = 0; i < linesAbove; i++) { - if (isBlankLine(lines[startLine - 2 - i])) { - actualAbove++; + + // Check lines above + if (linesAbove >= 0) { + let actualAbove = 0; + for (let i = 0; i < linesAbove; i++) { + if (isBlankLine(lines[startLine - 2 - i])) { + actualAbove++; + } } + addErrorDetailIf( + onError, + startLine, + linesAbove, + actualAbove, + "Above", + line, + null, + { + "insertText": + getBlockQuote(lines[startLine - 2], linesAbove - actualAbove) + } + ); } - addErrorDetailIf( - onError, - startLine, - linesAbove, - actualAbove, - "Above", - line, - null, - { - "insertText": - getBlockQuote(lines[startLine - 2], linesAbove - actualAbove) - } - ); - let actualBelow = 0; - for (let i = 0; i < linesBelow; i++) { - if (isBlankLine(lines[endLine + i])) { - actualBelow++; + + // Check lines below + if (linesBelow >= 0) { + let actualBelow = 0; + for (let i = 0; i < linesBelow; i++) { + if (isBlankLine(lines[endLine + i])) { + actualBelow++; + } } + addErrorDetailIf( + onError, + startLine, + linesBelow, + actualBelow, + "Below", + line, + null, + { + "lineNumber": endLine + 1, + "insertText": + getBlockQuote(lines[endLine], linesBelow - actualBelow) + } + ); } - addErrorDetailIf( - onError, - startLine, - linesBelow, - actualBelow, - "Below", - line, - null, - { - "lineNumber": endLine + 1, - "insertText": - getBlockQuote(lines[endLine], linesBelow - actualBelow) - } - ); } } }; diff --git a/schema/build-config-schema.js b/schema/build-config-schema.js index 8fe0b034..eae6ef5a 100644 --- a/schema/build-config-schema.js +++ b/schema/build-config-schema.js @@ -230,13 +230,13 @@ for (const rule of rules) { "lines_above": { "description": "Blank lines above heading", "type": "integer", - "minimum": 0, + "minimum": -1, "default": 1 }, "lines_below": { "description": "Blank lines below heading", "type": "integer", - "minimum": 0, + "minimum": -1, "default": 1 } }; diff --git a/schema/markdownlint-config-schema.json b/schema/markdownlint-config-schema.json index b6214254..ef14d1f9 100644 --- a/schema/markdownlint-config-schema.json +++ b/schema/markdownlint-config-schema.json @@ -362,13 +362,13 @@ "lines_above": { "description": "Blank lines above heading", "type": "integer", - "minimum": 0, + "minimum": -1, "default": 1 }, "lines_below": { "description": "Blank lines below heading", "type": "integer", - "minimum": 0, + "minimum": -1, "default": 1 } }, diff --git a/test/blanks-around-headings--1-1.md b/test/blanks-around-headings--1-1.md new file mode 100644 index 00000000..049d408d --- /dev/null +++ b/test/blanks-around-headings--1-1.md @@ -0,0 +1,33 @@ +# Blanks Around Headings + +## Apple + +Text +## Banana + +Text + +## Cherry + +Text + + +## Durian ## + +Text + +Elderberry {MD022} +------------------ +Text + +--- +## Fig + + diff --git a/test/blanks-around-headings-1--1.md b/test/blanks-around-headings-1--1.md new file mode 100644 index 00000000..0d5ce864 --- /dev/null +++ b/test/blanks-around-headings-1--1.md @@ -0,0 +1,35 @@ +# Blanks Around Headings + +## Apple +Text + +## Banana + +Text + +## Cherry + + +Text + +--- +## Durian {MD022} ## + +Text + +--- + +Elderberry +------------------ +Text + +## Fig + + diff --git a/test/markdownlint-test.js b/test/markdownlint-test.js index 2b3d6f3d..a7a9dc81 100644 --- a/test/markdownlint-test.js +++ b/test/markdownlint-test.js @@ -919,7 +919,7 @@ test("readme", (t) => new Promise((resolve) => { })); test("validateJsonUsingConfigSchemaStrict", (t) => { - t.plan(156); + t.plan(158); const configRe = /^[\s\S]*[\s\S]*$/; const ignoreFiles = new Set([ diff --git a/test/snapshots/markdownlint-test-scenarios.js.md b/test/snapshots/markdownlint-test-scenarios.js.md index 9ac1dc6c..43218a16 100644 --- a/test/snapshots/markdownlint-test-scenarios.js.md +++ b/test/snapshots/markdownlint-test-scenarios.js.md @@ -4173,6 +4173,68 @@ Generated by [AVA](https://avajs.dev). `, } +## blanks-around-headings--1-1.md + +> Snapshot 1 + + { + errors: [ + { + errorContext: 'Elderberry {MD022}', + errorDetail: 'Expected: 1; Actual: 0; Below', + errorRange: null, + fixInfo: { + insertText: `␊ + `, + lineNumber: 21, + }, + lineNumber: 19, + ruleDescription: 'Headings should be surrounded by blank lines', + ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md022.md', + ruleNames: [ + 'MD022', + 'blanks-around-headings', + 'blanks-around-headers', + ], + }, + ], + fixed: `# Blanks Around Headings␊ + ␊ + ## Apple␊ + ␊ + Text␊ + ## Banana␊ + ␊ + Text␊ + ␊ + ## Cherry␊ + ␊ + Text␊ + ␊ + ␊ + ## Durian ##␊ + ␊ + Text␊ + ␊ + Elderberry {MD022}␊ + ------------------␊ + ␊ + Text␊ + ␊ + ---␊ + ## Fig␊ + ␊ + ␊ + `, + } + ## blanks-around-headings-0-2.md > Snapshot 1 @@ -4256,6 +4318,69 @@ Generated by [AVA](https://avajs.dev). `, } +## blanks-around-headings-1--1.md + +> Snapshot 1 + + { + errors: [ + { + errorContext: '## Durian {MD022} ##', + errorDetail: 'Expected: 1; Actual: 0; Above', + errorRange: null, + fixInfo: { + insertText: `␊ + `, + }, + lineNumber: 16, + ruleDescription: 'Headings should be surrounded by blank lines', + ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md022.md', + ruleNames: [ + 'MD022', + 'blanks-around-headings', + 'blanks-around-headers', + ], + }, + ], + fixed: `# Blanks Around Headings␊ + ␊ + ## Apple␊ + Text␊ + ␊ + ## Banana␊ + ␊ + Text␊ + ␊ + ## Cherry␊ + ␊ + ␊ + Text␊ + ␊ + ---␊ + ␊ + ## Durian {MD022} ##␊ + ␊ + Text␊ + ␊ + ---␊ + ␊ + Elderberry␊ + ------------------␊ + Text␊ + ␊ + ## Fig␊ + ␊ + ␊ + `, + } + ## blanks-around-headings-3-0.md > Snapshot 1 diff --git a/test/snapshots/markdownlint-test-scenarios.js.snap b/test/snapshots/markdownlint-test-scenarios.js.snap index 36494a1d..e943b577 100644 Binary files a/test/snapshots/markdownlint-test-scenarios.js.snap and b/test/snapshots/markdownlint-test-scenarios.js.snap differ