Skip to content

Commit bebaf72

Browse files
committed
ensure automatic var injection only happens on variables
Not on functions that look like variables, e.g.: `--spacing(5)` or `--theme(--color-red-500)`.
1 parent b4ef24f commit bebaf72

File tree

2 files changed

+29
-7
lines changed

2 files changed

+29
-7
lines changed

packages/@tailwindcss-upgrade/src/template/codemods/automatic-var-injection.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ test.each([
3636
['supports-[--test]:flex', 'supports-(--test):flex'],
3737
['supports-[_--test]:flex', 'supports-[--test]:flex'],
3838

39+
// Custom CSS functions that look like variables should not be converted
40+
['w-[--spacing(5)]', 'w-[--spacing(5)]'],
41+
['bg-[--theme(--color-red-500)]', 'bg-[--theme(--color-red-500)]'],
42+
3943
// Some properties never had var() injection in v3.
4044
['[scroll-timeline-name:--myTimeline]', '[scroll-timeline-name:--myTimeline]'],
4145
['[timeline-scope:--myScope]', '[timeline-scope:--myScope]'],

packages/@tailwindcss-upgrade/src/template/codemods/automatic-var-injection.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { walk, WalkAction } from '../../../../tailwindcss/src/ast'
22
import { type Candidate, type Variant } from '../../../../tailwindcss/src/candidate'
33
import type { Config } from '../../../../tailwindcss/src/compat/plugin-api'
44
import type { DesignSystem } from '../../../../tailwindcss/src/design-system'
5+
import * as ValueParser from '../../../../tailwindcss/src/value-parser'
56
import { printCandidate } from '../candidates'
67

78
export function automaticVarInjection(
@@ -73,15 +74,32 @@ export function automaticVarInjection(
7374
}
7475

7576
function injectVar(value: string): { value: string; didChange: boolean } {
77+
let ast = ValueParser.parse(value)
78+
7679
let didChange = false
77-
if (value.startsWith('--')) {
78-
value = `var(${value})`
79-
didChange = true
80-
} else if (value.startsWith(' --')) {
81-
value = value.slice(1)
82-
didChange = true
80+
for (let [idx, node] of ast.entries()) {
81+
// Convert `--my-color` to `var(--my-color)`
82+
// Except if:
83+
// - It's a function like `--spacing(…)`
84+
// - It's preceeded by a space, e.g.: `bg-[_--my-color]` -> `bg-[--my-color]`
85+
if (
86+
node.kind === 'word' &&
87+
node.value.startsWith('--') &&
88+
!(ast[idx - 1]?.kind === 'separator' && ast[idx - 1]?.value === ' ')
89+
) {
90+
node.value = `var(${node.value})`
91+
didChange = true
92+
}
93+
94+
// Remove the space "hack" before a variable. E.g.: `bg-[_--my-color]` ->
95+
// `bg-[--my-color]`
96+
else if (node.kind === 'separator' && node.value === ' ') {
97+
ast.splice(idx, 1)
98+
didChange = true
99+
}
83100
}
84-
return { value, didChange }
101+
102+
return { value: ValueParser.toCss(ast), didChange }
85103
}
86104

87105
function injectVarIntoVariant(designSystem: DesignSystem, variant: Variant): boolean {

0 commit comments

Comments
 (0)