Skip to content

Commit d176917

Browse files
committed
feat: 增加 pseudo_key
1 parent 6dfbcc9 commit d176917

File tree

11 files changed

+387
-108
lines changed

11 files changed

+387
-108
lines changed

Cargo.lock

+5-57
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ html5ever = "0.26.0"
1717
indexmap = "2.2.3"
1818
lightningcss = {version = "1.0.0-alpha.45", features = ["visitor", "into_owned"]}
1919
once_cell = "1.18.0"
20-
selectors = "0.25.0"
2120
smallvec = "1.11.0"
2221
serde = { version = "1.0.130", features = ["derive"] }
2322
serde_json = "1.0.68"
@@ -29,6 +28,7 @@ flatbuffers = "24.3.25"
2928
rust_decimal = "1.36.0"
3029
rust_decimal_macros = "1.36.0"
3130
bitflags = "2.4.1"
31+
parcel_selectors = "0.26.5"
3232

3333
[build-dependencies]
3434
napi-build = "2.0.1"

__test__/fixure/pesudo.scss

+9
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,13 @@
66

77
.bbb {
88
margin-top: 30px;
9+
}
10+
11+
.hello .bbb:nth-child(-n + 3) {
12+
border: 2px solid orange;
13+
margin-bottom: 1px;
14+
}
15+
16+
.bbb:nth-child(even) {
17+
background-color: lightyellow;
918
}

__test__/fixure/style.bin

712 Bytes
Binary file not shown.

flatbuffers/stylesheet.fbs

+8
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,18 @@ table Selector {
7474
is_string:bool;
7575
}
7676

77+
table PseudoKey {
78+
integer_value:int8;
79+
bool_value:bool;
80+
is_int:bool;
81+
}
82+
7783
table Style {
7884
declarations:[DeclarationTuple];
7985
media:uint8;
8086
pseudo:uint8;
87+
pseudo_key:[PseudoKey];
88+
pseudo_val:string;
8189
selector:[Selector];
8290
}
8391

src/constants.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ pub const RN_CONVERT_STYLE_PX_FN: &'static str = "scalePx2dp";
1818
pub const RN_CONVERT_STYLE_VU_FN: &'static str = "scaleVu2dp";
1919

2020
#[repr(u32)]
21-
#[derive(Hash, PartialEq, Eq, Debug, Clone)]
21+
#[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)]
2222
pub enum Pseudo {
2323
None,
2424
Before,
2525
After,
2626
FirstChild,
2727
LastChild,
28-
NthChild(String),
28+
NthChild(i32, i32, bool),
2929
Empty,
3030
}
3131

@@ -38,7 +38,7 @@ impl Pseudo {
3838
Pseudo::After => 2,
3939
Pseudo::FirstChild => 3,
4040
Pseudo::LastChild => 4,
41-
Pseudo::NthChild(_) => 5,
41+
Pseudo::NthChild(_, _, _) => 5,
4242
Pseudo::Empty => 6,
4343
}) as f64
4444
}

src/json_writer.rs

+41-34
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,10 @@ impl JsonWriter {
4545
.filter_map(|rule_item| {
4646
Some({
4747
// 识别伪类
48-
let mut new_selector = rule_item.selector.clone();
49-
let mut pseudo_key = String::new();
50-
51-
if SUPPORT_PSEUDO_KEYS
52-
.into_iter()
53-
.any(|s| rule_item.selector.contains(s))
54-
{
55-
let key_arr = rule_item.selector.split(":").collect::<Vec<&str>>();
56-
if key_arr.len() == 2 {
57-
new_selector = key_arr[0].to_string();
58-
pseudo_key = key_arr[1].to_string();
59-
}
48+
let mut new_selector = rule_item.selector.selector.clone();
49+
let key_arr = new_selector.split(":").collect::<Vec<&str>>();
50+
if key_arr.len() == 2 {
51+
new_selector = key_arr[0].to_string();
6052
}
6153

6254
let nesting_selector = utils::split_selector(&new_selector);
@@ -147,35 +139,50 @@ impl JsonWriter {
147139
);
148140
}
149141

150-
if pseudo_key.len() > 0 {
151-
let mut pseudo_enum = None;
152-
if pseudo_key == "before" {
153-
pseudo_enum = Some(Pseudo::Before);
154-
} else if pseudo_key == "after" {
155-
pseudo_enum = Some(Pseudo::After);
156-
} else if pseudo_key == "first-child" {
157-
pseudo_enum = Some(Pseudo::FirstChild);
158-
} else if pseudo_key == "last-child" {
159-
pseudo_enum = Some(Pseudo::LastChild);
160-
} else if pseudo_key == "empty" {
161-
pseudo_enum = Some(Pseudo::Empty);
162-
} else if pseudo_key.starts_with("nth-child") {
163-
let key_arr = pseudo_key.split("(").collect::<Vec<&str>>();
164-
if key_arr.len() == 2 {
165-
let value = key_arr[1].trim_end_matches(")");
166-
pseudo_enum = Some(Pseudo::NthChild(value.to_string()));
167-
}
168-
}
169-
if let Some(pseudo_enum) = pseudo_enum {
170-
if let Pseudo::NthChild(str) = &pseudo_enum {
142+
if rule_item.selector.is_pseudo {
143+
if let Some(pseudo_enum) = &rule_item.selector.pseudo_type {
144+
if let Pseudo::NthChild(a, b, is_first) = &pseudo_enum {
145+
let value: String = if *a == 0 && *b == 0 {
146+
"".to_string()
147+
} else if *a == 0 {
148+
format!("{}", *b)
149+
} else if *b == 0 {
150+
format!("{}n", *a)
151+
} else {
152+
if *a == 1 {
153+
format!("n+{}", *b)
154+
} else {
155+
format!("{}n+{}", *a, *b)
156+
}
157+
};
171158
lit_props.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
172159
key: PropName::Ident(Ident::new("pseudo_val".into(), DUMMY_SP)),
173160
value: Box::new(Expr::Lit(Lit::Str(Str {
174161
span: DUMMY_SP,
175-
value: str.clone().into(),
162+
value: value.into(),
176163
raw: None,
177164
}))),
178165
}))));
166+
lit_props.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
167+
key: PropName::Ident(Ident::new("pseudo_key".into(), DUMMY_SP)),
168+
value: Box::new(Expr::Array(ArrayLit {
169+
span: DUMMY_SP,
170+
elems: vec![
171+
Some(ExprOrSpread {
172+
spread: None,
173+
expr: Box::new(Expr::Lit(Lit::Num(Number::from(*a as f64)))),
174+
}),
175+
Some(ExprOrSpread {
176+
spread: None,
177+
expr: Box::new(Expr::Lit(Lit::Num(Number::from(*b as f64)))),
178+
}),
179+
Some(ExprOrSpread {
180+
spread: None,
181+
expr: Box::new(Expr::Lit(Lit::Bool(Bool { span: DUMMY_SP, value: *is_first }))),
182+
}),
183+
],
184+
})),
185+
}))));
179186
};
180187
lit_props.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
181188
key: PropName::Ident(Ident::new("pseudo".into(), DUMMY_SP)),

src/lib.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ mod tests {
105105

106106
#[test]
107107
fn test_valid_input() {
108-
let json_input = json!({"fonts":[],"keyframes":[],"medias":[],"styles":[{"declarations":[[22,293],[42,4278753764u32]],"media":0,"selector":["app"]},{"declarations":[[41,4294901760u32]],"media":0,"selector":["tit"]},{"declarations":[[29,24],[41,4291979550u32]],"media":0,"selector":["tit",2,"app"]},{"declarations":[[22,100],[25,100]],"media":0,"selector":["img"]}, {"declarations":[[79,"hello"]],"media":0,"pseudo":1,"selector":["hello"]}]}).to_string();
108+
let json_input = json!({"fonts":[],"keyframes":[],"medias":[],"styles":[{"declarations":[[22,293],[42,4278753764u32]],"media":0,"selector":["app"]},{"declarations":[[41,4294901760u32]],"media":0,"selector":["tit"]},{"declarations":[[29,24],[41,4291979550u32]],"media":0,"selector":["tit",2,"app"]},{"declarations":[[22,100],[25,100]],"media":0,"selector":["img"]}, {"declarations":[[79,"hello"]],"media":0,"pseudo":1,"selector":["hello"]},{"declarations":[[42,4294967264u32]],"media":0,"pseudo":5,"pseudo_key":[2,0,true],"pseudo_val":"2n","selector":["bbb"]}]}).to_string();
109109

110110
let result = convert_json_to_flatbuffer(&json_input);
111111
assert!(result.is_ok());
@@ -124,7 +124,7 @@ mod tests {
124124

125125
// 验证 styles
126126
let styles = style_sheet.styles().unwrap();
127-
assert_eq!(styles.len(), 5); // 根据实际情况调整
127+
assert_eq!(styles.len(), 6); // 根据实际情况调整
128128
let first_style = styles.get(0);
129129
assert_eq!(first_style.declarations().unwrap().len(), 2);
130130

@@ -164,5 +164,27 @@ mod tests {
164164
let first_selector = selector.get(0);
165165
assert_eq!(first_selector.string_value().unwrap(), "hello");
166166
assert_eq!(fifth_style.pseudo(), 1);
167+
168+
let sixth_style = styles.get(5);
169+
assert_eq!(sixth_style.declarations().unwrap().len(), 1);
170+
let selector = sixth_style.selector().unwrap();
171+
assert_eq!(selector.len(), 1);
172+
let first_selector = selector.get(0);
173+
assert_eq!(first_selector.string_value().unwrap(), "bbb");
174+
assert_eq!(sixth_style.pseudo(), 5);
175+
assert_eq!(sixth_style.pseudo_key().unwrap().len(), 3);
176+
let first_pseudo_key = sixth_style.pseudo_key().unwrap().get(0);
177+
assert_eq!(first_pseudo_key.integer_value(), 2);
178+
assert_eq!(first_pseudo_key.bool_value(), false);
179+
assert_eq!(first_pseudo_key.is_int(), true);
180+
let second_pseudo_key = sixth_style.pseudo_key().unwrap().get(1);
181+
assert_eq!(second_pseudo_key.integer_value(), 0);
182+
assert_eq!(second_pseudo_key.bool_value(), false);
183+
assert_eq!(second_pseudo_key.is_int(), true);
184+
let third_pseudo_key = sixth_style.pseudo_key().unwrap().get(2);
185+
assert_eq!(third_pseudo_key.integer_value(), 0);
186+
assert_eq!(third_pseudo_key.bool_value(), true);
187+
assert_eq!(third_pseudo_key.is_int(), false);
188+
assert_eq!(sixth_style.pseudo_val().unwrap(), "2n");
167189
}
168190
}

0 commit comments

Comments
 (0)