2022-06-06 20:02:08 +08:00
|
|
|
import { compileStyle, parse } from '../src'
|
2020-11-18 02:03:47 +08:00
|
|
|
import { mockId, compileSFCScript, assertCode } from './utils'
|
2020-11-17 07:27:15 +08:00
|
|
|
|
|
|
|
describe('CSS vars injection', () => {
|
|
|
|
test('generating correct code for nested paths', () => {
|
|
|
|
const { content } = compileSFCScript(
|
|
|
|
`<script>const a = 1</script>\n` +
|
|
|
|
`<style>div{
|
2020-11-18 00:43:08 +08:00
|
|
|
color: v-bind(color);
|
|
|
|
font-size: v-bind('font.size');
|
2020-11-17 07:27:15 +08:00
|
|
|
}</style>`
|
|
|
|
)
|
|
|
|
expect(content).toMatch(`_useCssVars(_ctx => ({
|
2020-11-18 02:03:47 +08:00
|
|
|
"${mockId}-color": (_ctx.color),
|
|
|
|
"${mockId}-font_size": (_ctx.font.size)
|
2020-11-17 07:27:15 +08:00
|
|
|
})`)
|
|
|
|
assertCode(content)
|
|
|
|
})
|
|
|
|
|
2021-05-29 06:40:35 +08:00
|
|
|
test('w/ normal <script> binding analysis', () => {
|
|
|
|
const { content } = compileSFCScript(
|
|
|
|
`<script>
|
|
|
|
export default {
|
|
|
|
setup() {
|
|
|
|
return {
|
|
|
|
size: ref('100px')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>\n` +
|
|
|
|
`<style>
|
|
|
|
div {
|
|
|
|
font-size: v-bind(size);
|
|
|
|
}
|
|
|
|
</style>`
|
|
|
|
)
|
|
|
|
expect(content).toMatch(`_useCssVars(_ctx => ({
|
|
|
|
"${mockId}-size": (_ctx.size)
|
|
|
|
})`)
|
|
|
|
expect(content).toMatch(`import { useCssVars as _useCssVars } from 'vue'`)
|
|
|
|
assertCode(content)
|
|
|
|
})
|
|
|
|
|
2020-11-17 07:27:15 +08:00
|
|
|
test('w/ <script setup> binding analysis', () => {
|
|
|
|
const { content } = compileSFCScript(
|
|
|
|
`<script setup>
|
2020-11-25 04:12:59 +08:00
|
|
|
import { defineProps, ref } from 'vue'
|
2020-11-17 07:27:15 +08:00
|
|
|
const color = 'red'
|
|
|
|
const size = ref('10px')
|
2020-11-25 04:12:59 +08:00
|
|
|
defineProps({
|
|
|
|
foo: String
|
2020-11-17 07:27:15 +08:00
|
|
|
})
|
|
|
|
</script>\n` +
|
|
|
|
`<style>
|
|
|
|
div {
|
2020-11-18 00:43:08 +08:00
|
|
|
color: v-bind(color);
|
|
|
|
font-size: v-bind(size);
|
|
|
|
border: v-bind(foo);
|
2020-11-17 07:27:15 +08:00
|
|
|
}
|
|
|
|
</style>`
|
|
|
|
)
|
|
|
|
// should handle:
|
|
|
|
// 1. local const bindings
|
|
|
|
// 2. local potential ref bindings
|
|
|
|
// 3. props bindings (analyzed)
|
|
|
|
expect(content).toMatch(`_useCssVars(_ctx => ({
|
2020-11-18 02:03:47 +08:00
|
|
|
"${mockId}-color": (color),
|
2020-11-19 11:34:55 +08:00
|
|
|
"${mockId}-size": (size.value),
|
2020-11-18 02:03:47 +08:00
|
|
|
"${mockId}-foo": (__props.foo)
|
2020-11-17 07:27:15 +08:00
|
|
|
})`)
|
|
|
|
expect(content).toMatch(
|
|
|
|
`import { useCssVars as _useCssVars, unref as _unref } from 'vue'`
|
|
|
|
)
|
|
|
|
assertCode(content)
|
|
|
|
})
|
|
|
|
|
2020-11-18 04:58:46 +08:00
|
|
|
test('should rewrite CSS vars in compileStyle', () => {
|
2020-11-17 07:27:15 +08:00
|
|
|
const { code } = compileStyle({
|
|
|
|
source: `.foo {
|
2020-11-18 00:43:08 +08:00
|
|
|
color: v-bind(color);
|
|
|
|
font-size: v-bind('font.size');
|
2020-11-17 07:27:15 +08:00
|
|
|
}`,
|
|
|
|
filename: 'test.css',
|
|
|
|
id: 'data-v-test'
|
|
|
|
})
|
|
|
|
expect(code).toMatchInlineSnapshot(`
|
|
|
|
".foo {
|
|
|
|
color: var(--test-color);
|
|
|
|
font-size: var(--test-font_size);
|
|
|
|
}"
|
|
|
|
`)
|
|
|
|
})
|
2020-11-18 00:43:08 +08:00
|
|
|
|
2020-11-18 04:58:46 +08:00
|
|
|
test('prod mode', () => {
|
|
|
|
const { content } = compileSFCScript(
|
|
|
|
`<script>const a = 1</script>\n` +
|
|
|
|
`<style>div{
|
|
|
|
color: v-bind(color);
|
|
|
|
font-size: v-bind('font.size');
|
|
|
|
}</style>`,
|
|
|
|
{ isProd: true }
|
|
|
|
)
|
|
|
|
expect(content).toMatch(`_useCssVars(_ctx => ({
|
|
|
|
"4003f1a6": (_ctx.color),
|
|
|
|
"41b6490a": (_ctx.font.size)
|
|
|
|
}))}`)
|
|
|
|
|
|
|
|
const { code } = compileStyle({
|
|
|
|
source: `.foo {
|
|
|
|
color: v-bind(color);
|
|
|
|
font-size: v-bind('font.size');
|
|
|
|
}`,
|
|
|
|
filename: 'test.css',
|
|
|
|
id: mockId,
|
|
|
|
isProd: true
|
|
|
|
})
|
|
|
|
expect(code).toMatchInlineSnapshot(`
|
|
|
|
".foo {
|
|
|
|
color: var(--4003f1a6);
|
|
|
|
font-size: var(--41b6490a);
|
|
|
|
}"
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
|
2020-11-18 00:43:08 +08:00
|
|
|
describe('codegen', () => {
|
|
|
|
test('<script> w/ no default export', () => {
|
|
|
|
assertCode(
|
|
|
|
compileSFCScript(
|
|
|
|
`<script>const a = 1</script>\n` +
|
|
|
|
`<style>div{ color: v-bind(color); }</style>`
|
|
|
|
).content
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('<script> w/ default export', () => {
|
|
|
|
assertCode(
|
|
|
|
compileSFCScript(
|
|
|
|
`<script>export default { setup() {} }</script>\n` +
|
|
|
|
`<style>div{ color: v-bind(color); }</style>`
|
|
|
|
).content
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('<script> w/ default export in strings/comments', () => {
|
|
|
|
assertCode(
|
|
|
|
compileSFCScript(
|
|
|
|
`<script>
|
|
|
|
// export default {}
|
|
|
|
export default {}
|
|
|
|
</script>\n` + `<style>div{ color: v-bind(color); }</style>`
|
|
|
|
).content
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('w/ <script setup>', () => {
|
|
|
|
assertCode(
|
|
|
|
compileSFCScript(
|
|
|
|
`<script setup>const color = 'red'</script>\n` +
|
|
|
|
`<style>div{ color: v-bind(color); }</style>`
|
|
|
|
).content
|
|
|
|
)
|
|
|
|
})
|
2021-07-16 04:45:37 +08:00
|
|
|
|
2021-07-26 23:19:56 +08:00
|
|
|
//#4185
|
|
|
|
test('should ignore comments', () => {
|
|
|
|
const { content } = compileSFCScript(
|
2021-07-28 22:51:25 +08:00
|
|
|
`<script setup>const color = 'red';const width = 100</script>\n` +
|
2021-07-26 23:19:56 +08:00
|
|
|
`<style>
|
2021-07-28 22:51:25 +08:00
|
|
|
/* comment **/
|
2021-07-26 23:19:56 +08:00
|
|
|
div{ /* color: v-bind(color); */ width:20; }
|
2021-07-28 22:51:25 +08:00
|
|
|
div{ width: v-bind(width); }
|
|
|
|
/* comment */
|
2021-07-26 23:19:56 +08:00
|
|
|
</style>`
|
|
|
|
)
|
|
|
|
|
2021-07-28 22:51:25 +08:00
|
|
|
expect(content).not.toMatch(`"${mockId}-color": (color)`)
|
|
|
|
expect(content).toMatch(`"${mockId}-width": (width)`)
|
2021-07-26 23:19:56 +08:00
|
|
|
assertCode(content)
|
|
|
|
})
|
|
|
|
|
2021-07-16 04:45:37 +08:00
|
|
|
test('w/ <script setup> using the same var multiple times', () => {
|
|
|
|
const { content } = compileSFCScript(
|
|
|
|
`<script setup>
|
|
|
|
const color = 'red'
|
|
|
|
</script>\n` +
|
|
|
|
`<style>
|
|
|
|
div {
|
|
|
|
color: v-bind(color);
|
|
|
|
}
|
|
|
|
p {
|
|
|
|
color: v-bind(color);
|
|
|
|
}
|
|
|
|
</style>`
|
|
|
|
)
|
|
|
|
// color should only be injected once, even if it is twice in style
|
|
|
|
expect(content).toMatch(`_useCssVars(_ctx => ({
|
|
|
|
"${mockId}-color": (color)
|
2022-01-21 15:53:51 +08:00
|
|
|
})`)
|
|
|
|
assertCode(content)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('should work with w/ complex expression', () => {
|
|
|
|
const { content } = compileSFCScript(
|
|
|
|
`<script setup>
|
|
|
|
let a = 100
|
|
|
|
let b = 200
|
2022-01-23 20:58:43 +08:00
|
|
|
let foo = 300
|
2022-01-21 15:53:51 +08:00
|
|
|
</script>\n` +
|
|
|
|
`<style>
|
2022-01-23 20:58:43 +08:00
|
|
|
p{
|
|
|
|
width: calc(v-bind(foo) - 3px);
|
|
|
|
height: calc(v-bind('foo') - 3px);
|
2022-01-23 21:03:37 +08:00
|
|
|
top: calc(v-bind(foo + 'px') - 3px);
|
2022-01-23 20:58:43 +08:00
|
|
|
}
|
2022-01-21 15:53:51 +08:00
|
|
|
div {
|
|
|
|
color: v-bind((a + b) / 2 + 'px' );
|
|
|
|
}
|
|
|
|
div {
|
|
|
|
color: v-bind ((a + b) / 2 + 'px' );
|
|
|
|
}
|
|
|
|
p {
|
|
|
|
color: v-bind(((a + b)) / (2 * a));
|
|
|
|
}
|
|
|
|
</style>`
|
|
|
|
)
|
|
|
|
expect(content).toMatch(`_useCssVars(_ctx => ({
|
2022-01-23 20:58:43 +08:00
|
|
|
"${mockId}-foo": (_unref(foo)),
|
2022-01-23 21:03:37 +08:00
|
|
|
"${mockId}-foo____px_": (_unref(foo) + 'px'),
|
2022-01-23 20:58:43 +08:00
|
|
|
"${mockId}-_a___b____2____px_": ((_unref(a) + _unref(b)) / 2 + 'px'),
|
2022-01-21 15:53:51 +08:00
|
|
|
"${mockId}-__a___b______2___a_": (((_unref(a) + _unref(b))) / (2 * _unref(a)))
|
2021-07-16 04:45:37 +08:00
|
|
|
})`)
|
|
|
|
assertCode(content)
|
|
|
|
})
|
2022-06-06 20:02:08 +08:00
|
|
|
|
|
|
|
// #6022
|
|
|
|
test('should be able to parse incomplete expressions', () => {
|
|
|
|
const {
|
|
|
|
descriptor: { cssVars }
|
|
|
|
} = parse(
|
|
|
|
`<script setup>let xxx = 1</script>
|
|
|
|
<style scoped>
|
|
|
|
label {
|
|
|
|
font-weight: v-bind("count.toString(");
|
|
|
|
font-weight: v-bind(xxx);
|
|
|
|
}
|
|
|
|
</style>`
|
|
|
|
)
|
|
|
|
expect(cssVars).toMatchObject([`count.toString(`, `xxx`])
|
|
|
|
})
|
2020-11-18 00:43:08 +08:00
|
|
|
})
|
2020-11-17 07:27:15 +08:00
|
|
|
})
|