view_component 2.49.1 → 3.23.2
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/LICENSE.txt +1 -1
- data/app/assets/vendor/prism.css +3 -195
- data/app/assets/vendor/prism.min.js +11 -11
- data/app/controllers/concerns/view_component/preview_actions.rb +108 -0
- data/app/controllers/view_components_controller.rb +1 -87
- data/app/controllers/view_components_system_test_controller.rb +30 -0
- data/app/helpers/preview_helper.rb +30 -12
- data/app/views/view_components/_preview_source.html.erb +3 -3
- data/app/views/view_components/preview.html.erb +2 -2
- data/docs/CHANGELOG.md +1653 -24
- data/lib/rails/generators/abstract_generator.rb +16 -10
- data/lib/rails/generators/component/component_generator.rb +8 -4
- data/lib/rails/generators/component/templates/component.rb.tt +3 -2
- data/lib/rails/generators/erb/component_generator.rb +1 -1
- data/lib/rails/generators/locale/component_generator.rb +4 -4
- data/lib/rails/generators/preview/component_generator.rb +17 -3
- data/lib/rails/generators/preview/templates/component_preview.rb.tt +5 -1
- data/lib/rails/generators/rspec/component_generator.rb +15 -3
- data/lib/rails/generators/rspec/templates/component_spec.rb.tt +3 -1
- data/lib/rails/generators/stimulus/component_generator.rb +8 -3
- data/lib/rails/generators/stimulus/templates/component_controller.ts.tt +9 -0
- data/lib/rails/generators/test_unit/templates/component_test.rb.tt +3 -1
- data/lib/view_component/base.rb +352 -196
- data/lib/view_component/capture_compatibility.rb +44 -0
- data/lib/view_component/collection.rb +28 -9
- data/lib/view_component/compiler.rb +162 -193
- data/lib/view_component/config.rb +225 -0
- data/lib/view_component/configurable.rb +17 -0
- data/lib/view_component/deprecation.rb +8 -0
- data/lib/view_component/engine.rb +74 -47
- data/lib/view_component/errors.rb +240 -0
- data/lib/view_component/inline_template.rb +55 -0
- data/lib/view_component/instrumentation.rb +10 -2
- data/lib/view_component/preview.rb +21 -19
- data/lib/view_component/rails/tasks/view_component.rake +11 -2
- data/lib/view_component/render_component_helper.rb +1 -0
- data/lib/view_component/render_component_to_string_helper.rb +1 -1
- data/lib/view_component/render_to_string_monkey_patch.rb +1 -1
- data/lib/view_component/rendering_component_helper.rb +1 -1
- data/lib/view_component/rendering_monkey_patch.rb +1 -1
- data/lib/view_component/slot.rb +119 -1
- data/lib/view_component/slotable.rb +393 -96
- data/lib/view_component/slotable_default.rb +20 -0
- data/lib/view_component/system_test_case.rb +13 -0
- data/lib/view_component/system_test_helpers.rb +27 -0
- data/lib/view_component/template.rb +134 -0
- data/lib/view_component/test_helpers.rb +208 -47
- data/lib/view_component/translatable.rb +51 -33
- data/lib/view_component/use_helpers.rb +42 -0
- data/lib/view_component/version.rb +5 -4
- data/lib/view_component/with_content_helper.rb +3 -8
- data/lib/view_component.rb +7 -12
- metadata +339 -57
- data/lib/rails/generators/component/USAGE +0 -13
- data/lib/view_component/content_areas.rb +0 -57
- data/lib/view_component/polymorphic_slots.rb +0 -73
- data/lib/view_component/preview_template_error.rb +0 -6
- data/lib/view_component/previewable.rb +0 -62
- data/lib/view_component/slot_v2.rb +0 -104
- data/lib/view_component/slotable_v2.rb +0 -307
- data/lib/view_component/template_error.rb +0 -9
- data/lib/yard/mattr_accessor_handler.rb +0 -19
@@ -0,0 +1,44 @@
|
|
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
|
@@ -7,13 +7,19 @@ module ViewComponent
|
|
7
7
|
include Enumerable
|
8
8
|
attr_reader :component
|
9
9
|
|
10
|
-
delegate :format, to: :component
|
11
10
|
delegate :size, to: :@collection
|
12
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
|
+
|
13
18
|
def render_in(view_context, &block)
|
14
19
|
components.map do |component|
|
20
|
+
component.set_original_view_context(__vc_original_view_context)
|
15
21
|
component.render_in(view_context, &block)
|
16
|
-
end.join.html_safe
|
22
|
+
end.join(rendered_spacer(view_context)).html_safe
|
17
23
|
end
|
18
24
|
|
19
25
|
def components
|
@@ -34,11 +40,18 @@ module ViewComponent
|
|
34
40
|
components.each(&block)
|
35
41
|
end
|
36
42
|
|
43
|
+
# Rails expects us to define `format` on all renderables,
|
44
|
+
# but we do not know the `format` of a ViewComponent until runtime.
|
45
|
+
def format
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
|
37
49
|
private
|
38
50
|
|
39
|
-
def initialize(component, object, **options)
|
51
|
+
def initialize(component, object, spacer_component, **options)
|
40
52
|
@component = component
|
41
53
|
@collection = collection_variable(object || [])
|
54
|
+
@spacer_component = spacer_component
|
42
55
|
@options = options
|
43
56
|
end
|
44
57
|
|
@@ -46,19 +59,25 @@ module ViewComponent
|
|
46
59
|
if object.respond_to?(:to_ary)
|
47
60
|
object.to_ary
|
48
61
|
else
|
49
|
-
raise
|
50
|
-
"The value of the first argument passed to `with_collection` isn't a valid collection. " \
|
51
|
-
"Make sure it responds to `to_ary`."
|
52
|
-
)
|
62
|
+
raise InvalidCollectionArgumentError
|
53
63
|
end
|
54
64
|
end
|
55
65
|
|
56
66
|
def component_options(item, iterator)
|
57
|
-
item_options = {
|
58
|
-
item_options[component.collection_counter_parameter] = iterator.index
|
67
|
+
item_options = {component.collection_parameter => item}
|
68
|
+
item_options[component.collection_counter_parameter] = iterator.index if component.counter_argument_present?
|
59
69
|
item_options[component.collection_iteration_parameter] = iterator.dup if component.iteration_argument_present?
|
60
70
|
|
61
71
|
@options.merge(item_options)
|
62
72
|
end
|
73
|
+
|
74
|
+
def rendered_spacer(view_context)
|
75
|
+
if @spacer_component
|
76
|
+
@spacer_component.set_original_view_context(__vc_original_view_context)
|
77
|
+
@spacer_component.render_in(view_context)
|
78
|
+
else
|
79
|
+
""
|
80
|
+
end
|
81
|
+
end
|
63
82
|
end
|
64
83
|
end
|
@@ -1,260 +1,229 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "concurrent-ruby"
|
4
|
+
|
3
5
|
module ViewComponent
|
4
6
|
class Compiler
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
# Compiler mode. Can be either:
|
9
|
-
# * development (a blocking mode which ensures thread safety when redefining the `call` method for components,
|
7
|
+
# Compiler development mode. Can be either:
|
8
|
+
# * true (a blocking mode which ensures thread safety when redefining the `call` method for components,
|
10
9
|
# default in Rails development and test mode)
|
11
|
-
# *
|
12
|
-
|
13
|
-
PRODUCTION_MODE = :production
|
10
|
+
# * false(a non-blocking mode, default in Rails production mode)
|
11
|
+
class_attribute :development_mode, default: false
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
@component_class = component_class
|
19
|
-
@__vc_compiler_lock = Monitor.new
|
13
|
+
def initialize(component)
|
14
|
+
@component = component
|
15
|
+
@lock = Mutex.new
|
20
16
|
end
|
21
17
|
|
22
18
|
def compiled?
|
23
|
-
CompileCache.compiled?(
|
19
|
+
CompileCache.compiled?(@component)
|
24
20
|
end
|
25
21
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
22
|
+
def compile(raise_errors: false, force: false)
|
23
|
+
return if compiled? && !force
|
24
|
+
return if @component == ViewComponent::Base
|
29
25
|
|
30
|
-
|
31
|
-
|
26
|
+
@lock.synchronize do
|
27
|
+
# this check is duplicated so that concurrent compile calls can still
|
28
|
+
# early exit
|
29
|
+
return if compiled? && !force
|
32
30
|
|
33
|
-
|
34
|
-
CompileCache.invalidate_class!(component_class)
|
31
|
+
gather_templates
|
35
32
|
|
36
|
-
|
37
|
-
|
38
|
-
if subclass_instance_methods.include?(:with_content) && raise_errors
|
39
|
-
raise ViewComponent::ComponentError.new(
|
40
|
-
"#{component_class} implements a reserved method, `#with_content`.\n\n" \
|
41
|
-
"To fix this issue, change the name of the method."
|
42
|
-
)
|
33
|
+
if self.class.development_mode && @templates.any?(&:requires_compiled_superclass?)
|
34
|
+
@component.superclass.compile(raise_errors: raise_errors)
|
43
35
|
end
|
44
36
|
|
45
37
|
if template_errors.present?
|
46
|
-
raise
|
38
|
+
raise TemplateError.new(template_errors) if raise_errors
|
47
39
|
|
40
|
+
# this return is load bearing, and prevents the component from being considered "compiled?"
|
48
41
|
return false
|
49
42
|
end
|
50
43
|
|
51
|
-
if subclass_instance_methods.include?(:before_render_check)
|
52
|
-
ActiveSupport::Deprecation.warn(
|
53
|
-
"`#before_render_check` will be removed in v3.0.0.\n\n" \
|
54
|
-
"To fix this issue, use `#before_render` instead."
|
55
|
-
)
|
56
|
-
end
|
57
|
-
|
58
44
|
if raise_errors
|
59
|
-
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
templates.each do |template|
|
64
|
-
# Remove existing compiled template methods,
|
65
|
-
# as Ruby warns when redefining a method.
|
66
|
-
method_name = call_method_name(template[:variant])
|
67
|
-
|
68
|
-
if component_class.instance_methods.include?(method_name.to_sym)
|
69
|
-
component_class.send(:undef_method, method_name.to_sym)
|
70
|
-
end
|
71
|
-
|
72
|
-
component_class.class_eval <<-RUBY, template[:path], -1
|
73
|
-
def #{method_name}
|
74
|
-
@output_buffer = ActionView::OutputBuffer.new
|
75
|
-
#{compiled_template(template[:path])}
|
76
|
-
end
|
77
|
-
RUBY
|
45
|
+
@component.validate_initialization_parameters!
|
46
|
+
@component.validate_collection_parameter!
|
78
47
|
end
|
79
48
|
|
80
49
|
define_render_template_for
|
81
50
|
|
82
|
-
|
83
|
-
|
84
|
-
CompileCache.register(component_class)
|
85
|
-
end
|
86
|
-
end
|
51
|
+
@component.register_default_slots
|
52
|
+
@component.build_i18n_backend
|
87
53
|
|
88
|
-
|
89
|
-
if development?
|
90
|
-
__vc_compiler_lock.synchronize(&block)
|
91
|
-
else
|
92
|
-
block.call
|
54
|
+
CompileCache.register(@component)
|
93
55
|
end
|
94
56
|
end
|
95
57
|
|
96
58
|
private
|
97
59
|
|
98
|
-
attr_reader :
|
60
|
+
attr_reader :templates
|
99
61
|
|
100
62
|
def define_render_template_for
|
101
|
-
|
102
|
-
|
63
|
+
@templates.each do |template|
|
64
|
+
template.compile_to_component
|
103
65
|
end
|
104
66
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
if variant.nil?
|
111
|
-
call
|
112
|
-
#{variant_elsifs}
|
67
|
+
method_body =
|
68
|
+
if @templates.one?
|
69
|
+
@templates.first.safe_method_name_call
|
70
|
+
elsif (template = @templates.find(&:inline?))
|
71
|
+
template.safe_method_name_call
|
113
72
|
else
|
114
|
-
|
115
|
-
|
116
|
-
|
73
|
+
branches = []
|
74
|
+
|
75
|
+
@templates.each do |template|
|
76
|
+
conditional =
|
77
|
+
if template.inline_call?
|
78
|
+
"variant&.to_sym == #{template.variant.inspect}"
|
79
|
+
else
|
80
|
+
[
|
81
|
+
template.default_format? ? "(format == #{ViewComponent::Base::VC_INTERNAL_DEFAULT_FORMAT.inspect} || format.nil?)" : "format == #{template.format.inspect}",
|
82
|
+
template.variant.nil? ? "variant.nil?" : "variant&.to_sym == #{template.variant.inspect}"
|
83
|
+
].join(" && ")
|
84
|
+
end
|
85
|
+
|
86
|
+
branches << [conditional, template.safe_method_name_call]
|
87
|
+
end
|
117
88
|
|
118
|
-
|
119
|
-
|
120
|
-
def render_template_for(variant = nil)
|
121
|
-
self.class.compiler.with_lock do
|
122
|
-
#{body}
|
89
|
+
out = branches.each_with_object(+"") do |(conditional, branch_body), memo|
|
90
|
+
memo << "#{(!memo.present?) ? "if" : "elsif"} #{conditional}\n #{branch_body}\n"
|
123
91
|
end
|
92
|
+
out << "else\n #{templates.find { _1.variant.nil? && _1.default_format? }.safe_method_name_call}\nend"
|
124
93
|
end
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
end
|
131
|
-
RUBY
|
94
|
+
|
95
|
+
@component.silence_redefinition_of_method(:render_template_for)
|
96
|
+
@component.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
97
|
+
def render_template_for(variant = nil, format = nil)
|
98
|
+
#{method_body}
|
132
99
|
end
|
100
|
+
RUBY
|
133
101
|
end
|
134
102
|
|
135
103
|
def template_errors
|
136
|
-
@
|
137
|
-
|
138
|
-
errors = []
|
104
|
+
@_template_errors ||= begin
|
105
|
+
errors = []
|
139
106
|
|
140
|
-
|
141
|
-
errors << "Couldn't find a template file or inline render method for #{component_class}."
|
142
|
-
end
|
107
|
+
errors << "Couldn't find a template file or inline render method for #{@component}." if @templates.empty?
|
143
108
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
map { |variant, grouped| variant if grouped.length > 1 }.
|
154
|
-
compact.
|
155
|
-
sort
|
156
|
-
|
157
|
-
unless invalid_variants.empty?
|
158
|
-
errors <<
|
159
|
-
"More than one template found for #{'variant'.pluralize(invalid_variants.count)} " \
|
160
|
-
"#{invalid_variants.map { |v| "'#{v}'" }.to_sentence} in #{component_class}. " \
|
161
|
-
"There can only be one template file per variant."
|
162
|
-
end
|
109
|
+
# We currently allow components to have both an inline call method and a template for a variant, with the
|
110
|
+
# inline call method overriding the template. We should aim to change this in v4 to instead
|
111
|
+
# raise an error.
|
112
|
+
@templates.reject(&:inline_call?)
|
113
|
+
.map { |template| [template.variant, template.format] }
|
114
|
+
.tally
|
115
|
+
.select { |_, count| count > 1 }
|
116
|
+
.each do |tally|
|
117
|
+
variant, this_format = tally.first
|
163
118
|
|
164
|
-
|
165
|
-
errors <<
|
166
|
-
"Template file and inline render method found for #{component_class}. " \
|
167
|
-
"There can only be a template file or inline render method per component."
|
168
|
-
end
|
119
|
+
variant_string = " for variant `#{variant}`" if variant.present?
|
169
120
|
|
170
|
-
|
171
|
-
|
121
|
+
errors << "More than one #{this_format.upcase} template found#{variant_string} for #{@component}. "
|
122
|
+
end
|
172
123
|
|
173
|
-
|
174
|
-
|
124
|
+
default_template_types = @templates.each_with_object(Set.new) do |template, memo|
|
125
|
+
next if template.variant
|
175
126
|
|
176
|
-
|
177
|
-
|
178
|
-
"found for #{'variant'.pluralize(count)} " \
|
179
|
-
"#{duplicate_template_file_and_inline_variant_calls.map { |v| "'#{v}'" }.to_sentence} " \
|
180
|
-
"in #{component_class}. " \
|
181
|
-
"There can only be a template file or inline render method per variant."
|
182
|
-
end
|
127
|
+
memo << :template_file if !template.inline_call?
|
128
|
+
memo << :inline_render if template.inline_call? && template.defined_on_self?
|
183
129
|
|
184
|
-
|
130
|
+
memo
|
185
131
|
end
|
186
|
-
end
|
187
132
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
133
|
+
if default_template_types.length > 1
|
134
|
+
errors <<
|
135
|
+
"Template file and inline render method found for #{@component}. " \
|
136
|
+
"There can only be a template file or inline render method per component."
|
137
|
+
end
|
192
138
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
139
|
+
# If a template has inline calls, they can conflict with template files the component may use
|
140
|
+
# to render. This attempts to catch and raise that issue before run time. For example,
|
141
|
+
# `def render_mobile` would conflict with a sidecar template of `component.html+mobile.erb`
|
142
|
+
duplicate_template_file_and_inline_call_variants =
|
143
|
+
@templates.reject(&:inline_call?).map(&:variant) &
|
144
|
+
@templates.select { _1.inline_call? && _1.defined_on_self? }.map(&:variant)
|
145
|
+
|
146
|
+
unless duplicate_template_file_and_inline_call_variants.empty?
|
147
|
+
count = duplicate_template_file_and_inline_call_variants.count
|
148
|
+
|
149
|
+
errors <<
|
150
|
+
"Template #{"file".pluralize(count)} and inline render #{"method".pluralize(count)} " \
|
151
|
+
"found for #{"variant".pluralize(count)} " \
|
152
|
+
"#{duplicate_template_file_and_inline_call_variants.map { |v| "'#{v}'" }.to_sentence} " \
|
153
|
+
"in #{@component}. There can only be a template file or inline render method per variant."
|
201
154
|
end
|
202
|
-
end
|
203
155
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
view_component_ancestors =
|
210
|
-
(
|
211
|
-
component_class.ancestors.take_while { |ancestor| ancestor != ViewComponent::Base } -
|
212
|
-
component_class.included_modules
|
213
|
-
)
|
156
|
+
@templates.select(&:variant).each_with_object(Hash.new { |h, k| h[k] = Set.new }) do |template, memo|
|
157
|
+
memo[template.normalized_variant_name] << template.variant
|
158
|
+
memo
|
159
|
+
end.each do |_, variant_names|
|
160
|
+
next unless variant_names.length > 1
|
214
161
|
|
215
|
-
|
162
|
+
errors << "Colliding templates #{variant_names.sort.map { |v| "'#{v}'" }.to_sentence} found in #{@component}."
|
216
163
|
end
|
217
|
-
end
|
218
164
|
|
219
|
-
|
220
|
-
|
165
|
+
errors
|
166
|
+
end
|
221
167
|
end
|
222
168
|
|
223
|
-
def
|
224
|
-
@
|
225
|
-
|
226
|
-
|
227
|
-
|
169
|
+
def gather_templates
|
170
|
+
@templates ||=
|
171
|
+
begin
|
172
|
+
templates = @component.sidecar_files(
|
173
|
+
ActionView::Template.template_handler_extensions
|
174
|
+
).map do |path|
|
175
|
+
# Extract format and variant from template filename
|
176
|
+
this_format, variant =
|
177
|
+
File
|
178
|
+
.basename(path) # "variants_component.html+mini.watch.erb"
|
179
|
+
.split(".")[1..-2] # ["html+mini", "watch"]
|
180
|
+
.join(".") # "html+mini.watch"
|
181
|
+
.split("+") # ["html", "mini.watch"]
|
182
|
+
.map(&:to_sym) # [:html, :"mini.watch"]
|
183
|
+
|
184
|
+
out = Template.new(
|
185
|
+
component: @component,
|
186
|
+
type: :file,
|
187
|
+
path: path,
|
188
|
+
lineno: 0,
|
189
|
+
extension: path.split(".").last,
|
190
|
+
this_format: this_format.to_s.split(".").last&.to_sym, # strip locale from this_format, see #2113
|
191
|
+
variant: variant
|
192
|
+
)
|
228
193
|
|
229
|
-
|
230
|
-
|
231
|
-
variant_call.to_s.sub("call_", "").to_sym
|
232
|
-
end
|
233
|
-
end
|
194
|
+
out
|
195
|
+
end
|
234
196
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
197
|
+
component_instance_methods_on_self = @component.instance_methods(false)
|
198
|
+
|
199
|
+
(
|
200
|
+
@component.ancestors.take_while { |ancestor| ancestor != ViewComponent::Base } - @component.included_modules
|
201
|
+
).flat_map { |ancestor| ancestor.instance_methods(false).grep(/^call(_|$)/) }
|
202
|
+
.uniq
|
203
|
+
.each do |method_name|
|
204
|
+
templates << Template.new(
|
205
|
+
component: @component,
|
206
|
+
type: :inline_call,
|
207
|
+
this_format: ViewComponent::Base::VC_INTERNAL_DEFAULT_FORMAT,
|
208
|
+
variant: method_name.to_s.include?("call_") ? method_name.to_s.sub("call_", "").to_sym : nil,
|
209
|
+
method_name: method_name,
|
210
|
+
defined_on_self: component_instance_methods_on_self.include?(method_name)
|
211
|
+
)
|
212
|
+
end
|
213
|
+
|
214
|
+
if @component.inline_template.present?
|
215
|
+
templates << Template.new(
|
216
|
+
component: @component,
|
217
|
+
type: :inline,
|
218
|
+
path: @component.inline_template.path,
|
219
|
+
lineno: @component.inline_template.lineno,
|
220
|
+
source: @component.inline_template.source.dup,
|
221
|
+
extension: @component.inline_template.language
|
222
|
+
)
|
223
|
+
end
|
251
224
|
|
252
|
-
|
253
|
-
|
254
|
-
"call_#{variant}"
|
255
|
-
else
|
256
|
-
"call"
|
257
|
-
end
|
225
|
+
templates
|
226
|
+
end
|
258
227
|
end
|
259
228
|
end
|
260
229
|
end
|