Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(no-empty-component-block): support auto fix #2595

Merged
merged 13 commits into from
Nov 11, 2024
2 changes: 1 addition & 1 deletion docs/rules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ For example:
| [vue/no-deprecated-delete-set](./no-deprecated-delete-set.md) | disallow using deprecated `$delete` and `$set` (in Vue.js 3.0.0+) | | :warning: |
| [vue/no-deprecated-model-definition](./no-deprecated-model-definition.md) | disallow deprecated `model` definition (in Vue.js 3.0.0+) | :bulb: | :warning: |
| [vue/no-duplicate-attr-inheritance](./no-duplicate-attr-inheritance.md) | enforce `inheritAttrs` to be set to `false` when using `v-bind="$attrs"` | | :hammer: |
| [vue/no-empty-component-block](./no-empty-component-block.md) | disallow the `<template>` `<script>` `<style>` block to be empty | | :hammer: |
| [vue/no-empty-component-block](./no-empty-component-block.md) | disallow the `<template>` `<script>` `<style>` block to be empty | :wrench: | :hammer: |
| [vue/no-multiple-objects-in-class](./no-multiple-objects-in-class.md) | disallow to pass multiple objects into array to class | | :hammer: |
| [vue/no-potential-component-option-typo](./no-potential-component-option-typo.md) | disallow a potential typo in your component property | :bulb: | :hammer: |
| [vue/no-ref-object-reactivity-loss](./no-ref-object-reactivity-loss.md) | disallow usages of ref objects that can lead to loss of reactivity | | :warning: |
Expand Down
14 changes: 12 additions & 2 deletions docs/rules/no-empty-component-block.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ since: v7.0.0

> disallow the `<template>` `<script>` `<style>` block to be empty

- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.

## :book: Rule Details

This rule disallows the `<template>` `<script>` `<style>` block to be empty.

This rule also checks block what has attribute `src`.
See [Vue Single-File Component (SFC) Spec](https://vue-loader.vuejs.org/spec.html#src-imports).

<eslint-code-block :rules="{'vue/no-empty-component-block': ['error']}">
<eslint-code-block fix :rules="{'vue/no-empty-component-block': ['error', { autofix: true }]}">

```vue
<!-- ✓ GOOD -->
Expand Down Expand Up @@ -62,7 +64,15 @@ p {

## :wrench: Options

Nothing.
```json
{
"vue/no-duplicate-attributes": ["error", {
waynzh marked this conversation as resolved.
Show resolved Hide resolved
"autofix": false,
}]
}
```

- `"autofix"` ... If `true`, enable autofix. (Default: `false`)
FloEdelmann marked this conversation as resolved.
Show resolved Hide resolved

## :rocket: Version

Expand Down
41 changes: 31 additions & 10 deletions lib/rules/no-empty-component-block.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,16 @@ module.exports = {
categories: undefined,
url: 'https://eslint.vuejs.org/rules/no-empty-component-block.html'
},
fixable: null,
schema: [],
fixable: 'code',
schema: [
{
type: 'object',
properties: {
autofix: { type: 'boolean' }
},
additionalProperties: false
}
],
messages: {
unexpected: '`<{{ blockName }}>` is empty. Empty block is not allowed.'
}
Expand All @@ -66,10 +74,16 @@ module.exports = {
return {}
}

const options = context.options[0]
const autofix = options?.autofix === true

const componentBlocks = documentFragment.children.filter(isVElement)

return {
Program() {
/** @type {VElement[]} */
const emptyBlocks = []
FloEdelmann marked this conversation as resolved.
Show resolved Hide resolved

for (const componentBlock of componentBlocks) {
if (
componentBlock.name !== 'template' &&
Expand All @@ -85,16 +99,23 @@ module.exports = {
isValueOnlyWhiteSpacesOrLineBreaks(componentBlock) ||
componentBlock.children.length === 0
) {
context.report({
node: componentBlock,
loc: componentBlock.loc,
messageId: 'unexpected',
data: {
blockName: componentBlock.name
}
})
emptyBlocks.push(componentBlock)
}
}

if (emptyBlocks.length === 0) return

for (const componentBlock of emptyBlocks) {
context.report({
FloEdelmann marked this conversation as resolved.
Show resolved Hide resolved
node: componentBlock,
loc: componentBlock.loc,
messageId: 'unexpected',
data: {
blockName: componentBlock.name
},
fix: autofix ? (fixer) => fixer.remove(componentBlock) : undefined
})
}
}
}
}
Expand Down
106 changes: 105 additions & 1 deletion tests/lib/rules/no-empty-component-block.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,17 @@ tester.run('no-empty-component-block', rule, {
`<template src="./template.html" /><script src="./script.js" />`,
`<template src="./template.html"></template><script src="./script.js"></script><style src="./style.css"></style>`,
`<template src="./template.html" /><script src="./script.js" /><style src="./style.css" />`,
`var a = 1`
`var a = 1`,
// options
{
code: '<template><p>foo</p></template>',
options: [{ autofix: true }]
}
],
invalid: [
{
code: `<template></template>`,
output: null,
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
Expand All @@ -35,6 +41,7 @@ tester.run('no-empty-component-block', rule, {
},
{
code: `<template> </template>`,
output: null,
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
Expand All @@ -44,6 +51,7 @@ tester.run('no-empty-component-block', rule, {
{
code: `<template>
</template>`,
output: null,
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
Expand All @@ -52,6 +60,7 @@ tester.run('no-empty-component-block', rule, {
},
{
code: '<template />',
output: null,
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
Expand All @@ -60,6 +69,7 @@ tester.run('no-empty-component-block', rule, {
},
{
code: '<template src="" />',
output: null,
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
Expand All @@ -68,6 +78,7 @@ tester.run('no-empty-component-block', rule, {
},
{
code: '<template></template><script></script>',
output: null,
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
Expand All @@ -79,6 +90,7 @@ tester.run('no-empty-component-block', rule, {
},
{
code: '<template /><script />',
output: null,
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
Expand All @@ -90,6 +102,7 @@ tester.run('no-empty-component-block', rule, {
},
{
code: '<template src="" /><script src="" />',
output: null,
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
Expand All @@ -101,6 +114,7 @@ tester.run('no-empty-component-block', rule, {
},
{
code: '<template></template><script></script><style></style>',
output: null,
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
Expand All @@ -115,6 +129,7 @@ tester.run('no-empty-component-block', rule, {
},
{
code: '<template /><script /><style />',
output: null,
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
Expand All @@ -129,6 +144,50 @@ tester.run('no-empty-component-block', rule, {
},
{
code: '<template src="" /><script src="" /><style src="" />',
output: null,
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
},
{
message: '`<script>` is empty. Empty block is not allowed.'
},
{
message: '`<style>` is empty. Empty block is not allowed.'
}
]
},
// autofix
{
code: `<template></template>`,
output: '',
options: [{ autofix: true }],
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
}
]
},
{
code: '<template></template><script></script><style></style>',
output: '<script></script>',
options: [{ autofix: true }],
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
},
{
message: '`<script>` is empty. Empty block is not allowed.'
},
{
message: '`<style>` is empty. Empty block is not allowed.'
}
]
},
{
code: '<template></template> <script></script> <style></style>',
output: ' ',
options: [{ autofix: true }],
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
Expand All @@ -140,6 +199,51 @@ tester.run('no-empty-component-block', rule, {
message: '`<style>` is empty. Empty block is not allowed.'
}
]
},
{
code: '<template /> <script /> <style />',
output: ' ',
options: [{ autofix: true }],
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
},
{
message: '`<script>` is empty. Empty block is not allowed.'
},
{
message: '`<style>` is empty. Empty block is not allowed.'
}
]
},
{
code: '<template src="" /> <script src="" /> <style src="" />',
output: ' ',
options: [{ autofix: true }],
errors: [
{
message: '`<template>` is empty. Empty block is not allowed.'
},
{
message: '`<script>` is empty. Empty block is not allowed.'
},
{
message: '`<style>` is empty. Empty block is not allowed.'
}
]
},
{
code: '<template><p></p></template> <script src="" /> <style src="" />',
output: '<template><p></p></template> ',
options: [{ autofix: true }],
errors: [
{
message: '`<script>` is empty. Empty block is not allowed.'
},
{
message: '`<style>` is empty. Empty block is not allowed.'
}
]
}
]
})
Loading