Skip to content

Commit d4c44a1

Browse files
committed
Feat auto props
1 parent ea6fe0b commit d4c44a1

9 files changed

+109
-38
lines changed

libs/extractor/src/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,6 +1902,25 @@ e(o, { className: "a", bg: variable, style: { color: "blue" }, ...props })
19021902
));
19031903
}
19041904

1905+
#[test]
1906+
#[serial]
1907+
fn support_transpile_cjs22() {
1908+
reset_class_map();
1909+
assert_debug_snapshot!(ToBTreeSet::from(
1910+
extract(
1911+
"test.js",
1912+
r#"import { jsx as e } from "react/jsx-runtime";
1913+
import { Box as o } from "@devup-ui/core";
1914+
e(o, { className: "a", bg: variable, style: { color: "blue" }, ...props })
1915+
"#,
1916+
ExtractOption {
1917+
package: "@devup-ui/core".to_string(),
1918+
css_file: None
1919+
}
1920+
)
1921+
.unwrap()
1922+
));
1923+
}
19051924
#[test]
19061925
#[serial]
19071926
fn support_transpile_cjs() {

libs/extractor/src/prop_modify_utils.rs

Lines changed: 83 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use oxc_ast::AstBuilder;
66
use oxc_ast::ast::JSXAttributeItem::Attribute;
77
use oxc_ast::ast::JSXAttributeName::Identifier;
88
use oxc_ast::ast::{
9-
Expression, JSXAttributeItem, JSXAttributeValue, JSXExpression, ObjectPropertyKind,
10-
PropertyKey, PropertyKind, TemplateElementValue,
9+
Expression, JSXAttributeItem, JSXAttributeValue, JSXExpression, LogicalOperator,
10+
ObjectPropertyKind, PropertyKey, PropertyKind, TemplateElementValue,
1111
};
1212
use oxc_span::SPAN;
1313

@@ -21,6 +21,7 @@ pub fn modify_prop_object<'a>(
2121
) {
2222
let mut class_name_prop = None;
2323
let mut style_prop = None;
24+
let mut spread_props = vec![];
2425
for idx in (0..props.len()).rev() {
2526
let prop = props.remove(idx);
2627
match prop {
@@ -40,14 +41,20 @@ pub fn modify_prop_object<'a>(
4041
}
4142
props.insert(idx, ObjectPropertyKind::ObjectProperty(attr));
4243
}
43-
_ => {
44-
props.insert(idx, prop);
44+
ObjectPropertyKind::SpreadProperty(spread) => {
45+
spread_props.push(spread.argument.clone_in(ast_builder.allocator));
46+
props.insert(idx, ObjectPropertyKind::SpreadProperty(spread));
4547
}
4648
}
4749
}
4850

49-
if let Some(ex) = get_class_name_expression(ast_builder, &class_name_prop, styles, style_order)
50-
{
51+
if let Some(ex) = get_class_name_expression(
52+
ast_builder,
53+
&class_name_prop,
54+
styles,
55+
style_order,
56+
&spread_props,
57+
) {
5158
props.push(ObjectPropertyKind::ObjectProperty(
5259
ast_builder.alloc_object_property(
5360
SPAN,
@@ -60,7 +67,9 @@ pub fn modify_prop_object<'a>(
6067
),
6168
));
6269
}
63-
if let Some(ex) = get_style_expression(ast_builder, &style_prop, styles, &style_vars) {
70+
if let Some(ex) =
71+
get_style_expression(ast_builder, &style_prop, styles, &style_vars, &spread_props)
72+
{
6473
props.push(ObjectPropertyKind::ObjectProperty(
6574
ast_builder.alloc_object_property(
6675
SPAN,
@@ -84,6 +93,7 @@ pub fn modify_props<'a>(
8493
) {
8594
let mut class_name_prop = None;
8695
let mut style_prop = None;
96+
let mut spread_props = vec![];
8797
for idx in (0..props.len()).rev() {
8898
let prop = props.remove(idx);
8999
match prop {
@@ -125,13 +135,19 @@ pub fn modify_props<'a>(
125135
}
126136
props.insert(idx, Attribute(attr));
127137
}
128-
_ => {
129-
props.insert(idx, prop);
138+
JSXAttributeItem::SpreadAttribute(spread) => {
139+
spread_props.push(spread.argument.clone_in(ast_builder.allocator));
140+
props.insert(idx, JSXAttributeItem::SpreadAttribute(spread));
130141
}
131142
}
132143
}
133-
if let Some(ex) = get_class_name_expression(ast_builder, &class_name_prop, styles, style_order)
134-
{
144+
if let Some(ex) = get_class_name_expression(
145+
ast_builder,
146+
&class_name_prop,
147+
styles,
148+
style_order,
149+
&spread_props,
150+
) {
135151
props.push(Attribute(ast_builder.alloc_jsx_attribute(
136152
SPAN,
137153
Identifier(ast_builder.alloc_jsx_identifier(SPAN, "className")),
@@ -144,7 +160,9 @@ pub fn modify_props<'a>(
144160
}),
145161
)));
146162
}
147-
if let Some(ex) = get_style_expression(ast_builder, &style_prop, styles, &style_vars) {
163+
if let Some(ex) =
164+
get_style_expression(ast_builder, &style_prop, styles, &style_vars, &spread_props)
165+
{
148166
props.push(Attribute(ast_builder.alloc_jsx_attribute(
149167
SPAN,
150168
Identifier(ast_builder.alloc_jsx_identifier(SPAN, "style")),
@@ -160,16 +178,30 @@ pub fn get_class_name_expression<'a>(
160178
class_name_prop: &Option<Expression<'a>>,
161179
styles: &mut [ExtractStyleProp<'a>],
162180
style_order: Option<u8>,
181+
spread_props: &[Expression<'a>],
163182
) -> Option<Expression<'a>> {
164183
// should modify class name prop
165184
merge_string_expressions(
166185
ast_builder,
167186
[
168-
class_name_prop.clone_in(ast_builder.allocator),
187+
class_name_prop
188+
.as_ref()
189+
.map(|class_name| convert_class_name(ast_builder, class_name)),
169190
gen_class_names(ast_builder, styles, style_order),
170191
]
171192
.into_iter()
172193
.flatten()
194+
.chain(spread_props.iter().map(|ex| {
195+
convert_class_name(
196+
ast_builder,
197+
&Expression::StaticMemberExpression(ast_builder.alloc_static_member_expression(
198+
SPAN,
199+
ex.clone_in(ast_builder.allocator),
200+
ast_builder.identifier_name(SPAN, ast_builder.atom("className")),
201+
true,
202+
)),
203+
)
204+
}))
173205
.collect::<Vec<_>>()
174206
.as_slice(),
175207
)
@@ -180,6 +212,7 @@ pub fn get_style_expression<'a>(
180212
style_prop: &Option<Expression<'a>>,
181213
styles: &[ExtractStyleProp<'a>],
182214
style_vars: &Option<Expression<'a>>,
215+
spread_props: &[Expression<'a>],
183216
) -> Option<Expression<'a>> {
184217
merge_object_expressions(
185218
ast_builder,
@@ -192,6 +225,14 @@ pub fn get_style_expression<'a>(
192225
]
193226
.into_iter()
194227
.flatten()
228+
.chain(spread_props.iter().map(|ex| {
229+
Expression::StaticMemberExpression(ast_builder.alloc_static_member_expression(
230+
SPAN,
231+
ex.clone_in(ast_builder.allocator),
232+
ast_builder.identifier_name(SPAN, ast_builder.atom("style")),
233+
true,
234+
))
235+
}))
195236
.collect::<Vec<_>>()
196237
.as_slice(),
197238
)
@@ -333,6 +374,35 @@ fn merge_object_expressions<'a>(
333374
))
334375
}
335376

377+
pub fn convert_class_name<'a>(
378+
ast_builder: &AstBuilder<'a>,
379+
class_name: &Expression<'a>,
380+
) -> Expression<'a> {
381+
if matches!(
382+
class_name,
383+
Expression::StringLiteral(_)
384+
| Expression::TemplateLiteral(_)
385+
| Expression::NumericLiteral(_)
386+
) {
387+
return class_name.clone_in(ast_builder.allocator);
388+
}
389+
390+
// wrap ( and ?? ''
391+
Expression::LogicalExpression(
392+
ast_builder.alloc_logical_expression(
393+
SPAN,
394+
Expression::ParenthesizedExpression(
395+
ast_builder.alloc_parenthesized_expression(
396+
SPAN,
397+
class_name.clone_in(ast_builder.allocator),
398+
),
399+
),
400+
LogicalOperator::Coalesce,
401+
Expression::StringLiteral(ast_builder.alloc_string_literal(SPAN, "", None)),
402+
),
403+
)
404+
}
405+
336406
pub fn convert_style_vars<'a>(
337407
ast_builder: &AstBuilder<'a>,
338408
style_vars: &Expression<'a>,

libs/extractor/src/snapshots/extractor__tests__extract_class_name_from_component.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,5 @@ ToBTreeSet {
4545
},
4646
),
4747
},
48-
code: "import \"@devup-ui/core/devup-ui.css\";\n<div className={`${\"a\" + \"b\"} d0 d1 d2 d3`} />;\n",
48+
code: "import \"@devup-ui/core/devup-ui.css\";\n<div className={`${\"a\" + \"b\" ?? \"\"} d0 d1 d2 d3`} />;\n",
4949
}

libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-5.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ ToBTreeSet {
2323
},
2424
),
2525
},
26-
code: "import \"@devup-ui/core/devup-ui.css\";\n<div className={`${\"a\" + \"b\"} d0 d1`} />;\n",
26+
code: "import \"@devup-ui/core/devup-ui.css\";\n<div className={`${\"a\" + \"b\" ?? \"\"} d0 d1`} />;\n",
2727
}

libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-6.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ ToBTreeSet {
2323
},
2424
),
2525
},
26-
code: "import \"@devup-ui/core/devup-ui.css\";\n<img src=\"/next.svg\" alt=\"Next.js logo\" className={`${styles.logo} d0 d1`} />;\n",
26+
code: "import \"@devup-ui/core/devup-ui.css\";\n<img src=\"/next.svg\" alt=\"Next.js logo\" className={`${styles.logo ?? \"\"} d0 d1`} />;\n",
2727
}

libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-7.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ ToBTreeSet {
2323
},
2424
),
2525
},
26-
code: "import \"@devup-ui/core/devup-ui.css\";\n<div className={`${variable} d0 d1`} />;\n",
26+
code: "import \"@devup-ui/core/devup-ui.css\";\n<div className={`${variable ?? \"\"} d0 d1`} />;\n",
2727
}

libs/extractor/src/snapshots/extractor__tests__extract_style_props_with_class_name-8.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,5 @@ ToBTreeSet {
4040
},
4141
),
4242
},
43-
code: "import \"@devup-ui/core/devup-ui.css\";\n<div className={`${variable} d0 ${true ? \"d1\" : \"d2\"}`} />;\n",
43+
code: "import \"@devup-ui/core/devup-ui.css\";\n<div className={`${variable ?? \"\"} d0 ${true ? \"d1\" : \"d2\"}`} />;\n",
4444
}

libs/extractor/src/snapshots/extractor__tests__rest_props.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
source: libs/extractor/src/lib.rs
3-
expression: "ToBTreeSet::from(extract(\"test.js\",\nr#\"import {Flex} from '@devup-ui/core'\n <Flex opacity={0.5} {...props} />\n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap())"
3+
expression: "ToBTreeSet::from(extract(\"test.jsx\",\nr#\"import {Flex} from '@devup-ui/core'\n <Flex opacity={0.5} {...props} />\n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap())"
44
---
55
ToBTreeSet {
66
styles: {
@@ -25,5 +25,5 @@ ToBTreeSet {
2525
},
2626
),
2727
},
28-
code: "import \"@devup-ui/core/devup-ui.css\";\n<div {...props} className=\"d0 d1\" />;\n",
28+
code: "import \"@devup-ui/core/devup-ui.css\";\n<div {...props} className={`d0 d1 ${props?.className ?? \"\"}`} style={props?.style} />;\n",
2929
}

libs/extractor/src/snapshots/extractor__tests__support_transpile_mjs-5.snap

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)