Skip to content

Commit

Permalink
Add allowModifiers option to valid-v-slot (#1330)
Browse files Browse the repository at this point in the history
* add allowModifiers option to valid-v-slot

* update doc

* fix for missing cases & improve code

* add test cases

* revert option in test
  • Loading branch information
nokazn committed Oct 18, 2020
1 parent 9932d13 commit 0e1a05a
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 7 deletions.
38 changes: 37 additions & 1 deletion docs/rules/valid-v-slot.md
Expand Up @@ -100,7 +100,43 @@ This rule does not check syntax errors in directives because it's checked by [vu

## :wrench: Options

Nothing.
```json
{
"vue/valid-v-slot": ["error", {
"allowModifiers": false
}]
}
```

- `allowModifiers` (`boolean`) ... allows having modifiers in the argument of `v-slot` directives. Modifiers just after `v-slot` are still disallowed. E.g. `<template v-slot.foo>` default `false`.

### `allowModifiers: true`

<eslint-code-block :rules="{'vue/valid-v-slot': ['error', {allowModifiers: true}]}">

```vue
<template>
<!-- ignore -->
<MyComponent>
<template v-slot:foo></template>
<template v-slot:foo.bar></template>
<template v-slot:foo.baz></template>
<template v-slot:foo.bar.baz></template>
</MyComponent>
<!-- ✗ BAD */ -->
<MyComponent v-slot.foo="{data}">
{{ data }}
</MyComponent>
<MyComponent>
<template v-slot.foo>
bar
</template>
</MyComponent>
</template>
```

</eslint-code-block>

## :couple: Related Rules

Expand Down
40 changes: 34 additions & 6 deletions lib/rules/valid-v-slot.js
Expand Up @@ -75,15 +75,18 @@ function getSlotDirectivesOnChildren(node) {
}

/**
* Get the normalized name of a given `v-slot` directive node.
* Get the normalized name of a given `v-slot` directive node with modifiers after `v-slot:` directive.
* @param {VDirective} node The `v-slot` directive node.
* @param {SourceCode} sourceCode The source code.
* @returns {string} The normalized name.
*/
function getNormalizedName(node, sourceCode) {
return node.key.argument == null
? 'default'
: sourceCode.getText(node.key.argument)
if (node.key.argument == null) {
return 'default'
}
return node.key.modifiers.length === 0
? sourceCode.getText(node.key.argument)
: sourceCode.text.slice(node.key.argument.range[0], node.key.range[1])
}

/**
Expand Down Expand Up @@ -150,6 +153,19 @@ function isUsingScopeVar(vSlot) {
return false
}

/**
* If `allowModifiers` option is set to `true`, check whether a given argument node has invalid modifiers like `v-slot.foo`.
* Otherwise, check whether a given argument node has at least one modifier.
* @param {VDirective} vSlot The `v-slot` directive to check.
* @param {boolean} allowModifiers `allowModifiers` option in context.
* @return {boolean} `true` if that argument node has invalid modifiers like `v-slot.foo`.
*/
function hasInvalidModifiers(vSlot, allowModifiers) {
return allowModifiers
? vSlot.key.argument == null && vSlot.key.modifiers.length >= 1
: vSlot.key.modifiers.length >= 1
}

module.exports = {
meta: {
type: 'problem',
Expand All @@ -159,7 +175,16 @@ module.exports = {
url: 'https://eslint.vuejs.org/rules/valid-v-slot.html'
},
fixable: null,
schema: [],
schema: [
{
type: 'object',
properties: {
allowModifiers: {
type: 'boolean'
}
}
}
],
messages: {
ownerMustBeCustomElement:
"'v-slot' directive must be owned by a custom element, but '{{name}}' is not.",
Expand All @@ -181,6 +206,8 @@ module.exports = {
/** @param {RuleContext} context */
create(context) {
const sourceCode = context.getSourceCode()
const options = context.options[0] || {}
const allowModifiers = options.allowModifiers === true

return utils.defineTemplateBodyVisitor(context, {
/** @param {VDirective} node */
Expand Down Expand Up @@ -264,7 +291,8 @@ module.exports = {
}

// Verify modifiers.
if (node.key.modifiers.length >= 1) {
if (hasInvalidModifiers(node, allowModifiers)) {
// E.g., <template v-slot.foo>
context.report({
node,
messageId: 'disallowAnyModifier'
Expand Down
85 changes: 85 additions & 0 deletions tests/lib/rules/valid-v-slot.js
Expand Up @@ -84,6 +84,29 @@ tester.run('valid-v-slot', rule, {
<template v-for="(key, value) in xxxx" #[key]>{{value}}</template>
</MyComponent>
</template>`,
{
code: `
<template>
<MyComponent>
<template v-slot:foo.bar></template>
</MyComponent>
</template>
`,
options: [{ allowModifiers: true }]
},
{
code: `
<template>
<MyComponent>
<template v-slot:foo></template>
<template v-slot:foo.bar></template>
<template v-slot:foo.baz></template>
<template v-slot:foo.bar.baz></template>
</MyComponent>
</template>
`,
options: [{ allowModifiers: true }]
},
// parsing error
{
filename: 'parsing-error.vue',
Expand Down Expand Up @@ -259,6 +282,18 @@ tester.run('valid-v-slot', rule, {
`,
errors: [{ messageId: 'disallowDuplicateSlotsOnChildren' }]
},
{
code: `
<template>
<MyComponent>
<template v-slot:foo.bar></template>
<template v-slot:foo.bar></template>
</MyComponent>
</template>
`,
options: [{ allowModifiers: true }],
errors: [{ messageId: 'disallowDuplicateSlotsOnChildren' }]
},

// Verify arguments.
{
Expand Down Expand Up @@ -291,6 +326,56 @@ tester.run('valid-v-slot', rule, {
`,
errors: [{ messageId: 'disallowAnyModifier' }]
},
{
code: `
<template>
<MyComponent>
<template v-slot:foo.bar></template>
</MyComponent>
</template>
`,
errors: [{ messageId: 'disallowAnyModifier' }]
},
{
code: `
<template>
<MyComponent>
<template v-slot.foo></template>
</MyComponent>
</template>
`,
errors: [{ messageId: 'disallowAnyModifier' }],
options: [{ allowModifiers: true }]
},
{
code: `
<template>
<MyComponent>
<template v-slot:foo.bar></template>
</MyComponent>
</template>
`,
errors: [{ messageId: 'disallowAnyModifier' }],
options: [{ allowModifiers: false }]
},
{
code: `
<template>
<MyComponent>
<template v-slot:foo></template>
<template v-slot:foo.bar></template>
<template v-slot:foo.baz></template>
<template v-slot:foo.bar.baz></template>
</MyComponent>
</template>
`,
options: [{ allowModifiers: false }],
errors: [
{ messageId: 'disallowAnyModifier' },
{ messageId: 'disallowAnyModifier' },
{ messageId: 'disallowAnyModifier' }
]
},

// Verify value.
{
Expand Down

0 comments on commit 0e1a05a

Please sign in to comment.