Skip to content

Commit b71f5ed

Browse files
committed
Add testcases
1 parent 4305b6d commit b71f5ed

File tree

1 file changed

+80
-1
lines changed

1 file changed

+80
-1
lines changed

libs/extractor/src/css_utils.rs

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,11 +299,87 @@ pub fn css_to_style_literal<'a>(
299299
for (placeholder, idx) in &found_placeholders {
300300
if *idx < css.expressions.len() {
301301
let expr = &css.expressions[*idx];
302+
303+
// Check if expression is a function (arrow function or function expression)
304+
let is_function = matches!(
305+
expr,
306+
oxc_ast::ast::Expression::ArrowFunctionExpression(_)
307+
| oxc_ast::ast::Expression::FunctionExpression(_)
308+
);
309+
302310
let expr_code = expression_to_code(expr);
303311
// Normalize the expression code while preserving string literals
304-
let normalized_code =
312+
let mut normalized_code =
305313
normalize_whitespace_preserving_strings(&expr_code);
306314

315+
if is_function {
316+
// Normalize arrow function whitespace
317+
normalized_code = normalized_code
318+
.replace(" => ", "=>")
319+
.replace(" =>", "=>")
320+
.replace("=> ", "=>");
321+
// Normalize function() { } to function(){ }
322+
normalized_code =
323+
normalized_code.replace("function() {", "function(){");
324+
normalized_code =
325+
normalized_code.replace("function (", "function(");
326+
// Remove trailing semicolon and spaces before closing brace
327+
normalized_code = normalized_code.replace("; }", "}");
328+
normalized_code = normalized_code.replace(" }", "}");
329+
330+
// Wrap function in parentheses if not already wrapped
331+
let trimmed = normalized_code.trim();
332+
if !(trimmed.starts_with('(') && trimmed.ends_with(')')) {
333+
normalized_code = format!("({})", trimmed);
334+
}
335+
// Add (rest) call
336+
normalized_code = format!("{}(rest)", normalized_code);
337+
338+
// For function expressions, convert string literals in ternary operators
339+
let mut result = String::new();
340+
let mut chars = normalized_code.chars().peekable();
341+
let mut in_ternary_string = false;
342+
343+
while let Some(ch) = chars.next() {
344+
if ch == '?' || ch == ':' {
345+
result.push(ch);
346+
// Skip whitespace
347+
while let Some(&' ') = chars.peek() {
348+
result.push(chars.next().unwrap());
349+
}
350+
// Check if next is a string literal
351+
if let Some(&'"') = chars.peek() {
352+
in_ternary_string = true;
353+
result.push('\'');
354+
chars.next(); // consume the "
355+
}
356+
} else if in_ternary_string && ch == '"' {
357+
// Check if this is a closing quote by looking ahead
358+
let mut peeked = chars.clone();
359+
// Skip whitespace
360+
while let Some(&' ') = peeked.peek() {
361+
peeked.next();
362+
}
363+
// If next is : or ? or ) or } or end, it's a closing quote
364+
if peeked.peek().is_none()
365+
|| matches!(
366+
peeked.peek(),
367+
Some(&':') | Some(&'?') | Some(&')') | Some(&'}')
368+
)
369+
{
370+
result.push('\'');
371+
in_ternary_string = false;
372+
} else {
373+
// Not a closing quote, keep as is
374+
result.push(ch);
375+
}
376+
} else {
377+
result.push(ch);
378+
}
379+
}
380+
normalized_code = result;
381+
}
382+
307383
// Replace placeholder with ${expr} syntax
308384
let expr_template = format!("${{{}}}", normalized_code);
309385
template_literal =
@@ -896,6 +972,9 @@ mod tests {
896972
#[case("`width: ${1}${2}px;`", vec![("width", "12px", None)])]
897973
#[case("`width: ${func(\n\t 1 , \n\t2\n)}px;`", vec![("width", "`${func(1,2)}px`", None)])]
898974
#[case("`width: ${func(\" wow \")}px;`", vec![("width", "`${func(\" wow \")}px`", None)])]
975+
#[case("`width: ${func(\"hello\\nworld\")}px;`", vec![("width", "`${func(\"hello\\nworld\")}px`", None)])]
976+
#[case("`width: ${func('test\\'quote')}px;`", vec![("width", "`${func(\"test'quote\")}px`", None)])]
977+
#[case("`width: ${(props)=>props.b ? \"hello\\\"world\" : \"test\"}px;`", vec![("width", "`${((props)=>props.b ? 'hello\\\"world' : 'test')(rest)}px`", None)])]
899978
// wrong cases
900979
#[case(
901980
"`@media (min-width: 768px) {

0 commit comments

Comments
 (0)