Skip to content

feat(render): in-house formatter #2361

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 53 commits into
base: main
Choose a base branch
from

Conversation

gabrielmfern
Copy link
Member

@gabrielmfern gabrielmfern commented Jul 14, 2025

The current formatter (prettier) allows for us to format the resulting email templates in a way that feels familiar to users, but the downsides are:

  1. very opinionated and hard to change:
  2. very messy in the way it's built: so much so that it can't quite be bundled by Next.js Prettier warning in console #1910
  3. has an HTML parser that is extremely strict for no apparent reason: 'Unexpected closing tag "td". Help! #1838

So, this pull request shows off at least a good POC for a starting point for us to think about perhaps moving into our own in-house formatter and parser. We still want to parse the HTML's end result (in another pull request, perhaps) to avoid users sending invalid HTML, but this only includes a very lenient parser meant for roughly understanding the AST and printing it afterwards.

Having an in-house formatter also allows us to bend the end results to avoid email client quirks that wouldn't be really present in usual HTML.

(By the way, the majority of the additions in this pull request are the testing assets)


The other ecosystem options:

  1. Biome: only has an experimental API for JS and uses WASM which wouldn't be optimal
  2. js-beautify: interoperability problems with ESM and CJS, ugly formatting and overly complex code (this was what we used before prettier)

The original pull request in which we added prettier was #1777

Copy link

changeset-bot bot commented Jul 14, 2025

⚠️ No Changeset found

Latest commit: ad774ef

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link

vercel bot commented Jul 14, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
react-email ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 23, 2025 5:09pm
react-email-demo ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 23, 2025 5:09pm

Copy link

pkg-pr-new bot commented Jul 14, 2025

Open in StackBlitz

npm i https://pkg.pr.new/resend/react-email/@react-email/preview-server@2361
npm i https://pkg.pr.new/resend/react-email@2361
npm i https://pkg.pr.new/resend/react-email/@react-email/render@2361
npm i https://pkg.pr.new/resend/react-email/@react-email/tailwind@2361

commit: ad774ef

@roderickhsiao
Copy link
Contributor

Just to comment here kudos for jumping into the problem with a comprehensive solution!

even though it has node in the name it actually runs fine in the browser
});
return printChildrenOf(root, {
preserveLinebreaks: false,
maxLineLength: 80,
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is an unexpecting behavior for #1847

Although prettier use whitespace sensitive formating https://prettier.io/blog/2018/11/07/1.15.0.html#whitespace-sensitive-formatting

When we are building email template, the max line is restrictly related to language/fontsize/layout and CSS attributes. I think enforcing an 80 max is a very opinionated decision - the in house formater also carry the same logic that wouldn't fix the issue.

Or any way we can have an option to disable auto line-break for the max length check?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure I 100% understand what you're asking, but the preserveLineBreak being set to true should not wrap text at all. Maybe the option name is a bit confusing.

Also, the max line length is also configurable - 80 is just the default value.

@roderickhsiao
Copy link
Contributor

roderickhsiao commented Jul 25, 2025 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants