Repository: swc-project/swc (rust)

Issue:
css minify remove whitespace of number start selector
### Describe the bug

css minify remove whitespace of number start selector

### Input code

```typescript
.\32 8f99 {
    color: red;
}
```


### Config

_No response_

### Playground link

_No response_

### Expected behavior

.\32 8f99{color:red}

### Actual behavior

.\328f99{color:red}


### Version

latest

### Additional context

_No response_

Pull request:
fix: css minify class name with whitespace
<!-- Note: CI script will automatically rebase your PR so please do not rebase unless required -->

<!-- Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. -->

**Description:**

<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->

**BREAKING CHANGE:**

<!--
If this PR introduces a breaking change, it must contain a notice for it to be included in the CHANGELOG. Add description or remove entirely if not breaking.

You may need to update `MIGRATION.md` for the breaking changes.
-->

**Related issue (if exists):**

fixes #6978 


Patch:
diff --git a/crates/swc_css_utils/src/lib.rs b/crates/swc_css_utils/src/lib.rs
index 33343f96a7..8b7458f73b 100644
--- a/crates/swc_css_utils/src/lib.rs
+++ b/crates/swc_css_utils/src/lib.rs
@@ -274,22 +274,14 @@ pub fn serialize_ident(value: &str, minify: bool) -> Cow<'_, str> {
 }
 
 // https://github.com/servo/rust-cssparser/blob/4c5d065798ea1be649412532bde481dbd404f44a/src/serializer.rs#L166
-fn hex_escape(ascii_byte: u8, minify: bool) -> String {
+fn hex_escape(ascii_byte: u8, _minify: bool) -> String {
     static HEX_DIGITS: &[u8; 16] = b"0123456789abcdef";
 
     if ascii_byte > 0x0f {
         let high = (ascii_byte >> 4) as usize;
         let low = (ascii_byte & 0x0f) as usize;
-
-        if minify {
-            unsafe { str::from_utf8_unchecked(&[b'\\', HEX_DIGITS[high], HEX_DIGITS[low]]) }
-                .to_string()
-        } else {
-            unsafe { str::from_utf8_unchecked(&[b'\\', HEX_DIGITS[high], HEX_DIGITS[low], b' ']) }
-                .to_string()
-        }
-    } else if minify {
-        unsafe { str::from_utf8_unchecked(&[b'\\', HEX_DIGITS[ascii_byte as usize]]) }.to_string()
+        unsafe { str::from_utf8_unchecked(&[b'\\', HEX_DIGITS[high], HEX_DIGITS[low], b' ']) }
+            .to_string()
     } else {
         unsafe { str::from_utf8_unchecked(&[b'\\', HEX_DIGITS[ascii_byte as usize], b' ']) }
             .to_string()


Test patch:
diff --git a/crates/swc_css_codegen/tests/fixture/packages/tailwindcss/variants/output.min.css b/crates/swc_css_codegen/tests/fixture/packages/tailwindcss/variants/output.min.css
index 18be7c5e2d..acc732d8e5 100644
--- a/crates/swc_css_codegen/tests/fixture/packages/tailwindcss/variants/output.min.css
+++ b/crates/swc_css_codegen/tests/fixture/packages/tailwindcss/variants/output.min.css
@@ -7,6 +7,6 @@
         0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0#0000),var(--tw-ring-shadow,0 0#0000),var(--tw-shadow)}}@media(min-width:1024px){@keyframes spin{to{transform:rotate(360deg)}}.lg\:animate-spin{animation:spin 1s linear infinite}.lg\:shadow-md{--tw-shadow:0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),
         0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0#0000),var(--tw-ring-shadow,0 0#0000),var(--tw-shadow)}.dark .lg\:dark\:shadow-md{--tw-shadow:0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),
         0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0#0000),var(--tw-ring-shadow,0 0#0000),var(--tw-shadow)}}@media(min-width:1280px){.xl\:shadow-md{--tw-shadow:0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),
-        0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0#0000),var(--tw-ring-shadow,0 0#0000),var(--tw-shadow)}}@media(min-width:1536px){.\32xl\:shadow-md{--tw-shadow:0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),
-        0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0#0000),var(--tw-ring-shadow,0 0#0000),var(--tw-shadow)}@media(prefers-reduced-motion:no-preference){.dark .\32xl\:dark\:motion-safe\:focus-within\:shadow-md:focus-within{--tw-shadow:0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),
+        0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0#0000),var(--tw-ring-shadow,0 0#0000),var(--tw-shadow)}}@media(min-width:1536px){.\32 xl\:shadow-md{--tw-shadow:0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),
+        0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0#0000),var(--tw-ring-shadow,0 0#0000),var(--tw-shadow)}@media(prefers-reduced-motion:no-preference){.dark .\32 xl\:dark\:motion-safe\:focus-within\:shadow-md:focus-within{--tw-shadow:0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),
             0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0#0000),var(--tw-ring-shadow,0 0#0000),var(--tw-shadow)}}}@media(orientation:portrait){.portrait\:bg-yellow-300{--tw-bg-opacity:1;background-color:rgb(253 224 71/var(--tw-bg-opacity))}}@media(orientation:landscape){.landscape\:bg-yellow-300{--tw-bg-opacity:1;background-color:rgb(253 224 71/var(--tw-bg-opacity))}}
diff --git a/crates/swc_css_codegen/tests/fixture/selectors/class/input.css b/crates/swc_css_codegen/tests/fixture/selectors/class/input.css
index ff943d2acf..3036972af1 100644
--- a/crates/swc_css_codegen/tests/fixture/selectors/class/input.css
+++ b/crates/swc_css_codegen/tests/fixture/selectors/class/input.css
@@ -2,3 +2,4 @@
 .\10FFFFabc:after { content: '\\10FFFFabc' }
 .\10FFFF abc:after { content: '\\10FFFF abc' }
 .\FEFF:after { content: '\uFEFF' }
+.\32 8f99 { color: red }
diff --git a/crates/swc_css_codegen/tests/fixture/selectors/class/output.css b/crates/swc_css_codegen/tests/fixture/selectors/class/output.css
index e98c0c106a..e771ef51c8 100644
--- a/crates/swc_css_codegen/tests/fixture/selectors/class/output.css
+++ b/crates/swc_css_codegen/tests/fixture/selectors/class/output.css
@@ -10,3 +10,6 @@
 .﻿:after {
   content: "uFEFF";
 }
+.\32 8f99 {
+  color: red;
+}
diff --git a/crates/swc_css_codegen/tests/fixture/selectors/class/output.min.css b/crates/swc_css_codegen/tests/fixture/selectors/class/output.min.css
index 2627e87bc2..b383f8b765 100644
--- a/crates/swc_css_codegen/tests/fixture/selectors/class/output.min.css
+++ b/crates/swc_css_codegen/tests/fixture/selectors/class/output.min.css
@@ -1,1 +1,1 @@
-.𐿿abc:after{content:"\\10FFF abc"}.􏿿abc:after{content:"\\10FFFFabc"}.􏿿abc:after{content:"\\10FFFF abc"}.﻿:after{content:"uFEFF"}
+.𐿿abc:after{content:"\\10FFF abc"}.􏿿abc:after{content:"\\10FFFFabc"}.􏿿abc:after{content:"\\10FFFF abc"}.﻿:after{content:"uFEFF"}.\32 8f99{color:red}
diff --git a/crates/swc_css_codegen/tests/fixture/style-blocks-contents/hacks/output.min.css b/crates/swc_css_codegen/tests/fixture/style-blocks-contents/hacks/output.min.css
index 64af845922..e19be95a5e 100644
--- a/crates/swc_css_codegen/tests/fixture/style-blocks-contents/hacks/output.min.css
+++ b/crates/swc_css_codegen/tests/fixture/style-blocks-contents/hacks/output.min.css
@@ -1,1 +1,1 @@
-.selector:not(*:root){}@media screen and (min-width:0\0){}.selector:not(*:root){}@supports(-webkit-appearance:none){}.selector{(;property: value;);}.selector{[;property: value;];}@media \\0 screen {}@media all and (-webkit-min-device-pixel-ratio:0)and (min-resolution:.001dpcm){.selector{}}body:empty .selector{}body:last-child .selector,x:-moz-any-link{}@media �all{}body:last-child .selector,x:-moz-any-link,x:default{}body:not(:-moz-handler-blocked) .selector{}@media screen and (-moz-images-in-menus:0){}@media screen and (min--moz-device-pixel-ratio:0){}_::-moz-progress-bar,body:last-child .selector{}@media all and (min--moz-device-pixel-ratio:0)and (min-resolution:.001dpcm){}@media all and (-moz-images-in-menus:0)and (min-resolution:.001dpcm){}@media all and (min--moz-device-pixel-ratio:0){@media(min-width:0px){}}@media all and (-moz-images-in-menus:0){@media(min-width:0px){}}@supports(-moz-appearance:meterbar){}_::-moz-range-track,body:last-child .selector{}@supports(-moz-appearance:meterbar)and (display:flex){}@supports(-moz-appearance:meterbar)and (cursor:zoom-in){}@supports(-moz-appearance:meterbar)and (background-attachment:local){}@supports(-moz-appearance:meterbar)and (image-orientation:90deg){}@supports(-moz-appearance:meterbar)and (all:initial){}@supports(-moz-appearance:meterbar)and (list-style-type:japanese-formal){}@media all and (min--moz-device-pixel-ratio:0)and (min-resolution:30dpcm){}@supports(-moz-appearance:meterbar)and (background-blend-mode:difference,normal){}_:-moz-tree-row(hover),.selector{}_::selection,.selector:not([attr*=""]){}@supports(-webkit-appearance:none){}* html .selector{}.unused-class.selector{}html>body .selector{}*:first-child+html .selector{}.selector,x:-ie7{}*+html .selector{}body *.selector{}.selector\ {}html>body .selector{}head~body .selector{}_::selection,.selector:not([attr*=""]){}:root .selector{}body:last-child .selector{}body:nth-of-type(1) .selector{}body:first-of-type .selector{}.selector:not([attr*=""]){}.selector{_property:value}.selector{-property:value}.selector{property:value\9}.selector{property:value\9}.selector{!property: value;color:red}.selector{$property: value;color:red}.selector{&property: value;color:red}.selector{*property: value;color:red}.selector{)property: value;color:red}.selector{=property: value;color:red}.selector{%property: value;color:red}.selector{+property: value;color:red}.selector{color:red;@property: value;}.selector{,property: value;color:red}.selector{.property: value;color:red}.selector{/property: value;color:red}.selector{`property: value;color:red}.selector{]property: value;color:red}.selector{#property: value;color:red}.selector{~property: value;color:red}.selector{?property: value;color:red}.selector{:property: value;color:red}.selector{|property: value;color:red}.selector{property:value !ie}@media screen\9{}@media �screen\,screen\9{}@media �screen{}@media screen and (min-width:0\0){}_:-ms-input-placeholder,:root .selector{}_:-ms-fullscreen,:root .selector{}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){}@media screen{@media(min-width:0px){}}.selector:not(*:root){}@supports(-webkit-appearance:none){}.selector{(;property: value;);}.selector{[;property: value;];}html:first-child .selector{}_:-o-prefocus,body:last-child .selector{}@media all and (-webkit-min-device-pixel-ratio:1e4),not all and (-webkit-min-device-pixel-ratio:0){}@media(min-resolution:.001dpcm){_:-o-prefocus,.selector{}}*|html[xmlns*=""] .selector{}@media all and (-webkit-min-device-pixel-ratio:0)and (min-resolution:.001dpcm){.selector{}}.selector:not(*:root){}@supports(-webkit-appearance:none){}.selector{(;property: value;);}.selector{[;property: value;];}@media screen and (min-width:0\0){}@media screen{@media(min-width:0px){}}html:first-child .selector{}html[xmlns*=""] body:last-child .selector{}html[xmlns*=""]:root .selector{}*|html[xmlns*=""] .selector{}_::-moz-svg-foreign-content,:root .selector{}@media \\0 screen {}a{*color : black;_background:white;font-size:big;$(var)-size: 100%;}a{*b:c}div{color:red}selector{property:value;property:normal-value}div{color:red}
+.selector:not(*:root){}@media screen and (min-width:0\0){}.selector:not(*:root){}@supports(-webkit-appearance:none){}.selector{(;property: value;);}.selector{[;property: value;];}@media \\0 screen {}@media all and (-webkit-min-device-pixel-ratio:0)and (min-resolution:.001dpcm){.selector{}}body:empty .selector{}body:last-child .selector,x:-moz-any-link{}@media �all{}body:last-child .selector,x:-moz-any-link,x:default{}body:not(:-moz-handler-blocked) .selector{}@media screen and (-moz-images-in-menus:0){}@media screen and (min--moz-device-pixel-ratio:0){}_::-moz-progress-bar,body:last-child .selector{}@media all and (min--moz-device-pixel-ratio:0)and (min-resolution:.001dpcm){}@media all and (-moz-images-in-menus:0)and (min-resolution:.001dpcm){}@media all and (min--moz-device-pixel-ratio:0){@media(min-width:0px){}}@media all and (-moz-images-in-menus:0){@media(min-width:0px){}}@supports(-moz-appearance:meterbar){}_::-moz-range-track,body:last-child .selector{}@supports(-moz-appearance:meterbar)and (display:flex){}@supports(-moz-appearance:meterbar)and (cursor:zoom-in){}@supports(-moz-appearance:meterbar)and (background-attachment:local){}@supports(-moz-appearance:meterbar)and (image-orientation:90deg){}@supports(-moz-appearance:meterbar)and (all:initial){}@supports(-moz-appearance:meterbar)and (list-style-type:japanese-formal){}@media all and (min--moz-device-pixel-ratio:0)and (min-resolution:30dpcm){}@supports(-moz-appearance:meterbar)and (background-blend-mode:difference,normal){}_:-moz-tree-row(hover),.selector{}_::selection,.selector:not([attr*=""]){}@supports(-webkit-appearance:none){}* html .selector{}.unused-class.selector{}html>body .selector{}*:first-child+html .selector{}.selector,x:-ie7{}*+html .selector{}body *.selector{}.selector\ {}html>body .selector{}head~body .selector{}_::selection,.selector:not([attr*=""]){}:root .selector{}body:last-child .selector{}body:nth-of-type(1) .selector{}body:first-of-type .selector{}.selector:not([attr*=""]){}.selector{_property:value}.selector{-property:value}.selector{property:value\9 }.selector{property:value\9 }.selector{!property: value;color:red}.selector{$property: value;color:red}.selector{&property: value;color:red}.selector{*property: value;color:red}.selector{)property: value;color:red}.selector{=property: value;color:red}.selector{%property: value;color:red}.selector{+property: value;color:red}.selector{color:red;@property: value;}.selector{,property: value;color:red}.selector{.property: value;color:red}.selector{/property: value;color:red}.selector{`property: value;color:red}.selector{]property: value;color:red}.selector{#property: value;color:red}.selector{~property: value;color:red}.selector{?property: value;color:red}.selector{:property: value;color:red}.selector{|property: value;color:red}.selector{property:value !ie}@media screen\9 {}@media �screen\,screen\9 {}@media �screen{}@media screen and (min-width:0\0){}_:-ms-input-placeholder,:root .selector{}_:-ms-fullscreen,:root .selector{}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){}@media screen{@media(min-width:0px){}}.selector:not(*:root){}@supports(-webkit-appearance:none){}.selector{(;property: value;);}.selector{[;property: value;];}html:first-child .selector{}_:-o-prefocus,body:last-child .selector{}@media all and (-webkit-min-device-pixel-ratio:1e4),not all and (-webkit-min-device-pixel-ratio:0){}@media(min-resolution:.001dpcm){_:-o-prefocus,.selector{}}*|html[xmlns*=""] .selector{}@media all and (-webkit-min-device-pixel-ratio:0)and (min-resolution:.001dpcm){.selector{}}.selector:not(*:root){}@supports(-webkit-appearance:none){}.selector{(;property: value;);}.selector{[;property: value;];}@media screen and (min-width:0\0){}@media screen{@media(min-width:0px){}}html:first-child .selector{}html[xmlns*=""] body:last-child .selector{}html[xmlns*=""]:root .selector{}*|html[xmlns*=""] .selector{}_::-moz-svg-foreign-content,:root .selector{}@media \\0 screen {}a{*color : black;_background:white;font-size:big;$(var)-size: 100%;}a{*b:c}div{color:red}selector{property:value;property:normal-value}div{color:red}
diff --git a/crates/swc_css_codegen/tests/fixture/values/ident/output.min.css b/crates/swc_css_codegen/tests/fixture/values/ident/output.min.css
index 99551ac966..67e2c18356 100644
--- a/crates/swc_css_codegen/tests/fixture/values/ident/output.min.css
+++ b/crates/swc_css_codegen/tests/fixture/values/ident/output.min.css
@@ -1,1 +1,1 @@
-:root{--fg-color:blue;--fg-\color-other:blue;--Foo:blue}.box{background-color:rebeccapurple;background-color:var(--fg-color);border-radius:10px;width:100px;height:100px}.box:hover{animation-name:rotate\ rotate;animation-duration:.7s}@keyframes rotate\ rotate{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes rotate{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes rotat\e{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}*|*{color:blue}\*|*{color:blue}@media screen and (min-width:0\0){body{color:red}}body{margin:-\1px}
+:root{--fg-color:blue;--fg-\c olor-other:blue;--Foo:blue}.box{background-color:rebeccapurple;background-color:var(--fg-color);border-radius:10px;width:100px;height:100px}.box:hover{animation-name:rotate\ rotate;animation-duration:.7s}@keyframes rotate\ rotate{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes rotate{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes rotat\e {0%{transform:rotate(0)}100%{transform:rotate(360deg)}}*|*{color:blue}\*|*{color:blue}@media screen and (min-width:0\0){body{color:red}}body{margin:-\1 px}