view_component 3.7.0 → 3.8.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/helpers/preview_helper.rb +20 -0
- data/app/views/view_components/_preview_source.html.erb +2 -2
- data/docs/CHANGELOG.md +44 -0
- data/lib/view_component/base.rb +2 -1
- data/lib/view_component/compiler.rb +4 -2
- data/lib/view_component/engine.rb +9 -1
- data/lib/view_component/errors.rb +18 -3
- data/lib/view_component/slotable.rb +18 -1
- data/lib/view_component/test_helpers.rb +20 -2
- data/lib/view_component/use_helpers.rb +20 -0
- data/lib/view_component/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bb442fbd129d82aadace3ec12fcf80c62bb9fbd9f0f204ac6668aec801e904b
|
4
|
+
data.tar.gz: d39cbee68cace857998a380a80bcd7cd0b5c0b6d22774d36a82e2072d2a8631f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 966508a6e21eae5af04e14fabdfd43fbc77dd85f39bc3332b6519686a5da1eb404a8f23e4b25a90cafeaa9143a81437f6a4ca0cf0c57690132bd384030b66071
|
7
|
+
data.tar.gz: 4bc638d9dc1f925a6aa2c75e6f2f0e0f10ed01e61e39eac37c6a2f496f4eff66f50022ec8f7850c94761a40c3a064365f1b02957c35aaa15b3c17fc0f796b328
|
@@ -1,6 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module PreviewHelper
|
4
|
+
# :nocov:
|
5
|
+
include ActionView::Helpers::AssetUrlHelper if Rails.version.to_f < 6.1
|
6
|
+
# :nocov:
|
7
|
+
|
4
8
|
AVAILABLE_PRISM_LANGUAGES = %w[ruby erb haml]
|
5
9
|
FALLBACK_LANGUAGE = "ruby"
|
6
10
|
|
@@ -10,6 +14,14 @@ module PreviewHelper
|
|
10
14
|
render "preview_source"
|
11
15
|
end
|
12
16
|
|
17
|
+
def prism_css_source_url
|
18
|
+
serve_static_preview_assets? ? asset_path("prism.css", skip_pipeline: true) : "https://cdn.jsdelivr.net/npm/prismjs@1.28.0/themes/prism.min.css"
|
19
|
+
end
|
20
|
+
|
21
|
+
def prism_js_source_url
|
22
|
+
serve_static_preview_assets? ? asset_path("prism.min.js", skip_pipeline: true) : "https://cdn.jsdelivr.net/npm/prismjs@1.28.0/prism.min.js"
|
23
|
+
end
|
24
|
+
|
13
25
|
def find_template_data(lookup_context:, template_identifier:)
|
14
26
|
template = lookup_context.find_template(template_identifier)
|
15
27
|
|
@@ -18,6 +30,7 @@ module PreviewHelper
|
|
18
30
|
source: template.source,
|
19
31
|
prism_language_name: prism_language_name_by_template(template: template)
|
20
32
|
}
|
33
|
+
# :nocov:
|
21
34
|
else
|
22
35
|
# Fetch template source via finding it through preview paths
|
23
36
|
# to accomodate source view when exclusively using templates
|
@@ -43,6 +56,7 @@ module PreviewHelper
|
|
43
56
|
prism_language_name: prism_language_name
|
44
57
|
}
|
45
58
|
end
|
59
|
+
# :nocov:
|
46
60
|
end
|
47
61
|
|
48
62
|
private
|
@@ -55,6 +69,7 @@ module PreviewHelper
|
|
55
69
|
language
|
56
70
|
end
|
57
71
|
|
72
|
+
# :nocov:
|
58
73
|
def prism_language_name_by_template_path(template_file_path:)
|
59
74
|
language = template_file_path.gsub(".html", "").split(".").last
|
60
75
|
|
@@ -62,4 +77,9 @@ module PreviewHelper
|
|
62
77
|
|
63
78
|
language
|
64
79
|
end
|
80
|
+
# :nocov:
|
81
|
+
|
82
|
+
def serve_static_preview_assets?
|
83
|
+
ViewComponent::Base.config.show_previews && Rails.application.config.public_file_server.enabled
|
84
|
+
end
|
65
85
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<link href="<%=
|
1
|
+
<link href="<%= prism_css_source_url %>" media="screen" rel="stylesheet" type="text/css">
|
2
2
|
<div class="view-component-source-example">
|
3
3
|
<h2>Source:</h2>
|
4
4
|
<pre class="source">
|
@@ -14,4 +14,4 @@
|
|
14
14
|
<% end %>
|
15
15
|
</pre>
|
16
16
|
</div>
|
17
|
-
<script type="text/javascript" src="<%=
|
17
|
+
<script type="text/javascript" src="<%= prism_js_source_url %>"></script>
|
data/docs/CHANGELOG.md
CHANGED
@@ -10,6 +10,50 @@ nav_order: 5
|
|
10
10
|
|
11
11
|
## main
|
12
12
|
|
13
|
+
## 3.8.0
|
14
|
+
|
15
|
+
* Use correct value for the `config.action_dispatch.show_exceptions` config option for edge Rails.
|
16
|
+
|
17
|
+
*Cameron Dutro*
|
18
|
+
|
19
|
+
* Remove unsupported versions of Rails & Ruby from CI matrix.
|
20
|
+
|
21
|
+
*Reegan Viljoen*
|
22
|
+
|
23
|
+
* Raise error when uncountable slot names are used in `renders_many`
|
24
|
+
|
25
|
+
*Hugo Chantelauze*
|
26
|
+
*Reegan Viljoen*
|
27
|
+
|
28
|
+
* Replace usage of `String#ends_with?` with `String#end_with?` to reduce the dependency on ActiveSupport core extensions.
|
29
|
+
|
30
|
+
*halo*
|
31
|
+
|
32
|
+
* Don't add ActionDispatch::Static middleware unless `public_file_server.enabled`.
|
33
|
+
|
34
|
+
*Daniel Gonzalez*
|
35
|
+
*Reegan Viljoen*
|
36
|
+
|
37
|
+
* Resolve an issue where slots starting with `call` would cause a `NameError`
|
38
|
+
|
39
|
+
*Blake Williams*
|
40
|
+
|
41
|
+
* Add `use_helper` API.
|
42
|
+
|
43
|
+
*Reegan Viljoen*
|
44
|
+
|
45
|
+
* Fix bug where the `Rails` module wasn't being searched from the root namespace.
|
46
|
+
|
47
|
+
*Zenéixe*
|
48
|
+
|
49
|
+
* Fix bug where `#with_request_url`, set the incorrect `request.fullpath`.
|
50
|
+
|
51
|
+
*Nachiket Pusalkar*
|
52
|
+
|
53
|
+
* Allow setting method when using the `with_request_url` test helper.
|
54
|
+
|
55
|
+
*Andrew Duthie*
|
56
|
+
|
13
57
|
## 3.7.0
|
14
58
|
|
15
59
|
* Support Rails 7.1 in CI.
|
data/lib/view_component/base.rb
CHANGED
@@ -12,6 +12,7 @@ require "view_component/preview"
|
|
12
12
|
require "view_component/slotable"
|
13
13
|
require "view_component/translatable"
|
14
14
|
require "view_component/with_content_helper"
|
15
|
+
require "view_component/use_helpers"
|
15
16
|
|
16
17
|
module ViewComponent
|
17
18
|
class Base < ActionView::Base
|
@@ -219,7 +220,7 @@ module ViewComponent
|
|
219
220
|
@__vc_helpers ||= __vc_original_view_context || controller.view_context
|
220
221
|
end
|
221
222
|
|
222
|
-
if Rails.env.development? || Rails.env.test?
|
223
|
+
if ::Rails.env.development? || ::Rails.env.test?
|
223
224
|
def method_missing(method_name, *args) # rubocop:disable Style/MissingRespondToMissing
|
224
225
|
super
|
225
226
|
rescue => e # rubocop:disable Style/RescueStandardError
|
@@ -219,12 +219,12 @@ module ViewComponent
|
|
219
219
|
component_class.included_modules
|
220
220
|
)
|
221
221
|
|
222
|
-
view_component_ancestors.flat_map { |ancestor| ancestor.instance_methods(false).grep(/^call/) }.uniq
|
222
|
+
view_component_ancestors.flat_map { |ancestor| ancestor.instance_methods(false).grep(/^call(_|$)/) }.uniq
|
223
223
|
end
|
224
224
|
end
|
225
225
|
|
226
226
|
def inline_calls_defined_on_self
|
227
|
-
@inline_calls_defined_on_self ||= component_class.instance_methods(false).grep(/^call/)
|
227
|
+
@inline_calls_defined_on_self ||= component_class.instance_methods(false).grep(/^call(_|$)/)
|
228
228
|
end
|
229
229
|
|
230
230
|
def variants
|
@@ -258,6 +258,7 @@ module ViewComponent
|
|
258
258
|
|
259
259
|
if handler.method(:call).parameters.length > 1
|
260
260
|
handler.call(component_class, template)
|
261
|
+
# :nocov:
|
261
262
|
else
|
262
263
|
handler.call(
|
263
264
|
OpenStruct.new(
|
@@ -267,6 +268,7 @@ module ViewComponent
|
|
267
268
|
)
|
268
269
|
)
|
269
270
|
end
|
271
|
+
# :nocov:
|
270
272
|
end
|
271
273
|
|
272
274
|
def call_method_name(variant)
|
@@ -80,6 +80,7 @@ module ViewComponent
|
|
80
80
|
initializer "view_component.monkey_patch_render" do |app|
|
81
81
|
next if Rails.version.to_f >= 6.1 || !app.config.view_component.render_monkey_patch_enabled
|
82
82
|
|
83
|
+
# :nocov:
|
83
84
|
ActiveSupport.on_load(:action_view) do
|
84
85
|
require "view_component/render_monkey_patch"
|
85
86
|
ActionView::Base.prepend ViewComponent::RenderMonkeyPatch
|
@@ -91,11 +92,13 @@ module ViewComponent
|
|
91
92
|
ActionController::Base.prepend ViewComponent::RenderingMonkeyPatch
|
92
93
|
ActionController::Base.prepend ViewComponent::RenderToStringMonkeyPatch
|
93
94
|
end
|
95
|
+
# :nocov:
|
94
96
|
end
|
95
97
|
|
96
98
|
initializer "view_component.include_render_component" do |_app|
|
97
99
|
next if Rails.version.to_f >= 6.1
|
98
100
|
|
101
|
+
# :nocov:
|
99
102
|
ActiveSupport.on_load(:action_view) do
|
100
103
|
require "view_component/render_component_helper"
|
101
104
|
ActionView::Base.include ViewComponent::RenderComponentHelper
|
@@ -107,14 +110,19 @@ module ViewComponent
|
|
107
110
|
ActionController::Base.include ViewComponent::RenderingComponentHelper
|
108
111
|
ActionController::Base.include ViewComponent::RenderComponentToStringHelper
|
109
112
|
end
|
113
|
+
# :nocov:
|
110
114
|
end
|
111
115
|
|
112
116
|
initializer "static assets" do |app|
|
113
|
-
if app.config
|
117
|
+
if serve_static_preview_assets?(app.config)
|
114
118
|
app.middleware.use(::ActionDispatch::Static, "#{root}/app/assets/vendor")
|
115
119
|
end
|
116
120
|
end
|
117
121
|
|
122
|
+
def serve_static_preview_assets?(app_config)
|
123
|
+
app_config.view_component.show_previews && app_config.public_file_server.enabled
|
124
|
+
end
|
125
|
+
|
118
126
|
initializer "compiler mode" do |_app|
|
119
127
|
ViewComponent::Compiler.mode = if Rails.env.development? || Rails.env.test?
|
120
128
|
ViewComponent::Compiler::DEVELOPMENT_MODE
|
@@ -104,7 +104,10 @@ module ViewComponent
|
|
104
104
|
"string, or callable (that is proc, lambda, etc)"
|
105
105
|
end
|
106
106
|
|
107
|
-
class
|
107
|
+
class InvalidSlotNameError < StandardError
|
108
|
+
end
|
109
|
+
|
110
|
+
class SlotPredicateNameError < InvalidSlotNameError
|
108
111
|
MESSAGE =
|
109
112
|
"COMPONENT declares a slot named SLOT_NAME, which ends with a question mark.\n\n" \
|
110
113
|
"This isn't allowed because the ViewComponent framework already provides predicate " \
|
@@ -126,7 +129,7 @@ module ViewComponent
|
|
126
129
|
end
|
127
130
|
end
|
128
131
|
|
129
|
-
class ReservedSingularSlotNameError <
|
132
|
+
class ReservedSingularSlotNameError < InvalidSlotNameError
|
130
133
|
MESSAGE =
|
131
134
|
"COMPONENT declares a slot named SLOT_NAME, which is a reserved word in the ViewComponent framework.\n\n" \
|
132
135
|
"To fix this issue, choose a different name."
|
@@ -136,7 +139,7 @@ module ViewComponent
|
|
136
139
|
end
|
137
140
|
end
|
138
141
|
|
139
|
-
class ReservedPluralSlotNameError <
|
142
|
+
class ReservedPluralSlotNameError < InvalidSlotNameError
|
140
143
|
MESSAGE =
|
141
144
|
"COMPONENT declares a slot named SLOT_NAME, which is a reserved word in the ViewComponent framework.\n\n" \
|
142
145
|
"To fix this issue, choose a different name."
|
@@ -146,6 +149,16 @@ module ViewComponent
|
|
146
149
|
end
|
147
150
|
end
|
148
151
|
|
152
|
+
class UncountableSlotNameError < InvalidSlotNameError
|
153
|
+
MESSAGE =
|
154
|
+
"COMPONENT declares a slot named SLOT_NAME, which is an uncountable word\n\n" \
|
155
|
+
"To fix this issue, choose a different name."
|
156
|
+
|
157
|
+
def initialize(klass_name, slot_name)
|
158
|
+
super(MESSAGE.gsub("COMPONENT", klass_name.to_s).gsub("SLOT_NAME", slot_name.to_s))
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
149
162
|
class ContentAlreadySetForPolymorphicSlotError < StandardError
|
150
163
|
MESSAGE = "Content for slot SLOT_NAME has already been provided."
|
151
164
|
|
@@ -187,6 +200,7 @@ module ViewComponent
|
|
187
200
|
"`#controller` to a [`#before_render` method](https://viewcomponent.org/api.html#before_render--void)."
|
188
201
|
end
|
189
202
|
|
203
|
+
# :nocov:
|
190
204
|
class NoMatchingTemplatesForPreviewError < StandardError
|
191
205
|
MESSAGE = "Found 0 matches for templates for TEMPLATE_IDENTIFIER."
|
192
206
|
|
@@ -202,6 +216,7 @@ module ViewComponent
|
|
202
216
|
super(MESSAGE.gsub("TEMPLATE_IDENTIFIER", template_identifier))
|
203
217
|
end
|
204
218
|
end
|
219
|
+
# :nocov:
|
205
220
|
|
206
221
|
class SystemTestControllerOnlyAllowedInTestError < BaseError
|
207
222
|
MESSAGE = "ViewComponent SystemTest controller must only be called in a test environment for security reasons."
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/concern"
|
4
|
+
require "active_support/inflector/inflections"
|
4
5
|
require "view_component/slot"
|
5
6
|
|
6
7
|
module ViewComponent
|
@@ -295,6 +296,8 @@ module ViewComponent
|
|
295
296
|
raise ReservedPluralSlotNameError.new(name, slot_name)
|
296
297
|
end
|
297
298
|
|
299
|
+
raise_if_slot_name_uncountable(slot_name)
|
300
|
+
raise_if_slot_conflicts_with_call(slot_name)
|
298
301
|
raise_if_slot_ends_with_question_mark(slot_name)
|
299
302
|
raise_if_slot_registered(slot_name)
|
300
303
|
end
|
@@ -308,6 +311,7 @@ module ViewComponent
|
|
308
311
|
raise ReservedSingularSlotNameError.new(name, slot_name)
|
309
312
|
end
|
310
313
|
|
314
|
+
raise_if_slot_conflicts_with_call(slot_name)
|
311
315
|
raise_if_slot_ends_with_question_mark(slot_name)
|
312
316
|
raise_if_slot_registered(slot_name)
|
313
317
|
end
|
@@ -320,7 +324,20 @@ module ViewComponent
|
|
320
324
|
end
|
321
325
|
|
322
326
|
def raise_if_slot_ends_with_question_mark(slot_name)
|
323
|
-
raise SlotPredicateNameError.new(name, slot_name) if slot_name.to_s.
|
327
|
+
raise SlotPredicateNameError.new(name, slot_name) if slot_name.to_s.end_with?("?")
|
328
|
+
end
|
329
|
+
|
330
|
+
def raise_if_slot_conflicts_with_call(slot_name)
|
331
|
+
if slot_name.start_with?("call_")
|
332
|
+
raise InvalidSlotNameError, "Slot cannot start with 'call_'. Please rename #{slot_name}"
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
def raise_if_slot_name_uncountable(slot_name)
|
337
|
+
slot_name = slot_name.to_s
|
338
|
+
if slot_name.pluralize == slot_name.singularize
|
339
|
+
raise UncountableSlotNameError.new(name, slot_name)
|
340
|
+
end
|
324
341
|
end
|
325
342
|
end
|
326
343
|
|
@@ -48,10 +48,14 @@ module ViewComponent
|
|
48
48
|
@rendered_content =
|
49
49
|
if Rails.version.to_f >= 6.1
|
50
50
|
vc_test_controller.view_context.render(component, args, &block)
|
51
|
+
|
52
|
+
# :nocov:
|
51
53
|
else
|
52
54
|
vc_test_controller.view_context.render_component(component, &block)
|
53
55
|
end
|
54
56
|
|
57
|
+
# :nocov:
|
58
|
+
|
55
59
|
Nokogiri::HTML.fragment(@rendered_content)
|
56
60
|
end
|
57
61
|
|
@@ -163,18 +167,31 @@ module ViewComponent
|
|
163
167
|
# end
|
164
168
|
# ```
|
165
169
|
#
|
170
|
+
# To specify a request method, pass the method param:
|
171
|
+
#
|
172
|
+
# ```ruby
|
173
|
+
# with_request_url("/users/42", method: "POST") do
|
174
|
+
# render_inline(MyComponent.new)
|
175
|
+
# end
|
176
|
+
# ```
|
177
|
+
#
|
166
178
|
# @param path [String] The path to set for the current request.
|
167
179
|
# @param host [String] The host to set for the current request.
|
168
|
-
|
180
|
+
# @param method [String] The request method to set for the current request.
|
181
|
+
def with_request_url(full_path, host: nil, method: nil)
|
169
182
|
old_request_host = vc_test_request.host
|
183
|
+
old_request_method = vc_test_request.request_method
|
170
184
|
old_request_path_info = vc_test_request.path_info
|
171
185
|
old_request_path_parameters = vc_test_request.path_parameters
|
172
186
|
old_request_query_parameters = vc_test_request.query_parameters
|
173
187
|
old_request_query_string = vc_test_request.query_string
|
174
188
|
old_controller = defined?(@vc_test_controller) && @vc_test_controller
|
175
189
|
|
176
|
-
path, query =
|
190
|
+
path, query = full_path.split("?", 2)
|
191
|
+
vc_test_request.instance_variable_set(:@fullpath, full_path)
|
192
|
+
vc_test_request.instance_variable_set(:@original_fullpath, full_path)
|
177
193
|
vc_test_request.host = host if host
|
194
|
+
vc_test_request.request_method = method if method
|
178
195
|
vc_test_request.path_info = path
|
179
196
|
vc_test_request.path_parameters = Rails.application.routes.recognize_path_with_request(vc_test_request, path, {})
|
180
197
|
vc_test_request.set_header("action_dispatch.request.query_parameters",
|
@@ -183,6 +200,7 @@ module ViewComponent
|
|
183
200
|
yield
|
184
201
|
ensure
|
185
202
|
vc_test_request.host = old_request_host
|
203
|
+
vc_test_request.request_method = old_request_method
|
186
204
|
vc_test_request.path_info = old_request_path_info
|
187
205
|
vc_test_request.path_parameters = old_request_path_parameters
|
188
206
|
vc_test_request.set_header("action_dispatch.request.query_parameters", old_request_query_parameters)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent::UseHelpers
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
class_methods do
|
7
|
+
def use_helpers(*args)
|
8
|
+
args.each do |helper_method|
|
9
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
10
|
+
def #{helper_method}(*args, &block)
|
11
|
+
raise HelpersCalledBeforeRenderError if view_context.nil?
|
12
|
+
__vc_original_view_context.#{helper_method}(*args, &block)
|
13
|
+
end
|
14
|
+
RUBY
|
15
|
+
|
16
|
+
ruby2_keywords(helper_method) if respond_to?(:ruby2_keywords, true)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
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: 3.
|
4
|
+
version: 3.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ViewComponent Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -395,6 +395,7 @@ files:
|
|
395
395
|
- lib/view_component/test_case.rb
|
396
396
|
- lib/view_component/test_helpers.rb
|
397
397
|
- lib/view_component/translatable.rb
|
398
|
+
- lib/view_component/use_helpers.rb
|
398
399
|
- lib/view_component/version.rb
|
399
400
|
- lib/view_component/with_content_helper.rb
|
400
401
|
- lib/yard/mattr_accessor_handler.rb
|