mjml-rb 0.2.39 → 0.3.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: c7864f17e62acc702b5da45e9ca4322bc5207d486190de2ae7bab1a19e5109be
4
- data.tar.gz: 9a5587f0f059d2d422407d65ad149e0d1ba04b731409a42290d3b4aa2aa34fc3
3
+ metadata.gz: cfa6cc54a797f8b4323003dbcfd92fa4ef02b1e0b118e58acd14bb8e901e502d
4
+ data.tar.gz: 12d0fb1d71e03a23811caac5b0417b7f32823b95870e47296ea51fd8bd713018
5
5
  SHA512:
6
- metadata.gz: a910ab3a64a41505e662a31c97ad11b29a72bee403c5e98b70a2abafa7fee0e056a173e55232bde1d8a5b765a524a6acf1a99d0536c0c74a49ef67dcaa17265b
7
- data.tar.gz: 0d9e9e08cfc38bcde65ba9480ca5a10365b0ecc60a20695a57cbc027dbe4a86df6d92424d46597d2ae8c46c7e25f6e4ccb6575d6d43f0d4dd157c54939afec36
6
+ metadata.gz: 689a1974e1c6e7477e202c3fb070c63eadf3b66617e2ea177feb6b45ae9d58cf9c1472dd7ddbe4e141d6583e67f83c93f76ca91c5f787d4a706241523c313361
7
+ data.tar.gz: ad73e16bd469bdfd98ccff031aca1796f99c460c87ab6435ba272492ffeb4ffff2b1e77f1019c368324286942cc561239e20b4219e6010efcac7d2066a945bb6
data/README.md CHANGED
@@ -51,15 +51,18 @@ By default, `.mjml` files are treated as raw MJML/XML source.
51
51
  If you want Slim-backed MJML templates, configure it explicitly:
52
52
 
53
53
  ```ruby
54
- config.mjml_rb.template_language = :slim
54
+ config.mjml_rb.rails_template_language = :slim
55
55
  ```
56
56
 
57
- Supported values are `:erb`, `:slim`, and `:haml`.
57
+ Supported values are `:slim` and `:haml`.
58
58
 
59
- With a configured `template_language`, `.mjml` templates are rendered through
60
- that template engine first, so partials and embedded Ruby can assemble MJML
61
- before the outer template is compiled to HTML. Without that setting, non-XML
62
- MJML source is rejected instead of being guessed.
59
+ With a configured `rails_template_language`, `.mjml` templates are rendered
60
+ through that template engine first, so partials and embedded Ruby can assemble
61
+ MJML before the outer template is compiled to HTML. Without that setting,
62
+ non-XML MJML source is rejected instead of being guessed.
63
+
64
+ For `:slim` or `:haml`, the matching Rails template handler must already be
65
+ registered in `ActionView` by the corresponding gem or integration layer.
63
66
 
64
67
  Create a view such as `app/views/user_mailer/welcome.html.mjml`:
65
68
 
@@ -1,17 +1,19 @@
1
- require_relative "template_handler"
1
+ if defined?(Rails::Railtie)
2
+ require_relative "template_handler"
2
3
 
3
- module MjmlRb
4
- class Railtie < Rails::Railtie
5
- config.mjml_rb = ActiveSupport::OrderedOptions.new
6
- config.mjml_rb.compiler_options = {validation_level: "strict"}
7
- config.mjml_rb.template_language = nil
4
+ module MjmlRb
5
+ class Railtie < Rails::Railtie
6
+ config.mjml_rb = ActiveSupport::OrderedOptions.new
7
+ config.mjml_rb.compiler_options = {validation_level: "strict"}
8
+ config.mjml_rb.rails_template_language = nil
8
9
 
9
- initializer "mjml_rb.action_view" do |app|
10
- MjmlRb.rails_compiler_options = app.config.mjml_rb.compiler_options.to_h
11
- MjmlRb.rails_template_language = app.config.mjml_rb.template_language
10
+ initializer "mjml_rb.action_view" do |app|
11
+ MjmlRb.rails_compiler_options = app.config.mjml_rb.compiler_options.to_h
12
+ MjmlRb.rails_template_language = app.config.mjml_rb.rails_template_language
12
13
 
13
- ActiveSupport.on_load(:action_view) do
14
- MjmlRb.register_action_view_template_handler!
14
+ ActiveSupport.on_load(:action_view) do
15
+ MjmlRb.register_action_view_template_handler!
16
+ end
15
17
  end
16
18
  end
17
19
  end
@@ -1,114 +1,65 @@
1
+ require "action_view"
2
+ require "action_view/template"
3
+
1
4
  module MjmlRb
2
5
  class TemplateHandler
3
- MJML_CAPTURE_DEPTH_IVAR = :@_mjml_rb_capture_depth
4
- TEMPLATE_ENGINES = {
5
- slim: {
6
- require: "slim",
7
- gem_name: "slim"
8
- },
9
- haml: {
10
- require: "haml",
11
- gem_name: "haml"
12
- }
13
- }.freeze
14
-
15
- class << self
16
- def call(template, source = nil)
17
- <<~RUBY
18
- ::MjmlRb::TemplateHandler.render(self, #{template.source.inspect}, #{template.identifier.inspect}, local_assigns)
19
- RUBY
20
- end
6
+ SUPPORTED_TEMPLATE_LANGUAGES = %w[:slim :haml].freeze
21
7
 
22
- def render(view_context, source, identifier, local_assigns = {})
23
- if capture_mode?(view_context)
24
- return mark_html_safe(render_source(view_context, source, local_assigns))
25
- end
8
+ def call(template, source = nil)
9
+ compiled_source = compile_source(template, source)
10
+ template_path = template.respond_to?(:virtual_path) ? template.virtual_path : template.identifier
26
11
 
27
- with_capture_mode(view_context) do
28
- mjml_source = render_source(view_context, source, local_assigns).to_s
29
- mjml_result = ::MjmlRb::Compiler.new(::MjmlRb.rails_compiler_options || {}).compile(mjml_source)
12
+ if /<mjml.*?>/i.match?(compiled_source)
13
+ "::MjmlRb::TemplateHandler.render_compiled_source(begin;#{compiled_source};end, #{template_path.inspect})"
14
+ else
15
+ "::MjmlRb::TemplateHandler.render_partial_source(begin;#{compiled_source};end)"
16
+ end
17
+ end
30
18
 
31
- if mjml_result.errors.any?
32
- raise "MJML compilation failed for #{identifier}: #{mjml_result.errors.map { |error| error[:formatted_message] || error[:message] }.join(', ')}"
33
- end
19
+ def self.render_compiled_source(mjml_source, template_path)
20
+ mjml_result = ::MjmlRb::Compiler.new(::MjmlRb.rails_compiler_options || {}).compile(mjml_source.to_s)
34
21
 
35
- mark_html_safe(mjml_result.html.to_s)
36
- end
22
+ if mjml_result.errors.any?
23
+ raise "MJML compilation failed for #{template_path}: #{mjml_result.errors.map { |error| error[:formatted_message] || error[:message] }.join(', ')}"
37
24
  end
38
25
 
39
- private
40
-
41
- def render_source(view_context, source, local_assigns)
42
- language = ::MjmlRb.rails_template_language
43
- if language.nil?
44
- stripped_source = source.to_s.lstrip
45
- return source.to_s if stripped_source.start_with?("<")
46
-
47
- raise "MJML Rails template_language is not configured for non-XML templates. Supported values: nil, :erb, :slim, :haml"
48
- end
49
-
50
- case language
51
- when :erb
52
- render_erb_source(view_context, source.to_s, local_assigns)
53
- when :slim, :haml
54
- render_template_language_source(view_context, source.to_s, local_assigns, language)
55
- else
56
- raise "Unsupported MJML Rails template_language `#{language}`. Supported values: nil, :erb, :slim, :haml"
57
- end
58
- end
26
+ html = mjml_result.html.to_s
27
+ html.respond_to?(:html_safe) ? html.html_safe : html
28
+ end
59
29
 
60
- def render_erb_source(view_context, source, local_assigns)
61
- require "erb"
30
+ def self.render_partial_source(compiled_source)
31
+ output = compiled_source.to_s
32
+ output.respond_to?(:html_safe) ? output.html_safe : output
33
+ end
62
34
 
63
- local_assigns.each do |name, value|
64
- define_local_reader(view_context, name, value)
65
- end
35
+ private
66
36
 
67
- erb = ::ERB.new(source)
68
- erb.result(view_context.instance_eval { binding })
69
- end
37
+ def template_handler
38
+ language = MjmlRb.rails_template_language
39
+ raise missing_rails_template_language_error if language.nil?
70
40
 
71
- def render_template_language_source(view_context, source, local_assigns, language)
72
- engine = TEMPLATE_ENGINES.fetch(language)
73
- require engine[:require]
74
-
75
- case language
76
- when :slim
77
- ::Slim::Template.new { source }.render(view_context, local_assigns.transform_keys(&:to_sym))
78
- when :haml
79
- if defined?(::Haml::Template)
80
- ::Haml::Template.new { source }.render(view_context, local_assigns.transform_keys(&:to_sym))
81
- else
82
- raise "MJML Rails template_language is set to :haml, but this Haml version does not expose Haml::Template"
83
- end
84
- end
85
- rescue LoadError
86
- raise "MJML Rails template_language is set to :#{language}, but the `#{engine[:gem_name]}` gem is not available"
87
- end
41
+ handler = ActionView::Template.registered_template_handler(language)
42
+ return handler if handler
88
43
 
89
- def define_local_reader(view_context, name, value)
90
- singleton_class = class << view_context; self; end
91
- singleton_class.send(:define_method, name) do
92
- value
93
- end
94
- end
44
+ raise "MJML Rails rails_template_language `#{language}` is not registered with ActionView. Make sure the matching Rails template handler is loaded."
45
+ end
95
46
 
96
- def capture_mode?(view_context)
97
- view_context.instance_variable_get(MJML_CAPTURE_DEPTH_IVAR).to_i.positive?
98
- end
47
+ def compile_source(template, source)
48
+ return template.source.inspect if xml_source?(template.source)
99
49
 
100
- def with_capture_mode(view_context)
101
- depth = view_context.instance_variable_get(MJML_CAPTURE_DEPTH_IVAR).to_i
102
- view_context.instance_variable_set(MJML_CAPTURE_DEPTH_IVAR, depth + 1)
103
- yield
104
- ensure
105
- next_depth = view_context.instance_variable_get(MJML_CAPTURE_DEPTH_IVAR).to_i - 1
106
- view_context.instance_variable_set(MJML_CAPTURE_DEPTH_IVAR, [next_depth, 0].max)
107
- end
50
+ template_handler.call(template, source)
51
+ rescue RuntimeError => error
52
+ raise error unless error.message == missing_rails_template_language_error
108
53
 
109
- def mark_html_safe(value)
110
- value.respond_to?(:html_safe) ? value.html_safe : value
111
- end
54
+ %(raise #{missing_rails_template_language_error.inspect})
55
+ end
56
+
57
+ def xml_source?(source)
58
+ source.to_s.lstrip.start_with?("<")
59
+ end
60
+
61
+ def missing_rails_template_language_error
62
+ "MJML Rails rails_template_language is not configured for non-XML templates. Configure it with one of: #{SUPPORTED_TEMPLATE_LANGUAGES.join(', ')}. Otherwise use raw XML MJML."
112
63
  end
113
64
  end
114
65
  end
@@ -1,3 +1,3 @@
1
1
  module MjmlRb
2
- VERSION = "0.2.39".freeze
2
+ VERSION = "0.3.0".freeze
3
3
  end
data/lib/mjml-rb.rb CHANGED
@@ -40,7 +40,7 @@ module MjmlRb
40
40
  return unless defined?(ActionView::Template)
41
41
 
42
42
  require_relative "mjml-rb/template_handler"
43
- ActionView::Template.register_template_handler(:mjml, TemplateHandler)
43
+ ActionView::Template.register_template_handler(:mjml, TemplateHandler.new)
44
44
  end
45
45
 
46
46
  def mjml2html(mjml, options = {})
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mjml-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.39
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrei Andriichuk