view_component 3.27.0 → 4.0.0.alpha1

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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/view_component/preview_actions.rb +2 -9
  3. data/app/controllers/view_components_system_test_controller.rb +17 -29
  4. data/app/views/test_mailer/test_asset_email.html.erb +1 -0
  5. data/app/views/view_components/preview.html.erb +1 -9
  6. data/docs/CHANGELOG.md +68 -24
  7. data/lib/view_component/base.rb +49 -115
  8. data/lib/view_component/collection.rb +16 -28
  9. data/lib/view_component/compiler.rb +51 -83
  10. data/lib/view_component/config.rb +0 -21
  11. data/lib/view_component/deprecation.rb +1 -1
  12. data/lib/view_component/engine.rb +3 -82
  13. data/lib/view_component/errors.rb +16 -35
  14. data/lib/view_component/inline_template.rb +2 -4
  15. data/lib/view_component/instrumentation.rb +5 -11
  16. data/lib/view_component/preview.rb +3 -12
  17. data/lib/view_component/request_details.rb +30 -0
  18. data/lib/view_component/slot.rb +3 -6
  19. data/lib/view_component/slotable.rb +30 -37
  20. data/lib/view_component/system_test_helpers.rb +1 -2
  21. data/lib/view_component/template.rb +106 -83
  22. data/lib/view_component/test_helpers.rb +22 -42
  23. data/lib/view_component/translatable.rb +24 -23
  24. data/lib/view_component/use_helpers.rb +3 -4
  25. data/lib/view_component/version.rb +3 -3
  26. data/lib/view_component.rb +0 -1
  27. metadata +71 -214
  28. data/app/assets/vendor/prism.css +0 -4
  29. data/app/assets/vendor/prism.min.js +0 -12
  30. data/app/helpers/preview_helper.rb +0 -93
  31. data/app/views/view_components/_preview_source.html.erb +0 -17
  32. data/lib/rails/generators/abstract_generator.rb +0 -56
  33. data/lib/rails/generators/component/component_generator.rb +0 -67
  34. data/lib/rails/generators/component/templates/component.rb.tt +0 -16
  35. data/lib/rails/generators/erb/component_generator.rb +0 -33
  36. data/lib/rails/generators/erb/templates/component.html.erb.tt +0 -1
  37. data/lib/rails/generators/haml/component_generator.rb +0 -22
  38. data/lib/rails/generators/haml/templates/component.html.haml.tt +0 -1
  39. data/lib/rails/generators/locale/component_generator.rb +0 -46
  40. data/lib/rails/generators/preview/component_generator.rb +0 -39
  41. data/lib/rails/generators/preview/templates/component_preview.rb.tt +0 -9
  42. data/lib/rails/generators/rspec/component_generator.rb +0 -31
  43. data/lib/rails/generators/rspec/templates/component_spec.rb.tt +0 -15
  44. data/lib/rails/generators/slim/component_generator.rb +0 -22
  45. data/lib/rails/generators/slim/templates/component.html.slim.tt +0 -1
  46. data/lib/rails/generators/stimulus/component_generator.rb +0 -44
  47. data/lib/rails/generators/stimulus/templates/component_controller.js.tt +0 -7
  48. data/lib/rails/generators/stimulus/templates/component_controller.ts.tt +0 -9
  49. data/lib/rails/generators/tailwindcss/component_generator.rb +0 -11
  50. data/lib/rails/generators/tailwindcss/templates/component.html.erb.tt +0 -1
  51. data/lib/rails/generators/test_unit/component_generator.rb +0 -20
  52. data/lib/rails/generators/test_unit/templates/component_test.rb.tt +0 -12
  53. data/lib/view_component/component_error.rb +0 -6
  54. data/lib/view_component/rails/tasks/view_component.rake +0 -20
  55. data/lib/view_component/render_component_helper.rb +0 -10
  56. data/lib/view_component/render_component_to_string_helper.rb +0 -9
  57. data/lib/view_component/render_monkey_patch.rb +0 -13
  58. data/lib/view_component/render_to_string_monkey_patch.rb +0 -13
  59. data/lib/view_component/rendering_component_helper.rb +0 -9
  60. data/lib/view_component/rendering_monkey_patch.rb +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea3b7eaa6244e04ffa83e7c9d4aeafca18230bedcce0fb160b1001b0441270b0
4
- data.tar.gz: aa605998a6e975f74c307faca61ec6d10b837cdee83c48fe2424e5b6421daf8a
3
+ metadata.gz: e8c0d5be4a21f5c14ed5447caeaffb8d6e51397a1ec786f573bc58d9486fc747
4
+ data.tar.gz: 332de180e52e1b5eae806fb47e9d1dea4a32374cdf63a0642ca69d3661e4c802
5
5
  SHA512:
6
- metadata.gz: a3ec820b42851cb62062972e1473ebb508798e0acd63bfff6e6fda1087c62776806c0199a9e11d6b13bd2914330bf0ad1cb899511c55f62af1538be7a9292a13
7
- data.tar.gz: 748b43b70dec2efc5319bec3379f6b7cf115789f731e3a32af789c304644d20f14d62c9bc727ab88baa4a52dbeba806f8f403dcee1bcf1bc9a6df6ee73f0d412
6
+ metadata.gz: e298e8e18d147034b30fb60f32a7bbf5d5f42d1235d5947cfeba4e3e1b8ad65a57379f3a3fb361ba7ffdec727687689ceb98b4b893e038a16ea5496663d4423a
7
+ data.tar.gz: f6e8f8956abde8eac1e4825c09a2554dde1dd80efac74ba541210e2fe663e23399ddc01289ca44dee21e6c3551b32117b88444d9795fbb450b02639ebc9fadbf
@@ -10,18 +10,11 @@ module ViewComponent
10
10
  around_action :set_locale, only: :previews
11
11
  before_action :require_local!, unless: :show_previews?
12
12
 
13
- content_security_policy(false) if respond_to?(:content_security_policy)
13
+ content_security_policy(false)
14
14
 
15
15
  # Including helpers here ensures that we're loading the
16
16
  # latest version of helpers if code-reloading is enabled
17
- if include_all_helpers
18
- helper :all
19
- else
20
- # :nocov:
21
- # Always provide the #view_source helper
22
- helper PreviewHelper
23
- # :nocov:
24
- end
17
+ helper :all if include_all_helpers
25
18
  end
26
19
 
27
20
  def index
@@ -1,39 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "view_component/errors"
4
-
5
3
  class ViewComponentsSystemTestController < ActionController::Base # :nodoc:
6
- before_action :validate_test_env
7
- before_action :validate_file_path
8
-
9
- rescue_from ViewComponent::SystemTestControllerNefariousPathError, with: :render_not_found
10
-
11
- def self.temp_dir
12
- @_tmpdir ||= FileUtils.mkdir_p("./tmp/view_components/").first
13
- end
14
-
15
- def system_test_entrypoint
16
- render file: @path
17
- end
4
+ if Rails.env.test?
5
+ before_action :validate_file_path
18
6
 
19
- private
7
+ def self.temp_dir
8
+ @_tmpdir ||= FileUtils.mkdir_p("./tmp/view_components/").first
9
+ end
20
10
 
21
- def render_not_found
22
- head :not_found
23
- end
11
+ def system_test_entrypoint
12
+ render file: @path
13
+ end
24
14
 
25
- def validate_test_env
26
- raise ViewComponent::SystemTestControllerOnlyAllowedInTestError unless Rails.env.test?
27
- end
15
+ private
28
16
 
29
- # Ensure that the file path is valid and doesn't target files outside
30
- # the expected directory (e.g. via a path traversal or symlink attack)
31
- def validate_file_path
32
- base_path = ::File.realpath(self.class.temp_dir)
33
- @path = ::File.realpath(params.permit(:file)[:file], base_path)
34
- allowed_prefix = "#{base_path}#{::File::SEPARATOR}"
35
- unless @path == base_path || @path.start_with?(allowed_prefix)
36
- raise ViewComponent::SystemTestControllerNefariousPathError
17
+ # Ensure that the file path is valid and doesn't target files outside
18
+ # the expected directory (e.g. via a path traversal or symlink attack)
19
+ def validate_file_path
20
+ base_path = ::File.realpath(self.class.temp_dir)
21
+ @path = ::File.realpath(params.permit(:file)[:file], base_path)
22
+ unless @path.start_with?(base_path)
23
+ raise ViewComponent::SystemTestControllerNefariousPathError
24
+ end
37
25
  end
38
26
  end
39
27
  end
@@ -0,0 +1 @@
1
+ <%= render AssetComponent.new %>
@@ -1,13 +1,5 @@
1
1
  <% if @render_args[:component] %>
2
- <% if ViewComponent::Base.config.render_monkey_patch_enabled || Rails.version.to_f >= 6.1 %>
3
- <%= render(@render_args[:component], @render_args[:args], &@render_args[:block]) %>
4
- <% else %>
5
- <%= render_component(@render_args[:component], &@render_args[:block]) %>
6
- <% end %>
2
+ <%= render(@render_args[:component], @render_args[:args], &@render_args[:block]) %>
7
3
  <% else %>
8
4
  <%= render template: @render_args[:template], locals: @render_args[:locals] || {} %>
9
5
  <% end %>
10
-
11
- <% if ViewComponent::Base.config.show_previews_source %>
12
- <%= preview_source %>
13
- <% end %>
data/docs/CHANGELOG.md CHANGED
@@ -10,63 +10,107 @@ nav_order: 6
10
10
 
11
11
  ## main
12
12
 
13
- ## 3.27.0
13
+ ## 4.0.0
14
14
 
15
- * [Security] Fix incomplete remediation for CVE-2026-54497 (GHSA-8qw7-6phv-7q6p): reused ViewComponent instances could still leak `with_content` and `renders_one`/`renders_many` slot content from an earlier render into a later render because slot state and content set via `with_content` are populated by the caller before `render_in` runs and were not cleared by the previous per-render reset. Reinstate the `ViewComponent::ReusedInstanceError` guard that raises when a component instance is rendered more than once. Rebuild collection child components per render and dup collection spacer components before each render so that legitimate re-rendering of `Collection`/spacer objects continues to work.
15
+ Almost six years after releasing [v1.0.0](https://github.com/ViewComponent/view_component/releases/tag/v1.0.0), we're proud to ship ViewComponent 4. This release marks a shift towards a Long Term Support model for the project, having reached significant feature maturity. While contributions are always welcome, we're unlikely to accept further breaking changes or major feature additions.
16
16
 
17
- *Yazan Balawneh, Cystack.ps*
17
+ This release makes the following breaking changes:
18
18
 
19
- ## 3.26.0
19
+ * BREAKING: `--inline` generator option now generates inline template. Use `--call` to generate `#call` method.
20
20
 
21
- * Fix rendering partials from components rendered as a collection when the original view context is explicitly stashed as `nil`.
21
+ *Joel Hawksley*
22
+
23
+ * BREAKING: Remove `use_deprecated_instrumentation_name` configuration option. Events will always use `render.view_component` name.
22
24
 
23
- *Justin Coyne, Joel Hawksley*
25
+ *Joel Hawksley*
24
26
 
25
- * Restore compatibility with Rails main after `ActionView::Template.template_handler_extensions` and `ActionView::LookupContext#find_template` were removed.
27
+ * BREAKING: Remove `preview_source` functionality. Consider using [Lookbook](https://lookbook.build/) instead.
26
28
 
27
29
  *Joel Hawksley*
28
30
 
29
- ## 3.25.0
31
+ * BREAKING: Use `Nokogiri::HTML5` instead of `Nokogiri::HTML4` for test helpers.
32
+
33
+ *Noah Silvera*, *Joel Hawksley*
34
+
35
+ * BREAKING: Move generators to a ViewComponent namespace.
36
+
37
+ Before, ViewComponent generators pollute the generator namespace with a bunch of top level items, and claim the generic "component" name.
38
+
39
+ Now, generators live in a "view_component" module/namespace, so what was before `rails g
40
+ component` is now `rails g view_component:component`.
41
+
42
+ *Paul Sadauskas*
30
43
 
31
- * Support Rails `render_in` options signature. Rails [#50623](https://github.com/rails/rails/pull/50623) changed the `render_in` signature from `render_in(view_context, &block)` to `render_in(view_context, **options, &block)`. `ViewComponent::Base#render_in`, `ViewComponent::Collection#render_in`, and `ViewComponent::Instrumentation#render_in` now accept `**options`, restoring compatibility with Rails main and silencing the deprecation warning.
44
+ * BREAKING: Require [non-EOL](https://endoflife.date/rails) Rails (`>= 7.1.0`).
32
45
 
33
46
  *Joel Hawksley*
34
47
 
35
- * Fix stale render context on reused component instances. A `ViewComponent::Base` instance memoized its controller, helpers, request, view context, lookup context, view flow, and requested format/variant on first render via `||=`. Rendering the same instance a second time (intentionally or via aliasing) reused that stale context, which could leak data across requests, sessions, or users. `#render_in` now resets these ivars on every call so each render derives its context from the current view.
48
+ * BREAKING: Require [non-EOL](https://www.ruby-lang.org/en/downloads/branches/) Ruby (`>= 3.2.0`).
36
49
 
37
50
  *Joel Hawksley*
38
51
 
39
- * Fix path traversal vulnerability in `ViewComponentsSystemTestController` where sibling directories sharing a string prefix with the allowed temp directory could bypass the path containment check. The `start_with?` check has been replaced with a separator-aware prefix check, and nefarious path errors now return a 404 instead of an unhandled exception.
52
+ * BREAKING: Remove `render_component` and `render` monkey patch configured with `render_monkey_patch_enabled`.
40
53
 
41
54
  *Joel Hawksley*
42
55
 
43
- * Fix preview route vulnerability where inherited methods on `ViewComponent::Preview` (such as `render_with_template`) could be invoked via the preview URL, allowing arbitrary internal Rails templates to be rendered with attacker-controlled locals and request parameters. `render_args` now raises `AbstractController::ActionNotFound` for any example not explicitly declared on the preview subclass.
56
+ * BREAKING: Remove support for variant names containing `.` to be consistent with Rails.
57
+
58
+ *Stephen Nelson*
59
+
60
+ * BREAKING: Use ActionView's `lookup_context` for picking templates instead of the request format.
61
+
62
+ 3.15 added support for using templates that match the request format, i.e. if `/resource.csv` is requested then
63
+ ViewComponents would pick `_component.csv.erb` over `_component.html.erb`.
64
+
65
+ With this release, the request format is no longer considered and instead ViewComponent will use the Rails logic
66
+ for picking the most appropriate template type, i.e. the csv template will be used if it matches the `Accept` header
67
+ or because the controller uses a `respond_to` block to pick the response format.
68
+
69
+ *Stephen Nelson*
70
+
71
+ * BREAKING: Rename internal methods to have `__vc_` prefix if they shouldn't be used by consumers. Make internal constants private. Make `Collection#components`, `Slotable#register_polymorphic_slot` private. Remove unused `ComponentError` class.
44
72
 
45
73
  *Joel Hawksley*
46
74
 
47
- ## 3.24.0
75
+ * Fix bug where request-aware helpers did not work outside of the request context.
48
76
 
49
- * Add Rails 8.1 support to ViewComponent v3.
77
+ *Joel Hawksley*, *Stephen Nelson*
50
78
 
51
- *Hans Lemuet*
79
+ * `ViewComponentsSystemTestController` should not be useable outside of test environment
52
80
 
53
- ## 3.23.2
81
+ *Joel Hawksley*, *Stephen Nelson*
54
82
 
55
- * Include .tt files in published gem. Fixes templates not being available when using generators.
83
+ * Remove unnecessary ENABLE_RELOADING test suite flag.
56
84
 
57
- *Florian Aßmann*
85
+ *Joel Hawksley*
58
86
 
59
- ## 3.23.1
87
+ * Add test coverage for uncovered code.
60
88
 
61
- * Restore Rake tasks in published gem.
89
+ *Joel Hawksley*
62
90
 
63
- *Franz Liedke*
91
+ * Remove unnecessary `#format` methods that returned `nil`.
92
+
93
+ *Joel Hawksley*
94
+
95
+ * Clean up project dependencies, relaxing versions of development gems.
96
+
97
+ *Joel Hawksley*
98
+
99
+ * Test against `turbo-rails` `v2`.
64
100
 
65
- ## 3.23.0
101
+ *Joel Hawksley*
102
+
103
+ * Test against `rspec-rails` `v7`.
104
+
105
+ *Joel Hawksley*
106
+
107
+ * Remove unnecessary usage of `ruby2_keywords`.
108
+
109
+ *Joel Hawksley*
66
110
 
67
- * Add docs about Slack channel in Ruby Central workspace. (Join us! #oss-view-component). Email joelhawksley@github.com for an invite.
111
+ * Remove unnecessary `respond_to` checks.
68
112
 
69
- *Joel Hawksley
113
+ *Tiago Menegaz*, *Joel Hawksley*
70
114
 
71
115
  * Do not include internal `DocsBuilderComponent` or `YARD::MattrAccessorHandler` in published gem.
72
116
 
@@ -9,6 +9,7 @@ require "view_component/config"
9
9
  require "view_component/errors"
10
10
  require "view_component/inline_template"
11
11
  require "view_component/preview"
12
+ require "view_component/request_details"
12
13
  require "view_component/slotable"
13
14
  require "view_component/slotable_default"
14
15
  require "view_component/template"
@@ -25,10 +26,9 @@ module ViewComponent
25
26
  #
26
27
  # @return [ActiveSupport::OrderedOptions]
27
28
  def config
28
- module_parents.each do |module_parent|
29
- next unless module_parent.respond_to?(:config)
30
- module_parent_config = module_parent.config.try(:view_component)
31
- return module_parent_config if module_parent_config
29
+ module_parents.each do |m|
30
+ config = m.try(:config).try(:view_component)
31
+ return config if config
32
32
  end
33
33
  ViewComponent::Config.current
34
34
  end
@@ -40,9 +40,6 @@ module ViewComponent
40
40
  include ViewComponent::Translatable
41
41
  include ViewComponent::WithContentHelper
42
42
 
43
- RESERVED_PARAMETER = :content
44
- VC_INTERNAL_DEFAULT_FORMAT = :html
45
-
46
43
  # For CSRF authenticity tokens in forms
47
44
  delegate :form_authenticity_token, :protect_against_forgery?, :config, to: :helpers
48
45
 
@@ -50,8 +47,7 @@ module ViewComponent
50
47
  delegate :content_security_policy_nonce, to: :helpers
51
48
 
52
49
  # Config option that strips trailing whitespace in templates before compiling them.
53
- class_attribute :__vc_strip_trailing_whitespace, instance_accessor: false, instance_predicate: false
54
- self.__vc_strip_trailing_whitespace = false # class_attribute:default doesn't work until Rails 5.2
50
+ class_attribute :__vc_strip_trailing_whitespace, instance_accessor: false, instance_predicate: false, default: false
55
51
 
56
52
  attr_accessor :__vc_original_view_context
57
53
 
@@ -65,55 +61,41 @@ module ViewComponent
65
61
  # @param view_context [ActionView::Base] The original view context.
66
62
  # @return [void]
67
63
  def set_original_view_context(view_context)
68
- # Stash on a separate ivar that survives `__vc_reset_render_state!` so a
69
- # parent component can call `set_original_view_context` immediately before
70
- # `render_in` without having that value clobbered by the per-render reset.
71
- @__vc_pending_original_view_context = view_context
64
+ self.__vc_original_view_context = view_context
72
65
  end
73
66
 
67
+ using RequestDetails
68
+
74
69
  # Entrypoint for rendering components.
75
70
  #
76
71
  # - `view_context`: ActionView context from calling view
77
- # - `options`: optional render options (e.g., locals)
78
72
  # - `block`: optional block to be captured within the view context
79
73
  #
80
74
  # Returns HTML that has been escaped by the respective template handler.
81
75
  #
82
76
  # @return [String]
83
- def render_in(view_context, **options, &block)
84
- self.class.compile(raise_errors: true)
85
-
86
- __vc_check_reused_instance!
87
- __vc_reset_render_state!
77
+ def render_in(view_context, &block)
78
+ self.class.__vc_compile(raise_errors: true)
88
79
 
89
80
  @view_context = view_context
90
- self.__vc_original_view_context =
91
- if instance_variable_defined?(:@__vc_pending_original_view_context)
92
- remove_instance_variable(:@__vc_pending_original_view_context) || view_context
93
- else
94
- view_context
95
- end
81
+ self.__vc_original_view_context ||= view_context
96
82
 
97
83
  @output_buffer = ActionView::OutputBuffer.new
98
84
 
99
- @lookup_context = view_context.lookup_context
100
-
101
- # required for path helpers in older Rails versions
102
- @view_renderer = view_context.view_renderer
85
+ @lookup_context ||= view_context.lookup_context
103
86
 
104
87
  # For content_for
105
- @view_flow = view_context.view_flow
88
+ @view_flow ||= view_context.view_flow
106
89
 
107
90
  # For i18n
108
91
  @virtual_path ||= virtual_path
109
92
 
110
- # For template variants (+phone, +desktop, etc.)
111
- @__vc_variant = @lookup_context.variants.first
93
+ # Describes the inferred request constraints (locales, formats, variants)
94
+ @__vc_requested_details ||= @lookup_context.vc_requested_details
112
95
 
113
96
  # For caching, such as #cache_if
114
97
  @current_template = nil unless defined?(@current_template)
115
98
  old_current_template = @current_template
116
- @current_template = self
117
99
 
118
100
  if block && defined?(@__vc_content_set_by_with_content)
119
101
  raise DuplicateContentError.new(self.class.name)
@@ -125,7 +107,7 @@ module ViewComponent
125
107
  before_render
126
108
 
127
109
  if render?
128
- rendered_template = render_template_for(@__vc_variant, __vc_request&.format&.to_sym).to_s
110
+ rendered_template = render_template_for(@__vc_requested_details).to_s
129
111
 
130
112
  # Avoid allocating new string when output_preamble and output_postamble are blank
131
113
  if output_preamble.blank? && output_postamble.blank?
@@ -138,7 +120,6 @@ module ViewComponent
138
120
  end
139
121
  ensure
140
122
  @current_template = old_current_template
141
- @__vc_rendered = true
142
123
  end
143
124
 
144
125
  # Subclass components that call `super` inside their template code will cause a
@@ -174,7 +155,7 @@ module ViewComponent
174
155
  target_render = self.class.instance_variable_get(:@__vc_ancestor_calls)[@__vc_parent_render_level]
175
156
  @__vc_parent_render_level += 1
176
157
 
177
- target_render.bind_call(self, @__vc_variant)
158
+ target_render.bind_call(self, @__vc_requested_details)
178
159
  ensure
179
160
  @__vc_parent_render_level -= 1
180
161
  end
@@ -219,12 +200,12 @@ module ViewComponent
219
200
  #
220
201
  # This prevents an exception when rendering a partial inside of a component that has also been rendered outside
221
202
  # of the component. This is due to the partials compiled template method existing in the parent `view_context`,
222
- # and not the component's `view_context`.
203
+ # and not the component's `view_context`.
223
204
  #
224
205
  # @private
225
206
  def render(options = {}, args = {}, &block)
226
207
  if options.respond_to?(:set_original_view_context)
227
- options.set_original_view_context(__vc_original_view_context)
208
+ options.set_original_view_context(self.__vc_original_view_context)
228
209
  super
229
210
  else
230
211
  __vc_original_view_context.render(options, args, &block)
@@ -267,7 +248,7 @@ module ViewComponent
267
248
  raise e, <<~MESSAGE.chomp if view_context && e.is_a?(NameError) && helpers.respond_to?(method_name)
268
249
  #{e.message}
269
250
 
270
- You may be trying to call a method provided as a view helper. Did you mean `helpers.#{method_name}`?
251
+ You may be trying to call a method provided as a view helper. Did you mean `helpers.#{method_name}'?
271
252
  MESSAGE
272
253
 
273
254
  raise
@@ -287,13 +268,6 @@ module ViewComponent
287
268
  []
288
269
  end
289
270
 
290
- # For caching, such as #cache_if
291
- #
292
- # @private
293
- def format
294
- @__vc_variant if defined?(@__vc_variant)
295
- end
296
-
297
271
  # The current request. Use sparingly as doing so introduces coupling that
298
272
  # inhibits encapsulation & reuse, often making testing difficult.
299
273
  #
@@ -302,10 +276,9 @@ module ViewComponent
302
276
  __vc_request
303
277
  end
304
278
 
305
- # Enables consumers to override request/@request
306
- #
307
279
  # @private
308
280
  def __vc_request
281
+ # The current request (if present, as mailers/jobs/etc do not have a request)
309
282
  @__vc_request ||= controller.request if controller.respond_to?(:request)
310
283
  end
311
284
 
@@ -348,7 +321,7 @@ module ViewComponent
348
321
  end
349
322
 
350
323
  def maybe_escape_html(text)
351
- return text if __vc_request && !__vc_request.format.html?
324
+ return text if @current_template && !@current_template.html?
352
325
  return text if text.blank?
353
326
 
354
327
  if text.html_safe?
@@ -381,13 +354,6 @@ module ViewComponent
381
354
  # configured on a per-test basis using `with_controller_class`.
382
355
  #
383
356
 
384
- # Set if render monkey patches should be included or not in Rails <6.1:
385
- #
386
- # ```ruby
387
- # config.view_component.render_monkey_patch_enabled = false
388
- # ```
389
- #
390
-
391
357
  # Path for component files
392
358
  #
393
359
  # ```ruby
@@ -407,36 +373,6 @@ module ViewComponent
407
373
  # "ApplicationComponent" if defined, "ViewComponent::Base" otherwise.
408
374
  #
409
375
 
410
- # Resets every render-scoped instance variable derived from the calling view
411
- # context so a reused instance cannot leak controller/helper/request/format
412
- # state from a previous render. Slot state (`@__vc_set_slots`,
413
- # `@__vc_content_set_by_with_content`) is intentionally preserved because it
414
- # is populated by callers _before_ `render_in` runs (e.g. via `with_*`
415
- # slot setters or `with_content`); reuse of an instance that has slot or
416
- # `with_content` state is guarded against separately by
417
- # `__vc_check_reused_instance!`.
418
- def __vc_reset_render_state!
419
- %i[
420
- @__vc_controller
421
- @__vc_helpers
422
- @__vc_request
423
- @__vc_original_view_context
424
- ].each do |ivar|
425
- remove_instance_variable(ivar) if instance_variable_defined?(ivar)
426
- end
427
- end
428
-
429
- # Raises when a component instance is rendered more than once.
430
- # Reusing a component instance across renders can leak request-scoped state
431
- # (controller, helpers, request, view_flow, slot content, `with_content`)
432
- # from an earlier render into a later one. See
433
- # `ViewComponent::ReusedInstanceError` and GHSA-8qw7-6phv-7q6p.
434
- def __vc_check_reused_instance!
435
- return unless defined?(@__vc_rendered) && @__vc_rendered
436
-
437
- raise ReusedInstanceError.new(self.class.name)
438
- end
439
-
440
376
  # Configuration for generators.
441
377
  #
442
378
  # All options under this namespace default to `false` unless otherwise
@@ -566,20 +502,20 @@ module ViewComponent
566
502
  def inherited(child)
567
503
  # Compile so child will inherit compiled `call_*` template methods that
568
504
  # `compile` defines
569
- compile
505
+ __vc_compile
570
506
 
571
507
  # Give the child its own personal #render_template_for to protect against the case when
572
508
  # eager loading is disabled and the parent component is rendered before the child. In
573
509
  # such a scenario, the parent will override ViewComponent::Base#render_template_for,
574
510
  # meaning it will not be called for any children and thus not compile their templates.
575
- if !child.instance_methods(false).include?(:render_template_for) && !child.compiled?
511
+ if !child.instance_methods(false).include?(:render_template_for) && !child.__vc_compiled?
576
512
  child.class_eval <<~RUBY, __FILE__, __LINE__ + 1
577
- def render_template_for(variant = nil, format = nil)
513
+ def render_template_for(requested_details)
578
514
  # Force compilation here so the compiler always redefines render_template_for.
579
515
  # This is mostly a safeguard to prevent infinite recursion.
580
- self.class.compile(raise_errors: true, force: true)
581
- # .compile replaces this method; call the new one
582
- render_template_for(variant, format)
516
+ self.class.__vc_compile(raise_errors: true, force: true)
517
+ # .__vc_compile replaces this method; call the new one
518
+ render_template_for(requested_details)
583
519
  end
584
520
  RUBY
585
521
  end
@@ -618,22 +554,22 @@ module ViewComponent
618
554
  end
619
555
 
620
556
  # @private
621
- def compiled?
622
- compiler.compiled?
557
+ def __vc_compiled?
558
+ __vc_compiler.compiled?
623
559
  end
624
560
 
625
561
  # @private
626
- def ensure_compiled
627
- compile unless compiled?
562
+ def __vc_ensure_compiled
563
+ __vc_compile unless __vc_compiled?
628
564
  end
629
565
 
630
566
  # @private
631
- def compile(raise_errors: false, force: false)
632
- compiler.compile(raise_errors: raise_errors, force: force)
567
+ def __vc_compile(raise_errors: false, force: false)
568
+ __vc_compiler.compile(raise_errors: raise_errors, force: force)
633
569
  end
634
570
 
635
571
  # @private
636
- def compiler
572
+ def __vc_compiler
637
573
  @__vc_compiler ||= Compiler.new(self)
638
574
  end
639
575
 
@@ -675,8 +611,8 @@ module ViewComponent
675
611
  # is accepted, as support for collection
676
612
  # rendering is optional.
677
613
  # @private
678
- def validate_collection_parameter!(validate_default: false)
679
- parameter = validate_default ? collection_parameter : provided_collection_parameter
614
+ def __vc_validate_collection_parameter!(validate_default: false)
615
+ parameter = validate_default ? __vc_collection_parameter : provided_collection_parameter
680
616
 
681
617
  return unless parameter
682
618
  return if initialize_parameter_names.include?(parameter) || splatted_keyword_argument_present?
@@ -695,35 +631,35 @@ module ViewComponent
695
631
  # invalid parameters that could override the framework's
696
632
  # methods.
697
633
  # @private
698
- def validate_initialization_parameters!
699
- return unless initialize_parameter_names.include?(RESERVED_PARAMETER)
634
+ def __vc_validate_initialization_parameters!
635
+ return unless initialize_parameter_names.include?(:content)
700
636
 
701
- raise ReservedParameterError.new(name, RESERVED_PARAMETER)
637
+ raise ReservedParameterError.new(name, :content)
702
638
  end
703
639
 
704
640
  # @private
705
- def collection_parameter
641
+ def __vc_collection_parameter
706
642
  provided_collection_parameter || name && name.demodulize.underscore.chomp("_component").to_sym
707
643
  end
708
644
 
709
645
  # @private
710
- def collection_counter_parameter
711
- :"#{collection_parameter}_counter"
646
+ def __vc_collection_counter_parameter
647
+ :"#{__vc_collection_parameter}_counter"
712
648
  end
713
649
 
714
650
  # @private
715
- def counter_argument_present?
716
- initialize_parameter_names.include?(collection_counter_parameter)
651
+ def __vc_counter_argument_present?
652
+ initialize_parameter_names.include?(__vc_collection_counter_parameter)
717
653
  end
718
654
 
719
655
  # @private
720
- def collection_iteration_parameter
721
- :"#{collection_parameter}_iteration"
656
+ def __vc_collection_iteration_parameter
657
+ :"#{__vc_collection_parameter}_iteration"
722
658
  end
723
659
 
724
660
  # @private
725
- def iteration_argument_present?
726
- initialize_parameter_names.include?(collection_iteration_parameter)
661
+ def __vc_iteration_argument_present?
662
+ initialize_parameter_names.include?(__vc_collection_iteration_parameter)
727
663
  end
728
664
 
729
665
  private
@@ -736,8 +672,6 @@ module ViewComponent
736
672
  def initialize_parameter_names
737
673
  return attribute_names.map(&:to_sym) if respond_to?(:attribute_names)
738
674
 
739
- return attribute_types.keys.map(&:to_sym) if Rails::VERSION::MAJOR <= 5 && respond_to?(:attribute_types)
740
-
741
675
  initialize_parameters.map(&:last)
742
676
  end
743
677