view_component 2.82.0 → 3.0.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/view_components_system_test_controller.rb +24 -1
- data/app/helpers/preview_helper.rb +2 -4
- data/docs/CHANGELOG.md +278 -0
- data/lib/view_component/base.rb +41 -92
- data/lib/view_component/capture_compatibility.rb +44 -0
- data/lib/view_component/collection.rb +2 -5
- data/lib/view_component/compiler.rb +51 -28
- data/lib/view_component/config.rb +9 -13
- data/lib/view_component/deprecation.rb +1 -1
- data/lib/view_component/docs_builder_component.html.erb +5 -1
- data/lib/view_component/docs_builder_component.rb +28 -9
- data/lib/view_component/engine.rb +12 -22
- data/lib/view_component/errors.rb +213 -0
- data/lib/view_component/inline_template.rb +55 -0
- data/lib/view_component/preview.rb +1 -7
- data/lib/view_component/rails/tasks/view_component.rake +1 -1
- data/lib/view_component/slot.rb +107 -1
- data/lib/view_component/slotable.rb +356 -96
- data/lib/view_component/system_test_helpers.rb +5 -5
- data/lib/view_component/test_helpers.rb +67 -54
- data/lib/view_component/translatable.rb +35 -23
- data/lib/view_component/version.rb +4 -3
- data/lib/view_component/with_content_helper.rb +3 -8
- data/lib/view_component.rb +3 -12
- metadata +28 -17
- data/lib/view_component/content_areas.rb +0 -56
- data/lib/view_component/polymorphic_slots.rb +0 -103
- data/lib/view_component/preview_template_error.rb +0 -6
- data/lib/view_component/slot_v2.rb +0 -98
- data/lib/view_component/slotable_v2.rb +0 -391
- data/lib/view_component/template_error.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 639cd1c50a78567738c9d90363e98cb740f1f45ca70c9cb7ea20d22aacbce6e9
|
4
|
+
data.tar.gz: cbec2597e6193dcb43ddab199d1147977d505dd320b765ed38eb11f877917f23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b26863964af13fd7c3bca798f4acd88c87709965badda42b02fe8125151f6e91b879e5118551d5b4c041509bbe26c2d463fcd4470bf6cbe5f946bc99c34f6a9c
|
7
|
+
data.tar.gz: e170eae333570563f5e068e8cbc1c4cfab05363671a9691169eaa2cbb30202076d38d8b59b8d7b28a73ab8777542c9173455e6f828f5f7344a3213424a69d049
|
@@ -1,7 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class ViewComponentsSystemTestController < ActionController::Base # :nodoc:
|
4
|
+
before_action :validate_test_env
|
5
|
+
before_action :validate_file_path
|
6
|
+
|
7
|
+
def self.temp_dir
|
8
|
+
@_tmpdir ||= FileUtils.mkdir_p("./tmp/view_components/").first
|
9
|
+
end
|
10
|
+
|
4
11
|
def system_test_entrypoint
|
5
|
-
render file:
|
12
|
+
render file: @path
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def validate_test_env
|
18
|
+
raise ViewComponent::SystemTestControllerOnlyAllowedInTestError unless Rails.env.test?
|
19
|
+
end
|
20
|
+
|
21
|
+
# Ensure that the file path is valid and doesn't target files outside
|
22
|
+
# the expected directory (e.g. via a path traversal or symlink attack)
|
23
|
+
def validate_file_path
|
24
|
+
base_path = ::File.realpath(self.class.temp_dir)
|
25
|
+
@path = ::File.realpath(params.permit(:file)[:file], base_path)
|
26
|
+
unless @path.start_with?(base_path)
|
27
|
+
raise ViewComponent::SystemTestControllerNefariousPathError
|
28
|
+
end
|
6
29
|
end
|
7
30
|
end
|
@@ -31,10 +31,8 @@ module PreviewHelper
|
|
31
31
|
path =~ /#{template_identifier}*.(html)/
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
raise "found 0 matches for templates for #{template_identifier}." if matching_templates.empty?
|
37
|
-
raise "found multiple templates for #{template_identifier}." if matching_templates.size > 1
|
34
|
+
raise ViewComponent::NoMatchingTemplatesForPreviewError.new(template_identifier) if matching_templates.empty?
|
35
|
+
raise ViewComponent::MultipleMatchingTemplatesForPreviewError.new(template_identifier) if matching_templates.size > 1
|
38
36
|
|
39
37
|
template_file_path = matching_templates.first
|
40
38
|
template_source = File.read(template_file_path)
|
data/docs/CHANGELOG.md
CHANGED
@@ -10,6 +10,284 @@ nav_order: 5
|
|
10
10
|
|
11
11
|
## main
|
12
12
|
|
13
|
+
### v3.0.0
|
14
|
+
|
15
|
+
1,000+ days and 100+ releases later, the 200+ contributors to ViewComponent are proud to ship v3.0.0!
|
16
|
+
|
17
|
+
We're so grateful for all the work of community members to get us to this release. Whether it’s filing bug reports, designing APIs in long-winded discussion threads, or writing code itself, ViewComponent is built by the community, for the community. We couldn’t be more proud of what we’re building together :heart:
|
18
|
+
|
19
|
+
This release makes the following breaking changes, many of which have long been deprecated:
|
20
|
+
|
21
|
+
* BREAKING: Remove deprecated slots setter methods. Use `with_SLOT_NAME` instead.
|
22
|
+
|
23
|
+
*Joel Hawksley*
|
24
|
+
|
25
|
+
* BREAKING: Remove deprecated SlotsV1 in favor of current SlotsV2.
|
26
|
+
|
27
|
+
*Joel Hawksley*
|
28
|
+
|
29
|
+
* BREAKING: Remove deprecated `content_areas` feature. Use Slots instead.
|
30
|
+
|
31
|
+
*Joel Hawksley*
|
32
|
+
|
33
|
+
* BREAKING: Remove deprecated support for loading ViewComponent engine manually. Make sure `require "view_component/engine"` is removed from `Gemfile`.
|
34
|
+
|
35
|
+
*Joel Hawksley*
|
36
|
+
|
37
|
+
* BREAKING: Remove deprecated `generate_*` methods. Use `generate.*` instead.
|
38
|
+
|
39
|
+
*Joel Hawksley*
|
40
|
+
|
41
|
+
* BREAKING: Remove deprecated `with_variant` method.
|
42
|
+
|
43
|
+
*Joel Hawksley*
|
44
|
+
|
45
|
+
* BREAKING: Remove deprecated `rendered_component` in favor of `rendered_content`.
|
46
|
+
|
47
|
+
*Joel Hawksley*
|
48
|
+
|
49
|
+
* BREAKING: Remove deprecated `config.preview_path` in favor of `config.preview_paths`.
|
50
|
+
|
51
|
+
*Joel Hawksley*
|
52
|
+
|
53
|
+
* BREAKING: Support Ruby 2.7+ instead of 2.4+
|
54
|
+
|
55
|
+
*Joel Hawksley*
|
56
|
+
|
57
|
+
* BREAKING: Remove deprecated `before_render_check`.
|
58
|
+
|
59
|
+
*Joel Hawksley*
|
60
|
+
|
61
|
+
* BREAKING: Change counter variable to start iterating from `0` instead of `1`.
|
62
|
+
|
63
|
+
*Frank S*
|
64
|
+
|
65
|
+
* BREAKING: `#SLOT_NAME` getter no longer accepts arguments. This change was missed as part of the earlier deprecation in `3.0.0.rc1`.
|
66
|
+
|
67
|
+
*Joel Hawksley*
|
68
|
+
|
69
|
+
* BREAKING: Raise `TranslateCalledBeforeRenderError`, `ControllerCalledBeforeRenderError`, or `HelpersCalledBeforeRenderError` instead of `ViewContextCalledBeforeRenderError`.
|
70
|
+
|
71
|
+
*Joel Hawksley*
|
72
|
+
|
73
|
+
* BREAKING: Raise `SlotPredicateNameError`, `RedefinedSlotError`, `ReservedSingularSlotNameError`, `ContentSlotNameError`, `InvalidSlotDefinitionError`, `ReservedPluralSlotNameError`, `ContentAlreadySetForPolymorphicSlotErrror`, `SystemTestControllerOnlyAllowedInTestError`, `SystemTestControllerNefariousPathError`, `NoMatchingTemplatesForPreviewError`, `MultipleMatchingTemplatesForPreviewError`, `DuplicateContentError`, `EmptyOrInvalidInitializerError`, `MissingCollectionArgumentError`, `ReservedParameterError`, `InvalidCollectionArgumentError`, `MultipleInlineTemplatesError`, `MissingPreviewTemplateError`, `DuplicateSlotContentError` or `NilWithContentError` instead of generic error classes.
|
74
|
+
|
75
|
+
*Joel Hawksley*
|
76
|
+
|
77
|
+
* BREAKING: Rename `SlotV2` to `Slot` and `SlotableV2` to `Slotable`.
|
78
|
+
|
79
|
+
*Joel Hawksley*
|
80
|
+
|
81
|
+
* BREAKING: Incorporate `PolymorphicSlots` into `Slotable`. To migrate, remove any references to `PolymorphicSlots` as they are no longer necessary.
|
82
|
+
|
83
|
+
*Joel Hawksley*
|
84
|
+
|
85
|
+
* BREAKING: Rename private TestHelpers#controller, #build_controller, #request, and #preview_class to avoid conflicts. Note: While these methods were undocumented and marked as private, they were accessible in tests. As such, we're considering this to be a breaking change.
|
86
|
+
|
87
|
+
*Joel Hawksley*
|
88
|
+
|
89
|
+
### v3.0.0.rc6
|
90
|
+
|
91
|
+
Run into an issue with this release candidate? [Let us know](https://github.com/ViewComponent/view_component/issues/1629). We hope to release v3.0.0 in the near future!
|
92
|
+
|
93
|
+
* BREAKING: `#SLOT_NAME` getter no longer accepts arguments. This change was missed as part of the earlier deprecation in `3.0.0.rc1`.
|
94
|
+
|
95
|
+
*Joel Hawksley*
|
96
|
+
|
97
|
+
* BREAKING: Raise `TranslateCalledBeforeRenderError`, `ControllerCalledBeforeRenderError`, or `HelpersCalledBeforeRenderError` instead of `ViewContextCalledBeforeRenderError`.
|
98
|
+
|
99
|
+
*Joel Hawksley*
|
100
|
+
|
101
|
+
* BREAKING: Raise `SlotPredicateNameError`, `RedefinedSlotError`, `ReservedSingularSlotNameError`, `ContentSlotNameError`, `InvalidSlotDefinitionError`, `ReservedPluralSlotNameError`, `ContentAlreadySetForPolymorphicSlotErrror`, `SystemTestControllerOnlyAllowedInTestError`, `SystemTestControllerNefariousPathError`, `NoMatchingTemplatesForPreviewError`, `MultipleMatchingTemplatesForPreviewError`, `DuplicateContentError`, `EmptyOrInvalidInitializerError`, `MissingCollectionArgumentError`, `ReservedParameterError`, `InvalidCollectionArgumentError`, `MultipleInlineTemplatesError`, `MissingPreviewTemplateError`, `DuplicateSlotContentError` or `NilWithContentError` instead of generic error classes.
|
102
|
+
|
103
|
+
*Joel Hawksley*
|
104
|
+
|
105
|
+
* Fix bug where `content?` and `with_content` didn't work reliably with slots.
|
106
|
+
|
107
|
+
*Derek Kniffin, Joel Hawksley*
|
108
|
+
|
109
|
+
* Add `with_SLOT_NAME_content` helper.
|
110
|
+
|
111
|
+
*Will Cosgrove*
|
112
|
+
|
113
|
+
* Allow ActiveRecord objects to be passed to `renders_many`.
|
114
|
+
|
115
|
+
*Leigh Halliday*
|
116
|
+
|
117
|
+
* Fix broken links in documentation.
|
118
|
+
|
119
|
+
*Ellen Keal*
|
120
|
+
|
121
|
+
* Run `standardrb` against markdown in docs.
|
122
|
+
|
123
|
+
*Joel Hawksley*
|
124
|
+
|
125
|
+
* Allow `.with_content` to be redefined by components.
|
126
|
+
|
127
|
+
*Joel Hawksley*
|
128
|
+
|
129
|
+
* Run `standardrb` against markdown in docs.
|
130
|
+
|
131
|
+
*Joel Hawksley*
|
132
|
+
|
133
|
+
* Raise error if translations are used in initializer.
|
134
|
+
|
135
|
+
*Joel Hawksley*
|
136
|
+
|
137
|
+
## v3.0.0.rc5
|
138
|
+
|
139
|
+
Run into an issue with this release candidate? [Let us know](https://github.com/ViewComponent/view_component/issues/1629).
|
140
|
+
|
141
|
+
* Fix bug where `mkdir_p` failed due to incorrect permissions.
|
142
|
+
|
143
|
+
*Joel Hawksley*
|
144
|
+
|
145
|
+
* Check for inline `erb_template` calls when deciding whether to compile a component's superclass.
|
146
|
+
|
147
|
+
*Justin Kenyon*
|
148
|
+
|
149
|
+
* Protect against `SystemStackError` if `CaptureCompatibility` module is included more than once.
|
150
|
+
|
151
|
+
*Cameron Dutro*
|
152
|
+
|
153
|
+
## v3.0.0.rc4
|
154
|
+
|
155
|
+
Run into an issue with this release candidate? [Let us know](https://github.com/ViewComponent/view_component/issues/1629).
|
156
|
+
|
157
|
+
* Add `TestHelpers#vc_test_request`.
|
158
|
+
|
159
|
+
*Joel Hawksley*
|
160
|
+
|
161
|
+
## v3.0.0.rc3
|
162
|
+
|
163
|
+
Run into an issue with this release candidate? [Let us know](https://github.com/ViewComponent/view_component/issues/1629).
|
164
|
+
|
165
|
+
* Fix typos in generator docs.
|
166
|
+
|
167
|
+
*Sascha Karnatz*
|
168
|
+
|
169
|
+
* Add `TestHelpers#vc_test_controller`.
|
170
|
+
|
171
|
+
*Joel Hawksley*
|
172
|
+
|
173
|
+
* Document `config.view_component.capture_compatibility_patch_enabled` as option for the known incompatibilities with Rails form helpers.
|
174
|
+
|
175
|
+
*Tobias L. Maier*
|
176
|
+
|
177
|
+
* Add support for experimental inline templates.
|
178
|
+
|
179
|
+
*Blake Williams*
|
180
|
+
|
181
|
+
* Expose `translate` and `t` I18n methods on component classes.
|
182
|
+
|
183
|
+
*Elia Schito*
|
184
|
+
|
185
|
+
* Protect against Arbitrary File Read edge case in `ViewComponentsSystemTestController`.
|
186
|
+
|
187
|
+
*Nick Malcolm*
|
188
|
+
|
189
|
+
## v3.0.0.rc2
|
190
|
+
|
191
|
+
Run into an issue with this release? [Let us know](https://github.com/ViewComponent/view_component/issues/1629).
|
192
|
+
|
193
|
+
* BREAKING: Rename `SlotV2` to `Slot` and `SlotableV2` to `Slotable`.
|
194
|
+
|
195
|
+
*Joel Hawksley*
|
196
|
+
|
197
|
+
* BREAKING: Incorporate `PolymorphicSlots` into `Slotable`. To migrate, remove any references to `PolymorphicSlots` as they are no longer necessary.
|
198
|
+
|
199
|
+
*Joel Hawksley*
|
200
|
+
|
201
|
+
* BREAKING: Rename private TestHelpers#controller, #build_controller, #request, and #preview_class to avoid conflicts. Note: While these methods were undocumented and marked as private, they were accessible in tests. As such, we're considering this to be a breaking change.
|
202
|
+
|
203
|
+
*Joel Hawksley*
|
204
|
+
|
205
|
+
* Avoid loading ActionView::Base during Rails initialization. Originally submitted in #1528.
|
206
|
+
|
207
|
+
*Jonathan del Strother*
|
208
|
+
|
209
|
+
* Improve documentation of known incompatibilities with Rails form helpers.
|
210
|
+
|
211
|
+
*Tobias L. Maier*
|
212
|
+
|
213
|
+
* Remove dependency on environment task from `view_component:statsetup`.
|
214
|
+
|
215
|
+
*Svetlin Simonyan*
|
216
|
+
|
217
|
+
* Add experimental `config.view_component.capture_compatibility_patch_enabled` option resolving rendering issues related to forms, capture, turbo frames, etc.
|
218
|
+
|
219
|
+
*Blake Williams*
|
220
|
+
|
221
|
+
* Add `#content?` method that indicates if content has been passed to component.
|
222
|
+
|
223
|
+
*Joel Hawksley*
|
224
|
+
|
225
|
+
* Added example of a custom preview controller.
|
226
|
+
|
227
|
+
*Graham Rogers*
|
228
|
+
|
229
|
+
* Add Krystal to list of companies using ViewComponent.
|
230
|
+
|
231
|
+
*Matt Bearman*
|
232
|
+
|
233
|
+
* Add Mon Ami to list of companies using ViewComponent.
|
234
|
+
|
235
|
+
*Ethan Lee-Tyson*
|
236
|
+
|
237
|
+
## 3.0.0.rc1
|
238
|
+
|
239
|
+
1,000+ days and 100+ releases later, the 200+ contributors to ViewComponent are proud to ship v3.0.0!
|
240
|
+
|
241
|
+
We're so grateful for all the work of community members to get us to this release. Whether it’s filing bug reports, designing APIs in long-winded discussion threads, or writing code itself, ViewComponent is built by the community, for the community. We couldn’t be more proud of what we’re building together :heart:
|
242
|
+
|
243
|
+
This release makes the following breaking changes, many of which have long been deprecated:
|
244
|
+
|
245
|
+
* BREAKING: Remove deprecated slots setter methods. Use `with_SLOT_NAME` instead.
|
246
|
+
|
247
|
+
*Joel Hawksley*
|
248
|
+
|
249
|
+
* BREAKING: Remove deprecated SlotsV1 in favor of current SlotsV2.
|
250
|
+
|
251
|
+
*Joel Hawksley*
|
252
|
+
|
253
|
+
* BREAKING: Remove deprecated `content_areas` feature. Use Slots instead.
|
254
|
+
|
255
|
+
*Joel Hawksley*
|
256
|
+
|
257
|
+
* BREAKING: Remove deprecated support for loading ViewComponent engine manually. Make sure `require "view_component/engine"` is removed from `Gemfile`.
|
258
|
+
|
259
|
+
*Joel Hawksley*
|
260
|
+
|
261
|
+
* BREAKING: Remove deprecated `generate_*` methods. Use `generate.*` instead.
|
262
|
+
|
263
|
+
*Joel Hawksley*
|
264
|
+
|
265
|
+
* BREAKING: Remove deprecated `with_variant` method.
|
266
|
+
|
267
|
+
*Joel Hawksley*
|
268
|
+
|
269
|
+
* BREAKING: Remove deprecated `rendered_component` in favor of `rendered_content`.
|
270
|
+
|
271
|
+
*Joel Hawksley*
|
272
|
+
|
273
|
+
* BREAKING: Remove deprecated `config.preview_path` in favor of `config.preview_paths`.
|
274
|
+
|
275
|
+
*Joel Hawksley*
|
276
|
+
|
277
|
+
* BREAKING: Support Ruby 2.7+ instead of 2.4+
|
278
|
+
|
279
|
+
*Joel Hawksley*
|
280
|
+
|
281
|
+
* BREAKING: Remove deprecated `before_render_check`.
|
282
|
+
|
283
|
+
*Joel Hawksley*
|
284
|
+
|
285
|
+
* BREAKING: Change counter variable to start iterating from `0` instead of `1`.
|
286
|
+
|
287
|
+
*Frank S*
|
288
|
+
|
289
|
+
Run into an issue with this release? [Let us know](https://github.com/ViewComponent/view_component/issues/1629).
|
290
|
+
|
13
291
|
## 2.82.0
|
14
292
|
|
15
293
|
* Revert "Avoid loading ActionView::Base during initialization (#1528)"
|
data/lib/view_component/base.rb
CHANGED
@@ -6,11 +6,9 @@ require "view_component/collection"
|
|
6
6
|
require "view_component/compile_cache"
|
7
7
|
require "view_component/compiler"
|
8
8
|
require "view_component/config"
|
9
|
-
require "view_component/
|
10
|
-
require "view_component/polymorphic_slots"
|
9
|
+
require "view_component/errors"
|
11
10
|
require "view_component/preview"
|
12
11
|
require "view_component/slotable"
|
13
|
-
require "view_component/slotable_v2"
|
14
12
|
require "view_component/translatable"
|
15
13
|
require "view_component/with_content_helper"
|
16
14
|
|
@@ -23,7 +21,7 @@ module ViewComponent
|
|
23
21
|
#
|
24
22
|
# @return [ViewComponent::Config]
|
25
23
|
def config
|
26
|
-
@config ||=
|
24
|
+
@config ||= ActiveSupport::OrderedOptions.new
|
27
25
|
end
|
28
26
|
|
29
27
|
# Replaces the entire config. You shouldn't need to use this directly
|
@@ -31,22 +29,15 @@ module ViewComponent
|
|
31
29
|
attr_writer :config
|
32
30
|
end
|
33
31
|
|
34
|
-
include ViewComponent::
|
35
|
-
include ViewComponent::PolymorphicSlots
|
36
|
-
include ViewComponent::SlotableV2
|
32
|
+
include ViewComponent::Slotable
|
37
33
|
include ViewComponent::Translatable
|
38
34
|
include ViewComponent::WithContentHelper
|
39
35
|
|
40
|
-
ViewContextCalledBeforeRenderError = Class.new(StandardError)
|
41
|
-
|
42
36
|
RESERVED_PARAMETER = :content
|
43
37
|
|
44
38
|
# For CSRF authenticity tokens in forms
|
45
39
|
delegate :form_authenticity_token, :protect_against_forgery?, :config, to: :helpers
|
46
40
|
|
47
|
-
class_attribute :content_areas
|
48
|
-
self.content_areas = [] # class_attribute:default doesn't work until Rails 5.2
|
49
|
-
|
50
41
|
# Config option that strips trailing whitespace in templates before compiling them.
|
51
42
|
class_attribute :__vc_strip_trailing_whitespace, instance_accessor: false, instance_predicate: false
|
52
43
|
self.__vc_strip_trailing_whitespace = false # class_attribute:default doesn't work until Rails 5.2
|
@@ -66,23 +57,6 @@ module ViewComponent
|
|
66
57
|
self.__vc_original_view_context = view_context
|
67
58
|
end
|
68
59
|
|
69
|
-
# @!macro [attach] deprecated_generate_mattr_accessor
|
70
|
-
# @method generate_$1
|
71
|
-
# @deprecated Use `#generate.$1` instead. Will be removed in v3.0.0.
|
72
|
-
def self._deprecated_generate_mattr_accessor(name)
|
73
|
-
define_singleton_method("generate_#{name}".to_sym) do
|
74
|
-
generate.public_send(name)
|
75
|
-
end
|
76
|
-
define_singleton_method("generate_#{name}=".to_sym) do |value|
|
77
|
-
generate.public_send("#{name}=".to_sym, value)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
_deprecated_generate_mattr_accessor :distinct_locale_files
|
82
|
-
_deprecated_generate_mattr_accessor :locale
|
83
|
-
_deprecated_generate_mattr_accessor :sidecar
|
84
|
-
_deprecated_generate_mattr_accessor :stimulus_controller
|
85
|
-
|
86
60
|
# Entrypoint for rendering components.
|
87
61
|
#
|
88
62
|
# - `view_context`: ActionView context from calling view
|
@@ -119,9 +93,7 @@ module ViewComponent
|
|
119
93
|
@current_template = self
|
120
94
|
|
121
95
|
if block && defined?(@__vc_content_set_by_with_content)
|
122
|
-
raise
|
123
|
-
"which means that ViewComponent doesn't know which content to use.\n\n" \
|
124
|
-
"To fix this issue, use either `with_content` or a block."
|
96
|
+
raise DuplicateContentError.new(self.class.name)
|
125
97
|
end
|
126
98
|
|
127
99
|
@__vc_content_evaluated = false
|
@@ -165,14 +137,6 @@ module ViewComponent
|
|
165
137
|
#
|
166
138
|
# @return [void]
|
167
139
|
def before_render
|
168
|
-
before_render_check
|
169
|
-
end
|
170
|
-
|
171
|
-
# Called after rendering the component.
|
172
|
-
#
|
173
|
-
# @deprecated Use `#before_render` instead. Will be removed in v3.0.0.
|
174
|
-
# @return [void]
|
175
|
-
def before_render_check
|
176
140
|
# noop
|
177
141
|
end
|
178
142
|
|
@@ -208,16 +172,7 @@ module ViewComponent
|
|
208
172
|
#
|
209
173
|
# @return [ActionController::Base]
|
210
174
|
def controller
|
211
|
-
if view_context.nil?
|
212
|
-
raise(
|
213
|
-
ViewContextCalledBeforeRenderError,
|
214
|
-
"`#controller` can't be used during initialization, as it depends " \
|
215
|
-
"on the view context that only exists once a ViewComponent is passed to " \
|
216
|
-
"the Rails render pipeline.\n\n" \
|
217
|
-
"It's sometimes possible to fix this issue by moving code dependent on " \
|
218
|
-
"`#controller` to a `#before_render` method: https://viewcomponent.org/api.html#before_render--void."
|
219
|
-
)
|
220
|
-
end
|
175
|
+
raise ControllerCalledBeforeRenderError if view_context.nil?
|
221
176
|
|
222
177
|
@__vc_controller ||= view_context.controller
|
223
178
|
end
|
@@ -227,16 +182,7 @@ module ViewComponent
|
|
227
182
|
#
|
228
183
|
# @return [ActionView::Base]
|
229
184
|
def helpers
|
230
|
-
if view_context.nil?
|
231
|
-
raise(
|
232
|
-
ViewContextCalledBeforeRenderError,
|
233
|
-
"`#helpers` can't be used during initialization, as it depends " \
|
234
|
-
"on the view context that only exists once a ViewComponent is passed to " \
|
235
|
-
"the Rails render pipeline.\n\n" \
|
236
|
-
"It's sometimes possible to fix this issue by moving code dependent on " \
|
237
|
-
"`#helpers` to a `#before_render` method: https://viewcomponent.org/api.html#before_render--void."
|
238
|
-
)
|
239
|
-
end
|
185
|
+
raise HelpersCalledBeforeRenderError if view_context.nil?
|
240
186
|
|
241
187
|
# Attempt to re-use the original view_context passed to the first
|
242
188
|
# component rendered in the rendering pipeline. This prevents the
|
@@ -265,22 +211,9 @@ module ViewComponent
|
|
265
211
|
#
|
266
212
|
# @private
|
267
213
|
def format
|
268
|
-
# Ruby 2.6 throws a warning without checking `defined?`, 2.7 doesn't
|
269
214
|
@__vc_variant if defined?(@__vc_variant)
|
270
215
|
end
|
271
216
|
|
272
|
-
# Use the provided variant instead of the one determined by the current request.
|
273
|
-
#
|
274
|
-
# @deprecated Will be removed in v3.0.0.
|
275
|
-
# @param variant [Symbol] The variant to be used by the component.
|
276
|
-
# @return [self]
|
277
|
-
def with_variant(variant)
|
278
|
-
@__vc_variant = variant
|
279
|
-
|
280
|
-
self
|
281
|
-
end
|
282
|
-
deprecate :with_variant, deprecator: ViewComponent::Deprecation
|
283
|
-
|
284
217
|
# The current request. Use sparingly as doing so introduces coupling that
|
285
218
|
# inhibits encapsulation & reuse, often making testing difficult.
|
286
219
|
#
|
@@ -289,24 +222,42 @@ module ViewComponent
|
|
289
222
|
@request ||= controller.request if controller.respond_to?(:request)
|
290
223
|
end
|
291
224
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
225
|
+
# The content passed to the component instance as a block.
|
226
|
+
#
|
227
|
+
# @return [String]
|
296
228
|
def content
|
297
229
|
@__vc_content_evaluated = true
|
298
230
|
return @__vc_content if defined?(@__vc_content)
|
299
231
|
|
300
232
|
@__vc_content =
|
301
|
-
if
|
233
|
+
if __vc_render_in_block_provided?
|
302
234
|
view_context.capture(self, &@__vc_render_in_block)
|
303
|
-
elsif
|
235
|
+
elsif __vc_content_set_by_with_content_defined?
|
304
236
|
@__vc_content_set_by_with_content
|
305
237
|
end
|
306
238
|
end
|
307
239
|
|
240
|
+
# Whether `content` has been passed to the component.
|
241
|
+
#
|
242
|
+
# @return [Boolean]
|
243
|
+
def content?
|
244
|
+
__vc_render_in_block_provided? || __vc_content_set_by_with_content_defined?
|
245
|
+
end
|
246
|
+
|
247
|
+
private
|
248
|
+
|
249
|
+
attr_reader :view_context
|
250
|
+
|
251
|
+
def __vc_render_in_block_provided?
|
252
|
+
defined?(@view_context) && @view_context && @__vc_render_in_block
|
253
|
+
end
|
254
|
+
|
255
|
+
def __vc_content_set_by_with_content_defined?
|
256
|
+
defined?(@__vc_content_set_by_with_content)
|
257
|
+
end
|
258
|
+
|
308
259
|
def content_evaluated?
|
309
|
-
@__vc_content_evaluated
|
260
|
+
defined?(@__vc_content_evaluated) && @__vc_content_evaluated
|
310
261
|
end
|
311
262
|
|
312
263
|
# Set the controller used for testing components:
|
@@ -509,6 +460,11 @@ module ViewComponent
|
|
509
460
|
compiler.compiled?
|
510
461
|
end
|
511
462
|
|
463
|
+
# @private
|
464
|
+
def ensure_compiled
|
465
|
+
compile unless compiled?
|
466
|
+
end
|
467
|
+
|
512
468
|
# Compile templates to instance methods, assuming they haven't been compiled already.
|
513
469
|
#
|
514
470
|
# Do as much work as possible in this step, as doing so reduces the amount
|
@@ -558,7 +514,7 @@ module ViewComponent
|
|
558
514
|
# end
|
559
515
|
# ```
|
560
516
|
#
|
561
|
-
# @param value [Boolean] Whether
|
517
|
+
# @param value [Boolean] Whether to strip newlines.
|
562
518
|
def strip_trailing_whitespace(value = true)
|
563
519
|
self.__vc_strip_trailing_whitespace = value
|
564
520
|
end
|
@@ -582,20 +538,14 @@ module ViewComponent
|
|
582
538
|
return unless parameter
|
583
539
|
return if initialize_parameter_names.include?(parameter) || splatted_keyword_argument_present?
|
584
540
|
|
585
|
-
# If Ruby can't parse the component class, then the
|
541
|
+
# If Ruby can't parse the component class, then the initialize
|
586
542
|
# parameters will be empty and ViewComponent will not be able to render
|
587
543
|
# the component.
|
588
544
|
if initialize_parameters.empty?
|
589
|
-
raise
|
590
|
-
"It must accept the parameter `#{parameter}` to render it as a collection.\n\n" \
|
591
|
-
"To fix this issue, update the initializer to accept `#{parameter}`.\n\n" \
|
592
|
-
"See https://viewcomponent.org/guide/collections.html for more information on rendering collections."
|
545
|
+
raise EmptyOrInvalidInitializerError.new(name, parameter)
|
593
546
|
end
|
594
547
|
|
595
|
-
raise
|
596
|
-
"which is required in order to render it as a collection.\n\n" \
|
597
|
-
"To fix this issue, update the initializer to accept `#{parameter}`.\n\n" \
|
598
|
-
"See https://viewcomponent.org/guide/collections.html for more information on rendering collections."
|
548
|
+
raise MissingCollectionArgumentError.new(name, parameter)
|
599
549
|
end
|
600
550
|
|
601
551
|
# Ensure the component initializer doesn't define
|
@@ -605,8 +555,7 @@ module ViewComponent
|
|
605
555
|
def validate_initialization_parameters!
|
606
556
|
return unless initialize_parameter_names.include?(RESERVED_PARAMETER)
|
607
557
|
|
608
|
-
raise
|
609
|
-
"public ViewComponent method. To fix this issue, rename the parameter."
|
558
|
+
raise ReservedParameterError.new(name, RESERVED_PARAMETER)
|
610
559
|
end
|
611
560
|
|
612
561
|
# @private
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
# CaptureCompatibility is a module that patches #capture to fix issues
|
5
|
+
# related to ViewComponent and functionality that relies on `capture`
|
6
|
+
# like forms, capture itself, turbo frames, etc.
|
7
|
+
#
|
8
|
+
# This underlying incompatibility with ViewComponent and capture is
|
9
|
+
# that several features like forms keep a reference to the primary
|
10
|
+
# `ActionView::Base` instance which has its own @output_buffer. When
|
11
|
+
# `#capture` is called on the original `ActionView::Base` instance while
|
12
|
+
# evaluating a block from a ViewComponent the @output_buffer is overridden
|
13
|
+
# in the ActionView::Base instance, and *not* the component. This results
|
14
|
+
# in a double render due to `#capture` implementation details.
|
15
|
+
#
|
16
|
+
# To resolve the issue, we override `#capture` so that we can delegate
|
17
|
+
# the `capture` logic to the ViewComponent that created the block.
|
18
|
+
module CaptureCompatibility
|
19
|
+
def self.included(base)
|
20
|
+
return if base < InstanceMethods
|
21
|
+
|
22
|
+
base.class_eval do
|
23
|
+
alias_method :original_capture, :capture
|
24
|
+
end
|
25
|
+
|
26
|
+
base.prepend(InstanceMethods)
|
27
|
+
end
|
28
|
+
|
29
|
+
module InstanceMethods
|
30
|
+
def capture(*args, &block)
|
31
|
+
# Handle blocks that originate from C code and raise, such as `&:method`
|
32
|
+
return original_capture(*args, &block) if block.source_location.nil?
|
33
|
+
|
34
|
+
block_context = block.binding.receiver
|
35
|
+
|
36
|
+
if block_context != self && block_context.class < ActionView::Base
|
37
|
+
block_context.original_capture(*args, &block)
|
38
|
+
else
|
39
|
+
original_capture(*args, &block)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -53,16 +53,13 @@ module ViewComponent
|
|
53
53
|
if object.respond_to?(:to_ary)
|
54
54
|
object.to_ary
|
55
55
|
else
|
56
|
-
raise
|
57
|
-
"The value of the first argument passed to `with_collection` isn't a valid collection. " \
|
58
|
-
"Make sure it responds to `to_ary`."
|
59
|
-
)
|
56
|
+
raise InvalidCollectionArgumentError
|
60
57
|
end
|
61
58
|
end
|
62
59
|
|
63
60
|
def component_options(item, iterator)
|
64
61
|
item_options = {component.collection_parameter => item}
|
65
|
-
item_options[component.collection_counter_parameter] = iterator.index
|
62
|
+
item_options[component.collection_counter_parameter] = iterator.index if component.counter_argument_present?
|
66
63
|
item_options[component.collection_iteration_parameter] = iterator.dup if component.iteration_argument_present?
|
67
64
|
|
68
65
|
@options.merge(item_options)
|