view_component 2.62.0 → 2.82.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/LICENSE.txt +1 -1
- data/app/assets/vendor/prism.css +3 -195
- data/app/assets/vendor/prism.min.js +11 -11
- data/app/controllers/concerns/view_component/preview_actions.rb +6 -10
- data/app/controllers/view_components_system_test_controller.rb +7 -0
- data/app/helpers/preview_helper.rb +2 -2
- data/app/views/view_components/preview.html.erb +2 -2
- data/docs/CHANGELOG.md +383 -21
- data/lib/rails/generators/abstract_generator.rb +3 -5
- data/lib/rails/generators/component/component_generator.rb +5 -4
- data/lib/rails/generators/locale/component_generator.rb +1 -1
- data/lib/rails/generators/preview/component_generator.rb +10 -3
- data/lib/view_component/base.rb +41 -47
- data/lib/view_component/compiler.rb +57 -68
- data/lib/view_component/config.rb +176 -0
- data/lib/view_component/content_areas.rb +2 -3
- data/lib/view_component/deprecation.rb +2 -2
- data/lib/view_component/docs_builder_component.html.erb +1 -1
- data/lib/view_component/docs_builder_component.rb +1 -1
- data/lib/view_component/engine.rb +23 -29
- data/lib/view_component/polymorphic_slots.rb +11 -5
- data/lib/view_component/render_component_helper.rb +1 -0
- data/lib/view_component/slotable.rb +2 -3
- data/lib/view_component/slotable_v2.rb +48 -8
- data/lib/view_component/system_test_case.rb +13 -0
- data/lib/view_component/system_test_helpers.rb +27 -0
- data/lib/view_component/test_helpers.rb +65 -15
- data/lib/view_component/translatable.rb +1 -1
- data/lib/view_component/version.rb +1 -1
- data/lib/view_component.rb +6 -3
- metadata +50 -18
- data/lib/view_component/previewable.rb +0 -62
- data/lib/view_component/render_preview_helper.rb +0 -50
data/lib/view_component/base.rb
CHANGED
@@ -4,9 +4,11 @@ require "action_view"
|
|
4
4
|
require "active_support/configurable"
|
5
5
|
require "view_component/collection"
|
6
6
|
require "view_component/compile_cache"
|
7
|
+
require "view_component/compiler"
|
8
|
+
require "view_component/config"
|
7
9
|
require "view_component/content_areas"
|
8
10
|
require "view_component/polymorphic_slots"
|
9
|
-
require "view_component/
|
11
|
+
require "view_component/preview"
|
10
12
|
require "view_component/slotable"
|
11
13
|
require "view_component/slotable_v2"
|
12
14
|
require "view_component/translatable"
|
@@ -14,10 +16,23 @@ require "view_component/with_content_helper"
|
|
14
16
|
|
15
17
|
module ViewComponent
|
16
18
|
class Base < ActionView::Base
|
17
|
-
|
19
|
+
class << self
|
20
|
+
delegate(*ViewComponent::Config.defaults.keys, to: :config)
|
21
|
+
|
22
|
+
# Returns the current config.
|
23
|
+
#
|
24
|
+
# @return [ViewComponent::Config]
|
25
|
+
def config
|
26
|
+
@config ||= ViewComponent::Config.defaults
|
27
|
+
end
|
28
|
+
|
29
|
+
# Replaces the entire config. You shouldn't need to use this directly
|
30
|
+
# unless you're building a `ViewComponent::Config` elsewhere.
|
31
|
+
attr_writer :config
|
32
|
+
end
|
33
|
+
|
18
34
|
include ViewComponent::ContentAreas
|
19
35
|
include ViewComponent::PolymorphicSlots
|
20
|
-
include ViewComponent::Previewable
|
21
36
|
include ViewComponent::SlotableV2
|
22
37
|
include ViewComponent::Translatable
|
23
38
|
include ViewComponent::WithContentHelper
|
@@ -51,15 +66,6 @@ module ViewComponent
|
|
51
66
|
self.__vc_original_view_context = view_context
|
52
67
|
end
|
53
68
|
|
54
|
-
# EXPERIMENTAL: This API is experimental and may be removed at any time.
|
55
|
-
# Hook for allowing components to do work as part of the compilation process.
|
56
|
-
#
|
57
|
-
# For example, one might compile component-specific assets at this point.
|
58
|
-
# @private TODO: add documentation
|
59
|
-
def self._after_compile
|
60
|
-
# noop
|
61
|
-
end
|
62
|
-
|
63
69
|
# @!macro [attach] deprecated_generate_mattr_accessor
|
64
70
|
# @method generate_$1
|
65
71
|
# @deprecated Use `#generate.$1` instead. Will be removed in v3.0.0.
|
@@ -113,11 +119,9 @@ module ViewComponent
|
|
113
119
|
@current_template = self
|
114
120
|
|
115
121
|
if block && defined?(@__vc_content_set_by_with_content)
|
116
|
-
raise ArgumentError.
|
117
|
-
"It looks like a block was provided after calling `with_content` on #{self.class.name}, " \
|
122
|
+
raise ArgumentError, "It looks like a block was provided after calling `with_content` on #{self.class.name}, " \
|
118
123
|
"which means that ViewComponent doesn't know which content to use.\n\n" \
|
119
124
|
"To fix this issue, use either `with_content` or a block."
|
120
|
-
)
|
121
125
|
end
|
122
126
|
|
123
127
|
@__vc_content_evaluated = false
|
@@ -126,7 +130,7 @@ module ViewComponent
|
|
126
130
|
before_render
|
127
131
|
|
128
132
|
if render?
|
129
|
-
render_template_for(@__vc_variant).to_s +
|
133
|
+
render_template_for(@__vc_variant).to_s + output_postamble
|
130
134
|
else
|
131
135
|
""
|
132
136
|
end
|
@@ -149,10 +153,10 @@ module ViewComponent
|
|
149
153
|
nil
|
150
154
|
end
|
151
155
|
|
152
|
-
#
|
156
|
+
# Optional content to be returned after the rendered template.
|
153
157
|
#
|
154
158
|
# @return [String]
|
155
|
-
def
|
159
|
+
def output_postamble
|
156
160
|
""
|
157
161
|
end
|
158
162
|
|
@@ -262,9 +266,7 @@ module ViewComponent
|
|
262
266
|
# @private
|
263
267
|
def format
|
264
268
|
# Ruby 2.6 throws a warning without checking `defined?`, 2.7 doesn't
|
265
|
-
if defined?(@__vc_variant)
|
266
|
-
@__vc_variant
|
267
|
-
end
|
269
|
+
@__vc_variant if defined?(@__vc_variant)
|
268
270
|
end
|
269
271
|
|
270
272
|
# Use the provided variant instead of the one determined by the current request.
|
@@ -313,11 +315,9 @@ module ViewComponent
|
|
313
315
|
# config.view_component.test_controller = "MyTestController"
|
314
316
|
# ```
|
315
317
|
#
|
316
|
-
# Defaults to ApplicationController. Can also be
|
317
|
-
# basis using `with_controller_class`.
|
318
|
+
# Defaults to `nil`. If this is falsy, `"ApplicationController"` is used. Can also be
|
319
|
+
# configured on a per-test basis using `with_controller_class`.
|
318
320
|
#
|
319
|
-
mattr_accessor :test_controller
|
320
|
-
@@test_controller = "ApplicationController"
|
321
321
|
|
322
322
|
# Set if render monkey patches should be included or not in Rails <6.1:
|
323
323
|
#
|
@@ -325,7 +325,6 @@ module ViewComponent
|
|
325
325
|
# config.view_component.render_monkey_patch_enabled = false
|
326
326
|
# ```
|
327
327
|
#
|
328
|
-
mattr_accessor :render_monkey_patch_enabled, instance_writer: false, default: true
|
329
328
|
|
330
329
|
# Path for component files
|
331
330
|
#
|
@@ -333,9 +332,8 @@ module ViewComponent
|
|
333
332
|
# config.view_component.view_component_path = "app/my_components"
|
334
333
|
# ```
|
335
334
|
#
|
336
|
-
# Defaults to `app/components
|
335
|
+
# Defaults to `nil`. If this is falsy, `app/components` is used.
|
337
336
|
#
|
338
|
-
mattr_accessor :view_component_path, instance_writer: false, default: "app/components"
|
339
337
|
|
340
338
|
# Parent class for generated components
|
341
339
|
#
|
@@ -346,7 +344,6 @@ module ViewComponent
|
|
346
344
|
# Defaults to nil. If this is falsy, generators will use
|
347
345
|
# "ApplicationComponent" if defined, "ViewComponent::Base" otherwise.
|
348
346
|
#
|
349
|
-
mattr_accessor :component_parent_class, instance_writer: false
|
350
347
|
|
351
348
|
# Configuration for generators.
|
352
349
|
#
|
@@ -397,21 +394,19 @@ module ViewComponent
|
|
397
394
|
# ```
|
398
395
|
#
|
399
396
|
# Defaults to `false`.
|
400
|
-
mattr_accessor :generate, instance_writer: false, default: ActiveSupport::OrderedOptions.new(false)
|
401
397
|
|
402
398
|
class << self
|
403
399
|
# @private
|
404
400
|
attr_accessor :source_location, :virtual_path
|
405
401
|
|
406
|
-
# EXPERIMENTAL: This API is experimental and may be removed at any time.
|
407
402
|
# Find sidecar files for the given extensions.
|
408
403
|
#
|
409
404
|
# The provided array of extensions is expected to contain
|
410
|
-
# strings starting without the
|
405
|
+
# strings starting without the dot, example: `["erb", "haml"]`.
|
411
406
|
#
|
412
407
|
# For example, one might collect sidecar CSS files that need to be compiled.
|
413
|
-
# @
|
414
|
-
def
|
408
|
+
# @param extensions [Array<String>] Extensions of which to return matching sidecar files.
|
409
|
+
def sidecar_files(extensions)
|
415
410
|
return [] unless source_location
|
416
411
|
|
417
412
|
extensions = extensions.join(",")
|
@@ -489,8 +484,8 @@ module ViewComponent
|
|
489
484
|
|
490
485
|
# If Rails application is loaded, add application url_helpers to the component context
|
491
486
|
# we need to check this to use this gem as a dependency
|
492
|
-
if defined?(Rails) && Rails.application
|
493
|
-
child.include Rails.application.routes.url_helpers
|
487
|
+
if defined?(Rails) && Rails.application && !(child < Rails.application.routes.url_helpers)
|
488
|
+
child.include Rails.application.routes.url_helpers
|
494
489
|
end
|
495
490
|
|
496
491
|
# Derive the source location of the component Ruby file from the call stack.
|
@@ -500,7 +495,7 @@ module ViewComponent
|
|
500
495
|
|
501
496
|
# Removes the first part of the path and the extension.
|
502
497
|
child.virtual_path = child.source_location.gsub(
|
503
|
-
|
498
|
+
/(.*#{Regexp.quote(ViewComponent::Base.config.view_component_path)})|(\.rb)/, ""
|
504
499
|
)
|
505
500
|
|
506
501
|
# Set collection parameter to the extended component
|
@@ -585,26 +580,22 @@ module ViewComponent
|
|
585
580
|
parameter = validate_default ? collection_parameter : provided_collection_parameter
|
586
581
|
|
587
582
|
return unless parameter
|
588
|
-
return if initialize_parameter_names.include?(parameter)
|
583
|
+
return if initialize_parameter_names.include?(parameter) || splatted_keyword_argument_present?
|
589
584
|
|
590
585
|
# If Ruby can't parse the component class, then the initalize
|
591
586
|
# parameters will be empty and ViewComponent will not be able to render
|
592
587
|
# the component.
|
593
588
|
if initialize_parameters.empty?
|
594
|
-
raise ArgumentError.
|
595
|
-
"The #{self} initializer is empty or invalid." \
|
589
|
+
raise ArgumentError, "The #{self} initializer is empty or invalid." \
|
596
590
|
"It must accept the parameter `#{parameter}` to render it as a collection.\n\n" \
|
597
591
|
"To fix this issue, update the initializer to accept `#{parameter}`.\n\n" \
|
598
592
|
"See https://viewcomponent.org/guide/collections.html for more information on rendering collections."
|
599
|
-
)
|
600
593
|
end
|
601
594
|
|
602
|
-
raise ArgumentError
|
603
|
-
"The initializer for #{self} doesn't accept the parameter `#{parameter}`, " \
|
595
|
+
raise ArgumentError, "The initializer for #{self} doesn't accept the parameter `#{parameter}`, " \
|
604
596
|
"which is required in order to render it as a collection.\n\n" \
|
605
597
|
"To fix this issue, update the initializer to accept `#{parameter}`.\n\n" \
|
606
598
|
"See https://viewcomponent.org/guide/collections.html for more information on rendering collections."
|
607
|
-
)
|
608
599
|
end
|
609
600
|
|
610
601
|
# Ensure the component initializer doesn't define
|
@@ -614,10 +605,8 @@ module ViewComponent
|
|
614
605
|
def validate_initialization_parameters!
|
615
606
|
return unless initialize_parameter_names.include?(RESERVED_PARAMETER)
|
616
607
|
|
617
|
-
raise ViewComponent::ComponentError
|
618
|
-
"#{self} initializer can't accept the parameter `#{RESERVED_PARAMETER}`, as it will override a " \
|
608
|
+
raise ViewComponent::ComponentError, "#{self} initializer can't accept the parameter `#{RESERVED_PARAMETER}`, as it will override a " \
|
619
609
|
"public ViewComponent method. To fix this issue, rename the parameter."
|
620
|
-
)
|
621
610
|
end
|
622
611
|
|
623
612
|
# @private
|
@@ -647,6 +636,11 @@ module ViewComponent
|
|
647
636
|
|
648
637
|
private
|
649
638
|
|
639
|
+
def splatted_keyword_argument_present?
|
640
|
+
initialize_parameters.flatten.include?(:keyrest) &&
|
641
|
+
!initialize_parameters.include?([:keyrest, :**]) # Un-named splatted keyword args don't count!
|
642
|
+
end
|
643
|
+
|
650
644
|
def initialize_parameter_names
|
651
645
|
return attribute_names.map(&:to_sym) if respond_to?(:attribute_names)
|
652
646
|
|
@@ -1,10 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "concurrent-ruby"
|
4
|
+
|
3
5
|
module ViewComponent
|
4
6
|
class Compiler
|
5
|
-
# Lock required to be obtained before compiling the component
|
6
|
-
attr_reader :__vc_compiler_lock
|
7
|
-
|
8
7
|
# Compiler mode. Can be either:
|
9
8
|
# * development (a blocking mode which ensures thread safety when redefining the `call` method for components,
|
10
9
|
# default in Rails development and test mode)
|
@@ -16,7 +15,7 @@ module ViewComponent
|
|
16
15
|
|
17
16
|
def initialize(component_class)
|
18
17
|
@component_class = component_class
|
19
|
-
@
|
18
|
+
@redefinition_lock = Mutex.new
|
20
19
|
end
|
21
20
|
|
22
21
|
def compiled?
|
@@ -32,46 +31,39 @@ module ViewComponent
|
|
32
31
|
return if component_class == ViewComponent::Base
|
33
32
|
|
34
33
|
component_class.superclass.compile(raise_errors: raise_errors) if should_compile_superclass?
|
34
|
+
subclass_instance_methods = component_class.instance_methods(false)
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
raise ViewComponent::ComponentError.new(
|
43
|
-
"#{component_class} implements a reserved method, `#with_content`.\n\n" \
|
44
|
-
"To fix this issue, change the name of the method."
|
45
|
-
)
|
46
|
-
end
|
47
|
-
|
48
|
-
if template_errors.present?
|
49
|
-
raise ViewComponent::TemplateError.new(template_errors) if raise_errors
|
36
|
+
if subclass_instance_methods.include?(:with_content) && raise_errors
|
37
|
+
raise ViewComponent::ComponentError.new(
|
38
|
+
"#{component_class} implements a reserved method, `#with_content`.\n\n" \
|
39
|
+
"To fix this issue, change the name of the method."
|
40
|
+
)
|
41
|
+
end
|
50
42
|
|
51
|
-
|
52
|
-
|
43
|
+
if template_errors.present?
|
44
|
+
raise ViewComponent::TemplateError.new(template_errors) if raise_errors
|
53
45
|
|
54
|
-
|
55
|
-
|
56
|
-
"`#before_render_check` will be removed in v3.0.0.\n\n" \
|
57
|
-
"To fix this issue, use `#before_render` instead."
|
58
|
-
)
|
59
|
-
end
|
46
|
+
return false
|
47
|
+
end
|
60
48
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
49
|
+
if subclass_instance_methods.include?(:before_render_check)
|
50
|
+
ViewComponent::Deprecation.deprecation_warning(
|
51
|
+
"`before_render_check`", :"`before_render`"
|
52
|
+
)
|
53
|
+
end
|
65
54
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
55
|
+
if raise_errors
|
56
|
+
component_class.validate_initialization_parameters!
|
57
|
+
component_class.validate_collection_parameter!
|
58
|
+
end
|
70
59
|
|
71
|
-
|
72
|
-
|
73
|
-
|
60
|
+
templates.each do |template|
|
61
|
+
# Remove existing compiled template methods,
|
62
|
+
# as Ruby warns when redefining a method.
|
63
|
+
method_name = call_method_name(template[:variant])
|
74
64
|
|
65
|
+
redefinition_lock.synchronize do
|
66
|
+
component_class.silence_redefinition_of_method(method_name)
|
75
67
|
# rubocop:disable Style/EvalWithLocation
|
76
68
|
component_class.class_eval <<-RUBY, template[:path], 0
|
77
69
|
def #{method_name}
|
@@ -80,35 +72,22 @@ module ViewComponent
|
|
80
72
|
RUBY
|
81
73
|
# rubocop:enable Style/EvalWithLocation
|
82
74
|
end
|
75
|
+
end
|
83
76
|
|
84
|
-
|
85
|
-
|
86
|
-
component_class.build_i18n_backend
|
87
|
-
component_class._after_compile
|
77
|
+
define_render_template_for
|
88
78
|
|
89
|
-
|
90
|
-
end
|
91
|
-
end
|
79
|
+
component_class.build_i18n_backend
|
92
80
|
|
93
|
-
|
94
|
-
if development?
|
95
|
-
__vc_compiler_lock.synchronize(&block)
|
96
|
-
else
|
97
|
-
block.call
|
98
|
-
end
|
81
|
+
CompileCache.register(component_class)
|
99
82
|
end
|
100
83
|
|
101
84
|
private
|
102
85
|
|
103
|
-
attr_reader :component_class
|
86
|
+
attr_reader :component_class, :redefinition_lock
|
104
87
|
|
105
88
|
def define_render_template_for
|
106
|
-
if component_class.instance_methods.include?(:render_template_for)
|
107
|
-
component_class.send(:undef_method, :render_template_for)
|
108
|
-
end
|
109
|
-
|
110
89
|
variant_elsifs = variants.compact.uniq.map do |variant|
|
111
|
-
"elsif variant.to_sym ==
|
90
|
+
"elsif variant.to_sym == :'#{variant}'\n #{call_method_name(variant)}"
|
112
91
|
end.join("\n")
|
113
92
|
|
114
93
|
body = <<-RUBY
|
@@ -120,15 +99,8 @@ module ViewComponent
|
|
120
99
|
end
|
121
100
|
RUBY
|
122
101
|
|
123
|
-
|
124
|
-
component_class.
|
125
|
-
def render_template_for(variant = nil)
|
126
|
-
self.class.compiler.with_lock do
|
127
|
-
#{body}
|
128
|
-
end
|
129
|
-
end
|
130
|
-
RUBY
|
131
|
-
else
|
102
|
+
redefinition_lock.synchronize do
|
103
|
+
component_class.silence_redefinition_of_method(:render_template_for)
|
132
104
|
component_class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
133
105
|
def render_template_for(variant = nil)
|
134
106
|
#{body}
|
@@ -186,6 +158,19 @@ module ViewComponent
|
|
186
158
|
"There can only be a template file or inline render method per variant."
|
187
159
|
end
|
188
160
|
|
161
|
+
uniq_variants = variants.compact.uniq
|
162
|
+
normalized_variants = uniq_variants.map { |variant| normalized_variant_name(variant) }
|
163
|
+
|
164
|
+
colliding_variants = uniq_variants.select do |variant|
|
165
|
+
normalized_variants.count(normalized_variant_name(variant)) > 1
|
166
|
+
end
|
167
|
+
|
168
|
+
unless colliding_variants.empty?
|
169
|
+
errors <<
|
170
|
+
"Colliding templates #{colliding_variants.sort.map { |v| "'#{v}'" }.to_sentence} " \
|
171
|
+
"found in #{component_class}."
|
172
|
+
end
|
173
|
+
|
189
174
|
errors
|
190
175
|
end
|
191
176
|
end
|
@@ -195,11 +180,11 @@ module ViewComponent
|
|
195
180
|
begin
|
196
181
|
extensions = ActionView::Template.template_handler_extensions
|
197
182
|
|
198
|
-
component_class.
|
183
|
+
component_class.sidecar_files(extensions).each_with_object([]) do |path, memo|
|
199
184
|
pieces = File.basename(path).split(".")
|
200
185
|
memo << {
|
201
186
|
path: path,
|
202
|
-
variant: pieces.
|
187
|
+
variant: pieces[1..-2].join(".").split("+").second&.to_sym,
|
203
188
|
handler: pieces.last
|
204
189
|
}
|
205
190
|
end
|
@@ -257,12 +242,16 @@ module ViewComponent
|
|
257
242
|
|
258
243
|
def call_method_name(variant)
|
259
244
|
if variant.present? && variants.include?(variant)
|
260
|
-
"call_#{variant}"
|
245
|
+
"call_#{normalized_variant_name(variant)}"
|
261
246
|
else
|
262
247
|
"call"
|
263
248
|
end
|
264
249
|
end
|
265
250
|
|
251
|
+
def normalized_variant_name(variant)
|
252
|
+
variant.to_s.gsub("-", "__").gsub(".", "___")
|
253
|
+
end
|
254
|
+
|
266
255
|
def should_compile_superclass?
|
267
256
|
development? &&
|
268
257
|
templates.empty? &&
|
@@ -0,0 +1,176 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "view_component/deprecation"
|
4
|
+
|
5
|
+
module ViewComponent
|
6
|
+
class Config
|
7
|
+
class << self
|
8
|
+
# `new` without any arguments initializes the default configuration, but
|
9
|
+
# it's important to differentiate in case that's no longer the case in
|
10
|
+
# future.
|
11
|
+
alias_method :default, :new
|
12
|
+
|
13
|
+
def defaults
|
14
|
+
ActiveSupport::OrderedOptions.new.merge!({
|
15
|
+
generate: default_generate_options,
|
16
|
+
preview_controller: "ViewComponentsController",
|
17
|
+
preview_route: "/rails/view_components",
|
18
|
+
show_previews_source: false,
|
19
|
+
instrumentation_enabled: false,
|
20
|
+
render_monkey_patch_enabled: true,
|
21
|
+
view_component_path: "app/components",
|
22
|
+
component_parent_class: nil,
|
23
|
+
show_previews: Rails.env.development? || Rails.env.test?,
|
24
|
+
preview_paths: default_preview_paths,
|
25
|
+
test_controller: "ApplicationController",
|
26
|
+
default_preview_layout: nil
|
27
|
+
})
|
28
|
+
end
|
29
|
+
|
30
|
+
# @!attribute generate
|
31
|
+
# @return [ActiveSupport::OrderedOptions]
|
32
|
+
# The subset of configuration options relating to generators.
|
33
|
+
#
|
34
|
+
# All options under this namespace default to `false` unless otherwise
|
35
|
+
# stated.
|
36
|
+
#
|
37
|
+
# #### `#sidecar`
|
38
|
+
#
|
39
|
+
# Always generate a component with a sidecar directory:
|
40
|
+
#
|
41
|
+
# config.view_component.generate.sidecar = true
|
42
|
+
#
|
43
|
+
# #### `#stimulus_controller`
|
44
|
+
#
|
45
|
+
# Always generate a Stimulus controller alongside the component:
|
46
|
+
#
|
47
|
+
# config.view_component.generate.stimulus_controller = true
|
48
|
+
#
|
49
|
+
# #### `#locale`
|
50
|
+
#
|
51
|
+
# Always generate translations file alongside the component:
|
52
|
+
#
|
53
|
+
# config.view_component.generate.locale = true
|
54
|
+
#
|
55
|
+
# #### `#distinct_locale_files`
|
56
|
+
#
|
57
|
+
# Always generate as many translations files as available locales:
|
58
|
+
#
|
59
|
+
# config.view_component.generate.distinct_locale_files = true
|
60
|
+
#
|
61
|
+
# One file will be generated for each configured `I18n.available_locales`,
|
62
|
+
# falling back to `[:en]` when no `available_locales` is defined.
|
63
|
+
#
|
64
|
+
# #### `#preview`
|
65
|
+
#
|
66
|
+
# Always generate a preview alongside the component:
|
67
|
+
#
|
68
|
+
# config.view_component.generate.preview = true
|
69
|
+
#
|
70
|
+
# #### #preview_path
|
71
|
+
#
|
72
|
+
# Path to generate preview:
|
73
|
+
#
|
74
|
+
# config.view_component.generate.preview_path = "test/components/previews"
|
75
|
+
#
|
76
|
+
# Required when there is more than one path defined in preview_paths.
|
77
|
+
# Defaults to `""`. If this is blank, the generator will use
|
78
|
+
# `ViewComponent.config.preview_paths` if defined,
|
79
|
+
# `"test/components/previews"` otherwise
|
80
|
+
|
81
|
+
# @!attribute preview_controller
|
82
|
+
# @return [String]
|
83
|
+
# The controller used for previewing components.
|
84
|
+
# Defaults to `ViewComponentsController`.
|
85
|
+
|
86
|
+
# @!attribute preview_route
|
87
|
+
# @return [String]
|
88
|
+
# The entry route for component previews.
|
89
|
+
# Defaults to `"/rails/view_components"`.
|
90
|
+
|
91
|
+
# @!attribute show_previews_source
|
92
|
+
# @return [Boolean]
|
93
|
+
# Whether to display source code previews in component previews.
|
94
|
+
# Defaults to `false`.
|
95
|
+
|
96
|
+
# @!attribute instrumentation_enabled
|
97
|
+
# @return [Boolean]
|
98
|
+
# Whether ActiveSupport notifications are enabled.
|
99
|
+
# Defaults to `false`.
|
100
|
+
|
101
|
+
# @!attribute render_monkey_patch_enabled
|
102
|
+
# @return [Boolean] Whether the #render method should be monkey patched.
|
103
|
+
# If this is disabled, use `#render_component` or
|
104
|
+
# `#render_component_to_string` instead.
|
105
|
+
# Defaults to `true`.
|
106
|
+
|
107
|
+
# @!attribute view_component_path
|
108
|
+
# @return [String]
|
109
|
+
# The path in which components, their templates, and their sidecars should
|
110
|
+
# be stored.
|
111
|
+
# Defaults to `"app/components"`.
|
112
|
+
|
113
|
+
# @!attribute component_parent_class
|
114
|
+
# @return [String]
|
115
|
+
# The parent class from which generated components will inherit.
|
116
|
+
# Defaults to `nil`. If this is falsy, generators will use
|
117
|
+
# `"ApplicationComponent"` if defined, `"ViewComponent::Base"` otherwise.
|
118
|
+
|
119
|
+
# @!attribute show_previews
|
120
|
+
# @return [Boolean]
|
121
|
+
# Whether component previews are enabled.
|
122
|
+
# Defaults to `true` in development and test environments.
|
123
|
+
|
124
|
+
# @!attribute preview_paths
|
125
|
+
# @return [Array<String>]
|
126
|
+
# The locations in which component previews will be looked up.
|
127
|
+
# Defaults to `['test/component/previews']` relative to your Rails root.
|
128
|
+
|
129
|
+
# @!attribute preview_path
|
130
|
+
# @deprecated Use #preview_paths instead. Will be removed in v3.0.0.
|
131
|
+
|
132
|
+
# @!attribute test_controller
|
133
|
+
# @return [String]
|
134
|
+
# The controller used for testing components.
|
135
|
+
# Can also be configured on a per-test basis using `#with_controller_class`.
|
136
|
+
# Defaults to `ApplicationController`.
|
137
|
+
|
138
|
+
# @!attribute default_preview_layout
|
139
|
+
# @return [String]
|
140
|
+
# A custom default layout used for the previews index page and individual
|
141
|
+
# previews.
|
142
|
+
# Defaults to `nil`. If this is falsy, `"component_preview"` is used.
|
143
|
+
|
144
|
+
def default_preview_paths
|
145
|
+
return [] unless defined?(Rails.root) && Dir.exist?("#{Rails.root}/test/components/previews")
|
146
|
+
|
147
|
+
["#{Rails.root}/test/components/previews"]
|
148
|
+
end
|
149
|
+
|
150
|
+
def default_generate_options
|
151
|
+
options = ActiveSupport::OrderedOptions.new(false)
|
152
|
+
options.preview_path = ""
|
153
|
+
options
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def initialize
|
158
|
+
@config = self.class.defaults
|
159
|
+
end
|
160
|
+
|
161
|
+
def preview_path
|
162
|
+
preview_paths
|
163
|
+
end
|
164
|
+
|
165
|
+
def preview_path=(new_value)
|
166
|
+
ViewComponent::Deprecation.deprecation_warning("`preview_path`", :"`preview_paths`")
|
167
|
+
self.preview_paths = Array.wrap(new_value)
|
168
|
+
end
|
169
|
+
|
170
|
+
delegate_missing_to :config
|
171
|
+
|
172
|
+
private
|
173
|
+
|
174
|
+
attr_reader :config
|
175
|
+
end
|
176
|
+
end
|
@@ -31,9 +31,8 @@ module ViewComponent
|
|
31
31
|
|
32
32
|
class_methods do
|
33
33
|
def with_content_areas(*areas)
|
34
|
-
ViewComponent::Deprecation.
|
35
|
-
"`with_content_areas`
|
36
|
-
"Use slots (https://viewcomponent.org/guide/slots.html) instead."
|
34
|
+
ViewComponent::Deprecation.deprecation_warning(
|
35
|
+
"`with_content_areas`", "use slots (https://viewcomponent.org/guide/slots.html) instead"
|
37
36
|
)
|
38
37
|
|
39
38
|
if areas.include?(:content)
|
@@ -3,6 +3,6 @@
|
|
3
3
|
require "active_support/deprecation"
|
4
4
|
|
5
5
|
module ViewComponent
|
6
|
-
DEPRECATION_HORIZON = 3
|
7
|
-
Deprecation = ActiveSupport::Deprecation.new(DEPRECATION_HORIZON
|
6
|
+
DEPRECATION_HORIZON = "3.0.0"
|
7
|
+
Deprecation = ActiveSupport::Deprecation.new(DEPRECATION_HORIZON, "ViewComponent")
|
8
8
|
end
|