Skip to content

charlie: align Conditional/Raw rendering with main (rehype plugins) #372

Description

@charliecreates

All PRs must branch from next/v3 and target base next/v3 (not main).

Context
main landed multiple correctness fixes for <Conditional>/<Raw> rendering (rehype plugins, correct conditional closers, no-dup guards, raw linebreak support). next/v3 currently implements conditionals via dangerouslySetInnerHTML and post-stringify regex replacements, which is incompatible with several of those fixes.

Maps to the report:

  • Section 2: “Conditional/Raw correctness fixes missing on next/v3”
  • Section 4: “Conditional/Raw exists on both but is implemented differently”

Scope

  1. Port the rehype-based approach from main:
    • Add packages/jsx-email/src/renderer/conditional.ts (from main commit 9d467757 + 2acbec9b).
    • Expand packages/jsx-email/src/renderer/raw.ts to include getRawPlugin() (from main commit fb8e1126).
  2. Update the renderer pipeline in packages/jsx-email/src/renderer/render.ts:
    • Use getRawPlugin() + getConditionalPlugin() (order matters: raw before conditional) like main.
    • Replace the regex-based raw unescape and the overly-strict reJsxTags with the main behavior (supports attributes).
  3. Align components:
    • Update packages/jsx-email/src/components/conditional.tsx to the main approach (render a marker element with data-* attributes; let rehype handle the final HTML).
    • Adjust packages/jsx-email/src/components/head.tsx to use the main pattern (<Conditional head mso><Raw .../></Conditional>) and remove the nested-<head> approach.
  4. Port/restore tests that prove the fixes:
    • conditional-endif-closer and conditional-raw-nodup style assertions from main (2acbec9b).
    • Ensure raw content with linebreaks is preserved (from main 1196527e).

Acceptance criteria (done when)

  • <Conditional> emits correct open/close sequences, including <![endif]/--> where required.
  • <Raw> content is preserved verbatim (including line breaks) and does not duplicate when nested inside <Conditional>.
  • render() output contains no leftover <jsx-email-cond ...> or <jsx-email-raw ...> wrapper tags.
  • Snapshot and non-snapshot tests pass on next/v3.

Verification

pnpm install

moon jsx-email:build
moon run :build --query "project~plugin-*"

FORCE_COLOR=1 moon jsx-email:test

# Optional: catch preview regressions since Conditional/Raw is exercised there
moon test-smoke:run.ci

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions