Skip to content

Commit 4a1dd61

Browse files
committed
Fix selector issue
1 parent cf4b3fc commit 4a1dd61

28 files changed

+176
-173
lines changed

.changeset/gentle-peas-double.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@devup-ui/wasm": patch
3+
---
4+
5+
Fix selector issue

libs/css/src/lib.rs

Lines changed: 61 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use crate::StyleSelector::{Dual, Media, Postfix, Prefix};
21
use once_cell::sync::Lazy;
32
use regex::Regex;
43
use serde::{Deserialize, Serialize};
@@ -10,20 +9,18 @@ use std::sync::Mutex;
109

1110
static SELECTOR_ORDER_MAP: Lazy<HashMap<String, u8>> = Lazy::new(|| {
1211
let mut map = HashMap::new();
13-
map.insert("disabled".to_string(), 5);
14-
map.insert("selected".to_string(), 4);
15-
map.insert("active".to_string(), 3);
16-
map.insert("focus".to_string(), 2);
17-
map.insert("hover".to_string(), 1);
12+
map.insert("&:disabled".to_string(), 5);
13+
map.insert("&:selected".to_string(), 4);
14+
map.insert("&:active".to_string(), 3);
15+
map.insert("&:focus".to_string(), 2);
16+
map.insert("&:hover".to_string(), 1);
1817
map
1918
});
2019

2120
#[derive(Debug, PartialEq, Clone, Hash, Eq, Serialize, Deserialize)]
2221
pub enum StyleSelector {
23-
Postfix(String),
24-
Prefix(String),
2522
Media(String),
26-
Dual(String, String),
23+
Selector(String),
2724
}
2825

2926
impl PartialOrd for StyleSelector {
@@ -35,77 +32,72 @@ impl PartialOrd for StyleSelector {
3532
impl Ord for StyleSelector {
3633
fn cmp(&self, other: &Self) -> Ordering {
3734
match (self, other) {
38-
(Media(a), Media(b)) => a.cmp(b),
39-
(Media(_), _) => Ordering::Less,
40-
(_, Media(_)) => Ordering::Greater,
41-
(Postfix(a), Postfix(b)) => SELECTOR_ORDER_MAP
35+
(StyleSelector::Media(a), StyleSelector::Media(b)) => a.cmp(b),
36+
(StyleSelector::Selector(a), StyleSelector::Selector(b)) => SELECTOR_ORDER_MAP
4237
.get(a)
43-
.unwrap_or(&0)
44-
.cmp(SELECTOR_ORDER_MAP.get(b).unwrap_or(&0)),
45-
(Prefix(a), Prefix(b)) => a.cmp(b),
46-
(Dual(p1, a), Dual(p2, b)) => match p1.cmp(p2) {
47-
Ordering::Equal => SELECTOR_ORDER_MAP
48-
.get(a)
49-
.unwrap_or(&0)
50-
.cmp(SELECTOR_ORDER_MAP.get(b).unwrap_or(&0)),
51-
x => x,
52-
},
53-
(Postfix(_), _) => Ordering::Less,
54-
(Prefix(_), Postfix(_)) => Ordering::Greater,
55-
(Prefix(_), Dual(_, _)) => Ordering::Less,
56-
(Dual(_, _), _) => Ordering::Greater,
38+
.unwrap_or(if a.starts_with("&") { &0 } else { &99 })
39+
.cmp(SELECTOR_ORDER_MAP.get(b).unwrap_or(if b.starts_with("&") {
40+
&0
41+
} else {
42+
&99
43+
})),
44+
(StyleSelector::Media(_), StyleSelector::Selector(_)) => Ordering::Greater,
45+
(StyleSelector::Selector(_), StyleSelector::Media(_)) => Ordering::Less,
5746
}
5847
}
5948
}
6049

6150
impl From<&str> for StyleSelector {
6251
fn from(value: &str) -> Self {
6352
if value.contains("&") {
64-
let t: Vec<_> = value.split("&").collect();
65-
if let Prefix(v) = t[0].into() {
66-
if t[1].is_empty() {
67-
Prefix(v)
68-
} else {
69-
Dual(v, t[1].to_string())
70-
}
71-
} else {
72-
Postfix(t[1].to_string())
73-
}
53+
StyleSelector::Selector(value.to_string())
7454
} else if let Some(s) = value.strip_prefix("group") {
7555
let post = to_kebab_case(s);
76-
Prefix(format!(
77-
"{}{}{}",
56+
StyleSelector::Selector(format!(
57+
"{}{}{} &",
7858
"*[role=group]",
7959
get_selector_separator(&post),
8060
post
8161
))
8262
} else if let Some(s) = value.strip_prefix("theme") {
8363
// first character should lower case
84-
Prefix(format!(
85-
":root[data-theme={}{}]",
64+
StyleSelector::Selector(format!(
65+
":root[data-theme={}{}] &",
8666
s.chars().next().unwrap().to_ascii_lowercase(),
8767
&s[1..]
8868
))
8969
} else if value == "print" {
90-
Media("print".to_string())
70+
StyleSelector::Media("print".to_string())
9171
} else if value.ends_with(" ") {
92-
Prefix(value.trim().to_string())
72+
StyleSelector::Selector(format!("{} &", value.trim()))
9373
} else {
94-
Postfix(to_kebab_case(value))
74+
let post = to_kebab_case(value);
75+
76+
StyleSelector::Selector(format!("&{}{}", get_selector_separator(&post), post))
9577
}
9678
}
9779
}
9880

81+
impl From<[&str; 2]> for StyleSelector {
82+
fn from(value: [&str; 2]) -> Self {
83+
let post = to_kebab_case(value[1]);
84+
StyleSelector::Selector(format!(
85+
"{}{}{}",
86+
StyleSelector::from(value[0]),
87+
get_selector_separator(&post),
88+
post
89+
))
90+
}
91+
}
92+
9993
impl Display for StyleSelector {
10094
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
10195
write!(
10296
f,
10397
"{}",
10498
match self {
105-
Postfix(value) => format!("-{}", value),
106-
Prefix(value) => format!("-{}-", value),
107-
Dual(prefix, postfix) => format!("-{}-{}", prefix, postfix),
108-
Media(value) => format!("@{}", value),
99+
StyleSelector::Selector(value) => value.to_string(),
100+
StyleSelector::Media(value) => format!("@{}", value),
109101
}
110102
)
111103
}
@@ -114,21 +106,8 @@ impl Display for StyleSelector {
114106
pub fn merge_selector(class_name: &str, selector: Option<&StyleSelector>) -> String {
115107
if let Some(selector) = selector {
116108
match selector {
117-
Postfix(postfix) => format!(
118-
".{}{}{}",
119-
class_name,
120-
get_selector_separator(postfix),
121-
postfix
122-
),
123-
Prefix(prefix) => format!("{} .{}", prefix, class_name),
124-
Dual(prefix, postfix) => format!(
125-
"{} .{}{}{}",
126-
prefix,
127-
class_name,
128-
get_selector_separator(postfix),
129-
postfix
130-
),
131-
Media(_) => format!(".{}", class_name),
109+
StyleSelector::Selector(value) => value.replace("&", &format!(".{}", class_name)),
110+
StyleSelector::Media(_) => format!(".{}", class_name),
132111
}
133112
} else {
134113
format!(".{}", class_name)
@@ -660,43 +639,40 @@ mod tests {
660639

661640
#[test]
662641
fn test_style_selector() {
663-
assert_eq!(StyleSelector::from("hover"), Postfix("hover".to_string()));
642+
assert_eq!(
643+
StyleSelector::from("hover"),
644+
StyleSelector::Selector("&:hover".to_string())
645+
);
664646
assert_eq!(
665647
StyleSelector::from("focusVisible"),
666-
Postfix("focus-visible".to_string())
648+
StyleSelector::Selector("&:focus-visible".to_string())
667649
);
668650
assert_eq!(
669651
StyleSelector::from("groupHover"),
670-
Prefix("*[role=group]:hover".to_string())
652+
StyleSelector::Selector("*[role=group]:hover &".to_string())
671653
);
672654
assert_eq!(
673655
StyleSelector::from("groupFocusVisible"),
674-
Prefix("*[role=group]:focus-visible".to_string())
656+
StyleSelector::Selector("*[role=group]:focus-visible &".to_string())
675657
);
676658
assert_eq!(
677659
StyleSelector::from("group1"),
678-
Prefix("*[role=group]:1".to_string())
660+
StyleSelector::Selector("*[role=group]:1 &".to_string())
679661
);
680662

681663
assert_eq!(
682-
StyleSelector::from("themeDark&placeholder"),
683-
Dual(
684-
":root[data-theme=dark]".to_string(),
685-
"placeholder".to_string()
686-
)
664+
StyleSelector::from(["themeDark", "placeholder"]),
665+
StyleSelector::Selector(":root[data-theme=dark] &::placeholder".to_string())
687666
);
688667

689-
assert_eq!(Prefix(".cls".to_string()).to_string(), "-.cls-");
690-
assert_eq!(Postfix(".cls".to_string()).to_string(), "-.cls");
691-
692668
assert_eq!(
693669
StyleSelector::from("themeLight"),
694-
Prefix(":root[data-theme=light]".to_string())
670+
StyleSelector::Selector(":root[data-theme=light] &".to_string())
695671
);
696672

697673
assert_eq!(
698674
StyleSelector::from("*[aria=disabled='true'] &:hover"),
699-
Dual("*[aria=disabled='true']".to_string(), ":hover".to_string())
675+
StyleSelector::Selector("*[aria=disabled='true'] &:hover".to_string())
700676
);
701677
}
702678

@@ -714,20 +690,24 @@ mod tests {
714690
assert_eq!(
715691
merge_selector(
716692
"cls",
717-
Some(&Prefix(":root[data-theme=dark]:hover".to_string(),)),
693+
Some(&StyleSelector::Selector(
694+
":root[data-theme=dark]:hover &".to_string(),
695+
)),
718696
),
719697
":root[data-theme=dark]:hover .cls"
720698
);
721699
assert_eq!(
722700
merge_selector(
723701
"cls",
724-
Some(&Prefix(":root[data-theme=dark]::placeholder".to_string())),
702+
Some(&StyleSelector::Selector(
703+
":root[data-theme=dark]::placeholder &".to_string()
704+
)),
725705
),
726706
":root[data-theme=dark]::placeholder .cls"
727707
);
728708

729709
assert_eq!(
730-
merge_selector("cls", Some(&"themeDark&hover".into()),),
710+
merge_selector("cls", Some(&["themeDark", "hover"].into()),),
731711
":root[data-theme=dark] .cls:hover"
732712
);
733713
}

libs/extractor/src/snapshots/extractor__tests__custom_selector-2.snap

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ ExtractOutput {
1010
value: "0.5",
1111
level: 0,
1212
selector: Some(
13-
Dual(
14-
"*[aria-diabled='true']",
15-
":hover",
13+
Selector(
14+
"*[aria-diabled='true'] &:hover",
1615
),
1716
),
1817
basic: false,

libs/extractor/src/snapshots/extractor__tests__custom_selector-3.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ ExtractOutput {
1010
value: "0.5",
1111
level: 0,
1212
selector: Some(
13-
Prefix(
14-
"*[aria-diabled='true']",
13+
Selector(
14+
"*[aria-diabled='true'] &",
1515
),
1616
),
1717
basic: false,

libs/extractor/src/snapshots/extractor__tests__custom_selector.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ ExtractOutput {
1010
value: "0.5",
1111
level: 0,
1212
selector: Some(
13-
Postfix(
14-
"[aria-diabled='true']",
13+
Selector(
14+
"&[aria-diabled='true']",
1515
),
1616
),
1717
basic: false,

libs/extractor/src/snapshots/extractor__tests__extract_selector.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ ExtractOutput {
1010
value: "4px",
1111
level: 0,
1212
selector: Some(
13-
Postfix(
14-
"hover",
13+
Selector(
14+
"&:hover",
1515
),
1616
),
1717
basic: false,

libs/extractor/src/snapshots/extractor__tests__extract_selector_with_responsive-2.snap

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ ExtractOutput {
1010
value: "40px",
1111
level: 0,
1212
selector: Some(
13-
Postfix(
14-
"hover",
13+
Selector(
14+
"&:hover",
1515
),
1616
),
1717
basic: false,
@@ -23,8 +23,8 @@ ExtractOutput {
2323
value: "80px",
2424
level: 1,
2525
selector: Some(
26-
Postfix(
27-
"hover",
26+
Selector(
27+
"&:hover",
2828
),
2929
),
3030
basic: false,

libs/extractor/src/snapshots/extractor__tests__extract_selector_with_responsive.snap

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ ExtractOutput {
1010
value: "4px",
1111
level: 0,
1212
selector: Some(
13-
Postfix(
14-
"hover",
13+
Selector(
14+
"&:hover",
1515
),
1616
),
1717
basic: false,
@@ -23,8 +23,8 @@ ExtractOutput {
2323
value: "8px",
2424
level: 1,
2525
selector: Some(
26-
Postfix(
27-
"hover",
26+
Selector(
27+
"&:hover",
2828
),
2929
),
3030
basic: false,

libs/extractor/src/snapshots/extractor__tests__extract_static_css_class_name_props-5.snap

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ ExtractOutput {
1010
value: "red",
1111
level: 0,
1212
selector: Some(
13-
Postfix(
14-
"hover",
13+
Selector(
14+
"&:hover",
1515
),
1616
),
1717
basic: false,
@@ -23,8 +23,8 @@ ExtractOutput {
2323
value: "blue",
2424
level: 0,
2525
selector: Some(
26-
Postfix(
27-
"hover",
26+
Selector(
27+
"&:hover",
2828
),
2929
),
3030
basic: false,

libs/extractor/src/snapshots/extractor__tests__group_selector_props.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ ExtractOutput {
1010
value: "red",
1111
level: 0,
1212
selector: Some(
13-
Prefix(
14-
"*[role=group]:hover",
13+
Selector(
14+
"*[role=group]:hover &",
1515
),
1616
),
1717
basic: false,

0 commit comments

Comments
 (0)