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 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