amber_component 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46dc65dbef14224da8e0ce373eb07528188c399444eb2b90968c1cf3dc049864
4
- data.tar.gz: d547837963b2e6148a0724d961f3ba9fa1f540365a711d40d483a24ccdcf8909
3
+ metadata.gz: '0142826c9117720944d7c6f3ab6a8c56e551ed684c92e1d7ce4857ccbe2632c0'
4
+ data.tar.gz: 749a03720a2a3a6b7131ffc0e432af7dce37e11d4375052f6b051b799f9f66be
5
5
  SHA512:
6
- metadata.gz: 9f060bd9c1a97475c0678ddc5c0df166bf6f05001cde7f43a41bdc130c068b2ea24c15518d384016aeef2e8ef592b2928c305a41aaaa24dcebf038783a96b57b
7
- data.tar.gz: 8f2f8029094be9ac3eccbb55b1c46a3c1ed43bb5e7d4c55263bf9bf0a2501862589f7644b8c357ceaa1d8762ea2370125f29c85bce7299925588570ba5118860
6
+ metadata.gz: c06aa0648eb8767949de4b69ab288a1534333f0281095d757daf9564402c24c896bb94b78206d2b9219ddbccd61db1dc67281480ee8ac52abf541d8c17e18bc9
7
+ data.tar.gz: 196d879455fc376f6558048e801522a865753ece6aec2ecb6f0888a867707a43a04b629d87c2a2767800280482ec9d375cf56008e74bdbafd56d4b5ab5f8f2e5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.1.0] - 2022-07-21
3
+ ## [1.2.0] - 2023-01-25
4
+
5
+ ### Breaking changes
6
+
7
+ - Inline view syntax has been changed from `view :[view_type] { '[content]' }` to `view '[content]', type: :[view_type]`
8
+
9
+ - Overriding the view template when rendering a component has been removed (eg. `ExampleComponent.call view: '<h1>Some overriden view</h1>'`)
10
+
11
+ ### Added
12
+
13
+ - ERB compiled template caching in production
14
+
15
+ ### Changed
16
+
17
+ - View rendering pipeline has been rewritten
18
+
19
+ ### Fixed
20
+
21
+ - Nesting components has been fixed
22
+
23
+ ## [1.1.1] - 2022-11-14
24
+
25
+ ### Added
26
+
27
+ - Support for webpacker
28
+
29
+ ## [1.1.0] - 2022-11-13
30
+
31
+ ### Added
32
+
33
+ - StimulusJS controllers for components
34
+
35
+ ## [1.0.0] - 2022-11-07
4
36
 
5
37
  - Initial release
data/Gemfile CHANGED
@@ -10,7 +10,7 @@ gem 'rake', '~> 13.0'
10
10
  # Development dependencies
11
11
  gem 'byebug'
12
12
  gem 'git'
13
- gem 'haml'
13
+ gem 'haml-rails'
14
14
  gem 'rubocop', '~> 1.21'
15
15
  gem 'sassc'
16
16
  gem 'solargraph'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- amber_component (1.1.1)
4
+ amber_component (1.2.0)
5
5
  actionview (>= 6)
6
6
  activemodel (>= 6)
7
7
  activesupport (>= 6)
@@ -48,9 +48,15 @@ GEM
48
48
  ffi (1.15.5)
49
49
  git (1.11.0)
50
50
  rchardet (~> 1.8)
51
- haml (5.2.2)
52
- temple (>= 0.8.0)
51
+ haml (6.1.1)
52
+ temple (>= 0.8.2)
53
+ thor
53
54
  tilt
55
+ haml-rails (2.1.0)
56
+ actionpack (>= 5.1)
57
+ activesupport (>= 5.1)
58
+ haml (>= 4.0.6)
59
+ railties (>= 5.1)
54
60
  i18n (1.12.0)
55
61
  concurrent-ruby (~> 1.0)
56
62
  jaro_winkler (1.5.4)
@@ -139,7 +145,7 @@ GEM
139
145
  thor (~> 1.0)
140
146
  tilt (~> 2.0)
141
147
  yard (~> 0.9, >= 0.9.24)
142
- temple (0.8.2)
148
+ temple (0.10.0)
143
149
  thor (1.2.1)
144
150
  tilt (2.0.11)
145
151
  tzinfo (2.0.5)
@@ -159,7 +165,7 @@ DEPENDENCIES
159
165
  bundler-audit
160
166
  byebug
161
167
  git
162
- haml
168
+ haml-rails
163
169
  minitest (~> 5.0)
164
170
  railties
165
171
  rake (~> 13.0)
data/README.md CHANGED
@@ -337,7 +337,10 @@ custom HTML to a component.
337
337
 
338
338
  This works similarly to React's `props.children`.
339
339
 
340
- To render the passed nested content call `yield.html_safe` somewhere inside the template/view.
340
+ To render the passed nested content call `children(&block)` somewhere inside the ERB template/view.
341
+ If you're using another template language like Haml,
342
+ you may need to use `children{yield}` instead. This difference
343
+ is due to how these templates are compiled.
341
344
 
342
345
  ```ruby
343
346
  # app/components/modal_component.rb
@@ -358,7 +361,7 @@ end
358
361
 
359
362
  <div class="modal_body">
360
363
  <!-- nested content will be rendered here -->
361
- <%= yield.html_safe %>
364
+ <%= children(&block) %>
362
365
  </div>
363
366
 
364
367
  <div class="modal_footer">
@@ -389,7 +392,7 @@ Note that this will raise an error when no block/nested content is provided.
389
392
 
390
393
  In order to render nested content
391
394
  only when it is present (will work without nested content)
392
- you can use `yield.html_safe if block_given?`
395
+ you can use `children(&block) if block_given?` in ERB templates (or `children{yield} if block_given?` for Haml and others)
393
396
 
394
397
  In general `block_given?` will return `true` when a block/nested content is present, otherwise `false`.
395
398
  You can use it to render content conditionally based on
@@ -5,15 +5,15 @@ module ::AmberComponent
5
5
  module Assets
6
6
  # Class methods for assets.
7
7
  module ClassMethods
8
- # @return [String]
8
+ # @return [Pathname]
9
9
  def asset_dir_path
10
- component_file_path, = source_location
10
+ component_file_path = source_location.first
11
11
  return asset_dir_from_name unless component_file_path
12
12
 
13
- component_file_path.delete_suffix('.rb')
13
+ ::Pathname.new component_file_path.delete_suffix('.rb')
14
14
  end
15
15
 
16
- # @return [String, nil]
16
+ # @return [Pathname, nil]
17
17
  def asset_dir_from_name
18
18
  return unless defined?(::Rails)
19
19
 
@@ -23,17 +23,17 @@ module ::AmberComponent
23
23
  # Get an array of all folders containing component assets.
24
24
  # This method should only be used on the parent class `AmberComponent::Base` or `ApplicationComponent`.
25
25
  #
26
- # @return [Array<String>]
26
+ # @return [Array<Pathname>]
27
27
  def all_asset_dir_paths
28
28
  subclasses.map(&:asset_dir_path)
29
29
  end
30
30
 
31
- # @param file_name [String, nil]
32
- # @return [String, nil]
31
+ # @param file_name [String, Pathname, nil]
32
+ # @return [Pathname, nil]
33
33
  def asset_path(file_name)
34
34
  return unless file_name
35
35
 
36
- ::File.join(asset_dir_path, file_name)
36
+ asset_dir_path / file_name
37
37
  end
38
38
 
39
39
  # Returns the name of the file inside the asset directory
@@ -45,15 +45,12 @@ module ::AmberComponent
45
45
  return [] unless ::File.directory?(asset_dir_path)
46
46
 
47
47
  ::Dir.entries(asset_dir_path).select do |file|
48
- next unless ::File.file?(::File.join(asset_dir_path, file))
48
+ next unless ::File.file?(asset_dir_path / file)
49
49
 
50
50
  file.match? type_regexp
51
51
  end
52
52
  end
53
53
  end
54
54
 
55
- # Instance methods for assets.
56
- module InstanceMethods
57
- end
58
55
  end
59
56
  end
@@ -42,9 +42,7 @@ module ::AmberComponent
42
42
  extend Helpers::ClassHelper
43
43
 
44
44
  include Helpers::CssHelper
45
- include Views::InstanceMethods
46
45
  extend Views::ClassMethods
47
- include Assets::InstanceMethods
48
46
  extend Assets::ClassMethods
49
47
  include Rendering::InstanceMethods
50
48
  extend Rendering::ClassMethods
@@ -57,18 +55,40 @@ module ::AmberComponent
57
55
  memoize :asset_dir_path
58
56
 
59
57
  # Memoize these methods in production
60
- if ::ENV['RAILS_ENV'] == 'production'
58
+ if defined?(::Rails.env) && ::Rails.env.production?
61
59
  memoize :view_path
62
60
  memoize :view_file_name
63
61
  memoize :view_type
64
62
  end
65
63
 
64
+ # @return [Class]
65
+ def compiled_method_container
66
+ self
67
+ end
68
+
69
+ # @return [String]
70
+ def type
71
+ 'text/html'
72
+ end
73
+
74
+ # @return [Symbol]
75
+ def format
76
+ :html
77
+ end
78
+
79
+ # @return [String]
80
+ def identifier
81
+ source_location.first
82
+ end
83
+
66
84
  private
67
85
 
68
86
  # @param subclass [Class]
69
87
  # @return [void]
70
88
  def inherited(subclass)
71
89
  super
90
+ return unless subclass.name
91
+
72
92
  method_body = lambda do |**kwargs, &block|
73
93
  subclass.render(**kwargs, &block)
74
94
  end
@@ -130,6 +150,11 @@ module ::AmberComponent
130
150
  end
131
151
  end
132
152
 
153
+ # @return [Class]
154
+ def compiled_method_container
155
+ self.class
156
+ end
157
+
133
158
  private
134
159
 
135
160
  # @param kwargs [Hash{Symbol => Object}]
@@ -3,17 +3,82 @@
3
3
  module ::AmberComponent
4
4
  # Provides universal methods for rendering components.
5
5
  module Rendering
6
+
7
+ # @return [Symbol]
8
+ RENDER_TEMPLATE_METHOD_NAME = :__render
9
+
6
10
  # Class methods for rendering.
7
11
  module ClassMethods
8
12
  # @param kwargs [Hash{Symbol => Object}]
9
13
  # @return [String]
10
14
  def render(**kwargs, &block)
11
- comp = new(**kwargs)
12
-
13
- comp.render(&block)
15
+ new(**kwargs).render(&block)
14
16
  end
15
17
 
16
18
  alias call render
19
+
20
+ # @return [Boolean]
21
+ def compiled?
22
+ method_defined?(RENDER_TEMPLATE_METHOD_NAME)
23
+ end
24
+
25
+ # @return [Boolean]
26
+ def compile?
27
+ return true if defined?(::Rails.env) && ::Rails.env.development?
28
+
29
+ !compiled?
30
+ end
31
+
32
+ # @param force [Boolean] force recompilation
33
+ # @return [void]
34
+ def compile(force: false)
35
+ return if !compile? && !force
36
+ return if template_handler.nil?
37
+
38
+ render_template_method_redefinition_lock.synchronize do
39
+ silence_redefinition_of_method(RENDER_TEMPLATE_METHOD_NAME)
40
+ # rubocop:disable Style/EvalWithLocation
41
+ class_eval <<~CODE, view_path.to_s, 0 # rubocop:disable Style/DocumentDynamicEvalDefinition
42
+ def #{RENDER_TEMPLATE_METHOD_NAME}(local_assigns, output_buffer, &block)
43
+ #{compiled_template_source}
44
+ end
45
+ CODE
46
+ # rubocop:enable Style/EvalWithLocation
47
+ end
48
+ end
49
+
50
+ # @return [Class, nil]
51
+ def template_handler
52
+ @template_handler ||= ::ActionView::Template.registered_template_handler(view_type)
53
+ end
54
+
55
+ private
56
+
57
+ # @return [Mutex]
58
+ def render_template_method_redefinition_lock
59
+ @render_template_method_redefinition_lock ||= ::Mutex.new
60
+ end
61
+
62
+ # @return [String]
63
+ def compiled_template_source
64
+ handler = template_handler
65
+ unless handler
66
+ raise UnknownViewTypeError,
67
+ "view type `#{view_type.inspect}` is not known in #{self}, " \
68
+ "available types: #{::ActionView::Template.template_handler_extensions.inspect}"
69
+ end
70
+
71
+ if handler.method(:call).parameters.length > 1
72
+ handler.call(self, view_template_source)
73
+ else
74
+ handler.call(
75
+ source: view_template_source,
76
+ identifier: identifier,
77
+ type: type
78
+ )
79
+ end
80
+ end
81
+
17
82
  end
18
83
 
19
84
  # Instance methods for rendering.
@@ -21,10 +86,7 @@ module ::AmberComponent
21
86
  # @return [String]
22
87
  def render(&block)
23
88
  run_callbacks :render do
24
- element = render_view(&block)
25
- # styles = inject_styles
26
- # element += styles unless styles.nil?
27
- element.html_safe
89
+ compile_and_render(&block)
28
90
  end
29
91
  end
30
92
 
@@ -39,13 +101,49 @@ module ::AmberComponent
39
101
  render
40
102
  end
41
103
 
42
- protected
104
+ # @param args [Array<Object>]
105
+ # @return [String]
106
+ def nested_content(*args, &block)
107
+ block_self = block.binding.receiver
108
+ return block_self.safe_capture(*args, &block) if block_self.respond_to?(:safe_capture)
109
+
110
+ safe_capture(*args, &block)
111
+ end
112
+ alias children nested_content
113
+
114
+ def safe_capture(*args)
115
+ value = nil
116
+ buffer = with_output_buffer { value = yield(*args) }
117
+ buffer.presence || value.html_safe
118
+ end
119
+
120
+ private
121
+
122
+ # @return [String]
123
+ def compile_and_render(&block)
124
+ self.class.compile
125
+ if self.class.compiled?
126
+ return _run(
127
+ RENDER_TEMPLATE_METHOD_NAME,
128
+ self.class.template_handler,
129
+ [],
130
+ ::ActionView::OutputBuffer.new,
131
+ &block
132
+ )
133
+ end
134
+
135
+ render_non_rails_string(
136
+ self.class.view_template_source,
137
+ self.class.view_type,
138
+ block
139
+ )
140
+ end
43
141
 
44
142
  # @param content [String]
45
143
  # @param type [Symbol]
46
144
  # @param block [Proc, nil]
47
145
  # @return [String]
48
- def render_string(content, type, block = nil)
146
+ def render_non_rails_string(content, type, block = nil)
49
147
  TemplateHandler.render_from_string(self, content, type, block)
50
148
  end
51
149
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ::AmberComponent
4
4
  # Provides code which handles rendering different
5
- # template languages.
5
+ # template languages outside of Rails.
6
6
  module TemplateHandler
7
7
  class << self
8
8
  # @param context [AmberComponent::Base]
@@ -11,16 +11,15 @@ module ::AmberComponent
11
11
  # @param block [Proc, nil]
12
12
  # @return [String]
13
13
  def render_from_string(context, content, type, block = nil)
14
- options = if type.to_sym == :erb
15
- { engine_class: ERB }
16
- else
17
- {}
18
- end
14
+ tilt_handler = ::Tilt[type]
15
+ raise UnknownViewTypeError, <<~ERR.squish unless tilt_handler
16
+ Unknown view type for `#{context.class}`!
17
+ Check return value of param type in `view type: :[type]`
18
+ or the view file extension.
19
+ ERR
19
20
 
20
- ::Tilt[type].new(options) { content }.render(context, &block)
21
+ tilt_handler.new { content }.render(context, &block).html_safe
21
22
  end
22
23
  end
23
24
  end
24
25
  end
25
-
26
- require_relative 'template_handler/erb'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ::AmberComponent
4
- VERSION = '1.1.1'
4
+ VERSION = '1.2.0'
5
5
  end
@@ -1,14 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'pathname'
4
+
3
5
  module ::AmberComponent
4
6
  # Provides methods concerning view registering and rendering.
5
7
  module Views
6
- # View types with built-in embedded Ruby
7
- #
8
- # @return [Set<Symbol>]
9
- VIEW_TYPES_WITH_RUBY = ::Set[:erb, :haml, :slim].freeze
10
- # @return [Set<Symbol>]
11
- ALLOWED_VIEW_TYPES = ::Set[:erb, :haml, :slim, :html].freeze
12
8
  # @return [Regexp]
13
9
  VIEW_FILE_REGEXP = /^view\./.freeze
14
10
 
@@ -18,28 +14,25 @@ module ::AmberComponent
18
14
  #
19
15
  # Usage:
20
16
  #
21
- # view do
22
- # <<~ERB
23
- # <h1>
24
- # Hello <%= @name %>
25
- # </h1>
26
- # ERB
27
- # end
17
+ # view <<~ERB
18
+ # <h1>
19
+ # Hello <%= @name %>
20
+ # </h1>
21
+ # ERB
28
22
  #
29
23
  # or:
30
24
  #
31
- # view :haml do
32
- # <<~HAML
33
- # %h1
34
- # Hello
35
- # = @name
36
- # HAML
37
- # end
25
+ # view <<~HAML, type: :haml
26
+ # %h1
27
+ # Hello
28
+ # = @name
29
+ # HAML
38
30
  #
31
+ # @param content [String, Proc]
39
32
  # @param type [Symbol]
40
33
  # @return [void]
41
- def view(type = :erb, &block)
42
- @method_view = TypedContent.new(type: type, content: block)
34
+ def view(content, type: :erb)
35
+ @method_view = TypedContent.new(type: type, content: content)
43
36
  end
44
37
 
45
38
  # ERB/Haml/Slim view registered through the `view` method.
@@ -48,6 +41,13 @@ module ::AmberComponent
48
41
  attr_reader :method_view
49
42
 
50
43
  # @return [String]
44
+ def view_template_source
45
+ return @method_view.to_s if @method_view
46
+
47
+ ::File.read(view_path)
48
+ end
49
+
50
+ # @return [String, nil]
51
51
  def view_path
52
52
  asset_path view_file_name
53
53
  end
@@ -62,136 +62,11 @@ module ::AmberComponent
62
62
 
63
63
  # @return [Symbol]
64
64
  def view_type
65
- (view_file_name.split('.')[1..].grep_v(/erb/).last || 'erb')&.to_sym
66
- end
67
- end
68
-
69
- # Instance methods for views.
70
- module InstanceMethods
71
- protected
72
-
73
- # @return [String]
74
- def render_view(&block)
75
- view_from_file = render_view_from_file(&block)
76
- view_from_method = render_class_method_view(&block)
77
- view_from_inline = render_view_from_inline(&block)
78
-
79
- view_content = view_from_file unless view_from_file.empty?
80
- view_content = view_from_method unless view_from_method.empty?
81
- view_content = view_from_inline unless view_from_inline.empty?
82
-
83
- if view_content.nil? || view_content.empty?
84
- raise ViewFileNotFoundError, "View for `#{self.class}` could not be found!"
85
- end
86
-
87
- view_content
88
- end
89
-
90
- # Helper method to render view from string or with other provided type.
91
- #
92
- # Usage:
93
- #
94
- # render_view_from_content('<h1>Hello World</h1>')
95
- #
96
- # or:
97
- #
98
- # render_view_from_content content: '**Hello World**', type: 'md'
99
- #
100
- # @param content [TypedContent, Hash{Symbol => String, Symbol, Proc}, String]
101
- # @return [String, nil]
102
- def render_view_from_content(content, &block)
103
- return '' unless content
104
- return content if content.is_a?(::String)
105
-
106
- content = TypedContent.wrap(content)
107
- type = content.type
108
- content = content.to_s
109
-
110
- if content.empty?
111
- raise EmptyViewError, <<~ERR.squish
112
- Custom view for `#{self.class}` from view method cannot be empty!
113
- ERR
114
- end
115
-
116
- unless ALLOWED_VIEW_TYPES.include? type
117
- raise UnknownViewTypeError, <<~ERR.squish
118
- Unknown view type for `#{self.class}` from view method!
119
- Check return value of param type in `view :[type] do`
120
- ERR
121
- end
122
-
123
- unless VIEW_TYPES_WITH_RUBY.include? type
124
- # first render the content with ERB if the
125
- # type does not support embedding Ruby by default
126
- content = render_string(content, :erb, block)
127
- end
128
-
129
- render_string(content, type, block)
130
- end
131
-
132
- # @return [String]
133
- def render_view_from_file(&block)
134
- view_path = self.class.view_path
135
- return '' if view_path.nil? || !::File.file?(view_path)
136
-
137
- content = ::File.read(view_path)
138
- type = self.class.view_type
139
-
140
- unless VIEW_TYPES_WITH_RUBY.include? type
141
- content = render_string(content, :erb, block)
142
- end
143
-
144
- render_string(content, type, block)
145
- end
146
-
147
- # Method returning view from method in class file.
148
- # Usage:
149
- #
150
- # view do
151
- # <<~HTML
152
- # <h1>
153
- # Hello <%= @name %>
154
- # </h1>
155
- # HTML
156
- # end
157
- #
158
- # or:
159
- #
160
- # view :haml do
161
- # <<~HAML
162
- # %h1
163
- # Hello
164
- # = @name
165
- # HAML
166
- # end
167
- #
168
- # @return [String]
169
- def render_class_method_view(&block)
170
- render_view_from_content(self.class.method_view, &block)
171
- end
172
-
173
- # Method returning view from params in view.
174
- # Usage:
175
- #
176
- # <%= ExampleComponent data: data, view: "<h1>Hello #{@name}</h1>" %>
177
- #
178
- # or:
179
- #
180
- # <%= ExampleComponent data: data, view: { content: "<h1>Hello #{@name}</h1>", type: 'erb' } %>
181
- #
182
- # @return [String]
183
- def render_view_from_inline(&block)
184
- data = \
185
- if @view.is_a? ::String
186
- TypedContent.new(
187
- type: :erb,
188
- content: @view
189
- )
190
- else
191
- @view
192
- end
65
+ return @method_view.type if @method_view
66
+ raise ViewFileNotFoundError, "No view file for #{self}" unless view_file_name
193
67
 
194
- render_view_from_content(data, &block)
68
+ view_file_path = ::Pathname.new view_file_name
69
+ view_file_path.extname.delete_prefix('.').to_sym
195
70
  end
196
71
  end
197
72
  end
@@ -12,7 +12,6 @@ module ::AmberComponent
12
12
  class Error < ::StandardError; end
13
13
  class MissingPropsError < Error; end
14
14
  class IncorrectPropTypeError < Error; end
15
- class ViewFileNotFoundError < Error; end
16
15
  class InvalidTypeError < Error; end
17
16
 
18
17
  class EmptyViewError < Error; end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amber_component
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ruby-Amber
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2022-11-14 00:00:00.000000000 Z
13
+ date: 2023-01-25 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: actionview
@@ -123,7 +123,6 @@ files:
123
123
  - lib/amber_component/railtie.rb
124
124
  - lib/amber_component/rendering.rb
125
125
  - lib/amber_component/template_handler.rb
126
- - lib/amber_component/template_handler/erb.rb
127
126
  - lib/amber_component/test_helper.rb
128
127
  - lib/amber_component/typed_content.rb
129
128
  - lib/amber_component/version.rb
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'action_view'
4
- require 'ostruct'
5
-
6
- module ::AmberComponent
7
- module TemplateHandler
8
- # Handles rendering ERB with Rails-like syntax
9
- class ERB < ::ActionView::Template::Handlers::ERB::Erubi
10
- def initialize(input, properties = {})
11
- properties[:bufvar] ||= "@output_buffer"
12
- properties[:preamble] = "#{properties[:bufvar]}=#{::ActionView::OutputBuffer}.new;"
13
- super
14
- end
15
- end
16
- end
17
- end