Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 37 additions & 24 deletions lib/rules/template-no-multiple-empty-lines.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,45 +49,58 @@ module.exports = {
offset += line.length + 1; // +1 for the '\n'
}

// Swallow the final newline, as some editors add it automatically
// and we don't want it to cause an issue.
const effectiveLines = lines.length > 0 && lines.at(-1) === '' ? lines.slice(0, -1) : lines;

let emptyCount = 0;
let firstEmptyLine = -1;

for (const [index, line] of lines.entries()) {
function reportExcess(endIndex) {
const startLine = firstEmptyLine + max;
const endLine = endIndex;

// Remove the excess empty lines: keep `max` empty lines,
// remove everything from the start of the (max+1)-th empty
// line to the start of the next non-empty line (or end of content).
const rangeStart = lineOffsets[firstEmptyLine + max];
const rangeEnd = endIndex < lines.length ? lineOffsets[endIndex] : text.length;

context.report({
loc: {
start: { line: startLine + 1, column: 0 },
end: { line: endLine + 1, column: 0 },
},
messageId: 'unexpected',
data: {
max,
pluralizedLines: max === 1 ? 'line' : 'lines',
},
fix(fixer) {
return fixer.replaceTextRange([rangeStart, rangeEnd], '');
},
});
}

for (const [index, line] of effectiveLines.entries()) {
if (line.trim() === '') {
if (emptyCount === 0) {
firstEmptyLine = index;
}
emptyCount++;
} else {
if (emptyCount > max) {
const startLine = firstEmptyLine + max + 1;
const endLine = index;

// Remove the excess empty lines: keep `max` empty lines,
// remove everything from the start of the (max+1)-th empty
// line to the start of the next non-empty line.
const rangeStart = lineOffsets[firstEmptyLine + max];
const rangeEnd = lineOffsets[endLine];

context.report({
loc: {
start: { line: startLine + 1, column: 0 },
end: { line: endLine, column: 0 },
},
messageId: 'unexpected',
data: {
max,
pluralizedLines: max === 1 ? 'line' : 'lines',
},
fix(fixer) {
return fixer.replaceTextRange([rangeStart, rangeEnd], '');
},
});
reportExcess(index);
}
emptyCount = 0;
firstEmptyLine = -1;
}
}

// Handle trailing empty lines at the end of the effective content
if (emptyCount > max) {
reportExcess(effectiveLines.length);
}
},
};
},
Expand Down
17 changes: 17 additions & 0 deletions tests/lib/rules/template-no-multiple-empty-lines.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,5 +177,22 @@ hbsRuleTester.run('template-no-multiple-empty-lines', rule, {
options: [{ max: 3 }],
errors: [{ message: 'More than 3 blank lines not allowed.' }],
},
// loc fix: the excess empty line (line 3) is reported at the correct location
{
code: '<div>foo</div>\n\n\n<div>bar</div>',
output: '<div>foo</div>\n\n<div>bar</div>',
errors: [{ message: 'More than 1 blank line not allowed.', line: 3, endLine: 4 }],
},
// Trailing empty lines
{
code: '<div>foo</div>\n\n\n',
output: '<div>foo</div>\n\n',
errors: [{ message: 'More than 1 blank line not allowed.' }],
},
{
code: '<div>foo</div>\n\n\n\n\n',
output: '<div>foo</div>\n\n',
errors: [{ message: 'More than 1 blank line not allowed.' }],
},
],
});
Loading