From 0b9ac9c25528b23cca0605032abb1e810152b1d9 Mon Sep 17 00:00:00 2001 From: RobertAKARobin Date: Tue, 3 Sep 2024 12:50:56 -0500 Subject: [PATCH] Strip trailing spaces --- .vscode/settings.json | 4 +- docs/rules/no-extra-spacing-text.md | 7 +- .../lib/rules/no-extra-spacing-text.js | 13 ++-- .../tests/rules/no-extra-spacing-text.test.js | 75 ++++++++++++++----- 4 files changed, 71 insertions(+), 28 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 6171e827..1e741cbb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,5 +3,7 @@ "eslint.validate": [ "javascript", // ... "html" // Add "html" to enable linting `.html` files. - ] + ], + + "files.trimTrailingWhitespace": false } diff --git a/docs/rules/no-extra-spacing-text.md b/docs/rules/no-extra-spacing-text.md index 19297f77..8bdec5e2 100644 --- a/docs/rules/no-extra-spacing-text.md +++ b/docs/rules/no-extra-spacing-text.md @@ -14,13 +14,16 @@ module.exports = { ## Rule Details -[Whitespace in HTML is largely ignored](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Whitespace), so the purpose of this rule is to prevent unnecessary sequences of whitespace in text. +[Whitespace in HTML is largely ignored](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Whitespace), so the purpose of this rule is to prevent unnecessary whitespace in text, such as: + +- Tab characters +- Sequences of more than 1 whitepsace character When used with `--fix`, the rule will replace invalid whitespace with a single space. Note: -- This rule ignores whitespace at the start and end of lines/strings so as not to conflict with indentation rules. See [./indent](@html-eslint/indent). +- This rule ignores whitespace at the start of lines in order to not conflict with indentation rules. See [./indent](@html-eslint/indent). - This rule does **not** affect whitespace around attributes. See [./no-extra-spacing-attrs](@html-eslint/no-extra-spacing-attrs). Examples of **incorrect** code for this rule: diff --git a/packages/eslint-plugin/lib/rules/no-extra-spacing-text.js b/packages/eslint-plugin/lib/rules/no-extra-spacing-text.js index ce794e67..6698b7eb 100644 --- a/packages/eslint-plugin/lib/rules/no-extra-spacing-text.js +++ b/packages/eslint-plugin/lib/rules/no-extra-spacing-text.js @@ -41,7 +41,7 @@ module.exports = { }, ], messages: { - [MESSAGE_IDS.UNEXPECTED]: "Multiple consecutive spaces not allowed here", + [MESSAGE_IDS.UNEXPECTED]: "Tabs and/or multiple consecutive spaces not allowed here", }, }, @@ -83,7 +83,7 @@ module.exports = { */ function stripConsecutiveSpaces(node) { const text = node.value; - const matcher = /(^|[^\n \t])([ \t]{2,})($|[^\n \t])/g; + const matcher = /(^|[^\n \t])([ \t]+\n|\t[\t ]*|[ \t]{2,})/g; // eslint-disable-next-line no-constant-condition while (true) { @@ -93,9 +93,7 @@ module.exports = { } const space = offender[2]; - const spaceAfter = offender[3]; - const indexStart = - node.range[0] + matcher.lastIndex - space.length - spaceAfter.length; + const indexStart = node.range[0] + matcher.lastIndex - space.length; const indexEnd = indexStart + space.length; context.report({ @@ -106,7 +104,10 @@ module.exports = { }, messageId: MESSAGE_IDS.UNEXPECTED, fix(fixer) { - return fixer.replaceTextRange([indexStart, indexEnd], ` `); + return fixer.replaceTextRange( + [indexStart, indexEnd], + space.endsWith(`\n`) ? `\n` : ` ` + ); }, }); } diff --git a/packages/eslint-plugin/tests/rules/no-extra-spacing-text.test.js b/packages/eslint-plugin/tests/rules/no-extra-spacing-text.test.js index b32539bc..10b41552 100644 --- a/packages/eslint-plugin/tests/rules/no-extra-spacing-text.test.js +++ b/packages/eslint-plugin/tests/rules/no-extra-spacing-text.test.js @@ -1,17 +1,29 @@ const createRuleTester = require("../rule-tester"); const rule = require("../../lib/rules/no-extra-spacing-text"); -/** - * @param {Array>} positions - */ + function errorsAt(...positions) { - return positions.map(([line, column, length]) => ({ - messageId: `unexpected`, - line, - column, - endLine: line, - endColumn: column + length, - })); + return positions.map(input => { + const [line, column, length] = input; + if (input.length === 3) { + return { + messageId: `unexpected`, + line, + column, + endLine: line, + endColumn: column + length, + }; + } else { + const [line, column, endLine, endColumn] = input; + return { + messageId: `unexpected`, + line, + column, + endLine, + endColumn, + }; + } + }); } const ruleTester = createRuleTester(); @@ -23,7 +35,7 @@ ruleTester.run("no-extra-spacing-text", rule, { }, { - code: `
\tfoo\tbar\t
`, + code: `
foo bar
`, }, { @@ -38,7 +50,7 @@ ruleTester.run("no-extra-spacing-text", rule, { }, { - code: `
   foo   bar   
`, + code: `
   foo\t\t\tbar   
`, options: [ { skip: [`pre`], @@ -64,15 +76,15 @@ ruleTester.run("no-extra-spacing-text", rule, { invalid: [ { - code: `foo bar`, - output: `foo bar`, - errors: errorsAt([1, 4, 3]), + code: `foo bar `, + output: `foo bar `, + errors: errorsAt([1, 4, 3], [1, 10, 3]), }, { code: `
\tfoo \t
`, - output: `
\tfoo
`, - errors: errorsAt([1, 10, 2]), + output: `
foo
`, + errors: errorsAt([1, 6, 1], [1, 10, 2]), }, { @@ -81,6 +93,28 @@ ruleTester.run("no-extra-spacing-text", rule, { errors: errorsAt([1, 6, 2], [1, 11, 3]), }, + { + code: `
foo \n
`, + output: `
foo\n
`, + errors: errorsAt([1, 9, 2, 1]), + }, + + { + code: `
foo\t\n
`, + output: `
foo\n
`, + errors: errorsAt([1, 9, 2, 1]), + }, + + { + code: `
\n\tfoo \n
\n
\n\tbar\t\n
`, + output: `
\n\tfoo\n
\n
\n\tbar\n
`, + errors: errorsAt( + [2, 5, 3, 1], + [3, 7, 4, 1], + [5, 5, 6, 1], + ), + }, + { code: `
\t\tfoo \t\t
@@ -94,7 +128,7 @@ ruleTester.run("no-extra-spacing-text", rule, { { code: `
- foo bar + foo bar
`, output: ` @@ -102,7 +136,10 @@ ruleTester.run("no-extra-spacing-text", rule, { foo bar `, - errors: errorsAt([3, 6, 5]), + errors: errorsAt( + [3, 6, 5], + [3, 14, 4, 1], + ), }, {