view_component 3.21.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.
- checksums.yaml +4 -4
- data/app/controllers/concerns/view_component/preview_actions.rb +1 -1
- data/app/controllers/view_components_system_test_controller.rb +17 -20
- data/app/views/test_mailer/test_asset_email.html.erb +1 -0
- data/app/views/view_components/preview.html.erb +1 -9
- data/docs/CHANGELOG.md +171 -1
- data/lib/view_component/base.rb +45 -61
- data/lib/view_component/collection.rb +11 -17
- data/lib/view_component/compiler.rb +50 -74
- data/lib/view_component/config.rb +0 -21
- data/lib/view_component/configurable.rb +17 -0
- data/lib/view_component/deprecation.rb +1 -1
- data/lib/view_component/engine.rb +3 -82
- data/lib/view_component/errors.rb +19 -25
- data/lib/view_component/inline_template.rb +2 -3
- data/lib/view_component/instrumentation.rb +4 -10
- data/lib/view_component/preview.rb +3 -10
- data/lib/view_component/request_details.rb +30 -0
- data/lib/view_component/slot.rb +2 -5
- data/lib/view_component/slotable.rb +31 -39
- data/lib/view_component/system_test_helpers.rb +1 -2
- data/lib/view_component/template.rb +106 -83
- data/lib/view_component/test_helpers.rb +22 -42
- data/lib/view_component/translatable.rb +24 -23
- data/lib/view_component/use_helpers.rb +3 -4
- data/lib/view_component/version.rb +3 -3
- data/lib/view_component.rb +0 -1
- metadata +76 -213
- data/app/assets/vendor/prism.css +0 -4
- data/app/assets/vendor/prism.min.js +0 -12
- data/app/helpers/preview_helper.rb +0 -85
- data/app/views/view_components/_preview_source.html.erb +0 -17
- data/lib/rails/generators/abstract_generator.rb +0 -56
- data/lib/rails/generators/component/USAGE +0 -13
- data/lib/rails/generators/component/component_generator.rb +0 -67
- data/lib/rails/generators/component/templates/component.rb.tt +0 -16
- data/lib/rails/generators/erb/component_generator.rb +0 -33
- data/lib/rails/generators/erb/templates/component.html.erb.tt +0 -1
- data/lib/rails/generators/haml/component_generator.rb +0 -22
- data/lib/rails/generators/haml/templates/component.html.haml.tt +0 -1
- data/lib/rails/generators/locale/component_generator.rb +0 -46
- data/lib/rails/generators/preview/component_generator.rb +0 -39
- data/lib/rails/generators/preview/templates/component_preview.rb.tt +0 -9
- data/lib/rails/generators/rspec/component_generator.rb +0 -31
- data/lib/rails/generators/rspec/templates/component_spec.rb.tt +0 -15
- data/lib/rails/generators/slim/component_generator.rb +0 -22
- data/lib/rails/generators/slim/templates/component.html.slim.tt +0 -1
- data/lib/rails/generators/stimulus/component_generator.rb +0 -44
- data/lib/rails/generators/stimulus/templates/component_controller.js.tt +0 -7
- data/lib/rails/generators/stimulus/templates/component_controller.ts.tt +0 -9
- data/lib/rails/generators/tailwindcss/component_generator.rb +0 -11
- data/lib/rails/generators/tailwindcss/templates/component.html.erb.tt +0 -1
- data/lib/rails/generators/test_unit/component_generator.rb +0 -20
- data/lib/rails/generators/test_unit/templates/component_test.rb.tt +0 -12
- data/lib/view_component/component_error.rb +0 -6
- data/lib/view_component/docs_builder_component.html.erb +0 -22
- data/lib/view_component/docs_builder_component.rb +0 -96
- data/lib/view_component/rails/tasks/view_component.rake +0 -20
- data/lib/view_component/render_component_helper.rb +0 -10
- data/lib/view_component/render_component_to_string_helper.rb +0 -9
- data/lib/view_component/render_monkey_patch.rb +0 -13
- data/lib/view_component/render_to_string_monkey_patch.rb +0 -13
- data/lib/view_component/rendering_component_helper.rb +0 -9
- data/lib/view_component/rendering_monkey_patch.rb +0 -13
- data/lib/yard/mattr_accessor_handler.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8c0d5be4a21f5c14ed5447caeaffb8d6e51397a1ec786f573bc58d9486fc747
|
4
|
+
data.tar.gz: 332de180e52e1b5eae806fb47e9d1dea4a32374cdf63a0642ca69d3661e4c802
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e298e8e18d147034b30fb60f32a7bbf5d5f42d1235d5947cfeba4e3e1b8ad65a57379f3a3fb361ba7ffdec727687689ceb98b4b893e038a16ea5496663d4423a
|
7
|
+
data.tar.gz: f6e8f8956abde8eac1e4825c09a2554dde1dd80efac74ba541210e2fe663e23399ddc01289ca44dee21e6c3551b32117b88444d9795fbb450b02639ebc9fadbf
|
@@ -10,7 +10,7 @@ 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)
|
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
|
@@ -1,30 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class ViewComponentsSystemTestController < ActionController::Base # :nodoc:
|
4
|
-
|
5
|
-
|
4
|
+
if Rails.env.test?
|
5
|
+
before_action :validate_file_path
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def system_test_entrypoint
|
12
|
-
render file: @path
|
13
|
-
end
|
7
|
+
def self.temp_dir
|
8
|
+
@_tmpdir ||= FileUtils.mkdir_p("./tmp/view_components/").first
|
9
|
+
end
|
14
10
|
|
15
|
-
|
11
|
+
def system_test_entrypoint
|
12
|
+
render file: @path
|
13
|
+
end
|
16
14
|
|
17
|
-
|
18
|
-
raise ViewComponent::SystemTestControllerOnlyAllowedInTestError unless Rails.env.test?
|
19
|
-
end
|
15
|
+
private
|
20
16
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
28
25
|
end
|
29
26
|
end
|
30
27
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render AssetComponent.new %>
|
@@ -1,13 +1,5 @@
|
|
1
1
|
<% if @render_args[:component] %>
|
2
|
-
|
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
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
layout: default
|
3
3
|
title: Changelog
|
4
|
-
nav_order:
|
4
|
+
nav_order: 6
|
5
5
|
---
|
6
6
|
|
7
7
|
<!-- Add unreleased changes under the "main" heading. -->
|
@@ -10,6 +10,172 @@ nav_order: 5
|
|
10
10
|
|
11
11
|
## main
|
12
12
|
|
13
|
+
## 4.0.0
|
14
|
+
|
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
|
+
|
17
|
+
This release makes the following breaking changes:
|
18
|
+
|
19
|
+
* BREAKING: `--inline` generator option now generates inline template. Use `--call` to generate `#call` method.
|
20
|
+
|
21
|
+
*Joel Hawksley*
|
22
|
+
|
23
|
+
* BREAKING: Remove `use_deprecated_instrumentation_name` configuration option. Events will always use `render.view_component` name.
|
24
|
+
|
25
|
+
*Joel Hawksley*
|
26
|
+
|
27
|
+
* BREAKING: Remove `preview_source` functionality. Consider using [Lookbook](https://lookbook.build/) instead.
|
28
|
+
|
29
|
+
*Joel Hawksley*
|
30
|
+
|
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*
|
43
|
+
|
44
|
+
* BREAKING: Require [non-EOL](https://endoflife.date/rails) Rails (`>= 7.1.0`).
|
45
|
+
|
46
|
+
*Joel Hawksley*
|
47
|
+
|
48
|
+
* BREAKING: Require [non-EOL](https://www.ruby-lang.org/en/downloads/branches/) Ruby (`>= 3.2.0`).
|
49
|
+
|
50
|
+
*Joel Hawksley*
|
51
|
+
|
52
|
+
* BREAKING: Remove `render_component` and `render` monkey patch configured with `render_monkey_patch_enabled`.
|
53
|
+
|
54
|
+
*Joel Hawksley*
|
55
|
+
|
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.
|
72
|
+
|
73
|
+
*Joel Hawksley*
|
74
|
+
|
75
|
+
* Fix bug where request-aware helpers did not work outside of the request context.
|
76
|
+
|
77
|
+
*Joel Hawksley*, *Stephen Nelson*
|
78
|
+
|
79
|
+
* `ViewComponentsSystemTestController` should not be useable outside of test environment
|
80
|
+
|
81
|
+
*Joel Hawksley*, *Stephen Nelson*
|
82
|
+
|
83
|
+
* Remove unnecessary ENABLE_RELOADING test suite flag.
|
84
|
+
|
85
|
+
*Joel Hawksley*
|
86
|
+
|
87
|
+
* Add test coverage for uncovered code.
|
88
|
+
|
89
|
+
*Joel Hawksley*
|
90
|
+
|
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`.
|
100
|
+
|
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*
|
110
|
+
|
111
|
+
* Remove unnecessary `respond_to` checks.
|
112
|
+
|
113
|
+
*Tiago Menegaz*, *Joel Hawksley*
|
114
|
+
|
115
|
+
* Do not include internal `DocsBuilderComponent` or `YARD::MattrAccessorHandler` in published gem.
|
116
|
+
|
117
|
+
*Joel Hawksley*
|
118
|
+
|
119
|
+
* Only lock to `concurrent-ruby` `1.3.4` for Rails 6.1.
|
120
|
+
|
121
|
+
*Joel Hawksley*
|
122
|
+
|
123
|
+
* Fix generation of ViewComponent documentation that was broken due to HTML safety issues.
|
124
|
+
|
125
|
+
*Simon Fish*
|
126
|
+
|
127
|
+
* Add documentation on how ViewComponent works.
|
128
|
+
|
129
|
+
*Joel Hawksley*
|
130
|
+
|
131
|
+
* Clarify that `config.use_deprecated_instrumentation_name` will be removed in v4.
|
132
|
+
|
133
|
+
*Joel Hawksley*
|
134
|
+
|
135
|
+
* Run RSpec tests in CI.
|
136
|
+
|
137
|
+
*Joel Hawksley*
|
138
|
+
|
139
|
+
## 3.22.0
|
140
|
+
|
141
|
+
* Rewrite `ViewComponents at GitHub` documentation as more general `Best practices`.
|
142
|
+
|
143
|
+
*Phil Schalm*, *Joel Hawksley*
|
144
|
+
|
145
|
+
* Add unused mechanism for inheriting config from parent modules to enable future engine-local configuration.
|
146
|
+
|
147
|
+
*Simon Fish*
|
148
|
+
|
149
|
+
* Improve handling of malformed component edge case when mocking components in tests.
|
150
|
+
|
151
|
+
*Martin Meyerhoff*, *Joel Hawksley*
|
152
|
+
|
153
|
+
* Add Content Harmony & Learn To Be to list of companies using ViewComponent.
|
154
|
+
|
155
|
+
*Kane Jamison*
|
156
|
+
|
157
|
+
* Clarify error message about render-dependent logic.
|
158
|
+
|
159
|
+
Error messages about render-dependent logic were sometimes inaccurate, saying `during initialization` despite also being raised after a component had been initialized but before it was rendered.
|
160
|
+
|
161
|
+
*Joel Hawksley*
|
162
|
+
|
163
|
+
* Remove JS and CSS docs as they proved difficult to maintain and lacked consensus.
|
164
|
+
|
165
|
+
*Joel Hawksley*
|
166
|
+
|
167
|
+
* Do not prefix release tags with `v`, per recommendation from @bkuhlmann.
|
168
|
+
|
169
|
+
*Joel Hawksley*
|
170
|
+
|
171
|
+
* Add ruby 3.4 support to CI.
|
172
|
+
|
173
|
+
*Reegan Viljoen*
|
174
|
+
|
175
|
+
* Add HomeStyler AI to list of companies using ViewComponent.
|
176
|
+
|
177
|
+
*JP Balarini*
|
178
|
+
|
13
179
|
## 3.21.0
|
14
180
|
|
15
181
|
* Updates testing docs to include an example of how to use with RSpec.
|
@@ -218,6 +384,10 @@ nav_order: 5
|
|
218
384
|
|
219
385
|
*Reegan Viljoen*
|
220
386
|
|
387
|
+
* Fix a bug where component previews would crash with "undefined local variable or method `preview_source`."
|
388
|
+
|
389
|
+
*Henning Koch*
|
390
|
+
|
221
391
|
## 3.12.1
|
222
392
|
|
223
393
|
* Ensure content is rendered correctly for forwarded slots.
|
data/lib/view_component/base.rb
CHANGED
@@ -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,6 +26,10 @@ module ViewComponent
|
|
25
26
|
#
|
26
27
|
# @return [ActiveSupport::OrderedOptions]
|
27
28
|
def config
|
29
|
+
module_parents.each do |m|
|
30
|
+
config = m.try(:config).try(:view_component)
|
31
|
+
return config if config
|
32
|
+
end
|
28
33
|
ViewComponent::Config.current
|
29
34
|
end
|
30
35
|
end
|
@@ -35,9 +40,6 @@ module ViewComponent
|
|
35
40
|
include ViewComponent::Translatable
|
36
41
|
include ViewComponent::WithContentHelper
|
37
42
|
|
38
|
-
RESERVED_PARAMETER = :content
|
39
|
-
VC_INTERNAL_DEFAULT_FORMAT = :html
|
40
|
-
|
41
43
|
# For CSRF authenticity tokens in forms
|
42
44
|
delegate :form_authenticity_token, :protect_against_forgery?, :config, to: :helpers
|
43
45
|
|
@@ -45,8 +47,7 @@ module ViewComponent
|
|
45
47
|
delegate :content_security_policy_nonce, to: :helpers
|
46
48
|
|
47
49
|
# Config option that strips trailing whitespace in templates before compiling them.
|
48
|
-
class_attribute :__vc_strip_trailing_whitespace, instance_accessor: false, instance_predicate: false
|
49
|
-
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
|
50
51
|
|
51
52
|
attr_accessor :__vc_original_view_context
|
52
53
|
|
@@ -63,6 +64,8 @@ module ViewComponent
|
|
63
64
|
self.__vc_original_view_context = view_context
|
64
65
|
end
|
65
66
|
|
67
|
+
using RequestDetails
|
68
|
+
|
66
69
|
# Entrypoint for rendering components.
|
67
70
|
#
|
68
71
|
# - `view_context`: ActionView context from calling view
|
@@ -72,7 +75,7 @@ module ViewComponent
|
|
72
75
|
#
|
73
76
|
# @return [String]
|
74
77
|
def render_in(view_context, &block)
|
75
|
-
self.class.
|
78
|
+
self.class.__vc_compile(raise_errors: true)
|
76
79
|
|
77
80
|
@view_context = view_context
|
78
81
|
self.__vc_original_view_context ||= view_context
|
@@ -81,22 +84,18 @@ module ViewComponent
|
|
81
84
|
|
82
85
|
@lookup_context ||= view_context.lookup_context
|
83
86
|
|
84
|
-
# required for path helpers in older Rails versions
|
85
|
-
@view_renderer ||= view_context.view_renderer
|
86
|
-
|
87
87
|
# For content_for
|
88
88
|
@view_flow ||= view_context.view_flow
|
89
89
|
|
90
90
|
# For i18n
|
91
91
|
@virtual_path ||= virtual_path
|
92
92
|
|
93
|
-
#
|
94
|
-
@
|
93
|
+
# Describes the inferred request constraints (locales, formats, variants)
|
94
|
+
@__vc_requested_details ||= @lookup_context.vc_requested_details
|
95
95
|
|
96
96
|
# For caching, such as #cache_if
|
97
97
|
@current_template = nil unless defined?(@current_template)
|
98
98
|
old_current_template = @current_template
|
99
|
-
@current_template = self
|
100
99
|
|
101
100
|
if block && defined?(@__vc_content_set_by_with_content)
|
102
101
|
raise DuplicateContentError.new(self.class.name)
|
@@ -108,7 +107,7 @@ module ViewComponent
|
|
108
107
|
before_render
|
109
108
|
|
110
109
|
if render?
|
111
|
-
rendered_template = render_template_for(@
|
110
|
+
rendered_template = render_template_for(@__vc_requested_details).to_s
|
112
111
|
|
113
112
|
# Avoid allocating new string when output_preamble and output_postamble are blank
|
114
113
|
if output_preamble.blank? && output_postamble.blank?
|
@@ -156,7 +155,7 @@ module ViewComponent
|
|
156
155
|
target_render = self.class.instance_variable_get(:@__vc_ancestor_calls)[@__vc_parent_render_level]
|
157
156
|
@__vc_parent_render_level += 1
|
158
157
|
|
159
|
-
target_render.bind_call(self, @
|
158
|
+
target_render.bind_call(self, @__vc_requested_details)
|
160
159
|
ensure
|
161
160
|
@__vc_parent_render_level -= 1
|
162
161
|
end
|
@@ -191,6 +190,8 @@ module ViewComponent
|
|
191
190
|
true
|
192
191
|
end
|
193
192
|
|
193
|
+
# Override the ActionView::Base initializer so that components
|
194
|
+
# do not need to define their own initializers.
|
194
195
|
# @private
|
195
196
|
def initialize(*)
|
196
197
|
end
|
@@ -199,7 +200,7 @@ module ViewComponent
|
|
199
200
|
#
|
200
201
|
# This prevents an exception when rendering a partial inside of a component that has also been rendered outside
|
201
202
|
# of the component. This is due to the partials compiled template method existing in the parent `view_context`,
|
202
|
-
#
|
203
|
+
# and not the component's `view_context`.
|
203
204
|
#
|
204
205
|
# @private
|
205
206
|
def render(options = {}, args = {}, &block)
|
@@ -267,13 +268,6 @@ module ViewComponent
|
|
267
268
|
[]
|
268
269
|
end
|
269
270
|
|
270
|
-
# For caching, such as #cache_if
|
271
|
-
#
|
272
|
-
# @private
|
273
|
-
def format
|
274
|
-
@__vc_variant if defined?(@__vc_variant)
|
275
|
-
end
|
276
|
-
|
277
271
|
# The current request. Use sparingly as doing so introduces coupling that
|
278
272
|
# inhibits encapsulation & reuse, often making testing difficult.
|
279
273
|
#
|
@@ -282,10 +276,9 @@ module ViewComponent
|
|
282
276
|
__vc_request
|
283
277
|
end
|
284
278
|
|
285
|
-
# Enables consumers to override request/@request
|
286
|
-
#
|
287
279
|
# @private
|
288
280
|
def __vc_request
|
281
|
+
# The current request (if present, as mailers/jobs/etc do not have a request)
|
289
282
|
@__vc_request ||= controller.request if controller.respond_to?(:request)
|
290
283
|
end
|
291
284
|
|
@@ -328,7 +321,7 @@ module ViewComponent
|
|
328
321
|
end
|
329
322
|
|
330
323
|
def maybe_escape_html(text)
|
331
|
-
return text if
|
324
|
+
return text if @current_template && !@current_template.html?
|
332
325
|
return text if text.blank?
|
333
326
|
|
334
327
|
if text.html_safe?
|
@@ -361,13 +354,6 @@ module ViewComponent
|
|
361
354
|
# configured on a per-test basis using `with_controller_class`.
|
362
355
|
#
|
363
356
|
|
364
|
-
# Set if render monkey patches should be included or not in Rails <6.1:
|
365
|
-
#
|
366
|
-
# ```ruby
|
367
|
-
# config.view_component.render_monkey_patch_enabled = false
|
368
|
-
# ```
|
369
|
-
#
|
370
|
-
|
371
357
|
# Path for component files
|
372
358
|
#
|
373
359
|
# ```ruby
|
@@ -516,20 +502,20 @@ module ViewComponent
|
|
516
502
|
def inherited(child)
|
517
503
|
# Compile so child will inherit compiled `call_*` template methods that
|
518
504
|
# `compile` defines
|
519
|
-
|
505
|
+
__vc_compile
|
520
506
|
|
521
507
|
# Give the child its own personal #render_template_for to protect against the case when
|
522
508
|
# eager loading is disabled and the parent component is rendered before the child. In
|
523
509
|
# such a scenario, the parent will override ViewComponent::Base#render_template_for,
|
524
510
|
# meaning it will not be called for any children and thus not compile their templates.
|
525
|
-
if !child.instance_methods(false).include?(:render_template_for) && !child.
|
511
|
+
if !child.instance_methods(false).include?(:render_template_for) && !child.__vc_compiled?
|
526
512
|
child.class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
527
|
-
def render_template_for(
|
513
|
+
def render_template_for(requested_details)
|
528
514
|
# Force compilation here so the compiler always redefines render_template_for.
|
529
515
|
# This is mostly a safeguard to prevent infinite recursion.
|
530
|
-
self.class.
|
531
|
-
# .
|
532
|
-
render_template_for(
|
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)
|
533
519
|
end
|
534
520
|
RUBY
|
535
521
|
end
|
@@ -568,22 +554,22 @@ module ViewComponent
|
|
568
554
|
end
|
569
555
|
|
570
556
|
# @private
|
571
|
-
def
|
572
|
-
|
557
|
+
def __vc_compiled?
|
558
|
+
__vc_compiler.compiled?
|
573
559
|
end
|
574
560
|
|
575
561
|
# @private
|
576
|
-
def
|
577
|
-
|
562
|
+
def __vc_ensure_compiled
|
563
|
+
__vc_compile unless __vc_compiled?
|
578
564
|
end
|
579
565
|
|
580
566
|
# @private
|
581
|
-
def
|
582
|
-
|
567
|
+
def __vc_compile(raise_errors: false, force: false)
|
568
|
+
__vc_compiler.compile(raise_errors: raise_errors, force: force)
|
583
569
|
end
|
584
570
|
|
585
571
|
# @private
|
586
|
-
def
|
572
|
+
def __vc_compiler
|
587
573
|
@__vc_compiler ||= Compiler.new(self)
|
588
574
|
end
|
589
575
|
|
@@ -625,8 +611,8 @@ module ViewComponent
|
|
625
611
|
# is accepted, as support for collection
|
626
612
|
# rendering is optional.
|
627
613
|
# @private
|
628
|
-
def
|
629
|
-
parameter = validate_default ?
|
614
|
+
def __vc_validate_collection_parameter!(validate_default: false)
|
615
|
+
parameter = validate_default ? __vc_collection_parameter : provided_collection_parameter
|
630
616
|
|
631
617
|
return unless parameter
|
632
618
|
return if initialize_parameter_names.include?(parameter) || splatted_keyword_argument_present?
|
@@ -645,35 +631,35 @@ module ViewComponent
|
|
645
631
|
# invalid parameters that could override the framework's
|
646
632
|
# methods.
|
647
633
|
# @private
|
648
|
-
def
|
649
|
-
return unless initialize_parameter_names.include?(
|
634
|
+
def __vc_validate_initialization_parameters!
|
635
|
+
return unless initialize_parameter_names.include?(:content)
|
650
636
|
|
651
|
-
raise ReservedParameterError.new(name,
|
637
|
+
raise ReservedParameterError.new(name, :content)
|
652
638
|
end
|
653
639
|
|
654
640
|
# @private
|
655
|
-
def
|
641
|
+
def __vc_collection_parameter
|
656
642
|
provided_collection_parameter || name && name.demodulize.underscore.chomp("_component").to_sym
|
657
643
|
end
|
658
644
|
|
659
645
|
# @private
|
660
|
-
def
|
661
|
-
:"#{
|
646
|
+
def __vc_collection_counter_parameter
|
647
|
+
:"#{__vc_collection_parameter}_counter"
|
662
648
|
end
|
663
649
|
|
664
650
|
# @private
|
665
|
-
def
|
666
|
-
initialize_parameter_names.include?(
|
651
|
+
def __vc_counter_argument_present?
|
652
|
+
initialize_parameter_names.include?(__vc_collection_counter_parameter)
|
667
653
|
end
|
668
654
|
|
669
655
|
# @private
|
670
|
-
def
|
671
|
-
:"#{
|
656
|
+
def __vc_collection_iteration_parameter
|
657
|
+
:"#{__vc_collection_parameter}_iteration"
|
672
658
|
end
|
673
659
|
|
674
660
|
# @private
|
675
|
-
def
|
676
|
-
initialize_parameter_names.include?(
|
661
|
+
def __vc_iteration_argument_present?
|
662
|
+
initialize_parameter_names.include?(__vc_collection_iteration_parameter)
|
677
663
|
end
|
678
664
|
|
679
665
|
private
|
@@ -686,8 +672,6 @@ module ViewComponent
|
|
686
672
|
def initialize_parameter_names
|
687
673
|
return attribute_names.map(&:to_sym) if respond_to?(:attribute_names)
|
688
674
|
|
689
|
-
return attribute_types.keys.map(&:to_sym) if Rails::VERSION::MAJOR <= 5 && respond_to?(:attribute_types)
|
690
|
-
|
691
675
|
initialize_parameters.map(&:last)
|
692
676
|
end
|
693
677
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "action_view/renderer/collection_renderer"
|
3
|
+
require "action_view/renderer/collection_renderer"
|
4
4
|
|
5
5
|
module ViewComponent
|
6
6
|
class Collection
|
@@ -22,12 +22,18 @@ module ViewComponent
|
|
22
22
|
end.join(rendered_spacer(view_context)).html_safe
|
23
23
|
end
|
24
24
|
|
25
|
+
def each(&block)
|
26
|
+
components.each(&block)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
25
31
|
def components
|
26
32
|
return @components if defined? @components
|
27
33
|
|
28
34
|
iterator = ActionView::PartialIteration.new(@collection.size)
|
29
35
|
|
30
|
-
component.
|
36
|
+
component.__vc_validate_collection_parameter!(validate_default: true)
|
31
37
|
|
32
38
|
@components = @collection.map do |item|
|
33
39
|
component.new(**component_options(item, iterator)).tap do |component|
|
@@ -36,18 +42,6 @@ module ViewComponent
|
|
36
42
|
end
|
37
43
|
end
|
38
44
|
|
39
|
-
def each(&block)
|
40
|
-
components.each(&block)
|
41
|
-
end
|
42
|
-
|
43
|
-
# Rails expects us to define `format` on all renderables,
|
44
|
-
# but we do not know the `format` of a ViewComponent until runtime.
|
45
|
-
def format
|
46
|
-
nil
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
45
|
def initialize(component, object, spacer_component, **options)
|
52
46
|
@component = component
|
53
47
|
@collection = collection_variable(object || [])
|
@@ -64,9 +58,9 @@ module ViewComponent
|
|
64
58
|
end
|
65
59
|
|
66
60
|
def component_options(item, iterator)
|
67
|
-
item_options = {component.
|
68
|
-
item_options[component.
|
69
|
-
item_options[component.
|
61
|
+
item_options = {component.__vc_collection_parameter => item}
|
62
|
+
item_options[component.__vc_collection_counter_parameter] = iterator.index if component.__vc_counter_argument_present?
|
63
|
+
item_options[component.__vc_collection_iteration_parameter] = iterator.dup if component.__vc_iteration_argument_present?
|
70
64
|
|
71
65
|
@options.merge(item_options)
|
72
66
|
end
|