Plain Text Generation
Relevant source files
The following files were used as context for generating this wiki page:
Plain Text Generation converts React-based email templates into a text-only format. This process ensures that email content remains accessible to recipients using email clients that do not support HTML or for users who prefer text-only versions for accessibility and performance.
The system utilizes specialized utilities to parse HTML structures and transform them into human-readable strings while adhering to specific formatting rules, such as link de-duplication and image suppression.
Sources: skills/react-email/SKILL.md:154-156, packages/render/src/shared/utils/to-plain-text.spec.ts:7-14
Core Transformation Logic
The generation process converts a rendered HTML string into plain text by applying a set of default selectors and formatting rules. Developers trigger this by passing the plainText: true option to the render function.
The diagram above shows the data flow from a React component to the final plain text output.
Sources: skills/react-email/SKILL.md:154-156, packages/render/src/browser/render-web.spec.tsx:112-123
Element Handling and Filtering
The parser follows specific rules for different HTML elements to maintain readability:
- Images: Images are skipped by default. Neither the
srcnor thealttext appears in the output. - Explicit Skips: Any element with the attribute
data-skip-in-text="true"is excluded from the final output. - Links: Links are formatted without brackets. If the link text and the
hrefare identical, the system hides the redundanthref. - Head and Styles: Content inside
<head>, including<style>and<title>tags, is dropped to prevent CSS or metadata from leaking into the text body.
Sources: packages/render/src/shared/utils/to-plain-text.spec.ts:7-25, packages/render/src/shared/utils/to-plain-text.spec.ts:40-54, packages/render/src/shared/utils/unstable-to-plain-text.spec.ts:40-48
Table Formatting
Tables can be rendered as aligned rows using the data-text-format="dataTable" attribute. Standard layout tables used by components like Row and Column typically result in no specific separation between cells to maintain flow.
Sources: packages/render/src/shared/utils/to-plain-text.spec.ts:27-38, packages/render/src/shared/utils/unstable-to-plain-text.spec.ts:88-93
Parser Variants
The project maintains two primary utilities for plain text generation, as evidenced by the testing suite.
Standard Parser (toPlainText)
The standard parser provides predictable output by stripping formatting and normalizing structure. It supports custom selectors that allow developers to override default behaviors or add new skipping rules for specific CSS selectors.
Sources: packages/render/src/shared/utils/to-plain-text.spec.ts:57-89
Unstable Parser (unstableToPlainText)
The unstableToPlainText utility introduces specific behavioral changes to improve content quality and avoid spam filters:
| Feature | Behavior |
|---|---|
| Heading Case | Preserves original casing (e.g., "iPhone" remains "iPhone" instead of "IPHONE"). |
| Block Separation | Separates every block with exactly one blank line for consistency. |
| Word Wrapping | Disables automatic line wrapping at 80 columns to keep long URLs intact. |
| List Indentation | Renders nested unordered lists with indentation and numbers ordered lists. |
| Link Schemes | Strips the mailto: scheme from email link hrefs. |
Sources: packages/render/src/shared/utils/unstable-to-plain-text.spec.ts:50-59, packages/render/src/shared/utils/unstable-to-plain-text.spec.ts:61-68, packages/render/src/shared/utils/unstable-to-plain-text.spec.ts:108-115, packages/render/src/shared/utils/unstable-to-plain-text.spec.ts:221-226
Whitespace and Break Handling
The generation logic distinguishes between block-level separation and explicit hard breaks.
- Hard Breaks (
<br>): Hard breaks stack additively on top of block separation. Unlike standard block margins, hard breaks at the very start or end of the output are preserved. - Whitespace Preservation: Text inside
<pre>tags retains its original whitespace and indentation. - Empty Blocks: Empty blocks between content contribute to the final newline count to preserve the intended layout.
Sources: packages/render/src/shared/utils/unstable-to-plain-text.spec.ts:138-146, packages/render/src/shared/utils/unstable-to-plain-text.spec.ts:153-157, packages/render/src/shared/utils/unstable-to-plain-text.spec.ts:228-233
Summary
Plain text generation in React Email is a controlled transformation process that prioritizes accessibility and readability. By stripping stylistic elements like images and CSS while providing structured handling for links, lists, and tables, the system produces a functional fallback for all email clients. The distinction between the standard and unstable parsers allows for fine-tuning heading cases and line wrapping to avoid spam heuristics and maintain brand voice in text-only environments.
Sources: skills/react-email/SKILL.md:154-156, packages/render/src/shared/utils/unstable-to-plain-text.spec.ts:50-59