From 8af627d5c4720644246f99012b6f49b419066eef Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Tue, 27 Dec 2022 15:22:46 +0300 Subject: [PATCH] feat(css/parser): Normalize urange (#6704) --- crates/swc_css_ast/src/value.rs | 11 ++- crates/swc_css_codegen/src/lib.rs | 3 +- crates/swc_css_codegen/tests/fixture.rs | 38 +++++++++ .../src/compressor/unicode_range.rs | 4 +- .../tests/fixture/compress-urange/input.css | 5 ++ .../fixture/compress-urange/output.min.css | 2 +- .../src/parser/values_and_units/mod.rs | 20 ++--- .../tests/fixture/value/urange/output.json | 82 +++++++++---------- .../fixture/vendor/csstree/basic/output.json | 8 +- crates/swc_css_visit/src/lib.rs | 2 +- 10 files changed, 112 insertions(+), 63 deletions(-) diff --git a/crates/swc_css_ast/src/value.rs b/crates/swc_css_ast/src/value.rs index a5857b928bd..6cc74e0d3e2 100644 --- a/crates/swc_css_ast/src/value.rs +++ b/crates/swc_css_ast/src/value.rs @@ -454,14 +454,21 @@ pub enum UrlModifier { } #[ast_node("UnicodeRange")] -#[derive(Eq, Hash, EqIgnoreSpan)] +#[derive(Eq, Hash)] pub struct UnicodeRange { pub span: Span, - pub prefix: char, #[cfg_attr(feature = "rkyv", with(swc_atoms::EncodeJsWord))] pub start: JsWord, #[cfg_attr(feature = "rkyv", with(swc_atoms::EncodeJsWord))] pub end: Option, + pub raw: Option, +} + +impl EqIgnoreSpan for UnicodeRange { + #[inline] + fn eq_ignore_span(&self, other: &Self) -> bool { + self.start == other.start && self.end == other.end + } } #[ast_node("CalcSum")] diff --git a/crates/swc_css_codegen/src/lib.rs b/crates/swc_css_codegen/src/lib.rs index d76a18cb7ea..0be5a7eb155 100644 --- a/crates/swc_css_codegen/src/lib.rs +++ b/crates/swc_css_codegen/src/lib.rs @@ -1998,8 +1998,7 @@ where + 2, ); - value.push(n.prefix); - value.push('+'); + value.push_str("u+"); value.push_str(&n.start); if let Some(end) = &n.end { diff --git a/crates/swc_css_codegen/tests/fixture.rs b/crates/swc_css_codegen/tests/fixture.rs index 85bbe8e7f75..d2ba7675e4c 100644 --- a/crates/swc_css_codegen/tests/fixture.rs +++ b/crates/swc_css_codegen/tests/fixture.rs @@ -287,6 +287,44 @@ impl VisitMut for NormalizeTest { n.raw = None; } + fn visit_mut_unicode_range(&mut self, n: &mut UnicodeRange) { + n.visit_mut_children_with(self); + + n.raw = None; + } + + fn visit_mut_declaration(&mut self, n: &mut Declaration) { + n.visit_mut_children_with(self); + + if let DeclarationName::Ident(name) = &mut n.name { + name.value = name.value.to_lowercase().into(); + } + } + + fn visit_mut_pseudo_class_selector(&mut self, n: &mut PseudoClassSelector) { + n.visit_mut_children_with(self); + + n.name.value = n.name.value.to_lowercase().into(); + } + + fn visit_mut_pseudo_element_selector(&mut self, n: &mut PseudoElementSelector) { + n.visit_mut_children_with(self); + + n.name.value = n.name.value.to_lowercase().into(); + } + + fn visit_mut_tag_name_selector(&mut self, n: &mut TagNameSelector) { + n.visit_mut_children_with(self); + + n.name.value.value = n.name.value.value.to_lowercase().into(); + } + + fn visit_mut_attribute_selector_modifier(&mut self, n: &mut AttributeSelectorModifier) { + n.visit_mut_children_with(self); + + n.value.value = n.value.value.to_lowercase().into(); + } + fn visit_mut_an_plus_b_notation(&mut self, n: &mut AnPlusBNotation) { n.visit_mut_children_with(self); diff --git a/crates/swc_css_minifier/src/compressor/unicode_range.rs b/crates/swc_css_minifier/src/compressor/unicode_range.rs index a0f6d14b1d1..4e54976b057 100644 --- a/crates/swc_css_minifier/src/compressor/unicode_range.rs +++ b/crates/swc_css_minifier/src/compressor/unicode_range.rs @@ -46,9 +46,9 @@ impl Compressor { for (idx, start_c) in start.chars().enumerate() { if let Some(end_c) = &end.chars().nth(idx) { - if start_c.eq_ignore_ascii_case(end_c) && question_counter == 0 { + if start_c == *end_c && question_counter == 0 { minified.push(start_c); - } else if start_c == '0' && end_c.eq_ignore_ascii_case(&'f') { + } else if start_c == '0' && *end_c == 'f' { question_counter += 1; minified.push('?') diff --git a/crates/swc_css_minifier/tests/fixture/compress-urange/input.css b/crates/swc_css_minifier/tests/fixture/compress-urange/input.css index 921605507d6..15b36bb37d4 100644 --- a/crates/swc_css_minifier/tests/fixture/compress-urange/input.css +++ b/crates/swc_css_minifier/tests/fixture/compress-urange/input.css @@ -109,3 +109,8 @@ @font-face { unicode-range: U+000450-0004FF; } + +@font-face { + unicode-range: U+26; + unicode-range: u+26; +} diff --git a/crates/swc_css_minifier/tests/fixture/compress-urange/output.min.css b/crates/swc_css_minifier/tests/fixture/compress-urange/output.min.css index 6f6c590e712..d5c2b7aa256 100644 --- a/crates/swc_css_minifier/tests/fixture/compress-urange/output.min.css +++ b/crates/swc_css_minifier/tests/fixture/compress-urange/output.min.css @@ -1 +1 @@ -@font-face{unicode-range:U+26}@font-face{unicode-range:U+-7F}@font-face{unicode-range:U+25-FF}@font-face{unicode-range:U+25-FF,U+4??}@font-face{unicode-range:U+10????}@font-face{unicode-range:U+2b??}@font-face{unicode-range:u+2b??}@font-face{unicode-range:U+1e??}@font-face{unicode-range:U+2125-2128}@font-face{unicode-range:U+4??}@font-face{unicode-range:U+25-FF,U+4??}@font-face{unicode-range:U+450-4FF}@font-face{unicode-range:U+A5,U+4E00-9FFF,U+30??,U+FF00-FF9F}@font-face{unicode-range:U+????}@font-face{unicode-range:U+????}@font-face{unicode-range:U+10????}@font-face{unicode-range:U+10????}@font-face{unicode-range:U+1e1e?}@font-face{unicode-range:u+????,U+1????,U+10????}@font-face{unicode-range:U+25}@font-face{unicode-range:U+1e1e?}@font-face{unicode-range:U+25}@font-face{unicode-range:U+125}@font-face{unicode-range:U+100-FFFF}@font-face{unicode-range:U+10125}@font-face{unicode-range:U+450-4FF}@font-face{unicode-range:U+450-4FF}@font-face{unicode-range:U+450-4FF} +@font-face{unicode-range:u+26}@font-face{unicode-range:u+-7f}@font-face{unicode-range:u+25-ff}@font-face{unicode-range:u+25-ff,u+4??}@font-face{unicode-range:u+10????}@font-face{unicode-range:u+2b??}@font-face{unicode-range:u+2b??}@font-face{unicode-range:u+1e??}@font-face{unicode-range:u+2125-2128}@font-face{unicode-range:u+4??}@font-face{unicode-range:u+25-ff,u+4??}@font-face{unicode-range:u+450-4ff}@font-face{unicode-range:u+a5,u+4e00-9fff,u+30??,u+ff00-ff9f}@font-face{unicode-range:u+????}@font-face{unicode-range:u+????}@font-face{unicode-range:u+10????}@font-face{unicode-range:u+10????}@font-face{unicode-range:u+1e1e?}@font-face{unicode-range:u+????,u+1????,u+10????}@font-face{unicode-range:u+25}@font-face{unicode-range:u+1e1e?}@font-face{unicode-range:u+25}@font-face{unicode-range:u+125}@font-face{unicode-range:u+100-ffff}@font-face{unicode-range:u+10125}@font-face{unicode-range:u+450-4ff}@font-face{unicode-range:u+450-4ff}@font-face{unicode-range:u+450-4ff}@font-face{unicode-range:u+26} diff --git a/crates/swc_css_parser/src/parser/values_and_units/mod.rs b/crates/swc_css_parser/src/parser/values_and_units/mod.rs index 93aafd5c356..a356176202f 100644 --- a/crates/swc_css_parser/src/parser/values_and_units/mod.rs +++ b/crates/swc_css_parser/src/parser/values_and_units/mod.rs @@ -2726,14 +2726,14 @@ where // should start with `u` or `U` match cur!(self) { Token::Ident { value, .. } if matches_eq_ignore_ascii_case!(value, js_word!("u")) => { - let ident = match bump!(self) { + let u = match bump!(self) { Token::Ident { value, .. } => value, _ => { unreachable!(); } }; - unicode_range.push_str(&ident); + unicode_range.push_str(&u); } _ => { return Err(Error::new(span, ErrorKind::Expected("'u' ident token"))); @@ -2915,12 +2915,12 @@ where // 1. Skipping the first u token, concatenate the representations of all the // tokens in the production together. Let this be text. - let prefix = chars.next().unwrap(); - - let mut next = chars.next(); + chars.next(); // 2. If the first character of text is U+002B PLUS SIGN, consume it. Otherwise, // this is an invalid , and this algorithm must exit. + let mut next = chars.next(); + if next != Some('+') { return Err(Error::new( span, @@ -2944,7 +2944,7 @@ where next = chars.next(); } Some(c @ 'A'..='F') | Some(c @ 'a'..='f') => { - start.push(c); + start.push(c.to_ascii_lowercase()); next = chars.next(); } @@ -2999,9 +2999,9 @@ where // 4. Exit this algorithm. return Ok(UnicodeRange { span: span!(self, span.lo), - prefix, start: start.into(), end: None, + raw: Some(unicode_range.into()), }); } @@ -3013,9 +3013,9 @@ where if next.is_none() { return Ok(UnicodeRange { span: span!(self, span.lo), - prefix, start: start.into(), end: None, + raw: Some(unicode_range.into()), }); } @@ -3044,7 +3044,7 @@ where next = chars.next(); } Some(c @ 'A'..='F') | Some(c @ 'a'..='f') => { - end.push(c); + end.push(c.to_ascii_lowercase()); next = chars.next(); } _ => { @@ -3073,9 +3073,9 @@ where return Ok(UnicodeRange { span: span!(self, span.lo), - prefix, start: start.into(), end: Some(end.into()), + raw: Some(unicode_range.into()), }); } } diff --git a/crates/swc_css_parser/tests/fixture/value/urange/output.json b/crates/swc_css_parser/tests/fixture/value/urange/output.json index ce6aea91606..5190d4ea3fc 100644 --- a/crates/swc_css_parser/tests/fixture/value/urange/output.json +++ b/crates/swc_css_parser/tests/fixture/value/urange/output.json @@ -148,9 +148,9 @@ "end": 102, "ctxt": 0 }, - "prefix": "U", "start": "26", - "end": null + "end": null, + "raw": "U+26" } ], "important": null @@ -180,9 +180,9 @@ "end": 164, "ctxt": 0 }, - "prefix": "u", "start": "26", - "end": null + "end": null, + "raw": "u+26" } ], "important": null @@ -212,9 +212,9 @@ "end": 191, "ctxt": 0 }, - "prefix": "U", "start": "0", - "end": "7F" + "end": "7f", + "raw": "U+0-7F" } ], "important": null @@ -244,9 +244,9 @@ "end": 223, "ctxt": 0 }, - "prefix": "U", "start": "0025", - "end": "00FF" + "end": "00ff", + "raw": "U+0025-00FF" } ], "important": null @@ -276,9 +276,9 @@ "end": 278, "ctxt": 0 }, - "prefix": "U", "start": "4??", - "end": null + "end": null, + "raw": "U+4??" } ], "important": null @@ -308,9 +308,9 @@ "end": 344, "ctxt": 0 }, - "prefix": "U", "start": "0025", - "end": "00FF" + "end": "00ff", + "raw": "U+0025-00FF" }, { "type": "Delimiter", @@ -328,9 +328,9 @@ "end": 351, "ctxt": 0 }, - "prefix": "U", "start": "4??", - "end": null + "end": null, + "raw": "U+4??" } ], "important": null @@ -360,9 +360,9 @@ "end": 398, "ctxt": 0 }, - "prefix": "U", - "start": "A5", - "end": null + "start": "a5", + "end": null, + "raw": "U+A5" }, { "type": "Delimiter", @@ -380,9 +380,9 @@ "end": 411, "ctxt": 0 }, - "prefix": "U", - "start": "4E00", - "end": "9FFF" + "start": "4e00", + "end": "9fff", + "raw": "U+4E00-9FFF" }, { "type": "Delimiter", @@ -400,9 +400,9 @@ "end": 419, "ctxt": 0 }, - "prefix": "U", "start": "30??", - "end": null + "end": null, + "raw": "U+30??" }, { "type": "Delimiter", @@ -420,9 +420,9 @@ "end": 432, "ctxt": 0 }, - "prefix": "U", - "start": "FF00", - "end": "FF9F" + "start": "ff00", + "end": "ff9f", + "raw": "U+FF00-FF9F" } ], "important": null @@ -452,9 +452,9 @@ "end": 481, "ctxt": 0 }, - "prefix": "U", "start": "????", - "end": null + "end": null, + "raw": "U+????" } ], "important": null @@ -484,9 +484,9 @@ "end": 510, "ctxt": 0 }, - "prefix": "U", "start": "??????", - "end": null + "end": null, + "raw": "U+??????" } ], "important": null @@ -516,9 +516,9 @@ "end": 535, "ctxt": 0 }, - "prefix": "U", "start": "12", - "end": null + "end": null, + "raw": "U+12" } ], "important": null @@ -548,9 +548,9 @@ "end": 564, "ctxt": 0 }, - "prefix": "U", "start": "12e112", - "end": null + "end": null, + "raw": "U+12e112" } ], "important": null @@ -580,9 +580,9 @@ "end": 593, "ctxt": 0 }, - "prefix": "U", "start": "1e1ee1", - "end": null + "end": null, + "raw": "U+1e1ee1" } ], "important": null @@ -612,9 +612,9 @@ "end": 629, "ctxt": 0 }, - "prefix": "U", "start": "1e1ee1", - "end": "FFFFFF" + "end": "ffffff", + "raw": "U+1e1ee1-FFFFFF" } ], "important": null @@ -644,9 +644,9 @@ "end": 658, "ctxt": 0 }, - "prefix": "U", "start": "1e1ee?", - "end": null + "end": null, + "raw": "U+1e1ee?" } ], "important": null @@ -676,9 +676,9 @@ "end": 686, "ctxt": 0 }, - "prefix": "U", "start": "12", - "end": "13" + "end": "13", + "raw": "U+12-13" } ], "important": null diff --git a/crates/swc_css_parser/tests/fixture/vendor/csstree/basic/output.json b/crates/swc_css_parser/tests/fixture/vendor/csstree/basic/output.json index 361a49e4a91..eda6da25417 100644 --- a/crates/swc_css_parser/tests/fixture/vendor/csstree/basic/output.json +++ b/crates/swc_css_parser/tests/fixture/vendor/csstree/basic/output.json @@ -1875,9 +1875,9 @@ "end": 651, "ctxt": 0 }, - "prefix": "u", "start": "123", - "end": "456" + "end": "456", + "raw": "u+123-456" }, { "type": "UnicodeRange", @@ -1886,9 +1886,9 @@ "end": 660, "ctxt": 0 }, - "prefix": "u", "start": "123???", - "end": null + "end": null, + "raw": "u+123???" }, { "type": "Function", diff --git a/crates/swc_css_visit/src/lib.rs b/crates/swc_css_visit/src/lib.rs index 0f96ddf7e9c..b8216e76719 100644 --- a/crates/swc_css_visit/src/lib.rs +++ b/crates/swc_css_visit/src/lib.rs @@ -308,9 +308,9 @@ define!({ pub struct UnicodeRange { pub span: Span, - pub prefix: char, pub start: JsWord, pub end: Option, + pub raw: Option, } pub struct CalcSum {