From 52e9623b732bdf8a9cbdd6d52c1922bff46c90ea Mon Sep 17 00:00:00 2001 From: CharlieHelps Date: Wed, 21 Jan 2026 19:07:27 +0000 Subject: [PATCH 01/18] fix(jsx-email): use standard MSO closer in MSO conditionals rendered in now close with `` to match standard conditional comment syntax. --- packages/jsx-email/src/renderer/conditional.ts | 6 ++++-- .../test/.snapshots/conditional-raw.test.tsx.snap | 2 +- .../jsx-email/test/.snapshots/debug.test.tsx.snap | 2 +- .../test/conditional-endif-closer.test.tsx | 13 +++++++++++++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/packages/jsx-email/src/renderer/conditional.ts b/packages/jsx-email/src/renderer/conditional.ts index 70690334..80fce1f2 100644 --- a/packages/jsx-email/src/renderer/conditional.ts +++ b/packages/jsx-email/src/renderer/conditional.ts @@ -57,6 +57,8 @@ export const getConditionalPlugin = async () => { ? false : Boolean(headProp); + const willRenderInHead = Boolean(headEl && (toHead || parent === headEl)); + let openRaw: string | undefined; let closeRaw: string | undefined; @@ -72,8 +74,8 @@ export const getConditionalPlugin = async () => { // Older Outlook/Word HTML parsers prefer the self-closing // conditional terminator variant to avoid comment spillover // when adjacent comments appear. Use the `` form - // for maximum compatibility. - closeRaw = ''; + // for maximum compatibility, except within . + closeRaw = willRenderInHead ? '' : ''; } } diff --git a/packages/jsx-email/test/.snapshots/conditional-raw.test.tsx.snap b/packages/jsx-email/test/.snapshots/conditional-raw.test.tsx.snap index b8722635..78ca16ae 100644 --- a/packages/jsx-email/test/.snapshots/conditional-raw.test.tsx.snap +++ b/packages/jsx-email/test/.snapshots/conditional-raw.test.tsx.snap @@ -2,4 +2,4 @@ exports[`Raw in Conditional > Raw in Conditional 1`] = `""`; -exports[`Raw in Conditional > Raw in Conditional 2`] = `""`; +exports[`Raw in Conditional > Raw in Conditional 2`] = `""`; diff --git a/packages/jsx-email/test/.snapshots/debug.test.tsx.snap b/packages/jsx-email/test/.snapshots/debug.test.tsx.snap index fb89dce3..7fafeaab 100644 --- a/packages/jsx-email/test/.snapshots/debug.test.tsx.snap +++ b/packages/jsx-email/test/.snapshots/debug.test.tsx.snap @@ -11,7 +11,7 @@ exports[`render > renders with debug attributes 1`] = ` - + diff --git a/packages/jsx-email/test/conditional-endif-closer.test.tsx b/packages/jsx-email/test/conditional-endif-closer.test.tsx index ff98b18a..ee6f3951 100644 --- a/packages/jsx-email/test/conditional-endif-closer.test.tsx +++ b/packages/jsx-email/test/conditional-endif-closer.test.tsx @@ -17,4 +17,17 @@ describe(' closer', () => { // Robustness: ensure the closer appears exactly once expect((html.match(//g) || []).length).toBe(1); }); + + it('emits the standard MSO closer `` within ', async () => { + const html = await render( + + hi'} /> + + ); + + expect(html).toContain('' /* standard closer */); + expect(html).not.toContain('' /* slashed closer */); + // Robustness: ensure the closer appears exactly once + expect((html.match(//g) || []).length).toBe(1); + }); }); From d71cbb7c4ebe5413a2a88336a1836483ad607f88 Mon Sep 17 00:00:00 2001 From: CharlieHelps Date: Wed, 21 Jan 2026 19:31:11 +0000 Subject: [PATCH 02/18] test(jsx-email): update snapshots for head MSO closer --- .../render/.snapshots/render.test.tsx.snap | 20 +++++++++---------- .../.snapshots/tailwind-head.test.tsx.snap | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/jsx-email/test/render/.snapshots/render.test.tsx.snap b/packages/jsx-email/test/render/.snapshots/render.test.tsx.snap index 29588d1d..51804905 100644 --- a/packages/jsx-email/test/render/.snapshots/render.test.tsx.snap +++ b/packages/jsx-email/test/render/.snapshots/render.test.tsx.snap @@ -28,7 +28,7 @@ exports[`render > inlining 1`] = ` - + @@ -265,7 +265,7 @@ exports[`render > inlining 2`] = ` } } } - + @@ -338,7 +338,7 @@ exports[`render > inlining 2`] = ` `; exports[`render > renders the airbnb demo template 1`] = ` -"
Read undefined's review
 ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏
Airbnb

Here's what wrote

Now that the review period is over, we’ve posted ’s review to your Airbnb profile.

While it’s too late to write a review of your own, you can send your feedback to using your Airbnb message thread.

Read undefined's review
 ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏
Airbnb

Here's what wrote

Now that the review period is over, we’ve posted ’s review to your Airbnb profile.

While it’s too late to write a review of your own, you can send your feedback to using your Airbnb message thread.

+ @@ -453,7 +453,7 @@ exports[`render > renders the airbnb demo template 2`] = ` " `; -exports[`render > renders the plaid demo template 1`] = `"
Plaid

Verify Your Identity

Enter the following code to finish linking Venmo.

Not expecting this email?

Contact login@plaid.com if you did not request this code.

Securely powered by Plaid.

"`; +exports[`render > renders the plaid demo template 1`] = `"
Plaid

Verify Your Identity

Enter the following code to finish linking Venmo.

Not expecting this email?

Contact login@plaid.com if you did not request this code.

Securely powered by Plaid.

"`; exports[`render > renders the plaid demo template 2`] = ` " @@ -466,7 +466,7 @@ exports[`render > renders the plaid demo template 2`] = ` - + @@ -541,7 +541,7 @@ exports[`render > renders the vercel demo template 1`] = ` .dark\\:bg-black{background-color:rgb(0,0,0);} @media (prefers-color-scheme: dark){ .dark\\:bg-black{background-color:rgb(0,0,0);}} -}