view_component 4.0.0.alpha2 → 4.0.0.alpha4
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/docs/CHANGELOG.md +28 -0
- data/lib/view_component/base.rb +63 -23
- data/lib/view_component/collection.rb +0 -8
- data/lib/view_component/component_local_config.rb +60 -0
- data/lib/view_component/config.rb +1 -9
- data/lib/view_component/engine.rb +33 -6
- data/lib/view_component/slot.rb +1 -9
- data/lib/view_component/slotable.rb +16 -6
- data/lib/view_component/template.rb +2 -1
- data/lib/view_component/translatable.rb +3 -3
- data/lib/view_component/version.rb +1 -1
- metadata +2 -3
- data/lib/view_component/capture_compatibility.rb +0 -44
- data/lib/view_component/slotable_default.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70feada9d7f9456623bfed2a6c76a9546f8fe5596f81e0f47ed7059808b1a68d
|
4
|
+
data.tar.gz: 77d8002e2a0fdb344c3647972b9051ce1c3ac3bc299e49442c8631921a6b5437
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3aeae640580d7d5c9192836fbc8ab26932a9527117438f4fa808fed36cd2c4393194fd66e5d01ddbc56bd0f0d5042b1707ee25b94760969b06a9d34a1700f85
|
7
|
+
data.tar.gz: cb4ee57d927b7b9a27436ec1d736675ee59fe2dfc7aa281e8c6a1b9be87fa517849bc3443a6057a01f1a3e1b97320e8d566681dc989c452fa8c45ff261e058c9
|
data/docs/CHANGELOG.md
CHANGED
@@ -10,6 +10,26 @@ nav_order: 6
|
|
10
10
|
|
11
11
|
## main
|
12
12
|
|
13
|
+
## 4.0.0.alpha4
|
14
|
+
|
15
|
+
* BREAKING: Remove default initializer from `ViewComponent::Base`. Previously, `ViewComponent::Base` defined a catch-all initializer that allowed components without an initializer defined to be passed arbitrary arguments.
|
16
|
+
|
17
|
+
*Joel Hawksley*
|
18
|
+
|
19
|
+
* Graduate `SlotableDefault` to be included by default.
|
20
|
+
|
21
|
+
*Joel Hawksley*
|
22
|
+
|
23
|
+
* Fix bug in `SlotableDefault` where default couldn't be overridden when content was passed as a block.
|
24
|
+
|
25
|
+
*Bill Watts*, *Joel Hawksley*
|
26
|
+
|
27
|
+
## 4.0.0.alpha3
|
28
|
+
|
29
|
+
* BREAKING: Remove dependency on `ActionView::Base`, eliminating the need for capture compatibility patch.
|
30
|
+
|
31
|
+
*Cameron Dutro*
|
32
|
+
|
13
33
|
## 4.0.0.alpha2
|
14
34
|
|
15
35
|
* Add `#current_template` accessor and `Template#path` for diagnostic usage.
|
@@ -118,6 +138,14 @@ This release makes the following breaking changes:
|
|
118
138
|
|
119
139
|
*Tiago Menegaz*, *Joel Hawksley*
|
120
140
|
|
141
|
+
* Introduce component-local config and migrate `strip_trailing_whitespace` to use it under the hood.
|
142
|
+
|
143
|
+
*Simon Fish*
|
144
|
+
|
145
|
+
* Add docs about Slack channel in Ruby Central workspace. (Join us! #oss-view-component). Email joelhawksley@github.com for an invite.
|
146
|
+
|
147
|
+
*Joel Hawksley
|
148
|
+
|
121
149
|
* Do not include internal `DocsBuilderComponent` or `YARD::MattrAccessorHandler` in published gem.
|
122
150
|
|
123
151
|
*Joel Hawksley*
|
data/lib/view_component/base.rb
CHANGED
@@ -5,20 +5,33 @@ require "active_support/configurable"
|
|
5
5
|
require "view_component/collection"
|
6
6
|
require "view_component/compile_cache"
|
7
7
|
require "view_component/compiler"
|
8
|
+
require "view_component/component_local_config"
|
8
9
|
require "view_component/config"
|
9
10
|
require "view_component/errors"
|
10
11
|
require "view_component/inline_template"
|
11
12
|
require "view_component/preview"
|
12
13
|
require "view_component/request_details"
|
13
14
|
require "view_component/slotable"
|
14
|
-
require "view_component/slotable_default"
|
15
15
|
require "view_component/template"
|
16
16
|
require "view_component/translatable"
|
17
17
|
require "view_component/with_content_helper"
|
18
18
|
require "view_component/use_helpers"
|
19
19
|
|
20
|
+
module ActionView
|
21
|
+
class OutputBuffer
|
22
|
+
def with_buffer(buf = nil)
|
23
|
+
new_buffer = buf || +""
|
24
|
+
old_buffer, @raw_buffer = @raw_buffer, new_buffer
|
25
|
+
yield
|
26
|
+
new_buffer
|
27
|
+
ensure
|
28
|
+
@raw_buffer = old_buffer
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
20
33
|
module ViewComponent
|
21
|
-
class Base
|
34
|
+
class Base
|
22
35
|
class << self
|
23
36
|
delegate(*ViewComponent::Config.defaults.keys, to: :config)
|
24
37
|
|
@@ -34,21 +47,26 @@ module ViewComponent
|
|
34
47
|
end
|
35
48
|
end
|
36
49
|
|
50
|
+
include ActionView::Helpers
|
51
|
+
include ERB::Escape
|
52
|
+
include ActiveSupport::CoreExt::ERBUtil
|
53
|
+
|
37
54
|
include ViewComponent::InlineTemplate
|
38
55
|
include ViewComponent::UseHelpers
|
39
56
|
include ViewComponent::Slotable
|
40
57
|
include ViewComponent::Translatable
|
41
58
|
include ViewComponent::WithContentHelper
|
59
|
+
include ViewComponent::ComponentLocalConfig
|
42
60
|
|
43
61
|
# For CSRF authenticity tokens in forms
|
44
62
|
delegate :form_authenticity_token, :protect_against_forgery?, :config, to: :helpers
|
45
63
|
|
64
|
+
# HTML construction methods
|
65
|
+
delegate :output_buffer, :lookup_context, :view_renderer, :view_flow, to: :helpers
|
66
|
+
|
46
67
|
# For Content Security Policy nonces
|
47
68
|
delegate :content_security_policy_nonce, to: :helpers
|
48
69
|
|
49
|
-
# Config option that strips trailing whitespace in templates before compiling them.
|
50
|
-
class_attribute :__vc_strip_trailing_whitespace, instance_accessor: false, instance_predicate: false, default: false
|
51
|
-
|
52
70
|
attr_accessor :__vc_original_view_context
|
53
71
|
attr_reader :current_template
|
54
72
|
|
@@ -62,7 +80,7 @@ module ViewComponent
|
|
62
80
|
# @param view_context [ActionView::Base] The original view context.
|
63
81
|
# @return [void]
|
64
82
|
def set_original_view_context(view_context)
|
65
|
-
|
83
|
+
# noop
|
66
84
|
end
|
67
85
|
|
68
86
|
using RequestDetails
|
@@ -81,7 +99,7 @@ module ViewComponent
|
|
81
99
|
@view_context = view_context
|
82
100
|
self.__vc_original_view_context ||= view_context
|
83
101
|
|
84
|
-
@output_buffer =
|
102
|
+
@output_buffer = view_context.output_buffer
|
85
103
|
|
86
104
|
@lookup_context ||= view_context.lookup_context
|
87
105
|
|
@@ -108,14 +126,20 @@ module ViewComponent
|
|
108
126
|
before_render
|
109
127
|
|
110
128
|
if render?
|
111
|
-
|
129
|
+
value = nil
|
130
|
+
|
131
|
+
@output_buffer.with_buffer do
|
132
|
+
rendered_template = render_template_for(@__vc_requested_details).to_s
|
112
133
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
134
|
+
# Avoid allocating new string when output_preamble and output_postamble are blank
|
135
|
+
value = if output_preamble.blank? && output_postamble.blank?
|
136
|
+
rendered_template
|
137
|
+
else
|
138
|
+
safe_output_preamble + rendered_template + safe_output_postamble
|
139
|
+
end
|
118
140
|
end
|
141
|
+
|
142
|
+
value
|
119
143
|
else
|
120
144
|
""
|
121
145
|
end
|
@@ -191,12 +215,6 @@ module ViewComponent
|
|
191
215
|
true
|
192
216
|
end
|
193
217
|
|
194
|
-
# Override the ActionView::Base initializer so that components
|
195
|
-
# do not need to define their own initializers.
|
196
|
-
# @private
|
197
|
-
def initialize(*)
|
198
|
-
end
|
199
|
-
|
200
218
|
# Re-use original view_context if we're not rendering a component.
|
201
219
|
#
|
202
220
|
# This prevents an exception when rendering a partial inside of a component that has also been rendered outside
|
@@ -207,7 +225,7 @@ module ViewComponent
|
|
207
225
|
def render(options = {}, args = {}, &block)
|
208
226
|
if options.respond_to?(:set_original_view_context)
|
209
227
|
options.set_original_view_context(self.__vc_original_view_context)
|
210
|
-
|
228
|
+
@view_context.render(options, args, &block)
|
211
229
|
else
|
212
230
|
__vc_original_view_context.render(options, args, &block)
|
213
231
|
end
|
@@ -249,7 +267,7 @@ module ViewComponent
|
|
249
267
|
raise e, <<~MESSAGE.chomp if view_context && e.is_a?(NameError) && helpers.respond_to?(method_name)
|
250
268
|
#{e.message}
|
251
269
|
|
252
|
-
You may be trying to call a method provided as a view helper. Did you mean `helpers.#{method_name}
|
270
|
+
You may be trying to call a method provided as a view helper. Did you mean `helpers.#{method_name}`?
|
253
271
|
MESSAGE
|
254
272
|
|
255
273
|
raise
|
@@ -594,16 +612,38 @@ module ViewComponent
|
|
594
612
|
# end
|
595
613
|
# ```
|
596
614
|
#
|
615
|
+
# @deprecated Use the new component-local configuration option instead.
|
616
|
+
#
|
617
|
+
# ```ruby
|
618
|
+
# class MyComponent < ViewComponent::Base
|
619
|
+
# configure_view_component do |config|
|
620
|
+
# config.strip_trailing_whitespace = true
|
621
|
+
# end
|
622
|
+
# end
|
623
|
+
# ```
|
624
|
+
#
|
597
625
|
# @param value [Boolean] Whether to strip newlines.
|
598
626
|
def strip_trailing_whitespace(value = true)
|
599
|
-
|
627
|
+
ViewComponent::Deprecation.deprecation_warning(
|
628
|
+
"strip_trailing_whitespace",
|
629
|
+
<<~DOC
|
630
|
+
Use the new component-local configuration option instead:
|
631
|
+
|
632
|
+
class #{self.class.name} < ViewComponent::Base
|
633
|
+
configure_view_component do |config|
|
634
|
+
config.strip_trailing_whitespace = #{value}
|
635
|
+
end
|
636
|
+
end
|
637
|
+
DOC
|
638
|
+
)
|
639
|
+
view_component_config.strip_trailing_whitespace = value
|
600
640
|
end
|
601
641
|
|
602
642
|
# Whether trailing whitespace will be stripped before compilation.
|
603
643
|
#
|
604
644
|
# @return [Boolean]
|
605
645
|
def strip_trailing_whitespace?
|
606
|
-
|
646
|
+
view_component_config.strip_trailing_whitespace
|
607
647
|
end
|
608
648
|
|
609
649
|
# Ensure the component initializer accepts the
|
@@ -9,15 +9,8 @@ module ViewComponent
|
|
9
9
|
|
10
10
|
delegate :size, to: :@collection
|
11
11
|
|
12
|
-
attr_accessor :__vc_original_view_context
|
13
|
-
|
14
|
-
def set_original_view_context(view_context)
|
15
|
-
self.__vc_original_view_context = view_context
|
16
|
-
end
|
17
|
-
|
18
12
|
def render_in(view_context, &block)
|
19
13
|
components.map do |component|
|
20
|
-
component.set_original_view_context(__vc_original_view_context)
|
21
14
|
component.render_in(view_context, &block)
|
22
15
|
end.join(rendered_spacer(view_context)).html_safe
|
23
16
|
end
|
@@ -67,7 +60,6 @@ module ViewComponent
|
|
67
60
|
|
68
61
|
def rendered_spacer(view_context)
|
69
62
|
if @spacer_component
|
70
|
-
@spacer_component.set_original_view_context(__vc_original_view_context)
|
71
63
|
@spacer_component.render_in(view_context)
|
72
64
|
else
|
73
65
|
""
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module ComponentLocalConfig
|
5
|
+
class Configuration
|
6
|
+
def self.defaults
|
7
|
+
ActiveSupport::Configurable::Configuration[
|
8
|
+
strip_trailing_whitespace: false
|
9
|
+
]
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(config = defaults)
|
13
|
+
@config = config
|
14
|
+
end
|
15
|
+
|
16
|
+
delegate_missing_to :@config
|
17
|
+
|
18
|
+
def inheritable_copy
|
19
|
+
self.class.new(@config.inheritable_copy)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
delegate :defaults, to: :class
|
25
|
+
end
|
26
|
+
|
27
|
+
extend ActiveSupport::Concern
|
28
|
+
|
29
|
+
included do
|
30
|
+
# :nocov:
|
31
|
+
def view_component_config
|
32
|
+
@__vc_config ||= self.class.view_component_config.inheritable_copy
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def inherited(child)
|
38
|
+
child.instance_variable_set(:@__vc_config, nil)
|
39
|
+
super
|
40
|
+
end
|
41
|
+
# :nocov:
|
42
|
+
end
|
43
|
+
|
44
|
+
class_methods do
|
45
|
+
def view_component_config
|
46
|
+
@__vc_config ||= if respond_to?(:superclass) && superclass.respond_to?(:view_component_config)
|
47
|
+
superclass.view_component_config.inheritable_copy
|
48
|
+
else
|
49
|
+
# create a new "anonymous" class that will host the compiled reader methods
|
50
|
+
ViewComponent::ComponentLocalConfig::Configuration.new
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def configure_view_component(&block)
|
55
|
+
view_component_config.instance_eval(&block)
|
56
|
+
view_component_config.compile_methods!
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -21,8 +21,7 @@ module ViewComponent
|
|
21
21
|
show_previews: Rails.env.development? || Rails.env.test?,
|
22
22
|
preview_paths: default_preview_paths,
|
23
23
|
test_controller: "ApplicationController",
|
24
|
-
default_preview_layout: nil
|
25
|
-
capture_compatibility_patch_enabled: false
|
24
|
+
default_preview_layout: nil
|
26
25
|
})
|
27
26
|
end
|
28
27
|
|
@@ -145,13 +144,6 @@ module ViewComponent
|
|
145
144
|
# previews.
|
146
145
|
# Defaults to `nil`. If this is falsy, `"component_preview"` is used.
|
147
146
|
|
148
|
-
# @!attribute capture_compatibility_patch_enabled
|
149
|
-
# @return [Boolean]
|
150
|
-
# Enables the experimental capture compatibility patch that makes ViewComponent
|
151
|
-
# compatible with forms, capture, and other built-ins.
|
152
|
-
# previews.
|
153
|
-
# Defaults to `false`.
|
154
|
-
|
155
147
|
def default_preview_paths
|
156
148
|
(default_rails_preview_paths + default_rails_engines_preview_paths).uniq
|
157
149
|
end
|
@@ -51,12 +51,6 @@ module ViewComponent
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
-
initializer "view_component.enable_capture_patch" do |app|
|
55
|
-
ActiveSupport.on_load(:view_component) do
|
56
|
-
ActionView::Base.include(ViewComponent::CaptureCompatibility) if app.config.view_component.capture_compatibility_patch_enabled
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
54
|
initializer "view_component.set_autoload_paths" do |app|
|
61
55
|
options = app.config.view_component
|
62
56
|
|
@@ -66,6 +60,39 @@ module ViewComponent
|
|
66
60
|
end
|
67
61
|
end
|
68
62
|
|
63
|
+
initializer "view_component.propshaft_support" do |_app|
|
64
|
+
ActiveSupport.on_load(:view_component) do
|
65
|
+
if defined?(Propshaft)
|
66
|
+
include Propshaft::Helper
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
config.after_initialize do |app|
|
72
|
+
ActiveSupport.on_load(:view_component) do
|
73
|
+
if defined?(Sprockets::Rails)
|
74
|
+
include Sprockets::Rails::Helper
|
75
|
+
|
76
|
+
# Copy relevant config to VC context
|
77
|
+
# See: https://github.com/rails/sprockets-rails/blob/266ec49f3c7c96018dd75f9dc4f9b62fe3f7eecf/lib/sprockets/railtie.rb#L245
|
78
|
+
self.debug_assets = app.config.assets.debug
|
79
|
+
self.digest_assets = app.config.assets.digest
|
80
|
+
self.assets_prefix = app.config.assets.prefix
|
81
|
+
self.assets_precompile = app.config.assets.precompile
|
82
|
+
|
83
|
+
self.assets_environment = app.assets
|
84
|
+
self.assets_manifest = app.assets_manifest
|
85
|
+
|
86
|
+
self.resolve_assets_with = app.config.assets.resolve_with
|
87
|
+
|
88
|
+
self.check_precompiled_asset = app.config.assets.check_precompiled_asset
|
89
|
+
self.unknown_asset_fallback = app.config.assets.unknown_asset_fallback
|
90
|
+
# Expose the app precompiled asset check to the view
|
91
|
+
self.precompiled_asset_checker = ->(logical_path) { app.asset_precompiled? logical_path }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
69
96
|
initializer "view_component.eager_load_actions" do
|
70
97
|
ActiveSupport.on_load(:after_initialize) do
|
71
98
|
ViewComponent::Base.descendants.each(&:__vc_compile) if Rails.application.config.eager_load
|
data/lib/view_component/slot.rb
CHANGED
@@ -58,15 +58,7 @@ module ViewComponent
|
|
58
58
|
if defined?(@__vc_content_block)
|
59
59
|
# render_in is faster than `parent.render`
|
60
60
|
@__vc_component_instance.render_in(view_context) do |*args|
|
61
|
-
|
62
|
-
|
63
|
-
block_context = @__vc_content_block.binding.receiver
|
64
|
-
|
65
|
-
if block_context.class < ActionView::Base
|
66
|
-
block_context.capture(*args, &@__vc_content_block)
|
67
|
-
else
|
68
|
-
@__vc_content_block.call(*args)
|
69
|
-
end
|
61
|
+
@__vc_content_block.call(*args)
|
70
62
|
end
|
71
63
|
else
|
72
64
|
@__vc_component_instance.render_in(view_context)
|
@@ -351,16 +351,26 @@ module ViewComponent
|
|
351
351
|
end
|
352
352
|
|
353
353
|
def get_slot(slot_name)
|
354
|
+
@__vc_set_slots ||= {}
|
354
355
|
content unless content_evaluated? # ensure content is loaded so slots will be defined
|
355
356
|
|
356
|
-
slot
|
357
|
-
@__vc_set_slots
|
357
|
+
# If the slot is set, return it
|
358
|
+
return @__vc_set_slots[slot_name] if @__vc_set_slots[slot_name]
|
358
359
|
|
359
|
-
|
360
|
-
|
361
|
-
|
360
|
+
# If there is a default method for the slot, call it
|
361
|
+
if (default_method = registered_slots[slot_name][:default_method])
|
362
|
+
renderable_value = send(default_method)
|
363
|
+
slot = Slot.new(self)
|
364
|
+
|
365
|
+
if renderable_value.respond_to?(:render_in)
|
366
|
+
slot.__vc_component_instance = renderable_value
|
367
|
+
else
|
368
|
+
slot.__vc_content = renderable_value
|
369
|
+
end
|
362
370
|
|
363
|
-
|
371
|
+
slot
|
372
|
+
elsif self.class.registered_slots[slot_name][:collection]
|
373
|
+
# If empty slot is a collection, return an empty array
|
364
374
|
[]
|
365
375
|
end
|
366
376
|
end
|
@@ -98,8 +98,9 @@ module ViewComponent
|
|
98
98
|
@component.silence_redefinition_of_method(call_method_name)
|
99
99
|
|
100
100
|
# rubocop:disable Style/EvalWithLocation
|
101
|
-
@component.class_eval <<~RUBY, @path, @lineno
|
101
|
+
@component.class_eval <<~RUBY, @path, @lineno - 1
|
102
102
|
def #{call_method_name}
|
103
|
+
@view_context.instance_variable_set(:@virtual_path, virtual_path)
|
103
104
|
#{compiled_source}
|
104
105
|
end
|
105
106
|
RUBY
|
@@ -93,7 +93,7 @@ module ViewComponent
|
|
93
93
|
def translate(key = nil, **options)
|
94
94
|
raise ViewComponent::TranslateCalledBeforeRenderError if view_context.nil?
|
95
95
|
|
96
|
-
return
|
96
|
+
return @view_context.translate(key, **options) unless __vc_i18n_backend
|
97
97
|
return key.map { |k| translate(k, **options) } if key.is_a?(Array)
|
98
98
|
|
99
99
|
locale = options.delete(:locale) || ::I18n.locale
|
@@ -110,13 +110,13 @@ module ViewComponent
|
|
110
110
|
|
111
111
|
# Fallback to the global translations
|
112
112
|
if translated.is_a? ::I18n::MissingTranslation
|
113
|
-
return
|
113
|
+
return @view_context.translate(key, locale: locale, **options)
|
114
114
|
end
|
115
115
|
|
116
116
|
translated = html_safe_translation(translated) if as_html
|
117
117
|
translated
|
118
118
|
else
|
119
|
-
|
119
|
+
@view_context.translate(key, locale: locale, **options)
|
120
120
|
end
|
121
121
|
end
|
122
122
|
alias_method :t, :translate
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: view_component
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.0.
|
4
|
+
version: 4.0.0.alpha4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ViewComponent Team
|
@@ -466,10 +466,10 @@ files:
|
|
466
466
|
- docs/CHANGELOG.md
|
467
467
|
- lib/view_component.rb
|
468
468
|
- lib/view_component/base.rb
|
469
|
-
- lib/view_component/capture_compatibility.rb
|
470
469
|
- lib/view_component/collection.rb
|
471
470
|
- lib/view_component/compile_cache.rb
|
472
471
|
- lib/view_component/compiler.rb
|
472
|
+
- lib/view_component/component_local_config.rb
|
473
473
|
- lib/view_component/config.rb
|
474
474
|
- lib/view_component/configurable.rb
|
475
475
|
- lib/view_component/deprecation.rb
|
@@ -481,7 +481,6 @@ files:
|
|
481
481
|
- lib/view_component/request_details.rb
|
482
482
|
- lib/view_component/slot.rb
|
483
483
|
- lib/view_component/slotable.rb
|
484
|
-
- lib/view_component/slotable_default.rb
|
485
484
|
- lib/view_component/system_test_case.rb
|
486
485
|
- lib/view_component/system_test_helpers.rb
|
487
486
|
- lib/view_component/template.rb
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ViewComponent
|
4
|
-
# CaptureCompatibility is a module that patches #capture to fix issues
|
5
|
-
# related to ViewComponent and functionality that relies on `capture`
|
6
|
-
# like forms, capture itself, turbo frames, etc.
|
7
|
-
#
|
8
|
-
# This underlying incompatibility with ViewComponent and capture is
|
9
|
-
# that several features like forms keep a reference to the primary
|
10
|
-
# `ActionView::Base` instance which has its own @output_buffer. When
|
11
|
-
# `#capture` is called on the original `ActionView::Base` instance while
|
12
|
-
# evaluating a block from a ViewComponent the @output_buffer is overridden
|
13
|
-
# in the ActionView::Base instance, and *not* the component. This results
|
14
|
-
# in a double render due to `#capture` implementation details.
|
15
|
-
#
|
16
|
-
# To resolve the issue, we override `#capture` so that we can delegate
|
17
|
-
# the `capture` logic to the ViewComponent that created the block.
|
18
|
-
module CaptureCompatibility
|
19
|
-
def self.included(base)
|
20
|
-
return if base < InstanceMethods
|
21
|
-
|
22
|
-
base.class_eval do
|
23
|
-
alias_method :original_capture, :capture
|
24
|
-
end
|
25
|
-
|
26
|
-
base.prepend(InstanceMethods)
|
27
|
-
end
|
28
|
-
|
29
|
-
module InstanceMethods
|
30
|
-
def capture(*args, &block)
|
31
|
-
# Handle blocks that originate from C code and raise, such as `&:method`
|
32
|
-
return original_capture(*args, &block) if block.source_location.nil?
|
33
|
-
|
34
|
-
block_context = block.binding.receiver
|
35
|
-
|
36
|
-
if block_context != self && block_context.class < ActionView::Base
|
37
|
-
block_context.original_capture(*args, &block)
|
38
|
-
else
|
39
|
-
original_capture(*args, &block)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module ViewComponent
|
2
|
-
module SlotableDefault
|
3
|
-
def get_slot(slot_name)
|
4
|
-
@__vc_set_slots ||= {}
|
5
|
-
|
6
|
-
return super unless !@__vc_set_slots[slot_name] && (default_method = registered_slots[slot_name][:default_method])
|
7
|
-
|
8
|
-
renderable_value = send(default_method)
|
9
|
-
slot = Slot.new(self)
|
10
|
-
|
11
|
-
if renderable_value.respond_to?(:render_in)
|
12
|
-
slot.__vc_component_instance = renderable_value
|
13
|
-
else
|
14
|
-
slot.__vc_content = renderable_value
|
15
|
-
end
|
16
|
-
|
17
|
-
slot
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|