Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1d966df

Browse files
⭐️New: Add vue/no-static-inline-styles rule
1 parent febc727 commit 1d966df

File tree

5 files changed

+500
-0
lines changed

5 files changed

+500
-0
lines changed

‎docs/rules/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ For example:
154154
| [vue/no-boolean-default](./no-boolean-default.md) | disallow boolean defaults | :wrench: |
155155
| [vue/no-empty-pattern](./no-empty-pattern.md) | disallow empty destructuring patterns | |
156156
| [vue/no-restricted-syntax](./no-restricted-syntax.md) | disallow specified syntax | |
157+
| [vue/no-static-inline-styles](./no-static-inline-styles.md) | disallow static inline `style` attributes | |
157158
| [vue/object-curly-spacing](./object-curly-spacing.md) | enforce consistent spacing inside braces | :wrench: |
158159
| [vue/require-direct-export](./require-direct-export.md) | require the component to be directly exported | |
159160
| [vue/script-indent](./script-indent.md) | enforce consistent indentation in `<script>` | :wrench: |

‎docs/rules/no-static-inline-styles.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
pageClass: rule-details
3+
sidebarDepth: 0
4+
title: vue/no-static-inline-styles
5+
description: disallow static inline `style` attributes
6+
---
7+
# vue/no-static-inline-styles
8+
> disallow static inline `style` attributes
9+
10+
## :book: Rule Details
11+
12+
This rule reports static inline `style` bindings and `style` attributes.
13+
The styles reported in this rule mean that we recommend separating them into `<style>` tag.
14+
15+
<eslint-code-block :rules="{'vue/no-static-inline-styles': ['error']}">
16+
17+
```vue
18+
<template>
19+
<!-- ✓ GOOD -->
20+
<div :style="styleObject"></div>
21+
<div :style="{ backgroundImage: 'url('+img+')' }"></div>
22+
23+
<!-- ✗ BAD -->
24+
<div style="color: pink;"></div>
25+
<div :style="{ color: 'pink' }"></div>
26+
<div :style="[ { color: 'pink' }, { 'font-size': '85%' } ]"></div>
27+
<div :style="{ backgroundImage, color: 'pink' }"></div>
28+
</template>
29+
```
30+
31+
</eslint-code-block>
32+
33+
## :wrench: Options
34+
35+
```json
36+
{
37+
"vue/no-static-inline-styles": ["error", {
38+
"allowBinding": false
39+
}]
40+
}
41+
```
42+
43+
- allowBinding ... if `true`, allow binding static inline `style`. default `false`.
44+
45+
### `"allowBinding": true`
46+
47+
<eslint-code-block :rules="{'vue/no-static-inline-styles': ['error', {'allowBinding': true}]}">
48+
49+
```vue
50+
<template>
51+
<!-- ✓ GOOD -->
52+
<div :style="{ transform: 'scale(0.5)' }"></div>
53+
<div :style="[ { transform: 'scale(0.5)' }, { 'user-select': 'none' } ]"></div>
54+
55+
<!-- ✗ BAD -->
56+
<div style="transform: scale(0.5);"></div>
57+
</template>
58+
```
59+
60+
</eslint-code-block>
61+
62+
## :books: Further reading
63+
64+
- [Guide - Binding Inline Styles](https://vuejs.org/v2/guide/class-and-style.html#Binding-Inline-Styles)
65+
66+
## :mag: Implementation
67+
68+
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-static-inline-styles.js)
69+
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-static-inline-styles.js)

‎lib/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ module.exports = {
4646
'no-shared-component-data': require('./rules/no-shared-component-data'),
4747
'no-side-effects-in-computed-properties': require('./rules/no-side-effects-in-computed-properties'),
4848
'no-spaces-around-equal-signs-in-attribute': require('./rules/no-spaces-around-equal-signs-in-attribute'),
49+
'no-static-inline-styles': require('./rules/no-static-inline-styles'),
4950
'no-template-key': require('./rules/no-template-key'),
5051
'no-template-shadow': require('./rules/no-template-shadow'),
5152
'no-textarea-mustache': require('./rules/no-textarea-mustache'),

‎lib/rules/no-static-inline-styles.js

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/**
2+
* @author Yosuke Ota
3+
* See LICENSE file in root directory for full license.
4+
*/
5+
'use strict'
6+
7+
const utils = require('../utils')
8+
module.exports = {
9+
meta: {
10+
type: 'suggestion',
11+
docs: {
12+
description: 'disallow static inline `style` attributes',
13+
category: undefined,
14+
url: 'https://eslint.vuejs.org/rules/no-static-inline-styles.html'
15+
},
16+
fixable: null,
17+
schema: [
18+
{
19+
type: 'object',
20+
properties: {
21+
allowBinding: {
22+
type: 'boolean'
23+
}
24+
},
25+
additionalProperties: false
26+
}
27+
],
28+
messages: {
29+
forbiddenStaticInlineStyle: 'Static inline `style` are forbidden.',
30+
forbiddenStyleAttr: '`style` attributes are forbidden.'
31+
}
32+
},
33+
create (context) {
34+
/**
35+
* Checks whether if the given property node is a static value.
36+
* @param {AssignmentProperty} prop property node to check
37+
* @returns {boolean} `true` if the given property node is a static value.
38+
*/
39+
function isStaticValue (prop) {
40+
return (
41+
!prop.computed &&
42+
prop.value.type === 'Literal' &&
43+
(prop.key.type === 'Identifier' || prop.key.type === 'Literal')
44+
)
45+
}
46+
47+
/**
48+
* Gets the static properties of a given expression node.
49+
* - If `SpreadElement` or computed property exists, it gets only the static properties before it.
50+
* `:style="{ color: 'red', display: 'flex', ...spread, width: '16px' }"`
51+
* ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
52+
* - If non-static object exists, it gets only the static properties up to that object.
53+
* `:style="[ { color: 'red' }, { display: 'flex', color, width: '16px' }, { height: '16px' } ]"`
54+
* ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
55+
* - If all properties are static properties, it returns one root node.
56+
* `:style="[ { color: 'red' }, { display: 'flex', width: '16px' } ]"`
57+
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
58+
* @param {VAttribute} node `:style` node to check
59+
* @returns {AssignmentProperty[] | [VAttribute]} the static properties.
60+
*/
61+
function getReportNodes (node) {
62+
const { value } = node
63+
if (!value) {
64+
return []
65+
}
66+
const { expression } = value
67+
if (!expression) {
68+
return []
69+
}
70+
71+
let elements
72+
if (expression.type === 'ObjectExpression') {
73+
elements = [expression]
74+
} else if (expression.type === 'ArrayExpression') {
75+
elements = expression.elements
76+
} else {
77+
return []
78+
}
79+
const staticProperties = []
80+
for (const element of elements) {
81+
if (!element) {
82+
continue
83+
}
84+
if (element.type !== 'ObjectExpression') {
85+
return staticProperties
86+
}
87+
88+
let isAllStatic = true
89+
for (const prop of element.properties) {
90+
if (prop.type === 'SpreadElement' || prop.computed) {
91+
// If `SpreadElement` or computed property exists, it gets only the static properties before it.
92+
return staticProperties
93+
}
94+
if (isStaticValue(prop)) {
95+
staticProperties.push(prop)
96+
} else {
97+
isAllStatic = false
98+
}
99+
}
100+
if (!isAllStatic) {
101+
// If non-static object exists, it gets only the static properties up to that object.
102+
return staticProperties
103+
}
104+
}
105+
// If all properties are static properties, it returns one root node.
106+
return [node]
107+
}
108+
109+
/**
110+
* Reports if the value is static.
111+
* @param {VAttribute} node `:style` node to check
112+
*/
113+
function verifyVBindStyle (node) {
114+
for (const n of getReportNodes(node)) {
115+
context.report({
116+
node: n,
117+
messageId: 'forbiddenStaticInlineStyle'
118+
})
119+
}
120+
}
121+
122+
const visitor = {
123+
"VAttribute[directive=false][key.name='style']" (node) {
124+
context.report({
125+
node,
126+
messageId: 'forbiddenStyleAttr'
127+
})
128+
}
129+
}
130+
if (!context.options[0] || !context.options[0].allowBinding) {
131+
visitor[
132+
"VAttribute[directive=true][key.name.name='bind'][key.argument.name='style']"
133+
] = verifyVBindStyle
134+
}
135+
136+
return utils.defineTemplateBodyVisitor(context, visitor)
137+
}
138+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /