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
- 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).
- 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).
- 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.
- 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
All PRs must branch from
next/v3and target basenext/v3(notmain).Context
mainlanded multiple correctness fixes for<Conditional>/<Raw>rendering (rehype plugins, correct conditional closers, no-dup guards, raw linebreak support).next/v3currently implements conditionals viadangerouslySetInnerHTMLand post-stringify regex replacements, which is incompatible with several of those fixes.Maps to the report:
Scope
main:packages/jsx-email/src/renderer/conditional.ts(frommaincommit9d467757+2acbec9b).packages/jsx-email/src/renderer/raw.tsto includegetRawPlugin()(frommaincommitfb8e1126).packages/jsx-email/src/renderer/render.ts:getRawPlugin()+getConditionalPlugin()(order matters: raw before conditional) likemain.reJsxTagswith themainbehavior (supports attributes).packages/jsx-email/src/components/conditional.tsxto themainapproach (render a marker element withdata-*attributes; let rehype handle the final HTML).packages/jsx-email/src/components/head.tsxto use themainpattern (<Conditional head mso><Raw .../></Conditional>) and remove the nested-<head>approach.conditional-endif-closerandconditional-raw-nodupstyle assertions frommain(2acbec9b).main1196527e).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.next/v3.Verification