render: unstableTextConversion outputs HTML comments and repeats link URLs in plain text

Abierto Apto para principiantes
#3,864 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@lakshya-dhariwal ya está trabajando en esto.

Desde el 6/11/2026.

  • #3873 de @lakshya-dhariwal — abierto

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
87/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
react, typescript
Área
backend, testing

Línea de trabajo

Empieza con packages/render/src/shared/utils/unstable-to-plain-text.ts y sigue cómo maneja los comentarios HTML y el texto de los enlaces al convertir la salida renderizada. El issue incluye una reproducción autónoma con render(); ejecútala para ver los fallos y luego añade casos de spec que usen una salida real de render(), como se sugiere. El trabajo está terminado cuando se omitan los comentarios y el texto de los enlaces coincidente y las URL aparezcan solo una vez cada uno.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

What versions are you using? (if relevant)

@react-email/[email protected], [email protected], [email protected]

Describe the Bug

With unstableTextConversion: true, the plain-text output keeps HTML comments and sometimes repeats link URLs:

  1. React's Suspense markers <!--$--> and <!--/$--> show up as $ and /$ at the start and end of every render.
  2. <Button>'s Outlook conditional comments come out as raw text: [if mso]><i style="mso-font-width:0%;mso-text-raise:0px" hidden></i><![endif].
  3. A link whose text equals its URL repeats the URL (Hi [email protected] [email protected]), unless the link is the first thing in its block. The check that drops the URL when it matches the text seems to pick up the space before the link.

The default converter (toPlainText) doesn't do any of these.

What is affected (leave empty if unsure)

Render Utility

Link to the code that reproduces this issue

Self-contained script below (npm i @react-email/render react-email react react-dom tsx, then npx tsx repro.tsx).

import * as React from 'react';
import { render } from '@react-email/render';
import { Button, Text } from 'react-email';

const opts = { plainText: true, unstableTextConversion: true };

console.log(JSON.stringify(await render(<Text>Hi <a href="mailto:[email protected]">[email protected]</a></Text>, opts)));
console.log(JSON.stringify(await render(<Text><a href="https://a.b">https://a.b</a></Text>, opts)));
console.log(JSON.stringify(await render(<Button href="https://a.b">Go</Button>, opts)));
To Reproduce

Run the script. Output:

"$\n\nHi [email protected] [email protected]\n\n/$"
"$\n\nhttps://a.b\n\n/$"
"$[if mso]><i style=\"mso-font-width:0%;mso-text-raise:0px\" hidden></i><![endif]Go[if mso]><i style=\"mso-font-width:0%\" hidden> </i><![endif] https://a.b/$"
Expected Behavior
"Hi [email protected]"
"https://a.b"
"Go https://a.b"

HTML comments are skipped, and a link whose text matches its URL is printed once wherever it appears. In packages/render/src/shared/utils/unstable-to-plain-text.ts the parser seems to treat <!--...--> as a tag named !--, which isn't in SKIPPED_TAGS. I'm happy to open a PR with spec cases built from real render() output.

What's your node version? (if relevant)

v22.15.0

Lenguaje dominante
TypeScript
Estrellas
19.9k
Forks
1.1k
Merge medio
1 d 15 h
PR fusionados (30 d)
49

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de resend/react-email

Todos los issues de resend/react-email

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.