diff --git a/.changeset/grumpy-sloths-move.md b/.changeset/grumpy-sloths-move.md new file mode 100644 index 00000000..9aec864e --- /dev/null +++ b/.changeset/grumpy-sloths-move.md @@ -0,0 +1,5 @@ +--- +"@devup-ui/wasm": patch +--- + +Impl Conditional as diff --git a/Cargo.lock b/Cargo.lock index d32a9d54..9e9d22c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -340,18 +340,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" -[[package]] -name = "fixedbitset" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - [[package]] name = "futures" version = "0.3.31" @@ -468,11 +456,6 @@ name = "hashbrown" version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", -] [[package]] name = "hashbrown" @@ -667,9 +650,9 @@ dependencies = [ [[package]] name = "oxc_allocator" -version = "0.87.0" +version = "0.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90237f36cf0cd3ea2dcf9682b48fa0c1762a4b407fdcc630f60a72c277877c9f" +checksum = "9a3bc07f64a774ff9d6bd4d54d29d2a057048ed2abd5e876bffc1a295ec1b355" dependencies = [ "allocator-api2", "bumpalo", @@ -680,9 +663,9 @@ dependencies = [ [[package]] name = "oxc_ast" -version = "0.87.0" +version = "0.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a73ff824d44e51ac6c20381b644d48db4326935e811eeab29d52ca45e4d19670" +checksum = "f45156a623e26047f4f7e4c380621193295432ac996da090543e81f731dcdd47" dependencies = [ "bitflags", "oxc_allocator", @@ -697,9 +680,9 @@ dependencies = [ [[package]] name = "oxc_ast_macros" -version = "0.87.0" +version = "0.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f6af164ffae11248f32c449dad6a15f85d2154fe398bfec75502e0e2af5767a" +checksum = "6dce015e6ed092e7f22b2429bdebeafc52d603ad02308cc36c9599474b47d21d" dependencies = [ "phf", "proc-macro2", @@ -709,9 +692,9 @@ dependencies = [ [[package]] name = "oxc_ast_visit" -version = "0.87.0" +version = "0.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0ff52052e2cfb72fff062d4b7a393f9e9bded601dc16df796e3e460e17a9031" +checksum = "d74ea97de22e236da2350095e35fde2d390ddbb67714df11933dcc34cdd56078" dependencies = [ "oxc_allocator", "oxc_ast", @@ -719,26 +702,11 @@ dependencies = [ "oxc_syntax", ] -[[package]] -name = "oxc_cfg" -version = "0.87.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859f43d20760f159a0b94264bd4d1d0b3c062b69c074d894e80e65295117719b" -dependencies = [ - "bitflags", - "itertools 0.14.0", - "nonmax", - "oxc_index", - "oxc_syntax", - "petgraph", - "rustc-hash", -] - [[package]] name = "oxc_codegen" -version = "0.87.0" +version = "0.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08e84ab41c9f848471f206674c94781bdc0364699fb14574a3d26dd2a2985844" +checksum = "0fb9883d560b6f1ba584d859eb620db2317503a2c460ed72c4f1c878fc07af77" dependencies = [ "bitflags", "cow-utils", @@ -758,15 +726,15 @@ dependencies = [ [[package]] name = "oxc_data_structures" -version = "0.87.0" +version = "0.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f048c4ae3569bcc9dbbed29730b5c5f6dd3a35e9f5c3750cd4b3ed72381fbd0" +checksum = "12f7029a05de883d1461a1017211716690b342ac20c197b8539a712b426ab0a1" [[package]] name = "oxc_diagnostics" -version = "0.87.0" +version = "0.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d96c95294deec2f038e8c7749a751f929c263da34cc68a621472c57c916c14e" +checksum = "5c9b92b29ce9f356a8068eade68951e983247b7f5a7e51bb40047a20ca9c6ebf" dependencies = [ "cow-utils", "oxc-miette", @@ -775,9 +743,9 @@ dependencies = [ [[package]] name = "oxc_ecmascript" -version = "0.87.0" +version = "0.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa7b86782020722b3190c083dfc3de59cb73425d1fa275ff6f91b5b4ee509550" +checksum = "b91691a6df9a23176be896706e4b6a80b083b8af96cbb4967ec2fab804d06b4f" dependencies = [ "cow-utils", "num-bigint", @@ -790,9 +758,9 @@ dependencies = [ [[package]] name = "oxc_estree" -version = "0.87.0" +version = "0.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97f7078ef0c6da21657f5dcade4540c65a460d2a26a42e4418d12ecac860143a" +checksum = "8c0c1992f1cf16115e26a06761b34f9ef1460ffa1887256b85bcdc6b8bc04517" [[package]] name = "oxc_index" @@ -802,9 +770,9 @@ checksum = "2fa07b0cfa997730afed43705766ef27792873fdf5215b1391949fec678d2392" [[package]] name = "oxc_parser" -version = "0.87.0" +version = "0.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef71ea1e9bde8ff15f89b60874363359fc7e9796de7bf6cdff69fa54f6869bba" +checksum = "ae29814c4bc44bb6e63bdd7386ff8664e7a3e3b21dfa78e51201d3e032b0f2b6" dependencies = [ "bitflags", "cow-utils", @@ -825,9 +793,9 @@ dependencies = [ [[package]] name = "oxc_regular_expression" -version = "0.87.0" +version = "0.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a4df17b1c47c7fe749208f3a32158dfe90dca5ce630ce86cb9415521f87eb3" +checksum = "d1270bd284948924e9c4882ae6ce70ef20d33959fd33151cdde5d89c3e4e41ce" dependencies = [ "bitflags", "oxc_allocator", @@ -841,15 +809,14 @@ dependencies = [ [[package]] name = "oxc_semantic" -version = "0.87.0" +version = "0.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8239fa4e6eaee7a16039a3292a3adbaa645ba3013bf2f801517d8fadc4396557" +checksum = "42355b0a4ed2b3a3eaf6429db642be4f90e45a3f7d8fef9c7eb943745cc1bb5d" dependencies = [ "itertools 0.14.0", "oxc_allocator", "oxc_ast", "oxc_ast_visit", - "oxc_cfg", "oxc_data_structures", "oxc_diagnostics", "oxc_ecmascript", @@ -877,9 +844,9 @@ dependencies = [ [[package]] name = "oxc_span" -version = "0.87.0" +version = "0.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d88265af3fb8fc2a2317144dfc40b5e120e0ebe21693cfbf7508d4d3ec6d74f" +checksum = "57176a1bafa266ae12af0207f444786a611c0fa035bf62a960ec6833a860e526" dependencies = [ "compact_str", "oxc-miette", @@ -890,9 +857,9 @@ dependencies = [ [[package]] name = "oxc_syntax" -version = "0.87.0" +version = "0.89.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2596e7891b08899f7b74a1fb87b5f5c14153918bb2966648c84581f0a7e6795" +checksum = "fcbd72aa852c40eceb8624280f64ef0d405911e073855d890f7dac114f3f36a0" dependencies = [ "bitflags", "cow-utils", @@ -938,18 +905,6 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "petgraph" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54acf3a685220b533e437e264e4d932cfbdc4cc7ec0cd232ed73c08d03b8a7ca" -dependencies = [ - "fixedbitset", - "hashbrown 0.15.4", - "indexmap", - "serde", -] - [[package]] name = "phf" version = "0.13.1" @@ -1230,10 +1185,11 @@ checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.225" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "fd6c24dee235d0da097043389623fb913daddf92c76e9f5a1db88607a0bcbd1d" dependencies = [ + "serde_core", "serde_derive", ] @@ -1248,11 +1204,20 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "serde_core" +version = "1.0.225" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "659356f9a0cb1e529b24c01e43ad2bdf520ec4ceaf83047b83ddcc2251f96383" +dependencies = [ + "serde_derive", +] + [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.225" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "0ea936adf78b1f766949a4977b91d2f5595825bd6ec079aa9543ad2685fc4516" dependencies = [ "proc-macro2", "quote", @@ -1261,14 +1226,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] diff --git a/bindings/devup-ui-wasm/Cargo.toml b/bindings/devup-ui-wasm/Cargo.toml index 3043d3c0..8f0b5372 100644 --- a/bindings/devup-ui-wasm/Cargo.toml +++ b/bindings/devup-ui-wasm/Cargo.toml @@ -27,7 +27,7 @@ css = { path = "../../libs/css" } console_error_panic_hook = { version = "0.1.7", optional = true } once_cell = "1.21.3" js-sys = "0.3.78" -serde_json = "1.0.143" +serde_json = "1.0.145" serde-wasm-bindgen = "0.6.5" bimap = { version = "0.6.3", features = ["serde"] } diff --git a/libs/css/Cargo.toml b/libs/css/Cargo.toml index b5c66528..486d8897 100644 --- a/libs/css/Cargo.toml +++ b/libs/css/Cargo.toml @@ -7,7 +7,7 @@ edition = "2024" once_cell = "1.21.3" phf = { version = "0.13", features = ["macros"] } serial_test = "3.2.0" -serde = { version = "1.0.219", features = ["derive"] } +serde = { version = "1.0.225", features = ["derive"] } regex = "1.11.2" bimap = { version = "0.6.3" } diff --git a/libs/extractor/Cargo.toml b/libs/extractor/Cargo.toml index 777d0b16..f41e05a9 100644 --- a/libs/extractor/Cargo.toml +++ b/libs/extractor/Cargo.toml @@ -4,13 +4,13 @@ version = "0.1.0" edition = "2024" [dependencies] -oxc_parser = "0.87.0" -oxc_syntax = "0.87.0" -oxc_span = "0.87.0" -oxc_allocator = "0.87.0" -oxc_ast = "0.87.0" -oxc_ast_visit = "0.87.0" -oxc_codegen = "0.87.0" +oxc_parser = "0.89.0" +oxc_syntax = "0.89.0" +oxc_span = "0.89.0" +oxc_allocator = "0.89.0" +oxc_ast = "0.89.0" +oxc_ast_visit = "0.89.0" +oxc_codegen = "0.89.0" css = { path = "../css" } phf = "0.13" strum = "0.27.2" diff --git a/libs/extractor/src/as_visit.rs b/libs/extractor/src/as_visit.rs new file mode 100644 index 00000000..d9a4fe61 --- /dev/null +++ b/libs/extractor/src/as_visit.rs @@ -0,0 +1,62 @@ +use crate::utils::get_string_by_literal_expression; +use oxc_allocator::{Allocator, CloneIn}; +use oxc_ast::ast::{Expression, JSXElement}; +use oxc_ast_visit::VisitMut; +use oxc_ast_visit::walk_mut::walk_expression; + +use oxc_ast::AstBuilder; +use oxc_span::SPAN; + +pub struct AsVisitor<'a> { + ast: AstBuilder<'a>, + element: JSXElement<'a>, +} + +impl<'a> AsVisitor<'a> { + pub fn new(allocator: &'a Allocator, element: JSXElement<'a>) -> Self { + Self { + ast: AstBuilder::new(allocator), + element, + } + } +} + +fn change_element_name<'a>(ast: &AstBuilder<'a>, element: &mut JSXElement<'a>, element_name: &str) { + let element_name = ast.jsx_element_name_identifier(SPAN, ast.atom(element_name)); + element.opening_element.name = element_name.clone_in(ast.allocator); + if let Some(el) = &mut element.closing_element { + el.name = element_name; + } +} + +impl<'a> VisitMut<'a> for AsVisitor<'a> { + fn visit_expression(&mut self, it: &mut oxc_ast::ast::Expression<'a>) { + if let Some(element_name) = get_string_by_literal_expression(it) { + let mut element = self.element.clone_in(self.ast.allocator); + change_element_name(&self.ast, &mut element, &element_name); + *it = Expression::JSXElement(self.ast.alloc(element)); + } else if let Expression::Identifier(ident) = it { + let element_name = ident.name.to_string(); + if element_name != "undefined" { + let mut element = self.element.clone_in(self.ast.allocator); + change_element_name(&self.ast, &mut element, &element_name); + *it = Expression::JSXElement(self.ast.alloc(element)); + } + } else if let Expression::ConditionalExpression(conditional) = it { + self.visit_expression(&mut conditional.consequent); + self.visit_expression(&mut conditional.alternate); + } else if let Expression::ComputedMemberExpression(member) = it { + self.visit_expression(&mut member.object); + } else { + walk_expression(self, it); + } + } + + fn visit_object_property(&mut self, it: &mut oxc_ast::ast::ObjectProperty<'a>) { + self.visit_expression(&mut it.value); + } + + fn visit_spread_element(&mut self, _: &mut oxc_ast::ast::SpreadElement<'a>) { + // spread be mantained + } +} diff --git a/libs/extractor/src/extractor/extract_global_style_from_expression.rs b/libs/extractor/src/extractor/extract_global_style_from_expression.rs index 58ee09fe..33843b20 100644 --- a/libs/extractor/src/extractor/extract_global_style_from_expression.rs +++ b/libs/extractor/src/extractor/extract_global_style_from_expression.rs @@ -81,31 +81,31 @@ pub fn extract_global_style_from_expression<'a>( for p in arr.elements.iter() { if let ArrayExpressionElement::ObjectExpression(o) = p { styles.push(ExtractStyleProp::Static(ExtractStyleValue::FontFace(ExtractFontFace { - properties: BTreeMap::from_iter( - o.properties - .iter() - .filter_map(|p| { - if let ObjectPropertyKind::ObjectProperty(o) = p - && let PropertyKey::StaticIdentifier(ident) = &o.key - && let Some(s) = get_string_by_literal_expression(&o.value) - { - Some(disassemble_property(&ident.name).iter().map(|p| { - let v= if check_multi_css_optimize(p) { optimize_mutli_css_value(&s) } else { s.clone() }; - if *p == "src" { - (p.to_string(), wrap_url(&v)) - } - else { - (p.to_string(), v) + properties: BTreeMap::from_iter( + o.properties + .iter() + .filter_map(|p| { + if let ObjectPropertyKind::ObjectProperty(o) = p + && let PropertyKey::StaticIdentifier(ident) = &o.key + && let Some(s) = get_string_by_literal_expression(&o.value) + { + Some( + disassemble_property(&ident.name) + .iter() + .map(|p| { + let v = if check_multi_css_optimize(p) { optimize_mutli_css_value(&s) } else { s.clone() }; + if *p == "src" { (p.to_string(), wrap_url(&v)) } else { (p.to_string(), v) } + }) + .collect::>(), + ) + } else { + None } - }).collect::>()) - } else { - None - } - }) - .flatten(), - ), - file: file.to_string(), - }))); + }) + .flatten(), + ), + file: file.to_string(), + }))); } else if let ArrayExpressionElement::TemplateLiteral(t) = p { let css_styles = css_to_style( t.quasis diff --git a/libs/extractor/src/extractor/extract_style_from_expression.rs b/libs/extractor/src/extractor/extract_style_from_expression.rs index 01ec40c4..510dea1c 100644 --- a/libs/extractor/src/extractor/extract_style_from_expression.rs +++ b/libs/extractor/src/extractor/extract_style_from_expression.rs @@ -41,6 +41,7 @@ pub fn extract_style_from_expression<'a>( if name.is_none() && selector.is_none() { let mut style_order = None; let mut style_vars = None; + let mut props = None; return match expression { Expression::ObjectExpression(obj) => { let mut props_styles: Vec> = vec![]; @@ -61,6 +62,8 @@ pub fn extract_style_from_expression<'a>( } else if &property_name == "styleVars" { style_vars = Some(prop.value.clone_in(ast_builder.allocator)); + } else if &property_name == "props" { + props = Some(prop.value.clone_in(ast_builder.allocator)); } else { let ExtractResult { styles, tag: _tag, .. @@ -103,9 +106,11 @@ pub fn extract_style_from_expression<'a>( tag, style_order, style_vars, + props, } } Expression::ConditionalExpression(conditional) => ExtractResult { + props: None, styles: vec![ExtractStyleProp::Conditional { condition: conditional.test.clone_in(ast_builder.allocator), consequent: Some(Box::new(ExtractStyleProp::StaticArray( @@ -211,10 +216,8 @@ pub fn extract_style_from_expression<'a>( ]) .to_string() } - } else if name.contains("&") { - name.replace("&", &selector.to_string()) } else { - StyleSelector::from([&selector.to_string(), *name]).to_string() + name.replace("&", &selector.to_string()) } } else if name.starts_with("_") { StyleSelector::from(to_kebab_case(&name.replace("_", "")).as_str()) @@ -496,6 +499,7 @@ pub fn extract_style_from_expression<'a>( tag: None, style_order: None, style_vars: None, + props: None, } } Expression::ConditionalExpression(conditional) => { diff --git a/libs/extractor/src/extractor/extract_style_from_member_expression.rs b/libs/extractor/src/extractor/extract_style_from_member_expression.rs index 8cd39642..fba3da51 100644 --- a/libs/extractor/src/extractor/extract_style_from_member_expression.rs +++ b/libs/extractor/src/extractor/extract_style_from_member_expression.rs @@ -30,127 +30,63 @@ pub(super) fn extract_style_from_member_expression<'a>( let mem_expression = &mem.expression.clone_in(ast_builder.allocator); let mut ret: Vec = vec![]; - match &mut mem.object { - Expression::ArrayExpression(array) if !array.elements.is_empty() => { - if let Some(num) = get_number_by_literal_expression(mem_expression) { - if num < 0f64 { - return ExtractResult::default(); - } - let mut etc = None; - for (idx, p) in array.elements.iter_mut().enumerate() { - if let ArrayExpressionElement::SpreadElement(sp) = p { - etc = Some(sp.argument.clone_in(ast_builder.allocator)); - } else if idx as f64 == num - && let Some(p) = p.as_expression_mut() - { - return extract_style_from_expression( - ast_builder, - name, - p, - level, - selector, - ); - } - } - return ExtractResult { - styles: etc - .map(|etc| { - vec![ExtractStyleProp::Static(ExtractStyleValue::Dynamic( - ExtractDynamicStyle::new( - name.unwrap(), - level, - &expression_to_code(&Expression::ComputedMemberExpression( - ast_builder.alloc_computed_member_expression( - SPAN, - etc, - mem_expression.clone_in(ast_builder.allocator), - false, - ), - )), - selector.clone(), - ), - ))] - }) - .unwrap_or_default(), - tag: None, - style_order: None, - style_vars: None, - }; + if let Expression::ArrayExpression(array) = &mut mem.object + && !array.elements.is_empty() + { + if let Some(num) = get_number_by_literal_expression(mem_expression) { + if num < 0f64 { + return ExtractResult::default(); } - - let mut map = BTreeMap::new(); + let mut etc = None; for (idx, p) in array.elements.iter_mut().enumerate() { if let ArrayExpressionElement::SpreadElement(sp) = p { - map.insert( - idx.to_string(), - Box::new(ExtractStyleProp::Static(ExtractStyleValue::Dynamic( + etc = Some(sp.argument.clone_in(ast_builder.allocator)); + } else if idx as f64 == num + && let Some(p) = p.as_expression_mut() + { + return extract_style_from_expression(ast_builder, name, p, level, selector); + } + } + return ExtractResult { + props: None, + styles: etc + .map(|etc| { + vec![ExtractStyleProp::Static(ExtractStyleValue::Dynamic( ExtractDynamicStyle::new( name.unwrap(), level, &expression_to_code(&Expression::ComputedMemberExpression( ast_builder.alloc_computed_member_expression( SPAN, - sp.argument.clone_in(ast_builder.allocator), + etc, mem_expression.clone_in(ast_builder.allocator), false, ), )), selector.clone(), ), - ))), - ); - } else if let Some(p) = p.as_expression_mut() { - map.insert( - idx.to_string(), - Box::new(ExtractStyleProp::StaticArray( - extract_style_from_expression(ast_builder, name, p, level, selector) - .styles, - )), - ); - } - } - - ret.push(ExtractStyleProp::MemberExpression { - expression: mem_expression.clone_in(ast_builder.allocator), - map, - }); + ))] + }) + .unwrap_or_default(), + tag: None, + style_order: None, + style_vars: None, + }; } - Expression::ObjectExpression(obj) if !obj.properties.is_empty() => { - let mut map = BTreeMap::new(); - if let Some(k) = get_string_by_literal_expression(mem_expression) { - let mut etc = None; - for p in obj.properties.iter_mut() { - if let ObjectPropertyKind::ObjectProperty(o) = p { - if let PropertyKey::StaticIdentifier(ref pk) = o.key - && pk.name == k - { - return ExtractResult { - styles: extract_style_from_expression( - ast_builder, - name, - &mut o.value, - level, - selector, - ) - .styles, - ..ExtractResult::default() - }; - } - } else if let ObjectPropertyKind::SpreadProperty(sp) = p { - etc = Some(sp.argument.clone_in(ast_builder.allocator)); - } - } - match etc { - None => return ExtractResult::default(), - Some(etc) => ret.push(ExtractStyleProp::Static(ExtractStyleValue::Dynamic( + let mut map = BTreeMap::new(); + for (idx, p) in array.elements.iter_mut().enumerate() { + if let ArrayExpressionElement::SpreadElement(sp) = p { + map.insert( + idx.to_string(), + Box::new(ExtractStyleProp::Static(ExtractStyleValue::Dynamic( ExtractDynamicStyle::new( name.unwrap(), level, &expression_to_code(&Expression::ComputedMemberExpression( ast_builder.alloc_computed_member_expression( SPAN, - etc, + sp.argument.clone_in(ast_builder.allocator), mem_expression.clone_in(ast_builder.allocator), false, ), @@ -158,19 +94,34 @@ pub(super) fn extract_style_from_member_expression<'a>( selector.clone(), ), ))), - } + ); + } else if let Some(p) = p.as_expression_mut() { + map.insert( + idx.to_string(), + Box::new(ExtractStyleProp::StaticArray( + extract_style_from_expression(ast_builder, name, p, level, selector).styles, + )), + ); } + } + ret.push(ExtractStyleProp::MemberExpression { + expression: mem_expression.clone_in(ast_builder.allocator), + map, + }); + } else if let Expression::ObjectExpression(obj) = &mut mem.object + && !obj.properties.is_empty() + { + let mut map = BTreeMap::new(); + if let Some(k) = get_string_by_literal_expression(mem_expression) { + let mut etc = None; for p in obj.properties.iter_mut() { - if let ObjectPropertyKind::ObjectProperty(o) = p - && let PropertyKey::StaticIdentifier(_) - | PropertyKey::NumericLiteral(_) - | PropertyKey::StringLiteral(_) = o.key - { - map.insert( - o.key.name().unwrap().to_string(), - Box::new(ExtractStyleProp::StaticArray( - extract_style_from_expression( + if let ObjectPropertyKind::ObjectProperty(o) = p { + if let PropertyKey::StaticIdentifier(ref pk) = o.key + && pk.name == k + { + return ExtractResult { + styles: extract_style_from_expression( ast_builder, name, &mut o.value, @@ -178,17 +129,62 @@ pub(super) fn extract_style_from_member_expression<'a>( selector, ) .styles, - )), - ); + ..ExtractResult::default() + }; + } + } else if let ObjectPropertyKind::SpreadProperty(sp) = p { + etc = Some(sp.argument.clone_in(ast_builder.allocator)); } } - ret.push(ExtractStyleProp::MemberExpression { - expression: mem_expression.clone_in(ast_builder.allocator), - map, - }); + + match etc { + None => return ExtractResult::default(), + Some(etc) => ret.push(ExtractStyleProp::Static(ExtractStyleValue::Dynamic( + ExtractDynamicStyle::new( + name.unwrap(), + level, + &expression_to_code(&Expression::ComputedMemberExpression( + ast_builder.alloc_computed_member_expression( + SPAN, + etc, + mem_expression.clone_in(ast_builder.allocator), + false, + ), + )), + selector.clone(), + ), + ))), + } } - Expression::Identifier(_) => ret.push(ExtractStyleProp::Static( - ExtractStyleValue::Dynamic(ExtractDynamicStyle::new( + + for p in obj.properties.iter_mut() { + if let ObjectPropertyKind::ObjectProperty(o) = p + && let PropertyKey::StaticIdentifier(_) + | PropertyKey::NumericLiteral(_) + | PropertyKey::StringLiteral(_) = o.key + { + map.insert( + o.key.name().unwrap().to_string(), + Box::new(ExtractStyleProp::StaticArray( + extract_style_from_expression( + ast_builder, + name, + &mut o.value, + level, + selector, + ) + .styles, + )), + ); + } + } + ret.push(ExtractStyleProp::MemberExpression { + expression: mem_expression.clone_in(ast_builder.allocator), + map, + }); + } else if let Expression::Identifier(_) = &mut mem.object { + ret.push(ExtractStyleProp::Static(ExtractStyleValue::Dynamic( + ExtractDynamicStyle::new( name.unwrap(), level, &expression_to_code(&Expression::ComputedMemberExpression( @@ -200,10 +196,9 @@ pub(super) fn extract_style_from_member_expression<'a>( ), )), selector.clone(), - )), - )), - _ => {} - }; + ), + ))) + } ExtractResult { styles: ret, diff --git a/libs/extractor/src/extractor/mod.rs b/libs/extractor/src/extractor/mod.rs index 61c14f84..e467d099 100644 --- a/libs/extractor/src/extractor/mod.rs +++ b/libs/extractor/src/extractor/mod.rs @@ -22,6 +22,7 @@ pub struct ExtractResult<'a> { pub tag: Option>, pub style_order: Option, pub style_vars: Option>, + pub props: Option>, } #[derive(Debug)] diff --git a/libs/extractor/src/gen_class_name.rs b/libs/extractor/src/gen_class_name.rs index 42869aa9..1796a098 100644 --- a/libs/extractor/src/gen_class_name.rs +++ b/libs/extractor/src/gen_class_name.rs @@ -34,17 +34,13 @@ fn gen_class_name<'a>( if let Some(style_order) = style_order { st.set_style_order(style_order); } - let target = st.extract(filename); - - Some(ast_builder.expression_string_literal( - SPAN, - ast_builder.atom(match &target { - Some(StyleProperty::ClassName(cls)) => cls, - Some(StyleProperty::Variable { class_name, .. }) => class_name, - None => return None, - }), - None, - )) + st.extract(filename).map(|style| { + let v = ast_builder.atom(&match style { + StyleProperty::ClassName(cls) => cls, + StyleProperty::Variable { class_name, .. } => class_name, + }); + ast_builder.expression_string_literal(SPAN, v, None) + }) } ExtractStyleProp::StaticArray(res) => merge_expression_for_class_name( ast_builder, @@ -148,25 +144,22 @@ pub fn merge_expression_for_class_name<'a>( let mut qu = oxc_allocator::Vec::new_in(ast_builder.allocator); for idx in 0..unknown_expr.len() + 1 { let tail = idx == unknown_expr.len(); - qu.push(ast_builder.template_element( - SPAN, - TemplateElementValue { - raw: ast_builder.atom(if idx == 0 { - if class_name.is_empty() { - "" - } else { - class_name.push(' '); - class_name.as_str() - } - } else if tail { + let t = TemplateElementValue { + raw: ast_builder.atom(if idx == 0 { + if class_name.is_empty() { "" } else { - " " - }), - cooked: None, - }, - tail, - )); + class_name.push(' '); + class_name.as_str() + } + } else if tail { + "" + } else { + " " + }), + cooked: None, + }; + qu.push(ast_builder.template_element(SPAN, t, tail)); } Some(ast_builder.expression_template_literal( diff --git a/libs/extractor/src/gen_style.rs b/libs/extractor/src/gen_style.rs index 5e2ac607..2bac6c6c 100644 --- a/libs/extractor/src/gen_style.rs +++ b/libs/extractor/src/gen_style.rs @@ -32,257 +32,197 @@ fn gen_style<'a>( filename: Option<&str>, ) -> Vec> { let mut properties = vec![]; - match style { - ExtractStyleProp::Static(st) => { - if let Some(StyleProperty::Variable { - variable_name, - identifier, - .. - }) = st.extract(filename) - { - properties.push(ast_builder.object_property_kind_object_property( + if let ExtractStyleProp::Static(st) = style { + if let Some(StyleProperty::Variable { + variable_name, + identifier, + .. + }) = st.extract(filename) + { + properties.push(ast_builder.object_property_kind_object_property( + SPAN, + PropertyKind::Init, + PropertyKey::StringLiteral(ast_builder.alloc_string_literal( SPAN, - PropertyKind::Init, - PropertyKey::StringLiteral(ast_builder.alloc_string_literal( - SPAN, - ast_builder.atom(&variable_name), - None, - )), - ast_builder.expression_identifier(SPAN, ast_builder.atom(&identifier)), - false, - false, - false, - )); - } + ast_builder.atom(&variable_name), + None, + )), + ast_builder.expression_identifier(SPAN, ast_builder.atom(&identifier)), + false, + false, + false, + )); } - ExtractStyleProp::StaticArray(res) => { - properties.append( - &mut res - .iter() - .flat_map(|r| gen_style(ast_builder, r, filename)) - .rev() - .collect(), - ); - } - ExtractStyleProp::Conditional { - condition, - consequent, - alternate, - } => match (consequent, alternate) { - (None, None) => { - return vec![]; - } - (None, Some(c)) => { - gen_style(ast_builder, c, filename) - .into_iter() - .for_each(|p| { - if let ObjectPropertyKind::ObjectProperty(p) = p { - properties.push(ast_builder.object_property_kind_object_property( - SPAN, - PropertyKind::Init, - p.key.clone_in(ast_builder.allocator), - ast_builder.expression_conditional( - SPAN, - condition.clone_in(ast_builder.allocator), - ast_builder.expression_identifier(SPAN, "undefined"), - p.value.clone_in(ast_builder.allocator), - ), - false, - false, - false, - )) - } - }); - } - (Some(c), None) => { - gen_style(ast_builder, c, filename) - .into_iter() - .for_each(|p| { - if let ObjectPropertyKind::ObjectProperty(p) = p { - properties.push(ast_builder.object_property_kind_object_property( - SPAN, - PropertyKind::Init, - p.key.clone_in(ast_builder.allocator), - ast_builder.expression_conditional( - SPAN, - condition.clone_in(ast_builder.allocator), - p.value.clone_in(ast_builder.allocator), - ast_builder.expression_identifier(SPAN, "undefined"), - ), - false, - false, - false, - )) - } - }); - } - (Some(c), Some(a)) => { - let collect_c = gen_style(ast_builder, c, filename); - let collect_a = gen_style(ast_builder, a, filename); - if collect_c.is_empty() && collect_a.is_empty() { - return vec![]; - } - for p in collect_c.iter() { - let mut found = false; - for q in collect_a.iter() { - if let ( - ObjectPropertyKind::ObjectProperty(p), - ObjectPropertyKind::ObjectProperty(q), - ) = (p, q) - && p.key.name() == q.key.name() - { - found = true; - properties.push(ast_builder.object_property_kind_object_property( - SPAN, - PropertyKind::Init, - p.key.clone_in(ast_builder.allocator), - ast_builder.expression_conditional( - SPAN, - condition.clone_in(ast_builder.allocator), - p.value.clone_in(ast_builder.allocator), - q.value.clone_in(ast_builder.allocator), - ), - false, - false, - false, - )); - break; - } - } - if !found && let ObjectPropertyKind::ObjectProperty(p) = p { + } else if let ExtractStyleProp::StaticArray(res) = style { + properties.append( + &mut res + .iter() + .flat_map(|r| gen_style(ast_builder, r, filename)) + .rev() + .collect(), + ); + } else if let ExtractStyleProp::Conditional { + condition, + consequent, + alternate, + } = style + { + let r = (consequent, alternate); + if let (None, Some(c)) = r { + gen_style(ast_builder, c, filename) + .into_iter() + .for_each(|p| { + if let ObjectPropertyKind::ObjectProperty(p) = p { properties.push(ast_builder.object_property_kind_object_property( SPAN, PropertyKind::Init, p.key.clone_in(ast_builder.allocator), - p.value.clone_in(ast_builder.allocator), + ast_builder.expression_conditional( + SPAN, + condition.clone_in(ast_builder.allocator), + ast_builder.expression_identifier(SPAN, "undefined"), + p.value.clone_in(ast_builder.allocator), + ), false, false, false, - )); + )) } - } - - for q in collect_a.iter() { - let mut found = false; - for p in collect_c.iter() { - if let ( - ObjectPropertyKind::ObjectProperty(p), - ObjectPropertyKind::ObjectProperty(q), - ) = (p, q) - && p.key.name() == q.key.name() - { - found = true; - break; - } - } - if !found && let ObjectPropertyKind::ObjectProperty(q) = q { + }); + } else if let (Some(c), None) = r { + gen_style(ast_builder, c, filename) + .into_iter() + .for_each(|p| { + if let ObjectPropertyKind::ObjectProperty(p) = p { properties.push(ast_builder.object_property_kind_object_property( SPAN, PropertyKind::Init, - q.key.clone_in(ast_builder.allocator), - q.value.clone_in(ast_builder.allocator), + p.key.clone_in(ast_builder.allocator), + ast_builder.expression_conditional( + SPAN, + condition.clone_in(ast_builder.allocator), + p.value.clone_in(ast_builder.allocator), + ast_builder.expression_identifier(SPAN, "undefined"), + ), false, false, false, - )); + )) + } + }); + } else if let (Some(c), Some(a)) = r { + let collect_c = gen_style(ast_builder, c, filename); + let collect_a = gen_style(ast_builder, a, filename); + if collect_c.is_empty() && collect_a.is_empty() { + return vec![]; + } + for p in collect_c.iter() { + let found = collect_a.iter().any(|q| { + let r = matches!((p, q), (ObjectPropertyKind::ObjectProperty(p), ObjectPropertyKind::ObjectProperty(q)) if p.key.name() == q.key.name()); + if let ObjectPropertyKind::ObjectProperty(p) = p + && let ObjectPropertyKind::ObjectProperty(q) = q + && r + { + properties.push(ast_builder.object_property_kind_object_property(SPAN, PropertyKind::Init, p.key.clone_in(ast_builder.allocator), ast_builder.expression_conditional(SPAN, condition.clone_in(ast_builder.allocator), p.value.clone_in(ast_builder.allocator), q.value.clone_in(ast_builder.allocator)), false, false, false)); } + r + }); + if !found && let ObjectPropertyKind::ObjectProperty(p) = p { + properties.push(ast_builder.object_property_kind_object_property( + SPAN, + PropertyKind::Init, + p.key.clone_in(ast_builder.allocator), + p.value.clone_in(ast_builder.allocator), + false, + false, + false, + )); } } - }, - ExtractStyleProp::Expression { styles, .. } => { - for style in styles { - if let Some(StyleProperty::Variable { - variable_name, - identifier, - .. - }) = style.extract(filename) - { + + for q in collect_a.iter() { + let found = collect_c.iter().any(|p| matches!((p, q), (ObjectPropertyKind::ObjectProperty(p), ObjectPropertyKind::ObjectProperty(q)) if p.key.name() == q.key.name())); + if !found && let ObjectPropertyKind::ObjectProperty(q) = q { properties.push(ast_builder.object_property_kind_object_property( SPAN, PropertyKind::Init, - PropertyKey::StringLiteral(ast_builder.alloc_string_literal( - SPAN, - ast_builder.atom(&variable_name), - None, - )), - ast_builder.expression_identifier(SPAN, ast_builder.atom(&identifier)), + q.key.clone_in(ast_builder.allocator), + q.value.clone_in(ast_builder.allocator), + false, false, false, - true, )); } } } - ExtractStyleProp::MemberExpression { map, expression } => { - let mut tmp_map = BTreeMap::>::new(); - for (key, value) in map.iter() { - for style in value.extract() { - if let Some(StyleProperty::Variable { - variable_name, - identifier, - .. - }) = style.extract(filename) - { - tmp_map - .entry(variable_name) - .or_default() - .push((key.to_string(), identifier)); - } + } else if let ExtractStyleProp::MemberExpression { map, expression } = style { + let mut tmp_map = BTreeMap::>::new(); + for (key, value) in map.iter() { + for style in value.extract() { + if let Some(StyleProperty::Variable { + variable_name, + identifier, + .. + }) = style.extract(filename) + { + tmp_map + .entry(variable_name) + .or_default() + .push((key.to_string(), identifier)); } } + } - for (key, value) in tmp_map { - properties.push(ast_builder.object_property_kind_object_property( - SPAN, - PropertyKind::Init, - PropertyKey::StringLiteral(ast_builder.alloc_string_literal( + for (key, value) in tmp_map { + let v = if value.len() == 1 { + // do not create object expression when property is single + ast_builder.expression_identifier(SPAN, ast_builder.atom(&value[0].1)) + } else { + Expression::ComputedMemberExpression( + ast_builder.alloc_computed_member_expression( SPAN, - ast_builder.atom(&key), - None, - )), - if value.len() == 1 { - // do not create object expression when property is single - ast_builder.expression_identifier(SPAN, ast_builder.atom(&value[0].1)) - } else { - Expression::ComputedMemberExpression( - ast_builder.alloc_computed_member_expression( - SPAN, - ast_builder.expression_object( - SPAN, - oxc_allocator::Vec::from_iter_in( - value - .into_iter() - .map(|(k, v)| { - ast_builder.object_property_kind_object_property( - SPAN, - PropertyKind::Init, - ast_builder.property_key_static_identifier( - SPAN, - ast_builder.atom(&k), - ), - ast_builder.expression_identifier( - SPAN, - ast_builder.atom(&v), - ), - false, - false, - false, - ) - }) - .collect::>(), - ast_builder.allocator, - ), - ), - expression.clone_in(ast_builder.allocator), - false, + ast_builder.expression_object( + SPAN, + oxc_allocator::Vec::from_iter_in( + value + .into_iter() + .map(|(k, v)| { + ast_builder.object_property_kind_object_property( + SPAN, + PropertyKind::Init, + ast_builder.property_key_static_identifier( + SPAN, + ast_builder.atom(&k), + ), + ast_builder + .expression_identifier(SPAN, ast_builder.atom(&v)), + false, + false, + false, + ) + }) + .collect::>(), + ast_builder.allocator, ), - ) - }, - false, - false, - false, - )); - } + ), + expression.clone_in(ast_builder.allocator), + false, + ), + ) + }; + properties.push(ast_builder.object_property_kind_object_property( + SPAN, + PropertyKind::Init, + PropertyKey::StringLiteral(ast_builder.alloc_string_literal( + SPAN, + ast_builder.atom(&key), + None, + )), + v, + false, + false, + false, + )); } } properties.sort_by_key(|p| { diff --git a/libs/extractor/src/lib.rs b/libs/extractor/src/lib.rs index 73a464ce..66ac074f 100644 --- a/libs/extractor/src/lib.rs +++ b/libs/extractor/src/lib.rs @@ -1,3 +1,4 @@ +mod as_visit; mod component; mod css_utils; pub mod extract_style; @@ -227,11 +228,7 @@ mod tests { r#"import {Box} from '@devup-ui/core' {}} aria-valuenow={24} key={2} tabIndex={1} id="id" /> "#, - ExtractOption { - package: "@devup-ui/core".to_string(), - css_dir: "@devup-ui/core".to_string(), - single_css: true,import_main_css: false, - } + ExtractOption { package: "@devup-ui/core".to_string(), css_dir: "@devup-ui/core".to_string(), single_css: true, import_main_css: false } ) .unwrap() )); @@ -290,6 +287,8 @@ mod tests { ) .unwrap() )); + + reset_class_map(); assert_debug_snapshot!(ToBTreeSet::from( extract( "test.tsx", @@ -322,6 +321,8 @@ mod tests { ) .unwrap() )); + + reset_class_map(); assert_debug_snapshot!(ToBTreeSet::from( extract( "test.tsx", @@ -337,51 +338,270 @@ mod tests { ) .unwrap() )); - // assert_debug_snapshot!(extract( - // "test.tsx", - // r#"import {Box} from '@devup-ui/core' - // - // "#, - // ExtractOption { - // package: "@devup-ui/core".to_string(), - // css_file: None - // } - // ) - // .unwrap()); - // assert_debug_snapshot!(extract( - // "test.tsx", - // r#"import {Box} from '@devup-ui/core' - // - // "#, - // ExtractOption { - // package: "@devup-ui/core".to_string(), - // css_file: None - // } - // ) - // .unwrap()); - // - // assert_debug_snapshot!(extract( - // "test.tsx", - // r#"import {Box} from '@devup-ui/core' - // - // "#, - // ExtractOption { - // package: "@devup-ui/core".to_string(), - // css_file: None - // } - // ) - // .unwrap()); - // assert_debug_snapshot!(extract( - // "test.tsx", - // r#"import {Box} from '@devup-ui/core' - // - // "#, - // ExtractOption { - // package: "@devup-ui/core".to_string(), - // css_file: None - // } - // ) - // .unwrap()); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { package: "@devup-ui/core".to_string(), css_dir: "@devup-ui/core".to_string(), single_css: true, import_main_css: false } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { package: "@devup-ui/core".to_string(), css_dir: "@devup-ui/core".to_string(), single_css: true, import_main_css: false } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + // maintain object expression + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + // maintain object expression + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); } #[test] #[serial] @@ -1276,6 +1496,23 @@ import clsx from 'clsx' "test.tsx", r#"import { Box } from "@devup-ui/core"; ; +"#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import { Box } from "@devup-ui/core"; +; "#, ExtractOption { package: "@devup-ui/core".to_string(), @@ -3397,22 +3634,67 @@ e(o, { className: "a", bg: variable, style: { color: "blue" }, ...props }) ) .unwrap() )); + + // conditional as + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.js", + r#"import { jsx as e } from "react/jsx-runtime"; + import { Box as o } from "@devup-ui/core"; + e(o, { as: b ? "div" : "section", className: "a", bg: variable, style: { color: "blue" }, props: { animate: { duration: 1 } } }) + "#, + ExtractOption { package: "@devup-ui/core".to_string(), css_dir: "@devup-ui/core".to_string(), single_css: true, import_main_css: false } + ) + .unwrap() + )); + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.js", + r#"import { jsx as e } from "react/jsx-runtime"; + import { Box as o } from "@devup-ui/core"; + e(o, { as: Variable, className: "a", bg: variable, style: { color: "blue" }, props: { animate: { duration: 1 } } }) + "#, + ExtractOption { package: "@devup-ui/core".to_string(), css_dir: "@devup-ui/core".to_string(), single_css: true, import_main_css: false } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.js", + r#"import { jsx as e } from "react/jsx-runtime"; + import { Box as o } from "@devup-ui/core"; + e(o, { as: b ? null : undefined, className: "a", bg: variable, style: { color: "blue" }, props: { animate: { duration: 1 } } }) + "#, + ExtractOption { package: "@devup-ui/core".to_string(), css_dir: "@devup-ui/core".to_string(), single_css: true, import_main_css: false } + ) + .unwrap() + )); } #[test] #[serial] fn support_transpile_cjs() { reset_class_map(); - assert_debug_snapshot!(ToBTreeSet::from(extract("test.cjs", r#""use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("@devup-ui/react");function t(){return e.jsxs("div",{children:[e.jsx(r.Box,{_hover:{bg:"blue"},bg:"$text",color:"red",children:"hello"}),e.jsx(r.Text,{typography:"header",children:"typo"}),e.jsx(r.Flex,{as:"section",mt:2,children:"section"})]})}exports.Lib=t;"#, ExtractOption { package: "@devup-ui/react".to_string(), css_dir: "@devup-ui/react".to_string(),single_css:true,import_main_css: false }).unwrap())); + assert_debug_snapshot!(ToBTreeSet::from(extract("test.cjs", r#""use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("@devup-ui/react");function t(){return e.jsxs("div",{children:[e.jsx(r.Box,{_hover:{bg:"blue"},bg:"$text",color:"red",children:"hello"}),e.jsx(r.Text,{typography:"header",children:"typo"}),e.jsx(r.Flex,{as:"section",mt:2,children:"section"})]})}exports.Lib=t;"#, ExtractOption { package: "@devup-ui/react".to_string(), css_dir: "@devup-ui/react".to_string(), single_css: true, import_main_css: false }).unwrap())); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from(extract("test.cjs", r#""use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const {jsx:e1, jsxs:e2}=require("react/jsx-runtime"),r=require("@devup-ui/react");function t(){return e2("div",{children:[e1(r.Box,{_hover:{bg:"blue"},bg:"$text",color:"red",children:"hello"}),e1(r.Text,{typography:"header",children:"typo"}),e1(r.Flex,{as:"section",mt:2,children:"section"})]})}exports.Lib=t;"#, ExtractOption { package: "@devup-ui/react".to_string(), css_dir: "@devup-ui/react".to_string(), single_css: true, import_main_css: false }).unwrap())); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from(extract("test.js", r#""use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("@devup-ui/react");function t(){return e.jsxs("div",{children:[e.jsx(r.Box,{_hover:{bg:"blue"},bg:"$text",color:"red",children:"hello"}),e.jsx(r.Text,{typography:"header",children:"typo"}),e.jsx(r.Flex,{as:"section",mt:2,children:"section"})]})}exports.Lib=t;"#, ExtractOption { package: "@devup-ui/react".to_string(), css_dir: "@devup-ui/react".to_string(), single_css: true, import_main_css: false }).unwrap())); reset_class_map(); - assert_debug_snapshot!(ToBTreeSet::from(extract("test.cjs", r#""use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const {jsx:e1, jsxs:e2}=require("react/jsx-runtime"),r=require("@devup-ui/react");function t(){return e2("div",{children:[e1(r.Box,{_hover:{bg:"blue"},bg:"$text",color:"red",children:"hello"}),e1(r.Text,{typography:"header",children:"typo"}),e1(r.Flex,{as:"section",mt:2,children:"section"})]})}exports.Lib=t;"#, ExtractOption { package: "@devup-ui/react".to_string(), css_dir: "@devup-ui/react".to_string(),single_css:true,import_main_css: false }).unwrap())); + assert_debug_snapshot!(ToBTreeSet::from(extract("test.js", r#""use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("@devup-ui/react");function t(){return e.jsxs("div",{children:[e.jsx(r.Box,{_hover:{bg:"blue"},bg:"$text",color:"red",children:"hello"}),e.jsx(r.Text,{typography:`header`,children:"typo"}),e.jsx(r.Flex,{as:"section",mt:2,children:"section"})]})}exports.Lib=t;"#, ExtractOption { package: "@devup-ui/react".to_string(), css_dir: "@devup-ui/react".to_string(), single_css: true, import_main_css: false }).unwrap())); reset_class_map(); - assert_debug_snapshot!(ToBTreeSet::from(extract("test.js", r#""use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("@devup-ui/react");function t(){return e.jsxs("div",{children:[e.jsx(r.Box,{_hover:{bg:"blue"},bg:"$text",color:"red",children:"hello"}),e.jsx(r.Text,{typography:"header",children:"typo"}),e.jsx(r.Flex,{as:"section",mt:2,children:"section"})]})}exports.Lib=t;"#, ExtractOption { package: "@devup-ui/react".to_string(), css_dir: "@devup-ui/react".to_string(),single_css:true,import_main_css: false }).unwrap())); + assert_debug_snapshot!(ToBTreeSet::from(extract("test.js", r#""use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),{Box,Text,Flex}=require("@devup-ui/react");function t(){return e.jsxs("div",{children:[e.jsx(Box,{_hover:{bg:"blue"},bg:"$text",color:"red",children:"hello"}),e.jsx(Text,{typography:`header`,children:"typo"}),e.jsx(Flex,{as:"section",mt:2,children:"section"})]})}exports.Lib=t;"#, ExtractOption { package: "@devup-ui/react".to_string(), css_dir: "@devup-ui/react".to_string(), single_css: true, import_main_css: false }).unwrap())); reset_class_map(); - assert_debug_snapshot!(ToBTreeSet::from(extract("test.js", r#""use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("@devup-ui/react");function t(){return e.jsxs("div",{children:[e.jsx(r.Box,{_hover:{bg:"blue"},bg:"$text",color:"red",children:"hello"}),e.jsx(r.Text,{typography:`header`,children:"typo"}),e.jsx(r.Flex,{as:"section",mt:2,children:"section"})]})}exports.Lib=t;"#, ExtractOption { package: "@devup-ui/react".to_string(), css_dir: "@devup-ui/react".to_string(),single_css:true,import_main_css: false }).unwrap())); + assert_debug_snapshot!(ToBTreeSet::from(extract("test.js", r#""use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),{Box,Text,Flex}=require("@devup-ui/react");function t(){return e.jsxs("div",{children:[e.jsx(Box,{["_hover"]:{bg:"blue"},bg:"$text",color:"red",children:"hello"}),e.jsx(Text,{typography:`header`,children:"typo"}),e.jsx(Flex,{as:"section",mt:2,children:"section"})]})}exports.Lib=t;"#, ExtractOption { package: "@devup-ui/react".to_string(), css_dir: "@devup-ui/react".to_string(), single_css: true, import_main_css: false }).unwrap())); } #[test] @@ -3424,11 +3706,28 @@ e(o, { className: "a", bg: variable, style: { color: "blue" }, ...props }) "test.jsx", r#"import {Flex} from '@devup-ui/core' + "#, + ExtractOption { package: "@devup-ui/core".to_string(), css_dir: "@devup-ui/core".to_string(), single_css: true, import_main_css: false } + ) + .unwrap() + )); + } + + #[test] + #[serial] + fn with_prefix() { + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.jsx", + r#"import {Flex} from '@devup-ui/core' + "#, ExtractOption { package: "@devup-ui/core".to_string(), css_dir: "@devup-ui/core".to_string(), - single_css: true,import_main_css: false, + single_css: true, + import_main_css: false } ) .unwrap() @@ -5291,6 +5590,23 @@ export { ) .unwrap() )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.jsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: true, + import_main_css: false + } + ) + .unwrap() + )); } #[test] @@ -6721,4 +7037,46 @@ keyframes({ .unwrap() )); } + + #[test] + #[serial] + fn import_main_css() { + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: false, + import_main_css: true + } + ) + .unwrap() + )); + } + + #[test] + #[serial] + fn optimize_multi_css_value() { + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: false, + import_main_css: false + } + ) + .unwrap() + )); + } } diff --git a/libs/extractor/src/prop_modify_utils.rs b/libs/extractor/src/prop_modify_utils.rs index 990ce197..96b3553b 100644 --- a/libs/extractor/src/prop_modify_utils.rs +++ b/libs/extractor/src/prop_modify_utils.rs @@ -3,7 +3,6 @@ use crate::gen_class_name::gen_class_names; use crate::gen_style::gen_styles; use oxc_allocator::CloneIn; use oxc_ast::AstBuilder; -use oxc_ast::ast::JSXAttributeItem::Attribute; use oxc_ast::ast::JSXAttributeName::Identifier; use oxc_ast::ast::{ Expression, JSXAttributeItem, JSXAttributeValue, LogicalOperator, ObjectPropertyKind, @@ -18,6 +17,7 @@ pub fn modify_prop_object<'a>( styles: &mut [ExtractStyleProp<'a>], style_order: Option, style_vars: Option>, + props_prop: Option>, filename: Option<&str>, ) { let mut class_name_prop = None; @@ -28,19 +28,17 @@ pub fn modify_prop_object<'a>( match prop { ObjectPropertyKind::ObjectProperty(attr) => { if let PropertyKey::StaticIdentifier(ident) = &attr.key { - match ident.name.as_str() { - "className" => { - class_name_prop = Some(attr.value.clone_in(ast_builder.allocator)); - continue; - } - "style" => { - style_prop = Some(attr.value.clone_in(ast_builder.allocator)); - continue; - } - _ => {} + let name = ident.name.as_str(); + if name == "className" { + class_name_prop = Some(attr.value.clone_in(ast_builder.allocator)); + } else if name == "style" { + style_prop = Some(attr.value.clone_in(ast_builder.allocator)); + } else { + props.insert(idx, ObjectPropertyKind::ObjectProperty(attr)); } + } else { + props.insert(idx, ObjectPropertyKind::ObjectProperty(attr)); } - props.insert(idx, ObjectPropertyKind::ObjectProperty(attr)); } ObjectPropertyKind::SpreadProperty(spread) => { spread_props.push(spread.argument.clone_in(ast_builder.allocator)); @@ -85,6 +83,12 @@ pub fn modify_prop_object<'a>( false, )); } + if let Some(ex) = props_prop { + props.push( + ast_builder + .object_property_kind_spread_property(SPAN, ex.clone_in(ast_builder.allocator)), + ); + } } /// modify JSX props pub fn modify_props<'a>( @@ -93,6 +97,7 @@ pub fn modify_props<'a>( styles: &mut [ExtractStyleProp<'a>], style_order: Option, style_vars: Option>, + props_prop: Option>, filename: Option<&str>, ) { let mut class_name_prop = None; @@ -101,31 +106,31 @@ pub fn modify_props<'a>( for idx in (0..props.len()).rev() { let prop = props.remove(idx); match prop { - Attribute(attr) => { + JSXAttributeItem::Attribute(attr) => { if let Identifier(ident) = &attr.name && let Some(value) = &attr.value && (ident.name == "className" || ident.name == "style") { - let value = match &value { - JSXAttributeValue::ExpressionContainer(container) => container + let mut res = None; + + if let JSXAttributeValue::ExpressionContainer(container) = &value { + res = container .expression .as_expression() - .map(|expression| expression.clone_in(ast_builder.allocator)), - JSXAttributeValue::StringLiteral(literal) => { - Some(ast_builder.expression_string_literal(SPAN, literal.value, None)) - } - _ => None, - }; - - match ident.name.as_str() { - "className" => class_name_prop = value, - "style" => style_prop = value, - _ => unreachable!(), + .map(|expression| expression.clone_in(ast_builder.allocator)); + } else if let JSXAttributeValue::StringLiteral(literal) = &value { + res = + Some(ast_builder.expression_string_literal(SPAN, literal.value, None)); } - - continue; + let name = ident.name.as_str(); + if name == "className" { + class_name_prop = res; + } else if name == "style" { + style_prop = res; + } + } else { + props.insert(idx, JSXAttributeItem::Attribute(attr)); } - props.insert(idx, Attribute(attr)); } JSXAttributeItem::SpreadAttribute(spread) => { spread_props.push(spread.argument.clone_in(ast_builder.allocator)); @@ -165,6 +170,14 @@ pub fn modify_props<'a>( Some(ast_builder.jsx_attribute_value_expression_container(SPAN, ex.into())), )); } + if let Some(props_prop) = props_prop { + props.push( + ast_builder.jsx_attribute_item_spread_attribute( + SPAN, + props_prop.clone_in(ast_builder.allocator), + ), + ); + } } pub fn get_class_name_expression<'a>( @@ -270,59 +283,55 @@ fn merge_string_expressions<'a>( let mut other_expressions = vec![]; let mut prev_str = String::new(); for ex in expressions.iter() { - match ex { - Expression::StringLiteral(literal) => { + if let Expression::StringLiteral(literal) = ex { + let target_prev = prev_str.trim(); + let target = literal.value.trim(); + prev_str = format!( + "{}{}{}", + target_prev, + if target_prev.is_empty() { "" } else { " " }, + target + ); + } else if let Expression::TemplateLiteral(template) = ex { + for (idx, q) in template.quasis.iter().enumerate() { let target_prev = prev_str.trim(); - let target = literal.value.trim(); - prev_str = format!( - "{}{}{}", - target_prev, - if target_prev.is_empty() { "" } else { " " }, - target - ); - } - Expression::TemplateLiteral(template) => { - for (idx, q) in template.quasis.iter().enumerate() { - let target_prev = prev_str.trim(); - let target = q.value.raw.trim(); - if idx < template.quasis.len() - 1 { - string_literals.push(format!( - "{}{}{}{}{}", - if !other_expressions.is_empty() || idx > 0 { - " " - } else { - "" - }, - target_prev, - if !target_prev.is_empty() { " " } else { "" }, - target, - if !target.is_empty() && !target.ends_with("typo-") { - " " - } else { - "" - } - )); - } else { - prev_str = q.value.raw.trim().to_string(); - } + let target = q.value.raw.trim(); + if idx < template.quasis.len() - 1 { + string_literals.push(format!( + "{}{}{}{}{}", + if !other_expressions.is_empty() || idx > 0 { + " " + } else { + "" + }, + target_prev, + if !target_prev.is_empty() { " " } else { "" }, + target, + if !target.is_empty() && !target.ends_with("typo-") { + " " + } else { + "" + } + )); + } else { + prev_str = q.value.raw.trim().to_string(); } - other_expressions.extend(template.expressions.clone_in(ast_builder.allocator)); - } - ex => { - let target_prev = prev_str.trim(); - string_literals.push(format!( - "{}{}{}", - if !other_expressions.is_empty() { - " " - } else { - "" - }, - target_prev, - if !target_prev.is_empty() { " " } else { "" } - )); - other_expressions.push(ex.clone_in(ast_builder.allocator)); - prev_str = String::new(); } + other_expressions.extend(template.expressions.clone_in(ast_builder.allocator)); + } else { + let target_prev = prev_str.trim(); + string_literals.push(format!( + "{}{}{}", + if !other_expressions.is_empty() { + " " + } else { + "" + }, + target_prev, + if !target_prev.is_empty() { " " } else { "" } + )); + other_expressions.push(ex.clone_in(ast_builder.allocator)); + prev_str = String::new(); } } string_literals.push(format!( @@ -338,23 +347,24 @@ fn merge_string_expressions<'a>( )); } + let q = oxc_allocator::Vec::from_iter_in( + string_literals.iter().enumerate().map(|(idx, s)| { + let tail = idx == string_literals.len() - 1; + ast_builder.template_element( + SPAN, + TemplateElementValue { + raw: ast_builder.atom(s), + cooked: None, + }, + tail, + ) + }), + ast_builder.allocator, + ); Some( ast_builder.expression_template_literal( SPAN, - oxc_allocator::Vec::from_iter_in( - string_literals.iter().enumerate().map(|(idx, s)| { - let tail = idx == string_literals.len() - 1; - ast_builder.template_element( - SPAN, - TemplateElementValue { - raw: ast_builder.atom(s), - cooked: None, - }, - tail, - ) - }), - ast_builder.allocator, - ), + q, oxc_allocator::Vec::from_iter_in( other_expressions .into_iter() @@ -419,63 +429,67 @@ pub fn convert_style_vars<'a>( for idx in (0..obj.properties.len()).rev() { let mut prop = obj.properties.remove(idx); - if let ObjectPropertyKind::ObjectProperty(prop) = &mut prop { - let name = match &prop.key { - PropertyKey::StaticIdentifier(ident) => ident.name, - PropertyKey::StringLiteral(ident) => ident.value, - etc => { - obj.properties.insert( - idx, - ast_builder.object_property_kind_object_property( + if let ObjectPropertyKind::ObjectProperty(p) = &mut prop { + let name = if let PropertyKey::StaticIdentifier(ident) = &p.key { + Some(ident.name) + } else if let PropertyKey::StringLiteral(ident) = &p.key { + Some(ident.value) + } else { + obj.properties.insert( + idx, + ast_builder.object_property_kind_object_property( + SPAN, + PropertyKind::Init, + PropertyKey::TemplateLiteral(ast_builder.alloc_template_literal( SPAN, - PropertyKind::Init, - PropertyKey::TemplateLiteral(ast_builder.alloc_template_literal( - SPAN, - oxc_allocator::Vec::from_array_in( - [ - ast_builder.template_element( - SPAN, - TemplateElementValue { - raw: ast_builder.atom("--"), - cooked: None, - }, - false, - ), - ast_builder.template_element( - SPAN, - TemplateElementValue { - raw: ast_builder.atom(""), - cooked: None, - }, - true, - ), - ], - ast_builder.allocator, - ), - oxc_allocator::Vec::from_array_in( - [etc.to_expression().clone_in(ast_builder.allocator)], - ast_builder.allocator, - ), - )), - prop.value.clone_in(ast_builder.allocator), - false, - false, - true, - ), - ); - continue; - } + oxc_allocator::Vec::from_array_in( + [ + ast_builder.template_element( + SPAN, + TemplateElementValue { + raw: ast_builder.atom("--"), + cooked: None, + }, + false, + ), + ast_builder.template_element( + SPAN, + TemplateElementValue { + raw: ast_builder.atom(""), + cooked: None, + }, + true, + ), + ], + ast_builder.allocator, + ), + oxc_allocator::Vec::from_array_in( + [p.key.to_expression().clone_in(ast_builder.allocator)], + ast_builder.allocator, + ), + )), + p.value.clone_in(ast_builder.allocator), + false, + false, + true, + ), + ); + None }; - if !name.starts_with("--") { - prop.key = PropertyKey::StringLiteral(ast_builder.alloc_string_literal( - SPAN, - ast_builder.atom(&format!("--{name}")), - None, - )); + if let Some(name) = name { + if !name.starts_with("--") { + p.key = PropertyKey::StringLiteral(ast_builder.alloc_string_literal( + SPAN, + ast_builder.atom(&format!("--{name}")), + None, + )); + } + obj.properties.insert(idx, prop); } + } else { + obj.properties.insert(idx, prop); } - obj.properties.insert(idx, prop); } } style_vars diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-10.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-10.snap new file mode 100644 index 00000000..089ac336 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-10.snap @@ -0,0 +1,8 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: {}, + code: "<>{b ?
: undefined};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-11.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-11.snap new file mode 100644 index 00000000..870125a2 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-11.snap @@ -0,0 +1,8 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: {}, + code: "<>{b ?
: null};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-12.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-12.snap new file mode 100644 index 00000000..eb065ebd --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-12.snap @@ -0,0 +1,8 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: {}, + code: "<>{b ? null : undefined};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-13.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-13.snap new file mode 100644 index 00000000..8cd8d0ca --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-13.snap @@ -0,0 +1,27 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "height", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "width", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n<>{};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-14.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-14.snap new file mode 100644 index 00000000..e5af20a4 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-14.snap @@ -0,0 +1,27 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "height", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "width", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n<>{b ? :
};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-15.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-15.snap new file mode 100644 index 00000000..4fe436bc --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-15.snap @@ -0,0 +1,27 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "height", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "width", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n<>{{\n\tA:
,\n\tB:
,\n\tC: ,\n\tD: ,\n\t[key]:
,\n\t...rest\n}[key]};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-16.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-16.snap new file mode 100644 index 00000000..ddea7c49 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-16.snap @@ -0,0 +1,27 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "height", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "width", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n<>{{\n\tA:
,\n\tB:
,\n\tC: ,\n\tD: ,\n\t[\"key\"]:
,\n\t...rest\n}[\"key\"]};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-17.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-17.snap new file mode 100644 index 00000000..00326863 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-17.snap @@ -0,0 +1,27 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "height", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "width", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n<>{b === 1 ?
:
};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-18.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-18.snap new file mode 100644 index 00000000..37729f43 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-18.snap @@ -0,0 +1,27 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "height", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "width", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n<>{[
,
][b]};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-19.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-19.snap new file mode 100644 index 00000000..37729f43 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-19.snap @@ -0,0 +1,27 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "height", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "width", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n<>{[
,
][b]};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-20.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-20.snap new file mode 100644 index 00000000..3867914d --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-20.snap @@ -0,0 +1,18 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "width", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n<>{};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-21.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-21.snap new file mode 100644 index 00000000..c6cd67af --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-21.snap @@ -0,0 +1,18 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "width", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n<>{};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-6.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-6.snap new file mode 100644 index 00000000..971c4fdc --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-6.snap @@ -0,0 +1,8 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: {}, + code: "<>{b ?
:
};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-7.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-7.snap new file mode 100644 index 00000000..7520a855 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-7.snap @@ -0,0 +1,18 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "width", + value: "100%", + level: 0, + selector: None, + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n<>{b ?
:
};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-8.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-8.snap new file mode 100644 index 00000000..e5329bf7 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-8.snap @@ -0,0 +1,8 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: {}, + code: "<>{b ? undefined :
};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__convert_tag-9.snap b/libs/extractor/src/snapshots/extractor__tests__convert_tag-9.snap new file mode 100644 index 00000000..32fb70e7 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__convert_tag-9.snap @@ -0,0 +1,8 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: {}, + code: "<>{b ? null :
};\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_conditional_style_props-10.snap b/libs/extractor/src/snapshots/extractor__tests__extract_conditional_style_props-10.snap new file mode 100644 index 00000000..19a56861 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_conditional_style_props-10.snap @@ -0,0 +1,8 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import { Box } from \"@devup-ui/core\";\n;\n\"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: {}, + code: "
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__import_main_css.snap b/libs/extractor/src/snapshots/extractor__tests__import_main_css.snap new file mode 100644 index 00000000..cf7f92db --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__import_main_css.snap @@ -0,0 +1,27 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: false, import_main_css: true\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "margin", + value: "8px", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "padding", + value: "4px", + level: 0, + selector: None, + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\nimport \"@devup-ui/core/devup-ui-0.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__optimize_multi_css_value.snap b/libs/extractor/src/snapshots/extractor__tests__optimize_multi_css_value.snap new file mode 100644 index 00000000..323eee18 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__optimize_multi_css_value.snap @@ -0,0 +1,18 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: false, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "font-family", + value: "Roboto,Arial,sans-serif", + level: 0, + selector: None, + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui-0.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__style_variables-11.snap b/libs/extractor/src/snapshots/extractor__tests__style_variables-11.snap new file mode 100644 index 00000000..6828dd3e --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__style_variables-11.snap @@ -0,0 +1,8 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.jsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: {}, + code: "
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-5.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-5.snap new file mode 100644 index 00000000..9ed0b70d --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-5.snap @@ -0,0 +1,63 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.js\",\nr#\"\"use strict\";Object.defineProperty(exports,Symbol.toStringTag,{value:\"Module\"});const e=require(\"react/jsx-runtime\"),{Box,Text,Flex}=require(\"@devup-ui/react\");function t(){return e.jsxs(\"div\",{children:[e.jsx(Box,{_hover:{bg:\"blue\"},bg:\"$text\",color:\"red\",children:\"hello\"}),e.jsx(Text,{typography:`header`,children:\"typo\"}),e.jsx(Flex,{as:\"section\",mt:2,children:\"section\"})]})}exports.Lib=t;\"#,\nExtractOption\n{\n package: \"@devup-ui/react\".to_string(), css_dir:\n \"@devup-ui/react\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "background", + value: "$text", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "background", + value: "blue", + level: 0, + selector: Some( + Selector( + "&:hover", + ), + ), + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "color", + value: "red", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "display", + value: "flex", + level: 0, + selector: None, + style_order: Some( + 0, + ), + }, + ), + Static( + ExtractStaticStyle { + property: "margin-top", + value: "8px", + level: 0, + selector: None, + style_order: None, + }, + ), + Typography( + "header", + ), + }, + code: "\"use strict\";\nimport \"@devup-ui/react/devup-ui.css\";\nObject.defineProperty(exports, Symbol.toStringTag, { value: \"Module\" });\nconst e = require(\"react/jsx-runtime\"), { Box, Text, Flex } = require(\"@devup-ui/react\");\nfunction t() {\n\treturn e.jsxs(\"div\", { children: [\n\t\te.jsx(\"div\", {\n\t\t\tchildren: \"hello\",\n\t\t\tclassName: \"a b c\"\n\t\t}),\n\t\te.jsx(\"span\", {\n\t\t\tchildren: \"typo\",\n\t\t\tclassName: \"typo-header\"\n\t\t}),\n\t\te.jsx(\"section\", {\n\t\t\tchildren: \"section\",\n\t\t\tclassName: \"d e\"\n\t\t})\n\t] });\n}\nexports.Lib = t;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-6.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-6.snap new file mode 100644 index 00000000..162958c2 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-6.snap @@ -0,0 +1,50 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.js\",\nr#\"\"use strict\";Object.defineProperty(exports,Symbol.toStringTag,{value:\"Module\"});const e=require(\"react/jsx-runtime\"),{Box,Text,Flex}=require(\"@devup-ui/react\");function t(){return e.jsxs(\"div\",{children:[e.jsx(Box,{[\"_hover\"]:{bg:\"blue\"},bg:\"$text\",color:\"red\",children:\"hello\"}),e.jsx(Text,{typography:`header`,children:\"typo\"}),e.jsx(Flex,{as:\"section\",mt:2,children:\"section\"})]})}exports.Lib=t;\"#,\nExtractOption\n{\n package: \"@devup-ui/react\".to_string(), css_dir:\n \"@devup-ui/react\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "background", + value: "$text", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "color", + value: "red", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "display", + value: "flex", + level: 0, + selector: None, + style_order: Some( + 0, + ), + }, + ), + Static( + ExtractStaticStyle { + property: "margin-top", + value: "8px", + level: 0, + selector: None, + style_order: None, + }, + ), + Typography( + "header", + ), + }, + code: "\"use strict\";\nimport \"@devup-ui/react/devup-ui.css\";\nObject.defineProperty(exports, Symbol.toStringTag, { value: \"Module\" });\nconst e = require(\"react/jsx-runtime\"), { Box, Text, Flex } = require(\"@devup-ui/react\");\nfunction t() {\n\treturn e.jsxs(\"div\", { children: [\n\t\te.jsx(\"div\", {\n\t\t\t[\"_hover\"]: { bg: \"blue\" },\n\t\t\tchildren: \"hello\",\n\t\t\tclassName: \"a b\"\n\t\t}),\n\t\te.jsx(\"span\", {\n\t\t\tchildren: \"typo\",\n\t\t\tclassName: \"typo-header\"\n\t\t}),\n\t\te.jsx(\"section\", {\n\t\t\tchildren: \"section\",\n\t\t\tclassName: \"c d\"\n\t\t})\n\t] });\n}\nexports.Lib = t;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-6.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-6.snap new file mode 100644 index 00000000..febee9d1 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-6.snap @@ -0,0 +1,18 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.js\",\nr#\"import { jsx as e } from \"react/jsx-runtime\";\n import { Box as o } from \"@devup-ui/core\";\n e(o, { as: b ? \"div\" : \"section\", className: \"a\", bg: variable, style: { color: \"blue\" }, props: { animate: { duration: 1 } } })\n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Dynamic( + ExtractDynamicStyle { + property: "background", + level: 0, + identifier: "variable", + selector: None, + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\nimport { jsx as e } from \"react/jsx-runtime\";\ne(b ? \"div\" : \"section\", {\n\tclassName: \"a a\",\n\tstyle: {\n\t\t...{ \"--b\": variable },\n\t\t...{ color: \"blue\" }\n\t},\n\t...{ animate: { duration: 1 } }\n});\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-7.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-7.snap new file mode 100644 index 00000000..3352f742 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-7.snap @@ -0,0 +1,18 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.js\",\nr#\"import { jsx as e } from \"react/jsx-runtime\";\n import { Box as o } from \"@devup-ui/core\";\n e(o, { as: Variable, className: \"a\", bg: variable, style: { color: \"blue\" }, props: { animate: { duration: 1 } } })\n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Dynamic( + ExtractDynamicStyle { + property: "background", + level: 0, + identifier: "variable", + selector: None, + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\nimport { jsx as e } from \"react/jsx-runtime\";\ne(Variable, {\n\tclassName: \"a a\",\n\tstyle: {\n\t\t...{ \"--b\": variable },\n\t\t...{ color: \"blue\" }\n\t},\n\t...{ animate: { duration: 1 } }\n});\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-8.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-8.snap new file mode 100644 index 00000000..3d33ce7f --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-8.snap @@ -0,0 +1,18 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.js\",\nr#\"import { jsx as e } from \"react/jsx-runtime\";\n import { Box as o } from \"@devup-ui/core\";\n e(o, { as: b ? null : undefined, className: \"a\", bg: variable, style: { color: \"blue\" }, props: { animate: { duration: 1 } } })\n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Dynamic( + ExtractDynamicStyle { + property: "background", + level: 0, + identifier: "variable", + selector: None, + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\nimport { jsx as e } from \"react/jsx-runtime\";\ne(b ? null : undefined, {\n\tclassName: \"a a\",\n\tstyle: {\n\t\t...{ \"--b\": variable },\n\t\t...{ color: \"blue\" }\n\t},\n\t...{ animate: { duration: 1 } }\n});\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__with_prefix.snap b/libs/extractor/src/snapshots/extractor__tests__with_prefix.snap new file mode 100644 index 00000000..a94f5195 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__with_prefix.snap @@ -0,0 +1,47 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.jsx\",\nr#\"import {Flex} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false,\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "-moz-tab-size", + value: "16px", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "-ms-border-radius", + value: "16px", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "-webkit-line-clamp", + value: "4", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "display", + value: "flex", + level: 0, + selector: None, + style_order: Some( + 0, + ), + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/visit.rs b/libs/extractor/src/visit.rs index 6872ad28..a71c0bbf 100644 --- a/libs/extractor/src/visit.rs +++ b/libs/extractor/src/visit.rs @@ -1,3 +1,4 @@ +use crate::as_visit::AsVisitor; use crate::component::ExportVariableKind; use crate::css_utils::{css_to_style, keyframes_to_keyframes_style, optimize_css_block}; use crate::extract_style::ExtractStyleProperty; @@ -23,7 +24,7 @@ use oxc_ast::ast::JSXAttributeItem::Attribute; use oxc_ast::ast::JSXAttributeName::Identifier; use oxc_ast::ast::{ Argument, BindingPatternKind, CallExpression, Expression, ImportDeclaration, - ImportOrExportKind, JSXAttributeValue, JSXElement, Program, PropertyKey, Statement, + ImportOrExportKind, JSXAttributeValue, JSXChild, JSXElement, Program, PropertyKey, Statement, VariableDeclarator, WithClause, }; use oxc_ast_visit::VisitMut; @@ -154,91 +155,85 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { } }; } else { - *it = match util_type.as_ref() { - UtilType::Css => { - let ExtractResult { - mut styles, - style_order, - .. - } = extract_style_from_expression( + let r = util_type.as_ref(); + *it = if let UtilType::Css = r { + let ExtractResult { + mut styles, + style_order, + .. + } = extract_style_from_expression( + &self.ast, + None, + if let Argument::SpreadElement(spread) = &mut call.arguments[0] { + &mut spread.argument + } else { + call.arguments[0].to_expression_mut() + }, + 0, + &None, + ); + + if styles.is_empty() { + self.ast + .expression_string_literal(SPAN, self.ast.atom(""), None) + } else { + // css can not reachable + let class_name = gen_class_names( &self.ast, - None, - if let Argument::SpreadElement(spread) = &mut call.arguments[0] { - &mut spread.argument - } else { - call.arguments[0].to_expression_mut() - }, - 0, - &None, + &mut styles, + style_order, + self.split_filename.as_deref(), ); - if styles.is_empty() { + // already set style order + self.styles + .extend(styles.into_iter().flat_map(|ex| ex.extract())); + if let Some(cls) = class_name { + cls + } else { self.ast .expression_string_literal(SPAN, self.ast.atom(""), None) - } else { - // css can not reachable - let class_name = gen_class_names( - &self.ast, - &mut styles, - style_order, - self.split_filename.as_deref(), - ); - - // already set style order - self.styles - .extend(styles.into_iter().flat_map(|ex| ex.extract())); - if let Some(cls) = class_name { - cls - } else { - self.ast.expression_string_literal( - SPAN, - self.ast.atom(""), - None, - ) - } } } - UtilType::Keyframes => { - let KeyframesExtractResult { keyframes } = - extract_keyframes_from_expression( - &self.ast, - if let Argument::SpreadElement(spread) = &mut call.arguments[0] - { - &mut spread.argument - } else { - call.arguments[0].to_expression_mut() - }, - ); - - let name = keyframes - .extract(self.split_filename.as_deref()) - .to_string(); - self.styles.insert(ExtractStyleValue::Keyframes(keyframes)); - self.ast - .expression_string_literal(SPAN, self.ast.atom(&name), None) - } - UtilType::GlobalCss => { - let GlobalExtractResult { - styles, - style_order, - } = extract_global_style_from_expression( + } else if let UtilType::Keyframes = r { + let KeyframesExtractResult { keyframes } = + extract_keyframes_from_expression( &self.ast, if let Argument::SpreadElement(spread) = &mut call.arguments[0] { &mut spread.argument } else { call.arguments[0].to_expression_mut() }, - &self.filename, ); - // already set style order - self.styles.extend(styles.into_iter().flat_map(|mut ex| { - if let ExtractStyleProp::Static(css) = &mut ex { - css.set_style_order(style_order.unwrap_or(0)); - } - ex.extract() - })); - self.ast.expression_identifier(SPAN, self.ast.atom("")) - } + + let name = keyframes + .extract(self.split_filename.as_deref()) + .to_string(); + self.styles.insert(ExtractStyleValue::Keyframes(keyframes)); + self.ast + .expression_string_literal(SPAN, self.ast.atom(&name), None) + } else { + // global + let GlobalExtractResult { + styles, + style_order, + } = extract_global_style_from_expression( + &self.ast, + if let Argument::SpreadElement(spread) = &mut call.arguments[0] { + &mut spread.argument + } else { + call.arguments[0].to_expression_mut() + }, + &self.filename, + ); + // already set style order + self.styles.extend(styles.into_iter().flat_map(|mut ex| { + if let ExtractStyleProp::Static(css) = &mut ex { + css.set_style_order(style_order.unwrap_or(0)); + } + ex.extract() + })); + self.ast.expression_identifier(SPAN, self.ast.atom("")) } } } @@ -252,56 +247,49 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { .iter() .map(|quasi| quasi.value.raw.to_string()) .collect::(); - match css_type.as_ref() { - UtilType::Css => { - let styles = css_to_style(&css_str, 0, &None); - let class_name = gen_class_names( - &self.ast, - &mut styles - .iter() - .map(|ex| { - ExtractStyleProp::Static(ExtractStyleValue::Static(ex.clone())) - }) - .collect::>(), - None, - self.split_filename.as_deref(), - ); + let r = css_type.as_ref(); + *it = if let UtilType::Css = r { + let styles = css_to_style(&css_str, 0, &None); + let class_name = gen_class_names( + &self.ast, + &mut styles + .iter() + .map(|ex| ExtractStyleProp::Static(ExtractStyleValue::Static(ex.clone()))) + .collect::>(), + None, + self.split_filename.as_deref(), + ); - if let Some(cls) = class_name { - *it = cls; - } else { - *it = self - .ast - .expression_string_literal(SPAN, self.ast.atom(""), None); - } - // already set style order - self.styles - .extend(styles.into_iter().map(ExtractStyleValue::Static)); + self.styles + .extend(styles.into_iter().map(ExtractStyleValue::Static)); + if let Some(cls) = class_name { + cls + } else { + self.ast + .expression_string_literal(SPAN, self.ast.atom(""), None) } - UtilType::Keyframes => { - let keyframes = ExtractKeyframes { - keyframes: keyframes_to_keyframes_style(&css_str), - }; - let name = keyframes - .extract(self.split_filename.as_deref()) - .to_string(); + // already set style order + } else if let UtilType::Keyframes = r { + let keyframes = ExtractKeyframes { + keyframes: keyframes_to_keyframes_style(&css_str), + }; + let name = keyframes + .extract(self.split_filename.as_deref()) + .to_string(); - self.styles.insert(ExtractStyleValue::Keyframes(keyframes)); - *it = self - .ast - .expression_string_literal(SPAN, self.ast.atom(&name), None); - } - UtilType::GlobalCss => { - let optimized_css = optimize_css_block(&css_str); - if !optimized_css.is_empty() { - let css = ExtractStyleValue::Css(ExtractCss { - css: optimized_css, - file: self.filename.clone(), - }); - self.styles.insert(css); - } - *it = self.ast.expression_identifier(SPAN, self.ast.atom("")); + self.styles.insert(ExtractStyleValue::Keyframes(keyframes)); + self.ast + .expression_string_literal(SPAN, self.ast.atom(&name), None) + } else { + let optimized_css = optimize_css_block(&css_str); + if !optimized_css.is_empty() { + let css = ExtractStyleValue::Css(ExtractCss { + css: optimized_css, + file: self.filename.clone(), + }); + self.styles.insert(css); } + self.ast.expression_identifier(SPAN, self.ast.atom("")) } } } @@ -346,6 +334,7 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { tag: _tag, style_order, style_vars, + props, } = extract_style_from_expression( &self.ast, None, @@ -381,6 +370,7 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { &mut props_styles, style_order, style_vars, + props, self.split_filename.as_deref(), ); } @@ -445,10 +435,7 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { .insert(import.local.to_string(), import.imported.to_string()); } } - return; - } - - if it.source.value == self.package + } else if it.source.value == self.package && let Some(specifiers) = &mut it.specifiers { for i in (0..specifiers.len()).rev() { @@ -503,19 +490,16 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { } } } - return; + } else { + walk_import_declaration(self, it); } - - walk_import_declaration(self, it); } fn visit_jsx_element(&mut self, elem: &mut JSXElement<'a>) { walk_jsx_element(self, elem); // after run to convert css literal - - let opening_element = &mut elem.opening_element; - let component_name = &opening_element.name.to_string(); + let component_name = &elem.opening_element.name.to_string(); if let Some(kind) = self.imports.get(component_name) { - let attrs = &mut opening_element.attributes; + let attrs = &mut elem.opening_element.attributes; let mut tag_name = self.ast .expression_string_literal(SPAN, kind.to_tag().unwrap_or("div"), None); @@ -525,6 +509,7 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { let mut duplicate_set = HashSet::new(); let mut style_order = None; let mut style_vars = None; + let mut props = None; for i in (0..attrs.len()).rev() { let mut attr = attrs.remove(i); if let Attribute(attr) = &mut attr @@ -533,36 +518,37 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { { let property_name = name.name.to_string(); for name in disassemble_property(&property_name) { - if duplicate_set.contains(&name) { - continue; - } - duplicate_set.insert(name.clone()); - if &property_name == "styleOrder" { - style_order = jsx_expression_to_number(attr.value.as_ref().unwrap()) - .map(|n| n as u8); - continue; - } - if property_name == "styleVars" { - if let Some(value) = attr.value.as_ref() - && let JSXAttributeValue::ExpressionContainer(expr) = value - && let Some(expression) = expr.expression.as_expression() - { - style_vars = Some(expression.clone_in(self.ast.allocator)); + if !duplicate_set.contains(&name) { + duplicate_set.insert(name.clone()); + if property_name == "styleOrder" { + style_order = + jsx_expression_to_number(attr.value.as_ref().unwrap()) + .map(|n| n as u8); + } else if property_name == "props" { + if let Some(value) = attr.value.as_ref() + && let JSXAttributeValue::ExpressionContainer(expr) = value + && let Some(expression) = expr.expression.as_expression() + { + props = Some(expression.clone_in(self.ast.allocator)); + } + } else if property_name == "styleVars" { + if let Some(value) = attr.value.as_ref() + && let JSXAttributeValue::ExpressionContainer(expr) = value + && let Some(expression) = expr.expression.as_expression() + { + style_vars = Some(expression.clone_in(self.ast.allocator)); + } + } else if let Some(at) = &mut attr.value { + let ExtractResult { styles, tag, .. } = + extract_style_from_jsx(&self.ast, &name, at); + props_styles.extend(styles.into_iter().rev()); + tag_name = tag.unwrap_or(tag_name); } - continue; - } - - if let Some(at) = &mut attr.value { - let ExtractResult { styles, tag, .. } = - extract_style_from_jsx(&self.ast, &name, at); - props_styles.extend(styles.into_iter().rev()); - tag_name = tag.unwrap_or(tag_name); - continue; } } - continue; + } else { + attrs.insert(i, attr); } - attrs.insert(i, attr); } kind.extract() @@ -576,6 +562,7 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { &mut props_styles, style_order, style_vars, + props, self.split_filename.as_deref(), ); @@ -585,19 +572,52 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { .for_each(|style| self.styles.extend(style.extract())); // modify!! - if let Some(tag) = match tag_name { - Expression::StringLiteral(str) => Some(str.value.as_str()), - Expression::TemplateLiteral(literal) => Some(literal.quasis[0].value.raw.as_str()), - _ => None, + if let Some(tag) = if let Expression::StringLiteral(str) = tag_name { + Some(str.value.as_str()) + } else if let Expression::TemplateLiteral(literal) = tag_name { + Some(literal.quasis[0].value.raw.as_str()) + } else { + let mut v = AsVisitor::new(self.ast.allocator, elem.clone_in(self.ast.allocator)); + let mut el = self.ast.expression_statement(SPAN, tag_name); + v.visit_expression_statement(&mut el); + let mut children = oxc_allocator::Vec::new_in(self.ast.allocator); + children.push(JSXChild::ExpressionContainer( + self.ast.alloc_jsx_expression_container( + SPAN, + el.expression.clone_in(self.ast.allocator).into(), + ), + )); + *elem = self.ast.jsx_element( + SPAN, + self.ast.alloc_jsx_opening_element( + SPAN, + self.ast + .jsx_element_name_identifier(SPAN, self.ast.atom("")), + Some(self.ast.alloc_ts_type_parameter_instantiation( + SPAN, + oxc_allocator::Vec::new_in(self.ast.allocator), + )), + oxc_allocator::Vec::new_in(self.ast.allocator), + ), + children, + Some( + self.ast.alloc_jsx_closing_element( + SPAN, + self.ast + .jsx_element_name_identifier(SPAN, self.ast.atom("")), + ), + ), + ); + None } { let ident = self .ast .jsx_element_name_identifier(SPAN, self.ast.atom(tag)); + elem.opening_element.name = ident.clone_in(self.ast.allocator); if let Some(el) = &mut elem.closing_element { - el.name = ident.clone_in(self.ast.allocator); + el.name = ident } - opening_element.name = ident; } } } diff --git a/libs/sheet/Cargo.toml b/libs/sheet/Cargo.toml index 641cb644..1866ccd7 100644 --- a/libs/sheet/Cargo.toml +++ b/libs/sheet/Cargo.toml @@ -5,14 +5,14 @@ edition = "2024" [dependencies] css = { path = "../css" } -serde = { version = "1.0.219", features = ["derive"] } +serde = { version = "1.0.225", features = ["derive"] } regex = "1.11.2" once_cell = "1.21.3" extractor = { path = "../extractor" } [dev-dependencies] insta = "1.43.2" -serde_json = "1.0.143" +serde_json = "1.0.145" criterion = { version = "0.7", features = ["html_reports"] } rstest = "0.26.1" diff --git a/libs/sheet/src/lib.rs b/libs/sheet/src/lib.rs index 045871ce..a763789c 100644 --- a/libs/sheet/src/lib.rs +++ b/libs/sheet/src/lib.rs @@ -284,25 +284,18 @@ impl StyleSheet { for style in styles.iter() { match style { ExtractStyleValue::Static(st) => { - let (cls, _) = - match style.extract(if !single_css { Some(filename) } else { None }) { - Some(StyleProperty::ClassName(cls)) => (cls, None), - Some(StyleProperty::Variable { - class_name, - variable_name, - .. - }) => (class_name, Some(variable_name)), - None => continue, - }; - if self.add_property( - &cls, - st.property(), - st.level(), - st.value(), - st.selector(), - st.style_order(), - if !single_css { Some(filename) } else { None }, - ) { + if let Some(StyleProperty::ClassName(cls)) = + style.extract(if !single_css { Some(filename) } else { None }) + && self.add_property( + &cls, + st.property(), + st.level(), + st.value(), + st.selector(), + st.style_order(), + if !single_css { Some(filename) } else { None }, + ) + { collected = true; if st.style_order() == Some(0) { updated_base_style = true; @@ -310,25 +303,21 @@ impl StyleSheet { } } ExtractStyleValue::Dynamic(dy) => { - let (cls, variable) = - match style.extract(if !single_css { Some(filename) } else { None }) { - Some(StyleProperty::ClassName(cls)) => (cls, None), - Some(StyleProperty::Variable { - class_name, - variable_name, - .. - }) => (class_name, Some(variable_name)), - None => continue, - }; - if self.add_property( - &cls, - dy.property(), - dy.level(), - &format!("var({})", variable.unwrap()), - dy.selector(), - dy.style_order(), - if !single_css { Some(filename) } else { None }, - ) { + if let Some(StyleProperty::Variable { + class_name, + variable_name, + .. + }) = style.extract(if !single_css { Some(filename) } else { None }) + && self.add_property( + &class_name, + dy.property(), + dy.level(), + &format!("var({})", variable_name), + dy.selector(), + dy.style_order(), + if !single_css { Some(filename) } else { None }, + ) + { collected = true; if dy.style_order() == Some(0) { updated_base_style = true; @@ -683,6 +672,7 @@ mod tests { use crate::theme::{ColorTheme, Typography}; use super::*; + use extractor::{ExtractOption, extract}; use insta::assert_debug_snapshot; #[test] @@ -786,6 +776,12 @@ mod tests { assert_debug_snapshot!(sheet.create_css(None, false).split("*/").nth(1).unwrap()); } + #[test] + fn test_import_css() { + let sheet = StyleSheet::default(); + assert_debug_snapshot!(sheet.create_css(Some("index.tsx"), true)); + } + #[test] fn test_create_css() { let mut sheet = StyleSheet::default(); @@ -1731,4 +1727,16 @@ mod tests { assert_debug_snapshot!(css.split("*/").nth(1).unwrap()); } + + #[test] + fn test_update_styles() { + let mut sheet = StyleSheet::default(); + sheet.update_styles(&HashSet::new(), "index.tsx", true); + assert_debug_snapshot!(sheet.create_css(Some("index.tsx"), true)); + + let mut sheet = StyleSheet::default(); + let output = extract("index.tsx", "import {Box,globalCss,keyframes,Flex} from '@devup-ui/core';;keyframes({from:{opacity:0},to:{opacity:1}});;globalCss`div{color:red}`;globalCss({div:{display:flex},imports:['https://test.com/a.css'],fontFaces:[{fontFamily:'Roboto',src:'url(/fonts/Roboto-Regular.ttf)'}]})", ExtractOption { package: "@devup-ui/core".to_string(), css_dir: "@devup-ui/core".to_string(), single_css: true, import_main_css: false }).unwrap(); + sheet.update_styles(&output.styles, "index.tsx", true); + assert_debug_snapshot!(sheet.create_css(None, true).split("*/").nth(1).unwrap()); + } } diff --git a/libs/sheet/src/snapshots/sheet__tests__import_css.snap b/libs/sheet/src/snapshots/sheet__tests__import_css.snap new file mode 100644 index 00000000..636b5729 --- /dev/null +++ b/libs/sheet/src/snapshots/sheet__tests__import_css.snap @@ -0,0 +1,5 @@ +--- +source: libs/sheet/src/lib.rs +expression: "sheet.create_css(Some(\"index.tsx\"), true)" +--- +"@import \"./devup-ui.css\";" diff --git a/libs/sheet/src/snapshots/sheet__tests__update_styles-2.snap b/libs/sheet/src/snapshots/sheet__tests__update_styles-2.snap new file mode 100644 index 00000000..8845739a --- /dev/null +++ b/libs/sheet/src/snapshots/sheet__tests__update_styles-2.snap @@ -0,0 +1,5 @@ +--- +source: libs/sheet/src/lib.rs +expression: "sheet.create_css(None, true).split(\"*/\").nth(1).unwrap()" +--- +"@import \"https://test.com/a.css\";@layer b;@font-face{font-family:Roboto;src:url(/fonts/Roboto-Regular.ttf)}div{color:red}@layer b{div{display:var(--g)}.a{display:flex}}@keyframes b{from{opacity:0}to{opacity:1}}.d{height:var(--e)}.c{width:4px}" diff --git a/libs/sheet/src/snapshots/sheet__tests__update_styles.snap b/libs/sheet/src/snapshots/sheet__tests__update_styles.snap new file mode 100644 index 00000000..636b5729 --- /dev/null +++ b/libs/sheet/src/snapshots/sheet__tests__update_styles.snap @@ -0,0 +1,5 @@ +--- +source: libs/sheet/src/lib.rs +expression: "sheet.create_css(Some(\"index.tsx\"), true)" +--- +"@import \"./devup-ui.css\";"