Skip to content

Commit

Permalink
Merge 2f55fc9 into 53977e0
Browse files Browse the repository at this point in the history
  • Loading branch information
ota-meshi committed Nov 18, 2021
2 parents 53977e0 + 2f55fc9 commit af6fdf1
Show file tree
Hide file tree
Showing 144 changed files with 1,229 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ The rules with the following star :star: are included in the config.
| [yml/flow-sequence-bracket-spacing](https://ota-meshi.github.io/eslint-plugin-yml/rules/flow-sequence-bracket-spacing.html) | enforce consistent spacing inside flow sequence brackets | :wrench: | | :star: |
| [yml/key-spacing](https://ota-meshi.github.io/eslint-plugin-yml/rules/key-spacing.html) | enforce consistent spacing between keys and values in mapping pairs | :wrench: | | :star: |
| [yml/no-irregular-whitespace](https://ota-meshi.github.io/eslint-plugin-yml/rules/no-irregular-whitespace.html) | disallow irregular whitespace | | :star: | :star: |
| [yml/no-multiple-empty-lines](https://ota-meshi.github.io/eslint-plugin-yml/rules/no-multiple-empty-lines.html) | disallow multiple empty lines | :wrench: | | |
| [yml/sort-keys](https://ota-meshi.github.io/eslint-plugin-yml/rules/sort-keys.html) | require mapping keys to be sorted | :wrench: | | |
| [yml/spaced-comment](https://ota-meshi.github.io/eslint-plugin-yml/rules/spaced-comment.html) | enforce consistent spacing after the `#` in a comment | :wrench: | | :star: |

Expand Down
1 change: 1 addition & 0 deletions docs/rules/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,6 @@ The rules with the following star :star: are included in the `plugin:yml/recomme
| [yml/flow-sequence-bracket-spacing](./flow-sequence-bracket-spacing.md) | enforce consistent spacing inside flow sequence brackets | :wrench: | | :star: |
| [yml/key-spacing](./key-spacing.md) | enforce consistent spacing between keys and values in mapping pairs | :wrench: | | :star: |
| [yml/no-irregular-whitespace](./no-irregular-whitespace.md) | disallow irregular whitespace | | :star: | :star: |
| [yml/no-multiple-empty-lines](./no-multiple-empty-lines.md) | disallow multiple empty lines | :wrench: | | |
| [yml/sort-keys](./sort-keys.md) | require mapping keys to be sorted | :wrench: | | |
| [yml/spaced-comment](./spaced-comment.md) | enforce consistent spacing after the `#` in a comment | :wrench: | | :star: |
72 changes: 72 additions & 0 deletions docs/rules/no-multiple-empty-lines.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
pageClass: "rule-details"
sidebarDepth: 0
title: "yml/no-multiple-empty-lines"
description: "disallow multiple empty lines"
---
# yml/no-multiple-empty-lines

> disallow multiple empty lines
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>
- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.

## :book: Rule Details

This rule aims to reduce the scrolling required when reading through your code. It will warn when the maximum amount of empty lines has been exceeded.
Use `max: 0` if you want to remove all blank lines.

<eslint-code-block fix>

<!-- eslint-skip -->

```yaml
# eslint yml/no-multiple-empty-lines: 'error'

# ✓ GOOD
"GOOD":
- "foo"
- "bar"

# ✗ BAD
"BAD":
- "foo"



- "bar"
```

</eslint-code-block>

## :wrench: Options

Nothing.

```yaml
yml/no-multiple-empty-lines:
- error
- max: 2
maxEOF: 2
maxBOF: 2
```

- `max` ... Enforces a maximum number of consecutive empty lines. Default is `2`.
- `maxEOF` ... Enforces a maximum number of consecutive empty lines at the end of files. Default is value specified for `max`.
- `maxBOF` ... Enforces a maximum number of consecutive empty lines at the beginning of files. Default is value specified for `max`.

Same as [no-multiple-empty-lines] rule option. See [here](https://eslint.org/docs/rules/no-multiple-empty-lines#options) for details.

## :couple: Related rules

- [no-multiple-empty-lines]

[no-multiple-empty-lines]: https://eslint.org/docs/rules/no-multiple-empty-lines

## :mag: Implementation

- [Rule source](https://github.com/ota-meshi/eslint-plugin-yml/blob/master/src/rules/no-multiple-empty-lines.ts)
- [Test source](https://github.com/ota-meshi/eslint-plugin-yml/blob/master/tests/src/rules/no-multiple-empty-lines.ts)
- [Test fixture sources](https://github.com/ota-meshi/eslint-plugin-yml/tree/master/tests/fixtures/rules/no-multiple-empty-lines)

<sup>Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/no-multiple-empty-lines)</sup>
1 change: 1 addition & 0 deletions src/configs/prettier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export = {
"yml/flow-sequence-bracket-spacing": "off",
"yml/indent": "off",
"yml/key-spacing": "off",
"yml/no-multiple-empty-lines": "off",
"yml/quotes": "off",
},
}
158 changes: 158 additions & 0 deletions src/rules/no-multiple-empty-lines.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import { createRule } from "../utils"

export default createRule("no-multiple-empty-lines", {
meta: {
docs: {
description: "disallow multiple empty lines",
categories: null,
extensionRule: "no-multiple-empty-lines",
layout: true,
},
fixable: "whitespace",

schema: [
{
type: "object",
properties: {
max: {
type: "integer",
minimum: 0,
},
maxEOF: {
type: "integer",
minimum: 0,
},
maxBOF: {
type: "integer",
minimum: 0,
},
},
required: ["max"],
additionalProperties: false,
},
],

messages: {
blankBeginningOfFile:
"Too many blank lines at the beginning of file. Max of {{max}} allowed.",
blankEndOfFile:
"Too many blank lines at the end of file. Max of {{max}} allowed.",
consecutiveBlank:
"More than {{max}} blank {{pluralizedLines}} not allowed.",
},
type: "layout",
},
create(context) {
if (!context.parserServices.isYAML) {
return {}
}

const maxOption = context.options[0]?.max ?? 2

const options = {
max: maxOption,
maxEOF: context.options[0]?.maxEOF ?? maxOption,
maxBOF: context.options[0]?.maxBOF ?? maxOption,
}

const sourceCode = context.getSourceCode()

const allLines = [...sourceCode.lines]
if (allLines[allLines.length - 1] === "") {
allLines.pop()
}

const ignoreLineIndexes = new Set()

/**
* Verify
*/
function verifyEmptyLines(
startLineIndex: number,
endLineIndex: number,
) {
const emptyLineCount = endLineIndex - startLineIndex

let messageId: string, max: number
if (startLineIndex === 0) {
messageId = "blankBeginningOfFile"
max = options.maxBOF
} else if (endLineIndex === allLines.length) {
messageId = "blankEndOfFile"
max = options.maxEOF
} else {
messageId = "consecutiveBlank"
max = options.max
}

if (emptyLineCount > max) {
context.report({
loc: {
start: {
line: startLineIndex + max + 1,
column: 0,
},
end: { line: endLineIndex + 1, column: 0 },
},
messageId,
data: {
max: String(max),
pluralizedLines: max === 1 ? "line" : "lines",
},
fix(fixer) {
const rangeStart = sourceCode.getIndexFromLoc({
line: startLineIndex + max + 1,
column: 0,
})
const rangeEnd =
endLineIndex < allLines.length
? sourceCode.getIndexFromLoc({
line: endLineIndex + 1,
column: 0,
})
: sourceCode.text.length

return fixer.removeRange([rangeStart, rangeEnd])
},
})
}
}

return {
YAMLScalar(node) {
for (
let lineIndex = node.loc.start.line - 1;
lineIndex < node.loc.end.line;
lineIndex++
) {
ignoreLineIndexes.add(lineIndex)
}
},
"Program:exit"() {
let startEmptyLineIndex: number | null = null

for (
let lineIndex = 0;
lineIndex < allLines.length;
lineIndex++
) {
const line = allLines[lineIndex]

const isEmptyLine =
!line.trim() && !ignoreLineIndexes.has(lineIndex)
if (isEmptyLine) {
startEmptyLineIndex ??= lineIndex
} else {
if (startEmptyLineIndex != null) {
verifyEmptyLines(startEmptyLineIndex, lineIndex)
}
startEmptyLineIndex = null
}
}
if (startEmptyLineIndex != null) {
verifyEmptyLines(startEmptyLineIndex, allLines.length)
}
},
}
},
})
2 changes: 2 additions & 0 deletions src/utils/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import noEmptyKey from "../rules/no-empty-key"
import noEmptyMappingValue from "../rules/no-empty-mapping-value"
import noEmptySequenceEntry from "../rules/no-empty-sequence-entry"
import noIrregularWhitespace from "../rules/no-irregular-whitespace"
import noMultipleEmptyLines from "../rules/no-multiple-empty-lines"
import noTabIndent from "../rules/no-tab-indent"
import plainScalar from "../rules/plain-scalar"
import quotes from "../rules/quotes"
Expand All @@ -40,6 +41,7 @@ export const rules = [
noEmptyMappingValue,
noEmptySequenceEntry,
noIrregularWhitespace,
noMultipleEmptyLines,
noTabIndent,
plainScalar,
quotes,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"message": "Too many blank lines at the end of file. Max of 0 allowed.",
"line": 3,
"column": 1
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# {"options": [{"maxEOF": 0, "max": 0}]}
a: a

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# no-multiple-empty-lines/invalid/max-eof0-test-input.yml
a: a
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"message": "Too many blank lines at the end of file. Max of 0 allowed.",
"line": 3,
"column": 1
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# {"options": [{"maxEOF": 0, "max": 0}]}
a: a


Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# no-multiple-empty-lines/invalid/max-eof1-test-input.yml
a: a
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"message": "Too many blank lines at the end of file. Max of 2 allowed.",
"line": 5,
"column": 1
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# {"options": [{"maxEOF": 2, "max": 0}]}
a: a



Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# no-multiple-empty-lines/invalid/max-eof2-test-input.yml
a: a


Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[
{
"message": "More than 0 blank lines not allowed.",
"line": 4,
"column": 1
},
{
"message": "More than 0 blank lines not allowed.",
"line": 6,
"column": 1
},
{
"message": "More than 0 blank lines not allowed.",
"line": 9,
"column": 1
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# {"options": [{"max": 0}]}
a: a
b: b

c: c


d: d



e: e
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# no-multiple-empty-lines/invalid/max0-test-input.yml
a: a
b: b
c: c
d: d
e: e
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"message": "More than 1 blank line not allowed.",
"line": 7,
"column": 1
},
{
"message": "More than 1 blank line not allowed.",
"line": 10,
"column": 1
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# {"options": [{"max": 1}]}
a: a
b: b

c: c


d: d



e: e
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# no-multiple-empty-lines/invalid/max1-test-input.yml
a: a
b: b

c: c

d: d

e: e

0 comments on commit af6fdf1

Please sign in to comment.