view_component 2.57.1 → 2.58.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/app/controllers/concerns/view_component/preview_actions.rb +7 -4
- data/app/helpers/preview_helper.rb +3 -3
- data/docs/CHANGELOG.md +47 -0
- data/lib/rails/generators/abstract_generator.rb +4 -4
- data/lib/view_component/base.rb +65 -19
- data/lib/view_component/collection.rb +3 -3
- data/lib/view_component/compiler.rb +23 -9
- data/lib/view_component/content_areas.rb +1 -1
- data/lib/view_component/docs_builder_component.rb +1 -1
- data/lib/view_component/engine.rb +6 -5
- data/lib/view_component/global_output_buffer.rb +4 -3
- data/lib/view_component/output_buffer_stack.rb +0 -2
- data/lib/view_component/polymorphic_slots.rb +17 -2
- data/lib/view_component/preview.rb +8 -6
- 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/slotable.rb +5 -6
- data/lib/view_component/slotable_v2.rb +7 -9
- data/lib/view_component/test_helpers.rb +3 -0
- data/lib/view_component/translatable.rb +9 -10
- data/lib/view_component/version.rb +2 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73dd7bae94ee1c5a5886e248924ccfea872df61e783e713c0744390d6729d128
|
4
|
+
data.tar.gz: e70c67571e32098ee5997b7912d07e65d427e265766c5caa398bcd47d06d3e55
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '080f91f8f3f6aa9e0db95a4b533643c627be1e31fe8fcd32cea979556e52a351f956a9b01000f0a4654039f2588d88fa6680107f5b94c1103fa4a5c0190953f3'
|
7
|
+
data.tar.gz: 7c4e322ca388053c13ad36ad8d79e706aede23d5a2e25d15cdadb2e2e8c6776c95a5981c5588134061534037fd89a11c859fe74110418072378ee4b14e10b8d6
|
@@ -37,21 +37,24 @@ module ViewComponent
|
|
37
37
|
opts = {}
|
38
38
|
opts[:layout] = layout if layout.present? || layout == false
|
39
39
|
opts[:locals] = locals if locals.present?
|
40
|
-
render "view_components/preview", opts
|
40
|
+
render "view_components/preview", opts
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
44
|
private
|
45
45
|
|
46
|
-
|
46
|
+
# :doc:
|
47
|
+
def default_preview_layout
|
47
48
|
ViewComponent::Base.default_preview_layout
|
48
49
|
end
|
49
50
|
|
50
|
-
|
51
|
+
# :doc:
|
52
|
+
def show_previews?
|
51
53
|
ViewComponent::Base.show_previews
|
52
54
|
end
|
53
55
|
|
54
|
-
|
56
|
+
# :doc:
|
57
|
+
def find_preview
|
55
58
|
candidates = []
|
56
59
|
params[:path].to_s.scan(%r{/|$}) { candidates << $` }
|
57
60
|
preview = candidates.detect { |candidate| ViewComponent::Preview.exists?(candidate) }
|
@@ -7,14 +7,14 @@ module PreviewHelper
|
|
7
7
|
def preview_source
|
8
8
|
return if @render_args.nil?
|
9
9
|
|
10
|
-
render "preview_source"
|
10
|
+
render "preview_source"
|
11
11
|
end
|
12
12
|
|
13
13
|
def find_template_data(lookup_context:, template_identifier:)
|
14
14
|
template = lookup_context.find_template(template_identifier)
|
15
15
|
|
16
16
|
if Rails.version.to_f >= 6.1 || template.source.present?
|
17
|
-
|
17
|
+
{
|
18
18
|
source: template.source,
|
19
19
|
prism_language_name: prism_language_name_by_template(template: template)
|
20
20
|
}
|
@@ -40,7 +40,7 @@ module PreviewHelper
|
|
40
40
|
template_source = File.read(template_file_path)
|
41
41
|
prism_language_name = prism_language_name_by_template_path(template_file_path: template_file_path)
|
42
42
|
|
43
|
-
|
43
|
+
{
|
44
44
|
source: template_source,
|
45
45
|
prism_language_name: prism_language_name
|
46
46
|
}
|
data/docs/CHANGELOG.md
CHANGED
@@ -9,6 +9,53 @@ title: Changelog
|
|
9
9
|
|
10
10
|
## main
|
11
11
|
|
12
|
+
## 2.58.0
|
13
|
+
|
14
|
+
* Switch to `standardrb`.
|
15
|
+
|
16
|
+
*Joel Hawksley*
|
17
|
+
|
18
|
+
* Add BootrAils article to resources.
|
19
|
+
|
20
|
+
*Joel Hawksley*
|
21
|
+
|
22
|
+
* Add @boardfish and @spone as maintainers.
|
23
|
+
|
24
|
+
*Joel Hawksley*, *Cameron Dutro*, *Blake Williams*
|
25
|
+
|
26
|
+
* Re-compile updated, inherited templates when class caching is disabled.
|
27
|
+
|
28
|
+
*Patrick Arnett*
|
29
|
+
|
30
|
+
* Add the latest version to the docs index.
|
31
|
+
* Improve the docs: add the versions various features were introduced in.
|
32
|
+
|
33
|
+
*Hans Lemuet*
|
34
|
+
|
35
|
+
* Update docs to reflect lack of block content support in controllers.
|
36
|
+
|
37
|
+
*Joel Hawksley*
|
38
|
+
|
39
|
+
* Prevent adding duplicates to `autoload_paths`.
|
40
|
+
|
41
|
+
*Thomas Hutterer*
|
42
|
+
|
43
|
+
* Add FreeAgent to list of companies using ViewComponent.
|
44
|
+
|
45
|
+
*Simon Fish*
|
46
|
+
|
47
|
+
* Include polymorphic slots in `ViewComponent::Base` by default.
|
48
|
+
|
49
|
+
*Cameron Dutro*
|
50
|
+
|
51
|
+
* Add per-component config option for stripping newlines from templates before compilation.
|
52
|
+
|
53
|
+
*Cameron Dutro*
|
54
|
+
|
55
|
+
* Add link to article by Matouš Borák.
|
56
|
+
|
57
|
+
*Joel Hawksley*
|
58
|
+
|
12
59
|
## 2.57.1
|
13
60
|
|
14
61
|
* Fix issue causing `NoMethodError`s when calling helper methods from components rendered as part of a collection.
|
@@ -36,10 +36,10 @@ module ViewComponent
|
|
36
36
|
|
37
37
|
def stimulus_controller
|
38
38
|
if options["stimulus"]
|
39
|
-
File.join(destination_directory, destination_file_name)
|
40
|
-
sub("#{component_path}/", "")
|
41
|
-
|
42
|
-
gsub("/", "--")
|
39
|
+
File.join(destination_directory, destination_file_name)
|
40
|
+
.sub("#{component_path}/", "")
|
41
|
+
.tr("_", "-")
|
42
|
+
.gsub("/", "--")
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
data/lib/view_component/base.rb
CHANGED
@@ -16,6 +16,7 @@ module ViewComponent
|
|
16
16
|
class Base < ActionView::Base
|
17
17
|
include ActiveSupport::Configurable
|
18
18
|
include ViewComponent::ContentAreas
|
19
|
+
include ViewComponent::PolymorphicSlots
|
19
20
|
include ViewComponent::Previewable
|
20
21
|
include ViewComponent::SlotableV2
|
21
22
|
include ViewComponent::Translatable
|
@@ -31,6 +32,10 @@ module ViewComponent
|
|
31
32
|
class_attribute :content_areas
|
32
33
|
self.content_areas = [] # class_attribute:default doesn't work until Rails 5.2
|
33
34
|
|
35
|
+
# Config option that strips trailing whitespace in templates before compiling them.
|
36
|
+
class_attribute :__vc_strip_trailing_whitespace, instance_accessor: false, instance_predicate: false
|
37
|
+
self.__vc_strip_trailing_whitespace = false # class_attribute:default doesn't work until Rails 5.2
|
38
|
+
|
34
39
|
attr_accessor :__vc_original_view_context
|
35
40
|
|
36
41
|
# Components render in their own view context. Helpers and other functionality
|
@@ -135,8 +140,10 @@ module ViewComponent
|
|
135
140
|
# Subclass components that call `super` inside their template code will cause a
|
136
141
|
# double render if they emit the result:
|
137
142
|
#
|
138
|
-
#
|
139
|
-
#
|
143
|
+
# ```erb
|
144
|
+
# <%= super %> # double-renders
|
145
|
+
# <% super %> # does not double-render
|
146
|
+
# ```
|
140
147
|
#
|
141
148
|
# Calls `super`, returning `nil` to avoid rendering the result twice.
|
142
149
|
def render_parent
|
@@ -187,7 +194,8 @@ module ViewComponent
|
|
187
194
|
end
|
188
195
|
|
189
196
|
# @private
|
190
|
-
def initialize(*)
|
197
|
+
def initialize(*)
|
198
|
+
end
|
191
199
|
|
192
200
|
# Re-use original view_context if we're not rendering a component.
|
193
201
|
#
|
@@ -315,7 +323,9 @@ module ViewComponent
|
|
315
323
|
|
316
324
|
# Set the controller used for testing components:
|
317
325
|
#
|
318
|
-
#
|
326
|
+
# ```ruby
|
327
|
+
# config.view_component.test_controller = "MyTestController"
|
328
|
+
# ```
|
319
329
|
#
|
320
330
|
# Defaults to ApplicationController. Can also be configured on a per-test
|
321
331
|
# basis using `with_controller_class`.
|
@@ -325,13 +335,17 @@ module ViewComponent
|
|
325
335
|
|
326
336
|
# Set if render monkey patches should be included or not in Rails <6.1:
|
327
337
|
#
|
328
|
-
#
|
338
|
+
# ```ruby
|
339
|
+
# config.view_component.render_monkey_patch_enabled = false
|
340
|
+
# ```
|
329
341
|
#
|
330
342
|
mattr_accessor :render_monkey_patch_enabled, instance_writer: false, default: true
|
331
343
|
|
332
344
|
# Path for component files
|
333
345
|
#
|
334
|
-
#
|
346
|
+
# ```ruby
|
347
|
+
# config.view_component.view_component_path = "app/my_components"
|
348
|
+
# ```
|
335
349
|
#
|
336
350
|
# Defaults to `app/components`.
|
337
351
|
#
|
@@ -339,7 +353,9 @@ module ViewComponent
|
|
339
353
|
|
340
354
|
# Parent class for generated components
|
341
355
|
#
|
342
|
-
#
|
356
|
+
# ```ruby
|
357
|
+
# config.view_component.component_parent_class = "MyBaseComponent"
|
358
|
+
# ```
|
343
359
|
#
|
344
360
|
# Defaults to nil. If this is falsy, generators will use
|
345
361
|
# "ApplicationComponent" if defined, "ViewComponent::Base" otherwise.
|
@@ -355,25 +371,33 @@ module ViewComponent
|
|
355
371
|
#
|
356
372
|
# Always generate a component with a sidecar directory:
|
357
373
|
#
|
358
|
-
#
|
374
|
+
# ```ruby
|
375
|
+
# config.view_component.generate.sidecar = true
|
376
|
+
# ```
|
359
377
|
#
|
360
378
|
# #### #stimulus_controller
|
361
379
|
#
|
362
380
|
# Always generate a Stimulus controller alongside the component:
|
363
381
|
#
|
364
|
-
#
|
382
|
+
# ```ruby
|
383
|
+
# config.view_component.generate.stimulus_controller = true
|
384
|
+
# ```
|
365
385
|
#
|
366
386
|
# #### #locale
|
367
387
|
#
|
368
388
|
# Always generate translations file alongside the component:
|
369
389
|
#
|
370
|
-
#
|
390
|
+
# ```ruby
|
391
|
+
# config.view_component.generate.locale = true
|
392
|
+
# ```
|
371
393
|
#
|
372
394
|
# #### #distinct_locale_files
|
373
395
|
#
|
374
396
|
# Always generate as many translations files as available locales:
|
375
397
|
#
|
376
|
-
#
|
398
|
+
# ```ruby
|
399
|
+
# config.view_component.generate.distinct_locale_files = true
|
400
|
+
# ```
|
377
401
|
#
|
378
402
|
# One file will be generated for each configured `I18n.available_locales`,
|
379
403
|
# falling back to `[:en]` when no `available_locales` is defined.
|
@@ -382,7 +406,9 @@ module ViewComponent
|
|
382
406
|
#
|
383
407
|
# Always generate preview alongside the component:
|
384
408
|
#
|
385
|
-
#
|
409
|
+
# ```ruby
|
410
|
+
# config.view_component.generate.preview = true
|
411
|
+
# ```
|
386
412
|
#
|
387
413
|
# Defaults to `false`.
|
388
414
|
mattr_accessor :generate, instance_writer: false, default: ActiveSupport::OrderedOptions.new(false)
|
@@ -436,7 +462,9 @@ module ViewComponent
|
|
436
462
|
|
437
463
|
# Render a component for each element in a collection ([documentation](/guide/collections)):
|
438
464
|
#
|
439
|
-
#
|
465
|
+
# ```ruby
|
466
|
+
# render(ProductsComponent.with_collection(@products, foo: :bar))
|
467
|
+
# ```
|
440
468
|
#
|
441
469
|
# @param collection [Enumerable] A list of items to pass the ViewComponent one at a time.
|
442
470
|
# @param args [Arguments] Arguments to pass to the ViewComponent every time.
|
@@ -532,13 +560,35 @@ module ViewComponent
|
|
532
560
|
|
533
561
|
# Set the parameter name used when rendering elements of a collection ([documentation](/guide/collections)):
|
534
562
|
#
|
535
|
-
#
|
563
|
+
# ```ruby
|
564
|
+
# with_collection_parameter :item
|
565
|
+
# ```
|
536
566
|
#
|
537
567
|
# @param parameter [Symbol] The parameter name used when rendering elements of a collection.
|
538
568
|
def with_collection_parameter(parameter)
|
539
569
|
@provided_collection_parameter = parameter
|
540
570
|
end
|
541
571
|
|
572
|
+
# Strips trailing whitespace from templates before compiling them.
|
573
|
+
#
|
574
|
+
# ```ruby
|
575
|
+
# class MyComponent < ViewComponent::Base
|
576
|
+
# strip_trailing_whitespace
|
577
|
+
# end
|
578
|
+
# ```
|
579
|
+
#
|
580
|
+
# @param value [Boolean] Whether or not to strip newlines.
|
581
|
+
def strip_trailing_whitespace(value = true)
|
582
|
+
self.__vc_strip_trailing_whitespace = value
|
583
|
+
end
|
584
|
+
|
585
|
+
# Whether trailing whitespace will be stripped before compilation.
|
586
|
+
#
|
587
|
+
# @return [Boolean]
|
588
|
+
def strip_trailing_whitespace?
|
589
|
+
__vc_strip_trailing_whitespace
|
590
|
+
end
|
591
|
+
|
542
592
|
# Ensure the component initializer accepts the
|
543
593
|
# collection parameter. By default, we don't
|
544
594
|
# validate that the default parameter name
|
@@ -586,11 +636,7 @@ module ViewComponent
|
|
586
636
|
|
587
637
|
# @private
|
588
638
|
def collection_parameter
|
589
|
-
|
590
|
-
provided_collection_parameter
|
591
|
-
else
|
592
|
-
name && name.demodulize.underscore.chomp("_component").to_sym
|
593
|
-
end
|
639
|
+
provided_collection_parameter || name && name.demodulize.underscore.chomp("_component").to_sym
|
594
640
|
end
|
595
641
|
|
596
642
|
# @private
|
@@ -18,9 +18,9 @@ module ViewComponent
|
|
18
18
|
|
19
19
|
def render_in(view_context, &block)
|
20
20
|
components.map do |component|
|
21
|
-
component.set_original_view_context(
|
21
|
+
component.set_original_view_context(__vc_original_view_context)
|
22
22
|
component.render_in(view_context, &block)
|
23
|
-
end.join.html_safe
|
23
|
+
end.join.html_safe
|
24
24
|
end
|
25
25
|
|
26
26
|
def components
|
@@ -61,7 +61,7 @@ module ViewComponent
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def component_options(item, iterator)
|
64
|
-
item_options = {
|
64
|
+
item_options = {component.collection_parameter => item}
|
65
65
|
item_options[component.collection_counter_parameter] = iterator.index + 1 if component.counter_argument_present?
|
66
66
|
item_options[component.collection_iteration_parameter] = iterator.dup if component.iteration_argument_present?
|
67
67
|
|
@@ -31,6 +31,8 @@ module ViewComponent
|
|
31
31
|
return if compiled? && !force
|
32
32
|
return if component_class == ViewComponent::Base
|
33
33
|
|
34
|
+
component_class.superclass.compile(raise_errors: raise_errors) if should_compile_superclass?
|
35
|
+
|
34
36
|
with_lock do
|
35
37
|
subclass_instance_methods = component_class.instance_methods(false)
|
36
38
|
|
@@ -68,11 +70,13 @@ module ViewComponent
|
|
68
70
|
component_class.send(:remove_method, method_name.to_sym)
|
69
71
|
end
|
70
72
|
|
73
|
+
# rubocop:disable Style/EvalWithLocation
|
71
74
|
component_class.class_eval <<-RUBY, template[:path], 0
|
72
75
|
def #{method_name}
|
73
76
|
#{compiled_template(template[:path])}
|
74
77
|
end
|
75
78
|
RUBY
|
79
|
+
# rubocop:enable Style/EvalWithLocation
|
76
80
|
end
|
77
81
|
|
78
82
|
define_render_template_for
|
@@ -151,15 +155,15 @@ module ViewComponent
|
|
151
155
|
end
|
152
156
|
|
153
157
|
invalid_variants =
|
154
|
-
templates
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
158
|
+
templates
|
159
|
+
.group_by { |template| template[:variant] }
|
160
|
+
.map { |variant, grouped| variant if grouped.length > 1 }
|
161
|
+
.compact
|
162
|
+
.sort
|
159
163
|
|
160
164
|
unless invalid_variants.empty?
|
161
165
|
errors <<
|
162
|
-
"More than one template found for #{
|
166
|
+
"More than one template found for #{"variant".pluralize(invalid_variants.count)} " \
|
163
167
|
"#{invalid_variants.map { |v| "'#{v}'" }.to_sentence} in #{component_class}. " \
|
164
168
|
"There can only be one template file per variant."
|
165
169
|
end
|
@@ -177,8 +181,8 @@ module ViewComponent
|
|
177
181
|
count = duplicate_template_file_and_inline_variant_calls.count
|
178
182
|
|
179
183
|
errors <<
|
180
|
-
"Template #{
|
181
|
-
"found for #{
|
184
|
+
"Template #{"file".pluralize(count)} and inline render #{"method".pluralize(count)} " \
|
185
|
+
"found for #{"variant".pluralize(count)} " \
|
182
186
|
"#{duplicate_template_file_and_inline_variant_calls.map { |v| "'#{v}'" }.to_sentence} " \
|
183
187
|
"in #{component_class}. " \
|
184
188
|
"There can only be a template file or inline render method per variant."
|
@@ -236,8 +240,9 @@ module ViewComponent
|
|
236
240
|
end
|
237
241
|
|
238
242
|
def compiled_template(file_path)
|
239
|
-
handler = ActionView::Template.handler_for_extension(File.extname(file_path).
|
243
|
+
handler = ActionView::Template.handler_for_extension(File.extname(file_path).delete("."))
|
240
244
|
template = File.read(file_path)
|
245
|
+
template.rstrip! if component_class.strip_trailing_whitespace?
|
241
246
|
|
242
247
|
if handler.method(:call).parameters.length > 1
|
243
248
|
handler.call(component_class, template)
|
@@ -259,5 +264,14 @@ module ViewComponent
|
|
259
264
|
"call"
|
260
265
|
end
|
261
266
|
end
|
267
|
+
|
268
|
+
def should_compile_superclass?
|
269
|
+
development? &&
|
270
|
+
templates.empty? &&
|
271
|
+
!(
|
272
|
+
component_class.instance_methods(false).include?(:call) ||
|
273
|
+
component_class.private_instance_methods(false).include?(:call)
|
274
|
+
)
|
275
|
+
end
|
262
276
|
end
|
263
277
|
end
|
@@ -28,7 +28,7 @@ module ViewComponent
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def types
|
31
|
-
" → [#{@method.tag(:return).types.join(
|
31
|
+
" → [#{@method.tag(:return).types.join(",")}]" if @method.tag(:return)&.types && show_types?
|
32
32
|
end
|
33
33
|
|
34
34
|
def signature_or_name
|
@@ -77,7 +77,8 @@ module ViewComponent
|
|
77
77
|
options = app.config.view_component
|
78
78
|
|
79
79
|
if options.show_previews && !options.preview_paths.empty?
|
80
|
-
ActiveSupport::Dependencies.autoload_paths
|
80
|
+
paths_to_add = options.preview_paths - ActiveSupport::Dependencies.autoload_paths
|
81
|
+
ActiveSupport::Dependencies.autoload_paths.concat(paths_to_add) if paths_to_add.any?
|
81
82
|
end
|
82
83
|
end
|
83
84
|
|
@@ -133,10 +134,10 @@ module ViewComponent
|
|
133
134
|
|
134
135
|
initializer "compiler mode" do |app|
|
135
136
|
ViewComponent::Compiler.mode = if Rails.env.development? || Rails.env.test?
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
137
|
+
ViewComponent::Compiler::DEVELOPMENT_MODE
|
138
|
+
else
|
139
|
+
ViewComponent::Compiler::PRODUCTION_MODE
|
140
|
+
end
|
140
141
|
end
|
141
142
|
|
142
143
|
config.after_initialize do |app|
|
@@ -34,13 +34,14 @@ module ViewComponent
|
|
34
34
|
def with_output_buffer(buf = nil)
|
35
35
|
unless buf
|
36
36
|
buf = ActionView::OutputBuffer.new
|
37
|
+
# rubocop:disable Style/SafeNavigation
|
37
38
|
if output_buffer && output_buffer.respond_to?(:encoding)
|
38
39
|
buf.force_encoding(output_buffer.encoding)
|
39
40
|
end
|
41
|
+
# rubocop:enable Style/SafeNavigation
|
40
42
|
end
|
41
43
|
|
42
44
|
output_buffer.push(buf)
|
43
|
-
result = nil
|
44
45
|
|
45
46
|
begin
|
46
47
|
yield
|
@@ -65,13 +66,13 @@ module ViewComponent
|
|
65
66
|
def with_output_buffer(buf = nil)
|
66
67
|
unless buf
|
67
68
|
buf = ActionView::OutputBuffer.new
|
69
|
+
# rubocop:disable Style/SafeNavigation
|
68
70
|
if @output_buffer && @output_buffer.respond_to?(:encoding)
|
69
71
|
buf.force_encoding(@output_buffer.encoding)
|
70
72
|
end
|
73
|
+
# rubocop:enable Style/SafeNavigation
|
71
74
|
end
|
72
75
|
|
73
|
-
result = nil
|
74
|
-
|
75
76
|
if @output_buffer.is_a?(OutputBufferStack)
|
76
77
|
@output_buffer.push(buf)
|
77
78
|
|
@@ -5,6 +5,17 @@ module ViewComponent
|
|
5
5
|
# In older rails versions, using a concern isn't a good idea here because they appear to not work with
|
6
6
|
# Module#prepend and class methods.
|
7
7
|
def self.included(base)
|
8
|
+
if base != ViewComponent::Base
|
9
|
+
# :nocov:
|
10
|
+
location = Kernel.caller_locations(1, 1)[0]
|
11
|
+
|
12
|
+
warn(
|
13
|
+
"warning: ViewComponent::PolymorphicSlots is now included in ViewComponent::Base by default "\
|
14
|
+
"and can be removed from #{location.path}:#{location.lineno}"
|
15
|
+
)
|
16
|
+
# :nocov:
|
17
|
+
end
|
18
|
+
|
8
19
|
base.singleton_class.prepend(ClassMethods)
|
9
20
|
base.include(InstanceMethods)
|
10
21
|
end
|
@@ -45,8 +56,12 @@ module ViewComponent
|
|
45
56
|
"#{slot_name}_#{poly_type}"
|
46
57
|
end
|
47
58
|
|
48
|
-
# Deprecated: Will be removed in 3.0
|
49
59
|
define_method(setter_name) do |*args, &block|
|
60
|
+
ViewComponent::Deprecation.warn(
|
61
|
+
"polymorphic slot setters like `#{setter_name}` are deprecated and will be removed in"\
|
62
|
+
"ViewComponent v3.0.0.\n\nUse `with_#{setter_name}` instead."
|
63
|
+
)
|
64
|
+
|
50
65
|
set_polymorphic_slot(slot_name, poly_type, *args, &block)
|
51
66
|
end
|
52
67
|
ruby2_keywords(setter_name.to_sym) if respond_to?(:ruby2_keywords, true)
|
@@ -57,7 +72,7 @@ module ViewComponent
|
|
57
72
|
ruby2_keywords(:"with_#{setter_name}") if respond_to?(:ruby2_keywords, true)
|
58
73
|
end
|
59
74
|
|
60
|
-
|
75
|
+
registered_slots[slot_name] = {
|
61
76
|
collection: collection,
|
62
77
|
renderable_hash: renderable_hash
|
63
78
|
}
|
@@ -14,7 +14,7 @@ module ViewComponent # :nodoc:
|
|
14
14
|
block: block,
|
15
15
|
component: component,
|
16
16
|
locals: {},
|
17
|
-
template: "view_components/preview"
|
17
|
+
template: "view_components/preview"
|
18
18
|
}
|
19
19
|
end
|
20
20
|
|
@@ -66,10 +66,12 @@ module ViewComponent # :nodoc:
|
|
66
66
|
name.chomp("Preview").underscore
|
67
67
|
end
|
68
68
|
|
69
|
+
# rubocop:disable Style/TrivialAccessors
|
69
70
|
# Setter for layout name.
|
70
71
|
def layout(layout_name)
|
71
72
|
@layout = layout_name
|
72
73
|
end
|
74
|
+
# rubocop:enable Style/TrivialAccessors
|
73
75
|
|
74
76
|
# Returns the relative path (from preview_path) to the preview example template if the template exists
|
75
77
|
def preview_example_template_path(example)
|
@@ -87,15 +89,15 @@ module ViewComponent # :nodoc:
|
|
87
89
|
end
|
88
90
|
|
89
91
|
path = Dir["#{preview_path}/#{preview_name}_preview/#{example}.html.*"].first
|
90
|
-
Pathname.new(path)
|
91
|
-
relative_path_from(Pathname.new(preview_path))
|
92
|
-
to_s
|
93
|
-
sub(/\..*$/, "")
|
92
|
+
Pathname.new(path)
|
93
|
+
.relative_path_from(Pathname.new(preview_path))
|
94
|
+
.to_s
|
95
|
+
.sub(/\..*$/, "")
|
94
96
|
end
|
95
97
|
|
96
98
|
# Returns the method body for the example from the preview file.
|
97
99
|
def preview_source(example)
|
98
|
-
source =
|
100
|
+
source = instance_method(example.to_sym).source.split("\n")
|
99
101
|
source[1...(source.size - 1)].join("\n")
|
100
102
|
end
|
101
103
|
|
@@ -4,7 +4,7 @@ module ViewComponent
|
|
4
4
|
module RenderingMonkeyPatch # :nodoc:
|
5
5
|
def render(options = {}, args = {})
|
6
6
|
if options.respond_to?(:render_in)
|
7
|
-
self.response_body = options.render_in(
|
7
|
+
self.response_body = options.render_in(view_context)
|
8
8
|
else
|
9
9
|
super
|
10
10
|
end
|
@@ -30,7 +30,7 @@ module ViewComponent
|
|
30
30
|
|
31
31
|
slot_names.each do |slot_name|
|
32
32
|
# Ensure slot_name isn't already declared
|
33
|
-
if
|
33
|
+
if slots.key?(slot_name)
|
34
34
|
raise ArgumentError.new("#{slot_name} slot declared multiple times")
|
35
35
|
end
|
36
36
|
|
@@ -73,7 +73,7 @@ module ViewComponent
|
|
73
73
|
class_name = "ViewComponent::Slot" unless class_name.present?
|
74
74
|
|
75
75
|
# Register the slot on the component
|
76
|
-
|
76
|
+
slots[slot_name] = {
|
77
77
|
class_name: class_name,
|
78
78
|
instance_variable_name: instance_variable_name,
|
79
79
|
collection: collection
|
@@ -84,7 +84,7 @@ module ViewComponent
|
|
84
84
|
def inherited(child)
|
85
85
|
# Clone slot configuration into child class
|
86
86
|
# see #test_slots_pollution
|
87
|
-
child.slots =
|
87
|
+
child.slots = slots.clone
|
88
88
|
|
89
89
|
super
|
90
90
|
end
|
@@ -106,7 +106,7 @@ module ViewComponent
|
|
106
106
|
#
|
107
107
|
def slot(slot_name, **args, &block)
|
108
108
|
# Raise ArgumentError if `slot` doesn't exist
|
109
|
-
unless slots.
|
109
|
+
unless slots.key?(slot_name)
|
110
110
|
raise ArgumentError.new "Unknown slot '#{slot_name}' - expected one of '#{slots.keys}'"
|
111
111
|
end
|
112
112
|
|
@@ -123,8 +123,7 @@ module ViewComponent
|
|
123
123
|
slot_instance = args.present? ? slot_class.new(**args) : slot_class.new
|
124
124
|
|
125
125
|
# Capture block and assign to slot_instance#content
|
126
|
-
|
127
|
-
slot_instance.content = view_context.capture(&block).to_s.strip.html_safe if block_given?
|
126
|
+
slot_instance.content = view_context.capture(&block).to_s.strip.html_safe if block
|
128
127
|
|
129
128
|
if slot[:collection]
|
130
129
|
# Initialize instance variable as an empty array
|
@@ -9,7 +9,7 @@ module ViewComponent
|
|
9
9
|
|
10
10
|
RESERVED_NAMES = {
|
11
11
|
singular: %i[content render].freeze,
|
12
|
-
plural: %i[contents renders].freeze
|
12
|
+
plural: %i[contents renders].freeze
|
13
13
|
}.freeze
|
14
14
|
|
15
15
|
# Setup component slot state
|
@@ -190,20 +190,20 @@ module ViewComponent
|
|
190
190
|
# Clone slot configuration into child class
|
191
191
|
# see #test_slots_pollution
|
192
192
|
def inherited(child)
|
193
|
-
child.registered_slots =
|
193
|
+
child.registered_slots = registered_slots.clone
|
194
194
|
super
|
195
195
|
end
|
196
196
|
|
197
197
|
private
|
198
198
|
|
199
199
|
def register_slot(slot_name, **kwargs)
|
200
|
-
|
200
|
+
registered_slots[slot_name] = define_slot(slot_name, **kwargs)
|
201
201
|
end
|
202
202
|
|
203
203
|
def define_slot(slot_name, collection:, callable:)
|
204
204
|
# Setup basic slot data
|
205
205
|
slot = {
|
206
|
-
collection: collection
|
206
|
+
collection: collection
|
207
207
|
}
|
208
208
|
return slot unless callable
|
209
209
|
|
@@ -254,7 +254,7 @@ module ViewComponent
|
|
254
254
|
end
|
255
255
|
|
256
256
|
def raise_if_slot_registered(slot_name)
|
257
|
-
if
|
257
|
+
if registered_slots.key?(slot_name)
|
258
258
|
# TODO remove? This breaks overriding slots when slots are inherited
|
259
259
|
raise ArgumentError.new(
|
260
260
|
"#{self} declares the #{slot_name} slot multiple times.\n\n" \
|
@@ -287,8 +287,6 @@ module ViewComponent
|
|
287
287
|
|
288
288
|
if slot[:collection]
|
289
289
|
[]
|
290
|
-
else
|
291
|
-
nil
|
292
290
|
end
|
293
291
|
end
|
294
292
|
|
@@ -305,7 +303,7 @@ module ViewComponent
|
|
305
303
|
# 2. Since we've to pass block content to components when calling
|
306
304
|
# `render`, evaluating the block here would require us to call
|
307
305
|
# `view_context.capture` twice, which is slower
|
308
|
-
slot.__vc_content_block = block if
|
306
|
+
slot.__vc_content_block = block if block
|
309
307
|
|
310
308
|
# If class
|
311
309
|
if slot_definition[:renderable]
|
@@ -321,7 +319,7 @@ module ViewComponent
|
|
321
319
|
# methods like `content_tag` as well as parent component state.
|
322
320
|
renderable_function = slot_definition[:renderable_function].bind(self)
|
323
321
|
renderable_value =
|
324
|
-
if
|
322
|
+
if block
|
325
323
|
renderable_function.call(*args) do |*rargs|
|
326
324
|
view_context.capture(*rargs, &block)
|
327
325
|
end
|
@@ -32,6 +32,9 @@ module ViewComponent
|
|
32
32
|
# @private
|
33
33
|
attr_reader :rendered_content
|
34
34
|
|
35
|
+
# Returns the result of a render_inline call.
|
36
|
+
#
|
37
|
+
# @return [String]
|
35
38
|
def rendered_component
|
36
39
|
ViewComponent::Deprecation.warn(
|
37
40
|
"`rendered_component` is deprecated and will be removed in v3.0.0. " \
|
@@ -9,7 +9,7 @@ module ViewComponent
|
|
9
9
|
module Translatable
|
10
10
|
extend ActiveSupport::Concern
|
11
11
|
|
12
|
-
HTML_SAFE_TRANSLATION_KEY = /(?:_|\b)html\z
|
12
|
+
HTML_SAFE_TRANSLATION_KEY = /(?:_|\b)html\z/
|
13
13
|
|
14
14
|
included do
|
15
15
|
class_attribute :i18n_backend, instance_writer: false, instance_predicate: false
|
@@ -23,14 +23,13 @@ module ViewComponent
|
|
23
23
|
def build_i18n_backend
|
24
24
|
return if CompileCache.compiled? self
|
25
25
|
|
26
|
-
if (translation_files = _sidecar_files(%w[yml yaml])).any?
|
27
|
-
|
26
|
+
self.i18n_backend = if (translation_files = _sidecar_files(%w[yml yaml])).any?
|
27
|
+
# Returning nil cleans up if translations file has been removed since the last compilation
|
28
|
+
|
29
|
+
I18nBackend.new(
|
28
30
|
i18n_scope: i18n_scope,
|
29
|
-
load_paths: translation_files
|
31
|
+
load_paths: translation_files
|
30
32
|
)
|
31
|
-
else
|
32
|
-
# Cleanup if translations file has been removed since the last compilation
|
33
|
-
self.i18n_backend = nil
|
34
33
|
end
|
35
34
|
end
|
36
35
|
end
|
@@ -50,7 +49,7 @@ module ViewComponent
|
|
50
49
|
|
51
50
|
def scope_data(data)
|
52
51
|
@i18n_scope.reverse_each do |part|
|
53
|
-
data = {
|
52
|
+
data = {part => data}
|
54
53
|
end
|
55
54
|
data
|
56
55
|
end
|
@@ -95,7 +94,7 @@ module ViewComponent
|
|
95
94
|
super(key, locale: locale, **options)
|
96
95
|
end
|
97
96
|
end
|
98
|
-
|
97
|
+
alias_method :t, :translate
|
99
98
|
|
100
99
|
# Exposes .i18n_scope as an instance method
|
101
100
|
def i18n_scope
|
@@ -109,7 +108,7 @@ module ViewComponent
|
|
109
108
|
# It's assumed here that objects loaded by the i18n backend will respond to `#html_safe?`.
|
110
109
|
# It's reasonable that if we're in Rails, `active_support/core_ext/string/output_safety.rb`
|
111
110
|
# will provide this to `Object`.
|
112
|
-
translation.html_safe
|
111
|
+
translation.html_safe
|
113
112
|
end
|
114
113
|
end
|
115
114
|
|
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.58.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-07-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -185,19 +185,19 @@ dependencies:
|
|
185
185
|
- !ruby/object:Gem::Version
|
186
186
|
version: '13.0'
|
187
187
|
- !ruby/object:Gem::Dependency
|
188
|
-
name:
|
188
|
+
name: standard
|
189
189
|
requirement: !ruby/object:Gem::Requirement
|
190
190
|
requirements:
|
191
191
|
- - "~>"
|
192
192
|
- !ruby/object:Gem::Version
|
193
|
-
version:
|
193
|
+
version: '1'
|
194
194
|
type: :development
|
195
195
|
prerelease: false
|
196
196
|
version_requirements: !ruby/object:Gem::Requirement
|
197
197
|
requirements:
|
198
198
|
- - "~>"
|
199
199
|
- !ruby/object:Gem::Version
|
200
|
-
version:
|
200
|
+
version: '1'
|
201
201
|
- !ruby/object:Gem::Dependency
|
202
202
|
name: simplecov
|
203
203
|
requirement: !ruby/object:Gem::Requirement
|