Skip to content

Commit 814541c

Browse files
committed
Lookup variables in the CSS theme
1 parent 0ef371e commit 814541c

File tree

4 files changed

+50
-7
lines changed

4 files changed

+50
-7
lines changed

packages/tailwindcss-language-service/src/util/color.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ function getColorsInString(state: State, str: string): (culori.Color | KeywordCo
6464
return getKeywordColor(color) ?? culori.parse(color)
6565
}
6666

67-
str = replaceCssVarsWithFallbacks(str)
67+
str = replaceCssVarsWithFallbacks(state, str)
6868
str = removeColorMixWherePossible(str)
6969

7070
let possibleColors = str.matchAll(colorRegex)
Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,56 @@
11
import { expect, test } from 'vitest'
22
import { replaceCssVarsWithFallbacks } from './css-vars'
3+
import { State } from './state'
4+
import { DesignSystem } from './v4'
35

46
test('replacing CSS variables with their fallbacks (when they have them)', () => {
5-
expect(replaceCssVarsWithFallbacks('var(--foo, red)')).toBe(' red')
6-
expect(replaceCssVarsWithFallbacks('var(--foo, )')).toBe(' ')
7+
let map = new Map<string, string>([
8+
['--known', 'blue'],
9+
])
710

8-
expect(replaceCssVarsWithFallbacks('rgb(var(--foo, 255 0 0))')).toBe('rgb( 255 0 0)')
9-
expect(replaceCssVarsWithFallbacks('rgb(var(--foo, var(--bar)))')).toBe('rgb( var(--bar))')
11+
let state: State = {
12+
enabled: true,
13+
designSystem: {
14+
resolveThemeValue: (name) => map.get(name) ?? null,
15+
} as DesignSystem,
16+
}
17+
18+
expect(replaceCssVarsWithFallbacks(state, 'var(--foo, red)')).toBe(' red')
19+
expect(replaceCssVarsWithFallbacks(state, 'var(--foo, )')).toBe(' ')
20+
21+
expect(replaceCssVarsWithFallbacks(state, 'rgb(var(--foo, 255 0 0))')).toBe('rgb( 255 0 0)')
22+
expect(replaceCssVarsWithFallbacks(state, 'rgb(var(--foo, var(--bar)))')).toBe('rgb( var(--bar))')
1023

1124
expect(
12-
replaceCssVarsWithFallbacks('rgb(var(var(--bar, var(--baz), var(--qux), var(--thing))))'),
25+
replaceCssVarsWithFallbacks(
26+
state,
27+
'rgb(var(var(--bar, var(--baz), var(--qux), var(--thing))))',
28+
),
1329
).toBe('rgb(var(var(--bar, var(--baz), var(--qux), var(--thing))))')
1430

1531
expect(
1632
replaceCssVarsWithFallbacks(
33+
state,
1734
'rgb(var(--one, var(--bar, var(--baz), var(--qux), var(--thing))))',
1835
),
1936
).toBe('rgb( var(--baz), var(--qux), var(--thing))')
2037

2138
expect(
2239
replaceCssVarsWithFallbacks(
40+
state,
2341
'color-mix(in srgb, var(--color-primary, oklch(0 0 0 / 2.5)), var(--color-secondary, oklch(0 0 0 / 2.5)), 50%)',
2442
),
2543
).toBe('color-mix(in srgb, oklch(0 0 0 / 2.5), oklch(0 0 0 / 2.5), 50%)')
44+
45+
// Known theme keys are replaced with their values
46+
expect(replaceCssVarsWithFallbacks(state, 'var(--known)')).toBe('blue')
47+
48+
// Values from the theme take precedence over fallbacks
49+
expect(replaceCssVarsWithFallbacks(state, 'var(--known, red)')).toBe('blue')
50+
51+
// Unknown theme keys use a fallback if provided
52+
expect(replaceCssVarsWithFallbacks(state, 'var(--unknown, red)')).toBe(' red')
53+
54+
// Unknown theme keys without fallbacks are not replaced
55+
expect(replaceCssVarsWithFallbacks(state, 'var(--unknown)')).toBe('var(--unknown)')
2656
})

packages/tailwindcss-language-service/src/util/css-vars.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
1-
export function replaceCssVarsWithFallbacks(str: string): string {
1+
import type { State } from './state'
2+
3+
export function replaceCssVarsWithFallbacks(state: State, str: string): string {
24
return replaceCssVars(str, (name, fallback) => {
5+
// Replace with the value from the design system first. The design system
6+
// take precedences over other sources as that emulates the behavior of a
7+
// browser where the fallback is only used if the variable is defined.
8+
if (state.designSystem && name.startsWith('--')) {
9+
let value = state.designSystem.resolveThemeValue?.(name) ?? null
10+
if (value !== null) return value
11+
}
12+
313
if (fallback) {
414
return fallback
515
}

packages/tailwindcss-language-service/src/util/v4/design-system.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,7 @@ export interface DesignSystem {
3737
export interface DesignSystem {
3838
compile(classes: string[]): postcss.Root[]
3939
toCss(nodes: postcss.Root | postcss.Node[]): string
40+
41+
// Optional because it did not exist in earlier v4 alpha versions
42+
resolveThemeValue?(path: string): string | undefined
4043
}

0 commit comments

Comments
 (0)