shellscape / shellscape/jsx-email
MSO conditional comments in <head> use non-standard <![endif]/--> closing that breaks Classic Outlook
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1.3k
- Forks
- 55
- PR merge metrics
- No merged PRs in 30d
Description
- Component or Package Name:
jsx-email(renderer/conditional.ts) - Component or Package Version: 2.8.4
@jsx-email/cliVersion?: 2.8.4- Operating System (or Browser): Linux / Classic Outlook 2019, Outlook 365 desktop
- Node Version: 24.13.0
- Link to reproduction (⚠️ read below): Not relevant
Expected Behavior
MSO conditional comments in the <head> section should use the standard closing syntax <![endif]-->:
<!--[if mso]><xml><o:OfficeDocumentSettings><o:AllowPNG /><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml><![endif]-->
Actual Behavior
MSO conditional comments in the use non-standard closing syntax <![endif]/-->:
<!--[if mso]><xml><o:OfficeDocumentSettings><o:AllowPNG /><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml><![endif]/-->
Note the trailing / before -->. This causes Classic Outlook (2007-2019, Office 365 desktop) to fail to parse the conditional, resulting in emails not rendering at all.
Additional Information
The issue is in src/renderer/conditional.ts where there's intentional logic to use <![endif]/--> for head conditionals:
// when adjacent comments appear. Use the `<![endif]/-->` form
closeRaw = '<![endif]/-->';
However, <![endif]/--> is not valid IE/Outlook conditional comment syntax. The standard closing is <![endif]-->. Classic Outlook's Word rendering engine doesn't recognize the non-standard form.
Workaround:
const html = await render(<Email />);
const fixed = html.replaceAll('<![endif]/-->', '<![endif]-->');
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/renderer/conditional.ts and inspect the head-conditional branch that assigns closeRaw. Render an email containing an MSO head conditional and verify that the output uses the standard <![endif]--> closing without the slash. Done means Classic Outlook-compatible conditional markup is emitted without requiring the documented workaround.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- html, typescript
- Domain
- web-dev
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100