Skip to content

Commit ecd49fa

Browse files
committed
Extract rule: template-no-multiple-empty-lines
1 parent 79e34fd commit ecd49fa

4 files changed

Lines changed: 305 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ rules in templates can be disabled with eslint directives with mustache or html
210210
| [template-no-input-placeholder](docs/rules/template-no-input-placeholder.md) | disallow placeholder attribute on input elements | | | |
211211
| [template-no-input-tagname](docs/rules/template-no-input-tagname.md) | disallow tagName attribute on {{input}} helper | | | |
212212
| [template-no-log](docs/rules/template-no-log.md) | disallow {{log}} in templates | | | |
213+
| [template-no-multiple-empty-lines](docs/rules/template-no-multiple-empty-lines.md) | disallow multiple consecutive empty lines in templates | | | |
213214
| [template-no-mut-helper](docs/rules/template-no-mut-helper.md) | disallow usage of (mut) helper | | | |
214215
| [template-no-negated-comparison](docs/rules/template-no-negated-comparison.md) | disallow negated comparisons in templates | | | |
215216
| [template-no-negated-condition](docs/rules/template-no-negated-condition.md) | disallow negated conditions in if/unless | | | |
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# ember/template-no-multiple-empty-lines
2+
3+
<!-- end auto-generated rule header -->
4+
5+
Disallows multiple consecutive empty lines in templates.
6+
7+
Multiple consecutive blank lines reduce readability and should be limited.
8+
9+
## Rule Details
10+
11+
This rule enforces a maximum number of consecutive empty lines (default: 1).
12+
13+
## Configuration
14+
15+
The following values are valid configuration:
16+
17+
- object -- An object with the following keys:
18+
- `max` -- An integer specifying the maximum number of consecutive empty lines allowed. Defaults to `1`.
19+
20+
## Examples
21+
22+
Examples of **incorrect** code for this rule:
23+
24+
```gjs
25+
<template>
26+
<div>First</div>
27+
28+
29+
<div>Second</div>
30+
</template>
31+
```
32+
33+
```gjs
34+
<template>
35+
<div>Content</div>
36+
37+
38+
39+
<div>More content</div>
40+
</template>
41+
```
42+
43+
Examples of **correct** code for this rule:
44+
45+
```gjs
46+
<template>
47+
<div>First</div>
48+
49+
<div>Second</div>
50+
</template>
51+
```
52+
53+
```gjs
54+
<template>
55+
<div>Content</div>
56+
<div>More content</div>
57+
</template>
58+
```
59+
60+
## References
61+
62+
- [eslint-plugin-ember template-no-multiple-empty-lines](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/template-no-multiple-empty-lines.md)
63+
- [ESLint no-multiple-empty-lines](https://eslint.org/docs/rules/no-multiple-empty-lines)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/** @type {import('eslint').Rule.RuleModule} */
2+
module.exports = {
3+
meta: {
4+
type: 'suggestion',
5+
docs: {
6+
description: 'disallow multiple consecutive empty lines in templates',
7+
category: 'Best Practices',
8+
url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-no-multiple-empty-lines.md',
9+
templateMode: 'both',
10+
},
11+
fixable: null,
12+
schema: [
13+
{
14+
type: 'object',
15+
properties: {
16+
max: {
17+
type: 'integer',
18+
minimum: 0,
19+
},
20+
},
21+
additionalProperties: false,
22+
},
23+
],
24+
messages: {
25+
unexpected: 'More than {{max}} blank {{pluralizedLines}} not allowed.',
26+
},
27+
originallyFrom: {
28+
name: 'ember-template-lint',
29+
rule: 'lib/rules/no-multiple-empty-lines.js',
30+
docs: 'docs/rule/no-multiple-empty-lines.md',
31+
tests: 'test/unit/rules/no-multiple-empty-lines-test.js',
32+
},
33+
},
34+
35+
create(context) {
36+
const max = context.options[0]?.max ?? 1;
37+
const sourceCode = context.sourceCode;
38+
39+
return {
40+
Program(node) {
41+
const text = sourceCode.getText();
42+
const lines = text.split('\n');
43+
let emptyCount = 0;
44+
let firstEmptyLine = -1;
45+
46+
for (const [index, line] of lines.entries()) {
47+
if (line.trim() === '') {
48+
if (emptyCount === 0) {
49+
firstEmptyLine = index;
50+
}
51+
emptyCount++;
52+
} else {
53+
if (emptyCount > max) {
54+
const startLine = firstEmptyLine + max + 1;
55+
const endLine = index;
56+
57+
context.report({
58+
loc: {
59+
start: { line: startLine + 1, column: 0 },
60+
end: { line: endLine, column: 0 },
61+
},
62+
messageId: 'unexpected',
63+
data: {
64+
max,
65+
pluralizedLines: max === 1 ? 'line' : 'lines',
66+
},
67+
});
68+
}
69+
emptyCount = 0;
70+
firstEmptyLine = -1;
71+
}
72+
}
73+
},
74+
};
75+
},
76+
};
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
//------------------------------------------------------------------------------
2+
// Requirements
3+
//------------------------------------------------------------------------------
4+
5+
const rule = require('../../../lib/rules/template-no-multiple-empty-lines');
6+
const RuleTester = require('eslint').RuleTester;
7+
8+
//------------------------------------------------------------------------------
9+
// Tests
10+
//------------------------------------------------------------------------------
11+
12+
const ruleTester = new RuleTester({
13+
parser: require.resolve('ember-eslint-parser'),
14+
parserOptions: { ecmaVersion: 2022, sourceType: 'module' },
15+
});
16+
17+
ruleTester.run('template-no-multiple-empty-lines', rule, {
18+
valid: [
19+
`<template>
20+
<div>Hello</div>
21+
22+
<div>World</div>
23+
</template>`,
24+
{
25+
code: `<template>
26+
<div>Hello</div>
27+
28+
29+
<div>World</div>
30+
</template>`,
31+
options: [{ max: 2 }],
32+
},
33+
`<template>
34+
<div>Content</div>
35+
</template>`,
36+
37+
'<template><div>foo</div><div>bar</div></template>',
38+
`<template><div>foo</div>
39+
<div>bar</div></template>`,
40+
`<template><div>foo</div>r
41+
<div>bar</div></template>`,
42+
`<template><div>foo</div>
43+
44+
<div>bar</div></template>`,
45+
`<template><div>foo</div>r
46+
r
47+
<div>bar</div></template>`,
48+
`<template>
49+
<div>foo</div>
50+
51+
<div>bar</div>
52+
</template>`,
53+
],
54+
55+
invalid: [
56+
{
57+
code: `<template>
58+
<div>Hello</div>
59+
60+
61+
<div>World</div>
62+
</template>`,
63+
output: null,
64+
errors: [
65+
{
66+
message: 'More than 1 blank line not allowed.',
67+
},
68+
],
69+
},
70+
{
71+
code: `<template>
72+
<div>First</div>
73+
74+
75+
76+
<div>Second</div>
77+
</template>`,
78+
output: null,
79+
errors: [
80+
{
81+
message: 'More than 1 blank line not allowed.',
82+
},
83+
],
84+
},
85+
86+
{
87+
code: `<template><div>foo</div>
88+
89+
90+
<div>bar</div></template>`,
91+
output: null,
92+
errors: [{ message: 'More than 1 blank line not allowed.' }],
93+
},
94+
{
95+
code: `<template><div>foo</div>
96+
97+
98+
99+
100+
<div>bar</div></template>`,
101+
output: null,
102+
errors: [{ message: 'More than 1 blank line not allowed.' }],
103+
},
104+
],
105+
});
106+
107+
const hbsRuleTester = new RuleTester({
108+
parser: require.resolve('ember-eslint-parser/hbs'),
109+
parserOptions: {
110+
ecmaVersion: 2022,
111+
sourceType: 'module',
112+
},
113+
});
114+
115+
hbsRuleTester.run('template-no-multiple-empty-lines', rule, {
116+
valid: [
117+
'<div>foo</div><div>bar</div>',
118+
`<div>foo</div>
119+
<div>bar</div>`,
120+
`<div>foo</div>
121+
122+
<div>bar</div>`,
123+
`
124+
<div>foo</div>
125+
126+
<div>bar</div>
127+
`,
128+
'<div>foo</div>\r\n<div>bar</div>',
129+
'<div>foo</div>\r\n\r\n<div>bar</div>',
130+
{
131+
code: '<div>foo</div>\n\n\n<div>bar</div>',
132+
options: [{ max: 2 }],
133+
},
134+
{
135+
code: '<div>foo</div>\r\n\r\n\r\n<div>bar</div>',
136+
options: [{ max: 2 }],
137+
},
138+
],
139+
invalid: [
140+
{
141+
code: `<div>foo</div>
142+
143+
144+
<div>bar</div>`,
145+
output: null,
146+
errors: [{ message: 'More than 1 blank line not allowed.' }],
147+
},
148+
{
149+
code: `<div>foo</div>
150+
151+
152+
153+
154+
<div>bar</div>`,
155+
output: null,
156+
errors: [{ message: 'More than 1 blank line not allowed.' }],
157+
},
158+
{
159+
code: '<div>foo</div>\n\n\n\n\n<div>bar</div>',
160+
output: null,
161+
options: [{ max: 3 }],
162+
errors: [{ message: 'More than 3 blank lines not allowed.' }],
163+
},
164+
],
165+
});

0 commit comments

Comments
 (0)