From 873f596267c9295de4daa54449273f44b0896557 Mon Sep 17 00:00:00 2001 From: owjs3901 Date: Tue, 21 Jan 2025 14:26:18 +0900 Subject: [PATCH] Fix duplicate issue --- .changeset/slimy-walls-melt.md | 5 ++++ libs/css/src/lib.rs | 24 +++++++++++++++++++ libs/extractor/src/extract_style/mod.rs | 8 ++++--- libs/extractor/src/lib.rs | 17 +++++++++++++ .../extractor__tests__backtick_prop-2.snap | 2 +- .../extractor__tests__backtick_prop.snap | 2 +- ...tractor__tests__duplicate_style_props.snap | 18 ++++++++++++++ ...tract_compound_responsive_style_props.snap | 2 +- ...extract_static_css_class_name_props-3.snap | 2 +- ...extract_static_css_class_name_props-4.snap | 2 +- ...xtractor__tests__group_selector_props.snap | 2 +- ...ractor__tests__props_direct_select-10.snap | 2 +- ...ractor__tests__props_direct_select-11.snap | 2 +- ...tractor__tests__props_direct_select-9.snap | 2 +- ...actor__tests__support_transpile_cjs-2.snap | 6 ++--- ...actor__tests__support_transpile_cjs-3.snap | 6 ++--- ...tractor__tests__support_transpile_cjs.snap | 6 ++--- ...actor__tests__support_transpile_mjs-2.snap | 6 ++--- ...tractor__tests__support_transpile_mjs.snap | 6 ++--- ...tests__ternary_operator_in_selector-2.snap | 2 +- ...__tests__ternary_operator_in_selector.snap | 2 +- libs/extractor/src/visit.rs | 18 +++++++++++--- 22 files changed, 110 insertions(+), 32 deletions(-) create mode 100644 .changeset/slimy-walls-melt.md create mode 100644 libs/extractor/src/snapshots/extractor__tests__duplicate_style_props.snap diff --git a/.changeset/slimy-walls-melt.md b/.changeset/slimy-walls-melt.md new file mode 100644 index 00000000..5fa86be7 --- /dev/null +++ b/.changeset/slimy-walls-melt.md @@ -0,0 +1,5 @@ +--- +"@devup-ui/wasm": patch +--- + +Fix duplicate props issue diff --git a/libs/css/src/lib.rs b/libs/css/src/lib.rs index 40d01436..53c8624c 100644 --- a/libs/css/src/lib.rs +++ b/libs/css/src/lib.rs @@ -196,6 +196,20 @@ pub fn to_kebab_case(value: &str) -> String { .collect() } +pub fn to_camel_case(value: &str) -> String { + value + .split('-') + .enumerate() + .map(|(i, s)| { + if i == 0 { + s.to_string() + } else { + format!("{}{}", s[0..1].to_uppercase(), &s[1..]) + } + }) + .collect() +} + pub fn convert_property(property: &str) -> PropertyType { GLOBAL_STYLE_PROPERTY .get(property) @@ -203,6 +217,16 @@ pub fn convert_property(property: &str) -> PropertyType { .unwrap_or_else(|| to_kebab_case(property).into()) } +pub fn sort_to_long(property: &str) -> String { + GLOBAL_STYLE_PROPERTY + .get(property) + .map(|v| match v { + PropertyType::Single(value) => to_camel_case(value), + PropertyType::Multi(_) => property.to_string(), + }) + .unwrap_or_else(|| property.to_string()) +} + pub fn sheet_to_classname( property: &str, level: u8, diff --git a/libs/extractor/src/extract_style/mod.rs b/libs/extractor/src/extract_style/mod.rs index 81d21ec1..9686e17b 100644 --- a/libs/extractor/src/extract_style/mod.rs +++ b/libs/extractor/src/extract_style/mod.rs @@ -1,6 +1,8 @@ use crate::utils::convert_value; use crate::StyleProperty; -use css::{css_to_classname, sheet_to_classname, sheet_to_variable_name, StyleSelector}; +use css::{ + css_to_classname, sheet_to_classname, sheet_to_variable_name, sort_to_long, StyleSelector, +}; use once_cell::sync::Lazy; use std::collections::HashSet; @@ -37,7 +39,7 @@ impl ExtractStaticStyle { } else { convert_value(value) }, - property: property.to_string(), + property: sort_to_long(property), level, selector, basic: false, @@ -134,7 +136,7 @@ impl ExtractDynamicStyle { selector: Option, ) -> Self { Self { - property: property.to_string(), + property: sort_to_long(property), level, identifier: identifier.to_string(), selector, diff --git a/libs/extractor/src/lib.rs b/libs/extractor/src/lib.rs index 3dee1252..cc163e23 100644 --- a/libs/extractor/src/lib.rs +++ b/libs/extractor/src/lib.rs @@ -1312,4 +1312,21 @@ PROCESS_DATA.map(({ id, title, content }, idx) => ( ) .unwrap()); } + + #[test] + #[serial] + fn test_duplicate_style_props() { + reset_class_map(); + assert_debug_snapshot!(extract( + "test.js", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap()); + } } diff --git a/libs/extractor/src/snapshots/extractor__tests__backtick_prop-2.snap b/libs/extractor/src/snapshots/extractor__tests__backtick_prop-2.snap index 8f7f3c60..af3c7388 100644 --- a/libs/extractor/src/snapshots/extractor__tests__backtick_prop-2.snap +++ b/libs/extractor/src/snapshots/extractor__tests__backtick_prop-2.snap @@ -6,7 +6,7 @@ ExtractOutput { styles: [ Dynamic( ExtractDynamicStyle { - property: "bg", + property: "background", level: 0, identifier: "`${variable}`", selector: None, diff --git a/libs/extractor/src/snapshots/extractor__tests__backtick_prop.snap b/libs/extractor/src/snapshots/extractor__tests__backtick_prop.snap index ea494c11..8b473b28 100644 --- a/libs/extractor/src/snapshots/extractor__tests__backtick_prop.snap +++ b/libs/extractor/src/snapshots/extractor__tests__backtick_prop.snap @@ -6,7 +6,7 @@ ExtractOutput { styles: [ Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "black", level: 0, selector: None, diff --git a/libs/extractor/src/snapshots/extractor__tests__duplicate_style_props.snap b/libs/extractor/src/snapshots/extractor__tests__duplicate_style_props.snap new file mode 100644 index 00000000..fabac2d0 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__duplicate_style_props.snap @@ -0,0 +1,18 @@ +--- +source: libs/extractor/src/lib.rs +expression: "extract(\"test.js\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap()" +--- +ExtractOutput { + styles: [ + Static( + ExtractStaticStyle { + property: "background", + value: "red", + level: 0, + selector: None, + basic: false, + }, + ), + ], + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_compound_responsive_style_props.snap b/libs/extractor/src/snapshots/extractor__tests__extract_compound_responsive_style_props.snap index 169fb00b..e01b2cb5 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_compound_responsive_style_props.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_compound_responsive_style_props.snap @@ -30,7 +30,7 @@ ExtractOutput { ), Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "red", level: 0, selector: None, diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_static_css_class_name_props-3.snap b/libs/extractor/src/snapshots/extractor__tests__extract_static_css_class_name_props-3.snap index 043a737d..bc8a8814 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_static_css_class_name_props-3.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_static_css_class_name_props-3.snap @@ -15,7 +15,7 @@ ExtractOutput { ), Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "red", level: 0, selector: None, diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_static_css_class_name_props-4.snap b/libs/extractor/src/snapshots/extractor__tests__extract_static_css_class_name_props-4.snap index 53b5a8cd..f9307be1 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_static_css_class_name_props-4.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_static_css_class_name_props-4.snap @@ -6,7 +6,7 @@ ExtractOutput { styles: [ Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "red", level: 0, selector: None, diff --git a/libs/extractor/src/snapshots/extractor__tests__group_selector_props.snap b/libs/extractor/src/snapshots/extractor__tests__group_selector_props.snap index c9e43d17..7803f363 100644 --- a/libs/extractor/src/snapshots/extractor__tests__group_selector_props.snap +++ b/libs/extractor/src/snapshots/extractor__tests__group_selector_props.snap @@ -6,7 +6,7 @@ ExtractOutput { styles: [ Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "red", level: 0, selector: Some( diff --git a/libs/extractor/src/snapshots/extractor__tests__props_direct_select-10.snap b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-10.snap index afc34e56..8a408fa0 100644 --- a/libs/extractor/src/snapshots/extractor__tests__props_direct_select-10.snap +++ b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-10.snap @@ -15,7 +15,7 @@ ExtractOutput { ), Dynamic( ExtractDynamicStyle { - property: "bg", + property: "background", level: 0, identifier: "[`var(--red)`, `${variable}`][idx]", selector: None, diff --git a/libs/extractor/src/snapshots/extractor__tests__props_direct_select-11.snap b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-11.snap index c71576d4..b0bec8af 100644 --- a/libs/extractor/src/snapshots/extractor__tests__props_direct_select-11.snap +++ b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-11.snap @@ -33,7 +33,7 @@ ExtractOutput { ), Dynamic( ExtractDynamicStyle { - property: "bg", + property: "background", level: 0, identifier: "[\n\t\"var(--webBg)\",\n\t\"var(--appBg)\",\n\t\"var(--solutionBg)\"\n][categoryId - 1]", selector: None, diff --git a/libs/extractor/src/snapshots/extractor__tests__props_direct_select-9.snap b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-9.snap index 47ff1b3f..b6634d48 100644 --- a/libs/extractor/src/snapshots/extractor__tests__props_direct_select-9.snap +++ b/libs/extractor/src/snapshots/extractor__tests__props_direct_select-9.snap @@ -15,7 +15,7 @@ ExtractOutput { ), Dynamic( ExtractDynamicStyle { - property: "bg", + property: "background", level: 0, identifier: "[\"var(--red)\", \"var(--blue)\"][idx]", selector: None, diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-2.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-2.snap index c01c5230..759f0559 100644 --- a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-2.snap +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-2.snap @@ -6,7 +6,7 @@ ExtractOutput { styles: [ Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "blue", level: 0, selector: Some( @@ -19,7 +19,7 @@ ExtractOutput { ), Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "$text", level: 0, selector: None, @@ -49,7 +49,7 @@ ExtractOutput { ), Static( ExtractStaticStyle { - property: "mt", + property: "marginTop", value: "8px", level: 0, selector: None, diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-3.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-3.snap index 13ddbfd4..1c586b39 100644 --- a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-3.snap +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-3.snap @@ -6,7 +6,7 @@ ExtractOutput { styles: [ Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "blue", level: 0, selector: Some( @@ -19,7 +19,7 @@ ExtractOutput { ), Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "$text", level: 0, selector: None, @@ -49,7 +49,7 @@ ExtractOutput { ), Static( ExtractStaticStyle { - property: "mt", + property: "marginTop", value: "8px", level: 0, selector: None, diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs.snap index bf44a672..c135f51e 100644 --- a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs.snap +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs.snap @@ -6,7 +6,7 @@ ExtractOutput { styles: [ Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "blue", level: 0, selector: Some( @@ -19,7 +19,7 @@ ExtractOutput { ), Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "$text", level: 0, selector: None, @@ -49,7 +49,7 @@ ExtractOutput { ), Static( ExtractStaticStyle { - property: "mt", + property: "marginTop", value: "8px", level: 0, selector: None, diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-2.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-2.snap index 328983c9..571bb883 100644 --- a/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-2.snap +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-2.snap @@ -6,7 +6,7 @@ ExtractOutput { styles: [ Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "blue", level: 0, selector: Some( @@ -19,7 +19,7 @@ ExtractOutput { ), Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "$text", level: 0, selector: None, @@ -49,7 +49,7 @@ ExtractOutput { ), Static( ExtractStaticStyle { - property: "mt", + property: "marginTop", value: "8px", level: 0, selector: None, diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs.snap index aa903f9b..e946b918 100644 --- a/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs.snap +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs.snap @@ -6,7 +6,7 @@ ExtractOutput { styles: [ Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "blue", level: 0, selector: Some( @@ -19,7 +19,7 @@ ExtractOutput { ), Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "$text", level: 0, selector: None, @@ -49,7 +49,7 @@ ExtractOutput { ), Static( ExtractStaticStyle { - property: "mt", + property: "marginTop", value: "8px", level: 0, selector: None, diff --git a/libs/extractor/src/snapshots/extractor__tests__ternary_operator_in_selector-2.snap b/libs/extractor/src/snapshots/extractor__tests__ternary_operator_in_selector-2.snap index 4bd74638..07303133 100644 --- a/libs/extractor/src/snapshots/extractor__tests__ternary_operator_in_selector-2.snap +++ b/libs/extractor/src/snapshots/extractor__tests__ternary_operator_in_selector-2.snap @@ -15,7 +15,7 @@ ExtractOutput { ), Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "red", level: 0, selector: Some( diff --git a/libs/extractor/src/snapshots/extractor__tests__ternary_operator_in_selector.snap b/libs/extractor/src/snapshots/extractor__tests__ternary_operator_in_selector.snap index 19e94a6c..ea214a57 100644 --- a/libs/extractor/src/snapshots/extractor__tests__ternary_operator_in_selector.snap +++ b/libs/extractor/src/snapshots/extractor__tests__ternary_operator_in_selector.snap @@ -15,7 +15,7 @@ ExtractOutput { ), Static( ExtractStaticStyle { - property: "bg", + property: "background", value: "red", level: 0, selector: Some( diff --git a/libs/extractor/src/visit.rs b/libs/extractor/src/visit.rs index 50fd3111..8e37df03 100644 --- a/libs/extractor/src/visit.rs +++ b/libs/extractor/src/visit.rs @@ -5,6 +5,7 @@ use crate::style_extractor::{ extract_style_from_expression, extract_style_from_jsx_attr, ExtractResult, }; use crate::{ExtractStyleProp, ExtractStyleValue, StyleProperty}; +use css::sort_to_long; use oxc_allocator::{Allocator, CloneIn}; use oxc_ast::ast::ImportDeclarationSpecifier::ImportSpecifier; use oxc_ast::ast::JSXAttributeItem::Attribute; @@ -20,7 +21,7 @@ use oxc_ast::visit::walk_mut::{ }; use oxc_ast::{AstBuilder, VisitMut}; use oxc_span::SPAN; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; pub struct DevupVisitor<'a> { pub ast: AstBuilder<'a>, @@ -120,6 +121,7 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { if let Expression::ObjectExpression(obj) = it.arguments[1].to_expression_mut() { + let mut duplicate_set = HashSet::new(); let mut tag = kind.to_tag().unwrap_or("div").to_string(); let mut props_styles = vec![]; for idx in (0..obj.properties.len()).rev() { @@ -127,7 +129,11 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { let mut rm = false; if let ObjectPropertyKind::ObjectProperty(prop) = &mut prop { if let PropertyKey::StaticIdentifier(ident) = &prop.key { - let name = ident.name.to_string(); + let name = sort_to_long(&ident.name); + if duplicate_set.contains(name.as_str()) { + continue; + } + duplicate_set.insert(name.clone()); rm = match extract_style_from_expression( &self.ast, Some(&name), @@ -283,12 +289,18 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { let mut props_styles = vec![]; // extract ExtractStyleProp and remain style and class name, just extract + let mut duplicate_set = HashSet::new(); for i in (0..attrs.len()).rev() { let mut attr = attrs.remove(i); let mut rm = false; if let Attribute(ref mut attr) = &mut attr { if let Identifier(name) = &attr.name { - let name = name.to_string(); + let name = sort_to_long(name.name.as_str()); + println!("name: {} {:?}", name, duplicate_set); + if duplicate_set.contains(&name) { + continue; + } + duplicate_set.insert(name.clone()); if let Some(at) = &mut attr.value { rm = match extract_style_from_jsx_attr(&self.ast, &name, at, None) { ExtractResult::Maintain => false,