Skip to content

Commit

Permalink
fix(css/modules): Allow any order of composes (#8930)
Browse files Browse the repository at this point in the history
**Related issue:**

 - Closes #8240
  • Loading branch information
kdy1 authored May 7, 2024
1 parent ad1cc5f commit 7014c63
Show file tree
Hide file tree
Showing 10 changed files with 264 additions and 192 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/swc_css_modules/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ swc_css_parser = { version = "0.150.33", path = "../swc_css_parser" }
swc_css_visit = { version = "0.139.22", path = "../swc_css_visit" }

[dev-dependencies]
indexmap = { workspace = true, features = ["serde"] }
serde_json = { workspace = true }

swc_css_compat = { version = "0.27.35", path = "../swc_css_compat" }
Expand Down
67 changes: 46 additions & 21 deletions crates/swc_css_modules/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,50 @@ pub fn compile<'a>(ss: &mut Stylesheet, config: impl 'a + TransformConfig) -> Tr

ss.visit_mut_with(&mut compiler);

fn add(result: &mut TransformResult, data: &Data, key: &JsWord, composes: &[CssClassName]) {
let mut extra_classes = vec![];
{
let class_names = result.renamed.entry(key.clone()).or_default();

class_names.extend(composes.iter().cloned());
}

for composed_class_name in composes.iter() {
if let CssClassName::Local { name } = composed_class_name {
if let Some(original_class_name) = data.renamed_to_orig.get(&name.value) {
extra_classes.extend(
result
.renamed
.entry(original_class_name.clone())
.or_default()
.split_at(1)
.1
.to_vec(),
);
}
}
}

{
let class_names = result.renamed.entry(key.clone()).or_default();

class_names.extend(extra_classes);
}
}

let composes = compiler.data.composes_inherit.take();

for (key, composes) in &composes {
add(&mut compiler.result, &compiler.data, key, composes);
}
for (key, composes) in &composes {
add(&mut compiler.result, &compiler.data, key, composes);
}
compiler.result.renamed.iter_mut().for_each(|(_, v)| {
v.sort();
v.dedup();
});

compiler.result
}

Expand All @@ -76,6 +120,7 @@ where
struct Data {
/// Context for `composes`
composes_for_current: Option<Vec<CssClassName>>,
composes_inherit: Vec<(JsWord, Vec<CssClassName>)>,

renamed_to_orig: FxHashMap<JsWord, JsWord>,
orig_to_renamed: FxHashMap<JsWord, JsWord>,
Expand Down Expand Up @@ -214,27 +259,7 @@ where
.cloned();

if let Some(key) = key {
let mut renamed = self.result.renamed.clone();
let class_names = self.result.renamed.entry(key).or_default();

class_names.extend(composes.clone());

for composed_class_name in composes.iter() {
if let CssClassName::Local { name } = composed_class_name {
if let Some(original_class_name) =
self.data.renamed_to_orig.get(&name.value)
{
class_names.extend(
renamed
.entry(original_class_name.clone())
.or_default()
.split_at(1)
.1
.to_vec(),
);
}
}
}
self.data.composes_inherit.push((key, composes.clone()));
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions crates/swc_css_modules/tests/fixture.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::path::PathBuf;

use rustc_hash::FxHashMap;
use indexmap::IndexMap;
use serde::Serialize;
use swc_atoms::JsWord;
use swc_css_codegen::{
Expand Down Expand Up @@ -89,7 +89,7 @@ fn compile(input: PathBuf) {
.unwrap();

if !transform_result.renamed.is_empty() {
let transformed_classes = &transform_result
let mut transformed_classes = transform_result
.renamed
.into_iter()
.map(|(k, v)| {
Expand All @@ -113,7 +113,9 @@ fn compile(input: PathBuf) {
.collect::<Vec<_>>(),
)
})
.collect::<FxHashMap<_, _>>();
.collect::<IndexMap<_, _>>();

transformed_classes.sort_keys();

NormalizedOutput::compare_json_to_file(
&transformed_classes,
Expand Down
3 changes: 3 additions & 0 deletions crates/swc_css_modules/tests/fixture/issue-8240.compiled.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.__local__root-class {}
.__local__chain1 {}
.__local__chain2 {}
8 changes: 8 additions & 0 deletions crates/swc_css_modules/tests/fixture/issue-8240.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.root-class {
composes: chain1;
}
.chain1 {
composes: chain2;
}
.chain2 {
}
32 changes: 32 additions & 0 deletions crates/swc_css_modules/tests/fixture/issue-8240.transform.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"chain1": [
{
"name": "__local__chain1",
"type": "local"
},
{
"name": "__local__chain2",
"type": "local"
}
],
"chain2": [
{
"name": "__local__chain2",
"type": "local"
}
],
"root-class": [
{
"name": "__local__root-class",
"type": "local"
},
{
"name": "__local__chain1",
"type": "local"
},
{
"name": "__local__chain2",
"type": "local"
}
]
}
Original file line number Diff line number Diff line change
@@ -1,86 +1,86 @@
{
"chain2": [
{
"type": "local",
"name": "__local__chain2"
},
{
"type": "global",
"name": "e"
},
{
"type": "import",
"name": "f",
"from": "./f.css"
}
],
"chain1": [
{
"type": "local",
"name": "__local__chain1"
},
{
"type": "local",
"name": "__local__chain2"
},
{
"type": "global",
"name": "c"
},
{
"type": "import",
"name": "d",
"from": "./d.css"
},
{
"type": "global",
"name": "e"
},
{
"type": "import",
"name": "f",
"from": "./f.css"
}
],
"root-class": [
{
"type": "local",
"name": "__local__root-class"
},
{
"type": "local",
"name": "__local__chain1"
},
{
"type": "global",
"name": "a"
},
{
"type": "import",
"name": "b",
"from": "./b.css"
},
{
"type": "local",
"name": "__local__chain2"
},
{
"type": "global",
"name": "c"
},
{
"type": "import",
"name": "d",
"from": "./d.css"
},
{
"type": "global",
"name": "e"
},
{
"type": "import",
"name": "f",
"from": "./f.css"
}
]
"chain1": [
{
"name": "__local__chain1",
"type": "local"
},
{
"name": "__local__chain2",
"type": "local"
},
{
"name": "e",
"type": "global"
},
{
"name": "c",
"type": "global"
},
{
"from": "./f.css",
"name": "f",
"type": "import"
},
{
"from": "./d.css",
"name": "d",
"type": "import"
}
],
"chain2": [
{
"name": "__local__chain2",
"type": "local"
},
{
"name": "e",
"type": "global"
},
{
"from": "./f.css",
"name": "f",
"type": "import"
}
],
"root-class": [
{
"name": "__local__chain2",
"type": "local"
},
{
"name": "__local__root-class",
"type": "local"
},
{
"name": "__local__chain1",
"type": "local"
},
{
"name": "e",
"type": "global"
},
{
"name": "c",
"type": "global"
},
{
"name": "a",
"type": "global"
},
{
"from": "./f.css",
"name": "f",
"type": "import"
},
{
"from": "./d.css",
"name": "d",
"type": "import"
},
{
"from": "./b.css",
"name": "b",
"type": "import"
}
]
}
Loading

0 comments on commit 7014c63

Please sign in to comment.