Skip to content

formatter: JSX text/expression line wrapping differs from Prettier (inserts {" "} instead of breaking at operator) #21907

@jsmecham

Description

@jsmecham

Input

function f() {
  return (
    <div>
      <div>
        <div>
          <div>
            <div>
              <div>
                <div>
                  <div>
                    {participants.map((c, i) => (
                      <span key={c.participantId}>
                        {i > 0 ? ", " : ""}
                        {c.fullName ?? `Participant #${c.participantId}`} on {c.planName}
                      </span>
                    ))}
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

Config

{}

Oxfmt output

{c.fullName ?? `Participant #${c.participantId}`} on{" "}
{c.planName}

Oxfmt playground link

https://playground.oxc.rs/?t=formatter&formatterPanels=output,prettier&code=function%20f()%20%7B%0A%20%20return%20(%0A%20%20%20%20%3Cdiv%3E%0A%20%20%20%20%20%20%3Cdiv%3E%0A%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7Bparticipants.map((c%2C%20i)%20%3D%3E%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%20key%3D%7Bc.participantId%7D%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7Bi%20%3E%200%20%3F%20'%2C%20'%20%3A%20''%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7Bc.fullName%20%3F%3F%20%60Participant%20%23%24%7Bc.participantId%7D%60%7D%20on%20%7Bc.planName%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fspan%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20))%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%3C%2Fdiv%3E%0A%20%20)%3B%0A%7D

Prettier output

{c.fullName ??
  `Participant #${c.participantId}`} on {c.planName}

Additional notes

When a JSX expression child sits next to literal text and another JSX expression child (i.e. {expr1} text {expr2}) and the combined sequence exceeds printWidth at the current indent, the formatters pick different break points:

  • Prettier breaks inside the first expression (at the ?? operator) and keeps the trailing literal text and second expression on the same line: } on {c.planName}.
  • oxfmt keeps the first expression atomic and instead inserts {" "} after the literal text, splitting the expression list across two lines.

Both produce the same DOM output (the space is preserved either way), but the visual structure and source diff are noticeably different. The threshold appears tied to indentation depth — at shallower nesting both formatters agree.

Tested against oxfmt 0.47.0 and prettier 3.8.1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions