123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- import { compileStyle, parse } from '../src'
- import { mockId, compile, assertCode } from './util'
- describe('CSS vars injection', () => {
- test('generating correct code for nested paths', () => {
- const { content } = compile(
- `<script>const a = 1</script>\n` +
- `<style>div{
- color: v-bind(color);
- font-size: v-bind('font.size');
- }</style>`
- )
- expect(content).toMatch(`_useCssVars((_vm, _setup) => ({
- "${mockId}-color": (_vm.color),
- "${mockId}-font_size": (_vm.font.size)
- })`)
- assertCode(content)
- })
- test('w/ normal <script> binding analysis', () => {
- const { content } = compile(
- `<script>
- export default {
- setup() {
- return {
- size: ref('100px')
- }
- }
- }
- </script>\n` +
- `<style>
- div {
- font-size: v-bind(size);
- }
- </style>`
- )
- expect(content).toMatch(`_useCssVars((_vm, _setup) => ({
- "${mockId}-size": (_vm.size)
- })`)
- expect(content).toMatch(`import { useCssVars as _useCssVars } from 'vue'`)
- assertCode(content)
- })
- test('w/ <script setup> binding analysis', () => {
- const { content } = compile(
- `<script setup>
- import { defineProps, ref } from 'vue'
- const color = 'red'
- const size = ref('10px')
- defineProps({
- foo: String
- })
- </script>\n` +
- `<style>
- div {
- color: v-bind(color);
- font-size: v-bind(size);
- border: v-bind(foo);
- }
- </style>`
- )
- // should handle:
- // 1. local const bindings
- // 2. local potential ref bindings
- // 3. props bindings (analyzed)
- expect(content).toMatch(`_useCssVars((_vm, _setup) => ({
- "${mockId}-color": (_setup.color),
- "${mockId}-size": (_setup.size),
- "${mockId}-foo": (_vm.foo)
- })`)
- expect(content).toMatch(`import { useCssVars as _useCssVars } from 'vue'`)
- assertCode(content)
- })
- test('should rewrite CSS vars in compileStyle', () => {
- const { code } = compileStyle({
- source: `.foo {
- color: v-bind(color);
- font-size: v-bind('font.size');
- }`,
- filename: 'test.css',
- id: 'data-v-test'
- })
- expect(code).toMatchInlineSnapshot(`
- ".foo[data-v-test] {
- color: var(--test-color);
- font-size: var(--test-font_size);
- }"
- `)
- })
- test('prod mode', () => {
- const { content } = compile(
- `<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((_vm, _setup) => ({
- "4003f1a6": (_vm.color),
- "41b6490a": (_vm.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[xxxxxxxx] {
- color: var(--4003f1a6);
- font-size: var(--41b6490a);
- }"
- `)
- })
- describe('codegen', () => {
- test('<script> w/ no default export', () => {
- assertCode(
- compile(
- `<script>const a = 1</script>\n` +
- `<style>div{ color: v-bind(color); }</style>`
- ).content
- )
- })
- test('<script> w/ default export', () => {
- assertCode(
- compile(
- `<script>export default { setup() {} }</script>\n` +
- `<style>div{ color: v-bind(color); }</style>`
- ).content
- )
- })
- test('<script> w/ default export in strings/comments', () => {
- assertCode(
- compile(
- `<script>
- // export default {}
- export default {}
- </script>\n` + `<style>div{ color: v-bind(color); }</style>`
- ).content
- )
- })
- test('w/ <script setup>', () => {
- assertCode(
- compile(
- `<script setup>const color = 'red'</script>\n` +
- `<style>div{ color: v-bind(color); }</style>`
- ).content
- )
- })
- //#4185
- test('should ignore comments', () => {
- const { content } = compile(
- `<script setup>const color = 'red';const width = 100</script>\n` +
- `<style>
- /* comment **/
- div{ /* color: v-bind(color); */ width:20; }
- div{ width: v-bind(width); }
- /* comment */
- </style>`
- )
- expect(content).not.toMatch(`"${mockId}-color": (_setup.color)`)
- expect(content).toMatch(`"${mockId}-width": (_setup.width)`)
- assertCode(content)
- })
- test('w/ <script setup> using the same var multiple times', () => {
- const { content } = compile(
- `<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((_vm, _setup) => ({
- "${mockId}-color": (_setup.color)
- })`)
- assertCode(content)
- })
- test('should work with w/ complex expression', () => {
- const { content } = compile(
- `<script setup>
- let a = 100
- let b = 200
- let foo = 300
- </script>\n` +
- `<style>
- p{
- width: calc(v-bind(foo) - 3px);
- height: calc(v-bind('foo') - 3px);
- top: calc(v-bind(foo + 'px') - 3px);
- }
- 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((_vm, _setup) => ({
- "${mockId}-foo": (_setup.foo),
- "${mockId}-foo____px_": (_setup.foo + 'px'),
- "${mockId}-_a___b____2____px_": ((_setup.a + _setup.b) / 2 + 'px'),
- "${mockId}-__a___b______2___a_": (((_setup.a + _setup.b)) / (2 * _setup.a))
- })`)
- assertCode(content)
- })
- // #6022
- test('should be able to parse incomplete expressions', () => {
- const { cssVars } = parse({
- source: `<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`])
- })
- })
- })
|