diff --git a/__test__/fixure/pesudo.jsx b/__test__/fixure/pesudo.jsx index d621e0c..8fb275c 100644 --- a/__test__/fixure/pesudo.jsx +++ b/__test__/fixure/pesudo.jsx @@ -1,10 +1,13 @@ -import { View, Text } from '@tarojs/components' -import React from 'react' -import './pesudo.scss' +import { View, Text } from "@tarojs/components"; +import React from "react"; +import "./pesudo.scss"; export default function Pesudo() { - return - - - + return ( + + + + + + ); } diff --git a/__test__/fixure/pesudo.scss b/__test__/fixure/pesudo.scss index b5657b2..462545e 100644 --- a/__test__/fixure/pesudo.scss +++ b/__test__/fixure/pesudo.scss @@ -1,3 +1,25 @@ .a { box-shadow: 0px 0px rgba(0, 0, 0, 0.04); + transform: translate(0, 0) rotate(0) skewX(0) skewY(0) scaleX(1) scaleY(1); + color: var(--primary-color); +} + +.gap-4 { + gap: 16px; +} + +.w-\[300px\] { + width: 300px +} + +.h-\[50px\] { + width: 300px +} + +.p-2 { + padding: 8px; +} + +.bg-\[rgba\(0\2c 0\2c 0\2c 0\.5\)\] { + background-color: rgba(0,0,0,0.5); } diff --git a/src/constants.rs b/src/constants.rs index 7ef7b35..b41aa22 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -7,6 +7,8 @@ pub const NESTING_STYLE: &'static str = "__nesting_style__"; pub const COMBINE_NESTING_STYLE: &'static str = "__combine_nesting_style__"; pub const NESTINT_STYLE_DATA: &'static str = "__nesting_style_data__"; pub const ENV_FUN: &'static str = "__env__"; +pub const VAR_FUN: &'static str = "__var__"; +pub const GLOBAL_SHARED: &'static str = "__global_shared__"; // pub const CALC_DYMAMIC_STYLE: &'static str = "calcDynamicStyle"; pub const CALC_STATIC_STYLE: &'static str = "calcStaticStyle"; diff --git a/src/lib.rs b/src/lib.rs index 62def69..6f9ca39 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,8 +7,7 @@ use style_parser::StyleParser; use style_propetries::unit::Platform; use swc_core::{ - ecma::codegen::{text_writer::JsWriter, Emitter}, - common::{comments::SingleThreadedComments, sync::Lrc, SourceMap} + common::{comments::SingleThreadedComments, sync::Lrc, SourceMap}, ecma::{ast::Bool, codegen::{text_writer::JsWriter, Emitter}} }; use crate::{document::JSXDocument, style_write::StyleWrite}; @@ -32,7 +31,8 @@ mod parse_style_properties; #[napi(object)] #[derive(Deserialize)] pub struct ParseOptions { - pub platform_string: String + pub platform_string: String, + pub is_entry: bool } #[napi(object)] @@ -49,6 +49,8 @@ pub fn parse(component: String, styles: Vec, options: ParseOptions) -> P _ => Platform::Harmony }; + let is_entry = options.is_entry || false; + let mut is_enable_nesting = true; // 解析组件文件 @@ -59,7 +61,7 @@ pub fn parse(component: String, styles: Vec, options: ParseOptions) -> P // 解析样式文件 let css = styles.join("\n"); - let mut style_parser = StyleParser::new(&document, platform.clone()); + let mut style_parser = StyleParser::new(&document, platform.clone(), is_entry.clone()); style_parser.parse(&css); let style_data = style_parser.calc(); @@ -76,6 +78,7 @@ pub fn parse(component: String, styles: Vec, options: ParseOptions) -> P style_data.pesudo_style_record.clone(), style_data.all_style.clone(), is_enable_nesting, + is_entry, ); style_write.write(platform, document.taro_components.clone()); diff --git a/src/main.rs b/src/main.rs index 0a58e12..fb4a9ec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,7 +30,7 @@ pub fn main() { let css = fs::read_to_string("__test__/fixure/pesudo.scss").unwrap(); let platform = Platform::Harmony; - + let is_entry = false; // 是否是入口文件 let mut is_enable_nesting = true; // 解析组件文件 @@ -40,7 +40,7 @@ pub fn main() { document.parse(component, cm.clone(), &comments); // 解析样式文件 - let mut style_parser = StyleParser::new(&document, platform.clone()); + let mut style_parser = StyleParser::new(&document, platform.clone(), is_entry.clone()); style_parser.parse(&css); let style_data = style_parser.calc(); @@ -57,6 +57,7 @@ pub fn main() { style_data.pesudo_style_record.clone(), style_data.all_style.clone(), is_enable_nesting, + is_entry ); style_write.write(platform, document.taro_components.clone()); diff --git a/src/parse_style_properties.rs b/src/parse_style_properties.rs index 226ade4..8ecdfe9 100644 --- a/src/parse_style_properties.rs +++ b/src/parse_style_properties.rs @@ -4,7 +4,7 @@ use lightningcss::{properties::{custom::TokenOrValue, Property}, stylesheet::Pri use swc_core::{common::DUMMY_SP, ecma::{ast::{self}, utils::quote_ident}}; use swc_core::ecma::ast::*; -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, box_shadow::BoxShadow, 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}}; +use crate::{constants::ENV_FUN, constants::VAR_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, box_shadow::BoxShadow, 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}}; pub fn parse_style_properties(properties: &Vec<(String, Property)>, keyframes_map: Option>>>>) -> Vec { let mut final_properties = vec![]; @@ -44,6 +44,35 @@ pub fn parse_style_properties(properties: &Vec<(String, Property)>, keyframes_ma type_args: None })))); }, + TokenOrValue::Var(env) => { + is_env = true; + let mut args = vec![ + ExprOrSpread { + spread: None, + expr: Box::new(ast::Expr::Lit(Lit::Str(env.name.to_css_string(PrinterOptions::default()).unwrap().into()))) + } + ]; + // env.name.to_css_string(PrinterOptions::default()).unwrap())) + if env.fallback.is_some() { + let fallback = env.fallback.as_ref().unwrap().0.get(0); + if let Some(token) = fallback { + if let TokenOrValue::Length(length) = token { + args.push( + ExprOrSpread { + spread: None, + expr: Box::new(generate_expr_by_length_value(length, Platform::Harmony)) + } + ) + } + } + } + final_properties.push(StyleValueType::Expr(Expr::new(id.to_string(), ast::Expr::Call(CallExpr { + span: DUMMY_SP, + callee: Callee::Expr(Box::new(ast::Expr::Ident(quote_ident!(VAR_FUN)))), + args: args, + type_args: None + })))); + }, _ => {} } }); diff --git a/src/style_parser.rs b/src/style_parser.rs index 447b5d0..a365c02 100644 --- a/src/style_parser.rs +++ b/src/style_parser.rs @@ -2,7 +2,7 @@ use std::{rc::Rc, cell::RefCell, convert::Infallible, collections::HashMap, hash use lightningcss::{declaration::DeclarationBlock, properties::Property, rules::{keyframes::KeyframeSelector, CssRule}, stylesheet::{ParserOptions, PrinterOptions, StyleSheet}, traits::ToCss, visit_types, visitor::{Visit, VisitTypes, Visitor}}; -use crate::{constants::SUPPORT_PSEUDO_KEYS, document::JSXDocument, style_propetries::{style_value_type::StyleValueType, unit::Platform}, utils::to_camel_case, visitor::SpanKey}; +use crate::{constants::SUPPORT_PSEUDO_KEYS, document::JSXDocument, style_propetries::{style_value_type::StyleValueType, unit::Platform}, utils::{is_tailwind_arbitrary, to_camel_case}, visitor::SpanKey}; use super::parse_style_properties::parse_style_properties; @@ -58,9 +58,11 @@ impl<'i> Visitor<'i> for StyleVisitor<'i> { // 属性规则收集 CssRule::Style(style) => { let selectors_str = style.selectors.to_string(); - let selectors: Vec<&str> = selectors_str.split(",").collect::>(); + // FEATURE: 按照,分割选择器,且保证,前面不是转义字符,以支持 tailwind.css 动态类名 + let selectors: Vec<&str> = selectors_str.split("(?>(); for index in 0..selectors.len() { - let selector = selectors[index].trim().to_string(); + // FEATURE: 优化 key 的生成 移除 key 中的 \\ 转义,以支持 tailwind.css 动态类名匹配 + let selector = selectors[index].trim().to_string().replace("\\", ""); let mut all_style = self.all_style.borrow_mut(); let decorations = all_style.iter_mut().find(|(id, _)| id == &selector); if let Some((_, declarations)) = decorations { @@ -132,16 +134,18 @@ pub struct StyleParser<'i> { pub all_style: Rc>)>>>, pub keyframes: Rc>>>, pub document: &'i JSXDocument, - pub platform: Platform + pub platform: Platform, + pub is_entry: bool } impl<'i> StyleParser<'i> { - pub fn new(document: &'i JSXDocument, platform:Platform) -> Self { + pub fn new(document: &'i JSXDocument, platform:Platform, is_entry: bool) -> Self { StyleParser { all_style: Rc::new(RefCell::new(vec![])), keyframes: Rc::new(RefCell::new(HashMap::new())), document, - platform + platform, + is_entry } } @@ -191,7 +195,8 @@ impl<'i> StyleParser<'i> { }) .collect::>(); // Specify the lifetime of the tuple elements to match the input data // 判断是否含有嵌套选择器 - if selector.contains(" ") || selector.chars().filter(|&c| c == '.').count() > 1 { + // FEATURE: 此处会误判,比如 tailwind 动态样式中 bg-[rgba(0,0,0,0.5)] + if selector.contains(" ") || (selector.chars().filter(|&c| c == '.').count() > 1 && !is_tailwind_arbitrary(&selector)) { has_nesting = true } final_all_style.push((selector.to_owned(), properties)); diff --git a/src/style_propetries/transform.rs b/src/style_propetries/transform.rs index f5fa31c..f9a5dec 100644 --- a/src/style_propetries/transform.rs +++ b/src/style_propetries/transform.rs @@ -159,14 +159,24 @@ impl From<(String, &Property<'_>)> for Transform { transform.push(Matrix4::Scales(scale)); } LNTransform::ScaleX(x) => { - let mut scale = Scale::new(); - scale.x = Some(x.clone()); - transform.push(Matrix4::Scales(scale)); + // 如果 transform 已经存在 scale 则不再添加,直接取出已经存在的 scale 进行修改 + if let Some(Matrix4::Scales(scale)) = transform.iter_mut().find(|m| matches!(m, Matrix4::Scales(_))) { + scale.x = Some(x.clone()); + } else { + let mut scale = Scale::new(); + scale.x = Some(x.clone()); + transform.push(Matrix4::Scales(scale)); + } } LNTransform::ScaleY(y) => { - let mut scale = Scale::new(); - scale.x = Some(y.clone()); - transform.push(Matrix4::Scales(scale)); + // 如果 transform 已经存在 scale 则不再添加,直接取出已经存在的 scale 进行修改 + if let Some(Matrix4::Scales(scale)) = transform.iter_mut().find(|m| matches!(m, Matrix4::Scales(_))) { + scale.y = Some(y.clone()); + } else { + let mut scale = Scale::new(); + scale.y = Some(y.clone()); + transform.push(Matrix4::Scales(scale)); + } } LNTransform::ScaleZ(z) => { let mut scale = Scale::new(); diff --git a/src/style_write.rs b/src/style_write.rs index f81ba7f..9e03848 100644 --- a/src/style_write.rs +++ b/src/style_write.rs @@ -17,6 +17,7 @@ pub struct StyleWrite<'i> { pub pesudo_style_record: Rc)>)>>>>, pub all_style: Rc>>, pub is_enable_nesting: bool, + pub is_entry: bool, } impl<'i> StyleWrite<'i> { @@ -25,7 +26,8 @@ impl<'i> StyleWrite<'i> { jsx_record: Rc>, pesudo_style_record: Rc)>)>>>>, all_style: Rc>>, - is_enable_nesting: bool + is_enable_nesting: bool, + is_entry: bool, ) -> Self { StyleWrite { module, @@ -33,6 +35,7 @@ impl<'i> StyleWrite<'i> { pesudo_style_record, all_style, is_enable_nesting, + is_entry, } } @@ -54,7 +57,7 @@ impl<'i> StyleWrite<'i> { } // 插入样式表 { - let mut insert_mut_visitor = ModuleMutVisitor::new(self.all_style.clone(),platform.clone(), self.is_enable_nesting); + let mut insert_mut_visitor = ModuleMutVisitor::new(self.all_style.clone(),platform.clone(), self.is_enable_nesting, self.is_entry); self .module .borrow_mut() diff --git a/src/utils.rs b/src/utils.rs index 5714fb0..50d0f42 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -201,6 +201,11 @@ pub fn split_selector(selector: &str) -> Vec { // 分割类名 .a.b.c => ["a", "b", "c"] fn split_classes(input: &str) -> TSelector { + // 如果是 tailwindcss 的任意类,进行如下转换 例如:.bg-[rgba(0,0,0,0.5)] => bg-[rgba(0,0,0,0.5)] , .w-[100px] => w-[100px] + if is_tailwind_arbitrary(input) { + return TSelector::String(input[1..].to_string()); + } + let mut matches = Vec::new(); let mut current_class = String::new(); for char in input.chars() { @@ -222,3 +227,8 @@ fn split_classes(input: &str) -> TSelector { TSelector::String(input.replace(".", "")) } } + +// 是否是 tailwind.css 的任意值类名 +pub fn is_tailwind_arbitrary(input: &str) -> bool { + input.contains('[') && input.contains(']') +} diff --git a/src/visitor.rs b/src/visitor.rs index 7b8a7bc..3aa4d0b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,4 +1,3 @@ - use std::{ cell::RefCell, collections::{BTreeMap, HashMap}, hash::{Hash, Hasher}, rc::Rc, vec }; @@ -18,8 +17,8 @@ use swc_core::{ use swc_core::ecma::ast::*; use crate::{ - constants::{CALC_STATIC_STYLE, COMBINE_NESTING_STYLE, CONVERT_STYLE_PX_FN, ENV_FUN, HM_STYLE, INNER_STYLE, INNER_STYLE_DATA, NESTING_STYLE, NESTINT_STYLE_DATA, RN_CONVERT_STYLE_PX_FN, RN_CONVERT_STYLE_VU_FN, SUPPORT_PSEUDO_KEYS}, scraper::Element, style_parser::StyleValue, style_propetries::{style_value_type::StyleValueType, traits::ToStyleValue, unit::{Platform, PropertyTuple}}, utils::{ - create_qualname, get_callee_attributes, is_starts_with_uppercase, prefix_style_key, recursion_jsx_member, split_selector, TSelector + constants::{CALC_STATIC_STYLE, COMBINE_NESTING_STYLE, CONVERT_STYLE_PX_FN, ENV_FUN, GLOBAL_SHARED, HM_STYLE, INNER_STYLE, INNER_STYLE_DATA, NESTING_STYLE, NESTINT_STYLE_DATA, RN_CONVERT_STYLE_PX_FN, RN_CONVERT_STYLE_VU_FN, SUPPORT_PSEUDO_KEYS, VAR_FUN}, scraper::Element, style_parser::StyleValue, style_propetries::{style_value_type::StyleValueType, traits::ToStyleValue, unit::{Platform, PropertyTuple}}, utils::{ + create_qualname, get_callee_attributes, is_starts_with_uppercase, is_tailwind_arbitrary, prefix_style_key, recursion_jsx_member, split_selector, TSelector } }; @@ -425,6 +424,18 @@ pub fn insert_import_module_decl(module: &mut Module, last_import_index: usize, local: Ident::new(ENV_FUN.into(), DUMMY_SP), imported: None, is_type_only: false, + }), + ImportSpecifier::Named(ImportNamedSpecifier { + span: DUMMY_SP, + local: Ident::new(VAR_FUN.into(), DUMMY_SP), + imported: None, + is_type_only: false, + }), + ImportSpecifier::Named(ImportNamedSpecifier { + span: DUMMY_SP, + local: Ident::new(GLOBAL_SHARED.into(), DUMMY_SP), + imported: None, + is_type_only: false, }) ], src: Box::new(Str::from("@tarojs/runtime")), @@ -441,15 +452,17 @@ pub struct ModuleMutVisitor { pub all_style: Rc>>, pub platform: Platform, pub is_enable_nesting: bool, + pub is_entry: bool, } impl ModuleMutVisitor { pub fn new( all_style: Rc>>, platform: Platform, - is_enable_nesting: bool + is_enable_nesting: bool, + is_entry: bool ) -> Self { - ModuleMutVisitor { all_style, platform, is_enable_nesting } + ModuleMutVisitor { all_style, platform, is_enable_nesting, is_entry } } } @@ -605,6 +618,7 @@ impl VisitMut for ModuleMutVisitor { noop_visit_mut_type!(); fn visit_mut_module(&mut self, module: &mut Module) { + // println!("visit_mut_module {:?}", self.platform); let binding = self.all_style.borrow_mut(); let style_entries: BTreeMap<_, _> = binding.iter().collect(); @@ -649,7 +663,7 @@ impl VisitMut for ModuleMutVisitor { // 判断是否嵌套样式 if self.platform == Platform::Harmony { - if insert_key.contains(" ") || insert_key.chars().filter(|&c| c == '.').count() > 1 { + if insert_key.contains(" ") || (insert_key.chars().filter(|&c| c == '.').count() > 1 && !insert_key.contains("[")) { // 拆分选择器字符串,安装' ' 或 '>' 拆分,如:container > wrapper item => ['container', '>', 'wrapper', ' ', 'item'] let selectors = split_selector(insert_key.as_str()); @@ -665,7 +679,14 @@ impl VisitMut for ModuleMutVisitor { } } - let _key = insert_key.replace(".", ""); + let _key= if is_tailwind_arbitrary(insert_key.as_str()) { + // 如果是 tailwindcss 的任意类,进行如下转换 例如:.bg-[rgba(0,0,0,0.5)] => bg-[rgba(0,0,0,0.5)] , .w-[100px] => w-[100px] + insert_key[1..].to_string() + } else { + insert_key.replace(".", "") + }; + + if let Some(props) = final_style_entries.get(_key.as_str()) { let mut new_insert_value = props.clone(); new_insert_value.extend(insert_value); @@ -752,7 +773,7 @@ impl VisitMut for ModuleMutVisitor { let mut var_checker = VarChecker { found: false }; module.visit_with(&mut var_checker); - if var_checker.found { + if var_checker.found || self.is_entry { let style_object = Box::new(Expr::Object(ObjectLit { span: DUMMY_SP, props: final_style_entries @@ -770,19 +791,26 @@ impl VisitMut for ModuleMutVisitor { .into(), })); - let (identifier, style_func) = generate_stylesheet(INNER_STYLE.to_string(), INNER_STYLE_DATA.to_string(), style_object); - // 插入代码 let __inner_style_data__; - module.body.insert(last_import_index, ModuleItem::Stmt(identifier)); - last_import_index += 1; - // 插入代码 function __inner_style__() { ... } - module - .body - .insert(last_import_index, ModuleItem::Stmt(style_func)); + if self.is_entry { + // 入口文件注入全局公共样式 + // 插入代码 Taro.__inner_style__= { ... } + let common_inner_style = generate_common_stylesheet(INNER_STYLE.to_string(), style_object.clone()); + module.body.insert(last_import_index, ModuleItem::Stmt(common_inner_style)); + last_import_index += 1; + } else { + let (identifier, style_func) = generate_stylesheet(INNER_STYLE.to_string(), INNER_STYLE_DATA.to_string(), style_object.clone()); + // 插入代码 let __inner_style_data__; + module.body.insert(last_import_index, ModuleItem::Stmt(identifier)); + last_import_index += 1; + // 插入代码 function __inner_style__() { ... } + module + .body + .insert(last_import_index, ModuleItem::Stmt(style_func)); + } } if self.is_enable_nesting { // 插入嵌套样式 - let mut nestings = nesting_style_entries.into_iter().collect::, Vec))>>(); // 根据类的数量进行权重排序 nestings.sort_by(|a, b| { @@ -839,21 +867,28 @@ impl VisitMut for ModuleMutVisitor { .into(), })); - let (identifier, style_func) = generate_stylesheet(NESTING_STYLE.to_string(), NESTINT_STYLE_DATA.to_string(), nesting_style_object); - // 插入代码 let __inner_style_data__; - module.body.insert(last_import_index, ModuleItem::Stmt(identifier)); - last_import_index += 1; - // 插入代码 function __inner_style__() { ... } - module - .body - .insert(last_import_index, ModuleItem::Stmt(style_func)) + if self.is_entry { + // 插入代码 Taro.__nesting_style__= { ... } + let common_inner_style = generate_common_stylesheet(NESTING_STYLE.to_string(), nesting_style_object.clone()); + module.body.insert(last_import_index, ModuleItem::Stmt(common_inner_style)); + } else { + let (identifier, style_func) = generate_stylesheet(NESTING_STYLE.to_string(), NESTINT_STYLE_DATA.to_string(), nesting_style_object); + // 插入代码 let __nesting_style_data__; + module.body.insert(last_import_index, ModuleItem::Stmt(identifier)); + last_import_index += 1; + // 插入代码 function __nesting_style__() { ... } + module + .body + .insert(last_import_index, ModuleItem::Stmt(style_func)) + } + } } } fn generate_stylesheet(fn_name: String, fn_data_name: String, style_object: Box) -> (Stmt, Stmt) { - let ident = Ident::new(fn_data_name.into(), DUMMY_SP); + let ident = Ident::new(fn_data_name.clone().into(), DUMMY_SP); let identifier = Stmt::Decl(Decl::Var(Box::new(VarDecl { span: DUMMY_SP, @@ -895,7 +930,35 @@ fn generate_stylesheet(fn_name: String, fn_data_name: String, style_object: Box< id: ident.clone(), type_ann: None })), - right: style_object + right: Box::new(Expr::Object(ObjectLit { + span: DUMMY_SP, + props: vec![ + PropOrSpread::Spread(SpreadElement { + dot3_token: DUMMY_SP, + // ...__global_shared__.__inner_style__?.() + expr: Box::new(Expr::OptChain(OptChainExpr { + span: DUMMY_SP, + optional: true, + base: Box::new(OptChainBase::Call(OptCall { + span: DUMMY_SP, + callee: Box::new(Expr::Member( + MemberExpr { + span: DUMMY_SP, + obj: Box::new(Expr::Ident(Ident::new(GLOBAL_SHARED.into(), DUMMY_SP))), + prop: MemberProp::Ident(Ident::new(fn_name.clone().into(), DUMMY_SP)), + } + )), + args: vec![], + type_args: None + })) + })), + }), + PropOrSpread::Spread(SpreadElement { + dot3_token: DUMMY_SP, + expr: style_object + }) + ] + })) }) ) } @@ -938,6 +1001,51 @@ fn generate_stylesheet(fn_name: String, fn_data_name: String, style_object: Box< } +// 挂载全局入口样式 +fn generate_common_stylesheet(attr_name: String, style_object: Box) -> Stmt { + let common_inner_style = Stmt::Expr( + ExprStmt { + span: DUMMY_SP, + expr: Box::new( + Expr::Assign(AssignExpr { span: DUMMY_SP, op: AssignOp::Assign, + left: AssignTarget::Simple(SimpleAssignTarget::Member(MemberExpr { + span: DUMMY_SP, + obj: Box::new(Expr::Ident(Ident::new(GLOBAL_SHARED.into(), DUMMY_SP))), + prop: MemberProp::Ident(Ident { + span: DUMMY_SP, + sym: attr_name.into(), + optional: false, + }), + })), + // () => return { ... } + right: Box::new(Expr::Arrow(ArrowExpr { + span: DUMMY_SP, + body: Box::new(BlockStmtOrExpr::BlockStmt( + BlockStmt { + span: DUMMY_SP, + stmts: vec![ + Stmt::Return(ReturnStmt { + span: DUMMY_SP, + arg: Some(style_object) + }) + ] + } + )), + params: vec![], + is_async: false, + is_generator: false, + type_params: None, + return_type: None + })) + }) + ) + } + ); + + common_inner_style +} + + fn check_is_jsx_callee (call_expr: &CallExpr) -> bool { if let Callee::Expr(expr) = &call_expr.callee { if let Expr::Member(member) = &**expr {