Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

feat(rome_js_formatter): Format JSX #3144

Merged
merged 8 commits into from
Sep 2, 2022
Merged

feat(rome_js_formatter): Format JSX #3144

merged 8 commits into from
Sep 2, 2022

Conversation

MichaReiser
Copy link
Contributor

@MichaReiser MichaReiser commented Sep 1, 2022

Summary

This PR improves Rome's formatting of JSX to bring it closer to Prettier's formatting. It improves the formatting of attributes, element heads, and most importantly of the children.

The formatting of the children is complicated for two reasons:

  • It is necessary to merge multiple children. For example, two {' '}{' '} should be merged into a single whitespace. Isolating children in isolation is, therefore, not possible.
  • The formatter has to format children twice, once for a flat representation and one if the element doesn't fit on a single line.

The way this PR solves this challenge is by transforming a JsxChildList into an intermediate representation that strips any children that have no semantic meaning and have no effect on the formatting (empty line has no semantic meaning, but is something we want to preserve). It then uses this transformed representation to perform the formatting, applying slightly different formatting between the "flat" and expanded versions.

This PR does not implement the special handling of JSX inside of conditional expression. This is left for another pull request.

Test Plan

Average compatibility: 84.94 -> 85.41
Compatible lines: 83.08 -> 83.70

I formatted the ant design project with Prettier and then Rome and manually went through the changes. This helped me identify a few bugs that I fixed. The main remaining differences are now caused by call arguments being formatted differently.

Verified that the example from the bug report #2830 now gets formatted the same as prettier.

@netlify
Copy link

netlify bot commented Sep 1, 2022

Deploy Preview for rometools canceled.

Name Link
🔨 Latest commit 534dff8
🔍 Latest deploy log https://app.netlify.com/sites/rometools/deploys/6311f3f4f5d1a70008f4a22d

@MichaReiser MichaReiser added this to the 0.9.0 milestone Sep 1, 2022
@MichaReiser MichaReiser mentioned this pull request Sep 1, 2022
17 tasks
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Sep 1, 2022

Deploying with  Cloudflare Pages  Cloudflare Pages

Latest commit: 534dff8
Status: ✅  Deploy successful!
Preview URL: https://2f609d86.tools-8rn.pages.dev
Branch Preview URL: https://feat-jsx-formatting.tools-8rn.pages.dev

View logs

@MichaReiser MichaReiser temporarily deployed to aws September 1, 2022 11:22 Inactive
@MichaReiser MichaReiser linked an issue Sep 1, 2022 that may be closed by this pull request
1 task
@github-actions
Copy link

github-actions bot commented Sep 1, 2022

@@ -70,8 +70,19 @@ const value = (bifornCringerMoshedPerplexSawder
- </Element2>
-);
+)
+ ? <Element><Sub /><Sub /><Sub /><Sub /><Sub /><Sub /></Element>
+ : <Element2><Sub /><Sub /><Sub /></Element2>;
+ ? <Element>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Matching Prettier's formatting for conditional's containing JSX requires changes to the conditional formatting. I'll follow up with another PR to not further increase the size of this PR.

@MichaReiser MichaReiser temporarily deployed to aws September 1, 2022 12:25 Inactive
@MichaReiser MichaReiser changed the base branch from main to fix/skipped-token-trivia-spacing September 1, 2022 12:25
@MichaReiser MichaReiser force-pushed the feat/jsx-formatting branch 2 times, most recently from 7b5a7f6 to 16f3aa2 Compare September 1, 2022 15:40

match interned.0.as_ref() {
element @ FormatElement::Text(_) | element @ FormatElement::Space => {
write!(f, [text("\""), element, text("\"")])
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes an issue where an interned string token wasn't put in quotes which made it very confusing when reading Rome's format IR

@MichaReiser MichaReiser added the A-Formatter Area: formatter label Sep 1, 2022
@MichaReiser MichaReiser marked this pull request as ready for review September 1, 2022 16:00
@MichaReiser MichaReiser requested a review from a team September 1, 2022 16:00
Base automatically changed from fix/skipped-token-trivia-spacing to main September 1, 2022 16:00
@MichaReiser MichaReiser temporarily deployed to aws September 1, 2022 16:04 Inactive
crates/rome_formatter/src/printed_tokens.rs Outdated Show resolved Hide resolved
crates/rome_formatter/src/printer/mod.rs Show resolved Hide resolved
crates/rome_formatter/src/printer/mod.rs Show resolved Hide resolved
crates/rome_js_formatter/src/jsx/tag/element.rs Outdated Show resolved Hide resolved
@MichaReiser MichaReiser temporarily deployed to aws September 2, 2022 11:00 Inactive
@MichaReiser MichaReiser temporarily deployed to aws September 2, 2022 11:01 Inactive
@MichaReiser MichaReiser temporarily deployed to aws September 2, 2022 11:45 Inactive
@MichaReiser MichaReiser temporarily deployed to aws September 2, 2022 12:15 Inactive
@MichaReiser MichaReiser merged commit f9b585f into main Sep 2, 2022
@MichaReiser MichaReiser deleted the feat/jsx-formatting branch September 2, 2022 12:40
ematipico pushed a commit that referenced this pull request Sep 5, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A-Formatter Area: formatter
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

🐛 Formatting of TSX file may differ from Prettier
2 participants