From 769b09f5b29fd438a60998ea8fb4035f18376fa7 Mon Sep 17 00:00:00 2001 From: Thierry Date: Thu, 6 Jun 2024 16:16:02 +0200 Subject: [PATCH 1/2] feat(v-on-handler-style): allow `["inline", "inline-function"]` option --- docs/rules/v-on-handler-style.md | 30 +++++++++++- lib/rules/v-on-handler-style.js | 15 +++++- tests/lib/rules/v-on-handler-style.js | 67 +++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 2 deletions(-) diff --git a/docs/rules/v-on-handler-style.md b/docs/rules/v-on-handler-style.md index 039577494..d88a3e043 100644 --- a/docs/rules/v-on-handler-style.md +++ b/docs/rules/v-on-handler-style.md @@ -47,7 +47,7 @@ This rule aims to enforce a consistent style in `v-on` event handlers: ```json { "vue/v-on-handler-style": ["error", - ["method", "inline-function"], // ["method", "inline-function"] | ["method", "inline"] | "inline-function" | "inline" + ["method", "inline-function"], // ["method", "inline-function"] | ["method", "inline"] | ["inline", "inline-function"] | "inline-function" | "inline" { "ignoreIncludesComment": false } @@ -58,6 +58,7 @@ This rule aims to enforce a consistent style in `v-on` event handlers: - First option ... Specifies the name of an allowed style. Default is `["method", "inline-function"]`. - `["method", "inline-function"]` ... Allow handlers by method binding. e.g. `v-on:click="handler"`. Allow inline functions where method handlers cannot be used. e.g. `v-on:click="() => handler(listItem)"`. - `["method", "inline"]` ... Allow handlers by method binding. e.g. `v-on:click="handler"`. Allow inline handlers where method handlers cannot be used. e.g. `v-on:click="handler(listItem)"`. + - `["inline", "inline-function"]` ... Allow inline handlers. e.g. `v-on:click="handler()"`. Allow inline functions if they have at least 1 argument. e.g. `v-on:click="(arg1, arg2) => handler(arg1, arg2)"`. - `"inline-function"` ... Allow inline functions. e.g. `v-on:click="() => handler()"` - `"inline"` ... Allow inline handlers. e.g. `v-on:click="handler()"` - Second option @@ -121,6 +122,33 @@ This rule aims to enforce a consistent style in `v-on` event handlers: +### `["inline", "inline-function"]` + + + +```vue + +``` + + + ### `"inline-function"` diff --git a/lib/rules/v-on-handler-style.js b/lib/rules/v-on-handler-style.js index 10ff9b6b1..de09a89a4 100644 --- a/lib/rules/v-on-handler-style.js +++ b/lib/rules/v-on-handler-style.js @@ -126,6 +126,14 @@ module.exports = { additionalItems: false, minItems: 2, maxItems: 2 + }, + { + type: 'array', + items: [{ const: 'inline' }, { const: 'inline-function' }], + uniqueItems: true, + additionalItems: false, + minItems: 2, + maxItems: 2 } ] }, @@ -527,7 +535,12 @@ module.exports = { case 'ArrowFunctionExpression': case 'FunctionExpression': { // e.g. v-on:click="()=>foo()" - if (allows[0] === 'inline-function') { + if ( + allows[0] === 'inline-function' || + (allows[0] === 'inline' && + allows[1] === 'inline-function' && + expression.params.length > 0) + ) { return } for (const allow of allows) { diff --git a/tests/lib/rules/v-on-handler-style.js b/tests/lib/rules/v-on-handler-style.js index a169402f7..ed854eed1 100644 --- a/tests/lib/rules/v-on-handler-style.js +++ b/tests/lib/rules/v-on-handler-style.js @@ -71,6 +71,23 @@ tester.run('v-on-handler-style', rule, { { filename: 'test.vue', code: '' + }, + { + filename: 'test.vue', + code: ``, + options: [['inline', 'inline-function']] } ], invalid: [ @@ -1136,6 +1153,56 @@ tester.run('v-on-handler-style', rule, { column: 25 } ] + }, + // ['inline', 'inline-function'] + { + filename: 'test.vue', + code: ``, + output: ``, + options: [['inline', 'inline-function']], + errors: [ + { + message: 'Prefer inline handler over inline function in v-on.', + line: 2, + column: 25 + }, + { + message: 'Prefer inline handler over method handler in v-on.', + line: 3, + column: 25 + }, + { + message: 'Prefer inline handler over inline function in v-on.', + line: 4, + column: 25 + }, + { + message: 'Prefer inline handler over inline function in v-on.', + line: 5, + column: 25 + }, + { + message: 'Prefer inline handler over inline function in v-on.', + line: 7, + column: 27 + } + ] } ] }) From 91da52239f01f12e991c82abe4d06d6bf75dc945 Mon Sep 17 00:00:00 2001 From: Thierry Date: Sat, 8 Jun 2024 12:30:20 +0200 Subject: [PATCH 2/2] feat(v-on-handler-style): add `allowInlineFuncSingleArg` option --- docs/rules/v-on-handler-style.md | 38 +++++++- lib/rules/v-on-handler-style.js | 128 ++++++++++++++++-------- tests/lib/rules/v-on-handler-style.js | 135 +++++++++++++++++++++++++- 3 files changed, 255 insertions(+), 46 deletions(-) diff --git a/docs/rules/v-on-handler-style.md b/docs/rules/v-on-handler-style.md index d88a3e043..4fd1d3dae 100644 --- a/docs/rules/v-on-handler-style.md +++ b/docs/rules/v-on-handler-style.md @@ -63,6 +63,7 @@ This rule aims to enforce a consistent style in `v-on` event handlers: - `"inline"` ... Allow inline handlers. e.g. `v-on:click="handler()"` - Second option - `ignoreIncludesComment` ... If `true`, do not report inline handlers or inline functions containing comments, even if the preferred style is `"method"`. Default is `false`. + - `allowInlineFuncSingleArg` ... Used in conjunction with `["method", "inline-function"]` or `["inline", "inline-function"]`. If `true`, allow inline functions with a single argument. Default is `false`. ### `["method", "inline-function"]` (Default) @@ -126,6 +127,37 @@ This rule aims to enforce a consistent style in `v-on` event handlers: +```vue + +``` + + + +### `["inline", "inline-function"]` with `allowInlineFuncSingleArg: true` + + + ```vue ``` diff --git a/lib/rules/v-on-handler-style.js b/lib/rules/v-on-handler-style.js index de09a89a4..d5f98574a 100644 --- a/lib/rules/v-on-handler-style.js +++ b/lib/rules/v-on-handler-style.js @@ -11,6 +11,7 @@ const utils = require('../utils') * @typedef {'method' | 'inline' | 'inline-function'} HandlerKind * @typedef {object} ObjectOption * @property {boolean} [ignoreIncludesComment] + * @property {boolean} [allowInlineFuncSingleArg] */ /** @@ -33,8 +34,9 @@ function parseOptions(context) { const option = options[1] || {} const ignoreIncludesComment = !!option.ignoreIncludesComment + const allowInlineFuncSingleArg = option.allowInlineFuncSingleArg === true - return { allows, ignoreIncludesComment } + return { allows, ignoreIncludesComment, allowInlineFuncSingleArg } } /** @@ -112,41 +114,73 @@ module.exports = { url: 'https://eslint.vuejs.org/rules/v-on-handler-style.html' }, fixable: 'code', - schema: [ - { - oneOf: [ - { enum: ['inline', 'inline-function'] }, - { - type: 'array', - items: [ - { const: 'method' }, - { enum: ['inline', 'inline-function'] } - ], - uniqueItems: true, - additionalItems: false, - minItems: 2, - maxItems: 2 - }, - { - type: 'array', - items: [{ const: 'inline' }, { const: 'inline-function' }], - uniqueItems: true, - additionalItems: false, - minItems: 2, - maxItems: 2 - } - ] - }, - { - type: 'object', - properties: { - ignoreIncludesComment: { - type: 'boolean' - } + schema: { + anyOf: [ + // `inline`, `inline-function` or `['method', 'inline']` + { + type: 'array', + items: [ + { + anyOf: [ + { enum: ['inline', 'inline-function'] }, + { + type: 'array', + items: [{ const: 'method' }, { const: 'inline' }], + uniqueItems: true, + additionalItems: false, + minItems: 2, + maxItems: 2 + } + ] + }, + { + type: 'object', + properties: { + ignoreIncludesComment: { + type: 'boolean' + } + }, + additionalProperties: false + } + ], + additionalItems: false, + minItems: 1, + maxItems: 2 }, - additionalProperties: false - } - ], + // `['method', 'inline-function']` or `['inline', 'inline-function']` + { + type: 'array', + items: [ + { + type: 'array', + items: [ + { enum: ['method', 'inline'] }, + { const: 'inline-function' } + ], + uniqueItems: true, + additionalItems: false, + minItems: 2, + maxItems: 2 + }, + { + type: 'object', + properties: { + ignoreIncludesComment: { + type: 'boolean' + }, + allowInlineFuncSingleArg: { + type: 'boolean' + } + }, + additionalProperties: false + } + ], + additionalItems: false, + minItems: 0, + maxItems: 2 + } + ] + }, messages: { preferMethodOverInline: 'Prefer method handler over inline handler in v-on.', @@ -170,7 +204,8 @@ module.exports = { }, /** @param {RuleContext} context */ create(context) { - const { allows, ignoreIncludesComment } = parseOptions(context) + const { allows, ignoreIncludesComment, allowInlineFuncSingleArg } = + parseOptions(context) /** @type {Set} */ const upperElements = new Set() @@ -535,14 +570,23 @@ module.exports = { case 'ArrowFunctionExpression': case 'FunctionExpression': { // e.g. v-on:click="()=>foo()" - if ( - allows[0] === 'inline-function' || - (allows[0] === 'inline' && - allows[1] === 'inline-function' && - expression.params.length > 0) - ) { + if (allows[0] === 'inline-function') { return } + + if (allows[1] === 'inline-function') { + if (expression.params.length > 1) { + return + } + + if ( + expression.params.length === 1 && + allowInlineFuncSingleArg + ) { + return + } + } + for (const allow of allows) { if (verifyForInlineFunction(expression, allow)) { return diff --git a/tests/lib/rules/v-on-handler-style.js b/tests/lib/rules/v-on-handler-style.js index ed854eed1..55d6423fb 100644 --- a/tests/lib/rules/v-on-handler-style.js +++ b/tests/lib/rules/v-on-handler-style.js @@ -72,6 +72,21 @@ tester.run('v-on-handler-style', rule, { filename: 'test.vue', code: '' }, + { + filename: 'test.vue', + code: ``, + options: [['inline', 'inline-function']] + }, { filename: 'test.vue', code: ` `, - options: [['inline', 'inline-function']] + options: [ + ['inline', 'inline-function'], + { allowInlineFuncSingleArg: true } + ] } ], invalid: [ @@ -208,6 +226,30 @@ tester.run('v-on-handler-style', rule, { } ] }, + { + filename: 'test.vue', + code: ``, + output: ``, + options: [['method', 'inline-function']], + errors: [ + { + message: 'Prefer method handler over inline function in v-on.', + line: 2, + column: 22 + }, + { + message: 'Prefer method handler over inline function in v-on.', + line: 3, + column: 22 + } + ] + }, { filename: 'test.vue', code: ``, + output: ``, + options: [['inline', 'inline-function']], + errors: [ + { + message: 'Prefer inline handler over inline function in v-on.', + line: 2, + column: 25 + }, + { + message: 'Prefer inline handler over method handler in v-on.', + line: 3, + column: 25 + }, + { + message: 'Prefer inline handler over inline function in v-on.', + line: 4, + column: 25 + }, + { + message: 'Prefer inline handler over inline function in v-on.', + line: 5, + column: 25 + }, + { + message: 'Prefer inline handler over inline function in v-on.', + line: 6, + column: 25 + }, + { + message: 'Prefer inline handler over inline function in v-on.', + line: 8, + column: 27 + } + ] + }, + // ['inline', 'inline-function'] + allowInlineFuncSingleArg + { + filename: 'test.vue', + code: ``, output: ``, - options: [['inline', 'inline-function']], + options: [ + ['inline', 'inline-function'], + { allowInlineFuncSingleArg: true } + ], errors: [ { message: 'Prefer inline handler over inline function in v-on.', @@ -1199,10 +1305,33 @@ tester.run('v-on-handler-style', rule, { }, { message: 'Prefer inline handler over inline function in v-on.', - line: 7, + line: 8, column: 27 } ] + }, + // ['method', 'inline-function'] + allowInlineFuncSingleArg + { + filename: 'test.vue', + code: ``, + output: ``, + options: [ + ['method', 'inline-function'], + { allowInlineFuncSingleArg: true } + ], + errors: [ + { + message: 'Prefer method handler over inline function in v-on.', + line: 2, + column: 22 + } + ] } ] })