view_component 2.57.1 → 2.58.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of view_component might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c0dea17d60642f97d9edad061c538054015eac0f774bc58d37ba30c177a76ac
4
- data.tar.gz: bb12f7080b7c90ab0e475550bf44577ef25d2b1e0d0966cc5f07c272d9ea5fec
3
+ metadata.gz: 73dd7bae94ee1c5a5886e248924ccfea872df61e783e713c0744390d6729d128
4
+ data.tar.gz: e70c67571e32098ee5997b7912d07e65d427e265766c5caa398bcd47d06d3e55
5
5
  SHA512:
6
- metadata.gz: 3eb53d5be8bdb0ab083f0c57938bda3df2094c6368619efb59254bd8ce6a749ffcd4d1dab653b80be48a17f361fa15611c9086c2a526891d81e92527ffd67c9d
7
- data.tar.gz: 418af4138439260637f53b025de631a11f222a699030afe36d3b51b7a31c5f451e7d3eb2ec5c6d13fa39b9b44e12e27fae972b631c92133bfbf054079695b80d
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 # rubocop:disable GitHub/RailsControllerRenderLiteral
40
+ render "view_components/preview", opts
41
41
  end
42
42
  end
43
43
 
44
44
  private
45
45
 
46
- def default_preview_layout # :doc:
46
+ # :doc:
47
+ def default_preview_layout
47
48
  ViewComponent::Base.default_preview_layout
48
49
  end
49
50
 
50
- def show_previews? # :doc:
51
+ # :doc:
52
+ def show_previews?
51
53
  ViewComponent::Base.show_previews
52
54
  end
53
55
 
54
- def find_preview # :doc:
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" # rubocop:disable GitHub/RailsViewRenderPathsExist
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
- return {
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
- return {
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
- gsub("_", "-").
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
 
@@ -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
- # <%= super %> # double-renders
139
- # <% super %> # does not double-render
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(*); end
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
- # config.view_component.test_controller = "MyTestController"
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
- # config.view_component.render_monkey_patch_enabled = false
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
- # config.view_component.view_component_path = "app/my_components"
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
- # config.view_component.component_parent_class = "MyBaseComponent"
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
- # config.view_component.generate.sidecar = true
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
- # config.view_component.generate.stimulus_controller = true
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
- # config.view_component.generate.locale = true
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
- # config.view_component.generate.distinct_locale_files = true
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
- # config.view_component.generate.preview = true
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
- # render(ProductsComponent.with_collection(@products, foo: :bar))
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
- # with_collection_parameter :item
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
- if provided_collection_parameter
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(self.__vc_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 # rubocop:disable Rails/OutputSafety
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 = { component.collection_parameter => item }
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
- group_by { |template| template[:variant] }.
156
- map { |variant, grouped| variant if grouped.length > 1 }.
157
- compact.
158
- sort
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 #{'variant'.pluralize(invalid_variants.count)} " \
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 #{'file'.pluralize(count)} and inline render #{'method'.pluralize(count)} " \
181
- "found for #{'variant'.pluralize(count)} " \
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).gsub(".", ""))
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
@@ -21,7 +21,7 @@ module ViewComponent
21
21
  )
22
22
  end
23
23
 
24
- if block_given?
24
+ if block
25
25
  content = view_context.capture(&block)
26
26
  end
27
27
 
@@ -28,7 +28,7 @@ module ViewComponent
28
28
  end
29
29
 
30
30
  def types
31
- " → [#{@method.tag(:return).types.join(',')}]" if @method.tag(:return)&.types && show_types?
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.concat(options.preview_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
- ViewComponent::Compiler::DEVELOPMENT_MODE
137
- else
138
- ViewComponent::Compiler::PRODUCTION_MODE
139
- end
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
 
@@ -37,9 +37,7 @@ module ViewComponent
37
37
  end
38
38
 
39
39
  def safe_concat(arg)
40
- # rubocop:disable Rails/OutputSafety
41
40
  @current_buffer.safe_concat(arg)
42
- # rubocop:enable Rails/OutputSafety
43
41
  end
44
42
 
45
43
  def length
@@ -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
- self.registered_slots[slot_name] = {
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 = self.instance_method(example.to_sym).source.split("\n")
100
+ source = instance_method(example.to_sym).source.split("\n")
99
101
  source[1...(source.size - 1)].join("\n")
100
102
  end
101
103
 
@@ -3,7 +3,7 @@
3
3
  module ViewComponent
4
4
  module RenderComponentToStringHelper # :nodoc:
5
5
  def render_component_to_string(component)
6
- component.render_in(self.view_context)
6
+ component.render_in(view_context)
7
7
  end
8
8
  end
9
9
  end
@@ -4,7 +4,7 @@ module ViewComponent
4
4
  module RenderToStringMonkeyPatch # :nodoc:
5
5
  def render_to_string(options = {}, args = {})
6
6
  if options.respond_to?(:render_in)
7
- options.render_in(self.view_context)
7
+ options.render_in(view_context)
8
8
  else
9
9
  super
10
10
  end
@@ -3,7 +3,7 @@
3
3
  module ViewComponent
4
4
  module RenderingComponentHelper # :nodoc:
5
5
  def render_component(component)
6
- self.response_body = component.render_in(self.view_context)
6
+ self.response_body = component.render_in(view_context)
7
7
  end
8
8
  end
9
9
  end
@@ -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(self.view_context)
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 self.slots.key?(slot_name)
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
- self.slots[slot_name] = {
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 = self.slots.clone
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.keys.include?(slot_name)
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
- # rubocop:disable Rails/OutputSafety
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 = self.registered_slots.clone
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
- self.registered_slots[slot_name] = define_slot(slot_name, **kwargs)
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 self.registered_slots.key?(slot_name)
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 block_given?
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 block_given?
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/.freeze
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
- self.i18n_backend = I18nBackend.new(
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 = { part => 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
- alias :t :translate
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 # rubocop:disable Rails/OutputSafety
111
+ translation.html_safe
113
112
  end
114
113
  end
115
114
 
@@ -3,8 +3,8 @@
3
3
  module ViewComponent
4
4
  module VERSION
5
5
  MAJOR = 2
6
- MINOR = 57
7
- PATCH = 1
6
+ MINOR = 58
7
+ PATCH = 0
8
8
 
9
9
  STRING = [MAJOR, MINOR, PATCH].join(".")
10
10
  end
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.57.1
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-06-15 00:00:00.000000000 Z
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: rubocop-github
188
+ name: standard
189
189
  requirement: !ruby/object:Gem::Requirement
190
190
  requirements:
191
191
  - - "~>"
192
192
  - !ruby/object:Gem::Version
193
- version: 0.16.1
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: 0.16.1
200
+ version: '1'
201
201
  - !ruby/object:Gem::Dependency
202
202
  name: simplecov
203
203
  requirement: !ruby/object:Gem::Requirement