Skip to content

Commit fb4b334

Browse files
committed
fix CSS module scoping with variables
fixes parcel-bundler#194
1 parent 83839a9 commit fb4b334

File tree

3 files changed

+139
-13
lines changed

3 files changed

+139
-13
lines changed

src/lib.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23672,6 +23672,99 @@ mod tests {
2367223672
},
2367323673
);
2367423674

23675+
css_modules_test(
23676+
r#"
23677+
.test {
23678+
animation: rotate var(--duration) linear infinite;
23679+
}
23680+
"#,
23681+
indoc! {r#"
23682+
.EgL3uq_test {
23683+
animation: EgL3uq_rotate var(--duration) linear infinite;
23684+
}
23685+
"#},
23686+
map! {
23687+
"test" => "EgL3uq_test",
23688+
"rotate" => "EgL3uq_rotate" referenced: true
23689+
},
23690+
HashMap::new(),
23691+
Default::default(),
23692+
);
23693+
css_modules_test(
23694+
r#"
23695+
.test {
23696+
animation: none var(--duration);
23697+
}
23698+
"#,
23699+
indoc! {r#"
23700+
.EgL3uq_test {
23701+
animation: none var(--duration);
23702+
}
23703+
"#},
23704+
map! {
23705+
"test" => "EgL3uq_test"
23706+
},
23707+
HashMap::new(),
23708+
Default::default(),
23709+
);
23710+
css_modules_test(
23711+
r#"
23712+
.test {
23713+
animation: var(--animation);
23714+
}
23715+
"#,
23716+
indoc! {r#"
23717+
.EgL3uq_test {
23718+
animation: var(--animation);
23719+
}
23720+
"#},
23721+
map! {
23722+
"test" => "EgL3uq_test"
23723+
},
23724+
HashMap::new(),
23725+
Default::default(),
23726+
);
23727+
css_modules_test(
23728+
r#"
23729+
.test {
23730+
animation: rotate var(--duration);
23731+
}
23732+
"#,
23733+
indoc! {r#"
23734+
.EgL3uq_test {
23735+
animation: rotate var(--duration);
23736+
}
23737+
"#},
23738+
map! {
23739+
"test" => "EgL3uq_test"
23740+
},
23741+
HashMap::new(),
23742+
crate::css_modules::Config {
23743+
animation: false,
23744+
..Default::default()
23745+
}
23746+
);
23747+
css_modules_test(
23748+
r#"
23749+
.test {
23750+
animation: "rotate" var(--duration);
23751+
}
23752+
"#,
23753+
indoc! {r#"
23754+
.EgL3uq_test {
23755+
animation: EgL3uq_rotate var(--duration);
23756+
}
23757+
"#},
23758+
map! {
23759+
"test" => "EgL3uq_test",
23760+
"rotate" => "EgL3uq_rotate" referenced: true
23761+
},
23762+
HashMap::new(),
23763+
crate::css_modules::Config {
23764+
..Default::default()
23765+
}
23766+
);
23767+
2367523768
// Stable hashes between project roots.
2367623769
fn test_project_root(project_root: &str, filename: &str, hash: &str) {
2367723770
let stylesheet = StyleSheet::parse(

src/properties/animation.rs

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
//! CSS properties related to keyframe animations.
22
3+
use std::borrow::Cow;
4+
35
use crate::context::PropertyHandlerContext;
46
use crate::declaration::{DeclarationBlock, DeclarationList};
57
use crate::error::{ParserError, PrinterError};
68
use crate::macros::*;
79
use crate::prefixes::Feature;
810
use crate::printer::Printer;
9-
use crate::properties::{Property, PropertyId, VendorPrefix};
11+
use crate::properties::{Property, PropertyId, TokenOrValue, VendorPrefix};
1012
use crate::traits::{Parse, PropertyHandler, Shorthand, ToCss, Zero};
1113
use crate::values::number::CSSNumber;
1214
use crate::values::string::CowArcStr;
@@ -346,8 +348,6 @@ impl<'i> PropertyHandler<'i> for AnimationHandler<'i> {
346348
dest: &mut DeclarationList<'i>,
347349
context: &mut PropertyHandlerContext<'i, '_>,
348350
) -> bool {
349-
use Property::*;
350-
351351
macro_rules! maybe_flush {
352352
($prop: ident, $val: expr, $vp: ident) => {{
353353
// If two vendor prefixes for the same property have different
@@ -376,15 +376,15 @@ impl<'i> PropertyHandler<'i> for AnimationHandler<'i> {
376376
}
377377

378378
match property {
379-
AnimationName(val, vp) => property!(names, val, vp),
380-
AnimationDuration(val, vp) => property!(durations, val, vp),
381-
AnimationTimingFunction(val, vp) => property!(timing_functions, val, vp),
382-
AnimationIterationCount(val, vp) => property!(iteration_counts, val, vp),
383-
AnimationDirection(val, vp) => property!(directions, val, vp),
384-
AnimationPlayState(val, vp) => property!(play_states, val, vp),
385-
AnimationDelay(val, vp) => property!(delays, val, vp),
386-
AnimationFillMode(val, vp) => property!(fill_modes, val, vp),
387-
Animation(val, vp) => {
379+
Property::AnimationName(val, vp) => property!(names, val, vp),
380+
Property::AnimationDuration(val, vp) => property!(durations, val, vp),
381+
Property::AnimationTimingFunction(val, vp) => property!(timing_functions, val, vp),
382+
Property::AnimationIterationCount(val, vp) => property!(iteration_counts, val, vp),
383+
Property::AnimationDirection(val, vp) => property!(directions, val, vp),
384+
Property::AnimationPlayState(val, vp) => property!(play_states, val, vp),
385+
Property::AnimationDelay(val, vp) => property!(delays, val, vp),
386+
Property::AnimationFillMode(val, vp) => property!(fill_modes, val, vp),
387+
Property::Animation(val, vp) => {
388388
let names = val.iter().map(|b| b.name.clone()).collect();
389389
maybe_flush!(names, &names, vp);
390390

@@ -418,7 +418,33 @@ impl<'i> PropertyHandler<'i> for AnimationHandler<'i> {
418418
property!(delays, &delays, vp);
419419
property!(fill_modes, &fill_modes, vp);
420420
}
421-
Unparsed(val) if is_animation_property(&val.property_id) => {
421+
Property::Unparsed(val) if is_animation_property(&val.property_id) => {
422+
let mut val = Cow::Borrowed(val);
423+
if matches!(val.property_id, PropertyId::Animation(_)) {
424+
use crate::properties::custom::Token;
425+
426+
// Find an identifier that isn't a keyword and replace it with an
427+
// AnimationName token so it is scoped in CSS modules.
428+
for token in &mut val.to_mut().value.0 {
429+
match token {
430+
TokenOrValue::Token(Token::Ident(id)) => {
431+
if AnimationDirection::parse_string(&id).is_err()
432+
&& AnimationPlayState::parse_string(&id).is_err()
433+
&& AnimationFillMode::parse_string(&id).is_err()
434+
&& !EasingFunction::is_ident(&id)
435+
&& id.as_ref() != "infinite"
436+
{
437+
*token = TokenOrValue::AnimationName(AnimationName::Ident(CustomIdent(id.clone())));
438+
}
439+
}
440+
TokenOrValue::Token(Token::String(s)) => {
441+
*token = TokenOrValue::AnimationName(AnimationName::String(s.clone()));
442+
}
443+
_ => {}
444+
}
445+
}
446+
}
447+
422448
self.flush(dest, context);
423449
dest.push(Property::Unparsed(
424450
val.get_prefixed(context.targets, Feature::Animation),

src/properties/custom.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use cssparser::*;
2929

3030
#[cfg(feature = "serde")]
3131
use crate::serialization::ValueWrapper;
32+
use super::AnimationName;
3233

3334
/// A CSS custom property, representing any unknown property.
3435
#[derive(Debug, Clone, PartialEq)]
@@ -241,6 +242,8 @@ pub enum TokenOrValue<'i> {
241242
Resolution(Resolution),
242243
/// A dashed ident.
243244
DashedIdent(DashedIdent<'i>),
245+
/// An animation name.
246+
AnimationName(AnimationName<'i>),
244247
}
245248

246249
impl<'i> From<Token<'i>> for TokenOrValue<'i> {
@@ -590,6 +593,10 @@ impl<'i> TokenList<'i> {
590593
v.to_css(dest)?;
591594
false
592595
}
596+
TokenOrValue::AnimationName(v) => {
597+
v.to_css(dest)?;
598+
false
599+
}
593600
TokenOrValue::Token(token) => match token {
594601
Token::Delim(d) => {
595602
if *d == '+' || *d == '-' {

0 commit comments

Comments
 (0)