Skip to content

Commit dc9e034

Browse files
Ensure underscore in theme() are also preserved (#14781)
Quick follow-up to #14776 to treat the `theme()` function the same way.
1 parent 4c9df22 commit dc9e034

File tree

5 files changed

+53
-7
lines changed

5 files changed

+53
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Changed
1111

12-
- Don't convert underscores in the first argument to `var()` to spaces ([#14776](https://github.com/tailwindlabs/tailwindcss/pull/14776))
12+
- Don't convert underscores in the first argument to `var()` and `theme()` to spaces ([#14776](https://github.com/tailwindlabs/tailwindcss/pull/14776), [#14781](https://github.com/tailwindlabs/tailwindcss/pull/14781))
1313

1414
### Fixed
1515

packages/tailwindcss/src/candidate.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,6 +1105,31 @@ it('should not replace `_` in the first argument to `var()`', () => {
11051105
`)
11061106
})
11071107

1108+
it('should not replace `_` in the first argument to `theme()`', () => {
1109+
let utilities = new Utilities()
1110+
utilities.functional('ml', () => [])
1111+
1112+
expect(run('ml-[theme(--spacing-1_5,_theme(--spacing-2_5,_1rem))]', { utilities }))
1113+
.toMatchInlineSnapshot(`
1114+
[
1115+
{
1116+
"important": false,
1117+
"kind": "functional",
1118+
"modifier": null,
1119+
"negative": false,
1120+
"raw": "ml-[theme(--spacing-1_5,_theme(--spacing-2_5,_1rem))]",
1121+
"root": "ml",
1122+
"value": {
1123+
"dataType": null,
1124+
"kind": "arbitrary",
1125+
"value": "theme(--spacing-1_5, theme(--spacing-2_5, 1rem))",
1126+
},
1127+
"variants": [],
1128+
},
1129+
]
1130+
`)
1131+
})
1132+
11081133
it('should parse arbitrary properties', () => {
11091134
expect(run('[color:red]')).toMatchInlineSnapshot(`
11101135
[

packages/tailwindcss/src/index.test.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ describe('compiling CSS', () => {
116116
).toMatchSnapshot()
117117
})
118118

119-
test('unescapes underscores to spaces inside arbitrary values except for `url()` and first argument of `var()`', async () => {
119+
test('unescapes underscores to spaces inside arbitrary values except for `url()` and first argument of `var()` and `theme()`', async () => {
120120
expect(
121121
await compileCss(
122122
css`
@@ -126,14 +126,22 @@ describe('compiling CSS', () => {
126126
}
127127
@tailwind utilities;
128128
`,
129-
['bg-[no-repeat_url(./my_file.jpg)', 'ml-[var(--spacing-1_5,_var(--spacing-2_5,_1rem))]'],
129+
[
130+
'bg-[no-repeat_url(./my_file.jpg)',
131+
'ml-[var(--spacing-1_5,_var(--spacing-2_5,_1rem))]',
132+
'ml-[theme(--spacing-1_5,theme(--spacing-2_5,_1rem)))]',
133+
],
130134
),
131135
).toMatchInlineSnapshot(`
132136
":root {
133137
--spacing-1_5: 1.5rem;
134138
--spacing-2_5: 2.5rem;
135139
}
136140
141+
.ml-\\[theme\\(--spacing-1_5\\,theme\\(--spacing-2_5\\,_1rem\\)\\)\\)\\] {
142+
margin-left: 1.5rem;
143+
}
144+
137145
.ml-\\[var\\(--spacing-1_5\\,_var\\(--spacing-2_5\\,_1rem\\)\\)\\] {
138146
margin-left: var(--spacing-1_5, var(--spacing-2_5, 1rem));
139147
}

packages/tailwindcss/src/utils/decode-arbitrary-value.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ describe('decoding arbitrary values', () => {
2929
)
3030
})
3131

32+
it('should not replace underscores in the first argument of theme()', () => {
33+
expect(decodeArbitraryValue('theme(--spacing-1_5)')).toBe('theme(--spacing-1_5)')
34+
expect(decodeArbitraryValue('theme(--spacing-1_5,_1rem)')).toBe('theme(--spacing-1_5, 1rem)')
35+
expect(decodeArbitraryValue('theme(--spacing-1_5,_theme(--spacing-2_5,_1rem))')).toBe(
36+
'theme(--spacing-1_5, theme(--spacing-2_5, 1rem))',
37+
)
38+
})
39+
3240
it('should leave var(…) as is', () => {
3341
expect(decodeArbitraryValue('var(--foo)')).toBe('var(--foo)')
3442
expect(decodeArbitraryValue('var(--headings-h1-size)')).toBe('var(--headings-h1-size)')

packages/tailwindcss/src/utils/decode-arbitrary-value.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,12 @@ function recursivelyDecodeArbitraryValues(ast: ValueParser.ValueAstNode[]) {
5555
break
5656
}
5757

58-
if (node.value === 'var' || node.value.endsWith('_var')) {
58+
if (
59+
node.value === 'var' ||
60+
node.value.endsWith('_var') ||
61+
node.value === 'theme' ||
62+
node.value.endsWith('_theme')
63+
) {
5964
// Don't decode underscores in the first argument of var() but do
6065
// decode the function name
6166
node.value = convertUnderscoresToWhitespace(node.value)
@@ -78,11 +83,11 @@ function recursivelyDecodeArbitraryValues(ast: ValueParser.ValueAstNode[]) {
7883
break
7984
}
8085
default:
81-
never()
86+
never(node)
8287
}
8388
}
8489
}
8590

86-
function never(): never {
87-
throw new Error('This should never happen')
91+
function never(value: never): never {
92+
throw new Error(`Unexpected value: ${value}`)
8893
}

0 commit comments

Comments
 (0)