Skip to content

Commit 38e6856

Browse files
committed
feat: 支持empty选择器,支持解析createElement嵌套样式
1 parent e06ff4e commit 38e6856

File tree

5 files changed

+106
-27
lines changed

5 files changed

+106
-27
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,4 +196,4 @@ Cargo.lock
196196

197197
*.node
198198

199-
src/main.rs
199+
# src/main.rs

src/constants.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub const ENV_FUN: &'static str = "__env__";
1111
// pub const CALC_DYMAMIC_STYLE: &'static str = "calcDynamicStyle";
1212
pub const CALC_STATIC_STYLE: &'static str = "calcStaticStyle";
1313
pub const CSS_VAR_FN: &'static str = "__var_fn";
14-
pub static SUPPORT_PSEUDO_KEYS: [&'static str; 5] = [":before", ":after", ":first-child", ":last-child", ":nth-child"];
14+
pub static SUPPORT_PSEUDO_KEYS: [&'static str; 6] = [":before", ":after", ":first-child", ":last-child", ":nth-child", ":empty"];
1515

1616

1717
pub const RN_CONVERT_STYLE_PX_FN: &'static str = "scalePx2dp";

src/main.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use std::{cell::RefCell, fs, rc::Rc};
2+
use style_parser::StyleParser;
3+
use style_propetries::unit::Platform;
4+
5+
use swc_core::{
6+
ecma::codegen::{text_writer::JsWriter, Emitter},
7+
common::{comments::SingleThreadedComments, sync::Lrc, SourceMap}
8+
};
9+
use crate::{document::JSXDocument, style_write::StyleWrite};
10+
11+
12+
mod document;
13+
mod scraper;
14+
mod style_write;
15+
mod utils;
16+
mod visitor;
17+
mod constants;
18+
mod style_propetries;
19+
mod style_parser;
20+
mod parse_style_properties;
21+
22+
// component: jsx的code string
23+
// styles: css的code string
24+
// platform_string: "ReactNative" | "Harmony"
25+
26+
27+
pub fn main() {
28+
29+
let component = fs::read_to_string("__test__/fixure/pesudo.jsx").unwrap();
30+
let css = fs::read_to_string("__test__/fixure/pesudo.scss").unwrap();
31+
32+
let platform = Platform::Harmony;
33+
34+
let mut is_enable_nesting = true;
35+
36+
// 解析组件文件
37+
let cm: Lrc<SourceMap> = Default::default();
38+
let comments = SingleThreadedComments::default();
39+
let mut document = JSXDocument::new();
40+
document.parse(component, cm.clone(), &comments);
41+
42+
// 解析样式文件
43+
let mut style_parser = StyleParser::new(&document, platform.clone());
44+
style_parser.parse(&css);
45+
let style_data = style_parser.calc();
46+
47+
// 判断计算的结果是否会含有嵌套选择器
48+
if is_enable_nesting {
49+
is_enable_nesting = style_data.has_nesting;
50+
}
51+
52+
let program = Rc::new(RefCell::new(document.program.as_ref().unwrap().clone()));
53+
let jsx_record = Rc::new(RefCell::new(document.jsx_record.as_ref().unwrap().clone()));
54+
let mut style_write = StyleWrite::new(
55+
program.clone(),
56+
jsx_record.clone(),
57+
style_data.pesudo_style_record.clone(),
58+
style_data.all_style.clone(),
59+
is_enable_nesting,
60+
);
61+
style_write.write(platform, document.taro_components.clone());
62+
63+
// ast 转代码
64+
let mut buf = Vec::new();
65+
{
66+
let writer = Box::new(JsWriter::new(cm.clone(), "\n", &mut buf, None));
67+
let mut emitter = Emitter {
68+
cfg: Default::default(),
69+
cm: cm.clone(),
70+
wr: writer,
71+
comments: Some(&comments),
72+
};
73+
emitter.emit_program(&program.borrow()).unwrap();
74+
}
75+
let code = String::from_utf8(buf).unwrap().replace("\r\n", "\n");
76+
77+
println!("{}", code);
78+
}

src/parse_style_properties.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use lightningcss::{properties::{custom::TokenOrValue, Property}, stylesheet::Pri
44
use swc_core::{common::DUMMY_SP, ecma::{ast::{self}, utils::quote_ident}};
55
use swc_core::ecma::ast::*;
66

7-
use crate::{constants::ENV_FUN, style_parser::KeyFrameItem, style_propetries::{animation::Animation, aspect_ratio::AspactRatio, background::Background, background_image::BackgroundImage, background_position::BackgroundPosition, background_repeat::BackgroundRepeat, background_size::BackgroundSize, border::Border, border_color::BorderColor, border_radius::BorderRadius, border_style::BorderStyle, border_width::BorderWidth, color::ColorProperty, display::Display, expr::Expr, flex::Flex, flex_align::FlexAlign, flex_basis::FlexBasis, flex_direction::FlexDirection, flex_wrap::FlexWrap, font_size::FontSize, font_style::FontStyle, font_weight::FontWeight, gap::Gap, item_align::ItemAlign, length_value::LengthValueProperty, letter_spacing::LetterSpacing, line_height::LineHeight, marin_padding::MarginPadding, max_size::MaxSizeProperty, normal::Normal, number::NumberProperty, overflow::Overflow, size::SizeProperty, style_value_type::StyleValueType, text_align::TextAlign, text_decoration::TextDecoration, text_overflow::TextOverflow, text_shadow::TextShadow, text_transform::TextTransform, transform::Transform, transform_origin::TransformOrigin, unit::{generate_expr_by_length_value, generate_expr_with_css_input, Platform}, vertical_align::VerticalAlign}};
7+
use crate::{constants::ENV_FUN, style_parser::KeyFrameItem, style_propetries::{animation::Animation, aspect_ratio::AspactRatio, background::Background, background_image::BackgroundImage, background_position::BackgroundPosition, background_repeat::BackgroundRepeat, background_size::BackgroundSize, border::Border, border_color::BorderColor, border_radius::BorderRadius, border_style::BorderStyle, border_width::BorderWidth, color::ColorProperty, display::Display, expr::Expr, flex::Flex, flex_align::FlexAlign, flex_basis::FlexBasis, flex_direction::FlexDirection, flex_wrap::FlexWrap, font_size::FontSize, font_style::FontStyle, font_weight::FontWeight, gap::Gap, item_align::ItemAlign, length_value::LengthValueProperty, letter_spacing::LetterSpacing, line_height::LineHeight, marin_padding::MarginPadding, max_size::MaxSizeProperty, normal::Normal, number::NumberProperty, overflow::Overflow, size::SizeProperty, style_value_type::StyleValueType, text_align::TextAlign, text_decoration::TextDecoration, text_overflow::TextOverflow, text_shadow::TextShadow, text_transform::TextTransform, transform::Transform, transform_origin::TransformOrigin, unit::{generate_expr_by_length_value, Platform}, vertical_align::VerticalAlign}};
88

99
pub fn parse_style_properties(properties: &Vec<(String, Property)>, keyframes_map: Option<Rc<RefCell<HashMap<String, Vec<KeyFrameItem>>>>>) -> Vec<StyleValueType> {
1010
let mut final_properties = vec![];
@@ -14,7 +14,6 @@ pub fn parse_style_properties(properties: &Vec<(String, Property)>, keyframes_ma
1414
match value {
1515
Property::Unparsed(unparsed) => {
1616
unparsed.value.0.iter().for_each(|item| {
17-
println!("Unparsed item: {:?}", item);
1817
match item {
1918
TokenOrValue::Env(env) => {
2019
is_env = true;

src/visitor.rs

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -484,11 +484,12 @@ impl ModuleMutVisitor {
484484
let arg = &mut stmt.arg;
485485
if let Some(expr_in_box) = arg {
486486
let is_return_jsx_like = match &mut **expr_in_box {
487+
// JSX
487488
Expr::JSXElement(_) |
488489
Expr::JSXFragment(_) |
489-
Expr::JSXMember(_) => {
490-
true
491-
},
490+
Expr::JSXMember(_) => true,
491+
// React.createElement
492+
Expr::Call(call_expr) => check_is_jsx_callee(call_expr),
492493
_ => false
493494
};
494495
if is_return_jsx_like {
@@ -948,6 +949,26 @@ fn generate_stylesheet(fn_name: String, fn_data_name: String, style_object: Box<
948949
)
949950
}
950951

952+
953+
fn check_is_jsx_callee (call_expr: &CallExpr) -> bool {
954+
if let Callee::Expr(expr) = &call_expr.callee {
955+
if let Expr::Member(member) = &**expr {
956+
if let MemberProp::Ident(ident) = &member.prop {
957+
if ident.sym.to_string() == "createElement" {
958+
return true
959+
}
960+
}
961+
}
962+
if let Expr::Ident(ident) = &**expr {
963+
if ident.sym.to_string() == "createElement" {
964+
return true
965+
}
966+
}
967+
}
968+
969+
return false
970+
}
971+
951972
pub enum EtsDirection {
952973
Row,
953974
Column,
@@ -980,25 +1001,6 @@ impl<'i> JSXMutVisitor<'i> {
9801001
}
9811002
}
9821003

983-
fn check_is_jsx_callee (&self, call_expr: &CallExpr) -> bool {
984-
if let Callee::Expr(expr) = &call_expr.callee {
985-
if let Expr::Member(member) = &**expr {
986-
if let MemberProp::Ident(ident) = &member.prop {
987-
if ident.sym.to_string() == "createElement" {
988-
return true
989-
}
990-
}
991-
}
992-
if let Expr::Ident(ident) = &**expr {
993-
if ident.sym.to_string() == "createElement" {
994-
return true
995-
}
996-
}
997-
}
998-
999-
return false
1000-
}
1001-
10021004
fn get_jsx_element_or_callee_calss_value_and_dynamic_class_styles (&self, jsx_element_or_callee: &JSXElementOrJSXCallee) -> (Option<Expr>, bool) {
10031005
let mut has_dynamic_class = false;
10041006
let mut class_attr_value = None;
@@ -1362,7 +1364,7 @@ impl<'i> VisitMut for JSXMutVisitor<'i> {
13621364
noop_visit_mut_type!();
13631365

13641366
fn visit_mut_call_expr(&mut self, n: &mut CallExpr) {
1365-
if self.check_is_jsx_callee(n) {
1367+
if check_is_jsx_callee(n) {
13661368

13671369
let span_key = SpanKey(n.span);
13681370
if let Some(_) = self.jsx_record.borrow_mut().get(&span_key) {

0 commit comments

Comments
 (0)