react-email-rails 0.10.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +28 -106
- data/lib/generators/react_email_rails/install_generator.rb +1 -2
- data/lib/generators/react_email_rails/templates/email/component.tsx +1 -1
- data/lib/react_email_rails/mailer_context.rb +2 -2
- data/lib/react_email_rails/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 727de1abdcab5dab75ca38cf157b919b01a74fc6e8c1aef873a658ebed812a68
|
|
4
|
+
data.tar.gz: 023f5e0bd2ac88a010e8db0a3f1bcdaac28b2cf9424106ad45d2a6ab68a8411a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ad68609561536c4eb37215e578d1b94ec37fb77ef80c9334b68e2277a29c10d5d13040fe5817810e430ff067fe7d2ac03960815649897ab424b0fade017981bb
|
|
7
|
+
data.tar.gz: 77e460b82033c452fd7a4baaa2b711dba701dce6f7c2e572b10f2ddd4b7ad5b87b0b8572b3cd47382adc72a247227a57a8a9e2109ed717e7b23f7d44619ba08a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.11.1
|
|
4
|
+
|
|
5
|
+
- Republish of 0.11.0 with no code changes. The 0.11.0 npm package was never published: npm provenance publishing requires GitHub-hosted runners, so the release workflow's publish job now runs on one. Do not use gem 0.11.0; it has no matching npm package.
|
|
6
|
+
|
|
7
|
+
## 0.11.0
|
|
8
|
+
|
|
9
|
+
- Generated applications now use React Email 6's unified `react-email` package for email components instead of `@react-email/components`.
|
|
10
|
+
- `@react-email/render` is now a runtime dependency of the `react-email-rails` npm package instead of a peer dependency, so applications no longer install it directly. The npm package now declares `react-dom` as a peer dependency alongside `react`, matching what the renderer already required at runtime.
|
|
11
|
+
|
|
3
12
|
## 0.10.0
|
|
4
13
|
|
|
5
14
|
- **Breaking:** Remove the instance-level `react_share` helper (calling `react_share` from within an action before `mail`). Pass per-mail props directly in the `react:` hash instead; use the class-level `react_share` (with `only`/`except`/`if`/`unless`) for conditional sharing.
|
data/README.md
CHANGED
|
@@ -8,16 +8,7 @@ react-email-rails lets Rails render React Email components into HTML and plain t
|
|
|
8
8
|
|
|
9
9
|
## Why
|
|
10
10
|
|
|
11
|
-
HTML email is still awkward. React Email gives you a nicer component model, email-safe primitives, Tailwind support, and TypeScript. This gem connects that workflow to Rails without replacing Action Mailer.
|
|
12
|
-
|
|
13
|
-
You get:
|
|
14
|
-
|
|
15
|
-
- React Email components rendered from `mail(...)`
|
|
16
|
-
- HTML and plain-text output from the same component
|
|
17
|
-
- Rails mailer previews, tests, queues, callbacks, and delivery
|
|
18
|
-
- Vite-powered development rendering
|
|
19
|
-
- A production renderer bundle built during `assets:precompile`
|
|
20
|
-
- Optional persistent rendering for high-volume workers
|
|
11
|
+
HTML email is still awkward. React Email gives you a nicer component model, email-safe primitives, Tailwind support, and TypeScript. This gem connects that workflow to Rails without replacing Action Mailer: components render through Vite in development and a prebuilt renderer bundle in production, with optional persistent rendering for high-volume workers.
|
|
21
12
|
|
|
22
13
|
## Status
|
|
23
14
|
|
|
@@ -34,7 +25,6 @@ The supported Ruby, Rails, Node, React, and Vite versions are tested in CI. Plea
|
|
|
34
25
|
- [Usage](#usage)
|
|
35
26
|
- [Configuration](#configuration)
|
|
36
27
|
- [Deployment](#deployment)
|
|
37
|
-
- [Development](#development)
|
|
38
28
|
- [Contributing](#contributing)
|
|
39
29
|
- [Security](#security)
|
|
40
30
|
- [License](#license)
|
|
@@ -43,12 +33,12 @@ The supported Ruby, Rails, Node, React, and Vite versions are tested in CI. Plea
|
|
|
43
33
|
|
|
44
34
|
| Dependency | Version |
|
|
45
35
|
|------------|---------|
|
|
46
|
-
| Ruby |
|
|
47
|
-
| Rails |
|
|
48
|
-
| Node |
|
|
36
|
+
| Ruby | 3.3+ |
|
|
37
|
+
| Rails | 7.1–8.x |
|
|
38
|
+
| Node | 20.19+ |
|
|
49
39
|
| Vite | 7 or 8 |
|
|
50
40
|
| React | 18 or 19 |
|
|
51
|
-
|
|
|
41
|
+
| React Email | 6.x |
|
|
52
42
|
|
|
53
43
|
We recommend [rails_vite](https://github.com/skryukov/rails_vite/) for Vite in Rails apps.
|
|
54
44
|
|
|
@@ -68,21 +58,20 @@ bundle install
|
|
|
68
58
|
bin/rails generate react_email_rails:install
|
|
69
59
|
```
|
|
70
60
|
|
|
71
|
-
The installer creates `config/initializers/react_email_rails.rb`, installs missing JavaScript dependencies when it can detect your package manager, adds `reactEmailRails()` to `vite.config
|
|
61
|
+
The installer creates `config/initializers/react_email_rails.rb`, installs missing JavaScript dependencies when it can detect your package manager, adds `reactEmailRails()` to `vite.config.*` (creating `vite.config.ts` if none exists), and creates `app/javascript/emails`.
|
|
72
62
|
|
|
73
63
|
After installation, the normal Rails flow applies:
|
|
74
64
|
|
|
75
65
|
- Generate mailers and components with `bin/rails generate react_email_rails:email ...`.
|
|
76
66
|
- Run `bin/dev` in development; email components render through Vite on demand.
|
|
77
67
|
- Run `bin/rails assets:precompile` for production; the renderer bundle builds automatically.
|
|
78
|
-
- Run `bin/rails react_email_rails:build` directly when CI or tests need the bundle without the full asset task.
|
|
79
68
|
|
|
80
69
|
### Manual Setup
|
|
81
70
|
|
|
82
71
|
If you prefer to wire things up yourself, install the npm package and React Email dependencies:
|
|
83
72
|
|
|
84
73
|
```sh
|
|
85
|
-
npm i react-email-rails
|
|
74
|
+
npm i react-email-rails react-email react react-dom
|
|
86
75
|
```
|
|
87
76
|
|
|
88
77
|
Use the equivalent command for pnpm, Yarn, or Bun if your app uses a different package manager.
|
|
@@ -107,7 +96,7 @@ Generate a mailer and React Email component:
|
|
|
107
96
|
bin/rails generate react_email_rails:email Account welcome
|
|
108
97
|
```
|
|
109
98
|
|
|
110
|
-
The generator follows Rails' mailer generator shape: `NAME [method method]`. It creates a mailer, React component, mailer preview, and test. It also reads `emails.path` and `emails.extension` from `reactEmailRails()` when available.
|
|
99
|
+
The generator follows Rails' mailer generator shape: `NAME [method method]`. It creates a mailer, React component, mailer preview, and test. It also reads `emails.path` and `emails.extension` from your `reactEmailRails()` Vite options when available.
|
|
111
100
|
|
|
112
101
|
Pass flags when you need to override the detected component directory or extension:
|
|
113
102
|
|
|
@@ -139,7 +128,7 @@ Then edit the generated component:
|
|
|
139
128
|
|
|
140
129
|
```tsx
|
|
141
130
|
// app/javascript/emails/account_mailer/welcome.tsx
|
|
142
|
-
import { Body, Container, Html, Text } from "
|
|
131
|
+
import { Body, Container, Html, Text } from "react-email"
|
|
143
132
|
|
|
144
133
|
type WelcomeProps = {
|
|
145
134
|
account: {
|
|
@@ -166,7 +155,7 @@ Deliver it like any other Action Mailer email:
|
|
|
166
155
|
AccountMailer.with(account: current_account).welcome.deliver_later
|
|
167
156
|
```
|
|
168
157
|
|
|
169
|
-
React Email also provides primitives like [`<Button>`, `<Heading>`, `<Tailwind>`, and more](https://react.email/
|
|
158
|
+
React Email also provides primitives like [`<Button>`, `<Heading>`, `<Tailwind>`, and more](https://react.email/components).
|
|
170
159
|
|
|
171
160
|
## Rendering
|
|
172
161
|
|
|
@@ -178,9 +167,9 @@ Every `react:` email renders HTML and plain text from the same component. If ren
|
|
|
178
167
|
|
|
179
168
|
### Live-Reloading Previews
|
|
180
169
|
|
|
181
|
-
In development, Action Mailer previews automatically reload themselves when you edit an email component. react-email-rails registers a [preview interceptor](https://api.rubyonrails.org/classes/ActionMailer/Base.html#class-ActionMailer::Base-label-Previewing+emails) that injects `@vite/client` into the preview, and the `reactEmailRails()` plugin broadcasts a full reload over Vite's
|
|
170
|
+
In development, Action Mailer previews automatically reload themselves when you edit an email component. react-email-rails registers a [preview interceptor](https://api.rubyonrails.org/classes/ActionMailer/Base.html#class-ActionMailer::Base-label-Previewing+emails) that injects `@vite/client` into the preview, and the `reactEmailRails()` plugin broadcasts a full reload over Vite's WebSocket whenever a file under your emails directory changes.
|
|
182
171
|
|
|
183
|
-
|
|
172
|
+
`live_reload_url` defaults to Vite's `http://localhost:5173`. Point it elsewhere if your dev server runs on a different port, or set it to a falsy value to disable live reload:
|
|
184
173
|
|
|
185
174
|
```ruby
|
|
186
175
|
ReactEmailRails.configure do |config|
|
|
@@ -192,31 +181,7 @@ end
|
|
|
192
181
|
|
|
193
182
|
### Passing Props
|
|
194
183
|
|
|
195
|
-
Top-level keys passed to `react:` become props on the component's default export. The API is intentionally close to [inertia-rails](https://inertia-rails.dev), so apps using both libraries should feel consistent.
|
|
196
|
-
|
|
197
|
-
```ruby
|
|
198
|
-
mail(
|
|
199
|
-
to: account.email,
|
|
200
|
-
subject: "Welcome",
|
|
201
|
-
react: {
|
|
202
|
-
account: {
|
|
203
|
-
name: account.name,
|
|
204
|
-
},
|
|
205
|
-
},
|
|
206
|
-
)
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
```tsx
|
|
210
|
-
type WelcomeProps = {
|
|
211
|
-
account: {
|
|
212
|
-
name: string
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
export default function Welcome({ account }: WelcomeProps) {
|
|
217
|
-
// ...
|
|
218
|
-
}
|
|
219
|
-
```
|
|
184
|
+
Top-level keys passed to `react:` become props on the component's default export, as shown in the [Quick Start](#quick-start). The API is intentionally close to [inertia-rails](https://inertia-rails.dev), so apps using both libraries should feel consistent.
|
|
220
185
|
|
|
221
186
|
### Component Inference
|
|
222
187
|
|
|
@@ -249,7 +214,7 @@ class AccountMailer < ApplicationMailer
|
|
|
249
214
|
end
|
|
250
215
|
```
|
|
251
216
|
|
|
252
|
-
Action Mailer's
|
|
217
|
+
Action Mailer's internal assigns, such as `params` and `rendered_format`, are excluded from instance props.
|
|
253
218
|
|
|
254
219
|
To make React the default for every action, set `default react: true` on the mailer (or `ApplicationMailer`). Each `mail` call then renders the inferred component without repeating `react: true`, and a single action can opt back out with `react: false`:
|
|
255
220
|
|
|
@@ -361,26 +326,12 @@ Every `react:` email receives `mailer` and `message` props, mirroring the [`mail
|
|
|
361
326
|
|
|
362
327
|
```tsx
|
|
363
328
|
import type { Mailer, Message } from "react-email-rails"
|
|
364
|
-
import { Body, Container, Html, Text } from "@react-email/components"
|
|
365
329
|
|
|
366
330
|
type WelcomeProps = {
|
|
367
331
|
account: { name: string }
|
|
368
332
|
mailer: Mailer
|
|
369
333
|
message: Message
|
|
370
334
|
}
|
|
371
|
-
|
|
372
|
-
export default function Welcome({ account, mailer, message }: WelcomeProps) {
|
|
373
|
-
return (
|
|
374
|
-
<Html>
|
|
375
|
-
<Body>
|
|
376
|
-
<Container>
|
|
377
|
-
<Text>Welcome, {account.name}</Text>
|
|
378
|
-
<Text>Re: {message.subject}</Text>
|
|
379
|
-
</Container>
|
|
380
|
-
</Body>
|
|
381
|
-
</Html>
|
|
382
|
-
)
|
|
383
|
-
}
|
|
384
335
|
```
|
|
385
336
|
|
|
386
337
|
| Prop | Example |
|
|
@@ -394,7 +345,7 @@ export default function Welcome({ account, mailer, message }: WelcomeProps) {
|
|
|
394
345
|
|
|
395
346
|
Context is merged before prop serialization, so keys follow `config.transform_props` just like your own props. The exported TypeScript types describe the default `:lower_camel` shape.
|
|
396
347
|
|
|
397
|
-
Per-mail and shared props win on conflict, so a prop named `mailer` or `message` overrides the injected context.
|
|
348
|
+
Per-mail and shared props win on conflict, so a prop named `mailer` or `message` overrides the injected context. When props come from a serializer, the context is merged in as long as `as_json` returns a hash; collections, arrays, and other non-object values pass through unchanged so their top-level shape is preserved.
|
|
398
349
|
|
|
399
350
|
### Prop Serialization
|
|
400
351
|
|
|
@@ -404,7 +355,7 @@ Prop keys are camelized by default, so `plan_name` arrives in React as `planName
|
|
|
404
355
|
|
|
405
356
|
### Component Files
|
|
406
357
|
|
|
407
|
-
Files and directories starting with `_` are
|
|
358
|
+
Files and directories starting with `_` are excluded from the email component registry by default. Use them for shared components, layouts, and helpers:
|
|
408
359
|
|
|
409
360
|
```text
|
|
410
361
|
app/javascript/emails/
|
|
@@ -422,7 +373,7 @@ Action Mailer layouts are not applied to `react:` emails. In React Email, layout
|
|
|
422
373
|
|
|
423
374
|
```tsx
|
|
424
375
|
// app/javascript/emails/_components/email_layout.tsx
|
|
425
|
-
import { Body, Container, Html } from "
|
|
376
|
+
import { Body, Container, Html } from "react-email"
|
|
426
377
|
import type { ReactNode } from "react"
|
|
427
378
|
|
|
428
379
|
type EmailLayoutProps = {
|
|
@@ -442,7 +393,7 @@ export function EmailLayout({ children }: EmailLayoutProps) {
|
|
|
442
393
|
|
|
443
394
|
```tsx
|
|
444
395
|
// app/javascript/emails/account_mailer/welcome.tsx
|
|
445
|
-
import { Text } from "
|
|
396
|
+
import { Text } from "react-email"
|
|
446
397
|
import { EmailLayout } from "../_components/email_layout"
|
|
447
398
|
|
|
448
399
|
export default function Welcome() {
|
|
@@ -526,7 +477,7 @@ Persistent mode details:
|
|
|
526
477
|
|
|
527
478
|
### Render Options
|
|
528
479
|
|
|
529
|
-
`render_options` is passed to [@react-email/render](https://react.email/docs/utilities/render). Use `html` and `text` keys to configure each output. Option keys are camelized before they cross into JavaScript
|
|
480
|
+
`render_options` is passed to [@react-email/render](https://react.email/docs/utilities/render). Use `html` and `text` keys to configure each output. Option keys are camelized before they cross into JavaScript, so `html_to_text_options` becomes `htmlToTextOptions`.
|
|
530
481
|
|
|
531
482
|
```ruby
|
|
532
483
|
ReactEmailRails.configure do |config|
|
|
@@ -561,7 +512,7 @@ The callback receives the error plus render context such as `component:`.
|
|
|
561
512
|
|
|
562
513
|
### Instrumentation
|
|
563
514
|
|
|
564
|
-
Every render emits `render.react-email-rails` through [ActiveSupport::Notifications](https://guides.rubyonrails.org/active_support_instrumentation.html). Payloads include `component` and
|
|
515
|
+
Every render emits `render.react-email-rails` through [ActiveSupport::Notifications](https://guides.rubyonrails.org/active_support_instrumentation.html). Payloads include the `component` and, on success, the rendered HTML size in `html_bytes`.
|
|
565
516
|
|
|
566
517
|
```ruby
|
|
567
518
|
ActiveSupport::Notifications.subscribe("render.react-email-rails") do |event|
|
|
@@ -574,18 +525,9 @@ end
|
|
|
574
525
|
|
|
575
526
|
### Vite Configuration
|
|
576
527
|
|
|
577
|
-
Most apps only need the plugin from [Installation](#installation)
|
|
578
|
-
|
|
579
|
-
```ts
|
|
580
|
-
import { defineConfig } from "vite"
|
|
581
|
-
import { reactEmailRails } from "react-email-rails"
|
|
582
|
-
|
|
583
|
-
export default defineConfig({
|
|
584
|
-
plugins: [reactEmailRails()],
|
|
585
|
-
})
|
|
586
|
-
```
|
|
528
|
+
Most apps only need the bare `reactEmailRails()` plugin from [Installation](#installation).
|
|
587
529
|
|
|
588
|
-
The isolated renderer loads `reactEmailRails()`, JSX support, and component-facing Vite config such as `
|
|
530
|
+
The isolated renderer loads `reactEmailRails()`, JSX support, and component-facing Vite config such as `assetsInclude`, `css`, `define`, `esbuild`, `json`, `oxc`, and `resolve`. It does not load your other app plugins unless you explicitly add them with `vite.plugins`.
|
|
589
531
|
|
|
590
532
|
Server, preview, dependency optimization, and build output settings stay owned by react-email-rails so Rails can always find the renderer bundle.
|
|
591
533
|
|
|
@@ -617,7 +559,7 @@ reactEmailRails({
|
|
|
617
559
|
})
|
|
618
560
|
```
|
|
619
561
|
|
|
620
|
-
Component names come from the
|
|
562
|
+
Component names come from the file layout under `emails.path`. To map mailer actions to a different layout, override `component_path_resolver` on the Ruby side so both halves stay in sync.
|
|
621
563
|
|
|
622
564
|
### Email-Only Vite Plugins
|
|
623
565
|
|
|
@@ -653,7 +595,7 @@ reactEmailRails({
|
|
|
653
595
|
})
|
|
654
596
|
```
|
|
655
597
|
|
|
656
|
-
Externalized bundles can be smaller and may build faster, but the
|
|
598
|
+
Externalized bundles can be smaller and may build faster, but the packages they reference must be available at runtime.
|
|
657
599
|
|
|
658
600
|
## Deployment
|
|
659
601
|
|
|
@@ -663,7 +605,7 @@ Production deploys should run the normal Rails asset task:
|
|
|
663
605
|
bin/rails assets:precompile
|
|
664
606
|
```
|
|
665
607
|
|
|
666
|
-
react-email-rails hooks `react_email_rails:build` into `assets:precompile
|
|
608
|
+
react-email-rails hooks `react_email_rails:build` into `assets:precompile` (and `react_email_rails:clobber` into `assets:clobber`). The build task loads `reactEmailRails()` options from your Vite config and writes `tmp/react-email-rails/emails.js` with the email component registry.
|
|
667
609
|
|
|
668
610
|
You can run the renderer build directly:
|
|
669
611
|
|
|
@@ -673,9 +615,9 @@ bin/rails react_email_rails:build
|
|
|
673
615
|
|
|
674
616
|
Production rendering requires that bundle. If it is missing, rendering raises `ReactEmailRails::RenderError` and Action Mailer does not send the email.
|
|
675
617
|
|
|
676
|
-
Set `SKIP_REACT_EMAIL_RAILS_BUILD=1` to skip the automatic asset
|
|
618
|
+
Set `SKIP_REACT_EMAIL_RAILS_BUILD=1` to skip the automatic asset hooks. Directly running `bin/rails react_email_rails:build` always attempts the build.
|
|
677
619
|
|
|
678
|
-
The npm package, Vite,
|
|
620
|
+
The npm package, Vite, and React must be available when Rails runs `assets:precompile`.
|
|
679
621
|
|
|
680
622
|
The Ruby gem and npm package must stay on the same version. A protocol/version handshake catches mismatched installs and raises an actionable `ReactEmailRails::RenderError`.
|
|
681
623
|
|
|
@@ -701,29 +643,9 @@ end
|
|
|
701
643
|
|
|
702
644
|
If you check at boot, scope it to processes that send mail so the rest of the app does not pay the cost.
|
|
703
645
|
|
|
704
|
-
## Development
|
|
705
|
-
|
|
706
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup, checks, formatting, and release verification.
|
|
707
|
-
|
|
708
|
-
The short version:
|
|
709
|
-
|
|
710
|
-
```sh
|
|
711
|
-
bundle install
|
|
712
|
-
cd vite && pnpm install
|
|
713
|
-
```
|
|
714
|
-
|
|
715
|
-
Run the core checks before opening a pull request:
|
|
716
|
-
|
|
717
|
-
```sh
|
|
718
|
-
ruby scripts/check_version_sync.rb
|
|
719
|
-
bin/test
|
|
720
|
-
bin/lint
|
|
721
|
-
cd vite && pnpm run build
|
|
722
|
-
```
|
|
723
|
-
|
|
724
646
|
## Contributing
|
|
725
647
|
|
|
726
|
-
Bug reports and pull requests are welcome.
|
|
648
|
+
Bug reports and pull requests are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup, the checks to run before opening a pull request, and release expectations.
|
|
727
649
|
|
|
728
650
|
## Security
|
|
729
651
|
|
|
@@ -7,8 +7,7 @@ module ReactEmailRails::Generators; end
|
|
|
7
7
|
class ReactEmailRails::Generators::InstallGenerator < Rails::Generators::Base
|
|
8
8
|
JAVASCRIPT_PACKAGES = [
|
|
9
9
|
"react-email-rails",
|
|
10
|
-
"
|
|
11
|
-
"@react-email/components",
|
|
10
|
+
"react-email",
|
|
12
11
|
"react",
|
|
13
12
|
"react-dom",
|
|
14
13
|
].freeze
|
|
@@ -33,8 +33,8 @@ class ReactEmailRails::MailerContext
|
|
|
33
33
|
def message_context
|
|
34
34
|
message = mailer.message
|
|
35
35
|
|
|
36
|
-
MESSAGE_FIELDS.
|
|
37
|
-
|
|
36
|
+
MESSAGE_FIELDS.to_h do |field|
|
|
37
|
+
[field.to_s, message.public_send(field)]
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
end
|