diff --git a/docs/rules/no-multi-spaces.md b/docs/rules/no-multi-spaces.md new file mode 100644 index 000000000..b93254dab --- /dev/null +++ b/docs/rules/no-multi-spaces.md @@ -0,0 +1,31 @@ +# This rule warns about the usage of extra whitespaces between attributes (no-multi-spaces) + +The `--fix` option on the command line can automatically fix some of the problems reported by this rule. + +This rule aims to remove multiple spaces in a row between attributes witch are not used for indentation. + +## Rule Details + +Examples of **incorrect** code for this rule: + +```html + +``` + +Examples of **correct** code for this rule: + +```html + +``` + +### Options + +Nothing diff --git a/lib/rules/no-multi-spaces.js b/lib/rules/no-multi-spaces.js new file mode 100644 index 000000000..c9d6369f4 --- /dev/null +++ b/lib/rules/no-multi-spaces.js @@ -0,0 +1,66 @@ +/** + * @fileoverview This rule warns about the usage of extra whitespaces between attributes + * @author Armano + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Rule Definition +// ------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: 'This rule warns about the usage of extra whitespaces between attributes', + category: 'Stylistic Issues', + recommended: false + }, + fixable: 'whitespace', // or "code" or "whitespace" + schema: [] + }, + + /** + * @param {RuleContext} context - The rule context. + * @returns {Object} AST event handlers. + */ + create (context) { + // ---------------------------------------------------------------------- + // Public + // ---------------------------------------------------------------------- + + return { + Program (node) { + if (context.parserServices.getTemplateBodyTokenStore == null) { + context.report({ + loc: { line: 1, column: 0 }, + message: 'Use the latest vue-eslint-parser. See also https://github.com/vuejs/eslint-plugin-vue#what-is-the-use-the-latest-vue-eslint-parser-error.' + }) + return + } + const sourceCode = context.getSourceCode() + const tokenStore = context.parserServices.getTemplateBodyTokenStore() + const tokens = tokenStore.getTokens(node.templateBody, { includeComments: true }) + + let prevToken = tokens.shift() + for (const token of tokens) { + const spaces = token.range[0] - prevToken.range[1] + if (spaces > 1 && token.loc.start.line === prevToken.loc.start.line) { + context.report({ + node: token, + loc: { + start: prevToken.loc.end, + end: token.loc.start + }, + message: "Multiple spaces found before '{{displayValue}}'.", + fix: (fixer) => fixer.replaceTextRange([prevToken.range[1], token.range[0]], ' '), + data: { + displayValue: sourceCode.getText(token) + } + }) + } + prevToken = token + } + } + } + } +} diff --git a/package.json b/package.json index 6ebff6e25..e111a90cc 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ }, "dependencies": { "requireindex": "^1.1.0", - "vue-eslint-parser": "2.0.0-beta.6" + "vue-eslint-parser": "2.0.0-beta.7" }, "devDependencies": { "@types/node": "^4.2.16", diff --git a/tests/lib/rules/no-multi-spaces.js b/tests/lib/rules/no-multi-spaces.js new file mode 100644 index 000000000..afb93cf07 --- /dev/null +++ b/tests/lib/rules/no-multi-spaces.js @@ -0,0 +1,177 @@ +/** + * @fileoverview This rule warns about the usage of extra whitespaces between attributes + * @author Armano + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const rule = require('../../../lib/rules/no-multi-spaces') +const RuleTester = require('eslint').RuleTester + +// ------------------------------------------------------------------------------ +// Tests +// ------------------------------------------------------------------------------ + +const ruleTester = new RuleTester({ + parser: 'vue-eslint-parser', + parserOptions: { ecmaVersion: 2015 } +}) + +ruleTester.run('no-multi-spaces', rule, { + valid: [ + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '' + ], + invalid: [ + { + code: '', + output: '', + errors: [{ + message: "Multiple spaces found before '/>'.", + type: 'HTMLSelfClosingTagClose' + }] + }, + { + code: '', + output: '', + errors: [ + { + message: "Multiple spaces found before 'class'.", + type: 'HTMLIdentifier' + }, + { + message: "Multiple spaces found before '/>'.", + type: 'HTMLSelfClosingTagClose' + } + ] + }, + { + code: '', + output: '', + errors: [ + { + message: "Multiple spaces found before 'class'.", + type: 'HTMLIdentifier' + }, + { + message: "Multiple spaces found before '/>'.", + type: 'HTMLSelfClosingTagClose' + } + ] + }, + { + code: '', + output: '', + errors: [ + { + message: "Multiple spaces found before ':class'.", + type: 'HTMLIdentifier' + }, + { + message: "Multiple spaces found before '/>'.", + type: 'HTMLSelfClosingTagClose' + } + ] + }, + { + code: '', + output: '', + errors: [{ + message: "Multiple spaces found before '/>'.", + type: 'HTMLSelfClosingTagClose' + }] + }, + { + code: '', + output: '', + errors: [{ + message: "Multiple spaces found before '/>'.", + type: 'HTMLSelfClosingTagClose' + }] + }, + { + code: '', + output: '', + errors: [{ + message: "Multiple spaces found before '/>'.", + type: 'HTMLSelfClosingTagClose' + }] + }, + { + code: '', + output: '', + errors: [ + { + message: "Multiple spaces found before '/>'.", + type: 'HTMLSelfClosingTagClose' + } + ] + }, + { + code: '', + output: '', + errors: [ + { + message: "Multiple spaces found before 'test'.", + type: 'Identifier' + }, + { + message: "Multiple spaces found before '}}'.", + type: 'VExpressionEnd' + } + ] + }, + { + code: '', + output: '', + errors: [ + { + message: "Multiple spaces found before '>'.", + type: 'HTMLTagClose' + } + ] + }, + { + code: '', + output: '', + errors: [ + { + message: "Multiple spaces found before 'i'.", + type: 'Identifier' + }, + { + message: "Multiple spaces found before 'in'.", + type: 'Keyword' + }, + { + message: "Multiple spaces found before 'b'.", + type: 'Identifier' + }, + { + message: "Multiple spaces found before '\"'.", + type: 'Punctuator' + } + ] + } + ] +})