Skip to content

Commit

Permalink
fix CSS module scoping with variables
Browse files Browse the repository at this point in the history
fixes #194
  • Loading branch information
devongovett committed May 15, 2024
1 parent 83839a9 commit fb4b334
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 13 deletions.
93 changes: 93 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23672,6 +23672,99 @@ mod tests {
},
);

css_modules_test(
r#"
.test {
animation: rotate var(--duration) linear infinite;
}
"#,
indoc! {r#"
.EgL3uq_test {
animation: EgL3uq_rotate var(--duration) linear infinite;
}
"#},
map! {
"test" => "EgL3uq_test",
"rotate" => "EgL3uq_rotate" referenced: true
},
HashMap::new(),
Default::default(),
);
css_modules_test(
r#"
.test {
animation: none var(--duration);
}
"#,
indoc! {r#"
.EgL3uq_test {
animation: none var(--duration);
}
"#},
map! {
"test" => "EgL3uq_test"
},
HashMap::new(),
Default::default(),
);
css_modules_test(
r#"
.test {
animation: var(--animation);
}
"#,
indoc! {r#"
.EgL3uq_test {
animation: var(--animation);
}
"#},
map! {
"test" => "EgL3uq_test"
},
HashMap::new(),
Default::default(),
);
css_modules_test(
r#"
.test {
animation: rotate var(--duration);
}
"#,
indoc! {r#"
.EgL3uq_test {
animation: rotate var(--duration);
}
"#},
map! {
"test" => "EgL3uq_test"
},
HashMap::new(),
crate::css_modules::Config {
animation: false,
..Default::default()
}
);
css_modules_test(
r#"
.test {
animation: "rotate" var(--duration);
}
"#,
indoc! {r#"
.EgL3uq_test {
animation: EgL3uq_rotate var(--duration);
}
"#},
map! {
"test" => "EgL3uq_test",
"rotate" => "EgL3uq_rotate" referenced: true
},
HashMap::new(),
crate::css_modules::Config {
..Default::default()
}
);

// Stable hashes between project roots.
fn test_project_root(project_root: &str, filename: &str, hash: &str) {
let stylesheet = StyleSheet::parse(
Expand Down
52 changes: 39 additions & 13 deletions src/properties/animation.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
//! CSS properties related to keyframe animations.

use std::borrow::Cow;

use crate::context::PropertyHandlerContext;
use crate::declaration::{DeclarationBlock, DeclarationList};
use crate::error::{ParserError, PrinterError};
use crate::macros::*;
use crate::prefixes::Feature;
use crate::printer::Printer;
use crate::properties::{Property, PropertyId, VendorPrefix};
use crate::properties::{Property, PropertyId, TokenOrValue, VendorPrefix};
use crate::traits::{Parse, PropertyHandler, Shorthand, ToCss, Zero};
use crate::values::number::CSSNumber;
use crate::values::string::CowArcStr;
Expand Down Expand Up @@ -346,8 +348,6 @@ impl<'i> PropertyHandler<'i> for AnimationHandler<'i> {
dest: &mut DeclarationList<'i>,
context: &mut PropertyHandlerContext<'i, '_>,
) -> bool {
use Property::*;

macro_rules! maybe_flush {
($prop: ident, $val: expr, $vp: ident) => {{
// If two vendor prefixes for the same property have different
Expand Down Expand Up @@ -376,15 +376,15 @@ impl<'i> PropertyHandler<'i> for AnimationHandler<'i> {
}

match property {
AnimationName(val, vp) => property!(names, val, vp),
AnimationDuration(val, vp) => property!(durations, val, vp),
AnimationTimingFunction(val, vp) => property!(timing_functions, val, vp),
AnimationIterationCount(val, vp) => property!(iteration_counts, val, vp),
AnimationDirection(val, vp) => property!(directions, val, vp),
AnimationPlayState(val, vp) => property!(play_states, val, vp),
AnimationDelay(val, vp) => property!(delays, val, vp),
AnimationFillMode(val, vp) => property!(fill_modes, val, vp),
Animation(val, vp) => {
Property::AnimationName(val, vp) => property!(names, val, vp),
Property::AnimationDuration(val, vp) => property!(durations, val, vp),
Property::AnimationTimingFunction(val, vp) => property!(timing_functions, val, vp),
Property::AnimationIterationCount(val, vp) => property!(iteration_counts, val, vp),
Property::AnimationDirection(val, vp) => property!(directions, val, vp),
Property::AnimationPlayState(val, vp) => property!(play_states, val, vp),
Property::AnimationDelay(val, vp) => property!(delays, val, vp),
Property::AnimationFillMode(val, vp) => property!(fill_modes, val, vp),
Property::Animation(val, vp) => {
let names = val.iter().map(|b| b.name.clone()).collect();
maybe_flush!(names, &names, vp);

Expand Down Expand Up @@ -418,7 +418,33 @@ impl<'i> PropertyHandler<'i> for AnimationHandler<'i> {
property!(delays, &delays, vp);
property!(fill_modes, &fill_modes, vp);
}
Unparsed(val) if is_animation_property(&val.property_id) => {
Property::Unparsed(val) if is_animation_property(&val.property_id) => {
let mut val = Cow::Borrowed(val);
if matches!(val.property_id, PropertyId::Animation(_)) {
use crate::properties::custom::Token;

// Find an identifier that isn't a keyword and replace it with an
// AnimationName token so it is scoped in CSS modules.
for token in &mut val.to_mut().value.0 {
match token {
TokenOrValue::Token(Token::Ident(id)) => {
if AnimationDirection::parse_string(&id).is_err()
&& AnimationPlayState::parse_string(&id).is_err()
&& AnimationFillMode::parse_string(&id).is_err()
&& !EasingFunction::is_ident(&id)
&& id.as_ref() != "infinite"
{
*token = TokenOrValue::AnimationName(AnimationName::Ident(CustomIdent(id.clone())));
}
}
TokenOrValue::Token(Token::String(s)) => {
*token = TokenOrValue::AnimationName(AnimationName::String(s.clone()));
}
_ => {}
}
}
}

self.flush(dest, context);
dest.push(Property::Unparsed(
val.get_prefixed(context.targets, Feature::Animation),
Expand Down
7 changes: 7 additions & 0 deletions src/properties/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use cssparser::*;

#[cfg(feature = "serde")]
use crate::serialization::ValueWrapper;
use super::AnimationName;

/// A CSS custom property, representing any unknown property.
#[derive(Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -241,6 +242,8 @@ pub enum TokenOrValue<'i> {
Resolution(Resolution),
/// A dashed ident.
DashedIdent(DashedIdent<'i>),
/// An animation name.
AnimationName(AnimationName<'i>),
}

impl<'i> From<Token<'i>> for TokenOrValue<'i> {
Expand Down Expand Up @@ -590,6 +593,10 @@ impl<'i> TokenList<'i> {
v.to_css(dest)?;
false
}
TokenOrValue::AnimationName(v) => {
v.to_css(dest)?;
false
}
TokenOrValue::Token(token) => match token {
Token::Delim(d) => {
if *d == '+' || *d == '-' {
Expand Down

0 comments on commit fb4b334

Please sign in to comment.