Skip to content

Commit

Permalink
Update vue/no-unused-properties and vue/script-setup-uses-vars ru…
Browse files Browse the repository at this point in the history
…le to support style CSS vars
  • Loading branch information
ota-meshi committed Jul 17, 2021
1 parent 738132c commit c92577a
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 1 deletion.
10 changes: 10 additions & 0 deletions lib/rules/no-unused-properties.js
Expand Up @@ -10,6 +10,7 @@

const utils = require('../utils')
const eslintUtils = require('eslint-utils')
const { getStyleVariablesContext } = require('../utils/style-variables')

/**
* @typedef {import('../utils').GroupName} GroupName
Expand Down Expand Up @@ -1044,6 +1045,15 @@ module.exports = {
{
/** @param {Program} node */
'Program:exit'(node) {
const styleVars = getStyleVariablesContext(context)
if (styleVars) {
for (const { id } of styleVars.references) {
templatePropertiesContainer.usedProperties.addUsed(
id.name,
(context) => extractPatternOrThisProperties(id, context, true)
)
}
}
if (!node.templateBody) {
reportUnusedProperties()
}
Expand Down
12 changes: 11 additions & 1 deletion lib/rules/script-setup-uses-vars.js
Expand Up @@ -4,6 +4,7 @@
*/
'use strict'

const { getStyleVariablesContext } = require('../utils/style-variables')
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
Expand Down Expand Up @@ -112,7 +113,16 @@ module.exports = {
}
}
},
undefined,
{
Program() {
const styleVars = getStyleVariablesContext(context)
if (styleVars) {
for (const ref of styleVars.references) {
context.markVariableAsUsed(ref.id.name)
}
}
}
},
{
templateBodyTriggerSelector: 'Program'
}
Expand Down
58 changes: 58 additions & 0 deletions lib/utils/style-variables/index.js
@@ -0,0 +1,58 @@
const { isVElement } = require('..')

module.exports = {
getStyleVariablesContext
}

class StyleVariablesContext {
/**
* @param {RuleContext} context
* @param {VElement[]} styles
*/
constructor(context, styles) {
this.context = context
this.styles = styles
/** @type {VReference[]} */
this.references = []
for (const style of styles) {
for (const node of style.children) {
if (node.type === 'VExpressionContainer') {
for (const ref of node.references.filter(
(ref) => ref.variable == null
)) {
this.references.push(ref)
}
}
}
}
}
}

/** @type {Map<VElement, StyleVariablesContext} */
const cache = new Map()
/**
* Get the style vars context
* @param {RuleContext} context
* @returns {StyleVariablesContext | null}
*/
function getStyleVariablesContext(context) {
const df =
context.parserServices.getDocumentFragment &&
context.parserServices.getDocumentFragment()
if (!df) {
return null
}
const styles = df.children
.filter(isVElement)
.filter((e) => e.name === 'style')
if (!styles.length) {
return null
}
let ctx = cache.get(styles[0])
if (ctx) {
return ctx
}
ctx = new StyleVariablesContext(context, styles)
cache.set(styles[0], ctx)
return ctx
}
32 changes: 32 additions & 0 deletions tests/lib/rules/no-unused-properties.js
Expand Up @@ -1535,6 +1535,38 @@ tester.run('no-unused-properties', rule, {
ignorePublicMembers: true
}
]
},

//style vars
{
filename: 'test.vue',
code: `
<template>
<div class="text">hello</div>
</template>
<script>
export default {
data() {
return {
color: 'red',
font: {
size: '2em',
},
}
},
}
</script>
<style>
.text {
color: v-bind(color);
/* expressions (wrap in quotes) */
font-size: v-bind('font.size');
}
</style>
`
}
],

Expand Down
40 changes: 40 additions & 0 deletions tests/lib/rules/script-setup-uses-vars.js
Expand Up @@ -179,6 +179,25 @@ describe('script-setup-uses-vars', () => {
<div ref="v"/>
</template>
`
},

//style vars
{
filename: 'test.vue',
code: `
<script setup>
/* eslint script-setup-uses-vars: 1 */
const color = 'red'
const font = { size: '2em' }
</script>
<style>
* {
color: v-bind(color);
font-size: v-bind('font.size');
}
</style>
`
}
],

Expand Down Expand Up @@ -305,6 +324,27 @@ describe('script-setup-uses-vars', () => {
line: 4
}
]
},

//style vars
{
filename: 'test.vue',
code: `
<script setup>
/* eslint script-setup-uses-vars: 1 */
const color = 'red'
</script>
<style>
.v-bind .color {
color: 'v-bind(color)';
background-color: 'v-bind(color)';
}
/* v-bind(color) */
// v-bind(color)
</style>
`,
errors: ["'color' is assigned a value but never used."]
}
]
})
Expand Down

0 comments on commit c92577a

Please sign in to comment.