Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions apps/oxfmt/test/api/sort_tailwindcss.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,20 @@ shadow-lg\` : "font-normal"}\`} />;`;
expect(result.errors).toStrictEqual([]);
});

// https://github.com/oxc-project/oxc/issues/20397
it("should preserve trailing space in ternary inside binary concat", async () => {
const input = `const A = <div className={"h-fit m-1 w-full " + (flag1 ? "block " : "hidden ") + (flag2 ? "p-2" : "p-4")} />;`;

const result = await format("test.tsx", input, {
experimentalTailwindcss: {},
});

expect(result.code).toContain('"m-1 h-fit w-full "');
expect(result.code).toContain('"block "');
expect(result.code).toContain('"hidden "');
expect(result.errors).toStrictEqual([]);
});

// Tests for template literals in binary expressions
it("should sort template literal on right side of binary expression", async () => {
const input = "const A = <div className={a + ` p-4 flex `} />;";
Expand Down
45 changes: 27 additions & 18 deletions crates/oxc_formatter/src/utils/tailwindcss.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,24 +188,33 @@ where

// 2. Check binary concat context (walk parent chain)
for ancestor in ancestors {
let AstNodes::BinaryExpression(binary) = ancestor else {
break;
};

if binary.operator() != BinaryOperator::Addition {
break;
}

let left = binary.left().span();
let right = binary.right().span();

// Left operand needs trailing space for separation from `+ right`
if left.contains_inclusive(span) {
collapse.end = false;
}
// Right operand needs leading space for separation from `left +`
if right.contains_inclusive(span) {
collapse.start = false;
match ancestor {
AstNodes::BinaryExpression(binary) if binary.operator() == BinaryOperator::Addition => {
let left = binary.left().span();
let right = binary.right().span();

// Left operand needs trailing space for separation from `+ right`
if left.contains_inclusive(span) {
collapse.end = false;
}
// Right operand needs leading space for separation from `left +`
if right.contains_inclusive(span) {
collapse.start = false;
}

// Both flags are one-way latches; no need to continue once both are set.
if !collapse.start && !collapse.end {
break;
}
}
// Transparent nodes: skip through to find outer BinaryExpression(+)
AstNodes::ConditionalExpression(_)
| AstNodes::ParenthesizedExpression(_)
| AstNodes::TSAsExpression(_)
| AstNodes::TSSatisfiesExpression(_)
| AstNodes::TSNonNullExpression(_)
| AstNodes::TSTypeAssertion(_) => {}
_ => break,
}
}

Expand Down
Loading