From a7d9313c65ac186c579455b9fede66ceefd81dc9 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 29 Jun 2017 11:24:28 +0100 Subject: [PATCH 01/12] Inits new rule. Adds documentation. --- docs/rules/max-attributes-per-line.md | 88 ++++++++++++++++++++++ lib/rules/max-attributes-per-line.js | 44 +++++++++++ tests/lib/rules/max-attributes-per-line.js | 37 +++++++++ 3 files changed, 169 insertions(+) create mode 100644 docs/rules/max-attributes-per-line.md create mode 100644 lib/rules/max-attributes-per-line.js create mode 100644 tests/lib/rules/max-attributes-per-line.js diff --git a/docs/rules/max-attributes-per-line.md b/docs/rules/max-attributes-per-line.md new file mode 100644 index 000000000..dc0a1fa38 --- /dev/null +++ b/docs/rules/max-attributes-per-line.md @@ -0,0 +1,88 @@ +# Define the number of attributes allows per line (max-attributes-per-line) + +Limits the maximum number of props per line to improve readability + + +## Rule Details + +This rule aims to enforce a number of props per line in templates. It checks all the elements in a template and verifies that the number of props per line does not exceed the defined maximum. +A prop is considered to be in a new line when there is a line break between two props. + +The default is one prop per line + +Examples of **incorrect** code for this rule: + +```js + + + + + +``` + +Examples of **correct** code for this rule: + +```js + + + + +``` + +### Options + +``` +{ + "vue/max-attributes-per-line": ["error", { + "singleline": 2, + "multiline": 1 + }] +} +``` +### `singleline` +Number of maximum number of props when a tag is in a single line. + +The following patterns is considered a warning: +```js +// ["error", { "singleline": 2, "multiline": 1}] +; +``` + +The following pattern is not considered a warning: +```js +// ["error", { "singleline": 3, "multiline": 1}] +; +``` + + +### `multiline` +Number of maximum number of props when a tag is in a single line. + + +The following patterns is considered a warning: +```js +// ["error", { "singleline": 2, "multiline": 1}] + +; +``` + +The following pattern is not considered a warning: +```js +// ["error", { "singleline": 3, "multiline": 1}] + +; +``` + +## When Not To Use It + +If you do not want to check the number of props declared per line you can disable this rule. + diff --git a/lib/rules/max-attributes-per-line.js b/lib/rules/max-attributes-per-line.js new file mode 100644 index 000000000..0138b4aa1 --- /dev/null +++ b/lib/rules/max-attributes-per-line.js @@ -0,0 +1,44 @@ +/** + * @fileoverview Define the number of attributes allows per line + * @author Filipa Lacerda + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "Define the number of attributes allows per line", + category: "Fill me in", + recommended: false + }, + fixable: null, // or "code" or "whitespace" + schema: [ + // fill in your schema + ] + }, + + create: function(context) { + + // variables should be defined here + + //---------------------------------------------------------------------- + // Helpers + //---------------------------------------------------------------------- + + // any helper functions should go here or else delete this section + + //---------------------------------------------------------------------- + // Public + //---------------------------------------------------------------------- + + return { + + // give me methods + + }; + } +}; diff --git a/tests/lib/rules/max-attributes-per-line.js b/tests/lib/rules/max-attributes-per-line.js new file mode 100644 index 000000000..9da2a5ea3 --- /dev/null +++ b/tests/lib/rules/max-attributes-per-line.js @@ -0,0 +1,37 @@ +/** + * @fileoverview Define the number of attributes allows per line + * @author Filipa Lacerda + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +var rule = require("../../../lib/rules/max-attributes-per-line"), + + RuleTester = require("eslint").RuleTester; + + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +var ruleTester = new RuleTester(); +ruleTester.run("max-attributes-per-line", rule, { + + valid: [ + + // give me some code that won't trigger a warning + ], + + invalid: [ + { + code: "", + errors: [{ + message: "Fill me in.", + type: "Me too" + }] + } + ] +}); From 7ef1ca540716d6e57e04009109669f48c234bf2f Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 29 Jun 2017 12:03:50 +0100 Subject: [PATCH 02/12] Improves rule definition --- docs/rules/max-attributes-per-line.md | 71 ++++++++++++++++++++------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/docs/rules/max-attributes-per-line.md b/docs/rules/max-attributes-per-line.md index dc0a1fa38..b20e1b03e 100644 --- a/docs/rules/max-attributes-per-line.md +++ b/docs/rules/max-attributes-per-line.md @@ -1,33 +1,42 @@ # Define the number of attributes allows per line (max-attributes-per-line) -Limits the maximum number of props per line to improve readability +Limits the maximum number of attributes/properties per line to improve readability. ## Rule Details -This rule aims to enforce a number of props per line in templates. It checks all the elements in a template and verifies that the number of props per line does not exceed the defined maximum. -A prop is considered to be in a new line when there is a line break between two props. +This rule aims to enforce a number of attributes per line in templates. It checks all the elements in a template and verifies that the number of attributes per line does not exceed the defined maximum. +An attribute is considered to be in a new line when there is a line break between two attributes. -The default is one prop per line +There is predefined number of attributes that are acceptable in one-line case, as well as how many attributes are acceptable per line in multi-line case. + +The default is one attribute per line for multiline and three attributes per line in singleline. Examples of **incorrect** code for this rule: ```js + + - - - - + + ``` Examples of **correct** code for this rule: ```js + + @@ -38,34 +47,60 @@ Examples of **correct** code for this rule: ``` { "vue/max-attributes-per-line": ["error", { + "firstline": 1, "singleline": 2, "multiline": 1 }] } ``` + +### `firstline` +For muliline declarations, defines if it accepts an attribute in the first line. + +The following patterns is considered a warning: +```js +// ["error", { "firstline": 1, "singleline": 2, "multiline": 1}] + +; +``` + +The following pattern is not considered a warning: +```js +// ["error", { "firstline": 0, "singleline": 3, "multiline": 1}] + +; +``` + + ### `singleline` -Number of maximum number of props when a tag is in a single line. +Number of maximum attributes per line when the opening tag is in a single line. The following patterns is considered a warning: ```js -// ["error", { "singleline": 2, "multiline": 1}] +// ["error", { "firstline": 1, "singleline": 2, "multiline": 1}] ; ``` The following pattern is not considered a warning: ```js -// ["error", { "singleline": 3, "multiline": 1}] +// ["error", { "firstline": 1, "singleline": 3, "multiline": 1}] ; ``` ### `multiline` -Number of maximum number of props when a tag is in a single line. +Number of maximum attributes per line when a tag is in multiple lines. The following patterns is considered a warning: ```js -// ["error", { "singleline": 2, "multiline": 1}] +// ["error", { "firstline": 1, "singleline": 2, "multiline": 1}] ; @@ -73,7 +108,7 @@ The following patterns is considered a warning: The following pattern is not considered a warning: ```js -// ["error", { "singleline": 3, "multiline": 1}] +// ["error", { "firstline": 0, "singleline": 3, "multiline": 1}] Date: Fri, 30 Jun 2017 19:08:42 +0100 Subject: [PATCH 03/12] Update docs to match review --- docs/rules/max-attributes-per-line.md | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/docs/rules/max-attributes-per-line.md b/docs/rules/max-attributes-per-line.md index b20e1b03e..fed2a6875 100644 --- a/docs/rules/max-attributes-per-line.md +++ b/docs/rules/max-attributes-per-line.md @@ -5,12 +5,11 @@ Limits the maximum number of attributes/properties per line to improve readabili ## Rule Details -This rule aims to enforce a number of attributes per line in templates. It checks all the elements in a template and verifies that the number of attributes per line does not exceed the defined maximum. +This rule aims to enforce a number of attributes per line in templates. +It checks all the elements in a template and verifies that the number of attributes per line does not exceed the defined maximum. An attribute is considered to be in a new line when there is a line break between two attributes. -There is predefined number of attributes that are acceptable in one-line case, as well as how many attributes are acceptable per line in multi-line case. - -The default is one attribute per line for multiline and three attributes per line in singleline. +There is a configurable number of attributes that are acceptable in one-line case (default 3), as well as how many attributes are acceptable per line in multi-line case (default 1). Examples of **incorrect** code for this rule: @@ -55,9 +54,9 @@ Examples of **correct** code for this rule: ``` ### `firstline` -For muliline declarations, defines if it accepts an attribute in the first line. +For multi-line declarations, defines how many attributes are acceptable to be put in the first line. (Default 0) -The following patterns is considered a warning: +Example of **incorrect** code for this setting: ```js // ["error", { "firstline": 1, "singleline": 2, "multiline": 1}] ; ``` -The following pattern is not considered a warning: +Example of **correct** code for this setting: ```js // ["error", { "firstline": 0, "singleline": 3, "multiline": 1}] ; ``` -The following pattern is not considered a warning: +Example of **correct** code for this setting: ```js // ["error", { "firstline": 1, "singleline": 3, "multiline": 1}] ; @@ -97,8 +96,7 @@ The following pattern is not considered a warning: ### `multiline` Number of maximum attributes per line when a tag is in multiple lines. - -The following patterns is considered a warning: +Example of **incorrect** code for this setting: ```js // ["error", { "firstline": 1, "singleline": 2, "multiline": 1}] ; ``` -The following pattern is not considered a warning: +Example of **correct** code for this setting: ```js // ["error", { "firstline": 0, "singleline": 3, "multiline": 1}] Date: Thu, 6 Jul 2017 23:30:36 +0100 Subject: [PATCH 04/12] Adds rule to check for number of attributes per line --- lib/rules/max-attributes-per-line.js | 119 ++++++++++++++++----- tests/lib/rules/max-attributes-per-line.js | 104 +++++++++++++----- 2 files changed, 172 insertions(+), 51 deletions(-) diff --git a/lib/rules/max-attributes-per-line.js b/lib/rules/max-attributes-per-line.js index 0138b4aa1..1f1e3d6b9 100644 --- a/lib/rules/max-attributes-per-line.js +++ b/lib/rules/max-attributes-per-line.js @@ -2,43 +2,110 @@ * @fileoverview Define the number of attributes allows per line * @author Filipa Lacerda */ -"use strict"; +'use strict' -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ // Rule Definition -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ +const utils = require('../utils') module.exports = { - meta: { - docs: { - description: "Define the number of attributes allows per line", - category: "Fill me in", - recommended: false - }, - fixable: null, // or "code" or "whitespace" - schema: [ - // fill in your schema - ] + meta: { + docs: { + description: 'Define the number of attributes allows per line', + category: 'Stylistic Issues', + recommended: false }, + fixable: 'code', + schema: [{ + type: 'object', + properties: { + 'firstline': { + type: 'number', + minimum: 0 + }, + 'singleline': { + type: 'number', + minimum: 1 + }, + 'multiline': { + type: 'number', + minimum: 1 + } + } + }] + }, + + create: function (context) { + const configuration = context.options[0] + const multilineMaximum = configuration.multiline + const singlelinemMaximum = configuration.singleline + const canHaveFirstLine = configuration.firstline !== 0 + + utils.registerTemplateBodyVisitor(context, { + 'VStartTag' (node) { + const numberOfAttributes = node.attributes.length - create: function(context) { + if (!numberOfAttributes) return - // variables should be defined here + if (isSingleLine(node) && numberOfAttributes > singlelinemMaximum) { + context.report({ + node, + loc: node.loc, + message: 'It has more than {{singlelinemMaximum}} attributes per line.', + data: { + singlelinemMaximum + } + }) + } - //---------------------------------------------------------------------- - // Helpers - //---------------------------------------------------------------------- + if (!isSingleLine(node)) { + if (!canHaveFirstLine && node.attributes[0].loc.start.line === node.loc.start.line) { + context.report({ + node, + loc: node.loc, + message: 'Attribute {{propName}} should be on a new line.', + data: { + propName: node.attributes[0].key.name + } + }) + } - // any helper functions should go here or else delete this section + const propsPerLine = [[node.attributes[0]]] - //---------------------------------------------------------------------- - // Public - //---------------------------------------------------------------------- + node.attributes.reduce(function (previous, current) { + if (previous.loc.end.line === current.loc.start.line) { + propsPerLine[propsPerLine.length - 1].push(current) + } else { + propsPerLine.push([current]) + } + return current + }) - return { + propsPerLine.forEach(function (attributes) { + if (attributes.length > multilineMaximum) { + const prop = attributes[multilineMaximum] - // give me methods + context.report({ + node, + loc: node.loc, + message: 'Attribute {{propName}} should be on a new line.', + data: { + propName: prop.key.name + } + }) + } + }) + } + } + }) - }; + // ---------------------------------------------------------------------- + // Helpers + // ---------------------------------------------------------------------- + function isSingleLine (node) { + return node.loc.start.line === node.loc.end.line } -}; + return {} + } +} diff --git a/tests/lib/rules/max-attributes-per-line.js b/tests/lib/rules/max-attributes-per-line.js index 9da2a5ea3..09c9eed61 100644 --- a/tests/lib/rules/max-attributes-per-line.js +++ b/tests/lib/rules/max-attributes-per-line.js @@ -2,36 +2,90 @@ * @fileoverview Define the number of attributes allows per line * @author Filipa Lacerda */ -"use strict"; +'use strict' -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ // Requirements -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ -var rule = require("../../../lib/rules/max-attributes-per-line"), +const RuleTester = require('eslint').RuleTester +const rule = require('../../../lib/rules/max-attributes-per-line') - RuleTester = require("eslint").RuleTester; - - -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ // Tests -//------------------------------------------------------------------------------ - -var ruleTester = new RuleTester(); -ruleTester.run("max-attributes-per-line", rule, { +// ------------------------------------------------------------------------------ - valid: [ +const ruleTester = new RuleTester({ + parser: 'vue-eslint-parser', + parserOptions: { ecmaVersion: 2015 } +}) - // give me some code that won't trigger a warning - ], +ruleTester.run('max-attributes-per-line', rule, { + valid: [ + { + code: ``, + options: [{ singleline: 1, multiline: 1, firstline: 0 }] + }, + { + code: ``, + options: [{ singleline: 3, multiline: 1, firstline: 0 }] + }, + { + code: ``, + options: [{ singleline: 3, multiline: 1, firstline: 1 }] + }, + { + code: ``, + options: [{ singleline: 3, multiline: 1, firstline: 0 }] + }, + { + code: ``, + options: [{ singleline: 3, multiline: 2, firstline: 0 }] + } + ], - invalid: [ - { - code: "", - errors: [{ - message: "Fill me in.", - type: "Me too" - }] - } - ] -}); + invalid: [ + { + code: ``, + options: [{ singleline: 1, multiline: 1, firstline: 0 }], + errors: ['It has more than 1 attributes per line.'] + }, + { + code: ``, + options: [{ singleline: 3, multiline: 1, firstline: 0 }], + errors: ['Attribute name should be on a new line.'] + }, + { + code: ``, + options: [{ singleline: 3, multiline: 1, firstline: 0 }], + errors: ['Attribute age should be on a new line.'] + }, + { + code: ``, + options: [{ singleline: 3, multiline: 2, firstline: 0 }], + errors: ['Attribute petname should be on a new line.'] + } + ] +}) From c78b20d131041dc1b371f134235e9783967a5a17 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 13 Jul 2017 10:15:19 +0100 Subject: [PATCH 05/12] Updates per code review: - Adds defaults values - Adds tests for the default values --- lib/rules/max-attributes-per-line.js | 24 +++++++----- tests/lib/rules/max-attributes-per-line.js | 43 +++++++++++++++++----- 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/lib/rules/max-attributes-per-line.js b/lib/rules/max-attributes-per-line.js index 1f1e3d6b9..c1a6d0149 100644 --- a/lib/rules/max-attributes-per-line.js +++ b/lib/rules/max-attributes-per-line.js @@ -16,31 +16,35 @@ module.exports = { category: 'Stylistic Issues', recommended: false }, - fixable: 'code', + fixable: null, schema: [{ type: 'object', properties: { - 'firstline': { - type: 'number', - minimum: 0 - }, 'singleline': { type: 'number', minimum: 1 }, 'multiline': { - type: 'number', - minimum: 1 + type: 'object', + properties: { + 'max': { + type: 'number', + minimum: 1 + }, + 'allowFirstLine': { + type: 'boolean' + } + } } } }] }, create: function (context) { - const configuration = context.options[0] - const multilineMaximum = configuration.multiline + const configuration = context.options[0] || { singleline: 3, multiline: { max: 1, allowFirstLine: false }} + const multilineMaximum = configuration.multiline.max const singlelinemMaximum = configuration.singleline - const canHaveFirstLine = configuration.firstline !== 0 + const canHaveFirstLine = configuration.multiline.allowFirstLine utils.registerTemplateBodyVisitor(context, { 'VStartTag' (node) { diff --git a/tests/lib/rules/max-attributes-per-line.js b/tests/lib/rules/max-attributes-per-line.js index 09c9eed61..189d47a30 100644 --- a/tests/lib/rules/max-attributes-per-line.js +++ b/tests/lib/rules/max-attributes-per-line.js @@ -22,20 +22,33 @@ const ruleTester = new RuleTester({ ruleTester.run('max-attributes-per-line', rule, { valid: [ + { + code: `` + }, + { + code: `` + }, + { + code: `` + }, { code: ``, - options: [{ singleline: 1, multiline: 1, firstline: 0 }] + options: [{ singleline: 1, multiline: { max: 1, allowFirstLine: false }}] }, { code: ``, - options: [{ singleline: 3, multiline: 1, firstline: 0 }] + options: [{ singleline: 3, multiline: { max: 1, allowFirstLine: false }}] }, { code: ``, - options: [{ singleline: 3, multiline: 1, firstline: 1 }] + options: [{ singleline: 3, multiline: { max: 1, allowFirstLine: true }}] }, { code: ``, - options: [{ singleline: 3, multiline: 1, firstline: 0 }] + options: [{ singleline: 3, multiline: { max: 1, allowFirstLine: false }}] }, { code: ``, - options: [{ singleline: 3, multiline: 2, firstline: 0 }] + options: [{ singleline: 3, multiline: { max: 2, allowFirstLine: false }}] } ], invalid: [ + { + code: ``, + errors: ['It has more than 3 attributes per line.'] + }, + { + code: ``, + errors: ['Attribute job should be on a new line.'] + }, { code: ``, - options: [{ singleline: 1, multiline: 1, firstline: 0 }], + options: [{ singleline: 1, multiline: { max: 1, allowFirstLine: false }}], errors: ['It has more than 1 attributes per line.'] }, { @@ -66,7 +91,7 @@ ruleTester.run('max-attributes-per-line', rule, { age="30"> `, - options: [{ singleline: 3, multiline: 1, firstline: 0 }], + options: [{ singleline: 3, multiline: { max: 1, allowFirstLine: false }}], errors: ['Attribute name should be on a new line.'] }, { @@ -75,7 +100,7 @@ ruleTester.run('max-attributes-per-line', rule, { job="Vet"> `, - options: [{ singleline: 3, multiline: 1, firstline: 0 }], + options: [{ singleline: 3, multiline: { max: 1, allowFirstLine: false }}], errors: ['Attribute age should be on a new line.'] }, { @@ -84,7 +109,7 @@ ruleTester.run('max-attributes-per-line', rule, { job="Vet" pet="dog" petname="Snoopy"> `, - options: [{ singleline: 3, multiline: 2, firstline: 0 }], + options: [{ singleline: 3, multiline: { max: 2, allowFirstLine: false }}], errors: ['Attribute petname should be on a new line.'] } ] From 56f5f7062ceb6b69376db51db4944a08fa21d923 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 18 Jul 2017 14:37:46 +0100 Subject: [PATCH 06/12] Updates single line max attributes error as per code review --- lib/rules/max-attributes-per-line.js | 3 ++- tests/lib/rules/max-attributes-per-line.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/rules/max-attributes-per-line.js b/lib/rules/max-attributes-per-line.js index c1a6d0149..2c6b50b3e 100644 --- a/lib/rules/max-attributes-per-line.js +++ b/lib/rules/max-attributes-per-line.js @@ -56,8 +56,9 @@ module.exports = { context.report({ node, loc: node.loc, - message: 'It has more than {{singlelinemMaximum}} attributes per line.', + message: 'There are {{numberOfAttributes}} in this line, but the maximum is {{singlelinemMaximum}}.', data: { + numberOfAttributes, singlelinemMaximum } }) diff --git a/tests/lib/rules/max-attributes-per-line.js b/tests/lib/rules/max-attributes-per-line.js index 189d47a30..0701e414a 100644 --- a/tests/lib/rules/max-attributes-per-line.js +++ b/tests/lib/rules/max-attributes-per-line.js @@ -71,7 +71,7 @@ ruleTester.run('max-attributes-per-line', rule, { invalid: [ { code: ``, - errors: ['It has more than 3 attributes per line.'] + errors: ['There are 4 in this line, but the maximum is 3.'] }, { code: ``, options: [{ singleline: 1, multiline: { max: 1, allowFirstLine: false }}], - errors: ['It has more than 1 attributes per line.'] + errors: ['There are 3 in this line, but the maximum is 1.'] }, { code: `