refactor: only rewrite css varaiable in <style scoped>
when vars is present
This commit is contained in:
parent
f3cc41f0c8
commit
73bfce3706
@ -1,15 +1,23 @@
|
||||
import { compileStyle, compileStyleAsync } from '../src/compileStyle'
|
||||
import {
|
||||
compileStyle,
|
||||
compileStyleAsync,
|
||||
SFCStyleCompileOptions
|
||||
} from '../src/compileStyle'
|
||||
import { mockWarn } from '@vue/shared'
|
||||
|
||||
describe('SFC scoped CSS', () => {
|
||||
mockWarn()
|
||||
|
||||
function compileScoped(source: string): string {
|
||||
function compileScoped(
|
||||
source: string,
|
||||
options?: Partial<SFCStyleCompileOptions>
|
||||
): string {
|
||||
const res = compileStyle({
|
||||
source,
|
||||
filename: 'test.css',
|
||||
id: 'test',
|
||||
scoped: true
|
||||
scoped: true,
|
||||
...options
|
||||
})
|
||||
if (res.errors.length) {
|
||||
res.errors.forEach(err => {
|
||||
@ -254,10 +262,15 @@ describe('SFC scoped CSS', () => {
|
||||
|
||||
describe('<style vars>', () => {
|
||||
test('should rewrite CSS vars in scoped mode', () => {
|
||||
const code = compileScoped(`.foo {
|
||||
const code = compileScoped(
|
||||
`.foo {
|
||||
color: var(--color);
|
||||
font-size: var(--global:font);
|
||||
}`)
|
||||
}`,
|
||||
{
|
||||
vars: true
|
||||
}
|
||||
)
|
||||
expect(code).toMatchInlineSnapshot(`
|
||||
".foo[test] {
|
||||
color: var(--test-color);
|
||||
|
@ -174,7 +174,7 @@ export function compileScript(
|
||||
}
|
||||
|
||||
// 2. check <script setup="xxx"> function signature
|
||||
const setupValue = scriptSetup.attrs.setup
|
||||
const setupValue = scriptSetup.setup
|
||||
const hasExplicitSignature = typeof setupValue === 'string'
|
||||
|
||||
let propsVar: string | undefined
|
||||
|
@ -15,6 +15,7 @@ export interface SFCStyleCompileOptions {
|
||||
id: string
|
||||
map?: RawSourceMap
|
||||
scoped?: boolean
|
||||
vars?: boolean
|
||||
trim?: boolean
|
||||
preprocessLang?: PreprocessLang
|
||||
preprocessOptions?: any
|
||||
@ -73,6 +74,7 @@ export function doCompileStyle(
|
||||
filename,
|
||||
id,
|
||||
scoped = false,
|
||||
vars = false,
|
||||
trim = true,
|
||||
modules = false,
|
||||
modulesOptions = {},
|
||||
@ -90,7 +92,7 @@ export function doCompileStyle(
|
||||
plugins.push(trimPlugin())
|
||||
}
|
||||
if (scoped) {
|
||||
plugins.push(scopedPlugin(id))
|
||||
plugins.push(scopedPlugin({ id, vars }))
|
||||
}
|
||||
let cssModules: Record<string, string> | undefined
|
||||
if (modules) {
|
||||
|
@ -40,12 +40,14 @@ export interface SFCTemplateBlock extends SFCBlock {
|
||||
|
||||
export interface SFCScriptBlock extends SFCBlock {
|
||||
type: 'script'
|
||||
setup?: string | boolean
|
||||
bindings?: BindingMetadata
|
||||
}
|
||||
|
||||
export interface SFCStyleBlock extends SFCBlock {
|
||||
type: 'style'
|
||||
scoped?: boolean
|
||||
vars?: string
|
||||
module?: string | boolean
|
||||
}
|
||||
|
||||
@ -266,11 +268,15 @@ function createBlock(
|
||||
} else if (type === 'style') {
|
||||
if (p.name === 'scoped') {
|
||||
;(block as SFCStyleBlock).scoped = true
|
||||
} else if (p.name === 'vars' && typeof attrs.vars === 'string') {
|
||||
;(block as SFCStyleBlock).vars = attrs.vars
|
||||
} else if (p.name === 'module') {
|
||||
;(block as SFCStyleBlock).module = attrs[p.name]
|
||||
}
|
||||
} else if (type === 'template' && p.name === 'functional') {
|
||||
;(block as SFCTemplateBlock).functional = true
|
||||
} else if (type === 'script' && p.name === 'setup') {
|
||||
;(block as SFCScriptBlock).setup = attrs.setup
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -6,7 +6,7 @@ const animationRE = /^(-\w+-)?animation$/
|
||||
const cssVarRE = /\bvar\(--(global:)?([^)]+)\)/g
|
||||
|
||||
export default postcss.plugin('vue-scoped', (options: any) => (root: Root) => {
|
||||
const id: string = options
|
||||
const { id, vars: hasInjectedVars } = options as { id: string; vars: boolean }
|
||||
const keyframes = Object.create(null)
|
||||
|
||||
root.each(function rewriteSelectors(node) {
|
||||
@ -135,44 +135,45 @@ export default postcss.plugin('vue-scoped', (options: any) => (root: Root) => {
|
||||
})
|
||||
|
||||
const hasKeyframes = Object.keys(keyframes).length
|
||||
root.walkDecls(decl => {
|
||||
// If keyframes are found in this <style>, find and rewrite animation names
|
||||
// in declarations.
|
||||
// Caveat: this only works for keyframes and animation rules in the same
|
||||
// <style> element.
|
||||
if (hasKeyframes) {
|
||||
// individual animation-name declaration
|
||||
if (animationNameRE.test(decl.prop)) {
|
||||
decl.value = decl.value
|
||||
.split(',')
|
||||
.map(v => keyframes[v.trim()] || v.trim())
|
||||
.join(',')
|
||||
if (hasKeyframes || hasInjectedVars)
|
||||
root.walkDecls(decl => {
|
||||
// If keyframes are found in this <style>, find and rewrite animation names
|
||||
// in declarations.
|
||||
// Caveat: this only works for keyframes and animation rules in the same
|
||||
// <style> element.
|
||||
if (hasKeyframes) {
|
||||
// individual animation-name declaration
|
||||
if (animationNameRE.test(decl.prop)) {
|
||||
decl.value = decl.value
|
||||
.split(',')
|
||||
.map(v => keyframes[v.trim()] || v.trim())
|
||||
.join(',')
|
||||
}
|
||||
// shorthand
|
||||
if (animationRE.test(decl.prop)) {
|
||||
decl.value = decl.value
|
||||
.split(',')
|
||||
.map(v => {
|
||||
const vals = v.trim().split(/\s+/)
|
||||
const i = vals.findIndex(val => keyframes[val])
|
||||
if (i !== -1) {
|
||||
vals.splice(i, 1, keyframes[vals[i]])
|
||||
return vals.join(' ')
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
})
|
||||
.join(',')
|
||||
}
|
||||
}
|
||||
// shorthand
|
||||
if (animationRE.test(decl.prop)) {
|
||||
decl.value = decl.value
|
||||
.split(',')
|
||||
.map(v => {
|
||||
const vals = v.trim().split(/\s+/)
|
||||
const i = vals.findIndex(val => keyframes[val])
|
||||
if (i !== -1) {
|
||||
vals.splice(i, 1, keyframes[vals[i]])
|
||||
return vals.join(' ')
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
})
|
||||
.join(',')
|
||||
}
|
||||
}
|
||||
|
||||
// rewrite CSS variables
|
||||
if (cssVarRE.test(decl.value)) {
|
||||
decl.value = decl.value.replace(cssVarRE, (_, $1, $2) => {
|
||||
return $1 ? `var(--${$2})` : `var(--${id}-${$2})`
|
||||
})
|
||||
}
|
||||
})
|
||||
// rewrite CSS variables
|
||||
if (hasInjectedVars && cssVarRE.test(decl.value)) {
|
||||
decl.value = decl.value.replace(cssVarRE, (_, $1, $2) => {
|
||||
return $1 ? `var(--${$2})` : `var(--${id}-${$2})`
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
function isSpaceCombinator(node: Node) {
|
||||
|
Loading…
Reference in New Issue
Block a user