Show warning when using unsupported bare value data type (#17464)
This PR will show a warning if you are using a bare value data type that
is not supported.
Let's say you want to create a new utility that allows `color` to be a
bare value data type like this:
```css
@utility paint-* {
paint: --value([color], color);
}
```
This means that this would enable new syntax that we don't support yet.
E.g.: `paint-#0088cc`.
The only supported data types for bare values are:
- `number` — `2.5`
- `integer` — `2`
- `ratio` — `1/2`
- `percentage` — `50%`
All other data types are not supported in this position. This PR will
now show a warning:
~~~
Unsupported bare value data type: "color".
Only valid data types are: "number", "integer", "ratio", "percentage".
```css
--value([color],color)
^^^^^
```
~~~
Once we have better sourcemap / location tracking support, this warning
will point to the exact spot, but for now, only a re-print of the AST
can be used.
If you _do_ want to use other data types, then you will have to use
arbitrary value syntax with `[…]` instead.
```css
@utility paint-* {
paint: --value([color]);
}
```
This will allow for `paint-[#0088cc]` for example.
Note: this is not a behavioral change, we already didn't support other
data types, but we silently ignored them. This means that we have to do
more parsing at runtime when evaluating the utility.
With this change, a warning is shown when registering the `@utility`,
not when using it.
This commit is contained in:
parent
57e55a6fe4
commit
2fd7c8d967
3 changed files with 73 additions and 9 deletions
|
|
@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
- Nothing yet!
|
||||
### Fixed
|
||||
|
||||
- Show warning when using unsupported bare value data type in `--value(…)` ([#17464](https://github.com/tailwindlabs/tailwindcss/pull/17464))
|
||||
|
||||
## [4.1.2] - 2025-04-03
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { describe, expect, test } from 'vitest'
|
||||
import { describe, expect, test, vi } from 'vitest'
|
||||
import { compile } from '.'
|
||||
import { compileCss, optimizeCss, run } from './test-utils/run'
|
||||
|
||||
|
|
@ -26530,6 +26530,34 @@ describe('custom utilities', () => {
|
|||
expect(await compileCss(input, ['tab-foo'])).toEqual('')
|
||||
})
|
||||
|
||||
test('bare values with unsupported data types should result in a warning', async () => {
|
||||
let spy = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
||||
let input = css`
|
||||
@utility paint-* {
|
||||
paint: --value([color], color);
|
||||
}
|
||||
|
||||
@tailwind utilities;
|
||||
`
|
||||
|
||||
expect(await compileCss(input, ['paint-#0088cc', 'paint-red'])).toMatchInlineSnapshot(`""`)
|
||||
expect(spy.mock.calls).toMatchInlineSnapshot(`
|
||||
[
|
||||
[
|
||||
"Unsupported bare value data type: "color".
|
||||
Only valid data types are: "number", "integer", "ratio", "percentage".
|
||||
",
|
||||
],
|
||||
[
|
||||
"\`\`\`css
|
||||
--value([color],color)
|
||||
^^^^^
|
||||
\`\`\`",
|
||||
],
|
||||
]
|
||||
`)
|
||||
})
|
||||
|
||||
test('resolve literal values', async () => {
|
||||
let input = css`
|
||||
@utility tab-* {
|
||||
|
|
|
|||
|
|
@ -5692,6 +5692,16 @@ export function createUtilities(theme: Theme) {
|
|||
return utilities
|
||||
}
|
||||
|
||||
// Only allowed bare value data types, to prevent creating new syntax that we
|
||||
// typically don't support right now. E.g.: `--value(color)` would allow you to
|
||||
// use `text-#0088cc` as a valid utility, which is not what we want.
|
||||
export const BARE_VALUE_DATA_TYPES = [
|
||||
'number', // 2.5
|
||||
'integer', // 8
|
||||
'ratio', // 2/3
|
||||
'percentage', // 25%
|
||||
]
|
||||
|
||||
export function createCssUtility(node: AtRule) {
|
||||
let name = node.params
|
||||
|
||||
|
|
@ -5824,7 +5834,6 @@ export function createCssUtility(node: AtRule) {
|
|||
}
|
||||
fn.nodes = ValueParser.parse(args.join(','))
|
||||
|
||||
// Track information for suggestions
|
||||
for (let node of fn.nodes) {
|
||||
// Track literal values
|
||||
if (
|
||||
|
|
@ -5841,6 +5850,36 @@ export function createCssUtility(node: AtRule) {
|
|||
let value = node.value.replace(/-\*.*$/g, '') as `--${string}`
|
||||
storage[fn.value].themeKeys.add(value)
|
||||
}
|
||||
|
||||
// Validate bare value data types
|
||||
else if (
|
||||
node.kind === 'word' &&
|
||||
!(node.value[0] === '[' && node.value[node.value.length - 1] === ']') && // Ignore arbitrary values
|
||||
!BARE_VALUE_DATA_TYPES.includes(node.value)
|
||||
) {
|
||||
console.warn(
|
||||
`Unsupported bare value data type: "${node.value}".\nOnly valid data types are: ${BARE_VALUE_DATA_TYPES.map((x) => `"${x}"`).join(', ')}.\n`,
|
||||
)
|
||||
// TODO: Once we properly track the location of the node, we can
|
||||
// clean this up in a better way.
|
||||
let dataType = node.value
|
||||
let copy = structuredClone(fn)
|
||||
let sentinelValue = '¶'
|
||||
ValueParser.walk(copy.nodes, (node, { replaceWith }) => {
|
||||
if (node.kind === 'word' && node.value === dataType) {
|
||||
replaceWith({ kind: 'word', value: sentinelValue })
|
||||
}
|
||||
})
|
||||
let underline = '^'.repeat(ValueParser.toCss([node]).length)
|
||||
let offset = ValueParser.toCss([copy]).indexOf(sentinelValue)
|
||||
let output = [
|
||||
'```css',
|
||||
ValueParser.toCss([fn]),
|
||||
' '.repeat(offset) + underline,
|
||||
'```',
|
||||
].join('\n')
|
||||
console.warn(output)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -6084,12 +6123,7 @@ function resolveValueFunction(
|
|||
// Limit the bare value types, to prevent new syntax that we
|
||||
// don't want to support. E.g.: `text-#000` is something we
|
||||
// don't want to support, but could be built this way.
|
||||
if (
|
||||
arg.value !== 'number' &&
|
||||
arg.value !== 'integer' &&
|
||||
arg.value !== 'ratio' &&
|
||||
arg.value !== 'percentage'
|
||||
) {
|
||||
if (!BARE_VALUE_DATA_TYPES.includes(arg.value)) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue