Skip to content

formatter: Diff with Prettier on JSX whitespace between self-closing element and adjacent text #21148

@jsmecham

Description

@jsmecham

Input

const App = () => (
  <div>
    I have a footnote.
    <FootnoteRef i18nKey="footnote1" />
    I have another footnote.
    <FootnoteRef i18nKey="footnote2" />
  </div>
);

Config

{}

Oxfmt output

Oxfmt version: 0.44.0

const App = () => (
  <div>
    I have a footnote.
    <FootnoteRef i18nKey="footnote1" />I have another footnote.
    <FootnoteRef i18nKey="footnote2" />
  </div>
);

Oxfmt playground link

https://playground.oxc.rs/?t=formatter&formatterPanels=output,prettier&code=const%20App%20%3D%20%28%29%20%3D%3E%20%28%0A%20%20%3Cdiv%3E%0A%20%20%20%20I%20have%20a%20footnote.%0A%20%20%20%20%3CFootnoteRef%20i18nKey%3D%22footnote1%22%20/%3E%0A%20%20%20%20I%20have%20another%20footnote.%0A%20%20%20%20%3CFootnoteRef%20i18nKey%3D%22footnote2%22%20/%3E%0A%20%20%3C/div%3E%0A%29%3B

Prettier output

Prettier version: 3.8.1

const App = () => (
  <div>
    I have a footnote.
    <FootnoteRef i18nKey="footnote1" />
    I have another footnote.
    <FootnoteRef i18nKey="footnote2" />
  </div>
);

Additional notes

oxfmt collapses the newline between a self-closing JSX element (<FootnoteRef ... />) and the following text (I have another footnote.) onto the same line when it fits within printWidth.

This is a semantic change, not just a formatting difference. In JSX, a newline between sibling children renders as a single space character in the output. Collapsing <FootnoteRef i18nKey="footnote1" /> and I have another footnote. onto the same line as <FootnoteRef i18nKey="footnote1" />I have another footnote. removes that whitespace from the rendered DOM.

The htmlWhitespaceSensitivity: "strict" option does not affect this behavior — it only applies to HTML/Vue/Angular, not JSX.

Prettier preserves the newlines in this case, correctly maintaining the whitespace semantics.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Priority

    None yet

    Effort

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions