view_component 3.7.0 → 3.8.0

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

Potentially problematic release.


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

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47e62a0d72c8f9b594303a04d917565ea3766f30ee1335154643e311f92b6128
4
- data.tar.gz: 412377cfaf624ddfb930d52dcf07a469666f57024d35712f71f752f454f507a5
3
+ metadata.gz: 1bb442fbd129d82aadace3ec12fcf80c62bb9fbd9f0f204ac6668aec801e904b
4
+ data.tar.gz: d39cbee68cace857998a380a80bcd7cd0b5c0b6d22774d36a82e2072d2a8631f
5
5
  SHA512:
6
- metadata.gz: f55188297a16933853b95796a14686a29c1ba14eab0cf50d965c28ad8a18664cdafe8ebb12c700c5877f533b6ddb112cbba8dd498735d4a1f66a9b37647f33bd
7
- data.tar.gz: 780c452ac9a0e33079ca50d49408c74a1c69f427836415c6c08bbdd82f0cb098a646859d26da8ecd93affe8724ab871ed08a210234a9fff71d68ba0ab7668fe8
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="<%= asset_path('prism.css', skip_pipeline: true) %>" media="screen" rel="stylesheet" type="text/css">
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="<%= asset_path('prism.min.js', skip_pipeline: true) %>"></script>
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.
@@ -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.view_component.show_previews
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 SlotPredicateNameError < StandardError
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 < StandardError
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 < StandardError
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.ends_with?("?")
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
- def with_request_url(path, host: nil)
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 = path.split("?", 2)
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
@@ -3,7 +3,7 @@
3
3
  module ViewComponent
4
4
  module VERSION
5
5
  MAJOR = 3
6
- MINOR = 7
6
+ MINOR = 8
7
7
  PATCH = 0
8
8
  PRE = nil
9
9
 
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.7.0
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-10-30 00:00:00.000000000 Z
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