Skip to content

Commit b9be60b

Browse files
committed
feat: Add no-empty-component-block rule
1 parent b57a273 commit b9be60b

File tree

3 files changed

+277
-0
lines changed

3 files changed

+277
-0
lines changed
+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
pageClass: rule-details
3+
sidebarDepth: 0
4+
title: vue/no-empty-component-block
5+
description: disallow the `<template>` `<script>` `<style>` block to be empty
6+
---
7+
# vue/no-empty-component-block
8+
> disallow the `<template>` `<script>` `<style>` block to be empty
9+
10+
## :book: Rule Details
11+
12+
This rule disallows the `<template>` `<script>` `<style>` block to be empty.
13+
14+
This rule also checks block what has attribute `src`.
15+
See: https://vue-loader.vuejs.org/spec.html#src-imports
16+
17+
<eslint-code-block :rules="{'vue/no-empty-component-block': ['error']}">
18+
19+
```vue
20+
// ✓ GOOD
21+
<template>
22+
<p>foo</p>
23+
</template>
24+
25+
<script>
26+
console.log('foo')
27+
</script>
28+
29+
<style>
30+
p {
31+
display: inline;
32+
}
33+
</style>
34+
35+
<template src="./template.html"></template>
36+
<template src="./template.html" />
37+
38+
<script src="./script.js"></script>
39+
<script src="./script.js" />
40+
41+
<style src="./style.css"></style>
42+
<style src="./style.css" />
43+
44+
45+
// ✗ BAD
46+
<template></template>
47+
<template />
48+
<template src="" />
49+
50+
<script></script>
51+
<script />
52+
<script src="" />
53+
54+
<style></style>
55+
<style />
56+
<style src="" />
57+
```
58+
59+
</eslint-code-block>
60+
61+
## :wrench: Options
62+
63+
Nothing.
64+
65+
## :mag: Implementation
66+
67+
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-empty-component-block.js)
68+
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-empty-component-block.js)

lib/rules/no-empty-component-block.js

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/**
2+
* @author tyankatsu <https://github.com/tyankatsu0105>
3+
* See LICENSE file in root directory for full license.
4+
*/
5+
'use strict'
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
// ------------------------------------------------------------------------------
12+
// Rule Definition
13+
// ------------------------------------------------------------------------------
14+
/**
15+
* check whether has attribute `src`
16+
*/
17+
function hasAttributeSrc(componentBlock) {
18+
const hasAttribute = componentBlock.startTag.attributes.length > 0
19+
20+
const hasSrc =
21+
componentBlock.startTag.attributes.filter(
22+
(attribute) =>
23+
attribute.key.name === 'src' && attribute.value.value !== ''
24+
).length > 0
25+
26+
return hasAttribute && hasSrc
27+
}
28+
29+
module.exports = {
30+
meta: {
31+
type: 'suggestion',
32+
docs: {
33+
description:
34+
'disallow the `<template>` `<script>` `<style>` block to be empty',
35+
categories: undefined,
36+
url: 'https://eslint.vuejs.org/rules/no-empty-component-block.html'
37+
},
38+
fixable: null,
39+
schema: [],
40+
messages: {
41+
unexpected: '`<{{ blockName }}>` is empty. Empty block is not allowed.'
42+
}
43+
},
44+
45+
/**
46+
* @param {RuleContext} context - The rule context.
47+
* @returns {RuleListener} AST event handlers.
48+
*/
49+
create(context) {
50+
return {
51+
Program(node) {
52+
const componentBlocks = node.templateBody.parent.children
53+
54+
for (const componentBlock of componentBlocks) {
55+
if (
56+
componentBlock.name !== 'template' &&
57+
componentBlock.name !== 'script' &&
58+
componentBlock.name !== 'style'
59+
)
60+
return
61+
62+
// https://vue-loader.vuejs.org/spec.html#src-imports
63+
if (hasAttributeSrc(componentBlock)) return
64+
65+
if (componentBlock.children.length === 0) {
66+
context.report({
67+
node: componentBlock,
68+
loc: componentBlock.loc,
69+
messageId: 'unexpected',
70+
data: {
71+
blockName: componentBlock.name
72+
}
73+
})
74+
}
75+
}
76+
}
77+
}
78+
}
79+
}
+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/**
2+
* @author tyankatsu <https://github.com/tyankatsu0105>
3+
*/
4+
'use strict'
5+
6+
const RuleTester = require('eslint').RuleTester
7+
const rule = require('../../../lib/rules/no-empty-component-block')
8+
9+
const tester = new RuleTester({
10+
parser: require.resolve('vue-eslint-parser'),
11+
parserOptions: { ecmaVersion: 2018 }
12+
})
13+
14+
tester.run('no-empty-component-block', rule, {
15+
valid: [
16+
`<template><p>foo</p></template>`,
17+
`<template><p>foo</p></template><script>console.log('foo')</script>`,
18+
`<template><p>foo</p></template><script>console.log('foo')</script><style>p{display: inline;}</style>`,
19+
20+
`<template src="./template.html"></template>`,
21+
`<template src="./template.html" />`,
22+
23+
`<template src="./template.html"></template><script src="./script.js"></script>`,
24+
`<template src="./template.html" /><script src="./script.js" />`,
25+
26+
`<template src="./template.html"></template><script src="./script.js"></script><style src="./style.css"></style>`,
27+
`<template src="./template.html" /><script src="./script.js" /><style src="./style.css" />`
28+
],
29+
invalid: [
30+
{
31+
code: '<template></template>',
32+
errors: [
33+
{
34+
message: '`<template>` is empty. Empty block is not allowed.'
35+
}
36+
]
37+
},
38+
{
39+
code: '<template />',
40+
errors: [
41+
{
42+
message: '`<template>` is empty. Empty block is not allowed.'
43+
}
44+
]
45+
},
46+
{
47+
code: '<template src="" />',
48+
errors: [
49+
{
50+
message: '`<template>` is empty. Empty block is not allowed.'
51+
}
52+
]
53+
},
54+
{
55+
code: '<template></template><script></script>',
56+
errors: [
57+
{
58+
message: '`<template>` is empty. Empty block is not allowed.'
59+
},
60+
{
61+
message: '`<script>` is empty. Empty block is not allowed.'
62+
}
63+
]
64+
},
65+
{
66+
code: '<template /><script />',
67+
errors: [
68+
{
69+
message: '`<template>` is empty. Empty block is not allowed.'
70+
},
71+
{
72+
message: '`<script>` is empty. Empty block is not allowed.'
73+
}
74+
]
75+
},
76+
{
77+
code: '<template src="" /><script src="" />',
78+
errors: [
79+
{
80+
message: '`<template>` is empty. Empty block is not allowed.'
81+
},
82+
{
83+
message: '`<script>` is empty. Empty block is not allowed.'
84+
}
85+
]
86+
},
87+
{
88+
code: '<template></template><script></script><style></style>',
89+
errors: [
90+
{
91+
message: '`<template>` is empty. Empty block is not allowed.'
92+
},
93+
{
94+
message: '`<script>` is empty. Empty block is not allowed.'
95+
},
96+
{
97+
message: '`<style>` is empty. Empty block is not allowed.'
98+
}
99+
]
100+
},
101+
{
102+
code: '<template /><script /><style />',
103+
errors: [
104+
{
105+
message: '`<template>` is empty. Empty block is not allowed.'
106+
},
107+
{
108+
message: '`<script>` is empty. Empty block is not allowed.'
109+
},
110+
{
111+
message: '`<style>` is empty. Empty block is not allowed.'
112+
}
113+
]
114+
},
115+
{
116+
code: '<template src="" /><script src="" /><style src="" />',
117+
errors: [
118+
{
119+
message: '`<template>` is empty. Empty block is not allowed.'
120+
},
121+
{
122+
message: '`<script>` is empty. Empty block is not allowed.'
123+
},
124+
{
125+
message: '`<style>` is empty. Empty block is not allowed.'
126+
}
127+
]
128+
}
129+
]
130+
})

0 commit comments

Comments
 (0)