diff --git a/__test__/fixure/rn/index.scss b/__test__/fixure/rn/index.scss index 57c60ee..f22d41a 100644 --- a/__test__/fixure/rn/index.scss +++ b/__test__/fixure/rn/index.scss @@ -1,5 +1,6 @@ .c_div { - border-right: 20px dashed #f00; - border: 2px solid #f00; - border-left: 20px dashed #f00; -} + text-shadow: 1px 1px 1px #000; + text-transform: uppercase; + margin: 10% 20px; + flex: 1 1 auto; +} \ No newline at end of file diff --git a/src/react_native/create_stylesheet.rs b/src/react_native/create_stylesheet.rs index 8c236f3..550b96a 100644 --- a/src/react_native/create_stylesheet.rs +++ b/src/react_native/create_stylesheet.rs @@ -52,7 +52,7 @@ impl RNStyleSheet { value: Box::new(expr), })))) }) - }, + } } } diff --git a/src/react_native/parse_style_properties.rs b/src/react_native/parse_style_properties.rs index fb3c271..688c150 100644 --- a/src/react_native/parse_style_properties.rs +++ b/src/react_native/parse_style_properties.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use lightningcss::{properties::Property, stylesheet::PrinterOptions}; -use crate::style_propetries::{style_value_type::StyleValueType, flex_align::FlexAlign, item_align::ItemAlign, aspect_ratio::AspactRatio, display::Display, flex_basis::FlexBasis, flex_direction::FlexDirection, flex_wrap::FlexWrap, gap::Gap, length_value::LengthValueProperty, size::SizeProperty, max_size::MaxSizeProperty, overflow::Overflow, normal::Normal, number::NumberProperty, color::ColorProperty, font_size::FontSize, font_weight::FontWeight, line_height::LineHeight, text_align::TextAlign, text_decoration::TextDecoration, text_shadow::TextShadow, letter_spacing::LetterSpacing, font_style::FontStyle, text_transform::TextTransform, vertical_align::VerticalAlign, border_color::BorderColor, border_width::BorderWidth, border_radius::BorderRadius, border_style::BorderStyle, border::Border}; +use crate::style_propetries::{aspect_ratio::AspactRatio, border::Border, border_color::BorderColor, border_radius::BorderRadius, border_style::BorderStyle, border_width::BorderWidth, color::ColorProperty, display::Display, 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_shadow::TextShadow, text_transform::TextTransform, transform::Transform, vertical_align::VerticalAlign}; pub fn parse_style_properties(properties: &Vec<(String, Property)>) -> HashMap { let mut final_properties = HashMap::new(); @@ -23,6 +23,9 @@ pub fn parse_style_properties(properties: &Vec<(String, Property)>) -> HashMap { final_properties.insert("alignSelf".to_string(), StyleValueType::AlignItems(ItemAlign::from((id.to_string(), value)))); } + "flex" => { + final_properties.insert("flexBasis".to_string(), StyleValueType::Flex(Flex::from((id.to_string(), value)))); + } "flexBasis" => { final_properties.insert("flexBasis".to_string(), StyleValueType::FlexBasis(FlexBasis::from((id.to_string(), value)))); } @@ -44,11 +47,11 @@ pub fn parse_style_properties(properties: &Vec<(String, Property)>) -> HashMap { final_properties.insert("display".to_string(), StyleValueType::Display(Display::from((id.to_string(), value)))); } - "columnGap" => { - final_properties.insert("columnGap".to_string(), StyleValueType::Gap(Gap::from((id.to_string(), value)))); + "gap" | "columnGap" | "rowGap" => { + final_properties.insert(id.to_string(), StyleValueType::Gap(Gap::from((id.to_string(), value)))); } - "rowGap" => { - final_properties.insert("rowGap".to_string(), StyleValueType::Gap(Gap::from((id.to_string(), value)))); + "margin" | "padding" => { + final_properties.insert(id.to_string(), StyleValueType::MarginPadding(MarginPadding::from((id.to_string(), value)))); } "marginTop" | "marginBottom" | "marginLeft" | "marginRight" | "paddingTop" | "paddingBottom" | "paddingLeft" | "paddingRight" | "top" | "bottom" | "left" | "right" => { final_properties.insert(id.to_string(), StyleValueType::LengthValueProperty(LengthValueProperty::from((id.to_string(), value)))); @@ -136,6 +139,9 @@ pub fn parse_style_properties(properties: &Vec<(String, Property)>) -> HashMap { final_properties.insert(property_name.to_string(), StyleValueType::Border(Border::from((id.to_string(), value)))); } + "transform" => { + final_properties.insert(property_name.to_string(), StyleValueType::Transform(Transform::from((id.to_string(), value)))); + } _ => { // position、zIndex等... 会自动处理 单位、数字等相关信息 final_properties.insert(property_name.to_string(), StyleValueType::Normal(Normal::new(id.to_string(), value.value_to_css_string(PrinterOptions::default()).unwrap()))); diff --git a/src/style_propetries/border.rs b/src/style_propetries/border.rs index 6349ad5..822951e 100644 --- a/src/style_propetries/border.rs +++ b/src/style_propetries/border.rs @@ -145,9 +145,15 @@ impl ToExpr for Border { let mut props: Vec<(PropName, Expr)> = vec![]; match prop_name.as_str() { "border" => { - props.push((generate_prop_name!("borderWidth"), generate_expr_by_border_side_width!(self.width.clone().unwrap().top.unwrap()))); - props.push((generate_prop_name!("borderStyle"), generate_expr_by_line_style!(self.style.clone().unwrap().top.unwrap(), Platform::Harmony))); - props.push((generate_prop_name!("borderColor"), generate_string_by_css_color!(self.color.clone().unwrap().top.unwrap()))); + vec!["borderTopWidth", "borderRightWidth", "borderBottomWidth", "borderLeftWidth"].iter().for_each(|item| { + props.push((generate_prop_name!(item.to_owned()), generate_expr_by_border_side_width!(self.width.clone().unwrap().top.unwrap()))); + }); + vec!["borderTopStyle", "borderRightStyle", "borderBottomStyle", "borderLeftStyle"].iter().for_each(|item| { + props.push((generate_prop_name!(item.to_owned()), generate_expr_by_line_style!(self.style.clone().unwrap().top.unwrap(), Platform::Harmony))); + }); + vec!["borderTopColor", "borderRightColor", "borderBottomColor", "borderLeftColor"].iter().for_each(|item| { + props.push((generate_prop_name!(item.to_owned()), generate_string_by_css_color!(self.color.clone().unwrap().top.unwrap()))); + }); PropertyTuple::Array(props) }, "borderTop" => { diff --git a/src/style_propetries/border_color.rs b/src/style_propetries/border_color.rs index 8b56192..094f202 100644 --- a/src/style_propetries/border_color.rs +++ b/src/style_propetries/border_color.rs @@ -83,16 +83,16 @@ impl ToExpr for BorderColor { fn to_expr(&self) -> PropertyTuple { let mut props: Vec<(PropName, Expr)> = vec![]; if let Some(top) = &self.top { - props.push((generate_prop_name!(self.id.clone()), generate_string_by_css_color!(top))) + props.push((generate_prop_name!("borderTopColor"), generate_string_by_css_color!(top))) } if let Some(bottom) = &self.bottom { - props.push((generate_prop_name!(self.id.clone()), generate_string_by_css_color!(bottom))) + props.push((generate_prop_name!("borderBottomColor"), generate_string_by_css_color!(bottom))) } if let Some(left) = &self.left { - props.push((generate_prop_name!(self.id.clone()), generate_string_by_css_color!(left))) + props.push((generate_prop_name!("borderLeftColor"), generate_string_by_css_color!(left))) } if let Some(right) = &self.right { - props.push((generate_prop_name!(self.id.clone()), generate_string_by_css_color!(right))) + props.push((generate_prop_name!("borderRightColor"), generate_string_by_css_color!(right))) } PropertyTuple::Array(props) } diff --git a/src/style_propetries/border_radius.rs b/src/style_propetries/border_radius.rs index 4f61719..89cd3b2 100644 --- a/src/style_propetries/border_radius.rs +++ b/src/style_propetries/border_radius.rs @@ -87,17 +87,18 @@ impl From<(String, &Property<'_>)> for BorderRadius { impl ToExpr for BorderRadius { fn to_expr(&self) -> PropertyTuple { let mut props: Vec<(PropName, Expr)> = vec![]; + if let Some(top) = &self.top_left { - props.push((generate_prop_name!(self.id.clone()), generate_expr_by_dimension_percentage!(top))) + props.push((generate_prop_name!("borderTopLeftRadius"), generate_expr_by_dimension_percentage!(top))) } if let Some(bottom) = &self.top_right { - props.push((generate_prop_name!(self.id.clone()), generate_expr_by_dimension_percentage!(bottom))) + props.push((generate_prop_name!("borderTopRightRadius"), generate_expr_by_dimension_percentage!(bottom))) } if let Some(left) = &self.bottom_left { - props.push((generate_prop_name!(self.id.clone()), generate_expr_by_dimension_percentage!(left))) + props.push((generate_prop_name!("borderBottomLeftRadius"), generate_expr_by_dimension_percentage!(left))) } if let Some(right) = &self.bottom_right { - props.push((generate_prop_name!(self.id.clone()), generate_expr_by_dimension_percentage!(right))) + props.push((generate_prop_name!("borderBottomRightRadius"), generate_expr_by_dimension_percentage!(right))) } PropertyTuple::Array(props) } diff --git a/src/style_propetries/border_style.rs b/src/style_propetries/border_style.rs index b6df3e4..6c0e6ef 100644 --- a/src/style_propetries/border_style.rs +++ b/src/style_propetries/border_style.rs @@ -109,16 +109,16 @@ impl ToExpr for BorderStyle { fn to_expr(&self) -> PropertyTuple { let mut props: Vec<(PropName, Expr)> = vec![]; if let Some(top) = &self.top { - props.push((generate_prop_name!(self.id.clone()), generate_expr_by_line_style!(top, Platform::Harmony))) + props.push((generate_prop_name!("borderTopStyle"), generate_expr_by_line_style!(top, Platform::Harmony))) } if let Some(bottom) = &self.bottom { - props.push((generate_prop_name!(self.id.clone()), generate_expr_by_line_style!(bottom, Platform::Harmony))) + props.push((generate_prop_name!("borderBottomStyle"), generate_expr_by_line_style!(bottom, Platform::Harmony))) } if let Some(left) = &self.left { - props.push((generate_prop_name!(self.id.clone()), generate_expr_by_line_style!(left, Platform::Harmony))) + props.push((generate_prop_name!("borderLeftStyle"), generate_expr_by_line_style!(left, Platform::Harmony))) } if let Some(right) = &self.right { - props.push((generate_prop_name!(self.id.clone()), generate_expr_by_line_style!(right, Platform::Harmony))) + props.push((generate_prop_name!("borderRightStyle"), generate_expr_by_line_style!(right, Platform::Harmony))) } PropertyTuple::Array(props) } diff --git a/src/style_propetries/border_width.rs b/src/style_propetries/border_width.rs index 312359f..7481a5d 100644 --- a/src/style_propetries/border_width.rs +++ b/src/style_propetries/border_width.rs @@ -97,16 +97,16 @@ impl ToExpr for BorderWidth { fn to_expr(&self) -> PropertyTuple { let mut props: Vec<(PropName, Expr)> = vec![]; if let Some(top) = &self.top { - props.push((generate_prop_name!(self.id.clone()), generate_expr_by_border_side_width!(top))) + props.push((generate_prop_name!("borderTopWidth"), generate_expr_by_border_side_width!(top))) } if let Some(bottom) = &self.bottom { - props.push((generate_prop_name!(self.id.clone()), generate_expr_by_border_side_width!(bottom))) + props.push((generate_prop_name!("borderBottomWidth"), generate_expr_by_border_side_width!(bottom))) } if let Some(left) = &self.left { - props.push((generate_prop_name!(self.id.clone()), generate_expr_by_border_side_width!(left))) + props.push((generate_prop_name!("borderLeftWidth"), generate_expr_by_border_side_width!(left))) } if let Some(right) = &self.right { - props.push((generate_prop_name!(self.id.clone()), generate_expr_by_border_side_width!(right))) + props.push((generate_prop_name!("borderRightWidth"), generate_expr_by_border_side_width!(right))) } PropertyTuple::Array(props) } diff --git a/src/style_propetries/color.rs b/src/style_propetries/color.rs index ae31d49..e509f60 100644 --- a/src/style_propetries/color.rs +++ b/src/style_propetries/color.rs @@ -2,4 +2,4 @@ use crate::{generate_color_property, generate_prop_name}; use super::{traits::ToExpr, unit::PropertyTuple}; // 生成property_name的value类型为 Size的属性 -generate_color_property![ColorProperty, Color]; +generate_color_property![ColorProperty, Color, BackgroundColor]; diff --git a/src/style_propetries/flex.rs b/src/style_propetries/flex.rs new file mode 100644 index 0000000..bab1a8e --- /dev/null +++ b/src/style_propetries/flex.rs @@ -0,0 +1,98 @@ +use lightningcss::properties::Property; + +use crate::{generate_invalid_expr, generate_prop_name, generate_tpl_expr}; + +use super::{flex_basis::FlexBasis, number::NumberProperty, traits::ToExpr, unit::PropertyTuple}; + + + +#[derive(Debug, Clone)] +pub struct Flex { + pub id: String, + pub value: Option +} + +#[derive(Debug, Clone)] +pub struct FlexValue { + grow: NumberProperty, + shrink: NumberProperty, + basis: FlexBasis +} + +impl ToExpr for Flex { + fn to_expr(&self) -> PropertyTuple { + let mut props = vec![]; + if let Some(value) = &self.value { + match value.basis.to_rn_expr() { + PropertyTuple::One(_, val) => props.push((generate_prop_name!("flexBasis"), val)), + _ => {} + }; + match value.grow.to_rn_expr() { + PropertyTuple::One(_, val) => props.push((generate_prop_name!("flexGrow"), val)), + _ => {} + }; + match value.shrink.to_rn_expr() { + PropertyTuple::One(_, val) => props.push((generate_prop_name!("flexShrink"), val)), + _ => {} + }; + PropertyTuple::Array(props) + } else { + PropertyTuple::One( + generate_prop_name!("flex"), + generate_invalid_expr!() + ) + } + } + + fn to_rn_expr(&self) -> PropertyTuple { + let mut props = vec![]; + + if let Some(value) = &self.value { + match value.grow.to_rn_expr() { + PropertyTuple::One(_, val) => props.push(val), + _ => {} + }; + match value.shrink.to_rn_expr() { + PropertyTuple::One(_, val) => props.push(val), + _ => {} + }; + match value.basis.to_rn_expr() { + PropertyTuple::One(_, val) => props.push(val), + _ => {} + }; + PropertyTuple::One( + generate_prop_name!("flex"), + generate_tpl_expr!(props) + ) + } else { + PropertyTuple::One( + generate_prop_name!("flex"), + generate_invalid_expr!() + ) + } + } +} + +impl From<(String, &Property<'_>)> for Flex { + fn from(prop: (String, &Property<'_>)) -> Self { + + match &prop.1 { + Property::Flex(flex, _) => { + Flex { + id: prop.0, + value: Some(FlexValue { + basis: FlexBasis::from_value(("flexBasis".to_string(), flex.basis.clone())), + grow: NumberProperty::from_value(("flexGrow".to_string(), flex.grow)), + shrink: NumberProperty::from_value(("flexShrink".to_string(),flex.shrink)) + }) + } + }, + _ => { + Flex { + id: prop.0, + value: None + } + } + } + } +} \ No newline at end of file diff --git a/src/style_propetries/flex_basis.rs b/src/style_propetries/flex_basis.rs index 95839b1..530ef23 100644 --- a/src/style_propetries/flex_basis.rs +++ b/src/style_propetries/flex_basis.rs @@ -61,3 +61,15 @@ impl From<(String, &Property<'_>)> for FlexBasis { } } } + +impl FlexBasis { + pub fn from_value(prop: (String, LengthPercentageOrAuto)) -> Self { + FlexBasis { + id: prop.0, + value: match prop.1 { + LengthPercentageOrAuto::Auto => EnumValue::String("auto".to_string()), + LengthPercentageOrAuto::LengthPercentage(value) => generate_dimension_percentage!(EnumValue, value), + } + } + } +} \ No newline at end of file diff --git a/src/style_propetries/gap.rs b/src/style_propetries/gap.rs index f2c9330..d0dc5e4 100644 --- a/src/style_propetries/gap.rs +++ b/src/style_propetries/gap.rs @@ -1,85 +1,130 @@ +use std::borrow::Borrow; + use lightningcss::{ - properties::{Property, align::GapValue}, - values::{length::LengthValue, percentage::{DimensionPercentage, Percentage}}, traits::ToCss, stylesheet::PrinterOptions, + properties::{Property, align::GapValue}, traits::ToCss, }; +use swc_ecma_ast::Expr; -use crate::{generate_expr_lit_str, generate_expr_lit_num, generate_prop_name}; +use crate::{generate_expr_by_length_percentage, generate_expr_lit_num, generate_expr_lit_str, generate_prop_name, generate_tpl_expr}; -use super::{traits::ToExpr, unit::{generate_expr_by_length_value, Platform, PropertyTuple}}; +use super::{traits::ToExpr, unit::{Platform, PropertyTuple}}; -#[derive(Debug, Clone)] -pub struct Gap { - pub id: String, - pub value: EnumValue +macro_rules! generate_expr_gap { + ($value:expr) => { + match $value { + GapValue::Normal => generate_expr_lit_num!(0.0), + GapValue::LengthPercentage(val) => generate_expr_by_length_percentage!(val, Platform::ReactNative), + } + } } #[derive(Debug, Clone)] -pub enum EnumValue { - LengthValue(LengthValue), - Percentage(Percentage), - String(String), - Normal +pub struct Gap { + pub id: String, + pub row: Option, + pub column: Option, + pub gap: Option<(GapValue, GapValue)>, } impl ToExpr for Gap { fn to_expr(&self) -> PropertyTuple { - PropertyTuple::One( - generate_prop_name!(*self.id), - match &self.value { - EnumValue::String(value) => generate_expr_lit_str!(value.to_owned()), - EnumValue::LengthValue(length_value) => generate_expr_by_length_value(length_value, Platform::Harmony), - EnumValue::Percentage(value) => generate_expr_lit_str!((value.0 * 100.0).to_string() + "%"), - EnumValue::Normal => generate_expr_lit_num!(0.0), - } - ) + let mut expr = vec![]; + if let Some(row) = &self.row { + expr.push(( + generate_prop_name!("rowGap"), + match &row { + GapValue::Normal => generate_expr_lit_num!(0.0), + GapValue::LengthPercentage(val) => generate_expr_by_length_percentage!(val, Platform::Harmony), + } + )); + } + if let Some(column) = &self.column { + expr.push(( + generate_prop_name!("columnGap"), + match &column { + GapValue::Normal => generate_expr_lit_num!(0.0), + GapValue::LengthPercentage(val) => generate_expr_by_length_percentage!(val, Platform::Harmony), + } + )); + } + if let Some(gap) = &self.gap { + expr.push(( + generate_prop_name!("rowGap"), + match &gap.0 { + GapValue::Normal => generate_expr_lit_num!(0.0), + GapValue::LengthPercentage(val) => generate_expr_by_length_percentage!(val, Platform::Harmony), + } + )); + expr.push(( + generate_prop_name!("columnGap"), + match &gap.1 { + GapValue::Normal => generate_expr_lit_num!(0.0), + GapValue::LengthPercentage(val) => generate_expr_by_length_percentage!(val, Platform::Harmony), + } + )); + } + PropertyTuple::Array(expr) } fn to_rn_expr(&self) -> PropertyTuple { - PropertyTuple::One( - generate_prop_name!(*self.id), - match &self.value { - EnumValue::String(value) => generate_expr_lit_str!(value.to_owned()), - EnumValue::LengthValue(length_value) => generate_expr_by_length_value(length_value, Platform::ReactNative), - EnumValue::Percentage(value) => generate_expr_lit_str!((value.0 * 100.0).to_string() + "%"), - EnumValue::Normal => generate_expr_lit_str!("normal"), - } - ) - } -} - -macro_rules! generate_gap { - ($value:expr) => { - match &$value { - GapValue::Normal => EnumValue::Normal, - GapValue::LengthPercentage(value) => match value { - DimensionPercentage::Dimension(value) => { - EnumValue::LengthValue(value.clone()) - } - DimensionPercentage::Percentage(value) => { - EnumValue::Percentage(value.clone()) + let mut expr = vec![]; + if let Some(row) = &self.row { + expr.push(( + generate_prop_name!("rowGap"), + match &row { + GapValue::Normal => generate_expr_lit_num!(0.0), + GapValue::LengthPercentage(val) => generate_expr_by_length_percentage!(val, Platform::ReactNative), } - DimensionPercentage::Calc(value) => { - EnumValue::String(value.to_css_string(PrinterOptions::default()).unwrap()) + )) + } + if let Some(column) = &self.column { + expr.push(( + generate_prop_name!("columnGap"), + match &column { + GapValue::Normal => generate_expr_lit_num!(0.0), + GapValue::LengthPercentage(val) => generate_expr_by_length_percentage!(val, Platform::ReactNative), } - }, + )) } + if let Some(gap) = &self.gap { + let items: Vec = vec![ + generate_expr_gap!(gap.0.borrow()), + generate_expr_gap!(gap.1.borrow()) + ]; + + expr.push(( + generate_prop_name!("gap"), + generate_tpl_expr!(items) + )) + } + PropertyTuple::Array( + expr + ) } } + impl From<(String, &Property<'_>)> for Gap { fn from(prop: (String, &Property<'_>)) -> Self { - Gap { + let mut gap = Gap { id: prop.0, - value: match &prop.1 { - Property::RowGap(value) => { - generate_gap!(value) - } - Property::ColumnGap(value) => { - generate_gap!(value) - } - _ => EnumValue::Normal + row: None, + column: None, + gap: None + }; + match prop.1 { + Property::Gap(value) => { + gap.gap = Some((value.row.clone(), value.column.clone())); } - } + Property::RowGap(value) => { + gap.row = Some(value.clone()) + } + Property::ColumnGap(value) => { + gap.column = Some(value.clone()) + } + _ => {} + }; + gap } } diff --git a/src/style_propetries/macros.rs b/src/style_propetries/macros.rs index 44dc1ec..1b4d208 100644 --- a/src/style_propetries/macros.rs +++ b/src/style_propetries/macros.rs @@ -28,16 +28,17 @@ macro_rules! generate_expr_ident { #[macro_export] macro_rules! generate_string_by_css_color { - ($color:expr) => { - $color.to_css_string(lightningcss::stylesheet::PrinterOptions { + ($color:expr) => {{ + use $crate::style_propetries::unit::convert_color_keywords_to_hex; + convert_color_keywords_to_hex($color.to_css_string(lightningcss::stylesheet::PrinterOptions { minify: false, targets: lightningcss::targets::Targets { include: lightningcss::targets::Features::HexAlphaColors, ..lightningcss::targets::Targets::default() }, ..lightningcss::stylesheet::PrinterOptions::default() - }).unwrap().into() - }; + }).unwrap()).into() + }}; } #[macro_export] @@ -52,6 +53,32 @@ macro_rules! generate_expr_by_length { }}; } +#[macro_export] +macro_rules! generate_expr_by_length_percentage_or_auto { + ($var:expr, $platform:expr) => {{ + + match $var { + LengthPercentageOrAuto::LengthPercentage(length_percent) => { + generate_expr_by_length_percentage!(length_percent, $platform) + }, + LengthPercentageOrAuto::Auto => generate_invalid_expr!(), + } + }}; +} + + +#[macro_export] +macro_rules! generate_expr_by_length_percentage { + ($var:expr, $platform:expr) => {{ + use $crate::style_propetries::unit::{generate_expr_by_length_value}; + + match $var { + lightningcss::values::percentage::DimensionPercentage::Dimension(dimension) => generate_expr_by_length_value(&dimension, $platform), + lightningcss::values::percentage::DimensionPercentage::Percentage(percentage) => generate_expr_lit_str!((percentage.0 * 100.0).to_string() + "%"), + lightningcss::values::percentage::DimensionPercentage::Calc(calc) => generate_expr_lit_str!(calc.to_css_string(lightningcss::stylesheet::PrinterOptions::default()).unwrap()), + } + }}; +} #[macro_export] macro_rules! generate_invalid_expr { @@ -116,14 +143,15 @@ macro_rules! generate_color_property { value: match prop.1 { $( lightningcss::properties::Property::$property_name(_) => { - prop.1.value_to_css_string(lightningcss::stylesheet::PrinterOptions { + use $crate::style_propetries::unit::convert_color_keywords_to_hex; + convert_color_keywords_to_hex(prop.1.value_to_css_string(lightningcss::stylesheet::PrinterOptions { minify: false, targets: lightningcss::targets::Targets { include: lightningcss::targets::Features::HexAlphaColors, ..lightningcss::targets::Targets::default() }, ..lightningcss::stylesheet::PrinterOptions::default() - }).unwrap() + }).unwrap()) } )* _ => "".to_string() @@ -188,9 +216,19 @@ macro_rules! generate_number_property { } } } + + impl $class { + pub fn from_value (prop: (String, f32)) -> Self { + $class { + id: prop.0, + value: prop.1 + } + } + } }; } + // 生成property_name的value类型为 LengthValue的属性 // 依赖:use swc_ecma_ast; use lightningcss #[macro_export] @@ -337,4 +375,76 @@ macro_rules! generate_size_property { } }; +} + +// 生成字符串模版 +#[macro_export] +macro_rules! generate_tpl_expr { + ($items: expr) => {{ + + let mut quasis = vec![ + swc_ecma_ast::TplElement { + span: swc_common::DUMMY_SP, + tail: false, + cooked: None, + raw: swc_atoms::Atom::from("").into(), + }, + ]; + let mut exprs = vec![]; + $items.iter().for_each(|value| { + match value { + swc_ecma_ast::Expr::Lit(lit) => { + match lit { + swc_ecma_ast::Lit::Str(str_lit) => { + let mut quasi = quasis.pop().unwrap(); + quasi.raw = swc_atoms::Atom::from(format!(" {} {} ",quasi.raw.to_string(), str_lit.value.as_ref())); + quasis.push(quasi); + }, + swc_ecma_ast::Lit::Num(num_lit) => { + let mut quasi = quasis.pop().unwrap(); + quasi.raw = swc_atoms::Atom::from(format!(" {} {} ",quasi.raw.to_string(), num_lit.value.to_string())); + quasis.push(quasi); + }, + _ => {} + }; + }, + _ => { + exprs.push(Box::new(value.to_owned())); + quasis.push( + swc_ecma_ast::TplElement { + span: swc_common::DUMMY_SP, + tail: false, + cooked: None, + raw: swc_atoms::Atom::from("").into(), + }, + ) + } + } + }); + + // 删除无用空格 + for (i, quasi) in quasis.clone().into_iter().enumerate() { + let cleaned_string: String = quasi.raw + .split_whitespace() + .collect::>() + .join(" "); + if i == 0 { + quasis[i].raw = swc_atoms::Atom::from(format!("{} ", cleaned_string).trim_start()).into(); + } else if i == quasis.len() - 1 { + quasis[i].raw = swc_atoms::Atom::from(format!(" {}", cleaned_string).trim_end()).into(); + quasis[i].tail = true; + } else { + quasis[i].raw = swc_atoms::Atom::from(format!(" {} ", cleaned_string)).into(); + } + } + if quasis.len() == 1 { + quasis[0].raw = swc_atoms::Atom::from(format!("{} ", quasis[0].raw).trim()).into(); + } + + swc_ecma_ast::Expr::Tpl(swc_ecma_ast::Tpl { + span: swc_common::DUMMY_SP, + exprs, + quasis: quasis, + }) + }}; } \ No newline at end of file diff --git a/src/style_propetries/marin_padding.rs b/src/style_propetries/marin_padding.rs new file mode 100644 index 0000000..94f564a --- /dev/null +++ b/src/style_propetries/marin_padding.rs @@ -0,0 +1,83 @@ +use std::vec; + +use lightningcss::{ + properties::Property, traits::ToCss, values::length::LengthPercentageOrAuto +}; +use swc_ecma_ast::Expr; + +use crate::{generate_expr_by_length_percentage, generate_expr_by_length_percentage_or_auto, generate_expr_lit_str, generate_invalid_expr, generate_prop_name, generate_tpl_expr, style_propetries::traits::ToExpr}; + +use super::unit::{Platform, PropertyTuple}; + + +#[derive(Debug, Clone)] +pub struct MarginPadding { + pub id: String, + top: Option, + right: Option, + bottom: Option, + left: Option, +} + +impl MarginPadding { + + pub fn new(id: String) -> Self { + MarginPadding { + id: id, + top: None, + right: None, + bottom: None, + left: None, + } + } +} + +impl ToExpr for MarginPadding { + fn to_expr(&self) -> PropertyTuple { + PropertyTuple::Array(vec![ + (generate_prop_name!("marginTop"), generate_expr_by_length_percentage_or_auto!(self.top.as_ref().unwrap(), Platform::Harmony)), + (generate_prop_name!("marginRight"), generate_expr_by_length_percentage_or_auto!(self.right.as_ref().unwrap(), Platform::Harmony)), + (generate_prop_name!("marginBottom"), generate_expr_by_length_percentage_or_auto!(self.bottom.as_ref().unwrap(), Platform::Harmony)), + (generate_prop_name!("marginLeft"), generate_expr_by_length_percentage_or_auto!(self.left.as_ref().unwrap(), Platform::Harmony)), + + ]) + } + + fn to_rn_expr(&self) -> PropertyTuple { + + let margin_padding = vec![ + generate_expr_by_length_percentage_or_auto!(self.top.as_ref().unwrap(), Platform::ReactNative), + generate_expr_by_length_percentage_or_auto!(self.right.as_ref().unwrap(), Platform::ReactNative), + generate_expr_by_length_percentage_or_auto!(self.bottom.as_ref().unwrap(), Platform::ReactNative), + generate_expr_by_length_percentage_or_auto!(self.left.as_ref().unwrap(), Platform::ReactNative), + ]; + + PropertyTuple::One( + generate_prop_name!(self.id.clone()), + // 生成`${top} ${right} ${bottom} ${left}` + generate_tpl_expr!(margin_padding) + ) + } +} + +impl From<(String, &Property<'_>)> for MarginPadding { + fn from(prop: (String, &Property<'_>)) -> Self { + let mut margin_padding = MarginPadding::new(prop.0); + match prop.1 { + Property::Margin(value) => { + margin_padding.top = Some(value.top.clone()); + margin_padding.right = Some(value.right.clone()); + margin_padding.bottom = Some(value.bottom.clone()); + margin_padding.left = Some(value.left.clone()); + }, + Property::Padding(value) => { + margin_padding.top = Some(value.top.clone()); + margin_padding.right = Some(value.right.clone()); + margin_padding.bottom = Some(value.bottom.clone()); + margin_padding.left = Some(value.left.clone()); + }, + _ => {} + }; + margin_padding + } +} diff --git a/src/style_propetries/mod.rs b/src/style_propetries/mod.rs index 2e16825..1b360ae 100644 --- a/src/style_propetries/mod.rs +++ b/src/style_propetries/mod.rs @@ -10,6 +10,7 @@ pub mod number; pub mod color; pub mod display; pub mod aspect_ratio; +pub mod flex; pub mod flex_align; pub mod flex_basis; pub mod flex_direction; @@ -32,3 +33,6 @@ pub mod border_width; pub mod border_radius; pub mod border_style; pub mod border; +pub mod transform; +pub mod transform_properties; +pub mod marin_padding; \ No newline at end of file diff --git a/src/style_propetries/style_value_type.rs b/src/style_propetries/style_value_type.rs index 8c7d772..9aa7675 100644 --- a/src/style_propetries/style_value_type.rs +++ b/src/style_propetries/style_value_type.rs @@ -1,6 +1,6 @@ use crate::generate_expr_based_on_platform; -use super::{traits::{ToExpr, ToStyleValue}, flex_align::FlexAlign, item_align::ItemAlign, aspect_ratio::AspactRatio, display::Display, flex_basis::FlexBasis, unit::{Platform, PropertyTuple}, normal::Normal, flex_direction::FlexDirection, flex_wrap::FlexWrap, gap::Gap, length_value::LengthValueProperty, size::SizeProperty, max_size::MaxSizeProperty, overflow::Overflow, number::NumberProperty, color::ColorProperty, font_size::FontSize, font_weight::FontWeight, line_height::LineHeight, text_align::TextAlign, text_decoration::TextDecoration, text_shadow::TextShadow, letter_spacing::LetterSpacing, font_style::FontStyle, text_transform::TextTransform, vertical_align::VerticalAlign, border_color::BorderColor, border_width::BorderWidth, border_radius::BorderRadius, border_style::BorderStyle, border::Border}; +use super::{aspect_ratio::AspactRatio, border::Border, border_color::BorderColor, border_radius::BorderRadius, border_style::BorderStyle, border_width::BorderWidth, color::ColorProperty, display::Display, 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, text_align::TextAlign, text_decoration::TextDecoration, text_shadow::TextShadow, text_transform::TextTransform, traits::{ToExpr, ToStyleValue}, transform::Transform, unit::{Platform, PropertyTuple}, vertical_align::VerticalAlign}; #[derive(Debug, Clone)] @@ -11,8 +11,10 @@ pub enum StyleValueType { LengthValueProperty(LengthValueProperty), SizeProperty(SizeProperty), MaxSizeProperty(MaxSizeProperty), + MarginPadding(MarginPadding), FlexAlign(FlexAlign), AlignItems(ItemAlign), + Flex(Flex), FlexBasis(FlexBasis), FlexDirection(FlexDirection), FlexWrap(FlexWrap), @@ -34,7 +36,8 @@ pub enum StyleValueType { BorderWidth(BorderWidth), BorderRadius(BorderRadius), BorderStyle(BorderStyle), - Border(Border) + Border(Border), + Transform(Transform) } impl ToStyleValue for StyleValueType { @@ -58,6 +61,12 @@ impl ToStyleValue for StyleValueType { StyleValueType::MaxSizeProperty(value) => { generate_expr_based_on_platform!(platform, value) }, + StyleValueType::MarginPadding(value) => { + generate_expr_based_on_platform!(platform, value) + }, + StyleValueType::Flex(value) => { + generate_expr_based_on_platform!(platform, value) + }, StyleValueType::FlexAlign(value) => { generate_expr_based_on_platform!(platform, value) }, @@ -130,6 +139,9 @@ impl ToStyleValue for StyleValueType { StyleValueType::Border(value) => { generate_expr_based_on_platform!(platform, value) } + StyleValueType::Transform(value) => { + generate_expr_based_on_platform!(platform, value) + } } } diff --git a/src/style_propetries/text_decoration.rs b/src/style_propetries/text_decoration.rs index 5d6bbfb..97c41f6 100644 --- a/src/style_propetries/text_decoration.rs +++ b/src/style_propetries/text_decoration.rs @@ -1,6 +1,6 @@ use lightningcss::{properties::{Property, text}, traits::ToCss, stylesheet::PrinterOptions, targets::{Targets, Features}}; use swc_common::DUMMY_SP; -use swc_ecma_ast::{Expr, Ident, MemberProp, MemberExpr, PropName}; +use swc_ecma_ast::{Expr, Ident, KeyValueProp, MemberExpr, MemberProp, ObjectLit, Prop, PropName, PropOrSpread}; use crate::{style_propetries::traits::ToExpr, generate_invalid_expr, generate_expr_lit_str, generate_prop_name}; @@ -35,24 +35,43 @@ pub struct TextDecorationColor(String); impl ToExpr for TextDecoration { fn to_expr(&self) -> PropertyTuple { + let mut props = vec![]; + + if let Some(line) = &self.line { + props.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: generate_prop_name!("type"), + value: Expr::Member(MemberExpr { + span: DUMMY_SP, + obj: Box::new(Expr::Ident(Ident::new("TextDecorationType".into(), DUMMY_SP))), + prop: MemberProp::Ident(Ident { + span: DUMMY_SP, + sym: match line { + TextDecorationLine::Underline => "Underline", + TextDecorationLine::LineThrough => "LineThrough", + TextDecorationLine::Overline => "Overline", + _ => "None", + } + .into(), + optional: false, + }), + }) + .into(), + })))); + } + + if let Some(color) = &self.color { + props.push( PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: generate_prop_name!("color"), + value: generate_expr_lit_str!(color.0.clone()).into() + })))); + } + PropertyTuple::One( generate_prop_name!(*self.id), - Expr::Member(MemberExpr { + Expr::Object(ObjectLit { span: DUMMY_SP, - obj: Box::new(Expr::Ident(Ident::new("TextDecorationType".into(), DUMMY_SP))), - prop: MemberProp::Ident(Ident { - span: DUMMY_SP, - sym: match self.line { - Some(TextDecorationLine::Underline) => "Underline", - Some(TextDecorationLine::LineThrough) => "LineThrough", - Some(TextDecorationLine::Overline) => "Overline", - _ => "None", - } - .into(), - optional: false, - }), + props: props }) - .into() ) } diff --git a/src/style_propetries/transform.rs b/src/style_propetries/transform.rs new file mode 100644 index 0000000..2647c1a --- /dev/null +++ b/src/style_propetries/transform.rs @@ -0,0 +1,255 @@ +use std::vec; + +use lightningcss::properties::{transform::Transform as LNTransform, Property}; +use swc_ecma_ast::{ArrayLit, Expr, ExprOrSpread}; + +use crate::{generate_prop_name, style_propetries::traits::ToExpr}; + +use super::{transform_properties::{matrix::Matrix, rotate::Rotate, scale::Scale, skew::Skew, translate::Translate}, unit::PropertyTuple}; + + +#[derive(Debug, Clone)] +pub enum Matrix4 { + Translates(Translate), + Rotates(Rotate), + Scales(Scale), + Skew(Skew), + Matrix(Matrix), +} + +#[derive(Debug, Clone)] +pub struct Transform { + pub id: String, + pub value: Vec +} + +impl ToExpr for Transform { + fn to_expr(&self) -> PropertyTuple { + let mut props = vec![]; + self.value.iter().for_each(|item| { + match item { + Matrix4::Translates(value) => { + props.extend(value.to_expr()); + }, + Matrix4::Rotates(value) => { + props.extend(value.to_expr()); + } + Matrix4::Scales(value) => { + props.extend(value.to_expr()); + } + Matrix4::Matrix(value) => { + props.extend(value.to_expr()); + }, + _ => {} + } + }); + PropertyTuple::One( + generate_prop_name!("transform"), + Expr::Array(ArrayLit { + span: Default::default(), + elems: props.into_iter().map(Some).map( + |item| { + Some(ExprOrSpread { + spread: None, + expr: Box::new(item.unwrap()), + }) + } + ).collect::>(), + }) + ) + } + + fn to_rn_expr(&self) -> PropertyTuple { + let mut props = vec![]; + self.value.iter().for_each(|item| { + match item { + Matrix4::Translates(value) => { + props.extend(value.to_rn_expr()); + }, + Matrix4::Rotates(value) => { + props.extend(value.to_rn_expr()); + } + Matrix4::Scales(value) => { + props.extend(value.to_rn_expr()); + } + Matrix4::Skew(value) => { + props.extend(value.to_rn_expr()); + } + Matrix4::Matrix(value) => { + props.extend(value.to_rn_expr()); + } + } + }); + PropertyTuple::One( + generate_prop_name!("transform"), + Expr::Array(ArrayLit { + span: Default::default(), + elems: props.into_iter().map(Some).map( + |item| { + Some(ExprOrSpread { + spread: None, + expr: Box::new(item.unwrap()), + }) + } + ).collect::>(), + }) + ) + } +} + + +impl From<(String, &Property<'_>)> for Transform { + fn from(prop: (String, &Property<'_>)) -> Self { + let mut transform = vec![]; + if let Property::Transform(value, _) = prop.1 { + for item in value.0.iter() { + match item { + LNTransform::Translate(x, y) => { + let mut translate = Translate::new(); + translate.x = Some(x.clone()); + translate.y = Some(y.clone()); + transform.push(Matrix4::Translates(translate)); + } + LNTransform::TranslateX(x) => { + let mut translate = Translate::new(); + translate.x = Some(x.clone()); + transform.push(Matrix4::Translates(translate)); + } + LNTransform::TranslateY(y) => { + let mut translate = Translate::new(); + translate.y = Some(y.clone()); + transform.push(Matrix4::Translates(translate)); + } + LNTransform::TranslateZ(z) => { + let mut translate = Translate::new(); + translate.z = Some(z.clone()); + transform.push(Matrix4::Translates(translate)); + } + LNTransform::Translate3d(x, y, z) => { + let mut translate = Translate::new(); + translate.x = Some(x.clone()); + translate.y = Some(y.clone()); + translate.z = Some(z.clone()); + transform.push(Matrix4::Translates(translate)); + } + LNTransform::Rotate(angle) | LNTransform::RotateZ(angle) => { + let mut rotate = Rotate::new(); + rotate.rotate = Some(1.0); + rotate.angle = angle.clone(); + transform.push(Matrix4::Rotates(rotate)); + } + LNTransform::RotateX(angle) => { + let mut rotate = Rotate::new(); + rotate.x = Some(1.0); + rotate.angle = angle.clone(); + transform.push(Matrix4::Rotates(rotate)); + } + LNTransform::RotateY(angle) => { + let mut rotate = Rotate::new(); + rotate.y = Some(1.0); + rotate.angle = angle.clone(); + transform.push(Matrix4::Rotates(rotate)); + } + LNTransform::Rotate3d(x, y, z, angle) => { + let mut rotate = Rotate::new(); + rotate.x = Some(*x); + rotate.y = Some(*y); + rotate.z = Some(*z); + rotate.angle = angle.clone(); + transform.push(Matrix4::Rotates(rotate)); + } + LNTransform::Scale(x, y) => { + let mut scale = Scale::new(); + scale.x = Some(x.clone()); + scale.y = Some(y.clone()); + transform.push(Matrix4::Scales(scale)); + } + LNTransform::ScaleX(x) => { + 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)); + } + LNTransform::ScaleZ(z) => { + let mut scale = Scale::new(); + scale.z = Some(z.clone()); + transform.push(Matrix4::Scales(scale)); + } + LNTransform::Scale3d(x, y, z) => { + let mut scale = Scale::new(); + scale.x = Some(x.clone()); + scale.y = Some(y.clone()); + scale.z = Some(z.clone()); + transform.push(Matrix4::Scales(scale)); + } + LNTransform::SkewX(x) => { + let mut skew = Skew::new(); + skew.x = Some(x.clone()); + transform.push(Matrix4::Skew(skew)); + } + LNTransform::SkewY(y) => { + let mut skew = Skew::new(); + skew.y = Some(y.clone()); + transform.push(Matrix4::Skew(skew)); + } + LNTransform::Skew(x, y) => { + let mut skew = Skew::new(); + skew.x = Some(x.clone()); + skew.y = Some(y.clone()); + transform.push(Matrix4::Skew(skew)); + } + LNTransform::Matrix(m) => { + let mut matrix = Matrix::new(); + let matrix3d = m.to_matrix3d(); + matrix.m00 = matrix3d.m11; + matrix.m01 = matrix3d.m12; + matrix.m02 = matrix3d.m13; + matrix.m03 = matrix3d.m14; + matrix.m10 = matrix3d.m21; + matrix.m11 = matrix3d.m22; + matrix.m12 = matrix3d.m23; + matrix.m13 = matrix3d.m24; + matrix.m20 = matrix3d.m31; + matrix.m21 = matrix3d.m32; + matrix.m22 = matrix3d.m33; + matrix.m23 = matrix3d.m34; + matrix.m30 = matrix3d.m41; + matrix.m31 = matrix3d.m42; + matrix.m32 = matrix3d.m43; + matrix.m33 = matrix3d.m44; + transform.push(Matrix4::Matrix(matrix)); + } + LNTransform::Matrix3d(m) => { + let mut matrix = Matrix::new(); + matrix.m00 = m.m11; + matrix.m01 = m.m12; + matrix.m02 = m.m13; + matrix.m03 = m.m14; + matrix.m10 = m.m21; + matrix.m11 = m.m22; + matrix.m12 = m.m23; + matrix.m13 = m.m24; + matrix.m20 = m.m31; + matrix.m21 = m.m32; + matrix.m22 = m.m33; + matrix.m23 = m.m34; + matrix.m30 = m.m41; + matrix.m31 = m.m42; + matrix.m32 = m.m43; + matrix.m33 = m.m44; + transform.push(Matrix4::Matrix(matrix)); + } + _ => {} + } + } + } + Transform { + id: prop.0, + value: transform + } + } +} diff --git a/src/style_propetries/transform_properties/matrix.rs b/src/style_propetries/transform_properties/matrix.rs new file mode 100644 index 0000000..3a7cc3e --- /dev/null +++ b/src/style_propetries/transform_properties/matrix.rs @@ -0,0 +1,128 @@ + +use swc_common::DUMMY_SP; +use swc_ecma_ast::{ArrayLit, Expr, Ident, KeyValueProp, Lit, ObjectLit, Prop, PropName, PropOrSpread}; + +use crate::generate_expr_lit_num; + + + +#[derive(Debug, Clone)] +pub struct Matrix { + pub m00: f32, + pub m01: f32, + pub m02: f32, + pub m03: f32, + pub m10: f32, + pub m11: f32, + pub m12: f32, + pub m13: f32, + pub m20: f32, + pub m21: f32, + pub m22: f32, + pub m23: f32, + pub m30: f32, + pub m31: f32, + pub m32: f32, + pub m33: f32, +} + +impl Matrix { + + pub fn new() -> Self { + Matrix { + m00: 1.0, + m01: 0.0, + m02: 0.0, + m03: 0.0, + m10: 0.0, + m11: 1.0, + m12: 0.0, + m13: 0.0, + m20: 0.0, + m21: 0.0, + m22: 1.0, + m23: 0.0, + m30: 0.0, + m31: 0.0, + m32: 0.0, + m33: 1.0, + } + } + pub fn to_expr(&self) -> Vec { + + let expr = Expr::Object(ObjectLit { + span: DUMMY_SP, + props: vec![ + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new("type".into(), DUMMY_SP)), + value: Expr::Lit(Lit::Str(swc_ecma_ast::Str { + span: DUMMY_SP, + value: "Matrix".into(), + raw: None + })).into(), + }))), + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new("value".into(), DUMMY_SP)), + value: Expr::Array(ArrayLit { + span: DUMMY_SP, + elems: vec![ + Some(generate_expr_lit_num!(self.m00 as f64).into()), + Some(generate_expr_lit_num!(self.m01 as f64).into()), + Some(generate_expr_lit_num!(self.m02 as f64).into()), + Some(generate_expr_lit_num!(self.m03 as f64).into()), + Some(generate_expr_lit_num!(self.m10 as f64).into()), + Some(generate_expr_lit_num!(self.m11 as f64).into()), + Some(generate_expr_lit_num!(self.m12 as f64).into()), + Some(generate_expr_lit_num!(self.m13 as f64).into()), + Some(generate_expr_lit_num!(self.m20 as f64).into()), + Some(generate_expr_lit_num!(self.m21 as f64).into()), + Some(generate_expr_lit_num!(self.m22 as f64).into()), + Some(generate_expr_lit_num!(self.m23 as f64).into()), + Some(generate_expr_lit_num!(self.m30 as f64).into()), + Some(generate_expr_lit_num!(self.m31 as f64).into()), + Some(generate_expr_lit_num!(self.m32 as f64).into()), + Some(generate_expr_lit_num!(self.m33 as f64).into()), + ], + }) + .into(), + }))), + ] + }); + vec![expr] + } + + pub fn to_rn_expr(&self) -> Vec { + vec![ + Expr::Object(ObjectLit { + span: DUMMY_SP, + props: vec![ + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new("matrix".into(), DUMMY_SP)), + value: Expr::Array(ArrayLit { + span: DUMMY_SP, + elems: vec![ + Some(generate_expr_lit_num!(self.m00 as f64).into()), + Some(generate_expr_lit_num!(self.m01 as f64).into()), + Some(generate_expr_lit_num!(self.m02 as f64).into()), + Some(generate_expr_lit_num!(self.m03 as f64).into()), + Some(generate_expr_lit_num!(self.m10 as f64).into()), + Some(generate_expr_lit_num!(self.m11 as f64).into()), + Some(generate_expr_lit_num!(self.m12 as f64).into()), + Some(generate_expr_lit_num!(self.m13 as f64).into()), + Some(generate_expr_lit_num!(self.m20 as f64).into()), + Some(generate_expr_lit_num!(self.m21 as f64).into()), + Some(generate_expr_lit_num!(self.m22 as f64).into()), + Some(generate_expr_lit_num!(self.m23 as f64).into()), + Some(generate_expr_lit_num!(self.m30 as f64).into()), + Some(generate_expr_lit_num!(self.m31 as f64).into()), + Some(generate_expr_lit_num!(self.m32 as f64).into()), + Some(generate_expr_lit_num!(self.m33 as f64).into()), + ], + }) + .into(), + }))), + ] + }) + ] + } +} diff --git a/src/style_propetries/transform_properties/mod.rs b/src/style_propetries/transform_properties/mod.rs new file mode 100644 index 0000000..422368a --- /dev/null +++ b/src/style_propetries/transform_properties/mod.rs @@ -0,0 +1,5 @@ +pub mod translate; +pub mod rotate; +pub mod scale; +pub mod skew; +pub mod matrix; \ No newline at end of file diff --git a/src/style_propetries/transform_properties/rotate.rs b/src/style_propetries/transform_properties/rotate.rs new file mode 100644 index 0000000..d7643e9 --- /dev/null +++ b/src/style_propetries/transform_properties/rotate.rs @@ -0,0 +1,93 @@ +use std::{borrow::Borrow, vec}; + +use lightningcss::{printer::PrinterOptions, traits::ToCss, values:: + angle::Angle + } +; +use swc_atoms::Atom; +use swc_common::DUMMY_SP; +use swc_ecma_ast::{Expr, Ident, KeyValueProp, Lit, ObjectLit, Prop, PropName, PropOrSpread}; + +use crate::{generate_expr_lit_num, generate_expr_lit_str, utils::to_camel_case}; + + +#[derive(Debug, Clone)] +pub struct Rotate { + pub x: Option, + pub y: Option, + pub z: Option, + pub rotate: Option, + pub angle: Angle, +} + + +impl Rotate { + pub fn new() -> Self { + Rotate { + x: None, + y: None, + z: None, + rotate: None, + angle: Angle::Deg(0.0), + } + } + + pub fn to_expr(&self) -> Vec { + + let mut props = vec![]; + + [("x", &self.x), ("y", &self.y), ("z", &self.z), ("z", &self.rotate)].into_iter().for_each(|item| { + if let (name, Some(value)) = item.borrow() { + props.push( + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new(Atom::new(*name), DUMMY_SP)), + value: Box::new(generate_expr_lit_num!(*value as f64)) + }))) + ) + } + }); + + let expr = Expr::Object(ObjectLit { + span: DUMMY_SP, + props: vec![ + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new("type".into(), DUMMY_SP)), + value: Expr::Lit(Lit::Str(swc_ecma_ast::Str { + span: DUMMY_SP, + value: "Rotate".into(), + raw: None + })).into(), + }))), + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new("value".into(), DUMMY_SP)), + value: Expr::Object(ObjectLit { + span: DUMMY_SP, + props, + }) + .into(), + }))), + ] + }); + + vec![expr] + + } + + pub fn to_rn_expr(&self) -> Vec { + let mut props = vec![]; + [("-x", &self.x), ("-y", &self.y), ("-z", &self.z), ("", &self.rotate)].into_iter().for_each(|item| { + if let (name, Some(_)) = item.borrow() { + props.push( + Expr::Object(ObjectLit { + span: DUMMY_SP, + props: vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new(to_camel_case(format!("{}{}", "rotate", name).as_str(), false).into(), DUMMY_SP)), + value: Box::new(generate_expr_lit_str!(self.angle.to_css_string(PrinterOptions::default()).unwrap())) + })))] + }) + ); + } + }); + props + } +} diff --git a/src/style_propetries/transform_properties/scale.rs b/src/style_propetries/transform_properties/scale.rs new file mode 100644 index 0000000..fd2a56e --- /dev/null +++ b/src/style_propetries/transform_properties/scale.rs @@ -0,0 +1,100 @@ +use std::{borrow::Borrow, vec}; + +use lightningcss:: + values:: + percentage::NumberOrPercentage + +; +use swc_atoms::Atom; +use swc_common::DUMMY_SP; +use swc_ecma_ast::{Expr, Ident, KeyValueProp, Lit, ObjectLit, Prop, PropName, PropOrSpread}; + +use crate::{generate_expr_lit_num, utils::to_camel_case}; + + +#[derive(Debug, Clone)] +pub struct Scale { + pub x: Option, + pub y: Option, + pub z: Option +} + + +impl Scale { + pub fn new() -> Self { + Scale { + x: None, + y: None, + z: None, + } + } + + pub fn to_expr(&self) -> Vec { + + let mut props = vec![]; + + [("x", &self.x), ("y", &self.y), ("z", &self.z)].into_iter().for_each(|item| { + if let (name, Some(side)) = item.borrow() { + match &side { + NumberOrPercentage::Number(value) => { + props.push( + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new(Atom::new(*name), DUMMY_SP)), + value: Box::new(generate_expr_lit_num!(*value as f64)) + }))) + ); + }, + _ => {} + } + } + }); + + let expr = Expr::Object(ObjectLit { + span: DUMMY_SP, + props: vec![ + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new("type".into(), DUMMY_SP)), + value: Expr::Lit(Lit::Str(swc_ecma_ast::Str { + span: DUMMY_SP, + value: "Scale".into(), + raw: None + })).into(), + }))), + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new("value".into(), DUMMY_SP)), + value: Expr::Object(ObjectLit { + span: DUMMY_SP, + props, + }) + .into(), + }))), + ] + }); + + vec![expr] + + } + + pub fn to_rn_expr(&self) -> Vec { + let mut props = vec![]; + [("x", &self.x), ("y", &self.y)].into_iter().for_each(|item| { + if let (name, Some(side)) = item.borrow() { + match &side { + NumberOrPercentage::Number(value) => { + props.push( + Expr::Object(ObjectLit { + span: DUMMY_SP, + props: vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new(to_camel_case(format!("{}{}", "scale-", name).as_str(), false).into(), DUMMY_SP)), + value: Box::new(generate_expr_lit_num!(*value as f64)) + })))] + }) + ); + }, + _ => {} + } + } + }); + props + } +} diff --git a/src/style_propetries/transform_properties/skew.rs b/src/style_propetries/transform_properties/skew.rs new file mode 100644 index 0000000..f76c6f5 --- /dev/null +++ b/src/style_propetries/transform_properties/skew.rs @@ -0,0 +1,42 @@ +use std::{borrow::Borrow, vec}; + +use lightningcss::{printer::PrinterOptions, traits::ToCss, values::angle::Angle} +; +use swc_common::DUMMY_SP; +use swc_ecma_ast::{Expr, Ident, KeyValueProp, ObjectLit, Prop, PropName, PropOrSpread}; + +use crate::{generate_expr_lit_str, utils::to_camel_case}; + + +#[derive(Debug, Clone)] +pub struct Skew { + pub x: Option, + pub y: Option, +} + + +impl Skew { + pub fn new() -> Self { + Skew { + x: None, + y: None, + } + } + pub fn to_rn_expr(&self) -> Vec { + let mut props = vec![]; + [("x", &self.x), ("y", &self.y)].into_iter().for_each(|item| { + if let (name, Some(side)) = item.borrow() { + props.push( + Expr::Object(ObjectLit { + span: DUMMY_SP, + props: vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new(to_camel_case(format!("{}{}", "skew-", name).as_str(), false).into(), DUMMY_SP)), + value: Box::new(generate_expr_lit_str!(side.to_css_string(PrinterOptions::default()).unwrap())) + })))] + }) + ) + } + }); + props + } +} diff --git a/src/style_propetries/transform_properties/translate.rs b/src/style_propetries/transform_properties/translate.rs new file mode 100644 index 0000000..5a44740 --- /dev/null +++ b/src/style_propetries/transform_properties/translate.rs @@ -0,0 +1,110 @@ +use std::{borrow::Borrow, vec}; + +use lightningcss:: + values::{ + length::{Length, LengthValue}, percentage::DimensionPercentage + } +; +use swc_atoms::Atom; +use swc_common::DUMMY_SP; +use swc_ecma_ast::{Expr, Ident, KeyValueProp, Lit, ObjectLit, Prop, PropName, PropOrSpread}; + +use crate::{style_propetries::unit::{generate_expr_by_length_value, Platform}, utils::to_camel_case}; + + +#[derive(Debug, Clone)] +pub struct Translate { + pub x: Option>, + pub y: Option>, + pub z: Option, +} + + +impl Translate { + pub fn new() -> Self { + Translate { + x: None, + y: None, + z: None, + } + } + + pub fn to_expr(&self) -> Vec { + + let mut props = vec![]; + + [("x", &self.x), ("y", &self.y)].into_iter().for_each(|item| { + if let (name, Some(side)) = item.borrow() { + match &side { + DimensionPercentage::Dimension(value) => { + props.push( + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new(Atom::new(*name), DUMMY_SP)), + value: Box::new(generate_expr_by_length_value(value, Platform::Harmony)) + }))) + ); + }, + _ => {} + } + } + }); + + if let Some(z) = &self.z { + match z { + Length::Value(val) => props.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new(stringify!("z").into(), DUMMY_SP)), + value: Box::new(generate_expr_by_length_value(&val, Platform::Harmony)) + })))), + _ => {} + }; + } + + let expr = Expr::Object(ObjectLit { + span: DUMMY_SP, + props: vec![ + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new("type".into(), DUMMY_SP)), + value: Expr::Lit(Lit::Str(swc_ecma_ast::Str { + span: DUMMY_SP, + value: "Translate".into(), + raw: None + })).into(), + }))), + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new("value".into(), DUMMY_SP)), + value: Expr::Object(ObjectLit { + span: DUMMY_SP, + props, + }) + .into(), + }))), + ] + }); + + vec![expr] + + } + + pub fn to_rn_expr(&self) -> Vec { + let mut props = vec![]; + [("x", &self.x), ("y", &self.y)].into_iter().for_each(|item| { + if let (name, Some(side)) = item.borrow() { + match &side { + DimensionPercentage::Dimension(value) => { + props.push( + Expr::Object(ObjectLit { + span: DUMMY_SP, + props: vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new(to_camel_case(format!("{}{}", "translate-", name).as_str(), false).into(), DUMMY_SP)), + value: Box::new(generate_expr_by_length_value(value, Platform::ReactNative)) + })))] + }) + ); + }, + _ => {} + } + } + }); + props + } +} diff --git a/src/style_propetries/unit.rs b/src/style_propetries/unit.rs index 7a50638..4dffc11 100644 --- a/src/style_propetries/unit.rs +++ b/src/style_propetries/unit.rs @@ -183,3 +183,159 @@ pub fn generate_expr_with_css_input(input: String) -> Expr { // 如果没有匹配到,则返回原始字符串 Expr::Lit(Lit::Str(input.into())) } + + +// 处理将color关键字转换为hex +// 参考颜色关键字:https://www.w3.org/TR/css-color-3/#svg-color +pub fn convert_color_keywords_to_hex(color: String) -> String { + match color.as_str() { + "aliceblue" => "#F0F8FF".to_string(), + "antiquewhite" => "#FAEBD7".to_string(), + "aqua" => "#00FFFF".to_string(), + "aquamarine" => "#7FFFD4".to_string(), + "azure" => "#F0FFFF".to_string(), + "beige" => "#F5F5DC".to_string(), + "bisque" => "#FFE4C4".to_string(), + "black" => "#000000".to_string(), + "blanchedalmond" => "#FFEBCD".to_string(), + "blue" => "#0000FF".to_string(), + "blueviolet" => "#8A2BE2".to_string(), + "brown" => "#A52A2A".to_string(), + "burlywood" => "#DEB887".to_string(), + "cadetblue" => "#5F9EA0".to_string(), + "chartreuse" => "#7FFF00".to_string(), + "chocolate" => "#D2691E".to_string(), + "coral" => "#FF7F50".to_string(), + "cornflowerblue" => "#6495ED".to_string(), + "cornsilk" => "#FFF8DC".to_string(), + "crimson" => "#DC143C".to_string(), + "cyan" => "#00FFFF".to_string(), + "darkblue" => "#00008B".to_string(), + "darkcyan" => "#008B8B".to_string(), + "darkgoldenrod" => "#B8860B".to_string(), + "darkgray" => "#A9A9A9".to_string(), + "darkgreen" => "#006400".to_string(), + "darkgrey" => "#A9A9A9".to_string(), + "darkkhaki" => "#BDB76B".to_string(), + "darkmagenta" => "#8B008B".to_string(), + "darkolivegreen" => "#556B2F".to_string(), + "darkorange" => "#FF8C00".to_string(), + "darkorchid" => "#9932CC".to_string(), + "darkred" => "#8B0000".to_string(), + "darksalmon" => "#E9967A".to_string(), + "darkseagreen" => "#8FBC8F".to_string(), + "darkslateblue" => "#483D8B".to_string(), + "darkslategray" => "#2F4F4F".to_string(), + "darkslategrey" => "#2F4F4F".to_string(), + "darkturquoise" => "#00CED1".to_string(), + "darkviolet" => "#9400D3".to_string(), + "deeppink" => "#FF1493".to_string(), + "deepskyblue" => "#00BFFF".to_string(), + "dimgray" => "#696969".to_string(), + "dimgrey" => "#696969".to_string(), + "dodgerblue" => "#1E90FF".to_string(), + "firebrick" => "#B22222".to_string(), + "floralwhite" => "#FFFAF0".to_string(), + "forestgreen" => "#228B22".to_string(), + "fuchsia" => "#FF00FF".to_string(), + "gainsboro" => "#DCDCDC".to_string(), + "ghostwhite" => "#F8F8FF".to_string(), + "gold" => "#FFD700".to_string(), + "goldenrod" => "#DAA520".to_string(), + "gray" => "#808080".to_string(), + "green" => "#008000".to_string(), + "greenyellow" => "#ADFF2F".to_string(), + "grey" => "#808080".to_string(), + "honeydew" => "#F0FFF0".to_string(), + "hotpink" => "#FF69B4".to_string(), + "indianred" => "#CD5C5C".to_string(), + "indigo" => "#4B0082".to_string(), + "ivory" => "#FFFFF0".to_string(), + "khaki" => "#F0E68C".to_string(), + "lavender" => "#E6E6FA".to_string(), + "lavenderblush" => "#FFF0F5".to_string(), + "lawngreen" => "#7CFC00".to_string(), + "lemonchiffon" => "#FFFACD".to_string(), + "lightblue" => "#ADD8E6".to_string(), + "lightcoral" => "#F08080".to_string(), + "lightcyan" => "#E0FFFF".to_string(), + "lightgoldenrodyellow" => "#FAFAD2".to_string(), + "lightgray" => "#D3D3D3".to_string(), + "lightgreen" => "#90EE90".to_string(), + "lightgrey" => "#D3D3D3".to_string(), + "lightpink" => "#FFB6C1".to_string(), + "lightsalmon" => "#FFA07A".to_string(), + "lightseagreen" => "#20B2AA".to_string(), + "lightskyblue" => "#87CEFA".to_string(), + "lightslategray" => "#778899".to_string(), + "lightslategrey" => "#778899".to_string(), + "lightsteelblue" => "#B0C4DE".to_string(), + "lightyellow" => "#FFFFE0".to_string(), + "lime" => "#00FF00".to_string(), + "limegreen" => "#32CD32".to_string(), + "linen" => "#FAF0E6".to_string(), + "magenta" => "#FF00FF".to_string(), + "maroon" => "#800000".to_string(), + "mediumaquamarine" => "#66CDAA".to_string(), + "mediumblue" => "#0000CD".to_string(), + "mediumorchid" => "#BA55D3".to_string(), + "mediumpurple" => "#9370DB".to_string(), + "mediumseagreen" => "#3CB371".to_string(), + "mediumslateblue" => "#7B68EE".to_string(), + "mediumspringgreen" => "#00FA9A".to_string(), + "mediumturquoise" => "#48D1CC".to_string(), + "mediumvioletred" => "#C71585".to_string(), + "midnightblue" => "#191970".to_string(), + "mintcream" => "#F5FFFA".to_string(), + "mistyrose" => "#FFE4E1".to_string(), + "moccasin" => "#FFE4B5".to_string(), + "navajowhite" => "#FFDEAD".to_string(), + "navy" => "#000080".to_string(), + "oldlace" => "#FDF5E6".to_string(), + "olive" => "#808000".to_string(), + "olivedrab" => "#6B8E23".to_string(), + "orange" => "#FFA500".to_string(), + "orangered" => "#FF4500".to_string(), + "orchid" => "#DA70D6".to_string(), + "palegoldenrod" => "#EEE8AA".to_string(), + "palegreen" => "#98FB98".to_string(), + "paleturquoise" => "#AFEEEE".to_string(), + "palevioletred" => "#DB7093".to_string(), + "papayawhip" => "#FFEFD5".to_string(), + "peachpuff" => "#FFDAB9".to_string(), + "peru" => "#CD853F".to_string(), + "pink" => "#FFC0CB".to_string(), + "plum" => "#DDA0DD".to_string(), + "powderblue" => "#B0E0E6".to_string(), + "purple" => "#800080".to_string(), + "red" => "#FF0000".to_string(), + "rosybrown" => "#BC8F8F".to_string(), + "royalblue" => "#4169E1".to_string(), + "saddlebrown" => "#8B4513".to_string(), + "salmon" => "#FA8072".to_string(), + "sandybrown" => "#F4A460".to_string(), + "seagreen" => "#2E8B57".to_string(), + "seashell" => "#FFF5EE".to_string(), + "sienna" => "#A0522D".to_string(), + "silver" => "#C0C0C0".to_string(), + "skyblue" => "#87CEEB".to_string(), + "slateblue" => "#6A5ACD".to_string(), + "slategray" => "#708090".to_string(), + "slategrey" => "#708090".to_string(), + "snow" => "#FFFAFA".to_string(), + "springgreen" => "#00FF7F".to_string(), + "steelblue" => "#4682B4".to_string(), + "tan" => "#D2B48C".to_string(), + "teal" => "#008080".to_string(), + "thistle" => "#D8BFD8".to_string(), + "tomato" => "#FF6347".to_string(), + "turquoise" => "#40E0D0".to_string(), + "violet" => "#EE82EE".to_string(), + "wheat" => "#F5DEB3".to_string(), + "white" => "#FFFFFF".to_string(), + "whitesmoke" => "#F5F5F5".to_string(), + "yellow" => "#FFFF00".to_string(), + "yellowgreen" => "#9ACD32".to_string(), + _ => color + } +} \ No newline at end of file diff --git a/src/style_propetries/vertical_align.rs b/src/style_propetries/vertical_align.rs index 8266ef7..c7a219d 100644 --- a/src/style_propetries/vertical_align.rs +++ b/src/style_propetries/vertical_align.rs @@ -57,7 +57,7 @@ impl ToExpr for VerticalAlign { fn to_rn_expr(&self) -> PropertyTuple { PropertyTuple::One( - generate_prop_name!(*self.id), + generate_prop_name!("textAlignVertical"), match self.value { EnumValue::Baseline => generate_invalid_expr!(), EnumValue::Sub => generate_invalid_expr!(), diff --git a/src/style_transform/transform/rotate.rs b/src/style_transform/transform/rotate.rs index 9d52367..7d6e0db 100644 --- a/src/style_transform/transform/rotate.rs +++ b/src/style_transform/transform/rotate.rs @@ -16,8 +16,6 @@ pub struct Rotate { pub y: Option, pub z: Option, pub angle: StringNumber, - pub center_x: Option, - pub center_y: Option, } impl Rotate { @@ -27,8 +25,6 @@ impl Rotate { y: None, z: None, angle: StringNumber::Number(0.0), - center_x: None, - center_y: None, } } } diff --git a/src/style_transform/transform/scale.rs b/src/style_transform/transform/scale.rs index deece2c..dcf98f5 100644 --- a/src/style_transform/transform/scale.rs +++ b/src/style_transform/transform/scale.rs @@ -5,7 +5,7 @@ use crate::{ impl_to_expr_for_transform_mem, style_transform::{ traits::ToExpr, - utils::{StringNumber, WrapCSSNumber}, + utils::WrapCSSNumber, }, utils::to_camel_case, }; @@ -15,8 +15,6 @@ pub struct Scale { pub x: Option, pub y: Option, pub z: Option, - pub center_x: Option, - pub center_y: Option, } impl Scale { @@ -25,8 +23,6 @@ impl Scale { x: None, y: None, z: None, - center_x: None, - center_y: None, } } }