react-email-rails 0.6.0 → 0.7.0
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 +8 -0
- data/README.md +25 -4
- data/lib/generators/react_email_rails/email_generator.rb +0 -1
- data/lib/generators/react_email_rails/vite_config_files.rb +0 -1
- data/lib/react_email_rails/action_mailer.rb +12 -6
- data/lib/react_email_rails/configuration.rb +9 -3
- data/lib/react_email_rails/preview_live_reload.rb +33 -0
- data/lib/react_email_rails/props_resolver.rb +0 -2
- data/lib/react_email_rails/railtie.rb +1 -0
- data/lib/react_email_rails/render_modes/persistent/command_runner.rb +0 -3
- data/lib/react_email_rails/render_modes/persistent/server.rb +0 -6
- data/lib/react_email_rails/render_modes/subprocess.rb +0 -3
- data/lib/react_email_rails/render_protocol.rb +0 -1
- data/lib/react_email_rails/rendered_email.rb +0 -1
- data/lib/react_email_rails/shared_props.rb +0 -6
- data/lib/react_email_rails/version.rb +1 -1
- data/lib/react_email_rails.rb +1 -3
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 957e5d57adf900478fa7736755f400bd424dbfc4aa47bee2e6ef82822fa9d048
|
|
4
|
+
data.tar.gz: 7bdd67d8de3ce6051c1849338337e74734fb51514d18eee0931ba172c2edac93
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7e44fad8be9e76043f9811a5cadffc9ffe4a6da0dd4b649b283a6f5af599d600d4c69750a2dc454224923abab985204f07238978def3fd2ca3af7506c73444d6
|
|
7
|
+
data.tar.gz: 86617b862cfaf09b4a20a21918b042732648d8a8383dcf319cbe4ba77e5f982d9dd98d0abdc643d8ef902dfcc46485f0428547c0aed2a2eccae7e508a87ee5c2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
- Add development live-reloading for Action Mailer previews. A development-only preview interceptor injects Vite's `@vite/client` into previews, and the `reactEmailRails()` plugin triggers a full reload when an email component changes, so the open preview refreshes on save. Configure the dev-server URL with `live_reload_url`, or set it to a falsy value to disable.
|
|
6
|
+
|
|
7
|
+
## 0.6.1
|
|
8
|
+
|
|
9
|
+
- Fix `react:` rendering — and the `mailer`/`message` props — being skipped for actions that opt in through a class-level `default react: true` rather than a per-`mail` `react:` option. `mail` now resolves `react` (in any form: `true`, a component string, or a prop hash) from the mailer's `default`, a per-action `react: false` opts back out, and the internal `react`/`props`/`deep_merge` options never leak onto the message as email headers.
|
|
10
|
+
|
|
3
11
|
## 0.6.0
|
|
4
12
|
|
|
5
13
|
- Every `react:` email now receives `mailer` and `message` props, mirroring Action Mailer's `mailer`/`message` ERB view helpers. Rendering now happens after Action Mailer assigns headers, so `message` includes subject, addressing, and default `from`/`reply_to` values. Per-mail and shared props win on conflict, serializers whose `as_json` returns a Hash receive the context, and collection props keep their original shape. The npm package exports matching `Mailer`/`Message` TypeScript types.
|
data/README.md
CHANGED
|
@@ -30,8 +30,8 @@ The supported Ruby, Rails, Node, React, and Vite versions are tested in CI. Plea
|
|
|
30
30
|
|
|
31
31
|
- [Requirements](#requirements)
|
|
32
32
|
- [Installation](#installation)
|
|
33
|
-
- [
|
|
34
|
-
- [
|
|
33
|
+
- [Quick Start](#quick-start)
|
|
34
|
+
- [Rendering](#rendering)
|
|
35
35
|
- [Usage](#usage)
|
|
36
36
|
- [Configuration](#configuration)
|
|
37
37
|
- [Deployment](#deployment)
|
|
@@ -100,7 +100,7 @@ export default defineConfig({
|
|
|
100
100
|
})
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
##
|
|
103
|
+
## Quick Start
|
|
104
104
|
|
|
105
105
|
Generate a mailer and React Email component:
|
|
106
106
|
|
|
@@ -169,7 +169,7 @@ AccountMailer.with(account: current_account).welcome.deliver_later
|
|
|
169
169
|
|
|
170
170
|
React Email also provides primitives like [`<Button>`, `<Heading>`, `<Tailwind>`, and more](https://react.email/docs/components/html).
|
|
171
171
|
|
|
172
|
-
##
|
|
172
|
+
## Rendering
|
|
173
173
|
|
|
174
174
|
In development, react-email-rails renders components through Vite's dev pipeline. Your email components get the same module resolution and transforms as the rest of your frontend.
|
|
175
175
|
|
|
@@ -177,6 +177,18 @@ In production, `assets:precompile` builds a server-side renderer bundle from you
|
|
|
177
177
|
|
|
178
178
|
Every `react:` email renders HTML and plain text from the same component. If rendering fails, the email is not sent and `ReactEmailRails::RenderError` is raised.
|
|
179
179
|
|
|
180
|
+
### Live-Reloading Previews
|
|
181
|
+
|
|
182
|
+
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.
|
|
183
|
+
|
|
184
|
+
The `live_reload_url` defaults to Vite's `http://localhost:5173`, but you can point elsewhere if needed, or set it to a falsy value to disable live reload. (See [Configuration](#configuration))
|
|
185
|
+
|
|
186
|
+
```ruby
|
|
187
|
+
ReactEmailRails.configure do |config|
|
|
188
|
+
config.live_reload_url = "http://localhost:3036" # or nil or false to disable
|
|
189
|
+
end
|
|
190
|
+
```
|
|
191
|
+
|
|
180
192
|
## Usage
|
|
181
193
|
|
|
182
194
|
### Passing Props
|
|
@@ -240,6 +252,14 @@ end
|
|
|
240
252
|
|
|
241
253
|
Action Mailer's framework assigns, including `params` and `rendered_format`, are excluded from instance props.
|
|
242
254
|
|
|
255
|
+
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`:
|
|
256
|
+
|
|
257
|
+
```ruby
|
|
258
|
+
class ApplicationMailer < ActionMailer::Base
|
|
259
|
+
default react: true
|
|
260
|
+
end
|
|
261
|
+
```
|
|
262
|
+
|
|
243
263
|
### Explicit Components
|
|
244
264
|
|
|
245
265
|
Pass a component name when the mailer action and component path do not line up:
|
|
@@ -484,6 +504,7 @@ end
|
|
|
484
504
|
| `render_process_max_requests` | `1_000` |
|
|
485
505
|
| `on_render_error` | `nil` |
|
|
486
506
|
| `deep_merge_shared_props` | `false` |
|
|
507
|
+
| `live_reload_url` | `http://localhost:5173` |
|
|
487
508
|
|
|
488
509
|
### Prop Transformation
|
|
489
510
|
|
|
@@ -139,7 +139,6 @@ class ReactEmailRails::Generators::EmailGenerator < Rails::Generators::NamedBase
|
|
|
139
139
|
].find { |path| File.exist?(File.join(destination_root, path)) }
|
|
140
140
|
end
|
|
141
141
|
|
|
142
|
-
# The reactEmailRails({ ... }) plugin call, up to the option key being scanned for.
|
|
143
142
|
PLUGIN_OPENING = /reactEmailRails\s*\(\s*\{.*?/m
|
|
144
143
|
|
|
145
144
|
def emails_path_from_vite_config
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
module ReactEmailRails::ActionMailer
|
|
2
2
|
extend(ActiveSupport::Concern)
|
|
3
3
|
|
|
4
|
-
# `react_email_share` kwargs reserved for `before_action` filtering, not prop data.
|
|
5
4
|
SHARED_FILTER_OPTIONS = [:if, :unless, :only, :except].freeze
|
|
6
5
|
|
|
7
6
|
prepended do
|
|
@@ -28,12 +27,15 @@ module ReactEmailRails::ActionMailer
|
|
|
28
27
|
end
|
|
29
28
|
|
|
30
29
|
def mail(headers = {}, &block)
|
|
31
|
-
return super unless headers.is_a?(Hash)
|
|
30
|
+
return super unless headers.is_a?(Hash)
|
|
31
|
+
return super if headers.empty? && @_mail_was_called
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
react = headers.key?(:react) ? headers[:react] : compute_default(self.class.default[:react])
|
|
34
|
+
return super unless react
|
|
35
|
+
|
|
36
|
+
props = headers[:props]
|
|
37
|
+
deep_merge = headers[:deep_merge]
|
|
38
|
+
headers = headers.except(:react, :props, :deep_merge)
|
|
37
39
|
|
|
38
40
|
component, resolved_props = ReactEmailRails::PropsResolver.new(self).resolve(react, props)
|
|
39
41
|
resolved_props = ReactEmailRails::SharedProps.new(self).merge_into(
|
|
@@ -53,6 +55,10 @@ module ReactEmailRails::ActionMailer
|
|
|
53
55
|
|
|
54
56
|
private
|
|
55
57
|
|
|
58
|
+
def assign_headers_to_message(message, headers)
|
|
59
|
+
super(message, headers.except(:react, :props, :deep_merge))
|
|
60
|
+
end
|
|
61
|
+
|
|
56
62
|
def react_email_render(component, props)
|
|
57
63
|
props = ReactEmailRails::MailerContext.new(self).merge_into(props)
|
|
58
64
|
render_options = ReactEmailRails.configuration.resolve_render_options(self)
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
class ReactEmailRails::Configuration
|
|
2
|
-
# Must match OUT_DIR/BUNDLE_FILE in vite/src/index.ts (check_version_sync.rb asserts it).
|
|
3
2
|
BUNDLE_PATH = "tmp/react-email-rails/emails.js"
|
|
4
3
|
BUILD_BIN = "node_modules/.bin/react-email-rails-build"
|
|
5
4
|
CONFIG_BIN = "node_modules/.bin/react-email-rails-config"
|
|
@@ -7,6 +6,7 @@ class ReactEmailRails::Configuration
|
|
|
7
6
|
|
|
8
7
|
DEFAULT_RENDER_TIMEOUT = 10
|
|
9
8
|
DEFAULT_RENDER_PROCESS_MAX_REQUESTS = 1_000
|
|
9
|
+
DEFAULT_LIVE_RELOAD_URL = "http://localhost:5173"
|
|
10
10
|
|
|
11
11
|
RENDER_MODES = {
|
|
12
12
|
subprocess: ReactEmailRails::RenderModes::Subprocess,
|
|
@@ -35,6 +35,7 @@ class ReactEmailRails::Configuration
|
|
|
35
35
|
:transform_props,
|
|
36
36
|
:on_render_error,
|
|
37
37
|
:deep_merge_shared_props,
|
|
38
|
+
:live_reload_url,
|
|
38
39
|
)
|
|
39
40
|
|
|
40
41
|
attr_reader(
|
|
@@ -54,10 +55,17 @@ class ReactEmailRails::Configuration
|
|
|
54
55
|
config.transform_props = :lower_camel
|
|
55
56
|
config.on_render_error = nil
|
|
56
57
|
config.deep_merge_shared_props = false
|
|
58
|
+
config.live_reload_url = DEFAULT_LIVE_RELOAD_URL
|
|
57
59
|
end
|
|
58
60
|
end
|
|
59
61
|
end
|
|
60
62
|
|
|
63
|
+
def resolve_live_reload_url
|
|
64
|
+
return if live_reload_url.blank?
|
|
65
|
+
|
|
66
|
+
live_reload_url.to_s.chomp("/")
|
|
67
|
+
end
|
|
68
|
+
|
|
61
69
|
def render_mode=(value)
|
|
62
70
|
if (value.is_a?(Symbol) || value.is_a?(String)) && !RENDER_MODES.key?(value.to_sym)
|
|
63
71
|
raise(ArgumentError, "Unknown react-email-rails render mode: #{value.inspect}")
|
|
@@ -88,8 +96,6 @@ class ReactEmailRails::Configuration
|
|
|
88
96
|
end
|
|
89
97
|
end
|
|
90
98
|
|
|
91
|
-
# A callable render_options is instance_exec'd against `context` (the mailer) when given,
|
|
92
|
-
# so it can use per-mail helpers; otherwise it's called or returned as-is.
|
|
93
99
|
def resolve_render_options(context = nil)
|
|
94
100
|
value =
|
|
95
101
|
if render_options.respond_to?(:call) && context
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
class ReactEmailRails::PreviewLiveReload
|
|
2
|
+
SCRIPT_TEMPLATE = %(<script type="module" src="%s/@vite/client"></script>)
|
|
3
|
+
BODY_CLOSE = %r{</body>}i
|
|
4
|
+
|
|
5
|
+
class << self
|
|
6
|
+
def previewing_email(message)
|
|
7
|
+
url = ReactEmailRails.configuration.resolve_live_reload_url
|
|
8
|
+
return unless url
|
|
9
|
+
|
|
10
|
+
part = html_part(message)
|
|
11
|
+
return unless part
|
|
12
|
+
|
|
13
|
+
part.body = inject(part.body.decoded, url)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def html_part(message)
|
|
19
|
+
return message.html_part if message.html_part
|
|
20
|
+
return message if message.mime_type == "text/html"
|
|
21
|
+
|
|
22
|
+
nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def inject(html, url)
|
|
26
|
+
snippet = format(SCRIPT_TEMPLATE, url)
|
|
27
|
+
return html if html.include?(snippet)
|
|
28
|
+
return "#{html}#{snippet}" unless BODY_CLOSE.match?(html)
|
|
29
|
+
|
|
30
|
+
html.sub(BODY_CLOSE) { |tag| "#{snippet}#{tag}" }
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
class ReactEmailRails::PropsResolver
|
|
2
2
|
INTERNAL_ASSIGN_PREFIX = "_"
|
|
3
|
-
# Some Action Mailer framework assigns do not use the internal `_` prefix.
|
|
4
3
|
RESERVED_ASSIGNS = ["params", "rendered_format"].freeze
|
|
5
4
|
|
|
6
5
|
def initialize(mailer)
|
|
@@ -34,7 +33,6 @@ class ReactEmailRails::PropsResolver
|
|
|
34
33
|
end
|
|
35
34
|
|
|
36
35
|
def assign_props
|
|
37
|
-
# `react: true` infers the component; instance vars become props only when the mailer opts in.
|
|
38
36
|
return {} unless mailer.class.react_email_use_instance_props
|
|
39
37
|
|
|
40
38
|
mailer.instance_variables.each_with_object({}) do |ivar, props|
|
|
@@ -2,6 +2,7 @@ class ReactEmailRails::Railtie < Rails::Railtie
|
|
|
2
2
|
initializer("react-email-rails.action_mailer") do
|
|
3
3
|
ActiveSupport.on_load(:action_mailer) do
|
|
4
4
|
prepend(ReactEmailRails::ActionMailer)
|
|
5
|
+
register_preview_interceptor(ReactEmailRails::PreviewLiveReload) if Rails.env.development?
|
|
5
6
|
end
|
|
6
7
|
end
|
|
7
8
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
class ReactEmailRails::RenderModes::Persistent::CommandRunner
|
|
2
|
-
# Eager (not lazy) so concurrent first renders can't each create separate Mutexes.
|
|
3
2
|
@mutex = Mutex.new
|
|
4
3
|
|
|
5
4
|
class << self
|
|
@@ -30,8 +29,6 @@ class ReactEmailRails::RenderModes::Persistent::CommandRunner
|
|
|
30
29
|
end
|
|
31
30
|
end
|
|
32
31
|
|
|
33
|
-
# A forked child inherits the parent's Servers and their open pipes; sharing those pipes
|
|
34
|
-
# interleaves requests across processes, so drop them without killing the parent's process.
|
|
35
32
|
def reset_after_fork
|
|
36
33
|
return if @owner_pid == Process.pid && @servers
|
|
37
34
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
class ReactEmailRails::RenderModes::Persistent::Server
|
|
2
2
|
STDERR_LIMIT = 8 * 1024
|
|
3
3
|
|
|
4
|
-
# Minimal Process::Status stand-in; only #success? is ever read.
|
|
5
4
|
Status = Data.define(:success) do
|
|
6
5
|
def success? = success
|
|
7
6
|
end
|
|
@@ -38,7 +37,6 @@ class ReactEmailRails::RenderModes::Persistent::Server
|
|
|
38
37
|
release_io
|
|
39
38
|
end
|
|
40
39
|
|
|
41
|
-
# Release this process's copy of an inherited child's pipes without signalling the parent-owned process.
|
|
42
40
|
def abandon
|
|
43
41
|
release_io
|
|
44
42
|
rescue IOError
|
|
@@ -47,14 +45,12 @@ class ReactEmailRails::RenderModes::Persistent::Server
|
|
|
47
45
|
|
|
48
46
|
private
|
|
49
47
|
|
|
50
|
-
# Shared by stop (which also kills the process) and abandon (which must not).
|
|
51
48
|
def release_io
|
|
52
49
|
[@stdin, @stdout, @stderr].compact.each { |io| io.close unless io.closed? }
|
|
53
50
|
@stdin = @stdout = @stderr = @wait_thread = @stderr_reader = nil
|
|
54
51
|
@stdout_buffer.clear
|
|
55
52
|
end
|
|
56
53
|
|
|
57
|
-
# Run under the mutex; on a broken pipe, stop and retry once (the child respawns).
|
|
58
54
|
def with_retry_on_broken_pipe(&block)
|
|
59
55
|
@mutex.synchronize(&block)
|
|
60
56
|
rescue Errno::EPIPE, IOError
|
|
@@ -72,8 +68,6 @@ class ReactEmailRails::RenderModes::Persistent::Server
|
|
|
72
68
|
response = request(input, timeout:)
|
|
73
69
|
return failure(response["error"].to_s.presence || "render process failed") unless response["ok"]
|
|
74
70
|
|
|
75
|
-
# Re-serialize into the same Result.stdout contract the subprocess produces, so
|
|
76
|
-
# Subprocess#run parses and validates every render uniformly.
|
|
77
71
|
success(JSON.generate(
|
|
78
72
|
{
|
|
79
73
|
protocolVersion: response["protocolVersion"],
|
|
@@ -8,8 +8,6 @@ class ReactEmailRails::RenderModes::Subprocess
|
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
# `label` names the render in error messages. `response` reads the reply as `:email`
|
|
12
|
-
# (RenderedEmail, for render/compose) or `:document` (parsed document, for parse).
|
|
13
11
|
def initialize(payload:, label:, response: :email)
|
|
14
12
|
@payload = payload
|
|
15
13
|
@label = label
|
|
@@ -44,7 +42,6 @@ class ReactEmailRails::RenderModes::Subprocess
|
|
|
44
42
|
end
|
|
45
43
|
end
|
|
46
44
|
|
|
47
|
-
# Shared by Persistent#capture so the transport-error messages live in one place.
|
|
48
45
|
def with_capture_rescues
|
|
49
46
|
yield
|
|
50
47
|
rescue Timeout::Error
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
# Collects props registered with `react_email_share` and merges them beneath the
|
|
2
|
-
# per-mail props, which win on conflict. Mirrors inertia-rails shared data.
|
|
3
1
|
class ReactEmailRails::SharedProps
|
|
4
2
|
IVAR = :@_react_email_shared
|
|
5
3
|
|
|
@@ -7,8 +5,6 @@ class ReactEmailRails::SharedProps
|
|
|
7
5
|
@mailer = mailer
|
|
8
6
|
end
|
|
9
7
|
|
|
10
|
-
# Returns `props` untouched when nothing is shared, so non-Hash inputs (e.g.
|
|
11
|
-
# serializers) still flow straight through to serialization.
|
|
12
8
|
def merge_into(props, deep_merge:)
|
|
13
9
|
shared = to_h
|
|
14
10
|
return props if shared.empty?
|
|
@@ -32,8 +28,6 @@ class ReactEmailRails::SharedProps
|
|
|
32
28
|
mailer.instance_variable_get(IVAR) || []
|
|
33
29
|
end
|
|
34
30
|
|
|
35
|
-
# An entry is either a static Hash or a block evaluated at render time. Callable
|
|
36
|
-
# values inside a Hash are evaluated too, so `unread_count: -> { ... }` works.
|
|
37
31
|
def resolve(entry)
|
|
38
32
|
hash = entry.respond_to?(:call) ? mailer.instance_exec(&entry) : entry
|
|
39
33
|
|
data/lib/react_email_rails.rb
CHANGED
|
@@ -27,6 +27,7 @@ require_relative("react_email_rails/tasks")
|
|
|
27
27
|
require_relative("react_email_rails/props_resolver")
|
|
28
28
|
require_relative("react_email_rails/shared_props")
|
|
29
29
|
require_relative("react_email_rails/mailer_context")
|
|
30
|
+
require_relative("react_email_rails/preview_live_reload")
|
|
30
31
|
require_relative("react_email_rails/railtie")
|
|
31
32
|
|
|
32
33
|
module ReactEmailRails
|
|
@@ -46,7 +47,6 @@ module ReactEmailRails
|
|
|
46
47
|
perform(payload:, label: component, kind: "email", component:)
|
|
47
48
|
end
|
|
48
49
|
|
|
49
|
-
# The document is sent verbatim (keys are structural); only context is key-transformed, like props.
|
|
50
50
|
def compose(type:, document:, context: {}, preview: nil)
|
|
51
51
|
payload = {
|
|
52
52
|
kind: "document",
|
|
@@ -59,7 +59,6 @@ module ReactEmailRails
|
|
|
59
59
|
perform(payload:, label: type, kind: "document", type:)
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
# Returns an editor document Hash, built via the renderer's extensions. Pass exactly one of `html:`/`markdown:`.
|
|
63
62
|
def parse(type:, html: nil, markdown: nil, context: {})
|
|
64
63
|
payload = {
|
|
65
64
|
kind: "parse",
|
|
@@ -90,7 +89,6 @@ module ReactEmailRails
|
|
|
90
89
|
raise
|
|
91
90
|
end
|
|
92
91
|
|
|
93
|
-
# Markdown is converted renderer-side, not here; both inputs are sent as-is.
|
|
94
92
|
def parse_source(html:, markdown:)
|
|
95
93
|
if !html.nil? && !markdown.nil?
|
|
96
94
|
raise(ArgumentError, "ReactEmailRails.parse accepts only one of html: or markdown:")
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: react-email-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Supertape
|
|
@@ -154,6 +154,7 @@ files:
|
|
|
154
154
|
- lib/react_email_rails/action_mailer.rb
|
|
155
155
|
- lib/react_email_rails/configuration.rb
|
|
156
156
|
- lib/react_email_rails/mailer_context.rb
|
|
157
|
+
- lib/react_email_rails/preview_live_reload.rb
|
|
157
158
|
- lib/react_email_rails/props_resolver.rb
|
|
158
159
|
- lib/react_email_rails/railtie.rb
|
|
159
160
|
- lib/react_email_rails/render_error.rb
|