view_component 2.62.0 → 2.82.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 +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
|