Skip to content

Commit c92577a

Browse files
committed
Update vue/no-unused-properties and vue/script-setup-uses-vars rule to support style CSS vars
1 parent 738132c commit c92577a

File tree

5 files changed

+151
-1
lines changed

5 files changed

+151
-1
lines changed

lib/rules/no-unused-properties.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
const utils = require('../utils')
1212
const eslintUtils = require('eslint-utils')
13+
const { getStyleVariablesContext } = require('../utils/style-variables')
1314

1415
/**
1516
* @typedef {import('../utils').GroupName} GroupName
@@ -1044,6 +1045,15 @@ module.exports = {
10441045
{
10451046
/** @param {Program} node */
10461047
'Program:exit'(node) {
1048+
const styleVars = getStyleVariablesContext(context)
1049+
if (styleVars) {
1050+
for (const { id } of styleVars.references) {
1051+
templatePropertiesContainer.usedProperties.addUsed(
1052+
id.name,
1053+
(context) => extractPatternOrThisProperties(id, context, true)
1054+
)
1055+
}
1056+
}
10471057
if (!node.templateBody) {
10481058
reportUnusedProperties()
10491059
}

lib/rules/script-setup-uses-vars.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
'use strict'
66

7+
const { getStyleVariablesContext } = require('../utils/style-variables')
78
// ------------------------------------------------------------------------------
89
// Requirements
910
// ------------------------------------------------------------------------------
@@ -112,7 +113,16 @@ module.exports = {
112113
}
113114
}
114115
},
115-
undefined,
116+
{
117+
Program() {
118+
const styleVars = getStyleVariablesContext(context)
119+
if (styleVars) {
120+
for (const ref of styleVars.references) {
121+
context.markVariableAsUsed(ref.id.name)
122+
}
123+
}
124+
}
125+
},
116126
{
117127
templateBodyTriggerSelector: 'Program'
118128
}

lib/utils/style-variables/index.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
const { isVElement } = require('..')
2+
3+
module.exports = {
4+
getStyleVariablesContext
5+
}
6+
7+
class StyleVariablesContext {
8+
/**
9+
* @param {RuleContext} context
10+
* @param {VElement[]} styles
11+
*/
12+
constructor(context, styles) {
13+
this.context = context
14+
this.styles = styles
15+
/** @type {VReference[]} */
16+
this.references = []
17+
for (const style of styles) {
18+
for (const node of style.children) {
19+
if (node.type === 'VExpressionContainer') {
20+
for (const ref of node.references.filter(
21+
(ref) => ref.variable == null
22+
)) {
23+
this.references.push(ref)
24+
}
25+
}
26+
}
27+
}
28+
}
29+
}
30+
31+
/** @type {Map<VElement, StyleVariablesContext} */
32+
const cache = new Map()
33+
/**
34+
* Get the style vars context
35+
* @param {RuleContext} context
36+
* @returns {StyleVariablesContext | null}
37+
*/
38+
function getStyleVariablesContext(context) {
39+
const df =
40+
context.parserServices.getDocumentFragment &&
41+
context.parserServices.getDocumentFragment()
42+
if (!df) {
43+
return null
44+
}
45+
const styles = df.children
46+
.filter(isVElement)
47+
.filter((e) => e.name === 'style')
48+
if (!styles.length) {
49+
return null
50+
}
51+
let ctx = cache.get(styles[0])
52+
if (ctx) {
53+
return ctx
54+
}
55+
ctx = new StyleVariablesContext(context, styles)
56+
cache.set(styles[0], ctx)
57+
return ctx
58+
}

tests/lib/rules/no-unused-properties.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,6 +1535,38 @@ tester.run('no-unused-properties', rule, {
15351535
ignorePublicMembers: true
15361536
}
15371537
]
1538+
},
1539+
1540+
//style vars
1541+
{
1542+
filename: 'test.vue',
1543+
code: `
1544+
<template>
1545+
<div class="text">hello</div>
1546+
</template>
1547+
1548+
<script>
1549+
export default {
1550+
data() {
1551+
return {
1552+
color: 'red',
1553+
font: {
1554+
size: '2em',
1555+
},
1556+
}
1557+
},
1558+
}
1559+
</script>
1560+
1561+
<style>
1562+
.text {
1563+
color: v-bind(color);
1564+
1565+
/* expressions (wrap in quotes) */
1566+
font-size: v-bind('font.size');
1567+
}
1568+
</style>
1569+
`
15381570
}
15391571
],
15401572

tests/lib/rules/script-setup-uses-vars.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,25 @@ describe('script-setup-uses-vars', () => {
179179
<div ref="v"/>
180180
</template>
181181
`
182+
},
183+
184+
//style vars
185+
{
186+
filename: 'test.vue',
187+
code: `
188+
<script setup>
189+
/* eslint script-setup-uses-vars: 1 */
190+
const color = 'red'
191+
const font = { size: '2em' }
192+
</script>
193+
194+
<style>
195+
* {
196+
color: v-bind(color);
197+
font-size: v-bind('font.size');
198+
}
199+
</style>
200+
`
182201
}
183202
],
184203

@@ -305,6 +324,27 @@ describe('script-setup-uses-vars', () => {
305324
line: 4
306325
}
307326
]
327+
},
328+
329+
//style vars
330+
{
331+
filename: 'test.vue',
332+
code: `
333+
<script setup>
334+
/* eslint script-setup-uses-vars: 1 */
335+
const color = 'red'
336+
</script>
337+
338+
<style>
339+
.v-bind .color {
340+
color: 'v-bind(color)';
341+
background-color: 'v-bind(color)';
342+
}
343+
/* v-bind(color) */
344+
// v-bind(color)
345+
</style>
346+
`,
347+
errors: ["'color' is assigned a value but never used."]
308348
}
309349
]
310350
})

0 commit comments

Comments
 (0)