react-email-rails 0.7.0 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 957e5d57adf900478fa7736755f400bd424dbfc4aa47bee2e6ef82822fa9d048
4
- data.tar.gz: 7bdd67d8de3ce6051c1849338337e74734fb51514d18eee0931ba172c2edac93
3
+ metadata.gz: cf2e6b94aa19f4ccec30037d5eefb38b1b98ba2f070ede1a89c99818e47b2eec
4
+ data.tar.gz: 26710f44d94a84d1df7a73a0759973c37fc9b3ec031c143ae902aed890ebb2d2
5
5
  SHA512:
6
- metadata.gz: 7e44fad8be9e76043f9811a5cadffc9ffe4a6da0dd4b649b283a6f5af599d600d4c69750a2dc454224923abab985204f07238978def3fd2ca3af7506c73444d6
7
- data.tar.gz: 86617b862cfaf09b4a20a21918b042732648d8a8383dcf319cbe4ba77e5f982d9dd98d0abdc643d8ef902dfcc46485f0428547c0aed2a2eccae7e508a87ee5c2
6
+ metadata.gz: 911446dcf37e32e420bef4e0f02cdf8c30c6076854dba593737ae552138e139473f355d1ef14328bf50cf77943e5b376e82300185b8d23ea34fb41a1a3deaaaf
7
+ data.tar.gz: 708ac8a7339f5133be74caccce59a1f30dc890f6da95adeb5385a5117b894295fd8e3e5748a50e8a46d0cdd6bcc1abc6d3943abf9bf146dd2b57163c3d0c94a5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.0
4
+
5
+ - **Breaking:** Remove `@react-email/editor` document rendering to focus the library on component-based Action Mailer emails. `ReactEmailRails.compose`, `ReactEmailRails.parse`, the `documents` Vite plugin option, and the `react-email-rails/document` module are gone, along with the `@react-email/editor`, `@tiptap/core`, `@tiptap/html`, `happy-dom`, and `marked` optional peer dependencies.
6
+ - **Breaking:** `on_render_error` callbacks and the `render.react-email-rails` instrumentation payload no longer include `kind:` (every render is a component email again); `RenderedEmail` no longer has `warnings`.
7
+ - Bump the render protocol to 4 (the renderer no longer accepts document or parse requests). The Ruby gem and npm package must be upgraded together, as before.
8
+
3
9
  ## 0.7.0
4
10
 
5
11
  - 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.
data/README.md CHANGED
@@ -18,7 +18,6 @@ You get:
18
18
  - Vite-powered development rendering
19
19
  - A production renderer bundle built during `assets:precompile`
20
20
  - Optional persistent rendering for high-volume workers
21
- - Optional server-side rendering for `@react-email/editor` documents
22
21
 
23
22
  ## Status
24
23
 
@@ -471,12 +470,6 @@ export default function Welcome() {
471
470
  }
472
471
  ```
473
472
 
474
- ### Editor Documents
475
-
476
- If your app uses [@react-email/editor](https://react.email/docs/editor) to let users compose emails visually, `ReactEmailRails.compose` can render stored editor documents on the server.
477
-
478
- See [Editor rendering](docs/editor.md) for setup and usage.
479
-
480
473
  ## Configuration
481
474
 
482
475
  Configuration lives in two places:
@@ -580,11 +573,11 @@ ReactEmailRails.configure do |config|
580
573
  end
581
574
  ```
582
575
 
583
- The callback receives the error plus render context such as `kind:` and `component:`.
576
+ The callback receives the error plus render context such as `component:`.
584
577
 
585
578
  ### Instrumentation
586
579
 
587
- Every render emits `render.react-email-rails` through [ActiveSupport::Notifications](https://guides.rubyonrails.org/active_support_instrumentation.html). Email payloads include `kind`, `component`, and successful HTML size in `html_bytes`.
580
+ Every render emits `render.react-email-rails` through [ActiveSupport::Notifications](https://guides.rubyonrails.org/active_support_instrumentation.html). Payloads include `component` and successful HTML size in `html_bytes`.
588
581
 
589
582
  ```ruby
590
583
  ActiveSupport::Notifications.subscribe("render.react-email-rails") do |event|
@@ -619,7 +612,6 @@ Server, preview, dependency optimization, and build output settings stay owned b
619
612
  | `emails.path` | `"app/javascript/emails"` | Directory containing email components |
620
613
  | `emails.extension` | `[".tsx", ".jsx"]` | Component extension, or an array of extensions |
621
614
  | `emails.ignore` | `["**/_*", "**/_*/**"]` | Glob patterns ignored under `emails.path` |
622
- | `documents` | `false` | Optional `@react-email/editor` document renderer discovery; see [Editor rendering](docs/editor.md) |
623
615
  | `standalone` | `true` | Inline production renderer bundle dependencies |
624
616
  | `vite` | `{}` | Extra email-only Vite config for compilation and resolution |
625
617
 
@@ -687,7 +679,7 @@ Production deploys should run the normal Rails asset task:
687
679
  bin/rails assets:precompile
688
680
  ```
689
681
 
690
- react-email-rails hooks `react_email_rails:build` into `assets:precompile`. The build task loads `reactEmailRails()` options from your Vite config and writes `tmp/react-email-rails/emails.js` with the email component registry. If [Editor rendering](docs/editor.md) is enabled, the bundle also includes document renderers.
682
+ react-email-rails hooks `react_email_rails:build` into `assets:precompile`. The build task loads `reactEmailRails()` options from your Vite config and writes `tmp/react-email-rails/emails.js` with the email component registry.
691
683
 
692
684
  You can run the renderer build directly:
693
685
 
@@ -699,7 +691,7 @@ Production rendering requires that bundle. If it is missing, rendering raises `R
699
691
 
700
692
  Set `SKIP_REACT_EMAIL_RAILS_BUILD=1` to skip the automatic asset hook. Directly running `bin/rails react_email_rails:build` always attempts the build.
701
693
 
702
- The npm package, Vite, React, and `@react-email/render` must be available when Rails runs `assets:precompile`. If [Editor rendering](docs/editor.md) is enabled, its peer dependencies must be available too.
694
+ The npm package, Vite, React, and `@react-email/render` must be available when Rails runs `assets:precompile`.
703
695
 
704
696
  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`.
705
697
 
data/SECURITY.md CHANGED
@@ -3,7 +3,3 @@
3
3
  Please report security issues privately by emailing hi@supertape.com.
4
4
 
5
5
  Do not open a public GitHub issue for suspected vulnerabilities. Include the affected version, a minimal reproduction when possible, and any relevant deployment details.
6
-
7
- ## Rendering editor documents
8
-
9
- `ReactEmailRails.compose` renders an `@react-email/editor` document (Tiptap/ProseMirror JSON) server-side. Treat that document as untrusted input: it is typically authored in a visual editor and stored, then rendered later. The renderer only dispatches to the extensions you register for that document type, and React Email escapes rendered output, but URL and asset sanitization inside your custom extensions (links, image sources, button hrefs) remains your application's responsibility. Validate or sanitize those values where you build extensions or transform the document.
@@ -75,8 +75,6 @@ class ReactEmailRails::RenderModes::Persistent::Server
75
75
  }.tap do |body|
76
76
  body[:html] = response["html"] if response.key?("html")
77
77
  body[:text] = response["text"] if response.key?("text")
78
- body[:warnings] = response["warnings"] if response.key?("warnings")
79
- body[:document] = response["document"] if response.key?("document")
80
78
  end,
81
79
  ))
82
80
  rescue JSON::ParserError => e
@@ -8,10 +8,9 @@ class ReactEmailRails::RenderModes::Subprocess
8
8
  end
9
9
  end
10
10
 
11
- def initialize(payload:, label:, response: :email)
11
+ def initialize(payload:, label:)
12
12
  @payload = payload
13
13
  @label = label
14
- @response = response
15
14
  end
16
15
 
17
16
  def render
@@ -20,7 +19,7 @@ class ReactEmailRails::RenderModes::Subprocess
20
19
 
21
20
  private
22
21
 
23
- attr_reader(:payload, :label, :response)
22
+ attr_reader(:payload, :label)
24
23
 
25
24
  def run
26
25
  result = capture(payload_json)
@@ -28,7 +27,7 @@ class ReactEmailRails::RenderModes::Subprocess
28
27
 
29
28
  body = JSON.parse(result.stdout)
30
29
  validate_metadata!(body)
31
- build_result(body)
30
+ build_rendered_email(body)
32
31
  rescue JSON::ParserError => e
33
32
  raise(render_error("render process returned invalid JSON: #{e.message}"))
34
33
  rescue KeyError => e
@@ -86,32 +85,12 @@ class ReactEmailRails::RenderModes::Subprocess
86
85
  raise(render_error(ReactEmailRails::RenderProtocol.mismatch_message(body)))
87
86
  end
88
87
 
89
- def build_result(body)
90
- response == :document ? build_document(body) : build_rendered_email(body)
91
- end
92
-
93
88
  def build_rendered_email(body)
94
89
  raise(KeyError.new(key: "html")) unless body.key?("html")
95
90
  raise(render_error("render process returned an invalid response: html must be a string")) unless body["html"].is_a?(String)
96
91
  raise(render_error("render process returned an invalid response: text must be a string")) if body.key?("text") && !body["text"].is_a?(String)
97
92
 
98
- ReactEmailRails::RenderedEmail.new(html: body.fetch("html"), text: body["text"].to_s, warnings: warnings_from(body))
99
- end
100
-
101
- def build_document(body)
102
- raise(KeyError.new(key: "document")) unless body.key?("document")
103
-
104
- document = body.fetch("document")
105
- raise(render_error("parse process returned an invalid response: document must be an object")) unless document.is_a?(Hash)
106
-
107
- document
108
- end
109
-
110
- def warnings_from(body)
111
- warnings = body["warnings"]
112
- return [] unless warnings.is_a?(Array)
113
-
114
- warnings.filter_map { |warning| warning.transform_keys(&:to_sym) if warning.is_a?(Hash) }
93
+ ReactEmailRails::RenderedEmail.new(html: body.fetch("html"), text: body["text"].to_s)
115
94
  end
116
95
 
117
96
  def render_error(message)
@@ -1,7 +1,7 @@
1
1
  require("json")
2
2
 
3
3
  module ReactEmailRails
4
- RENDER_PROTOCOL_VERSION = 3
4
+ RENDER_PROTOCOL_VERSION = 4
5
5
 
6
6
  module RenderProtocol
7
7
  extend(self)
@@ -1,7 +1,3 @@
1
1
  module ReactEmailRails
2
- RenderedEmail = Data.define(:html, :text, :warnings) do
3
- def initialize(html:, text:, warnings: [])
4
- super
5
- end
6
- end
2
+ RenderedEmail = Data.define(:html, :text)
7
3
  end
@@ -1,3 +1,3 @@
1
1
  module ReactEmailRails
2
- VERSION = "0.7.0"
2
+ VERSION = "0.8.0"
3
3
  end
@@ -44,29 +44,12 @@ module ReactEmailRails
44
44
  payload = { component:, props: serialized_props(props) }
45
45
  payload[:renderOptions] = render_options if render_options.present?
46
46
 
47
- perform(payload:, label: component, kind: "email", component:)
48
- end
49
-
50
- def compose(type:, document:, context: {}, preview: nil)
51
- payload = {
52
- kind: "document",
53
- type:,
54
- document: document.as_json,
55
- context: serialized_props(context),
56
- preview:,
57
- }
58
-
59
- perform(payload:, label: type, kind: "document", type:)
60
- end
61
-
62
- def parse(type:, html: nil, markdown: nil, context: {})
63
- payload = {
64
- kind: "parse",
65
- type:,
66
- context: serialized_props(context),
67
- }.merge(parse_source(html:, markdown:))
68
-
69
- perform(payload:, label: type, response: :document, kind: "parse", type:)
47
+ instrument(component:) do
48
+ configuration.resolved_render_mode.new(payload:, label: component).render
49
+ end
50
+ rescue ReactEmailRails::RenderError => e
51
+ configuration.on_render_error&.call(e, component:)
52
+ raise
70
53
  end
71
54
 
72
55
  def healthy?
@@ -80,38 +63,13 @@ module ReactEmailRails
80
63
 
81
64
  private
82
65
 
83
- def perform(payload:, label:, response: :email, **metadata)
84
- instrument(**metadata) do
85
- configuration.resolved_render_mode.new(payload:, label:, response:).render
86
- end
87
- rescue ReactEmailRails::RenderError => e
88
- configuration.on_render_error&.call(e, **metadata)
89
- raise
90
- end
91
-
92
- def parse_source(html:, markdown:)
93
- if !html.nil? && !markdown.nil?
94
- raise(ArgumentError, "ReactEmailRails.parse accepts only one of html: or markdown:")
95
- end
96
-
97
- return { html: html.to_s } unless html.nil?
98
- return { markdown: markdown.to_s } unless markdown.nil?
99
-
100
- raise(ArgumentError, "ReactEmailRails.parse requires html: or markdown:")
101
- end
102
-
103
66
  def serialized_props(value)
104
67
  configuration.send(:serialize_props, value)
105
68
  end
106
69
 
107
- def instrument(**metadata)
108
- ActiveSupport::Notifications.instrument("render.react-email-rails", **metadata) do |payload|
109
- yield.tap do |result|
110
- next unless result.respond_to?(:html)
111
-
112
- payload[:html_bytes] = result.html.bytesize
113
- payload[:warnings] = result.warnings if result.warnings.present?
114
- end
70
+ def instrument(component:)
71
+ ActiveSupport::Notifications.instrument("render.react-email-rails", component:) do |payload|
72
+ yield.tap { |result| payload[:html_bytes] = result.html.bytesize }
115
73
  end
116
74
  end
117
75
  end
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.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Supertape