Skip to content

Commit f5db268

Browse files
committed
Add Testcase
1 parent 9a8fcd1 commit f5db268

6 files changed

+175
-109
lines changed

libs/extractor/src/extractor/extract_style_from_styled.rs

Lines changed: 62 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -19,41 +19,28 @@ use oxc_span::SPAN;
1919

2020
fn extract_base_tag_and_class_name<'a>(
2121
input: &Expression<'a>,
22-
styled_name: &str,
2322
imports: &HashMap<String, ExportVariableKind>,
2423
) -> (Option<String>, Option<Vec<ExtractStyleValue>>) {
2524
match input {
2625
Expression::StaticMemberExpression(member) => {
27-
if let Expression::Identifier(ident) = &member.object {
28-
if ident.name.as_str() == styled_name {
29-
(Some(member.property.name.to_string()), None)
30-
} else {
31-
(None, None)
32-
}
33-
} else {
34-
(None, None)
35-
}
26+
(Some(member.property.name.to_string()), None)
3627
}
3728
Expression::CallExpression(call) => {
38-
if let Expression::Identifier(ident) = &call.callee {
39-
if ident.name.as_str() == styled_name && call.arguments.len() == 1 {
40-
// styled("div") or styled(Component)
41-
if let Argument::StringLiteral(lit) = &call.arguments[0] {
42-
(Some(lit.value.to_string()), None)
43-
} else if let Argument::Identifier(ident) = &call.arguments[0] {
44-
if let Some(export_variable_kind) = imports.get(ident.name.as_str()) {
45-
(
46-
Some(export_variable_kind.to_tag().to_string()),
47-
Some(export_variable_kind.extract()),
48-
)
49-
} else {
50-
(Some(ident.name.to_string()), None)
51-
}
29+
if call.arguments.len() == 1 {
30+
// styled("div") or styled(Component)
31+
if let Argument::StringLiteral(lit) = &call.arguments[0] {
32+
(Some(lit.value.to_string()), None)
33+
} else if let Argument::Identifier(ident) = &call.arguments[0] {
34+
if let Some(export_variable_kind) = imports.get(ident.name.as_str()) {
35+
(
36+
Some(export_variable_kind.to_tag().to_string()),
37+
Some(export_variable_kind.extract()),
38+
)
5239
} else {
53-
// Component reference - we'll handle this later
54-
(None, None)
40+
(Some(ident.name.to_string()), None)
5541
}
5642
} else {
43+
// Component reference - we'll handle this later
5744
(None, None)
5845
}
5946
} else {
@@ -74,16 +61,14 @@ fn extract_base_tag_and_class_name<'a>(
7461
pub fn extract_style_from_styled<'a>(
7562
ast_builder: &AstBuilder<'a>,
7663
expression: &mut Expression<'a>,
77-
styled_name: &str,
7864
split_filename: Option<&str>,
7965
imports: &HashMap<String, ExportVariableKind>,
8066
) -> (ExtractResult<'a>, Expression<'a>) {
8167
let (result, new_expr) = match expression {
8268
// Case 1: styled.div`css` or styled("div")`css`
8369
Expression::TaggedTemplateExpression(tag) => {
8470
// Check if tag is styled.div or styled(...)
85-
let (tag_name, default_class_name) =
86-
extract_base_tag_and_class_name(&tag.tag, styled_name, imports);
71+
let (tag_name, default_class_name) = extract_base_tag_and_class_name(&tag.tag, imports);
8772

8873
if let Some(tag_name) = tag_name {
8974
// Extract CSS from template literal
@@ -101,13 +86,13 @@ pub fn extract_style_from_styled<'a>(
10186

10287
let class_name =
10388
gen_class_names(ast_builder, &mut props_styles, None, split_filename);
104-
105-
let new_expr = create_styled_component(
89+
let styled_component = create_styled_component(
10690
ast_builder,
10791
&tag_name,
10892
&class_name,
10993
&gen_styles(ast_builder, &props_styles, None),
11094
);
95+
11196
let result = ExtractResult {
11297
styles: props_styles,
11398
tag: Some(ast_builder.expression_string_literal(
@@ -120,7 +105,7 @@ pub fn extract_style_from_styled<'a>(
120105
props: None,
121106
};
122107

123-
(Some(result), Some(new_expr))
108+
(Some(result), Some(styled_component))
124109
} else {
125110
(None, None)
126111
}
@@ -129,7 +114,7 @@ pub fn extract_style_from_styled<'a>(
129114
Expression::CallExpression(call) => {
130115
// Check if this is a call to styled.div or styled("div")
131116
let (tag_name, default_class_name) =
132-
extract_base_tag_and_class_name(&call.callee, styled_name, imports);
117+
extract_base_tag_and_class_name(&call.callee, imports);
133118

134119
if let Some(tag_name) = tag_name
135120
&& call.arguments.len() == 1
@@ -196,14 +181,15 @@ fn create_styled_component<'a>(
196181
SPAN,
197182
FormalParameterKind::ArrowFormalParameters,
198183
oxc_allocator::Vec::from_iter_in(
199-
vec![ast_builder.formal_parameter(
200-
SPAN,
201-
oxc_allocator::Vec::from_iter_in(vec![], ast_builder.allocator),
202-
ast_builder.binding_pattern(
203-
ast_builder.binding_pattern_kind_object_pattern(
204-
SPAN,
205-
oxc_allocator::Vec::from_iter_in(
206-
vec![
184+
vec![
185+
ast_builder.formal_parameter(
186+
SPAN,
187+
oxc_allocator::Vec::from_iter_in(vec![], ast_builder.allocator),
188+
ast_builder.binding_pattern(
189+
ast_builder.binding_pattern_kind_object_pattern(
190+
SPAN,
191+
oxc_allocator::Vec::from_iter_in(
192+
vec![
207193
ast_builder.binding_property(
208194
SPAN,
209195
ast_builder.property_key_static_identifier(SPAN, "style"),
@@ -241,27 +227,28 @@ fn create_styled_component<'a>(
241227
false,
242228
),
243229
],
244-
ast_builder.allocator,
245-
),
246-
Some(ast_builder.binding_rest_element(
247-
SPAN,
248-
ast_builder.binding_pattern(
249-
ast_builder.binding_pattern_kind_binding_identifier(
250-
SPAN,
251-
ast_builder.atom("rest"),
252-
),
253-
None::<oxc_allocator::Box<oxc_ast::ast::TSTypeAnnotation<'a>>>,
254-
false,
230+
ast_builder.allocator,
255231
),
256-
)),
232+
Some(ast_builder.binding_rest_element(
233+
SPAN,
234+
ast_builder.binding_pattern(
235+
ast_builder.binding_pattern_kind_binding_identifier(
236+
SPAN,
237+
ast_builder.atom("rest"),
238+
),
239+
None::<oxc_allocator::Box<oxc_ast::ast::TSTypeAnnotation<'a>>>,
240+
false,
241+
),
242+
)),
243+
),
244+
None::<oxc_allocator::Box<oxc_ast::ast::TSTypeAnnotation<'a>>>,
245+
false,
257246
),
258-
None::<oxc_allocator::Box<oxc_ast::ast::TSTypeAnnotation<'a>>>,
247+
None,
248+
false,
259249
false,
260250
),
261-
None,
262-
false,
263-
false,
264-
)],
251+
],
265252
ast_builder.allocator,
266253
),
267254
None::<oxc_allocator::Box<oxc_ast::ast::BindingRestElement<'a>>>,
@@ -270,16 +257,20 @@ fn create_styled_component<'a>(
270257
SPAN,
271258
oxc_allocator::Vec::from_iter_in(vec![], ast_builder.allocator),
272259
oxc_allocator::Vec::from_iter_in(
273-
vec![ast_builder.statement_expression(
274-
SPAN,
275-
ast_builder.expression_jsx_element(
260+
vec![
261+
ast_builder.statement_expression(
276262
SPAN,
277-
ast_builder.alloc_jsx_opening_element(
263+
ast_builder.expression_jsx_element(
278264
SPAN,
279-
ast_builder.jsx_element_name_identifier(SPAN, ast_builder.atom(tag_name)),
280-
None::<oxc_allocator::Box<oxc_ast::ast::TSTypeParameterInstantiation<'a>>>,
281-
oxc_allocator::Vec::from_iter_in(
282-
vec![
265+
ast_builder.alloc_jsx_opening_element(
266+
SPAN,
267+
ast_builder
268+
.jsx_element_name_identifier(SPAN, ast_builder.atom(tag_name)),
269+
None::<
270+
oxc_allocator::Box<oxc_ast::ast::TSTypeParameterInstantiation<'a>>,
271+
>,
272+
oxc_allocator::Vec::from_iter_in(
273+
vec![
283274
ast_builder.jsx_attribute_item_spread_attribute(
284275
SPAN,
285276
ast_builder
@@ -358,13 +349,14 @@ fn create_styled_component<'a>(
358349
),
359350
),
360351
],
361-
ast_builder.allocator,
352+
ast_builder.allocator,
353+
),
362354
),
355+
oxc_allocator::Vec::from_iter_in(vec![], ast_builder.allocator),
356+
None::<oxc_allocator::Box<oxc_ast::ast::JSXClosingElement<'a>>>,
363357
),
364-
oxc_allocator::Vec::from_iter_in(vec![], ast_builder.allocator),
365-
None::<oxc_allocator::Box<oxc_ast::ast::JSXClosingElement<'a>>>,
366358
),
367-
)],
359+
],
368360
ast_builder.allocator,
369361
),
370362
);

libs/extractor/src/lib.rs

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8020,7 +8020,7 @@ keyframes({
80208020
#[test]
80218021
#[serial]
80228022
fn test_styled_with_variable_like_emotion_props() {
8023-
// Test 3: styled.div`css with ${props => props.bg}` - props를 사용하는 함수형 변수
8023+
// Test 3: styled.div`css with ${props => props.bg}`
80248024
reset_class_map();
80258025
assert_debug_snapshot!(ToBTreeSet::from(
80268026
extract(
@@ -8041,7 +8041,7 @@ keyframes({
80418041
.unwrap()
80428042
));
80438043

8044-
// Test 4: styled(Component)`css with ${variable}` - 컴포넌트에 외부 변수 사용
8044+
// Test 4: styled(Component)`css with ${variable}`
80458045
reset_class_map();
80468046
assert_debug_snapshot!(ToBTreeSet::from(
80478047
extract(
@@ -8063,7 +8063,7 @@ keyframes({
80638063
.unwrap()
80648064
));
80658065

8066-
// Test 5: styled.div`css with multiple ${variables}` - 여러 변수 조합
8066+
// Test 5: styled.div`css with multiple ${variables}`
80678067
reset_class_map();
80688068
assert_debug_snapshot!(ToBTreeSet::from(
80698069
extract(
@@ -8087,7 +8087,7 @@ keyframes({
80878087
.unwrap()
80888088
));
80898089

8090-
// Test 6: styled.div`css with ${expression}` - 표현식 사용
8090+
// Test 6: styled.div`css with ${expression}`
80918091
reset_class_map();
80928092
assert_debug_snapshot!(ToBTreeSet::from(
80938093
extract(
@@ -8109,4 +8109,65 @@ keyframes({
81098109
.unwrap()
81108110
));
81118111
}
8112+
8113+
#[test]
8114+
#[serial]
8115+
fn test_wrong_styled_with_variable_like_emotion_props() {
8116+
reset_class_map();
8117+
assert_debug_snapshot!(ToBTreeSet::from(
8118+
extract(
8119+
"test.tsx",
8120+
r#"import {styled} from '@devup-ui/core'
8121+
const StyledDiv = styled(null)`
8122+
background: ${props => props.bg};
8123+
color: red;
8124+
`
8125+
"#,
8126+
ExtractOption {
8127+
package: "@devup-ui/core".to_string(),
8128+
css_dir: "@devup-ui/core".to_string(),
8129+
single_css: false,
8130+
import_main_css: false
8131+
}
8132+
)
8133+
.unwrap()
8134+
));
8135+
8136+
reset_class_map();
8137+
assert_debug_snapshot!(ToBTreeSet::from(
8138+
extract(
8139+
"test.tsx",
8140+
r#"import {styled} from '@devup-ui/core'
8141+
const StyledDiv = styled("div", "span")`
8142+
background: ${props => props.bg};
8143+
color: red;
8144+
`
8145+
"#,
8146+
ExtractOption {
8147+
package: "@devup-ui/core".to_string(),
8148+
css_dir: "@devup-ui/core".to_string(),
8149+
single_css: false,
8150+
import_main_css: false
8151+
}
8152+
)
8153+
.unwrap()
8154+
));
8155+
8156+
reset_class_map();
8157+
assert_debug_snapshot!(ToBTreeSet::from(
8158+
extract(
8159+
"test.tsx",
8160+
r#"import {styled} from '@devup-ui/core'
8161+
const StyledDiv = styled("div", "span").filter(Boolean)
8162+
"#,
8163+
ExtractOption {
8164+
package: "@devup-ui/core".to_string(),
8165+
css_dir: "@devup-ui/core".to_string(),
8166+
single_css: false,
8167+
import_main_css: false
8168+
}
8169+
)
8170+
.unwrap()
8171+
));
8172+
}
81128173
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
source: libs/extractor/src/lib.rs
3+
expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {styled} from '@devup-ui/core'\n const StyledDiv = styled(\"div\", \"span\")`\n background: ${props => props.bg};\n color: red;\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())"
4+
---
5+
ToBTreeSet {
6+
styles: {},
7+
code: "const StyledDiv = styled(\"div\", \"span\")`\n background: ${(props) => props.bg};\n color: red;\n `;\n",
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
source: libs/extractor/src/lib.rs
3+
expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {styled} from '@devup-ui/core'\n const StyledDiv = styled(\"div\", \"span\").filter(Boolean)\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())"
4+
---
5+
ToBTreeSet {
6+
styles: {},
7+
code: "const StyledDiv = styled(\"div\", \"span\").filter(Boolean);\n",
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
source: libs/extractor/src/lib.rs
3+
expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {styled} from '@devup-ui/core'\n const StyledDiv = styled(null)`\n background: ${props => props.bg};\n color: red;\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())"
4+
---
5+
ToBTreeSet {
6+
styles: {},
7+
code: "const StyledDiv = styled(null)`\n background: ${(props) => props.bg};\n color: red;\n `;\n",
8+
}

0 commit comments

Comments
 (0)