view_component 2.61.1 → 2.64.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.
Potentially problematic release.
This version of view_component might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/docs/CHANGELOG.md +58 -0
- data/lib/view_component/base.rb +4 -18
- data/lib/view_component/compile_cache.rb +1 -2
- data/lib/view_component/compiler.rb +16 -12
- data/lib/view_component/engine.rb +0 -16
- data/lib/view_component/polymorphic_slots.rb +10 -4
- data/lib/view_component/render_component_helper.rb +1 -0
- data/lib/view_component/slotable_v2.rb +34 -6
- data/lib/view_component/version.rb +2 -2
- data/lib/view_component.rb +0 -2
- metadata +30 -4
- data/lib/view_component/global_output_buffer.rb +0 -100
- data/lib/view_component/output_buffer_stack.rb +0 -65
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1cee1c1b53cec5fec9d4613416a27999c653c2cf8fb176798b235c7b71dc795d
|
4
|
+
data.tar.gz: 5fb8a364788849fecfb8bb2160ebd6dc403f624ba6b3fe13c818706f928b8257
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d721f8d07af64e314a506afc364941f95d3b824d27e587e12d8c774f4fa168b7ae00ac400c4f73b546ed0d5728aec60d586e52dacaee2b8f10e01230bbe3ab8f
|
7
|
+
data.tar.gz: 598ab2f08524a8eb10b17a001ed7429223ca39ab204c25cec4375ea201e3afa1c852ba1578f81a1de5c83211e1eb05f3c1a7d146f83cc1d77e3f4ed0bfdef962
|
data/docs/CHANGELOG.md
CHANGED
@@ -9,6 +9,64 @@ title: Changelog
|
|
9
9
|
|
10
10
|
## main
|
11
11
|
|
12
|
+
## 2.64.0
|
13
|
+
|
14
|
+
* Add `warn_on_deprecated_slot_setter` flag to opt-in to deprecation warning.
|
15
|
+
|
16
|
+
In [v2.54.0](https://viewcomponent.org/CHANGELOG.html#2540), the Slots API was updated to require the `with_*` prefix for setting Slots. The non-`with_*` setters will be deprecated in a coming version and removed in `v3.0`.
|
17
|
+
|
18
|
+
To enable the coming deprecation warning, add `warn_on_deprecated_slot_setter`:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
class DeprecatedSlotsSetterComponent < ViewComponent::Base
|
22
|
+
warn_on_deprecated_slot_setter
|
23
|
+
end
|
24
|
+
```
|
25
|
+
|
26
|
+
*Joel Hawksley*
|
27
|
+
|
28
|
+
* Add [`m`](https://rubygems.org/gems/m) to development environment.
|
29
|
+
|
30
|
+
*Joel Hawksley*
|
31
|
+
|
32
|
+
* Fix potential deadlock scenario in the compiler's development mode.
|
33
|
+
|
34
|
+
*Blake Williams*
|
35
|
+
|
36
|
+
## 2.63.0
|
37
|
+
|
38
|
+
* Fixed typo in `renders_many` documentation.
|
39
|
+
|
40
|
+
*Graham Rogers*
|
41
|
+
|
42
|
+
* Add documentation about working with `turbo-rails`.
|
43
|
+
|
44
|
+
*Matheus Poli Camilo*
|
45
|
+
|
46
|
+
* Fix issue causing helper methods to not be available in nested components when the render monkey patch is disabled and `render_component` is used.
|
47
|
+
|
48
|
+
*Daniel Scheffknecht*
|
49
|
+
|
50
|
+
## 2.62.0
|
51
|
+
|
52
|
+
* Remove the experimental global output buffer feature.
|
53
|
+
* Restore functionality that used to attempt to compile templates on each call to `#render_in`.
|
54
|
+
* Un-pin `rails` `main` dependency.
|
55
|
+
|
56
|
+
*Cameron Dutro*
|
57
|
+
|
58
|
+
* Add blank space between "in" and "ViewComponent" in a deprecation warning.
|
59
|
+
|
60
|
+
*Vikram Dighe*
|
61
|
+
|
62
|
+
* Add HappyCo to list of companies using ViewComponent.
|
63
|
+
|
64
|
+
*Josh Clayton*
|
65
|
+
|
66
|
+
* Add predicate method support to polymorphic slots.
|
67
|
+
|
68
|
+
*Graham Rogers*
|
69
|
+
|
12
70
|
## 2.61.1
|
13
71
|
|
14
72
|
* Revert `Expose Capybara DSL methods directly inside tests.` This change unintentionally broke other Capybara methods and thus introduced a regression. We aren't confident that we can fail forward so we have decided to revert this change.
|
data/lib/view_component/base.rb
CHANGED
@@ -86,10 +86,12 @@ module ViewComponent
|
|
86
86
|
#
|
87
87
|
# @return [String]
|
88
88
|
def render_in(view_context, &block)
|
89
|
+
self.class.compile(raise_errors: true)
|
90
|
+
|
89
91
|
@view_context = view_context
|
90
92
|
self.__vc_original_view_context ||= view_context
|
91
93
|
|
92
|
-
@output_buffer = ActionView::OutputBuffer.new
|
94
|
+
@output_buffer = ActionView::OutputBuffer.new
|
93
95
|
|
94
96
|
@lookup_context ||= view_context.lookup_context
|
95
97
|
|
@@ -124,7 +126,7 @@ module ViewComponent
|
|
124
126
|
before_render
|
125
127
|
|
126
128
|
if render?
|
127
|
-
|
129
|
+
render_template_for(@__vc_variant).to_s + _output_postamble
|
128
130
|
else
|
129
131
|
""
|
130
132
|
end
|
@@ -132,11 +134,6 @@ module ViewComponent
|
|
132
134
|
@current_template = old_current_template
|
133
135
|
end
|
134
136
|
|
135
|
-
# @private
|
136
|
-
def perform_render
|
137
|
-
render_template_for(@__vc_variant).to_s + _output_postamble
|
138
|
-
end
|
139
|
-
|
140
137
|
# Subclass components that call `super` inside their template code will cause a
|
141
138
|
# double render if they emit the result:
|
142
139
|
#
|
@@ -152,17 +149,6 @@ module ViewComponent
|
|
152
149
|
nil
|
153
150
|
end
|
154
151
|
|
155
|
-
# @private
|
156
|
-
# :nocov:
|
157
|
-
def render_template_for(variant = nil)
|
158
|
-
# Force compilation here so the compiler always redefines render_template_for.
|
159
|
-
# This is mostly a safeguard to prevent infinite recursion.
|
160
|
-
self.class.compile(raise_errors: true, force: true)
|
161
|
-
# .compile replaces this method; call the new one
|
162
|
-
render_template_for(variant)
|
163
|
-
end
|
164
|
-
# :nocov:
|
165
|
-
|
166
152
|
# EXPERIMENTAL: Optional content to be returned after the rendered template.
|
167
153
|
#
|
168
154
|
# @return [String]
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "concurrent-ruby"
|
4
|
+
|
3
5
|
module ViewComponent
|
4
6
|
class Compiler
|
5
7
|
# Lock required to be obtained before compiling the component
|
@@ -16,7 +18,7 @@ module ViewComponent
|
|
16
18
|
|
17
19
|
def initialize(component_class)
|
18
20
|
@component_class = component_class
|
19
|
-
@__vc_compiler_lock =
|
21
|
+
@__vc_compiler_lock = Concurrent::ReadWriteLock.new
|
20
22
|
end
|
21
23
|
|
22
24
|
def compiled?
|
@@ -33,7 +35,9 @@ module ViewComponent
|
|
33
35
|
|
34
36
|
component_class.superclass.compile(raise_errors: raise_errors) if should_compile_superclass?
|
35
37
|
|
36
|
-
|
38
|
+
with_write_lock do
|
39
|
+
CompileCache.invalidate_class!(component_class)
|
40
|
+
|
37
41
|
subclass_instance_methods = component_class.instance_methods(false)
|
38
42
|
|
39
43
|
if subclass_instance_methods.include?(:with_content) && raise_errors
|
@@ -66,8 +70,8 @@ module ViewComponent
|
|
66
70
|
# as Ruby warns when redefining a method.
|
67
71
|
method_name = call_method_name(template[:variant])
|
68
72
|
|
69
|
-
if component_class.instance_methods
|
70
|
-
component_class.send(:
|
73
|
+
if component_class.instance_methods.include?(method_name.to_sym)
|
74
|
+
component_class.send(:undef_method, method_name.to_sym)
|
71
75
|
end
|
72
76
|
|
73
77
|
# rubocop:disable Style/EvalWithLocation
|
@@ -88,18 +92,16 @@ module ViewComponent
|
|
88
92
|
end
|
89
93
|
end
|
90
94
|
|
91
|
-
def
|
95
|
+
def with_write_lock(&block)
|
92
96
|
if development?
|
93
|
-
__vc_compiler_lock.
|
97
|
+
__vc_compiler_lock.with_write_lock(&block)
|
94
98
|
else
|
95
99
|
block.call
|
96
100
|
end
|
97
101
|
end
|
98
102
|
|
99
|
-
def
|
100
|
-
|
101
|
-
component_class.send(:remove_method, :render_template_for)
|
102
|
-
end
|
103
|
+
def with_read_lock(&block)
|
104
|
+
__vc_compiler_lock.with_read_lock(&block)
|
103
105
|
end
|
104
106
|
|
105
107
|
private
|
@@ -107,7 +109,9 @@ module ViewComponent
|
|
107
109
|
attr_reader :component_class
|
108
110
|
|
109
111
|
def define_render_template_for
|
110
|
-
|
112
|
+
if component_class.instance_methods.include?(:render_template_for)
|
113
|
+
component_class.send(:undef_method, :render_template_for)
|
114
|
+
end
|
111
115
|
|
112
116
|
variant_elsifs = variants.compact.uniq.map do |variant|
|
113
117
|
"elsif variant.to_sym == :#{variant}\n #{call_method_name(variant)}"
|
@@ -125,7 +129,7 @@ module ViewComponent
|
|
125
129
|
if development?
|
126
130
|
component_class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
127
131
|
def render_template_for(variant = nil)
|
128
|
-
self.class.compiler.
|
132
|
+
self.class.compiler.with_read_lock do
|
129
133
|
#{body}
|
130
134
|
end
|
131
135
|
end
|
@@ -20,7 +20,6 @@ module ViewComponent
|
|
20
20
|
options.instrumentation_enabled = false if options.instrumentation_enabled.nil?
|
21
21
|
options.preview_route ||= ViewComponent::Base.preview_route
|
22
22
|
options.preview_controller ||= ViewComponent::Base.preview_controller
|
23
|
-
options.use_global_output_buffer = false if options.use_global_output_buffer.nil?
|
24
23
|
|
25
24
|
if options.show_previews
|
26
25
|
options.preview_paths << "#{Rails.root}/test/components/previews" if defined?(Rails.root) && Dir.exist?(
|
@@ -58,21 +57,6 @@ module ViewComponent
|
|
58
57
|
end
|
59
58
|
end
|
60
59
|
|
61
|
-
initializer "view_component.enable_global_output_buffer" do |app|
|
62
|
-
ActiveSupport.on_load(:view_component) do
|
63
|
-
env_use_gob = ENV.fetch("VIEW_COMPONENT_USE_GLOBAL_OUTPUT_BUFFER", "false") == "true"
|
64
|
-
config_use_gob = app.config.view_component.use_global_output_buffer
|
65
|
-
|
66
|
-
if config_use_gob || env_use_gob
|
67
|
-
# :nocov:
|
68
|
-
app.config.view_component.use_global_output_buffer = true
|
69
|
-
ViewComponent::Base.prepend(ViewComponent::GlobalOutputBuffer)
|
70
|
-
ActionView::Base.prepend(ViewComponent::GlobalOutputBuffer::ActionViewMods)
|
71
|
-
# :nocov:
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
60
|
initializer "view_component.set_autoload_paths" do |app|
|
77
61
|
options = app.config.view_component
|
78
62
|
|
@@ -42,6 +42,10 @@ module ViewComponent
|
|
42
42
|
define_method(getter_name) do
|
43
43
|
get_slot(slot_name)
|
44
44
|
end
|
45
|
+
|
46
|
+
define_method("#{getter_name}?") do
|
47
|
+
get_slot(slot_name).present?
|
48
|
+
end
|
45
49
|
end
|
46
50
|
|
47
51
|
renderable_hash = types.each_with_object({}) do |(poly_type, poly_callable), memo|
|
@@ -57,10 +61,12 @@ module ViewComponent
|
|
57
61
|
end
|
58
62
|
|
59
63
|
define_method(setter_name) do |*args, &block|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
+
if _warn_on_deprecated_slot_setter
|
65
|
+
ViewComponent::Deprecation.warn(
|
66
|
+
"polymorphic slot setters like `#{setter_name}` are deprecated and will be removed in " \
|
67
|
+
"ViewComponent v3.0.0.\n\nUse `with_#{setter_name}` instead."
|
68
|
+
)
|
69
|
+
end
|
64
70
|
|
65
71
|
set_polymorphic_slot(slot_name, poly_type, *args, &block)
|
66
72
|
end
|
@@ -17,9 +17,19 @@ module ViewComponent
|
|
17
17
|
# Hash of registered Slots
|
18
18
|
class_attribute :registered_slots
|
19
19
|
self.registered_slots = {}
|
20
|
+
|
21
|
+
class_attribute :_warn_on_deprecated_slot_setter
|
22
|
+
self._warn_on_deprecated_slot_setter = false
|
20
23
|
end
|
21
24
|
|
22
25
|
class_methods do
|
26
|
+
##
|
27
|
+
# Enables deprecations coming to the Slots API in ViewComponent v3
|
28
|
+
#
|
29
|
+
def warn_on_deprecated_slot_setter
|
30
|
+
self._warn_on_deprecated_slot_setter = true
|
31
|
+
end
|
32
|
+
|
23
33
|
##
|
24
34
|
# Registers a sub-component
|
25
35
|
#
|
@@ -80,7 +90,13 @@ module ViewComponent
|
|
80
90
|
if args.empty? && block.nil?
|
81
91
|
get_slot(slot_name)
|
82
92
|
else
|
83
|
-
|
93
|
+
if _warn_on_deprecated_slot_setter
|
94
|
+
ViewComponent::Deprecation.warn(
|
95
|
+
"Setting a slot with `##{slot_name}` is deprecated and will be removed in ViewComponent v3.0.0. " \
|
96
|
+
"Use `#with_#{slot_name}` to set the slot instead."
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
84
100
|
set_slot(slot_name, nil, *args, &block)
|
85
101
|
end
|
86
102
|
end
|
@@ -98,11 +114,11 @@ module ViewComponent
|
|
98
114
|
#
|
99
115
|
# = Example
|
100
116
|
#
|
101
|
-
#
|
117
|
+
# renders_many :items, -> (name:) { ItemComponent.new(name: name }
|
102
118
|
#
|
103
119
|
# # OR
|
104
120
|
#
|
105
|
-
#
|
121
|
+
# renders_many :items, ItemComponent
|
106
122
|
#
|
107
123
|
# = Rendering sub-components
|
108
124
|
#
|
@@ -138,9 +154,15 @@ module ViewComponent
|
|
138
154
|
# Define setter for singular names
|
139
155
|
# for example `renders_many :items` allows fetching all tabs with
|
140
156
|
# `component.tabs` and setting a tab with `component.tab`
|
141
|
-
|
142
|
-
# Deprecated: Will remove in 3.0
|
157
|
+
|
143
158
|
define_method singular_name do |*args, &block|
|
159
|
+
if _warn_on_deprecated_slot_setter
|
160
|
+
ViewComponent::Deprecation.warn(
|
161
|
+
"Setting a slot with `##{singular_name}` is deprecated and will be removed in ViewComponent v3.0.0. " \
|
162
|
+
"Use `#with_#{singular_name}` to set the slot instead."
|
163
|
+
)
|
164
|
+
end
|
165
|
+
|
144
166
|
set_slot(slot_name, nil, *args, &block)
|
145
167
|
end
|
146
168
|
ruby2_keywords(singular_name.to_sym) if respond_to?(:ruby2_keywords, true)
|
@@ -162,7 +184,13 @@ module ViewComponent
|
|
162
184
|
if collection_args.nil? && block.nil?
|
163
185
|
get_slot(slot_name)
|
164
186
|
else
|
165
|
-
|
187
|
+
if _warn_on_deprecated_slot_setter
|
188
|
+
ViewComponent::Deprecation.warn(
|
189
|
+
"Setting a slot with `##{slot_name}` is deprecated and will be removed in ViewComponent v3.0.0. " \
|
190
|
+
"Use `#with_#{slot_name}` to set the slot instead."
|
191
|
+
)
|
192
|
+
end
|
193
|
+
|
166
194
|
collection_args.map do |args|
|
167
195
|
set_slot(slot_name, nil, **args, &block)
|
168
196
|
end
|
data/lib/view_component.rb
CHANGED
@@ -11,9 +11,7 @@ module ViewComponent
|
|
11
11
|
autoload :CompileCache
|
12
12
|
autoload :ComponentError
|
13
13
|
autoload :Deprecation
|
14
|
-
autoload :GlobalOutputBuffer
|
15
14
|
autoload :Instrumentation
|
16
|
-
autoload :OutputBufferStack
|
17
15
|
autoload :Preview
|
18
16
|
autoload :PreviewTemplateError
|
19
17
|
autoload :TestHelpers
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: view_component
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.64.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub Open Source
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-08-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -44,6 +44,20 @@ dependencies:
|
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '1.0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: concurrent-ruby
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '1.0'
|
47
61
|
- !ruby/object:Gem::Dependency
|
48
62
|
name: appraisal
|
49
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,6 +156,20 @@ dependencies:
|
|
142
156
|
- - "~>"
|
143
157
|
- !ruby/object:Gem::Version
|
144
158
|
version: '2'
|
159
|
+
- !ruby/object:Gem::Dependency
|
160
|
+
name: m
|
161
|
+
requirement: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - "~>"
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '1'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - "~>"
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '1'
|
145
173
|
- !ruby/object:Gem::Dependency
|
146
174
|
name: minitest
|
147
175
|
requirement: !ruby/object:Gem::Requirement
|
@@ -334,9 +362,7 @@ files:
|
|
334
362
|
- lib/view_component/docs_builder_component.html.erb
|
335
363
|
- lib/view_component/docs_builder_component.rb
|
336
364
|
- lib/view_component/engine.rb
|
337
|
-
- lib/view_component/global_output_buffer.rb
|
338
365
|
- lib/view_component/instrumentation.rb
|
339
|
-
- lib/view_component/output_buffer_stack.rb
|
340
366
|
- lib/view_component/polymorphic_slots.rb
|
341
367
|
- lib/view_component/preview.rb
|
342
368
|
- lib/view_component/preview_template_error.rb
|
@@ -1,100 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ViewComponent
|
4
|
-
module GlobalOutputBuffer
|
5
|
-
def render_in(view_context, &block)
|
6
|
-
unless view_context.output_buffer.is_a?(OutputBufferStack)
|
7
|
-
# use instance_variable_set here to avoid triggering the code in the #output_buffer= method below
|
8
|
-
view_context.instance_variable_set(:@output_buffer, OutputBufferStack.new(view_context.output_buffer))
|
9
|
-
end
|
10
|
-
|
11
|
-
@output_buffer = view_context.output_buffer
|
12
|
-
@global_buffer_in_use = true
|
13
|
-
|
14
|
-
super(view_context, &block)
|
15
|
-
end
|
16
|
-
|
17
|
-
def perform_render
|
18
|
-
# HAML unhelpfully assigns to @output_buffer directly, so we hold onto a reference to
|
19
|
-
# it and restore @output_buffer when the HAML engine is finished. In non-HAML cases,
|
20
|
-
# @output_buffer and orig_buf will point to the same object, making the reassignment
|
21
|
-
# statements no-ops.
|
22
|
-
orig_buf = @output_buffer
|
23
|
-
@output_buffer.push
|
24
|
-
result = render_template_for(@__vc_variant).to_s + _output_postamble
|
25
|
-
@output_buffer = orig_buf
|
26
|
-
@output_buffer.pop
|
27
|
-
result
|
28
|
-
end
|
29
|
-
|
30
|
-
def output_buffer=(other_buffer)
|
31
|
-
@output_buffer.replace(other_buffer)
|
32
|
-
end
|
33
|
-
|
34
|
-
def with_output_buffer(buf = nil)
|
35
|
-
unless buf
|
36
|
-
buf = ActionView::OutputBuffer.new
|
37
|
-
# rubocop:disable Style/SafeNavigation
|
38
|
-
if output_buffer && output_buffer.respond_to?(:encoding)
|
39
|
-
buf.force_encoding(output_buffer.encoding)
|
40
|
-
end
|
41
|
-
# rubocop:enable Style/SafeNavigation
|
42
|
-
end
|
43
|
-
|
44
|
-
output_buffer.push(buf)
|
45
|
-
|
46
|
-
begin
|
47
|
-
yield
|
48
|
-
ensure
|
49
|
-
# assign result here to avoid a return statement, which will
|
50
|
-
# immediately return to the caller and swallow any errors
|
51
|
-
result = output_buffer.pop
|
52
|
-
end
|
53
|
-
|
54
|
-
result
|
55
|
-
end
|
56
|
-
|
57
|
-
module ActionViewMods
|
58
|
-
def output_buffer=(other_buffer)
|
59
|
-
if @output_buffer.is_a?(OutputBufferStack)
|
60
|
-
@output_buffer.replace(other_buffer)
|
61
|
-
else
|
62
|
-
super
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def with_output_buffer(buf = nil)
|
67
|
-
unless buf
|
68
|
-
buf = ActionView::OutputBuffer.new
|
69
|
-
# rubocop:disable Style/SafeNavigation
|
70
|
-
if @output_buffer && @output_buffer.respond_to?(:encoding)
|
71
|
-
buf.force_encoding(@output_buffer.encoding)
|
72
|
-
end
|
73
|
-
# rubocop:enable Style/SafeNavigation
|
74
|
-
end
|
75
|
-
|
76
|
-
if @output_buffer.is_a?(OutputBufferStack)
|
77
|
-
@output_buffer.push(buf)
|
78
|
-
|
79
|
-
begin
|
80
|
-
yield
|
81
|
-
ensure
|
82
|
-
result = @output_buffer.pop
|
83
|
-
end
|
84
|
-
|
85
|
-
result
|
86
|
-
else
|
87
|
-
@output_buffer, old_buffer = buf, output_buffer
|
88
|
-
|
89
|
-
begin
|
90
|
-
yield
|
91
|
-
ensure
|
92
|
-
@output_buffer = old_buffer
|
93
|
-
end
|
94
|
-
|
95
|
-
buf
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ViewComponent
|
4
|
-
class OutputBufferStack
|
5
|
-
delegate_missing_to :@current_buffer
|
6
|
-
delegate :presence, :present?, :html_safe?, to: :@current_buffer
|
7
|
-
|
8
|
-
attr_reader :buffer_stack
|
9
|
-
|
10
|
-
def self.make_frame(*args)
|
11
|
-
ActionView::OutputBuffer.new(*args)
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize(initial_buffer = nil)
|
15
|
-
if initial_buffer.is_a?(self.class)
|
16
|
-
@current_buffer = self.class.make_frame(initial_buffer.current)
|
17
|
-
@buffer_stack = [*initial_buffer.buffer_stack[0..-2], @current_buffer]
|
18
|
-
else
|
19
|
-
@current_buffer = initial_buffer || self.class.make_frame
|
20
|
-
@buffer_stack = [@current_buffer]
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def replace(buffer)
|
25
|
-
return if self == buffer
|
26
|
-
|
27
|
-
@current_buffer = buffer.current
|
28
|
-
@buffer_stack = buffer.buffer_stack
|
29
|
-
end
|
30
|
-
|
31
|
-
def append=(arg)
|
32
|
-
@current_buffer.append = arg
|
33
|
-
end
|
34
|
-
|
35
|
-
def safe_append=(arg)
|
36
|
-
@current_buffer.safe_append = arg
|
37
|
-
end
|
38
|
-
|
39
|
-
def safe_concat(arg)
|
40
|
-
@current_buffer.safe_concat(arg)
|
41
|
-
end
|
42
|
-
|
43
|
-
def length
|
44
|
-
@current_buffer.length
|
45
|
-
end
|
46
|
-
|
47
|
-
def push(buffer = nil)
|
48
|
-
buffer ||= self.class.make_frame
|
49
|
-
@buffer_stack.push(buffer)
|
50
|
-
@current_buffer = buffer
|
51
|
-
end
|
52
|
-
|
53
|
-
def pop
|
54
|
-
@buffer_stack.pop.tap do
|
55
|
-
@current_buffer = @buffer_stack.last
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def to_s
|
60
|
-
@current_buffer
|
61
|
-
end
|
62
|
-
|
63
|
-
alias_method :current, :to_s
|
64
|
-
end
|
65
|
-
end
|