Skip to content

Commit

Permalink
feat(v-on-handler-style): add allowInlineFuncSingleArg option
Browse files Browse the repository at this point in the history
  • Loading branch information
ByScripts committed Jun 8, 2024
1 parent 769b09f commit 91da522
Show file tree
Hide file tree
Showing 3 changed files with 255 additions and 46 deletions.
38 changes: 37 additions & 1 deletion docs/rules/v-on-handler-style.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -126,24 +127,59 @@ This rule aims to enforce a consistent style in `v-on` event handlers:

<eslint-code-block fix :rules="{'vue/v-on-handler-style': ['error', ['inline', 'inline-function']]}">

```vue
<template>
<!-- ✓ GOOD -->
<button v-on:click="count++" />
<button v-on:click="handler()" />
<button v-on:click="handler($event)" />
<button v-on:click="(arg1, arg2) => handler(arg1, arg2)" />
<template v-for="e in list">
<button v-on:click="handler(e)" />
<button v-on:click="handler($event, e)" />
<button v-on:click="(arg1, arg2) => handler(arg1, arg2, e)" />
</template>
<!-- ✗ BAD -->
<button v-on:click="() => count++" />
<button v-on:click="handler" />
<button v-on:click="() => handler()" />
<button v-on:click="(arg) => handler(arg)" />
<template v-for="e in list">
<button v-on:click="() => handler(e)" />
<button v-on:click="(arg) => handler(arg, e)" />
</template>
</template>
```

</eslint-code-block>

### `["inline", "inline-function"]` with `allowInlineFuncSingleArg: true`

<eslint-code-block fix :rules="{'vue/v-on-handler-style': ['error', ['inline', 'inline-function'], { allowInlineFuncSingleArg: true }]}">

```vue
<template>
<!-- ✓ GOOD -->
<button v-on:click="count++" />
<button v-on:click="handler()" />
<button v-on:click="handler($event)" />
<button v-on:click="(arg) => handler(arg)" />
<button v-on:click="(arg1, arg2) => handler(arg1, arg2)" />
<template v-for="e in list">
<button v-on:click="handler(e)" />
<button v-on:click="handler($event, e)" />
<button v-on:click="(arg) => handler(arg, e)" />
<button v-on:click="(arg1, arg2) => handler(arg1, arg2, e)" />
</template>
<!-- ✗ BAD -->
<button v-on:click="() => count++" />
<button v-on:click="handler" />
<button v-on:click="() => handler()" />
<button v-on:click="() => handler($event)" />
<template v-for="e in list">
<button v-on:click="() => handler(e)" />
</template>
</template>
```

Expand Down
128 changes: 86 additions & 42 deletions lib/rules/v-on-handler-style.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const utils = require('../utils')
* @typedef {'method' | 'inline' | 'inline-function'} HandlerKind
* @typedef {object} ObjectOption
* @property {boolean} [ignoreIncludesComment]
* @property {boolean} [allowInlineFuncSingleArg]
*/

/**
Expand All @@ -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 }
}

/**
Expand Down Expand Up @@ -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.',
Expand All @@ -170,7 +204,8 @@ module.exports = {
},
/** @param {RuleContext} context */
create(context) {
const { allows, ignoreIncludesComment } = parseOptions(context)
const { allows, ignoreIncludesComment, allowInlineFuncSingleArg } =
parseOptions(context)

/** @type {Set<VElement>} */
const upperElements = new Set()
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 91da522

Please sign in to comment.