activemail 1.2.2 → 2.0.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 +65 -2
- data/README.md +105 -47
- data/UPGRADING.md +112 -0
- data/app/assets/stylesheets/activemail/_components.scss +33 -42
- data/app/assets/stylesheets/activemail/_dark.scss +31 -20
- data/app/assets/stylesheets/activemail/_grid.scss +2 -0
- data/app/assets/stylesheets/activemail/_settings.scss +22 -10
- data/app/assets/stylesheets/activemail/_utilities.scss +3 -1
- data/app/assets/stylesheets/activemail/activemail.scss +6 -5
- data/app/helpers/active_mail/styles_helper.rb +14 -15
- data/app/views/layouts/activemail/mailer.html.inky-erb +0 -5
- data/lib/activemail/asset_pipeline/base.rb +47 -0
- data/lib/activemail/asset_pipeline/null.rb +19 -0
- data/lib/activemail/asset_pipeline/propshaft.rb +19 -0
- data/lib/activemail/asset_pipeline/sprockets.rb +39 -0
- data/lib/activemail/asset_pipeline.rb +35 -0
- data/lib/activemail/components/base.rb +35 -39
- data/lib/activemail/components/block_grid.rb +11 -4
- data/lib/activemail/components/button.rb +5 -28
- data/lib/activemail/components/button_renderer.rb +65 -0
- data/lib/activemail/components/callout.rb +4 -5
- data/lib/activemail/components/center.rb +5 -7
- data/lib/activemail/components/columns.rb +26 -7
- data/lib/activemail/components/container.rb +11 -4
- data/lib/activemail/components/cta.rb +9 -33
- data/lib/activemail/components/h_line.rb +3 -5
- data/lib/activemail/components/info_box.rb +6 -12
- data/lib/activemail/components/menu.rb +3 -4
- data/lib/activemail/components/menu_item.rb +10 -3
- data/lib/activemail/components/row.rb +3 -4
- data/lib/activemail/components/spacer.rb +16 -12
- data/lib/activemail/components/table_component.rb +23 -0
- data/lib/activemail/components/wrapper.rb +10 -4
- data/lib/activemail/configuration.rb +43 -57
- data/lib/activemail/errors.rb +15 -0
- data/lib/activemail/inliner/base.rb +2 -10
- data/lib/activemail/inliner/null.rb +0 -5
- data/lib/activemail/inliner/roadie.rb +1 -1
- data/lib/activemail/inliner.rb +33 -0
- data/lib/activemail/parse_error_reporter.rb +5 -4
- data/lib/activemail/pipeline.rb +26 -0
- data/lib/activemail/quality/builtin_rules.rb +154 -0
- data/lib/activemail/quality/configuration.rb +83 -3
- data/lib/activemail/quality/guard.rb +45 -87
- data/lib/activemail/quality/minitest.rb +41 -25
- data/lib/activemail/quality/output_dir.rb +52 -0
- data/lib/activemail/quality/preview_renderer.rb +46 -33
- data/lib/activemail/quality/render_all.rb +96 -40
- data/lib/activemail/quality/rspec.rb +4 -8
- data/lib/activemail/quality/rule.rb +47 -0
- data/lib/activemail/rails/engine.rb +13 -13
- data/lib/activemail/rails/rendering.rb +51 -0
- data/lib/activemail/rails/template_handler.rb +3 -1
- data/lib/activemail/tokens/button_style.rb +1 -2
- data/lib/activemail/tokens/defaults.rb +77 -0
- data/lib/activemail/tokens/scss_serializer.rb +4 -4
- data/lib/activemail/tokens.rb +19 -58
- data/lib/activemail/version.rb +1 -1
- data/lib/activemail.rb +89 -61
- data/lib/generators/activemail/templates/component.rb.tt +2 -3
- data/lib/generators/activemail/templates/initializer.rb +0 -3
- data/lib/generators/activemail/templates/mailer_layout.html.inky-erb +0 -2
- data/lib/generators/activemail/templates/mailer_layout.html.inky-haml +0 -2
- data/lib/generators/activemail/templates/mailer_layout.html.inky-slim +0 -2
- data/lib/tasks/activemail.rake +4 -5
- metadata +38 -7
- data/lib/activemail/components/inky.rb +0 -18
- data/lib/activemail/inliner/interceptor.rb +0 -51
- data/lib/activemail/rails/compiled_stylesheet.rb +0 -62
|
@@ -8,8 +8,6 @@ html lang=I18n.locale xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-
|
|
|
8
8
|
meta name="supported-color-schemes" content="light dark"
|
|
9
9
|
| <!--[if mso]><noscript><xml><o:OfficeDocumentSettings><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml></noscript><![endif]-->
|
|
10
10
|
= activemail_inline_styles
|
|
11
|
-
/ Fallback for when activemail_inline_styles cannot read the compiled asset.
|
|
12
|
-
= stylesheet_link_tag "activemail/activemail", media: "all"
|
|
13
11
|
body style="margin:0;padding:0;word-spacing:normal;"
|
|
14
12
|
div role="article" aria-roledescription="email" lang=I18n.locale style="width:100%;"
|
|
15
13
|
container
|
data/lib/tasks/activemail.rake
CHANGED
|
@@ -20,15 +20,14 @@ namespace :activemail do
|
|
|
20
20
|
task render_all: :environment do
|
|
21
21
|
require 'activemail/quality/render_all'
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
puts "Rendered #{result.rendered} email(s) into #{output_root}"
|
|
23
|
+
root = defined?(Rails) && Rails.respond_to?(:root) && Rails.root ? Rails.root : Pathname.pwd
|
|
24
|
+
result = ActiveMail::Quality::RenderAll.new(root: root, config: ActiveMail::Quality.config).call
|
|
25
|
+
puts "Rendered #{result.rendered} email(s) into #{result.output_root}"
|
|
27
26
|
# A green run on zero previews would silently verify nothing — make it visible.
|
|
28
27
|
warn '[activemail] WARNING: no mailer previews were discovered — nothing was checked.' if result.discovered.zero?
|
|
29
28
|
result.render_failures.each { |key, error| puts " render failed: #{key}: #{error}" }
|
|
30
29
|
result.guard_failures.each do |key, violations|
|
|
31
|
-
puts " guard failed: #{key}", violations.map { |v| " -
|
|
30
|
+
puts " guard failed: #{key}", violations.map { |v| " - #{v}" }.join("\n")
|
|
32
31
|
end
|
|
33
32
|
abort "\n#{result.broken_required.size} required preview(s) failed: #{result.broken_required.join(', ')}" if result.broken_required.any?
|
|
34
33
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activemail
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Advitam
|
|
@@ -16,6 +16,9 @@ dependencies:
|
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
18
|
version: '1.16'
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '1.20'
|
|
19
22
|
type: :runtime
|
|
20
23
|
prerelease: false
|
|
21
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -23,6 +26,9 @@ dependencies:
|
|
|
23
26
|
- - ">="
|
|
24
27
|
- !ruby/object:Gem::Version
|
|
25
28
|
version: '1.16'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '1.20'
|
|
26
32
|
- !ruby/object:Gem::Dependency
|
|
27
33
|
name: premailer
|
|
28
34
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -30,6 +36,9 @@ dependencies:
|
|
|
30
36
|
- - ">="
|
|
31
37
|
- !ruby/object:Gem::Version
|
|
32
38
|
version: '1.21'
|
|
39
|
+
- - "<"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '2'
|
|
33
42
|
type: :runtime
|
|
34
43
|
prerelease: false
|
|
35
44
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -37,20 +46,29 @@ dependencies:
|
|
|
37
46
|
- - ">="
|
|
38
47
|
- !ruby/object:Gem::Version
|
|
39
48
|
version: '1.21'
|
|
49
|
+
- - "<"
|
|
50
|
+
- !ruby/object:Gem::Version
|
|
51
|
+
version: '2'
|
|
40
52
|
- !ruby/object:Gem::Dependency
|
|
41
53
|
name: sorbet-runtime
|
|
42
54
|
requirement: !ruby/object:Gem::Requirement
|
|
43
55
|
requirements:
|
|
44
56
|
- - ">="
|
|
45
57
|
- !ruby/object:Gem::Version
|
|
46
|
-
version:
|
|
58
|
+
version: 0.5.10600
|
|
59
|
+
- - "<"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0.7'
|
|
47
62
|
type: :runtime
|
|
48
63
|
prerelease: false
|
|
49
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
65
|
requirements:
|
|
51
66
|
- - ">="
|
|
52
67
|
- !ruby/object:Gem::Version
|
|
53
|
-
version:
|
|
68
|
+
version: 0.5.10600
|
|
69
|
+
- - "<"
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: '0.7'
|
|
54
72
|
description: |
|
|
55
73
|
ActiveMail is a plug & play gem for sending beautiful emails, written entirely in Ruby.
|
|
56
74
|
It turns simple, semantic tags into responsive, bulletproof email markup and ships with
|
|
@@ -63,6 +81,7 @@ files:
|
|
|
63
81
|
- CHANGELOG.md
|
|
64
82
|
- LICENSE.txt
|
|
65
83
|
- README.md
|
|
84
|
+
- UPGRADING.md
|
|
66
85
|
- app/assets/stylesheets/activemail/_activemail_tokens.scss.erb
|
|
67
86
|
- app/assets/stylesheets/activemail/_components.scss
|
|
68
87
|
- app/assets/stylesheets/activemail/_dark.scss
|
|
@@ -75,9 +94,15 @@ files:
|
|
|
75
94
|
- app/views/layouts/activemail/_head.html.inky-erb
|
|
76
95
|
- app/views/layouts/activemail/mailer.html.inky-erb
|
|
77
96
|
- lib/activemail.rb
|
|
97
|
+
- lib/activemail/asset_pipeline.rb
|
|
98
|
+
- lib/activemail/asset_pipeline/base.rb
|
|
99
|
+
- lib/activemail/asset_pipeline/null.rb
|
|
100
|
+
- lib/activemail/asset_pipeline/propshaft.rb
|
|
101
|
+
- lib/activemail/asset_pipeline/sprockets.rb
|
|
78
102
|
- lib/activemail/components/base.rb
|
|
79
103
|
- lib/activemail/components/block_grid.rb
|
|
80
104
|
- lib/activemail/components/button.rb
|
|
105
|
+
- lib/activemail/components/button_renderer.rb
|
|
81
106
|
- lib/activemail/components/callout.rb
|
|
82
107
|
- lib/activemail/components/center.rb
|
|
83
108
|
- lib/activemail/components/columns.rb
|
|
@@ -85,32 +110,38 @@ files:
|
|
|
85
110
|
- lib/activemail/components/cta.rb
|
|
86
111
|
- lib/activemail/components/h_line.rb
|
|
87
112
|
- lib/activemail/components/info_box.rb
|
|
88
|
-
- lib/activemail/components/inky.rb
|
|
89
113
|
- lib/activemail/components/menu.rb
|
|
90
114
|
- lib/activemail/components/menu_item.rb
|
|
91
115
|
- lib/activemail/components/row.rb
|
|
92
116
|
- lib/activemail/components/spacer.rb
|
|
117
|
+
- lib/activemail/components/table_component.rb
|
|
93
118
|
- lib/activemail/components/wrapper.rb
|
|
94
119
|
- lib/activemail/configuration.rb
|
|
120
|
+
- lib/activemail/errors.rb
|
|
121
|
+
- lib/activemail/inliner.rb
|
|
95
122
|
- lib/activemail/inliner/base.rb
|
|
96
|
-
- lib/activemail/inliner/interceptor.rb
|
|
97
123
|
- lib/activemail/inliner/null.rb
|
|
98
124
|
- lib/activemail/inliner/premailer.rb
|
|
99
125
|
- lib/activemail/inliner/roadie.rb
|
|
100
126
|
- lib/activemail/libxml.rb
|
|
101
127
|
- lib/activemail/parse_error_reporter.rb
|
|
128
|
+
- lib/activemail/pipeline.rb
|
|
102
129
|
- lib/activemail/quality.rb
|
|
130
|
+
- lib/activemail/quality/builtin_rules.rb
|
|
103
131
|
- lib/activemail/quality/configuration.rb
|
|
104
132
|
- lib/activemail/quality/guard.rb
|
|
105
133
|
- lib/activemail/quality/minitest.rb
|
|
134
|
+
- lib/activemail/quality/output_dir.rb
|
|
106
135
|
- lib/activemail/quality/preview_renderer.rb
|
|
107
136
|
- lib/activemail/quality/render_all.rb
|
|
108
137
|
- lib/activemail/quality/rspec.rb
|
|
109
|
-
- lib/activemail/
|
|
138
|
+
- lib/activemail/quality/rule.rb
|
|
110
139
|
- lib/activemail/rails/engine.rb
|
|
140
|
+
- lib/activemail/rails/rendering.rb
|
|
111
141
|
- lib/activemail/rails/template_handler.rb
|
|
112
142
|
- lib/activemail/tokens.rb
|
|
113
143
|
- lib/activemail/tokens/button_style.rb
|
|
144
|
+
- lib/activemail/tokens/defaults.rb
|
|
114
145
|
- lib/activemail/tokens/scss_serializer.rb
|
|
115
146
|
- lib/activemail/version.rb
|
|
116
147
|
- lib/generators/activemail/component_generator.rb
|
|
@@ -145,7 +176,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
145
176
|
- !ruby/object:Gem::Version
|
|
146
177
|
version: '0'
|
|
147
178
|
requirements: []
|
|
148
|
-
rubygems_version:
|
|
179
|
+
rubygems_version: 4.0.20
|
|
149
180
|
specification_version: 4
|
|
150
181
|
summary: Plug & play gem to send modern emails, entirely in Ruby, with dark mode and
|
|
151
182
|
more out of the box.
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# typed: strict
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require_relative 'base'
|
|
5
|
-
|
|
6
|
-
module ActiveMail
|
|
7
|
-
module Components
|
|
8
|
-
# Renders a bare <tr>, useful inside hand-written tables.
|
|
9
|
-
class Inky < Base
|
|
10
|
-
extend T::Sig
|
|
11
|
-
|
|
12
|
-
sig { override.params(_node: Nokogiri::XML::Node, inner: String).returns(String) }
|
|
13
|
-
def transform(_node, inner)
|
|
14
|
-
%(<tr>#{inner}</tr>)
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# typed: strict
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require 'sorbet-runtime'
|
|
5
|
-
|
|
6
|
-
module ActiveMail
|
|
7
|
-
module Inliner
|
|
8
|
-
class Interceptor
|
|
9
|
-
class << self
|
|
10
|
-
extend T::Sig
|
|
11
|
-
|
|
12
|
-
sig { params(message: T.untyped).void }
|
|
13
|
-
def delivering_email(message)
|
|
14
|
-
config = ActiveMail.configuration
|
|
15
|
-
# Runtime check: an engine initializer runs before the host's, so a
|
|
16
|
-
# boot-time flag read would always see the default.
|
|
17
|
-
return unless config.register_inline_interceptor
|
|
18
|
-
|
|
19
|
-
inliner = config.resolved_inliner
|
|
20
|
-
return if inliner.noop?
|
|
21
|
-
|
|
22
|
-
html_parts(message).each do |part|
|
|
23
|
-
part.body = inliner.inline(part.body.to_s)
|
|
24
|
-
rescue StandardError => e
|
|
25
|
-
# Surface which inliner failed; do not swallow (a silently non-inlined
|
|
26
|
-
# mail is worse). Ruby sets e as #cause, preserving the original backtrace.
|
|
27
|
-
raise ActiveMail::Inliner::Error, "[#{inliner.class}] CSS inlining failed: #{e.message}"
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
private
|
|
32
|
-
|
|
33
|
-
# The html part(s) to inline: a single text/html message, or every text/html
|
|
34
|
-
# part of a multipart message. Attachments are never inlined.
|
|
35
|
-
sig { params(message: T.untyped).returns(T::Array[T.untyped]) }
|
|
36
|
-
def html_parts(message)
|
|
37
|
-
return message.all_parts.select { |part| html_body_part?(part) } if message.multipart?
|
|
38
|
-
|
|
39
|
-
html_body_part?(message) ? [message] : []
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
sig { params(part: T.untyped).returns(T::Boolean) }
|
|
43
|
-
def html_body_part?(part)
|
|
44
|
-
return false unless part.respond_to?(:mime_type) && part.mime_type == 'text/html'
|
|
45
|
-
|
|
46
|
-
!(part.respond_to?(:attachment?) && part.attachment?)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# typed: strict
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require 'sorbet-runtime'
|
|
5
|
-
|
|
6
|
-
module ActiveMail
|
|
7
|
-
# Reads a compiled CSS asset's bytes (Sprockets or Propshaft, by duck-type) — the
|
|
8
|
-
# bytes, not a digest URL, are what the Premailer adapter needs to inline.
|
|
9
|
-
module CompiledStylesheet
|
|
10
|
-
class << self
|
|
11
|
-
extend T::Sig
|
|
12
|
-
|
|
13
|
-
# '' (not nil) on a miss: callers embed the result verbatim, and a missing
|
|
14
|
-
# asset must degrade to an empty <style>, never interpolate "nil" into HTML.
|
|
15
|
-
sig { params(logical_path: String).returns(String) }
|
|
16
|
-
def read(logical_path)
|
|
17
|
-
sprockets_source(logical_path) || propshaft_source(logical_path) || ''
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
private
|
|
21
|
-
|
|
22
|
-
# Sprockets: config.assets.compile (dev) resolves logical paths in-memory;
|
|
23
|
-
# precompiled (prod) resolves through the manifest. #find_asset covers both.
|
|
24
|
-
sig { params(logical_path: String).returns(T.nilable(String)) }
|
|
25
|
-
def sprockets_source(logical_path)
|
|
26
|
-
assets = rails_assets_environment
|
|
27
|
-
return unless assets.respond_to?(:find_asset)
|
|
28
|
-
|
|
29
|
-
asset = assets.find_asset(logical_path)
|
|
30
|
-
asset&.source&.to_s
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# Propshaft: the load_path resolves a logical path to a compiled file on disk.
|
|
34
|
-
sig { params(logical_path: String).returns(T.nilable(String)) }
|
|
35
|
-
def propshaft_source(logical_path)
|
|
36
|
-
assets = rails_assets
|
|
37
|
-
load_path = assets.respond_to?(:load_path) ? assets.load_path : nil
|
|
38
|
-
return unless load_path.respond_to?(:find)
|
|
39
|
-
|
|
40
|
-
asset = load_path.find(logical_path)
|
|
41
|
-
asset&.path && File.exist?(asset.path) ? File.read(asset.path) : nil
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# config.assets.environment is the Sprockets::Environment; absent under Propshaft.
|
|
45
|
-
sig { returns(T.untyped) }
|
|
46
|
-
def rails_assets_environment
|
|
47
|
-
assets = rails_assets
|
|
48
|
-
assets.respond_to?(:environment) ? assets.environment : nil
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
sig { returns(T.untyped) }
|
|
52
|
-
def rails_assets
|
|
53
|
-
return unless Object.const_defined?(:Rails)
|
|
54
|
-
|
|
55
|
-
rails = Object.const_get(:Rails)
|
|
56
|
-
app = rails.respond_to?(:application) ? rails.application : nil
|
|
57
|
-
config = app&.config
|
|
58
|
-
config.respond_to?(:assets) ? config.assets : nil
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|