|
| 1 | +import { __unstable__loadDesignSystem } from '@tailwindcss/node' |
| 2 | +import { expect, test } from 'vitest' |
| 3 | +import { themeToVar } from './theme-to-var' |
| 4 | + |
| 5 | +test.each([ |
| 6 | + // Keep candidates that don't contain `theme(…)` or `theme(…, …)` |
| 7 | + ['[color:red]', '[color:red]'], |
| 8 | + |
| 9 | + // Convert to `var(…)` if we can resolve the path |
| 10 | + ['[color:theme(colors.red.500)]', '[color:var(--color-red-500)]'], // Arbitrary property |
| 11 | + ['[color:theme(colors.red.500)]/50', '[color:var(--color-red-500)]/50'], // Arbitrary property + modifier |
| 12 | + ['bg-[theme(colors.red.500)]', 'bg-[var(--color-red-500)]'], // Arbitrary value |
| 13 | + ['bg-[size:theme(spacing.4)]', 'bg-[size:var(--spacing-4)]'], // Arbitrary value + data type hint |
| 14 | + |
| 15 | + // Convert to `var(…)` if we can resolve the path, but keep fallback values |
| 16 | + ['bg-[theme(colors.red.500,red)]', 'bg-[var(--color-red-500,_red)]'], |
| 17 | + |
| 18 | + // Keep `theme(…)` if we can't resolve the path |
| 19 | + ['bg-[theme(colors.foo.1000)]', 'bg-[theme(colors.foo.1000)]'], |
| 20 | + |
| 21 | + // Keep `theme(…)` if we can't resolve the path, but still try to convert the |
| 22 | + // fallback value. |
| 23 | + [ |
| 24 | + 'bg-[theme(colors.foo.1000,theme(colors.red.500))]', |
| 25 | + 'bg-[theme(colors.foo.1000,var(--color-red-500))]', |
| 26 | + ], |
| 27 | + |
| 28 | + // Use `theme(…)` (deeply nested) inside of a `calc(…)` function |
| 29 | + ['text-[calc(theme(fontSize.xs)*2)]', 'text-[calc(var(--font-size-xs)_*_2)]'], |
| 30 | + |
| 31 | + // Multiple `theme(… / …)` calls should result in modern syntax of `theme(…)` |
| 32 | + // - Can't convert to `var(…)` because that would lose the modifier. |
| 33 | + // - Can't convert to a candidate modifier because there are multiple |
| 34 | + // `theme(…)` calls. |
| 35 | + // |
| 36 | + // If we really want to, we can make a fancy migration that tries to move it |
| 37 | + // to a candidate modifier _if_ all `theme(…)` calls use the same modifier. |
| 38 | + [ |
| 39 | + '[color:theme(colors.red.500/50,theme(colors.blue.500/50))]', |
| 40 | + '[color:theme(--color-red-500/50,_theme(--color-blue-500/50))]', |
| 41 | + ], |
| 42 | + [ |
| 43 | + '[color:theme(colors.red.500/50,theme(colors.blue.500/50))]/50', |
| 44 | + '[color:theme(--color-red-500/50,_theme(--color-blue-500/50))]/50', |
| 45 | + ], |
| 46 | + |
| 47 | + // Convert the `theme(…)`, but try to move the inline modifier (e.g. `50%`), |
| 48 | + // to a candidate modifier. |
| 49 | + // Arbitrary property, with simple percentage modifier |
| 50 | + ['[color:theme(colors.red.500/75%)]', '[color:var(--color-red-500)]/75'], |
| 51 | + |
| 52 | + // Arbitrary property, with numbers (0-1) without a unit |
| 53 | + ['[color:theme(colors.red.500/.12)]', '[color:var(--color-red-500)]/12'], |
| 54 | + ['[color:theme(colors.red.500/0.12)]', '[color:var(--color-red-500)]/12'], |
| 55 | + |
| 56 | + // Arbitrary property, with more complex modifier (we only allow whole numbers |
| 57 | + // as bare modifiers). Convert the complex numbers to arbitrary values instead. |
| 58 | + ['[color:theme(colors.red.500/12.34%)]', '[color:var(--color-red-500)]/[12.34%]'], |
| 59 | + ['[color:theme(colors.red.500/var(--opacity))]', '[color:var(--color-red-500)]/[var(--opacity)]'], |
| 60 | + ['[color:theme(colors.red.500/.12345)]', '[color:var(--color-red-500)]/[12.345]'], |
| 61 | + ['[color:theme(colors.red.500/50.25%)]', '[color:var(--color-red-500)]/[50.25%]'], |
| 62 | + |
| 63 | + // Arbitrary value |
| 64 | + ['bg-[theme(colors.red.500/75%)]', 'bg-[var(--color-red-500)]/75'], |
| 65 | + ['bg-[theme(colors.red.500/12.34%)]', 'bg-[var(--color-red-500)]/[12.34%]'], |
| 66 | + |
| 67 | + // Arbitrary property that already contains a modifier |
| 68 | + ['[color:theme(colors.red.500/50%)]/50', '[color:theme(--color-red-500/50%)]/50'], |
| 69 | + |
| 70 | + // Arbitrary value, where the candidate already contains a modifier |
| 71 | + // This should still migrate the `theme(…)` syntax to the modern syntax. |
| 72 | + ['bg-[theme(colors.red.500/50%)]/50', 'bg-[theme(--color-red-500/50%)]/50'], |
| 73 | + |
| 74 | + // Variants, we can't use `var(…)` especially inside of `@media(…)`. We can |
| 75 | + // still upgrade the `theme(…)` to the modern syntax. |
| 76 | + ['max-[theme(spacing.4)]:flex', 'max-[theme(--spacing-4)]:flex'], |
| 77 | + |
| 78 | + // This test in itself doesn't make much sense. But we need to make sure |
| 79 | + // that this doesn't end up as the modifier in the candidate itself. |
| 80 | + ['max-[theme(spacing.4/50)]:flex', 'max-[theme(--spacing-4/50)]:flex'], |
| 81 | + |
| 82 | + // `theme(…)` calls valid in v3, but not in v4 should still be converted. |
| 83 | + ['[--foo:theme(fontWeight.semibold)]', '[--foo:theme(fontWeight.semibold)]'], |
| 84 | + |
| 85 | + // Invalid cases |
| 86 | + ['[--foo:theme(colors.red.500/50/50)]', '[--foo:theme(colors.red.500/50/50)]'], |
| 87 | + ['[--foo:theme(colors.red.500/50/50)]/50', '[--foo:theme(colors.red.500/50/50)]/50'], |
| 88 | + |
| 89 | + // Partially invalid cases |
| 90 | + [ |
| 91 | + '[--foo:theme(colors.red.500/50/50)_theme(colors.blue.200)]', |
| 92 | + '[--foo:theme(colors.red.500/50/50)_var(--color-blue-200)]', |
| 93 | + ], |
| 94 | + [ |
| 95 | + '[--foo:theme(colors.red.500/50/50)_theme(colors.blue.200)]/50', |
| 96 | + '[--foo:theme(colors.red.500/50/50)_var(--color-blue-200)]/50', |
| 97 | + ], |
| 98 | +])('%s => %s', async (candidate, result) => { |
| 99 | + let designSystem = await __unstable__loadDesignSystem('@import "tailwindcss";', { |
| 100 | + base: __dirname, |
| 101 | + }) |
| 102 | + |
| 103 | + expect(themeToVar(designSystem, {}, candidate)).toEqual(result) |
| 104 | +}) |
0 commit comments