view_component 2.60.0 → 2.62.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 +36 -0
- data/lib/view_component/base.rb +4 -18
- data/lib/view_component/compile_cache.rb +1 -2
- data/lib/view_component/compiler.rb +7 -9
- data/lib/view_component/engine.rb +0 -16
- data/lib/view_component/polymorphic_slots.rb +2 -2
- data/lib/view_component/slotable_v2.rb +2 -2
- data/lib/view_component/test_helpers.rb +1 -22
- data/lib/view_component/version.rb +1 -1
- data/lib/view_component.rb +0 -3
- metadata +2 -5
- data/lib/view_component/capybara_simple_session.rb +0 -132
- 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: e57d7d7eece678a577cf5f89f4b506fbe1026c79cc8b28d269e6984a01de29c7
|
4
|
+
data.tar.gz: e8fd167897e4bbcfaf0b4d657605acf26a5e1c6dc72e6fd5a868e0e0e76d232b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6bae85903899c93cb78e11a49082c4e6c2393605c9b3e94cca98ecff1e790a97dd7acda4c5e13b11ad4e4591384d0d30e62d86831998577531b595378f9fcb7
|
7
|
+
data.tar.gz: 814913871cc0d5b4865a6864a0585f06d6c26088cdbab888e4c4d33787f7ab2e74c9dafffd52fe726999d03b9a453186b3f495afc1c0c9da5207b5edb3a89480
|
data/docs/CHANGELOG.md
CHANGED
@@ -9,6 +9,42 @@ title: Changelog
|
|
9
9
|
|
10
10
|
## main
|
11
11
|
|
12
|
+
## 2.62.0
|
13
|
+
|
14
|
+
* Remove the experimental global output buffer feature.
|
15
|
+
* Restore functionality that used to attempt to compile templates on each call to `#render_in`.
|
16
|
+
* Un-pin `rails` `main` dependency.
|
17
|
+
|
18
|
+
*Cameron Dutro*
|
19
|
+
|
20
|
+
* Add blank space between "in" and "ViewComponent" in a deprecation warning.
|
21
|
+
|
22
|
+
*Vikram Dighe*
|
23
|
+
|
24
|
+
* Add HappyCo to list of companies using ViewComponent.
|
25
|
+
|
26
|
+
*Josh Clayton*
|
27
|
+
|
28
|
+
## 2.61.1
|
29
|
+
|
30
|
+
* 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.
|
31
|
+
|
32
|
+
*Joel Hawksley*, *Blake Williams*
|
33
|
+
|
34
|
+
* Revert change making content evaluation consistent.
|
35
|
+
|
36
|
+
*Blake Williams*
|
37
|
+
|
38
|
+
* Pin `rails` `main` dependency due to incompatibility with Global Output Buffer.
|
39
|
+
|
40
|
+
*Joel Hawksley*
|
41
|
+
|
42
|
+
## 2.61.0
|
43
|
+
|
44
|
+
* Ensure side-effects in `content` are consistently evaluated before components are rendered. This change effectively means that `content` is evaluated for every component render where `render?` returns true. As a result, code that is passed to a component via a block/content will now always be evaluated, before `#call`, which can reveal bugs in existing components.
|
45
|
+
|
46
|
+
*Blake Williams*
|
47
|
+
|
12
48
|
## 2.60.0
|
13
49
|
|
14
50
|
* Add support for `render_preview` in RSpec tests.
|
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]
|
@@ -34,6 +34,8 @@ module ViewComponent
|
|
34
34
|
component_class.superclass.compile(raise_errors: raise_errors) if should_compile_superclass?
|
35
35
|
|
36
36
|
with_lock do
|
37
|
+
CompileCache.invalidate_class!(component_class)
|
38
|
+
|
37
39
|
subclass_instance_methods = component_class.instance_methods(false)
|
38
40
|
|
39
41
|
if subclass_instance_methods.include?(:with_content) && raise_errors
|
@@ -66,8 +68,8 @@ module ViewComponent
|
|
66
68
|
# as Ruby warns when redefining a method.
|
67
69
|
method_name = call_method_name(template[:variant])
|
68
70
|
|
69
|
-
if component_class.instance_methods
|
70
|
-
component_class.send(:
|
71
|
+
if component_class.instance_methods.include?(method_name.to_sym)
|
72
|
+
component_class.send(:undef_method, method_name.to_sym)
|
71
73
|
end
|
72
74
|
|
73
75
|
# rubocop:disable Style/EvalWithLocation
|
@@ -96,18 +98,14 @@ module ViewComponent
|
|
96
98
|
end
|
97
99
|
end
|
98
100
|
|
99
|
-
def reset_render_template_for
|
100
|
-
if component_class.instance_methods(false).include?(:render_template_for)
|
101
|
-
component_class.send(:remove_method, :render_template_for)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
101
|
private
|
106
102
|
|
107
103
|
attr_reader :component_class
|
108
104
|
|
109
105
|
def define_render_template_for
|
110
|
-
|
106
|
+
if component_class.instance_methods.include?(:render_template_for)
|
107
|
+
component_class.send(:undef_method, :render_template_for)
|
108
|
+
end
|
111
109
|
|
112
110
|
variant_elsifs = variants.compact.uniq.map do |variant|
|
113
111
|
"elsif variant.to_sym == :#{variant}\n #{call_method_name(variant)}"
|
@@ -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
|
|
@@ -10,7 +10,7 @@ module ViewComponent
|
|
10
10
|
location = Kernel.caller_locations(1, 1)[0]
|
11
11
|
|
12
12
|
warn(
|
13
|
-
"warning: ViewComponent::PolymorphicSlots is now included in ViewComponent::Base by default "\
|
13
|
+
"warning: ViewComponent::PolymorphicSlots is now included in ViewComponent::Base by default " \
|
14
14
|
"and can be removed from #{location.path}:#{location.lineno}"
|
15
15
|
)
|
16
16
|
# :nocov:
|
@@ -58,7 +58,7 @@ module ViewComponent
|
|
58
58
|
|
59
59
|
define_method(setter_name) do |*args, &block|
|
60
60
|
ViewComponent::Deprecation.warn(
|
61
|
-
"polymorphic slot setters like `#{setter_name}` are deprecated and will be removed in"\
|
61
|
+
"polymorphic slot setters like `#{setter_name}` are deprecated and will be removed in " \
|
62
62
|
"ViewComponent v3.0.0.\n\nUse `with_#{setter_name}` instead."
|
63
63
|
)
|
64
64
|
|
@@ -266,8 +266,8 @@ module ViewComponent
|
|
266
266
|
def raise_if_slot_ends_with_question_mark(slot_name)
|
267
267
|
if slot_name.to_s.ends_with?("?")
|
268
268
|
raise ArgumentError.new(
|
269
|
-
"#{self} declares a slot named #{slot_name}, which ends with a question mark.\n\n"\
|
270
|
-
"This is not allowed because the ViewComponent framework already provides predicate "\
|
269
|
+
"#{self} declares a slot named #{slot_name}, which ends with a question mark.\n\n" \
|
270
|
+
"This is not allowed because the ViewComponent framework already provides predicate " \
|
271
271
|
"methods ending in `?`.\n\n" \
|
272
272
|
"To fix this issue, choose a different name."
|
273
273
|
)
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "view_component/render_preview_helper"
|
4
|
-
require "view_component/capybara_simple_session"
|
5
4
|
|
6
5
|
module ViewComponent
|
7
6
|
module TestHelpers
|
@@ -10,28 +9,8 @@ module ViewComponent
|
|
10
9
|
|
11
10
|
include Capybara::Minitest::Assertions
|
12
11
|
|
13
|
-
CapybaraSimpleSession::DSL_METHODS.each do |method|
|
14
|
-
if RUBY_VERSION >= "2.7"
|
15
|
-
class_eval <<~METHOD, __FILE__, __LINE__ + 1
|
16
|
-
def #{method}(...)
|
17
|
-
page.method("#{method}").call(...)
|
18
|
-
end
|
19
|
-
METHOD
|
20
|
-
else
|
21
|
-
define_method method do |*args, &block|
|
22
|
-
page.send method, *args, &block
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.included(mod)
|
28
|
-
Capybara::Node::Simple.send(:define_method, :to_capybara_node) do
|
29
|
-
self
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
12
|
def page
|
34
|
-
@page ||=
|
13
|
+
@page ||= Capybara::Node::Simple.new(rendered_content)
|
35
14
|
end
|
36
15
|
|
37
16
|
def refute_component_rendered
|
data/lib/view_component.rb
CHANGED
@@ -7,14 +7,11 @@ module ViewComponent
|
|
7
7
|
extend ActiveSupport::Autoload
|
8
8
|
|
9
9
|
autoload :Base
|
10
|
-
autoload :CapybaraSimpleSession
|
11
10
|
autoload :Compiler
|
12
11
|
autoload :CompileCache
|
13
12
|
autoload :ComponentError
|
14
13
|
autoload :Deprecation
|
15
|
-
autoload :GlobalOutputBuffer
|
16
14
|
autoload :Instrumentation
|
17
|
-
autoload :OutputBufferStack
|
18
15
|
autoload :Preview
|
19
16
|
autoload :PreviewTemplateError
|
20
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.62.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-07-
|
11
|
+
date: 2022-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -325,7 +325,6 @@ files:
|
|
325
325
|
- lib/rails/generators/test_unit/templates/component_test.rb.tt
|
326
326
|
- lib/view_component.rb
|
327
327
|
- lib/view_component/base.rb
|
328
|
-
- lib/view_component/capybara_simple_session.rb
|
329
328
|
- lib/view_component/collection.rb
|
330
329
|
- lib/view_component/compile_cache.rb
|
331
330
|
- lib/view_component/compiler.rb
|
@@ -335,9 +334,7 @@ files:
|
|
335
334
|
- lib/view_component/docs_builder_component.html.erb
|
336
335
|
- lib/view_component/docs_builder_component.rb
|
337
336
|
- lib/view_component/engine.rb
|
338
|
-
- lib/view_component/global_output_buffer.rb
|
339
337
|
- lib/view_component/instrumentation.rb
|
340
|
-
- lib/view_component/output_buffer_stack.rb
|
341
338
|
- lib/view_component/polymorphic_slots.rb
|
342
339
|
- lib/view_component/preview.rb
|
343
340
|
- lib/view_component/preview_template_error.rb
|
@@ -1,132 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ViewComponent
|
4
|
-
# This is a simpler version of {Capybara::Session}.
|
5
|
-
#
|
6
|
-
# It only includes {Capybara::Node::Finders}, {Capybara::Node::Matchers},
|
7
|
-
# {#within} and {#within_element}. It is useful in that it does not require a
|
8
|
-
# session, an application or a driver, but can still use Capybara's finders
|
9
|
-
# and matchers on any string that contains HTML.
|
10
|
-
class CapybaraSimpleSession
|
11
|
-
# Most of the code in this class is shamelessly stolen from the
|
12
|
-
# {Capybara::Session} class in the Capybara gem
|
13
|
-
# (https://github.com/teamcapybara/capybara/blob/e704d00879fb1d1e1a0cc01e04c101bcd8af4a68/lib/capybara/session.rb#L38).
|
14
|
-
|
15
|
-
NODE_METHODS = %i[
|
16
|
-
all
|
17
|
-
first
|
18
|
-
text
|
19
|
-
|
20
|
-
find
|
21
|
-
find_all
|
22
|
-
find_button
|
23
|
-
find_by_id
|
24
|
-
find_field
|
25
|
-
find_link
|
26
|
-
|
27
|
-
has_content?
|
28
|
-
has_text?
|
29
|
-
has_css?
|
30
|
-
has_no_content?
|
31
|
-
has_no_text?
|
32
|
-
has_no_css?
|
33
|
-
has_no_xpath?
|
34
|
-
has_xpath?
|
35
|
-
has_link?
|
36
|
-
has_no_link?
|
37
|
-
has_button?
|
38
|
-
has_no_button?
|
39
|
-
has_field?
|
40
|
-
has_no_field?
|
41
|
-
has_checked_field?
|
42
|
-
has_unchecked_field?
|
43
|
-
has_no_table?
|
44
|
-
has_table?
|
45
|
-
has_select?
|
46
|
-
has_no_select?
|
47
|
-
has_selector?
|
48
|
-
has_no_selector?
|
49
|
-
has_no_checked_field?
|
50
|
-
has_no_unchecked_field?
|
51
|
-
|
52
|
-
assert_selector
|
53
|
-
assert_no_selector
|
54
|
-
assert_all_of_selectors
|
55
|
-
assert_none_of_selectors
|
56
|
-
assert_any_of_selectors
|
57
|
-
assert_text
|
58
|
-
assert_no_text
|
59
|
-
].freeze
|
60
|
-
|
61
|
-
private_constant :NODE_METHODS
|
62
|
-
|
63
|
-
SESSION_METHODS = %i[within within_element within_fieldset within_table].freeze
|
64
|
-
|
65
|
-
private_constant :SESSION_METHODS
|
66
|
-
|
67
|
-
DSL_METHODS = (NODE_METHODS + SESSION_METHODS).freeze
|
68
|
-
|
69
|
-
# Stolen from: https://github.com/teamcapybara/capybara/blob/e704d00879fb1d1e1a0cc01e04c101bcd8af4a68/lib/capybara/session.rb#L767-L774.
|
70
|
-
NODE_METHODS.each do |method|
|
71
|
-
if RUBY_VERSION >= "2.7"
|
72
|
-
class_eval <<~METHOD, __FILE__, __LINE__ + 1
|
73
|
-
def #{method}(...)
|
74
|
-
current_scope.#{method}(...)
|
75
|
-
end
|
76
|
-
METHOD
|
77
|
-
else
|
78
|
-
define_method method do |*args, &block|
|
79
|
-
current_scope.send(method, *args, &block)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
# Initializes the receiver with the given string of HTML.
|
85
|
-
#
|
86
|
-
# @param html [String] the HTML to create the session out of
|
87
|
-
def initialize(html)
|
88
|
-
@document = Capybara::Node::Simple.new(html)
|
89
|
-
end
|
90
|
-
|
91
|
-
# (see Capybara::Session#within)
|
92
|
-
def within(*args, **kw_args)
|
93
|
-
new_scope = args.first.respond_to?(:to_capybara_node) ? args.first.to_capybara_node : find(*args, **kw_args)
|
94
|
-
begin
|
95
|
-
scopes.push(new_scope)
|
96
|
-
yield if block_given?
|
97
|
-
ensure
|
98
|
-
scopes.pop
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
# (see Capybara::Session#within_element)
|
103
|
-
alias_method :within_element, :within
|
104
|
-
|
105
|
-
# (see Capybara::Session#within_fieldset)
|
106
|
-
def within_fieldset(locator, &block)
|
107
|
-
within(:fieldset, locator, &block)
|
108
|
-
end
|
109
|
-
|
110
|
-
# (see Capybara::Session#within_table)
|
111
|
-
def within_table(locator, &block)
|
112
|
-
within(:table, locator, &block)
|
113
|
-
end
|
114
|
-
|
115
|
-
# (see Capybara::Node::Element#native)
|
116
|
-
def native
|
117
|
-
current_scope.native
|
118
|
-
end
|
119
|
-
|
120
|
-
private
|
121
|
-
|
122
|
-
attr_reader :document
|
123
|
-
|
124
|
-
def scopes
|
125
|
-
@scopes ||= [nil]
|
126
|
-
end
|
127
|
-
|
128
|
-
def current_scope
|
129
|
-
scopes.last.presence || document
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
@@ -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
|