Skip to content

Commit d22cb94

Browse files
committed
Update vue/no-unused-properties and vue/script-setup-uses-vars rule to support style CSS vars
1 parent 9dc78d0 commit d22cb94

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
@@ -1056,6 +1057,15 @@ module.exports = {
10561057
{
10571058
/** @param {Program} node */
10581059
'Program:exit'(node) {
1060+
const styleVars = getStyleVariablesContext(context)
1061+
if (styleVars) {
1062+
for (const { id } of styleVars.references) {
1063+
templatePropertiesContainer.usedProperties.addUsed(
1064+
id.name,
1065+
(context) => extractPatternOrThisProperties(id, context, true)
1066+
)
1067+
}
1068+
}
10591069
if (!node.templateBody) {
10601070
reportUnusedProperties()
10611071
}

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
@@ -1562,6 +1562,38 @@ tester.run('no-unused-properties', rule, {
15621562
}
15631563
</script>`,
15641564
options: allOptions
1565+
},
1566+
1567+
//style vars
1568+
{
1569+
filename: 'test.vue',
1570+
code: `
1571+
<template>
1572+
<div class="text">hello</div>
1573+
</template>
1574+
1575+
<script>
1576+
export default {
1577+
data() {
1578+
return {
1579+
color: 'red',
1580+
font: {
1581+
size: '2em',
1582+
},
1583+
}
1584+
},
1585+
}
1586+
</script>
1587+
1588+
<style>
1589+
.text {
1590+
color: v-bind(color);
1591+
1592+
/* expressions (wrap in quotes) */
1593+
font-size: v-bind('font.size');
1594+
}
1595+
</style>
1596+
`
15651597
}
15661598
],
15671599

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)