Repository: tailwindlabs/tailwindcss

Problem statement:
Tailwind incorrect generate CSS variables as minus sign
**What version of Tailwind CSS are you using?**

3.0.23

Hi,

I am not sure if this issue is linked to the other problems I have reported in #7874 and #7884 as the output issue seems different. I am therefore opening a new issue.

If I use the following CSS:

```
.prose h1 {
    @apply tw-text-[length:var(--heading-h1-font-size)];
  }
```

Tailwind will generate the following code:

```
.prose h1 {
  font-size: var(--heading-h1 - font-size);
}
```

For some reason the dash after the -h1 part is considered as a minus (maybe due to the number ?). In all cases this seems like a bug.

Thanks :)


Hints:
Definitely seems like a bug and I think you’re right it’s probably because of the number! Will try to look at this this week 👍🏻

Patch:
diff --git a/src/util/dataTypes.js b/src/util/dataTypes.js
--- a/src/util/dataTypes.js
+++ b/src/util/dataTypes.js
@@ -42,10 +42,16 @@ export function normalize(value, isRoot = true) {
 
   // Add spaces around operators inside calc() that do not follow an operator
   // or '('.
-  return value.replace(
-    /(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g,
-    '$1 $2 '
-  )
+  value = value.replace(/calc\(.+\)/g, (match) => {
+    return match.replace(
+      /(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g,
+      '$1 $2 '
+    )
+  })
+
+  // Add spaces around some operators not inside calc() that do not follow an operator
+  // or '('.
+  return value.replace(/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([\/])/g, '$1 $2 ')
 }
 
 export function url(value) {


Test patch:
diff --git a/tests/normalize-data-types.test.js b/tests/normalize-data-types.test.js
new file mode 100644
--- /dev/null
+++ b/tests/normalize-data-types.test.js
@@ -0,0 +1,42 @@
+import { normalize } from '../src/util/dataTypes'
+
+let table = [
+  ['foo', 'foo'],
+  ['foo-bar', 'foo-bar'],
+  ['16/9', '16 / 9'],
+
+  // '_'s are converted to spaces except when escaped
+  ['foo_bar', 'foo bar'],
+  ['foo__bar', 'foo  bar'],
+  ['foo\\_bar', 'foo_bar'],
+
+  // Urls are preserved as-is
+  [
+    'url("https://example.com/abc+def/some-path/2022-01-01-abc/some_underscoered_path")',
+    'url("https://example.com/abc+def/some-path/2022-01-01-abc/some_underscoered_path")',
+  ],
+
+  // var(…) is preserved as is
+  ['var(--foo)', 'var(--foo)'],
+  ['var(--headings-h1-size)', 'var(--headings-h1-size)'],
+
+  // calc(…) get's spaces around operators
+  ['calc(1+2)', 'calc(1 + 2)'],
+  ['calc(100%+1rem)', 'calc(100% + 1rem)'],
+  ['calc(1+calc(100%-20px))', 'calc(1 + calc(100% - 20px))'],
+  ['calc(var(--headings-h1-size)*100)', 'calc(var(--headings-h1-size) * 100)'],
+  [
+    'calc(var(--headings-h1-size)*calc(100%+50%))',
+    'calc(var(--headings-h1-size) * calc(100% + 50%))',
+  ],
+  ['var(--heading-h1-font-size)', 'var(--heading-h1-font-size)'],
+  ['var(--my-var-with-more-than-3-words)', 'var(--my-var-with-more-than-3-words)'],
+  ['var(--width, calc(100%+1rem))', 'var(--width, calc(100% + 1rem))'],
+
+  // Misc
+  ['color(0_0_0/1.0)', 'color(0 0 0 / 1.0)'],
+]
+
+it.each(table)('normalize data: %s', (input, output) => {
+  expect(normalize(input)).toBe(output)
+})