diff --git a/src/dependencies.rs b/src/dependencies.rs index 08bf143..da35e39 100644 --- a/src/dependencies.rs +++ b/src/dependencies.rs @@ -274,11 +274,96 @@ impl CssModulesModeData { } } +#[derive(Debug)] +struct AnimationProperty { + keywords: AnimationKeywords, + keyframes: Option, + balanced_len: usize, +} + +impl AnimationProperty { + pub fn new(balanced_len: usize) -> Self { + Self { + keywords: AnimationKeywords::default(), + keyframes: None, + balanced_len, + } + } + + fn check_keywords(&mut self, ident: &str) -> bool { + self.keywords.check(ident) + } + + pub fn set_keyframes(&mut self, ident: &str, range: Range) { + if self.check_keywords(ident) { + self.keyframes = Some(range); + } + } + + pub fn take_keyframes(&mut self, balanced_len: usize) -> Option { + // Don't rename animation name when we in functions + if balanced_len != self.balanced_len { + return None; + } + std::mem::take(&mut self.keyframes) + } +} + #[derive(Debug, Default)] -enum AnimationKeyframes { - #[default] - Start, - LastIdent(Range), +struct AnimationKeywords { + bits: u32, +} + +impl AnimationKeywords { + const NORMAL: u32 = 1 << 0; + const REVERSE: u32 = 1 << 1; + const ALTERNATE: u32 = 1 << 2; + const ALTERNATE_REVERSE: u32 = 1 << 3; + const FORWARDS: u32 = 1 << 4; + const BACKWARDS: u32 = 1 << 5; + const BOTH: u32 = 1 << 6; + const INFINITE: u32 = 1 << 7; + const PAUSED: u32 = 1 << 8; + const RUNNING: u32 = 1 << 9; + const EASE: u32 = 1 << 10; + const EASE_IN: u32 = 1 << 11; + const EASE_OUT: u32 = 1 << 12; + const EASE_IN_OUT: u32 = 1 << 13; + const LINEAR: u32 = 1 << 14; + const STEP_END: u32 = 1 << 15; + const STEP_START: u32 = 1 << 16; + + pub fn check(&mut self, ident: &str) -> bool { + match ident { + "normal" => self.keyword_check(Self::NORMAL), + "reverse" => self.keyword_check(Self::REVERSE), + "alternate" => self.keyword_check(Self::ALTERNATE), + "alternate_reverse" => self.keyword_check(Self::ALTERNATE_REVERSE), + "forwards" => self.keyword_check(Self::FORWARDS), + "backwards" => self.keyword_check(Self::BACKWARDS), + "both" => self.keyword_check(Self::BOTH), + "infinite" => self.keyword_check(Self::INFINITE), + "paused" => self.keyword_check(Self::PAUSED), + "running" => self.keyword_check(Self::RUNNING), + "ease" => self.keyword_check(Self::EASE), + "ease_in" => self.keyword_check(Self::EASE_IN), + "ease_out" => self.keyword_check(Self::EASE_OUT), + "ease_in_out" => self.keyword_check(Self::EASE_IN_OUT), + "linear" => self.keyword_check(Self::LINEAR), + "step_end" => self.keyword_check(Self::STEP_END), + "step_start" => self.keyword_check(Self::STEP_START), + "none" | "initial" | "inherit" | "unset" | "revert" | "revert-layer" => false, + _ => true, + } + } + + fn keyword_check(&mut self, bit: u32) -> bool { + if self.bits & bit == bit { + return true; + } + self.bits |= bit; + false + } } #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -384,7 +469,7 @@ pub struct LexDependencies<'s, D, W> { allow_import_at_rule: bool, balanced: BalancedStack, is_next_rule_prelude: bool, - in_animation_property: Option, + in_animation_property: Option, handle_dependency: D, handle_warning: W, } @@ -423,11 +508,19 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> LexDependencies<'s, D, W fn get_media(&self, lexer: &Lexer<'s>, start: Pos, end: Pos) -> Option<&'s str> { let media = lexer.slice(start, end)?; let mut media_lexer = Lexer::from(media); - media_lexer.consume()?; + media_lexer.consume(); media_lexer.consume_white_space_and_comments()?; Some(media) } + fn enter_animation_property(&mut self) { + self.in_animation_property = Some(AnimationProperty::new(self.balanced.len())); + } + + fn exit_animation_property(&mut self) { + self.in_animation_property = None; + } + fn consume_icss_export_prop(&self, lexer: &mut Lexer<'s>) -> Option<()> { loop { let c = lexer.cur()?; @@ -438,7 +531,7 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> LexDependencies<'s, D, W { break; } - lexer.consume()?; + lexer.consume(); } Some(()) } @@ -449,7 +542,7 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> LexDependencies<'s, D, W if c == C_RIGHT_CURLY || c == C_SEMICOLON { break; } - lexer.consume()?; + lexer.consume(); } Some(()) } @@ -464,7 +557,7 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> LexDependencies<'s, D, W }); return Some(()); } - lexer.consume()?; + lexer.consume(); lexer.consume_white_space_and_comments()?; while lexer.cur()? != C_RIGHT_CURLY { lexer.consume_white_space_and_comments()?; @@ -479,13 +572,13 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> LexDependencies<'s, D, W }); return Some(()); } - lexer.consume()?; + lexer.consume(); lexer.consume_white_space_and_comments()?; let value_start = lexer.cur_pos()?; self.consume_icss_export_value(lexer)?; let value_end = lexer.cur_pos()?; if lexer.cur()? == C_SEMICOLON { - lexer.consume()?; + lexer.consume(); lexer.consume_white_space_and_comments()?; } self.handle_dependency @@ -498,7 +591,7 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> LexDependencies<'s, D, W .trim_end_matches(is_white_space), }); } - lexer.consume()?; + lexer.consume(); Some(()) } @@ -534,7 +627,7 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> LexDependencies<'s, D, W if lexer.cur()? != C_COLON { return Some(()); } - lexer.consume()?; + lexer.consume(); self.handle_dependency .handle_dependency(Dependency::LocalVarDecl { name, @@ -607,7 +700,7 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> LexDependencies<'s, D, W fn handle_local_keyframes_dependency(&mut self, lexer: &Lexer<'s>) -> Option<()> { if let Some(animation) = &mut self.in_animation_property { - if let AnimationKeyframes::LastIdent(range) = std::mem::take(animation) { + if let Some(range) = animation.take_keyframes(self.balanced.len()) { self.handle_dependency .handle_dependency(Dependency::LocalKeyframes { name: lexer.slice(range.start, range.end)?, @@ -623,7 +716,7 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> LexDependencies<'s, D, W if lexer.cur()? != C_COLON { return Some(()); } - lexer.consume()?; + lexer.consume(); let mut end; let mut has_from = false; loop { @@ -661,7 +754,7 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> LexDependencies<'s, D, W from: None, }); if c == C_COMMA { - lexer.consume()?; + lexer.consume(); continue; } end = names_end; @@ -669,7 +762,7 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> LexDependencies<'s, D, W } let path_start = lexer.cur_pos()?; if c == '\'' || c == '"' { - lexer.consume()?; + lexer.consume(); lexer.consume_string(self, c)?; } else if start_ident_sequence(c, lexer.peek()?, lexer.peek2()?) { lexer.consume_ident_sequence()?; @@ -691,10 +784,10 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> LexDependencies<'s, D, W if lexer.cur()? != C_COMMA { break; } - lexer.consume()?; + lexer.consume(); } if lexer.cur()? == C_SEMICOLON { - lexer.consume()?; + lexer.consume(); end = lexer.cur_pos()?; } self.handle_dependency @@ -916,7 +1009,7 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> Visitor<'s> for LexDepen if let Some(mode_data) = &self.mode_data { if mode_data.is_local_mode() { self.handle_local_keyframes_dependency(lexer)?; - self.in_animation_property = None; + self.exit_animation_property(); } self.is_next_rule_prelude = self.is_next_nested_syntax(lexer)?; } @@ -943,12 +1036,6 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> Visitor<'s> for LexDepen return Some(()); }; if mode_data.is_local_mode() { - // Don't rename animation name when we in functions - if let Some(animation) = &mut self.in_animation_property { - if !self.balanced.is_empty() { - *animation = AnimationKeyframes::Start; - } - } if name == "var(" { self.lex_local_var(lexer)?; } @@ -1019,7 +1106,8 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> Visitor<'s> for LexDepen if let Some(animation) = &mut self.in_animation_property { // Not inside functions if self.balanced.is_empty() { - *animation = AnimationKeyframes::LastIdent(Range::new(start, end)); + animation + .set_keyframes(lexer.slice(start, end)?, Range::new(start, end)); } return Some(()); } @@ -1029,7 +1117,7 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> Visitor<'s> for LexDepen } let ident = ident.to_ascii_lowercase(); if ident == "animation" || ident == "animation-name" { - self.in_animation_property = Some(AnimationKeyframes::Start); + self.enter_animation_property(); return Some(()); } if ident == "composes" { @@ -1108,7 +1196,7 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> Visitor<'s> for LexDepen if let Some(mode_data) = &self.mode_data { if mode_data.is_local_mode() { self.handle_local_keyframes_dependency(lexer)?; - self.in_animation_property = None; + self.exit_animation_property(); } } self.block_nesting_level -= 1; diff --git a/src/lexer.rs b/src/lexer.rs index 7f4426d..83846a1 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -102,13 +102,11 @@ impl<'s> From<&'s str> for Lexer<'s> { } impl<'s> Lexer<'s> { - #[must_use] - pub fn consume(&mut self) -> Option { + pub fn consume(&mut self) { self.cur_pos = self.peek_pos(); self.cur = self.peek; self.peek = self.peek2; self.peek2 = self.iter.next(); - self.cur() } pub fn cur_pos(&self) -> Option { @@ -151,7 +149,7 @@ impl<'s> Lexer<'s> { } fn lex_impl>(&mut self, visitor: &mut T) -> Option<()> { - self.consume()?; + self.consume(); while self.cur().is_some() { self.consume_comments()?; // https://drafts.csswg.org/css-syntax/#consume-token @@ -170,14 +168,14 @@ impl<'s> Lexer<'s> { C_SEMICOLON => self.consume_semicolon(visitor)?, C_LESS_THAN_SIGN => self.consume_less_than_sign()?, C_AT_SIGN => self.consume_at_sign(visitor)?, - C_LEFT_SQUARE => self.consume_delim()?, + C_LEFT_SQUARE => self.consume_delim(), C_REVERSE_SOLIDUS => self.consume_reverse_solidus(visitor)?, - C_RIGHT_SQUARE => self.consume_delim()?, + C_RIGHT_SQUARE => self.consume_delim(), C_LEFT_CURLY => self.consume_left_curly(visitor)?, C_RIGHT_CURLY => self.consume_right_curly(visitor)?, c if is_digit(c) => self.consume_numeric_token()?, c if is_ident_start(c) => self.consume_ident_like(visitor)?, - _ => self.consume_delim()?, + _ => self.consume_delim(), } } Some(()) @@ -185,10 +183,13 @@ impl<'s> Lexer<'s> { pub fn consume_comments(&mut self) -> Option<()> { if self.cur()? == C_SOLIDUS && self.peek()? == C_ASTERISK { - while let Some(c) = self.consume() { + self.consume(); + loop { + self.consume(); + let c = self.cur()?; if c == C_ASTERISK && self.peek()? == C_SOLIDUS { - self.consume()?; - self.consume()?; + self.consume(); + self.consume(); break; } } @@ -196,13 +197,15 @@ impl<'s> Lexer<'s> { Some(()) } - pub fn consume_delim(&mut self) -> Option<()> { - self.consume()?; - Some(()) + pub fn consume_delim(&mut self) { + self.consume(); } pub fn consume_space(&mut self) -> Option<()> { - while is_white_space(self.consume()?) {} + self.consume(); + while is_white_space(self.cur()?) { + self.consume(); + } Some(()) } @@ -213,27 +216,33 @@ impl<'s> Lexer<'s> { return self.consume_ident_sequence(); } if c == C_PERCENTAGE { - self.consume()?; + self.consume(); } Some(()) } pub fn consume_number(&mut self) -> Option<()> { - while matches!(self.consume(), Some(c) if is_digit(c)) {} + self.consume(); + while is_digit(self.cur()?) { + self.consume(); + } if self.cur()? == C_FULL_STOP && is_digit(self.peek()?) { - self.consume()?; - while matches!(self.consume(), Some(c) if is_digit(c)) {} + self.consume(); + self.consume(); + while is_digit(self.cur()?) { + self.consume(); + } } let c = self.cur()?; if c == C_LOWER_E || c == C_UPPER_E { let c = self.peek()?; if is_digit(c) { - self.consume()?; + self.consume(); } else if c == C_HYPHEN_MINUS || c == C_PLUS_SIGN { let c = self.peek2()?; if is_digit(c) { - self.consume()?; - self.consume()?; + self.consume(); + self.consume(); } else { return Some(()); } @@ -243,7 +252,10 @@ impl<'s> Lexer<'s> { } else { return Some(()); } - while matches!(self.consume(), Some(c) if is_digit(c)) {} + self.consume(); + while is_digit(self.cur()?) { + self.consume(); + } Some(()) } @@ -251,10 +263,10 @@ impl<'s> Lexer<'s> { loop { let c = self.cur()?; if maybe_valid_escape(c) { - self.consume()?; + self.consume(); self.consume_escaped()?; } else if is_ident(c) { - self.consume()?; + self.consume(); } else { return Some(()); } @@ -264,15 +276,16 @@ impl<'s> Lexer<'s> { pub fn consume_escaped(&mut self) -> Option<()> { if is_hex_digit(self.cur()?) { for _ in 1..5 { - if !is_hex_digit(self.consume()?) { + self.consume(); + if !is_hex_digit(self.cur()?) { break; } } if is_white_space(self.cur()?) { - self.consume()?; + self.consume(); } } else { - self.consume()?; + self.consume(); } Some(()) } @@ -284,7 +297,10 @@ impl<'s> Lexer<'s> { if self.cur_pos()? == start + 3 && self.slice(start, peek_pos)?.to_ascii_lowercase() == "url(" { - while is_white_space(self.consume()?) {} + self.consume(); + while is_white_space(self.cur()?) { + self.consume(); + } let c = self.cur()?; if c == C_QUOTATION_MARK || c == C_APOSTROPHE { visitor.function(self, start, peek_pos) @@ -292,7 +308,7 @@ impl<'s> Lexer<'s> { self.consume_url(visitor, start) } } else if self.cur()? == C_LEFT_PARENTHESIS { - self.consume()?; + self.consume(); visitor.function(self, start, self.cur_pos()?) } else { visitor.ident(self, start, self.cur_pos()?) @@ -308,46 +324,53 @@ impl<'s> Lexer<'s> { loop { let c = self.cur()?; if maybe_valid_escape(c) { - self.consume()?; + self.consume(); self.consume_escaped()?; } else if is_white_space(c) { let content_end = self.cur_pos()?; - while is_white_space(self.consume()?) {} + self.consume(); + while is_white_space(self.cur()?) { + self.consume(); + } if self.cur()? != C_RIGHT_PARENTHESIS { return Some(()); } - self.consume()?; + self.consume(); return visitor.url(self, start, self.cur_pos()?, content_start, content_end); } else if c == C_RIGHT_PARENTHESIS { let content_end = self.cur_pos()?; - self.consume()?; + self.consume(); return visitor.url(self, start, self.cur_pos()?, content_start, content_end); } else if c == C_LEFT_PARENTHESIS { return Some(()); } else { - self.consume()?; + self.consume(); } } } pub fn consume_string>(&mut self, visitor: &mut T, end: char) -> Option<()> { let start = self.cur_pos()?; - while let Some(c) = self.consume() { + self.consume(); + loop { + let c = self.cur()?; if c == end { - self.consume()?; + self.consume(); break; } if is_new_line(c) { break; } if c == C_REVERSE_SOLIDUS { - let c2 = self.consume()?; + self.consume(); + let c2 = self.cur()?; if is_new_line(c2) { - self.consume()?; + self.consume(); } else if are_valid_escape(c, c2) { self.consume_escaped()?; } } + self.consume(); } visitor.string(self, start, self.cur_pos()?) } @@ -356,39 +379,42 @@ impl<'s> Lexer<'s> { let c2 = self.peek()?; if is_ident(c2) || are_valid_escape(c2, self.peek2()?) { let start = self.cur_pos()?; - let c = self.consume()?; - if visitor.is_selector(self)? && start_ident_sequence(c, self.peek()?, self.peek2()?) { + self.consume(); + if visitor.is_selector(self)? + && start_ident_sequence(self.cur()?, self.peek()?, self.peek2()?) + { self.consume_ident_sequence()?; return visitor.id(self, start, self.cur_pos()?); } } else { - return self.consume_delim(); + self.consume_delim(); } Some(()) } pub fn consume_left_parenthesis>(&mut self, visitor: &mut T) -> Option<()> { - self.consume()?; + self.consume(); let end = self.cur_pos()?; visitor.left_parenthesis(self, end - 1, end) } pub fn consume_right_parenthesis>(&mut self, visitor: &mut T) -> Option<()> { - self.consume()?; + self.consume(); let end = self.cur_pos()?; visitor.right_parenthesis(self, end - 1, end) } pub fn consume_plus_sign(&mut self) -> Option<()> { if start_number(self.cur()?, self.peek()?, self.peek2()?) { - self.consume_numeric_token() + self.consume_numeric_token()?; } else { - self.consume_delim() + self.consume_delim(); } + Some(()) } pub fn consume_comma>(&mut self, visitor: &mut T) -> Option<()> { - self.consume()?; + self.consume(); let end = self.cur_pos()?; visitor.comma(self, end - 1, end) } @@ -398,16 +424,16 @@ impl<'s> Lexer<'s> { let c2 = self.peek()?; let c3 = self.peek2()?; if start_number(c, c2, c3) { - self.consume_numeric_token() + self.consume_numeric_token()?; } else if c2 == C_HYPHEN_MINUS && c3 == C_GREATER_THAN_SIGN { - self.consume()?; - self.consume()?; - Some(()) + self.consume(); + self.consume(); } else if start_ident_sequence(c, c2, c3) { - self.consume_ident_like(visitor) + self.consume_ident_like(visitor)?; } else { - self.consume_delim() + self.consume_delim(); } + Some(()) } pub fn consume_full_stop>(&mut self, visitor: &mut T) -> Option<()> { @@ -418,9 +444,10 @@ impl<'s> Lexer<'s> { return self.consume_numeric_token(); } let start = self.cur_pos()?; - self.consume()?; + self.consume(); if !visitor.is_selector(self)? || !start_ident_sequence(c2, c3, self.peek2()?) { - return self.consume_delim(); + self.consume_delim(); + return Some(()); } self.consume_ident_sequence()?; visitor.class(self, start, self.cur_pos()?) @@ -428,13 +455,15 @@ impl<'s> Lexer<'s> { pub fn consume_potential_pseudo>(&mut self, visitor: &mut T) -> Option<()> { let start = self.cur_pos()?; - let c = self.consume()?; - if !visitor.is_selector(self)? || !start_ident_sequence(c, self.peek()?, self.peek2()?) { + self.consume(); + if !visitor.is_selector(self)? + || !start_ident_sequence(self.cur()?, self.peek()?, self.peek2()?) + { return Some(()); } self.consume_ident_sequence()?; if self.cur()? == C_LEFT_PARENTHESIS { - self.consume()?; + self.consume(); visitor.pseudo_function(self, start, self.cur_pos()?) } else { visitor.pseudo_class(self, start, self.cur_pos()?) @@ -442,24 +471,25 @@ impl<'s> Lexer<'s> { } pub fn consume_semicolon>(&mut self, visitor: &mut T) -> Option<()> { - self.consume()?; + self.consume(); let end = self.cur_pos()?; visitor.semicolon(self, end - 1, end) } pub fn consume_less_than_sign(&mut self) -> Option<()> { - if self.consume()? == '!' && self.peek()? == '-' && self.peek2()? == '-' { - self.consume()?; - self.consume()?; - self.consume()?; + self.consume(); + if self.cur()? == '!' && self.peek()? == '-' && self.peek2()? == '-' { + self.consume(); + self.consume(); + self.consume(); } Some(()) } pub fn consume_at_sign>(&mut self, visitor: &mut T) -> Option<()> { let start = self.cur_pos()?; - let c = self.consume()?; - if start_ident_sequence(c, self.peek()?, self.peek2()?) { + self.consume(); + if start_ident_sequence(self.cur()?, self.peek()?, self.peek2()?) { self.consume_ident_sequence()?; return visitor.at_keyword(self, start, self.cur_pos()?); } @@ -468,20 +498,21 @@ impl<'s> Lexer<'s> { pub fn consume_reverse_solidus>(&mut self, visitor: &mut T) -> Option<()> { if are_valid_escape(self.cur()?, self.peek()?) { - self.consume_ident_like(visitor) + self.consume_ident_like(visitor)?; } else { - self.consume_delim() + self.consume_delim(); } + Some(()) } pub fn consume_left_curly>(&mut self, visitor: &mut T) -> Option<()> { - self.consume()?; + self.consume(); let end = self.cur_pos()?; visitor.left_curly_bracket(self, end - 1, end) } pub fn consume_right_curly>(&mut self, visitor: &mut T) -> Option<()> { - self.consume()?; + self.consume(); let end = self.cur_pos()?; visitor.right_curly_bracket(self, end - 1, end) } diff --git a/tests/postcss_plugins/modules_local_by_default_test.rs b/tests/postcss_plugins/modules_local_by_default_test.rs index 2eecb77..48d91e9 100644 --- a/tests/postcss_plugins/modules_local_by_default_test.rs +++ b/tests/postcss_plugins/modules_local_by_default_test.rs @@ -51,22 +51,18 @@ fn scope_escaped_selectors() { #[test] fn scope_ids() { - test("#foobar {}", ":local(#foobar) {}") + test("#foobar {}", ":local(#foobar) {}"); } #[test] fn scope_escaped_ids() { - test("#\\#test {}", ":local(#\\#test) {}") -} - -#[test] -fn scope_escaped_ids_2() { - test("#u-m\\00002b {}", ":local(#u-m\\00002b) {}") + test("#\\#test {}", ":local(#\\#test) {}"); + test("#u-m\\00002b {}", ":local(#u-m\\00002b) {}"); } #[test] fn scope_multiple_selectors() { - test(".foo, .baz {}", ":local(.foo), :local(.baz) {}") + test(".foo, .baz {}", ":local(.foo), :local(.baz) {}"); } #[test] @@ -268,45 +264,33 @@ fn localize_multiple_animation_names() { ); } -// #[test] -// fn not_localize_revert() { -// test( -// ".foo { animation: revert; }", -// ":local(.foo) { animation: revert; }", -// ); -// } - -// #[test] -// fn not_localize_revert_2() { -// test( -// ".foo { animation-name: revert; }", -// ":local(.foo) { animation-name: revert; }", -// ); -// } - -// #[test] -// fn not_localize_revert_3() { -// test( -// ".foo { animation-name: revert, foo, none; }", -// ":local(.foo) { animation-name: revert, :local(foo), none; }", -// ); -// } - -// #[test] -// fn not_localize_revert_layer() { -// test( -// ".foo { animation: revert-layer; }", -// ":local(.foo) { animation: revert-layer; }", -// ); -// } - -// #[test] -// fn not_localize_revert_layer_2() { -// test( -// ".foo { animation-name: revert-layer; }", -// ":local(.foo) { animation-name: revert-layer; }", -// ); -// } +#[test] +fn not_localize_revert() { + test( + ".foo { animation: revert; }", + ":local(.foo) { animation: revert; }", + ); + test( + ".foo { animation-name: revert; }", + ":local(.foo) { animation-name: revert; }", + ); + test( + ".foo { animation-name: revert, foo, none; }", + ":local(.foo) { animation-name: revert, :local(foo), none; }", + ); +} + +#[test] +fn not_localize_revert_layer() { + test( + ".foo { animation: revert-layer; }", + ":local(.foo) { animation: revert-layer; }", + ); + test( + ".foo { animation-name: revert-layer; }", + ":local(.foo) { animation-name: revert-layer; }", + ); +} #[test] fn localize_animation_using_special_characters() { @@ -350,4 +334,48 @@ fn localize_animation_using_special_characters() { ".foo { animation: 😃bounce😃; }", ":local(.foo) { animation: :local(😃bounce😃); }", ); + test( + ".foo { animation: --foo; }", + ":local(.foo) { animation: :local(--foo); }", + ); +} + +#[test] +fn not_localize_name_in_nested_function() { + test( + ".foo { animation: fade .2s var(--easeOutQuart) .1s forwards }", + ":local(.foo) { animation: :local(fade) .2s var(--easeOutQuart) .1s forwards }", + ); + test( + ".foo { animation: fade .2s env(FOO_BAR) .1s forwards, name }", + ":local(.foo) { animation: :local(fade) .2s env(FOO_BAR) .1s forwards, :local(name) }", + ); + test( + ".foo { animation: var(--foo-bar) .1s forwards, name }", + ":local(.foo) { animation: var(--foo-bar) .1s forwards, :local(name) }", + ); + test( + ".foo { animation: var(--foo-bar) .1s forwards name, name }", + ":local(.foo) { animation: var(--foo-bar) .1s forwards :local(name), :local(name) }", + ); +} + +#[test] +fn localize_animation() { + test( + ".foo { animation: a; }", + ":local(.foo) { animation: :local(a); }", + ); + test( + ".foo { animation: bar 5s, foobar; }", + ":local(.foo) { animation: :local(bar) 5s, :local(foobar); }", + ); + test( + ".foo { animation: ease ease; }", + ":local(.foo) { animation: ease :local(ease); }", + ); + test( + ".foo { animation: 0s ease 0s 1 normal none test running; }", + ":local(.foo) { animation: 0s ease 0s 1 normal none :local(test) running; }", + ); } diff --git a/tests/test.rs b/tests/test.rs index 986ac00..3e1df5b 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -328,12 +328,15 @@ fn assert_icss_export_dependency(_input: &str, dependency: &Dependency, prop: &s fn lexer_start() { let mut l = Lexer::from(""); assert_lexer_state(&l, None, None, None, Some(0), None, None); - assert_eq!(l.consume(), None); + l.consume(); + assert_eq!(l.cur(), None); assert_lexer_state(&l, None, Some(0), None, None, None, None); - assert_eq!(l.consume(), None); + l.consume(); + assert_eq!(l.cur(), None); let mut l = Lexer::from("0壹👂삼"); assert_lexer_state(&l, None, None, Some('0'), Some(0), Some('壹'), Some(1)); - assert_eq!(l.consume(), Some('0')); + l.consume(); + assert_eq!(l.cur(), Some('0')); assert_lexer_state( &l, Some('0'), @@ -343,7 +346,8 @@ fn lexer_start() { Some('👂'), Some(4), ); - assert_eq!(l.consume(), Some('壹')); + l.consume(); + assert_eq!(l.cur(), Some('壹')); assert_lexer_state( &l, Some('壹'), @@ -353,13 +357,17 @@ fn lexer_start() { Some('삼'), Some(8), ); - assert_eq!(l.consume(), Some('👂')); + l.consume(); + assert_eq!(l.cur(), Some('👂')); assert_lexer_state(&l, Some('👂'), Some(4), Some('삼'), Some(8), None, Some(11)); - assert_eq!(l.consume(), Some('삼')); + l.consume(); + assert_eq!(l.cur(), Some('삼')); assert_lexer_state(&l, Some('삼'), Some(8), None, Some(11), None, None); - assert_eq!(l.consume(), None); + l.consume(); + assert_eq!(l.cur(), None); assert_lexer_state(&l, None, Some(11), None, None, None, None); - assert_eq!(l.consume(), None); + l.consume(); + assert_eq!(l.cur(), None); } #[test] @@ -1015,7 +1023,7 @@ fn css_modules_keyframes_1() { animation: 3s ease-in 1s 2 reverse both paused localkeyframes, localkeyframes2; --theme-color1: red; --theme-color2: blue; - } + } "#}; let (dependencies, warnings) = collect_css_modules_dependencies(input); assert!(warnings.is_empty()); @@ -1045,7 +1053,7 @@ fn css_modules_keyframes_2() { var(--animation-name) 3s, 3s linear 1s infinite running env(slidein), 3s linear env(slidein, var(--baz)) infinite running slidein; - } + } "#}; let (dependencies, warnings) = collect_css_modules_dependencies(input); assert!(warnings.is_empty());