view_component 2.23.2 → 2.26.1
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/CHANGELOG.md +55 -1
- data/lib/rails/generators/component/component_generator.rb +7 -0
- data/lib/rails/generators/component/templates/component.rb.tt +6 -0
- data/lib/rails/generators/erb/component_generator.rb +4 -1
- data/lib/rails/generators/haml/component_generator.rb +3 -1
- data/lib/rails/generators/preview/component_generator.rb +21 -0
- data/lib/rails/generators/preview/templates/component_preview.rb.tt +5 -0
- data/lib/rails/generators/slim/component_generator.rb +3 -1
- data/lib/view_component/base.rb +68 -5
- data/lib/view_component/collection.rb +0 -1
- data/lib/view_component/compiler.rb +7 -27
- data/lib/view_component/slot_v2.rb +14 -2
- data/lib/view_component/slotable.rb +7 -1
- data/lib/view_component/slotable_v2.rb +2 -0
- data/lib/view_component/version.rb +2 -2
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 071c4caebc8e0dd567d8850adff146e65f6c8c1fe600b866f072d9bfa94bbc46
|
4
|
+
data.tar.gz: 64df3c2eb8d27431da23a2c628de6c9c00d7988130494d37319f4a01d653fd9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69bc43697d70dfb9b96280f47b80c06d1020fd180c01cbc6ae8c8416c3e1b97ffc6587d00741fa81743ae482a316e653790db5af2584c16baf3839a58b809195
|
7
|
+
data.tar.gz: 636d5d91edb07cb90f44e3fc21e7ee63c3c115d1f5fbf7666619205b628761028c4963c65b30a181f27fbbd0bf9539cab0ec3271a48b4d747d7a705528218f11
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,60 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
-
##
|
3
|
+
## main
|
4
|
+
|
5
|
+
## 2.26.1
|
6
|
+
|
7
|
+
* Fix bug that raises when trying to use a collection before the component has been compiled.
|
8
|
+
|
9
|
+
*Blake Williams*
|
10
|
+
|
11
|
+
## 2.26.0
|
12
|
+
|
13
|
+
* Lazily evaluate component `content` in `render?`, preventing the `content` block from being evaluated when `render?` returns false.
|
14
|
+
|
15
|
+
*Blake Williams*
|
16
|
+
|
17
|
+
* Do not generate template when using `--inline` flag.
|
18
|
+
|
19
|
+
*Hans Lemuet*
|
20
|
+
|
21
|
+
* Add `--inline` option to the Haml and Slim generators
|
22
|
+
|
23
|
+
*Hans Lemuet*
|
24
|
+
|
25
|
+
## 2.25.1
|
26
|
+
|
27
|
+
* Experimental: call `._after_compile` class method after a component is compiled.
|
28
|
+
|
29
|
+
*Joel Hawksley*
|
30
|
+
|
31
|
+
* Fix bug where SlotV2 was rendered as an HTML string when using Slim.
|
32
|
+
|
33
|
+
*Manuel Puyol*
|
34
|
+
|
35
|
+
## 2.25.0
|
36
|
+
|
37
|
+
* Add `--preview` generator option to create an associated preview file.
|
38
|
+
|
39
|
+
*Bob Maerten*
|
40
|
+
|
41
|
+
* Add argument validation to avoid `content` override.
|
42
|
+
|
43
|
+
*Manuel Puyol*
|
44
|
+
|
45
|
+
## 2.24.0
|
46
|
+
|
47
|
+
* Add `--inline` option to the erb generator. Prevents default erb template from being created and creates a component with a call method.
|
48
|
+
|
49
|
+
*Nachiket Pusalkar*
|
50
|
+
|
51
|
+
* Add test case for checking presence of `content` in `#render?`.
|
52
|
+
|
53
|
+
*Joel Hawksley*
|
54
|
+
|
55
|
+
* Rename `master` branch to `main`.
|
56
|
+
|
57
|
+
*Joel Hawksley*
|
4
58
|
|
5
59
|
## 2.23.2
|
6
60
|
|
@@ -7,6 +7,7 @@ module Rails
|
|
7
7
|
|
8
8
|
argument :attributes, type: :array, default: [], banner: "attribute"
|
9
9
|
check_class_collision suffix: "Component"
|
10
|
+
class_option :inline, type: :boolean, default: false
|
10
11
|
|
11
12
|
def create_component_file
|
12
13
|
template "component.rb", File.join("app/components", class_path, "#{file_name}_component.rb")
|
@@ -14,6 +15,8 @@ module Rails
|
|
14
15
|
|
15
16
|
hook_for :test_framework
|
16
17
|
|
18
|
+
hook_for :preview, type: :boolean
|
19
|
+
|
17
20
|
hook_for :template_engine do |instance, template_engine|
|
18
21
|
instance.invoke template_engine, [instance.name]
|
19
22
|
end
|
@@ -37,6 +40,10 @@ module Rails
|
|
37
40
|
def initialize_body
|
38
41
|
attributes.map { |attr| "@#{attr.name} = #{attr.name}" }.join("\n ")
|
39
42
|
end
|
43
|
+
|
44
|
+
def initialize_call_method_for_inline?
|
45
|
+
options["inline"]
|
46
|
+
end
|
40
47
|
end
|
41
48
|
end
|
42
49
|
end
|
@@ -7,9 +7,12 @@ module Erb
|
|
7
7
|
class ComponentGenerator < Base
|
8
8
|
source_root File.expand_path("templates", __dir__)
|
9
9
|
class_option :sidecar, type: :boolean, default: false
|
10
|
+
class_option :inline, type: :boolean, default: false
|
10
11
|
|
11
12
|
def copy_view_file
|
12
|
-
|
13
|
+
unless options["inline"]
|
14
|
+
template "component.html.erb", destination
|
15
|
+
end
|
13
16
|
end
|
14
17
|
|
15
18
|
private
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Preview
|
4
|
+
module Generators
|
5
|
+
class ComponentGenerator < ::Rails::Generators::NamedBase
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
7
|
+
|
8
|
+
check_class_collision suffix: "ComponentPreview"
|
9
|
+
|
10
|
+
def create_preview_file
|
11
|
+
template "component_preview.rb", File.join("test/components/previews", class_path, "#{file_name}_component_preview.rb")
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def file_name
|
17
|
+
@_file_name ||= super.sub(/_component\z/i, "")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/view_component/base.rb
CHANGED
@@ -15,12 +15,22 @@ module ViewComponent
|
|
15
15
|
|
16
16
|
ViewContextCalledBeforeRenderError = Class.new(StandardError)
|
17
17
|
|
18
|
+
RESERVED_PARAMETER = :content
|
19
|
+
|
18
20
|
# For CSRF authenticity tokens in forms
|
19
21
|
delegate :form_authenticity_token, :protect_against_forgery?, :config, to: :helpers
|
20
22
|
|
21
23
|
class_attribute :content_areas
|
22
24
|
self.content_areas = [] # class_attribute:default doesn't work until Rails 5.2
|
23
25
|
|
26
|
+
# EXPERIMENTAL: This API is experimental and may be removed at any time.
|
27
|
+
# Hook for allowing components to do work as part of the compilation process.
|
28
|
+
#
|
29
|
+
# For example, one might compile component-specific assets at this point.
|
30
|
+
def self._after_compile
|
31
|
+
# noop
|
32
|
+
end
|
33
|
+
|
24
34
|
# Entrypoint for rendering components.
|
25
35
|
#
|
26
36
|
# view_context: ActionView context from calling view
|
@@ -68,8 +78,8 @@ module ViewComponent
|
|
68
78
|
old_current_template = @current_template
|
69
79
|
@current_template = self
|
70
80
|
|
71
|
-
|
72
|
-
@
|
81
|
+
@_content_evaluated = false
|
82
|
+
@_render_in_block = block
|
73
83
|
|
74
84
|
before_render
|
75
85
|
|
@@ -167,7 +177,20 @@ module ViewComponent
|
|
167
177
|
@request ||= controller.request
|
168
178
|
end
|
169
179
|
|
170
|
-
attr_reader :
|
180
|
+
attr_reader :view_context
|
181
|
+
|
182
|
+
def content
|
183
|
+
return @_content if defined?(@_content)
|
184
|
+
@_content_evaluated = true
|
185
|
+
|
186
|
+
@_content = if @view_context && @_render_in_block
|
187
|
+
view_context.capture(self, &@_render_in_block)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def content_evaluated?
|
192
|
+
@_content_evaluated
|
193
|
+
end
|
171
194
|
|
172
195
|
# The controller used for testing components.
|
173
196
|
# Defaults to ApplicationController. This should be set early
|
@@ -246,7 +269,14 @@ module ViewComponent
|
|
246
269
|
if areas.include?(:content)
|
247
270
|
raise ArgumentError.new ":content is a reserved content area name. Please use another name, such as ':body'"
|
248
271
|
end
|
249
|
-
|
272
|
+
|
273
|
+
areas.each do |area|
|
274
|
+
define_method area.to_sym do
|
275
|
+
content unless content_evaluated? # ensure content is loaded so content_areas will be defined
|
276
|
+
instance_variable_get(:"@#{area}") if instance_variable_defined?(:"@#{area}")
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
250
280
|
self.content_areas = areas
|
251
281
|
end
|
252
282
|
|
@@ -264,7 +294,7 @@ module ViewComponent
|
|
264
294
|
parameter = validate_default ? collection_parameter : provided_collection_parameter
|
265
295
|
|
266
296
|
return unless parameter
|
267
|
-
return if
|
297
|
+
return if initialize_parameter_names.include?(parameter)
|
268
298
|
|
269
299
|
# If Ruby cannot parse the component class, then the initalize
|
270
300
|
# parameters will be empty and ViewComponent will not be able to render
|
@@ -281,8 +311,41 @@ module ViewComponent
|
|
281
311
|
)
|
282
312
|
end
|
283
313
|
|
314
|
+
# Ensure the component initializer does not define
|
315
|
+
# invalid parameters that could override the framework's
|
316
|
+
# methods.
|
317
|
+
def validate_initialization_parameters!
|
318
|
+
return unless initialize_parameter_names.include?(RESERVED_PARAMETER)
|
319
|
+
|
320
|
+
raise ArgumentError.new(
|
321
|
+
"#{self} initializer cannot contain " \
|
322
|
+
"`#{RESERVED_PARAMETER}` since it will override a " \
|
323
|
+
"public ViewComponent method."
|
324
|
+
)
|
325
|
+
end
|
326
|
+
|
327
|
+
def collection_parameter
|
328
|
+
if provided_collection_parameter
|
329
|
+
provided_collection_parameter
|
330
|
+
else
|
331
|
+
name && name.demodulize.underscore.chomp("_component").to_sym
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
def collection_counter_parameter
|
336
|
+
"#{collection_parameter}_counter".to_sym
|
337
|
+
end
|
338
|
+
|
339
|
+
def counter_argument_present?
|
340
|
+
instance_method(:initialize).parameters.map(&:second).include?(collection_counter_parameter)
|
341
|
+
end
|
342
|
+
|
284
343
|
private
|
285
344
|
|
345
|
+
def initialize_parameter_names
|
346
|
+
initialize_parameters.map(&:last)
|
347
|
+
end
|
348
|
+
|
286
349
|
def initialize_parameters
|
287
350
|
instance_method(:initialize).parameters
|
288
351
|
end
|
@@ -10,7 +10,6 @@ module ViewComponent
|
|
10
10
|
def render_in(view_context, &block)
|
11
11
|
iterator = ActionView::PartialIteration.new(@collection.size)
|
12
12
|
|
13
|
-
component.compile(raise_errors: true)
|
14
13
|
component.validate_collection_parameter!(validate_default: true)
|
15
14
|
|
16
15
|
@collection.map do |item|
|
@@ -24,30 +24,11 @@ module ViewComponent
|
|
24
24
|
)
|
25
25
|
end
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
component_class.remove_possible_singleton_method(:collection_counter_parameter)
|
31
|
-
component_class.remove_possible_singleton_method(:counter_argument_present?)
|
32
|
-
|
33
|
-
component_class.define_singleton_method(:collection_parameter) do
|
34
|
-
if provided_collection_parameter
|
35
|
-
provided_collection_parameter
|
36
|
-
else
|
37
|
-
name.demodulize.underscore.chomp("_component").to_sym
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
component_class.define_singleton_method(:collection_counter_parameter) do
|
42
|
-
"#{collection_parameter}_counter".to_sym
|
27
|
+
if raise_errors
|
28
|
+
component_class.validate_initialization_parameters!
|
29
|
+
component_class.validate_collection_parameter!
|
43
30
|
end
|
44
31
|
|
45
|
-
component_class.define_singleton_method(:counter_argument_present?) do
|
46
|
-
instance_method(:initialize).parameters.map(&:second).include?(collection_counter_parameter)
|
47
|
-
end
|
48
|
-
|
49
|
-
component_class.validate_collection_parameter! if raise_errors
|
50
|
-
|
51
32
|
templates.each do |template|
|
52
33
|
# Remove existing compiled template methods,
|
53
34
|
# as Ruby warns when redefining a method.
|
@@ -64,6 +45,8 @@ module ViewComponent
|
|
64
45
|
|
65
46
|
define_render_template_for
|
66
47
|
|
48
|
+
component_class._after_compile
|
49
|
+
|
67
50
|
CompileCache.register(component_class)
|
68
51
|
end
|
69
52
|
|
@@ -163,9 +146,8 @@ module ViewComponent
|
|
163
146
|
# end
|
164
147
|
#
|
165
148
|
# Without this, `MyOtherComponent` will not look for `my_component/my_other_component.html.erb`
|
166
|
-
nested_component_files = if component_class.name.include?("::")
|
167
|
-
|
168
|
-
Dir["#{directory}/#{nested_component_path}/#{component_name}.*{#{extensions}}"]
|
149
|
+
nested_component_files = if component_class.name.include?("::") && component_name != filename
|
150
|
+
Dir["#{directory}/#{filename}/#{component_name}.*{#{extensions}}"]
|
169
151
|
else
|
170
152
|
[]
|
171
153
|
end
|
@@ -205,7 +187,6 @@ module ViewComponent
|
|
205
187
|
end
|
206
188
|
end
|
207
189
|
|
208
|
-
# :nocov:
|
209
190
|
def compiled_template(file_path)
|
210
191
|
handler = ActionView::Template.handler_for_extension(File.extname(file_path).gsub(".", ""))
|
211
192
|
template = File.read(file_path)
|
@@ -216,7 +197,6 @@ module ViewComponent
|
|
216
197
|
handler.call(OpenStruct.new(source: template, identifier: component_class.identifier, type: component_class.type))
|
217
198
|
end
|
218
199
|
end
|
219
|
-
# :nocov:
|
220
200
|
|
221
201
|
def call_method_name(variant)
|
222
202
|
if variant.present? && variants.include?(variant)
|
@@ -22,17 +22,25 @@ module ViewComponent
|
|
22
22
|
# If there is no slot renderable, we evaluate the block passed to
|
23
23
|
# the slot and return it.
|
24
24
|
def to_s
|
25
|
+
return @content if defined?(@content)
|
26
|
+
|
25
27
|
view_context = @parent.send(:view_context)
|
26
|
-
view_context.capture do
|
28
|
+
@content = view_context.capture do
|
27
29
|
if defined?(@_component_instance)
|
28
30
|
# render_in is faster than `parent.render`
|
29
|
-
@
|
31
|
+
if defined?(@_content_block)
|
32
|
+
@_component_instance.render_in(view_context, &@_content_block)
|
33
|
+
else
|
34
|
+
@_component_instance.render_in(view_context)
|
35
|
+
end
|
30
36
|
elsif defined?(@_content)
|
31
37
|
@_content
|
32
38
|
elsif defined?(@_content_block)
|
33
39
|
@_content_block.call
|
34
40
|
end
|
35
41
|
end
|
42
|
+
|
43
|
+
@content
|
36
44
|
end
|
37
45
|
|
38
46
|
# Allow access to public component methods via the wrapper
|
@@ -58,6 +66,10 @@ module ViewComponent
|
|
58
66
|
@_component_instance.public_send(symbol, *args, &block)
|
59
67
|
end
|
60
68
|
|
69
|
+
def html_safe?
|
70
|
+
to_s.html_safe?
|
71
|
+
end
|
72
|
+
|
61
73
|
def respond_to_missing?(symbol, include_all = false)
|
62
74
|
defined?(@_component_instance) && @_component_instance.respond_to?(symbol, include_all)
|
63
75
|
end
|
@@ -51,11 +51,17 @@ module ViewComponent
|
|
51
51
|
if collection
|
52
52
|
class_eval <<-RUBY
|
53
53
|
def #{accessor_name}
|
54
|
+
content unless content_evaluated? # ensure content is loaded so slots will be defined
|
54
55
|
#{instance_variable_name} ||= []
|
55
56
|
end
|
56
57
|
RUBY
|
57
58
|
else
|
58
|
-
|
59
|
+
class_eval <<-RUBY
|
60
|
+
def #{accessor_name}
|
61
|
+
content unless content_evaluated? # ensure content is loaded so slots will be defined
|
62
|
+
#{instance_variable_name} if defined?(#{instance_variable_name})
|
63
|
+
end
|
64
|
+
RUBY
|
59
65
|
end
|
60
66
|
|
61
67
|
# Default class_name to ViewComponent::Slot
|
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: 2.
|
4
|
+
version: 2.26.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub Open Source
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -219,6 +219,8 @@ files:
|
|
219
219
|
- lib/rails/generators/erb/templates/component.html.erb.tt
|
220
220
|
- lib/rails/generators/haml/component_generator.rb
|
221
221
|
- lib/rails/generators/haml/templates/component.html.haml.tt
|
222
|
+
- lib/rails/generators/preview/component_generator.rb
|
223
|
+
- lib/rails/generators/preview/templates/component_preview.rb.tt
|
222
224
|
- lib/rails/generators/rspec/component_generator.rb
|
223
225
|
- lib/rails/generators/rspec/templates/component_spec.rb.tt
|
224
226
|
- lib/rails/generators/slim/component_generator.rb
|
@@ -268,7 +270,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
268
270
|
- !ruby/object:Gem::Version
|
269
271
|
version: '0'
|
270
272
|
requirements: []
|
271
|
-
rubygems_version: 3.
|
273
|
+
rubygems_version: 3.0.3
|
272
274
|
signing_key:
|
273
275
|
specification_version: 4
|
274
276
|
summary: View components for Rails
|