view_component 3.20.0 → 3.21.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/docs/CHANGELOG.md +30 -0
- data/lib/rails/generators/component/component_generator.rb +2 -1
- data/lib/rails/generators/component/templates/component.rb.tt +1 -1
- data/lib/view_component/base.rb +18 -30
- data/lib/view_component/compiler.rb +4 -13
- data/lib/view_component/instrumentation.rb +1 -1
- data/lib/view_component/template.rb +8 -0
- data/lib/view_component/version.rb +1 -1
- metadata +16 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24be9824d2f5208831e8de57930415019c781a1245224659efb9258372dcafbc
|
4
|
+
data.tar.gz: 33182c814b14959c85370e274619a3da70ea19906dd40c8d0be0cd12c9f16a2b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d856adb4c86acc808277c7fcc17291b41328b932b53991db003dccab6e23f2a02177e200065e78d3004f8233df98b0926202138b8b536f67c8f848f876231e2
|
7
|
+
data.tar.gz: a7c6b583fd6eaf4bdb20cdc9d7ca86ed0a5e818e90d1099c5fd799d2127122c058d5d58285251ea0713aeb73d719cabad8ab971e994e0f658767235089953dfd
|
data/docs/CHANGELOG.md
CHANGED
@@ -10,6 +10,36 @@ nav_order: 5
|
|
10
10
|
|
11
11
|
## main
|
12
12
|
|
13
|
+
## 3.21.0
|
14
|
+
|
15
|
+
* Updates testing docs to include an example of how to use with RSpec.
|
16
|
+
|
17
|
+
*Rylan Bowers*
|
18
|
+
|
19
|
+
* Add `--skip-suffix` option to component generator.
|
20
|
+
|
21
|
+
*KAWAKAMI Moeki*
|
22
|
+
|
23
|
+
* Add FreeATS to list of companies using ViewComponent.
|
24
|
+
|
25
|
+
*Ilia Liamshin*
|
26
|
+
|
27
|
+
* Ensure HTML output safety wrapper is used for all inline templates.
|
28
|
+
|
29
|
+
*Joel Hawksley*
|
30
|
+
|
31
|
+
* Expose `.identifier` method as part of public API.
|
32
|
+
|
33
|
+
*Joel Hawksley*
|
34
|
+
|
35
|
+
* Add rails 8 support to CI.
|
36
|
+
|
37
|
+
*Reegan Viljoen*
|
38
|
+
|
39
|
+
* Updates ActionText compatibility documentation to reference `rich_textarea_tag` for Rails 8.0 support.
|
40
|
+
|
41
|
+
*Alvin Crespo*
|
42
|
+
|
13
43
|
## 3.20.0
|
14
44
|
|
15
45
|
* Allow rendering `with_collection` to accept an optional `spacer_component` to be rendered between each item.
|
@@ -19,9 +19,10 @@ module Rails
|
|
19
19
|
class_option :sidecar, type: :boolean, default: false
|
20
20
|
class_option :stimulus, type: :boolean,
|
21
21
|
default: ViewComponent::Base.config.generate.stimulus_controller
|
22
|
+
class_option :skip_suffix, type: :boolean, default: false
|
22
23
|
|
23
24
|
def create_component_file
|
24
|
-
template "component.rb", File.join(component_path, class_path, "#{file_name}_component.rb")
|
25
|
+
template "component.rb", File.join(component_path, class_path, "#{file_name}#{options[:skip_suffix] ? "" : "_component"}.rb")
|
25
26
|
end
|
26
27
|
|
27
28
|
hook_for :test_framework
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
<% module_namespacing do -%>
|
4
|
-
class <%= class_name
|
4
|
+
class <%= class_name %><%= options[:skip_suffix] ? "" : "Component" %> < <%= parent_class %>
|
5
5
|
<%- if initialize_signature -%>
|
6
6
|
def initialize(<%= initialize_signature %>)
|
7
7
|
<%= initialize_body %>
|
data/lib/view_component/base.rb
CHANGED
@@ -108,14 +108,7 @@ module ViewComponent
|
|
108
108
|
before_render
|
109
109
|
|
110
110
|
if render?
|
111
|
-
rendered_template =
|
112
|
-
if compiler.renders_template_for?(@__vc_variant, __vc_request&.format&.to_sym)
|
113
|
-
render_template_for(@__vc_variant, __vc_request&.format&.to_sym)
|
114
|
-
else
|
115
|
-
maybe_escape_html(render_template_for(@__vc_variant, __vc_request&.format&.to_sym)) do
|
116
|
-
Kernel.warn("WARNING: The #{self.class} component rendered HTML-unsafe output. The output will be automatically escaped, but you may want to investigate.")
|
117
|
-
end
|
118
|
-
end.to_s
|
111
|
+
rendered_template = render_template_for(@__vc_variant, __vc_request&.format&.to_sym).to_s
|
119
112
|
|
120
113
|
# Avoid allocating new string when output_preamble and output_postamble are blank
|
121
114
|
if output_preamble.blank? && output_postamble.blank?
|
@@ -358,10 +351,6 @@ module ViewComponent
|
|
358
351
|
end
|
359
352
|
end
|
360
353
|
|
361
|
-
def compiler
|
362
|
-
@compiler ||= self.class.compiler
|
363
|
-
end
|
364
|
-
|
365
354
|
# Set the controller used for testing components:
|
366
355
|
#
|
367
356
|
# ```ruby
|
@@ -457,8 +446,16 @@ module ViewComponent
|
|
457
446
|
# Defaults to `false`.
|
458
447
|
|
459
448
|
class << self
|
449
|
+
# The file path of the component Ruby file.
|
450
|
+
#
|
451
|
+
# @return [String]
|
452
|
+
attr_reader :identifier
|
453
|
+
|
454
|
+
# @private
|
455
|
+
attr_writer :identifier
|
456
|
+
|
460
457
|
# @private
|
461
|
-
attr_accessor :
|
458
|
+
attr_accessor :virtual_path
|
462
459
|
|
463
460
|
# Find sidecar files for the given extensions.
|
464
461
|
#
|
@@ -468,13 +465,13 @@ module ViewComponent
|
|
468
465
|
# For example, one might collect sidecar CSS files that need to be compiled.
|
469
466
|
# @param extensions [Array<String>] Extensions of which to return matching sidecar files.
|
470
467
|
def sidecar_files(extensions)
|
471
|
-
return [] unless
|
468
|
+
return [] unless identifier
|
472
469
|
|
473
470
|
extensions = extensions.join(",")
|
474
471
|
|
475
472
|
# view files in a directory named like the component
|
476
|
-
directory = File.dirname(
|
477
|
-
filename = File.basename(
|
473
|
+
directory = File.dirname(identifier)
|
474
|
+
filename = File.basename(identifier, ".rb")
|
478
475
|
component_name = name.demodulize.underscore
|
479
476
|
|
480
477
|
# Add support for nested components defined in the same file.
|
@@ -499,7 +496,7 @@ module ViewComponent
|
|
499
496
|
|
500
497
|
sidecar_directory_files = Dir["#{directory}/#{component_name}/#{filename}.*{#{extensions}}"]
|
501
498
|
|
502
|
-
(sidecar_files - [
|
499
|
+
(sidecar_files - [identifier] + sidecar_directory_files + nested_component_files).uniq
|
503
500
|
end
|
504
501
|
|
505
502
|
# Render a component for each element in a collection ([documentation](/guide/collections)):
|
@@ -548,11 +545,11 @@ module ViewComponent
|
|
548
545
|
# has been re-defined by the consuming application, likely in ApplicationComponent.
|
549
546
|
# We use `base_label` method here instead of `label` to avoid cases where the method
|
550
547
|
# owner is included in a prefix like `ApplicationComponent.inherited`.
|
551
|
-
child.
|
548
|
+
child.identifier = caller_locations(1, 10).reject { |l| l.base_label == "inherited" }[0].path
|
552
549
|
|
553
550
|
# If Rails application is loaded, removes the first part of the path and the extension.
|
554
551
|
if defined?(Rails) && Rails.application
|
555
|
-
child.virtual_path = child.
|
552
|
+
child.virtual_path = child.identifier.gsub(
|
556
553
|
/(.*#{Regexp.quote(ViewComponent::Base.config.view_component_path)})|(\.rb)/, ""
|
557
554
|
)
|
558
555
|
end
|
@@ -590,15 +587,6 @@ module ViewComponent
|
|
590
587
|
@__vc_compiler ||= Compiler.new(self)
|
591
588
|
end
|
592
589
|
|
593
|
-
# @private
|
594
|
-
def identifier
|
595
|
-
# :nocov:
|
596
|
-
Kernel.warn("WARNING: The #{self.class}.identifier is undocumented and was meant for internal framework usage only. As it is no longer used by the framework it will be removed in a coming non-breaking ViewComponent release.")
|
597
|
-
|
598
|
-
source_location
|
599
|
-
# :nocov:
|
600
|
-
end
|
601
|
-
|
602
590
|
# Set the parameter name used when rendering elements of a collection ([documentation](/guide/collections)):
|
603
591
|
#
|
604
592
|
# ```ruby
|
@@ -636,7 +624,7 @@ module ViewComponent
|
|
636
624
|
# validate that the default parameter name
|
637
625
|
# is accepted, as support for collection
|
638
626
|
# rendering is optional.
|
639
|
-
# @private
|
627
|
+
# @private
|
640
628
|
def validate_collection_parameter!(validate_default: false)
|
641
629
|
parameter = validate_default ? collection_parameter : provided_collection_parameter
|
642
630
|
|
@@ -656,7 +644,7 @@ module ViewComponent
|
|
656
644
|
# Ensure the component initializer doesn't define
|
657
645
|
# invalid parameters that could override the framework's
|
658
646
|
# methods.
|
659
|
-
# @private
|
647
|
+
# @private
|
660
648
|
def validate_initialization_parameters!
|
661
649
|
return unless initialize_parameter_names.include?(RESERVED_PARAMETER)
|
662
650
|
|
@@ -13,7 +13,6 @@ module ViewComponent
|
|
13
13
|
def initialize(component)
|
14
14
|
@component = component
|
15
15
|
@lock = Mutex.new
|
16
|
-
@rendered_templates = Set.new
|
17
16
|
end
|
18
17
|
|
19
18
|
def compiled?
|
@@ -56,10 +55,6 @@ module ViewComponent
|
|
56
55
|
end
|
57
56
|
end
|
58
57
|
|
59
|
-
def renders_template_for?(variant, format)
|
60
|
-
@rendered_templates.include?([variant, format])
|
61
|
-
end
|
62
|
-
|
63
58
|
private
|
64
59
|
|
65
60
|
attr_reader :templates
|
@@ -71,9 +66,9 @@ module ViewComponent
|
|
71
66
|
|
72
67
|
method_body =
|
73
68
|
if @templates.one?
|
74
|
-
@templates.first.
|
69
|
+
@templates.first.safe_method_name_call
|
75
70
|
elsif (template = @templates.find(&:inline?))
|
76
|
-
template.
|
71
|
+
template.safe_method_name_call
|
77
72
|
else
|
78
73
|
branches = []
|
79
74
|
|
@@ -88,13 +83,13 @@ module ViewComponent
|
|
88
83
|
].join(" && ")
|
89
84
|
end
|
90
85
|
|
91
|
-
branches << [conditional, template.
|
86
|
+
branches << [conditional, template.safe_method_name_call]
|
92
87
|
end
|
93
88
|
|
94
89
|
out = branches.each_with_object(+"") do |(conditional, branch_body), memo|
|
95
90
|
memo << "#{(!memo.present?) ? "if" : "elsif"} #{conditional}\n #{branch_body}\n"
|
96
91
|
end
|
97
|
-
out << "else\n #{templates.find { _1.variant.nil? && _1.default_format? }.
|
92
|
+
out << "else\n #{templates.find { _1.variant.nil? && _1.default_format? }.safe_method_name_call}\nend"
|
98
93
|
end
|
99
94
|
|
100
95
|
@component.silence_redefinition_of_method(:render_template_for)
|
@@ -196,10 +191,6 @@ module ViewComponent
|
|
196
191
|
variant: variant
|
197
192
|
)
|
198
193
|
|
199
|
-
# TODO: We should consider inlining the HTML output safety logic into the compiled render_template_for
|
200
|
-
# instead of this indirect approach
|
201
|
-
@rendered_templates << [out.variant, out.this_format]
|
202
|
-
|
203
194
|
out
|
204
195
|
end
|
205
196
|
|
@@ -59,6 +59,14 @@ module ViewComponent
|
|
59
59
|
@component.define_method(safe_method_name, @component.instance_method(@call_method_name))
|
60
60
|
end
|
61
61
|
|
62
|
+
def safe_method_name_call
|
63
|
+
return safe_method_name unless inline_call?
|
64
|
+
|
65
|
+
"maybe_escape_html(#{safe_method_name}) " \
|
66
|
+
"{ Kernel.warn('WARNING: The #{@component} component rendered HTML-unsafe output. " \
|
67
|
+
"The output will be automatically escaped, but you may want to investigate.') } "
|
68
|
+
end
|
69
|
+
|
62
70
|
def requires_compiled_superclass?
|
63
71
|
inline_call? && !defined_on_self?
|
64
72
|
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.21.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: 2024-
|
11
|
+
date: 2024-12-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -324,6 +324,20 @@ dependencies:
|
|
324
324
|
- - '='
|
325
325
|
- !ruby/object:Gem::Version
|
326
326
|
version: 4.9.0
|
327
|
+
- !ruby/object:Gem::Dependency
|
328
|
+
name: sprockets-rails
|
329
|
+
requirement: !ruby/object:Gem::Requirement
|
330
|
+
requirements:
|
331
|
+
- - "~>"
|
332
|
+
- !ruby/object:Gem::Version
|
333
|
+
version: 3.4.2
|
334
|
+
type: :development
|
335
|
+
prerelease: false
|
336
|
+
version_requirements: !ruby/object:Gem::Requirement
|
337
|
+
requirements:
|
338
|
+
- - "~>"
|
339
|
+
- !ruby/object:Gem::Version
|
340
|
+
version: 3.4.2
|
327
341
|
- !ruby/object:Gem::Dependency
|
328
342
|
name: standard
|
329
343
|
requirement: !ruby/object:Gem::Requirement
|
@@ -380,20 +394,6 @@ dependencies:
|
|
380
394
|
- - "~>"
|
381
395
|
- !ruby/object:Gem::Version
|
382
396
|
version: '5.1'
|
383
|
-
- !ruby/object:Gem::Dependency
|
384
|
-
name: sprockets-rails
|
385
|
-
requirement: !ruby/object:Gem::Requirement
|
386
|
-
requirements:
|
387
|
-
- - "~>"
|
388
|
-
- !ruby/object:Gem::Version
|
389
|
-
version: 3.4.2
|
390
|
-
type: :development
|
391
|
-
prerelease: false
|
392
|
-
version_requirements: !ruby/object:Gem::Requirement
|
393
|
-
requirements:
|
394
|
-
- - "~>"
|
395
|
-
- !ruby/object:Gem::Version
|
396
|
-
version: 3.4.2
|
397
397
|
- !ruby/object:Gem::Dependency
|
398
398
|
name: turbo-rails
|
399
399
|
requirement: !ruby/object:Gem::Requirement
|