diff --git a/.changeset/six-lions-float.md b/.changeset/six-lions-float.md new file mode 100644 index 00000000..f68c5dcf --- /dev/null +++ b/.changeset/six-lions-float.md @@ -0,0 +1,5 @@ +--- +"@devup-ui/webpack-plugin": patch +--- + +Fix css pile up issue diff --git a/.changeset/strong-owls-rescue.md b/.changeset/strong-owls-rescue.md new file mode 100644 index 00000000..c4a963ca --- /dev/null +++ b/.changeset/strong-owls-rescue.md @@ -0,0 +1,5 @@ +--- +"@devup-ui/react": patch +--- + +Add placehoder to selector diff --git a/.changeset/ten-walls-cheer.md b/.changeset/ten-walls-cheer.md new file mode 100644 index 00000000..5d5f46e3 --- /dev/null +++ b/.changeset/ten-walls-cheer.md @@ -0,0 +1,5 @@ +--- +"@devup-ui/wasm": patch +--- + +Fix ternary operator issue, css order issue, basic style issue diff --git a/Cargo.lock b/Cargo.lock index 6a406c04..6bac79ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -436,20 +436,22 @@ dependencies = [ [[package]] name = "oxc_allocator" -version = "0.46.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd735ac4f5202cd854cc1f23b334de42e034ed89b07ea5acc183c629ac961922" +checksum = "5f5b38027b943889e914774968782a2b67df6ba50f6d4e265eaa7a933a8e3075" dependencies = [ "allocator-api2", "bumpalo", + "hashbrown", + "rustc-hash", "simdutf8", ] [[package]] name = "oxc_ast" -version = "0.46.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c509311d40c5364ecd88b4dbc5f69634eb7e760bd1d549863c6d74bc4be26c33" +checksum = "eb78951e98af99dfdac1e530f5a36af114d9d8a03e967b5ea68be271509183da" dependencies = [ "bitflags", "cow-utils", @@ -465,9 +467,9 @@ dependencies = [ [[package]] name = "oxc_ast_macros" -version = "0.46.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "920d141997d08c4d3110c5461418e23270e484f608b4e5c4d186ad794cef5c51" +checksum = "f17b1dc89732a6969c6dcb274035c737db46fe1f378ce86fb6c4674db201f5ca" dependencies = [ "proc-macro2", "quote", @@ -476,9 +478,9 @@ dependencies = [ [[package]] name = "oxc_cfg" -version = "0.46.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f1234386c2df9690b8bcc3f4da22ab27ceb699ee1ed40a803ae4029aa6eb6c5" +checksum = "3bc62e52879170ba6e818ec93f8ed2c32e38afa3de0aee64fb28555e91615843" dependencies = [ "bitflags", "itertools", @@ -491,9 +493,9 @@ dependencies = [ [[package]] name = "oxc_codegen" -version = "0.46.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3974d4e1727035d012401743e95d81956341d7baf84c9d318996ee36f1e658ca" +checksum = "64866a6b9761c75da095ef24a93925fe7be309373125c4bf52ebc959b3254035" dependencies = [ "assert-unchecked", "bitflags", @@ -511,9 +513,9 @@ dependencies = [ [[package]] name = "oxc_data_structures" -version = "0.46.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6a1dbe29d67d3ed8b8f6582dd0b1de3b50c10f3e8f6505cef2340205eccc2c2" +checksum = "24075d02645a88bc56ea5b82bddf685eeb58284df2079ac357d26222bbe382be" dependencies = [ "assert-unchecked", "ropey", @@ -521,19 +523,18 @@ dependencies = [ [[package]] name = "oxc_diagnostics" -version = "0.46.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7987595069022940d1100d0206b3ccbbb6f7f35a0cc61a12031d3a4079abba84" +checksum = "0b5f7392025441f29ae145b21bc0e656530f2443fb197195b6ba39ac0d613b8b" dependencies = [ "oxc-miette", - "rustc-hash", ] [[package]] name = "oxc_ecmascript" -version = "0.46.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d95c9815396146b129c43deaab2d9f136c14ed2883663133edf81a0f77d7d6" +checksum = "5993579c5c04491bfcfc9a675c9939caa9f8f5faceecc5e4d281c432bbfd4c6e" dependencies = [ "num-bigint", "num-traits", @@ -544,9 +545,9 @@ dependencies = [ [[package]] name = "oxc_estree" -version = "0.46.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "987b6d27d27d361009a61167c6a925053e840eadddf62136060772af0f5e9692" +checksum = "0b216e48759b14e08652c925aa024f6b2d318a795793bbe51482718829ac9bc4" [[package]] name = "oxc_index" @@ -556,11 +557,10 @@ checksum = "5eca5d9726cd0a6e433debe003b7bc88b2ecad0bb6109f0cef7c55e692139a34" [[package]] name = "oxc_mangler" -version = "0.46.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cffde4bbb35698c67efaeb03989c836a01e62a59f82231831df9eafb60f221" +checksum = "7241cb3b72c30d77117fc07066bfa7530bb52c0c769996186ea6779d287f37c3" dependencies = [ - "compact_str", "itertools", "oxc_allocator", "oxc_ast", @@ -572,9 +572,9 @@ dependencies = [ [[package]] name = "oxc_parser" -version = "0.46.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e9f2e3a80279537b52ffab68282e09062a8794c421bc7e57c6b9b5060a8447" +checksum = "08e83d2a08991efc1a79c3b42fcc77344f3de58d27c53cd9b184d17b1ed4ace3" dependencies = [ "assert-unchecked", "bitflags", @@ -595,9 +595,9 @@ dependencies = [ [[package]] name = "oxc_regular_expression" -version = "0.46.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22065fe1523c70162b00cd6ac6e5b9ddd521cedf4f691801f0d024ee1f619a40" +checksum = "d495804e1bf588e5e1a2d6fe760ff1ba53ece5cbf04e4dce531da64014869fea" dependencies = [ "oxc_allocator", "oxc_ast_macros", @@ -611,12 +611,11 @@ dependencies = [ [[package]] name = "oxc_semantic" -version = "0.46.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca7a8365faa0603f314b62b24cd751342455bd339f8d25d354f7dfd2c48628a" +checksum = "f93df6d4abf46480c5479eba2a367e9fb837aece6f908d4d4271c2e5ae1bf126" dependencies = [ "assert-unchecked", - "hashbrown", "itertools", "oxc_allocator", "oxc_ast", @@ -648,9 +647,9 @@ dependencies = [ [[package]] name = "oxc_span" -version = "0.46.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "394f0317461a29c55a50a05c70e3ea23694cdb3748ff7adab979a6a60c2cb709" +checksum = "9a50160bfd66b0ef0acff1181c6860c61cf59d6c0d5bf05b589f1fc6dcdbafc2" dependencies = [ "compact_str", "oxc-miette", @@ -661,9 +660,9 @@ dependencies = [ [[package]] name = "oxc_syntax" -version = "0.46.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dc1cad48f366df99384009928eae2b5dab39b629123b704ccb03221d41eddf4" +checksum = "7aa0a2543f375feb387b0b94a6d72ec5b0cc6a2349518d48704189b23d6c4070" dependencies = [ "assert-unchecked", "bitflags", @@ -947,6 +946,7 @@ name = "sheet" version = "0.1.0" dependencies = [ "css", + "insta", ] [[package]] diff --git a/bindings/devup-ui-wasm/src/lib.rs b/bindings/devup-ui-wasm/src/lib.rs index fa11103e..7b4d4776 100644 --- a/bindings/devup-ui-wasm/src/lib.rs +++ b/bindings/devup-ui-wasm/src/lib.rs @@ -51,6 +51,7 @@ impl Output { st.level(), st.value(), st.selector(), + st.basic(), ) { collected = true; } @@ -62,6 +63,7 @@ impl Output { dy.level(), &format!("var({})", variable.unwrap()), dy.selector(), + false, ) { collected = true; } diff --git a/libs/extractor/Cargo.toml b/libs/extractor/Cargo.toml index debfd490..4652bf4d 100644 --- a/libs/extractor/Cargo.toml +++ b/libs/extractor/Cargo.toml @@ -4,12 +4,12 @@ version = "0.1.0" edition = "2021" [dependencies] -oxc_parser = "0.46.0" -oxc_syntax = "0.46.0" -oxc_span = "0.46.0" -oxc_allocator = "0.46.0" -oxc_ast = "0.46.0" -oxc_codegen = "0.46.0" +oxc_parser = "0.47.1" +oxc_syntax = "0.47.1" +oxc_span = "0.47.1" +oxc_allocator = "0.47.1" +oxc_ast = "0.47.1" +oxc_codegen = "0.47.1" css = { path = "../css" } once_cell = "1.20.2" diff --git a/libs/extractor/src/component.rs b/libs/extractor/src/component.rs index b5619bf8..a0f16142 100644 --- a/libs/extractor/src/component.rs +++ b/libs/extractor/src/component.rs @@ -41,23 +41,17 @@ impl ExportVariableKind { | ExportVariableKind::Text | ExportVariableKind::Image | ExportVariableKind::Box => vec![], - ExportVariableKind::Flex => vec![Static(ExtractStaticStyle::new( - "display".to_string(), - "flex".to_string(), - 0, - None, - ))], + ExportVariableKind::Flex => { + vec![Static(ExtractStaticStyle::new_basic( + "display", "flex", 0, None, + ))] + } ExportVariableKind::VStack => { vec![ - Static(ExtractStaticStyle::new( - "display".to_string(), - "flex".to_string(), - 0, - None, - )), - Static(ExtractStaticStyle::new( - "flexDirection".to_string(), - "column".to_string(), + Static(ExtractStaticStyle::new_basic("display", "flex", 0, None)), + Static(ExtractStaticStyle::new_basic( + "flexDirection", + "column", 0, None, )), @@ -65,32 +59,26 @@ impl ExportVariableKind { } ExportVariableKind::Center => { vec![ - Static(ExtractStaticStyle::new( - "display".to_string(), - "flex".to_string(), - 0, - None, - )), - Static(ExtractStaticStyle::new( - "justifyContent".to_string(), - "center".to_string(), + Static(ExtractStaticStyle::new_basic("display", "flex", 0, None)), + Static(ExtractStaticStyle::new_basic( + "justifyContent", + "center", 0, None, )), - Static(ExtractStaticStyle::new( - "alignItems".to_string(), - "center".to_string(), + Static(ExtractStaticStyle::new_basic( + "alignItems", + "center", 0, None, )), ] } - ExportVariableKind::Grid => vec![Static(ExtractStaticStyle::new( - "display".to_string(), - "grid".to_string(), - 0, - None, - ))], + ExportVariableKind::Grid => { + vec![Static(ExtractStaticStyle::new_basic( + "display", "grid", 0, None, + ))] + } } } } @@ -182,25 +170,17 @@ mod tests { assert_eq!(ExportVariableKind::Input.extract(), vec![]); assert_eq!( ExportVariableKind::Flex.extract(), - vec![Static(ExtractStaticStyle::new( - "display".to_string(), - "flex".to_string(), - 0, - None, + vec![Static(ExtractStaticStyle::new_basic( + "display", "flex", 0, None, ))] ); assert_eq!( ExportVariableKind::VStack.extract(), vec![ - Static(ExtractStaticStyle::new( - "display".to_string(), - "flex".to_string(), - 0, - None, - )), - Static(ExtractStaticStyle::new( - "flexDirection".to_string(), - "column".to_string(), + Static(ExtractStaticStyle::new_basic("display", "flex", 0, None,)), + Static(ExtractStaticStyle::new_basic( + "flexDirection", + "column", 0, None, )) @@ -209,21 +189,16 @@ mod tests { assert_eq!( ExportVariableKind::Center.extract(), vec![ - Static(ExtractStaticStyle::new( - "display".to_string(), - "flex".to_string(), - 0, - None, - )), - Static(ExtractStaticStyle::new( - "justifyContent".to_string(), - "center".to_string(), + Static(ExtractStaticStyle::new_basic("display", "flex", 0, None,)), + Static(ExtractStaticStyle::new_basic( + "justifyContent", + "center", 0, None, )), - Static(ExtractStaticStyle::new( - "alignItems".to_string(), - "center".to_string(), + Static(ExtractStaticStyle::new_basic( + "alignItems", + "center", 0, None, )) @@ -231,11 +206,8 @@ mod tests { ); assert_eq!( ExportVariableKind::Grid.extract(), - vec![Static(ExtractStaticStyle::new( - "display".to_string(), - "grid".to_string(), - 0, - None, + vec![Static(ExtractStaticStyle::new_basic( + "display", "grid", 0, None, ))] ); } diff --git a/libs/extractor/src/extract_style/mod.rs b/libs/extractor/src/extract_style/mod.rs index cbcf4248..42fd457f 100644 --- a/libs/extractor/src/extract_style/mod.rs +++ b/libs/extractor/src/extract_style/mod.rs @@ -14,6 +14,8 @@ pub struct ExtractStaticStyle { level: u8, /// selector selector: Option, + /// basic, if the value is true then css created by this style will be added to the first + basic: bool, } static MAINTAIN_VALUE_PROPERTIES: Lazy> = Lazy::new(|| { @@ -27,16 +29,31 @@ static MAINTAIN_VALUE_PROPERTIES: Lazy> = Lazy::new(|| { impl ExtractStaticStyle { /// create a new ExtractStaticStyle - pub fn new(property: String, value: String, level: u8, selector: Option) -> Self { + pub fn new(property: &str, value: &str, level: u8, selector: Option<&str>) -> Self { Self { - value: if MAINTAIN_VALUE_PROPERTIES.contains(&property) { - value + value: if MAINTAIN_VALUE_PROPERTIES.contains(property) { + value.to_string() } else { - convert_value(&value) + convert_value(value) }, - property, + property: property.to_string(), level, - selector, + selector: selector.map(|s| s.to_string()), + basic: false, + } + } + + pub fn new_basic(property: &str, value: &str, level: u8, selector: Option<&str>) -> Self { + Self { + value: if MAINTAIN_VALUE_PROPERTIES.contains(property) { + value.to_string() + } else { + convert_value(value) + }, + property: property.to_string(), + level, + selector: selector.map(|s| s.to_string()), + basic: true, } } @@ -55,6 +72,10 @@ impl ExtractStaticStyle { pub fn selector(&self) -> Option<&str> { self.selector.as_deref() } + + pub fn basic(&self) -> bool { + self.basic + } } pub trait ExtractStyleProperty { @@ -103,12 +124,12 @@ pub struct ExtractDynamicStyle { impl ExtractDynamicStyle { /// create a new ExtractDynamicStyle - pub fn new(property: String, level: u8, identifier: String, selector: Option) -> Self { + pub fn new(property: &str, level: u8, identifier: &str, selector: Option<&str>) -> Self { Self { - property, + property: property.to_string(), level, - identifier, - selector, + identifier: identifier.to_string(), + selector: selector.map(|s| s.to_string()), } } diff --git a/libs/extractor/src/lib.rs b/libs/extractor/src/lib.rs index fd205ae4..35181f88 100644 --- a/libs/extractor/src/lib.rs +++ b/libs/extractor/src/lib.rs @@ -2,9 +2,8 @@ mod component; pub mod extract_style; mod gen_class_name; mod gen_style; -mod object_prop_extract_utils; -mod prop_extract_utils; mod prop_modify_utils; +mod style_extractor; mod utils; mod visit; @@ -350,7 +349,7 @@ mod tests { css_file: None } ) - .unwrap(),); + .unwrap()); } #[test] #[serial] @@ -966,4 +965,155 @@ export { ) .unwrap()); } + + #[test] + #[serial] + fn ternary_operator_in_selector() { + reset_class_map(); + assert_debug_snapshot!(extract( + "test.js", + r#"import {Flex} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap()); + + reset_class_map(); + assert_debug_snapshot!(extract( + "test.js", + r#"import {Flex} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap()); + } + + #[test] + #[serial] + fn test_rest_props() { + reset_class_map(); + assert_debug_snapshot!(extract( + "test.js", + r#"import {Flex} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap()); + } + + #[test] + #[serial] + fn props_direct_select() { + reset_class_map(); + assert_debug_snapshot!(extract( + "test.js", + r#"import {Flex} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap()); + assert_debug_snapshot!(extract( + "test.js", + r#"import {Flex} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap()); + assert_debug_snapshot!(extract( + "test.js", + r#"import {Flex} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap()); + + reset_class_map(); + assert_debug_snapshot!(extract( + "test.js", + r#"import {Flex} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap()); + + reset_class_map(); + assert_debug_snapshot!(extract( + "test.js", + r#"import {Flex} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap()); + + reset_class_map(); + assert_debug_snapshot!(extract( + "test.js", + r#"import {Flex} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap()); + + reset_class_map(); + assert_debug_snapshot!(extract( + "test.js", + r#"import {Flex} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap()); + + reset_class_map(); + assert_debug_snapshot!(extract( + "test.js", + r#"import {Flex} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap()); + } } diff --git a/libs/extractor/src/object_prop_extract_utils.rs b/libs/extractor/src/object_prop_extract_utils.rs deleted file mode 100644 index ec05ed50..00000000 --- a/libs/extractor/src/object_prop_extract_utils.rs +++ /dev/null @@ -1,102 +0,0 @@ -use crate::prop_extract_utils::extract_style_prop_from_express; -use crate::utils::is_special_property; -use crate::ExtractStyleProp; -use oxc_ast::ast::{ - ArrayExpressionElement, Expression, JSXAttributeValue, JSXExpression, ObjectExpression, - ObjectPropertyKind, -}; -use oxc_ast::AstBuilder; - -pub fn extract_object_from_jsx_attr<'a>( - ast_builder: &AstBuilder<'a>, - value: &JSXAttributeValue<'a>, - media: Option<&str>, -) -> Option>> { - match value { - JSXAttributeValue::ExpressionContainer(expression) => match &expression.expression { - JSXExpression::ObjectExpression(obj) => { - let mut props = vec![]; - props.append(&mut extract_props_from_object_expression( - ast_builder, - obj, - 0, - media, - )); - Some(props) - } - JSXExpression::ArrayExpression(arr) => { - let mut props = vec![]; - for (idx, e) in arr.elements.iter().enumerate() { - if let ArrayExpressionElement::ObjectExpression(oo) = e { - props.append(&mut extract_props_from_object_expression( - ast_builder, - oo, - idx as u8, - media, - )); - } - } - Some(props) - } - _ => None, - }, - _ => None, - } -} - -pub fn extract_from_style_value<'a>( - ast_builder: &AstBuilder<'a>, - value: &Expression<'a>, - media: Option<&str>, -) -> Option>> { - match value { - Expression::ObjectExpression(obj) => { - let mut props = vec![]; - props.append(&mut extract_props_from_object_expression( - ast_builder, - obj, - 0, - media, - )); - Some(props) - } - Expression::ArrayExpression(arr) => { - let mut props = vec![]; - for (idx, e) in arr.elements.iter().enumerate() { - if let ArrayExpressionElement::ObjectExpression(oo) = e { - props.append(&mut extract_props_from_object_expression( - ast_builder, - oo, - idx as u8, - media, - )); - } - } - Some(props) - } - _ => None, - } -} - -fn extract_props_from_object_expression<'a>( - ast_builder: &AstBuilder<'a>, - obj: &ObjectExpression<'a>, - level: u8, - media: Option<&str>, -) -> Vec> { - let mut props = vec![]; - for p in obj.properties.iter() { - if let ObjectPropertyKind::ObjectProperty(o) = p { - let name = o.key.name().unwrap(); - if is_special_property(&name) { - continue; - } - if let Some(ret) = - extract_style_prop_from_express(ast_builder, &name, &o.value, level, media) - { - props.push(ret); - } - }; - } - props -} diff --git a/libs/extractor/src/prop_extract_utils.rs b/libs/extractor/src/prop_extract_utils.rs deleted file mode 100644 index 52522883..00000000 --- a/libs/extractor/src/prop_extract_utils.rs +++ /dev/null @@ -1,207 +0,0 @@ -use crate::extract_style::{ExtractDynamicStyle, ExtractStaticStyle}; -use crate::ExtractStyleProp; -use crate::ExtractStyleValue::{Dynamic, Static}; -use oxc_allocator::CloneIn; -use oxc_ast::ast::{ - ArrayExpression, ConditionalExpression, Expression, JSXAttributeValue, JSXExpression, -}; -use oxc_ast::AstBuilder; -use oxc_span::SPAN; -use oxc_syntax::operator::{BinaryOperator, LogicalOperator}; - -const IGNORED_IDENTIFIERS: [&str; 3] = ["undefined", "NaN", "Infinity"]; - -/// JSX attribute to style property -pub fn extract_style_prop<'a>( - ast_builder: &AstBuilder<'a>, - name: String, - value: &JSXAttributeValue<'a>, -) -> Option> { - match value { - JSXAttributeValue::StringLiteral(str) => Some(ExtractStyleProp::Static(Static( - ExtractStaticStyle::new(name, str.value.to_string(), 0, None), - ))), - JSXAttributeValue::ExpressionContainer(expression) => { - if let JSXExpression::EmptyExpression(_) = expression.expression { - None - } else { - extract_style_prop_from_express( - ast_builder, - name.as_str(), - expression.expression.to_expression(), - 0, - None, - ) - } - } - _ => None, - } -} -pub fn extract_style_prop_from_express<'a>( - ast_builder: &AstBuilder<'a>, - name: &str, - expression: &Expression<'a>, - level: u8, - selector: Option<&str>, -) -> Option> { - match &expression { - Expression::NumericLiteral(num) => { - Some(ExtractStyleProp::Static(Static(ExtractStaticStyle::new( - name.to_string(), - num.value.to_string(), - level, - selector.map(|s| s.to_string()), - )))) - } - Expression::StringLiteral(str) => { - Some(ExtractStyleProp::Static(Static(ExtractStaticStyle::new( - name.to_string(), - str.value.to_string(), - level, - selector.map(|s| s.to_string()), - )))) - } - Expression::Identifier(identifier) => { - if IGNORED_IDENTIFIERS.contains(&identifier.name.as_str()) { - None - } else { - Some(ExtractStyleProp::Static(Dynamic(ExtractDynamicStyle::new( - name.to_string(), - level, - identifier.name.to_string(), - selector.map(|s| s.to_string()), - )))) - } - } - Expression::LogicalExpression(logical) => match logical.operator { - LogicalOperator::Or => Some(ExtractStyleProp::Conditional { - condition: logical.left.clone_in(ast_builder.allocator), - consequent: None, - alternate: extract_style_prop_from_express( - ast_builder, - name, - &logical.right, - level, - selector, - ) - .map(Box::new), - }), - LogicalOperator::And => Some(ExtractStyleProp::Conditional { - condition: logical.left.clone_in(ast_builder.allocator), - consequent: extract_style_prop_from_express( - ast_builder, - name, - &logical.right, - level, - selector, - ) - .map(Box::new), - alternate: None, - }), - LogicalOperator::Coalesce => Some(ExtractStyleProp::Conditional { - condition: Expression::LogicalExpression(ast_builder.alloc_logical_expression( - SPAN, - Expression::BinaryExpression(ast_builder.alloc_binary_expression( - SPAN, - logical.left.clone_in(ast_builder.allocator), - BinaryOperator::StrictInequality, - Expression::NullLiteral(ast_builder.alloc_null_literal(SPAN)), - )), - LogicalOperator::And, - Expression::BinaryExpression(ast_builder.alloc_binary_expression( - SPAN, - logical.left.clone_in(ast_builder.allocator), - BinaryOperator::StrictInequality, - Expression::Identifier( - ast_builder.alloc_identifier_reference(SPAN, "undefined"), - ), - )), - )), - consequent: None, - alternate: extract_style_prop_from_express( - ast_builder, - name, - &logical.right, - level, - selector, - ) - .map(Box::new), - }), - }, - Expression::ParenthesizedExpression(parenthesized) => extract_style_prop_from_express( - ast_builder, - name, - &parenthesized.expression, - level, - selector, - ), - Expression::ArrayExpression(array) => { - extract_style_prop_from_array_express(ast_builder, name, array, selector) - } - Expression::ConditionalExpression(conditional) => { - extract_style_prop_from_conditional_express( - ast_builder, - name, - conditional, - level, - selector, - ) - } - _ => None, - } -} - -fn extract_style_prop_from_conditional_express<'a>( - ast_builder: &AstBuilder<'a>, - name: &str, - conditional: &ConditionalExpression<'a>, - level: u8, - media: Option<&str>, -) -> Option> { - Some(ExtractStyleProp::Conditional { - condition: conditional.test.clone_in(ast_builder.allocator), - consequent: extract_style_prop_from_express( - ast_builder, - name, - &conditional.consequent, - level, - media, - ) - .map(Box::new), - alternate: extract_style_prop_from_express( - ast_builder, - name, - &conditional.alternate, - level, - media, - ) - .map(Box::new), - }) -} - -fn extract_style_prop_from_array_express<'a>( - ast_builder: &AstBuilder<'a>, - name: &str, - array: &ArrayExpression<'a>, - selector: Option<&str>, -) -> Option> { - let ret = array - .elements - .iter() - .enumerate() - .filter_map(|(idx, element)| { - extract_style_prop_from_express( - ast_builder, - name, - element.to_expression(), - idx as u8, - selector, - ) - }) - .collect::>(); - if ret.is_empty() { - None - } else { - Some(ExtractStyleProp::Responsive(ret)) - } -} diff --git a/libs/extractor/src/prop_modify_utils.rs b/libs/extractor/src/prop_modify_utils.rs index b8733255..dcdf2a5f 100644 --- a/libs/extractor/src/prop_modify_utils.rs +++ b/libs/extractor/src/prop_modify_utils.rs @@ -20,7 +20,8 @@ pub fn modify_prop_object<'a>( let mut style_prop = None; for idx in (0..props.len()).rev() { - if let ObjectPropertyKind::ObjectProperty(attr) = props.remove(idx) { + let prop = props.remove(idx); + if let ObjectPropertyKind::ObjectProperty(attr) = prop { if let PropertyKey::StaticIdentifier(ident) = &attr.key { if ident.name == "className" { class_name_prop = Some(attr); @@ -31,6 +32,8 @@ pub fn modify_prop_object<'a>( } } props.insert(idx, ObjectPropertyKind::ObjectProperty(attr)); + } else { + props.insert(idx, prop); } } @@ -120,7 +123,8 @@ pub fn modify_props<'a>( let mut style_prop = None; for idx in (0..props.len()).rev() { - if let Attribute(attr) = props.remove(idx) { + let prop = props.remove(idx); + if let Attribute(attr) = prop { if let Identifier(ident) = &attr.name { if ident.name == "className" { class_name_prop = Some(attr); @@ -131,6 +135,8 @@ pub fn modify_props<'a>( } } props.insert(idx, Attribute(attr)); + } else { + props.insert(idx, prop); } } diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_class_name_from_component.snap b/libs/extractor/src/snapshots/extractor__tests__extract_class_name_from_component.snap index e443d0a2..f8031c64 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_class_name_from_component.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_class_name_from_component.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "flex", level: 0, selector: None, + basic: true, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "column", level: 0, selector: None, + basic: true, }, ), Static( @@ -26,6 +28,7 @@ ExtractOutput { value: "4px", level: 0, selector: None, + basic: false, }, ), Static( @@ -34,6 +37,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_compound_responsive_style_props.snap b/libs/extractor/src/snapshots/extractor__tests__extract_compound_responsive_style_props.snap index f839704c..169fb00b 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_compound_responsive_style_props.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_compound_responsive_style_props.snap @@ -34,6 +34,7 @@ ExtractOutput { value: "red", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_conditional_style_props-3.snap b/libs/extractor/src/snapshots/extractor__tests__extract_conditional_style_props-3.snap index 7666592d..8a37d51f 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_conditional_style_props-3.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_conditional_style_props-3.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 0, selector: None, + basic: false, }, ), Dynamic( diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_conditional_style_props.snap b/libs/extractor/src/snapshots/extractor__tests__extract_conditional_style_props.snap index 1895de9b..6da0a3d3 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_conditional_style_props.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_conditional_style_props.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 0, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "3px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_logical_case-2.snap b/libs/extractor/src/snapshots/extractor__tests__extract_logical_case-2.snap index 6772ebad..7d9a4b83 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_logical_case-2.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_logical_case-2.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "1px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_logical_case-3.snap b/libs/extractor/src/snapshots/extractor__tests__extract_logical_case-3.snap index 41428a9a..289a369d 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_logical_case-3.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_logical_case-3.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "1px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_logical_case.snap b/libs/extractor/src/snapshots/extractor__tests__extract_logical_case.snap index 56eac602..1df5aad9 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_logical_case.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_logical_case.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "1px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-2.snap b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-2.snap index 83935fb1..43ca35c5 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-2.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-2.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "6px", level: 0, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "4px", level: 1, selector: None, + basic: false, }, ), Static( @@ -26,6 +28,7 @@ ExtractOutput { value: "3px", level: 1, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-3.snap b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-3.snap index 781d6807..b843765e 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-3.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-3.snap @@ -42,6 +42,7 @@ ExtractOutput { value: "2px", level: 3, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-4.snap b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-4.snap index 85b57c3a..a21d1890 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-4.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-4.snap @@ -42,6 +42,7 @@ ExtractOutput { value: "4px", level: 3, selector: None, + basic: false, }, ), Static( @@ -50,6 +51,7 @@ ExtractOutput { value: "2px", level: 3, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-5.snap b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-5.snap index 3f3f1b84..401aa757 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-5.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-5.snap @@ -34,6 +34,7 @@ ExtractOutput { value: "4px", level: 3, selector: None, + basic: false, }, ), Static( @@ -42,6 +43,7 @@ ExtractOutput { value: "2px", level: 3, selector: None, + basic: false, }, ), Dynamic( diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-6.snap b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-6.snap index 5b148599..2de64c89 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-6.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-6.snap @@ -34,6 +34,7 @@ ExtractOutput { value: "4px", level: 3, selector: None, + basic: false, }, ), Static( @@ -42,6 +43,7 @@ ExtractOutput { value: "2px", level: 3, selector: None, + basic: false, }, ), Static( @@ -50,6 +52,7 @@ ExtractOutput { value: "1px", level: 0, selector: None, + basic: false, }, ), Static( @@ -58,6 +61,7 @@ ExtractOutput { value: "2px", level: 1, selector: None, + basic: false, }, ), Static( @@ -66,6 +70,7 @@ ExtractOutput { value: "3px", level: 2, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-7.snap b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-7.snap index 1de9cca6..722b9810 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-7.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-7.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 1, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-8.snap b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-8.snap index 49bfc1f9..0cd148c0 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-8.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props-8.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 1, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "5px", level: 2, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props.snap b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props.snap index aa48960f..119a0b31 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 1, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "3px", level: 1, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props_with_class_name-2.snap b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props_with_class_name-2.snap index d870f3d7..d77c333b 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props_with_class_name-2.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props_with_class_name-2.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 1, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props_with_class_name.snap b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props_with_class_name.snap index 612d6e3c..9ba331f8 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props_with_class_name.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_conditional_style_props_with_class_name.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 1, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "8px", level: 1, selector: None, + basic: false, }, ), Static( @@ -26,6 +28,7 @@ ExtractOutput { value: "3px", level: 1, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_style_props.snap b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_style_props.snap index 3cca84bc..97c36182 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_responsive_style_props.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_responsive_style_props.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 1, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), Static( @@ -26,6 +28,7 @@ ExtractOutput { value: "16px", level: 2, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_selector.snap b/libs/extractor/src/snapshots/extractor__tests__extract_selector.snap index 1638d1ed..fee9aa34 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_selector.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_selector.snap @@ -12,6 +12,7 @@ ExtractOutput { selector: Some( "hover", ), + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_selector_with_responsive-2.snap b/libs/extractor/src/snapshots/extractor__tests__extract_selector_with_responsive-2.snap index fd825f48..fb2bed60 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_selector_with_responsive-2.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_selector_with_responsive-2.snap @@ -7,21 +7,23 @@ ExtractOutput { Static( ExtractStaticStyle { property: "mx", - value: "80px", - level: 1, + value: "40px", + level: 0, selector: Some( "hover", ), + basic: false, }, ), Static( ExtractStaticStyle { property: "mx", - value: "40px", - level: 0, + value: "80px", + level: 1, selector: Some( "hover", ), + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_selector_with_responsive.snap b/libs/extractor/src/snapshots/extractor__tests__extract_selector_with_responsive.snap index 4bd429ac..c6e93bc2 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_selector_with_responsive.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_selector_with_responsive.snap @@ -12,6 +12,7 @@ ExtractOutput { selector: Some( "hover", ), + basic: false, }, ), Static( @@ -22,6 +23,7 @@ ExtractOutput { selector: Some( "hover", ), + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_static_css_with_theme.snap b/libs/extractor/src/snapshots/extractor__tests__extract_static_css_with_theme.snap index d9ea984a..55cd9a6a 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_static_css_with_theme.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_static_css_with_theme.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "$nice", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_style_props-2.snap b/libs/extractor/src/snapshots/extractor__tests__extract_style_props-2.snap index d4d9d0f0..2d5656ca 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_style_props-2.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_style_props-2.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 0, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_style_props-3.snap b/libs/extractor/src/snapshots/extractor__tests__extract_style_props-3.snap index a5e8c1fe..1fd69ec3 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_style_props-3.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_style_props-3.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 0, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_style_props-4.snap b/libs/extractor/src/snapshots/extractor__tests__extract_style_props-4.snap index de636714..6ba24408 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_style_props-4.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_style_props-4.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 0, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_style_props-5.snap b/libs/extractor/src/snapshots/extractor__tests__extract_style_props-5.snap index 16dd3eb6..8d318bb9 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_style_props-5.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_style_props-5.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "flex", level: 0, selector: None, + basic: true, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "4px", level: 0, selector: None, + basic: false, }, ), Static( @@ -26,6 +28,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_style_props.snap b/libs/extractor/src/snapshots/extractor__tests__extract_style_props.snap index 9cdc4db9..a74daa20 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_style_props.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_style_props.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 0, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-2.snap b/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-2.snap index d2ba4b34..bbb7105b 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-2.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-2.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 0, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-3.snap b/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-3.snap index f24e7214..ad178752 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-3.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-3.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 0, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-4.snap b/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-4.snap index 2f703bcc..c79fa2de 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-4.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-4.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 0, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-5.snap b/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-5.snap index 7a32787a..715f9d9c 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-5.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-5.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 0, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-6.snap b/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-6.snap index 2494160d..818be778 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-6.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-6.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "720px", level: 0, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "152px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name.snap b/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name.snap index d1380695..3b3b9fdd 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 0, selector: None, + basic: false, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__ignore_special_props.snap b/libs/extractor/src/snapshots/extractor__tests__ignore_special_props.snap index faa9b467..a8f99bc8 100644 --- a/libs/extractor/src/snapshots/extractor__tests__ignore_special_props.snap +++ b/libs/extractor/src/snapshots/extractor__tests__ignore_special_props.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "4px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__maintain_value.snap b/libs/extractor/src/snapshots/extractor__tests__maintain_value.snap index f723f8bb..ab6f3493 100644 --- a/libs/extractor/src/snapshots/extractor__tests__maintain_value.snap +++ b/libs/extractor/src/snapshots/extractor__tests__maintain_value.snap @@ -10,6 +10,7 @@ ExtractOutput { value: "flex", level: 0, selector: None, + basic: true, }, ), Static( @@ -18,6 +19,7 @@ ExtractOutput { value: "1", level: 0, selector: None, + basic: false, }, ), Static( @@ -26,6 +28,7 @@ ExtractOutput { value: "2", level: 0, selector: None, + basic: false, }, ), Static( @@ -34,6 +37,7 @@ ExtractOutput { value: "900", level: 0, selector: None, + basic: false, }, ), Static( @@ -42,6 +46,7 @@ ExtractOutput { value: "2", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__props_direct_select-2.snap b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-2.snap new file mode 100644 index 00000000..9dace631 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-2.snap @@ -0,0 +1,18 @@ +--- +source: libs/extractor/src/lib.rs +expression: "extract(\"test.js\",\nr#\"import {Flex} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap()" +--- +ExtractOutput { + styles: [ + Static( + ExtractStaticStyle { + property: "display", + value: "flex", + level: 0, + selector: None, + basic: true, + }, + ), + ], + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__props_direct_select-3.snap b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-3.snap new file mode 100644 index 00000000..1d157256 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-3.snap @@ -0,0 +1,27 @@ +--- +source: libs/extractor/src/lib.rs +expression: "extract(\"test.js\",\nr#\"import {Flex} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap()" +--- +ExtractOutput { + styles: [ + Static( + ExtractStaticStyle { + property: "display", + value: "flex", + level: 0, + selector: None, + basic: true, + }, + ), + Static( + ExtractStaticStyle { + property: "opacity", + value: "1", + level: 0, + selector: None, + basic: false, + }, + ), + ], + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__props_direct_select-4.snap b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-4.snap new file mode 100644 index 00000000..596ca9a4 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-4.snap @@ -0,0 +1,26 @@ +--- +source: libs/extractor/src/lib.rs +expression: "extract(\"test.js\",\nr#\"import {Flex} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap()" +--- +ExtractOutput { + styles: [ + Static( + ExtractStaticStyle { + property: "display", + value: "flex", + level: 0, + selector: None, + basic: true, + }, + ), + Dynamic( + ExtractDynamicStyle { + property: "opacity", + level: 0, + identifier: "[1, .5][a]", + selector: None, + }, + ), + ], + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__props_direct_select-5.snap b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-5.snap new file mode 100644 index 00000000..9de962c5 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-5.snap @@ -0,0 +1,27 @@ +--- +source: libs/extractor/src/lib.rs +expression: "extract(\"test.js\",\nr#\"import {Flex} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap()" +--- +ExtractOutput { + styles: [ + Static( + ExtractStaticStyle { + property: "display", + value: "flex", + level: 0, + selector: None, + basic: true, + }, + ), + Static( + ExtractStaticStyle { + property: "opacity", + value: "1", + level: 0, + selector: None, + basic: false, + }, + ), + ], + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__props_direct_select-6.snap b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-6.snap new file mode 100644 index 00000000..898d5585 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-6.snap @@ -0,0 +1,18 @@ +--- +source: libs/extractor/src/lib.rs +expression: "extract(\"test.js\",\nr#\"import {Flex} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap()" +--- +ExtractOutput { + styles: [ + Static( + ExtractStaticStyle { + property: "display", + value: "flex", + level: 0, + selector: None, + basic: true, + }, + ), + ], + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__props_direct_select-7.snap b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-7.snap new file mode 100644 index 00000000..bc706aff --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-7.snap @@ -0,0 +1,26 @@ +--- +source: libs/extractor/src/lib.rs +expression: "extract(\"test.js\",\nr#\"import {Flex} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap()" +--- +ExtractOutput { + styles: [ + Static( + ExtractStaticStyle { + property: "display", + value: "flex", + level: 0, + selector: None, + basic: true, + }, + ), + Dynamic( + ExtractDynamicStyle { + property: "opacity", + level: 0, + identifier: "({\n\ta: 1,\n\tb: .5\n})[a]", + selector: None, + }, + ), + ], + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__props_direct_select-8.snap b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-8.snap new file mode 100644 index 00000000..a12961b8 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-8.snap @@ -0,0 +1,26 @@ +--- +source: libs/extractor/src/lib.rs +expression: "extract(\"test.js\",\nr#\"import {Flex} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap()" +--- +ExtractOutput { + styles: [ + Static( + ExtractStaticStyle { + property: "display", + value: "flex", + level: 0, + selector: None, + basic: true, + }, + ), + Dynamic( + ExtractDynamicStyle { + property: "opacity", + level: 0, + identifier: "({\n\ta: 1,\n\tb: .5,\n\t...any\n})[\"some\"]", + selector: None, + }, + ), + ], + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__props_direct_select.snap b/libs/extractor/src/snapshots/extractor__tests__props_direct_select.snap new file mode 100644 index 00000000..adfc95fa --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__props_direct_select.snap @@ -0,0 +1,18 @@ +--- +source: libs/extractor/src/lib.rs +expression: "extract(\"test.js\",\nr#\"import {Flex} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap()" +--- +ExtractOutput { + styles: [ + Static( + ExtractStaticStyle { + property: "display", + value: "flex", + level: 0, + selector: None, + basic: true, + }, + ), + ], + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__rest_props.snap b/libs/extractor/src/snapshots/extractor__tests__rest_props.snap new file mode 100644 index 00000000..291f56f1 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__rest_props.snap @@ -0,0 +1,27 @@ +--- +source: libs/extractor/src/lib.rs +expression: "extract(\"test.js\",\nr#\"import {Flex} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap()" +--- +ExtractOutput { + styles: [ + Static( + ExtractStaticStyle { + property: "display", + value: "flex", + level: 0, + selector: None, + basic: true, + }, + ), + Static( + ExtractStaticStyle { + property: "opacity", + value: "0.5", + level: 0, + selector: None, + basic: false, + }, + ), + ], + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-2.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-2.snap index e51539f5..860207da 100644 --- a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-2.snap +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-2.snap @@ -12,6 +12,7 @@ ExtractOutput { selector: Some( "hover", ), + basic: false, }, ), Static( @@ -20,6 +21,7 @@ ExtractOutput { value: "$text", level: 0, selector: None, + basic: false, }, ), Static( @@ -28,6 +30,7 @@ ExtractOutput { value: "red", level: 0, selector: None, + basic: false, }, ), Typography( @@ -39,6 +42,7 @@ ExtractOutput { value: "flex", level: 0, selector: None, + basic: true, }, ), Static( @@ -47,6 +51,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-3.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-3.snap index e16c736a..ca01a1ac 100644 --- a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-3.snap +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-3.snap @@ -12,6 +12,7 @@ ExtractOutput { selector: Some( "hover", ), + basic: false, }, ), Static( @@ -20,6 +21,7 @@ ExtractOutput { value: "$text", level: 0, selector: None, + basic: false, }, ), Static( @@ -28,6 +30,7 @@ ExtractOutput { value: "red", level: 0, selector: None, + basic: false, }, ), Typography( @@ -39,6 +42,7 @@ ExtractOutput { value: "flex", level: 0, selector: None, + basic: true, }, ), Static( @@ -47,6 +51,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs.snap index 1bc68428..24ef10c1 100644 --- a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs.snap +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs.snap @@ -12,6 +12,7 @@ ExtractOutput { selector: Some( "hover", ), + basic: false, }, ), Static( @@ -20,6 +21,7 @@ ExtractOutput { value: "$text", level: 0, selector: None, + basic: false, }, ), Static( @@ -28,6 +30,7 @@ ExtractOutput { value: "red", level: 0, selector: None, + basic: false, }, ), Typography( @@ -39,6 +42,7 @@ ExtractOutput { value: "flex", level: 0, selector: None, + basic: true, }, ), Static( @@ -47,6 +51,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-2.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-2.snap index b499ae7e..fe0d4cce 100644 --- a/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-2.snap +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-2.snap @@ -12,6 +12,7 @@ ExtractOutput { selector: Some( "hover", ), + basic: false, }, ), Static( @@ -20,6 +21,7 @@ ExtractOutput { value: "$text", level: 0, selector: None, + basic: false, }, ), Static( @@ -28,6 +30,7 @@ ExtractOutput { value: "red", level: 0, selector: None, + basic: false, }, ), Typography( @@ -39,6 +42,7 @@ ExtractOutput { value: "flex", level: 0, selector: None, + basic: true, }, ), Static( @@ -47,6 +51,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs.snap index ffb20886..f1333282 100644 --- a/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs.snap +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs.snap @@ -12,6 +12,7 @@ ExtractOutput { selector: Some( "hover", ), + basic: false, }, ), Static( @@ -20,6 +21,7 @@ ExtractOutput { value: "$text", level: 0, selector: None, + basic: false, }, ), Static( @@ -28,6 +30,7 @@ ExtractOutput { value: "red", level: 0, selector: None, + basic: false, }, ), Typography( @@ -39,6 +42,7 @@ ExtractOutput { value: "flex", level: 0, selector: None, + basic: true, }, ), Static( @@ -47,6 +51,7 @@ ExtractOutput { value: "8px", level: 0, selector: None, + basic: false, }, ), ], diff --git a/libs/extractor/src/snapshots/extractor__tests__ternary_operator_in_selector-2.snap b/libs/extractor/src/snapshots/extractor__tests__ternary_operator_in_selector-2.snap new file mode 100644 index 00000000..52826f22 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__ternary_operator_in_selector-2.snap @@ -0,0 +1,29 @@ +--- +source: libs/extractor/src/lib.rs +expression: "extract(\"test.js\",\nr#\"import {Flex} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap()" +--- +ExtractOutput { + styles: [ + Static( + ExtractStaticStyle { + property: "display", + value: "flex", + level: 0, + selector: None, + basic: true, + }, + ), + Static( + ExtractStaticStyle { + property: "bg", + value: "red", + level: 0, + selector: Some( + "hover", + ), + basic: false, + }, + ), + ], + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__ternary_operator_in_selector.snap b/libs/extractor/src/snapshots/extractor__tests__ternary_operator_in_selector.snap new file mode 100644 index 00000000..9ceb9297 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__ternary_operator_in_selector.snap @@ -0,0 +1,29 @@ +--- +source: libs/extractor/src/lib.rs +expression: "extract(\"test.js\",\nr#\"import {Flex} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap()" +--- +ExtractOutput { + styles: [ + Static( + ExtractStaticStyle { + property: "display", + value: "flex", + level: 0, + selector: None, + basic: true, + }, + ), + Static( + ExtractStaticStyle { + property: "bg", + value: "red", + level: 0, + selector: Some( + "hover", + ), + basic: false, + }, + ), + ], + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/style_extractor.rs b/libs/extractor/src/style_extractor.rs new file mode 100644 index 00000000..072a04af --- /dev/null +++ b/libs/extractor/src/style_extractor.rs @@ -0,0 +1,418 @@ +use crate::utils::is_special_property; +use crate::ExtractStyleProp; +use oxc_allocator::CloneIn; +use oxc_ast::ast::{Expression, JSXAttributeValue, ObjectPropertyKind, PropertyKey, Statement}; + +use crate::extract_style::ExtractStyleValue::{Dynamic, Static}; +use crate::extract_style::{ExtractDynamicStyle, ExtractStaticStyle, ExtractStyleValue}; +use oxc_ast::AstBuilder; +use oxc_codegen::Codegen; +use oxc_parser::Parser; +use oxc_span::{SourceType, SPAN}; +use oxc_syntax::operator::{BinaryOperator, LogicalOperator}; + +const IGNORED_IDENTIFIERS: [&str; 3] = ["undefined", "NaN", "Infinity"]; + +/** + * type + * 1. jsx -> + * 2. object -> createElement('div', {a: 1}) + * 3. object with select -> createElement('div', {a: 1}) + */ + +#[derive(Debug)] +pub enum ExtractResult<'a> { + // attribute will be maintained + Maintain, + // attribute will be removed + Remove, + // attribute will be removed and the value will be extracted + ExtractStyle(Vec>), + // attribute will be removed and the tag will be changed + ChangeTag(String), +} + +impl<'a> From> for Vec> { + fn from(v: ExtractResult<'a>) -> Self { + vec![v] + } +} + +pub fn extract_style_from_jsx_attr<'a>( + ast_builder: &AstBuilder<'a>, + name: &str, + value: &mut JSXAttributeValue<'a>, + selector: Option<&str>, +) -> ExtractResult<'a> { + match value { + JSXAttributeValue::ExpressionContainer(ref mut expression) => { + if expression.expression.is_expression() { + extract_style_from_expression( + ast_builder, + Some(name), + expression.expression.to_expression_mut(), + 0, + selector, + ) + } else { + ExtractResult::Maintain + } + } + JSXAttributeValue::StringLiteral(literal) => extract_style_from_expression( + ast_builder, + Some(name), + &mut Expression::StringLiteral(literal.clone_in(ast_builder.allocator)), + 0, + selector, + ), + _ => ExtractResult::Maintain, + } +} + +pub fn extract_style_from_expression<'a>( + ast_builder: &AstBuilder<'a>, + name: Option<&str>, + expression: &mut Expression<'a>, + level: u8, + selector: Option<&str>, +) -> ExtractResult<'a> { + if let Some(name) = name { + if is_special_property(name) { + return ExtractResult::Maintain; + } + if name == "typography" { + if let Expression::StringLiteral(ident) = &expression { + return ExtractResult::ExtractStyle(vec![ExtractStyleProp::Static( + ExtractStyleValue::Typography(ident.value.to_string()), + )]); + } + return ExtractResult::Remove; + } + + if name == "as" { + if let Expression::StringLiteral(ident) = &expression { + return ExtractResult::ChangeTag(ident.value.to_string()); + } + return ExtractResult::Remove; + } + + if let Some(selector) = name.strip_prefix("_") { + return extract_style_from_expression( + ast_builder, + None, + expression, + level, + Some(selector), + ); + } + } + println!("expression: {:?}", expression); + match expression { + Expression::ComputedMemberExpression(mem) => match &mem.object { + Expression::ArrayExpression(array) => { + match &mem.expression { + Expression::NumericLiteral(v) => { + if array.elements.len() < v.value as usize { + // wrong indexing case + ExtractResult::Remove + } else { + extract_style_from_expression( + ast_builder, + name, + array.elements[v.value as usize] + .clone_in(ast_builder.allocator) + .to_expression_mut(), + level, + selector, + ) + } + } + // wrong indexing case + Expression::UnaryExpression(unary) => { + if let Expression::NumericLiteral(_) = &unary.argument { + ExtractResult::Remove + } else { + ExtractResult::Maintain + } + } + Expression::Identifier(_) => { + if let Some(name) = name { + let source = ""; + let mut parsed = + Parser::new(ast_builder.allocator, source, SourceType::d_ts()) + .parse(); + parsed.program.body.insert( + 0, + Statement::ExpressionStatement( + ast_builder.alloc_expression_statement( + SPAN, + expression.clone_in(ast_builder.allocator), + ), + ), + ); + let code = Codegen::new().build(&parsed.program).code; + return ExtractResult::ExtractStyle(vec![ExtractStyleProp::Static( + Dynamic(ExtractDynamicStyle::new( + name, + level, + code[0..code.len() - 2].to_string().as_str(), + selector, + )), + )]); + } + ExtractResult::Maintain + } + _ => ExtractResult::Maintain, + } + } + Expression::ObjectExpression(obj) => match &mem.expression { + Expression::StringLiteral(str) => { + let key = str.value.as_str(); + for p in obj.properties.iter() { + match p { + ObjectPropertyKind::ObjectProperty(o) => { + if let PropertyKey::StaticIdentifier(ident) = &o.key { + if ident.name == key { + return extract_style_from_expression( + ast_builder, + name, + &mut o.value.clone_in(ast_builder.allocator), + level, + selector, + ); + } + } + } + ObjectPropertyKind::SpreadProperty(_) => { + if let Some(name) = name { + let source = ""; + let mut parsed = Parser::new( + ast_builder.allocator, + source, + SourceType::d_ts(), + ) + .parse(); + parsed.program.body.insert( + 0, + Statement::ExpressionStatement( + ast_builder.alloc_expression_statement( + SPAN, + expression.clone_in(ast_builder.allocator), + ), + ), + ); + let code = Codegen::new().build(&parsed.program).code; + return ExtractResult::ExtractStyle(vec![ + ExtractStyleProp::Static(Dynamic( + ExtractDynamicStyle::new( + name, + level, + code[0..code.len() - 2].to_string().as_str(), + selector, + ), + )), + ]); + } + } + } + } + ExtractResult::Remove + } + Expression::Identifier(_) => { + if let Some(name) = name { + let source = ""; + let mut parsed = + Parser::new(ast_builder.allocator, source, SourceType::d_ts()).parse(); + parsed.program.body.insert( + 0, + Statement::ExpressionStatement(ast_builder.alloc_expression_statement( + SPAN, + expression.clone_in(ast_builder.allocator), + )), + ); + let code = Codegen::new().build(&parsed.program).code; + return ExtractResult::ExtractStyle(vec![ExtractStyleProp::Static( + Dynamic(ExtractDynamicStyle::new( + name, + level, + code[0..code.len() - 2].to_string().as_str(), + selector, + )), + )]); + } + ExtractResult::Maintain + } + _ => ExtractResult::Maintain, + }, + _ => ExtractResult::Maintain, + }, + Expression::NumericLiteral(v) => { + if let Some(name) = name { + ExtractResult::ExtractStyle(vec![ExtractStyleProp::Static(Static( + ExtractStaticStyle::new(name, &v.value.to_string(), level, selector), + ))]) + } else { + ExtractResult::Maintain + } + } + Expression::StringLiteral(v) => { + if let Some(name) = name { + ExtractResult::ExtractStyle(vec![ExtractStyleProp::Static(Static( + ExtractStaticStyle::new(name, v.value.as_str(), level, selector), + ))]) + } else { + ExtractResult::Maintain + } + } + Expression::Identifier(identifier) => { + if IGNORED_IDENTIFIERS.contains(&identifier.name.as_str()) { + ExtractResult::Maintain + } else if let Some(name) = name { + ExtractResult::ExtractStyle(vec![ExtractStyleProp::Static(Dynamic( + ExtractDynamicStyle::new(name, level, identifier.name.as_str(), selector), + ))]) + } else { + ExtractResult::Maintain + } + } + Expression::LogicalExpression(logical) => { + let res = name.and_then(|name| { + match extract_style_from_expression( + ast_builder, + Some(name), + &mut logical.right, + level, + selector, + ) { + ExtractResult::ExtractStyle(mut styles) => Some(Box::new(styles.remove(0))), + _ => None, + } + }); + match logical.operator { + LogicalOperator::Or => { + ExtractResult::ExtractStyle(vec![ExtractStyleProp::Conditional { + condition: logical.left.clone_in(ast_builder.allocator), + consequent: None, + alternate: res, + }]) + } + + LogicalOperator::And => { + ExtractResult::ExtractStyle(vec![ExtractStyleProp::Conditional { + condition: logical.left.clone_in(ast_builder.allocator), + consequent: res, + alternate: None, + }]) + } + LogicalOperator::Coalesce => { + ExtractResult::ExtractStyle(vec![ExtractStyleProp::Conditional { + condition: Expression::LogicalExpression( + ast_builder.alloc_logical_expression( + SPAN, + Expression::BinaryExpression(ast_builder.alloc_binary_expression( + SPAN, + logical.left.clone_in(ast_builder.allocator), + BinaryOperator::StrictInequality, + Expression::NullLiteral(ast_builder.alloc_null_literal(SPAN)), + )), + LogicalOperator::And, + Expression::BinaryExpression(ast_builder.alloc_binary_expression( + SPAN, + logical.left.clone_in(ast_builder.allocator), + BinaryOperator::StrictInequality, + Expression::Identifier( + ast_builder.alloc_identifier_reference(SPAN, "undefined"), + ), + )), + ), + ), + consequent: None, + alternate: res, + }]) + } + } + } + Expression::ParenthesizedExpression(parenthesized) => extract_style_from_expression( + ast_builder, + name, + &mut parenthesized.expression, + level, + selector, + ), + Expression::ArrayExpression(array) => { + let mut props = vec![]; + + for (idx, element) in array.elements.iter_mut().enumerate() { + let a = extract_style_from_expression( + ast_builder, + name, + element.to_expression_mut(), + idx as u8, + selector, + ); + + if let ExtractResult::ExtractStyle(mut styles) = a { + props.append(&mut styles); + } + } + + if props.is_empty() { + ExtractResult::Maintain + } else { + ExtractResult::ExtractStyle(props) + } + } + Expression::ConditionalExpression(ref mut conditional) => { + ExtractResult::ExtractStyle(vec![ExtractStyleProp::Conditional { + condition: conditional.test.clone_in(ast_builder.allocator), + consequent: if let ExtractResult::ExtractStyle(styles) = + extract_style_from_expression( + ast_builder, + name, + &mut conditional.consequent, + level, + selector, + ) { + Some(Box::new(ExtractStyleProp::Responsive(styles))) + } else { + None + }, + alternate: if let ExtractResult::ExtractStyle(styles) = + extract_style_from_expression( + ast_builder, + name, + &mut conditional.alternate, + level, + selector, + ) { + Some(Box::new(ExtractStyleProp::Responsive(styles))) + } else { + None + }, + }]) + } + Expression::ObjectExpression(obj) => { + let mut props = vec![]; + for p in obj.properties.iter_mut() { + if let ObjectPropertyKind::ObjectProperty(ref mut o) = p { + let name = o.key.name().unwrap(); + if let ExtractResult::ExtractStyle(ref mut ret) = extract_style_from_expression( + ast_builder, + Some(&name), + &mut o.value, + level, + selector, + ) { + props.append(ret); + } + }; + } + if props.is_empty() { + ExtractResult::Remove + } else { + ExtractResult::ExtractStyle(props) + } + } + _ => ExtractResult::Maintain, + } +} diff --git a/libs/extractor/src/visit.rs b/libs/extractor/src/visit.rs index 13d57320..7684d048 100644 --- a/libs/extractor/src/visit.rs +++ b/libs/extractor/src/visit.rs @@ -1,9 +1,9 @@ use crate::component::ExportVariableKind; use crate::extract_style::ExtractCss; -use crate::object_prop_extract_utils::{extract_from_style_value, extract_object_from_jsx_attr}; -use crate::prop_extract_utils::{extract_style_prop, extract_style_prop_from_express}; use crate::prop_modify_utils::{modify_prop_object, modify_props}; -use crate::utils::is_special_property; +use crate::style_extractor::{ + extract_style_from_expression, extract_style_from_jsx_attr, ExtractResult, +}; use crate::{ExtractStyleProp, ExtractStyleValue, StyleProperty}; use oxc_allocator::{Allocator, CloneIn}; use oxc_ast::ast::ImportDeclarationSpecifier::ImportSpecifier; @@ -11,8 +11,8 @@ use oxc_ast::ast::JSXAttributeItem::Attribute; use oxc_ast::ast::JSXAttributeName::Identifier; use oxc_ast::ast::{ Argument, BindingPatternKind, CallExpression, Expression, ImportDeclaration, - ImportOrExportKind, JSXAttributeValue, JSXElement, JSXElementName, Program, Statement, - TaggedTemplateExpression, TemplateElementValue, VariableDeclarator, WithClause, + ImportOrExportKind, JSXElement, JSXElementName, ObjectPropertyKind, Program, PropertyKey, + Statement, TaggedTemplateExpression, TemplateElementValue, VariableDeclarator, WithClause, }; use oxc_ast::visit::walk_mut::{ walk_call_expression, walk_import_declaration, walk_jsx_element, walk_program, @@ -114,95 +114,66 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { None }; if let Some(kind) = element_kind { - let mut tag = kind.to_tag().unwrap_or("div"); if it.arguments.len() > 1 { - if let Argument::ObjectExpression(ref mut object) = &mut it.arguments[1] { - let mut collected_props_styles = vec![]; - for i in (0..object.properties.len()).rev() { - if let oxc_ast::ast::ObjectPropertyKind::ObjectProperty(prop) = - &object.properties[i] - { - if let oxc_ast::ast::PropertyKey::StaticIdentifier(ident) = - &prop.key - { + if let Expression::ObjectExpression(obj) = + it.arguments[1].to_expression_mut() + { + let mut tag = kind.to_tag().unwrap_or("div").to_string(); + let mut props_styles = vec![]; + for idx in (0..obj.properties.len()).rev() { + let mut prop = obj.properties.remove(idx); + let mut rm = false; + if let ObjectPropertyKind::ObjectProperty(prop) = &mut prop { + if let PropertyKey::StaticIdentifier(ident) = &prop.key { let name = ident.name.to_string(); - // ignore special attributes - if is_special_property(&name) { - continue; - } - if name == "typography" { - if let Expression::StringLiteral(ident) = &prop.value { - collected_props_styles.push( - ExtractStyleProp::Static( - ExtractStyleValue::Typography( - ident.value.to_string(), - ), - ), - ); - } - object.properties.remove(i); - continue; - } - if name == "as" { - if let Expression::StringLiteral(ident) = &prop.value { - tag = ident.value.as_str(); - } - object.properties.remove(i); - continue; - } - if name.starts_with("_") { - let media = name.trim_start_matches('_'); - if let Some(props_styles) = extract_from_style_value( - &self.ast, - &prop.value, - Some(media), - ) { - for style in props_styles.into_iter().rev() { - collected_props_styles.push(style); - } - object.properties.remove(i); + rm = match extract_style_from_expression( + &self.ast, + Some(&name), + &mut prop.value, + 0, + None, + ) { + ExtractResult::Maintain => false, + ExtractResult::Remove => true, + ExtractResult::ExtractStyle(mut styles) => { + styles.reverse(); + props_styles.append(&mut styles); + true } - } else { - let prop_styles = extract_style_prop_from_express( - &self.ast, - &name, - &prop.value, - 0, - None, - ); - if let Some(prop_styles) = prop_styles { - collected_props_styles.push(prop_styles); - object.properties.remove(i); + ExtractResult::ChangeTag(t) => { + tag = t; + true } } } } + if !rm { + obj.properties.insert(idx, prop); + } } + for ex in kind.extract().into_iter().rev() { - collected_props_styles.push(ExtractStyleProp::Static(ex)); + props_styles.push(ExtractStyleProp::Static(ex)); } - for ex in collected_props_styles.iter().rev() { - self.styles.append(&mut ex.extract()); + + for style in props_styles.iter().rev() { + self.styles.append(&mut style.extract()); } - modify_prop_object( - &self.ast, - &mut object.properties, - collected_props_styles, - ); + modify_prop_object(&self.ast, &mut obj.properties, props_styles); + it.arguments[0] = + Argument::StringLiteral(self.ast.alloc_string_literal( + SPAN, + self.ast.atom(tag.as_str()), + None, + )); } } - - it.arguments[0] = Argument::StringLiteral(self.ast.alloc_string_literal( - SPAN, - self.ast.atom(tag), - None, - )); } } - } - walk_call_expression(self, it); + walk_call_expression(self, it); + } } fn visit_tagged_template_expression(&mut self, it: &mut TaggedTemplateExpression<'a>) { if let Expression::Identifier(ident) = &it.tag { @@ -247,58 +218,36 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { let component_name = &opening_element.name.to_string(); if let Some(kind) = self.imports.get(component_name) { let attrs = &mut opening_element.attributes; - let mut tag_name = kind.to_tag().unwrap_or("div"); + let mut tag_name = kind.to_tag().unwrap_or("div").to_string(); let mut props_styles = vec![]; // extract ExtractStyleProp and remain style and class name, just extract for i in (0..attrs.len()).rev() { - let attr = &attrs[i]; - if let Attribute(attr) = attr { + let mut attr = attrs.remove(i); + let mut rm = false; + if let Attribute(ref mut attr) = &mut attr { if let Identifier(name) = &attr.name { let name = name.to_string(); - - // ignore special attributes - if is_special_property(&name) { - continue; - } - if name == "typography" { - if let Some(JSXAttributeValue::StringLiteral(ident)) = &attr.value { - props_styles.push(ExtractStyleProp::Static( - ExtractStyleValue::Typography(ident.value.to_string()), - )); - } - attrs.remove(i); - continue; - } - if name == "as" { - if let Some(JSXAttributeValue::StringLiteral(ident)) = &attr.value { - tag_name = ident.value.as_str() - } - attrs.remove(i); - continue; - } - - if let Some(value) = &attr.value { - // media query - if name.starts_with("_") { - if let Some(prop_styles) = &mut extract_object_from_jsx_attr( - &self.ast, - value, - Some(name.trim_start_matches('_')), - ) { - props_styles.append(prop_styles); - attrs.remove(i); + if let Some(at) = &mut attr.value { + rm = match extract_style_from_jsx_attr(&self.ast, &name, at, None) { + ExtractResult::Maintain => false, + ExtractResult::Remove => true, + ExtractResult::ExtractStyle(mut styles) => { + styles.reverse(); + props_styles.append(&mut styles); + true + } + ExtractResult::ChangeTag(tag) => { + tag_name = tag; + true } - continue; - } - let prop_styles = extract_style_prop(&self.ast, name, value); - if let Some(prop_styles) = prop_styles { - props_styles.push(prop_styles); - attrs.remove(i); } } } } + if !rm { + attrs.insert(i, attr); + } } for ex in kind.extract().into_iter().rev() { @@ -330,9 +279,7 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { self.jsx_object = Some(ident.name.to_string()); } else if let BindingPatternKind::ObjectPattern(object) = &it.id.kind { for prop in &object.properties { - if let oxc_ast::ast::PropertyKey::StaticIdentifier(ident) = - &prop.key - { + if let PropertyKey::StaticIdentifier(ident) = &prop.key { if let Some(k) = prop .value .get_binding_identifier() @@ -348,9 +295,7 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { self.import_object = Some(ident.name.to_string()); } else if let BindingPatternKind::ObjectPattern(object) = &it.id.kind { for prop in &object.properties { - if let oxc_ast::ast::PropertyKey::StaticIdentifier(ident) = - &prop.key - { + if let PropertyKey::StaticIdentifier(ident) = &prop.key { if let Ok(kind) = ExportVariableKind::try_from( prop.value .get_binding_identifier() diff --git a/libs/sheet/Cargo.toml b/libs/sheet/Cargo.toml index e3634adc..f0673f57 100644 --- a/libs/sheet/Cargo.toml +++ b/libs/sheet/Cargo.toml @@ -6,3 +6,5 @@ edition = "2021" [dependencies] css = { path = "../css" } +[dev-dependencies] +insta = "1.42.0" diff --git a/libs/sheet/src/lib.rs b/libs/sheet/src/lib.rs index 2ef6d57e..b41f8a88 100644 --- a/libs/sheet/src/lib.rs +++ b/libs/sheet/src/lib.rs @@ -2,6 +2,7 @@ pub mod theme; use crate::theme::Theme; use css::{convert_property, to_kebab_case, PropertyType}; +use std::cmp::Ordering::{Greater, Less}; use std::collections::{BTreeMap, HashSet}; trait ExtractStyle { @@ -14,6 +15,7 @@ pub struct StyleSheetProperty { pub property: String, pub value: String, pub selector: Option, + pub basic: bool, } impl ExtractStyle for StyleSheetProperty { @@ -98,12 +100,14 @@ impl StyleSheet { level: u8, value: &str, selector: Option<&str>, + basic: bool, ) -> bool { let prop = StyleSheetProperty { class_name: class_name.to_string(), property: property.to_string(), value: value.to_string(), selector: selector.map(|s| s.to_string()), + basic, }; self.properties.entry(level).or_default().insert(prop) } @@ -123,11 +127,20 @@ impl StyleSheet { pub fn create_css(&self) -> String { let mut css = self.theme_declaration.clone(); for (level, props) in self.properties.iter() { - // If has a selector property, move it to the back - let (mut select_props, other_props): (Vec<_>, Vec<_>) = - props.iter().partition(|prop| prop.selector.is_some()); - let mut sorted_props = other_props; - sorted_props.append(&mut select_props); + let mut sorted_props = props.iter().collect::>(); + sorted_props.sort_by(|a, b| { + if a.basic == b.basic { + if a.selector.is_some() && b.selector.is_none() { + return Greater; + } + if a.selector.is_none() && b.selector.is_some() { + return Less; + } + a.property.cmp(&b.property) + } else { + b.basic.cmp(&a.basic) + } + }); let inner_css = sorted_props .into_iter() @@ -168,6 +181,7 @@ impl StyleSheet { #[cfg(test)] mod tests { use super::*; + use insta::assert_debug_snapshot; #[test] fn test_convert_theme_variable_value() { @@ -177,4 +191,89 @@ mod tests { "var(--var)" ); } + + #[test] + fn test_create_css_sort_test() { + let mut sheet = StyleSheet::default(); + sheet.add_property("test", "background-color", 1, "red", None, false); + sheet.add_property("test", "background", 1, "some", None, false); + sheet.set_theme(Theme::default()); + assert_debug_snapshot!(sheet.create_css()); + + let mut sheet = StyleSheet::default(); + sheet.add_property("test", "border", 0, "1px solid", None, false); + sheet.add_property("test", "border-color", 0, "red", None, false); + sheet.set_theme(Theme::default()); + assert_debug_snapshot!(sheet.create_css()); + } + #[test] + fn test_create_css_with_selector_sort_test() { + let mut sheet = StyleSheet::new(); + sheet.add_property("test", "background-color", 1, "red", Some("hover"), false); + sheet.add_property("test", "background-color", 1, "some", None, false); + sheet.set_theme(Theme::new()); + assert_debug_snapshot!(sheet.create_css()); + + let mut sheet = StyleSheet::new(); + sheet.add_property("test", "background-color", 1, "red", None, false); + sheet.add_property("test", "background-color", 1, "some", Some("hover"), false); + sheet.set_theme(Theme::new()); + assert_debug_snapshot!(sheet.create_css()); + + let mut sheet = StyleSheet::new(); + sheet.add_property("test", "background-color", 1, "red", None, false); + sheet.add_property("test", "background", 1, "some", None, false); + sheet.set_theme(Theme::new()); + assert_debug_snapshot!(sheet.create_css()); + } + #[test] + fn test_create_css_with_basic_sort_test() { + let mut sheet = StyleSheet::new(); + sheet.add_property("test", "background-color", 1, "red", None, true); + sheet.add_property("test", "background", 1, "some", None, false); + sheet.set_theme(Theme::new()); + assert_debug_snapshot!(sheet.create_css()); + + let mut sheet = StyleSheet::new(); + sheet.add_property("test", "border", 0, "1px solid", None, false); + sheet.add_property("test", "border-color", 0, "red", None, true); + sheet.set_theme(Theme::new()); + assert_debug_snapshot!(sheet.create_css()); + + let mut sheet = StyleSheet::new(); + sheet.add_property("test", "display", 0, "flex", None, true); + sheet.add_property("test", "display", 0, "block", None, false); + sheet.set_theme(Theme::new()); + assert_debug_snapshot!(sheet.create_css()); + } + + #[test] + fn test_create_css_with_selector_and_basic_sort_test() { + let mut sheet = StyleSheet::new(); + sheet.add_property("test", "background-color", 1, "red", Some("hover"), false); + sheet.add_property("test", "background-color", 1, "some", None, true); + sheet.set_theme(Theme::new()); + assert_debug_snapshot!(sheet.create_css()); + } + + #[test] + fn test_create_css() { + let mut sheet = StyleSheet::new(); + sheet.add_property("test", "mx", 1, "40px", None, false); + sheet.set_theme(Theme::new()); + assert_debug_snapshot!(sheet.create_css()); + + let mut sheet = StyleSheet::new(); + sheet.add_css("test".to_string(), "display:flex;".to_string()); + sheet.set_theme(Theme::new()); + assert_debug_snapshot!(sheet.create_css()); + } + + #[test] + fn wrong_breakpoint() { + let mut sheet = StyleSheet::new(); + sheet.add_property("test", "mx", 10, "40px", None, false); + sheet.set_theme(Theme::new()); + assert_debug_snapshot!(sheet.create_css()); + } } diff --git a/libs/sheet/src/snapshots/sheet__tests__create_css-2.snap b/libs/sheet/src/snapshots/sheet__tests__create_css-2.snap new file mode 100644 index 00000000..0b67b7c8 --- /dev/null +++ b/libs/sheet/src/snapshots/sheet__tests__create_css-2.snap @@ -0,0 +1,5 @@ +--- +source: libs/sheet/src/lib.rs +expression: sheet.create_css() +--- +".test{display:flex;}" diff --git a/libs/sheet/src/snapshots/sheet__tests__create_css.snap b/libs/sheet/src/snapshots/sheet__tests__create_css.snap new file mode 100644 index 00000000..e80972ed --- /dev/null +++ b/libs/sheet/src/snapshots/sheet__tests__create_css.snap @@ -0,0 +1,5 @@ +--- +source: libs/sheet/src/lib.rs +expression: sheet.create_css() +--- +"\n@media (min-width:480px){.test{margin-left:40px;margin-right:40px;}}" diff --git a/libs/sheet/src/snapshots/sheet__tests__create_css_sort_test-2.snap b/libs/sheet/src/snapshots/sheet__tests__create_css_sort_test-2.snap new file mode 100644 index 00000000..0f8986e1 --- /dev/null +++ b/libs/sheet/src/snapshots/sheet__tests__create_css_sort_test-2.snap @@ -0,0 +1,5 @@ +--- +source: libs/sheet/src/lib.rs +expression: sheet.create_css() +--- +".test{border:1px solid}.test{border-color:red}" diff --git a/libs/sheet/src/snapshots/sheet__tests__create_css_sort_test.snap b/libs/sheet/src/snapshots/sheet__tests__create_css_sort_test.snap new file mode 100644 index 00000000..34857e52 --- /dev/null +++ b/libs/sheet/src/snapshots/sheet__tests__create_css_sort_test.snap @@ -0,0 +1,5 @@ +--- +source: libs/sheet/src/lib.rs +expression: sheet.create_css() +--- +"\n@media (min-width:480px){.test{background:some}.test{background-color:red}}" diff --git a/libs/sheet/src/snapshots/sheet__tests__create_css_with_basic_sort_test-2.snap b/libs/sheet/src/snapshots/sheet__tests__create_css_with_basic_sort_test-2.snap new file mode 100644 index 00000000..8f71f77b --- /dev/null +++ b/libs/sheet/src/snapshots/sheet__tests__create_css_with_basic_sort_test-2.snap @@ -0,0 +1,5 @@ +--- +source: libs/sheet/src/lib.rs +expression: sheet.create_css() +--- +".test{border-color:red}.test{border:1px solid}" diff --git a/libs/sheet/src/snapshots/sheet__tests__create_css_with_basic_sort_test-3.snap b/libs/sheet/src/snapshots/sheet__tests__create_css_with_basic_sort_test-3.snap new file mode 100644 index 00000000..8b9ed207 --- /dev/null +++ b/libs/sheet/src/snapshots/sheet__tests__create_css_with_basic_sort_test-3.snap @@ -0,0 +1,5 @@ +--- +source: libs/sheet/src/lib.rs +expression: sheet.create_css() +--- +".test{display:flex}.test{display:block}" diff --git a/libs/sheet/src/snapshots/sheet__tests__create_css_with_basic_sort_test.snap b/libs/sheet/src/snapshots/sheet__tests__create_css_with_basic_sort_test.snap new file mode 100644 index 00000000..2700b0dd --- /dev/null +++ b/libs/sheet/src/snapshots/sheet__tests__create_css_with_basic_sort_test.snap @@ -0,0 +1,5 @@ +--- +source: libs/sheet/src/lib.rs +expression: sheet.create_css() +--- +"\n@media (min-width:480px){.test{background-color:red}.test{background:some}}" diff --git a/libs/sheet/src/snapshots/sheet__tests__create_css_with_selector_and_basic_sort_test.snap b/libs/sheet/src/snapshots/sheet__tests__create_css_with_selector_and_basic_sort_test.snap new file mode 100644 index 00000000..20595798 --- /dev/null +++ b/libs/sheet/src/snapshots/sheet__tests__create_css_with_selector_and_basic_sort_test.snap @@ -0,0 +1,5 @@ +--- +source: libs/sheet/src/lib.rs +expression: sheet.create_css() +--- +"\n@media (min-width:480px){.test{background-color:some}.test:hover{background-color:red}}" diff --git a/libs/sheet/src/snapshots/sheet__tests__create_css_with_selector_sort_test-2.snap b/libs/sheet/src/snapshots/sheet__tests__create_css_with_selector_sort_test-2.snap new file mode 100644 index 00000000..7e5d7ad4 --- /dev/null +++ b/libs/sheet/src/snapshots/sheet__tests__create_css_with_selector_sort_test-2.snap @@ -0,0 +1,5 @@ +--- +source: libs/sheet/src/lib.rs +expression: sheet.create_css() +--- +"\n@media (min-width:480px){.test{background-color:red}.test:hover{background-color:some}}" diff --git a/libs/sheet/src/snapshots/sheet__tests__create_css_with_selector_sort_test-3.snap b/libs/sheet/src/snapshots/sheet__tests__create_css_with_selector_sort_test-3.snap new file mode 100644 index 00000000..34857e52 --- /dev/null +++ b/libs/sheet/src/snapshots/sheet__tests__create_css_with_selector_sort_test-3.snap @@ -0,0 +1,5 @@ +--- +source: libs/sheet/src/lib.rs +expression: sheet.create_css() +--- +"\n@media (min-width:480px){.test{background:some}.test{background-color:red}}" diff --git a/libs/sheet/src/snapshots/sheet__tests__create_css_with_selector_sort_test.snap b/libs/sheet/src/snapshots/sheet__tests__create_css_with_selector_sort_test.snap new file mode 100644 index 00000000..20595798 --- /dev/null +++ b/libs/sheet/src/snapshots/sheet__tests__create_css_with_selector_sort_test.snap @@ -0,0 +1,5 @@ +--- +source: libs/sheet/src/lib.rs +expression: sheet.create_css() +--- +"\n@media (min-width:480px){.test{background-color:some}.test:hover{background-color:red}}" diff --git a/libs/sheet/src/snapshots/sheet__tests__wrong_breakpoint.snap b/libs/sheet/src/snapshots/sheet__tests__wrong_breakpoint.snap new file mode 100644 index 00000000..19d89706 --- /dev/null +++ b/libs/sheet/src/snapshots/sheet__tests__wrong_breakpoint.snap @@ -0,0 +1,5 @@ +--- +source: libs/sheet/src/lib.rs +expression: sheet.create_css() +--- +"\n@media (min-width:1280px){.test{margin-left:40px;margin-right:40px;}}" diff --git a/packages/react/src/types/props/media/index.ts b/packages/react/src/types/props/selector/index.ts similarity index 95% rename from packages/react/src/types/props/media/index.ts rename to packages/react/src/types/props/selector/index.ts index a218b6f6..2eafe383 100644 --- a/packages/react/src/types/props/media/index.ts +++ b/packages/react/src/types/props/selector/index.ts @@ -20,4 +20,5 @@ export interface DevupMediaProps { _link?: DevupCommonProps _onlyChild?: DevupCommonProps _optional?: DevupCommonProps + _placeholder?: DevupCommonProps } diff --git a/packages/webpack-plugin/src/__tests__/loader.test.ts b/packages/webpack-plugin/src/__tests__/loader.test.ts index a6faf6bb..a7b82433 100644 --- a/packages/webpack-plugin/src/__tests__/loader.test.ts +++ b/packages/webpack-plugin/src/__tests__/loader.test.ts @@ -177,7 +177,7 @@ describe('devupUILoader', () => { 'index.tsx', 'code', 'package', - 'cssFile?' + Date.now(), + 'cssFile', ) }) }) diff --git a/packages/webpack-plugin/src/loader.ts b/packages/webpack-plugin/src/loader.ts index 17b6e109..31f16329 100644 --- a/packages/webpack-plugin/src/loader.ts +++ b/packages/webpack-plugin/src/loader.ts @@ -30,7 +30,7 @@ const devupUILoader: RawLoaderDefinitionFunction = this.resourcePath, source.toString(), libPackage, - cssFile + (plugin.watch ? '?' + Date.now() : ''), + cssFile, ) if (css) { // should be reset css diff --git a/packages/webpack-plugin/src/plugin.ts b/packages/webpack-plugin/src/plugin.ts index 20848fc0..fa6ca5c5 100644 --- a/packages/webpack-plugin/src/plugin.ts +++ b/packages/webpack-plugin/src/plugin.ts @@ -24,7 +24,6 @@ export interface DevupUIWebpackPluginOptions { export class DevupUIWebpackPlugin { options: DevupUIWebpackPluginOptions - watch = false constructor({ package: libPackage = '@devup-ui/react', @@ -82,7 +81,6 @@ export class DevupUIWebpackPlugin { let lastModifiedTime: number | null = null compiler.hooks.watchRun.tapAsync('DevupUIWebpackPlugin', (_, callback) => { - this.watch = true if (existsDevup) stat(this.options.devupPath, (err, stats) => { if (err) {