-
Notifications
You must be signed in to change notification settings - Fork 833
fix(render): decode HTML entities in style attributes #2552
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
base: canary
Are you sure you want to change the base?
fix(render): decode HTML entities in style attributes #2552
Conversation
Fixes resend#1767 - This resolves the issue where React's renderToStaticMarkup encodes quotes in style attributes as HTML entities ("), which can break CSS font-family declarations with quoted font names. The fix: - Created decodeAttributeEntities utility function - Decodes ", ', &resend#39;, and & in style attributes - Only decodes & in href attributes to preserve HTML structure - Added comprehensive tests to verify correct decoding Changes: - packages/render/src/shared/utils/decode-html-entities.ts: New utility - packages/render/src/node/render.tsx: Apply decoding after rendering - packages/render/src/browser/render.tsx: Apply decoding after rendering - packages/render/src/edge/render.tsx: Apply decoding after rendering - packages/render/src/node/render-node.spec.tsx: Added tests
🦋 Changeset detectedLatest commit: 9c37138 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@iagocavalcante is attempting to deploy a commit to the resend Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 issue found across 6 files
Prompt for AI agents (all 1 issues)
Understand the root cause of the following 1 issues and fix them.
<file name="packages/render/src/node/render.tsx">
<violation number="1" location="packages/render/src/node/render.tsx:47">
Decoding the rendered HTML here replaces `&quot;` inside `style` attributes with raw `"`, so markup like `style="font-family:&quot;Helvetica Neue&quot;,Arial"` becomes `style="font-family:"Helvetica Neue",Arial"`; the double quote now closes the attribute early, yielding invalid HTML and dropping the intended styles.</violation>
</file>
React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai
to give feedback, ask questions, or re-run the review.
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'; | ||
|
||
const document = `${doctype}${html.replace(/<!DOCTYPE.*?>/, '')}`; | ||
const decodedHtml = decodeAttributeEntities(html); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Decoding the rendered HTML here replaces "
inside style
attributes with raw "
, so markup like style="font-family:"Helvetica Neue",Arial"
becomes style="font-family:"Helvetica Neue",Arial"
; the double quote now closes the attribute early, yielding invalid HTML and dropping the intended styles.
Prompt for AI agents
Address the following comment on packages/render/src/node/render.tsx at line 47:
<comment>Decoding the rendered HTML here replaces `&quot;` inside `style` attributes with raw `"`, so markup like `style="font-family:&quot;Helvetica Neue&quot;,Arial"` becomes `style="font-family:"Helvetica Neue",Arial"`; the double quote now closes the attribute early, yielding invalid HTML and dropping the intended styles.</comment>
<file context>
@@ -43,7 +44,8 @@ export const render = async (node: React.ReactNode, options?: Options) => {
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
- const document = `${doctype}${html.replace(/<!DOCTYPE.*?>/, '')}`;
+ const decodedHtml = decodeAttributeEntities(html);
+ const document = `${doctype}${decodedHtml.replace(/<!DOCTYPE.*?>/, '')}`;
</file context>
Caution Review the following alerts detected in dependencies. According to your organization's Security Policy, you must resolve all "Block" alerts before proceeding. Learn more about Socket for GitHub.
|
Can you also run |
'@react-email/render': patch | ||
--- | ||
|
||
Fix HTML entity encoding in style attributes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we stick with just this initial portion here, and can you make it all lowercase?
: (processed.type as React.FC); | ||
|
||
const rendered = OriginalComponent(processed.props); | ||
// Handle async Server Components |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems unrelated to the pull request
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I tried to fix because of build failing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not do that here.
const decodeHrefValue = (value: string): string => { | ||
// Only decode ampersands in hrefs to fix URL query parameters | ||
// Do NOT decode quotes to avoid breaking the attribute syntax | ||
return value.replace(/&/g, '&'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you elaborate on why you didn't use html-entities
instead of a replace
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using html-entities
would be overkill for this single character replacement and this only touch in &
nothing else, that's make sense?
8128be7
to
19de23f
Compare
Fixes #1767
Summary
This PR resolves the issue where React's rendering encodes quotes in style attributes as HTML entities (
"
), which can break CSS font-family declarations with quoted font names.Changes
decodeAttributeEntities
utility function to selectively decode HTML entities"
,'
,'
, and&
to fix font-family and other CSS declarations&
to fix URL query parameters while preserving HTML structureExample
Before:
After:
Test Plan
Summary by cubic
Fixes broken CSS font-family and URL query params by decoding safe HTML entities in style and href attributes after render. Applied to node, browser, and edge renderers.